From c4b1b1937e6175d5c27fca41ca0ce9417935ad96 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 15 Apr 2018 11:17:57 -0500 Subject: [PATCH 01/20] Remove support for all other platforms other than macOS --- BasiliskII/src/AmigaOS/BasiliskII.info | Bin 1519 -> 0 bytes BasiliskII/src/AmigaOS/Makefile | 64 - BasiliskII/src/AmigaOS/asm_support.asm | 1393 ---- BasiliskII/src/AmigaOS/audio_amiga.cpp | 515 -- BasiliskII/src/AmigaOS/clip_amiga.cpp | 166 - BasiliskII/src/AmigaOS/ether_amiga.cpp | 705 -- BasiliskII/src/AmigaOS/extfs_amiga.cpp | 387 - BasiliskII/src/AmigaOS/main_amiga.cpp | 743 -- BasiliskII/src/AmigaOS/prefs_amiga.cpp | 89 - BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp | 1735 ---- BasiliskII/src/AmigaOS/scsi_amiga.cpp | 289 - BasiliskII/src/AmigaOS/serial_amiga.cpp | 861 -- BasiliskII/src/AmigaOS/sys_amiga.cpp | 1122 --- BasiliskII/src/AmigaOS/sysdeps.h | 76 - BasiliskII/src/AmigaOS/timer_amiga.cpp | 157 - BasiliskII/src/AmigaOS/user_strings_amiga.cpp | 85 - BasiliskII/src/AmigaOS/user_strings_amiga.h | 51 - BasiliskII/src/AmigaOS/video_amiga.cpp | 1165 --- BasiliskII/src/AmigaOS/xpram_amiga.cpp | 80 - BasiliskII/src/BeOS/Makefile | 151 - BasiliskII/src/BeOS/SheepDriver/Makefile | 117 - .../src/BeOS/SheepDriver/sheep_driver.c | 476 -- .../src/BeOS/SheepDriver/sheep_driver.h | 33 - BasiliskII/src/BeOS/SheepNet/Makefile | 115 - BasiliskII/src/BeOS/SheepNet/sheep_net.cpp | 294 - BasiliskII/src/BeOS/SheepNet/sheep_net.h | 65 - BasiliskII/src/BeOS/about_window.cpp | 59 - BasiliskII/src/BeOS/about_window.h | 27 - BasiliskII/src/BeOS/audio_beos.cpp | 342 - BasiliskII/src/BeOS/clip_beos.cpp | 128 - BasiliskII/src/BeOS/ether_beos.cpp | 532 -- BasiliskII/src/BeOS/extfs_beos.cpp | 489 -- BasiliskII/src/BeOS/main_beos.cpp | 826 -- BasiliskII/src/BeOS/prefs_beos.cpp | 106 - BasiliskII/src/BeOS/prefs_editor_beos.cpp | 1022 --- BasiliskII/src/BeOS/scsi_beos.cpp | 237 - BasiliskII/src/BeOS/serial_beos.cpp | 873 -- BasiliskII/src/BeOS/sys_beos.cpp | 841 -- BasiliskII/src/BeOS/sysdeps.h | 144 - BasiliskII/src/BeOS/timer_beos.cpp | 166 - BasiliskII/src/BeOS/user_strings_beos.cpp | 69 - BasiliskII/src/BeOS/user_strings_beos.h | 35 - BasiliskII/src/BeOS/video_beos.cpp | 1086 --- BasiliskII/src/BeOS/xpram_beos.cpp | 84 - BasiliskII/src/CrossPlatform/sigsegv.cpp | 2053 +---- BasiliskII/src/CrossPlatform/video_blit.cpp | 2 +- BasiliskII/src/CrossPlatform/video_vosf.h | 11 +- BasiliskII/src/CrossPlatform/vm_alloc.cpp | 134 +- BasiliskII/src/MacOSX/AudioBackEnd.cpp | 307 - BasiliskII/src/MacOSX/AudioBackEnd.h | 86 - BasiliskII/src/MacOSX/AudioDevice.cpp | 97 - BasiliskII/src/MacOSX/AudioDevice.h | 72 - BasiliskII/src/MacOSX/BasiliskII.icns | Bin 44909 -> 0 bytes BasiliskII/src/MacOSX/Controller.h | 59 - BasiliskII/src/MacOSX/Controller.mm | 410 - BasiliskII/src/MacOSX/Credits.html | 11 - BasiliskII/src/MacOSX/Emulator.h | 82 - BasiliskII/src/MacOSX/Emulator.mm | 473 -- BasiliskII/src/MacOSX/EmulatorView.h | 108 - BasiliskII/src/MacOSX/EmulatorView.mm | 550 -- .../MacOSX/English.lproj/InfoPlist.strings | 3 - .../English.lproj/MainMenu.nib/Collapsed.tiff | Bin 870 -> 0 bytes .../English.lproj/MainMenu.nib/Expanded.tiff | Bin 870 -> 0 bytes .../English.lproj/MainMenu.nib/classes.nib | 131 - .../English.lproj/MainMenu.nib/info.nib | 36 - .../English.lproj/MainMenu.nib/objects.nib | Bin 29653 -> 0 bytes .../English.lproj/MainMenu.nib/resetH.tiff | Bin 9798 -> 0 bytes .../English.lproj/MainMenu.nib/resetN.tiff | Bin 9798 -> 0 bytes .../English.lproj/MainMenu.nib/shutdownH.tiff | Bin 9798 -> 0 bytes .../English.lproj/MainMenu.nib/shutdownN.tiff | Bin 9798 -> 0 bytes BasiliskII/src/MacOSX/HowTo.html | 226 - BasiliskII/src/MacOSX/Info.plist | 32 - BasiliskII/src/MacOSX/MacOSX_sound_if.cpp | 86 - BasiliskII/src/MacOSX/MacOSX_sound_if.h | 41 - .../English.lproj/InfoPlist.strings | 4 - .../English.lproj/MainMenu.nib/classes.nib | 118 - .../English.lproj/MainMenu.nib/info.nib | 20 - .../English.lproj/MainMenu.nib/objects.nib | Bin 19336 -> 0 bytes .../Win512x342.nib/Collapsed.tiff | Bin 870 -> 0 bytes .../Win512x342.nib/Expanded.tiff | Bin 870 -> 0 bytes .../English.lproj/Win512x342.nib/classes.nib | 32 - .../English.lproj/Win512x342.nib/info.nib | 20 - .../English.lproj/Win512x342.nib/objects.nib | Bin 3069 -> 0 bytes .../English.lproj/Win512x342.nib/resetH.tiff | Bin 9798 -> 0 bytes .../English.lproj/Win512x342.nib/resetN.tiff | Bin 9798 -> 0 bytes .../Win512x342.nib/shutdownH.tiff | Bin 9798 -> 0 bytes .../Win512x342.nib/shutdownN.tiff | Bin 9798 -> 0 bytes BasiliskII/src/MacOSX/Multiple-Windows/README | 5 - BasiliskII/src/MacOSX/NNThread.h | 91 - BasiliskII/src/MacOSX/NNThread.m | 257 - BasiliskII/src/MacOSX/PrefsEditor.h | 145 - BasiliskII/src/MacOSX/PrefsEditor.mm | 844 -- BasiliskII/src/MacOSX/ToDo.html | 61 - BasiliskII/src/MacOSX/Versions.html | 120 - BasiliskII/src/MacOSX/audio_defs_macosx.h | 80 - BasiliskII/src/MacOSX/audio_macosx.cpp | 271 - BasiliskII/src/MacOSX/autorelease.h | 46 - BasiliskII/src/MacOSX/clip_macosx.cpp | 211 - BasiliskII/src/MacOSX/clip_macosx64.mm | 1286 --- BasiliskII/src/MacOSX/extfs_macosx.cpp | 634 -- BasiliskII/src/MacOSX/macos_util_macosx.h | 178 - BasiliskII/src/MacOSX/main_macosx.h | 29 - BasiliskII/src/MacOSX/main_macosx.mm | 744 -- BasiliskII/src/MacOSX/misc_macosx.h | 38 - BasiliskII/src/MacOSX/misc_macosx.mm | 112 - BasiliskII/src/MacOSX/prefs_macosx.cpp | 150 - BasiliskII/src/MacOSX/utils_macosx.h | 27 - BasiliskII/src/MacOSX/utils_macosx.mm | 30 - BasiliskII/src/MacOSX/video_macosx.h | 75 - BasiliskII/src/MacOSX/video_macosx.mm | 1123 --- BasiliskII/src/SDL/SDLMain.h | 16 - BasiliskII/src/SDL/SDLMain.m | 381 - BasiliskII/src/SDL/audio_sdl.cpp | 13 +- BasiliskII/src/SDL/video_sdl.cpp | 85 +- .../{MacOSX => Unix/Darwin}/sys_darwin.cpp | 0 BasiliskII/src/Unix/FreeBSD/scsi_freebsd.cpp | 743 -- BasiliskII/src/Unix/FreeBSD/scsidump.cpp | 478 -- BasiliskII/src/Unix/Irix/README.networking | 110 - BasiliskII/src/Unix/Irix/audio_irix.cpp | 680 -- BasiliskII/src/Unix/Irix/unaligned.c | 44 - BasiliskII/src/Unix/Linux/NetDriver/Makefile | 53 - BasiliskII/src/Unix/Linux/NetDriver/config.h | 1 - .../src/Unix/Linux/NetDriver/sheep_net.c | 770 -- BasiliskII/src/Unix/Linux/scsi_linux.cpp | 271 - BasiliskII/src/Unix/Makefile.in | 150 +- BasiliskII/src/Unix/Solaris/audio_solaris.cpp | 320 - BasiliskII/src/Unix/Solaris/which_sparc | 121 - BasiliskII/src/Unix/asm_support.s | 180 - BasiliskII/src/Unix/audio_oss_esd.cpp | 558 -- BasiliskII/src/Unix/bincue_unix.cpp | 834 -- BasiliskII/src/Unix/bincue_unix.h | 43 - BasiliskII/src/Unix/clip_unix.cpp | 691 -- BasiliskII/src/Unix/configure.ac | 984 +-- BasiliskII/src/Unix/disk_sparsebundle.cpp | 315 - BasiliskII/src/Unix/disk_unix.h | 3 - BasiliskII/src/Unix/ether_unix.cpp | 1051 --- BasiliskII/src/Unix/ldscripts/freebsd-i386.ld | 175 - BasiliskII/src/Unix/ldscripts/linux-i386.ld | 137 - BasiliskII/src/Unix/ldscripts/linux-ppc.ld | 219 - BasiliskII/src/Unix/ldscripts/linux-x86_64.ld | 171 - BasiliskII/src/Unix/main_unix.cpp | 692 +- BasiliskII/src/Unix/prefs_editor_gtk.cpp | 1828 ----- BasiliskII/src/Unix/prefs_unix.cpp | 13 - BasiliskII/src/Unix/rpc_unix.cpp | 5 - BasiliskII/src/Unix/serial_unix.cpp | 833 -- BasiliskII/src/Unix/sshpty.c | 478 -- BasiliskII/src/Unix/sshpty.h | 26 - BasiliskII/src/Unix/strlcpy.c | 75 - BasiliskII/src/Unix/strlcpy.h | 12 - BasiliskII/src/Unix/sys_unix.cpp | 681 +- BasiliskII/src/Unix/sysdeps.h | 161 +- BasiliskII/src/Unix/timer_unix.cpp | 43 +- BasiliskII/src/Unix/tinyxml2.cpp | 2095 ----- BasiliskII/src/Unix/tinyxml2.h | 1968 ----- BasiliskII/src/Unix/user_strings_unix.cpp | 8 - BasiliskII/src/Unix/user_strings_unix.h | 8 - BasiliskII/src/Unix/vhd_unix.cpp | 160 - BasiliskII/src/Unix/video_x.cpp | 2686 ------- .../src/Windows/BasiliskII.DebugJIT.props | 14 - .../src/Windows/BasiliskII.ReleaseJIT.props | 14 - BasiliskII/src/Windows/BasiliskII.ico | Bin 2998 -> 0 bytes BasiliskII/src/Windows/BasiliskII.props | 14 - BasiliskII/src/Windows/BasiliskII.rc | 2 - BasiliskII/src/Windows/BasiliskII.sln | 140 - BasiliskII/src/Windows/BasiliskII.vcxproj | 685 -- .../src/Windows/BasiliskII.vcxproj.filters | 589 -- BasiliskII/src/Windows/BasiliskIIGUI.ico | Bin 1078 -> 0 bytes BasiliskII/src/Windows/BasiliskIIGUI.rc | 2 - BasiliskII/src/Windows/Makefile.in | 236 - BasiliskII/src/Windows/b2ether/driver/DEBUG.H | 43 - .../src/Windows/b2ether/driver/MAKEFILE | 7 - .../src/Windows/b2ether/driver/OEMSETUP.INF | 430 - BasiliskII/src/Windows/b2ether/driver/SOURCES | 15 - .../src/Windows/b2ether/driver/b2ether.c | 556 -- .../src/Windows/b2ether/driver/b2ether.h | 195 - .../b2ether/driver/b2ether_openclose.c | 303 - .../src/Windows/b2ether/driver/b2ether_read.c | 238 - .../Windows/b2ether/driver/b2ether_write.c | 103 - .../src/Windows/b2ether/inc/b2ether_hl.h | 115 - BasiliskII/src/Windows/b2ether/inc/ntddpack.h | 32 - BasiliskII/src/Windows/b2ether/multiopt.h | 27 - .../src/Windows/b2ether/nt5/B2Win2k.inf | 80 - .../Windows/b2ether/nt5/B2Win7Vista-x64.inf | 80 - BasiliskII/src/Windows/b2ether/nt5/MAKEFILE | 7 - BasiliskII/src/Windows/b2ether/nt5/NTDDPACK.H | 32 - BasiliskII/src/Windows/b2ether/nt5/SOURCES | 17 - BasiliskII/src/Windows/b2ether/nt5/b2ether.c | 755 -- BasiliskII/src/Windows/b2ether/nt5/b2ether.h | 276 - BasiliskII/src/Windows/b2ether/nt5/b2ether.rc | 10 - .../src/Windows/b2ether/nt5/b2ether64.sln | 26 - .../src/Windows/b2ether/nt5/b2ether64.vcxproj | 120 - .../Windows/b2ether/nt5/b2ether_openclose.c | 155 - .../src/Windows/b2ether/nt5/b2ether_read.c | 418 - .../src/Windows/b2ether/nt5/b2ether_write.c | 101 - BasiliskII/src/Windows/b2ether/packet32.cpp | 694 -- BasiliskII/src/Windows/build68k.vcxproj | 156 - .../src/Windows/build68k.vcxproj.filters | 22 - BasiliskII/src/Windows/cd_defs.h | 153 - BasiliskII/src/Windows/cdenable/cache.cpp | 181 - BasiliskII/src/Windows/cdenable/cache.h | 50 - BasiliskII/src/Windows/cdenable/cdenable.h | 60 - BasiliskII/src/Windows/cdenable/eject_nt.cpp | 189 - BasiliskII/src/Windows/cdenable/eject_nt.h | 44 - BasiliskII/src/Windows/cdenable/ntcd.cpp | 344 - BasiliskII/src/Windows/cdenable/ntcd.h | 99 - BasiliskII/src/Windows/clip_windows.cpp | 281 - BasiliskII/src/Windows/config.h | 260 - BasiliskII/src/Windows/configure.ac | 569 -- BasiliskII/src/Windows/ether_windows.cpp | 1609 ---- BasiliskII/src/Windows/ether_windows.h | 10 - BasiliskII/src/Windows/extfs_windows.cpp | 405 - BasiliskII/src/Windows/gencomp.vcxproj | 182 - .../src/Windows/gencomp.vcxproj.filters | 36 - BasiliskII/src/Windows/gencpu.vcxproj | 182 - BasiliskII/src/Windows/gencpu.vcxproj.filters | 36 - BasiliskII/src/Windows/main_windows.cpp | 703 -- BasiliskII/src/Windows/posix_emu.cpp | 1125 --- BasiliskII/src/Windows/posix_emu.h | 122 - BasiliskII/src/Windows/prefs_editor_gtk.cpp | 1769 ---- BasiliskII/src/Windows/prefs_windows.cpp | 137 - BasiliskII/src/Windows/router/arp.cpp | 96 - BasiliskII/src/Windows/router/arp.h | 28 - BasiliskII/src/Windows/router/dump.cpp | 50 - BasiliskII/src/Windows/router/dump.h | 30 - BasiliskII/src/Windows/router/dynsockets.cpp | 185 - BasiliskII/src/Windows/router/dynsockets.h | 59 - BasiliskII/src/Windows/router/ftp.cpp | 193 - BasiliskII/src/Windows/router/ftp.h | 50 - BasiliskII/src/Windows/router/icmp.cpp | 221 - BasiliskII/src/Windows/router/icmp.h | 38 - BasiliskII/src/Windows/router/iphelp.cpp | 236 - BasiliskII/src/Windows/router/iphelp.h | 36 - BasiliskII/src/Windows/router/ipsocket.cpp | 266 - BasiliskII/src/Windows/router/ipsocket.h | 66 - .../src/Windows/router/mib/interfaces.cpp | 69 - .../src/Windows/router/mib/interfaces.h | 35 - .../src/Windows/router/mib/mibaccess.cpp | 308 - BasiliskII/src/Windows/router/mib/mibaccess.h | 83 - BasiliskII/src/Windows/router/router.cpp | 201 - BasiliskII/src/Windows/router/router.h | 54 - BasiliskII/src/Windows/router/router_types.h | 187 - BasiliskII/src/Windows/router/tcp.cpp | 1605 ---- BasiliskII/src/Windows/router/tcp.h | 31 - BasiliskII/src/Windows/router/udp.cpp | 206 - BasiliskII/src/Windows/router/udp.h | 38 - BasiliskII/src/Windows/serial_windows.cpp | 1198 --- BasiliskII/src/Windows/sys_windows.cpp | 994 --- BasiliskII/src/Windows/sysdeps.h | 336 - BasiliskII/src/Windows/timer_windows.cpp | 268 - .../src/Windows/user_strings_windows.cpp | 179 - BasiliskII/src/Windows/user_strings_windows.h | 75 - BasiliskII/src/Windows/util_windows.cpp | 510 -- BasiliskII/src/Windows/util_windows.h | 125 - BasiliskII/src/Windows/xpram_windows.cpp | 99 - BasiliskII/src/emul_op.cpp | 13 +- BasiliskII/src/ether.cpp | 11 +- BasiliskII/src/extfs.cpp | 22 +- BasiliskII/src/include/debug.h | 82 - BasiliskII/src/include/ether.h | 8 +- BasiliskII/src/main.cpp | 25 - BasiliskII/src/native_cpu/cpu_emulation.h | 67 - BasiliskII/src/pict.c | 267 - BasiliskII/src/powerrom_cpu/cpu_emulation.h | 66 - BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp | 1367 ---- BasiliskII/src/prefs_items.cpp | 10 - BasiliskII/src/rom_patches.cpp | 25 +- BasiliskII/src/rsrc_patches.cpp | 3 - BasiliskII/src/slirp/COPYRIGHT | 61 - BasiliskII/src/slirp/VERSION | 1 - BasiliskII/src/slirp/bootp.c | 242 - BasiliskII/src/slirp/bootp.h | 121 - BasiliskII/src/slirp/cksum.c | 137 - BasiliskII/src/slirp/ctl.h | 7 - BasiliskII/src/slirp/debug.c | 379 - BasiliskII/src/slirp/debug.h | 50 - BasiliskII/src/slirp/icmp_var.h | 65 - BasiliskII/src/slirp/if.c | 323 - BasiliskII/src/slirp/if.h | 50 - BasiliskII/src/slirp/ip.h | 333 - BasiliskII/src/slirp/ip_icmp.c | 371 - BasiliskII/src/slirp/ip_icmp.h | 168 - BasiliskII/src/slirp/ip_input.c | 693 -- BasiliskII/src/slirp/ip_output.c | 202 - BasiliskII/src/slirp/libslirp.h | 41 - BasiliskII/src/slirp/main.h | 54 - BasiliskII/src/slirp/mbuf.c | 230 - BasiliskII/src/slirp/mbuf.h | 143 - BasiliskII/src/slirp/misc.c | 863 -- BasiliskII/src/slirp/misc.h | 87 - BasiliskII/src/slirp/sbuf.c | 183 - BasiliskII/src/slirp/sbuf.h | 33 - BasiliskII/src/slirp/slirp.c | 676 -- BasiliskII/src/slirp/slirp.h | 358 - BasiliskII/src/slirp/slirp_config.h | 127 - BasiliskII/src/slirp/socket.c | 733 -- BasiliskII/src/slirp/socket.h | 104 - BasiliskII/src/slirp/tcp.h | 181 - BasiliskII/src/slirp/tcp_input.c | 1724 ---- BasiliskII/src/slirp/tcp_output.c | 597 -- BasiliskII/src/slirp/tcp_subr.c | 1296 --- BasiliskII/src/slirp/tcp_timer.c | 322 - BasiliskII/src/slirp/tcp_timer.h | 138 - BasiliskII/src/slirp/tcp_var.h | 248 - BasiliskII/src/slirp/tcpip.h | 70 - BasiliskII/src/slirp/tftp.c | 334 - BasiliskII/src/slirp/tftp.h | 40 - BasiliskII/src/slirp/udp.c | 672 -- BasiliskII/src/slirp/udp.h | 114 - BasiliskII/src/sony.cpp | 4 - BasiliskII/src/uae_cpu/basilisk_glue.cpp | 53 +- BasiliskII/src/uae_cpu/build68k.c | 8 - .../src/uae_cpu/compiler/codegen_x86.cpp | 4758 ----------- BasiliskII/src/uae_cpu/compiler/codegen_x86.h | 2565 ------ BasiliskII/src/uae_cpu/compiler/compemu.h | 609 -- .../src/uae_cpu/compiler/compemu_fpp.cpp | 1637 ---- .../src/uae_cpu/compiler/compemu_support.cpp | 7129 ----------------- BasiliskII/src/uae_cpu/compiler/flags_x86.h | 47 - BasiliskII/src/uae_cpu/compiler/gencomp.c | 3072 ------- .../src/uae_cpu/compiler/test_codegen_x86.cpp | 2254 ------ BasiliskII/src/uae_cpu/cpu_emulation.h | 15 - BasiliskII/src/uae_cpu/fpu/flags.h | 6 - BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp | 2152 ----- BasiliskII/src/uae_cpu/fpu/fpu_ieee.h | 149 - BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp | 6126 -------------- BasiliskII/src/uae_cpu/fpu/fpu_x86.h | 361 - BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h | 72 - BasiliskII/src/uae_cpu/fpu/mathlib.h | 6 - BasiliskII/src/uae_cpu/gencpu.c | 20 +- BasiliskII/src/uae_cpu/memory.cpp | 585 -- BasiliskII/src/uae_cpu/memory.h | 133 +- BasiliskII/src/uae_cpu/newcpu.cpp | 61 +- BasiliskII/src/uae_cpu/newcpu.h | 18 +- BasiliskII/src/uae_cpu/spcflags.h | 8 +- BasiliskII/src/user_strings.cpp | 4 - 334 files changed, 198 insertions(+), 120731 deletions(-) delete mode 100644 BasiliskII/src/AmigaOS/BasiliskII.info delete mode 100644 BasiliskII/src/AmigaOS/Makefile delete mode 100644 BasiliskII/src/AmigaOS/asm_support.asm delete mode 100644 BasiliskII/src/AmigaOS/audio_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/clip_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/ether_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/extfs_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/main_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/prefs_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/scsi_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/serial_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/sys_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/sysdeps.h delete mode 100644 BasiliskII/src/AmigaOS/timer_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/user_strings_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/user_strings_amiga.h delete mode 100644 BasiliskII/src/AmigaOS/video_amiga.cpp delete mode 100644 BasiliskII/src/AmigaOS/xpram_amiga.cpp delete mode 100644 BasiliskII/src/BeOS/Makefile delete mode 100644 BasiliskII/src/BeOS/SheepDriver/Makefile delete mode 100644 BasiliskII/src/BeOS/SheepDriver/sheep_driver.c delete mode 100644 BasiliskII/src/BeOS/SheepDriver/sheep_driver.h delete mode 100644 BasiliskII/src/BeOS/SheepNet/Makefile delete mode 100644 BasiliskII/src/BeOS/SheepNet/sheep_net.cpp delete mode 100644 BasiliskII/src/BeOS/SheepNet/sheep_net.h delete mode 100644 BasiliskII/src/BeOS/about_window.cpp delete mode 100644 BasiliskII/src/BeOS/about_window.h delete mode 100644 BasiliskII/src/BeOS/audio_beos.cpp delete mode 100644 BasiliskII/src/BeOS/clip_beos.cpp delete mode 100644 BasiliskII/src/BeOS/ether_beos.cpp delete mode 100644 BasiliskII/src/BeOS/extfs_beos.cpp delete mode 100644 BasiliskII/src/BeOS/main_beos.cpp delete mode 100644 BasiliskII/src/BeOS/prefs_beos.cpp delete mode 100644 BasiliskII/src/BeOS/prefs_editor_beos.cpp delete mode 100644 BasiliskII/src/BeOS/scsi_beos.cpp delete mode 100644 BasiliskII/src/BeOS/serial_beos.cpp delete mode 100644 BasiliskII/src/BeOS/sys_beos.cpp delete mode 100644 BasiliskII/src/BeOS/sysdeps.h delete mode 100644 BasiliskII/src/BeOS/timer_beos.cpp delete mode 100644 BasiliskII/src/BeOS/user_strings_beos.cpp delete mode 100644 BasiliskII/src/BeOS/user_strings_beos.h delete mode 100644 BasiliskII/src/BeOS/video_beos.cpp delete mode 100644 BasiliskII/src/BeOS/xpram_beos.cpp delete mode 100644 BasiliskII/src/MacOSX/AudioBackEnd.cpp delete mode 100644 BasiliskII/src/MacOSX/AudioBackEnd.h delete mode 100644 BasiliskII/src/MacOSX/AudioDevice.cpp delete mode 100644 BasiliskII/src/MacOSX/AudioDevice.h delete mode 100644 BasiliskII/src/MacOSX/BasiliskII.icns delete mode 100644 BasiliskII/src/MacOSX/Controller.h delete mode 100644 BasiliskII/src/MacOSX/Controller.mm delete mode 100644 BasiliskII/src/MacOSX/Credits.html delete mode 100644 BasiliskII/src/MacOSX/Emulator.h delete mode 100644 BasiliskII/src/MacOSX/Emulator.mm delete mode 100644 BasiliskII/src/MacOSX/EmulatorView.h delete mode 100644 BasiliskII/src/MacOSX/EmulatorView.mm delete mode 100755 BasiliskII/src/MacOSX/English.lproj/InfoPlist.strings delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/Collapsed.tiff delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/Expanded.tiff delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/classes.nib delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/info.nib delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/objects.nib delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/resetH.tiff delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/resetN.tiff delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/shutdownH.tiff delete mode 100644 BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/shutdownN.tiff delete mode 100644 BasiliskII/src/MacOSX/HowTo.html delete mode 100644 BasiliskII/src/MacOSX/Info.plist delete mode 100644 BasiliskII/src/MacOSX/MacOSX_sound_if.cpp delete mode 100644 BasiliskII/src/MacOSX/MacOSX_sound_if.h delete mode 100755 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/InfoPlist.strings delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/classes.nib delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/info.nib delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/objects.nib delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/Collapsed.tiff delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/Expanded.tiff delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/classes.nib delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/info.nib delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/objects.nib delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/resetH.tiff delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/resetN.tiff delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/shutdownH.tiff delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/shutdownN.tiff delete mode 100644 BasiliskII/src/MacOSX/Multiple-Windows/README delete mode 100644 BasiliskII/src/MacOSX/NNThread.h delete mode 100644 BasiliskII/src/MacOSX/NNThread.m delete mode 100644 BasiliskII/src/MacOSX/PrefsEditor.h delete mode 100644 BasiliskII/src/MacOSX/PrefsEditor.mm delete mode 100644 BasiliskII/src/MacOSX/ToDo.html delete mode 100644 BasiliskII/src/MacOSX/Versions.html delete mode 100644 BasiliskII/src/MacOSX/audio_defs_macosx.h delete mode 100644 BasiliskII/src/MacOSX/audio_macosx.cpp delete mode 100644 BasiliskII/src/MacOSX/autorelease.h delete mode 100644 BasiliskII/src/MacOSX/clip_macosx.cpp delete mode 100644 BasiliskII/src/MacOSX/clip_macosx64.mm delete mode 100644 BasiliskII/src/MacOSX/extfs_macosx.cpp delete mode 100644 BasiliskII/src/MacOSX/macos_util_macosx.h delete mode 100644 BasiliskII/src/MacOSX/main_macosx.h delete mode 100644 BasiliskII/src/MacOSX/main_macosx.mm delete mode 100644 BasiliskII/src/MacOSX/misc_macosx.h delete mode 100644 BasiliskII/src/MacOSX/misc_macosx.mm delete mode 100644 BasiliskII/src/MacOSX/prefs_macosx.cpp delete mode 100644 BasiliskII/src/MacOSX/utils_macosx.h delete mode 100644 BasiliskII/src/MacOSX/utils_macosx.mm delete mode 100644 BasiliskII/src/MacOSX/video_macosx.h delete mode 100644 BasiliskII/src/MacOSX/video_macosx.mm delete mode 100644 BasiliskII/src/SDL/SDLMain.h delete mode 100644 BasiliskII/src/SDL/SDLMain.m rename BasiliskII/src/{MacOSX => Unix/Darwin}/sys_darwin.cpp (100%) delete mode 100644 BasiliskII/src/Unix/FreeBSD/scsi_freebsd.cpp delete mode 100644 BasiliskII/src/Unix/FreeBSD/scsidump.cpp delete mode 100644 BasiliskII/src/Unix/Irix/README.networking delete mode 100644 BasiliskII/src/Unix/Irix/audio_irix.cpp delete mode 100644 BasiliskII/src/Unix/Irix/unaligned.c delete mode 100644 BasiliskII/src/Unix/Linux/NetDriver/Makefile delete mode 120000 BasiliskII/src/Unix/Linux/NetDriver/config.h delete mode 100644 BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c delete mode 100644 BasiliskII/src/Unix/Linux/scsi_linux.cpp delete mode 100644 BasiliskII/src/Unix/Solaris/audio_solaris.cpp delete mode 100755 BasiliskII/src/Unix/Solaris/which_sparc delete mode 100644 BasiliskII/src/Unix/asm_support.s delete mode 100644 BasiliskII/src/Unix/audio_oss_esd.cpp delete mode 100644 BasiliskII/src/Unix/bincue_unix.cpp delete mode 100644 BasiliskII/src/Unix/bincue_unix.h delete mode 100644 BasiliskII/src/Unix/clip_unix.cpp delete mode 100644 BasiliskII/src/Unix/disk_sparsebundle.cpp delete mode 100644 BasiliskII/src/Unix/ether_unix.cpp delete mode 100644 BasiliskII/src/Unix/ldscripts/freebsd-i386.ld delete mode 100644 BasiliskII/src/Unix/ldscripts/linux-i386.ld delete mode 100644 BasiliskII/src/Unix/ldscripts/linux-ppc.ld delete mode 100644 BasiliskII/src/Unix/ldscripts/linux-x86_64.ld delete mode 100644 BasiliskII/src/Unix/prefs_editor_gtk.cpp delete mode 100644 BasiliskII/src/Unix/serial_unix.cpp delete mode 100644 BasiliskII/src/Unix/sshpty.c delete mode 100644 BasiliskII/src/Unix/sshpty.h delete mode 100644 BasiliskII/src/Unix/strlcpy.c delete mode 100644 BasiliskII/src/Unix/strlcpy.h delete mode 100755 BasiliskII/src/Unix/tinyxml2.cpp delete mode 100755 BasiliskII/src/Unix/tinyxml2.h delete mode 100644 BasiliskII/src/Unix/vhd_unix.cpp delete mode 100644 BasiliskII/src/Unix/video_x.cpp delete mode 100644 BasiliskII/src/Windows/BasiliskII.DebugJIT.props delete mode 100644 BasiliskII/src/Windows/BasiliskII.ReleaseJIT.props delete mode 100755 BasiliskII/src/Windows/BasiliskII.ico delete mode 100644 BasiliskII/src/Windows/BasiliskII.props delete mode 100644 BasiliskII/src/Windows/BasiliskII.rc delete mode 100644 BasiliskII/src/Windows/BasiliskII.sln delete mode 100644 BasiliskII/src/Windows/BasiliskII.vcxproj delete mode 100644 BasiliskII/src/Windows/BasiliskII.vcxproj.filters delete mode 100755 BasiliskII/src/Windows/BasiliskIIGUI.ico delete mode 100644 BasiliskII/src/Windows/BasiliskIIGUI.rc delete mode 100755 BasiliskII/src/Windows/Makefile.in delete mode 100755 BasiliskII/src/Windows/b2ether/driver/DEBUG.H delete mode 100755 BasiliskII/src/Windows/b2ether/driver/MAKEFILE delete mode 100755 BasiliskII/src/Windows/b2ether/driver/OEMSETUP.INF delete mode 100755 BasiliskII/src/Windows/b2ether/driver/SOURCES delete mode 100755 BasiliskII/src/Windows/b2ether/driver/b2ether.c delete mode 100755 BasiliskII/src/Windows/b2ether/driver/b2ether.h delete mode 100755 BasiliskII/src/Windows/b2ether/driver/b2ether_openclose.c delete mode 100755 BasiliskII/src/Windows/b2ether/driver/b2ether_read.c delete mode 100755 BasiliskII/src/Windows/b2ether/driver/b2ether_write.c delete mode 100755 BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h delete mode 100755 BasiliskII/src/Windows/b2ether/inc/ntddpack.h delete mode 100755 BasiliskII/src/Windows/b2ether/multiopt.h delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/B2Win2k.inf delete mode 100755 BasiliskII/src/Windows/b2ether/nt5/B2Win7Vista-x64.inf delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/MAKEFILE delete mode 100755 BasiliskII/src/Windows/b2ether/nt5/NTDDPACK.H delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/SOURCES delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/b2ether.c delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/b2ether.h delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/b2ether.rc delete mode 100755 BasiliskII/src/Windows/b2ether/nt5/b2ether64.sln delete mode 100755 BasiliskII/src/Windows/b2ether/nt5/b2ether64.vcxproj delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/b2ether_openclose.c delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/b2ether_read.c delete mode 100644 BasiliskII/src/Windows/b2ether/nt5/b2ether_write.c delete mode 100755 BasiliskII/src/Windows/b2ether/packet32.cpp delete mode 100644 BasiliskII/src/Windows/build68k.vcxproj delete mode 100644 BasiliskII/src/Windows/build68k.vcxproj.filters delete mode 100755 BasiliskII/src/Windows/cd_defs.h delete mode 100755 BasiliskII/src/Windows/cdenable/cache.cpp delete mode 100755 BasiliskII/src/Windows/cdenable/cache.h delete mode 100755 BasiliskII/src/Windows/cdenable/cdenable.h delete mode 100755 BasiliskII/src/Windows/cdenable/eject_nt.cpp delete mode 100755 BasiliskII/src/Windows/cdenable/eject_nt.h delete mode 100755 BasiliskII/src/Windows/cdenable/ntcd.cpp delete mode 100755 BasiliskII/src/Windows/cdenable/ntcd.h delete mode 100755 BasiliskII/src/Windows/clip_windows.cpp delete mode 100644 BasiliskII/src/Windows/config.h delete mode 100755 BasiliskII/src/Windows/configure.ac delete mode 100755 BasiliskII/src/Windows/ether_windows.cpp delete mode 100755 BasiliskII/src/Windows/ether_windows.h delete mode 100755 BasiliskII/src/Windows/extfs_windows.cpp delete mode 100644 BasiliskII/src/Windows/gencomp.vcxproj delete mode 100644 BasiliskII/src/Windows/gencomp.vcxproj.filters delete mode 100644 BasiliskII/src/Windows/gencpu.vcxproj delete mode 100644 BasiliskII/src/Windows/gencpu.vcxproj.filters delete mode 100755 BasiliskII/src/Windows/main_windows.cpp delete mode 100755 BasiliskII/src/Windows/posix_emu.cpp delete mode 100755 BasiliskII/src/Windows/posix_emu.h delete mode 100644 BasiliskII/src/Windows/prefs_editor_gtk.cpp delete mode 100755 BasiliskII/src/Windows/prefs_windows.cpp delete mode 100755 BasiliskII/src/Windows/router/arp.cpp delete mode 100755 BasiliskII/src/Windows/router/arp.h delete mode 100755 BasiliskII/src/Windows/router/dump.cpp delete mode 100755 BasiliskII/src/Windows/router/dump.h delete mode 100755 BasiliskII/src/Windows/router/dynsockets.cpp delete mode 100755 BasiliskII/src/Windows/router/dynsockets.h delete mode 100755 BasiliskII/src/Windows/router/ftp.cpp delete mode 100755 BasiliskII/src/Windows/router/ftp.h delete mode 100755 BasiliskII/src/Windows/router/icmp.cpp delete mode 100755 BasiliskII/src/Windows/router/icmp.h delete mode 100755 BasiliskII/src/Windows/router/iphelp.cpp delete mode 100755 BasiliskII/src/Windows/router/iphelp.h delete mode 100755 BasiliskII/src/Windows/router/ipsocket.cpp delete mode 100755 BasiliskII/src/Windows/router/ipsocket.h delete mode 100755 BasiliskII/src/Windows/router/mib/interfaces.cpp delete mode 100755 BasiliskII/src/Windows/router/mib/interfaces.h delete mode 100755 BasiliskII/src/Windows/router/mib/mibaccess.cpp delete mode 100755 BasiliskII/src/Windows/router/mib/mibaccess.h delete mode 100755 BasiliskII/src/Windows/router/router.cpp delete mode 100755 BasiliskII/src/Windows/router/router.h delete mode 100755 BasiliskII/src/Windows/router/router_types.h delete mode 100755 BasiliskII/src/Windows/router/tcp.cpp delete mode 100755 BasiliskII/src/Windows/router/tcp.h delete mode 100755 BasiliskII/src/Windows/router/udp.cpp delete mode 100755 BasiliskII/src/Windows/router/udp.h delete mode 100755 BasiliskII/src/Windows/serial_windows.cpp delete mode 100755 BasiliskII/src/Windows/sys_windows.cpp delete mode 100755 BasiliskII/src/Windows/sysdeps.h delete mode 100755 BasiliskII/src/Windows/timer_windows.cpp delete mode 100755 BasiliskII/src/Windows/user_strings_windows.cpp delete mode 100755 BasiliskII/src/Windows/user_strings_windows.h delete mode 100755 BasiliskII/src/Windows/util_windows.cpp delete mode 100755 BasiliskII/src/Windows/util_windows.h delete mode 100755 BasiliskII/src/Windows/xpram_windows.cpp delete mode 100644 BasiliskII/src/native_cpu/cpu_emulation.h delete mode 100644 BasiliskII/src/pict.c delete mode 100644 BasiliskII/src/powerrom_cpu/cpu_emulation.h delete mode 100644 BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp delete mode 100644 BasiliskII/src/slirp/COPYRIGHT delete mode 100644 BasiliskII/src/slirp/VERSION delete mode 100644 BasiliskII/src/slirp/bootp.c delete mode 100644 BasiliskII/src/slirp/bootp.h delete mode 100644 BasiliskII/src/slirp/cksum.c delete mode 100644 BasiliskII/src/slirp/ctl.h delete mode 100644 BasiliskII/src/slirp/debug.c delete mode 100644 BasiliskII/src/slirp/debug.h delete mode 100644 BasiliskII/src/slirp/icmp_var.h delete mode 100644 BasiliskII/src/slirp/if.c delete mode 100644 BasiliskII/src/slirp/if.h delete mode 100644 BasiliskII/src/slirp/ip.h delete mode 100644 BasiliskII/src/slirp/ip_icmp.c delete mode 100644 BasiliskII/src/slirp/ip_icmp.h delete mode 100644 BasiliskII/src/slirp/ip_input.c delete mode 100644 BasiliskII/src/slirp/ip_output.c delete mode 100644 BasiliskII/src/slirp/libslirp.h delete mode 100644 BasiliskII/src/slirp/main.h delete mode 100644 BasiliskII/src/slirp/mbuf.c delete mode 100644 BasiliskII/src/slirp/mbuf.h delete mode 100644 BasiliskII/src/slirp/misc.c delete mode 100644 BasiliskII/src/slirp/misc.h delete mode 100644 BasiliskII/src/slirp/sbuf.c delete mode 100644 BasiliskII/src/slirp/sbuf.h delete mode 100644 BasiliskII/src/slirp/slirp.c delete mode 100644 BasiliskII/src/slirp/slirp.h delete mode 100644 BasiliskII/src/slirp/slirp_config.h delete mode 100644 BasiliskII/src/slirp/socket.c delete mode 100644 BasiliskII/src/slirp/socket.h delete mode 100644 BasiliskII/src/slirp/tcp.h delete mode 100644 BasiliskII/src/slirp/tcp_input.c delete mode 100644 BasiliskII/src/slirp/tcp_output.c delete mode 100644 BasiliskII/src/slirp/tcp_subr.c delete mode 100644 BasiliskII/src/slirp/tcp_timer.c delete mode 100644 BasiliskII/src/slirp/tcp_timer.h delete mode 100644 BasiliskII/src/slirp/tcp_var.h delete mode 100644 BasiliskII/src/slirp/tcpip.h delete mode 100644 BasiliskII/src/slirp/tftp.c delete mode 100644 BasiliskII/src/slirp/tftp.h delete mode 100644 BasiliskII/src/slirp/udp.c delete mode 100644 BasiliskII/src/slirp/udp.h delete mode 100644 BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp delete mode 100644 BasiliskII/src/uae_cpu/compiler/codegen_x86.h delete mode 100644 BasiliskII/src/uae_cpu/compiler/compemu.h delete mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp delete mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_support.cpp delete mode 100644 BasiliskII/src/uae_cpu/compiler/flags_x86.h delete mode 100644 BasiliskII/src/uae_cpu/compiler/gencomp.c delete mode 100644 BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_ieee.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_x86.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h delete mode 100644 BasiliskII/src/uae_cpu/memory.cpp diff --git a/BasiliskII/src/AmigaOS/BasiliskII.info b/BasiliskII/src/AmigaOS/BasiliskII.info deleted file mode 100644 index b590d7da63a3715fbbdad593d3b0af11ed0a8366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1519 zcmeH_zfQw25XL{}kKCa`WB@Xe873CGwhKZ631z?&1APQWwtDLm@DT76jIhHV39)xU zVyJrDogFoFLZV|nDf#)kJI9xkKXzdty1^|*I6#gR#-6;sXms;s(##e|u*K<{=bSui z`LG;e9|I)C9j#Ny;(FMn^-y0u2aW@)aie}l-$FyQ5~dV9bD`e3T9^Pkkw(b>lL)!H zOgTlVEbpgEJNHUyMe0OD%t*9^f=_yPqPojE`pI61M@}MvT;kWig9(_VbOmslN~ZyASz=ySkK5WItaO2t)t? diff --git a/BasiliskII/src/AmigaOS/Makefile b/BasiliskII/src/AmigaOS/Makefile deleted file mode 100644 index 2ccaeec0..00000000 --- a/BasiliskII/src/AmigaOS/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# AmigaOS makefile for Basilisk II (GeekGadgets tool chain) - -## System specific configuration -CC = gcc -CXX = c++ -CXXFLAGS = -g -O1 -noixemul -m68020 -msmall-code -Wno-multichar -CPPFLAGS = -I../include -I../native_cpu -I. -DEFS = -LDFLAGS = -noixemul -LIBS = /gg/lib/libnix/swapstack.o -AS = PhxAss -ASFLAGS = OPT ! INCPATH GG:os-include FPU=1 - -## Files -SRCS = ../main.cpp main_amiga.cpp ../prefs.cpp ../prefs_items.cpp \ - prefs_amiga.cpp prefs_editor_amiga.cpp sys_amiga.cpp ../rom_patches.cpp \ - ../slot_rom.cpp ../rsrc_patches.cpp ../emul_op.cpp \ - ../macos_util.cpp ../xpram.cpp xpram_amiga.cpp ../timer.cpp \ - timer_amiga.cpp clip_amiga.cpp ../adb.cpp ../serial.cpp \ - serial_amiga.cpp ../ether.cpp ether_amiga.cpp ../sony.cpp ../disk.cpp \ - ../cdrom.cpp ../scsi.cpp scsi_amiga.cpp ../video.cpp video_amiga.cpp \ - ../audio.cpp audio_amiga.cpp ../extfs.cpp extfs_amiga.cpp \ - ../user_strings.cpp user_strings_amiga.cpp asm_support.asm -APP = BasiliskII - -## Rules -.PHONY: clean distclean -.SUFFIXES: -.SUFFIXES: .c .cpp .asm .o .h - -all: $(APP) - -OBJ_DIR = obj -$(OBJ_DIR):: - @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 - -define SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ - $(basename $(notdir $(file)))))) -endef -OBJS = $(SRCS_LIST_TO_OBJS) - -SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) -VPATH := -VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) - -$(APP): $(OBJ_DIR) $(OBJS) - $(CXX) -o $(APP) $(LDFLAGS) $(LIBS) $(OBJS) - -clean: - rm -f $(APP) $(OBJ_DIR)/* *~ *.bak obj.0000.* - -distclean: clean - rm -rf $(OBJ_DIR) - -$(OBJ_DIR)/%.o : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.asm - $(AS) $(ASFLAGS) $< TO $(OBJ_DIR)/$*.obj - hunk2aout $(OBJ_DIR)/$*.obj >/dev/null - mv obj.0000.* $@ - -#------------------------------------------------------------------------- -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/BasiliskII/src/AmigaOS/asm_support.asm b/BasiliskII/src/AmigaOS/asm_support.asm deleted file mode 100644 index d2a81b07..00000000 --- a/BasiliskII/src/AmigaOS/asm_support.asm +++ /dev/null @@ -1,1393 +0,0 @@ -* -* asm_support.asm - AmigaOS utility functions in assembly language -* -* Basilisk II (C) 1997-2001 Christian Bauer -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* - -DEBUG_DETAIL SET 1 - - INCLUDE "exec/types.i" - INCLUDE "exec/macros.i" - INCLUDE "exec/memory.i" - INCLUDE "exec/tasks.i" - INCLUDE "dos/dos.i" - INCLUDE "devices/timer.i" - -; INCLUDE "asmsupp.i" - - XDEF _AtomicAnd - XDEF _AtomicOr - XDEF _MoveVBR - XDEF _DisableSuperBypass - XDEF _Execute68k - XDEF _Execute68kTrap - XDEF _TrapHandlerAsm - XDEF _ExceptionHandlerAsm - XDEF _AsmTriggerNMI - - XREF _OldTrapHandler - XREF _OldExceptionHandler - XREF _IllInstrHandler - XREF _PrivViolHandler - XREF _EmulatedSR - XREF _IRQSigMask - XREF _InterruptFlags - XREF _MainTask - XREF _SysBase - XREF _quit_emulator - -INFO_LEVEL equ 0 - - SECTION text,CODE - - MACHINE 68020 - - IFGE INFO_LEVEL -subSysName: dc.b '+',0 - ENDIF - -* -* Atomic bit operations (don't trust the compiler) -* - -_AtomicAnd move.l 4(sp),a0 - move.l 8(sp),d0 - and.l d0,(a0) - rts - -_AtomicOr move.l 4(sp),a0 - move.l 8(sp),d0 - or.l d0,(a0) - rts - -* -* Move VBR away from 0 if neccessary -* - -_MoveVBR movem.l d0-d1/a0-a1/a5-a6,-(sp) - move.l _SysBase,a6 - - lea getvbr,a5 ;VBR at 0? - JSRLIB Supervisor - tst.l d0 - bne.s 1$ - - move.l #$400,d0 ;Yes, allocate memory for new table - move.l #MEMF_PUBLIC,d1 - JSRLIB AllocMem - tst.l d0 - beq.s 1$ - - JSRLIB Disable - - move.l d0,a5 ;Copy old table - move.l d0,a1 - sub.l a0,a0 - move.l #$400,d0 - JSRLIB CopyMem - JSRLIB CacheClearU - - move.l a5,d0 ;Set VBR - lea setvbr,a5 - JSRLIB Supervisor - - JSRLIB Enable - -1$ movem.l (sp)+,d0-d1/a0-a1/a5-a6 - rts - -getvbr movec vbr,d0 - rte - -setvbr movec d0,vbr - rte - -* -* Disable 68060 Super Bypass mode -* - -_DisableSuperBypass - movem.l d0-d1/a0-a1/a5-a6,-(sp) - move.l _SysBase,a6 - - lea dissb,a5 - JSRLIB Supervisor - - movem.l (sp)+,d0-d1/a0-a1/a5-a6 - rts - - MACHINE 68060 - -dissb movec pcr,d0 - bset #5,d0 - movec d0,pcr - rte - - MACHINE 68020 - -* -* Execute 68k subroutine (must be ended with rts) -* r->a[7] and r->sr are unused! -* - -; void Execute68k(uint32 addr, M68kRegisters *r); -_Execute68k - move.l 4(sp),d0 ;Get arguments - move.l 8(sp),a0 - - movem.l d2-d7/a2-a6,-(sp) ;Save registers - - move.l a0,-(sp) ;Push pointer to M68kRegisters on stack - pea 1$ ;Push return address on stack - move.l d0,-(sp) ;Push pointer to 68k routine on stack - movem.l (a0),d0-d7/a0-a6 ;Load registers from M68kRegisters - - rts ;Jump into 68k routine - -1$ move.l a6,-(sp) ;Save a6 - move.l 4(sp),a6 ;Get pointer to M68kRegisters - movem.l d0-d7/a0-a5,(a6) ;Save d0-d7/a0-a5 to M68kRegisters - move.l (sp)+,56(a6) ;Save a6 to M68kRegisters - addq.l #4,sp ;Remove pointer from stack - - movem.l (sp)+,d2-d7/a2-a6 ;Restore registers - rts - -* -* Execute MacOS 68k trap -* r->a[7] and r->sr are unused! -* - -; void Execute68kTrap(uint16 trap, M68kRegisters *r); -_Execute68kTrap - move.l 4(sp),d0 ;Get arguments - move.l 8(sp),a0 - - movem.l d2-d7/a2-a6,-(sp) ;Save registers - - move.l a0,-(sp) ;Push pointer to M68kRegisters on stack - move.w d0,-(sp) ;Push trap word on stack - subq.l #8,sp ;Create fake A-Line exception frame - movem.l (a0),d0-d7/a0-a6 ;Load registers from M68kRegisters - - move.l a2,-(sp) ;Save a2 and d2 - move.l d2,-(sp) - lea 1$,a2 ;a2 points to return address - move.w 16(sp),d2 ;Load trap word into d2 - - jmp ([$28.w],10) ;Jump into MacOS A-Line handler - -1$ move.l a6,-(sp) ;Save a6 - move.l 6(sp),a6 ;Get pointer to M68kRegisters - movem.l d0-d7/a0-a5,(a6) ;Save d0-d7/a0-a5 to M68kRegisters - move.l (sp)+,56(a6) ;Save a6 to M68kRegisters - addq.l #6,sp ;Remove pointer and trap word from stack - - movem.l (sp)+,d2-d7/a2-a6 ;Restore registers - rts - -* -* Exception handler of main task (for interrupts) -* - -_ExceptionHandlerAsm - move.l d0,-(sp) ;Save d0 - - and.l #SIGBREAKF_CTRL_C,d0 ;CTRL-C? - bne.s 2$ - - move.w _EmulatedSR,d0 ;Interrupts enabled in emulated SR? - and.w #$0700,d0 - bne 1$ - move.w #$0064,-(sp) ;Yes, fake interrupt stack frame - pea 1$ - move.w _EmulatedSR,d0 - move.w d0,-(sp) - or.w #$2100,d0 ;Set interrupt level in SR, enter (virtual) supervisor mode - move.w d0,_EmulatedSR - move.l $64.w,-(sp) ;Jump to MacOS interrupt handler - rts - -1$ move.l (sp)+,d0 ;Restore d0 - rts - -2$ JSRLIB Forbid ;Waiting for Dos signal? - sub.l a1,a1 - JSRLIB FindTask - move.l d0,a0 - move.l TC_SIGWAIT(a0),d0 - move.l TC_SIGRECVD(a0),d1 - JSRLIB Permit - btst #SIGB_DOS,d0 - beq 3$ - btst #SIGB_DOS,d1 - bne 4$ - -3$ lea TC_SIZE(a0),a0 ;No, remove pending Dos packets - JSRLIB GetMsg - - move.w _EmulatedSR,d0 - or.w #$0700,d0 ;Disable all interrupts - move.w d0,_EmulatedSR - moveq #0,d0 ;Disable all exception signals - moveq #-1,d1 - JSRLIB SetExcept - jsr _quit_emulator ;CTRL-C, quit emulator -4$ move.l (sp)+,d0 - rts - -* -* Trap handler of main task -* - -_TrapHandlerAsm: - IFEQ INFO_LEVEL-1002 - move.w ([6,a0]),-(sp) - move.w #0,-(sp) - move.l (4+6,a0),-(sp) - PUTMSG 0,'%s/TrapHandlerAsm: addr=%08lx opcode=%04lx' - lea (2*4,sp),sp - ENDC - - cmp.l #4,(sp) ;Illegal instruction? - beq.s doillinstr - cmp.l #10,(sp) ;A-Line exception? - beq.s doaline - cmp.l #8,(sp) ;Privilege violation? - beq.s doprivviol - - cmp.l #9,(sp) ;Trace? - beq dotrace - cmp.l #3,(sp) ;Illegal Address? - beq.s doilladdr - cmp.l #11,(sp) ;F-Line exception - beq.s dofline - - cmp.l #32,(sp) - blt 1$ - cmp.l #47,(sp) - ble doTrapXX ; Vector 32-47 : TRAP #0 - 15 Instruction Vectors - -1$: - cmp.l #48,(sp) - blt 2$ - cmp.l #55,(sp) - ble doTrapFPU -2$: - IFEQ INFO_LEVEL-1009 - PUTMSG 0,'%s/TrapHandlerAsm: stack=%08lx %08lx %08lx %08lx' - ENDC - - move.l _OldTrapHandler,-(sp) ;No, jump to old trap handler - rts - -* -* TRAP #0 - 15 Instruction Vectors -* - -doTrapXX: - IFEQ INFO_LEVEL-1009 - PUTMSG 0,'%s/doTrapXX: stack=%08lx %08lx %08lx %08lx' - ENDC - - movem.l a0/d0,-(sp) ;Save a0,d0 - move.l (2*4,sp),d0 ;vector number 32-47 - - move.l usp,a0 ;Get user stack pointer - move.l (4*4,sp),-(a0) ;Copy 4-word stack frame to user stack - move.l (3*4,sp),-(a0) - move.l a0,usp ;Update USP - or.w #$2000,(a0) ;set Supervisor bit in SR - - lsl.l #2,d0 ;convert vector number to vector offset - move.l d0,a0 - move.l (a0),d0 ;get mac trap vector - - move.l usp,a0 ;Get user stack pointer - move.l d0,-(a0) ;store vector offset as return address - move.l a0,usp ;Update USP - - movem.l (sp)+,a0/d0 ;Restore a0,d0 - addq.l #4*2,sp ;Remove exception frame from supervisor stack - - andi #$d8ff,sr ;Switch to user mode, enable interrupts - rts - - -* -* FPU Exception Instruction Vectors -* - -doTrapFPU: - move.l d0,(sp) - fmove.l fpcr,d0 - and.w #$00ff,d0 ;disable FPU exceptions - fmove.l d0,fpcr - move.l (sp)+,d0 ;Restore d0 - rte - - -* -* trace Vector -* - -dotrace - IFEQ INFO_LEVEL-1009 - PUTMSG 0,'%s/dotrace: stack=%08lx %08lx %08lx %08lx' - ENDC - - move.l a0,(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - - IFEQ INFO_LEVEL-1009 - move.l (12,a0),-(sp) - move.l (8,a0),-(sp) - move.l (4,a0),-(sp) - move.l (0,a0),-(sp) - move.l a0,-(sp) - move.l a7,-(sp) - PUTMSG 0,'%s/dotrace: sp=%08lx usp=%08lx (%08lx %08lx %08lx %08lx)' - lea (6*4,sp),sp - ENDC - - move.l 3*4(sp),-(a0) ;Copy 6-word stack frame to user stack - move.l 2*4(sp),-(a0) - move.l 1*4(sp),-(a0) - move.l a0,usp ;Update USP - or.w #$2000,(a0) ;set Supervisor bit in SR - move.l (sp)+,a0 ;Restore a0 - - lea 6*2(sp),sp ;Remove exception frame from supervisor stack - andi #$18ff,sr ;Switch to user mode, enable interrupts, disable trace - - move.l $24.w,-(sp) ;Jump to MacOS exception handler - rts - - -* -* A-Line handler: call MacOS A-Line handler -* - -doaline move.l a0,(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.l 8(sp),-(a0) ;Copy stack frame to user stack - move.l 4(sp),-(a0) - move.l a0,usp ;Update USP - - or.w #$2000,(a0) ;set Supervisor bit in SR - move.l (sp)+,a0 ;Restore a0 - - addq.l #8,sp ;Remove exception frame from supervisor stack - andi #$d8ff,sr ;Switch to user mode, enable interrupts - -; and.w #$f8ff,_EmulatedSR ;enable interrupts in EmulatedSR - - move.l $28.w,-(sp) ;Jump to MacOS exception handler - rts - -* -* F-Line handler: call F-Line exception handler -* - -dofline move.l a0,(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.l 8(sp),-(a0) ;Copy stack frame to user stack - move.l 4(sp),-(a0) - move.l a0,usp ;Update USP - or.w #$2000,(a0) ;set Supervisor bit in SR - move.l (sp)+,a0 ;Restore a0 - - addq.l #8,sp ;Remove exception frame from supervisor stack - andi #$d8ff,sr ;Switch to user mode, enable interrupts - - and.w #$f8ff,_EmulatedSR ;enable interrupts in EmulatedSR - - move.l $2c.w,-(sp) ;Jump to MacOS exception handler - rts - -* -* Illegal address handler -* - -doilladdr: - IFEQ INFO_LEVEL-1009 - PUTMSG 0,'%s/doilladdr: stack=%08lx %08lx %08lx %08lx' - ENDC - - move.l a0,(sp) ;Save a0 - - move.l usp,a0 ;Get user stack pointer - move.l 3*4(sp),-(a0) ;Copy 6-word stack frame to user stack - move.l 2*4(sp),-(a0) - move.l 1*4(sp),-(a0) - move.l a0,usp ;Update USP - or.w #$2000,(a0) ;set Supervisor bit in SR - move.l (sp)+,a0 ;Restore a0 - - lea 6*2(sp),sp ;Remove exception frame from supervisor stack - andi #$d8ff,sr ;Switch to user mode, enable interrupts - - move.l $0c.w,-(sp) ;Jump to MacOS exception handler - rts - - -* -* Illegal instruction handler: call IllInstrHandler() (which calls EmulOp()) -* to execute extended opcodes (see emul_op.h) -* - -doillinstr movem.l a0/d0,-(sp) - move.w ([6+2*4,sp]),d0 - and.w #$ff00,d0 - cmp.w #$7100,d0 - - IFEQ INFO_LEVEL-1009 - move.l d0,-(sp) - PUTMSG 0,'%s/doillinst: d0=%08lx stack=%08lx %08lx %08lx %08lx' - lea (1*4,sp),sp - ENDC - movem.l (sp)+,a0/d0 - beq 1$ - - move.l a0,(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.l 8(sp),-(a0) ;Copy stack frame to user stack - move.l 4(sp),-(a0) - move.l a0,usp ;Update USP - or.w #$2000,(a0) ;set Supervisor bit in SR - move.l (sp)+,a0 ;Restore a0 - - add.w #3*4,sp ;Remove exception frame from supervisor stack - andi #$d8ff,sr ;Switch to user mode, enable interrupts - - move.l $10.w,-(sp) ;Jump to MacOS exception handler - rts - -1$: - move.l a6,(sp) ;Save a6 - move.l usp,a6 ;Get user stack pointer - - move.l a6,-10(a6) ;Push USP (a7) - move.l 6(sp),-(a6) ;Push PC - move.w 4(sp),-(a6) ;Push SR - subq.l #4,a6 ;Skip saved USP - move.l (sp),-(a6) ;Push old a6 - movem.l d0-d7/a0-a5,-(a6) ;Push remaining registers - move.l a6,usp ;Update USP - - add.w #12,sp ;Remove exception frame from supervisor stack - andi #$d8ff,sr ;Switch to user mode, enable interrupts - - move.l a6,-(sp) ;Jump to IllInstrHandler() in main.cpp - jsr _IllInstrHandler - addq.l #4,sp - - movem.l (sp)+,d0-d7/a0-a6 ;Restore registers - addq.l #4,sp ;Skip saved USP (!!) - rtr ;Return from exception - -* -* Privilege violation handler: MacOS runs in supervisor mode, -* so we have to emulate certain privileged instructions -* - -doprivviol move.l d0,(sp) ;Save d0 - move.w ([6,sp]),d0 ;Get instruction word - - IFEQ INFO_LEVEL-1001 - move.w ([6,a0]),-(sp) - move.w #0,-(sp) - PUTMSG 0,'%s/doprivviol: opcode=%04lx' - lea (1*4,sp),sp - ENDC - - cmp.w #$40e7,d0 ;move sr,-(sp)? - beq pushsr - cmp.w #$46df,d0 ;move (sp)+,sr? - beq popsr - - cmp.w #$007c,d0 ;ori #xxxx,sr? - beq orisr - cmp.w #$027c,d0 ;andi #xxxx,sr? - beq andisr - - cmp.w #$46fc,d0 ;move #xxxx,sr? - beq movetosrimm - - cmp.w #$46ef,d0 ;move (xxxx,sp),sr? - beq movetosrsprel - cmp.w #$46d8,d0 ;move (a0)+,sr? - beq movetosra0p - cmp.w #$46d9,d0 ;move (a1)+,sr? - beq movetosra1p - - cmp.w #$40f8,d0 ;move sr,xxxx.w? - beq movefromsrabs - cmp.w #$40d0,d0 ;move sr,(a0)? - beq movefromsra0 - cmp.w #$40d7,d0 ;move sr,(sp)? - beq movefromsrsp - - cmp.w #$f327,d0 ;fsave -(sp)? - beq fsavepush - cmp.w #$f35f,d0 ;frestore (sp)+? - beq frestorepop - cmp.w #$f32d,d0 ;fsave xxx(a5) ? - beq fsavea5 - cmp.w #$f36d,d0 ;frestore xxx(a5) ? - beq frestorea5 - - cmp.w #$4e73,d0 ;rte? - beq pvrte - - cmp.w #$40c0,d0 ;move sr,d0? - beq movefromsrd0 - cmp.w #$40c1,d0 ;move sr,d1? - beq movefromsrd1 - cmp.w #$40c2,d0 ;move sr,d2? - beq movefromsrd2 - cmp.w #$40c3,d0 ;move sr,d3? - beq movefromsrd3 - cmp.w #$40c4,d0 ;move sr,d4? - beq movefromsrd4 - cmp.w #$40c5,d0 ;move sr,d5? - beq movefromsrd5 - cmp.w #$40c6,d0 ;move sr,d6? - beq movefromsrd6 - cmp.w #$40c7,d0 ;move sr,d7? - beq movefromsrd7 - - cmp.w #$46c0,d0 ;move d0,sr? - beq movetosrd0 - cmp.w #$46c1,d0 ;move d1,sr? - beq movetosrd1 - cmp.w #$46c2,d0 ;move d2,sr? - beq movetosrd2 - cmp.w #$46c3,d0 ;move d3,sr? - beq movetosrd3 - cmp.w #$46c4,d0 ;move d4,sr? - beq movetosrd4 - cmp.w #$46c5,d0 ;move d5,sr? - beq movetosrd5 - cmp.w #$46c6,d0 ;move d6,sr? - beq movetosrd6 - cmp.w #$46c7,d0 ;move d7,sr? - beq movetosrd7 - - cmp.w #$4e7a,d0 ;movec cr,x? - beq movecfromcr - cmp.w #$4e7b,d0 ;movec x,cr? - beq movectocr - - cmp.w #$f478,d0 ;cpusha dc? - beq cpushadc - cmp.w #$f4f8,d0 ;cpusha dc/ic? - beq cpushadcic - - cmp.w #$4e69,d0 ;move usp,a1 - beq moveuspa1 - cmp.w #$4e68,d0 ;move usp,a0 - beq moveuspa0 - - cmp.w #$4e61,d0 ;move a1,usp - beq moved1usp - -pv_unhandled move.l (sp),d0 ;Unhandled instruction, jump to handler in main.cpp - move.l a6,(sp) ;Save a6 - move.l usp,a6 ;Get user stack pointer - - move.l a6,-10(a6) ;Push USP (a7) - move.l 6(sp),-(a6) ;Push PC - move.w 4(sp),-(a6) ;Push SR - subq.l #4,a6 ;Skip saved USP - move.l (sp),-(a6) ;Push old a6 - movem.l d0-d7/a0-a5,-(a6) ;Push remaining registers - move.l a6,usp ;Update USP - - add.w #12,sp ;Remove exception frame from supervisor stack - andi #$d8ff,sr ;Switch to user mode, enable interrupts - - move.l a6,-(sp) ;Jump to PrivViolHandler() in main.cpp - jsr _PrivViolHandler - addq.l #4,sp - - movem.l (sp)+,d0-d7/a0-a6 ;Restore registers - addq.l #4,sp ;Skip saved USP - rtr ;Return from exception - -; move sr,-(sp) -pushsr move.l a0,-(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.w 8(sp),d0 ;Get CCR from exception stack frame - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - move.w d0,-(a0) ;Store SR on user stack - move.l a0,usp ;Update USP - move.l (sp)+,a0 ;Restore a0 - move.l (sp)+,d0 ;Restore d0 - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; move (sp)+,sr -popsr move.l a0,-(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.w (a0)+,d0 ;Get SR from user stack - move.w d0,8(sp) ;Store into CCR on exception stack frame - and.w #$00ff,8(sp) - and.w #$e700,d0 ;Extract supervisor bits - move.w d0,_EmulatedSR ;And save them - - and.w #$0700,d0 ;Rethrow exception if interrupts are pending and reenabled - bne 1$ - tst.l _InterruptFlags - beq 1$ - movem.l d0-d1/a0-a1/a6,-(sp) - move.l _SysBase,a6 - move.l _MainTask,a1 - move.l _IRQSigMask,d0 - JSRLIB Signal - movem.l (sp)+,d0-d1/a0-a1/a6 -1$ - move.l a0,usp ;Update USP - move.l (sp)+,a0 ;Restore a0 - move.l (sp)+,d0 ;Restore d0 - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; ori #xxxx,sr -orisr move.w 4(sp),d0 ;Get CCR from stack - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - or.w ([6,sp],2),d0 ;Or with immediate value - move.w d0,4(sp) ;Store into CCR on stack - and.w #$00ff,4(sp) - and.w #$e700,d0 ;Extract supervisor bits - move.w d0,_EmulatedSR ;And save them - move.l (sp)+,d0 ;Restore d0 - addq.l #4,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; andi #xxxx,sr -andisr move.w 4(sp),d0 ;Get CCR from stack - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - and.w ([6,sp],2),d0 ;And with immediate value -storesr4 move.w d0,4(sp) ;Store into CCR on stack - and.w #$00ff,4(sp) - and.w #$e700,d0 ;Extract supervisor bits - move.w d0,_EmulatedSR ;And save them - - and.w #$0700,d0 ;Rethrow exception if interrupts are pending and reenabled - bne.s 1$ - tst.l _InterruptFlags - beq.s 1$ - movem.l d0-d1/a0-a1/a6,-(sp) - move.l _SysBase,a6 - move.l _MainTask,a1 - move.l _IRQSigMask,d0 - JSRLIB Signal - movem.l (sp)+,d0-d1/a0-a1/a6 -1$ move.l (sp)+,d0 ;Restore d0 - addq.l #4,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; move #xxxx,sr -movetosrimm move.w ([6,sp],2),d0 ;Get immediate value - bra.s storesr4 - -; move (xxxx,sp),sr -movetosrsprel move.l a0,-(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.w ([10,sp],2),d0 ;Get offset - move.w (a0,d0.w),d0 ;Read word - move.l (sp)+,a0 ;Restore a0 - bra.s storesr4 - -; move (a0)+,sr -movetosra0p move.w (a0)+,d0 ;Read word - bra storesr2 - -; move (a1)+,sr -movetosra1p move.w (a1)+,d0 ;Read word - bra storesr2 - -; move sr,xxxx.w -movefromsrabs move.l a0,-(sp) ;Save a0 - move.w ([10,sp],2),a0 ;Get address - move.w 8(sp),d0 ;Get CCR - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - move.w d0,(a0) ;Store SR - move.l (sp)+,a0 ;Restore a0 - move.l (sp)+,d0 ;Restore d0 - addq.l #4,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; move sr,(a0) -movefromsra0 move.w 4(sp),d0 ;Get CCR - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - move.w d0,(a0) ;Store SR - move.l (sp)+,d0 ;Restore d0 - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; move sr,(sp) -movefromsrsp move.l a0,-(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.w 8(sp),d0 ;Get CCR - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - move.w d0,(a0) ;Store SR - move.l (sp)+,a0 ;Restore a0 - move.l (sp)+,d0 ;Restore d0 - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; fsave -(sp) -fsavepush move.l (sp),d0 ;Restore d0 - move.l a0,(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.l #$41000000,-(a0) ;Push idle frame - move.l a0,usp ;Update USP - move.l (sp)+,a0 ;Restore a0 - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; fsave xxx(a5) -fsavea5 move.l (sp),d0 ;Restore d0 - move.l a0,(sp) ;Save a0 - move.l a5,a0 ;Get base register - add.w ([6,sp],2),a0 ;Add offset to base register - move.l #$41000000,(a0) ;Push idle frame - move.l (sp)+,a0 ;Restore a0 - addq.l #4,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; frestore (sp)+ -frestorepop move.l (sp),d0 ;Restore d0 - move.l a0,(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - addq.l #4,a0 ;Nothing to do... - move.l a0,usp ;Update USP - move.l (sp)+,a0 ;Restore a0 - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; frestore xxx(a5) -frestorea5 move.l (sp),d0 ;Restore d0 - move.l a0,(sp) ;Save a0 - move.l (sp)+,a0 ;Restore a0 - addq.l #4,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; rte -pvrte movem.l a0/a1,-(sp) ;Save a0 and a1 - move.l usp,a0 ;Get user stack pointer - - move.w (a0)+,d0 ;Get SR from user stack - move.w d0,8+4(sp) ;Store into CCR on exception stack frame - and.w #$c0ff,8+4(sp) - and.w #$e700,d0 ;Extract supervisor bits - move.w d0,_EmulatedSR ;And save them - move.l (a0)+,10+4(sp) ;Store return address in exception stack frame - - move.w (a0)+,d0 ;get format word - lsr.w #7,d0 ;get stack frame Id - lsr.w #4,d0 - and.w #$001e,d0 - move.w (StackFormatTable,pc,d0.w),d0 ; get total stack frame length - subq.w #4,d0 ; count only extra words - lea 16+4(sp),a1 ; destination address (in supervisor stack) - bra 1$ - -2$ move.w (a0)+,(a1)+ ; copy additional stack words back to supervisor stack -1$ dbf d0,2$ - - move.l a0,usp ;Update USP - movem.l (sp)+,a0/a1 ;Restore a0 and a1 - move.l (sp)+,d0 ;Restore d0 - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; sizes of exceptions stack frames -StackFormatTable: - dc.w 4 ; Four-word stack frame, format $0 - dc.w 4 ; Throwaway four-word stack frame, format $1 - dc.w 6 ; Six-word stack frame, format $2 - dc.w 6 ; MC68040 floating-point post-instruction stack frame, format $3 - dc.w 8 ; MC68EC040 and MC68LC040 floating-point unimplemented stack frame, format $4 - dc.w 4 ; Format $5 - dc.w 4 ; Format $6 - dc.w 30 ; MC68040 access error stack frame, Format $7 - dc.w 29 ; MC68010 bus and address error stack frame, format $8 - dc.w 10 ; MC68020 and MC68030 coprocessor mid-instruction stack frame, format $9 - dc.w 16 ; MC68020 and MC68030 short bus cycle stack frame, format $a - dc.w 46 ; MC68020 and MC68030 long bus cycle stack frame, format $b - dc.w 12 ; CPU32 bus error for prefetches and operands stack frame, format $c - dc.w 4 ; Format $d - dc.w 4 ; Format $e - dc.w 4 ; Format $f - -; move sr,dx -movefromsrd0 addq.l #4,sp ;Skip saved d0 - moveq #0,d0 - move.w (sp),d0 ;Get CCR - or.w _EmulatedSR,d0 ;Add emulated supervisor bits - addq.l #2,2(sp) ;Skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd1 move.l (sp)+,d0 - moveq #0,d1 - move.w (sp),d1 - or.w _EmulatedSR,d1 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd2 move.l (sp)+,d0 - moveq #0,d2 - move.w (sp),d2 - or.w _EmulatedSR,d2 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd3 move.l (sp)+,d0 - moveq #0,d3 - move.w (sp),d3 - or.w _EmulatedSR,d3 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd4 move.l (sp)+,d0 - moveq #0,d4 - move.w (sp),d4 - or.w _EmulatedSR,d4 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd5 move.l (sp)+,d0 - moveq #0,d5 - move.w (sp),d5 - or.w _EmulatedSR,d5 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd6 move.l (sp)+,d0 - moveq #0,d6 - move.w (sp),d6 - or.w _EmulatedSR,d6 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movefromsrd7 move.l (sp)+,d0 - moveq #0,d7 - move.w (sp),d7 - or.w _EmulatedSR,d7 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; move dx,sr -movetosrd0 move.l (sp),d0 -storesr2 move.w d0,4(sp) - and.w #$00ff,4(sp) - and.w #$e700,d0 - move.w d0,_EmulatedSR - - and.w #$0700,d0 ;Rethrow exception if interrupts are pending and reenabled - bne.s 1$ - tst.l _InterruptFlags - beq.s 1$ - movem.l d0-d1/a0-a1/a6,-(sp) - move.l _SysBase,a6 - move.l _MainTask,a1 - move.l _IRQSigMask,d0 - JSRLIB Signal - movem.l (sp)+,d0-d1/a0-a1/a6 -1$ move.l (sp)+,d0 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movetosrd1 move.l d1,d0 - bra.s storesr2 - -movetosrd2 move.l d2,d0 - bra.s storesr2 - -movetosrd3 move.l d3,d0 - bra.s storesr2 - -movetosrd4 move.l d4,d0 - bra.s storesr2 - -movetosrd5 move.l d5,d0 - bra.s storesr2 - -movetosrd6 move.l d6,d0 - bra.s storesr2 - -movetosrd7 move.l d7,d0 - bra.s storesr2 - -; movec cr,x -movecfromcr move.w ([6,sp],2),d0 ;Get next instruction word - - cmp.w #$8801,d0 ;movec vbr,a0? - beq.s movecvbra0 - cmp.w #$9801,d0 ;movec vbr,a1? - beq.s movecvbra1 - cmp.w #$A801,d0 ;movec vbr,a2? - beq.s movecvbra2 - cmp.w #$1801,d0 ;movec vbr,d1? - beq movecvbrd1 - cmp.w #$0002,d0 ;movec cacr,d0? - beq.s moveccacrd0 - cmp.w #$1002,d0 ;movec cacr,d1? - beq.s moveccacrd1 - cmp.w #$0003,d0 ;movec tc,d0? - beq.s movectcd0 - cmp.w #$1003,d0 ;movec tc,d1? - beq.s movectcd1 - cmp.w #$1000,d0 ;movec sfc,d1? - beq movecsfcd1 - cmp.w #$1001,d0 ;movec dfc,d1? - beq movecdfcd1 - cmp.w #$0806,d0 ;movec urp,d0? - beq movecurpd0 - cmp.w #$0807,d0 ;movec srp,d0? - beq.s movecsrpd0 - cmp.w #$0004,d0 ;movec itt0,d0 - beq.s movecitt0d0 - cmp.w #$0005,d0 ;movec itt1,d0 - beq.s movecitt1d0 - cmp.w #$0006,d0 ;movec dtt0,d0 - beq.s movecdtt0d0 - cmp.w #$0007,d0 ;movec dtt1,d0 - beq.s movecdtt1d0 - - bra pv_unhandled - -; movec cacr,d0 -moveccacrd0 move.l (sp)+,d0 - move.l #$3111,d0 ;All caches and bursts on - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec cacr,d1 -moveccacrd1 move.l (sp)+,d0 - move.l #$3111,d1 ;All caches and bursts on - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec vbr,a0 -movecvbra0 move.l (sp)+,d0 - sub.l a0,a0 ;VBR always appears to be at 0 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec vbr,a1 -movecvbra1 move.l (sp)+,d0 - sub.l a1,a1 ;VBR always appears to be at 0 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec vbr,a2 -movecvbra2 move.l (sp)+,d0 - sub.l a2,a2 ;VBR always appears to be at 0 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec vbr,d1 -movecvbrd1 move.l (sp)+,d0 - moveq.l #0,d1 ;VBR always appears to be at 0 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec tc,d0 -movectcd0 addq.l #4,sp - moveq #0,d0 ;MMU is always off - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec tc,d1 +jl+ -movectcd1 move.l (sp)+,d0 ;Restore d0 - moveq #0,d1 ;MMU is always off - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec sfc,d1 +jl+ -movecsfcd1 move.l (sp)+,d0 ;Restore d0 - moveq #0,d1 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec dfc,d1 +jl+ -movecdfcd1 move.l (sp)+,d0 ;Restore d0 - moveq #0,d1 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -movecurpd0 ; movec urp,d0 +jl+ -movecsrpd0 ; movec srp,d0 -movecitt0d0 ; movec itt0,d0 -movecitt1d0 ; movec itt1,d0 -movecdtt0d0 ; movec dtt0,d0 -movecdtt1d0 ; movec dtt1,d0 - addq.l #4,sp - moveq.l #0,d0 ;MMU is always off - addq.l #4,2(sp) ;skip instruction - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec x,cr -movectocr move.w ([6,sp],2),d0 ;Get next instruction word - - cmp.w #$0801,d0 ;movec d0,vbr? - beq.s movectovbr - cmp.w #$1801,d0 ;movec d1,vbr? - beq.s movectovbr - cmp.w #$A801,d0 ;movec a2,vbr? - beq.s movectovbr - cmp.w #$0002,d0 ;movec d0,cacr? - beq.s movectocacr - cmp.w #$1002,d0 ;movec d1,cacr? - beq.s movectocacr - cmp.w #$1000,d0 ;movec d1,sfc? - beq.s movectoxfc - cmp.w #$1001,d0 ;movec d1,dfc? - beq.s movectoxfc - - bra pv_unhandled - -; movec x,vbr -movectovbr move.l (sp)+,d0 ;Ignore moves to VBR - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec dx,cacr -movectocacr movem.l d1/a0-a1/a6,-(sp) ;Move to CACR, clear caches - move.l _SysBase,a6 - JSRLIB CacheClearU - movem.l (sp)+,d1/a0-a1/a6 - move.l (sp)+,d0 - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; movec x,sfc -; movec x,dfc -movectoxfc move.l (sp)+,d0 ;Ignore moves to SFC, DFC - addq.l #4,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; cpusha -cpushadc -cpushadcic - IFEQ INFO_LEVEL-1003 - move.l (4),-(sp) - move.l d0,-(sp) - PUTMSG 0,'%s/cpushadc: opcode=%04lx Execbase=%08lx' - lea (2*4,sp),sp - ENDC - movem.l d1/a0-a1/a6,-(sp) ;Clear caches - move.l _SysBase,a6 - JSRLIB CacheClearU - movem.l (sp)+,d1/a0-a1/a6 - move.l (sp)+,d0 - addq.l #2,2(sp) - rte - -; move usp,a1 +jl+ -moveuspa1 move.l (sp)+,d0 - move usp,a1 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1009 - move.l a1,-(sp) - move.l a7,-(sp) - PUTMSG 0,'%s/moveuspa1: a7=%08lx a1=%08lx' - lea (2*4,sp),sp - ENDC - - rte - -; move usp,a0 +jl+ -moveuspa0 move.l (sp)+,d0 - move usp,a0 - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1009 - move.l a0,-(sp) - move.l a7,-(sp) - PUTMSG 0,'%s/moveuspa0: a7=%08lx a0=%08lx' - lea (2*4,sp),sp - ENDC - - rte - -; move a1,usp +jl+ -moved1usp move.l (sp)+,d0 - move a1,usp - addq.l #2,2(sp) - - IFEQ INFO_LEVEL-1001 - move.l (4),-(sp) - PUTMSG 0,'%s/doprivviol END: Execbase=%08lx' - lea (1*4,sp),sp - ENDC - rte - -; -; Trigger NMI (Pop up debugger) -; - -_AsmTriggerNMI move.l d0,-(sp) ;Save d0 - move.w #$007c,-(sp) ;Yes, fake NMI stack frame - pea 1$ - move.w _EmulatedSR,d0 - and.w #$f8ff,d0 ;Set interrupt level in SR - move.w d0,-(sp) - move.w d0,_EmulatedSR - - move.l $7c.w,-(sp) ;Jump to MacOS NMI handler - rts - -1$ move.l (sp)+,d0 ;Restore d0 - rts - - -CopyTrapStack: - movem.l d0/a0/a1,-(sp) - - move.w (5*4+6,sp),d0 ;get format word - lsr.w #7,d0 ;get stack frame Id - lsr.w #4,d0 - and.w #$001e,d0 - move.w (StackFormatTable,pc,d0.w),d0 ; get total stack frame length - - lea (5*4,sp),a0 ;get start of exception stack frame - move.l usp,a1 ;Get user stack pointer - bra 1$ - -2$ move.w (a0)+,(a1)+ ; copy additional stack words back to supervisor stack -1$ dbf d0,2$ - - move.l (3*4,sp),-(a0) ;copy return address to new top of stack - move.l a0,sp - rts - - END diff --git a/BasiliskII/src/AmigaOS/audio_amiga.cpp b/BasiliskII/src/AmigaOS/audio_amiga.cpp deleted file mode 100644 index 5c264314..00000000 --- a/BasiliskII/src/AmigaOS/audio_amiga.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - * audio_amiga.cpp - Audio support, AmigaOS implementation using AHI - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "audio.h" -#include "audio_defs.h" - -#define DEBUG 0 -#include "debug.h" - -#define D1(x) ; - - -// Global variables -static ULONG ahi_id = AHI_DEFAULT_ID; // AHI audio ID -static struct AHIAudioCtrl *ahi_ctrl = NULL; -static struct AHISampleInfo sample[2]; // Two sample infos for double-buffering -static struct Hook sf_hook; -static int play_buf = 0; // Number of currently played buffer -static long sound_buffer_size; // Size of one audio buffer in bytes -static int audio_block_fetched = 0; // Number of audio blocks fetched by interrupt routine - -static bool main_mute = false; -static bool speaker_mute = false; -static ULONG supports_volume_changes = false; -static ULONG supports_stereo_panning = false; -static ULONG current_main_volume; -static ULONG current_speaker_volume; - - -// Prototypes -static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/); -void audio_set_sample_rate_byval(uint32 value); -void audio_set_sample_size_byval(uint32 value); -void audio_set_channels_byval(uint32 value); - - -/* - * Initialization - */ - -// Set AudioStatus to reflect current audio stream format -static void set_audio_status_format(int sample_rate_index) -{ - AudioStatus.sample_rate = audio_sample_rates[sample_rate_index]; - AudioStatus.sample_size = audio_sample_sizes[0]; - AudioStatus.channels = audio_channel_counts[0]; -} - -void AudioInit(void) -{ - sample[0].ahisi_Address = sample[1].ahisi_Address = NULL; - - // Init audio status and feature flags - audio_channel_counts.push_back(2); -// set_audio_status_format(); - AudioStatus.mixer = 0; - AudioStatus.num_sources = 0; - audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut; - - // Sound disabled in prefs? Then do nothing - if (PrefsFindBool("nosound")) - return; - - // AHI available? - if (AHIBase == NULL) { - WarningAlert(GetString(STR_NO_AHI_WARN)); - return; - } - - // Initialize callback hook - sf_hook.h_Entry = (HOOKFUNC)audio_callback; - - // Read "sound" preferences - const char *str = PrefsFindString("sound"); - if (str) - sscanf(str, "ahi/%08lx", &ahi_id); - - // Open audio control structure - if ((ahi_ctrl = AHI_AllocAudio( - AHIA_AudioID, ahi_id, - AHIA_MixFreq, AudioStatus.sample_rate >> 16, - AHIA_Channels, 1, - AHIA_Sounds, 2, - AHIA_SoundFunc, (ULONG)&sf_hook, - TAG_END)) == NULL) { - WarningAlert(GetString(STR_NO_AHI_CTRL_WARN)); - return; - } - - ULONG max_channels, sample_rate, frequencies, sample_rate_index; - - AHI_GetAudioAttrs(ahi_id, ahi_ctrl, - AHIDB_MaxChannels, (ULONG) &max_channels, - AHIDB_Frequencies, (ULONG) &frequencies, - TAG_END); - - D(bug("AudioInit: max_channels=%ld frequencies=%ld\n", max_channels, frequencies)); - - for (int n=0; n> 3) * AudioStatus.channels * audio_frames_per_block; - - // Prepare SampleInfos and load sounds (two sounds for double buffering) - sample[0].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S; - sample[0].ahisi_Length = audio_frames_per_block; - sample[0].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR); - sample[1].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S; - sample[1].ahisi_Length = audio_frames_per_block; - sample[1].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR); - if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL) - return; - - AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl); - AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl); - - // Set parameters - play_buf = 0; - current_main_volume = current_speaker_volume = 0x10000; - AHI_SetVol(0, current_speaker_volume, 0x8000, ahi_ctrl, AHISF_IMM); - - AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, AHISF_IMM); - AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM); - - // Everything OK - audio_open = true; -} - - -/* - * Deinitialization - */ - -void AudioExit(void) -{ - // Free everything - if (ahi_ctrl != NULL) { - AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END); - AHI_FreeAudio(ahi_ctrl); - } - - FreeVec(sample[0].ahisi_Address); - FreeVec(sample[1].ahisi_Address); -} - - -/* - * First source added, start audio stream - */ - -void audio_enter_stream() -{ - AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_END); -} - - -/* - * Last source removed, stop audio stream - */ - -void audio_exit_stream() -{ - AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END); -} - - -/* - * AHI sound callback, request next buffer - */ - -static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/) -{ - play_buf ^= 1; - - // New buffer available? - if (audio_block_fetched) - { - audio_block_fetched--; - - if (main_mute || speaker_mute) - { - memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size); - } - else - { - // Get size of audio data - uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo); - if (apple_stream_info) { - int32 sample_count = ReadMacInt32(apple_stream_info + scd_sampleCount); - - uint32 num_channels = ReadMacInt16(apple_stream_info + scd_numChannels); - uint32 sample_size = ReadMacInt16(apple_stream_info + scd_sampleSize); - uint32 sample_rate = ReadMacInt32(apple_stream_info + scd_sampleRate); - - D(bug("stream: sample_count=%ld num_channels=%ld sample_size=%ld sample_rate=%ld\n", sample_count, num_channels, sample_size, sample_rate >> 16)); - - // Yes, this can happen. - if(sample_count != 0) { - if(sample_rate != AudioStatus.sample_rate) { - audio_set_sample_rate_byval(sample_rate); - } - if(num_channels != AudioStatus.channels) { - audio_set_channels_byval(num_channels); - } - if(sample_size != AudioStatus.sample_size) { - audio_set_sample_size_byval(sample_size); - } - } - - if (sample_count < 0) - sample_count = 0; - - int work_size = sample_count * num_channels * (sample_size>>3); - D(bug("stream: work_size=%ld sound_buffer_size=%ld\n", work_size, sound_buffer_size)); - - if (work_size > sound_buffer_size) - work_size = sound_buffer_size; - - // Put data into AHI buffer (convert 8-bit data unsigned->signed) - if (AudioStatus.sample_size == 16) - Mac2Host_memcpy(sample[play_buf].ahisi_Address, ReadMacInt32(apple_stream_info + scd_buffer), work_size); - else { - uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)); - uint32 *q = (uint32 *)sample[play_buf].ahisi_Address; - int r = work_size >> 2; - while (r--) - *q++ = *p++ ^ 0x80808080; - } - if (work_size != sound_buffer_size) - memset((uint8 *)sample[play_buf].ahisi_Address + work_size, 0, sound_buffer_size - work_size); - } - } - - } - else - memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size); - - // Play next buffer - AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, 0); - - // Trigger audio interrupt to get new buffer - if (AudioStatus.num_sources) { - D1(bug("stream: triggering irq\n")); - SetInterruptFlag(INTFLAG_AUDIO); - TriggerInterrupt(); - } - return 0; -} - - -/* - * MacOS audio interrupt, read next data block - */ - -void AudioInterrupt(void) -{ - D1(bug("AudioInterrupt\n")); - - // Get data from apple mixer - if (AudioStatus.mixer) { - M68kRegisters r; - r.a[0] = audio_data + adatStreamInfo; - r.a[1] = AudioStatus.mixer; - Execute68k(audio_data + adatGetSourceData, &r); - D1(bug(" GetSourceData() returns %08lx\n", r.d[0])); - } else - WriteMacInt32(audio_data + adatStreamInfo, 0); - - // Signal stream function - audio_block_fetched++; - D1(bug("AudioInterrupt done\n")); -} - - -/* - * Set sampling parameters - * "index" is an index into the audio_sample_rates[] etc. arrays - * It is guaranteed that AudioStatus.num_sources == 0 - */ - -void audio_set_sample_rate_byval(uint32 value) -{ - bool changed = (AudioStatus.sample_rate != value); - if(changed) - { - ULONG sample_rate_index; - - // get index of sample rate closest to Hz - AHI_GetAudioAttrs(ahi_id, ahi_ctrl, - AHIDB_IndexArg, value >> 16, - AHIDB_Index, (ULONG) &sample_rate_index, - TAG_END); - - D(bug(" audio_set_sample_rate_byval requested rate=%ld Hz\n", value >> 16)); - - AudioStatus.sample_rate = audio_sample_rates[sample_rate_index]; - - AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, 0); - } - - D(bug(" audio_set_sample_rate_byval rate=%ld Hz\n", AudioStatus.sample_rate >> 16)); -} - -void audio_set_sample_size_byval(uint32 value) -{ - bool changed = (AudioStatus.sample_size != value); - if(changed) { -// AudioStatus.sample_size = value; -// update_sound_parameters(); -// WritePrivateProfileInt( "Audio", "SampleSize", AudioStatus.sample_size, ini_file_name ); - } - D(bug(" audio_set_sample_size_byval %d\n", AudioStatus.sample_size)); -} - -void audio_set_channels_byval(uint32 value) -{ - bool changed = (AudioStatus.channels != value); - if(changed) { -// AudioStatus.channels = value; -// update_sound_parameters(); -// WritePrivateProfileInt( "Audio", "Channels", AudioStatus.channels, ini_file_name ); - } - D(bug(" audio_set_channels_byval %d\n", AudioStatus.channels)); -} - -bool audio_set_sample_rate(int index) -{ - if(index >= 0 && index < audio_sample_rates.size() ) { - audio_set_sample_rate_byval( audio_sample_rates[index] ); - D(bug(" audio_set_sample_rate index=%ld rate=%ld\n", index, AudioStatus.sample_rate >> 16)); - } - - return true; -} - -bool audio_set_sample_size(int index) -{ - if(index >= 0 && index < audio_sample_sizes.size() ) { - audio_set_sample_size_byval( audio_sample_sizes[index] ); - D(bug(" audio_set_sample_size %d,%d\n", index,AudioStatus.sample_size)); - } - - return true; -} - -bool audio_set_channels(int index) -{ - if(index >= 0 && index < audio_channel_counts.size() ) { - audio_set_channels_byval( audio_channel_counts[index] ); - D(bug(" audio_set_channels %d,%d\n", index,AudioStatus.channels)); - } - - return true; -} - - -/* - * Get/set volume controls (volume values received/returned have the left channel - * volume in the upper 16 bits and the right channel volume in the lower 16 bits; - * both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume")) - */ - -bool audio_get_main_mute(void) -{ - D(bug("audio_get_main_mute: mute=%ld\n", main_mute)); - - return main_mute; -} - -uint32 audio_get_main_volume(void) -{ - D(bug("audio_get_main_volume\n")); - - ULONG volume = current_main_volume >> 8; // 0x10000 => 0x100 - - D(bug("audio_get_main_volume: volume=%08lx\n", volume)); - - return (volume << 16) + volume; - - return 0x01000100; -} - -bool audio_get_speaker_mute(void) -{ - D(bug("audio_get_speaker_mute: mute=%ld\n", speaker_mute)); - - return speaker_mute; -} - -uint32 audio_get_speaker_volume(void) -{ - D(bug("audio_get_speaker_volume: \n")); - - if (audio_open) - { - ULONG volume = current_speaker_volume >> 8; // 0x10000 => 0x100 - - D(bug("audio_get_speaker_volume: volume=%08lx\n", volume)); - - return (volume << 16) + volume; - } - - return 0x01000100; -} - -void audio_set_main_mute(bool mute) -{ - D(bug("audio_set_main_mute: mute=%ld\n", mute)); - - if (mute != main_mute) - { - main_mute = mute; - } -} - -void audio_set_main_volume(uint32 vol) -{ - D(bug("audio_set_main_volume: vol=%08lx\n", vol)); - - if (audio_open && supports_volume_changes) - { - ULONG volume = 0x80 * ((vol >> 16) + (vol & 0xffff)); - - D(bug("audio_set_main_volume: volume=%08lx\n", volume)); - - current_main_volume = volume; - - AHI_SetVol(0, volume, 0x8000, ahi_ctrl, AHISF_IMM); - } -} - -void audio_set_speaker_mute(bool mute) -{ - D(bug("audio_set_speaker_mute: mute=%ld\n", mute)); - - if (mute != speaker_mute) - { - speaker_mute = mute; - } -} - -void audio_set_speaker_volume(uint32 vol) -{ - D(bug("audio_set_speaker_volume: vol=%08lx\n", vol)); - - if (audio_open && supports_volume_changes) - { - ULONG volume = 0x80 * ((vol >> 16) + (vol & 0xffff)); - - D(bug("audio_set_speaker_volume: volume=%08lx\n", volume)); - - current_speaker_volume = volume; - - AHI_SetVol(0, volume, 0x8000, ahi_ctrl, AHISF_IMM); - } -} diff --git a/BasiliskII/src/AmigaOS/clip_amiga.cpp b/BasiliskII/src/AmigaOS/clip_amiga.cpp deleted file mode 100644 index 10336bbd..00000000 --- a/BasiliskII/src/AmigaOS/clip_amiga.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * clip_amiga.cpp - Clipboard handling, AmigaOS implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include - -#include "clip.h" -#include "prefs.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static struct IFFHandle *iffw = NULL; -static struct ClipboardHandle *ch = NULL; -static bool clipboard_open = false; -static bool no_clip_conversion; - - -// Conversion tables -static const uint8 mac2iso[0x80] = { - 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, - 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, - 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, - 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, - 0x2b, 0xb0, 0xa2, 0xa3, 0xa7, 0xb7, 0xb6, 0xdf, - 0xae, 0xa9, 0x20, 0xb4, 0xa8, 0x23, 0xc6, 0xd8, - 0x20, 0xb1, 0x3c, 0x3e, 0xa5, 0xb5, 0xf0, 0x53, - 0x50, 0x70, 0x2f, 0xaa, 0xba, 0x4f, 0xe6, 0xf8, - 0xbf, 0xa1, 0xac, 0x2f, 0x66, 0x7e, 0x44, 0xab, - 0xbb, 0x2e, 0x20, 0xc0, 0xc3, 0xd5, 0x4f, 0x6f, - 0x2d, 0x2d, 0x22, 0x22, 0x60, 0x27, 0xf7, 0x20, - 0xff, 0x59, 0x2f, 0xa4, 0x3c, 0x3e, 0x66, 0x66, - 0x23, 0xb7, 0x2c, 0x22, 0x25, 0xc2, 0xca, 0xc1, - 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, - 0x20, 0xd2, 0xda, 0xdb, 0xd9, 0x69, 0x5e, 0x7e, - 0xaf, 0x20, 0xb7, 0xb0, 0xb8, 0x22, 0xb8, 0x20 -}; - - -/* - * Initialization - */ - -void ClipInit(void) -{ - no_clip_conversion = PrefsFindBool("noclipconversion"); - - // Create clipboard IFF handle - iffw = AllocIFF(); - if (iffw) { - ch = OpenClipboard(PRIMARY_CLIP); - if (ch) { - iffw->iff_Stream = (ULONG)ch; - InitIFFasClip(iffw); - clipboard_open = true; - } - } -} - - -/* - * Deinitialization - */ - -void ClipExit(void) -{ - if (ch) - CloseClipboard(ch); - if (iffw) - FreeIFF(iffw); -} - -/* - * Mac application zeroes clipboard - */ - -void ZeroScrap() -{ - -} - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32 type, int32 offset) -{ - D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); -} - - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32 type, void *scrap, int32 length) -{ - D(bug("PutScrap type %08lx, data %08lx, length %ld\n", type, scrap, length)); - if (length <= 0 || !clipboard_open) - return; - - switch (type) { - case 'TEXT': { - D(bug(" clipping TEXT\n")); - - // Open IFF stream - if (OpenIFF(iffw, IFFF_WRITE)) - break; - - // Convert text from Mac charset to ISO-Latin1 - uint8 *buf = new uint8[length]; - uint8 *p = (uint8 *)scrap; - uint8 *q = buf; - for (int i=0; i LF - c = 10; - } else if (!no_clip_conversion) - c = mac2iso[c & 0x7f]; - *q++ = c; - } - - // Write text - if (!PushChunk(iffw, 'FTXT', 'FORM', IFFSIZE_UNKNOWN)) { - if (!PushChunk(iffw, 0, 'CHRS', IFFSIZE_UNKNOWN)) { - WriteChunkBytes(iffw, scrap, length); - PopChunk(iffw); - } - PopChunk(iffw); - } - - // Close IFF stream - CloseIFF(iffw); - delete[] buf; - break; - } - } -} diff --git a/BasiliskII/src/AmigaOS/ether_amiga.cpp b/BasiliskII/src/AmigaOS/ether_amiga.cpp deleted file mode 100644 index 99121a24..00000000 --- a/BasiliskII/src/AmigaOS/ether_amiga.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/* - * ether_amiga.cpp - Ethernet device driver, AmigaOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "macos_util.h" -#include "ether.h" -#include "ether_defs.h" - -#define DEBUG 0 -#include "debug.h" - -#define MONITOR 0 - - -// These messages are sent to the network process -const uint32 MSG_CLEANUP = 'clea'; // Remove all protocols -const uint32 MSG_ADD_MULTI = 'addm'; // Add multicast address -const uint32 MSG_DEL_MULTI = 'delm'; // Add multicast address -const uint32 MSG_ATTACH_PH = 'atph'; // Attach protocol handler -const uint32 MSG_DETACH_PH = 'deph'; // Attach protocol handler -const uint32 MSG_WRITE = 'writ'; // Write packet - -struct NetMessage : public Message { - NetMessage(uint32 what_, const struct MsgPort *reply_port) - { - what = what_; - mn_ReplyPort = (struct MsgPort *)reply_port; - mn_Length = sizeof(*this); - } - uint32 what; - uint32 pointer; - uint16 type; - int16 result; -}; - - -// List of attached protocols -static const int NUM_READ_REQUESTS = 32; // Number of read requests that are sent to device in advance - -struct NetProtocol : public Node { - struct IOSana2Req read_io[NUM_READ_REQUESTS]; - uint8 read_buf[NUM_READ_REQUESTS][1518]; // 14 bytes header, 1500 bytes data, 4 bytes CRC - uint16 type; - uint32 handler; -}; - -static struct List prot_list; - - -// Global variables -static struct Process *net_proc = NULL; // Network device handler process -static bool proc_error; // Flag: process didn't initialize -static struct MsgPort *proc_port = NULL; // Message port of process, for communication with main task -static struct MsgPort *reply_port = NULL; // Reply port for communication with process -static struct MsgPort *read_port = NULL; // Reply port for read IORequests (set up and owned by network process) - -static bool write_done = false; // Flag: write request done - -extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp) - - -// Prototypes -static void net_func(void); - - -/* - * Send message to network process - */ - -static int16 send_to_proc(uint32 what, uint32 pointer = 0, uint16 type = 0) -{ - D(bug("sending %08lx to net_proc\n", what)); - NetMessage msg(what, reply_port); - msg.pointer = pointer; - msg.type = type; - PutMsg(proc_port, &msg); - WaitPort(reply_port); - GetMsg(reply_port); - D(bug(" sent\n")); - return msg.result; -} - - -/* - * Initialization - */ - -bool ether_init(void) -{ - // Do nothing if no Ethernet device specified - if (PrefsFindString("ether") == NULL) - return false; - - // Initialize protocol list - NewList(&prot_list); - - // Create message port - reply_port = CreateMsgPort(); - if (reply_port == NULL) - goto open_error; - D(bug("signal mask %08lx\n", 1 << reply_port->mp_SigBit)); - - // Start process - proc_error = false; - SetSignal(0, SIGF_SINGLE); - net_proc = CreateNewProcTags( - NP_Entry, (ULONG)net_func, - NP_Name, (ULONG)"Basilisk II Ethernet Task", - NP_Priority, 1, - TAG_END - ); - if (net_proc == NULL) - goto open_error; - - // Wait for signal from process - Wait(SIGF_SINGLE); - - // Initialization error? Then bail out - if (proc_error) - goto open_error; - - // Everything OK - return true; - -open_error: - net_proc = NULL; - if (reply_port) { - DeleteMsgPort(reply_port); - reply_port = NULL; - } - return false; -} - - -/* - * Deinitialization - */ - -void ether_exit(void) -{ - // Stop process - if (net_proc) { - SetSignal(0, SIGF_SINGLE); - Signal(&net_proc->pr_Task, SIGBREAKF_CTRL_C); - Wait(SIGF_SINGLE); - } - - // Delete reply port - if (reply_port) { - DeleteMsgPort(reply_port); - reply_port = NULL; - } -} - - -/* - * Reset - */ - -void ether_reset(void) -{ - // Remove all protocols - if (net_proc) - send_to_proc(MSG_CLEANUP); -} - - -/* - * Add multicast address - */ - -int16 ether_add_multicast(uint32 pb) -{ - return send_to_proc(MSG_ADD_MULTI, pb); -} - - -/* - * Delete multicast address - */ - -int16 ether_del_multicast(uint32 pb) -{ - return send_to_proc(MSG_DEL_MULTI, pb); -} - - -/* - * Attach protocol handler - */ - -int16 ether_attach_ph(uint16 type, uint32 handler) -{ - return send_to_proc(MSG_ATTACH_PH, handler, type); -} - - -/* - * Detach protocol handler - */ - -int16 ether_detach_ph(uint16 type) -{ - return send_to_proc(MSG_DETACH_PH, type); -} - - -/* - * Transmit raw ethernet packet - */ - -int16 ether_write(uint32 wds) -{ - send_to_proc(MSG_WRITE, wds); - return 1; // Command in progress -} - - -/* - * Remove protocol from protocol list - */ - -static void remove_protocol(NetProtocol *p) -{ - // Remove from list - Forbid(); - Remove(p); - Permit(); - - // Cancel read requests - for (int i=0; iread_io + i)); - WaitIO((struct IORequest *)(p->read_io + i)); - } - - // Free protocol struct - FreeMem(p, sizeof(NetProtocol)); -} - - -/* - * Remove all protocols - */ - -static void remove_all_protocols(void) -{ - NetProtocol *n = (NetProtocol *)prot_list.lh_Head, *next; - while ((next = (NetProtocol *)n->ln_Succ) != NULL) { - remove_protocol(n); - n = next; - } -} - - -/* - * Copy received network packet to Mac side - */ - -static __saveds __regargs LONG copy_to_buff(uint8 *to /*a0*/, uint8 *from /*a1*/, uint32 packet_len /*d0*/) -{ - D(bug("CopyToBuff to %08lx, from %08lx, size %08lx\n", to, from, packet_len)); - - // It would be more efficient (and take up less memory) if we - // could invoke the packet handler from here. But we don't know - // in what context we run, so calling Execute68k() would not be - // a good idea, and even worse, we might run inside a hardware - // interrupt, so we can't even trigger a Basilisk interrupt from - // here and wait for its completion. - CopyMem(from, to, packet_len); -#if MONITOR - bug("Receiving Ethernet packet:\n"); - for (int i=0; imp_SigBit; - - // Create message ports for device I/O - read_port = CreateMsgPort(); - if (read_port == NULL) - goto quit; - read_mask = 1 << read_port->mp_SigBit; - write_port = CreateMsgPort(); - if (write_port == NULL) - goto quit; - write_mask = 1 << write_port->mp_SigBit; - control_port = CreateMsgPort(); - if (control_port == NULL) - goto quit; - - // Create control IORequest - control_io = (struct IOSana2Req *)CreateIORequest(control_port, sizeof(struct IOSana2Req)); - if (control_io == NULL) - goto quit; - control_io->ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug - - // Parse device name - char dev_name[256]; - ULONG dev_unit; - - str = PrefsFindString("ether"); - if (str) { - const char *FirstSlash = strchr(str, '/'); - const char *LastSlash = strrchr(str, '/'); - - if (FirstSlash && FirstSlash && FirstSlash != LastSlash) { - - // Device name contains path, i.e. "Networks/xyzzy.device" - const char *lp = str; - char *dp = dev_name; - - while (lp != LastSlash) - *dp++ = *lp++; - *dp = '\0'; - - if (strlen(dev_name) < 1) - goto quit; - - if (sscanf(LastSlash, "/%ld", &dev_unit) != 1) - goto quit; - } else { - if (sscanf(str, "%[^/]/%ld", dev_name, &dev_unit) != 2) - goto quit; - } - } else - goto quit; - - // Open device - control_io->ios2_BufferManagement = buffer_tags; - od_error = OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)control_io, 0); - if (od_error != 0 || control_io->ios2_Req.io_Device == 0) { - printf("WARNING: OpenDevice(<%s>, unit=%d) returned error %d)\n", (UBYTE *)dev_name, dev_unit, od_error); - goto quit; - } - opened = true; - - // Is it Ethernet? - control_io->ios2_Req.io_Command = S2_DEVICEQUERY; - control_io->ios2_StatData = (void *)&query_data; - DoIO((struct IORequest *)control_io); - if (control_io->ios2_Req.io_Error) - goto quit; - if (query_data.HardwareType != S2WireType_Ethernet) { - WarningAlert(GetString(STR_NOT_ETHERNET_WARN)); - goto quit; - } - - // Yes, create IORequest for writing - write_io = (struct IOSana2Req *)CreateIORequest(write_port, sizeof(struct IOSana2Req)); - if (write_io == NULL) - goto quit; - memcpy(write_io, control_io, sizeof(struct IOSana2Req)); - write_io->ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug - write_io->ios2_Req.io_Message.mn_ReplyPort = write_port; - - // Configure Ethernet - control_io->ios2_Req.io_Command = S2_GETSTATIONADDRESS; - DoIO((struct IORequest *)control_io); - memcpy(ether_addr, control_io->ios2_DstAddr, 6); - memcpy(control_io->ios2_SrcAddr, control_io->ios2_DstAddr, 6); - control_io->ios2_Req.io_Command = S2_CONFIGINTERFACE; - DoIO((struct IORequest *)control_io); - D(bug("Ethernet address %08lx %08lx\n", *(uint32 *)ether_addr, *(uint16 *)(ether_addr + 4))); - - // Initialization went well, inform main task - proc_error = false; - Signal(MainTask, SIGF_SINGLE); - - // Main loop - for (;;) { - - // Wait for I/O and messages (CTRL_C is used for quitting the task) - ULONG sig = Wait(proc_port_mask | read_mask | write_mask | SIGBREAKF_CTRL_C); - - // Main task wants to quit us - if (sig & SIGBREAKF_CTRL_C) - break; - - // Main task sent a command to us - if (sig & proc_port_mask) { - struct NetMessage *msg; - while (msg = (NetMessage *)GetMsg(proc_port)) { - D(bug("net_proc received %08lx\n", msg->what)); - switch (msg->what) { - case MSG_CLEANUP: - remove_all_protocols(); - break; - - case MSG_ADD_MULTI: - control_io->ios2_Req.io_Command = S2_ADDMULTICASTADDRESS; - Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6); - DoIO((struct IORequest *)control_io); - if (control_io->ios2_Req.io_Error == S2ERR_NOT_SUPPORTED) { - WarningAlert(GetString(STR_NO_MULTICAST_WARN)); - msg->result = noErr; - } else if (control_io->ios2_Req.io_Error) - msg->result = eMultiErr; - else - msg->result = noErr; - break; - - case MSG_DEL_MULTI: - control_io->ios2_Req.io_Command = S2_DELMULTICASTADDRESS; - Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6); - DoIO((struct IORequest *)control_io); - if (control_io->ios2_Req.io_Error) - msg->result = eMultiErr; - else - msg->result = noErr; - break; - - case MSG_ATTACH_PH: { - uint16 type = msg->type; - uint32 handler = msg->pointer; - - // Protocol of that type already installed? - NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next; - while ((next = (NetProtocol *)p->ln_Succ) != NULL) { - if (p->type == type) { - msg->result = lapProtErr; - goto reply; - } - p = next; - } - - // Allocate NetProtocol, set type and handler - p = (NetProtocol *)AllocMem(sizeof(NetProtocol), MEMF_PUBLIC); - if (p == NULL) { - msg->result = lapProtErr; - goto reply; - } - p->type = type; - p->handler = handler; - - // Set up and submit read requests - for (int i=0; iread_io + i, control_io, sizeof(struct IOSana2Req)); - p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Name = (char *)p; // Hide pointer to NetProtocol in node name - p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug - p->read_io[i].ios2_Req.io_Message.mn_ReplyPort = read_port; - p->read_io[i].ios2_Req.io_Command = CMD_READ; - p->read_io[i].ios2_PacketType = type; - p->read_io[i].ios2_Data = p->read_buf[i]; - p->read_io[i].ios2_Req.io_Flags = SANA2IOF_RAW; - BeginIO((struct IORequest *)(p->read_io + i)); - } - - // Add protocol to list - AddTail(&prot_list, p); - - // Everything OK - msg->result = noErr; - break; - } - - case MSG_DETACH_PH: { - uint16 type = msg->type; - msg->result = lapProtErr; - NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next; - while ((next = (NetProtocol *)p->ln_Succ) != NULL) { - if (p->type == type) { - remove_protocol(p); - msg->result = noErr; - break; - } - p = next; - } - break; - } - - case MSG_WRITE: { - // Get pointer to Write Data Structure - uint32 wds = msg->pointer; - write_io->ios2_Data = (void *)wds; - - // Calculate total packet length - long len = 0; - uint32 tmp = wds; - for (;;) { - int16 w = ReadMacInt16(tmp); - if (w == 0) - break; - len += w; - tmp += 6; - } - write_io->ios2_DataLength = len; - - // Get destination address - uint32 hdr = ReadMacInt32(wds + 2); - Mac2Host_memcpy(write_io->ios2_DstAddr, hdr, 6); - - // Get packet type - uint32 type = ReadMacInt16(hdr + 12); - if (type <= 1500) - type = 0; // 802.3 packet - write_io->ios2_PacketType = type; - - // Multicast/broadcard packet? - if (write_io->ios2_DstAddr[0] & 1) { - if (*(uint32 *)(write_io->ios2_DstAddr) == 0xffffffff && *(uint16 *)(write_io->ios2_DstAddr + 4) == 0xffff) - write_io->ios2_Req.io_Command = S2_BROADCAST; - else - write_io->ios2_Req.io_Command = S2_MULTICAST; - } else - write_io->ios2_Req.io_Command = CMD_WRITE; - - // Send packet - write_done = false; - write_io->ios2_Req.io_Flags = SANA2IOF_RAW; - BeginIO((IORequest *)write_io); - break; - } - } -reply: D(bug(" net_proc replying\n")); - ReplyMsg(msg); - } - } - - // Packet received - if (sig & read_mask) { - D(bug(" packet received, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - } - - // Packet write completed - if (sig & write_mask) { - GetMsg(write_port); - WriteMacInt32(ether_data + ed_Result, write_io->ios2_Req.io_Error ? excessCollsns : 0); - write_done = true; - D(bug(" packet write done, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - } - } -quit: - - // Close everything - remove_all_protocols(); - if (opened) { - if (CheckIO((struct IORequest *)write_io) == 0) { - AbortIO((struct IORequest *)write_io); - WaitIO((struct IORequest *)write_io); - } - CloseDevice((struct IORequest *)control_io); - } - if (write_io) - DeleteIORequest(write_io); - if (control_io) - DeleteIORequest(control_io); - if (control_port) - DeleteMsgPort(control_port); - if (write_port) - DeleteMsgPort(write_port); - if (read_port) - DeleteMsgPort(read_port); - - // Send signal to main task to confirm termination - Forbid(); - Signal(MainTask, SIGF_SINGLE); -} - - -/* - * Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers - */ - -void EtherInterrupt(void) -{ - D(bug("EtherIRQ\n")); - - // Packet write done, enqueue DT to call IODone - if (write_done) { - EnqueueMac(ether_data + ed_DeferredTask, 0xd92); - write_done = false; - } - - // Call protocol handler for received packets - IOSana2Req *io; - while (io = (struct IOSana2Req *)GetMsg(read_port)) { - - // Get pointer to NetProtocol (hidden in node name) - NetProtocol *p = (NetProtocol *)io->ios2_Req.io_Message.mn_Node.ln_Name; - - // No default handler - if (p->handler == 0) - continue; - - // Copy header to RHA - Host2Mac_memcpy(ether_data + ed_RHA, io->ios2_Data, 14); - D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); - - // Call protocol handler - M68kRegisters r; - r.d[0] = *(uint16 *)((uint32)io->ios2_Data + 12); // Packet type - r.d[1] = io->ios2_DataLength - 18; // Remaining packet length (without header, for ReadPacket) (-18 because the CRC is also included) - r.a[0] = (uint32)io->ios2_Data + 14; // Pointer to packet (host address, for ReadPacket) - r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA - r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines - D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", p->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); - Execute68k(p->handler, &r); - - // Resend IORequest - io->ios2_Req.io_Flags = SANA2IOF_RAW; - BeginIO((struct IORequest *)io); - } - D(bug(" EtherIRQ done\n")); -} diff --git a/BasiliskII/src/AmigaOS/extfs_amiga.cpp b/BasiliskII/src/AmigaOS/extfs_amiga.cpp deleted file mode 100644 index 9f157e29..00000000 --- a/BasiliskII/src/AmigaOS/extfs_amiga.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/* - * extfs_amiga.cpp - MacOS file system for access native file system access, AmigaOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#define __USE_SYSBASE -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "extfs.h" -#include "extfs_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -// Default Finder flags -const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited; - - -/* - * Initialization - */ - -void extfs_init(void) -{ -} - - -/* - * Deinitialization - */ - -void extfs_exit(void) -{ -} - - -/* - * Add component to path name - */ - -void add_path_component(char *path, const char *component) -{ - AddPart(path, (char *)component, MAX_PATH_LENGTH); -} - - -/* - * Finder info and resource forks are kept in helper files - * - * Finder info: - * /path/.finf/file - * Resource fork: - * /path/.rsrc/file - * - * The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo - * (16+16 bytes) - */ - -static void make_helper_path(const char *src, char *dest, const char *add, bool only_dir = false) -{ - dest[0] = 0; - - // Get pointer to last component of path - const char *last_part = FilePart((char *)src); - - // Copy everything before - strncpy(dest, src, last_part-src); - dest[last_part-src] = 0; - - // Add additional component - AddPart(dest, (char *)add, MAX_PATH_LENGTH); - - // Add last component - if (!only_dir) - AddPart(dest, (char *)last_part, MAX_PATH_LENGTH); -} - -static int create_helper_dir(const char *path, const char *add) -{ - char helper_dir[MAX_PATH_LENGTH]; - make_helper_path(path, helper_dir, add, true); - if (helper_dir[strlen(helper_dir) - 1] == '/') // Remove trailing "/" - helper_dir[strlen(helper_dir) - 1] = 0; - return mkdir(helper_dir, 0777); -} - -static int open_helper(const char *path, const char *add, int flag) -{ - char helper_path[MAX_PATH_LENGTH]; - make_helper_path(path, helper_path, add); - - if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY) - flag |= O_CREAT; - int fd = open(helper_path, flag, 0666); - if (fd < 0) { - if (errno == ENOENT && (flag & O_CREAT)) { - // One path component was missing, probably the helper - // directory. Try to create it and re-open the file. - int ret = create_helper_dir(path, add); - if (ret < 0) - return ret; - fd = open(helper_path, flag, 0666); - } - } - return fd; -} - -static int open_finf(const char *path, int flag) -{ - return open_helper(path, ".finf/", flag); -} - -static int open_rsrc(const char *path, int flag) -{ - return open_helper(path, ".rsrc/", flag); -} - - -/* - * Get/set finder type/creator for file specified by full path - */ - -struct ext2type { - const char *ext; - uint32 type; - uint32 creator; -}; - -static const ext2type e2t_translation[] = { - {".z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')}, - {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')}, - {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')}, - {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')}, - {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')}, - {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')}, - {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')}, - {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')}, - {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')}, - {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')}, - {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')}, - {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')}, - {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')}, - {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')}, - {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')}, - {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')}, - {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')}, - {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')}, - {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')}, - {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')}, - {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')}, - {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')}, - {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')}, - {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')}, - {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')}, - {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')}, - {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')}, - {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')}, - {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')}, - {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')}, - {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')}, - {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')}, - {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')}, - {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')}, - {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')}, - {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')}, - {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')}, - {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')}, - {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')}, - {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')}, - {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')}, - {NULL, 0, 0} // End marker -}; - -void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Set default finder info - Mac_memset(finfo, 0, SIZEOF_FInfo); - if (fxinfo) - Mac_memset(fxinfo, 0, SIZEOF_FXInfo); - WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS); - WriteMacInt32(finfo + fdLocation, (uint32)-1); - - // Read Finder info file - int fd = open_finf(path, O_RDONLY); - if (fd >= 0) { - ssize_t actual = read(fd, Mac2HostAddr(finfo), SIZEOF_FInfo); - if (fxinfo) - actual += read(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo); - close(fd); - if (actual >= SIZEOF_FInfo) - return; - } - - // No Finder info file, translate file name extension to MacOS type/creator - if (!is_dir) { - int path_len = strlen(path); - for (int i=0; e2t_translation[i].ext; i++) { - int ext_len = strlen(e2t_translation[i].ext); - if (path_len < ext_len) - continue; - if (!strcasecmp(path + path_len - ext_len, e2t_translation[i].ext)) { - WriteMacInt32(finfo + fdType, e2t_translation[i].type); - WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator); - break; - } - } - } -} - -void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Open Finder info file - int fd = open_finf(path, O_RDWR); - if (fd < 0) - return; - - // Write file - write(fd, Mac2HostAddr(finfo), SIZEOF_FInfo); - if (fxinfo) - write(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo); - close(fd); -} - - -/* - * Resource fork emulation functions - */ - -uint32 get_rfork_size(const char *path) -{ - // Open resource file - int fd = open_rsrc(path, O_RDONLY); - if (fd < 0) - return 0; - - // Get size - off_t size = lseek(fd, 0, SEEK_END); - - // Close file and return size - close(fd); - return size < 0 ? 0 : size; -} - -int open_rfork(const char *path, int flag) -{ - return open_rsrc(path, flag); -} - -void close_rfork(const char *path, int fd) -{ - close(fd); -} - - -/* - * Read "length" bytes from file to "buffer", - * returns number of bytes read (or -1 on error) - */ - -ssize_t extfs_read(int fd, void *buffer, size_t length) -{ - return read(fd, buffer, length); -} - - -/* - * Write "length" bytes from "buffer" to file, - * returns number of bytes written (or -1 on error) - */ - -ssize_t extfs_write(int fd, void *buffer, size_t length) -{ - return write(fd, buffer, length); -} - - -/* - * Remove file/directory (and associated helper files), - * returns false on error (and sets errno) - */ - -bool extfs_remove(const char *path) -{ - // Remove helpers first, don't complain if this fails - char helper_path[MAX_PATH_LENGTH]; - make_helper_path(path, helper_path, ".finf/", false); - remove(helper_path); - make_helper_path(path, helper_path, ".rsrc/", false); - remove(helper_path); - - // Now remove file or directory (and helper directories in the directory) - if (remove(path) < 0) { - if (errno == EISDIR || errno == ENOTEMPTY) { - helper_path[0] = 0; - strncpy(helper_path, path, MAX_PATH_LENGTH-1); - add_path_component(helper_path, ".finf"); - rmdir(helper_path); - helper_path[0] = 0; - strncpy(helper_path, path, MAX_PATH_LENGTH-1); - add_path_component(helper_path, ".rsrc"); - rmdir(helper_path); - return rmdir(path) == 0; - } else - return false; - } - return true; -} - - -/* - * Rename/move file/directory (and associated helper files), - * returns false on error (and sets errno) - */ - -bool extfs_rename(const char *old_path, const char *new_path) -{ - // Rename helpers first, don't complain if this fails - char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH]; - make_helper_path(old_path, old_helper_path, ".finf/", false); - make_helper_path(new_path, new_helper_path, ".finf/", false); - create_helper_dir(new_path, ".finf/"); - rename(old_helper_path, new_helper_path); - make_helper_path(old_path, old_helper_path, ".rsrc/", false); - make_helper_path(new_path, new_helper_path, ".rsrc/", false); - create_helper_dir(new_path, ".rsrc/"); - rename(old_helper_path, new_helper_path); - - // Now rename file - return rename(old_path, new_path) == 0; -} - - -/* - * ftruncate() is missing from libnix - */ - -extern unsigned long *__stdfiledes; - -int ftruncate(int fd, off_t size) -{ - if (SetFileSize(__stdfiledes[fd], size, OFFSET_BEGINNING) < 0) - return -1; - else - return 0; -} diff --git a/BasiliskII/src/AmigaOS/main_amiga.cpp b/BasiliskII/src/AmigaOS/main_amiga.cpp deleted file mode 100644 index 90ac6db2..00000000 --- a/BasiliskII/src/AmigaOS/main_amiga.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/* - * main_amiga.cpp - Startup code for AmigaOS - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "xpram.h" -#include "timer.h" -#include "sony.h" -#include "disk.h" -#include "cdrom.h" -#include "scsi.h" -#include "audio.h" -#include "video.h" -#include "serial.h" -#include "ether.h" -#include "clip.h" -#include "emul_op.h" -#include "rom_patches.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "sys.h" -#include "user_strings.h" -#include "version.h" - -#define DEBUG 0 -#include "debug.h" - - -// Options for libnix -unsigned long __stack = 0x4000; // Stack requirement -int __nocommandline = 1; // Disable command line parsing - - -// Constants -static const char ROM_FILE_NAME[] = "ROM"; -static const char __ver[] = "$VER: " VERSION_STRING " " __DATE__; -static const int SCRATCH_MEM_SIZE = 65536; - - -// RAM and ROM pointers -uint32 RAMBaseMac; // RAM base (Mac address space) -uint8 *RAMBaseHost; // RAM base (host address space) -uint32 RAMSize; // Size of RAM -uint32 ROMBaseMac; // ROM base (Mac address space) -uint8 *ROMBaseHost; // ROM base (host address space) -uint32 ROMSize; // Size of ROM - - -// CPU and FPU type, addressing mode -int CPUType; -bool CPUIs68060; -int FPUType; -bool TwentyFourBitAddressing; - - -// Global variables -extern ExecBase *SysBase; -struct Library *GfxBase = NULL; -struct IntuitionBase *IntuitionBase = NULL; -struct Library *GadToolsBase = NULL; -struct Library *IFFParseBase = NULL; -struct Library *AslBase = NULL; -struct Library *P96Base = NULL; -struct Library *CyberGfxBase = NULL; -struct Library *TimerBase = NULL; -struct Library *AHIBase = NULL; -struct Library *DiskBase = NULL; - -struct Task *MainTask; // Our task -uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes -APTR OldTrapHandler = NULL; // Old trap handler -APTR OldExceptionHandler = NULL; // Old exception handler -BYTE IRQSig = -1; // "Interrupt" signal number -ULONG IRQSigMask = 0; // "Interrupt" signal mask - -static struct timerequest *timereq = NULL; // IORequest for timer - -static struct MsgPort *ahi_port = NULL; // Port for AHI -static struct AHIRequest *ahi_io = NULL; // IORequest for AHI - -static struct Process *xpram_proc = NULL; // XPRAM watchdog -static volatile bool xpram_proc_active = true; // Flag for quitting the XPRAM watchdog - -static struct Process *tick_proc = NULL; // 60Hz process -static volatile bool tick_proc_active = true; // Flag for quitting the 60Hz process - -static bool stack_swapped = false; // Stack swapping -static StackSwapStruct stack_swap; - - -// Assembly functions -struct trap_regs; -extern "C" void AtomicAnd(uint32 *p, uint32 val); -extern "C" void AtomicOr(uint32 *p, uint32 val); -extern "C" void MoveVBR(void); -extern "C" void DisableSuperBypass(void); -extern "C" void TrapHandlerAsm(void); -extern "C" void ExceptionHandlerAsm(void); -extern "C" void IllInstrHandler(trap_regs *regs); -extern "C" void PrivViolHandler(trap_regs *regs); -extern "C" void quit_emulator(void); -extern "C" void AsmTriggerNMI(void); -uint16 EmulatedSR; // Emulated SR (supervisor bit and interrupt mask) - - -// Prototypes -static void jump_to_rom(void); -static void xpram_func(void); -static void tick_func(void); - - -/* - * Main program - */ - -int main(int argc, char **argv) -{ - // Initialize variables - RAMBaseHost = NULL; - ROMBaseHost = NULL; - MainTask = FindTask(NULL); - struct DateStamp ds; - DateStamp(&ds); - srand(ds.ds_Tick); - - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - - // Open libraries - GfxBase = OpenLibrary((UBYTE *) "graphics.library", 39); - if (GfxBase == NULL) { - printf("Cannot open graphics.library V39.\n"); - exit(1); - } - IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *) "intuition.library", 39); - if (IntuitionBase == NULL) { - printf("Cannot open intuition.library V39.\n"); - CloseLibrary(GfxBase); - exit(1); - } - DiskBase = (struct Library *)OpenResource((UBYTE *) "disk.resource"); - if (DiskBase == NULL) - QuitEmulator(); - GadToolsBase = OpenLibrary((UBYTE *) "gadtools.library", 39); - if (GadToolsBase == NULL) { - ErrorAlert(STR_NO_GADTOOLS_LIB_ERR); - QuitEmulator(); - } - IFFParseBase = OpenLibrary((UBYTE *) "iffparse.library", 39); - if (IFFParseBase == NULL) { - ErrorAlert(STR_NO_IFFPARSE_LIB_ERR); - QuitEmulator(); - } - AslBase = OpenLibrary((UBYTE *) "asl.library", 36); - if (AslBase == NULL) { - ErrorAlert(STR_NO_ASL_LIB_ERR); - QuitEmulator(); - } - - if (FindTask((UBYTE *) "« Enforcer »")) { - ErrorAlert(STR_ENFORCER_RUNNING_ERR); - QuitEmulator(); - } - - // These two can fail (the respective gfx support won't be available, then) - P96Base = OpenLibrary((UBYTE *) "Picasso96API.library", 2); - CyberGfxBase = OpenLibrary((UBYTE *) "cybergraphics.library", 2); - - // Read preferences - PrefsInit(NULL, argc, argv); - - // Open AHI - ahi_port = CreateMsgPort(); - if (ahi_port) { - ahi_io = (struct AHIRequest *)CreateIORequest(ahi_port, sizeof(struct AHIRequest)); - if (ahi_io) { - ahi_io->ahir_Version = 2; - if (OpenDevice((UBYTE *) AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, 0) == 0) { - AHIBase = (struct Library *)ahi_io->ahir_Std.io_Device; - } - } - } - - // Init system routines - SysInit(); - - // Show preferences editor - if (!PrefsFindBool("nogui")) - if (!PrefsEditor()) - QuitEmulator(); - - // Check start of Chip memory (because we need access to 0x0000..0x2000) - if ((uint32)FindName(&SysBase->MemList, (UBYTE *) "chip memory") < 0x2000) { - ErrorAlert(STR_NO_PREPARE_EMUL_ERR); - QuitEmulator(); - } - - // Open timer.device - timereq = (struct timerequest *)AllocVec(sizeof(timerequest), MEMF_PUBLIC | MEMF_CLEAR); - if (timereq == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } - if (OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timereq, 0)) { - ErrorAlert(STR_NO_TIMER_DEV_ERR); - QuitEmulator(); - } - TimerBase = (struct Library *)timereq->tr_node.io_Device; - - // Allocate scratch memory - ScratchMem = (uint8 *)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC); - if (ScratchMem == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } - ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block - - // Create area for Mac RAM and ROM (ROM must be higher in memory, - // so we allocate one big chunk and put the ROM at the top of it) - RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary - if (RAMSize < 1024*1024) { - WarningAlert(GetString(STR_SMALL_RAM_WARN)); - RAMSize = 1024*1024; - } - RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC); - if (RAMBaseHost == NULL) { - uint32 newRAMSize = AvailMem(MEMF_LARGEST) - 0x100000; - char xText[120]; - - sprintf(xText, GetString(STR_NOT_ENOUGH_MEM_WARN), RAMSize, newRAMSize); - - if (ChoiceAlert(xText, "Use", "Quit") != 1) - QuitEmulator(); - - RAMSize = newRAMSize; - RAMBaseHost = (uint8 *)AllocVec(RAMSize - 0x100000, MEMF_PUBLIC); - if (RAMBaseHost == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } - } - RAMBaseMac = (uint32)RAMBaseHost; - D(bug("Mac RAM starts at %08lx\n", RAMBaseHost)); - ROMBaseHost = RAMBaseHost + RAMSize; - ROMBaseMac = (uint32)ROMBaseHost; - D(bug("Mac ROM starts at %08lx\n", ROMBaseHost)); - - // Get rom file path from preferences - const char *rom_path = PrefsFindString("rom"); - - // Load Mac ROM - BPTR rom_fh = Open(rom_path ? (char *)rom_path : (char *)ROM_FILE_NAME, MODE_OLDFILE); - if (rom_fh == 0) { - ErrorAlert(STR_NO_ROM_FILE_ERR); - QuitEmulator(); - } - printf(GetString(STR_READING_ROM_FILE)); - Seek(rom_fh, 0, OFFSET_END); - ROMSize = Seek(rom_fh, 0, OFFSET_CURRENT); - if (ROMSize != 512*1024 && ROMSize != 1024*1024) { - ErrorAlert(STR_ROM_SIZE_ERR); - Close(rom_fh); - QuitEmulator(); - } - Seek(rom_fh, 0, OFFSET_BEGINNING); - if (Read(rom_fh, ROMBaseHost, ROMSize) != ROMSize) { - ErrorAlert(STR_ROM_FILE_READ_ERR); - Close(rom_fh); - QuitEmulator(); - } - - // Set CPU and FPU type - UWORD attn = SysBase->AttnFlags; - CPUType = attn & AFF_68040 ? 4 : (attn & AFF_68030 ? 3 : 2); - CPUIs68060 = attn & AFF_68060; - FPUType = attn & AFF_68881 ? 1 : 0; - - // Initialize everything - if (!InitAll(NULL)) - QuitEmulator(); - - // Move VBR away from 0 if neccessary - MoveVBR(); - - // On 68060, disable Super Bypass mode because of a CPU bug that is triggered by MacOS 8 - if (CPUIs68060) - DisableSuperBypass(); - - memset((UBYTE *) 8, 0, 0x2000-8); - - // Install trap handler - EmulatedSR = 0x2700; - OldTrapHandler = MainTask->tc_TrapCode; - MainTask->tc_TrapCode = (APTR)TrapHandlerAsm; - - // Allocate signal for interrupt emulation and install exception handler - IRQSig = AllocSignal(-1); - IRQSigMask = 1 << IRQSig; - OldExceptionHandler = MainTask->tc_ExceptCode; - MainTask->tc_ExceptCode = (APTR)ExceptionHandlerAsm; - SetExcept(SIGBREAKF_CTRL_C | IRQSigMask, SIGBREAKF_CTRL_C | IRQSigMask); - - // Start XPRAM watchdog process - xpram_proc = CreateNewProcTags( - NP_Entry, (ULONG)xpram_func, - NP_Name, (ULONG)"Basilisk II XPRAM Watchdog", - NP_Priority, 0, - TAG_END - ); - - // Start 60Hz process - tick_proc = CreateNewProcTags( - NP_Entry, (ULONG)tick_func, - NP_Name, (ULONG)"Basilisk II 60Hz", - NP_Priority, 5, - TAG_END - ); - - // Set task priority to -1 so we don't use all processing time - SetTaskPri(MainTask, -1); - - WriteMacInt32(0xbff, 0); // MacsBugFlags - - // Swap stack to Mac RAM area - stack_swap.stk_Lower = RAMBaseHost; - stack_swap.stk_Upper = (ULONG)RAMBaseHost + RAMSize; - stack_swap.stk_Pointer = RAMBaseHost + 0x8000; - StackSwap(&stack_swap); - stack_swapped = true; - - // Jump to ROM boot routine - Start680x0(); - - QuitEmulator(); - return 0; -} - -void Start680x0(void) -{ - typedef void (*rom_func)(void); - rom_func fp = (rom_func)(ROMBaseHost + 0x2a); - fp(); -} - - -/* - * Quit emulator (__saveds because it might be called from an exception) - */ - -// Assembly entry point -void __saveds quit_emulator(void) -{ - QuitEmulator(); -} - -void QuitEmulator(void) -{ - // Stop 60Hz process - if (tick_proc) { - SetSignal(0, SIGF_SINGLE); - tick_proc_active = false; - Wait(SIGF_SINGLE); - } - - // Stop XPRAM watchdog process - if (xpram_proc) { - SetSignal(0, SIGF_SINGLE); - xpram_proc_active = false; - Wait(SIGF_SINGLE); - } - - // Restore stack - if (stack_swapped) { - stack_swapped = false; - StackSwap(&stack_swap); - } - - // Remove exception handler - if (IRQSig >= 0) { - SetExcept(0, SIGBREAKF_CTRL_C | IRQSigMask); - MainTask->tc_ExceptCode = OldExceptionHandler; - FreeSignal(IRQSig); - } - - // Remove trap handler - MainTask->tc_TrapCode = OldTrapHandler; - - // Deinitialize everything - ExitAll(); - - // Delete RAM/ROM area - if (RAMBaseHost) - FreeVec(RAMBaseHost); - - // Delete scratch memory area - if (ScratchMem) - FreeMem((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE); - - // Close timer.device - if (TimerBase) - CloseDevice((struct IORequest *)timereq); - if (timereq) - FreeVec(timereq); - - // Exit system routines - SysExit(); - - // Close AHI - if (AHIBase) - CloseDevice((struct IORequest *)ahi_io); - if (ahi_io) - DeleteIORequest((struct IORequest *)ahi_io); - if (ahi_port) - DeleteMsgPort(ahi_port); - - // Exit preferences - PrefsExit(); - - // Close libraries - if (CyberGfxBase) - CloseLibrary(CyberGfxBase); - if (P96Base) - CloseLibrary(P96Base); - if (AslBase) - CloseLibrary(AslBase); - if (IFFParseBase) - CloseLibrary(IFFParseBase); - if (GadToolsBase) - CloseLibrary(GadToolsBase); - if (IntuitionBase) - CloseLibrary((struct Library *)IntuitionBase); - if (GfxBase) - CloseLibrary(GfxBase); - - exit(0); -} - - -/* - * Code was patched, flush caches if neccessary (i.e. when using a real 680x0 - * or a dynamically recompiling emulator) - */ - -void FlushCodeCache(void *start, uint32 size) -{ - CacheClearE(start, size, CACRF_ClearI | CACRF_ClearD); -} - - -/* - * Mutexes - */ - -struct B2_mutex { - int dummy; //!! -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - - -/* - * Interrupt flags (must be handled atomically!) - */ - -uint32 InterruptFlags; - -void SetInterruptFlag(uint32 flag) -{ - AtomicOr(&InterruptFlags, flag); -} - -void ClearInterruptFlag(uint32 flag) -{ - AtomicAnd(&InterruptFlags, ~flag); -} - -void TriggerInterrupt(void) -{ - Signal(MainTask, IRQSigMask); -} - -void TriggerNMI(void) -{ - AsmTriggerNMI(); -} - - -/* - * 60Hz thread (really 60.15Hz) - */ - -static __saveds void tick_func(void) -{ - int tick_counter = 0; - struct MsgPort *timer_port = NULL; - struct timerequest *timer_io = NULL; - ULONG timer_mask = 0; - - // Start 60Hz timer - timer_port = CreateMsgPort(); - if (timer_port) { - timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest)); - if (timer_io) { - if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) { - timer_mask = 1 << timer_port->mp_SigBit; - timer_io->tr_node.io_Command = TR_ADDREQUEST; - timer_io->tr_time.tv_secs = 0; - timer_io->tr_time.tv_micro = 16625; - SendIO((struct IORequest *)timer_io); - } - } - } - - while (tick_proc_active) { - - // Wait for timer tick - Wait(timer_mask); - - // Restart timer - timer_io->tr_node.io_Command = TR_ADDREQUEST; - timer_io->tr_time.tv_secs = 0; - timer_io->tr_time.tv_micro = 16625; - SendIO((struct IORequest *)timer_io); - - // Pseudo Mac 1Hz interrupt, update local time - if (++tick_counter > 60) { - tick_counter = 0; - WriteMacInt32(0x20c, TimerDateTime()); - SetInterruptFlag(INTFLAG_1HZ); - TriggerInterrupt(); - } - - // Trigger 60Hz interrupt - SetInterruptFlag(INTFLAG_60HZ); - TriggerInterrupt(); - } - - // Stop timer - if (timer_io) { - if (!CheckIO((struct IORequest *)timer_io)) - AbortIO((struct IORequest *)timer_io); - WaitIO((struct IORequest *)timer_io); - CloseDevice((struct IORequest *)timer_io); - DeleteIORequest(timer_io); - } - if (timer_port) - DeleteMsgPort(timer_port); - - // Main task asked for termination, send signal - Forbid(); - Signal(MainTask, SIGF_SINGLE); -} - - -/* - * XPRAM watchdog thread (saves XPRAM every minute) - */ - -static __saveds void xpram_func(void) -{ - uint8 last_xpram[XPRAM_SIZE]; - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - - while (xpram_proc_active) { - for (int i=0; i<60 && xpram_proc_active; i++) - Delay(50); // Only wait 1 second so we quit promptly when xpram_proc_active becomes false - if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - SaveXPRAM(); - } - } - - // Main task asked for termination, send signal - Forbid(); - Signal(MainTask, SIGF_SINGLE); -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - if (PrefsFindBool("nogui")) { - printf(GetString(STR_SHELL_ERROR_PREFIX), text); - return; - } - EasyStruct req; - req.es_StructSize = sizeof(EasyStruct); - req.es_Flags = 0; - req.es_Title = (UBYTE *)GetString(STR_ERROR_ALERT_TITLE); - req.es_TextFormat = (UBYTE *)GetString(STR_GUI_ERROR_PREFIX); - req.es_GadgetFormat = (UBYTE *)GetString(STR_QUIT_BUTTON); - EasyRequest(NULL, &req, NULL, (ULONG)text); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - if (PrefsFindBool("nogui")) { - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return; - } - EasyStruct req; - req.es_StructSize = sizeof(EasyStruct); - req.es_Flags = 0; - req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE); - req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX); - req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON); - EasyRequest(NULL, &req, NULL, (ULONG)text); -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - char str[256]; - sprintf(str, "%s|%s", pos, neg); - EasyStruct req; - req.es_StructSize = sizeof(EasyStruct); - req.es_Flags = 0; - req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE); - req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX); - req.es_GadgetFormat = (UBYTE *)str; - return EasyRequest(NULL, &req, NULL, (ULONG)text); -} - - -/* - * Illegal Instruction and Privilege Violation trap handlers - */ - -struct trap_regs { // This must match the layout of M68kRegisters - uint32 d[8]; - uint32 a[8]; - uint16 sr; - uint32 pc; -}; - -void __saveds IllInstrHandler(trap_regs *r) -{ -// D(bug("IllInstrHandler/%ld\n", __LINE__)); - - uint16 opcode = *(uint16 *)(r->pc); - if ((opcode & 0xff00) != 0x7100) { - printf("Illegal Instruction %04x at %08lx\n", *(uint16 *)(r->pc), r->pc); - printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n" - "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n" - "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n" - "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n" - "sr %04x\n", - r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7], - r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7], - r->sr); - QuitEmulator(); - } else { - // Disable interrupts - uint16 sr = EmulatedSR; - EmulatedSR |= 0x0700; - - // Call opcode routine - EmulOp(opcode, (M68kRegisters *)r); - r->pc += 2; - - // Restore interrupts - EmulatedSR = sr; - if ((EmulatedSR & 0x0700) == 0 && InterruptFlags) - Signal(MainTask, IRQSigMask); - } -} - -void __saveds PrivViolHandler(trap_regs *r) -{ - printf("Privileged instruction %04x %04x at %08lx\n", *(uint16 *)(r->pc), *(uint16 *)(r->pc + 2), r->pc); - printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n" - "d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n" - "a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n" - "a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n" - "sr %04x\n", - r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7], - r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7], - r->sr); - QuitEmulator(); -} diff --git a/BasiliskII/src/AmigaOS/prefs_amiga.cpp b/BasiliskII/src/AmigaOS/prefs_amiga.cpp deleted file mode 100644 index 3d71c1de..00000000 --- a/BasiliskII/src/AmigaOS/prefs_amiga.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * prefs_amiga.cpp - Preferences handling, AmigaOS specifix stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "sysdeps.h" -#include "prefs.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { - {"sound", TYPE_STRING, false, "sound output mode description"}, - {"scsimemtype", TYPE_INT32, false, "SCSI buffer memory type"}, - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Prefs file name -const char PREFS_FILE_NAME[] = "ENV:BasiliskII_prefs"; -const char PREFS_FILE_NAME_ARC[] = "ENVARC:BasiliskII_prefs"; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(void) -{ - // Read preferences from settings file - FILE *f = fopen(PREFS_FILE_NAME, "r"); - if (f != NULL) { - - // Prefs file found, load settings - LoadPrefsFromStream(f); - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - } -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = fopen(PREFS_FILE_NAME, "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } - if ((f = fopen(PREFS_FILE_NAME_ARC, "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsReplaceString("extfs", "WORK:"); - PrefsAddInt32("scsimemtype", 0); -} diff --git a/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp b/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp deleted file mode 100644 index f1956906..00000000 --- a/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp +++ /dev/null @@ -1,1735 +0,0 @@ -/* - * prefs_editor_amiga.cpp - Preferences editor, AmigaOS implementation (using gtlayout.library) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "xpram.h" -#include "cdrom.h" -#include "user_strings.h" -#include "version.h" -#include "prefs.h" -#include "prefs_editor.h" - - -// Gadget/menu IDs -const int MSG_OK = 0x0100; // "Start" button -const int MSG_CANCEL = 0x0101; // "Quit" button -const int MSG_ABOUT = 0x0102; // "About..." menu item -const int MSG_ZAP_PRAM = 0x0103; // "Zap PRAM" menu item - -const int GAD_PAGEGROUP = 0x0200; - -const int GAD_DISK_LIST = 0x0300; // "Volumes" pane -const int GAD_ADD_VOLUME = 0x0301; -const int GAD_EDIT_VOLUME = 0x0302; -const int GAD_REMOVE_VOLUME = 0x0303; -const int GAD_CDROM_DEVICE = 0x0304; -const int GAD_CDROM_UNIT = 0x0305; -const int GAD_BOOTDRIVER = 0x0306; -const int GAD_NOCDROM = 0x0307; -const int GAD_EXTFS = 0x0308; - -const int GAD_VOLUME_READONLY = 0x0310; // "Add/Edit Volume" window -const int GAD_VOLUME_TYPE = 0x0311; -const int GAD_VOLUME_FILE = 0x0312; -const int GAD_VOLUME_DEVICE = 0x0313; -const int GAD_VOLUME_UNIT = 0x0314; -const int GAD_VOLUME_OPENFLAGS = 0x0315; -const int GAD_VOLUME_STARTBLOCK = 0x0316; -const int GAD_VOLUME_SIZE = 0x0317; -const int GAD_VOLUME_BLOCKSIZE = 0x0318; -const int GAD_VOLUME_PAGEGROUP = 0x0319; - -const int GAD_SCSI0_DEVICE = 0x0400; // "SCSI" pane -const int GAD_SCSI1_DEVICE = 0x0401; -const int GAD_SCSI2_DEVICE = 0x0402; -const int GAD_SCSI3_DEVICE = 0x0403; -const int GAD_SCSI4_DEVICE = 0x0404; -const int GAD_SCSI5_DEVICE = 0x0405; -const int GAD_SCSI6_DEVICE = 0x0406; -const int GAD_SCSI0_UNIT = 0x0410; -const int GAD_SCSI1_UNIT = 0x0411; -const int GAD_SCSI2_UNIT = 0x0412; -const int GAD_SCSI3_UNIT = 0x0413; -const int GAD_SCSI4_UNIT = 0x0414; -const int GAD_SCSI5_UNIT = 0x0415; -const int GAD_SCSI6_UNIT = 0x0416; -const int GAD_SCSI_MEMTYPE = 0x0420; - -const int GAD_VIDEO_TYPE = 0x0500; // "Graphics/Sound" pane -const int GAD_DISPLAY_X = 0x0501; -const int GAD_DISPLAY_Y = 0x0502; -const int GAD_FRAMESKIP = 0x0503; -const int GAD_SCREEN_MODE = 0x0504; -const int GAD_AHI_MODE = 0x0505; -const int GAD_NOSOUND = 0x0506; - -const int GAD_SERIALA_DEVICE = 0x0600; // "Serial/Network" pane -const int GAD_SERIALA_UNIT = 0x0601; -const int GAD_SERIALA_ISPAR = 0x0602; -const int GAD_SERIALB_DEVICE = 0x0603; -const int GAD_SERIALB_UNIT = 0x0604; -const int GAD_SERIALB_ISPAR = 0x0605; -const int GAD_ETHER_DEVICE = 0x0606; -const int GAD_ETHER_UNIT = 0x00607; - -const int GAD_RAMSIZE = 0x0700; // "Memory/Misc" pane -const int GAD_MODELID = 0x0701; -const int GAD_ROM_FILE = 0x0702; - - -// Global variables -struct Library *GTLayoutBase = NULL; -static struct FileRequester *dev_request = NULL, *file_request = NULL; - -// gtlayout.library macros -#define VGROUP LT_New(h, LA_Type, VERTICAL_KIND, TAG_END) -#define HGROUP LT_New(h, LA_Type, HORIZONTAL_KIND, TAG_END) -#define ENDGROUP LT_EndGroup(h) - -// Prototypes -static void create_volumes_pane(struct LayoutHandle *h); -static void create_scsi_pane(struct LayoutHandle *h); -static void create_graphics_pane(struct LayoutHandle *h); -static void create_serial_pane(struct LayoutHandle *h); -static void create_memory_pane(struct LayoutHandle *h); -static void add_edit_volume(struct LayoutHandle *h, bool adding); -static void remove_volume(struct LayoutHandle *h); -static void ghost_volumes_gadgets(struct LayoutHandle *h); -static void ghost_graphics_gadgets(struct LayoutHandle *h); -static void screen_mode_req(struct Window *win, struct LayoutHandle *h); -static void ahi_mode_req(struct Window *win, struct LayoutHandle *h); -static void read_settings(struct LayoutHandle *h); - - -/* - * Locale hook - returns string for given ID - */ - -static __saveds __attribute__((regparm(3))) const char *locale_hook_func(struct Hook *hook /*a0*/, void *id /*a1*/, struct LayoutHandle *h /*a2*/) -{ - return GetString((uint32)id); -} - -struct Hook locale_hook = {{NULL, NULL}, (HOOKFUNC)locale_hook_func, NULL, NULL}; - - -/* - * Show preferences editor - * Returns true when user clicked on "Start", false otherwise - */ - -bool PrefsEditor(void) -{ - bool retval = true, done = false; - struct LayoutHandle *h = NULL; - struct Window *win = NULL; - struct Menu *menu = NULL; - - // Pane tabs - static const LONG labels[] = { - STR_VOLUMES_PANE_TITLE, - STR_SCSI_PANE_TITLE, - STR_GRAPHICS_SOUND_PANE_TITLE, - STR_SERIAL_NETWORK_PANE_TITLE, - STR_MEMORY_MISC_PANE_TITLE, - -1 - }; - - // Open gtlayout.library - GTLayoutBase = (struct Library *)OpenLibrary("gtlayout.library", 39); - if (GTLayoutBase == NULL) { - WarningAlert(GetString(STR_NO_GTLAYOUT_LIB_WARN)); - return true; - } - - // Create layout handle - h = LT_CreateHandleTags(NULL, - LAHN_AutoActivate, FALSE, - LAHN_LocaleHook, (ULONG)&locale_hook, - TAG_END - ); - if (h == NULL) - goto quit; - - // Create menus - menu = LT_NewMenuTags( - LAMN_LayoutHandle, (ULONG)h, - LAMN_TitleID, STR_PREFS_MENU, - LAMN_ItemID, STR_PREFS_ITEM_ABOUT, - LAMN_UserData, MSG_ABOUT, - LAMN_ItemText, (ULONG)NM_BARLABEL, - LAMN_ItemID, STR_PREFS_ITEM_START, - LAMN_UserData, MSG_OK, - LAMN_ItemID, STR_PREFS_ITEM_ZAP_PRAM, - LAMN_UserData, MSG_ZAP_PRAM, - LAMN_ItemText, (ULONG)NM_BARLABEL, - LAMN_ItemID, STR_PREFS_ITEM_QUIT, - LAMN_UserData, MSG_CANCEL, - LAMN_KeyText, (ULONG)"Q", - TAG_END - ); - - // Create window contents - VGROUP; - VGROUP; - LT_New(h, LA_Type, TAB_KIND, - LATB_LabelTable, (ULONG)labels, - LATB_AutoPageID, GAD_PAGEGROUP, - LATB_FullWidth, TRUE, - TAG_END - ); - ENDGROUP; - - // Panes - LT_New(h, LA_Type, VERTICAL_KIND, - LA_ID, GAD_PAGEGROUP, - LAGR_ActivePage, 0, - TAG_END - ); - create_volumes_pane(h); - create_scsi_pane(h); - create_graphics_pane(h); - create_serial_pane(h); - create_memory_pane(h); - ENDGROUP; - - // Separator between tabs and buttons - VGROUP; - LT_New(h, LA_Type, XBAR_KIND, - LAXB_FullSize, TRUE, - TAG_END - ); - ENDGROUP; - - // "Start" and "Quit" buttons - LT_New(h, LA_Type, HORIZONTAL_KIND, - LAGR_SameSize, TRUE, - LAGR_Spread, TRUE, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_START_BUTTON, - LA_ID, MSG_OK, - LABT_ReturnKey, TRUE, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_QUIT_BUTTON, - LA_ID, MSG_CANCEL, - LABT_EscKey, TRUE, - TAG_END - ); - ENDGROUP; - ENDGROUP; - - // Open window - win = LT_Build(h, - LAWN_TitleID, STR_PREFS_TITLE, - LAWN_Menu, (ULONG)menu, - LAWN_IDCMP, IDCMP_CLOSEWINDOW, - LAWN_BelowMouse, TRUE, - LAWN_SmartZoom, TRUE, - WA_SimpleRefresh, TRUE, - WA_Activate, TRUE, - WA_CloseGadget, TRUE, - WA_DepthGadget, TRUE, - WA_DragBar, TRUE, - TAG_END - ); - if (win == NULL) - goto quit; - - // Create file requesters - dev_request = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest, - ASLFR_DoPatterns, TRUE, - ASLFR_RejectIcons, TRUE, - ASLFR_InitialDrawer, (ULONG)"DEVS:", - ASLFR_InitialPattern, (ULONG)"#?.device", - TAG_END - ); - file_request = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest, - ASLFR_DoPatterns, TRUE, - ASLFR_RejectIcons, TRUE, - ASLFR_InitialPattern, (ULONG)"#?", - TAG_END - ); - - // Event loop - do { - struct IntuiMessage *msg; - - // Wait for message - WaitPort(win->UserPort); - - // Get pending messages - while (msg = LT_GetIMsg(h)) { - - // Get data from message and reply - ULONG cl = msg->Class; - UWORD code = msg->Code; - struct Gadget *gad = (struct Gadget *)msg->IAddress; - LT_ReplyIMsg(msg); - - // Handle message according to class - switch (cl) { - case IDCMP_CLOSEWINDOW: - retval = false; - done = true; - break; - - case IDCMP_GADGETUP: - switch (gad->GadgetID) { - case MSG_OK: - read_settings(h); - SavePrefs(); - retval = true; - done = true; - break; - - case MSG_CANCEL: - retval = false; - done = true; - break; - - case GAD_DISK_LIST: - ghost_volumes_gadgets(h); - break; - - case GAD_ADD_VOLUME: - LT_LockWindow(win); - add_edit_volume(h, true); - LT_UnlockWindow(win); - break; - - case GAD_EDIT_VOLUME: - LT_LockWindow(win); - add_edit_volume(h, false); - LT_UnlockWindow(win); - break; - - case GAD_REMOVE_VOLUME: - remove_volume(h); - break; - - case GAD_BOOTDRIVER: - switch (code) { - case 0: - PrefsReplaceInt32("bootdriver", 0); - break; - case 1: - PrefsReplaceInt32("bootdriver", CDROMRefNum); - break; - } - break; - - case GAD_SCSI_MEMTYPE: - PrefsReplaceInt32("scsimemtype", code); - break; - - case GAD_VIDEO_TYPE: - ghost_graphics_gadgets(h); - break; - - case GAD_FRAMESKIP: - switch (code) { - case 0: - PrefsReplaceInt32("frameskip", 12); - break; - case 1: - PrefsReplaceInt32("frameskip", 8); - break; - case 2: - PrefsReplaceInt32("frameskip", 6); - break; - case 3: - PrefsReplaceInt32("frameskip", 4); - break; - case 4: - PrefsReplaceInt32("frameskip", 2); - break; - case 5: - PrefsReplaceInt32("frameskip", 1); - break; - } - break; - - case GAD_MODELID: - switch (code) { - case 0: - PrefsReplaceInt32("modelid", 5); - break; - case 1: - PrefsReplaceInt32("modelid", 14); - break; - } - break; - } - break; - - case IDCMP_IDCMPUPDATE: - switch (gad->GadgetID) { - case GAD_DISK_LIST: // Double-click on volumes list = edit volume - LT_LockWindow(win); - add_edit_volume(h, false); - LT_UnlockWindow(win); - break; - - case GAD_SCREEN_MODE: - screen_mode_req(win, h); - break; - - case GAD_AHI_MODE: - ahi_mode_req(win, h); - break; - - case GAD_CDROM_DEVICE: - case GAD_SCSI0_DEVICE: - case GAD_SCSI1_DEVICE: - case GAD_SCSI2_DEVICE: - case GAD_SCSI3_DEVICE: - case GAD_SCSI4_DEVICE: - case GAD_SCSI5_DEVICE: - case GAD_SCSI6_DEVICE: - case GAD_SERIALA_DEVICE: - case GAD_SERIALB_DEVICE: - if (dev_request) { - LT_LockWindow(win); - BOOL result = AslRequestTags(dev_request, - ASLFR_Window, (ULONG)win, - ASLFR_InitialDrawer, (ULONG) "Devs:", - TAG_END); - LT_UnlockWindow(win); - if (result) { - char *str; - GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END); - strncpy(str, dev_request->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that. - str[255] = 0; - LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END); - } - } - break; - - case GAD_ETHER_DEVICE: - if (dev_request) { - LT_LockWindow(win); - BOOL result = AslRequestTags(dev_request, - ASLFR_Window, (ULONG)win, - ASLFR_InitialDrawer, (ULONG) "Devs:Networks", - TAG_END); - LT_UnlockWindow(win); - if (result) { - char *str; - GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END); - strncpy(str, dev_request->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that. - str[255] = 0; - LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END); - } - } - break; - - case GAD_ROM_FILE: - if (file_request) { - LT_LockWindow(win); - BOOL result = AslRequestTags(file_request, ASLFR_Window, (ULONG)win, TAG_END); - LT_UnlockWindow(win); - if (result) { - char *str; - GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END); - strncpy(str, file_request->rf_Dir, 255); - str[255] = 0; - AddPart(str, file_request->rf_File, 255); - LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END); - } - } - break; - } - break; - - case IDCMP_MENUPICK: - while (code != MENUNULL) { - struct MenuItem *item = ItemAddress(menu, code); - if (item == NULL) - break; - switch ((ULONG)GTMENUITEM_USERDATA(item)) { - case MSG_OK: - read_settings(h); - SavePrefs(); - retval = true; - done = true; - break; - - case MSG_CANCEL: - retval = false; - done = true; - break; - - case MSG_ABOUT: { - char str[256]; - sprintf(str, GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - strncat(str, "\n", 255); - strncat(str, GetString(STR_ABOUT_TEXT2), 255); - - EasyStruct req; - req.es_StructSize = sizeof(EasyStruct); - req.es_Flags = 0; - req.es_Title = (UBYTE *)GetString(STR_ABOUT_TITLE); - req.es_TextFormat = (UBYTE *)str; - req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON); - LT_LockWindow(win); - EasyRequest(win, &req, NULL); - LT_UnlockWindow(win); - break; - } - - case MSG_ZAP_PRAM: - ZapPRAM(); - break; - } - code = item->NextSelect; - } - break; - } - } - } while (!done); - -quit: - // Free requesters - FreeAslRequest(dev_request); - FreeAslRequest(file_request); - - // Delete Menus - LT_DisposeMenu(menu); - - // Delete handle - LT_DeleteHandle(h); - - // Close gtlayout.library - CloseLibrary(GTLayoutBase); - return retval; -} - - -/* - * "Volumes" pane - */ - -static struct List disk_list; -static char cdrom_name[256], extfs_name[256]; -static ULONG cdrom_unit, cdrom_flags, cdrom_start, cdrom_size, cdrom_bsize; -static BYTE bootdriver_num, nocdrom; - -// Read volumes preferences -static void parse_volumes_prefs(void) -{ - NewList(&disk_list); - const char *str; - for (int i=0; (str = PrefsFindString("disk", i)) != NULL; i++) { - struct Node *item = (struct Node *)AllocMem(sizeof(struct Node), MEMF_CLEAR); - item->ln_Name = (char *)str; - AddTail(&disk_list, item); - } - - cdrom_name[0] = 0; - cdrom_unit = 0; cdrom_flags = 0; cdrom_start = 0; cdrom_size = 0; cdrom_bsize = 2048; - - str = PrefsFindString("cdrom"); - if (str) - sscanf(str, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", cdrom_name, &cdrom_unit, &cdrom_flags, &cdrom_start, &cdrom_size, &cdrom_bsize); - - bootdriver_num = 0; - - int bootdriver = PrefsFindInt32("bootdriver"); - switch (bootdriver) { - case 0: - bootdriver_num = 0; - break; - case CDROMRefNum: - bootdriver_num = 1; - break; - } - - nocdrom = PrefsFindBool("nocdrom"); - - extfs_name[0] = 0; - str = PrefsFindString("extfs"); - if (str) - strncpy(extfs_name, str, sizeof(extfs_name) - 1); -} - -// Ghost/unghost "Edit" and "Remove" buttons -static void ghost_volumes_gadgets(struct LayoutHandle *h) -{ - UWORD sel = LT_GetAttributes(h, GAD_DISK_LIST, TAG_END); - if (sel == 0xffff) { - LT_SetAttributes(h, GAD_EDIT_VOLUME, GA_Disabled, TRUE, TAG_END); - LT_SetAttributes(h, GAD_REMOVE_VOLUME, GA_Disabled, TRUE, TAG_END); - } else { - LT_SetAttributes(h, GAD_EDIT_VOLUME, GA_Disabled, FALSE, TAG_END); - LT_SetAttributes(h, GAD_REMOVE_VOLUME, GA_Disabled, FALSE, TAG_END); - } -} - -// Get device data from partition name -static void analyze_partition(const char *part, char *dev_name, ULONG &dev_unit, ULONG &dev_flags, ULONG &dev_start, ULONG &dev_size, ULONG &dev_bsize) -{ - // Remove everything after and including the ':' - char str[256]; - strncpy(str, part, sizeof(str) - 1); - str[sizeof(str) - 1] = 0; - char *colon = strchr(str, ':'); - if (colon) - *colon = 0; - - // Look for partition - struct DosList *dl = LockDosList(LDF_DEVICES | LDF_READ); - dl = FindDosEntry(dl, str, LDF_DEVICES); - if (dl) { - // Get File System Startup Message - struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)(dl->dol_misc.dol_handler.dol_Startup << 2); - if (fssm) { - // Get DOS environment vector - struct DosEnvec *de = (struct DosEnvec *)(fssm->fssm_Environ << 2); - if (de && de->de_TableSize >= DE_UPPERCYL) { - // Read settings from FSSM and Envec - strncpy(dev_name, (char *)(fssm->fssm_Device << 2) + 1, 255); - dev_name[255] = 0; - dev_unit = fssm->fssm_Unit; - dev_flags = fssm->fssm_Flags; - dev_start = de->de_BlocksPerTrack * de->de_Surfaces * de->de_LowCyl; - dev_size = de->de_BlocksPerTrack * de->de_Surfaces * (de->de_HighCyl - de->de_LowCyl + 1); - dev_bsize = de->de_SizeBlock << 2; - } - } - } - UnLockDosList(LDF_DEVICES | LDF_READ); -} - -// Display and handle "Add/Edit Volume" window -static void add_edit_volume(struct LayoutHandle *h2, bool adding) -{ - bool ok_clicked = false; - - UWORD sel = LT_GetAttributes(h2, GAD_DISK_LIST, TAG_END); - if ((sel == 0xffff) && !adding) - return; - - char dev_name[256] = ""; - char file_name[256] = ""; - ULONG dev_unit = 0, dev_flags = 0, dev_start = 0, dev_size = 0, dev_bsize = 512; - BYTE read_only = false, is_device = false; - - if (!adding) { - const char *str = PrefsFindString("disk", sel); - if (str == NULL) - return; - if (str[0] == '*') { - read_only = true; - str++; - } - if (strstr(str, "/dev/") == str) { - is_device = true; - sscanf(str, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", dev_name, &dev_unit, &dev_flags, &dev_start, &dev_size, &dev_bsize); - } else { - strncpy(file_name, str, sizeof(file_name) - 1); - file_name[sizeof(file_name) - 1] = 0; - } - } - - // Create layout handle - struct LayoutHandle *h = NULL; - struct Window *win = NULL; - h = LT_CreateHandleTags(NULL, - LAHN_AutoActivate, FALSE, - LAHN_LocaleHook, (ULONG)&locale_hook, - TAG_END - ); - if (h == NULL) - return; - - // Create window contents - VGROUP; - // Volume gadgets - VGROUP; - LT_New(h, LA_Type, CHECKBOX_KIND, - LA_LabelID, STR_VOL_READONLY_CTRL, - LA_ID, GAD_VOLUME_READONLY, - LA_BYTE, (ULONG)&read_only, - TAG_END - ); - LT_New(h, LA_Type, CYCLE_KIND, - LA_LabelID, STR_VOL_TYPE_CTRL, - LA_ID, GAD_VOLUME_TYPE, - LACY_AutoPageID, GAD_VOLUME_PAGEGROUP, - LACY_FirstLabel, STR_VOL_FILE_LAB, - LACY_LastLabel, STR_VOL_DEVICE_LAB, - LA_BYTE, (ULONG)&is_device, - TAG_END - ); - ENDGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_ID, GAD_VOLUME_PAGEGROUP, - LAGR_ActivePage, is_device, - TAG_END - ); - VGROUP; - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_VOL_FILE_CTRL, - LA_ID, GAD_VOLUME_FILE, - LA_Chars, 20, - LA_STRPTR, (ULONG)file_name, - GTST_MaxChars, sizeof(file_name) - 1, - LAST_Picker, TRUE, - TAG_END - ); - ENDGROUP; - VGROUP; - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_DEVICE_CTRL, - LA_ID, GAD_VOLUME_DEVICE, - LA_Chars, 20, - LA_STRPTR, (ULONG)dev_name, - GTST_MaxChars, sizeof(dev_name) - 1, - LAST_Picker, TRUE, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_UNIT_CTRL, - LA_ID, GAD_VOLUME_UNIT, - LA_LONG, (ULONG)&dev_unit, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_VOL_OPENFLAGS_CTRL, - LA_ID, GAD_VOLUME_OPENFLAGS, - LA_LONG, (ULONG)&dev_flags, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_VOL_STARTBLOCK_CTRL, - LA_ID, GAD_VOLUME_STARTBLOCK, - LA_LONG, (ULONG)&dev_start, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_VOL_SIZE_CTRL, - LA_ID, GAD_VOLUME_SIZE, - LA_LONG, (ULONG)&dev_size, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_VOL_BLOCKSIZE_CTRL, - LA_ID, GAD_VOLUME_BLOCKSIZE, - LA_LONG, (ULONG)&dev_bsize, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - ENDGROUP; - ENDGROUP; - - // Separator between gadgets and buttons - VGROUP; - LT_New(h, LA_Type, XBAR_KIND, - LAXB_FullSize, TRUE, - TAG_END - ); - ENDGROUP; - - // "OK" and "Cancel" buttons - LT_New(h, LA_Type, HORIZONTAL_KIND, - LAGR_SameSize, TRUE, - LAGR_Spread, TRUE, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_OK_BUTTON, - LA_ID, MSG_OK, - LABT_ReturnKey, TRUE, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_CANCEL_BUTTON, - LA_ID, MSG_CANCEL, - LABT_EscKey, TRUE, - TAG_END - ); - ENDGROUP; - ENDGROUP; - - // Open window - win = LT_Build(h, - LAWN_TitleID, adding ? STR_ADD_VOLUME_TITLE : STR_EDIT_VOLUME_TITLE, - LAWN_IDCMP, IDCMP_CLOSEWINDOW, - LAWN_BelowMouse, TRUE, - LAWN_SmartZoom, TRUE, - WA_SimpleRefresh, TRUE, - WA_Activate, TRUE, - WA_CloseGadget, TRUE, - WA_DepthGadget, TRUE, - WA_DragBar, TRUE, - TAG_END - ); - if (win == NULL) { - LT_DeleteHandle(h); - return; - } - - // Event loop - bool done = false; - do { - struct IntuiMessage *msg; - - // Wait for message - WaitPort(win->UserPort); - - // Get pending messages - while (msg = LT_GetIMsg(h)) { - - // Get data from message and reply - ULONG cl = msg->Class; - UWORD code = msg->Code; - struct Gadget *gad = (struct Gadget *)msg->IAddress; - LT_ReplyIMsg(msg); - - // Handle message according to class - switch (cl) { - case IDCMP_CLOSEWINDOW: - done = true; - break; - - case IDCMP_GADGETUP: - switch (gad->GadgetID) { - case MSG_OK: - ok_clicked = true; - done = true; - break; - case MSG_CANCEL: - done = true; - break; - } - break; - - case IDCMP_IDCMPUPDATE: { - struct FileRequester *req = NULL; - switch (gad->GadgetID) { - case GAD_VOLUME_FILE: - req = file_request; - goto do_req; - case GAD_VOLUME_DEVICE: - req = dev_request; -do_req: if (req) { - LT_LockWindow(win); - BOOL result = AslRequestTags(req, ASLFR_Window, (ULONG)win, TAG_END); - LT_UnlockWindow(win); - if (result) { - char *str; - GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END); - if (gad->GadgetID == GAD_VOLUME_FILE) { - strncpy(str, req->rf_Dir, 255); - str[255] = 0; - AddPart(str, req->rf_File, 255); - } else { - if (strlen(req->rf_File)) { - strncpy(str, req->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that. - str[255] = 0; - } else if (strlen(req->rf_Dir) && req->rf_Dir[strlen(req->rf_Dir) - 1] == ':') { - analyze_partition(req->rf_Dir, str, dev_unit, dev_flags, dev_start, dev_size, dev_bsize); - LT_SetAttributes(h, GAD_VOLUME_UNIT, GTIN_Number, dev_unit, TAG_END); - LT_SetAttributes(h, GAD_VOLUME_OPENFLAGS, GTIN_Number, dev_flags, TAG_END); - LT_SetAttributes(h, GAD_VOLUME_STARTBLOCK, GTIN_Number, dev_start, TAG_END); - LT_SetAttributes(h, GAD_VOLUME_SIZE, GTIN_Number, dev_size, TAG_END); - LT_SetAttributes(h, GAD_VOLUME_BLOCKSIZE, GTIN_Number, dev_bsize, TAG_END); - } - } - LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END); - } - } - break; - } - break; - } - } - } - } while (!done); - - // Update preferences and list view - if (ok_clicked) { - char str[256]; - LT_UpdateStrings(h); - - if (is_device) - sprintf(str, "%s/dev/%s/%ld/%ld/%ld/%ld/%ld", read_only ? "*" : "", dev_name, dev_unit, dev_flags, dev_start, dev_size, dev_bsize); - else - sprintf(str, "%s%s", read_only ? "*" : "", file_name); - LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, ~0, TAG_END); - - if (adding) { - - // Add new item - int i; - PrefsAddString("disk", str); - struct Node *item = (struct Node *)AllocMem(sizeof(struct Node), MEMF_CLEAR); - for (i=0; PrefsFindString("disk", i); i++) ; - item->ln_Name = (char *)PrefsFindString("disk", i - 1); - AddTail(&disk_list, item); - - } else { - - // Replace existing item - PrefsReplaceString("disk", str, sel); - struct Node *item = disk_list.lh_Head; - for (int i=0; item->ln_Succ; i++) { - if (i == sel) { - item->ln_Name = (char *)PrefsFindString("disk", sel); - break; - } - item = item->ln_Succ; - } - } - LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, TAG_END); - ghost_volumes_gadgets(h2); - } - - // Delete handle - LT_DeleteHandle(h); -} - -// Remove volume from list -static void remove_volume(struct LayoutHandle *h) -{ - UWORD sel = LT_GetAttributes(h, GAD_DISK_LIST, TAG_END); - if (sel != 0xffff) { - - // Remove item from preferences and list view - LT_SetAttributes(h, GAD_DISK_LIST, GTLV_Labels, ~0, TAG_END); - PrefsRemoveItem("disk", sel); - struct Node *item = disk_list.lh_Head; - for (int i=0; item->ln_Succ; i++) { - struct Node *next = item->ln_Succ; - if (i == sel) { - Remove(item); - FreeMem(item, sizeof(struct Node)); - break; - } - item = next; - } - LT_SetAttributes(h, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, GTLV_Selected, 0xffff, TAG_END); - ghost_volumes_gadgets(h); - } -} - -// Read settings from gadgets and set preferences -static void read_volumes_settings(void) -{ - struct Node *item = disk_list.lh_Head; - while (item->ln_Succ) { - struct Node *next = item->ln_Succ; - Remove(item); - FreeMem(item, sizeof(struct Node)); - item = next; - } - - if (strlen(cdrom_name)) { - char str[256]; - sprintf(str, "/dev/%s/%ld/%ld/%ld/%ld/%ld", cdrom_name, cdrom_unit, cdrom_flags, cdrom_start, cdrom_size, cdrom_bsize); - PrefsReplaceString("cdrom", str); - } else - PrefsRemoveItem("cdrom"); - - PrefsReplaceBool("nocdrom", nocdrom); - - if (strlen(extfs_name)) - PrefsReplaceString("extfs", extfs_name); -} - -// Create "Volumes" pane -static void create_volumes_pane(struct LayoutHandle *h) -{ - parse_volumes_prefs(); - - VGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_VOLUMES_CTRL, - TAG_END - ); - VGROUP; - LT_New(h, LA_Type, LISTVIEW_KIND, - LA_ID, GAD_DISK_LIST, - LA_Chars, 20, - GTLV_Labels, (ULONG)&disk_list, - LALV_Lines, 6, - LALV_Link, (ULONG)NIL_LINK, - LALV_ResizeX, TRUE, - LALV_ResizeY, TRUE, - LALV_Selected, 0, - TAG_END - ); - ENDGROUP; - LT_New(h, LA_Type, HORIZONTAL_KIND, - LAGR_SameSize, TRUE, - LAGR_Spread, TRUE, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_ADD_VOLUME_BUTTON, - LA_ID, GAD_ADD_VOLUME, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_EDIT_VOLUME_BUTTON, - LA_ID, GAD_EDIT_VOLUME, - TAG_END - ); - LT_New(h, LA_Type, BUTTON_KIND, - LA_LabelID, STR_REMOVE_VOLUME_BUTTON, - LA_ID, GAD_REMOVE_VOLUME, - TAG_END - ); - ENDGROUP; - ENDGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_CDROM_DRIVE_CTRL, - TAG_END - ); - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_DEVICE_CTRL, - LA_ID, GAD_CDROM_DEVICE, - LA_Chars, 20, - LA_STRPTR, (ULONG)cdrom_name, - GTST_MaxChars, sizeof(cdrom_name) - 1, - LAST_Picker, TRUE, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_UNIT_CTRL, - LA_ID, GAD_CDROM_UNIT, - LA_LONG, (ULONG)&cdrom_unit, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, CYCLE_KIND, - LA_LabelID, STR_BOOTDRIVER_CTRL, - LA_ID, GAD_BOOTDRIVER, - LACY_FirstLabel, STR_BOOT_ANY_LAB, - LACY_LastLabel, STR_BOOT_CDROM_LAB, - LA_BYTE, (ULONG)&bootdriver_num, - TAG_END - ); - LT_New(h, LA_Type, CHECKBOX_KIND, - LA_LabelID, STR_NOCDROM_CTRL, - LA_ID, GAD_NOCDROM, - LA_BYTE, (ULONG)&nocdrom, - TAG_END - ); - ENDGROUP; - VGROUP; - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_EXTFS_CTRL, - LA_ID, GAD_EXTFS, - LA_Chars, 20, - LA_STRPTR, (ULONG)extfs_name, - GTST_MaxChars, sizeof(extfs_name) - 1, - TAG_END - ); - ENDGROUP; - ENDGROUP; -} - - -/* - * "SCSI" pane - */ - -static char scsi_dev[6][256]; -static LONG scsi_unit[6]; -static LONG scsi_memtype; - -// Read SCSI preferences -static void parse_scsi_prefs(void) -{ - for (int i=0; i<7; i++) { - scsi_dev[i][0] = 0; - scsi_unit[i] = 0; - - char prefs_name[16]; - sprintf(prefs_name, "scsi%d", i); - const char *str = PrefsFindString(prefs_name); - if (str) - sscanf(str, "%[^/]/%ld", scsi_dev[i], &scsi_unit[i]); - } - - scsi_memtype = PrefsFindInt32("scsimemtype"); -} - -// Read settings from gadgets and set preferences -static void read_scsi_settings(void) -{ - for (int i=0; i<7; i++) { - char prefs_name[16]; - sprintf(prefs_name, "scsi%d", i); - - if (strlen(scsi_dev[i])) { - char str[256]; - sprintf(str, "%s/%ld", scsi_dev[i], scsi_unit[i]); - PrefsReplaceString(prefs_name, str); - } else - PrefsRemoveItem(prefs_name); - } -} - -// Create "SCSI" pane -static void create_scsi_pane(struct LayoutHandle *h) -{ - parse_scsi_prefs(); - - VGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_SCSI_DEVICES_CTRL, - TAG_END - ); - for (int i=0; i<7; i++) { - HGROUP; - LT_New(h, LA_Type, TEXT_KIND, - LA_LabelID, STR_SCSI_ID_0 + i, - TAG_END - ); - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_DEVICE_CTRL, - LA_ID, GAD_SCSI0_DEVICE + i, - LA_Chars, 20, - LA_STRPTR, (ULONG)scsi_dev[i], - GTST_MaxChars, sizeof(scsi_dev[i]) - 1, - LAST_Picker, TRUE, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_UNIT_CTRL, - LA_ID, GAD_SCSI0_UNIT + i, - LA_Chars, 4, - LA_LONG, (ULONG)&scsi_unit[i], - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - ENDGROUP; - } - ENDGROUP; - VGROUP; - LT_New(h, LA_Type, CYCLE_KIND, - LA_LabelID, STR_SCSI_MEMTYPE_CTRL, - LA_ID, GAD_SCSI_MEMTYPE, - LACY_FirstLabel, STR_MEMTYPE_CHIP_LAB, - LACY_LastLabel, STR_MEMTYPE_ANY_LAB, - LA_LONG, (ULONG)&scsi_memtype, - TAG_END - ); - ENDGROUP; - ENDGROUP; -} - - -/* - * "Graphics/Sound" pane - */ - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_PIP, - DISPLAY_SCREEN -}; - -static LONG display_type; -static LONG dis_width, dis_height; -static ULONG mode_id; -static BYTE frameskip_num; -static struct NameInfo mode_name; -static ULONG ahi_id; -static char ahi_mode_name[256]; -static BYTE nosound; - -// Read graphics preferences -static void parse_graphics_prefs(void) -{ - display_type = DISPLAY_WINDOW; - dis_width = 512; - dis_height = 384; - mode_id = 0; - ahi_id = AHI_DEFAULT_ID; - ahi_mode_name[0] = 0; - - frameskip_num = 0; - int frameskip = PrefsFindInt32("frameskip"); - switch (frameskip) { - case 12: - frameskip_num = 0; - break; - case 8: - frameskip_num = 1; - break; - case 6: - frameskip_num = 2; - break; - case 4: - frameskip_num = 3; - break; - case 2: - frameskip_num = 4; - break; - case 1: - frameskip_num = 5; - break; - } - - const char *str = PrefsFindString("screen"); - if (str) { - if (sscanf(str, "win/%ld/%ld", &dis_width, &dis_height) == 2) - display_type = DISPLAY_WINDOW; - else if (sscanf(str, "pip/%ld/%ld", &dis_width, &dis_height) == 2) - display_type = DISPLAY_PIP; - else if (sscanf(str, "scr/%08lx", &mode_id) == 1) - display_type = DISPLAY_SCREEN; - } - - GetDisplayInfoData(NULL, (UBYTE *)&mode_name, sizeof(mode_name), DTAG_NAME, mode_id); - - str = PrefsFindString("sound"); - if (str) { - if (sscanf(str, "ahi/%08lx", &ahi_id) == 1 && AHIBase) { - AHI_GetAudioAttrs(ahi_id, NULL, - AHIDB_Name, (ULONG)ahi_mode_name, - AHIDB_BufferLen, sizeof(ahi_mode_name) - 1, - TAG_END - ); - } - } - nosound = PrefsFindBool("nosound"); -} - -// Ghost/unghost graphics gadgets, depending on display type -static void ghost_graphics_gadgets(struct LayoutHandle *h) -{ - bool dis_xy, dis_skip, dis_mode; - switch (display_type) { - case DISPLAY_WINDOW: - dis_xy = false; - dis_skip = false; - dis_mode = true; - break; - case DISPLAY_PIP: - dis_xy = false; - dis_skip = true; - dis_mode = true; - break; - case DISPLAY_SCREEN: - dis_xy = true; - dis_skip = true; - dis_mode = false; - break; - } - LT_SetAttributes(h, GAD_DISPLAY_X, GA_Disabled, dis_xy, TAG_END); - LT_SetAttributes(h, GAD_DISPLAY_Y, GA_Disabled, dis_xy, TAG_END); - LT_SetAttributes(h, GAD_FRAMESKIP, GA_Disabled, dis_skip, TAG_END); - LT_SetAttributes(h, GAD_SCREEN_MODE, GA_Disabled, dis_mode, TAG_END); - LT_SetAttributes(h, GAD_AHI_MODE, GA_Disabled, AHIBase == NULL, TAG_END); -} - -// Show screen mode requester -static void screen_mode_req(struct Window *win, struct LayoutHandle *h) -{ - if (P96Base == NULL && CyberGfxBase == NULL) - return; - - LT_LockWindow(win); - - ULONG id; - - // Try P96 first, because it also provides a (fake) cybergraphics.library - if (P96Base) { - id = p96RequestModeIDTags( - P96MA_MinDepth, 8, - P96MA_FormatsAllowed, RGBFF_CLUT | RGBFF_R5G5B5 | RGBFF_A8R8G8B8, - TAG_END - ); - } else { - UWORD ModelArray[] = { PIXFMT_LUT8, PIXFMT_RGB15, PIXFMT_ARGB32, 0, ~0 }; - id = (ULONG) CModeRequestTags(NULL, - CYBRMREQ_MinDepth, 8, - CYBRMREQ_CModelArray, (ULONG) ModelArray, - TAG_END - ); - } - LT_UnlockWindow(win); - - if (id != INVALID_ID) { - mode_id = id; - GetDisplayInfoData(NULL, (UBYTE *)&mode_name, sizeof(mode_name), DTAG_NAME, mode_id); - LT_SetAttributes(h, GAD_SCREEN_MODE, GTTX_Text, (ULONG)mode_name.Name, TAG_END); - } -} - -// Show AHI mode requester -static void ahi_mode_req(struct Window *win, struct LayoutHandle *h) -{ - if (AHIBase == NULL) - return; - - struct AHIAudioModeRequester *req = AHI_AllocAudioRequest( - AHIR_Window, (ULONG)win, - TAG_END - ); - if (req == NULL) - return; - - LT_LockWindow(win); - BOOL ok = AHI_AudioRequest(req, - AHIR_InitialAudioID, ahi_id, - TAG_END - ); - LT_UnlockWindow(win); - - if (ok) { - ahi_id = req->ahiam_AudioID; - AHI_GetAudioAttrs(ahi_id, NULL, - AHIDB_Name, (ULONG)ahi_mode_name, - AHIDB_BufferLen, sizeof(ahi_mode_name) - 1, - TAG_END - ); - LT_SetAttributes(h, GAD_AHI_MODE, GTTX_Text, (ULONG)ahi_mode_name, TAG_END); - } - AHI_FreeAudioRequest(req); -} - -// Read settings from gadgets and set preferences -static void read_graphics_settings(void) -{ - char str[256]; - switch (display_type) { - case DISPLAY_WINDOW: - sprintf(str, "win/%ld/%ld", dis_width, dis_height); - break; - case DISPLAY_PIP: - sprintf(str, "pip/%ld/%ld", dis_width, dis_height); - break; - case DISPLAY_SCREEN: - sprintf(str, "scr/%08lx", mode_id); - break; - default: - PrefsRemoveItem("screen"); - return; - } - PrefsReplaceString("screen", str); - - sprintf(str, "ahi/%08lx", ahi_id); - PrefsReplaceString("sound", str); - - PrefsReplaceBool("nosound", nosound); -} - -// Create "Graphics/Sound" pane -static void create_graphics_pane(struct LayoutHandle *h) -{ - parse_graphics_prefs(); - - VGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_GRAPHICS_CTRL, - TAG_END - ); - static const LONG labels[] = {STR_WINDOW_LAB, STR_PIP_LAB, STR_FULLSCREEN_LAB, -1}; - LT_New(h, LA_Type, CYCLE_KIND, - LA_LabelID, STR_VIDEO_TYPE_CTRL, - LA_ID, GAD_VIDEO_TYPE, - LACY_LabelTable, (ULONG)labels, - LA_LONG, (ULONG)&display_type, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_DISPLAY_X_CTRL, - LA_ID, GAD_DISPLAY_X, - LA_LONG, (ULONG)&dis_width, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_DISPLAY_Y_CTRL, - LA_ID, GAD_DISPLAY_Y, - LA_LONG, (ULONG)&dis_height, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, POPUP_KIND, - LA_LabelID, STR_FRAMESKIP_CTRL, - LA_ID, GAD_FRAMESKIP, - LAPU_FirstLabel, STR_REF_5HZ_LAB, - LAPU_LastLabel, STR_REF_60HZ_LAB, - LA_BYTE, (ULONG)&frameskip_num, - TAG_END - ); - LT_New(h, LA_Type, TEXT_KIND, - LA_LabelID, STR_SCREEN_MODE_CTRL, - LA_ID, GAD_SCREEN_MODE, - LA_Chars, DISPLAYNAMELEN, - LATX_Picker, TRUE, - GTTX_Text, (ULONG)mode_name.Name, - GTTX_Border, TRUE, - TAG_END - ); - ENDGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_SOUND_CTRL, - TAG_END - ); - LT_New(h, LA_Type, TEXT_KIND, - LA_LabelID, STR_AHI_MODE_CTRL, - LA_ID, GAD_AHI_MODE, - LA_Chars, DISPLAYNAMELEN, - LATX_Picker, TRUE, - GTTX_Text, (ULONG)ahi_mode_name, - GTTX_Border, TRUE, - TAG_END - ); - LT_New(h, LA_Type, CHECKBOX_KIND, - LA_LabelID, STR_NOSOUND_CTRL, - LA_ID, GAD_NOSOUND, - LA_BYTE, (ULONG)&nosound, - TAG_END - ); - ENDGROUP; - ENDGROUP; - - ghost_graphics_gadgets(h); -} - - -/* - * "Serial/Network" pane - */ - -static char seriala_dev[256], serialb_dev[256]; -static LONG seriala_unit, serialb_unit; -static BYTE seriala_ispar, serialb_ispar; - -static char ether_dev[256]; -static ULONG ether_unit; - -// Read serial/network preferences -static void parse_ser_prefs(const char *prefs, char *dev, LONG &unit, BYTE &ispar) -{ - dev[0] = 0; - unit = 0; - ispar = false; - - const char *str = PrefsFindString(prefs); - if (str) { - if (str[0] == '*') { - ispar = true; - str++; - } - sscanf(str, "%[^/]/%ld", dev, &unit); - } -} - -static void parse_serial_prefs(void) -{ - parse_ser_prefs("seriala", seriala_dev, seriala_unit, seriala_ispar); - parse_ser_prefs("serialb", serialb_dev, serialb_unit, serialb_ispar); - - ether_dev[0] = 0; - ether_unit = 0; - - const char *str = PrefsFindString("ether"); - if (str) { - const char *FirstSlash = strchr(str, '/'); - const char *LastSlash = strrchr(str, '/'); - - if (FirstSlash && FirstSlash && FirstSlash != LastSlash) { - // Device name contains path, i.e. "Networks/xyzzy.device" - const char *lp = str; - char *dp = ether_dev; - - while (lp != LastSlash) - *dp++ = *lp++; - *dp = '\0'; - - sscanf(LastSlash, "/%ld", ðer_unit); - -// printf("dev=<%s> unit=%d\n", ether_dev, ether_unit); - } else { - sscanf(str, "%[^/]/%ld", ether_dev, ðer_unit); - } - } -} - -// Set serial preference item -static void make_serial_prefs(const char *prefs, const char *dev, LONG unit, BYTE ispar) -{ - if (strlen(dev)) { - char str[256]; - sprintf(str, "%s%s/%ld", ispar ? "*" : "", dev, unit); - PrefsReplaceString(prefs, str); - } else - PrefsRemoveItem(prefs); -} - -// Read settings from gadgets and set preferences -static void read_serial_settings(void) -{ - make_serial_prefs("seriala", seriala_dev, seriala_unit, seriala_ispar); - make_serial_prefs("serialb", serialb_dev, serialb_unit, serialb_ispar); - - if (strlen(ether_dev)) { - char str[256]; - - sprintf(str, "%s/%ld", ether_dev, ether_unit); - PrefsReplaceString("ether", str); - } else - PrefsRemoveItem("ether"); -} - -// Create "Serial/Network" pane -static void create_serial_pane(struct LayoutHandle *h) -{ - parse_serial_prefs(); - - VGROUP; - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_SERIALA_CTRL, - TAG_END - ); - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_DEVICE_CTRL, - LA_ID, GAD_SERIALA_DEVICE, - LA_Chars, 20, - LA_STRPTR, (ULONG)seriala_dev, - GTST_MaxChars, sizeof(seriala_dev) - 1, - LAST_Picker, TRUE, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_UNIT_CTRL, - LA_ID, GAD_SERIALA_UNIT, - LA_LONG, (ULONG)&seriala_unit, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, CHECKBOX_KIND, - LA_LabelID, STR_ISPAR_CTRL, - LA_ID, GAD_SERIALA_ISPAR, - LA_BYTE, (ULONG)&seriala_ispar, - TAG_END - ); - ENDGROUP; - - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_SERIALB_CTRL, - TAG_END - ); - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_DEVICE_CTRL, - LA_ID, GAD_SERIALB_DEVICE, - LA_Chars, 20, - LA_STRPTR, (ULONG)serialb_dev, - GTST_MaxChars, sizeof(serialb_dev) - 1, - LAST_Picker, TRUE, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_UNIT_CTRL, - LA_ID, GAD_SERIALB_UNIT, - LA_LONG, (ULONG)&serialb_unit, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - LT_New(h, LA_Type, CHECKBOX_KIND, - LA_LabelID, STR_ISPAR_CTRL, - LA_ID, GAD_SERIALB_ISPAR, - LA_BYTE, (ULONG)&serialb_ispar, - TAG_END - ); - ENDGROUP; - - LT_New(h, LA_Type, VERTICAL_KIND, - LA_LabelID, STR_ETHERNET_IF_CTRL, - TAG_END - ); - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_DEVICE_CTRL, - LA_ID, GAD_ETHER_DEVICE, - LA_Chars, 20, - LA_STRPTR, (ULONG)ether_dev, - GTST_MaxChars, sizeof(ether_dev) - 1, - LAST_Picker, TRUE, - TAG_END - ); - LT_New(h, LA_Type, INTEGER_KIND, - LA_LabelID, STR_UNIT_CTRL, - LA_ID, GAD_ETHER_UNIT, - LA_LONG, (ULONG)ðer_unit, - LAIN_UseIncrementers, TRUE, - GTIN_MaxChars, 8, - TAG_END - ); - ENDGROUP; - ENDGROUP; -} - - -/* - * "Memory/Misc" pane - */ - -static ULONG ramsize_mb; -static BYTE model_num; -static char rom_file[256]; - -// Read memory/misc preferences -static void parse_memory_prefs(void) -{ - ramsize_mb = PrefsFindInt32("ramsize") >> 20; - - model_num = 0; - int id = PrefsFindInt32("modelid"); - switch (id) { - case 5: - model_num = 0; - break; - case 14: - model_num = 1; - break; - } - - rom_file[0] = 0; - const char *str = PrefsFindString("rom"); - if (str) { - strncpy(rom_file, str, sizeof(rom_file) - 1); - rom_file[sizeof(rom_file) - 1] = 0; - } -} - -// Read settings from gadgets and set preferences -static void read_memory_settings(void) -{ - PrefsReplaceInt32("ramsize", ramsize_mb << 20); - - if (strlen(rom_file)) - PrefsReplaceString("rom", rom_file); - else - PrefsRemoveItem("rom"); -} - -// Create "Memory/Misc" pane -static void create_memory_pane(struct LayoutHandle *h) -{ - parse_memory_prefs(); - - VGROUP; - LT_New(h, LA_Type, LEVEL_KIND, - LA_LabelID, STR_RAMSIZE_SLIDER, - LA_ID, GAD_RAMSIZE, - LA_Chars, 20, - LA_LONG, (ULONG)&ramsize_mb, - GTSL_LevelFormat, (ULONG)GetString(STR_RAMSIZE_FMT), - GTSL_Min, 1, - GTSL_Max, AvailMem(MEMF_LARGEST) >> 20, - TAG_END - ); - LT_New(h, LA_Type, CYCLE_KIND, - LA_LabelID, STR_MODELID_CTRL, - LA_ID, GAD_MODELID, - LACY_FirstLabel, STR_MODELID_5_LAB, - LACY_LastLabel, STR_MODELID_14_LAB, - LA_BYTE, (ULONG)&model_num, - TAG_END - ); - LT_New(h, LA_Type, STRING_KIND, - LA_LabelID, STR_ROM_FILE_CTRL, - LA_ID, GAD_ROM_FILE, - LA_Chars, 20, - LA_STRPTR, (ULONG)rom_file, - GTST_MaxChars, sizeof(rom_file) - 1, - LAST_Picker, TRUE, - TAG_END - ); - ENDGROUP; -} - - -/* - * Read settings from gadgets and set preferences - */ - -static void read_settings(struct LayoutHandle *h) -{ - LT_UpdateStrings(h); - read_volumes_settings(); - read_scsi_settings(); - read_graphics_settings(); - read_serial_settings(); - read_memory_settings(); -} diff --git a/BasiliskII/src/AmigaOS/scsi_amiga.cpp b/BasiliskII/src/AmigaOS/scsi_amiga.cpp deleted file mode 100644 index c660eb26..00000000 --- a/BasiliskII/src/AmigaOS/scsi_amiga.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * scsi_amiga.cpp - SCSI Manager, Amiga specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "scsi.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static struct SCSICmd scsi; - -static IOStdReq *ios[8*8]; // IORequests for 8 units and 8 LUNs each -static IOStdReq *io; // Active IORequest (selected target) - -static struct MsgPort *the_port = NULL; // Message port for device communication - -static ULONG buffer_size; // Size of data buffer -static UBYTE *buffer = NULL; // Pointer to data buffer -static ULONG buffer_memf; // Buffer memory flags - -static UBYTE cmd_buffer[12]; // Buffer for SCSI command - -const int SENSE_LENGTH = 256; -static UBYTE *sense_buffer = NULL; // Buffer for autosense data - -static bool direct_transfers_supported = false; // Direct data transfers (bypassing the buffer) are supported - - -/* - * Initialization - */ - -void SCSIInit(void) -{ - int id, lun; - - int memtype = PrefsFindInt32("scsimemtype"); - switch (memtype) { - case 1: - buffer_memf = MEMF_24BITDMA | MEMF_PUBLIC; - break; - case 2: - buffer_memf = MEMF_ANY | MEMF_PUBLIC; - direct_transfers_supported = true; - break; - default: - buffer_memf = MEMF_CHIP | MEMF_PUBLIC; - break; - } - - // Create port and buffers - the_port = CreateMsgPort(); - buffer = (UBYTE *)AllocMem(buffer_size = 0x10000, buffer_memf); - sense_buffer = (UBYTE *)AllocMem(SENSE_LENGTH, MEMF_CHIP | MEMF_PUBLIC); - if (the_port == NULL || buffer == NULL || sense_buffer == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } - - // Create and open IORequests for all 8 units (and all 8 LUNs) - for (id=0; id<8; id++) { - for (lun=0; lun<8; lun++) - ios[id*8+lun] = NULL; - char prefs_name[16]; - sprintf(prefs_name, "scsi%d", id); - const char *str = PrefsFindString(prefs_name); - if (str) { - char dev_name[256]; - ULONG dev_unit = 0; - if (sscanf(str, "%[^/]/%ld", dev_name, &dev_unit) == 2) { - for (lun=0; lun<8; lun++) { - struct IOStdReq *io = (struct IOStdReq *)CreateIORequest(the_port, sizeof(struct IOStdReq)); - if (io == NULL) - continue; - if (OpenDevice((UBYTE *) dev_name, dev_unit + lun * 10, (struct IORequest *)io, 0)) { - DeleteIORequest(io); - continue; - } - io->io_Data = &scsi; - io->io_Length = sizeof(scsi); - io->io_Command = HD_SCSICMD; - ios[id*8+lun] = io; - } - } - } - } - - // Reset SCSI bus - SCSIReset(); - - // Init SCSICmd - memset(&scsi, 0, sizeof(scsi)); - scsi.scsi_Command = cmd_buffer; - scsi.scsi_SenseData = sense_buffer; - scsi.scsi_SenseLength = SENSE_LENGTH; -} - - -/* - * Deinitialization - */ - -void SCSIExit(void) -{ - // Close all devices - for (int i=0; i<8; i++) - for (int j=0; j<8; j++) { - struct IOStdReq *io = ios[i*8+j]; - if (io) { - CloseDevice((struct IORequest *)io); - DeleteIORequest(io); - } - } - - // Delete port and buffers - if (the_port) - DeleteMsgPort(the_port); - if (buffer) - FreeMem(buffer, buffer_size); - if (sense_buffer) - FreeMem(sense_buffer, SENSE_LENGTH); -} - - -/* - * Check if requested data size fits into buffer, allocate new buffer if needed - */ - -static bool try_buffer(int size) -{ - if (size <= buffer_size) - return true; - - UBYTE *new_buffer = (UBYTE *)AllocMem(size, buffer_memf); - if (new_buffer == NULL) - return false; - FreeMem(buffer, buffer_size); - buffer = new_buffer; - buffer_size = size; - return true; -} - - -/* - * Set SCSI command to be sent by scsi_send_cmd() - */ - -void scsi_set_cmd(int cmd_length, uint8 *cmd) -{ - scsi.scsi_CmdLength = cmd_length; - memcpy(cmd_buffer, cmd, cmd_length); -} - - -/* - * Check for presence of SCSI target - */ - -bool scsi_is_target_present(int id) -{ - return ios[id * 8] != NULL; -} - - -/* - * Set SCSI target (returns false on error) - */ - -bool scsi_set_target(int id, int lun) -{ - struct IOStdReq *new_io = ios[id * 8 + lun]; - if (new_io == NULL) - return false; - if (new_io != io) - scsi.scsi_SenseActual = 0; // Clear sense data when selecting new target - io = new_io; - return true; -} - - -/* - * Send SCSI command to active target (scsi_set_command() must have been called), - * read/write data according to S/G table (returns false on error); timeout is in 1/60 sec - */ - -bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout) -{ - // Bypass the buffer if there's only one S/G table entry - bool do_direct_transfer = (sg_size == 1 && ((uint32)sg_ptr[0] & 1) == 0 && direct_transfers_supported); - - if (!do_direct_transfer) { - - // Check if buffer is large enough, allocate new buffer if needed - if (!try_buffer(data_length)) { - char str[256]; - sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length); - ErrorAlert(str); - return false; - } - - // Process S/G table when writing - if (!reading) { - D(bug(" writing to buffer\n")); - uint8 *buffer_ptr = buffer; - for (int i=0; i -#include -#include -#include -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "serial.h" -#include "serial_defs.h" - -#define DEBUG 0 -#include "debug.h" - -#define MONITOR 0 - - -// These messages are sent to the serial process -const uint32 MSG_QUERY = 'qery'; // Query port status, return status in control_io -const uint32 MSG_SET_PARAMS = 'setp'; // Set serial parameters (parameters in control_io) -const uint32 MSG_SET_PAR_PARAMS = 'pstp'; // Set parallel parameters (parameters in control_io) -const uint32 MSG_KILL_IO = 'kill'; // Kill pending I/O requests -const uint32 MSG_BREAK = 'brek'; // Send break -const uint32 MSG_RESET = 'rset'; // Reset channel -const uint32 MSG_PRIME_IN = 'prin'; // Data input -const uint32 MSG_PRIME_OUT = 'pout'; // Data output - -struct SerMessage : public Message { - SerMessage(uint32 what_, const struct MsgPort *reply_port = NULL) - { - what = what_; - mn_ReplyPort = (struct MsgPort *)reply_port; - mn_Length = sizeof(*this); - } - uint32 what; - uint32 pb; -}; - - -// Driver private variables -class ASERDPort : public SERDPort { -public: - ASERDPort(const char *dev) - { - device_name = dev; - if (dev && dev[0] == '*') { - is_parallel = true; - device_name++; - } else - is_parallel = false; - control_io = NULL; - serial_proc = NULL; - reply_port = NULL; - } - - virtual ~ASERDPort() - { - } - - virtual int16 open(uint16 config); - virtual int16 prime_in(uint32 pb, uint32 dce); - virtual int16 prime_out(uint32 pb, uint32 dce); - virtual int16 control(uint32 pb, uint32 dce, uint16 code); - virtual int16 status(uint32 pb, uint32 dce, uint16 code); - virtual int16 close(void); - -private: - bool configure(uint16 config); - void set_handshake(uint32 s, bool with_dtr); - void send_to_proc(uint32 what, uint32 pb = 0); - bool query(void); - bool set_params(void); - bool set_par_params(void); - void conv_error(struct IOExtSer *io, uint32 dt); - static void serial_func(void); - - const char *device_name; // Device name - bool is_parallel; // Flag: Port is parallel - IOExtSer *control_io; // IORequest for setting serial port characteristics etc. - - struct Process *serial_proc; // Serial device handler process - bool proc_error; // Flag: process didn't initialize - struct MsgPort *proc_port; // Message port of process, for communication with main task - struct MsgPort *reply_port; // Reply port for communication with process - - uint8 err_mask; // shkErrs -}; - - -// Global variables -static void *proc_arg; // Argument to process -extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp) - - -/* - * Initialization - */ - -void SerialInit(void) -{ - // Read serial preferences and create structs for both ports - the_serd_port[0] = new ASERDPort(PrefsFindString("seriala")); - the_serd_port[1] = new ASERDPort(PrefsFindString("serialb")); -} - - -/* - * Deinitialization - */ - -void SerialExit(void) -{ - delete (ASERDPort *)the_serd_port[0]; - delete (ASERDPort *)the_serd_port[1]; -} - - -/* - * Open serial port - */ - -int16 ASERDPort::open(uint16 config) -{ - // Don't open NULL name devices - if (device_name == NULL) - return openErr; - - // Init variables - err_mask = 0; - - // Create message port - reply_port = CreateMsgPort(); - if (reply_port == NULL) - goto open_error; - - // Start process - proc_error = false; - proc_arg = this; - SetSignal(0, SIGF_SINGLE); - serial_proc = CreateNewProcTags( - NP_Entry, (ULONG)serial_func, - NP_Name, (ULONG)"Basilisk II Serial Task", - NP_Priority, 1, - TAG_END - ); - if (serial_proc == NULL) - goto open_error; - - // Wait for signal from process - Wait(SIGF_SINGLE); - - // Initialization error? Then bail out - if (proc_error) - goto open_error; - - // Configure port - configure(config); - return noErr; - -open_error: - serial_proc = NULL; - if (reply_port) { - DeleteMsgPort(reply_port); - reply_port = NULL; - } - return openErr; -} - - -/* - * Read data from port - */ - -int16 ASERDPort::prime_in(uint32 pb, uint32 dce) -{ - // Send input command to serial process - D(bug("primein\n")); - read_done = false; - read_pending = true; - WriteMacInt32(input_dt + serdtDCE, dce); - send_to_proc(MSG_PRIME_IN, pb); - return 1; // Command in progress -} - - -/* - * Write data to port - */ - -int16 ASERDPort::prime_out(uint32 pb, uint32 dce) -{ - // Send output command to serial process - D(bug("primeout\n")); - write_done = false; - write_pending = true; - WriteMacInt32(output_dt + serdtDCE, dce); - send_to_proc(MSG_PRIME_OUT, pb); - return 1; // Command in progress -} - - -/* - * Control calls - */ - -int16 ASERDPort::control(uint32 pb, uint32 dce, uint16 code) -{ - D(bug("control(%ld)\n", (uint32)code)); - switch (code) { - case 1: // KillIO - send_to_proc(MSG_KILL_IO); - return noErr; - - case kSERDConfiguration: - if (configure(ReadMacInt16(pb + csParam))) - return noErr; - else - return paramErr; - - case kSERDInputBuffer: { - if (is_parallel) - return noErr; - int buf = ReadMacInt16(pb + csParam + 4) & 0xffffffc0; - if (buf < 1024) // 1k minimum - buf = 1024; - D(bug(" buffer size is now %08lx\n", buf)); - control_io->io_RBufLen = buf; - return set_params() ? noErr : paramErr; - } - - case kSERDSerHShake: - set_handshake(pb + csParam, false); - return noErr; - - case kSERDSetBreak: - if (!is_parallel) - send_to_proc(MSG_BREAK); - return noErr; - - case kSERDClearBreak: - return noErr; - - case kSERDBaudRate: - if (is_parallel) - return noErr; - control_io->io_Baud = ReadMacInt16(pb + csParam); - D(bug(" baud rate %ld\n", control_io->io_Baud)); - return set_params() ? noErr : paramErr; - - case kSERDHandshake: - case kSERDHandshakeRS232: - set_handshake(pb + csParam, true); - return noErr; - - case kSERDClockMIDI: - if (is_parallel) - return noErr; - control_io->io_Baud = 31250; - control_io->io_SerFlags = SERF_XDISABLED | SERF_SHARED; - control_io->io_StopBits = 1; - control_io->io_ReadLen = control_io->io_WriteLen = 8; - return set_params() ? noErr : paramErr; - - case kSERDMiscOptions: - case kSERDAssertDTR: - case kSERDNegateDTR: - case kSERDSetPEChar: - case kSERDSetPEAltChar: - case kSERDAssertRTS: - case kSERDNegateRTS: - return noErr; // Not supported under AmigaOS - - case kSERD115KBaud: - if (is_parallel) - return noErr; - control_io->io_Baud = 115200; - return set_params() ? noErr : paramErr; - - case kSERD230KBaud: - case kSERDSetHighSpeed: - if (is_parallel) - return noErr; - control_io->io_Baud = 230400; - return set_params() ? noErr : paramErr; - - case kSERDResetChannel: - send_to_proc(MSG_RESET); - return noErr; - - default: - printf("WARNING: SerialControl(): unimplemented control code %d\n", code); - return controlErr; - } -} - - -/* - * Status calls - */ - -int16 ASERDPort::status(uint32 pb, uint32 dce, uint16 code) -{ - D(bug("status(%ld)\n", (uint32)code)); - switch (code) { - case kSERDInputCount: - WriteMacInt32(pb + csParam, 0); - if (!is_parallel) { - if (!query()) - return noErr; - D(bug("status(2) successful, returning %08lx\n", control_io->IOSer.io_Actual)); - WriteMacInt32(pb + csParam, control_io->IOSer.io_Actual); - } - return noErr; - - case kSERDStatus: { - uint32 p = pb + csParam; - WriteMacInt8(p + staCumErrs, cum_errors); - cum_errors = 0; - WriteMacInt8(p + staRdPend, read_pending); - WriteMacInt8(p + staWrPend, write_pending); - if (is_parallel) { - WriteMacInt8(p + staXOffSent, 0); - WriteMacInt8(p + staXOffHold, 0); - WriteMacInt8(p + staCtsHold, 0); - WriteMacInt8(p + staDsrHold, 0); - WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent); - } else { - query(); - WriteMacInt8(p + staXOffSent, - (control_io->io_Status & IO_STATF_XOFFREAD ? xOffWasSent : 0) - | (control_io->io_Status & (1 << 6) ? dtrNegated : 0)); // RTS - WriteMacInt8(p + staXOffHold, control_io->io_Status & IO_STATF_XOFFWRITE); - WriteMacInt8(p + staCtsHold, control_io->io_Status & (1 << 4)); // CTS - WriteMacInt8(p + staDsrHold, control_io->io_Status & (1 << 3)); // DSR - WriteMacInt8(p + staModemStatus, - (control_io->io_Status & (1 << 3) ? 0 : dsrEvent) - | (control_io->io_Status & (1 << 2) ? riEvent : 0) - | (control_io->io_Status & (1 << 5) ? 0 : dcdEvent) - | (control_io->io_Status & (1 << 4) ? 0 : ctsEvent) - | (control_io->io_Status & IO_STATF_READBREAK ? breakEvent : 0)); - } - return noErr; - } - - default: - printf("WARNING: SerialStatus(): unimplemented status code %d\n", code); - return statusErr; - } -} - - -/* - * Close serial port - */ - -int16 ASERDPort::close() -{ - // Stop process - if (serial_proc) { - SetSignal(0, SIGF_SINGLE); - Signal(&serial_proc->pr_Task, SIGBREAKF_CTRL_C); - Wait(SIGF_SINGLE); - } - - // Delete reply port - if (reply_port) { - DeleteMsgPort(reply_port); - reply_port = NULL; - } - return noErr; -} - - -/* - * Configure serial port with MacOS config word - */ - -bool ASERDPort::configure(uint16 config) -{ - D(bug(" configure %04lx\n", (uint32)config)); - if (is_parallel) - return true; - - // Set number of stop bits - switch (config & 0xc000) { - case stop10: - control_io->io_StopBits = 1; - break; - case stop20: - control_io->io_StopBits = 2; - break; - default: - return false; - } - - // Set parity mode - switch (config & 0x3000) { - case noParity: - control_io->io_SerFlags &= ~SERF_PARTY_ON; - break; - case oddParity: - control_io->io_SerFlags |= SERF_PARTY_ON | SERF_PARTY_ODD; - break; - case evenParity: - control_io->io_SerFlags |= SERF_PARTY_ON; - control_io->io_SerFlags &= ~SERF_PARTY_ODD; - break; - default: - return false; - } - - // Set number of data bits - switch (config & 0x0c00) { - case data5: - control_io->io_ReadLen = control_io->io_WriteLen = 5; - break; - case data6: - control_io->io_ReadLen = control_io->io_WriteLen = 6; - break; - case data7: - control_io->io_ReadLen = control_io->io_WriteLen = 7; - break; - case data8: - control_io->io_ReadLen = control_io->io_WriteLen = 8; - break; - } - - // Set baud rate - control_io->io_Baud = 115200 / ((config & 0x03ff) + 2); - return set_params(); -} - - -/* - * Set serial handshaking - */ - -void ASERDPort::set_handshake(uint32 s, bool with_dtr) -{ - D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n", - ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3), - ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7))); - - err_mask = ReadMacInt8(s + shkErrs); - - if (is_parallel) { - - // Parallel handshake - if (with_dtr) { - if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) - ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE; - else - ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE; - } else { - if (ReadMacInt8(s + shkFCTS)) - ((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE; - else - ((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE; - } - set_par_params(); - - } else { - - // Serial handshake - if (ReadMacInt8(s + shkFXOn) || ReadMacInt8(s + shkFInX)) - control_io->io_SerFlags &= ~SERF_XDISABLED; - else - control_io->io_SerFlags |= SERF_XDISABLED; - - if (with_dtr) { - if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) - control_io->io_SerFlags |= SERF_7WIRE; - else - control_io->io_SerFlags &= ~SERF_7WIRE; - } else { - if (ReadMacInt8(s + shkFCTS)) - control_io->io_SerFlags |= SERF_7WIRE; - else - control_io->io_SerFlags &= ~SERF_7WIRE; - } - control_io->io_CtlChar = ReadMacInt16(s + shkXOn) << 16; - set_params(); - } -} - - -/* - * Send message to serial process - */ - -void ASERDPort::send_to_proc(uint32 what, uint32 pb) -{ - D(bug("sending %08lx to serial_proc\n", what)); - SerMessage msg(what, reply_port); - msg.pb = pb; - PutMsg(proc_port, &msg); - WaitPort(reply_port); - GetMsg(reply_port); - D(bug(" sent\n")); -} - - -/* - * Query serial port status - */ - -bool ASERDPort::query(void) -{ - send_to_proc(MSG_QUERY); - return control_io->IOSer.io_Error == 0; -} - - -/* - * Set serial parameters - */ - -bool ASERDPort::set_params(void) -{ - // Set/clear RadBoogie - UBYTE flags = control_io->io_SerFlags; - if (!(flags & SERF_PARTY_ON) && (flags & SERF_XDISABLED) && control_io->io_ReadLen == 8) - control_io->io_SerFlags |= SERF_RAD_BOOGIE; - else - control_io->io_SerFlags &= ~SERF_RAD_BOOGIE; - - // Send message to serial process - send_to_proc(MSG_SET_PARAMS); - return control_io->IOSer.io_Error == 0; -} - - -/* - * Set parallel parameters - */ - -bool ASERDPort::set_par_params(void) -{ - send_to_proc(MSG_SET_PAR_PARAMS); - return control_io->IOSer.io_Error == 0; -} - - -/* - * Convert AmigaOS error code to MacOS error code, set serdtResult and cum_errors - */ - -void ASERDPort::conv_error(struct IOExtSer *io, uint32 dt) -{ - int16 oserr; - uint8 cum; - - BYTE err = io->IOSer.io_Error; - if (err == 0 || err == IOERR_NOCMD) { - oserr = 0; - cum = 0; - } else { - if (is_parallel) { - oserr = (err_mask & framingErr) ? rcvrErr : 0; - cum = framingErr; - } else { - switch (io->IOSer.io_Error) { - case SerErr_DetectedBreak: - oserr = breakRecd; - cum = breakErr; - break; - case SerErr_ParityErr: - oserr = (err_mask & parityErr) ? rcvrErr : 0; - cum = parityErr; - break; - case SerErr_BufOverflow: - oserr = (err_mask & swOverrunErr) ? rcvrErr : 0; - cum = swOverrunErr; - break; - case SerErr_LineErr: - oserr = (err_mask & hwOverrunErr) ? rcvrErr : 0; - cum = hwOverrunErr; - break; - default: - oserr = (err_mask & framingErr) ? rcvrErr : 0; - cum = framingErr; - break; - } - } - } - - WriteMacInt32(dt + serdtResult, oserr); - cum_errors |= cum; -} - - -/* - * Process for communication with the serial.device - */ - -__saveds void ASERDPort::serial_func(void) -{ - struct ASERDPort *obj = (ASERDPort *)proc_arg; - struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL; - struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL; - uint8 orig_params[sizeof(struct IOExtSer)]; - bool opened = false; - ULONG io_mask = 0, proc_port_mask = 0; - - // Default: error occured - obj->proc_error = true; - - // Create message port for communication with main task - proc_port = CreateMsgPort(); - if (proc_port == NULL) - goto quit; - proc_port_mask = 1 << proc_port->mp_SigBit; - - // Create message ports for serial.device I/O - io_port = CreateMsgPort(); - if (io_port == NULL) - goto quit; - io_mask = 1 << io_port->mp_SigBit; - control_port = CreateMsgPort(); - if (control_port == NULL) - goto quit; - - // Create IORequests - read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer)); - write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer)); - control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer)); - if (read_io == NULL || write_io == NULL || control_io == NULL) - goto quit; - read_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug - write_io->IOSer.io_Message.mn_Node.ln_Type = 0; - control_io->IOSer.io_Message.mn_Node.ln_Type = 0; - - // Parse device name - char dev_name[256]; - ULONG dev_unit; - if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2) - goto quit; - - // Open device - if (obj->is_parallel) - ((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED; - else - read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE; - if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL) - goto quit; - opened = true; - - // Copy IORequests - memcpy(write_io, read_io, sizeof(struct IOExtSer)); - memcpy(control_io, read_io, sizeof(struct IOExtSer)); - - // Attach control_io to control_port and set default values - control_io->IOSer.io_Message.mn_ReplyPort = control_port; - if (!obj->is_parallel) { - control_io->io_CtlChar = SER_DEFAULT_CTLCHAR; - control_io->io_RBufLen = 64; - control_io->io_ExtFlags = 0; - control_io->io_Baud = 9600; - control_io->io_BrkTime = 250000; - control_io->io_ReadLen = control_io->io_WriteLen = 8; - control_io->io_StopBits = 1; - control_io->io_SerFlags = SERF_SHARED; - control_io->IOSer.io_Command = SDCMD_SETPARAMS; - DoIO((struct IORequest *)control_io); - memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); - } - - // Initialization went well, inform main task - obj->proc_port = proc_port; - obj->control_io = control_io; - obj->proc_error = false; - Signal(MainTask, SIGF_SINGLE); - - // Main loop - for (;;) { - - // Wait for I/O and messages (CTRL_C is used for quitting the task) - ULONG sig = Wait(proc_port_mask | io_mask | SIGBREAKF_CTRL_C); - - // Main task wants to quit us - if (sig & SIGBREAKF_CTRL_C) - break; - - // Main task sent a command to us - if (sig & proc_port_mask) { - struct SerMessage *msg; - while (msg = (SerMessage *)GetMsg(proc_port)) { - D(bug("serial_proc received %08lx\n", msg->what)); - switch (msg->what) { - case MSG_QUERY: - control_io->IOSer.io_Command = SDCMD_QUERY; - DoIO((struct IORequest *)control_io); - D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual)); - break; - - case MSG_SET_PARAMS: - // Only send SDCMD_SETPARAMS when configuration has changed - if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) { - memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); - memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); - memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); - control_io->IOSer.io_Command = SDCMD_SETPARAMS; - D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76))); - DoIO((struct IORequest *)control_io); - D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error)); - } - break; - - case MSG_SET_PAR_PARAMS: - control_io->IOSer.io_Command = PDCMD_SETPARAMS; - DoIO((struct IORequest *)control_io); - D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error)); - break; - - case MSG_BREAK: - control_io->IOSer.io_Command = SDCMD_BREAK; - DoIO((struct IORequest *)control_io); - D(bug(" break returned %08lx\n", control_io->IOSer.io_Error)); - break; - - case MSG_RESET: - control_io->IOSer.io_Command = CMD_RESET; - DoIO((struct IORequest *)control_io); - D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error)); - break; - - case MSG_KILL_IO: - AbortIO((struct IORequest *)read_io); - AbortIO((struct IORequest *)write_io); - WaitIO((struct IORequest *)read_io); - WaitIO((struct IORequest *)write_io); - obj->read_pending = obj->write_pending = false; - obj->read_done = obj->write_done = false; - break; - - case MSG_PRIME_IN: - read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb; - read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); - read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount); - read_io->IOSer.io_Actual = 0; - read_io->IOSer.io_Command = CMD_READ; - D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data)); - SendIO((struct IORequest *)read_io); - break; - - case MSG_PRIME_OUT: { - write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb; - write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); - write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount); - write_io->IOSer.io_Actual = 0; - write_io->IOSer.io_Command = CMD_WRITE; - D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data)); -#if MONITOR - bug("Sending serial data:\n"); - uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); - for (int i=0; iIOSer.io_Actual, read_io->IOSer.io_Error)); - uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name; -#if MONITOR - bug("Receiving serial data:\n"); - uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); - for (int i=0; iIOSer.io_Actual; i++) { - bug("%02lx ", adr[i]); - } - bug("\n"); -#endif - WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual); - obj->conv_error(read_io, obj->input_dt); - obj->read_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } else if (io == write_io) { - D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error)); - uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name; - WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual); - obj->conv_error(write_io, obj->output_dt); - obj->write_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - } - } -quit: - - // Close everything - if (opened) { - if (CheckIO((struct IORequest *)write_io) == 0) { - AbortIO((struct IORequest *)write_io); - WaitIO((struct IORequest *)write_io); - } - if (CheckIO((struct IORequest *)read_io) == 0) { - AbortIO((struct IORequest *)read_io); - WaitIO((struct IORequest *)read_io); - } - CloseDevice((struct IORequest *)read_io); - } - if (control_io) - DeleteIORequest(control_io); - if (write_io) - DeleteIORequest(write_io); - if (read_io) - DeleteIORequest(read_io); - if (control_port) - DeleteMsgPort(control_port); - if (io_port) - DeleteMsgPort(io_port); - - // Send signal to main task to confirm termination - Forbid(); - Signal(MainTask, SIGF_SINGLE); -} diff --git a/BasiliskII/src/AmigaOS/sys_amiga.cpp b/BasiliskII/src/AmigaOS/sys_amiga.cpp deleted file mode 100644 index 617df7b0..00000000 --- a/BasiliskII/src/AmigaOS/sys_amiga.cpp +++ /dev/null @@ -1,1122 +0,0 @@ -/* - * sys_amiga.cpp - System dependent routines, Amiga implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "user_strings.h" -#include "sys.h" - -#define DEBUG 0 -#include "debug.h" - - -// File handles are pointers to these structures -struct file_handle { - bool is_file; // Flag: plain file or /dev/something? - bool read_only; // Copy of Sys_open() flag - loff_t start_byte; // Size of file header (if any) - loff_t size; // Size of file/device (minus header) - - BPTR f; // AmigaDOS file handle (if is_file == true) - - struct IOStdReq *io; // Pointer to IORequest (if is_file == false) - ULONG block_size; // Block size of device (must be a power of two) - bool is_nsd; // New style device? - bool does_64bit; // Supports 64 bit trackdisk commands? - bool is_ejected; // Volume has been (logically) ejected - bool is_2060scsi; // Enable workaround for 2060scsi.device CD-ROM TD_READ bug -}; - - -// FileInfoBlock (must be global because it has to be on a longword boundary) -static struct FileInfoBlock FIB; - -// Message port for device communication -static struct MsgPort *the_port = NULL; - -// Temporary buffer in chip memory -const int TMP_BUF_SIZE = 0x10000; -static UBYTE *tmp_buf = NULL; - - -/* - * Initialization - */ - -void SysInit(void) -{ - // Create port and temporary buffer - the_port = CreateMsgPort(); - tmp_buf = (UBYTE *)AllocMem(TMP_BUF_SIZE, MEMF_CHIP | MEMF_PUBLIC); - if (the_port == NULL || tmp_buf == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } -} - - -/* - * Deinitialization - */ - -void SysExit(void) -{ - // Delete port and temporary buffer - if (the_port) { - DeleteMsgPort(the_port); - the_port = NULL; - } - if (tmp_buf) { - FreeMem(tmp_buf, TMP_BUF_SIZE); - tmp_buf = NULL; - } -} - - -/* - * This gets called when no "floppy" prefs items are found - * It scans for available floppy drives and adds appropriate prefs items - */ - -void SysAddFloppyPrefs(void) -{ - for (int i=0; i<4; i++) { - ULONG id = GetUnitID(i); - if (id == DRT_150RPM) { // We need an HD drive - char str[256]; - sprintf(str, "/dev/mfm.device/%d/0/0/2880/512", i); - PrefsAddString("floppy", str); - } - } -} - - -/* - * This gets called when no "disk" prefs items are found - * It scans for available HFS volumes and adds appropriate prefs items - */ - -void SysAddDiskPrefs(void) -{ - // AmigaOS doesn't support MacOS partitioning, so this probably doesn't make much sense... -} - - -/* - * This gets called when no "cdrom" prefs items are found - * It scans for available CD-ROM drives and adds appropriate prefs items - */ - -void SysAddCDROMPrefs(void) -{ - // Don't scan for drives if nocdrom option given - if (PrefsFindBool("nocdrom")) - return; - - //!! -} - - -/* - * Add default serial prefs (must be added, even if no ports present) - */ - -void SysAddSerialPrefs(void) -{ - PrefsAddString("seriala", "serial.device/0"); - PrefsAddString("serialb", "*parallel.device/0"); -} - - -/* - * Open file/device, create new file handle (returns NULL on error) - * - * Format for device names: /dev////// - */ - -void *Sys_open(const char *name, bool read_only) -{ - bool is_file = (strstr(name, "/dev/") != name); - - D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write")); - - // File or device? - if (is_file) { - - // File, open it and get stats - BPTR f = Open((char *)name, MODE_OLDFILE); - if (!f) - return NULL; - if (!ExamineFH(f, &FIB)) { - Close(f); - return NULL; - } - - // Check if file is write protected - if (FIB.fib_Protection & FIBF_WRITE) - read_only = true; - - // Create file_handle - file_handle *fh = new file_handle; - fh->f = f; - fh->is_file = true; - fh->read_only = read_only; - - // Detect disk image file layout - loff_t size = FIB.fib_Size; - Seek(fh->f, 0, OFFSET_BEGINNING); - Read(fh->f, tmp_buf, 256); - FileDiskLayout(size, tmp_buf, fh->start_byte, fh->size); - return fh; - - } else { - - // Device, parse string - char dev_name[256]; - ULONG dev_unit = 0, dev_flags = 0, dev_start = 0, dev_size = 16, dev_bsize = 512; - if (sscanf(name, "/dev/%[^/]/%ld/%ld/%ld/%ld/%ld", dev_name, &dev_unit, &dev_flags, &dev_start, &dev_size, &dev_bsize) < 2) - return NULL; - - // Create IORequest - struct IOStdReq *io = (struct IOStdReq *)CreateIORequest(the_port, sizeof(struct IOExtTD)); - if (io == NULL) - return NULL; - - // Open device - if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)io, dev_flags)) { - D(bug(" couldn't open device\n")); - DeleteIORequest(io); - return NULL; - } - - // Check for new style device - bool is_nsd = false, does_64bit = false; - struct NSDeviceQueryResult nsdqr; - nsdqr.DevQueryFormat = 0; - nsdqr.SizeAvailable = 0; - io->io_Command = NSCMD_DEVICEQUERY; - io->io_Length = sizeof(nsdqr); - io->io_Data = (APTR)&nsdqr; - LONG error = DoIO((struct IORequest *)io); - D(bug("DEVICEQUERY returned %ld (length %ld, actual %ld)\n", error, io->io_Length, io->io_Actual)); - if ((!error) && (io->io_Actual >= 16) && (io->io_Actual <= sizeof(nsdqr)) && (nsdqr.SizeAvailable == io->io_Actual)) { - - // Looks like an NSD - is_nsd = true; - D(bug(" new style device, type %ld\n", nsdqr.DeviceType)); - - // We only work with trackdisk-like devices - if (nsdqr.DeviceType != NSDEVTYPE_TRACKDISK) { - CloseDevice((struct IORequest *)io); - DeleteIORequest(io); - return NULL; - } - - // Check whether device is 64 bit capable - UWORD *cmdcheck; - for (cmdcheck = nsdqr.SupportedCommands; *cmdcheck; cmdcheck++) { - if (*cmdcheck == NSCMD_TD_READ64) { - D(bug(" supports 64 bit commands\n")); - does_64bit = true; - } - } - } - - // Create file_handle - file_handle *fh = new file_handle; - fh->io = io; - fh->is_file = false; - fh->read_only = read_only; - fh->start_byte = (loff_t)dev_start * dev_bsize; - fh->size = (loff_t)dev_size * dev_bsize; - fh->block_size = dev_bsize; - fh->is_nsd = is_nsd; - fh->does_64bit = does_64bit; - fh->is_ejected = false; - fh->is_2060scsi = (strcmp(dev_name, "2060scsi.device") == 0); - return fh; - } -} - - -/* - * Close file/device, delete file handle - */ - -void Sys_close(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - D(bug("Sys_close(%08lx)\n", arg)); - - // File or device? - if (fh->is_file) { - - // File, simply close it - Close(fh->f); - - } else { - - // Device, close it and delete IORequest - fh->io->io_Command = CMD_UPDATE; - DoIO((struct IORequest *)fh->io); - - fh->io->io_Command = TD_MOTOR; - fh->io->io_Length = 0; - DoIO((struct IORequest *)fh->io); - - CloseDevice((struct IORequest *)fh->io); - DeleteIORequest(fh->io); - } - delete fh; -} - - -/* - * Send one I/O request, using 64-bit addressing if the device supports it - */ - -static loff_t send_io_request(file_handle *fh, bool writing, ULONG length, loff_t offset, APTR data) -{ - if (fh->does_64bit) { - fh->io->io_Command = writing ? NSCMD_TD_WRITE64 : NSCMD_TD_READ64; - fh->io->io_Actual = offset >> 32; - } else { - fh->io->io_Command = writing ? CMD_WRITE : CMD_READ; - fh->io->io_Actual = 0; - } - fh->io->io_Length = length; - fh->io->io_Offset = offset; - fh->io->io_Data = data; - - if (fh->is_2060scsi && fh->block_size == 2048) { - - // 2060scsi.device has serious problems reading CD-ROMs via TD_READ - static struct SCSICmd scsi; - const int SENSE_LENGTH = 256; - static UBYTE sense_buffer[SENSE_LENGTH]; // Buffer for autosense data - static UBYTE cmd_buffer[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - D(bug("send_io_request length=%lu offset=%lu\n", length, (ULONG) offset)); - - memset(sense_buffer, 0, sizeof(sense_buffer)); - - scsi.scsi_Command = cmd_buffer; - scsi.scsi_CmdLength = sizeof(cmd_buffer); - scsi.scsi_SenseData = sense_buffer; - scsi.scsi_SenseLength = SENSE_LENGTH; - scsi.scsi_Flags = SCSIF_AUTOSENSE | (writing ? SCSIF_WRITE : SCSIF_READ); - scsi.scsi_Data = (UWORD *) data; - scsi.scsi_Length = length; - - ULONG block_offset = (ULONG) offset / fh->block_size; - ULONG block_length = length / fh->block_size; - - cmd_buffer[2] = block_offset >> 24; - cmd_buffer[3] = block_offset >> 16; - cmd_buffer[4] = block_offset >> 8; - cmd_buffer[5] = block_offset & 0xff; - - cmd_buffer[7] = block_length >> 8; - cmd_buffer[8] = block_length & 0xff; - - fh->io->io_Command = HD_SCSICMD; - fh->io->io_Actual = 0; - fh->io->io_Offset = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - - BYTE result = DoIO((struct IORequest *)fh->io); - - if (result) { - D(bug("send_io_request SCSI FAIL result=%lu\n", result)); - - if (result == HFERR_BadStatus) { - D(bug("send_io_request SCSI Status=%lu\n", scsi.scsi_Status)); - if (scsi.scsi_Status == 2) { - D(bug("send_io_request Sense Key=%02lx\n", sense_buffer[2] & 0x0f)); - D(bug("send_io_request ASC=%02lx ASCQ=%02lx\n", sense_buffer[12], sense_buffer[13])); - } - } - return 0; - } - - D(bug("send_io_request SCSI Actual=%lu\n", scsi.scsi_Actual)); - - if (scsi.scsi_Actual != length) - return 0; - - return scsi.scsi_Actual; - - } else { - -// if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length) - if (DoIO((struct IORequest *)fh->io)) - { - D(bug("send_io_request/%ld: Actual=%lu length=%lu Err=%ld\n", __LINE__, fh->io->io_Actual, length, fh->io->io_Error)); - return 0; - } - return fh->io->io_Actual; - } -} - - -/* - * Read "length" bytes from file/device, starting at "offset", to "buffer", - * returns number of bytes read (or 0) - */ - -size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - { - D(bug("Sys_read/%ld return 0\n", __LINE__)); - return 0; - } - - D(bug("Sys_read/%ld length=%ld\n", __LINE__, length)); - - // File or device? - if (fh->is_file) { - - // File, seek to position - if (Seek(fh->f, offset + fh->start_byte, OFFSET_BEGINNING) == -1) - { - D(bug("Sys_read/%ld return 0\n", __LINE__)); - return 0; - } - - // Read data - LONG actual = Read(fh->f, buffer, length); - if (actual == -1) - { - D(bug("Sys_read/%ld return 0\n", __LINE__)); - return 0; - } - else - { - D(bug("Sys_read/%ld return %ld\n", __LINE__, actual)); - return actual; - } - - } else { - - // Device, pre-read (partial read of first block) necessary? - loff_t pos = offset + fh->start_byte; - size_t actual = 0; - uint32 pre_offset = pos % fh->block_size; - if (pre_offset) { - - // Yes, read one block - if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0) - { - D(bug("Sys_read/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Copy data to destination buffer - size_t pre_length = fh->block_size - pre_offset; - if (pre_length > length) - pre_length = length; - memcpy(buffer, tmp_buf + pre_offset, pre_length); - - // Adjust data pointers - buffer = (uint8 *)buffer + pre_length; - pos += pre_length; - length -= pre_length; - actual += pre_length; - } - - // Main read (complete reads of middle blocks) possible? - if (length >= fh->block_size) { - - // Yes, read blocks - size_t main_length = length & ~(fh->block_size - 1); - if (send_io_request(fh, false, main_length, pos, buffer) == 0) - { - D(bug("Sys_read/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Adjust data pointers - buffer = (uint8 *)buffer + main_length; - pos += main_length; - length -= main_length; - actual += main_length; - } - - // Post-read (partial read of last block) necessary? - if (length) { - - // Yes, read one block - if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0) - { - D(bug("Sys_read/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Copy data to destination buffer - memcpy(buffer, tmp_buf, length); - actual += length; - } - - D(bug("Sys_read/%ld return %ld\n", __LINE__, actual)); - return actual; - } -} - - -/* - * Write "length" bytes from "buffer" to file/device, starting at "offset", - * returns number of bytes written (or 0) - */ - -size_t Sys_write(void *arg, void *buffer, loff_t offset, size_t length) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - D(bug("Sys_write/%ld length=%ld\n", __LINE__, length)); - - // File or device? - if (fh->is_file) { - - // File, seek to position if necessary - if (Seek(fh->f, offset + fh->start_byte, OFFSET_BEGINNING) == -1) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Write data - LONG actual = Write(fh->f, buffer, length); - if (actual == -1) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - else - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, actual)); - return actual; - } - - } else { - - // Device, pre-write (partial write of first block) necessary - loff_t pos = offset + fh->start_byte; - size_t actual = 0; - uint32 pre_offset = pos % fh->block_size; - if (pre_offset) { - - // Yes, read one block - if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Copy data from source buffer - size_t pre_length = fh->block_size - pre_offset; - if (pre_length > length) - pre_length = length; - memcpy(tmp_buf + pre_offset, buffer, pre_length); - - // Write block back - if (send_io_request(fh, true, fh->block_size, pos - pre_offset, tmp_buf) == 0) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Adjust data pointers - buffer = (uint8 *)buffer + pre_length; - pos += pre_length; - length -= pre_length; - actual += pre_length; - } - - // Main write (complete writes of middle blocks) possible? - if (length >= fh->block_size) { - - // Yes, write blocks - size_t main_length = length & ~(fh->block_size - 1); - if (send_io_request(fh, true, main_length, pos, buffer) == 0) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Adjust data pointers - buffer = (uint8 *)buffer + main_length; - pos += main_length; - length -= main_length; - actual += main_length; - } - - // Post-write (partial write of last block) necessary? - if (length) { - - // Yes, read one block - if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - - // Copy data from source buffer - memcpy(buffer, tmp_buf, length); - - // Write block back - if (send_io_request(fh, true, fh->block_size, pos, tmp_buf) == 0) - { - D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); - return 0; - } - actual += length; - } - - D(bug("Sys_write/%ld return %ld\n", __LINE__, actual)); - return actual; - } -} - - -/* - * Return size of file/device (minus header) - */ - -loff_t SysGetFileSize(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - return fh->size; -} - - -/* - * Eject volume (if applicable) - */ - -void SysEject(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) { - - // Flush buffer, turn off the drive motor and eject volume - fh->io->io_Command = CMD_UPDATE; - DoIO((struct IORequest *)fh->io); - - fh->io->io_Command = TD_MOTOR; - fh->io->io_Length = 0; - DoIO((struct IORequest *)fh->io); - - fh->io->io_Command = TD_EJECT; - fh->io->io_Length = 1; - DoIO((struct IORequest *)fh->io); - - fh->is_ejected = true; - } -} - - -/* - * Format volume (if applicable) - */ - -bool SysFormat(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - //!! - return true; -} - - -/* - * Check if file/device is read-only (this includes the read-only flag on Sys_open()) - */ - -bool SysIsReadOnly(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (fh->is_file) { - - // File, return flag given to Sys_open - return fh->read_only; - - } else { - - // Device, check write protection - fh->io->io_Command = TD_PROTSTATUS; - DoIO((struct IORequest *)fh->io); - if (fh->io->io_Actual) - return true; - else - return fh->read_only; - } -} - - -/* - * Check if the given file handle refers to a fixed or a removable disk - */ - -bool SysIsFixedDisk(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - return true; -} - - -/* - * Check if a disk is inserted in the drive (always true for files) - */ - -bool SysIsDiskInserted(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return true; - else { - - // Check medium status - fh->io->io_Command = TD_CHANGESTATE; - fh->io->io_Actual = 0; - DoIO((struct IORequest *)fh->io); - bool inserted = (fh->io->io_Actual == 0); - - if (!inserted) { - // Disk was ejected and has now been taken out - fh->is_ejected = false; - } - - if (fh->is_ejected) { - // Disk was ejected but has not yet been taken out, report it as - // no longer in the drive - return false; - } else - return inserted; - } -} - - -/* - * Prevent medium removal (if applicable) - */ - -void SysPreventRemoval(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) { - - // Send PREVENT ALLOW MEDIUM REMOVAL SCSI command - struct SCSICmd scsi; - static const UBYTE the_cmd[6] = {0x1e, 0, 0, 0, 1, 0}; - scsi.scsi_Length = 0; - scsi.scsi_Command = (UBYTE *)the_cmd; - scsi.scsi_CmdLength = 6; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - DoIO((struct IORequest *)fh->io); - } -} - - -/* - * Allow medium removal (if applicable) - */ - -void SysAllowRemoval(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) { - - // Send PREVENT ALLOW MEDIUM REMOVAL SCSI command - struct SCSICmd scsi; - static const UBYTE the_cmd[6] = {0x1e, 0, 0, 0, 0, 0}; - scsi.scsi_Length = 0; - scsi.scsi_Command = (UBYTE *)the_cmd; - scsi.scsi_CmdLength = 6; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - DoIO((struct IORequest *)fh->io); - } -} - - -/* - * Read CD-ROM TOC (binary MSF format, 804 bytes max.) - */ - -bool SysCDReadTOC(void *arg, uint8 *toc) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return false; - else { - - // Send READ TOC MSF SCSI command - struct SCSICmd scsi; - static const UBYTE read_toc_cmd[10] = {0x43, 0x02, 0, 0, 0, 0, 0, 0x03, 0x24, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 804; - scsi.scsi_Command = (UBYTE *)read_toc_cmd; - scsi.scsi_CmdLength = 10; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return false; - memcpy(toc, tmp_buf, 804); - return true; - } -} - - -/* - * Read CD-ROM position data (Sub-Q Channel, 16 bytes, see SCSI standard) - */ - -bool SysCDGetPosition(void *arg, uint8 *pos) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return false; - else { - - // Send READ SUB-CHANNEL SCSI command - struct SCSICmd scsi; - static const UBYTE read_subq_cmd[10] = {0x42, 0x02, 0x40, 0x01, 0, 0, 0, 0, 0x10, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 16; - scsi.scsi_Command = (UBYTE *)read_subq_cmd; - scsi.scsi_CmdLength = 10; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return false; - memcpy(pos, tmp_buf, 16); - return true; - } -} - - -/* - * Play CD audio - */ - -bool SysCDPlay(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, uint8 end_m, uint8 end_s, uint8 end_f) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return false; - else { - - // Send PLAY AUDIO MSF SCSI command - struct SCSICmd scsi; - UBYTE play_cmd[10] = {0x47, 0, 0, start_m, start_s, start_f, end_m, end_s, end_f, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 0; - scsi.scsi_Command = play_cmd; - scsi.scsi_CmdLength = 10; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return false; - return true; - } -} - - -/* - * Pause CD audio - */ - -bool SysCDPause(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return false; - else { - - // Send PAUSE RESUME SCSI command - struct SCSICmd scsi; - static const UBYTE pause_cmd[10] = {0x4b, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 0; - scsi.scsi_Command = (UBYTE *)pause_cmd; - scsi.scsi_CmdLength = 10; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return false; - return true; - } -} - - -/* - * Resume paused CD audio - */ - -bool SysCDResume(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return false; - else { - - // Send PAUSE RESUME SCSI command - struct SCSICmd scsi; - static const UBYTE resume_cmd[10] = {0x4b, 0, 0, 0, 0, 0, 0, 0, 1, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 0; - scsi.scsi_Command = (UBYTE *)resume_cmd; - scsi.scsi_CmdLength = 10; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return false; - return true; - } -} - - -/* - * Stop CD audio - */ - -bool SysCDStop(void *arg, uint8 lead_out_m, uint8 lead_out_s, uint8 lead_out_f) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return false; - else { - - uint8 end_m = lead_out_m; - uint8 end_s = lead_out_s; - uint8 end_f = lead_out_f + 1; - if (end_f >= 75) { - end_f = 0; - end_s++; - if (end_s >= 60) { - end_s = 0; - end_m++; - } - } - - // Send PLAY AUDIO MSF SCSI command (play first frame of lead-out area) - struct SCSICmd scsi; - UBYTE play_cmd[10] = {0x47, 0, 0, lead_out_m, lead_out_s, lead_out_f, end_m, end_s, end_f, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 0; - scsi.scsi_Command = play_cmd; - scsi.scsi_CmdLength = 10; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return false; - return true; - } -} - - -/* - * Perform CD audio fast-forward/fast-reverse operation starting from specified address - */ - -bool SysCDScan(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, bool reverse) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - //!! - return false; -} - - -/* - * Set CD audio volume (0..255 each channel) - */ - -void SysCDSetVolume(void *arg, uint8 left, uint8 right) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) { - - // Send MODE SENSE (CD-ROM Audio Control Parameters Page) SCSI command - struct SCSICmd scsi; - static const UBYTE mode_sense_cmd[6] = {0x1a, 0x08, 0x0e, 0, 20, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 20; - scsi.scsi_Command = (UBYTE *)mode_sense_cmd; - scsi.scsi_CmdLength = 6; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return; - - tmp_buf[6] = 0x04; // Immed - tmp_buf[9] = 0; // LBA/sec format - tmp_buf[10] = 0; // LBA/sec - tmp_buf[11] = 0; - tmp_buf[13] = left; // Port 0 volume - tmp_buf[15] = right; // Port 1 volume - - // Send MODE SELECT (CD-ROM Audio Control Parameters Page) SCSI command - static const UBYTE mode_select_cmd[6] = {0x15, 0x10, 0, 0, 20, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 20; - scsi.scsi_Command = (UBYTE *)mode_select_cmd; - scsi.scsi_CmdLength = 6; - scsi.scsi_Flags = SCSIF_WRITE; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - DoIO((struct IORequest *)fh->io); - } -} - - -/* - * Get CD audio volume (0..255 each channel) - */ - -void SysCDGetVolume(void *arg, uint8 &left, uint8 &right) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) { - - // Send MODE SENSE (CD-ROM Audio Control Parameters Page) SCSI command - struct SCSICmd scsi; - static const UBYTE mode_sense_cmd[6] = {0x1a, 0x08, 0x0e, 0, 20, 0}; - scsi.scsi_Data = (UWORD *)tmp_buf; - scsi.scsi_Length = 20; - scsi.scsi_Command = (UBYTE *)mode_sense_cmd; - scsi.scsi_CmdLength = 6; - scsi.scsi_Flags = SCSIF_READ; - scsi.scsi_Status = 0; - fh->io->io_Data = &scsi; - fh->io->io_Length = sizeof(scsi); - fh->io->io_Command = HD_SCSICMD; - if (DoIO((struct IORequest *)fh->io) || scsi.scsi_Status) - return; - left = tmp_buf[13]; // Port 0 volume - right = tmp_buf[15]; // Port 1 volume - } -} diff --git a/BasiliskII/src/AmigaOS/sysdeps.h b/BasiliskII/src/AmigaOS/sysdeps.h deleted file mode 100644 index 89505830..00000000 --- a/BasiliskII/src/AmigaOS/sysdeps.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * sysdeps.h - System dependent definitions for AmigaOS - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -#include -#include -#include -#include -#include -#include -#include - -#include "user_strings_amiga.h" - -// Mac and host address space are the same -#define REAL_ADDRESSING 1 - -// Using 68k natively -#define EMULATED_68K 0 - -// Mac ROM is not write protected -#define ROM_IS_WRITE_PROTECTED 0 -#define USE_SCRATCHMEM_SUBTERFUGE 1 - -// ExtFS is supported -#define SUPPORTS_EXTFS 1 - -// mon is not supported -#undef ENABLE_MON - -// Data types -typedef unsigned char uint8; -typedef signed char int8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned long uint32; -typedef signed long int32; -typedef unsigned long long uint64; -typedef signed long long int64; - -typedef unsigned long long loff_t; - -// Time data type for Time Manager emulation -typedef struct timeval tm_time_t; - -// Endianess conversion (not needed) -#define ntohs(x) (x) -#define ntohl(x) (x) -#define htons(x) (x) -#define htonl(x) (x) - -// Some systems don't define this (ExecBase->AttnFlags) -#ifndef AFF_68060 -#define AFF_68060 (1L<<7) -#endif - -#endif diff --git a/BasiliskII/src/AmigaOS/timer_amiga.cpp b/BasiliskII/src/AmigaOS/timer_amiga.cpp deleted file mode 100644 index ce5fd515..00000000 --- a/BasiliskII/src/AmigaOS/timer_amiga.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * timer_amiga.cpp - Time Manager emulation, AmigaOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include - -#include "sysdeps.h" -#include "timer.h" - -#define DEBUG 0 -#include "debug.h" - - -/* - * Return microseconds since boot (64 bit) - */ - -void Microseconds(uint32 &hi, uint32 &lo) -{ - D(bug("Microseconds\n")); - struct timeval tv; - GetSysTime(&tv); - uint64 tl = (uint64)tv.tv_secs * 1000000 + tv.tv_micro; - hi = tl >> 32; - lo = tl; -} - - -/* - * Return local date/time in Mac format (seconds since 1.1.1904) - */ - -uint32 TimerDateTime(void) -{ - ULONG secs, mics; - CurrentTime(&secs, &mics); - return secs + 0x8b31ef80; -} - - -/* - * Get current time - */ - -void timer_current_time(tm_time_t &t) -{ - GetSysTime(&t); -} - - -/* - * Add times - */ - -void timer_add_time(tm_time_t &res, tm_time_t a, tm_time_t b) -{ - res = a; - AddTime(&res, &b); -} - - -/* - * Subtract times - */ - -void timer_sub_time(tm_time_t &res, tm_time_t a, tm_time_t b) -{ - res = a; - SubTime(&res, &b); -} - - -/* - * Compare times (<0: a < b, =0: a = b, >0: a > b) - */ - -int timer_cmp_time(tm_time_t a, tm_time_t b) -{ - return CmpTime(&b, &a); -} - - -/* - * Convert Mac time value (>0: microseconds, <0: microseconds) to tm_time_t - */ - -void timer_mac2host_time(tm_time_t &res, int32 mactime) -{ - if (mactime > 0) { - res.tv_secs = mactime / 1000; // Time in milliseconds - res.tv_micro = (mactime % 1000) * 1000; - } else { - res.tv_secs = -mactime / 1000000; // Time in negative microseconds - res.tv_micro = -mactime % 1000000; - } -} - - -/* - * Convert positive tm_time_t to Mac time value (>0: microseconds, <0: microseconds) - * A negative input value for hosttime results in a zero return value - * As long as the microseconds value fits in 32 bit, it must not be converted to milliseconds! - */ - -int32 timer_host2mac_time(tm_time_t hosttime) -{ - if (hosttime.tv_secs < 0) - return 0; - else { - uint64 t = (uint64)hosttime.tv_secs * 1000000 + hosttime.tv_micro; - if (t > 0x7fffffff) - return t / 1000; // Time in milliseconds - else - return -t; // Time in negative microseconds - } -} - - -/* - * Suspend emulator thread, virtual CPU in idle mode - */ - -void idle_wait(void) -{ - // XXX if you implement this make sure to call idle_resume() from TriggerInterrupt() -} - - -/* - * Resume execution of emulator thread, events just arrived - */ - -void idle_resume(void) -{ -} diff --git a/BasiliskII/src/AmigaOS/user_strings_amiga.cpp b/BasiliskII/src/AmigaOS/user_strings_amiga.cpp deleted file mode 100644 index 5b41a587..00000000 --- a/BasiliskII/src/AmigaOS/user_strings_amiga.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * user_strings_amiga.cpp - AmigaOS-specific localizable strings - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "user_strings.h" - - -// Platform-specific string definitions -user_string_def platform_strings[] = { - // Common strings that have a platform-specific variant - {STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under AmigaOS. Basilisk II will try to unmount it."}, - {STR_EXTFS_CTRL, "Amiga Root"}, - {STR_EXTFS_NAME, "Amiga Directory Tree"}, - {STR_EXTFS_VOLUME_NAME, "Amiga"}, - - // Purely platform-specific strings - {STR_NO_PREPARE_EMUL_ERR, "PrepareEmul is not installed. Run PrepareEmul and then try again to start Basilisk II."}, - {STR_NO_GADTOOLS_LIB_ERR, "Cannot open gadtools.library V39."}, - {STR_NO_IFFPARSE_LIB_ERR, "Cannot open iffparse.library V39."}, - {STR_NO_ASL_LIB_ERR, "Cannot open asl.library V36."}, - {STR_NO_TIMER_DEV_ERR, "Cannot open timer.device."}, - {STR_NO_P96_MODE_ERR, "The selected screen mode is not a Picasso96 or CyberGraphX mode."}, - {STR_NO_VIDEO_MODE_ERR, "Cannot obtain selected video mode."}, - {STR_WRONG_SCREEN_DEPTH_ERR, "Basilisk II only supports 8, 16 or 24 bit screens."}, - {STR_WRONG_SCREEN_FORMAT_ERR, "Basilisk II only supports big-endian chunky ARGB screen modes."}, - {STR_ENFORCER_RUNNING_ERR, "Enforcer/CyberGuard is running. Remove and then try again to start Basilisk II."}, - - {STR_NOT_ETHERNET_WARN, "The selected network device is not an Ethernet device. Networking will be disabled."}, - {STR_NO_MULTICAST_WARN, "Your Ethernet card does not support multicast and is not usable with AppleTalk. Please report this to the manufacturer of the card."}, - {STR_NO_GTLAYOUT_LIB_WARN, "Cannot open gtlayout.library V39. The preferences editor GUI will not be available."}, - {STR_NO_AHI_WARN, "Cannot open ahi.device V2. Audio output will be disabled."}, - {STR_NO_AHI_CTRL_WARN, "Cannot open AHI control structure. Audio output will be disabled."}, - {STR_NOT_ENOUGH_MEM_WARN, "Could not get %lu MBytes of memory.\nShould I use the largest Block (%lu MBytes) instead ?"}, - - {STR_AHI_MODE_CTRL, "AHI Mode"}, - {STR_SCSI_MEMTYPE_CTRL, "Buffer Memory Type"}, - {STR_MEMTYPE_CHIP_LAB, "Chip"}, - {STR_MEMTYPE_24BITDMA_LAB, "24-Bit DMA"}, - {STR_MEMTYPE_ANY_LAB, "Any"}, - {STR_SCSI_DEVICES_CTRL, "Virtual SCSI Devices"}, - - {-1, NULL} // End marker -}; - - -/* - * Fetch pointer to string, given the string number - */ - -const char *GetString(int num) -{ - // First search for platform-specific string - int i = 0; - while (platform_strings[i].num >= 0) { - if (platform_strings[i].num == num) - return platform_strings[i].str; - i++; - } - - // Not found, search for common string - i = 0; - while (common_strings[i].num >= 0) { - if (common_strings[i].num == num) - return common_strings[i].str; - i++; - } - return NULL; -} diff --git a/BasiliskII/src/AmigaOS/user_strings_amiga.h b/BasiliskII/src/AmigaOS/user_strings_amiga.h deleted file mode 100644 index 8903e5e8..00000000 --- a/BasiliskII/src/AmigaOS/user_strings_amiga.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * user_strings_amiga.h - AmigaOS-specific localizable strings - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_AMIGA_H -#define USER_STRINGS_AMIGA_H - -enum { - STR_NO_PREPARE_EMUL_ERR = 10000, - STR_NO_GADTOOLS_LIB_ERR, - STR_NO_IFFPARSE_LIB_ERR, - STR_NO_ASL_LIB_ERR, - STR_NO_TIMER_DEV_ERR, - STR_NO_P96_MODE_ERR, - STR_NO_VIDEO_MODE_ERR, - STR_WRONG_SCREEN_DEPTH_ERR, - STR_WRONG_SCREEN_FORMAT_ERR, - STR_ENFORCER_RUNNING_ERR, - - STR_NOT_ETHERNET_WARN, - STR_NO_MULTICAST_WARN, - STR_NO_GTLAYOUT_LIB_WARN, - STR_NO_AHI_WARN, - STR_NO_AHI_CTRL_WARN, - STR_NOT_ENOUGH_MEM_WARN, - - STR_AHI_MODE_CTRL, - STR_SCSI_MEMTYPE_CTRL, - STR_MEMTYPE_CHIP_LAB, - STR_MEMTYPE_24BITDMA_LAB, - STR_MEMTYPE_ANY_LAB, - STR_SCSI_DEVICES_CTRL -}; - -#endif diff --git a/BasiliskII/src/AmigaOS/video_amiga.cpp b/BasiliskII/src/AmigaOS/video_amiga.cpp deleted file mode 100644 index 5e870a9c..00000000 --- a/BasiliskII/src/AmigaOS/video_amiga.cpp +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * video_amiga.cpp - Video/graphics emulation, AmigaOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#define __USE_SYSBASE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "adb.h" -#include "prefs.h" -#include "user_strings.h" -#include "video.h" - -#define DEBUG 0 -#include "debug.h" - - -// Supported video modes -static vector VideoModes; - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_PIP, - DISPLAY_SCREEN_P96, - DISPLAY_SCREEN_CGFX -}; - -// Global variables -static int32 frame_skip; -static UWORD *null_pointer = NULL; // Blank mouse pointer data -static UWORD *current_pointer = (UWORD *)-1; // Currently visible mouse pointer data -static struct Process *periodic_proc = NULL; // Periodic process - -extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp) - - -// Amiga -> Mac raw keycode translation table -static const uint8 keycode2mac[0x80] = { - 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, 0x1a, // ` 1 2 3 4 5 6 7 - 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x2a, 0xff, 0x52, // 8 9 0 - = \ inv 0 - 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, // Q W E R T Y U I - 0x1f, 0x23, 0x21, 0x1e, 0xff, 0x53, 0x54, 0x55, // O P [ ] inv 1 2 3 - 0x00, 0x01, 0x02, 0x03, 0x05, 0x04, 0x26, 0x28, // A S D F G H J K - 0x25, 0x29, 0x27, 0x2a, 0xff, 0x56, 0x57, 0x58, // L ; ' # inv 4 5 6 - 0x32, 0x06, 0x07, 0x08, 0x09, 0x0b, 0x2d, 0x2e, // < Z X C V B N M - 0x2b, 0x2f, 0x2c, 0xff, 0x41, 0x59, 0x5b, 0x5c, // , . / inv . 7 8 9 - 0x31, 0x33, 0x30, 0x4c, 0x24, 0x35, 0x75, 0xff, // SPC BSP TAB ENT RET ESC DEL inv - 0xff, 0xff, 0x4e, 0xff, 0x3e, 0x3d, 0x3c, 0x3b, // inv inv - inv CUP CDN CRT CLF - 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, 0x62, 0x64, // F1 F2 F3 F4 F5 F6 F7 F8 - 0x65, 0x6d, 0x47, 0x51, 0x4b, 0x43, 0x45, 0x72, // F9 F10 ( ) / * + HLP - 0x38, 0x38, 0x39, 0x36, 0x3a, 0x3a, 0x37, 0x37, // SHL SHR CAP CTL ALL ALR AML AMR - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv -}; - - -class Amiga_monitor_desc : public monitor_desc { -public: - Amiga_monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id, int default_display_type) - : monitor_desc(available_modes, default_depth, default_id), display_type(default_display_type) {}; - ~Amiga_monitor_desc() {}; - - virtual void switch_to_current_mode(void); - virtual void set_palette(uint8 *pal, int num); - - bool video_open(void); - void video_close(void); -public: - int display_type; // See enum above -}; - - -/* - * Display "driver" classes - */ - -class driver_base { -public: - driver_base(Amiga_monitor_desc &m); - virtual ~driver_base(); - - virtual void set_palette(uint8 *pal, int num) {}; - virtual struct BitMap *get_bitmap() { return NULL; }; -public: - Amiga_monitor_desc &monitor; // Associated video monitor - const video_mode &mode; // Video mode handled by the driver - BOOL init_ok; // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer) - struct Window *the_win; -}; - - -class driver_window : public driver_base { -public: - driver_window(Amiga_monitor_desc &m, int width, int height); - ~driver_window(); - - struct BitMap *get_bitmap() { return the_bitmap; }; - -private: - LONG black_pen, white_pen; - struct BitMap *the_bitmap; -}; - -class driver_pip : public driver_base { -public: - driver_pip(Amiga_monitor_desc &m, int width, int height); - ~driver_pip(); - - struct BitMap *get_bitmap() { return the_bitmap; }; - -private: - struct BitMap *the_bitmap; -}; - -class driver_screen_p96 : public driver_base { -public: - driver_screen_p96(Amiga_monitor_desc &m, ULONG mode_id); - ~driver_screen_p96(); - - void set_palette(uint8 *pal, int num); - -private: - struct Screen *the_screen; -}; - -class driver_screen_cgfx : public driver_base { -public: - driver_screen_cgfx(Amiga_monitor_desc &m, ULONG mode_id); - ~driver_screen_cgfx(); - - void set_palette(uint8 *pal, int num); - -private: - struct Screen *the_screen; -}; - - -static driver_base *drv = NULL; // Pointer to currently used driver object - - - -// Prototypes -static void periodic_func(void); -static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth); -static void add_modes(uint32 width, uint32 height, video_depth depth); -static ULONG find_mode_for_depth(uint32 width, uint32 height, uint32 depth); -static ULONG bits_from_depth(video_depth depth); -static bool is_valid_modeid(int display_type, ULONG mode_id); -static bool check_modeid_p96(ULONG mode_id); -static bool check_modeid_cgfx(ULONG mode_id); - - -/* - * Initialization - */ - - -bool VideoInit(bool classic) -{ - video_depth default_depth = VDEPTH_1BIT; - int default_width, default_height; - int default_display_type = DISPLAY_WINDOW; - int window_width, window_height; // width and height for window display - ULONG screen_mode_id; // mode ID for screen display - - // Allocate blank mouse pointer data - null_pointer = (UWORD *)AllocMem(12, MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR); - if (null_pointer == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - return false; - } - - // Read frame skip prefs - frame_skip = PrefsFindInt32("frameskip"); - if (frame_skip == 0) - frame_skip = 1; - - // Get screen mode from preferences - const char *mode_str; - if (classic) - mode_str = "win/512/342"; - else - mode_str = PrefsFindString("screen"); - - default_width = window_width = 512; - default_height = window_height = 384; - - if (mode_str) { - if (sscanf(mode_str, "win/%d/%d", &window_width, &window_height) == 2) - default_display_type = DISPLAY_WINDOW; - else if (sscanf(mode_str, "pip/%d/%d", &window_width, &window_height) == 2 && P96Base) - default_display_type = DISPLAY_PIP; - else if (sscanf(mode_str, "scr/%08lx", &screen_mode_id) == 1 && (CyberGfxBase || P96Base)) { - if (P96Base && p96GetModeIDAttr(screen_mode_id, P96IDA_ISP96)) - default_display_type = DISPLAY_SCREEN_P96; - else if (CyberGfxBase && IsCyberModeID(screen_mode_id)) - default_display_type = DISPLAY_SCREEN_CGFX; - else { - ErrorAlert(STR_NO_P96_MODE_ERR); - return false; - } - } - } - - D(bug("default_display_type %d, window_width %d, window_height %d\n", default_display_type, window_width, window_height)); - - // Construct list of supported modes - switch (default_display_type) { - case DISPLAY_WINDOW: - default_width = window_width; - default_height = window_height; - default_depth = VDEPTH_1BIT; - add_modes(window_width, window_height, VDEPTH_1BIT); - break; - - case DISPLAY_PIP: - default_width = window_width; - default_height = window_height; - default_depth = VDEPTH_16BIT; - add_modes(window_width, window_height, VDEPTH_16BIT); - break; - - case DISPLAY_SCREEN_P96: - case DISPLAY_SCREEN_CGFX: - struct DimensionInfo dimInfo; - DisplayInfoHandle handle = FindDisplayInfo(screen_mode_id); - - if (handle == NULL) - return false; - - if (GetDisplayInfoData(handle, (UBYTE *) &dimInfo, sizeof(dimInfo), DTAG_DIMS, 0) <= 0) - return false; - - default_width = 1 + dimInfo.Nominal.MaxX - dimInfo.Nominal.MinX; - default_height = 1 + dimInfo.Nominal.MaxY - dimInfo.Nominal.MinY; - - switch (dimInfo.MaxDepth) { - case 1: - default_depth = VDEPTH_1BIT; - break; - case 8: - default_depth = VDEPTH_8BIT; - break; - case 15: - case 16: - default_depth = VDEPTH_16BIT; - break; - case 24: - case 32: - default_depth = VDEPTH_32BIT; - break; - } - - for (unsigned d=VDEPTH_8BIT; d<=VDEPTH_32BIT; d++) { - ULONG mode_id = find_mode_for_depth(default_width, default_height, bits_from_depth(video_depth(d))); - - if (is_valid_modeid(default_display_type, mode_id)) - add_modes(default_width, default_height, video_depth(d)); - } - break; - } - -#if DEBUG - bug("Available video modes:\n"); - vector::const_iterator i = VideoModes.begin(), end = VideoModes.end(); - while (i != end) { - bug(" %ld x %ld (ID %02lx), %ld colors\n", i->x, i->y, i->resolution_id, 1 << bits_from_depth(i->depth)); - ++i; - } -#endif - - D(bug("VideoInit/%ld: def_width=%ld def_height=%ld def_depth=%ld\n", \ - __LINE__, default_width, default_height, default_depth)); - - // Find requested default mode and open display - if (VideoModes.size() == 1) { - uint32 default_id ; - - // Create Amiga_monitor_desc for this (the only) display - default_id = VideoModes[0].resolution_id; - D(bug("VideoInit/%ld: default_id=%ld\n", __LINE__, default_id)); - Amiga_monitor_desc *monitor = new Amiga_monitor_desc(VideoModes, default_depth, default_id, default_display_type); - VideoMonitors.push_back(monitor); - - // Open display - return monitor->video_open(); - - } else { - - // Find mode with specified dimensions - std::vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - D(bug("VideoInit/%ld: w=%ld h=%ld d=%ld\n", __LINE__, i->x, i->y, bits_from_depth(i->depth))); - if (i->x == default_width && i->y == default_height && i->depth == default_depth) { - // Create Amiga_monitor_desc for this (the only) display - uint32 default_id = i->resolution_id; - D(bug("VideoInit/%ld: default_id=%ld\n", __LINE__, default_id)); - Amiga_monitor_desc *monitor = new Amiga_monitor_desc(VideoModes, default_depth, default_id, default_display_type); - VideoMonitors.push_back(monitor); - - // Open display - return monitor->video_open(); - } - } - - // Create Amiga_monitor_desc for this (the only) display - uint32 default_id = VideoModes[0].resolution_id; - D(bug("VideoInit/%ld: default_id=%ld\n", __LINE__, default_id)); - Amiga_monitor_desc *monitor = new Amiga_monitor_desc(VideoModes, default_depth, default_id, default_display_type); - VideoMonitors.push_back(monitor); - - // Open display - return monitor->video_open(); - } - - return true; -} - - -bool Amiga_monitor_desc::video_open() -{ - const video_mode &mode = get_current_mode(); - ULONG depth_bits = bits_from_depth(mode.depth); - ULONG ID = find_mode_for_depth(mode.x, mode.y, depth_bits); - - D(bug("video_open/%ld: width=%ld height=%ld depth=%ld ID=%08lx\n", __LINE__, mode.x, mode.y, depth_bits, ID)); - - if (ID == INVALID_ID) { - ErrorAlert(STR_NO_VIDEO_MODE_ERR); - return false; - } - - D(bug("video_open/%ld: display_type=%ld\n", __LINE__, display_type)); - - // Open display - switch (display_type) { - case DISPLAY_WINDOW: - drv = new driver_window(*this, mode.x, mode.y); - break; - - case DISPLAY_PIP: - drv = new driver_pip(*this, mode.x, mode.y); - break; - - case DISPLAY_SCREEN_P96: - drv = new driver_screen_p96(*this, ID); - break; - - case DISPLAY_SCREEN_CGFX: - drv = new driver_screen_cgfx(*this, ID); - break; - } - - D(bug("video_open/%ld: drv=%08lx\n", __LINE__, drv)); - - if (drv == NULL) - return false; - - D(bug("video_open/%ld: init_ok=%ld\n", __LINE__, drv->init_ok)); - if (!drv->init_ok) { - delete drv; - drv = NULL; - return false; - } - - // Start periodic process - periodic_proc = CreateNewProcTags( - NP_Entry, (ULONG)periodic_func, - NP_Name, (ULONG)"Basilisk II IDCMP Handler", - NP_Priority, 0, - TAG_END - ); - - D(bug("video_open/%ld: periodic_proc=%08lx\n", __LINE__, periodic_proc)); - - if (periodic_proc == NULL) { - ErrorAlert(STR_NO_MEM_ERR); - return false; - } - - return true; -} - - -void Amiga_monitor_desc::video_close() -{ - // Stop periodic process - if (periodic_proc) { - SetSignal(0, SIGF_SINGLE); - Signal(&periodic_proc->pr_Task, SIGBREAKF_CTRL_C); - Wait(SIGF_SINGLE); - } - - delete drv; - drv = NULL; - - // Free mouse pointer - if (null_pointer) { - FreeMem(null_pointer, 12); - null_pointer = NULL; - } -} - - -/* - * Deinitialization - */ - -void VideoExit(void) -{ - // Close displays - vector::iterator i, end = VideoMonitors.end(); - for (i = VideoMonitors.begin(); i != end; ++i) - dynamic_cast(*i)->video_close(); -} - - -/* - * Set palette - */ - -void Amiga_monitor_desc::set_palette(uint8 *pal, int num) -{ - drv->set_palette(pal, num); -} - - -/* - * Switch video mode - */ - -void Amiga_monitor_desc::switch_to_current_mode() -{ - // Close and reopen display - video_close(); - if (!video_open()) { - ErrorAlert(STR_OPEN_WINDOW_ERR); - QuitEmulator(); - } -} - - -/* - * Close down full-screen mode (if bringing up error alerts is unsafe while in full-screen mode) - */ - -void VideoQuitFullScreen(void) -{ -} - - -/* - * Video message handling (not neccessary under AmigaOS, handled by periodic_func()) - */ - -void VideoInterrupt(void) -{ -} - - -/* - * Process for window refresh and message handling - */ - -static __saveds void periodic_func(void) -{ - struct MsgPort *timer_port = NULL; - struct timerequest *timer_io = NULL; - struct IntuiMessage *msg; - ULONG win_mask = 0, timer_mask = 0; - - D(bug("periodic_func/%ld: \n", __LINE__)); - - // Create message port for window and attach it - struct MsgPort *win_port = CreateMsgPort(); - if (win_port) { - win_mask = 1 << win_port->mp_SigBit; - drv->the_win->UserPort = win_port; - ModifyIDCMP(drv->the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | - ((drv->monitor.display_type == DISPLAY_SCREEN_P96 || drv->monitor.display_type == DISPLAY_SCREEN_CGFX) ? IDCMP_DELTAMOVE : 0)); - } - - D(bug("periodic_func/%ld: \n", __LINE__)); - - // Start 60Hz timer for window refresh - if (drv->monitor.display_type == DISPLAY_WINDOW) { - timer_port = CreateMsgPort(); - if (timer_port) { - timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest)); - if (timer_io) { - if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) { - timer_mask = 1 << timer_port->mp_SigBit; - timer_io->tr_node.io_Command = TR_ADDREQUEST; - timer_io->tr_time.tv_secs = 0; - timer_io->tr_time.tv_micro = 16667 * frame_skip; - SendIO((struct IORequest *)timer_io); - } - } - } - } - - D(bug("periodic_func/%ld: \n", __LINE__)); - - // Main loop - for (;;) { - const video_mode &mode = drv->monitor.get_current_mode(); - - // Wait for timer and/or window (CTRL_C is used for quitting the task) - ULONG sig = Wait(win_mask | timer_mask | SIGBREAKF_CTRL_C); - - if (sig & SIGBREAKF_CTRL_C) - break; - -// D(bug("periodic_func/%ld: display_type=%ld the_win=%08lx\n", __LINE__, drv->monitor.display_type, drv->the_win)); - - if (sig & timer_mask) { - if (drv->get_bitmap()) { - // Timer tick, update display - BltTemplate(drv->get_bitmap()->Planes[0], 0, - drv->get_bitmap()->BytesPerRow, drv->the_win->RPort, - drv->the_win->BorderLeft, drv->the_win->BorderTop, - mode.x, mode.y); - } - - // Restart timer - timer_io->tr_node.io_Command = TR_ADDREQUEST; - timer_io->tr_time.tv_secs = 0; - timer_io->tr_time.tv_micro = 16667 * frame_skip; - SendIO((struct IORequest *)timer_io); - } - - if (sig & win_mask) { - - // Handle window messages - while (msg = (struct IntuiMessage *)GetMsg(win_port)) { - - // Get data from message and reply - ULONG cl = msg->Class; - UWORD code = msg->Code; - UWORD qualifier = msg->Qualifier; - WORD mx = msg->MouseX; - WORD my = msg->MouseY; - ReplyMsg((struct Message *)msg); - - // Handle message according to class - switch (cl) { - case IDCMP_MOUSEMOVE: - switch (drv->monitor.display_type) { - case DISPLAY_SCREEN_P96: - case DISPLAY_SCREEN_CGFX: -// D(bug("periodic_func/%ld: IDCMP_MOUSEMOVE mx=%ld my=%ld\n", __LINE__, mx, my)); - ADBMouseMoved(mx, my); - break; - default: -// D(bug("periodic_func/%ld: IDCMP_MOUSEMOVE mx=%ld my=%ld\n", __LINE__, mx - drv->the_win->BorderLeft, my - drv->the_win->BorderTop)); - ADBMouseMoved(mx - drv->the_win->BorderLeft, my - drv->the_win->BorderTop); - if (mx < drv->the_win->BorderLeft - || my < drv->the_win->BorderTop - || mx >= drv->the_win->BorderLeft + mode.x - || my >= drv->the_win->BorderTop + mode.y) { - if (current_pointer) { - ClearPointer(drv->the_win); - current_pointer = NULL; - } - } else { - if (current_pointer != null_pointer) { - // Hide mouse pointer inside window - SetPointer(drv->the_win, null_pointer, 1, 16, 0, 0); - current_pointer = null_pointer; - } - } - break; - } - break; - - case IDCMP_MOUSEBUTTONS: - if (code == SELECTDOWN) - ADBMouseDown(0); - else if (code == SELECTUP) - ADBMouseUp(0); - else if (code == MENUDOWN) - ADBMouseDown(1); - else if (code == MENUUP) - ADBMouseUp(1); - else if (code == MIDDLEDOWN) - ADBMouseDown(2); - else if (code == MIDDLEUP) - ADBMouseUp(2); - break; - - case IDCMP_RAWKEY: - if (qualifier & IEQUALIFIER_REPEAT) // Keyboard repeat is done by MacOS - break; - if ((qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL)) == - (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL) && code == 0x5f) { - SetInterruptFlag(INTFLAG_NMI); - TriggerInterrupt(); - break; - } - - if (code & IECODE_UP_PREFIX) - ADBKeyUp(keycode2mac[code & 0x7f]); - else - ADBKeyDown(keycode2mac[code & 0x7f]); - break; - } - } - } - } - - D(bug("periodic_func/%ld: \n", __LINE__)); - - // Stop timer - if (timer_io) { - if (!CheckIO((struct IORequest *)timer_io)) - AbortIO((struct IORequest *)timer_io); - WaitIO((struct IORequest *)timer_io); - CloseDevice((struct IORequest *)timer_io); - DeleteIORequest(timer_io); - } - if (timer_port) - DeleteMsgPort(timer_port); - - // Remove port from window and delete it - Forbid(); - msg = (struct IntuiMessage *)win_port->mp_MsgList.lh_Head; - struct Node *succ; - while (succ = msg->ExecMessage.mn_Node.ln_Succ) { - if (msg->IDCMPWindow == drv->the_win) { - Remove((struct Node *)msg); - ReplyMsg((struct Message *)msg); - } - msg = (struct IntuiMessage *)succ; - } - drv->the_win->UserPort = NULL; - ModifyIDCMP(drv->the_win, 0); - Permit(); - DeleteMsgPort(win_port); - - // Main task asked for termination, send signal - Forbid(); - Signal(MainTask, SIGF_SINGLE); -} - - -// Add mode to list of supported modes -static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth) -{ - video_mode mode; - mode.x = width; - mode.y = height; - mode.resolution_id = resolution_id; - mode.bytes_per_row = bytes_per_row; - mode.depth = depth; - - D(bug("Added video mode: w=%ld h=%ld d=%ld\n", width, height, depth)); - - VideoModes.push_back(mode); -} - -// Add standard list of modes for given color depth -static void add_modes(uint32 width, uint32 height, video_depth depth) -{ - D(bug("add_modes: w=%ld h=%ld d=%ld\n", width, height, depth)); - - if (width >= 512 && height >= 384) - add_mode(512, 384, 0x80, TrivialBytesPerRow(512, depth), depth); - if (width >= 640 && height >= 480) - add_mode(640, 480, 0x81, TrivialBytesPerRow(640, depth), depth); - if (width >= 800 && height >= 600) - add_mode(800, 600, 0x82, TrivialBytesPerRow(800, depth), depth); - if (width >= 1024 && height >= 768) - add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, depth), depth); - if (width >= 1152 && height >= 870) - add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, depth), depth); - if (width >= 1280 && height >= 1024) - add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, depth), depth); - if (width >= 1600 && height >= 1200) - add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, depth), depth); -} - - -static ULONG find_mode_for_depth(uint32 width, uint32 height, uint32 depth) -{ - ULONG ID = BestModeID(BIDTAG_NominalWidth, width, - BIDTAG_NominalHeight, height, - BIDTAG_Depth, depth, - BIDTAG_DIPFMustNotHave, DIPF_IS_ECS | DIPF_IS_HAM | DIPF_IS_AA, - TAG_END); - - return ID; -} - - -static ULONG bits_from_depth(video_depth depth) -{ - int bits = 1 << depth; - if (bits == 16) - bits = 15; - else if (bits == 32) - bits = 24; - - return bits; -} - - -static bool is_valid_modeid(int display_type, ULONG mode_id) -{ - if (INVALID_ID == mode_id) - return false; - - switch (display_type) { - case DISPLAY_SCREEN_P96: - return check_modeid_p96(mode_id); - break; - case DISPLAY_SCREEN_CGFX: - return check_modeid_cgfx(mode_id); - break; - default: - return false; - break; - } -} - - -static bool check_modeid_p96(ULONG mode_id) -{ - // Check if the mode is one we can handle - uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH); - uint32 format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT); - - D(bug("check_modeid_p96: mode_id=%08lx depth=%ld format=%ld\n", mode_id, depth, format)); - - if (!p96GetModeIDAttr(mode_id, P96IDA_ISP96)) - return false; - - switch (depth) { - case 8: - break; - case 15: - case 16: - if (format != RGBFB_R5G5B5) - return false; - break; - case 24: - case 32: - if (format != RGBFB_A8R8G8B8) - return false; - break; - default: - return false; - } - - return true; -} - - -static bool check_modeid_cgfx(ULONG mode_id) -{ - uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id); - uint32 format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id); - - D(bug("check_modeid_cgfx: mode_id=%08lx depth=%ld format=%ld\n", mode_id, depth, format)); - - if (!IsCyberModeID(mode_id)) - return false; - - switch (depth) { - case 8: - break; - case 15: - case 16: - if (format != PIXFMT_RGB15) - return false; - break; - case 24: - case 32: - if (format != PIXFMT_ARGB32) - return false; - break; - default: - return false; - } - - return true; -} - - -driver_base::driver_base(Amiga_monitor_desc &m) - : monitor(m), mode(m.get_current_mode()), init_ok(false) -{ -} - -driver_base::~driver_base() -{ -} - - -// Open window -driver_window::driver_window(Amiga_monitor_desc &m, int width, int height) - : black_pen(-1), white_pen(-1), driver_base(m) -{ - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - // Open window - the_win = OpenWindowTags(NULL, - WA_Left, 0, WA_Top, 0, - WA_InnerWidth, width, WA_InnerHeight, height, - WA_SimpleRefresh, true, - WA_NoCareRefresh, true, - WA_Activate, true, - WA_RMBTrap, true, - WA_ReportMouse, true, - WA_DragBar, true, - WA_DepthGadget, true, - WA_SizeGadget, false, - WA_Title, (ULONG)GetString(STR_WINDOW_TITLE), - TAG_END - ); - if (the_win == NULL) { - init_ok = false; - ErrorAlert(STR_OPEN_WINDOW_ERR); - return; - } - - // Create bitmap ("height + 2" for safety) - the_bitmap = AllocBitMap(width, height + 2, 1, BMF_CLEAR, NULL); - if (the_bitmap == NULL) { - init_ok = false; - ErrorAlert(STR_NO_MEM_ERR); - return; - } - - // Add resolution and set VideoMonitor - monitor.set_mac_frame_base((uint32)the_bitmap->Planes[0]); - - // Set FgPen and BgPen - black_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0, 0, 0, NULL); - white_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0xffffffff, 0xffffffff, 0xffffffff, NULL); - SetAPen(the_win->RPort, black_pen); - SetBPen(the_win->RPort, white_pen); - SetDrMd(the_win->RPort, JAM2); - - init_ok = true; -} - - -driver_window::~driver_window() -{ - // Window mode, free bitmap - if (the_bitmap) { - WaitBlit(); - FreeBitMap(the_bitmap); - } - - // Free pens and close window - if (the_win) { - ReleasePen(the_win->WScreen->ViewPort.ColorMap, black_pen); - ReleasePen(the_win->WScreen->ViewPort.ColorMap, white_pen); - - CloseWindow(the_win); - the_win = NULL; - } -} - - -// Open PIP (requires Picasso96) -driver_pip::driver_pip(Amiga_monitor_desc &m, int width, int height) - : driver_base(m) -{ - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - D(bug("driver_pip(%d,%d)\n", width, height)); - - // Open window - ULONG error = 0; - the_win = p96PIP_OpenTags( - P96PIP_SourceFormat, RGBFB_R5G5B5, - P96PIP_SourceWidth, width, - P96PIP_SourceHeight, height, - P96PIP_ErrorCode, (ULONG)&error, - P96PIP_AllowCropping, true, - WA_Left, 0, WA_Top, 0, - WA_InnerWidth, width, WA_InnerHeight, height, - WA_SimpleRefresh, true, - WA_NoCareRefresh, true, - WA_Activate, true, - WA_RMBTrap, true, - WA_ReportMouse, true, - WA_DragBar, true, - WA_DepthGadget, true, - WA_SizeGadget, false, - WA_Title, (ULONG)GetString(STR_WINDOW_TITLE), - WA_PubScreenName, (ULONG)"Workbench", - TAG_END - ); - if (the_win == NULL || error) { - init_ok = false; - ErrorAlert(STR_OPEN_WINDOW_ERR); - return; - } - - // Find bitmap - p96PIP_GetTags(the_win, P96PIP_SourceBitMap, (ULONG)&the_bitmap, TAG_END); - - // Add resolution and set VideoMonitor - monitor.set_mac_frame_base(p96GetBitMapAttr(the_bitmap, P96BMA_MEMORY)); - - init_ok = true; -} - -driver_pip::~driver_pip() -{ - // Close PIP - if (the_win) - p96PIP_Close(the_win); -} - - -// Open Picasso96 screen -driver_screen_p96::driver_screen_p96(Amiga_monitor_desc &m, ULONG mode_id) - : driver_base(m) -{ - // Set relative mouse mode - ADBSetRelMouseMode(true); - - // Check if the mode is one we can handle - if (!check_modeid_p96(mode_id)) - { - init_ok = false; - ErrorAlert(STR_WRONG_SCREEN_FORMAT_ERR); - return; - } - - // Yes, get width and height - uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH); - uint32 width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH); - uint32 height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT); - - // Open screen - the_screen = p96OpenScreenTags( - P96SA_DisplayID, mode_id, - P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE), - P96SA_Quiet, true, - P96SA_NoMemory, true, - P96SA_NoSprite, true, - P96SA_Exclusive, true, - TAG_END - ); - if (the_screen == NULL) { - ErrorAlert(STR_OPEN_SCREEN_ERR); - init_ok = false; - return; - } - - // Open window - the_win = OpenWindowTags(NULL, - WA_Left, 0, WA_Top, 0, - WA_Width, width, WA_Height, height, - WA_SimpleRefresh, true, - WA_NoCareRefresh, true, - WA_Borderless, true, - WA_Activate, true, - WA_RMBTrap, true, - WA_ReportMouse, true, - WA_CustomScreen, (ULONG)the_screen, - TAG_END - ); - if (the_win == NULL) { - ErrorAlert(STR_OPEN_WINDOW_ERR); - init_ok = false; - return; - } - - ScreenToFront(the_screen); - - // Add resolution and set VideoMonitor - monitor.set_mac_frame_base(p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY)); - - init_ok = true; -} - - -driver_screen_p96::~driver_screen_p96() -{ - // Close window - if (the_win) - { - CloseWindow(the_win); - the_win = NULL; - } - - // Close screen - if (the_screen) { - p96CloseScreen(the_screen); - the_screen = NULL; - } -} - - -void driver_screen_p96::set_palette(uint8 *pal, int num) -{ - // Convert palette to 32 bits - ULONG table[2 + 256 * 3]; - table[0] = num << 16; - table[num * 3 + 1] = 0; - for (int i=0; iViewPort, table); -} - - -// Open CyberGraphX screen -driver_screen_cgfx::driver_screen_cgfx(Amiga_monitor_desc &m, ULONG mode_id) - : driver_base(m) -{ - D(bug("driver_screen_cgfx/%ld: mode_id=%08lx\n", __LINE__, mode_id)); - - // Set absolute mouse mode - ADBSetRelMouseMode(true); - - // Check if the mode is one we can handle - if (!check_modeid_cgfx(mode_id)) - { - ErrorAlert(STR_WRONG_SCREEN_FORMAT_ERR); - init_ok = false; - return; - } - - // Yes, get width and height - uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id); - uint32 width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id); - uint32 height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id); - - // Open screen - the_screen = OpenScreenTags(NULL, - SA_DisplayID, mode_id, - SA_Title, (ULONG)GetString(STR_WINDOW_TITLE), - SA_Quiet, true, - SA_Exclusive, true, - TAG_END - ); - if (the_screen == NULL) { - ErrorAlert(STR_OPEN_SCREEN_ERR); - init_ok = false; - return; - } - - // Open window - the_win = OpenWindowTags(NULL, - WA_Left, 0, WA_Top, 0, - WA_Width, width, WA_Height, height, - WA_SimpleRefresh, true, - WA_NoCareRefresh, true, - WA_Borderless, true, - WA_Activate, true, - WA_RMBTrap, true, - WA_ReportMouse, true, - WA_CustomScreen, (ULONG)the_screen, - TAG_END - ); - if (the_win == NULL) { - ErrorAlert(STR_OPEN_WINDOW_ERR); - init_ok = false; - return; - } - - ScreenToFront(the_screen); - static UWORD ptr[] = { 0, 0, 0, 0 }; - SetPointer(the_win, ptr, 0, 0, 0, 0); // Hide mouse pointer - - // Set VideoMonitor - ULONG frame_base; - APTR handle = LockBitMapTags(the_screen->RastPort.BitMap, - LBMI_BASEADDRESS, (ULONG)&frame_base, - TAG_END - ); - UnLockBitMap(handle); - - D(bug("driver_screen_cgfx/%ld: frame_base=%08lx\n", __LINE__, frame_base)); - - monitor.set_mac_frame_base(frame_base); - - init_ok = true; -} - - -driver_screen_cgfx::~driver_screen_cgfx() -{ - D(bug("~driver_screen_cgfx/%ld: \n", __LINE__)); - - // Close window - if (the_win) - { - CloseWindow(the_win); - the_win = NULL; - } - - // Close screen - if (the_screen) { - CloseScreen(the_screen); - the_screen = NULL; - } -} - - -void driver_screen_cgfx::set_palette(uint8 *pal, int num) -{ - // Convert palette to 32 bits - ULONG table[2 + 256 * 3]; - table[0] = num << 16; - table[num * 3 + 1] = 0; - for (int i=0; iViewPort, table); -} diff --git a/BasiliskII/src/AmigaOS/xpram_amiga.cpp b/BasiliskII/src/AmigaOS/xpram_amiga.cpp deleted file mode 100644 index 69195d11..00000000 --- a/BasiliskII/src/AmigaOS/xpram_amiga.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * xpram_amiga.cpp - XPRAM handling, AmigaOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#define __USE_SYSBASE -#include -#include - -#include "sysdeps.h" -#include "xpram.h" - - -// XPRAM file name -#if POWERPC_ROM -static char XPRAM_FILE_NAME[] = "ENV:SheepShaver_NVRAM"; -static char XPRAM_FILE_NAME_ARC[] = "ENVARC:SheepShaver_NVRAM"; -#else -static char XPRAM_FILE_NAME[] = "ENV:BasiliskII_XPRAM"; -static char XPRAM_FILE_NAME_ARC[] = "ENVARC:BasiliskII_XPRAM"; -#endif - - -/* - * Load XPRAM from settings file - */ - -void LoadXPRAM(void) -{ - BPTR fh; - if ((fh = Open(XPRAM_FILE_NAME, MODE_OLDFILE)) != NULL) { - Read(fh, XPRAM, XPRAM_SIZE); - Close(fh); - } -} - - -/* - * Save XPRAM to settings file - */ - -void SaveXPRAM(void) -{ - BPTR fh; - if ((fh = Open(XPRAM_FILE_NAME, MODE_NEWFILE)) != NULL) { - Write(fh, XPRAM, XPRAM_SIZE); - Close(fh); - } - if ((fh = Open(XPRAM_FILE_NAME_ARC, MODE_NEWFILE)) != NULL) { - Write(fh, XPRAM, XPRAM_SIZE); - Close(fh); - } -} - - -/* - * Delete PRAM file - */ - -void ZapPRAM(void) -{ - DeleteFile(XPRAM_FILE_NAME); - DeleteFile(XPRAM_FILE_NAME_ARC); -} diff --git a/BasiliskII/src/BeOS/Makefile b/BasiliskII/src/BeOS/Makefile deleted file mode 100644 index e7feb636..00000000 --- a/BasiliskII/src/BeOS/Makefile +++ /dev/null @@ -1,151 +0,0 @@ -## BeOS Generic Makefile v2.1 ## - -## Fill in this file to specify the project being created, and the referenced -## makefile-engine will do all of the hard work for you. This handles both -## Intel and PowerPC builds of the BeOS. - -## Application Specific Settings --------------------------------------------- - -# specify the name of the binary -NAME= BasiliskII - -# specify the type of binary -# APP: Application -# SHARED: Shared library or add-on -# STATIC: Static library archive -# DRIVER: Kernel Driver -TYPE= APP - -# add support for new Pe and Eddie features -# to fill in generic makefile - -#%{ -# @src->@ - -# specify the source files to use -# full paths or paths relative to the makefile can be included -# all files, regardless of directory, will have their object -# files created in the common object directory. -# Note that this means this makefile will not work correctly -# if two source files with the same name (source.c or source.cpp) -# are included from different directories. Also note that spaces -# in folder names do not work well with this makefile. -MACHINE=$(shell uname -m) -ifeq ($(MACHINE), BePC) - CPUSRCS = ../uae_cpu/basilisk_glue.cpp ../uae_cpu/memory.cpp ../uae_cpu/newcpu.cpp \ - ../uae_cpu/readcpu.cpp ../uae_cpu/fpu/fpu_x86.cpp cpustbl.cpp cpudefs.cpp cpufast.s -else -# CPUSRCS = ../powerrom_cpu/powerrom_cpu.cpp - CPUSRCS = ../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp \ - ../uae_cpu/readcpu.cpp ../uae_cpu/fpu/fpu_uae.cpp cpustbl.cpp cpudefs.cpp cpuemu.cpp -endif -SRCS = ../main.cpp main_beos.cpp ../prefs.cpp ../prefs_items.cpp prefs_beos.cpp \ - prefs_editor_beos.cpp sys_beos.cpp ../rom_patches.cpp ../slot_rom.cpp \ - ../rsrc_patches.cpp ../emul_op.cpp ../macos_util.cpp ../xpram.cpp \ - xpram_beos.cpp ../timer.cpp timer_beos.cpp clip_beos.cpp ../adb.cpp \ - ../serial.cpp serial_beos.cpp ../ether.cpp ether_beos.cpp ../sony.cpp \ - ../disk.cpp ../cdrom.cpp ../scsi.cpp scsi_beos.cpp ../video.cpp \ - video_beos.cpp ../audio.cpp audio_beos.cpp ../extfs.cpp extfs_beos.cpp \ - ../user_strings.cpp user_strings_beos.cpp about_window.cpp \ - $(CPUSRCS) - -# specify the resource files to use -# full path or a relative path to the resource file can be used. -RSRCS= - -# @<-src@ -#%} - -# end support for Pe and Eddie - -# specify additional libraries to link against -# there are two acceptable forms of library specifications -# - if your library follows the naming pattern of: -# libXXX.so or libXXX.a you can simply specify XXX -# library: libbe.so entry: be -# -# - if your library does not follow the standard library -# naming scheme you need to specify the path to the library -# and it's name -# library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS=be game media device textencoding tracker net - -# specify additional paths to directories following the standard -# libXXX.so or libXXX.a naming scheme. You can specify full paths -# or paths relative to the makefile. The paths included may not -# be recursive, so include all of the paths where libraries can -# be found. Directories where source files are found are -# automatically included. -LIBPATHS= - -# additional paths to look for system headers -# thes use the form: #include
-# source file directories are NOT auto-included here -SYSTEM_INCLUDE_PATHS = - -# additional paths to look for local headers -# thes use the form: #include "header" -# source file directories are automatically included -LOCAL_INCLUDE_PATHS = ../include SheepDriver SheepNet - -# specify the level of optimization that you desire -# NONE, SOME, FULL -OPTIMIZE= FULL - -# specify any preprocessor symbols to be defined. The symbols will not -# have their values set automatically; you must supply the value (if any) -# to use. For example, setting DEFINES to "DEBUG=1" will cause the -# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" -# would pass "-DDEBUG" on the compiler's command line. -DEFINES= FPU_X86 SIZEOF_FLOAT=4 SIZEOF_DOUBLE=8 SIZEOF_LONG_DOUBLE=10 - -# specify special warning levels -# if unspecified default warnings will be used -# NONE = supress all warnings -# ALL = enable all warnings -WARNINGS = - -# specify whether image symbols will be created -# so that stack crawls in the debugger are meaningful -# if TRUE symbols will be created -SYMBOLS = - -# specify debug settings -# if TRUE will allow application to be run from -# a source-level debugger -DEBUGGER = - -# specify additional compiler flags for all files -COMPILER_FLAGS = -fomit-frame-pointer -fno-PIC - -# specify additional linker flags -LINKER_FLAGS = - - -## include the makefile-engine -include /boot/system/develop/etc/makefile-engine - - -# special handling of UAE CPU engine -$(OBJ_DIR)/%.o : %.s - $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuopti: $(OBJ_DIR)/cpuopti.o - $(CC) $(LDFLAGS) -o $(OBJ_DIR)/cpuopti $(OBJ_DIR)/cpuopti.o -$(OBJ_DIR)/build68k: $(OBJ_DIR)/build68k.o - $(CC) $(LDFLAGS) -o $(OBJ_DIR)/build68k $(OBJ_DIR)/build68k.o -$(OBJ_DIR)/gencpu: $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o - $(CC) $(LDFLAGS) -o $(OBJ_DIR)/gencpu $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o -cpudefs.cpp: $(OBJ_DIR)/build68k ../uae_cpu/table68k - $(OBJ_DIR)/build68k <../uae_cpu/table68k >cpudefs.cpp -cpuemu.cpp: $(OBJ_DIR)/gencpu - $(OBJ_DIR)/gencpu -cpustbl.cpp: cpuemu.cpp -cputbl.h: cpuemu.cpp -cpufast.s: cpuemu.cpp $(OBJ_DIR)/cpuopti - $(CXX) $(INCLUDES) -S $(CFLAGS) $< -o cputmp.s - $(OBJ_DIR)/cpuopti $@ || mv cputmp.s $@ - rm -f cputmp.s - -streifenfrei: - -rm -f $(OBJ_DIR)/gencpu $(OBJ_DIR)/build68k $(OBJ_DIR)/cpuopti - -rm -f cpuemu.cpp cpudefs.cpp cputmp.s cpufast*.s cpustbl.cpp cputbl.h diff --git a/BasiliskII/src/BeOS/SheepDriver/Makefile b/BasiliskII/src/BeOS/SheepDriver/Makefile deleted file mode 100644 index 52b2b70e..00000000 --- a/BasiliskII/src/BeOS/SheepDriver/Makefile +++ /dev/null @@ -1,117 +0,0 @@ -## BeOS Generic Makefile v2.1 ## - -## Fill in this file to specify the project being created, and the referenced -## makefile-engine will do all of the hard work for you. This handles both -## Intel and PowerPC builds of the BeOS. - -## Application Specific Settings --------------------------------------------- - -# specify the name of the binary -NAME= sheep - -# specify the type of binary -# APP: Application -# SHARED: Shared library or add-on -# STATIC: Static library archive -# DRIVER: Kernel Driver -TYPE= DRIVER - -# add support for new Pe and Eddie features -# to fill in generic makefile - -#%{ -# @src->@ - -# specify the source files to use -# full paths or paths relative to the makefile can be included -# all files, regardless of directory, will have their object -# files created in the common object directory. -# Note that this means this makefile will not work correctly -# if two source files with the same name (source.c or source.cpp) -# are included from different directories. Also note that spaces -# in folder names do not work well with this makefile. -SRCS= sheep_driver.c - -# specify the resource files to use -# full path or a relative path to the resource file can be used. -RSRCS= - -# @<-src@ -#%} - -# end support for Pe and Eddie - -# specify additional libraries to link against -# there are two acceptable forms of library specifications -# - if your library follows the naming pattern of: -# libXXX.so or libXXX.a you can simply specify XXX -# library: libbe.so entry: be -# -# - if your library does not follow the standard library -# naming scheme you need to specify the path to the library -# and it's name -# library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS= - -# specify additional paths to directories following the standard -# libXXX.so or libXXX.a naming scheme. You can specify full paths -# or paths relative to the makefile. The paths included may not -# be recursive, so include all of the paths where libraries can -# be found. Directories where source files are found are -# automatically included. -LIBPATHS= - -# additional paths to look for system headers -# thes use the form: #include
-# source file directories are NOT auto-included here -SYSTEM_INCLUDE_PATHS = - -# additional paths to look for local headers -# thes use the form: #include "header" -# source file directories are automatically included -LOCAL_INCLUDE_PATHS = - -# specify the level of optimization that you desire -# NONE, SOME, FULL -OPTIMIZE= FULL - -# specify any preprocessor symbols to be defined. The symbols will not -# have their values set automatically; you must supply the value (if any) -# to use. For example, setting DEFINES to "DEBUG=1" will cause the -# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" -# would pass "-DDEBUG" on the compiler's command line. -DEFINES= - -# specify special warning levels -# if unspecified default warnings will be used -# NONE = supress all warnings -# ALL = enable all warnings -WARNINGS = - -# specify whether image symbols will be created -# so that stack crawls in the debugger are meaningful -# if TRUE symbols will be created -SYMBOLS = - -# specify debug settings -# if TRUE will allow application to be run from a source-level -# debugger. Note that this will disable all optimzation. -DEBUGGER = - -# specify additional compiler flags for all files -COMPILER_FLAGS = - -# specify additional linker flags -LINKER_FLAGS = - - -## include the makefile-engine -include /boot/develop/etc/makefile-engine - -install: $(TARGET) - cp $(TARGET) /boot/home/config/add-ons/kernel/drivers/bin - ln -sf /boot/home/config/add-ons/kernel/drivers/bin/$(NAME) /boot/home/config/add-ons/kernel/drivers/dev/$(NAME) - -uninstall: - rm /boot/home/config/add-ons/kernel/drivers/bin/$(NAME) - rm /boot/home/config/add-ons/kernel/drivers/dev/$(NAME) diff --git a/BasiliskII/src/BeOS/SheepDriver/sheep_driver.c b/BasiliskII/src/BeOS/SheepDriver/sheep_driver.c deleted file mode 100644 index 859d82e2..00000000 --- a/BasiliskII/src/BeOS/SheepDriver/sheep_driver.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * sheep_driver.c - Low memory and ROM access driver for SheepShaver and - * Basilisk II on PowerPC systems - * - * SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer - * Basilisk II (C) 1997-2002 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef __i386__ -#error The sheep driver only runs on PowerPC machines. -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "sheep_driver.h" - -#define DEBUG 0 - -#if DEBUG==1 -#define bug pprintf -#elif DEBUG==2 -#define bug dprintf -#endif - -#if DEBUG -#define D(x) (x) -#else -#define D(x) ; -#endif - -#define PORT_NAME "sheep_driver installed" - - -/* - * For debugging - */ - -static int pprintf(const char* format, ...) -{ - port_id PortNum; - int len, ret; - char Buffer[1024]; - va_list ap; - - if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND) - return(PortNum); - for (len=0; len<1024; len++) - Buffer[len]='\0'; - va_start(ap, format); - vsprintf(Buffer, format, ap); - ret = write_port(PortNum, 0, Buffer, strlen(Buffer)); - return ret; -} - - -/* - * Page table functions - */ - -static uint32 *pte_address = 0; -static uint32 vsid; -static uint32 table_size; - -static status_t map_page(uint32 ea, uint32 ra, uint32 **free_pte, uint32 bits) -{ - int i; - int pte_class; - uint32 hash1, hash2, api, *pteg1, *pteg2; - - D(bug("Trying to map EA %p -> RA %p\n", ea, ra)); - - // Find PTEG addresses for given EA - hash1 = (vsid & 0x7ffff) ^ ((ea >> 12) & 0xffff); - hash2 = ~hash1 & 0x7ffff; - api = (ea >> 22) & 0x3f; - pteg1 = (uint32 *)((uint32)pte_address + ((hash1 << 6) & (table_size - 1))); - pteg2 = (uint32 *)((uint32)pte_address + ((hash2 << 6) & (table_size - 1))); - D(bug("PTEG1 at %p, PTEG2 at %p\n", pteg1, pteg2)); - - // Search all 8 PTEs of each PTEG - *free_pte = NULL; - pte_class = 0; - for (i=0; i<8; i++) { - D(bug(" found %08lx %08lx\n", pteg1[i*2], pteg1[i*2+1])); - if (pteg1[i*2] == (0x80000000 | (vsid << 7) | (pte_class << 6) | api)) { - *free_pte = pteg1 + i*2; - D(bug(" existing PTE found (PTEG1)\n")); - break; - } else if (!pteg1[i*2]) { - *free_pte = pteg1 + i*2; - D(bug(" free PTE found (PTEG1)\n")); - break; - } - } - if (*free_pte == NULL) { - pte_class = 1; - for (i=0; i<8; i++) { - D(bug(" found %08lx %08lx\n", pteg2[i*2], pteg2[i*2+1])); - if (pteg2[i*2] == (0x80000000 | (vsid << 7) | (pte_class << 6) | api)) { - *free_pte = pteg2 + i*2; - D(bug(" existing PTE found (PTEG2)\n")); - break; - } else if (!pteg2[i*2]) { - *free_pte = pteg2 + i*2; - D(bug(" free PTE found (PTEG2)\n")); - break; - } - } - } - - // Remap page - if (*free_pte == NULL) { - D(bug(" No free PTE found :-(\m")); - return B_DEVICE_FULL; - } else { - (*free_pte)[0] = 0x80000000 | (vsid << 7) | (pte_class << 6) | api; - (*free_pte)[1] = ra | bits; - D(bug(" written %08lx %08lx to PTE\n", (*free_pte)[0], (*free_pte)[1])); - return B_NO_ERROR; - } -} - -static status_t remap_page(uint32 *free_pte, uint32 ra, uint32 bits) -{ - D(bug("Remapping PTE %p -> RA %p\n", free_pte, ra)); - - // Remap page - if (free_pte == NULL) { - D(bug(" Invalid PTE :-(\n")); - return B_BAD_ADDRESS; - } else { - free_pte[1] = ra | bits; - D(bug(" written %08lx %08lx to PTE\n", free_pte[0], free_pte[1])); - return B_NO_ERROR; - } -} - - -/* - * Foward declarations for hook functions - */ - -static status_t sheep_open(const char *name, uint32 flags, void **cookie); -static status_t sheep_close(void *cookie); -static status_t sheep_free(void *cookie); -static status_t sheep_control(void *cookie, uint32 op, void *data, size_t len); -static status_t sheep_read(void *cookie, off_t pos, void *data, size_t *len); -static status_t sheep_write(void *cookie, off_t pos, const void *data, size_t *len); - - -/* - * Version of our driver - */ - -int32 api_version = B_CUR_DRIVER_API_VERSION; - - -/* - * Device_hooks structure - has function pointers to the - * various entry points for device operations - */ - -static device_hooks my_device_hooks = { - &sheep_open, - &sheep_close, - &sheep_free, - &sheep_control, - &sheep_read, - &sheep_write, - NULL, - NULL, - NULL, - NULL -}; - - -/* - * List of device names to be returned by publish_devices() - */ - -static char *device_name_list[] = { - "sheep", - 0 -}; - - -/* - * Init - do nothing - */ - -status_t init_hardware(void) -{ -#if DEBUG==2 - set_dprintf_enabled(true); -#endif - D(bug("init_hardware()\n")); - return B_NO_ERROR; -} - -status_t init_driver(void) -{ - D(bug("init_driver()\n")); - return B_NO_ERROR; -} - -void uninit_driver(void) -{ - D(bug("uninit_driver()\n")); -} - - -/* - * publish_devices - return list of device names implemented by this driver - */ - -const char **publish_devices(void) -{ - return device_name_list; -} - - -/* - * find_device - return device hooks for a specific device name - */ - -device_hooks *find_device(const char *name) -{ - if (!strcmp(name, device_name_list[0])) - return &my_device_hooks; - - return NULL; -} - - -/* - * sheep_open - hook function for the open call. - */ - -static status_t sheep_open(const char *name, uint32 flags, void **cookie) -{ - return B_NO_ERROR; -} - - -/* - * sheep_close - hook function for the close call. - */ - -static status_t sheep_close(void *cookie) -{ - return B_NO_ERROR; -} - - -/* - * sheep_free - hook function to free the cookie returned - * by the open hook. Since the open hook did not return - * a cookie, this is a no-op. - */ - -static status_t sheep_free(void *cookie) -{ - return B_NO_ERROR; -} - - -/* - * sheep_control - hook function for the ioctl call - */ - -static asm void inval_tlb(uint32 ea) -{ - isync - tlbie r3 - sync - blr -} - -static asm void tlbsync(void) -{ - machine 604 - tlbsync - sync - blr -} - -static status_t sheep_control(void *cookie, uint32 op, void *data, size_t len) -{ - static void *block; - static void *block_aligned; - physical_entry pe[2]; - system_info sysinfo; - area_id id; - area_info info; - cpu_status cpu_st; - status_t res; - uint32 ra0, ra1; - uint32 *free_pte_0, *free_pte_1; - int i; - - D(bug("control(%d) data %p, len %08x\n", op, data, len)); - - switch (op) { - case SHEEP_UP: - - // Already messed up? Then do nothing now - if (find_port(PORT_NAME) != B_NAME_NOT_FOUND) - return B_NO_ERROR; - - // Get system info - get_system_info(&sysinfo); - - // Prepare replacement memory - block = malloc(B_PAGE_SIZE * 3); - D(bug("3 pages malloc()ed at %p\n", block)); - block_aligned = (void *)(((uint32)block + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE-1)); - D(bug("Address aligned to %p\n", block_aligned)); - res = lock_memory(block_aligned, B_PAGE_SIZE * 2, 0); - if (res < 0) - return res; - - // Get memory mapping - D(bug("Memory locked\n")); - res = get_memory_map(block_aligned, B_PAGE_SIZE * 2, pe, 2); - D(bug("get_memory_map returned %d\n", res)); - if (res != B_NO_ERROR) - return res; - - // Find PTE table area - id = find_area("pte_table"); - get_area_info(id, &info); - pte_address = (uint32 *)info.address; - D(bug("PTE table seems to be at %p\n", pte_address)); - table_size = info.size; - D(bug("PTE table size: %dKB\n", table_size / 1024)); - - // Disable interrupts - cpu_st = disable_interrupts(); - - // Find vsid and real addresses of replacement memory - for (i=0; i> 31),((pte_address[i*2]&0x7fffff80) >> 7), - ((pte_address[i*2]&0x00000040) >> 6),(pte_address[i*2] & 0x3f), - ((pte_address[i*2+1]&0xfffff000) >> 12),((pte_address[i*2+1]&0x00000100) >> 8), - ((pte_address[i*2+1]&0x00000080) >> 7),((pte_address[i*2+1]&0x00000078) >> 3), - (pte_address[i*2+1]&0x00000003))); - vsid = (pte_address[i*2]&0x7fffff80) >> 7; - ra0 = (uint32)pe[0].address & 0xfffff000; - } - if ((uint32)pe[0].size == B_PAGE_SIZE) { - if (((uint32)pe[1].address & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) { - D(bug("Found page 1f PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n", - i << 2, - ((pte_address[i*2]&0x80000000) >> 31), ((pte_address[i*2]&0x7fffff80) >> 7), - ((pte_address[i*2]&0x00000040) >> 6), (pte_address[i*2] & 0x3f), - ((pte_address[i*2+1]&0xfffff000) >> 12), ((pte_address[i*2+1]&0x00000100) >> 8), - ((pte_address[i*2+1]&0x00000080) >> 7), ((pte_address[i*2+1]&0x00000078) >> 3), - (pte_address[i*2+1]&0x00000003))); - ra1 = (uint32)pe[1].address & 0xfffff000; - } - } else { - if ((((uint32)pe[0].address + B_PAGE_SIZE) & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) { - D(bug("Found page 1d PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n", - i << 2, - ((pte_address[i*2]&0x80000000) >> 31), ((pte_address[i*2]&0x7fffff80) >> 7), - ((pte_address[i*2]&0x00000040) >> 6), (pte_address[i*2] & 0x3f), - ((pte_address[i*2+1]&0xfffff000) >> 12), ((pte_address[i*2+1]&0x00000100) >> 8), - ((pte_address[i*2+1]&0x00000080) >> 7), ((pte_address[i*2+1]&0x00000078) >> 3), - (pte_address[i*2+1]&0x00000003))); - ra1 = ((uint32)pe[0].address + B_PAGE_SIZE) & 0xfffff000; - } - } - } - - // Map low memory for emulator - free_pte_0 = NULL; - free_pte_1 = NULL; - __sync(); - __isync(); - inval_tlb(0); - inval_tlb(B_PAGE_SIZE); - if (sysinfo.cpu_type != B_CPU_PPC_603 && sysinfo.cpu_type != B_CPU_PPC_603e) - tlbsync(); - res = map_page(0, ra0, &free_pte_0, 0x12); - if (res == B_NO_ERROR) - res = map_page(B_PAGE_SIZE, ra1, &free_pte_1, 0x12); - inval_tlb(0); - inval_tlb(B_PAGE_SIZE); - if (sysinfo.cpu_type != B_CPU_PPC_603 && sysinfo.cpu_type != B_CPU_PPC_603e) - tlbsync(); - __sync(); - __isync(); - - // Restore interrupts - restore_interrupts(cpu_st); - - // Create port so we know that messing was successful - set_port_owner(create_port(1, PORT_NAME), B_SYSTEM_TEAM); - return B_NO_ERROR; - - case SHEEP_DOWN: - return B_NO_ERROR; - - default: - return B_BAD_VALUE; - } -} - - -/* - * sheep_read - hook function for the read call - */ - -static status_t sheep_read(void *cookie, off_t pos, void *data, size_t *len) -{ - void *rom_adr; - area_id area; - system_info info; - - D(bug("read() pos %Lx, data %p, len %08x\n", pos, data, *len)); - - get_system_info(&info); - if (info.platform_type == B_BEBOX_PLATFORM) { - *len = 0; - return B_ERROR; - } - if (*len != 0x400000 && pos != 0) { - *len = 0; - return B_BAD_VALUE; - } - area = map_physical_memory("mac_rom", (void *)0xff000000, 0x00400000, B_ANY_KERNEL_ADDRESS, B_READ_AREA, &rom_adr); - D(bug("Mapped ROM to %p, area id %d\n", rom_adr, area)); - if (area < 0) { - *len = 0; - return area; - } - D(bug("Copying ROM\n")); - memcpy(data, rom_adr, *len); - D(bug("Deleting area\n")); - delete_area(area); - return B_NO_ERROR; -} - - -/* - * sheep_write - hook function for the write call - */ - -static status_t sheep_write(void *cookie, off_t pos, const void *data, size_t *len) -{ - D(bug("write() pos %Lx, data %p, len %08x\n", pos, data, *len)); - return B_READ_ONLY_DEVICE; -} diff --git a/BasiliskII/src/BeOS/SheepDriver/sheep_driver.h b/BasiliskII/src/BeOS/SheepDriver/sheep_driver.h deleted file mode 100644 index 8486a021..00000000 --- a/BasiliskII/src/BeOS/SheepDriver/sheep_driver.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * sheep_driver.h - Low memory and ROM access driver for SheepShaver and - * Basilisk II on PowerPC systems - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SHEEP_DRIVER_H -#define SHEEP_DRIVER_H - -#include - -enum { - SHEEP_UP = B_DEVICE_OP_CODES_END + 1, - SHEEP_DOWN -}; - -#endif diff --git a/BasiliskII/src/BeOS/SheepNet/Makefile b/BasiliskII/src/BeOS/SheepNet/Makefile deleted file mode 100644 index 36b882fc..00000000 --- a/BasiliskII/src/BeOS/SheepNet/Makefile +++ /dev/null @@ -1,115 +0,0 @@ -## BeOS Generic Makefile v2.1 ## - -## Fill in this file to specify the project being created, and the referenced -## makefile-engine will do all of the hard work for you. This handles both -## Intel and PowerPC builds of the BeOS. - -## Application Specific Settings --------------------------------------------- - -# specify the name of the binary -NAME= sheep_net - -# specify the type of binary -# APP: Application -# SHARED: Shared library or add-on -# STATIC: Static library archive -# DRIVER: Kernel Driver -TYPE= SHARED - -# add support for new Pe and Eddie features -# to fill in generic makefile - -#%{ -# @src->@ - -# specify the source files to use -# full paths or paths relative to the makefile can be included -# all files, regardless of directory, will have their object -# files created in the common object directory. -# Note that this means this makefile will not work correctly -# if two source files with the same name (source.c or source.cpp) -# are included from different directories. Also note that spaces -# in folder names do not work well with this makefile. -SRCS= sheep_net.cpp - -# specify the resource files to use -# full path or a relative path to the resource file can be used. -RSRCS= - -# @<-src@ -#%} - -# end support for Pe and Eddie - -# specify additional libraries to link against -# there are two acceptable forms of library specifications -# - if your library follows the naming pattern of: -# libXXX.so or libXXX.a you can simply specify XXX -# library: libbe.so entry: be -# -# - if your library does not follow the standard library -# naming scheme you need to specify the path to the library -# and it's name -# library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS= netdev - -# specify additional paths to directories following the standard -# libXXX.so or libXXX.a naming scheme. You can specify full paths -# or paths relative to the makefile. The paths included may not -# be recursive, so include all of the paths where libraries can -# be found. Directories where source files are found are -# automatically included. -LIBPATHS= - -# additional paths to look for system headers -# thes use the form: #include
-# source file directories are NOT auto-included here -SYSTEM_INCLUDE_PATHS = - -# additional paths to look for local headers -# thes use the form: #include "header" -# source file directories are automatically included -LOCAL_INCLUDE_PATHS = - -# specify the level of optimization that you desire -# NONE, SOME, FULL -OPTIMIZE= FULL - -# specify any preprocessor symbols to be defined. The symbols will not -# have their values set automatically; you must supply the value (if any) -# to use. For example, setting DEFINES to "DEBUG=1" will cause the -# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" -# would pass "-DDEBUG" on the compiler's command line. -DEFINES= - -# specify special warning levels -# if unspecified default warnings will be used -# NONE = supress all warnings -# ALL = enable all warnings -WARNINGS = - -# specify whether image symbols will be created -# so that stack crawls in the debugger are meaningful -# if TRUE symbols will be created -SYMBOLS = - -# specify debug settings -# if TRUE will allow application to be run from a source-level -# debugger. Note that this will disable all optimzation. -DEBUGGER = - -# specify additional compiler flags for all files -COMPILER_FLAGS = - -# specify additional linker flags -LINKER_FLAGS = - - -## include the makefile-engine -include /boot/develop/etc/makefile-engine - -install: $(TARGET) - cp $(TARGET) /boot/beos/system/add-ons/net_server/$(NAME) - -uninstall: - rm /boot/beos/system/add-ons/net_server/$(NAME) diff --git a/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp b/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp deleted file mode 100644 index c026293c..00000000 --- a/BasiliskII/src/BeOS/SheepNet/sheep_net.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * sheep_net.cpp - Net server add-on for SheepShaver and Basilisk II - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sheep_net.h" - -#define DEBUG 0 - -#if DEBUG==1 -#define bug pprintf -#elif DEBUG==2 -#define bug kprintf -#endif - -#if DEBUG -#define D(x) (x) -#else -#define D(x) ; -#endif - -static int pprintf(const char* format, ...) -{ - port_id PortNum; - int len,Ret; - char Buffer[1024]; - va_list ap; - - if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND) - return(PortNum); - for (len=0; len<1024; len++) - Buffer[len]='\0'; - va_start(ap, format); - vsprintf(Buffer, format, ap); - Ret = write_port(PortNum, 0, Buffer, strlen(Buffer)); - return(Ret); -} - - -// Constants -#define NETDUMP_PRIO 1 // Default is 0 - -const uint32 buffer_size = (sizeof(net_buffer) / B_PAGE_SIZE + 1) * B_PAGE_SIZE; - - -// SheepNet add-on object -class SheepNetAddOn : public BNetProtocol, BPacketHandler { -public: - void AddDevice(BNetDevice *dev, const char *name); - bool PacketReceived(BNetPacket *buf, BNetDevice *dev); -}; - - -// Global variables -static bool shutdown_now = false; -static bool active = false; - -static thread_id write_thread; // Packet writer -static sem_id write_sem; // Semaphore to trigger packet writing -static BNetDevice *EtherCard = NULL; // The Ethernet card we are attached to -static area_id buffer_area; // Packet buffer area -static net_buffer *net_buffer_ptr; // Pointer to packet buffer - -static uint32 rd_pos; // Current read position in packet buffer -static uint32 wr_pos; // Current write position in packet buffer - - -/* - * Clear packet buffer - */ - -static void clear(void) -{ - int i; - for (i=0;iread[i].cmd = 0; - net_buffer_ptr->read[i].length = 0; - net_buffer_ptr->read[i].card = 0; - net_buffer_ptr->read[i].reserved = 0; - } - for (i=0;iwrite[i].cmd = 0; - net_buffer_ptr->write[i].length = 0; - net_buffer_ptr->write[i].card = 0; - net_buffer_ptr->write[i].reserved = 0; - } - rd_pos = wr_pos = 0; -} - - -/* - * Packet writer thread - */ - -static status_t write_packet_func(void *arg) -{ - while (!shutdown_now) { - - // Read and execute command - net_packet *p = &net_buffer_ptr->write[wr_pos]; - while (p->cmd & IN_USE) { - D(bug("wp: %d\n", wr_pos)); - switch (p->cmd >> 8) { - - case ACTIVATE_SHEEP_NET: - D(bug("activate sheep-net\n")); - active = false; - clear(); - active = true; - goto next; - - case DEACTIVATE_SHEEP_NET: - D(bug("deactivate sheep-net\n")); - active = false; - clear(); - goto next; - - case SHUTDOWN_SHEEP_NET: - D(bug("shutdown sheep-net\n")); - active = false; - clear(); - shutdown_now = true; - goto next; - - case ADD_MULTICAST: { - const char *data = (const char *)p->data; - D(bug("add multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5])); - if (active) { - status_t result; - if ((result = EtherCard->AddMulticastAddress(data)) != B_OK) { - // !! handle error !! error while creating multicast address - D(bug("error while creating multicast address %d\n", result)); - } - } - break; - } - - case REMOVE_MULTICAST: { - const char *data = (const char *)p->data; - D(bug("remove multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5])); - if (active) { - status_t result; - if ((result = EtherCard->RemoveMulticastAddress(data)) != B_OK) { - // !! handle error !! error while removing multicast address - D(bug("error while removing multicast address %d\n", result)); - } - } - break; - } - - case SHEEP_PACKET: { - uint32 length = p->length; - // D(bug("sheep packet %d\n", length)); - if (active) { - BStandardPacket *packet = new BStandardPacket(length); - packet->Write(0, (const char *)p->data, length); - EtherCard->SendPacket(packet); - } - break; - } - - default: - D(bug("error: unknown port packet type\n")); - break; - } - p->cmd = 0; // Free packet - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - p = &net_buffer_ptr->write[wr_pos]; - } - - // Wait for next packet -next: acquire_sem_etc(write_sem, 1, B_TIMEOUT, 25000); - } - return 0; -} - - -/* - * Init the net add-on - */ - -static void init_addon() -{ - int i; - D(bug("init sheep-net\n")); - - // Create packet buffer - if ((buffer_area = create_area("packet buffer", (void **)&net_buffer_ptr, B_ANY_ADDRESS, buffer_size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_NO_ERROR) { - D(bug("FATAL ERROR: can't create shared area\n")); - return; - } - - // Init packet buffer - clear(); - EtherCard->Address((char *)net_buffer_ptr->ether_addr); - net_buffer_ptr->read_sem = -1; - net_buffer_ptr->read_ofs = (uint32)(net_buffer_ptr->read) - (uint32)net_buffer_ptr; - net_buffer_ptr->read_packet_size = sizeof(net_packet); - net_buffer_ptr->read_packet_count = READ_PACKET_COUNT; - if ((write_sem = create_sem(0, "ether write")) < B_NO_ERROR) { - D(bug("FATAL ERROR: can't create semaphore\n")); - return; - } - net_buffer_ptr->write_sem = write_sem; - net_buffer_ptr->write_ofs = (uint32)(net_buffer_ptr->write) - (uint32)net_buffer_ptr; - net_buffer_ptr->write_packet_size = sizeof(net_packet); - net_buffer_ptr->write_packet_count = WRITE_PACKET_COUNT; - - // Start packet writer thread - write_thread = spawn_thread(write_packet_func, "sheep_net ether write", B_URGENT_DISPLAY_PRIORITY, NULL); - resume_thread(write_thread); -} - - -/* - * Add-on attached to Ethernet card - */ - -void SheepNetAddOn::AddDevice(BNetDevice *dev, const char *name) -{ - if (dev->Type() != B_ETHER_NET_DEVICE) - return; - if (EtherCard != NULL) { - // !! handle error !! support for multiple ethernet cards ... - D(bug("error: SheepShaver doesn't support multiple Ethernetcards !\n")); - return; - } - EtherCard = dev; - init_addon(); - register_packet_handler(this, dev, NETDUMP_PRIO); -} - - -/* - * Ethernet packet received - */ - -bool SheepNetAddOn::PacketReceived(BNetPacket *pkt, BNetDevice *dev) -{ - if (shutdown_now) { - unregister_packet_handler(this, dev); - return false; - } -// D(bug("read_packet_func %d\n", pkt->Size())); - if (active) { - D(bug("rp: %d\n", rd_pos)); - net_packet *p = &net_buffer_ptr->read[rd_pos]; - if (p->cmd & IN_USE) { - D(bug("error: full read buffer ... lost packet\n")); - } else { - memcpy(p->data, pkt->Data(), pkt->Size()); - p->length = pkt->Size(); - p->cmd = IN_USE | (SHEEP_PACKET << 8); - rd_pos = (rd_pos + 1) % READ_PACKET_COUNT; - release_sem(net_buffer_ptr->read_sem); - } - } - //D(bug("%02x %02x %02x %02x %02x %02x", (uchar) (pkt->Data())[0],(uchar) (pkt->Data())[1],(uchar) (pkt->Data())[2],(uchar) (pkt->Data())[3],(uchar) (pkt->Data())[4],(uchar) (pkt->Data())[5])); - return false; -} - -#pragma export on -extern "C" BNetProtocol *open_protocol(const char *device) -{ - SheepNetAddOn *dev = new SheepNetAddOn; - return dev; -} -#pragma export off diff --git a/BasiliskII/src/BeOS/SheepNet/sheep_net.h b/BasiliskII/src/BeOS/SheepNet/sheep_net.h deleted file mode 100644 index d4585b4d..00000000 --- a/BasiliskII/src/BeOS/SheepNet/sheep_net.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * sheep_net.h - Net server add-on for SheepShaver and Basilisk II - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SHEEP_NET_H -#define SHEEP_NET_H - -// Net buffer dimensions -#define READ_PACKET_COUNT 10 -#define WRITE_PACKET_COUNT 10 - -// Net packet -struct net_packet { - uint32 cmd; // Command - uint32 length; // Data length - uint32 card; // Network card ID - uint32 reserved; - uint8 data[1584]; -}; - -// Net buffer (shared area) -struct net_buffer { - uint8 ether_addr[6]; // Ethernet address - uint8 filler1[2]; - sem_id read_sem; // Semaphore for read packets - uint32 read_ofs; - uint32 read_packet_size; - uint32 read_packet_count; - sem_id write_sem; // Semaphore for write packets - uint32 write_ofs; - uint32 write_packet_size; - uint32 write_packet_count; - uint8 filler[24]; - net_packet read[READ_PACKET_COUNT]; - net_packet write[WRITE_PACKET_COUNT]; -}; - -// Packet commands -#define SHEEP_PACKET 0 -#define ADD_MULTICAST 1 -#define REMOVE_MULTICAST 2 -#define ACTIVATE_SHEEP_NET 8 -#define DEACTIVATE_SHEEP_NET 9 -#define SHUTDOWN_SHEEP_NET 10 - -#define IN_USE 1 - -#endif diff --git a/BasiliskII/src/BeOS/about_window.cpp b/BasiliskII/src/BeOS/about_window.cpp deleted file mode 100644 index 94f9944e..00000000 --- a/BasiliskII/src/BeOS/about_window.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * about_window.cpp - "About" window - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "sysdeps.h" -#include "version.h" -#include "user_strings.h" - -/* - * Display "About" window - */ - -void ShowAboutWindow(void) -{ - char str[512]; - sprintf(str, - "Basilisk II\nVersion %d.%d\n\n" - "Copyright " B_UTF8_COPYRIGHT " 1997-2008 Christian Bauer et al.\n" - "E-mail: Christian.Bauer@uni-mainz.de\n" - "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n" - "Basilisk II comes with ABSOLUTELY NO\n" - "WARRANTY. This is free software, and\n" - "you are welcome to redistribute it\n" - "under the terms of the GNU General\n" - "Public License.\n", - VERSION_MAJOR, VERSION_MINOR - ); - BAlert *about = new BAlert("", str, GetString(STR_OK_BUTTON), NULL, NULL, B_WIDTH_FROM_LABEL); - BTextView *theText = about->TextView(); - if (theText) { - theText->SetStylable(true); - theText->Select(0, 11); - BFont ourFont; - theText->SetFontAndColor(be_bold_font); - theText->GetFontAndColor(2, &ourFont, NULL); - ourFont.SetSize(24); - theText->SetFontAndColor(&ourFont); - } - about->Go(); -} diff --git a/BasiliskII/src/BeOS/about_window.h b/BasiliskII/src/BeOS/about_window.h deleted file mode 100644 index 1960c976..00000000 --- a/BasiliskII/src/BeOS/about_window.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * about_window.h - "About" window - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ABOUT_WINDOW_H -#define ABOUT_WINDOW_H - -// Display "About" window -extern void ShowAboutWindow(void); - -#endif diff --git a/BasiliskII/src/BeOS/audio_beos.cpp b/BasiliskII/src/BeOS/audio_beos.cpp deleted file mode 100644 index 02654587..00000000 --- a/BasiliskII/src/BeOS/audio_beos.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - * audio_beos.cpp - Audio support, BeOS implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * Portions written by Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "audio.h" -#include "audio_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static int audio_irq_done_sem = -1; // Signal from interrupt to streaming thread: data block read -static BSoundPlayer *the_player; - -// Prototypes -static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format); - - -/* - * Audio manager thread (for calling media kit functions; - * this is not safe under R4 when running on the MacOS stack in kernel space) - */ - -// Message constants -const uint32 MSG_QUIT_AUDIO_MANAGER = 'quit'; -const uint32 MSG_ENTER_STREAM = 'entr'; -const uint32 MSG_EXIT_STREAM = 'exit'; -const uint32 MSG_GET_VOLUME = 'getv'; -const uint32 MSG_SET_VOLUME = 'setv'; - -static thread_id am_thread = -1; -static sem_id am_done_sem = -1; - -static volatile float am_volume; - -static status_t audio_manager(void *arg) -{ - for (;;) { - - // Receive message - thread_id sender; - uint32 code = receive_data(&sender, NULL, 0); - D(bug("Audio manager received %08lx\n", code)); - switch (code) { - case MSG_QUIT_AUDIO_MANAGER: - return 0; - - case MSG_ENTER_STREAM: - the_player->Start(); - break; - - case MSG_EXIT_STREAM: - the_player->Stop(); - break; - - case MSG_GET_VOLUME: - am_volume = the_player->Volume(); - break; - - case MSG_SET_VOLUME: - the_player->SetVolume(am_volume); - break; - } - - // Acknowledge - release_sem(am_done_sem); - } -} - - -/* - * Initialization - */ - -// Set AudioStatus to reflect current audio stream format -static void set_audio_status_format(void) -{ - AudioStatus.sample_rate = audio_sample_rates[0]; - AudioStatus.sample_size = audio_sample_sizes[0]; - AudioStatus.channels = audio_channel_counts[0]; -} - -void AudioInit(void) -{ - // Init audio status and feature flags - audio_sample_rates.push_back(44100 << 16); - audio_sample_sizes.push_back(16); - audio_channel_counts.push_back(2); - set_audio_status_format(); - AudioStatus.mixer = 0; - AudioStatus.num_sources = 0; - audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut; - - // Sound disabled in prefs? Then do nothing - if (PrefsFindBool("nosound")) - return; - - // Init semaphores - audio_irq_done_sem = create_sem(0, "Audio IRQ Done"); - am_done_sem = create_sem(0, "Audio Manager Done"); - - // Start audio manager thread - am_thread = spawn_thread(audio_manager, "Audio Manager", B_NORMAL_PRIORITY, NULL); - resume_thread(am_thread); - - // Start stream - media_raw_audio_format format; - format.frame_rate = AudioStatus.sample_rate >> 16; - format.channel_count = AudioStatus.channels; - format.format = media_raw_audio_format::B_AUDIO_SHORT; - format.byte_order = B_MEDIA_BIG_ENDIAN; - audio_frames_per_block = 4096; - size_t block_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block; - D(bug("AudioInit: block size %d\n", block_size)); - format.buffer_size = block_size; - the_player = new BSoundPlayer(&format, "MacOS Audio", playbuffer_func, NULL, NULL); - if (the_player->InitCheck() != B_NO_ERROR) { - printf("FATAL: Cannot initialize BSoundPlayer\n"); - delete the_player; - the_player = NULL; - return; - } else - the_player->SetHasData(true); - - // Everything OK - audio_open = true; -} - - -/* - * Deinitialization - */ - -void AudioExit(void) -{ - // Stop stream - if (the_player) { - the_player->Stop(); - delete the_player; - the_player = NULL; - } - - // Stop audio manager - if (am_thread > 0) { - status_t l; - send_data(am_thread, MSG_QUIT_AUDIO_MANAGER, NULL, 0); - wait_for_thread(am_thread, &l); - } - - // Delete semaphores - delete_sem(am_done_sem); - delete_sem(audio_irq_done_sem); -} - - -/* - * First source added, start audio stream - */ - -void audio_enter_stream() -{ - while (send_data(am_thread, MSG_ENTER_STREAM, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(am_done_sem) == B_INTERRUPTED) ; -} - - -/* - * Last source removed, stop audio stream - */ - -void audio_exit_stream() -{ - while (send_data(am_thread, MSG_EXIT_STREAM, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(am_done_sem) == B_INTERRUPTED) ; -} - - -/* - * Streaming function - */ - -static uint32 apple_stream_info; // Mac address of SoundComponentData struct describing next buffer - -static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format) -{ - // Check if new buffer is available - if (acquire_sem_etc(audio_irq_done_sem, 1, B_TIMEOUT, 0) == B_NO_ERROR) { - - // Get size of audio data - D(bug("stream: new buffer present\n")); - uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo); - if (apple_stream_info) { - size_t work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels; - D(bug("stream: size %d, work_size %d\n", size, work_size)); - if (work_size > size) - work_size = size; - - if (format.format != media_raw_audio_format::B_AUDIO_SHORT) { - D(bug("Wrong audio format %04x\n", format.format)); - return; - } - - // Place data into Media Kit buffer - Mac2Host_memcpy(buf, ReadMacInt32(apple_stream_info + scd_buffer), work_size); - if (work_size != size) - memset((uint8 *)buf + work_size, 0, size - work_size); - } - - } else - memset(buf, 0, size); - - // Trigger audio interrupt to get new buffer - if (AudioStatus.num_sources) { - D(bug("stream: triggering irq\n")); - SetInterruptFlag(INTFLAG_AUDIO); - TriggerInterrupt(); - } -} - - -/* - * MacOS audio interrupt, read next data block - */ - -void AudioInterrupt(void) -{ - D(bug("AudioInterrupt\n")); - - // Get data from apple mixer - if (AudioStatus.mixer) { - M68kRegisters r; - r.a[0] = audio_data + adatStreamInfo; - r.a[1] = AudioStatus.mixer; - Execute68k(audio_data + adatGetSourceData, &r); - D(bug(" GetSourceData() returns %08lx\n", r.d[0])); - } else - WriteMacInt32(audio_data + adatStreamInfo, 0); - - // Signal stream function - release_sem(audio_irq_done_sem); - D(bug("AudioInterrupt done\n")); -} - - -/* - * Set sampling parameters - * "index" is an index into the audio_sample_rates[] etc. arrays - * It is guaranteed that AudioStatus.num_sources == 0 - */ - -bool audio_set_sample_rate(int index) -{ - return true; -} - -bool audio_set_sample_size(int index) -{ - return true; -} - -bool audio_set_channels(int index) -{ - return true; -} - - -/* - * Get/set audio info - */ - -bool audio_get_main_mute(void) -{ - return false; -} - -uint32 audio_get_main_volume(void) -{ - if (audio_open) { - while (send_data(am_thread, MSG_GET_VOLUME, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(am_done_sem) == B_INTERRUPTED) ; - return int(am_volume * 256.0) * 0x00010001; - } else - return 0x01000100; -} - -bool audio_get_speaker_mute(void) -{ - return false; -} - -uint32 audio_get_speaker_volume(void) -{ - return 0x01000100; -} - -void audio_set_main_mute(bool mute) -{ -} - -void audio_set_main_volume(uint32 vol) -{ - if (audio_open) { - am_volume = float((vol >> 16) + (vol & 0xffff)) / 512.0; - while (send_data(am_thread, MSG_SET_VOLUME, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(am_done_sem) == B_INTERRUPTED) ; - } -} - -void audio_set_speaker_mute(bool mute) -{ -} - -void audio_set_speaker_volume(uint32 vol) -{ -} diff --git a/BasiliskII/src/BeOS/clip_beos.cpp b/BasiliskII/src/BeOS/clip_beos.cpp deleted file mode 100644 index 10159ec6..00000000 --- a/BasiliskII/src/BeOS/clip_beos.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * clip_beos.cpp - Clipboard handling, BeOS implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include - -#include "clip.h" -#include "prefs.h" - -#define DEBUG 1 -#include "debug.h" - - -// Flag: Don't convert clipboard text -static bool no_clip_conversion; - - -/* - * Initialization - */ - -void ClipInit(void) -{ - no_clip_conversion = PrefsFindBool("noclipconversion"); -} - - -/* - * Deinitialization - */ - -void ClipExit(void) -{ -} - -/* - * Mac application zeroes clipboard - */ - -void ZeroScrap() -{ - -} - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32 type, int32 offset) -{ - D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); -} - - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32 type, void *scrap, int32 length) -{ - D(bug("PutScrap type %08lx, data %08lx, length %ld\n", type, scrap, length)); - if (length <= 0) - return; - - switch (type) { - case 'TEXT': - D(bug(" clipping TEXT\n")); - if (be_clipboard->Lock()) { - be_clipboard->Clear(); - BMessage *clipper = be_clipboard->Data(); - - if (no_clip_conversion) { - - // Only convert CR->LF - char *buf = new char[length]; - for (int i=0; iAddData("text/plain", B_MIME_TYPE, buf, length); - be_clipboard->Commit(); - delete[] buf; - - } else { - - // Convert text from Mac charset to UTF-8 - int32 dest_length = length*3; - int32 state = 0; - char *buf = new char[dest_length]; - if (convert_to_utf8(B_MAC_ROMAN_CONVERSION, (char *)scrap, &length, buf, &dest_length, &state) == B_OK) { - for (int i=0; iAddData("text/plain", B_MIME_TYPE, buf, dest_length); - be_clipboard->Commit(); - } - delete[] buf; - } - be_clipboard->Unlock(); - } - break; - } -} diff --git a/BasiliskII/src/BeOS/ether_beos.cpp b/BasiliskII/src/BeOS/ether_beos.cpp deleted file mode 100644 index ebc85daa..00000000 --- a/BasiliskII/src/BeOS/ether_beos.cpp +++ /dev/null @@ -1,532 +0,0 @@ -/* - * ether_beos.cpp - Ethernet device driver, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * Portions written by Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef __HAIKU__ -#include -#include -#endif - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "macos_util.h" -#include "ether.h" -#include "ether_defs.h" - -#include "sheep_net.h" - -#define DEBUG 0 -#include "debug.h" - -#define MONITOR 0 - - -// List of attached protocols -struct NetProtocol { - uint16 type; - uint32 handler; -}; - -static BList prot_list; - - -// Global variables -static thread_id read_thread; // Packet reception thread -static bool ether_thread_active = true; // Flag for quitting the reception thread - -static area_id buffer_area; // Packet buffer area -static net_buffer *net_buffer_ptr; // Pointer to packet buffer -static uint32 rd_pos; // Current read position in packet buffer -static uint32 wr_pos; // Current write position in packet buffer -static sem_id read_sem, write_sem; // Semaphores to trigger packet reading/writing - -static int fd = -1; // UDP socket fd -static bool udp_tunnel = false; - - -// Prototypes -static status_t receive_proc(void *data); - - -/* - * Find protocol in list - */ - -static NetProtocol *find_protocol(uint16 type) -{ - // All 802.2 types are the same - if (type <= 1500) - type = 0; - - // Search list (we could use hashing here but there are usually only three - // handlers installed: 0x0000 for AppleTalk and 0x0800/0x0806 for TCP/IP) - NetProtocol *p; - for (int i=0; (p = (NetProtocol *)prot_list.ItemAt(i)) != NULL; i++) - if (p->type == type) - return p; - return NULL; -} - - -/* - * Remove all protocols - */ - -static void remove_all_protocols(void) -{ - NetProtocol *p; - while ((p = (NetProtocol *)prot_list.RemoveItem((long)0)) != NULL) - delete p; -} - - -/* - * Initialization - */ - -bool ether_init(void) -{ - // Do nothing if no Ethernet device specified - if (PrefsFindString("ether") == NULL) - return false; - - // Find net_server team -i_wanna_try_that_again: - bool found_add_on = false; - team_info t_info; - int32 t_cookie = 0; - image_info i_info; - int32 i_cookie = 0; - while (get_next_team_info(&t_cookie, &t_info) == B_NO_ERROR) { - if (strstr(t_info.args,"net_server")!=NULL) { - - // Check if sheep_net add-on is loaded - while (get_next_image_info(t_info.team, &i_cookie, &i_info) == B_NO_ERROR) { - if (strstr(i_info.name, "sheep_net") != NULL) { - found_add_on = true; - break; - } - } - } - if (found_add_on) break; - } - if (!found_add_on) { - - // Search for sheep_net in network config file - char str[1024]; - bool sheep_net_found = false; - FILE *fin = fopen("/boot/home/config/settings/network", "r"); - while (!feof(fin)) { - fgets(str, 1024, fin); - if (strstr(str, "PROTOCOLS")) - if (strstr(str, "sheep_net")) - sheep_net_found = true; - } - fclose(fin); - - // It was found, so something else must be wrong - if (sheep_net_found) { - WarningAlert(GetString(STR_NO_NET_ADDON_WARN)); - return false; - } - - // Not found, inform the user - if (!ChoiceAlert(GetString(STR_NET_CONFIG_MODIFY_WARN), GetString(STR_OK_BUTTON), GetString(STR_CANCEL_BUTTON))) - return false; - - // Change the network config file and restart the network - fin = fopen("/boot/home/config/settings/network", "r"); - FILE *fout = fopen("/boot/home/config/settings/network.2", "w"); - bool global_found = false; - bool modified = false; - while (!feof(fin)) { - str[0] = 0; - fgets(str, 1024, fin); - if (!global_found && strstr(str, "GLOBAL:")) { - global_found = true; - } else if (global_found && !modified && strstr(str, "PROTOCOLS")) { - str[strlen(str)-1] = 0; - strcat(str, " sheep_net\n"); - modified = true; - } else if (global_found && !modified && strlen(str) > 2 && str[strlen(str) - 2] == ':') { - fputs("\tPROTOCOLS = sheep_net\n", fout); - modified = true; - } - fputs(str, fout); - } - if (!modified) - fputs("\tPROTOCOLS = sheep_net\n", fout); - fclose(fout); - fclose(fin); - remove("/boot/home/config/settings/network.orig"); - rename("/boot/home/config/settings/network", "/boot/home/config/settings/network.orig"); - rename("/boot/home/config/settings/network.2", "/boot/home/config/settings/network"); - - app_info ai; - if (be_roster->GetAppInfo("application/x-vnd.Be-NETS", &ai) == B_OK) { - BMessenger msg(NULL, ai.team); - if (msg.IsValid()) { - while (be_roster->IsRunning("application/x-vnd.Be-NETS")) { - msg.SendMessage(B_QUIT_REQUESTED); - snooze(500000); - } - } - } - BPath path; - find_directory(B_BEOS_BOOT_DIRECTORY, &path); - path.Append("Netscript"); - const char *argv[3] = {"/bin/sh", path.Path(), NULL}; - thread_id net_server = load_image(2, argv, (const char **)environ); - resume_thread(net_server); - status_t l; - wait_for_thread(net_server, &l); - goto i_wanna_try_that_again; - } - - // Set up communications with add-on - area_id handler_buffer; - if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) { - WarningAlert(GetString(STR_NET_ADDON_INIT_FAILED)); - return false; - } - if ((buffer_area = clone_area("local packet buffer", (void **)&net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) { - D(bug("EtherInit: couldn't clone packet area\n")); - WarningAlert(GetString(STR_NET_ADDON_CLONE_FAILED)); - return false; - } - if ((read_sem = create_sem(0, "ether read")) < B_NO_ERROR) { - printf("FATAL: can't create Ethernet semaphore\n"); - return false; - } - net_buffer_ptr->read_sem = read_sem; - write_sem = net_buffer_ptr->write_sem; - read_thread = spawn_thread(receive_proc, "Ethernet Receiver", B_URGENT_DISPLAY_PRIORITY, NULL); - resume_thread(read_thread); - for (int i=0; iwrite[i].cmd = IN_USE | (ACTIVATE_SHEEP_NET << 8); - rd_pos = wr_pos = 0; - release_sem(write_sem); - - // Get Ethernet address - memcpy(ether_addr, net_buffer_ptr->ether_addr, 6); - D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - - // Everything OK - return true; -} - - -/* - * Deinitialization - */ - -void ether_exit(void) -{ - // Close communications with add-on - for (int i=0; iwrite[i].cmd = IN_USE | (DEACTIVATE_SHEEP_NET << 8); - release_sem(write_sem); - - // Quit reception thread - ether_thread_active = false; - status_t result; - release_sem(read_sem); - wait_for_thread(read_thread, &result); - - delete_sem(read_sem); - delete_area(buffer_area); - - // Remove all protocols - remove_all_protocols(); -} - - -/* - * Reset - */ - -void ether_reset(void) -{ - remove_all_protocols(); -} - - -/* - * Add multicast address - */ - -int16 ether_add_multicast(uint32 pb) -{ - net_packet *p = &net_buffer_ptr->write[wr_pos]; - if (p->cmd & IN_USE) { - D(bug("WARNING: Couldn't enable multicast address\n")); - } else { - Mac2Host_memcpy(p->data, pb + eMultiAddr, 6); - p->length = 6; - p->cmd = IN_USE | (ADD_MULTICAST << 8); - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - release_sem(write_sem); - } - return noErr; -} - - -/* - * Delete multicast address - */ - -int16 ether_del_multicast(uint32 pb) -{ - net_packet *p = &net_buffer_ptr->write[wr_pos]; - if (p->cmd & IN_USE) { - D(bug("WARNING: Couldn't enable multicast address\n")); - } else { - Mac2Host_memcpy(p->data, pb + eMultiAddr, 6); - p->length = 6; - p->cmd = IN_USE | (REMOVE_MULTICAST << 8); - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - release_sem(write_sem); - } - return noErr; -} - - -/* - * Attach protocol handler - */ - -int16 ether_attach_ph(uint16 type, uint32 handler) -{ - // Already attached? - NetProtocol *p = find_protocol(type); - if (p != NULL) - return lapProtErr; - else { - // No, create and attach - p = new NetProtocol; - p->type = type; - p->handler = handler; - prot_list.AddItem(p); - return noErr; - } -} - - -/* - * Detach protocol handler - */ - -int16 ether_detach_ph(uint16 type) -{ - NetProtocol *p = find_protocol(type); - if (p != NULL) { - prot_list.RemoveItem(p); - delete p; - return noErr; - } else - return lapProtErr; -} - - -/* - * Transmit raw ethernet packet - */ - -int16 ether_write(uint32 wds) -{ - net_packet *p = &net_buffer_ptr->write[wr_pos]; - if (p->cmd & IN_USE) { - D(bug("WARNING: Couldn't transmit packet (buffer full)\n")); - } else { - - // Copy packet to buffer - int len = ether_wds_to_buffer(wds, p->data); - -#if MONITOR - bug("Sending Ethernet packet:\n"); - for (int i=0; idata[i]); - } - bug("\n"); -#endif - - // Notify add-on - p->length = len; - p->cmd = IN_USE | (SHEEP_PACKET << 8); - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - release_sem(write_sem); - } - return noErr; -} - - -/* - * Packet reception thread (non-UDP) - */ - -static status_t receive_proc(void *data) -{ - while (ether_thread_active) { - if (net_buffer_ptr->read[rd_pos].cmd & IN_USE) { - D(bug(" packet received, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - } - acquire_sem_etc(read_sem, 1, B_TIMEOUT, 25000); - } - return 0; -} - - -/* - * Packet reception thread (UDP) - */ - -static status_t receive_proc_udp(void *data) -{ - while (ether_thread_active) { - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0) { - D(bug(" packet received, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - } - } - return 0; -} - - -/* - * Start UDP packet reception thread - */ - -bool ether_start_udp_thread(int socket_fd) -{ - fd = socket_fd; - udp_tunnel = true; - ether_thread_active = true; - read_thread = spawn_thread(receive_proc_udp, "UDP Receiver", B_URGENT_DISPLAY_PRIORITY, NULL); - resume_thread(read_thread); - return true; -} - - -/* - * Stop UDP packet reception thread - */ - -void ether_stop_udp_thread(void) -{ - ether_thread_active = false; - status_t result; - wait_for_thread(read_thread, &result); -} - - -/* - * Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers - */ - -void EtherInterrupt(void) -{ - D(bug("EtherIRQ\n")); - EthernetPacket ether_packet; - uint32 packet = ether_packet.addr(); - - if (udp_tunnel) { - - ssize_t length; - - // Read packets from socket and hand to ether_udp_read() for processing - while (true) { - struct sockaddr_in from; - socklen_t from_len = sizeof(from); - length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len); - if (length < 14) - break; - ether_udp_read(packet, length, &from); - } - - } else { - - // Call protocol handler for received packets - net_packet *p = &net_buffer_ptr->read[rd_pos]; - while (p->cmd & IN_USE) { - if ((p->cmd >> 8) == SHEEP_PACKET) { - Host2Mac_memcpy(packet, p->data, p->length); -#if MONITOR - bug("Receiving Ethernet packet:\n"); - for (int i=0; ilength; i++) { - bug("%02x ", ReadMacInt8(packet + i)); - } - bug("\n"); -#endif - // Get packet type - uint16 type = ReadMacInt16(packet + 12); - - // Look for protocol - NetProtocol *prot = find_protocol(type); - if (prot == NULL) - goto next; - - // No default handler - if (prot->handler == 0) - goto next; - - // Copy header to RHA - Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14); - D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); - - // Call protocol handler - M68kRegisters r; - r.d[0] = type; // Packet type - r.d[1] = p->length - 14; // Remaining packet length (without header, for ReadPacket) - r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket) - r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA - r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines - D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); - Execute68k(prot->handler, &r); - } -next: p->cmd = 0; // Free packet - rd_pos = (rd_pos + 1) % READ_PACKET_COUNT; - p = &net_buffer_ptr->read[rd_pos]; - } - } - D(bug(" EtherIRQ done\n")); -} diff --git a/BasiliskII/src/BeOS/extfs_beos.cpp b/BasiliskII/src/BeOS/extfs_beos.cpp deleted file mode 100644 index 5b7ab4d6..00000000 --- a/BasiliskII/src/BeOS/extfs_beos.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* - * extfs_beos.cpp - MacOS file system for access native file system access, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "extfs.h" -#include "extfs_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -// Default Finder flags -const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited; - -// Temporary buffer for transfers from/to kernel space -const int TMP_BUF_SIZE = 0x10000; -static uint8 *tmp_buf = NULL; - - -/* - * Initialization - */ - -void extfs_init(void) -{ - // Allocate temporary buffer - tmp_buf = new uint8[TMP_BUF_SIZE]; -} - - -/* - * Deinitialization - */ - -void extfs_exit(void) -{ - // Delete temporary buffer - delete[] tmp_buf; -} - - -/* - * Add component to path name - */ - -void add_path_component(char *path, const char *component) -{ - int l = strlen(path); - if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') { - path[l] = '/'; - path[l+1] = 0; - } - strncat(path, component, MAX_PATH_LENGTH-1); -} - - -/* - * Get/set finder info for file/directory specified by full path - */ - -struct mime2type { - const char *mime; - uint32 type; - uint32 creator; - bool reversible; // type -> mime translation possible -}; - -static const mime2type m2t_translation[] = { - {"application/x-compress", 'ZIVM', 'LZIV', true}, - {"application/x-gzip", 'Gzip', 'Gzip', true}, - {"application/x-macbinary", 'BINA', '????', false}, - {"application/mac-binhex40", 'TEXT', 'SITx', false}, - {"application/pdf", 'PDF ', 'CARO', true}, - {"application/postscript", 'TEXT', 'ttxt', false}, - {"application/x-stuffit", 'SIT!', 'SITx', true}, - {"application/x-tar", 'TARF', 'TAR ', true}, - {"application/x-uuencode", 'TEXT', 'SITx', false}, - {"application/zip", 'ZIP ', 'ZIP ', true}, - {"audio/x-8svx", '8SVX', 'SNDM', true}, - {"audio/x-aifc", 'AIFC', 'TVOD', true}, - {"audio/x-aiff", 'AIFF', 'TVOD', true}, - {"audio/basic", 'ULAW', 'TVOD', true}, - {"audio/x-midi", 'MIDI', 'TVOD', true}, - {"audio/x-mpeg", 'MPG ', 'TVOD', true}, - {"audio/x-wav", 'WAVE', 'TVOD', true}, - {"image/x-bmp", 'BMPf', 'ogle', true}, - {"image/gif", 'GIFf', 'ogle', true}, - {"image/x-ilbm", 'ILBM', 'GKON', true}, - {"image/jpeg", 'JPEG', 'ogle', true}, - {"image/jpeg", 'JFIF', 'ogle', true}, - {"image/x-photoshop", '8BPS', '8BIM', true}, - {"image/pict", 'PICT', 'ogle', true}, - {"image/png", 'PNGf', 'ogle', true}, - {"image/x-sgi", '.SGI', 'ogle', true}, - {"image/x-targa", 'TPIC', 'ogle', true}, - {"image/tiff", 'TIFF', 'ogle', true}, - {"text/html", 'TEXT', 'MOSS', false}, - {"text/plain", 'TEXT', 'ttxt', true}, - {"text/rtf", 'TEXT', 'MSWD', false}, - {"text/x-source-code", 'TEXT', 'R*ch', false}, - {"video/mpeg", 'MPEG', 'TVOD', true}, - {"video/quicktime", 'MooV', 'TVOD', true}, - {"video/x-flc", 'FLI ', 'TVOD', true}, - {"video/x-msvideo", 'VfW ', 'TVOD', true}, - {NULL, 0, 0, false} // End marker -}; - -void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Set default finder info - Mac_memset(finfo, 0, SIZEOF_FInfo); - if (fxinfo) - Mac_memset(fxinfo, 0, SIZEOF_FXInfo); - WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS); - WriteMacInt32(finfo + fdLocation, (uint32)-1); - - // Open file - int fd = open(path, O_RDONLY); - if (fd < 0) - return; - - if (!is_dir) { - - // Read BeOS MIME type - ssize_t actual = fs_read_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, tmp_buf, 256); - tmp_buf[255] = 0; - - if (actual > 0) { - - // Translate MIME type to MacOS type/creator - uint8 mactype[4]; - if (sscanf((char *)tmp_buf, "application/x-MacOS-%c%c%c%c", mactype, mactype+1, mactype+2, mactype+3) == 4) { - - // MacOS style type - WriteMacInt32(finfo + fdType, (mactype[0] << 24) | (mactype[1] << 16) | (mactype[2] << 8) | mactype[3]); - - } else { - - // MIME string, look in table - for (int i=0; m2t_translation[i].mime; i++) { - if (!strcmp((char *)tmp_buf, m2t_translation[i].mime)) { - WriteMacInt32(finfo + fdType, m2t_translation[i].type); - WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator); - break; - } - } - } - } - - // Override file type with MACOS:CREATOR attribute - if (fs_read_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4) == 4) - WriteMacInt32(finfo + fdCreator, (tmp_buf[0] << 24) | (tmp_buf[1] << 16) | (tmp_buf[2] << 8) | tmp_buf[3]); - } - - // Read MACOS:HFS_FLAGS attribute - if (fs_read_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2) == 2) - WriteMacInt16(finfo + fdFlags, (tmp_buf[0] << 8) | tmp_buf[1]); - - // Close file - close(fd); -} - -void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Open file - int fd = open(path, O_WRONLY); - if (fd < 0) - return; - - if (!is_dir) { - - // Set BEOS:TYPE attribute - uint32 type = ReadMacInt32(finfo + fdType); - if (type) { - for (int i=0; m2t_translation[i].mime; i++) { - if (m2t_translation[i].type == type && m2t_translation[i].reversible) { - fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1); - break; - } - } - } - - // Set MACOS:CREATOR attribute - uint32 creator = ReadMacInt32(finfo + fdCreator); - if (creator) { - tmp_buf[0] = creator >> 24; - tmp_buf[1] = creator >> 16; - tmp_buf[2] = creator >> 8; - tmp_buf[3] = creator; - fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4); - } - } - - // Write MACOS:HFS_FLAGS attribute - uint16 flags = ReadMacInt16(finfo + fdFlags); - if (flags != DEFAULT_FINDER_FLAGS) { - tmp_buf[0] = flags >> 8; - tmp_buf[1] = flags; - fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2); - } else - fs_remove_attr(fd, "MACOS:HFS_FLAGS"); - - // Close file - close(fd); -} - - -/* - * Resource fork emulation functions - */ - -uint32 get_rfork_size(const char *path) -{ - // Open file - int fd = open(path, O_RDONLY); - if (fd < 0) - return 0; - - // Get size of MACOS:RFORK attribute - struct attr_info info; - if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0) - info.size = 0; - - // Close file and return size - close(fd); - return info.size; -} - -int open_rfork(const char *path, int flag) -{ - // Open original file - int fd = open(path, flag); - if (fd < 0) - return -1; - - // Open temporary file for resource fork - char rname[L_tmpnam]; - tmpnam(rname); - int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666); - if (rfd < 0) { - close(fd); - return -1; - } - unlink(rname); // File will be deleted when closed - - // Get size of MACOS:RFORK attribute - struct attr_info info; - if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0) - info.size = 0; - - // Copy resource data from attribute to temporary file - if (info.size > 0) { - - // Allocate buffer - void *buf = malloc(info.size); - if (buf == NULL) { - close(rfd); - close(fd); - return -1; - } - - // Copy data - fs_read_attr(fd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, info.size); - write(rfd, buf, info.size); - lseek(rfd, 0, SEEK_SET); - - // Free buffer - if (buf) - free(buf); - } - - // Close original file - close(fd); - return rfd; -} - -void close_rfork(const char *path, int fd) -{ - if (fd < 0) - return; - - // Get size of temporary file - struct stat st; - if (fstat(fd, &st) < 0) - st.st_size = 0; - - // Open original file - int ofd = open(path, O_WRONLY); - if (ofd > 0) { - - // Copy resource data to MACOS:RFORK attribute - if (st.st_size > 0) { - - // Allocate buffer - void *buf = malloc(st.st_size); - if (buf == NULL) { - close(ofd); - close(fd); - return; - } - - // Copy data - lseek(fd, 0, SEEK_SET); - read(fd, buf, st.st_size); - fs_write_attr(ofd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, st.st_size); - - // Free buffer - if (buf) - free(buf); - - } else - fs_remove_attr(ofd, "MACOS:RFORK"); - - // Close original file - close(ofd); - } - - // Close temporary file - close(fd); -} - - -/* - * Read "length" bytes from file to "buffer", - * returns number of bytes read (or -1 on error) - */ - -static inline ssize_t sread(int fd, void *buf, size_t count) -{ - ssize_t res; - while ((res = read(fd, buf, count)) == B_INTERRUPTED) ; - return res; -} - -ssize_t extfs_read(int fd, void *buffer, size_t length) -{ - // Buffer in kernel space? - if ((uint32)buffer < 0x80000000) { - - // Yes, transfer via buffer - ssize_t actual = 0; - while (length) { - size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length; - ssize_t res = sread(fd, tmp_buf, transfer_size); - if (res < 0) - return res; - memcpy(buffer, tmp_buf, res); - buffer = (void *)((uint8 *)buffer + res); - length -= res; - actual += res; - if (res != transfer_size) - return actual; - } - return actual; - - } else { - - // No, transfer directly - return sread(fd, buffer, length); - } -} - - -/* - * Write "length" bytes from "buffer" to file, - * returns number of bytes written (or -1 on error) - */ - -static inline ssize_t swrite(int fd, void *buf, size_t count) -{ - ssize_t res; - while ((res = write(fd, buf, count)) == B_INTERRUPTED) ; - return res; -} - -ssize_t extfs_write(int fd, void *buffer, size_t length) -{ - // Buffer in kernel space? - if ((uint32)buffer < 0x80000000) { - - // Yes, transfer via buffer - ssize_t actual = 0; - while (length) { - size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length; - memcpy(tmp_buf, buffer, transfer_size); - ssize_t res = swrite(fd, tmp_buf, transfer_size); - if (res < 0) - return res; - buffer = (void *)((uint8 *)buffer + res); - length -= res; - actual += res; - if (res != transfer_size) - return actual; - } - return actual; - - } else { - - // No, transfer directly - return swrite(fd, buffer, length); - } -} - - -/* - * Remove file/directory, returns false on error (and sets errno) - */ - -bool extfs_remove(const char *path) -{ - if (remove(path) < 0) { - if (errno == EISDIR) - return rmdir(path) == 0; - else - return false; - } - return true; -} - - -/* - * Rename/move file/directory, returns false on error (and sets errno) - */ - -bool extfs_rename(const char *old_path, const char *new_path) -{ - return rename(old_path, new_path) == 0; -} - -/* - * Strings (filenames) conversion - */ - -// Convert from the host OS filename encoding to MacRoman -const char *host_encoding_to_macroman(const char *filename) -{ - int32 state = 0; - static char buffer[512]; - int32 size = sizeof(buffer) - 1; - int32 insize = strlen(filename); - convert_from_utf8(B_MAC_ROMAN_CONVERSION, filename, &insize, buffer, &size, &state); - buffer[size] = 0; - return buffer; -} - -// Convert from MacRoman to host OS filename encoding -const char *macroman_to_host_encoding(const char *filename) -{ - int32 state = 0; - static char buffer[512]; - int32 insize = strlen(filename); - int32 size = sizeof(buffer) - 1; - convert_to_utf8(B_MAC_ROMAN_CONVERSION, filename, &insize, buffer, &size, &state); - buffer[size] = 0; - return buffer; -} diff --git a/BasiliskII/src/BeOS/main_beos.cpp b/BasiliskII/src/BeOS/main_beos.cpp deleted file mode 100644 index 507e3bde..00000000 --- a/BasiliskII/src/BeOS/main_beos.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/* - * main_beos.cpp - Startup code for BeOS - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "xpram.h" -#include "timer.h" -#include "video.h" -#include "rom_patches.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "sys.h" -#include "user_strings.h" -#include "version.h" -#include "main.h" - -#include "sheep_driver.h" - -#define DEBUG 0 -#include "debug.h" - - -// Constants -const char APP_SIGNATURE[] = "application/x-vnd.cebix-BasiliskII"; -const char ROM_FILE_NAME[] = "ROM"; -const char RAM_AREA_NAME[] = "Macintosh RAM"; -const char ROM_AREA_NAME[] = "Macintosh ROM"; -const uint32 MSG_START = 'strt'; // Emulator start message -const uint32 ROM_AREA_SIZE = 0x500000; // Enough to hold PowerMac ROM (for powerrom_cpu) - -// Prototypes -#if __POWERPC__ -static void sigsegv_handler(vregs *r); -#endif - - -// Application object -class BasiliskII : public BApplication { -public: - BasiliskII() : BApplication(APP_SIGNATURE) - { - // Find application directory and cwd to it - app_info the_info; - GetAppInfo(&the_info); - BEntry the_file(&the_info.ref); - BEntry the_dir; - the_file.GetParent(&the_dir); - BPath the_path; - the_dir.GetPath(&the_path); - chdir(the_path.Path()); - - // Initialize other variables - rom_area = ram_area = -1; - xpram_thread = tick_thread = -1; - xpram_thread_active = true; - tick_thread_active = true; - AllowQuitting = true; - } - virtual void ReadyToRun(void); - virtual void MessageReceived(BMessage *msg); - void StartEmulator(void); - virtual bool QuitRequested(void); - virtual void Quit(void); - - thread_id xpram_thread; // XPRAM watchdog - thread_id tick_thread; // 60Hz thread - - volatile bool xpram_thread_active; // Flag for quitting the XPRAM thread - volatile bool tick_thread_active; // Flag for quitting the 60Hz thread - - bool AllowQuitting; // Flag: Alt-Q quitting allowed - -private: - static status_t emul_func(void *arg); - static status_t tick_func(void *arg); - static status_t xpram_func(void *arg); - static void sigsegv_invoc(int sig, void *arg, vregs *r); - - void init_rom(void); - void load_rom(void); - - area_id rom_area; // ROM area ID - area_id ram_area; // RAM area ID - - struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) - - // Exceptions - class area_error {}; - class file_open_error {}; - class file_read_error {}; - class rom_size_error {}; - - char* vmdir; -}; - -static BasiliskII *the_app; - - -// CPU and FPU type, addressing mode -int CPUType; -bool CPUIs68060; -int FPUType; -bool TwentyFourBitAddressing; - - -// Global variables for PowerROM CPU -thread_id emul_thread = -1; // Emulator thread - -#if __POWERPC__ -int sheep_fd = -1; // fd of sheep driver -#endif - - -/* - * Create application object and start it - */ - -int main(int argc, char **argv) -{ - the_app = new BasiliskII(); - the_app->Run(); - delete the_app; - return 0; -} - - -/* - * Run application - */ - -void BasiliskII::ReadyToRun(void) -{ - // Initialize variables - RAMBaseHost = NULL; - ROMBaseHost = NULL; - srand(real_time_clock()); - tzset(); - - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - - // Delete old areas - area_id old_ram_area = find_area(RAM_AREA_NAME); - if (old_ram_area > 0) - delete_area(old_ram_area); - area_id old_rom_area = find_area(ROM_AREA_NAME); - if (old_rom_area > 0) - delete_area(old_rom_area); - - // Read preferences - int argc = 0; - char **argv = NULL; - PrefsInit(vmdir, argc, argv); - - // Init system routines - SysInit(); - - // Show preferences editor (or start emulator directly) - if (!PrefsFindBool("nogui")) - PrefsEditor(); - else - PostMessage(MSG_START); -} - - -/* - * Message received - */ - -void BasiliskII::MessageReceived(BMessage *msg) -{ - switch (msg->what) { - case MSG_START: - StartEmulator(); - break; - default: - BApplication::MessageReceived(msg); - } -} - - -/* - * Start emulator - */ - -void BasiliskII::StartEmulator(void) -{ - char str[256]; - -#if REAL_ADDRESSING - // Open sheep driver and remap low memory - sheep_fd = open("/dev/sheep", 0); - if (sheep_fd < 0) { - sprintf(str, GetString(STR_NO_SHEEP_DRIVER_ERR), strerror(sheep_fd), sheep_fd); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - status_t res = ioctl(sheep_fd, SHEEP_UP); - if (res < 0) { - sprintf(str, GetString(STR_SHEEP_UP_ERR), strerror(res), res); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } -#endif - - // Create area for Mac RAM - RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary - if (RAMSize < 1024*1024) { - WarningAlert(GetString(STR_SMALL_RAM_WARN)); - RAMSize = 1024*1024; - } - - RAMBaseHost = (uint8 *)0x10000000; - ram_area = create_area(RAM_AREA_NAME, (void **)&RAMBaseHost, B_BASE_ADDRESS, RAMSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (ram_area < 0) { - ErrorAlert(STR_NO_RAM_AREA_ERR); - PostMessage(B_QUIT_REQUESTED); - return; - } - D(bug("RAM area %ld at %p\n", ram_area, RAMBaseHost)); - - // Create area and load Mac ROM - try { - init_rom(); - } catch (area_error) { - ErrorAlert(STR_NO_ROM_AREA_ERR); - PostMessage(B_QUIT_REQUESTED); - return; - } catch (file_open_error) { - ErrorAlert(STR_NO_ROM_FILE_ERR); - PostMessage(B_QUIT_REQUESTED); - return; - } catch (file_read_error) { - ErrorAlert(STR_ROM_FILE_READ_ERR); - PostMessage(B_QUIT_REQUESTED); - return; - } catch (rom_size_error) { - ErrorAlert(STR_ROM_SIZE_ERR); - PostMessage(B_QUIT_REQUESTED); - return; - } - - // Initialize everything - if (!InitAll(NULL)) { - PostMessage(B_QUIT_REQUESTED); - return; - } - - // Write protect ROM - set_area_protection(rom_area, B_READ_AREA); - - // Disallow quitting with Alt-Q from now on - AllowQuitting = false; - - // Start XPRAM watchdog thread - xpram_thread = spawn_thread(xpram_func, "XPRAM Watchdog", B_LOW_PRIORITY, this); - resume_thread(xpram_thread); - - // Start 60Hz interrupt - tick_thread = spawn_thread(tick_func, "60Hz", B_REAL_TIME_PRIORITY, this); - resume_thread(tick_thread); - - // Start emulator thread - emul_thread = spawn_thread(emul_func, "MacOS", B_NORMAL_PRIORITY, this); - resume_thread(emul_thread); -} - - -/* - * Quit emulator - */ - -void QuitEmulator(void) -{ - the_app->AllowQuitting = true; - be_app->PostMessage(B_QUIT_REQUESTED); - exit_thread(0); -} - -bool BasiliskII::QuitRequested(void) -{ - if (AllowQuitting) - return BApplication::QuitRequested(); - else - return false; -} - -void BasiliskII::Quit(void) -{ - status_t l; - - // Stop 60Hz interrupt - if (tick_thread > 0) { - tick_thread_active = false; - wait_for_thread(tick_thread, &l); - } - - // Wait for emulator thread to finish - if (emul_thread > 0) - wait_for_thread(emul_thread, &l); - - // Exit 680x0 emulation - Exit680x0(); - - // Stop XPRAM watchdog thread - if (xpram_thread > 0) { - xpram_thread_active = false; - suspend_thread(xpram_thread); // Wake thread up from snooze() - snooze(1000); - resume_thread(xpram_thread); - wait_for_thread(xpram_thread, &l); - } - - // Deinitialize everything - ExitAll(); - - // Delete ROM area - if (rom_area >= 0) - delete_area(rom_area); - - // Delete RAM area - if (ram_area >= 0) - delete_area(ram_area); - -#if REAL_ADDRESSING - // Unmap low memory and close memory mess driver - if (sheep_fd >= 0) { - ioctl(sheep_fd, SHEEP_DOWN); - close(sheep_fd); - } -#endif - - // Exit system routines - SysExit(); - - // Exit preferences - PrefsExit(); - - BApplication::Quit(); -} - - -/* - * Create area for ROM (sets rom_area) and load ROM file - * - * area_error : Cannot create area - * file_open_error: Cannot open ROM file - * file_read_error: Cannot read ROM file - */ - -void BasiliskII::init_rom(void) -{ - // Create area for ROM - ROMBaseHost = (uint8 *)0x40800000; - rom_area = create_area(ROM_AREA_NAME, (void **)&ROMBaseHost, B_BASE_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (rom_area < 0) - throw area_error(); - D(bug("ROM area %ld at %p\n", rom_area, ROMBaseHost)); - - // Load ROM - load_rom(); -} - - -/* - * Load ROM file - * - * file_open_error: Cannot open ROM file - * file_read_error: Cannot read ROM file - */ - -void BasiliskII::load_rom(void) -{ - // Get rom file path from preferences - const char *rom_path = PrefsFindString("rom"); - - // Try to open ROM file - BFile file(rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY); - if (file.InitCheck() != B_NO_ERROR) - throw file_open_error(); - - printf(GetString(STR_READING_ROM_FILE)); - - // Is the ROM size correct? - off_t rom_size = 0; - file.GetSize(&rom_size); - if (rom_size != 64*1024 && rom_size != 128*1024 && rom_size != 256*1024 && rom_size != 512*1024 && rom_size != 1024*1024) - throw rom_size_error(); - - uint8 *rom = new uint8[rom_size]; // Reading directly into the area doesn't work - ssize_t actual = file.Read((void *)rom, rom_size); - if (actual == rom_size) - memcpy(ROMBaseHost, rom, rom_size); - delete[] rom; - if (actual != rom_size) - throw file_read_error(); - ROMSize = rom_size; -} - - -/* - * Emulator thread function - */ - -status_t BasiliskII::emul_func(void *arg) -{ - BasiliskII *obj = (BasiliskII *)arg; - -#if __POWERPC__ - // Install data access signal handler - sigemptyset(&obj->sigsegv_action.sa_mask); - obj->sigsegv_action.sa_handler = (__signal_func_ptr)(obj->sigsegv_invoc); - obj->sigsegv_action.sa_flags = 0; - obj->sigsegv_action.sa_userdata = arg; - sigaction(SIGSEGV, &obj->sigsegv_action, NULL); -#endif - - // Exceptions will send signals - disable_debugger(true); - - // Start 68k and jump to ROM boot routine - Start680x0(); - - // Quit program - obj->AllowQuitting = true; - be_app->PostMessage(B_QUIT_REQUESTED); - return 0; -} - - -/* - * Code was patched, flush caches if neccessary (i.e. when using a real 680x0 - * or a dynamically recompiling emulator) - */ - -void FlushCodeCache(void *start, uint32 size) -{ -} - - -/* - * Mutexes - */ - -struct B2_mutex { - int dummy; //!! -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - - -/* - * Interrupt flags (must be handled atomically!) - */ - -uint32 InterruptFlags = 0; - -void SetInterruptFlag(uint32 flag) -{ - atomic_or((int32 *)&InterruptFlags, flag); -} - -void ClearInterruptFlag(uint32 flag) -{ - atomic_and((int32 *)&InterruptFlags, ~flag); -} - - -/* - * 60Hz thread (really 60.15Hz) - */ - -status_t BasiliskII::tick_func(void *arg) -{ - BasiliskII *obj = (BasiliskII *)arg; - int tick_counter = 0; - bigtime_t current = system_time(); - - while (obj->tick_thread_active) { - - // Wait - current += 16625; - snooze_until(current, B_SYSTEM_TIMEBASE); - - // Pseudo Mac 1Hz interrupt, update local time - if (++tick_counter > 60) { - tick_counter = 0; - WriteMacInt32(0x20c, TimerDateTime()); - SetInterruptFlag(INTFLAG_1HZ); - TriggerInterrupt(); - } - - // Trigger 60Hz interrupt - SetInterruptFlag(INTFLAG_60HZ); - TriggerInterrupt(); - } - return 0; -} - - -/* - * XPRAM watchdog thread (saves XPRAM every minute) - */ - -status_t BasiliskII::xpram_func(void *arg) -{ - uint8 last_xpram[XPRAM_SIZE]; - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - - while (((BasiliskII *)arg)->xpram_thread_active) { - snooze(60*1000000); - if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - SaveXPRAM(); - } - } - return 0; -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - if (PrefsFindBool("nogui")) { - printf(GetString(STR_SHELL_ERROR_PREFIX), text); - return; - } - VideoQuitFullScreen(); - char str[256]; - sprintf(str, GetString(STR_GUI_ERROR_PREFIX), text); - BAlert *alert = new BAlert(GetString(STR_ERROR_ALERT_TITLE), str, GetString(STR_QUIT_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); - alert->Go(); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - if (PrefsFindBool("nogui")) { - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return; - } - char str[256]; - sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text); - BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, GetString(STR_OK_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); - alert->Go(); -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - char str[256]; - sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text); - BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, pos, neg, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); - return alert->Go() == 0; -} - - -/* - * SEGV handler - */ - -#if __POWERPC__ -static uint32 segv_r[32]; - -asm void BasiliskII::sigsegv_invoc(register int sig, register void *arg, register vregs *r) -{ - mflr r0 - stw r0,8(r1) - stwu r1,-56(r1) - - lwz r3,segv_r(r2) - stmw r13,13*4(r3) - - mr r3,r5 - bl sigsegv_handler - - lwz r3,segv_r(r2) - lmw r13,13*4(r3) - - lwz r0,56+8(r1) - mtlr r0 - addi r1,r1,56 - blr -} - -static void sigsegv_handler(vregs *r) -{ - // Fetch volatile registers - segv_r[0] = r->r0; - segv_r[1] = r->r1; - segv_r[2] = r->r2; - segv_r[3] = r->r3; - segv_r[4] = r->r4; - segv_r[5] = r->r5; - segv_r[6] = r->r6; - segv_r[7] = r->r7; - segv_r[8] = r->r8; - segv_r[9] = r->r9; - segv_r[10] = r->r10; - segv_r[11] = r->r11; - segv_r[12] = r->r12; - - // Get opcode and divide into fields - uint32 opcode = *(uint32 *)r->pc; - uint32 primop = opcode >> 26; - uint32 exop = (opcode >> 1) & 0x3ff; - uint32 ra = (opcode >> 16) & 0x1f; - uint32 rb = (opcode >> 11) & 0x1f; - uint32 rd = (opcode >> 21) & 0x1f; - uint32 imm = opcode & 0xffff; - - // Analyze opcode - enum { - TYPE_UNKNOWN, - TYPE_LOAD, - TYPE_STORE - } transfer_type = TYPE_UNKNOWN; - enum { - SIZE_UNKNOWN, - SIZE_BYTE, - SIZE_HALFWORD, - SIZE_WORD - } transfer_size = SIZE_UNKNOWN; - enum { - MODE_UNKNOWN, - MODE_NORM, - MODE_U, - MODE_X, - MODE_UX - } addr_mode = MODE_UNKNOWN; - switch (primop) { - case 31: - switch (exop) { - case 23: // lwzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 55: // lwzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 87: // lbzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 119: // lbzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 151: // stwx - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 183: // stwux - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 215: // stbx - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 247: // stbux - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 279: // lhzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 311: // lhzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - case 343: // lhax - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 375: // lhaux - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - case 407: // sthx - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 439: // sthux - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - } - break; - - case 32: // lwz - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 33: // lwzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 34: // lbz - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 35: // lbzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 36: // stw - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 37: // stwu - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 38: // stb - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 39: // stbu - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 40: // lhz - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 41: // lhzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - case 42: // lha - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 43: // lhau - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - case 44: // sth - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 45: // sthu - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - } - - // Calculate effective address - uint32 addr = 0; - switch (addr_mode) { - case MODE_X: - case MODE_UX: - if (ra == 0) - addr = segv_r[rb]; - else - addr = segv_r[ra] + segv_r[rb]; - break; - case MODE_NORM: - case MODE_U: - if (ra == 0) - addr = (int32)(int16)imm; - else - addr = segv_r[ra] + (int32)(int16)imm; - break; - } - - // Ignore ROM writes - if (transfer_type == TYPE_STORE && addr >= (uint32)ROMBaseHost && addr < (uint32)ROMBaseHost + ROMSize) { -// D(bug("WARNING: %s write access to ROM at %p, 68k pc %p\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc)); - if (addr_mode == MODE_U || addr_mode == MODE_UX) - segv_r[ra] = addr; - r->pc += 4; - goto rti; - } - - // For all other errors, jump into debugger - char str[256]; - sprintf(str, "SIGSEGV\n" - " pc %08lx lr %08lx ctr %08lx msr %08lx\n" - " xer %08lx cr %08lx fpscr %08lx\n" - " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n" - " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n" - " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n" - " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n" - " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n" - " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n" - " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n" - " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", - r->pc, r->lr, r->ctr, r->msr, - r->xer, r->cr, r->fpscr, - r->r0, r->r1, r->r2, r->r3, - r->r4, r->r5, r->r6, r->r7, - r->r8, r->r9, r->r10, r->r11, - r->r12, segv_r[13], segv_r[14], segv_r[15], - segv_r[16], segv_r[17], segv_r[18], segv_r[19], - segv_r[20], segv_r[21], segv_r[22], segv_r[23], - segv_r[24], segv_r[25], segv_r[26], segv_r[27], - segv_r[28], segv_r[29], segv_r[30], segv_r[31]); - disable_debugger(false); - debugger(str); - QuitEmulator(); - return; - -rti: - // Restore volatile registers - r->r0 = segv_r[0]; - r->r1 = segv_r[1]; - r->r2 = segv_r[2]; - r->r3 = segv_r[3]; - r->r4 = segv_r[4]; - r->r5 = segv_r[5]; - r->r6 = segv_r[6]; - r->r7 = segv_r[7]; - r->r8 = segv_r[8]; - r->r9 = segv_r[9]; - r->r10 = segv_r[10]; - r->r11 = segv_r[11]; - r->r12 = segv_r[12]; -} -#endif diff --git a/BasiliskII/src/BeOS/prefs_beos.cpp b/BasiliskII/src/BeOS/prefs_beos.cpp deleted file mode 100644 index 9a74d643..00000000 --- a/BasiliskII/src/BeOS/prefs_beos.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * prefs_beos.cpp - Preferences handling, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include "sysdeps.h" -#include "prefs.h" -#include "main.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { - {"powerrom", TYPE_STRING, false, "path of PowerMac ROM"}, - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Preferences file name and path -const char PREFS_FILE_NAME[] = "BasiliskII_prefs"; -static BPath prefs_path; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(const char* vmdir) -{ -#if 0 - if (vmdir) { - prefs_path.SetTo(vmdir); - prefs_path.Append("prefs"); - FILE *prefs = fopen(prefs_path.Path(), "r"); - if (!prefs) { - printf("No file at %s found.\n", prefs_path.Path()); - exit(1); - } - LoadPrefsFromStream(prefs); - fclose(prefs); - return; - } -#endif - - // Construct prefs path - find_directory(B_USER_SETTINGS_DIRECTORY, &prefs_path, true); - prefs_path.Append(PREFS_FILE_NAME); - - // Read preferences from settings file - FILE *f = fopen(prefs_path.Path(), "r"); - if (f != NULL) { - - // Prefs file found, load settings - LoadPrefsFromStream(f); - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - } -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = fopen(prefs_path.Path(), "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsReplaceString("extfs", "/boot"); -} diff --git a/BasiliskII/src/BeOS/prefs_editor_beos.cpp b/BasiliskII/src/BeOS/prefs_editor_beos.cpp deleted file mode 100644 index a40e4748..00000000 --- a/BasiliskII/src/BeOS/prefs_editor_beos.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * prefs_editor_beos.cpp - Preferences editor, BeOS implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "cdrom.h" -#include "xpram.h" -#include "prefs.h" -#include "about_window.h" -#include "user_strings.h" -#include "prefs_editor.h" - - -// Special colors -const rgb_color fill_color = {216, 216, 216, 0}; -const rgb_color slider_fill_color = {102, 152, 255, 0}; - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_SCREEN -}; - -// Window messages -const uint32 MSG_OK = 'okok'; // "Start" clicked -const uint32 MSG_CANCEL = 'cncl'; // "Quit" clicked -const uint32 MSG_ZAP_PRAM = 'zprm'; - -const int NUM_PANES = 4; - -const uint32 MSG_VOLUME_SELECTED = 'volu'; // "Volumes" pane -const uint32 MSG_VOLUME_INVOKED = 'voli'; -const uint32 MSG_ADD_VOLUME = 'addv'; -const uint32 MSG_CREATE_VOLUME = 'crev'; -const uint32 MSG_REMOVE_VOLUME = 'remv'; -const uint32 MSG_ADD_VOLUME_PANEL = 'advp'; -const uint32 MSG_CREATE_VOLUME_PANEL = 'crvp'; -const uint32 MSG_DEVICE_NAME = 'devn'; -const uint32 MSG_BOOT_ANY = 'bany'; -const uint32 MSG_BOOT_CDROM = 'bcdr'; -const uint32 MSG_NOCDROM = 'nocd'; - -const uint32 MSG_REF_5HZ = ' 5Hz'; // "Graphics/Sound" pane -const uint32 MSG_REF_7_5HZ = ' 7Hz'; -const uint32 MSG_REF_10HZ = '10Hz'; -const uint32 MSG_REF_15HZ = '15Hz'; -const uint32 MSG_REF_30HZ = '30Hz'; -const uint32 MSG_VIDEO_WINDOW = 'vtyw'; -const uint32 MSG_VIDEO_SCREEN = 'vtys'; -const uint32 MSG_SCREEN_MODE = 'sm\0\0'; -const uint32 MSG_NOSOUND = 'nosn'; - -const uint32 MSG_SER_A = 'sera'; // "Serial/Network" pane -const uint32 MSG_SER_B = 'serb'; -const uint32 MSG_ETHER = 'ethr'; -const uint32 MSG_UDPTUNNEL = 'udpt'; - -const uint32 MSG_RAMSIZE = 'rmsz'; // "Memory/Misc" pane -const uint32 MSG_MODELID_5 = 'mi05'; -const uint32 MSG_MODELID_14 = 'mi14'; -const uint32 MSG_CPU_68020 = 'cpu2'; -const uint32 MSG_CPU_68020_FPU = 'cpf2'; -const uint32 MSG_CPU_68030 = 'cpu3'; -const uint32 MSG_CPU_68030_FPU = 'cpf3'; -const uint32 MSG_CPU_68040 = 'cpu4'; - - -// RAM size slider class -class RAMSlider : public BSlider { -public: - RAMSlider(BRect frame, const char *name, const char *label, BMessage *message, - int32 minValue, int32 maxValue, thumb_style thumbType = B_BLOCK_THUMB, - uint32 resizingMode = B_FOLLOW_LEFT | - B_FOLLOW_TOP, - uint32 flags = B_NAVIGABLE | B_WILL_DRAW | - B_FRAME_EVENTS) : BSlider(frame, name, label, message, minValue, maxValue, thumbType, resizingMode, flags) - { - update_text = (char *)malloc(256); - } - - virtual ~RAMSlider() - { - if (update_text) - free(update_text); - } - - virtual char *UpdateText(void) const - { - if (update_text) { - sprintf(update_text, GetString(STR_RAMSIZE_FMT), Value()); - } - return update_text; - } - -private: - char *update_text; -}; - - -// Volumes list view class -class VolumeListView : public BListView { -public: - VolumeListView(BRect frame, const char *name, list_view_type type = B_SINGLE_SELECTION_LIST, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE) - : BListView(frame, name, type, resizeMask, flags) - {} - - // Handle dropped files and volumes - virtual void MessageReceived(BMessage *msg) - { - if (msg->what == B_SIMPLE_DATA) { - BMessage msg2(MSG_ADD_VOLUME_PANEL); - entry_ref ref; - for (int i=0; msg->FindRef("refs", i, &ref) == B_NO_ERROR; i++) - msg2.AddRef("refs", &ref); - Window()->PostMessage(&msg2); - } else - BListView::MessageReceived(msg); - } -}; - - -// Number-entry BTextControl -class NumberControl : public BTextControl { -public: - NumberControl(BRect frame, float divider, const char *name, const char *label, long value, BMessage *message) - : BTextControl(frame, name, label, NULL, message, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE) - { - SetDivider(divider); - for (int c=0; c<256; c++) - if (!isdigit(c) && c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW) - ((BTextView *)ChildAt(0))->DisallowChar(c); - SetValue(value); - } - - // Set integer value - void SetValue(long value) - { - char str[32]; - sprintf(str, "%ld", value); - SetText(str); - } - - // Get integer value - long Value(void) - { - return atol(Text()); - } -}; - - -// Path-entry BTextControl -class PathControl : public BTextControl { -public: - PathControl(bool dir_ctrl_, BRect frame, const char *name, const char *label, const char *text, BMessage *message) : BTextControl(frame, name, label, text, message), dir_ctrl(dir_ctrl_) - { - for (int c=0; c<' '; c++) - if (c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW) - ((BTextView *)ChildAt(0))->DisallowChar(c); - } - - virtual void MessageReceived(BMessage *msg) - { - if (msg->what == B_SIMPLE_DATA) { - entry_ref the_ref; - BEntry the_entry; - - // Look for dropped refs - if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) { - if (the_entry.SetTo(&the_ref) == B_NO_ERROR && (dir_ctrl&& the_entry.IsDirectory() || !dir_ctrl && the_entry.IsFile())) { - BPath the_path; - the_entry.GetPath(&the_path); - SetText(the_path.Path()); - } - } else - BTextControl::MessageReceived(msg); - - MakeFocus(); - } else - BTextControl::MessageReceived(msg); - } - -private: - bool dir_ctrl; -}; - - -// Preferences window class -class PrefsWindow : public BWindow { -public: - PrefsWindow(uint32 msg); - virtual ~PrefsWindow(); - virtual void MessageReceived(BMessage *msg); - -private: - void read_volumes_prefs(void); - void hide_show_graphics_ctrls(void); - void read_graphics_prefs(void); - void hide_show_serial_ctrls(void); - void read_serial_prefs(void); - void add_serial_names(BPopUpMenu *menu, uint32 msg); - void read_memory_prefs(void); - - BView *create_volumes_pane(void); - BView *create_graphics_pane(void); - BView *create_serial_pane(void); - BView *create_memory_pane(void); - - uint32 ok_message; - bool send_quit_on_close; - - system_info sys_info; - BMessenger this_messenger; - BView *top; - BRect top_frame; - BTabView *pane_tabs; - BView *panes[NUM_PANES]; - int current_pane; - - VolumeListView *volume_list; - BCheckBox *nocdrom_checkbox; - BMenuField *frameskip_menu; - NumberControl *display_x_ctrl; - NumberControl *display_y_ctrl; - BMenuField *scr_mode_menu; - BCheckBox *nosound_checkbox; - BCheckBox *ether_checkbox; - BCheckBox *udptunnel_checkbox; - NumberControl *udpport_ctrl; - RAMSlider *ramsize_slider; - PathControl *extfs_control; - PathControl *rom_control; - BCheckBox *fpu_checkbox; - - BFilePanel *add_volume_panel; - BFilePanel *create_volume_panel; - - uint32 max_ramsize; // In MB - int display_type; - int scr_mode_bit; -}; - - -/* - * Show preferences editor (asynchronously) - * Under BeOS, the return value is ignored. Instead, a message is sent to the - * application when the user clicks on "Start" or "Quit" - */ - -bool PrefsEditor(void) -{ - new PrefsWindow('strt'); - return true; -} - - -/* - * Preferences window constructor - */ - -PrefsWindow::PrefsWindow(uint32 msg) : BWindow(BRect(0, 0, 400, 289), GetString(STR_PREFS_TITLE), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS), this_messenger(this) -{ - int i; - ok_message = msg; - send_quit_on_close = true; - get_system_info(&sys_info); - - // Move window to right position - Lock(); - MoveTo(80, 80); - - // Set up menus - BMenuBar *bar = new BMenuBar(Bounds(), "menu"); - BMenu *menu = new BMenu(GetString(STR_PREFS_MENU)); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ABOUT), new BMessage(B_ABOUT_REQUESTED))); - menu->AddItem(new BSeparatorItem); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_START), new BMessage(MSG_OK))); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ZAP_PRAM), new BMessage(MSG_ZAP_PRAM))); - menu->AddItem(new BSeparatorItem); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_QUIT), new BMessage(MSG_CANCEL), 'Q')); - bar->AddItem(menu); - AddChild(bar); - SetKeyMenuBar(bar); - int mbar_height = int(bar->Bounds().bottom) + 1; - - // Resize window to fit menu bar - ResizeBy(0, mbar_height); - - // Light gray background - BRect b = Bounds(); - top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, B_WILL_DRAW); - AddChild(top); - top->SetViewColor(fill_color); - top_frame = top->Bounds(); - - // Create panes - panes[0] = create_volumes_pane(); - panes[1] = create_graphics_pane(); - panes[2] = create_serial_pane(); - panes[3] = create_memory_pane(); - - // Prefs item tab view - pane_tabs = new BTabView(BRect(10, 10, top_frame.right-10, top_frame.bottom-50), "items", B_WIDTH_FROM_LABEL); - for (i=0; iAddTab(panes[i]); - top->AddChild(pane_tabs); - - volume_list->Select(0); - - // Create volume file panels - add_volume_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_ADD_VOLUME_PANEL)); - add_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_ADD_VOLUME_PANEL_BUTTON)); - add_volume_panel->Window()->SetTitle(GetString(STR_ADD_VOLUME_TITLE)); - create_volume_panel = new BFilePanel(B_SAVE_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_CREATE_VOLUME_PANEL)); - create_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_CREATE_VOLUME_PANEL_BUTTON)); - create_volume_panel->Window()->SetTitle(GetString(STR_CREATE_VOLUME_TITLE)); - - create_volume_panel->Window()->Lock(); - BView *background = create_volume_panel->Window()->ChildAt(0); - background->FindView("PoseView")->ResizeBy(0, -30); - background->FindView("VScrollBar")->ResizeBy(0, -30); - background->FindView("CountVw")->MoveBy(0, -30); - BView *v = background->FindView("HScrollBar"); - if (v) - v->MoveBy(0, -30); - else { - i = 0; - while ((v = background->ChildAt(i++)) != NULL) { - if (v->Name() == NULL || v->Name()[0] == 0) { - v->MoveBy(0, -30); // unnamed horizontal scroll bar - break; - } - } - } - BView *filename = background->FindView("text view"); - BRect fnr(filename->Frame()); - fnr.OffsetBy(0, -30); - NumberControl *nc = new NumberControl(fnr, 80, "hardfile_size", GetString(STR_HARDFILE_SIZE_CTRL), 40, NULL); - background->AddChild(nc); - create_volume_panel->Window()->Unlock(); - - // "Start" button - BButton *button = new BButton(BRect(20, top_frame.bottom-35, 90, top_frame.bottom-10), "start", GetString(STR_START_BUTTON), new BMessage(MSG_OK)); - top->AddChild(button); - SetDefaultButton(button); - - // "Quit" button - top->AddChild(new BButton(BRect(top_frame.right-90, top_frame.bottom-35, top_frame.right-20, top_frame.bottom-10), "cancel", GetString(STR_QUIT_BUTTON), new BMessage(MSG_CANCEL))); - - Unlock(); - Show(); -} - - -/* - * Preferences window destructor - */ - -PrefsWindow::~PrefsWindow() -{ - delete add_volume_panel; - delete create_volume_panel; - if (send_quit_on_close) - be_app->PostMessage(B_QUIT_REQUESTED); -} - - -/* - * Create "Volumes" pane - */ - -void PrefsWindow::read_volumes_prefs(void) -{ - PrefsReplaceString("extfs", extfs_control->Text()); -} - -BView *PrefsWindow::create_volumes_pane(void) -{ - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_VOLUMES_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - const char *str; - int32 index = 0; - volume_list = new VolumeListView(BRect(15, 10, pane->Bounds().right-30, 113), "volumes"); - while ((str = PrefsFindString("disk", index++)) != NULL) - volume_list->AddItem(new BStringItem(str)); - volume_list->SetSelectionMessage(new BMessage(MSG_VOLUME_SELECTED)); - volume_list->SetInvocationMessage(new BMessage(MSG_VOLUME_INVOKED)); - pane->AddChild(new BScrollView("volumes_border", volume_list, B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true)); - - pane->AddChild(new BButton(BRect(10, 118, pane->Bounds().right/3, 138), "add_volume", GetString(STR_ADD_VOLUME_BUTTON), new BMessage(MSG_ADD_VOLUME))); - pane->AddChild(new BButton(BRect(pane->Bounds().right/3, 118, pane->Bounds().right*2/3, 138), "create_volume", GetString(STR_CREATE_VOLUME_BUTTON), new BMessage(MSG_CREATE_VOLUME))); - pane->AddChild(new BButton(BRect(pane->Bounds().right*2/3, 118, pane->Bounds().right-11, 138), "remove_volume", GetString(STR_REMOVE_VOLUME_BUTTON), new BMessage(MSG_REMOVE_VOLUME))); - - extfs_control = new PathControl(true, BRect(10, 145, right, 160), "extfs", GetString(STR_EXTFS_CTRL), PrefsFindString("extfs"), NULL); - extfs_control->SetDivider(90); - pane->AddChild(extfs_control); - - BMenuField *menu_field; - BPopUpMenu *menu = new BPopUpMenu(""); - menu_field = new BMenuField(BRect(10, 165, right, 180), "bootdriver", GetString(STR_BOOTDRIVER_CTRL), menu); - menu_field->SetDivider(90); - menu->AddItem(new BMenuItem(GetString(STR_BOOT_ANY_LAB), new BMessage(MSG_BOOT_ANY))); - menu->AddItem(new BMenuItem(GetString(STR_BOOT_CDROM_LAB), new BMessage(MSG_BOOT_CDROM))); - pane->AddChild(menu_field); - int32 i32 = PrefsFindInt32("bootdriver"); - BMenuItem *item; - if (i32 == 0) { - if ((item = menu->FindItem(GetString(STR_BOOT_ANY_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == CDROMRefNum) { - if ((item = menu->FindItem(GetString(STR_BOOT_CDROM_LAB))) != NULL) - item->SetMarked(true); - } - - nocdrom_checkbox = new BCheckBox(BRect(10, 185, right, 200), "nocdrom", GetString(STR_NOCDROM_CTRL), new BMessage(MSG_NOCDROM)); - pane->AddChild(nocdrom_checkbox); - nocdrom_checkbox->SetValue(PrefsFindBool("nocdrom") ? B_CONTROL_ON : B_CONTROL_OFF); - - return pane; -} - - -/* - * Create "Graphics/Sound" pane - */ - -// Screen mode list -struct scr_mode_desc { - int mode_mask; - int str; -}; - -static const scr_mode_desc scr_mode[] = { - {B_8_BIT_640x480, STR_8_BIT_640x480_LAB}, - {B_8_BIT_800x600, STR_8_BIT_800x600_LAB}, - {B_8_BIT_1024x768, STR_8_BIT_1024x768_LAB}, - {B_8_BIT_1152x900, STR_8_BIT_1152x900_LAB}, - {B_8_BIT_1280x1024, STR_8_BIT_1280x1024_LAB}, - {B_8_BIT_1600x1200, STR_8_BIT_1600x1200_LAB}, - {B_15_BIT_640x480, STR_15_BIT_640x480_LAB}, - {B_15_BIT_800x600, STR_15_BIT_800x600_LAB}, - {B_15_BIT_1024x768, STR_15_BIT_1024x768_LAB}, - {B_15_BIT_1152x900, STR_15_BIT_1152x900_LAB}, - {B_15_BIT_1280x1024, STR_15_BIT_1280x1024_LAB}, - {B_15_BIT_1600x1200, STR_15_BIT_1600x1200_LAB}, - {B_32_BIT_640x480, STR_24_BIT_640x480_LAB}, - {B_32_BIT_800x600, STR_24_BIT_800x600_LAB}, - {B_32_BIT_1024x768, STR_24_BIT_1024x768_LAB}, - {B_32_BIT_1152x900, STR_24_BIT_1152x900_LAB}, - {B_32_BIT_1280x1024, STR_24_BIT_1280x1024_LAB}, - {B_32_BIT_1600x1200, STR_24_BIT_1600x1200_LAB}, - {0, 0} // End marker -}; - -void PrefsWindow::hide_show_graphics_ctrls(void) -{ - if (display_type == DISPLAY_WINDOW) { - if (!scr_mode_menu->IsHidden()) - scr_mode_menu->Hide(); - if (frameskip_menu->IsHidden()) - frameskip_menu->Show(); - if (display_x_ctrl->IsHidden()) - display_x_ctrl->Show(); - if (display_y_ctrl->IsHidden()) - display_y_ctrl->Show(); - } else { - if (!frameskip_menu->IsHidden()) - frameskip_menu->Hide(); - if (!display_x_ctrl->IsHidden()) - display_x_ctrl->Hide(); - if (!display_y_ctrl->IsHidden()) - display_y_ctrl->Hide(); - if (scr_mode_menu->IsHidden()) - scr_mode_menu->Show(); - } -} - -void PrefsWindow::read_graphics_prefs(void) -{ - char str[64]; - if (display_type == DISPLAY_WINDOW) { - sprintf(str, "win/%d/%d", display_x_ctrl->Value(), display_y_ctrl->Value()); - } else { - sprintf(str, "scr/%d", scr_mode_bit); - } - PrefsReplaceString("screen", str); -} - -BView *PrefsWindow::create_graphics_pane(void) -{ - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_GRAPHICS_SOUND_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - const char *mode_str = PrefsFindString("screen"); - int width = 512, height = 384; - scr_mode_bit = 0; - display_type = DISPLAY_WINDOW; - if (mode_str) { - if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2) - display_type = DISPLAY_WINDOW; - else if (sscanf(mode_str, "scr/%d", &scr_mode_bit) == 1) - display_type = DISPLAY_SCREEN; - } - - BMenuField *menu_field; - BMenuItem *item; - BPopUpMenu *menu; - - menu = new BPopUpMenu(""); - menu_field = new BMenuField(BRect(10, 5, right, 20), "videotype", GetString(STR_VIDEO_TYPE_CTRL), menu); - menu_field->SetDivider(120); - menu->AddItem(item = new BMenuItem(GetString(STR_WINDOW_LAB), new BMessage(MSG_VIDEO_WINDOW))); - if (display_type == DISPLAY_WINDOW) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem(GetString(STR_FULLSCREEN_LAB), new BMessage(MSG_VIDEO_SCREEN))); - if (display_type == DISPLAY_SCREEN) - item->SetMarked(true); - pane->AddChild(menu_field); - - menu = new BPopUpMenu(""); - frameskip_menu = new BMenuField(BRect(10, 26, right, 41), "frameskip", GetString(STR_FRAMESKIP_CTRL), menu); - frameskip_menu->SetDivider(120); - menu->AddItem(new BMenuItem(GetString(STR_REF_5HZ_LAB), new BMessage(MSG_REF_5HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_7_5HZ_LAB), new BMessage(MSG_REF_7_5HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_10HZ_LAB), new BMessage(MSG_REF_10HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_15HZ_LAB), new BMessage(MSG_REF_15HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_30HZ_LAB), new BMessage(MSG_REF_30HZ))); - pane->AddChild(frameskip_menu); - int32 i32 = PrefsFindInt32("frameskip"); - if (i32 == 12) { - if ((item = menu->FindItem(GetString(STR_REF_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 8) { - if ((item = menu->FindItem(GetString(STR_REF_7_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 6) { - if ((item = menu->FindItem(GetString(STR_REF_10HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 4) { - if ((item = menu->FindItem(GetString(STR_REF_15HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 2) { - if ((item = menu->FindItem(GetString(STR_REF_30HZ_LAB))) != NULL) - item->SetMarked(true); - } - - display_x_ctrl = new NumberControl(BRect(10, 48, right / 2, 66), 118, "width", GetString(STR_DISPLAY_X_CTRL), width, NULL); - pane->AddChild(display_x_ctrl); - display_y_ctrl = new NumberControl(BRect(10, 69, right / 2, 87), 118, "height", GetString(STR_DISPLAY_Y_CTRL), height, NULL); - pane->AddChild(display_y_ctrl); - - menu = new BPopUpMenu(""); - scr_mode_menu = new BMenuField(BRect(10, 26, right, 41), "screenmode", GetString(STR_SCREEN_MODE_CTRL), menu); - scr_mode_menu->SetDivider(120); - for (int i=0; scr_mode[i].mode_mask; i++) { - menu->AddItem(item = new BMenuItem(GetString(scr_mode[i].str), new BMessage(MSG_SCREEN_MODE + i))); - if (scr_mode[i].mode_mask & (1 << scr_mode_bit)) - item->SetMarked(true); - } - pane->AddChild(scr_mode_menu); - - nosound_checkbox = new BCheckBox(BRect(10, 90, right, 105), "nosound", GetString(STR_NOSOUND_CTRL), new BMessage(MSG_NOSOUND)); - pane->AddChild(nosound_checkbox); - nosound_checkbox->SetValue(PrefsFindBool("nosound") ? B_CONTROL_ON : B_CONTROL_OFF); - - hide_show_graphics_ctrls(); - return pane; -} - - -/* - * Create "Serial/Network" pane - */ - -void PrefsWindow::hide_show_serial_ctrls(void) -{ - if (udptunnel_checkbox->Value() == B_CONTROL_ON) { - ether_checkbox->SetEnabled(false); - udpport_ctrl->SetEnabled(true); - } else { - ether_checkbox->SetEnabled(true); - udpport_ctrl->SetEnabled(false); - } -} - -void PrefsWindow::read_serial_prefs(void) -{ - PrefsReplaceInt32("udpport", udpport_ctrl->Value()); -} - -void PrefsWindow::add_serial_names(BPopUpMenu *menu, uint32 msg) -{ - BSerialPort *port = new BSerialPort; - char name[B_PATH_NAME_LENGTH]; - for (int i=0; iCountDevices(); i++) { - port->GetDeviceName(i, name); - menu->AddItem(new BMenuItem(name, new BMessage(msg))); - } - BDirectory dir; - BEntry entry; - dir.SetTo("/dev/parallel"); - if (dir.InitCheck() == B_NO_ERROR) { - dir.Rewind(); - while (dir.GetNextEntry(&entry) >= 0) { - if (!entry.IsDirectory()) { - entry.GetName(name); - menu->AddItem(new BMenuItem(name, new BMessage(msg))); - } - } - } - delete port; -} - -static void set_serial_label(BPopUpMenu *menu, const char *prefs_name) -{ - const char *str; - BMenuItem *item; - if ((str = PrefsFindString(prefs_name)) != NULL) - if ((item = menu->FindItem(str)) != NULL) - item->SetMarked(true); -} - -BView *PrefsWindow::create_serial_pane(void) -{ - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_SERIAL_NETWORK_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - BMenuField *menu_field; - BPopUpMenu *menu_a = new BPopUpMenu(""); - add_serial_names(menu_a, MSG_SER_A); - menu_field = new BMenuField(BRect(10, 5, right, 20), "seriala", GetString(STR_SERIALA_CTRL), menu_a); - menu_field->SetDivider(90); - pane->AddChild(menu_field); - set_serial_label(menu_a, "seriala"); - - BPopUpMenu *menu_b = new BPopUpMenu(""); - add_serial_names(menu_b, MSG_SER_B); - menu_field = new BMenuField(BRect(10, 26, right, 41), "serialb", GetString(STR_SERIALB_CTRL), menu_b); - menu_field->SetDivider(90); - pane->AddChild(menu_field); - set_serial_label(menu_b, "serialb"); - - ether_checkbox = new BCheckBox(BRect(10, 47, right, 62), "ether", GetString(STR_ETHER_ENABLE_CTRL), new BMessage(MSG_ETHER)); - pane->AddChild(ether_checkbox); - ether_checkbox->SetValue(PrefsFindString("ether") ? B_CONTROL_ON : B_CONTROL_OFF); - - udptunnel_checkbox = new BCheckBox(BRect(10, 67, right, 72), "udptunnel", GetString(STR_UDPTUNNEL_CTRL), new BMessage(MSG_UDPTUNNEL)); - pane->AddChild(udptunnel_checkbox); - udptunnel_checkbox->SetValue(PrefsFindBool("udptunnel") ? B_CONTROL_ON : B_CONTROL_OFF); - - udpport_ctrl = new NumberControl(BRect(10, 87, right / 2, 105), 118, "udpport", GetString(STR_UDPPORT_CTRL), PrefsFindInt32("udpport"), NULL); - pane->AddChild(udpport_ctrl); - - hide_show_serial_ctrls(); - return pane; -} - - -/* - * Create "Memory" pane - */ - -void PrefsWindow::read_memory_prefs(void) -{ - const char *str = rom_control->Text(); - if (strlen(str)) - PrefsReplaceString("rom", str); - else - PrefsRemoveItem("rom"); -} - -BView *PrefsWindow::create_memory_pane(void) -{ - char str[256], str2[256]; - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_MEMORY_MISC_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - BEntry entry("/boot/var/swap"); - off_t swap_space; - if (entry.GetSize(&swap_space) == B_NO_ERROR) - max_ramsize = swap_space / (1024 * 1024) - 8; - else - max_ramsize = sys_info.max_pages * B_PAGE_SIZE / (1024 * 1024) - 8; - - int32 value = PrefsFindInt32("ramsize") / (1024 * 1024); - - ramsize_slider = new RAMSlider(BRect(10, 5, right, 55), "ramsize", GetString(STR_RAMSIZE_SLIDER), new BMessage(MSG_RAMSIZE), 1, max_ramsize, B_TRIANGLE_THUMB); - ramsize_slider->SetValue(value); - ramsize_slider->UseFillColor(true, &slider_fill_color); - sprintf(str, GetString(STR_RAMSIZE_FMT), 1); - sprintf(str2, GetString(STR_RAMSIZE_FMT), max_ramsize); - ramsize_slider->SetLimitLabels(str, str2); - pane->AddChild(ramsize_slider); - - BMenuField *menu_field; - BMenuItem *item; - BPopUpMenu *menu; - - int id = PrefsFindInt32("modelid"); - menu = new BPopUpMenu(""); - menu_field = new BMenuField(BRect(10, 60, right, 75), "modelid", GetString(STR_MODELID_CTRL), menu); - menu_field->SetDivider(120); - menu->AddItem(item = new BMenuItem(GetString(STR_MODELID_5_LAB), new BMessage(MSG_MODELID_5))); - if (id == 5) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem(GetString(STR_MODELID_14_LAB), new BMessage(MSG_MODELID_14))); - if (id == 14) - item->SetMarked(true); - pane->AddChild(menu_field); - - int cpu = PrefsFindInt32("cpu"); - bool fpu = PrefsFindBool("fpu"); - menu = new BPopUpMenu(""); - menu_field = new BMenuField(BRect(10, 82, right, 97), "cpu", GetString(STR_CPU_CTRL), menu); - menu_field->SetDivider(120); - menu->AddItem(item = new BMenuItem(GetString(STR_CPU_68020_LAB), new BMessage(MSG_CPU_68020))); - if (cpu == 2 && !fpu) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem(GetString(STR_CPU_68020_FPU_LAB), new BMessage(MSG_CPU_68020_FPU))); - if (cpu == 2 && fpu) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem(GetString(STR_CPU_68030_LAB), new BMessage(MSG_CPU_68030))); - if (cpu == 3 && !fpu) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem(GetString(STR_CPU_68030_FPU_LAB), new BMessage(MSG_CPU_68030_FPU))); - if (cpu == 3 && fpu) - item->SetMarked(true); - menu->AddItem(item = new BMenuItem(GetString(STR_CPU_68040_LAB), new BMessage(MSG_CPU_68040))); - if (cpu == 4) - item->SetMarked(true); - pane->AddChild(menu_field); - - rom_control = new PathControl(false, BRect(10, 104, right, 119), "rom", GetString(STR_ROM_FILE_CTRL), PrefsFindString("rom"), NULL); - rom_control->SetDivider(117); - pane->AddChild(rom_control); - - return pane; -} - - -/* - * Message from controls/menus received - */ - -void PrefsWindow::MessageReceived(BMessage *msg) -{ - switch (msg->what) { - case MSG_OK: { // "Start" button clicked - read_volumes_prefs(); - read_memory_prefs(); - read_graphics_prefs(); - SavePrefs(); - send_quit_on_close = false; - PostMessage(B_QUIT_REQUESTED); - be_app->PostMessage(ok_message); - break; - } - - case MSG_CANCEL: // "Quit" button clicked - send_quit_on_close = false; - PostMessage(B_QUIT_REQUESTED); - be_app->PostMessage(B_QUIT_REQUESTED); - break; - - case B_ABOUT_REQUESTED: { // "About" menu item selected - ShowAboutWindow(); - break; - } - - case MSG_ZAP_PRAM: // "Zap PRAM File" menu item selected - ZapPRAM(); - break; - - case MSG_VOLUME_INVOKED: { // Double-clicked on volume name, toggle read-only flag - int selected = volume_list->CurrentSelection(); - if (selected >= 0) { - const char *str = PrefsFindString("disk", selected); - BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected); - delete item; - char newstr[256]; - if (str[0] == '*') - strcpy(newstr, str+1); - else { - strcpy(newstr, "*"); - strcat(newstr, str); - } - PrefsReplaceString("disk", newstr, selected); - volume_list->AddItem(new BStringItem(newstr), selected); - volume_list->Select(selected); - } - break; - } - - case MSG_ADD_VOLUME: - add_volume_panel->Show(); - break; - - case MSG_CREATE_VOLUME: - create_volume_panel->Show(); - break; - - case MSG_ADD_VOLUME_PANEL: { - entry_ref ref; - if (msg->FindRef("refs", &ref) == B_NO_ERROR) { - BEntry entry(&ref, true); - BPath path; - entry.GetPath(&path); - if (entry.IsFile()) { - PrefsAddString("disk", path.Path()); - volume_list->AddItem(new BStringItem(path.Path())); - } else if (entry.IsDirectory()) { - BVolume volume; - if (path.Path()[0] == '/' && strchr(path.Path()+1, '/') == NULL && entry.GetVolume(&volume) == B_NO_ERROR) { - int32 i = 0; - dev_t d; - fs_info info; - while ((d = next_dev(&i)) >= 0) { - fs_stat_dev(d, &info); - if (volume.Device() == info.dev) { - PrefsAddString("disk", info.device_name); - volume_list->AddItem(new BStringItem(info.device_name)); - } - } - } - } - } - break; - } - - case MSG_CREATE_VOLUME_PANEL: { - entry_ref dir; - if (msg->FindRef("directory", &dir) == B_NO_ERROR) { - BEntry entry(&dir, true); - BPath path; - entry.GetPath(&path); - path.Append(msg->FindString("name")); - - create_volume_panel->Window()->Lock(); - BView *background = create_volume_panel->Window()->ChildAt(0); - NumberControl *v = (NumberControl *)background->FindView("hardfile_size"); - int size = v->Value(); - - char cmd[1024]; - sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", path.Path(), size); - int ret = system(cmd); - if (ret == 0) { - PrefsAddString("disk", path.Path()); - volume_list->AddItem(new BStringItem(path.Path())); - } else { - sprintf(cmd, GetString(STR_CREATE_VOLUME_WARN), strerror(ret)); - WarningAlert(cmd); - } - } - break; - } - - case MSG_REMOVE_VOLUME: { - int selected = volume_list->CurrentSelection(); - if (selected >= 0) { - PrefsRemoveItem("disk", selected); - BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected); - delete item; - volume_list->Select(selected); - } - break; - } - - case MSG_BOOT_ANY: - PrefsReplaceInt32("bootdriver", 0); - break; - - case MSG_BOOT_CDROM: - PrefsReplaceInt32("bootdriver", CDROMRefNum); - break; - - case MSG_NOCDROM: - PrefsReplaceBool("nocdrom", nocdrom_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_VIDEO_WINDOW: - display_type = DISPLAY_WINDOW; - hide_show_graphics_ctrls(); - break; - - case MSG_VIDEO_SCREEN: - display_type = DISPLAY_SCREEN; - hide_show_graphics_ctrls(); - break; - - case MSG_REF_5HZ: - PrefsReplaceInt32("frameskip", 12); - break; - - case MSG_REF_7_5HZ: - PrefsReplaceInt32("frameskip", 8); - break; - - case MSG_REF_10HZ: - PrefsReplaceInt32("frameskip", 6); - break; - - case MSG_REF_15HZ: - PrefsReplaceInt32("frameskip", 4); - break; - - case MSG_REF_30HZ: - PrefsReplaceInt32("frameskip", 2); - break; - - case MSG_NOSOUND: - PrefsReplaceBool("nosound", nosound_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_SER_A: { - BMenuItem *source = NULL; - msg->FindPointer("source", (void **)&source); - if (source) - PrefsReplaceString("seriala", source->Label()); - break; - } - - case MSG_SER_B: { - BMenuItem *source = NULL; - msg->FindPointer("source", (void **)&source); - if (source) - PrefsReplaceString("serialb", source->Label()); - break; - } - - case MSG_ETHER: - if (ether_checkbox->Value() == B_CONTROL_ON) - PrefsReplaceString("ether", "yes"); - else - PrefsRemoveItem("ether"); - break; - - case MSG_UDPTUNNEL: - PrefsReplaceBool("udptunnel", udptunnel_checkbox->Value() == B_CONTROL_ON); - hide_show_serial_ctrls(); - break; - - case MSG_RAMSIZE: - PrefsReplaceInt32("ramsize", ramsize_slider->Value() * 1024 * 1024); - break; - - case MSG_MODELID_5: - PrefsReplaceInt32("modelid", 5); - break; - - case MSG_MODELID_14: - PrefsReplaceInt32("modelid", 14); - break; - - case MSG_CPU_68020: - PrefsReplaceInt32("cpu", 2); - PrefsReplaceBool("fpu", false); - break; - - case MSG_CPU_68020_FPU: - PrefsReplaceInt32("cpu", 2); - PrefsReplaceBool("fpu", true); - break; - - case MSG_CPU_68030: - PrefsReplaceInt32("cpu", 3); - PrefsReplaceBool("fpu", false); - break; - - case MSG_CPU_68030_FPU: - PrefsReplaceInt32("cpu", 3); - PrefsReplaceBool("fpu", true); - break; - - case MSG_CPU_68040: - PrefsReplaceInt32("cpu", 4); - PrefsReplaceBool("fpu", true); - break; - - default: { - // Screen mode messages - if ((msg->what & 0xffff0000) == MSG_SCREEN_MODE) { - int m = msg->what & 0xffff; - uint32 mask = scr_mode[m].mode_mask; - for (int i=0; i<32; i++) - if (mask & (1 << i)) - scr_mode_bit = i; - } else - BWindow::MessageReceived(msg); - } - } -} diff --git a/BasiliskII/src/BeOS/scsi_beos.cpp b/BasiliskII/src/BeOS/scsi_beos.cpp deleted file mode 100644 index 75d1e29a..00000000 --- a/BasiliskII/src/BeOS/scsi_beos.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - * scsi_beos.cpp - SCSI Manager, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#ifdef __HAIKU__ -#include -#else -#include -#endif - -#include "sysdeps.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "scsi.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static raw_device_command rdc; - -static int fds[8*8]; // fd's for 8 units and 8 LUNs each -static int fd; // Active fd (selected target) - -static uint32 buffer_size; // Size of data buffer -static uint8 *buffer = NULL; // Pointer to data buffer - -static uint8 sense_data[256]; // Buffer for autosense data - - -/* - * Initialization - */ - -void SCSIInit(void) -{ - int id, lun; - - // Allocate buffer - buffer = (uint8 *)malloc(buffer_size = 0x10000); - - // Open scsi_raw driver for all 8 units (and all 8 LUNs) - char dev_name[256]; - for (id=0; id<8; id++) { - for (lun=0; lun<8; lun++) - fds[id*8+lun] = -1; - char prefs_name[16]; - sprintf(prefs_name, "scsi%d", id); - const char *str = PrefsFindString(prefs_name); - if (str) { - int bus, unit; - if (sscanf(str, "%d/%d", &bus, &unit) == 2) { - for (lun=0; lun<8; lun++) { - sprintf(dev_name, "/dev/bus/scsi/%d/%d/%d/raw", bus, unit, lun); - D(bug("SCSI %d: Opening %s\n", id, dev_name)); - fds[id*8+lun] = open(dev_name, O_RDWR); - } - } - } - } - - // Reset SCSI bus - SCSIReset(); - - // Init rdc - memset(&rdc, 0, sizeof(rdc)); - rdc.data = buffer; - rdc.sense_data = sense_data; -} - - -/* - * Deinitialization - */ - -void SCSIExit(void) -{ - // Close all devices - for (int i=0; i<8; i++) - for (int j=0; j<8; j++) { - int fd = fds[i*8+j]; - if (fd > 0) - close(fd); - } - - // Free buffer - if (buffer) { - free(buffer); - buffer = NULL; - } -} - - -/* - * Check if requested data size fits into buffer, allocate new buffer if needed - */ - -static bool try_buffer(int size) -{ - if (size <= buffer_size) - return true; - - uint8 *new_buffer = (uint8 *)malloc(size); - if (new_buffer == NULL) - return false; - free(buffer); - buffer = new_buffer; - buffer_size = size; - return true; -} - - -/* - * Set SCSI command to be sent by scsi_send_cmd() - */ - -void scsi_set_cmd(int cmd_length, uint8 *cmd) -{ - rdc.command_length = cmd_length; - memcpy(rdc.command, cmd, cmd_length); -} - - -/* - * Check for presence of SCSI target - */ - -bool scsi_is_target_present(int id) -{ - return fds[id * 8] > 0; -} - - -/* - * Set SCSI target (returns false on error) - */ - -bool scsi_set_target(int id, int lun) -{ - int new_fd = fds[id * 8 + lun]; - if (new_fd < 0) - return false; - if (new_fd != fd) - rdc.cam_status &= ~CAM_AUTOSNS_VALID; // Clear sense data when selecting new target - fd = new_fd; - return true; -} - - -/* - * Send SCSI command to active target (scsi_set_command() must have been called), - * read/write data according to S/G table (returns false on error); timeout is in 1/60 sec - */ - -bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout) -{ - // Check if buffer is large enough, allocate new buffer if needed - if (!try_buffer(data_length)) { - char str[256]; - sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length); - ErrorAlert(str); - return false; - } - - // Process S/G table when writing - if (!reading) { - D(bug(" writing to buffer\n")); - uint8 *buffer_ptr = buffer; - for (int i=0; i -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "serial.h" -#include "serial_defs.h" - -#define DEBUG 0 -#include "debug.h" - -#define MONITOR 0 - - -// Buffer size for kernel-space transfers -const int TMP_BUF_SIZE = 2048; - -// These packets are sent to the input/output threads -const uint32 CMD_READ = 'read'; -const uint32 CMD_WRITE = 'writ'; -const uint32 CMD_QUIT = 'quit'; - -struct ThreadPacket { - uint32 pb; -}; - - -// Driver private variables -class BeSERDPort : public SERDPort { -public: - BeSERDPort(const char *dev) - { - device_name = dev; - if (strstr(dev, "parallel")) { - is_parallel = true; - fd = -1; - device = NULL; - } else { - is_parallel = false; - device = new BSerialPort; - } - device_sem = create_sem(1, "serial port"); - input_thread = output_thread = 0; - } - - virtual ~BeSERDPort() - { - status_t l; - if (input_thread > 0) { - send_data(input_thread, CMD_QUIT, NULL, 0); - suspend_thread(input_thread); // Unblock thread - snooze(1000); - resume_thread(input_thread); - while (wait_for_thread(input_thread, &l) == B_INTERRUPTED) ; - } - if (output_thread > 0) { - send_data(output_thread, CMD_QUIT, NULL, 0); - suspend_thread(output_thread); // Unblock thread - snooze(1000); - resume_thread(output_thread); - while (wait_for_thread(output_thread, &l) == B_INTERRUPTED) ; - } - acquire_sem(device_sem); - delete_sem(device_sem); - delete device; - } - - virtual int16 open(uint16 config); - virtual int16 prime_in(uint32 pb, uint32 dce); - virtual int16 prime_out(uint32 pb, uint32 dce); - virtual int16 control(uint32 pb, uint32 dce, uint16 code); - virtual int16 status(uint32 pb, uint32 dce, uint16 code); - virtual int16 close(void); - -private: - bool configure(uint16 config); - void set_handshake(uint32 s, bool with_dtr); - static status_t input_func(void *arg); - static status_t output_func(void *arg); - - const char *device_name; // Name of BeOS port - BSerialPort *device; // BeOS port object - bool is_parallel; // Flag: Port is parallel, use fd - int fd; // FD for parallel ports - sem_id device_sem; // BSerialPort arbitration - - thread_id input_thread; // Data input thread - thread_id output_thread; // Data output thread - - bool io_killed; // Flag: KillIO called, I/O threads must not call deferred tasks - bool drop_dtr_on_close; // Flag: Negate DTR when driver is closed - - uint8 tmp_in_buf[TMP_BUF_SIZE]; // Buffers for copying from/to kernel space - uint8 tmp_out_buf[TMP_BUF_SIZE]; -}; - - -#if DEBUG -static const int baud_rates[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 31250 -}; -#endif - - -/* - * Initialization - */ - -void SerialInit(void) -{ - // Read serial preferences and create structs for both ports - the_serd_port[0] = new BeSERDPort(PrefsFindString("seriala")); - the_serd_port[1] = new BeSERDPort(PrefsFindString("serialb")); -} - - -/* - * Deinitialization - */ - -void SerialExit(void) -{ - delete (BeSERDPort *)the_serd_port[0]; - delete (BeSERDPort *)the_serd_port[1]; -} - - -/* - * Open serial port - */ - -int16 BeSERDPort::open(uint16 config) -{ - // Don't open NULL name devices - if (device_name == NULL) - return openErr; - - // Init variables - io_killed = false; - drop_dtr_on_close = true; - - // Open port - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - if (is_parallel) { - char name[256]; - sprintf(name, "/dev/parallel/%s", device_name); - fd = ::open(name, O_WRONLY); - if (fd < 0) { - release_sem(device_sem); - return openErr; - } - } else { - device->SetFlowControl(B_HARDWARE_CONTROL); // Must be set before port is opened - if (device->Open(device_name) > 0) { - device->SetBlocking(true); - device->SetTimeout(10000000); - device->SetDTR(true); - device->SetRTS(true); - } else { - release_sem(device_sem); - return openErr; - } - } - - // Start input/output threads - release_sem(device_sem); - configure(config); - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - while ((input_thread = spawn_thread(input_func, "Serial Input", B_NORMAL_PRIORITY, this)) == B_INTERRUPTED) ; - resume_thread(input_thread); - while ((output_thread = spawn_thread(output_func, "Serial Output", B_NORMAL_PRIORITY, this)) == B_INTERRUPTED) ; - resume_thread(output_thread); - release_sem(device_sem); - return noErr; -} - - -/* - * Read data from port - */ - -int16 BeSERDPort::prime_in(uint32 pb, uint32 dce) -{ - // Send input command to input_thread - read_done = false; - read_pending = true; - ThreadPacket p; - p.pb = pb; - WriteMacInt32(input_dt + serdtDCE, dce); - while (send_data(input_thread, CMD_READ, &p, sizeof(ThreadPacket)) == B_INTERRUPTED) ; - return 1; // Command in progress -} - - -/* - * Write data to port - */ - -int16 BeSERDPort::prime_out(uint32 pb, uint32 dce) -{ - // Send output command to output_thread - write_done = false; - write_pending = true; - ThreadPacket p; - p.pb = pb; - WriteMacInt32(output_dt + serdtDCE, dce); - while (send_data(output_thread, CMD_WRITE, &p, sizeof(ThreadPacket)) == B_INTERRUPTED) ; - return 1; // Command in progress -} - - -/* - * Control calls - */ - -int16 BeSERDPort::control(uint32 pb, uint32 dce, uint16 code) -{ - switch (code) { - case 1: // KillIO - io_killed = true; - suspend_thread(input_thread); // Unblock threads - suspend_thread(output_thread); - snooze(1000); - resume_thread(input_thread); - resume_thread(output_thread); - while (read_pending || write_pending) - snooze(10000); - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->ClearInput(); - device->ClearOutput(); - release_sem(device_sem); - } - io_killed = false; - return noErr; - - case kSERDConfiguration: - if (configure(ReadMacInt16(pb + csParam))) - return noErr; - else - return paramErr; - - case kSERDInputBuffer: - return noErr; // Not supported under BeOS - - case kSERDSerHShake: - set_handshake(pb + csParam, false); - return noErr; - - case kSERDClearBreak: - case kSERDSetBreak: - return noErr; // Not supported under BeOS - - case kSERDBaudRate: - if (!is_parallel) { - uint16 rate = ReadMacInt16(pb + csParam); - data_rate baud_rate; - if (rate <= 50) { - rate = 50; baud_rate = B_50_BPS; - } else if (rate <= 75) { - rate = 75; baud_rate = B_75_BPS; - } else if (rate <= 110) { - rate = 110; baud_rate = B_110_BPS; - } else if (rate <= 134) { - rate = 134; baud_rate = B_134_BPS; - } else if (rate <= 150) { - rate = 150; baud_rate = B_150_BPS; - } else if (rate <= 200) { - rate = 200; baud_rate = B_200_BPS; - } else if (rate <= 300) { - rate = 300; baud_rate = B_300_BPS; - } else if (rate <= 600) { - rate = 600; baud_rate = B_600_BPS; - } else if (rate <= 1200) { - rate = 1200; baud_rate = B_1200_BPS; - } else if (rate <= 1800) { - rate = 1800; baud_rate = B_1800_BPS; - } else if (rate <= 2400) { - rate = 2400; baud_rate = B_2400_BPS; - } else if (rate <= 4800) { - rate = 4800; baud_rate = B_4800_BPS; - } else if (rate <= 9600) { - rate = 9600; baud_rate = B_9600_BPS; - } else if (rate <= 19200) { - rate = 19200; baud_rate = B_19200_BPS; - } else if (rate <= 31250) { - rate = 31250; baud_rate = B_31250_BPS; - } else if (rate <= 38400) { - rate = 38400; baud_rate = B_38400_BPS; - } else if (rate <= 57600) { - rate = 57600; baud_rate = B_57600_BPS; - } - WriteMacInt16(pb + csParam, rate); - acquire_sem(device_sem); - if (device->SetDataRate(baud_rate) == B_OK) { - release_sem(device_sem); - return noErr; - } else { - release_sem(device_sem); - return paramErr; - } - } else - return noErr; - - case kSERDHandshake: - case kSERDHandshakeRS232: - set_handshake(pb + csParam, true); - return noErr; - - case kSERDClockMIDI: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->SetParityMode(B_NO_PARITY); - device->SetDataBits(B_DATA_BITS_8); - device->SetStopBits(B_STOP_BITS_1); - if (device->SetDataRate(B_31250_BPS) == B_OK) { - release_sem(device_sem); - return noErr; - } else { - release_sem(device_sem); - return paramErr; - } - } else - return noErr; - - case kSERDMiscOptions: - drop_dtr_on_close = !(ReadMacInt8(pb + csParam) & kOptionPreserveDTR); - return noErr; - - case kSERDAssertDTR: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->SetDTR(true); - release_sem(device_sem); - } - return noErr; - - case kSERDNegateDTR: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->SetDTR(false); - release_sem(device_sem); - } - return noErr; - - case kSERDSetPEChar: - case kSERDSetPEAltChar: - return noErr; // Not supported under BeOS - - case kSERDResetChannel: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->ClearInput(); - device->ClearOutput(); - release_sem(device_sem); - } - return noErr; - - case kSERDAssertRTS: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->SetRTS(true); - release_sem(device_sem); - } - return noErr; - - case kSERDNegateRTS: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->SetRTS(false); - release_sem(device_sem); - } - return noErr; - - case kSERD115KBaud: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - if (device->DataRate() != B_115200_BPS) - if (device->SetDataRate(B_115200_BPS) != B_OK) { - release_sem(device_sem); - return paramErr; - } - release_sem(device_sem); - } - return noErr; - - case kSERD230KBaud: - case kSERDSetHighSpeed: - if (!is_parallel) { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - if (device->DataRate() != B_230400_BPS) - if (device->SetDataRate(B_230400_BPS) != B_OK) { - release_sem(device_sem); - return paramErr; - } - release_sem(device_sem); - } - return noErr; - - default: - printf("WARNING: SerialControl(): unimplemented control code %d\n", code); - return controlErr; - } -} - - -/* - * Status calls - */ - -int16 BeSERDPort::status(uint32 pb, uint32 dce, uint16 code) -{ - switch (code) { - case kSERDInputCount: - WriteMacInt32(pb + csParam, 0); - if (!is_parallel) { - int32 num = 0; - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - device->NumCharsAvailable(&num); - release_sem(device_sem); - D(bug(" %d bytes in buffer\n", num)); - WriteMacInt32(pb + csParam, num); - } - return noErr; - - case kSERDStatus: { - uint32 p = pb + csParam; - WriteMacInt8(p + staCumErrs, cum_errors); - cum_errors = 0; - WriteMacInt8(p + staXOffSent, 0); - WriteMacInt8(p + staXOffHold, 0); - WriteMacInt8(p + staRdPend, read_pending); - WriteMacInt8(p + staWrPend, write_pending); - if (is_parallel) { - WriteMacInt8(p + staCtsHold, 0); - WriteMacInt8(p + staDsrHold, 0); - WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent); - } else { - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - WriteMacInt8(p + staCtsHold, !device->IsCTS()); - WriteMacInt8(p + staDsrHold, !device->IsDSR()); - WriteMacInt8(p + staModemStatus, - (device->IsDSR() ? dsrEvent : 0) - | (device->IsRI() ? riEvent : 0) - | (device->IsDCD() ? dcdEvent : 0) - | (device->IsCTS() ? ctsEvent : 0)); - release_sem(device_sem); - } - return noErr; - } - - default: - printf("WARNING: SerialStatus(): unimplemented status code %d\n", code); - return statusErr; - } -} - - -/* - * Close serial port - */ - -int16 BeSERDPort::close() -{ - // Kill threads - status_t l; - io_killed = true; - if (input_thread > 0) { - while (send_data(input_thread, CMD_QUIT, NULL, 0) == B_INTERRUPTED) ; - if (read_pending) { - suspend_thread(input_thread); // Unblock thread - snooze(1000); - resume_thread(input_thread); - } - while (wait_for_thread(input_thread, &l) == B_INTERRUPTED) ; - } - if (output_thread > 0) { - while (send_data(output_thread, CMD_QUIT, NULL, 0) == B_INTERRUPTED) ; - if (write_pending) { - suspend_thread(output_thread); // Unblock thread - snooze(1000); - resume_thread(output_thread); - } - while (wait_for_thread(output_thread, &l) == B_INTERRUPTED) ; - } - input_thread = output_thread = 0; - - // Close port - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - if (is_parallel) { - ::close(fd); - fd = -1; - } else { - if (drop_dtr_on_close) - device->SetDTR(false); - device->Close(); - } - release_sem(device_sem); - return noErr; -} - - -/* - * Configure serial port with MacOS config word - */ - -bool BeSERDPort::configure(uint16 config) -{ - D(bug(" configure %04x\n", config)); - if (is_parallel) - return true; - - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - - // Set number of stop bits - switch (config & 0xc000) { - case stop10: - if (device->StopBits() != B_STOP_BITS_1) - device->SetStopBits(B_STOP_BITS_1); - break; - case stop20: - if (device->StopBits() != B_STOP_BITS_2) - device->SetStopBits(B_STOP_BITS_2); - break; - default: - release_sem(device_sem); - return false; - } - - // Set parity mode - switch (config & 0x3000) { - case noParity: - if (device->ParityMode() != B_NO_PARITY) - device->SetParityMode(B_NO_PARITY); - break; - case oddParity: - if (device->ParityMode() != B_ODD_PARITY) - device->SetParityMode(B_ODD_PARITY); - break; - case evenParity: - if (device->ParityMode() != B_EVEN_PARITY) - device->SetParityMode(B_EVEN_PARITY); - break; - default: - release_sem(device_sem); - return false; - } - - // Set number of data bits - switch (config & 0x0c00) { - case data7: - if (device->DataBits() != B_DATA_BITS_7) - device->SetDataBits(B_DATA_BITS_7); - break; - case data8: - if (device->DataBits() != B_DATA_BITS_8) - device->SetDataBits(B_DATA_BITS_8); - break; - default: - release_sem(device_sem); - return false; - } - - // Set baud rate - data_rate baud_rate; - switch (config & 0x03ff) { - case baud150: baud_rate = B_150_BPS; break; - case baud300: baud_rate = B_300_BPS; break; - case baud600: baud_rate = B_600_BPS; break; - case baud1200: baud_rate = B_1200_BPS; break; - case baud1800: baud_rate = B_1800_BPS; break; - case baud2400: baud_rate = B_2400_BPS; break; - case baud4800: baud_rate = B_4800_BPS; break; - case baud9600: baud_rate = B_9600_BPS; break; - case baud19200: baud_rate = B_19200_BPS; break; - case baud38400: baud_rate = B_38400_BPS; break; - case baud57600: baud_rate = B_57600_BPS; break; - default: - release_sem(device_sem); - return false; - } - - D(bug(" baud rate %d, %d stop bits, %s parity, %d data bits\n", baud_rates[baud_rate], device->StopBits() == B_STOP_BITS_1 ? 1 : 2, device->ParityMode() == B_NO_PARITY ? "no" : device->ParityMode() == B_ODD_PARITY ? "odd" : "even", device->DataBits() == B_DATA_BITS_7 ? 7 : 8)); - if (device->DataRate() != baud_rate) { - bool res = device->SetDataRate(baud_rate) == B_OK; - release_sem(device_sem); - return res; - } else { - release_sem(device_sem); - return true; - } -} - - -/* - * Set serial handshaking - */ - -void BeSERDPort::set_handshake(uint32 s, bool with_dtr) -{ - D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n", - ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3), - ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7))); - if (is_parallel) - return; - - uint32 flow; - if (with_dtr) { - if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) - flow = B_HARDWARE_CONTROL; - else - flow = B_SOFTWARE_CONTROL; - } else { - if (ReadMacInt8(s + shkFCTS)) - flow = B_HARDWARE_CONTROL; - else - flow = B_SOFTWARE_CONTROL; - } - - D(bug(" %sware flow control\n", flow == B_HARDWARE_CONTROL ? "hard" : "soft")); - while (acquire_sem(device_sem) == B_INTERRUPTED) ; - if (device->FlowControl() != flow) { - device->Close(); - device->SetFlowControl(flow); - device->Open(device_name); - } - release_sem(device_sem); -} - - -/* - * Data input thread - */ - -status_t BeSERDPort::input_func(void *arg) -{ - BeSERDPort *s = (BeSERDPort *)arg; - for (;;) { - - // Wait for commands - thread_id sender; - ThreadPacket p; - uint32 code = receive_data(&sender, &p, sizeof(ThreadPacket)); - if (code == CMD_QUIT) - break; - if (code != CMD_READ) - continue; - - // Execute command - void *buf = Mac2HostAddr(ReadMacInt32(p.pb + ioBuffer)); - uint32 length = ReadMacInt32(p.pb + ioReqCount); - D(bug("input_func waiting for %ld bytes of data...\n", length)); - int32 actual; - - // Buffer in kernel space? - if ((uint32)buf < 0x80000000) { - - // Yes, transfer via buffer - actual = 0; - while (length) { - uint32 transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length; - int32 transferred; - acquire_sem(s->device_sem); - if (s->is_parallel) { - if ((transferred = read(s->fd, s->tmp_in_buf, transfer_size)) < 0 || s->io_killed) { - // Error - actual = transferred; - release_sem(s->device_sem); - break; - } - } else { - if ((transferred = s->device->Read(s->tmp_in_buf, transfer_size)) < 0 || s->io_killed) { - // Error - actual = transferred; - release_sem(s->device_sem); - break; - } - } - release_sem(s->device_sem); - memcpy(buf, s->tmp_in_buf, transferred); - buf = (void *)((uint8 *)buf + transferred); - length -= transferred; - actual += transferred; - } - - } else { - - // No, transfer directly - acquire_sem(s->device_sem); - if (s->is_parallel) - actual = read(s->fd, buf, length); - else - actual = s->device->Read(buf, length); - release_sem(s->device_sem); - } - - D(bug(" %ld bytes received\n", actual)); - -#if MONITOR - bug("Receiving serial data:\n"); - uint8 *adr = Mac2HostAddr(ReadMacInt32(p.pb + ioBuffer)); - for (int i=0; iio_killed) { - - WriteMacInt16(p.pb + ioResult, abortErr); - WriteMacInt32(p.pb + ioActCount, 0); - s->read_pending = s->read_done = false; - - } else { - - // Set error code - if (actual >= 0) { - WriteMacInt32(p.pb + ioActCount, actual); - WriteMacInt32(s->input_dt + serdtResult, noErr); - } else { - WriteMacInt32(p.pb + ioActCount, 0); - WriteMacInt32(s->input_dt + serdtResult, readErr); - } - - // Trigger serial interrupt - D(bug(" triggering serial interrupt\n")); - s->read_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - return 0; -} - - -/* - * Data output thread - */ - -status_t BeSERDPort::output_func(void *arg) -{ - BeSERDPort *s = (BeSERDPort *)arg; - for (;;) { - - // Wait for commands - thread_id sender; - ThreadPacket p; - uint32 code = receive_data(&sender, &p, sizeof(ThreadPacket)); - if (code == CMD_QUIT) - break; - if (code != CMD_WRITE) - continue; - - // Execute command - void *buf = Mac2HostAddr(ReadMacInt32(p.pb + ioBuffer)); - uint32 length = ReadMacInt32(p.pb + ioReqCount); - D(bug("output_func transmitting %ld bytes of data...\n", length)); - int32 actual; - -#if MONITOR - bug("Sending serial data:\n"); - uint8 *adr = (uint8 *)buf; - for (int i=0; i TMP_BUF_SIZE) ? TMP_BUF_SIZE : length; - memcpy(s->tmp_out_buf, buf, transfer_size); - int32 transferred; - acquire_sem(s->device_sem); - if (s->is_parallel) { - if ((transferred = write(s->fd, s->tmp_out_buf, transfer_size)) < transfer_size || s->io_killed) { - if (transferred < 0) // Error - actual = transferred; - else - actual += transferred; - release_sem(s->device_sem); - break; - } - } else { - if ((transferred = s->device->Write(s->tmp_out_buf, transfer_size)) < transfer_size || s->io_killed) { - if (transferred < 0) // Error - actual = transferred; - else - actual += transferred; - release_sem(s->device_sem); - break; - } - } - release_sem(s->device_sem); - if (transferred > transfer_size) // R3 parallel port driver bug - transferred = transfer_size; - buf = (void *)((uint8 *)buf + transferred); - length -= transferred; - actual += transferred; - } - - } else { - - // No, transfer directly - acquire_sem(s->device_sem); - if (s->is_parallel) - actual = write(s->fd, buf, length); - else - actual = s->device->Write(buf, length); - release_sem(s->device_sem); - if (actual > length) // R3 parallel port driver bug - actual = length; - } - - D(bug(" %ld bytes transmitted\n", actual)); - - // KillIO called? Then simply return - if (s->io_killed) { - - WriteMacInt16(p.pb + ioResult, abortErr); - WriteMacInt32(p.pb + ioActCount, 0); - s->write_pending = s->write_done = false; - - } else { - - // Set error code - if (actual >= 0) { - WriteMacInt32(p.pb + ioActCount, actual); - WriteMacInt32(s->output_dt + serdtResult, noErr); - } else { - WriteMacInt32(p.pb + ioActCount, 0); - WriteMacInt32(s->output_dt + serdtResult, writErr); - } - - // Trigger serial interrupt - D(bug(" triggering serial interrupt\n")); - s->write_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - return 0; -} diff --git a/BasiliskII/src/BeOS/sys_beos.cpp b/BasiliskII/src/BeOS/sys_beos.cpp deleted file mode 100644 index ff6fcb83..00000000 --- a/BasiliskII/src/BeOS/sys_beos.cpp +++ /dev/null @@ -1,841 +0,0 @@ -/* - * sys_beos.cpp - System dependent routines, BeOS implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "user_strings.h" -#include "sys.h" - -#define DEBUG 0 -#include "debug.h" - -#ifdef __HAIKU__ -#include -#define unmount(x) fs_unmount_volume(x, 0) -#endif - - -// File handles are pointers to these structures -struct file_handle { - file_handle *next; // Pointer to next file handle (must be first in struct!) - const char *name; // File/device name (copied, for mount menu) - int fd; // fd of file/device - bool is_file; // Flag: plain file or /dev/something? - bool read_only; // Copy of Sys_open() flag - loff_t start_byte; // Size of file header (if any) - loff_t file_size; // Size of file data (only valid if is_file is true) -}; - -// Linked list of file handles -static file_handle *first_file_handle; - -// Temporary buffer for transfers from/to kernel space -const int TMP_BUF_SIZE = 0x10000; -static uint8 *tmp_buf; - -// For B_SCSI_PREVENT_ALLOW -static const int32 PREVENT = 1; -static const int32 ALLOW = 0; - - -/* - * Check if device is a mounted HFS volume, get mount name - */ - -static bool is_drive_mounted(const char *dev_name, char *mount_name) -{ - int32 i = 0; - dev_t d; - fs_info info; - while ((d = next_dev(&i)) >= 0) { - fs_stat_dev(d, &info); - if (strcmp(dev_name, info.device_name) == 0) { - status_t err = -1; - BPath mount; - BDirectory dir; - BEntry entry; - node_ref node; - node.device = info.dev; - node.node = info.root; - err = dir.SetTo(&node); - if (!err) - err = dir.GetEntry(&entry); - if (!err) - err = entry.GetPath(&mount); - if (!err) { - strcpy(mount_name, mount.Path()); - return true; - } - } - } - return false; -} - - -/* - * Initialization - */ - -void SysInit(void) -{ - first_file_handle = NULL; - - // Allocate temporary buffer - tmp_buf = new uint8[TMP_BUF_SIZE]; -} - - -/* - * Deinitialization - */ - -void SysExit(void) -{ - delete[] tmp_buf; -} - - -/* - * Create menu of used volumes (for "mount" menu) - */ - -void SysCreateVolumeMenu(BMenu *menu, uint32 msg) -{ - for (file_handle *fh=first_file_handle; fh; fh=fh->next) - if (!SysIsFixedDisk(fh)) - menu->AddItem(new BMenuItem(fh->name, new BMessage(msg))); -} - - -/* - * Mount volume given name from mount menu - */ - -void SysMountVolume(const char *name) -{ - file_handle *fh; - for (fh=first_file_handle; fh && strcmp(fh->name, name); fh=fh->next) ; - if (fh) - MountVolume(fh); -} - - -/* - * This gets called when no "floppy" prefs items are found - * It scans for available floppy drives and adds appropriate prefs items - */ - -void SysAddFloppyPrefs(void) -{ - // Only one floppy drive under BeOS - PrefsAddString("floppy", "/dev/disk/floppy/raw"); -} - - -/* - * This gets called when no "disk" prefs items are found - * It scans for available HFS volumes and adds appropriate prefs items - */ - -void SysAddDiskPrefs(void) -{ - // Let BeOS scan for HFS drives - D(bug("Looking for Mac volumes...\n")); - system("mountvolume -allhfs"); - - // Add all HFS volumes - int32 i = 0; - dev_t d; - fs_info info; - while ((d = next_dev(&i)) >= 0) { - fs_stat_dev(d, &info); - status_t err = -1; - BPath mount; - if (!strcmp(info.fsh_name, "hfs")) { - BDirectory dir; - BEntry entry; - node_ref node; - node.device = info.dev; - node.node = info.root; - err = dir.SetTo(&node); - if (!err) - err = dir.GetEntry(&entry); - if (!err) - err = entry.GetPath(&mount); - } - if (!err) - err = unmount(mount.Path()); - if (!err) { - char dev_name[B_FILE_NAME_LENGTH]; - if (info.flags & B_FS_IS_READONLY) { - dev_name[0] = '*'; - dev_name[1] = 0; - } else - dev_name[0] = 0; - strcat(dev_name, info.device_name); - PrefsAddString("disk", dev_name); - } - } -} - - -/* - * This gets called when no "cdrom" prefs items are found - * It scans for available CD-ROM drives and adds appropriate prefs items - */ - -// Scan directory for CD-ROM drives, add them to prefs -static void scan_for_cdrom_drives(const char *directory) -{ - // Set directory - BDirectory dir; - dir.SetTo(directory); - if (dir.InitCheck() != B_NO_ERROR) - return; - dir.Rewind(); - - // Scan each entry - BEntry entry; - while (dir.GetNextEntry(&entry) >= 0) { - - // Get path and ref for entry - BPath path; - if (entry.GetPath(&path) != B_NO_ERROR) - continue; - const char *name = path.Path(); - entry_ref e; - if (entry.GetRef(&e) != B_NO_ERROR) - continue; - - // Recursively enter subdirectories (except for floppy) - if (entry.IsDirectory()) { - if (!strcmp(e.name, "floppy")) - continue; - scan_for_cdrom_drives(name); - } else { - - D(bug(" checking '%s'\n", name)); - - // Ignore partitions - if (strcmp(e.name, "raw")) - continue; - - // Open device - int fd = open(name, O_RDONLY); - if (fd < 0) - continue; - - // Get geometry and device type - device_geometry g; - if (ioctl(fd, B_GET_GEOMETRY, &g, sizeof(g)) < 0) { - close(fd); - continue; - } - - // Insert to list if it is a CD drive - if (g.device_type == B_CD) - PrefsAddString("cdrom", name); - close(fd); - } - } -} - -void SysAddCDROMPrefs(void) -{ - // Don't scan for drives if nocdrom option given - if (PrefsFindBool("nocdrom")) - return; - - // Look for CD-ROM drives and add prefs items - D(bug("Looking for CD-ROM drives...\n")); - scan_for_cdrom_drives("/dev/disk"); -} - - -/* - * Add default serial prefs (must be added, even if no ports present) - */ - -void SysAddSerialPrefs(void) -{ -#ifdef __HAIKU__ - PrefsAddString("seriala", "serial1"); - PrefsAddString("serialb", "serial2"); -#else - system_info info; - get_system_info(&info); - switch (info.platform_type) { - case B_BEBOX_PLATFORM: - case B_AT_CLONE_PLATFORM: - PrefsAddString("seriala", "serial1"); - PrefsAddString("serialb", "serial2"); - break; - case B_MAC_PLATFORM: - PrefsAddString("seriala", "modem"); - PrefsAddString("serialb", "printer"); - break; - default: - PrefsAddString("seriala", "none"); - PrefsAddString("serialb", "none"); - break; - } -#endif -} - - -/* - * Open file/device, create new file handle (returns NULL on error) - */ - -void *Sys_open(const char *name, bool read_only) -{ - static bool published_all = false; - bool is_file = (strstr(name, "/dev/") != name); - - D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write")); - - // Print warning message and eventually unmount drive when this is an HFS volume mounted under BeOS (double mounting will corrupt the volume) - char mount_name[B_FILE_NAME_LENGTH]; - if (!is_file && !read_only && is_drive_mounted(name, mount_name)) { - char str[256 + B_FILE_NAME_LENGTH]; - sprintf(str, GetString(STR_VOLUME_IS_MOUNTED_WARN), mount_name); - WarningAlert(str); - if (unmount(mount_name) != 0) { - sprintf(str, GetString(STR_CANNOT_UNMOUNT_WARN), mount_name); - WarningAlert(str); - return NULL; - } - } - - int fd = open(name, read_only ? O_RDONLY : O_RDWR); - if (fd < 0 && !published_all) { - // Open failed, create all device nodes and try again, but only the first time - system("mountvolume -publishall"); - published_all = true; - fd = open(name, read_only ? O_RDONLY : O_RDWR); - } - if (fd >= 0) { - file_handle *fh = new file_handle; - fh->name = strdup(name); - fh->fd = fd; - fh->is_file = is_file; - fh->read_only = read_only; - fh->start_byte = 0; - if (fh->is_file) { - // Detect disk image file layout - loff_t size = lseek(fd, 0, SEEK_END); - uint8 data[256]; - lseek(fd, 0, SEEK_SET); - read(fd, data, 256); - FileDiskLayout(size, data, fh->start_byte, fh->file_size); - } - - // Enqueue file handle - fh->next = NULL; - file_handle *q = first_file_handle; - if (q) { - while (q->next) - q = q->next; - q->next = fh; - } else - first_file_handle = fh; - return fh; - } else - return NULL; -} - - -/* - * Close file/device, delete file handle - */ - -void Sys_close(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - // Free device name and close file/device - free((void *)fh->name); - close(fh->fd); - - // Dequeue file handle - file_handle *q = first_file_handle; - if (q == fh) { - first_file_handle = NULL; - delete fh; - return; - } - while (q) { - if (q->next == fh) { - q->next = fh->next; - delete fh; - return; - } - q = q->next; - } -} - - -/* - * Read "length" bytes from file/device, starting at "offset", to "buffer", - * returns number of bytes read (or 0) - */ - -static inline ssize_t sread(int fd, void *buf, size_t count) -{ - ssize_t res; - while ((res = read(fd, buf, count)) == B_INTERRUPTED) ; - return res; -} - -size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return 0; - -// D(bug("Sys_read(%08lx, %08lx, %Ld, %d)\n", fh, buffer, offset, length)); - - // Seek to position - if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0) - return 0; - - // Buffer in kernel space? - size_t actual = 0; - if ((uint32)buffer < 0x80000000) { - - // Yes, transfer via buffer - while (length) { - size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length; - if (sread(fh->fd, tmp_buf, transfer_size) != transfer_size) - return actual; - memcpy(buffer, tmp_buf, transfer_size); - buffer = (void *)((uint8 *)buffer + transfer_size); - length -= transfer_size; - actual += transfer_size; - } - - } else { - - // No, transfer directly - actual = sread(fh->fd, buffer, length); - if (actual < 0) - actual = 0; - } - return actual; -} - - -/* - * Write "length" bytes from "buffer" to file/device, starting at "offset", - * returns number of bytes written (or 0) - */ - -static inline ssize_t swrite(int fd, void *buf, size_t count) -{ - ssize_t res; - while ((res = write(fd, buf, count)) == B_INTERRUPTED) ; - return res; -} - -size_t Sys_write(void *arg, void *buffer, loff_t offset, size_t length) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return 0; - -// D(bug("Sys_write(%08lx, %08lx, %Ld, %d)\n", fh, buffer, offset, length)); - - // Seek to position - if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0) - return 0; - - // Buffer in kernel space? - size_t actual = 0; - if ((uint32)buffer < 0x80000000) { - - // Yes, transfer via buffer - while (length) { - size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length; - memcpy(tmp_buf, buffer, transfer_size); - if (swrite(fh->fd, tmp_buf, transfer_size) != transfer_size) - return actual; - buffer = (void *)((uint8 *)buffer + transfer_size); - length -= transfer_size; - actual += transfer_size; - } - - } else { - - // No, transfer directly - actual = swrite(fh->fd, buffer, length); - if (actual < 0) - actual = 0; - } - return actual; -} - - -/* - * Return size of file/device (minus header) - */ - -loff_t SysGetFileSize(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (fh->is_file) - return fh->file_size; - else { - device_geometry g; - if (ioctl(fh->fd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) - return (loff_t)g.bytes_per_sector * g.sectors_per_track * g.cylinder_count * g.head_count; - else - return 0; - } -} - - -/* - * Eject volume (if applicable) - */ - -void SysEject(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) - ioctl(fh->fd, B_EJECT_DEVICE); -} - - -/* - * Format volume (if applicable) - */ - -bool SysFormat(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) - return ioctl(fh->fd, B_FORMAT_DEVICE) >= 0; - else - return false; -} - - -/* - * Check if file/device is read-only (this includes the read-only flag on Sys_open()) - */ - -bool SysIsReadOnly(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (fh->is_file) { - - // File, return flag given to Sys_open - return fh->read_only; - - } else { - - // Device, check write protection - device_geometry g; - if (ioctl(fh->fd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) - return g.read_only | fh->read_only; - else - return fh->read_only; // Removable but not inserted - } -} - - -/* - * Check if the given file handle refers to a fixed or a removable disk - */ - -bool SysIsFixedDisk(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (fh->is_file) - return true; - else { - device_geometry g; - if (ioctl(fh->fd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) - return !g.removable; - else - return false; // Removable but not inserted - } -} - - -/* - * Check if a disk is inserted in the drive (always true for files) - */ - -bool SysIsDiskInserted(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return true; - else { - status_t l; - if (ioctl(fh->fd, B_GET_MEDIA_STATUS, &l, sizeof(l)) >= 0 && l == B_NO_ERROR) - return true; - else - return false; - } -} - - -/* - * Prevent medium removal (if applicable) - */ - -void SysPreventRemoval(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) - ioctl(fh->fd, B_SCSI_PREVENT_ALLOW, &PREVENT, sizeof(PREVENT)); -} - - -/* - * Allow medium removal (if applicable) - */ - -void SysAllowRemoval(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) - ioctl(fh->fd, B_SCSI_PREVENT_ALLOW, &ALLOW, sizeof(ALLOW)); -} - - -/* - * Read CD-ROM TOC (binary MSF format, 804 bytes max.) - */ - -bool SysCDReadTOC(void *arg, uint8 *toc) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) { - memset(tmp_buf, 0, 804); - if (ioctl(fh->fd, B_SCSI_GET_TOC, tmp_buf, 804) < 0) - return false; - memcpy(toc, tmp_buf, 804); - return true; - } else - return false; -} - - -/* - * Read CD-ROM position data (Sub-Q Channel, 16 bytes, see SCSI standard) - */ - -bool SysCDGetPosition(void *arg, uint8 *pos) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) { - if (ioctl(fh->fd, B_SCSI_GET_POSITION, tmp_buf, 16) < 0) - return false; - memcpy(pos, tmp_buf, 16); - return true; - } else - return false; -} - - -/* - * Play CD audio - */ - -bool SysCDPlay(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, uint8 end_m, uint8 end_s, uint8 end_f) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) { - scsi_play_position *p = (scsi_play_position *)tmp_buf; - p->start_m = start_m; - p->start_s = start_s; - p->start_f = start_f; - p->end_m = end_m; - p->end_s = end_s; - p->end_f = end_f; - return ioctl(fh->fd, B_SCSI_PLAY_POSITION, p, sizeof(scsi_play_position)) == 0; - } else - return false; -} - - -/* - * Pause CD audio - */ - -bool SysCDPause(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (!fh->is_file) - return ioctl(fh->fd, B_SCSI_PAUSE_AUDIO) == 0; - else - return false; -} - - -/* - * Resume paused CD audio - */ - -bool SysCDResume(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) - return ioctl(fh->fd, B_SCSI_RESUME_AUDIO) == 0; - else - return false; -} - - -/* - * Stop CD audio - */ - -bool SysCDStop(void *arg, uint8 lead_out_m, uint8 lead_out_s, uint8 lead_out_f) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) - return ioctl(fh->fd, B_SCSI_STOP_AUDIO) == 0; - else - return false; -} - - -/* - * Perform CD audio fast-forward/fast-reverse operation starting from specified address - */ - -bool SysCDScan(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, bool reverse) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (!fh->is_file) { - scsi_scan *p = (scsi_scan *)tmp_buf; - p->speed = 0; - p->direction = reverse ? -1 : 1; - return ioctl(fh->fd, B_SCSI_SCAN, p, sizeof(scsi_scan)) == 0; - } else - return false; -} - - -/* - * Set CD audio volume (0..255 each channel) - */ - -void SysCDSetVolume(void *arg, uint8 left, uint8 right) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (!fh->is_file) { - scsi_volume *p = (scsi_volume *)tmp_buf; - p->flags = B_SCSI_PORT0_VOLUME | B_SCSI_PORT1_VOLUME; - p->port0_volume = left; - p->port1_volume = right; - ioctl(fh->fd, B_SCSI_SET_VOLUME, p, sizeof(scsi_volume)); - } -} - - -/* - * Get CD audio volume (0..255 each channel) - */ - -void SysCDGetVolume(void *arg, uint8 &left, uint8 &right) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - left = right = 0; - if (!fh->is_file) { - scsi_volume *p = (scsi_volume *)tmp_buf; - p->flags = B_SCSI_PORT0_VOLUME | B_SCSI_PORT1_VOLUME; - if (ioctl(fh->fd, B_SCSI_GET_VOLUME, p, sizeof(scsi_volume)) == 0) { - left = p->port0_volume; - right = p->port1_volume; - } - } -} diff --git a/BasiliskII/src/BeOS/sysdeps.h b/BasiliskII/src/BeOS/sysdeps.h deleted file mode 100644 index ed3ba9c3..00000000 --- a/BasiliskII/src/BeOS/sysdeps.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * sysdeps.h - System dependent definitions for BeOS - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -#ifdef __POWERPC__ -#define NO_STD_NAMESPACE -#endif - -#include -#include -#include - -#include "user_strings_beos.h" - -// Are the Mac and the host address space the same? -#ifdef __i386__ -#define REAL_ADDRESSING 0 -#undef WORDS_BIGENDIAN -#else -#define REAL_ADDRESSING 1 -#define WORDS_BIGENDIAN 1 -#endif - -// Using 68k emulator -#define EMULATED_68K 1 - -// Mac ROM is write protected -#define ROM_IS_WRITE_PROTECTED 1 - -// ExtFS is supported -#define SUPPORTS_EXTFS 1 - -// BSD socket API is supported -#define SUPPORTS_UDP_TUNNEL 1 - -// mon is not supported -#undef ENABLE_MON - -// Time data type for Time Manager emulation -typedef bigtime_t tm_time_t; - -// 64 bit file offsets -typedef off_t loff_t; - -// Networking types -#define PF_INET AF_INET -#ifndef __HAIKU__ -typedef int socklen_t; -#endif - -// UAE CPU data types -#define uae_s8 int8 -#define uae_u8 uint8 -#define uae_s16 int16 -#define uae_u16 uint16 -#define uae_s32 int32 -#define uae_u32 uint32 -#define uae_s64 int64 -#define uae_u64 uint64 -typedef uae_u32 uaecptr; -#define VAL64(a) (a ## LL) -#define UVAL64(a) (a ## uLL) -typedef uint32 uintptr; -typedef int32 intptr; - -/* Timing functions */ -extern void Delay_usec(uint32 usec); - -// UAE CPU defines -#ifdef __i386__ - -// Intel x86 assembler optimizations -#define X86_PPRO_OPT -static inline uae_u32 do_get_mem_long(uae_u32 *a) {uint32 retval; __asm__ ("bswap %0" : "=r" (retval) : "0" (*a) : "cc"); return retval;} -#ifdef X86_PPRO_OPT -static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint32 retval; __asm__ ("movzwl %w1,%k0\n\tshll $16,%k0\n\tbswap %k0\n" : "=&r" (retval) : "m" (*a) : "cc"); return retval;} -#else -static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint32 retval; __asm__ ("xorl %k0,%k0\n\tmovw %w1,%w0\n\trolw $8,%w0" : "=&r" (retval) : "m" (*a) : "cc"); return retval;} -#endif -#define HAVE_GET_WORD_UNSWAPPED -#define do_get_mem_word_unswapped(a) ((uae_u32)*((uae_u16 *)(a))) -static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {__asm__ ("bswap %0" : "=r" (v) : "0" (v) : "cc"); *a = v;} -#ifdef X86_PPRO_OPT -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {__asm__ ("bswap %0" : "=&r" (v) : "0" (v << 16) : "cc"); *a = v;} -#else -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {__asm__ ("rolw $8,%0" : "=r" (v) : "0" (v) : "cc"); *a = v;} -#endif - -#define X86_ASSEMBLY -#define UNALIGNED_PROFITABLE -#define OPTIMIZED_FLAGS -#define ASM_SYM(a) __asm__(a) -#define REGPARAM __attribute__((regparm(3))) - -#else - -// PowerPC (memory.cpp not used, so no optimization neccessary) -static inline uae_u32 do_get_mem_long(uae_u32 *a) {return *a;} -static inline uae_u32 do_get_mem_word(uae_u16 *a) {return *a;} -static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {*a = v;} -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {*a = v;} - -#undef X86_ASSEMBLY -#define UNALIGNED_PROFITABLE -#undef OPTIMIZED_FLAGS -#define ASM_SYM(a) -#define REGPARAM -#endif - -#define do_get_mem_byte(a) ((uae_u32)*((uae_u8 *)(a))) -#define do_put_mem_byte(a, v) (*(uae_u8 *)(a) = (v)) - -#define call_mem_get_func(func, addr) ((*func)(addr)) -#define call_mem_put_func(func, addr, v) ((*func)(addr, v)) -#define __inline__ inline -#define CPU_EMU_SIZE 0 -#undef NO_INLINE_MEMORY_ACCESS -#undef MD_HAVE_MEM_1_FUNCS -#undef USE_COMPILER -#define REGPARAM2 -#define ENUMDECL typedef enum -#define ENUMNAME(name) name -#define write_log printf - -#endif diff --git a/BasiliskII/src/BeOS/timer_beos.cpp b/BasiliskII/src/BeOS/timer_beos.cpp deleted file mode 100644 index f6e71b50..00000000 --- a/BasiliskII/src/BeOS/timer_beos.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * timer_beos.cpp - Time Manager emulation, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "sysdeps.h" -#include "macos_util.h" -#include "timer.h" - -#define DEBUG 0 -#include "debug.h" - - -// From main_beos.cpp -extern thread_id emul_thread; - - -/* - * Return microseconds since boot (64 bit) - */ - -void Microseconds(uint32 &hi, uint32 &lo) -{ - D(bug("Microseconds\n")); - bigtime_t time = system_time(); - hi = time >> 32; - lo = time; -} - - -/* - * Return local date/time in Mac format (seconds since 1.1.1904) - */ - -uint32 TimerDateTime(void) -{ - return TimeToMacTime(time(NULL)); -} - - -/* - * Get current time - */ - -void timer_current_time(tm_time_t &t) -{ - t = system_time(); -} - - -/* - * Add times - */ - -void timer_add_time(tm_time_t &res, tm_time_t a, tm_time_t b) -{ - res = a + b; -} - - -/* - * Subtract times - */ - -void timer_sub_time(tm_time_t &res, tm_time_t a, tm_time_t b) -{ - res = a - b; -} - - -/* - * Compare times (<0: a < b, =0: a = b, >0: a > b) - */ - -int timer_cmp_time(tm_time_t a, tm_time_t b) -{ - tm_time_t r = a - b; - return r < 0 ? -1 : (r > 0 ? 1 : 0); -} - - -/* - * Convert Mac time value (>0: microseconds, <0: microseconds) to tm_time_t - */ - -void timer_mac2host_time(tm_time_t &res, int32 mactime) -{ - if (mactime > 0) - res = mactime * 1000; // Time in milliseconds - else - res = -mactime; // Time in negative microseconds -} - - -/* - * Convert positive tm_time_t to Mac time value (>0: microseconds, <0: microseconds) - * A negative input value for hosttime results in a zero return value - * As long as the microseconds value fits in 32 bit, it must not be converted to milliseconds! - */ - -int32 timer_host2mac_time(tm_time_t hosttime) -{ - if (hosttime < 0) - return 0; - else if (hosttime > 0x7fffffff) - return hosttime / 1000; // Time in milliseconds - else - return -hosttime; // Time in negative microseconds -} - - -/* - * Delay by specified number of microseconds (<1 second) - */ - -void Delay_usec(uint32 usec) -{ - snooze(usec); -} - - -/* - * Suspend emulator thread, virtual CPU in idle mode - */ - -void idle_wait(void) -{ -#if 0 - /* - FIXME: add a semaphore (counter) to avoid a B_BAD_THREAD_STATE - return if we call idle_resume() when thread is not suspended? - - Sorry, I can't test -- gb. - */ - suspend_thread(emul_thread); -#endif -} - - -/* - * Resume execution of emulator thread, events just arrived - */ - -void idle_resume(void) -{ -#if 0 - resume_thread(emul_thread); -#endif -} diff --git a/BasiliskII/src/BeOS/user_strings_beos.cpp b/BasiliskII/src/BeOS/user_strings_beos.cpp deleted file mode 100644 index c3694578..00000000 --- a/BasiliskII/src/BeOS/user_strings_beos.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * user_strings_beos.cpp - BeOS-specific localizable strings - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "user_strings.h" - - -// Platform-specific string definitions -user_string_def platform_strings[] = { - // Common strings that have a platform-specific variant - {STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under BeOS. Basilisk II will try to unmount it."}, - {STR_EXTFS_CTRL, "BeOS Root"}, - {STR_EXTFS_NAME, "BeOS Directory Tree"}, - {STR_EXTFS_VOLUME_NAME, "BeOS"}, - - // Purely platform-specific strings - {STR_NO_SHEEP_DRIVER_ERR, "Cannot open /dev/sheep: %s (%08x). Basilisk II is not properly installed."}, - {STR_SHEEP_UP_ERR, "Cannot allocate Low Memory Globals: %s (%08x)."}, - {STR_NO_KERNEL_DATA_ERR, "Cannot create Kernel Data area: %s (%08x)."}, - {STR_NO_NET_ADDON_WARN, "The SheepShaver net server add-on cannot be found. Ethernet will not be available."}, - {STR_NET_CONFIG_MODIFY_WARN, "To enable Ethernet networking for Basilisk II, your network configuration has to be modified and the network restarted. Do you want this to be done now (selecting \"Cancel\" will disable Ethernet under Basilisk II)?."}, - {STR_NET_ADDON_INIT_FAILED, "SheepShaver net server add-on found\nbut there seems to be no network hardware.\nPlease check your network preferences."}, - {STR_NET_ADDON_CLONE_FAILED, "Cloning of the network transfer area failed."}, - {STR_VIDEO_FAILED, "Failed to set video mode."}, - - {-1, NULL} // End marker -}; - - -/* - * Fetch pointer to string, given the string number - */ - -const char *GetString(int num) -{ - // First search for platform-specific string - int i = 0; - while (platform_strings[i].num >= 0) { - if (platform_strings[i].num == num) - return platform_strings[i].str; - i++; - } - - // Not found, search for common string - i = 0; - while (common_strings[i].num >= 0) { - if (common_strings[i].num == num) - return common_strings[i].str; - i++; - } - return NULL; -} diff --git a/BasiliskII/src/BeOS/user_strings_beos.h b/BasiliskII/src/BeOS/user_strings_beos.h deleted file mode 100644 index 8de695e9..00000000 --- a/BasiliskII/src/BeOS/user_strings_beos.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * user_strings_beos.h - BeOS-specific localizable strings - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_BEOS_H -#define USER_STRINGS_BEOS_H - -enum { - STR_NO_SHEEP_DRIVER_ERR = 10000, - STR_SHEEP_UP_ERR, - STR_NO_KERNEL_DATA_ERR, - STR_NO_NET_ADDON_WARN, - STR_NET_CONFIG_MODIFY_WARN, - STR_NET_ADDON_INIT_FAILED, - STR_NET_ADDON_CLONE_FAILED, - STR_VIDEO_FAILED -}; - -#endif diff --git a/BasiliskII/src/BeOS/video_beos.cpp b/BasiliskII/src/BeOS/video_beos.cpp deleted file mode 100644 index d70ad834..00000000 --- a/BasiliskII/src/BeOS/video_beos.cpp +++ /dev/null @@ -1,1086 +0,0 @@ -/* - * video_beos.cpp - Video/graphics emulation, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * Portions written by Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "adb.h" -#include "prefs.h" -#include "user_strings.h" -#include "about_window.h" -#include "video.h" - -#include "m68k.h" -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" - -#define DEBUG 0 -#include "debug.h" - -#define DEBUGGER_AVAILABLE 0 - - -// Messages -const uint32 MSG_REDRAW = 'draw'; -const uint32 MSG_ABOUT_REQUESTED = B_ABOUT_REQUESTED; -const uint32 MSG_REF_5HZ = ' 5Hz'; -const uint32 MSG_REF_7_5HZ = ' 7Hz'; -const uint32 MSG_REF_10HZ = '10Hz'; -const uint32 MSG_REF_15HZ = '15Hz'; -const uint32 MSG_REF_30HZ = '30Hz'; -const uint32 MSG_REF_60HZ = '60Hz'; -const uint32 MSG_MOUNT = 'moun'; -const uint32 MSG_DEBUGGER = 'dbug'; - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_SCREEN -}; - -// From sys_beos.cpp -extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg); -extern void SysMountVolume(const char *name); - -// Global variables -static bool classic_mode = false; // Flag: Classic Mac video mode -static int scr_mode_bit = 0; -static vector VideoModes; // Supported video modes - - /* - * monitor_desc subclass for BeOS display - */ - -class BeOS_monitor_desc : public monitor_desc { -public: - BeOS_monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id) : monitor_desc(available_modes, default_depth, default_id) {} - ~BeOS_monitor_desc() {} - - virtual void switch_to_current_mode(void); - virtual void set_palette(uint8 *pal, int num); - - bool video_open(void); - void video_close(void); -}; - - -/* - * A simple view class for blitting a bitmap on the screen - */ - -class BitmapView : public BView { -public: - BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "bitmap", B_FOLLOW_NONE, B_WILL_DRAW) - { - the_bitmap = bitmap; - } - virtual void Draw(BRect update) - { - DrawBitmap(the_bitmap, update, update); - } - virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); - -private: - BBitmap *the_bitmap; -}; - - -/* - * Window class - */ - -class MacWindow : public BDirectWindow { -public: - MacWindow(BRect frame, const BeOS_monitor_desc& monitor); - virtual ~MacWindow(); - virtual void MessageReceived(BMessage *msg); - virtual void DirectConnected(direct_buffer_info *info); - virtual void WindowActivated(bool active); - - int32 frame_skip; - bool mouse_in_view; // Flag: Mouse pointer within bitmap view - uint8 remap_mac_be[256]; // For remapping of Mac colors to Be colors - -private: - static status_t tick_func(void *arg); - - thread_id tick_thread; - bool tick_thread_active; // Flag for quitting the tick thread - - BitmapView *main_view; // Main view for bitmap drawing - BBitmap *the_bitmap; // Mac screen bitmap - - uint32 old_scroll_lock_state; - - bool supports_direct_mode; // Flag: Direct frame buffer access supported - sem_id drawing_sem; - - void *bits; - int32 bytes_per_row; - color_space pixel_format; - bool unclipped; - - BeOS_monitor_desc monitor; -}; - - -/* - * Screen class - */ - -class MacScreen : public BWindowScreen { -public: - MacScreen(const BeOS_monitor_desc& monitor, const char *name, int mode_bit, status_t *error); - virtual ~MacScreen(); - virtual void Quit(void); - virtual void ScreenConnected(bool active); - - rgb_color palette[256]; // Color palette, 256 entries - bool palette_changed; - -private: - static status_t tick_func(void *arg); - - thread_id tick_thread; - bool tick_thread_active; // Flag for quitting the tick thread - - BView *main_view; // Main view for GetMouse() - uint8 *frame_backup; // Frame buffer backup when switching from/to different workspace - bool quitting; // Flag for ScreenConnected: We are quitting, don't pause emulator thread - bool screen_active; - bool first_time; - - BeOS_monitor_desc monitor; -}; - - -// Global variables -static int display_type = DISPLAY_WINDOW; // See enum above -static MacWindow *the_window = NULL; // Pointer to the window -static MacScreen *the_screen = NULL; // Pointer to the screen -static sem_id mac_os_lock = -1; // This is used to stop the MacOS thread when the Basilisk workspace is switched out -static uint8 MacCursor[68] = {16, 1}; // Mac cursor image - - -/* - * Initialization - */ - -// Add mode to list of supported modes -static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth) -{ - video_mode mode; - mode.x = width; - mode.y = height; - mode.resolution_id = resolution_id; - mode.bytes_per_row = bytes_per_row; - mode.depth = depth; - VideoModes.push_back(mode); -} - -// Add standard list of windowed modes for given color depth -static void add_window_modes(video_depth depth) -{ -#if 0 - add_mode(512, 384, 0x80, TrivialBytesPerRow(512, depth), depth); - add_mode(640, 480, 0x81, TrivialBytesPerRow(640, depth), depth); - add_mode(800, 600, 0x82, TrivialBytesPerRow(800, depth), depth); - add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, depth), depth); - add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, depth), depth); - add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, depth), depth); - add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, depth), depth); -#endif -} - - - -bool VideoInit(bool classic) -{ - classic_mode = classic; - - // Get screen mode from preferences - const char *mode_str; - if (classic_mode) - mode_str = "win/512/342"; - else - mode_str = PrefsFindString("screen"); - - // Determine type and mode - int default_width = 512, default_height = 384; - display_type = DISPLAY_WINDOW; - if (mode_str) { - if (sscanf(mode_str, "win/%d/%d", &default_width, &default_height) == 2) - display_type = DISPLAY_WINDOW; - else if (sscanf(mode_str, "scr/%d", &scr_mode_bit) == 1) - display_type = DISPLAY_SCREEN; - } -#if 0 - if (default_width <= 0) - default_width = DisplayWidth(x_display, screen); - else if (default_width > DisplayWidth(x_display, screen)) - default_width = DisplayWidth(x_display, screen); - if (default_height <= 0) - default_height = DisplayHeight(x_display, screen); - else if (default_height > DisplayHeight(x_display, screen)) - default_height = DisplayHeight(x_display, screen); -#endif - - // Mac screen depth follows BeOS depth - video_depth default_depth = VDEPTH_1BIT; - switch (BScreen().ColorSpace()) { - case B_CMAP8: - default_depth = VDEPTH_8BIT; - break; - case B_RGB15: - default_depth = VDEPTH_16BIT; - break; - case B_RGB32: - default_depth = VDEPTH_32BIT; - break; - default: - fprintf(stderr, "Unknown color space!"); - } - - // Construct list of supported modes - if (display_type == DISPLAY_WINDOW) { - if (classic) - add_mode(512, 342, 0x80, 64, VDEPTH_1BIT); - else { - add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth); -#if 0 - for (unsigned d=VDEPTH_1BIT; d<=VDEPTH_32BIT; d++) { - if (find_visual_for_depth(video_depth(d))) - add_window_modes(video_depth(d)); - } -#endif - } - } else - add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth); - if (VideoModes.empty()) { - ErrorAlert(STR_VIDEO_FAILED); - return false; - } - - // Find requested default mode with specified dimensions - uint32 default_id; - std::vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->x == default_width && i->y == default_height && i->depth == default_depth) { - default_id = i->resolution_id; - break; - } - } - if (i == end) { // not found, use first available mode - default_depth = VideoModes[0].depth; - default_id = VideoModes[0].resolution_id; - } - -#if DEBUG - D(bug("Available video modes:\n")); - for (i = VideoModes.begin(); i != end; ++i) { - int bits = 1 << i->depth; - if (bits == 16) - bits = 15; - else if (bits == 32) - bits = 24; - D(bug(" %dx%d (ID %02x), %d colors\n", i->x, i->y, i->resolution_id, 1 << bits)); - } -#endif - - // Create X11_monitor_desc for this (the only) display - BeOS_monitor_desc *monitor = new BeOS_monitor_desc(VideoModes, default_depth, default_id); - VideoMonitors.push_back(monitor); - - // Open display - return monitor->video_open(); -} - -bool BeOS_monitor_desc::video_open() { - // Create semaphore - mac_os_lock = create_sem(0, "MacOS Frame Buffer Lock"); - - const video_mode &mode = get_current_mode(); - - // Open display - switch (display_type) { - case DISPLAY_WINDOW: - the_window = new MacWindow(BRect(0, 0, mode.x-1, mode.y-1), *this); - break; - case DISPLAY_SCREEN: { - status_t screen_error; - the_screen = new MacScreen(*this, GetString(STR_WINDOW_TITLE), scr_mode_bit & 0x1f, &screen_error); - if (screen_error != B_NO_ERROR) { - the_screen->PostMessage(B_QUIT_REQUESTED); - while (the_screen) - snooze(200000); - ErrorAlert(STR_OPEN_SCREEN_ERR); - return false; - } else { - the_screen->Show(); - acquire_sem(mac_os_lock); - } - break; - } - } - return true; -} - - -/* - * Deinitialization - */ - -void VideoExit(void) -{ - // Close display - switch (display_type) { - case DISPLAY_WINDOW: - if (the_window != NULL) { - the_window->PostMessage(B_QUIT_REQUESTED); - while (the_window) - snooze(200000); - } - break; - case DISPLAY_SCREEN: - if (the_screen != NULL) { - the_screen->PostMessage(B_QUIT_REQUESTED); - while (the_screen) - snooze(200000); - } - break; - } - - // Delete semaphore - delete_sem(mac_os_lock); -} - - -/* - * Set palette - */ - -void BeOS_monitor_desc::set_palette(uint8 *pal, int num) -{ - switch (display_type) { - case DISPLAY_WINDOW: { - BScreen screen(the_window); - for (int i=0; i<256; i++) - the_window->remap_mac_be[i] = screen.IndexForColor(pal[i*3], pal[i*3+1], pal[i*3+2]); - break; - } - case DISPLAY_SCREEN: - for (int i=0; i<256; i++) { - the_screen->palette[i].red = pal[i*3]; - the_screen->palette[i].green = pal[i*3+1]; - the_screen->palette[i].blue = pal[i*3+2]; - } - the_screen->palette_changed = true; - break; - } -} - - -/* - * Switch video mode - */ - -void BeOS_monitor_desc::switch_to_current_mode() -{ -} - - -/* - * Close down full-screen mode (if bringing up error alerts is unsafe while in full-screen mode) - */ - -void VideoQuitFullScreen(void) -{ - D(bug("VideoQuitFullScreen()\n")); - if (display_type == DISPLAY_SCREEN) { - if (the_screen != NULL) { - the_screen->PostMessage(B_QUIT_REQUESTED); - while (the_screen) - snooze(200000); - } - } -} - - -/* - * Video event handling (not neccessary under BeOS, handled by filter function) - */ - -void VideoInterrupt(void) -{ - release_sem(mac_os_lock); - while (acquire_sem(mac_os_lock) == B_INTERRUPTED) ; -} - - -/* - * Filter function for receiving mouse and keyboard events - */ - -#define MENU_IS_POWER 0 - -// Be -> Mac raw keycode translation table -static const uint8 keycode2mac[0x80] = { - 0xff, 0x35, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, // inv Esc F1 F2 F3 F4 F5 F6 - 0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b, // F7 F8 F9 F10 F11 F12 F13 F14 - 0x71, 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, // F15 ` 1 2 3 4 5 6 - 0x1a, 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x33, 0x72, // 7 8 9 0 - = BSP INS - 0x73, 0x74, 0x47, 0x4b, 0x43, 0x4e, 0x30, 0x0c, // HOM PUP NUM / * - TAB Q - 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, 0x1f, // W E R T Y U I O - 0x23, 0x21, 0x1e, 0x2a, 0x75, 0x77, 0x79, 0x59, // P [ ] \ DEL END PDN 7 - 0x5b, 0x5c, 0x45, 0x39, 0x00, 0x01, 0x02, 0x03, // 8 9 + CAP A S D F - 0x05, 0x04, 0x26, 0x28, 0x25, 0x29, 0x27, 0x24, // G H J K L ; ' RET - 0x56, 0x57, 0x58, 0x38, 0x06, 0x07, 0x08, 0x09, // 4 5 6 SHL Z X C V - 0x0b, 0x2d, 0x2e, 0x2b, 0x2f, 0x2c, 0x38, 0x3e, // B N M , . / SHR CUP - 0x53, 0x54, 0x55, 0x4c, 0x36, 0x37, 0x31, 0x37, // 1 2 3 ENT CTL ALT SPC ALT - 0x36, 0x3b, 0x3d, 0x3c, 0x52, 0x41, 0x3a, 0x3a, // CTR CLF CDN CRT 0 . CMD CMD -#if MENU_IS_POWER - 0x7f, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv -#else - 0x32, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv -#endif - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv -}; - -static const uint8 modifier2mac[0x20] = { -#if MENU_IS_POWER - 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x7f, // SHF CMD inv CAP F14 NUM OPT MNU -#else - 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x32, // SHF CMD CTR CAP F14 NUM OPT MNU -#endif - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv -}; - -static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter) -{ - switch (msg->what) { - case B_KEY_DOWN: - case B_KEY_UP: { - uint32 be_code = msg->FindInt32("key") & 0xff; - uint32 mac_code = keycode2mac[be_code]; - - // Intercept Ctrl-F1 (mount floppy disk shortcut) - uint32 mods = msg->FindInt32("modifiers"); - if (be_code == 0x02 && (mods & B_CONTROL_KEY)) - SysMountVolume("/dev/disk/floppy/raw"); - - if (mac_code == 0xff) - return B_DISPATCH_MESSAGE; - if (msg->what == B_KEY_DOWN) - ADBKeyDown(mac_code); - else - ADBKeyUp(mac_code); - return B_SKIP_MESSAGE; - } - - case B_MODIFIERS_CHANGED: { - uint32 mods = msg->FindInt32("modifiers"); - uint32 old_mods = msg->FindInt32("be:old_modifiers"); - uint32 changed = mods ^ old_mods; - uint32 mask = 1; - for (int i=0; i<32; i++, mask<<=1) - if (changed & mask) { - uint32 mac_code = modifier2mac[i]; - if (mac_code == 0xff) - continue; - if (mods & mask) - ADBKeyDown(mac_code); - else - ADBKeyUp(mac_code); - } - return B_SKIP_MESSAGE; - } - - case B_MOUSE_MOVED: { - BPoint point; - msg->FindPoint("where", &point); - ADBMouseMoved(int(point.x), int(point.y)); - return B_DISPATCH_MESSAGE; // Otherwise BitmapView::MouseMoved() wouldn't be called - } - - case B_MOUSE_DOWN: { - uint32 buttons = msg->FindInt32("buttons"); - if (buttons & B_PRIMARY_MOUSE_BUTTON) - ADBMouseDown(0); - if (buttons & B_SECONDARY_MOUSE_BUTTON) - ADBMouseDown(1); - if (buttons & B_TERTIARY_MOUSE_BUTTON) - ADBMouseDown(2); - return B_SKIP_MESSAGE; - } - - case B_MOUSE_UP: // B_MOUSE_UP means "all buttons released" - ADBMouseUp(0); - ADBMouseUp(1); - ADBMouseUp(2); - return B_SKIP_MESSAGE; - - default: - return B_DISPATCH_MESSAGE; - } -} - - -/* - * Window constructor - */ - -MacWindow::MacWindow(BRect frame, const BeOS_monitor_desc& monitor) - : BDirectWindow(frame, GetString(STR_WINDOW_TITLE), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE) - , monitor(monitor) -{ - supports_direct_mode = SupportsWindowMode(); - - // Move window to right position - Lock(); - MoveTo(80, 60); - - // Allocate bitmap and Mac frame buffer - uint32 x = frame.IntegerWidth() + 1; - uint32 y = frame.IntegerHeight() + 1; - int fbsize = x * y; - const video_mode &mode = monitor.get_current_mode(); - switch (mode.depth) { - case VDEPTH_1BIT: - fprintf(stderr, "1BIT SCREEN CREATED"); - the_bitmap = new BBitmap(frame, B_GRAY1); - fbsize /= 8; - break; - case VDEPTH_8BIT: - fprintf(stderr, "8BIT SCREEN CREATED"); - the_bitmap = new BBitmap(frame, B_CMAP8); - break; - case VDEPTH_32BIT: - fprintf(stderr, "32BIT SCREEN CREATED"); - the_bitmap = new BBitmap(frame, B_RGB32_BIG); - fbsize *= 4; - break; - default: - fprintf(stderr, "width: %d", 1 << mode.depth); - debugger("OOPS"); - } - -#if REAL_ADDRESSING - monitor.set_mac_frame_base((uint32)the_bitmap->Bits()); -#else - monitor.set_mac_frame_base(MacFrameBaseMac); -#endif - -#if !REAL_ADDRESSING - // Set variables for UAE memory mapping - MacFrameBaseHost = (uint8*)the_bitmap->Bits(); - MacFrameSize = fbsize; - MacFrameLayout = FLAYOUT_DIRECT; -#endif - - // Create bitmap view - main_view = new BitmapView(frame, the_bitmap); - AddChild(main_view); - main_view->MakeFocus(); - - // Read frame skip prefs - frame_skip = PrefsFindInt32("frameskip"); - if (frame_skip == 0) - frame_skip = 1; - - // Set up menus - BRect bounds = Bounds(); - bounds.OffsetBy(0, bounds.IntegerHeight() + 1); - BMenuItem *item; - BMenuBar *bar = new BMenuBar(bounds, "menu"); - BMenu *menu = new BMenu(GetString(STR_WINDOW_MENU)); - menu->AddItem(new BMenuItem(GetString(STR_WINDOW_ITEM_ABOUT), new BMessage(MSG_ABOUT_REQUESTED))); - menu->AddItem(new BSeparatorItem); - BMenu *submenu = new BMenu(GetString(STR_WINDOW_ITEM_REFRESH)); - submenu->AddItem(new BMenuItem(GetString(STR_REF_5HZ_LAB), new BMessage(MSG_REF_5HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_7_5HZ_LAB), new BMessage(MSG_REF_7_5HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_10HZ_LAB), new BMessage(MSG_REF_10HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_15HZ_LAB), new BMessage(MSG_REF_15HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_30HZ_LAB), new BMessage(MSG_REF_30HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_60HZ_LAB), new BMessage(MSG_REF_60HZ))); - submenu->SetRadioMode(true); - if (frame_skip == 12) { - if ((item = submenu->FindItem(GetString(STR_REF_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 8) { - if ((item = submenu->FindItem(GetString(STR_REF_7_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 6) { - if ((item = submenu->FindItem(GetString(STR_REF_10HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 4) { - if ((item = submenu->FindItem(GetString(STR_REF_15HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 2) { - if ((item = submenu->FindItem(GetString(STR_REF_30HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 1) { - if ((item = submenu->FindItem(GetString(STR_REF_60HZ_LAB))) != NULL) - item->SetMarked(true); - } - menu->AddItem(submenu); - submenu = new BMenu(GetString(STR_WINDOW_ITEM_MOUNT)); - SysCreateVolumeMenu(submenu, MSG_MOUNT); - menu->AddItem(submenu); -#if DEBUGGER_AVAILABLE - menu->AddItem(new BMenuItem("Debugger", new BMessage(MSG_DEBUGGER))); -#endif - bar->AddItem(menu); - AddChild(bar); - SetKeyMenuBar(bar); - int mbar_height = bar->Frame().IntegerHeight() + 1; - - // Resize window to fit menu bar - ResizeBy(0, mbar_height); - - // Set absolute mouse mode and get scroll lock state - ADBSetRelMouseMode(false); - mouse_in_view = true; - old_scroll_lock_state = modifiers() & B_SCROLL_LOCK; - if (old_scroll_lock_state) - SetTitle(GetString(STR_WINDOW_TITLE_FROZEN)); - else - SetTitle(GetString(STR_WINDOW_TITLE)); - - // Keep window aligned to 8-byte frame buffer boundaries for faster blitting - SetWindowAlignment(B_BYTE_ALIGNMENT, 8); - - // Create drawing semaphore (for direct mode) - drawing_sem = create_sem(0, "direct frame buffer access"); - - // Start 60Hz interrupt - tick_thread_active = true; - tick_thread = spawn_thread(tick_func, "Window Redraw", B_DISPLAY_PRIORITY, this); - resume_thread(tick_thread); - - // Add filter for keyboard and mouse events - BMessageFilter *filter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, filter_func); - main_view->AddFilter(filter); - - // Show window - Unlock(); - Show(); - Sync(); -} - - -/* - * Window destructor - */ - -MacWindow::~MacWindow() -{ - // Restore cursor - mouse_in_view = false; - be_app->SetCursor(B_HAND_CURSOR); - - // Hide window - Hide(); - Sync(); - - // Stop 60Hz interrupt - status_t l; - tick_thread_active = false; - delete_sem(drawing_sem); - wait_for_thread(tick_thread, &l); - - // Free bitmap and frame buffer - delete the_bitmap; - - // Tell emulator that we're done - the_window = NULL; -} - - -/* - * Window connected/disconnected - */ - -void MacWindow::DirectConnected(direct_buffer_info *info) -{ - switch (info->buffer_state & B_DIRECT_MODE_MASK) { - case B_DIRECT_STOP: - acquire_sem(drawing_sem); - break; - case B_DIRECT_MODIFY: - acquire_sem(drawing_sem); - case B_DIRECT_START: - bits = (void *)((uint8 *)info->bits + info->window_bounds.top * info->bytes_per_row + info->window_bounds.left * info->bits_per_pixel / 8); - bytes_per_row = info->bytes_per_row; - pixel_format = info->pixel_format; - unclipped = false; - if (info->clip_list_count == 1) - if (memcmp(&info->clip_bounds, &info->window_bounds, sizeof(clipping_rect)) == 0) - unclipped = true; - release_sem(drawing_sem); - break; - } -} - - -/* - * Handle redraw and menu messages - */ - -void MacWindow::MessageReceived(BMessage *msg) -{ - BMessage *msg2; - - switch (msg->what) { - case MSG_REDRAW: { - - // Prevent backlog of messages - MessageQueue()->Lock(); - while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) { - MessageQueue()->RemoveMessage(msg2); - delete msg2; - } - MessageQueue()->Unlock(); - - // Convert Mac screen buffer to BeOS palette and blit - const video_mode &mode = monitor.get_current_mode(); - BRect update_rect = BRect(0, 0, mode.x-1, mode.y-1); - main_view->DrawBitmapAsync(the_bitmap, update_rect, update_rect); - break; - } - - case MSG_ABOUT_REQUESTED: { - ShowAboutWindow(); - break; - } - - case MSG_REF_5HZ: - PrefsReplaceInt32("frameskip", frame_skip = 12); - break; - - case MSG_REF_7_5HZ: - PrefsReplaceInt32("frameskip", frame_skip = 8); - break; - - case MSG_REF_10HZ: - PrefsReplaceInt32("frameskip", frame_skip = 6); - break; - - case MSG_REF_15HZ: - PrefsReplaceInt32("frameskip", frame_skip = 4); - break; - - case MSG_REF_30HZ: - PrefsReplaceInt32("frameskip", frame_skip = 2); - break; - - case MSG_REF_60HZ: - PrefsReplaceInt32("frameskip", frame_skip = 1); - break; - - case MSG_MOUNT: { - BMenuItem *source = NULL; - msg->FindPointer("source", (void **)&source); - if (source) - SysMountVolume(source->Label()); - break; - } - -#if DEBUGGER_AVAILABLE - case MSG_DEBUGGER: - extern int debugging; - debugging = 1; - regs.spcflags |= SPCFLAG_BRK; - break; -#endif - - default: - BDirectWindow::MessageReceived(msg); - } -} - - -/* - * Window activated/deactivated - */ - -void MacWindow::WindowActivated(bool active) -{ - if (active) { - frame_skip = PrefsFindInt32("frameskip"); - if (frame_skip == 0) - frame_skip = 1; - } else - frame_skip = 12; // 5Hz in background -} - - -/* - * 60Hz interrupt routine - */ - -status_t MacWindow::tick_func(void *arg) -{ - MacWindow *obj = (MacWindow *)arg; - static int tick_counter = 0; - while (obj->tick_thread_active) { - - tick_counter++; - if (tick_counter >= obj->frame_skip) { - tick_counter = 0; - - // Window title is determined by Scroll Lock state - uint32 scroll_lock_state = modifiers() & B_SCROLL_LOCK; - if (scroll_lock_state != obj->old_scroll_lock_state) { - if (scroll_lock_state) - obj->SetTitle(GetString(STR_WINDOW_TITLE_FROZEN)); - else - obj->SetTitle(GetString(STR_WINDOW_TITLE)); - obj->old_scroll_lock_state = scroll_lock_state; - } - - // Has the Mac started? - if (HasMacStarted()) { - - // Yes, set new cursor image if it was changed - if (memcmp(MacCursor+4, Mac2HostAddr(0x844), 64)) { - Mac2Host_memcpy(MacCursor+4, 0x844, 64); // Cursor image - MacCursor[2] = ReadMacInt8(0x885); // Hotspot - MacCursor[3] = ReadMacInt8(0x887); - be_app->SetCursor(MacCursor); - } - } - - // Refresh screen unless Scroll Lock is down - if (!scroll_lock_state) { - obj->PostMessage(MSG_REDRAW); - } - } - snooze(16666); - } - return 0; -} - - -/* - * Mouse moved in window - */ - -void BitmapView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) -{ - switch (transit) { - case B_ENTERED_VIEW: - ((MacWindow *)Window())->mouse_in_view = true; - be_app->SetCursor(MacCursor); - break; - case B_EXITED_VIEW: - ((MacWindow *)Window())->mouse_in_view = false; - be_app->SetCursor(B_HAND_CURSOR); - break; - } -} - - -/* - * Screen constructor - */ - -MacScreen::MacScreen(const BeOS_monitor_desc& monitor, const char *name, int mode_bit, status_t *error) - : BWindowScreen(name, 1 << mode_bit, error), tick_thread(-1) - , monitor(monitor) -{ - // Set all variables - frame_backup = NULL; - palette_changed = false; - screen_active = false; - first_time = true; - quitting = false; - - // Set relative mouse mode - ADBSetRelMouseMode(true); - - // Create view to get mouse events - main_view = new BView(Frame(), NULL, B_FOLLOW_NONE, 0); - AddChild(main_view); - - // Start 60Hz interrupt - tick_thread_active = true; - tick_thread = spawn_thread(tick_func, "Polling sucks...", B_DISPLAY_PRIORITY, this); - resume_thread(tick_thread); - - // Add filter for keyboard and mouse events - BMessageFilter *filter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, filter_func); - AddCommonFilter(filter); -} - - -/* - * Screen destructor - */ - -MacScreen::~MacScreen() -{ - // Stop 60Hz interrupt - if (tick_thread > 0) { - status_t l; - tick_thread_active = false; - wait_for_thread(tick_thread, &l); - } - - // Tell emulator that we're done - the_screen = NULL; -} - - -/* - * Screen closed - */ - -void MacScreen::Quit(void) -{ - // Tell ScreenConnected() that we are quitting - quitting = true; - BWindowScreen::Quit(); -} - - -/* - * Screen connected/disconnected - */ - -void MacScreen::ScreenConnected(bool active) -{ - graphics_card_info *info = CardInfo(); - screen_active = active; - const video_mode &mode = monitor.get_current_mode(); - - if (active == true) { - - // Set VideoMonitor -#if REAL_ADDRESSING - monitor.set_mac_frame_base((uint32)info->frame_buffer); -#else - monitor.set_mac_frame_base(MacFrameBaseMac); -#endif - -#if !REAL_ADDRESSING - // Set variables for UAE memory mapping - MacFrameBaseHost = (uint8 *)info->frame_buffer; - MacFrameSize = mode.bytes_per_row * mode.y; - switch (info->bits_per_pixel) { - case 15: - MacFrameLayout = FLAYOUT_HOST_555; - break; - case 16: - MacFrameLayout = FLAYOUT_HOST_565; - break; - case 32: - MacFrameLayout = FLAYOUT_HOST_888; - break; - default: - MacFrameLayout = FLAYOUT_DIRECT; - break; - } -#endif - - // Copy from backup store to frame buffer - if (frame_backup != NULL) { - memcpy(info->frame_buffer, frame_backup, mode.bytes_per_row * mode.y); - delete[] frame_backup; - frame_backup = NULL; - } - - // Restore palette - if (mode.depth == VDEPTH_8BIT) - SetColorList(palette); - - // Restart/signal emulator thread - release_sem(mac_os_lock); - - } else { - - if (!quitting) { - - // Stop emulator thread - acquire_sem(mac_os_lock); - - // Create backup store and save frame buffer - frame_backup = new uint8[mode.bytes_per_row * mode.y]; - memcpy(frame_backup, info->frame_buffer, mode.bytes_per_row * mode.y); - } - } -} - - -/* - * Screen 60Hz interrupt routine - */ - -status_t MacScreen::tick_func(void *arg) -{ - MacScreen *obj = (MacScreen *)arg; - while (obj->tick_thread_active) { - - // Wait - snooze(16667); - - // Workspace activated? Then poll the mouse and set the palette if needed - if (!obj->quitting && obj->LockWithTimeout(200000) == B_OK) { - if (obj->screen_active) { - BPoint pt; - uint32 button = 0; - if (obj->palette_changed) { - obj->palette_changed = false; - obj->SetColorList(obj->palette); - } - obj->main_view->GetMouse(&pt, &button); - set_mouse_position(320, 240); - ADBMouseMoved(int(pt.x) - 320, int(pt.y) - 240); - if (button & B_PRIMARY_MOUSE_BUTTON) - ADBMouseDown(0); - if (!(button & B_PRIMARY_MOUSE_BUTTON)) - ADBMouseUp(0); - if (button & B_SECONDARY_MOUSE_BUTTON) - ADBMouseDown(1); - if (!(button & B_SECONDARY_MOUSE_BUTTON)) - ADBMouseUp(1); - if (button & B_TERTIARY_MOUSE_BUTTON) - ADBMouseDown(2); - if (!(button & B_TERTIARY_MOUSE_BUTTON)) - ADBMouseUp(2); - } - obj->Unlock(); - } - } - return 0; -} diff --git a/BasiliskII/src/BeOS/xpram_beos.cpp b/BasiliskII/src/BeOS/xpram_beos.cpp deleted file mode 100644 index 8ee250a4..00000000 --- a/BasiliskII/src/BeOS/xpram_beos.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * xpram_beos.cpp - XPRAM handling, BeOS specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "sysdeps.h" -#include "xpram.h" - - -// XPRAM file name and path -#if POWERPC_ROM -const char XPRAM_FILE_NAME[] = "SheepShaver_NVRAM"; -#else -const char XPRAM_FILE_NAME[] = "BasiliskII_XPRAM"; -#endif -static BPath xpram_path; - - -/* - * Load XPRAM from settings file - */ - -void LoadXPRAM(const char *vmdir) -{ - // Construct XPRAM path - find_directory(B_USER_SETTINGS_DIRECTORY, &xpram_path, true); - xpram_path.Append(XPRAM_FILE_NAME); - - // Load XPRAM from settings file - int fd; - if ((fd = open(xpram_path.Path(), O_RDONLY)) >= 0) { - read(fd, XPRAM, XPRAM_SIZE); - close(fd); - } -} - - -/* - * Save XPRAM to settings file - */ - -void SaveXPRAM(void) -{ - if (xpram_path.InitCheck() != B_NO_ERROR) - return; - int fd; - if ((fd = open(xpram_path.Path(), O_WRONLY | O_CREAT, 0666)) >= 0) { - write(fd, XPRAM, XPRAM_SIZE); - close(fd); - } -} - - -/* - * Delete PRAM file - */ - -void ZapPRAM(void) -{ - // Construct PRAM path - find_directory(B_USER_SETTINGS_DIRECTORY, &xpram_path, true); - xpram_path.Append(XPRAM_FILE_NAME); - - // Delete file - unlink(xpram_path.Path()); -} diff --git a/BasiliskII/src/CrossPlatform/sigsegv.cpp b/BasiliskII/src/CrossPlatform/sigsegv.cpp index 570058c2..41a5d04e 100644 --- a/BasiliskII/src/CrossPlatform/sigsegv.cpp +++ b/BasiliskII/src/CrossPlatform/sigsegv.cpp @@ -53,14 +53,8 @@ using std::list; // Size of an unsigned integer large enough to hold all bits of a pointer // NOTE: this can be different than SIGSEGV_REGISTER_TYPE. In // particular, on ILP32 systems with a 64-bit kernel (HP-UX/ia64?) -#if defined(HAVE_WIN32_VM) -// Windows is either ILP32 or LLP64 -#include -typedef UINT_PTR sigsegv_uintptr_t; -#else // Other systems are sane enough to follow ILP32 or LP64 models typedef unsigned long sigsegv_uintptr_t; -#endif // Type of the system signal handler typedef RETSIGTYPE (*signal_handler)(int); @@ -96,507 +90,19 @@ enum transfer_size_t { SIZE_QUAD // 8 bytes }; -#if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)) -// Addressing mode -enum addressing_mode_t { - MODE_UNKNOWN, - MODE_NORM, - MODE_U, - MODE_X, - MODE_UX -}; - -// Decoded instruction -struct instruction_t { - transfer_type_t transfer_type; - transfer_size_t transfer_size; - addressing_mode_t addr_mode; - unsigned int addr; - char ra, rd; -}; - -static void powerpc_decode_instruction(instruction_t *instruction, unsigned int nip, unsigned long * gpr) -{ - // Get opcode and divide into fields - unsigned int opcode = *((unsigned int *)(unsigned long)nip); - unsigned int primop = opcode >> 26; - unsigned int exop = (opcode >> 1) & 0x3ff; - unsigned int ra = (opcode >> 16) & 0x1f; - unsigned int rb = (opcode >> 11) & 0x1f; - unsigned int rd = (opcode >> 21) & 0x1f; - signed int imm = (signed short)(opcode & 0xffff); - - // Analyze opcode - transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN; - transfer_size_t transfer_size = SIZE_UNKNOWN; - addressing_mode_t addr_mode = MODE_UNKNOWN; - switch (primop) { - case 31: - switch (exop) { - case 23: // lwzx - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_X; break; - case 55: // lwzux - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break; - case 87: // lbzx - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 119: // lbzux - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 151: // stwx - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_X; break; - case 183: // stwux - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_UX; break; - case 215: // stbx - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 247: // stbux - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 279: // lhzx - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 311: // lhzux - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 343: // lhax - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 375: // lhaux - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 407: // sthx - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 439: // sthux - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - } - break; - - case 32: // lwz - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break; - case 33: // lwzu - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_LONG; addr_mode = MODE_U; break; - case 34: // lbz - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 35: // lbzu - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 36: // stw - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_NORM; break; - case 37: // stwu - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_LONG; addr_mode = MODE_U; break; - case 38: // stb - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 39: // stbu - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 40: // lhz - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 41: // lhzu - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 42: // lha - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 43: // lhau - transfer_type = SIGSEGV_TRANSFER_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 44: // sth - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 45: // sthu - transfer_type = SIGSEGV_TRANSFER_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 58: // ld, ldu, lwa - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_QUAD; - addr_mode = ((opcode & 3) == 1) ? MODE_U : MODE_NORM; - imm &= ~3; - break; - case 62: // std, stdu, stq - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_QUAD; - addr_mode = ((opcode & 3) == 1) ? MODE_U : MODE_NORM; - imm &= ~3; - break; - } - - // Calculate effective address - unsigned int addr = 0; - switch (addr_mode) { - case MODE_X: - case MODE_UX: - if (ra == 0) - addr = gpr[rb]; - else - addr = gpr[ra] + gpr[rb]; - break; - case MODE_NORM: - case MODE_U: - if (ra == 0) - addr = (signed int)(signed short)imm; - else - addr = gpr[ra] + (signed int)(signed short)imm; - break; - default: - break; - } - - // Commit decoded instruction - instruction->addr = addr; - instruction->addr_mode = addr_mode; - instruction->transfer_type = transfer_type; - instruction->transfer_size = transfer_size; - instruction->ra = ra; - instruction->rd = rd; -} -#endif - - /* * OS-dependant SIGSEGV signals support section */ #if HAVE_SIGINFO_T // Generic extended signal handler -#if defined(__hpux) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) FAULT_HANDLER(SIGBUS) -#else -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#endif + #define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, siginfo_t *sip, void *scp #define SIGSEGV_FAULT_HANDLER_ARGLIST_1 siginfo_t *sip, void *scp #define SIGSEGV_FAULT_HANDLER_ARGS sip, scp #define SIGSEGV_FAULT_ADDRESS sip->si_addr -#if (defined(sgi) || defined(__sgi)) -#include -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs) -#define SIGSEGV_FAULT_INSTRUCTION (unsigned long)SIGSEGV_CONTEXT_REGS[CTX_EPC] -#if (defined(mips) || defined(__mips)) -#define SIGSEGV_REGISTER_FILE &SIGSEGV_CONTEXT_REGS[CTX_EPC], &SIGSEGV_CONTEXT_REGS[CTX_R0] -#define SIGSEGV_SKIP_INSTRUCTION mips_skip_instruction -#endif -#endif -#if defined(__sun__) -#if (defined(sparc) || defined(__sparc__)) -#include -#include -#include -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[REG_PC] -#define SIGSEGV_SPARC_GWINDOWS (((ucontext_t *)scp)->uc_mcontext.gwins) -#define SIGSEGV_SPARC_RWINDOW (struct rwindow *)((char *)SIGSEGV_CONTEXT_REGS[REG_SP] + STACK_BIAS) -#define SIGSEGV_REGISTER_FILE ((unsigned long *)SIGSEGV_CONTEXT_REGS), SIGSEGV_SPARC_GWINDOWS, SIGSEGV_SPARC_RWINDOW -#define SIGSEGV_SKIP_INSTRUCTION sparc_skip_instruction -#endif -#if defined(__i386__) -#include -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[EIP] -#define SIGSEGV_REGISTER_FILE (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) -#if (defined(i386) || defined(__i386__)) -#undef SIGSEGV_ALL_SIGNALS -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) -#define SIGSEGV_FAULT_INSTRUCTION (((struct sigcontext *)scp)->sc_eip) -#define SIGSEGV_REGISTER_FILE ((SIGSEGV_REGISTER_TYPE *)&(((struct sigcontext *)scp)->sc_edi)) /* EDI is the first GPR (even below EIP) in sigcontext */ -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#elif (defined(x86_64) || defined(__x86_64__)) -#define SIGSEGV_FAULT_INSTRUCTION (((struct sigcontext *)scp)->sc_rip) -#define SIGSEGV_REGISTER_FILE ((SIGSEGV_REGISTER_TYPE *)&(((struct sigcontext *)scp)->sc_rdi)) -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#endif -#if defined(__NetBSD__) -#if (defined(i386) || defined(__i386__)) -#include -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.__gregs) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[_REG_EIP] -#define SIGSEGV_REGISTER_FILE (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#if (defined(powerpc) || defined(__powerpc__)) -#include -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.__gregs) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[_REG_PC] -#define SIGSEGV_REGISTER_FILE (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_PC], (unsigned long *)&SIGSEGV_CONTEXT_REGS[_REG_R0] -#define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction -#endif -#endif -#if defined(__linux__) -#if HAVE_ASM_UCONTEXT -#include /* use kernel structure, glibc may not be in sync */ -#else -#include -#endif -#if (defined(hppa) || defined(__hppa__)) -#undef SIGSEGV_FAULT_ADDRESS -#define SIGSEGV_FAULT_ADDRESS sip->si_ptr -#endif -#if (defined(i386) || defined(__i386__)) -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[14] /* should use REG_EIP instead */ -#define SIGSEGV_REGISTER_FILE (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#elif (defined(x86_64) || defined(__x86_64__)) -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.gregs) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS[16] /* should use REG_RIP instead */ -#define SIGSEGV_REGISTER_FILE (SIGSEGV_REGISTER_TYPE *)SIGSEGV_CONTEXT_REGS -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#elif (defined(ia64) || defined(__ia64__)) -#define SIGSEGV_CONTEXT_REGS ((struct sigcontext *)scp) -#define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */ -#define SIGSEGV_REGISTER_FILE SIGSEGV_CONTEXT_REGS -#define SIGSEGV_SKIP_INSTRUCTION ia64_skip_instruction -#elif (defined(powerpc) || defined(__powerpc__)) -#define SIGSEGV_CONTEXT_REGS (((ucontext_t *)scp)->uc_mcontext.regs) -#define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->nip) -#define SIGSEGV_REGISTER_FILE (unsigned long *)&SIGSEGV_CONTEXT_REGS->nip, (unsigned long *)(SIGSEGV_CONTEXT_REGS->gpr) -#define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction -#elif (defined(arm) || defined(__arm__)) -#define SIGSEGV_CONTEXT_REGS (((struct ucontext *)scp)->uc_mcontext) -#define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS.arm_pc) -#define SIGSEGV_REGISTER_FILE (&SIGSEGV_CONTEXT_REGS.arm_r0) -#define SIGSEGV_SKIP_INSTRUCTION arm_skip_instruction -#elif (defined(mips) || defined(__mips__)) -#define SIGSEGV_CONTEXT_REGS (((struct ucontext *)scp)->uc_mcontext) -#define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS.pc) -#define SIGSEGV_REGISTER_FILE &SIGSEGV_CONTEXT_REGS.pc, &SIGSEGV_CONTEXT_REGS.gregs[0] -#define SIGSEGV_SKIP_INSTRUCTION mips_skip_instruction -#endif -#endif // defined(__linux__) -#if (defined(__hpux) || defined(__hpux__)) -#if (defined(__hppa) || defined(__hppa__)) -#define SIGSEGV_CONTEXT_REGS (&((ucontext_t *)scp)->uc_mcontext) -#define SIGSEGV_FAULT_INSTRUCTION_32 (SIGSEGV_CONTEXT_REGS->ss_narrow.ss_pcoq_head & ~3ul) -#define SIGSEGV_FAULT_INSTRUCTION_64 (SIGSEGV_CONTEXT_REGS->ss_wide.ss_64.ss_pcoq_head & ~3ull) -#if defined(__LP64__) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_FAULT_INSTRUCTION_64 -#else -#define SIGSEGV_FAULT_INSTRUCTION ((SIGSEGV_CONTEXT_REGS->ss_flags & SS_WIDEREGS) ? \ - (uint32_t)SIGSEGV_FAULT_INSTRUCTION_64 : \ - SIGSEGV_FAULT_INSTRUCTION_32) -#endif -#endif -#if (defined(__ia64) || defined(__ia64__)) -#include -#define SIGSEGV_CONTEXT_REGS ((ucontext_t *)scp) -#define SIGSEGV_FAULT_INSTRUCTION get_fault_instruction(SIGSEGV_CONTEXT_REGS) -#define SIGSEGV_REGISTER_FILE SIGSEGV_CONTEXT_REGS -#define SIGSEGV_SKIP_INSTRUCTION ia64_skip_instruction - -#include -static inline sigsegv_address_t get_fault_instruction(const ucontext_t *ucp) -{ - uint64_t ip; - if (__uc_get_ip(ucp, &ip) != 0) - return SIGSEGV_INVALID_ADDRESS; - return (sigsegv_address_t)(ip & ~3ULL); -} -#endif -#endif -#endif - -#if HAVE_SIGCONTEXT_SUBTERFUGE -// Linux kernels prior to 2.4 ? -#if defined(__linux__) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#if (defined(i386) || defined(__i386__)) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext scs -#define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS &scs -#define SIGSEGV_FAULT_ADDRESS scp->cr2 -#define SIGSEGV_FAULT_INSTRUCTION scp->eip -#define SIGSEGV_REGISTER_FILE (SIGSEGV_REGISTER_TYPE *)scp -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#if (defined(sparc) || defined(__sparc__)) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr -#define SIGSEGV_FAULT_ADDRESS addr -#endif -#if (defined(powerpc) || defined(__powerpc__)) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, scp -#define SIGSEGV_FAULT_ADDRESS scp->regs->dar -#define SIGSEGV_FAULT_INSTRUCTION scp->regs->nip -#define SIGSEGV_REGISTER_FILE (unsigned long *)&scp->regs->nip, (unsigned long *)(scp->regs->gpr) -#define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction -#endif -#if (defined(alpha) || defined(__alpha__)) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp) -#define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc -#endif -#if (defined(arm) || defined(__arm__)) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int r1, int r2, int r3, struct sigcontext sc -#define SIGSEGV_FAULT_HANDLER_ARGLIST_1 struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS &sc -#define SIGSEGV_FAULT_ADDRESS scp->fault_address -#define SIGSEGV_FAULT_INSTRUCTION scp->arm_pc -#define SIGSEGV_REGISTER_FILE &scp->arm_r0 -#define SIGSEGV_SKIP_INSTRUCTION arm_skip_instruction -#endif -#endif - -// Irix 5 or 6 on MIPS -#if (defined(sgi) || defined(__sgi)) && (defined(SYSTYPE_SVR4) || defined(_SYSTYPE_SVR4)) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS (unsigned long)scp->sc_badvaddr -#define SIGSEGV_FAULT_INSTRUCTION (unsigned long)scp->sc_pc -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#endif - -// HP-UX -#if (defined(hpux) || defined(__hpux__)) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS scp->sc_sl.sl_ss.ss_narrow.ss_cr21 -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) FAULT_HANDLER(SIGBUS) -#endif - -// OSF/1 on Alpha -#if defined(__osf__) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS scp->sc_traparg_a0 -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#endif - -// AIX -#if defined(_AIX) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS scp->sc_jmpbuf.jmp_context.o_vaddr -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#endif - -// NetBSD -#if defined(__NetBSD__) -#if (defined(m68k) || defined(__m68k__)) -#include -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) - -// Use decoding scheme from BasiliskII/m68k native -static sigsegv_address_t get_fault_address(struct sigcontext *scp) -{ - struct sigstate { - int ss_flags; - struct frame ss_frame; - }; - struct sigstate *state = (struct sigstate *)scp->sc_ap; - char *fault_addr; - switch (state->ss_frame.f_format) { - case 7: /* 68040 access error */ - /* "code" is sometimes unreliable (i.e. contains NULL or a bogus address), reason unknown */ - fault_addr = state->ss_frame.f_fmt7.f_fa; - break; - default: - fault_addr = (char *)code; - break; - } - return (sigsegv_address_t)fault_addr; -} -#endif -#if (defined(alpha) || defined(__alpha__)) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) -#endif -#if (defined(i386) || defined(__i386__)) -#error "FIXME: need to decode instruction and compute EA" -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#endif -#endif -#if defined(__FreeBSD__) -#if (defined(i386) || defined(__i386__)) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp, char *addr -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp, addr -#define SIGSEGV_FAULT_ADDRESS addr -#define SIGSEGV_FAULT_INSTRUCTION scp->sc_eip -#define SIGSEGV_REGISTER_FILE ((SIGSEGV_REGISTER_TYPE *)&scp->sc_edi) -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#if (defined(alpha) || defined(__alpha__)) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGSEGV) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, char *addr, struct sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, addr, scp -#define SIGSEGV_FAULT_ADDRESS addr -#define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc -#endif -#endif - -// Extract fault address out of a sigcontext -#if (defined(alpha) || defined(__alpha__)) -// From Boehm's GC 6.0alpha8 -static sigsegv_address_t get_fault_address(struct sigcontext *scp) -{ - unsigned int instruction = *((unsigned int *)(scp->sc_pc)); - unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f]; - fault_address += (signed long)(signed short)(instruction & 0xffff); - return (sigsegv_address_t)fault_address; -} -#endif -// MacOS X, not sure which version this works in. Under 10.1 -// vm_protect does not appear to work from a signal handler. Under -// 10.2 signal handlers get siginfo type arguments but the si_addr -// field is the address of the faulting instruction and not the -// address that caused the SIGBUS. Maybe this works in 10.0? In any -// case with Mach exception handlers there is a way to do what this -// was meant to do. -#ifndef HAVE_MACH_EXCEPTIONS -#if defined(__APPLE__) && defined(__MACH__) -#if (defined(ppc) || defined(__ppc__)) -#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct __darwin_sigcontext *scp -#define SIGSEGV_FAULT_HANDLER_ARGS sig, code, scp -#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp) -#define SIGSEGV_FAULT_INSTRUCTION scp->MACH_FIELD_NAME(sc_ir) -#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS) -#define SIGSEGV_REGISTER_FILE (unsigned int *)&scp->sc_ir, &((unsigned int *) scp->sc_regs)[2] -#define SIGSEGV_SKIP_INSTRUCTION powerpc_skip_instruction - -// Use decoding scheme from SheepShaver -static sigsegv_address_t get_fault_address(struct sigcontext *scp) -{ - unsigned int nip = (unsigned int) scp->MACH_FIELD_NAME(sc_ir); - unsigned int * gpr = &((unsigned int *) scp->MACH_FIELD_NAME(sc_regs))[2]; - instruction_t instr; - - powerpc_decode_instruction(&instr, nip, (long unsigned int*)gpr); - return (sigsegv_address_t)instr.addr; -} -#endif -#endif -#endif -#endif - -#if HAVE_WIN32_EXCEPTIONS -#define WIN32_LEAN_AND_MEAN /* avoid including junk */ -#include -#include - -#define SIGSEGV_FAULT_HANDLER_ARGLIST EXCEPTION_POINTERS *ExceptionInfo -#define SIGSEGV_FAULT_HANDLER_ARGS ExceptionInfo -#define SIGSEGV_FAULT_ADDRESS ExceptionInfo->ExceptionRecord->ExceptionInformation[1] -#define SIGSEGV_CONTEXT_REGS ExceptionInfo->ContextRecord -#if defined(_M_IX86) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS->Eip -#define SIGSEGV_REGISTER_FILE ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Edi) -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#if defined(_M_X64) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS->Rip -#define SIGSEGV_REGISTER_FILE ((SIGSEGV_REGISTER_TYPE *)&SIGSEGV_CONTEXT_REGS->Rax) -#define SIGSEGV_SKIP_INSTRUCTION ix86_skip_instruction -#endif -#if defined(_M_IA64) -#define SIGSEGV_FAULT_INSTRUCTION SIGSEGV_CONTEXT_REGS->StIIP -#endif #endif #if HAVE_MACH_EXCEPTIONS @@ -748,130 +254,11 @@ handleExceptions(void *priv) #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION // Decode and skip X86 instruction #if (defined(i386) || defined(__i386__) || defined(_M_IX86)) || (defined(__x86_64__) || defined(_M_X64)) -#if defined(__linux__) -enum { -#if (defined(i386) || defined(__i386__)) - X86_REG_EIP = 14, - X86_REG_EAX = 11, - X86_REG_ECX = 10, - X86_REG_EDX = 9, - X86_REG_EBX = 8, - X86_REG_ESP = 7, - X86_REG_EBP = 6, - X86_REG_ESI = 5, - X86_REG_EDI = 4 -#endif -#if defined(__x86_64__) - X86_REG_R8 = 0, - X86_REG_R9 = 1, - X86_REG_R10 = 2, - X86_REG_R11 = 3, - X86_REG_R12 = 4, - X86_REG_R13 = 5, - X86_REG_R14 = 6, - X86_REG_R15 = 7, - X86_REG_EDI = 8, - X86_REG_ESI = 9, - X86_REG_EBP = 10, - X86_REG_EBX = 11, - X86_REG_EDX = 12, - X86_REG_EAX = 13, - X86_REG_ECX = 14, - X86_REG_ESP = 15, - X86_REG_EIP = 16 -#endif -}; -#endif -#if defined(__NetBSD__) -enum { -#if (defined(i386) || defined(__i386__)) - X86_REG_EIP = _REG_EIP, - X86_REG_EAX = _REG_EAX, - X86_REG_ECX = _REG_ECX, - X86_REG_EDX = _REG_EDX, - X86_REG_EBX = _REG_EBX, - X86_REG_ESP = _REG_ESP, - X86_REG_EBP = _REG_EBP, - X86_REG_ESI = _REG_ESI, - X86_REG_EDI = _REG_EDI -#endif -}; -#endif -#if defined(__FreeBSD__) -enum { -#if (defined(i386) || defined(__i386__)) - X86_REG_EIP = 10, - X86_REG_EAX = 7, - X86_REG_ECX = 6, - X86_REG_EDX = 5, - X86_REG_EBX = 4, - X86_REG_ESP = 13, - X86_REG_EBP = 2, - X86_REG_ESI = 1, - X86_REG_EDI = 0 -#endif -#if (defined(x86_64) || defined(__x86_64__)) - X86_REG_EDI = 0, - X86_REG_ESI = 1, - X86_REG_EDX = 2, - X86_REG_ECX = 3, - X86_REG_R8 = 4, - X86_REG_R9 = 5, - X86_REG_EAX = 6, - X86_REG_EBX = 7, - X86_REG_EBP = 8, - X86_REG_R10 = 9, - X86_REG_R11 = 10, - X86_REG_R12 = 11, - X86_REG_R13 = 12, - X86_REG_R14 = 13, - X86_REG_R15 = 14, - X86_REG_EIP = 19, - X86_REG_ESP = 22, -#endif -}; -#endif -#if defined(__OpenBSD__) -enum { -#if defined(__i386__) - // EDI is the first register we consider -#define OREG(REG) offsetof(struct sigcontext, sc_##REG) -#define DREG(REG) ((OREG(REG) - OREG(edi)) / 4) - X86_REG_EIP = DREG(eip), // 7 - X86_REG_EAX = DREG(eax), // 6 - X86_REG_ECX = DREG(ecx), // 5 - X86_REG_EDX = DREG(edx), // 4 - X86_REG_EBX = DREG(ebx), // 3 - X86_REG_ESP = DREG(esp), // 10 - X86_REG_EBP = DREG(ebp), // 2 - X86_REG_ESI = DREG(esi), // 1 - X86_REG_EDI = DREG(edi) // 0 -#undef DREG -#undef OREG -#endif -}; -#endif -#if defined(__sun__) -// Same as for Linux, need to check for x86-64 -enum { -#if defined(__i386__) - X86_REG_EIP = EIP, - X86_REG_EAX = EAX, - X86_REG_ECX = ECX, - X86_REG_EDX = EDX, - X86_REG_EBX = EBX, - X86_REG_ESP = ESP, - X86_REG_EBP = EBP, - X86_REG_ESI = ESI, - X86_REG_EDI = EDI -#endif -}; -#endif + #if defined(__APPLE__) && defined(__MACH__) enum { #if (defined(i386) || defined(__i386__)) #ifdef i386_SAVED_STATE - // same as FreeBSD (in Open Darwin 8.0.1) X86_REG_EIP = 10, X86_REG_EAX = 7, X86_REG_ECX = 6, @@ -915,40 +302,7 @@ enum { #endif }; #endif -#if defined(_WIN32) -enum { -#if defined(_M_IX86) - X86_REG_EIP = 7, - X86_REG_EAX = 5, - X86_REG_ECX = 4, - X86_REG_EDX = 3, - X86_REG_EBX = 2, - X86_REG_ESP = 10, - X86_REG_EBP = 6, - X86_REG_ESI = 1, - X86_REG_EDI = 0 -#endif -#if defined(_M_X64) - X86_REG_EAX = 0, - X86_REG_ECX = 1, - X86_REG_EDX = 2, - X86_REG_EBX = 3, - X86_REG_ESP = 4, - X86_REG_EBP = 5, - X86_REG_ESI = 6, - X86_REG_EDI = 7, - X86_REG_R8 = 8, - X86_REG_R9 = 9, - X86_REG_R10 = 10, - X86_REG_R11 = 11, - X86_REG_R12 = 12, - X86_REG_R13 = 13, - X86_REG_R14 = 14, - X86_REG_R15 = 15, - X86_REG_EIP = 16 -#endif -}; -#endif + // FIXME: this is partly redundant with the instruction decoding phase // to discover transfer type and register number static inline int ix86_step_over_modrm(unsigned char * p) @@ -989,10 +343,6 @@ static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs) if (eip == 0) return false; -#ifdef _WIN32 - if (IsBadCodePtr((FARPROC)eip)) - return false; -#endif enum instruction_type_t { i_MOV, @@ -1242,1261 +592,6 @@ static bool ix86_skip_instruction(SIGSEGV_REGISTER_TYPE * regs) } #endif -// Decode and skip IA-64 instruction -#if defined(__ia64) || defined(__ia64__) -typedef uint64_t ia64_bundle_t[2]; -#if defined(__linux__) -// We can directly patch the slot number -#define IA64_CAN_PATCH_IP_SLOT 1 -// Helper macros to access the machine context -#define IA64_CONTEXT_TYPE struct sigcontext * -#define IA64_CONTEXT scp -#define IA64_GET_IP() (IA64_CONTEXT->sc_ip) -#define IA64_SET_IP(V) (IA64_CONTEXT->sc_ip = (V)) -#define IA64_GET_PR(P) ((IA64_CONTEXT->sc_pr >> (P)) & 1) -#define IA64_GET_NAT(I) ((IA64_CONTEXT->sc_nat >> (I)) & 1) -#define IA64_GET_GR(R) (IA64_CONTEXT->sc_gr[(R)]) -#define _IA64_SET_GR(R,V) (IA64_CONTEXT->sc_gr[(R)] = (V)) -#define _IA64_SET_NAT(I,V) (IA64_CONTEXT->sc_nat = (IA64_CONTEXT->sc_nat & ~(1ull << (I))) | (((uint64_t)!!(V)) << (I))) -#define IA64_SET_GR(R,V,N) (_IA64_SET_GR(R,V), _IA64_SET_NAT(R,N)) - -// Load bundle (in little-endian) -static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip) -{ - uint64_t *ip = (uint64_t *)(raw_ip & ~3ull); - bundle[0] = ip[0]; - bundle[1] = ip[1]; -} -#endif -#if defined(__hpux) || defined(__hpux__) -// We can directly patch the slot number -#define IA64_CAN_PATCH_IP_SLOT 1 -// Helper macros to access the machine context -#define IA64_CONTEXT_TYPE ucontext_t * -#define IA64_CONTEXT ucp -#define IA64_GET_IP() ia64_get_ip(IA64_CONTEXT) -#define IA64_SET_IP(V) ia64_set_ip(IA64_CONTEXT, V) -#define IA64_GET_PR(P) ia64_get_pr(IA64_CONTEXT, P) -#define IA64_GET_NAT(I) ia64_get_nat(IA64_CONTEXT, I) -#define IA64_GET_GR(R) ia64_get_gr(IA64_CONTEXT, R) -#define IA64_SET_GR(R,V,N) ia64_set_gr(IA64_CONTEXT, R, V, N) -#define UC_ACCESS(FUNC,ARGS) do { if (__uc_##FUNC ARGS != 0) abort(); } while (0) - -static inline uint64_t ia64_get_ip(IA64_CONTEXT_TYPE IA64_CONTEXT) - { uint64_t v; UC_ACCESS(get_ip,(IA64_CONTEXT, &v)); return v; } -static inline void ia64_set_ip(IA64_CONTEXT_TYPE IA64_CONTEXT, uint64_t v) - { UC_ACCESS(set_ip,(IA64_CONTEXT, v)); } -static inline unsigned int ia64_get_pr(IA64_CONTEXT_TYPE IA64_CONTEXT, int pr) - { uint64_t v; UC_ACCESS(get_prs,(IA64_CONTEXT, &v)); return (v >> pr) & 1; } -static inline unsigned int ia64_get_nat(IA64_CONTEXT_TYPE IA64_CONTEXT, int r) - { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return (nat >> r) & 1; } -static inline uint64_t ia64_get_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r) - { uint64_t v; unsigned int nat; UC_ACCESS(get_grs,(IA64_CONTEXT, r, 1, &v, &nat)); return v; } - -static void ia64_set_gr(IA64_CONTEXT_TYPE IA64_CONTEXT, int r, uint64_t v, unsigned int nat) -{ - if (r == 0) - return; - if (r > 0 && r < 32) - UC_ACCESS(set_grs,(IA64_CONTEXT, r, 1, &v, (!!nat) << r)); - else { - uint64_t bsp, bspstore; - UC_ACCESS(get_ar_bsp,(IA64_CONTEXT, &bsp)); - UC_ACCESS(get_ar_bspstore,(IA64_CONTEXT, &bspstore)); - abort(); /* XXX: use libunwind, this is not fun... */ - } -} - -// Byte-swapping -#if defined(__GNUC__) -#define BSWAP64(V) ({ uint64_t r; __asm__ __volatile__("mux1 %0=%1,@rev;;" : "=r" (r) : "r" (V)); r; }) -#elif defined (__HP_aCC) -#define BSWAP64(V) _Asm_mux1(_MBTYPE_REV, V) -#else -#error "Define byte-swap instruction" -#endif - -// Load bundle (in little-endian) -static inline void ia64_load_bundle(ia64_bundle_t bundle, uint64_t raw_ip) -{ - uint64_t *ip = (uint64_t *)(raw_ip & ~3ull); - bundle[0] = BSWAP64(ip[0]); - bundle[1] = BSWAP64(ip[1]); -} -#endif - -// Instruction operations -enum { - IA64_INST_UNKNOWN = 0, - IA64_INST_LD1, // ld1 op0=[op1] - IA64_INST_LD1_UPDATE, // ld1 op0=[op1],op2 - IA64_INST_LD2, // ld2 op0=[op1] - IA64_INST_LD2_UPDATE, // ld2 op0=[op1],op2 - IA64_INST_LD4, // ld4 op0=[op1] - IA64_INST_LD4_UPDATE, // ld4 op0=[op1],op2 - IA64_INST_LD8, // ld8 op0=[op1] - IA64_INST_LD8_UPDATE, // ld8 op0=[op1],op2 - IA64_INST_ST1, // st1 [op0]=op1 - IA64_INST_ST1_UPDATE, // st1 [op0]=op1,op2 - IA64_INST_ST2, // st2 [op0]=op1 - IA64_INST_ST2_UPDATE, // st2 [op0]=op1,op2 - IA64_INST_ST4, // st4 [op0]=op1 - IA64_INST_ST4_UPDATE, // st4 [op0]=op1,op2 - IA64_INST_ST8, // st8 [op0]=op1 - IA64_INST_ST8_UPDATE, // st8 [op0]=op1,op2 - IA64_INST_ADD, // add op0=op1,op2,op3 - IA64_INST_SUB, // sub op0=op1,op2,op3 - IA64_INST_SHLADD, // shladd op0=op1,op3,op2 - IA64_INST_AND, // and op0=op1,op2 - IA64_INST_ANDCM, // andcm op0=op1,op2 - IA64_INST_OR, // or op0=op1,op2 - IA64_INST_XOR, // xor op0=op1,op2 - IA64_INST_SXT1, // sxt1 op0=op1 - IA64_INST_SXT2, // sxt2 op0=op1 - IA64_INST_SXT4, // sxt4 op0=op1 - IA64_INST_ZXT1, // zxt1 op0=op1 - IA64_INST_ZXT2, // zxt2 op0=op1 - IA64_INST_ZXT4, // zxt4 op0=op1 - IA64_INST_NOP // nop op0 -}; - -const int IA64_N_OPERANDS = 4; - -// Decoded operand type -struct ia64_operand_t { - uint8_t commit; // commit result of operation to register file? - uint8_t valid; // XXX: not really used, can be removed (debug) - int8_t index; // index of GPR, or -1 if immediate value - uint8_t nat; // NaT state before operation - uint64_t value; // register contents or immediate value -}; - -// Decoded instruction type -struct ia64_instruction_t { - uint8_t mnemo; // operation to perform - uint8_t pred; // predicate register to check - uint8_t no_memory; // used to emulated main fault instruction - uint64_t inst; // the raw instruction bits (41-bit wide) - ia64_operand_t operands[IA64_N_OPERANDS]; -}; - -// Get immediate sign-bit -static inline int ia64_inst_get_sbit(uint64_t inst) -{ - return (inst >> 36) & 1; -} - -// Get 8-bit immediate value (A3, A8, I27, M30) -static inline uint64_t ia64_inst_get_imm8(uint64_t inst) -{ - uint64_t value = (inst >> 13) & 0x7full; - if (ia64_inst_get_sbit(inst)) - value |= ~0x7full; - return value; -} - -// Get 9-bit immediate value (M3) -static inline uint64_t ia64_inst_get_imm9b(uint64_t inst) -{ - uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 13) & 0x7f); - if (ia64_inst_get_sbit(inst)) - value |= ~0xffull; - return value; -} - -// Get 9-bit immediate value (M5) -static inline uint64_t ia64_inst_get_imm9a(uint64_t inst) -{ - uint64_t value = (((inst >> 27) & 1) << 7) | ((inst >> 6) & 0x7f); - if (ia64_inst_get_sbit(inst)) - value |= ~0xffull; - return value; -} - -// Get 14-bit immediate value (A4) -static inline uint64_t ia64_inst_get_imm14(uint64_t inst) -{ - uint64_t value = (((inst >> 27) & 0x3f) << 7) | (inst & 0x7f); - if (ia64_inst_get_sbit(inst)) - value |= ~0x1ffull; - return value; -} - -// Get 22-bit immediate value (A5) -static inline uint64_t ia64_inst_get_imm22(uint64_t inst) -{ - uint64_t value = ((((inst >> 22) & 0x1f) << 16) | - (((inst >> 27) & 0x1ff) << 7) | - (inst & 0x7f)); - if (ia64_inst_get_sbit(inst)) - value |= ~0x1fffffull; - return value; -} - -// Get 21-bit immediate value (I19) -static inline uint64_t ia64_inst_get_imm21(uint64_t inst) -{ - return (((inst >> 36) & 1) << 20) | ((inst >> 6) & 0xfffff); -} - -// Get 2-bit count value (A2) -static inline int ia64_inst_get_count2(uint64_t inst) -{ - return (inst >> 27) & 0x3; -} - -// Get bundle template -static inline unsigned int ia64_get_template(uint64_t ip) -{ - ia64_bundle_t bundle; - ia64_load_bundle(bundle, ip); - return bundle[0] & 0x1f; -} - -// Get specified instruction in bundle -static uint64_t ia64_get_instruction(uint64_t ip, int slot) -{ - uint64_t inst; - ia64_bundle_t bundle; - ia64_load_bundle(bundle, ip); -#if DEBUG - printf("Bundle: %016llx%016llx\n", bundle[1], bundle[0]); -#endif - - switch (slot) { - case 0: - inst = (bundle[0] >> 5) & 0x1ffffffffffull; - break; - case 1: - inst = ((bundle[1] & 0x7fffffull) << 18) | ((bundle[0] >> 46) & 0x3ffffull); - break; - case 2: - inst = (bundle[1] >> 23) & 0x1ffffffffffull; - break; - case 3: - fprintf(stderr, "ERROR: ia64_get_instruction(), invalid slot number %d\n", slot); - abort(); - break; - } - -#if DEBUG - printf(" Instruction %d: 0x%016llx\n", slot, inst); -#endif - return inst; -} - -// Decode group 0 instructions -static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - const int r1 = (inst->inst >> 6) & 0x7f; - const int r3 = (inst->inst >> 20) & 0x7f; - - const int x3 = (inst->inst >> 33) & 0x07; - const int x6 = (inst->inst >> 27) & 0x3f; - const int x2 = (inst->inst >> 31) & 0x03; - const int x4 = (inst->inst >> 27) & 0x0f; - - if (x3 == 0) { - switch (x6) { - case 0x01: // nop.i (I19) - inst->mnemo = IA64_INST_NOP; - inst->operands[0].valid = true; - inst->operands[0].index = -1; - inst->operands[0].value = ia64_inst_get_imm21(inst->inst); - return true; - case 0x14: // sxt1 (I29) - case 0x15: // sxt2 (I29) - case 0x16: // sxt4 (I29) - case 0x10: // zxt1 (I29) - case 0x11: // zxt2 (I29) - case 0x12: // zxt4 (I29) - switch (x6) { - case 0x14: inst->mnemo = IA64_INST_SXT1; break; - case 0x15: inst->mnemo = IA64_INST_SXT2; break; - case 0x16: inst->mnemo = IA64_INST_SXT4; break; - case 0x10: inst->mnemo = IA64_INST_ZXT1; break; - case 0x11: inst->mnemo = IA64_INST_ZXT2; break; - case 0x12: inst->mnemo = IA64_INST_ZXT4; break; - default: abort(); - } - inst->operands[0].valid = true; - inst->operands[0].index = r1; - inst->operands[1].valid = true; - inst->operands[1].index = r3; - inst->operands[1].value = IA64_GET_GR(r3); - inst->operands[1].nat = IA64_GET_NAT(r3); - return true; - } - } - return false; -} - -// Decode group 4 instructions (load/store instructions) -static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - const int r1 = (inst->inst >> 6) & 0x7f; - const int r2 = (inst->inst >> 13) & 0x7f; - const int r3 = (inst->inst >> 20) & 0x7f; - - const int m = (inst->inst >> 36) & 1; - const int x = (inst->inst >> 27) & 1; - const int x6 = (inst->inst >> 30) & 0x3f; - - switch (x6) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - if (x == 0) { - inst->operands[0].valid = true; - inst->operands[0].index = r1; - inst->operands[1].valid = true; - inst->operands[1].index = r3; - inst->operands[1].value = IA64_GET_GR(r3); - inst->operands[1].nat = IA64_GET_NAT(r3); - if (m == 0) { - switch (x6) { - case 0x00: inst->mnemo = IA64_INST_LD1; break; - case 0x01: inst->mnemo = IA64_INST_LD2; break; - case 0x02: inst->mnemo = IA64_INST_LD4; break; - case 0x03: inst->mnemo = IA64_INST_LD8; break; - } - } - else { - inst->operands[2].valid = true; - inst->operands[2].index = r2; - inst->operands[2].value = IA64_GET_GR(r2); - inst->operands[2].nat = IA64_GET_NAT(r2); - switch (x6) { - case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break; - case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break; - case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break; - case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break; - } - } - return true; - } - break; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - if (m == 0 && x == 0) { - inst->operands[0].valid = true; - inst->operands[0].index = r3; - inst->operands[0].value = IA64_GET_GR(r3); - inst->operands[0].nat = IA64_GET_NAT(r3); - inst->operands[1].valid = true; - inst->operands[1].index = r2; - inst->operands[1].value = IA64_GET_GR(r2); - inst->operands[1].nat = IA64_GET_NAT(r2); - switch (x6) { - case 0x30: inst->mnemo = IA64_INST_ST1; break; - case 0x31: inst->mnemo = IA64_INST_ST2; break; - case 0x32: inst->mnemo = IA64_INST_ST4; break; - case 0x33: inst->mnemo = IA64_INST_ST8; break; - } - return true; - } - break; - } - return false; -} - -// Decode group 5 instructions (load/store instructions) -static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - const int r1 = (inst->inst >> 6) & 0x7f; - const int r2 = (inst->inst >> 13) & 0x7f; - const int r3 = (inst->inst >> 20) & 0x7f; - - const int x6 = (inst->inst >> 30) & 0x3f; - - switch (x6) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - inst->operands[0].valid = true; - inst->operands[0].index = r1; - inst->operands[1].valid = true; - inst->operands[1].index = r3; - inst->operands[1].value = IA64_GET_GR(r3); - inst->operands[1].nat = IA64_GET_NAT(r3); - inst->operands[2].valid = true; - inst->operands[2].index = -1; - inst->operands[2].value = ia64_inst_get_imm9b(inst->inst); - inst->operands[2].nat = 0; - switch (x6) { - case 0x00: inst->mnemo = IA64_INST_LD1_UPDATE; break; - case 0x01: inst->mnemo = IA64_INST_LD2_UPDATE; break; - case 0x02: inst->mnemo = IA64_INST_LD4_UPDATE; break; - case 0x03: inst->mnemo = IA64_INST_LD8_UPDATE; break; - } - return true; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - inst->operands[0].valid = true; - inst->operands[0].index = r3; - inst->operands[0].value = IA64_GET_GR(r3); - inst->operands[0].nat = IA64_GET_NAT(r3); - inst->operands[1].valid = true; - inst->operands[1].index = r2; - inst->operands[1].value = IA64_GET_GR(r2); - inst->operands[1].nat = IA64_GET_NAT(r2); - inst->operands[2].valid = true; - inst->operands[2].index = -1; - inst->operands[2].value = ia64_inst_get_imm9a(inst->inst); - inst->operands[2].nat = 0; - switch (x6) { - case 0x30: inst->mnemo = IA64_INST_ST1_UPDATE; break; - case 0x31: inst->mnemo = IA64_INST_ST2_UPDATE; break; - case 0x32: inst->mnemo = IA64_INST_ST4_UPDATE; break; - case 0x33: inst->mnemo = IA64_INST_ST8_UPDATE; break; - } - return true; - } - return false; -} - -// Decode group 8 instructions (ALU integer) -static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - const int r1 = (inst->inst >> 6) & 0x7f; - const int r2 = (inst->inst >> 13) & 0x7f; - const int r3 = (inst->inst >> 20) & 0x7f; - - const int x2a = (inst->inst >> 34) & 0x3; - const int x2b = (inst->inst >> 27) & 0x3; - const int x4 = (inst->inst >> 29) & 0xf; - const int ve = (inst->inst >> 33) & 0x1; - - // destination register (r1) is always valid in this group - inst->operands[0].valid = true; - inst->operands[0].index = r1; - - // source register (r3) is always valid in this group - inst->operands[2].valid = true; - inst->operands[2].index = r3; - inst->operands[2].value = IA64_GET_GR(r3); - inst->operands[2].nat = IA64_GET_NAT(r3); - - if (x2a == 0 && ve == 0) { - inst->operands[1].valid = true; - inst->operands[1].index = r2; - inst->operands[1].value = IA64_GET_GR(r2); - inst->operands[1].nat = IA64_GET_NAT(r2); - switch (x4) { - case 0x0: // add (A1) - inst->mnemo = IA64_INST_ADD; - inst->operands[3].valid = true; - inst->operands[3].index = -1; - inst->operands[3].value = x2b == 1; - return true; - case 0x1: // add (A1) - inst->mnemo = IA64_INST_SUB; - inst->operands[3].valid = true; - inst->operands[3].index = -1; - inst->operands[3].value = x2b == 0; - return true; - case 0x4: // shladd (A2) - inst->mnemo = IA64_INST_SHLADD; - inst->operands[3].valid = true; - inst->operands[3].index = -1; - inst->operands[3].value = ia64_inst_get_count2(inst->inst); - return true; - case 0x9: - if (x2b == 1) { - inst->mnemo = IA64_INST_SUB; - inst->operands[1].index = -1; - inst->operands[1].value = ia64_inst_get_imm8(inst->inst); - inst->operands[1].nat = 0; - return true; - } - break; - case 0xb: - inst->operands[1].index = -1; - inst->operands[1].value = ia64_inst_get_imm8(inst->inst); - inst->operands[1].nat = 0; - // fall-through - case 0x3: - switch (x2b) { - case 0: inst->mnemo = IA64_INST_AND; break; - case 1: inst->mnemo = IA64_INST_ANDCM; break; - case 2: inst->mnemo = IA64_INST_OR; break; - case 3: inst->mnemo = IA64_INST_XOR; break; - } - return true; - } - } - return false; -} - -// Decode instruction -static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - const int major = (inst->inst >> 37) & 0xf; - - inst->mnemo = IA64_INST_UNKNOWN; - inst->pred = inst->inst & 0x3f; - memset(&inst->operands[0], 0, sizeof(inst->operands)); - - switch (major) { - case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT); - case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT); - case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT); - case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT); - } - return false; -} - -static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - // XXX: handle Register NaT Consumption fault? - // XXX: this simple emulator assumes instructions in a bundle - // don't depend on effects of other instructions in the same - // bundle. It probably would be simpler to JIT-generate code to be - // executed natively but probably more costly (inject/extract CPU state) - if (inst->mnemo == IA64_INST_UNKNOWN) - return false; - if (inst->pred && !IA64_GET_PR(inst->pred)) - return true; - - uint8_t nat, nat2; - uint64_t dst, dst2, src1, src2, src3; - - switch (inst->mnemo) { - case IA64_INST_NOP: - break; - case IA64_INST_ADD: - case IA64_INST_SUB: - case IA64_INST_SHLADD: - src3 = inst->operands[3].value; - // fall-through - case IA64_INST_AND: - case IA64_INST_ANDCM: - case IA64_INST_OR: - case IA64_INST_XOR: - src1 = inst->operands[1].value; - src2 = inst->operands[2].value; - switch (inst->mnemo) { - case IA64_INST_ADD: dst = src1 + src2 + src3; break; - case IA64_INST_SUB: dst = src1 - src2 - src3; break; - case IA64_INST_SHLADD: dst = (src1 << src3) + src2; break; - case IA64_INST_AND: dst = src1 & src2; break; - case IA64_INST_ANDCM: dst = src1 &~ src2; break; - case IA64_INST_OR: dst = src1 | src2; break; - case IA64_INST_XOR: dst = src1 ^ src2; break; - } - inst->operands[0].commit = true; - inst->operands[0].value = dst; - inst->operands[0].nat = inst->operands[1].nat | inst->operands[2].nat; - break; - case IA64_INST_SXT1: - case IA64_INST_SXT2: - case IA64_INST_SXT4: - case IA64_INST_ZXT1: - case IA64_INST_ZXT2: - case IA64_INST_ZXT4: - src1 = inst->operands[1].value; - switch (inst->mnemo) { - case IA64_INST_SXT1: dst = (int64_t)(int8_t)src1; break; - case IA64_INST_SXT2: dst = (int64_t)(int16_t)src1; break; - case IA64_INST_SXT4: dst = (int64_t)(int32_t)src1; break; - case IA64_INST_ZXT1: dst = (uint8_t)src1; break; - case IA64_INST_ZXT2: dst = (uint16_t)src1; break; - case IA64_INST_ZXT4: dst = (uint32_t)src1; break; - } - inst->operands[0].commit = true; - inst->operands[0].value = dst; - inst->operands[0].nat = inst->operands[1].nat; - break; - case IA64_INST_LD1_UPDATE: - case IA64_INST_LD2_UPDATE: - case IA64_INST_LD4_UPDATE: - case IA64_INST_LD8_UPDATE: - inst->operands[1].commit = true; - dst2 = inst->operands[1].value + inst->operands[2].value; - nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0; - // fall-through - case IA64_INST_LD1: - case IA64_INST_LD2: - case IA64_INST_LD4: - case IA64_INST_LD8: - src1 = inst->operands[1].value; - if (inst->no_memory) - dst = 0; - else { - switch (inst->mnemo) { - case IA64_INST_LD1: case IA64_INST_LD1_UPDATE: dst = *((uint8_t *)src1); break; - case IA64_INST_LD2: case IA64_INST_LD2_UPDATE: dst = *((uint16_t *)src1); break; - case IA64_INST_LD4: case IA64_INST_LD4_UPDATE: dst = *((uint32_t *)src1); break; - case IA64_INST_LD8: case IA64_INST_LD8_UPDATE: dst = *((uint64_t *)src1); break; - } - } - inst->operands[0].commit = true; - inst->operands[0].value = dst; - inst->operands[0].nat = 0; - inst->operands[1].value = dst2; - inst->operands[1].nat = nat2; - break; - case IA64_INST_ST1_UPDATE: - case IA64_INST_ST2_UPDATE: - case IA64_INST_ST4_UPDATE: - case IA64_INST_ST8_UPDATE: - inst->operands[0].commit = 0; - dst2 = inst->operands[0].value + inst->operands[2].value; - nat2 = inst->operands[2].nat ? inst->operands[2].nat : 0; - // fall-through - case IA64_INST_ST1: - case IA64_INST_ST2: - case IA64_INST_ST4: - case IA64_INST_ST8: - dst = inst->operands[0].value; - src1 = inst->operands[1].value; - if (!inst->no_memory) { - switch (inst->mnemo) { - case IA64_INST_ST1: case IA64_INST_ST1_UPDATE: *((uint8_t *)dst) = src1; break; - case IA64_INST_ST2: case IA64_INST_ST2_UPDATE: *((uint16_t *)dst) = src1; break; - case IA64_INST_ST4: case IA64_INST_ST4_UPDATE: *((uint32_t *)dst) = src1; break; - case IA64_INST_ST8: case IA64_INST_ST8_UPDATE: *((uint64_t *)dst) = src1; break; - } - } - inst->operands[0].value = dst2; - inst->operands[0].nat = nat2; - break; - default: - return false; - } - - for (int i = 0; i < IA64_N_OPERANDS; i++) { - ia64_operand_t const & op = inst->operands[i]; - if (!op.commit) - continue; - if (op.index == -1) - return false; // XXX: internal error - IA64_SET_GR(op.index, op.value, op.nat); - } - return true; -} - -static bool ia64_emulate_instruction(uint64_t raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - ia64_instruction_t inst; - memset(&inst, 0, sizeof(inst)); - inst.inst = raw_inst; - if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) - return false; - return ia64_emulate_instruction(&inst, IA64_CONTEXT); -} - -static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT) -{ - uint64_t ip = IA64_GET_IP(); -#if DEBUG - printf("IP: 0x%016llx\n", ip); -#if 0 - printf(" Template 0x%02x\n", ia64_get_template(ip)); - ia64_get_instruction(ip, 0); - ia64_get_instruction(ip, 1); - ia64_get_instruction(ip, 2); -#endif -#endif - - // Select which decode switch to use - ia64_instruction_t inst; - inst.inst = ia64_get_instruction(ip, ip & 3); - if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) { - fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n"); - return false; - } - - transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN; - transfer_size_t transfer_size = SIZE_UNKNOWN; - - switch (inst.mnemo) { - case IA64_INST_LD1: - case IA64_INST_LD2: - case IA64_INST_LD4: - case IA64_INST_LD8: - case IA64_INST_LD1_UPDATE: - case IA64_INST_LD2_UPDATE: - case IA64_INST_LD4_UPDATE: - case IA64_INST_LD8_UPDATE: - transfer_type = SIGSEGV_TRANSFER_LOAD; - break; - case IA64_INST_ST1: - case IA64_INST_ST2: - case IA64_INST_ST4: - case IA64_INST_ST8: - case IA64_INST_ST1_UPDATE: - case IA64_INST_ST2_UPDATE: - case IA64_INST_ST4_UPDATE: - case IA64_INST_ST8_UPDATE: - transfer_type = SIGSEGV_TRANSFER_STORE; - break; - } - - if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) { - // Unknown machine code, let it crash. Then patch the decoder - fprintf(stderr, "ERROR: ia64_skip_instruction(): not a load/store instruction\n"); - return false; - } - - switch (inst.mnemo) { - case IA64_INST_LD1: - case IA64_INST_LD1_UPDATE: - case IA64_INST_ST1: - case IA64_INST_ST1_UPDATE: - transfer_size = SIZE_BYTE; - break; - case IA64_INST_LD2: - case IA64_INST_LD2_UPDATE: - case IA64_INST_ST2: - case IA64_INST_ST2_UPDATE: - transfer_size = SIZE_WORD; - break; - case IA64_INST_LD4: - case IA64_INST_LD4_UPDATE: - case IA64_INST_ST4: - case IA64_INST_ST4_UPDATE: - transfer_size = SIZE_LONG; - break; - case IA64_INST_LD8: - case IA64_INST_LD8_UPDATE: - case IA64_INST_ST8: - case IA64_INST_ST8_UPDATE: - transfer_size = SIZE_QUAD; - break; - } - - if (transfer_size == SIZE_UNKNOWN) { - // Unknown machine code, let it crash. Then patch the decoder - fprintf(stderr, "ERROR: ia64_skip_instruction(): unknown transfer size\n"); - return false; - } - - inst.no_memory = true; - if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) { - fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n"); - return false; - } - - int slot = ip & 3; - bool emulate_next = false; - switch (slot) { - case 0: - switch (ia64_get_template(ip)) { - case 0x2: // MI;I - case 0x3: // MI;I; - emulate_next = true; - slot = 2; - break; - case 0xa: // M;MI - case 0xb: // M;MI; - emulate_next = true; - slot = 1; - break; - } - break; - } - if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) { - while (slot < 3) { - if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) { - fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n"); - return false; - } - ++slot; - } - } - -#if IA64_CAN_PATCH_IP_SLOT - if ((slot = ip & 3) < 2) - IA64_SET_IP((ip & ~3ull) + (slot + 1)); - else -#endif - IA64_SET_IP((ip & ~3ull) + 16); -#if DEBUG - printf("IP: 0x%016llx\n", IA64_GET_IP()); -#endif - return true; -} -#endif - -// Decode and skip PPC instruction -#if (defined(powerpc) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)) -static bool powerpc_skip_instruction(unsigned long * nip_p, unsigned long * regs) -{ - instruction_t instr; - powerpc_decode_instruction(&instr, *nip_p, regs); - - if (instr.transfer_type == SIGSEGV_TRANSFER_UNKNOWN) { - // Unknown machine code, let it crash. Then patch the decoder - return false; - } - -#if DEBUG - printf("%08x: %s %s access", *nip_p, - instr.transfer_size == SIZE_BYTE ? "byte" : - instr.transfer_size == SIZE_WORD ? "word" : - instr.transfer_size == SIZE_LONG ? "long" : "quad", - instr.transfer_type == SIGSEGV_TRANSFER_LOAD ? "read" : "write"); - - if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX) - printf(" r%d (ra = %08x)\n", instr.ra, instr.addr); - if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD) - printf(" r%d (rd = 0)\n", instr.rd); -#endif - - if (instr.addr_mode == MODE_U || instr.addr_mode == MODE_UX) - regs[instr.ra] = instr.addr; - if (instr.transfer_type == SIGSEGV_TRANSFER_LOAD) - regs[instr.rd] = 0; - - *nip_p += 4; - return true; -} -#endif - -// Decode and skip MIPS instruction -#if (defined(mips) || defined(__mips)) -static bool mips_skip_instruction(greg_t * pc_p, greg_t * regs) -{ - unsigned int * epc = (unsigned int *)(unsigned long)*pc_p; - - if (epc == 0) - return false; - -#if DEBUG - printf("IP: %p [%08x]\n", epc, epc[0]); -#endif - - transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN; - transfer_size_t transfer_size = SIZE_LONG; - int direction = 0; - - const unsigned int opcode = epc[0]; - switch (opcode >> 26) { - case 32: // Load Byte - case 36: // Load Byte Unsigned - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_BYTE; - break; - case 33: // Load Halfword - case 37: // Load Halfword Unsigned - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_WORD; - break; - case 35: // Load Word - case 39: // Load Word Unsigned - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_LONG; - break; - case 34: // Load Word Left - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_LONG; - direction = -1; - break; - case 38: // Load Word Right - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_LONG; - direction = 1; - break; - case 55: // Load Doubleword - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_QUAD; - break; - case 26: // Load Doubleword Left - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_QUAD; - direction = -1; - break; - case 27: // Load Doubleword Right - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_QUAD; - direction = 1; - break; - case 40: // Store Byte - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_BYTE; - break; - case 41: // Store Halfword - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_WORD; - break; - case 43: // Store Word - case 42: // Store Word Left - case 46: // Store Word Right - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_LONG; - break; - case 63: // Store Doubleword - case 44: // Store Doubleword Left - case 45: // Store Doubleword Right - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_QUAD; - break; - /* Misc instructions unlikely to be used within CPU emulators */ - case 48: // Load Linked Word - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_LONG; - break; - case 52: // Load Linked Doubleword - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_QUAD; - break; - case 56: // Store Conditional Word - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_LONG; - break; - case 60: // Store Conditional Doubleword - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_QUAD; - break; - } - - if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) { - // Unknown machine code, let it crash. Then patch the decoder - return false; - } - - // Zero target register in case of a load operation - const int reg = (opcode >> 16) & 0x1f; - if (transfer_type == SIGSEGV_TRANSFER_LOAD) { - if (direction == 0) - regs[reg] = 0; - else { - // FIXME: untested code - unsigned long ea = regs[(opcode >> 21) & 0x1f]; - ea += (signed long)(signed int)(signed short)(opcode & 0xffff); - const int offset = ea & (transfer_size == SIZE_LONG ? 3 : 7); - unsigned long value; - if (direction > 0) { - const unsigned long rmask = ~((1L << ((offset + 1) * 8)) - 1); - value = regs[reg] & rmask; - } - else { - const unsigned long lmask = (1L << (offset * 8)) - 1; - value = regs[reg] & lmask; - } - // restore most significant bits - if (transfer_size == SIZE_LONG) - value = (signed long)(signed int)value; - regs[reg] = value; - } - } - -#if DEBUG -#if (defined(_ABIN32) || defined(_ABI64)) - static const char * mips_gpr_names[32] = { - "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" - }; -#else - static const char * mips_gpr_names[32] = { - "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" - }; -#endif - printf("%s %s register %s\n", - transfer_size == SIZE_BYTE ? "byte" : - transfer_size == SIZE_WORD ? "word" : - transfer_size == SIZE_LONG ? "long" : - transfer_size == SIZE_QUAD ? "quad" : "unknown", - transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from", - mips_gpr_names[reg]); -#endif - - *pc_p += 4; - return true; -} -#endif - -// Decode and skip SPARC instruction -#if (defined(sparc) || defined(__sparc__)) -enum { -#if (defined(__sun__)) - SPARC_REG_G1 = REG_G1, - SPARC_REG_O0 = REG_O0, - SPARC_REG_PC = REG_PC, - SPARC_REG_nPC = REG_nPC -#endif -}; -static bool sparc_skip_instruction(unsigned long * regs, gwindows_t * gwins, struct rwindow * rwin) -{ - unsigned int * pc = (unsigned int *)regs[SPARC_REG_PC]; - - if (pc == 0) - return false; - -#if DEBUG - printf("IP: %p [%08x]\n", pc, pc[0]); -#endif - - transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN; - transfer_size_t transfer_size = SIZE_LONG; - bool register_pair = false; - - const unsigned int opcode = pc[0]; - if ((opcode >> 30) != 3) - return false; - switch ((opcode >> 19) & 0x3f) { - case 9: // Load Signed Byte - case 1: // Load Unsigned Byte - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_BYTE; - break; - case 10:// Load Signed Halfword - case 2: // Load Unsigned Word - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_WORD; - break; - case 8: // Load Word - case 0: // Load Unsigned Word - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_LONG; - break; - case 11:// Load Extended Word - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_QUAD; - break; - case 3: // Load Doubleword - transfer_type = SIGSEGV_TRANSFER_LOAD; - transfer_size = SIZE_LONG; - register_pair = true; - break; - case 5: // Store Byte - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_BYTE; - break; - case 6: // Store Halfword - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_WORD; - break; - case 4: // Store Word - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_LONG; - break; - case 14:// Store Extended Word - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_QUAD; - break; - case 7: // Store Doubleword - transfer_type = SIGSEGV_TRANSFER_STORE; - transfer_size = SIZE_LONG; - register_pair = true; - break; - } - - if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) { - // Unknown machine code, let it crash. Then patch the decoder - return false; - } - - const int reg = (opcode >> 25) & 0x1f; - -#if DEBUG - static const char * reg_names[] = { - "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", - "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", - "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", - "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7" - }; - printf("%s %s register %s\n", - transfer_size == SIZE_BYTE ? "byte" : - transfer_size == SIZE_WORD ? "word" : - transfer_size == SIZE_LONG ? "long" : - transfer_size == SIZE_QUAD ? "quad" : "unknown", - transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from", - reg_names[reg]); -#endif - - // Zero target register in case of a load operation - if (transfer_type == SIGSEGV_TRANSFER_LOAD && reg != 0) { - // FIXME: code to handle local & input registers is not tested - if (reg >= 1 && reg < 8) { - // global registers - regs[reg - 1 + SPARC_REG_G1] = 0; - } - else if (reg >= 8 && reg < 16) { - // output registers - regs[reg - 8 + SPARC_REG_O0] = 0; - } - else if (reg >= 16 && reg < 24) { - // local registers (in register windows) - if (gwins) - gwins->wbuf->rw_local[reg - 16] = 0; - else - rwin->rw_local[reg - 16] = 0; - } - else { - // input registers (in register windows) - if (gwins) - gwins->wbuf->rw_in[reg - 24] = 0; - else - rwin->rw_in[reg - 24] = 0; - } - } - - regs[SPARC_REG_PC] += 4; - regs[SPARC_REG_nPC] += 4; - return true; -} -#endif -#endif - -// Decode and skip ARM instruction -#if (defined(arm) || defined(__arm__)) -enum { -#if (defined(__linux__)) - ARM_REG_PC = 15, - ARM_REG_CPSR = 16 -#endif -}; -static bool arm_skip_instruction(unsigned long * regs) -{ - unsigned int * pc = (unsigned int *)regs[ARM_REG_PC]; - - if (pc == 0) - return false; - -#if DEBUG - printf("IP: %p [%08x]\n", pc, pc[0]); -#endif - - transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN; - transfer_size_t transfer_size = SIZE_UNKNOWN; - enum { op_sdt = 1, op_sdth = 2 }; - int op = 0; - - // Handle load/store instructions only - const unsigned int opcode = pc[0]; - switch ((opcode >> 25) & 7) { - case 0: // Halfword and Signed Data Transfer (LDRH, STRH, LDRSB, LDRSH) - op = op_sdth; - // Determine transfer size (S/H bits) - switch ((opcode >> 5) & 3) { - case 0: // SWP instruction - break; - case 1: // Unsigned halfwords - case 3: // Signed halfwords - transfer_size = SIZE_WORD; - break; - case 2: // Signed byte - transfer_size = SIZE_BYTE; - break; - } - break; - case 2: - case 3: // Single Data Transfer (LDR, STR) - op = op_sdt; - // Determine transfer size (B bit) - if (((opcode >> 22) & 1) == 1) - transfer_size = SIZE_BYTE; - else - transfer_size = SIZE_LONG; - break; - default: - // FIXME: support load/store mutliple? - return false; - } - - // Check for invalid transfer size (SWP instruction?) - if (transfer_size == SIZE_UNKNOWN) - return false; - - // Determine transfer type (L bit) - if (((opcode >> 20) & 1) == 1) - transfer_type = SIGSEGV_TRANSFER_LOAD; - else - transfer_type = SIGSEGV_TRANSFER_STORE; - - // Compute offset - int offset; - if (((opcode >> 25) & 1) == 0) { - if (op == op_sdt) - offset = opcode & 0xfff; - else if (op == op_sdth) { - int rm = opcode & 0xf; - if (((opcode >> 22) & 1) == 0) { - // register offset - offset = regs[rm]; - } - else { - // immediate offset - offset = ((opcode >> 4) & 0xf0) | (opcode & 0x0f); - } - } - } - else { - const int rm = opcode & 0xf; - const int sh = (opcode >> 7) & 0x1f; - if (((opcode >> 4) & 1) == 1) { - // we expect only legal load/store instructions - printf("FATAL: invalid shift operand\n"); - return false; - } - const unsigned int v = regs[rm]; - switch ((opcode >> 5) & 3) { - case 0: // logical shift left - offset = sh ? v << sh : v; - break; - case 1: // logical shift right - offset = sh ? v >> sh : 0; - break; - case 2: // arithmetic shift right - if (sh) - offset = ((signed int)v) >> sh; - else - offset = (v & 0x80000000) ? 0xffffffff : 0; - break; - case 3: // rotate right - if (sh) - offset = (v >> sh) | (v << (32 - sh)); - else - offset = (v >> 1) | ((regs[ARM_REG_CPSR] << 2) & 0x80000000); - break; - } - } - if (((opcode >> 23) & 1) == 0) - offset = -offset; - - int rd = (opcode >> 12) & 0xf; - int rn = (opcode >> 16) & 0xf; -#if DEBUG - static const char * reg_names[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r9", "r9", "sl", "fp", "ip", "sp", "lr", "pc" - }; - printf("%s %s register %s\n", - transfer_size == SIZE_BYTE ? "byte" : - transfer_size == SIZE_WORD ? "word" : - transfer_size == SIZE_LONG ? "long" : "unknown", - transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from", - reg_names[rd]); -#endif - - unsigned int base = regs[rn]; - if (((opcode >> 24) & 1) == 1) - base += offset; - - if (transfer_type == SIGSEGV_TRANSFER_LOAD) - regs[rd] = 0; - - if (((opcode >> 24) & 1) == 0) // post-index addressing - regs[rn] += offset; - else if (((opcode >> 21) & 1) == 1) // write-back address into base - regs[rn] = base; - - regs[ARM_REG_PC] += 4; - return true; -} #endif @@ -2528,18 +623,7 @@ static bool arm_skip_instruction(unsigned long * regs) */ #ifdef HAVE_MACH_EXCEPTIONS -#ifdef EMULATED_PPC -static void mach_get_exception_state(sigsegv_info_t *SIP) -{ - SIP->exc_state_count = SIGSEGV_EXCEPTION_STATE_COUNT; - kern_return_t krc = thread_get_state(SIP->thread, - SIGSEGV_EXCEPTION_STATE_FLAVOR, - (natural_t *)&SIP->exc_state, - &SIP->exc_state_count); - MACH_CHECK_ERROR(thread_get_state, krc); - SIP->has_exc_state = true; -} -#endif + static void mach_get_thread_state(sigsegv_info_t *SIP) { @@ -2565,28 +649,6 @@ static void mach_set_thread_state(sigsegv_info_t *SIP) // Return the address of the invalid memory reference sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP) { -#ifdef HAVE_MACH_EXCEPTIONS -#ifdef EMULATED_PPC - static int use_fast_path = -1; - if (use_fast_path != 1 && !SIP->has_exc_state) { - mach_get_exception_state(SIP); - - sigsegv_address_t addr = (sigsegv_address_t)SIGSEGV_FAULT_ADDRESS; - if (use_fast_path < 0) { - const char *machfault = getenv("SIGSEGV_MACH_FAULT"); - if (machfault) { - if (strcmp(machfault, "fast") == 0) - use_fast_path = 1; - else if (strcmp(machfault, "slow") == 0) - use_fast_path = 0; - } - if (use_fast_path < 0) - use_fast_path = addr == SIP->addr; - } - SIP->addr = addr; - } -#endif -#endif return SIP->addr; } @@ -2594,15 +656,6 @@ sigsegv_address_t sigsegv_get_fault_address(sigsegv_info_t *SIP) // SIGSEGV_INVALID_ADDRESS if we could not retrieve this information sigsegv_address_t sigsegv_get_fault_instruction_address(sigsegv_info_t *SIP) { -#ifdef HAVE_MACH_EXCEPTIONS -#ifdef EMULATED_PPC - if (!SIP->has_thr_state) { - mach_get_thread_state(SIP); - - SIP->pc = (sigsegv_address_t)SIGSEGV_FAULT_INSTRUCTION; - } -#endif -#endif return SIP->pc; } @@ -2907,10 +960,6 @@ static bool sigsegv_do_install_handler(int sig) sigemptyset(&sigsegv_sa.sa_mask); sigsegv_sa.sa_handler = (signal_handler)sigsegv_handler; sigsegv_sa.sa_flags = 0; -#if !EMULATED_68K && defined(__NetBSD__) - sigaddset(&sigsegv_sa.sa_mask, SIGALRM); - sigsegv_sa.sa_flags |= SA_ONSTACK; -#endif return (sigaction(sig, &sigsegv_sa, 0) == 0); #else return (signal(sig, (signal_handler)sigsegv_handler) != SIG_ERR); @@ -3003,95 +1052,6 @@ static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler) } #endif -#ifdef HAVE_WIN32_EXCEPTIONS -static LONG WINAPI main_exception_filter(EXCEPTION_POINTERS *ExceptionInfo) -{ - if (sigsegv_fault_handler != NULL - && ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION - && ExceptionInfo->ExceptionRecord->NumberParameters >= 2 - && handle_badaccess(ExceptionInfo)) - return EXCEPTION_CONTINUE_EXECUTION; - - return EXCEPTION_CONTINUE_SEARCH; -} - -#if defined __CYGWIN__ && defined __i386__ -/* In Cygwin programs, SetUnhandledExceptionFilter has no effect because Cygwin - installs a global exception handler. We have to dig deep in order to install - our main_exception_filter. */ - -/* Data structures for the current thread's exception handler chain. - On the x86 Windows uses register fs, offset 0 to point to the current - exception handler; Cygwin mucks with it, so we must do the same... :-/ */ - -/* Magic taken from winsup/cygwin/include/exceptions.h. */ - -struct exception_list { - struct exception_list *prev; - int (*handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *); -}; -typedef struct exception_list exception_list; - -/* Magic taken from winsup/cygwin/exceptions.cc. */ - -__asm__ (".equ __except_list,0"); - -extern exception_list *_except_list __asm__ ("%fs:__except_list"); - -/* For debugging. _except_list is not otherwise accessible from gdb. */ -static exception_list * -debug_get_except_list () -{ - return _except_list; -} - -/* Cygwin's original exception handler. */ -static int (*cygwin_exception_handler) (EXCEPTION_RECORD *, void *, CONTEXT *, void *); - -/* Our exception handler. */ -static int -libsigsegv_exception_handler (EXCEPTION_RECORD *exception, void *frame, CONTEXT *context, void *dispatch) -{ - EXCEPTION_POINTERS ExceptionInfo; - ExceptionInfo.ExceptionRecord = exception; - ExceptionInfo.ContextRecord = context; - if (main_exception_filter (&ExceptionInfo) == EXCEPTION_CONTINUE_SEARCH) - return cygwin_exception_handler (exception, frame, context, dispatch); - else - return 0; -} - -static void -do_install_main_exception_filter () -{ - /* We cannot insert any handler into the chain, because such handlers - must lie on the stack (?). Instead, we have to replace(!) Cygwin's - global exception handler. */ - cygwin_exception_handler = _except_list->handler; - _except_list->handler = libsigsegv_exception_handler; -} - -#else - -static void -do_install_main_exception_filter () -{ - SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER) &main_exception_filter); -} -#endif - -static bool sigsegv_do_install_handler(sigsegv_fault_handler_t handler) -{ - static bool main_exception_filter_installed = false; - if (!main_exception_filter_installed) { - do_install_main_exception_filter(); - main_exception_filter_installed = true; - } - sigsegv_fault_handler = handler; - return true; -} -#endif - bool sigsegv_install_handler(sigsegv_fault_handler_t handler) { #if defined(HAVE_SIGSEGV_RECOVERY) @@ -3102,7 +1062,7 @@ bool sigsegv_install_handler(sigsegv_fault_handler_t handler) if (success) sigsegv_fault_handler = handler; return success; -#elif defined(HAVE_MACH_EXCEPTIONS) || defined(HAVE_WIN32_EXCEPTIONS) +#elif defined(HAVE_MACH_EXCEPTIONS) return sigsegv_do_install_handler(handler); #else // FAIL: no siginfo_t nor sigcontext subterfuge is available @@ -3128,9 +1088,6 @@ void sigsegv_deinstall_handler(void) SIGSEGV_ALL_SIGNALS #undef FAULT_HANDLER #endif -#ifdef HAVE_WIN32_EXCEPTIONS - sigsegv_fault_handler = NULL; -#endif } diff --git a/BasiliskII/src/CrossPlatform/video_blit.cpp b/BasiliskII/src/CrossPlatform/video_blit.cpp index 19e400fd..d889291a 100644 --- a/BasiliskII/src/CrossPlatform/video_blit.cpp +++ b/BasiliskII/src/CrossPlatform/video_blit.cpp @@ -498,7 +498,7 @@ bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_or #else const bool use_sdl_video = false; #endif -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING if (mac_depth == 1 && !use_sdl_video && !visual_format.fullscreen) { // Windowed 1-bit mode uses a 1-bit X image, so there's no need for special blitting routines diff --git a/BasiliskII/src/CrossPlatform/video_vosf.h b/BasiliskII/src/CrossPlatform/video_vosf.h index 4a5677e1..148a9e6f 100644 --- a/BasiliskII/src/CrossPlatform/video_vosf.h +++ b/BasiliskII/src/CrossPlatform/video_vosf.h @@ -26,10 +26,7 @@ #include "sigsegv.h" #include "vm_alloc.h" -#ifdef _WIN32 -#include "util_windows.h" -#endif - + // Glue for SDL and X11 support #ifdef TEST_VOSF_PERFORMANCE #define MONITOR_INIT /* nothing */ @@ -180,10 +177,6 @@ static inline unsigned find_next_page_clear(unsigned page) static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect frame buffer (dirtyPages in fact) #define LOCK_VOSF pthread_mutex_lock(&vosf_lock); #define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock); -#elif defined(_WIN32) -static mutex_t vosf_lock; // Mutex to protect frame buffer (dirtyPages in fact) -#define LOCK_VOSF vosf_lock.lock(); -#define UNLOCK_VOSF vosf_lock.unlock(); #elif defined(HAVE_SPINLOCKS) static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED; // Mutex to protect frame buffer (dirtyPages in fact) #define LOCK_VOSF spin_lock(&vosf_lock) @@ -533,7 +526,7 @@ static void update_display_window_vosf(VIDEO_DRV_WIN_INIT) */ #ifndef TEST_VOSF_PERFORMANCE -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT) { VIDEO_MODE_INIT; diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.cpp b/BasiliskII/src/CrossPlatform/vm_alloc.cpp index 005cb727..0dde455c 100644 --- a/BasiliskII/src/CrossPlatform/vm_alloc.cpp +++ b/BasiliskII/src/CrossPlatform/vm_alloc.cpp @@ -27,11 +27,6 @@ #include #endif -#ifdef HAVE_WIN32_VM -#define WIN32_LEAN_AND_MEAN /* avoid including junk */ -#include -#endif - #include #include #include @@ -53,13 +48,8 @@ #endif #endif -#ifdef HAVE_WIN32_VM -/* Windows is either ILP32 or LLP64 */ -typedef UINT_PTR vm_uintptr_t; -#else /* Other systems are sane as they are either ILP32 or LP64 */ typedef unsigned long vm_uintptr_t; -#endif /* We want MAP_32BIT, if available, for SheepShaver and BasiliskII because the emulated target is 32-bit and this helps to allocate @@ -71,11 +61,7 @@ typedef unsigned long vm_uintptr_t; #ifndef MAP_32BIT #define MAP_32BIT 0 #endif -#ifdef __FreeBSD__ -#define FORCE_MAP_32BIT MAP_FIXED -#else #define FORCE_MAP_32BIT MAP_32BIT -#endif #ifndef MAP_ANON #define MAP_ANON 0 #endif @@ -86,10 +72,9 @@ typedef unsigned long vm_uintptr_t; #define MAP_EXTRA_FLAGS (MAP_32BIT) #ifdef HAVE_MMAP_VM -#if (defined(__linux__) && defined(__i386__)) || defined(__FreeBSD__) || HAVE_LINKER_SCRIPT +#if HAVE_LINKER_SCRIPT /* Force a reasonnable address below 0x80000000 on x86 so that we - don't get addresses above when the program is run on AMD64. - NOTE: this is empirically determined on Linux/x86. */ + don't get addresses above when the program is run on AMD64. */ #define MAP_BASE 0x10000000 #else #define MAP_BASE 0x00000000 @@ -127,40 +112,6 @@ static int translate_map_flags(int vm_flags) } #endif -/* Align ADDR and SIZE to 64K boundaries. */ - -#ifdef HAVE_WIN32_VM -static inline LPVOID align_addr_segment(LPVOID addr) -{ - return LPVOID(vm_uintptr_t(addr) & ~vm_uintptr_t(0xFFFF)); -} - -static inline DWORD align_size_segment(LPVOID addr, DWORD size) -{ - return size + ((vm_uintptr_t)addr - (vm_uintptr_t)align_addr_segment(addr)); -} -#endif - -/* Translate generic VM prot flags to host values. */ - -#ifdef HAVE_WIN32_VM -static int translate_prot_flags(int prot_flags) -{ - int prot = PAGE_READWRITE; - if (prot_flags == (VM_PAGE_EXECUTE | VM_PAGE_READ | VM_PAGE_WRITE)) - prot = PAGE_EXECUTE_READWRITE; - else if (prot_flags == (VM_PAGE_EXECUTE | VM_PAGE_READ)) - prot = PAGE_EXECUTE_READ; - else if (prot_flags == (VM_PAGE_READ | VM_PAGE_WRITE)) - prot = PAGE_READWRITE; - else if (prot_flags == VM_PAGE_READ) - prot = PAGE_READONLY; - else if (prot_flags == 0) - prot = PAGE_NOACCESS; - return prot; -} -#endif - /* Translate Mach return codes to POSIX errno values. */ #ifdef HAVE_MACH_VM static int vm_error(kern_return_t ret_code) @@ -193,17 +144,17 @@ int vm_init(void) // On 10.4 and earlier, reset CrashReporter's task signal handler to // avoid having it show up for signals that get handled. -#if defined(__APPLE__) && defined(__MACH__) - struct utsname info; +// #if defined(__APPLE__) && defined(__MACH__) +// struct utsname info; - if (!uname(&info) && atoi(info.release) <= 8) { - task_set_exception_ports(mach_task_self(), - EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, - MACH_PORT_NULL, - EXCEPTION_STATE_IDENTITY, - MACHINE_THREAD_STATE); - } -#endif +// if (!uname(&info) && atoi(info.release) <= 8) { +// task_set_exception_ports(mach_task_self(), +// EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, +// MACH_PORT_NULL, +// EXCEPTION_STATE_IDENTITY, +// MACHINE_THREAD_STATE); +// } +// #endif return 0; } @@ -260,13 +211,6 @@ void * vm_acquire(size_t size, int options) return VM_MAP_FAILED; next_address = (char *)addr + size; -#elif defined(HAVE_WIN32_VM) - int alloc_type = MEM_RESERVE | MEM_COMMIT; - if (options & VM_MAP_WRITE_WATCH) - alloc_type |= MEM_WRITE_WATCH; - - if ((addr = VirtualAlloc(NULL, size, alloc_type, PAGE_EXECUTE_READWRITE)) == NULL) - return VM_MAP_FAILED; #else if ((addr = calloc(size, 1)) == 0) return VM_MAP_FAILED; @@ -312,21 +256,6 @@ int vm_acquire_fixed(void * addr, size_t size, int options) if (mmap((caddr_t)addr, size, VM_PAGE_DEFAULT, the_map_flags, fd, 0) == (void *)MAP_FAILED) return -1; -#elif defined(HAVE_WIN32_VM) - // Windows cannot allocate Low Memory - if (addr == NULL) - return -1; - - int alloc_type = MEM_RESERVE | MEM_COMMIT; - if (options & VM_MAP_WRITE_WATCH) - alloc_type |= MEM_WRITE_WATCH; - - // Allocate a possibly offset region to align on 64K boundaries - LPVOID req_addr = align_addr_segment(addr); - DWORD req_size = align_size_segment(addr, size); - LPVOID ret_addr = VirtualAlloc(req_addr, req_size, alloc_type, PAGE_EXECUTE_READWRITE); - if (ret_addr != req_addr) - return -1; #else // Unsupported return -1; @@ -356,14 +285,9 @@ int vm_release(void * addr, size_t size) #ifdef HAVE_MMAP_VM if (munmap((caddr_t)addr, size) != 0) return -1; -#else -#ifdef HAVE_WIN32_VM - if (VirtualFree(align_addr_segment(addr), 0, MEM_RELEASE) == 0) - return -1; #else free(addr); #endif -#endif #endif return 0; @@ -381,17 +305,11 @@ int vm_protect(void * addr, size_t size, int prot) #ifdef HAVE_MMAP_VM int ret_code = mprotect((caddr_t)addr, size, prot); return ret_code == 0 ? 0 : -1; -#else -#ifdef HAVE_WIN32_VM - DWORD old_prot; - int ret_code = VirtualProtect(addr, size, translate_prot_flags(prot), &old_prot); - return ret_code != 0 ? 0 : -1; #else // Unsupported return -1; #endif #endif -#endif } /* Return the addresses of the pages that got modified in the @@ -403,20 +321,7 @@ int vm_get_write_watch(void * addr, size_t size, int options) { #ifdef HAVE_VM_WRITE_WATCH -#ifdef HAVE_WIN32_VM - DWORD flags = 0; - if (options & VM_WRITE_WATCH_RESET) - flags |= WRITE_WATCH_FLAG_RESET; - ULONG page_size; - ULONG_PTR count = *n_pages; - int ret_code = GetWriteWatch(flags, addr, size, pages, &count, &page_size); - if (ret_code != 0) - return -1; - - *n_pages = count; - return 0; -#endif #endif // Unsupported return -1; @@ -428,10 +333,7 @@ int vm_get_write_watch(void * addr, size_t size, int vm_reset_write_watch(void * addr, size_t size) { #ifdef HAVE_VM_WRITE_WATCH -#ifdef HAVE_WIN32_VM - int ret_code = ResetWriteWatch(addr, size); - return ret_code == 0 ? 0 : -1; -#endif + #endif // Unsupported return -1; @@ -441,17 +343,7 @@ int vm_reset_write_watch(void * addr, size_t size) int vm_get_page_size(void) { -#ifdef HAVE_WIN32_VM - static vm_uintptr_t page_size = 0; - if (page_size == 0) { - SYSTEM_INFO si; - GetSystemInfo(&si); - page_size = si.dwAllocationGranularity; - } - return page_size; -#else return getpagesize(); -#endif } #ifdef CONFIGURE_TEST_VM_WRITE_WATCH diff --git a/BasiliskII/src/MacOSX/AudioBackEnd.cpp b/BasiliskII/src/MacOSX/AudioBackEnd.cpp deleted file mode 100644 index 65a8cb5d..00000000 --- a/BasiliskII/src/MacOSX/AudioBackEnd.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* - * - * This is based on Apple example software AudioBackEnd.cpp - * - * Copyright © 2004 Apple Computer, Inc., All Rights Reserved - * Original Apple code modified by Daniel Sumorok - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "AudioBackEnd.h" - -#pragma mark ---Public Methods--- - -AudioBackEnd::AudioBackEnd(int bitsPerSample, int numChannels, int sampleRate): - mBitsPerSample(bitsPerSample), - mSampleRate(sampleRate), - mNumChannels(numChannels), - mCallback(NULL), - mCallbackArg(NULL), - mBufferSizeFrames(0), - mFramesProcessed(0), - mAudioBuffer(NULL), - mAudioBufferWriteIndex(0), - mAudioBufferReadIndex(0), - mBytesPerFrame(0), - mAudioBufferSize(0) { - OSStatus err = noErr; - err = Init(); - if(err) { - fprintf(stderr,"AudioBackEnd ERROR: Cannot Init AudioBackEnd"); - exit(1); - } -} - -AudioBackEnd::~AudioBackEnd() { //clean up - Stop(); - - AUGraphClose(mGraph); - DisposeAUGraph(mGraph); - - if(mAudioBuffer != NULL) { - delete mAudioBuffer; - mAudioBuffer = NULL; - mAudioBufferSize = 0; - } -} - -OSStatus AudioBackEnd::Init() { - OSStatus err = noErr; - - err = SetupGraph(); - checkErr(err); - - err = SetupBuffers(); - checkErr(err); - - err = AUGraphInitialize(mGraph); - checkErr(err); - - return err; -} - -#pragma mark --- Operation--- - -OSStatus AudioBackEnd::Start() -{ - OSStatus err = noErr; - if(!IsRunning()) { - mFramesProcessed = 0; - mAudioBufferWriteIndex = 0; - mAudioBufferReadIndex = 0; - - err = AUGraphStart(mGraph); - } - return err; -} - -OSStatus AudioBackEnd::Stop() { - OSStatus err = noErr; - - if(IsRunning()) { - err = AUGraphStop(mGraph); - } - return err; -} - -Boolean AudioBackEnd::IsRunning() { - OSStatus err = noErr; - Boolean graphRunning; - - err = AUGraphIsRunning(mGraph,&graphRunning); - - return (graphRunning); -} - -#pragma mark - -#pragma mark --Private methods--- -OSStatus AudioBackEnd::SetupGraph() { - OSStatus err = noErr; - AURenderCallbackStruct output; - UInt32 size; - ComponentDescription outDesc; - AudioDeviceID out; - - //Make a New Graph - err = NewAUGraph(&mGraph); - checkErr(err); - - //Open the Graph, AudioUnits are opened but not initialized - err = AUGraphOpen(mGraph); - checkErr(err); - - outDesc.componentType = kAudioUnitType_Output; - outDesc.componentSubType = kAudioUnitSubType_DefaultOutput; - outDesc.componentManufacturer = kAudioUnitManufacturer_Apple; - outDesc.componentFlags = 0; - outDesc.componentFlagsMask = 0; - - ////////////////////////// - ///MAKE NODES - //This creates a node in the graph that is an AudioUnit, using - //the supplied ComponentDescription to find and open that unit - err = AUGraphNewNode(mGraph, &outDesc, 0, NULL, &mOutputNode); - checkErr(err); - - //Get Audio Units from AUGraph node - err = AUGraphGetNodeInfo(mGraph, mOutputNode, NULL, NULL, NULL, &mOutputUnit); - checkErr(err); - - err = AUGraphUpdate(mGraph, NULL); - checkErr(err); - - size = sizeof(AudioDeviceID); - err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, - &size, &out); - checkErr(err); - mOutputDevice.Init(out, false); - - //Set the Current Device to the Default Output Unit. - err = AudioUnitSetProperty(mOutputUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &out, - sizeof(out)); - checkErr(err); - - output.inputProc = OutputProc; - output.inputProcRefCon = this; - - err = AudioUnitSetProperty(mOutputUnit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, - 0, - &output, - sizeof(output)); - checkErr(err); - return err; -} - -//Allocate Audio Buffer List(s) to hold the data from input. -OSStatus AudioBackEnd::SetupBuffers() { - OSStatus err = noErr; - UInt32 safetyOffset; - AudioStreamBasicDescription asbd; - UInt32 propertySize; - - propertySize = sizeof(mBufferSizeFrames); - err = AudioUnitGetProperty(mOutputUnit, kAudioDevicePropertyBufferFrameSize, - kAudioUnitScope_Global, 0, &mBufferSizeFrames, - &propertySize); - - propertySize = sizeof(safetyOffset); - safetyOffset = 0; - err = AudioUnitGetProperty(mOutputUnit, kAudioDevicePropertySafetyOffset, - kAudioUnitScope_Global, 0, &safetyOffset, - &propertySize); - - - asbd.mFormatID = 0x6c70636d; // 'lpcm' - asbd.mFormatFlags = (kAudioFormatFlagIsSignedInteger | - kAudioFormatFlagIsBigEndian | - kAudioFormatFlagIsPacked); - asbd.mChannelsPerFrame = mNumChannels; - asbd.mSampleRate = mSampleRate; - - if(asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) { - asbd.mBitsPerChannel = mBitsPerSample; - } else if(asbd.mFormatFlags & kAudioFormatFlagIsFloat) { - asbd.mBitsPerChannel = 32; - } else { - asbd.mBitsPerChannel = 0; - } - - asbd.mFramesPerPacket = 1; - asbd.mBytesPerFrame = (asbd.mBitsPerChannel / 8) * asbd.mChannelsPerFrame; - asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket; - - asbd.mReserved = 0; - - mBytesPerFrame = asbd.mBytesPerFrame; - if((mBytesPerFrame & (mBytesPerFrame - 1)) != 0) { - printf("Audio buffer size must be a power of two!\n"); - return -1; - } - - propertySize = sizeof(asbd); - err = AudioUnitSetProperty(mOutputUnit, kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 0, &asbd, propertySize); - checkErr(err); - - if(mAudioBuffer != NULL) { - delete mAudioBuffer; - mAudioBufferSize = 0; - } - - mAudioBufferSize = mBytesPerFrame * mBufferSizeFrames * 2; - mAudioBuffer = new UInt8[mAudioBufferSize]; - bzero(mAudioBuffer, mAudioBufferSize); - return err; -} - -#pragma mark - -#pragma mark -- IO Procs -- -OSStatus AudioBackEnd::OutputProc(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *TimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList * ioData) { - OSStatus err = noErr; - AudioBackEnd *This = (AudioBackEnd *)inRefCon; - UInt8 *dstPtr; - UInt32 bytesToCopy; - UInt32 bytesUntilEnd; - - This->mFramesProcessed += inNumberFrames; - - dstPtr = (UInt8 *)ioData->mBuffers[0].mData; - if(This->mAudioBuffer == NULL) { - bzero(dstPtr, inNumberFrames * This->mBytesPerFrame); - return noErr; - } - - bytesToCopy = inNumberFrames * This->mBytesPerFrame; - bytesUntilEnd = This->mAudioBufferSize - This->mAudioBufferReadIndex; - if(bytesUntilEnd < bytesToCopy) { - memcpy(dstPtr, &This->mAudioBuffer[This->mAudioBufferReadIndex], - bytesUntilEnd); - memcpy(dstPtr, This->mAudioBuffer, bytesToCopy - bytesUntilEnd); - - This->mAudioBufferReadIndex = bytesToCopy - bytesUntilEnd; - } else { - memcpy(dstPtr, &This->mAudioBuffer[This->mAudioBufferReadIndex], - bytesToCopy); - This->mAudioBufferReadIndex += bytesToCopy; - } - - - while(This->mFramesProcessed >= This->mBufferSizeFrames) { - This->mFramesProcessed -= This->mBufferSizeFrames; - if(This->mCallback != NULL) { - This->mCallback(This->mCallbackArg); - } - } - - return err; -} - -void AudioBackEnd::setCallback(playthruCallback func, void *arg) { - mCallback = func; - mCallbackArg = arg; -} - -UInt32 AudioBackEnd::BufferSizeFrames() { - return mBufferSizeFrames; -} - -int AudioBackEnd::sendAudioBuffer(void *buffer, int numFrames) { - UInt8 *dstBuffer; - int totalBytes; - - mAudioBufferWriteIndex += (mAudioBufferSize / 2); - mAudioBufferWriteIndex &= (mAudioBufferSize - 1); - - dstBuffer = &mAudioBuffer[mAudioBufferWriteIndex]; - totalBytes = mBytesPerFrame * numFrames; - memcpy(dstBuffer, buffer, totalBytes); - - dstBuffer += totalBytes; - bzero(dstBuffer, (mBufferSizeFrames * mBytesPerFrame) - totalBytes); - - return numFrames; -} diff --git a/BasiliskII/src/MacOSX/AudioBackEnd.h b/BasiliskII/src/MacOSX/AudioBackEnd.h deleted file mode 100644 index 455d42ff..00000000 --- a/BasiliskII/src/MacOSX/AudioBackEnd.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * This is based on Apple example software AudioBackEnd.cpp - * - * Copyright © 2004 Apple Computer, Inc., All Rights Reserved - * Original Apple code modified by Daniel Sumorok - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __AudioBackEnd_H__ -#define __AudioBackEnd_H__ - -#define checkErr( err) \ -if(err) {\ - OSStatus error = static_cast(err);\ - fprintf(stderr, "AudioBackEnd Error: %ld -> %s: %d\n", error,\ - __FILE__, \ - __LINE__\ - );\ - fflush(stdout);\ -} - -#include -#include -#include -#include -#include "AudioDevice.h" - -typedef void (*playthruCallback)(void *arg); - -class AudioBackEnd { - public: - AudioBackEnd(int bitsPerSample, int numChannels, int sampleRate); - ~AudioBackEnd(); - OSStatus Init(); - OSStatus Start(); - OSStatus Stop(); - Boolean IsRunning(); - void setCallback(playthruCallback func, void *arg); - UInt32 BufferSizeFrames(); - int sendAudioBuffer(void *buffer, int numFrames); - private: - OSStatus SetupGraph(); - OSStatus CallbackSetup(); - OSStatus SetupBuffers(); - - static OSStatus OutputProc(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList * ioData); - - AudioDevice mOutputDevice; - - AUGraph mGraph; - AUNode mOutputNode; - AudioUnit mOutputUnit; - int mBitsPerSample; - int mSampleRate; - int mNumChannels; - playthruCallback mCallback; - void *mCallbackArg; - UInt32 mBufferSizeFrames; - UInt32 mFramesProcessed; - UInt8 *mAudioBuffer; - UInt32 mAudioBufferWriteIndex; - UInt32 mAudioBufferReadIndex; - UInt32 mBytesPerFrame; - UInt32 mAudioBufferSize; -}; - -#endif //__AudioBackEnd_H__ diff --git a/BasiliskII/src/MacOSX/AudioDevice.cpp b/BasiliskII/src/MacOSX/AudioDevice.cpp deleted file mode 100644 index 9fe065f6..00000000 --- a/BasiliskII/src/MacOSX/AudioDevice.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright: © Copyright 2004 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. - ("Apple") in consideration of your agreement to the following terms, and your - use, installation, modification or redistribution of this Apple software - constitutes acceptance of these terms. If you do not agree with these terms, - please do not use, install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject - to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs - copyrights in this original Apple software (the "Apple Software"), to use, - reproduce, modify and redistribute the Apple Software, with or without - modifications, in source and/or binary forms; provided that if you redistribute - the Apple Software in its entirety and without modifications, you must retain - this notice and the following text and disclaimers in all such redistributions of - the Apple Software. Neither the name, trademarks, service marks or logos of - Apple Computer, Inc. may be used to endorse or promote products derived from the - Apple Software without specific prior written permission from Apple. Except as - expressly stated in this notice, no other rights or licenses, express or implied, - are granted by Apple herein, including but not limited to any patent rights that - may be infringed by your derivative works or by other works in which the Apple - Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/*============================================================================= - AudioDevice.cpp - -=============================================================================*/ - -#include "AudioDevice.h" - -void AudioDevice::Init(AudioDeviceID devid, bool isInput) -{ - mID = devid; - mIsInput = isInput; - if (mID == kAudioDeviceUnknown) return; - - UInt32 propsize; - - propsize = sizeof(UInt32); - verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertySafetyOffset, &propsize, &mSafetyOffset)); - - propsize = sizeof(UInt32); - verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyBufferFrameSize, &propsize, &mBufferSizeFrames)); - - propsize = sizeof(AudioStreamBasicDescription); - verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyStreamFormat, &propsize, &mFormat)); - -} - -void AudioDevice::SetBufferSize(UInt32 size) -{ - UInt32 propsize = sizeof(UInt32); - verify_noerr(AudioDeviceSetProperty(mID, NULL, 0, mIsInput, kAudioDevicePropertyBufferFrameSize, propsize, &size)); - - propsize = sizeof(UInt32); - verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyBufferFrameSize, &propsize, &mBufferSizeFrames)); -} - -int AudioDevice::CountChannels() -{ - OSStatus err; - UInt32 propSize; - int result = 0; - - err = AudioDeviceGetPropertyInfo(mID, 0, mIsInput, kAudioDevicePropertyStreamConfiguration, &propSize, NULL); - if (err) return 0; - - AudioBufferList *buflist = (AudioBufferList *)malloc(propSize); - err = AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist); - if (!err) { - for (UInt32 i = 0; i < buflist->mNumberBuffers; ++i) { - result += buflist->mBuffers[i].mNumberChannels; - } - } - free(buflist); - return result; -} - -char * AudioDevice::GetName(char *buf, UInt32 maxlen) -{ - verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyDeviceName, &maxlen, buf)); - return buf; -} diff --git a/BasiliskII/src/MacOSX/AudioDevice.h b/BasiliskII/src/MacOSX/AudioDevice.h deleted file mode 100644 index d32be287..00000000 --- a/BasiliskII/src/MacOSX/AudioDevice.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright: © Copyright 2004 Apple Computer, Inc. All rights reserved. - - Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. - ("Apple") in consideration of your agreement to the following terms, and your - use, installation, modification or redistribution of this Apple software - constitutes acceptance of these terms. If you do not agree with these terms, - please do not use, install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject - to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs - copyrights in this original Apple software (the "Apple Software"), to use, - reproduce, modify and redistribute the Apple Software, with or without - modifications, in source and/or binary forms; provided that if you redistribute - the Apple Software in its entirety and without modifications, you must retain - this notice and the following text and disclaimers in all such redistributions of - the Apple Software. Neither the name, trademarks, service marks or logos of - Apple Computer, Inc. may be used to endorse or promote products derived from the - Apple Software without specific prior written permission from Apple. Except as - expressly stated in this notice, no other rights or licenses, express or implied, - are granted by Apple herein, including but not limited to any patent rights that - may be infringed by your derivative works or by other works in which the Apple - Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/*============================================================================= - AudioDevice.h - -=============================================================================*/ - -#ifndef __AudioDevice_h__ -#define __AudioDevice_h__ - -#include -#include - -class AudioDevice { -public: - AudioDevice() : mID(kAudioDeviceUnknown) { } - AudioDevice(AudioDeviceID devid, bool isInput) { Init(devid, isInput); } - - void Init(AudioDeviceID devid, bool isInput); - - bool Valid() { return mID != kAudioDeviceUnknown; } - - void SetBufferSize(UInt32 size); - - int CountChannels(); - char * GetName(char *buf, UInt32 maxlen); - -public: - AudioDeviceID mID; - bool mIsInput; - UInt32 mSafetyOffset; - UInt32 mBufferSizeFrames; - AudioStreamBasicDescription mFormat; -}; - - -#endif // __AudioDevice_h__ diff --git a/BasiliskII/src/MacOSX/BasiliskII.icns b/BasiliskII/src/MacOSX/BasiliskII.icns deleted file mode 100644 index b26870dd94b59d5f08b0047b5e4a87fc752c8450..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44909 zcmeHw30zah_wNKyKoC$-aM$+NR$FV`mAZnW1uH^O)VLv_C{cr;f`F2Zkc6-%Y#KHN zR0MGYH!NDMiXv_ZuAqP-Zn)H1t@ge%_a-4B0e|+rKYreOjUNPZ?|jdhGv~~ine*jl zh39I2gz{H8Om_MbA(|1PeEkJK)VJSHq#^yk$0Pl_W8llT@BO>?*!uVG8R*xZG|)e3 zXP|#Z59tfqBf}^IWGI0z)8p`U@~)vN&0XJ=Hp$SKGb!BY-fcr8+H*q*?YN;t|F|Jv z-`(((em}$7GjE6&=id;2P9%uG6>^dCWoC^KypQ00_@?XYZ+QRjQ0nVFe18wOee?_8 zr~H~o6tnx1UlWn}-{#2ty%}1ua`-TWjJK5_y*0!d4x%|4#v#k)#IrsfzIt|He-h>p9v2id=tDGM%92aqeN@GTYxP8# zgvUnacR;QqgO4v}c{1y(*!9L$08mf7DUbx=wt5VDFo!T~%%bOEWL~`?Q6F*>$X7F;)I z^pw#hxG_L)h5QPFI8FC=1Y9tv z>=;NPjndJ1a9YEBI$-<jk2NF|829hbX){dlO{!}E*lla@|iX=}@GLqVpjhPI#zad=}OWl}dWGq?9`~jKi z=_&E|_auXVXmkilg#nBWFGMKJZC^QmC+koY@N!Nh>eieNIYs%I*KiNR;u z;b8g(3~i^3CK*E!O<+ztg*SUjn2uC54Xt8iDWVCkJ1U~dQwH`?L=#gPO&-vQiYB_F z4C082COb!EG>wMfQbZF&=I^M8CQtBpDw;Y=pzl;PGjT`AXsYm3MUypnk0TXMU>-** zoILreaI%^N?^5C9$@f%*lYdh<^@Lf5iYL&Hil;ofT0DIv31;AU8WZfIh$lv0DxPd* z!HmJEZ}2>2Jo%IHWMV#V9{8*0*Z(M>%u#zqKpC4MGYBZNe*Fdt5Y4Ki2pN!p6oERa zLZ}}k6)Nu_Ro;OVs?0m6n~fq~ED%!0OMmDu#ETJ9#0%W79WTh5iWfRUL$%_?=rk&z z;ss_a9r0p=sCY3$$VOMZAU?zk59vrd1&9ikZU|ZH3YPu@Ay{}wAA-S%jSQ_-kz$Ax zk-~-S0$Pg7MW^AO)IDu^fNLOSV zq|7!*86JFO?Mdbugy>Xk$iW!OT!Z?uQD+<*R>({d8>kx<8$$qfFfvDG%Gf~4Tw@41 z#_H2UW967tOa!)7t`z@IeD^0{6^szkUndxoXzXu2u(7Oy;0Fiu;a@Pnz(yq>*31L@ z(`7PPeyY7}z{WOwxEbE(%THI7WvN|+A5RxRuxY-f`P;G9ufO59e!apDp{y<}PVughMbqUKYw=diJqOlyw`0zuN`xm9v_0L{BeEj&u+YiJCF44XwBxJs`vrjt2 z(k{5e^nFfw&Epr3>mStJyZ7QCkpuF~{(|?OynK59UR6c;r7N!w60{tUiE_5WMT_@2 zrEu}tgX+pl=T06k{`Gkwq4&P#K5PJLGT?eAkO-IS@7}n0=9j{~`FjpF7831WKYaA~ z$)i_ka6^~BimMx5K7CMKQFf~6K<>`%+jGfV?$_O`sk&F63b$CkD6fD1(X6>_+#+lSJcXAKSaZeITF=)PUq+qPxx+;jNkh1YP~ zg`-Cg79Kiwb_?8Q_5NnV%lg_|SI!>WzblKn>(}$w?)-UxFnX1pm6?%|nR_T4#gw5( zVMO;2*Up_e^~=HC*>aggz~c$TF^TEfy9VtGiclE!-yX5 z_M~i1h>hTftXsWe+0tb`taTw=VN_f~viu@6i53dOg`(J$eB4BmLEHa(7}4`tjyy>g z70wRu^;zcSwS1*t5JwmpmzXS1O+B}tKo>b&1Acf+Dk&x+gZ9h2FrwG*+qNXeM(~3D zS1$AP@LIll{U(6~3rS5&Pd~JuFizXFiOuE-W49f|lEfM4lz^~)m!B+)7P13a%RQGY z@mjHF14k4SkK1t4QQkfRHL^q7Z({Q!5_5`iD^UizBp|Hb?M{l5goXGsmo8bn#Ea=4 z5+;dD+L8i|*cs^cUIHD&%{YSS)V*hMGhqh09Zq!Joe(SLZ17#~v3QaD(v|Brg-6FH zr=+sexfwLU**yg9O&By|^F*?&qZe_raH`qy_~`IW>sBpwU%1eH>8b#>C^i9P;btAB z&T#~Br~JmXUoy8OMaup3f>Yn}2->-g0K^H4OwK(~fq?`hkku7gWLSuwkLRKV3l=Y1 z9l#NT(%3rujE+p_`DJ2=Jj5G&`VRD?!W)@yMy+19I8x$B27`S0W zQV@~?R?fOmHk-2S?FNj+11urYHBZD|ztU?VWA40#UaJC0DCikcPL9H zy$xD?+MnptL#l%WwvUphndJKT41?+G>PY}6f_sJU%USL2D zM8R7Cd=$QE?TRG}=DPhj&UTuUTN5BC*g35B?(M6m59e-61u0uIv$DsI<&2Bjg^u!w zjyt46NqCq@x~=fS-DjkZoD5ViBrH=m`mITag(Mx&0ZiSH3U}^aGg69)!wVV ze(|@W!u|UX6dpW$#OifEOBimhuCp0Sm^0@r^7LLoBEq49Np&0V~F?d$~}%a;43N06>eTUf!X6V>vZ zqiWF;(Bx(L>4J@2=o*Ki+%i-|6WmMxq+i%y?4chT~-90^#!hl$%l7$QL| z)%F>*eN=w>KzdBLEMwo<+YMksAtcsLZ~PX|olU2^!ho+=qjk3OLSSGTc^Dhw4G@tIBhSvt*+1 zlzbdj*kI5$0D9}<0%Di>g+|D>tf1OrKM=%GO`k*4+N;0qON$nYw;jaMQwpOlCOV&9 zG}o2xLI+E&+8~Hc!jUbZ?7Vw>9eNMizP)krm)ztCVPwwnE42@6NQs?7=gp>Li3`2K zNC{iO@gkMVX4jzxY@mvggIO}MC~jZLt%k;OQd+0$q@p0rV|9=)E;%JVJxXC(5cUe2 z=FXLqdsCxD5lKfb-FsY5nnrKSTvxV>iR&B~5pHCH98?5hq)#eTe09C-SWZ%eC?@sf z_4{BH+_O%v8CXS9Rxro{6+ss10-z!Gy}D~>3%5zd5%F22cb`3`?4kFo8!5|e;qrCd zs6;Faw}Me%RzS1YpyFS*F8`V@j}}MC^U7;qQTDJ1RLWWfvNnUPXsTaQ&=3d8)9a;0 zI}#-k(yaw5Yv?`3vP{8<%hqzBUs=Cgs$tjb*IfE#yC8#{Y0z$v3EpN_eeHC?R%wJJ zDd(8dDzw5`92cWmbC;|P3QsP6DkSutp4tu>K-t4LAocalODA^Aqa$Kd_nxX(I16n( z2sNb7Ua-`Uefm!cL3?|NovxRW0ewVF5QhV!q4NBZ?FkaF%;9rSl$Loti_Ugw=Q?Mx zPxA8^g7#`3JDrLOX!IQ0tIPm)t{t#s07P% z6R-)BKli1irlxF8jEhWdh#-t!uW*>oslHcJn?bt2*ohi(eMaIZ?pSX1M zZVd^+ap{U3AW#6yrDSOYC(xJa?d9pQBs_vJ-Y?22JW+D-YWX!$MGP4#7B6t9q{K$b zG7HaKyK}GhFLH)02Q^&4aaV3Nkhhu0dmBw=&1EP}nBwQ9BR+JFs#>-o^1tdT!X zvUdPy5W=JnKydWm=`FZu!B$yhT-x4KS8jo|NQHXsAd$c>ylC7lF+0G2Z9oVoOd#O1 zFNg`_mqSO6wVmoXW9Cc�c~aVyn}Wo0pF7md8XTWF0E0th!fQr@(S{#?#`8fUwx) zEy*$oe^baNo-i^dE-ofA0n}m*9X)>XPt%<+loZs0Ila?89BzqGG4i}(@Rb?`l+_L} zlk42Y%pjq3a|&M23k0IbxP&BjvR*=54d|6Wc=(tJQ*a-{oJnIr7t2q6zjc_GWzNeF*pzGLgHd#@sQ^!hD&5J z2JLXhcyas6seS3vsCb2svFi{y5+)=X9@LoR6xfZxj)aq;pPrsp23Wt~3=|@gLE^$# z8GwaTT^+1tcWsG@*}RK#G<7T()aC18P*Vl4yw^)lF9evYkds!d=f@QW=fonpp&cHq7?xG(kigUgXI;`;dkh@mv5*fK^}`&D1d@H_T<*( zlY7#n(Fxgb@!%8#IoGfgpjUUjm?wFkyN5u_F_?7)Ss>IE4ykI833-;$oB@r35nB zfr0SE5Wgih9OJ98bT1_qM?8s8bs2d}Dfn#;@FkrXRSS4>_?I8zNc*knlsVy2id_nSOr>hxKQR|d?* z>MdLt;f!!MkL);e`oLCMY@))i_+&RBUKN8VmTgH(=VjZ016wIn}OV}W_14RUZfhrh>Sqot*7CN_Q3NngH>hRLz5oG!O8M3(K z9XQ+7G(n}{aPv__3M}NLBEs|rXft}Ot%K_VfMLUKjwz64>@F&)0N;5JKK0=)B>p_P zRF5ODoYM!C&eWw zW+j0Vql)wyaw5TtL=j<5P4i1uZ;bFHF~n5(KOpBdnRJU{E}{_dFkvTI2eTTv$^-x@ znI|*=K0rU-;hlLd^do&QEPWuYs1P71=P&igvn;u~%>xWSoE_$Qur^7&u(Jq6RK!0c zXR<_T68K65B)M?th8Rp?vfpJE%={47FdKtiVSj7!JDJuQ9*_?yd%8>uc=dID(_ICRKfkr72^UZHE=Xq;sP+_Y5>6J zW0)cs1V|C)FRLNv@7OF&%%WCCU@OoC`r{9&z>h;_IRJSYP9QNX^OXUy0w*hg!1>_; zIQ@aG2{O6DK`?{_fvXZ7j!}k<2g62YgcGz!*frQ*f4HRzU3I+yI_}9bTsN6!2ouhE|N#*{Mh- z;BEi}r-piecwi*3j5jt|N*qpm07SV9>;Ti_Rqmny%J~z3Uc1kSm*9_-jdN*>-?p^8P}9gQ@;_e*fBu-P^Y9K5^~-^FQ9clVG5n>enK| z_&Po&CC?K?NI-Ocm=Po3u*u`XU#{Z4CMpI?6?5S5-~2dB@1@ zHqha6?mv8oyOg{YpQ${<8+QR=ab z*?Uis+wU}F5L*818Cb@sCOPk9WzDPm#R5R-^ssnGf|$qQ3Zhf?oVt#WF8~I*#Ks+Z z|D^uT`9nLl?KpJd4nCepM+U|BA3nk;6`2Pwkh<`(RbE{_oGBIZxO`DU_R$N~cjog#hY8&c{c^KzSRmuLeXgIjX z$LFW7KX_S_!$s&Oc(o5@;3qYgi*mPRA2>@Ml5IupitoRwulfsc>W`OJH9W7*;Q&sT zcMmE~<|a$R;H)!gN73b)r=So3;i0Mlb>2U3xP7J|d)v+<7pk8&lx{=qL(88$tGbS@ z{I06}-jgTgFeHHU*VC$t&@)jOKH)4Vx$y|>1N9j^Si1n{{=?cU$MZ8Y^H1Wl%A8Ep zKBxM{quZrVL`1v48ehDA^B0s$-o3nE`P<%QE*V8HJYCKdP-bb>(dWVfpUaGw`YGL`k?PddtpZ7w^_L-pqm0(E_$} zmo-3{{P2o2ZDz)7`Oc4VAW{k-80%s@HUq6w=HuWFt>s=s*_!YoP>os?C0 z_Ik~u27IUo&5wkZH#XcVDa_uw{y0o`MtL5e>z;XiyFYx^?0B-ptLh5@EO~QYz2h zd-%kev**s9EIP0=V@pzU#;!wWuK`R=aU3AjynJx;!mq`rE|adAhrR=Zhjn+ZoGQ#o zPmF~F`l#5%^zC_j3knYG*_D-^B2UZSd#vQf{b$fVG!CqJv+>!z>z6KHt9tOTzBnHZ z3@vYX*-%qi^2@#*X^GO9=oo22aw;6jXKu?#Pv4rIcktxJ+qF+|YbmrYt$+EjwyL`B zQN!c%&^^dJwDkUqXSkGBv~TCO)XhokL`$e9!E!e+6d&B1yCaLety5<9_MN$V3X4vjzfx6O{}S#?0`Gxx<>SZo zP{urfz6ix2PafU7eXZ>5ug8uaEGR5Ec(~~JsdJYr?$kCkJgX@U-HZ%FbBaq#i*rIV z)at3Ywo27h4T_}h?nTPFs$q5bn4jmb@Ep@rUNt`BZnG>hM!3=2zNyY?cE){bkW3mA zvC-A_ns&jp8@>$1z^IM%aWb8y*RQHq!5wfw;OAtYUZ-iv zuNW#k_D z6P7^(NyrTMvlVDYH=n62>h_XO3X;Y|iZG+9nNakd|fukWYV};c1%{RSxmH;8?<)Kkn74C@Hf&)Y-x-{z?rqOPDd?x z7H%6O5ebEC5nqf%Jh7fgERu+6A~9QJCKPaj*ZaBosEWnkRJ*&&;-ba8K!-S;MdLYu z7Z(YMc~fSn*`|;U>->DjC#j0a-xf^?lEp=dxa+6v(p^ku;Pw&R;Pvac>uCW2?Dg#f z)|3A@@auYZ01v*ptcSPOuUqHu=j%OIz3@E9e?}z0hqKq&?QWs^9Oy2S#fsU1{(fuN zerQb$e1*Xm*N?r1?Q86`ShFxaXtRSi?oW6qbF8SP>hw|yGQe+#FPmjNgsWMo9vopC zM4Duik9|yw)#_FAKrK;dfS+#~iw`g~x9OU->mNew!)4M~N!X^<6B1f3VDqMuIP3j< zQ(0Yo*ZBEEKYe{!tnoh0s@h+yn-PgUiWlNHQP^T_+c?e!<84~M#&-vc<~_Q3mAn5k zSL_X8p+UYA1ufUQjedxfMuSI_C=QI~Melxd!Kb2x+>n5^Hi8yw-$sJb{?d@uvz({0 z$0Hm0AiW{BOfE~0IU=xmHN4;4RiqaLt@oe0rnRED-NZq|MzNTyS<5_^%Kh|LFPOsQ zu=L!fYL&&mpb$ehtX)H2&{}oe$w9q3PMffZ!!jMQLaRRBckwcr6!-*yw|LqomC4Z{ z4y)s$3EGwNzUy2ekVPDTTsd0uNd%{mc1$LUPH=vJCX!yCkNNacJ1u`an`Pl`t5t0OqAUZOJ2oFg|z^2e0Sfj96dh|(f zCfJRl4@i7%huAvJU%Y4$!^w7t-MY<9Gy=J&wrNtvK8iO+spX`^OjT0QgnNXC1 z1*7dfe0@1d3X(Gp^r|aB>BkU(jn%EG&Q&+}_`5^%?ad2419z&XV5#&ta z=Bq`FFd78$5sAZ`&FVk?C-U&0;pw?plOyrthL{Nc#`XSSPGhGLO=Jl&>}b|Fw8t0RtL8s8q|uec&?!bYjZ35NpYH0%vXy>fzG;U79CdDtx_(-I4q+P z<1`2tWQ2AaQKC(`7`h6tR1{P4qLGxLb+Ip2*eF*tFog8MnmmkdY4+HGbr3O(a84$@ zgU$NdX#$C_o0H*y_dWugq1dbr%t6iA8Qt)dWiQu3&!8qP$kx#A8>b1aFf~HRbp{W6 zD(rV{zt<#fkWt-vNVyK$2I-9w${Vdg1g@#-VsMxw#KAFvB4VKzZiAX}Ijr!+=H{!5 z%t6XfxaK$Gf1*ZNH?LzAI9nW0lyQ$cG6(Bmcv#`3jqMIy6c0)co|4%tD@u+owueb- zO589wVIf@u_JTGuw0R%a7e?T4&`JEjVyKxProZvibaOyV(o&{vfcwbv12)Ul!A^?} zLQW9$V4ZXjN(L2lrj(3k%n(yxhIlQ;*5bm}2PC-tsKpT>r^*o}I!Pi538YVw5->GD z#TPM2Pv_W!jiSO}=?dVBMrtufx}LDXfuWl^LZXX8Npv%;zXpq>dwTjHDL4~(`~c~5 zaC1HhX&QUEPC|(idJS}%G(WC2s&Pv|bz64R2z3}lmH5?ICgdDC|#RdeyMQVSsfZ_ZQcR#7wzlJH>NJQWI_ ziZFF}6=lVkr|=r=k{DhwI7;$Lcapqf2U9A2tWNfdx&$+|4p2lEQy{VgVhPa#(l5Qd%rW!@O$qlTJ^5f47ovRCndebc=1GVP*{&)@3#UeEf8J0It_s!7_OV? zf)fO+nW(YW6rv!#7^%Vl`|@}#{);8Hl*2-u1Q;VoZ#d!mL&h~7q;Mn+E{rvx%VHJj z)n>Q`Eyi->A{J}NHJ!W|BS_15TJgikLuOL(qd}3OkjXPh7Hg0uTc+DWrT`{S#!{Vh z8Ka^Z7#n;Wj<@jWslp4Y+I=YI45>Cu9(XII09SHodQco1oNH`%=p@k?!Ty6<=z{=< zNqFLE;?s1OQrP(Ll;ttFWnvAUIhmvH>Lk{Hi{hOgZ0R9K(Z{Ly5+uE)x0--O!*sB1 zEb+8S57tSy0f&JMOGR%-kKv?itC%-v5L;$N?uKA3N+oJ_3Jp1B+WexEgkww%C>R}7 z24B%2SF~(qAOqD?t>n8SCgInWR$0mjYk)PE`KD}4Z!`Ik& zM{GZtTqbIgeaJnb?GBx6A8ZNmHcDd$TMgn*_hqnrhBJKZ%n+v91R%UQ1TWS}0I~+3 zfGH5q9}o(|HMl_C;fxPXi8jEG{Ef)q}ylM`f(w~8v2ZKkX9gG}t$pztP`5m~m= zv}r<0AJ)YavI>C10HuZ9epDw6nGC{fMmRr&^9CKnA)M~92kRmZS>IAqmO0Etok3*E zhdm8-MQ^fE^ESAzR6Q z>eV=V4JQ}=84wIvEVRQ|Z-fq`&9 zH#ML|Qj}#Xj2v@}7A?A zX`};d@uYexcv9;otiopxIG$NdH;3`#ZRy@Dwy)JnC)bOuu%{eG4jQ!bVRQDBxq>~F zHphku1$#eV5zE@!X>8o5@~F&|JgO*{VL#9J@fEOoded#~rS+dksIq7xR7sZoJaXiC zdyZ3Y+wnuDa0~x;X;p!%z2>_wTN%3z=q>-!s{TKtRpoA+Fd=U7)P~GtvY&Kzn)5eYR%yHwU zQxvM|qw$RA?tM`(y9V~DoeC=B)LB5j#06u2K5 zFK)&QLS6!7Z4}xfBM3$AgNL~^=K&#S0kSgM)G`AIwcm@-wC2PgG(H@4-P9uEhbHL0 z2hj}IHRtz`&D>if_Q1no%(~8-y~u0++=cM83#L;$9-@7xMeD&pR+C%f^Gvr@=kuW6 zJY?df#pXfN;JJ!le-e#{hfI5Gb9j&!02zxuiM)e60n1UFx`VugsOzdvrR<>TT-4D* z2VsZCGlH@D>64i{s22cE)xp!DB^m=@&woJBK@mLEQK*BSg9ZqZ@2A#jvqQ+pUoo2Si zh(U+3skHbos012zZ-oYfys(ijG-tt}MIxj(wiWUVspu>%?hC30dF@-FypY~_K#TB# zHiEn_TjRMPH&C>f7R?3qf${jMWp)c0J{z^jE!Zx4rkb3V_|?wC*#q>4JFiYuiOw0Y1R8PfMukxs}E@zCO& zpux~&Bz{%}oM(NLfDEUocqKS2%zkaoDnXTEc-k@fM2sQu>`==A13E+@Lwgl@1o?q# z-)eD3kR0TgU^(>Jv*4kuhChliVD#DCAviS5E;Xlw;69>(2|_ z7}Fwhc z$rjkvJ6+bITEru(0c3GS7rO$UkMSkwWzmdNfkU(NY;8(KJnB83GP`aT#R4%hZKs1f zf#bIGW^L+3JnBZ`>0(R3voWG0kcquEM*^MUpf0_1P$c4!`8eII2zWBa*J5PygBBNp z3>FU^R0#NED-x?2`vE@}!wHc3YH=ROus@}P@<1WsYO#vt0FR+q4# zE^0$O>InL1uo>_(F;Itg%{dHYmn1qU43v4Au@*p;KHvdbTm^C(IHiNCfE9tFuc~~i zWGB$lhk-Uf<9@1h67W=DK3WGQAs(3yQxuQYSqQXrXMh>6EO{uo2V^=OrGt6^)*Ya# zqBlJYgMmSsa}3~F7{+X5(M}h~Km$ibD?ouHPBStA^(2g8(6KLda0$RbO&U@30sI_{ zRbpgD)@*f?22gi^o2ZjBfF}cUOI0V8Q~@+cjJl0$i6DTcgD08m<_F-p%2WeT`78`% zK1_=XfN)10by5Kk4h6*^YA^uc?e8?o{>TzQuIQ}#qm6L)&pL|z@U~`!AD)N70hnnz z3;ZY-CLb`c$}!cRh@k{hR`V54#J~%X%{q(uINOl=yCX)d+IFFlVfJCS(yj7pr&^9x;YvCg*waeq@^{B@BlHK%nlk5 z@KAJ%?{t^mv1LpkJk<*BC=yWYa9+@;vy+j(NoScId$h@aG^*%G!4cl-smunWx$tCM%o%M3E zOW$jh$&s@VbyN^yHJ^|19qB1L%j0-)V`8pR6-UFvky#I2<#5VhbXLRh61T%-^%^+p z1Ak!tqjvFI;V`;t-)I4R>_;EPfOV9*k-}qimAcU_=utZ-^$IuI062qmmbR5% zqocA-D_#id3{)>@RC?ORyrs!hW~ zG7gH6@j$hbG#U)2>^3b`qtQ{Acou3Eqw#|>yhX@pc~cD<9SuX4COcXzKcht)WOlxJ z^%*}b<2&3pVN=x^!5O@TwB>>`e(;8QAFX;bequ(IsSp``*;Hpn@-WmXu*DKHiUgzx ztqL=KYQ~WcfHbmI#}7fs7yXNqX57Re^eEdY1M-OYhFu* zWIZ303wk+e)se}kXXL|4p5ZrX%K9;h)n$H*wPRY%1W;>B^U^W(1dSZf%fxu`DMiT` z7j3%CZ?RmAl0mDM9->k7y$BhaICJ(N%4PKlLtVDCSRY2?0A`_9d06=v4Ns$Z)b)q+ ztyF?-O%Za^sst;aqmeu|4s|mN`P2fi>OmUfQBlac@5WCp{Hi@kL+CctJRJ4ty<*4z zZpqi*)79Q_<{WNP$-gDv|CgVnv6lSAl1XYGi~t{5@bBwi3;b(=|BEeP&^Ed|vx|$J zb%?SiG(Jg1#~uF%-s%@keg;sZHk2`Zt_yrv<^SkwQZWd@uWCdiUro|zTk-q&Q-uD< zUMlIt#i4q7`UVCD`g$~)LLBvJPyd4>&?LQ)qi@jO$k@cBgHbzug#vSN@Batw-!GpO z0RL65>C(=~#Jr1Dj~-tqUT!>IoX=*vGsvs|jrA=ixwDJYnm)AWzZxxzXr=VxCHn1+ zJ9g>Of8dZ2!$rz>KlyucbN6Xg4R__|UKQJdbhEC#2MnJ$eb(IBS3X&;s)0V~KCMbs zUK~=aXjQ#Lza2>L`|X%%bC&rBZ(M&}1^1~x>@)6QVq#*f6w%suwh}uU#vP=8_oL&2 z)uE9|Dan%C%1fX8eYI8h9zDCmhw6RoHRPfKyV};k$kej;w>Hxkt>MWsa(3rtME!I5 zeA^$(H$S+j=nYn9h4E*#mc zln$R4)|Rg)kDok!Qh)Q;)XyXT{Tq1w{`B_oq|YP&?++i||Mkb?%0kKKkq@5`{^76R zA6(e6@pH*1KD>Qibv#Ke{@T+0p#Sgxcyx7d`25e+|G(e8tT~ghPHp~c)BgYc;m@Zx z4o7>A`#k;s`)}-hJ2%pQ_&oC8zkmDuPH_@*@_#;${I~C3H(c2h#u(Z2^T_}GkLUM( zOY?Ue*yZ!cfA->0MPcNUv3=k}kd?2t^#A(DHRrN}oWJj;w*G5N`8D^iAC)bi^o2!x zW$)WI|5jC%?&7!&>u#d9VQN9y%$oXjXG6Wu)Bo!i_6iq{?q%9expxIM+Oq%U zzoxJM`Ma)0`kzUDSwXbd_I1ay;|@M zY17e%Q?d~~Ow_$Et&Qb74AAgCi#8Td{Me_X`rOBEYx#q_X?S0CTg(5v-bWCh*ZT-U z!~2l(kf-fNLBspnI{2ZR8r~P(cKudLQlI;f@_bWyu?@bf&wXvW@KE$kJ@vS^L4TWz zP)j}NGYmhWw($8J!>=K~xoz6w_oiJB`V7%e5Nh&2hx@6^Z}Z%X$5*ZY`E4=Y&1I;` zFK&LVEq+&%-`E!Nn#)j=-~3XW{Qj?el?B?w-pz%mq_^#{i%N}u<*O{9vPoP1ppyRY z__w9mRkHrIzsdriJO34{2Bi&uQ1u?6&%OTn-0MH*HZ;3Rl$!lN_xc~Hlxo8t)cW7H z2k(kLs>}Zz4yZ2wb2xyy{LgUwrM~|{D6I`0PsjM9&oBdM*#9#OfTsMmj{r^i{o33C zH07hMZLL5v`TzOM@(s4Nu>#Hdum8>Gm9N)c*tQBZ>p#t)XHAJ7I>jTJeg`XcD*4|x4*@}n<`#^p4l4U^nEuq1Gp3Q=)dGOZmf7UWCY9{Y^|(PTU=DUy=&s~_+Rcc{_*VqT4&PcTN?Bjx>oO{r z?=kH;lEKX^$d|3O{|ZeYsp6aWKs8?@>Vg%tel$ri7PUv{EM5-RcAzx_F2TS?u^ z*UxLt?c~lI)mvG~qXxjZ7`OE5^dCE)*u28+f`wyxYjBKOl8z8fuf18H(SdJpd&TSR zFYY6Hnc)#o{q;p=@6ii{`{3_FU(}Zu#;%z1byFde8~_j8w6TNL4=zEe2M(kJ%mjv; zdabEt`49p|UB0&S)tHC=I3jfU$u*{0p%Agma=~^&1ep-h=&kpXVQJ}&uf1BO9j;IhfAZ(`;M6(mRDB$^wFKu+c^t< z>~CS%)H^bXza)q~R+a<7`}Q5o;?5hjs+~syNHt+tOy?5l^vb%LvrF&ymI(*;Vw4Iu7)5u1X_1ar}X}dfo@6fIY&*l`b z*5xBTgAQH4nY5U@?ZnL&@BVJmp*Cs0Sx57(eZHTvgr9w?vijEfeQ~}{Ln+^E!nDIJ zChHklemmVidC$I72!3m|39RYHmVTn?wKKIEXt#vBt@zsg#@BCNzkGPREL-F@=DRQZ z_Wk19(T-l+jANH>RGi%_UE?yMulnF)NC-hY1Dd`ucz5SVuT z&!`zoHzn*kcK+I}JGUw>o+&^`x z#KHY6F|y9yV-T7?{BdH(jwbjoBUPZE@&io|ccJIkBkY_PG1s%hCDAd_5+OHe&9Zqv dkN@FIYjb1uX-69w+8eZMhyOBE` -#import "PrefsEditor.h" - -// If the application supports multiple windows, -// ENABLE_MULTIPLE can be defined in config.h - -@interface Controller : NSApplication -{ -#ifdef ENABLE_MULTIPLE - NSMutableArray *emulators; // Array of created Emulators -#endif - IBOutlet Emulator *theEmulator; - IBOutlet PrefsEditor *thePrefsEditor; -} - -- (void) dispatchKeyEvent: (NSEvent *)event - type: (NSEventType)type; -- (void) dispatchEvent: (NSEvent *)event - type: (NSEventType)type; - - -- (IBAction) HelpHowTo: (id)sender; -- (IBAction) HelpToDo: (id)sender; -- (IBAction) HelpVersions: (id)sender; - -#ifdef ENABLE_MULTIPLE -- (IBAction) NewEmulator: (id)sender; -- (IBAction) PauseAll: (id)sender; -- (IBAction) RunAll: (id)sender; -- (IBAction) TerminateAll: (id)sender; -#endif - -- (BOOL) isAnyEmulatorDisplayingSheets; -- (BOOL) isAnyEmulatorRunning; -- (short) emulatorCreatedCount; // If any emulator environments have been setup, count how many - -@end diff --git a/BasiliskII/src/MacOSX/Controller.mm b/BasiliskII/src/MacOSX/Controller.mm deleted file mode 100644 index af4a96e6..00000000 --- a/BasiliskII/src/MacOSX/Controller.mm +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Controller.m - Simple application window management. - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "Controller.h" -#import "Emulator.h" - -#import "sysdeps.h" // Types used in Basilisk C++ code - -#import -#import - -#define DEBUG 0 -#import - -#import "misc_macosx.h" -#import "video_macosx.h" - -@implementation Controller - -// -// Standard NSApplication methods that we override -// - -- (id) init -{ -#ifdef ENABLE_MULTIPLE - emulators = [NSMutableArray new]; -#endif - return [super init]; -} - -- (void) dealloc -{ -#ifdef ENABLE_MULTIPLE - [emulators dealloc]; -#endif - [super dealloc]; -} - -- (void) awakeFromNib -{ -#ifdef ENABLE_MULTIPLE - [self NewEmulator: self]; // So the user gets something on screen -#endif - [[NSApplication sharedApplication] - setDelegate: self]; // Enable applicationShouldTerminate -} - -- (void) sendEvent: (NSEvent *)event; -{ - // We can either process the event ourselves, - // or pass it to our superclass for the other UI objects to process - bool passToSuper = false; - - if ( [self isAnyEmulatorDisplayingSheets] || - [[thePrefsEditor window] isVisible] || ! [self isAnyEmulatorRunning] ) - passToSuper = true; - - if ( [[theEmulator screen] isFullScreen] ) - passToSuper = false; - - if ( passToSuper ) - [super sendEvent: event]; // NSApplication default - else - { - NSEventType type = [event type]; - - if ( type == NSKeyUp || type == NSKeyDown || type == NSFlagsChanged ) - [self dispatchKeyEvent: event - type: type]; - else - [self dispatchEvent: event - type: type]; - } -} - -// NSApplication methods which are invoked through delegation - -- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *)app -{ return YES; } - -- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *)app -{ - short count; - const char *stillRunningMessage; - - if ( [thePrefsEditor hasEdited] ) - if ( ChoiceAlert("Preferences have been edited", - "Save changes", "Quit") ) - SavePrefs(); - -// if ( edited ) -// { -// NSString *title = [NSString stringWithCString: getString(STR_WARNING_ALERT_TITLE)], -// *msg = @"Preferences have been edited", -// *def = @"Save changes", -// *alt = @"Quit Application", -// *other = @"Continue"; -// -// switch ( NSRunAlertPanel(title, msg, def, alt, other, nil) ) -// { -// case NSAlertDefault: savePrefs(); -// case NSAlertAlternate: return NSTerminateNow; -// case NSAlertOther: return NSTerminateCancel; -// } -// } - - - if ( [[thePrefsEditor window] isVisible] ) - [[thePrefsEditor window] performClose: self]; - - - count = [self emulatorCreatedCount]; - - if ( count > 0 ) - { - if ( count > 1 ) - stillRunningMessage = "Emulators are still running\nExiting Basilisk may lose data"; - else - stillRunningMessage = "Emulator is still running\nExiting Basilisk may lose data"; - if ( ! ChoiceAlert(stillRunningMessage, "Exit", "Continue") ) - return NSTerminateCancel; // NSTerminateLater? - } - - return NSTerminateNow; -} - - -// Event dispatching, called by sendEvent - -- (void) dispatchKeyEvent: (NSEvent *)event - type: (NSEventType)type -{ - EmulatorView *view; - -#ifdef ENABLE_MULTIPLE - // We need to work out what window's Emulator should receive these messages - - - int tmp; - - for ( tmp = 0; tmp < [emulators count], ++tmp ) - { - theEmulator = [emulators objectAtIndex: tmp]; - view = [theEmulator screen]; - - if ( [ theEmulator isRunning ] && - ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) ) - break; - } - - if ( tmp < [emulators count] ) // i.e. if we exited the for loop -#else - view = [theEmulator screen]; - - if ( [theEmulator isRunning] && - ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) ) -#endif - { - D(NSLog(@"Got a key event - %d\n", [event keyCode])); - switch ( type ) - { - case NSKeyUp: - [view keyUp: event]; - break; - case NSKeyDown: - D(NSLog(@"%s - NSKeyDown - %@", __PRETTY_FUNCTION__, event)); - [view keyDown: event]; - break; - case NSFlagsChanged: - [view flagsChanged: event]; - break; - default: - NSLog(@"%s - Sent a non-key event (logic error)", - __PRETTY_FUNCTION__); - [super sendEvent: event]; - } - } - else // No Basilisk window is key (maybe a panel or pane). - [super sendEvent: event]; // Call NSApplication default - -} - -- (void) dispatchEvent: (NSEvent *)event - type: (NSEventType)type -{ - EmulatorView *view; - BOOL fullScreen; - -#ifdef ENABLE_MULTIPLE - // We need to work out what window's Emulator should receive these messages - - - int tmp; - - for ( tmp = 0; tmp < [emulators count], ++tmp ) - { - theEmulator = [emulators objectAtIndex: tmp]; - view = [theEmulator screen]; - fullScreen = [view isFullScreen]; - - if ( [theEmulator isRunning] && - ( fullScreen || [[theEmulator window] isMainWindow] ) ) - break; - } - - if ( tmp < [emulators count] ) // i.e. if we exited the for loop -#else - view = [theEmulator screen]; - fullScreen = [view isFullScreen]; - - if ( [theEmulator isRunning] && - ( fullScreen || [[theEmulator window] isMainWindow] ) ) -#endif - { - if ( fullScreen || [view mouseInView: event] ) - { - switch ( type ) - { - case NSLeftMouseDown: - [view mouseDown: event]; - break; - case NSLeftMouseUp: - [view mouseUp: event]; - break; - case NSLeftMouseDragged: - case NSMouseMoved: - if ( fullScreen ) - [view fullscreenMouseMove]; - else - [view processMouseMove: event]; - break; - default: - [super sendEvent: event]; // NSApplication default - } - return; - } - } - - // Either the pointer is not in the Emulator's screen, no Basilisk window is running, - // or no Basilisk window is main (e.g. there might be a panel or pane up). - // - // We should just be calling NSApp's default sendEvent, but then for some reason - // mouseMoved events are still passed to our EmulatorView, so we filter them out. - - if ( type != NSMouseMoved ) - [super sendEvent: event]; -} - - -// Methods to display documentation: - -- (IBAction) HelpHowTo: (id)sender -{ - NSString *path = [[NSBundle mainBundle] pathForResource: @"HowTo" - ofType: @"html"]; - - if ( ! path ) - InfoSheet(@"Cannot find HowTo.html", [theEmulator window]); - else - if ( ! [[NSWorkspace sharedWorkspace] openFile: path] ) - InfoSheet(@"Cannot open HowTo.html with default app", [theEmulator window]); -} - -- (IBAction) HelpToDo: (id)sender -{ - NSString *path = [[NSBundle mainBundle] pathForResource: @"ToDo" - ofType: @"html"]; - - if ( ! path ) - InfoSheet(@"Cannot find ToDo.html", [theEmulator window]); - else - if ( ! [[NSWorkspace sharedWorkspace] openFile: path - withApplication: @"TextEdit"] ) - InfoSheet(@"Cannot open ToDo.html with TextEdit", [theEmulator window]); -} - -- (IBAction) HelpVersions: (id)sender -{ - NSString *path = [[NSBundle mainBundle] pathForResource: @"Versions" - ofType: @"html"]; - - if ( ! path ) - InfoSheet(@"Cannot find Versions.html", [theEmulator window]); - else - if ( ! [[NSWorkspace sharedWorkspace] openFile: path - withApplication: @"TextEdit"] ) - InfoSheet(@"Cannot open Versions.html with TextEdit", - [theEmulator window]); -} - - -// Menu items which for managing more than one window - -#ifdef ENABLE_MULTIPLE - -- (IBAction) NewEmulator: (id)sender -{ - NSString *title; - - if ( ! [NSBundle loadNibNamed:@"Win512x342" owner:self] ) - { - NSLog(@"%s - LoadNibNamed@Win512x342 failed", __PRETTY_FUNCTION__); - return; - } - - if ( theEmulator == nil) - { - NSLog(@"%s - Newly created emulator's NIB stuff not fully linked?", __PRETTY_FUNCTION__); - return; - } - - [emulators addObject: theEmulator]; - title = [NSString localizedStringWithFormat:@"BasiliskII Emulator %d", [emulators count]]; - [theEmulator -> win setTitle: title]; -} - -- (IBAction) PauseAll: (id)sender -{ - [emulators makeObjectsPerformSelector:@selector(Suspend:) - withObject:self]; -} - -- (IBAction) RunAll: (id)sender -{ - [emulators makeObjectsPerformSelector:@selector(Resume:) - withObject:self]; -} - -- (IBAction) TerminateAll: (id)sender -{ - [emulators makeObjectsPerformSelector:@selector(Terminate:) - withObject:self]; -} - -#endif - -- (BOOL) isAnyEmulatorDisplayingSheets -{ -#ifdef ENABLE_MULTIPLE - int tmp; - - for ( tmp = 0; tmp < [emulators count], ++tmp ) - if ( [[[emulators objectAtIndex: tmp] window] attachedSheet] ) - break; - - if ( tmp < [emulators count] ) // i.e. if we exited the for loop -#else - if ( [[theEmulator window] attachedSheet] ) -#endif - return TRUE; - - return FALSE; -} - -- (BOOL) isAnyEmulatorRunning -{ -#ifdef ENABLE_MULTIPLE - int tmp; - - for ( tmp = 0; tmp < [emulators count], ++tmp ) - if ( [[emulators objectAtIndex: tmp] isRunning] ) - break; - - if ( tmp < [emulators count] ) // i.e. if we exited the for loop -#else - if ( [theEmulator isRunning] ) -#endif - return TRUE; - - return FALSE; -} - -- (short) emulatorCreatedCount -{ - short count = 0; -#ifdef ENABLE_MULTIPLE - int tmp; - - for ( tmp = 0; tmp < [emulators count], ++tmp ) - if ( [[emulators objectAtIndex: tmp] uaeCreated] ) - ++count; -#else - if ( [theEmulator uaeCreated] ) - ++count; -#endif - - return count; -} - -@end diff --git a/BasiliskII/src/MacOSX/Credits.html b/BasiliskII/src/MacOSX/Credits.html deleted file mode 100644 index 29ee57a9..00000000 --- a/BasiliskII/src/MacOSX/Credits.html +++ /dev/null @@ -1,11 +0,0 @@ -Basilisk II is an open source, 68k Mac. emulator. -
-It enables you to run 68k MacOS software on your computer, even if you are using a different operating system (however, you do need a copy of the MacOS and a Macintosh ROM image to use it). -
-The Official Basilisk II Home Page -
- -MacOS X (native windowing) port -
-by Nigel Pearson <nigel@ind.tansu.com.au> -
diff --git a/BasiliskII/src/MacOSX/Emulator.h b/BasiliskII/src/MacOSX/Emulator.h deleted file mode 100644 index 761ce55e..00000000 --- a/BasiliskII/src/MacOSX/Emulator.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Emulator.h - Class whose actions are attached GUI widgets in a window, - * used to control a single Basilisk II emulated Macintosh. - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import -#import -#import "EmulatorView.h" -#import "NNThread.h" - -@interface Emulator : NSObject -{ - NNThread *emul; // Run emulThread - NNTimer *RTC, // Invoke RTCinterrupt - *redraw, // Invoke redrawScreen - *tick, // Invoke tickInterrupt - *xPRAM; // Invoke xPRAMbackup - - BOOL uaeCreated, // Has thread created the emulator environment? - running; // Is the emulator currently grinding away? - float redrawDelay; // Seconds until next screen update - - // UI elements that this class changes the state of - - IBOutlet NSProgressIndicator *barberPole; - IBOutlet NSButton *runOrPause; - IBOutlet EmulatorView *screen; - IBOutlet NSSlider *speed; - IBOutlet NSWindow *win; -} - -// The following allow the Controller and PrefsEditor classes to access our internal data - -- (BOOL) isRunning; -- (BOOL) uaeCreated; -- (EmulatorView *) screen; -- (NSSlider *) speed; -- (NSWindow *) window; - -- (void) runUpdate; // Update some UI elements - -- (IBAction) Benchmark: (id)sender; -- (IBAction) Interrupt: (id)sender; -- (IBAction) PowerKey: (id)sender; -- (IBAction) Restart: (id)sender; -- (IBAction) Resume: (id)sender; -- (IBAction) ScreenHideShow:(NSButton *)sender; -- (IBAction) Snapshot: (id)sender; -- (IBAction) SpeedChange: (NSSlider *)sender; -- (IBAction) Suspend: (id)sender; -- (IBAction) Terminate: (id)sender; -- (IBAction) ToggleState: (NSButton *)sender; -- (IBAction) ZapPRAM: (id)sender; - -- (void) createThreads; -- (void) exitThreads; - -- (void) emulThread; // Thread for processor emulator -- (void) RTCinterrupt; // Emulator real time clock update -- (void) redrawScreen; // Draw emulator screen in window -- (void) tickInterrupt; // Draw emulator screen in window -- (void) xPRAMbackup; // PRAM watchdog - -@end diff --git a/BasiliskII/src/MacOSX/Emulator.mm b/BasiliskII/src/MacOSX/Emulator.mm deleted file mode 100644 index 61d191ff..00000000 --- a/BasiliskII/src/MacOSX/Emulator.mm +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Emulator.mm - Class whose actions are attached to GUI widgets in a window, - * used to control a single Basilisk II emulated Macintosh. - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "Emulator.h" -#import "EmulatorView.h" - -#import "sysdeps.h" // Types used in Basilisk C++ code - -#import "main_macosx.h" // Prototypes for QuitEmuNoExit() and InitEmulator() -#import "misc_macosx.h" // Some other prototypes -#import "video_macosx.h" // Some window/view globals - -#import "adb.h" -#import "main.h" -#import "prefs.h" -#import "timer.h" - -#undef check // memory.h defines a check macro, - // which may clash with an OS X one on 10.1 or 10.2 -#import "cpu_emulation.h" - -#define DEBUG 0 -#import "debug.h" - -@implementation Emulator - -// NSWindow method, which is invoked via delegation - -- (BOOL) windowShouldClose: (id)sender -{ - if ( uaeCreated ) - { - NSLog(@"windowShouldClose returning NO"); - return NO; // Should initiate poweroff and return NSTerminateLater ? - } - - NSLog(@"windowShouldClose returning YES"); - return YES; -} - -// Default methods - -- (Emulator *) init -{ - int frameSkip; - - self = [super init]; - - running = NO; // Save churn when application loads -// running = YES; - uaeCreated = NO; - - frameSkip = PrefsFindInt32("frameskip"); - if ( frameSkip ) - redrawDelay = frameSkip / 60.0; - else - redrawDelay = 0.0; - - // We do this so that we can work out if we are in full screen mode: - parse_screen_prefs(PrefsFindString("screen")); - - [self createThreads]; - - return self; -} - -- (void) awakeFromNib -{ - the_win = win; // Set global for access by Basilisk C++ code - - - [win setDelegate: self]; // Enable windowShouldClose calling - - // Try to speed up everything - //[win setHasShadow: NO]; // This causes view & window to now be drawn correctly - [win useOptimizedDrawing: YES]; - - [win makeKeyAndOrderFront:self]; - - if ( redrawDelay ) - [speed setFloatValue: 1.0 / redrawDelay]; - else - [speed setFloatValue: 60.0]; - - - if ( runOrPause == nil ) - NSLog(@"%s - runOrPause button pointer is nil!", __PRETTY_FUNCTION__); - - [self runUpdate]; -} - - -// Helpers which other classes use to access our private stuff - -- (BOOL) isRunning { return running; } -- (BOOL) uaeCreated { return uaeCreated; } -- (EmulatorView *) screen { return screen; } -- (NSSlider *) speed { return speed; } -- (NSWindow *) window { return win; } - - -// Update some UI elements - -- (void) runUpdate -{ - if ( running ) - [runOrPause setState: NSOnState]; // Running. Change button label to 'Pause' - else - [runOrPause setState: NSOffState]; // Paused. Change button label to 'Run' - - [win setDocumentEdited: uaeCreated]; // Set the little dimple in the close button -} - - -// Methods invoked by buttons & menu items - -- (IBAction) Benchmark: (id)sender; -{ - BOOL wasRunning = running; - - if ( running ) - [self Suspend: self]; - [screen benchmark]; - if ( wasRunning ) - [self Resume: self]; -} - -#ifdef NIGEL -- (IBAction) EjectCD: (id)sender; -{ - NSString *path; - const char *cdrom = PrefsFindString("cdrom"); - - if ( cdrom ) - { - #include - #define KERNEL - #include - - struct statfs buf; - if ( fsstat(path, &buf) < 0 ) - return; - - path = [NSString stringWithCString: cdrom]; - - [[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: path]; -// [path release]; - } -} -#endif - -- (IBAction) Interrupt: (id)sender; -{ - WarningSheet (@"Interrupt action not yet supported", win); -} - -- (IBAction) PowerKey: (id)sender; -{ - if ( uaeCreated ) // If Mac has started - { - ADBKeyDown(0x7f); // Send power key, which is also - ADBKeyUp(0x7f); // called ADB_RESET or ADB_POWER - } - else - { - running = YES; // Start emulator - [self runUpdate]; - [self Resume: nil]; - } -} - -- (IBAction) Restart: (id)sender -{ - if ( ! running ) - { - running = YES; // Start emulator - [self runUpdate]; - [self Resume: nil]; - } - - if ( running ) -#ifdef UAE_CPU_HAS_RESET - reset680x0(); -#else - { - uaeCreated = NO; - [redraw suspend]; - NSLog (@"%s - uae_cpu reset not yet supported, will try to fake it", - __PRETTY_FUNCTION__); - - [screen clear]; - [screen display]; - - [emul terminate]; QuitEmuNoExit(); - - - // OK. We have killed & cleaned up. Now, start afresh: - #include - int argc = 0; - char **argv; - - PrefsInit(NULL, argc, argv); - SysInit(); - - emul = [NNThread new]; - [emul perform:@selector(emulThread) of:self]; - [emul start]; - - if ( display_type != DISPLAY_SCREEN ) - [redraw resume]; - } -#endif -} - -- (IBAction) Resume: (id)sender -{ - [RTC resume]; - [emul resume]; - if ( display_type != DISPLAY_SCREEN ) - [redraw resume]; - [tick resume]; - [xPRAM resume]; -} - -- (IBAction) ScreenHideShow: (NSButton *)sender; -{ - WarningSheet(@"Nigel doesn't know how to shrink or grow this window", - @"Maybe you can grab the source code and have a go yourself?", - nil, win); -} - -- (IBAction) Snapshot: (id) sender -{ - if ( screen == nil || uaeCreated == NO ) - WarningSheet(@"The emulator has not yet started.", - @"There is no screen output to snapshot", - nil, win); - else - { - NSData *TIFFdata; - - [self Suspend: self]; - - TIFFdata = [screen TIFFrep]; - if ( TIFFdata == nil ) - NSLog(@"%s - Unable to convert Basilisk screen to a TIFF representation", - __PRETTY_FUNCTION__); - else - { - NSSavePanel *sp = [NSSavePanel savePanel]; - - [sp setRequiredFileType:@"tiff"]; - - if ( [sp runModalForDirectory:NSHomeDirectory() - file:@"B2-screen-snapshot.tiff"] == NSOKButton ) - if ( ! [TIFFdata writeToFile:[sp filename] atomically:YES] ) - NSLog(@"%s - Could not write TIFF data to file @%", - __PRETTY_FUNCTION__, [sp filename]); - - } - if ( running ) - [self Resume: self]; - } -} - -- (IBAction) SpeedChange: (NSSlider *)sender -{ - float frequency = [sender floatValue]; - - [redraw suspend]; - - if ( frequency == 0.0 ) - redrawDelay = 0.0; - else - { - frequencyToTickDelay(frequency); - - redrawDelay = 1.0 / frequency; - - [redraw changeIntervalTo: (int)(redrawDelay * 1e6) - units: NNmicroSeconds]; - if ( running && display_type != DISPLAY_SCREEN ) - [redraw resume]; - } -} - -- (IBAction) Suspend: (id)sender -{ - [RTC suspend]; - [emul suspend]; - [redraw suspend]; - [tick suspend]; - [xPRAM suspend]; -} - -- (IBAction) ToggleState: (NSButton *)sender -{ - running = [sender state]; // State of the toggled NSButton - if ( running ) - [self Resume: nil]; - else - [self Suspend: nil]; -} - -- (IBAction) Terminate: (id)sender; -{ - [self exitThreads]; - [win performClose: self]; -} - -#include - -#define XPRAM_SIZE 256 - -uint8 lastXPRAM[XPRAM_SIZE]; // Copy of PRAM - -- (IBAction) ZapPRAM: (id)sender; -{ - memset(XPRAM, 0, XPRAM_SIZE); - memset(lastXPRAM, 0, XPRAM_SIZE); - ZapPRAM(); -} - -// -// Threads, Timers and stuff to manage them: -// - -- (void) createThreads -{ -#ifdef USE_PTHREADS - // Make UI threadsafe: - [NSThread detachNewThreadSelector:(SEL)"" toTarget:nil withObject:nil]; - //emul = [[NNThread alloc] initWithAutoReleasePool]; -#endif - emul = [NNThread new]; - RTC = [NNTimer new]; - redraw = [[NNTimer alloc] initWithAutoRelPool]; - tick = [NNTimer new]; - xPRAM = [NNTimer new]; - - [emul perform:@selector(emulThread) of:self]; - [RTC repeat:@selector(RTCinterrupt) of:self - every:1 - units:NNseconds]; - [redraw repeat:@selector(redrawScreen) of:self - every:(int)(1000*redrawDelay) - units:NNmilliSeconds]; - [tick repeat:@selector(tickInterrupt) of:self - every:16625 - units:NNmicroSeconds]; - [xPRAM repeat:@selector(xPRAMbackup) of:self - every:60 - units:NNseconds]; - - if ( running ) // Start emulator, then threads in most economical order - { - [emul start]; - [xPRAM start]; - [RTC start]; - if ( display_type != DISPLAY_SCREEN ) - [redraw start]; - [tick start]; - } -} - -- (void) exitThreads -{ - running = NO; - [emul terminate]; [emul release]; emul = nil; - [tick invalidate]; [tick release]; tick = nil; - [redraw invalidate]; [redraw release]; redraw = nil; - [RTC invalidate]; [RTC release]; RTC = nil; - [xPRAM invalidate]; [xPRAM release]; xPRAM = nil; -} - -- (void) emulThread -{ - NSAutoreleasePool *pool = [NSAutoreleasePool new]; - - if ( ! InitEmulator() ) - { - [redraw suspend]; // Stop the barberpole - - ErrorSheet(@"Cannot start Emulator", @"", @"Quit", win); - } - else - { - memcpy(lastXPRAM, XPRAM, XPRAM_SIZE); - - uaeCreated = YES; // Enable timers to access emulated Mac's memory - - while ( screen == nil ) // If we are still loading from Nib? - [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow: 1.0]]; - - [self runUpdate]; // Set the window close gadget to dimpled - - Start680x0(); // Start 68k and jump to ROM boot routine - - puts ("Emulator exited normally"); - } - - [pool release]; - QuitEmulator(); -} - -- (void) RTCinterrupt -{ - if ( ! uaeCreated ) - return; - - WriteMacInt32 (0x20c, TimerDateTime() ); // Update MacOS time - - SetInterruptFlag(INTFLAG_1HZ); - TriggerInterrupt(); -} - -- (void) redrawScreen -{ - if ( display_type == DISPLAY_SCREEN ) - { - NSLog(@"We are in fullscreen mode - why was redrawScreen() called?"); - return; - } - [barberPole animate:self]; // wobble the pole - [screen setNeedsDisplay: YES]; // redisplay next time through runLoop - // Or, use a direct method. e.g. - // [screen display] or [screen cgDrawInto: ...]; -} - -#include // For #define INTFLAG_60HZ -#include // For ROMVersion -#include "macos_util_macosx.h" // For HasMacStarted() - -- (void) tickInterrupt -{ - if ( ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted() ) - { - SetInterruptFlag (INTFLAG_60HZ); - TriggerInterrupt (); - } -} - -- (void) xPRAMbackup -{ - if ( uaeCreated && - memcmp(lastXPRAM, XPRAM, XPRAM_SIZE) ) // if PRAM changed from copy - { - memcpy (lastXPRAM, XPRAM, XPRAM_SIZE); // re-copy - SaveXPRAM (); // and save to disk - } -} - -@end diff --git a/BasiliskII/src/MacOSX/EmulatorView.h b/BasiliskII/src/MacOSX/EmulatorView.h deleted file mode 100644 index 9fc152b5..00000000 --- a/BasiliskII/src/MacOSX/EmulatorView.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * EmulatorView.h - Custom NSView for Basilisk II window input & output - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef NSBITMAP -#import -#endif - -#import - - -@interface EmulatorView : NSView -{ -#ifdef CGIMAGEREF - CGImageRef cgImgRep; -#endif -#ifdef NSBITMAP - NSBitmapImageRep *bitmap; -#else - void *bitmap; -#endif -#ifdef CGDRAWBITMAP - short bps, spp, bpp; - int bytesPerRow; - BOOL isPlanar, hasAlpha; -#endif - float numBytes; - - short x, y; - - BOOL drawView, // Set when the bitmap is all set up - // and ready to display - fullScreen; // Is this Emulator using the whole screen? - - NSRect displayBox; // Cached dimensions of the screen - - int screen_height; // Height of the screen with the key window -} - -- (void) benchmark; -- (NSData *) TIFFrep; // Used for snapshot function - -// Enable display of, and drawing into, the view -#ifdef NSBITMAP -- (void) readyToDraw: (NSBitmapImageRep *) theBitmap - imageWidth: (short) width - imageHeight: (short) height; -#endif -#ifdef CGIMAGEREF -- (void) readyToDraw: (CGImageRef) image - bitmap: (void *) theBitmap - imageWidth: (short) width - imageHeight: (short) height; -#endif -#ifdef CGDRAWBITMAP -- (void) readyToDraw: (void *) theBitmap - width: (short) width - height: (short) height - bps: (short) bitsPerSample - spp: (short) samplesPerPixel - bpp: (short) bitsPerPixel - bpr: (int) bpr - isPlanar: (BOOL) planar - hasAlpha: (BOOL) alpha; -#endif - -- (void) disableDrawing; -- (void) startedFullScreen: (CGDirectDisplayID) theDisplay; - -- (void) blacken; -- (void) clear; - -- (short) width; -- (short) height; - -- (BOOL) isFullScreen; -- (BOOL) mouseInView: (NSEvent *) event; -- (BOOL) mouseInView; -- (void) fullscreenMouseMove; -- (BOOL) processMouseMove: (NSEvent *) event; - -#ifdef CGDRAWBITMAP -- (void) CGDrawBitmap; -#endif - -#ifdef CGIMAGEREF -void cgDrawInto(NSRect rect, CGImageRef bitmap); -#endif - -@end diff --git a/BasiliskII/src/MacOSX/EmulatorView.mm b/BasiliskII/src/MacOSX/EmulatorView.mm deleted file mode 100644 index cf300481..00000000 --- a/BasiliskII/src/MacOSX/EmulatorView.mm +++ /dev/null @@ -1,550 +0,0 @@ -/* - * EmulatorView.mm - Custom NSView for Basilisk II windowed graphics output - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "sysdeps.h" // Types used in Basilisk C++ code, - -#define DEBUG 0 -#import - -#import - -#import "main_macosx.h" // For WarningAlert() et al prototypes -#import "misc_macosx.h" // For InfoSheet() prototype -#import "video_macosx.h" // For init_* globals, and bitmap drawing strategy - -#import "EmulatorView.h" - -@implementation EmulatorView - - -// -// Standard NSView methods that we override -// - -- (id) initWithFrame: (NSRect) frameRect -{ - self = [super initWithFrame: frameRect]; - - output = self; // Set global for access by Basilisk C++ code -// bitmap = nil; // Set by readyToDraw: - drawView = NO; // Disable drawing until later - fullScreen = NO; - - return self; -} - -- (void) awakeFromNib -{ - // Here we store the height of the screen which the app was opened on. - // NSApplication's sendEvent: always uses that screen for its mouse co-ords - screen_height = (int) [[NSScreen mainScreen] frame].size.height; -} - - -// Mouse click in this window. If window is not active, -// should the click be passed to this view? -- (BOOL) acceptsFirstMouse: (NSEvent *) event -{ - return [self mouseInView]; -} - - -// -// Key event processing. -// OS X doesn't send us separate events for the modifier keys -// (shift/control/command), so we need to monitor them separately -// - -#include - -static int prevFlags; - -- (void) flagsChanged: (NSEvent *) event -{ - int flags = [event modifierFlags]; - - if ( (flags & NSAlphaShiftKeyMask) != (prevFlags & NSAlphaShiftKeyMask) ) - if ( flags & NSAlphaShiftKeyMask ) - ADBKeyDown(0x39); // CAPS_LOCK - else - ADBKeyUp(0x39); - - if ( (flags & NSShiftKeyMask) != (prevFlags & NSShiftKeyMask) ) - if ( flags & NSShiftKeyMask ) - ADBKeyDown(0x38); // SHIFT_LEFT - else - ADBKeyUp(0x38); - - if ( (flags & NSControlKeyMask) != (prevFlags & NSControlKeyMask) ) - if ( flags & NSControlKeyMask ) - ADBKeyDown(0x36); // CTL_LEFT - else - ADBKeyUp(0x36); - - if ( (flags & NSAlternateKeyMask) != (prevFlags & NSAlternateKeyMask) ) - if ( flags & NSAlternateKeyMask ) - ADBKeyDown(0x3a); // OPTION_LEFT - else - ADBKeyUp(0x3a); - - if ( (flags & NSCommandKeyMask) != (prevFlags & NSCommandKeyMask) ) - if ( flags & NSCommandKeyMask ) - ADBKeyDown(0x37); // APPLE_LEFT - else - ADBKeyUp(0x37); - - prevFlags = flags; -} - -// -// Windowed mode. We only send mouse/key events -// if the OS X mouse is within the little screen -// -- (BOOL) mouseInView: (NSEvent *) event -{ - NSRect box; - NSPoint loc; - - if ( fullScreen ) - { - box = displayBox; - loc = [NSEvent mouseLocation]; - } - else - { - box = [self frame]; - loc = [event locationInWindow]; - } - - D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f, box.size.width=%f, box.size.height=%f", __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y, box.size.width, box.size.height)); - return [self mouse: loc inRect: box]; -} - -- (BOOL) mouseInView -{ - NSPoint loc = [[self window] mouseLocationOutsideOfEventStream]; - NSRect box = [self frame]; - D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f", - __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y)); - return [self mouse: loc inRect: box]; -} - -// -// Custom methods -// - -- (void) benchmark -{ - int i; - float seconds; - NSDate *startDate; - const char *method; - - if ( ! drawView ) - { - WarningSheet (@"The emulator has not been setup yet.", - @"Try to run, then pause the emulator, first.", nil, [self window]); - return; - } - - drawView = NO; - [self lockFocus]; - startDate = [NSDate date]; - for (i = 1; i < 300; ++i ) -#ifdef NSBITMAP - [bitmap draw]; -#endif -#ifdef CGIMAGEREF - cgDrawInto([self bounds], cgImgRep); -#endif -#ifdef CGDRAWBITMAP - [self CGDrawBitmap]; -#endif - seconds = -[startDate timeIntervalSinceNow]; - [self unlockFocus]; - drawView = YES; - -#ifdef NSBITMAP - method = "NSBITMAP"; -#endif -#ifdef CGIMAGEREF - method = "CGIMAGEREF"; -#endif -#ifdef CGDRAWBITMAP - method = "CGDRAWBITMAP"; -#endif - - InfoSheet(@"Ran benchmark (300 screen redraws)", - [NSString stringWithFormat: - @"%.2f seconds, %.3f frames per second (using %s implementation)", - seconds, i/seconds, method], - @"Thanks", [self window]); -} - -// Return a TIFF for a snapshot of the screen image -- (NSData *) TIFFrep -{ -#ifdef NSBITMAP - return [bitmap TIFFRepresentation]; -#else - NSBitmapImageRep *b = [NSBitmapImageRep alloc]; - - b = [b initWithBitmapDataPlanes: (unsigned char **) &bitmap - pixelsWide: x - pixelsHigh: y - #ifdef CGIMAGEREF - bitsPerSample: CGImageGetBitsPerComponent(cgImgRep) - samplesPerPixel: 3 - hasAlpha: NO - isPlanar: NO - colorSpaceName: NSCalibratedRGBColorSpace - bytesPerRow: CGImageGetBytesPerRow(cgImgRep) - bitsPerPixel: CGImageGetBitsPerPixel(cgImgRep)]; - #endif - #ifdef CGDRAWBITMAP - bitsPerSample: bps - samplesPerPixel: spp - hasAlpha: hasAlpha - isPlanar: isPlanar - colorSpaceName: NSCalibratedRGBColorSpace - bytesPerRow: bytesPerRow - bitsPerPixel: bpp]; - #endif - - if ( ! b ) - { - ErrorAlert("Could not allocate an NSBitmapImageRep for the TIFF\nTry setting the emulation to millions of colours?"); - return nil; - } - - return [b TIFFRepresentation]; -#endif -} - -// Enable display of, and drawing into, the view -#ifdef NSBITMAP -- (void) readyToDraw: (NSBitmapImageRep *) theBitmap - imageWidth: (short) width - imageHeight: (short) height -{ - numBytes = [theBitmap bytesPerRow] * height; -#endif -#ifdef CGIMAGEREF -- (void) readyToDraw: (CGImageRef) image - bitmap: (void *) theBitmap - imageWidth: (short) width - imageHeight: (short) height -{ - cgImgRep = image; - numBytes = CGImageGetBytesPerRow(image) * height; -#endif -#ifdef CGDRAWBITMAP -- (void) readyToDraw: (void *) theBitmap - width: (short) width - height: (short) height - bps: (short) bitsPerSample - spp: (short) samplesPerPixel - bpp: (short) bitsPerPixel - bpr: (int) bpr - isPlanar: (BOOL) planar - hasAlpha: (BOOL) alpha -{ - bps = bitsPerSample; - spp = samplesPerPixel; - bpp = bitsPerPixel; - bytesPerRow = bpr; - isPlanar = planar; - hasAlpha = alpha; - numBytes = bpr * height; -#endif - D(NSLog(@"readyToDraw: theBitmap=%lx\n", theBitmap)); - - bitmap = theBitmap; - x = width, y = height; - drawView = YES; - [[self window] setAcceptsMouseMovedEvents: YES]; -// [[self window] setInitialFirstResponder: self]; - [[self window] makeFirstResponder: self]; -} - -- (void) disableDrawing -{ - drawView = NO; -} - -- (void) startedFullScreen: (CGDirectDisplayID) display -{ - CGRect displayBounds = CGDisplayBounds(display); - - fullScreen = YES; - memcpy(&displayBox, &displayBounds, sizeof(displayBox)); -} - -- (short) width -{ - return (short)[self bounds].size.width; -} - -- (short) height -{ - return (short)[self bounds].size.height; -} - -- (BOOL) isFullScreen -{ - return fullScreen; -} - -- (BOOL) isOpaque -{ - return drawView; -} - -- (BOOL) processKeyEvent: (NSEvent *) event -{ - if ( fullScreen || [self acceptsFirstMouse: event] ) - if ( [event isARepeat] ) - return NO; - else - return YES; - - [self interpretKeyEvents:[NSArray arrayWithObject:event]]; - return NO; -} - -- (void) keyDown: (NSEvent *) event -{ - if ( [self processKeyEvent: event] ) - { - int code = [event keyCode]; - - if ( code == 126 ) code = 0x3e; // CURS_UP - if ( code == 125 ) code = 0x3d; // CURS_DOWN - if ( code == 124 ) code = 0x3c; // CURS_RIGHT - if ( code == 123 ) code = 0x3b; // CURS_LEFT - - ADBKeyDown(code); - } -} - -- (void) keyUp: (NSEvent *) event -{ - if ( [self processKeyEvent: event] ) - { - int code = [event keyCode]; - - if ( code == 126 ) code = 0x3e; // CURS_UP - if ( code == 125 ) code = 0x3d; // CURS_DOWN - if ( code == 124 ) code = 0x3c; // CURS_RIGHT - if ( code == 123 ) code = 0x3b; // CURS_LEFT - - ADBKeyUp(code); - } -} - - -- (void) fullscreenMouseMove -{ - NSPoint location = [NSEvent mouseLocation]; - - D(NSLog (@"%s - loc.x=%f, loc.y=%f", - __PRETTY_FUNCTION__, location.x, location.y)); - D(NSLog (@"%s - Sending ADBMouseMoved(%d,%d). (%d-%d)", - __PRETTY_FUNCTION__, (int)location.x, - screen_height - (int)location.y, screen_height, (int)location.y)); - ADBMouseMoved((int)location.x, screen_height - (int)location.y); -} - -static NSPoint mouse; // Previous/current mouse location - -- (BOOL) processMouseMove: (NSEvent *) event -{ - if ( ! drawView ) - { - D(NSLog(@"Unable to process event - Emulator has not started yet")); - return NO; - } - - if ( fullScreen ) - { - [self fullscreenMouseMove]; - return YES; - } - - NSPoint location = [self convertPoint: [event locationInWindow] fromView:nil]; - - D(NSLog (@"%s - loc.x=%f, loc.y=%f", - __PRETTY_FUNCTION__, location.x, location.y)); - - if ( NSEqualPoints(location, mouse) ) - return NO; - - mouse = location; - - int mouseY = y - (int) (y * mouse.y / [self height]); - int mouseX = (int) (x * mouse.x / [self width]); - // If the view was not resizable, then this would be simpler: - // int mouseY = y - (int) mouse.y; - // int mouseX = (int) mouse.x; - - ADBMouseMoved(mouseX, mouseY); - return YES; -} - -- (void) mouseDown: (NSEvent *) event -{ - [self processMouseMove: event]; - ADBMouseDown(0); -} - -- (void) mouseDragged: (NSEvent *) event -{ - [self processMouseMove: event]; -} - -- (void) mouseMoved: (NSEvent *) event -{ -#if DEBUG - if ( ! [self mouseInView] ) - { - NSLog (@"%s - Received event while outside of view", __PRETTY_FUNCTION__); - return; - } -#endif - [self processMouseMove: event]; -} - -- (void) mouseUp: (NSEvent *) event -{ - [self processMouseMove: event]; - ADBMouseUp(0); -} - -#if DEBUG -- (void) randomise // Draw some coloured snow in the bitmap -{ - unsigned char *data, - *pixel; - - #ifdef NSBITMAP - data = [bitmap bitmapData]; - #else - data = bitmap; - #endif - - for ( int i = 0; i < 1000; ++i ) - { - pixel = data + (int) (numBytes * rand() / RAND_MAX); - *pixel = (unsigned char) (256.0 * rand() / RAND_MAX); - } -} -#endif - -- (void) drawRect: (NSRect) rect -{ - if ( ! drawView ) // If the emulator is still being setup, - return; // we do not want to draw - -#if DEBUG - NSLog(@"In drawRect"); - [self randomise]; -#endif - -#ifdef NSBITMAP - NSRectClip(rect); - [bitmap draw]; -#endif -#ifdef CGIMAGEREF - cgDrawInto(rect, cgImgRep); -#endif -#ifdef CGDRAWBITMAP - [self CGDrawBitmap]; -#endif -} - -- (void) setTo: (int) val // Set all of bitmap to val -{ - unsigned char *data - #ifdef NSBITMAP - = [bitmap bitmapData]; - #else - = (unsigned char *) bitmap; - #endif - - memset(data, val, (long unsigned)numBytes); -} - -- (void) blacken // Set bitmap black -{ - [self setTo: 0]; -} - -- (void) clear // Set bitmap white -{ - [self setTo: 0xFF]; -} - -// -// Extra drawing stuff -// - -#ifdef CGDRAWBITMAP -extern "C" void CGDrawBitmap(...); - -- (void) CGDrawBitmap -{ - CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext] - graphicsPort]; - NSRect rect = [self bounds]; - CGRect cgRect = { - {rect.origin.x, rect.origin.y}, - {rect.size.width, rect.size.height} - }; - - CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); - - -// CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect? - - CGDrawBitmap(cgContext, cgRect, x, y, bps, spp, bpp, - bytesPerRow, isPlanar, hasAlpha, colourSpace, &bitmap); -} -#endif - -#ifdef CGIMAGEREF -void -cgDrawInto(NSRect rect, CGImageRef cgImgRep) -{ - CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext] - graphicsPort]; - CGRect cgRect = { - {rect.origin.x, rect.origin.y}, - {rect.size.width, rect.size.height} - }; - -// CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect? - - CGContextDrawImage(cgContext, cgRect, cgImgRep); -} -#endif - -@end diff --git a/BasiliskII/src/MacOSX/English.lproj/InfoPlist.strings b/BasiliskII/src/MacOSX/English.lproj/InfoPlist.strings deleted file mode 100755 index fbcc2d40..00000000 --- a/BasiliskII/src/MacOSX/English.lproj/InfoPlist.strings +++ /dev/null @@ -1,3 +0,0 @@ -/* Localized versions of Info.plist keys */ - -NSHumanReadableCopyright = "Copyright © 1997-2006 Christian Bauer et al. Freely distributable under the terms of the GNU GPL."; diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/Collapsed.tiff b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/Collapsed.tiff deleted file mode 100644 index e4647bbb7671104bc0058766a208c68e3c2aac72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 870 zcmebEWzb?^U|PdK8L%Zo`xKy_J|I>iLGON`S`c0Z#Cbr>2gHN`Ob?7+2h`vX#4LC; z!qlSE^MQJdftVYMUUap{{GCActt99n#U4`pLrS=j6F=mn11!OULx`7=fq@w)$H>47 zBp8v{Okg%JMw$H>nW5r9#f)rFHWQF72##@}C<6zhC{!G%gHaqN&a{M4ih&huJ_BiRDkn2wa1B1E%1C#~;K3plk diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/Expanded.tiff b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/Expanded.tiff deleted file mode 100644 index 819a88f0b74b93e6599b8685a75e65ff98199a98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 870 zcmc&wu?_)25Ph?YT*wK9NKk2rR_zmxM4|Kv_YE4YO0Q9g=v979;mulXTI0I(5JQP zd6=;odbIwA5(jpq`ZQ`?1Y-`JNsUEOw~SUxX^`I8_wF6Ra8RIJxIEES&{ x=1q4Ys)(fJbvmT|(9K>tD7*cz3+X=drSyWG!(iw9rMt64xPR5_3K%rt;|*=YDZc;! diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/classes.nib b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/classes.nib deleted file mode 100644 index 8d5b001b..00000000 --- a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/classes.nib +++ /dev/null @@ -1,131 +0,0 @@ -{ - IBClasses = ( - { - ACTIONS = { - HelpHowTo = id; - HelpToDo = id; - HelpVersions = id; - NewEmulator = id; - PauseAll = id; - RunAll = id; - TerminateAll = id; - }; - CLASS = Controller; - LANGUAGE = ObjC; - OUTLETS = {theEmulator = id; thePrefsEditor = id; }; - SUPERCLASS = NSApplication; - }, - { - ACTIONS = { - Benchmark = id; - Interrupt = id; - PowerKey = id; - Restart = id; - Resume = id; - ScreenHideShow = id; - Snapshot = id; - SpeedChange = id; - Suspend = id; - Terminate = id; - ToggleState = id; - ZapPRAM = id; - }; - CLASS = Emulator; - LANGUAGE = ObjC; - OUTLETS = {barberPole = id; runOrPause = id; screen = id; speed = id; win = id; }; - SUPERCLASS = NSObject; - }, - {CLASS = EmulatorView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, - { - ACTIONS = { - Interrupt = id; - PowerKey = id; - Restart = id; - Resume = id; - Snapshot = id; - Suspend = id; - Terminate = id; - ZapPRAM = id; - }; - CLASS = FirstResponder; - LANGUAGE = ObjC; - SUPERCLASS = NSObject; - }, - { - ACTIONS = { - AddSCSI = id; - AddVolume = id; - BrowseExtFS = id; - BrowsePrefs = id; - BrowseROM = id; - ChangeBootFrom = id; - ChangeCPU = id; - ChangeDisableCD = id; - ChangeDisableSound = id; - ChangeFPU = id; - ChangeKeyboard = id; - ChangeModel = id; - ChangeScreen = id; - CreateVolume = id; - DeleteVolume = id; - EditBytes = id; - EditDelay = id; - EditEtherNetDevice = id; - EditExtFS = id; - EditFrequency = id; - EditMB = id; - EditModemDevice = id; - EditPrinterDevice = id; - EditROMpath = id; - LoadPrefs = id; - RemoveSCSI = id; - RemoveVolume = id; - ResetPrefs = id; - SavePrefs = id; - ShowPrefs = id; - }; - CLASS = PrefsEditor; - LANGUAGE = ObjC; - OUTLETS = { - CPU68000 = id; - CPU68020 = id; - CPU68030 = id; - CPU68040 = id; - FPU = id; - IIci = id; - MB = id; - ROMfile = id; - SCSIdisks = id; - bootFromAny = id; - bootFromCD = id; - bytes = id; - classic = id; - delay = id; - depth = id; - disableCD = id; - disableSound = id; - diskImages = id; - emuFreq = id; - emuWin = id; - etherNet = id; - extFS = id; - frequency = id; - height = id; - keyboard = id; - modem = id; - newVolumeSize = id; - newVolumeView = id; - panel = id; - prefsFile = id; - printer = id; - quadra900 = id; - screen = id; - theEmulator = id; - width = id; - window = id; - }; - SUPERCLASS = NSObject; - } - ); - IBVersion = 1; -} \ No newline at end of file diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/info.nib b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/info.nib deleted file mode 100644 index 86784542..00000000 --- a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/info.nib +++ /dev/null @@ -1,36 +0,0 @@ - - - - - IBDocumentLocation - 3 11 521 240 0 4 1152 742 - IBEditorPositions - - 29 - 3 256 365 44 0 0 1152 746 - - IBFramework Version - 349.0 - IBLockedObjects - - 288 - - IBOpenObjects - - 29 - 813 - - IBSystem Version - 7D24 - IBUserGuides - - VolumeSize - - guideLocations - - guidesLocked - NO - - - - diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/objects.nib b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/objects.nib deleted file mode 100644 index c86a0e8f72eba08a87ae03bbdfafb7c95cabef6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29653 zcmeHwd3+RA_HW&)>>Gp~QPbiAC=wDD5fu^=mIw(;g4^KJPEwGTB;9s*SR5U^p}XI6 zbkxZ}4RIZ0)IokQZa>9A1Qe0S=&0y8I{f6x=u;U~RD3;*2>tt>d#kFemjJ%s=l$_M zpK0i>s&nr>_ndRjJ?GTjl93-=?$etCLBH;9;SQSz$s3@}42mPM*MQl}wU6fblZ4dgrt*yF05{`tJ zhbylc$dy%BU#quwaOL$?p$tz&MTHVtvnHq3?P(`)MB=aQ2)Y|v^-90ry<7=}vg_*Q z?W*ofq99M=s0r$ATzz;|S9hoom}+VWUByI?Kv_^%Kc%C+xmB-ox9Jhop+q{B-ip$> zA{L7&VPNT9S1Rm5QKLph9&z%KQlfLaq9~7? zJdY50z3yM)0m>A7Yi+_IB$9w^46|*~SawP9rI2WQ-GHVy(TP@!nB<=>F}-GZnsui{ zfRwc)G*}9w#6-R*H#^v(`&0Qym1ItRi+8E3vb8mZ=fu3HP4?UlPeMZy**Et@Hc6@g zlB)FiT6Kq*x`kHcRC(Ll-0jV&e8k)1RS3L@6l0etQaH!ERQJ2)`%0_5OWS+YBAGdJ zj=Liul$wp|iNZK)ZC=O85T05w3Fu3VLCSummUTVUmVkW|{hSw=dA*1#c(m zxTjA_;T#wzSG^wW@R2njm78Q#X~YU90K{iprOr93R<_j4H2hxyamf z>dfdt0Vo~`e939#u4>iY{*$)3q&Kf#Z-uuNW{GgSd%~UAHd$ADAmybg6(qEdl?m+w z$N8HsMYK;rRjW6kyG#UB=hB|)j2Ftk&g*Tn%A8D-WgWe0J?)-0&n*enw4J<~Q@60h z-De6#86+@Q(CeD!N1%}+2FsvRa}~kpN@fEoW;bJo-s(#!oghS+1tQEKX%q_)_L^Pq zy2j=6`h%_+-lYvv+b5rlJz1_OUarAg?Mmu@MuIWN}^n97>qd5e$0UtMt}Zu9k@yl-h~13z)Ju z6cXW_m20wimZ&I4u?Q>at`fnh$I}_AJfU>vAP@>=RNzC=9^%evP?Y|wy3Y$`{$$Mf zrt7nieg?iLV#+L~LupbxO0(itrYnB@w&Pw$dA6`H#F~^%Y?HDnBN7e+y&2erLWK$B zBcc^Cuw({NYcAqT83T_H)sy^imtR*8XXo>_H|u_7Raa;!zj(g(;z7 z>pL@;DUm18(wQJY4@NEwhkq|(y@{dRK)@rS=L)Xu9?Uu;ofWZ1(DDib-ix}=gv81x zNQw265}N_(v?@#R8-(1N6!*qLNQk6_BIH9Hl(8FYI5lP`Q?14D`FWs`~ZMCT5o(y24`=iPXYqTF~+0*%RvoIAzuT^i8;cKc&-Viu%t zU-aEDW1MZ~Dhz|X%6`%nj-U^rN3pJPluN1N?0L>!q+E2hCkM?r(Nd zvQ)~dP&U%(gGOOx5%gqqTf(b$g~oR2RvmyZlJ{`Qqq;n}r~a#H4dA!ooGy=~DzT4D zkQ$X$+1#AK>|zJAqPxmIYxNWh`PJHWKz`jRkk8ZGyv{D@J3ZuFc}p|f>SVO%R$-ta znAlbwr&$9VeOl6~MkIv@&9-Z|oD9A2AqdeiL_vm@D}Nh}#^_XTS45+sal}AFRjbEG z=@UnHtw8E_naU^?mK+Mus#Ee6rCnU8H z1gO2$Nm_Mu^^Uf7j1}dO4L2{243xpgOSWTwQd>o~icDy6HWhRhPeD$!6^kv+oT z=d5seJldmaCsIYmM3I2jCHdl5ecnL1__7z#qb_|VB zLUc%S46no+HM|>W?~s;12@eL(MK`8WmhDFtltqgCwL5W=U3cW)ZOVZwuSQVSJtnnD zz1uS75`Wy7lf?_KtXy}ml1I}8iIz^SsgC>zv-YYmrV1I;S0VlcW4f|x-D}P&tR9vx zbfj9RQR}3-Y?GKTO}Y#$uSKo|yZYmuNEW0nod^is%3vo=7w~FC8e^D1VQwo@&FxL1 zjc+0$ixzrS{@U#%t)Xn_q$Vitg~Gk8qPBTOUb2V-cC^0ju&1dQ9(bSw_OzpyS#@%G zr$yb3JbOf!A&Yt|ksP=cux)}^QckXXfbTwhU%^-8-y6526v9$JuwFv3Gud1(sB?~O>*$sf7xFblmF`r3WktJQhK~u8XGvUvu=i?WZ zAC#3_t{~yHvrnzJS#OhrQ_Z5cINmdJr_y{*ogQ>y#9H?+bT>I)pSki)Px#S0XCRpzCVo?;6o0*S zI?V5!4$~cxbn9XVKD^x)}v(VQ6=?px~i>xmw;JTeZBG3gwEER zHeRmAc8!yYE?p~Q@~J==6sDPKk6DoSBoM{flHv<IpWrAovf3`qH#9jWdc!u3pRwYZ#@&v}Zh@ z7>6>46#Z>X4Exo(G55V}5?%vs;&aZrrc_a`5uiBP;ZUD*J@`zVI8j8UG-6OOJQhN|LmG9F^p!_E{&!CAFP7YWiE{5rRDw~?hJH|!C}<2kxR+b3o?J|+rSqow^_x2|v1nm99a%dGI4xPT zYbOkaq=%kL&Y3|^(_+Wi9%rMSf`x&Mi-m6KJe-BIK;MqoK3ra-~by;I1Sa9RAC23^}N< zTr>Kpth4%emgRzN4q1VFmYfK8wtuy-#)`1U!jf?|gX{~;|C%)zSe@r?_IRZsMg#`q z<+SzItfs^I0Ux_}ro@Ly8ZovmEcmEZU15rq<_^6G1v$ z0#89f!L0J~@;@$EupqW_<;qxhcenUro*~xQ*cdA-D|;V#ZUCN4e3S7AdO^cwGiT0x zcg2bovBw^J?AR->ymI{Qx8FYT&O7hKUVH7e<4-;H)G@+`Jf8s99Fr!CS8)Zs#g|`x z`QwCR?b@}+UV7=J*z2#q9s{1(yYIdm+q-u!;fg)_=%dGOz4g`@@@`jE^=uOt@k#V4 z+1c5Xyk768_uqeiY}2Mq$6tK$#n|@k+r@XsjvcXW+qT8FY}pb6O(*WV@4lGd@BbDw zU1j2-0m5v$FDfd!(Zq3V>(;F?@D$s*bEmixo|j*KIYw7X+qiM#u{CSf#D)wRayym9 zhiIXJP1e7EfB&=3J{to+-xEK?2g&8nfBv)0*PCy?8GGZ6H)5dm`)8hcCN^x?uvI8) z@kF?C`u6SH{`~XLQ@-QxzyJP;k3RY+cHqE)*e9QSBEBDg{Bdmm{{68JKKLNEXV0GF zn>TNcK^K0GvIY1O4&to&@`0(M_x8Hsn`}*szV_$yx zW$f>N|2w6fKs~W1o_ONB0Rskfpe)`#1rDOC2<=rhZ{EC@2oG?aICA7j?ECM($1=QF z?1vwIi2dUq|A>9_%{Q^nKmYv1zJ2>*ixw^VQ$|L{T$F{m6?#s(l#lPo-o1O@e%D=h z{q3u-zKR_?cI*T`G5Q`qeq7uiJ$h8o_RvEQ{eAG@!S|rd7<`NHC0Ym%@ki6XwSxu? z>V_VF2tGtvL6G@FH2&&Wzxrh8(4mha?|gh+_)>dYdTr4J8=zd9m6i32%PzZY+p=ZL z{tCT5v|+=BFQA|Mr%s)^GcPZ1HS*kuFJcgz7Tk&t;UT>y8VMKi9l-Yve5q}z>|OXS z#g}xCa9|yyEf?I{9}8C=AZOt_7T+0=e*?b6!%TcH!S@_|3-P6TsZ38FN+WrZUQk=~ zH@|dG<%Qnjn)oS1F^L&Ai!sN&D(<0OnSWrK2}fp@W!|HWSh3I?syT=CH{mG323qjU z-s}uP74l@h%!b(ad)S!{oWmVB=f&ZI)Eq_r%lqMWgfG1n^9nyh^8^?m#+wRfHHh

WdFas$iKV@>Eyq>$iKYEzq|g7`@Z+dWG>Y`ezO?vm%V&Ef?c=%e%(Oq~yWnqUnCO zuf@|8D8KwOGmHUtU`42{et0^DdR7T&jpf+?xhX%56Q_%$55tK-*nV+*K|KuxA(;1|Ai& z?J}n<4`S}rp&4z?W{YFY2EHobt2#NpTrAXg)nl=6f-3lWz}Z*{jFqVvouh@hRdeRM zXn#`z#z15}wFXJa1Cm9#%6)=KQ97m} z*z&}IEUQhj^CyAZNvGhJx@*!hL(YDhp0GMJ%6nptZI*0!qri(_qtO{lhtH4`Q#Y`u9VP`UEe7?eAXRsXHIm(qee!}R{qn&l$Vb;0( z@=9wlZ5lg6<;rC_Rhk5p!(f)$Dau*aBJnK*WyZ)d+K(wSR+h==xy*mXl-(&N8RDYk z?CgndEGltNND-z+!gM=?i6s?IVP;pgy0Ij=Nr=<5zQ$>ZGlzOJqUb3k znm4z@-RyU}E;XC5sON(J6%nn0h{g(C!vv2x^R?DAzp5(6D#jo(SZi8;GWuM(b65sm z+A}V(q?l~(H7p&E>zx$}tiyl_f{O$L&kzUPHwXr0P^v+38hEvKN*p0)kEORHm^y}$ z8v-Z8=cZio|S&yaFuvxu^A?HUvJ zq>yHK)>6*KV*H1GErF7gJ1-)1B*FNc{(2F|;&<9NAvZ@1l$#?gs%b06@GEN)H%PEB zHa4ys5bin;Z50k_o(fOr6^MXK`qCIg*V$b*w!TnoOo)3i_cgApd}jKs7VBUR2vfXR zzvLYnHTAPow`i<`Nk}YrzAT5OS2}hoG`kYGsH~nc(v=<&dR!u+fpNO$c>O^UVW!zvk(z(^M+r(0Z$_2oY7Vo2V2wJtxo_#oMCVrwWu?8T+k9o`;vr69TN;Iw7a zb6S{O_$*ntviT-#4i~Kq)gh?ZM9y>XwEwon)Lki z{?T}nyRss>a&a=AL3UHnI!4)-v-=_uhBkau< z2qb8ZdY}DHb7#MDc&Ku$2V(mY-)Yj%DDQXps038S13KWNI%xVg36a=bWxX8ruG5#g z+l#DEr{<|DWtU`{{c1+c6TDw7TY1j($%~xxC+O44X}$VWs!Bz!3hO& z)sI)~V4!-eD&dX9!kRgL?;@<-2-LJUdz#!>=gXDMDD6^@lxw%PU&CM9br`3ssKUd(V zXo~IQ?AK*wic(ecV3%vko=xRqWwz3YeViWUX6%5~?Y%S9+s)-L zYM)ScGd@_cb~$F+Aaqh@GO-qoxw*wKT*YL#(k)B12K<=w-B=wIw_1tV7Um8Hw!x>u zrjAcQH>4+YXXajsiPbBMPC;D$G(V1s36utO449pM*q?7MEGclv>+CowWREdGs`lgT zEwY((wQMrBUpacszKqi{N%k=rah+nHo0^@Itl3$xwR$jak>s;9M`$YJi%$)%e1(@d zqqrCDKE$eILvJ*8?}CdRj%8|qZNoZfJk8{+8c!QBh>WMF$p_y!4nKzo4R|Us4u5Kl zpJ1$i7*FAHqhB$u>&x*IC^z;HzJXX@XoL)M6FHWfK<8R*Y*=r64LaDfK&l)ckGuUa z(Z)c+u!b`Om%Sy%8@r4~q$xXyMy~uGv>*Yap&Fjvz|wqU!31ODdgBP8dalG6Tx`6F zYSliHz;_AxH^eFJf?_w~!a%=rfY80Q%lQ3zBl@Xvi^mv3)ow;^cE7CqutX3O7j=+) zT3$}^2X_C7g+b(1&nR`cPZ@!z7uylYFV4pzx|^T?`0e8A#fec!##4?>w_JI8in-4g zuZtsH=9YigF1_@U zzums7eDvtCuBsNlClK_wae#@t153BDw%Xk~iWVN~t;=b#I{a;;Jm$xRc?IOa5^NV1 zU$+JFybHy{^t$=3={oiRx?5dyIvQI&O|Dtkh|wO<9V5(KEsbkGSiMN}ZHFj+-ix#G z=#ccAMikEB)?#8We)s_-5aH@Mal2F=uSxVX?CpJ<(`pHMjrTKQxY1w;7_Fm>^dR)$-SpleClsPeSM`eTtVHVU?r37R9SZLn%R!+a&HscJ|m z8p-U3ZAkbJp2amuqH!H1Couv`gB9r_WQ2lkr-YnBF|5?C!7fEH6@f7bj|Zz|BAXZl zelhyOdnLw`>y44+#$M{mca$6dq;B>x^;6FNK)pp5ol1fHUq!ciN_NlpON^(VMB*gT zP1%FgqmF%Qyh}(l^gvu*EHSDk;5u6Nnn0#W64xt+Vyw+zb<*Q^;}bs=;P$JtpFlETYc$DZKq8W9jr2(wTIVT2Sj zZs+RXH?i#kAI4s+J^W^wO{$p^fo&NgjDhkhtP(hQiNsJMIsGYFzB?f)q8qSMDc|iS#s?&nBa~(HdfZh~F69KWl*=q@3FQ*}D4$_zzp)q? z+1*qFXJaVuJ}UomiJ>XR79dcfB+2Ozt$J~Yt5d$#Xot%$WY4g~lzI*s_{HgGbKLEE zYXq+hQa(TtX5To4qx_jGoP?7pPBM!?EQkt>i4%J4!*#wXm@2*~HR^yNoQw zco-bBog}8AMDf=3razFUB+yAiUOFjmH8T8+xV=}hw}I~4@S|3)Hue*n*wD8Y)nM%L zGeEPYT%Rm4wyigE6r}H>I;yD-I300OULePU5a14@WTdfuy>Wo>j2CI@^woyXW8|Zx za#XsA-6h6kh)&tUl^2ljn5aQHBodYI3Zp7&{vJ@;h;LO+u1DCmWYUj3Huevhkiwu@0pnbkIQn@rH}BcRV&El^qi?vWRezlcF9}Ek!{P zWs58;><>_#heyXo56W>smXS-KAqFVA6EZ$x5aTFh5fw3X0IXMT<1p1ej_9nG<>Ixg z(*ZHNF47M=i!GL!WwjvneLSmzU*%QYI!`Kj~BuU{sE$fJq!|1HhyWRvVKt?d0l>Mimku?YQJ{*kdZ?MSwwAw6`W=48=o& zC}C9ra`FM}x5!))@fd1H#sPv$k)Vh%5|5zCai$S5uoY0LD54$D#-kIn;O0&Vl!(Y% zM~q#>46L0jEmb97!j=P;sPpB{T!_1520K0_T5kjlw8lFm9bb^rpV&u$I>`f{`y@8I z0g0)n0JEh`vQVNXI;%mXgxZqO32ui=gx1C;Axav^un~$}Yh+QUOb|5y7#F7U6&{nd z0Df4Ov~@#h<{=4;j~Pac-DVf1CV@OH20_nMj0v>HEj71oDbaF9R^IgSF+v+TS;e066`@dC+h*?Z$NF{;g#OPvxdNfWM}qvsgttLkTXp{ zf{Y%(98F7IC?Sh5GXnul^yMrQAcrE6KX3?QJTTLySqElnHK!QH37XV8%4NQa7<=)M zL4gx7u+dq*0}nQ*M3a)>;yEJ~b?OgvauGn5f{`_Hm>0A!DX0T70XQ)%D43FCmH@Ez z064KCd_p9j1Qa3~Ez#Mnj8_MVOg2Eoco&cHpzw1%+58Z@>JUJjRRMUAR8e3LBqff+ z+dEgse}VX4t;79;2w_7sBZ0T>I!|Mjb;w$KyEuCUi^0SRgfdCOidSv>I*bZ3nmVu_ zR^U6b?Fd0Kn=s^JgQ5h=5`zae>=?oF0^*EMoLFhYa|qtohyCr)TRJS$9qjOnC2%JG z0?N?KjU%wz7wI+a;+RXj^Z{8Do#|@B_7kkg-_cG7#LjXr#~x@q?Vlol6CFuv!wwQG z6T>}T8}x+$`Eeqv4H`lqOlEkO(n*;%IE%mqCi!$UsGXvbl_@k+#7U!e(qd`2^Kgop zbX9grhfFDyXM`ms-eM-o`G}MQKaV4+hMdB0CR1uSausnfOow(0&^3v*?csHD$Xqjb;iRbS=!jNC}1d30XC+ouC!|sAlWR7MnWP@s zhL;E_vR+c0w1iu(;CA2@FN(Qz3JS_&C%H3;Ud%IT32j>fm|h*SePqlKpgHqXP?MvZ z$AO3xq5@MDqG#p6j!-@ECdG)pNXeJhATg2MArtc?@o30+L3XW7>z&ZstEv-}LcB=k z5m(~HDuFc-4@32_ncSjtHy0rg1{rWlJJ!P3we67!IrSX@AJ&7|@HZqp8>h44Y$_Z4 zmIUY3SZAr*DSJ&sC_sm&+wgbI68357cFKEZ2^^13r=#2OeG;B)OhUtn1 zueY_qg)u5dmMMjDOZlJ^;sz_7(7FoPZhE@qwilXf}Z-owp zrQ&I+rWi`lebH1hPog@CR$Q1ibh~;u)z4~X3@l4ED3F>?2Uo=-WE#ZpsUKL1F5Yjk zeghL0rs{lP8W8(0HOMBn{Q5MA*x5-f_)LPs2+)!GCZ>L(`Kc|%5%0F@3?z6i!RZKh z8$6i6g#@U zR$34a^E^_jrWpmo(uq`4-O)0PUfI)%wzuiK?L`ZgENJ#qqwui5h$LLz_EPV{g{j%# z>P5D`(knt{*tN0LO zQLZ5({Q;MCT>A+wA8~C*)Wg~1(PQ~hEPU*YVqpx|zD81SuI5FjbM49KB8*W2K8Tz5i<=TSiV6Hum zqL9yMT(EZMW2EfhT30lG0qziO^>wu$kks0bUjy3ME7x)hx@;A?d51WS09gJ z4)F{CF2UR_E>OTLqHl6`JMK^LjLay_ZYvMq>2a>z4B`%Q^$>t(b8Q%auW)S@F8#P# z5bZt-RaJ5ok|39{0=a%TABmS@ZX2K%x%Of7iy#0ua5Vd1yb!3 zkQUWB8-RP1XpD~M4CG;PkX8zin`@YTCv6!X9pVKXbNR05TR5W_iD9mh++X9`{kUx4 z8nqCb7S*aJi0Lc1x*nH7P+_Eu=jz<(hn(f${t(yB!v&G^^|*Y@wd;_tiE9j(|IW1v zuz_=wAHviBgwo&%Zxeg)ggA3U^l%66&fsb>E*rT9Nx^M1)I=*U4&(9?*Y+drk6imL zNXh2fg?Q4r2KKScR(l(lJzOI-_>5~iaZ#=UsFADR;{Fb<#n1+TUgz2oJRRcNE?lN_6%4WWx%NeL*IeA~ z^d(*gPw z*QNpVIoB@0)1SG9R@E?6HZ+PQgdF!?u8qaz-??^6RO^SkoTbqcuDyjqYq|PJv=Lhe zabL}~+mSevtAt=RDhIHOt7~z24$eP{6&k<9{mWeYU&!zmV8rDDuAU1nj&laVX*a{# zf%+j_8-=ICT>C0IhO3X^zLu-cq3|TGUKcIC33pfs@d++}f}xMDfN4XXUvurs=zE;` zai4b!em>wDbV9?}9$3R733Wc60$dx9I!d|n5H1&SZ3uubaP6nKe1l4Hna$PbQ2_Oq zMWg7?>bGD}*#O0l?gm#_I;EnMY293#g~Vt{6l)w0N3)gzh7kV}z%&fX;pqt1VBs*X z$({f{EdD_^)8?WGfG=?MPk7qGwOdhO1lLFoJGi<%ie)DTQtk)W0DZ>QucH09_B&wM z%(Z>d26P+T@8{YzNIuF{kj!?%>!8e1u1&zDo~!?ez7M+r%olUzeq4^a0RIoJZNue4 zu0n~}TR0gSm;1STFMtnnZBFz_uB-$I?(7?Y$mmALLDtcKk^#GztKf~HvyQ~ma#-}} z9vA@JZ{^x;NckBI51!_uw&+lFVcb6qenI7TT>UcoDH-NFxeB>sDXU7dD1g*yXzx+n zgQ4w6*}~N~q64``t&TNUV23fTk}EsPGgvfdAOOob10O8R)&GXe5|~6>Fx>Tj!07kq z;NAy6gAzaG+QcaCsr1!c{bv+`=r>WQ#eD#*1*OQ3@Z)@xSjW|M0G4qT#)F2YUPoFT zn8sx~SD;_CVvOYV2gngQx4|Xj@;%RhoY*d|9l#T`^>SQpgSUxdsq53-JR`ds^S95g U>0L9W%G>01i?z$*G}p*~0xMf;$N&HU diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/resetH.tiff b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/resetH.tiff deleted file mode 100644 index ed556af40b23bbcea388895fe599760f8cfd04c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9798 zcmc&(2Ut~C))laq#NLyT7@g7R7?T)VR3dg!5wT&#f(R%@iUO+r$493 z&@i%M$kDYkq04W8pYwZ3U;gg@vq^X}udbbBI{zrwxxaRgKI6Rm4_$ca^D(=GV<$T_ zO#I2KZQPV24f11kg#CvuzSN`7H{Nnx`fGE4(Rc0ovQGa?eOMOTlI$$=74g~AyWjN0 zQIife&QgiOdfgi^I#LS9QxD)7_87h~PvI5*1kQnVFmt(&t;RW+w=NNXo$A!sXW*LRf_$H-8*u7eCe9j5fl-xPhZY*z-1j#a}au@M*YfxIf9>fCdrEz2da{6C^cNB+Huzg_=H2im?|;)n0I#Y1u56)d;U z#+qY=SbyRUHhSN|X0HOMd)>x1?|keaXq?Q)PM`PSdkwnZagzF+EWlRpLTvHAi%s6e zQ1d9l%A>cjz#xg!2MeQ!g{uMoRW7h;e99Vz%;o3P8bP^5>t zXC5}V=VGl}4pf|PVeye)FvsdTrW#$ugdJz`#fm`mpJLf0+ij5XM|#lhziiB(t~mT)bOAqGUdCdF8(8U_1-0WjWPi4I0d!8^fnHz{#nC+& z2})orDD8j}>~JRLSzp7n{b`u6ClRAIhhx}s zKlB=_Ud}v3eBS5BKU0EZi0cpM)2PmaCMWfq;HtN}62l-`_ z=WVPZe=0fLB>P;!55^ZTTJtQ1tA$~};*;nyY(^6E5%Xex%=7me`+)0OUzzTM5BC1a z2K`s~Y?O-m#D4|(e!WLNw)@_Jc0e)oLrRHP8F6gqYY|g{L$MXGVw`OU z-&@l2{eicjX=IJHYu7?))n@1f6p>FTpF9h&>R2xM_aCH(61MS`uuFIktLP%=S)aiA4I81Pq=Z?sW?`<<+pI4ZmV+@+!ni*IX>L&%|`|42;)1kKyW3_*5kjT}Q9Xqw+MVou7#3Z~21P58Vj^ zI&~jt-b3Lq`jQR4&^U`plxMRouR+O)YLPqD6rW;f1(p(jp@_eE6!DL#6!Etu{tgLM zIGk98BLs(dA&id(W0U$eC@U*t&YU@zK7Bf-O`8VAB`dKvsF3`44?00**m0_u>RcgK zxa4B4Z62`UMo4}VfLX+d~28nd5w7VT^$Np`MK%L zkH9=RW;*(U+TBty+b7^X5r;&sm^^ZI-_8?-wbjZg#g*atWi{{Xg$wXlw++GKScYHDhteC-%7n++VG=MsxO zPLa@Y498BpV5ts@q{IH;T&e}-IC!=O`=V-~PwN$}kP2+^E63^+C0OWKfa#VuF;*`X z!)T7}JYsSL^Az)C-ppSTM+52in67_O${tSh%Qt(|G2_rJEIN7ztG&vg?q3OQ0j-B3 z9$it6UxBLUd7SslxlFPG*j>#%003G`i~iGMo`-Q!{8aSnRUG4FL)tPJze z+oD=vmGF@4QU{}`TI@MfjU7Q%Q1dCrGPiqBu*=1_`>sM>GZ8%|tj=bh1m?@}&-@uY zr}5f-eD7&G59D{otGzsvT9*?>@2oy--#6~R*34P z#P-Y7G>B&u@sEK4>0m_M&3rGyD)#F<<7*{JBPPE{r5h8o1cLY0U0qOtH8{ z-xfpFs~qY<51@VKAq=A*LEkeK+qL&%<;s;%R8*AmS+Hz1bPk8Yz%7n&mTaB?GoMsg zg=FGzbOBt?3E`YribEkcrQgh@x^yU_2=)|@_9;(co%9su@lVK3kFh7B9y>zo$QM;m zI#!CAv`!vxcm=~(dNeUlF<<7*{5dZ^A$(4lJVe#2?Hhwj_{rurmbeMAj@HE*p^va9 z@+nkz+ezh1?5;3(AvA6LVc>p_xF?9>#ndN_xZlK)m^(O@bRQ>D>)@U71n#M|u#3o- zjxl$M3T&hA!SQ@Oj$Hf|b}27lne+ntS3b(Zt_OTyIQE1a9YHMt6f!*@mBZU}e?P1+ah(U`_DkFd=?5?oItIxJYQ zKvaiz=o0NYMg!eHfqVt3>-s0TlS>d6|+b1tRW$cFp|KlZ~^F<<7*{3SYkMZc#H znP*z}-Tv#Cd$a^9J`|H7PoN$790sw^U_^0h7*Y(~lh?6kk1b}-o+IV6c=2MaTelAS z2c6)aQh`&~UcjIBZvI(K2%!BN!~4op^37f8H}jNKXdbVCOFHcZuQtOmqZxLoO|VF5 z!oG8j(2aSC9bwO~#;*>G-0ow#bv`~CKkBf$Es8H z*cSEzyJH(*c=iR=j0Z3Xx&s~WYuM#_9vTjjP}ypT89&XE@>;fR8P=~~k3$|22+Dbb z;Jj8T{4yJGG`>{Ycb?Kpn$I7=?Mfq#-)M#NwN^M}yn|KRTbR-Q)*zu7nvo6I5cmX2 zC#o^it`I|KX%=+QfqDOfANqVfGkJ>nbu2nwiM4@Gp%M8C`th&HF3m8bI5ml^fKgx` z^iN)<{d_X?JPflHoHYM?XmOq1(VO zy?)%64keFjs0BZVW=t~-lUi}$0@)|E8CDmb!z!Vg)<{KE+p}OAa2ck4X)vetg^_y{ zl-0ILIda`nRaJ%NZhf3gD@9Nq+55tWI=H6S!jt1H5AetaoNog5q=)4tz%-=|yW`$q zOIQO`eCsjWz5qRjjPW8JKF)^^>XK}?UIr621+SGns<4st-*xsaj8gy$8q@A-E1Yh; zf%ElOaJljXju$IopKu4(5jSBGk^zh0G#nCSz`!K{^OgQF?{!Tr;S!$%t^-^X7A#YR z`_)?bMi^bL7Sj+J4fpaEKO?_hF~>~aM-Og5tBJx=7e!YjW8CvzL%mGubjm&L_$k$M%+?1cImB;)DAI}dT%+vIKe$OFe0_GpiAsrf_72gKh{(!dYa3o*5 z(b<+aoz?l3v>~{x6(Oas5mfXNez_0fohgLd#XKBMxK8t0Ivfc05f`!D#1cQvnk|hn zNnKv3tP1a6Y7tOGb*l{UxkvFt{%|Hc(e?r6loxtQz_zG2Q1+@qpAp{#Fh9b_^EB(g z>kiR+iLSF{J9pI{t70Zp3wj3a1i&PnbRfGp(b(>HNfw>w1(X8pyeb^3CYJ~AD7z{ zx8w_R@;zrdU{4}Z_IQs-hc-Dr*r*9Eg--MW&XE;+*gVQ-hIB_`(t|^z{ zbS@2!2^V4N6Nsg2*Nc3zXoV_H(IIR|Wix`S$+u(|FR~A9RbWRxH>aGSEf_WgKSTeo zz85erF+X{_GGFG+{JC*n^V(w=VFF>kjBID^uNAjtZ#_fv0{MZKzo2adJjmat$Y#NG zt{P6~r!jOE98YJ$Neuu^O}Nn5hLnakNPgak__`!^6> zAM?aIZC&^m*FsQ3XP9+Vdr1#3@`Wqq1?yl&I%p@n#ki$<+02J|iTN>4=F7Y#O%hMM zKl++5gP_{I?@(6-{lI#?I!@SxmwqP%9m?+B@A88muw2=fs0VP3ztpQcx$ zHEjEyy8S$g=MiOs#;|W@#cG6>w;iIhYG=v^Ptt*wlc1#xqA7+FUXvfl_Nl~Mq61A+ zV6ZONNS7<`-XX2I8A&f*Ac}RVu0cpu9m48gLh$$vf=CBn(!q`Lfo-LK?rGb|Ns6&7 zU(AE~j3P*Uz;nXKP2vklUVK9x6bNew8Y3o<9)Y)8Y;)+$o&4=b`5a1qU>)LHfb*oo z#SS`9D2w>B4ia1;UDDpZ#d*>t?$s+qKYxXY7cFFqRs>Kic~OiWrMjmdTi)`;cT)Z= zpLsAJNgi;_NOGBee$Y5CMCW{T<^9CB1kR%k1dSo1zY9^d7S!A4G{KYP1(5B+C?9A^ zgG9;$n$AH}iPRUY2m6Ar3<__g6H-W*M9P=gCaTH5(wgu|8+^$o&UfEpqf1=<@UcH~ z{ILC5F3V>g%%?Ab`7zJmYpfgRI`8q=XI~M1AS@(oBxv*=IKp-68l7yb>yJo}R?xB# z;pB^0@jTbmKiw-9dqgbhBa>> zAb&(tUc^yMF~{>_zR7fzfS=QJgP6CZH`TJh$M2}ly@cukH{loGP8Y~_?xIIBB=%={ zESKdo59Y(X{+SQxwX|`+t_04F!2}+M?ZJK(9-cator1j&S*9){v@;;mJLvWYwJ&bug zF?f8I!}3@z%V!?U=ilW|T}8g?s0Z8OD+0%*0zsL;^-dyJqsJ$Gtw)ZV7&Lj=nsnuT zRzQvbDCZ9%iC-+a+`GnqUu%m+ZIh(u`d0y@somje%jBvio`it7W{Ii5dM30nwKUH-st{+`F-@pxPwpXIPTmMgLU z|CK*|DryovI1V|V`VzRlah>M*hUfG71YXCe5!4C)jy~Lv`}24FJ&(iV@whxb%VBwv z`2VB)X$Wa!e{?2rU1Q&}jd;G~c;)pKuM>Ga$$XRu%xx8cV|%Um%J=-7-*Z3i&)@O) zJPwb?F-%GBRh=w*A8Q6k(INESmIXy}L=7DQA&@{oAV8**LJycC z!1Rvk5WvBqmzds6LI>M4pPldI&fDu38;l|Bu}1H`d(S!Z&&)q_iW@ifEAHo4bb{Zz zX&#v-og?YxGlNLRWQ6Cu*S?JVe>TMpF8}oD(^trvHEWL|MT&e=ty;C69XfP~88BeL zqfw(qB@P-i=uxLmonmU#sIjwX(W2i31qJn>KjTCgk4^8>9>t!~({TFix)4NlP6D_y?ghXB}EG%N7$86Js7ed}vbB;^X73 zZTt4^Gv9vut@-%lj}K+fo_&DKn@0p&{*1UVCo%tvw5Fv>m0I)VmtR_c9y)Z$#Ky*& z=g*&~27Z!0*nHx|3A1k9I)g7h`skxI%#R*NA9~-mxqbhE@TOnOmMt%Yg@u{*>(^V( zT)leL+`D(rJbwJx%A-e*%!3CH?6W&}?iiK3ckkNgypM~EGsJ>1w{PDz=gyrok&%%$ zCXzQ7B*y&&cqWmzjfvtX?=t7ko%`!vy?VvXm@&hwTD8i+gX71KTmA3|{)6T8>C@J? zygPR6n6;Bne&ciA(~mKiE?u&Da`x<5bL7Yovth#qLrx7IJUA|I-n?I!8qQS2Ba_yf~u2XKAS5fKq)(V|7xZ^XZR`SKeDPhk=A9DLwRsbM2^El6Vc#gHLG3^}}D!2+{v*)oeC zJ@^eizzzHkCO76YXU-V%)K_?p-@)FlT|3jcb7z|m%!4n8De=G#{DmE?A7jRhF*$SQ z`~qAKzLa8tZEz@1*3GhY>(-5)Fkym?>C&Z3&DynVt^e^C`0>5+1^oCLjMN;J^XJbS z72-5?>Qp1O(==+-$W*Uh-Lz`e%G!V*5MqLj*g=gV_wXN_YTC4EG`PU$;7l$Stn&dP z*`+>zK4QcO%OQM0Y&UP-?DfCmSKq7O!478XtO~YK3qJYe6Vt3&GgGr>O(S~@Q@L_w z)1pNSi(7f9b`TG02E4_8-+%wT!JiU~&%x*51h2bk46?|>e3dFyikvcKink7dAO7Qi z<&JV)eecFj?ML84&z?OkRRWHFK*cv+1RQb z!Vg;)n3MU4nc4xbu!C9!rxq?;XoMT_;1jGG3wK_S>+mdZjvP5gjvF`5<`Z=kUr>MG zkK)Jo>UVHoxNyM={bWCC+O}C&#ZC;^pRixWH@-Fy1LjjZ;HdIy_wL=6Q`B4P zORikGMuOA93vL?mU_B$}3l=Y4eEH0oGp+4#2wy0E{Dkk}x*I#W%^EIe2Ai*nkxyzf zHI4NhPOz8I_rw8y;uHM9ylM+}z$@M>r^s)q_shZQ-~~7Ml}9<`dohW96gfyfQ6H#z zV8mB$?Cf>$8-DHDwJUYQo2y_PIB=lFPEI21v4|`FblU)Dn1}O)#uGg}!w&pMEre5y z6+Kbl6ag>%2S38v!QQ>3;JHrB8AA++Dfsa}I>1g0nD5h1KQ+ypH@9_CaZ!I5&wKn2 zm&qwOq5RgqVpkcUm9x?%n%3I32v;20t~5T*xm{ zR`yzP_>4TJKHv*<;3xF3{`BkD&&VFc)T&j>>r?WVykji&2%p16d`K-&u49MW2Hr8Z zp7+?xBkC*cpbzT?x+PcR!0F%xH~7hmzlszPDKC8z*|RW)7~p^A13&qy`t`GZ{ra|k zgBkqnArw1206XKs$S2&TOTzMNy#4r&$S$P1~liQshbf*btQ zS@QWqkxE~E^;H}g7()!;4>86!=prxSzT&7?ub!<##0LN4cWehc{lWC>ufLk#e*4Xy ztFcSR!b5a$-sV015Y9!|qjnGr=7f(@JBULi2QRq6uQn8t?^T3vH`&u^48Wmr#vW<~ z+!R~wnyYvkHf(6xw{LI8j~{PyA1wFp-?wKs&YTFoX1tDJohHsa*RvmILe6~H#B=N* z|A+l~U*KI?v^Q?;OVU80sa*46{h`I15zsW)N0dR(T*|%@sBstxrNfY+V z_MM(PIeQ}D!tZVyn3MDBlP6E?*%VvV9{LjxI7MBj&UWe2<+#fRaQ`6=6)RTUOdP01 zj0L~?1v}sfbpku7zX%-q?6c3j*yMi6)+=fh>)x|x&+MH6*zmjBKwTit;C}k_sYysk zu;*;f+IlX>4q`!_La*FWZFbq}tZ@n00FRgh9^faPAA9f*xehmoF|}CFr>v3G9L1`6KXT+qyJqp5cWxV! zT-wMF?s~98^9WAJ{x2agFpxVB-@24!eUSH!BsZhMhL4y7F5o9^_zRneH#Gzwkw5T; zcwh@_JZCWXo{zle>_9z!oek*1XT*Zoqa!plG#Y#&zUxDhbz0unl{?e<)Bxgu&%x~5 zH1_H%au1$R&lrmh2)Tv-LqbBlanbm^Dh{fT`LTieDto#4;1ls(r?G*3huts9XNbSQ ze-F9ii6MU2;EsXLt)INZUvL`U5j*l$_c>|{`wh9@Nn%H8Y#`pmdhFP-G2jB9i0^)h zeINTj^17f1_tDKulqeC-UIV_QreO;lCU>Y~)Dr5UJMW1JdrxX_YPf`6Y`~Xg%a#oX zmxHgMe1aF;;HQz->^<0*|5K!{+^zSJvu_kN;Z`d+M>) zCEt1UH$3Rpty@%v3>k<4JOZEZ`9U6e_urh4iilJdX(jiQVRPopi3QV}w&e1jy%D*> z+CuJ=JLC~OOsUCPK34Ag!ocI;0$+0HIO4&2mqmp0YH5*rBL68_vg9J!H$H{)Z`z0n zw)o~f`wj3@zsXnll3bJ8{Z#J47lFgU1Fn?L)AGvhVeOe(z84l@9cd;KTD5A`2w5i+ z(_#nMu*IGCx}SrmTDyI15Ze-K)~p$Ueg_A5z@;%@P4I0R3(boX(xHY(Tai$?4~mdA z<7skr)>nT@zp;h9hdb~bAqKv4;(uA=6+imH0Upf*IHS2NUz0TIti9)xPtFr%M98B~ zBB4?n7RmW6mVAAirW_+S;O94u-?Gn%mAgs!ga6TsesF*%NCbS~OsQcTHHtGHF)JkU zFOm8p{}u_&moHyf_wL=J*bAoRe?Q6Djty{1&LC0w^XCskkE0L0=m!UQQgh!b-K>qo zDzivV5$XW@6Xvt=kUH0=T)A@La^DieTJSb`0-vPL#>jp-T<(tghz|8X`p}DhaDWF~ zuZn@Z_BQ(Yi;x?+M3@JE5LcTY@);_3>VwLZDf5HeVMI&aOyK-N4Z|hy|ZB)FRBx#K zuWpq5uW@0UHfTN3pWskEfo=dLJ+MGqG~^J1zI!kz)5k`QOYa_jqSM=B*)u z9`vEtjX$M4mTt*5`ll1Y4&n$O$t&sub&mC;l}Hy6uPtf#&UofwKIUb9^q>#D=m*D} z;+G+|sU7f;d>Kd`dN356dmHi9*MD~;5X(R%+)*^7bo%6|Wp7Wl5^k*F7nTPq9m-*3yKJ>oJ z=8j2#Ow7Ino%pSwNHLL;B4tI&i@*!+A5{3wbKcXB{sl!C&pgb>yzkQYGF`F_Thfc5 z3!V6l*yj+*Bf@V3w$$A{YoFijpP6BPUTrQOsgM za*(KkC@N;6@Xl6Uz(sdvcmLVh{V(77`gOQfr@E@Ux-WC*wiwo;#Sq&Tf6XI7Vk8^U zlFC+u*1rR8=l-U#{NDfP)5M#3wP_*IYC_9a-Spab9_G@mkLuMQr8gH0l|A}#^kir8 zu!+_mrG{=P=+)%Kl-yR>ZGO^?S5?={%VHvKQ{VO>0zG|v(PiO;r9T@}s^k}t)bslWaJcCo)C++l^X1Ke}$#HlQ3RQgswji!W`S>EA6EnS zTc6>5_cMI%*TCm)6}%HG;B|-b30{ex;Cr_M{`ad8@Sq0%Nj$b5r>@q+BC-;jol2p) z`#wf22t?PxYYQdY_Si+lI}q6C|A|kU__rZB9b2~Vf2jLt!%As2Z%oyT$70JAY;Y>X zHlJtM9asv3U`8?hF2c@$0_^h7$4PEtvU=i#Ci#=|IgUboPQ_cf4G~BnfT}5JTPwkS}jgh*gfs0{>0!Y0&k^z*f%;sIJ?OY4cWL_6BpIu19T~-7^F` z);gs?>r^t9oqUKzb`LPe`W}=H-iDk(JVtJe!cPl*&~4&@O3Ai84ZpF2s{is~{v3xL zTeNJyq{EJmz7(8}5hRe?uN&~9z4tPYdm5r_5Srk9%WOEv{PN!gr{R7OiO2kZyTae##1tYhe z!=Tl{=sVv79fz(hVjcpYzpsyfW(3C&??1er2DR!b8{1XsIQlI0#lQ_=7`-zVlTEKe z_0VlBI(DDtF@@qH1G=7Bv@V!qE{uZmU>uwWlfXw9EHe#*2wd)=x(T%#2j#;cFb_M( zPCc(|Y$U&|a!P{+`BUxaU7DX87;kt9Lv*6hPcsnR=eVME-$}8|r;!))W1fHXun%}& z>mt#v*S=1ZEzxbE7k*e1ilJN2(Hvcd3h`e^zF%=V6&u_$q34~0o&I^mD<6gd+1O+o z4YSaE>&iJlrFe5ZU85*_;NV_uE?nCI_3Y#YZAtsx1S)>3m)I{)T^UMqtkt#=Nx zMpvM0aR&>ICD9tBb?KfBJzv^)MENiZF2qKw2rSmMz{HvAFb~g%sVI&3D`4PAd7(57 zOv6EHmz%j5OST?{&aoJngcLzPumIcq@}TXJgH_HMSZtpR)gy^eFujHmJ1(H#+Aw^- z$OmnPEKZ^ANv46H!1MQf!RLo|gzhcc^)PL(XoW5`2R~^?L59}Zv;()GW=ng~DcV!q za-i#zNBj%0!!sGn4NpTsRRg0Y&%rO_m0%H`i+!RL3>qa*HcS*su3JRp3jJfI{Dw)h zmtm!;JM{gtXg@B%7TF3Z|JSVvPP3NNJx%m!$!alu}M$egx*pG1J@^9A6DSkZe7-^(2$3?z9gL z(mjuH#@8_8&;u;6PluMvBW(06z}5hYfuP4w-*p1xrq3t-v~DT(7jLtInST-v2B*P1 zFd2g>mIjTK6H2Zh3`xgc??f!nwWM`EMR%opVXw79D#X==7Td`mc|~h+S7O=|Cdp z*rs9W=^U)}D1fftW9%aSD=mUCX6oFAy=Tm1n$MFka=!snpL?(jPK9MqGKP>1gGb2; zCD$#?~Ykdg$LuT51Y_h)u{g9{F67U!syb7_xB^UGUGoVQGCu4LS zKkJ-F*QGv?=+yUsz_Wob^X7;B!TF5Wyp&|0(IGvScwrFb%W)<*G5ts~7M#q1mRkWf z`O;hkKBavq7fLG(Fm!@4t=Gwzt7D1X&R1aUaRUcM4{;yBLOXxT8 zxCwoi1k72tSMc9(ITfg`-v^^ml1=9oUH`{e<57gAj=4~^Nr%FLyBNCTGWt@EZPi~k zgn2gdW!}ucDUN#3Z|OF_s3rBI{4#uZ0w$S1!0cn0Sn8aQwO&u4C!+IEa0yl&iNbJ& z*}^=IQ`UgK>owwk6XpTQI2!Q?wlR6I3eSY}m`P-Zyii(2WZ)RLQ@=T_4Yp&mO*qCX zsZ$P_iV+H`*y2ogkI-k>7F3LlzE7d)R)l#cA3^bOGR7F+gp|%Xv>&-NiFp#3FULRg zXK+sAv-^ln@>`xsZ90pwd+v}A(lFm44_Y2iu*ts!JA$7JI_7M)!mqN*7)X2nqOI02 z@w`p(p9-7kd>oH^h7)ncu!+jSFER}_aCs~`2M%#hsjmdqQMtl;G4{L(wGI0OUk;rx z6HAQGz&N}VyF#BsSM&^Pyo;eu=SmgZEXeJ@k6*T3Mpq@HXUwyaFY{*pyhrg`7(kHe zG3Q97^wu~`-2Z^y&4Ide5!U)XgI>@J=!ccTDEt}Z7wQOmjyAlJl$V3{2P5$DWAiFbsQ% zZ6RgY81S5Y@f2z&@-T(Y$s_b{px@%tmCUn|FY{*pye_^Y{78`Pt?n!yzUwL`Tc+W+ zlLc5#=VI*uk{MbK!^l@Kjwr?ODf5NBk#n%AKgAF6KXJJX&ez|<_11f`<0b6R7vh(( zQ-nDBl}fHVU3&=^>UW}XC*oh=XcV10XkD-z>2cFBYWiaAjd}r-=yL1~FURJfS6Jo! z919$uV7hfSWcDWF$2CD>=Gn-Xc{6|BXL&vUOpxoh(5`Zf(M>2?WeM+UdB1>8&};0B zd=D#XO<=7|nlT70%qNh6lm@_IsR;e+H|tG#m=NFO*z&qjt}GRl*ooy5pTp zD5re#5Yi-v^TjB|Mc5bp0%oxvV0^v;+ao?;W8fQTcs$4KlZ8;QNX3r}jyz|c1m@e^ zhOUim3f(8HNS8HD#4P(lEICt#^?~oOEvf>>vDGlU@CjzoWsqO6iF8gCV%R)53r@Ey z;gKYU*F!P9lk4I2pc<~^i{t0=VH24plw9|wb|32Zrg0t*>fm^*0y`Wo&>lTQkf*q8 zC-%p@!v2eu*h}}@T`^VA3H=BypVv@xEXI_>8R#=rC%u^s%=;hw(0TBbxQV8>G27t@ zmid%JJM;m)HavZ!& zdg8?}jID)kL?u=Qyu*B#QYaqHLf2s`am{RK?uReyp>2aZ@T0*lYQguKb+>Xz*~@i&ie_oc7$1NE!* zSI|oN?Ll=8C@hRIEbfoD9dDDG@&&$78&2g^GET^X_c zycp|3tD#P7Q%YGkh4~S_%@1GYY3f($&|BJD#p)s1PyyYuV$k&mbX|w_{d(BmuYk>s z=QwgP2g{AEiNkcrD5_${B2Aciguy?f4Ch_|v4r#AfZM&3p2F~y50n-z!|16q>ApQ3 zYb_jM9iI!kJCs+Fs&I_fJY64PdL7si3#<>T#RBK2=-hv}H}fNWo2S_ZK6eP`B`T*$ zwrZm{bkW`dP2V@rivf%h$Of7h8a#^U8z zXM6yM1J6<($VB9m_qa&kD9=8tfal$89P|yxYJF2EEz+RzDs*R3!YWg19J`!}Re@xywtCEu@a=ht&wYIU<8>`X;P253zyEQh zXyK_GY$iV#lTQ!c1?XA=hm1O$&iDj}r01}|`3N?b9$>>Ed*U<`<7Ui){G54E(a^;F z)$5_YQ3p%4Hwz`#xm|wtTpFh$jMueuhW+()oVc9}$7IU$*_Cj5R1dnU;BXSzKx=}o zV9@e=gKh)IiI`U-KPf7iFY{*p{P4QwvqxXTNP>!lWGlVFGu9`q3!?l+exTzo=o*1j zIbyix*TOaD9h_2⁡^m)SYy?dq!Zn!5-o_6S6Z^F>%&xOjMl>In_Br$#vP8vxI(4 z!@W3q{t6ru)8Tk82d-%)IFtJxXNqd!lrM%o?Qv|wUa~F-Ju%vI$M%RGZ`=ZM_bRS^Pd>VN%zu&vZu|GK9@jaFAtD_0C2&=nEjrL#W zoKmyrdOeO%ES<;!Tp!cgEUANkX%+mQzJX7EF+8(!;gOLE&-8ToWMm*9D+>YH*_1OH z;7@g5YWJdkPa5ZyoeTe>5{OFQLR3}_zZdoJpndB!?Y*{?2ifl%{U6u#93tz_JR12h zuRpp^Qvc7PU%p3R z=?errehlA7kKjjq{fMtG@%2qhgCCV#=k|cyT!?5~$cr+Bm486kyBY+&sfX`Nz@2P3 zN#Fl@u6CX;7Y~q`5y|=+c`%SF~W-@ZjeSsB8MixE;-h~T_D1QBO0!-|R!QBs1amoIVl z-8-DEtVDE0Ey6$1JiH^nmI2O`TaINB|Hz`6pT>US&-$4M^J!WK95YR8nSOrt@VXGb z^HIt7i7^CTM_L5!-b2Rvt6PZ5jy$COgYU`SQ>Y(t{zd^tlJN4*qFQ>63>EP{`WJf*dScqWa5m^Jo z)Qb^UUyqA*b-48TGvbNsrJ5R{jHmh~YL63(aUPVz>nLAWk}uyj@V8F=h$*XfC4JZX z2Yc4jsE_rse&)e^m>2W=BOg$g@UV^StB!=81l|Yue8Tbse@M1$y<@w`+|)@|Dv_8%(ar?g>r z%KrG2YUcvlBVSb`@KYVxBSz$BF`{U`>DY+y8ZkmD>f!&Umewwvxo&1w&(bwY`C;UE zzt-*A8?wAcuzc3T`dBaPXCBPw-{nt31z$C{gXdu&f#Xttnrt<uQRzHuRf$a11ji{{F`N7+stF=63GqaXg;iYl@lwC3jN$4^NXl zY!lBV^I|`J3vTCr9>@4=cy}f-4IZR8m5^xmTe69b^eBmzjqNm8qD|v(;vmsgV9QL} zN%U-NC!P|$o7#t1O7s&fp)t}EB>I2(Jyl{rGnv0Oley^c?If4|)$rG$?m&wczjSHQ GSpE$k?VslW diff --git a/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/shutdownN.tiff b/BasiliskII/src/MacOSX/English.lproj/MainMenu.nib/shutdownN.tiff deleted file mode 100644 index 61f5a7dd98c86c8695316bc91ca68cfb128cba31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9798 zcmc)P3Dnoqx(D!H4Y!kAMUh*}>PYTgxQJVlDO0B6pv=}~p=DT-BvXz^Su8^=L&uy- z$dECa%1lIrOqD6gOqvYuzRzc$|9b9 z^#V`7E?v4jaK;&DEWGKao6=*CJ(ga5_0{y=d+()>KmIs<^2sM@?%cU)&YU^vjW^y% zPe1*1y7ksuQ|Pv^Teofxv~1b3A3mW2zwyyOQ}c=Gwb#I^S( zn{0CLIp>^{?KySo)HHwo{Pg3GKdub?W!BL7_19ld_uqeiVvEf;-~3+u$*IUA_aD8g zZU2Xen*sanx8Lj$BSxeL9(W+f%ts%6l)nD@>-7Ei-)CB|U_tu!+i&x;FTeaU75eI{ zukv&Aixw?PeBqtXKKm@a^UgbI^5n_cCy_U^!^Z;xc(b5?)F%bMyjykcwbveY!U-oV zy6UQ{(%pC8oy5V688fncaU}j>nK^T2wyn9>UVAO;X>`x#=B@M2`|rP>^W^Qf-%c;R z^iq28!3UF^I`!037p=3-I>X2fBLCOKRyF?SZQ8UM-oJnU+RHAxER7pCF3WoAsi%@S znl^1(mjB|5FXnsCmPaqV@Iu{lYhix*<(Jbdue_4S=bwK*J^JXQ>CQXv%>Fp@%rk34 zkKuv8`LEQ2-t=!Cbz>0wi`P-3My0#%x-0AO_~VbKC!TmB*O_OZeKtM!+;a(zf{$*2 zBSmbav(7pzt`X;}}j~}0Iyz$0##T8eiLk>A)4jk}QaQ#xAiy`&r4?*i~y6L79 z&pYqDG;-v~>;rz5%X|($+rt4nj3wrcbcnsKj_S|5rwhNZfqlc?^3X#Mr3n)zq_Jbi zX1no!=gyrc2A&Q<@*F-mS9H-)U273O{PXFjpPuCK%{SkiZomEZjGr8K6AxkoR+#Ny zFwwL8-g@h;Q|x2OXwGx^_``2GP8T*{3qIu!df-D3`^WI%!&B?lt^W*H1>cH%K{qkf zJoe2_5d+gNy6B?p)7x&lE!}tDecAr(1wXl^-oRtc*=L`f_T6{ijE{Y{+G?w`<(6CK z(YX_q)C(N>|gN1B%ai(K7IP6-FDk8MNgD*!PB*C*A#t79^JFM`Q3NlJ?+2${@KTT ziBE|?>-a;>5Vve|-F4R`_6%PPhOdGX-s-FPV6}MIHe^q}{PN4|>Ja?mpZ!bhup#{X zyw_fP<-FZ)yX|rv5+7otS_k)@A9mPb$vXKSwoR8_dTI7&@rgC^ogU(r|J5lm74J-j zF9=RCQ|$}!m3`2-apPVmpM3J->#x5)+dvJ1U*3sn_9E}Cx86$XRj*#XGA1!kA9}$+ z-)bF7{>UYL$~N00s8wQW^ytxIbuoN_wfLesFXXy7Tc=g4Rzohh z;DQ`O>L^>lC4LHivcy>QYPs&fuYOo7U#fMG4|Jh}=cWG8*L!@z4&ugsjknk;`SIkF zPv$xGR()A(t+j^0S-}gpi$CmVa=!hB8*VuM>Z`BLx{Dz`E%-~HAO}x6>7=ydjyvYM zGi1n+oG)USzsQHTeolK%7whmo?X=Uf9?}2i{ZJ3`?z``1UFg9d)|Z%)-%;Rr((st^OCi4 zgwEE|Pi*(=*KaPI6})i6uSUs*c0rw@$62H=mB-?NJpRS^gAYE)dK`W9(YZ#lv;GEt zcKh(d5A)f^NFVWTjnRGeJbbXJH`cI8^p#nTb$VL*SjUI<4SQeY>LNHRc;SX$Ui@p& zx|O|72AJAA^QY@U}j-+c2;=Eslt*e~pP z;?>#CT72mtruaf^L?1s7&LDWJb!b_6)-CGH3_g=f-Yx!TKYEaH)KN!exnh{E=A17J z(TCo0z`W7D=Vi^pg$uJkmRbG5 z;^&`#PD__A&AQRu*&k-l%T-%jn{9i{F~?*-;3w|*nvdvfq&pwVb#d3BLx+)}L;ZYM zrY<#W)@(rRaZ5@a!Gr%{LhLKY;(VHOP%W{aRO5rwJ)855vHrYg`lQk?o^r}587Fzg zpY&h@b`ulP|1D|Wyt!{4_3P3y`$Nq4Jm{curtS?yJi#4LN2i!bOvUi5OK z;0vn1Pt!r)k^7|>w{Oy<$?@@xXBPj_q3|?{Cw0g^A;;wRPCM)J$?Nt(zDMt~(MB7M z(`)c;^~JyR;tM%rjqiSHi#||%^U0A%9+~9pvBw^pNB5rFNF0n3cmI+!V5S2E_to@(3k&bP>=Ywetdizng(m}1HOK<6`QGB>OC zeIL*v&hqo)d*29nD!AZV-Z_px?02gLIj?RSv}@3RZ@lrwW22{8T51KpF8A_}9&m^U zI=}{_J(6yP+!yTDSF1ldRa6x28R zu?ewH)>i8wriwqrLFozPNHt#PhHAZF7vJJvonDdsqZZXh&QBn}f&(77iVy4w^{?WK zk{27rg6=^F1oe$`?}V`5()#vtFV@r^HieB})GhrW%;o&S?rKcgH@#P%A0M-S)VhM7 zd^q4Kc_3y=F2~PhE_F74=Zn#KVzVH5bZAiDs10M|JUAcT>WfeK2qv{fErU~>=~ayG zJr{okdv&eA50B_`=Et{5@x%V)k`D(wErQ^Kb43^3)F@{>K3gy7zk+rPIxMJf+qP{- z9CzGt)7V>2P<@s7g2f!HV#Qc`j{3O0@0qw7Fkry6cJ11YAg3aaT=L<7XJx*(#M9w`sH!)?WljqDE23h zT=L<72d=;8gP5+ntZNb^H`WTmhduZ;=SPfvgv+-d8@8g3XzW9?vUWxx-i$7S@UF^^( zNL}MwHnLxeSN)4VQ9lV!&mh?P1c~hfE2DeQ&0A-^_q>k}e)!@~4teDMmRGe;ng(Ni z37PEHK4^oWje|M`bq*32zCRRl@40#FtZyIWeSGl4_qVituv_j$mxe)Pk;!g+-zun0 zkne@!`Hw;CRgrto&0A-^_q<=Q@`x|_yWz}!b&0A-^_e#wC zp4da|-&{o>IjtVyidpi52Ly5HN?w5#IzA5}c}{om)om%sk{*X*Yu N4I2D=iw2ePe*pf7`a1vs diff --git a/BasiliskII/src/MacOSX/HowTo.html b/BasiliskII/src/MacOSX/HowTo.html deleted file mode 100644 index 49fcb4c6..00000000 --- a/BasiliskII/src/MacOSX/HowTo.html +++ /dev/null @@ -1,226 +0,0 @@ - -Basilisk II, Mac OS X port, HowTos - - -

Index

- - - -
- -

Minimum Requirements

- -To run Basilisk II, you need both: -
    -
  • A Mac ROM image. Even though there is a ROM in your OS X Mac, - it is too new for a 68k Mac to make use of. Any Mac II ROM, - and most of the Quadra ROMS, will work. -
    (Quadra 660av and 840av ROMs are currently unusable. - I don't know about Mac LC ROMs. In the near future, Mac Plus, - SE or Classic ROMS may also be usable, though only for emulating - a monochrome Mac).
  • -
  • A copy of the MacOS, which at the moment has to either be on - a CD-ROM, or on a disk image
  • -
- -
- -

Macintosh ROM image

- -

To run Basilisk II, you need a ROM image, which is a data file -containing a copy of the ROM chips from a real 68k Macintosh.

- -

The best way (i.e. most legally acceptable) to get a ROM -image is to produce it from your old Mac. Take a program like CopyROM, -download it onto your old Mac, and use it to produce the image file, -which you then copy or upload to your OS X Mac. -A good page which describes this process is -here. -

- -

The easiest way to get a ROM image is to get one from someone else -(e.g. another Basilisk II user, or an emulation web site). -Note that this probably contravenes several copyright laws.

- -

Once you have your ROM image, you need to tell Basilisk II to use it: -

    -
  1. Open the Basilisk II application
  2. -
  3. Go to the 'BasiliskII' menu, then the Preferences...' menu item
  4. -
  5. On the Emulation tab, there is a field 'ROM file:'. Either type in the -path to the ROM file, or click the Browse button and Open the ROM file
  6. -
  7. Click the Save button, so that Basilisk II will be able to find the ROM -each time you boot it
  8. -
-

- -

If you want to test this, press the Run or Power button -(in the top right corner of the 'BasiliskII Emulator' window). -After a few moments you should see a Mac screen, with a picture of a floppy -disk with a flashing question mark. That is the Mac telling you that it needs -a disk to boot from.

- -
- -

Finding a boot disk

- -

Basilisk II needs a copy of the MacOS to boot from. Anything from System 7 -through to MacOS 8.1 should be usable. -
(Felix Eng and I have only tested System 7.0.1, 7.1, 7.5.3 and 7.6, -although Felix also got System 6.0.8 to work with SE/30 Roms)

- -Basilisk II can currently boot from: - - - - - - - - - - - - - -
CD-ROM Most (not all) MacOS Install CDs will also boot your Mac. I also think - that some old Norton Utilities install CDs might have booted 68k Macs
Floppy disk image Jonathan C. Silverstein reports that - this Apple floppy disk image will boot Basilisk II
Preinstalled Basilisk II disk image Another Basilisk II user might be willing to loan you the disk image -that they are using
- -

It is possible to use Basilisk II with a CD-ROM or floppy image, but -because most bootable CDs have a minimal System Folder, it is better if you -use a disk image with a more complete MacOS installed on it. The next section -tells you how to do this.

- -

Note that there is currently no Install CD image on Apple's Web site, but -they do seem to have MacOS 7.5.3 floppy disk images (all 19 of them). Burning -those images onto a CD (not in the extended format) should allow you to install. -
Thanks to Attilio Farina for this tip!

- -

Installing the MacOS

- -

Create a new BasiliskII disk

- -

Before you can install the MacOS onto a disk volume, -you need to create a disk to install onto:

- -
    -
  1. Start up the Basilisk application.
    - (If it is already running, skip this step)
  2. -
  3. Open the preferences.
  4. -
  5. Go to the Disk Volumes tab.
  6. -
  7. Press the 'Create...' button - (go with the defaults, unless you think you will need a huge disk).
  8. -
- -

If you want to have more than one hard disk available to Basilisk II, -you could create additional volumes here.

- -

Installing the MacOS

- -

Insert your MacOS install CD-ROM, and wait a few moments for the -OS X Finder to mount the disk. While still in your preferences:

- -
    -
  1. Go to the Emulation tab and check that your emulation is appropriate - for your install image -
    (e.g. I had to change from Quadra900 to IIci, - because my generic 7.1 install CD didn't support the Quadra), - and that you have the RAM size set appropriately -
    (e.g. 8MB RAM may not be enough for a 7.5.3 install).
  2. -
  3. Click the save button.
  4. -
  5. In the BasiliskII Emulator window, click Run.
    - (If it is already running, but showing the floppy with the question mark, - press the restart button - the triangle in the bottom right hand corner)
    - You should get a HappyMac, and the emulator will start to boot from the CD. - You should then a dialog asking you to format a disk.
  6. -
  7. Click Initialize, then Erase, give the disk an appropriate name - (e.g. Hard Disk), then click OK.
  8. -
  9. Find the OS installer (in my case the CD booted into At Ease, and one of - the first buttons was 'Install System'), and go with the defaults.
  10. -
- -

After the installer finishes it may try to reboot (or you may need to -force a reboot). When it reboots, BasiliskII may exit. Start it again, -and you should boot into your installed OS.

- -
- -

Mounting Unix Files

- -

If Basilisk II is running MacOS 7.5.3 or newer, you can easily access some -of the files from your OS X disks. Just set the 'Unix directory to mount' in the -Volumes tab of the Preferences. Next time the Emulator starts up, a new disk -will appear on its Desktop (called Unix).

- -

To prevent clashes with the OS X desktop files, I suggest that the directory -you select is not a whole disk (e.g. '/' or '/Volumes/disk'). Mount a -sub-folder instead (like '/Applications (Mac OS 9)').

- -
- -

Importing Mac Files

- -

If you are not running MacOS 7.5.3 or newer, the above trick won't work. -This makes getting files into Basilisk II harder. Luckily, Apple's 'Disk Copy' -or 'Disk Utility' can create a disk image file that is compatible -with Basilisk II (i.e. you can add it as a disk volume).

- -
    -
  1. Open 10.1's 'Disk Copy' program, and create a 'Mac Standard' image, -
    or 10.3's 'Disk Utility', and create a 'read/write disk image', -
    or Disk Copy 6.??? in Classic, and create new image
  2. -
  3. If the image is not mounted, mount it
  4. -
  5. Copy any files that you want to access in the emulator to the mounted - image
  6. -
  7. Unmount the image
  8. -
  9. In Basilisk II's preferences, go to the 'Disk Volumes' tab, - add your new image, and start the emulation
  10. -
- -A new disk should appear on the emulation's desktop which contains the files -that you wanted to access. If the emulator complains about a disk needing to -be formatted, you may have chosen the wrong type of image type in 'Disk Copy' -or 'Disk Utility.' - -
-

Networking

- -

If your Mac is networked, then your emulated MacOS can also access that -network: -

    -
  1. Open Basilisk II, go to the Preferences, then the Hardware tab, -and set the emulator's EtherNet interface to slirp
  2. -
  3. Start the Emulator
  4. -
  5. In the emulated MacOS, open the TCP/IP Control Panel and set: -
      -
    • 'Connect via:' to EtherNet, and
    • -
    • 'Configure:' to 'Using DHCP Server'
    • -
    -
  6. Restart the emulation.
  7. -
-You should now be able to surf the web, or FTP download software, -in the emulated Mac. Not sure about AppleTalk networking, though.

- -

Note that this does not require the OS X Mac to be using EtherNet, -any working TCP/IP networking should be fine. I have tested it over -DHCP EtherNet (ADSL modem/router at home), and with a static IP -address at work (which also has an external web proxy/firewall).

- -
- -$Id$ -
-Written by Nigel Pearson on 26th March, 2003. - - - - diff --git a/BasiliskII/src/MacOSX/Info.plist b/BasiliskII/src/MacOSX/Info.plist deleted file mode 100644 index 31a02329..00000000 --- a/BasiliskII/src/MacOSX/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - BasiliskII - CFBundleGetInfoString - Basilisk II version 1.0, Copyright © 1997-2006 Christian Bauer et al. Mac OS X port 19 - CFBundleIconFile - BasiliskII.icns - CFBundleIdentifier - - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - BasiliskII - CFBundlePackageType - APPL - CFBundleShortVersionString - Basilisk II 1.0, Mac OS X port 19 - CFBundleSignature - ???? - NSHelpFile - README.txt - NSMainNibFile - MainMenu - NSPrincipalClass - Controller - - diff --git a/BasiliskII/src/MacOSX/MacOSX_sound_if.cpp b/BasiliskII/src/MacOSX/MacOSX_sound_if.cpp deleted file mode 100644 index bb463c65..00000000 --- a/BasiliskII/src/MacOSX/MacOSX_sound_if.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * MacOSX_sound_if.h - * BasiliskII - * - * Copyright 2006 Daniel Sumorok. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "AudioBackEnd.h" -#include "MacOSX_sound_if.h" - -OSXsoundOutput::OSXsoundOutput() : - player(NULL), - callback(NULL) { -} - -void OSXsoundOutput::getMoreSamples(void *arg) { - OSXsoundOutput *me; - - me = (OSXsoundOutput *)arg; - - if(me == NULL) { - return; - } - - if(me->callback == NULL) { - return; - } - - me->callback(); -} - -int OSXsoundOutput::start(int bitsPerSample, int numChannels, int sampleRate) { - stop(); - player = new AudioBackEnd(bitsPerSample, numChannels, sampleRate); - if(player != NULL) { - player->setCallback(getMoreSamples, (void *)this); - player->Start(); - } - return 0; -} - -int OSXsoundOutput::stop() { - if(player != NULL) { - player->Stop(); - delete player; - player = NULL; - } - return 0; -} - -OSXsoundOutput::~OSXsoundOutput() { - stop(); -} - -void OSXsoundOutput::setCallback(audioCallback fn) { - callback = fn; -} - -unsigned int OSXsoundOutput::bufferSizeFrames() { - if(player != NULL) { - return player->BufferSizeFrames(); - } - - return 0; -} - -int OSXsoundOutput::sendAudioBuffer(void *buffer, int numFrames) { - if(player != NULL) { - return player->sendAudioBuffer(buffer, numFrames); - } - - return 0; -} diff --git a/BasiliskII/src/MacOSX/MacOSX_sound_if.h b/BasiliskII/src/MacOSX/MacOSX_sound_if.h deleted file mode 100644 index 5cfdd438..00000000 --- a/BasiliskII/src/MacOSX/MacOSX_sound_if.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * MacOSX_sound_if.h - * BasiliskII - * - * Copyright 2006 Daniel Sumorok. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -typedef int (*audioCallback)(void); - -class AudioBackEnd; - -class OSXsoundOutput { - private: - static void getMoreSamples(void *arg); - - AudioBackEnd *player; - audioCallback callback; - public: - OSXsoundOutput(); - ~OSXsoundOutput(); - int start(int bitsPerSample, int numChannels, int sampleRate); - int stop(); - int putBuffer(void *buffer, int numSamples); - void setCallback(audioCallback fn); - unsigned int bufferSizeFrames(); - int sendAudioBuffer(void *buffer, int numFrames); -}; diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/InfoPlist.strings b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/InfoPlist.strings deleted file mode 100755 index da3ff3eb..00000000 --- a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/InfoPlist.strings +++ /dev/null @@ -1,4 +0,0 @@ -/* Localized versions of Info.plist keys */ - -CFBundleName = "BasiliskII"; -NSHumanReadableCopyright = "Copyright 1997-2001 Christian Bauer et al., Freely distributable under the terms of the GNU GPL"; diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/classes.nib b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/classes.nib deleted file mode 100644 index aee209e4..00000000 --- a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/classes.nib +++ /dev/null @@ -1,118 +0,0 @@ -{ - IBClasses = ( - { - ACTIONS = { - NewEmulator = id; - PauseAll = id; - RunAll = id; - ShowAbout = id; - TerminateAll = id; - }; - CLASS = Controller; - LANGUAGE = ObjC; - OUTLETS = {myEmulator = id; }; - SUPERCLASS = NSObject; - }, - { - ACTIONS = { - Interrupt = id; - PowerKey = id; - Restart = id; - Resume = id; - Snapshot = id; - SpeedChange = id; - Suspend = id; - Terminate = id; - ToggleState = id; - ZapPRAM = id; - }; - CLASS = Emulator; - LANGUAGE = ObjC; - OUTLETS = {barberPole = id; runOrPause = id; screen = id; speed = id; win = id; }; - SUPERCLASS = NSObject; - }, - {CLASS = EmulatorView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, - { - ACTIONS = { - Interrupt = id; - PowerKey = id; - Restart = id; - Resume = id; - Snapshot = id; - Suspend = id; - Terminate = id; - ZapPRAM = id; - }; - CLASS = FirstResponder; - LANGUAGE = ObjC; - SUPERCLASS = NSObject; - }, - { - ACTIONS = { - AddSCSI = id; - AddVolume = id; - BrowseEtherNet = id; - BrowseExtFS = id; - BrowseModem = id; - BrowsePrinter = id; - BrowseROM = id; - ChangeBootFrom = id; - ChangeCPU = id; - ChangeDisableCD = id; - ChangeDisableSound = id; - ChangeFPU = id; - ChangeModel = id; - CreateVolume = id; - DeleteVolume = id; - EditBytes = id; - EditDelay = id; - EditDepth = id; - EditEtherNetDevice = id; - EditExtFS = id; - EditFrequency = id; - EditHeight = id; - EditMB = id; - EditModemDevice = id; - EditPrinterDevice = id; - EditROMpath = id; - EditWidth = id; - RemoveSCSI = id; - RemoveVolume = id; - ShowPrefs = id; - }; - CLASS = PrefsEditor; - LANGUAGE = ObjC; - OUTLETS = { - CPU68000 = id; - CPU68020 = id; - CPU68030 = id; - CPU68040 = id; - FPU = id; - IIci = id; - MB = id; - Quadra900 = id; - ROMfile = id; - SCSIdisks = id; - bootFromAny = id; - bootFromCD = id; - bytes = id; - classic = id; - delay = id; - depth = id; - disableCD = id; - disableSound = id; - diskImages = id; - etherNet = id; - extFS = id; - frequency = id; - height = id; - modem = id; - panel = id; - printer = id; - width = id; - }; - SUPERCLASS = NSObject; - } - ); - IBVersion = 1; -} \ No newline at end of file diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/info.nib b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/info.nib deleted file mode 100644 index c3bc0447..00000000 --- a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/info.nib +++ /dev/null @@ -1,20 +0,0 @@ - - - - - IBDocumentLocation - 5 42 473 240 0 41 1024 705 - IBMainMenuLocation - 0 702 365 44 0 42 1152 704 - IBUserGuides - - About - - guideLocations - - guidesLocked - NO - - - - diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/objects.nib b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/MainMenu.nib/objects.nib deleted file mode 100644 index 25afc5f2a1473970e433191774cb77dabe798bab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19336 zcmbtc3z$^Jm9DxyJ?~)v5g*9XD2SjU4}*vgW|$F}4`+C^Ad5up>A5g1J>6}04+9#F zHFUS^>SwffXko+*f+ztYfRB)%26c5^HwL4UhpYKao46)KH^!)WxUm1Jy7zW<&%-f6 z=(_ius#8_xRi{qXwWuP#K4P}S;!)GrCR`sRcugXa7}Dfzn6t3?Cet6U_r-mJy_-ms zHhC3}H9|8vI#h{ZTWpMp_$<`qr~V zq69;ek6qn7y(5)OCOH>;o8a3SQ)N1-{!4YUhZ2vX)^@7JP72;5csJFeGQCsPN))5V zfZvarE*d1JZjGuTZnm+mLnxqgSfa=pS#fPkOZJXOQXmB(%!Ncw?dl$va9=llhX3oujIlHE@5D)VHEU;n z7GN#R$L6spenWURL5Z)bN^n0rzz?tk#b6jZnguONrk_ZZ#bSYgpTRp*oi!&D zo42r({7ELB?mi1WO`EBD8lifc52``77Qb=y=V!kCRiI4N8T2WYPCV%_M(|TzE5Mo+ z4r_K1SHAaHZlZg^{o*BNTX?ORI-E=%lp{Oxc%S3>VFCH;TsMOFjRO-etAlaHP2!Fm)c9dr(roL(!7!Y`f#QTqnNzWM zeGE31f^0|nl@poc^RHPQ4Y!9{WbIVqodd3fv1-+Z*^_qf;i(jc&Qlf}$fi_>R=01d znWT@A8C2aso+%nq!)A&<7WX6*1Yg94V#Gt$c%kYkW!1J12$~o}ds_%@vy^-iO@-7j z81}C*TT-5(o?aXx8$C<&? zH8qU*^2~-ScN0_aT>SJeLAknBiix_;aqk&0ER{<9?y=4hQ%}@%7D4QLVYhDSz;n8u zd_mFV8oi;GP;vzSkVMvj(J?y=<&!_Deo`*uZD)FAtD^x;EuPsh8*{kOq3|~_G2OVzH+-#S4Y$bVrx7NB)OO;9`>}sGUKE)se>*9 z42L4*uYqpmWw16rkS?*-J(|c3BdN<9My5+thtfkrC%bMwQQOHNyuHUA`Io)G9hsjJ zhcXvBg->!SUq*PP?9k10GQnrjpq_L(7wliS<^J`q3)hyiIni)OEZ_ZC_wS!cK9bS% zC7b7`-8z%Y!Q7RS#Vc(Fzg)oBsY^qFb)J?$6wzBa8qm1wId5&i=eY_Ime+Hxr_twM z==EGOdB#M^^%BK(sUBkmzf15S^+Tl^06DQOTPmg4mXY@|V>xD3TK25?^)9IF0Iwc< z1TA_;Hlvgzv6MWR9<81cAH9|yleY-Hksh13?EEx+j;h;xojE5b`Q)L*FK8LbYde8v z#W5Ra85xTf6X>61wEg-0^Q^g#PbIRFW`PykZl37n-2D4Tk{fDw+{?--qSif^(NN#N zo9f$j!e23-9-r?QH`H~{%TY(jCQYhBO1|D)8}R3QLr3Q;lp9x4`Xr@0Nl40a++TeS zp`gxMLtfx-O9wkXMGp3F{W;K^NVgW=lqSB7r+<#~JlPkUhgG9NwWfqP zOO9V8q3Z(Ly0sl%vAtS$lix1q6VFRel1fiL@f$R(8^4hrgCUVpU6#HAC2IUf&J&Ug z7-RV#!44Z%cu7rU7k!17RtW9*q1pZ0e;#>0Vo>A@qu2WW$I;)HiJ@^ORgYkFv(As|wj#aiun`}uh&@Hk8cDPPj|}_=q;b9liV_#+F~C&nKA}eog>?X3d%=d2ZiZNN6QW?EkKTzqYy zCEhB%2_-xP+t?=oPHPefyq4d(WWE_#-5R%=r%wAM*)Ii|4N2y;-@K(*?(pp1<+>*w zZ%*Pzy?*#d|1h09v{B6S>D7oOBSGJKPt;r$HDj$ghb~x`?i~e7ID8lE=;#PIAIazZ zk8L(b^4Z)UXXLyDyZ^O@e7+)+;#+UeY+$bRZe2b%YTn##hWs{#!LU{zz#v%5>t~(~ z)}B2uYu)jHe@#qh=uVxX59HX%>pc@dZ^D<*n{P(rx9IeC>GTBHX$!x2v0(Q~W4|}g z*poj#1lM7}66OzQyt5uboU#NsfpK;STa3-FX@>NU_E?7h^5wOb;ghxsvRNclm-t!& zVU-U>_yR2iwS+_M+CZo!+)+S{-@Cx*l+=zV1=|m6Kkbvlc1lpXBDbWPYnFUmpb_hw zKXdWPq}51zF~JVzDgKr2vrmO=PAydXzLsslp3;}eoJibd(;<-QeG8;iItZkS>dlDd z0F-|e?2s;z96595B#@ibH#xaK1}BRnfpumuPhk%CLvGC9NAB5v$Q2Jln~RzQ@w~A; zmm}sZou*tm&2(H}ItBX(i|2Z|c&<-xSE#~3cF4S_FVY(D$1cKx5NaX0r`B3A>^54- zXoZ8`LR)@TD%c*W+g^iy2Xke`w&8d@MFZEi?zJUl! zt~(Dny}3s>LU4`4^7^rTsI3R(bHd@cXKpmyCY_e83$NrDM5{y6A-cGG z@Tl6n6lN}VSju3BC_QqkcbVMS?3P*~*lwE_g?drhh*N>+`imL^G5=(#6+KET6ty9= z*XVInO4)w8i}`T~axECAZgsTHV0Z%9hkN zdc1*K^lgP;@AN~lxfT>_dsEc6S!H#LmU`$&Fi)G_?VBP_Cz>r4Eu6DXvmBWwr1x6P zU>?!;`X;*Y))wr2T1FPKvCDU&R!`*#_I|$mv?WneaV6$?<(JHp>~a;-$azEhpzk3y zl?e8%+>kxndsuyB83jA85ADgElJH?TERqLCI>QFD0TS#(X>jU@Oa;J6`#8#;x?uly z8BCZp4bS7A9%Ywa8;G}h<}O;Q>)^-zyCd=)Hu(h;Y8Eh7vp^>6sYD9T@l z-7{uRnKDK1@l&fuZBds?alY@McGFZlLq)P^*K7Ii-DbLK>-d`fu}(xTnu$ zke*|u;FYs{IA!(C?8QtMG1I3p6S+}6s41xn`fzIMm+Vv?l^cU%XDJzCLxVpco4Vyp zsp*$+w0v>9uO;g9TxyAMNdFE00T%Hhu;?MFYX}SFW>WAf%exu|o6Zmur2*2GcfszO zP;?1nMVHuIe0f9hh?S-CM~mw>Z*k#v0L>aFO4Su~o|8&<=ezIU-Z}~tXp?We;do!;9c=_`ZLI45Ty-8o0plUXn-Gi^NGkHD!? zqZw+a%L9V{1-n+cM>4_>-XlRhf z?Xv>1W@VGv;Za-saFlk-Je2BWLmBJ*=E;*MacFy6=5|2oQU`jeYc>6A+I&baq-+c} z;Dl*J^w{E!W42E;6S#=|h z+1n6i+D$QF-Zs#*a@`J|^Qy1mbLiF>F@g?-v9H0Q@IWIa*$lyb3^l13Iir+fX=Pn7 z9LpPW$3R0Cygnn?>w>+S>DdNGUrhj=xj6fz+)l_XrEu z3VT+q;SOatgYX1{8k!Wk;EI0r;`TtENJ;l^9!QahJC)!L-EuTFeXN!f)RcoLwGKoH zW5}#q3$6TIuuq|qMh~95)>0^dbysQpHD()9sBu&9KX+k)59IRBeixnd?GpSYn+lL8d%ObQU9V6%HbJF~mp zo-BgS3p~ppSll}FOqo2hyw-z+uX%wybCa186`6WWdD;+;mY3IsBkQA-r1m`j9naKD zFTLc#X;Y?5_0+XS1F?9(7lM_wBSyg4nlCt+@~&oZJ)K1&OW&;SpO$}x%TV_H!7>DN zRtkm3b1|58=S`j&5P#0xnqvus0l#41c{Ss>a*4~RSUPaOlQ$ra-LmCWT${vJGX$>@ zThtuJamzK>VW(21NG9EZzhI^;3)m^|*~vcT5dkjGFqKqMK^ZR4X%}f5Z~;T6KoTw- zKrn-)4scjxzU=OE3-hA3!1)UYMy9m95l^^JM$2dktSR%^F+6obhf(c8Wb^af zJxt-MmOz}`e5viJHcB^Nv=mFMj0tWT$a)JJEitV|D+bqS@C&CJm8%Y?W#m%U4M<<` zJM#yIxEVJkWy`e#wzS-$>djpjg#7zlNecb6YEbUQ6;*#+dTJV_Z=k;HsHlj%fE=2C zpz4BegaqH~$&49|as!0VXOo!Y+wpo330nZX`Aa#r!hw)<&Q_$KOo6x;8`&xpJ z$&C#NJ1ZUPVlGNg25PafpoJZ!4b-N-piR+yGZ^WU;c8sYTCFN#TJSw;2ew-dv%GOV z{Dnu7AqmVLh^2IoniyY!h0I|U;wr(f8EDYn6j)s^_#>Hp#Pml5r%(#%R@fXnO0kvT z_bG8bOJc%p`E8j!J2GeNz{~ln+6lGTT`u2vGg)qR37WqvW8KitN{nj3-Drq=`S!9l z(q3sA8a!GsMKi$puN@QHtJ}^b|E2Coh}0wGs4J*#%&HD|A`B*sk>pbNCN=8!$(!s@ z(<&n$vQzK_7~Eggpc^P?Y+QgkSS5F4jvUO4Is-2)Gzs__!P`(=r`~pBamL$)YMy%q z-<`Q|JV+fP=k?0=Oo?oc#%OUa=iu`g} zun#C^*h9R&OU>Z^wV9QTnQhxMuN(yCFk#M-ov^*iQr1a_$fv2E5kHU!;|ln&d}E*X zWX6uktc`=fozlzlD&osMY5?6-ym&A(ek@?)6qzF8)e@S(OE5~_D5Gt@QSgT|WhI%} zV=@Z~_ZAKId^mB%q%EeTuK`4EpWdhj~H45lvRX6fdnUxqMeei)xr1G@<;;E_30>IRl zDyhsgJmWhXd5<3V@o*U&6_A?%*fn)3J+nLUjH~wcB>{=QRKdt~Q66X-)q4jp#2`*r zsMrIL^~nrTy;`2o;Gqq0Yq`vEcvoIY2str^#_l z1k{)++0s?ehNi=w1CZEmi{)#Q)x5Kyt{nb@02c6{y{}+Sd!qSXLE{;z%ou>2X_n|O zuov}8Vnu5{8}sF8;#OcJD$)59cmdZHU+`Y9zsuR(4G0o~wsH`qYDGat@EF!nyykuU zLv`j+Z*q3e0o$sF9xW6U1Fl*yBb$b2QYqWLYa!z=A5 zYzwD4jOJ5F4vrg8_cVA5S%+psU*_1VP29z@@;r)*fhwMA)x1#A(mW5n008-AjK*OKD((YR zliy^#LZKvuzv8(!D^>uS*Y}G6IP#IhTLuVbXft*u&5%R_AE>+=vEeS#1L-O52MRl5 z8Y%ki#+z;}G?s0EDNdjP@d^V_bDb_ndKe&`eWa!A3q>fW7|@;ZfRW_vZ>mz62q5{Y zLdL|W0qmA?q&E_z3qqymxJ4o-{Mmpw15z6DDL~q6$Kn;^Q{R`^UgKi`9llA@QvfNV zPN|=Jh(GYYf|miDCkKqsayfYvIXUXwpvMsbNva5Nbf4oyDzikKAz->d$eFRX3V@Q)2=T~n&IQh(K@fYDs3m$ECXw4h zfXJ)BYn(-tOVgABKU6>;%=-;Mz1MzuU7~;?2x1gv#U>o-BW^p zFS8#oJJz6^oQ^du#f!cID(}HpQyp?8G~Hu($yZ3SFJ1ph!~KBeG)ywaryANehDw4H z1M(sz+Lzq=-}oE}o0O%LTS0=PDbQ?1bSOgd(-m65=u>2cQm|oNPYYZ>1q+J&?YO{5 znlIEv zjZ~%DhtGsVtIdXxOi*hSW~(0QO1TEToS;LZ?IAi=xZ1ZKSz-;lS+?=hhFXK(MNl`= z&0!6Aj|4`MO3;9N30Q{HkPh10X^44*sI;a-secW(n!>DdoH(g7Aq~^K3Gy1*ifpV* z#%ejHm{w~E)pAoU4cH=^wucA|&i2!^E{Ud9*05xf-XZaX(w1_3FQGm$axgC{OqKeU zwgCBxg;bxx79fvUNcE9K0TSW5v`_Vo)>ZUrl+z{lcZ4ga_&y(lEfQf)scR)Iux@+F zyJJpc+8O1VTeo#>EkbTe;wp%=eHYh3ZqXWA*HInZg9Z_@JnSE_8Fmt*hoX7 zb;3=Hgjcx^2~;~RcL!am&I417UEC_~O6S2Th;idSlW%<0sK8l|T-3OG%@J4Kffey1`?!lznW;N9iL_8ZU+`TnS0N zagNRl72MOk1HD_?k(J^Wn7Xo~WB!`M;8Ko`p_s;MgR3_>hN6E9g9|nqhEsrCBrl`r zP?ArXx^F_)O>`863nhN*?u&+y`<#kqT!W-rkaSB?N4}0$=gyLoFH{$xRvKp^TCy_$>C}GqD zgpn4;MOk5dQy61VtVcdFi!6pPuFDGeWhPKGx`Ej*jDskCEL=R>DvaM|k(oRb$k|P( zk0s^9Y_~8T2H--$??AD!DtlD$2eZ?J@e{PW0XeJe8EB7Z6AiNakc-0eK4Ba{?UBM& zinmvUaT3M93*!p_w~fY6-3S1731bh6j4&=iZ?6mEPrzJDzW0PhI?G~U{9 z_>(<`*`OX+Gz*~3D}X*Kj6Y`M!ocv^OTzdV#mB<99_ZCLnaW-WZs0j8*aK*IP#BM+ z__=TuqaIdT!u8C=&kDi*7e#kP7V*S)Q0E82_zZx%VtD@gt@ycD7?V*P62|ucF985= zKNT)_cBwG_2hTBK49m{OWI*~;h$lN%7)P>8gz*Q|KS#K#vZICZOm@65zMowSqNs-8 zxJ zGF%utF(w3d|AjhG;r~OiTNsZ4hye6G6o~djz2+Xx>(FRF(cofzp_y+)eBwXj< z4QBw*H1?L@hXKqA7o=~%HNl7sNbD)JI~`&(=0VuFpv0cYmIzM0yes%KC=j%Ml=Tba zgDhh4m08RP5@HBde~3n}2^UE6i-n8GJqAaXT>-7b^ZUXD2V=Y|Tq9BV1>2mhhvMS- z5n;fRaOh(6;O)9w@cachg<_}R#P0=TL2_>xKlioc^=;vTXpzxpWHD)w&|m?_wIf!r>PIo-lFuA8N??HbxJr!MRd`{qV*BS3zxnfiZF C3$ywF diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/Collapsed.tiff b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/Collapsed.tiff deleted file mode 100644 index e4647bbb7671104bc0058766a208c68e3c2aac72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 870 zcmebEWzb?^U|PdK8L%Zo`xKy_J|I>iLGON`S`c0Z#Cbr>2gHN`Ob?7+2h`vX#4LC; z!qlSE^MQJdftVYMUUap{{GCActt99n#U4`pLrS=j6F=mn11!OULx`7=fq@w)$H>47 zBp8v{Okg%JMw$H>nW5r9#f)rFHWQF72##@}C<6zhC{!G%gHaqN&a{M4ih&huJ_BiRDkn2wa1B1E%1C#~;K3plk diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/Expanded.tiff b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/Expanded.tiff deleted file mode 100644 index 819a88f0b74b93e6599b8685a75e65ff98199a98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 870 zcmc&wu?_)25Ph?YT*wK9NKk2rR_zmxM4|Kv_YE4YO0Q9g=v979;mulXTI0I(5JQP zd6=;odbIwA5(jpq`ZQ`?1Y-`JNsUEOw~SUxX^`I8_wF6Ra8RIJxIEES&{ x=1q4Ys)(fJbvmT|(9K>tD7*cz3+X=drSyWG!(iw9rMt64xPR5_3K%rt;|*=YDZc;! diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/classes.nib b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/classes.nib deleted file mode 100644 index e78b8572..00000000 --- a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/classes.nib +++ /dev/null @@ -1,32 +0,0 @@ -{ - IBClasses = ( - { - ACTIONS = {NewEmulator = id; ShowAbout = id; pauseAll = id; terminateAll = id; }; - CLASS = Controller; - LANGUAGE = ObjC; - OUTLETS = {myEmulator = id; }; - SUPERCLASS = NSObject; - }, - { - ACTIONS = { - Interrupt = id; - PowerKey = id; - Restart = id; - Resume = id; - Snapshot = id; - SpeedChange = id; - Suspend = id; - Terminate = id; - ToggleState = id; - ZapPRAM = id; - }; - CLASS = Emulator; - LANGUAGE = ObjC; - OUTLETS = {barberPole = id; runOrPause = id; screen = id; speed = id; win = id; }; - SUPERCLASS = NSObject; - }, - {CLASS = EmulatorView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, - {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; } - ); - IBVersion = 1; -} \ No newline at end of file diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/info.nib b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/info.nib deleted file mode 100644 index 8c4ad339..00000000 --- a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/info.nib +++ /dev/null @@ -1,20 +0,0 @@ - - - - - IBDocumentLocation - 18 42 473 240 0 41 1024 705 - IBMainMenuLocation - 0 702 365 44 0 41 1024 705 - IBUserGuides - - Window - - guideLocations - - guidesLocked - NO - - - - diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/objects.nib b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/objects.nib deleted file mode 100644 index a1bd5ec9c1220688221cbb813122a05b3bfe71f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3069 zcma)8U1%It6h3#d+3cp9+Sn?_`qN@X;%`%Hk)pUsv>LUW&G!jK+^tw72Z2BSqS4S?VNk-j>VDkJX?pQP4HP z$l&`(MW0aNB2zmu<@c)S^r6lwZ+)p}$LM|nfWP=61US*i49o~q(u|y9@b)IO1m86~ zc&nxr3L20?0V1`CVPDyCOaq-wqjM6&ZlM-c;={-?BX9Ne0QB_Kr6hDs%c5F|h!oII zi^azxgnBhcHw|&_i~=A&^sk_dD^yhU1-TN zIMby}rG~RtQ6UIj*X8nYq~i>V=^JYC#Z)oNmPWg)B6OGr1LNu#6;Vsu2g^>uoG@~p z$3OSKXeK@7Vd^2SA2z{vkdgO?w*m}rt-<$!K<=aC4KO}J87=$DhWDxKei~UncT(6) zrq1xl=GGy#Y*X(P#$&Dc<;3dP{HyRbbjMLGr=egWQh=a5p1pdCeR!OIwEa_3mvTarU3qe7#0E*3x?&9RM92*AC&S zdhE`{(4JWfZR&|bB^BFGp^-TK*ss)*El6v0GI%p{03AAT4TlgRfp02r;QfPU6TC|` zhpKgWW!lJ&S=2=XJXX)p)Mlp(!0B4$T2#mRh*eZCg9{(ad_|>EvYZU=#dz)9DdV;6 z8u5brU=T(yhB~~81x!z5;!+hIN@n^pZ!6%V>-r(|Gc8;h9ev}myN?|w7{Xs>lJmbJ+lH7;SkPcS4annFTuyeo*by$& z@g7Zgp$lEBUHEB@y~?g8gD=j(&%dFlh1G&?Nk6?F;OX_NuvjZ--5yIFr}hIj)$aGO z%C>#-f12uvb#a_B^*CK>7=bjGq?xjbk#EJI6aVFytKi_}9GmF#x`8cnn2wil;!#Ha zsPYb77n4?YWUWn%$rgEcYWpGV{D&MsN1g$3~Z^*N)ZQ~QBt0VxtEBhXW$Z^ z5aQr&mUx{hU(S%zk+2IDypW99XOz>dWd~DcJ^yUrF9!a(z`qpu=L3H^@Q(!kT;N}x z_Kybs#lT+*{Dr{hzG(NUx^~x__Gg2j(+`ALxl5ohJm9dDbMGO~Uu-__@ceVl=UtwE z3D3AW)Ke5$&LgQg$31@;DPp6Eiq7+o$UBW~!}F)n{mdS{Nbj<@3{Dt0HT^kxNm}Ch zm+@G0-am>5(&PCTrKGxcBrPGS?!ZpZUuZt#_bYgAfZ)$IfBj&zH=sMU0ZJXLrB<{Y zKj0!ZKq{A!^0v+iywYdr*&56SA@mwBdRq*ts%2W zMJL!ezapG!nb3{+D1b@Ynnh_u;rxb31qu?|UtJ#R*fhT^9LeNMlot9As>T@I9Sad) zx7va(2%G0;1!Fo|MV_IP5!dGVrHEK-urYBi5;<&+jTLF$!Q_tV3xb}C=WI+{6twpG z1dOR?BTgJdVh%+#baGB`T4iI3X zGJ`AOA|ro>-AqY`7a2)}ml$acZ({I6c!a@XxWLFtc$vZ1;ayBgg=ZQ0E4+s(cZPQ| zr7gUX!BTi1Q?`e9FeMqT;L;dwWyA}wXYgHk9&0r`iYrNYJ0os*DO+r$493 z&@i%M$kDYkq04W8pYwZ3U;gg@vq^X}udbbBI{zrwxxaRgKI6Rm4_$ca^D(=GV<$T_ zO#I2KZQPV24f11kg#CvuzSN`7H{Nnx`fGE4(Rc0ovQGa?eOMOTlI$$=74g~AyWjN0 zQIife&QgiOdfgi^I#LS9QxD)7_87h~PvI5*1kQnVFmt(&t;RW+w=NNXo$A!sXW*LRf_$H-8*u7eCe9j5fl-xPhZY*z-1j#a}au@M*YfxIf9>fCdrEz2da{6C^cNB+Huzg_=H2im?|;)n0I#Y1u56)d;U z#+qY=SbyRUHhSN|X0HOMd)>x1?|keaXq?Q)PM`PSdkwnZagzF+EWlRpLTvHAi%s6e zQ1d9l%A>cjz#xg!2MeQ!g{uMoRW7h;e99Vz%;o3P8bP^5>t zXC5}V=VGl}4pf|PVeye)FvsdTrW#$ugdJz`#fm`mpJLf0+ij5XM|#lhziiB(t~mT)bOAqGUdCdF8(8U_1-0WjWPi4I0d!8^fnHz{#nC+& z2})orDD8j}>~JRLSzp7n{b`u6ClRAIhhx}s zKlB=_Ud}v3eBS5BKU0EZi0cpM)2PmaCMWfq;HtN}62l-`_ z=WVPZe=0fLB>P;!55^ZTTJtQ1tA$~};*;nyY(^6E5%Xex%=7me`+)0OUzzTM5BC1a z2K`s~Y?O-m#D4|(e!WLNw)@_Jc0e)oLrRHP8F6gqYY|g{L$MXGVw`OU z-&@l2{eicjX=IJHYu7?))n@1f6p>FTpF9h&>R2xM_aCH(61MS`uuFIktLP%=S)aiA4I81Pq=Z?sW?`<<+pI4ZmV+@+!ni*IX>L&%|`|42;)1kKyW3_*5kjT}Q9Xqw+MVou7#3Z~21P58Vj^ zI&~jt-b3Lq`jQR4&^U`plxMRouR+O)YLPqD6rW;f1(p(jp@_eE6!DL#6!Etu{tgLM zIGk98BLs(dA&id(W0U$eC@U*t&YU@zK7Bf-O`8VAB`dKvsF3`44?00**m0_u>RcgK zxa4B4Z62`UMo4}VfLX+d~28nd5w7VT^$Np`MK%L zkH9=RW;*(U+TBty+b7^X5r;&sm^^ZI-_8?-wbjZg#g*atWi{{Xg$wXlw++GKScYHDhteC-%7n++VG=MsxO zPLa@Y498BpV5ts@q{IH;T&e}-IC!=O`=V-~PwN$}kP2+^E63^+C0OWKfa#VuF;*`X z!)T7}JYsSL^Az)C-ppSTM+52in67_O${tSh%Qt(|G2_rJEIN7ztG&vg?q3OQ0j-B3 z9$it6UxBLUd7SslxlFPG*j>#%003G`i~iGMo`-Q!{8aSnRUG4FL)tPJze z+oD=vmGF@4QU{}`TI@MfjU7Q%Q1dCrGPiqBu*=1_`>sM>GZ8%|tj=bh1m?@}&-@uY zr}5f-eD7&G59D{otGzsvT9*?>@2oy--#6~R*34P z#P-Y7G>B&u@sEK4>0m_M&3rGyD)#F<<7*{JBPPE{r5h8o1cLY0U0qOtH8{ z-xfpFs~qY<51@VKAq=A*LEkeK+qL&%<;s;%R8*AmS+Hz1bPk8Yz%7n&mTaB?GoMsg zg=FGzbOBt?3E`YribEkcrQgh@x^yU_2=)|@_9;(co%9su@lVK3kFh7B9y>zo$QM;m zI#!CAv`!vxcm=~(dNeUlF<<7*{5dZ^A$(4lJVe#2?Hhwj_{rurmbeMAj@HE*p^va9 z@+nkz+ezh1?5;3(AvA6LVc>p_xF?9>#ndN_xZlK)m^(O@bRQ>D>)@U71n#M|u#3o- zjxl$M3T&hA!SQ@Oj$Hf|b}27lne+ntS3b(Zt_OTyIQE1a9YHMt6f!*@mBZU}e?P1+ah(U`_DkFd=?5?oItIxJYQ zKvaiz=o0NYMg!eHfqVt3>-s0TlS>d6|+b1tRW$cFp|KlZ~^F<<7*{3SYkMZc#H znP*z}-Tv#Cd$a^9J`|H7PoN$790sw^U_^0h7*Y(~lh?6kk1b}-o+IV6c=2MaTelAS z2c6)aQh`&~UcjIBZvI(K2%!BN!~4op^37f8H}jNKXdbVCOFHcZuQtOmqZxLoO|VF5 z!oG8j(2aSC9bwO~#;*>G-0ow#bv`~CKkBf$Es8H z*cSEzyJH(*c=iR=j0Z3Xx&s~WYuM#_9vTjjP}ypT89&XE@>;fR8P=~~k3$|22+Dbb z;Jj8T{4yJGG`>{Ycb?Kpn$I7=?Mfq#-)M#NwN^M}yn|KRTbR-Q)*zu7nvo6I5cmX2 zC#o^it`I|KX%=+QfqDOfANqVfGkJ>nbu2nwiM4@Gp%M8C`th&HF3m8bI5ml^fKgx` z^iN)<{d_X?JPflHoHYM?XmOq1(VO zy?)%64keFjs0BZVW=t~-lUi}$0@)|E8CDmb!z!Vg)<{KE+p}OAa2ck4X)vetg^_y{ zl-0ILIda`nRaJ%NZhf3gD@9Nq+55tWI=H6S!jt1H5AetaoNog5q=)4tz%-=|yW`$q zOIQO`eCsjWz5qRjjPW8JKF)^^>XK}?UIr621+SGns<4st-*xsaj8gy$8q@A-E1Yh; zf%ElOaJljXju$IopKu4(5jSBGk^zh0G#nCSz`!K{^OgQF?{!Tr;S!$%t^-^X7A#YR z`_)?bMi^bL7Sj+J4fpaEKO?_hF~>~aM-Og5tBJx=7e!YjW8CvzL%mGubjm&L_$k$M%+?1cImB;)DAI}dT%+vIKe$OFe0_GpiAsrf_72gKh{(!dYa3o*5 z(b<+aoz?l3v>~{x6(Oas5mfXNez_0fohgLd#XKBMxK8t0Ivfc05f`!D#1cQvnk|hn zNnKv3tP1a6Y7tOGb*l{UxkvFt{%|Hc(e?r6loxtQz_zG2Q1+@qpAp{#Fh9b_^EB(g z>kiR+iLSF{J9pI{t70Zp3wj3a1i&PnbRfGp(b(>HNfw>w1(X8pyeb^3CYJ~AD7z{ zx8w_R@;zrdU{4}Z_IQs-hc-Dr*r*9Eg--MW&XE;+*gVQ-hIB_`(t|^z{ zbS@2!2^V4N6Nsg2*Nc3zXoV_H(IIR|Wix`S$+u(|FR~A9RbWRxH>aGSEf_WgKSTeo zz85erF+X{_GGFG+{JC*n^V(w=VFF>kjBID^uNAjtZ#_fv0{MZKzo2adJjmat$Y#NG zt{P6~r!jOE98YJ$Neuu^O}Nn5hLnakNPgak__`!^6> zAM?aIZC&^m*FsQ3XP9+Vdr1#3@`Wqq1?yl&I%p@n#ki$<+02J|iTN>4=F7Y#O%hMM zKl++5gP_{I?@(6-{lI#?I!@SxmwqP%9m?+B@A88muw2=fs0VP3ztpQcx$ zHEjEyy8S$g=MiOs#;|W@#cG6>w;iIhYG=v^Ptt*wlc1#xqA7+FUXvfl_Nl~Mq61A+ zV6ZONNS7<`-XX2I8A&f*Ac}RVu0cpu9m48gLh$$vf=CBn(!q`Lfo-LK?rGb|Ns6&7 zU(AE~j3P*Uz;nXKP2vklUVK9x6bNew8Y3o<9)Y)8Y;)+$o&4=b`5a1qU>)LHfb*oo z#SS`9D2w>B4ia1;UDDpZ#d*>t?$s+qKYxXY7cFFqRs>Kic~OiWrMjmdTi)`;cT)Z= zpLsAJNgi;_NOGBee$Y5CMCW{T<^9CB1kR%k1dSo1zY9^d7S!A4G{KYP1(5B+C?9A^ zgG9;$n$AH}iPRUY2m6Ar3<__g6H-W*M9P=gCaTH5(wgu|8+^$o&UfEpqf1=<@UcH~ z{ILC5F3V>g%%?Ab`7zJmYpfgRI`8q=XI~M1AS@(oBxv*=IKp-68l7yb>yJo}R?xB# z;pB^0@jTbmKiw-9dqgbhBa>> zAb&(tUc^yMF~{>_zR7fzfS=QJgP6CZH`TJh$M2}ly@cukH{loGP8Y~_?xIIBB=%={ zESKdo59Y(X{+SQxwX|`+t_04F!2}+M?ZJK(9-cator1j&S*9){v@;;mJLvWYwJ&bug zF?f8I!}3@z%V!?U=ilW|T}8g?s0Z8OD+0%*0zsL;^-dyJqsJ$Gtw)ZV7&Lj=nsnuT zRzQvbDCZ9%iC-+a+`GnqUu%m+ZIh(u`d0y@somje%jBvio`it7W{Ii5dM30nwKUH-st{+`F-@pxPwpXIPTmMgLU z|CK*|DryovI1V|V`VzRlah>M*hUfG71YXCe5!4C)jy~Lv`}24FJ&(iV@whxb%VBwv z`2VB)X$Wa!e{?2rU1Q&}jd;G~c;)pKuM>Ga$$XRu%xx8cV|%Um%J=-7-*Z3i&)@O) zJPwb?F-%GBRh=w*A8Q6k(INESmIXy}L=7DQA&@{oAV8**LJycC z!1Rvk5WvBqmzds6LI>M4pPldI&fDu38;l|Bu}1H`d(S!Z&&)q_iW@ifEAHo4bb{Zz zX&#v-og?YxGlNLRWQ6Cu*S?JVe>TMpF8}oD(^trvHEWL|MT&e=ty;C69XfP~88BeL zqfw(qB@P-i=uxLmonmU#sIjwX(W2i31qJn>KjTCgk4^8>9>t!~({TFix)4NlP6D_y?ghXB}EG%N7$86Js7ed}vbB;^X73 zZTt4^Gv9vut@-%lj}K+fo_&DKn@0p&{*1UVCo%tvw5Fv>m0I)VmtR_c9y)Z$#Ky*& z=g*&~27Z!0*nHx|3A1k9I)g7h`skxI%#R*NA9~-mxqbhE@TOnOmMt%Yg@u{*>(^V( zT)leL+`D(rJbwJx%A-e*%!3CH?6W&}?iiK3ckkNgypM~EGsJ>1w{PDz=gyrok&%%$ zCXzQ7B*y&&cqWmzjfvtX?=t7ko%`!vy?VvXm@&hwTD8i+gX71KTmA3|{)6T8>C@J? zygPR6n6;Bne&ciA(~mKiE?u&Da`x<5bL7Yovth#qLrx7IJUA|I-n?I!8qQS2Ba_yf~u2XKAS5fKq)(V|7xZ^XZR`SKeDPhk=A9DLwRsbM2^El6Vc#gHLG3^}}D!2+{v*)oeC zJ@^eizzzHkCO76YXU-V%)K_?p-@)FlT|3jcb7z|m%!4n8De=G#{DmE?A7jRhF*$SQ z`~qAKzLa8tZEz@1*3GhY>(-5)Fkym?>C&Z3&DynVt^e^C`0>5+1^oCLjMN;J^XJbS z72-5?>Qp1O(==+-$W*Uh-Lz`e%G!V*5MqLj*g=gV_wXN_YTC4EG`PU$;7l$Stn&dP z*`+>zK4QcO%OQM0Y&UP-?DfCmSKq7O!478XtO~YK3qJYe6Vt3&GgGr>O(S~@Q@L_w z)1pNSi(7f9b`TG02E4_8-+%wT!JiU~&%x*51h2bk46?|>e3dFyikvcKink7dAO7Qi z<&JV)eecFj?ML84&z?OkRRWHFK*cv+1RQb z!Vg;)n3MU4nc4xbu!C9!rxq?;XoMT_;1jGG3wK_S>+mdZjvP5gjvF`5<`Z=kUr>MG zkK)Jo>UVHoxNyM={bWCC+O}C&#ZC;^pRixWH@-Fy1LjjZ;HdIy_wL=6Q`B4P zORikGMuOA93vL?mU_B$}3l=Y4eEH0oGp+4#2wy0E{Dkk}x*I#W%^EIe2Ai*nkxyzf zHI4NhPOz8I_rw8y;uHM9ylM+}z$@M>r^s)q_shZQ-~~7Ml}9<`dohW96gfyfQ6H#z zV8mB$?Cf>$8-DHDwJUYQo2y_PIB=lFPEI21v4|`FblU)Dn1}O)#uGg}!w&pMEre5y z6+Kbl6ag>%2S38v!QQ>3;JHrB8AA++Dfsa}I>1g0nD5h1KQ+ypH@9_CaZ!I5&wKn2 zm&qwOq5RgqVpkcUm9x?%n%3I32v;20t~5T*xm{ zR`yzP_>4TJKHv*<;3xF3{`BkD&&VFc)T&j>>r?WVykji&2%p16d`K-&u49MW2Hr8Z zp7+?xBkC*cpbzT?x+PcR!0F%xH~7hmzlszPDKC8z*|RW)7~p^A13&qy`t`GZ{ra|k zgBkqnArw1206XKs$S2&TOTzMNy#4r&$S$P1~liQshbf*btQ zS@QWqkxE~E^;H}g7()!;4>86!=prxSzT&7?ub!<##0LN4cWehc{lWC>ufLk#e*4Xy ztFcSR!b5a$-sV015Y9!|qjnGr=7f(@JBULi2QRq6uQn8t?^T3vH`&u^48Wmr#vW<~ z+!R~wnyYvkHf(6xw{LI8j~{PyA1wFp-?wKs&YTFoX1tDJohHsa*RvmILe6~H#B=N* z|A+l~U*KI?v^Q?;OVU80sa*46{h`I15zsW)N0dR(T*|%@sBstxrNfY+V z_MM(PIeQ}D!tZVyn3MDBlP6E?*%VvV9{LjxI7MBj&UWe2<+#fRaQ`6=6)RTUOdP01 zj0L~?1v}sfbpku7zX%-q?6c3j*yMi6)+=fh>)x|x&+MH6*zmjBKwTit;C}k_sYysk zu;*;f+IlX>4q`!_La*FWZFbq}tZ@n00FRgh9^faPAA9f*xehmoF|}CFr>v3G9L1`6KXT+qyJqp5cWxV! zT-wMF?s~98^9WAJ{x2agFpxVB-@24!eUSH!BsZhMhL4y7F5o9^_zRneH#Gzwkw5T; zcwh@_JZCWXo{zle>_9z!oek*1XT*Zoqa!plG#Y#&zUxDhbz0unl{?e<)Bxgu&%x~5 zH1_H%au1$R&lrmh2)Tv-LqbBlanbm^Dh{fT`LTieDto#4;1ls(r?G*3huts9XNbSQ ze-F9ii6MU2;EsXLt)INZUvL`U5j*l$_c>|{`wh9@Nn%H8Y#`pmdhFP-G2jB9i0^)h zeINTj^17f1_tDKulqeC-UIV_QreO;lCU>Y~)Dr5UJMW1JdrxX_YPf`6Y`~Xg%a#oX zmxHgMe1aF;;HQz->^<0*|5K!{+^zSJvu_kN;Z`d+M>) zCEt1UH$3Rpty@%v3>k<4JOZEZ`9U6e_urh4iilJdX(jiQVRPopi3QV}w&e1jy%D*> z+CuJ=JLC~OOsUCPK34Ag!ocI;0$+0HIO4&2mqmp0YH5*rBL68_vg9J!H$H{)Z`z0n zw)o~f`wj3@zsXnll3bJ8{Z#J47lFgU1Fn?L)AGvhVeOe(z84l@9cd;KTD5A`2w5i+ z(_#nMu*IGCx}SrmTDyI15Ze-K)~p$Ueg_A5z@;%@P4I0R3(boX(xHY(Tai$?4~mdA z<7skr)>nT@zp;h9hdb~bAqKv4;(uA=6+imH0Upf*IHS2NUz0TIti9)xPtFr%M98B~ zBB4?n7RmW6mVAAirW_+S;O94u-?Gn%mAgs!ga6TsesF*%NCbS~OsQcTHHtGHF)JkU zFOm8p{}u_&moHyf_wL=J*bAoRe?Q6Djty{1&LC0w^XCskkE0L0=m!UQQgh!b-K>qo zDzivV5$XW@6Xvt=kUH0=T)A@La^DieTJSb`0-vPL#>jp-T<(tghz|8X`p}DhaDWF~ zuZn@Z_BQ(Yi;x?+M3@JE5LcTY@);_3>VwLZDf5HeVMI&aOyK-N4Z|hy|ZB)FRBx#K zuWpq5uW@0UHfTN3pWskEfo=dLJ+MGqG~^J1zI!kz)5k`QOYa_jqSM=B*)u z9`vEtjX$M4mTt*5`ll1Y4&n$O$t&sub&mC;l}Hy6uPtf#&UofwKIUb9^q>#D=m*D} z;+G+|sU7f;d>Kd`dN356dmHi9*MD~;5X(R%+)*^7bo%6|Wp7Wl5^k*F7nTPq9m-*3yKJ>oJ z=8j2#Ow7Ino%pSwNHLL;B4tI&i@*!+A5{3wbKcXB{sl!C&pgb>yzkQYGF`F_Thfc5 z3!V6l*yj+*Bf@V3w$$A{YoFijpP6BPUTrQOsgM za*(KkC@N;6@Xl6Uz(sdvcmLVh{V(77`gOQfr@E@Ux-WC*wiwo;#Sq&Tf6XI7Vk8^U zlFC+u*1rR8=l-U#{NDfP)5M#3wP_*IYC_9a-Spab9_G@mkLuMQr8gH0l|A}#^kir8 zu!+_mrG{=P=+)%Kl-yR>ZGO^?S5?={%VHvKQ{VO>0zG|v(PiO;r9T@}s^k}t)bslWaJcCo)C++l^X1Ke}$#HlQ3RQgswji!W`S>EA6EnS zTc6>5_cMI%*TCm)6}%HG;B|-b30{ex;Cr_M{`ad8@Sq0%Nj$b5r>@q+BC-;jol2p) z`#wf22t?PxYYQdY_Si+lI}q6C|A|kU__rZB9b2~Vf2jLt!%As2Z%oyT$70JAY;Y>X zHlJtM9asv3U`8?hF2c@$0_^h7$4PEtvU=i#Ci#=|IgUboPQ_cf4G~BnfT}5JTPwkS}jgh*gfs0{>0!Y0&k^z*f%;sIJ?OY4cWL_6BpIu19T~-7^F` z);gs?>r^t9oqUKzb`LPe`W}=H-iDk(JVtJe!cPl*&~4&@O3Ai84ZpF2s{is~{v3xL zTeNJyq{EJmz7(8}5hRe?uN&~9z4tPYdm5r_5Srk9%WOEv{PN!gr{R7OiO2kZyTae##1tYhe z!=Tl{=sVv79fz(hVjcpYzpsyfW(3C&??1er2DR!b8{1XsIQlI0#lQ_=7`-zVlTEKe z_0VlBI(DDtF@@qH1G=7Bv@V!qE{uZmU>uwWlfXw9EHe#*2wd)=x(T%#2j#;cFb_M( zPCc(|Y$U&|a!P{+`BUxaU7DX87;kt9Lv*6hPcsnR=eVME-$}8|r;!))W1fHXun%}& z>mt#v*S=1ZEzxbE7k*e1ilJN2(Hvcd3h`e^zF%=V6&u_$q34~0o&I^mD<6gd+1O+o z4YSaE>&iJlrFe5ZU85*_;NV_uE?nCI_3Y#YZAtsx1S)>3m)I{)T^UMqtkt#=Nx zMpvM0aR&>ICD9tBb?KfBJzv^)MENiZF2qKw2rSmMz{HvAFb~g%sVI&3D`4PAd7(57 zOv6EHmz%j5OST?{&aoJngcLzPumIcq@}TXJgH_HMSZtpR)gy^eFujHmJ1(H#+Aw^- z$OmnPEKZ^ANv46H!1MQf!RLo|gzhcc^)PL(XoW5`2R~^?L59}Zv;()GW=ng~DcV!q za-i#zNBj%0!!sGn4NpTsRRg0Y&%rO_m0%H`i+!RL3>qa*HcS*su3JRp3jJfI{Dw)h zmtm!;JM{gtXg@B%7TF3Z|JSVvPP3NNJx%m!$!alu}M$egx*pG1J@^9A6DSkZe7-^(2$3?z9gL z(mjuH#@8_8&;u;6PluMvBW(06z}5hYfuP4w-*p1xrq3t-v~DT(7jLtInST-v2B*P1 zFd2g>mIjTK6H2Zh3`xgc??f!nwWM`EMR%opVXw79D#X==7Td`mc|~h+S7O=|Cdp z*rs9W=^U)}D1fftW9%aSD=mUCX6oFAy=Tm1n$MFka=!snpL?(jPK9MqGKP>1gGb2; zCD$#?~Ykdg$LuT51Y_h)u{g9{F67U!syb7_xB^UGUGoVQGCu4LS zKkJ-F*QGv?=+yUsz_Wob^X7;B!TF5Wyp&|0(IGvScwrFb%W)<*G5ts~7M#q1mRkWf z`O;hkKBavq7fLG(Fm!@4t=Gwzt7D1X&R1aUaRUcM4{;yBLOXxT8 zxCwoi1k72tSMc9(ITfg`-v^^ml1=9oUH`{e<57gAj=4~^Nr%FLyBNCTGWt@EZPi~k zgn2gdW!}ucDUN#3Z|OF_s3rBI{4#uZ0w$S1!0cn0Sn8aQwO&u4C!+IEa0yl&iNbJ& z*}^=IQ`UgK>owwk6XpTQI2!Q?wlR6I3eSY}m`P-Zyii(2WZ)RLQ@=T_4Yp&mO*qCX zsZ$P_iV+H`*y2ogkI-k>7F3LlzE7d)R)l#cA3^bOGR7F+gp|%Xv>&-NiFp#3FULRg zXK+sAv-^ln@>`xsZ90pwd+v}A(lFm44_Y2iu*ts!JA$7JI_7M)!mqN*7)X2nqOI02 z@w`p(p9-7kd>oH^h7)ncu!+jSFER}_aCs~`2M%#hsjmdqQMtl;G4{L(wGI0OUk;rx z6HAQGz&N}VyF#BsSM&^Pyo;eu=SmgZEXeJ@k6*T3Mpq@HXUwyaFY{*pyhrg`7(kHe zG3Q97^wu~`-2Z^y&4Ide5!U)XgI>@J=!ccTDEt}Z7wQOmjyAlJl$V3{2P5$DWAiFbsQ% zZ6RgY81S5Y@f2z&@-T(Y$s_b{px@%tmCUn|FY{*pye_^Y{78`Pt?n!yzUwL`Tc+W+ zlLc5#=VI*uk{MbK!^l@Kjwr?ODf5NBk#n%AKgAF6KXJJX&ez|<_11f`<0b6R7vh(( zQ-nDBl}fHVU3&=^>UW}XC*oh=XcV10XkD-z>2cFBYWiaAjd}r-=yL1~FURJfS6Jo! z919$uV7hfSWcDWF$2CD>=Gn-Xc{6|BXL&vUOpxoh(5`Zf(M>2?WeM+UdB1>8&};0B zd=D#XO<=7|nlT70%qNh6lm@_IsR;e+H|tG#m=NFO*z&qjt}GRl*ooy5pTp zD5re#5Yi-v^TjB|Mc5bp0%oxvV0^v;+ao?;W8fQTcs$4KlZ8;QNX3r}jyz|c1m@e^ zhOUim3f(8HNS8HD#4P(lEICt#^?~oOEvf>>vDGlU@CjzoWsqO6iF8gCV%R)53r@Ey z;gKYU*F!P9lk4I2pc<~^i{t0=VH24plw9|wb|32Zrg0t*>fm^*0y`Wo&>lTQkf*q8 zC-%p@!v2eu*h}}@T`^VA3H=BypVv@xEXI_>8R#=rC%u^s%=;hw(0TBbxQV8>G27t@ zmid%JJM;m)HavZ!& zdg8?}jID)kL?u=Qyu*B#QYaqHLf2s`am{RK?uReyp>2aZ@T0*lYQguKb+>Xz*~@i&ie_oc7$1NE!* zSI|oN?Ll=8C@hRIEbfoD9dDDG@&&$78&2g^GET^X_c zycp|3tD#P7Q%YGkh4~S_%@1GYY3f($&|BJD#p)s1PyyYuV$k&mbX|w_{d(BmuYk>s z=QwgP2g{AEiNkcrD5_${B2Aciguy?f4Ch_|v4r#AfZM&3p2F~y50n-z!|16q>ApQ3 zYb_jM9iI!kJCs+Fs&I_fJY64PdL7si3#<>T#RBK2=-hv}H}fNWo2S_ZK6eP`B`T*$ zwrZm{bkW`dP2V@rivf%h$Of7h8a#^U8z zXM6yM1J6<($VB9m_qa&kD9=8tfal$89P|yxYJF2EEz+RzDs*R3!YWg19J`!}Re@xywtCEu@a=ht&wYIU<8>`X;P253zyEQh zXyK_GY$iV#lTQ!c1?XA=hm1O$&iDj}r01}|`3N?b9$>>Ed*U<`<7Ui){G54E(a^;F z)$5_YQ3p%4Hwz`#xm|wtTpFh$jMueuhW+()oVc9}$7IU$*_Cj5R1dnU;BXSzKx=}o zV9@e=gKh)IiI`U-KPf7iFY{*p{P4QwvqxXTNP>!lWGlVFGu9`q3!?l+exTzo=o*1j zIbyix*TOaD9h_2⁡^m)SYy?dq!Zn!5-o_6S6Z^F>%&xOjMl>In_Br$#vP8vxI(4 z!@W3q{t6ru)8Tk82d-%)IFtJxXNqd!lrM%o?Qv|wUa~F-Ju%vI$M%RGZ`=ZM_bRS^Pd>VN%zu&vZu|GK9@jaFAtD_0C2&=nEjrL#W zoKmyrdOeO%ES<;!Tp!cgEUANkX%+mQzJX7EF+8(!;gOLE&-8ToWMm*9D+>YH*_1OH z;7@g5YWJdkPa5ZyoeTe>5{OFQLR3}_zZdoJpndB!?Y*{?2ifl%{U6u#93tz_JR12h zuRpp^Qvc7PU%p3R z=?errehlA7kKjjq{fMtG@%2qhgCCV#=k|cyT!?5~$cr+Bm486kyBY+&sfX`Nz@2P3 zN#Fl@u6CX;7Y~q`5y|=+c`%SF~W-@ZjeSsB8MixE;-h~T_D1QBO0!-|R!QBs1amoIVl z-8-DEtVDE0Ey6$1JiH^nmI2O`TaINB|Hz`6pT>US&-$4M^J!WK95YR8nSOrt@VXGb z^HIt7i7^CTM_L5!-b2Rvt6PZ5jy$COgYU`SQ>Y(t{zd^tlJN4*qFQ>63>EP{`WJf*dScqWa5m^Jo z)Qb^UUyqA*b-48TGvbNsrJ5R{jHmh~YL63(aUPVz>nLAWk}uyj@V8F=h$*XfC4JZX z2Yc4jsE_rse&)e^m>2W=BOg$g@UV^StB!=81l|Yue8Tbse@M1$y<@w`+|)@|Dv_8%(ar?g>r z%KrG2YUcvlBVSb`@KYVxBSz$BF`{U`>DY+y8ZkmD>f!&Umewwvxo&1w&(bwY`C;UE zzt-*A8?wAcuzc3T`dBaPXCBPw-{nt31z$C{gXdu&f#Xttnrt<uQRzHuRf$a11ji{{F`N7+stF=63GqaXg;iYl@lwC3jN$4^NXl zY!lBV^I|`J3vTCr9>@4=cy}f-4IZR8m5^xmTe69b^eBmzjqNm8qD|v(;vmsgV9QL} zN%U-NC!P|$o7#t1O7s&fp)t}EB>I2(Jyl{rGnv0Oley^c?If4|)$rG$?m&wczjSHQ GSpE$k?VslW diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/shutdownN.tiff b/BasiliskII/src/MacOSX/Multiple-Windows/English.lproj/Win512x342.nib/shutdownN.tiff deleted file mode 100644 index 61f5a7dd98c86c8695316bc91ca68cfb128cba31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9798 zcmc)P3Dnoqx(D!H4Y!kAMUh*}>PYTgxQJVlDO0B6pv=}~p=DT-BvXz^Su8^=L&uy- z$dECa%1lIrOqD6gOqvYuzRzc$|9b9 z^#V`7E?v4jaK;&DEWGKao6=*CJ(ga5_0{y=d+()>KmIs<^2sM@?%cU)&YU^vjW^y% zPe1*1y7ksuQ|Pv^Teofxv~1b3A3mW2zwyyOQ}c=Gwb#I^S( zn{0CLIp>^{?KySo)HHwo{Pg3GKdub?W!BL7_19ld_uqeiVvEf;-~3+u$*IUA_aD8g zZU2Xen*sanx8Lj$BSxeL9(W+f%ts%6l)nD@>-7Ei-)CB|U_tu!+i&x;FTeaU75eI{ zukv&Aixw?PeBqtXKKm@a^UgbI^5n_cCy_U^!^Z;xc(b5?)F%bMyjykcwbveY!U-oV zy6UQ{(%pC8oy5V688fncaU}j>nK^T2wyn9>UVAO;X>`x#=B@M2`|rP>^W^Qf-%c;R z^iq28!3UF^I`!037p=3-I>X2fBLCOKRyF?SZQ8UM-oJnU+RHAxER7pCF3WoAsi%@S znl^1(mjB|5FXnsCmPaqV@Iu{lYhix*<(Jbdue_4S=bwK*J^JXQ>CQXv%>Fp@%rk34 zkKuv8`LEQ2-t=!Cbz>0wi`P-3My0#%x-0AO_~VbKC!TmB*O_OZeKtM!+;a(zf{$*2 zBSmbav(7pzt`X;}}j~}0Iyz$0##T8eiLk>A)4jk}QaQ#xAiy`&r4?*i~y6L79 z&pYqDG;-v~>;rz5%X|($+rt4nj3wrcbcnsKj_S|5rwhNZfqlc?^3X#Mr3n)zq_Jbi zX1no!=gyrc2A&Q<@*F-mS9H-)U273O{PXFjpPuCK%{SkiZomEZjGr8K6AxkoR+#Ny zFwwL8-g@h;Q|x2OXwGx^_``2GP8T*{3qIu!df-D3`^WI%!&B?lt^W*H1>cH%K{qkf zJoe2_5d+gNy6B?p)7x&lE!}tDecAr(1wXl^-oRtc*=L`f_T6{ijE{Y{+G?w`<(6CK z(YX_q)C(N>|gN1B%ai(K7IP6-FDk8MNgD*!PB*C*A#t79^JFM`Q3NlJ?+2${@KTT ziBE|?>-a;>5Vve|-F4R`_6%PPhOdGX-s-FPV6}MIHe^q}{PN4|>Ja?mpZ!bhup#{X zyw_fP<-FZ)yX|rv5+7otS_k)@A9mPb$vXKSwoR8_dTI7&@rgC^ogU(r|J5lm74J-j zF9=RCQ|$}!m3`2-apPVmpM3J->#x5)+dvJ1U*3sn_9E}Cx86$XRj*#XGA1!kA9}$+ z-)bF7{>UYL$~N00s8wQW^ytxIbuoN_wfLesFXXy7Tc=g4Rzohh z;DQ`O>L^>lC4LHivcy>QYPs&fuYOo7U#fMG4|Jh}=cWG8*L!@z4&ugsjknk;`SIkF zPv$xGR()A(t+j^0S-}gpi$CmVa=!hB8*VuM>Z`BLx{Dz`E%-~HAO}x6>7=ydjyvYM zGi1n+oG)USzsQHTeolK%7whmo?X=Uf9?}2i{ZJ3`?z``1UFg9d)|Z%)-%;Rr((st^OCi4 zgwEE|Pi*(=*KaPI6})i6uSUs*c0rw@$62H=mB-?NJpRS^gAYE)dK`W9(YZ#lv;GEt zcKh(d5A)f^NFVWTjnRGeJbbXJH`cI8^p#nTb$VL*SjUI<4SQeY>LNHRc;SX$Ui@p& zx|O|72AJAA^QY@U}j-+c2;=Eslt*e~pP z;?>#CT72mtruaf^L?1s7&LDWJb!b_6)-CGH3_g=f-Yx!TKYEaH)KN!exnh{E=A17J z(TCo0z`W7D=Vi^pg$uJkmRbG5 z;^&`#PD__A&AQRu*&k-l%T-%jn{9i{F~?*-;3w|*nvdvfq&pwVb#d3BLx+)}L;ZYM zrY<#W)@(rRaZ5@a!Gr%{LhLKY;(VHOP%W{aRO5rwJ)855vHrYg`lQk?o^r}587Fzg zpY&h@b`ulP|1D|Wyt!{4_3P3y`$Nq4Jm{curtS?yJi#4LN2i!bOvUi5OK z;0vn1Pt!r)k^7|>w{Oy<$?@@xXBPj_q3|?{Cw0g^A;;wRPCM)J$?Nt(zDMt~(MB7M z(`)c;^~JyR;tM%rjqiSHi#||%^U0A%9+~9pvBw^pNB5rFNF0n3cmI+!V5S2E_to@(3k&bP>=Ywetdizng(m}1HOK<6`QGB>OC zeIL*v&hqo)d*29nD!AZV-Z_px?02gLIj?RSv}@3RZ@lrwW22{8T51KpF8A_}9&m^U zI=}{_J(6yP+!yTDSF1ldRa6x28R zu?ewH)>i8wriwqrLFozPNHt#PhHAZF7vJJvonDdsqZZXh&QBn}f&(77iVy4w^{?WK zk{27rg6=^F1oe$`?}V`5()#vtFV@r^HieB})GhrW%;o&S?rKcgH@#P%A0M-S)VhM7 zd^q4Kc_3y=F2~PhE_F74=Zn#KVzVH5bZAiDs10M|JUAcT>WfeK2qv{fErU~>=~ayG zJr{okdv&eA50B_`=Et{5@x%V)k`D(wErQ^Kb43^3)F@{>K3gy7zk+rPIxMJf+qP{- z9CzGt)7V>2P<@s7g2f!HV#Qc`j{3O0@0qw7Fkry6cJ11YAg3aaT=L<7XJx*(#M9w`sH!)?WljqDE23h zT=L<72d=;8gP5+ntZNb^H`WTmhduZ;=SPfvgv+-d8@8g3XzW9?vUWxx-i$7S@UF^^( zNL}MwHnLxeSN)4VQ9lV!&mh?P1c~hfE2DeQ&0A-^_q>k}e)!@~4teDMmRGe;ng(Ni z37PEHK4^oWje|M`bq*32zCRRl@40#FtZyIWeSGl4_qVituv_j$mxe)Pk;!g+-zun0 zkne@!`Hw;CRgrto&0A-^_q<=Q@`x|_yWz}!b&0A-^_e#wC zp4da|-&{o>IjtVyidpi52Ly5HN?w5#IzA5}c}{om)om%sk{*X*Yu N4I2D=iw2ePe*pf7`a1vs diff --git a/BasiliskII/src/MacOSX/Multiple-Windows/README b/BasiliskII/src/MacOSX/Multiple-Windows/README deleted file mode 100644 index b67bd892..00000000 --- a/BasiliskII/src/MacOSX/Multiple-Windows/README +++ /dev/null @@ -1,5 +0,0 @@ -This is a version of the interface that would allow multiple emulations to -run side-by-side, in different windows. Currently, the uae_cpu engine is not -re-entrant, and some of the Basilisk glue would not allow this, so this will -probably never be used. I will save it here for educational purposes, and just -in case this feature is ever needed. diff --git a/BasiliskII/src/MacOSX/NNThread.h b/BasiliskII/src/MacOSX/NNThread.h deleted file mode 100644 index 72a0a1d5..00000000 --- a/BasiliskII/src/MacOSX/NNThread.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// NNThread.h -Not Nextstep Thread? -// Nigel's Nice Thread? -// -// Revision 1.2, Tuesday May 25 2004 -// -// Created by Nigel Pearson on Tue Nov 28 2000. -// Public Domain. No rights reserved. -// - -// Define what flavour of threading to use: -#define USE_NSTHREAD -//#define USE_PTHREAD - -#import - -#import -#import - -#ifdef USE_PTHREAD -#include - -struct pthreadArgs // This duplicates most of the stuff in the NNThread object -{ - id *object; - SEL *sel; - - NSAutoreleasePool *pool; - BOOL allocPool, - *completed; -}; -#endif - -@interface NNThread : NSObject -{ - id object; - SEL sel; - thread_t machThread; -#ifdef USE_PTHREAD - pthread_t pThread; - struct pthreadArgs pthreadArgs; -#endif - NSAutoreleasePool *pool; - BOOL allocPool, - completed, - suspended; -} - -- (NNThread *) initWithAutoReleasePool; -- (NNThread *) initSuspended: (BOOL) startSuspended - withAutoreleasePool: (BOOL) allocatePool; - -- (void) perform: (SEL)action of: (id)receiver; -- (void) resume; -- (BOOL) start; -- (void) suspend; -- (void) terminate; - -@end - -typedef enum _NNTimeUnits -{ - NNnanoSeconds = 1, - NNmicroSeconds = 2, - NNmilliSeconds = 3, - NNseconds = 4 -} -NNTimeUnits; - -#import - -@interface NNTimer : NNThread -{ - struct timespec delay; - BOOL repeating; - id timerObject; - SEL timerSel; -} - -- (NNTimer *) initWithAutoRelPool; - -- (void) changeIntervalTo: (int)number units: (NNTimeUnits)units; -- (void) invalidate; - -- (void) perform: (SEL)action of: (id)receiver - after: (int)number units: (NNTimeUnits)units; - -- (void) repeat: (SEL)action of: (id)receiver - every: (int)number units: (NNTimeUnits)units; - -@end \ No newline at end of file diff --git a/BasiliskII/src/MacOSX/NNThread.m b/BasiliskII/src/MacOSX/NNThread.m deleted file mode 100644 index 535aa877..00000000 --- a/BasiliskII/src/MacOSX/NNThread.m +++ /dev/null @@ -1,257 +0,0 @@ -// -// NNThread.m -Not Nextstep Thread? -// Nigel's Nice Thread? -// -// Revision 1.4, Tuesday May 25 2004 -// -// Created by Nigel Pearson on Tue Nov 28 2000. -// Public Domain. No rights reserved. -// - -#import "NNThread.h" -#import // For objc_msgSend() prototype - -@implementation NNThread - -// Define the wrapper first so that init knows about it without having to put it in the .h - -#ifdef USE_NSTHREAD -- (void) wrapper -{ - machThread = mach_thread_self(); - - if ( object == nil || sel == (SEL) nil || suspended ) - thread_suspend (machThread); // Suspend myself - - if ( allocPool ) - pool = [NSAutoreleasePool new]; - - // [object sel] caused "cannot find method" warnings, so I do it a non-obvious way: - objc_msgSend (object, sel); - - completed = YES; - - if ( allocPool ) - [pool release]; -} -#endif - -#ifdef USE_PTHREAD -void * -pthreadWrapper (void *arg) -{ - struct pthreadArgs *args = arg; - - if ( args -> allocPool ) - args -> pool = [NSAutoreleasePool new]; - - objc_msgSend (*(args->object), *(args->sel)); - - *(args->completed) = YES; - - if ( args -> allocPool ) - [args -> pool release]; - - return NULL; -} - -- (BOOL) wrapper -{ - int error; - - pthreadArgs.object = &object; - pthreadArgs.sel = &sel; - pthreadArgs.allocPool = allocPool; - pthreadArgs.completed = &completed; - pthreadArgs.pool = nil; - - if ( object == nil || sel == (SEL) nil || suspended ) - error = pthread_create_suspended_np (&pThread, NULL, &pthreadWrapper, &pthreadArgs); - else - error = pthread_create (&pThread, NULL, &pthreadWrapper, &pthreadArgs); - - if ( error ) - NSLog(@"%s - pthread_create failed"); - else - machThread = pthread_mach_thread_np (pThread); - - return ! error; -} -#endif - -- (NNThread *) initSuspended: (BOOL) startSuspended - withAutoreleasePool: (BOOL) allocatePool -{ - self = [super init]; - - allocPool = allocatePool; - completed = NO; - suspended = startSuspended; - object = nil; - sel = (SEL) nil; - -#ifdef USE_NSTHREAD - [NSThread detachNewThreadSelector:@selector(wrapper) - toTarget:self - withObject:nil]; -#endif - -#ifdef USE_PTHREAD - if ( ! [self wrapper] ) // Wrapper does the thread creation - { - NSLog(@"%s - pthread wrapper failed", __PRETTY_FUNCTION__); - return nil; - } -#endif - - return self; -} - -- (NNThread *) init -{ - return [self initSuspended: YES withAutoreleasePool: NO]; -} - -- (NNThread *) initWithAutoReleasePool -{ - return [self initSuspended: YES withAutoreleasePool: YES]; -} - -- (BOOL) completed -{ - return completed; -} - -- (void) perform: (SEL)action of: (id)receiver -{ - object = receiver, sel = action; -} - -- (void) resume -{ - if ( suspended ) - [self start]; - else - NSLog (@"%s - thread not suspended", __PRETTY_FUNCTION__); -} - -- (BOOL) start -{ - kern_return_t error; - - if ( object == nil || sel == (SEL) nil ) - { - NSLog (@"%s - cannot start thread, object or selector invalid", __PRETTY_FUNCTION__); - return NO; - } - if ( ( error = thread_resume (machThread) ) != KERN_SUCCESS ) - NSLog (@"%s - thread_resume() failed, returned %d", __PRETTY_FUNCTION__, error); - suspended = NO; - return YES; -} - -- (void) suspend -{ - if ( ! suspended ) - { - kern_return_t error; - - if ( ( error = thread_suspend (machThread) ) != KERN_SUCCESS ) - NSLog (@"%s - thread_resume() failed, returned %d", __PRETTY_FUNCTION__, error); - suspended = YES; - } -} - -- (void) terminate -{ - kern_return_t error; - - if ( ( error = thread_terminate (machThread) ) != KERN_SUCCESS ) - NSLog (@"%s - thread_terminate() failed, returned %d", __PRETTY_FUNCTION__, error); -} - -@end - -@implementation NNTimer - -- (NNTimer *) init -{ - self = [super init]; - repeating = YES; - return self; -} - -- (NNTimer *) initWithAutoRelPool -{ - self = [super init]; - allocPool = YES; - repeating = YES; - return self; -} - - -- (void) changeIntervalTo: (int)number - units: (NNTimeUnits)units -{ - switch ( units ) - { - case NNnanoSeconds: - delay.tv_nsec = number; - delay.tv_sec = 0; - break; - case NNmicroSeconds: - delay.tv_nsec = number * 1000; - delay.tv_sec = 0; - break; - case NNmilliSeconds: - delay.tv_nsec = number * 1000000; - delay.tv_sec = 0; - break; - case NNseconds: - delay.tv_nsec = 0; - delay.tv_sec = number; - break; - default: - NSLog (@"%s illegal units(%d)", __PRETTY_FUNCTION__, units); - } -} - -- (void) invalidate -{ - repeating = NO; -} - -- (void) timerLoop -{ - // For some strange reason, Mac OS X does not have this prototype - extern int nanosleep (const struct timespec *rqtp, struct timespec *rmtp); - - while ( repeating ) - { - nanosleep(&delay, NULL); - completed = NO; - // This caused a few warnings: - // [timerObject timerSel]; - // so I do it a non-obvious way: - objc_msgSend (timerObject, timerSel); - completed = YES; - } -} - -- (void) perform: (SEL)action of: (id)receiver - after: (int)number units: (NNTimeUnits)units -{ - object = self, sel = @selector(timerLoop), - timerObject = receiver, timerSel = action, repeating = NO; - [self changeIntervalTo: number units: units]; -} - -- (void) repeat: (SEL)action of: (id)receiver - every: (int)number units: (NNTimeUnits)units -{ - object = self, sel = @selector(timerLoop), - timerObject = receiver, timerSel = action, repeating = YES; - [self changeIntervalTo: number units: units]; -} - -@end \ No newline at end of file diff --git a/BasiliskII/src/MacOSX/PrefsEditor.h b/BasiliskII/src/MacOSX/PrefsEditor.h deleted file mode 100644 index b67c2310..00000000 --- a/BasiliskII/src/MacOSX/PrefsEditor.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * PrefsEditor.h - GUI stuff for Basilisk II preferences - * (which is a text file in the user's home directory) - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -@interface TableDS : NSObject -{ - int numItems; - NSMutableArray *col1, - *col2; -} - -- (void) addInt: (int)target - withPath: (NSString *)path; - -- (void) addObject: (NSObject *)obj - withPath: (NSString *)path; - -- (void) deleteAll; - -- (BOOL) deleteRow: (int)row; - -- (int) intAtRow: (int)row; - -- (int) numberOfRowsInTableView: (NSTableView *)tView; - -- (NSString *) pathAtRow: (int)row; - -- (id) tableView: (NSTableView *)tView - objectValueForTableColumn: (NSTableColumn *)tColumn - row: (int)rowIndex; -@end - -#include "Emulator.h" - -@interface PrefsEditor : NSObject -{ - IBOutlet NSSlider *emuFreq; - IBOutlet NSView *newVolumeView; - IBOutlet NSTextField *newVolumeSize; - IBOutlet NSWindow *panel; - IBOutlet Emulator *theEmulator; - - - IBOutlet NSButton *bootFromAny, - *bootFromCD; - IBOutlet NSTextField *bytes; - IBOutlet NSButton *classic, - *CPU68000, - *CPU68020, - *CPU68030, - *CPU68040; - IBOutlet NSTextField *delay, - *depth; - IBOutlet NSButton *disableCD, - *disableSound; - IBOutlet NSTableView *diskImages; - IBOutlet NSTextField *etherNet, - *extFS; - IBOutlet NSButton *FPU; - IBOutlet NSTextField *frequency, - *height; - IBOutlet NSButton *IIci; - IBOutlet NSPopUpButton *keyboard; - IBOutlet NSTextField *MB, - *modem; - IBOutlet NSButton *openGL; - IBOutlet NSTextField *prefsFile, - *printer; - IBOutlet NSButton *quadra900; - IBOutlet NSTextField *ROMfile; - IBOutlet NSButton *screen; - IBOutlet NSTableView *SCSIdisks; - IBOutlet NSTextField *width; - IBOutlet NSButton *window; - - NSString *devs, - *home; - - TableDS *volsDS, // Object managing tha data in the Volumes, - *SCSIds; // and SCSI devices, tables - - NSImage *locked, - *blank; - NSImageCell *lockCell; - - BOOL edited; // Set if the user changes anything, reset on save -} - -- (BOOL) hasEdited; -- (NSWindow *) window; - -- (IBAction) AddSCSI: (id)sender; -- (IBAction) AddVolume: (id)sender; -- (IBAction) BrowseExtFS: (id)sender; -- (IBAction) BrowsePrefs: (id)sender; -- (IBAction) BrowseROM: (id)sender; -- (IBAction) ChangeBootFrom: (NSMatrix *)sender; -- (IBAction) ChangeCPU: (NSMatrix *)sender; -- (IBAction) ChangeDisableCD: (NSButton *)sender; -- (IBAction) ChangeDisableSound:(NSButton *)sender; -- (IBAction) ChangeFPU: (NSButton *)sender; -- (IBAction) ChangeKeyboard: (NSPopUpButton *)sender; -- (IBAction) ChangeModel: (NSMatrix *)sender; -- (IBAction) ChangeScreen: (id)sender; -- (IBAction) CreateVolume: (id)sender; -- (IBAction) DeleteVolume: (id)sender; -- (IBAction) EditBytes: (NSTextField *)sender; -- (IBAction) EditDelay: (NSTextField *)sender; -- (IBAction) EditEtherNetDevice:(NSTextField *)sender; -- (IBAction) EditExtFS: (NSTextField *)sender; -- (IBAction) EditFrequency: (NSTextField *)sender; -- (IBAction) EditMB: (NSTextField *)sender; -- (IBAction) EditModemDevice: (NSTextField *)sender; -- (IBAction) EditPrinterDevice: (NSTextField *)sender; -- (IBAction) EditROMpath: (NSTextField *)sender; -- (IBAction) LoadPrefs: (id)sender; -- (IBAction) RemoveSCSI: (id)sender; -- (IBAction) RemoveVolume: (id)sender; -- (NSString *) RemoveVolumeEntry; -- (IBAction) ResetPrefs: (id)sender; -- (IBAction) ShowPrefs: (id)sender; -- (IBAction) SavePrefs: (id)sender; - -@end \ No newline at end of file diff --git a/BasiliskII/src/MacOSX/PrefsEditor.mm b/BasiliskII/src/MacOSX/PrefsEditor.mm deleted file mode 100644 index 1b9cd13a..00000000 --- a/BasiliskII/src/MacOSX/PrefsEditor.mm +++ /dev/null @@ -1,844 +0,0 @@ -/* - * PrefsEditor.m - GUI stuff for Basilisk II preferences - * (which is a text file in the user's home directory) - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "PrefsEditor.h" - -@implementation TableDS - -- (TableDS *) init -{ - self = [super init]; - - numItems = 0; - col1 = [NSMutableArray new]; - col2 = [NSMutableArray new]; - - return self; -} - -- (void) dealloc -{ - [col1 dealloc]; - [col2 dealloc]; - [super dealloc]; -} - -- (void) addInt: (int)target - withPath: (NSString *)path -{ - [col1 addObject: [NSNumber numberWithInt: target]]; - [col2 addObject: path]; - ++numItems; -} - -- (void) addObject: (NSObject *)obj - withPath: (NSString *)path -{ - [col1 addObject: obj]; - [col2 addObject: path]; - ++numItems; -} - -- (void) deleteAll -{ - numItems = 0; - [col1 removeAllObjects]; - [col2 removeAllObjects]; -} - -- (BOOL) deleteRow: (int)row -{ - if ( row > numItems ) - return NO; - - [col1 removeObjectAtIndex: row]; - [col2 removeObjectAtIndex: row]; - -- numItems; - - return YES; -} - -- (int)intAtRow: (int)row -{ - return [[col1 objectAtIndex: row] intValue]; -} - -- (int) numberOfRowsInTableView: (NSTableView *)tView -{ - return numItems; -} - -- (NSString *)pathAtRow: (int)row -{ - return (NSString *) [col2 objectAtIndex: row]; -} - -- (id) tableView: (NSTableView *)tView - objectValueForTableColumn: (NSTableColumn *)tColumn - row: (int)row -{ - if ( [[tColumn identifier] isEqualToString:@"path"] ) - return [col2 objectAtIndex: row]; - else - return [col1 objectAtIndex: row]; -} - -@end - -#import // For [NSBundle pathForImageResource:] proto - -#include -using std::string; -extern string UserPrefsPath; // from prefs_unix.cpp - -#import "sysdeps.h" // Types used in Basilisk C++ code -#import "video_macosx.h" // some items that we edit here -#import "misc_macosx.h" // WarningSheet() prototype -#import "main_macosx.h" // ChoiceAlert() prototype - - -#import - -#define DEBUG 0 -#import - -@implementation PrefsEditor - -- (PrefsEditor *) init -{ - self = [super init]; - - edited = NO; - - devs = @"/dev"; - home = [NSHomeDirectory() retain]; - volsDS = [TableDS new]; - SCSIds = [TableDS new]; - - lockCell = [NSImageCell new]; - if ( lockCell == nil ) - NSLog (@"%s - Can't create NSImageCell?", __PRETTY_FUNCTION__); - - blank = [NSImage new]; - locked = [[NSImage alloc] initWithContentsOfFile: - [[NSBundle mainBundle] pathForImageResource: @"nowrite.icns"]]; - if (locked == nil ) - NSLog(@"%s - Couldn't open write protection image", __PRETTY_FUNCTION__); - - return self; -} - -- (void) dealloc -{ - [home release]; - [volsDS release]; - [SCSIds release]; - [lockCell release]; - [blank release]; - [locked release]; - [super dealloc]; -} - -- (void) awakeFromNib -{ - emuFreq = [theEmulator speed]; -#if DEBUG - [self ShowPrefs: self]; // For testing -#endif -} - -- (BOOL) hasEdited -{ - return edited; -} - -- (NSWindow *) window -{ - return panel; -} - -- (IBAction) AddSCSI: (id)sender -{ - NSOpenPanel *oP = [NSOpenPanel openPanel]; - - if ( [oP runModalForDirectory:home file:nil types:nil] == NSOKButton ) - { - [SCSIds addInt: -1 - withPath: [oP filename] ]; - [SCSIdisks reloadData]; - edited = YES; - } -} - -- (IBAction) AddVolume: (id)sender -{ - NSOpenPanel *oP = [NSOpenPanel openPanel]; - - if ( [oP runModalForDirectory:home file:nil types:nil] == NSOKButton ) - { - [volsDS addObject: (NSObject *) locked - withPath: [oP filename] ]; - PrefsAddString("disk", [[oP filename] UTF8String]); - [diskImages reloadData]; - edited = YES; - } -} - -- (IBAction) BrowseExtFS: (id)sender -{ - NSOpenPanel *oP = [NSOpenPanel openPanel]; - - [oP setCanChooseDirectories: YES]; - [oP setCanChooseFiles: NO]; - [oP setPrompt: @"Select"]; - [oP setTitle: @"Select a directory to mount"]; - D(NSLog(@"%s - home = %@, [extFS stringValue] = %@", - __PRETTY_FUNCTION__, home, [extFS stringValue])); - if ( [oP runModalForDirectory: ([extFS stringValue] ? [extFS stringValue] : home) - file:nil - types:nil] == NSOKButton ) - { - [extFS setStringValue: [oP directory] ]; - PrefsReplaceString("extfs", [[oP directory] UTF8String]); - edited = YES; - } -} - -- (IBAction) BrowsePrefs: (id)sender -{ - NSOpenPanel *oP = [NSOpenPanel openPanel]; - - [oP setCanChooseFiles: YES]; - [oP setTitle: @"Select a Preferences file"]; - D(NSLog(@"%s - home = %@", __PRETTY_FUNCTION__, home)); - if ( [oP runModalForDirectory: ([prefsFile stringValue] ? [prefsFile stringValue] : home) - file:nil - types:nil] == NSOKButton ) - { - [prefsFile setStringValue: [oP filename] ]; - UserPrefsPath = [[oP filename] UTF8String]; - } -} - -- (IBAction) BrowseROM: (id)sender -{ - NSOpenPanel *oP = [NSOpenPanel openPanel]; - - [oP setCanChooseFiles: YES]; - [oP setTitle: @"Open a ROM file"]; - D(NSLog(@"%s - home = %@", __PRETTY_FUNCTION__, home)); - if ( [oP runModalForDirectory: ([ROMfile stringValue] ? [ROMfile stringValue] : home) - file:nil - types:nil] == NSOKButton ) - { - [ROMfile setStringValue: [oP filename] ]; - PrefsReplaceString("rom", [[oP filename] UTF8String]); - edited = YES; - } -} - -#include // for CDROMRefNum - -- (IBAction) ChangeBootFrom: (NSMatrix *)sender -{ - if ( [sender selectedCell] == (id)bootFromCD ) - { - [disableCD setState: NSOffState]; - - PrefsReplaceInt32("bootdriver", CDROMRefNum); - } - else - PrefsReplaceInt32("bootdriver", 0); - edited = YES; -} - -- (IBAction) ChangeCPU: (NSMatrix *)sender -{ - PrefsReplaceInt32("cpu", [[sender selectedCell] tag]); - edited = YES; -} - -- (IBAction) ChangeDisableCD: (NSButton *)sender -{ - int disabled = [disableCD state]; - - PrefsReplaceBool("nocdrom", disabled); - if ( disabled ) - { - [bootFromAny setState: NSOnState]; - [bootFromCD setState: ![disableCD state]]; - } - edited = YES; -} - -- (IBAction) ChangeDisableSound: (NSButton *)sender -{ - BOOL noSound = [disableSound state]; - - if ( ! noSound ) - WarningSheet(@"Sound is currently unimplemented", panel); - - PrefsReplaceBool("nosound", noSound); - edited = YES; -} - -- (IBAction) ChangeFPU: (NSButton *)sender -{ - PrefsReplaceBool("fpu", [FPU state]); - edited = YES; -} - -- (IBAction) ChangeKeyboard: (NSPopUpButton *)sender -{ - // Deselest current item - int current = [keyboard indexOfItemWithTag: PrefsFindInt32("keyboardtype")]; - if ( current != -1 ) - [[keyboard itemAtIndex: current] setState: FALSE]; - - PrefsReplaceInt32("keyboardtype", [[sender selectedItem] tag]); - edited = YES; -} - -- (IBAction) ChangeModel: (NSMatrix *)sender -{ - PrefsReplaceInt32("modelid", [[sender selectedCell] tag]); - edited = YES; -} - - -// If we are not using the CGIMAGEREF drawing strategy, -// then source bitmaps must be 32bits deep. - -- (short) testWinDepth: (int) newbpp -{ -#ifdef CGIMAGEREF - return newbpp; -#else - if ( newbpp != 32 ) - WarningSheet(@"Sorry - In windowed mode, depth must be 32", panel); - return 32; -#endif -} - -// This is called when the screen/window, -// width, height or depth is clicked. -// -// Note that sender may not actually be an NSMatrix. - -- (IBAction) ChangeScreen: (NSMatrix *)sender -{ - NSButton *cell = [sender selectedCell]; - - short newx = [width intValue]; - short newy = [height intValue]; - short newbpp = [depth intValue]; - short newtype; - char str[20]; - - if ( cell == screen ) - newtype = DISPLAY_SCREEN; - else if ( cell == window ) - newtype = DISPLAY_WINDOW; - else - newtype = display_type; - - // Check that a field actually changed - if ( newbpp == init_depth && newx == init_width && - newy == init_height && newtype == display_type ) - { - D(NSLog(@"No changed GUI items in ChangeScreen")); - return; - } - - // If we are changing type, supply some sensible defaults - - short screenx = CGDisplayPixelsWide(kCGDirectMainDisplay), - screeny = CGDisplayPixelsHigh(kCGDirectMainDisplay), - screenb = CGDisplayBitsPerPixel(kCGDirectMainDisplay); - - if ( newtype != display_type ) - { - D(NSLog(@"Changing display type in ChangeScreen")); - - // If changing to full screen, supply main screen dimensions as a default - if ( newtype == DISPLAY_SCREEN ) - newx = screenx, newy = screeny, newbpp = screenb; - - // If changing from full screen, use minimum screen resolutions - if ( display_type == DISPLAY_SCREEN ) - { - newx = MIN_WIDTH, newy = MIN_HEIGHT; - newbpp = [self testWinDepth: newbpp]; - } - } - else - { - newbpp = [self testWinDepth: newbpp]; - - // Check size is within ranges of MIN_WIDTH ... MAX_WIDTH - // and MIN_HEIGHT ... MAX_HEIGHT - // ??? - } - - [width setIntValue: newx]; - [height setIntValue: newy]; - [depth setIntValue: newbpp]; - - - // Store new prefs - *str = '\0'; - switch ( newtype ) - { - case DISPLAY_WINDOW: - if ( newbpp ) - sprintf(str, "win/%hd/%hd/%hd", newx, newy, newbpp); - else - sprintf(str, "win/%hd/%hd", newx, newy); - break; - case DISPLAY_SCREEN: - if ( newbpp ) - sprintf(str, "full/%hd/%hd/%hd", newx, newy, newbpp); - else - sprintf(str, "full/%hd/%hd", newx, newy); - break; - }; - PrefsReplaceString("screen", str); - - parse_screen_prefs(str); - - edited = YES; - - if ( display_type != DISPLAY_SCREEN ) - { - D(NSLog(@"Display type is not SCREEN (%d), resizing window", - display_type)); - resizeWinTo(newx, newy); - } -} - -- (IBAction) CreateVolume: (id)sender -{ - NSSavePanel *sP = [NSSavePanel savePanel]; - - [sP setAccessoryView: newVolumeView]; - [sP setPrompt: @"Create"]; - [sP setTitle: @"Create new volume as"]; - - if ( [sP runModalForDirectory:NSHomeDirectory() file:@"basilisk-II.vol"] == NSOKButton ) - { - char cmd[1024]; - const char *filename = [[sP filename] UTF8String]; - int retVal, - size = [newVolumeSize intValue]; - - sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", filename, size); - - retVal = system(cmd); - if (retVal != 0) - { - NSString *details = [NSString stringWithFormat: - @"The dd command failed.\nReturn status %d (%s)", - retVal, strerror(errno)]; - WarningSheet(@"Unable to create volume", details, nil, panel); - } - else - { - [volsDS addObject: (NSObject *) blank - withPath: [sP filename] ]; - PrefsAddString("disk", filename); - [diskImages reloadData]; - } - } -} - -- (BOOL) fileManager: (NSFileManager *) manager -shouldProceedAfterError: (NSDictionary *) errorDict -{ - NSRunAlertPanel(@"File operation error", - @"%@ %@, toPath %@", - @"Bugger!", nil, nil, - [errorDict objectForKey:@"Error"], - [errorDict objectForKey:@"Path"], - [errorDict objectForKey:@"ToPath"]); - return NO; -} - -- (IBAction) DeleteVolume: (id)sender -{ - NSString *Path = [self RemoveVolumeEntry]; - - if ( ! Path ) - return; - - if ( ! [[NSFileManager defaultManager] removeFileAtPath: Path - handler: self] ) - { - WarningSheet(@"Unable to delete volume", panel); - NSLog(@"%s unlink(%s) failed - %s", __PRETTY_FUNCTION__, - [Path cString], strerror(errno)); - } -} - -- (IBAction) EditDelay: (NSTextField *)sender -{ - int ticks = [delay intValue]; - float freq; - - if ( ticks ) - freq = 60.0 / ticks; - else - freq = 60.0; - - [frequency setFloatValue: freq]; - [emuFreq setFloatValue: freq]; - PrefsReplaceInt32("frameskip", ticks); - edited = YES; -} - -- (IBAction) EditBytes: (NSTextField *)sender -{ - int B = (int) [bytes floatValue]; - float M = B / 1024 / 1024; - - D(NSLog(@"%s = %f %d", __PRETTY_FUNCTION__, M, B)); - PrefsReplaceInt32("ramsize", B); - [MB setFloatValue: M]; - edited = YES; -} - -- (IBAction) EditEtherNetDevice: (NSTextField *)sender -{ - NSString *path = [etherNet stringValue]; - - PrefsReplaceString("ether", [path UTF8String]); - edited = YES; -} - -- (IBAction) EditExtFS: (NSTextField *)sender -{ - NSString *path = [extFS stringValue]; - - PrefsReplaceString("extfs", [path UTF8String]); - edited = YES; -} - -- (IBAction) EditFrequency: (NSTextField *)sender -{ - float freq = [frequency floatValue]; - - [delay setIntValue: frequencyToTickDelay(freq)]; - [emuFreq setFloatValue: freq]; - edited = YES; -} - -- (IBAction) EditModemDevice: (NSTextField *)sender -{ - NSString *path = [modem stringValue]; - - PrefsReplaceString("seriala", [path UTF8String]); - edited = YES; -} - -- (IBAction) EditMB: (NSTextField *)sender -{ - float M = [MB floatValue]; - int B = (int) (M * 1024 * 1024); - - D(NSLog(@"%s = %f %d", __PRETTY_FUNCTION__, M, B)); - PrefsReplaceInt32("ramsize", B); - [bytes setIntValue: B]; - edited = YES; -} - -- (IBAction) EditPrinterDevice: (NSTextField *)sender -{ - NSString *path = [printer stringValue]; - - PrefsReplaceString("serialb", [path UTF8String]); - edited = YES; -} - -- (IBAction) EditROMpath: (NSTextField *)sender -{ - NSString *path = [ROMfile stringValue]; - - PrefsReplaceString("rom", [path UTF8String]); -} - -- (IBAction) RemoveSCSI: (id)sender -{ - char pref[6]; - int row = [SCSIdisks selectedRow], - SCSIid = [SCSIds intAtRow: row]; - - if ( ! [SCSIds deleteRow: row] ) - NSLog (@"%s - [SCSIds deleteRow: %d] failed", __PRETTY_FUNCTION__, row); - [SCSIdisks reloadData]; - sprintf(pref, "scsi%d", SCSIid); - //PrefsRemoveItem(pref,0); - PrefsRemoveItem(pref, 1); -} - -- (NSString *) RemoveVolumeEntry -{ - int row = [diskImages selectedRow]; - - if ( row != -1 ) - { - NSString *Path = [volsDS pathAtRow: row]; - const char *path = [Path UTF8String], - *str; - int tmp = 0; - - NSString *prompt = [NSString stringWithFormat: @"%s\n%s", - "Are you sure you want to delete the file", - path]; - - if ( ! ChoiceAlert([prompt cString], "Delete", "Cancel") ) - return NULL; - - while ( (str = PrefsFindString("disk", tmp) ) != NULL ) - { - if ( strcmp(str, path) == 0 ) - { - PrefsRemoveItem("disk", tmp); - D(NSLog(@"%s - Deleted prefs entry \"disk\", %d", - __PRETTY_FUNCTION__, tmp)); - edited = YES; - break; - } - ++tmp; - } - - if ( str == NULL ) - { - NSLog(@"%s - Couldn't find any disk preference to match %s", - __PRETTY_FUNCTION__, path); - return NULL; - } - - if ( ! [volsDS deleteRow: row] ) - NSLog (@"%s - RemoveVolume %d failed", __PRETTY_FUNCTION__, tmp); - [diskImages reloadData]; -// return path; - return Path; - } - else - { - WarningSheet(@"Please select a volume first", panel); - return NULL; - } -} - -- (IBAction) RemoveVolume: (id)sender -{ - [self RemoveVolumeEntry]; -} - -- (void) loadPrefs: (int) argc - args: (char **) argv -{ - [panel close]; // Temporarily hide preferences panel - - PrefsExit(); // Purge all the old pref values - - PrefsInit(NULL, argc, argv); - AddPrefsDefaults(); - AddPlatformPrefsDefaults(); // and only create basic ones - - [SCSIds deleteAll]; // Clear out datasources for the tables - [volsDS deleteAll]; - - [self ShowPrefs: self]; // Reset items in panel, and redisplay - edited = NO; -} - -- (IBAction) LoadPrefs: (id)sender -{ - int argc = 2; - char *argv[2]; - - argv[0] = "--prefs", - argv[1] = (char *) [[prefsFile stringValue] UTF8String]; - - [self loadPrefs: argc - args: argv]; -} - -- (IBAction) ResetPrefs: (id)sender -{ - [self loadPrefs: 0 - args: NULL]; -} - -- (void) setStringOf: (NSTextField *) field - fromPref: (const char *) prefName -{ - const char *value = PrefsFindString(prefName, 0); - - if ( value ) - [field setStringValue: [NSString stringWithUTF8String: value] ]; -} - -- (IBAction) SavePrefs: (id)sender -{ - SavePrefs(); - edited = NO; -} - -- (IBAction) ShowPrefs: (id)sender -{ - NSTableColumn *locks; - const char *str; - int cpu, tmp, val; - - - // Set simple single field items - - val = PrefsFindInt32("frameskip"); - [delay setIntValue: val]; - if ( val ) - [frequency setFloatValue: 60.0 / val]; - else - [frequency setFloatValue: 60.0]; - - val = PrefsFindInt32("ramsize"); - [bytes setIntValue: val]; - [MB setFloatValue: val / (1024.0 * 1024.0)]; - - [disableCD setState: PrefsFindBool("nocdrom")]; - [disableSound setState: PrefsFindBool("nosound")]; - [FPU setState: PrefsFindBool("fpu") ]; - - [self setStringOf: etherNet fromPref: "ether" ]; - [self setStringOf: extFS fromPref: "extfs" ]; - [self setStringOf: modem fromPref: "seriala"]; - [self setStringOf: printer fromPref: "serialb"]; - [self setStringOf: ROMfile fromPref: "rom"]; - - [prefsFile setStringValue: [NSString stringWithUTF8String: UserPrefsPath.c_str()] ]; - - - parse_screen_prefs(PrefsFindString("screen")); - - [width setIntValue: init_width]; - [height setIntValue: init_height]; - [depth setIntValue: init_depth]; - - [screen setState: NO]; - switch ( display_type ) - { - case DISPLAY_WINDOW: [window setState: YES]; break; - case DISPLAY_SCREEN: [screen setState: YES]; break; - } - - [newVolumeSize setIntValue: 10]; - - // Radio button groups: - - val = PrefsFindInt32("bootdriver"); - [bootFromAny setState: val != CDROMRefNum]; - [bootFromCD setState: val == CDROMRefNum]; - - cpu = PrefsFindInt32("cpu"); - val = PrefsFindInt32("modelid"); - -#if REAL_ADDRESSING || DIRECT_ADDRESSING - puts("Current memory model does not support 24bit addressing"); - if ( val == [classic tag] ) - { - // Window already created by NIB file, just display - [panel makeKeyAndOrderFront:self]; - WarningSheet(@"Compiled-in memory model does not support 24bit", - @"Disabling Mac Classic emulation", nil, panel); - cpu = [CPU68030 tag]; - PrefsReplaceInt32("cpu", cpu); - val = [IIci tag]; - PrefsReplaceInt32("modelid", val); - } - - puts("Disabling 68000 & Mac Classic buttons"); - [CPU68000 setEnabled:FALSE]; - [classic setEnabled:FALSE]; -#endif - - [CPU68000 setState: [CPU68000 tag] == cpu]; - [CPU68020 setState: [CPU68020 tag] == cpu]; - [CPU68030 setState: [CPU68030 tag] == cpu]; - [CPU68040 setState: [CPU68040 tag] == cpu]; - - [classic setState: [classic tag] == val]; - [IIci setState: [IIci tag] == val]; - [quadra900 setState: [quadra900 tag] == val]; - - - // Lists of thingies: - - val = PrefsFindInt32("keyboardtype"); - tmp = [keyboard indexOfItemWithTag: val]; - if ( tmp != -1 ) - [keyboard selectItemAtIndex: tmp]; - for ( tmp = 0; tmp < [keyboard numberOfItems]; ++tmp ) - { - NSMenuItem *type = [keyboard itemAtIndex: tmp]; - [type setState: [type tag] == val]; - } - - - for ( tmp = 0; tmp < 7; ++tmp) - { - char pref[6]; - - pref[0] = '\0'; - - sprintf (pref, "scsi%d", tmp); - if ( (str = PrefsFindString(pref, 0) ) ) - [SCSIds addInt: tmp - withPath: [NSString stringWithCString: str] ]; - } - - [SCSIdisks setDataSource: SCSIds]; - - locks = [diskImages tableColumnWithIdentifier: @"locked"]; - if ( locks == nil ) - NSLog (@"%s - Can't find column for lock images", __PRETTY_FUNCTION__); - [locks setDataCell: lockCell]; - - tmp = 0; - while ( (str = PrefsFindString("disk", tmp++) ) != NULL ) - { - if ( *str == '*' ) - [volsDS addObject: (NSObject *) locked - withPath: [NSString stringWithUTF8String: str+1]]; - else - [volsDS addObject: (NSObject *) blank - withPath: [NSString stringWithUTF8String: str]]; - } - - [diskImages setDataSource: volsDS]; - - - [panel makeKeyAndOrderFront:self]; // Window already created by NIB file, just display -} - -@end diff --git a/BasiliskII/src/MacOSX/ToDo.html b/BasiliskII/src/MacOSX/ToDo.html deleted file mode 100644 index d4b4f66d..00000000 --- a/BasiliskII/src/MacOSX/ToDo.html +++ /dev/null @@ -1,61 +0,0 @@ - -Bugs: -
    -
  • In window mode, if the framerate is low (e.g. if you leave it at the - default of 10fps) or if the emulated screen is too large, - really fast mouse clicks are sometimes not picked up - by the Emulator. For now, click more slowly
  • -
  • In full screen mode after a restart, when the mouse is first moved, - the emulated pointer jumps to the location that it was before the restart. - Disturbing, but not damaging.
  • -
  • Ejecting a CD only works in 10.2 or higher, and it freezes the emulation - for about 5 seconds.
  • -
  • Status of 'dd' command is not always correct. (If it runs out of space, - an error about file not found is printed?)
  • -
  • The Snapshot function is currently broken in some situations - (if the emulation changes its own screen settings, and the program - is compiled with the default window drawing mode of CGIMAGEREF). - Setting the depth to millions (in the emulator) is a workaround for now
  • -
  • Cut and paste between emulator and OS X only half works
  • -
-Untested: -
    -
  • Mac Classic emulation. I don't have a ROM, but I suspect it will crash
  • -
  • Serial port code
  • -
-Unimplemented: -
    -
  • CD audio stuff. I am still trying to get this to work
  • -
  • CD insert detection. At the moment, if a CD isn't there when the - emulator boots, or if you change CDs, it will never know. I don't - know how to register with the OS for disk insertion and mount events. - (Gwenolé rewrote the CD code, and it should poll for new disks, - but it don't work for me. I must be doing something wrong!)
  • -
  • Floppy stuff. If a floppy is mounted by the OS X Finder, - it is busy and cannot be opened by the emulator
  • -
  • Interrupt function for emulator
  • -
  • 'nogui' to disable GUI alerts (and maybe preferences, but I need to split - MainMenu.nib to do that)
  • -
-Possible Enhancements: -
    -
  • Use NSFileManager's movePath:toPath:handler to rename all a file's forks - in extfs_macosx.mm
  • -
  • Emulator snapshot - save the current emulator state - (memory + registers) to a file for fast startup next time
  • -
  • Multiple emulators. The window stuff is mostly there, - but the uae_cpu code has lots of globals, and is not re-entrant
  • -
  • Real addressing mode for the emulator. Mike Sliczniak had done most of the - work, but with real addressing the emulator just crashes for me
  • -
  • Improve Objective-C object allocation. e.g. http://www.mulle-kybernetik.com/artikel/Optimisation/opti-5.html
  • -
  • Use automake instead of the current 1_prepare_files.sh ?
  • -
  • Add JIT options to preferences?
  • -
  • Use internal windows to display Help doco?
  • -
  • Provide feedback during external commands (e.g. ejecting a CD or - creating a disk volume)
  • -
  • Widescreen window layout (suggestion by Michael Franz), so that users - with widescreen displays can squeeze a bigger emulated screen in. - I have a mock up of this that can be pasted in (MainMenu.nib). - Ideally, this would be via a generalised "theme" facility, - but who has time for that :-)
  • -
diff --git a/BasiliskII/src/MacOSX/Versions.html b/BasiliskII/src/MacOSX/Versions.html deleted file mode 100644 index 9486ef74..00000000 --- a/BasiliskII/src/MacOSX/Versions.html +++ /dev/null @@ -1,120 +0,0 @@ - -Versions of MacOS X port of Basilisk II: -
    -
  1. Initial port to Public Beta, made minor changes to get it to compile under Final Release. -
    Gave a copy of this version to Gwenolé Beauchesne (one of the other porters)
  2. -
  3. Ported to version 0.9 of the Basilisk II tarball. -
    Re-engineered autoconfig files to give a clean autoconf and make of cpu_uae code. -
    Fixed a bug in the EmulatorView class (I was customising release instead of dealloc). -
    Added: -
      -
    • Transparency to icon
    • -
    • Port-specific doco: 0_HOW_TO_BUILD.txt, ToDo.html and Versions.html
    • -
    • Screen Snapshot code
    • -
    • Preferences saving and resetting
    • -
    • Delegate code, called when user attempts to close emulator window or quit application, - to check whether preferences need saving or application should be allowed to quit
    • -
    • ExtFS resource and type/creator access code
    • -
    • Window resizing stuff: -
        -
      1. The screensize can be set in the preferences. If the emulator has yet to - start then the window and emulator screen is resized. Otherwise, and
      2. -
      3. At any time, the window can be resized, which scales the emulator screen image
      4. -
      -
    • -
    - Gave a copy of this to Max Horn
  4. -
  5. Some code fixes suggested by Max, doco updates, and porting to OS 10.1
  6. -
  7. Event handling re-write inspired by Max (subclassing NSApplication for custom sendEvent:). - Command key and double clicks are now passed correctly to the Emulator. Took out the custom - "About" window stuff, and added some credits (with an html link to the official Basilisk home - page) in the standard About box. Also has the standard README in the help menu. -
    Gave a copy to Max
  8. -
  9. Streamlining of event sending (filter mouseMoved events when not in Emulator screen)
  10. -
  11. Recompile in Project Builder, because the makefile generated binary dies at startup
  12. -
  13. Ported to the Basilisk II 1.0 snapshot's source and implemented video resolution switching. - Also uses Objective-C++, which eliminates some of the wrapper code which was previously needed.
  14. -
  15. Video preferences fixes, small tidyup of source.
  16. -
  17. Full screen mode added, more source tidied up.
  18. - -
  19. Finally checked into CVS repository. Key event bug fixes: -
      -
    • Cursor keys are now decoded and passed to the Emulator correctly
    • -
    • New one (in version 9) reported by Kentaro Nakatani - - full screen mode was not passing key events
    • -
  20. -
  21. Repaired help menu item, added documentation folder.
  22. -
  23. Several monitor resolution-changing fixes. Windowed mode now supports all depths, - and is up to 6 times faster. I now no longer have any plans to do an OpenGL mode. -
    Minor change in preferences (RAM size fields no longer require - the user to press return or enter for the value to "take"). -
    Some modifications for compilation on 10.2 and 10.1 -
    Initial CD-ROM reading code.
  24. -
  25. Restarting the emulator should be safe and fairly reliable, - and errors in starting the emulator should now be caught. -
    Resizing of window is now animated, and window is centred afterwards. -
    Reduced memory leaks when changing screensize in windowed mode. -
    Screen default pref is now Mac II (and not Classic) size. -
    Fixed: -
      -
    • Bug where the Prefs could not be edited while the emulator was running
    • -
    • Help menu item (again) and added extra doco there
    • -
    • Preferences RAM size thing (again)
    • -
    • A minor Prefs editor button anomaly
    • -
  26. -
  27. Preferences file can now be specified on the command line, - and changed/loaded in the Preferences editor. - Added a feature from the windows port - now supports different keyboard types. - Changed: -
      -
    • Default extfs; was '/', now user's home directory (Suggestion by Olaf Pluta. - Seeing all the Unix dirs is a bit scary!)
    • -
    • HowTo now displayed by default web browser (as it contains links)
    • -
    • Project Builder defaults so that debug symbols are not included
    • -
  28. -
  29. Now built on 10.3 and Xcode. Also adds: -
      -
    • Xcode project files
    • -
    • Initial floppy and serial port locating code
    • -
    • Some help labels on the buttons - (some users didn't understand what the triangle button meant)
    • -
    • Signal handling for crash protection - (thanks to Mike Sliczniak's hard work)
    • -
    -
  30. -
  31. Now distributed as two applications; the usual one (which should be faster), - and one for emulating a Mac Classic (which may also help the 10.2/10.3 users - who are having problems with a black screen at startup). The difference is - that the "classic" version uses virtual or "banks" memory addressing. - Fixed: -
      -
    • Loading of ROM or disk images from directories or filenames which - contain non-ASCII characters
    • -
    • Floppy locating code. It can't actually access a floppy, but at - least it now won't add the cdrom multiple times
    • -
    -
  32. -
  33. Working ethernet, without extra drivers, thanks to Gwenolé. -
    Lots of bug fixes by Bernie Zenis. Some 10.4 fixes by Kirk Kerekes. -
    Some fixes by Marcus Gail ( 'Boot From: CD-ROM' vs - 'Disable CD-ROM Driver' clash). -
    Some cosmetic changes (widened RAM MB in prefs, added confirmation - when deleting volumes). -
    Now no need for "classic" version - - Gwenolé fixed the black screen problem
  34. -
  35. (actually 18a) Minor fixes: -
      -
    • Mouse should always woork in fullscreen mode, and
    • -
    • If snapshot fails, the dialog makes a workaround suggestion
    • -
    -
  36. -
  37. Updated the HowTo, external filesystem fix on 10.4, CD code rewrite. - Added some new features: -
      -
    • Sound support by Daniel Sumorok! Thanks also to Dave Vasilevsky, - who produced earlier versions of sound code that I didn't use.
    • -
    • Cut & Paste support from Gwenolé. You can now paste from the OS X - clipboard into the emulator (pasting the other way doesn't work - for me yet)
    • -
    -
diff --git a/BasiliskII/src/MacOSX/audio_defs_macosx.h b/BasiliskII/src/MacOSX/audio_defs_macosx.h deleted file mode 100644 index dc37fb42..00000000 --- a/BasiliskII/src/MacOSX/audio_defs_macosx.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * $Id$ - * - * audio_defs_macosx.h - Work around clashes with the enums in - * Based on: - * - * audio_defs.h - Definitions for MacOS audio components - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef AUDIO_DEFS_H -#define AUDIO_DEFS_H - -#include "macos_util_macosx.h" - -enum { // ComponentResource struct - componentType = 0, - componentSubType = 4, - componentManufacturer = 8, - componentFlags = 12, - componentFlagsMask = 16, - componentResType = 20, - componentResID = 24, - componentNameType = 26, - componentNameID = 30, - componentInfoType = 32, - componentInfoID = 36, - componentIconType = 38, - componentIconID = 42, - componentVersion = 44, - componentRegisterFlags = 48, - componentIconFamily = 52, - componentPFCount = 54, - componentPFFlags = 58, - componentPFResType = 62, - componentPFResID = 66, - componentPFPlatform = 68 -}; - - -enum { // ComponentParameters struct - cp_flags = 0, // call modifiers: sync/async, deferred, immed, etc - cp_paramSize = 1, // size in bytes of actual parameters passed to this call - cp_what = 2, // routine selector, negative for Component management calls - cp_params = 4 // actual parameters for the indicated routine -}; - -enum { // SoundComponentData struct - scd_flags = 0, - scd_format = 4, - scd_numChannels = 8, - scd_sampleSize = 10, - scd_sampleRate = 12, - scd_sampleCount = 16, - scd_buffer = 20, - scd_reserved = 24, - SIZEOF_scd = 28 -}; - -enum { // SoundInfoList struct - sil_count = 0, - sil_infoHandle = 2 -}; - -#endif diff --git a/BasiliskII/src/MacOSX/audio_macosx.cpp b/BasiliskII/src/MacOSX/audio_macosx.cpp deleted file mode 100644 index 840d2f13..00000000 --- a/BasiliskII/src/MacOSX/audio_macosx.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * audio_macosx.cpp - Audio support, implementation Mac OS X - * Copyright (C) 2006, Daniel Sumorok - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "audio.h" -#include "audio_defs.h" -#include "MacOSX_sound_if.h" - -#define DEBUG 0 -#include "debug.h" - - -// The currently selected audio parameters (indices in -// audio_sample_rates[] etc. vectors) -static int audio_sample_rate_index = 0; -static int audio_sample_size_index = 0; -static int audio_channel_count_index = 0; - -// Prototypes -static OSXsoundOutput *soundOutput = NULL; -static bool main_mute = false; -static bool speaker_mute = false; - -/* - * Initialization - */ -static int audioInt(void); - -static bool open_audio(void) -{ - AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index]; - AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index]; - AudioStatus.channels = audio_channel_counts[audio_channel_count_index]; - - if (soundOutput) - delete soundOutput; - - soundOutput = new OSXsoundOutput(); - soundOutput->start(AudioStatus.sample_size, AudioStatus.channels, - AudioStatus.sample_rate >> 16); - soundOutput->setCallback(audioInt); - audio_frames_per_block = soundOutput->bufferSizeFrames(); - - audio_open = true; - return true; -} - -void AudioInit(void) -{ - // Sound disabled in prefs? Then do nothing - if (PrefsFindBool("nosound")) - return; - - //audio_sample_sizes.push_back(8); - audio_sample_sizes.push_back(16); - - audio_channel_counts.push_back(1); - audio_channel_counts.push_back(2); - - audio_sample_rates.push_back(11025 << 16); - audio_sample_rates.push_back(22050 << 16); - audio_sample_rates.push_back(44100 << 16); - - // Default to highest supported values - audio_sample_rate_index = audio_sample_rates.size() - 1; - audio_sample_size_index = audio_sample_sizes.size() - 1; - audio_channel_count_index = audio_channel_counts.size() - 1; - - AudioStatus.mixer = 0; - AudioStatus.num_sources = 0; - audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut; - audio_component_flags = 0; - - open_audio(); -} - - -/* - * Deinitialization - */ - -static void close_audio(void) -{ - D(bug("Closing Audio\n")); - - if (soundOutput) - { - delete soundOutput; - soundOutput = NULL; - } - - audio_open = false; -} - -void AudioExit(void) -{ - // Close audio device - close_audio(); -} - - -/* - * First source added, start audio stream - */ - -void audio_enter_stream() -{ - // Streaming thread is always running to avoid clicking noises -} - - -/* - * Last source removed, stop audio stream - */ - -void audio_exit_stream() -{ - // Streaming thread is always running to avoid clicking noises -} - - -/* - * MacOS audio interrupt, read next data block - */ - -void AudioInterrupt(void) -{ - D(bug("AudioInterrupt\n")); - uint32 apple_stream_info; - uint32 numSamples; - int16 *p; - M68kRegisters r; - - if (!AudioStatus.mixer) - { - numSamples = 0; - soundOutput->sendAudioBuffer((void *)p, (int)numSamples); - D(bug("AudioInterrupt done\n")); - return; - } - - // Get data from apple mixer - r.a[0] = audio_data + adatStreamInfo; - r.a[1] = AudioStatus.mixer; - Execute68k(audio_data + adatGetSourceData, &r); - D(bug(" GetSourceData() returns %08lx\n", r.d[0])); - - apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo); - if (apple_stream_info && (main_mute == false) && (speaker_mute == false)) - { - numSamples = ReadMacInt32(apple_stream_info + scd_sampleCount); - p = (int16 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)); - } - else - { - numSamples = 0; - p = NULL; - } - - soundOutput->sendAudioBuffer((void *)p, (int)numSamples); - - D(bug("AudioInterrupt done\n")); -} - - -/* - * Set sampling parameters - * "index" is an index into the audio_sample_rates[] etc. vectors - * It is guaranteed that AudioStatus.num_sources == 0 - */ - -bool audio_set_sample_rate(int index) -{ - close_audio(); - audio_sample_rate_index = index; - return open_audio(); -} - -bool audio_set_sample_size(int index) -{ - close_audio(); - audio_sample_size_index = index; - return open_audio(); -} - -bool audio_set_channels(int index) -{ - close_audio(); - audio_channel_count_index = index; - return open_audio(); -} - -/* - * Get/set volume controls (volume values received/returned have the - * left channel volume in the upper 16 bits and the right channel - * volume in the lower 16 bits; both volumes are 8.8 fixed point - * values with 0x0100 meaning "maximum volume")) - */ -bool audio_get_main_mute(void) -{ - return main_mute; -} - -uint32 audio_get_main_volume(void) -{ - return 0x01000100; -} - -bool audio_get_speaker_mute(void) -{ - return speaker_mute; -} - -uint32 audio_get_speaker_volume(void) -{ - return 0x01000100; -} - -void audio_set_main_mute(bool mute) -{ - main_mute = mute; -} - -void audio_set_main_volume(uint32 vol) -{ -} - -void audio_set_speaker_mute(bool mute) -{ - speaker_mute = mute; -} - -void audio_set_speaker_volume(uint32 vol) -{ -} - -static int audioInt(void) -{ - SetInterruptFlag(INTFLAG_AUDIO); - TriggerInterrupt(); - return 0; -} diff --git a/BasiliskII/src/MacOSX/autorelease.h b/BasiliskII/src/MacOSX/autorelease.h deleted file mode 100644 index c89cb100..00000000 --- a/BasiliskII/src/MacOSX/autorelease.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * autorelease.h - a macro wrapping autorelease pools for use with Objective-C++ source files. - * - * Expands to @autoreleasepool on clang, uses a little hack to emulate @autoreleasepool on gcc. - * - * (C) 2012 Charles Srstka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -#ifndef __Autorelease_H__ -#define __Autorelease_H__ - -// just a little forward compatibility in case we ever support LLVM/clang -#if __clang__ -#define AUTORELEASE_POOL @autoreleasepool -#else -class Autorelease_Pool_Wrapper { -public: - Autorelease_Pool_Wrapper() { m_pool = [[NSAutoreleasePool alloc] init]; } - ~Autorelease_Pool_Wrapper() { [m_pool drain]; } - operator bool() const { return true; } -private: - NSAutoreleasePool *m_pool; -}; - -#define POOL_NAME(x, y) x##_##y -#define POOL_NAME2(x, y) POOL_NAME(x, y) -#define AUTORELEASE_POOL if(Autorelease_Pool_Wrapper POOL_NAME2(pool, __LINE__) = Autorelease_Pool_Wrapper()) -#endif // !__clang__ - -#endif // __Autorelease_H__ diff --git a/BasiliskII/src/MacOSX/clip_macosx.cpp b/BasiliskII/src/MacOSX/clip_macosx.cpp deleted file mode 100644 index 1d37edfc..00000000 --- a/BasiliskII/src/MacOSX/clip_macosx.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * clip_macosx.cpp - Clipboard handling, MacOS X (Carbon) implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#define _UINT64 -#include - -#include "clip.h" -#include "main.h" -#include "cpu_emulation.h" -#include "emul_op.h" - -#define DEBUG 0 -#include "debug.h" - - -// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the MacOS X side -static bool we_put_this_data = false; - - -static void SwapScrapData(uint32 type, void *data, int32 length, int from_host) { -#if BYTE_ORDER != BIG_ENDIAN - if (type == kScrapFlavorTypeTextStyle) { - uint16 *sdata = (uint16 *) data; - // the first short stores the number of runs - uint16 runs = sdata[0]; - sdata[0] = htons(sdata[0]); - if (from_host) - runs = sdata[0]; - sdata++; - // loop through each run - for (int i = 0; i < runs; i++) { - struct style_data { - uint32 offset; - uint16 line_height; - uint16 line_ascent; - uint16 font_family; - uint16 character_style; // not swapped - uint16 point_size; - uint16 red; - uint16 green; - uint16 blue; - } *style = (struct style_data *) (sdata + i*10); - style->offset = htonl(style->offset); - style->line_height = htons(style->line_height); - style->line_ascent = htons(style->line_ascent); - style->font_family = htons(style->font_family); - style->point_size = htons(style->point_size); - style->red = htons(style->red); - style->green = htons(style->green); - style->blue = htons(style->blue); - } - } else { - // add byteswapping code for other flavor types here ... - } -#endif -} - - -/* - * Initialization - */ - -void ClipInit(void) -{ -} - - -/* - * Deinitialization - */ - -void ClipExit(void) -{ -} - - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32 type, int32 offset) -{ -#if defined(__LP64__) - D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); - #warning Carbon scrapbook function are not implemented in 64-bit mode -#else - D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); - ScrapRef theScrap; - - if (GetCurrentScrap(&theScrap) != noErr) { - D(bug(" could not open scrap\n")); - return; - } - - Size byteCount; - if (GetScrapFlavorSize(theScrap, type, &byteCount) == noErr) { - - // Allocate space for new scrap in MacOS side - M68kRegisters r; - r.d[0] = byteCount; - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32 scrap_area = r.a[0]; - - // Get the native clipboard data - if (scrap_area) { - uint8 * const data = Mac2HostAddr(scrap_area); - if (GetScrapFlavorData(theScrap, type, &byteCount, data) == noErr) { - SwapScrapData(type, data, byteCount, FALSE); - // Add new data to clipboard - static uint8 proc[] = { - 0x59, 0x8f, // subq.l #4,sp - 0xa9, 0xfc, // ZeroScrap() - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #length,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #type,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #outbuf,-(sp) - 0xa9, 0xfe, // PutScrap() - 0x58, 0x8f, // addq.l #4,sp - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32 proc_area = r.a[0]; - - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - WriteMacInt32(proc_area + 6, byteCount); - WriteMacInt32(proc_area + 12, type); - WriteMacInt32(proc_area + 18, scrap_area); - we_put_this_data = true; - Execute68k(proc_area, &r); - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - } - - r.a[0] = scrap_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - } -#endif -} - -/* - * ZeroScrap() is called before a Mac application writes to the clipboard; clears out the previous contents - */ - -void ZeroScrap() -{ - D(bug("ZeroScrap\n")); - - we_put_this_data = false; -} - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32 type, void *scrap, int32 length) -{ -#if defined(__LP64__) - #warning Carbon scrapbook function are not implemented in 64-bit mode - D(bug("PutScrap type %4.4s, data %08lx, length %ld\n", &type, scrap, length)); -#else - static bool clear = true; - D(bug("PutScrap type %4.4s, data %08lx, length %ld\n", &type, scrap, length)); - ScrapRef theScrap; - - if (we_put_this_data) { - we_put_this_data = false; - clear = true; - return; - } - if (length <= 0) - return; - - if (clear) { - D(bug(" calling ClearCurrentScrap\n")); - ClearCurrentScrap(); - } - if (GetCurrentScrap(&theScrap) != noErr) { - D(bug(" could not open scrap\n")); - return; - } - - SwapScrapData(type, scrap, length, TRUE); - if (PutScrapFlavor(theScrap, type, kScrapFlavorMaskNone, length, scrap) != noErr) { - D(bug(" could not put to scrap\n")); - //return; - } - SwapScrapData(type, scrap, length, FALSE); // swap it back -#endif -} diff --git a/BasiliskII/src/MacOSX/clip_macosx64.mm b/BasiliskII/src/MacOSX/clip_macosx64.mm deleted file mode 100644 index 23261890..00000000 --- a/BasiliskII/src/MacOSX/clip_macosx64.mm +++ /dev/null @@ -1,1286 +0,0 @@ -/* - * clip_macosx64.mm - Clipboard handling, MacOS X (Pasteboard Manager) implementation - * - * (C) 2012 Jean-Pierre Stierlin - * (C) 2012 Alexei Svitkine - * (C) 2012 Charles Srstka - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#define _UINT64 -#import -#include - -#include "clip.h" -#include "main.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "autorelease.h" -#include "pict.h" - -#define DEBUG 0 -#include "debug.h" - -#ifndef FOURCC -#define FOURCC(a,b,c,d) (((uint32)(a) << 24) | ((uint32)(b) << 16) | ((uint32)(c) << 8) | (uint32)(d)) -#endif - -#define TYPE_PICT FOURCC('P','I','C','T') -#define TYPE_TEXT FOURCC('T','E','X','T') -#define TYPE_STYL FOURCC('s','t','y','l') -#define TYPE_UTXT FOURCC('u','t','x','t') -#define TYPE_UT16 FOURCC('u','t','1','6') -#define TYPE_USTL FOURCC('u','s','t','l') -#define TYPE_MOOV FOURCC('m','o','o','v') -#define TYPE_SND FOURCC('s','n','d',' ') -#define TYPE_ICNS FOURCC('i','c','n','s') - -static NSPasteboard *g_pboard; -static NSInteger g_pb_change_count = 0; - -// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the MacOS X side -static bool we_put_this_data = false; - -static bool should_clear = false; - -static NSMutableDictionary *g_macScrap; - -// flavor UTIs - -static NSString * const UTF16_TEXT_FLAVOR_NAME = @"public.utf16-plain-text"; -static NSString * const TEXT_FLAVOR_NAME = @"com.apple.traditional-mac-plain-text"; -static NSString * const STYL_FLAVOR_NAME = @"net.cebix.basilisk.styl-data"; - -// font face types - -enum { - FONT_FACE_PLAIN = 0, - FONT_FACE_BOLD = 1, - FONT_FACE_ITALIC = 2, - FONT_FACE_UNDERLINE = 4, - FONT_FACE_OUTLINE = 8, - FONT_FACE_SHADOW = 16, - FONT_FACE_CONDENSED = 32, - FONT_FACE_EXTENDED = 64 -}; - -// Script Manager constants - -#define smRoman 0 -#define smMacSysScript 18 -#define smMacRegionCode 40 - -static NSString *UTIForFlavor(uint32_t type) -{ - switch (type) { - case TYPE_MOOV: - return (NSString *)kUTTypeQuickTimeMovie; - case TYPE_SND: - return (NSString *)kUTTypeAudio; - case TYPE_ICNS: - return (NSString *)kUTTypeAppleICNS; - default: { - CFStringRef typeString = UTCreateStringForOSType(type); - NSString *uti = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, typeString, NULL); - - CFRelease(typeString); - - if (uti == nil || [uti hasPrefix:@"dyn."]) { - // The docs threaten that this may stop working at some unspecified point in the future. - // However, it seems to work on Lion and Mountain Lion, and there's no other way to do this - // that I can see. Most likely, whichever release eventually breaks this will probably also - // drop support for the 32-bit applications which typically use these 32-bit scrap types anyway, - // making it irrelevant. When this happens, we should include a version check for the version of - // OS X that dropped this support, and leave uti alone in that case. - - [uti release]; - uti = [[NSString alloc] initWithFormat:@"CorePasteboardFlavorType 0x%08x", type]; - } - - return [uti autorelease]; - } - } -} - -static uint32_t FlavorForUTI(NSString *uti) -{ - CFStringRef typeTag = UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassOSType); - - if (!typeTag) - return 0; - - uint32_t type = UTGetOSTypeFromString(typeTag); - - CFRelease(typeTag); - - return type; -} - -/* - * Get current system script encoding on Mac - */ - -static int GetMacScriptManagerVariable(uint16_t varID) -{ - int ret = -1; - M68kRegisters r; - static uint8_t proc[] = { - 0x59, 0x4f, // subq.w #4,sp - 0x3f, 0x3c, 0x00, 0x00, // move.w #varID,-(sp) - 0x2f, 0x3c, 0x84, 0x02, 0x00, 0x08, // move.l #-2080243704,-(sp) - 0xa8, 0xb5, // ScriptUtil() - 0x20, 0x1f, // move.l (a7)+,d0 - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - WriteMacInt16(proc_area + 4, varID); - Execute68k(proc_area, &r); - ret = r.d[0]; - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - return ret; -} - -static ScriptCode ScriptNumberForFontID(int16_t fontID) -{ - ScriptCode ret = -1; - M68kRegisters r; - static uint8_t proc[] = { - 0x55, 0x4f, // subq.w #2,sp - 0x3f, 0x3c, 0x00, 0x00, // move.w #fontID,-(sp) - 0x2f, 0x3c, 0x82, 0x02, 0x00, 0x06, // move.l #-2113798138,-(sp) - 0xa8, 0xb5, // ScriptUtil() - 0x30, 0x1f, // move.w (sp)+,d0 - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - WriteMacInt16(proc_area + 4, fontID); - Execute68k(proc_area, &r); - ret = r.d[0]; - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - return ret; -} - -/* - * Get Mac's default text encoding - */ - -static TextEncoding MacDefaultTextEncoding() -{ - int script = GetMacScriptManagerVariable(smMacSysScript); - int region = GetMacScriptManagerVariable(smMacRegionCode); - TextEncoding encoding; - - if (UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region, NULL, &encoding)) - encoding = kTextEncodingMacRoman; - - return encoding; -} - -static NSData *ConvertToMacTextEncoding(NSAttributedString *aStr, NSArray **styleAndScriptRuns) -{ - NSUInteger length = [aStr length]; - - NSMutableArray *styleRuns = [NSMutableArray array]; - - for (NSUInteger index = 0; index < length;) { - NSRange attrRange; - NSDictionary *attrs = [aStr attributesAtIndex:index effectiveRange:&attrRange]; - - [styleRuns addObject:[NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithUnsignedInteger:index], @"offset", - attrs, @"attributes", nil]]; - - index = NSMaxRange(attrRange); - } - - UnicodeToTextRunInfo info; - - OSStatus err = CreateUnicodeToTextRunInfoByScriptCode(0, NULL, &info); - - if (err != noErr) { - if (styleAndScriptRuns) - *styleAndScriptRuns = styleRuns; - - return [[aStr string] dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(MacDefaultTextEncoding())]; - } - - unichar chars[length]; - - [[aStr string] getCharacters:chars range:NSMakeRange(0, length)]; - - NSUInteger unicodeLength = length * sizeof(unichar); - NSUInteger bufLen = unicodeLength * 2; - uint8_t buf[bufLen]; - ByteCount bytesRead; - - ItemCount scriptRunCount = 1601; // max number of allowed style changes - ScriptCodeRun scriptRuns[scriptRunCount]; - - ItemCount inOffsetCount = [styleRuns count]; - ByteOffset inOffsets[inOffsetCount]; - - if (inOffsetCount) { - for (NSUInteger i = 0; i < inOffsetCount; i++) { - NSDictionary *eachRun = [styleRuns objectAtIndex:i]; - - inOffsets[i] = [[eachRun objectForKey:@"offset"] unsignedLongValue] * 2; - } - } - - ItemCount offsetCount; - ByteOffset offsets[inOffsetCount]; - - err = ConvertFromUnicodeToScriptCodeRun(info, unicodeLength, chars, - kUnicodeTextRunMask | kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask, - inOffsetCount, inOffsets, &offsetCount, offsets, - bufLen, &bytesRead, &bufLen, buf, - scriptRunCount, &scriptRunCount, scriptRuns); - - if (err != noErr) { - if (styleAndScriptRuns) - *styleAndScriptRuns = styleRuns; - - return [[aStr string] dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(MacDefaultTextEncoding())]; - } - - if (styleAndScriptRuns) { - NSMutableArray *runs = [NSMutableArray array]; - NSUInteger currentStyleRun = 0; - NSUInteger currentScriptRun = 0; - - for (NSUInteger currentOffset = 0; currentOffset < bufLen;) { - ScriptCodeRun scriptRun = scriptRuns[currentScriptRun]; - NSDictionary *attrs = [[styleRuns objectAtIndex:currentStyleRun] objectForKey:@"attributes"]; - - NSUInteger nextStyleOffset = (currentStyleRun < offsetCount - 1) ? offsets[currentStyleRun + 1] : bufLen; - NSUInteger nextScriptOffset = (currentScriptRun < scriptRunCount - 1) ? scriptRuns[currentScriptRun + 1].offset : bufLen; - - [runs addObject:[NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithUnsignedInteger:currentOffset], @"offset", - [NSNumber numberWithShort:scriptRun.script], @"script", - attrs, @"attributes", nil]]; - - if (nextStyleOffset == nextScriptOffset) { - currentStyleRun++; - currentScriptRun++; - currentOffset = nextStyleOffset; - } else if (nextStyleOffset < nextScriptOffset) { - currentStyleRun++; - currentOffset = nextStyleOffset; - } else { - currentScriptRun++; - currentOffset = nextScriptOffset; - } - } - - *styleAndScriptRuns = runs; - } - - return [NSData dataWithBytes:buf length:bufLen]; -} - -/* - * Count all Mac font IDs on the system - */ - -static NSUInteger CountMacFonts() -{ - M68kRegisters r; - static uint8_t proc[] = { - 0x55, 0x4f, // subq.w #2,sp - 0x2f, 0x3c, 'F', 'O', 'N', 'D', // move.l #'FOND',-(sp) - 0xa9, 0x9c, // CountResources() - 0x30, 0x1f, // move.w (sp)+,D0 - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - int16_t fontCount = 0; - - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - Execute68k(proc_area, &r); - - fontCount = r.d[0]; - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - - if (fontCount < 0) { - fontCount = 0; - } - - return fontCount; -} - -/* - * Get Mac font ID at index - */ - -static int16_t MacFontIDAtIndex(NSUInteger index) -{ - M68kRegisters r; - static uint8_t get_res_handle_proc[] = { - 0x42, 0x27, // clr.b -(sp) - 0xa9, 0x9b, // SetResLoad() - 0x59, 0x4f, // subq.w #4,sp - 0x2f, 0x3c, 'F', 'O', 'N', 'D', // move.l #'FOND',-(sp) - 0x3f, 0x3c, 0, 0, // move.w #index,-(sp) - 0xa9, 0x9d, // GetIndResource() - 0x26, 0x5f, // movea.l (sp)+,A3 - 0x1f, 0x3c, 0x00, 0x01, // move.b #1,-(sp) - 0xa9, 0x9b, // SetResLoad() - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(get_res_handle_proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - - uint32_t res_handle = 0; - int16_t fontID = 0; - - if (proc_area) { - Host2Mac_memcpy(proc_area, get_res_handle_proc, sizeof(get_res_handle_proc)); - WriteMacInt16(proc_area + 14, (uint16_t)(index + 1)); - - Execute68k(proc_area, &r); - - res_handle = r.a[3]; - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr() - } - - if (res_handle) { - static uint8_t get_info_proc[] = { - 0x2f, 0x0a, // move.l A2,-(sp) - 0x2f, 0x0b, // move.l A3,-(sp) - 0x42, 0xa7, // clr.l -(sp) - 0x42, 0xa7, // clr.l -(sp) - 0xa9, 0xa8, // GetResInfo() - 0x2f, 0x0a, // move.l A2,-(sp) - 0xa9, 0xa3, // ReleaseResource() - M68K_RTS >> 8, M68K_RTS & 0xff, - 0, 0 - }; - - r.d[0] = sizeof(get_info_proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - proc_area = r.a[0]; - - if (proc_area) { - Host2Mac_memcpy(proc_area, get_info_proc, sizeof(get_info_proc)); - r.a[2] = res_handle; - r.a[3] = proc_area + 16; - - Execute68k(proc_area, &r); - - fontID = ReadMacInt16(proc_area + 16); - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr() - } - } - - return fontID; -} - -/* - * List all font IDs on the system - */ - -static NSArray *ListMacFonts() -{ - NSUInteger fontCount = CountMacFonts(); - NSMutableArray *fontIDs = [NSMutableArray array]; - - for (NSUInteger i = 0; i < fontCount; i++) { - int16_t eachFontID = MacFontIDAtIndex(i); - - [fontIDs addObject:[NSNumber numberWithShort:eachFontID]]; - } - - return fontIDs; -} - -/* - * List all font IDs having a certain script - */ - -static NSArray *ListMacFontsForScript(ScriptCode script) -{ - NSMutableArray *fontIDs = [NSMutableArray array]; - - for (NSNumber *eachFontIDNum in ListMacFonts()) { - if (ScriptNumberForFontID([eachFontIDNum shortValue]) == script) - [fontIDs addObject:eachFontIDNum]; - } - - return fontIDs; -} - -/* - * Convert Mac font ID to font name - */ - -static NSString *FontNameFromFontID(int16_t fontID) -{ - M68kRegisters r; - r.d[0] = 256; // Str255: 255 characters + length byte - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t name_area = r.a[0]; - - if (!name_area) - return nil; - - uint8_t proc[] = { - 0x3f, 0x3c, 0, 0, // move.w #fontID,-(sp) - 0x2f, 0x0a, // move.l A2,-(sp) - 0xa8, 0xff, // GetFontName() - M68K_RTS >> 8, M68K_RTS & 0xff - }; - - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - WriteMacInt16(proc_area + 2, fontID); - r.a[2] = name_area; - Execute68k(proc_area, &r); - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - - uint8_t * const namePtr = Mac2HostAddr(name_area); - - NSString *name = (NSString *)CFStringCreateWithPascalString(kCFAllocatorDefault, namePtr, kCFStringEncodingMacRoman); - - r.a[0] = name_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - - return [name autorelease]; -} - -/* - * Convert font name to Mac font ID - */ - -static int16_t FontIDFromFontName(NSString *fontName) -{ - M68kRegisters r; - r.d[0] = 256; // Str255: 255 characters + length byte - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t name_area = r.a[0]; - - if (!name_area) - return 0; - - uint8_t * const namePtr = Mac2HostAddr(name_area); - - CFStringGetPascalString((CFStringRef)fontName, namePtr, 256, kCFStringEncodingMacRoman); - - uint8_t proc[] = { - 0x2f, 0x0a, // move.l A2,-(sp) - 0x2f, 0x0b, // move.l A3,-(sp) - 0xa9, 0x00, // GetFNum() - M68K_RTS >> 8, M68K_RTS & 0xff, - 0, 0 - }; - - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - int16_t fontID = 0; - - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - r.a[2] = name_area; - r.a[3] = proc_area + 8; - - Execute68k(proc_area, &r); - - fontID = ReadMacInt16(proc_area + 8); - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - - r.a[0] = name_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - - return fontID; -} - -/* - * Get font ID in desired script if possible; otherwise, try to get some font in the desired script. - */ - -static int16_t FontIDFromFontNameAndScript(NSString *fontName, ScriptCode script) -{ - int16_t fontID = FontIDFromFontName(fontName); - - if (ScriptNumberForFontID(fontID) == script) - return fontID; - - NSArray *fontIDs = ListMacFontsForScript(script); - - if ([fontIDs count] == 0) - return fontID; // no fonts are going to work; might as well return the original one - - if (fontName) { - // look for a localized version of our font; e.g. "Helvetica CE" if our font is Helvetica - for (NSNumber *eachFontIDNum in fontIDs) { - int16_t eachFontID = [eachFontIDNum shortValue]; - - if ([FontNameFromFontID(eachFontID) hasPrefix:fontName]) - return eachFontID; - } - } - - // Give up and just return a font that will work - return [[fontIDs objectAtIndex:0] shortValue]; -} - -/* - * Convert Mac TEXT/styl to attributed string - */ - -static NSAttributedString *AttributedStringFromMacTEXTAndStyl(NSData *textData, NSData *stylData) -{ - NSMutableAttributedString *aStr = [[[NSMutableAttributedString alloc] init] autorelease]; - - if (aStr == nil) - return nil; - - const uint8_t *bytes = (const uint8_t *)[stylData bytes]; - NSUInteger length = [stylData length]; - - if (length < 2) - return nil; - - uint16_t elements = CFSwapInt16BigToHost(*(uint16_t *)bytes); - const NSUInteger elementSize = 20; - - if (length < elements * elementSize) - return nil; - - NSUInteger cursor = 2; - - for (NSUInteger i = 0; i < elements; i++) AUTORELEASE_POOL { - int32_t startChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + cursor)); cursor += 4; - int16_t height __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - int16_t ascent __attribute__((unused)) = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - int16_t fontID = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - uint8_t face = bytes[cursor]; cursor += 2; - int16_t size = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - uint16_t red = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - uint16_t green = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - uint16_t blue = CFSwapInt16BigToHost(*(int16_t *)&bytes[cursor]); cursor += 2; - - int32_t nextChar; - - if (i + 1 == elements) - nextChar = [textData length]; - else - nextChar = CFSwapInt32BigToHost(*(int32_t *)(bytes + cursor)); - - NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init]; - NSColor *color = [NSColor colorWithDeviceRed:(CGFloat)red / 65535.0 green:(CGFloat)green / 65535.0 blue:(CGFloat)blue / 65535.0 alpha:1.0]; - NSFont *font; - TextEncoding encoding; - - if (fontID == 0) { // System font - CGFloat fontSize = (size == 0) ? [NSFont systemFontSize] : (CGFloat)size; - font = [NSFont systemFontOfSize:fontSize]; - } else if (fontID == 1) { // Application font - font = [NSFont userFontOfSize:(CGFloat)size]; - } else { - NSString *fontName = FontNameFromFontID(fontID); - font = [NSFont fontWithName:fontName size:(CGFloat)size]; - - if (font == nil) { - // Convert localized variants of fonts; e.g. "Helvetica CE" to "Helvetica" - - NSRange wsRange = [fontName rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet] options:NSBackwardsSearch]; - - if (wsRange.length) { - fontName = [fontName substringToIndex:wsRange.location]; - font = [NSFont fontWithName:fontName size:(CGFloat)size]; - } - } - } - - if (font == nil) - font = [NSFont userFontOfSize:(CGFloat)size]; - - if (UpgradeScriptInfoToTextEncoding(ScriptNumberForFontID(fontID), kTextLanguageDontCare, kTextRegionDontCare, NULL, &encoding)) - encoding = MacDefaultTextEncoding(); - - NSFontManager *fm = [NSFontManager sharedFontManager]; - - if (face & FONT_FACE_BOLD) - font = [fm convertFont:font toHaveTrait:NSBoldFontMask]; - - if (face & FONT_FACE_ITALIC) - font = [fm convertFont:font toHaveTrait:NSItalicFontMask]; - - if (face & FONT_FACE_CONDENSED) - font = [fm convertFont:font toHaveTrait:NSCondensedFontMask]; - - if (face & FONT_FACE_EXTENDED) - font = [fm convertFont:font toHaveTrait:NSExpandedFontMask]; - - [attrs setObject:font forKey:NSFontAttributeName]; - - if (face & FONT_FACE_UNDERLINE) - [attrs setObject:[NSNumber numberWithInteger:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName]; - - if (face & FONT_FACE_OUTLINE) { - [attrs setObject:color forKey:NSStrokeColorAttributeName]; - [attrs setObject:[NSNumber numberWithInteger:3] forKey:NSStrokeWidthAttributeName]; - } - - if (face & FONT_FACE_SHADOW) { - NSShadow *shadow = [[NSShadow alloc] init]; - NSColor *shadowColor = [NSColor colorWithDeviceRed:(CGFloat)red / 65535.0 green:(CGFloat)green / 65535.0 blue:(CGFloat)blue / 65535.0 alpha:0.5]; - - [shadow setShadowColor:shadowColor]; - [shadow setShadowOffset:NSMakeSize(2, -2.0)]; - - [attrs setObject:shadow forKey:NSShadowAttributeName]; - - [shadow release]; - } - - [attrs setObject:color forKey:NSForegroundColorAttributeName]; - - NSData *partialData = [textData subdataWithRange:NSMakeRange(startChar, nextChar - startChar)]; - NSString *partialString = [[NSString alloc] initWithData:partialData encoding:CFStringConvertEncodingToNSStringEncoding(encoding)]; - - if (partialString) { - NSAttributedString *partialAttribString = [[NSAttributedString alloc] initWithString:partialString attributes:attrs]; - - [aStr appendAttributedString:partialAttribString]; - - [partialAttribString release]; - } - - [partialString release]; - [attrs release]; - } - - return aStr; -} - -/* - * Append styl data for one text run - */ - -static void AppendStylRunData(NSMutableData *stylData, NSDictionary *attrs, ScriptCode script) -{ - NSFontManager *fontManager = [NSFontManager sharedFontManager]; - NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; - - NSFont *font = [attrs objectForKey:NSFontAttributeName]; - NSColor *color = [[attrs objectForKey:NSForegroundColorAttributeName] colorUsingColorSpaceName:NSDeviceRGBColorSpace device:nil]; - NSFontTraitMask traits = [fontManager traitsOfFont:font]; - NSNumber *underlineStyle = [attrs objectForKey:NSUnderlineStyleAttributeName]; - NSNumber *strokeWidth = [attrs objectForKey:NSStrokeWidthAttributeName]; - NSShadow *shadow = [attrs objectForKey:NSShadowAttributeName]; - - int16_t hostFontID = FontIDFromFontNameAndScript([font familyName], script); - - if (hostFontID == 0) { - hostFontID = [font isFixedPitch] ? 4 /* Monaco */ : 1 /* Application font */; - } - - int16_t height = CFSwapInt16HostToBig((int16_t)rint([layoutManager defaultLineHeightForFont:font])); - int16_t ascent = CFSwapInt16HostToBig((int16_t)rint([font ascender])); - int16_t fontID = CFSwapInt16HostToBig(hostFontID); - uint8_t face = 0; - int16_t size = CFSwapInt16HostToBig((int16_t)rint([font pointSize])); - uint16_t red = CFSwapInt16HostToBig((int16_t)rint([color redComponent] * 65535.0)); - uint16_t green = CFSwapInt16HostToBig((int16_t)rint([color greenComponent] * 65535.0)); - uint16_t blue = CFSwapInt16HostToBig((int16_t)rint([color blueComponent] * 65535.0)); - - if (traits & NSBoldFontMask) { - face |= FONT_FACE_BOLD; - } - - if (traits & NSItalicFontMask) { - face |= FONT_FACE_ITALIC; - } - - if (traits & NSCondensedFontMask) { - face |= FONT_FACE_CONDENSED; - } - - if (traits & NSExpandedFontMask) { - face |= FONT_FACE_EXTENDED; - } - - if (underlineStyle && [underlineStyle integerValue] != NSUnderlineStyleNone) { - face |= FONT_FACE_UNDERLINE; - } - - if (strokeWidth && [strokeWidth doubleValue] > 0.0) { - face |= FONT_FACE_OUTLINE; - } - - if (shadow) { - face |= FONT_FACE_SHADOW; - } - - [stylData appendBytes:&height length:2]; - [stylData appendBytes:&ascent length:2]; - [stylData appendBytes:&fontID length:2]; - [stylData appendBytes:&face length:1]; - [stylData increaseLengthBy:1]; - [stylData appendBytes:&size length:2]; - [stylData appendBytes:&red length:2]; - [stylData appendBytes:&green length:2]; - [stylData appendBytes:&blue length:2]; - - [layoutManager release]; -} - -/* - * Convert attributed string to TEXT/styl - */ - -static NSData *ConvertToMacTEXTAndStyl(NSAttributedString *aStr, NSData **outStylData) -{ - // Limitations imposed by the Mac TextEdit system. - const NSUInteger charLimit = 32 * 1024; - const NSUInteger elementLimit = 1601; - - NSUInteger length = [aStr length]; - - if (length > charLimit) { - aStr = [aStr attributedSubstringFromRange:NSMakeRange(0, charLimit)]; - } - - NSArray *runs = nil; - - NSData *textData = ConvertToMacTextEncoding(aStr, &runs); - - NSMutableData *stylData = [NSMutableData dataWithLength:2]; // number of styles to be filled in at the end - - NSUInteger elements = 0; - - for (NSDictionary *eachRun in runs) { - if (elements >= elementLimit) - break; - - NSUInteger offset = [[eachRun objectForKey:@"offset"] unsignedIntegerValue]; - ScriptCode script = [[eachRun objectForKey:@"script"] shortValue]; - NSDictionary *attrs = [eachRun objectForKey:@"attributes"]; - - int32_t startChar = CFSwapInt32HostToBig((int32_t)offset); - [stylData appendBytes:&startChar length:4]; - - AppendStylRunData(stylData, attrs, script); - - elements++; - } - - uint16_t bigEndianElements = CFSwapInt16HostToBig((uint16_t)elements); - - [stylData replaceBytesInRange:NSMakeRange(0, 2) withBytes:&bigEndianElements length:2]; - - if (outStylData) - *outStylData = stylData; - - return textData; -} - -/* - * Get data of a particular flavor from the pasteboard - */ - -static NSData *DataFromPasteboard(NSPasteboard *pboard, NSString *flavor) -{ - return [pboard dataForType:flavor]; -} - -/* - * Convert Mac TEXT/styl to RTF - */ - -static void WriteMacTEXTAndStylToPasteboard(NSPasteboard *pboard, NSData *textData, NSData *stylData) -{ - NSMutableAttributedString *aStr = [AttributedStringFromMacTEXTAndStyl(textData, stylData) mutableCopy]; - - if (!aStr) { - NSString *string = [[NSString alloc] initWithData:textData encoding:CFStringConvertEncodingToNSStringEncoding(MacDefaultTextEncoding())]; - - if (!string) - return; - - aStr = [[NSMutableAttributedString alloc] initWithString:string attributes:nil]; - - [string release]; - } - - // fix line endings - [[aStr mutableString] replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [aStr length])]; - - [pboard writeObjects:[NSArray arrayWithObject:aStr]]; - - [aStr release]; -} - -/* - * Convert RTF to Mac TEXT/styl - */ - -static NSData *MacTEXTAndStylDataFromPasteboard(NSPasteboard *pboard, NSData **outStylData) -{ - NSMutableAttributedString *aStr; - - NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSAttributedString class]] options:nil]; - - if ([objs count]) { - aStr = [[objs objectAtIndex:0] mutableCopy]; - } else { - objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSString class]] options:nil]; - - if (![objs count]) - return nil; - - aStr = [[NSMutableAttributedString alloc] initWithString:[objs objectAtIndex:0]]; - } - - // fix line endings - [[aStr mutableString] replaceOccurrencesOfString:@"\n" withString:@"\r" options:NSLiteralSearch range:NSMakeRange(0, [[aStr mutableString] length])]; - - NSData *stylData = nil; - NSData *textData = ConvertToMacTEXTAndStyl(aStr, &stylData); - - [aStr release]; - - if (outStylData) - *outStylData = stylData; - - return textData; -} - -/* - * Initialization - */ - -void ClipInit(void) -{ - g_pboard = [[NSPasteboard generalPasteboard] retain]; - if (!g_pboard) { - D(bug("could not create Pasteboard\n")); - } - - g_macScrap = [[NSMutableDictionary alloc] init]; -} - - -/* - * Deinitialization - */ - -void ClipExit(void) -{ - [g_pboard release]; - g_pboard = nil; - - [g_macScrap release]; - g_macScrap = nil; -} - -/* - * Convert an NSImage to PICT format. - */ - -static NSData *ConvertImageToPICT(NSImage *image) { - if ([[image representations] count] == 0) { - return nil; - } - - NSImageRep *rep = [[image representations] objectAtIndex:0]; - NSUInteger width; - NSUInteger height; - - if ([rep isKindOfClass:[NSBitmapImageRep class]]) { - width = [rep pixelsWide]; - height = [rep pixelsHigh]; - } else { - width = lrint([image size].width); - height = lrint([image size].height); - } - - // create a new bitmap image rep in our desired format, following the advice here: - // https://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html#X10_6Notes - - NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bytesPerRow:width * 4 - bitsPerPixel:32]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:bitmap]]; - [rep draw]; - [NSGraphicsContext restoreGraphicsState]; - - unsigned char *rgba = [bitmap bitmapData]; - - long bufSize = ConvertRGBAToPICT(NULL, 0, rgba, width, height); - - NSData *pictData = nil; - - if (bufSize > 0) { - uint8_t *buf = (uint8_t *)malloc(bufSize); - - long pictSize = ConvertRGBAToPICT(buf, bufSize, rgba, width, height); - - if (pictSize > 0) - pictData = [NSData dataWithBytes:buf length:pictSize]; - - free(buf); - } - - [bitmap release]; - - return pictData; -} - -/* - * Convert any images that may be on the clipboard to PICT format if possible. - */ - -static NSData *MacPICTDataFromPasteboard(NSPasteboard *pboard) -{ - // check if there's any PICT data on the pasteboard - NSData *pictData = DataFromPasteboard(pboard, (NSString *)kUTTypePICT); - - if (pictData) - return pictData; - - // now check to see if any images on the pasteboard have PICT representations - NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSImage class]] options:nil]; - - for (NSImage *eachImage in objs) { - for (NSImageRep *eachRep in [eachImage representations]) { - - if ([eachRep isKindOfClass:[NSPICTImageRep class]]) - return [(NSPICTImageRep *)eachRep PICTRepresentation]; - } - } - - // Give up and perform the conversion ourselves - if ([objs count]) - return ConvertImageToPICT([objs objectAtIndex:0]); - - // If none of that worked, sorry, we're out of options - return nil; -} - -/* - * Zero Mac clipboard - */ - -static void ZeroMacClipboard() -{ - D(bug("Zeroing Mac clipboard\n")); - M68kRegisters r; - static uint8_t proc[] = { - 0x59, 0x8f, // subq.l #4,sp - 0xa9, 0xfc, // ZeroScrap() - 0x58, 0x8f, // addq.l #4,sp - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - Execute68k(proc_area, &r); - - [g_macScrap removeAllObjects]; - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } -} - -/* - * Write data to Mac clipboard - */ - -static void WriteDataToMacClipboard(NSData *pbData, uint32_t type) -{ - D(bug("Writing data %s to Mac clipboard with type '%c%c%c%c'\n", [[pbData description] UTF8String], - (type >> 24) & 0xff, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff)); - - if ([pbData length] == 0) - return; - - NSNumber *typeNum = [NSNumber numberWithInteger:type]; - - if ([g_macScrap objectForKey:typeNum]) { - // the classic Mac OS can't have more than one object of the same type on the clipboard - return; - } - - // Allocate space for new scrap in MacOS side - M68kRegisters r; - r.d[0] = [pbData length]; - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t scrap_area = r.a[0]; - - // Get the native clipboard data - if (scrap_area) { - uint8_t * const data = Mac2HostAddr(scrap_area); - - memcpy(data, [pbData bytes], [pbData length]); - - // Add new data to clipboard - static uint8_t proc[] = { - 0x59, 0x8f, // subq.l #4,sp - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #length,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #type,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #outbuf,-(sp) - 0xa9, 0xfe, // PutScrap() - 0x58, 0x8f, // addq.l #4,sp - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32_t proc_area = r.a[0]; - - if (proc_area) { - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - WriteMacInt32(proc_area + 4, [pbData length]); - WriteMacInt32(proc_area + 10, type); - WriteMacInt32(proc_area + 16, scrap_area); - we_put_this_data = true; - Execute68k(proc_area, &r); - - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - - [g_macScrap setObject:pbData forKey:typeNum]; - } - - r.a[0] = scrap_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } -} - -/* - * Take all the data on host pasteboard and convert it to something the Mac understands if possible - */ - -static void ConvertHostPasteboardToMacScrap() -{ - D(bug("ConvertHostPasteboardToMacScrap\n")); - - ZeroMacClipboard(); - - NSData *stylData = nil; - NSData *textData = MacTEXTAndStylDataFromPasteboard(g_pboard, &stylData); - - if (textData) { - if (stylData) - WriteDataToMacClipboard(stylData, TYPE_STYL); - - WriteDataToMacClipboard(textData, TYPE_TEXT); - } - - NSData *pictData = MacPICTDataFromPasteboard(g_pboard); - - if (pictData) - WriteDataToMacClipboard(pictData, TYPE_PICT); - - for (NSString *eachType in [g_pboard types]) { - if (UTTypeConformsTo((CFStringRef)eachType, kUTTypeText)) { - // text types are already handled - continue; - } - - if (UTTypeConformsTo((CFStringRef)eachType, kUTTypeImage)) { - // image types are already handled - continue; - } - - uint32_t type = FlavorForUTI(eachType); - - // skip styl and ustl as well; those fall under text, which is handled already - if (!type || type == TYPE_STYL || type == TYPE_USTL) - continue; - - WriteDataToMacClipboard(DataFromPasteboard(g_pboard, eachType), type); - } -} - -/* - * Take all the data on the Mac clipbord and convert it to something the host pasteboard understands if possible - */ - -static void ConvertMacScrapToHostPasteboard() -{ - D(bug("ConvertMacScrapToHostPasteboard\n")); - - BOOL wroteText = NO; - - [g_pboard clearContents]; - - for (NSNumber *eachTypeNum in g_macScrap) AUTORELEASE_POOL { - uint32_t eachType = [eachTypeNum integerValue]; - - if (eachType == TYPE_TEXT || eachType == TYPE_STYL || eachType == TYPE_UTXT || eachType == TYPE_UT16 || eachType == TYPE_USTL) { - if (wroteText) - continue; - - NSData *textData; - NSData *stylData; - - textData = [g_macScrap objectForKey:[NSNumber numberWithInteger:TYPE_TEXT]]; - stylData = [g_macScrap objectForKey:[NSNumber numberWithInteger:TYPE_STYL]]; - - if (textData) { - WriteMacTEXTAndStylToPasteboard(g_pboard, textData, stylData); - wroteText = YES; - } - - // sometime, it might be interesting to write a converter for utxt/ustl if possible - - continue; - } - - NSData *pbData = [g_macScrap objectForKey:eachTypeNum]; - - if (pbData) { - NSString *typeStr = UTIForFlavor(eachType); - - if (!typeStr) - continue; - - [g_pboard setData:pbData forType:typeStr]; - } - } -} - -/* - * Check whether the pasteboard has changed since our last check; if it has, write it to the emulated pasteboard - */ - -static void ConvertHostPasteboardToMacScrapIfChanged() -{ - if (!g_pboard) - return; - - if ([g_pboard changeCount] > g_pb_change_count) { - ConvertHostPasteboardToMacScrap(); - g_pb_change_count = [g_pboard changeCount]; - } -} - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32_t type, int32_t offset) -{ - D(bug("GetScrap handle %p, type %4.4s, offset %d\n", handle, (char *)&type, offset)); - - AUTORELEASE_POOL { - ConvertHostPasteboardToMacScrapIfChanged(); - } -} - -/* - * ZeroScrap() is called before a Mac application writes to the clipboard; clears out the previous contents - */ - -void ZeroScrap() -{ - D(bug("ZeroScrap\n")); - - we_put_this_data = false; - - // Defer clearing the host pasteboard until the Mac tries to put something on it. - // This prevents us from clearing the pasteboard when ZeroScrap() is called during startup. - should_clear = true; -} - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32_t type, void *scrap, int32_t length) -{ - D(bug("PutScrap type %4.4s, data %p, length %ld\n", (char *)&type, scrap, (long)length)); - - AUTORELEASE_POOL { - if (!g_pboard) - return; - - if (we_put_this_data) { - we_put_this_data = false; - return; - } - - if (length <= 0) - return; - - if (should_clear) { - [g_macScrap removeAllObjects]; - should_clear = false; - } - - NSData *pbData = [NSData dataWithBytes:scrap length:length]; - if (!pbData) - return; - - [g_macScrap setObject:pbData forKey:[NSNumber numberWithInteger:type]]; - - ConvertMacScrapToHostPasteboard(); - - // So that our PutScrap() patch won't bounce the data we just wrote back to the Mac clipboard - g_pb_change_count = [g_pboard changeCount]; - } -} diff --git a/BasiliskII/src/MacOSX/extfs_macosx.cpp b/BasiliskII/src/MacOSX/extfs_macosx.cpp deleted file mode 100644 index 41b35a18..00000000 --- a/BasiliskII/src/MacOSX/extfs_macosx.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/* - * extfs_macosx.cpp - MacOS file system for access native file system access, MacOS X specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "prefs.h" -#include "extfs.h" -#include "extfs_defs.h" - -// XXX: don't clobber with native definitions -#define noErr native_noErr -#define Point native_Point -#define Rect native_Rect -#define ProcPtr native_ProcPtr -# include -#undef ProcPtr -#undef Rect -#undef Point -#undef noErr - -#define DEBUG 0 -#include "debug.h" - - -// Default Finder flags -const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited; - - -/* - * Extended attributes (Tiger+) - */ - -#define USE_XATTRS g_use_xattrs -static bool g_use_xattrs = false; - -#define XATTR_TEST "org.BasiliskII.TestAttr" -#define XATTR_FINFO "org.BasiliskII.FinderInfo" -#define XATTR_FXINFO "org.BasiliskII.ExtendedFinderInfo" - -static bool get_xattr(const char *path, const char *name, void *value, uint32 size) -{ - return syscall(SYS_getxattr, path, name, value, size, 0, 0) == size; -} - -static bool set_xattr(const char *path, const char *name, const void *value, uint32 size) -{ - return syscall(SYS_setxattr, path, name, value, size, 0, 0) == 0; -} - -static bool remove_xattr(const char *path, const char *name) -{ - return syscall(SYS_removexattr, path, name, 0) == 0; -} - -static bool check_xattr(void) -{ - const char *path = PrefsFindString("extfs"); - if (path == NULL) - return false; - const uint32 sentinel = 0xdeadbeef; - if (!set_xattr(path, XATTR_TEST, &sentinel, sizeof(sentinel))) - return false; - uint32 v; - if (!get_xattr(path, XATTR_TEST, &v, sizeof(v))) - return false; - if (!remove_xattr(path, XATTR_TEST)) - return false; - return v == sentinel; -} - - -/* - * Initialization - */ - -void extfs_init(void) -{ - g_use_xattrs = check_xattr(); -} - - -/* - * Deinitialization - */ - -void extfs_exit(void) -{ -} - - -/* - * Add component to path name - */ - -void add_path_component(char *path, const char *component) -{ - int l = strlen(path); - if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') { - path[l] = '/'; - path[l+1] = 0; - } - strncat(path, component, MAX_PATH_LENGTH-1); -} - - -/* - * Finder info manipulation helpers - */ - -typedef uint8 FinderInfo[SIZEOF_FInfo]; - -struct FinderInfoAttrBuf { - uint32 length; - FinderInfo finderInfo; - FinderInfo extendedFinderInfo; -}; - -static const FinderInfo kNativeFInfoMask = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00}; -static const FinderInfo kNativeFXInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00}; -static const FinderInfo kNativeDInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00}; -static const FinderInfo kNativeDXInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00}; /* XXX: keep frScroll? */ - -static void finfo_merge(FinderInfo dst, const FinderInfo emu, const FinderInfo nat, const FinderInfo mask) -{ - for (int i = 0; i < SIZEOF_FInfo; i++) - dst[i] = (emu[i] & ~mask[i]) | (nat[i] & mask[i]); -} - -static void finfo_split(FinderInfo dst, const FinderInfo emu, const FinderInfo mask) -{ - for (int i = 0; i < SIZEOF_FInfo; i++) - dst[i] = emu[i] & mask[i]; -} - - -/* - * Finder info are kept in helper files (on anything below Tiger) - * - * Finder info: - * /path/.finf/file - * - * The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo - * (16+16 bytes) - */ - -static void make_finf_path(const char *src, char *dest, bool only_dir = false) -{ - dest[0] = 0; - - // Get pointer to last component of path - const char *last_part = strrchr(src, '/'); - if (last_part) - last_part++; - else - last_part = src; - - // Copy everything before - strncpy(dest, src, last_part-src); - dest[last_part-src] = 0; - - // Add additional component - strncat(dest, ".finf/", MAX_PATH_LENGTH-1); - - // Add last component - if (!only_dir) - strncat(dest, last_part, MAX_PATH_LENGTH-1); -} - -static int create_finf_dir(const char *path) -{ - char finf_dir[MAX_PATH_LENGTH]; - make_finf_path(path, finf_dir, true); - if (finf_dir[strlen(finf_dir) - 1] == '/') // Remove trailing "/" - finf_dir[strlen(finf_dir) - 1] = 0; - return mkdir(finf_dir, 0777); -} - -static int open_finf(const char *path, int flag) -{ - char finf_path[MAX_PATH_LENGTH]; - make_finf_path(path, finf_path); - - if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY) - flag |= O_CREAT; - int fd = open(finf_path, flag, 0666); - if (fd < 0) { - if (errno == ENOENT && (flag & O_CREAT)) { - // One path component was missing, probably the finf - // directory. Try to create it and re-open the file. - int ret = create_finf_dir(path); - if (ret < 0) - return ret; - fd = open(finf_path, flag, 0666); - } - } - return fd; -} - - -/* - * Resource forks are kept into their native location - * - * Resource fork: - * /path/file/..namedfork/rsrc - */ - -static void make_rsrc_path(const char *src, char *dest) -{ - int l = strlen(src); - if (l + 1 + 16 + 1 <= MAX_PATH_LENGTH) - memcpy(dest, src, l + 1); - else { - // The rsrc component is copied as is, if there is not enough - // space to add it. In that case, open() will fail gracefully - // and this is what we want. - dest[0] = '.'; - dest[1] = '\0'; - } - - add_path_component(dest, "..namedfork/rsrc"); -} - -static int open_rsrc(const char *path, int flag) -{ - char rsrc_path[MAX_PATH_LENGTH]; - make_rsrc_path(path, rsrc_path); - - return open(rsrc_path, flag); -} - - -/* - * Get/set finder info for file/directory specified by full path - */ - -struct ext2type { - const char *ext; - uint32 type; - uint32 creator; -}; - -static const ext2type e2t_translation[] = { - {".Z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')}, - {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')}, - {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')}, - {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')}, - {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')}, - {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')}, - {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')}, - {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')}, - {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')}, - {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')}, - {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')}, - {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')}, - {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')}, - {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')}, - {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')}, - {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')}, - {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')}, - {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')}, - {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')}, - {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')}, - {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')}, - {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')}, - {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')}, - {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')}, - {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')}, - {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')}, - {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')}, - {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')}, - {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')}, - {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')}, - {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')}, - {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')}, - {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".C", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".S", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')}, - {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')}, - {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')}, - {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')}, - {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')}, - {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')}, - {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')}, - {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')}, - {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')}, - {NULL, 0, 0} // End marker -}; - -// Get emulated Finder info from metadata (Tiger+) -static bool get_finfo_from_xattr(const char *path, uint8 *finfo, uint8 *fxinfo) -{ - if (!get_xattr(path, XATTR_FINFO, finfo, SIZEOF_FInfo)) - return false; - if (fxinfo && !get_xattr(path, XATTR_FXINFO, fxinfo, SIZEOF_FXInfo)) - return false; - return true; -} - -// Get emulated Finder info from helper file -static bool get_finfo_from_helper(const char *path, uint8 *finfo, uint8 *fxinfo) -{ - int fd = open_finf(path, O_RDONLY); - if (fd < 0) - return false; - - ssize_t actual = read(fd, finfo, SIZEOF_FInfo); - if (fxinfo) - actual += read(fd, fxinfo, SIZEOF_FXInfo); - close(fd); - return actual == (SIZEOF_FInfo + (fxinfo ? SIZEOF_FXInfo : 0)); -} - -// Get native Finder info -static bool get_finfo_from_native(const char *path, uint8 *finfo, uint8 *fxinfo) -{ - struct attrlist attrList; - memset(&attrList, 0, sizeof(attrList)); - attrList.bitmapcount = ATTR_BIT_MAP_COUNT; - attrList.commonattr = ATTR_CMN_FNDRINFO; - - FinderInfoAttrBuf attrBuf; - if (getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0) < 0) - return false; - - memcpy(finfo, attrBuf.finderInfo, SIZEOF_FInfo); - if (fxinfo) - memcpy(fxinfo, attrBuf.extendedFinderInfo, SIZEOF_FXInfo); - return true; -} - -static bool do_get_finfo(const char *path, bool has_fxinfo, - FinderInfo emu_finfo, FinderInfo emu_fxinfo, - FinderInfo nat_finfo, FinderInfo nat_fxinfo) -{ - memset(emu_finfo, 0, SIZEOF_FInfo); - if (has_fxinfo) - memset(emu_fxinfo, 0, SIZEOF_FXInfo); - *((uint16 *)(emu_finfo + fdFlags)) = htonl(DEFAULT_FINDER_FLAGS); - *((uint32 *)(emu_finfo + fdLocation)) = htonl((uint32)-1); - - if (USE_XATTRS) - get_finfo_from_xattr(path, emu_finfo, has_fxinfo ? emu_fxinfo : NULL); - else - get_finfo_from_helper(path, emu_finfo, has_fxinfo ? emu_fxinfo : NULL); - - if (!get_finfo_from_native(path, nat_finfo, has_fxinfo ? nat_fxinfo : NULL)) - return false; - return true; -} - -void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Set default finder info - Mac_memset(finfo, 0, SIZEOF_FInfo); - if (fxinfo) - Mac_memset(fxinfo, 0, SIZEOF_FXInfo); - WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS); - WriteMacInt32(finfo + fdLocation, (uint32)-1); - - // Merge emulated and native Finder info - FinderInfo emu_finfo, emu_fxinfo; - FinderInfo nat_finfo, nat_fxinfo; - if (do_get_finfo(path, fxinfo, emu_finfo, emu_fxinfo, nat_finfo, nat_fxinfo)) { - if (!is_dir) { - finfo_merge(Mac2HostAddr(finfo), emu_finfo, nat_finfo, kNativeFInfoMask); - if (fxinfo) - finfo_merge(Mac2HostAddr(fxinfo), emu_fxinfo, nat_fxinfo, kNativeFXInfoMask); - if (ReadMacInt32(finfo + fdType) != 0 && ReadMacInt32(finfo + fdCreator) != 0) - return; - } - else { - finfo_merge(Mac2HostAddr(finfo), emu_finfo, nat_finfo, kNativeDInfoMask); - if (fxinfo) - finfo_merge(Mac2HostAddr(fxinfo), emu_fxinfo, nat_fxinfo, kNativeDXInfoMask); - return; - } - } - - // No native Finder info, translate file name extension to MacOS type/creator - if (!is_dir) { - int path_len = strlen(path); - for (int i=0; e2t_translation[i].ext; i++) { - int ext_len = strlen(e2t_translation[i].ext); - if (path_len < ext_len) - continue; - if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) { - WriteMacInt32(finfo + fdType, e2t_translation[i].type); - WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator); - break; - } - } - } -} - -// Set emulated Finder info into metada (Tiger+) -static bool set_finfo_to_xattr(const char *path, const uint8 *finfo, const uint8 *fxinfo) -{ - if (!set_xattr(path, XATTR_FINFO, finfo, SIZEOF_FInfo)) - return false; - if (fxinfo && !set_xattr(path, XATTR_FXINFO, fxinfo, SIZEOF_FXInfo)) - return false; - return true; -} - -// Set emulated Finder info into helper file -static bool set_finfo_to_helper(const char *path, const uint8 *finfo, const uint8 *fxinfo) -{ - int fd = open_finf(path, O_RDWR); - if (fd < 0) - return false; - - ssize_t actual = write(fd, finfo, SIZEOF_FInfo); - if (fxinfo) - actual += write(fd, fxinfo, SIZEOF_FXInfo); - close(fd); - return actual == (SIZEOF_FInfo + (fxinfo ? SIZEOF_FXInfo : 0)); -} - -// Set native Finder info -static bool set_finfo_to_native(const char *path, const uint8 *finfo, const uint8 *fxinfo, bool is_dir) -{ - struct attrlist attrList; - memset(&attrList, 0, sizeof(attrList)); - attrList.bitmapcount = ATTR_BIT_MAP_COUNT; - attrList.commonattr = ATTR_CMN_FNDRINFO; - - FinderInfoAttrBuf attrBuf; - if (getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0) < 0) - return false; - - finfo_merge(attrBuf.finderInfo, attrBuf.finderInfo, finfo, is_dir ? kNativeDInfoMask : kNativeFInfoMask); - if (fxinfo) - finfo_merge(attrBuf.extendedFinderInfo, attrBuf.extendedFinderInfo, fxinfo, is_dir ? kNativeDXInfoMask : kNativeFXInfoMask); - - attrList.commonattr = ATTR_CMN_FNDRINFO; - if (setattrlist(path, &attrList, attrBuf.finderInfo, 2 * SIZEOF_FInfo, 0) < 0) - return false; - return true; -} - -void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Extract native Finder info flags - FinderInfo nat_finfo, nat_fxinfo; - const uint8 *emu_finfo = Mac2HostAddr(finfo); - const uint8 *emu_fxinfo = fxinfo ? Mac2HostAddr(fxinfo) : NULL; - finfo_split(nat_finfo, emu_finfo, is_dir ? kNativeDInfoMask : kNativeFInfoMask); - if (fxinfo) - finfo_split(nat_fxinfo, emu_fxinfo, is_dir ? kNativeDXInfoMask : kNativeFXInfoMask); - - // Update Finder info file (all flags) - if (USE_XATTRS) - set_finfo_to_xattr(path, emu_finfo, emu_fxinfo); - else - set_finfo_to_helper(path, emu_finfo, emu_fxinfo); - - // Update native Finder info flags - set_finfo_to_native(path, nat_finfo, nat_fxinfo, is_dir); -} - - -/* - * Resource fork emulation functions - */ - -uint32 get_rfork_size(const char *path) -{ - // Open resource file - int fd = open_rsrc(path, O_RDONLY); - if (fd < 0) - return 0; - - // Get size - off_t size = lseek(fd, 0, SEEK_END); - - // Close file and return size - close(fd); - return size < 0 ? 0 : size; -} - -int open_rfork(const char *path, int flag) -{ - return open_rsrc(path, flag); -} - -void close_rfork(const char *path, int fd) -{ - close(fd); -} - - -/* - * Read "length" bytes from file to "buffer", - * returns number of bytes read (or -1 on error) - */ - -ssize_t extfs_read(int fd, void *buffer, size_t length) -{ - return read(fd, buffer, length); -} - - -/* - * Write "length" bytes from "buffer" to file, - * returns number of bytes written (or -1 on error) - */ - -ssize_t extfs_write(int fd, void *buffer, size_t length) -{ - return write(fd, buffer, length); -} - - -/* - * Remove file/directory (and associated helper files), - * returns false on error (and sets errno) - */ - -bool extfs_remove(const char *path) -{ - // Remove helpers first, don't complain if this fails - char helper_path[MAX_PATH_LENGTH]; - make_finf_path(path, helper_path, false); - remove(helper_path); - make_rsrc_path(path, helper_path); - remove(helper_path); - - // Now remove file or directory (and helper directories in the directory) - if (remove(path) < 0) { - if (errno == EISDIR || errno == ENOTEMPTY) { - helper_path[0] = 0; - strncpy(helper_path, path, MAX_PATH_LENGTH-1); - add_path_component(helper_path, ".finf"); - rmdir(helper_path); - return rmdir(path) == 0; - } else - return false; - } - return true; -} - - -/* - * Rename/move file/directory (and associated helper files), - * returns false on error (and sets errno) - */ - -bool extfs_rename(const char *old_path, const char *new_path) -{ - // Rename helpers first, don't complain if this fails - char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH]; - make_finf_path(old_path, old_helper_path, false); - make_finf_path(new_path, new_helper_path, false); - create_finf_dir(new_path); - rename(old_helper_path, new_helper_path); - make_rsrc_path(old_path, old_helper_path); - make_rsrc_path(new_path, new_helper_path); - rename(old_helper_path, new_helper_path); - - // Now rename file - return rename(old_path, new_path) == 0; -} - - -/* - * Strings (filenames) conversion - */ - -// Convert string in the specified source and target encodings -const char *convert_string(const char *str, CFStringEncoding from, CFStringEncoding to) -{ - const char *ostr = str; - CFStringRef cfstr = CFStringCreateWithCString(NULL, str, from); - if (cfstr) { - static char buffer[MAX_PATH_LENGTH]; - memset(buffer, 0, sizeof(buffer)); - if (CFStringGetCString(cfstr, buffer, sizeof(buffer), to)) - ostr = buffer; - CFRelease(cfstr); - } - return ostr; -} - -// Convert from the host OS filename encoding to MacRoman -const char *host_encoding_to_macroman(const char *filename) -{ - return convert_string(filename, kCFStringEncodingUTF8, kCFStringEncodingMacRoman); -} - -// Convert from MacRoman to host OS filename encoding -const char *macroman_to_host_encoding(const char *filename) -{ - return convert_string(filename, kCFStringEncodingMacRoman, kCFStringEncodingUTF8); -} diff --git a/BasiliskII/src/MacOSX/macos_util_macosx.h b/BasiliskII/src/MacOSX/macos_util_macosx.h deleted file mode 100644 index 47c07859..00000000 --- a/BasiliskII/src/MacOSX/macos_util_macosx.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * $Id$ - * - * macos_util_macosx.h - Work around clashes with the enums in - * Based on: - * - * macos_util.h - MacOS definitions/utility functions - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MACOS_UTIL_H -#define MACOS_UTIL_H - -#include "cpu_emulation.h" - -#import - -/* - * Queues - */ - -enum { // QElem struct - qLink = 0, - qType = 4, - qData = 6 -}; - -enum { // QHdr struct - qFlags = 0, - qHead = 2, - qTail = 6 -}; - - -/* - * Definitions for Device Manager - */ - -// Misc constants - -enum { // IOParam struct - ioTrap = 6, - ioCmdAddr = 8, - ioCompletion = 12, - ioResult = 16, - ioNamePtr = 18, - ioVRefNum = 22, - ioRefNum = 24, - ioVersNum = 26, - ioPermssn = 27, - ioMisc = 28, - ioBuffer = 32, - ioReqCount = 36, - ioActCount = 40, - ioPosMode = 44, - ioPosOffset = 46, - ioWPosOffset = 46, // Wide positioning offset when ioPosMode has kWidePosOffsetBit set - SIZEOF_IOParam = 50 -}; - -enum { // CntrlParam struct - csCode = 26, - csParam = 28 -}; - -enum { // DrvSts struct - dsTrack = 0, - dsWriteProt = 2, - dsDiskInPlace = 3, - dsInstalled = 4, - dsSides = 5, - dsQLink = 6, - dsQType = 10, - dsQDrive = 12, - dsQRefNum = 14, - dsQFSID = 16, - dsTwoSideFmt = 18, - dsNewIntf = 19, - dsDiskErrs = 20, - dsMFMDrive = 22, - dsMFMDisk = 23, - dsTwoMegFmt = 24 -}; - -enum { // DrvSts2 struct - dsDriveSize = 18, - dsDriveS1 = 20, - dsDriveType = 22, - dsDriveManf = 24, - dsDriveChar = 26, - dsDriveMisc = 28, - SIZEOF_DrvSts = 30 -}; - -enum { // DCtlEntry struct - dCtlDriver = 0, - dCtlFlags = 4, - dCtlQHdr = 6, - dCtlPosition = 16, - dCtlStorage = 20, - dCtlRefNum = 24, - dCtlCurTicks = 26, - dCtlWindow = 30, - dCtlDelay = 34, - dCtlEMask = 36, - dCtlMenu = 38, - dCtlSlot = 40, - dCtlSlotId = 41, - dCtlDevBase = 42, - dCtlOwner = 46, - dCtlExtDev = 50, - dCtlFillByte = 51, - dCtlNodeID = 52 -}; - - -/* - * Definitions for Deferred Task Manager - */ - -enum { // DeferredTask struct - dtFlags = 6, - dtAddr = 8, - dtParam = 12, - dtReserved = 16 -}; - - -// Definitions for DebugUtil() Selector -enum { - duDebuggerGetMax = 0, - duDebuggerEnter = 1, - duDebuggerExit = 2, - duDebuggerPoll = 3, - duGetPageState = 4, - duPageFaultFatal = 5, - duDebuggerLockMemory = 6, - duDebuggerUnlockMemory = 7, - duEnterSupervisorMode = 8 -}; - -// Functions -extern void EnqueueMac(uint32 elem, uint32 list); // Enqueue QElem in list -extern int FindFreeDriveNumber(int num); // Find first free drive number, starting at "num" -extern void MountVolume(void *fh); // Mount volume with given file handle (see sys.h) -extern void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size); // Calculate disk image file layout given file size and first 256 data bytes -extern uint32 DebugUtil(uint32 Selector); // DebugUtil() Replacement -extern uint32 TimeToMacTime(time_t t); // Convert time_t value to MacOS time - -// Construct four-character-code -#define FOURCC(a,b,c,d) (((uint32)(a) << 24) | ((uint32)(b) << 16) | ((uint32)(c) << 8) | (uint32)(d)) - -// Emulator identification codes (4 and 2 characters) -const uint32 EMULATOR_ID_4 = 0x62617369; // 'basi' -const uint16 EMULATOR_ID_2 = 0x6261; // 'ba' - -// Test if basic MacOS initializations (of the ROM) are done -static inline bool HasMacStarted(void) -{ - return ReadMacInt32(0xcfc) == FOURCC('W','L','S','C'); // Mac warm start flag -} - -#endif diff --git a/BasiliskII/src/MacOSX/main_macosx.h b/BasiliskII/src/MacOSX/main_macosx.h deleted file mode 100644 index 15fdda96..00000000 --- a/BasiliskII/src/MacOSX/main_macosx.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * main_macosx.h - Prototypes for Mac OS X general definitions - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -bool InitEmulator (); -void QuitEmuNoExit(); - - -extern void ErrorAlert (const char *text); -extern void WarningAlert(const char *text); -extern bool ChoiceAlert (const char *text, const char *pos, const char *neg); diff --git a/BasiliskII/src/MacOSX/main_macosx.mm b/BasiliskII/src/MacOSX/main_macosx.mm deleted file mode 100644 index abb046c1..00000000 --- a/BasiliskII/src/MacOSX/main_macosx.mm +++ /dev/null @@ -1,744 +0,0 @@ -/* - * $Id$ - * - * main_macosx.mm - Startup code for MacOS X - * Based (in a small way) on the default main.m, - and on Basilisk's main_unix.cpp - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import -#undef check - -#define PTHREADS // Why is this here? -#include "sysdeps.h" - -#ifdef HAVE_PTHREADS -# include -#endif - -#if REAL_ADDRESSING || DIRECT_ADDRESSING -# include -#endif - -#include -using std::string; - -#include "cpu_emulation.h" -#include "sys.h" -#include "rom_patches.h" -#include "xpram.h" -#include "video.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "macos_util_macosx.h" -#include "user_strings.h" -#include "version.h" -#include "main.h" -#include "vm_alloc.h" -#include "sigsegv.h" - -#if USE_JIT -extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp -#endif - -#ifdef ENABLE_MON -# include "mon.h" -#endif - -#define DEBUG 0 -#include "debug.h" - - -#include "main_macosx.h" // To bridge between main() and misc. classes - - -// Constants -const char ROM_FILE_NAME[] = "ROM"; -const int SCRATCH_MEM_SIZE = 0x10000; // Size of scratch memory area - - -static char *bundle = NULL; // If in an OS X application bundle, its path - - -// CPU and FPU type, addressing mode -int CPUType; -bool CPUIs68060; -int FPUType; -bool TwentyFourBitAddressing; - - -// Global variables - -#ifdef HAVE_PTHREADS - -static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect InterruptFlags -#define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock) -#define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock) - -#else - -#define LOCK_INTFLAGS -#define UNLOCK_INTFLAGS - -#endif - -#if USE_SCRATCHMEM_SUBTERFUGE -uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes -#endif - -#ifdef ENABLE_MON -static struct sigaction sigint_sa; // sigaction for SIGINT handler -static void sigint_handler(...); -#endif - -#if REAL_ADDRESSING -static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped -#endif - - -/* - * Helpers to map memory that can be accessed from the Mac side - */ - -// NOTE: VM_MAP_32BIT is only used when compiling a 64-bit JIT on specific platforms -void *vm_acquire_mac(size_t size) -{ - return vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); -} - -static int vm_acquire_mac_fixed(void *addr, size_t size) -{ - return vm_acquire_fixed(addr, size, VM_MAP_DEFAULT | VM_MAP_32BIT); -} - - -/* - * SIGSEGV handler - */ - -static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip) -{ - const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip); -#if ENABLE_VOSF - // Handle screen fault - extern bool Screen_fault_handler(sigsegv_info_t *sip); - if (Screen_fault_handler(sip)) - return SIGSEGV_RETURN_SUCCESS; -#endif - -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - // Ignore writes to ROM - if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // Ignore all other faults, if requested - if (PrefsFindBool("ignoresegv")) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; -#endif - - return SIGSEGV_RETURN_FAILURE; -} - -/* - * Dump state when everything went wrong after a SEGV - */ - -static void sigsegv_dump_state(sigsegv_info_t *sip) -{ - const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip); - const sigsegv_address_t fault_instruction = sigsegv_get_fault_instruction_address(sip); - fprintf(stderr, "Caught SIGSEGV at address %p", fault_address); - if (fault_instruction != SIGSEGV_INVALID_ADDRESS) - fprintf(stderr, " [IP=%p]", fault_instruction); - fprintf(stderr, "\n"); - uaecptr nextpc; - extern void m68k_dumpstate(uaecptr *nextpc); - m68k_dumpstate(&nextpc); -#if USE_JIT && JIT_DEBUG - extern void compiler_dumpstate(void); - compiler_dumpstate(); -#endif - VideoQuitFullScreen(); -#ifdef ENABLE_MON - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif - QuitEmulator(); -} - - -/* - * Screen fault handler - */ - -bool Screen_fault_handler(sigsegv_info_t *sip) -{ - return true; -} - - -/* - * Main program - */ - -static void usage(const char *prg_name) -{ - printf( - "Usage: %s [OPTION...]\n" - "\nUnix options:\n" - " --config FILE\n read/write configuration from/to FILE\n" - " --break ADDRESS\n set ROM breakpoint\n" - " --rominfo\n dump ROM information\n", prg_name - ); - LoadPrefs(NULL); // read the prefs file so PrefsPrintUsage() will print the correct default values - PrefsPrintUsage(); - exit(0); -} - -int main(int argc, char **argv) -{ - const char *vmdir = NULL; - char str[256]; - - // Initialize variables - RAMBaseHost = NULL; - ROMBaseHost = NULL; - srand(time(NULL)); - tzset(); - - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - - // Parse command line arguments - for (int i=1; i i) { - k -= i; - for (int j=i+k; j 1023*1024*1024) // Cap to 1023MB (APD crashes at 1GB) - RAMSize = 1023*1024*1024; - -#if REAL_ADDRESSING || DIRECT_ADDRESSING - RAMSize = RAMSize & -getpagesize(); // Round down to page boundary -#endif - - // Initialize VM system - vm_init(); - -#if REAL_ADDRESSING - // Flag: RAM and ROM are contigously allocated from address 0 - bool memory_mapped_from_zero = false; - - // Make sure to map RAM & ROM at address 0 only on platforms that - // supports linker scripts to relocate the Basilisk II executable - // above 0x70000000 -#if HAVE_LINKER_SCRIPT - const bool can_map_all_memory = true; -#else - const bool can_map_all_memory = false; -#endif - - // Try to allocate all memory from 0x0000, if it is not known to crash - if (can_map_all_memory && (vm_acquire_mac_fixed(0, RAMSize + 0x100000) == 0)) { - D(bug("Could allocate RAM and ROM from 0x0000\n")); - memory_mapped_from_zero = true; - } - -#ifndef PAGEZERO_HACK - // Otherwise, just create the Low Memory area (0x0000..0x2000) - else if (vm_acquire_mac_fixed(0, 0x2000) == 0) { - D(bug("Could allocate the Low Memory globals\n")); - lm_area_mapped = true; - } - - // Exit on failure - else { - sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } -#endif -#else - *str = 0; // Eliminate unused variable warning -#endif /* REAL_ADDRESSING */ - - // Create areas for Mac RAM and ROM -#if REAL_ADDRESSING - if (memory_mapped_from_zero) { - RAMBaseHost = (uint8 *)0; - ROMBaseHost = RAMBaseHost + RAMSize; - } - else -#endif - { - uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000); - if (ram_rom_area == VM_MAP_FAILED) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } - RAMBaseHost = ram_rom_area; - ROMBaseHost = RAMBaseHost + RAMSize; - } - -#if USE_SCRATCHMEM_SUBTERFUGE - // Allocate scratch memory - ScratchMem = (uint8 *)vm_acquire_mac(SCRATCH_MEM_SIZE); - if (ScratchMem == VM_MAP_FAILED) { - ErrorAlert(STR_NO_MEM_ERR); - QuitEmulator(); - } - ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block -#endif - -#if DIRECT_ADDRESSING - // RAMBaseMac shall always be zero - MEMBaseDiff = (uintptr)RAMBaseHost; - RAMBaseMac = 0; - ROMBaseMac = Host2MacAddr(ROMBaseHost); -#endif -#if REAL_ADDRESSING - RAMBaseMac = Host2MacAddr(RAMBaseHost); - ROMBaseMac = Host2MacAddr(ROMBaseHost); -#endif - D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac)); - D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac)); - - // Get rom file path from preferences - const char *rom_path = PrefsFindString("rom"); - if ( ! rom_path ) - if ( bundle ) - WarningAlert("No rom pathname set. Trying BasiliskII.app/ROM"); - else - WarningAlert("No rom pathname set. Trying ./ROM"); - - // Load Mac ROM - int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY); - if (rom_fd < 0) { - ErrorAlert(STR_NO_ROM_FILE_ERR); - QuitEmulator(); - } - printf(GetString(STR_READING_ROM_FILE)); - ROMSize = lseek(rom_fd, 0, SEEK_END); - if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) { - ErrorAlert(STR_ROM_SIZE_ERR); - close(rom_fd); - QuitEmulator(); - } - lseek(rom_fd, 0, SEEK_SET); - if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) { - ErrorAlert(STR_ROM_FILE_READ_ERR); - close(rom_fd); - QuitEmulator(); - } - - - // Initialize everything - if (!InitAll(vmdir)) - QuitEmulator(); - D(bug("Initialization complete\n")); - - -#ifdef ENABLE_MON - // Setup SIGINT handler to enter mon - sigemptyset(&sigint_sa.sa_mask); - sigint_sa.sa_handler = (void (*)(int))sigint_handler; - sigint_sa.sa_flags = 0; - sigaction(SIGINT, &sigint_sa, NULL); -#endif - - - return YES; -} - -#undef QuitEmulator() - - -/* - * Quit emulator - */ - -void QuitEmuNoExit() -{ - D(bug("QuitEmulator\n")); - - // Exit 680x0 emulation - Exit680x0(); - - // Deinitialize everything - ExitAll(); - - // Free ROM/RAM areas - if (RAMBaseHost != VM_MAP_FAILED) { - vm_release(RAMBaseHost, RAMSize + 0x100000); - RAMBaseHost = NULL; - ROMBaseHost = NULL; - } - -#if USE_SCRATCHMEM_SUBTERFUGE - // Delete scratch memory area - if (ScratchMem != (uint8 *)VM_MAP_FAILED) { - vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE); - ScratchMem = NULL; - } -#endif - -#if REAL_ADDRESSING - // Delete Low Memory area - if (lm_area_mapped) - vm_release(0, 0x2000); -#endif - - // Exit VM wrappers - vm_exit(); - - // Exit system routines - SysExit(); - - // Exit preferences - PrefsExit(); -} - -void QuitEmulator(void) -{ - QuitEmuNoExit(); - - // Stop run loop? - [NSApp terminate: nil]; - - exit(0); -} - - -/* - * Code was patched, flush caches if neccessary (i.e. when using a real 680x0 - * or a dynamically recompiling emulator) - */ - -void FlushCodeCache(void *start, uint32 size) -{ -#if USE_JIT - if (UseJIT) - flush_icache_range((uint8 *)start, size); -#endif -} - - -/* - * SIGINT handler, enters mon - */ - -#ifdef ENABLE_MON -static void sigint_handler(...) -{ - uaecptr nextpc; - extern void m68k_dumpstate(uaecptr *nextpc); - m68k_dumpstate(&nextpc); - VideoQuitFullScreen(); - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); - QuitEmulator(); -} -#endif - - -#ifdef HAVE_PTHREADS -/* - * Pthread configuration - */ - -void Set_pthread_attr(pthread_attr_t *attr, int priority) -{ - pthread_attr_init(attr); -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - // Some of these only work for superuser - if (geteuid() == 0) { - pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); - pthread_attr_setschedpolicy(attr, SCHED_FIFO); - struct sched_param fifo_param; - fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) - + sched_get_priority_max(SCHED_FIFO)) - / 2 + priority); - pthread_attr_setschedparam(attr, &fifo_param); - } - if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) { -#ifdef PTHREAD_SCOPE_BOUND_NP - // If system scope is not available (eg. we're not running - // with CAP_SCHED_MGT capability on an SGI box), try bound - // scope. It exposes pthread scheduling to the kernel, - // without setting realtime priority. - pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP); -#endif - } -#endif -} -#endif // HAVE_PTHREADS - - -/* - * Mutexes - */ - -#ifdef HAVE_PTHREADS - -struct B2_mutex { - B2_mutex() { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - // Initialize the mutex for priority inheritance -- - // required for accurate timing. -#ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL - pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); -#endif -#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL) - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); -#endif -#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); -#endif - pthread_mutex_init(&m, &attr); - pthread_mutexattr_destroy(&attr); - } - ~B2_mutex() { - pthread_mutex_trylock(&m); // Make sure it's locked before - pthread_mutex_unlock(&m); // unlocking it. - pthread_mutex_destroy(&m); - } - pthread_mutex_t m; -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ - pthread_mutex_lock(&mutex->m); -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ - pthread_mutex_unlock(&mutex->m); -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - -#else - -struct B2_mutex { - int dummy; -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - -#endif - - -/* - * Interrupt flags (must be handled atomically!) - */ - -uint32 InterruptFlags = 0; - -void SetInterruptFlag(uint32 flag) -{ - LOCK_INTFLAGS; - InterruptFlags |= flag; - UNLOCK_INTFLAGS; -} - -void ClearInterruptFlag(uint32 flag) -{ - LOCK_INTFLAGS; - InterruptFlags &= ~flag; - UNLOCK_INTFLAGS; -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - NSString *title = [NSString stringWithCString: - GetString(STR_ERROR_ALERT_TITLE) ]; - NSString *error = [NSString stringWithCString: text]; - NSString *button = [NSString stringWithCString: GetString(STR_QUIT_BUTTON) ]; - - NSLog(error); - if ( PrefsFindBool("nogui") ) - return; - VideoQuitFullScreen(); - NSRunCriticalAlertPanel(title, error, button, nil, nil); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - NSString *title = [NSString stringWithCString: - GetString(STR_WARNING_ALERT_TITLE) ]; - NSString *warning = [NSString stringWithCString: text]; - NSString *button = [NSString stringWithCString: GetString(STR_OK_BUTTON) ]; - - NSLog(warning); - if ( PrefsFindBool("nogui") ) - return; - VideoQuitFullScreen(); - NSRunAlertPanel(title, warning, button, nil, nil); -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - NSString *title = [NSString stringWithCString: - GetString(STR_WARNING_ALERT_TITLE) ]; - NSString *warning = [NSString stringWithCString: text]; - NSString *yes = [NSString stringWithCString: pos]; - NSString *no = [NSString stringWithCString: neg]; - - return NSRunInformationalAlertPanel(title, warning, yes, no, nil); -} diff --git a/BasiliskII/src/MacOSX/misc_macosx.h b/BasiliskII/src/MacOSX/misc_macosx.h deleted file mode 100644 index b22f1c10..00000000 --- a/BasiliskII/src/MacOSX/misc_macosx.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * $Id$ - * - * misc_macosx.h - Some prototypes of functions defined in misc_macosx.mm - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if defined(__APPLE__) && defined(__MACH__) - // This means we are on Mac OS X of some sort -#endif - -extern void ErrorSheet (NSString *msg, NSWindow *win), - ErrorSheet (NSString *msg1, NSString *msg2, - NSString *button, NSWindow *win), - WarningSheet (NSString *message,NSWindow *win), - WarningSheet (NSString *msg1, NSString *msg2, - NSString *button, NSWindow *win), - InfoSheet (NSString *msg, NSWindow *win), - InfoSheet (NSString *msg1, NSString *msg2, - NSString *button, NSWindow *win), - EndSheet (NSWindow * window); - -extern int frequencyToTickDelay (float frequency); diff --git a/BasiliskII/src/MacOSX/misc_macosx.mm b/BasiliskII/src/MacOSX/misc_macosx.mm deleted file mode 100644 index f214261e..00000000 --- a/BasiliskII/src/MacOSX/misc_macosx.mm +++ /dev/null @@ -1,112 +0,0 @@ -/* - * $Id$ - * - * misc_macosx.m - Miscellaneous Mac OS X routines. - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -#import "sysdeps.h" // Types used in Basilisk C++ code - -#import - -#define DEBUG 0 -#import - - - -/************************************************************************/ -/* Display Errors and Warnings in a sliding thingy attached to a */ -/* particular window, instead of as a separate window (Panel or Dialog) */ -/************************************************************************/ - -void ErrorSheet (NSString * message, NSWindow * window) -{ - NSLog(message); - NSBeginCriticalAlertSheet(message, nil, nil, nil, window, - nil, nil, nil, NULL, @""); - while ( [window attachedSheet] ) - sleep(1); - //[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow: 1.0]]; -} - -void ErrorSheet (NSString * message1, NSString * message2, - NSString * button, NSWindow * window) -{ - NSLog(message1); - NSLog(message2); - NSBeginCriticalAlertSheet(message1, button, nil, nil, window, - nil, nil, nil, NULL, message2); - while ( [window attachedSheet] ) - sleep(1); - //[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow: 1.0]]; -} - - -void WarningSheet (NSString * message, NSWindow * window) -{ - NSLog(message); - NSBeginAlertSheet(message, nil, nil, nil, window, - nil, nil, nil, NULL, @""); -} - -void WarningSheet (NSString * message1, NSString * message2, - NSString * button, NSWindow * window) -{ - NSLog(message1); - NSLog(message2); - NSBeginAlertSheet(message1, button, nil, nil, window, - nil, nil, nil, NULL, message2); -} - - -void InfoSheet (NSString * message, NSWindow * window) -{ - NSLog(message); - NSBeginInformationalAlertSheet(message, nil, nil, nil, window, - nil, nil, nil, NULL, @""); -} - -void InfoSheet (NSString * message1, NSString * message2, - NSString * button, NSWindow * window) -{ - NSLog(message1); - NSLog(message2); - NSBeginInformationalAlertSheet(message1, nil, nil, nil, window, - nil, nil, nil, NULL, message2); -} - -void EndSheet (NSWindow * window) -{ - [[window attachedSheet] close]; -} - -// Convert a frequency (i.e. updates per second) to a 60hz tick delay, and update prefs -int frequencyToTickDelay (float freq) -{ - if ( freq == 0.0 ) - return 0; - else - { - int delay = (int) (60.0 / freq); - - PrefsReplaceInt32("frameskip", delay); - return delay; - } -} diff --git a/BasiliskII/src/MacOSX/prefs_macosx.cpp b/BasiliskII/src/MacOSX/prefs_macosx.cpp deleted file mode 100644 index 74000fd7..00000000 --- a/BasiliskII/src/MacOSX/prefs_macosx.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * $Id$ - * - * prefs_macosx.cpp - Preferences handling, Mac OS X specific. - * Based on prefs_unix.cpp - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include - -#include -using std::string; - -#include "prefs.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - {"ignoresegv", TYPE_BOOLEAN, false, "ignore illegal memory accesses"}, -#endif - {"idlewait", TYPE_BOOLEAN, false, "sleep when idle"}, - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Prefs file name and path -const char PREFS_FILE_NAME[] = ".basilisk_ii_prefs"; -string UserPrefsPath; -static string prefs_path; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(const char *vmdir) -{ - if (vmdir) { - prefs_path = string(vmdir) + '/' + string("prefs"); - FILE *prefs = fopen(prefs_path.c_str(), "r"); - if (!prefs) { - printf("No file at %s found.\n", prefs_path.c_str()); - exit(1); - } - LoadPrefsFromStream(prefs); - fclose(prefs); - return; - } - - // Construct prefs path - if (UserPrefsPath.empty()) { - char *home = getenv("HOME"); - if (home) - prefs_path = string(home) + '/'; - prefs_path += PREFS_FILE_NAME; - UserPrefsPath = prefs_path; - } else - prefs_path = UserPrefsPath; - - // Read preferences from settings file - FILE *f = fopen(prefs_path.c_str(), "r"); - if (f != NULL) { - - // Prefs file found, load settings - LoadPrefsFromStream(f); - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - } - - // Remove Nigel's bad old serial prefs - - const char *str; - int tmp = 0; - - if ( (str = PrefsFindString("seriala") ) != NULL - && strcmp(str, "/dev/ttys0") == 0 ) - { - puts("Deleting invalid prefs item 'seriala /dev/ttys0'"); - PrefsRemoveItem("seriala", 1); - } - - if ( (str = PrefsFindString("serialb") ) != NULL - && strcmp(str, "/dev/ttys1") == 0 ) - { - puts("Deleting invalid prefs item 'serialb /dev/ttys1'"); - PrefsRemoveItem("serialb", 1); - } - - // Floppy & cdrom prefs are always removed - - // we search for them each time the emulator is started - - while ( (str = PrefsFindString("floppy", tmp) ) != NULL ) - PrefsRemoveItem("floppy", tmp); - - while ( (str = PrefsFindString("cdrom", tmp) ) != NULL ) - PrefsRemoveItem("cdrom", tmp); -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = fopen(prefs_path.c_str(), "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsReplaceString("extfs", getenv("HOME")); - PrefsReplaceString("screen", "win/512/384/16"); -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - PrefsAddBool("ignoresegv", false); -#endif - PrefsAddBool("idlewait", true); -} diff --git a/BasiliskII/src/MacOSX/utils_macosx.h b/BasiliskII/src/MacOSX/utils_macosx.h deleted file mode 100644 index fc2c83c6..00000000 --- a/BasiliskII/src/MacOSX/utils_macosx.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * utils_macosx.h - Mac OS X utility functions. - * - * Copyright (C) 2011 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef UTILS_MACOSX_H -#define UTILS_MACOSX_H - -// Invokes the specified function with an NSAutoReleasePool in place. -void NSAutoReleasePool_wrap(void (*fn)(void)); - -#endif diff --git a/BasiliskII/src/MacOSX/utils_macosx.mm b/BasiliskII/src/MacOSX/utils_macosx.mm deleted file mode 100644 index b653638d..00000000 --- a/BasiliskII/src/MacOSX/utils_macosx.mm +++ /dev/null @@ -1,30 +0,0 @@ -/* - * utils_macosx.mm - Mac OS X utility functions. - * - * Copyright (C) 2011 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include "utils_macosx.h" - -// This is used from video_sdl.cpp. -void NSAutoReleasePool_wrap(void (*fn)(void)) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - fn(); - [pool release]; -} diff --git a/BasiliskII/src/MacOSX/video_macosx.h b/BasiliskII/src/MacOSX/video_macosx.h deleted file mode 100644 index 9cecd9f2..00000000 --- a/BasiliskII/src/MacOSX/video_macosx.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * video_macosx.h - Some video constants and globals - * - * $Id$ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -/* Set the strategy for drawing the bitmap in the Mac OS X window */ -//#define CGDRAWBITMAP -#if defined __i386__ -#define CGIMAGEREF -//#define NSBITMAP -#else -#define CGIMAGEREF -//#define NSBITMAP -#endif - -// Using Core Graphics is fastest when rendering 32bit data. -// Using CGImageRefs allows us to use all the bitmaps that BasiliskII supports. -// When both Basilisk II and OS X are set to 'Thousands', updating a 312x342 -// window happens at over 500fps under 10.2, and over 600fps on 10.3! - -/* When the BasiliskII video driver respects the alpha bits, set this to let us use */ -/* kCGImageAlphaPremultipliedFirst, and to have nice rounded corners on the screen. */ -//#define CG_USE_ALPHA -/* At the moment, it writes in the full 32bits :-( */ - - -#define MIN_WIDTH 512 -#define MIN_HEIGHT 384 -#define MIN_HEIGHTC 342 // For classic emulation - -#define MAX_WIDTH 1240 -#define MAX_HEIGHT 1024 - -// Display types -enum -{ - DISPLAY_OPENGL, - DISPLAY_SCREEN, - DISPLAY_WINDOW -}; - - -extern uint8 display_type, - frame_skip; -extern uint16 init_width, - init_height, - init_depth; - -extern bool parse_screen_prefs (const char *); -extern void resizeWinTo (const uint16, const uint16); - -#import -#import "EmulatorView.h" - -extern NSWindow *the_win; -extern EmulatorView *output; diff --git a/BasiliskII/src/MacOSX/video_macosx.mm b/BasiliskII/src/MacOSX/video_macosx.mm deleted file mode 100644 index d4eff082..00000000 --- a/BasiliskII/src/MacOSX/video_macosx.mm +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * $Id$ - * - * video_macosx.mm - Interface between Basilisk II and Cocoa windowing. - * Based on video_amiga.cpp and video_x.cpp - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "sysdeps.h" - -#ifdef HAVE_PTHREADS -# include -#endif - -#include -#include -#include -#include "macos_util_macosx.h" -#include -#include -#include "video_macosx.h" - -#define DEBUG 0 -#define VERBOSE 0 -#include "debug.h" - -#ifdef NSBITMAP -#import -#endif - -#import // Needed for NSLog(@"") -#import "misc_macosx.h" // WarningSheet() prototype - - - -// Global variables -uint8 display_type = DISPLAY_WINDOW, // These are used by PrefsEditor - frame_skip; -uint16 init_width = MIN_WIDTH, // as well as this code - init_height = MIN_HEIGHT, - init_depth = 32; - - EmulatorView *output = nil; // Set by [EmulatorView init] - NSWindow *the_win = nil; // Set by [Emulator awakeFromNib] - -static BOOL singleDisplay = YES; - -/* - * Utility functions - */ - -static uint8 -bits_from_depth(const video_depth depth) -{ - int bits = 1 << depth; -// if (bits == 16) -// bits = 15; -// else if (bits == 32) -// bits = 24; - return bits; -} - -static const char * -colours_from_depth(const video_depth depth) -{ - switch ( depth ) - { - case VDEPTH_1BIT : return "Monochrome"; - case VDEPTH_2BIT : return "4 colours"; - case VDEPTH_4BIT : return "16 colours"; - case VDEPTH_8BIT : return "256 colours"; - case VDEPTH_16BIT: return "Thousands of colours"; - case VDEPTH_32BIT: return "Millions of colours"; - } - - return "illegal colour depth"; -} - -static const char * -colours_from_depth(const uint16 depth) -{ - return colours_from_depth(DepthModeForPixelDepth(depth) ); -} - -bool -parse_screen_prefs(const char *mode_str) -{ - if ( ! mode_str ) - { - // No screen pref was found. Supply a default: - mode_str = "win/512/384"; - } - - if (sscanf(mode_str, "win/%hd/%hd/%hd", - &init_width, &init_height, &init_depth) == 3) - display_type = DISPLAY_WINDOW; - else if (sscanf(mode_str, "win/%hd/%hd", &init_width, &init_height) == 2) - display_type = DISPLAY_WINDOW; - else if (strcmp(mode_str, "full") == 0) - display_type = DISPLAY_SCREEN; - else if (sscanf(mode_str, "full/%hd/%hd/%hd", - &init_width, &init_height, &init_depth) == 3) - display_type = DISPLAY_SCREEN; - else if (sscanf(mode_str, "full/%hd/%hd", &init_width, &init_height) == 2) - display_type = DISPLAY_SCREEN; - else if (sscanf(mode_str, "opengl/%hd/%hd/%hd", - &init_width, &init_height, &init_depth) == 3) - display_type = DISPLAY_OPENGL; - else if (sscanf(mode_str, "opengl/%hd/%hd", &init_width, &init_height) == 2) - display_type = DISPLAY_OPENGL; - else return false; - - return true; -} - -// Supported video modes -static vector VideoModes; - - -// Add mode to list of supported modes -static void -add_mode(const uint16 width, const uint16 height, - const uint32 resolution_id, const uint32 bytes_per_row, - const uint32 user_data, - const video_depth depth) -{ - vector::const_iterator i, - end = VideoModes.end(); - - for (i = VideoModes.begin(); i != end; ++i) - if ( i->x == width && i->y == height && - i->bytes_per_row == bytes_per_row && i->depth == depth ) - { - D(NSLog(@"Duplicate mode (%hdx%hdx%ld, ID %02x, new ID %02x)\n", - width, height, depth, i->resolution_id, resolution_id)); - return; - } - - video_mode mode; - - mode.x = width; - mode.y = height; - mode.resolution_id = resolution_id; - mode.bytes_per_row = bytes_per_row; - mode.user_data = user_data; - mode.depth = depth; - - D(bug("Added video mode: w=%d h=%d d=%d(%d bits)\n", - width, height, depth, bits_from_depth(depth) )); - - VideoModes.push_back(mode); -} - -// Add standard list of windowed modes for given color depth -static void add_standard_modes(const video_depth depth) -{ - D(bug("add_standard_modes: depth=%d(%d bits)\n", - depth, bits_from_depth(depth) )); - - add_mode(512, 384, 0x80, TrivialBytesPerRow(512, depth), 0, depth); - add_mode(640, 480, 0x81, TrivialBytesPerRow(640, depth), 0, depth); - add_mode(800, 600, 0x82, TrivialBytesPerRow(800, depth), 0, depth); - add_mode(832, 624, 0x83, TrivialBytesPerRow(832, depth), 0, depth); - add_mode(1024, 768, 0x84, TrivialBytesPerRow(1024, depth), 0, depth); - add_mode(1152, 768, 0x85, TrivialBytesPerRow(1152, depth), 0, depth); - add_mode(1152, 870, 0x86, TrivialBytesPerRow(1152, depth), 0, depth); - add_mode(1280, 1024, 0x87, TrivialBytesPerRow(1280, depth), 0, depth); - add_mode(1600, 1200, 0x88, TrivialBytesPerRow(1600, depth), 0, depth); -} - -// Helper function to get a 32bit int from a dictionary -static int32 getCFint32 (CFDictionaryRef dict, CFStringRef key) -{ - CFNumberRef ref = (CFNumberRef) CFDictionaryGetValue(dict, key); - - if ( ref ) - { - int32 val; - - if ( CFNumberGetValue(ref, kCFNumberSInt32Type, &val) ) - return val; - else - NSLog(@"getCFint32() - Failed to get the value %@", key); - } - else - NSLog(@"getCFint32() - Failed to get a 32bit int for %@", key); - - return 0; -} - -// Nasty hack. Under 10.1, CGDisplayAvailableModes() does not provide bytes per row, -// and the emulator doesn't like setting the bytes per row after the screen, -// so we use a lot of magic numbers here. -// This will probably fail on some video hardware. -// I have tested on my G4 PowerBook 400 and G3 PowerBook Series 292 - -static int -CGBytesPerRow(const uint16 width, const video_depth depth) -{ - if ( depth == VDEPTH_8BIT ) - switch ( width ) - { - case 640: - case 720: return 768; - case 800: - case 896: return 1024; - case 1152: return 1280; - } - - if ( width == 720 && depth == VDEPTH_16BIT) return 1536; - if ( width == 720 && depth == VDEPTH_32BIT) return 3072; - if ( width == 800 && depth == VDEPTH_16BIT) return 1792; - if ( width == 800 && depth == VDEPTH_32BIT) return 3328; - - return TrivialBytesPerRow(width, depth); -} - -static bool add_CGDirectDisplay_modes() -{ -#define kMaxDisplays 8 - CGDirectDisplayID displays[kMaxDisplays]; - CGDisplayErr err; - CGDisplayCount n; - int32 oldRes = 0, - res_id = 0x80; - - - err = CGGetActiveDisplayList(kMaxDisplays, displays, &n); - if ( err != CGDisplayNoErr ) - n = 1, displays[n] = kCGDirectMainDisplay; - - if ( n > 1 ) - singleDisplay = NO; - - for ( CGDisplayCount dc = 0; dc < n; ++dc ) - { - CGDirectDisplayID d = displays[dc]; - CFArrayRef m = CGDisplayAvailableModes(d); - - if ( ! m ) // Store the current display mode - add_mode(CGDisplayPixelsWide(d), - CGDisplayPixelsHigh(d), - res_id++, CGDisplayBytesPerRow(d), - (const uint32) d, - DepthModeForPixelDepth(CGDisplayBitsPerPixel(d))); - else - { - CFIndex nModes = CFArrayGetCount(m); - - for ( CFIndex mc = 0; mc < nModes; ++mc ) - { - CFDictionaryRef modeSpec = (CFDictionaryRef) - CFArrayGetValueAtIndex(m, mc); - - int32 bpp = getCFint32(modeSpec, kCGDisplayBitsPerPixel); - int32 height = getCFint32(modeSpec, kCGDisplayHeight); - int32 width = getCFint32(modeSpec, kCGDisplayWidth); -#ifdef MAC_OS_X_VERSION_10_2 - int32 bytes = getCFint32(modeSpec, kCGDisplayBytesPerRow); -#else - int32 bytes = 0; -#endif - video_depth depth = DepthModeForPixelDepth(bpp); - - if ( ! bpp || ! height || ! width ) - { - NSLog(@"Could not get details of mode %d, display %d", - mc, dc); - return false; - } -#if VERBOSE - else - NSLog(@"Display %ld, spec = %@", d, modeSpec); -#endif - - if ( ! bytes ) - { - NSLog(@"Could not get bytes per row, guessing"); - bytes = CGBytesPerRow(width, depth); - } - - if ( ! oldRes ) - oldRes = width * height; - else - if ( oldRes != width * height ) - { - oldRes = width * height; - ++res_id; - } - - add_mode(width, height, res_id, bytes, (const uint32) d, depth); - } - } - } - - return true; -} - -#ifdef CG_USE_ALPHA -// memset() by long instead of byte - -static void memsetl (long *buffer, long pattern, size_t length) -{ - long *buf = (long *) buffer, - *end = buf + length/4; - - while ( ++buf < end ) - *buf = pattern; -} - -// Sets the alpha channel in a image to full on, except for the corners - -static void mask_buffer (void *buffer, size_t width, size_t size) -{ - long *bufl = (long *) buffer; - char *bufc = (char *) buffer; - - - memsetl(bufl, 0xFF000000, size); - - - // Round upper-left corner - *bufl = 0, *bufc+4 = 0; // XXXXX - bufc += width, *bufc++ = 0, *bufc++ = 0, *bufc++ = 0; // XXX - bufc += width, *bufc++ = 0, *bufc = 0; // XX - bufc += width, *bufc = 0; // X - bufc += width, *bufc = 0; // X - - - NSLog(@"Masked buffer"); -} -#endif - -// monitor_desc subclass for Mac OS X displays - -class OSX_monitor : public monitor_desc -{ - public: - OSX_monitor(const vector &available_modes, - video_depth default_depth, - uint32 default_id); - - virtual void set_palette(uint8 *pal, int num); - virtual void switch_to_current_mode(void); - - void set_mac_frame_buffer(const video_mode mode); - - void video_close(void); - bool video_open (const video_mode &mode); - - - private: - bool init_opengl(const video_mode &mode); - bool init_screen( video_mode &mode); - bool init_window(const video_mode &mode); - - -#ifdef CGIMAGEREF - CGColorSpaceRef colourSpace; - uint8 *colourTable; - CGImageRef imageRef; - CGDataProviderRef provider; - short x, y, bpp, depth, bpr; -#endif -#ifdef NSBITMAP - NSBitmapImageRep *bitmap; -#endif - void *the_buffer; - - - // These record changes we made in setting full screen mode, - // so that we can set the display back as it was again. - CGDirectDisplayID theDisplay; - CFDictionaryRef originalMode, - newMode; -}; - - -OSX_monitor :: OSX_monitor (const vector &available_modes, - video_depth default_depth, - uint32 default_id) - : monitor_desc (available_modes, default_depth, default_id) -{ -#ifdef CGIMAGEREF - colourSpace = nil; - colourTable = (uint8 *) malloc(256 * 3); - imageRef = nil; - provider = nil; -#endif -#ifdef NSBITMAP - bitmap = nil; -#endif - newMode = originalMode = nil; - the_buffer = NULL; - theDisplay = nil; -}; - -// Should also have a destructor which does -//#ifdef CGIMAGEREF -// free(colourTable); -//#endif - - -// Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac) -void -OSX_monitor::set_mac_frame_buffer(const video_mode mode) -{ -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING - switch ( mode.depth ) - { - // case VDEPTH_15BIT: - case VDEPTH_16BIT: MacFrameLayout = FLAYOUT_HOST_555; break; - // case VDEPTH_24BIT: - case VDEPTH_32BIT: MacFrameLayout = FLAYOUT_HOST_888; break; - default : MacFrameLayout = FLAYOUT_DIRECT; - } - set_mac_frame_base(MacFrameBaseMac); - - // Set variables used by UAE memory banking - MacFrameBaseHost = (uint8 *) the_buffer; - MacFrameSize = mode.bytes_per_row * mode.y; - InitFrameBufferMapping(); -#else - set_mac_frame_base((unsigned int)Host2MacAddr((uint8 *)the_buffer)); -#endif - D(bug("mac_frame_base = %08x\n", get_mac_frame_base())); -} - -static void -resizeWinBy(const short deltaX, const short deltaY) -{ - NSRect rect = [the_win frame]; - - D(bug("resizeWinBy(%d,%d) - ", deltaX, deltaY)); - D(bug("old x=%g, y=%g", rect.size.width, rect.size.height)); - - rect.size.width += deltaX; - rect.size.height += deltaY; - - D(bug(", new x=%g, y=%g\n", rect.size.width, rect.size.height)); - - [the_win setFrame: rect display: YES animate: YES]; - [the_win center]; - rect = [the_win frame]; -} - -void resizeWinTo(const uint16 newWidth, const uint16 newHeight) -{ - int deltaX = newWidth - [output width], - deltaY = newHeight - [output height]; - - D(bug("resizeWinTo(%d,%d)\n", newWidth, newHeight)); - - if ( deltaX || deltaY ) - resizeWinBy(deltaX, deltaY); -} - -// Open window -bool -OSX_monitor::init_window(const video_mode &mode) -{ - D(bug("init_window: depth=%d(%d bits)\n", - mode.depth, bits_from_depth(mode.depth) )); - - - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - - // Is the window open? - if ( ! the_win ) - { - ErrorAlert(STR_OPEN_WINDOW_ERR); - return false; - } - resizeWinTo(mode.x, mode.y); - - - // Create frame buffer ("height + 2" for safety) - int the_buffer_size = mode.bytes_per_row * (mode.y + 2); - - the_buffer = calloc(the_buffer_size, 1); - if ( ! the_buffer ) - { - NSLog(@"calloc(%d) failed", the_buffer_size); - ErrorAlert(STR_NO_MEM_ERR); - return false; - } - D(bug("the_buffer = %p\n", the_buffer)); - - - unsigned char *offsetBuffer = (unsigned char *) the_buffer; - offsetBuffer += 1; // OS X NSBitmaps are RGBA, but Basilisk generates ARGB - -#ifdef CGIMAGEREF - switch ( mode.depth ) - { - case VDEPTH_1BIT: bpp = 1; break; - case VDEPTH_2BIT: bpp = 2; break; - case VDEPTH_4BIT: bpp = 4; break; - case VDEPTH_8BIT: bpp = 8; break; - case VDEPTH_16BIT: bpp = 5; break; - case VDEPTH_32BIT: bpp = 8; break; - } - - x = mode.x, y = mode.y, depth = bits_from_depth(mode.depth), bpr = mode.bytes_per_row; - - colourSpace = CGColorSpaceCreateDeviceRGB(); - - if ( mode.depth < VDEPTH_16BIT ) - { - CGColorSpaceRef oldColourSpace = colourSpace; - - colourSpace = CGColorSpaceCreateIndexed(colourSpace, 255, colourTable); - - CGColorSpaceRelease(oldColourSpace); - } - - if ( ! colourSpace ) - { - ErrorAlert("No valid colour space"); - return false; - } - - provider = CGDataProviderCreateWithData(NULL, the_buffer, - the_buffer_size, NULL); - if ( ! provider ) - { - ErrorAlert("Could not create CGDataProvider from buffer data"); - return false; - } - - imageRef = CGImageCreate(x, y, bpp, depth, bpr, colourSpace, - #ifdef CG_USE_ALPHA - kCGImageAlphaPremultipliedFirst, - #else - kCGImageAlphaNoneSkipFirst, - #endif - provider, - NULL, // colourMap translation table - NO, // shouldInterpolate colours? - kCGRenderingIntentDefault); - if ( ! imageRef ) - { - ErrorAlert("Could not create CGImage from CGDataProvider"); - return false; - } - - [output readyToDraw: imageRef - bitmap: offsetBuffer - imageWidth: x - imageHeight: y]; - - - #ifdef CG_USE_ALPHA - mask_buffer(the_buffer, x, the_buffer_size); - -/* Create an image mask with this call? */ -//CG_EXTERN CGImageRef -//CGImageMaskCreate(size_t width, size_t height, size_t bitsPerComponent, -// size_t bitsPerPixel, size_t bytesPerRow, -// CGDataProviderRef provider, const float decode[], bool shouldInterpolate); - #endif - - return true; -#endif - - -#ifndef CGIMAGEREF - short bitsPer, samplesPer; // How big is each Pixel? - - if ( mode.depth == VDEPTH_1BIT ) - bitsPer = 1; - else - bitsPer = 8; - - if ( mode.depth == VDEPTH_32BIT ) - samplesPer = 3; - else - samplesPer = 1; -#endif - - -#ifdef NSBITMAP - bitmap = [NSBitmapImageRep alloc]; - bitmap = [bitmap initWithBitmapDataPlanes: (unsigned char **) &offsetBuffer - pixelsWide: mode.x - pixelsHigh: mode.y - bitsPerSample: bitsPer - samplesPerPixel: samplesPer - hasAlpha: NO - isPlanar: NO - colorSpaceName: NSCalibratedRGBColorSpace - bytesPerRow: mode.bytes_per_row - bitsPerPixel: bits_from_depth(mode.depth)]; - - if ( ! bitmap ) - { - ErrorAlert("Could not allocate an NSBitmapImageRep"); - return false; - } - - [output readyToDraw: bitmap - imageWidth: mode.x - imageHeight: mode.y]; -#endif - -#ifdef CGDRAWBITMAP - [output readyToDraw: offsetBuffer - width: mode.x - height: mode.y - bps: bitsPer - spp: samplesPer - bpp: bits_from_depth(mode.depth) - bpr: mode.bytes_per_row - isPlanar: NO - hasAlpha: NO]; -#endif - - return true; -} - -#import -#import -#import "NNThread.h" - -bool -OSX_monitor::init_screen(video_mode &mode) -{ - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - // Display stored by add_CGDirectDisplay_modes() - theDisplay = (CGDirectDisplayID) mode.user_data; - - originalMode = CGDisplayCurrentMode(theDisplay); - if ( ! originalMode ) - { - ErrorSheet(@"Could not get current mode of display", the_win); - return false; - } - - D(NSLog(@"About to call CGDisplayBestModeForParameters()")); - newMode = CGDisplayBestModeForParameters(theDisplay, - bits_from_depth(mode.depth), - mode.x, mode.y, NULL); - if ( ! newMode ) - { - ErrorSheet(@"Could not find a matching screen mode", the_win); - return false; - } - -// This sometimes takes ages to return after the window is genied, -// so for now we leave it onscreen -// [the_win miniaturize: nil]; - - D(NSLog(@"About to call CGDisplayCapture()")); - if ( CGDisplayCapture(theDisplay) != CGDisplayNoErr ) - { -// [the_win deminiaturize: nil]; - ErrorSheet(@"Could not capture display", the_win); - return false; - } - - D(NSLog(@"About to call CGDisplaySwitchToMode()")); - if ( CGDisplaySwitchToMode(theDisplay, newMode) != CGDisplayNoErr ) - { - CGDisplayRelease(theDisplay); -// [the_win deminiaturize: nil]; - ErrorSheet(@"Could not switch to matching screen mode", the_win); - return false; - } - - the_buffer = CGDisplayBaseAddress(theDisplay); - if ( ! the_buffer ) - { - CGDisplaySwitchToMode(theDisplay, originalMode); - CGDisplayRelease(theDisplay); -// [the_win deminiaturize: nil]; - ErrorSheet(@"Could not get base address of screen", the_win); - return false; - } - - if ( mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) ) - { - D(bug("Bytes per row (%d) doesn't match current (%ld)\n", - mode.bytes_per_row, CGDisplayBytesPerRow(theDisplay))); - mode.bytes_per_row = CGDisplayBytesPerRow(theDisplay); - } - - [NSMenu setMenuBarVisible:NO]; - - if ( singleDisplay ) - { - CGDisplayHideCursor(theDisplay); - - [output startedFullScreen: theDisplay]; - - // Send emulated mouse to current location - [output fullscreenMouseMove]; - } - else - { - // Should set up something to hide the cursor when it enters theDisplay? - } - - return true; -} - - -bool -OSX_monitor::init_opengl(const video_mode &mode) -{ - ErrorAlert("Sorry. OpenGL mode is not implemented yet"); - return false; -} - -/* - * Initialization - */ -static bool -monitor_init(const video_mode &init_mode) -{ - OSX_monitor *monitor; - BOOL success; - - monitor = new OSX_monitor(VideoModes, init_mode.depth, - init_mode.resolution_id); - success = monitor->video_open(init_mode); - - if ( success ) - { - monitor->set_mac_frame_buffer(init_mode); - VideoMonitors.push_back(monitor); - return YES; - } - - return NO; -} - -bool VideoInit(bool classic) -{ - // Read frame skip prefs - frame_skip = PrefsFindInt32("frameskip"); - if (frame_skip == 0) - frame_skip = 1; - - // Get screen mode from preferences - const char *mode_str; - if (classic) - mode_str = "win/512/342"; - else - mode_str = PrefsFindString("screen"); - - // Determine display_type and init_width, height & depth - parse_screen_prefs(mode_str); - - // Construct list of supported modes - if (classic) - add_mode(512, 342, 0x80, 64, 0, VDEPTH_1BIT); - else - switch ( display_type ) - { - case DISPLAY_SCREEN: - if ( ! add_CGDirectDisplay_modes() ) - { - ErrorAlert("Unable to get list of displays for full screen mode"); - return false; - } - break; - case DISPLAY_OPENGL: - // Same as window depths and sizes? - case DISPLAY_WINDOW: -#ifdef CGIMAGEREF - add_standard_modes(VDEPTH_1BIT); - add_standard_modes(VDEPTH_2BIT); - add_standard_modes(VDEPTH_4BIT); - add_standard_modes(VDEPTH_8BIT); - add_standard_modes(VDEPTH_16BIT); -#endif - add_standard_modes(VDEPTH_32BIT); - break; - } - -// video_init_depth_list(); Now done in monitor_desc constructor? - -#if DEBUG - bug("Available video modes:\n"); - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) - bug(" %dx%d (ID %02x), %s\n", i->x, i->y, i->resolution_id, - colours_from_depth(i->depth)); -#endif - - D(bug("VideoInit: width=%hd height=%hd depth=%d\n", - init_width, init_height, init_depth)); - - // Find requested default mode and open display - if (VideoModes.size() > 0) - { - // Find mode with specified dimensions - std::vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) - { - D(bug("VideoInit: w=%d h=%d d=%d\n", - i->x, i->y, bits_from_depth(i->depth))); - if (i->x == init_width && i->y == init_height - && bits_from_depth(i->depth) == init_depth) - return monitor_init(*i); - } - } - - char str[150]; - sprintf(str, "Cannot open selected video mode\r(%hd x %hd, %s).\r%s", - init_width, init_height, - colours_from_depth(init_depth), "Using lowest resolution"); - WarningAlert(str); - - return monitor_init(VideoModes[0]); -} - - -// Open display for specified mode -bool -OSX_monitor::video_open(const video_mode &mode) -{ - D(bug("video_open: width=%d height=%d depth=%d bytes_per_row=%d\n", - mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row)); - - // Open display - switch ( display_type ) - { - case DISPLAY_WINDOW: return init_window(mode); - case DISPLAY_SCREEN: return init_screen((video_mode &)mode); - case DISPLAY_OPENGL: return init_opengl(mode); - } - - return false; -} - - -void -OSX_monitor::video_close() -{ - D(bug("video_close()\n")); - - switch ( display_type ) { - case DISPLAY_WINDOW: - // Stop redraw thread - [output disableDrawing]; - - // Free frame buffer stuff -#ifdef CGIMAGEREF - CGImageRelease(imageRef); - CGColorSpaceRelease(colourSpace); - CGDataProviderRelease(provider); -#endif -#ifdef NSBITMAP - [bitmap release]; -#endif - free(the_buffer); - - break; - - case DISPLAY_SCREEN: - if ( theDisplay && originalMode ) - { - if ( singleDisplay ) - CGDisplayShowCursor(theDisplay); - [NSMenu setMenuBarVisible:YES]; - CGDisplaySwitchToMode(theDisplay, originalMode); - CGDisplayRelease(theDisplay); - //[the_win deminiaturize: nil]; - } - break; - - case DISPLAY_OPENGL: - break; - } -} - - -/* - * Deinitialization - */ - -void VideoExit(void) -{ - // Close displays - vector::iterator i, end; - - end = VideoMonitors.end(); - - for (i = VideoMonitors.begin(); i != end; ++i) - dynamic_cast(*i)->video_close(); - - VideoMonitors.clear(); - VideoModes.clear(); -} - - -/* - * Set palette - */ - -void -OSX_monitor::set_palette(uint8 *pal, int num) -{ - if ( [output isFullScreen] && CGDisplayCanSetPalette(theDisplay) - && ! IsDirectMode(get_current_mode()) ) - { - CGDirectPaletteRef CGpal; - CGDisplayErr err; - - - CGpal = CGPaletteCreateWithByteSamples((CGDeviceByteColor *)pal, num); - err = CGDisplaySetPalette(theDisplay, CGpal); - if ( err != noErr ) - NSLog(@"Failed to set palette, error = %d", err); - CGPaletteRelease(CGpal); - } - -#ifdef CGIMAGEREF - if ( display_type != DISPLAY_WINDOW ) - return; - - // To change the palette, we have to regenerate - // the CGImageRef with the new colour space. - - CGImageRef oldImageRef = imageRef; - CGColorSpaceRef oldColourSpace = colourSpace; - - colourSpace = CGColorSpaceCreateDeviceRGB(); - - if ( depth < 16 ) - { - CGColorSpaceRef tempColourSpace = colourSpace; - - colourSpace = CGColorSpaceCreateIndexed(colourSpace, 255, pal); - CGColorSpaceRelease(tempColourSpace); - } - - if ( ! colourSpace ) - { - ErrorAlert("No valid colour space"); - return; - } - - imageRef = CGImageCreate(x, y, bpp, depth, bpr, colourSpace, - #ifdef CG_USE_ALPHA - kCGImageAlphaPremultipliedFirst, - #else - kCGImageAlphaNoneSkipFirst, - #endif - provider, - NULL, // colourMap translation table - NO, // shouldInterpolate colours? - kCGRenderingIntentDefault); - if ( ! imageRef ) - { - ErrorAlert("Could not create CGImage from CGDataProvider"); - return; - } - - unsigned char *offsetBuffer = (unsigned char *) the_buffer; - offsetBuffer += 1; // OS X NSBitmaps are RGBA, but Basilisk generates ARGB - - [output readyToDraw: imageRef - bitmap: offsetBuffer - imageWidth: x - imageHeight: y]; - - CGColorSpaceRelease(oldColourSpace); - CGImageRelease(oldImageRef); -#endif -} - - -/* - * Switch video mode - */ - -void -OSX_monitor::switch_to_current_mode(void) -{ - video_mode mode = get_current_mode(); - const char *failure = NULL; - - D(bug("switch_to_current_mode(): width=%d height=%d depth=%d bytes_per_row=%d\n", mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row)); - - if ( display_type == DISPLAY_SCREEN && originalMode ) - { - D(NSLog(@"About to call CGDisplayBestModeForParameters()")); - newMode = CGDisplayBestModeForParameters(theDisplay, - bits_from_depth(mode.depth), - mode.x, mode.y, NULL); - if ( ! newMode ) - failure = "Could not find a matching screen mode"; - else - { - D(NSLog(@"About to call CGDisplaySwitchToMode()")); - if ( CGDisplaySwitchToMode(theDisplay, newMode) != CGDisplayNoErr ) - failure = "Could not switch to matching screen mode"; - } - - // For mouse event processing: update screen height - [output startedFullScreen: theDisplay]; - - if ( ! failure && - mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) ) - { - D(bug("Bytes per row (%d) doesn't match current (%ld)\n", - mode.bytes_per_row, CGDisplayBytesPerRow(theDisplay))); - mode.bytes_per_row = CGDisplayBytesPerRow(theDisplay); - } - - if ( ! failure && - ! ( the_buffer = CGDisplayBaseAddress(theDisplay) ) ) - failure = "Could not get base address of screen"; - - } -#ifdef CGIMAGEREF - // Clean up the old CGImageRef stuff - else if ( display_type == DISPLAY_WINDOW && imageRef ) - { - CGImageRef oldImageRef = imageRef; - CGColorSpaceRef oldColourSpace = colourSpace; - CGDataProviderRef oldProvider = provider; - void *oldBuffer = the_buffer; - - if ( video_open(mode) ) - { - CGImageRelease(oldImageRef); - CGColorSpaceRelease(oldColourSpace); - CGDataProviderRelease(oldProvider); - free(oldBuffer); - } - else - failure = "Could not video_open() requested mode"; - } -#endif - else if ( ! video_open(mode) ) - failure = "Could not video_open() requested mode"; - - if ( ! failure && display_type == DISPLAY_SCREEN ) - { - // Whenever we change screen resolution, the MacOS mouse starts - // up in the top left corner. Send real mouse to that location -// if ( CGDisplayMoveCursorToPoint(theDisplay, CGPointMake(15,15)) -// == CGDisplayNoErr ) -// { - // - [output fullscreenMouseMove]; -// } -// else -// failure = "Could move (jump) cursor on screen"; - } - - if ( failure ) - { - NSLog(@"In switch_to_current_mode():"); - NSLog(@"%s.", failure); - video_close(); - if ( display_type == DISPLAY_SCREEN ) - ErrorAlert("Cannot switch screen to selected video mode"); - else - ErrorAlert(STR_OPEN_WINDOW_ERR); - QuitEmulator(); - } - else - set_mac_frame_buffer(mode); -} - -/* - * Close down full-screen mode - * (if bringing up error alerts is unsafe while in full-screen mode) - */ - -void VideoQuitFullScreen(void) -{ -} - - -/* - * Mac VBL interrupt - */ - -void VideoInterrupt(void) -{ -} - - -// This function is called on non-threaded platforms from a timer interrupt -void VideoRefresh(void) -{ -} - - - -// Deal with a memory access signal referring to the screen. -// For now, just ignore -bool Screen_fault_handler(char *a, char *b) -{ -// NSLog(@"Got a screen fault %lx %lx", a, b); -// [output setNeedsDisplay: YES]; - return YES; -} diff --git a/BasiliskII/src/SDL/SDLMain.h b/BasiliskII/src/SDL/SDLMain.h deleted file mode 100644 index c56d90cb..00000000 --- a/BasiliskII/src/SDL/SDLMain.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#ifndef _SDLMain_h_ -#define _SDLMain_h_ - -#import - -@interface SDLMain : NSObject -@end - -#endif /* _SDLMain_h_ */ diff --git a/BasiliskII/src/SDL/SDLMain.m b/BasiliskII/src/SDL/SDLMain.m deleted file mode 100644 index 2434f81a..00000000 --- a/BasiliskII/src/SDL/SDLMain.m +++ /dev/null @@ -1,381 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#include "SDL.h" -#include "SDLMain.h" -#include /* for MAXPATHLEN */ -#include - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - const NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface NSApplication (SDLApplication) -@end - -@implementation NSApplication (SDLApplication) -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { - chdir(parentdir); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [NSApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [NSApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff --git a/BasiliskII/src/SDL/audio_sdl.cpp b/BasiliskII/src/SDL/audio_sdl.cpp index 921beb4c..85ad4c8b 100644 --- a/BasiliskII/src/SDL/audio_sdl.cpp +++ b/BasiliskII/src/SDL/audio_sdl.cpp @@ -32,10 +32,6 @@ #define DEBUG 0 #include "debug.h" -#if defined(BINCUE) -#include "bincue_unix.h" -#endif - #define MAC_MAX_VOLUME 0x0100 @@ -100,11 +96,6 @@ static bool open_sdl_audio(void) return false; } -#if defined(BINCUE) - OpenAudio_bincue(audio_spec.freq, audio_spec.format, audio_spec.channels, - audio_spec.silence); -#endif - char driver_name[32]; printf("Using SDL/%s audio output\n", SDL_AudioDriverName(driver_name, sizeof(driver_name) - 1)); silence_byte = audio_spec.silence; @@ -236,9 +227,7 @@ static void stream_func(void *arg, uint8 *stream, int stream_len) // Audio not active, play silence silence: memset(stream, silence_byte, stream_len); } -#if defined(BINCUE) - MixAudio_bincue(stream, stream_len); -#endif + } diff --git a/BasiliskII/src/SDL/video_sdl.cpp b/BasiliskII/src/SDL/video_sdl.cpp index 4ea28b72..9b2855da 100644 --- a/BasiliskII/src/SDL/video_sdl.cpp +++ b/BasiliskII/src/SDL/video_sdl.cpp @@ -48,10 +48,6 @@ #include #include -#ifdef WIN32 -#include /* alloca() */ -#endif - #include "cpu_emulation.h" #include "main.h" #include "adb.h" @@ -86,11 +82,7 @@ static int display_type = DISPLAY_WINDOW; // See enum above #endif // Constants -#ifdef WIN32 -const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes"; -#else const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; -#endif // Global variables @@ -217,43 +209,6 @@ static inline void vm_release_framebuffer(void *fb, uint32 size) } -/* - * Windows message handler - */ - -#ifdef WIN32 -#include -static WNDPROC sdl_window_proc = NULL; // Window proc used by SDL - -extern void SysMediaArrived(void); -extern void SysMediaRemoved(void); -extern HWND GetMainWindowHandle(void); - -static LRESULT CALLBACK windows_message_handler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_DEVICECHANGE: - if (wParam == DBT_DEVICEREMOVECOMPLETE) { - DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; - if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) - SysMediaRemoved(); - } - else if (wParam == DBT_DEVICEARRIVAL) { - DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; - if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) - SysMediaArrived(); - } - return 0; - - default: - if (sdl_window_proc) - return CallWindowProc(sdl_window_proc, hwnd, msg, wParam, lParam); - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} -#endif - /* * SheepShaver glue @@ -502,26 +457,9 @@ static void add_mode(int type, int width, int height, int resolution_id, int byt // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac) static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool native_byte_order) { -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING - int layout = FLAYOUT_DIRECT; - if (depth == VIDEO_DEPTH_16BIT) - layout = (screen_depth == 15) ? FLAYOUT_HOST_555 : FLAYOUT_HOST_565; - else if (depth == VIDEO_DEPTH_32BIT) - layout = (screen_depth == 24) ? FLAYOUT_HOST_888 : FLAYOUT_DIRECT; - if (native_byte_order) - MacFrameLayout = layout; - else - MacFrameLayout = FLAYOUT_DIRECT; - monitor.set_mac_frame_base(MacFrameBaseMac); - // Set variables used by UAE memory banking - const VIDEO_MODE &mode = monitor.get_current_mode(); - MacFrameBaseHost = the_buffer; - MacFrameSize = VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y; - InitFrameBufferMapping(); -#else monitor.set_mac_frame_base(Host2MacAddr(the_buffer)); -#endif + D(bug("monitor.mac_frame_base = %08x\n", monitor.get_mac_frame_base())); } @@ -934,13 +872,6 @@ bool SDL_monitor_desc::video_open(void) return false; } -#ifdef WIN32 - // Chain in a new message handler for WM_DEVICECHANGE - HWND the_window = GetMainWindowHandle(); - sdl_window_proc = (WNDPROC)GetWindowLongPtr(the_window, GWLP_WNDPROC); - SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)windows_message_handler); -#endif - // Initialize VideoRefresh function VideoRefreshInit(); @@ -1162,12 +1093,6 @@ void SDL_monitor_desc::video_close(void) { D(bug("video_close()\n")); -#ifdef WIN32 - // Remove message handler for WM_DEVICECHANGE - HWND the_window = GetMainWindowHandle(); - SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)sdl_window_proc); -#endif - // Stop redraw thread #ifndef USE_CPU_EMUL_SERVICES if (redraw_thread_active) { @@ -1489,9 +1414,7 @@ void video_set_cursor(void) // On Mac, if mouse is grabbed, SDL_ShowCursor() recenters the // mouse, we have to put it back. bool move = false; -#ifdef WIN32 - move = true; -#elif defined(__APPLE__) +#if defined(__APPLE__) move = mouse_grabbed; #endif if (move) { @@ -2095,7 +2018,7 @@ static void video_refresh_dga(void) } #ifdef ENABLE_VOSF -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING static void video_refresh_dga_vosf(void) { // Quit DGA mode if requested @@ -2158,7 +2081,7 @@ static void VideoRefreshInit(void) { // TODO: set up specialised 8bpp VideoRefresh handlers ? if (display_type == DISPLAY_SCREEN) { -#if ENABLE_VOSF && (REAL_ADDRESSING || DIRECT_ADDRESSING) +#if ENABLE_VOSF && (DIRECT_ADDRESSING) if (use_vosf) video_refresh = video_refresh_dga_vosf; else diff --git a/BasiliskII/src/MacOSX/sys_darwin.cpp b/BasiliskII/src/Unix/Darwin/sys_darwin.cpp similarity index 100% rename from BasiliskII/src/MacOSX/sys_darwin.cpp rename to BasiliskII/src/Unix/Darwin/sys_darwin.cpp diff --git a/BasiliskII/src/Unix/FreeBSD/scsi_freebsd.cpp b/BasiliskII/src/Unix/FreeBSD/scsi_freebsd.cpp deleted file mode 100644 index 556af295..00000000 --- a/BasiliskII/src/Unix/FreeBSD/scsi_freebsd.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/* - * scsi_freebsd.cpp - SCSI Manager, FreeBSD SCSI Driver implementation - * Copyright (C) 1999 Orlando Bassotto - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * History: - * 29-Jun-1999 Started - * 05-Jul-1999 Changed from array to queue removing the limit of 8 - * devices. - * Implemented old SCSI management for FreeBSD 2.x. - * (Note: This implementation hasn't been tested; - * I don't own anymore a machine with FreeBSD 2.x, - * so if something goes wrong, please mail me to - * future@mediabit.net). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CAM -#include -#include -#include -#include -#include -#include -#include -#include -#else /* !CAM */ -#include -#include -#endif /* !CAM */ - -#include "sysdeps.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "scsi.h" - -#define DEBUG 0 -#include "debug.h" - - -#undef u_int8_t -#define u_int8_t unsigned char - -typedef struct _SCSIDevice { - int controller; // SCSI Controller - int controller_bus; // SCSI Controller Bus - char controller_name[33]; // SCSI Controller name - int mac_unit; // Macintosh SCSI ID (remapped) - int faked_controller; // "Faked" SCSI Controller (Always 0) - int faked_unit; // "Faked" SCSI ID - int unit; // Real SCSI ID - int lun; // Real SCSI LUN - u_int8_t vendor[16]; // SCSI Vendor - u_int8_t product[48]; // SCSI Product - u_int8_t revision[16]; // SCSI Revision - char device[33]; // SCSI Device -#ifdef CAM - char pass_device[33]; // SCSI Pass Device -#else /* !CAM */ - int dev_fd; // Device File Descriptor -#endif /* !CAM */ - void* dev_ptr; // Pointer to CAM/SCSI structure - bool enabled; // Device enabled ? - struct _SCSIDevice* next; // Pointer to the next device -} SCSIDevice; - -static int nDevices = 0; -static SCSIDevice* Devices = NULL; - -static uint32 buffer_size; -static uint8* buffer = NULL; - -static uint8 the_cmd[12]; -static int the_cmd_len; - -static SCSIDevice* CurrentDevice = NULL; - -inline static SCSIDevice* _GetSCSIDeviceByID(int id) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->faked_unit==id) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _GetSCSIDeviceByIDLUN(int id, int lun) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->faked_unit==id&&aux->lun==lun) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _GetSCSIDeviceByMacID(int id) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->mac_unit==id) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _GetSCSIDeviceByMacIDLUN(int id, int lun) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->mac_unit==id&&aux->lun==lun) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _AllocNewDevice() -{ - SCSIDevice* aux; - - aux = new SCSIDevice; - if(aux==NULL) return NULL; - memset(aux, 0, sizeof(SCSIDevice)); - aux->next = Devices; - Devices = aux; - return aux; -} - -#ifdef CAM -inline static struct cam_device* _GetCurrentSCSIDevice() -{ - if(CurrentDevice==NULL) return NULL; - - return (struct cam_device*)CurrentDevice->dev_ptr; -} -#else /* !CAM */ -inline static struct scsireq* _GetCurrentSCSIDevice() -{ - if(CurrentDevice==NULL) return NULL; - - return (struct scsireq*)CurrentDevice->dev_ptr; -} -#endif /* !CAM */ - -/* - * _Build_SCSI_Controller() - * - * This function builds a virtual SCSI Controller (Controller=0) - * where keeps all the devices found, this is due the fact - * I have two SCSI controllers in my PC. :-) - * Use scsidump in contrib/ to see how is remapped your - * SCSI device (only if you have more than one controller, - * that's for sure :-). - * If you have only one controller, remapping does not take act. - */ - -#define GET_FREE_ID(id) \ - { \ - for(int x=0;x<32;x++) { \ - if(!(busyIDs&(1<<(x+1)))) { \ - id = x; \ - break; \ - } \ - } \ - } - -static void _Build_SCSI_Controller() -{ - unsigned int id = 0; - unsigned long long busyIDs = 0x0ll; - SCSIDevice* aux, * dev; - - // What IDs are busy? - dev = Devices; - while(dev) { - dev->enabled = false; - dev->faked_controller = 0; - dev->faked_unit = dev->unit; - busyIDs |= (1 << (dev->unit+1)); - dev = dev->next; - } - - // Find out the duplicate IDs and remap them - dev = Devices, aux = NULL; - while(dev) { - aux = dev; - while(aux) { - SCSIDevice* dev1, * dev2; - - dev1 = dev, dev2 = aux; - - if(dev1->controller!=dev2->controller&& - dev1->unit==dev2->unit) { - int free_id; - GET_FREE_ID(free_id); - busyIDs |= (1<<(free_id+1)); - dev1->faked_unit = free_id; - } - aux = aux->next; - } - dev = dev->next; - } - - // Now reorder the queue -#if 0 - dev = Devices; - while(dev) { - aux = dev; - while(aux) { - SCSIDevice* dev1, * dev2; - - dev1 = dev, dev2 = aux; - if(dev1->faked_unit>dev2->faked_unit) { - SCSIDevice tmp; - - memcpy(&tmp, dev1, sizeof(SCSIDevice)); - memcpy(dev1, dev2, sizeof(SCSIDevice)); - memcpy(dev2, &tmp, sizeof(SCSIDevice)); - } - aux = aux->next; - } - dev = dev->next; - } -#endif - - // Now open the selected SCSI devices :-) - for(int n=0;n<8;n++) { - char tmp[25]; - - snprintf(tmp, sizeof(tmp), "scsi%d", n); - const char* scsi = PrefsFindString(tmp); - if(scsi) { - int id, lun; - - // The format is: RemappedID (or FakedID)/LUN - sscanf(scsi, "%d/%d", &id, &lun); - - SCSIDevice* dev = _GetSCSIDeviceByIDLUN(id, lun); - if(dev==NULL) continue; - dev->enabled = true; - dev->mac_unit = n; - -#ifdef CAM - struct cam_device* cam; - - cam = cam_open_btl(dev->controller, - dev->unit, - dev->lun, O_RDWR, NULL); - if(cam==NULL) { - fprintf(stderr, "Failed to open %d:%d:%d = %s!!!\n", - dev->controller, dev->unit, dev->lun, - cam_errbuf); - } - dev->dev_ptr = (void*)cam; -#else /* !CAM */ - dev->dev_fd = scsi_open(dev->device, O_RDWR); - if(dev->dev_fd<0) { - perror("Failed to open %d:%d:%d"); - } - else { - dev->dev_ptr = (void*)scsireq_new(); - } -#endif /* !CAM */ - } - } -} - - -/* - * Initialization - */ - -void SCSIInit(void) -{ - // Finds the SCSI hosts in the system filling the SCSIDevices queue. - // "Stolen" from camcontrol.c - // Copyright (C) 1997-99 Kenneth D. Merry - // Old SCSI detection "stolen" from scsi.c - // Copyright (C) 1993 Julian Elischer - // - int bufsize, fd; - int need_close = 0; - int error = 0; - int skip_device = 0; - SCSIDevice* Dev, * dev, * PrevDev = NULL; - - nDevices = 0; - - if(PrefsFindBool("noscsi")) - goto no_scsi; - -#ifdef CAM - union ccb ccb; - if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { - fprintf(stderr, "WARNING: Cannot open CAM device %s (%s)\n", XPT_DEVICE, strerror(errno)); - goto no_scsi; - } - - memset(&(&ccb.ccb_h)[1], 0, sizeof(struct ccb_dev_match)-sizeof(struct ccb_hdr)); - ccb.ccb_h.func_code = XPT_DEV_MATCH; - bufsize = sizeof(struct dev_match_result) * 100; - ccb.cdm.match_buf_len = bufsize; - ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); - ccb.cdm.num_matches = 0; - - ccb.cdm.num_patterns = 0; - ccb.cdm.pattern_buf_len = 0; - - do { - Dev = _AllocNewDevice(); - if(ioctl(fd, CAMIOCOMMAND, &ccb)==-1) { - fprintf(stderr, "Error sending CAMIOCOMMAND ioctl\n"); - return; - } - - if((ccb.ccb_h.status != CAM_REQ_CMP) - || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) - && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { - fprintf(stderr, "Got CAM error %#x, CDM error %d\n", - ccb.ccb_h.status, ccb.cdm.status); - return; - } - - char current_controller_name[33]; - int current_controller = -1; - for(int i=0;ipath_id==-1) break; - Dev->controller = bus_result->path_id; - snprintf(Dev->controller_name, sizeof(Dev->controller_name), "%s%d", - bus_result->dev_name, - bus_result->unit_number); - strncpy(current_controller_name, Dev->controller_name, sizeof(current_controller_name)); - current_controller = Dev->controller; - Dev->controller_bus = bus_result->bus_id; - break; - } - case DEV_MATCH_DEVICE: - { - struct device_match_result* dev_result; - char tmpstr[256]; - - dev_result = &ccb.cdm.matches[i].result.device_result; - if(current_controller==-1||dev_result->target_id==-1) { - skip_device = 1; - break; - } - else skip_device = 0; - - cam_strvis(Dev->vendor, (u_int8_t*)dev_result->inq_data.vendor, - sizeof(dev_result->inq_data.vendor), - sizeof(Dev->vendor)); - cam_strvis(Dev->product, (u_int8_t*)dev_result->inq_data.product, - sizeof(dev_result->inq_data.product), - sizeof(Dev->product)); - cam_strvis(Dev->revision, (u_int8_t*)dev_result->inq_data.revision, - sizeof(dev_result->inq_data.revision), - sizeof(Dev->revision)); - strncpy(Dev->controller_name, current_controller_name, sizeof(Dev->controller_name)); - Dev->controller = current_controller; - Dev->unit = dev_result->target_id; - Dev->lun = dev_result->target_lun; - break; - } - case DEV_MATCH_PERIPH: - { - struct periph_match_result* periph_result; - - periph_result = &ccb.cdm.matches[i].result.periph_result; - - if(skip_device != 0) break; - - if(need_close==1) { - snprintf(Dev->device, sizeof(Dev->device), "%s%d*", - periph_result->periph_name, - periph_result->unit_number); - need_close = 0; - } - else if(need_close==0) { - snprintf(Dev->pass_device, sizeof(Dev->pass_device), "%s%d", - periph_result->periph_name, - periph_result->unit_number); - need_close++; - break; - } - else { - need_close = 0; - } - PrevDev = Dev; - Dev = _AllocNewDevice(); - break; - } - } - } - } while (ccb.ccb_h.status == CAM_REQ_CMP - && ccb.cdm.status == CAM_DEV_MATCH_MORE); - - /* Remove last one (ugly coding) */ - Devices = PrevDev; - delete Dev; -end_loop: - close(fd); -#else /* !CAM */ - /* - * FreeBSD 2.x SCSI management is quiet different and - * unfortunatly not flexible as CAM library in FreeBSD 3.x... - * I probe only the first bus, LUN 0, and the - * first 8 devices only. - */ - u_char* inq_buf; - scsireq_t* scsireq; - struct scsi_addr scsi; - int ssc_fd; - - if((ssc_fd=open("/dev/ssc", O_RDWR))==-1) { - fprintf(stderr, "Cannot open SCSI manager: /dev/ssc\n"); - SCSIReset(); - return; - } - - inq_buf = (u_char*)malloc(96); - if(inq_buf==NULL) { - perror("malloc failed"); - SCSIReset(); - return; - } - - scsireq = scsireq_build((scsireq_t*)dev->dev_ptr, - 96, inq_buf, SCCMD_READ, - "12 0 0 0 v 0", 96); - - addr.scbus = 0; - addr.lun = 0; - - for(int n=0;n<8;n++) { - addr.target = n; - - if(ioctl(ssc_fd, SCIOCADDR, &addr) != -1) { - Dev = _AllocNewDevice(); - Dev->controller = addr.scbus; - Dev->lun = addr.lun; - Dev->unit = addr.target; - - struct scsi_devinfo devInfo; - devInfo.addr = addr; - if(ioctl(ssc_fd, SCIOCGETDEVINFO, &devInfo) != -1) { - strncpy(Dev->device, devInfo.devname, sizeof(Dev->device)); - } - strncpy(Dev->controller_name, "FreeBSD 2.x SCSI Manager", sizeof(Dev->controller_name)); - if(scsireq_enter(ssc_fd, scsireq)!=-1) { - Dev->vendor[sizeof(Dev->vendor)-1] = 0; - Dev->product[sizeof(Dev->product)-1] = 0; - Dev->revision[sizeof(Dev->revision)-1] = 0; - - scsireq_decode(scsireq, "s8 c8 c16 c4", - Dev->vendor, Dev->product, Dev->revision); - } - } - } - free(inq_buf); - close(ssc_fd); -#endif /* !CAM */ - _Build_SCSI_Controller(); - - // Print out the periph with ID:LUNs - fprintf(stderr, "Device RealID FkdID MacID Enabled\n"); - fprintf(stderr, "-------------------------------------------------------------\n"); - // 012345678901234567890123456789012 0:0:0 0/0 0:0 Yes - dev = Devices; - while(dev) { - char tmp[40]; - snprintf(tmp, sizeof(tmp), "%s %s %s", - dev->vendor, - dev->product, - dev->revision); - fprintf(stderr, "%-33s %d:%d:%d %d/%d %d:%d %s\n", - tmp, dev->controller, dev->unit, dev->lun, - dev->faked_unit, dev->lun, - dev->mac_unit, dev->lun, dev->enabled?"Yes":"No"); - dev = dev->next; - } - -no_scsi: - // Reset SCSI bus - SCSIReset(); -} - - -/* - * Deinitialization - */ - -void SCSIExit(void) -{ - SCSIDevice* aux; - while(Devices) { - aux = Devices->next; - if(Devices->dev_ptr!=NULL) { -#ifdef CAM - cam_close_device((struct cam_device*)Devices->dev_ptr); -#else /* !CAM */ - free(Devices->dev_ptr); // Is this right? - close(Devices->dev_fd); // And this one? -#endif /* !CAM */ - } - delete Devices; - Devices = aux; - } - nDevices = 0; -} - - -/* - * Set SCSI command to be sent by scsi_send_cmd() - */ - -void scsi_set_cmd(int cmd_length, uint8 *cmd) -{ - the_cmd_len = cmd_length; - memset(the_cmd, 0, sizeof(the_cmd)); - memcpy(the_cmd, cmd, the_cmd_len); -} - - -/* - * Check for presence of SCSI target - */ - -bool scsi_is_target_present(int id) -{ - return (_GetSCSIDeviceByMacID(id)!=NULL&&_GetSCSIDeviceByMacID(id)->enabled); -} - - -/* - * Set SCSI target (returns false on error) - */ - -bool scsi_set_target(int id, int lun) -{ - SCSIDevice* dev; - - dev = _GetSCSIDeviceByMacIDLUN(id, lun); - if(dev==NULL) return false; - CurrentDevice = dev; - return true; -} - - -/* - * Send SCSI command to active target (scsi_set_command() must have been called), - * read/write data according to S/G table (returns false on error) - */ - -static bool try_buffer(int size) -{ - if(size <= buffer_size) { - return true; - } - - D(bug("Allocating buffer of %d bytes.\n", size)); - uint8* new_buffer = (uint8*)valloc(size); - if(new_buffer==NULL) { - return false; - } - if(buffer!=NULL) free(buffer); - buffer = new_buffer; - buffer_size = size; - return true; -} - -bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout) -{ - int value = 0; -#ifdef CAM -#ifdef VERBOSE_CAM_DEBUG - D(bug("Sending command %x (len=%d) to SCSI Device %d:%d:%d\n", the_cmd[0], - the_cmd_len, - CurrentDevice->controller, - CurrentDevice->unit, - CurrentDevice->lun)); - D(bug("DataLength: %d\n", data_length)); - D(bug("Reading: %d\n", reading)); - D(bug("SG Size: %d\n", sg_size)); - D(bug("Timeout: %d\n", timeout)); -#endif /* VERBOSE_CAM_DEBUG */ -#endif /* CAM */ - if(!try_buffer(data_length)) { - char str[256]; - sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length); - ErrorAlert(str); - return false; - } - - if(!reading) { - uint8* buffer_ptr = buffer; - for(int i=0;i0) { - dir_flags = reading?CAM_DIR_IN:CAM_DIR_OUT; - } - - ccb.ccb_h.path_id = CurrentDevice->controller; - ccb.ccb_h.target_id = CurrentDevice->unit; - ccb.ccb_h.target_lun = CurrentDevice->lun; - - cam_fill_csio(&ccb.csio, - 0, - NULL, - dir_flags, - MSG_SIMPLE_Q_TAG, - (u_int8_t*)buffer, - data_length, - SSD_FULL_SIZE, - the_cmd_len, - (timeout?timeout:50)*1000); - - ccb.ccb_h.flags |= CAM_DEV_QFRZDIS; - - memcpy(ccb.csio.cdb_io.cdb_bytes, the_cmd, the_cmd_len); - - if(cam_send_ccb(device, &ccb)<0) { - fprintf(stderr, "%d:%d:%d ", CurrentDevice->controller, - CurrentDevice->unit, CurrentDevice->lun); - perror("cam_send_ccb"); - return false; - } - - value = ccb.ccb_h.status; - *stat = ccb.csio.scsi_status; - - if((value & CAM_STATUS_MASK) != CAM_REQ_CMP) { - char tmp[4096]; - if((value & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { - scsi_sense_string(device, &ccb.csio, tmp, sizeof(tmp)); - fprintf(stderr, "SCSI Status Error:\n%s\n", tmp); - return false; - } - } -#else /* !CAM */ - struct scsireq* scsireq = _GetCurrentSCSIDevice(); - if(device==NULL) return false; - - int dir_flags = 0x00; - if(data_length>0) dir_flags = reading?SCCMD_READ:SCCMD_WRITE; - - scsireq_reset(scsireq); - scsireq->timeout = (timeout?timeout:50)*1000; - scsireq_build(scsireq, data_length, - (caddr_t)buffer, dir_flags, - "0"); - memcpy(scsireq->cmd, the_cmd, scsireq->cmdlen = the_cmd_len); - - int result = scsi_enter(dev->dev_fd, scsireq); - if(SCSIREQ_ERROR(result)) { - scsi_debug(stderr, result, scsireq); - } - *stat = scsireq->status; -#endif /* !CAM */ - - if(reading) { - uint8* buffer_ptr = buffer; - for(int i=0;i -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CAM -#include -#include -#include -#include -#include -#include -#include -#include -#else /* !CAM */ -#include -#include -#endif /* !CAM */ - -#undef u_int8_t -#define u_int8_t unsigned char - -typedef struct _SCSIDevice { - int controller; // SCSI Controller - int controller_bus; // SCSI Controller Bus - char controller_name[33]; // SCSI Controller name - int mac_unit; // Macintosh SCSI ID (remapped) - int faked_controller; // "Faked" SCSI Controller (Always 0) - int faked_unit; // "Faked" SCSI ID - int unit; // Real SCSI ID - int lun; // Real SCSI LUN - u_int8_t vendor[16]; // SCSI Vendor - u_int8_t product[48]; // SCSI Product - u_int8_t revision[16]; // SCSI Revision - char device[33]; // SCSI Device -#ifdef CAM - char pass_device[33]; // SCSI Pass Device -#else /* !CAM */ - int dev_fd; // Device File Descriptor -#endif /* !CAM */ - void* dev_ptr; // Pointer to CAM/SCSI structure - bool enabled; // Device enabled ? - struct _SCSIDevice* next; // Pointer to the next device -} SCSIDevice; - -static int nDevices = 0; -static SCSIDevice* Devices = NULL; - -inline static SCSIDevice* _GetSCSIDeviceByID(int id) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->faked_unit==id) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _GetSCSIDeviceByIDLUN(int id, int lun) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->faked_unit==id&&aux->lun==lun) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _GetSCSIDeviceByMacID(int id) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->mac_unit==id) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _GetSCSIDeviceByMacIDLUN(int id, int lun) -{ - SCSIDevice* aux = Devices; - while(aux) { - if(aux->mac_unit==id&&aux->lun==lun) { - return aux; - } - aux = aux->next; - } - return NULL; -} - -inline static SCSIDevice* _AllocNewDevice() -{ - SCSIDevice* aux; - - aux = new SCSIDevice; - if(aux==NULL) return NULL; - memset(aux, 0, sizeof(SCSIDevice)); - aux->next = Devices; - Devices = aux; - return aux; -} - -/* - * _Build_SCSI_Controller() - * - * This function builds a virtual SCSI Controller (Controller=0) - * where keeps all the devices found, this is due the fact - * I have two SCSI controllers in my PC. :-) - * Use FreeBSD-SCSIDump in contrib/ to see how is remapped your - * SCSI device (only if you have more than one controller, - * that's for sure :-). - */ - -#define GET_FREE_ID(id) \ - { \ - for(int x=0;x<32;x++) { \ - if(!(busyIDs&(1<<(x+1)))) { \ - id = x; \ - break; \ - } \ - } \ - } - -static void _Build_SCSI_Controller() -{ - unsigned int id = 0; - unsigned long long busyIDs = 0x0ll; - SCSIDevice* aux, * dev; - - // What IDs are busy? - dev = Devices; - while(dev) { - dev->enabled = false; - dev->faked_controller = 0; - dev->faked_unit = dev->unit; - busyIDs |= (1 << (dev->unit+1)); - dev = dev->next; - } - - // Find out the duplicate IDs and change them - dev = Devices, aux = NULL; - while(dev) { - aux = dev; - while(aux) { - SCSIDevice* dev1, * dev2; - - dev1 = dev, dev2 = aux; - - if(dev1->controller!=dev2->controller&& - dev1->unit==dev2->unit) { - int free_id; - GET_FREE_ID(free_id); - busyIDs |= (1<<(free_id+1)); - dev1->faked_unit = free_id; - } - aux = aux->next; - } - dev = dev->next; - } - - // Now reorder the queue - dev = Devices; - while(dev) { - aux = dev; - while(aux) { - SCSIDevice* dev1, * dev2; - - dev1 = dev, dev2 = aux; -/* - if(dev1->faked_unit>dev2->faked_unit) { - SCSIDevice tmp; - - memcpy(&tmp, dev1, sizeof(SCSIDevice)); - memcpy(dev1, dev2, sizeof(SCSIDevice)); - memcpy(dev2, &tmp, sizeof(SCSIDevice)); - } - */ - aux = aux->next; - } - dev = dev->next; - } -} - -#define SCSIReset() - -/* - * Initialization - */ - -void SCSIInit(void) -{ - // Find the SCSI hosts in the system - // Filling out the SCSIDevices queue. - // Stolen from camcontrol.c - int bufsize, fd; - int need_close = 0; - int error = 0; - int skip_device = 0; - SCSIDevice* Dev, * dev, * PrevDev = NULL; - - nDevices = 0; - -#ifdef CAM - union ccb ccb; - - if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { - fprintf(stderr, "Cannot open CAM device: %s\n", XPT_DEVICE); - goto no_scsi; - } - - memset(&(&ccb.ccb_h)[1], 0, sizeof(struct ccb_dev_match)-sizeof(struct ccb_hdr)); - ccb.ccb_h.func_code = XPT_DEV_MATCH; - bufsize = sizeof(struct dev_match_result) * 100; - ccb.cdm.match_buf_len = bufsize; - ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); - ccb.cdm.num_matches = 0; - - ccb.cdm.num_patterns = 0; - ccb.cdm.pattern_buf_len = 0; - - do { - Dev = _AllocNewDevice(); - if(ioctl(fd, CAMIOCOMMAND, &ccb)==-1) { - fprintf(stderr, "Error sending CAMIOCOMMAND ioctl\n"); - return; - } - - if((ccb.ccb_h.status != CAM_REQ_CMP) - || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) - && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { - fprintf(stderr, "Got CAM error %#x, CDM error %d\n", - ccb.ccb_h.status, ccb.cdm.status); - return; - } - - char current_controller_name[33]; - int current_controller = -1; - for(int i=0;ipath_id==-1) break; - Dev->controller = bus_result->path_id; - snprintf(Dev->controller_name, sizeof(Dev->controller_name), "%s%d", - bus_result->dev_name, - bus_result->unit_number); - strncpy(current_controller_name, Dev->controller_name, sizeof(current_controller_name)); - current_controller = Dev->controller; - Dev->controller_bus = bus_result->bus_id; - break; - } - case DEV_MATCH_DEVICE: - { - struct device_match_result* dev_result; - char tmpstr[256]; - - dev_result = &ccb.cdm.matches[i].result.device_result; - if(current_controller==-1||dev_result->target_id==-1) { - skip_device = 1; - break; - } - else skip_device = 0; - - cam_strvis(Dev->vendor, (u_int8_t*)dev_result->inq_data.vendor, - sizeof(dev_result->inq_data.vendor), - sizeof(Dev->vendor)); - cam_strvis(Dev->product, (u_int8_t*)dev_result->inq_data.product, - sizeof(dev_result->inq_data.product), - sizeof(Dev->product)); - cam_strvis(Dev->revision, (u_int8_t*)dev_result->inq_data.revision, - sizeof(dev_result->inq_data.revision), - sizeof(Dev->revision)); - strncpy(Dev->controller_name, current_controller_name, sizeof(Dev->controller_name)); - Dev->controller = current_controller; - Dev->unit = dev_result->target_id; - Dev->lun = dev_result->target_lun; - break; - } - case DEV_MATCH_PERIPH: - { - struct periph_match_result* periph_result; - - periph_result = &ccb.cdm.matches[i].result.periph_result; - - if(skip_device != 0) break; - - if(need_close==1) { - snprintf(Dev->device, sizeof(Dev->device), "%s%d*", - periph_result->periph_name, - periph_result->unit_number); - need_close = 0; - } - else if(need_close==0) { - snprintf(Dev->pass_device, sizeof(Dev->pass_device), "%s%d", - periph_result->periph_name, - periph_result->unit_number); - need_close++; - break; - } - else { - need_close = 0; - } - PrevDev = Dev; - Dev = _AllocNewDevice(); - break; - } - } - } - } while (ccb.ccb_h.status == CAM_REQ_CMP - && ccb.cdm.status == CAM_DEV_MATCH_MORE); - - /* Remove last one (ugly coding) */ - Devices = PrevDev; - delete Dev; -end_loop: - close(fd); -#else /* !CAM */ - /* - * FreeBSD 2.x SCSI management is quiet different and - * unfortunatly not flexible as CAM library in FreeBSD 3.x... - * I only scan for the first bus, LUN 0, and the - * first 8 devices only. - */ - u_char* inq_buf; - scsireq_t* scsireq; - struct scsi_addr scsi; - int ssc_fd; - - if((ssc_fd=open("/dev/ssc", O_RDWR))==-1) { - fprintf(stderr, "Cannot open SCSI manager: /dev/ssc\n"); - SCSIReset(); - return; - } - - inq_buf = (u_char*)malloc(96); - if(inq_buf==NULL) { - perror("malloc failed"); - SCSIReset(); - return; - } - - scsireq = scsireq_build((scsireq_t*)dev->dev_ptr, - 96, inq_buf, SCCMD_READ, - "12 0 0 0 v 0", 96); - - addr.scbus = 0; - addr.lun = 0; - - for(int n=0;n<8;n++) { - addr.target = n; - - if(ioctl(ssc_fd, SCIOCADDR, &addr) != -1) { - Dev = _AllocNewDevice(); - Dev->controller = addr.scbus; - Dev->lun = addr.lun; - Dev->unit = addr.target; - - struct scsi_devinfo devInfo; - devInfo.addr = addr; - if(ioctl(ssc_fd, SCIOCGETDEVINFO, &devInfo) != -1) { - strncpy(Dev->device, devInfo.devname, sizeof(Dev->device)); - } - strncpy(Dev->controller_name, "FreeBSD 2.x SCSI Manager", sizeof(Dev->controller_name)); - if(scsireq_enter(ssc_fd, scsireq)!=-1) { - Dev->vendor[sizeof(Dev->vendor)-1] = 0; - Dev->product[sizeof(Dev->product)-1] = 0; - Dev->revision[sizeof(Dev->revision)-1] = 0; - - scsireq_decode(scsireq, "s8 c8 c16 c4", - Dev->vendor, Dev->product, Dev->revision); - } - } - } - free(inq_buf); - close(ssc_fd); -#endif /* !CAM */ - _Build_SCSI_Controller(); - - // Print out the periph with ID:LUNs - fprintf(stderr, "Device RealID FkdID\n"); - fprintf(stderr, "----------------------------------------------\n"); - // 012345678901234567890123456789012 0:0:0 0/0 - dev = Devices; - while(dev) { - char tmp[40]; - snprintf(tmp, sizeof(tmp), "%s %s %s", - dev->vendor, - dev->product, - dev->revision); - fprintf(stderr, "%-33s %d:%d:%d %d/%d\n", - tmp, dev->controller, dev->unit, dev->lun, - dev->faked_unit, dev->lun); - dev = dev->next; - } - -no_scsi: - // Reset SCSI bus - SCSIReset(); -} - - -/* - * Deinitialization - */ - -void SCSIExit(void) -{ - SCSIDevice* aux; - while(Devices) { - aux = Devices->next; - if(Devices->dev_ptr!=NULL) { -#ifdef CAM - cam_close_device((struct cam_device*)Devices->dev_ptr); -#else /* !CAM */ - free(Devices->dev_ptr); // Is this right? - close(Devices->dev_fd); // And this one? -#endif /* !CAM */ - } - delete Devices; - Devices = aux; - } - nDevices = 0; -} - -int main() -{ - SCSIInit(); - SCSIExit(); - return 0; -} diff --git a/BasiliskII/src/Unix/Irix/README.networking b/BasiliskII/src/Unix/Irix/README.networking deleted file mode 100644 index f6145a71..00000000 --- a/BasiliskII/src/Unix/Irix/README.networking +++ /dev/null @@ -1,110 +0,0 @@ -README file for networking under IRIX -by Brian J. Johnson 7/23/2002 -version 1.0 -================================================== - -BasiliskII does not currently support networking natively on IRIX. -That is, the emulated Ethernet card does not do anything. There's no -reason one couldn't use raw domain sockets and the snoop(7p) facility -to do networking, but so far no one has written the required glue -code. - -However, it is possible to do TCP/IP networking with BasiliskII on -IRIX via PPP, by connecting an emulated serial port to the IRIX PPP -daemon. Here are the steps to set it up: - - -Set up PPP on IRIX ------------------- - -You need root privileges to do this. - -First, make sure you have eoe.sw.ppp and eoe.sw.uucp installed: - - IRIS# versions eoe.sw.ppp eoe.sw.uucp - I = Installed, R = Removed - - Name Date Description - - I eoe 07/22/2002 IRIX Execution Environment, 6.5.17m - I eoe.sw 07/22/2002 IRIX Execution Environment Software - I eoe.sw.ppp 07/22/2002 Point-to-Point Protocol Software - I eoe.sw.uucp 07/22/2002 UUCP Utilities - -If they aren't installed, install them from your distribution CDs. - -Next, pick IP addresses for the IRIX and MacOS sides of the PPP -connection. You may want to ask your local network administrator -about this, but any two unused addresses on your local subnet should -work. - -Edit /etc/ppp.conf and add these three lines: - -_NET_INCOMING - remotehost= - localhost= - -(Replace the angle brackets and the text in them with the appropriate -IP addresses.) - -Next, make a script to set up the environment properly when invoking -pppd from BasiliskII. You can name this whatever you want; I chose -/usr/etc/ppp-b2: - -IRIS# whoami -root -IRIS# cat < /usr/etc/ppp-b2 -#!/bin/sh -export USER=_NET_INCOMING -exec /usr/etc/ppp "$@" -IRIS# chmod 4775 /usr/etc/ppp-b2 - -Rewrite this in perl or python or C or whatever if you don't like -setuid shell scripts. The alternative is to run BasiliskII as root: -pppd _must_ be run as root. - - -Configure BasiliskII to start the PPP daemon --------------------------------------------- - -Start up BasiliskII, and in the serial devices tab, enter: - - |exec /usr/etc/ppp-b2 - -Supply the name you used for the script you created. Be sure to -include the leading pipe symbol ("|"). - -The "exec" causes your PPP startup script to replace the shell -BasiliskII runs to interpret the command. It's not strictly -necessary, but cuts down on the number of extra processes hanging -about. - - -Install a PPP client on MacOS ------------------------------ - -The details of this step will vary depending on your PPP client -software. Set it up for a "direct" connection, with no modem chatting -or login scripting. For instance, with FreePPP I set the "Connect:" -item on the "Edit..." screen under the "Accounts" tab to "Directly". -Be sure to select the correct serial port. The serial port speed -shouldn't matter (BasiliskII ignores it), but I set it to 115200 bps. - -Next, configure MacOS's TCP/IP stack. If you're using Open Transport, -Open the TCP/IP control panel and select "Using PPP Server" under the -"Configure" item. Copy IRIX's DNS client info. from /etc/resolv.conf -to the control panel: the addresses from the "nameserver" lines go in -the "Name server addr.:" box, and the domains from the "search" lines -go in the "Search domains:" box. The steps should be similar for -MacTCP. - -Now fire up PPP. Your PPP client should establish communication with -the IRIX PPP daemon, and you're off and running. - - -Disclaimer ----------- - -I haven't tried this procedure from scratch on a freshly installed -system, so I might have missed a step somewhere. But it should get -you close.... diff --git a/BasiliskII/src/Unix/Irix/audio_irix.cpp b/BasiliskII/src/Unix/Irix/audio_irix.cpp deleted file mode 100644 index ebd8eb69..00000000 --- a/BasiliskII/src/Unix/Irix/audio_irix.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* - * audio_irix.cpp - Audio support, SGI Irix implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "audio.h" -#include "audio_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -// The currently selected audio parameters (indices in audio_sample_rates[] -// etc. vectors) -static int audio_sample_rate_index = 0; -static int audio_sample_size_index = 0; -static int audio_channel_count_index = 0; - -// Global variables -static int audio_fd = -1; // fd from audio library -static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read -static bool sem_inited = false; // Flag: audio_irq_done_sem initialized -static int sound_buffer_size; // Size of sound buffer in bytes -static int sound_buffer_fill_point; // Fill buffer when this many frames are empty -static uint8 silence_byte = 0; // Byte value to use to fill sound buffers with silence -static pthread_t stream_thread; // Audio streaming thread -static pthread_attr_t stream_thread_attr; // Streaming thread attributes -static bool stream_thread_active = false; // Flag: streaming thread installed -static volatile bool stream_thread_cancel = false; // Flag: cancel streaming thread - -static bool current_main_mute = false; // Flag: output muted -static bool current_speaker_mute = false; // Flag: speaker muted -static uint32 current_main_volume = 0; // Output volume -static uint32 current_speaker_volume = 0; // Speaker volume - -// IRIX libaudio control structures -static ALconfig config; -static ALport port; - - -// Prototypes -static void *stream_func(void *arg); -static uint32 read_volume(void); -static bool read_mute(void); -static void set_mute(bool mute); - - -/* - * Initialization - */ - -// Set AudioStatus to reflect current audio stream format -static void set_audio_status_format(void) -{ - AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index]; - AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index]; - AudioStatus.channels = audio_channel_counts[audio_channel_count_index]; -} - -bool open_audio(void) -{ - ALpv pv[2]; - - printf("Using libaudio audio output\n"); - - // Get supported sample formats - - if (audio_sample_sizes.empty()) { - // All sample sizes are supported - audio_sample_sizes.push_back(8); - audio_sample_sizes.push_back(16); - - // Assume at least two channels are supported. Some IRIX boxes - // can do 4 or more... MacOS only handles up to 2. - audio_channel_counts.push_back(1); - audio_channel_counts.push_back(2); - - if (audio_sample_sizes.empty() || audio_channel_counts.empty()) { - WarningAlert(GetString(STR_AUDIO_FORMAT_WARN)); - alClosePort(port); - audio_fd = -1; - return false; - } - - audio_sample_rates.push_back( 8000 << 16); - audio_sample_rates.push_back(11025 << 16); - audio_sample_rates.push_back(22050 << 16); - audio_sample_rates.push_back(44100 << 16); - - // Default to highest supported values - audio_sample_rate_index = audio_sample_rates.size() - 1; - audio_sample_size_index = audio_sample_sizes.size() - 1; - audio_channel_count_index = audio_channel_counts.size() - 1; - } - - // Set the sample format - - D(bug("Size %d, channels %d, rate %d\n", - audio_sample_sizes[audio_sample_size_index], - audio_channel_counts[audio_channel_count_index], - audio_sample_rates[audio_sample_rate_index] >> 16)); - config = alNewConfig(); - alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP); - if (audio_sample_sizes[audio_sample_size_index] == 8) { - alSetWidth(config, AL_SAMPLE_8); - } - else { - alSetWidth(config, AL_SAMPLE_16); - } - alSetChannels(config, audio_channel_counts[audio_channel_count_index]); - alSetDevice(config, AL_DEFAULT_OUTPUT); // Allow selecting via prefs? - - // Try to open the audio library - - port = alOpenPort("BasiliskII", "w", config); - if (port == NULL) { - fprintf(stderr, "ERROR: Cannot open audio port: %s\n", - alGetErrorString(oserror())); - WarningAlert(GetString(STR_NO_AUDIO_WARN)); - return false; - } - - // Set the sample rate - - pv[0].param = AL_RATE; - pv[0].value.ll = alDoubleToFixed(audio_sample_rates[audio_sample_rate_index] >> 16); - pv[1].param = AL_MASTER_CLOCK; - pv[1].value.i = AL_CRYSTAL_MCLK_TYPE; - if (alSetParams(AL_DEFAULT_OUTPUT, pv, 2) < 0) { - fprintf(stderr, "ERROR: libaudio setparams failed: %s\n", - alGetErrorString(oserror())); - alClosePort(port); - return false; - } - - // Compute sound buffer size and libaudio refill point - - config = alGetConfig(port); - audio_frames_per_block = alGetQueueSize(config); - if (audio_frames_per_block < 0) { - fprintf(stderr, "ERROR: couldn't get queue size: %s\n", - alGetErrorString(oserror())); - alClosePort(port); - return false; - } - D(bug("alGetQueueSize %d, width %d, channels %d\n", - audio_frames_per_block, - alGetWidth(config), - alGetChannels(config))); - - // Put a limit on the Mac sound buffer size, to decrease delay -#define AUDIO_BUFFER_MSEC 50 // milliseconds of sound to buffer - int target_frames_per_block = - (audio_sample_rates[audio_sample_rate_index] >> 16) * - AUDIO_BUFFER_MSEC / 1000; - if (audio_frames_per_block > target_frames_per_block) - audio_frames_per_block = target_frames_per_block; - D(bug("frames per block %d\n", audio_frames_per_block)); - - alZeroFrames(port, audio_frames_per_block); // so we don't underflow - - // Try to keep the buffer pretty full - sound_buffer_fill_point = alGetQueueSize(config) - - 2 * audio_frames_per_block; - if (sound_buffer_fill_point < 0) - sound_buffer_fill_point = alGetQueueSize(config) / 3; - D(bug("fill point %d\n", sound_buffer_fill_point)); - - sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) * - audio_channel_counts[audio_channel_count_index] * - audio_frames_per_block; - set_audio_status_format(); - - // Get a file descriptor we can select() on - - audio_fd = alGetFD(port); - if (audio_fd < 0) { - fprintf(stderr, "ERROR: couldn't get libaudio file descriptor: %s\n", - alGetErrorString(oserror())); - alClosePort(port); - return false; - } - - // Initialize volume, mute settings - current_main_volume = current_speaker_volume = read_volume(); - current_main_mute = current_speaker_mute = read_mute(); - - - // Start streaming thread - Set_pthread_attr(&stream_thread_attr, 0); - stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0); - - // Everything went fine - audio_open = true; - return true; -} - -void AudioInit(void) -{ - // Init audio status (reasonable defaults) and feature flags - AudioStatus.sample_rate = 44100 << 16; - AudioStatus.sample_size = 16; - AudioStatus.channels = 2; - AudioStatus.mixer = 0; - AudioStatus.num_sources = 0; - audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut; - - // Sound disabled in prefs? Then do nothing - if (PrefsFindBool("nosound")) - return; - - // Init semaphore - if (sem_init(&audio_irq_done_sem, 0, 0) < 0) - return; - sem_inited = true; - - // Open and initialize audio device - open_audio(); -} - - -/* - * Deinitialization - */ - -static void close_audio(void) -{ - // Stop stream and delete semaphore - if (stream_thread_active) { - stream_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(stream_thread); -#endif - pthread_join(stream_thread, NULL); - stream_thread_active = false; - stream_thread_cancel = false; - } - - // Close audio library - alClosePort(port); - - audio_open = false; -} - -void AudioExit(void) -{ - // Close audio device - close_audio(); - - // Delete semaphore - if (sem_inited) { - sem_destroy(&audio_irq_done_sem); - sem_inited = false; - } -} - - -/* - * First source added, start audio stream - */ - -void audio_enter_stream() -{ - // Streaming thread is always running to avoid clicking noises -} - - -/* - * Last source removed, stop audio stream - */ - -void audio_exit_stream() -{ - // Streaming thread is always running to avoid clicking noises -} - - -/* - * Streaming function - */ - -static void *stream_func(void *arg) -{ - int32 *last_buffer = new int32[sound_buffer_size / 4]; - fd_set audio_fdset; - int numfds, was_error; - - numfds = audio_fd + 1; - FD_ZERO(&audio_fdset); - - while (!stream_thread_cancel) { - if (AudioStatus.num_sources) { - - // Trigger audio interrupt to get new buffer - D(bug("stream: triggering irq\n")); - SetInterruptFlag(INTFLAG_AUDIO); - TriggerInterrupt(); - D(bug("stream: waiting for ack\n")); - sem_wait(&audio_irq_done_sem); - D(bug("stream: ack received\n")); - - // Get size of audio data - uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo); - if (!current_main_mute && - !current_speaker_mute && - apple_stream_info) { - int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels; - D(bug("stream: work_size %d\n", work_size)); - if (work_size > sound_buffer_size) - work_size = sound_buffer_size; - if (work_size == 0) - goto silence; - - // Send data to audio library. Convert 8-bit data - // unsigned->signed, using same algorithm as audio_amiga.cpp. - // It works fine for 8-bit mono, but not stereo. - if (AudioStatus.sample_size == 8) { - uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)); - uint32 *q = (uint32 *)last_buffer; - int r = work_size >> 2; - // XXX not quite right.... - while (r--) - *q++ = *p++ ^ 0x80808080; - if (work_size != sound_buffer_size) - memset((uint8 *)last_buffer + work_size, silence_byte, sound_buffer_size - work_size); - alWriteFrames(port, last_buffer, audio_frames_per_block); - } - else if (work_size == sound_buffer_size) - alWriteFrames(port, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), audio_frames_per_block); - else { - // Last buffer - Mac2Host_memcpy(last_buffer, ReadMacInt32(apple_stream_info + scd_buffer), work_size); - memset((uint8 *)last_buffer + work_size, silence_byte, sound_buffer_size - work_size); - alWriteFrames(port, last_buffer, audio_frames_per_block); - } - D(bug("stream: data written\n")); - } else - goto silence; - - } else { - - // Audio not active, play silence - silence: // D(bug("stream: silence\n")); - alZeroFrames(port, audio_frames_per_block); - } - - // Wait for fill point to be reached (may be immediate) - - if (alSetFillPoint(port, sound_buffer_fill_point) < 0) { - fprintf(stderr, "ERROR: alSetFillPoint failed: %s\n", - alGetErrorString(oserror())); - // Should stop the audio here.... - } - - do { - errno = 0; - FD_SET(audio_fd, &audio_fdset); - was_error = select(numfds, NULL, &audio_fdset, NULL, NULL); - } while(was_error < 0 && (errno == EINTR)); - if (was_error < 0) { - fprintf(stderr, "ERROR: select returned %d, errno %d\n", - was_error, errno); - // Should stop audio here.... - } - } - delete[] last_buffer; - return NULL; -} - - -/* - * Read or set the current output volume using the audio library - */ - -static uint32 read_volume(void) -{ - ALpv x[2]; - ALfixed gain[8]; - double maxgain, mingain; - ALparamInfo pi; - uint32 ret = 0x01000100; // default, maximum value - int dev = alGetDevice(config); - - // Fetch the maximum and minimum gain settings - - alGetParamInfo(dev, AL_GAIN, &pi); - maxgain = alFixedToDouble(pi.max.ll); - mingain = alFixedToDouble(pi.min.ll); -// printf("maxgain = %lf dB, mingain = %lf dB\n", maxgain, mingain); - - // Get the current gain values - - x[0].param = AL_GAIN; - x[0].value.ptr = gain; - x[0].sizeIn = sizeof(gain) / sizeof(gain[0]); - x[1].param = AL_CHANNELS; - if (alGetParams(dev, x, 2) < 0) { - printf("alGetParams failed: %s\n", alGetErrorString(oserror())); - } - else { - if (x[0].sizeOut < 0) { - printf("AL_GAIN was an unrecognized parameter\n"); - } - else { - double v; - uint32 left, right; - - // Left - v = alFixedToDouble(gain[0]); - if (v < mingain) - v = mingain; // handle gain == -inf - v = (v - mingain) / (maxgain - mingain); // scale to 0..1 - left = (uint32)(v * (double)256); // convert to 8.8 fixed point - - // Right - if (x[0].sizeOut <= 1) { // handle a mono interface - right = left; - } - else { - v = alFixedToDouble(gain[1]); - if (v < mingain) - v = mingain; // handle gain == -inf - v = (v - mingain) / (maxgain - mingain); // scale to 0..1 - right = (uint32)(v * (double)256); // convert to 8.8 fixed point - } - - ret = (left << 16) | right; - } - } - - return ret; -} - -static void set_volume(uint32 vol) -{ - ALpv x[1]; - ALfixed gain[2]; // left and right - double maxgain, mingain; - ALparamInfo pi; - int dev = alGetDevice(config); - - // Fetch the maximum and minimum gain settings - - alGetParamInfo(dev, AL_GAIN, &pi); - maxgain = alFixedToDouble(pi.max.ll); - mingain = alFixedToDouble(pi.min.ll); - - // Set the new gain values - - x[0].param = AL_GAIN; - x[0].value.ptr = gain; - x[0].sizeIn = sizeof(gain) / sizeof(gain[0]); - - uint32 left = vol >> 16; - uint32 right = vol & 0xffff; - double lv, rv; - - if (left == 0 && pi.specialVals & AL_NEG_INFINITY_BIT) { - lv = AL_NEG_INFINITY; - } - else { - lv = ((double)left / 256) * (maxgain - mingain) + mingain; - } - - if (right == 0 && pi.specialVals & AL_NEG_INFINITY_BIT) { - rv = AL_NEG_INFINITY; - } - else { - rv = ((double)right / 256) * (maxgain - mingain) + mingain; - } - - D(bug("set_volume: left=%lf dB, right=%lf dB\n", lv, rv)); - - gain[0] = alDoubleToFixed(lv); - gain[1] = alDoubleToFixed(rv); - - if (alSetParams(dev, x, 1) < 0) { - printf("alSetParams failed: %s\n", alGetErrorString(oserror())); - } -} - - -/* - * Read or set the mute setting using the audio library - */ - -static bool read_mute(void) -{ - bool ret; - int dev = alGetDevice(config); - ALpv x; - x.param = AL_MUTE; - - if (alGetParams(dev, &x, 1) < 0) { - printf("alSetParams failed: %s\n", alGetErrorString(oserror())); - return current_main_mute; // Or just return false? - } - - ret = x.value.i; - - D(bug("read_mute: mute=%d\n", ret)); - return ret; -} - -static void set_mute(bool mute) -{ - D(bug("set_mute: mute=%ld\n", mute)); - - int dev = alGetDevice(config); - ALpv x; - x.param = AL_MUTE; - x.value.i = mute; - - if (alSetParams(dev, &x, 1) < 0) { - printf("alSetParams failed: %s\n", alGetErrorString(oserror())); - } -} - - - -/* - * MacOS audio interrupt, read next data block - */ - -void AudioInterrupt(void) -{ - D(bug("AudioInterrupt\n")); - - // Get data from apple mixer - if (AudioStatus.mixer) { - M68kRegisters r; - r.a[0] = audio_data + adatStreamInfo; - r.a[1] = AudioStatus.mixer; - Execute68k(audio_data + adatGetSourceData, &r); - D(bug(" GetSourceData() returns %08lx\n", r.d[0])); - } else - WriteMacInt32(audio_data + adatStreamInfo, 0); - - // Signal stream function - sem_post(&audio_irq_done_sem); - D(bug("AudioInterrupt done\n")); -} - - -/* - * Set sampling parameters - * "index" is an index into the audio_sample_rates[] etc. vectors - * It is guaranteed that AudioStatus.num_sources == 0 - */ - -bool audio_set_sample_rate(int index) -{ - close_audio(); - audio_sample_rate_index = index; - return open_audio(); -} - -bool audio_set_sample_size(int index) -{ - close_audio(); - audio_sample_size_index = index; - return open_audio(); -} - -bool audio_set_channels(int index) -{ - close_audio(); - audio_channel_count_index = index; - return open_audio(); -} - - -/* - * Get/set volume controls (volume values received/returned have the left channel - * volume in the upper 16 bits and the right channel volume in the lower 16 bits; - * both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume")) - */ - -bool audio_get_main_mute(void) -{ - D(bug("audio_get_main_mute: mute=%ld\n", current_main_mute)); - - return current_main_mute; -} - -uint32 audio_get_main_volume(void) -{ - uint32 ret = current_main_volume; - - D(bug("audio_get_main_volume: vol=0x%x\n", ret)); - - return ret; -} - -bool audio_get_speaker_mute(void) -{ - D(bug("audio_get_speaker_mute: mute=%ld\n", current_speaker_mute)); - - return current_speaker_mute; -} - -uint32 audio_get_speaker_volume(void) -{ - uint32 ret = current_speaker_volume; - - D(bug("audio_get_speaker_volume: vol=0x%x\n", ret)); - - return ret; -} - -void audio_set_main_mute(bool mute) -{ - D(bug("audio_set_main_mute: mute=%ld\n", mute)); - - if (mute != current_main_mute) { - current_main_mute = mute; - } - - set_mute(current_main_mute); -} - -void audio_set_main_volume(uint32 vol) -{ - - D(bug("audio_set_main_volume: vol=%x\n", vol)); - - current_main_volume = vol; - - set_volume(vol); -} - -void audio_set_speaker_mute(bool mute) -{ - D(bug("audio_set_speaker_mute: mute=%ld\n", mute)); - - if (mute != current_speaker_mute) { - current_speaker_mute = mute; - } - - set_mute(current_speaker_mute); -} - -void audio_set_speaker_volume(uint32 vol) -{ - D(bug("audio_set_speaker_volume: vol=%x\n", vol)); - - current_speaker_volume = vol; - - set_volume(vol); -} diff --git a/BasiliskII/src/Unix/Irix/unaligned.c b/BasiliskII/src/Unix/Irix/unaligned.c deleted file mode 100644 index 9f4befb8..00000000 --- a/BasiliskII/src/Unix/Irix/unaligned.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Irix/unaligned.c - Optimized unaligned access for Irix - * - * Basilisk II (C) 1997-2005 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef sgi -#include "sysdeps.h" - -/* Tell the compiler to pack data on 1-byte boundaries - * (i.e. arbitrary alignment). Requires SGI MIPSPro compilers. */ -#pragma pack(1) - -typedef struct _ual32 { - uae_u32 v; -} ual32_t; - -typedef struct _ual16 { - uae_u16 v; -} ual16_t; - -#pragma pack(0) - -/* The compiler is smart enough to inline these when you build with "-ipa" */ -uae_u32 do_get_mem_long(uae_u32 *a) {return ((ual32_t *)a)->v;} -uae_u32 do_get_mem_word(uae_u16 *a) {return ((ual16_t *)a)->v;} -void do_put_mem_long(uae_u32 *a, uae_u32 v) {((ual32_t *)a)->v = v;} -void do_put_mem_word(uae_u16 *a, uae_u32 v) {((ual16_t *)a)->v = v;} - -#endif /* sgi */ diff --git a/BasiliskII/src/Unix/Linux/NetDriver/Makefile b/BasiliskII/src/Unix/Linux/NetDriver/Makefile deleted file mode 100644 index 50a1d238..00000000 --- a/BasiliskII/src/Unix/Linux/NetDriver/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# Linux makefile for sheep_net driver -KERNEL_DIR = /lib/modules/$(shell uname -r) -KERNEL_SOURCE = $(KERNEL_DIR)/build -LV := $(shell test -f $(KERNEL_SOURCE)/Rules.make && echo 24 || echo 26) -MP := $(shell test -f $(KERNEL_SOURCE)/Rules.make && echo "o" || echo "ko") - -ifeq ($(LV),26) -# Kernel 2.6 - -KERNEL_DRIVER = $(KERNEL_DIR)/kernel/drivers -obj-m = sheep_net.o - -sheep_net.ko: sheep_net.c - $(MAKE) -C $(KERNEL_SOURCE) M=$$PWD modules - -clean: - $(MAKE) -C $(KERNEL_SOURCE) M=$$PWD clean - -else -# Kernel 2.4 - -## System specific configuration -CPPFLAGS = -I. -I$(KERNEL_SOURCE)/include -CFLAGS = -O2 -Wall -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES -ASFLAGS = -LDFLAGS = -LIBS = - -## Files -KERNEL_DRIVER = $(KERNEL_DIR) -OBJS = sheep_net.o - -## Rules -sheep_net.o: sheep_net.c - $(CC) -c $(CPPFLAGS) $(CFLAGS) sheep_net.c - -clean: - -rm $(OBJS) - -dep depend: - makedepend $(CPPFLAGS) -Y *.c - -endif - -dev: - mknod /dev/sheep_net c 10 198 - -install: sheep_net.$(MP) - install -d $(KERNEL_DRIVER)/misc - install -m 644 sheep_net.$(MP) $(KERNEL_DRIVER)/misc - depmod -a - -# DO NOT DELETE diff --git a/BasiliskII/src/Unix/Linux/NetDriver/config.h b/BasiliskII/src/Unix/Linux/NetDriver/config.h deleted file mode 120000 index fc383f11..00000000 --- a/BasiliskII/src/Unix/Linux/NetDriver/config.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../SheepShaver/src/Unix/config.h \ No newline at end of file diff --git a/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c b/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c deleted file mode 100644 index b02153f0..00000000 --- a/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * sheep_net.c - Linux driver for SheepShaver/Basilisk II networking (access to raw Ethernet packets) - * - * sheep_net (C) 1999-2004 Mar"c" Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* modversions.h redefines kernel symbols. Now include other headers */ -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) -#define LINUX_3_15 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) -#define LINUX_26_35 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) -#define LINUX_26_36 -#endif - -/* Compatibility glue */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) -#define LINUX_26_30 - -#else - -/* determine whether to use checksummed versions of kernel symbols */ -/*** -#include -***/ -#include "config.h" -#include - -#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) -#define MODVERSIONS -#endif - -#if defined(MODVERSIONS) -#include -#endif - -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Christian Bauer"); -MODULE_DESCRIPTION("Pseudo ethernet device for emulators"); - -/* Compatibility glue */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define LINUX_26 -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -#define LINUX_24 -#else -#define net_device device -typedef struct wait_queue *wait_queue_head_t; -#define init_waitqueue_head(x) *(x)=NULL -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -#define eth_hdr(skb) (skb)->mac.ethernet -#define skb_mac_header(skb) (skb)->mac.raw -#define ipip_hdr(skb) (skb)->h.ipiph -#endif - -#ifdef LINUX_26 -#define skt_set_dead(skt) do {} while(0) -#define wmem_alloc sk_wmem_alloc -#else -#define skt_set_dead(skt) (skt)->dead = 1 -#endif - -#define DEBUG 0 - -#define bug printk -#if DEBUG -#define D(x) (x); -#else -#define D(x) ; -#endif - - -/* Constants */ -#define SHEEP_NET_MINOR 198 /* Driver minor number */ -#define MAX_QUEUE 32 /* Maximum number of packets in queue */ -#define PROT_MAGIC 1520 /* Our "magic" protocol type */ - -#define ETH_ADDR_MULTICAST 0x1 -#define ETH_ADDR_LOCALLY_DEFINED 0x02 - -#define SIOC_MOL_GET_IPFILTER SIOCDEVPRIVATE -#define SIOC_MOL_SET_IPFILTER (SIOCDEVPRIVATE + 1) - -/* Prototypes */ -static int sheep_net_open(struct inode *inode, struct file *f); -static int sheep_net_release(struct inode *inode, struct file *f); -static ssize_t sheep_net_read(struct file *f, char *buf, size_t count, loff_t *off); -static ssize_t sheep_net_write(struct file *f, const char *buf, size_t count, loff_t *off); -static unsigned int sheep_net_poll(struct file *f, struct poll_table_struct *wait); -#ifdef LINUX_26_36 -static long sheep_net_ioctl(struct file *f, unsigned int code, unsigned long arg); -#else -static int sheep_net_ioctl(struct inode *inode, struct file *f, unsigned int code, unsigned long arg); -#endif -#ifdef LINUX_26 -static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *foo); -#else -static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt); -#endif - -/* - * Driver private variables - */ - -struct SheepVars { - /* IMPORTANT: the packet_type struct must go first. It no longer - (2.6) contains * a data field so we typecast to get the SheepVars - struct */ - struct packet_type pt; /* Receiver packet type */ - struct net_device *ether; /* The Ethernet device we're attached to */ - struct sock *skt; /* Socket for communication with Ethernet card */ - struct sk_buff_head queue; /* Receiver packet queue */ - wait_queue_head_t wait; /* Wait queue for blocking read operations */ - u32 ipfilter; /* Only receive IP packets destined for this address (host byte order) */ - char eth_addr[6]; /* Hardware address of the Ethernet card */ - char fake_addr[6]; /* Local faked hardware address (what SheepShaver sees) */ -#ifdef LINUX_3_15 - atomic_t got_packet; -#endif -}; - - -/* - * file_operations structure - has function pointers to the - * various entry points for device operations - */ - -static struct file_operations sheep_net_fops = { - .owner = THIS_MODULE, - .read = sheep_net_read, - .write = sheep_net_write, - .poll = sheep_net_poll, -#ifdef LINUX_26_36 - .unlocked_ioctl = sheep_net_ioctl, -#else - .ioctl = sheep_net_ioctl, -#endif - .open = sheep_net_open, - .release = sheep_net_release, -}; - - -/* - * miscdevice structure for driver initialization - */ - -static struct miscdevice sheep_net_device = { - .minor = SHEEP_NET_MINOR, /* minor number */ - .name = "sheep_net", /* name */ - .fops = &sheep_net_fops -}; - - -/* - * fake protocol to use a common socket - */ -static struct proto sheep_proto = { - .name = "SHEEP", - .owner = THIS_MODULE, - .obj_size = sizeof(struct sock), -}; - - -/* - * Initialize module - */ - -int init_module(void) -{ - int ret; - - /* Register driver */ - ret = misc_register(&sheep_net_device); - D(bug("Sheep net driver installed\n")); - return ret; -} - - -/* - * Deinitialize module - */ - -void cleanup_module(void) -{ - /* Unregister driver */ - misc_deregister(&sheep_net_device); - D(bug("Sheep net driver removed\n")); -} - - -/* - * Driver open() function - */ - -static int sheep_net_open(struct inode *inode, struct file *f) -{ - struct SheepVars *v; - D(bug("sheep_net: open\n")); - - /* Must be opened with read permissions */ - if ((f->f_flags & O_ACCMODE) == O_WRONLY) - return -EPERM; - - /* Allocate private variables */ - v = (struct SheepVars *)kmalloc(sizeof(struct SheepVars), GFP_USER); - if (v == NULL) - return -ENOMEM; - -#ifndef LINUX_26_30 - lock_kernel(); -#endif - memset(v, 0, sizeof(struct SheepVars)); - skb_queue_head_init(&v->queue); - init_waitqueue_head(&v->wait); - v->fake_addr[0] = 'v'; /* "SheepShaver" */ - v->fake_addr[1] = 'r'; /* ^ ^ */ - get_random_bytes(&v->fake_addr[2], 4); - - /* Put our stuff where we will be able to find it later */ - f->private_data = (void *)v; - - /* Yes, we're open */ -#ifndef LINUX_26 - MOD_INC_USE_COUNT; -#endif -#ifndef LINUX_26_30 - unlock_kernel(); -#endif - return 0; -} - - -/* - * Driver release() function - */ - -static int sheep_net_release(struct inode *inode, struct file *f) -{ - struct SheepVars *v = (struct SheepVars *)f->private_data; - struct sk_buff *skb; - D(bug("sheep_net: close\n")); - - /* Detach from Ethernet card */ - if (v->ether) { - dev_remove_pack(&v->pt); - sk_free(v->skt); - v->skt = NULL; -#ifdef LINUX_24 - dev_put( v->ether ); -#endif - v->ether = NULL; - } - - /* Empty packet queue */ - while ((skb = skb_dequeue(&v->queue)) != NULL) - dev_kfree_skb(skb); - - /* Free private variables */ - kfree(v); - - /* Sorry, we're closed */ -#ifndef LINUX_26 - MOD_DEC_USE_COUNT; -#endif - return 0; -} - - -/* - * Check whether an Ethernet address is the local (attached) one or - * the fake one - */ - -static inline int is_local_addr(struct SheepVars *v, void *a) -{ - return memcmp(a, v->eth_addr, 6) == 0; -} - -static inline int is_fake_addr(struct SheepVars *v, void *a) -{ - return memcmp(a, v->fake_addr, 6) == 0; -} - - -/* - * Outgoing packet. Replace the fake enet addr with the real local one. - */ - -static inline void do_demasq(struct SheepVars *v, u8 *p) -{ - memcpy(p, v->eth_addr, 6); -} - -static void demasquerade(struct SheepVars *v, struct sk_buff *skb) -{ - u8 *p = skb_mac_header(skb); - int proto = (p[12] << 8) | p[13]; - - do_demasq(v, p + 6); /* source address */ - - /* Need to fix ARP packets */ - if (proto == ETH_P_ARP) { - if (is_fake_addr(v, p + 14 + 8)) /* sender HW-addr */ - do_demasq(v, p + 14 + 8); - } - - /* ...and AARPs (snap code: 0x00,0x00,0x00,0x80,0xF3) */ - if (p[17] == 0 && p[18] == 0 && p[19] == 0 && p[20] == 0x80 && p[21] == 0xf3) { - /* XXX: we should perhaps look for the 802 frame too */ - if (is_fake_addr(v, p + 30)) - do_demasq(v, p + 30); /* sender HW-addr */ - } -} - - -/* - * Incoming packet. Replace the local enet addr with the fake one. - */ - -static inline void do_masq(struct SheepVars *v, u8 *p) -{ - memcpy(p, v->fake_addr, 6); -} - -static void masquerade(struct SheepVars *v, struct sk_buff *skb) -{ - u8 *p = skb_mac_header(skb); - if (!(p[0] & ETH_ADDR_MULTICAST)) - do_masq(v, p); /* destination address */ - - /* XXX: reverse ARP might need to be fixed */ -} - - -/* - * Driver read() function - */ - -static ssize_t sheep_net_read(struct file *f, char *buf, size_t count, loff_t *off) -{ - struct SheepVars *v = (struct SheepVars *)f->private_data; - struct sk_buff *skb; - - D(bug("sheep_net: read\n")); - - for (;;) { - - /* Get next packet from queue */ - skb = skb_dequeue(&v->queue); - if (skb != NULL || (f->f_flags & O_NONBLOCK)) - break; - - /* No packet in queue and in blocking mode, so block */ -#ifdef LINUX_3_15 - atomic_set(&v->got_packet, 0); - wait_event_interruptible(v->wait, atomic_read(&v->got_packet)); -#else - interruptible_sleep_on(&v->wait); -#endif - - /* Signal received? Then bail out */ - if (signal_pending(current)) - return -EINTR; - } - if (skb == NULL) - return -EAGAIN; - - /* Pass packet to caller */ - if (count > skb->len) - count = skb->len; - if (copy_to_user(buf, skb->data, count)) - count = -EFAULT; - dev_kfree_skb(skb); - return count; -} - - -/* - * Driver write() function - */ - -static inline void do_nothing(struct sk_buff *skb) -{ - return; -} - -static ssize_t sheep_net_write(struct file *f, const char *buf, size_t count, loff_t *off) -{ - struct SheepVars *v = (struct SheepVars *)f->private_data; - struct sk_buff *skb; - char *p; - D(bug("sheep_net: write\n")); - - /* Check packet size */ - if (count < sizeof(struct ethhdr)) - return -EINVAL; - if (count > 1514) { - printk("sheep_net_write: packet size %ld > 1514\n", count); - count = 1514; - } - - /* Interface active? */ - if (v->ether == NULL) - return count; - - /* Allocate buffer for packet */ - skb = dev_alloc_skb(count); - if (skb == NULL) - return -ENOBUFS; - - /* Stuff packet in buffer */ - p = skb_put(skb, count); - if (copy_from_user(p, buf, count)) { - kfree_skb(skb); - return -EFAULT; - } - - /* Transmit packet */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) - atomic_add(skb->truesize, &v->skt->wmem_alloc); -#endif - skb->sk = v->skt; - skb->dev = v->ether; - skb->priority = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - skb->nh.raw = skb->h.raw = skb->data + v->ether->hard_header_len; - skb->mac.raw = skb->data; -#else - skb_reset_mac_header(skb); - skb_set_transport_header(skb, v->ether->hard_header_len); - skb_set_network_header(skb, v->ether->hard_header_len); -#endif - - /* Base the IP-filtering on the IP address in any outgoing ARP packets */ - if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { - u8 *p = &skb->data[14+14]; /* source IP address */ - u32 ip = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - if (ip != v->ipfilter) { - v->ipfilter = ip; - printk("sheep_net: ipfilter set to %d.%d.%d.%d\n", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); - } - } - - /* Is this packet addressed solely to the local host? */ - if (is_local_addr(v, skb->data) && !(skb->data[0] & ETH_ADDR_MULTICAST)) { - skb->destructor = do_nothing; - skb->protocol = eth_type_trans(skb, v->ether); - netif_rx(skb); - return count; - } - if (skb->data[0] & ETH_ADDR_MULTICAST) { - /* We can't clone the skb since we will manipulate the data below */ - struct sk_buff *lskb = skb_copy(skb, GFP_ATOMIC); - if (lskb) { - lskb->protocol = eth_type_trans(lskb, v->ether); - netif_rx(lskb); - } - } - - /* Outgoing packet (will be on the net) */ - demasquerade(v, skb); - - skb->destructor = do_nothing; - skb->protocol = PROT_MAGIC; /* Magic value (we can recognize the packet in sheep_net_receiver) */ - dev_queue_xmit(skb); - return count; -} - - -/* - * Driver poll() function - */ - -static unsigned int sheep_net_poll(struct file *f, struct poll_table_struct *wait) -{ - struct SheepVars *v = (struct SheepVars *)f->private_data; - D(bug("sheep_net: poll\n")); - - /* Packets in queue? Then return */ - if (!skb_queue_empty(&v->queue)) - return POLLIN | POLLRDNORM; - - /* Otherwise wait for packet */ - poll_wait(f, &v->wait, wait); - if (!skb_queue_empty(&v->queue)) - return POLLIN | POLLRDNORM; - else - return 0; -} - - -/* - * Driver ioctl() function - */ - -#ifdef LINUX_26_36 -static long sheep_net_ioctl(struct file *f, unsigned int code, unsigned long arg) -#else -static int sheep_net_ioctl(struct inode *inode, struct file *f, unsigned int code, unsigned long arg) -#endif -{ - struct SheepVars *v = (struct SheepVars *)f->private_data; - D(bug("sheep_net: ioctl %04x\n", code)); - - switch (code) { - - /* Attach to Ethernet card - arg: pointer to name of Ethernet device (char[20]) */ - case SIOCSIFLINK: { - char name[20]; - int err; - - /* Already attached? */ - if (v->ether) - return -EBUSY; - - /* Get Ethernet card name */ - if (copy_from_user(name, (void *)arg, 20)) - return -EFAULT; - name[19] = 0; - - /* Find card */ -#ifdef LINUX_26 - v->ether = dev_get_by_name(&init_net, name); -#elif defined(LINUX_24) - v->ether = dev_get_by_name(name); -#else - dev_lock_list(); - v->ether = dev_get(name); -#endif - if (v->ether == NULL) { - err = -ENODEV; - goto error; - } - - /* Is it Ethernet? */ - if (v->ether->type != ARPHRD_ETHER) { - err = -EINVAL; - goto error; - } - - /* Remember the card's hardware address */ - memcpy(v->eth_addr, v->ether->dev_addr, 6); - - /* Allocate socket */ -#ifdef LINUX_26 - v->skt = sk_alloc(dev_net(v->ether), GFP_USER, 1, &sheep_proto); -#else - v->skt = sk_alloc(0, GFP_USER, 1); -#endif - if (v->skt == NULL) { - err = -ENOMEM; - goto error; - } - skt_set_dead(v->skt); - - /* Attach packet handler */ - v->pt.type = htons(ETH_P_ALL); - v->pt.dev = v->ether; - v->pt.func = sheep_net_receiver; - dev_add_pack(&v->pt); -#ifndef LINUX_24 - dev_unlock_list(); -#endif - return 0; - -error: -#ifdef LINUX_24 - if (v->ether) - dev_put(v->ether); -#else - dev_unlock_list(); -#endif - v->ether = NULL; - return err; - } - - /* Get hardware address of the sheep_net module - arg: pointer to buffer (6 bytes) to store address */ - case SIOCGIFADDR: - if (copy_to_user((void *)arg, v->fake_addr, 6)) - return -EFAULT; - return 0; - - /* Set the hardware address of the sheep_net module - arg: pointer to new address (6 bytes) */ - case SIOCSIFADDR: - if (copy_from_user(v->fake_addr, (void*)arg, 6)) - return -EFAULT; - return 0; - - /* Add multicast address - arg: pointer to address (6 bytes) */ - case SIOCADDMULTI: { - char addr[6]; - if (v->ether == NULL) - return -ENODEV; - if (copy_from_user(addr, (void *)arg, 6)) - return -EFAULT; - #ifdef LINUX_26_35 - return dev_mc_add(v->ether, addr); - #else - return dev_mc_add(v->ether, addr, 6, 0); - #endif - } - - /* Remove multicast address - arg: pointer to address (6 bytes) */ - case SIOCDELMULTI: { - char addr[6]; - if (v->ether == NULL) - return -ENODEV; - if (copy_from_user(addr, (void *)arg, 6)) - return -EFAULT; - #ifdef LINUX_26_35 - return dev_mc_del(v->ether, addr); - #else - return dev_mc_delete(v->ether, addr, 6, 0); - #endif - } - - /* Return size of first packet in queue */ - case FIONREAD: { - int count = 0; - struct sk_buff *skb; -#ifdef LINUX_24 - unsigned long flags; - spin_lock_irqsave(&v->queue.lock, flags); -#else - cli(); -#endif - skb = skb_peek(&v->queue); - if (skb) - count = skb->len; -#ifdef LINUX_24 - spin_unlock_irqrestore(&v->queue.lock, flags); -#else - sti(); -#endif - return put_user(count, (int *)arg); - } - - case SIOC_MOL_GET_IPFILTER: - return put_user(v->ipfilter, (int *)arg); - - case SIOC_MOL_SET_IPFILTER: - v->ipfilter = arg; - return 0; - - default: - return -ENOIOCTLCMD; - } -} - - -/* - * Packet receiver function - */ - -#ifdef LINUX_26 -static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *foo) -#else -static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) -#endif -{ - struct SheepVars *v = (struct SheepVars *)pt; - struct sk_buff *skb2; - int fake; - int multicast; - D(bug("sheep_net: packet received\n")); - - multicast = (eth_hdr(skb)->h_dest[0] & ETH_ADDR_MULTICAST); - fake = is_fake_addr(v, ð_hdr(skb)->h_dest); - - /* Packet sent by us? Then discard */ - if (is_fake_addr(v, ð_hdr(skb)->h_source) || skb->protocol == PROT_MAGIC) - goto drop; - - /* If the packet is not meant for this host, discard it */ - if (!is_local_addr(v, ð_hdr(skb)->h_dest) && !multicast && !fake) - goto drop; - - /* Discard packets if queue gets too full */ - if (skb_queue_len(&v->queue) > MAX_QUEUE) - goto drop; - - /* Apply any filters here (if fake is true, then we *know* we want this packet) */ - if (!fake) { - if ((skb->protocol == htons(ETH_P_IP)) - && (!v->ipfilter || (ntohl(ipip_hdr(skb)->daddr) != v->ipfilter && !multicast))) - goto drop; - } - - /* Masquerade (we are typically a clone - best to make a real copy) */ - skb2 = skb_copy(skb, GFP_ATOMIC); - if (!skb2) - goto drop; - kfree_skb(skb); - skb = skb2; - masquerade(v, skb); - - /* We also want the Ethernet header */ - skb_push(skb, skb->data - skb_mac_header(skb)); - - /* Enqueue packet */ - skb_queue_tail(&v->queue, skb); - - /* Unblock blocked read */ -#ifdef LINUX_3_15 - - atomic_set(&v->got_packet, 1); - - wake_up_interruptible(&v->wait); - -#else - - wake_up(&v->wait); - -#endif - return 0; - -drop: - kfree_skb(skb); - return 0; -} - -MODULE_LICENSE("GPL"); diff --git a/BasiliskII/src/Unix/Linux/scsi_linux.cpp b/BasiliskII/src/Unix/Linux/scsi_linux.cpp deleted file mode 100644 index d6365277..00000000 --- a/BasiliskII/src/Unix/Linux/scsi_linux.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * scsi_linux.cpp - SCSI Manager, Linux specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include // workaround for broken RedHat 6.0 /usr/include/scsi -#include -#include - -#define DRIVER_SENSE 0x08 - -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "scsi.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static int fds[8]; // fd's for 8 units -static int fd; // Active fd (selected target) - -static uint32 buffer_size; // Size of data buffer -static uint8 *buffer = NULL; // Pointer to data buffer - -static uint8 the_cmd[12]; // Active SCSI command -static int the_cmd_len; - - -/* - * Initialization - */ - -void SCSIInit(void) -{ - int id; - - // Allocate buffer - buffer = (uint8 *)malloc(buffer_size = 0x10000); - - // Open generic SCSI driver for all 8 units - for (id=0; id<8; id++) { - char prefs_name[16]; - sprintf(prefs_name, "scsi%d", id); - const char *str = PrefsFindString(prefs_name); - if (str) { - int fd = fds[id] = open(str, O_RDWR | O_EXCL); - if (fd > 0) { - // Is it really a Generic SCSI device? - int timeout = ioctl(fd, SG_GET_TIMEOUT); - if (timeout < 0) { - // Error with SG_GET_TIMEOUT, doesn't seem to be a Generic SCSI device - char msg[256]; - sprintf(msg, GetString(STR_SCSI_DEVICE_NOT_SCSI_WARN), str); - WarningAlert(msg); - close(fd); - fds[id] = -1; - } else { - // Flush unwanted garbage from previous use of device - uint8 reply[256]; - int old_fl = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, old_fl | O_NONBLOCK); - while (read(fd, reply, sizeof(reply)) != -1 || errno != EAGAIN) ; - fcntl(fd, F_SETFL, old_fl); - } - } else { - char msg[256]; - sprintf(msg, GetString(STR_SCSI_DEVICE_OPEN_WARN), str, strerror(errno)); - WarningAlert(msg); - } - } - } - - // Reset SCSI bus - SCSIReset(); -} - - -/* - * Deinitialization - */ - -void SCSIExit(void) -{ - // Close all devices - for (int i=0; i<8; i++) { - int fd = fds[i]; - if (fd > 0) - close(fd); - } - - // Free buffer - if (buffer) { - free(buffer); - buffer = NULL; - } -} - - -/* - * Check if requested data size fits into buffer, allocate new buffer if needed - */ - -static bool try_buffer(uint32 size) -{ - size += sizeof(sg_header) + 12; - if (size <= buffer_size) - return true; - - uint8 *new_buffer = (uint8 *)malloc(size); - if (new_buffer == NULL) - return false; - free(buffer); - buffer = new_buffer; - buffer_size = size; - return true; -} - - -/* - * Set SCSI command to be sent by scsi_send_cmd() - */ - -void scsi_set_cmd(int cmd_length, uint8 *cmd) -{ - memcpy(the_cmd, cmd, the_cmd_len = cmd_length); -} - - -/* - * Check for presence of SCSI target - */ - -bool scsi_is_target_present(int id) -{ - return fds[id] > 0; -} - - -/* - * Set SCSI target (returns false on error) - */ - -bool scsi_set_target(int id, int lun) -{ - int new_fd = fds[id]; - if (new_fd < 0) - return false; - if (new_fd != fd) { - // New target, clear autosense data - sg_header *h = (sg_header *)buffer; - h->driver_status &= ~DRIVER_SENSE; - } - fd = new_fd; - return true; -} - - -/* - * Send SCSI command to active target (scsi_set_command() must have been called), - * read/write data according to S/G table (returns false on error); timeout is in 1/60 sec - */ - -bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout) -{ - static int pack_id = 0; - - // Check if buffer is large enough, allocate new buffer if needed - if (!try_buffer(data_length)) { - char str[256]; - sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length); - ErrorAlert(str); - return false; - } - - // Process S/G table when writing - if (!reading) { - D(bug(" writing to buffer\n")); - uint8 *buffer_ptr = buffer + sizeof(sg_header) + the_cmd_len; - for (int i=0; itarget_status & DRIVER_SENSE)) { - - // Yes, fake command - D(bug(" autosense\n")); - memcpy(buffer + sizeof(sg_header), h->sense_buffer, 16); - h->target_status &= ~DRIVER_SENSE; - res = 0; - *stat = 0; - - } else { - - // No, send regular command - if (timeout) { - int to = timeout * HZ / 60; - ioctl(fd, SG_SET_TIMEOUT, &to); - } - ioctl(fd, SG_NEXT_CMD_LEN, &the_cmd_len); - - D(bug(" sending command, length %d\n", data_length)); - - int request_size, reply_size; - if (reading) { - h->pack_len = request_size = sizeof(sg_header) + the_cmd_len; - h->reply_len = reply_size = sizeof(sg_header) + data_length; - } else { - h->pack_len = request_size = sizeof(sg_header) + the_cmd_len + data_length; - h->reply_len = reply_size = sizeof(sg_header); - } - h->pack_id = pack_id++; - h->result = 0; - h->twelve_byte = (the_cmd_len == 12); - h->target_status = 0; - h->host_status = 0; - h->driver_status = 0; - h->other_flags = 0; - memcpy(buffer + sizeof(sg_header), the_cmd, the_cmd_len); - - res = write(fd, buffer, request_size); - D(bug(" request sent, actual %d, result %d\n", res, h->result)); - if (res >= 0) { - res = read(fd, buffer, reply_size); - D(bug(" reply read, actual %d, result %d, status %02x\n", res, h->result, h->target_status << 1)); - } - - *stat = h->target_status << 1; - } - - // Process S/G table when reading - if (reading && h->result == 0) { - D(bug(" reading from buffer\n")); - uint8 *buffer_ptr = buffer + sizeof(sg_header); - for (int i=0; i= 0; -} diff --git a/BasiliskII/src/Unix/Makefile.in b/BasiliskII/src/Unix/Makefile.in index 8ce51385..389e8eed 100644 --- a/BasiliskII/src/Unix/Makefile.in +++ b/BasiliskII/src/Unix/Makefile.in @@ -21,7 +21,7 @@ CFLAGS = @CFLAGS@ CXXFLAGS = @CXXFLAGS@ CPUINCLUDES_FLAGS=@CPUINCLUDES@ CPUINCLUDES_FLAGS:=$(CPUINCLUDES_FLAGS:-I%=-I@top_srcdir@/%) -CPPFLAGS = @CPPFLAGS@ -I@top_srcdir@/../include -I@top_srcdir@/. -I. -I@top_srcdir@/../CrossPlatform $(CPUINCLUDES_FLAGS) -I@top_srcdir@/../slirp +CPPFLAGS = @CPPFLAGS@ -I@top_srcdir@/../include -I@top_srcdir@/. -I. -I@top_srcdir@/../CrossPlatform $(CPUINCLUDES_FLAGS) DEFS = @DEFS@ @DEFINES@ -D_REENTRANT -DDATADIR=\"$(datadir)/$(APP)\" LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ @@ -33,16 +33,6 @@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ -SLIRP_CFLAGS = @SLIRP_CFLAGS@ -SLIRP_SRCS = @SLIRP_SRCS@ -SLIRP_OBJS = $(SLIRP_SRCS:../slirp/%.c=obj/%.o) - -STANDALONE_GUI = @STANDALONE_GUI@ -GUI_CFLAGS = @GUI_CFLAGS@ -GUI_LIBS = @GUI_LIBS@ -GUI_SRCS = ../prefs.cpp prefs_unix.cpp prefs_editor_gtk.cpp ../prefs_items.cpp \ - ../user_strings.cpp user_strings_unix.cpp xpram_unix.cpp sys_unix.cpp rpc_unix.cpp - XPLAT_SRCS = ../CrossPlatform/vm_alloc.cpp ../CrossPlatform/sigsegv.cpp ../CrossPlatform/video_blit.cpp ## Files @@ -51,10 +41,9 @@ SRCS = ../main.cpp ../prefs.cpp ../prefs_items.cpp \ ../emul_op.cpp ../macos_util.cpp ../xpram.cpp xpram_unix.cpp ../timer.cpp \ timer_unix.cpp ../adb.cpp ../serial.cpp ../ether.cpp \ ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp \ - ../audio.cpp ../extfs.cpp disk_sparsebundle.cpp \ - tinyxml2.cpp \ - ../user_strings.cpp user_strings_unix.cpp sshpty.c strlcpy.c rpc_unix.cpp \ - $(XPLAT_SRCS) $(SYSSRCS) $(CPUSRCS) $(SLIRP_SRCS) + ../audio.cpp ../extfs.cpp \ + ../user_strings.cpp user_strings_unix.cpp rpc_unix.cpp \ + $(XPLAT_SRCS) $(SYSSRCS) $(CPUSRCS) APP_FLAVOR ?= ifneq ($(APP_FLAVOR),) CURR_APP_FLAVOR := -$(APP_FLAVOR) @@ -63,20 +52,11 @@ else endif APP_BASENAME = BasiliskII APP = $(APP_BASENAME)$(CURR_APP_FLAVOR) -APP_APP = $(APP).app PROGS = $(APP)$(EXEEXT) -ifeq ($(STANDALONE_GUI),yes) -GUI_APP = BasiliskIIGUI -GUI_APP_APP = $(GUI_APP).app -PROGS += $(GUI_APP)$(EXEEXT) -else -CXXFLAGS += $(GUI_CFLAGS) -LIBS += $(GUI_LIBS) -endif ## Rules -.PHONY: modules install installdirs uninstall mostlyclean clean distclean depend dep +.PHONY: install installdirs uninstall mostlyclean clean distclean depend dep .SUFFIXES: .SUFFIXES: .c .cpp .s .o .h @@ -93,60 +73,18 @@ endef OBJS := $(SRCS_LIST_TO_OBJS) SRCS := $(SRCS:%=@top_srcdir@/%) -define GUI_SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .guio, $(foreach file, $(GUI_SRCS), \ - $(basename $(notdir $(file)))))) -endef -GUI_OBJS = $(GUI_SRCS_LIST_TO_OBJS) -GUI_SRCS := $(GUI_SRCS:%=@top_srcdir@/%) - SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) VPATH := VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) ## Documentation files -OSX_DOCS = ../MacOSX/Credits.html ../MacOSX/ToDo.html ../MacOSX/HowTo.html ../MacOSX/Versions.html $(APP)$(EXEEXT): $(OBJ_DIR) $(OBJS) $(CXX) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) $(BLESS) $(APP)$(EXEEXT) -$(GUI_APP)$(EXEEXT): $(OBJ_DIR) $(GUI_OBJS) - $(CXX) -o $@ $(LDFLAGS) $(GUI_OBJS) $(GUI_LIBS) - -$(APP)_app: $(APP) $(OSX_DOCS) ../../README ../MacOSX/Info.plist ../MacOSX/$(APP).icns - rm -rf $(APP_APP)/Contents - mkdir -p $(APP_APP)/Contents - ./cpr.sh ../MacOSX/Info.plist $(APP_APP)/Contents/ - echo -n 'APPL????' > $(APP_APP)/Contents/PkgInfo - mkdir -p $(APP_APP)/Contents/MacOS - ./cpr.sh $(APP) $(APP_APP)/Contents/MacOS/ - strip -x $(APP_APP)/Contents/MacOS/$(APP) - mkdir -p $(APP_APP)/Contents/Resources - ./cpr.sh ../MacOSX/$(APP).icns $(APP_APP)/Contents/Resources/ - ./cpr.sh ../MacOSX/English.lproj $(APP_APP)/Contents/Resources/ - cp -f $(OSX_DOCS) $(APP_APP)/Contents/Resources/ - cp -f ../../README $(APP_APP)/Contents/Resources/README.txt - -$(GUI_APP)_app: $(GUI_APP) ../MacOSX/Info.plist ../MacOSX/$(APP).icns - rm -rf $(GUI_APP_APP)/Contents - mkdir -p $(GUI_APP_APP)/Contents - sed -e "s/$(APP)/$(GUI_APP)/" < ../MacOSX/Info.plist > $(GUI_APP_APP)/Contents/Info.plist - echo -n 'APPL????' > $(GUI_APP_APP)/Contents/PkgInfo - mkdir -p $(GUI_APP_APP)/Contents/MacOS - ./cpr.sh $(GUI_APP) $(GUI_APP_APP)/Contents/MacOS/ - strip -x $(GUI_APP_APP)/Contents/MacOS/$(GUI_APP) - mkdir -p $(GUI_APP_APP)/Contents/Resources - ./cpr.sh ../MacOSX/$(APP).icns $(GUI_APP_APP)/Contents/Resources/$(GUI_APP).icns - -modules: - cd Linux/NetDriver; make - install: $(PROGS) installdirs $(INSTALL_PROGRAM) $(APP)$(EXEEXT) $(DESTDIR)$(bindir)/$(APP)$(EXEEXT) - if test -f "$(GUI_APP)$(EXEEXT)"; then \ - $(INSTALL_PROGRAM) $(GUI_APP)$(EXEEXT) $(DESTDIR)$(bindir)/$(GUI_APP)$(EXEEXT); \ - fi -$(INSTALL_DATA) @top_srcdir@/$(APP_BASENAME).1 $(DESTDIR)$(man1dir)/$(APP).1 $(INSTALL_DATA) @top_srcdir@/$(KEYCODES) $(DESTDIR)$(datadir)/$(APP)/keycodes $(INSTALL_DATA) @top_srcdir@/fbdevices $(DESTDIR)$(datadir)/$(APP)/fbdevices @@ -157,7 +95,6 @@ installdirs: uninstall: rm -f $(DESTDIR)$(bindir)/$(APP)$(EXEEXT) - rm -f $(DESTDIR)$(bindir)/$(GUI_APP)$(EXEEXT) rm -f $(DESTDIR)$(man1dir)/$(APP).1 rm -f $(DESTDIR)$(datadir)/$(APP)/keycodes rm -f $(DESTDIR)$(datadir)/$(APP)/fbdevices @@ -168,7 +105,7 @@ mostlyclean: rm -f $(PROGS) $(OBJ_DIR)/* core* *.core *~ *.bak clean: mostlyclean - rm -f cpuemu.cpp cpudefs.cpp cputmp*.s cpufast*.s cpustbl.cpp cputbl.h compemu.cpp compstbl.cpp comptbl.h + rm -f cpuemu.cpp cpudefs.cpp cputmp*.s cpufast*.s cpustbl.cpp cputbl.h distclean: clean rm -rf $(OBJ_DIR) @@ -180,10 +117,6 @@ distclean: clean depend dep: makedepend $(CPPFLAGS) -Y. $(SRCS) 2>/dev/null -$(OBJ_DIR)/SDLMain.o : SDLMain.m - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : @top_srcdir@/../slirp/%.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(SLIRP_CFLAGS) -c $< -o $@ $(OBJ_DIR)/%.o : %.c $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ $(OBJ_DIR)/%.o : %.cpp @@ -194,90 +127,19 @@ $(OBJ_DIR)/%.o : %.mm $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ $(OBJ_DIR)/%.o : %.s $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.guio : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) $(GUI_CFLAGS) -DSTANDALONE_GUI -c $< -o $@ - -# Windows resources -$(OBJ_DIR)/%.o: %.rc - windres --include-dir ../Windows -i $< -o $@ $(OBJ_DIR)/build68k$(EXEEXT): $(OBJ_DIR)/build68k.o $(CC) $(LDFLAGS) -o $(OBJ_DIR)/build68k$(EXEEXT) $(OBJ_DIR)/build68k.o $(OBJ_DIR)/gencpu$(EXEEXT): $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o $(CXX) $(LDFLAGS) -o $(OBJ_DIR)/gencpu$(EXEEXT) $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o -$(OBJ_DIR)/gencomp$(EXEEXT): $(OBJ_DIR)/gencomp.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o - $(CXX) $(LDFLAGS) -o $(OBJ_DIR)/gencomp$(EXEEXT) $(OBJ_DIR)/gencomp.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o cpudefs.cpp: $(OBJ_DIR)/build68k$(EXEEXT) @top_srcdir@/../uae_cpu/table68k $(OBJ_DIR)/build68k$(EXEEXT) <@top_srcdir@/../uae_cpu/table68k >cpudefs.cpp cpustbl.cpp: cpuemu.cpp -cpustbl_nf.cpp: cpustbl.cpp -compstbl.cpp: compemu.cpp cputbl.h: cpuemu.cpp -comptbl.h: compemu.cpp cpuemu.cpp: $(OBJ_DIR)/gencpu$(EXEEXT) $(OBJ_DIR)/gencpu$(EXEEXT) -compemu.cpp: $(OBJ_DIR)/gencomp$(EXEEXT) - $(OBJ_DIR)/gencomp$(EXEEXT) - -$(OBJ_DIR)/cpustbl_nf.o: cpustbl.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -DNOFLAGS -c $< -o $@ - -$(OBJ_DIR)/compemu_support.o: compemu_support.cpp comptbl.h - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/cpuemu1.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_1 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu2.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_2 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu3.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_3 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu4.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_4 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu5.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_5 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu6.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_6 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu7.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_7 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu8.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_8 $(CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/cpuemu1_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_1 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu2_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_2 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu3_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_3 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu4_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_4 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu5_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_5 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu6_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_6 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu7_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_7 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu8_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_8 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/compemu1.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_1 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu2.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_2 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu3.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_3 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu4.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_4 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu5.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_5 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu6.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_6 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu7.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_7 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu8.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_8 $(CXXFLAGS) -c $< -o $@ - #------------------------------------------------------------------------- # DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/BasiliskII/src/Unix/Solaris/audio_solaris.cpp b/BasiliskII/src/Unix/Solaris/audio_solaris.cpp deleted file mode 100644 index d4b7e0df..00000000 --- a/BasiliskII/src/Unix/Solaris/audio_solaris.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* - * audio_solaris.cpp - Audio support, Solaris implementation - * - * Adapted from Frodo's Solaris sound routines by Marc Chabanas - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "audio.h" -#include "audio_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static int fd = -1; // fd of /dev/audio -static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read -static pthread_t stream_thread; // Audio streaming thread -static pthread_attr_t stream_thread_attr; // Streaming thread attributes -static bool stream_thread_active = false; -static int sound_buffer_size; // Size of sound buffer in bytes - -// Prototypes -static void *stream_func(void *arg); - - -/* - * Initialization - */ - -// Set AudioStatus to reflect current audio stream format -static void set_audio_status_format(void) -{ - AudioStatus.sample_rate = audio_sample_rates[0]; - AudioStatus.sample_size = audio_sample_sizes[0]; - AudioStatus.channels = audio_channel_counts[0]; -} - -void AudioInit(void) -{ - char str[256]; - - // Init audio status and feature flags - audio_sample_rates.push_back(44100 << 16); - audio_sample_sizes.push_back(16); - audio_channel_counts.push_back(2); - set_audio_status_format(); - AudioStatus.mixer = 0; - AudioStatus.num_sources = 0; - audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut; - - // Sound disabled in prefs? Then do nothing - if (PrefsFindBool("nosound")) - return; - - // Init semaphore - if (sem_init(&audio_irq_done_sem, 0, 0) < 0) - return; - - // Open /dev/audio - fd = open("/dev/audio", O_WRONLY | O_NDELAY); - if (fd < 0) { - sprintf(str, GetString(STR_NO_AUDIO_DEV_WARN), "/dev/audio", strerror(errno)); - WarningAlert(str); - sem_destroy(&audio_irq_done_sem); - return; - } - - // Set audio parameters - struct audio_info info; - AUDIO_INITINFO(&info); - info.play.sample_rate = AudioStatus.sample_rate >> 16; - info.play.channels = AudioStatus.channels; - info.play.precision = AudioStatus.sample_size; - info.play.encoding = AUDIO_ENCODING_LINEAR; - info.play.port = AUDIO_SPEAKER; - if (ioctl(fd, AUDIO_SETINFO, &info)) { - WarningAlert(GetString(STR_AUDIO_FORMAT_WARN)); - close(fd); - fd = -1; - sem_destroy(&audio_irq_done_sem); - return; - } - - // 2048 frames per buffer - audio_frames_per_block = 2048; - sound_buffer_size = (AudioStatus.sample_size>>3) * AudioStatus.channels * audio_frames_per_block; - - // Start audio thread - Set_pthread_attr(&stream_thread_attr, 0); - stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0); - - // Everything OK - audio_open = true; -} - - -/* - * Deinitialization - */ - -void AudioExit(void) -{ - // Stop audio thread - if (stream_thread_active) { - pthread_cancel(stream_thread); - pthread_join(stream_thread, NULL); - sem_destroy(&audio_irq_done_sem); - stream_thread_active = false; - } - - // Close /dev/audio - if (fd > 0) { - ioctl(fd, AUDIO_DRAIN); - close(fd); - } -} - - -/* - * First source added, start audio stream - */ - -void audio_enter_stream() -{ -} - - -/* - * Last source removed, stop audio stream - */ - -void audio_exit_stream() -{ -} - - -/* - * Streaming function - */ - -static uint32 apple_stream_info; // Mac address of SoundComponentData struct describing next buffer - -static void *stream_func(void *arg) -{ - int16 *silent_buffer = new int16[sound_buffer_size / 2]; - int16 *last_buffer = new int16[sound_buffer_size / 2]; - memset(silent_buffer, 0, sound_buffer_size); - - uint_t sent = 0, delta; - struct audio_info status; - - for (;;) { - if (AudioStatus.num_sources) { - - // Trigger audio interrupt to get new buffer - D(bug("stream: triggering irq\n")); - SetInterruptFlag(INTFLAG_AUDIO); - TriggerInterrupt(); - D(bug("stream: waiting for ack\n")); - sem_wait(&audio_irq_done_sem); - D(bug("stream: ack received\n")); - - // Get size of audio data - uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo); - if (apple_stream_info) { - int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels; - D(bug("stream: work_size %d\n", work_size)); - if (work_size > sound_buffer_size) - work_size = sound_buffer_size; - if (work_size == 0) - goto silence; - - // Send data to audio port - if (work_size == sound_buffer_size) - write(fd, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), sound_buffer_size); - else { - // Last buffer - Mac2Host_memcpy(last_buffer, ReadMacInt32(apple_stream_info + scd_buffer), work_size); - memset((uint8 *)last_buffer + work_size, 0, sound_buffer_size - work_size); - write(fd, last_buffer, sound_buffer_size); - } - D(bug("stream: data written\n")); - } else - goto silence; - - } else { - - // Audio not active, play silence -silence: write(fd, silent_buffer, sound_buffer_size); - } - - // We allow a maximum of three buffers to be sent - sent += audio_frames_per_block; - ioctl(fd, AUDIO_GETINFO, &status); - while ((delta = sent - status.play.samples) > (audio_frames_per_block * 3)) { - unsigned int sl = 1000000 * (delta - audio_frames_per_block * 3) / (AudioStatus.sample_rate >> 16); - usleep(sl); - ioctl(fd, AUDIO_GETINFO, &status); - } - } - return NULL; -} - - -/* - * MacOS audio interrupt, read next data block - */ - -void AudioInterrupt(void) -{ - D(bug("AudioInterrupt\n")); - - // Get data from apple mixer - if (AudioStatus.mixer) { - M68kRegisters r; - r.a[0] = audio_data + adatStreamInfo; - r.a[1] = AudioStatus.mixer; - Execute68k(audio_data + adatGetSourceData, &r); - D(bug(" GetSourceData() returns %08lx\n", r.d[0])); - } else - WriteMacInt32(audio_data + adatStreamInfo, 0); - - // Signal stream function - sem_post(&audio_irq_done_sem); - D(bug("AudioInterrupt done\n")); -} - - -/* - * Set sampling parameters - * "index" is an index into the audio_sample_rates[] etc. arrays - * It is guaranteed that AudioStatus.num_sources == 0 - */ - -bool audio_set_sample_rate(int index) -{ - return true; -} - -bool audio_set_sample_size(int index) -{ - return true; -} - -bool audio_set_channels(int index) -{ - return true; -} - - -/* - * Get/set volume controls (volume values received/returned have the left channel - * volume in the upper 16 bits and the right channel volume in the lower 16 bits; - * both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume")) - */ - -bool audio_get_main_mute(void) -{ - return false; -} - -uint32 audio_get_main_volume(void) -{ - return 0x01000100; -} - -bool audio_get_speaker_mute(void) -{ - return false; -} - -uint32 audio_get_speaker_volume(void) -{ - return 0x01000100; -} - -void audio_set_main_mute(bool mute) -{ -} - -void audio_set_main_volume(uint32 vol) -{ -} - -void audio_set_speaker_mute(bool mute) -{ -} - -void audio_set_speaker_volume(uint32 vol) -{ -} diff --git a/BasiliskII/src/Unix/Solaris/which_sparc b/BasiliskII/src/Unix/Solaris/which_sparc deleted file mode 100755 index b6824fd0..00000000 --- a/BasiliskII/src/Unix/Solaris/which_sparc +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -# which_sparc -# -# This script generates a program that tests for a SPARC processor class -# Program returns: -# 0 unknown SPARC processor -# 8 SPARC V8 `compliant' processor (umul instruction is legal) -# 9 SPARC V9 `compliant' processor (popc instruction is legal) -# -# The script prints: -# "unknown SPARC architecture" -# SPARC_V8 -# SPARC_V9 -# -# I hope this works for other machines and OS. Tested machines are: -# Sun Ultra 10 (Solaris 7), SPARC Station 5 (Solaris 2.5.1) -# -# Gwenole Beauchesne -# gb@dial.oleane.com - -CC=gcc -PROG=./conftest -SOURCE=./conftest.c - -if [ ! -x $PROG ]; then -cat > $SOURCE << EOF -#include -#include - -typedef unsigned int uint32; -typedef uint32 (*sparc_code_func)(void); - -#define SPARC_UNKNOWN 0 -#define SPARC_V8 8 -#define SPARC_V9 9 - -#define MAX_CODE_SIZE 16 -struct sparc_code_struct { - int version; - uint32 code[MAX_CODE_SIZE]; - struct sparc_code_struct * next; -}; -typedef struct sparc_code_struct sparc_code_struct; - -static sparc_code_struct *current_test_code; - -static sparc_code_struct unknown_sparc_code = -{ - SPARC_UNKNOWN, - { - 0x81C3E008, /* retl */ - 0x01000000 /* nop */ - } -}; - -static sparc_code_struct sparc_v9_code = -{ - SPARC_V9, - { - 0x81C3E008, /* retl */ - 0x81702007 /* popc 7, %g0 */ - } -}; - -static sparc_code_struct sparc_v8_code = -{ - SPARC_V8, - { - 0x90102002, /* mov 2, %o0 */ - 0x81C3E008, /* retl */ - 0x90520008 /* umul %o0, %o0, %o0 */ - } -}; - -static void test_sparc_code(int unused_int) -{ - sparc_code_struct *tested_code = current_test_code; - - if (current_test_code == NULL) - exit(SPARC_UNKNOWN); - - signal(SIGILL, test_sparc_code); - current_test_code = current_test_code->next; - (void) ((sparc_code_func)(tested_code->code))(); - exit(tested_code->version); -} - -int main(void) -{ - sparc_v9_code.next = &sparc_v8_code; - sparc_v8_code.next = &unknown_sparc_code; - unknown_sparc_code.next = NULL; - - signal(SIGILL, test_sparc_code); - current_test_code = &sparc_v9_code; - raise(SIGILL); - - return 0; -} -EOF - -$CC -o $PROG $SOURCE -if [ $? -ne 0 ]; then - echo "Error: could not compile the test program" - exit 1 -fi - -fi - -$PROG -case $? in - 0) echo "unknown SPARC architecture";; - 8) echo "SPARC_V8";; - 9) echo "SPARC_V9";; -esac - -rm -f $PROG -rm -f $SOURCE - -exit 0 diff --git a/BasiliskII/src/Unix/asm_support.s b/BasiliskII/src/Unix/asm_support.s deleted file mode 100644 index ba7b0ba1..00000000 --- a/BasiliskII/src/Unix/asm_support.s +++ /dev/null @@ -1,180 +0,0 @@ -/* - * asm_support.s - Utility functions in assembly language (for native 68k support) - * - * Basilisk II (C) 1997-2005 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - .file "asm_support.s" - .text - - .globl _m68k_sync_icache - .globl _Start680x0__Fv - .globl _SetInterruptFlag__FUi - .globl _ClearInterruptFlag__FUi - .globl _Execute68k - .globl _Execute68kTrap - .globl _EmulOpTrampoline - - .globl _RAMBaseHost - .globl _ROMBaseHost - .globl _EmulOp__FUsP13M68kRegisters - .globl _EmulatedSR - .globl _InterruptFlags - .globl _TriggerInterrupt__Fv - - -/* - * Call m68k_sync_icache() (NetBSD, the version in libm68k is broken) - */ - - .type _m68k_sync_icache,@function -_m68k_sync_icache: - movl sp@(8),d1 - movl sp@(4),a1 - movl #0x80000004,d0 - trap #12 - rts - - -/* - * Jump to Mac ROM, start emulation - */ - - .type _Start680x0__Fv,@function -_Start680x0__Fv: - movl _RAMBaseHost,a0 - addl #0x8000,a0 - movl a0,sp - movl _ROMBaseHost,a0 - lea a0@(0x2a),a0 - jmp a0@ - - -/* - * Set/clear interrupt flag (atomically) - */ - - .type _SetInterruptFlag__FUi,@function -_SetInterruptFlag__FUi: - movl sp@(4),d0 - orl d0,_InterruptFlags - rts - - .type _ClearInterruptFlag__FUi,@function -_ClearInterruptFlag__FUi: - movl sp@(4),d0 - notl d0 - andl d0,_InterruptFlags - rts - - -/* - * Execute 68k subroutine (must be ended with rts) - * r->a[7] and r->sr are unused! - */ - -/* void Execute68k(uint32 addr, M68kRegisters *r); */ - .type _Execute68k,@function -_Execute68k: movl sp@(4),d0 |Get arguments - movl sp@(8),a0 - - movml d2-d7/a2-a6,sp@- |Save registers - - movl a0,sp@- |Push pointer to M68kRegisters on stack - pea exec68kret |Push return address on stack - movl d0,sp@- |Push pointer to 68k routine on stack - movml a0@,d0-d7/a0-a6 |Load registers from M68kRegisters - - rts |Jump into 68k routine - -exec68kret: movl a6,sp@- |Save a6 - movl sp@(4),a6 |Get pointer to M68kRegisters - movml d0-d7/a0-a5,a6@ |Save d0-d7/a0-a5 to M68kRegisters - movl sp@+,a6@(56) |Save a6 to M68kRegisters - addql #4,sp |Remove pointer from stack - - movml sp@+,d2-d7/a2-a6 |Restore registers - rts - - -/* - * Execute MacOS 68k trap - * r->a[7] and r->sr are unused! - */ - -/* void Execute68kTrap(uint16 trap, M68kRegisters *r); */ - .type _Execute68kTrap,@function -_Execute68kTrap: - movl sp@(4),d0 |Get arguments - movl sp@(8),a0 - - movml d2-d7/a2-a6,sp@- |Save registers - - movl a0,sp@- |Push pointer to M68kRegisters on stack - movw d0,sp@- |Push trap word on stack - subql #8,sp |Create fake A-Line exception frame - movml a0@,d0-d7/a0-a6 |Load registers from M68kRegisters - - movl a2,sp@- |Save a2 and d2 - movl d2,sp@- - lea exectrapret,a2 |a2 points to return address - movw sp@(16),d2 |Load trap word into d2 - - jmp zpc@(0x28:w)@(10) |Jump into MacOS A-Line handler - -exectrapret: movl a6,sp@- |Save a6 - movl sp@(6),a6 |Get pointer to M68kRegisters - movml d0-d7/a0-a5,a6@ |Save d0-d7/a0-a5 to M68kRegisters - movl sp@+,a6@(56) |Save a6 to M68kRegisters - addql #6,sp |Remove pointer and trap word from stack - - movml sp@+,d2-d7/a2-a6 |Restore registers - rts - - -/* - * Call EmulOp() after return from SIGILL handler, registers are pushed on stack - */ - - .type _EmulOpTrampoline,@function -_EmulOpTrampoline: - movl sp,a0 |Get pointer to registers - - movw _EmulatedSR,d0 |Save EmulatedSR, disable interrupts - movw d0,sp@- - oriw #0x0700,d0 - movw d0,_EmulatedSR - - movl a0,sp@- |Push pointer to registers - movl a0@(66),a1 |Get saved PC - addql #2,a0@(66) |Skip EMUL_OP opcode - movw a1@,sp@- |Push opcode word - clrw sp@- - jbsr _EmulOp__FUsP13M68kRegisters - addql #8,sp - - movw sp@+,d0 |Restore interrupts, trigger pending interrupt - movw d0,_EmulatedSR - andiw #0x0700,d0 - bne eot1 - tstl _InterruptFlags - beq eot1 - jbsr _TriggerInterrupt__Fv - -eot1: moveml sp@+,d0-d7/a0-a6 |Restore registers - addql #4,sp |Skip saved SP - rtr diff --git a/BasiliskII/src/Unix/audio_oss_esd.cpp b/BasiliskII/src/Unix/audio_oss_esd.cpp deleted file mode 100644 index 203a5ac7..00000000 --- a/BasiliskII/src/Unix/audio_oss_esd.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/* - * audio_oss_esd.cpp - Audio support, implementation for OSS and ESD (Linux and FreeBSD) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include - -#ifdef __linux__ -#include -#endif - -#ifdef __FreeBSD__ -#include -#endif - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "audio.h" -#include "audio_defs.h" - -#ifdef ENABLE_ESD -#include -#endif - -#define DEBUG 0 -#include "debug.h" - - -// The currently selected audio parameters (indices in audio_sample_rates[] etc. vectors) -static int audio_sample_rate_index = 0; -static int audio_sample_size_index = 0; -static int audio_channel_count_index = 0; - -// Global variables -static bool is_dsp_audio = false; // Flag: is DSP audio -static int audio_fd = -1; // fd of dsp or ESD -static int mixer_fd = -1; // fd of mixer -static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read -static bool sem_inited = false; // Flag: audio_irq_done_sem initialized -static int sound_buffer_size; // Size of sound buffer in bytes -static bool little_endian = false; // Flag: DSP accepts only little-endian 16-bit sound data -static uint8 silence_byte; // Byte value to use to fill sound buffers with silence -static pthread_t stream_thread; // Audio streaming thread -static pthread_attr_t stream_thread_attr; // Streaming thread attributes -static bool stream_thread_active = false; // Flag: streaming thread installed -static volatile bool stream_thread_cancel = false; // Flag: cancel streaming thread - -// Prototypes -static void *stream_func(void *arg); - - -/* - * Initialization - */ - -// Set AudioStatus to reflect current audio stream format -static void set_audio_status_format(void) -{ - AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index]; - AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index]; - AudioStatus.channels = audio_channel_counts[audio_channel_count_index]; -} - -// Init using the dsp device, returns false on error -static bool open_dsp(void) -{ - // Open the device - const char *dsp = PrefsFindString("dsp"); - audio_fd = open(dsp, O_WRONLY); - if (audio_fd < 0) { - fprintf(stderr, "WARNING: Cannot open %s (%s)\n", dsp, strerror(errno)); - return false; - } - - printf("Using %s audio output\n", dsp); - is_dsp_audio = true; - - // Get supported sample formats - if (audio_sample_sizes.empty()) { - unsigned long format; - ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format); - if (format & AFMT_U8) - audio_sample_sizes.push_back(8); - if (format & (AFMT_S16_BE | AFMT_S16_LE)) - audio_sample_sizes.push_back(16); - - int stereo = 0; - if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 0) - audio_channel_counts.push_back(1); - stereo = 1; - if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 1) - audio_channel_counts.push_back(2); - - if (audio_sample_sizes.empty() || audio_channel_counts.empty()) { - WarningAlert(GetString(STR_AUDIO_FORMAT_WARN)); - close(audio_fd); - audio_fd = -1; - return false; - } - - audio_sample_rates.push_back(11025 << 16); - audio_sample_rates.push_back(22050 << 16); - int rate = 44100; - ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate); - if (rate > 22050) - audio_sample_rates.push_back(rate << 16); - - // Default to highest supported values - audio_sample_rate_index = audio_sample_rates.size() - 1; - audio_sample_size_index = audio_sample_sizes.size() - 1; - audio_channel_count_index = audio_channel_counts.size() - 1; - } - - // Set DSP parameters - unsigned long format; - if (audio_sample_sizes[audio_sample_size_index] == 8) { - format = AFMT_U8; - little_endian = false; - silence_byte = 0x80; - } else { - unsigned long sup_format; - ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &sup_format); - if (sup_format & AFMT_S16_BE) { - little_endian = false; - format = AFMT_S16_BE; - } else { - little_endian = true; - format = AFMT_S16_LE; - } - silence_byte = 0; - } - ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format); - int frag = 0x0004000c; // Block size: 4096 frames - ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag); - int stereo = (audio_channel_counts[audio_channel_count_index] == 2); - ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo); - int rate = audio_sample_rates[audio_sample_rate_index] >> 16; - ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate); - - // Get sound buffer size - ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &audio_frames_per_block); - D(bug("DSP_GETBLKSIZE %d\n", audio_frames_per_block)); - return true; -} - -// Init using ESD, returns false on error -static bool open_esd(void) -{ -#ifdef ENABLE_ESD - int rate; - esd_format_t format = ESD_STREAM | ESD_PLAY; - - if (audio_sample_sizes.empty()) { - - // Default values - rate = 44100; - format |= (ESD_BITS16 | ESD_STEREO); - - } else { - - rate = audio_sample_rates[audio_sample_rate_index] >> 16; - if (audio_sample_sizes[audio_sample_size_index] == 8) - format |= ESD_BITS8; - else - format |= ESD_BITS16; - if (audio_channel_counts[audio_channel_count_index] == 1) - format |= ESD_MONO; - else - format |= ESD_STEREO; - } - -#if WORDS_BIGENDIAN - little_endian = false; -#else - little_endian = true; -#endif - silence_byte = 0; // Is this correct for 8-bit mode? - - // Open connection to ESD server - audio_fd = esd_play_stream(format, rate, NULL, NULL); - if (audio_fd < 0) { - fprintf(stderr, "WARNING: Cannot open ESD connection\n"); - return false; - } - - printf("Using ESD audio output\n"); - - // ESD supports a variety of twisted little audio formats, all different - if (audio_sample_sizes.empty()) { - - // The reason we do this here is that we don't want to add sample - // rates etc. unless the ESD server connection could be opened - // (if ESD fails, dsp might be tried next) - audio_sample_rates.push_back(11025 << 16); - audio_sample_rates.push_back(22050 << 16); - audio_sample_rates.push_back(44100 << 16); - audio_sample_sizes.push_back(8); - audio_sample_sizes.push_back(16); - audio_channel_counts.push_back(1); - audio_channel_counts.push_back(2); - - // Default to highest supported values - audio_sample_rate_index = audio_sample_rates.size() - 1; - audio_sample_size_index = audio_sample_sizes.size() - 1; - audio_channel_count_index = audio_channel_counts.size() - 1; - } - - // Sound buffer size = 4096 frames - audio_frames_per_block = 4096; - return true; -#else - // ESD is not enabled, shut up the compiler - return false; -#endif -} - -static bool open_audio(void) -{ -#ifdef ENABLE_ESD - // If ESPEAKER is set, the user probably wants to use ESD, so try that first - if (getenv("ESPEAKER")) - if (open_esd()) - goto dev_opened; -#endif - - // Try to open dsp - if (open_dsp()) - goto dev_opened; - -#ifdef ENABLE_ESD - // Hm, dsp failed so we try ESD again if ESPEAKER wasn't set - if (!getenv("ESPEAKER")) - if (open_esd()) - goto dev_opened; -#endif - - // No audio device succeeded - WarningAlert(GetString(STR_NO_AUDIO_WARN)); - return false; - - // Device opened, set AudioStatus -dev_opened: - sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) * audio_channel_counts[audio_channel_count_index] * audio_frames_per_block; - set_audio_status_format(); - - // Start streaming thread - Set_pthread_attr(&stream_thread_attr, 0); - stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0); - - // Everything went fine - audio_open = true; - return true; -} - -void AudioInit(void) -{ - // Init audio status (reasonable defaults) and feature flags - AudioStatus.sample_rate = 44100 << 16; - AudioStatus.sample_size = 16; - AudioStatus.channels = 2; - AudioStatus.mixer = 0; - AudioStatus.num_sources = 0; - audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut; - - // Sound disabled in prefs? Then do nothing - if (PrefsFindBool("nosound")) - return; - - // Init semaphore - if (sem_init(&audio_irq_done_sem, 0, 0) < 0) - return; - sem_inited = true; - - // Try to open the mixer device - const char *mixer = PrefsFindString("mixer"); - mixer_fd = open(mixer, O_RDWR); - if (mixer_fd < 0) - printf("WARNING: Cannot open %s (%s)\n", mixer, strerror(errno)); - - // Open and initialize audio device - open_audio(); -} - - -/* - * Deinitialization - */ - -static void close_audio(void) -{ - // Stop stream and delete semaphore - if (stream_thread_active) { - stream_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(stream_thread); -#endif - pthread_join(stream_thread, NULL); - stream_thread_active = false; - } - - // Close dsp or ESD socket - if (audio_fd >= 0) { - close(audio_fd); - audio_fd = -1; - } - - audio_open = false; -} - -void AudioExit(void) -{ - // Stop the device immediately. Otherwise, close() sends - // SNDCTL_DSP_SYNC, which may hang - if (is_dsp_audio) - ioctl(audio_fd, SNDCTL_DSP_RESET, 0); - - // Close audio device - close_audio(); - - // Delete semaphore - if (sem_inited) { - sem_destroy(&audio_irq_done_sem); - sem_inited = false; - } - - // Close mixer device - if (mixer_fd >= 0) { - close(mixer_fd); - mixer_fd = -1; - } -} - - -/* - * First source added, start audio stream - */ - -void audio_enter_stream() -{ - // Streaming thread is always running to avoid clicking noises -} - - -/* - * Last source removed, stop audio stream - */ - -void audio_exit_stream() -{ - // Streaming thread is always running to avoid clicking noises -} - - -/* - * Streaming function - */ - -static void *stream_func(void *arg) -{ - int16 *silent_buffer = new int16[sound_buffer_size / 2]; - int16 *last_buffer = new int16[sound_buffer_size / 2]; - memset(silent_buffer, silence_byte, sound_buffer_size); - - while (!stream_thread_cancel) { - if (AudioStatus.num_sources) { - - // Trigger audio interrupt to get new buffer - D(bug("stream: triggering irq\n")); - SetInterruptFlag(INTFLAG_AUDIO); - TriggerInterrupt(); - D(bug("stream: waiting for ack\n")); - sem_wait(&audio_irq_done_sem); - D(bug("stream: ack received\n")); - - // Get size of audio data - uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo); - if (apple_stream_info) { - int work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels; - D(bug("stream: work_size %d\n", work_size)); - if (work_size > sound_buffer_size) - work_size = sound_buffer_size; - if (work_size == 0) - goto silence; - - // Send data to DSP - if (work_size == sound_buffer_size && !little_endian) - write(audio_fd, Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)), sound_buffer_size); - else { - // Last buffer or little-endian DSP - if (little_endian) { - int16 *p = (int16 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer)); - for (int i=0; i= 0) { - int vol; - if (ioctl(mixer_fd, SOUND_MIXER_READ_PCM, &vol) == 0) { - int left = vol >> 8; - int right = vol & 0xff; - return ((left * 256 / 100) << 16) | (right * 256 / 100); - } - } - return 0x01000100; -} - -bool audio_get_speaker_mute(void) -{ - return false; -} - -uint32 audio_get_speaker_volume(void) -{ - if (mixer_fd >= 0) { - int vol; - if (ioctl(mixer_fd, SOUND_MIXER_READ_VOLUME, &vol) == 0) { - int left = vol >> 8; - int right = vol & 0xff; - return ((left * 256 / 100) << 16) | (right * 256 / 100); - } - } - return 0x01000100; -} - -void audio_set_main_mute(bool mute) -{ -} - -void audio_set_main_volume(uint32 vol) -{ - if (mixer_fd >= 0) { - int left = vol >> 16; - int right = vol & 0xffff; - int p = ((left * 100 / 256) << 8) | (right * 100 / 256); - ioctl(mixer_fd, SOUND_MIXER_WRITE_PCM, &p); - } -} - -void audio_set_speaker_mute(bool mute) -{ -} - -void audio_set_speaker_volume(uint32 vol) -{ - if (mixer_fd >= 0) { - int left = vol >> 16; - int right = vol & 0xffff; - int p = ((left * 100 / 256) << 8) | (right * 100 / 256); - ioctl(mixer_fd, SOUND_MIXER_WRITE_VOLUME, &p); - } -} diff --git a/BasiliskII/src/Unix/bincue_unix.cpp b/BasiliskII/src/Unix/bincue_unix.cpp deleted file mode 100644 index 11c93548..00000000 --- a/BasiliskII/src/Unix/bincue_unix.cpp +++ /dev/null @@ -1,834 +0,0 @@ -/* - * Copyright (C) 2002-2010 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* Geoffrey Brown 2010 - * Includes ideas from dosbox src/dos/cdrom_image.cpp - * - * Limitations: 1) cue files must reference single bin file - * 2) only supports raw mode1 data and audio - * 3) no support for audio flags - * 4) requires SDL audio or OS X core audio - * 5) limited cue file keyword support - * - * Creating cue/bin files: - * cdrdao read-cd --read-raw --paranoia 3 foo.toc - * toc2cue foo.toc - */ - -#include "sysdeps.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef OSX_CORE_AUDIO -#include "../MacOSX/MacOSX_sound_if.h" -static int bincue_core_audio_callback(void); -#endif - -#ifdef USE_SDL_AUDIO -#include -#include -#endif - -#include "bincue_unix.h" -#define DEBUG 0 -#include "debug.h" - -#define MAXTRACK 100 -#define MAXLINE 512 -#define CD_FRAMES 75 -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 - -// Bits of Track Control Field -- These are standard for scsi cd players - -#define PREMPHASIS 0x1 -#define COPY 0x2 -#define DATA 0x4 -#define AUDIO 0 -#define FOURTRACK 0x8 - -// Audio status -- These are standard for scsi cd players - -#define CDROM_AUDIO_INVALID 0x00 -#define CDROM_AUDIO_PLAY 0x11 -#define CDROM_AUDIO_PAUSED 0x12 -#define CDROM_AUDIO_COMPLETED 0x13 -#define CDROM_AUDIO_ERROR 0x14 -#define CDROM_AUDIO_NO_STATUS 0x15 - -typedef unsigned char uint8; - -// cuefiles can be challenging as some information is -// implied. For example, there may a pregap (also postgap) -// of silence that must be generated. Here we implement -// only the pregap. - -typedef struct { - int number; - unsigned int start; // Track start in frames - unsigned int length; // Track length in frames - loff_t fileoffset; // Track frame start within file - unsigned int pregap; // Silence in frames to generate - unsigned char tcf; // Track control field -} Track; - -typedef struct { - char *binfile; // Binary file name - unsigned int length; // file length in frames - int binfh; // binary file handle - int tcnt; // number of tracks - Track tracks[MAXTRACK]; -} CueSheet; - -typedef struct { - CueSheet *cs; // cue sheet to play from - int audiofh; // file handle for audio data - unsigned int audioposition; // current position from audiostart (bytes) - unsigned int audiostart; // start position if playing (frame) - unsigned int audioend; // end position if playing (frames) - unsigned int silence; // pregap (silence) bytes - unsigned char audiostatus; // See defines above for status - loff_t fileoffset; // offset from file beginning to audiostart -#ifdef OSX_CORE_AUDIO - OSXsoundOutput soundoutput; -#endif -} CDPlayer; - -// Minute,Second,Frame data type - -typedef struct { - int m, s, f; // note size matters since we scan for %d ! -} MSF; - -// Parser State - -static unsigned int totalPregap; -static unsigned int prestart; - -// Audio System State - -static bool audio_enabled = false; -static uint8 silence_byte; - - -// CD Player state. Note only one player is supported ! - -static CDPlayer player; - -static void FramesToMSF(unsigned int frames, MSF *msf) -{ - msf->m = frames/(60 * CD_FRAMES); - frames = frames%(60 * CD_FRAMES); - msf->s = frames/CD_FRAMES; - msf->f = frames%CD_FRAMES; -} - -static int MSFToFrames(MSF msf) -{ - return (msf.m * 60 * CD_FRAMES) + (msf.s * CD_FRAMES) + msf.f; -} - - -static int PositionToTrack(CueSheet *cs, unsigned int position) -{ - int i; - MSF msf; - - FramesToMSF(position, &msf); - - for (i = 0; i < cs->tcnt; i++) { - if ((position >= cs->tracks[i].start) && - (position <= (cs->tracks[i].start + cs->tracks[i].length))) - break; - } - return i; -} - -static bool AddTrack(CueSheet *cs) -{ - int skip = prestart; - Track *prev; - Track *curr = &(cs->tracks[cs->tcnt]); - - prestart = 0; - - if (skip > 0) { - if (skip > curr->start) { - D(bug("AddTrack: prestart > start\n")); - return false; - } - } - - curr->fileoffset = curr->start * RAW_SECTOR_SIZE; - - // now we patch up the indicated time - - curr->start += totalPregap; - - // curr->pregap is supposed to be part of this track, but it - // must be generated as silence - - totalPregap += curr->pregap; - - if (cs->tcnt == 0) { - if (curr->number != 1) { - D(bug("AddTrack: number != 1\n")); - return false; - } - cs->tcnt++; - return true; - } - - prev = &(cs->tracks[cs->tcnt - 1]); - - if (prev->start < skip) - prev->length = skip - prev->start - curr->pregap; - else - prev->length = curr->start - prev->start - curr->pregap; - - // error checks - - if (curr->number <= 1) { - D(bug("Bad track number %d\n", curr->number)); - return false; - } - if ((prev->number + 1 != curr->number) && (curr->number != 0xAA)) { - D(bug("Bad track number %d\n", curr->number)); - return false; - } - if (curr->start < prev->start + prev->length) { - D(bug("unexpected start %d\n", curr->start)); - return false; - } - - cs->tcnt++; - return true; -} - -static bool ParseCueSheet(FILE *fh, CueSheet *cs, const char *cuefile) -{ - bool seen1st = false; - char line[MAXLINE]; - unsigned int i_line=0; - char *keyword; - - totalPregap = 0; - prestart = 0; - - while (fgets(line, MAXLINE, fh) != NULL) { - Track *curr = &cs->tracks[cs->tcnt]; - - // check for CUE file - - if (!i_line && (strncmp("FILE", line, 4) != 0)) { - return false; - } - i_line++; - - // extract keyword - - if (NULL != (keyword = strtok(line, " \t\n\t"))) { - if (!strcmp("FILE", keyword)) { - char *filename; - char *filetype; - - if (i_line > 1) { - D(bug("More than one FILE token\n")); - goto fail; - } - filename = strtok(NULL, "\"\t\n\r"); - filetype = strtok(NULL, " \"\t\n\r"); - if (strcmp("BINARY", filetype)) { - D(bug("Not binary file %s", filetype)); - goto fail; - } - else { - char *tmp = strdup(cuefile); - char *b = dirname(tmp); - cs->binfile = (char *) malloc(strlen(b) + strlen(filename) + 2); - sprintf(cs->binfile, "%s/%s", b, filename); - free(tmp); - } - } else if (!strcmp("TRACK", keyword)) { - char *field; - int i_track; - - if (seen1st) { - if (!AddTrack(cs)){ - D(bug("AddTrack failed \n")); - goto fail; - } - curr = &cs->tracks[cs->tcnt]; - } - - seen1st = true; - - // parse track number - - field = strtok(NULL, " \t\n\r"); - if (1 != sscanf(field, "%d", &i_track)) { - D(bug("Expected track number\n")); - goto fail; - } - curr->number = i_track; - - // parse track type - - field = strtok(NULL, " \t\n\r"); - if (!strcmp("MODE1/2352", field)) { - curr->tcf = DATA; - } else if (!strcmp("AUDIO", field)) { - curr->tcf = AUDIO; - } else { - D(bug("Unexpected track type %s", field)); - goto fail; - } - - } else if (!strcmp("INDEX", keyword)) { - char *field; - int i_index; - MSF msf; - - // parse INDEX number - - field = strtok(NULL, " \t\n\r"); - if (1 != sscanf(field, "%d", &i_index)) { - D(bug("Expected index number")); - goto fail; - } - - // parse INDEX start - - field = strtok(NULL, " \t\n\r"); - if (3 != sscanf(field, "%d:%d:%d", - &msf.m, &msf.s, &msf.f)) { - D(bug("Expected index start frame\n")); - goto fail; - } - - if (i_index == 1) - curr->start = MSFToFrames(msf); - else if (i_index == 0) - prestart = MSFToFrames(msf); - } else if (!strcmp("PREGAP", keyword)) { - MSF msf; - char *field = strtok(NULL, " \t\n\r"); - if (3 != sscanf(field, "%d:%d:%d", - &msf.m, &msf.s, &msf.f)) { - D(bug("Expected pregap frame\n")); - goto fail; - } - curr->pregap = MSFToFrames(msf); - - // Ignored directives - - } else if (!strcmp("TITLE", keyword)) { - } else if (!strcmp("PERFORMER", keyword)) { - } else if (!strcmp("REM", keyword)) { - } else if (!strcmp("ISRC", keyword)) { - } else if (!strcmp("SONGWRITER", keyword)) { - } else { - D(bug("Unexpected keyword %s\n", keyword)); - goto fail; - } - } - } - - AddTrack(cs); // add final track - return true; - fail: - return false; -} - -static bool LoadCueSheet(const char *cuefile, CueSheet *cs) -{ - FILE *fh = NULL; - int binfh = -1; - struct stat buf; - Track *tlast = NULL; - - if (cs) { - bzero(cs, sizeof(*cs)); - if (!(fh = fopen(cuefile, "r"))) - return false; - - if (!ParseCueSheet(fh, cs, cuefile)) goto fail; - - // Open bin file and find length - - if ((binfh = open(cs->binfile,O_RDONLY)) < 0) { - D(bug("Can't read bin file %s\n", cs->binfile)); - goto fail; - } - - if (fstat(binfh, &buf)) { - D(bug("fstat returned error\n")); - goto fail; - } - - // compute length of final track - - - tlast = &cs->tracks[cs->tcnt - 1]; - tlast->length = buf.st_size/RAW_SECTOR_SIZE - - tlast->start + totalPregap; - - if (tlast->length < 0) { - D(bug("Binary file too short \n")); - goto fail; - } - - // save bin file length and pointer - - cs->length = buf.st_size/RAW_SECTOR_SIZE; - cs->binfh = binfh; - - fclose(fh); - return true; - - fail: - if (binfh >= 0) - close(binfh); - fclose(fh); - free(cs->binfile); - return false; - - } - return false; -} - - - -void *open_bincue(const char *name) -{ - CueSheet *cs; - - if (player.cs == NULL) { - cs = (CueSheet *) malloc(sizeof(CueSheet)); - if (!cs) { - D(bug("malloc failed\n")); - return NULL; - } - - if (LoadCueSheet(name, cs)) { - player.cs = cs; -#ifdef OSX_CORE_AUDIO - audio_enabled = true; -#endif - if (audio_enabled) - player.audiostatus = CDROM_AUDIO_NO_STATUS; - else - player.audiostatus = CDROM_AUDIO_INVALID; - player.audiofh = dup(cs->binfh); - return cs; - } - else - free(cs); - } - return NULL; -} - -void close_bincue(void *fh) -{ - - -} - -/* - * File read (cooked) - * Data are stored in raw sectors of which only COOKED_SECTOR_SIZE - * bytes are valid -- the remaining include 16 bytes at the beginning - * of each raw sector and RAW_SECTOR_SIZE - COOKED_SECTOR_SIZE - bytes - * at the end - * - * We assume that a read request can land in the middle of - * sector. We compute the byte address of that sector (sec) - * and the offset of the first byte we want within that sector (secoff) - * - * Reading is performed one raw sector at a time, extracting as many - * valid bytes as possible from that raw sector (available) - */ - -size_t read_bincue(void *fh, void *b, loff_t offset, size_t len) -{ - size_t bytes_read = 0; // bytes read so far - unsigned char *buf = (unsigned char *) b; // target buffer - unsigned char secbuf[RAW_SECTOR_SIZE]; // temporary buffer - - off_t sec = ((offset/COOKED_SECTOR_SIZE) * RAW_SECTOR_SIZE); - off_t secoff = offset % COOKED_SECTOR_SIZE; - - // sec contains location (in bytes) of next raw sector to read - // secoff contains offset within that sector at which to start - // reading since we can request a read that starts in the middle - // of a sector - - CueSheet *cs = (CueSheet *) fh; - - if (cs == NULL || lseek(cs->binfh, sec, SEEK_SET) < 0) { - return -1; - } - while (len) { - - // bytes available in next raw sector or len (bytes) - // we want whichever is less - - size_t available = COOKED_SECTOR_SIZE - secoff; - available = (available > len) ? len : available; - - // read the next raw sector - - if (read(cs->binfh, secbuf, RAW_SECTOR_SIZE) != RAW_SECTOR_SIZE) { - return bytes_read; - } - - // copy cooked sector bytes (skip first 16) - // we want out of those available - - bcopy(&secbuf[16+secoff], &buf[bytes_read], available); - - // next sector we start at the beginning - - secoff = 0; - - // increment running count decrement request - - bytes_read += available; - len -= available; - } - return bytes_read; -} - -loff_t size_bincue(void *fh) -{ - if (fh) { - return ((CueSheet *)fh)->length * COOKED_SECTOR_SIZE; - } -} - -bool readtoc_bincue(void *fh, unsigned char *toc) -{ - CueSheet *cs = (CueSheet *) fh; - if (cs) { - - MSF msf; - unsigned char *p = toc + 2; - *p++ = cs->tracks[0].number; - *p++ = cs->tracks[cs->tcnt - 1].number; - for (int i = 0; i < cs->tcnt; i++) { - - FramesToMSF(cs->tracks[i].start, &msf); - *p++ = 0; - *p++ = 0x10 | cs->tracks[i].tcf; - *p++ = cs->tracks[i].number; - *p++ = 0; - *p++ = 0; - *p++ = msf.m; - *p++ = msf.s; - *p++ = msf.f; - } - FramesToMSF(cs->length, &msf); - *p++ = 0; - *p++ = 0x14; - *p++ = 0xAA; - *p++ = 0; - *p++ = 0; - *p++ = msf.m; - *p++ = msf.s; - *p++ = msf.f; - - int toc_size = p - toc; - *toc++ = toc_size >> 8; - *toc++ = toc_size & 0xff; - return true; - } -} - -bool GetPosition_bincue(void *fh, uint8 *pos) -{ - CueSheet *cs = (CueSheet *) fh; - if (cs && player.cs == cs) { - MSF abs, rel; - int fpos = player.audioposition / RAW_SECTOR_SIZE + player.audiostart; - int trackno = PositionToTrack(cs, fpos); - - if (!audio_enabled) - return false; - - FramesToMSF(fpos, &abs); - if (trackno < cs->tcnt) { - // compute position relative to start of frame - - unsigned int position = player.audioposition/RAW_SECTOR_SIZE + - player.audiostart - player.cs->tracks[trackno].start; - - FramesToMSF(position, &rel); - } - else - FramesToMSF(0, &rel); - - *pos++ = 0; - *pos++ = player.audiostatus; - *pos++ = 0; - *pos++ = 12; // Sub-Q data length - *pos++ = 0; - if (trackno < cs->tcnt) - *pos++ = 0x10 | cs->tracks[trackno].tcf; - *pos++ = (trackno < cs->tcnt) ? cs->tracks[trackno].number : 0xAA; - *pos++ = 1; // track index - *pos++ = 0; - *pos++ = abs.m; - *pos++ = abs.s; - *pos++ = abs.f; - *pos++ = 0; - *pos++ = rel.m; - *pos++ = rel.s; - *pos++ = rel.f; - *pos++ = 0; -// D(bug("CDROM position %02d:%02d:%02d track %02d\n", abs.m, abs.s, abs.f, trackno)); - return true; - } - else - return false; -} - -bool CDPause_bincue(void *fh) -{ - CueSheet *cs = (CueSheet *) fh; - if (cs && cs == player.cs) { - if (player.audiostatus == CDROM_AUDIO_PLAY) { - player.audiostatus = CDROM_AUDIO_PAUSED; - return true; - } - } - return false; -} - -bool CDStop_bincue(void *fh) -{ - CueSheet *cs = (CueSheet *) fh; - - if (cs && cs == player.cs) { -#ifdef OSX_CORE_AUDIO - player.soundoutput.stop(); -#endif - if (player.audiostatus != CDROM_AUDIO_INVALID) - player.audiostatus = CDROM_AUDIO_NO_STATUS; - return true; - } - return false; -} - -bool CDResume_bincue(void *fh) -{ - CueSheet *cs = (CueSheet *) fh; - if (cs && cs == player.cs) { - if (player.audiostatus == CDROM_AUDIO_PAUSED) { - player.audiostatus = CDROM_AUDIO_PLAY; - return true; - } - } - return false; -} - -bool CDPlay_bincue(void *fh, uint8 start_m, uint8 start_s, uint8 start_f, - uint8 end_m, uint8 end_s, uint8 end_f) -{ - CueSheet *cs = (CueSheet *)fh; - if (cs && cs == player.cs) { - int track; - MSF msf; - -#ifdef USE_SDL_AUDIO - SDL_LockAudio(); -#endif - - player.audiostatus = CDROM_AUDIO_NO_STATUS; - - player.audiostart = (start_m * 60 * CD_FRAMES) + - (start_s * CD_FRAMES) + start_f; - player.audioend = (end_m * 60 * CD_FRAMES) + (end_s * CD_FRAMES) + end_f; - - track = PositionToTrack(player.cs, player.audiostart); - - if (track < player.cs->tcnt) { - player.audioposition = 0; - - // here we need to compute silence - - if (player.audiostart - player.cs->tracks[track].start > - player.cs->tracks[track].pregap) - player.silence = 0; - else - player.silence = (player.cs->tracks[track].pregap - - player.audiostart + - player.cs->tracks[track].start) * RAW_SECTOR_SIZE; - - player.fileoffset = player.cs->tracks[track].fileoffset; - - D(bug("file offset %d\n", (unsigned int) player.fileoffset)); - - // fix up file offset if beyond the silence bytes - - if (!player.silence) // not at the beginning - player.fileoffset += (player.audiostart - - player.cs->tracks[track].start - - player.cs->tracks[track].pregap) * RAW_SECTOR_SIZE; - - FramesToMSF(player.cs->tracks[track].start, &msf); - D(bug("CDPlay_bincue track %02d start %02d:%02d:%02d silence %d", - player.cs->tracks[track].number, msf.m, msf.s, msf.f, - player.silence/RAW_SECTOR_SIZE)); - D(bug(" Stop %02u:%02u:%02u\n", end_m, end_s, end_f)); - } - else - D(bug("CDPlay_bincue: play beyond last track !\n")); - -#ifdef USE_SDL_AUDIO - SDL_UnlockAudio(); -#endif - - if (audio_enabled) { - player.audiostatus = CDROM_AUDIO_PLAY; -#ifdef OSX_CORE_AUDIO - D(bug("starting os x sound")); - player.soundoutput.setCallback(bincue_core_audio_callback); - // should be from current track ! - player.soundoutput.start(16, 2, 44100); -#endif - return true; - } - } - return false; -} - -static uint8 *fill_buffer(int stream_len) -{ - static uint8 *buf = 0; - static int bufsize = 0; - int offset = 0; - - if (bufsize < stream_len) { - free(buf); - buf = (uint8 *) malloc(stream_len); - if (buf) { - bufsize = stream_len; - } - else { - D(bug("malloc failed \n")); - return NULL; - } - } - - memset(buf, silence_byte, stream_len); - - if (player.audiostatus == CDROM_AUDIO_PLAY) { - int remaining_silence = player.silence - player.audioposition; - - if (player.audiostart + player.audioposition/RAW_SECTOR_SIZE - >= player.audioend) { - player.audiostatus = CDROM_AUDIO_COMPLETED; - return buf; - } - - if (remaining_silence >= stream_len) { - player.audioposition += stream_len; - return buf; - } - - if (remaining_silence > 0) { - offset += remaining_silence; - player.audioposition += remaining_silence; - } - - int ret = 0; - int available = ((player.audioend - player.audiostart) * - RAW_SECTOR_SIZE) - player.audioposition; - if (available > (stream_len - offset)) - available = stream_len - offset; - - if (lseek(player.audiofh, - player.fileoffset + player.audioposition - player.silence, - SEEK_SET) < 0) - return NULL; - - if (available < 0) { - player.audioposition += available; // correct end !; - available = 0; - } - - if ((ret = read(player.audiofh, &buf[offset], available)) >= 0) { - player.audioposition += ret; - offset += ret; - available -= ret; - } - - while (offset < stream_len) { - buf[offset++] = silence_byte; - if (available-- > 0){ - player.audioposition++; - } - } - } - return buf; -} - - -#ifdef USE_SDL_AUDIO -void MixAudio_bincue(uint8 *stream, int stream_len) -{ - uint8 *buf; - if (audio_enabled && (player.audiostatus == CDROM_AUDIO_PLAY)) { - if (buf = fill_buffer(stream_len)) - SDL_MixAudio(stream, buf, stream_len, SDL_MIX_MAXVOLUME); - } -} - -void OpenAudio_bincue(int freq, int format, int channels, uint8 silence) -{ - if (freq == 44100 && format == AUDIO_S16MSB && channels == 2) { - audio_enabled = true; - silence_byte = silence; - } - else { - D(bug("unexpected frequency %d , format %d, or channels %d\n", - freq, format, channels)); - } -} -#endif - -#ifdef OSX_CORE_AUDIO -static int bincue_core_audio_callback(void) -{ - int frames = player.soundoutput.bufferSizeFrames(); - uint8 *buf = fill_buffer(frames*4); - - // D(bug("Audio request %d\n", stream_len)); - - player.soundoutput.sendAudioBuffer((void *) buf, (buf ? frames : 0)); - - return 1; -} -#endif diff --git a/BasiliskII/src/Unix/bincue_unix.h b/BasiliskII/src/Unix/bincue_unix.h deleted file mode 100644 index dbf5d8b5..00000000 --- a/BasiliskII/src/Unix/bincue_unix.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * bincue_unix.h -- support for cdrom image files in bin/cue format - * - * (C) 2010 Geoffrey Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BINCUE_H -#define BINCUE_H - -extern void *open_bincue(const char *name); -extern bool readtoc_bincue(void *, uint8 *); -extern size_t read_bincue(void *, void *, loff_t, size_t); -extern loff_t size_bincue(void *); -extern void close_bincue(void *); - -extern bool GetPosition_bincue(void *, uint8 *); - -extern bool CDPlay_bincue(void *, uint8, uint8, - uint8, uint8, uint8, uint8); -extern bool CDPause_bincue(void *); -extern bool CDResume_bincue(void *); -extern bool CDStop_bincue(void *); - -#ifdef USE_SDL_AUDIO -extern void OpenAudio_bincue(int, int, int, uint8); -extern void MixAudio_bincue(uint8 *, int); -#endif - -#endif diff --git a/BasiliskII/src/Unix/clip_unix.cpp b/BasiliskII/src/Unix/clip_unix.cpp deleted file mode 100644 index e2a5edfb..00000000 --- a/BasiliskII/src/Unix/clip_unix.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/* - * clip_unix.cpp - Clipboard handling, Unix implementation - * - * SheepShaver (C) Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - * We must have (fast) X11 display locking routines. Otherwise, we - * can corrupt the X11 event queue from the emulator thread whereas - * the redraw thread is expected to handle them. - * - * Two functions are exported to video_x.cpp: - * - ClipboardSelectionClear() - * called when we lose the selection ownership - * - ClipboardSelectionRequest() - * called when another client wants our clipboard data - * The display is locked by the redraw thread during their execution. - * - * On PutScrap (Mac application wrote to clipboard), we always cache - * the Mac clipboard to a local structure (clip_data). Then, the - * selection ownership is grabbed until ClipboardSelectionClear() - * occurs. In that case, contents in cache becomes invalid. - * - * On GetScrap (Mac application reads clipboard), we always fetch - * data from the X11 clipboard and immediately put it back to Mac - * side. Local cache does not need to be updated. If the selection - * owner supports the TIMESTAMP target, we can avoid useless copies. - * - * For safety purposes, we lock the X11 display in the emulator - * thread during the whole GetScrap/PutScrap execution. Of course, we - * temporarily release the lock when waiting for SelectioNotify. - * - * TODO: - * - handle 'PICT' to image/png, image/ppm, PIXMAP (prefs order) - * - handle 'styl' to text/richtext (OOo Writer) - * - patch ZeroScrap so that we know when cached 'styl' is stale? - */ - -#include "sysdeps.h" - -#include -#include -#include -#include - -#include "macos_util.h" -#include "clip.h" -#include "prefs.h" -#include "cpu_emulation.h" -#include "main.h" -#include "emul_op.h" - -#define DEBUG 0 -#include "debug.h" - -#ifndef NO_STD_NAMESPACE -using std::vector; -#endif - - -// Do we want GetScrap() to check for TIMESTAMP and optimize out clipboard syncs? -#define GETSCRAP_REQUESTS_TIMESTAMP 0 - -// Do we want GetScrap() to first check for TARGETS available from the clipboard? -#define GETSCRAP_REQUESTS_TARGETS 0 - - -// From main_linux.cpp -extern Display *x_display; - - -// Conversion tables -static const uint8 mac2iso[0x80] = { - 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, - 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, - 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, - 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, - 0x2b, 0xb0, 0xa2, 0xa3, 0xa7, 0xb7, 0xb6, 0xdf, - 0xae, 0xa9, 0x20, 0xb4, 0xa8, 0x23, 0xc6, 0xd8, - 0x20, 0xb1, 0x3c, 0x3e, 0xa5, 0xb5, 0xf0, 0x53, - 0x50, 0x70, 0x2f, 0xaa, 0xba, 0x4f, 0xe6, 0xf8, - 0xbf, 0xa1, 0xac, 0x2f, 0x66, 0x7e, 0x44, 0xab, - 0xbb, 0x2e, 0x20, 0xc0, 0xc3, 0xd5, 0x4f, 0x6f, - 0x2d, 0x2d, 0x22, 0x22, 0x60, 0x27, 0xf7, 0x20, - 0xff, 0x59, 0x2f, 0xa4, 0x3c, 0x3e, 0x66, 0x66, - 0x23, 0xb7, 0x2c, 0x22, 0x25, 0xc2, 0xca, 0xc1, - 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, - 0x20, 0xd2, 0xda, 0xdb, 0xd9, 0x69, 0x5e, 0x7e, - 0xaf, 0x20, 0xb7, 0xb0, 0xb8, 0x22, 0xb8, 0x20 -}; - -static const uint8 iso2mac[0x80] = { - 0xad, 0xb0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, - 0xf6, 0xe4, 0xde, 0xdc, 0xce, 0xb2, 0xb3, 0xb6, - 0xb7, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, - 0xf7, 0xaa, 0xdf, 0xdd, 0xcf, 0xba, 0xfd, 0xd9, - 0xca, 0xc1, 0xa2, 0xa3, 0xdb, 0xb4, 0xbd, 0xa4, - 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xf0, 0xa8, 0xf8, - 0xa1, 0xb1, 0xc3, 0xc5, 0xab, 0xb5, 0xa6, 0xe1, - 0xfc, 0xc6, 0xbc, 0xc8, 0xf9, 0xda, 0xd7, 0xc0, - 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, - 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, - 0xf5, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xfb, - 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xfa, 0xb8, 0xa7, - 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, - 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, - 0xfe, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, - 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xff, 0xb9, 0xd8 -}; - -// Flag: Don't convert clipboard text -static bool no_clip_conversion; - -// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the Unix side -static bool we_put_this_data = false; - -// X11 variables -static int screen; // Screen number -static Window rootwin, clip_win; // Root window and the clipboard window -static Atom xa_clipboard; -static Atom xa_targets; -static Atom xa_multiple; -static Atom xa_timestamp; -static Atom xa_atom_pair; - -// Define a byte array (rewrite if it's a bottleneck) -struct ByteArray : public vector { - void resize(int size) { reserve(size); vector::resize(size); } - uint8 *data() { return &(*this)[0]; } -}; - -// Clipboard data for requestors -struct ClipboardData { - Time time; - Atom type; - ByteArray data; -}; -static ClipboardData clip_data; - -// Prototypes -static void do_putscrap(uint32 type, void *scrap, int32 length); -static void do_getscrap(void **handle, uint32 type, int32 offset); - - -/* - * Read an X11 property (hack from QT 3.1.2) - */ - -static inline int max_selection_incr(Display *dpy) -{ - int max_request_size = 4 * XMaxRequestSize(dpy); - if (max_request_size > 4 * 65536) - max_request_size = 4 * 65536; - else if ((max_request_size -= 100) < 0) - max_request_size = 100; - return max_request_size; -} - -static bool read_property(Display *dpy, Window win, - Atom property, bool deleteProperty, - ByteArray & buffer, int *size, Atom *type, - int *format, bool nullterm) -{ - int maxsize = max_selection_incr(dpy); - unsigned long bytes_left; - unsigned long length; - unsigned char *data; - Atom dummy_type; - int dummy_format; - - if (!type) - type = &dummy_type; - if (!format) - format = &dummy_format; - - // Don't read anything but get the size of the property data - if (XGetWindowProperty(dpy, win, property, 0, 0, False, - AnyPropertyType, type, format, &length, &bytes_left, &data) != Success) { - buffer.clear(); - return false; - } - XFree(data); - - int offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left; - - switch (*format) { - case 16: - format_inc = sizeof(short) / 2; - proplen *= format_inc; - break; - case 32: - format_inc = sizeof(long) / 4; - proplen *= format_inc; - break; - } - - buffer.resize(proplen + (nullterm ? 1 : 0)); - while (bytes_left) { - if (XGetWindowProperty(dpy, win, property, offset, maxsize / 4, - False, AnyPropertyType, type, format, - &length, &bytes_left, &data) != Success) - break; - - offset += length / (32 / *format); - length *= format_inc * (*format / 8); - - memcpy(buffer.data() + buffer_offset, data, length); - buffer_offset += length; - XFree(data); - } - - if (nullterm) - buffer[buffer_offset] = '\0'; - - if (size) - *size = buffer_offset; - - if (deleteProperty) - XDeleteProperty(dpy, win, property); - - XFlush(dpy); - return true; -} - - -/* - * Timed wait for a SelectionNotify event - */ - -static const uint64 SELECTION_MAX_WAIT = 500000; // 500 ms - -static bool wait_for_selection_notify_event(Display *dpy, Window win, XEvent *event, int timeout) -{ - uint64 start = GetTicks_usec(); - - do { - // Wait - XDisplayUnlock(); - Delay_usec(5000); - XDisplayLock(); - - // Check for SelectionNotify event - if (XCheckTypedWindowEvent(dpy, win, SelectionNotify, event)) - return true; - - } while ((GetTicks_usec() - start) < timeout); - - return false; -} - - -/* - * Initialization - */ - -void ClipInit(void) -{ - no_clip_conversion = PrefsFindBool("noclipconversion"); - - // Find screen and root window - screen = XDefaultScreen(x_display); - rootwin = XRootWindow(x_display, screen); - - // Create fake window to receive selection events - clip_win = XCreateSimpleWindow(x_display, rootwin, 0, 0, 1, 1, 0, 0, 0); - - // Initialize X11 atoms - xa_clipboard = XInternAtom(x_display, "CLIPBOARD", False); - xa_targets = XInternAtom(x_display, "TARGETS", False); - xa_multiple = XInternAtom(x_display, "MULTIPLE", False); - xa_timestamp = XInternAtom(x_display, "TIMESTAMP", False); - xa_atom_pair = XInternAtom(x_display, "ATOM_PAIR", False); -} - - -/* - * Deinitialization - */ - -void ClipExit(void) -{ - // Close window - if (clip_win) - XDestroyWindow(x_display, clip_win); -} - - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32 type, void *scrap, int32 length) -{ - D(bug("PutScrap type %08lx, data %p, length %ld\n", type, scrap, length)); - if (we_put_this_data) { - we_put_this_data = false; - return; - } - if (length <= 0) - return; - - XDisplayLock(); - do_putscrap(type, scrap, length); - XDisplayUnlock(); -} - -static void do_putscrap(uint32 type, void *scrap, int32 length) -{ - clip_data.type = None; - switch (type) { - case FOURCC('T','E','X','T'): { - D(bug(" clipping TEXT\n")); - clip_data.type = XA_STRING; - clip_data.data.clear(); - clip_data.data.reserve(length); - - // Convert text from Mac charset to ISO-Latin1 - uint8 *p = (uint8 *)scrap; - for (int i=0; i LF - c = 10; - } else if (!no_clip_conversion) - c = mac2iso[c & 0x7f]; - clip_data.data.push_back(c); - } - break; - } - - case FOURCC('s','t','y','l'): { - D(bug(" clipping styl\n")); - uint16 *p = (uint16 *)scrap; - uint16 n = ntohs(*p++); - D(bug(" %d styles (%d bytes)\n", n, length)); - for (int i = 0; i < n; i++) { - uint32 offset = ntohl(*(uint32 *)p); p += 2; - uint16 line_height = ntohs(*p++); - uint16 font_ascent = ntohs(*p++); - uint16 font_family = ntohs(*p++); - uint16 style_code = ntohs(*p++); - uint16 char_size = ntohs(*p++); - uint16 r = ntohs(*p++); - uint16 g = ntohs(*p++); - uint16 b = ntohs(*p++); - D(bug(" offset=%d, height=%d, font ascent=%d, id=%d, style=%x, size=%d, RGB=%x/%x/%x\n", - offset, line_height, font_ascent, font_family, style_code, char_size, r, g, b)); - } - break; - } - } - - // Acquire selection ownership - if (clip_data.type != None) { - clip_data.time = CurrentTime; - while (XGetSelectionOwner(x_display, xa_clipboard) != clip_win) - XSetSelectionOwner(x_display, xa_clipboard, clip_win, clip_data.time); - } -} - -/* - * Mac application zeroes clipboard - */ - -void ZeroScrap() -{ - -} - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32 type, int32 offset) -{ - D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); - - XDisplayLock(); - do_getscrap(handle, type, offset); - XDisplayUnlock(); -} - -static void do_getscrap(void **handle, uint32 type, int32 offset) -{ - ByteArray data; - XEvent event; - - // If we own the selection, the data is already available on MacOS side - if (XGetSelectionOwner(x_display, xa_clipboard) == clip_win) - return; - - // Check TIMESTAMP -#if GETSCRAP_REQUESTS_TIMESTAMP - static Time last_timestamp = 0; - XConvertSelection(x_display, xa_clipboard, xa_timestamp, xa_clipboard, clip_win, CurrentTime); - if (wait_for_selection_notify_event(x_display, clip_win, &event, SELECTION_MAX_WAIT) && - event.xselection.property != None && - read_property(x_display, - event.xselection.requestor, event.xselection.property, - true, data, 0, 0, 0, false)) { - Time timestamp = ((long *)data.data())[0]; - if (timestamp <= last_timestamp) - return; - } - last_timestamp = CurrentTime; -#endif - - // Get TARGETS available -#if GETSCRAP_REQUESTS_TARGETS - XConvertSelection(x_display, xa_clipboard, xa_targets, xa_clipboard, clip_win, CurrentTime); - if (!wait_for_selection_notify_event(x_display, clip_win, &event, SELECTION_MAX_WAIT) || - event.xselection.property == None || - !read_property(x_display, - event.xselection.requestor, event.xselection.property, - true, data, 0, 0, 0, false)) - return; -#endif - - // Get appropriate format for requested data - Atom format = None; -#if GETSCRAP_REQUESTS_TARGETS - int n_atoms = data.size() / sizeof(long); - long *atoms = (long *)data.data(); - for (int i = 0; i < n_atoms; i++) { - Atom target = atoms[i]; - D(bug(" target %08x (%s)\n", target, XGetAtomName(x_display, target))); - switch (type) { - case FOURCC('T','E','X','T'): - D(bug(" clipping TEXT\n")); - if (target == XA_STRING) - format = target; - break; - case FOURCC('P','I','C','T'): - break; - } - } -#else - switch (type) { - case FOURCC('T','E','X','T'): - D(bug(" clipping TEXT\n")); - format = XA_STRING; - break; - case FOURCC('P','I','C','T'): - break; - } -#endif - if (format == None) - return; - - // Get the native clipboard data - XConvertSelection(x_display, xa_clipboard, format, xa_clipboard, clip_win, CurrentTime); - if (!wait_for_selection_notify_event(x_display, clip_win, &event, SELECTION_MAX_WAIT) || - event.xselection.property == None || - !read_property(x_display, - event.xselection.requestor, event.xselection.property, - false, data, 0, 0, 0, format == XA_STRING)) - return; - - // Allocate space for new scrap in MacOS side - M68kRegisters r; - r.d[0] = data.size(); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32 scrap_area = r.a[0]; - - if (scrap_area) { - switch (type) { - case FOURCC('T','E','X','T'): - // Convert text from ISO-Latin1 to Mac charset - uint8 *p = Mac2HostAddr(scrap_area); - for (int i = 0; i < data.size(); i++) { - uint8 c = data[i]; - if (c < 0x80) { - if (c == 10) // LF -> CR - c = 13; - } else if (!no_clip_conversion) - c = iso2mac[c & 0x7f]; - *p++ = c; - } - break; - } - - // Add new data to clipboard - static uint8 proc[] = { - 0x59, 0x8f, // subq.l #4,sp - 0xa9, 0xfc, // ZeroScrap() - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #length,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #type,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #outbuf,-(sp) - 0xa9, 0xfe, // PutScrap() - 0x58, 0x8f, // addq.l #4,sp - M68K_RTS >> 8, M68K_RTS & 0xff - }; - r.d[0] = sizeof(proc); - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32 proc_area = r.a[0]; - - // The procedure is run-time generated because it must lays in - // Mac address space. This is mandatory for "33-bit" address - // space optimization on 64-bit platforms because the static - // proc[] array is not remapped - Host2Mac_memcpy(proc_area, proc, sizeof(proc)); - WriteMacInt32(proc_area + 6, data.size()); - WriteMacInt32(proc_area + 12, type); - WriteMacInt32(proc_area + 18, scrap_area); - we_put_this_data = true; - Execute68k(proc_area, &r); - - // We are done with scratch memory - r.a[0] = proc_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - r.a[0] = scrap_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } -} - - -/* - * Handle X11 selection events - */ - -void ClipboardSelectionClear(XSelectionClearEvent *xev) -{ - if (xev->selection != xa_clipboard) - return; - - D(bug("Selection cleared, lost clipboard ownership\n")); - clip_data.type = None; - clip_data.data.clear(); -} - -// Top level selection handler -static bool handle_selection(XSelectionRequestEvent *req, bool is_multiple); - -static bool handle_selection_TIMESTAMP(XSelectionRequestEvent *req) -{ - // 32-bit integer values are always passed as a long whatever is its size - long timestamp = clip_data.time; - - // Change requestor property - XChangeProperty(x_display, req->requestor, req->property, - XA_INTEGER, 32, - PropModeReplace, (uint8 *)×tamp, 1); - - return true; -} - -static bool handle_selection_TARGETS(XSelectionRequestEvent *req) -{ - // Default supported targets - vector targets; - targets.push_back(xa_targets); - targets.push_back(xa_multiple); - targets.push_back(xa_timestamp); - - // Extra targets matchin current clipboard data - if (clip_data.type != None) - targets.push_back(clip_data.type); - - // Change requestor property - XChangeProperty(x_display, req->requestor, req->property, - xa_targets, 32, - PropModeReplace, (uint8 *)&targets[0], targets.size()); - - return true; -} - -static bool handle_selection_STRING(XSelectionRequestEvent *req) -{ - // Make sure we have valid data to send though ICCCM compliant - // clients should have first requested TARGETS to identify - // this possibility. - if (clip_data.type != XA_STRING) - return false; - - // Send the string, it's already encoded as ISO-8859-1 - XChangeProperty(x_display, req->requestor, req->property, - XA_STRING, 8, - PropModeReplace, (uint8 *)clip_data.data.data(), clip_data.data.size()); - - return true; -} - -static bool handle_selection_MULTIPLE(XSelectionRequestEvent *req) -{ - Atom rtype; - int rformat; - ByteArray data; - - if (!read_property(x_display, req->requestor, req->property, - false, data, 0, &rtype, &rformat, 0)) - return false; - - // rtype should be ATOM_PAIR but some clients don't honour that - if (rformat != 32) - return false; - - struct AtomPair { long target; long property; }; - AtomPair *atom_pairs = (AtomPair *)data.data(); - int n_atom_pairs = data.size() / sizeof(AtomPair); - - bool handled = true; - if (n_atom_pairs) { - // Setup a new XSelectionRequestEvent when servicing individual requests - XSelectionRequestEvent event; - memcpy(&event, req, sizeof(event)); - - for (int i = 0; i < n_atom_pairs; i++) { - Atom target = atom_pairs[i].target; - Atom property = atom_pairs[i].property; - - // None is not a valid property - if (property == None) - continue; - - // Service this request - event.target = target; - event.property = property; - if (!handle_selection(&event, true)) { - /* FIXME: ICCCM 2.6.2: - - If the owner fails to convert the target named by an - atom in the MULTIPLE property, it should replace that - atom in the property with None. - */ - handled = false; - } - } - } - - return handled; -} - -static bool handle_selection(XSelectionRequestEvent *req, bool is_multiple) -{ - bool handled =false; - - if (req->target == xa_timestamp) { - handled = handle_selection_TIMESTAMP(req); - } else if (req->target == xa_targets) { - handled = handle_selection_TARGETS(req); - } else if (req->target == XA_STRING) { - handled = handle_selection_STRING(req); - } else if (req->target == xa_multiple) { - handled = handle_selection_MULTIPLE(req); - } - - // Notify requestor only when we are done with his request - if (handled && !is_multiple) { - XEvent out_event; - out_event.xselection.type = SelectionNotify; - out_event.xselection.requestor = req->requestor; - out_event.xselection.selection = req->selection; - out_event.xselection.target = req->target; - out_event.xselection.property = req->property; - out_event.xselection.time = req->time; - XSendEvent(x_display, req->requestor, False, 0, &out_event); - } - - return handled; -} - -void ClipboardSelectionRequest(XSelectionRequestEvent *req) -{ - if (req->requestor == clip_win || req->selection != xa_clipboard) - return; - - D(bug("Selection requested from 0x%lx to 0x%lx (%s) 0x%lx (%s)\n", - req->requestor, - req->selection, - XGetAtomName(req->display, req->selection), - req->target, - XGetAtomName(req->display, req->target))); - - handle_selection(req, false); -} diff --git a/BasiliskII/src/Unix/configure.ac b/BasiliskII/src/Unix/configure.ac index b8aa82c8..ffba2f41 100644 --- a/BasiliskII/src/Unix/configure.ac +++ b/BasiliskII/src/Unix/configure.ac @@ -16,40 +16,20 @@ dnl Some systems do not put corefiles in the currect directory, avoid saving dnl cores for the configure tests since some are intended to dump core. ulimit -c 0 -AC_ARG_ENABLE(standalone-gui,[ --enable-standalone-gui enable a standalone GUI prefs editor [default=no]], [WANT_STANDALONE_GUI=$enableval], [WANT_STANDALONE_GUI=no]) - -dnl Mac OS X GUI. -AC_ARG_ENABLE(macosx-gui, [ --enable-macosx-gui enable Mac OS X GUI [default=no]], [WANT_MACOSX_GUI=$enableval], [WANT_MACOSX_GUI=no]) - -dnl Mac OS X Sound -AC_ARG_ENABLE(macosx-sound, [ --enable-macosx-sound enable Mac OS X Sound [default=no]], [WANT_MACOSX_SOUND=$enableval], [WANT_MACOSX_SOUND=no]) - dnl Video options. -AC_ARG_ENABLE(xf86-dga, [ --enable-xf86-dga use the XFree86 DGA extension [default=yes]], [WANT_XF86_DGA=$enableval], [WANT_XF86_DGA=yes]) -AC_ARG_ENABLE(xf86-vidmode, [ --enable-xf86-vidmode use the XFree86 VidMode extension [default=yes]], [WANT_XF86_VIDMODE=$enableval], [WANT_XF86_VIDMODE=yes]) -AC_ARG_ENABLE(fbdev-dga, [ --enable-fbdev-dga use direct frame buffer access via /dev/fb [default=yes]], [WANT_FBDEV_DGA=$enableval], [WANT_FBDEV_DGA=yes]) AC_ARG_ENABLE(vosf, [ --enable-vosf enable video on SEGV signals [default=yes]], [WANT_VOSF=$enableval], [WANT_VOSF=yes]) dnl SDL options. AC_ARG_ENABLE(sdl-static, [ --enable-sdl-static use SDL static libraries for linking [default=no]], [WANT_SDL_STATIC=$enableval], [WANT_SDL_STATIC=no]) AC_ARG_ENABLE(sdl-video, [ --enable-sdl-video use SDL for video graphics [default=no]], [WANT_SDL_VIDEO=$enableval], [WANT_SDL_VIDEO=no]) AC_ARG_ENABLE(sdl-audio, [ --enable-sdl-audio use SDL for audio [default=no]], [WANT_SDL_AUDIO=$enableval], [WANT_SDL_AUDIO=no]) -AC_ARG_ENABLE(sdl-framework, [ --enable-sdl-framework use SDL framework [default=no]], [WANT_SDL_FRAMEWORK=$enableval], [WANT_SDL_FRAMEWORK=no]) -AC_ARG_ENABLE(sdl-framework-prefix, [ --enable-sdl-framework-prefix=PFX default=/Library/Frameworks], [SDL_FRAMEWORK="$enableval"], [SDL_FRAMEWORK=/Library/Frameworks]) - -dnl JIT compiler options. -AC_ARG_ENABLE(jit-compiler, [ --enable-jit-compiler enable JIT compiler [default=no]], [WANT_JIT=$enableval], [WANT_JIT=no]) -AC_ARG_ENABLE(jit-debug, [ --enable-jit-debug activate native code disassemblers [default=no]], [WANT_JIT_DEBUG=$enableval], [WANT_JIT_DEBUG=no]) dnl FPU emulation core. AC_ARG_ENABLE(fpe, [ --enable-fpe=FPE specify which fpu emulator to use [default=auto]], [ case "$enableval" in dnl default is always ieee, if architecture has this fp format - auto) FPE_CORE_TEST_ORDER="ieee uae";; - ieee) FPE_CORE_TEST_ORDER="ieee";; uae) FPE_CORE_TEST_ORDER="uae";; - x86) FPE_CORE_TEST_ORDER="x86";; *) AC_MSG_ERROR([--enable-fpe takes only one of the following values: auto, x86, ieee, uae]);; esac ], @@ -70,35 +50,12 @@ AC_ARG_ENABLE(addressing, [ ADDRESSING_TEST_ORDER="direct banks" ]) -dnl External packages. -AC_ARG_WITH(esd, [ --with-esd support ESD for sound under Linux/FreeBSD [default=yes]], [WANT_ESD=$withval], [WANT_ESD=yes]) -AC_ARG_WITH(gtk, [ --with-gtk use GTK user interface [default=yes]], - [case "$withval" in - gtk1) WANT_GTK="gtk";; - gtk|gtk2) WANT_GTK="$withval";; - yes) WANT_GTK="gtk2 gtk";; - *) WANT_GTK="no";; - esac], - [WANT_GTK="gtk2 gtk"]) -AC_ARG_WITH(mon, [ --with-mon use mon as debugger [default=yes]], [WANT_MON=$withval], [WANT_MON=yes]) - -AC_ARG_WITH(bincue, - AS_HELP_STRING([--with-bincue], [Allow cdrom image files in bin/cue mode])) - -AC_ARG_WITH(libvhd, - AS_HELP_STRING([--with-libvhd], [Enable VHD disk images])) - - dnl Canonical system information. AC_CANONICAL_HOST AC_CANONICAL_TARGET dnl Target OS type (target is host if not cross-compiling). case "$target_os" in - linux*) OS_TYPE=linux;; - netbsd*) OS_TYPE=netbsd;; - freebsd*) OS_TYPE=freebsd;; - solaris*) OS_TYPE=solaris;; darwin*) OS_TYPE=darwin;; *) OS_TYPE=`echo $target_os | sed -e 's/-/_/g' | sed -e 's/\./_/g'`;; esac @@ -106,15 +63,9 @@ DEFINES="$DEFINES -DOS_$OS_TYPE" dnl Target CPU type. HAVE_I386=no -HAVE_M68K=no -HAVE_SPARC=no -HAVE_POWERPC=no HAVE_X86_64=no case "$target_cpu" in i386* | i486* | i586* | i686* | i786* ) HAVE_I386=yes;; - m68k* ) HAVE_M68K=yes;; - sparc* ) HAVE_SPARC=yes;; - powerpc* ) HAVE_POWERPC=yes;; x86_64* | amd64* ) HAVE_X86_64=yes;; esac @@ -143,73 +94,17 @@ AC_PROG_MAKE_SET AC_PROG_INSTALL AC_PROG_EGREP -dnl We use mon if possible. -MONSRCS= -if [[ "x$WANT_MON" = "xyes" ]]; then - AC_MSG_CHECKING(for mon) - mon_srcdir=../../../mon/src - if grep mon_init $mon_srcdir/mon.h >/dev/null 2>/dev/null; then - AC_MSG_RESULT(yes) - AC_DEFINE(ENABLE_MON, 1, [Define if using "mon".]) - MONSRCS="$mon_srcdir/mon.cpp $mon_srcdir/mon_6502.cpp $mon_srcdir/mon_z80.cpp $mon_srcdir/mon_cmd.cpp $mon_srcdir/mon_disass.cpp $mon_srcdir/mon_ppc.cpp $mon_srcdir/mon_lowmem.cpp $mon_srcdir/disass/floatformat.c $mon_srcdir/disass/i386-dis.c $mon_srcdir/disass/m68k-dis.c $mon_srcdir/disass/m68k-opc.c $mon_srcdir/disass/mips-dis.c $mon_srcdir/disass/mips-opc.c $mon_srcdir/disass/mips16-opc.c" - CXXFLAGS="$CXXFLAGS -I$mon_srcdir -I$mon_srcdir/disass" - AC_CHECK_LIB(ncurses, tgetent, , - [AC_CHECK_LIB(termcap, tgetent, , - [AC_CHECK_LIB(termlib, tgetent, , - [AC_CHECK_LIB(terminfo, tgetent, , - [AC_CHECK_LIB(Hcurses, tgetent, , - [AC_CHECK_LIB(curses, tgetent)])])])])]) - AC_CHECK_LIB(readline, readline) - else - AC_MSG_RESULT(no) - AC_MSG_WARN([Could not find mon, ignoring --with-mon.]) - WANT_MON=no - fi -fi - dnl Checks for libraries. AC_CHECK_LIB(posix4, sem_init) AC_CHECK_LIB(rt, timer_create) AC_CHECK_LIB(rt, shm_open) AC_CHECK_LIB(m, cos) -dnl AC_CHECK_SDLFRAMEWORK($1=NAME, $2=INCLUDES) -dnl AC_TRY_LINK uses main() but SDL needs main to take args, -dnl therefore main is undefined with #undef. -dnl Framework can be in an custom location. -AC_DEFUN([AC_CHECK_SDLFRAMEWORK], [ - AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1]) - AC_CACHE_CHECK([whether compiler supports framework $1], - ac_Framework, [ - saved_LIBS="$LIBS" - LIBS="$LIBS -framework $1" - if [[ "x$SDL_FRAMEWORK" != "x/Library/Frameworks" ]]; then - if [[ "x$SDL_FRAMEWORK" != "x/System/Library/Frameworks" ]]; then - LIBS="$saved_LIBS -F$SDL_FRAMEWORK -framework $1" - fi - fi - saved_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -I$SDL_FRAMEWORK/SDL.framework/Headers" - AC_TRY_LINK( - [$2 -#undef main], [], - [AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no); -LIBS="$saved_LIBS"; CPPFLAGS="$saved_CPPFLAGS"] - ) - ]) - AS_IF([test AS_VAR_GET(ac_Framework) = yes], - [AC_DEFINE(AS_TR_CPP(HAVE_FRAMEWORK_$1), 1, [Define if framework $1 is available.])] - ) - AS_VAR_POPDEF([ac_Framework]) -]) dnl Do we need SDL? WANT_SDL=no if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then WANT_SDL=yes - WANT_XF86_DGA=no - WANT_XF86_VIDMODE=no - WANT_FBDEV_DGA=no SDL_SUPPORT="$SDL_SUPPORT video" fi if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then @@ -217,86 +112,36 @@ if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then SDL_SUPPORT="$SDL_SUPPORT audio" fi if [[ "x$WANT_SDL" = "xyes" ]]; then - if [[ "x$WANT_SDL_FRAMEWORK" = "xyes" ]]; then - AC_CHECK_SDLFRAMEWORK(SDL, [#include ]) + + AC_PATH_PROG(sdl_config, "sdl-config") + if [[ -n "$sdl_config" ]]; then + case $target_os in + *) + sdl_cflags=`$sdl_config --cflags` + if [[ "x$WANT_SDL_STATIC" = "xyes" ]]; then + sdl_libs=`$sdl_config --static-libs` + else + sdl_libs=`$sdl_config --libs` + fi + ;; + esac + CFLAGS="$CFLAGS $sdl_cflags" + CXXFLAGS="$CXXFLAGS $sdl_cflags" + LIBS="$LIBS $sdl_libs" else - ac_cv_framework_SDL=no - fi - if [[ "x$ac_cv_framework_SDL" = "xno" ]]; then - AC_PATH_PROG(sdl_config, "sdl-config") - if [[ -n "$sdl_config" ]]; then - case $target_os in - # Special treatment for Cygwin so that we can still use the POSIX layer - *cygwin*) - sdl_cflags="-I`$sdl_config --prefix`/include/SDL" - sdl_libs="-L`$sdl_config --exec-prefix`/lib -lSDL" - ;; - *) - sdl_cflags=`$sdl_config --cflags` - if [[ "x$WANT_SDL_STATIC" = "xyes" ]]; then - sdl_libs=`$sdl_config --static-libs` - else - sdl_libs=`$sdl_config --libs` - fi - ;; - esac - CFLAGS="$CFLAGS $sdl_cflags" - CXXFLAGS="$CXXFLAGS $sdl_cflags" - LIBS="$LIBS $sdl_libs" - else - WANT_SDL=no - fi + WANT_SDL=no fi + SDL_SUPPORT=`echo "$SDL_SUPPORT" | sed -e "s/^ //"` else SDL_SUPPORT="none" fi -dnl We need X11, if not using SDL. -if [[ "x$WANT_SDL_VIDEO" = "xno" ]]; then - AC_PATH_XTRA - if [[ "x$no_x" = "xyes" ]]; then - AC_MSG_ERROR([You need X11 to run Basilisk II.]) - fi - CFLAGS="$CFLAGS $X_CFLAGS" - CXXFLAGS="$CXXFLAGS $X_CFLAGS" - LIBS="$LIBS $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS" -fi - -dnl BINCUE -AS_IF([test "x$with_bincue" = "xyes" ], [have_bincue=yes], [have_bincue=no]) -AS_IF([test "x$have_bincue" = "xyes" ], [ - if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then - DEFINES="$DEFINES -DBINCUE" - else - AC_MSG_ERROR([You need SDL Audio to use BINCUE support.]) - fi -]) - -dnl LIBVHD -AS_IF([test "x$with_libvhd" = "xyes" ], [have_libvhd=yes], [have_libvhd=no]) -AS_IF([test "x$have_libvhd" = "xyes" ], [ - CPPFLAGS="$CPPFLAGS -DHAVE_LIBVHD" - LIBS="$LIBS -lvhd" - case $target_os in - linux*) - LIBS="$LIBS -luuid" - esac - AC_CHECK_LIB(vhd, vhd_open) - AC_CHECK_LIB(vhd, vhd_io_read) - AC_CHECK_LIB(vhd, vhd_io_write) - AC_CHECK_LIB(vhd, vhd_close) -]) - - - -dnl We want pthreads. Try libpthread first, then libc_r (FreeBSD), then PTL. +dnl We want pthreads. Try libpthread first, then PTL. HAVE_PTHREADS=yes AC_CHECK_LIB(pthread, pthread_create, , [ - AC_CHECK_LIB(c_r, pthread_create, , [ - AC_CHECK_LIB(PTL, pthread_create, , [ - HAVE_PTHREADS=no - ]) + AC_CHECK_LIB(PTL, pthread_create, , [ + HAVE_PTHREADS=no ]) ]) if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then @@ -316,103 +161,7 @@ AC_CHECK_FUNCS(sem_init, , [ fi ]) -dnl We use DGA (XFree86 or fbdev) if possible. -if [[ "x$WANT_XF86_DGA" = "xyes" ]]; then - AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension, [ - AC_DEFINE(ENABLE_XF86_DGA, 1, [Define if using XFree86 DGA extension.]) - LIBS="$LIBS -lXxf86dga" - if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then - AC_MSG_WARN([Cannot have both --enable-xf86-dga and --enable-fbdev-dga, ignoring --enable-fbdev-dga.]) - WANT_FBDEV_DGA=no - fi - ], [ - AC_MSG_WARN([Could not find XFree86 DGA extension, ignoring --enable-xf86-dga.]) - WANT_XF86_DGA=no - ]) -fi -if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then - AC_DEFINE(ENABLE_FBDEV_DGA, 1, [Define if using DGA with framebuffer device.]) -fi - -dnl We use XFree86 VidMode if possible. -if [[ "x$WANT_XF86_VIDMODE" = "xyes" ]]; then - AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension, [ - AC_DEFINE(ENABLE_XF86_VIDMODE, 1, [Define if using XFree86 DGA extension.]) - LIBS="$LIBS -lXxf86vm" - ], [ - AC_MSG_WARN([Could not find XFree86 VidMode extension, ignoring --enable-xf86-vidmode.]) - WANT_XF86_VIDMODE=no - ]) -fi - -dnl We use GTK+ if possible. UISRCS=../dummy/prefs_editor_dummy.cpp -case "x$WANT_GTK" in -xgtk2*) - AM_PATH_GTK_2_0(1.3.15, [ - GUI_CFLAGS="$GTK_CFLAGS" - GUI_LIBS="$GTK_LIBS" - WANT_GTK=gtk2 - ], [ - case "x${WANT_GTK}x" in - *gtkx) - AC_MSG_WARN([Could not find GTK+ 2.0, trying with GTK+ 1.2.]) - WANT_GTK=gtk - ;; - *) - AC_MSG_WARN([Could not find GTK+, disabling user interface.]) - WANT_GTK=no - ;; - esac - ]) - ;; -esac -if [[ "x$WANT_GTK" = "xgtk" ]]; then - AM_PATH_GTK(1.2.0, [ - GUI_CFLAGS="$GTK_CFLAGS" - GUI_LIBS="$GTK_LIBS" - dnl somehow, would redefine gettext() to nothing if - dnl ENABLE_NLS is not set, thusly conflicting with C++ which - dnl includes - AM_GNU_GETTEXT - B2_PATH_GNOMEUI([ - AC_DEFINE(HAVE_GNOMEUI, 1, [Define if libgnomeui is available.]) - GUI_CFLAGS="$GUI_CFLAGS $GNOMEUI_CFLAGS" - GUI_LIBS="$GUI_LIBS $GNOMEUI_LIBS" - ], []) - ], [ - AC_MSG_WARN([Could not find GTK+, disabling user interface.]) - WANT_GTK=no - ]) -fi -if [[ "x$WANT_GTK" != "xno" -a "x$WANT_STANDALONE_GUI" = "xno" ]]; then - AC_DEFINE(ENABLE_GTK, 1, [Define if using GTK.]) - UISRCS=prefs_editor_gtk.cpp -fi -AC_SUBST(GUI_CFLAGS) -AC_SUBST(GUI_LIBS) - -dnl Build external GUI if requested. -if [[ "$WANT_STANDALONE_GUI" != "yes" ]]; then - WANT_STANDALONE_GUI=no -fi -if [[ "$WANT_GTK" = "no" ]]; then - WANT_STANDALONE_GUI=no -fi -AC_SUBST(STANDALONE_GUI, [$WANT_STANDALONE_GUI]) - -dnl We use ESD if possible. -if [[ "x$WANT_ESD" = "xyes" ]]; then - AM_PATH_ESD(0.2.8, [ - AC_DEFINE(ENABLE_ESD, 1, [Define is using ESD.]) - CFLAGS="$CFLAGS $ESD_CFLAGS" - CXXFLAGS="$CXXFLAGS $ESD_CFLAGS" - LIBS="$LIBS $ESD_LIBS" - ], [ - AC_MSG_WARN([Could not find ESD, disabling ESD support.]) - WANT_ESD=no - ]) -fi dnl We use 64-bit file size support if possible. AC_SYS_LARGEFILE @@ -425,14 +174,6 @@ AC_CHECK_HEADERS(readline.h history.h readline/readline.h readline/history.h) AC_CHECK_HEADERS(sys/socket.h sys/ioctl.h sys/filio.h sys/bitypes.h sys/wait.h) AC_CHECK_HEADERS(sys/poll.h sys/select.h) AC_CHECK_HEADERS(arpa/inet.h) -AC_CHECK_HEADERS(linux/if.h linux/if_tun.h net/if.h net/if_tun.h, [], [], [ -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -]) AC_CHECK_HEADERS(AvailabilityMacros.h) AC_CHECK_HEADERS(IOKit/storage/IOBlockStorageDevice.h) AC_CHECK_HEADERS(sys/stropts.h stropts.h) @@ -485,58 +226,6 @@ AC_CHECK_FUNCS(poll inet_aton) dnl Darwin seems to define mach_task_self() instead of task_self(). AC_CHECK_FUNCS(mach_task_self task_self) -dnl Check for headers and functions related to pty support (sshpty.c) -dnl From openssh-3.2.2p1 configure.ac - -AC_CHECK_HEADERS(strings.h login.h sys/bsdtty.h sys/stat.h util.h pty.h) -AC_CHECK_FUNCS(_getpty vhangup strlcpy) - -case "$host" in -*-*-hpux10.26) - disable_ptmx_check=yes - ;; -*-*-linux*) - no_dev_ptmx=1 - ;; -mips-sony-bsd|mips-sony-newsos4) - AC_DEFINE(HAVE_NEWS4, 1, [Define if you are on NEWS-OS (additions from openssh-3.2.2p1, for sshpty.c).]) - ;; -*-*-sco3.2v4*) - no_dev_ptmx=1 - ;; -*-*-sco3.2v5*) - no_dev_ptmx=1 - ;; -*-*-cygwin*) - no_dev_ptmx=1 - ;; -*-*-darwin*) - no_dev_ptmx=1 - LIBS="$LIBS -lstdc++" - ;; -*-*-freebsd*) - no_dev_ptmx=1 - ;; -esac - -if test -z "$no_dev_ptmx" ; then - if test "x$disable_ptmx_check" != "xyes" ; then - AC_CHECK_FILE([/dev/ptmx], - [ - AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX, 1, [Define if you have /dev/ptmx.]) - have_dev_ptmx=1 - ] - ) - fi -fi -AC_CHECK_FILE([/dev/ptc], - [ - AC_DEFINE_UNQUOTED(HAVE_DEV_PTS_AND_PTC, 1, [Define if you have /dev/ptc.]) - have_dev_ptc=1 - ] -) -dnl (end of code from openssh-3.2.2p1 configure.ac) - dnl Check for systems where POSIX-style non-blocking I/O (O_NONBLOCK) dnl doesn't work or is unimplemented. On these systems (mostly older dnl ones), use the old BSD-style FIONBIO approach instead. [tcl.m4] @@ -616,191 +305,41 @@ AC_CHECK_FRAMEWORK(IOKit, [#include ]) AC_CHECK_FRAMEWORK(CoreFoundation, [#include ]) dnl Select system-dependant source files. -SERIALSRC=serial_unix.cpp +SERIALSRC=../dummy/serial_dummy.cpp ETHERSRC=../dummy/ether_dummy.cpp SCSISRC=../dummy/scsi_dummy.cpp AUDIOSRC=../dummy/audio_dummy.cpp EXTFSSRC=extfs_unix.cpp EXTRASYSSRCS= -CAN_NATIVE_M68K=no case "$target_os" in -linux*) - ETHERSRC=ether_unix.cpp - AUDIOSRC=audio_oss_esd.cpp - SCSISRC=Linux/scsi_linux.cpp - ;; -freebsd*) - ETHERSRC=ether_unix.cpp - AUDIOSRC=audio_oss_esd.cpp - DEFINES="$DEFINES -DBSD_COMP" - CXXFLAGS="$CXXFLAGS -fpermissive" - dnl Check for the CAM library - AC_CHECK_LIB(cam, cam_open_btl, HAVE_LIBCAM=yes, HAVE_LIBCAM=no) - if [[ "x$HAVE_LIBCAM" = "xno" ]]; then - AC_MSG_WARN([Cannot find libcam for SCSI management, disabling SCSI support.]) - else - dnl Check for the sys kernel includes - AC_CHECK_HEADER(camlib.h) - if [[ "x$ac_cv_header_camlib_h" = "xno" ]]; then - dnl In this case I should fix this thing including a "patch" - dnl to access directly to the functions in the kernel :) --Orlando - AC_MSG_WARN([Cannot find includes for CAM library, disabling SCSI support.]) - else - SCSISRC=FreeBSD/scsi_freebsd.cpp - LIBS="$LIBS -lcam" - DEFINES="$DEFINES -DCAM" - fi - fi - ;; -netbsd*) - CAN_NATIVE_M68K=yes - ETHERSRC=ether_unix.cpp - ;; -solaris*) - AUDIOSRC=Solaris/audio_solaris.cpp - DEFINES="$DEFINES -DBSD_COMP -D_POSIX_PTHREAD_SEMANTICS" - ;; -irix*) - AUDIOSRC=Irix/audio_irix.cpp - EXTRASYSSRCS=Irix/unaligned.c - LIBS="$LIBS -laudio" - WANT_ESD=no - - dnl Check if our compiler supports -IPA (MIPSPro) - HAVE_IPA=no - ocflags="$CFLAGS" - CFLAGS=`echo "$CFLAGS -IPA" | sed -e "s/-g//g"` - AC_MSG_CHECKING(if "-IPA" works) - dnl Do a test compile of an empty function - AC_TRY_COMPILE([#if defined __GNUC__ - # error GCC does not support IPA yet - #endif],, [AC_MSG_RESULT(yes); HAVE_IPA=yes], AC_MSG_RESULT(no)) - CFLAGS="$ocflags" - ;; darwin*) - ETHERSRC=ether_unix.cpp if [[ "x$ac_cv_framework_IOKit" = "xyes" -a "x$ac_cv_framework_CoreFoundation" = "xyes" ]]; then - EXTRASYSSRCS="../MacOSX/sys_darwin.cpp" + EXTRASYSSRCS="Darwin/sys_darwin.cpp" fi - if [[ "x$ac_cv_framework_Carbon" = "xyes" ]]; then - EXTFSSRC=../MacOSX/extfs_macosx.cpp - fi - ;; -cygwin*) - SERIALSRC="../dummy/serial_dummy.cpp" - EXTRASYSSRCS="../Windows/BasiliskII.rc" ;; esac -dnl Is the slirp library supported? -case "$ac_cv_have_byte_bitfields" in -yes|"guessing yes") - CAN_SLIRP=yes - ETHERSRC=ether_unix.cpp - ;; -esac -if [[ -n "$CAN_SLIRP" ]]; then - AC_DEFINE(HAVE_SLIRP, 1, [Define if slirp library is supported]) - SLIRP_SRCS="\ - ../slirp/bootp.c ../slirp/ip_output.c ../slirp/tcp_input.c \ - ../slirp/cksum.c ../slirp/mbuf.c ../slirp/tcp_output.c \ - ../slirp/debug.c ../slirp/misc.c ../slirp/tcp_subr.c \ - ../slirp/if.c ../slirp/sbuf.c ../slirp/tcp_timer.c \ - ../slirp/ip_icmp.c ../slirp/slirp.c ../slirp/tftp.c \ - ../slirp/ip_input.c ../slirp/socket.c ../slirp/udp.c" -fi -AC_SUBST(SLIRP_SRCS) - -if [[ "x$WANT_MACOSX_GUI" = "xyes" ]]; then - CPPFLAGS="$CPPFLAGS -I../MacOSX" - LIBS="$LIBS -framework CoreAudio -framework AudioUnit -framework AudioToolbox" - - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/Controller.mm" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/Emulator.mm" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/EmulatorView.mm" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/PrefsEditor.mm" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/NNThread.m" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/misc_macosx.mm" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx.cpp" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/main_macosx.mm" - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/prefs_macosx.cpp" - - VIDEOSRCS="../MacOSX/video_macosx.mm" -else - EXTRASYSSRCS="$EXTRASYSSRCS main_unix.cpp prefs_unix.cpp" -fi - -if [[ "x$WANT_MACOSX_SOUND" = "xyes" ]]; then - AUDIOSRC="../MacOSX/audio_macosx.cpp ../MacOSX/AudioBackEnd.cpp ../MacOSX/AudioDevice.cpp ../MacOSX/MacOSX_sound_if.cpp" - LIBS="$LIBS -framework AudioToolbox -framework AudioUnit -framework CoreAudio" -fi +EXTRASYSSRCS="$EXTRASYSSRCS main_unix.cpp prefs_unix.cpp" dnl SDL overrides if [[ "x$WANT_SDL" = "xyes" ]]; then AC_DEFINE(USE_SDL, 1, [Define to enble SDL support]) - if [[ "x$WANT_SDL_FRAMEWORK" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS ../SDL/SDLMain.m" - fi fi if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then AC_DEFINE(USE_SDL_VIDEO, 1, [Define to enable SDL video graphics support]) VIDEOSRCS="../SDL/video_sdl.cpp" KEYCODES="../SDL/keycodes" - if [[ "x$ac_cv_framework_Carbon" = "xyes" ]]; then - AC_MSG_CHECKING([whether __LP64__ is defined]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if !defined(__LP64__) - # error __LP64__ not defined - #endif - ]])], - [AC_MSG_RESULT(yes); LP64_DEFINED=yes], - [AC_MSG_RESULT(no)]) - if [[ "x$LP64_DEFINED" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm ../pict.c" - else - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx.cpp" - fi - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/utils_macosx.mm" - CPPFLAGS="$CPPFLAGS -I../MacOSX" - else - case "$target_os" in - cygwin*) - EXTRASYSSRCS="$EXTRASYSSRCS ../Windows/clip_windows.cpp" - ;; - *) - EXTRASYSSRCS="$EXTRASYSSRCS ../dummy/clip_dummy.cpp" - ;; - esac - fi -elif [[ "x$WANT_MACOSX_GUI" != "xyes" ]]; then - VIDEOSRCS="video_x.cpp" - KEYCODES="keycodes" - EXTRASYSSRCS="$EXTRASYSSRCS clip_unix.cpp" + case "$target_os" in + *) + EXTRASYSSRCS="$EXTRASYSSRCS ../dummy/clip_dummy.cpp" + ;; + esac fi if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then AC_DEFINE(USE_SDL_AUDIO, 1, [Define to enable SDL audio support]) AUDIOSRC="../SDL/audio_sdl.cpp" fi -dnl BINCUE overrides - -if [[ "x$have_bincue" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS bincue_unix.cpp" -fi - -dnl libvhd overrides - -if [[ "x$have_libvhd" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS vhd_unix.cpp" -fi - - -dnl Use 68k CPU natively? -WANT_NATIVE_M68K=no -if [[ "x$HAVE_M68K" = "xyes" -a "x$CAN_NATIVE_M68K" = "xyes" ]]; then - AC_DEFINE(ENABLE_NATIVE_M68K, 1, [Define if using native 68k mode.]) - WANT_NATIVE_M68K=yes -fi - if [[ "x$HAVE_PTHREADS" = "xno" ]]; then dnl Serial, ethernet and audio support needs pthreads AC_MSG_WARN([You don't have pthreads, disabling serial, ethernet and audio support.]) @@ -808,7 +347,7 @@ if [[ "x$HAVE_PTHREADS" = "xno" ]]; then ETHERSRC=../dummy/ether_dummy.cpp AUDIOSRC=../dummy/audio_dummy.cpp fi -SYSSRCS="$VIDEOSRCS $EXTFSSRC $SERIALSRC $ETHERSRC $SCSISRC $AUDIOSRC $SEMSRC $UISRCS $MONSRCS $EXTRASYSSRCS" +SYSSRCS="$VIDEOSRCS $EXTFSSRC $SERIALSRC $ETHERSRC $SCSISRC $AUDIOSRC $SEMSRC $UISRCS $EXTRASYSSRCS" dnl Define a macro that translates a yesno-variable into a C macro definition dnl to be put into the config.h file @@ -825,10 +364,6 @@ dnl Check that the host supports TUN/TAP devices AC_CACHE_CHECK([whether TUN/TAP is supported], ac_cv_tun_tap_support, [ AC_TRY_COMPILE([ - #if defined(HAVE_LINUX_IF_H) && defined(HAVE_LINUX_IF_TUN_H) - #include - #include - #endif #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_IF_TUN_H) #include #include @@ -1114,30 +649,6 @@ AC_CACHE_CHECK([whether your system supports Mach exceptions], AC_TRANSLATE_DEFINE(HAVE_MACH_EXCEPTIONS, "$ac_cv_have_mach_exceptions", [Define if your system supports Mach exceptions.]) -dnl Check if Windows exceptions are supported. -AC_CACHE_CHECK([whether your system supports Windows exceptions], - ac_cv_have_win32_exceptions, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_WIN32_EXCEPTIONS 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], [ - sigsegv_recovery=win32 - ac_cv_have_win32_exceptions=yes - ], - ac_cv_have_win32_exceptions=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_win32_exceptions=no - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_WIN32_EXCEPTIONS, "$ac_cv_have_win32_exceptions", - [Define if your system supports Windows exceptions.]) - dnl Otherwise, check if extended signals are supported with . if [[ -z "$sigsegv_recovery" ]]; then AC_CACHE_CHECK([whether your system supports extended signal handlers via asm], @@ -1254,11 +765,6 @@ AC_PATH_PROG([BLESS], "true") dnl Check for linker script support case $target_os:$target_cpu in -linux*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-i386.ld";; -linux*:x86_64) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-x86_64.ld";; -linux*:powerpc) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-ppc.ld";; -netbsd*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-i386.ld";; -freebsd*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/freebsd-i386.ld";; darwin*:*) LINKER_SCRIPT_FLAGS="-Wl,-seg1addr,0x78048000";; esac if [[ -n "$LINKER_SCRIPT_FLAGS" ]]; then @@ -1286,60 +792,52 @@ AC_TRANSLATE_DEFINE(HAVE_LINKER_SCRIPT, "$ac_cv_linker_script_works", [Define if there is a linker script to relocate the executable above 0x70000000.]) dnl Determine the addressing mode to use -if [[ "x$WANT_NATIVE_M68K" = "xyes" ]]; then - ADDRESSING_MODE="real" -else - ADDRESSING_MODE="" - AC_MSG_CHECKING([for the addressing mode to use]) - for am in $ADDRESSING_TEST_ORDER; do - case $am in - real) - dnl Requires ability to mmap() Low Memory globals - if [[ "x$ac_cv_can_map_lm$ac_cv_pagezero_hack" = "xnono" ]]; then - continue - fi - dnl Requires VOSF screen updates - if [[ "x$CAN_VOSF" = "xno" ]]; then - continue - fi - dnl Real addressing will probably work. - ADDRESSING_MODE="real" - WANT_VOSF=yes dnl we can use VOSF and we need it actually - DEFINES="$DEFINES -DREAL_ADDRESSING" - if [[ "x$ac_cv_pagezero_hack" = "xyes" ]]; then - BLESS=Darwin/lowmem - LDFLAGS="$LDFLAGS -pagezero_size 0x2000" - fi - break - ;; - direct) - dnl Requires VOSF screen updates - if [[ "x$CAN_VOSF" = "xyes" ]]; then - ADDRESSING_MODE="direct" - WANT_VOSF=yes dnl we can use VOSF and we need it actually - DEFINES="$DEFINES -DDIRECT_ADDRESSING" - break - fi - ;; - banks) - dnl Default addressing mode - ADDRESSING_MODE="memory banks" - break - ;; - *) - AC_MSG_ERROR([Internal configure.in script error for $am addressing mode]) - esac - done - AC_MSG_RESULT($ADDRESSING_MODE) - if [[ "x$ADDRESSING_MODE" = "x" ]]; then - AC_MSG_WARN([Sorry, no suitable addressing mode in $ADDRESSING_TEST_ORDER]) - ADDRESSING_MODE="memory banks" - fi -fi -dnl Banked Memory Addressing mode is not supported by the JIT compiler -if [[ "x$WANT_JIT" = "xyes" -a "x$ADDRESSING_MODE" = "xmemory banks" ]]; then - AC_MSG_ERROR([Sorry, the JIT Compiler requires Direct Addressing, at least]) +ADDRESSING_MODE="" +AC_MSG_CHECKING([for the addressing mode to use]) +for am in $ADDRESSING_TEST_ORDER; do + case $am in + real) + dnl Requires ability to mmap() Low Memory globals + if [[ "x$ac_cv_can_map_lm$ac_cv_pagezero_hack" = "xnono" ]]; then + continue + fi + dnl Requires VOSF screen updates + if [[ "x$CAN_VOSF" = "xno" ]]; then + continue + fi + dnl Real addressing will probably work. + ADDRESSING_MODE="real" + WANT_VOSF=yes dnl we can use VOSF and we need it actually + DEFINES="$DEFINES -DREAL_ADDRESSING" + if [[ "x$ac_cv_pagezero_hack" = "xyes" ]]; then + BLESS=Darwin/lowmem + LDFLAGS="$LDFLAGS -pagezero_size 0x2000" + fi + break + ;; + direct) + dnl Requires VOSF screen updates + if [[ "x$CAN_VOSF" = "xyes" ]]; then + ADDRESSING_MODE="direct" + WANT_VOSF=yes dnl we can use VOSF and we need it actually + DEFINES="$DEFINES -DDIRECT_ADDRESSING" + break + fi + ;; + banks) + dnl Default addressing mode + ADDRESSING_MODE="memory banks" + break + ;; + *) + AC_MSG_ERROR([Internal configure.in script error for $am addressing mode]) + esac +done +AC_MSG_RESULT($ADDRESSING_MODE) +if [[ "x$ADDRESSING_MODE" = "x" ]]; then + AC_MSG_WARN([Sorry, no suitable addressing mode in $ADDRESSING_TEST_ORDER]) + ADDRESSING_MODE="memory banks" fi dnl Enable VOSF screen updates with this feature is requested and feasible @@ -1349,16 +847,6 @@ else WANT_VOSF=no fi -dnl Check for GAS. -HAVE_GAS=no -AC_MSG_CHECKING(for GAS .p2align feature) -cat >conftest.S << EOF - .text - .p2align 5 -EOF -if $CC conftest.S -c -o conftest.o >/dev/null 2>&1 ; then HAVE_GAS=yes; fi -AC_MSG_RESULT($HAVE_GAS) - dnl Check for GCC 2.7 or higher. HAVE_GCC27=no AC_MSG_CHECKING(for GCC 2.7 or higher) @@ -1395,54 +883,6 @@ if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_I386" = "xyes" ]]; then CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -fno-exceptions" fi -dnl (gb) Do not merge constants since it breaks fpu/fpu_x86.cpp. -dnl As of 2001/08/02, this affects the following compilers: -dnl Official: probably gcc-3.1 (mainline CVS) -dnl Mandrake: gcc-2.96 >= 0.59mdk, gcc-3.0.1 >= 0.1mdk -dnl Red Hat : gcc-2.96 >= 89, gcc-3.0 >= 1 -if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then - SAVED_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -fno-merge-constants" - AC_CACHE_CHECK([whether GCC supports constants merging], ac_cv_gcc_constants_merging, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_COMPILE([],[],[ac_cv_gcc_constants_merging=yes],[ac_cv_gcc_constants_merging=no]) - AC_LANG_RESTORE - ]) - if [[ "x$ac_cv_gcc_constants_merging" != "xyes" ]]; then - CXXFLAGS="$SAVED_CXXFLAGS" - fi -fi - -dnl Store motion was introduced in 3.3-hammer branch and any gcc >= 3.4 -dnl However, there are some corner cases exposed on x86-64 -if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then - SAVED_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -fno-gcse-sm" - AC_CACHE_CHECK([whether GCC supports store motion], ac_cv_gcc_store_motion, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_COMPILE([],[],[ac_cv_gcc_store_motion=yes],[ac_cv_gcc_store_motion=no]) - AC_LANG_RESTORE - ]) - if [[ "x$ac_cv_gcc_store_motion" != "xyes" ]]; then - CXXFLAGS="$SAVED_CXXFLAGS" - fi -fi - -dnl Add -fno-strict-aliasing for slirp sources -if [[ "x$HAVE_GCC30" = "xyes" ]]; then - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-strict-aliasing" - AC_CACHE_CHECK([whether the compiler supports -fno-strict-aliasing], - ac_cv_gcc_no_strict_aliasing, [ - AC_TRY_COMPILE([],[],[ac_cv_gcc_no_strict_aliasing=yes],[ac_cv_gcc_no_strict_aliasing=no]) - ]) - if [[ "x$ac_cv_gcc_no_strict_aliasing" = "xyes" ]]; then - AC_SUBST(SLIRP_CFLAGS, "-fno-strict-aliasing") - fi - CFLAGS="$SAVED_CFLAGS" -fi dnl Add -mdynamic-no-pic for MacOS X (XXX icc10 will support MacOS X) if [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then @@ -1460,257 +900,13 @@ if [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then fi dnl Select appropriate CPU source and REGPARAM define. -ASM_OPTIMIZATIONS=none -CPUSRCS="cpuemu1.cpp cpuemu2.cpp cpuemu3.cpp cpuemu4.cpp cpuemu5.cpp cpuemu6.cpp cpuemu7.cpp cpuemu8.cpp" - -dnl (gb) JITSRCS will be emptied later if the JIT is not available -dnl Other platforms should define their own set of noflags file variants -CAN_JIT=no -JITSRCS="compemu1.cpp compemu2.cpp compemu3.cpp compemu4.cpp compemu5.cpp compemu6.cpp compemu7.cpp compemu8.cpp" - -if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_I386" = "xyes" ]]; then - dnl i386 CPU - DEFINES="$DEFINES -DUNALIGNED_PROFITABLE -DREGPARAM=\"__attribute__((regparm(3)))\"" - if [[ "x$HAVE_GAS" = "xyes" ]]; then - ASM_OPTIMIZATIONS=i386 - DEFINES="$DEFINES -DX86_ASSEMBLY -DOPTIMIZED_FLAGS -DSAHF_SETO_PROFITABLE" - JITSRCS="cpuemu1_nf.cpp cpuemu2_nf.cpp cpuemu3_nf.cpp cpuemu4_nf.cpp cpuemu5_nf.cpp cpuemu6_nf.cpp cpuemu7_nf.cpp cpuemu8_nf.cpp $JITSRCS" - CAN_JIT=yes - fi -elif [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_X86_64" = "xyes" ]]; then - dnl x86-64 CPU - DEFINES="$DEFINES -DUNALIGNED_PROFITABLE" - if [[ "x$HAVE_GAS" = "xyes" ]]; then - ASM_OPTIMIZATIONS="x86-64" - DEFINES="$DEFINES -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS" - JITSRCS="cpuemu1_nf.cpp cpuemu2_nf.cpp cpuemu3_nf.cpp cpuemu4_nf.cpp cpuemu5_nf.cpp cpuemu6_nf.cpp cpuemu7_nf.cpp cpuemu8_nf.cpp $JITSRCS" - CAN_JIT=yes - fi -elif [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_SPARC" = "xyes" -a "x$HAVE_GAS" = "xyes" ]]; then - dnl SPARC CPU - case "$target_os" in - solaris*) - AC_MSG_CHECKING(SPARC CPU architecture) - SPARC_TYPE=`Solaris/which_sparc` - AC_MSG_RESULT($SPARC_TYPE) - case "$SPARC_TYPE" in - SPARC_V8) - ASM_OPTIMIZATIONS="SPARC V8 architecture" - DEFINES="$DEFINES -DSPARC_V8_ASSEMBLY" dnl -DOPTIMIZED_FLAGS" - CFLAGS="$CFLAGS -Wa,-Av8" - CXXFLAGS="$CXXFLAGS -Wa,-Av8" - ;; - SPARC_V9) - ASM_OPTIMIZATIONS="SPARC V9 architecture" - DEFINES="$DEFINES -DSPARC_V9_ASSEMBLY" dnl -DOPTIMIZED_FLAGS" - CFLAGS="$CFLAGS -Wa,-Av9" - CXXFLAGS="$CXXFLAGS -Wa,-Av9" - ;; - esac - ;; - esac -elif [[ "x$WANT_NATIVE_M68K" = "xyes" ]]; then - dnl Native m68k, no emulation - CPUINCLUDES="-I../native_cpu" - CPUSRCS="asm_support.s" -fi - -dnl Enable JIT compiler, if possible. -if [[ "x$WANT_JIT" = "xyes" -a "x$CAN_JIT" ]]; then - JITSRCS="$JITSRCS ../uae_cpu/compiler/compemu_support.cpp ../uae_cpu/compiler/compemu_fpp.cpp compstbl.o cpustbl_nf.o" - DEFINES="$DEFINES -DUSE_JIT -DUSE_JIT_FPU" - - if [[ "x$WANT_JIT_DEBUG" = "xyes" ]]; then - if [[ "x$WANT_MON" = "xyes" ]]; then - DEFINES="$DEFINES -DJIT_DEBUG=1" - else - AC_MSG_WARN([cxmon not found, ignoring --enable-jit-debug]) - WANT_JIT_DEBUG=no - fi - fi - - dnl IEEE core is the only FPU emulator to use with the JIT compiler - case $FPE_CORE_TEST_ORDER in - ieee*) ;; - *) AC_MSG_WARN([Forcing use of the IEEE FPU core, as the JIT compiler supports only this one.]) ;; - esac - FPE_CORE_TEST_ORDER="ieee" -else - WANT_JIT=no - WANT_JIT_DEBUG=no - JITSRCS="" -fi - -dnl Utility macro used by next two tests. -dnl AC_EXAMINE_OBJECT(C source code, -dnl commands examining object file, -dnl [commands to run if compile failed]): -dnl -dnl Compile the source code to an object file; then convert it into a -dnl printable representation. All unprintable characters and -dnl asterisks (*) are replaced by dots (.). All white space is -dnl deleted. Newlines (ASCII 0x10) in the input are preserved in the -dnl output, but runs of newlines are compressed to a single newline. -dnl Finally, line breaks are forcibly inserted so that no line is -dnl longer than 80 columns and the file ends with a newline. The -dnl result of all this processing is in the file conftest.dmp, which -dnl may be examined by the commands in the second argument. -dnl -AC_DEFUN([gcc_AC_EXAMINE_OBJECT], -[AC_LANG_SAVE -AC_LANG_C -dnl Next bit cribbed from AC_TRY_COMPILE. -cat > conftest.$ac_ext < conftest.dmp - $2 -ifelse($3, , , else - $3 -)dnl -fi -rm -rf conftest* -AC_LANG_RESTORE]) - -dnl Floating point format probe. -dnl The basic concept is the same as the above: grep the object -dnl file for an interesting string. We have to watch out for -dnl rounding changing the values in the object, however; this is -dnl handled by ignoring the least significant byte of the float. -dnl -dnl Does not know about VAX G-float or C4x idiosyncratic format. -dnl It does know about PDP-10 idiosyncratic format, but this is -dnl not presently supported by GCC. S/390 "binary floating point" -dnl is in fact IEEE (but maybe we should have that in EBCDIC as well -dnl as ASCII?) -dnl -AC_DEFUN([gcc_AC_C_FLOAT_FORMAT], -[AC_CACHE_CHECK(floating point format, ac_cv_c_float_format, -[gcc_AC_EXAMINE_OBJECT( -[/* This will not work unless sizeof(double) == 8. */ -extern char sizeof_double_must_be_8 [sizeof(double) == 8 ? 1 : -1]; - -/* This structure must have no internal padding. */ -struct possibility { - char prefix[8]; - double candidate; - char postfix[8]; -}; - -#define C(cand) { "\nformat:", cand, ":tamrof\n" } -struct possibility table [] = -{ - C( 3.25724264705901305206e+01), /* @@IEEEFP - IEEE 754 */ - C( 3.53802595280598432000e+18), /* D__float - VAX */ - C( 5.32201830133125317057e-19), /* D.PDP-10 - PDP-10 - the dot is 0x13a */ - C( 1.77977764695171661377e+10), /* IBMHEXFP - s/390 format, ascii */ - C(-5.22995989424860458374e+10) /* IBMHEXFP - s/390 format, EBCDIC */ -};], - [if grep 'format:.@IEEEF.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (big-endian)' - elif grep 'format:.I@@PFE.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (big-endian)' - elif grep 'format:.FEEEI@.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (little-endian)' - elif grep 'format:.EFP@@I.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (little-endian)' - elif grep 'format:.__floa.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='VAX D-float' - elif grep 'format:..PDP-1.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='PDP-10' - elif grep 'format:.BMHEXF.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IBM 370 hex' - else - AC_MSG_ERROR(Unknown floating point format) - fi], - [AC_MSG_ERROR(compile failed)]) -]) -# IEEE is the default format. If the float endianness isn't the same -# as the integer endianness, we have to set FLOAT_WORDS_BIG_ENDIAN -# (which is a tristate: yes, no, default). This is only an issue with -# IEEE; the other formats are only supported by a few machines each, -# all with the same endianness. -format=IEEE_FLOAT_FORMAT -fbigend= -case $ac_cv_c_float_format in - 'IEEE (big-endian)' ) - if test $ac_cv_c_bigendian = no; then - fbigend=1 - fi - ;; - 'IEEE (little-endian)' ) - if test $ac_cv_c_bigendian = yes; then - fbigend=0 - fi - ;; - 'VAX D-float' ) - format=VAX_FLOAT_FORMAT - ;; - 'PDP-10' ) - format=PDP10_FLOAT_FORMAT - ;; - 'IBM 370 hex' ) - format=IBM_FLOAT_FORMAT - ;; -esac -AC_DEFINE_UNQUOTED(HOST_FLOAT_FORMAT, $format, - [Define to the floating point format of the host machine.]) -if test -n "$fbigend"; then - AC_DEFINE_UNQUOTED(HOST_FLOAT_WORDS_BIG_ENDIAN, $fbigend, - [Define to 1 if the host machine stores floating point numbers in - memory with the word containing the sign bit at the lowest address, - or to 0 if it does it the other way around. - - This macro should not be defined if the ordering is the same as for - multi-word integers.]) -fi -]) +CPUSRCS="cpuemu.cpp" dnl Select appropriate FPU source. -gcc_AC_C_FLOAT_FORMAT AC_CHECK_HEADERS(ieee754.h ieeefp.h floatingpoint.h nan.h) for fpe in $FPE_CORE_TEST_ORDER; do case $fpe in - ieee) - case $ac_cv_c_float_format in - IEEE*) - FPE_CORE="IEEE fpu core" - DEFINES="$DEFINES -DFPU_IEEE" - FPUSRCS="../uae_cpu/fpu/fpu_ieee.cpp" - dnl Math functions not mandated by C99 standard - AC_CHECK_FUNCS(isnanl isinfl) - dnl Math functions required by C99 standard, but probably not - dnl implemented everywhere. In that case, we fall back to the - dnl regular variant for doubles. - AC_CHECK_FUNCS(logl log10l expl powl fabsl sqrtl) - AC_CHECK_FUNCS(sinl cosl tanl sinhl coshl tanhl) - AC_CHECK_FUNCS(asinl acosl atanl asinhl acoshl atanhl) - AC_CHECK_FUNCS(floorl ceill) - break - ;; - esac - ;; - x86) - if [[ ":$HAVE_GCC27:$HAVE_I386:$HAVE_GAS:" = ":yes:yes:yes:" ]]; then - FPE_CORE="i387 fpu core" - DEFINES="$DEFINES -DFPU_X86" - FPUSRCS="../uae_cpu/fpu/fpu_x86.cpp" - break - fi - ;; uae) FPE_CORE="uae fpu core" DEFINES="$DEFINES -DFPU_UAE" @@ -1731,18 +927,8 @@ AC_CHECK_FUNCS(atanh) AC_CHECK_FUNCS(isnan isinf finite isnormal signbit) dnl UAE CPU sources for all non-m68k-native architectures. -if [[ "x$WANT_NATIVE_M68K" = "xno" ]]; then - CPUINCLUDES="-I../uae_cpu" - CPUSRCS="../uae_cpu/basilisk_glue.cpp ../uae_cpu/memory.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp $FPUSRCS cpustbl.cpp cpudefs.cpp $CPUSRCS $JITSRCS" -fi - -dnl Or if we have -IPA (MIPSPro compilers) -if [[ "x$HAVE_IPA" = "xyes" ]]; then - CFLAGS="`echo $CFLAGS | sed -e 's/-g//g'` -O3 -OPT:Olimit=0 -IPA" - CXXFLAGS="`echo $CXXFLAGS | sed -e 's/-g//g'` -O3 -OPT:Olimit=0 -IPA" - CXXFLAGS="-LANG:std $CXXFLAGS" - LDFLAGS="$LDFLAGS -O3 -OPT:Olimit=0 -IPA" -fi +CPUINCLUDES="-I../uae_cpu" +CPUSRCS="../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp $FPUSRCS cpustbl.cpp cpudefs.cpp $CPUSRCS" dnl Generate Makefile. AC_SUBST(DEFINES) @@ -1758,23 +944,9 @@ dnl Print summary. echo echo Basilisk II configuration summary: echo -echo Mac OS X GUI ........................... : $WANT_MACOSX_GUI -echo Mac OS X Sound ......................... : $WANT_MACOSX_SOUND echo SDL support ............................ : $SDL_SUPPORT -echo BINCUE support ......................... : $have_bincue -echo LIBVHD support ......................... : $have_libvhd -echo XFree86 DGA support .................... : $WANT_XF86_DGA -echo XFree86 VidMode support ................ : $WANT_XF86_VIDMODE -echo fbdev DGA support ...................... : $WANT_FBDEV_DGA echo Enable video on SEGV signals ........... : $WANT_VOSF -echo ESD sound support ...................... : $WANT_ESD -echo GTK user interface ..................... : $WANT_GTK -echo mon debugger support ................... : $WANT_MON -echo Running m68k code natively ............. : $WANT_NATIVE_M68K -echo Use JIT compiler ....................... : $WANT_JIT -echo JIT debug mode ......................... : $WANT_JIT_DEBUG echo Floating-Point emulation core .......... : $FPE_CORE -echo Assembly optimizations ................. : $ASM_OPTIMIZATIONS echo Addressing mode ........................ : $ADDRESSING_MODE echo Bad memory access recovery type ........ : $sigsegv_recovery echo diff --git a/BasiliskII/src/Unix/disk_sparsebundle.cpp b/BasiliskII/src/Unix/disk_sparsebundle.cpp deleted file mode 100644 index 063e3296..00000000 --- a/BasiliskII/src/Unix/disk_sparsebundle.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* - * disk_sparsebundle.cpp - Apple sparse bundle implementation - * - * Basilisk II (C) Dave Vasilevsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "disk_unix.h" -#include "tinyxml2.h" - -#include -#include -#include - -#if defined __APPLE__ && defined __MACH__ -#define __MACOSX__ 1 -#endif - -struct disk_sparsebundle : disk_generic { - disk_sparsebundle(const char *bands, int fd, bool read_only, - loff_t band_size, loff_t total_size) - : token_fd(fd), read_only(read_only), band_size(band_size), - total_size(total_size), band_dir(strdup(bands)), - band_cur(-1), band_fd(-1), band_alloc(-1) { - } - - virtual ~disk_sparsebundle() { - if (band_fd != -1) - close(band_fd); - close(token_fd); - free(band_dir); - } - - virtual bool is_read_only() { return read_only; } - virtual loff_t size() { return total_size; } - - virtual size_t read(void *buf, loff_t offset, size_t length) { - return band_do(&disk_sparsebundle::band_read, buf, offset, length); - } - - virtual size_t write(void *buf, loff_t offset, size_t length) { - return band_do(&disk_sparsebundle::band_write, buf, offset, length); - } - -protected: - int token_fd; // lockfile - bool read_only; - loff_t band_size, total_size; - char *band_dir; // directory containing band files - - // Currently open band - loff_t band_cur; // index of the band - int band_fd; // -1 if not open - loff_t band_alloc; // how much space is already used? - - typedef ssize_t (disk_sparsebundle::*band_func)(char *buf, loff_t band, - size_t offset, size_t len); - - // Split an (offset, length) operation into bands. - size_t band_do(band_func func, void *buf, loff_t offset, size_t length) { - char *b = (char*)buf; - loff_t band = offset / band_size; - size_t done = 0; - while (length) { - if (offset >= total_size) - break; - size_t start = offset % band_size; - size_t segment = std::min((size_t)band_size - start, length); - - ssize_t err = (this->*func)(b, band, start, segment); - if (err > 0) - done += err; - if (err < segment) - break; - - b += segment; - offset += segment; - length -= segment; - ++band; - } - return done; - } - - // Open a band by index. It's ok if the band is already open. - enum open_ret { - OPEN_FAILED = 0, - OPEN_NOENT, // Band doesn't exist yet - OPEN_OK, - }; - open_ret open_band(loff_t band, bool create) { - if (band_cur == band) - return OPEN_OK; - - char path[PATH_MAX + 1]; - if (snprintf(path, PATH_MAX, "%s/%lx", band_dir, - (unsigned long)band) >= PATH_MAX) { - return OPEN_FAILED; - } - - if (band_fd != -1) - close(band_fd); - band_alloc = -1; - band_cur = -1; - - int oflags = read_only ? O_RDONLY : O_RDWR; - if (create) - oflags |= O_CREAT; - band_fd = open(path, oflags, 0644); - if (band_fd == -1) { - return (!create && errno == ENOENT) ? OPEN_NOENT : OPEN_FAILED; - } - - // Get the allocated size - if (!read_only) { - band_alloc = lseek(band_fd, 0, SEEK_END); - if (band_alloc == -1) - band_alloc = band_size; - } - band_cur = band; - return OPEN_OK; - } - - ssize_t band_read(char *buf, loff_t band, size_t off, size_t len) { - open_ret st = open_band(band, false); - if (st == OPEN_FAILED) - return -1; - - // Unallocated bytes - size_t want = (st == OPEN_NOENT || off >= band_alloc) ? 0 - : std::min(len, (size_t)band_alloc - off); - if (want) { - if (lseek(band_fd, off, SEEK_SET) == -1) - return -1; - ssize_t err = ::read(band_fd, buf, want); - if (err < want) - return err; - } - memset(buf + want, 0, len - want); - return len; - } - - ssize_t band_write(char *buf, loff_t band, size_t off, size_t len) { - // If space is unused, don't needlessly fill it with zeros - - // Find min length such that all trailing chars are zero: - size_t nz = len; - for (; nz > 0 && !buf[nz-1]; --nz) - ; // pass - - open_ret st = open_band(band, nz); - if (st != OPEN_OK) - return st == OPEN_NOENT ? len : -1; - - if (lseek(band_fd, off, SEEK_SET) == -1) - return -1; - - size_t space = (off >= band_alloc ? 0 : band_alloc - off); - size_t want = std::max(nz, std::min(space, len)); - ssize_t err = ::write(band_fd, buf, want); - if (err >= 0) - band_alloc = std::max(band_alloc, loff_t(off + err)); - if (err < want) - return err; - return len; - } -}; - - - -using tinyxml2::XML_NO_ERROR; -using tinyxml2::XMLElement; - -// Simplistic plist parser -struct plist { - plist() : doc(true, tinyxml2::COLLAPSE_WHITESPACE) { } - - bool open(const char *path) { - if (doc.LoadFile(path) != XML_NO_ERROR) - return false; - tinyxml2::XMLHandle hnd(&doc); - dict = hnd.FirstChildElement("plist").FirstChildElement("dict") - .ToElement(); - return dict; - } - - const char *str_val(const char *key) { - return value(key, "string"); - } - - bool int_val(const char *key, loff_t *i) { - const char *v = value(key, "integer"); - if (!v || !*v) - return false; - - char *endp; - long long ll = strtoll(v, &endp, 10); - if (*endp) - return false; - *i = ll; - return true; - } - -protected: - tinyxml2::XMLDocument doc; - XMLElement *dict; - - const char *value(const char *key, const char *type) { - // Assume it's a flat plist - XMLElement *cur = dict->FirstChildElement(); - bool found_key = false; - while (cur) { - if (found_key) { - if (strcmp(cur->Name(), type) != 0) - return NULL; - return cur->GetText(); - } - found_key = strcmp(cur->Name(), "key") == 0 - && strcmp(cur->GetText(), key) == 0; - cur = cur->NextSiblingElement(); - } - return NULL; - } -}; - - -static int try_open(const char *path, bool read_only, bool *locked) { - int oflags = (read_only ? O_RDONLY : O_RDWR); - int lockflags = 0; -#if defined(__MACOSX__) - lockflags = O_NONBLOCK | (read_only ? O_SHLOCK : O_EXLOCK); -#endif - int fd = open(path, oflags | lockflags); -#if defined(__MACOSX__) - if (fd == -1) { - if (errno == EOPNOTSUPP) { // no locking support, try again - fd = open(path, oflags); - } else if (errno == EAGAIN) { // locked - *locked = true; - } - } -#endif - return fd; -} - -disk_generic::status disk_sparsebundle_factory(const char *path, - bool read_only, disk_generic **disk) { - // Does it look like a sparsebundle? - char buf[PATH_MAX + 1]; - if (snprintf(buf, PATH_MAX, "%s/%s", path, "Info.plist") >= PATH_MAX) - return disk_generic::DISK_UNKNOWN; - - plist pl; - if (!pl.open(buf)) - return disk_generic::DISK_UNKNOWN; - - const char *type; - if (!(type = pl.str_val("diskimage-bundle-type"))) - return disk_generic::DISK_UNKNOWN; - if (strcmp(type, "com.apple.diskimage.sparsebundle") != 0) - return disk_generic::DISK_UNKNOWN; - - - // Find the sparsebundle parameters - loff_t version, band_size, total_size; - if (!pl.int_val("bundle-backingstore-version", &version) || version != 1) { - fprintf(stderr, "sparsebundle: Bad version\n"); - return disk_generic::DISK_UNKNOWN; - } - if (!pl.int_val("band-size", &band_size) - || !pl.int_val("size", &total_size)) { - fprintf(stderr, "sparsebundle: Can't find size\n"); - return disk_generic::DISK_INVALID; - } - - - // Check if we can open it - if (snprintf(buf, PATH_MAX, "%s/%s", path, "token") >= PATH_MAX) - return disk_generic::DISK_INVALID; - bool locked = false; - int token = try_open(buf, read_only, &locked); - if (token == -1 && !read_only) { // try again, read-only - token = try_open(buf, true, &locked); - if (token != -1 && !read_only) - fprintf(stderr, "sparsebundle: Can only mount read-only\n"); - read_only = true; - } - if (token == -1) { - if (locked) - fprintf(stderr, "sparsebundle: Refusing to double-mount\n"); - else - perror("sparsebundle: open failed:"); - return disk_generic::DISK_INVALID; - } - - - // We're good to go! - if (snprintf(buf, PATH_MAX, "%s/%s", path, "bands") >= PATH_MAX) - return disk_generic::DISK_INVALID; - *disk = new disk_sparsebundle(buf, token, read_only, band_size, - total_size); - return disk_generic::DISK_VALID; -} diff --git a/BasiliskII/src/Unix/disk_unix.h b/BasiliskII/src/Unix/disk_unix.h index 6c427881..042c90ef 100644 --- a/BasiliskII/src/Unix/disk_unix.h +++ b/BasiliskII/src/Unix/disk_unix.h @@ -42,7 +42,4 @@ struct disk_generic { typedef disk_generic::status (disk_factory)(const char *path, bool read_only, disk_generic **disk); -extern disk_factory disk_sparsebundle_factory; -extern disk_factory disk_vhd_factory; - #endif diff --git a/BasiliskII/src/Unix/ether_unix.cpp b/BasiliskII/src/Unix/ether_unix.cpp deleted file mode 100644 index 526ee29c..00000000 --- a/BasiliskII/src/Unix/ether_unix.cpp +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * ether_unix.cpp - Ethernet device driver, Unix specific stuff (Linux and FreeBSD) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -/* - * NOTES concerning MacOS X issues: - * - poll() does not exist in 10.2.8, but is available in 10.4.4 - * - select(), and very likely poll(), are not cancellation points. So - * the ethernet thread doesn't stop on exit. An explicit check is - * performed to workaround this problem. - */ -#if (defined __APPLE__ && defined __MACH__) || ! defined HAVE_POLL -#define USE_POLL 0 -#else -#define USE_POLL 1 -#endif - -// Define to let the slirp library determine the right timeout for select() -#define USE_SLIRP_TIMEOUT 1 - -#ifdef HAVE_SYS_POLL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__FreeBSD__) || defined(sgi) || (defined(__APPLE__) && defined(__MACH__)) -#include -#endif - -#if defined(HAVE_LINUX_IF_H) && defined(HAVE_LINUX_IF_TUN_H) -#include -#include -#endif - -#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_IF_TUN_H) -#include -#include -#endif - -#ifdef HAVE_SLIRP -#include "libslirp.h" -#include "ctl.h" -#endif - -#include "cpu_emulation.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "user_strings.h" -#include "ether.h" -#include "ether_defs.h" - -#ifndef NO_STD_NAMESPACE -using std::map; -#endif - -#define DEBUG 0 -#include "debug.h" - -#define STATISTICS 0 -#define MONITOR 0 - - -// Ethernet device types -enum { - NET_IF_SHEEPNET, - NET_IF_ETHERTAP, - NET_IF_TUNTAP, - NET_IF_SLIRP -}; - -// Constants -#if ENABLE_TUNTAP -static const char ETHERCONFIG_FILE_NAME[] = DATADIR "/tunconfig"; -#endif - -// Global variables -static int fd = -1; // fd of sheep_net device -static pthread_t ether_thread; // Packet reception thread -static pthread_attr_t ether_thread_attr; // Packet reception thread attributes -static bool thread_active = false; // Flag: Packet reception thread installed -static sem_t int_ack; // Interrupt acknowledge semaphore -static bool udp_tunnel; // Flag: UDP tunnelling active, fd is the socket descriptor -static int net_if_type = -1; // Ethernet device type -static char *net_if_name = NULL; // TUN/TAP device name -static const char *net_if_script = NULL; // Network config script -static pthread_t slirp_thread; // Slirp reception thread -static bool slirp_thread_active = false; // Flag: Slirp reception threadinstalled -static int slirp_output_fd = -1; // fd of slirp output pipe -static int slirp_input_fds[2] = { -1, -1 }; // fds of slirp input pipe -#ifdef SHEEPSHAVER -static bool net_open = false; // Flag: initialization succeeded, network device open -static uint8 ether_addr[6]; // Our Ethernet address -#else -const bool ether_driver_opened = true; // Flag: is the MacOS driver opened? -#endif - -// Attached network protocols, maps protocol type to MacOS handler address -static map net_protocols; - -// Prototypes -static void *receive_func(void *arg); -static void *slirp_receive_func(void *arg); -static int16 ether_do_add_multicast(uint8 *addr); -static int16 ether_do_del_multicast(uint8 *addr); -static int16 ether_do_write(uint32 arg); -static void ether_do_interrupt(void); -static void slirp_add_redirs(); -static int slirp_add_redir(const char *redir_str); - - -/* - * Start packet reception thread - */ - -static bool start_thread(void) -{ - if (sem_init(&int_ack, 0, 0) < 0) { - printf("WARNING: Cannot init semaphore"); - return false; - } - - Set_pthread_attr(ðer_thread_attr, 1); - thread_active = (pthread_create(ðer_thread, ðer_thread_attr, receive_func, NULL) == 0); - if (!thread_active) { - printf("WARNING: Cannot start Ethernet thread"); - return false; - } - -#ifdef HAVE_SLIRP - if (net_if_type == NET_IF_SLIRP) { - slirp_thread_active = (pthread_create(&slirp_thread, NULL, slirp_receive_func, NULL) == 0); - if (!slirp_thread_active) { - printf("WARNING: Cannot start slirp reception thread\n"); - return false; - } - } -#endif - - return true; -} - - -/* - * Stop packet reception thread - */ - -static void stop_thread(void) -{ -#ifdef HAVE_SLIRP - if (slirp_thread_active) { -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(slirp_thread); -#endif - pthread_join(slirp_thread, NULL); - slirp_thread_active = false; - } -#endif - - if (thread_active) { -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(ether_thread); -#endif - pthread_join(ether_thread, NULL); - sem_destroy(&int_ack); - thread_active = false; - } -} - - -/* - * Execute network script up|down - */ - -static bool execute_network_script(const char *action) -{ - if (net_if_script == NULL || net_if_name == NULL) - return false; - - int pid = fork(); - if (pid >= 0) { - if (pid == 0) { - char *args[4]; - args[0] = (char *)net_if_script; - args[1] = net_if_name; - args[2] = (char *)action; - args[3] = NULL; - execv(net_if_script, args); - exit(1); - } - int status; - while (waitpid(pid, &status, 0) != pid); - return WIFEXITED(status) && WEXITSTATUS(status) == 0; - } - - return false; -} - - -/* - * Initialization - */ - -bool ether_init(void) -{ - int val; - char str[256]; - - // Do nothing if no Ethernet device specified - const char *name = PrefsFindString("ether"); - if (name == NULL) - return false; - - // Determine Ethernet device type - net_if_type = -1; - if (strncmp(name, "tap", 3) == 0) - net_if_type = NET_IF_ETHERTAP; -#if ENABLE_TUNTAP - else if (strcmp(name, "tun") == 0) - net_if_type = NET_IF_TUNTAP; -#endif -#ifdef HAVE_SLIRP - else if (strcmp(name, "slirp") == 0) - net_if_type = NET_IF_SLIRP; -#endif - else - net_if_type = NET_IF_SHEEPNET; - - // Don't raise SIGPIPE, let errno be set to EPIPE - struct sigaction sigpipe_sa; - if (sigaction(SIGPIPE, NULL, &sigpipe_sa) == 0) { - assert(sigpipe_sa.sa_handler == SIG_DFL || sigpipe_sa.sa_handler == SIG_IGN); - sigfillset(&sigpipe_sa.sa_mask); - sigpipe_sa.sa_flags = 0; - sigpipe_sa.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &sigpipe_sa, NULL); - } - -#ifdef HAVE_SLIRP - // Initialize slirp library - if (net_if_type == NET_IF_SLIRP) { - if (slirp_init() < 0) { - sprintf(str, "%s", GetString(STR_SLIRP_NO_DNS_FOUND_WARN)); - WarningAlert(str); - return false; - } - - // Open slirp output pipe - int fds[2]; - if (pipe(fds) < 0) - return false; - fd = fds[0]; - slirp_output_fd = fds[1]; - - // Open slirp input pipe - if (pipe(slirp_input_fds) < 0) - return false; - - // Set up port redirects - slirp_add_redirs(); - } -#endif - - // Open sheep_net or ethertap or TUN/TAP device - char dev_name[16]; - switch (net_if_type) { - case NET_IF_ETHERTAP: - sprintf(dev_name, "/dev/%s", name); - break; - case NET_IF_TUNTAP: - strcpy(dev_name, "/dev/net/tun"); - break; - case NET_IF_SHEEPNET: - strcpy(dev_name, "/dev/sheep_net"); - break; - } - if (net_if_type != NET_IF_SLIRP) { - fd = open(dev_name, O_RDWR); - if (fd < 0) { - sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno)); - WarningAlert(str); - goto open_error; - } - } - -#if ENABLE_TUNTAP - // Open TUN/TAP interface - if (net_if_type == NET_IF_TUNTAP) { - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strcpy(ifr.ifr_name, "tun%d"); - if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) { - sprintf(str, GetString(STR_SHEEP_NET_ATTACH_WARN), strerror(errno)); - WarningAlert(str); - goto open_error; - } - - // Get network config script file path - net_if_script = PrefsFindString("etherconfig"); - if (net_if_script == NULL) - net_if_script = ETHERCONFIG_FILE_NAME; - - // Start network script up - if (net_if_script == NULL) { - sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script not found"); - WarningAlert(str); - goto open_error; - } - net_if_name = strdup(ifr.ifr_name); - if (!execute_network_script("up")) { - sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script execute error"); - WarningAlert(str); - goto open_error; - } - D(bug("Connected to host network interface: %s\n", net_if_name)); - } -#endif - -#if defined(__linux__) - // Attach sheep_net to selected Ethernet card - if (net_if_type == NET_IF_SHEEPNET && ioctl(fd, SIOCSIFLINK, name) < 0) { - sprintf(str, GetString(STR_SHEEP_NET_ATTACH_WARN), strerror(errno)); - WarningAlert(str); - goto open_error; - } -#endif - - // Set nonblocking I/O -#ifdef USE_FIONBIO - int nonblock = 1; - if (ioctl(fd, FIONBIO, &nonblock) < 0) { - sprintf(str, GetString(STR_BLOCKING_NET_SOCKET_WARN), strerror(errno)); - WarningAlert(str); - goto open_error; - } -#else - val = fcntl(fd, F_GETFL, 0); - if (val < 0 || fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { - sprintf(str, GetString(STR_BLOCKING_NET_SOCKET_WARN), strerror(errno)); - WarningAlert(str); - goto open_error; - } -#endif - - // Get Ethernet address - if (net_if_type == NET_IF_ETHERTAP) { - pid_t p = getpid(); // If configured for multicast, ethertap requires that the lower 32 bit of the Ethernet address are our PID - ether_addr[0] = 0xfe; - ether_addr[1] = 0xfd; - ether_addr[2] = p >> 24; - ether_addr[3] = p >> 16; - ether_addr[4] = p >> 8; - ether_addr[5] = p; -#ifdef HAVE_SLIRP - } else if (net_if_type == NET_IF_SLIRP) { - ether_addr[0] = 0x52; - ether_addr[1] = 0x54; - ether_addr[2] = 0x00; - ether_addr[3] = 0x12; - ether_addr[4] = 0x34; - ether_addr[5] = 0x56; -#endif - } else - ioctl(fd, SIOCGIFADDR, ether_addr); - D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - - // Start packet reception thread - if (!start_thread()) - goto open_error; - - // Everything OK - return true; - -open_error: - stop_thread(); - - if (fd > 0) { - close(fd); - fd = -1; - } - if (slirp_input_fds[0] >= 0) { - close(slirp_input_fds[0]); - slirp_input_fds[0] = -1; - } - if (slirp_input_fds[1] >= 0) { - close(slirp_input_fds[1]); - slirp_input_fds[1] = -1; - } - if (slirp_output_fd >= 0) { - close(slirp_output_fd); - slirp_output_fd = -1; - } - return false; -} - - -/* - * Deinitialization - */ - -void ether_exit(void) -{ - // Stop reception threads - stop_thread(); - - // Shut down TUN/TAP interface - if (net_if_type == NET_IF_TUNTAP) - execute_network_script("down"); - - // Free TUN/TAP device name - if (net_if_name) - free(net_if_name); - - // Close sheep_net device - if (fd > 0) - close(fd); - - // Close slirp input buffer - if (slirp_input_fds[0] >= 0) - close(slirp_input_fds[0]); - if (slirp_input_fds[1] >= 0) - close(slirp_input_fds[1]); - - // Close slirp output buffer - if (slirp_output_fd > 0) - close(slirp_output_fd); - -#if STATISTICS - // Show statistics - printf("%ld messages put on write queue\n", num_wput); - printf("%ld error acks\n", num_error_acks); - printf("%ld packets transmitted (%ld raw, %ld normal)\n", num_tx_packets, num_tx_raw_packets, num_tx_normal_packets); - printf("%ld tx packets dropped because buffer full\n", num_tx_buffer_full); - printf("%ld packets received\n", num_rx_packets); - printf("%ld packets passed upstream (%ld Fast Path, %ld normal)\n", num_rx_fastpath + num_unitdata_ind, num_rx_fastpath, num_unitdata_ind); - printf("EtherIRQ called %ld times\n", num_ether_irq); - printf("%ld rx packets dropped due to low memory\n", num_rx_no_mem); - printf("%ld rx packets dropped because no stream found\n", num_rx_dropped); - printf("%ld rx packets dropped because stream not ready\n", num_rx_stream_not_ready); - printf("%ld rx packets dropped because no memory for unitdata_ind\n", num_rx_no_unitdata_mem); -#endif -} - - -/* - * Glue around low-level implementation - */ - -#ifdef SHEEPSHAVER -// Error codes -enum { - eMultiErr = -91, - eLenErr = -92, - lapProtErr = -94, - excessCollsns = -95 -}; - -// Initialize ethernet -void EtherInit(void) -{ - net_open = false; - - // Do nothing if the user disabled the network - if (PrefsFindBool("nonet")) - return; - - net_open = ether_init(); -} - -// Exit ethernet -void EtherExit(void) -{ - ether_exit(); - net_open = false; -} - -// Get ethernet hardware address -void AO_get_ethernet_address(uint32 arg) -{ - uint8 *addr = Mac2HostAddr(arg); - if (net_open) - OTCopy48BitAddress(ether_addr, addr); - else { - addr[0] = 0x12; - addr[1] = 0x34; - addr[2] = 0x56; - addr[3] = 0x78; - addr[4] = 0x9a; - addr[5] = 0xbc; - } - D(bug("AO_get_ethernet_address: got address %02x%02x%02x%02x%02x%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])); -} - -// Add multicast address -void AO_enable_multicast(uint32 addr) -{ - if (net_open) - ether_do_add_multicast(Mac2HostAddr(addr)); -} - -// Disable multicast address -void AO_disable_multicast(uint32 addr) -{ - if (net_open) - ether_do_del_multicast(Mac2HostAddr(addr)); -} - -// Transmit one packet -void AO_transmit_packet(uint32 mp) -{ - if (net_open) { - switch (ether_do_write(mp)) { - case noErr: - num_tx_packets++; - break; - case excessCollsns: - num_tx_buffer_full++; - break; - } - } -} - -// Copy packet data from message block to linear buffer -static inline int ether_arg_to_buffer(uint32 mp, uint8 *p) -{ - return ether_msgb_to_buffer(mp, p); -} - -// Ethernet interrupt -void EtherIRQ(void) -{ - D(bug("EtherIRQ\n")); - num_ether_irq++; - - OTEnterInterrupt(); - ether_do_interrupt(); - OTLeaveInterrupt(); - - // Acknowledge interrupt to reception thread - D(bug(" EtherIRQ done\n")); - sem_post(&int_ack); -} -#else -// Add multicast address -int16 ether_add_multicast(uint32 pb) -{ - return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr)); -} - -// Disable multicast address -int16 ether_del_multicast(uint32 pb) -{ - return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr)); -} - -// Transmit one packet -int16 ether_write(uint32 wds) -{ - return ether_do_write(wds); -} - -// Copy packet data from WDS to linear buffer -static inline int ether_arg_to_buffer(uint32 wds, uint8 *p) -{ - return ether_wds_to_buffer(wds, p); -} - -// Dispatch packet to protocol handler -static void ether_dispatch_packet(uint32 p, uint32 length) -{ - // Get packet type - uint16 type = ReadMacInt16(p + 12); - - // Look for protocol - uint16 search_type = (type <= 1500 ? 0 : type); - if (net_protocols.find(search_type) == net_protocols.end()) - return; - uint32 handler = net_protocols[search_type]; - - // No default handler - if (handler == 0) - return; - - // Copy header to RHA - Mac2Mac_memcpy(ether_data + ed_RHA, p, 14); - D(bug(" header %08x%04x %08x%04x %04x\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); - - // Call protocol handler - M68kRegisters r; - r.d[0] = type; // Packet type - r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket) - r.a[0] = p + 14; // Pointer to packet (Mac address, for ReadPacket) - r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA - r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines - D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); - Execute68k(handler, &r); -} - -// Ethernet interrupt -void EtherInterrupt(void) -{ - D(bug("EtherIRQ\n")); - ether_do_interrupt(); - - // Acknowledge interrupt to reception thread - D(bug(" EtherIRQ done\n")); - sem_post(&int_ack); -} -#endif - - -/* - * Reset - */ - -void ether_reset(void) -{ - net_protocols.clear(); -} - - -/* - * Add multicast address - */ - -static int16 ether_do_add_multicast(uint8 *addr) -{ - switch (net_if_type) { - case NET_IF_ETHERTAP: - case NET_IF_SHEEPNET: - if (ioctl(fd, SIOCADDMULTI, addr) < 0) { - D(bug("WARNING: Couldn't enable multicast address\n")); - if (net_if_type == NET_IF_ETHERTAP) { - return noErr; - } else { - return eMultiErr; - } - } - return noErr; - default: - return noErr; - } -} - - -/* - * Delete multicast address - */ - -static int16 ether_do_del_multicast(uint8 *addr) -{ - switch (net_if_type) { - case NET_IF_ETHERTAP: - case NET_IF_SHEEPNET: - if (ioctl(fd, SIOCDELMULTI, addr) < 0) { - D(bug("WARNING: Couldn't disable multicast address\n")); - return eMultiErr; - } - return noErr; - default: - return noErr; - } -} - - -/* - * Attach protocol handler - */ - -int16 ether_attach_ph(uint16 type, uint32 handler) -{ - if (net_protocols.find(type) != net_protocols.end()) - return lapProtErr; - net_protocols[type] = handler; - return noErr; -} - - -/* - * Detach protocol handler - */ - -int16 ether_detach_ph(uint16 type) -{ - if (net_protocols.erase(type) == 0) - return lapProtErr; - return noErr; -} - - -/* - * Transmit raw ethernet packet - */ - -static int16 ether_do_write(uint32 arg) -{ - // Copy packet to buffer - uint8 packet[1516], *p = packet; - int len = 0; -#if defined(__linux__) - if (net_if_type == NET_IF_ETHERTAP) { - *p++ = 0; // Linux ethertap discards the first 2 bytes - *p++ = 0; - len += 2; - } -#endif - len += ether_arg_to_buffer(arg, p); - -#if MONITOR - bug("Sending Ethernet packet:\n"); - for (int i=0; i 0) { - int len; - read(slirp_input_fd, &len, sizeof(len)); - uint8 packet[1516]; - assert(len <= sizeof(packet)); - read(slirp_input_fd, packet, len); - slirp_input(packet, len); - } - - // ... in the output queue - nfds = -1; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - int timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds); -#if ! USE_SLIRP_TIMEOUT - timeout = 10000; -#endif - tv.tv_sec = 0; - tv.tv_usec = timeout; - if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0) - slirp_select_poll(&rfds, &wfds, &xfds); - -#ifdef HAVE_PTHREAD_TESTCANCEL - // Explicit cancellation point if select() was not covered - // This seems to be the case on MacOS X 10.2 - pthread_testcancel(); -#endif - } - return NULL; -} -#else -int slirp_can_output(void) -{ - return 0; -} - -void slirp_output(const uint8 *packet, int len) -{ -} -#endif - - -/* - * Packet reception thread - */ - -static void *receive_func(void *arg) -{ - for (;;) { - - // Wait for packets to arrive -#if USE_POLL - struct pollfd pf = {fd, POLLIN, 0}; - int res = poll(&pf, 1, -1); -#else - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - // A NULL timeout could cause select() to block indefinitely, - // even if it is supposed to be a cancellation point [MacOS X] - struct timeval tv = { 0, 20000 }; - int res = select(fd + 1, &rfds, NULL, NULL, &tv); -#ifdef HAVE_PTHREAD_TESTCANCEL - pthread_testcancel(); -#endif - if (res == 0 || (res == -1 && errno == EINTR)) - continue; -#endif - if (res <= 0) - break; - - if (ether_driver_opened) { - // Trigger Ethernet interrupt - D(bug(" packet received, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - - // Wait for interrupt acknowledge by EtherInterrupt() - sem_wait(&int_ack); - } else - Delay_usec(20000); - } - return NULL; -} - - -/* - * Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers - */ - -void ether_do_interrupt(void) -{ - // Call protocol handler for received packets - EthernetPacket ether_packet; - uint32 packet = ether_packet.addr(); - ssize_t length; - for (;;) { - -#ifndef SHEEPSHAVER - if (udp_tunnel) { - - // Read packet from socket - struct sockaddr_in from; - socklen_t from_len = sizeof(from); - length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len); - if (length < 14) - break; - ether_udp_read(packet, length, &from); - - } else -#endif - { - - // Read packet from sheep_net device -#if defined(__linux__) - length = read(fd, Mac2HostAddr(packet), net_if_type == NET_IF_ETHERTAP ? 1516 : 1514); -#else - length = read(fd, Mac2HostAddr(packet), 1514); -#endif - if (length < 14) - break; - -#if MONITOR - bug("Receiving Ethernet packet:\n"); - for (int i=0; i 0) { - if (len > buf_size - 1) - len = buf_size - 1; - memcpy(buf, p, len); - buf[len] = '\0'; - } - *pp = p1; - return 0; -} - -// Set up port forwarding for slirp -static void slirp_add_redirs() -{ - int index = 0; - const char *str; - while ((str = PrefsFindString("redir", index++)) != NULL) { - slirp_add_redir(str); - } -} - -// Add a port forward/redirection for slirp -static int slirp_add_redir(const char *redir_str) -{ - // code adapted from qemu source - struct in_addr guest_addr = {0}; - int host_port, guest_port; - const char *p; - char buf[256]; - int is_udp; - char *end; - char str[256]; - - p = redir_str; - if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) { - goto fail_syntax; - } - if (!strcmp(buf, "tcp") || buf[0] == '\0') { - is_udp = 0; - } else if (!strcmp(buf, "udp")) { - is_udp = 1; - } else { - goto fail_syntax; - } - - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { - goto fail_syntax; - } - host_port = strtol(buf, &end, 0); - if (*end != '\0' || host_port < 1 || host_port > 65535) { - goto fail_syntax; - } - - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { - goto fail_syntax; - } - // 0.0.0.0 doesn't seem to work, so default to a client address - // if none is specified - if (buf[0] == '\0' ? - !inet_aton(CTL_LOCAL, &guest_addr) : - !inet_aton(buf, &guest_addr)) { - goto fail_syntax; - } - - guest_port = strtol(p, &end, 0); - if (*end != '\0' || guest_port < 1 || guest_port > 65535) { - goto fail_syntax; - } - - if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { - sprintf(str, "could not set up host forwarding rule '%s'", redir_str); - WarningAlert(str); - return -1; - } - return 0; - - fail_syntax: - sprintf(str, "invalid host forwarding rule '%s'", redir_str); - WarningAlert(str); - return -1; -} diff --git a/BasiliskII/src/Unix/ldscripts/freebsd-i386.ld b/BasiliskII/src/Unix/ldscripts/freebsd-i386.ld deleted file mode 100644 index a8d6745d..00000000 --- a/BasiliskII/src/Unix/ldscripts/freebsd-i386.ld +++ /dev/null @@ -1,175 +0,0 @@ -/* Script for -z combreloc: combine and sort reloc sections */ -OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd") -OUTPUT_ARCH(i386) -ENTRY(_start) -SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x78048000 + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.dyn : - { - *(.rel.init) - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.fini) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) - *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) - *(.rel.ctors) - *(.rel.dtors) - *(.rel.got) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : - { - KEEP (*(.init)) - } =0x90909090 - .plt : { *(.plt) } - .text : - { - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0x90909090 - .fini : - { - KEEP (*(.fini)) - } =0x90909090 - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .eh_frame_hdr : { *(.eh_frame_hdr) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000); - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { *(.preinit_array) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { *(.init_array) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { *(.fini_array) } - PROVIDE (__fini_array_end = .); - .data : - { - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .eh_frame : { KEEP (*(.eh_frame)) } - .gcc_except_table : { *(.gcc_except_table) } - .dynamic : { *(.dynamic) } - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin*.o(.ctors)) - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .got : { *(.got.plt) *(.got) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - . = ALIGN(32 / 8); - } - . = ALIGN(32 / 8); - _end = .; - PROVIDE (end = .); - . = DATA_SEGMENT_END (.); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} diff --git a/BasiliskII/src/Unix/ldscripts/linux-i386.ld b/BasiliskII/src/Unix/ldscripts/linux-i386.ld deleted file mode 100644 index ed3a0b5d..00000000 --- a/BasiliskII/src/Unix/ldscripts/linux-i386.ld +++ /dev/null @@ -1,137 +0,0 @@ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH(i386) -SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); -ENTRY(_start) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x78048000 + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.text : - { *(.rel.text) *(.rel.gnu.linkonce.t*) } - .rela.text : - { *(.rela.text) *(.rela.gnu.linkonce.t*) } - .rel.data : - { *(.rel.data) *(.rel.gnu.linkonce.d*) } - .rela.data : - { *(.rela.data) *(.rela.gnu.linkonce.d*) } - .rel.rodata : - { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } - .rela.rodata : - { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.init : { *(.rel.init) } - .rela.init : { *(.rela.init) } - .rel.fini : { *(.rel.fini) } - .rela.fini : { *(.rela.fini) } - .rel.bss : { *(.rel.bss) } - .rela.bss : { *(.rela.bss) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : { *(.init) } =0x47ff041f - .text : - { - *(.text) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t*) - } =0x47ff041f - _etext = .; - PROVIDE (etext = .); - .fini : { *(.fini) } =0x47ff041f - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { *(.preinit_array) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { *(.init_array) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { *(.fini_array) } - PROVIDE (__fini_array_end = .); - .rodata : { *(.rodata) *(.gnu.linkonce.r*) } - .rodata1 : { *(.rodata1) } - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(0x100000) + (. & (0x100000 - 1)); - .data : - { - *(.data) - *(.gnu.linkonce.d*) - CONSTRUCTORS - } - .data1 : { *(.data1) } - .ctors : - { - *(.ctors) - } - .dtors : - { - *(.dtors) - } - .plt : { *(.plt) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* These must appear regardless of . */ -} diff --git a/BasiliskII/src/Unix/ldscripts/linux-ppc.ld b/BasiliskII/src/Unix/ldscripts/linux-ppc.ld deleted file mode 100644 index b54743f5..00000000 --- a/BasiliskII/src/Unix/ldscripts/linux-ppc.ld +++ /dev/null @@ -1,219 +0,0 @@ -/* Script for -z combreloc: combine and sort reloc sections */ -OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") -OUTPUT_ARCH(powerpc:common) -ENTRY(_start) -SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/local/lib"); -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x78048000 + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.dyn : - { - *(.rel.init) - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.fini) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data.rel.ro*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) - *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) - *(.rel.ctors) - *(.rel.dtors) - *(.rel.got) - *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) - *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) - *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) - *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.got1) - *(.rela.got2) - *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) - *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) - *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) - *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : - { - KEEP (*(.init)) - } =0 - .text : - { - *(.text .stub .text.* .gnu.linkonce.t.*) - KEEP (*(.text.*personality*)) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0 - .fini : - { - KEEP (*(.fini)) - } =0 - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } - .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } - .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000); - /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } - /* Thread Local Storage sections */ - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { KEEP (*(.preinit_array)) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { KEEP (*(.init_array)) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { KEEP (*(.fini_array)) } - PROVIDE (__fini_array_end = .); - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin*.o(.ctors)) - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) } - .fixup : { *(.fixup) } - .got1 : { *(.got1) } - .got2 : { *(.got2) } - .dynamic : { *(.dynamic) } - . = DATA_SEGMENT_RELRO_END (0, .); - .data : - { - *(.data .data.* .gnu.linkonce.d.*) - KEEP (*(.gnu.linkonce.d.*personality*)) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - .got1 : { *(.got1) } - .got2 : { *(.got2) } - .got : { *(.got.plt) *(.got) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : - { - *(.sdata .sdata.* .gnu.linkonce.s.*) - } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - .sbss : - { - PROVIDE (__sbss_start = .); - PROVIDE (___sbss_start = .); - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - PROVIDE (__sbss_end = .); - PROVIDE (___sbss_end = .); - } - .plt : { *(.plt) } - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - . = ALIGN(32 / 8); - } - . = ALIGN(32 / 8); - _end = .; - PROVIDE (end = .); - . = DATA_SEGMENT_END (.); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /DISCARD/ : { *(.fixup) } -} diff --git a/BasiliskII/src/Unix/ldscripts/linux-x86_64.ld b/BasiliskII/src/Unix/ldscripts/linux-x86_64.ld deleted file mode 100644 index b824271a..00000000 --- a/BasiliskII/src/Unix/ldscripts/linux-x86_64.ld +++ /dev/null @@ -1,171 +0,0 @@ -/* Default linker script, for normal executables */ -OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") -OUTPUT_ARCH(i386:x86-64) -ENTRY(_start) -SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib64"); -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = 0x78048000 + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.init : { *(.rel.init) } - .rela.init : { *(.rela.init) } - .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } - .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } - .rel.fini : { *(.rel.fini) } - .rela.fini : { *(.rela.fini) } - .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } - .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } - .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } - .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } - .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } - .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } - .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } - .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } - .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : - { - KEEP (*(.init)) - } =0x90909090 - .plt : { *(.plt) } - .text : - { - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0x90909090 - .fini : - { - KEEP (*(.fini)) - } =0x90909090 - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000); - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(64 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { *(.preinit_array) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { *(.init_array) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { *(.fini_array) } - PROVIDE (__fini_array_end = .); - .data : - { - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) } - .dynamic : { *(.dynamic) } - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .got : { *(.got.plt) *(.got) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - . = ALIGN(64 / 8); - } - . = ALIGN(64 / 8); - _end = .; - PROVIDE (end = .); - . = DATA_SEGMENT_END (.); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 3505335e..644c215b 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -29,45 +29,14 @@ # include #endif -#ifndef USE_SDL_VIDEO -# include -#endif - #ifdef HAVE_PTHREADS # include #endif -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING # include #endif -#if !EMULATED_68K && defined(__NetBSD__) -# include -# include -# include -# include -struct sigstate { - int ss_flags; - struct frame ss_frame; - struct fpframe ss_fpstate; -}; -# define SS_FPSTATE 0x02 -# define SS_USERREGS 0x04 -#endif - -#ifdef ENABLE_GTK -# include -# include -# ifdef HAVE_GNOMEUI -# include -# endif -#endif - -#ifdef ENABLE_XF86_DGA -# include -# include -#endif - #include using std::string; @@ -88,13 +57,6 @@ using std::string; #include "sigsegv.h" #include "rpc.h" -#if USE_JIT -extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp -#endif - -#ifdef ENABLE_MON -# include "mon.h" -#endif #define DEBUG 0 #include "debug.h" @@ -102,23 +64,10 @@ extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_suppo // Constants const char ROM_FILE_NAME[] = "ROM"; -#if !EMULATED_68K -const int SIG_STACK_SIZE = SIGSTKSZ; // Size of signal stack -#endif + const int SCRATCH_MEM_SIZE = 0x10000; // Size of scratch memory area -#if !EMULATED_68K -// RAM and ROM pointers -uint32 RAMBaseMac; // RAM base (Mac address space) -uint8 *RAMBaseHost; // RAM base (host address space) -uint32 RAMSize; // Size of RAM -uint32 ROMBaseMac; // ROM base (Mac address space) -uint8 *ROMBaseHost; // ROM base (host address space) -uint32 ROMSize; // Size of ROM -#endif - - // CPU and FPU type, addressing mode int CPUType; bool CPUIs68060; @@ -127,20 +76,10 @@ bool TwentyFourBitAddressing; // Global variables -#ifndef USE_SDL_VIDEO -extern char *x_display_name; // X11 display name -extern Display *x_display; // X11 display handle -#ifdef X11_LOCK_TYPE -X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock -#endif -#endif static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes #ifdef HAVE_PTHREADS -#if !EMULATED_68K -static pthread_t emul_thread; // Handle of MacOS emulation thread (main thread) -#endif static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread @@ -162,14 +101,6 @@ static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to pro #endif -#if !EMULATED_68K -#define SIG_IRQ SIGUSR1 -static struct sigaction sigirq_sa; // Virtual 68k interrupt signal -static struct sigaction sigill_sa; // Illegal instruction -static void *sig_stack = NULL; // Stack for signal handlers -uint16 EmulatedSR; // Emulated bits of SR (supervisor bit and interrupt mask) -#endif - #if USE_SCRATCHMEM_SUBTERFUGE uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes #endif @@ -183,14 +114,6 @@ static timer_t timer; // 60Hz timer #endif #endif // !HAVE_PTHREADS -#ifdef ENABLE_MON -static struct sigaction sigint_sa; // sigaction for SIGINT handler -static void sigint_handler(...); -#endif - -#if REAL_ADDRESSING -static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped -#endif static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI static const char *gui_connection_path = NULL; // GUI connection identifier @@ -200,11 +123,6 @@ static const char *gui_connection_path = NULL; // GUI connection identifier static void *xpram_func(void *arg); static void *tick_func(void *arg); static void one_tick(...); -#if !EMULATED_68K -static void sigirq_handler(int sig, int code, struct sigcontext *scp); -static void sigill_handler(int sig, int code, struct sigcontext *scp); -extern "C" void EmulOpTrampoline(void); -#endif /* @@ -285,15 +203,9 @@ static void sigsegv_dump_state(sigsegv_info_t *sip) extern void m68k_dumpstate(uaecptr *nextpc); m68k_dumpstate(&nextpc); #endif -#if USE_JIT && JIT_DEBUG - extern void compiler_dumpstate(void); - compiler_dumpstate(); -#endif + VideoQuitFullScreen(); -#ifdef ENABLE_MON - const char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif + QuitEmulator(); } @@ -398,12 +310,6 @@ int main(int argc, char **argv) for (int i=1; i 1023*1024*1024) // Cap to 1023MB (APD crashes at 1GB) RAMSize = 1023*1024*1024; -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING RAMSize = RAMSize & -getpagesize(); // Round down to page boundary #endif // Initialize VM system vm_init(); -#if REAL_ADDRESSING - // Flag: RAM and ROM are contigously allocated from address 0 - bool memory_mapped_from_zero = false; - - // Make sure to map RAM & ROM at address 0 only on platforms that - // supports linker scripts to relocate the Basilisk II executable - // above 0x70000000 -#if HAVE_LINKER_SCRIPT - const bool can_map_all_memory = true; -#else - const bool can_map_all_memory = false; -#endif - - // Try to allocate all memory from 0x0000, if it is not known to crash - if (can_map_all_memory && (vm_acquire_mac_fixed(0, RAMSize + 0x100000) == 0)) { - D(bug("Could allocate RAM and ROM from 0x0000\n")); - memory_mapped_from_zero = true; - } - -#ifndef PAGEZERO_HACK - // Otherwise, just create the Low Memory area (0x0000..0x2000) - else if (vm_acquire_mac_fixed(0, 0x2000) == 0) { - D(bug("Could allocate the Low Memory globals\n")); - lm_area_mapped = true; - } - - // Exit on failure - else { - sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } -#endif -#endif /* REAL_ADDRESSING */ - // Create areas for Mac RAM and ROM -#if REAL_ADDRESSING - if (memory_mapped_from_zero) { - RAMBaseHost = (uint8 *)0; - ROMBaseHost = RAMBaseHost + RAMSize; - } - else -#endif { uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000); if (ram_rom_area == VM_MAP_FAILED) { @@ -615,10 +448,7 @@ int main(int argc, char **argv) RAMBaseMac = 0; ROMBaseMac = Host2MacAddr(ROMBaseHost); #endif -#if REAL_ADDRESSING - RAMBaseMac = Host2MacAddr(RAMBaseHost); - ROMBaseMac = Host2MacAddr(ROMBaseHost); -#endif + D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac)); D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac)); @@ -645,98 +475,11 @@ int main(int argc, char **argv) QuitEmulator(); } -#if !EMULATED_68K - // Get CPU model - int mib[2] = {CTL_HW, HW_MODEL}; - char *model; - size_t model_len; - sysctl(mib, 2, NULL, &model_len, NULL, 0); - model = (char *)malloc(model_len); - sysctl(mib, 2, model, &model_len, NULL, 0); - D(bug("Model: %s\n", model)); - - // Set CPU and FPU type - CPUIs68060 = false; - if (strstr(model, "020")) - CPUType = 2; - else if (strstr(model, "030")) - CPUType = 3; - else if (strstr(model, "040")) - CPUType = 4; - else if (strstr(model, "060")) { - CPUType = 4; - CPUIs68060 = true; - } else { - printf("WARNING: Cannot detect CPU type, assuming 68020\n"); - CPUType = 2; - } - FPUType = 1; // NetBSD has an FPU emulation, so the FPU ought to be available at all times - TwentyFourBitAddressing = false; -#endif - // Initialize everything if (!InitAll(vmdir)) QuitEmulator(); D(bug("Initialization complete\n")); -#if !EMULATED_68K - // (Virtual) supervisor mode, disable interrupts - EmulatedSR = 0x2700; - -#ifdef HAVE_PTHREADS - // Get handle of main thread - emul_thread = pthread_self(); -#endif - - // Create and install stack for signal handlers - sig_stack = malloc(SIG_STACK_SIZE); - D(bug("Signal stack at %p\n", sig_stack)); - if (sig_stack == NULL) { - ErrorAlert(STR_NOT_ENOUGH_MEMORY_ERR); - QuitEmulator(); - } - stack_t new_stack; - new_stack.ss_sp = sig_stack; - new_stack.ss_flags = 0; - new_stack.ss_size = SIG_STACK_SIZE; - if (sigaltstack(&new_stack, NULL) < 0) { - sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } - - // Install SIGILL handler for emulating privileged instructions and - // executing A-Trap and EMUL_OP opcodes - sigemptyset(&sigill_sa.sa_mask); // Block virtual 68k interrupts during SIGILL handling - sigaddset(&sigill_sa.sa_mask, SIG_IRQ); - sigaddset(&sigill_sa.sa_mask, SIGALRM); - sigill_sa.sa_handler = (void (*)(int))sigill_handler; - sigill_sa.sa_flags = SA_ONSTACK; - if (sigaction(SIGILL, &sigill_sa, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } - - // Install virtual 68k interrupt signal handler - sigemptyset(&sigirq_sa.sa_mask); - sigaddset(&sigirq_sa.sa_mask, SIGALRM); - sigirq_sa.sa_handler = (void (*)(int))sigirq_handler; - sigirq_sa.sa_flags = SA_ONSTACK | SA_RESTART; - if (sigaction(SIG_IRQ, &sigirq_sa, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_IRQ", strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } -#endif - -#ifdef ENABLE_MON - // Setup SIGINT handler to enter mon - sigemptyset(&sigint_sa.sa_mask); - sigint_sa.sa_handler = (void (*)(int))sigint_handler; - sigint_sa.sa_flags = 0; - sigaction(SIGINT, &sigint_sa, NULL); -#endif #ifndef USE_CPU_EMUL_SERVICES #if defined(HAVE_PTHREADS) @@ -786,9 +529,6 @@ int main(int argc, char **argv) // Start 60Hz timer sigemptyset(&timer_sa.sa_mask); // Block virtual 68k interrupts during SIGARLM handling -#if !EMULATED_68K - sigaddset(&timer_sa.sa_mask, SIG_IRQ); -#endif timer_sa.sa_handler = one_tick; timer_sa.sa_flags = SA_ONSTACK | SA_RESTART; if (sigaction(SIGALRM, &timer_sa, NULL) < 0) { @@ -887,12 +627,6 @@ void QuitEmulator(void) } #endif -#if REAL_ADDRESSING - // Delete Low Memory area - if (lm_area_mapped) - vm_release(0, 0x2000); -#endif - // Exit VM wrappers vm_exit(); @@ -902,12 +636,6 @@ void QuitEmulator(void) // Exit preferences PrefsExit(); - // Close X11 server connection -#ifndef USE_SDL_VIDEO - if (x_display) - XCloseDisplay(x_display); -#endif - // Notify GUI we are about to leave if (gui_connection) { if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) @@ -925,35 +653,10 @@ void QuitEmulator(void) void FlushCodeCache(void *start, uint32 size) { -#if USE_JIT - if (UseJIT) - flush_icache_range((uint8 *)start, size); -#endif -#if !EMULATED_68K && defined(__NetBSD__) - m68k_sync_icache(start, size); -#endif + } -/* - * SIGINT handler, enters mon - */ - -#ifdef ENABLE_MON -static void sigint_handler(...) -{ -#if EMULATED_68K - uaecptr nextpc; - extern void m68k_dumpstate(uaecptr *nextpc); - m68k_dumpstate(&nextpc); -#endif - VideoQuitFullScreen(); - const char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); - QuitEmulator(); -} -#endif - #ifdef HAVE_PTHREADS /* @@ -1089,22 +792,6 @@ void ClearInterruptFlag(uint32 flag) } #endif -#if !EMULATED_68K -void TriggerInterrupt(void) -{ -#if defined(HAVE_PTHREADS) - pthread_kill(emul_thread, SIG_IRQ); -#else - raise(SIG_IRQ); -#endif -} - -void TriggerNMI(void) -{ - // not yet supported -} -#endif - /* * XPRAM watchdog thread (saves XPRAM every minute) @@ -1200,354 +887,6 @@ static void *tick_func(void *arg) #endif -#if !EMULATED_68K -/* - * Virtual 68k interrupt handler - */ - -static void sigirq_handler(int sig, int code, struct sigcontext *scp) -{ - // Interrupts disabled? Then do nothing - if (EmulatedSR & 0x0700) - return; - - struct sigstate *state = (struct sigstate *)scp->sc_ap; - M68kRegisters *regs = (M68kRegisters *)&state->ss_frame; - - // Set up interrupt frame on stack - uint32 a7 = regs->a[7]; - a7 -= 2; - WriteMacInt16(a7, 0x64); - a7 -= 4; - WriteMacInt32(a7, scp->sc_pc); - a7 -= 2; - WriteMacInt16(a7, scp->sc_ps | EmulatedSR); - scp->sc_sp = regs->a[7] = a7; - - // Set interrupt level - EmulatedSR |= 0x2100; - - // Jump to MacOS interrupt handler on return - scp->sc_pc = ReadMacInt32(0x64); -} - - -/* - * SIGILL handler, for emulation of privileged instructions and executing - * A-Trap and EMUL_OP opcodes - */ - -static void sigill_handler(int sig, int code, struct sigcontext *scp) -{ - struct sigstate *state = (struct sigstate *)scp->sc_ap; - uint16 *pc = (uint16 *)scp->sc_pc; - uint16 opcode = *pc; - M68kRegisters *regs = (M68kRegisters *)&state->ss_frame; - -#define INC_PC(n) scp->sc_pc += (n) - -#define GET_SR (scp->sc_ps | EmulatedSR) - -#define STORE_SR(v) \ - scp->sc_ps = (v) & 0xff; \ - EmulatedSR = (v) & 0xe700; \ - if (((v) & 0x0700) == 0 && InterruptFlags) \ - TriggerInterrupt(); - -//printf("opcode %04x at %p, sr %04x, emul_sr %04x\n", opcode, pc, scp->sc_ps, EmulatedSR); - - if ((opcode & 0xf000) == 0xa000) { - - // A-Line instruction, set up A-Line trap frame on stack - uint32 a7 = regs->a[7]; - a7 -= 2; - WriteMacInt16(a7, 0x28); - a7 -= 4; - WriteMacInt32(a7, (uint32)pc); - a7 -= 2; - WriteMacInt16(a7, GET_SR); - scp->sc_sp = regs->a[7] = a7; - - // Jump to MacOS A-Line handler on return - scp->sc_pc = ReadMacInt32(0x28); - - } else if ((opcode & 0xff00) == 0x7100) { - - // Extended opcode, push registers on user stack - uint32 a7 = regs->a[7]; - a7 -= 4; - WriteMacInt32(a7, (uint32)pc); - a7 -= 2; - WriteMacInt16(a7, scp->sc_ps); - for (int i=7; i>=0; i--) { - a7 -= 4; - WriteMacInt32(a7, regs->a[i]); - } - for (int i=7; i>=0; i--) { - a7 -= 4; - WriteMacInt32(a7, regs->d[i]); - } - scp->sc_sp = regs->a[7] = a7; - - // Jump to EmulOp trampoline code on return - scp->sc_pc = (uint32)EmulOpTrampoline; - - } else switch (opcode) { // Emulate privileged instructions - - case 0x40e7: // move sr,-(sp) - regs->a[7] -= 2; - WriteMacInt16(regs->a[7], GET_SR); - scp->sc_sp = regs->a[7]; - INC_PC(2); - break; - - case 0x46df: { // move (sp)+,sr - uint16 sr = ReadMacInt16(regs->a[7]); - STORE_SR(sr); - regs->a[7] += 2; - scp->sc_sp = regs->a[7]; - INC_PC(2); - break; - } - - case 0x007c: { // ori #xxxx,sr - uint16 sr = GET_SR | pc[1]; - scp->sc_ps = sr & 0xff; // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR - EmulatedSR = sr & 0xe700; - INC_PC(4); - break; - } - - case 0x027c: { // andi #xxxx,sr - uint16 sr = GET_SR & pc[1]; - STORE_SR(sr); - INC_PC(4); - break; - } - - case 0x46fc: // move #xxxx,sr - STORE_SR(pc[1]); - INC_PC(4); - break; - - case 0x46ef: { // move (xxxx,sp),sr - uint16 sr = ReadMacInt16(regs->a[7] + (int32)(int16)pc[1]); - STORE_SR(sr); - INC_PC(4); - break; - } - - case 0x46d8: // move (a0)+,sr - case 0x46d9: { // move (a1)+,sr - uint16 sr = ReadMacInt16(regs->a[opcode & 7]); - STORE_SR(sr); - regs->a[opcode & 7] += 2; - INC_PC(2); - break; - } - - case 0x40f8: // move sr,xxxx.w - WriteMacInt16(pc[1], GET_SR); - INC_PC(4); - break; - - case 0x40d0: // move sr,(a0) - case 0x40d1: // move sr,(a1) - case 0x40d2: // move sr,(a2) - case 0x40d3: // move sr,(a3) - case 0x40d4: // move sr,(a4) - case 0x40d5: // move sr,(a5) - case 0x40d6: // move sr,(a6) - case 0x40d7: // move sr,(sp) - WriteMacInt16(regs->a[opcode & 7], GET_SR); - INC_PC(2); - break; - - case 0x40c0: // move sr,d0 - case 0x40c1: // move sr,d1 - case 0x40c2: // move sr,d2 - case 0x40c3: // move sr,d3 - case 0x40c4: // move sr,d4 - case 0x40c5: // move sr,d5 - case 0x40c6: // move sr,d6 - case 0x40c7: // move sr,d7 - regs->d[opcode & 7] = GET_SR; - INC_PC(2); - break; - - case 0x46c0: // move d0,sr - case 0x46c1: // move d1,sr - case 0x46c2: // move d2,sr - case 0x46c3: // move d3,sr - case 0x46c4: // move d4,sr - case 0x46c5: // move d5,sr - case 0x46c6: // move d6,sr - case 0x46c7: { // move d7,sr - uint16 sr = regs->d[opcode & 7]; - STORE_SR(sr); - INC_PC(2); - break; - } - - case 0xf327: // fsave -(sp) - regs->a[7] -= 4; - WriteMacInt32(regs->a[7], 0x41000000); // Idle frame - scp->sc_sp = regs->a[7]; - INC_PC(2); - break; - - case 0xf35f: // frestore (sp)+ - regs->a[7] += 4; - scp->sc_sp = regs->a[7]; - INC_PC(2); - break; - - case 0x4e73: { // rte - uint32 a7 = regs->a[7]; - uint16 sr = ReadMacInt16(a7); - a7 += 2; - scp->sc_ps = sr & 0xff; - EmulatedSR = sr & 0xe700; - scp->sc_pc = ReadMacInt32(a7); - a7 += 4; - uint16 format = ReadMacInt16(a7) >> 12; - a7 += 2; - static const int frame_adj[16] = { - 0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0 - }; - scp->sc_sp = regs->a[7] = a7 + frame_adj[format]; - break; - } - - case 0x4e7a: // movec cr,x - switch (pc[1]) { - case 0x0002: // movec cacr,d0 - regs->d[0] = 0x3111; - break; - case 0x1002: // movec cacr,d1 - regs->d[1] = 0x3111; - break; - case 0x0003: // movec tc,d0 - case 0x0004: // movec itt0,d0 - case 0x0005: // movec itt1,d0 - case 0x0006: // movec dtt0,d0 - case 0x0007: // movec dtt1,d0 - case 0x0806: // movec urp,d0 - case 0x0807: // movec srp,d0 - regs->d[0] = 0; - break; - case 0x1000: // movec sfc,d1 - case 0x1001: // movec dfc,d1 - case 0x1003: // movec tc,d1 - case 0x1801: // movec vbr,d1 - regs->d[1] = 0; - break; - case 0x8801: // movec vbr,a0 - regs->a[0] = 0; - break; - case 0x9801: // movec vbr,a1 - regs->a[1] = 0; - break; - default: - goto ill; - } - INC_PC(4); - break; - - case 0x4e7b: // movec x,cr - switch (pc[1]) { - case 0x1000: // movec d1,sfc - case 0x1001: // movec d1,dfc - case 0x0801: // movec d0,vbr - case 0x1801: // movec d1,vbr - break; - case 0x0002: // movec d0,cacr - case 0x1002: // movec d1,cacr - FlushCodeCache(NULL, 0); - break; - default: - goto ill; - } - INC_PC(4); - break; - - case 0xf478: // cpusha dc - case 0xf4f8: // cpusha dc/ic - FlushCodeCache(NULL, 0); - INC_PC(2); - break; - - default: -ill: printf("SIGILL num %d, code %d\n", sig, code); - printf(" context %p:\n", scp); - printf(" onstack %08x\n", scp->sc_onstack); - printf(" sp %08x\n", scp->sc_sp); - printf(" fp %08x\n", scp->sc_fp); - printf(" pc %08x\n", scp->sc_pc); - printf(" opcode %04x\n", opcode); - printf(" sr %08x\n", scp->sc_ps); - printf(" state %p:\n", state); - printf(" flags %d\n", state->ss_flags); - for (int i=0; i<8; i++) - printf(" d%d %08x\n", i, state->ss_frame.f_regs[i]); - for (int i=0; i<8; i++) - printf(" a%d %08x\n", i, state->ss_frame.f_regs[i+8]); - - VideoQuitFullScreen(); -#ifdef ENABLE_MON - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif - QuitEmulator(); - break; - } -} -#endif - - -/* - * Display alert - */ - -#ifdef ENABLE_GTK -static void dl_destroyed(void) -{ - gtk_main_quit(); -} - -static void dl_quit(GtkWidget *dialog) -{ - gtk_widget_destroy(dialog); -} - -void display_alert(int title_id, int prefix_id, int button_id, const char *text) -{ - char str[256]; - sprintf(str, GetString(prefix_id), text); - - GtkWidget *dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL); - - GtkWidget *label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - GtkWidget *button = gtk_button_new_with_label(GetString(button_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - gtk_widget_show(dialog); - - gtk_main(); -} -#endif - - /* * Display error alert */ @@ -1559,16 +898,7 @@ void ErrorAlert(const char *text) rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) return; } -#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) - if (PrefsFindBool("nogui") || x_display == NULL) { - printf(GetString(STR_SHELL_ERROR_PREFIX), text); - return; - } - VideoQuitFullScreen(); - display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text); -#else printf(GetString(STR_SHELL_ERROR_PREFIX), text); -#endif } @@ -1583,15 +913,7 @@ void WarningAlert(const char *text) rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) return; } -#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) - if (PrefsFindBool("nogui") || x_display == NULL) { - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return; - } - display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text); -#else printf(GetString(STR_SHELL_WARNING_PREFIX), text); -#endif } diff --git a/BasiliskII/src/Unix/prefs_editor_gtk.cpp b/BasiliskII/src/Unix/prefs_editor_gtk.cpp deleted file mode 100644 index 637e1e67..00000000 --- a/BasiliskII/src/Unix/prefs_editor_gtk.cpp +++ /dev/null @@ -1,1828 +0,0 @@ -/* - * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_GNOMEUI -#include -#endif - -#include "user_strings.h" -#include "version.h" -#include "cdrom.h" -#include "xpram.h" -#include "prefs.h" -#include "prefs_editor.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static GtkWidget *win; // Preferences window -static bool start_clicked = false; // Return value of PrefsEditor() function - - -// Prototypes -static void create_volumes_pane(GtkWidget *top); -static void create_scsi_pane(GtkWidget *top); -static void create_graphics_pane(GtkWidget *top); -static void create_input_pane(GtkWidget *top); -static void create_serial_pane(GtkWidget *top); -static void create_memory_pane(GtkWidget *top); -static void create_jit_pane(GtkWidget *top); -static void read_settings(void); - - -/* - * Utility functions - */ - -#if ! GLIB_CHECK_VERSION(2,0,0) -#define G_OBJECT(obj) GTK_OBJECT(obj) -#define g_object_get_data(obj, key) gtk_object_get_data((obj), (key)) -#define g_object_set_data(obj, key, data) gtk_object_set_data((obj), (key), (data)) -#endif - -struct opt_desc { - int label_id; - GtkSignalFunc func; -}; - -struct combo_desc { - int label_id; -}; - -struct file_req_assoc { - file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {} - GtkWidget *req; - GtkWidget *entry; -}; - -static void cb_browse_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (char *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - gtk_entry_set_text(GTK_ENTRY(assoc->entry), file); - gtk_widget_destroy(assoc->req); - delete assoc; -} - -static void cb_browse(GtkWidget *widget, void *user_data) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_BROWSE_TITLE)); - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(cb_browse_ok), new file_req_assoc(req, (GtkWidget *)user_data)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -static GtkWidget *make_browse_button(GtkWidget *entry) -{ - GtkWidget *button; - - button = gtk_button_new_with_label(GetString(STR_BROWSE_CTRL)); - gtk_widget_show(button); - gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)cb_browse, (void *)entry); - return button; -} - -static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func) -{ - GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id)); - gtk_widget_show(item); - gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL); - gtk_menu_append(GTK_MENU(menu), item); -} - -static GtkWidget *make_pane(GtkWidget *notebook, int title_id) -{ - GtkWidget *frame, *label, *box; - - frame = gtk_frame_new(NULL); - gtk_container_set_border_width(GTK_CONTAINER(frame), 4); - - box = gtk_vbox_new(FALSE, 4); - gtk_container_set_border_width(GTK_CONTAINER(box), 4); - gtk_container_add(GTK_CONTAINER(frame), box); - - gtk_widget_show_all(frame); - - label = gtk_label_new(GetString(title_id)); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); - return box; -} - -static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons) -{ - GtkWidget *bb, *button; - - bb = gtk_hbutton_box_new(); - gtk_widget_show(bb); - gtk_container_set_border_width(GTK_CONTAINER(bb), border); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE); - gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4); - gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0); - - while (buttons->label_id) { - button = gtk_button_new_with_label(GetString(buttons->label_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL); - gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0); - buttons++; - } - return bb; -} - -static GtkWidget *make_separator(GtkWidget *top) -{ - GtkWidget *sep = gtk_hseparator_new(); - gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0); - gtk_widget_show(sep); - return sep; -} - -static GtkWidget *make_table(GtkWidget *top, int x, int y) -{ - GtkWidget *table = gtk_table_new(x, y, FALSE); - gtk_widget_show(table); - gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0); - return table; -} - -static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active) -{ - GtkWidget *label, *opt, *menu; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - - while (options->label_id) { - add_menu_item(menu, options->label_id, options->func); - options++; - } - gtk_menu_set_active(GTK_MENU(menu), active); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - return menu; -} - -static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist) -{ - GtkWidget *label, *combo; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - return combo; -} - -static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options) -{ - GList *glist = NULL; - while (options->label_id) { - glist = g_list_append(glist, (void *)GetString(options->label_id)); - options++; - } - - return table_make_combobox(table, row, label_id, default_value, glist); -} - -static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false) -{ - GtkWidget *box, *label, *entry, *button; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - const char *str = PrefsFindString(prefs_item); - if (str == NULL) - str = ""; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_widget_show(entry); - gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); - - button = make_browse_button(entry); - gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(entry), "chooser_button", button); - return entry; -} - -static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active) -{ - GtkWidget *box, *label, *opt, *menu; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - - while (options->label_id) { - add_menu_item(menu, options->label_id, options->func); - options++; - } - gtk_menu_set_active(GTK_MENU(menu), active); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0); - return menu; -} - -static GtkWidget *make_file_entry(GtkWidget *top, int label_id, const char *prefs_item, bool only_dirs = false) -{ - GtkWidget *box, *label, *entry; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - const char *str = PrefsFindString(prefs_item); - if (str == NULL) - str = ""; - -#ifdef HAVE_GNOMEUI - entry = gnome_file_entry_new(NULL, GetString(label_id)); - if (only_dirs) - gnome_file_entry_set_directory(GNOME_FILE_ENTRY(entry), true); - gtk_entry_set_text(GTK_ENTRY(gnome_file_entry_gtk_entry(GNOME_FILE_ENTRY(entry))), str); -#else - entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(entry), str); -#endif - gtk_widget_show(entry); - gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); - return entry; -} - -static const gchar *get_file_entry_path(GtkWidget *entry) -{ -#ifdef HAVE_GNOMEUI - return gnome_file_entry_get_full_path(GNOME_FILE_ENTRY(entry), false); -#else - return gtk_entry_get_text(GTK_ENTRY(entry)); -#endif -} - -static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func) -{ - GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id)); - gtk_widget_show(button); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item)); - gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button); - gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0); - return button; -} - -static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *prefs_item, const combo_desc *options) -{ - GtkWidget *box, *label, *combo; - char str[32]; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - GList *glist = NULL; - while (options->label_id) { - glist = g_list_append(glist, (void *)GetString(options->label_id)); - options++; - } - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - - sprintf(str, "%d", PrefsFindInt32(prefs_item)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0); - - return combo; -} - - -/* - * Show preferences editor - * Returns true when user clicked on "Start", false otherwise - */ - -// Window closed -static gint window_closed(void) -{ - return FALSE; -} - -// Window destroyed -static void window_destroyed(void) -{ - gtk_main_quit(); -} - -// "Start" button clicked -static void cb_start(...) -{ - start_clicked = true; - read_settings(); - SavePrefs(); - gtk_widget_destroy(win); -} - -// "Quit" button clicked -static void cb_quit(...) -{ - start_clicked = false; - gtk_widget_destroy(win); -} - -// "OK" button of "About" dialog clicked -static void dl_quit(GtkWidget *dialog) -{ - gtk_widget_destroy(dialog); -} - -// "About" selected -static void mn_about(...) -{ - GtkWidget *dialog; - -#ifdef HAVE_GNOMEUI - - char version[32]; - sprintf(version, "Version %d.%d", VERSION_MAJOR, VERSION_MINOR); - const char *authors[] = { - "Christian Bauer", - "Orlando Bassotto", - "Gwenolé Beauchesne", - "Marc Chabanas", - "Marc Hellwig", - "Biill Huey", - "Brian J. Johnson", - "Jürgen Lachmann", - "Samuel Lander", - "David Lawrence", - "Lauri Pesonen", - "Bernd Schmidt", - "and others", - NULL - }; - dialog = gnome_about_new( - "Basilisk II", - version, - "Copyright (C) 1997-2008 Christian Bauer", - authors, - "Basilisk II comes with ABSOLUTELY NO WARRANTY." - "This is free software, and you are welcome to redistribute it" - "under the terms of the GNU General Public License.", - NULL - ); - gnome_dialog_set_parent(GNOME_DIALOG(dialog), GTK_WINDOW(win)); - -#else - - GtkWidget *label, *button; - - char str[512]; - sprintf(str, - "Basilisk II\nVersion %d.%d\n\n" - "Copyright (C) 1997-2008 Christian Bauer et al.\n" - "E-mail: Christian.Bauer@uni-mainz.de\n" - "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n" - "Basilisk II comes with ABSOLUTELY NO\n" - "WARRANTY. This is free software, and\n" - "you are welcome to redistribute it\n" - "under the terms of the GNU General\n" - "Public License.\n", - VERSION_MAJOR, VERSION_MINOR - ); - - dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - - label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - button = gtk_button_new_with_label(GetString(STR_OK_BUTTON)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - -#endif - - gtk_widget_show(dialog); -} - -// "Zap PRAM" selected -static void mn_zap_pram(...) -{ - ZapPRAM(); -} - -// Menu item descriptions -static GtkItemFactoryEntry menu_items[] = { - {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "S", GTK_SIGNAL_FUNC(cb_start), 0, NULL}, - {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(mn_zap_pram), 0, NULL}, - {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL}, - {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL} -}; - -bool PrefsEditor(void) -{ - // Create window - win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE)); - gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL); - gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL); - - // Create window contents - GtkWidget *box = gtk_vbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_container_add(GTK_CONTAINER(win), box); - - GtkAccelGroup *accel_group = gtk_accel_group_new(); - GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "
", accel_group); - gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL); -#if GTK_CHECK_VERSION(1,3,15) - gtk_window_add_accel_group(GTK_WINDOW(win), accel_group); -#else - gtk_accel_group_attach(accel_group, GTK_OBJECT(win)); -#endif - GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "
"); - gtk_widget_show(menu_bar); - gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0); - - GtkWidget *notebook = gtk_notebook_new(); - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); - gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE); - gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0); - gtk_widget_realize(notebook); - - create_volumes_pane(notebook); - create_scsi_pane(notebook); - create_graphics_pane(notebook); - create_input_pane(notebook); - create_serial_pane(notebook); - create_memory_pane(notebook); - create_jit_pane(notebook); - gtk_widget_show(notebook); - - static const opt_desc buttons[] = { - {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)}, - {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)}, - {0, NULL} - }; - make_button_box(box, 4, buttons); - - // Show window and enter main loop - gtk_widget_show(win); - gtk_main(); - return start_clicked; -} - - -/* - * "Volumes" pane - */ - -static GtkWidget *volume_list, *w_extfs; -static int selected_volume; - -// Volume in list selected -static void cl_selected(GtkWidget *list, int row, int column) -{ - selected_volume = row; -} - -// Volume selected for addition -static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - gtk_clist_append(GTK_CLIST(volume_list), &file); - gtk_widget_destroy(assoc->req); - delete assoc; -} - -// Volume selected for creation -static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - - const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry)); - int size = atoi(str); - - char cmd[1024]; - sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size); - int ret = system(cmd); - if (ret == 0) - gtk_clist_append(GTK_CLIST(volume_list), &file); - gtk_widget_destroy(GTK_WIDGET(assoc->req)); - delete assoc; -} - -// "Add Volume" button clicked -static void cb_add_volume(...) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE)); - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -// "Create Hardfile" button clicked -static void cb_create_volume(...) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE)); - - GtkWidget *box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL)); - gtk_widget_show(label); - GtkWidget *entry = gtk_entry_new(); - gtk_widget_show(entry); - char str[32]; - sprintf(str, "%d", 40); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0); - - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -// "Remove Volume" button clicked -static void cb_remove_volume(...) -{ - gtk_clist_remove(GTK_CLIST(volume_list), selected_volume); -} - -// "Boot From" selected -static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);} -static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);} - -// "No CD-ROM Driver" button toggled -static void tb_nocdrom(GtkWidget *widget) -{ - PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Read settings from widgets and set preferences -static void read_volumes_settings(void) -{ - while (PrefsFindString("disk")) - PrefsRemoveItem("disk"); - - for (int i=0; irows; i++) { - char *str; - gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str); - PrefsAddString("disk", str); - } - - PrefsReplaceString("extfs", get_file_entry_path(w_extfs)); -} - -// Create "Volumes" pane -static void create_volumes_pane(GtkWidget *top) -{ - GtkWidget *box, *scroll; - - box = make_pane(top, STR_VOLUMES_PANE_TITLE); - - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_show(scroll); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - volume_list = gtk_clist_new(1); - gtk_widget_show(volume_list); - gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE); - gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE); - gtk_clist_set_reorderable(GTK_CLIST(volume_list), true); - gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL); - char *str; - int32 index = 0; - while ((str = const_cast(PrefsFindString("disk", index++))) != NULL) - gtk_clist_append(GTK_CLIST(volume_list), &str); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list); - gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0); - selected_volume = 0; - - static const opt_desc buttons[] = { - {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)}, - {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)}, - {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)}, - {0, NULL}, - }; - make_button_box(box, 0, buttons); - make_separator(box); - - w_extfs = make_file_entry(box, STR_EXTFS_CTRL, "extfs", true); - - static const opt_desc options[] = { - {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)}, - {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)}, - {0, NULL} - }; - int bootdriver = PrefsFindInt32("bootdriver"), active = 0; - switch (bootdriver) { - case 0: active = 0; break; - case CDROMRefNum: active = 1; break; - } - make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active); - - make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom)); -} - - -/* - * "JIT Compiler" pane - */ - -static GtkWidget *w_jit_fpu; -static GtkWidget *w_jit_cache_size; -static GtkWidget *w_jit_lazy_flush; -static GtkWidget *w_jit_follow_const_jumps; - -// Are we running a JIT capable CPU? -static bool is_jit_capable(void) -{ -#if USE_JIT && (defined __i386__ || defined __x86_64__) - return true; -#elif defined __APPLE__ && defined __MACH__ - // XXX run-time detect so that we can use a PPC GUI prefs editor - static char cpu[10]; - if (cpu[0] == 0) { - FILE *fp = popen("uname -p", "r"); - if (fp == NULL) - return false; - fgets(cpu, sizeof(cpu) - 1, fp); - fclose(fp); - } - if (cpu[0] == 'i' && cpu[2] == '8' && cpu[3] == '6') // XXX assuming i?86 - return true; -#endif - return false; -} - -// Set sensitivity of widgets -static void set_jit_sensitive(void) -{ - const bool jit_enabled = PrefsFindBool("jit"); - gtk_widget_set_sensitive(w_jit_fpu, jit_enabled); - gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled); - gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled); - gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled); -} - -// "Use JIT Compiler" button toggled -static void tb_jit(GtkWidget *widget) -{ - PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active); - set_jit_sensitive(); -} - -// "Compile FPU Instructions" button toggled -static void tb_jit_fpu(GtkWidget *widget) -{ - PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active); -} - -// "Lazy translation cache invalidation" button toggled -static void tb_jit_lazy_flush(GtkWidget *widget) -{ - PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active); -} - -// "Translate through constant jumps (inline blocks)" button toggled -static void tb_jit_follow_const_jumps(GtkWidget *widget) -{ - PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Read settings from widgets and set preferences -static void read_jit_settings(void) -{ - bool jit_enabled = is_jit_capable() && PrefsFindBool("jit"); - if (jit_enabled) { - const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry)); - PrefsReplaceInt32("jitcachesize", atoi(str)); - } -} - -// Create "JIT Compiler" pane -static void create_jit_pane(GtkWidget *top) -{ - if (!is_jit_capable()) - return; - - GtkWidget *box; - - box = make_pane(top, STR_JIT_PANE_TITLE); - make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit)); - - w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu)); - - // Translation cache size - static const combo_desc options[] = { - STR_JIT_CACHE_SIZE_2MB_LAB, - STR_JIT_CACHE_SIZE_4MB_LAB, - STR_JIT_CACHE_SIZE_8MB_LAB, - STR_JIT_CACHE_SIZE_16MB_LAB, - 0 - }; - w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options); - - // Lazy translation cache invalidation - w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush)); - - // Follow constant jumps (inline basic blocks) - w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps)); - - set_jit_sensitive(); -} - -/* - * "SCSI" pane - */ - -static GtkWidget *w_scsi[7]; - -// Read settings from widgets and set preferences -static void read_scsi_settings(void) -{ - for (int id=0; id<7; id++) { - char prefs_name[32]; - sprintf(prefs_name, "scsi%d", id); - const char *str = get_file_entry_path(w_scsi[id]); - if (str && strlen(str)) - PrefsReplaceString(prefs_name, str); - else - PrefsRemoveItem(prefs_name); - } -} - -// Create "SCSI" pane -static void create_scsi_pane(GtkWidget *top) -{ - GtkWidget *box; - - box = make_pane(top, STR_SCSI_PANE_TITLE); - - for (int id=0; id<7; id++) { - char prefs_name[32]; - sprintf(prefs_name, "scsi%d", id); - w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name); - } -} - - -/* - * "Graphics/Sound" pane - */ - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_SCREEN -}; - -static GtkWidget *w_frameskip, *w_display_x, *w_display_y; -static GtkWidget *l_frameskip, *l_display_x, *l_display_y; -static int display_type; -static int dis_width, dis_height; - -#ifdef ENABLE_FBDEV_DGA -static GtkWidget *w_fbdev_name, *w_fbdevice_file; -static GtkWidget *l_fbdev_name, *l_fbdevice_file; -static char fbdev_name[256]; -#endif - -static GtkWidget *w_dspdevice_file, *w_mixerdevice_file; - -// Hide/show graphics widgets -static void hide_show_graphics_widgets(void) -{ - switch (display_type) { - case DISPLAY_WINDOW: - gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip); -#ifdef ENABLE_FBDEV_DGA - gtk_widget_show(w_display_x); gtk_widget_show(l_display_x); - gtk_widget_show(w_display_y); gtk_widget_show(l_display_y); - gtk_widget_hide(w_fbdev_name); gtk_widget_hide(l_fbdev_name); -#endif - break; - case DISPLAY_SCREEN: - gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip); -#ifdef ENABLE_FBDEV_DGA - gtk_widget_hide(w_display_x); gtk_widget_hide(l_display_x); - gtk_widget_hide(w_display_y); gtk_widget_hide(l_display_y); - gtk_widget_show(w_fbdev_name); gtk_widget_show(l_fbdev_name); -#endif - break; - } -} - -// "Window" video type selected -static void mn_window(...) -{ - display_type = DISPLAY_WINDOW; - hide_show_graphics_widgets(); -} - -// "Fullscreen" video type selected -static void mn_fullscreen(...) -{ - display_type = DISPLAY_SCREEN; - hide_show_graphics_widgets(); -} - -// "5 Hz".."60Hz" selected -static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);} -static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);} -static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);} -static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);} -static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);} -static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);} -static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);} - -// Set sensitivity of widgets -static void set_graphics_sensitive(void) -{ - const bool sound_enabled = !PrefsFindBool("nosound"); - gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled); - gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled); -} - -// "Disable Sound Output" button toggled -static void tb_nosound(GtkWidget *widget) -{ - PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active); - set_graphics_sensitive(); -} - -// Read graphics preferences -static void parse_graphics_prefs(void) -{ - display_type = DISPLAY_WINDOW; - dis_width = 512; - dis_height = 384; -#ifdef ENABLE_FBDEV_DGA - fbdev_name[0] = 0; -#endif - - const char *str = PrefsFindString("screen"); - if (str) { - if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2) - display_type = DISPLAY_WINDOW; -#ifdef ENABLE_FBDEV_DGA - else if (sscanf(str, "dga/%255s", fbdev_name) == 1) -#else - else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2) -#endif - display_type = DISPLAY_SCREEN; - } -} - -// Read settings from widgets and set preferences -static void read_graphics_settings(void) -{ - const char *str; - - str = gtk_entry_get_text(GTK_ENTRY(w_display_x)); - dis_width = atoi(str); - - str = gtk_entry_get_text(GTK_ENTRY(w_display_y)); - dis_height = atoi(str); - - char pref[256]; - switch (display_type) { - case DISPLAY_WINDOW: - sprintf(pref, "win/%d/%d", dis_width, dis_height); - break; - case DISPLAY_SCREEN: -#ifdef ENABLE_FBDEV_DGA - str = gtk_entry_get_text(GTK_ENTRY(w_fbdev_name)); - sprintf(pref, "dga/%s", str); -#else - sprintf(pref, "dga/%d/%d", dis_width, dis_height); -#endif - break; - default: - PrefsRemoveItem("screen"); - return; - } - PrefsReplaceString("screen", pref); - -#ifdef ENABLE_FBDEV_DGA - str = get_file_entry_path(w_fbdevice_file); - if (str && strlen(str)) - PrefsReplaceString("fbdevicefile", str); - else - PrefsRemoveItem("fbdevicefile"); -#endif - PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file)); - PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file)); -} - -// Create "Graphics/Sound" pane -static void create_graphics_pane(GtkWidget *top) -{ - GtkWidget *box, *table, *label, *opt, *menu, *combo; - char str[32]; - - parse_graphics_prefs(); - - box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE); - table = make_table(box, 2, 5); - - label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window)); - add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen)); - switch (display_type) { - case DISPLAY_WINDOW: - gtk_menu_set_active(GTK_MENU(menu), 0); - break; - case DISPLAY_SCREEN: - gtk_menu_set_active(GTK_MENU(menu), 1); - break; - } - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - - l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL)); - gtk_widget_show(l_frameskip); - gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - w_frameskip = gtk_option_menu_new(); - gtk_widget_show(w_frameskip); - menu = gtk_menu_new(); - add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz)); - add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz)); - add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz)); - add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz)); - add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz)); - add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz)); - add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic)); - int frameskip = PrefsFindInt32("frameskip"); - int item = -1; - switch (frameskip) { - case 12: item = 0; break; - case 8: item = 1; break; - case 6: item = 2; break; - case 4: item = 3; break; - case 2: item = 4; break; - case 1: item = 5; break; - case 0: item = 6; break; - } - if (item >= 0) - gtk_menu_set_active(GTK_MENU(menu), item); - gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu); - gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - - l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL)); - gtk_widget_show(l_display_x); - gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - GList *glist1 = NULL; - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB)); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1); - if (dis_width) - sprintf(str, "%d", dis_width); - else - strcpy(str, GetString(STR_SIZE_MAX_LAB)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - w_display_x = GTK_COMBO(combo)->entry; - - l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL)); - gtk_widget_show(l_display_y); - gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - GList *glist2 = NULL; - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB)); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2); - if (dis_height) - sprintf(str, "%d", dis_height); - else - strcpy(str, GetString(STR_SIZE_MAX_LAB)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - w_display_y = GTK_COMBO(combo)->entry; - -#ifdef ENABLE_FBDEV_DGA - l_fbdev_name = gtk_label_new(GetString(STR_FBDEV_NAME_CTRL)); - gtk_widget_show(l_fbdev_name); - gtk_table_attach(GTK_TABLE(table), l_fbdev_name, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - w_fbdev_name = gtk_entry_new(); - gtk_widget_show(w_fbdev_name); - gtk_entry_set_text(GTK_ENTRY(w_fbdev_name), fbdev_name); - gtk_table_attach(GTK_TABLE(table), w_fbdev_name, 1, 2, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - w_fbdevice_file = make_file_entry(box, STR_FBDEVICE_FILE_CTRL, "fbdevicefile"); -#endif - - make_separator(box); - make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound)); - w_dspdevice_file = make_file_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp"); - w_mixerdevice_file = make_file_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer"); - - set_graphics_sensitive(); - - hide_show_graphics_widgets(); -} - - -/* - * "Input" pane - */ - -static GtkWidget *w_keycode_file; -static GtkWidget *w_mouse_wheel_lines; - -// Set sensitivity of widgets -static void set_input_sensitive(void) -{ - const bool use_keycodes = PrefsFindBool("keycodes"); - gtk_widget_set_sensitive(w_keycode_file, use_keycodes); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes); - gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1); -} - -// "Use Raw Keycodes" button toggled -static void tb_keycodes(GtkWidget *widget) -{ - PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active); - set_input_sensitive(); -} - -// "Mouse Wheel Mode" selected -static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();} -static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();} - -// Read settings from widgets and set preferences -static void read_input_settings(void) -{ - const char *str = get_file_entry_path(w_keycode_file); - if (str && strlen(str)) - PrefsReplaceString("keycodefile", str); - else - PrefsRemoveItem("keycodefile"); - - PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines))); -} - -// Create "Input" pane -static void create_input_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *label, *button; - GtkObject *adj; - - box = make_pane(top, STR_INPUT_PANE_TITLE); - - make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes)); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_KEYCODES_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - const char *str = PrefsFindString("keycodefile"); - if (str == NULL) - str = ""; - - w_keycode_file = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str); - gtk_widget_show(w_keycode_file); - gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0); - - button = make_browse_button(w_keycode_file); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button); - - make_separator(box); - - static const opt_desc options[] = { - {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)}, - {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)}, - {0, NULL} - }; - int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0; - switch (wheelmode) { - case 0: active = 0; break; - case 1: active = 1; break; - } - make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0); - w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0); - gtk_widget_show(w_mouse_wheel_lines); - gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0); - - set_input_sensitive(); -} - - -/* - * "Serial/Network" pane - */ - -static GtkWidget *w_seriala, *w_serialb, *w_ether, *w_udp_port; - -// Set sensitivity of widgets -static void set_serial_sensitive(void) -{ -#if SUPPORTS_UDP_TUNNEL - gtk_widget_set_sensitive(w_ether, !PrefsFindBool("udptunnel")); - gtk_widget_set_sensitive(w_udp_port, PrefsFindBool("udptunnel")); -#endif -} - -// "Tunnel AppleTalk over IP" button toggled -static void tb_udptunnel(GtkWidget *widget) -{ - PrefsReplaceBool("udptunnel", GTK_TOGGLE_BUTTON(widget)->active); - set_serial_sensitive(); -} - -// Read settings from widgets and set preferences -static void read_serial_settings(void) -{ - const char *str; - - str = gtk_entry_get_text(GTK_ENTRY(w_seriala)); - PrefsReplaceString("seriala", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_serialb)); - PrefsReplaceString("serialb", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_ether)); - if (str && strlen(str)) - PrefsReplaceString("ether", str); - else - PrefsRemoveItem("ether"); - -#if SUPPORTS_UDP_TUNNEL - PrefsReplaceInt32("udpport", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_udp_port))); -#endif -} - -// Add names of serial devices -static gint gl_str_cmp(gconstpointer a, gconstpointer b) -{ - return strcmp((char *)a, (char *)b); -} - -static GList *add_serial_names(void) -{ - GList *glist = NULL; - - // Search /dev for ttyS* and lp* - DIR *d = opendir("/dev"); - if (d) { - struct dirent *de; - while ((de = readdir(d)) != NULL) { -#if defined(__linux__) - if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) { -#elif defined(__FreeBSD__) - if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) { -#elif defined(__NetBSD__) - if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) { -#elif defined(sgi) - if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) { -#else - if (false) { -#endif - char *str = new char[64]; - sprintf(str, "/dev/%s", de->d_name); - glist = g_list_append(glist, str); - } - } - closedir(d); - } - if (glist) - g_list_sort(glist, gl_str_cmp); - else - glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB)); - return glist; -} - -// Add names of ethernet interfaces -static GList *add_ether_names(void) -{ - GList *glist = NULL; - - // Get list of all Ethernet interfaces - int s = socket(PF_INET, SOCK_DGRAM, 0); - if (s >= 0) { - char inbuf[8192]; - struct ifconf ifc; - ifc.ifc_len = sizeof(inbuf); - ifc.ifc_buf = inbuf; - if (ioctl(s, SIOCGIFCONF, &ifc) == 0) { - struct ifreq req, *ifr = ifc.ifc_req; - for (int i=0; iifr_name, 63); - glist = g_list_append(glist, str); - } - } - } - close(s); - } -#ifdef HAVE_SLIRP - static char s_slirp[] = "slirp"; - glist = g_list_append(glist, s_slirp); -#endif - if (glist) - g_list_sort(glist, gl_str_cmp); - else - glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB)); - return glist; -} - -// Create "Serial/Network" pane -static void create_serial_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *table, *label, *combo, *sep; - GtkObject *adj; - - box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE); - table = make_table(box, 2, 4); - - label = gtk_label_new(GetString(STR_SERIALA_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - GList *glist = add_serial_names(); - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - const char *str = PrefsFindString("seriala"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_seriala = GTK_COMBO(combo)->entry; - - label = gtk_label_new(GetString(STR_SERIALB_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - str = PrefsFindString("serialb"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_serialb = GTK_COMBO(combo)->entry; - - sep = gtk_hseparator_new(); - gtk_widget_show(sep); - gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - glist = add_ether_names(); - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - str = PrefsFindString("ether"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_ether = GTK_COMBO(combo)->entry; - -#if SUPPORTS_UDP_TUNNEL - make_checkbox(box, STR_UDPTUNNEL_CTRL, "udptunnel", GTK_SIGNAL_FUNC(tb_udptunnel)); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_UDPPORT_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - adj = gtk_adjustment_new(PrefsFindInt32("udpport"), 1, 65535, 1, 5, 0); - w_udp_port = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0); - gtk_widget_show(w_udp_port); - gtk_box_pack_start(GTK_BOX(hbox), w_udp_port, FALSE, FALSE, 0); -#endif - - set_serial_sensitive(); -} - - -/* - * "Memory/Misc" pane - */ - -static GtkWidget *w_ramsize; -static GtkWidget *w_rom_file; - -// Don't use CPU when idle? -static void tb_idlewait(GtkWidget *widget) -{ - PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active); -} - -// "Ignore SEGV" button toggled -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION -static void tb_ignoresegv(GtkWidget *widget) -{ - PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// Model ID selected -static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);} -static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);} - -// CPU/FPU type -static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);} -static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);} -static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);} -static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);} -static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);} - -// Read settings from widgets and set preferences -static void read_memory_settings(void) -{ - const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry)); - PrefsReplaceInt32("ramsize", atoi(str) << 20); - - str = get_file_entry_path(w_rom_file); - if (str && strlen(str)) - PrefsReplaceString("rom", str); - else - PrefsRemoveItem("rom"); - -} - -// Create "Memory/Misc" pane -static void create_memory_pane(GtkWidget *top) -{ - GtkWidget *box, *table; - - box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE); - table = make_table(box, 2, 5); - - static const combo_desc options[] = { - STR_RAMSIZE_2MB_LAB, - STR_RAMSIZE_4MB_LAB, - STR_RAMSIZE_8MB_LAB, - STR_RAMSIZE_16MB_LAB, - STR_RAMSIZE_32MB_LAB, - STR_RAMSIZE_64MB_LAB, - STR_RAMSIZE_128MB_LAB, - STR_RAMSIZE_256MB_LAB, - STR_RAMSIZE_512MB_LAB, - STR_RAMSIZE_1024MB_LAB, - 0 - }; - char default_ramsize[10]; - sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20); - w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options); - - static const opt_desc model_options[] = { - {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)}, - {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)}, - {0, NULL} - }; - int modelid = PrefsFindInt32("modelid"), active = 0; - switch (modelid) { - case 5: active = 0; break; - case 14: active = 1; break; - } - table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active); - -#if EMULATED_68K - static const opt_desc cpu_options[] = { - {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)}, - {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)}, - {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)}, - {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)}, - {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)}, - {0, NULL} - }; - int cpu = PrefsFindInt32("cpu"); - bool fpu = PrefsFindBool("fpu"); - active = 0; - switch (cpu) { - case 2: active = fpu ? 1 : 0; break; - case 3: active = fpu ? 3 : 2; break; - case 4: active = 4; - } - table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active); -#endif - - w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom"); - - make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait)); -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv)); -#endif -} - - -/* - * Read settings from widgets and set preferences - */ - -static void read_settings(void) -{ - read_volumes_settings(); - read_scsi_settings(); - read_graphics_settings(); - read_input_settings(); - read_serial_settings(); - read_memory_settings(); - read_jit_settings(); -} - - -#ifdef STANDALONE_GUI -#include -#include -#include "rpc.h" - -/* - * Fake unused data and functions - */ - -uint8 XPRAM[XPRAM_SIZE]; -void MountVolume(void *fh) { } -void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { } - -#if defined __APPLE__ && defined __MACH__ -void DarwinSysInit(void) { } -void DarwinSysExit(void) { } -void DarwinAddFloppyPrefs(void) { } -void DarwinAddSerialPrefs(void) { } -bool DarwinCDReadTOC(char *, uint8 *) { } -#endif - - -/* - * Display alert - */ - -static void dl_destroyed(void) -{ - gtk_main_quit(); -} - -static void display_alert(int title_id, int prefix_id, int button_id, const char *text) -{ - char str[256]; - sprintf(str, GetString(prefix_id), text); - - GtkWidget *dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL); - - GtkWidget *label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - GtkWidget *button = gtk_button_new_with_label(GetString(button_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - gtk_widget_show(dialog); - - gtk_main(); -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text); -} - - -/* - * RPC handlers - */ - -static GMainLoop *g_gui_loop; - -static int handle_ErrorAlert(rpc_connection_t *connection) -{ - D(bug("handle_ErrorAlert\n")); - - int error; - char *str; - if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0) - return error; - - ErrorAlert(str); - free(str); - return RPC_ERROR_NO_ERROR; -} - -static int handle_WarningAlert(rpc_connection_t *connection) -{ - D(bug("handle_WarningAlert\n")); - - int error; - char *str; - if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0) - return error; - - WarningAlert(str); - free(str); - return RPC_ERROR_NO_ERROR; -} - -static int handle_Exit(rpc_connection_t *connection) -{ - D(bug("handle_Exit\n")); - - g_main_quit(g_gui_loop); - return RPC_ERROR_NO_ERROR; -} - - -/* - * SIGCHLD handler - */ - -static char g_app_path[PATH_MAX]; -static rpc_connection_t *g_gui_connection = NULL; - -static void sigchld_handler(int sig, siginfo_t *sip, void *) -{ - D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status)); - - // XXX perform a new wait because sip->si_status is sometimes not - // the exit _value_ on MacOS X but rather the usual status field - // from waitpid() -- we could arrange this code in some other way... - int status; - if (waitpid(sip->si_pid, &status, 0) < 0) - status = sip->si_status; - if (WIFEXITED(status)) - status = WEXITSTATUS(status); - if (status & 0x80) - status |= -1 ^0xff; - - if (status < 0) { // negative -> execlp/-errno - char str[256]; - sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status)); - ErrorAlert(str); - status = 1; - } - - if (status != 0) { - if (g_gui_connection) - rpc_exit(g_gui_connection); - exit(status); - } -} - - -/* - * Start standalone GUI - */ - -int main(int argc, char *argv[]) -{ -#ifdef HAVE_GNOMEUI - // Init GNOME/GTK - char version[16]; - sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR); - gnome_init("Basilisk II", version, argc, argv); -#else - // Init GTK - gtk_set_locale(); - gtk_init(&argc, &argv); -#endif - - // Read preferences - PrefsInit(NULL, argc, argv); - - // Show preferences editor - bool start = PrefsEditor(); - - // Exit preferences - PrefsExit(); - - // Transfer control to the executable - if (start) { - char gui_connection_path[64]; - sprintf(gui_connection_path, "/org/BasiliskII/GUI/%d", getpid()); - - // Catch exits from the child process - struct sigaction sigchld_sa, old_sigchld_sa; - sigemptyset(&sigchld_sa.sa_mask); - sigchld_sa.sa_sigaction = sigchld_handler; - sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; - if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) { - char str[256]; - sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno)); - ErrorAlert(str); - return 1; - } - - // Search and run the BasiliskII executable - char *p; - strcpy(g_app_path, argv[0]); - if ((p = strstr(g_app_path, "BasiliskIIGUI.app/Contents/MacOS")) != NULL) { - strcpy(p, "BasiliskII.app/Contents/MacOS/BasiliskII"); - if (access(g_app_path, X_OK) < 0) { - char str[256]; - sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(errno)); - WarningAlert(str); - strcpy(g_app_path, "/Applications/BasiliskII.app/Contents/MacOS/BasiliskII"); - } - } else { - p = strrchr(g_app_path, '/'); - p = p ? p + 1 : g_app_path; - strcpy(p, "BasiliskII"); - } - - int pid = fork(); - if (pid == 0) { - D(bug("Trying to execute %s\n", g_app_path)); - execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL); -#ifdef _POSIX_PRIORITY_SCHEDULING - // XXX get a chance to run the parent process so that to not confuse/upset GTK... - sched_yield(); -#endif - _exit(-errno); - } - - // Establish a connection to Basilisk II - if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) { - printf("ERROR: failed to initialize GUI-side RPC server connection\n"); - return 1; - } - static const rpc_method_descriptor_t vtable[] = { - { RPC_METHOD_ERROR_ALERT, handle_ErrorAlert }, - { RPC_METHOD_WARNING_ALERT, handle_WarningAlert }, - { RPC_METHOD_EXIT, handle_Exit } - }; - if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) { - printf("ERROR: failed to setup GUI method callbacks\n"); - return 1; - } - int socket; - if ((socket = rpc_listen_socket(g_gui_connection)) < 0) { - printf("ERROR: failed to initialize RPC server thread\n"); - return 1; - } - - g_gui_loop = g_main_new(TRUE); - while (g_main_is_running(g_gui_loop)) { - - // Process a few events pending - const int N_EVENTS_DISPATCH = 10; - for (int i = 0; i < N_EVENTS_DISPATCH; i++) { - if (!g_main_iteration(FALSE)) - break; - } - - // Check for RPC events (100 ms timeout) - int ret = rpc_wait_dispatch(g_gui_connection, 100000); - if (ret == 0) - continue; - if (ret < 0) - break; - rpc_dispatch(g_gui_connection); - } - - rpc_exit(g_gui_connection); - return 0; - } - - return 0; -} -#endif diff --git a/BasiliskII/src/Unix/prefs_unix.cpp b/BasiliskII/src/Unix/prefs_unix.cpp index a92cd640..39e4fba5 100644 --- a/BasiliskII/src/Unix/prefs_unix.cpp +++ b/BasiliskII/src/Unix/prefs_unix.cpp @@ -120,21 +120,8 @@ void AddPlatformPrefsDefaults(void) PrefsReplaceString("extfs", "/"); PrefsReplaceInt32("mousewheelmode", 1); PrefsReplaceInt32("mousewheellines", 3); -#ifdef __linux__ - if (access("/dev/sound/dsp", F_OK) == 0) { - PrefsReplaceString("dsp", "/dev/sound/dsp"); - } else { - PrefsReplaceString("dsp", "/dev/dsp"); - } - if (access("/dev/sound/mixer", F_OK) == 0) { - PrefsReplaceString("mixer", "/dev/sound/mixer"); - } else { - PrefsReplaceString("mixer", "/dev/mixer"); - } -#else PrefsReplaceString("dsp", "/dev/dsp"); PrefsReplaceString("mixer", "/dev/mixer"); -#endif #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION PrefsAddBool("ignoresegv", false); #endif diff --git a/BasiliskII/src/Unix/rpc_unix.cpp b/BasiliskII/src/Unix/rpc_unix.cpp index 378c5dd6..cbc23b60 100644 --- a/BasiliskII/src/Unix/rpc_unix.cpp +++ b/BasiliskII/src/Unix/rpc_unix.cpp @@ -48,11 +48,6 @@ #define NON_BLOCKING_IO 0 -#if defined __linux__ -#define USE_ABSTRACT_NAMESPACES 1 -#endif - - /* ====================================================================== */ /* === PThreads Glue === */ /* ====================================================================== */ diff --git a/BasiliskII/src/Unix/serial_unix.cpp b/BasiliskII/src/Unix/serial_unix.cpp deleted file mode 100644 index 81922b43..00000000 --- a/BasiliskII/src/Unix/serial_unix.cpp +++ /dev/null @@ -1,833 +0,0 @@ -/* - * serial_unix.cpp - Serial device driver, Unix specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -#include -#include -#include -#endif - -#include "cpu_emulation.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "serial.h" -#include "serial_defs.h" - -extern "C" { -#include "sshpty.h" -} - - -#define DEBUG 0 -#include "debug.h" - -#define MONITOR 0 - - -// IRIX missing or unsupported defines -#ifdef sgi -#ifndef CRTSCTS -#define CRTSCTS CNEW_RTSCTS -#endif -#ifndef B230400 -#define B230400 B115200 -#endif -#endif - - -// Missing functions -#ifndef HAVE_CFMAKERAW -static int cfmakeraw(struct termios *termios_p) -{ - termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); - termios_p->c_oflag &= ~OPOST; - termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - termios_p->c_cflag &= ~(CSIZE|PARENB); - termios_p->c_cflag |= CS8; - return 0; -} -#endif - - -// Driver private variables -class XSERDPort : public SERDPort { -public: - XSERDPort(const char *dev) - { - device_name = dev; - protocol = serial; - fd = -1; - pid = 0; - input_thread_active = output_thread_active = false; - - Set_pthread_attr(&thread_attr, 2); - } - - virtual ~XSERDPort() - { - if (input_thread_active) { - input_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(input_thread); -#endif - pthread_join(input_thread, NULL); - sem_destroy(&input_signal); - input_thread_active = false; - } - if (output_thread_active) { - output_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(output_thread); -#endif - pthread_join(output_thread, NULL); - sem_destroy(&output_signal); - output_thread_active = false; - } - } - - virtual int16 open(uint16 config); - virtual int16 prime_in(uint32 pb, uint32 dce); - virtual int16 prime_out(uint32 pb, uint32 dce); - virtual int16 control(uint32 pb, uint32 dce, uint16 code); - virtual int16 status(uint32 pb, uint32 dce, uint16 code); - virtual int16 close(void); - -private: - bool open_pty(void); - bool configure(uint16 config); - void set_handshake(uint32 s, bool with_dtr); - static void *input_func(void *arg); - static void *output_func(void *arg); - - const char *device_name; // Device name - enum {serial, parallel, pty, midi} - protocol; // Type of device - int fd; // FD of device - pid_t pid; // PID of child process - - bool io_killed; // Flag: KillIO called, I/O threads must not call deferred tasks - bool quitting; // Flag: Quit threads - - pthread_attr_t thread_attr; // Input/output thread attributes - - bool input_thread_active; // Flag: Input thread installed - volatile bool input_thread_cancel; // Flag: Cancel input thread - pthread_t input_thread; // Data input thread - sem_t input_signal; // Signal for input thread: execute command - uint32 input_pb; // Command parameter for input thread - - bool output_thread_active; // Flag: Output thread installed - volatile bool output_thread_cancel; // Flag: Cancel output thread - pthread_t output_thread; // Data output thread - sem_t output_signal; // Signal for output thread: execute command - uint32 output_pb; // Command parameter for output thread - - struct termios mode; // Terminal configuration -}; - - -/* - * Initialization - */ - -void SerialInit(void) -{ - // Read serial preferences and create structs for both ports - the_serd_port[0] = new XSERDPort(PrefsFindString("seriala")); - the_serd_port[1] = new XSERDPort(PrefsFindString("serialb")); -} - - -/* - * Deinitialization - */ - -void SerialExit(void) -{ - delete (XSERDPort *)the_serd_port[0]; - delete (XSERDPort *)the_serd_port[1]; -} - - -/* - * Open serial port - */ - -int16 XSERDPort::open(uint16 config) -{ - // Don't open NULL name devices - if (device_name == NULL) - return openErr; - - // Init variables - io_killed = false; - quitting = false; - - // Open port, according to the syntax of the path - if (device_name[0] == '|') { - // Open a process via ptys - if (!open_pty()) - goto open_error; - } - else if (!strcmp(device_name, "midi")) { - // MIDI: not yet implemented - return openErr; - } - else { - // Device special file - fd = ::open(device_name, O_RDWR); - if (fd < 0) - goto open_error; - -#if defined(__linux__) - // Parallel port? - struct stat st; - if (fstat(fd, &st) == 0) - if (S_ISCHR(st.st_mode)) - protocol = ((MAJOR(st.st_rdev) == LP_MAJOR) ? parallel : serial); -#elif defined(__FreeBSD__) || defined(__NetBSD__) - // Parallel port? - struct stat st; - if (fstat(fd, &st) == 0) - if (S_ISCHR(st.st_mode)) - protocol = (((st.st_rdev >> 16) == 16) ? parallel : serial); -#endif - } - - // Configure port for raw mode - if (protocol == serial || protocol == pty) { - if (tcgetattr(fd, &mode) < 0) - goto open_error; - cfmakeraw(&mode); - mode.c_cflag |= HUPCL; - mode.c_cc[VMIN] = 1; - mode.c_cc[VTIME] = 0; - tcsetattr(fd, TCSAFLUSH, &mode); - } - configure(config); - - // Start input/output threads - input_thread_cancel = false; - output_thread_cancel = false; - if (sem_init(&input_signal, 0, 0) < 0) - goto open_error; - if (sem_init(&output_signal, 0, 0) < 0) - goto open_error; - input_thread_active = (pthread_create(&input_thread, &thread_attr, input_func, this) == 0); - output_thread_active = (pthread_create(&output_thread, &thread_attr, output_func, this) == 0); - if (!input_thread_active || !output_thread_active) - goto open_error; - return noErr; - -open_error: - if (input_thread_active) { - input_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(input_thread); -#endif - pthread_join(input_thread, NULL); - sem_destroy(&input_signal); - input_thread_active = false; - } - if (output_thread_active) { - output_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(output_thread); -#endif - pthread_join(output_thread, NULL); - sem_destroy(&output_signal); - output_thread_active = false; - } - if (fd > 0) { - ::close(fd); - fd = -1; - } - return openErr; -} - - -/* - * Read data from port - */ - -int16 XSERDPort::prime_in(uint32 pb, uint32 dce) -{ - // Send input command to input_thread - read_done = false; - read_pending = true; - input_pb = pb; - WriteMacInt32(input_dt + serdtDCE, dce); - sem_post(&input_signal); - return 1; // Command in progress -} - - -/* - * Write data to port - */ - -int16 XSERDPort::prime_out(uint32 pb, uint32 dce) -{ - // Send output command to output_thread - write_done = false; - write_pending = true; - output_pb = pb; - WriteMacInt32(output_dt + serdtDCE, dce); - sem_post(&output_signal); - return 1; // Command in progress -} - - -/* - * Control calls - */ - -int16 XSERDPort::control(uint32 pb, uint32 dce, uint16 code) -{ - switch (code) { - case 1: // KillIO - io_killed = true; - if (protocol == serial) - tcflush(fd, TCIOFLUSH); - while (read_pending || write_pending) - usleep(10000); - io_killed = false; - return noErr; - - case kSERDConfiguration: - if (configure(ReadMacInt16(pb + csParam))) - return noErr; - else - return paramErr; - - case kSERDInputBuffer: - return noErr; // Not supported under Unix - - case kSERDSerHShake: - set_handshake(pb + csParam, false); - return noErr; - - case kSERDSetBreak: - if (protocol == serial) - tcsendbreak(fd, 0); - return noErr; - - case kSERDClearBreak: - return noErr; - - case kSERDBaudRate: { - if (protocol != serial) - return noErr; - uint16 rate = ReadMacInt16(pb + csParam); - speed_t baud_rate; - if (rate <= 50) { - rate = 50; baud_rate = B50; - } else if (rate <= 75) { - rate = 75; baud_rate = B75; - } else if (rate <= 110) { - rate = 110; baud_rate = B110; - } else if (rate <= 134) { - rate = 134; baud_rate = B134; - } else if (rate <= 150) { - rate = 150; baud_rate = B150; - } else if (rate <= 200) { - rate = 200; baud_rate = B200; - } else if (rate <= 300) { - rate = 300; baud_rate = B300; - } else if (rate <= 600) { - rate = 600; baud_rate = B600; - } else if (rate <= 1200) { - rate = 1200; baud_rate = B1200; - } else if (rate <= 1800) { - rate = 1800; baud_rate = B1800; - } else if (rate <= 2400) { - rate = 2400; baud_rate = B2400; - } else if (rate <= 4800) { - rate = 4800; baud_rate = B4800; - } else if (rate <= 9600) { - rate = 9600; baud_rate = B9600; - } else if (rate <= 19200) { - rate = 19200; baud_rate = B19200; - } else if (rate <= 38400) { - rate = 38400; baud_rate = B38400; - } else if (rate <= 57600) { - rate = 57600; baud_rate = B57600; - } else { - // Just for safety in case someone wants a rate between 57600 and 65535 - rate = 57600; baud_rate = B57600; - } - WriteMacInt16(pb + csParam, rate); - cfsetispeed(&mode, baud_rate); - cfsetospeed(&mode, baud_rate); - tcsetattr(fd, TCSANOW, &mode); - return noErr; - } - - case kSERDHandshake: - case kSERDHandshakeRS232: - set_handshake(pb + csParam, true); - return noErr; - - case kSERDMiscOptions: - if (protocol != serial) - return noErr; - if (ReadMacInt8(pb + csParam) & kOptionPreserveDTR) - mode.c_cflag &= ~HUPCL; - else - mode.c_cflag |= HUPCL; - tcsetattr(fd, TCSANOW, &mode); - return noErr; - - case kSERDAssertDTR: { - if (protocol != serial) - return noErr; - unsigned int status = TIOCM_DTR; - ioctl(fd, TIOCMBIS, &status); - return noErr; - } - - case kSERDNegateDTR: { - if (protocol != serial) - return noErr; - unsigned int status = TIOCM_DTR; - ioctl(fd, TIOCMBIC, &status); - return noErr; - } - - case kSERDSetPEChar: - case kSERDSetPEAltChar: - return noErr; // Not supported under Unix - - case kSERDResetChannel: - if (protocol == serial) - tcflush(fd, TCIOFLUSH); - return noErr; - - case kSERDAssertRTS: { - if (protocol != serial) - return noErr; - unsigned int status = TIOCM_RTS; - ioctl(fd, TIOCMBIS, &status); - return noErr; - } - - case kSERDNegateRTS: { - if (protocol != serial) - return noErr; - unsigned int status = TIOCM_RTS; - ioctl(fd, TIOCMBIC, &status); - return noErr; - } - - case kSERD115KBaud: - if (protocol != serial) - return noErr; - cfsetispeed(&mode, B115200); - cfsetospeed(&mode, B115200); - tcsetattr(fd, TCSANOW, &mode); - return noErr; - - case kSERD230KBaud: - case kSERDSetHighSpeed: - if (protocol != serial) - return noErr; - cfsetispeed(&mode, B230400); - cfsetospeed(&mode, B230400); - tcsetattr(fd, TCSANOW, &mode); - return noErr; - - default: - printf("WARNING: SerialControl(): unimplemented control code %d\n", code); - return controlErr; - } -} - - -/* - * Status calls - */ - -int16 XSERDPort::status(uint32 pb, uint32 dce, uint16 code) -{ - switch (code) { - case kSERDInputCount: { - int num; - ioctl(fd, FIONREAD, &num); - WriteMacInt32(pb + csParam, num); - return noErr; - } - - case kSERDStatus: { - uint32 p = pb + csParam; - WriteMacInt8(p + staCumErrs, cum_errors); - cum_errors = 0; - WriteMacInt8(p + staXOffSent, 0); - WriteMacInt8(p + staXOffHold, 0); - WriteMacInt8(p + staRdPend, read_pending); - WriteMacInt8(p + staWrPend, write_pending); - if (protocol != serial) { - WriteMacInt8(p + staCtsHold, 0); - WriteMacInt8(p + staDsrHold, 0); - WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent); - } else { - unsigned int status; - ioctl(fd, TIOCMGET, &status); - WriteMacInt8(p + staCtsHold, status & TIOCM_CTS ? 0 : 1); - WriteMacInt8(p + staDsrHold, status & TIOCM_DTR ? 0 : 1); - WriteMacInt8(p + staModemStatus, - (status & TIOCM_DSR ? dsrEvent : 0) - | (status & TIOCM_RI ? riEvent : 0) - | (status & TIOCM_CD ? dcdEvent : 0) - | (status & TIOCM_CTS ? ctsEvent : 0)); - } - return noErr; - } - - default: - printf("WARNING: SerialStatus(): unimplemented status code %d\n", code); - return statusErr; - } -} - - -/* - * Close serial port - */ - -int16 XSERDPort::close() -{ - // Kill threads - if (input_thread_active) { - quitting = true; - sem_post(&input_signal); - pthread_join(input_thread, NULL); - input_thread_active = false; - sem_destroy(&input_signal); - } - if (output_thread_active) { - quitting = true; - sem_post(&output_signal); - pthread_join(output_thread, NULL); - output_thread_active = false; - sem_destroy(&output_signal); - } - - // Close port - if (fd > 0) - ::close(fd); - fd = -1; - - // Wait for the subprocess to exit - if (pid) - waitpid(pid, NULL, 0); - pid = 0; - - return noErr; -} - - -/* - * Open a process via ptys - */ - -bool XSERDPort::open_pty(void) -{ - // Talk to a process via a pty - char slave[128]; - int slavefd; - - protocol = pty; - if (!pty_allocate(&fd, &slavefd, slave, sizeof(slave))) - return false; - - fflush(stdout); - fflush(stderr); - switch (pid = fork()) { - case -1: // error - return false; - break; - case 0: // child - ::close(fd); - - /* Make the pseudo tty our controlling tty. */ - pty_make_controlling_tty(&slavefd, slave); - - ::close(0); dup(slavefd); // Use the slave fd for stdin, - ::close(1); dup(slavefd); // stdout, - ::close(2); dup(slavefd); // and stderr. - - // - // - - // Let the shell do the dirty work - execlp("/bin/sh", "/bin/sh", "-c", ++device_name, (char *)NULL); - - // exec failed! - printf("serial_open: could not exec %s: %s\n", - "/bin/sh", strerror(errno)); - exit(1); - break; - default: // parent - // Pid was stored above - break; - } - - return true; -} - - -/* - * Configure serial port with MacOS config word - */ - -bool XSERDPort::configure(uint16 config) -{ - D(bug(" configure %04x\n", config)); - if (protocol != serial) - return true; - - // Set number of stop bits - switch (config & 0xc000) { - case stop10: - mode.c_cflag &= ~CSTOPB; - break; - case stop20: - mode.c_cflag |= CSTOPB; - break; - default: - return false; - } - - // Set parity mode - switch (config & 0x3000) { - case noParity: - mode.c_iflag &= ~INPCK; - mode.c_oflag &= ~PARENB; - break; - case oddParity: - mode.c_iflag |= INPCK; - mode.c_oflag |= PARENB; - mode.c_oflag |= PARODD; - break; - case evenParity: - mode.c_iflag |= INPCK; - mode.c_oflag |= PARENB; - mode.c_oflag &= ~PARODD; - break; - default: - return false; - } - - // Set number of data bits - switch (config & 0x0c00) { - case data5: - mode.c_cflag = mode.c_cflag & ~CSIZE | CS5; - break; - case data6: - mode.c_cflag = mode.c_cflag & ~CSIZE | CS6; - break; - case data7: - mode.c_cflag = mode.c_cflag & ~CSIZE | CS7; - break; - case data8: - mode.c_cflag = mode.c_cflag & ~CSIZE | CS8; - break; - } - - // Set baud rate - speed_t baud_rate; - switch (config & 0x03ff) { - case baud150: baud_rate = B150; break; - case baud300: baud_rate = B300; break; - case baud600: baud_rate = B600; break; - case baud1200: baud_rate = B1200; break; - case baud1800: baud_rate = B1800; break; - case baud2400: baud_rate = B2400; break; - case baud4800: baud_rate = B4800; break; - case baud9600: baud_rate = B9600; break; - case baud19200: baud_rate = B19200; break; - case baud38400: baud_rate = B38400; break; - case baud57600: baud_rate = B57600; break; - default: - return false; - } - cfsetispeed(&mode, baud_rate); - cfsetospeed(&mode, baud_rate); - tcsetattr(fd, TCSANOW, &mode); - return true; -} - - -/* - * Set serial handshaking - */ - -void XSERDPort::set_handshake(uint32 s, bool with_dtr) -{ - D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n", - ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3), - ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7))); - if (protocol != serial) - return; - - if (with_dtr) { - if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) - mode.c_cflag |= CRTSCTS; - else - mode.c_cflag &= ~CRTSCTS; - } else { - if (ReadMacInt8(s + shkFCTS)) - mode.c_cflag |= CRTSCTS; - else - mode.c_cflag &= ~CRTSCTS; - } - - D(bug(" %sware flow control\n", mode.c_cflag & CRTSCTS ? "hard" : "soft")); - tcsetattr(fd, TCSANOW, &mode); -} - - -/* - * Data input thread - */ - -void *XSERDPort::input_func(void *arg) -{ - XSERDPort *s = (XSERDPort *)arg; - while (!s->input_thread_cancel) { - - // Wait for commands - sem_wait(&s->input_signal); - if (s->quitting) - break; - - // Execute command - void *buf = Mac2HostAddr(ReadMacInt32(s->input_pb + ioBuffer)); - uint32 length = ReadMacInt32(s->input_pb + ioReqCount); - D(bug("input_func waiting for %ld bytes of data...\n", length)); - int32 actual = read(s->fd, buf, length); - D(bug(" %ld bytes received\n", actual)); - -#if MONITOR - bug("Receiving serial data:\n"); - uint8 *adr = (uint8 *)buf; - for (int i=0; iio_killed) { - - WriteMacInt16(s->input_pb + ioResult, uint16(abortErr)); - WriteMacInt32(s->input_pb + ioActCount, 0); - s->read_pending = s->read_done = false; - - } else { - - // Set error code - if (actual >= 0) { - WriteMacInt32(s->input_pb + ioActCount, actual); - WriteMacInt32(s->input_dt + serdtResult, noErr); - } else { - WriteMacInt32(s->input_pb + ioActCount, 0); - WriteMacInt32(s->input_dt + serdtResult, uint16(readErr)); - } - - // Trigger serial interrupt - D(bug(" triggering serial interrupt\n")); - s->read_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - return NULL; -} - - -/* - * Data output thread - */ - -void *XSERDPort::output_func(void *arg) -{ - XSERDPort *s = (XSERDPort *)arg; - while (!s->output_thread_cancel) { - - // Wait for commands - sem_wait(&s->output_signal); - if (s->quitting) - break; - - // Execute command - void *buf = Mac2HostAddr(ReadMacInt32(s->output_pb + ioBuffer)); - uint32 length = ReadMacInt32(s->output_pb + ioReqCount); - D(bug("output_func transmitting %ld bytes of data...\n", length)); - -#if MONITOR - bug("Sending serial data:\n"); - uint8 *adr = (uint8 *)buf; - for (int i=0; ifd, buf, length); - D(bug(" %ld bytes transmitted\n", actual)); - - // KillIO called? Then simply return - if (s->io_killed) { - - WriteMacInt16(s->output_pb + ioResult, uint16(abortErr)); - WriteMacInt32(s->output_pb + ioActCount, 0); - s->write_pending = s->write_done = false; - - } else { - - // Set error code - if (actual >= 0) { - WriteMacInt32(s->output_pb + ioActCount, actual); - WriteMacInt32(s->output_dt + serdtResult, noErr); - } else { - WriteMacInt32(s->output_pb + ioActCount, 0); - WriteMacInt32(s->output_dt + serdtResult, uint16(writErr)); - } - - // Trigger serial interrupt - D(bug(" triggering serial interrupt\n")); - s->write_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - return NULL; -} diff --git a/BasiliskII/src/Unix/sshpty.c b/BasiliskII/src/Unix/sshpty.c deleted file mode 100644 index 48e69dc7..00000000 --- a/BasiliskII/src/Unix/sshpty.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Allocating a pseudo-terminal, and making it the controlling tty. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#if 0 /* not in BasiliskII */ -#include "includes.h" -RCSID("$OpenBSD: sshpty.c,v 1.4 2001/12/19 07:18:56 deraadt Exp $"); -#else /* not in BasiliskII */ -/* Selections from openssh's "includes.h" */ -#include "config.h" - -#include -#include -#include -#include /* For O_NONBLOCK */ -#include -#include -#include - -#include /* For STDIN_FILENO, etc */ -#include /* Struct winsize */ - -/* - *-*-nto-qnx needs these headers for strcasecmp and LASTLOG_FILE respectively - */ -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_LOGIN_H -# include -#endif - -#include - -#ifdef HAVE_SYS_BSDTTY_H -# include -#endif - -#ifdef HAVE_SYS_STAT_H -# include /* For S_* constants and macros */ -#endif - -#ifndef _PATH_TTY -# define _PATH_TTY "/dev/tty" -#endif - -#include "strlcpy.h" - -#define debug(x) ; - -#endif /* not in BasiliskII */ - -#ifdef HAVE_UTIL_H -# include -#endif /* HAVE_UTIL_H */ - -#include "sshpty.h" -#if 0 /* not in BasiliskII */ -#include "log.h" -#include "misc.h" -#else /* stubs for BasiliskII */ -#define log printf -#define error printf -#define fatal(x) do { printf("Fatal error: %s", x); return 0; } while(0) -#endif /* not in BasiliskII */ - -#define mysig_t sig_t -#define mysignal signal -#include - -/* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */ -#if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY) -#undef HAVE_DEV_PTMX -#endif - -#ifdef HAVE_PTY_H -# include -#endif -#if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) -# include -#endif -#if defined(HAVE_DEV_PTMX) && defined(HAVE_STROPTS_H) -# include -#endif - -#ifndef O_NOCTTY -#define O_NOCTTY 0 -#endif - -/* - * Allocates and opens a pty. Returns 0 if no pty could be allocated, or - * nonzero if a pty was successfully allocated. On success, open file - * descriptors for the pty and tty sides and the name of the tty side are - * returned (the buffer must be able to hold at least 64 characters). - */ - -int -pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) -{ -#if defined(HAVE_OPENPTY) || defined(BSD4_4) - /* openpty(3) exists in OSF/1 and some other os'es */ - char *name; - int i; - - i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); - if (i < 0) { - error("openpty: %.100s", strerror(errno)); - return 0; - } - name = ttyname(*ttyfd); - if (!name) - fatal("openpty returns device for which ttyname fails."); - - strlcpy(namebuf, name, namebuflen); /* possible truncation */ - return 1; -#else /* HAVE_OPENPTY */ -#ifdef HAVE__GETPTY - /* - * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more - * pty's automagically when needed - */ - char *slave; - - slave = _getpty(ptyfd, O_RDWR, 0622, 0); - if (slave == NULL) { - error("_getpty: %.100s", strerror(errno)); - return 0; - } - strlcpy(namebuf, slave, namebuflen); - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("%.200s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } - return 1; -#else /* HAVE__GETPTY */ -#if defined(HAVE_DEV_PTMX) - /* - * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 - * also has bsd-style ptys, but they simply do not work.) - */ - int ptm; - char *pts; - mysig_t old_signal; - - ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); - if (ptm < 0) { - error("/dev/ptmx: %.100s", strerror(errno)); - return 0; - } - old_signal = mysignal(SIGCHLD, SIG_DFL); - if (grantpt(ptm) < 0) { - error("grantpt: %.100s", strerror(errno)); - return 0; - } - mysignal(SIGCHLD, old_signal); - if (unlockpt(ptm) < 0) { - error("unlockpt: %.100s", strerror(errno)); - return 0; - } - pts = ptsname(ptm); - if (pts == NULL) - error("Slave pty side name could not be obtained."); - strlcpy(namebuf, pts, namebuflen); - *ptyfd = ptm; - - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("%.100s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } -#ifndef HAVE_CYGWIN - /* - * Push the appropriate streams modules, as described in Solaris pts(7). - * HP-UX pts(7) doesn't have ttcompat module. - */ - if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) - error("ioctl I_PUSH ptem: %.100s", strerror(errno)); - if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) - error("ioctl I_PUSH ldterm: %.100s", strerror(errno)); -#ifndef __hpux - if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) - error("ioctl I_PUSH ttcompat: %.100s", strerror(errno)); -#endif -#endif - return 1; -#else /* HAVE_DEV_PTMX */ -#ifdef HAVE_DEV_PTS_AND_PTC - /* AIX-style pty code. */ - const char *name; - - *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY); - if (*ptyfd < 0) { - error("Could not open /dev/ptc: %.100s", strerror(errno)); - return 0; - } - name = ttyname(*ptyfd); - if (!name) - fatal("Open of /dev/ptc returns device for which ttyname fails."); - strlcpy(namebuf, name, namebuflen); - *ttyfd = open(name, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("Could not open pty slave side %.100s: %.100s", - name, strerror(errno)); - close(*ptyfd); - return 0; - } - return 1; -#else /* HAVE_DEV_PTS_AND_PTC */ -#ifdef _CRAY - char buf[64]; - int i; - int highpty; - -#ifdef _SC_CRAY_NPTY - highpty = sysconf(_SC_CRAY_NPTY); - if (highpty == -1) - highpty = 128; -#else - highpty = 128; -#endif - - for (i = 0; i < highpty; i++) { - snprintf(buf, sizeof(buf), "/dev/pty/%03d", i); - *ptyfd = open(buf, O_RDWR|O_NOCTTY); - if (*ptyfd < 0) - continue; - snprintf(namebuf, namebuflen, "/dev/ttyp%03d", i); - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); - if (*ttyfd < 0) { - error("%.100s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } - return 1; - } - return 0; -#else - /* BSD-style pty code. */ - char buf[64]; - int i; - const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; - const char *ptyminors = "0123456789abcdef"; - int num_minors = strlen(ptyminors); - int num_ptys = strlen(ptymajors) * num_minors; - struct termios tio; - - for (i = 0; i < num_ptys; i++) { - snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], - ptyminors[i % num_minors]); - snprintf(namebuf, namebuflen, "/dev/tty%c%c", - ptymajors[i / num_minors], ptyminors[i % num_minors]); - - *ptyfd = open(buf, O_RDWR | O_NOCTTY); - if (*ptyfd < 0) { - /* Try SCO style naming */ - snprintf(buf, sizeof buf, "/dev/ptyp%d", i); - snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); - *ptyfd = open(buf, O_RDWR | O_NOCTTY); - if (*ptyfd < 0) - continue; - } - - /* Open the slave side. */ - *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); - if (*ttyfd < 0) { - error("%.100s: %.100s", namebuf, strerror(errno)); - close(*ptyfd); - return 0; - } - /* set tty modes to a sane state for broken clients */ - if (tcgetattr(*ptyfd, &tio) < 0) - log("Getting tty modes for pty failed: %.100s", strerror(errno)); - else { - tio.c_lflag |= (ECHO | ISIG | ICANON); - tio.c_oflag |= (OPOST | ONLCR); - tio.c_iflag |= ICRNL; - - /* Set the new modes for the terminal. */ - if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) - log("Setting tty modes for pty failed: %.100s", strerror(errno)); - } - - return 1; - } - return 0; -#endif /* CRAY */ -#endif /* HAVE_DEV_PTS_AND_PTC */ -#endif /* HAVE_DEV_PTMX */ -#endif /* HAVE__GETPTY */ -#endif /* HAVE_OPENPTY */ -} - -/* Releases the tty. Its ownership is returned to root, and permissions to 0666. */ - -void -pty_release(const char *ttyname) -{ - if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0) - error("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno)); - if (chmod(ttyname, (mode_t) 0666) < 0) - error("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno)); -} - -/* Makes the tty the processes controlling tty and sets it to sane modes. */ - -void -pty_make_controlling_tty(int *ttyfd, const char *ttyname) -{ - int fd; -#ifdef USE_VHANGUP - void *old; -#endif /* USE_VHANGUP */ - -#ifdef _CRAY - if (setsid() < 0) - error("setsid: %.100s", strerror(errno)); - - fd = open(ttyname, O_RDWR|O_NOCTTY); - if (fd != -1) { - mysignal(SIGHUP, SIG_IGN); - ioctl(fd, TCVHUP, (char *)NULL); - mysignal(SIGHUP, SIG_DFL); - setpgid(0, 0); - close(fd); - } else { - error("Failed to disconnect from controlling tty."); - } - - debug("Setting controlling tty using TCSETCTTY."); - ioctl(*ttyfd, TCSETCTTY, NULL); - fd = open("/dev/tty", O_RDWR); - if (fd < 0) - error("%.100s: %.100s", ttyname, strerror(errno)); - close(*ttyfd); - *ttyfd = fd; -#else /* _CRAY */ - - /* First disconnect from the old controlling tty. */ -#ifdef TIOCNOTTY - fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); - if (fd >= 0) { - (void) ioctl(fd, TIOCNOTTY, NULL); - close(fd); - } -#endif /* TIOCNOTTY */ - if (setsid() < 0) - error("setsid: %.100s", strerror(errno)); - - /* - * Verify that we are successfully disconnected from the controlling - * tty. - */ - fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); - if (fd >= 0) { - error("Failed to disconnect from controlling tty."); - close(fd); - } - /* Make it our controlling tty. */ -#ifdef TIOCSCTTY - debug("Setting controlling tty using TIOCSCTTY."); - if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) - error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); -#endif /* TIOCSCTTY */ -#ifdef HAVE_NEWS4 - if (setpgrp(0,0) < 0) - error("SETPGRP %s",strerror(errno)); -#endif /* HAVE_NEWS4 */ -#ifdef USE_VHANGUP - old = mysignal(SIGHUP, SIG_IGN); - vhangup(); - mysignal(SIGHUP, old); -#endif /* USE_VHANGUP */ - fd = open(ttyname, O_RDWR); - if (fd < 0) { - error("%.100s: %.100s", ttyname, strerror(errno)); - } else { -#ifdef USE_VHANGUP - close(*ttyfd); - *ttyfd = fd; -#else /* USE_VHANGUP */ - close(fd); -#endif /* USE_VHANGUP */ - } - /* Verify that we now have a controlling tty. */ - fd = open(_PATH_TTY, O_WRONLY); - if (fd < 0) - error("open /dev/tty failed - could not set controlling tty: %.100s", - strerror(errno)); - else { - close(fd); - } -#endif /* _CRAY */ -} - -#if 0 /* not in BasiliskII */ -/* Changes the window size associated with the pty. */ - -void -pty_change_window_size(int ptyfd, int row, int col, - int xpixel, int ypixel) -{ - struct winsize w; - w.ws_row = row; - w.ws_col = col; - w.ws_xpixel = xpixel; - w.ws_ypixel = ypixel; - (void) ioctl(ptyfd, TIOCSWINSZ, &w); -} - -void -pty_setowner(struct passwd *pw, const char *ttyname) -{ - struct group *grp; - gid_t gid; - mode_t mode; - struct stat st; - - /* Determine the group to make the owner of the tty. */ - grp = getgrnam("tty"); - if (grp) { - gid = grp->gr_gid; - mode = S_IRUSR | S_IWUSR | S_IWGRP; - } else { - gid = pw->pw_gid; - mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH; - } - - /* - * Change owner and mode of the tty as required. - * Warn but continue if filesystem is read-only and the uids match/ - * tty is owned by root. - */ - if (stat(ttyname, &st)) - fatal("stat(%.100s) failed: %.100s", ttyname, - strerror(errno)); - - if (st.st_uid != pw->pw_uid || st.st_gid != gid) { - if (chown(ttyname, pw->pw_uid, gid) < 0) { - if (errno == EROFS && - (st.st_uid == pw->pw_uid || st.st_uid == 0)) - error("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); - else - fatal("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); - } - } - - if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) { - if (chmod(ttyname, mode) < 0) { - if (errno == EROFS && - (st.st_mode & (S_IRGRP | S_IROTH)) == 0) - error("chmod(%.100s, 0%o) failed: %.100s", - ttyname, mode, strerror(errno)); - else - fatal("chmod(%.100s, 0%o) failed: %.100s", - ttyname, mode, strerror(errno)); - } - } -} -#endif /* not in BasiliskII */ diff --git a/BasiliskII/src/Unix/sshpty.h b/BasiliskII/src/Unix/sshpty.h deleted file mode 100644 index df65e284..00000000 --- a/BasiliskII/src/Unix/sshpty.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $OpenBSD: sshpty.h,v 1.4 2002/03/04 17:27:39 stevesk Exp $ */ - -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Functions for allocating a pseudo-terminal and making it the controlling - * tty. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#ifndef SSHPTY_H -#define SSHPTY_H - -int pty_allocate(int *, int *, char *, int); -void pty_release(const char *); -void pty_make_controlling_tty(int *, const char *); -void pty_change_window_size(int, int, int, int, int); -void pty_setowner(struct passwd *, const char *); - -#endif /* SSHPTY_H */ diff --git a/BasiliskII/src/Unix/strlcpy.c b/BasiliskII/src/Unix/strlcpy.c deleted file mode 100644 index b5e5a552..00000000 --- a/BasiliskII/src/Unix/strlcpy.c +++ /dev/null @@ -1,75 +0,0 @@ -/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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 "config.h" -#ifndef HAVE_STRLCPY - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include "strlcpy.h" - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -strlcpy(dst, src, siz) - char *dst; - const char *src; - size_t siz; -{ - register char *d = dst; - register const char *s = src; - register size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -#endif /* !HAVE_STRLCPY */ diff --git a/BasiliskII/src/Unix/strlcpy.h b/BasiliskII/src/Unix/strlcpy.h deleted file mode 100644 index 7b33e4f6..00000000 --- a/BasiliskII/src/Unix/strlcpy.h +++ /dev/null @@ -1,12 +0,0 @@ -/* $Id$ */ - -#ifndef _BSD_STRLCPY_H -#define _BSD_STRLCPY_H - -#include "config.h" -#ifndef HAVE_STRLCPY -#include -size_t strlcpy(char *dst, const char *src, size_t siz); -#endif /* !HAVE_STRLCPY */ - -#endif /* _BSD_STRLCPY_H */ diff --git a/BasiliskII/src/Unix/sys_unix.cpp b/BasiliskII/src/Unix/sys_unix.cpp index 85d650c8..6a5729c1 100644 --- a/BasiliskII/src/Unix/sys_unix.cpp +++ b/BasiliskII/src/Unix/sys_unix.cpp @@ -28,27 +28,9 @@ #include #endif -#ifdef __linux__ -#include -#include -#include -#include -#include -#include -#include -#endif - -#if defined(__FreeBSD__) || defined(__NetBSD__) -#include -#endif - #if defined __APPLE__ && defined __MACH__ #include -#if (defined AQUA || defined HAVE_FRAMEWORK_COREFOUNDATION) -#ifndef __MACOSX__ -#define __MACOSX__ MAC_OS_X_VERSION_MIN_REQUIRED -#endif -#endif + #endif #include "main.h" @@ -58,22 +40,11 @@ #include "sys.h" #include "disk_unix.h" -#if defined(BINCUE) -#include "bincue_unix.h" -#endif - - - #define DEBUG 0 #include "debug.h" static disk_factory *disk_factories[] = { -#ifndef STANDALONE_GUI - disk_sparsebundle_factory, -#if defined(HAVE_LIBVHD) - disk_vhd_factory, -#endif -#endif + NULL }; @@ -93,19 +64,11 @@ struct mac_file_handle { bool is_media_present; // Flag: media is inserted and available disk_generic *generic_disk; -#if defined(__linux__) - int cdrom_cap; // CD-ROM capability flags (only valid if is_cdrom is true) -#elif defined(__FreeBSD__) - struct ioc_capability cdrom_cap; -#elif defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) char *ioctl_name; // For CDs on OS X - a device for special ioctls int ioctl_fd; #endif -#if defined(BINCUE) - bool is_bincue; // Flag: BIN CUE file - void *bincue_fd; -#endif }; // Open file handles @@ -129,10 +92,7 @@ static bool cdrom_open(mac_file_handle *fh, const char *path = NULL); void SysInit(void) { -#if defined __MACOSX__ - extern void DarwinSysInit(void); - DarwinSysInit(); -#endif + } @@ -142,10 +102,7 @@ void SysInit(void) void SysExit(void) { -#if defined __MACOSX__ - extern void DarwinSysExit(void); - DarwinSysExit(); -#endif + } @@ -242,12 +199,7 @@ void SysMediaRemoved(const char *path, int type) fh->is_media_present = false; break; } -#if defined __MACOSX__ - if (fh->ioctl_name && strcmp(fh->ioctl_name, path) == 0) { - fh->is_media_present = false; - break; - } -#endif + } } @@ -270,26 +222,7 @@ void SysMountFirstFloppy(void) void SysAddFloppyPrefs(void) { -#if defined(__linux__) - DIR *fd_dir = opendir("/dev/floppy"); - if (fd_dir) { - struct dirent *floppy_dev; - while ((floppy_dev = readdir(fd_dir)) != NULL) { - if (strstr(floppy_dev->d_name, "u1440") != NULL) { - char fd_dev[20]; - sprintf(fd_dev, "/dev/floppy/%s", floppy_dev->d_name); - PrefsAddString("floppy", fd_dev); - } - } - closedir(fd_dir); - } else { - PrefsAddString("floppy", "/dev/fd0"); - PrefsAddString("floppy", "/dev/fd1"); - } -#elif defined(__NetBSD__) - PrefsAddString("floppy", "/dev/fd0a"); - PrefsAddString("floppy", "/dev/fd1a"); -#elif defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) #if defined(AQUA) || defined(HAVE_FRAMEWORK_COREFOUNDATION) extern void DarwinAddFloppyPrefs(void); @@ -316,28 +249,7 @@ void SysAddFloppyPrefs(void) void SysAddDiskPrefs(void) { -#ifdef __linux__ - FILE *f = fopen("/etc/fstab", "r"); - if (f) { - char line[256]; - while(fgets(line, 255, f)) { - // Read line - int len = strlen(line); - if (len == 0 || line[0] == '#') - continue; - line[len-1] = 0; - // Parse line - char *dev = NULL, *mnt_point = NULL, *fstype = NULL; - if (sscanf(line, "%as %as %as", &dev, &mnt_point, &fstype) == 3) { - if (strcmp(fstype, "hfs") == 0) - PrefsAddString("disk", dev); - } - free(dev); free(mnt_point); free(fstype); - } - fclose(f); - } -#endif } @@ -352,32 +264,6 @@ void SysAddCDROMPrefs(void) if (PrefsFindBool("nocdrom")) return; -#if defined(__linux__) - if (access("/dev/.devfsd", F_OK) < 0) - PrefsAddString("cdrom", "/dev/cdrom"); - else { - DIR *cd_dir = opendir("/dev/cdroms"); - if (cd_dir) { - struct dirent *cdrom_dev; - while ((cdrom_dev = readdir(cd_dir)) != NULL) { - if (strcmp(cdrom_dev->d_name, ".") != 0 && strcmp(cdrom_dev->d_name, "..") != 0) { - char cd_dev[20]; - sprintf(cd_dev, "/dev/cdroms/%s", cdrom_dev->d_name); - PrefsAddString("cdrom", cd_dev); - } - } - closedir(cd_dir); - } - } -#elif defined __MACOSX__ - // There is no predefined path for CD-ROMs on MacOS X. Rather, we - // define a single fake CD-ROM entry for the emulated MacOS. - // XXX this means we handle only CD-ROM drive at a time, wherever - // the disk is, the latest one is used. - PrefsAddString("cdrom", "/dev/poll/cdrom"); -#elif defined(__FreeBSD__) || defined(__NetBSD__) - PrefsAddString("cdrom", "/dev/cd0c"); -#endif } @@ -387,21 +273,7 @@ void SysAddCDROMPrefs(void) void SysAddSerialPrefs(void) { -#if defined(__linux__) - if (access("/dev/.devfsd", F_OK) < 0) { - PrefsAddString("seriala", "/dev/ttyS0"); - PrefsAddString("serialb", "/dev/ttyS1"); - } else { - PrefsAddString("seriala", "/dev/tts/0"); - PrefsAddString("serialb", "/dev/tts/1"); - } -#elif defined(__FreeBSD__) - PrefsAddString("seriala", "/dev/cuaa0"); - PrefsAddString("serialb", "/dev/cuaa1"); -#elif defined(__NetBSD__) - PrefsAddString("seriala", "/dev/tty00"); - PrefsAddString("serialb", "/dev/tty01"); -#elif defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) #if defined(AQUA) || defined(HAVE_FRAMEWORK_COREFOUNDATION) extern void DarwinAddSerialPrefs(void); @@ -422,26 +294,7 @@ void SysAddSerialPrefs(void) static bool cdrom_open_1(mac_file_handle *fh) { -#if defined __MACOSX__ - // In OS X, the device name is OK for sending ioctls to, - // but not for reading raw CDROM data from. - // (it seems to have extra data padded in) - // - // So, we keep the already opened file handle, - // and open a slightly different file for CDROM data - // - fh->ioctl_fd = fh->fd; - fh->ioctl_name = fh->name; - fh->fd = -1; - fh->name = (char *)malloc(strlen(fh->ioctl_name) + 3); - if (fh->name) { - strcpy(fh->name, fh->ioctl_name); - strcat(fh->name, "s1"); - fh->fd = open(fh->name, O_RDONLY, O_NONBLOCK); - } - if (fh->ioctl_fd < 0) - return false; -#endif + return true; } @@ -472,16 +325,7 @@ void cdrom_close(mac_file_handle *fh) free(fh->name); fh->name = NULL; } -#if defined __MACOSX__ - if (fh->ioctl_fd >= 0) { - close(fh->ioctl_fd); - fh->ioctl_fd = -1; - } - if (fh->ioctl_name) { - free(fh->ioctl_name); - fh->ioctl_name = NULL; - } -#endif + } @@ -491,30 +335,7 @@ void cdrom_close(mac_file_handle *fh) static bool is_drive_mounted(const char *dev_name, char *mount_name) { -#ifdef __linux__ - FILE *f = fopen("/proc/mounts", "r"); - if (f) { - char line[256]; - while(fgets(line, 255, f)) { - // Read line - int len = strlen(line); - if (len == 0) - continue; - line[len-1] = 0; - // Parse line - if (strncmp(line, dev_name, strlen(dev_name)) == 0) { - mount_name[0] = 0; - char *dummy; - sscanf(line, "%as %s", &dummy, mount_name); - free(dummy); - fclose(f); - return true; - } - } - fclose(f); - } -#endif return false; } @@ -530,51 +351,29 @@ static mac_file_handle *open_filehandle(const char *name) fh->name = strdup(name); fh->fd = -1; fh->generic_disk = NULL; -#if defined __MACOSX__ - fh->ioctl_fd = -1; - fh->ioctl_name = NULL; -#endif + return fh; } void *Sys_open(const char *name, bool read_only) { bool is_file = strncmp(name, "/dev/", 5) != 0; -#if defined(__FreeBSD__) - // SCSI IDE - bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0 || strncmp(name, "/dev/acd", 8) == 0; -#else + bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0; -#endif + bool is_floppy = strncmp(name, "/dev/fd", 7) == 0; bool is_polled_media = strncmp(name, "/dev/poll/", 10) == 0; if (is_floppy) // Floppy open fails if there's no disk inserted is_polled_media = true; -#if defined __MACOSX__ - // There is no set filename in /dev which is the cdrom, - // so we have to see if it is any of the devices that we found earlier - { - int index = 0; - const char *str; - while ((str = PrefsFindString("cdrom", index++)) != NULL) { - if (is_polled_media || strcmp(str, name) == 0) { - is_cdrom = true; - read_only = true; - break; - } - } - } -#endif - D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write")); // Check if write access is allowed, set read-only flag if not if (!read_only && access(name, W_OK)) read_only = true; - // Print warning message and eventually unmount drive when this is an HFS volume mounted under Linux (double mounting will corrupt the volume) + // Print warning message and eventually unmount drive when this is an HFS volume mounted under (double mounting will corrupt the volume) char mount_name[256]; if (!is_file && !read_only && is_drive_mounted(name, mount_name)) { char str[512]; @@ -590,19 +389,6 @@ void *Sys_open(const char *name, bool read_only) // Open file/device -#if defined(BINCUE) - void *binfd = open_bincue(name); - if (binfd) { - mac_file_handle *fh = open_filehandle(name); - D(bug("opening %s as bincue\n", name)); - fh->bincue_fd = binfd; - fh->is_bincue = true; - fh->read_only = true; - fh->is_media_present = true; - sys_add_mac_file_handle(fh); - return fh; - } -#endif for (int i = 0; disk_factories[i]; ++i) { @@ -623,26 +409,9 @@ void *Sys_open(const char *name, bool read_only) } int open_flags = (read_only ? O_RDONLY : O_RDWR); -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MACOSX__) - open_flags |= (is_cdrom ? O_NONBLOCK : 0); -#endif -#if defined(__MACOSX__) - open_flags |= (is_file ? O_EXLOCK | O_NONBLOCK : 0); -#endif + int fd = open(name, open_flags); -#if defined(__MACOSX__) - if (fd < 0 && (open_flags & O_EXLOCK)) { - if (errno == EOPNOTSUPP) { - // File system does not support locking. Try again without. - open_flags &= ~O_EXLOCK; - fd = open(name, open_flags); - } else if (errno == EAGAIN) { - // File is likely already locked by another process. - printf("WARNING: Cannot open %s (%s)\n", name, strerror(errno)); - return NULL; - } - } -#endif + if (fd < 0 && !read_only) { // Read-write failed, try read-only read_only = true; @@ -670,35 +439,8 @@ void *Sys_open(const char *name, bool read_only) fh->is_media_present = true; if (S_ISBLK(st.st_mode)) { fh->is_cdrom = is_cdrom; -#if defined(__linux__) - fh->is_floppy = (MAJOR(st.st_rdev) == FLOPPY_MAJOR); -#ifdef CDROM_GET_CAPABILITY - if (is_cdrom) { - fh->cdrom_cap = ioctl(fh->fd, CDROM_GET_CAPABILITY); - if (fh->cdrom_cap < 0) - fh->cdrom_cap = 0; - } -#endif -#elif defined(__FreeBSD__) - fh->is_floppy = ((st.st_rdev >> 16) == 2); -#ifdef CDIOCCAPABILITY - if (is_cdrom) { - if (ioctl(fh->fd, CDIOCCAPABILITY, &fh->cdrom_cap) < 0) - memset(&fh->cdrom_cap, 0, sizeof(fh->cdrom_cap)); - } -#endif -#elif defined(__NetBSD__) - fh->is_floppy = ((st.st_rdev >> 16) == 2); -#endif } -#if defined __MACOSX__ - if (is_cdrom) { - fh->is_cdrom = true; - fh->is_floppy = false; - if (cdrom_open_1(fh)) - fh->is_media_present = true; - } -#endif + } } if (fh->is_floppy && first_floppy == NULL) @@ -724,10 +466,6 @@ void Sys_close(void *arg) sys_remove_mac_file_handle(fh); -#if defined(BINCUE) - if (fh->is_bincue) - close_bincue(fh->bincue_fd); -#endif if (fh->generic_disk) delete fh->generic_disk; @@ -752,10 +490,6 @@ size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length) if (!fh) return 0; -#if defined(BINCUE) - if (fh->is_bincue) - return read_bincue(fh->bincue_fd, buffer, offset, length); -#endif if (fh->generic_disk) return fh->generic_disk->read(buffer, offset, length); @@ -802,10 +536,6 @@ loff_t SysGetFileSize(void *arg) if (!fh) return true; -#if defined(BINCUE) - if (fh->is_bincue) - return size_bincue(fh->bincue_fd); -#endif if (fh->generic_disk) return fh->file_size; @@ -813,25 +543,9 @@ loff_t SysGetFileSize(void *arg) if (fh->is_file) return fh->file_size; else { -#if defined(__linux__) - long blocks; - if (ioctl(fh->fd, BLKGETSIZE, &blocks) < 0) - return 0; - D(bug(" BLKGETSIZE returns %d blocks\n", blocks)); - return (loff_t)blocks * 512; -#elif defined __MACOSX__ - uint32 block_size; - if (ioctl(fh->ioctl_fd, DKIOCGETBLOCKSIZE, &block_size) < 0) - return 0; - D(bug(" DKIOCGETBLOCKSIZE returns %lu bytes\n", (unsigned long)block_size)); - uint64 block_count; - if (ioctl(fh->ioctl_fd, DKIOCGETBLOCKCOUNT, &block_count) < 0) - return 0; - D(bug(" DKIOCGETBLOCKCOUNT returns %llu blocks\n", (unsigned long long)block_count)); - return block_count * block_size; -#else + return lseek(fh->fd, 0, SEEK_END) - fh->start_byte; -#endif + } } @@ -846,29 +560,7 @@ void SysEject(void *arg) if (!fh) return; -#if defined(__linux__) - if (fh->is_floppy) { - if (fh->fd >= 0) { - fsync(fh->fd); - ioctl(fh->fd, FDFLUSH); - ioctl(fh->fd, FDEJECT); - close(fh->fd); // Close and reopen so the driver will see the media change - } - fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR); - } else if (fh->is_cdrom) { - ioctl(fh->fd, CDROMEJECT); - close(fh->fd); // Close and reopen so the driver will see the media change - fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK); - } -#elif defined(__FreeBSD__) || defined(__NetBSD__) - if (fh->is_floppy) { - fsync(fh->fd); - } else if (fh->is_cdrom) { - ioctl(fh->fd, CDIOCEJECT); - close(fh->fd); // Close and reopen so the driver will see the media change - fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK); - } -#elif defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) if (fh->is_cdrom && fh->is_media_present) { close(fh->fd); fh->fd = -1; @@ -919,16 +611,6 @@ bool SysIsReadOnly(void *arg) if (!fh) return true; -#if defined(__linux__) - if (fh->is_floppy) { - if (fh->fd >= 0) { - struct floppy_drive_struct stat; - ioctl(fh->fd, FDGETDRVSTAT, &stat); - return !(stat.flags & FD_DISK_WRITABLE); - } else - return true; - } else -#endif return fh->read_only; } @@ -971,47 +653,6 @@ bool SysIsDiskInserted(void *arg) if (fh->is_file) { return true; -#if defined(__linux__) - } else if (fh->is_floppy) { - char block[512]; - lseek(fh->fd, 0, SEEK_SET); - ssize_t actual = read(fh->fd, block, 512); - if (actual < 0) { - close(fh->fd); // Close and reopen so the driver will see the media change - fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR); - actual = read(fh->fd, block, 512); - } - return actual == 512; - } else if (fh->is_cdrom) { -#ifdef CDROM_MEDIA_CHANGED - if (fh->cdrom_cap & CDC_MEDIA_CHANGED) { - // If we don't do this, all attempts to read from a disc fail - // once the tray has been opened (altough the TOC reads fine). - // Can somebody explain this to me? - if (ioctl(fh->fd, CDROM_MEDIA_CHANGED) == 1) { - close(fh->fd); - fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK); - } - } -#endif -#ifdef CDROM_DRIVE_STATUS - if (fh->cdrom_cap & CDC_DRIVE_STATUS) { - return ioctl(fh->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK; - } -#endif - cdrom_tochdr header; - return ioctl(fh->fd, CDROMREADTOCHDR, &header) == 0; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - } else if (fh->is_floppy) { - return false; //!! - } else if (fh->is_cdrom) { - struct ioc_toc_header header; - return ioctl(fh->fd, CDIOREADTOCHEADER, &header) == 0; -#elif defined __MACOSX__ - } else if (fh->is_cdrom || fh->is_floppy) { - return fh->is_media_present; -#endif - } else return true; } @@ -1027,10 +668,6 @@ void SysPreventRemoval(void *arg) if (!fh) return; -#if defined(__linux__) && defined(CDROM_LOCKDOOR) - if (fh->is_cdrom) - ioctl(fh->fd, CDROM_LOCKDOOR, 1); -#endif } @@ -1044,10 +681,6 @@ void SysAllowRemoval(void *arg) if (!fh) return; -#if defined(__linux__) && defined(CDROM_LOCKDOOR) - if (fh->is_cdrom) - ioctl(fh->fd, CDROM_LOCKDOOR, 0); -#endif } @@ -1061,138 +694,10 @@ bool SysCDReadTOC(void *arg, uint8 *toc) if (!fh) return false; -#if defined(BINCUE) - if (fh->is_bincue) - return readtoc_bincue(fh->bincue_fd, toc); -#endif - if (fh->is_cdrom) { -#if defined(__linux__) - uint8 *p = toc + 2; - - // Header - cdrom_tochdr header; - if (ioctl(fh->fd, CDROMREADTOCHDR, &header) < 0) - return false; - *p++ = header.cdth_trk0; - *p++ = header.cdth_trk1; - - // Tracks - cdrom_tocentry entry; - for (int i=header.cdth_trk0; i<=header.cdth_trk1; i++) { - entry.cdte_track = i; - entry.cdte_format = CDROM_MSF; - if (ioctl(fh->fd, CDROMREADTOCENTRY, &entry) < 0) - return false; - *p++ = 0; - *p++ = (entry.cdte_adr << 4) | entry.cdte_ctrl; - *p++ = entry.cdte_track; - *p++ = 0; - *p++ = 0; - *p++ = entry.cdte_addr.msf.minute; - *p++ = entry.cdte_addr.msf.second; - *p++ = entry.cdte_addr.msf.frame; - } - - // Leadout track - entry.cdte_track = CDROM_LEADOUT; - entry.cdte_format = CDROM_MSF; - if (ioctl(fh->fd, CDROMREADTOCENTRY, &entry) < 0) - return false; - *p++ = 0; - *p++ = (entry.cdte_adr << 4) | entry.cdte_ctrl; - *p++ = entry.cdte_track; - *p++ = 0; - *p++ = 0; - *p++ = entry.cdte_addr.msf.minute; - *p++ = entry.cdte_addr.msf.second; - *p++ = entry.cdte_addr.msf.frame; - - // TOC size - int toc_size = p - toc; - *toc++ = toc_size >> 8; - *toc++ = toc_size & 0xff; - return true; -#elif defined __MACOSX__ && defined MAC_OS_X_VERSION_10_2 - if (fh->is_media_present) { - extern bool DarwinCDReadTOC(char *name, uint8 *toc); - return DarwinCDReadTOC(fh->name, toc); - } return false; -#elif defined(__FreeBSD__) - uint8 *p = toc + 2; - // Header - struct ioc_toc_header header; - if (ioctl(fh->fd, CDIOREADTOCHEADER, &header) < 0) - return false; - *p++ = header.starting_track; - *p++ = header.ending_track; - - // Tracks - struct ioc_read_toc_single_entry entry; - for (int i=header.starting_track; i<=header.ending_track; i++) { - entry.track = i; - entry.address_format = CD_MSF_FORMAT; - if (ioctl(fh->fd, CDIOREADTOCENTRY, &entry) < 0) - return false; - *p++ = 0; - *p++ = (entry.entry.addr_type << 4) | entry.entry.control; - *p++ = entry.entry.track; - *p++ = 0; - *p++ = 0; - *p++ = entry.entry.addr.msf.minute; - *p++ = entry.entry.addr.msf.second; - *p++ = entry.entry.addr.msf.frame; - } - - // Leadout track - entry.track = CD_TRACK_INFO; - entry.address_format = CD_MSF_FORMAT; - if (ioctl(fh->fd, CDIOREADTOCENTRY, &entry) < 0) - return false; - *p++ = 0; - *p++ = (entry.entry.addr_type << 4) | entry.entry.control; - *p++ = entry.entry.track; - *p++ = 0; - *p++ = 0; - *p++ = entry.entry.addr.msf.minute; - *p++ = entry.entry.addr.msf.second; - *p++ = entry.entry.addr.msf.frame; - - // TOC size - int toc_size = p - toc; - *toc++ = toc_size >> 8; - *toc++ = toc_size & 0xff; - return true; -#elif defined(__NetBSD__) - uint8 *p = toc + 2; - - // Header - struct ioc_toc_header header; - if (ioctl(fh->fd, CDIOREADTOCHEADER, &header) < 0) - return false; - *p++ = header.starting_track; - *p++ = header.ending_track; - - // Tracks (this is nice... :-) - struct ioc_read_toc_entry entries; - entries.address_format = CD_MSF_FORMAT; - entries.starting_track = 1; - entries.data_len = 800; - entries.data = (cd_toc_entry *)p; - if (ioctl(fh->fd, CDIOREADTOCENTRIES, &entries) < 0) - return false; - - // TOC size - int toc_size = p - toc; - *toc++ = toc_size >> 8; - *toc++ = toc_size & 0xff; - return true; -#else - return false; -#endif } else return false; } @@ -1208,61 +713,10 @@ bool SysCDGetPosition(void *arg, uint8 *pos) if (!fh) return false; -#if defined(BINCUE) - if (fh->is_bincue) - return GetPosition_bincue(fh->bincue_fd, pos); -#endif - if (fh->is_cdrom) { -#if defined(__linux__) - cdrom_subchnl chan; - chan.cdsc_format = CDROM_MSF; - if (ioctl(fh->fd, CDROMSUBCHNL, &chan) < 0) - return false; - *pos++ = 0; - *pos++ = chan.cdsc_audiostatus; - *pos++ = 0; - *pos++ = 12; // Sub-Q data length - *pos++ = 0; - *pos++ = (chan.cdsc_adr << 4) | chan.cdsc_ctrl; - *pos++ = chan.cdsc_trk; - *pos++ = chan.cdsc_ind; - *pos++ = 0; - *pos++ = chan.cdsc_absaddr.msf.minute; - *pos++ = chan.cdsc_absaddr.msf.second; - *pos++ = chan.cdsc_absaddr.msf.frame; - *pos++ = 0; - *pos++ = chan.cdsc_reladdr.msf.minute; - *pos++ = chan.cdsc_reladdr.msf.second; - *pos++ = chan.cdsc_reladdr.msf.frame; - return true; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - struct ioc_read_subchannel chan; - chan.data_format = CD_MSF_FORMAT; - chan.address_format = CD_MSF_FORMAT; - chan.track = CD_CURRENT_POSITION; - if (ioctl(fh->fd, CDIOCREADSUBCHANNEL, &chan) < 0) - return false; - *pos++ = 0; - *pos++ = chan.data->header.audio_status; - *pos++ = 0; - *pos++ = 12; // Sub-Q data length - *pos++ = 0; - *pos++ = (chan.data->what.position.addr_type << 4) | chan.data->what.position.control; - *pos++ = chan.data->what.position.track_number; - *pos++ = chan.data->what.position.index_number; - *pos++ = 0; - *pos++ = chan.data->what.position.absaddr.msf.minute; - *pos++ = chan.data->what.position.absaddr.msf.second; - *pos++ = chan.data->what.position.absaddr.msf.frame; - *pos++ = 0; - *pos++ = chan.data->what.position.reladdr.msf.minute; - *pos++ = chan.data->what.position.reladdr.msf.second; - *pos++ = chan.data->what.position.reladdr.msf.frame; - return true; -#else + return false; -#endif + } else return false; } @@ -1278,33 +732,11 @@ bool SysCDPlay(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, uint8 end if (!fh) return false; -#if defined(BINCUE) - if (fh->is_bincue) - return CDPlay_bincue(fh->bincue_fd, start_m, start_s, start_f, end_m, end_s, end_f); -#endif if (fh->is_cdrom) { -#if defined(__linux__) - cdrom_msf play; - play.cdmsf_min0 = start_m; - play.cdmsf_sec0 = start_s; - play.cdmsf_frame0 = start_f; - play.cdmsf_min1 = end_m; - play.cdmsf_sec1 = end_s; - play.cdmsf_frame1 = end_f; - return ioctl(fh->fd, CDROMPLAYMSF, &play) == 0; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - struct ioc_play_msf play; - play.start_m = start_m; - play.start_s = start_s; - play.start_f = start_f; - play.end_m = end_m; - play.end_s = end_s; - play.end_f = end_f; - return ioctl(fh->fd, CDIOCPLAYMSF, &play) == 0; -#else + return false; -#endif + } else return false; } @@ -1320,19 +752,10 @@ bool SysCDPause(void *arg) if (!fh) return false; -#if defined(BINCUE) - if (fh->is_bincue) - return CDPause_bincue(fh->bincue_fd); -#endif - if (fh->is_cdrom) { -#if defined(__linux__) - return ioctl(fh->fd, CDROMPAUSE) == 0; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - return ioctl(fh->fd, CDIOCPAUSE) == 0; -#else + return false; -#endif + } else return false; } @@ -1348,20 +771,11 @@ bool SysCDResume(void *arg) if (!fh) return false; -#if defined(BINCUE) - if (fh->is_bincue) - return CDResume_bincue(fh->bincue_fd); -#endif - if (fh->is_cdrom) { -#if defined(__linux__) - return ioctl(fh->fd, CDROMRESUME) == 0; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - return ioctl(fh->fd, CDIOCRESUME) == 0; -#else + return false; -#endif + } else return false; } @@ -1377,20 +791,10 @@ bool SysCDStop(void *arg, uint8 lead_out_m, uint8 lead_out_s, uint8 lead_out_f) if (!fh) return false; -#if defined(BINCUE) - if (fh->is_bincue) - return CDStop_bincue(fh->bincue_fd); -#endif - - if (fh->is_cdrom) { -#if defined(__linux__) - return ioctl(fh->fd, CDROMSTOP) == 0; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - return ioctl(fh->fd, CDIOCSTOP) == 0; -#else + return false; -#endif + } else return false; } @@ -1406,7 +810,6 @@ bool SysCDScan(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, bool reve if (!fh) return false; - // Not supported under Linux return false; } @@ -1422,17 +825,7 @@ void SysCDSetVolume(void *arg, uint8 left, uint8 right) return; if (fh->is_cdrom) { -#if defined(__linux__) - cdrom_volctrl vol; - vol.channel0 = vol.channel2 = left; - vol.channel1 = vol.channel3 = right; - ioctl(fh->fd, CDROMVOLCTRL, &vol); -#elif defined(__FreeBSD__) || defined(__NetBSD__) - struct ioc_vol vol; - vol.vol[0] = vol.vol[2] = left; - vol.vol[1] = vol.vol[3] = right; - ioctl(fh->fd, CDIOCSETVOL, &vol); -#endif + } } @@ -1449,16 +842,6 @@ void SysCDGetVolume(void *arg, uint8 &left, uint8 &right) left = right = 0; if (fh->is_cdrom) { -#if defined(__linux__) - cdrom_volctrl vol; - ioctl(fh->fd, CDROMVOLREAD, &vol); - left = vol.channel0; - right = vol.channel1; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - struct ioc_vol vol; - ioctl(fh->fd, CDIOCGETVOL, &vol); - left = vol.vol[0]; - right = vol.vol[1]; -#endif + } } diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index df291939..285b5e63 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -66,25 +66,6 @@ #include #endif -#ifdef ENABLE_NATIVE_M68K - -/* Mac and host address space are the same */ -#define REAL_ADDRESSING 1 - -/* Using 68k natively */ -#define EMULATED_68K 0 - -/* Mac ROM is not write protected */ -#define ROM_IS_WRITE_PROTECTED 0 -#define USE_SCRATCHMEM_SUBTERFUGE 1 - -#else - -/* Mac and host address space are distinct */ -#ifndef REAL_ADDRESSING -#define REAL_ADDRESSING 0 -#endif - /* Using 68k emulator */ #define EMULATED_68K 1 @@ -92,21 +73,13 @@ #define USE_PREFETCH_BUFFER 0 /* Mac ROM is write protected when banked memory is used */ -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING # define ROM_IS_WRITE_PROTECTED 0 # define USE_SCRATCHMEM_SUBTERFUGE 1 #else # define ROM_IS_WRITE_PROTECTED 1 #endif -#endif - -/* Direct Addressing requires Video on SEGV signals in plain X11 mode */ -#if DIRECT_ADDRESSING && (!ENABLE_VOSF && !USE_SDL_VIDEO) -# undef ENABLE_VOSF -# define ENABLE_VOSF 1 -#endif - /* ExtFS is supported */ #define SUPPORTS_EXTFS 1 @@ -117,11 +90,6 @@ #ifdef HAVE_PTHREADS #define USE_PTHREADS_SERVICES #endif -#if EMULATED_68K -#if defined(__NetBSD__) -#define USE_CPU_EMUL_SERVICES -#endif -#endif #ifdef USE_CPU_EMUL_SERVICES #undef USE_PTHREADS_SERVICES #endif @@ -185,10 +153,11 @@ typedef char * caddr_t; #endif /* Time data type for Time Manager emulation */ -#ifdef HAVE_CLOCK_GETTIME -typedef struct timespec tm_time_t; -#elif defined(__MACH__) + +#if defined(__MACH__) typedef mach_timespec_t tm_time_t; +#elif defined(HAVE_CLOCK_GETTIME) +typedef struct timespec tm_time_t; #else typedef struct timeval tm_time_t; #endif @@ -221,107 +190,6 @@ typedef uae_u32 uaecptr; extern uint64 GetTicks_usec(void); extern void Delay_usec(uint32 usec); -/* Spinlocks */ -#ifdef __GNUC__ - -#if defined(__powerpc__) || defined(__ppc__) -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - __asm__ __volatile__("0: lwarx %0,0,%1\n" - " xor. %0,%3,%0\n" - " bne 1f\n" - " stwcx. %2,0,%1\n" - " bne- 0b\n" - "1: " - : "=&r" (ret) - : "r" (p), "r" (1), "r" (0) - : "cr0", "memory"); - return ret; -} -#endif - -/* FIXME: SheepShaver occasionnally hangs with those locks */ -#if 0 && (defined(__i386__) || defined(__x86_64__)) -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - long int ret; - /* Note: the "xchg" instruction does not need a "lock" prefix */ - __asm__ __volatile__("xchgl %k0, %1" - : "=r" (ret), "=m" (*p) - : "0" (1), "m" (*p) - : "memory"); - return ret; -} -#endif - -#ifdef __s390__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - - __asm__ __volatile__("0: cs %0,%1,0(%2)\n" - " jl 0b" - : "=&d" (ret) - : "r" (1), "a" (p), "0" (*p) - : "cc", "memory" ); - return ret; -} -#endif - -#ifdef __alpha__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - unsigned long one; - - __asm__ __volatile__("0: mov 1,%2\n" - " ldl_l %0,%1\n" - " stl_c %2,%1\n" - " beq %2,1f\n" - ".subsection 2\n" - "1: br 0b\n" - ".previous" - : "=r" (ret), "=m" (*p), "=r" (one) - : "m" (*p)); - return ret; -} -#endif - -#ifdef __sparc__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - - __asm__ __volatile__("ldstub [%1], %0" - : "=r" (ret) - : "r" (p) - : "memory"); - - return (ret ? 1 : 0); -} -#endif - -#ifdef __arm__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - register unsigned int ret; - __asm__ __volatile__("swp %0, %1, [%2]" - : "=r"(ret) - : "0"(1), "r"(p)); - - return ret; -} -#endif - -#endif /* __GNUC__ */ - typedef volatile int spinlock_t; static const spinlock_t SPIN_LOCK_UNLOCKED = 0; @@ -357,25 +225,6 @@ static inline int spin_trylock(spinlock_t *lock) } #endif -/* X11 display fast locks */ -#ifdef HAVE_SPINLOCKS -#define X11_LOCK_TYPE spinlock_t -#define X11_LOCK_INIT SPIN_LOCK_UNLOCKED -#define XDisplayLock() spin_lock(&x_display_lock) -#define XDisplayUnlock() spin_unlock(&x_display_lock) -#elif defined(HAVE_PTHREADS) -#define X11_LOCK_TYPE pthread_mutex_t -#define X11_LOCK_INIT PTHREAD_MUTEX_INITIALIZER -#define XDisplayLock() pthread_mutex_lock(&x_display_lock); -#define XDisplayUnlock() pthread_mutex_unlock(&x_display_lock); -#else -#define XDisplayLock() -#define XDisplayUnlock() -#endif -#ifdef X11_LOCK_TYPE -extern X11_LOCK_TYPE x_display_lock; -#endif - #ifdef HAVE_PTHREADS /* Centralized pthread attribute setup */ void Set_pthread_attr(pthread_attr_t *attr, int priority); diff --git a/BasiliskII/src/Unix/timer_unix.cpp b/BasiliskII/src/Unix/timer_unix.cpp index 9e227d02..a73e4280 100644 --- a/BasiliskII/src/Unix/timer_unix.cpp +++ b/BasiliskII/src/Unix/timer_unix.cpp @@ -27,11 +27,6 @@ #define DEBUG 0 #include "debug.h" -// For NetBSD with broken pthreads headers -#ifndef CLOCK_REALTIME -#define CLOCK_REALTIME 0 -#endif - #if defined(__MACH__) #include #include @@ -57,14 +52,14 @@ static inline void mach_current_time(tm_time_t &t) { void Microseconds(uint32 &hi, uint32 &lo) { D(bug("Microseconds\n")); -#if defined(HAVE_CLOCK_GETTIME) - struct timespec t; - clock_gettime(CLOCK_REALTIME, &t); - uint64 tl = (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000; -#elif defined(__MACH__) +#if defined(__MACH__) tm_time_t t; mach_current_time(t); uint64 tl = (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000; +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + uint64 tl = (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000; #else struct timeval t; gettimeofday(&t, NULL); @@ -91,10 +86,10 @@ uint32 TimerDateTime(void) void timer_current_time(tm_time_t &t) { -#ifdef HAVE_CLOCK_GETTIME - clock_gettime(CLOCK_REALTIME, &t); -#elif defined(__MACH__) +#if defined(__MACH__) mach_current_time(t); +#elif defined(HAVE_CLOCK_GETTIME) + clock_gettime(CLOCK_REALTIME, &t); #else gettimeofday(&t, NULL); #endif @@ -229,14 +224,14 @@ int32 timer_host2mac_time(tm_time_t hosttime) uint64 GetTicks_usec(void) { -#ifdef HAVE_CLOCK_GETTIME - struct timespec t; - clock_gettime(CLOCK_REALTIME, &t); - return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000; -#elif defined(__MACH__) +#if defined(__MACH__) tm_time_t t; mach_current_time(t); return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000; +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000; #else struct timeval t; gettimeofday(&t, NULL); @@ -251,17 +246,8 @@ uint64 GetTicks_usec(void) * the highest accuracy possible) */ -#if defined(linux) -// Linux select() changes its timeout parameter upon return to contain -// the remaining time. Most other unixen leave it unchanged or undefined. -#define SELECT_SETS_REMAINING -#elif defined(__FreeBSD__) || defined(__sun__) || (defined(__MACH__) && defined(__APPLE__)) +#if (defined(__MACH__) && defined(__APPLE__)) #define USE_NANOSLEEP -#elif defined(HAVE_PTHREADS) && defined(sgi) -// SGI pthreads has a bug when using pthreads+signals+nanosleep, -// so instead of using nanosleep, wait on a CV which is never signalled. -#include -#define USE_COND_TIMEDWAIT #endif void Delay_usec(uint32 usec) @@ -283,7 +269,6 @@ void Delay_usec(uint32 usec) #endif #endif - // Set the timeout interval - Linux only needs to do this once #if defined(SELECT_SETS_REMAINING) tv.tv_sec = 0; tv.tv_usec = usec; diff --git a/BasiliskII/src/Unix/tinyxml2.cpp b/BasiliskII/src/Unix/tinyxml2.cpp deleted file mode 100755 index 4cd8695d..00000000 --- a/BasiliskII/src/Unix/tinyxml2.cpp +++ /dev/null @@ -1,2095 +0,0 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include "tinyxml2.h" - -#include // yes, this one new style header, is in the Android SDK. -# ifdef ANDROID_NDK -# include -#else -# include -#endif - -static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF -static const char LF = LINE_FEED; -static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out -static const char CR = CARRIAGE_RETURN; -static const char SINGLE_QUOTE = '\''; -static const char DOUBLE_QUOTE = '\"'; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// ef bb bf (Microsoft "lead bytes") - designates UTF-8 - -static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - -#define DELETE_NODE( node ) { \ - if ( node ) { \ - MemPool* pool = node->_memPool; \ - node->~XMLNode(); \ - pool->Free( node ); \ - } \ - } -#define DELETE_ATTRIBUTE( attrib ) { \ - if ( attrib ) { \ - MemPool* pool = attrib->_memPool; \ - attrib->~XMLAttribute(); \ - pool->Free( attrib ); \ - } \ - } - -namespace tinyxml2 -{ - -struct Entity { - const char* pattern; - int length; - char value; -}; - -static const int NUM_ENTITIES = 5; -static const Entity entities[NUM_ENTITIES] = { - { "quot", 4, DOUBLE_QUOTE }, - { "amp", 3, '&' }, - { "apos", 4, SINGLE_QUOTE }, - { "lt", 2, '<' }, - { "gt", 2, '>' } -}; - - -StrPair::~StrPair() -{ - Reset(); -} - - -void StrPair::Reset() -{ - if ( _flags & NEEDS_DELETE ) { - delete [] _start; - } - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::SetStr( const char* str, int flags ) -{ - Reset(); - size_t len = strlen( str ); - _start = new char[ len+1 ]; - memcpy( _start, str, len+1 ); - _end = _start + len; - _flags = flags | NEEDS_DELETE; -} - - -char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) -{ - TIXMLASSERT( endTag && *endTag ); - - char* start = p; // fixme: hides a member - char endChar = *endTag; - size_t length = strlen( endTag ); - - // Inner loop of text parsing. - while ( *p ) { - if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { - Set( start, p, strFlags ); - return p + length; - } - ++p; - } - return 0; -} - - -char* StrPair::ParseName( char* p ) -{ - char* start = p; - - if ( !start || !(*start) ) { - return 0; - } - - while( *p && ( p == start ? XMLUtil::IsNameStartChar( *p ) : XMLUtil::IsNameChar( *p ) )) { - ++p; - } - - if ( p > start ) { - Set( start, p, 0 ); - return p; - } - return 0; -} - - -void StrPair::CollapseWhitespace() -{ - // Trim leading space. - _start = XMLUtil::SkipWhiteSpace( _start ); - - if ( _start && *_start ) { - char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( *p ) { - if ( XMLUtil::IsWhiteSpace( *p )) { - p = XMLUtil::SkipWhiteSpace( p ); - if ( *p == 0 ) { - break; // don't write to q; this trims the trailing space. - } - *q = ' '; - ++q; - } - *q = *p; - ++q; - ++p; - } - *q = 0; - } -} - - -const char* StrPair::GetStr() -{ - if ( _flags & NEEDS_FLUSH ) { - *_end = 0; - _flags ^= NEEDS_FLUSH; - - if ( _flags ) { - char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( p < _end ) { - if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { - // CR-LF pair becomes LF - // CR alone becomes LF - // LF-CR becomes LF - if ( *(p+1) == LF ) { - p += 2; - } - else { - ++p; - } - *q++ = LF; - } - else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { - if ( *(p+1) == CR ) { - p += 2; - } - else { - ++p; - } - *q++ = LF; - } - else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { - // Entities handled by tinyXML2: - // - special entities in the entity table [in/out] - // - numeric character reference [in] - // 中 or 中 - - if ( *(p+1) == '#' ) { - char buf[10] = { 0 }; - int len; - p = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); - for( int i=0; i(p); - // Check for BOM: - if ( *(pu+0) == TIXML_UTF_LEAD_0 - && *(pu+1) == TIXML_UTF_LEAD_1 - && *(pu+2) == TIXML_UTF_LEAD_2 ) { - *bom = true; - p += 3; - } - return p; -} - - -void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) { - *length = 1; - } - else if ( input < 0x800 ) { - *length = 2; - } - else if ( input < 0x10000 ) { - *length = 3; - } - else if ( input < 0x200000 ) { - *length = 4; - } - else { - *length = 0; // This code won't covert this correctly anyway. - return; - } - - output += *length; - - // Scary scary fall throughs. - switch (*length) { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - default: - break; - } -} - - -const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) -{ - // Presume an entity, and pull it out. - *length = 0; - - if ( *(p+1) == '#' && *(p+2) ) { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) { - // Hexadecimal. - if ( !*(p+3) ) { - return 0; - } - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) { - return 0; - } - - delta = q-p; - --q; - - while ( *q != 'x' ) { - if ( *q >= '0' && *q <= '9' ) { - ucs += mult * (*q - '0'); - } - else if ( *q >= 'a' && *q <= 'f' ) { - ucs += mult * (*q - 'a' + 10); - } - else if ( *q >= 'A' && *q <= 'F' ) { - ucs += mult * (*q - 'A' + 10 ); - } - else { - return 0; - } - mult *= 16; - --q; - } - } - else { - // Decimal. - if ( !*(p+2) ) { - return 0; - } - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) { - return 0; - } - - delta = q-p; - --q; - - while ( *q != '#' ) { - if ( *q >= '0' && *q <= '9' ) { - ucs += mult * (*q - '0'); - } - else { - return 0; - } - mult *= 10; - --q; - } - } - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - return p + delta + 1; - } - return p+1; -} - - -void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); -} - - -void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); -} - - -void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); -} - - -void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%g", v ); -} - - -void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%g", v ); -} - - -bool XMLUtil::ToInt( const char* str, int* value ) -{ - if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) -{ - if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToBool( const char* str, bool* value ) -{ - int ival = 0; - if ( ToInt( str, &ival )) { - *value = (ival==0) ? false : true; - return true; - } - if ( StringEqual( str, "true" ) ) { - *value = true; - return true; - } - else if ( StringEqual( str, "false" ) ) { - *value = false; - return true; - } - return false; -} - - -bool XMLUtil::ToFloat( const char* str, float* value ) -{ - if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToDouble( const char* str, double* value ) -{ - if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { - return true; - } - return false; -} - - -char* XMLDocument::Identify( char* p, XMLNode** node ) -{ - XMLNode* returnNode = 0; - char* start = p; - p = XMLUtil::SkipWhiteSpace( p ); - if( !p || !*p ) { - return p; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: - // - // With a special case: - // - // - // - // - // Where the closing element (/foo) *must* be the next thing after the opening - // element, and the names must match. BUT the tricky bit is that the closing - // element will be read by the child. - // - // 'endTag' is the end tag for this node, it is returned by a call to a child. - // 'parentEnd' is the end tag for the parent, which is filled in and returned. - - while( p && *p ) { - XMLNode* node = 0; - - p = _document->Identify( p, &node ); - if ( p == 0 || node == 0 ) { - break; - } - - StrPair endTag; - p = node->ParseDeep( p, &endTag ); - if ( !p ) { - DELETE_NODE( node ); - node = 0; - if ( !_document->Error() ) { - _document->SetError( XML_ERROR_PARSING, 0, 0 ); - } - break; - } - - // We read the end tag. Return it to the parent. - if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) { - if ( parentEnd ) { - *parentEnd = static_cast(node)->_value; - } - node->_memPool->SetTracked(); // created and then immediately deleted. - DELETE_NODE( node ); - return p; - } - - // Handle an end tag returned to this level. - // And handle a bunch of annoying errors. - XMLElement* ele = node->ToElement(); - if ( ele ) { - if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); - p = 0; - } - else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); - p = 0; - } - else if ( !endTag.Empty() ) { - if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); - p = 0; - } - } - } - if ( p == 0 ) { - DELETE_NODE( node ); - node = 0; - } - if ( node ) { - this->InsertEndChild( node ); - } - } - return 0; -} - -// --------- XMLText ---------- // -char* XMLText::ParseDeep( char* p, StrPair* ) -{ - const char* start = p; - if ( this->CData() ) { - p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 ); - } - return p; - } - else { - int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; - if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { - flags |= StrPair::COLLAPSE_WHITESPACE; - } - - p = _value.ParseText( p, "<", flags ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 ); - } - if ( p && *p ) { - return p-1; - } - } - return 0; -} - - -XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? - text->SetCData( this->CData() ); - return text; -} - - -bool XMLText::ShallowEqual( const XMLNode* compare ) const -{ - return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() )); -} - - -bool XMLText::Accept( XMLVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -// --------- XMLComment ---------- // - -XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLComment::~XMLComment() -{ -} - - -char* XMLComment::ParseDeep( char* p, StrPair* ) -{ - // Comment parses as text. - const char* start = p; - p = _value.ParseText( p, "-->", StrPair::COMMENT ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 ); - } - return p; -} - - -XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? - return comment; -} - - -bool XMLComment::ShallowEqual( const XMLNode* compare ) const -{ - return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() )); -} - - -bool XMLComment::Accept( XMLVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -// --------- XMLDeclaration ---------- // - -XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLDeclaration::~XMLDeclaration() -{ - //printf( "~XMLDeclaration\n" ); -} - - -char* XMLDeclaration::ParseDeep( char* p, StrPair* ) -{ - // Declaration parses as text. - const char* start = p; - p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 ); - } - return p; -} - - -XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? - return dec; -} - - -bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const -{ - return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() )); -} - - - -bool XMLDeclaration::Accept( XMLVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - -// --------- XMLUnknown ---------- // - -XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLUnknown::~XMLUnknown() -{ -} - - -char* XMLUnknown::ParseDeep( char* p, StrPair* ) -{ - // Unknown parses as text. - const char* start = p; - - p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); - } - return p; -} - - -XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? - return text; -} - - -bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const -{ - return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() )); -} - - -bool XMLUnknown::Accept( XMLVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - -// --------- XMLAttribute ---------- // -char* XMLAttribute::ParseDeep( char* p, bool processEntities ) -{ - // Parse using the name rules: bug fix, was using ParseText before - p = _name.ParseName( p ); - if ( !p || !*p ) { - return 0; - } - - // Skip white space before = - p = XMLUtil::SkipWhiteSpace( p ); - if ( !p || *p != '=' ) { - return 0; - } - - ++p; // move up to opening quote - p = XMLUtil::SkipWhiteSpace( p ); - if ( *p != '\"' && *p != '\'' ) { - return 0; - } - - char endTag[2] = { *p, 0 }; - ++p; // move past opening quote - - p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES ); - return p; -} - - -void XMLAttribute::SetName( const char* n ) -{ - _name.SetStr( n ); -} - - -XMLError XMLAttribute::QueryIntValue( int* value ) const -{ - if ( XMLUtil::ToInt( Value(), value )) { - return XML_NO_ERROR; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const -{ - if ( XMLUtil::ToUnsigned( Value(), value )) { - return XML_NO_ERROR; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryBoolValue( bool* value ) const -{ - if ( XMLUtil::ToBool( Value(), value )) { - return XML_NO_ERROR; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryFloatValue( float* value ) const -{ - if ( XMLUtil::ToFloat( Value(), value )) { - return XML_NO_ERROR; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryDoubleValue( double* value ) const -{ - if ( XMLUtil::ToDouble( Value(), value )) { - return XML_NO_ERROR; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -void XMLAttribute::SetAttribute( const char* v ) -{ - _value.SetStr( v ); -} - - -void XMLAttribute::SetAttribute( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -// --------- XMLElement ---------- // -XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( 0 ), - _rootAttribute( 0 ) -{ -} - - -XMLElement::~XMLElement() -{ - while( _rootAttribute ) { - XMLAttribute* next = _rootAttribute->_next; - DELETE_ATTRIBUTE( _rootAttribute ); - _rootAttribute = next; - } -} - - -XMLAttribute* XMLElement::FindAttribute( const char* name ) -{ - XMLAttribute* a = 0; - for( a=_rootAttribute; a; a = a->_next ) { - if ( XMLUtil::StringEqual( a->Name(), name ) ) { - return a; - } - } - return 0; -} - - -const XMLAttribute* XMLElement::FindAttribute( const char* name ) const -{ - XMLAttribute* a = 0; - for( a=_rootAttribute; a; a = a->_next ) { - if ( XMLUtil::StringEqual( a->Name(), name ) ) { - return a; - } - } - return 0; -} - - -const char* XMLElement::Attribute( const char* name, const char* value ) const -{ - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return 0; - } - if ( !value || XMLUtil::StringEqual( a->Value(), value )) { - return a->Value(); - } - return 0; -} - - -const char* XMLElement::GetText() const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - return FirstChild()->ToText()->Value(); - } - return 0; -} - - -XMLError XMLElement::QueryIntText( int* ival ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); - if ( XMLUtil::ToInt( t, ival ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); - if ( XMLUtil::ToUnsigned( t, uval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryBoolText( bool* bval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); - if ( XMLUtil::ToBool( t, bval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryDoubleText( double* dval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); - if ( XMLUtil::ToDouble( t, dval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryFloatText( float* fval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->ToText()->Value(); - if ( XMLUtil::ToFloat( t, fval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - - -XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) -{ - XMLAttribute* last = 0; - XMLAttribute* attrib = 0; - for( attrib = _rootAttribute; - attrib; - last = attrib, attrib = attrib->_next ) { - if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { - break; - } - } - if ( !attrib ) { - attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); - attrib->_memPool = &_document->_attributePool; - if ( last ) { - last->_next = attrib; - } - else { - _rootAttribute = attrib; - } - attrib->SetName( name ); - attrib->_memPool->SetTracked(); // always created and linked. - } - return attrib; -} - - -void XMLElement::DeleteAttribute( const char* name ) -{ - XMLAttribute* prev = 0; - for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { - if ( XMLUtil::StringEqual( name, a->Name() ) ) { - if ( prev ) { - prev->_next = a->_next; - } - else { - _rootAttribute = a->_next; - } - DELETE_ATTRIBUTE( a ); - break; - } - prev = a; - } -} - - -char* XMLElement::ParseAttributes( char* p ) -{ - const char* start = p; - XMLAttribute* prevAttribute = 0; - - // Read the attributes. - while( p ) { - p = XMLUtil::SkipWhiteSpace( p ); - if ( !p || !(*p) ) { - _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() ); - return 0; - } - - // attribute. - if (XMLUtil::IsNameStartChar( *p ) ) { - XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); - attrib->_memPool = &_document->_attributePool; - attrib->_memPool->SetTracked(); - - p = attrib->ParseDeep( p, _document->ProcessEntities() ); - if ( !p || Attribute( attrib->Name() ) ) { - DELETE_ATTRIBUTE( attrib ); - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); - return 0; - } - // There is a minor bug here: if the attribute in the source xml - // document is duplicated, it will not be detected and the - // attribute will be doubly added. However, tracking the 'prevAttribute' - // avoids re-scanning the attribute list. Preferring performance for - // now, may reconsider in the future. - if ( prevAttribute ) { - prevAttribute->_next = attrib; - } - else { - _rootAttribute = attrib; - } - prevAttribute = attrib; - } - // end of the tag - else if ( *p == '/' && *(p+1) == '>' ) { - _closingType = CLOSED; - return p+2; // done; sealed element. - } - // end of the tag - else if ( *p == '>' ) { - ++p; - break; - } - else { - _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p ); - return 0; - } - } - return p; -} - - -// -// -// foobar -// -char* XMLElement::ParseDeep( char* p, StrPair* strPair ) -{ - // Read the element name. - p = XMLUtil::SkipWhiteSpace( p ); - if ( !p ) { - return 0; - } - - // The closing element is the form. It is - // parsed just like a regular element then deleted from - // the DOM. - if ( *p == '/' ) { - _closingType = CLOSING; - ++p; - } - - p = _value.ParseName( p ); - if ( _value.Empty() ) { - return 0; - } - - p = ParseAttributes( p ); - if ( !p || !*p || _closingType ) { - return p; - } - - p = XMLNode::ParseDeep( p, strPair ); - return p; -} - - - -XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? - for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { - element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? - } - return element; -} - - -bool XMLElement::ShallowEqual( const XMLNode* compare ) const -{ - const XMLElement* other = compare->ToElement(); - if ( other && XMLUtil::StringEqual( other->Value(), Value() )) { - - const XMLAttribute* a=FirstAttribute(); - const XMLAttribute* b=other->FirstAttribute(); - - while ( a && b ) { - if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { - return false; - } - a = a->Next(); - b = b->Next(); - } - if ( a || b ) { - // different count - return false; - } - return true; - } - return false; -} - - -bool XMLElement::Accept( XMLVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, _rootAttribute ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLDocument ----------- // -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : - XMLNode( 0 ), - _writeBOM( false ), - _processEntities( processEntities ), - _errorID( XML_NO_ERROR ), - _whitespace( whitespace ), - _errorStr1( 0 ), - _errorStr2( 0 ), - _charBuffer( 0 ) -{ - _document = this; // avoid warning about 'this' in initializer list -} - - -XMLDocument::~XMLDocument() -{ - DeleteChildren(); - delete [] _charBuffer; - -#if 0 - _textPool.Trace( "text" ); - _elementPool.Trace( "element" ); - _commentPool.Trace( "comment" ); - _attributePool.Trace( "attribute" ); -#endif - -#ifdef DEBUG - if ( Error() == false ) { - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); - } -#endif -} - - -void XMLDocument::Clear() -{ - DeleteChildren(); - - _errorID = XML_NO_ERROR; - _errorStr1 = 0; - _errorStr2 = 0; - - delete [] _charBuffer; - _charBuffer = 0; -} - - -XMLElement* XMLDocument::NewElement( const char* name ) -{ - XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); - ele->_memPool = &_elementPool; - ele->SetName( name ); - return ele; -} - - -XMLComment* XMLDocument::NewComment( const char* str ) -{ - XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); - comment->_memPool = &_commentPool; - comment->SetValue( str ); - return comment; -} - - -XMLText* XMLDocument::NewText( const char* str ) -{ - XMLText* text = new (_textPool.Alloc()) XMLText( this ); - text->_memPool = &_textPool; - text->SetValue( str ); - return text; -} - - -XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) -{ - XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); - dec->_memPool = &_commentPool; - dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); - return dec; -} - - -XMLUnknown* XMLDocument::NewUnknown( const char* str ) -{ - XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); - unk->_memPool = &_commentPool; - unk->SetValue( str ); - return unk; -} - - -XMLError XMLDocument::LoadFile( const char* filename ) -{ - Clear(); - FILE* fp = 0; - -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - errno_t err = fopen_s(&fp, filename, "rb" ); - if ( !fp || err) { -#else - fp = fopen( filename, "rb" ); - if ( !fp) { -#endif - SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 ); - return _errorID; - } - LoadFile( fp ); - fclose( fp ); - return _errorID; -} - - -XMLError XMLDocument::LoadFile( FILE* fp ) -{ - Clear(); - - fseek( fp, 0, SEEK_END ); - size_t size = ftell( fp ); - fseek( fp, 0, SEEK_SET ); - - if ( size == 0 ) { - return _errorID; - } - - _charBuffer = new char[size+1]; - size_t read = fread( _charBuffer, 1, size, fp ); - if ( read != size ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - _charBuffer[size] = 0; - - const char* p = _charBuffer; - p = XMLUtil::SkipWhiteSpace( p ); - p = XMLUtil::ReadBOM( p, &_writeBOM ); - if ( !p || !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - - ParseDeep( _charBuffer + (p-_charBuffer), 0 ); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( const char* filename, bool compact ) -{ - FILE* fp = 0; -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - errno_t err = fopen_s(&fp, filename, "w" ); - if ( !fp || err) { -#else - fp = fopen( filename, "w" ); - if ( !fp) { -#endif - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); - return _errorID; - } - SaveFile(fp, compact); - fclose( fp ); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) -{ - XMLPrinter stream( fp, compact ); - Print( &stream ); - return _errorID; -} - - -XMLError XMLDocument::Parse( const char* p, size_t len ) -{ - Clear(); - - if ( !p || !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - if ( len == (size_t)(-1) ) { - len = strlen( p ); - } - _charBuffer = new char[ len+1 ]; - memcpy( _charBuffer, p, len ); - _charBuffer[len] = 0; - - p = XMLUtil::SkipWhiteSpace( p ); - p = XMLUtil::ReadBOM( p, &_writeBOM ); - if ( !p || !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - - ParseDeep( _charBuffer, 0 ); - return _errorID; -} - - -void XMLDocument::Print( XMLPrinter* streamer ) -{ - XMLPrinter stdStreamer( stdout ); - if ( !streamer ) { - streamer = &stdStreamer; - } - Accept( streamer ); -} - - -void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) -{ - _errorID = error; - _errorStr1 = str1; - _errorStr2 = str2; -} - - -void XMLDocument::PrintError() const -{ - if ( _errorID ) { - static const int LEN = 20; - char buf1[LEN] = { 0 }; - char buf2[LEN] = { 0 }; - - if ( _errorStr1 ) { - TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 ); - } - if ( _errorStr2 ) { - TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 ); - } - - printf( "XMLDocument error id=%d str1=%s str2=%s\n", - _errorID, buf1, buf2 ); - } -} - - -XMLPrinter::XMLPrinter( FILE* file, bool compact ) : - _elementJustOpened( false ), - _firstElement( true ), - _fp( file ), - _depth( 0 ), - _textDepth( -1 ), - _processEntities( true ), - _compactMode( compact ) -{ - for( int i=0; i'] = true; // not required, but consistency is nice - _buffer.Push( 0 ); -} - - -void XMLPrinter::Print( const char* format, ... ) -{ - va_list va; - va_start( va, format ); - - if ( _fp ) { - vfprintf( _fp, format, va ); - } - else { - // This seems brutally complex. Haven't figured out a better - // way on windows. -#ifdef _MSC_VER - int len = -1; - int expand = 1000; - while ( len < 0 ) { - len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va ); - if ( len < 0 ) { - expand *= 3/2; - _accumulator.PushArr( expand ); - } - } - char* p = _buffer.PushArr( len ) - 1; - memcpy( p, _accumulator.Mem(), len+1 ); -#else - int len = vsnprintf( 0, 0, format, va ); - // Close out and re-start the va-args - va_end( va ); - va_start( va, format ); - char* p = _buffer.PushArr( len ) - 1; - vsnprintf( p, len+1, format, va ); -#endif - } - va_end( va ); -} - - -void XMLPrinter::PrintSpace( int depth ) -{ - for( int i=0; i 0 && *q < ENTITY_RANGE ) { - // Check for entities. If one is found, flush - // the stream up until the entity, write the - // entity, and keep looking. - if ( flag[(unsigned)(*q)] ) { - while ( p < q ) { - Print( "%c", *p ); - ++p; - } - for( int i=0; i 0) ) { - Print( "%s", p ); - } -} - - -void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) -{ - static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; - if ( writeBOM ) { - Print( "%s", bom ); - } - if ( writeDec ) { - PushDeclaration( "xml version=\"1.0\"" ); - } -} - - -void XMLPrinter::OpenElement( const char* name ) -{ - if ( _elementJustOpened ) { - SealElement(); - } - _stack.Push( name ); - - if ( _textDepth < 0 && !_firstElement && !_compactMode ) { - Print( "\n" ); - PrintSpace( _depth ); - } - - Print( "<%s", name ); - _elementJustOpened = true; - _firstElement = false; - ++_depth; -} - - -void XMLPrinter::PushAttribute( const char* name, const char* value ) -{ - TIXMLASSERT( _elementJustOpened ); - Print( " %s=\"", name ); - PrintString( value, false ); - Print( "\"" ); -} - - -void XMLPrinter::PushAttribute( const char* name, int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::CloseElement() -{ - --_depth; - const char* name = _stack.Pop(); - - if ( _elementJustOpened ) { - Print( "/>" ); - } - else { - if ( _textDepth < 0 && !_compactMode) { - Print( "\n" ); - PrintSpace( _depth ); - } - Print( "", name ); - } - - if ( _textDepth == _depth ) { - _textDepth = -1; - } - if ( _depth == 0 && !_compactMode) { - Print( "\n" ); - } - _elementJustOpened = false; -} - - -void XMLPrinter::SealElement() -{ - _elementJustOpened = false; - Print( ">" ); -} - - -void XMLPrinter::PushText( const char* text, bool cdata ) -{ - _textDepth = _depth-1; - - if ( _elementJustOpened ) { - SealElement(); - } - if ( cdata ) { - Print( "" ); - } - else { - PrintString( text, true ); - } -} - -void XMLPrinter::PushText( int value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( unsigned value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( bool value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( float value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( double value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushComment( const char* comment ) -{ - if ( _elementJustOpened ) { - SealElement(); - } - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Print( "\n" ); - PrintSpace( _depth ); - } - _firstElement = false; - Print( "", comment ); -} - - -void XMLPrinter::PushDeclaration( const char* value ) -{ - if ( _elementJustOpened ) { - SealElement(); - } - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Print( "\n" ); - PrintSpace( _depth ); - } - _firstElement = false; - Print( "", value ); -} - - -void XMLPrinter::PushUnknown( const char* value ) -{ - if ( _elementJustOpened ) { - SealElement(); - } - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Print( "\n" ); - PrintSpace( _depth ); - } - _firstElement = false; - Print( "", value ); -} - - -bool XMLPrinter::VisitEnter( const XMLDocument& doc ) -{ - _processEntities = doc.ProcessEntities(); - if ( doc.HasBOM() ) { - PushHeader( true, false ); - } - return true; -} - - -bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) -{ - OpenElement( element.Name() ); - while ( attribute ) { - PushAttribute( attribute->Name(), attribute->Value() ); - attribute = attribute->Next(); - } - return true; -} - - -bool XMLPrinter::VisitExit( const XMLElement& ) -{ - CloseElement(); - return true; -} - - -bool XMLPrinter::Visit( const XMLText& text ) -{ - PushText( text.Value(), text.CData() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLComment& comment ) -{ - PushComment( comment.Value() ); - return true; -} - -bool XMLPrinter::Visit( const XMLDeclaration& declaration ) -{ - PushDeclaration( declaration.Value() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLUnknown& unknown ) -{ - PushUnknown( unknown.Value() ); - return true; -} - -} // namespace tinyxml2 - diff --git a/BasiliskII/src/Unix/tinyxml2.h b/BasiliskII/src/Unix/tinyxml2.h deleted file mode 100755 index 11fceb23..00000000 --- a/BasiliskII/src/Unix/tinyxml2.h +++ /dev/null @@ -1,1968 +0,0 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#ifndef TINYXML2_INCLUDED -#define TINYXML2_INCLUDED - -#if defined(ANDROID_NDK) || defined(__BORLANDC__) -# include -# include -# include -# include -# include -# include -#else -# include -# include -# include -# include -# include -# include -#endif - -/* - TODO: intern strings instead of allocation. -*/ -/* - gcc: - g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe - - Formatting, Artistic Style: - AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h -*/ - -#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) -# ifndef DEBUG -# define DEBUG -# endif -#endif - - -#if defined(DEBUG) -# if defined(_MSC_VER) -# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak() -# elif defined (ANDROID_NDK) -# include -# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } -# else -# include -# define TIXMLASSERT assert -# endif -# else -# define TIXMLASSERT( x ) {} -#endif - - -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) -// Microsoft visual studio, version 2005 and higher. -/*int _snprintf_s( - char *buffer, - size_t sizeOfBuffer, - size_t count, - const char *format [, - argument] ... -);*/ -inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) -{ - va_list va; - va_start( va, format ); - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - va_end( va ); - return result; -} -#define TIXML_SSCANF sscanf_s -#else -// GCC version 3 and higher -//#warning( "Using sn* functions." ) -#define TIXML_SNPRINTF snprintf -#define TIXML_SSCANF sscanf -#endif - -static const int TIXML2_MAJOR_VERSION = 1; -static const int TIXML2_MINOR_VERSION = 0; -static const int TIXML2_PATCH_VERSION = 11; - -namespace tinyxml2 -{ -class XMLDocument; -class XMLElement; -class XMLAttribute; -class XMLComment; -class XMLNode; -class XMLText; -class XMLDeclaration; -class XMLUnknown; - -class XMLPrinter; - -/* - A class that wraps strings. Normally stores the start and end - pointers into the XML file itself, and will apply normalization - and entity translation if actually read. Can also store (and memory - manage) a traditional char[] -*/ -class StrPair -{ -public: - enum { - NEEDS_ENTITY_PROCESSING = 0x01, - NEEDS_NEWLINE_NORMALIZATION = 0x02, - COLLAPSE_WHITESPACE = 0x04, - - TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, - TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, - ATTRIBUTE_NAME = 0, - ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, - ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, - COMMENT = NEEDS_NEWLINE_NORMALIZATION - }; - - StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} - ~StrPair(); - - void Set( char* start, char* end, int flags ) { - Reset(); - _start = start; - _end = end; - _flags = flags | NEEDS_FLUSH; - } - - const char* GetStr(); - - bool Empty() const { - return _start == _end; - } - - void SetInternedStr( const char* str ) { - Reset(); - _start = const_cast(str); - } - - void SetStr( const char* str, int flags=0 ); - - char* ParseText( char* in, const char* endTag, int strFlags ); - char* ParseName( char* in ); - -private: - void Reset(); - void CollapseWhitespace(); - - enum { - NEEDS_FLUSH = 0x100, - NEEDS_DELETE = 0x200 - }; - - // After parsing, if *end != 0, it can be set to zero. - int _flags; - char* _start; - char* _end; -}; - - -/* - A dynamic array of Plain Old Data. Doesn't support constructors, etc. - Has a small initial memory pool, so that low or no usage will not - cause a call to new/delete -*/ -template -class DynArray -{ -public: - DynArray< T, INIT >() { - _mem = _pool; - _allocated = INIT; - _size = 0; - } - - ~DynArray() { - if ( _mem != _pool ) { - delete [] _mem; - } - } - - void Push( T t ) { - EnsureCapacity( _size+1 ); - _mem[_size++] = t; - } - - T* PushArr( int count ) { - EnsureCapacity( _size+count ); - T* ret = &_mem[_size]; - _size += count; - return ret; - } - - T Pop() { - return _mem[--_size]; - } - - void PopArr( int count ) { - TIXMLASSERT( _size >= count ); - _size -= count; - } - - bool Empty() const { - return _size == 0; - } - - T& operator[](int i) { - TIXMLASSERT( i>= 0 && i < _size ); - return _mem[i]; - } - - const T& operator[](int i) const { - TIXMLASSERT( i>= 0 && i < _size ); - return _mem[i]; - } - - int Size() const { - return _size; - } - - int Capacity() const { - return _allocated; - } - - const T* Mem() const { - return _mem; - } - - T* Mem() { - return _mem; - } - -private: - void EnsureCapacity( int cap ) { - if ( cap > _allocated ) { - int newAllocated = cap * 2; - T* newMem = new T[newAllocated]; - memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs - if ( _mem != _pool ) { - delete [] _mem; - } - _mem = newMem; - _allocated = newAllocated; - } - } - - T* _mem; - T _pool[INIT]; - int _allocated; // objects allocated - int _size; // number objects in use -}; - - -/* - Parent virtual class of a pool for fast allocation - and deallocation of objects. -*/ -class MemPool -{ -public: - MemPool() {} - virtual ~MemPool() {} - - virtual int ItemSize() const = 0; - virtual void* Alloc() = 0; - virtual void Free( void* ) = 0; - virtual void SetTracked() = 0; -}; - - -/* - Template child class to create pools of the correct type. -*/ -template< int SIZE > -class MemPoolT : public MemPool -{ -public: - MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} - ~MemPoolT() { - // Delete the blocks. - for( int i=0; i<_blockPtrs.Size(); ++i ) { - delete _blockPtrs[i]; - } - } - - virtual int ItemSize() const { - return SIZE; - } - int CurrentAllocs() const { - return _currentAllocs; - } - - virtual void* Alloc() { - if ( !_root ) { - // Need a new block. - Block* block = new Block(); - _blockPtrs.Push( block ); - - for( int i=0; ichunk[i].next = &block->chunk[i+1]; - } - block->chunk[COUNT-1].next = 0; - _root = block->chunk; - } - void* result = _root; - _root = _root->next; - - ++_currentAllocs; - if ( _currentAllocs > _maxAllocs ) { - _maxAllocs = _currentAllocs; - } - _nAllocs++; - _nUntracked++; - return result; - } - virtual void Free( void* mem ) { - if ( !mem ) { - return; - } - --_currentAllocs; - Chunk* chunk = (Chunk*)mem; -#ifdef DEBUG - memset( chunk, 0xfe, sizeof(Chunk) ); -#endif - chunk->next = _root; - _root = chunk; - } - void Trace( const char* name ) { - printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", - name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); - } - - void SetTracked() { - _nUntracked--; - } - - int Untracked() const { - return _nUntracked; - } - - // This number is perf sensitive. 4k seems like a good tradeoff on my machine. - // The test file is large, 170k. - // Release: VS2010 gcc(no opt) - // 1k: 4000 - // 2k: 4000 - // 4k: 3900 21000 - // 16k: 5200 - // 32k: 4300 - // 64k: 4000 21000 - enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private - -private: - union Chunk { - Chunk* next; - char mem[SIZE]; - }; - struct Block { - Chunk chunk[COUNT]; - }; - DynArray< Block*, 10 > _blockPtrs; - Chunk* _root; - - int _currentAllocs; - int _nAllocs; - int _maxAllocs; - int _nUntracked; -}; - - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a XMLVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes support visiting. - - You should never change the document from a callback. - - @sa XMLNode::Accept() -*/ -class XMLVisitor -{ -public: - virtual ~XMLVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { - return true; - } - /// Visit a document. - virtual bool VisitExit( const XMLDocument& /*doc*/ ) { - return true; - } - - /// Visit an element. - virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { - return true; - } - /// Visit an element. - virtual bool VisitExit( const XMLElement& /*element*/ ) { - return true; - } - - /// Visit a declaration. - virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { - return true; - } - /// Visit a text node. - virtual bool Visit( const XMLText& /*text*/ ) { - return true; - } - /// Visit a comment node. - virtual bool Visit( const XMLComment& /*comment*/ ) { - return true; - } - /// Visit an unknown node. - virtual bool Visit( const XMLUnknown& /*unknown*/ ) { - return true; - } -}; - - -/* - Utility functionality. -*/ -class XMLUtil -{ -public: - // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't - // correct, but simple, and usually works. - static const char* SkipWhiteSpace( const char* p ) { - while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast(p) ) ) { - ++p; - } - return p; - } - static char* SkipWhiteSpace( char* p ) { - while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast(p) ) ) { - ++p; - } - return p; - } - static bool IsWhiteSpace( char p ) { - return !IsUTF8Continuation(p) && isspace( static_cast(p) ); - } - - inline static bool IsNameStartChar( unsigned char ch ) { - return ( ( ch < 128 ) ? isalpha( ch ) : 1 ) - || ch == ':' - || ch == '_'; - } - - inline static bool IsNameChar( unsigned char ch ) { - return IsNameStartChar( ch ) - || isdigit( ch ) - || ch == '.' - || ch == '-'; - } - - inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { - int n = 0; - if ( p == q ) { - return true; - } - while( *p && *q && *p == *q && n(const_cast(this)->FirstChildElement( value )); - } - - /// Get the last child node, or null if none exists. - const XMLNode* LastChild() const { - return _lastChild; - } - - XMLNode* LastChild() { - return const_cast(const_cast(this)->LastChild() ); - } - - /** Get the last child element or optionally the last child - element with the specified name. - */ - const XMLElement* LastChildElement( const char* value=0 ) const; - - XMLElement* LastChildElement( const char* value=0 ) { - return const_cast(const_cast(this)->LastChildElement(value) ); - } - - /// Get the previous (left) sibling node of this node. - const XMLNode* PreviousSibling() const { - return _prev; - } - - XMLNode* PreviousSibling() { - return _prev; - } - - /// Get the previous (left) sibling element of this node, with an opitionally supplied name. - const XMLElement* PreviousSiblingElement( const char* value=0 ) const ; - - XMLElement* PreviousSiblingElement( const char* value=0 ) { - return const_cast(const_cast(this)->PreviousSiblingElement( value ) ); - } - - /// Get the next (right) sibling node of this node. - const XMLNode* NextSibling() const { - return _next; - } - - XMLNode* NextSibling() { - return _next; - } - - /// Get the next (right) sibling element of this node, with an opitionally supplied name. - const XMLElement* NextSiblingElement( const char* value=0 ) const; - - XMLElement* NextSiblingElement( const char* value=0 ) { - return const_cast(const_cast(this)->NextSiblingElement( value ) ); - } - - /** - Add a child node as the last (right) child. - */ - XMLNode* InsertEndChild( XMLNode* addThis ); - - XMLNode* LinkEndChild( XMLNode* addThis ) { - return InsertEndChild( addThis ); - } - /** - Add a child node as the first (left) child. - */ - XMLNode* InsertFirstChild( XMLNode* addThis ); - /** - Add a node after the specified child node. - */ - XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); - - /** - Delete all the children of this node. - */ - void DeleteChildren(); - - /** - Delete a child of this node. - */ - void DeleteChild( XMLNode* node ); - - /** - Make a copy of this node, but not its children. - You may pass in a Document pointer that will be - the owner of the new Node. If the 'document' is - null, then the node returned will be allocated - from the current Document. (this->GetDocument()) - - Note: if called on a XMLDocument, this will return null. - */ - virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; - - /** - Test if 2 nodes are the same, but don't test children. - The 2 nodes do not need to be in the same Document. - - Note: if called on a XMLDocument, this will return false. - */ - virtual bool ShallowEqual( const XMLNode* compare ) const = 0; - - /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( XMLVisitor* visitor ) const = 0; - - // internal - virtual char* ParseDeep( char*, StrPair* ); - -protected: - XMLNode( XMLDocument* ); - virtual ~XMLNode(); - XMLNode( const XMLNode& ); // not supported - XMLNode& operator=( const XMLNode& ); // not supported - - XMLDocument* _document; - XMLNode* _parent; - mutable StrPair _value; - - XMLNode* _firstChild; - XMLNode* _lastChild; - - XMLNode* _prev; - XMLNode* _next; - -private: - MemPool* _memPool; - void Unlink( XMLNode* child ); -}; - - -/** XML text. - - Note that a text node can have child element nodes, for example: - @verbatim - This is bold - @endverbatim - - A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class XMLText : public XMLNode -{ - friend class XMLBase; - friend class XMLDocument; -public: - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLText* ToText() { - return this; - } - virtual const XMLText* ToText() const { - return this; - } - - /// Declare whether this should be CDATA or standard text. - void SetCData( bool isCData ) { - _isCData = isCData; - } - /// Returns true if this is a CDATA text element. - bool CData() const { - return _isCData; - } - - char* ParseDeep( char*, StrPair* endTag ); - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} - virtual ~XMLText() {} - XMLText( const XMLText& ); // not supported - XMLText& operator=( const XMLText& ); // not supported - -private: - bool _isCData; -}; - - -/** An XML Comment. */ -class XMLComment : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLComment* ToComment() { - return this; - } - virtual const XMLComment* ToComment() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - char* ParseDeep( char*, StrPair* endTag ); - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLComment( XMLDocument* doc ); - virtual ~XMLComment(); - XMLComment( const XMLComment& ); // not supported - XMLComment& operator=( const XMLComment& ); // not supported - -private: -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXML2 will happily read or write files without a declaration, - however. - - The text of the declaration isn't interpreted. It is parsed - and written as a string. -*/ -class XMLDeclaration : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLDeclaration* ToDeclaration() { - return this; - } - virtual const XMLDeclaration* ToDeclaration() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - char* ParseDeep( char*, StrPair* endTag ); - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLDeclaration( XMLDocument* doc ); - virtual ~XMLDeclaration(); - XMLDeclaration( const XMLDeclaration& ); // not supported - XMLDeclaration& operator=( const XMLDeclaration& ); // not supported -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class XMLUnknown : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLUnknown* ToUnknown() { - return this; - } - virtual const XMLUnknown* ToUnknown() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - char* ParseDeep( char*, StrPair* endTag ); - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLUnknown( XMLDocument* doc ); - virtual ~XMLUnknown(); - XMLUnknown( const XMLUnknown& ); // not supported - XMLUnknown& operator=( const XMLUnknown& ); // not supported -}; - - -enum XMLError { - XML_NO_ERROR = 0, - XML_SUCCESS = 0, - - XML_NO_ATTRIBUTE, - XML_WRONG_ATTRIBUTE_TYPE, - - XML_ERROR_FILE_NOT_FOUND, - XML_ERROR_FILE_COULD_NOT_BE_OPENED, - XML_ERROR_FILE_READ_ERROR, - XML_ERROR_ELEMENT_MISMATCH, - XML_ERROR_PARSING_ELEMENT, - XML_ERROR_PARSING_ATTRIBUTE, - XML_ERROR_IDENTIFYING_TAG, - XML_ERROR_PARSING_TEXT, - XML_ERROR_PARSING_CDATA, - XML_ERROR_PARSING_COMMENT, - XML_ERROR_PARSING_DECLARATION, - XML_ERROR_PARSING_UNKNOWN, - XML_ERROR_EMPTY_DOCUMENT, - XML_ERROR_MISMATCHED_ELEMENT, - XML_ERROR_PARSING, - - XML_CAN_NOT_CONVERT_TEXT, - XML_NO_TEXT_NODE -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not XMLNodes. You may only query the - Next() attribute in a list. -*/ -class XMLAttribute -{ - friend class XMLElement; -public: - /// The name of the attribute. - const char* Name() const { - return _name.GetStr(); - } - /// The value of the attribute. - const char* Value() const { - return _value.GetStr(); - } - /// The next attribute in the list. - const XMLAttribute* Next() const { - return _next; - } - - /** IntAttribute interprets the attribute as an integer, and returns the value. - If the value isn't an integer, 0 will be returned. There is no error checking; - use QueryIntAttribute() if you need error checking. - */ - int IntValue() const { - int i=0; - QueryIntValue( &i ); - return i; - } - /// Query as an unsigned integer. See IntAttribute() - unsigned UnsignedValue() const { - unsigned i=0; - QueryUnsignedValue( &i ); - return i; - } - /// Query as a boolean. See IntAttribute() - bool BoolValue() const { - bool b=false; - QueryBoolValue( &b ); - return b; - } - /// Query as a double. See IntAttribute() - double DoubleValue() const { - double d=0; - QueryDoubleValue( &d ); - return d; - } - /// Query as a float. See IntAttribute() - float FloatValue() const { - float f=0; - QueryFloatValue( &f ); - return f; - } - - /** QueryIntAttribute interprets the attribute as an integer, and returns the value - in the provided paremeter. The function will return XML_NO_ERROR on success, - and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. - */ - XMLError QueryIntValue( int* value ) const; - /// See QueryIntAttribute - XMLError QueryUnsignedValue( unsigned int* value ) const; - /// See QueryIntAttribute - XMLError QueryBoolValue( bool* value ) const; - /// See QueryIntAttribute - XMLError QueryDoubleValue( double* value ) const; - /// See QueryIntAttribute - XMLError QueryFloatValue( float* value ) const; - - /// Set the attribute to a string value. - void SetAttribute( const char* value ); - /// Set the attribute to value. - void SetAttribute( int value ); - /// Set the attribute to value. - void SetAttribute( unsigned value ); - /// Set the attribute to value. - void SetAttribute( bool value ); - /// Set the attribute to value. - void SetAttribute( double value ); - /// Set the attribute to value. - void SetAttribute( float value ); - -private: - enum { BUF_SIZE = 200 }; - - XMLAttribute() : _next( 0 ) {} - virtual ~XMLAttribute() {} - - XMLAttribute( const XMLAttribute& ); // not supported - void operator=( const XMLAttribute& ); // not supported - void SetName( const char* name ); - - char* ParseDeep( char* p, bool processEntities ); - - mutable StrPair _name; - mutable StrPair _value; - XMLAttribute* _next; - MemPool* _memPool; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class XMLElement : public XMLNode -{ - friend class XMLBase; - friend class XMLDocument; -public: - /// Get the name of an element (which is the Value() of the node.) - const char* Name() const { - return Value(); - } - /// Set the name of the element. - void SetName( const char* str, bool staticMem=false ) { - SetValue( str, staticMem ); - } - - virtual XMLElement* ToElement() { - return this; - } - virtual const XMLElement* ToElement() const { - return this; - } - virtual bool Accept( XMLVisitor* visitor ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none - exists. For example: - - @verbatim - const char* value = ele->Attribute( "foo" ); - @endverbatim - - The 'value' parameter is normally null. However, if specified, - the attribute will only be returned if the 'name' and 'value' - match. This allow you to write code: - - @verbatim - if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); - @endverbatim - - rather than: - @verbatim - if ( ele->Attribute( "foo" ) ) { - if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); - } - @endverbatim - */ - const char* Attribute( const char* name, const char* value=0 ) const; - - /** Given an attribute name, IntAttribute() returns the value - of the attribute interpreted as an integer. 0 will be - returned if there is an error. For a method with error - checking, see QueryIntAttribute() - */ - int IntAttribute( const char* name ) const { - int i=0; - QueryIntAttribute( name, &i ); - return i; - } - /// See IntAttribute() - unsigned UnsignedAttribute( const char* name ) const { - unsigned i=0; - QueryUnsignedAttribute( name, &i ); - return i; - } - /// See IntAttribute() - bool BoolAttribute( const char* name ) const { - bool b=false; - QueryBoolAttribute( name, &b ); - return b; - } - /// See IntAttribute() - double DoubleAttribute( const char* name ) const { - double d=0; - QueryDoubleAttribute( name, &d ); - return d; - } - /// See IntAttribute() - float FloatAttribute( const char* name ) const { - float f=0; - QueryFloatAttribute( name, &f ); - return f; - } - - /** Given an attribute name, QueryIntAttribute() returns - XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion - can't be performed, or XML_NO_ATTRIBUTE if the attribute - doesn't exist. If successful, the result of the conversion - will be written to 'value'. If not successful, nothing will - be written to 'value'. This allows you to provide default - value: - - @verbatim - int value = 10; - QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 - @endverbatim - */ - XMLError QueryIntAttribute( const char* name, int* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryIntValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryUnsignedValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryBoolAttribute( const char* name, bool* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryBoolValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryDoubleAttribute( const char* name, double* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryDoubleValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryFloatAttribute( const char* name, float* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryFloatValue( value ); - } - - - /** Given an attribute name, QueryAttribute() returns - XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion - can't be performed, or XML_NO_ATTRIBUTE if the attribute - doesn't exist. It is overloaded for the primitive types, - and is a generally more convenient replacement of - QueryIntAttribute() and related functions. - - If successful, the result of the conversion - will be written to 'value'. If not successful, nothing will - be written to 'value'. This allows you to provide default - value: - - @verbatim - int value = 10; - QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 - @endverbatim - */ - int QueryAttribute( const char* name, int* value ) const { - return QueryIntAttribute( name, value ); - } - - int QueryAttribute( const char* name, unsigned int* value ) const { - return QueryUnsignedAttribute( name, value ); - } - - int QueryAttribute( const char* name, bool* value ) const { - return QueryBoolAttribute( name, value ); - } - - int QueryAttribute( const char* name, double* value ) const { - return QueryDoubleAttribute( name, value ); - } - - int QueryAttribute( const char* name, float* value ) const { - return QueryFloatAttribute( name, value ); - } - - /// Sets the named attribute to value. - void SetAttribute( const char* name, const char* value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, int value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, unsigned value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, bool value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, double value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - - /** - Delete an attribute. - */ - void DeleteAttribute( const char* name ); - - /// Return the first attribute in the list. - const XMLAttribute* FirstAttribute() const { - return _rootAttribute; - } - /// Query a specific attribute in the list. - const XMLAttribute* FindAttribute( const char* name ) const; - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - */ - const char* GetText() const; - - /** - Convenience method to query the value of a child text node. This is probably best - shown by example. Given you have a document is this form: - @verbatim - - 1 - 1.4 - - @endverbatim - - The QueryIntText() and similar functions provide a safe and easier way to get to the - "value" of x and y. - - @verbatim - int x = 0; - float y = 0; // types of x and y are contrived for example - const XMLElement* xElement = pointElement->FirstChildElement( "x" ); - const XMLElement* yElement = pointElement->FirstChildElement( "y" ); - xElement->QueryIntText( &x ); - yElement->QueryFloatText( &y ); - @endverbatim - - @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted - to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. - - */ - XMLError QueryIntText( int* ival ) const; - /// See QueryIntText() - XMLError QueryUnsignedText( unsigned* uval ) const; - /// See QueryIntText() - XMLError QueryBoolText( bool* bval ) const; - /// See QueryIntText() - XMLError QueryDoubleText( double* dval ) const; - /// See QueryIntText() - XMLError QueryFloatText( float* fval ) const; - - // internal: - enum { - OPEN, // - CLOSED, // - CLOSING // - }; - int ClosingType() const { - return _closingType; - } - char* ParseDeep( char* p, StrPair* endTag ); - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -private: - XMLElement( XMLDocument* doc ); - virtual ~XMLElement(); - XMLElement( const XMLElement& ); // not supported - void operator=( const XMLElement& ); // not supported - - XMLAttribute* FindAttribute( const char* name ); - XMLAttribute* FindOrCreateAttribute( const char* name ); - //void LinkAttribute( XMLAttribute* attrib ); - char* ParseAttributes( char* p ); - - int _closingType; - // The attribute list is ordered; there is no 'lastAttribute' - // because the list needs to be scanned for dupes before adding - // a new attribute. - XMLAttribute* _rootAttribute; -}; - - -enum Whitespace { - PRESERVE_WHITESPACE, - COLLAPSE_WHITESPACE -}; - - -/** A Document binds together all the functionality. - It can be saved, loaded, and printed to the screen. - All Nodes are connected and allocated to a Document. - If the Document is deleted, all its Nodes are also deleted. -*/ -class XMLDocument : public XMLNode -{ - friend class XMLElement; -public: - /// constructor - XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); - ~XMLDocument(); - - virtual XMLDocument* ToDocument() { - return this; - } - virtual const XMLDocument* ToDocument() const { - return this; - } - - /** - Parse an XML file from a character string. - Returns XML_NO_ERROR (0) on success, or - an errorID. - - You may optionally pass in the 'nBytes', which is - the number of bytes which will be parsed. If not - specified, TinyXML will assume 'xml' points to a - null terminated string. - */ - XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); - - /** - Load an XML file from disk. - Returns XML_NO_ERROR (0) on success, or - an errorID. - */ - XMLError LoadFile( const char* filename ); - - /** - Load an XML file from disk. You are responsible - for providing and closing the FILE*. - - Returns XML_NO_ERROR (0) on success, or - an errorID. - */ - XMLError LoadFile( FILE* ); - - /** - Save the XML file to disk. - Returns XML_NO_ERROR (0) on success, or - an errorID. - */ - XMLError SaveFile( const char* filename, bool compact = false ); - - /** - Save the XML file to disk. You are responsible - for providing and closing the FILE*. - - Returns XML_NO_ERROR (0) on success, or - an errorID. - */ - XMLError SaveFile( FILE* fp, bool compact = false ); - - bool ProcessEntities() const { - return _processEntities; - } - Whitespace WhitespaceMode() const { - return _whitespace; - } - - /** - Returns true if this document has a leading Byte Order Mark of UTF8. - */ - bool HasBOM() const { - return _writeBOM; - } - /** Sets whether to write the BOM when writing the file. - */ - void SetBOM( bool useBOM ) { - _writeBOM = useBOM; - } - - /** Return the root element of DOM. Equivalent to FirstChildElement(). - To get the first node, use FirstChild(). - */ - XMLElement* RootElement() { - return FirstChildElement(); - } - const XMLElement* RootElement() const { - return FirstChildElement(); - } - - /** Print the Document. If the Printer is not provided, it will - print to stdout. If you provide Printer, this can print to a file: - @verbatim - XMLPrinter printer( fp ); - doc.Print( &printer ); - @endverbatim - - Or you can use a printer to print to memory: - @verbatim - XMLPrinter printer; - doc->Print( &printer ); - // printer.CStr() has a const char* to the XML - @endverbatim - */ - void Print( XMLPrinter* streamer=0 ); - virtual bool Accept( XMLVisitor* visitor ) const; - - /** - Create a new Element associated with - this Document. The memory for the Element - is managed by the Document. - */ - XMLElement* NewElement( const char* name ); - /** - Create a new Comment associated with - this Document. The memory for the Comment - is managed by the Document. - */ - XMLComment* NewComment( const char* comment ); - /** - Create a new Text associated with - this Document. The memory for the Text - is managed by the Document. - */ - XMLText* NewText( const char* text ); - /** - Create a new Declaration associated with - this Document. The memory for the object - is managed by the Document. - - If the 'text' param is null, the standard - declaration is used.: - @verbatim - - @endverbatim - */ - XMLDeclaration* NewDeclaration( const char* text=0 ); - /** - Create a new Unknown associated with - this Document. The memory forthe object - is managed by the Document. - */ - XMLUnknown* NewUnknown( const char* text ); - - /** - Delete a node associated with this document. - It will be unlinked from the DOM. - */ - void DeleteNode( XMLNode* node ) { - node->_parent->DeleteChild( node ); - } - - void SetError( XMLError error, const char* str1, const char* str2 ); - - /// Return true if there was an error parsing the document. - bool Error() const { - return _errorID != XML_NO_ERROR; - } - /// Return the errorID. - XMLError ErrorID() const { - return _errorID; - } - /// Return a possibly helpful diagnostic location or string. - const char* GetErrorStr1() const { - return _errorStr1; - } - /// Return a possibly helpful secondary diagnostic location or string. - const char* GetErrorStr2() const { - return _errorStr2; - } - /// If there is an error, print it to stdout. - void PrintError() const; - - /// Clear the document, resetting it to the initial state. - void Clear(); - - // internal - char* Identify( char* p, XMLNode** node ); - - virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { - return 0; - } - virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { - return false; - } - -private: - XMLDocument( const XMLDocument& ); // not supported - void operator=( const XMLDocument& ); // not supported - - bool _writeBOM; - bool _processEntities; - XMLError _errorID; - Whitespace _whitespace; - const char* _errorStr1; - const char* _errorStr2; - char* _charBuffer; - - MemPoolT< sizeof(XMLElement) > _elementPool; - MemPoolT< sizeof(XMLAttribute) > _attributePool; - MemPoolT< sizeof(XMLText) > _textPool; - MemPoolT< sizeof(XMLComment) > _commentPool; -}; - - -/** - A XMLHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that XMLHandle is not part of the TinyXML - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - XMLElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - XMLElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - XMLElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - XMLElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. XMLHandle addresses the verbosity - of such code. A XMLHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - XMLHandle docHandle( &document ); - XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - XMLHandle handleCopy = handle; - @endverbatim - - See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. -*/ -class XMLHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - XMLHandle( XMLNode* node ) { - _node = node; - } - /// Create a handle from a node. - XMLHandle( XMLNode& node ) { - _node = &node; - } - /// Copy constructor - XMLHandle( const XMLHandle& ref ) { - _node = ref._node; - } - /// Assignment - XMLHandle& operator=( const XMLHandle& ref ) { - _node = ref._node; - return *this; - } - - /// Get the first child of this handle. - XMLHandle FirstChild() { - return XMLHandle( _node ? _node->FirstChild() : 0 ); - } - /// Get the first child element of this handle. - XMLHandle FirstChildElement( const char* value=0 ) { - return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 ); - } - /// Get the last child of this handle. - XMLHandle LastChild() { - return XMLHandle( _node ? _node->LastChild() : 0 ); - } - /// Get the last child element of this handle. - XMLHandle LastChildElement( const char* _value=0 ) { - return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 ); - } - /// Get the previous sibling of this handle. - XMLHandle PreviousSibling() { - return XMLHandle( _node ? _node->PreviousSibling() : 0 ); - } - /// Get the previous sibling element of this handle. - XMLHandle PreviousSiblingElement( const char* _value=0 ) { - return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); - } - /// Get the next sibling of this handle. - XMLHandle NextSibling() { - return XMLHandle( _node ? _node->NextSibling() : 0 ); - } - /// Get the next sibling element of this handle. - XMLHandle NextSiblingElement( const char* _value=0 ) { - return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); - } - - /// Safe cast to XMLNode. This can return null. - XMLNode* ToNode() { - return _node; - } - /// Safe cast to XMLElement. This can return null. - XMLElement* ToElement() { - return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 ); - } - /// Safe cast to XMLText. This can return null. - XMLText* ToText() { - return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 ); - } - /// Safe cast to XMLUnknown. This can return null. - XMLUnknown* ToUnknown() { - return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 ); - } - /// Safe cast to XMLDeclaration. This can return null. - XMLDeclaration* ToDeclaration() { - return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 ); - } - -private: - XMLNode* _node; -}; - - -/** - A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the - same in all regards, except for the 'const' qualifiers. See XMLHandle for API. -*/ -class XMLConstHandle -{ -public: - XMLConstHandle( const XMLNode* node ) { - _node = node; - } - XMLConstHandle( const XMLNode& node ) { - _node = &node; - } - XMLConstHandle( const XMLConstHandle& ref ) { - _node = ref._node; - } - - XMLConstHandle& operator=( const XMLConstHandle& ref ) { - _node = ref._node; - return *this; - } - - const XMLConstHandle FirstChild() const { - return XMLConstHandle( _node ? _node->FirstChild() : 0 ); - } - const XMLConstHandle FirstChildElement( const char* value=0 ) const { - return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 ); - } - const XMLConstHandle LastChild() const { - return XMLConstHandle( _node ? _node->LastChild() : 0 ); - } - const XMLConstHandle LastChildElement( const char* _value=0 ) const { - return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 ); - } - const XMLConstHandle PreviousSibling() const { - return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); - } - const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { - return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); - } - const XMLConstHandle NextSibling() const { - return XMLConstHandle( _node ? _node->NextSibling() : 0 ); - } - const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { - return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); - } - - - const XMLNode* ToNode() const { - return _node; - } - const XMLElement* ToElement() const { - return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 ); - } - const XMLText* ToText() const { - return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 ); - } - const XMLUnknown* ToUnknown() const { - return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 ); - } - const XMLDeclaration* ToDeclaration() const { - return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 ); - } - -private: - const XMLNode* _node; -}; - - -/** - Printing functionality. The XMLPrinter gives you more - options than the XMLDocument::Print() method. - - It can: - -# Print to memory. - -# Print to a file you provide. - -# Print XML without a XMLDocument. - - Print to Memory - - @verbatim - XMLPrinter printer; - doc->Print( &printer ); - SomeFunction( printer.CStr() ); - @endverbatim - - Print to a File - - You provide the file pointer. - @verbatim - XMLPrinter printer( fp ); - doc.Print( &printer ); - @endverbatim - - Print without a XMLDocument - - When loading, an XML parser is very useful. However, sometimes - when saving, it just gets in the way. The code is often set up - for streaming, and constructing the DOM is just overhead. - - The Printer supports the streaming case. The following code - prints out a trivially simple XML file without ever creating - an XML document. - - @verbatim - XMLPrinter printer( fp ); - printer.OpenElement( "foo" ); - printer.PushAttribute( "foo", "bar" ); - printer.CloseElement(); - @endverbatim -*/ -class XMLPrinter : public XMLVisitor -{ -public: - /** Construct the printer. If the FILE* is specified, - this will print to the FILE. Else it will print - to memory, and the result is available in CStr(). - If 'compact' is set to true, then output is created - with only required whitespace and newlines. - */ - XMLPrinter( FILE* file=0, bool compact = false ); - ~XMLPrinter() {} - - /** If streaming, write the BOM and declaration. */ - void PushHeader( bool writeBOM, bool writeDeclaration ); - /** If streaming, start writing an element. - The element must be closed with CloseElement() - */ - void OpenElement( const char* name ); - /// If streaming, add an attribute to an open element. - void PushAttribute( const char* name, const char* value ); - void PushAttribute( const char* name, int value ); - void PushAttribute( const char* name, unsigned value ); - void PushAttribute( const char* name, bool value ); - void PushAttribute( const char* name, double value ); - /// If streaming, close the Element. - void CloseElement(); - - /// Add a text node. - void PushText( const char* text, bool cdata=false ); - /// Add a text node from an integer. - void PushText( int value ); - /// Add a text node from an unsigned. - void PushText( unsigned value ); - /// Add a text node from a bool. - void PushText( bool value ); - /// Add a text node from a float. - void PushText( float value ); - /// Add a text node from a double. - void PushText( double value ); - - /// Add a comment - void PushComment( const char* comment ); - - void PushDeclaration( const char* value ); - void PushUnknown( const char* value ); - - virtual bool VisitEnter( const XMLDocument& /*doc*/ ); - virtual bool VisitExit( const XMLDocument& /*doc*/ ) { - return true; - } - - virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); - virtual bool VisitExit( const XMLElement& element ); - - virtual bool Visit( const XMLText& text ); - virtual bool Visit( const XMLComment& comment ); - virtual bool Visit( const XMLDeclaration& declaration ); - virtual bool Visit( const XMLUnknown& unknown ); - - /** - If in print to memory mode, return a pointer to - the XML file in memory. - */ - const char* CStr() const { - return _buffer.Mem(); - } - /** - If in print to memory mode, return the size - of the XML file in memory. (Note the size returned - includes the terminating null.) - */ - int CStrSize() const { - return _buffer.Size(); - } - -private: - void SealElement(); - void PrintSpace( int depth ); - void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. - void Print( const char* format, ... ); - - bool _elementJustOpened; - bool _firstElement; - FILE* _fp; - int _depth; - int _textDepth; - bool _processEntities; - bool _compactMode; - - enum { - ENTITY_RANGE = 64, - BUF_SIZE = 200 - }; - bool _entityFlag[ENTITY_RANGE]; - bool _restrictedEntityFlag[ENTITY_RANGE]; - - DynArray< const char*, 10 > _stack; - DynArray< char, 20 > _buffer; -#ifdef _MSC_VER - DynArray< char, 20 > _accumulator; -#endif -}; - - -} // tinyxml2 - - -#endif // TINYXML2_INCLUDED diff --git a/BasiliskII/src/Unix/user_strings_unix.cpp b/BasiliskII/src/Unix/user_strings_unix.cpp index f095e06c..5c86a02f 100644 --- a/BasiliskII/src/Unix/user_strings_unix.cpp +++ b/BasiliskII/src/Unix/user_strings_unix.cpp @@ -59,14 +59,6 @@ user_string_def platform_strings[] = { {STR_KEYCODE_FILE_WARN, "Cannot open keycode translation file %s (%s)."}, {STR_KEYCODE_VENDOR_WARN, "Cannot find vendor '%s' in keycode translation file %s."}, - {STR_PREFS_MENU_FILE_GTK, "/_File"}, - {STR_PREFS_ITEM_START_GTK, "/File/_Start Basilisk II"}, - {STR_PREFS_ITEM_ZAP_PRAM_GTK, "/File/_Zap PRAM File"}, - {STR_PREFS_ITEM_SEPL_GTK, "/File/sepl"}, - {STR_PREFS_ITEM_QUIT_GTK, "/File/_Quit Basilisk II"}, - {STR_HELP_MENU_GTK, "/_Help"}, - {STR_HELP_ITEM_ABOUT_GTK, "/Help/_About Basilisk II"}, - {STR_FBDEV_NAME_CTRL, "Frame Buffer Name"}, {STR_FBDEVICE_FILE_CTRL, "Frame Buffer Spec File"}, {STR_DSPDEVICE_FILE_CTRL, "Audio Output Device"}, diff --git a/BasiliskII/src/Unix/user_strings_unix.h b/BasiliskII/src/Unix/user_strings_unix.h index 9bdb9f62..0c26dc2a 100644 --- a/BasiliskII/src/Unix/user_strings_unix.h +++ b/BasiliskII/src/Unix/user_strings_unix.h @@ -50,14 +50,6 @@ enum { STR_KEYCODE_FILE_WARN, STR_KEYCODE_VENDOR_WARN, - STR_PREFS_MENU_FILE_GTK, - STR_PREFS_ITEM_START_GTK, - STR_PREFS_ITEM_ZAP_PRAM_GTK, - STR_PREFS_ITEM_SEPL_GTK, - STR_PREFS_ITEM_QUIT_GTK, - STR_HELP_MENU_GTK, - STR_HELP_ITEM_ABOUT_GTK, - STR_FBDEV_NAME_CTRL, STR_FBDEVICE_FILE_CTRL, STR_DSPDEVICE_FILE_CTRL, diff --git a/BasiliskII/src/Unix/vhd_unix.cpp b/BasiliskII/src/Unix/vhd_unix.cpp deleted file mode 100644 index 45f04e85..00000000 --- a/BasiliskII/src/Unix/vhd_unix.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * vhd_unix.cpp -- support for disk images in vhd format - * - * (C) 2010 Geoffrey Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "disk_unix.h" -#include -#include -#include -#include -extern "C" { -#include -} -// libvhd.h defines DEBUG -#undef DEBUG -#define DEBUG 0 -#include "debug.h" - -static disk_generic::status vhd_unix_open(const char *name, int *size, - bool read_only, vhd_context_t **ctx) -{ - int amode = read_only ? R_OK : (R_OK | W_OK); - int fid; - vhd_context_t *vhd; - - D(bug("vhd open %s\n", name)); - - if (access(name, amode)) { - D(bug("vhd open -- incorrect permissions %s\n", name)); - return disk_generic::DISK_UNKNOWN; - } - - if (! (fid = open(name, O_RDONLY))) { - D(bug("vhd open -- couldn't open file %s\n", name)); - return disk_generic::DISK_UNKNOWN; - } - else { - char buf[9]; - read(fid, buf, sizeof(buf)-1); - buf[8] = 0; - close(fid); - if (strcmp("conectix", buf) != 0) { - D(bug("vhd open -- not vhd magic = %s\n", buf)); - return disk_generic::DISK_UNKNOWN; - } - if (vhd = (vhd_context_t *) malloc(sizeof(vhd_context_t))) { - int err; - if (err = vhd_open(vhd, name, read_only ? - VHD_OPEN_RDONLY : VHD_OPEN_RDWR)) { - D(bug("vhd_open failed (%d)\n", err)); - free(vhd); - return disk_generic::DISK_INVALID; - } - else { - *size = (int) vhd->footer.curr_size; - printf("VHD Open %s\n", name); - *ctx = vhd; - return disk_generic::DISK_VALID; - } - } - else { - D(bug("vhd open -- malloc failed\n")); - return disk_generic::DISK_INVALID; - } - } -} - -static int vhd_unix_read(vhd_context_t *ctx, void *buffer, loff_t offset, - size_t length) -{ - int err; - if ((offset % VHD_SECTOR_SIZE) || (length % VHD_SECTOR_SIZE)) { - printf("vhd read only supported on sector boundaries (%d)\n", - VHD_SECTOR_SIZE); - return 0; - } - if (err = vhd_io_read(ctx, (char *) buffer, offset / VHD_SECTOR_SIZE, - length / VHD_SECTOR_SIZE)){ - D(bug("vhd read error %d\n", err)); - return err; - } - else - return length; -} - -static int vhd_unix_write(vhd_context_t *ctx, void *buffer, loff_t offset, - size_t length) -{ - int err; - - if ((offset % VHD_SECTOR_SIZE) || (length % VHD_SECTOR_SIZE)) { - printf("vhd write only supported on sector boundaries (%d)\n", - VHD_SECTOR_SIZE); - return 0; - } - if (err = vhd_io_write(ctx, (char *) buffer, offset/VHD_SECTOR_SIZE, - length/VHD_SECTOR_SIZE)) { - D(bug("vhd write error %d\n", err)); - return err; - } - else - return length; -} - - -static void vhd_unix_close(vhd_context_t *ctx) -{ - D(bug("vhd close\n")); - vhd_close(ctx); - free(ctx); -} - - -struct disk_vhd : disk_generic { - disk_vhd(vhd_context_t *ctx, bool read_only, loff_t size) - : ctx(ctx), read_only(read_only), file_size(size) { } - - virtual ~disk_vhd() { vhd_unix_close(ctx); } - virtual bool is_read_only() { return read_only; } - virtual loff_t size() { return file_size; } - - virtual size_t read(void *buf, loff_t offset, size_t length) { - return vhd_unix_read(ctx, buf, offset, length); - } - - virtual size_t write(void *buf, loff_t offset, size_t length) { - return vhd_unix_write(ctx, buf, offset, length); - } - -protected: - vhd_context_t *ctx; - bool read_only; - loff_t file_size; -}; - -disk_generic::status disk_vhd_factory(const char *path, - bool read_only, disk_generic **disk) { - int size; - vhd_context_t *ctx = NULL; - disk_generic::status st = vhd_unix_open(path, &size, read_only, &ctx); - if (st == disk_generic::DISK_VALID) - *disk = new disk_vhd(ctx, read_only, size); - return st; -} diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp deleted file mode 100644 index 6f8ef67f..00000000 --- a/BasiliskII/src/Unix/video_x.cpp +++ /dev/null @@ -1,2686 +0,0 @@ -/* - * video_x.cpp - Video/graphics emulation, X11 specific stuff - * - * Basilisk II (C) Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * The Ctrl key works like a qualifier for special actions: - * Ctrl-Tab = suspend DGA mode - * Ctrl-Esc = emergency quit - * Ctrl-F1 = mount floppy - * Ctrl-F5 = grab mouse (in windowed mode) - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef HAVE_PTHREADS -# include -#endif - -#ifdef ENABLE_XF86_DGA -# include -#endif - -#ifdef ENABLE_XF86_VIDMODE -# include -#endif - -#ifdef ENABLE_FBDEV_DGA -# include -#endif - -#include "cpu_emulation.h" -#include "main.h" -#include "adb.h" -#include "macos_util.h" -#include "prefs.h" -#include "user_strings.h" -#include "video.h" -#include "video_blit.h" - -#define DEBUG 0 -#include "debug.h" - - -// Supported video modes -static vector VideoModes; - -// Display types -enum { - DISPLAY_WINDOW, // X11 window, using MIT SHM extensions if possible - DISPLAY_DGA // DGA fullscreen display -}; - -// Constants -const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; - -static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask; -static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask; - - -// Global variables -static int32 frame_skip; // Prefs items -static int16 mouse_wheel_mode; -static int16 mouse_wheel_lines; - -static int display_type = DISPLAY_WINDOW; // See enum above -static bool local_X11; // Flag: X server running on local machine? -static uint8 *the_buffer = NULL; // Mac frame buffer (where MacOS draws into) -static uint8 *the_buffer_copy = NULL; // Copy of Mac frame buffer (for refreshed modes) -static uint32 the_buffer_size; // Size of allocated the_buffer - -static bool redraw_thread_active = false; // Flag: Redraw thread installed -#ifdef HAVE_PTHREADS -static pthread_attr_t redraw_thread_attr; // Redraw thread attributes -static volatile bool redraw_thread_cancel; // Flag: Cancel Redraw thread -static volatile bool redraw_thread_cancel_ack; // Flag: Acknowledge for redraw thread cancellation -static pthread_t redraw_thread; // Redraw thread -#endif - -static bool has_dga = false; // Flag: Video DGA capable -static bool has_vidmode = false; // Flag: VidMode extension available - -#ifdef ENABLE_VOSF -static bool use_vosf = true; // Flag: VOSF enabled -#else -static const bool use_vosf = false; // VOSF not possible -#endif - -static bool ctrl_down = false; // Flag: Ctrl key pressed -static bool caps_on = false; // Flag: Caps Lock on -static bool quit_full_screen = false; // Flag: DGA close requested from redraw thread -static bool emerg_quit = false; // Flag: Ctrl-Esc pressed, emergency quit requested from MacOS thread -static bool emul_suspended = false; // Flag: Emulator suspended - -static bool classic_mode = false; // Flag: Classic Mac video mode - -static bool use_keycodes = false; // Flag: Use keycodes rather than keysyms -static int keycode_table[256]; // X keycode -> Mac keycode translation table - -// X11 variables -char *x_display_name = NULL; // X11 display name -Display *x_display = NULL; // X11 display handle -static int screen; // Screen number -static Window rootwin; // Root window and our window -static int num_depths = 0; // Number of available X depths -static int *avail_depths = NULL; // List of available X depths -static XColor black, white; -static unsigned long black_pixel, white_pixel; -static int eventmask; - -static int xdepth; // Depth of X screen -static VisualFormat visualFormat; -static XVisualInfo visualInfo; -static Visual *vis; -static int color_class; - -static bool x_native_byte_order; // XImage has native byte order? -static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of DirectColor/TrueColor modes - -static Colormap cmap[2] = {0, 0}; // Colormaps for indexed modes (DGA needs two of them) - -static XColor x_palette[256]; // Color palette to be used as CLUT and gamma table -static bool x_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors - -#ifdef ENABLE_FBDEV_DGA -static int fbdev_fd = -1; -#endif - -#ifdef ENABLE_XF86_VIDMODE -static XF86VidModeModeInfo **x_video_modes = NULL; // Array of all available modes -static int num_x_video_modes; -#endif - -// Mutex to protect palette -#ifdef HAVE_PTHREADS -static pthread_mutex_t x_palette_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_PALETTE pthread_mutex_lock(&x_palette_lock) -#define UNLOCK_PALETTE pthread_mutex_unlock(&x_palette_lock) -#else -#define LOCK_PALETTE -#define UNLOCK_PALETTE -#endif - -// Mutex to protect frame buffer -#ifdef HAVE_PTHREADS -static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_FRAME_BUFFER pthread_mutex_lock(&frame_buffer_lock); -#define UNLOCK_FRAME_BUFFER pthread_mutex_unlock(&frame_buffer_lock); -#else -#define LOCK_FRAME_BUFFER -#define UNLOCK_FRAME_BUFFER -#endif - -// Variables for non-VOSF incremental refresh -static const int sm_uptd[] = {4,1,6,3,0,5,2,7}; -static int sm_no_boxes[] = {1,8,32,64,128,300}; -static bool updt_box[17][17]; -static int nr_boxes; - -// Video refresh function -static void VideoRefreshInit(void); -static void (*video_refresh)(void); - - -// Prototypes -static void *redraw_func(void *arg); - -// From main_unix.cpp -extern char *x_display_name; -extern Display *x_display; - -// From sys_unix.cpp -extern void SysMountFirstFloppy(void); - -// From clip_unix.cpp -extern void ClipboardSelectionClear(XSelectionClearEvent *); -extern void ClipboardSelectionRequest(XSelectionRequestEvent *); - - -/* - * monitor_desc subclass for X11 display - */ - -class X11_monitor_desc : public monitor_desc { -public: - X11_monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id) : monitor_desc(available_modes, default_depth, default_id) {} - ~X11_monitor_desc() {} - - virtual void switch_to_current_mode(void); - virtual void set_palette(uint8 *pal, int num); - - bool video_open(void); - void video_close(void); -}; - - -/* - * Utility functions - */ - -// Map video_mode depth ID to numerical depth value -static inline int depth_of_video_mode(video_mode const & mode) -{ - int depth = -1; - switch (mode.depth) { - case VDEPTH_1BIT: - depth = 1; - break; - case VDEPTH_2BIT: - depth = 2; - break; - case VDEPTH_4BIT: - depth = 4; - break; - case VDEPTH_8BIT: - depth = 8; - break; - case VDEPTH_16BIT: - depth = 16; - break; - case VDEPTH_32BIT: - depth = 32; - break; - default: - abort(); - } - return depth; -} - -// Map RGB color to pixel value (this only works in TrueColor/DirectColor visuals) -static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue, bool fix_byte_order = false) -{ - uint32 val = ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift); - if (fix_byte_order && !x_native_byte_order) { - // We have to fix byte order in the ExpandMap[] - // NOTE: this is only an optimization since Screen_blitter_init() - // could be arranged to choose an NBO or OBO (with - // byteswapping) Blit_Expand_X_To_Y() function - switch (visualFormat.depth) { - case 15: case 16: - val = do_byteswap_16(val); - break; - case 24: case 32: - val = do_byteswap_32(val); - break; - } - } - return val; -} - -// Do we have a visual for handling the specified Mac depth? If so, set the -// global variables "xdepth", "visualInfo", "vis" and "color_class". -static bool find_visual_for_depth(video_depth depth) -{ - D(bug("have_visual_for_depth(%d)\n", 1 << depth)); - - // 1-bit works always and uses default visual - if (depth == VDEPTH_1BIT) { - vis = DefaultVisual(x_display, screen); - visualInfo.visualid = XVisualIDFromVisual(vis); - int num = 0; - XVisualInfo *vi = XGetVisualInfo(x_display, VisualIDMask, &visualInfo, &num); - visualInfo = vi[0]; - XFree(vi); - xdepth = visualInfo.depth; - color_class = visualInfo.c_class; - D(bug(" found visual ID 0x%02x, depth %d\n", visualInfo.visualid, xdepth)); - return true; - } - - // Calculate minimum and maximum supported X depth - int min_depth = 1, max_depth = 32; - switch (depth) { -#ifdef ENABLE_VOSF - case VDEPTH_2BIT: - case VDEPTH_4BIT: // VOSF blitters can convert 2/4/8-bit -> 8/16/32-bit - case VDEPTH_8BIT: - min_depth = 8; - max_depth = 32; - break; -#else - case VDEPTH_2BIT: - case VDEPTH_4BIT: // 2/4-bit requires VOSF blitters - return false; - case VDEPTH_8BIT: // 8-bit without VOSF requires an 8-bit visual - min_depth = 8; - max_depth = 8; - break; -#endif - case VDEPTH_16BIT: // 16-bit requires a 15/16-bit visual - min_depth = 15; - max_depth = 16; - break; - case VDEPTH_32BIT: // 32-bit requires a 24/32-bit visual - min_depth = 24; - max_depth = 32; - break; - } - D(bug(" minimum required X depth is %d, maximum supported X depth is %d\n", min_depth, max_depth)); - - // Try to find a visual for one of the color depths - bool visual_found = false; - for (int i=0; i max_depth) - continue; - - // Determine best color class for this depth - switch (xdepth) { - case 1: // Try StaticGray or StaticColor - if (XMatchVisualInfo(x_display, screen, xdepth, StaticGray, &visualInfo) - || XMatchVisualInfo(x_display, screen, xdepth, StaticColor, &visualInfo)) - visual_found = true; - break; - case 8: // Need PseudoColor - if (XMatchVisualInfo(x_display, screen, xdepth, PseudoColor, &visualInfo)) - visual_found = true; - break; - case 15: - case 16: - case 24: - case 32: // Try DirectColor first, as this will allow gamma correction - if (XMatchVisualInfo(x_display, screen, xdepth, DirectColor, &visualInfo) - || XMatchVisualInfo(x_display, screen, xdepth, TrueColor, &visualInfo)) - visual_found = true; - break; - default: - D(bug(" not a supported depth\n")); - break; - } - } - if (!visual_found) - return false; - - // Visual was found - vis = visualInfo.visual; - color_class = visualInfo.c_class; - D(bug(" found visual ID 0x%02x, depth %d, class ", visualInfo.visualid, xdepth)); -#if DEBUG - switch (color_class) { - case StaticGray: D(bug("StaticGray\n")); break; - case GrayScale: D(bug("GrayScale\n")); break; - case StaticColor: D(bug("StaticColor\n")); break; - case PseudoColor: D(bug("PseudoColor\n")); break; - case TrueColor: D(bug("TrueColor\n")); break; - case DirectColor: D(bug("DirectColor\n")); break; - } -#endif - return true; -} - -// Add mode to list of supported modes -static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth) -{ - video_mode mode; - mode.x = width; - mode.y = height; - mode.resolution_id = resolution_id; - mode.bytes_per_row = bytes_per_row; - mode.depth = depth; - mode.user_data = 0; - VideoModes.push_back(mode); -} - -// Add standard list of windowed modes for given color depth -static void add_window_modes(video_depth depth) -{ - add_mode(512, 384, 0x80, TrivialBytesPerRow(512, depth), depth); - add_mode(640, 480, 0x81, TrivialBytesPerRow(640, depth), depth); - add_mode(800, 600, 0x82, TrivialBytesPerRow(800, depth), depth); - add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, depth), depth); - add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, depth), depth); - add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, depth), depth); - add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, depth), depth); -} - -// Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac) -static void set_mac_frame_buffer(X11_monitor_desc &monitor, video_depth depth, bool native_byte_order) -{ -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING - int layout = FLAYOUT_DIRECT; - if (depth == VDEPTH_16BIT) - layout = (xdepth == 15) ? FLAYOUT_HOST_555 : FLAYOUT_HOST_565; - else if (depth == VDEPTH_32BIT) - layout = (xdepth == 24) ? FLAYOUT_HOST_888 : FLAYOUT_DIRECT; - if (native_byte_order) - MacFrameLayout = layout; - else - MacFrameLayout = FLAYOUT_DIRECT; - monitor.set_mac_frame_base(MacFrameBaseMac); - - // Set variables used by UAE memory banking - const video_mode &mode = monitor.get_current_mode(); - MacFrameBaseHost = the_buffer; - MacFrameSize = mode.bytes_per_row * mode.y; - InitFrameBufferMapping(); -#else - monitor.set_mac_frame_base(Host2MacAddr(the_buffer)); -#endif - D(bug("monitor.mac_frame_base = %08x\n", monitor.get_mac_frame_base())); -} - -// Set window name and class -static void set_window_name(Window w, int name) -{ - const char *str = GetString(name); - XStoreName(x_display, w, str); - XSetIconName(x_display, w, str); - - XClassHint *hints; - hints = XAllocClassHint(); - if (hints) { - hints->res_name = "BasiliskII"; - hints->res_class = "BasiliskII"; - XSetClassHint(x_display, w, hints); - XFree(hints); - } -} - -// Set window input focus flag -static void set_window_focus(Window w) -{ - XWMHints *hints = XAllocWMHints(); - if (hints) { - hints->input = True; - hints->initial_state = NormalState; - hints->flags = InputHint | StateHint; - XSetWMHints(x_display, w, hints); - XFree(hints); - } -} - -// Set WM_DELETE_WINDOW protocol on window (preventing it from being destroyed by the WM when clicking on the "close" widget) -static Atom WM_DELETE_WINDOW = (Atom)0; -static void set_window_delete_protocol(Window w) -{ - WM_DELETE_WINDOW = XInternAtom(x_display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(x_display, w, &WM_DELETE_WINDOW, 1); -} - -// Wait until window is mapped/unmapped -void wait_mapped(Window w) -{ - XEvent e; - do { - XMaskEvent(x_display, StructureNotifyMask, &e); - } while ((e.type != MapNotify) || (e.xmap.event != w)); -} - -void wait_unmapped(Window w) -{ - XEvent e; - do { - XMaskEvent(x_display, StructureNotifyMask, &e); - } while ((e.type != UnmapNotify) || (e.xmap.event != w)); -} - -// Trap SHM errors -static bool shm_error = false; -static int (*old_error_handler)(Display *, XErrorEvent *); - -static int error_handler(Display *d, XErrorEvent *e) -{ - if (e->error_code == BadAccess) { - shm_error = true; - return 0; - } else - return old_error_handler(d, e); -} - - -/* - * Framebuffer allocation routines - */ - -#ifdef ENABLE_VOSF -#include "vm_alloc.h" - -static void *vm_acquire_framebuffer(uint32 size) -{ - // always try to allocate framebuffer at the same address - static void *fb = VM_MAP_FAILED; - if (fb != VM_MAP_FAILED) { - if (vm_acquire_fixed(fb, size) < 0) - fb = VM_MAP_FAILED; - } - if (fb == VM_MAP_FAILED) - fb = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); - return fb; -} - -static inline void vm_release_framebuffer(void *fb, uint32 size) -{ - vm_release(fb, size); -} -#endif - - -/* - * Display "driver" classes - */ - -class driver_base { -public: - driver_base(X11_monitor_desc &m); - virtual ~driver_base(); - - virtual void update_palette(void); - virtual void suspend(void) {} - virtual void resume(void) {} - virtual void toggle_mouse_grab(void) {} - virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); } - - void disable_mouse_accel(void); - void restore_mouse_accel(void); - - virtual void grab_mouse(void) {} - virtual void ungrab_mouse(void) {} - -public: - X11_monitor_desc &monitor; // Associated video monitor - const video_mode &mode; // Video mode handled by the driver - - bool init_ok; // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer) - Window w; // The window we draw into - - int orig_accel_numer, orig_accel_denom, orig_threshold; // Original mouse acceleration -}; - -class driver_window; -static void update_display_window_vosf(driver_window *drv); -static void update_display_dynamic(int ticker, driver_window *drv); -static void update_display_static(driver_window *drv); - -class driver_window : public driver_base { - friend void update_display_window_vosf(driver_window *drv); - friend void update_display_dynamic(int ticker, driver_window *drv); - friend void update_display_static(driver_window *drv); - -public: - driver_window(X11_monitor_desc &monitor); - ~driver_window(); - - void toggle_mouse_grab(void); - void mouse_moved(int x, int y); - - void grab_mouse(void); - void ungrab_mouse(void); - -private: - GC gc; - XImage *img; - bool have_shm; // Flag: SHM extensions available - XShmSegmentInfo shminfo; - Cursor mac_cursor; - bool mouse_grabbed; // Flag: mouse pointer grabbed, using relative mouse mode - int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode) -}; - -class driver_dga; -static void update_display_dga_vosf(driver_dga *drv); - -class driver_dga : public driver_base { - friend void update_display_dga_vosf(driver_dga *drv); - -public: - driver_dga(X11_monitor_desc &monitor); - ~driver_dga(); - - void suspend(void); - void resume(void); - -protected: - struct FakeXImage { - int width, height; // size of image - int depth; // depth of image - int bytes_per_line; // accelerator to next line - - FakeXImage(int w, int h, int d) - : width(w), height(h), depth(d) - { bytes_per_line = TrivialBytesPerRow(width, DepthModeForPixelDepth(depth)); } - }; - FakeXImage *img; - -private: - Window suspend_win; // "Suspend" information window - void *fb_save; // Saved frame buffer for suspend/resume -}; - -static driver_base *drv = NULL; // Pointer to currently used driver object - -#ifdef ENABLE_VOSF -# include "video_vosf.h" -#endif - -driver_base::driver_base(X11_monitor_desc &m) - : monitor(m), mode(m.get_current_mode()), init_ok(false), w(0) -{ - the_buffer = NULL; - the_buffer_copy = NULL; - XGetPointerControl(x_display, &orig_accel_numer, &orig_accel_denom, &orig_threshold); -} - -driver_base::~driver_base() -{ - ungrab_mouse(); - restore_mouse_accel(); - - if (w) { - XUnmapWindow(x_display, w); - wait_unmapped(w); - XDestroyWindow(x_display, w); - } - - XFlush(x_display); - XSync(x_display, false); - - // Free frame buffer(s) - if (!use_vosf) { - if (the_buffer) { - free(the_buffer); - the_buffer = NULL; - } - if (the_buffer_copy) { - free(the_buffer_copy); - the_buffer_copy = NULL; - } - } -#ifdef ENABLE_VOSF - else { - // the_buffer shall always be mapped through vm_acquire() so that we can vm_protect() it at will - if (the_buffer != VM_MAP_FAILED) { - D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); - vm_release_framebuffer(the_buffer, the_buffer_size); - the_buffer = NULL; - } - if (the_host_buffer) { - D(bug(" freeing the_host_buffer at %p\n", the_host_buffer)); - free(the_host_buffer); - the_host_buffer = NULL; - } - if (the_buffer_copy) { - D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy)); - free(the_buffer_copy); - the_buffer_copy = NULL; - } - } -#endif -} - -// Palette has changed -void driver_base::update_palette(void) -{ - if (color_class == PseudoColor || color_class == DirectColor) { - int num = vis->map_entries; - if (!IsDirectMode(monitor.get_current_mode()) && color_class == DirectColor) - return; // Indexed mode on true color screen, don't set CLUT - XStoreColors(x_display, cmap[0], x_palette, num); - XStoreColors(x_display, cmap[1], x_palette, num); - } - XSync(x_display, false); -} - -// Disable mouse acceleration -void driver_base::disable_mouse_accel(void) -{ - XChangePointerControl(x_display, True, False, 1, 1, 0); -} - -// Restore mouse acceleration to original value -void driver_base::restore_mouse_accel(void) -{ - XChangePointerControl(x_display, True, True, orig_accel_numer, orig_accel_denom, orig_threshold); -} - - -/* - * Windowed display driver - */ - -// Open display -driver_window::driver_window(X11_monitor_desc &m) - : driver_base(m), gc(0), img(NULL), have_shm(false), mac_cursor(0), - mouse_grabbed(false), mouse_last_x(0), mouse_last_y(0) -{ - int width = mode.x, height = mode.y; - int aligned_width = (width + 15) & ~15; - int aligned_height = (height + 15) & ~15; - - // Set absolute mouse mode - ADBSetRelMouseMode(mouse_grabbed); - - // Create window (setting background_pixel, border_pixel and colormap is - // mandatory when using a non-default visual; in 1-bit mode we use the - // default visual, so we can also use the default colormap) - XSetWindowAttributes wattr; - wattr.event_mask = eventmask = win_eventmask; - wattr.background_pixel = (vis == DefaultVisual(x_display, screen) ? black_pixel : 0); - wattr.border_pixel = 0; - wattr.colormap = (mode.depth == VDEPTH_1BIT ? DefaultColormap(x_display, screen) : cmap[0]); - w = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth, - InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel | CWColormap, &wattr); - D(bug(" window created\n")); - - // Set window name/class - set_window_name(w, STR_WINDOW_TITLE); - - // Indicate that we want keyboard input - set_window_focus(w); - - // Set delete protocol property - set_window_delete_protocol(w); - - // Make window unresizable - { - XSizeHints *hints = XAllocSizeHints(); - if (hints) { - hints->min_width = width; - hints->max_width = width; - hints->min_height = height; - hints->max_height = height; - hints->flags = PMinSize | PMaxSize; - XSetWMNormalHints(x_display, w, hints); - XFree(hints); - } - } - D(bug(" window attributes set\n")); - - // Show window - XMapWindow(x_display, w); - wait_mapped(w); - D(bug(" window mapped\n")); - - // 1-bit mode is big-endian; if the X server is little-endian, we can't - // use SHM because that doesn't allow changing the image byte order - bool need_msb_image = (mode.depth == VDEPTH_1BIT && XImageByteOrder(x_display) == LSBFirst); - - // Try to create and attach SHM image - if (local_X11 && !need_msb_image && XShmQueryExtension(x_display)) { - - // Create SHM image ("height + 2" for safety) - img = XShmCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, &shminfo, width, height); - D(bug(" shm image created\n")); - shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777); - the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0); - shminfo.shmaddr = img->data = (char *)the_buffer_copy; - shminfo.readOnly = False; - - // Try to attach SHM image, catching errors - shm_error = false; - old_error_handler = XSetErrorHandler(error_handler); - XShmAttach(x_display, &shminfo); - XSync(x_display, false); - XSetErrorHandler(old_error_handler); - if (shm_error) { - shmdt(shminfo.shmaddr); - XDestroyImage(img); - img = NULL; - shminfo.shmid = -1; - } else { - have_shm = true; - shmctl(shminfo.shmid, IPC_RMID, 0); - } - D(bug(" shm image attached\n")); - } - - // Create normal X image if SHM doesn't work ("height + 2" for safety) - if (!have_shm) { - int bytes_per_row = (mode.depth == VDEPTH_1BIT ? aligned_width/8 : TrivialBytesPerRow(aligned_width, DepthModeForPixelDepth(xdepth))); - the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row); - img = XCreateImage(x_display, vis, mode.depth == VDEPTH_1BIT ? 1 : xdepth, mode.depth == VDEPTH_1BIT ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row); - D(bug(" X image created\n")); - } - - if (need_msb_image) { - img->byte_order = MSBFirst; - img->bitmap_bit_order = MSBFirst; - } - -#ifdef ENABLE_VOSF - use_vosf = true; - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - the_host_buffer = the_buffer_copy; - the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line); - the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); -#else - // Allocate memory for frame buffer - the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line); - D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); -#endif - - // Create GC - gc = XCreateGC(x_display, w, 0, 0); - XSetState(x_display, gc, black_pixel, white_pixel, GXcopy, AllPlanes); - - // Create no_cursor - mac_cursor = XCreatePixmapCursor(x_display, - XCreatePixmap(x_display, w, 1, 1, 1), - XCreatePixmap(x_display, w, 1, 1, 1), - &black, &white, 0, 0); - XDefineCursor(x_display, w, mac_cursor); - - // Init blitting routines -#ifdef ENABLE_VOSF - Screen_blitter_init(visualFormat, x_native_byte_order, depth_of_video_mode(mode)); -#endif - - // Set frame buffer base - set_mac_frame_buffer(monitor, mode.depth, x_native_byte_order); - - // Everything went well - init_ok = true; -} - -// Close display -driver_window::~driver_window() -{ - if (have_shm) { - XShmDetach(x_display, &shminfo); -#ifdef ENABLE_VOSF - the_host_buffer = NULL; // don't free() in driver_base dtor -#else - the_buffer_copy = NULL; // don't free() in driver_base dtor -#endif - } - if (img) { - if (!have_shm) - img->data = NULL; - XDestroyImage(img); - } - if (have_shm) { - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); - } - if (gc) - XFreeGC(x_display, gc); -} - -// Toggle mouse grab -void driver_window::toggle_mouse_grab(void) -{ - if (mouse_grabbed) - ungrab_mouse(); - else - grab_mouse(); -} - -// Grab mouse, switch to relative mouse mode -void driver_window::grab_mouse(void) -{ - int result; - for (int i=0; i<10; i++) { - result = XGrabPointer(x_display, w, True, 0, - GrabModeAsync, GrabModeAsync, w, None, CurrentTime); - if (result != AlreadyGrabbed) - break; - Delay_usec(100000); - } - if (result == GrabSuccess) { - XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED)); - ADBSetRelMouseMode(mouse_grabbed = true); - disable_mouse_accel(); - } -} - -// Ungrab mouse, switch to absolute mouse mode -void driver_window::ungrab_mouse(void) -{ - if (mouse_grabbed) { - XUngrabPointer(x_display, CurrentTime); - XStoreName(x_display, w, GetString(STR_WINDOW_TITLE)); - ADBSetRelMouseMode(mouse_grabbed = false); - restore_mouse_accel(); - } -} - -// Mouse moved -void driver_window::mouse_moved(int x, int y) -{ - if (!mouse_grabbed) { - mouse_last_x = x; mouse_last_y = y; - ADBMouseMoved(x, y); - return; - } - - // Warped mouse motion (this code is taken from SDL) - - // Post first mouse event - int width = monitor.get_current_mode().x, height = monitor.get_current_mode().y; - int delta_x = x - mouse_last_x, delta_y = y - mouse_last_y; - mouse_last_x = x; mouse_last_y = y; - ADBMouseMoved(delta_x, delta_y); - - // Only warp the pointer when it has reached the edge - const int MOUSE_FUDGE_FACTOR = 8; - if (x < MOUSE_FUDGE_FACTOR || x > (width - MOUSE_FUDGE_FACTOR) - || y < MOUSE_FUDGE_FACTOR || y > (height - MOUSE_FUDGE_FACTOR)) { - XEvent event; - while (XCheckTypedEvent(x_display, MotionNotify, &event)) { - delta_x = x - mouse_last_x; delta_y = y - mouse_last_y; - mouse_last_x = x; mouse_last_y = y; - ADBMouseMoved(delta_x, delta_y); - } - mouse_last_x = width/2; - mouse_last_y = height/2; - XWarpPointer(x_display, None, w, 0, 0, 0, 0, mouse_last_x, mouse_last_y); - for (int i=0; i<10; i++) { - XMaskEvent(x_display, PointerMotionMask, &event); - if (event.xmotion.x > (mouse_last_x - MOUSE_FUDGE_FACTOR) - && event.xmotion.x < (mouse_last_x + MOUSE_FUDGE_FACTOR) - && event.xmotion.y > (mouse_last_y - MOUSE_FUDGE_FACTOR) - && event.xmotion.y < (mouse_last_y + MOUSE_FUDGE_FACTOR)) - break; - } - } -} - - -#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA) -/* - * DGA display driver base class - */ - -driver_dga::driver_dga(X11_monitor_desc &m) - : driver_base(m), suspend_win(0), fb_save(NULL), img(NULL) -{ -} - -driver_dga::~driver_dga() -{ - XUngrabPointer(x_display, CurrentTime); - XUngrabKeyboard(x_display, CurrentTime); - - if (img) - delete img; -} - -// Suspend emulation -void driver_dga::suspend(void) -{ - // Release ctrl key - ADBKeyUp(0x36); - ctrl_down = false; - - // Lock frame buffer (this will stop the MacOS thread) - LOCK_FRAME_BUFFER; - - // Save frame buffer - fb_save = malloc(mode.y * mode.bytes_per_row); - if (fb_save) - memcpy(fb_save, the_buffer, mode.y * mode.bytes_per_row); - - // Close full screen display -#ifdef ENABLE_XF86_DGA - XF86DGADirectVideo(x_display, screen, 0); -#endif - XUngrabPointer(x_display, CurrentTime); - XUngrabKeyboard(x_display, CurrentTime); - restore_mouse_accel(); - XUnmapWindow(x_display, w); - wait_unmapped(w); - - // Open "suspend" window - XSetWindowAttributes wattr; - wattr.event_mask = KeyPressMask; - wattr.background_pixel = black_pixel; - - suspend_win = XCreateWindow(x_display, rootwin, 0, 0, 512, 1, 0, xdepth, - InputOutput, vis, CWEventMask | CWBackPixel, &wattr); - set_window_name(suspend_win, STR_SUSPEND_WINDOW_TITLE); - set_window_focus(suspend_win); - XMapWindow(x_display, suspend_win); - emul_suspended = true; -} - -// Resume emulation -void driver_dga::resume(void) -{ - // Close "suspend" window - XDestroyWindow(x_display, suspend_win); - XSync(x_display, false); - - // Reopen full screen display - XMapRaised(x_display, w); - wait_mapped(w); - XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0); - XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - disable_mouse_accel(); -#ifdef ENABLE_XF86_DGA - XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse); - XF86DGASetViewPort(x_display, screen, 0, 0); -#endif - XSync(x_display, false); - - // the_buffer already contains the data to restore. i.e. since a temporary - // frame buffer is used when VOSF is actually used, fb_save is therefore - // not necessary. -#ifdef ENABLE_VOSF - if (use_vosf) { - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); - } -#endif - - // Restore frame buffer - if (fb_save) { -#ifdef ENABLE_VOSF - // Don't copy fb_save to the temporary frame buffer in VOSF mode - if (!use_vosf) -#endif - memcpy(the_buffer, fb_save, mode.y * mode.bytes_per_row); - free(fb_save); - fb_save = NULL; - } - - // Unlock frame buffer (and continue MacOS thread) - UNLOCK_FRAME_BUFFER; - emul_suspended = false; -} -#endif - - -#ifdef ENABLE_FBDEV_DGA -/* - * fbdev DGA display driver - */ - -const char FBDEVICES_FILE_NAME[] = DATADIR "/fbdevices"; -const char FBDEVICE_FILE_NAME[] = "/dev/fb"; - -class driver_fbdev : public driver_dga { -public: - driver_fbdev(X11_monitor_desc &monitor); - ~driver_fbdev(); -}; - -// Open display -driver_fbdev::driver_fbdev(X11_monitor_desc &m) : driver_dga(m) -{ - int width = mode.x, height = mode.y; - - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - // Find the maximum depth available - int ndepths, max_depth(0); - int *depths = XListDepths(x_display, screen, &ndepths); - if (depths == NULL) { - printf("FATAL: Could not determine the maximal depth available\n"); - return; - } else { - while (ndepths-- > 0) { - if (depths[ndepths] > max_depth) - max_depth = depths[ndepths]; - } - } - - // Get fbdevices file path from preferences - const char *fbd_path = PrefsFindString("fbdevicefile"); - - // Open fbdevices file - FILE *fp = fopen(fbd_path ? fbd_path : FBDEVICES_FILE_NAME, "r"); - if (fp == NULL) { - char str[256]; - sprintf(str, GetString(STR_NO_FBDEVICE_FILE_ERR), fbd_path ? fbd_path : FBDEVICES_FILE_NAME, strerror(errno)); - ErrorAlert(str); - return; - } - - int fb_depth; // supported depth - uint32 fb_offset; // offset used for mmap(2) - char fb_name[20]; - char line[256]; - bool device_found = false; - while (fgets(line, 255, fp)) { - // Read line - int len = strlen(line); - if (len == 0) - continue; - line[len - 1] = '\0'; - - // Comments begin with "#" or ";" - if ((line[0] == '#') || (line[0] == ';') || (line[0] == '\0')) - continue; - - if ((sscanf(line, "%19s %d %x", fb_name, &fb_depth, &fb_offset) == 3) - && (strcmp(fb_name, fb_name) == 0) && (fb_depth == max_depth)) { - device_found = true; - break; - } - } - - // fbdevices file completely read - fclose(fp); - - // Frame buffer name not found ? Then, display warning - if (!device_found) { - char str[256]; - sprintf(str, GetString(STR_FBDEV_NAME_ERR), fb_name, max_depth); - ErrorAlert(str); - return; - } - - // Create window - XSetWindowAttributes wattr; - wattr.event_mask = eventmask = dga_eventmask; - wattr.background_pixel = white_pixel; - wattr.override_redirect = True; - wattr.colormap = cmap[0]; - - w = XCreateWindow(x_display, rootwin, - 0, 0, width, height, - 0, xdepth, InputOutput, vis, - CWEventMask | CWBackPixel | CWOverrideRedirect | (fb_depth <= 8 ? CWColormap : 0), - &wattr); - - // Set window name/class - set_window_name(w, STR_WINDOW_TITLE); - - // Indicate that we want keyboard input - set_window_focus(w); - - // Show window - XMapRaised(x_display, w); - wait_mapped(w); - - // Grab mouse and keyboard - XGrabKeyboard(x_display, w, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, w, True, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, w, None, CurrentTime); - disable_mouse_accel(); - - // Calculate bytes per row - int bytes_per_row = TrivialBytesPerRow(mode.x, mode.depth); - - // Map frame buffer - the_buffer_size = height * bytes_per_row; - if ((the_buffer = (uint8 *) mmap(NULL, the_buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fbdev_fd, fb_offset)) == MAP_FAILED) { - if ((the_buffer = (uint8 *) mmap(NULL, the_buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_fd, fb_offset)) == MAP_FAILED) { - char str[256]; - sprintf(str, GetString(STR_FBDEV_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - return; - } - } - -#if ENABLE_VOSF -#if REAL_ADDRESSING || DIRECT_ADDRESSING - // Screen_blitter_init() returns TRUE if VOSF is mandatory - // i.e. the framebuffer update function is not Blit_Copy_Raw - use_vosf = Screen_blitter_init(visualFormat, true, mode.depth); - - if (use_vosf) { - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - the_host_buffer = the_buffer; - the_buffer_size = page_extend((height + 2) * bytes_per_row); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); - - // Fake image for DGA/VOSF mode to know about display bounds - img = new FakeXImage(width, height, depth_of_video_mode(mode)); - } -#else - use_vosf = false; -#endif -#endif - - // Set frame buffer base - const_cast(&mode)->bytes_per_row = bytes_per_row; - const_cast(&mode)->depth = DepthModeForPixelDepth(fb_depth); - set_mac_frame_buffer(monitor, mode.depth, true); - - // Everything went well - init_ok = true; -} - -// Close display -driver_fbdev::~driver_fbdev() -{ - if (!use_vosf) { - if (the_buffer != MAP_FAILED) { - // don't free() the screen buffer in driver_base dtor - munmap(the_buffer, the_buffer_size); - the_buffer = NULL; - } - } -#ifdef ENABLE_VOSF - else { - if (the_host_buffer != MAP_FAILED) { - // don't free() the screen buffer in driver_base dtor - munmap(the_host_buffer, the_buffer_size); - the_host_buffer = NULL; - } - } -#endif -} -#endif - - -#ifdef ENABLE_XF86_DGA -/* - * XFree86 DGA display driver - */ - -class driver_xf86dga : public driver_dga { -public: - driver_xf86dga(X11_monitor_desc &monitor); - ~driver_xf86dga(); - - void update_palette(void); - void resume(void); - -private: - int current_dga_cmap; // Number (0 or 1) of currently installed DGA colormap -}; - -// Open display -driver_xf86dga::driver_xf86dga(X11_monitor_desc &m) - : driver_dga(m), current_dga_cmap(0) -{ - int width = mode.x, height = mode.y; - - // Set relative mouse mode - ADBSetRelMouseMode(true); - -#ifdef ENABLE_XF86_VIDMODE - // Switch to best mode - if (has_vidmode) { - int best = 0; - for (int i=1; ihdisplay >= width && x_video_modes[i]->vdisplay >= height && - x_video_modes[i]->hdisplay <= x_video_modes[best]->hdisplay && x_video_modes[i]->vdisplay <= x_video_modes[best]->vdisplay) { - best = i; - } - } - XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]); - XF86VidModeSetViewPort(x_display, screen, 0, 0); - XSync(x_display, false); - } -#endif - - // Create window - XSetWindowAttributes wattr; - wattr.event_mask = eventmask = dga_eventmask; - wattr.override_redirect = True; - wattr.colormap = (mode.depth == VDEPTH_1BIT ? DefaultColormap(x_display, screen) : cmap[0]); - - w = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth, - InputOutput, vis, CWEventMask | CWOverrideRedirect | - (color_class == DirectColor ? CWColormap : 0), &wattr); - - // Set window name/class - set_window_name(w, STR_WINDOW_TITLE); - - // Indicate that we want keyboard input - set_window_focus(w); - - // Show window - XMapRaised(x_display, w); - wait_mapped(w); - - // Establish direct screen connection - XMoveResizeWindow(x_display, w, 0, 0, width, height); - XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0); - XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - disable_mouse_accel(); - - int v_width, v_bank, v_size; - XF86DGAGetVideo(x_display, screen, (char **)&the_buffer, &v_width, &v_bank, &v_size); - XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse); - XF86DGASetViewPort(x_display, screen, 0, 0); - XF86DGASetVidPage(x_display, screen, 0); - - // Set colormap - if (!IsDirectMode(mode)) { - XSetWindowColormap(x_display, w, cmap[current_dga_cmap = 0]); - XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); - } - XSync(x_display, false); - - // Init blitting routines - int bytes_per_row = TrivialBytesPerRow((v_width + 7) & ~7, mode.depth); -#if ENABLE_VOSF -#if REAL_ADDRESSING || DIRECT_ADDRESSING - // Screen_blitter_init() returns TRUE if VOSF is mandatory - // i.e. the framebuffer update function is not Blit_Copy_Raw - use_vosf = Screen_blitter_init(visualFormat, x_native_byte_order, depth_of_video_mode(mode)); - - if (use_vosf) { - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - the_host_buffer = the_buffer; - the_buffer_size = page_extend((height + 2) * bytes_per_row); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); - - // Fake image for DGA/VOSF mode to know about display bounds - img = new FakeXImage((v_width + 7) & ~7, height, depth_of_video_mode(mode)); - } -#else - use_vosf = false; -#endif -#endif - - // Set frame buffer base - const_cast(&mode)->bytes_per_row = bytes_per_row; - set_mac_frame_buffer(monitor, mode.depth, true); - - // Everything went well - init_ok = true; -} - -// Close display -driver_xf86dga::~driver_xf86dga() -{ - XF86DGADirectVideo(x_display, screen, 0); - if (!use_vosf) { - // don't free() the screen buffer in driver_base dtor - the_buffer = NULL; - } -#ifdef ENABLE_VOSF - else { - // don't free() the screen buffer in driver_base dtor - the_host_buffer = NULL; - } -#endif -#ifdef ENABLE_XF86_VIDMODE - if (has_vidmode) - XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]); -#endif -} - -// Palette has changed -void driver_xf86dga::update_palette(void) -{ - driver_dga::update_palette(); - current_dga_cmap ^= 1; - if (!IsDirectMode(monitor.get_current_mode()) && cmap[current_dga_cmap]) - XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); -} - -// Resume emulation -void driver_xf86dga::resume(void) -{ - driver_dga::resume(); - if (!IsDirectMode(monitor.get_current_mode())) - XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); -} -#endif - - -/* - * Initialization - */ - -// Init keycode translation table -static void keycode_init(void) -{ - bool use_kc = PrefsFindBool("keycodes"); - if (use_kc) { - - // Get keycode file path from preferences - const char *kc_path = PrefsFindString("keycodefile"); - - // Open keycode table - FILE *f = fopen(kc_path ? kc_path : KEYCODE_FILE_NAME, "r"); - if (f == NULL) { - char str[256]; - sprintf(str, GetString(STR_KEYCODE_FILE_WARN), kc_path ? kc_path : KEYCODE_FILE_NAME, strerror(errno)); - WarningAlert(str); - return; - } - - // Default translation table - for (int i=0; i<256; i++) - keycode_table[i] = -1; - - // Search for server vendor string, then read keycodes - const char *vendor = ServerVendor(x_display); - // Force use of MacX mappings on MacOS X with Apple's X server - int dummy; - if (XQueryExtension(x_display, "Apple-DRI", &dummy, &dummy, &dummy)) - vendor = "MacX"; - bool vendor_found = false; - char line[256]; - while (fgets(line, 255, f)) { - // Read line - int len = strlen(line); - if (len == 0) - continue; - line[len-1] = 0; - - // Comments begin with "#" or ";" - if (line[0] == '#' || line[0] == ';' || line[0] == 0) - continue; - - if (vendor_found) { - // Read keycode - int x_code, mac_code; - if (sscanf(line, "%d %d", &x_code, &mac_code) == 2) - keycode_table[x_code & 0xff] = mac_code; - else - break; - } else { - // Search for vendor string - if (strstr(vendor, line) == vendor) - vendor_found = true; - } - } - - // Keycode file completely read - fclose(f); - use_keycodes = vendor_found; - - // Vendor not found? Then display warning - if (!vendor_found) { - char str[256]; - sprintf(str, GetString(STR_KEYCODE_VENDOR_WARN), vendor, kc_path ? kc_path : KEYCODE_FILE_NAME); - WarningAlert(str); - return; - } - } -} - -// Open display for current mode -bool X11_monitor_desc::video_open(void) -{ - D(bug("video_open()\n")); - const video_mode &mode = get_current_mode(); - - // Find best available X visual - if (!find_visual_for_depth(mode.depth)) { - ErrorAlert(STR_NO_XVISUAL_ERR); - return false; - } - - // Determine the byte order of an XImage content -#ifdef WORDS_BIGENDIAN - x_native_byte_order = (XImageByteOrder(x_display) == MSBFirst); -#else - x_native_byte_order = (XImageByteOrder(x_display) == LSBFirst); -#endif - - // Build up visualFormat structure - visualFormat.fullscreen = (display_type == DISPLAY_DGA); - visualFormat.depth = visualInfo.depth; - visualFormat.Rmask = visualInfo.red_mask; - visualFormat.Gmask = visualInfo.green_mask; - visualFormat.Bmask = visualInfo.blue_mask; - - // Create color maps - if (color_class == PseudoColor || color_class == DirectColor) { - cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll); - cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll); - } else { - cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocNone); - cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocNone); - } - - // Find pixel format of direct modes - if (color_class == DirectColor || color_class == TrueColor) { - rshift = gshift = bshift = 0; - rloss = gloss = bloss = 8; - uint32 mask; - for (mask=vis->red_mask; !(mask&1); mask>>=1) - ++rshift; - for (; mask&1; mask>>=1) - --rloss; - for (mask=vis->green_mask; !(mask&1); mask>>=1) - ++gshift; - for (; mask&1; mask>>=1) - --gloss; - for (mask=vis->blue_mask; !(mask&1); mask>>=1) - ++bshift; - for (; mask&1; mask>>=1) - --bloss; - } - - // Preset palette pixel values for CLUT or gamma table - if (color_class == DirectColor) { - int num = vis->map_entries; - for (int i=0; imap_entries : 256); - for (int i=0; i16/32 expand map - if (!IsDirectMode(mode) && xdepth > 8) - for (int i=0; i<256; i++) - ExpandMap[i] = map_rgb(i, i, i, true); -#endif - - // Create display driver object of requested type - switch (display_type) { - case DISPLAY_WINDOW: - drv = new driver_window(*this); - break; -#ifdef ENABLE_FBDEV_DGA - case DISPLAY_DGA: - drv = new driver_fbdev(*this); - break; -#endif -#ifdef ENABLE_XF86_DGA - case DISPLAY_DGA: - drv = new driver_xf86dga(*this); - break; -#endif - } - if (drv == NULL) - return false; - if (!drv->init_ok) { - delete drv; - drv = NULL; - return false; - } - -#ifdef ENABLE_VOSF - if (use_vosf) { - // Initialize the VOSF system - if (!video_vosf_init(*this)) { - ErrorAlert(STR_VOSF_INIT_ERR); - return false; - } - } -#endif - - // Initialize VideoRefresh function - VideoRefreshInit(); - - // Lock down frame buffer - XSync(x_display, false); - LOCK_FRAME_BUFFER; - - // Start redraw/input thread -#ifdef USE_PTHREADS_SERVICES - redraw_thread_cancel = false; - Set_pthread_attr(&redraw_thread_attr, 0); - redraw_thread_active = (pthread_create(&redraw_thread, &redraw_thread_attr, redraw_func, NULL) == 0); - if (!redraw_thread_active) { - printf("FATAL: cannot create redraw thread\n"); - return false; - } -#else - redraw_thread_active = true; -#endif - - return true; -} - -bool VideoInit(bool classic) -{ - classic_mode = classic; - -#ifdef ENABLE_VOSF - // Zero the mainBuffer structure - mainBuffer.dirtyPages = NULL; - mainBuffer.pageInfo = NULL; -#endif - - // Check if X server runs on local machine - local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0) - || (strncmp(XDisplayName(x_display_name), "/", 1) == 0) - || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0); - - // Init keycode translation - keycode_init(); - - // Read prefs - frame_skip = PrefsFindInt32("frameskip"); - mouse_wheel_mode = PrefsFindInt32("mousewheelmode"); - mouse_wheel_lines = PrefsFindInt32("mousewheellines"); - - // Find screen and root window - screen = XDefaultScreen(x_display); - rootwin = XRootWindow(x_display, screen); - - // Get sorted list of available depths - avail_depths = XListDepths(x_display, screen, &num_depths); - if (avail_depths == NULL) { - ErrorAlert(STR_UNSUPP_DEPTH_ERR); - return false; - } - std::sort(avail_depths, avail_depths + num_depths); - -#ifdef ENABLE_FBDEV_DGA - // Frame buffer name - char fb_name[20]; - - // Could do fbdev DGA? - if ((fbdev_fd = open(FBDEVICE_FILE_NAME, O_RDWR)) != -1) - has_dga = true; - else - has_dga = false; -#endif - -#ifdef ENABLE_XF86_DGA - // DGA available? - int dga_event_base, dga_error_base; - if (local_X11 && XF86DGAQueryExtension(x_display, &dga_event_base, &dga_error_base)) { - int dga_flags = 0; - XF86DGAQueryDirectVideo(x_display, screen, &dga_flags); - has_dga = dga_flags & XF86DGADirectPresent; - } else - has_dga = false; -#endif - -#ifdef ENABLE_XF86_VIDMODE - // VidMode available? - int vm_event_base, vm_error_base; - has_vidmode = XF86VidModeQueryExtension(x_display, &vm_event_base, &vm_error_base); - if (has_vidmode) - XF86VidModeGetAllModeLines(x_display, screen, &num_x_video_modes, &x_video_modes); -#endif - - // Find black and white colors - XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:00/00/00", &black); - XAllocColor(x_display, DefaultColormap(x_display, screen), &black); - XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:ff/ff/ff", &white); - XAllocColor(x_display, DefaultColormap(x_display, screen), &white); - black_pixel = BlackPixel(x_display, screen); - white_pixel = WhitePixel(x_display, screen); - - // Get screen mode from preferences - const char *mode_str; - if (classic_mode) - mode_str = "win/512/342"; - else - mode_str = PrefsFindString("screen"); - - // Determine display type and default dimensions - int default_width = 512, default_height = 384; - display_type = DISPLAY_WINDOW; - if (mode_str) { - if (sscanf(mode_str, "win/%d/%d", &default_width, &default_height) == 2) { - display_type = DISPLAY_WINDOW; -#ifdef ENABLE_FBDEV_DGA - } else if (has_dga && sscanf(mode_str, "dga/%19s", fb_name) == 1) { - display_type = DISPLAY_DGA; - default_width = -1; default_height = -1; // use entire screen -#endif -#ifdef ENABLE_XF86_DGA - } else if (has_dga && sscanf(mode_str, "dga/%d/%d", &default_width, &default_height) == 2) { - display_type = DISPLAY_DGA; -#endif - } - } - if (default_width <= 0) - default_width = DisplayWidth(x_display, screen); - else if (default_width > DisplayWidth(x_display, screen)) - default_width = DisplayWidth(x_display, screen); - if (default_height <= 0) - default_height = DisplayHeight(x_display, screen); - else if (default_height > DisplayHeight(x_display, screen)) - default_height = DisplayHeight(x_display, screen); - - // Mac screen depth follows X depth - video_depth default_depth = VDEPTH_1BIT; - switch (DefaultDepth(x_display, screen)) { - case 8: - default_depth = VDEPTH_8BIT; - break; - case 15: case 16: - default_depth = VDEPTH_16BIT; - break; - case 24: case 32: - default_depth = VDEPTH_32BIT; - break; - } - - // Construct list of supported modes - if (display_type == DISPLAY_WINDOW) { - if (classic) - add_mode(512, 342, 0x80, 64, VDEPTH_1BIT); - else { - for (unsigned d=VDEPTH_1BIT; d<=VDEPTH_32BIT; d++) { - if (find_visual_for_depth(video_depth(d))) - add_window_modes(video_depth(d)); - } - } - } else - add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth); - if (VideoModes.empty()) { - ErrorAlert(STR_NO_XVISUAL_ERR); - return false; - } - - // Find requested default mode with specified dimensions - uint32 default_id; - std::vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->x == default_width && i->y == default_height && i->depth == default_depth) { - default_id = i->resolution_id; - break; - } - } - if (i == end) { // not found, use first available mode - default_depth = VideoModes[0].depth; - default_id = VideoModes[0].resolution_id; - } - -#if DEBUG - D(bug("Available video modes:\n")); - for (i = VideoModes.begin(); i != end; ++i) { - int bits = 1 << i->depth; - if (bits == 16) - bits = 15; - else if (bits == 32) - bits = 24; - D(bug(" %dx%d (ID %02x), %d colors\n", i->x, i->y, i->resolution_id, 1 << bits)); - } -#endif - - // Create X11_monitor_desc for this (the only) display - X11_monitor_desc *monitor = new X11_monitor_desc(VideoModes, default_depth, default_id); - VideoMonitors.push_back(monitor); - - // Open display - return monitor->video_open(); -} - - -/* - * Deinitialization - */ - -// Close display -void X11_monitor_desc::video_close(void) -{ - D(bug("video_close()\n")); - - // Stop redraw thread -#ifdef USE_PTHREADS_SERVICES - if (redraw_thread_active) { - redraw_thread_cancel = true; - redraw_thread_cancel_ack = false; - pthread_join(redraw_thread, NULL); - while (!redraw_thread_cancel_ack) ; - } -#endif - redraw_thread_active = false; - - // Unlock frame buffer - UNLOCK_FRAME_BUFFER; - XSync(x_display, false); - D(bug(" frame buffer unlocked\n")); - -#ifdef ENABLE_VOSF - if (use_vosf) { - // Deinitialize VOSF - video_vosf_exit(); - } -#endif - - // Close display - delete drv; - drv = NULL; - - // Free colormaps - if (cmap[0]) { - XFreeColormap(x_display, cmap[0]); - cmap[0] = 0; - } - if (cmap[1]) { - XFreeColormap(x_display, cmap[1]); - cmap[1] = 0; - } -} - -void VideoExit(void) -{ - // Close displays - vector::iterator i, end = VideoMonitors.end(); - for (i = VideoMonitors.begin(); i != end; ++i) - dynamic_cast(*i)->video_close(); - -#ifdef ENABLE_XF86_VIDMODE - // Free video mode list - if (x_video_modes) { - XFree(x_video_modes); - x_video_modes = NULL; - } -#endif - -#ifdef ENABLE_FBDEV_DGA - // Close framebuffer device - if (fbdev_fd >= 0) { - close(fbdev_fd); - fbdev_fd = -1; - } -#endif - - // Free depth list - if (avail_depths) { - XFree(avail_depths); - avail_depths = NULL; - } -} - - -/* - * Close down full-screen mode (if bringing up error alerts is unsafe while in full-screen mode) - */ - -void VideoQuitFullScreen(void) -{ - D(bug("VideoQuitFullScreen()\n")); - quit_full_screen = true; -} - - -/* - * Mac VBL interrupt - */ - -void VideoInterrupt(void) -{ - // Emergency quit requested? Then quit - if (emerg_quit) - QuitEmulator(); - - // Temporarily give up frame buffer lock (this is the point where - // we are suspended when the user presses Ctrl-Tab) - UNLOCK_FRAME_BUFFER; - LOCK_FRAME_BUFFER; -} - - -/* - * Set palette - */ - -void X11_monitor_desc::set_palette(uint8 *pal, int num_in) -{ - const video_mode &mode = get_current_mode(); - - LOCK_PALETTE; - - // Convert colors to XColor array - int num_out = 256; - bool stretch = false; - if (IsDirectMode(mode)) { - // If X is in 565 mode we have to stretch the gamma table from 32 to 64 entries - num_out = vis->map_entries; - stretch = true; - } - XColor *p = x_palette; - for (int i=0; ired = pal[c*3 + 0] * 0x0101; - p->green = pal[c*3 + 1] * 0x0101; - p->blue = pal[c*3 + 2] * 0x0101; - p++; - } - -#ifdef ENABLE_VOSF - // Recalculate pixel color expansion map - if (!IsDirectMode(mode) && xdepth > 8) { - for (int i=0; i<256; i++) { - int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier) - ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2], true); - } - - // We have to redraw everything because the interpretation of pixel values changed - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); - } -#endif - - // Tell redraw thread to change palette - x_palette_changed = true; - - UNLOCK_PALETTE; -} - - -/* - * Switch video mode - */ - -void X11_monitor_desc::switch_to_current_mode(void) -{ - // Close and reopen display - video_close(); - video_open(); - - if (drv == NULL) { - ErrorAlert(STR_OPEN_WINDOW_ERR); - QuitEmulator(); - } -} - - -/* - * Translate key event to Mac keycode, returns -1 if no keycode was found - * and -2 if the key was recognized as a hotkey - */ - -static int kc_decode(KeySym ks, bool key_down) -{ - switch (ks) { - case XK_A: case XK_a: return 0x00; - case XK_B: case XK_b: return 0x0b; - case XK_C: case XK_c: return 0x08; - case XK_D: case XK_d: return 0x02; - case XK_E: case XK_e: return 0x0e; - case XK_F: case XK_f: return 0x03; - case XK_G: case XK_g: return 0x05; - case XK_H: case XK_h: return 0x04; - case XK_I: case XK_i: return 0x22; - case XK_J: case XK_j: return 0x26; - case XK_K: case XK_k: return 0x28; - case XK_L: case XK_l: return 0x25; - case XK_M: case XK_m: return 0x2e; - case XK_N: case XK_n: return 0x2d; - case XK_O: case XK_o: return 0x1f; - case XK_P: case XK_p: return 0x23; - case XK_Q: case XK_q: return 0x0c; - case XK_R: case XK_r: return 0x0f; - case XK_S: case XK_s: return 0x01; - case XK_T: case XK_t: return 0x11; - case XK_U: case XK_u: return 0x20; - case XK_V: case XK_v: return 0x09; - case XK_W: case XK_w: return 0x0d; - case XK_X: case XK_x: return 0x07; - case XK_Y: case XK_y: return 0x10; - case XK_Z: case XK_z: return 0x06; - - case XK_1: case XK_exclam: return 0x12; - case XK_2: case XK_at: return 0x13; - case XK_3: case XK_numbersign: return 0x14; - case XK_4: case XK_dollar: return 0x15; - case XK_5: case XK_percent: return 0x17; - case XK_6: return 0x16; - case XK_7: return 0x1a; - case XK_8: return 0x1c; - case XK_9: return 0x19; - case XK_0: return 0x1d; - - case XK_grave: case XK_asciitilde: return 0x0a; - case XK_minus: case XK_underscore: return 0x1b; - case XK_equal: case XK_plus: return 0x18; - case XK_bracketleft: case XK_braceleft: return 0x21; - case XK_bracketright: case XK_braceright: return 0x1e; - case XK_backslash: case XK_bar: return 0x2a; - case XK_semicolon: case XK_colon: return 0x29; - case XK_apostrophe: case XK_quotedbl: return 0x27; - case XK_comma: case XK_less: return 0x2b; - case XK_period: case XK_greater: return 0x2f; - case XK_slash: case XK_question: return 0x2c; - - case XK_Tab: if (ctrl_down) {if (key_down) drv->suspend(); return -2;} else return 0x30; - case XK_Return: return 0x24; - case XK_space: return 0x31; - case XK_BackSpace: return 0x33; - - case XK_Delete: return 0x75; - case XK_Insert: return 0x72; - case XK_Home: case XK_Help: return 0x73; - case XK_End: return 0x77; -#ifdef __hpux - case XK_Prior: return 0x74; - case XK_Next: return 0x79; -#else - case XK_Page_Up: return 0x74; - case XK_Page_Down: return 0x79; -#endif - - case XK_Control_L: return 0x36; - case XK_Control_R: return 0x36; - case XK_Shift_L: return 0x38; - case XK_Shift_R: return 0x38; - case XK_Alt_L: return 0x37; - case XK_Alt_R: return 0x37; - case XK_Meta_L: return 0x3a; - case XK_Meta_R: return 0x3a; - case XK_Menu: return 0x32; - case XK_Caps_Lock: return 0x39; - case XK_Num_Lock: return 0x47; - - case XK_Up: return 0x3e; - case XK_Down: return 0x3d; - case XK_Left: return 0x3b; - case XK_Right: return 0x3c; - - case XK_Escape: if (ctrl_down) {if (key_down) { quit_full_screen = true; emerg_quit = true; } return -2;} else return 0x35; - - case XK_F1: if (ctrl_down) {if (key_down) SysMountFirstFloppy(); return -2;} else return 0x7a; - case XK_F2: return 0x78; - case XK_F3: return 0x63; - case XK_F4: return 0x76; - case XK_F5: if (ctrl_down) {if (key_down) drv->toggle_mouse_grab(); return -2;} else return 0x60; - case XK_F6: return 0x61; - case XK_F7: return 0x62; - case XK_F8: return 0x64; - case XK_F9: return 0x65; - case XK_F10: return 0x6d; - case XK_F11: return 0x67; - case XK_F12: return 0x6f; - - case XK_Print: return 0x69; - case XK_Scroll_Lock: return 0x6b; - case XK_Pause: return 0x71; - -#if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End) - case XK_KP_0: case XK_KP_Insert: return 0x52; - case XK_KP_1: case XK_KP_End: return 0x53; - case XK_KP_2: case XK_KP_Down: return 0x54; - case XK_KP_3: case XK_KP_Next: return 0x55; - case XK_KP_4: case XK_KP_Left: return 0x56; - case XK_KP_5: case XK_KP_Begin: return 0x57; - case XK_KP_6: case XK_KP_Right: return 0x58; - case XK_KP_7: case XK_KP_Home: return 0x59; - case XK_KP_8: case XK_KP_Up: return 0x5b; - case XK_KP_9: case XK_KP_Prior: return 0x5c; - case XK_KP_Decimal: case XK_KP_Delete: return 0x41; -#else - case XK_KP_0: return 0x52; - case XK_KP_1: return 0x53; - case XK_KP_2: return 0x54; - case XK_KP_3: return 0x55; - case XK_KP_4: return 0x56; - case XK_KP_5: return 0x57; - case XK_KP_6: return 0x58; - case XK_KP_7: return 0x59; - case XK_KP_8: return 0x5b; - case XK_KP_9: return 0x5c; - case XK_KP_Decimal: return 0x41; -#endif - case XK_KP_Add: return 0x45; - case XK_KP_Subtract: return 0x4e; - case XK_KP_Multiply: return 0x43; - case XK_KP_Divide: return 0x4b; - case XK_KP_Enter: return 0x4c; - case XK_KP_Equal: return 0x51; - } - return -1; -} - -static int event2keycode(XKeyEvent &ev, bool key_down) -{ - KeySym ks; - int i = 0; - - do { - ks = XLookupKeysym(&ev, i++); - int as = kc_decode(ks, key_down); - if (as >= 0) - return as; - if (as == -2) - return as; - } while (ks != NoSymbol); - - return -1; -} - - -/* - * X event handling - */ - -static void handle_events(void) -{ - for (;;) { - XEvent event; - XDisplayLock(); - - if (!XCheckMaskEvent(x_display, eventmask, &event)) { - // Handle clipboard events - if (XCheckTypedEvent(x_display, SelectionRequest, &event)) - ClipboardSelectionRequest(&event.xselectionrequest); - else if (XCheckTypedEvent(x_display, SelectionClear, &event)) - ClipboardSelectionClear(&event.xselectionclear); - - // Window "close" widget clicked - else if (XCheckTypedEvent(x_display, ClientMessage, &event)) { - if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) { - ADBKeyDown(0x7f); // Power key - ADBKeyUp(0x7f); - } - } - XDisplayUnlock(); - break; - } - - switch (event.type) { - - // Mouse button - case ButtonPress: { - unsigned int button = event.xbutton.button; - if (button < 4) - ADBMouseDown(button - 1); - else if (button < 6) { // Wheel mouse - if (mouse_wheel_mode == 0) { - int key = (button == 5) ? 0x79 : 0x74; // Page up/down - ADBKeyDown(key); - ADBKeyUp(key); - } else { - int key = (button == 5) ? 0x3d : 0x3e; // Cursor up/down - for(int i=0; imouse_moved(event.xmotion.x, event.xmotion.y); - break; - - // Mouse entered window - case EnterNotify: - if (event.xcrossing.mode != NotifyGrab && event.xcrossing.mode != NotifyUngrab) - drv->mouse_moved(event.xmotion.x, event.xmotion.y); - break; - - // Keyboard - case KeyPress: { - int code = -1; - if (use_keycodes) { - if (event2keycode(event.xkey, true) != -2) // This is called to process the hotkeys - code = keycode_table[event.xkey.keycode & 0xff]; - } else - code = event2keycode(event.xkey, true); - if (code >= 0) { - if (!emul_suspended) { - if (code == 0x39) { // Caps Lock pressed - if (caps_on) { - ADBKeyUp(code); - caps_on = false; - } else { - ADBKeyDown(code); - caps_on = true; - } - } else - ADBKeyDown(code); - if (code == 0x36) - ctrl_down = true; - } else { - if (code == 0x31) - drv->resume(); // Space wakes us up - } - } - break; - } - case KeyRelease: { - int code = -1; - if (use_keycodes) { - if (event2keycode(event.xkey, false) != -2) // This is called to process the hotkeys - code = keycode_table[event.xkey.keycode & 0xff]; - } else - code = event2keycode(event.xkey, false); - if (code >= 0 && code != 0x39) { // Don't propagate Caps Lock releases - ADBKeyUp(code); - if (code == 0x36) - ctrl_down = false; - } - break; - } - - // Hidden parts exposed, force complete refresh of window - case Expose: - if (display_type == DISPLAY_WINDOW) { - const video_mode &mode = VideoMonitors[0]->get_current_mode(); -#ifdef ENABLE_VOSF - if (use_vosf) { // VOSF refresh - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); - } - else -#endif - if (frame_skip == 0) { // Dynamic refresh - int x1, y1; - for (y1=0; y1<16; y1++) - for (x1=0; x1<16; x1++) - updt_box[x1][y1] = true; - nr_boxes = 16 * 16; - } else // Static refresh - memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); - } - break; - } - - XDisplayUnlock(); - } -} - - -/* - * Window display update - */ - -// Dynamic display update (variable frame rate for each box) -static void update_display_dynamic(int ticker, driver_window *drv) -{ - int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xi; - int xil = 0; - int rxm = 0, rxmo = 0; - const video_mode &mode = drv->monitor.get_current_mode(); - int bytes_per_row = mode.bytes_per_row; - int bytes_per_pixel = mode.bytes_per_row / mode.x; - int rx = mode.bytes_per_row / 16; - int ry = mode.y / 16; - int max_box; - - y2s = sm_uptd[ticker % 8]; - y2a = 8; - for (i = 0; i < 6; i++) { - if (ticker % (2 << i)) - break; - } - max_box = sm_no_boxes[i]; - - if (y2a) { - for (y1=0; y1<16; y1++) { - for (y2=y2s; y2 < ry; y2 += y2a) { - i = ((y1 * ry) + y2) * bytes_per_row; - for (x1=0; x1<16; x1++, i += rx) { - if (updt_box[x1][y1] == false) { - if (memcmp(&the_buffer_copy[i], &the_buffer[i], rx)) { - updt_box[x1][y1] = true; - nr_boxes++; - } - } - } - } - } - } - - XDisplayLock(); - if ((nr_boxes <= max_box) && (nr_boxes)) { - for (y1=0; y1<16; y1++) { - for (x1=0; x1<16; x1++) { - if (updt_box[x1][y1] == true) { - if (rxm == 0) - xm = x1; - rxm += rx; - updt_box[x1][y1] = false; - } - if (((updt_box[x1+1][y1] == false) || (x1 == 15)) && (rxm)) { - if ((rxmo != rxm) || (xmo != xm) || (yo != y1 - 1)) { - if (rxmo) { - xi = xmo * rx; - yi = ymo * ry; - xil = rxmo; - yil = (yo - ymo +1) * ry; - } - rxmo = rxm; - xmo = xm; - ymo = y1; - } - rxm = 0; - yo = y1; - } - if (xil) { - i = (yi * bytes_per_row) + xi; - for (y2=0; y2 < yil; y2++, i += bytes_per_row) - memcpy(&the_buffer_copy[i], &the_buffer[i], xil); - if (mode.depth == VDEPTH_1BIT) { - if (drv->have_shm) - XShmPutImage(x_display, drv->w, drv->gc, drv->img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0); - else - XPutImage(x_display, drv->w, drv->gc, drv->img, xi * 8, yi, xi * 8, yi, xil * 8, yil); - } else { - if (drv->have_shm) - XShmPutImage(x_display, drv->w, drv->gc, drv->img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil, 0); - else - XPutImage(x_display, drv->w, drv->gc, drv->img, xi / bytes_per_pixel, yi, xi / bytes_per_pixel, yi, xil / bytes_per_pixel, yil); - } - xil = 0; - } - if ((x1 == 15) && (y1 == 15) && (rxmo)) { - x1--; - xi = xmo * rx; - yi = ymo * ry; - xil = rxmo; - yil = (yo - ymo +1) * ry; - rxmo = 0; - } - } - } - nr_boxes = 0; - } - XDisplayUnlock(); -} - -// Static display update (fixed frame rate, but incremental) -static void update_display_static(driver_window *drv) -{ - // Incremental update code - unsigned wide = 0, high = 0, x1, x2, y1, y2, i, j; - const video_mode &mode = drv->monitor.get_current_mode(); - int bytes_per_row = mode.bytes_per_row; - int bytes_per_pixel = mode.bytes_per_row / mode.x; - uint8 *p, *p2; - - // Check for first line from top and first line from bottom that have changed - y1 = 0; - for (j=0; j=y1; j--) { - if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) { - y2 = j; - break; - } - } - high = y2 - y1 + 1; - - // Check for first column from left and first column from right that have changed - if (high) { - if (mode.depth == VDEPTH_1BIT) { - x1 = mode.x - 1; - for (j=y1; j<=y2; j++) { - p = &the_buffer[j * bytes_per_row]; - p2 = &the_buffer_copy[j * bytes_per_row]; - for (i=0; i<(x1>>3); i++) { - if (*p != *p2) { - x1 = i << 3; - break; - } - p++; p2++; - } - } - x2 = x1; - for (j=y1; j<=y2; j++) { - p = &the_buffer[j * bytes_per_row]; - p2 = &the_buffer_copy[j * bytes_per_row]; - p += bytes_per_row; - p2 += bytes_per_row; - for (i=(mode.x>>3); i>(x2>>3); i--) { - p--; p2--; - if (*p != *p2) { - x2 = (i << 3) + 7; - break; - } - } - } - wide = x2 - x1 + 1; - - // Update copy of the_buffer - if (high && wide) { - for (j=y1; j<=y2; j++) { - i = j * bytes_per_row + (x1 >> 3); - memcpy(the_buffer_copy + i, the_buffer + i, wide >> 3); - } - } - - } else { - x1 = mode.x; - for (j=y1; j<=y2; j++) { - p = &the_buffer[j * bytes_per_row]; - p2 = &the_buffer_copy[j * bytes_per_row]; - for (i=0; ix2*bytes_per_pixel; i--) { - p--; - p2--; - if (*p != *p2) { - x2 = i / bytes_per_pixel; - break; - } - } - } - wide = x2 - x1; - - // Update copy of the_buffer - if (high && wide) { - for (j=y1; j<=y2; j++) { - i = j * bytes_per_row + x1 * bytes_per_pixel; - memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * wide); - } - } - } - } - - // Refresh display - XDisplayLock(); - if (high && wide) { - if (drv->have_shm) - XShmPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high, 0); - else - XPutImage(x_display, drv->w, drv->gc, drv->img, x1, y1, x1, y1, wide, high); - } - XDisplayUnlock(); -} - - -/* - * Screen refresh functions - */ - -// We suggest the compiler to inline the next two functions so that it -// may specialise the code according to the current screen depth and -// display type. A clever compiler would do that job by itself though... - -// NOTE: update_display_vosf is inlined too - -static inline void possibly_quit_dga_mode() -{ - // Quit DGA mode if requested (something terrible has happened and we - // want to give control back to the user) - if (quit_full_screen) { - quit_full_screen = false; - delete drv; - drv = NULL; - } -} - -static inline void possibly_ungrab_mouse() -{ - // Ungrab mouse if requested (something terrible has happened and we - // want to give control back to the user) - if (quit_full_screen) { - quit_full_screen = false; - if (drv) - drv->ungrab_mouse(); - } -} - -static inline void handle_palette_changes(void) -{ - LOCK_PALETTE; - - if (x_palette_changed) { - x_palette_changed = false; - XDisplayLock(); - drv->update_palette(); - XDisplayUnlock(); - } - - UNLOCK_PALETTE; -} - -static void video_refresh_dga(void) -{ - // Quit DGA mode if requested - possibly_quit_dga_mode(); -} - -#ifdef ENABLE_VOSF -#if REAL_ADDRESSING || DIRECT_ADDRESSING -static void video_refresh_dga_vosf(void) -{ - // Quit DGA mode if requested - possibly_quit_dga_mode(); - - // Update display (VOSF variant) - static int tick_counter = 0; - if (++tick_counter >= frame_skip) { - tick_counter = 0; - if (mainBuffer.dirty) { - LOCK_VOSF; - update_display_dga_vosf(static_cast(drv)); - UNLOCK_VOSF; - } - } -} -#endif - -static void video_refresh_window_vosf(void) -{ - // Ungrab mouse if requested - possibly_ungrab_mouse(); - - // Update display (VOSF variant) - static int tick_counter = 0; - if (++tick_counter >= frame_skip) { - tick_counter = 0; - if (mainBuffer.dirty) { - XDisplayLock(); - LOCK_VOSF; - update_display_window_vosf(static_cast(drv)); - UNLOCK_VOSF; - XSync(x_display, false); // Let the server catch up - XDisplayUnlock(); - } - } -} -#endif // def ENABLE_VOSF - -static void video_refresh_window_static(void) -{ - // Ungrab mouse if requested - possibly_ungrab_mouse(); - - // Update display (static variant) - static int tick_counter = 0; - if (++tick_counter >= frame_skip) { - tick_counter = 0; - update_display_static(static_cast(drv)); - } -} - -static void video_refresh_window_dynamic(void) -{ - // Ungrab mouse if requested - possibly_ungrab_mouse(); - - // Update display (dynamic variant) - static int tick_counter = 0; - tick_counter++; - update_display_dynamic(tick_counter, static_cast(drv)); -} - - -/* - * Thread for screen refresh, input handling etc. - */ - -static void VideoRefreshInit(void) -{ - // TODO: set up specialised 8bpp VideoRefresh handlers ? - if (display_type == DISPLAY_DGA) { -#if ENABLE_VOSF && (REAL_ADDRESSING || DIRECT_ADDRESSING) - if (use_vosf) - video_refresh = video_refresh_dga_vosf; - else -#endif - video_refresh = video_refresh_dga; - } - else { -#ifdef ENABLE_VOSF - if (use_vosf) - video_refresh = video_refresh_window_vosf; - else -#endif - if (frame_skip == 0) - video_refresh = video_refresh_window_dynamic; - else - video_refresh = video_refresh_window_static; - } -} - -// This function is called on non-threaded platforms from a timer interrupt -void VideoRefresh(void) -{ - // We need to check redraw_thread_active to inhibit refreshed during - // mode changes on non-threaded platforms - if (!redraw_thread_active) - return; - - // Handle X events - handle_events(); - - // Handle palette changes - handle_palette_changes(); - - // Update display - video_refresh(); -} - -const int VIDEO_REFRESH_HZ = 60; -const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ; - -#ifdef USE_PTHREADS_SERVICES -static void *redraw_func(void *arg) -{ - int fd = ConnectionNumber(x_display); - - uint64 start = GetTicks_usec(); - int64 ticks = 0; - uint64 next = GetTicks_usec() + VIDEO_REFRESH_DELAY; - - while (!redraw_thread_cancel) { - - int64 delay = next - GetTicks_usec(); - if (delay < -VIDEO_REFRESH_DELAY) { - - // We are lagging far behind, so we reset the delay mechanism - next = GetTicks_usec(); - - } else if (delay <= 0) { - - // Delay expired, refresh display - handle_events(); - handle_palette_changes(); - video_refresh(); - next += VIDEO_REFRESH_DELAY; - ticks++; - - } else { - - // No display refresh pending, check for X events - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = delay; - if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0) - handle_events(); - } - } - - uint64 end = GetTicks_usec(); - D(bug("%lld refreshes in %lld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); - - redraw_thread_cancel_ack = true; - return NULL; -} -#endif diff --git a/BasiliskII/src/Windows/BasiliskII.DebugJIT.props b/BasiliskII/src/Windows/BasiliskII.DebugJIT.props deleted file mode 100644 index 124285ea..00000000 --- a/BasiliskII/src/Windows/BasiliskII.DebugJIT.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - $(ProjectDir)Debug\ - - - - - - $(ToolsDir) - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/BasiliskII.ReleaseJIT.props b/BasiliskII/src/Windows/BasiliskII.ReleaseJIT.props deleted file mode 100644 index c67b5361..00000000 --- a/BasiliskII/src/Windows/BasiliskII.ReleaseJIT.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - $(ProjectDir)Release\ - - - - - - $(ToolsDir) - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/BasiliskII.ico b/BasiliskII/src/Windows/BasiliskII.ico deleted file mode 100755 index eb3ac0ef065e17dd4d66a244ce6c30c3f4a2c710..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2998 zcmc(gzi-?46~G@&0}=>=A}w5cgGe}%5ttqv+26s+R>U!I=OC~&WKMAd5unf^mWI>N zL8*Wo$D#!SaJ!)`+ToV`1)grWa88zH%5a56!Sz&PT{vtR8Q(>G?%F;N)0GP~oN+%?FYJx4;B z?f1p`?ZTLd6Z*+uFpxzTK^Qv3p7p-Sno1I`n(*i?5S+RW2C+wW6};JmQm9hvOQ^MQ#lQ1dXH zJ$0lRN^=o$bR3xu9H>RwT&Tm@wnTeT2)?cFNI=c1OyivO^As!+1 z*w$z+a0-yiq(5gDhwPyYq(ANT(MlA$t~8qi;;X$Z`WQHFF0-dOfK80UnGAC5_f0Ns z)BIExgW2raWUyHLV&2ZDv*y7fAIw$1{b~Mu-k8tw#ns0*Wp2)A3Xc&Crgw6oa;a5oZ)B9*Z&vM9Hkn}R~vU8?VO+e?M#0B{?D?$zE1g? z;`=_0isaU7ZFc=sN z34_7|&Mm5@BE4`*9mtqxS=F0iwu zCU*f-LDGT*1xy9G3zP-93vw6aw(YRFk(0k5e?fk2Q9=HK+7vJpFcj25+eTIF+aqD; zu5F|SCHYF&N;pdL+14rtH7MaIm4g?v?Z&BurG%vfq9mam0a!{LON>ecB`o}L5r>|X zu#{R4%c9euT|fpy4MPn>4MPn>4TBvg7)lsw7-|?w7zo3KJq$GrH4HTjgyupHLk&X> zLk&Pp{*qudjx|OZF*42>9JP(DHksU(Kgp9PPlTTsdGX?fynOjmUcY`VuU@^9w{PFd zyLa#8{rmTFets?=K75dmA3w^E|ET4U-+aUOcusZoJD?l!>`CM5u@>+Dtc%b6Zn{Ba zRuCt>RBsz8o9}tuz-xT+Su5Ro=&}yebjNjjakArXIZ2%OUW$JC*{@rv>yDOP?z+-A z=k*t*PRS^BVV)cz^BVm_|<9*cTY|xlU92PBa~>j90&Fr zeRX;|bPxUW(N?#0UR5i1a^L7rhVJRw?e_A>=>`ANQ%SFy z3cp(L-E{-+T;rm)@dNKVeK+ypb9ZmIj}=Vy?D$_V!r;G4_#;;pM_91m&{IXfQJqd& zaVrSMN8LDXjjPd?bM3E1_8Oz%vXyABx*9Zi;CBB_t^T`{mY*cOUc&NY$9nUAaZIOe z{$z*~0lFK9tu&y1DGBVX5>xrQfxcop8Xs>&>Obr< zr;3blXD47P^*IUBWz{18DSd0{z_f$*VbJ3#_Q&JE?;TgwanKks04HgBd>#Y|{|MuD z(r$UguQ`P*I|Z7?54)nRn8JghD% zESFbROZ%&{;qF$|)zL%T#-D^qL?1g$!&Rj9!Chh}7 axzyF^H27RLIv1UWJvSP^=jY&OUH=5W%Erh5 diff --git a/BasiliskII/src/Windows/BasiliskII.props b/BasiliskII/src/Windows/BasiliskII.props deleted file mode 100644 index 345f9f06..00000000 --- a/BasiliskII/src/Windows/BasiliskII.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - $(OutDir) - - - - - - $(ToolsDir) - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/BasiliskII.rc b/BasiliskII/src/Windows/BasiliskII.rc deleted file mode 100644 index ae955c53..00000000 --- a/BasiliskII/src/Windows/BasiliskII.rc +++ /dev/null @@ -1,2 +0,0 @@ -BasiliskII ICON PRELOAD "BasiliskII.ico" - diff --git a/BasiliskII/src/Windows/BasiliskII.sln b/BasiliskII/src/Windows/BasiliskII.sln deleted file mode 100644 index 1c4b7a1f..00000000 --- a/BasiliskII/src/Windows/BasiliskII.sln +++ /dev/null @@ -1,140 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasiliskII", "BasiliskII.vcxproj", "{1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}" - ProjectSection(ProjectDependencies) = postProject - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48} = {1A9EA738-8DA7-422F-9E0D-BE92893C0E48} - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04} = {95933FE9-C27C-41F0-B4AF-EAAADE94FD04} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "build68k", "build68k.vcxproj", "{7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gencpu", "gencpu.vcxproj", "{1A9EA738-8DA7-422F-9E0D-BE92893C0E48}" - ProjectSection(ProjectDependencies) = postProject - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0} = {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gencomp", "gencomp.vcxproj", "{95933FE9-C27C-41F0-B4AF-EAAADE94FD04}" - ProjectSection(ProjectDependencies) = postProject - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0} = {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDLmain", "..\..\..\..\SDL-1.2.15\VisualC\SDLmain\SDLmain.vcxproj", "{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL", "..\..\..\..\SDL-1.2.15\VisualC\SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug JIT|x64 = Debug JIT|x64 - Debug JIT|x86 = Debug JIT|x86 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release JIT|x64 = Release JIT|x64 - Release JIT|x86 = Release JIT|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug JIT|x64.ActiveCfg = Debug JIT|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug JIT|x64.Build.0 = Debug JIT|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug JIT|x86.ActiveCfg = Debug JIT|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug JIT|x86.Build.0 = Debug JIT|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug|x64.ActiveCfg = Debug|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug|x64.Build.0 = Debug|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug|x86.ActiveCfg = Debug|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Debug|x86.Build.0 = Debug|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release JIT|x64.ActiveCfg = Release JIT|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release JIT|x64.Build.0 = Release JIT|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release JIT|x86.ActiveCfg = Release JIT|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release JIT|x86.Build.0 = Release JIT|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release|x64.ActiveCfg = Release|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release|x64.Build.0 = Release|x64 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release|x86.ActiveCfg = Release|Win32 - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0}.Release|x86.Build.0 = Release|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug JIT|x64.ActiveCfg = Debug|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug JIT|x64.Build.0 = Debug|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug JIT|x86.ActiveCfg = Debug|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug JIT|x86.Build.0 = Debug|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug|x64.ActiveCfg = Debug|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug|x64.Build.0 = Debug|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug|x86.ActiveCfg = Debug|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Debug|x86.Build.0 = Debug|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release JIT|x64.ActiveCfg = Release|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release JIT|x64.Build.0 = Release|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release JIT|x86.ActiveCfg = Release|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release JIT|x86.Build.0 = Release|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release|x64.ActiveCfg = Release|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release|x64.Build.0 = Release|x64 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release|x86.ActiveCfg = Release|Win32 - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0}.Release|x86.Build.0 = Release|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug JIT|x64.ActiveCfg = Debug|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug JIT|x64.Build.0 = Debug|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug JIT|x86.ActiveCfg = Debug|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug JIT|x86.Build.0 = Debug|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug|x64.ActiveCfg = Debug|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug|x64.Build.0 = Debug|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug|x86.ActiveCfg = Debug|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Debug|x86.Build.0 = Debug|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release JIT|x64.ActiveCfg = Release|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release JIT|x64.Build.0 = Release|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release JIT|x86.ActiveCfg = Release|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release JIT|x86.Build.0 = Release|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release|x64.ActiveCfg = Release|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release|x64.Build.0 = Release|x64 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release|x86.ActiveCfg = Release|Win32 - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48}.Release|x86.Build.0 = Release|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug JIT|x64.ActiveCfg = Debug|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug JIT|x64.Build.0 = Debug|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug JIT|x86.ActiveCfg = Debug|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug JIT|x86.Build.0 = Debug|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug|x64.ActiveCfg = Debug|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug|x64.Build.0 = Debug|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug|x86.ActiveCfg = Debug|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Debug|x86.Build.0 = Debug|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release JIT|x64.ActiveCfg = Release|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release JIT|x64.Build.0 = Release|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release JIT|x86.ActiveCfg = Release|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release JIT|x86.Build.0 = Release|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release|x64.ActiveCfg = Release|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release|x64.Build.0 = Release|x64 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release|x86.ActiveCfg = Release|Win32 - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04}.Release|x86.Build.0 = Release|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug JIT|x64.ActiveCfg = Debug|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug JIT|x64.Build.0 = Debug|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug JIT|x86.ActiveCfg = Debug|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug JIT|x86.Build.0 = Debug|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x64.ActiveCfg = Debug|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x64.Build.0 = Debug|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x86.ActiveCfg = Debug|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Debug|x86.Build.0 = Debug|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release JIT|x64.ActiveCfg = Release|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release JIT|x64.Build.0 = Release|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release JIT|x86.ActiveCfg = Release|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release JIT|x86.Build.0 = Release|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|x64.ActiveCfg = Release|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|x64.Build.0 = Release|x64 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|x86.ActiveCfg = Release|Win32 - {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}.Release|x86.Build.0 = Release|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug JIT|x64.ActiveCfg = Debug|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug JIT|x64.Build.0 = Debug|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug JIT|x86.ActiveCfg = Debug|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug JIT|x86.Build.0 = Debug|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.ActiveCfg = Debug|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.Build.0 = Debug|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x86.ActiveCfg = Debug|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x86.Build.0 = Debug|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release JIT|x64.ActiveCfg = Release|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release JIT|x64.Build.0 = Release|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release JIT|x86.ActiveCfg = Release|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release JIT|x86.Build.0 = Release|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.ActiveCfg = Release|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.Build.0 = Release|x64 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x86.ActiveCfg = Release|Win32 - {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/BasiliskII/src/Windows/BasiliskII.vcxproj b/BasiliskII/src/Windows/BasiliskII.vcxproj deleted file mode 100644 index cd05c309..00000000 --- a/BasiliskII/src/Windows/BasiliskII.vcxproj +++ /dev/null @@ -1,685 +0,0 @@ - - - - - Debug JIT - Win32 - - - Debug JIT - x64 - - - Debug - Win32 - - - Debug - x64 - - - Release JIT - Win32 - - - Release JIT - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {81ce8daf-ebb2-4761-8e45-b71abcca8c68} - - - {da956fd3-e142-46f2-9dd5-c78bebb56b7a} - - - - {1AAA5D96-9498-4EB5-A436-0143E2B7A0B0} - Win32Proj - BasiliskII - 8.1 - - - - Application - true - v140_xp - Unicode - - - Application - true - v140_xp - Unicode - - - Application - true - v140_xp - Unicode - - - Application - true - v140_xp - Unicode - - - Application - false - v140_xp - true - Unicode - - - Application - false - v140_xp - true - Unicode - - - Application - false - v140_xp - true - Unicode - - - Application - false - v140_xp - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(Configuration)\$(ProjectName)\ - ClCompile - - - ClCompile - true - - - true - $(Configuration)\$(ProjectName)\ - ClCompile - - - ClCompile - true - - - false - $(Configuration)\$(ProjectName)\ - ClCompile - - - ClCompile - false - - - false - $(Configuration)\$(ProjectName)\ - ClCompile - - - ClCompile - false - - - - - - Level3 - Disabled - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - - - Level3 - Disabled - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - - - Level3 - Disabled - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;USE_JIT;USE_JIT_FPU;JIT_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - - - Level3 - Disabled - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;USE_JIT;USE_JIT_FPU;JIT_DEBUG;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - Level3 - - - MaxSpeed - true - true - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;OPTIMIZED_FLAGS;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - true - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - Level3 - - - MaxSpeed - true - true - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;OPTIMIZED_FLAGS;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - true - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - Level3 - - - MaxSpeed - true - true - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;OPTIMIZED_FLAGS;USE_JIT;USE_JIT_FPU;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - true - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - Level3 - - - MaxSpeed - true - true - HAVE_CONFIG_H;DIRECT_ADDRESSING;UNALIGNED_PROFITABLE;MSVC_INTRINSICS;OPTIMIZED_FLAGS;SAHF_SETO_PROFITABLE;FPU_IEEE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;OPTIMIZED_FLAGS;USE_JIT;USE_JIT_FPU;%(PreprocessorDefinitions) - ..\include;..\uae_cpu;.;..\CrossPlatform;..\slirp;..\..\..\..\SDL-1.2.15\include - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - $(IntDir)%(RelativeDir) - - - Windows - true - true - true - WS2_32.lib;IPHlpApi.lib;%(AdditionalDependencies) - - - cd ..\uae_cpu -"$(ToolsDir)gencpu" -"$(ToolsDir)gencomp" - - - - Generating CPU emulation sources... - - - ..\uae_cpu\cpustbl.cpp;..\uae_cpu\cpustbl_nf.cpp;..\uae_cpu\cputbl.h;..\uae_cpu\cpuemu.cpp;..\uae_cpu\cpuemu_nf.cpp;..\uae_cpu\compstbl.cpp;..\uae_cpu\comptbl.h;..\uae_cpu\compemu.cpp;%(Outputs) - - - $(ToolsDir)gencpu.exe;$(ToolsDir)gencomp.exe - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/BasiliskII.vcxproj.filters b/BasiliskII/src/Windows/BasiliskII.vcxproj.filters deleted file mode 100644 index 50eae3d1..00000000 --- a/BasiliskII/src/Windows/BasiliskII.vcxproj.filters +++ /dev/null @@ -1,589 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - - - - Resource Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/BasiliskIIGUI.ico b/BasiliskII/src/Windows/BasiliskIIGUI.ico deleted file mode 100755 index 67d4c55fab03db3146193a2c8fcfc69907eaabc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmchWJ#vIF422(?%(zQ90##;@kt4aI_0fEslqu7ZPqGc(#SJMUkfo~K;7@qcE31@<9aF-IC#51-QI&H>nq%`<+h!WfVQh$Ucf(}0+9O}TOLWlj#9k%d?_(vS@ zhtB_uPxal<*Ed7Oev8uSQNQgbmCE;P?Qr=cz4!c0+y9GgUz_t8Uf?$88GTHN8OOs+ zyI@7VHs?NE)M(_bp)q{oDCCYUpxD>wQo&^eIyQw6C(kdq=CwL?pBy+RocOn|vgQ2( DRT%bz diff --git a/BasiliskII/src/Windows/BasiliskIIGUI.rc b/BasiliskII/src/Windows/BasiliskIIGUI.rc deleted file mode 100644 index 2a0e5586..00000000 --- a/BasiliskII/src/Windows/BasiliskIIGUI.rc +++ /dev/null @@ -1,2 +0,0 @@ -BasiliskIIGUI ICON PRELOAD "BasiliskIIGUI.ico" - diff --git a/BasiliskII/src/Windows/Makefile.in b/BasiliskII/src/Windows/Makefile.in deleted file mode 100755 index dfa59a60..00000000 --- a/BasiliskII/src/Windows/Makefile.in +++ /dev/null @@ -1,236 +0,0 @@ -# Windows Makefile for Basilisk II - -## System specific configuration - -SHELL = /bin/sh - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -datadir = @datadir@ -mandir = @mandir@ -man1dir = $(mandir)/man1 - -KEYCODES = ../SDL/keycodes - -DESTDIR = - -SDL_CFLAGS = @SDL_CFLAGS@ -SDL_LIBS = @SDL_LIBS@ -WANT_GTK = @WANT_GTK@ -GTK_CFLAGS = @GTK_CFLAGS@ -GTK_LIBS = @GTK_LIBS@ - -SLIRP_CFLAGS = @SLIRP_CFLAGS@ -SLIRP_SRCS = \ - ../slirp/bootp.c ../slirp/ip_output.c ../slirp/tcp_input.c \ - ../slirp/cksum.c ../slirp/mbuf.c ../slirp/tcp_output.c \ - ../slirp/debug.c ../slirp/misc.c ../slirp/tcp_subr.c \ - ../slirp/if.c ../slirp/sbuf.c ../slirp/tcp_timer.c \ - ../slirp/ip_icmp.c ../slirp/slirp.c ../slirp/tftp.c \ - ../slirp/ip_input.c ../slirp/socket.c ../slirp/udp.c -SLIRP_OBJS = $(SLIRP_SRCS:../slirp/%.c=$(OBJ_DIR)/slirp-%.o) - -LN_S = @LN_S@ -WINDRES = @WINDRES@ -CC = @CC@ -CXX = @CXX@ -CFLAGS = @CFLAGS@ $(SDL_CFLAGS) -CXXFLAGS = @CXXFLAGS@ $(SDL_CFLAGS) -CPPFLAGS = @CPPFLAGS@ -I../include -I. -I../CrossPlatform @CPUINCLUDES@ -I../slirp -DEFS = @DEFS@ @DEFINES@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -lwsock32 -liphlpapi -CPUSRCS = @CPUSRCS@ - -HOST_CC = gcc -HOST_CXX = g++ -HOST_CFLAGS = -O2 -HOST_CXXFLAGS = -O2 -HOST_LDFLAGS = - -## Files -XPLATSRCS = vm_alloc.cpp vm_alloc.h sigsegv.cpp sigsegv.h video_vosf.h video_blit.cpp video_blit.h - -CDENABLESRCS = cdenable/cache.cpp cdenable/eject_nt.cpp cdenable/ntcd.cpp - -ROUTERSRCS = router/arp.cpp router/dump.cpp router/dynsockets.cpp router/ftp.cpp \ - router/icmp.cpp router/mib/interfaces.cpp router/iphelp.cpp router/ipsocket.cpp \ - router/mib/mibaccess.cpp router/router.cpp router/tcp.cpp router/udp.cpp b2ether/packet32.cpp - -SRCS = ../main.cpp main_windows.cpp ../prefs.cpp ../prefs_items.cpp prefs_windows.cpp \ - sys_windows.cpp ../rom_patches.cpp ../slot_rom.cpp ../rsrc_patches.cpp \ - ../emul_op.cpp ../macos_util.cpp ../xpram.cpp xpram_windows.cpp ../timer.cpp \ - timer_windows.cpp ../adb.cpp ../serial.cpp serial_windows.cpp \ - ../ether.cpp ether_windows.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp \ - ../scsi.cpp ../dummy/scsi_dummy.cpp ../video.cpp ../SDL/video_sdl.cpp \ - video_blit.cpp ../audio.cpp ../SDL/audio_sdl.cpp clip_windows.cpp \ - ../extfs.cpp extfs_windows.cpp ../user_strings.cpp user_strings_windows.cpp \ - vm_alloc.cpp sigsegv.cpp posix_emu.cpp util_windows.cpp \ - ../dummy/prefs_editor_dummy.cpp BasiliskII.rc \ - $(CDENABLESRCS) $(ROUTERSRCS) $(CPUSRCS) $(SLIRP_OBJS) - -UI_SRCS = ../prefs.cpp prefs_windows.cpp prefs_editor_gtk.cpp xpram_windows.cpp \ - ../prefs_items.cpp ../user_strings.cpp user_strings_windows.cpp util_windows.cpp \ - b2ether/Packet32.cpp BasiliskIIGUI.rc - -UI_APP = BasiliskIIGUI.exe - -APP = BasiliskII.exe - -PROGS = $(APP) - -ifeq ($(WANT_GTK),yes) -PROGS += $(UI_APP) -endif - -## Rules -.PHONY: modules install installdirs uninstall mostlyclean clean distclean depend dep -.SUFFIXES: -.SUFFIXES: .c .cpp .s .o .h - -all: $(PROGS) - -$(XPLATSRCS): %: ../CrossPlatform/% - $(LN_S) $< $@ - -OBJ_DIR = obj -$(OBJ_DIR):: - @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 - -define SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ - $(basename $(notdir $(file)))))) -endef -OBJS = $(SRCS_LIST_TO_OBJS) - -define UI_SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(UI_SRCS), \ - $(basename $(notdir $(file)))))) -endef -UI_OBJS = $(UI_SRCS_LIST_TO_OBJS) - -SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) -VPATH := -VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) - -$(APP): $(XPLATSRCS) $(OBJ_DIR) $(OBJS) - $(CXX) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) $(SDL_LIBS) - -$(UI_APP): $(XPLATSRCS) $(OBJ_DIR) $(UI_OBJS) - $(CXX) -o $@ $(LDFLAGS) $(UI_OBJS) $(LIBS) $(GTK_LIBS) -mwindows -mno-cygwin - -mostlyclean: - rm -f $(APP) $(UI_APP) $(OBJ_DIR)/* core* *.core *~ *.bak - -clean: mostlyclean - rm -f $(XPLATSRCS) - rm -f cpuemu.cpp cpudefs.cpp cputmp*.s cpufast*.s cpustbl.cpp cputbl.h compemu.cpp compstbl.cpp comptbl.h - -distclean: clean - rm -rf $(OBJ_DIR) - rm -rf autom4te.cache - rm -f Makefile - rm -f config.cache config.log config.status config.h - -depend dep: - makedepend $(CPPFLAGS) -Y. $(SRCS) 2>/dev/null - -$(OBJ_DIR)/%.ho : %.c - $(HOST_CC) $(CPPFLAGS) $(DEFS) $(HOST_CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.ho : %.cpp - $(HOST_CXX) $(CPPFLAGS) $(DEFS) $(HOST_CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/slirp-%.o : ../slirp/%.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(SLIRP_CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.s - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/prefs_editor_gtk.o: prefs_editor_gtk.cpp - $(CXX) -O2 -mno-cygwin -mms-bitfields $(CPPFLAGS) $(DEFS) $(GTK_CFLAGS) -c $< -o $@ - -# Windows resources -$(OBJ_DIR)/%.o: %.rc - $(WINDRES) --include-dir ../Windows -i $< -o $@ -$(OBJ_DIR)/build68k.exe: $(OBJ_DIR)/build68k.ho - $(HOST_CC) $(HOST_LDFLAGS) -o $@ $< -$(OBJ_DIR)/gencpu.exe: $(OBJ_DIR)/gencpu.ho $(OBJ_DIR)/readcpu.ho $(OBJ_DIR)/cpudefs.ho - $(HOST_CXX) $(HOST_LDFLAGS) -o $@ $(OBJ_DIR)/gencpu.ho $(OBJ_DIR)/readcpu.ho $(OBJ_DIR)/cpudefs.ho -$(OBJ_DIR)/gencomp.exe: $(OBJ_DIR)/gencomp.ho $(OBJ_DIR)/readcpu.ho $(OBJ_DIR)/cpudefs.ho - $(HOST_CXX) $(HOST_LDFLAGS) -o $@ $(OBJ_DIR)/gencomp.ho $(OBJ_DIR)/readcpu.ho $(OBJ_DIR)/cpudefs.ho - -cpudefs.cpp: $(OBJ_DIR)/build68k.exe ../uae_cpu/table68k - $(OBJ_DIR)/build68k.exe ../uae_cpu/table68k >cpudefs.cpp -cpustbl.cpp: cpuemu.cpp -cpustbl_nf.cpp: cpustbl.cpp -compstbl.cpp: compemu.cpp -cputbl.h: cpuemu.cpp -comptbl.h: compemu.cpp - -cpuemu.cpp: $(OBJ_DIR)/gencpu.exe - $(OBJ_DIR)/gencpu.exe - -compemu.cpp: $(OBJ_DIR)/gencomp.exe - $(OBJ_DIR)/gencomp.exe - -$(OBJ_DIR)/cpustbl_nf.o: cpustbl.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -DNOFLAGS -c $< -o $@ - -$(OBJ_DIR)/compemu_support.o: compemu_support.cpp comptbl.h - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/cpuemu1.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_1 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu2.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_2 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu3.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_3 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu4.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_4 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu5.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_5 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu6.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_6 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu7.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_7 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu8.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_8 $(CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/cpuemu1_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_1 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu2_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_2 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu3_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_3 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu4_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_4 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu5_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_5 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu6_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_6 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu7_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_7 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/cpuemu8_nf.o: cpuemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_8 -DNOFLAGS $(CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/compemu1.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_1 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu2.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_2 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu3.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_3 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu4.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_4 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu5.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_5 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu6.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_6 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu7.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_7 $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/compemu8.o: compemu.cpp - $(CXX) $(CPPFLAGS) $(DEFS) -DPART_8 $(CXXFLAGS) -c $< -o $@ - -#------------------------------------------------------------------------- -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/BasiliskII/src/Windows/b2ether/driver/DEBUG.H b/BasiliskII/src/Windows/b2ether/driver/DEBUG.H deleted file mode 100755 index 0a12c737..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/DEBUG.H +++ /dev/null @@ -1,43 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if DBG - -#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f)) -extern ULONG PacketDebugFlag; - -#define PACKET_DEBUG_LOUD 0x00000001 // debugging info -#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info - -#define PACKET_DEBUG_INIT 0x00000100 // init debugging info - -#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A } -#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A } -#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A } - -#else - -#define IF_LOUD(A) -#define IF_VERY_LOUD(A) -#define IF_INIT_LOUD(A) - -#endif diff --git a/BasiliskII/src/Windows/b2ether/driver/MAKEFILE b/BasiliskII/src/Windows/b2ether/driver/MAKEFILE deleted file mode 100755 index 9c985f57..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/MAKEFILE +++ /dev/null @@ -1,7 +0,0 @@ -# -# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source -# file to this component. This file merely indirects to the real make file -# that is shared by all the driver components of the Windows NT DDK -# - -!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/BasiliskII/src/Windows/b2ether/driver/OEMSETUP.INF b/BasiliskII/src/Windows/b2ether/driver/OEMSETUP.INF deleted file mode 100755 index 18a21ce7..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/OEMSETUP.INF +++ /dev/null @@ -1,430 +0,0 @@ -[Identification] -OptionType = NetService - -[Options] -B2ETHER - -[FileConstants] -UtilityInf = "UTILITY.INF" -subroutineinf = "SUBROUTN.INF" -SoftwareType = "service" -Exit_Code = 0 -NetEventDLL = "%SystemRoot%\System32\netevent.dll" -Manufacturer = "Microsoft" -ProductMajorVersion = "4" -ProductMinorVersion = "0" -ProductVersion = $(ProductMajorVersion)"."$(ProductMinorVersion) - -ProductSoftwareName = "B2Ether" -ProductSoftwareImagePath = "\SystemRoot\System32\drivers\B2Ether.sys" - -NetRuleSoftwareType = "B2Ether lmNetService ndisTransport" -NetRuleSoftwareClass = {"rasCapableTransport ndisTransport"} - -NetRuleSoftwareUse = "service yes yes" -NetRuleSoftwareBindForm = """B2Ether"" yes yes simple" - -ProductKeyName = $(!NTN_SoftwareBase)"\"$(Manufacturer)"\"$(ProductSoftwareName)"\CurrentVersion" -ParamKeyName = $(!NTN_ServiceBase)"\"$(ProductSoftwareName)"\Parameters" - -[GeneralConstants] -from = "" -to = "" -ExitCodeOk = 0 -ExitCodeCancel = 1 -ExitCodeFatal = 2 -KeyNull = "" -MAXIMUM_ALLOWED = 33554432 -RegistryErrorIndex = NO_ERROR -KeyProduct = "" -KeyParameters = "" -TRUE = 1 -FALSE = 0 -NoTitle = 0 -ExitState = "Active" -OldVersionExisted = $(FALSE) -DriverPath = $(!STF_NTPATH)\drivers - -[date] -Now = {} ? $(!LIBHANDLE) GetSystemDate - -[Identify] -read-syms Identification -set Status = STATUS_SUCCESSFUL -set Identifier = $(OptionType) -set Media = #("Source Media Descriptions", 1, 1) -Return $(Status) $(Identifier) $(Media) - -[ReturnOptions] - set Status = STATUS_FAILED - set OptionList = {} - set OptionTextList = {} - set LanguageList = ^(LanguagesSupported, 1) - Ifcontains(i) $($0) in $(LanguageList) - goto returnoptions - else - set Status = STATUS_NOLANGUAGE - goto finish_ReturnOptions - endif -returnoptions = + - set OptionList = ^(Options, 1) - set OptionTextList = ^(OptionsText$($0), 1) - set Status = STATUS_SUCCESSFUL -finish_ReturnOptions = + - Return $(Status) $(OptionList) $(OptionTextList) - -[InstallOption] - set Option = $($1) - set SrcDir = $($2) - set AddCopy = $($3) - set DoCopy = $($4) - set DoConfig = $($5) - set LanguageList = ^(LanguagesSupported, 1) - Ifcontains(i) $($0) NOT-IN $(LanguageList) - Return STATUS_NOLANGUAGE - endif - Debug-Output "OEMSETUP.INF: STF_CWDDIR is: "$(!STF_CWDDIR) - Debug-Output "OEMSETUP.INF: STF_LANGUAGE is: "$(!STF_LANGUAGE) - set-subst LF = "\n" - read-syms GeneralConstants - read-syms FileConstants - read-syms DialogConstants$(!STF_LANGUAGE) - ifstr(i) $(!NTN_Origination) == "NCPA" - set Continue = $(OK) - endif - read-syms FileConstants$(!STF_LANGUAGE) - detect date - set-title $(FunctionTitle) - set to = Begin - set from = Begin - set CommonStatus = STATUS_SUCCESSFUL - EndWait -Begin = + - Ifstr(i) $(!NTN_InstallMode) == deinstall - set StartLabel = removeadapter - else-Ifstr(i) $(!NTN_InstallMode) == Update - set StartLabel = UpgradeSoftware - else-Ifstr(i) $(!NTN_InstallMode) == bind - set StartLabel = bindingadapter - else-Ifstr(i) $(!NTN_InstallMode) == configure - Shell $(UtilityInf),RegistryErrorString,CANNOT_CONFIGURE_SOFTWARE - ifint $($ShellCode) != $(!SHELL_CODE_OK) - Debug-Output "OEMSETUP.INF: ShellCode error: cannot get an error string." - goto ShellCodeError - endif - set Error = $($R0) - set from = end - set to = end - goto nonfatalinfo - else - set StartLabel = installadapter - endif - set RadioDefault = 2 - set RadioIn = {$(RadioDefault)} - set from = $(fatal) - set to = $(fatal) - goto $(StartLabel) -installadapter = + - OpenRegKey $(!REG_H_LOCAL) "" $(ProductKeyName) $(MAXIMUM_ALLOWED) KeyProduct - Ifstr $(KeyProduct) != $(KeyNull) - CloseRegKey $(KeyProduct) - Shell $(UtilityInf), VerExistedDlg, $(ProductSoftwareTitle),+ - $(ProductVersion) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - Debug-Output "ShellCode error: cannot get an error string." - goto ShellCodeError - endif - goto end - endif - CloseRegKey $(KeyProduct) - goto installproduct -installproduct = + - StartWait - ifint $(OldVersionExisted) == $(FALSE) - Ifstr(i) $(DoCopy) == "YES" - Shell $(UtilityInf), DoAskSource, $(!STF_CWDDIR), $(SrcDir) YES - Ifint $($ShellCode) != $(!SHELL_CODE_OK) - Goto ShellCodeError - Else-Ifstr(i) $($R0) == STATUS_FAILED - Shell $(UtilityInf) RegistryErrorString "ASK_SOURCE_FAIL" - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - set Error = $($R0) - Goto fatal - Else-Ifstr(i) $($R0) == STATUS_USERCANCEL - Goto successful - Endif - Set SrcDir = $($R1) - Endif - install "Install-Option" - ifstr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS - Shell $(UtilityInf) RegistryErrorString "UNABLE_COPY_FILE" - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - set Error = $($R0) - goto fatal - endif - set OEM_ABANDON_ON = TRUE - Shell $(UtilityInf), AddSoftwareComponent, $(Manufacturer), + - $(ProductSoftwareName), + - $(ProductSoftwareName), + - $(ProductSoftwareDisplayName), $(STF_CONTEXTINFNAME), + - $(ProductSoftwareImagePath), "kernel", "TDI", {}, "",+ - $(NetEventDLL) - set RegistryErrorIndex = $($R0) - Ifstr(i) $(RegistryErrorIndex) != NO_ERROR - EndWait - CloseRegKey $($R1) - CloseRegKey $($R2) - CloseRegKey $($R3) - CloseRegKey $($R4) - CloseRegKey $($R5) - goto fatalRegistry - endif - Set SoftProductKey = $($R1) - Set SoftNetRuleKey = $($R2) - Set SoftServiceKey = $($R3) - set KeyParameters = $($R4) - Set SoftLinkageKey = $($R5) - set NewValueList = {{SoftwareType,$(NoTitle),$(!REG_VT_SZ),$(SoftwareType)},+ - {MajorVersion,$(NoTitle),$(!REG_VT_DWORD),$(ProductMajorVersion)},+ - {MinorVersion,$(NoTitle),$(!REG_VT_DWORD),$(ProductMinorVersion)},+ - {Title,$(NoTitle),$(!REG_VT_SZ),$(ProductSoftwareTitle)},+ - {Description,$(NoTitle),$(!REG_VT_SZ),$(ProductSoftwareDescription)},+ - {ServiceName,$(NoTitle),$(!REG_VT_SZ),$(ProductSoftwareName)},+ - {InstallDate,$(NoTitle),$(!REG_VT_DWORD),*($(Now),1)}} - Shell $(UtilityInf), AddValueList, $(SoftProductKey), $(NewValueList) - set RegistryErrorIndex = $($R0) - Ifstr $(RegistryErrorIndex) != NO_ERROR - CloseRegKey $(SoftProductKey) - CloseRegKey $(SoftNetRuleKey) - CloseRegKey $(SoftServiceKey) - CloseRegKey $(SoftLinkageKey) - CloseRegKey $(KeyParameters) - goto fatalRegistry - endif - set NewValueList = {{type ,$(NoTitle),$(!REG_VT_SZ),$(NetRuleSoftwareType)}, + - {use ,$(NoTitle),$(!REG_VT_SZ),$(NetRuleSoftwareUse)}, + - {bindform,$(NoTitle),$(!REG_VT_SZ),$(NetRuleSoftwareBindForm)}, + - {InfOption,$(NoTitle),$(!REG_VT_SZ),$(Option)}} - Shell $(UtilityInf), AddValueList, $(SoftNetRuleKey), $(NewValueList) - set RegistryErrorIndex = $($R0) - Ifstr $(RegistryErrorIndex) != NO_ERROR - CloseRegKey $(SoftProductKey) - CloseRegKey $(SoftNetRuleKey) - CloseRegKey $(SoftServiceKey) - CloseRegKey $(SoftLinkageKey) - CloseRegKey $(KeyParameters) - goto fatalRegistry - endif - Set NewValueList = {{Author,$(NoTitle),$(!REG_VT_SZ),"Lauri Pesonen"}} - Shell $(UtilityInf), AddValueList, $(KeyParameters), $(NewValueList) - Ifstr $(RegistryErrorIndex) != NO_ERROR - CloseRegKey $(SoftProductKey) - CloseRegKey $(SoftNetRuleKey) - CloseRegKey $(SoftServiceKey) - CloseRegKey $(SoftLinkageKey) - goto fatalRegistry - endif - CloseRegKey $(SoftProductKey) - CloseRegKey $(SoftNetRuleKey) - CloseRegKey $(SoftServiceKey) - CloseRegKey $(SoftLinkageKey) - endif - goto writeparameters -writeparameters = + - CloseRegKey $(KeyParameters) - EndWait - goto successful -bindingadapter =+ - set Error = "Binding: Sorry, not yet implemented." - goto fatal -removeadapter = + - Shell $(UtilityInf), RemoveSoftwareComponent, $(Manufacturer), + - $(ProductSoftwareName) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - Debug-Output "ShellCode error" - goto ShellCodeError - endif - set RegistryErrorIndex = $($R0) - Ifstr(i) $(RegistryErrorIndex) != NO_ERROR - goto fatalregistry - endif - goto end -UpgradeSoftware = + - ifstr(i) $(ProductKeyName) == $(!NTN_RegBase) - OpenRegKey $(!REG_H_LOCAL) "" $(ProductKeyName) $(MAXIMUM_ALLOWED) KeyProduct - Ifstr $(KeyProduct) != $(KeyNull) - GetRegValue $(KeyProduct),"MajorVersion", VersionInfo - set Version = *($(VersionInfo), 4) - Shell $(UtilityInf), GetInfFileNameFromRegistry, $(KeyProduct) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - Debug-Output "ShellCode error" - goto ShellCodeError - endif - set !UG_Filename = $($R0) - ifstr(i) $(!UG_Filename) != "" - install "Install-Update" - ifstr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS - goto fatal - endif - endif - SetRegValue $(KeyProduct) {MajorVersion,$(NoTitle),$(!REG_VT_SZ),$(ProductMajorVersion)} - SetRegValue $(KeyProduct) {MinorVersion,$(NoTitle),$(!REG_VT_SZ),$(ProductMinorVersion)} - ifint $(Version) != $(ProductVersion) - endif - CloseRegKey $(KeyProduct) - else - goto fatalregistry - endif - endif - goto end -successful = + - goto end -warning = + - Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "WARNING", $(Error) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - ifstr(i) $($R1) == "OK" - goto $(to) - else-ifstr(i) $($R1) == "CANCEL" - goto $(from) - else - goto "end" - endif -nonfatalinfo = + - Set CommonStatus = STATUS_USERCANCEL - Set Severity = STATUS - goto nonfatalmsg -nonfatal = + - Set Severity = NONFATAL - goto nonfatalmsg -nonfatalmsg = + - ifstr(i) $(Error) == "" - Shell $(UtilityInf) RegistryErrorString "SETUP_FAIL" - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - set Error = $($R0) - endif - Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), $(Severity), $(Error) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - ifstr(i) $($R1) == "OK" - goto $(from) - else - goto "end" - endif -fatalregistry = + - Shell $(UtilityInf) RegistryErrorString $(RegistryErrorIndex) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - set Error = $($R0) - goto fatal -fatal = + - ifstr(i) $(Error) == "" - Shell $(UtilityInf) RegistryErrorString "SETUP_FAIL" - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - set Error = $($R0) - endif - Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "FATAL", $(Error) - ifint $($ShellCode) != $(!SHELL_CODE_OK) - goto ShellCodeError - endif - goto setfailed -ShellCodeError = + - set DlgType = "MessageBox" - set STF_MB_TITLE = $(ShellCodeErrorTitle) - set STF_MB_TEXT = $(ShellCodeErrorText) - set STF_MB_TYPE = 1 - set STF_MB_ICON = 3 - set STF_MB_DEF = 1 - ui start "Error Message" - goto setfailed -setfailed = + - set CommonStatus = STATUS_FAILED - ifstr(i) $(OEM_ABANDON_ON) == TRUE - set OEM_ABANDON_ON = FALSE - goto removeadapter - endif - goto end -end = + - goto term -term = + - Return $(CommonStatus) - -[Install-Option] - set STF_VITAL = "" - ifstr(i) $(AddCopy) == "YES" - AddSectionFilesToCopyList Files-$(Option) $(SrcDir) $(!STF_WINDOWSSYSPATH)\drivers - AddSectionFilesToCopyList Files-App $(SrcDir) $(!STF_WINDOWSSYSPATH) - endif - ifstr(i) $(DoCopy) == "YES" - set !STF_NCPA_FLUSH_COPYLIST = TRUE - CopyFilesInCopyList - endif - ifstr(i) $(DoConfig) == "YES" - endif - Exit - -[Install-Update] - set STF_VITAL = "" - set STF_OVERWRITE = "VERIFYSOURCEOLDER" - AddSectionFilesToCopyList Files-$(Option) $(SrcDir) $(!STF_WINDOWSSYSPATH)\drivers - AddSectionFilesToCopyList Files-App $(SrcDir) $(!STF_WINDOWSSYSPATH) - AddSectionFilesToCopyList Files-Inf $(SrcDir) $(!STF_WINDOWSSYSPATH) - set !STF_NCPA_FLUSH_COPYLIST = TRUE - CopyFilesInCopyList - exit - -[Source Media Descriptions] -1 = "Windows NT Setup Disk #1" , TAGFILE = disk1 -2 = "Windows NT Setup CD-ROM Disk" , TAGFILE = disk2 - -[ProductType] -STF_PRODUCT = Winnt -STF_PLATFORM = I386 - -[Files-Inf] -2, oemsetup.inf, SIZE=1000, RENAME=$(!UG_Filename) - -[Files-B2Ether] -2,B2Ether.SYS , SIZE=999 - -[Files-App] - -[LanguagesSupported] -ENG - -[OptionsTextENG] -NDISPERF = "Basilisk II Ethernet Driver" - -[FileConstantsENG] -ProCaption = "Windows NT Setup" -ProCancel = "Cancel" -ProCancelMsg = "Windows NT Networking is not correctly installed. "+ - "Are you sure you want to cancel copying files?" -ProCancelCap = "Network Setup Message" -ProText1 = "Copying:" -ProText2 = "To:" -ProductSoftwareTitle = "Basilisk II Ethernet Driver" -ProductSoftwareDescription = "Adds ethernet capability to the Basilisk II Macintosh II emulator." -ProductSoftwareDisplayName = "Basilisk II Ethernet Driver" -FunctionTitle = $(ProductSoftwareTitle) -ShellCodeErrorTitle = "Error: "$(FunctionTitle) -ShellCodeErrorText = "Shell Code Error." - -[DialogConstantsENG] -Help = "&Help" -Exit = "Cancel" -OK = "OK" -HelpContext = "" -Continue = "Continue" -Cancel = "Cancel" diff --git a/BasiliskII/src/Windows/b2ether/driver/SOURCES b/BasiliskII/src/Windows/b2ether/driver/SOURCES deleted file mode 100755 index e7aa2866..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/SOURCES +++ /dev/null @@ -1,15 +0,0 @@ -# MYMODE must be set - -TARGETNAME=b2ether -TARGETPATH=$(BASEDIR)\lib -TARGETTYPE=DRIVER - -TARGETLIBS=$(BASEDIR)\lib\*\$(DDKBUILDENV)\ndis.lib -INCLUDES=$(BASEDIR)\inc;$(BASEDIR)\src\network\inc;..\inc - -MSC_WARNING_LEVEL=/W3 /WX /FR /FAcs /D$(MYMODE) - -SOURCES=b2ether.c \ - b2ether_openclose.c \ - b2ether_read.c \ - b2ether_write.c diff --git a/BasiliskII/src/Windows/b2ether/driver/b2ether.c b/BasiliskII/src/Windows/b2ether/driver/b2ether.c deleted file mode 100755 index 1119224d..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/b2ether.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "stdarg.h" -#include "ntddk.h" -#include "ntiologc.h" -#include "ndis.h" -#include "ntddpack.h" -#include "b2ether.h" - -#undef DBG -#define DBG 0 -#include "debug.h" - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ); - - -NTSTATUS -PacketReadRegistry( - IN PWSTR *MacDriverName, - IN PWSTR *PacketDriverName, - IN PUNICODE_STRING RegistryPath - ); - - -NTSTATUS -PacketCreateSymbolicLink( - IN PUNICODE_STRING DeviceName, - IN BOOLEAN Create - ); - -NTSTATUS -PacketQueryRegistryRoutine( - IN PWSTR ValueName, - IN ULONG ValueType, - IN PVOID ValueData, - IN ULONG ValueLength, - IN PVOID Context, - IN PVOID EntryContext - ); - - -#if DBG -ULONG PacketDebugFlag = PACKET_DEBUG_LOUD; -#endif - - -PDEVICE_EXTENSION GlobalDeviceExtension; - - -NTSTATUS DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath -) -{ - NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar; - - UNICODE_STRING MacDriverName; - UNICODE_STRING UnicodeDeviceName; - - PDEVICE_OBJECT DeviceObject = NULL; - PDEVICE_EXTENSION DeviceExtension = NULL; - - NTSTATUS Status = STATUS_SUCCESS; - NTSTATUS ErrorCode = STATUS_SUCCESS; - NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver"); - - ULONG DevicesCreated=0; - - PWSTR BindString; - PWSTR ExportString; - - PWSTR BindStringSave; - PWSTR ExportStringSave; - - NDIS_HANDLE NdisProtocolHandle; - - IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");) - - RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); - - ProtocolChar.MajorNdisVersion = 3; - ProtocolChar.MinorNdisVersion = 0; - ProtocolChar.Reserved = 0; - ProtocolChar.OpenAdapterCompleteHandler = PacketOpenAdapterComplete; - ProtocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete; - ProtocolChar.SendCompleteHandler = PacketSendComplete; - ProtocolChar.TransferDataCompleteHandler = PacketTransferDataComplete; - ProtocolChar.ResetCompleteHandler = PacketResetComplete; - ProtocolChar.RequestCompleteHandler = PacketRequestComplete; - ProtocolChar.ReceiveHandler = PacketReceiveIndicate; - ProtocolChar.ReceiveCompleteHandler = PacketReceiveComplete; - ProtocolChar.StatusHandler = PacketStatus; - ProtocolChar.StatusCompleteHandler = PacketStatusComplete; - ProtocolChar.Name = ProtoName; - - NdisRegisterProtocol( - &Status, - &NdisProtocolHandle, - &ProtocolChar, - sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); - - if (Status != NDIS_STATUS_SUCCESS) { - IF_LOUD(DbgPrint("Packet: Failed to register protocol with NDIS\n");) - return Status; - } - - // - // Set up the device driver entry points. - // - - DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = PacketClose; - DriverObject->MajorFunction[IRP_MJ_READ] = PacketRead; - DriverObject->MajorFunction[IRP_MJ_WRITE] = PacketWrite; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PacketCleanup; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PacketIoControl; - - DriverObject->DriverUnload = PacketUnload; - - - // - // Get the name of the Packet driver and the name of the MAC driver - // to bind to from the registry - // - - Status=PacketReadRegistry( - &BindString, - &ExportString, - RegistryPath - ); - - if (Status != STATUS_SUCCESS) { - IF_LOUD(DbgPrint("Perf: Failed to read registry\n");) - goto RegistryError; - } - - BindStringSave = BindString; - ExportStringSave = ExportString; - - // create a device object for each entry - while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) { - - // Create a counted unicode string for both null terminated strings - RtlInitUnicodeString( - &MacDriverName, - BindString - ); - - RtlInitUnicodeString( - &UnicodeDeviceName, - ExportString - ); - - // Advance to the next string of the MULTI_SZ string - BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR); - - ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR); - - IF_LOUD(DbgPrint("Packet: DeviceName=%ws MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);) - - // Create the device object - Status = IoCreateDevice( - DriverObject, - sizeof(DEVICE_EXTENSION), - &UnicodeDeviceName, - FILE_DEVICE_PROTOCOL, - 0, - FALSE, - &DeviceObject - ); - - if (Status != STATUS_SUCCESS) { - IF_LOUD(DbgPrint("Perf: IoCreateDevice() failed:\n");) - break; - } - - DevicesCreated++; - - DeviceObject->Flags |= DO_DIRECT_IO; - DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; - DeviceExtension->DeviceObject = DeviceObject; - - // Save the the name of the MAC driver to open in the Device Extension - DeviceExtension->AdapterName=MacDriverName; - - if (DevicesCreated == 1) { - DeviceExtension->BindString = BindStringSave; - DeviceExtension->ExportString = ExportStringSave; - } - - DeviceExtension->NdisProtocolHandle=NdisProtocolHandle; - } - - if (DevicesCreated > 0) { - return STATUS_SUCCESS; - } - - ExFreePool(BindStringSave); - ExFreePool(ExportStringSave); - -RegistryError: - - NdisDeregisterProtocol( - &Status, - NdisProtocolHandle - ); - - Status=STATUS_UNSUCCESSFUL; - - return(Status); -} - - -VOID PacketUnload( IN PDRIVER_OBJECT DriverObject ) -{ - PDEVICE_OBJECT DeviceObject; - PDEVICE_OBJECT OldDeviceObject; - PDEVICE_EXTENSION DeviceExtension; - - NDIS_HANDLE NdisProtocolHandle; - NDIS_STATUS Status; - - IF_LOUD(DbgPrint("Packet: Unload\n");) - - DeviceObject = DriverObject->DeviceObject; - - while (DeviceObject != NULL) { - DeviceExtension = DeviceObject->DeviceExtension; - NdisProtocolHandle = DeviceExtension->NdisProtocolHandle; - if (DeviceExtension->BindString != NULL) { - ExFreePool(DeviceExtension->BindString); - } - if (DeviceExtension->ExportString != NULL) { - ExFreePool(DeviceExtension->ExportString); - } - OldDeviceObject=DeviceObject; - DeviceObject=DeviceObject->NextDevice; - IoDeleteDevice(OldDeviceObject); - } - - NdisDeregisterProtocol( &Status, NdisProtocolHandle ); -} - - -NTSTATUS PacketIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE Open; - PIO_STACK_LOCATION IrpSp; - PLIST_ENTRY RequestListEntry; - PINTERNAL_REQUEST pRequest; - ULONG FunctionCode; - NDIS_STATUS Status; - - IF_LOUD(DbgPrint("Packet: IoControl\n");) - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode; - - Open=IrpSp->FileObject->FsContext; - - RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock); - if (RequestListEntry == NULL) { - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; - } - - pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement); - pRequest->Irp=Irp; - - IoMarkIrpPending(Irp); - Irp->IoStatus.Status = STATUS_PENDING; - - IF_LOUD(DbgPrint("Packet: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);) - - if (FunctionCode == IOCTL_PROTOCOL_RESET) { - IF_LOUD(DbgPrint("Packet: IoControl - Reset request\n");) - ExInterlockedInsertTailList( - &Open->ResetIrpList, - &Irp->Tail.Overlay.ListEntry, - &Open->RequestSpinLock); - NdisReset( &Status, Open->AdapterHandle ); - - if (Status != NDIS_STATUS_PENDING) { - IF_LOUD(DbgPrint("Packet: IoControl - ResetComplte being called\n");) - PacketResetComplete( Open, Status ); - } - - } else { - // See if it is an Ndis request - PPACKET_OID_DATA OidData=Irp->AssociatedIrp.SystemBuffer; - - if (((FunctionCode == IOCTL_PROTOCOL_SET_OID) || (FunctionCode == IOCTL_PROTOCOL_QUERY_OID)) - && - (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength) - && - (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)) - && - (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) { - - IF_LOUD(DbgPrint("Packet: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);) - - if (FunctionCode == IOCTL_PROTOCOL_SET_OID) { - pRequest->Request.RequestType=NdisRequestSetInformation; - pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid; - pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data; - pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length; - } else { - pRequest->Request.RequestType=NdisRequestQueryInformation; - pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid; - pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data; - pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length; - } - NdisRequest( - &Status, - Open->AdapterHandle, - &pRequest->Request - ); - } else { // buffer too small - Status=NDIS_STATUS_FAILURE; - pRequest->Request.DATA.SET_INFORMATION.BytesRead=0; - pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0; - } - - if (Status != NDIS_STATUS_PENDING) { - IF_LOUD(DbgPrint("Packet: Calling RequestCompleteHandler\n");) - PacketRequestComplete( - Open, - &pRequest->Request, - Status - ); - } - } - return(STATUS_PENDING); -} - - -VOID PacketRequestComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_REQUEST NdisRequest, - IN NDIS_STATUS Status -) -{ - POPEN_INSTANCE Open; - PIO_STACK_LOCATION IrpSp; - PIRP Irp; - PINTERNAL_REQUEST pRequest; - UINT FunctionCode; - - PPACKET_OID_DATA OidData; - - IF_LOUD(DbgPrint("Packet: RequestComplete\n");) - - Open= (POPEN_INSTANCE)ProtocolBindingContext; - - pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request); - Irp=pRequest->Irp; - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode; - - OidData=Irp->AssociatedIrp.SystemBuffer; - - if (FunctionCode == IOCTL_PROTOCOL_SET_OID) { - OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead; - } else { - if (FunctionCode == IOCTL_PROTOCOL_QUERY_OID) { - OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten; - } - } - - Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength; - - ExInterlockedInsertTailList( - &Open->RequestList, - &pRequest->ListElement, - &Open->RequestSpinLock); - - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); -} - - -VOID PacketStatus( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN PVOID StatusBuffer, - IN UINT StatusBufferSize -) -{ - IF_LOUD(DbgPrint("Packet: Status Indication\n");) -} - - -VOID PacketStatusComplete( IN NDIS_HANDLE ProtocolBindingContext ) -{ - IF_LOUD(DbgPrint("Packet: StatusIndicationComplete\n");) -} - - -#if 0 -NTSTATUS PacketCreateSymbolicLink( - IN PUNICODE_STRING DeviceName, - IN BOOLEAN Create -) -{ - UNICODE_STRING UnicodeDosDeviceName; - NTSTATUS Status; - - if (DeviceName->Length < sizeof(L"\\Device\\")) { - return STATUS_UNSUCCESSFUL; - } - - RtlInitUnicodeString(&UnicodeDosDeviceName,NULL); - UnicodeDosDeviceName.MaximumLength=DeviceName->Length+sizeof(L"\\DosDevices")+sizeof(UNICODE_NULL); - UnicodeDosDeviceName.Buffer=ExAllocatePool( - NonPagedPool, - UnicodeDosDeviceName.MaximumLength - ); - if (UnicodeDosDeviceName.Buffer != NULL) { - RtlZeroMemory( UnicodeDosDeviceName.Buffer, UnicodeDosDeviceName.MaximumLength ); - RtlAppendUnicodeToString( &UnicodeDosDeviceName, L"\\DosDevices\\" ); - RtlAppendUnicodeToString( &UnicodeDosDeviceName, (DeviceName->Buffer+(sizeof("\\Device"))) ); - IF_LOUD(DbgPrint("Packet: DosDeviceName is %ws\n",UnicodeDosDeviceName.Buffer);) - if (Create) { - Status=IoCreateSymbolicLink(&UnicodeDosDeviceName,DeviceName); - } else { - Status=IoDeleteSymbolicLink(&UnicodeDosDeviceName); - } - ExFreePool(UnicodeDosDeviceName.Buffer); - } - return Status; -} -#endif - - -NTSTATUS PacketReadRegistry( - IN PWSTR *MacDriverName, - IN PWSTR *PacketDriverName, - IN PUNICODE_STRING RegistryPath -) -{ - NTSTATUS Status; - RTL_QUERY_REGISTRY_TABLE ParamTable[5]; - PWSTR Bind = L"Bind"; // LAURI: \Device\W30NT1 - PWSTR Export = L"Export"; // \Device\appletalk\W30NT1\0\0 - PWSTR Parameters = L"Parameters"; - PWSTR Linkage = L"Linkage"; - PWCHAR Path; - - Path=ExAllocatePool( PagedPool, RegistryPath->Length+sizeof(WCHAR) ); - - if (!Path) return STATUS_INSUFFICIENT_RESOURCES; - - RtlZeroMemory( Path, RegistryPath->Length+sizeof(WCHAR) ); - RtlCopyMemory( Path, RegistryPath->Buffer, RegistryPath->Length ); - - IF_LOUD(DbgPrint("Packet: Reg path is %ws\n",RegistryPath->Buffer);) - - RtlZeroMemory( ParamTable, sizeof(ParamTable) ); - - // change to the parmeters key - ParamTable[0].QueryRoutine = NULL; - ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; - ParamTable[0].Name = Parameters; - - // change to the linkage key - ParamTable[1].QueryRoutine = NULL; - ParamTable[1].Flags = RTL_QUERY_REGISTRY_SUBKEY; - ParamTable[1].Name = Linkage; - - // Get the name of the mac driver we should bind to - ParamTable[2].QueryRoutine = PacketQueryRegistryRoutine; - ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; - - ParamTable[2].Name = Bind; - ParamTable[2].EntryContext = (PVOID)MacDriverName; - ParamTable[2].DefaultType = REG_MULTI_SZ; - - // Get the name that we should use for the driver object - ParamTable[3].QueryRoutine = PacketQueryRegistryRoutine; - ParamTable[3].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; - - ParamTable[3].Name = Export; - ParamTable[3].EntryContext = (PVOID)PacketDriverName; - ParamTable[3].DefaultType = REG_MULTI_SZ; - - Status=RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE, - Path, - ParamTable, - NULL, - NULL - ); - - ExFreePool(Path); - - return Status; -} - - -NTSTATUS PacketQueryRegistryRoutine( - IN PWSTR ValueName, - IN ULONG ValueType, - IN PVOID ValueData, - IN ULONG ValueLength, - IN PVOID Context, - IN PVOID EntryContext - ) - -{ - PUCHAR Buffer; - - IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");) - - if (ValueType != REG_MULTI_SZ) { - return STATUS_OBJECT_NAME_NOT_FOUND; - } - - Buffer=ExAllocatePool(NonPagedPool,ValueLength); - if(!Buffer) return STATUS_INSUFFICIENT_RESOURCES; - - RtlCopyMemory( Buffer, ValueData, ValueLength ); - - *((PUCHAR *)EntryContext)=Buffer; - - return STATUS_SUCCESS; -} diff --git a/BasiliskII/src/Windows/b2ether/driver/b2ether.h b/BasiliskII/src/Windows/b2ether/driver/b2ether.h deleted file mode 100755 index 50080b74..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/b2ether.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define MAX_REQUESTS 4 - -typedef struct _INTERNAL_REQUEST { - LIST_ENTRY ListElement; - PIRP Irp; - NDIS_REQUEST Request; -} INTERNAL_REQUEST, *PINTERNAL_REQUEST; - -// Port device extension. -typedef struct _DEVICE_EXTENSION { - PDEVICE_OBJECT DeviceObject; - NDIS_HANDLE NdisProtocolHandle; - NDIS_STRING AdapterName; - PWSTR BindString; - PWSTR ExportString; -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; - -typedef struct _OPEN_INSTANCE { - PDEVICE_EXTENSION DeviceExtension; - NDIS_HANDLE AdapterHandle; - NDIS_HANDLE PacketPool; - KSPIN_LOCK RcvQSpinLock; - LIST_ENTRY RcvList; - PIRP OpenCloseIrp; - KSPIN_LOCK RequestSpinLock; - LIST_ENTRY RequestList; - LIST_ENTRY ResetIrpList; - INTERNAL_REQUEST Requests[MAX_REQUESTS]; -} OPEN_INSTANCE, *POPEN_INSTANCE; - -typedef struct _PACKET_RESERVED { - LIST_ENTRY ListElement; - PIRP Irp; - PMDL pMdl; -} PACKET_RESERVED, *PPACKET_RESERVED; - - -#define ETHERNET_HEADER_LENGTH 14 -#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) -#define TRANSMIT_PACKETS 16 - - -VOID -PacketOpenAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN NDIS_STATUS OpenErrorStatus - ); - -VOID -PacketCloseAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status - ); - - -NDIS_STATUS -PacketReceiveIndicate( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_HANDLE MacReceiveContext, - IN PVOID HeaderBuffer, - IN UINT HeaderBufferSize, - IN PVOID LookAheadBuffer, - IN UINT LookaheadBufferSize, - IN UINT PacketSize - ); - -VOID -PacketReceiveComplete( - IN NDIS_HANDLE ProtocolBindingContext - ); - - -VOID -PacketRequestComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_REQUEST pRequest, - IN NDIS_STATUS Status - ); - -VOID -PacketSendComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET pPacket, - IN NDIS_STATUS Status - ); - - -VOID -PacketResetComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status - ); - - -VOID -PacketStatus( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN PVOID StatusBuffer, - IN UINT StatusBufferSize - ); - - -VOID -PacketStatusComplete( - IN NDIS_HANDLE ProtocolBindingContext - ); - -VOID -PacketTransferDataComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET Packet, - IN NDIS_STATUS Status, - IN UINT BytesTransferred - ); - - -VOID -PacketRemoveReference( - IN PDEVICE_EXTENSION DeviceExtension - ); - - -NTSTATUS -PacketCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP FlushIrp - ); - - -NTSTATUS -PacketShutdown( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -PacketUnload( - IN PDRIVER_OBJECT DriverObject - ); - - - -NTSTATUS -PacketOpen( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketRead( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketIoControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); diff --git a/BasiliskII/src/Windows/b2ether/driver/b2ether_openclose.c b/BasiliskII/src/Windows/b2ether/driver/b2ether_openclose.c deleted file mode 100755 index 6541993d..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/b2ether_openclose.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//#include "stdarg.h" -#include "ntddk.h" -#include "ntiologc.h" -#include "ndis.h" -#include "b2ether.h" - -#undef DBG -#define DBG 0 -#include "debug.h" - -static UINT Medium; -static NDIS_MEDIUM MediumArray=NdisMedium802_3; - -NTSTATUS PacketOpen( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -/* - This is the dispatch routine for create/open and close requests. - These requests complete successfully. -*/ -{ - PDEVICE_EXTENSION DeviceExtension; - - POPEN_INSTANCE Open; - - PIO_STACK_LOCATION IrpSp; - - NDIS_STATUS Status; - NDIS_STATUS ErrorStatus; - - UINT i; - - IF_LOUD(DbgPrint("Packet: OpenAdapter\n");) - - DeviceExtension = DeviceObject->DeviceExtension; - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - Open = ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE)); - if (Open==NULL) { - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory( Open, sizeof(OPEN_INSTANCE) ); - - // Save or open here - IrpSp->FileObject->FsContext = Open; - Open->DeviceExtension = DeviceExtension; - Open->OpenCloseIrp = Irp; - - // Allocate a packet pool for our xmit and receive packets - NdisAllocatePacketPool( - &Status, - &Open->PacketPool, - TRANSMIT_PACKETS, - sizeof(PACKET_RESERVED)); - - if (Status != NDIS_STATUS_SUCCESS) { - IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");) - ExFreePool(Open); - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // list to hold irp's want to reset the adapter - InitializeListHead(&Open->ResetIrpList); - - // Initialize list for holding pending read requests - KeInitializeSpinLock(&Open->RcvQSpinLock); - InitializeListHead(&Open->RcvList); - - // Initialize the request list - KeInitializeSpinLock(&Open->RequestSpinLock); - InitializeListHead(&Open->RequestList); - - // link up the request stored in our open block - for ( i=0; iRequestList, - &Open->Requests[i].ListElement, - &Open->RequestSpinLock); - - } - - IoMarkIrpPending(Irp); - Irp->IoStatus.Status = STATUS_PENDING; - - // Try to open the MAC - NdisOpenAdapter( - &Status, - &ErrorStatus, - &Open->AdapterHandle, - &Medium, - &MediumArray, - 1, - DeviceExtension->NdisProtocolHandle, - Open, - &DeviceExtension->AdapterName, - 0, - NULL); - - if (Status != NDIS_STATUS_PENDING) { - PacketOpenAdapterComplete( Open, Status, NDIS_STATUS_SUCCESS ); - } - return(STATUS_PENDING); -} - - -VOID PacketOpenAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN NDIS_STATUS OpenErrorStatus -) -{ - PIRP Irp; - POPEN_INSTANCE Open; - - IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");) - - Open = (POPEN_INSTANCE)ProtocolBindingContext; - - Irp = Open->OpenCloseIrp; - - if (Status != NDIS_STATUS_SUCCESS) { - IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");) - NdisFreePacketPool(Open->PacketPool); - ExFreePool(Open); - } - - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return; -} - - -NTSTATUS PacketClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE Open; - NDIS_STATUS Status; - PIO_STACK_LOCATION IrpSp; - - IF_LOUD(DbgPrint("Packet: CloseAdapter\n");) - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - Open = IrpSp->FileObject->FsContext; - Open->OpenCloseIrp =Irp; - - IoMarkIrpPending(Irp); - Irp->IoStatus.Status = STATUS_PENDING; - - NdisCloseAdapter( &Status, Open->AdapterHandle ); - - if (Status != NDIS_STATUS_PENDING) { - PacketCloseAdapterComplete( Open, Status ); - } - - return(STATUS_PENDING); -} - -VOID PacketCloseAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status -) -{ - POPEN_INSTANCE Open; - PIRP Irp; - - IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");) - - Open = (POPEN_INSTANCE)ProtocolBindingContext; - Irp = Open->OpenCloseIrp; - - NdisFreePacketPool(Open->PacketPool); - ExFreePool(Open); - - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); -} - - -NTSTATUS PacketCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP FlushIrp -) -{ - POPEN_INSTANCE Open; - PIO_STACK_LOCATION IrpSp; - PLIST_ENTRY PacketListEntry; - PNDIS_PACKET pPacket; - NDIS_STATUS Status; - - IF_LOUD(DbgPrint("Packet: Cleanup\n");) - - IrpSp = IoGetCurrentIrpStackLocation(FlushIrp); - - Open=IrpSp->FileObject->FsContext; - - IoMarkIrpPending(FlushIrp); - FlushIrp->IoStatus.Status = STATUS_PENDING; - - // - // The open instance of the device is about to close - // We need to complete all pending Irp's - // First we complete any pending read requests - // - while ((PacketListEntry=ExInterlockedRemoveHeadList( - &Open->RcvList, - &Open->RcvQSpinLock - )) != NULL) { - - IF_LOUD(DbgPrint("Packet: CleanUp - Completeing read\n");) - - pPacket=CONTAINING_RECORD(PacketListEntry,NDIS_PACKET,ProtocolReserved); - - // complete normally - PacketTransferDataComplete( - Open, - pPacket, - NDIS_STATUS_SUCCESS, - 0 - ); - } - - // IoMarkIrpPending(FlushIrp); - // FlushIrp->IoStatus.Status = STATUS_PENDING; - - // We now place the Irp on the Reset list - ExInterlockedInsertTailList( - &Open->ResetIrpList, - &FlushIrp->Tail.Overlay.ListEntry, - &Open->RequestSpinLock); - - // Now reset the adapter, the mac driver will complete any - // pending requests we have made to it. - NdisReset( &Status, Open->AdapterHandle ); - - if (Status != NDIS_STATUS_PENDING) { - IF_LOUD(DbgPrint("Packet: Cleanup - ResetComplte being called\n");) - PacketResetComplete( Open, Status ); - } - - return(STATUS_PENDING); -} - - -VOID PacketResetComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status -) -{ - POPEN_INSTANCE Open; - PIRP Irp; - PLIST_ENTRY ResetListEntry; - - IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");) - - Open = (POPEN_INSTANCE)ProtocolBindingContext; - - // remove the reset IRP from the list - ResetListEntry=ExInterlockedRemoveHeadList( - &Open->ResetIrpList, - &Open->RequestSpinLock - ); - -#if DBG - if (ResetListEntry == NULL) { - DbgBreakPoint(); - return; - } -#endif - - Irp = CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry); - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");) -} diff --git a/BasiliskII/src/Windows/b2ether/driver/b2ether_read.c b/BasiliskII/src/Windows/b2ether/driver/b2ether_read.c deleted file mode 100755 index 87ade9a9..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/b2ether_read.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "stdarg.h" -#include "ntddk.h" -#include "ntiologc.h" -#include "ndis.h" -#include "b2ether.h" - -#undef DBG -#define DBG 0 -#include "debug.h" - - -NTSTATUS PacketRead( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp -) -{ - POPEN_INSTANCE Open; - PIO_STACK_LOCATION IrpSp; - PNDIS_PACKET pPacket; - PMDL pMdl; - NDIS_STATUS Status; - - IF_LOUD(DbgPrint("Packet: Read\n");) - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - Open = IrpSp->FileObject->FsContext; - - if (IrpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) { - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; - } - - pMdl=IoAllocateMdl( - MmGetMdlVirtualAddress(Irp->MdlAddress), - MmGetMdlByteCount(Irp->MdlAddress), - FALSE, - FALSE, - NULL - ); - - if (!pMdl) { - IF_LOUD(DbgPrint("Packet: Read-Failed to allocate Mdl\n");) - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; - } - - IoBuildPartialMdl( - Irp->MdlAddress, - pMdl, - ((PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress))+ETHERNET_HEADER_LENGTH, - 0 - ); - pMdl->Next = NULL; - - // - // Try to get a packet from our list of free ones - // - NdisAllocatePacket( &Status, &pPacket, Open->PacketPool ); - - if (Status != NDIS_STATUS_SUCCESS) { - IF_LOUD(DbgPrint("Packet: Read- No free packets\n");) - IoFreeMdl(pMdl); - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; - } - - // - // Get a pointer to the packet itself - // - RESERVED(pPacket)->Irp = Irp; - RESERVED(pPacket)->pMdl = pMdl; - - IoMarkIrpPending(Irp); - Irp->IoStatus.Status = STATUS_PENDING; - - // - // Attach our new MDL to the packet - // - NdisChainBufferAtFront(pPacket,pMdl); - - - // - // Put this packet in a list of pending reads. - // The receive indication handler will attemp to remove packets - // from this list for use in transfer data calls - // - ExInterlockedInsertTailList( - &Open->RcvList, - &RESERVED(pPacket)->ListElement, - &Open->RcvQSpinLock); - - return(STATUS_PENDING); -} - - -NDIS_STATUS -PacketReceiveIndicate ( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_HANDLE MacReceiveContext, - IN PVOID HeaderBuffer, - IN UINT HeaderBufferSize, - IN PVOID LookAheadBuffer, - IN UINT LookaheadBufferSize, - IN UINT PacketSize - ) - -{ - POPEN_INSTANCE Open; - PIO_STACK_LOCATION IrpSp; - PIRP Irp; - PLIST_ENTRY PacketListEntry; - PNDIS_PACKET pPacket; - ULONG SizeToTransfer; - NDIS_STATUS Status; - UINT BytesTransfered; - ULONG BufferLength; - PPACKET_RESERVED Reserved; - - IF_LOUD(DbgPrint("Packet: ReceiveIndicate\n");) - - Open = (POPEN_INSTANCE)ProtocolBindingContext; - - if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) { - return NDIS_STATUS_NOT_ACCEPTED; // NDIS_STATUS_SUCCESS; - } - - // See if there are any pending read that we can satisfy - PacketListEntry=ExInterlockedRemoveHeadList( - &Open->RcvList, - &Open->RcvQSpinLock - ); - - if (PacketListEntry == NULL) { - IF_LOUD(DbgPrint("Packet: ReceiveIndicate dropped a packet\n");) - return NDIS_STATUS_NOT_ACCEPTED; - } - - Reserved=CONTAINING_RECORD(PacketListEntry,PACKET_RESERVED,ListElement); - pPacket=CONTAINING_RECORD(Reserved,NDIS_PACKET,ProtocolReserved); - - Irp=RESERVED(pPacket)->Irp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - // This is the length of our partial MDL - BufferLength = IrpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH; - - SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength; - - // copy the ethernet header into the actual readbuffer - NdisMoveMappedMemory( - MmGetSystemAddressForMdl(Irp->MdlAddress), - HeaderBuffer, - HeaderBufferSize - ); - - // Call the Mac to transfer the packet - NdisTransferData( - &Status, - Open->AdapterHandle, - MacReceiveContext, - 0, - SizeToTransfer, - pPacket, - &BytesTransfered); - - if (Status != NDIS_STATUS_PENDING) { - PacketTransferDataComplete( Open, pPacket, Status, BytesTransfered ); - } - - return NDIS_STATUS_SUCCESS; -} - -VOID PacketTransferDataComplete ( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET pPacket, - IN NDIS_STATUS Status, - IN UINT BytesTransfered -) -{ - PIO_STACK_LOCATION IrpSp; - POPEN_INSTANCE Open; - PIRP Irp; - PMDL pMdl; - - IF_LOUD(DbgPrint("Packet: TransferDataComplete\n");) - - Open = (POPEN_INSTANCE)ProtocolBindingContext; - Irp = RESERVED(pPacket)->Irp; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - pMdl = RESERVED(pPacket)->pMdl; - - // Free the MDL that we allocated - IoFreeMdl(pMdl); - - // recycle the packet - NdisReinitializePacket(pPacket); - - // Put the packet on the free queue - NdisFreePacket(pPacket); - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH; - IoCompleteRequest(Irp, IO_NO_INCREMENT); -} - - -VOID PacketReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext ) -{ -} diff --git a/BasiliskII/src/Windows/b2ether/driver/b2ether_write.c b/BasiliskII/src/Windows/b2ether/driver/b2ether_write.c deleted file mode 100755 index 4b6684ff..00000000 --- a/BasiliskII/src/Windows/b2ether/driver/b2ether_write.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "stdarg.h" -#include "ntddk.h" -#include "ntiologc.h" -#include "ndis.h" -#include "b2ether.h" - -#undef DBG -#define DBG 0 -#include "debug.h" - - -NTSTATUS PacketWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp -) -{ - POPEN_INSTANCE Open; - PIO_STACK_LOCATION IrpSp; - PNDIS_PACKET pPacket; - - NDIS_STATUS Status; - - IF_LOUD(DbgPrint("Packet: SendAdapter\n");) - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - Open = IrpSp->FileObject->FsContext; - - // Try to get a packet from our list of free ones - NdisAllocatePacket( &Status, &pPacket, Open->PacketPool ); - if (Status != NDIS_STATUS_SUCCESS) { - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; - } - - RESERVED(pPacket)->Irp=Irp; - - // Attach the writes buffer to the packet - NdisChainBufferAtFront(pPacket,Irp->MdlAddress); - - IoMarkIrpPending(Irp); - Irp->IoStatus.Status = STATUS_PENDING; - - // Call the MAC - NdisSend( &Status, Open->AdapterHandle, pPacket ); - - if (Status != NDIS_STATUS_PENDING) { - PacketSendComplete( Open, pPacket, Status ); - } - - return(STATUS_PENDING); -} - - -VOID PacketSendComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET pPacket, - IN NDIS_STATUS Status -) -{ - PIRP Irp; - - IF_LOUD(DbgPrint("Packet: SendComplete\n");) - - Irp = RESERVED(pPacket)->Irp; - - // recyle the packet - NdisReinitializePacket(pPacket); - - // Put the packet back on the free list - NdisFreePacket(pPacket); - - Irp->IoStatus.Status = Status; - - // a known bug, but I don't need this information - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); -} diff --git a/BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h b/BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h deleted file mode 100755 index d5e87655..00000000 --- a/BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * b2ether_hl.h - Win32 ethernet driver high-level interface - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _B2_ETHER_HL_ -#define _B2_ETHER_HL_ - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define ETH_802_3_ADDRESS_LENGTH 6 -#define MAX_LINK_NAME_LENGTH 124 - -typedef struct _ADAPTER { - HANDLE hFile; - TCHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; -} ADAPTER, *LPADAPTER; - -typedef struct _PACKET { - OVERLAPPED OverLapped; - PVOID Buffer; - UINT Length; - ULONG BytesReceived; - BOOL bIoComplete; - BOOL free; - struct _PACKET *next; -} PACKET, *LPPACKET; - - - -BOOLEAN StartPacketDriver( - LPCTSTR ServiceName -); - -LPADAPTER PacketOpenAdapter( - LPCTSTR AdapterName, - int16 mode -); - -VOID PacketCloseAdapter( - LPADAPTER lpAdapter -); - -LPPACKET PacketAllocatePacket( - LPADAPTER AdapterObject, - UINT Length -); - -VOID PacketFreePacket( - LPPACKET lpPacket -); - -BOOLEAN PacketSendPacket( - LPADAPTER AdapterObject, - LPPACKET lpPacket, - BOOLEAN Sync, - BOOLEAN RecyclingAllowed -); - -BOOLEAN PacketGetAddress( - LPADAPTER AdapterObject, - PUCHAR AddressBuffer, - PUINT Length -); - -BOOLEAN PacketReceivePacket( - LPADAPTER AdapterObject, - LPPACKET lpPacket, - BOOLEAN Sync -); - -BOOLEAN PacketSetFilter( LPADAPTER AdapterObject, ULONG Filter ); -BOOLEAN PacketGetMAC( LPADAPTER AdapterObject, LPBYTE address, BOOL permanent ); -BOOLEAN PacketAddMulticast( LPADAPTER AdapterObject, LPBYTE address ); -BOOLEAN PacketDelMulticast( LPADAPTER AdapterObject, LPBYTE address ); - -ULONG PacketGetAdapterNames( LPADAPTER lpAdapter, LPTSTR pStr, PULONG BufferSize ); - -// callbacks -void recycle_write_packet( LPPACKET Packet ); - -VOID CALLBACK packet_read_completion( - DWORD dwErrorCode, - DWORD dwNumberOfBytesTransfered, - LPOVERLAPPED lpOverlapped -); - - -#ifdef __cplusplus -} -#endif - - -#endif // _B2_ETHER_HL_ diff --git a/BasiliskII/src/Windows/b2ether/inc/ntddpack.h b/BasiliskII/src/Windows/b2ether/inc/ntddpack.h deleted file mode 100755 index 62af4f3f..00000000 --- a/BasiliskII/src/Windows/b2ether/inc/ntddpack.h +++ /dev/null @@ -1,32 +0,0 @@ -// #include - -#ifndef __NTDDPACKET -#define __NTDDPACKET 1 - -// #include - -#define MAX_LINK_NAME_LENGTH 124 - -#pragma pack(1) -typedef struct _PACKET_OID_DATA { - ULONG Oid; - ULONG Length; - UCHAR Data[1]; -} ATTRIBUTE_PACKED PACKET_OID_DATA, *PPACKET_OID_DATA; -#pragma pack() - - -#define FILE_DEVICE_PROTOCOL 0x8000 - - - -#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_SELECT_BY_NAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_ENUM_ADAPTERS CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) - -#endif diff --git a/BasiliskII/src/Windows/b2ether/multiopt.h b/BasiliskII/src/Windows/b2ether/multiopt.h deleted file mode 100755 index d924a199..00000000 --- a/BasiliskII/src/Windows/b2ether/multiopt.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * multiopt.h - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -enum { - ETHER_MULTICAST_MAC, - ETHER_MULTICAST_ALL, - ETHER_MULTICAST_PROMISCUOUS -}; diff --git a/BasiliskII/src/Windows/b2ether/nt5/B2Win2k.inf b/BasiliskII/src/Windows/b2ether/nt5/B2Win2k.inf deleted file mode 100644 index d8726610..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/B2Win2k.inf +++ /dev/null @@ -1,80 +0,0 @@ -[version] -Signature = "$Windows NT$" -Class = NetTrans -ClassGUID = {4d36e975-e325-11ce-bfc1-08002be10318} -Provider = %Msft% -DriverVer = 12/05/1999,5.00.2128 - -[Manufacturer] -%Msft%=MSFT - -[MSFT] -%B2ETHER_Desc%=Install, MS_B2ETHER - -;------------------------------------------------------------------------- -; Installation Section -;------------------------------------------------------------------------- -[Install] -AddReg=Inst_Ndi -Characteristics=0 ; Has no characterstic -CopyFiles=CpyFiles_Sys - -;------------------------------------------------------------------------- -; Ndi installation support -;------------------------------------------------------------------------- -[Inst_Ndi] -HKR,Ndi,Service,,"B2Ether" -HKR,Ndi,HelpText,,%B2ETHER_HelpText% -HKR, Ndi\Interfaces, UpperRange,, noupper -HKR,"Ndi\Interfaces","LowerRange",,"ndis5,ndis4" - -;------------------------------------------------------------------------- -; Service installation support -;------------------------------------------------------------------------- -[Install.Services] -AddService=B2Ether,,B2ETHER_Service_Inst - -[B2Ether_Service_Inst] -DisplayName = %B2ETHER_Desc% -ServiceType = 1 ;SERVICE_KERNEL_DRIVER -StartType = 2 ;SERVICE_AUTO_START -ErrorControl = 1 ;SERVICE_ERROR_NORMAL -ServiceBinary = %12%\B2Ether.sys -LoadOrderGroup = "PNP_TDI" -AddReg = AddReg_B2ETHER_Service_Inst -Description = %B2ETHER_Desc% - -[AddReg_B2ETHER_Service_Inst] -HKLM,"System\CurrentControlSet\Services\B2Ether","TextModeFlags",%REG_DWORD%,0x0001 -HKR,"Parameters","Version",,"5.00.2128" - -;------------------------------------------------------------------------- -; Support for removal of static registry settings -;------------------------------------------------------------------------- -[Install.Remove] -DelReg=Del_Static_Reg - -[Install.Remove.Services] -DelService=B2Ether - -[Del_Static_Reg] -HKLM,"System\CurrentControlSet\Services\B2Ether","TextModeFlags" - -;------------------------------------------------------------------------- -; Declare Destination Directories for file copy/deletion -;------------------------------------------------------------------------- -[DestinationDirs] -CpyFiles_Sys = 12 ; DIRID_DRIVERS - - -;------------------------------------------------------------------------- -; Files to Copy/Delete - Referenced by Install and Remove sections above -;------------------------------------------------------------------------- -[CpyFiles_Sys] -B2Ether.sys,,,2 - -[Strings] -Msft = "Microsoft" -B2ETHER_Desc = "Basilisk II Ethernet Driver" -B2ETHER_HelpText = "Adds ethernet capability to the Basilisk II Macintosh II emulator." -REG_DWORD = 0x10001 diff --git a/BasiliskII/src/Windows/b2ether/nt5/B2Win7Vista-x64.inf b/BasiliskII/src/Windows/b2ether/nt5/B2Win7Vista-x64.inf deleted file mode 100755 index f154af77..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/B2Win7Vista-x64.inf +++ /dev/null @@ -1,80 +0,0 @@ -[version] -Signature = "$Windows NT$" -Class = NetTrans -ClassGUID = {4d36e975-e325-11ce-bfc1-08002be10318} -Provider = %Msft% -DriverVer = 12/05/1999,5.00.2128 - -[Manufacturer] -%Msft%=MSFT,NTamd64 - -[MSFT.NTamd64] -%B2ETHER_Desc%=Install, MS_B2ETHER - -;------------------------------------------------------------------------- -; Installation Section -;------------------------------------------------------------------------- -[Install] -AddReg=Inst_Ndi -Characteristics=0 ; Has no characteristic -CopyFiles=CpyFiles_Sys - -;------------------------------------------------------------------------- -; Ndi installation support -;------------------------------------------------------------------------- -[Inst_Ndi] -HKR,Ndi,Service,,"B2Ether" -HKR,Ndi,HelpText,,%B2ETHER_HelpText% -HKR, Ndi\Interfaces, UpperRange,, noupper -HKR,"Ndi\Interfaces","LowerRange",,"ndis5,ndis4" - -;------------------------------------------------------------------------- -; Service installation support -;------------------------------------------------------------------------- -[Install.Services] -AddService=B2Ether,,B2ETHER_Service_Inst - -[B2Ether_Service_Inst] -DisplayName = %B2ETHER_Desc% -ServiceType = 1 ;SERVICE_KERNEL_DRIVER -StartType = 2 ;SERVICE_AUTO_START -ErrorControl = 1 ;SERVICE_ERROR_NORMAL -ServiceBinary = %12%\B2Ether64.sys -LoadOrderGroup = "PNP_TDI" -AddReg = AddReg_B2ETHER_Service_Inst -Description = %B2ETHER_Desc% - -[AddReg_B2ETHER_Service_Inst] -HKLM,"System\CurrentControlSet\Services\B2Ether","TextModeFlags",%REG_DWORD%,0x0001 -HKR,"Parameters","Version",,"5.00.2128" - -;------------------------------------------------------------------------- -; Support for removal of static registry settings -;------------------------------------------------------------------------- -[Install.Remove] -DelReg=Del_Static_Reg - -[Install.Remove.Services] -DelService=B2Ether - -[Del_Static_Reg] -HKLM,"System\CurrentControlSet\Services\B2Ether","TextModeFlags" - -;------------------------------------------------------------------------- -; Declare Destination Directories for file copy/deletion -;------------------------------------------------------------------------- -[DestinationDirs] -CpyFiles_Sys = 12 ; DIRID_DRIVERS - - -;------------------------------------------------------------------------- -; Files to Copy/Delete - Referenced by Install and Remove sections above -;------------------------------------------------------------------------- -[CpyFiles_Sys] -B2Ether64.sys,,,2 - -[Strings] -Msft = "Microsoft" -B2ETHER_Desc = "Basilisk II Ethernet Driver Test x64" -B2ETHER_HelpText = "Adds ethernet capability to the Basilisk II Macintosh II emulator." -REG_DWORD = 0x10001 diff --git a/BasiliskII/src/Windows/b2ether/nt5/MAKEFILE b/BasiliskII/src/Windows/b2ether/nt5/MAKEFILE deleted file mode 100644 index 58189757..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/MAKEFILE +++ /dev/null @@ -1,7 +0,0 @@ -# -# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source -# file to this component. This file merely indirects to the real make file -# that is shared by all the driver components of the Windows NT DDK -# - -!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/BasiliskII/src/Windows/b2ether/nt5/NTDDPACK.H b/BasiliskII/src/Windows/b2ether/nt5/NTDDPACK.H deleted file mode 100755 index 6c5e0ceb..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/NTDDPACK.H +++ /dev/null @@ -1,32 +0,0 @@ -// #include - -#ifndef __NTDDPACKET -#define __NTDDPACKET 1 - -// #include - -#define MAX_LINK_NAME_LENGTH 124 - -#pragma pack(1) -typedef struct _PACKET_OID_DATA { - ULONG Oid; - ULONG Length; - UCHAR Data[1]; -} PACKET_OID_DATA, *PPACKET_OID_DATA; -#pragma pack() - - -#define FILE_DEVICE_PROTOCOL 0x8000 - - - -#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_PROTOCOL_SELECT_BY_NAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_ENUM_ADAPTERS CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) - -#endif diff --git a/BasiliskII/src/Windows/b2ether/nt5/SOURCES b/BasiliskII/src/Windows/b2ether/nt5/SOURCES deleted file mode 100644 index 1e0c1aca..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/SOURCES +++ /dev/null @@ -1,17 +0,0 @@ -# MYMODE must be set - -TARGETNAME=b2ether -TARGETPATH=obj -TARGETTYPE=DRIVER - -TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib -C_DEFINES=$(C_DEFINES) -DNDIS50 -INCLUDES=$(BASEDIR)\inc;$(BASEDIR)\src\network\inc;..\inc - -MSC_WARNING_LEVEL=/W3 /WX /FR /FAcs /D$(MYMODE) - -SOURCES=b2ether.c \ - b2ether_openclose.c \ - b2ether_read.c \ - b2ether_write.c \ - b2ether.rc diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether.c b/BasiliskII/src/Windows/b2ether/nt5/b2ether.c deleted file mode 100644 index ec2c69c9..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "ntddk.h" -#include "ndis.h" -#include "ntddpack.h" -#include "b2ether.h" -#include "stdio.h" - - - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath -) -{ - NDIS_PROTOCOL_CHARACTERISTICS protocolChar; - NTSTATUS status = STATUS_SUCCESS; - NDIS_STRING protoName = NDIS_STRING_CONST("B2ether"); - UNICODE_STRING ntDeviceName; - UNICODE_STRING win32DeviceName; - BOOLEAN fSymbolicLink = FALSE; - PDEVICE_OBJECT deviceObject; - - // DebugPrint(("\n\nDriverEntry\n")); - - Globals.DriverObject = DriverObject; - Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL); - Globals.RegistryPath.Length = RegistryPath->Length; - Globals.RegistryPath.Buffer = ExAllocatePool( PagedPool, Globals.RegistryPath.MaximumLength ); - if (!Globals.RegistryPath.Buffer) { - // DebugPrint (("Couldn't allocate pool for registry path.")); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath); - RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME); - - status = IoCreateDevice (DriverObject, - 0, - &ntDeviceName, - FILE_DEVICE_UNKNOWN, - 0, - FALSE, - &deviceObject); - - - if (!NT_SUCCESS (status)) { - // Either not enough memory to create a deviceobject or another - // deviceobject with the same name exits. This could happen - // if you install another instance of this device. - goto ERROR; - } - - RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); - - status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName ); - if (!NT_SUCCESS(status)) goto ERROR; - - fSymbolicLink = TRUE; - - deviceObject->Flags |= DO_BUFFERED_IO; - Globals.ControlDeviceObject = deviceObject; - - InitializeListHead(&Globals.AdapterList); - KeInitializeSpinLock(&Globals.GlobalLock); - - NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); - - protocolChar.MajorNdisVersion = 5; - protocolChar.MinorNdisVersion = 0; - protocolChar.Name = protoName; - protocolChar.OpenAdapterCompleteHandler = PacketOpenAdapterComplete; - protocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete; - protocolChar.SendCompleteHandler = PacketSendComplete; - protocolChar.TransferDataCompleteHandler = PacketTransferDataComplete; - protocolChar.ResetCompleteHandler = PacketResetComplete; - protocolChar.RequestCompleteHandler = PacketRequestComplete; - protocolChar.ReceiveHandler = PacketReceiveIndicate; - protocolChar.ReceiveCompleteHandler = PacketReceiveComplete; - protocolChar.StatusHandler = PacketStatus; - protocolChar.StatusCompleteHandler = PacketStatusComplete; - protocolChar.BindAdapterHandler = PacketBindAdapter; - protocolChar.UnbindAdapterHandler = PacketUnbindAdapter; - protocolChar.UnloadHandler = NULL; - protocolChar.ReceivePacketHandler = PacketReceivePacket; - protocolChar.PnPEventHandler = PacketPNPHandler; - - NdisRegisterProtocol( - &status, - &Globals.NdisProtocolHandle, - &protocolChar, - sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); - - if (status != NDIS_STATUS_SUCCESS) { - // DebugPrint(("Failed to register protocol with NDIS\n")); - status = STATUS_UNSUCCESSFUL; - goto ERROR; - } - - DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = PacketClose; - DriverObject->MajorFunction[IRP_MJ_READ] = PacketRead; - DriverObject->MajorFunction[IRP_MJ_WRITE] = PacketWrite; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PacketCleanup; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PacketIoControl; - DriverObject->DriverUnload = PacketUnload; - - return(STATUS_SUCCESS); - -ERROR: - if(deviceObject) - IoDeleteDevice(deviceObject); - if(fSymbolicLink) - IoDeleteSymbolicLink(&win32DeviceName); - if(Globals.RegistryPath.Buffer) - ExFreePool(Globals.RegistryPath.Buffer); - return status; -} - - -VOID PacketUnload( IN PDRIVER_OBJECT DriverObject ) -{ - NDIS_STATUS status; - UNICODE_STRING win32DeviceName; - - // DebugPrint(("Unload Enter\n")); - - RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); - IoDeleteSymbolicLink(&win32DeviceName); - - if(Globals.ControlDeviceObject) - IoDeleteDevice(Globals.ControlDeviceObject); - - // Unbind from all the adapters. The system removes the driver code - // pages from the memory as soon as the unload returns. So you - // must wait for all the CloseAdapterCompleteHandler to finish - // before returning from the unload routine. You don't any callbacks - // to trigger after the driver is unloaded. - - while(DriverObject->DeviceObject) { - PacketUnbindAdapter(&status, DriverObject->DeviceObject->DeviceExtension,NULL); - } - - if(Globals.RegistryPath.Buffer) - ExFreePool(Globals.RegistryPath.Buffer); - - // DebugPrint(("Deregister\n")); - - NdisDeregisterProtocol( &status, Globals.NdisProtocolHandle ); - // DebugPrint(("Unload Exit\n")); -} - - - -NTSTATUS PacketIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE open; - PIO_STACK_LOCATION irpSp; - PINTERNAL_REQUEST pRequest; - ULONG functionCode; - NDIS_STATUS status; - ULONG dataLength =0; - - // DebugPrint(("IoControl\n")); - - irpSp = IoGetCurrentIrpStackLocation(Irp); - - functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode; - - if (functionCode == IOCTL_ENUM_ADAPTERS) { - // If the request is not made to the controlobject, fail the request. - - if(DeviceObject != Globals.ControlDeviceObject) { - status = STATUS_INVALID_DEVICE_REQUEST; - } else { - status = PacketGetAdapterList( - Irp->AssociatedIrp.SystemBuffer, - irpSp->Parameters.DeviceIoControl.OutputBufferLength, - &dataLength - ); - } - Irp->IoStatus.Status = status; - Irp->IoStatus.Information = dataLength; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; - } - - open = DeviceObject->DeviceExtension; - IoIncrement(open); - - if(!open->Bound) { - Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoDecrement(open); - return status; - } - - // DebugPrint(("Function code is %08lx buff size=%08lx %08lx\n", - // functionCode,irpSp->Parameters.DeviceIoControl.InputBufferLength, - // irpSp->Parameters.DeviceIoControl.OutputBufferLength)); - - // Important: Since we have marked the IRP pending, we must return - // STATUS_PENDING even we happen to complete the IRP synchronously. - - IoMarkIrpPending(Irp); - - if (functionCode == IOCTL_PROTOCOL_RESET) { - // DebugPrint(("IoControl - Reset request\n")); - - // - // Since NDIS doesn't have an interface to cancel a request - // pending at miniport, we cannot set a cancel routine. - // As a result if the application that made the request - // terminates, we wait in the Cleanup routine for all pending - // NDIS requests to complete. - - ExInterlockedInsertTailList( - &open->ResetIrpList, - &Irp->Tail.Overlay.ListEntry, - &open->ResetQueueLock); - - NdisReset( &status, open->AdapterHandle ); - - if (status != NDIS_STATUS_PENDING) { - // DebugPrint(("IoControl - ResetComplete being called\n")); - PacketResetComplete( open, status ); - } - } else { - // See if it is an Ndis request - PPACKET_OID_DATA OidData=Irp->AssociatedIrp.SystemBuffer; - - pRequest = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST)); - - if(!pRequest) { - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - IoDecrement(open); - return STATUS_PENDING; - } - pRequest->Irp=Irp; - - if (((functionCode == IOCTL_PROTOCOL_SET_OID) || (functionCode == IOCTL_PROTOCOL_QUERY_OID)) - && - (irpSp->Parameters.DeviceIoControl.InputBufferLength == irpSp->Parameters.DeviceIoControl.OutputBufferLength) - && - (irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)) - && - (irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) - { - // DebugPrint(("IoControl: Request: Oid=%08lx, Length=%08lx\n", OidData->Oid,OidData->Length)); - - if (functionCode == IOCTL_PROTOCOL_SET_OID) { - pRequest->Request.RequestType = NdisRequestSetInformation; - pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid; - pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data; - pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length; - } else { - pRequest->Request.RequestType=NdisRequestQueryInformation; - pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid; - pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data; - pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length; - } - NdisRequest( &status, open->AdapterHandle, &pRequest->Request ); - } else { - status=NDIS_STATUS_FAILURE; - pRequest->Request.DATA.SET_INFORMATION.BytesRead=0; - pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0; - } - - if (status != NDIS_STATUS_PENDING) { - // DebugPrint(("Calling RequestCompleteHandler\n")); - PacketRequestComplete( open, &pRequest->Request, status ); - } - } - return STATUS_PENDING; -} - - -VOID -PacketRequestComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_REQUEST NdisRequest, - IN NDIS_STATUS Status - ) -{ - POPEN_INSTANCE open; - PIO_STACK_LOCATION irpSp; - PIRP irp; - PINTERNAL_REQUEST pRequest; - UINT functionCode; - - PPACKET_OID_DATA OidData; - - // DebugPrint(("RequestComplete\n")); - - open = (POPEN_INSTANCE)ProtocolBindingContext; - - pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request); - irp = pRequest->Irp; - - if(Status == NDIS_STATUS_SUCCESS) { - irpSp = IoGetCurrentIrpStackLocation(irp); - functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode; - OidData = irp->AssociatedIrp.SystemBuffer; - if (functionCode == IOCTL_PROTOCOL_SET_OID) { - OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead; - } else { - if (functionCode == IOCTL_PROTOCOL_QUERY_OID) { - OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten; - } - } - irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information=irpSp->Parameters.DeviceIoControl.InputBufferLength; - } else { - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - irp->IoStatus.Information = 0; - } - - ExFreePool(pRequest); - IoCompleteRequest(irp, IO_NO_INCREMENT); - IoDecrement(open); -} - - -VOID -PacketStatus( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN PVOID StatusBuffer, - IN UINT StatusBufferSize -) -{ - // DebugPrint(("Indication Status: %0x, StatusBufferSize: %d\n", Status, StatusBufferSize)); -} - - -VOID PacketStatusComplete( IN NDIS_HANDLE ProtocolBindingContext ) -{ - // DebugPrint(("StatusIndicationComplete\n")); -} - - -NTSTATUS -PacketGetAdapterList( - IN PVOID Buffer, - IN ULONG Length, - IN OUT PULONG DataLength -) -{ - ULONG requiredLength = 0, numOfAdapters = 0; - KIRQL oldIrql; - PLIST_ENTRY thisEntry, listHead; - POPEN_INSTANCE open; - - // DebugPrint(("Enter PacketGetAdapterList\n")); - - KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql); - - // Walks the list to find out total space required for AdapterName and Symbolic Link. - - listHead = &Globals.AdapterList; - - for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink) { - open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry); - requiredLength += open->AdapterName.Length + sizeof(UNICODE_NULL); - requiredLength += open->SymbolicLink.Length + sizeof(UNICODE_NULL); - numOfAdapters++; - } - - // - // We will return the data in the following format: - // numOfAdapters + One_Or_More("AdapterName\0" + "SymbolicLink\0") + UNICODE_NULL - // So let's include the numOfAdapters and UNICODE_NULL size - // to the total length. - // - - requiredLength += sizeof(ULONG) + sizeof(UNICODE_NULL); - *DataLength = requiredLength; - - if(requiredLength > Length) { - KeReleaseSpinLock(&Globals.GlobalLock, oldIrql); - return STATUS_BUFFER_TOO_SMALL; - } - - *(PULONG)Buffer = numOfAdapters; - (PCHAR)Buffer += sizeof(ULONG); - - for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) { - open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry); - RtlCopyMemory( Buffer, open->AdapterName.Buffer, open->AdapterName.Length+sizeof(WCHAR) ); - (PCHAR)Buffer += open->AdapterName.Length+sizeof(WCHAR); - RtlCopyMemory( Buffer, open->SymbolicLink.Buffer, open->SymbolicLink.Length+sizeof(WCHAR) ); - (PCHAR)Buffer += open->SymbolicLink.Length+sizeof(WCHAR); - } - - *(PWCHAR)Buffer = UNICODE_NULL; - KeReleaseSpinLock(&Globals.GlobalLock, oldIrql); - return STATUS_SUCCESS; -} - -VOID -PacketBindAdapter( - OUT PNDIS_STATUS Status, - IN NDIS_HANDLE BindContext, - IN PNDIS_STRING DeviceName, - IN PVOID SystemSpecific1, - IN PVOID SystemSpecific2 -) -{ - NDIS_STATUS status; - UINT mediumIndex; - USHORT length; - POPEN_INSTANCE open = NULL; - UNICODE_STRING unicodeDeviceName; - PDEVICE_OBJECT deviceObject = NULL; - PWSTR symbolicLink = NULL, deviceNameStr = NULL; - NDIS_MEDIUM mediumArray = NdisMedium802_3; // Ethernet medium - - // DebugPrint(("Binding DeviceName %ws\n", DeviceName->Buffer)); - - do { - // Create a deviceobject for every adapter we bind to. - // To make a name for the deviceObject, we will append Packet_ - // to the name portion of the input DeviceName. - - unicodeDeviceName.Buffer = NULL; - length = DeviceName->Length + 7 * sizeof(WCHAR) + sizeof(UNICODE_NULL); - - deviceNameStr = ExAllocatePool(NonPagedPool, length); - if (!deviceNameStr) { - // DebugPrint(("Memory allocation for create symbolic failed\n")); - *Status = NDIS_STATUS_FAILURE; - break; - } - swprintf(deviceNameStr, L"\\Device\\B2ether_%ws", &DeviceName->Buffer[8]); - RtlInitUnicodeString(&unicodeDeviceName, deviceNameStr); - - // DebugPrint(("Exported DeviceName %ws\n", unicodeDeviceName.Buffer)); - - status = IoCreateDevice( - Globals.DriverObject, - sizeof(OPEN_INSTANCE), - &unicodeDeviceName, - FILE_DEVICE_PROTOCOL, - 0, - TRUE, // only one handle to the device at a time. - &deviceObject - ); - - if (status != STATUS_SUCCESS) { - // DebugPrint(("CreateDevice Failed: %x\n", status)); - *Status = NDIS_STATUS_FAILURE; - break; - } - - deviceObject->Flags |= DO_DIRECT_IO; - open = (POPEN_INSTANCE) deviceObject->DeviceExtension; - open->DeviceObject = deviceObject; - - // Create a symbolic link. - // We need to replace Device from \Device\Packet_{GUID} with DosDevices - // to create a symbolic link of the form \DosDevices\Packet_{GUID} - // There is a four character difference between these two - // strings. - - length = unicodeDeviceName.Length + sizeof(UNICODE_NULL) + (4 * sizeof(WCHAR)); - - symbolicLink = ExAllocatePool(NonPagedPool, length); - if (!symbolicLink) { - // DebugPrint(("Memory allocation for create symbolic failed\n")); - *Status = NDIS_STATUS_FAILURE; - break; - } - - swprintf( symbolicLink, L"\\DosDevices\\%ws", &unicodeDeviceName.Buffer[8]); - - RtlInitUnicodeString(&open->SymbolicLink,symbolicLink); - - // DebugPrint(("Symbolic Link: %ws\n", open->SymbolicLink.Buffer)); - - status = IoCreateSymbolicLink( - (PUNICODE_STRING) &open->SymbolicLink, - (PUNICODE_STRING) &unicodeDeviceName - ); - if (status != STATUS_SUCCESS) { - // DebugPrint(("Create symbolic failed\n")); - *Status = NDIS_STATUS_FAILURE; - break; - } - - ExFreePool(unicodeDeviceName.Buffer); - unicodeDeviceName.Buffer = NULL; - - NdisAllocatePacketPool( - &status, - &open->PacketPool, - TRANSMIT_PACKETS, - sizeof(PACKET_RESERVED)); - - if (status != NDIS_STATUS_SUCCESS) { - // DebugPrint(("B2ether: Failed to allocate packet pool\n")); - break; - } - - NdisInitializeEvent(&open->Event); - InitializeListHead(&open->ResetIrpList); - KeInitializeSpinLock(&open->ResetQueueLock); - KeInitializeSpinLock(&open->RcvQSpinLock); - InitializeListHead(&open->RcvList); - - NdisOpenAdapter(Status, - &status, - &open->AdapterHandle, - &mediumIndex, - &mediumArray, - sizeof(mediumArray)/sizeof(NDIS_MEDIUM), - Globals.NdisProtocolHandle, - open, - DeviceName, - 0, - NULL); - - if(*Status == NDIS_STATUS_PENDING) { - NdisWaitEvent(&open->Event, 0); - *Status = open->Status; - } - if(*Status != NDIS_STATUS_SUCCESS) { - // DebugPrint(("Failed to openAdapter\n")); - break; - } - - open->IrpCount = 0; - InterlockedExchange( (PLONG)&open->Bound, TRUE ); - NdisInitializeEvent(&open->CleanupEvent); - - NdisSetEvent(&open->CleanupEvent); - - NdisQueryAdapterInstanceName( &open->AdapterName, open->AdapterHandle ); - // DebugPrint(("Bound AdapterName %ws\n", open->AdapterName.Buffer)); - - open->Medium = mediumArray; - - InitializeListHead(&open->AdapterListEntry); - - ExInterlockedInsertTailList(&Globals.AdapterList, - &open->AdapterListEntry, - &Globals.GlobalLock); - - // Clear the DO_DEVICE_INITIALIZING flag. This is required - // if you create deviceobjects outside of DriverEntry. - // Untill you do this, application cannot send I/O request. - - deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - } while (FALSE); - - if (*Status != NDIS_STATUS_SUCCESS) { - if (open && open->PacketPool) NdisFreePacketPool(open->PacketPool); - if (deviceObject) IoDeleteDevice(deviceObject); - if(unicodeDeviceName.Buffer) ExFreePool(unicodeDeviceName.Buffer); - if(symbolicLink) { - IoDeleteSymbolicLink(&open->SymbolicLink); - ExFreePool(open->SymbolicLink.Buffer); - } - } - // DebugPrint(("Return BindAdapter :0x%x\n", *Status)); -} - - -VOID -PacketUnbindAdapter( - OUT PNDIS_STATUS Status, - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_HANDLE UnbindContext -) -{ - POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext; - KIRQL oldIrql; - - // DebugPrint(("PacketUnbindAdapter :%ws\n", open->AdapterName.Buffer)); - - if(open->AdapterHandle) { - NdisResetEvent(&open->Event); - InterlockedExchange( (PLONG) &open->Bound, FALSE ); - PacketCancelReadIrps(open->DeviceObject); - - // DebugPrint(("Waiting on CleanupEvent\n")); - NdisWaitEvent(&open->CleanupEvent, 0); - - NdisCloseAdapter(Status, open->AdapterHandle); - - // Wait for it to complete - if(*Status == NDIS_STATUS_PENDING) { - NdisWaitEvent(&open->Event, 0); - *Status = open->Status; - } else { - *Status = NDIS_STATUS_FAILURE; - // ASSERT(0); - } - - KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql); - RemoveEntryList(&open->AdapterListEntry); - KeReleaseSpinLock(&Globals.GlobalLock, oldIrql); - - NdisFreePacketPool(open->PacketPool); - - NdisFreeMemory(open->AdapterName.Buffer, open->AdapterName.Length, 0); - - IoDeleteSymbolicLink(&open->SymbolicLink); - ExFreePool(open->SymbolicLink.Buffer); - - IoDeleteDevice(open->DeviceObject); - } - - // DebugPrint(("Exit PacketUnbindAdapter\n")); -} - -VOID -PacketOpenAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN NDIS_STATUS OpenErrorStatus -) -{ - POPEN_INSTANCE open = ProtocolBindingContext; - - // DebugPrint(("B2ether: OpenAdapterComplete\n")); - - open->Status = Status; - NdisSetEvent(&open->Event); -} - -VOID -PacketCloseAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status -) -{ - POPEN_INSTANCE open = ProtocolBindingContext; - - // DebugPrint(("CloseAdapterComplete\n")); - - open->Status = Status; - NdisSetEvent(&open->Event); -} - - -NDIS_STATUS -PacketPNPHandler( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNET_PNP_EVENT NetPnPEvent -) -{ - POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext; - NDIS_STATUS Status = NDIS_STATUS_SUCCESS; - PNET_DEVICE_POWER_STATE powerState; - - // DebugPrint(("PacketPNPHandler\n")); - - powerState = (PNET_DEVICE_POWER_STATE)NetPnPEvent->Buffer; - - // This will happen when all entities in the system need to be notified - // - //if(open == NULL) - //{ - // return Status; - //} - - switch(NetPnPEvent->NetEvent) { - case NetEventSetPower : - // DebugPrint(("NetEventSetPower\n")); - switch (*powerState) { - case NetDeviceStateD0: - Status = NDIS_STATUS_SUCCESS; - break; - default: - // We can't suspend, so we ask NDIS to Unbind us by - // returning this status: - Status = NDIS_STATUS_NOT_SUPPORTED; - break; - } - break; - case NetEventQueryPower : - // DebugPrint(("NetEventQueryPower\n")); - break; - case NetEventQueryRemoveDevice : - // DebugPrint(("NetEventQueryRemoveDevice \n")); - break; - case NetEventCancelRemoveDevice : - // DebugPrint(("NetEventCancelRemoveDevice \n")); - break; - case NetEventReconfigure : - // The protocol should always succeed this event by returning NDIS_STATUS_SUCCESS - // DebugPrint(("NetEventReconfigure\n")); - break; - case NetEventBindsComplete : - // DebugPrint(("NetEventBindsComplete \n")); - break; - case NetEventPnPCapabilities : - // DebugPrint(("NetEventPnPCapabilities \n")); - case NetEventBindList: - // DebugPrint(("NetEventBindList \n")); - default: - Status = NDIS_STATUS_NOT_SUPPORTED; - break; - } - return Status; -} - - -VOID IoIncrement( IN OUT POPEN_INSTANCE Open ) -{ - LONG result = InterlockedIncrement(&Open->IrpCount); - - //DebugPrint(("IoIncrement %d\n", result)); - - // Need to clear event (when IrpCount bumps from 0 to 1) - if (result == 1) { - NdisResetEvent(&Open->CleanupEvent); - } -} - - -VOID IoDecrement ( IN OUT POPEN_INSTANCE Open ) -{ - LONG result = InterlockedDecrement(&Open->IrpCount); - - //DebugPrint(("IoDecrement %d\n", result)); - - if (result == 0) { - // Set the event when the count transition from 1 to 0. - NdisSetEvent (&Open->CleanupEvent); - } -} diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether.h b/BasiliskII/src/Windows/b2ether/nt5/b2ether.h deleted file mode 100644 index e1c729f8..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _B2ETHER_H_ -#define _B2ETHER_H_ - -#undef ExAllocatePool -#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a, b, 'te2B') - -#if DBG -#define DebugPrint(_x_) \ - DbgPrint("B2ETHER: ");\ - DbgPrint _x_; -#else -#define DebugPrint(_x_) -#endif - -#define NT_DEVICE_NAME L"\\Device\\B2ether" -#define DOS_DEVICE_NAME L"\\DosDevices\\B2ether" - -typedef struct _GLOBAL { - PDRIVER_OBJECT DriverObject; - NDIS_HANDLE NdisProtocolHandle; - UNICODE_STRING RegistryPath; - LIST_ENTRY AdapterList; - KSPIN_LOCK GlobalLock; - PDEVICE_OBJECT ControlDeviceObject; -} GLOBAL, *PGLOBAL; - -GLOBAL Globals; - -typedef struct _INTERNAL_REQUEST { - PIRP Irp; - NDIS_REQUEST Request; -} INTERNAL_REQUEST, *PINTERNAL_REQUEST; - -typedef struct _OPEN_INSTANCE { - PDEVICE_OBJECT DeviceObject; - ULONG IrpCount; - NDIS_STRING AdapterName; - NDIS_STRING SymbolicLink; - NDIS_HANDLE AdapterHandle; - NDIS_HANDLE PacketPool; - KSPIN_LOCK RcvQSpinLock; - LIST_ENTRY RcvList; - NDIS_MEDIUM Medium; - KSPIN_LOCK ResetQueueLock; - LIST_ENTRY ResetIrpList; - NDIS_STATUS Status; - NDIS_EVENT Event; - NDIS_EVENT CleanupEvent; - LIST_ENTRY AdapterListEntry; - BOOLEAN Bound; - CHAR Filler[3]; -} OPEN_INSTANCE, *POPEN_INSTANCE; - -typedef struct _PACKET_RESERVED { - LIST_ENTRY ListElement; - PIRP Irp; - PMDL pMdl; -} PACKET_RESERVED, *PPACKET_RESERVED; - - -#define ETHERNET_HEADER_LENGTH 14 -#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) -#define TRANSMIT_PACKETS 16 - - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ); - -NTSTATUS -PacketCancelReadIrps( - IN PDEVICE_OBJECT DeviceObject -); - -NTSTATUS -PacketCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -PacketBindAdapter( - OUT PNDIS_STATUS Status, - IN NDIS_HANDLE BindContext, - IN PNDIS_STRING DeviceName, - IN PVOID SystemSpecific1, - IN PVOID SystemSpecific2 - ); -VOID -PacketUnbindAdapter( - OUT PNDIS_STATUS Status, - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_HANDLE UnbindContext - ); - - -VOID -PacketOpenAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN NDIS_STATUS OpenErrorStatus - ); - -VOID -PacketCloseAdapterComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status - ); - - -NDIS_STATUS -PacketReceiveIndicate( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_HANDLE MacReceiveContext, - IN PVOID HeaderBuffer, - IN UINT HeaderBufferSize, - IN PVOID LookAheadBuffer, - IN UINT LookaheadBufferSize, - IN UINT PacketSize - ); - -VOID -PacketReceiveComplete( - IN NDIS_HANDLE ProtocolBindingContext - ); - - -VOID -PacketRequestComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_REQUEST pRequest, - IN NDIS_STATUS Status - ); - -VOID -PacketSendComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET pPacket, - IN NDIS_STATUS Status - ); - - -VOID -PacketResetComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status - ); - - -VOID -PacketStatus( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status, - IN PVOID StatusBuffer, - IN UINT StatusBufferSize - ); - - -VOID -PacketStatusComplete( - IN NDIS_HANDLE ProtocolBindingContext - ); - -VOID -PacketTransferDataComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET Packet, - IN NDIS_STATUS Status, - IN UINT BytesTransferred - ); - - -NTSTATUS -PacketShutdown( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -PacketUnload( - IN PDRIVER_OBJECT DriverObject - ); - - - -NTSTATUS -PacketOpen( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketRead( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -PacketIoControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -PacketCancelRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -INT -PacketReceivePacket( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET Packet - ); - -NTSTATUS -PacketGetAdapterList( - IN PVOID Buffer, - IN ULONG Length, - IN OUT PULONG DataLength - ); - -NDIS_STATUS -PacketPNPHandler( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNET_PNP_EVENT pNetPnPEvent - ); - - -VOID -IoIncrement ( - IN OUT POPEN_INSTANCE Open - ); - -VOID -IoDecrement ( - IN OUT POPEN_INSTANCE Open - ); - -#endif //_B2ETHER_H_ diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether.rc b/BasiliskII/src/Windows/b2ether/nt5/b2ether.rc deleted file mode 100644 index 3e4e918a..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether.rc +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_NETWORK -#define VER_FILEDESCRIPTION_STR "Basilisk II Protocol Driver" -#define VER_INTERNALNAME_STR "B2ETHER.SYS" -#define VER_ORIGINALFILENAME_STR "B2ETHER.SYS" - -#include "common.ver" diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether64.sln b/BasiliskII/src/Windows/b2ether/nt5/b2ether64.sln deleted file mode 100755 index 1d2055d9..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether64.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "b2ether64", "b2ether64.vcxproj", "{F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Debug|Win32.ActiveCfg = Debug|Win32 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Debug|Win32.Build.0 = Debug|Win32 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Debug|x64.ActiveCfg = Debug|x64 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Debug|x64.Build.0 = Debug|x64 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Release|Win32.ActiveCfg = Release|Win32 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Release|Win32.Build.0 = Release|Win32 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Release|x64.ActiveCfg = Release|x64 - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether64.vcxproj b/BasiliskII/src/Windows/b2ether/nt5/b2ether64.vcxproj deleted file mode 100755 index 51fe3bc7..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether64.vcxproj +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {F7EA62B6-E0EC-4074-8A83-D0CBB1C990B4} - MakeFileProj - - - - Makefile - true - - - Makefile - false - - - Makefile - - - Makefile - - - - - - - - - - - - - call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk win7 -build - rmdir /s /q objchk_win7_x86 - rmdir /s /q objchk_win7_x86 -call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk win7 -build - objchk_win7_x86 - objchk_win7_x86 - objchk_win7_x86\i386\b2ether.sys - WIN32;_CONSOLE;_X86_;_DDK_;_DEBUG;DBG=1;$(NMakePreprocessorDefinitions) - $(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath) - - - call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre win7 -build - rmdir /s /q objfre_win7_x86 - rmdir /s /q objfre_win7_x86 -call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre win7 -build - objfre_win7_x86 - objfre_win7_x86 - objfre_win7_x86\i386\b2ether.sys - WIN32;_CONSOLE;_X86_;_DDK_;_NDEBUG;DBG=0;$(NMakePreprocessorDefinitions) - $(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath) - - - call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x64 win7 -build - rmdir /s /q objchk_win7_amd64 - rmdir /s /q objchk_win7_amd64 -call $(WDKPATH)\bin\setenv.bat $(WDKPATH) chk x64 win7 -build - objchk_win7_amd64 - objchk_win7_amd64 - objchk_win7_amd64\amd64\b2ether64.sys - WIN32;_CONSOLE;_AMD64_;_DDK_;_DEBUG;DBG=1;$(NMakePreprocessorDefinitions) - $(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath) - - - call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x64 win7 -build - rmdir /s /q objfre_win7_amd64 - rmdir /s /q objfre_win7_amd64 -call $(WDKPATH)\bin\setenv.bat $(WDKPATH) fre x64 win7 -build - objfre_win7_amd64 - objfre_win7_amd64 - objfre_win7_amd64\amd64\b2ether64.sys - WIN32;_CONSOLE;_AMD64_;_DDK_;_NDEBUG;DBG=0;$(NMakePreprocessorDefinitions) - $(WDKPATH)\inc\ddk;$(WDKPATH)\inc\api;$(WDKPATH)\inc\crt;$(NMakeIncludeSearchPath) - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether_openclose.c b/BasiliskII/src/Windows/b2ether/nt5/b2ether_openclose.c deleted file mode 100644 index b584dbc7..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether_openclose.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ntddk.h" -#include "ndis.h" -#include "b2ether.h" - -NTSTATUS PacketOpen( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE open; - NTSTATUS status = STATUS_SUCCESS; - - // DebugPrint(("OpenAdapter\n")); - - if(DeviceObject == Globals.ControlDeviceObject) { - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; - } - - open = DeviceObject->DeviceExtension; - - // DebugPrint(("AdapterName :%ws\n", open->AdapterName.Buffer)); - - IoIncrement(open); - - if(!open->Bound) { - status = STATUS_DEVICE_NOT_READY; - } - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = status; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - IoDecrement(open); - return status; -} - - -NTSTATUS PacketClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE open; - NTSTATUS status = STATUS_SUCCESS; - - // DebugPrint(("CloseAdapter \n")); - - if(DeviceObject == Globals.ControlDeviceObject) { - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; - } - - open = DeviceObject->DeviceExtension; - IoIncrement(open); - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = status; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - IoDecrement(open); - return status; -} - - -NTSTATUS PacketCleanup( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE open; - NTSTATUS status = STATUS_SUCCESS; - - // DebugPrint(("Packet: Cleanup\n")); - - if(DeviceObject == Globals.ControlDeviceObject) { - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; - } - - open = DeviceObject->DeviceExtension; - - IoIncrement(open); - - PacketCancelReadIrps(DeviceObject); - - // Since the current implementation of NDIS doesn't - // allow us to cancel requests pending at the - // minport, we must wait here until they complete. - - IoDecrement(open); - - NdisWaitEvent(&open->CleanupEvent, 0); - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = status; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - return status; -} - - -VOID -PacketResetComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_STATUS Status -) -{ - POPEN_INSTANCE open; - PIRP irp; - - PLIST_ENTRY resetListEntry; - - // DebugPrint(("PacketResetComplte\n")); - - open= (POPEN_INSTANCE)ProtocolBindingContext; - - resetListEntry=ExInterlockedRemoveHeadList( - &open->ResetIrpList, - &open->ResetQueueLock - ); - -#if DBG - if (resetListEntry == NULL) { - DbgBreakPoint(); - return; - } -#endif - - irp=CONTAINING_RECORD(resetListEntry,IRP,Tail.Overlay.ListEntry); - - if(Status == NDIS_STATUS_SUCCESS) { - irp->IoStatus.Status = STATUS_SUCCESS; - } else { - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - } - - irp->IoStatus.Information = 0; - IoCompleteRequest(irp, IO_NO_INCREMENT); - IoDecrement(open); - - // DebugPrint(("PacketResetComplte exit\n")); -} diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether_read.c b/BasiliskII/src/Windows/b2ether/nt5/b2ether_read.c deleted file mode 100644 index 3f4f100d..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether_read.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ntddk.h" -#include "ndis.h" -#include "b2ether.h" - - -NTSTATUS PacketRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE open; - PNDIS_PACKET pPacket; - NDIS_STATUS status; - NTSTATUS ntStatus; - PIO_STACK_LOCATION irpSp; - - // DebugPrint(("Read\n")); - - open = DeviceObject->DeviceExtension; - - IoIncrement(open); - - if(!open->Bound) { - ntStatus = STATUS_DEVICE_NOT_READY; - goto ERROR; - } - - irpSp = IoGetCurrentIrpStackLocation(Irp); - - if (irpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) { - ntStatus = STATUS_BUFFER_TOO_SMALL; - goto ERROR; - } - - NdisAllocatePacket( &status, &pPacket, open->PacketPool ); - if (status != NDIS_STATUS_SUCCESS) { - // DebugPrint(("Packet: Read- No free packets\n")); - ntStatus = STATUS_INSUFFICIENT_RESOURCES; - goto ERROR; - } - - RESERVED(pPacket)->Irp=Irp; - RESERVED(pPacket)->pMdl=NULL; - IoMarkIrpPending(Irp); - - IoSetCancelRoutine(Irp, PacketCancelRoutine); - - ExInterlockedInsertTailList( - &open->RcvList, - &RESERVED(pPacket)->ListElement, - &open->RcvQSpinLock); - - return STATUS_PENDING; - -ERROR: - Irp->IoStatus.Status = ntStatus; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - IoDecrement(open); - return ntStatus; -} - - - -NDIS_STATUS -PacketReceiveIndicate ( - IN NDIS_HANDLE ProtocolBindingContext, - IN NDIS_HANDLE MacReceiveContext, - IN PVOID HeaderBuffer, - IN UINT HeaderBufferSize, - IN PVOID LookAheadBuffer, - IN UINT LookaheadBufferSize, - IN UINT PacketSize -) -{ - POPEN_INSTANCE open; - PIO_STACK_LOCATION irpSp; - PIRP irp; - PLIST_ENTRY packetListEntry; - PNDIS_PACKET pPacket; - ULONG sizeToTransfer; - NDIS_STATUS status; - UINT bytesTransfered = 0; - ULONG bufferLength; - PPACKET_RESERVED reserved; - PMDL pMdl; - - // DebugPrint(("ReceiveIndicate\n")); - - open= (POPEN_INSTANCE)ProtocolBindingContext; - - if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) { - return NDIS_STATUS_SUCCESS; - } - - // See if there are any pending read that we can satisfy - packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock ); - - if (packetListEntry == NULL) { - // DebugPrint(("No pending read, dropping packets\n")); - return NDIS_STATUS_NOT_ACCEPTED; - } - - reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); - pPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); - - irp = RESERVED(pPacket)->Irp; - irpSp = IoGetCurrentIrpStackLocation(irp); - - // We don't have to worry about the situation where the IRP is cancelled - // after we remove it from the queue and before we reset the cancel - // routine because the cancel routine has been coded to cancel an IRP - // only if it's in the queue. - - IoSetCancelRoutine(irp, NULL); - - bufferLength = irpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH; - - sizeToTransfer = (PacketSize < bufferLength) ? PacketSize : bufferLength; - - NdisMoveMappedMemory( - MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), - HeaderBuffer, - HeaderBufferSize - ); - - pMdl=IoAllocateMdl( - MmGetMdlVirtualAddress(irp->MdlAddress), - MmGetMdlByteCount(irp->MdlAddress), - FALSE, - FALSE, - NULL - ); - - if (pMdl == NULL) { - // DebugPrint(("Packet: Read-Failed to allocate Mdl\n")); - status = NDIS_STATUS_RESOURCES; - goto ERROR; - } - - IoBuildPartialMdl( - irp->MdlAddress, - pMdl, - ((PUCHAR)MmGetMdlVirtualAddress(irp->MdlAddress))+ETHERNET_HEADER_LENGTH, - 0 - ); - - pMdl->Next = NULL; - - RESERVED(pPacket)->pMdl=pMdl; - - NdisChainBufferAtFront(pPacket,pMdl); - - NdisTransferData( - &status, - open->AdapterHandle, - MacReceiveContext, - 0, - sizeToTransfer, - pPacket, - &bytesTransfered - ); - - if (status == NDIS_STATUS_PENDING) { - return NDIS_STATUS_SUCCESS; - } - -ERROR: - PacketTransferDataComplete( open, pPacket, status, bytesTransfered ); - return NDIS_STATUS_SUCCESS; -} - - -VOID -PacketTransferDataComplete ( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET pPacket, - IN NDIS_STATUS Status, - IN UINT BytesTransfered -) -{ - PIO_STACK_LOCATION irpSp; - POPEN_INSTANCE open; - PIRP irp; - PMDL pMdl; - - // DebugPrint(("Packet: TransferDataComplete\n")); - - open = (POPEN_INSTANCE)ProtocolBindingContext; - irp = RESERVED(pPacket)->Irp; - irpSp = IoGetCurrentIrpStackLocation(irp); - pMdl = RESERVED(pPacket)->pMdl; - - - if(pMdl) IoFreeMdl(pMdl); - - NdisFreePacket(pPacket); - - if(Status == NDIS_STATUS_SUCCESS) { - irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH; - } else { - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - irp->IoStatus.Information = 0; - } - - // DebugPrint(("BytesTransfered:%d\n", irp->IoStatus.Information)); - - IoCompleteRequest(irp, IO_NO_INCREMENT); - IoDecrement(open); -} - -VOID PacketReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext ) -{ -} - -INT -PacketReceivePacket( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET Packet -) -{ - UINT bytesTransfered = 0; - POPEN_INSTANCE open; - PIRP irp; - PNDIS_PACKET myPacket; - PLIST_ENTRY packetListEntry; - ULONG bufferLength; - PPACKET_RESERVED reserved; - PIO_STACK_LOCATION irpSp; - PMDL mdl; - PVOID startAddress; - NTSTATUS status; - - // DebugPrint(("PacketReceivePacket\n")); - - open = (POPEN_INSTANCE)ProtocolBindingContext; - - packetListEntry = ExInterlockedRemoveHeadList( - &open->RcvList, - &open->RcvQSpinLock - ); - - if (packetListEntry == NULL) { - // DebugPrint(("No pending read, dropping packets\n")); - return 0; - } - - reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); - myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); - - irp = RESERVED(myPacket)->Irp; - irpSp = IoGetCurrentIrpStackLocation(irp); - - // We don't have to worry about the situation where the IRP is cancelled - // after we remove it from the queue and before we reset the cancel - // routine because the cancel routine has been coded to cancel an IRP - // only if it's in the queue. - - IoSetCancelRoutine(irp, NULL); - - // Following block of code locks the destination packet - // MDLs in a safe manner. This is a temporary workaround - // for NdisCopyFromPacketToPacket that currently doesn't use - // safe functions to lock pages of MDL. This is required to - // prevent system from bugchecking under low memory resources. - // - { - PVOID virtualAddress; - PNDIS_BUFFER firstBuffer, nextBuffer; - ULONG totalLength; - - NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength); - while( firstBuffer ) { - NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority ); - if(!virtualAddress) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto CleanExit; - } - NdisGetNextBuffer(firstBuffer, &nextBuffer); - firstBuffer = nextBuffer; - } - } - - NdisChainBufferAtFront( myPacket, irp->MdlAddress ); - bufferLength=irpSp->Parameters.Read.Length; - NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0, &bytesTransfered ); - -CleanExit: - NdisFreePacket(myPacket); - irp->IoStatus.Status = status; - irp->IoStatus.Information = bytesTransfered; - IoCompleteRequest(irp, IO_NO_INCREMENT); - // DebugPrint(("BytesTransfered:%d\n", bytesTransfered)); - IoDecrement(open); - return 0; -} - - -VOID -PacketCancelRoutine ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp -) - -{ - POPEN_INSTANCE open = DeviceObject->DeviceExtension; - KIRQL oldIrql; - PIRP irpToComplete = NULL; - PLIST_ENTRY thisEntry, listHead; - PIRP pendingIrp; - PNDIS_PACKET myPacket = NULL; - PPACKET_RESERVED reserved; - PMDL mdl; - - // Don't assume that the IRP being cancelled is in the queue. - // Only complete the IRP if it IS in the queue. - // - // Must acquire the local spinlock before releasing - // the global cancel spinlock - // - // DebugPrint(("PacketCancelRoutine\n")); - - oldIrql = Irp->CancelIrql; - - // One should not intermix KeAcquireSpinLock(AtDpcLevel) - // and ExInterlocked...List() functions on the same spinlock if the - // routines that use the lock run at IRQL > DISPATCH_LEVEL. - // After acquiring the lock using Ke function, if we got interrupted - // and entered into an ISR and tried to manipulate the list using - // ExInterlocked...List function with the same lock, we deadlock. - // In this sample we can safely do that because none of our routines - // will be called at IRQL > DISPATCH_LEVEL. - - KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock); - IoReleaseCancelSpinLock( KeGetCurrentIrql() ); - - listHead = &open->RcvList; - for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) { - reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement); - myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); - pendingIrp = RESERVED(myPacket)->Irp; - if (pendingIrp == Irp) { - RemoveEntryList(thisEntry); - irpToComplete = pendingIrp; - break; - } - } - - KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql); - - if(irpToComplete) { - // DebugPrint(("Cancelling IRP\n")); - // ASSERT(myPacket); - - NdisFreePacket(myPacket); - - irpToComplete->IoStatus.Status = STATUS_CANCELLED; - irpToComplete->IoStatus.Information = 0; - IoCompleteRequest(irpToComplete, IO_NO_INCREMENT); - IoDecrement(open); - } -} - - -NTSTATUS PacketCancelReadIrps( IN PDEVICE_OBJECT DeviceObject ) -{ - POPEN_INSTANCE open = DeviceObject->DeviceExtension; - PLIST_ENTRY thisEntry; - PIRP pendingIrp; - PNDIS_PACKET myPacket = NULL; - PPACKET_RESERVED reserved; - PMDL mdl; - - // DebugPrint(("PacketCancelReadIrps\n")); - - // Walk through the RcvList and cancel all read IRPs. - - while( thisEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock )) { - reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement); - myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); - - ASSERT(myPacket); - - pendingIrp = RESERVED(myPacket)->Irp; - - NdisFreePacket(myPacket); - - // DebugPrint(("Cancelled : 0%0x\n", pendingIrp)); - - IoSetCancelRoutine(pendingIrp, NULL); - - pendingIrp->IoStatus.Information = 0; - pendingIrp->IoStatus.Status = STATUS_CANCELLED; - IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); - IoDecrement(open); - } - - return STATUS_SUCCESS; -} diff --git a/BasiliskII/src/Windows/b2ether/nt5/b2ether_write.c b/BasiliskII/src/Windows/b2ether/nt5/b2ether_write.c deleted file mode 100644 index 42b1ec94..00000000 --- a/BasiliskII/src/Windows/b2ether/nt5/b2ether_write.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * b2ether driver -- derived from DDK packet driver sample - * - * Basilisk II (C) 1997-1999 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ntddk.h" -#include "ndis.h" -#include "b2ether.h" - - -NTSTATUS PacketWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) -{ - POPEN_INSTANCE open; - PNDIS_PACKET pPacket; - NDIS_STATUS Status; - - // DebugPrint(("SendAdapter\n")); - - open = DeviceObject->DeviceExtension; - - IoIncrement(open); - - if(!open->Bound) { - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - IoDecrement(open); - return STATUS_UNSUCCESSFUL; - } - - NdisAllocatePacket( &Status, &pPacket, open->PacketPool ); - - if (Status != NDIS_STATUS_SUCCESS) { - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest (Irp, IO_NO_INCREMENT); - IoDecrement(open); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RESERVED(pPacket)->Irp=Irp; - - NdisChainBufferAtFront(pPacket,Irp->MdlAddress); - - // Important: Since we have marked the IRP pending, we must return - // STATUS_PENDING even we happen to complete the IRP synchronously. - - IoMarkIrpPending(Irp); - - NdisSend( &Status, open->AdapterHandle, pPacket ); - - if (Status != NDIS_STATUS_PENDING) { - PacketSendComplete( open, pPacket, Status ); - } - - return STATUS_PENDING; -} - -VOID -PacketSendComplete( - IN NDIS_HANDLE ProtocolBindingContext, - IN PNDIS_PACKET pPacket, - IN NDIS_STATUS Status -) -{ - PIRP irp; - PIO_STACK_LOCATION irpSp; - - // DebugPrint(("Packet: SendComplete :%x\n", Status)); - - irp = RESERVED(pPacket)->Irp; - irpSp = IoGetCurrentIrpStackLocation(irp); - - NdisFreePacket(pPacket); - - if(Status == NDIS_STATUS_SUCCESS) { - irp->IoStatus.Information = irpSp->Parameters.Write.Length; - irp->IoStatus.Status = STATUS_SUCCESS; - } else { - irp->IoStatus.Information = 0; - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - } - - IoCompleteRequest(irp, IO_NO_INCREMENT); - IoDecrement((POPEN_INSTANCE)ProtocolBindingContext); -} diff --git a/BasiliskII/src/Windows/b2ether/packet32.cpp b/BasiliskII/src/Windows/b2ether/packet32.cpp deleted file mode 100755 index 72efb1fe..00000000 --- a/BasiliskII/src/Windows/b2ether/packet32.cpp +++ /dev/null @@ -1,694 +0,0 @@ -/* - * packet32.cpp - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "util_windows.h" -#include -#include -#include "cpu_emulation.h" -typedef unsigned long ULONG_PTR, *PULONG_PTR; - -// VC6 does not have this, Platform SDK has. -// In case of errors, try to comment out, the needed -// definitions are below (#ifndef _NTDDNDIS_) - -// Most people don't have the Platform SDK, so I take this one out. -// #include - -#include "inc/ntddpack.h" - -#include "ether.h" -#include "ether_defs.h" -#include "b2ether/multiopt.h" -#include "b2ether/inc/b2ether_hl.h" - - - -#ifndef _NTDDNDIS_ -#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 -#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 -#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 -#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 -#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 -#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -#define OID_802_3_MULTICAST_LIST 0x01010103 - -#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E -#endif - -#define DEBUG_PACKETS 0 -#define DEBUG 0 -#include "debug.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if DEBUG -#pragma optimize("",off) -#endif - -#define MAX_MULTICAST 100 -#define MAX_MULTICAST_SZ (20*ETH_802_3_ADDRESS_LENGTH) - -static ULONG packet_filter = 0; - - -LPADAPTER PacketOpenAdapter( LPCTSTR AdapterName, int16 mode ) -{ - LPADAPTER lpAdapter; - BOOLEAN Result = TRUE; - - D(bug("Packet32: PacketOpenAdapter\n")); - - // May fail if user is not an Administrator. - StartPacketDriver( TEXT("B2ether") ); - - lpAdapter = (LPADAPTER)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(ADAPTER) ); - if (lpAdapter==NULL) { - D(bug("Packet32: PacketOpenAdapter GlobalAlloc Failed\n")); - return NULL; - } - - TCHAR device_name[256]; - _sntprintf(lpAdapter->SymbolicLink, lengthof(lpAdapter->SymbolicLink), TEXT("\\\\.\\B2ether_%s"), AdapterName ); - _sntprintf(device_name, lengthof(device_name), TEXT("\\Device\\B2ether_%s"), AdapterName ); - - // Work around one subtle NT4 bug. - DefineDosDevice( - DDD_REMOVE_DEFINITION, - &lpAdapter->SymbolicLink[4], - NULL - ); - DefineDosDevice( - DDD_RAW_TARGET_PATH, - &lpAdapter->SymbolicLink[4], - device_name - ); - - packet_filter = NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_MULTICAST | - NDIS_PACKET_TYPE_BROADCAST; - - if(mode == ETHER_MULTICAST_ALL) packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; - if(mode == ETHER_MULTICAST_PROMISCUOUS) packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; - - if (Result) { - lpAdapter->hFile = CreateFile(lpAdapter->SymbolicLink, - GENERIC_WRITE | GENERIC_READ, - 0, - NULL, - // (os == VER_PLATFORM_WIN32_NT) ? CREATE_ALWAYS : OPEN_EXISTING, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - 0 - ); - if (lpAdapter->hFile != INVALID_HANDLE_VALUE) { - if(*AdapterName && _tcscmp(AdapterName,TEXT("")) != 0) { - PacketSetFilter( lpAdapter, packet_filter ); - } - return lpAdapter; - } - } - D(bug("Packet32: PacketOpenAdapter Could not open adapter\n")); - GlobalFreePtr( lpAdapter ); - return NULL; -} - -VOID PacketCloseAdapter( LPADAPTER lpAdapter ) -{ - D(bug("Packet32: PacketCloseAdapter\n")); - - if(lpAdapter) { - if(lpAdapter->hFile) { - CloseHandle(lpAdapter->hFile); - } - GlobalFreePtr(lpAdapter); - } -} - -LPPACKET PacketAllocatePacket( LPADAPTER AdapterObject, UINT Length ) -{ - LPPACKET lpPacket; - - lpPacket = (LPPACKET)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(PACKET) ); - if(lpPacket==NULL) { - D(bug("Packet32: PacketAllocatePacket: GlobalAlloc Failed\n")); - return NULL; - } - - lpPacket->OverLapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); - if(!lpPacket->OverLapped.hEvent) { - D(bug("Packet32: PacketAllocatePacket: CreateEvent Failed\n")); - GlobalFreePtr(lpPacket); - return NULL; - } - - lpPacket->Buffer = GlobalAllocPtr(GMEM_MOVEABLE,2048); // 1514 - if(!lpPacket->Buffer) { - D(bug("Packet32: PacketAllocatePacket: GlobalAllocPtr Failed\n")); - if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent); - GlobalFreePtr(lpPacket); - return NULL; - } - - lpPacket->OverLapped.Offset = 0; - lpPacket->OverLapped.OffsetHigh = 0; - lpPacket->Length = Length; - lpPacket->BytesReceived = 0; - lpPacket->bIoComplete = FALSE; - lpPacket->free = TRUE; - - return lpPacket; -} - -VOID PacketFreePacket( LPPACKET lpPacket ) -{ - if(lpPacket) { - if(lpPacket->Buffer) GlobalFreePtr(lpPacket->Buffer); - if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent); - GlobalFreePtr(lpPacket); - } -} - -BOOLEAN PacketDeviceIoControl( - LPADAPTER lpAdapterObject, - LPPACKET lpPacket, - ULONG ulIoctl, - BOOLEAN bSync -) -{ - BOOLEAN Result; - - lpPacket->OverLapped.Offset = 0; - lpPacket->OverLapped.OffsetHigh = 0; - lpPacket->BytesReceived = 0; - - if ( !ResetEvent( lpPacket->OverLapped.hEvent ) ) { - lpPacket->bIoComplete = FALSE; - D(bug( "Packet32: PacketDeviceIoControl failed to reset event\r\n", GetLastError() )); - return FALSE; - } - - Result = DeviceIoControl( - lpAdapterObject->hFile, - ulIoctl, - lpPacket->Buffer, - lpPacket->Length, - lpPacket->Buffer, - lpPacket->Length, - &(lpPacket->BytesReceived), - &(lpPacket->OverLapped) ); - - if( !Result && bSync ) { - if (GetLastError() == ERROR_IO_PENDING) { - Result = GetOverlappedResult( lpAdapterObject->hFile, - &(lpPacket->OverLapped), - &(lpPacket->BytesReceived), - TRUE ); - } else { - D(bug( "Packet32: unsupported API call returned error 0x%x\r\n", GetLastError() )); - } - } - lpPacket->bIoComplete = Result; - return Result; -} - -VOID CALLBACK PacketSendCompletionRoutine( - DWORD dwErrorCode, - DWORD dwNumberOfBytesTransfered, - LPOVERLAPPED lpOverlapped -) -{ - LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped); - -#if DEBUG_PACKETS - D(bug("PacketSendCompletionRoutine %d\n",dwNumberOfBytesTransfered)); -#endif - - lpPacket->bIoComplete = TRUE; - // lpPacket->free = TRUE; - // PacketFreePacket(lpPacket); - recycle_write_packet(lpPacket); -} - -BOOLEAN PacketSendPacket( - LPADAPTER AdapterObject, - LPPACKET lpPacket, - BOOLEAN Sync, - BOOLEAN RecyclingAllowed -) -{ - BOOLEAN Result; - -#if DEBUG_PACKETS - D(bug("Packet32: PacketSendPacket bytes=%d, sync=%d\n",lpPacket->Length,Sync)); -#endif - - lpPacket->OverLapped.Offset = 0; - lpPacket->OverLapped.OffsetHigh = 0; - lpPacket->bIoComplete = FALSE; - - if(Sync) { - Result = WriteFile( - AdapterObject->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->BytesReceived, - &lpPacket->OverLapped - ); - if(Result) { - Result = GetOverlappedResult( - AdapterObject->hFile, - &lpPacket->OverLapped, - &lpPacket->BytesReceived, - TRUE - ); - } else { - D(bug("Packet32: PacketSendPacket WriteFile failed, err=%d\n",(int)GetLastError())); - } - lpPacket->bIoComplete = TRUE; - if(RecyclingAllowed) PacketFreePacket(lpPacket); -#if DEBUG_PACKETS - D(bug("Packet32: PacketSendPacket result=%d, bytes=%d\n",(int)Result,(int)lpPacket->BytesReceived)); -#endif - } else { - // don't care about the result - Result = WriteFileEx( - AdapterObject->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->OverLapped, - PacketSendCompletionRoutine - ); -#if DEBUG_PACKETS - D(bug("Packet32: PacketSendPacket result=%d\n",(int)Result)); -#endif - if(!Result && RecyclingAllowed) { - recycle_write_packet(lpPacket); - } - } - - return Result; -} - -BOOLEAN PacketReceivePacket( - LPADAPTER AdapterObject, - LPPACKET lpPacket, - BOOLEAN Sync -) -{ - BOOLEAN Result; - - lpPacket->OverLapped.Offset=0; - lpPacket->OverLapped.OffsetHigh=0; - lpPacket->bIoComplete = FALSE; - -#if DEBUG_PACKETS - D(bug("Packet32: PacketReceivePacket\n")); -#endif - - if (Sync) { - Result = ReadFile( - AdapterObject->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->BytesReceived, - &lpPacket->OverLapped - ); - if(Result) { - Result = GetOverlappedResult( - AdapterObject->hFile, - &lpPacket->OverLapped, - &lpPacket->BytesReceived, - TRUE - ); - if(Result) - lpPacket->bIoComplete = TRUE; - else - lpPacket->free = TRUE; - } - } else { - Result = ReadFileEx( - AdapterObject->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->OverLapped, - packet_read_completion - ); - } - - if(!Result) lpPacket->BytesReceived = 0; - -#if DEBUG_PACKETS - D(bug("Packet32: PacketReceivePacket got %d bytes, result=%d\n",lpPacket->BytesReceived,(int)Result)); -#endif - - return Result; -} - -BOOLEAN PacketRequest( - LPADAPTER lpAdapterObject, - LPPACKET lpPacket, - BOOLEAN bSet -) -{ - BOOLEAN Result = FALSE; - - Result = PacketDeviceIoControl( - lpAdapterObject, - lpPacket, - (ULONG) ((bSet) ? IOCTL_PROTOCOL_SET_OID : IOCTL_PROTOCOL_QUERY_OID), - TRUE ); - - if ( lpPacket->BytesReceived == 0 ) { - D(bug( "Packet32: Ndis returned error to OID\r\n")); - Result = FALSE; - } - return Result; -} - -LPPACKET PacketQueryOid( - LPADAPTER lpAdapter, - ULONG ulOid, - ULONG ulLength -) -{ - ULONG ioctl; - LPPACKET lpPacket; - -#define pOidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) - - lpPacket = PacketAllocatePacket( lpAdapter, sizeof(PACKET_OID_DATA)-1+ulLength ); - - if( lpPacket ) { - ioctl = IOCTL_PROTOCOL_QUERY_OID; - pOidData->Oid = ulOid; - pOidData->Length = ulLength; - - if (PacketRequest( lpAdapter, lpPacket, FALSE )) { - return lpPacket; - } - PacketFreePacket( lpPacket ); - } - -#undef pOidData - - return 0; -} - -BOOLEAN PacketGetMAC( LPADAPTER AdapterObject, LPBYTE address, BOOL permanent ) -{ - BOOLEAN Status; - LPPACKET lpPacket; - - lpPacket = PacketQueryOid( - AdapterObject, - permanent ? OID_802_3_PERMANENT_ADDRESS : OID_802_3_CURRENT_ADDRESS, - ETH_802_3_ADDRESS_LENGTH - ); - if(lpPacket) { - memcpy( address, - ((BYTE *)(lpPacket->Buffer)) + sizeof(PACKET_OID_DATA) - 1, - ETH_802_3_ADDRESS_LENGTH ); - PacketFreePacket( lpPacket ); - Status = TRUE; - } else { - Status = FALSE; - } - - return Status; -} - -// There are other ways to do this. - -BOOLEAN PacketAddMulticast( LPADAPTER AdapterObject, LPBYTE address ) -{ - BOOLEAN Status = FALSE; - LPBYTE p; - int i, count; - LPPACKET lpPacket; - - D(bug("PacketAddMulticast\n")); - - /* - if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) { - D(bug("PacketAddMulticast: already listening for all multicast\n")); - return TRUE; - } - */ - - lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ ); -#define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) - - if(lpPacket) { - count = OidData->Length / ETH_802_3_ADDRESS_LENGTH; - - D(bug("PacketAddMulticast: %d old addresses\n",count)); - - p = (LPBYTE)OidData->Data; - - for( i=0; i= MAX_MULTICAST) { - D(bug("PacketAddMulticast: too many addresses\n")); - Status = FALSE; - } else { - D(bug("PacketAddMulticast: adding a new address\n")); - - // ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*1-1); - ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count+1)-1); - - LPPACKET lpPacket2 = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); -#define OidData2 ((PPACKET_OID_DATA)(lpPacket2->Buffer)) - if ( lpPacket2 ) { - OidData2->Oid = OID_802_3_MULTICAST_LIST; - - // OidData2->Length = ETH_802_3_ADDRESS_LENGTH*1; - // memcpy( OidData2->Data, address, ETH_802_3_ADDRESS_LENGTH ); - - memcpy( OidData2->Data, OidData->Data, ETH_802_3_ADDRESS_LENGTH*count ); - memcpy( OidData2->Data+ETH_802_3_ADDRESS_LENGTH*count, address, ETH_802_3_ADDRESS_LENGTH ); - OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count+1); - - Status = PacketRequest( AdapterObject, lpPacket2, TRUE ); - PacketFreePacket( lpPacket2 ); - } -#undef OidData2 - } - } - PacketFreePacket( lpPacket ); - } - - #undef OidData - - // return Status; - return TRUE; -} - -// It seems that the last multicast address is never deleted. Why? -// Don't know the reason, but luckily this is not fatal. -// Hard to examine return codes. See NE2000 sources, always returns ok. - -BOOLEAN PacketDelMulticast( LPADAPTER AdapterObject, LPBYTE address ) -{ - BOOLEAN Status = FALSE; - LPBYTE p; - int i, count; - LPPACKET lpPacket, lpPacket2; - - D(bug("PacketDelMulticast\n")); - - if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) { - D(bug("PacketDelMulticast: already listening for all multicast\n")); - return TRUE; - } - - lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ ); -#define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) - - if(lpPacket) { - count = OidData->Length / ETH_802_3_ADDRESS_LENGTH; - - D(bug("PacketDelMulticast: %d old addresses\n",count)); - - Status = FALSE; - - p = (LPBYTE)OidData->Data; - - for( i=0; iBuffer)) - if ( lpPacket2 ) { - OidData2->Oid = OID_802_3_MULTICAST_LIST; - OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count-1); - tail_len = ETH_802_3_ADDRESS_LENGTH * (count-i-1); - if(tail_len) memmove( p, p+ETH_802_3_ADDRESS_LENGTH, tail_len ); - if(OidData2->Length) memcpy( OidData2->Data, OidData->Data, OidData2->Length ); - if(count == 1) memset( OidData2->Data, 0, ETH_802_3_ADDRESS_LENGTH ); // eh... - Status = PacketRequest( AdapterObject, lpPacket2, TRUE ); - PacketFreePacket( lpPacket2 ); - D(bug("PacketDelMulticast: PacketRequest returned status 0x%X, last error = 0x%X\n",Status,GetLastError())); - } - break; -#undef OidData2 - } - p += ETH_802_3_ADDRESS_LENGTH; - } - if( i == count ) { - D(bug("PacketDelMulticast: cannot delete, was not defined\n")); - } - PacketFreePacket( lpPacket ); -#undef OidData - } - - // return Status; - return TRUE; -} - -BOOLEAN PacketSetFilter( LPADAPTER AdapterObject, ULONG Filter ) -{ - BOOLEAN Status; - ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1); - LPPACKET lpPacket; - - lpPacket = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); -#define lpOidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) - - if ( lpPacket ) { - lpOidData->Oid = OID_GEN_CURRENT_PACKET_FILTER; - lpOidData->Length = sizeof(ULONG); - *((PULONG)lpOidData->Data) = Filter; - Status = PacketRequest( AdapterObject, lpPacket, TRUE ); - PacketFreePacket( lpPacket ); - } else { - Status = FALSE; - } - -#undef lpOidData - - return Status; -} - -BOOLEAN StartPacketDriver( LPCTSTR ServiceName ) -{ - BOOLEAN Status = FALSE; - - SC_HANDLE SCManagerHandle; - SC_HANDLE SCServiceHandle; - - SCManagerHandle = OpenSCManager( - NULL, - NULL, - SC_MANAGER_ALL_ACCESS); - - if(SCManagerHandle == NULL) { - D(bug("Could not open Service Control Manager\r\n")); - } else { - SCServiceHandle = OpenService(SCManagerHandle,ServiceName,SERVICE_START); - if (SCServiceHandle == NULL) { - D(bug(TEXT("Could not open service %s\r\n"),ServiceName)); - } else { - Status = StartService( SCServiceHandle, 0, NULL ); - if(!Status) { - if (GetLastError()==ERROR_SERVICE_ALREADY_RUNNING) { - Status = TRUE; - } - } - BOOL waiting = TRUE; - // loop until the service is fully started. - while (waiting) { - SERVICE_STATUS ServiceStatus; - if (QueryServiceStatus(SCServiceHandle, &ServiceStatus)) { - switch(ServiceStatus.dwCurrentState) { - case SERVICE_RUNNING: - waiting = FALSE; - Status = TRUE; - break; - case SERVICE_START_PENDING: - Sleep(500); - break; - default: - waiting = FALSE; - break; - } - } else { - waiting = FALSE; - } - } - CloseServiceHandle(SCServiceHandle); - } - CloseServiceHandle(SCManagerHandle); - } - return Status; -} - -ULONG PacketGetAdapterNames( LPADAPTER lpAdapter, LPTSTR pStr, PULONG BufferSize ) -{ - LONG Status; - - HKEY hKey; - DWORD RegType; - - Status = RegOpenKey( - HKEY_LOCAL_MACHINE, - TEXT("SYSTEM\\CurrentControlSet\\Services\\B2Ether\\Linkage"), - &hKey - ); - if( Status == ERROR_SUCCESS ) { - Status = RegQueryValueEx( - hKey, - TEXT("Export"), - NULL, - &RegType, - (LPBYTE)pStr, - BufferSize - ); - RegCloseKey(hKey); - } - - return Status; -} - -#ifdef __cplusplus -} -#endif - -#if DEBUG -#pragma optimize("",on) -#endif diff --git a/BasiliskII/src/Windows/build68k.vcxproj b/BasiliskII/src/Windows/build68k.vcxproj deleted file mode 100644 index b29e072d..00000000 --- a/BasiliskII/src/Windows/build68k.vcxproj +++ /dev/null @@ -1,156 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {7BCEAB0D-0C62-46E1-BA1E-AF42798B67D0} - Win32Proj - build68k - 8.1 - - - - Application - true - v140 - Unicode - - - Application - true - v140 - Unicode - - - Application - false - v140 - true - Unicode - - - Application - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(Configuration)\$(ProjectName)\ - - - true - - - false - $(Configuration)\$(ProjectName)\ - - - false - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - true - true - - - - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/build68k.vcxproj.filters b/BasiliskII/src/Windows/build68k.vcxproj.filters deleted file mode 100644 index 65e38167..00000000 --- a/BasiliskII/src/Windows/build68k.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/cd_defs.h b/BasiliskII/src/Windows/cd_defs.h deleted file mode 100755 index f58069e5..00000000 --- a/BasiliskII/src/Windows/cd_defs.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * cd_defs.h - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define MAXIMUM_NUMBER_TRACKS 100 -#define MAXIMUM_CDROM_SIZE 804 - -#pragma pack(push, 1) - -typedef struct _TRACK_DATA { - UCHAR Reserved; - UCHAR Control : 4; - UCHAR Adr : 4; - UCHAR TrackNumber; - UCHAR Reserved1; - UCHAR Address[4]; -} TRACK_DATA, *PTRACK_DATA; - -typedef struct _CDROM_TOC { - UCHAR Length[2]; - UCHAR FirstTrack; - UCHAR LastTrack; - TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; -} CDROM_TOC, *PCDROM_TOC; - -// #include "ntddcdrm.h" -#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM -#define IOCTL_CDROM_UNLOAD_DRIVER CTL_CODE(IOCTL_CDROM_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS) -// -// CDROM Audio Device Control Functions -// -#define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_CONTROL CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_PLAY_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_STOP_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_PAUSE_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RESUME_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_SET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_LAST_SESSION CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) -#define IOCTL_CDROM_DISK_TYPE CTL_CODE(IOCTL_CDROM_BASE, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS) - -typedef struct _VOLUME_CONTROL { - UCHAR PortVolume[4]; -} VOLUME_CONTROL, *PVOLUME_CONTROL; - -typedef struct _CDROM_PLAY_AUDIO_MSF { - UCHAR StartingM; - UCHAR StartingS; - UCHAR StartingF; - UCHAR EndingM; - UCHAR EndingS; - UCHAR EndingF; -} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; - -typedef struct _CDROM_SEEK_AUDIO_MSF { - UCHAR M; - UCHAR S; - UCHAR F; -} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; - - -// -// CD ROM Sub-Q Channel Data Format -// - -typedef struct _SUB_Q_HEADER { - UCHAR Reserved; - UCHAR AudioStatus; - UCHAR DataLength[2]; -} SUB_Q_HEADER, *PSUB_Q_HEADER; - -typedef struct _SUB_Q_CURRENT_POSITION { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Control : 4; - UCHAR ADR : 4; - UCHAR TrackNumber; - UCHAR IndexNumber; - UCHAR AbsoluteAddress[4]; - UCHAR TrackRelativeAddress[4]; -} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; - -typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved[3]; - UCHAR Reserved1 : 7; - UCHAR Mcval : 1; - UCHAR MediaCatalog[15]; -} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; - -typedef struct _SUB_Q_TRACK_ISRC { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved0; - UCHAR Track; - UCHAR Reserved1; - UCHAR Reserved2 : 7; - UCHAR Tcval : 1; - UCHAR TrackIsrc[15]; -} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; - -typedef union _SUB_Q_CHANNEL_DATA { - SUB_Q_CURRENT_POSITION CurrentPosition; - SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; - SUB_Q_TRACK_ISRC TrackIsrc; -} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; - -typedef enum _TRACK_MODE_TYPE { - YellowMode2, - XAForm2, - CDDA -} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; - -typedef struct __RAW_READ_INFO { - LARGE_INTEGER DiskOffset; - ULONG SectorCount; - TRACK_MODE_TYPE TrackMode; -} RAW_READ_INFO, *PRAW_READ_INFO; - -typedef struct _CDROM_SUB_Q_DATA_FORMAT { - UCHAR Format; - UCHAR Track; -} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; - -#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 -#define IOCTL_CDROM_CURRENT_POSITION 0x01 -#define IOCTL_CDROM_MEDIA_CATALOG 0x02 -#define IOCTL_CDROM_TRACK_ISRC 0x03 - -#pragma pack(pop) diff --git a/BasiliskII/src/Windows/cdenable/cache.cpp b/BasiliskII/src/Windows/cdenable/cache.cpp deleted file mode 100755 index 483f3ca1..00000000 --- a/BasiliskII/src/Windows/cdenable/cache.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * cache.cpp - simple floppy/cd cache for Win32 - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - Note that this is particularly silly cache code - and doesn't even use hash buckets. It is sufficient - for floppies and maybe emulated cd's but that's it. -*/ - -#include "sysdeps.h" -#include "cache.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -void cache_clear( cachetype *cptr ) -{ - if(cptr->inited) { - cptr->res_count = 0; - memset( cptr->LRU, 0, NBLOCKS * sizeof(int) ); - } -} - -static int init( cachetype *cptr, int sector_size ) -{ - cache_clear( cptr ); - cptr->sector_size = sector_size; - cptr->blocks = (char *)VirtualAlloc( - NULL, NBLOCKS*sector_size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); - cptr->block = (int *)VirtualAlloc( - NULL, NBLOCKS*sizeof(int), - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); - cptr->LRU = (DWORD *)VirtualAlloc( - NULL, NBLOCKS*sizeof(DWORD), - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); - return(cptr->blocks != NULL); -} - -static void final( cachetype *cptr ) -{ - if(cptr->blocks) { - VirtualFree( cptr->blocks, 0, MEM_RELEASE ); - cptr->blocks = 0; - } - if(cptr->block) { - VirtualFree( cptr->block, 0, MEM_RELEASE ); - cptr->block = 0; - } - if(cptr->LRU) { - VirtualFree( cptr->LRU, 0, MEM_RELEASE ); - cptr->LRU = 0; - } - cptr->inited = 0; -} - -void cache_init( cachetype *cptr ) -{ - cptr->inited = 0; -} - -void cache_final( cachetype *cptr ) -{ - if(cptr->inited) { - final( cptr ); - cptr->inited = 0; - } -} - -static int in_cache( cachetype *cptr, int block ) -{ - int i; - for(i=cptr->res_count-1; i>=0; i--) { - if(cptr->block[i] == block) return(i); - } - return(-1); -} - -static int get_LRU( cachetype *cptr ) -{ - int i, result = 0; - DWORD mtime = cptr->LRU[0]; - - for(i=1; iLRU[i] < mtime) { - mtime = cptr->LRU[i]; - result = i; - } - } - return(result); -} - -void cache_put( cachetype *cptr, int block, char *buf, int ss ) -{ - int inx; - - if(!cptr->inited) { - if(!init(cptr,ss)) return; - cptr->inited = 1; - } - inx = in_cache( cptr, block ); - if(inx < 0) { - if(cptr->res_count == NBLOCKS) { - inx = get_LRU( cptr ); - } else { - inx = cptr->res_count++; - } - cptr->block[inx] = block; - } - cptr->LRU[inx] = GetTickCount(); - memcpy( cptr->blocks + inx * ss, buf, ss ); -} - -int cache_get( cachetype *cptr, int block, char *buf ) -{ - int inx; - - if(!cptr->inited) return(0); - - inx = in_cache( cptr, block ); - if(inx >= 0) { - memcpy( buf, cptr->blocks + inx * cptr->sector_size, cptr->sector_size ); - return(1); - } else { - return(0); - } -} - -void cache_remove( cachetype *cptr, int block, int ss ) -{ - int inx, from; - - if(!cptr->inited) { - if(!init(cptr,ss)) return; - cptr->inited = 1; - } - inx = in_cache( cptr, block ); - if(inx >= 0) { - if(cptr->res_count > 1) { - from = cptr->res_count-1; - cptr->block[inx] = cptr->block[from]; - cptr->LRU[inx] = cptr->LRU[from]; - memcpy( - cptr->blocks + inx * cptr->sector_size, - cptr->blocks + from * cptr->sector_size, - cptr->sector_size - ); - } - cptr->res_count--; - } -} - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/BasiliskII/src/Windows/cdenable/cache.h b/BasiliskII/src/Windows/cdenable/cache.h deleted file mode 100755 index 14607bef..00000000 --- a/BasiliskII/src/Windows/cdenable/cache.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * cache.cpp - simple floppy/cd cache for Win32 - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _CACHE_H_ -#define _CACHE_H_ -#define NBLOCKS 1000 - -typedef struct { - int inited; - int res_count; - int sector_size; - char *blocks; - int *block; - DWORD *LRU; -} cachetype; - -void cache_init( cachetype *cptr ); -void cache_clear( cachetype *cptr ); -void cache_final( cachetype *cptr ); -int cache_get( cachetype *cptr, int block, char *buf ); -void cache_put( cachetype *cptr, int block, char *buf, int ss ); -void cache_remove( cachetype *cptr, int block, int ss ); -#endif - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/BasiliskII/src/Windows/cdenable/cdenable.h b/BasiliskII/src/Windows/cdenable/cdenable.h deleted file mode 100755 index 26b90242..00000000 --- a/BasiliskII/src/Windows/cdenable/cdenable.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * cdenable.h - cdenable.vxd definitions - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// max read requests, if larger -> STATUS_INVALID_PARAMETER -#define CDENABLE_MAX_TRANSFER_SIZE (0x10000) - - -// A structure representing the instance information associated with -// a particular device -typedef struct _DEVICE_EXTENSION -{ - // not needed. - ULONG StateVariable; -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; - - -// Define the various device type values. Note that values used by Microsoft -// Corporation are in the range 0-32767, and 32768-65535 are reserved for use -// by customers. -#define FILE_DEVICE_CDENABLE 0x00008301 - - -// Target NT version, internal version -#define CDENABLE_CURRENT_VERSION 0x04000100 - - -// Macro definition for defining IOCTL and FSCTL function control codes. Note -// that function codes 0-2047 are reserved for Microsoft Corporation, and -// 2048-4095 are reserved for customers. -#define CDENABLE_IOCTL_READ 0x830 -#define CDENABLE_IOCTL_GET_VERSION 0x831 - - -#define IOCTL_CDENABLE_READ CTL_CODE(FILE_DEVICE_CDENABLE, \ - CDENABLE_IOCTL_READ, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) -#define IOCTL_CDENABLE_GET_VERSION CTL_CODE(FILE_DEVICE_CDENABLE, \ - CDENABLE_IOCTL_GET_VERSION, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) diff --git a/BasiliskII/src/Windows/cdenable/eject_nt.cpp b/BasiliskII/src/Windows/cdenable/eject_nt.cpp deleted file mode 100755 index 414ce4b9..00000000 --- a/BasiliskII/src/Windows/cdenable/eject_nt.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * eject_nt.cpp - cd eject routines for WinNT (derived from MS samples) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include - -// Prototypes - -extern "C" { - -#include "eject_nt.h" - -LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:"); -LPTSTR szRootFormat = TEXT("%c:\\"); -LPTSTR szErrorFormat = TEXT("Error %d: %s\n"); - -void ReportError(LPTSTR szMsg) -{ - // _tprintf(szErrorFormat, GetLastError(), szMsg); -} - -HANDLE OpenVolume(TCHAR cDriveLetter) -{ - HANDLE hVolume; - UINT uDriveType; - TCHAR szVolumeName[8]; - TCHAR szRootName[5]; - DWORD dwAccessFlags; - - wsprintf(szRootName, szRootFormat, cDriveLetter); - - uDriveType = GetDriveType(szRootName); - switch(uDriveType) { - case DRIVE_REMOVABLE: - dwAccessFlags = GENERIC_READ | GENERIC_WRITE; - break; - case DRIVE_CDROM: - dwAccessFlags = GENERIC_READ; - break; - default: - // _tprintf(TEXT("Cannot eject. Drive type is incorrect.\n")); - return INVALID_HANDLE_VALUE; - } - - wsprintf(szVolumeName, szVolumeFormat, cDriveLetter); - - hVolume = CreateFile( szVolumeName, - dwAccessFlags, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL ); - if (hVolume == INVALID_HANDLE_VALUE) - ReportError(TEXT("CreateFile")); - - return hVolume; -} - -BOOL CloseVolume(HANDLE hVolume) -{ - return CloseHandle(hVolume); -} - -#define LOCK_TIMEOUT 1000 // 1 second -#define LOCK_RETRIES 20 - -BOOL LockVolume(HANDLE hVolume) -{ - DWORD dwBytesReturned; - DWORD dwSleepAmount; - int nTryCount; - - dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES; - - // Do this in a loop until a timeout period has expired - for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) { - if (DeviceIoControl(hVolume, - FSCTL_LOCK_VOLUME, - NULL, 0, - NULL, 0, - &dwBytesReturned, - NULL)) - return TRUE; - - Sleep(dwSleepAmount); - } - - return FALSE; -} - -BOOL DismountVolume(HANDLE hVolume) -{ - DWORD dwBytesReturned; - - return DeviceIoControl( hVolume, - FSCTL_DISMOUNT_VOLUME, - NULL, 0, - NULL, 0, - &dwBytesReturned, - NULL); -} - -BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval) -{ - DWORD dwBytesReturned; - PREVENT_MEDIA_REMOVAL PMRBuffer; - - PMRBuffer.PreventMediaRemoval = fPreventRemoval; - - return DeviceIoControl( hVolume, - IOCTL_STORAGE_MEDIA_REMOVAL, - &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL), - NULL, 0, - &dwBytesReturned, - NULL); -} - -BOOL AutoEjectVolume( HANDLE hVolume, BOOL reload ) -{ - DWORD dwBytesReturned; - - return DeviceIoControl( hVolume, - reload ? IOCTL_STORAGE_LOAD_MEDIA : IOCTL_STORAGE_EJECT_MEDIA, - NULL, 0, - NULL, 0, - &dwBytesReturned, - NULL); -} - -BOOL EjectVolume( TCHAR cDriveLetter, BOOL reload ) -{ - HANDLE hVolume; - - BOOL fRemoveSafely = FALSE; - BOOL fAutoEject = FALSE; - - // Open the volume. - hVolume = OpenVolume(cDriveLetter); - if (hVolume == INVALID_HANDLE_VALUE) - return FALSE; - - // Lock and dismount the volume. - if (LockVolume(hVolume) && DismountVolume(hVolume)) { - fRemoveSafely = TRUE; - - // Set prevent removal to false and eject the volume. - if (PreventRemovalOfVolume(hVolume, FALSE) && - AutoEjectVolume(hVolume,reload)) - fAutoEject = TRUE; - } - - // Close the volume so other processes can use the drive. - if (!CloseVolume(hVolume)) - return FALSE; - - /* - if (fAutoEject) - printf("Media in Drive %c has been ejected safely.\n", cDriveLetter); - else { - if (fRemoveSafely) - printf("Media in Drive %c can be safely removed.\n", cDriveLetter); - } - */ - - return TRUE; -} - -} // extern "C" diff --git a/BasiliskII/src/Windows/cdenable/eject_nt.h b/BasiliskII/src/Windows/cdenable/eject_nt.h deleted file mode 100755 index 88272cc6..00000000 --- a/BasiliskII/src/Windows/cdenable/eject_nt.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * eject_nt.cpp - cd eject routines for WinNT (derived from MS samples) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _EJECT_NT_H_ -#define _EJECT_NT_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -BOOL EjectVolume(TCHAR cDriveLetter,BOOL reload); - -HANDLE OpenVolume(TCHAR cDriveLetter); -BOOL LockVolume(HANDLE hVolume); -BOOL DismountVolume(HANDLE hVolume); -BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent); -BOOL AutoEjectVolume(HANDLE hVolume,BOOL reload); -BOOL CloseVolume(HANDLE hVolume); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif //_EJECT_NT_H_ diff --git a/BasiliskII/src/Windows/cdenable/ntcd.cpp b/BasiliskII/src/Windows/cdenable/ntcd.cpp deleted file mode 100755 index acefb13c..00000000 --- a/BasiliskII/src/Windows/cdenable/ntcd.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * ntcd.cpp - Interface to cdenable.sys driver - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -extern "C" { - -#include -#include -#include "ntcd.h" -#include "cdenable.h" - -static LPCTSTR sDriverShort = TEXT("cdenable"); -static LPCTSTR sDriverLong = TEXT("System32\\Drivers\\cdenable.sys"); -static LPCTSTR sCompleteName = TEXT("\\\\.\\cdenable"); - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// Start type must be SERVICE_AUTO_START or lower, in order -// it to start automatically and allow the mechanism work -// for users with no admin rights. -static BOOL InstallDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName, - IN LPCTSTR ServiceExe -) -{ - SC_HANDLE schService; - DWORD err; - - schService = CreateService ( - SchSCManager, // SCManager database - DriverName, // name of service - DriverName, // name to display - SERVICE_ALL_ACCESS, // desired access - SERVICE_KERNEL_DRIVER, // service type - SERVICE_AUTO_START, // SERVICE_DEMAND_START, // start type - SERVICE_ERROR_NORMAL, // error control type - ServiceExe, // service's binary - NULL, // no load ordering group - NULL, // no tag identifier - NULL, // no dependencies - NULL, // LocalSystem account - NULL // no password - ); - - if (schService == NULL) { - err = GetLastError(); - if (err == ERROR_SERVICE_EXISTS) { - return TRUE; - } else { - return FALSE; - } - } - CloseServiceHandle (schService); - return TRUE; -} - -static BOOL RemoveDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName -) -{ - SC_HANDLE schService; - BOOL ret; - - schService = OpenService (SchSCManager, - DriverName, - SERVICE_ALL_ACCESS - ); - if (schService == NULL) return FALSE; - ret = DeleteService (schService); - CloseServiceHandle (schService); - return ret; -} - -static BOOL StartDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName -) { - SC_HANDLE schService; - BOOL ret; - DWORD err; - - schService = OpenService (SchSCManager, - DriverName, - SERVICE_ALL_ACCESS - ); - if (schService == NULL) return FALSE; - ret = StartService (schService, // service identifier - 0, // number of arguments - NULL // pointer to arguments - ); - if(ret == 0) { - err = GetLastError(); - if (err == ERROR_SERVICE_ALREADY_RUNNING) { - ret = TRUE; - } else { - ret = FALSE; - } - } - CloseServiceHandle (schService); - return ret; -} - -static BOOL StopDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName -) -{ - SC_HANDLE schService; - BOOL ret; - SERVICE_STATUS serviceStatus; - - schService = OpenService (SchSCManager, - DriverName, - SERVICE_ALL_ACCESS - ); - if (schService == NULL) return FALSE; - ret = ControlService (schService, - SERVICE_CONTROL_STOP, - &serviceStatus - ); - CloseServiceHandle (schService); - return ret; -} - -static BOOL __cdecl start_driver( void ) -{ - SC_HANDLE schSCManager; - BOOL ret = FALSE; - - schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - if(!schSCManager) return(FALSE); - if(!InstallDriver( schSCManager, sDriverShort, sDriverLong )) { - CloseServiceHandle( schSCManager ); - return(FALSE); - } - ret = StartDriver( schSCManager, sDriverShort ); - if(!ret) { - (void)RemoveDriver( schSCManager, sDriverShort ); - } - CloseServiceHandle( schSCManager ); - return( ret ); -} - -static BOOL __cdecl stop_driver( void ) -{ - SC_HANDLE schSCManager; - BOOL ret = FALSE; - - schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - if(!schSCManager) return(FALSE); - if(StopDriver( schSCManager, sDriverShort )) ret = TRUE; - CloseServiceHandle( schSCManager ); - return( ret ); -} - -static BOOL __cdecl remove_driver( void ) -{ - SC_HANDLE schSCManager; - BOOL ret = FALSE; - - schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - if(!schSCManager) return(FALSE); - if(RemoveDriver( schSCManager, sDriverShort )) ret = TRUE; - CloseServiceHandle( schSCManager ); - return( ret ); -} - - - -// Exported stuff begins - -int CdenableSysReadCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ) -{ - HANDLE hDevice; - int ret; - DWORD nb; - DWORD in_buffer[10]; - DWORD out_buffer[10]; - - ret = 0; - - in_buffer[0] = (DWORD)h; - in_buffer[1] = (DWORD)start; - in_buffer[2] = (DWORD)count; - in_buffer[3] = (DWORD)buf; - out_buffer[0] = 0; - - hDevice = CreateFile (sCompleteName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - if (hDevice == ((HANDLE)-1)) { - ret = 0; - } else { - if ( DeviceIoControl( hDevice, - IOCTL_CDENABLE_READ, - (LPVOID)in_buffer, 16, - (LPVOID)out_buffer, 4, - &nb, NULL ) ) - { - if(out_buffer[0] != 0) ret = count; - } - CloseHandle (hDevice); - } - - return ret; -} - -int CdenableSysReadCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ) -{ - return( CdenableSysReadCdBytes( h, (start<<11), (count<<11), buf ) ); -} - -int CdenableSysWriteCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ) -{ - return( 0 ); - - /* - HANDLE hDevice; - int ret; - DWORD nb; - DWORD in_buffer[10]; - DWORD out_buffer[10]; - - ret = 0; - - in_buffer[0] = (DWORD)h; - in_buffer[1] = (DWORD)start; - in_buffer[2] = (DWORD)count; - in_buffer[3] = (DWORD)buf; - out_buffer[0] = 0; - - hDevice = CreateFile (sCompleteName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - - if (hDevice == ((HANDLE)-1)) { - ret = 0; - } else { - if ( DeviceIoControl( hDevice, - IOCTL_CDENABLE_WRITE, - (LPVOID)in_buffer, 16, - (LPVOID)out_buffer, 4, - &nb, NULL ) ) - { - if(out_buffer[0] != 0) ret = count; - } - CloseHandle (hDevice); - } - - return ret; - */ -} - -int CdenableSysWriteCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ) -{ - // return( CdenableSysWriteCdBytes( h, (start<<11), (count<<11), buf ) ); - return( 0 ); -} - -BOOL CdenableSysInstallStart(void) -{ - return(start_driver()); -} - -void CdenableSysStopRemove(void) -{ - stop_driver(); - remove_driver(); -} - -DWORD CdenableSysGetVersion( void ) -{ - HANDLE hDevice; - DWORD ret; - DWORD nb; - DWORD out_buffer[10]; - - ret = 0; - out_buffer[0] = 0; - hDevice = CreateFile (sCompleteName, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - if (hDevice == ((HANDLE)-1)) { - ret = 0; - } else { - if ( DeviceIoControl( hDevice, - IOCTL_CDENABLE_GET_VERSION, - NULL, 0, - (LPVOID)out_buffer, 4, - &nb, NULL ) ) - { - ret = out_buffer[0]; - } - CloseHandle (hDevice); - } - return ret; -} - -#ifdef __cplusplus -} //extern "C" -#endif - diff --git a/BasiliskII/src/Windows/cdenable/ntcd.h b/BasiliskII/src/Windows/cdenable/ntcd.h deleted file mode 100755 index 8be3193e..00000000 --- a/BasiliskII/src/Windows/cdenable/ntcd.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ntcd.h - Interface to cdenable.sys driver - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* - Installs the driver, if not already installed. - Starts the driver, if not already running. - - You can either always call "CdenableSysInstallStart" when your - program fires up and "CdenableSysStopRemove" when it terminates, - or just let the installation program call "CdenableSysInstallStart" - and leave it always be present. - - I recommend the latter option. Calling "CdenableSysInstallStart" - always doesn't hurt anything, it will immediately return - with success if the service is running. - - Returns non-zero if installation/startup was succesfull, - zero if anything failed. - Returns non-zero also if the driver was already running. - - The file "cdenable.sys" must already have been copied to - the directory "System32\Drivers" -*/ - -#ifndef _NT_CD_H_ -#define _NT_CD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -BOOL CdenableSysInstallStart(void); - - -/* - Stops and removes the driver. See above. - This must be called when new version of the driver is updated. -*/ -void CdenableSysStopRemove(void); - - -/* - HANDLE h: returned from CreateFile ( "\\\\.\\X:", GENERIC_READ, ... ); - Returns the bytes actually read (==count), 0 on failure. - NOTE: in my code, start and count are always aligned to - sector boundaries (2048 bytes). - I cannot guarantee that this works if they are not. - Max read is 64 kb. - Synchronous read, but quite fast. -*/ -int CdenableSysReadCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ); - - -/* - Same as SysReadCdBytes, but "start" and "count" are in 2048 byte - sectors. -*/ -int CdenableSysReadCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ); - - -/* - Ditto for writing stuff. - Not a cd of course but removable & hd media are supported now. -*/ -int CdenableSysWriteCdBytes( HANDLE h, DWORD start, DWORD count, char *buf ); -int CdenableSysWriteCdSectors( HANDLE h, DWORD start, DWORD count, char *buf ); - - -/* - Returns CDENABLE_CURRENT_VERSION (of the driver). -*/ -DWORD CdenableSysGetVersion( void ); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif //_NT_CD_H_ diff --git a/BasiliskII/src/Windows/clip_windows.cpp b/BasiliskII/src/Windows/clip_windows.cpp deleted file mode 100755 index c4ee65bc..00000000 --- a/BasiliskII/src/Windows/clip_windows.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * clip_windows.cpp - Clipboard handling, Windows implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include - -#include "macos_util.h" -#include "clip.h" -#include "prefs.h" -#include "cpu_emulation.h" -#include "main.h" -#include "emul_op.h" - -#define DEBUG 0 -#include "debug.h" - -#ifndef NO_STD_NAMESPACE -using std::vector; -#endif - - -// Conversion tables -static const uint8 mac2iso[0x80] = { - 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, - 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, - 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, - 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, - 0x2b, 0xb0, 0xa2, 0xa3, 0xa7, 0xb7, 0xb6, 0xdf, - 0xae, 0xa9, 0x20, 0xb4, 0xa8, 0x23, 0xc6, 0xd8, - 0x20, 0xb1, 0x3c, 0x3e, 0xa5, 0xb5, 0xf0, 0x53, - 0x50, 0x70, 0x2f, 0xaa, 0xba, 0x4f, 0xe6, 0xf8, - 0xbf, 0xa1, 0xac, 0x2f, 0x66, 0x7e, 0x44, 0xab, - 0xbb, 0x2e, 0x20, 0xc0, 0xc3, 0xd5, 0x4f, 0x6f, - 0x2d, 0x2d, 0x22, 0x22, 0x60, 0x27, 0xf7, 0x20, - 0xff, 0x59, 0x2f, 0xa4, 0x3c, 0x3e, 0x66, 0x66, - 0x23, 0xb7, 0x2c, 0x22, 0x25, 0xc2, 0xca, 0xc1, - 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, - 0x20, 0xd2, 0xda, 0xdb, 0xd9, 0x69, 0x5e, 0x7e, - 0xaf, 0x20, 0xb7, 0xb0, 0xb8, 0x22, 0xb8, 0x20 -}; - -static const uint8 iso2mac[0x80] = { - 0xad, 0xb0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, - 0xf6, 0xe4, 0xde, 0xdc, 0xce, 0xb2, 0xb3, 0xb6, - 0xb7, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, - 0xf7, 0xaa, 0xdf, 0xdd, 0xcf, 0xba, 0xfd, 0xd9, - 0xca, 0xc1, 0xa2, 0xa3, 0xdb, 0xb4, 0xbd, 0xa4, - 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xf0, 0xa8, 0xf8, - 0xa1, 0xb1, 0xc3, 0xc5, 0xab, 0xb5, 0xa6, 0xe1, - 0xfc, 0xc6, 0xbc, 0xc8, 0xf9, 0xda, 0xd7, 0xc0, - 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, - 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, - 0xf5, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xfb, - 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xfa, 0xb8, 0xa7, - 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, - 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, - 0xfe, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, - 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xff, 0xb9, 0xd8 -}; - -// Flag: Don't convert clipboard text -static bool no_clip_conversion; - -// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the Windows side -static bool we_put_this_data = false; - -// Define a byte array (rewrite if it's a bottleneck) -struct ByteArray : public vector { - uint8 *data() { return &(*this)[0]; } -}; - -// Prototypes -static void do_putscrap(uint32 type, void *scrap, int32 length); -static void do_getscrap(void **handle, uint32 type, int32 offset); - -// From main_windows.cpp -extern HWND GetMainWindowHandle(void); - - -/* - * Initialization - */ - -void ClipInit(void) -{ - no_clip_conversion = PrefsFindBool("noclipconversion"); -} - - -/* - * Deinitialization - */ - -void ClipExit(void) -{ -} - - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32 type, void *scrap, int32 length) -{ - D(bug("PutScrap type %08lx, data %p, length %ld\n", type, scrap, length)); - if (we_put_this_data) { - we_put_this_data = false; - return; - } - if (length <= 0) - return; - - do_putscrap(type, scrap, length); -} - -static void do_putscrap(uint32 type, void *scrap, int32 length) -{ - ByteArray clip_data; - UINT uFormat = 0; - - switch (type) { - case FOURCC('T','E','X','T'): { - D(bug(" clipping TEXT\n")); - - // Convert text from Mac charset to ISO-Latin1 - uint8 *p = (uint8 *)scrap; - for (int i=0; i CR/LF - clip_data.push_back(c); - c = 10; - } - } else if (!no_clip_conversion) - c = mac2iso[c & 0x7f]; - clip_data.push_back(c); - } - clip_data.push_back(0); - uFormat = CF_TEXT; - break; - } - } - if (uFormat != CF_TEXT) // 'TEXT' only - return; - - // Transfer data to the native clipboard - HWND hMainWindow = GetMainWindowHandle(); - if (!hMainWindow ||!OpenClipboard(hMainWindow)) - return; - EmptyClipboard(); - HANDLE hData = GlobalAlloc(GMEM_DDESHARE, clip_data.size()); - if (hData) { - uint8 *data = (uint8 *)GlobalLock(hData); - memcpy(data, clip_data.data(), clip_data.size()); - GlobalUnlock(hData); - if (!SetClipboardData(uFormat, hData)) - GlobalFree(hData); - } - CloseClipboard(); -} - -/* - * Mac application zeroes clipboard - */ - -void ZeroScrap() -{ - -} - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32 type, int32 offset) -{ - D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset)); - - do_getscrap(handle, type, offset); -} - -static void do_getscrap(void **handle, uint32 type, int32 offset) -{ - // Get appropriate format for requested data - UINT uFormat = 0; - switch (type) { - case FOURCC('T','E','X','T'): - uFormat = CF_TEXT; - break; - } - if (uFormat != CF_TEXT) // 'TEXT' only - return; - - // Get the native clipboard data - HWND hMainWindow = GetMainWindowHandle(); - if (!hMainWindow || !OpenClipboard(hMainWindow)) - return; - HANDLE hData = GetClipboardData(uFormat); - if (hData) { - uint8 *data = (uint8 *)GlobalLock(hData); - if (data) { - uint32 length = GlobalSize(hData); - if (length) { - int32 out_length = 0; - - // Allocate space for new scrap in MacOS side - M68kRegisters r; - r.d[0] = length; - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32 scrap_area = r.a[0]; - - if (scrap_area) { - switch (type) { - case FOURCC('T','E','X','T'): - D(bug(" clipping TEXT\n")); - - // Convert text from ISO-Latin1 to Mac charset - uint8 *p = Mac2HostAddr(scrap_area); - for (uint32 i = 0; i < length; i++) { - uint8 c = data[i]; - if (c < 0x80) { - if (c == 0) - break; - if (c == 13 && i < length - 1 && data[i + 1] == 10) { // CR/LF -> CR - c = 13; - i++; - } - } else if (!no_clip_conversion) - c = iso2mac[c & 0x7f]; - *p++ = c; - out_length++; - } - break; - } - - // Add new data to clipboard - static uint8 proc[] = { - 0x59, 0x8f, // subq.l #4,sp - 0xa9, 0xfc, // ZeroScrap() - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #length,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #type,-(sp) - 0x2f, 0x3c, 0, 0, 0, 0, // move.l #outbuf,-(sp) - 0xa9, 0xfe, // PutScrap() - 0x58, 0x8f, // addq.l #4,sp - uint8(M68K_RTS >> 8), uint8(M68K_RTS) - }; - uint32 proc_area = Host2MacAddr(proc); - WriteMacInt32(proc_area + 6, out_length); - WriteMacInt32(proc_area + 12, type); - WriteMacInt32(proc_area + 18, scrap_area); - we_put_this_data = true; - Execute68k(proc_area, &r); - - // We are done with scratch memory - r.a[0] = scrap_area; - Execute68kTrap(0xa01f, &r); // DisposePtr - } - } - GlobalUnlock(hData); - } - } - CloseClipboard(); -} diff --git a/BasiliskII/src/Windows/config.h b/BasiliskII/src/Windows/config.h deleted file mode 100644 index 88bd0904..00000000 --- a/BasiliskII/src/Windows/config.h +++ /dev/null @@ -1,260 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if using video enabled on SEGV signals. */ -#ifndef _DEBUG -#define ENABLE_VOSF 1 -#endif - -/* Define to 1 if you have the `acoshl' function. */ -#define HAVE_ACOSHL 1 - -/* Define to 1 if you have the `acosl' function. */ -#define HAVE_ACOSL 1 - -/* Define to 1 if you have the `asinhl' function. */ -#define HAVE_ASINHL 1 - -/* Define to 1 if you have the `asinl' function. */ -#define HAVE_ASINL 1 - -/* Define to 1 if you have the `atanh' function. */ -#define HAVE_ATANH 1 - -/* Define to 1 if you have the `atanhl' function. */ -#define HAVE_ATANHL 1 - -/* Define to 1 if you have the `atanl' function. */ -#define HAVE_ATANL 1 - -/* Define to 1 if the system has the type `caddr_t'. */ -/* #undef HAVE_CADDR_T */ - -/* Define to 1 if you have the `ceill' function. */ -#define HAVE_CEILL 1 - -/* Define to 1 if you have the `coshl' function. */ -#define HAVE_COSHL 1 - -/* Define to 1 if you have the `cosl' function. */ -#define HAVE_COSL 1 - -/* Define to 1 if you have the `expl' function. */ -/* #undef HAVE_EXPL */ - -/* Define to 1 if you have the `fabsl' function. */ -/* #undef HAVE_FABSL */ - -/* Define to 1 if you have the `finite' function. */ -#define HAVE_FINITE 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FLOATINGPOINT_H */ - -/* Define to 1 if you have the `floorl' function. */ -#define HAVE_FLOORL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_IEEE754_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_IEEEFP_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `isinf' function. */ -/* #undef HAVE_ISINF */ - -/* Define to 1 if you have the `isinfl' function. */ -/* #undef HAVE_ISINFL */ - -/* Define to 1 if you have the `isnan' function. */ -#define HAVE_ISNAN 1 - -/* Define to 1 if you have the `isnanl' function. */ -/* #undef HAVE_ISNANL */ - -/* Define to 1 if you have the `isnormal' function. */ -/* #undef HAVE_ISNORMAL */ - -/* Define to 1 if the system has the type `loff_t'. */ -/* #undef HAVE_LOFF_T */ - -/* Define to 1 if you have the `log10l' function. */ -/* #undef HAVE_LOG10L */ - -/* Define to 1 if you have the `logl' function. */ -/* #undef HAVE_LOGL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NAN_H */ - -/* Define to 1 if you have the `powl' function. */ -#define HAVE_POWL 1 - -/* Define to 1 if you have the `signbit' function. */ -/* #undef HAVE_SIGNBIT */ - -/* Define if we can ignore the fault (instruction skipping in SIGSEGV - handler). */ -#define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - -/* Define to 1 if you have the `sinhl' function. */ -#define HAVE_SINHL 1 - -/* Define to 1 if you have the `sinl' function. */ -#define HAVE_SINL 1 - -/* Define to 1 if you have the `sqrtl' function. */ -#define HAVE_SQRTL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the `tanhl' function. */ -#define HAVE_TANHL 1 - -/* Define to 1 if you have the `tanl' function. */ -#define HAVE_TANL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define if your system supports Windows exceptions. */ -#define HAVE_WIN32_EXCEPTIONS 1 - -/* Define if your system has a working Win32-based memory allocator. */ -#define HAVE_WIN32_VM 1 - -/* Define to the floating point format of the host machine. */ -#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* Define to 1 if the host machine stores floating point numbers in memory - with the word containing the sign bit at the lowest address, or to 0 if it - does it the other way around. This macro should not be defined if the - ordering is the same as for multi-word integers. */ -/* #undef HOST_FLOAT_WORDS_BIG_ENDIAN */ - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Define this program name. */ -#define PACKAGE "Basilisk II" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "Christian.Bauer@uni-mainz.de" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "Basilisk II" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Basilisk II 1.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "BasiliskII" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.0" - -/* The size of `double', as computed by sizeof. */ -#define SIZEOF_DOUBLE 8 - -/* The size of `float', as computed by sizeof. */ -#define SIZEOF_FLOAT 4 - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `long double', as computed by sizeof. */ -#define SIZEOF_LONG_DOUBLE 8 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* The size of `void *', as computed by sizeof. */ -#define SIZEOF_VOID_P 4 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to enble SDL support */ -#define USE_SDL 1 - -/* Define to enable SDL audio support */ -#define USE_SDL_AUDIO 1 - -/* Define to enable SDL video graphics support */ -#define USE_SDL_VIDEO 1 - -/* Define this program version. */ -#define VERSION "1.0" - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ diff --git a/BasiliskII/src/Windows/configure.ac b/BasiliskII/src/Windows/configure.ac deleted file mode 100755 index fc902704..00000000 --- a/BasiliskII/src/Windows/configure.ac +++ /dev/null @@ -1,569 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -dnl Written in 2002 by Christian Bauer et al. - -AC_INIT([Basilisk II], 1.0, [Christian.Bauer@uni-mainz.de], BasiliskII) -AC_CONFIG_SRCDIR(main_windows.cpp) -AC_CONFIG_AUX_DIR(../Unix) -AC_PREREQ(2.52) -AC_CONFIG_HEADER(config.h) - -dnl Aliases for PACKAGE and VERSION macros. -AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE_NAME", [Define this program name.]) -AC_DEFINE_UNQUOTED(VERSION, "$PACKAGE_VERSION", [Define this program version.]) - -dnl SDL options. -AC_ARG_ENABLE(sdl-static, [ --enable-sdl-static use SDL static libraries for linking [default=no]], [WANT_SDL_STATIC=$enableval], [WANT_SDL_STATIC=no]) - -dnl JIT compiler options. -AC_ARG_ENABLE(jit-compiler, [ --enable-jit-compiler enable JIT compiler [default=yes]], [WANT_JIT=$enableval], [WANT_JIT=yes]) -AC_ARG_ENABLE(jit-debug, [ --enable-jit-debug activate native code disassemblers [default=no]], [WANT_JIT_DEBUG=$enableval], [WANT_JIT_DEBUG=no]) - -dnl FPU emulation core. -AC_ARG_ENABLE(fpe, -[ --enable-fpe=FPE specify which fpu emulator to use [default=auto]], -[ case "$enableval" in - dnl default is always ieee, if architecture has this fp format - auto) FPE_CORE_TEST_ORDER="ieee uae";; - ieee) FPE_CORE_TEST_ORDER="ieee";; - uae) FPE_CORE_TEST_ORDER="uae";; - x86) FPE_CORE_TEST_ORDER="x86";; - *) AC_MSG_ERROR([--enable-fpe takes only one of the following values: auto, x86, ieee, uae]);; - esac -], -[ FPE_CORE_TEST_ORDER="ieee uae" -]) - -dnl External packages. -AC_ARG_WITH(gtk, [ --with-gtk use GTK user interface [default=yes]], [WANT_GTK=$withval], [WANT_GTK=yes]) - -dnl Addressing modes. -AC_ARG_ENABLE(addressing, -[ --enable-addressing=AM specify the addressing mode to use [default=fastest]], -[ case "$enableval" in - direct) ADDRESSING_TEST_ORDER="direct";; - banks) ADDRESSING_TEST_ORDER="banks";; - fastest)ADDRESSING_TEST_ORDER="direct banks";; - *) AC_MSG_ERROR([--enable-addressing takes only one of the following values: fastest, direct, banks]);; - esac -], -[ ADDRESSING_TEST_ORDER="direct banks" -]) - -dnl Canonical system information. -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -dnl Target CPU type. -HAVE_I386=no -HAVE_POWERPC=no -HAVE_X86_64=no -case "$target_cpu" in - i386* | i486* | i586* | i686* | i786* ) HAVE_I386=yes;; - powerpc* ) HAVE_POWERPC=yes;; - x86_64* ) HAVE_X86_64=yes;; -esac - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CC_C_O -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_MAKE_SET -AC_PROG_EGREP -AC_PROG_LN_S -AC_CHECK_TOOL(WINDRES, windres) - -dnl We use GTK+ if possible. -if [[ "x$WANT_GTK" = "xyes" ]]; then - AM_PATH_GTK_2_0(1.3.15, [], [ - AC_MSG_WARN([Could not find GTK+ 2.0, disabling user interface.]) - WANT_GTK=no - ]) -fi -AC_SUBST(WANT_GTK) - -dnl We use 64-bit file size support if possible. -AC_SYS_LARGEFILE - -dnl Checks for header files. -AC_HEADER_STDC - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_BIGENDIAN -AC_C_CONST -AC_C_INLINE -AC_CHECK_SIZEOF(short, 2) -AC_CHECK_SIZEOF(int, 4) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_SIZEOF(long long, 8) -AC_CHECK_SIZEOF(float, 4) -AC_CHECK_SIZEOF(double, 8) -AC_CHECK_SIZEOF(long double, 12) -AC_CHECK_SIZEOF(void *, 4) -AC_TYPE_OFF_T -AC_CHECK_TYPES(loff_t) -AC_CHECK_TYPES(caddr_t) -AC_TYPE_SIZE_T - -dnl Checks for library functions. -AC_CHECK_FUNCS(strdup strerror) - -dnl Define a macro that translates a yesno-variable into a C macro definition -dnl to be put into the config.h file -dnl $1 -- the macro to define -dnl $2 -- the value to translate -dnl $3 -- template name -AC_DEFUN([AC_TRANSLATE_DEFINE], [ - if [[ "x$2" = "xyes" -o "x$2" = "xguessing yes" ]]; then - AC_DEFINE($1, 1, $3) - fi -]) - -dnl Check that VirtualAlloc(), VirtualProtect() work -AC_CACHE_CHECK([whether VirtualProtect works], - ac_cv_VirtualProtect_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_cv_VirtualProtect_works=yes - dnl First the tests that should segfault - for test_def in NONE_READ NONE_WRITE READ_WRITE; do - AC_TRY_RUN([ - #define HAVE_WIN32_VM 1 - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_$test_def - #include "../Unix/vm_alloc.cpp" - ], ac_cv_VirtualProtect_works=no, rm -f core, - dnl When cross-compiling, assume it works - ac_cv_VirtualProtect_works="yes" - ) - done - AC_TRY_RUN([ - #define HAVE_WIN32_VM 1 - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_RDWR_WRITE - #include "../Unix/vm_alloc.cpp" - ], , ac_cv_VirtualProtect_works=no, - dnl When cross-compiling, assume it works - ac_cv_VirtualProtect_works="yes" - ) - AC_LANG_RESTORE - ] -) -if [[ "x$ac_cv_VirtualProtect_works" = "xyes" ]]; then - AC_DEFINE(HAVE_WIN32_VM, 1, [Define if your system has a working Win32-based memory allocator.]) -else - AC_MSG_ERROR([Sorry, Windows VM functions don't work as expected on your system.]) -fi - -dnl Check if Windows exceptions are supported. -AC_CACHE_CHECK([whether your system supports Windows exceptions], - ac_cv_have_win32_exceptions, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_WIN32_EXCEPTIONS 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../Unix/vm_alloc.cpp" - #include "../Unix/sigsegv.cpp" - ], - ac_cv_have_win32_exceptions=yes, - ac_cv_have_win32_exceptions=no, - dnl When cross-compiling, assume it works - ac_cv_have_win32_exceptions="yes" - ) - AC_LANG_RESTORE - ] -) -if [[ "x$ac_cv_have_win32_exceptions" = "xyes" ]]; then - AC_DEFINE(HAVE_WIN32_EXCEPTIONS, 1, [Define if your system supports Windows exceptions.]) -else - AC_MSG_ERROR([Sorry, Windows exceptions don't work as expected on your system.]) -fi - -dnl Check if we can ignore the fault (instruction skipping in SIGSEGV handler) -AC_CACHE_CHECK([whether we can skip instruction in SIGSEGV handler], - ac_cv_have_skip_instruction, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../Unix/vm_alloc.cpp" - #include "../Unix/sigsegv.cpp" - ], ac_cv_have_skip_instruction=yes, ac_cv_have_skip_instruction=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_skip_instruction=no - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_SIGSEGV_SKIP_INSTRUCTION, "$ac_cv_have_skip_instruction", - [Define if we can ignore the fault (instruction skipping in SIGSEGV handler).]) - -dnl We really want VOSF (Video on SEGV Signals) screen updates acceleration -AC_DEFINE(ENABLE_VOSF, 1, [Define if using video enabled on SEGV signals.]) - -dnl Determine the addressing mode to use -ADDRESSING_MODE="" -AC_MSG_CHECKING([for the addressing mode to use]) -for am in $ADDRESSING_TEST_ORDER; do - case $am in - direct) - dnl Direct addressing mode (constant offset) - ADDRESSING_MODE="direct" - DEFINES="$DEFINES -DDIRECT_ADDRESSING" - break - ;; - banks) - dnl Default addressing mode - ADDRESSING_MODE="memory banks" - break - ;; - *) - AC_MSG_ERROR([Internal configure.ac script error for $am addressing mode]) - esac -done -AC_MSG_RESULT($ADDRESSING_MODE) -if [[ "x$ADDRESSING_MODE" = "x" ]]; then - AC_MSG_WARN([Sorry, no suitable addressing mode in $ADDRESSING_TEST_ORDER]) - ADDRESSING_MODE="memory banks" -fi - -dnl Banked Memory Addressing mode is not supported by the JIT compiler -if [[ "x$WANT_JIT" = "xyes" -a "x$ADDRESSING_MODE" = "xmemory banks" ]]; then - AC_MSG_ERROR([Sorry, the JIT Compiler requires Direct Addressing, at least]) -fi - -dnl Check for GAS. -HAVE_GAS=no -AC_MSG_CHECKING(for GAS .p2align feature) -cat >conftest.S << EOF - .text - .p2align 5 -EOF -if $CC conftest.S -c -o conftest.o >/dev/null 2>&1 ; then HAVE_GAS=yes; fi -AC_MSG_RESULT($HAVE_GAS) - -dnl Check for GCC 2.7 or higher. -HAVE_GCC27=no -AC_MSG_CHECKING(for GCC 2.7 or higher) -AC_EGREP_CPP(xyes, -[#if __GNUC__ - 1 > 1 || __GNUC_MINOR__ - 1 > 5 - xyes -#endif -], [AC_MSG_RESULT(yes); HAVE_GCC27=yes], AC_MSG_RESULT(no)) - -dnl Check for GCC 3.0 or higher. -HAVE_GCC30=no -AC_MSG_CHECKING(for GCC 3.0 or higher) -AC_EGREP_CPP(xyes, -[#if __GNUC__ >= 3 - xyes -#endif -], [AC_MSG_RESULT(yes); HAVE_GCC30=yes], AC_MSG_RESULT(no)) - -dnl Add -fno-strict-aliasing for slirp sources -if [[ "x$HAVE_GCC30" = "xyes" ]]; then - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-strict-aliasing" - AC_CACHE_CHECK([whether the compiler supports -fno-strict-aliasing], - ac_cv_gcc_no_strict_aliasing, [ - AC_TRY_COMPILE([],[], - [ac_cv_gcc_no_strict_aliasing=yes; AC_SUBST(SLIRP_CFLAGS, "-fno-strict-aliasing")], - [ac_cv_gcc_no_strict_aliasing=no]) - ]) - CFLAGS="$SAVED_CFLAGS" -fi - -dnl Select appropriate CPU source and REGPARAM define. -ASM_OPTIMIZATIONS=none -CPUSRCS="cpuemu1.cpp cpuemu2.cpp cpuemu3.cpp cpuemu4.cpp cpuemu5.cpp cpuemu6.cpp cpuemu7.cpp cpuemu8.cpp" - -dnl JITSRCS will be emptied later if the JIT is not available -dnl Other platforms should define their own set of noflags file variants -CAN_JIT=no -JITSRCS="compemu1.cpp compemu2.cpp compemu3.cpp compemu4.cpp compemu5.cpp compemu6.cpp compemu7.cpp compemu8.cpp" - -if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_I386" = "xyes" ]]; then - dnl i386 CPU - DEFINES="$DEFINES -DUNALIGNED_PROFITABLE -DREGPARAM=\"__attribute__((regparm(3)))\"" - if [[ "x$HAVE_GAS" = "xyes" ]]; then - ASM_OPTIMIZATIONS=i386 - DEFINES="$DEFINES -DX86_ASSEMBLY -DOPTIMIZED_FLAGS -DSAHF_SETO_PROFITABLE" - JITSRCS="cpuemu1_nf.cpp cpuemu2_nf.cpp cpuemu3_nf.cpp cpuemu4_nf.cpp cpuemu5_nf.cpp cpuemu6_nf.cpp cpuemu7_nf.cpp cpuemu8_nf.cpp $JITSRCS" - CAN_JIT=yes - fi -elif [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_X86_64" = "xyes" ]]; then - dnl x86-64 CPU - DEFINES="$DEFINES -DUNALIGNED_PROFITABLE" - if [[ "x$HAVE_GAS" = "xyes" ]]; then - ASM_OPTIMIZATIONS="x86-64" - DEFINES="$DEFINES -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS" - JITSRCS="cpuemu1_nf.cpp cpuemu2_nf.cpp cpuemu3_nf.cpp cpuemu4_nf.cpp cpuemu5_nf.cpp cpuemu6_nf.cpp cpuemu7_nf.cpp cpuemu8_nf.cpp $JITSRCS" - CAN_JIT=yes - fi -fi - -dnl Enable JIT compiler, if possible. -if [[ "x$WANT_JIT" = "xyes" -a "x$CAN_JIT" ]]; then - JITSRCS="$JITSRCS ../uae_cpu/compiler/compemu_support.cpp ../uae_cpu/compiler/compemu_fpp.cpp compstbl.o cpustbl_nf.o" - DEFINES="$DEFINES -DUSE_JIT -DUSE_JIT_FPU" - - if [[ "x$WANT_JIT_DEBUG" = "xyes" ]]; then - if [[ "x$WANT_MON" = "xyes" ]]; then - DEFINES="$DEFINES -DJIT_DEBUG=1" - else - AC_MSG_WARN([cxmon not found, ignoring --enable-jit-debug]) - WANT_JIT_DEBUG=no - fi - fi - - dnl IEEE core is the only FPU emulator to use with the JIT compiler - case $FPE_CORE_TEST_ORDER in - ieee*) ;; - *) AC_MSG_WARN([Forcing use of the IEEE FPU core, as the JIT compiler supports only this one.]) ;; - esac - FPE_CORE_TEST_ORDER="ieee" -else - WANT_JIT=no - WANT_JIT_DEBUG=no - JITSRCS="" -fi - -dnl Utility macro used by next two tests. -dnl AC_EXAMINE_OBJECT(C source code, -dnl commands examining object file, -dnl [commands to run if compile failed]): -dnl -dnl Compile the source code to an object file; then convert it into a -dnl printable representation. All unprintable characters and -dnl asterisks (*) are replaced by dots (.). All white space is -dnl deleted. Newlines (ASCII 0x10) in the input are preserved in the -dnl output, but runs of newlines are compressed to a single newline. -dnl Finally, line breaks are forcibly inserted so that no line is -dnl longer than 80 columns and the file ends with a newline. The -dnl result of all this processing is in the file conftest.dmp, which -dnl may be examined by the commands in the second argument. -dnl -AC_DEFUN([gcc_AC_EXAMINE_OBJECT], -[AC_LANG_SAVE -AC_LANG_C -dnl Next bit cribbed from AC_TRY_COMPILE. -cat > conftest.$ac_ext < conftest.dmp - $2 -ifelse($3, , , else - $3 -)dnl -fi -rm -rf conftest* -AC_LANG_RESTORE]) - -dnl Floating point format probe. -dnl The basic concept is the same as the above: grep the object -dnl file for an interesting string. We have to watch out for -dnl rounding changing the values in the object, however; this is -dnl handled by ignoring the least significant byte of the float. -dnl -dnl Does not know about VAX G-float or C4x idiosyncratic format. -dnl It does know about PDP-10 idiosyncratic format, but this is -dnl not presently supported by GCC. S/390 "binary floating point" -dnl is in fact IEEE (but maybe we should have that in EBCDIC as well -dnl as ASCII?) -dnl -AC_DEFUN([gcc_AC_C_FLOAT_FORMAT], -[AC_CACHE_CHECK(floating point format, ac_cv_c_float_format, -[gcc_AC_EXAMINE_OBJECT( -[/* This will not work unless sizeof(double) == 8. */ -extern char sizeof_double_must_be_8 [sizeof(double) == 8 ? 1 : -1]; - -/* This structure must have no internal padding. */ -struct possibility { - char prefix[8]; - double candidate; - char postfix[8]; -}; - -#define C(cand) { "\nformat:", cand, ":tamrof\n" } -struct possibility table [] = -{ - C( 3.25724264705901305206e+01), /* @@IEEEFP - IEEE 754 */ - C( 3.53802595280598432000e+18), /* D__float - VAX */ - C( 5.32201830133125317057e-19), /* D.PDP-10 - PDP-10 - the dot is 0x13a */ - C( 1.77977764695171661377e+10), /* IBMHEXFP - s/390 format, ascii */ - C(-5.22995989424860458374e+10) /* IBMHEXFP - s/390 format, EBCDIC */ -};], - [if grep 'format:.@IEEEF.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (big-endian)' - elif grep 'format:.I@@PFE.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (big-endian)' - elif grep 'format:.FEEEI@.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (little-endian)' - elif grep 'format:.EFP@@I.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (little-endian)' - elif grep 'format:.__floa.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='VAX D-float' - elif grep 'format:..PDP-1.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='PDP-10' - elif grep 'format:.BMHEXF.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IBM 370 hex' - else - AC_MSG_ERROR(Unknown floating point format) - fi], - [AC_MSG_ERROR(compile failed)]) -]) -# IEEE is the default format. If the float endianness isn't the same -# as the integer endianness, we have to set FLOAT_WORDS_BIG_ENDIAN -# (which is a tristate: yes, no, default). This is only an issue with -# IEEE; the other formats are only supported by a few machines each, -# all with the same endianness. -format=IEEE_FLOAT_FORMAT -fbigend= -case $ac_cv_c_float_format in - 'IEEE (big-endian)' ) - if test $ac_cv_c_bigendian = no; then - fbigend=1 - fi - ;; - 'IEEE (little-endian)' ) - if test $ac_cv_c_bigendian = yes; then - fbigend=0 - fi - ;; - 'VAX D-float' ) - format=VAX_FLOAT_FORMAT - ;; - 'PDP-10' ) - format=PDP10_FLOAT_FORMAT - ;; - 'IBM 370 hex' ) - format=IBM_FLOAT_FORMAT - ;; -esac -AC_DEFINE_UNQUOTED(HOST_FLOAT_FORMAT, $format, - [Define to the floating point format of the host machine.]) -if test -n "$fbigend"; then - AC_DEFINE_UNQUOTED(HOST_FLOAT_WORDS_BIG_ENDIAN, $fbigend, - [Define to 1 if the host machine stores floating point numbers in - memory with the word containing the sign bit at the lowest address, - or to 0 if it does it the other way around. - - This macro should not be defined if the ordering is the same as for - multi-word integers.]) -fi -]) - -dnl Select appropriate FPU source. -gcc_AC_C_FLOAT_FORMAT -AC_CHECK_HEADERS(ieee754.h ieeefp.h floatingpoint.h nan.h) - -for fpe in $FPE_CORE_TEST_ORDER; do - case $fpe in - ieee) - case $ac_cv_c_float_format in - IEEE*) - FPE_CORE="IEEE fpu core" - DEFINES="$DEFINES -DFPU_IEEE" - FPUSRCS="../uae_cpu/fpu/fpu_ieee.cpp" - dnl Math functions not mandated by C99 standard - AC_CHECK_FUNCS(isnanl isinfl) - dnl Math functions required by C99 standard, but probably not - dnl implemented everywhere. In that case, we fall back to the - dnl regular variant for doubles. - AC_CHECK_FUNCS(logl log10l expl powl fabsl sqrtl) - AC_CHECK_FUNCS(sinl cosl tanl sinhl coshl tanhl) - AC_CHECK_FUNCS(asinl acosl atanl asinhl acoshl atanhl) - AC_CHECK_FUNCS(floorl ceill) - break - ;; - esac - ;; - x86) - if [[ ":$HAVE_GCC27:$HAVE_I386:$HAVE_GAS:" = ":yes:yes:yes:" ]]; then - FPE_CORE="i387 fpu core" - DEFINES="$DEFINES -DFPU_X86" - FPUSRCS="../uae_cpu/fpu/fpu_x86.cpp" - break - fi - ;; - uae) - FPE_CORE="uae fpu core" - DEFINES="$DEFINES -DFPU_UAE" - FPUSRCS="../uae_cpu/fpu/fpu_uae.cpp" - break - ;; - *) - AC_MSG_ERROR([Internal configure.in script error for $fpe fpu core]) - ;; - esac -done -if [[ "x$FPE_CORE" = "x" ]]; then - AC_MSG_ERROR([Sorry, no suitable FPU core found in $FPE_CORE_TEST_ORDER]) -fi - -dnl Check for certain math functions -AC_CHECK_FUNCS(atanh) -AC_CHECK_FUNCS(isnan isinf finite isnormal signbit) - -dnl UAE CPU sources for all non-m68k-native architectures. -CPUINCLUDES="-I../uae_cpu" -CPUSRCS="../uae_cpu/basilisk_glue.cpp ../uae_cpu/memory.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp $FPUSRCS cpustbl.cpp cpudefs.cpp $CPUSRCS $JITSRCS" - -dnl We really want SDL for now -AC_CHECK_TOOL(sdl_config, sdl-config, [AC_MSG_ERROR([Sorry, you currently need SDL for this port])]) -SDL_CFLAGS=`$sdl_config --cflags` -AC_SUBST(SDL_CFLAGS) -if [[ "x$WANT_SDL_STATIC" = "xyes" ]]; then - SDL_LIBS=`$sdl_config --static-libs` - sdl_prefix=`$sdl_config --exec-prefix` - if [[ -n "$sdl_prefix" ]]; then - SDL_LIBS=`echo "$SDL_LIBS" | sed -e "s,-l\(SDLmain\|SDL\),$sdl_prefix/lib/lib\1.a,g"` - fi - SDL_LIBS="$SDL_LIBS -lwinmm" -else - SDL_LIBS=`$sdl_config --libs` -fi -AC_SUBST(SDL_LIBS) -AC_DEFINE(USE_SDL, 1, [Define to enble SDL support]) -AC_DEFINE(USE_SDL_VIDEO, 1, [Define to enable SDL video graphics support]) -AC_DEFINE(USE_SDL_AUDIO, 1, [Define to enable SDL audio support]) - -dnl Remove the "-g" option if set for GCC. -if [[ "x$HAVE_GCC27" = "xyes" ]]; then - CFLAGS=`echo $CFLAGS | sed -e 's/-g\b//g'` - CXXFLAGS=`echo $CXXFLAGS | sed -e 's/-g\b//g'` -fi - -dnl Generate Makefile. -AC_SUBST(DEFINES) -AC_SUBST(CPUINCLUDES) -AC_SUBST(CPUSRCS) -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT - -dnl Print summary. -echo -echo Basilisk II configuration summary: -echo -echo Use JIT compiler ....................... : $WANT_JIT -echo JIT debug mode ......................... : $WANT_JIT_DEBUG -echo Floating-Point emulation core .......... : $FPE_CORE -echo Assembly optimizations ................. : $ASM_OPTIMIZATIONS -echo Addressing mode ........................ : $ADDRESSING_MODE -echo GTK user interface ..................... : $WANT_GTK -echo -echo "Configuration done. Now type \"make\" (or \"gmake\")." diff --git a/BasiliskII/src/Windows/ether_windows.cpp b/BasiliskII/src/Windows/ether_windows.cpp deleted file mode 100755 index 1f59d830..00000000 --- a/BasiliskII/src/Windows/ether_windows.cpp +++ /dev/null @@ -1,1609 +0,0 @@ -/* - * ether_windows.cpp - Ethernet device driver - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "macos_util.h" -#include "prefs.h" -#include "user_strings.h" -#include "ether.h" -#include "ether_defs.h" -#include "b2ether/multiopt.h" -#include "b2ether/inc/b2ether_hl.h" -#include "ether_windows.h" -#include "router/router.h" -#include "util_windows.h" -#include "libslirp.h" - -// Define to let the slirp library determine the right timeout for select() -#define USE_SLIRP_TIMEOUT 1 - - -#define DEBUG 0 -#define MONITOR 0 - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -// Ethernet device types -enum { - NET_IF_B2ETHER, - NET_IF_ROUTER, - NET_IF_SLIRP, - NET_IF_TAP, - NET_IF_FAKE, -}; - -// TAP-Win32 constants -#define TAP_VERSION_MIN_MAJOR 7 -#define TAP_VERSION_MIN_MINOR 1 - -#define TAP_CONTROL_CODE(request, method) \ - CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) - -#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) -#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) -#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) -#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) -#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) -#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) -#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) -#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) -#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) - -#define OLD_TAP_CONTROL_CODE(request, method) \ - CTL_CODE (FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS) - -#define OLD_TAP_IOCTL_GET_VERSION OLD_TAP_CONTROL_CODE (3, METHOD_BUFFERED) - -// Options -bool ether_use_permanent = true; -static int16 ether_multi_mode = ETHER_MULTICAST_MAC; - -// Global variables -HANDLE ether_th; -unsigned int ether_tid; -HANDLE ether_th1; -HANDLE ether_th2; -static int net_if_type = -1; // Ethernet device type -#ifdef SHEEPSHAVER -static bool net_open = false; // Flag: initialization succeeded, network device open -uint8 ether_addr[6]; // Our Ethernet address -#endif - -// These are protected by queue_csection -// Controls transfer for read thread to feed thread -static CRITICAL_SECTION queue_csection; -typedef struct _win_queue_t { - uint8 *buf; - int sz; -} win_queue_t; -#define MAX_QUEUE_ITEMS 1024 -static win_queue_t queue[MAX_QUEUE_ITEMS]; -static int queue_head = 0; -static int queue_inx = 0; -static bool wait_request = true; - - - -// Read thread protected packet pool -static CRITICAL_SECTION fetch_csection; -// Some people use pools as large as 64. -#define PACKET_POOL_COUNT 10 -static LPPACKET packets[PACKET_POOL_COUNT]; -static bool wait_request2 = false; - - - -// Write thread packet queue -static CRITICAL_SECTION send_csection; -static LPPACKET send_queue = 0; - - -// Write thread free packet pool -static CRITICAL_SECTION wpool_csection; -static LPPACKET write_packet_pool = 0; - - - -// Try to deal with echos. Protected by fetch_csection. -// The code should be moved to the driver. No need to lift -// the echo packets to the application level. -// MAX_ECHO must be a power of two. -#define MAX_ECHO (1<<2) -static int echo_count = 0; -typedef uint8 echo_t[1514]; -static echo_t pending_packet[MAX_ECHO]; -static int pending_packet_sz[MAX_ECHO]; - - -// List of attached protocols -struct NetProtocol { - NetProtocol *next; - uint16 type; - uint32 handler; -}; - -static NetProtocol *prot_list = NULL; - - -static LPADAPTER fd = 0; -static bool thread_active = false; -static bool thread_active_1 = false; -static bool thread_active_2 = false; -static bool thread_active_3 = false; -static HANDLE int_ack = 0; -static HANDLE int_sig = 0; -static HANDLE int_sig2 = 0; -static HANDLE int_send_now = 0; - -// Prototypes -static LPADAPTER tap_open_adapter(LPCTSTR dev_name); -static void tap_close_adapter(LPADAPTER fd); -static bool tap_check_version(LPADAPTER fd); -static bool tap_set_status(LPADAPTER fd, ULONG status); -static bool tap_get_mac(LPADAPTER fd, LPBYTE addr); -static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync); -static bool tap_send_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync, BOOLEAN recycle); -static unsigned int WINAPI slirp_receive_func(void *arg); -static unsigned int WINAPI ether_thread_feed_int(void *arg); -static unsigned int WINAPI ether_thread_get_packets_nt(void *arg); -static unsigned int WINAPI ether_thread_write_packets(void *arg); -static void init_queue(void); -static void final_queue(void); -static bool allocate_read_packets(void); -static void free_read_packets(void); -static void free_write_packets(void); -static int16 ether_do_add_multicast(uint8 *addr); -static int16 ether_do_del_multicast(uint8 *addr); -static int16 ether_do_write(uint32 arg); -static void ether_do_interrupt(void); - - -/* - * Find protocol in list - */ - -static NetProtocol *find_protocol(uint16 type) -{ - // All 802.2 types are the same - if (type <= 1500) - type = 0; - - // Search list (we could use hashing here but there are usually only three - // handlers installed: 0x0000 for AppleTalk and 0x0800/0x0806 for TCP/IP) - NetProtocol *p = prot_list; - while (p) { - if (p->type == type) - return p; - p = p->next; - } - return NULL; -} - - -/* - * Initialization - */ - -bool ether_init(void) -{ - TCHAR buf[256]; - - // Do nothing if no Ethernet device specified - const char *name = PrefsFindString("ether"); - if (name == NULL) - return false; - - ether_multi_mode = PrefsFindInt32("ethermulticastmode"); - ether_use_permanent = PrefsFindBool("etherpermanentaddress"); - - // Determine Ethernet device type - net_if_type = -1; - if (PrefsFindBool("routerenabled") || strcmp(name, "router") == 0) - net_if_type = NET_IF_ROUTER; - else if (strcmp(name, "slirp") == 0) - net_if_type = NET_IF_SLIRP; - else if (strcmp(name, "tap") == 0) - net_if_type = NET_IF_TAP; - else - net_if_type = NET_IF_B2ETHER; - - // Initialize NAT-Router - if (net_if_type == NET_IF_ROUTER) { - if (!router_init()) - net_if_type = NET_IF_FAKE; - } - - // Initialize slirp library - if (net_if_type == NET_IF_SLIRP) { - if (slirp_init() < 0) { - WarningAlert(GetString(STR_SLIRP_NO_DNS_FOUND_WARN)); - return false; - } - } - - // Open ethernet device - decltype(tstr(std::declval())) dev_name; - switch (net_if_type) { - case NET_IF_B2ETHER: - dev_name = tstr(PrefsFindString("etherguid")); - if (dev_name == NULL || strcmp(name, "b2ether") != 0) - dev_name = tstr(name); - break; - case NET_IF_TAP: - dev_name = tstr(PrefsFindString("etherguid")); - break; - } - if (net_if_type == NET_IF_B2ETHER) { - if (dev_name == NULL) { - WarningAlert("No ethernet device GUID specified. Ethernet is not available."); - goto open_error; - } - - fd = PacketOpenAdapter( dev_name.get(), ether_multi_mode ); - if (!fd) { - _sntprintf(buf, lengthof(buf), TEXT("Could not open ethernet adapter %s."), dev_name.get()); - WarningAlert(buf); - goto open_error; - } - - // Get Ethernet address - if(!PacketGetMAC(fd,ether_addr,ether_use_permanent)) { - _sntprintf(buf, lengthof(buf), TEXT("Could not get hardware address of device %s. Ethernet is not available."), dev_name.get()); - WarningAlert(buf); - goto open_error; - } - D(bug("Real ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - - const char *ether_fake_address; - ether_fake_address = PrefsFindString("etherfakeaddress"); - if(ether_fake_address && strlen(ether_fake_address) == 12) { - char sm[10]; - strcpy( sm, "0x00" ); - for( int i=0; i<6; i++ ) { - sm[2] = ether_fake_address[i*2]; - sm[3] = ether_fake_address[i*2+1]; - ether_addr[i] = (uint8)strtoul(sm,0,0); - } - D(bug("Fake ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - } - } - else if (net_if_type == NET_IF_TAP) { - if (dev_name == NULL) { - WarningAlert("No ethernet device GUID specified. Ethernet is not available."); - goto open_error; - } - - fd = tap_open_adapter(dev_name.get()); - if (!fd) { - _sntprintf(buf, lengthof(buf), TEXT("Could not open ethernet adapter %s."), dev_name.get()); - WarningAlert(buf); - goto open_error; - } - - if (!tap_check_version(fd)) { - _sntprintf(buf, lengthof(buf), TEXT("Minimal TAP-Win32 version supported is %d.%d."), TAP_VERSION_MIN_MAJOR, TAP_VERSION_MIN_MINOR); - WarningAlert(buf); - goto open_error; - } - - if (!tap_set_status(fd, true)) { - WarningAlert("Could not set media status to connected."); - goto open_error; - } - - if (!tap_get_mac(fd, ether_addr)) { - _sntprintf(buf, lengthof(buf), TEXT("Could not get hardware address of device %s. Ethernet is not available."), dev_name.get()); - WarningAlert(buf); - goto open_error; - } - D(bug("Real ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - - const char *ether_fake_address; - ether_fake_address = PrefsFindString("etherfakeaddress"); - if (ether_fake_address && strlen(ether_fake_address) == 12) { - char sm[10]; - strcpy( sm, "0x00" ); - for( int i=0; i<6; i++ ) { - sm[2] = ether_fake_address[i*2]; - sm[3] = ether_fake_address[i*2+1]; - ether_addr[i] = (uint8)strtoul(sm,0,0); - } - } -#if 1 - /* - If we bridge the underlying ethernet connection and the TAP - device altogether, we have to use a fake address. - */ - else { - ether_addr[0] = 0x52; - ether_addr[1] = 0x54; - ether_addr[2] = 0x00; - } -#endif - D(bug("Fake ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - } - else if (net_if_type == NET_IF_SLIRP) { - ether_addr[0] = 0x52; - ether_addr[1] = 0x54; - ether_addr[2] = 0x00; - ether_addr[3] = 0x12; - ether_addr[4] = 0x34; - ether_addr[5] = 0x56; - D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - } - else { - memcpy( ether_addr, router_mac_addr, 6 ); - D(bug("Fake ethernet address (same as router) %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5])); - } - - // Start packet reception thread - int_ack = CreateSemaphore( 0, 0, 1, NULL); - if(!int_ack) { - WarningAlert("WARNING: Cannot create int_ack semaphore"); - goto open_error; - } - - // nonsignaled - int_sig = CreateSemaphore( 0, 0, 1, NULL); - if(!int_sig) { - WarningAlert("WARNING: Cannot create int_sig semaphore"); - goto open_error; - } - - int_sig2 = CreateSemaphore( 0, 0, 1, NULL); - if(!int_sig2) { - WarningAlert("WARNING: Cannot create int_sig2 semaphore"); - goto open_error; - } - - int_send_now = CreateSemaphore( 0, 0, 1, NULL); - if(!int_send_now) { - WarningAlert("WARNING: Cannot create int_send_now semaphore"); - goto open_error; - } - - init_queue(); - - if(!allocate_read_packets()) goto open_error; - - // No need to enter wait state if we can avoid it. - // These all terminate fast. - - InitializeCriticalSectionAndSpinCount( &fetch_csection, 5000 ); - InitializeCriticalSectionAndSpinCount( &queue_csection, 5000 ); - InitializeCriticalSectionAndSpinCount( &send_csection, 5000 ); - InitializeCriticalSectionAndSpinCount( &wpool_csection, 5000 ); - - ether_th = (HANDLE)_beginthreadex( 0, 0, ether_thread_feed_int, 0, 0, ðer_tid ); - if (!ether_th) { - D(bug("Failed to create ethernet thread\n")); - goto open_error; - } - thread_active = true; - - unsigned int dummy; - unsigned int (WINAPI *receive_func)(void *); - switch (net_if_type) { - case NET_IF_SLIRP: - receive_func = slirp_receive_func; - break; - default: - receive_func = ether_thread_get_packets_nt; - break; - } - ether_th2 = (HANDLE)_beginthreadex( 0, 0, receive_func, 0, 0, &dummy ); - ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy ); - - // Everything OK - return true; - - open_error: - if (thread_active) { - TerminateThread(ether_th,0); - ether_th = 0; - if (int_ack) - CloseHandle(int_ack); - int_ack = 0; - if(int_sig) - CloseHandle(int_sig); - int_sig = 0; - if(int_sig2) - CloseHandle(int_sig2); - int_sig2 = 0; - if(int_send_now) - CloseHandle(int_send_now); - int_send_now = 0; - thread_active = false; - } - if (fd) { - switch (net_if_type) { - case NET_IF_B2ETHER: - PacketCloseAdapter(fd); - break; - case NET_IF_TAP: - tap_close_adapter(fd); - break; - } - fd = 0; - } - return false; -} - - -/* - * Deinitialization - */ - -void ether_exit(void) -{ - D(bug("EtherExit\n")); - - // Stop reception thread - thread_active = false; - - if(int_ack) ReleaseSemaphore(int_ack,1,NULL); - if(int_sig) ReleaseSemaphore(int_sig,1,NULL); - if(int_sig2) ReleaseSemaphore(int_sig2,1,NULL); - if(int_send_now) ReleaseSemaphore(int_send_now,1,NULL); - - D(bug("CancelIO if needed\n")); - if (fd && fd->hFile) - CancelIo(fd->hFile); - - // Wait max 2 secs to shut down pending io. After that, kill them. - D(bug("Wait delay\n")); - for( int i=0; i<10; i++ ) { - if(!thread_active_1 && !thread_active_2 && !thread_active_3) break; - Sleep(200); - } - - if(thread_active_1) { - D(bug("Ether killing ether_th1\n")); - if(ether_th1) TerminateThread(ether_th1,0); - thread_active_1 = false; - } - if(thread_active_2) { - D(bug("Ether killing ether_th2\n")); - if(ether_th2) TerminateThread(ether_th2,0); - thread_active_2 = false; - } - if(thread_active_3) { - D(bug("Ether killing thread\n")); - if(ether_th) TerminateThread(ether_th,0); - thread_active_3 = false; - } - - ether_th1 = 0; - ether_th2 = 0; - ether_th = 0; - - D(bug("Closing semaphores\n")); - if(int_ack) { - CloseHandle(int_ack); - int_ack = 0; - } - if(int_sig) { - CloseHandle(int_sig); - int_sig = 0; - } - if(int_sig2) { - CloseHandle(int_sig2); - int_sig2 = 0; - } - if(int_send_now) { - CloseHandle(int_send_now); - int_send_now = 0; - } - - // Close ethernet device - if (fd) { - switch (net_if_type) { - case NET_IF_B2ETHER: - PacketCloseAdapter(fd); - break; - case NET_IF_TAP: - tap_close_adapter(fd); - break; - } - fd = 0; - } - - // Remove all protocols - D(bug("Removing protocols\n")); - NetProtocol *p = prot_list; - while (p) { - NetProtocol *next = p->next; - delete p; - p = next; - } - prot_list = 0; - - D(bug("Deleting sections\n")); - DeleteCriticalSection( &fetch_csection ); - DeleteCriticalSection( &queue_csection ); - DeleteCriticalSection( &send_csection ); - DeleteCriticalSection( &wpool_csection ); - - D(bug("Freeing read packets\n")); - free_read_packets(); - - D(bug("Freeing write packets\n")); - free_write_packets(); - - D(bug("Finalizing queue\n")); - final_queue(); - - if (net_if_type == NET_IF_ROUTER) { - D(bug("Stopping router\n")); - router_final(); - } - - D(bug("EtherExit done\n")); -} - - -/* - * Glue around low-level implementation - */ - -#ifdef SHEEPSHAVER -// Error codes -enum { - eMultiErr = -91, - eLenErr = -92, - lapProtErr = -94, - excessCollsns = -95 -}; - -// Initialize ethernet -void EtherInit(void) -{ - net_open = false; - - // Do nothing if the user disabled the network - if (PrefsFindBool("nonet")) - return; - - net_open = ether_init(); -} - -// Exit ethernet -void EtherExit(void) -{ - ether_exit(); - net_open = false; -} - -// Get ethernet hardware address -void AO_get_ethernet_address(uint32 arg) -{ - uint8 *addr = Mac2HostAddr(arg); - if (net_open) - OTCopy48BitAddress(ether_addr, addr); - else { - addr[0] = 0x12; - addr[1] = 0x34; - addr[2] = 0x56; - addr[3] = 0x78; - addr[4] = 0x9a; - addr[5] = 0xbc; - } - D(bug("AO_get_ethernet_address: got address %02x%02x%02x%02x%02x%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])); -} - -// Add multicast address -void AO_enable_multicast(uint32 addr) -{ - if (net_open) - ether_do_add_multicast(Mac2HostAddr(addr)); -} - -// Disable multicast address -void AO_disable_multicast(uint32 addr) -{ - if (net_open) - ether_do_del_multicast(Mac2HostAddr(addr)); -} - -// Transmit one packet -void AO_transmit_packet(uint32 mp) -{ - if (net_open) { - switch (ether_do_write(mp)) { - case noErr: - num_tx_packets++; - break; - case excessCollsns: - num_tx_buffer_full++; - break; - } - } -} - -// Copy packet data from message block to linear buffer -static inline int ether_arg_to_buffer(uint32 mp, uint8 *p) -{ - return ether_msgb_to_buffer(mp, p); -} - -// Ethernet interrupt -void EtherIRQ(void) -{ - D(bug("EtherIRQ\n")); - num_ether_irq++; - - OTEnterInterrupt(); - ether_do_interrupt(); - OTLeaveInterrupt(); - - // Acknowledge interrupt to reception thread - D(bug(" EtherIRQ done\n")); - ReleaseSemaphore(int_ack,1,NULL); -} -#else -// Add multicast address -int16 ether_add_multicast(uint32 pb) -{ - return ether_do_add_multicast(Mac2HostAddr(pb + eMultiAddr)); -} - -// Disable multicast address -int16 ether_del_multicast(uint32 pb) -{ - return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr)); -} - -// Transmit one packet -int16 ether_write(uint32 wds) -{ - return ether_do_write(wds); -} - -// Copy packet data from WDS to linear buffer -static inline int ether_arg_to_buffer(uint32 wds, uint8 *p) -{ - return ether_wds_to_buffer(wds, p); -} - -// Dispatch packet to protocol handler -static void ether_dispatch_packet(uint32 packet, uint32 length) -{ - // Get packet type - uint16 type = ReadMacInt16(packet + 12); - - // Look for protocol - NetProtocol *prot = find_protocol(type); - if (prot == NULL) - return; - - // No default handler - if (prot->handler == 0) - return; - - // Copy header to RHA - Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14); - D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12))); - - // Call protocol handler - M68kRegisters r; - r.d[0] = type; // Packet type - r.d[1] = length - 14; // Remaining packet length (without header, for ReadPacket) - r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket) - r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA - r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines - D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4])); - Execute68k(prot->handler, &r); -} - -// Ethernet interrupt -void EtherInterrupt(void) -{ - D(bug("EtherIRQ\n")); - ether_do_interrupt(); - - // Acknowledge interrupt to reception thread - D(bug(" EtherIRQ done\n")); - ReleaseSemaphore(int_ack,1,NULL); -} -#endif - - -/* - * Reset - */ - -void ether_reset(void) -{ - D(bug("EtherReset\n")); - - // Remove all protocols - NetProtocol *p = prot_list; - while (p) { - NetProtocol *next = p->next; - delete p; - p = next; - } - prot_list = NULL; -} - - -/* - * Add multicast address - */ - -static int16 ether_do_add_multicast(uint8 *addr) -{ - D(bug("ether_add_multicast\n")); - - // We wouldn't need to do this - // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; - - switch (net_if_type) { - case NET_IF_B2ETHER: - if (!PacketAddMulticast( fd, addr)) { - D(bug("WARNING: couldn't enable multicast address\n")); - return eMultiErr; - } - default: - D(bug("ether_add_multicast: noErr\n")); - return noErr; - } -} - - -/* - * Delete multicast address - */ - -int16 ether_do_del_multicast(uint8 *addr) -{ - D(bug("ether_del_multicast\n")); - - // We wouldn't need to do this - // if(ether_multi_mode != ETHER_MULTICAST_MAC) return noErr; - - switch (net_if_type) { - case NET_IF_B2ETHER: - if (!PacketDelMulticast( fd, addr)) { - D(bug("WARNING: couldn't disable multicast address\n")); - return eMultiErr; - } - default: - return noErr; - } -} - - -/* - * Attach protocol handler - */ - -int16 ether_attach_ph(uint16 type, uint32 handler) -{ - D(bug("ether_attach_ph type=0x%x, handler=0x%x\n",(int)type,handler)); - - // Already attached? - NetProtocol *p = find_protocol(type); - if (p != NULL) { - D(bug("ether_attach_ph: lapProtErr\n")); - return lapProtErr; - } else { - // No, create and attach - p = new NetProtocol; - p->next = prot_list; - p->type = type; - p->handler = handler; - prot_list = p; - D(bug("ether_attach_ph: noErr\n")); - return noErr; - } -} - - -/* - * Detach protocol handler - */ - -int16 ether_detach_ph(uint16 type) -{ - D(bug("ether_detach_ph type=%08lx\n",(int)type)); - - NetProtocol *p = find_protocol(type); - if (p != NULL) { - NetProtocol *previous = 0; - NetProtocol *q = prot_list; - while(q) { - if (q == p) { - if(previous) { - previous->next = q->next; - } else { - prot_list = q->next; - } - delete p; - return noErr; - } - previous = q; - q = q->next; - } - } - return lapProtErr; -} - -#if MONITOR -static void dump_packet( uint8 *packet, int length ) -{ - char buf[1000], sm[10]; - - *buf = 0; - - if(length > 256) length = 256; - - for (int i=0; inext = 0; - if(send_queue) { - LPPACKET p = send_queue; - // The queue is short. It would be larger overhead to double-link it. - while(p->next) p = p->next; - p->next = Packet; - } else { - send_queue = Packet; - } - LeaveCriticalSection( &send_csection ); -} - -static LPPACKET get_send_head( void ) -{ - LPPACKET Packet = 0; - - EnterCriticalSection( &send_csection ); - if(send_queue) { - Packet = send_queue; - send_queue = send_queue->next; - } - LeaveCriticalSection( &send_csection ); - - return Packet; -} - -static int get_write_packet_pool_sz( void ) -{ - LPPACKET t = write_packet_pool; - int sz = 0; - - while(t) { - t = t->next; - sz++; - } - return(sz); -} - -static void free_write_packets( void ) -{ - LPPACKET next; - int i = 0; - while(write_packet_pool) { - next = write_packet_pool->next; - D(bug("Freeing write packet %ld\n",++i)); - PacketFreePacket(write_packet_pool); - write_packet_pool = next; - } -} - -void recycle_write_packet( LPPACKET Packet ) -{ - EnterCriticalSection( &wpool_csection ); - Packet->next = write_packet_pool; - write_packet_pool = Packet; - D(bug("Pool size after recycling = %ld\n",get_write_packet_pool_sz())); - LeaveCriticalSection( &wpool_csection ); -} - -static LPPACKET get_write_packet( UINT len ) -{ - LPPACKET Packet = 0; - - EnterCriticalSection( &wpool_csection ); - if(write_packet_pool) { - Packet = write_packet_pool; - write_packet_pool = write_packet_pool->next; - Packet->OverLapped.Offset = 0; - Packet->OverLapped.OffsetHigh = 0; - Packet->Length = len; - Packet->BytesReceived = 0; - Packet->bIoComplete = FALSE; - Packet->free = TRUE; - Packet->next = 0; - // actually an auto-reset event. - if(Packet->OverLapped.hEvent) ResetEvent(Packet->OverLapped.hEvent); - } else { - Packet = PacketAllocatePacket(fd,len); - } - - D(bug("Pool size after get wr packet = %ld\n",get_write_packet_pool_sz())); - - LeaveCriticalSection( &wpool_csection ); - - return Packet; -} - -unsigned int WINAPI ether_thread_write_packets(void *arg) -{ - LPPACKET Packet; - - thread_active_1 = true; - - D(bug("ether_thread_write_packets start\n")); - - while(thread_active) { - // must be alertable, otherwise write completion is never called - WaitForSingleObjectEx(int_send_now,INFINITE,TRUE); - while( thread_active && (Packet = get_send_head()) != 0 ) { - switch (net_if_type) { - case NET_IF_ROUTER: - if(router_write_packet((uint8 *)Packet->Buffer, Packet->Length)) { - Packet->bIoComplete = TRUE; - recycle_write_packet(Packet); - } - break; - case NET_IF_FAKE: - Packet->bIoComplete = TRUE; - recycle_write_packet(Packet); - break; - case NET_IF_B2ETHER: - if(!PacketSendPacket( fd, Packet, FALSE, TRUE )) { - // already recycled if async - } - break; - case NET_IF_TAP: - if (!tap_send_packet(fd, Packet, FALSE, TRUE)) { - // already recycled if async - } - break; - case NET_IF_SLIRP: - slirp_input((uint8 *)Packet->Buffer, Packet->Length); - Packet->bIoComplete = TRUE; - recycle_write_packet(Packet); - break; - } - } - } - - D(bug("ether_thread_write_packets exit\n")); - - thread_active_1 = false; - - return(0); -} - -static BOOL write_packet( uint8 *packet, int len ) -{ - LPPACKET Packet; - - D(bug("write_packet\n")); - - Packet = get_write_packet(len); - if(Packet) { - memcpy( Packet->Buffer, packet, len ); - - EnterCriticalSection( &fetch_csection ); - pending_packet_sz[echo_count] = min(sizeof(pending_packet),len); - memcpy( pending_packet[echo_count], packet, pending_packet_sz[echo_count] ); - echo_count = (echo_count+1) & (~(MAX_ECHO-1)); - LeaveCriticalSection( &fetch_csection ); - - insert_send_queue( Packet ); - - ReleaseSemaphore(int_send_now,1,NULL); - return(TRUE); - } else { - return(FALSE); - } -} - -static int16 ether_do_write(uint32 arg) -{ - D(bug("ether_write\n")); - - // Copy packet to buffer - uint8 packet[1514], *p = packet; - int len = ether_arg_to_buffer(arg, p); - - if(len > 1514) { - D(bug("illegal packet length: %d\n",len)); - return eLenErr; - } else { -#if MONITOR - bug("Sending Ethernet packet (%d bytes):\n",(int)len); - dump_packet( packet, len ); -#endif - } - - // Transmit packet - if (!write_packet(packet, len)) { - D(bug("WARNING: couldn't transmit packet\n")); - return excessCollsns; - } else { - // It's up to the protocol drivers to do the error checking. Even if the - // i/o completion routine returns ok, there can be errors, so there is - // no point to wait for write completion and try to make some sense of the - // possible error codes. - return noErr; - } -} - - -static void init_queue(void) -{ - queue_inx = 0; - queue_head = 0; - - for( int i=0; i 0) { - D(bug("ethernet queue full, packet dropped\n")); - } else { - if(sz > 1514) sz = 1514; - queue[queue_inx].sz = sz; - memcpy( queue[queue_inx].buf, buf, sz ); - queue_inx++; - if(queue_inx >= MAX_QUEUE_ITEMS) queue_inx = 0; - if(wait_request) { - wait_request = false; - ReleaseSemaphore(int_sig,1,NULL); - } - } - LeaveCriticalSection( &queue_csection ); -} - -static int dequeue_packet( uint8 *buf ) -{ - int sz; - - if(!thread_active) return(0); - - EnterCriticalSection( &queue_csection ); - sz = queue[queue_head].sz; - if(sz > 0) { - memcpy( buf, queue[queue_head].buf, sz ); - queue[queue_head].sz = 0; - queue_head++; - if(queue_head >= MAX_QUEUE_ITEMS) queue_head = 0; - } - LeaveCriticalSection( &queue_csection ); - return(sz); -} - -static void trigger_queue(void) -{ - EnterCriticalSection( &queue_csection ); - if( queue[queue_head].sz > 0 ) { - D(bug(" packet received, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - // of course can't wait here. - } - LeaveCriticalSection( &queue_csection ); -} - -static bool set_wait_request(void) -{ - bool result; - EnterCriticalSection( &queue_csection ); - if(queue[queue_head].sz) { - result = true; - } else { - result = false; - wait_request = true; - } - LeaveCriticalSection( &queue_csection ); - return(result); -} - - -/* - * TAP-Win32 glue - */ - -static LPADAPTER tap_open_adapter(LPCTSTR dev_name) -{ - fd = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*fd)); - if (fd == NULL) - return NULL; - - TCHAR dev_path[MAX_PATH]; - _sntprintf(dev_path, lengthof(dev_path), - TEXT("\\\\.\\Global\\%s.tap"), dev_name); - - HANDLE handle = CreateFile( - dev_path, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - NULL); - if (handle == NULL || handle == INVALID_HANDLE_VALUE) - return NULL; - - fd->hFile = handle; - return fd; -} - -static void tap_close_adapter(LPADAPTER fd) -{ - if (fd) { - if (fd->hFile) { - tap_set_status(fd, false); - CloseHandle(fd->hFile); - } - GlobalFreePtr(fd); - } -} - -static bool tap_check_version(LPADAPTER fd) -{ - ULONG len; - ULONG info[3] = { 0, }; - - if (!DeviceIoControl(fd->hFile, TAP_IOCTL_GET_VERSION, - &info, sizeof(info), - &info, sizeof(info), &len, NULL) - && !DeviceIoControl(fd->hFile, OLD_TAP_IOCTL_GET_VERSION, - &info, sizeof(info), - &info, sizeof(info), &len, NULL)) - return false; - - if (info[0] > TAP_VERSION_MIN_MAJOR) - return true; - if (info[0] == TAP_VERSION_MIN_MAJOR && info[1] >= TAP_VERSION_MIN_MINOR) - return true; - - return false; -} - -static bool tap_set_status(LPADAPTER fd, ULONG status) -{ - DWORD len = 0; - return DeviceIoControl(fd->hFile, TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof (status), - &status, sizeof (status), &len, NULL) != FALSE; -} - -static bool tap_get_mac(LPADAPTER fd, LPBYTE addr) -{ - DWORD len = 0; - return DeviceIoControl(fd->hFile, TAP_IOCTL_GET_MAC, - addr, 6, - addr, 6, &len, NULL) != FALSE; -} - -static VOID CALLBACK tap_write_completion( - DWORD dwErrorCode, - DWORD dwNumberOfBytesTransfered, - LPOVERLAPPED lpOverLapped - ) -{ - LPPACKET lpPacket = CONTAINING_RECORD(lpOverLapped, PACKET, OverLapped); - - lpPacket->bIoComplete = TRUE; - recycle_write_packet(lpPacket); -} - -static bool tap_send_packet( - LPADAPTER fd, - LPPACKET lpPacket, - BOOLEAN Sync, - BOOLEAN RecyclingAllowed) -{ - BOOLEAN Result; - - lpPacket->OverLapped.Offset = 0; - lpPacket->OverLapped.OffsetHigh = 0; - lpPacket->bIoComplete = FALSE; - - if (Sync) { - Result = WriteFile(fd->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->BytesReceived, - &lpPacket->OverLapped); - if (Result) { - GetOverlappedResult(fd->hFile, - &lpPacket->OverLapped, - &lpPacket->BytesReceived, - TRUE); - } - lpPacket->bIoComplete = TRUE; - if (RecyclingAllowed) - PacketFreePacket(lpPacket); - } - else { - Result = WriteFileEx(fd->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->OverLapped, - tap_write_completion); - - if (!Result && RecyclingAllowed) - recycle_write_packet(lpPacket); - } - - return Result != FALSE; -} - -static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync) -{ - BOOLEAN Result; - - lpPacket->OverLapped.Offset = 0; - lpPacket->OverLapped.OffsetHigh = 0; - lpPacket->bIoComplete = FALSE; - - if (Sync) { - Result = ReadFile(fd->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->BytesReceived, - &lpPacket->OverLapped); - if (Result) { - Result = GetOverlappedResult(fd->hFile, - &lpPacket->OverLapped, - &lpPacket->BytesReceived, - TRUE); - if (Result) - lpPacket->bIoComplete = TRUE; - else - lpPacket->free = TRUE; - } - } - else { - Result = ReadFileEx(fd->hFile, - lpPacket->Buffer, - lpPacket->Length, - &lpPacket->OverLapped, - packet_read_completion); - - if (!Result) - lpPacket->BytesReceived = 0; - } - - return Result != FALSE; -} - - -/* - * SLIRP output buffer glue - */ - -int slirp_can_output(void) -{ - return 1; -} - -void slirp_output(const uint8 *packet, int len) -{ - enqueue_packet(packet, len); -} - -unsigned int WINAPI slirp_receive_func(void *arg) -{ - D(bug("slirp_receive_func\n")); - thread_active_2 = true; - - while (thread_active) { - // Wait for packets to arrive - fd_set rfds, wfds, xfds; - int nfds, ret, timeout; - - // ... in the output queue - nfds = -1; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - timeout = slirp_select_fill(&nfds, &rfds, &wfds, &xfds); -#if ! USE_SLIRP_TIMEOUT - timeout = 10000; -#endif - if (nfds < 0) { - /* Windows does not honour the timeout if there is not - descriptor to wait for */ - Delay_usec(timeout); - ret = 0; - } - else { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = timeout; - ret = select(0, &rfds, &wfds, &xfds, &tv); - } - if (ret >= 0) - slirp_select_poll(&rfds, &wfds, &xfds); - } - - D(bug("slirp_receive_func exit\n")); - thread_active_2 = false; - return 0; -} - - -/* - * Packet reception threads - */ - -VOID CALLBACK packet_read_completion( - DWORD dwErrorCode, - DWORD dwNumberOfBytesTransfered, - LPOVERLAPPED lpOverlapped - ) -{ - EnterCriticalSection( &fetch_csection ); - - LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped); - - D(bug("packet_read_completion bytes=%d, error code=%d\n",dwNumberOfBytesTransfered,dwErrorCode)); - - if(thread_active && !dwErrorCode) { - int count = min(dwNumberOfBytesTransfered,1514); - if(count) { - int j = echo_count; - for(int i=MAX_ECHO; i; i--) { - j--; - if(j < 0) j = MAX_ECHO-1; - if(count == pending_packet_sz[j] && - memcmp(pending_packet[j],lpPacket->Buffer,count) == 0) - { - D(bug("packet_read_completion discarding own packet.\n")); - dwNumberOfBytesTransfered = 0; - - j = (j+1) & (~(MAX_ECHO-1)); - if(j != echo_count) { - D(bug("Wow, this fix made some good after all...\n")); - } - - break; - } - } - // XXX drop packets that are not for us - if (net_if_type == NET_IF_TAP) { - if (memcmp((LPBYTE)lpPacket->Buffer, ether_addr, 6) != 0) - dwNumberOfBytesTransfered = 0; - } - if(dwNumberOfBytesTransfered) { - if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) { - enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered ); - } - } - } - } - - // actually an auto-reset event. - if(lpPacket->OverLapped.hEvent) ResetEvent(lpPacket->OverLapped.hEvent); - - lpPacket->free = TRUE; - lpPacket->bIoComplete = TRUE; - - if(wait_request2) { - wait_request2 = false; - ReleaseSemaphore(int_sig2,1,NULL); - } - - LeaveCriticalSection( &fetch_csection ); -} - -static BOOL has_no_completed_io(void) -{ - BOOL result = TRUE; - - EnterCriticalSection( &fetch_csection ); - - for( int i=0; ibIoComplete) { - result = FALSE; - break; - } - } - if(result) wait_request2 = true; - - LeaveCriticalSection( &fetch_csection ); - return(result); -} - -static bool allocate_read_packets(void) -{ - for( int i=0; ifree) { - packets[i]->free = FALSE; - BOOLEAN Result; - switch (net_if_type) { - case NET_IF_B2ETHER: - Result = PacketReceivePacket(fd, packets[i], FALSE); - break; - case NET_IF_TAP: - Result = tap_receive_packet(fd, packets[i], FALSE); - break; - } - if (Result) { - if(packets[i]->bIoComplete) { - D(bug("Early io completion...\n")); - packet_read_completion( - ERROR_SUCCESS, - packets[i]->BytesReceived, - &packets[i]->OverLapped - ); - } - } else { - packets[i]->free = TRUE; - } - } - } - } - - if(thread_active && has_no_completed_io()) { - D(bug("Waiting for int_sig2\n")); - // "problem": awakens twice in a row. Fix if you increase the pool size. - WaitForSingleObjectEx(int_sig2,INFINITE,TRUE); - } - } - - D(bug("ether_thread_get_packets_nt exit\n")); - - thread_active_2 = false; - - return 0; -} - -unsigned int WINAPI ether_thread_feed_int(void *arg) -{ - bool looping; - - thread_active_3 = true; - - D(bug("ether_thread_feed_int start\n")); - - while(thread_active) { - D(bug("Waiting for int_sig\n")); - WaitForSingleObject(int_sig,INFINITE); - // Looping this way to avoid a race condition. - D(bug("Triggering\n")); - looping = true; - while(thread_active && looping) { - trigger_queue(); - // Wait for interrupt acknowledge by EtherInterrupt() - WaitForSingleObject(int_ack,INFINITE); - if(thread_active) looping = set_wait_request(); - } - D(bug("Queue empty.\n")); - } - - D(bug("ether_thread_feed_int exit\n")); - - thread_active_3 = false; - - return 0; -} - - -/* - * Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers - */ - -static void ether_do_interrupt(void) -{ - // Call protocol handler for received packets - EthernetPacket ether_packet; - uint32 packet = ether_packet.addr(); - ssize_t length; - for (;;) { - - // Read packet from Ethernet device - length = dequeue_packet(Mac2HostAddr(packet)); - if (length < 14) - break; - -#if MONITOR - bug("Receiving Ethernet packet (%d bytes):\n",(int)length); - dump_packet( Mac2HostAddr(packet), length ); -#endif - - // Dispatch packet - ether_dispatch_packet(packet, length); - } -} - -#if DEBUG -#pragma optimize("",on) -#endif diff --git a/BasiliskII/src/Windows/ether_windows.h b/BasiliskII/src/Windows/ether_windows.h deleted file mode 100755 index aed67040..00000000 --- a/BasiliskII/src/Windows/ether_windows.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ETHER_WINDOWS_H_ -#define _ETHER_WINDOWS_H_ - -void enqueue_packet( const uint8 *buf, int sz ); - -#ifdef SHEEPSHAVER -extern uint8 ether_addr[6]; -#endif - -#endif // _ETHER_WINDOWS_H_ diff --git a/BasiliskII/src/Windows/extfs_windows.cpp b/BasiliskII/src/Windows/extfs_windows.cpp deleted file mode 100755 index f2b8a372..00000000 --- a/BasiliskII/src/Windows/extfs_windows.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* - * extfs_windows.cpp - MacOS file system for access native file system access, Windows specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "extfs.h" -#include "extfs_defs.h" -#include "posix_emu.h" - -#include -#include -#include -#include -#include - - -#define DEBUG 0 -#include "debug.h" - - -// Constants -#define HOST_DIRSEP_CHAR '\\' -#define HOST_DIRSEP_STR "\\" - - -// Default Finder flags -const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited; - - -/* - * Initialization - */ - -void extfs_init(void) -{ - init_posix_emu(); -} - - -/* - * Deinitialization - */ - -void extfs_exit(void) -{ - final_posix_emu(); -} - - -/* - * Add component to path name - */ - -void add_path_component(char *path, const char *component) -{ - int l = strlen(path); - if (l < MAX_PATH_LENGTH-1 && path[l-1] != HOST_DIRSEP_CHAR) { - path[l] = HOST_DIRSEP_CHAR; - path[l+1] = 0; - } - strncat(path, component, MAX_PATH_LENGTH-1); -} - - -/* - * Finder info and resource forks are kept in helper files - * - * Finder info: - * /path/.finf/file - * Resource fork: - * /path/.rsrc/file - * - * The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo - * (16+16 bytes) - */ - -static void make_helper_path(const char *src, char *dest, const char *add, bool only_dir = false) -{ - dest[0] = 0; - - // Get pointer to last component of path - const char *last_part = strrchr(src, HOST_DIRSEP_CHAR); - if (last_part) - last_part++; - else - last_part = src; - - // Copy everything before - strncpy(dest, src, last_part-src); - dest[last_part-src] = 0; - - // Add additional component - strncat(dest, add, MAX_PATH_LENGTH-1); - - // Add last component - if (!only_dir) - strncat(dest, last_part, MAX_PATH_LENGTH-1); -} - -static int create_helper_dir(const char *path, const char *add) -{ - char helper_dir[MAX_PATH_LENGTH]; - make_helper_path(path, helper_dir, add, true); - if (helper_dir[strlen(helper_dir) - 1] == HOST_DIRSEP_CHAR) // Remove trailing "\" - helper_dir[strlen(helper_dir) - 1] = 0; - return mkdir(helper_dir, 0777); -} - -static int open_helper(const char *path, const char *add, int flag) -{ - char helper_path[MAX_PATH_LENGTH]; - make_helper_path(path, helper_path, add); - - switch (flag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { - case _O_WRONLY: - case _O_RDWR: - flag |= O_CREAT; - break; - } - - int fd = open(helper_path, flag, 0666); - if (fd < 0) { - if (/*errno == ENOENT &&*/ (flag & O_CREAT)) { - // One path component was missing, probably the helper - // directory. Try to create it and re-open the file. - int ret = create_helper_dir(path, add); - if (ret < 0) - return ret; - fd = open(helper_path, flag, 0666); - } - } - return fd; -} - -static int open_finf(const char *path, int flag) -{ - return open_helper(path, ".finf" HOST_DIRSEP_STR, flag); -} - -static int open_rsrc(const char *path, int flag) -{ - return open_helper(path, ".rsrc" HOST_DIRSEP_STR, flag); -} - - -/* - * Get/set finder info for file/directory specified by full path - */ - -struct ext2type { - const char *ext; - uint32 type; - uint32 creator; -}; - -static const ext2type e2t_translation[] = { - {".Z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')}, - {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')}, - {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')}, - {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')}, - {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')}, - {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')}, - {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')}, - {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')}, - {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')}, - {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')}, - {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')}, - {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')}, - {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')}, - {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')}, - {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')}, - {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')}, - {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')}, - {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')}, - {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')}, - {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')}, - {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')}, - {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')}, - {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')}, - {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')}, - {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')}, - {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')}, - {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')}, - {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')}, - {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')}, - {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')}, - {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')}, - {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')}, - {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')}, - {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".C", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".S", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')}, - {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')}, - {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')}, - {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')}, - {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')}, - {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')}, - {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')}, - {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')}, - {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')}, - {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')}, - {NULL, 0, 0} // End marker -}; - -void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Set default finder info - Mac_memset(finfo, 0, SIZEOF_FInfo); - if (fxinfo) - Mac_memset(fxinfo, 0, SIZEOF_FXInfo); - WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS); - WriteMacInt32(finfo + fdLocation, (uint32)-1); - - // Read Finder info file - int fd = open_finf(path, O_RDONLY); - if (fd >= 0) { - ssize_t actual = read(fd, Mac2HostAddr(finfo), SIZEOF_FInfo); - if (fxinfo) - actual += read(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo); - close(fd); - if (actual >= SIZEOF_FInfo) - return; - } - - // No Finder info file, translate file name extension to MacOS type/creator - if (!is_dir) { - int path_len = strlen(path); - for (int i=0; e2t_translation[i].ext; i++) { - int ext_len = strlen(e2t_translation[i].ext); - if (path_len < ext_len) - continue; - if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) { - WriteMacInt32(finfo + fdType, e2t_translation[i].type); - WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator); - break; - } - } - } -} - -void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir) -{ - // Open Finder info file - int fd = open_finf(path, O_RDWR); - if (fd < 0) - return; - - // Write file - write(fd, Mac2HostAddr(finfo), SIZEOF_FInfo); - if (fxinfo) - write(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo); - close(fd); -} - - -/* - * Resource fork emulation functions - */ - -uint32 get_rfork_size(const char *path) -{ - // Open resource file - int fd = open_rsrc(path, O_RDONLY); - if (fd < 0) - return 0; - - // Get size - off_t size = lseek(fd, 0, SEEK_END); - - // Close file and return size - close(fd); - return size < 0 ? 0 : size; -} - -int open_rfork(const char *path, int flag) -{ - return open_rsrc(path, flag); -} - -void close_rfork(const char *path, int fd) -{ - if (fd >= 0) - close(fd); -} - - -/* - * Read "length" bytes from file to "buffer", - * returns number of bytes read (or -1 on error) - */ - -ssize_t extfs_read(int fd, void *buffer, size_t length) -{ - return read(fd, buffer, length); -} - - -/* - * Write "length" bytes from "buffer" to file, - * returns number of bytes written (or -1 on error) - */ - -ssize_t extfs_write(int fd, void *buffer, size_t length) -{ - return write(fd, buffer, length); -} - - -/* - * Remove file/directory (and associated helper files), - * returns false on error (and sets errno) - */ - -bool extfs_remove(const char *path) -{ - // Remove helpers first, don't complain if this fails - char helper_path[MAX_PATH_LENGTH]; - make_helper_path(path, helper_path, ".finf" HOST_DIRSEP_STR, false); - remove(helper_path); - make_helper_path(path, helper_path, ".rsrc" HOST_DIRSEP_STR, false); - remove(helper_path); - - // Now remove file or directory (and helper directories in the directory) - if (remove(path) < 0) { - if (errno == EISDIR || errno == ENOTEMPTY) { - helper_path[0] = 0; - strncpy(helper_path, path, MAX_PATH_LENGTH-1); - add_path_component(helper_path, ".finf"); - rmdir(helper_path); - helper_path[0] = 0; - strncpy(helper_path, path, MAX_PATH_LENGTH-1); - add_path_component(helper_path, ".rsrc"); - rmdir(helper_path); - return rmdir(path) == 0; - } else - return false; - } - return true; -} - - -/* - * Rename/move file/directory (and associated helper files), - * returns false on error (and sets errno) - */ - -bool extfs_rename(const char *old_path, const char *new_path) -{ - // Rename helpers first, don't complain if this fails - char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH]; - make_helper_path(old_path, old_helper_path, ".finf" HOST_DIRSEP_STR, false); - make_helper_path(new_path, new_helper_path, ".finf" HOST_DIRSEP_STR, false); - create_helper_dir(new_path, ".finf" HOST_DIRSEP_STR); - rename(old_helper_path, new_helper_path); - make_helper_path(old_path, old_helper_path, ".rsrc" HOST_DIRSEP_STR, false); - make_helper_path(new_path, new_helper_path, ".rsrc" HOST_DIRSEP_STR, false); - create_helper_dir(new_path, ".rsrc" HOST_DIRSEP_STR); - rename(old_helper_path, new_helper_path); - - // Now rename file - return rename(old_path, new_path) == 0; -} - - -// Convert from the host OS filename encoding to MacRoman -const char *host_encoding_to_macroman(const char *filename) -{ - return filename; -} - -// Convert from MacRoman to host OS filename encoding -const char *macroman_to_host_encoding(const char *filename) -{ - return filename; -} - diff --git a/BasiliskII/src/Windows/gencomp.vcxproj b/BasiliskII/src/Windows/gencomp.vcxproj deleted file mode 100644 index b2c92701..00000000 --- a/BasiliskII/src/Windows/gencomp.vcxproj +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {95933FE9-C27C-41F0-B4AF-EAAADE94FD04} - Win32Proj - gencomp - 8.1 - - - - Application - true - v140 - Unicode - - - Application - true - v140 - Unicode - - - Application - false - v140 - true - Unicode - - - Application - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(Configuration)\$(ProjectName)\ - - - true - - - false - $(Configuration)\$(ProjectName)\ - - - false - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - true - true - - - - - - - - - - - - - Document - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - Generating cpudefs.cpp... - Generating cpudefs.cpp... - Generating cpudefs.cpp... - Generating cpudefs.cpp... - ..\uae_cpu\cpudefs.cpp - ..\uae_cpu\cpudefs.cpp - ..\uae_cpu\cpudefs.cpp - ..\uae_cpu\cpudefs.cpp - $(OutDir)build68k.exe - $(OutDir)build68k.exe - $(OutDir)build68k.exe - $(OutDir)build68k.exe - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/gencomp.vcxproj.filters b/BasiliskII/src/Windows/gencomp.vcxproj.filters deleted file mode 100644 index 861ff2a3..00000000 --- a/BasiliskII/src/Windows/gencomp.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/gencpu.vcxproj b/BasiliskII/src/Windows/gencpu.vcxproj deleted file mode 100644 index c688794b..00000000 --- a/BasiliskII/src/Windows/gencpu.vcxproj +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {1A9EA738-8DA7-422F-9E0D-BE92893C0E48} - Win32Proj - gencpu - 8.1 - - - - Application - true - v140 - Unicode - - - Application - true - v140 - Unicode - - - Application - false - v140 - true - Unicode - - - Application - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - $(Configuration)\$(ProjectName)\ - - - true - - - false - $(Configuration)\$(ProjectName)\ - - - false - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - - - - - - - Level3 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - . - - - Console - true - true - true - - - - - - - - - - - - - Document - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - Generating cpudefs.cpp... - Generating cpudefs.cpp... - ..\uae_cpu\cpudefs.cpp - ..\uae_cpu\cpudefs.cpp - $(OutDir)build68k.exe - $(OutDir)build68k.exe - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - "$(OutDir)build68k" "%(Identity)" > ..\uae_cpu\cpudefs.cpp - Generating cpudefs.cpp... - Generating cpudefs.cpp... - ..\uae_cpu\cpudefs.cpp - ..\uae_cpu\cpudefs.cpp - $(OutDir)build68k.exe - $(OutDir)build68k.exe - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/gencpu.vcxproj.filters b/BasiliskII/src/Windows/gencpu.vcxproj.filters deleted file mode 100644 index d8db474e..00000000 --- a/BasiliskII/src/Windows/gencpu.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - - - - \ No newline at end of file diff --git a/BasiliskII/src/Windows/main_windows.cpp b/BasiliskII/src/Windows/main_windows.cpp deleted file mode 100755 index 7d555c98..00000000 --- a/BasiliskII/src/Windows/main_windows.cpp +++ /dev/null @@ -1,703 +0,0 @@ -/* - * main_windows.cpp - Startup code for Windows - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include -typedef std::basic_string tstring; - -#include "cpu_emulation.h" -#include "sys.h" -#include "rom_patches.h" -#include "xpram.h" -#include "timer.h" -#include "video.h" -#include "cdrom.h" -#include "emul_op.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "macos_util.h" -#include "user_strings.h" -#include "version.h" -#include "main.h" -#include "vm_alloc.h" -#include "sigsegv.h" -#include "util_windows.h" - -#if USE_JIT -extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp -#endif - -#ifdef ENABLE_MON -# include "mon.h" -#endif - -#define DEBUG 0 -#include "debug.h" - - -// Constants -const TCHAR ROM_FILE_NAME[] = TEXT("ROM"); -const int SCRATCH_MEM_SIZE = 0x10000; // Size of scratch memory area - - -// CPU and FPU type, addressing mode -int CPUType; -bool CPUIs68060; -int FPUType; -bool TwentyFourBitAddressing; - - -// Global variables -HANDLE emul_thread = NULL; // Handle of MacOS emulation thread (main thread) - -static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes -static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed -static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread -static SDL_Thread *xpram_thread = NULL; // XPRAM watchdog - -static bool tick_thread_active = false; // Flag: 60Hz thread installed -static volatile bool tick_thread_cancel = false; // Flag: Cancel 60Hz thread -static SDL_Thread *tick_thread; // 60Hz thread - -static SDL_mutex *intflag_lock = NULL; // Mutex to protect InterruptFlags -#define LOCK_INTFLAGS SDL_LockMutex(intflag_lock) -#define UNLOCK_INTFLAGS SDL_UnlockMutex(intflag_lock) - -#if USE_SCRATCHMEM_SUBTERFUGE -uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes -#endif - -#if REAL_ADDRESSING -static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped -#endif - - -// Prototypes -static int xpram_func(void *arg); -static int tick_func(void *arg); -static void one_tick(...); - - -/* - * Ersatz functions - */ - -extern "C" { - -#ifndef HAVE_STRDUP -char *strdup(const char *s) -{ - char *n = (char *)malloc(strlen(s) + 1); - strcpy(n, s); - return n; -} -#endif - -} - - -/* - * Map memory that can be accessed from the Mac side - */ - -void *vm_acquire_mac(size_t size) -{ - return vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); -} - - -/* - * SIGSEGV handler - */ - -static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip) -{ - const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip); -#if ENABLE_VOSF - // Handle screen fault - extern bool Screen_fault_handler(sigsegv_info_t *sip); - if (Screen_fault_handler(sip)) - return SIGSEGV_RETURN_SUCCESS; -#endif - -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - // Ignore writes to ROM - if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // Ignore all other faults, if requested - if (PrefsFindBool("ignoresegv")) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; -#endif - - return SIGSEGV_RETURN_FAILURE; -} - -/* - * Dump state when everything went wrong after a SEGV - */ - -static void sigsegv_dump_state(sigsegv_info_t *sip) -{ - const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip); - const sigsegv_address_t fault_instruction = sigsegv_get_fault_instruction_address(sip); - fprintf(stderr, "Caught SIGSEGV at address %p", fault_address); - if (fault_instruction != SIGSEGV_INVALID_ADDRESS) - fprintf(stderr, " [IP=%p]", fault_instruction); - fprintf(stderr, "\n"); - uaecptr nextpc; - extern void m68k_dumpstate(uaecptr *nextpc); - m68k_dumpstate(&nextpc); -#if USE_JIT && JIT_DEBUG - extern void compiler_dumpstate(void); - compiler_dumpstate(); -#endif - VideoQuitFullScreen(); -#ifdef ENABLE_MON - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); - QuitEmulator(); -#endif -} - - -/* - * Main program - */ - -static void usage(const char *prg_name) -{ - printf( - "Usage: %s [OPTION...]\n" - "\nUnix options:\n" - " --config FILE\n read/write configuration from/to FILE\n" - " --display STRING\n X display to use\n" - " --break ADDRESS\n set ROM breakpoint\n" - " --rominfo\n dump ROM information\n", prg_name - ); - LoadPrefs(NULL); // read the prefs file so PrefsPrintUsage() will print the correct default values - PrefsPrintUsage(); - exit(0); -} - -int main(int argc, char **argv) -{ - char str[256]; - bool cd_boot = false; - - // Initialize variables - RAMBaseHost = NULL; - ROMBaseHost = NULL; - srand(unsigned(time(NULL))); - tzset(); - - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - - // Parse command line arguments - for (int i=1; i i) { - k -= i; - for (int j=i+k; jm); -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ - if (mutex) - SDL_UnlockMutex(mutex->m); -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - - -/* - * Interrupt flags (must be handled atomically!) - */ - -uint32 InterruptFlags = 0; - -void SetInterruptFlag(uint32 flag) -{ - LOCK_INTFLAGS; - InterruptFlags |= flag; - UNLOCK_INTFLAGS; -} - -void ClearInterruptFlag(uint32 flag) -{ - LOCK_INTFLAGS; - InterruptFlags &= ~flag; - UNLOCK_INTFLAGS; -} - - -/* - * XPRAM watchdog thread (saves XPRAM every minute) - */ - -static void xpram_watchdog(void) -{ - if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - SaveXPRAM(); - } -} - -static int xpram_func(void *arg) -{ - while (!xpram_thread_cancel) { - for (int i=0; i<60 && !xpram_thread_cancel; i++) - Delay_usec(999999); // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true - xpram_watchdog(); - } - return 0; -} - - -/* - * 60Hz thread (really 60.15Hz) - */ - -static void one_second(void) -{ - // Pseudo Mac 1Hz interrupt, update local time - WriteMacInt32(0x20c, TimerDateTime()); - - SetInterruptFlag(INTFLAG_1HZ); - TriggerInterrupt(); -} - -static void one_tick(...) -{ - static int tick_counter = 0; - if (++tick_counter > 60) { - tick_counter = 0; - one_second(); - } - - // Trigger 60Hz interrupt - if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) { - SetInterruptFlag(INTFLAG_60HZ); - TriggerInterrupt(); - } -} - -static int tick_func(void *arg) -{ - uint64 start = GetTicks_usec(); - int64 ticks = 0; - uint64 next = GetTicks_usec(); - while (!tick_thread_cancel) { - one_tick(); - next += 16625; - int64 delay = next - GetTicks_usec(); - if (delay > 0) - Delay_usec(uint32(delay)); - else if (delay < -16625) - next = GetTicks_usec(); - ticks++; - } - uint64 end = GetTicks_usec(); - D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); - return 0; -} - - -/* - * Get the main window handle - */ - -#ifdef USE_SDL_VIDEO -#include -HWND GetMainWindowHandle(void) -{ - SDL_SysWMinfo wmInfo; - SDL_VERSION(&wmInfo.version); - return SDL_GetWMInfo(&wmInfo) ? wmInfo.window : NULL; -} -#endif - - -/* - * Display alert - */ - -static void display_alert(int title_id, const char *text, int flags) -{ - HWND hMainWnd = GetMainWindowHandle(); - MessageBoxA(hMainWnd, text, GetString(title_id), MB_OK | flags); -} -static void display_alert(int title_id, const wchar_t *text, int flags) -{ - HWND hMainWnd = GetMainWindowHandle(); - MessageBoxW(hMainWnd, text, GetStringW(title_id).get(), MB_OK | flags); -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - if (PrefsFindBool("nogui")) - return; - - VideoQuitFullScreen(); - display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP); -} -void ErrorAlert(const wchar_t *text) -{ - if (PrefsFindBool("nogui")) - return; - - VideoQuitFullScreen(); - display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - if (PrefsFindBool("nogui")) - return; - - display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONINFORMATION); -} -void WarningAlert(const wchar_t *text) -{ - if (PrefsFindBool("nogui")) - return; - - display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONINFORMATION); -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return false; //!! -} diff --git a/BasiliskII/src/Windows/posix_emu.cpp b/BasiliskII/src/Windows/posix_emu.cpp deleted file mode 100755 index 518a526f..00000000 --- a/BasiliskII/src/Windows/posix_emu.cpp +++ /dev/null @@ -1,1125 +0,0 @@ -/* - * posix_emu.cpp -- posix and virtual desktop - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// TODO: UNC names. Customizable "Virtual Desktop" location. - -#include "sysdeps.h" -#define NO_POSIX_API_HOOK -#include "posix_emu.h" -#include "user_strings.h" -#include "util_windows.h" -#include "main.h" -#include "extfs_defs.h" -#include "prefs.h" -#include - - -#define DEBUG_EXTFS 0 - -#if DEBUG_EXTFS - -// This must be always on. -#define DEBUG 1 -#undef OutputDebugString -#define OutputDebugString extfs_log_write -extern void extfs_log_write( char *s ); -#define EXTFS_LOG_FILE_NAME "extfs.log" -#include "debug.h" - -enum { - DB_EXTFS_NONE=0, - DB_EXTFS_NORMAL, - DB_EXTFS_LOUD -}; -static int16 debug_extfs = DB_EXTFS_NONE; -static HANDLE extfs_log_file = INVALID_HANDLE_VALUE; - -static void extfs_log_open( char *path ) -{ - if(debug_extfs == DB_EXTFS_NONE) return; - - DeleteFile( path ); - extfs_log_file = CreateFile( - path, - GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - // FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING, - FILE_FLAG_WRITE_THROUGH, - NULL - ); - if( extfs_log_file == INVALID_HANDLE_VALUE ) { - ErrorAlert( "Could not create the EXTFS log file." ); - } -} - -static void extfs_log_close( void ) -{ - if(debug_extfs == DB_EXTFS_NONE) return; - - if( extfs_log_file != INVALID_HANDLE_VALUE ) { - CloseHandle( extfs_log_file ); - extfs_log_file = INVALID_HANDLE_VALUE; - } -} - -static void extfs_log_write( char *s ) -{ - DWORD bytes_written; - - // should have been checked already. - if(debug_extfs == DB_EXTFS_NONE) return; - - if( extfs_log_file != INVALID_HANDLE_VALUE ) { - - DWORD count = strlen(s); - if (0 == WriteFile(extfs_log_file, s, count, &bytes_written, NULL) || - (int)bytes_written != count) - { - extfs_log_close(); - ErrorAlert( "extfs log file write error (out of disk space?). Log closed." ); - } else { - FlushFileBuffers( extfs_log_file ); - } - } -} -#else - -#define DEBUG 0 -#include "debug.h" - -#endif // DEBUG_EXTFS - -int my_errno = 0; - -#define VIRTUAL_ROOT_ID ((HANDLE)0xFFFFFFFE) - -static LPCTSTR desktop_name = TEXT("Virtual Desktop"); -static const char *custom_icon_name = "Icon\r"; -#define my_computer GetString(STR_EXTFS_VOLUME_NAME) - -static TCHAR lb1[MAX_PATH_LENGTH]; -static TCHAR lb2[MAX_PATH_LENGTH]; - -#define MRP(path) translate(path,lb1) -#define MRP2(path) translate(path,lb2) - -#define DISABLE_ERRORS UINT prevmode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS) -#define RESTORE_ERRORS SetErrorMode(prevmode); - -static TCHAR host_drive_list[512]; -static TCHAR virtual_root[248]; // Not _MAX_PATH - -const uint8 my_comp_icon[2670] = { - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0xD8, 0x00, 0x00, 0x08, 0xD8, 0x00, 0x00, 0x00, 0x96, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x79, 0x79, 0x79, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xC0, 0xCC, 0xCC, 0xCC, - 0xCC, 0xD7, 0x97, 0x97, 0x97, 0x97, 0x97, 0xC0, 0xC0, 0xC0, 0xC0, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCD, 0xDB, 0xD9, 0x79, 0x79, 0x7E, 0x79, 0x0C, 0xDD, 0xCD, 0xDD, 0xCD, 0xCD, 0xDC, 0xDD, 0xCD, - 0xCC, 0xED, 0xED, 0x97, 0x97, 0x97, 0x97, 0x0C, 0xE7, 0x78, 0x77, 0x97, 0x97, 0x97, 0x97, 0x97, - 0xDC, 0xED, 0xDE, 0x79, 0x79, 0x79, 0x99, 0x0C, 0xD9, 0x7E, 0x5E, 0x65, 0x5E, 0x65, 0xD9, 0x79, - 0xCD, 0xDE, 0xDD, 0x97, 0xE7, 0x9E, 0x77, 0xC0, 0x97, 0x9D, 0xCD, 0xCC, 0xC7, 0xCC, 0xE7, 0x97, - 0xCC, 0xED, 0xEE, 0x79, 0x79, 0x79, 0x7E, 0xCC, 0x57, 0xD5, 0xD7, 0xD5, 0xDD, 0x5D, 0xD9, 0x7E, - 0xCD, 0xDE, 0xDE, 0x79, 0x97, 0x97, 0x99, 0x0C, 0x87, 0xCD, 0x75, 0xC7, 0x5C, 0x7D, 0xD9, 0x79, - 0xCD, 0xDD, 0xED, 0xE7, 0x7E, 0x79, 0x77, 0xCC, 0xE7, 0xB0, 0x00, 0xC0, 0x0C, 0xCD, 0xE7, 0x97, - 0xDC, 0xED, 0xEE, 0x79, 0x97, 0x86, 0x79, 0xC0, 0xE7, 0xD0, 0x2C, 0xC1, 0xC2, 0xCD, 0xD9, 0x79, - 0xCD, 0xDE, 0xDD, 0x97, 0x99, 0x79, 0x97, 0x0C, 0xE7, 0xB0, 0xD0, 0xDC, 0xCC, 0xCD, 0xD6, 0x87, - 0xDD, 0xDE, 0xED, 0x79, 0x77, 0xE7, 0x79, 0x0C, 0x58, 0xDC, 0x0C, 0x0C, 0xCC, 0xCD, 0xE9, 0x79, - 0xCD, 0xDD, 0xD5, 0x99, 0x97, 0x99, 0x79, 0xC0, 0x87, 0xD0, 0xC0, 0xC0, 0xC0, 0xCD, 0xD7, 0xE7, - 0xDD, 0xDE, 0xD7, 0x97, 0x79, 0x77, 0xE7, 0x0C, 0xE7, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x79, 0x79, - 0xCD, 0xDE, 0xD9, 0x79, 0x97, 0xE9, 0x79, 0x0C, 0x97, 0x79, 0x79, 0x79, 0x79, 0x79, 0x97, 0x97, - 0xDC, 0xED, 0xE7, 0x97, 0x79, 0x97, 0x97, 0x0C, 0xCD, 0xD7, 0xD7, 0xD7, 0xE7, 0xE7, 0x7E, 0x79, - 0xCD, 0xDE, 0x79, 0x79, 0x97, 0x7E, 0x79, 0xC0, 0xCC, 0xCC, 0x0C, 0xCC, 0x0D, 0xCC, 0xDC, 0xDC, - 0xDC, 0xED, 0x97, 0x97, 0x77, 0x99, 0x79, 0xCC, 0xCC, 0xCC, 0xDC, 0xCC, 0xDC, 0xCC, 0xCC, 0x8D, - 0xCD, 0xDE, 0x79, 0x79, 0x96, 0x77, 0x97, 0x97, 0x97, 0x90, 0xCC, 0xCD, 0xCD, 0xDD, 0xDD, 0xCC, - 0xDD, 0xD9, 0x76, 0x87, 0x97, 0x99, 0x7E, 0x7C, 0x0C, 0xCC, 0xDD, 0xDD, 0xED, 0xDE, 0xDD, 0xEE, - 0xDE, 0xD5, 0xBD, 0xDE, 0x79, 0x79, 0x9C, 0xC0, 0xCC, 0xDD, 0xDD, 0xDD, 0xDE, 0xDD, 0xED, 0xDE, - 0xDE, 0xDD, 0xDE, 0xDE, 0x79, 0x79, 0x70, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xDC, 0xDD, 0xDD, 0xDD, - 0xDD, 0xDD, 0xED, 0xED, 0x97, 0x97, 0x90, 0xCC, 0x8D, 0xCC, 0xDC, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, - 0xCC, 0xEE, 0xDE, 0xDE, 0x79, 0x7E, 0x70, 0xCC, 0x88, 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDD, 0xDC, - 0xCD, 0xDD, 0xED, 0xED, 0x97, 0x97, 0xEC, 0xCC, 0xCC, 0xCC, 0xDC, 0xCC, 0xCD, 0xDD, 0xED, 0xDD, - 0xDC, 0xED, 0xED, 0xEE, 0x79, 0x79, 0xDC, 0x0D, 0xCC, 0xDC, 0xCC, 0xCD, 0xCC, 0xCC, 0xCC, 0x0C, - 0xDC, 0xDE, 0xDE, 0xED, 0x97, 0xDC, 0xCC, 0xDC, 0xCD, 0xCC, 0xDC, 0xCD, 0xCC, 0xCC, 0xCD, 0xCC, - 0xCC, 0xED, 0xED, 0x79, 0xDD, 0xC0, 0xCD, 0xCC, 0xDC, 0xCD, 0xCC, 0xDC, 0xCC, 0xDC, 0xDD, 0xCD, - 0xCD, 0xED, 0x97, 0x97, 0xDD, 0xCC, 0xCC, 0x00, 0xC0, 0xDD, 0xCD, 0xCC, 0xCC, 0xCD, 0xD0, 0xDC, - 0xDD, 0xF7, 0x99, 0x79, 0x97, 0x9D, 0xDD, 0xDD, 0xCC, 0xC0, 0xCC, 0x0C, 0xDC, 0xDC, 0xCD, 0xCD, - 0xDF, 0x79, 0x77, 0x97, 0x79, 0x79, 0x79, 0x79, 0xDD, 0xDE, 0xDC, 0xCC, 0xCC, 0xC0, 0xC0, 0xDD, - 0xE9, 0x79, 0x97, 0x99, 0x97, 0xE7, 0xE7, 0x97, 0x97, 0x9D, 0x79, 0xDD, 0xDD, 0xDD, 0xCD, 0xDE, - 0x79, 0x79, 0x7E, 0x77, 0x00, 0x00, 0x04, 0x00, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0xF5, - 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, - 0x2B, 0x2B, 0xF9, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0xF6, - 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF7, 0xF7, 0xF7, - 0xF7, 0xF8, 0x81, 0xFA, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, - 0xF7, 0xF8, 0x81, 0x81, 0x81, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, - 0xF8, 0xF8, 0x81, 0xFA, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xC2, 0xFB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFB, 0xC2, 0xC2, 0xC2, - 0xF7, 0xF8, 0x81, 0x81, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0x2B, - 0xA5, 0xC2, 0xC2, 0xFB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x81, 0xC2, 0xC2, 0xC2, - 0xF7, 0xF8, 0x81, 0x81, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0x2B, - 0xA5, 0xC2, 0xF9, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF9, 0xFB, 0xC2, 0xC2, 0xC2, - 0xF7, 0xF8, 0x81, 0x81, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xF9, 0x81, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0xFA, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0xF9, 0xFB, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0x81, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0xF5, 0x0A, 0xF6, 0x2B, 0x0A, 0xF6, 0x0A, 0x2B, 0xF9, 0x81, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0xF5, 0xF8, 0xF6, 0x56, 0xF7, 0xF7, 0xF8, 0x2B, 0xF9, 0x81, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0x81, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0x2B, 0xF9, 0xFB, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0xFA, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0xF6, 0xF6, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0xF9, 0x81, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xC2, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xA5, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0xF7, 0x56, 0xF8, 0x7A, 0x7A, 0x9E, 0x9E, 0x9E, 0x9E, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, - 0xF8, 0x56, 0x81, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, - 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF7, 0xF7, 0xF8, 0xF8, - 0xF8, 0x56, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF7, 0xF7, - 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0x56, 0xB9, 0xF8, - 0xF8, 0x56, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, - 0xC2, 0xC2, 0xC2, 0xF6, 0x2B, 0x2B, 0xF7, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0xF8, - 0xF8, 0x56, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, - 0xF6, 0xF6, 0x2B, 0xF8, 0x56, 0xFA, 0xF9, 0x81, 0x81, 0x81, 0xFA, 0x81, 0x81, 0x81, 0xFB, 0x81, - 0xFB, 0xFB, 0xFB, 0x81, 0xFA, 0xFA, 0xFA, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xF6, 0xF6, - 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFB, - 0x81, 0xFB, 0xF9, 0xFA, 0xFA, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7, - 0xF8, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF8, 0xF8, 0x56, 0x56, 0xF9, 0xF9, 0xF9, 0xFA, - 0xFA, 0xFA, 0xFA, 0x81, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7, - 0x93, 0xA0, 0xF7, 0xF7, 0xF8, 0xF7, 0xF7, 0xF8, 0xF7, 0xF7, 0xF7, 0xF7, 0x2B, 0x2B, 0x2B, 0x2B, - 0x2B, 0x2B, 0x81, 0xFB, 0x81, 0xFB, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7, - 0xA0, 0xA0, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0x56, 0x56, 0xF9, 0xF9, 0xF9, 0xF8, 0xF7, - 0xF7, 0xF7, 0xFB, 0xFB, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7, - 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF9, 0xF9, 0xFB, 0xFB, 0xFB, 0xF8, 0xF9, - 0xF9, 0xF7, 0x81, 0xFB, 0xFB, 0x81, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF8, 0x2B, 0x2B, 0x56, - 0x2B, 0x2B, 0xF9, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF8, - 0xF8, 0xF7, 0xFB, 0xFB, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xF8, 0xF8, 0xF6, 0xF6, 0xF9, 0xF8, - 0x2B, 0xF9, 0xF8, 0x2B, 0xF9, 0x2B, 0x2B, 0xF9, 0x2B, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, - 0xF7, 0xF7, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xF9, 0xF8, 0xF6, 0xF6, 0xF7, 0xF9, 0xF8, 0x2B, - 0xF9, 0xF8, 0xF6, 0xF9, 0xF8, 0xF6, 0xF9, 0xF8, 0xF6, 0x2B, 0xF9, 0x2B, 0xF9, 0x56, 0x2B, 0xF9, - 0x2B, 0xF9, 0xAC, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xFA, 0xF9, 0xF8, 0x2B, 0x2B, 0x2B, 0xF5, 0xF5, - 0xF5, 0xF5, 0xF9, 0xF8, 0xF6, 0xF9, 0xF8, 0xF6, 0x2B, 0xF8, 0x2B, 0xF9, 0x56, 0x2B, 0x56, 0x2B, - 0x56, 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xFA, 0xFA, 0xFA, 0xF9, 0xF8, - 0xF8, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF5, 0x2B, 0xF9, 0xF6, 0xF9, 0xF8, 0xF7, 0xF9, 0x2B, 0xF9, - 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, - 0xFA, 0xFA, 0xFA, 0xFA, 0xF9, 0xF8, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF5, 0xF5, 0xF5, 0x56, 0x81, - 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, - 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xFA, 0xF9, 0xFA, 0xFA, 0xF9, 0xF9, 0xF8, 0xF8, 0x81, 0x81, - 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0x00, 0x00, 0x01, 0x00, 0x03, 0xFF, 0xFF, 0xE0, - 0x02, 0x00, 0x00, 0x38, 0x02, 0xFF, 0xFF, 0x3C, 0x02, 0xFF, 0xFF, 0x3C, 0x02, 0xFF, 0xFF, 0x3C, - 0x02, 0xF0, 0x0F, 0x3C, 0x02, 0xFF, 0xFF, 0x3C, 0x02, 0xFF, 0xFF, 0x7C, 0x02, 0xE0, 0x1F, 0x7C, - 0x02, 0xE0, 0x1F, 0x7C, 0x02, 0xE0, 0x1F, 0x7C, 0x02, 0xE0, 0x1F, 0x7C, 0x02, 0xE0, 0x1F, 0x78, - 0x02, 0xFF, 0xFF, 0x78, 0x02, 0xFF, 0xFF, 0x78, 0x02, 0x1F, 0xFF, 0x70, 0x02, 0x00, 0x00, 0x70, - 0x03, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x1F, 0xFF, 0xFF, - 0x02, 0x00, 0x3F, 0xFF, 0x02, 0x40, 0x00, 0x3F, 0x02, 0xC0, 0x7C, 0x3F, 0x02, 0x00, 0x7D, 0xBF, - 0x0F, 0x20, 0x00, 0x3F, 0x32, 0x49, 0x00, 0x3C, 0xC4, 0x92, 0x2D, 0x70, 0xE0, 0x24, 0x1A, 0xE0, - 0x1F, 0x00, 0xA5, 0xC0, 0x00, 0xFC, 0x03, 0x80, 0x00, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0xE0, - 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, - 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, - 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF8, - 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, - 0x03, 0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, - 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, - 0x0F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE0, - 0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1F, 0xFC, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x04, - 0x1F, 0xFC, 0x0F, 0xFE, 0x0F, 0xFF, 0x18, 0x67, 0x34, 0x06, 0x69, 0x64, 0x72, 0xC8, 0x3F, 0xF0, - 0x1F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFC, - 0x1F, 0xFC, 0x07, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x3F, 0xFF, 0x7F, 0xFE, 0xFF, 0xFC, 0x07, 0xF8, - 0x00, 0x00, 0x00, 0x80, 0x79, 0x7C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCD, 0x97, 0x97, 0x90, 0xE7, 0x97, - 0x97, 0x97, 0xDD, 0xD9, 0x79, 0x7C, 0xE7, 0xD5, 0x5E, 0x58, 0xCE, 0xD7, 0x97, 0x9C, 0xDD, 0x5D, - 0x7D, 0xB7, 0xDD, 0x59, 0x79, 0x7C, 0x9D, 0x10, 0x1D, 0xD9, 0xCE, 0xD7, 0x97, 0x9C, 0xDD, 0x0C, - 0xCC, 0xE7, 0xDD, 0xD9, 0x79, 0x7C, 0xED, 0xDD, 0xDD, 0x79, 0xCE, 0xE7, 0xE7, 0x90, 0xE7, 0x77, - 0x97, 0x97, 0xDD, 0x79, 0x79, 0x7C, 0xCC, 0xDC, 0xCD, 0xC8, 0xDD, 0x97, 0x97, 0x99, 0x7C, 0xDD, - 0xDD, 0xDE, 0xDE, 0xDE, 0x7E, 0x7C, 0xCC, 0xCC, 0xCD, 0xCD, 0xDD, 0xDE, 0x99, 0x0C, 0x8C, 0xCC, - 0xCC, 0xCC, 0xCD, 0xED, 0x77, 0xCC, 0xCC, 0xCD, 0xDD, 0xED, 0xCE, 0xDE, 0x9C, 0xCD, 0xCD, 0xCD, - 0x0D, 0xCC, 0xCE, 0xE7, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xCC, 0xDE, 0x99, 0x97, 0x97, 0x9D, 0xDD, - 0xDD, 0xDE, 0xE9, 0x77, 0x00, 0x00, 0x01, 0x00, 0xC2, 0xC2, 0xC2, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, - 0xF6, 0x2B, 0x2B, 0x2B, 0xF7, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xC2, 0xC2, 0xC2, - 0xC2, 0xC2, 0xC2, 0xC2, 0xF8, 0x81, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xC2, 0x81, 0xAA, - 0xAA, 0xAA, 0xFB, 0xC2, 0xF8, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0x7F, 0x7F, - 0x7F, 0x56, 0x81, 0xC2, 0xF8, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0x0A, 0xF6, - 0x0A, 0x56, 0xFB, 0xC2, 0xF8, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0xF6, 0xF6, - 0xF6, 0x56, 0x81, 0xC2, 0x56, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0xF9, 0xF9, - 0xF9, 0xF9, 0xC2, 0xC2, 0xF8, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xC2, 0xC2, 0xC2, - 0xC2, 0xC2, 0xC2, 0xC2, 0x56, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0x2B, 0x2B, 0x2B, 0xF7, 0xF7, - 0xF7, 0xF7, 0xF7, 0xB9, 0x56, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0x56, 0xF9, - 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0x81, 0xFA, 0x81, 0xC2, 0xC2, 0xC2, 0xF6, 0xF6, 0xF7, 0x2B, 0x2B, - 0x2B, 0xF8, 0xF8, 0xF8, 0xF9, 0xFA, 0x81, 0xFB, 0xC2, 0xC2, 0xF5, 0xF7, 0x93, 0xF7, 0xF7, 0xF7, - 0xF7, 0x2B, 0x2B, 0x2B, 0x2B, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xF5, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, - 0xF9, 0xFB, 0xFB, 0xF9, 0xF7, 0xFB, 0x81, 0xFB, 0xC2, 0xF6, 0xF8, 0xF9, 0x2B, 0xF9, 0x2B, 0xF9, - 0xF6, 0xF8, 0x2B, 0xF8, 0xF7, 0xFB, 0xFB, 0xC2, 0xF9, 0xF7, 0xF9, 0xF7, 0xF9, 0xF7, 0xF9, 0x2B, - 0xF9, 0x2B, 0xF8, 0x2B, 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF9, 0xF9, 0xF9, - 0xF9, 0xF9, 0xF9, 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0xD8, - 0x00, 0x00, 0x08, 0xD8, 0x00, 0x00, 0x00, 0x96, 0x02, 0x1C, 0xC1, 0xC4, 0x18, 0x9C, 0x00, 0x00, - 0x00, 0x1C, 0x00, 0x96, 0x00, 0x05, 0x69, 0x63, 0x6C, 0x34, 0x00, 0x00, 0x00, 0x32, 0x69, 0x63, - 0x6C, 0x38, 0x00, 0x00, 0x00, 0x3E, 0x49, 0x43, 0x4E, 0x23, 0x00, 0x00, 0x00, 0x4A, 0x69, 0x63, - 0x73, 0x23, 0x00, 0x00, 0x00, 0x56, 0x69, 0x63, 0x73, 0x34, 0x00, 0x00, 0x00, 0x62, 0x69, 0x63, - 0x73, 0x38, 0x00, 0x00, 0x00, 0x6E, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, - 0xE2, 0x10, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x04, 0x02, 0x1C, 0xE1, 0xAC, 0xBF, 0xB9, - 0xFF, 0xFF, 0x00, 0x00, 0x06, 0x08, 0x02, 0x1C, 0xE1, 0xA4, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, - 0x07, 0x0C, 0x02, 0x1C, 0xE1, 0xF8, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0x50, 0x02, 0x1C, - 0xE1, 0xDC, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0xD4, 0x02, 0x1C, 0xE1, 0xD0 -}; - -static bool use_streams[ 'Z'-'A'+1 ]; - -static bool is_ntfs_volume(LPCTSTR rootdir) -{ - bool ret = false; - TCHAR tst_file[_MAX_PATH], tst_stream[_MAX_PATH]; - _sntprintf( tst_file, lengthof(tst_file), TEXT("%sb2query.tmp"), rootdir ); - _sntprintf( tst_stream, lengthof(tst_stream), TEXT("%s:AFP_AfpInfo"), tst_file ); - if(!exists(tst_file)) { - if(create_file( tst_file, 0 )) { - if(create_file( tst_stream, 0 )) { - ret = true; - } - DeleteFile( tst_file ); - } - } - return ret; -} - - -// !!UNC -void init_posix_emu(void) -{ - if(!validate_stat_struct) { - ErrorAlert( "Invalid struct my_stat -- edit posix_emu.h" ); - QuitEmulator(); - } - -#if DEBUG_EXTFS - debug_extfs = PrefsFindInt16("debugextfs"); - - debug_extfs = DB_EXTFS_LOUD; - - if(debug_extfs != DB_EXTFS_NONE) { - extfs_log_open( EXTFS_LOG_FILE_NAME ); - } -#endif - - // We cannot use ExtFS "RootPath" because of the virtual desktop. - if(PrefsFindBool("enableextfs")) { - PrefsReplaceString("extfs", ""); - } else { - PrefsRemoveItem("extfs"); - D(bug("extfs disabled by user\n")); -#if DEBUG_EXTFS - extfs_log_close(); -#endif - return; - } - - const char *extdrives = PrefsFindString("extdrives"); - - // Set up drive list. - size_t outinx = 0; - for( TCHAR letter = TEXT('A'); letter <= TEXT('Z'); letter++ ) { - if(extdrives && !strchr(extdrives,letter)) continue; - TCHAR rootdir[20]; - _sntprintf( rootdir, lengthof(rootdir), TEXT("%c:\\"), letter ); - use_streams[ letter - 'A' ] = false; - switch(GetDriveType(rootdir)) { - case DRIVE_FIXED: - case DRIVE_REMOTE: - case DRIVE_RAMDISK: - // TODO: NTFS AFP? - // fall - case DRIVE_REMOVABLE: - case DRIVE_CDROM: - if(outinx < lengthof(host_drive_list)) { - host_drive_list[outinx] = letter; - outinx += 2; - } - } - } - - // Set up virtual desktop root. - // TODO: this should be customizable. - GetModuleFileName( NULL, virtual_root, lengthof(virtual_root) ); - TCHAR *p = _tcsrchr( virtual_root, TEXT('\\') ); - if(p) { - _tcscpy( ++p, desktop_name ); - } else { - // should never happen - _sntprintf( virtual_root, lengthof(virtual_root), TEXT("C:\\%s"), desktop_name ); - } - CreateDirectory( virtual_root, 0 ); - - // Set up an icon looking like "My Computer" - // Can be overwritten just like any other folder custom icon. - if(my_access(custom_icon_name,0) != 0) { - int fd = my_creat( custom_icon_name, 0 ); - if(fd >= 0) { - my_close(fd); - fd = open_rfork( custom_icon_name, O_RDWR|O_CREAT ); - if(fd >= 0) { - my_write( fd, my_comp_icon, sizeof(my_comp_icon) ); - my_close(fd); - static uint8 host_finfo[SIZEOF_FInfo]; - uint32 finfo = Host2MacAddr(host_finfo); - get_finfo(custom_icon_name, finfo, 0, false); - WriteMacInt16(finfo + fdFlags, kIsInvisible); - set_finfo(custom_icon_name, finfo, 0, false); - get_finfo(my_computer, finfo, 0, true); - WriteMacInt16(finfo + fdFlags, ReadMacInt16(finfo + fdFlags) | kHasCustomIcon); - set_finfo(my_computer, finfo, 0, true); - } else { - my_remove(custom_icon_name); - } - } - } -} - -void final_posix_emu(void) -{ -#if DEBUG_EXTFS - extfs_log_close(); -#endif -} - -static void charset_host2mac( char *s ) -{ - int i, len=strlen(s), code; - - for( i=len-3; i>=0; i-- ) { - if( s[i] == '%' && isxdigit(s[i+1]) && isxdigit(s[i+2]) ) { - sscanf( &s[i], "%%%02X", &code ); - memmove( &s[i], &s[i+2], strlen(&s[i+2])+1 ); - s[i] = code; - } - } -} - -static void charset_mac2host( LPTSTR s ) -{ - size_t len = _tcslen(s); - - D(bug(TEXT("charset_mac2host(%s)...\n"), s)); - - for( size_t i=len; i-->0; ) { - bool convert = false; - switch( (unsigned char)s[i] ) { - // case '\r': // handled by "default" - // case '\n': - // case '\t': - case '/': - // case '\\': // Backslash is tricky -- "s" is a full path! - // case ':': - case '*': - case '?': - case '"': - case '<': - case '>': - case '|': - case '%': - convert = true; - break; - default: - if((unsigned char)s[i] < ' ') convert = true; - break; - } - if(convert) { - TCHAR sml[10]; - _sntprintf( sml, lengthof(sml), TEXT("%%%02X"), s[i] ); - memmove( &s[i+2], &s[i], (_tcslen(&s[i])+1) * sizeof(TCHAR) ); - memmove( &s[i], sml, 3 * sizeof(TCHAR) ); - } - } - D(bug(TEXT("charset_mac2host = %s\n"), s)); -} - -static void make_mask( - TCHAR *mask, - LPCTSTR dir, - LPCTSTR a1, - LPCTSTR a2 -) -{ - _tcscpy( mask, dir ); - - size_t len = _tcslen(mask); - if( len && mask[len-1] != '\\' ) _tcscat( mask, TEXT("\\") ); - - if( a1 ) _tcscat( mask, a1 ); - if( a2 ) _tcscat( mask, a2 ); -} - -// !!UNC -static LPTSTR translate( LPCTSTR path, TCHAR *buffer ) -{ - TCHAR *l = host_drive_list; - const TCHAR *p = path; - - while(*l) { - if(_totupper(p[1]) == _totupper(*l)) break; - l += _tcslen(l) + 1; - } - - if(p[0] == TEXT('\\') && *l && (p[2] == 0 || p[2] == TEXT(':') || p[2] == TEXT('\\'))) { - p += 2; - if(*p == TEXT(':')) p++; - if(*p == TEXT('\\')) p++; - _sntprintf( buffer, MAX_PATH_LENGTH, TEXT("%c:\\%s"), *l, p ); - } else { - if(*path == TEXT('\\')) { - _sntprintf( buffer, MAX_PATH_LENGTH, TEXT("%s%s"), virtual_root, path ); - } else { - int len = _tcslen(path); - if(len == 0 || path[len-1] == TEXT('\\')) { - make_mask( buffer, virtual_root, path, tstr(my_computer).get() ); - } else { - make_mask( buffer, virtual_root, path, 0 ); - } - } - } - charset_mac2host( buffer ); - - return buffer; -} - -// helpers -static void strip_trailing_bs( LPTSTR path ) -{ - size_t len = _tcslen(path); - if(len > 0 && path[len-1] == TEXT('\\')) path[len-1] = 0; -} - -#if 0 /* defined is util_windows.cpp */ -static int exists( const char *p ) -{ - WIN32_FIND_DATA fdata; - - int result = 0; - - HANDLE h = FindFirstFile( p, &fdata ); - if(h != INVALID_HANDLE_VALUE) { - result = 1; - FindClose( h ); - } - - D(bug("exists(%s) = %d\n", p, result)); - - return result; -} -#endif - -static int is_dir( LPCTSTR p ) -{ - WIN32_FIND_DATA fdata; - - int result = 0; - - HANDLE h = FindFirstFile( p, &fdata ); - if(h != INVALID_HANDLE_VALUE) { - result = (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - FindClose( h ); - } - return result; -} - -static int myRemoveDirectory( LPCTSTR source ) -{ - HANDLE fh; - WIN32_FIND_DATA FindFileData; - int ok, result = 1; - TCHAR mask[_MAX_PATH]; - - D(bug(TEXT("removing folder %s\n"), source)); - - make_mask( mask, source, TEXT("*.*"), 0 ); - - fh = FindFirstFile( mask, &FindFileData ); - ok = fh != INVALID_HANDLE_VALUE; - while(ok) { - make_mask( mask, source, FindFileData.cFileName, 0 ); - D(bug(TEXT("removing item %s\n"), mask)); - int isdir = (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - if(isdir) { - // must delete ".finf", ".rsrc" but not ".", ".." - if(_tcscmp(FindFileData.cFileName,TEXT(".")) && _tcscmp(FindFileData.cFileName,TEXT(".."))) { - result = myRemoveDirectory( mask ); - if(!result) break; - } - } else { - D(bug(TEXT("DeleteFile %s\n"), mask)); - result = DeleteFile( mask ); - if(!result) break; - } - ok = FindNextFile( fh, &FindFileData ); - } - if(fh != INVALID_HANDLE_VALUE) FindClose( fh ); - if(result) { - D(bug(TEXT("RemoveDirectory %s\n"), source)); - result = RemoveDirectory( source ); - } - return result; -} - -static void make_folders( LPCTSTR path ) -{ - TCHAR local_path[_MAX_PATH], *p; - _tcscpy( local_path, path ); - p = _tcsrchr( local_path, TEXT('\\') ); - if(p) { - *p = 0; - if(_tcslen(local_path) > 3) { - make_folders(local_path); - _tmkdir(local_path); - } - } -} - -// !!UNC -static bool is_same_drive( LPCTSTR p1, LPCTSTR p2 ) -{ - return _totupper(*p1) == _totupper(*p2); -} - -// Used when the drives are known to be different. -// Can't use MoveFileEx() etc because of the Win9x limitations. -// It would simulate CopyFile*() -- DeleteFile*() anyway -static int file_move_copy( LPCTSTR src, LPCTSTR dst, bool delete_old ) -{ - int result = 0; - my_errno = 0; - - D(bug(TEXT("file_copy %s -> %s\n"), src, dst)); - - // Fail if exists -- it's up to MacOS to move things to Trash - if(CopyFile(src,dst,TRUE)) { - if(delete_old && !DeleteFile(src)) { - result = -1; - my_errno = EACCES; - } - } else { - result = -1; - if(exists(src)) - my_errno = EACCES; - else - my_errno = ENOENT; - } - return result; -} - -static int file_move( LPCTSTR src, LPCTSTR dst ) -{ - return file_move_copy( src, dst, true ); -} - -static int file_copy( LPCTSTR src, LPCTSTR dst ) -{ - return file_move_copy( src, dst, false ); -} - -static int folder_copy( LPCTSTR folder_src, LPCTSTR folder_dst ) -{ - HANDLE fh; - WIN32_FIND_DATA FindFileData; - int ok, result = 0; - TCHAR mask[_MAX_PATH]; - - D(bug(TEXT("copying folder %s -> \n"), folder_src, folder_dst)); - - my_errno = 0; - - if(!CreateDirectory( folder_dst, 0 )) { - my_errno = EACCES; - return -1; - } - - make_mask( mask, folder_src, TEXT("*.*"), 0 ); - - fh = FindFirstFile( mask, &FindFileData ); - ok = fh != INVALID_HANDLE_VALUE; - while(ok) { - make_mask( mask, folder_src, FindFileData.cFileName, 0 ); - int isdir = (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - TCHAR target[_MAX_PATH]; - make_mask( target, folder_dst, FindFileData.cFileName, 0 ); - D(bug(TEXT("copying item %s -> %s\n"), mask, target)); - if(isdir) { - if(_tcscmp(FindFileData.cFileName,TEXT(".")) && _tcscmp(FindFileData.cFileName,TEXT(".."))) { - result = folder_copy( mask, target ); - if(result < 0) break; - } - } else { - result = file_copy( mask, target ); - if(result < 0) break; - } - ok = FindNextFile( fh, &FindFileData ); - } - if(fh != INVALID_HANDLE_VALUE) FindClose( fh ); - return result; -} - -// dir enumeration -void closedir( struct DIR *d ) -{ - DISABLE_ERRORS; - if(d) { - if(d->h != INVALID_HANDLE_VALUE && d->h != VIRTUAL_ROOT_ID) { - FindClose( d->h ); - } - delete d; - } - RESTORE_ERRORS; -} - -static int make_dentry( struct DIR *d ) -{ - int ok = 0; - - memset( &d->de, 0, sizeof(d->de) ); - if(d->h != INVALID_HANDLE_VALUE) { - if( (d->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && - *d->FindFileData.cFileName == TEXT('.')) - { - ok = 0; - } else { - strlcpy( d->de.d_name, d->FindFileData.cFileName, lengthof(d->de.d_name) ); - charset_host2mac( d->de.d_name ); - ok = 1; - } - } - return ok; -} - -struct dirent *readdir( struct DIR *d ) -{ - DISABLE_ERRORS; - - dirent *de = 0; - - if(d) { - if(d->h != INVALID_HANDLE_VALUE) { - if(d->h == VIRTUAL_ROOT_ID) { - make_dentry(d); - de = &d->de; - d->vname_list += _tcslen(d->vname_list) + 1; - if(*d->vname_list) { - _tcscpy( d->FindFileData.cFileName, d->vname_list ); - d->FindFileData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - } else { - // Out of static drive entries. Continue with other stuff. - TCHAR mask[MAX_PATH_LENGTH]; - make_mask( mask, virtual_root, TEXT("*.*"), 0 ); - d->h = FindFirstFile( mask, &d->FindFileData ); - } - } else { - int done = 0; - do { - if(make_dentry(d)) { - de = &d->de; - done = 1; - } - if(!FindNextFile( d->h, &d->FindFileData )) { - FindClose( d->h ); - d->h = INVALID_HANDLE_VALUE; - done = 1; - } - } while(!done); - } - } - } - - if(de) { - D(bug("readdir found %s\n", de->d_name)); - } - - RESTORE_ERRORS; - - return de; -} - -struct DIR *opendir( const char *path ) -{ - DISABLE_ERRORS; - auto tpath = tstr(path); - DIR *d = new DIR; - if(d) { - memset( d, 0, sizeof(DIR) ); - if(*tpath.get() == 0) { - d->vname_list = host_drive_list; - if(d->vname_list) { - d->h = VIRTUAL_ROOT_ID; - _tcscpy( d->FindFileData.cFileName, d->vname_list ); - d->FindFileData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - } else { - d->h = INVALID_HANDLE_VALUE; - } - } else { - TCHAR mask[MAX_PATH_LENGTH]; - make_mask( mask, MRP(tpath.get()), TEXT("*.*"), 0 ); - - D(bug(TEXT("opendir path=%s, mask=%s\n"), tpath.get(), mask)); - - d->h = FindFirstFile( mask, &d->FindFileData ); - if(d->h == INVALID_HANDLE_VALUE) { - delete d; - d = 0; - } - } - } - - D(bug(TEXT("opendir(%s,%s) = %08x\n"), tpath.get(), MRP(tpath.get()), d)); - - RESTORE_ERRORS; - - return d; -} - -static void dump_stat( const struct my_stat *st ) -{ - D(bug("stat: size = %ld, mode = %ld, a = %ld, m = %ld, c = %ld\n", st->st_size, st->st_mode, st->st_atime, st->st_mtime, st->st_ctime)); -} - - - -// Exported hook functions -int my_stat( const char *path, struct my_stat *st ) -{ - DISABLE_ERRORS; - - auto tpath = tstr(path); - int result; - - if(*tpath.get() == 0) { - /// virtual root - memset( st, 0, sizeof(struct my_stat) ); - st->st_mode = _S_IFDIR; - result = 0; - my_errno = 0; - } else { - result = _tstat( MRP(tpath.get()), (struct _stat *)st ); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - } - - D(bug(TEXT("stat(%s,%s) = %d\n"), tpath.get(), MRP(tpath.get()), result)); - if(result >= 0) dump_stat( st ); - RESTORE_ERRORS; - return result; -} - -int my_fstat( int fd, struct my_stat *st ) -{ - DISABLE_ERRORS; - int result = _fstat( fd, (struct _stat *)st ); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - D(bug("fstat(%d) = %d\n", fd, result)); - if(result >= 0) dump_stat( st ); - RESTORE_ERRORS; - return result; -} - -int my_open( const char *path, int mode, ... ) -{ - DISABLE_ERRORS; - int result; - auto tpath = tstr(path); - LPCTSTR p = MRP(tpath.get()); - - // Windows "open" does not handle _O_CREAT and _O_BINARY as it should - if(mode & _O_CREAT) { - if(exists(p)) { - result = _topen( p, mode & ~_O_CREAT ); - D(bug(TEXT("open-nocreat(%s,%s,%d) = %d\n"), tpath.get(), p, mode, result)); - } else { - result = _tcreat( p, _S_IWRITE|_S_IREAD ); - if(result < 0) { - make_folders(p); - result = _tcreat( p, _S_IWRITE|_S_IREAD ); - } - D(bug(TEXT("open-creat(%s,%s,%d) = %d\n"), tpath.get(), p, mode, result)); - } - } else { - result = _topen( p, mode ); - D(bug(TEXT("open(%s,%s,%d) = %d\n"), tpath.get(), p, mode, result)); - } - if(result < 0) { - my_errno = errno; - } else { - setmode(result, _O_BINARY); - my_errno = 0; - } - RESTORE_ERRORS; - return result; -} - -int my_rename( const char *old_path, const char *new_path ) -{ - DISABLE_ERRORS; - int result = -1; - auto told_path = tstr(old_path); - auto tnew_path = tstr(new_path); - LPCTSTR p_old = MRP(told_path.get()); - LPCTSTR p_new = MRP2(tnew_path.get()); - - result = my_access(old_path,0); - if(result < 0) { - // my_errno already set - } else { - if(is_same_drive(p_old,p_new)) { - result = _trename( p_old, p_new ); - if(result != 0) { // by definition, rename may also return a positive value to indicate an error - my_errno = errno; - } else { - my_errno = 0; - } - } else { - if(is_dir(p_old)) { - result = folder_copy( p_old, p_new ); - // my_errno already set - if(result >= 0) { - if(myRemoveDirectory( p_old )) { - my_errno = 0; - result = 0; - } else { - // there is no proper error code for this failure. - my_errno = EACCES; - result = -1; - } - } - } else { - result = file_move( p_old, p_new ); - // my_errno already set - } - } - } - D(bug(TEXT("rename(%s,%s,%s,%s) = %d\n"), told_path.get(), p_old, tnew_path.get(), p_new, result)); - RESTORE_ERRORS; - return result; -} - -int my_access( const char *path, int mode ) -{ - DISABLE_ERRORS; - auto tpath = tstr(path); - LPCTSTR p = MRP(tpath.get()); - WIN32_FIND_DATA fdata; - - int result; - - if(is_dir(p)) { - // access does not work for folders. - HANDLE h = FindFirstFile( p, &fdata ); - if(h != INVALID_HANDLE_VALUE) { - FindClose( h ); - if(mode == W_OK) { - if( (fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0 ) { - result = 0; - my_errno = 0; - } else { - result = -1; - my_errno = EACCES; - } - } else { - result = 0; - my_errno = 0; - } - } else { - result = -1; - my_errno = ENOENT; - } - } else { - // W_OK, F_OK are ok. - result = _taccess(p,mode); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - } - - D(bug(TEXT("access(%s,%s,%d) = %d\n"), tpath.get(), p, mode, result)); - RESTORE_ERRORS; - return result; -} - -int my_mkdir( const char *path, int mode ) -{ - DISABLE_ERRORS; - auto tpath = tstr(path); - LPTSTR p = MRP(tpath.get()); - strip_trailing_bs(p); - int result = _tmkdir( p ); - if(result < 0) { - make_folders(p); - result = _tmkdir( p ); - } - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - D(bug(TEXT("mkdir(%s,%s,%d) = %d\n"), tpath.get(), p, mode, result)); - RESTORE_ERRORS; - return result; -} - -int my_remove( const char *path ) -{ - DISABLE_ERRORS; - auto tpath = tstr(path); - LPTSTR p = MRP(tpath.get()); - strip_trailing_bs(p); - int result; - if(is_dir(p)) { - result = myRemoveDirectory( p ); - } else { - D(bug(TEXT("DeleteFile %s\n"), p)); - result = DeleteFile( p ); - } - if(result) { - result = 0; - my_errno = 0; - } else { - result = -1; - if(exists(p)) { - my_errno = EACCES; - } else { - my_errno = ENOENT; - } - } - D(bug(TEXT("remove(%s,%s) = %d\n"), tpath.get(), p, result)); - RESTORE_ERRORS; - return result; -} - -int my_creat( const char *path, int mode ) -{ - DISABLE_ERRORS; - auto tpath = tstr(path); - LPCTSTR p = MRP(tpath.get()); - int result = _tcreat( p, _S_IWRITE|_S_IREAD ); // note mode - if(result < 0) { - make_folders(p); - result = _tcreat( p, _S_IWRITE|_S_IREAD ); // note mode - } - if(result < 0) { - my_errno = errno; - } else { - setmode(result, _O_BINARY); - my_errno = 0; - } - D(bug(TEXT("creat(%s,%s,%d) = %d\n"), tpath.get(), p, mode,result)); - RESTORE_ERRORS; - return result; -} - -int my_chsize( int fd, size_t sz ) -{ - DISABLE_ERRORS; - int result = chsize(fd,sz); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - RESTORE_ERRORS; - return result; -} - -int my_close( int fd ) -{ - DISABLE_ERRORS; - int result = close(fd); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - RESTORE_ERRORS; - D(bug("close(%d) = %d\n", fd, result)); - return result; -} - -long my_lseek( int fd, long offset, int origin ) -{ - DISABLE_ERRORS; - int result = lseek( fd, offset, origin ); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - RESTORE_ERRORS; - return result; -} - -int my_read( int fd, void *buffer, unsigned int count ) -{ - DISABLE_ERRORS; - int result = read( fd, buffer, count ); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - RESTORE_ERRORS; - D(bug("read(%ld,%08x,%ld) = %d\n", fd, buffer, count, result)); - - return result; -} - -int my_write( int fd, const void *buffer, unsigned int count ) -{ - DISABLE_ERRORS; - int result = write( fd, buffer, count ); - if(result < 0) { - my_errno = errno; - } else { - my_errno = 0; - } - RESTORE_ERRORS; - D(bug("write(%ld,%08x,%ld) = %d\n", fd, buffer, count, result)); - return result; -} diff --git a/BasiliskII/src/Windows/posix_emu.h b/BasiliskII/src/Windows/posix_emu.h deleted file mode 100755 index f5077558..00000000 --- a/BasiliskII/src/Windows/posix_emu.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * posix_emu.h - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include "extfs.h" - -void init_posix_emu(void); -void final_posix_emu(void); - -typedef struct dirent { - char d_name[MAX_PATH_LENGTH]; -} dirent; - -typedef struct DIR { - HANDLE h; - WIN32_FIND_DATA FindFileData; - dirent de; - TCHAR *vname_list; -} DIR; - -// emulated -DIR *opendir( const char *path ); -void closedir( DIR *d ); -struct dirent *readdir( DIR *d ); - -// access() mode: exists? -#ifndef F_OK -#define F_OK 0 -#endif -// access() mode: can do r/w? -#ifndef W_OK -#define W_OK 6 -#endif - -// hook stat functions to create virtual desktop -// because of errno all used funcs must be hooked. -int my_stat( const char *, struct my_stat * ); -int my_fstat( int, struct my_stat * ); -int my_open( const char *, int, ... ); -int my_rename( const char *, const char * ); -int my_access( const char *, int ); -int my_mkdir( const char *path, int mode ); -int my_remove( const char * ); -int my_creat( const char *path, int mode ); -int my_creat( const char *path, int mode ); -int my_close( int fd ); -long my_lseek( int fd, long, int); -int my_read( int fd, void *, unsigned int); -int my_write( int fd, const void *, unsigned int); -int my_chsize( int fd, unsigned int size ); -int my_locking( int fd, int mode, long nbytes ); - -extern int my_errno; - -// must hook all other functions that manipulate file names -#ifndef NO_POSIX_API_HOOK -#define stat my_stat -#define fstat my_fstat -#define open my_open -#define rename my_rename -#define access my_access -#define mkdir my_mkdir -#define remove my_remove -#define creat my_creat -#define close my_close -#define lseek my_lseek -#define read my_read -#define write my_write -#define ftruncate my_chsize -#define locking my_locking - -#undef errno -#define errno my_errno -#endif //!NO_POSIX_API_HOOK - -#ifndef S_ISDIR -#define S_ISDIR(stat_mode) (((stat_mode) & _S_IFDIR) != 0) -#endif - -// can't #define "stat" unless there's a replacement for "struct stat" -struct my_stat { - _dev_t st_dev; - _ino_t st_ino; - unsigned short st_mode; - short st_nlink; - short st_uid; - short st_gid; - _dev_t st_rdev; - _off_t st_size; - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -}; - -// Your compiler may have different "struct stat" -> edit "struct my_stat" -#define validate_stat_struct ( sizeof(struct my_stat) == sizeof(struct stat) ) - -#define st_crtime st_ctime diff --git a/BasiliskII/src/Windows/prefs_editor_gtk.cpp b/BasiliskII/src/Windows/prefs_editor_gtk.cpp deleted file mode 100644 index a659c4e0..00000000 --- a/BasiliskII/src/Windows/prefs_editor_gtk.cpp +++ /dev/null @@ -1,1769 +0,0 @@ -/* - * prefs_editor_gtk.cpp - Preferences editor, Unix implementation using GTK+ - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include - -#include "user_strings.h" -#include "version.h" -#include "cdrom.h" -#include "xpram.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "util_windows.h" -#include "b2ether/inc/b2ether_hl.h" - - -// Global variables -static GtkWidget *win; // Preferences window -static bool start_clicked = true; // Return value of PrefsEditor() function - - -// Prototypes -static void create_volumes_pane(GtkWidget *top); -static void create_scsi_pane(GtkWidget *top); -static void create_graphics_pane(GtkWidget *top); -static void create_input_pane(GtkWidget *top); -static void create_serial_pane(GtkWidget *top); -static void create_ethernet_pane(GtkWidget *top); -static void create_memory_pane(GtkWidget *top); -static void create_jit_pane(GtkWidget *top); -static void read_settings(void); - - -/* - * SheepShaver glue - */ - -#ifdef SHEEPSHAVER -#define DISABLE_SCSI 1 -#define PROGRAM_NAME "SheepShaver" -enum { - STR_WINDOW_LAB = STR_WINDOW_CTRL, - STR_FULLSCREEN_LAB = STR_FULLSCREEN_CTRL, - STR_SERIALA_CTRL = STR_SERPORTA_CTRL, - STR_SERIALB_CTRL = STR_SERPORTB_CTRL, -}; -#else -#define DISABLE_SCSI 1 /* XXX merge code from original Basilisk II for Windows */ -#define PROGRAM_NAME "BasiliskII" -#endif - - -/* - * Utility functions - */ - -struct opt_desc { - int label_id; - GtkSignalFunc func; -}; - -struct combo_desc { - int label_id; -}; - -struct file_req_assoc { - file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {} - GtkWidget *req; - GtkWidget *entry; -}; - -static void cb_browse_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (char *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - gtk_entry_set_text(GTK_ENTRY(assoc->entry), file); - gtk_widget_destroy(assoc->req); - delete assoc; -} - -static void cb_browse(GtkWidget *widget, void *user_data) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_BROWSE_TITLE)); - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(cb_browse_ok), new file_req_assoc(req, (GtkWidget *)user_data)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -static GtkWidget *make_browse_button(GtkWidget *entry) -{ - GtkWidget *button; - - button = gtk_button_new_with_label(GetString(STR_BROWSE_CTRL)); - gtk_widget_show(button); - gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)cb_browse, (void *)entry); - return button; -} - -static void add_menu_item(GtkWidget *menu, const char *label, GtkSignalFunc func, gpointer data = NULL) -{ - GtkWidget *item = gtk_menu_item_new_with_label(label); - gtk_widget_show(item); - gtk_signal_connect(GTK_OBJECT(item), "activate", func, data); - gtk_menu_append(GTK_MENU(menu), item); -} - -static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func) -{ - add_menu_item(menu, GetString(label_id), func, NULL); -} - -static GtkWidget *make_pane(GtkWidget *notebook, int title_id) -{ - GtkWidget *frame, *label, *box; - - frame = gtk_frame_new(NULL); - gtk_widget_show(frame); - gtk_container_border_width(GTK_CONTAINER(frame), 4); - - label = gtk_label_new(GetString(title_id)); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); - - box = gtk_vbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_container_set_border_width(GTK_CONTAINER(box), 4); - gtk_container_add(GTK_CONTAINER(frame), box); - return box; -} - -static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons) -{ - GtkWidget *bb, *button; - - bb = gtk_hbutton_box_new(); - gtk_widget_show(bb); - gtk_container_set_border_width(GTK_CONTAINER(bb), border); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE); - gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4); - gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0); - - while (buttons->label_id) { - button = gtk_button_new_with_label(GetString(buttons->label_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL); - gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0); - buttons++; - } - return bb; -} - -static GtkWidget *make_separator(GtkWidget *top) -{ - GtkWidget *sep = gtk_hseparator_new(); - gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0); - gtk_widget_show(sep); - return sep; -} - -static GtkWidget *make_table(GtkWidget *top, int x, int y) -{ - GtkWidget *table = gtk_table_new(x, y, FALSE); - gtk_widget_show(table); - gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0); - return table; -} - -static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active) -{ - GtkWidget *label, *opt, *menu; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - - while (options->label_id) { - add_menu_item(menu, options->label_id, options->func); - options++; - } - gtk_menu_set_active(GTK_MENU(menu), active); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - return menu; -} - -static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist) -{ - GtkWidget *label, *combo; - char str[32]; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - return combo; -} - -static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options) -{ - GList *glist = NULL; - while (options->label_id) { - glist = g_list_append(glist, (void *)GetString(options->label_id)); - options++; - } - - return table_make_combobox(table, row, label_id, default_value, glist); -} - -static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false) -{ - GtkWidget *box, *label, *entry, *button; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - const char *str = PrefsFindString(prefs_item); - if (str == NULL) - str = ""; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_widget_show(entry); - gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); - - button = make_browse_button(entry); - gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(entry), "chooser_button", button); - return entry; -} - -static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active) -{ - GtkWidget *box, *label, *opt, *menu; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - - while (options->label_id) { - add_menu_item(menu, options->label_id, options->func); - options++; - } - gtk_menu_set_active(GTK_MENU(menu), active); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0); - return menu; -} - -static GtkWidget *make_file_entry(GtkWidget *top, int label_id, const char *prefs_item, bool only_dirs = false) -{ - GtkWidget *box, *label, *entry; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - const char *str = PrefsFindString(prefs_item); - if (str == NULL) - str = ""; - - entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_widget_show(entry); - gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); - return entry; -} - -static const gchar *get_file_entry_path(GtkWidget *entry) -{ - return gtk_entry_get_text(GTK_ENTRY(entry)); -} - -static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func) -{ - GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id)); - gtk_widget_show(button); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item)); - gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button); - gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0); - return button; -} - -static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, GList *glist) -{ - GtkWidget *box, *label, *combo; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value); - gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0); - - return combo; -} - -static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, const combo_desc *options) -{ - GList *glist = NULL; - while (options->label_id) { - glist = g_list_append(glist, (void *)GetString(options->label_id)); - options++; - } - - return make_combobox(top, label_id, default_value, glist); -} - - -/* - * Show preferences editor - * Returns true when user clicked on "Start", false otherwise - */ - -// Window closed -static gint window_closed(void) -{ - return FALSE; -} - -// Window destroyed -static void window_destroyed(void) -{ - gtk_main_quit(); -} - -// "Start" button clicked -static void cb_start(...) -{ - start_clicked = true; - read_settings(); - SavePrefs(); - gtk_widget_destroy(win); -} - -// "Zap PRAM" button clicked -static void cb_zap_pram(...) -{ - ZapPRAM(); -} - -// "Quit" button clicked -static void cb_quit(...) -{ - start_clicked = false; - gtk_widget_destroy(win); -} - -// "OK" button of "About" dialog clicked -static void dl_quit(GtkWidget *dialog) -{ - gtk_widget_destroy(dialog); -} - -// "About" button clicked -static void cb_about(...) -{ - GtkWidget *dialog; - - GtkWidget *label, *button; - - char str[512]; - sprintf(str, - PROGRAM_NAME "\nVersion %d.%d\n\n" - "Copyright (C) 1997-2008 Christian Bauer et al.\n" - "E-mail: cb@cebix.net\n" -#ifdef SHEEPSHAVER - "http://sheepshaver.cebix.net/\n\n" -#else - "http://basilisk.cebix.net/\n\n" -#endif - PROGRAM_NAME " comes with ABSOLUTELY NO\n" - "WARRANTY. This is free software, and\n" - "you are welcome to redistribute it\n" - "under the terms of the GNU General\n" - "Public License.\n", - VERSION_MAJOR, VERSION_MINOR - ); - - dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - - label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - button = gtk_button_new_with_label(GetString(STR_OK_BUTTON)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - - gtk_widget_show(dialog); -} - -// Menu item descriptions -static GtkItemFactoryEntry menu_items[] = { - {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "S", GTK_SIGNAL_FUNC(cb_start), 0, NULL}, - {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(cb_zap_pram), 0, NULL}, - {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL}, - {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), "H", GTK_SIGNAL_FUNC(cb_about), 0, NULL} -}; - -void PrefsMigrate(void) -{ - // Ethernet - const char *ether = PrefsFindString("ether"); - if (ether && ether[0] == '{') { - PrefsReplaceString("etherguid", ether); - PrefsReplaceString("ether", "b2ether"); - } - if (PrefsFindBool("routerenabled")) { - PrefsRemoveItem("etherguid"); - PrefsReplaceString("ether", "router"); - } -} - -bool PrefsEditor(void) -{ - // Create window - win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE)); - gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL); - gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL); - - // Create window contents - GtkWidget *box = gtk_vbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_container_add(GTK_CONTAINER(win), box); - - GtkAccelGroup *accel_group = gtk_accel_group_new(); - GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "
", accel_group); - gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL); -#if GTK_CHECK_VERSION(1,3,15) - gtk_window_add_accel_group(GTK_WINDOW(win), accel_group); -#else - gtk_accel_group_attach(accel_group, GTK_OBJECT(win)); -#endif - GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "
"); - gtk_widget_show(menu_bar); - gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0); - - GtkWidget *notebook = gtk_notebook_new(); - gtk_widget_show(notebook); - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); - gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE); - gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0); - - create_volumes_pane(notebook); -#ifndef DISABLE_SCSI - create_scsi_pane(notebook); -#endif - create_graphics_pane(notebook); - create_input_pane(notebook); - create_serial_pane(notebook); - create_ethernet_pane(notebook); - create_memory_pane(notebook); - create_jit_pane(notebook); - - static const opt_desc buttons[] = { - {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)}, - {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)}, - {0, NULL} - }; - make_button_box(box, 4, buttons); - - // Show window and enter main loop - gtk_widget_show(win); - gtk_main(); - return start_clicked; -} - - -/* - * "Volumes" pane - */ - -static GtkWidget *w_enableextfs, *w_extdrives, *w_cdrom_drive; -static GtkWidget *volume_list; -static int selected_volume; - -// Set sensitivity of widgets -static void set_volumes_sensitive(void) -{ - const bool enable_extfs = PrefsFindBool("enableextfs"); - gtk_widget_set_sensitive(w_extdrives, enable_extfs); - const bool no_cdrom = PrefsFindBool("nocdrom"); - gtk_widget_set_sensitive(w_cdrom_drive, !no_cdrom); -} - -// Volume in list selected -static void cl_selected(GtkWidget *list, int row, int column) -{ - selected_volume = row; -} - -// Volume selected for addition -static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - gtk_clist_append(GTK_CLIST(volume_list), &file); - gtk_widget_destroy(assoc->req); - delete assoc; -} - -// Volume selected for creation -static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - - const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry)); - size_t size = atoi(str) << 20; - - int fd = _open(file, _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE); - if (fd >= 0) { - if (_chsize(fd, size) == 0) - gtk_clist_append(GTK_CLIST(volume_list), &file); - _close(fd); - } - gtk_widget_destroy(GTK_WIDGET(assoc->req)); - delete assoc; -} - -// "Add Volume" button clicked -static void cb_add_volume(...) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE)); - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -// "Create Hardfile" button clicked -static void cb_create_volume(...) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE)); - - GtkWidget *box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL)); - gtk_widget_show(label); - GtkWidget *entry = gtk_entry_new(); - gtk_widget_show(entry); - char str[32]; - sprintf(str, "%d", 40); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0); - - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -// "Remove Volume" button clicked -static void cb_remove_volume(...) -{ - gtk_clist_remove(GTK_CLIST(volume_list), selected_volume); -} - -// "Boot From" selected -static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);} -static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);} - -// "Enable external file system" button toggled -static void tb_enableextfs(GtkWidget *widget) -{ - PrefsReplaceBool("enableextfs", GTK_TOGGLE_BUTTON(widget)->active); - set_volumes_sensitive(); -} - -// "No CD-ROM Driver" button toggled -static void tb_nocdrom(GtkWidget *widget) -{ - PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active); - set_volumes_sensitive(); -} - -// Add names of CD-ROM devices -static GList *add_cdrom_names(void) -{ - GList *glist = NULL; - - char rootdir[4] = "X:\\"; - for (char letter = 'C'; letter <= 'Z'; letter++) { - rootdir[0] = letter; - if (GetDriveType(rootdir) == DRIVE_CDROM) - glist = g_list_append(glist, strdup(rootdir)); - } - - return glist; -} - -// "Enable polling" button toggled -static void tb_pollmedia(GtkWidget *widget) -{ - PrefsReplaceBool("pollmedia", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Read settings from widgets and set preferences -static void read_volumes_settings(void) -{ - while (PrefsFindString("disk")) - PrefsRemoveItem("disk"); - - for (int i=0; irows; i++) { - char *str; - gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str); - PrefsAddString("disk", str); - } - - const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_cdrom_drive)->entry)); - if (str && strlen(str)) - PrefsReplaceString("cdrom", str); - else - PrefsRemoveItem("cdrom"); - - PrefsReplaceString("extdrives", get_file_entry_path(w_extdrives)); -} - -// Create "Volumes" pane -static void create_volumes_pane(GtkWidget *top) -{ - GtkWidget *box, *scroll, *menu; - - box = make_pane(top, STR_VOLUMES_PANE_TITLE); - - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_show(scroll); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - volume_list = gtk_clist_new(1); - gtk_widget_show(volume_list); - gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE); - gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE); - gtk_clist_set_reorderable(GTK_CLIST(volume_list), true); - gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL); - char *str; - int32 index = 0; - while ((str = const_cast(PrefsFindString("disk", index++))) != NULL) - gtk_clist_append(GTK_CLIST(volume_list), &str); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list); - gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0); - selected_volume = 0; - - static const opt_desc buttons[] = { - {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)}, - {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)}, - {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)}, - {0, NULL}, - }; - make_button_box(box, 0, buttons); - make_separator(box); - - static const opt_desc options[] = { - {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)}, - {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)}, - {0, NULL} - }; - int bootdriver = PrefsFindInt32("bootdriver"), active = 0; - switch (bootdriver) { - case 0: active = 0; break; - case CDROMRefNum: active = 1; break; - } - menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active); - - make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom)); - - GList *glist = add_cdrom_names(); - str = const_cast(PrefsFindString("cdrom")); - if (str == NULL) - str = ""; - w_cdrom_drive = make_combobox(box, STR_CDROM_DRIVE_CTRL, str, glist); - - make_checkbox(box, STR_POLLMEDIA_CTRL, "pollmedia", GTK_SIGNAL_FUNC(tb_pollmedia)); - - make_separator(box); - w_enableextfs = make_checkbox(box, STR_EXTFS_ENABLE_CTRL, "enableextfs", GTK_SIGNAL_FUNC(tb_enableextfs)); - w_extdrives = make_file_entry(box, STR_EXTFS_DRIVES_CTRL, "extdrives", true); - - set_volumes_sensitive(); -} - - -/* - * "JIT Compiler" pane - */ - -#ifndef SHEEPSHAVER -static GtkWidget *w_jit_fpu; -static GtkWidget *w_jit_atraps; -static GtkWidget *w_jit_cache_size; -static GtkWidget *w_jit_lazy_flush; -static GtkWidget *w_jit_follow_const_jumps; -#endif - -// Set sensitivity of widgets -static void set_jit_sensitive(void) -{ -#ifndef SHEEPSHAVER - const bool jit_enabled = PrefsFindBool("jit"); - gtk_widget_set_sensitive(w_jit_fpu, jit_enabled); - gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled); - gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled); - gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled); -#endif -} - -// "Use JIT Compiler" button toggled -static void tb_jit(GtkWidget *widget) -{ - PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active); - set_jit_sensitive(); -} - -// "Compile FPU Instructions" button toggled -#ifndef SHEEPSHAVER -static void tb_jit_fpu(GtkWidget *widget) -{ - PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// "Lazy translation cache invalidation" button toggled -#ifndef SHEEPSHAVER -static void tb_jit_lazy_flush(GtkWidget *widget) -{ - PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// "Translate through constant jumps (inline blocks)" button toggled -#ifndef SHEEPSHAVER -static void tb_jit_follow_const_jumps(GtkWidget *widget) -{ - PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// Read settings from widgets and set preferences -static void read_jit_settings(void) -{ -#if USE_JIT - bool jit_enabled = PrefsFindBool("jit"); - if (jit_enabled) { -#ifndef SHEEPSHAVER - const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry)); - PrefsReplaceInt32("jitcachesize", atoi(str)); -#endif - } -#endif -} - -// "Use built-in 68k DR emulator" button toggled -#ifdef SHEEPSHAVER -static void tb_jit_68k(GtkWidget *widget) -{ - PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// Create "JIT Compiler" pane -static void create_jit_pane(GtkWidget *top) -{ -#if USE_JIT - GtkWidget *box, *table, *label, *menu; - char str[32]; - - box = make_pane(top, STR_JIT_PANE_TITLE); - make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit)); - -#ifndef SHEEPSHAVER - w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu)); - - // Translation cache size - static const combo_desc options[] = { - STR_JIT_CACHE_SIZE_2MB_LAB, - STR_JIT_CACHE_SIZE_4MB_LAB, - STR_JIT_CACHE_SIZE_8MB_LAB, - STR_JIT_CACHE_SIZE_16MB_LAB, - 0 - }; - sprintf(str, "%d", PrefsFindInt32("jitcachesize")); - w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, str, options); - - // Lazy translation cache invalidation - w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush)); - - // Follow constant jumps (inline basic blocks) - w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps)); -#endif - - set_jit_sensitive(); -#endif - -#ifdef SHEEPSHAVER - make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k)); -#endif -} - -/* - * "SCSI" pane - */ - -static GtkWidget *w_scsi[7]; - -// Read settings from widgets and set preferences -static void read_scsi_settings(void) -{ -#ifndef DISABLE_SCSI - for (int id=0; id<7; id++) { - char prefs_name[32]; - sprintf(prefs_name, "scsi%d", id); - const char *str = get_file_entry_path(w_scsi[id]); - if (str && strlen(str)) - PrefsReplaceString(prefs_name, str); - else - PrefsRemoveItem(prefs_name); - } -#endif -} - -// Create "SCSI" pane -static void create_scsi_pane(GtkWidget *top) -{ -#ifndef DISABLE_SCSI - GtkWidget *box; - - box = make_pane(top, STR_SCSI_PANE_TITLE); - - for (int id=0; id<7; id++) { - char prefs_name[32]; - sprintf(prefs_name, "scsi%d", id); - w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name); - } -#endif -} - - -/* - * "Graphics/Sound" pane - */ - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_SCREEN -}; - -static GtkWidget *w_frameskip, *w_display_x, *w_display_y; -static GtkWidget *l_frameskip, *l_display_x, *l_display_y; -static int display_type; -static int dis_width, dis_height; - -// Hide/show graphics widgets -static void hide_show_graphics_widgets(void) -{ - switch (display_type) { - case DISPLAY_WINDOW: - gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip); - break; - case DISPLAY_SCREEN: - gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip); - break; - } -} - -// "Window" video type selected -static void mn_window(...) -{ - display_type = DISPLAY_WINDOW; - hide_show_graphics_widgets(); -} - -// "Fullscreen" video type selected -static void mn_fullscreen(...) -{ - display_type = DISPLAY_SCREEN; - hide_show_graphics_widgets(); - PrefsReplaceInt32("frameskip", 1); -} - -// "5 Hz".."60Hz" selected -static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);} -static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);} -static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);} -static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);} -static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);} -static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);} -static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);} - -// QuickDraw acceleration -#ifdef SHEEPSHAVER -static void tb_gfxaccel(GtkWidget *widget) -{ - PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// Set sensitivity of widgets -static void set_graphics_sensitive(void) -{ - const bool sound_enabled = !PrefsFindBool("nosound"); -} - -// "Disable Sound Output" button toggled -static void tb_nosound(GtkWidget *widget) -{ - PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active); - set_graphics_sensitive(); -} - -// Read graphics preferences -static void parse_graphics_prefs(void) -{ - display_type = DISPLAY_WINDOW; -#ifdef SHEEPSHAVER - dis_width = 640; - dis_height = 480; -#else - dis_width = 512; - dis_height = 384; -#endif - - const char *str = PrefsFindString("screen"); - if (str) { - if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2) - display_type = DISPLAY_WINDOW; - else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2) - display_type = DISPLAY_SCREEN; - } -} - -// Read settings from widgets and set preferences -static void read_graphics_settings(void) -{ - const char *str; - - str = gtk_entry_get_text(GTK_ENTRY(w_display_x)); - dis_width = atoi(str); - - str = gtk_entry_get_text(GTK_ENTRY(w_display_y)); - dis_height = atoi(str); - - char pref[256]; - switch (display_type) { - case DISPLAY_WINDOW: - sprintf(pref, "win/%d/%d", dis_width, dis_height); - break; - case DISPLAY_SCREEN: - sprintf(pref, "dga/%d/%d", dis_width, dis_height); - break; - default: - PrefsRemoveItem("screen"); - return; - } - PrefsReplaceString("screen", pref); -} - -// Create "Graphics/Sound" pane -static void create_graphics_pane(GtkWidget *top) -{ - GtkWidget *box, *table, *label, *opt, *menu, *combo; - char str[32]; - - parse_graphics_prefs(); - - box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE); - table = make_table(box, 2, 5); - - label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - add_menu_item(menu, STR_WINDOW_LAB, GTK_SIGNAL_FUNC(mn_window)); - add_menu_item(menu, STR_FULLSCREEN_LAB, GTK_SIGNAL_FUNC(mn_fullscreen)); - switch (display_type) { - case DISPLAY_WINDOW: - gtk_menu_set_active(GTK_MENU(menu), 0); - break; - case DISPLAY_SCREEN: - gtk_menu_set_active(GTK_MENU(menu), 1); - break; - } - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - - l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL)); - gtk_widget_show(l_frameskip); - gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - w_frameskip = gtk_option_menu_new(); - gtk_widget_show(w_frameskip); - menu = gtk_menu_new(); - add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz)); - add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz)); - add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz)); - add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz)); - add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz)); - add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz)); - add_menu_item(menu, STR_REF_DYNAMIC_LAB, GTK_SIGNAL_FUNC(mn_dynamic)); - int frameskip = PrefsFindInt32("frameskip"); - int item = -1; - switch (frameskip) { - case 12: item = 0; break; - case 8: item = 1; break; - case 6: item = 2; break; - case 4: item = 3; break; - case 2: item = 4; break; - case 1: item = 5; break; - case 0: item = 6; break; - } - if (item >= 0) - gtk_menu_set_active(GTK_MENU(menu), item); - gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu); - gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - - l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL)); - gtk_widget_show(l_display_x); - gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - GList *glist1 = NULL; - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB)); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1); - if (dis_width) - sprintf(str, "%d", dis_width); - else - strcpy(str, GetString(STR_SIZE_MAX_LAB)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - w_display_x = GTK_COMBO(combo)->entry; - - l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL)); - gtk_widget_show(l_display_y); - gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - GList *glist2 = NULL; - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB)); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2); - if (dis_height) - sprintf(str, "%d", dis_height); - else - strcpy(str, GetString(STR_SIZE_MAX_LAB)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - w_display_y = GTK_COMBO(combo)->entry; - -#ifdef SHEEPSHAVER - make_checkbox(box, STR_GFXACCEL_CTRL, "gfxaccel", GTK_SIGNAL_FUNC(tb_gfxaccel)); -#endif - - make_separator(box); - make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound)); - - set_graphics_sensitive(); - - hide_show_graphics_widgets(); -} - - -/* - * "Input" pane - */ - -static GtkWidget *w_keycode_file; -static GtkWidget *w_mouse_wheel_lines; - -// Set sensitivity of widgets -static void set_input_sensitive(void) -{ - const bool use_keycodes = PrefsFindBool("keycodes"); - gtk_widget_set_sensitive(w_keycode_file, use_keycodes); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes); - gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1); -} - -// "Use Raw Keycodes" button toggled -static void tb_keycodes(GtkWidget *widget) -{ - PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active); - set_input_sensitive(); -} - -// "Mouse Wheel Mode" selected -static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();} -static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();} - -// Read settings from widgets and set preferences -static void read_input_settings(void) -{ - const char *str = get_file_entry_path(w_keycode_file); - if (str && strlen(str)) - PrefsReplaceString("keycodefile", str); - else - PrefsRemoveItem("keycodefile"); - - PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines))); -} - -// Create "Input" pane -static void create_input_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *menu, *label, *button; - GtkObject *adj; - - box = make_pane(top, STR_INPUT_PANE_TITLE); - - make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes)); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_KEYCODES_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - const char *str = PrefsFindString("keycodefile"); - if (str == NULL) - str = ""; - - w_keycode_file = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str); - gtk_widget_show(w_keycode_file); - gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0); - - button = make_browse_button(w_keycode_file); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button); - - make_separator(box); - - static const opt_desc options[] = { - {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)}, - {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)}, - {0, NULL} - }; - int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0; - switch (wheelmode) { - case 0: active = 0; break; - case 1: active = 1; break; - } - menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0); - w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0); - gtk_widget_show(w_mouse_wheel_lines); - gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0); - - set_input_sensitive(); -} - - -/* - * "Serial" pane - */ - -static GtkWidget *w_seriala, *w_portfile0; -static GtkWidget *w_serialb, *w_portfile1; - -// Set sensitivity of widgets -static void set_serial_sensitive(void) -{ - const char *str; - bool is_file; - - str = gtk_entry_get_text(GTK_ENTRY(w_seriala)); - is_file = strcmp(str, "FILE") == 0; - gtk_widget_set_sensitive(w_portfile0, is_file); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile0), "chooser_button")), is_file); - - str = gtk_entry_get_text(GTK_ENTRY(w_serialb)); - is_file = strcmp(str, "FILE") == 0; - gtk_widget_set_sensitive(w_portfile1, is_file); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile1), "chooser_button")), is_file); -} - -// Read settings from widgets and set preferences -static void read_serial_settings(void) -{ - const char *str; - - str = gtk_entry_get_text(GTK_ENTRY(w_seriala)); - PrefsReplaceString("seriala", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_serialb)); - PrefsReplaceString("serialb", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_portfile0)); - PrefsReplaceString("portfile0", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_portfile1)); - PrefsReplaceString("portfile1", str); -} - -// Port changed in combo -static void cb_serial_port_changed(...) -{ - set_serial_sensitive(); -} - -// Add names of serial devices -static GList *add_serial_names(void) -{ - GList *glist = NULL; - - static const char *port_names[] = { - "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", - "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", - "FILE", - NULL - }; - - for (int i = 0; port_names[i] != NULL; i++) - glist = g_list_append(glist, (void *)port_names[i]); - - return glist; -} - -// Create "Serial" pane -static void create_serial_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *table, *label, *combo, *sep, *entry; - GtkObject *adj; - - box = make_pane(top, STR_SERIAL_PANE_TITLE); - table = make_table(box, 2, 5); - - GList *glist = add_serial_names(); - const char *str = PrefsFindString("seriala"); - combo = table_make_combobox(table, 0, STR_SERIALA_CTRL, str, glist); - w_seriala = GTK_COMBO(combo)->entry; - gtk_signal_connect(GTK_OBJECT(w_seriala), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL); - - w_portfile0 = table_make_file_entry(table, 1, STR_FILE_CTRL, "portfile0"); - - sep = gtk_hseparator_new(); - gtk_widget_show(sep); - gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - str = PrefsFindString("serialb"); - combo = table_make_combobox(table, 3, STR_SERIALB_CTRL, str, glist); - w_serialb = GTK_COMBO(combo)->entry; - gtk_signal_connect(GTK_OBJECT(w_serialb), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL); - - w_portfile1 = table_make_file_entry(table, 4, STR_FILE_CTRL, "portfile1"); - - set_serial_sensitive(); -} - - -/* - * "Ethernet" pane - */ - -static GtkWidget *w_ftp_port_list, *w_tcp_port_list; - -// Set sensitivity of widgets -static void set_ethernet_sensitive(void) -{ - const char *str = PrefsFindString("ether"); - - bool is_router = str && strcmp(str, "router") == 0; - gtk_widget_set_sensitive(w_ftp_port_list, is_router); - gtk_widget_set_sensitive(w_tcp_port_list, is_router); -} - -// Read settings from widgets and set preferences -static void read_ethernet_settings(void) -{ - const char *str = PrefsFindString("ether"); - - bool is_router = str && strcmp(str, "router") == 0; - if (is_router) { - str = gtk_entry_get_text(GTK_ENTRY(w_ftp_port_list)); - PrefsReplaceString("ftp_port_list", str); - str = gtk_entry_get_text(GTK_ENTRY(w_tcp_port_list)); - PrefsReplaceString("tcp_port", str); - } -} - -// Ethernet emulation type changed in menulist -static void cb_ether_changed(...) -{ - set_ethernet_sensitive(); -} - -// Ethernet option "None" selected -static void mn_ether_none(void) -{ - PrefsRemoveItem("ether"); - PrefsRemoveItem("etherguid"); -} - -// Ethernet option "Basilisk II Router" selected -static void mn_ether_router(void) -{ - PrefsReplaceString("ether", "router"); - PrefsRemoveItem("etherguid"); -} - -// Ethernet option "Basilisk II Slirp" selected -static void mn_ether_slirp(void) -{ - PrefsReplaceString("ether", "slirp"); - PrefsRemoveItem("etherguid"); -} - -// Ethernet option for Basilisk II driver selected -static void mn_ether_b2ether(GtkWidget *, const char *guid) -{ - PrefsReplaceString("ether", "b2ether"); - PrefsReplaceString("etherguid", guid); -} - -// Ethernet option for Basilisk II driver selected -static void mn_ether_tap(GtkWidget *, const char *guid) -{ - PrefsReplaceString("ether", "tap"); - PrefsReplaceString("etherguid", guid); -} - -// Create ethernet interfaces menu -static int create_ether_menu(GtkWidget *menu) -{ - int active = -1; - int n_items = 0; - const char *ether = PrefsFindString("ether"); - const char *etherguid = PrefsFindString("etherguid"); - - // No Ethernet - add_menu_item(menu, STR_NONE_LAB, (GtkSignalFunc)mn_ether_none); - if (ether == NULL) - active = n_items; - n_items++; - - // Basilisk II Router - add_menu_item(menu, "Basilisk II Router", (GtkSignalFunc)mn_ether_router); - if (ether && strcmp(ether, "router") == 0) - active = n_items; - n_items++; - - // Basilisk II Slirp - add_menu_item(menu, "Basilisk II Slirp", (GtkSignalFunc)mn_ether_slirp); - if (ether && strcmp(ether, "slirp") == 0) - active = n_items; - n_items++; - - // Basilisk II Ethernet Adapter - PacketOpenAdapter("", 0); - { - ULONG sz; - char names[1024]; - sz = sizeof(names); - if (PacketGetAdapterNames(NULL, names, &sz) == ERROR_SUCCESS) { - char *p = names; - while (*p) { - const char DEVICE_HEADER[] = "\\Device\\B2ether_"; - if (strnicmp(p, DEVICE_HEADER, sizeof(DEVICE_HEADER) - 1) == 0) { - LPADAPTER fd = PacketOpenAdapter(p + sizeof(DEVICE_HEADER) - 1, 0); - if (fd) { - char guid[256]; - sprintf(guid, "%s", p + sizeof(DEVICE_HEADER) - 1); - const char *name = ether_guid_to_name(guid); - if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) { - add_menu_item(menu, name, (GtkSignalFunc)mn_ether_b2ether, strdup(guid)); - if (etherguid && strcmp(guid, etherguid) == 0 && - ether && strcmp(ether, "b2ether") == 0) - active = n_items; - n_items++; - } - PacketCloseAdapter(fd); - } - } - p += strlen(p) + 1; - } - } - } - PacketCloseAdapter(NULL); - - // TAP-Win32 - const char *tap_devices; - if ((tap_devices = ether_tap_devices()) != NULL) { - const char *guid = tap_devices; - while (*guid) { - const char *name = ether_guid_to_name(guid); - if (name && (name = g_locale_to_utf8(name, -1, NULL, NULL, NULL))) { - add_menu_item(menu, name, (GtkSignalFunc)mn_ether_tap, strdup(guid)); - if (etherguid && strcmp(guid, etherguid) == 0 && - ether && strcmp(ether, "tap") == 0) - active = n_items; - n_items++; - } - guid += strlen(guid) + 1; - } - free((char *)tap_devices); - } - - return active; -} - -// Create "Ethernet" pane -static void create_ethernet_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *table, *label, *sep, *entry, *opt, *menu, *item; - - box = make_pane(top, STR_NETWORK_PANE_TITLE); - table = make_table(box, 2, 5); - - label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - int active = create_ether_menu(menu); - if (active >= 0) - gtk_menu_set_active(GTK_MENU(menu), active); - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - gtk_signal_connect(GTK_OBJECT(opt), "changed", GTK_SIGNAL_FUNC(cb_ether_changed), NULL); - - sep = gtk_hseparator_new(); - gtk_widget_show(sep); - gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - label = gtk_label_new(GetString(STR_ETHER_FTP_PORT_LIST_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - entry = gtk_entry_new(); - const char *str = PrefsFindString("ftp_port_list"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_widget_show(entry); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_ftp_port_list = entry; - - label = gtk_label_new(GetString(STR_ETHER_TCP_PORT_LIST_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - entry = gtk_entry_new(); - str = PrefsFindString("tcp_port"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_widget_show(entry); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_tcp_port_list = entry; - - set_ethernet_sensitive(); -} - - -/* - * "Memory/Misc" pane - */ - -static GtkWidget *w_ramsize; -static GtkWidget *w_rom_file; - -// Don't use CPU when idle? -static void tb_idlewait(GtkWidget *widget) -{ - PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active); -} - -// "Ignore SEGV" button toggled -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION -static void tb_ignoresegv(GtkWidget *widget) -{ - PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active); -} -#endif - -// Model ID selected -static void mn_modelid_5(...) {PrefsReplaceInt32("modelid", 5);} -static void mn_modelid_14(...) {PrefsReplaceInt32("modelid", 14);} - -// CPU/FPU type -static void mn_cpu_68020(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", false);} -static void mn_cpu_68020_fpu(...) {PrefsReplaceInt32("cpu", 2); PrefsReplaceBool("fpu", true);} -static void mn_cpu_68030(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", false);} -static void mn_cpu_68030_fpu(...) {PrefsReplaceInt32("cpu", 3); PrefsReplaceBool("fpu", true);} -static void mn_cpu_68040(...) {PrefsReplaceInt32("cpu", 4); PrefsReplaceBool("fpu", true);} - -// Read settings from widgets and set preferences -static void read_memory_settings(void) -{ - const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry)); - PrefsReplaceInt32("ramsize", atoi(str) << 20); - - str = get_file_entry_path(w_rom_file); - if (str && strlen(str)) - PrefsReplaceString("rom", str); - else - PrefsRemoveItem("rom"); - -} - -// Create "Memory/Misc" pane -static void create_memory_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *table, *label, *scale, *menu; - - box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE); - table = make_table(box, 2, 5); - - static const combo_desc options[] = { -#ifndef SHEEPSHAVER - STR_RAMSIZE_2MB_LAB, -#endif - STR_RAMSIZE_4MB_LAB, - STR_RAMSIZE_8MB_LAB, - STR_RAMSIZE_16MB_LAB, - STR_RAMSIZE_32MB_LAB, - STR_RAMSIZE_64MB_LAB, - STR_RAMSIZE_128MB_LAB, - STR_RAMSIZE_256MB_LAB, - STR_RAMSIZE_512MB_LAB, - STR_RAMSIZE_1024MB_LAB, - 0 - }; - char default_ramsize[16]; - sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20); - w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options); - -#ifndef SHEEPSHAVER - static const opt_desc model_options[] = { - {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)}, - {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)}, - {0, NULL} - }; - int modelid = PrefsFindInt32("modelid"), active = 0; - switch (modelid) { - case 5: active = 0; break; - case 14: active = 1; break; - } - table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active); -#endif - -#if EMULATED_68K - static const opt_desc cpu_options[] = { - {STR_CPU_68020_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020)}, - {STR_CPU_68020_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68020_fpu)}, - {STR_CPU_68030_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030)}, - {STR_CPU_68030_FPU_LAB, GTK_SIGNAL_FUNC(mn_cpu_68030_fpu)}, - {STR_CPU_68040_LAB, GTK_SIGNAL_FUNC(mn_cpu_68040)}, - {0, NULL} - }; - int cpu = PrefsFindInt32("cpu"); - bool fpu = PrefsFindBool("fpu"); - active = 0; - switch (cpu) { - case 2: active = fpu ? 1 : 0; break; - case 3: active = fpu ? 3 : 2; break; - case 4: active = 4; - } - table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active); -#endif - - w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom"); - - make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait)); - -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv)); -#endif -} - - -/* - * Read settings from widgets and set preferences - */ - -static void read_settings(void) -{ - read_volumes_settings(); - read_scsi_settings(); - read_graphics_settings(); - read_input_settings(); - read_serial_settings(); - read_ethernet_settings(); - read_memory_settings(); - read_jit_settings(); -} - - -/* - * Fake unused data and functions - */ - -uint8 XPRAM[XPRAM_SIZE]; -void MountVolume(void *fh) { } -void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { } -void recycle_write_packet(LPPACKET) { } -VOID CALLBACK packet_read_completion(DWORD, DWORD, LPOVERLAPPED) { } - - -/* - * Add default serial prefs (must be added, even if no ports present) - */ - -void SysAddSerialPrefs(void) -{ - PrefsAddString("seriala", "COM1"); - PrefsAddString("serialb", "COM2"); -} - - -/* - * Display alerts - */ - -static void display_alert(int title_id, const char *text, int flags) -{ - MessageBox(NULL, text, GetString(title_id), MB_OK | flags); -} - -void ErrorAlert(const char *text) -{ - display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP); -} - -void WarningAlert(const char *text) -{ - display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONSTOP); -} - - -/* - * Start standalone GUI - */ - -int main(int argc, char *argv[]) -{ - // Init GTK - gtk_set_locale(); - gtk_init(&argc, &argv); - - // Read preferences - PrefsInit(NULL, argc, argv); - - // Migrate preferences - PrefsMigrate(); - - // Show preferences editor - bool start = PrefsEditor(); - - // Exit preferences - PrefsExit(); - - // Transfer control to the executable - if (start) { - char path[_MAX_PATH]; - bool ok = GetModuleFileName(NULL, path, sizeof(path)) != 0; - if (ok) { - char b2_path[_MAX_PATH]; - char *p = strrchr(path, '\\'); - *++p = '\0'; - SetCurrentDirectory(path); - strcpy(b2_path, path); - strcat(b2_path, PROGRAM_NAME); - strcat(b2_path, ".exe"); - HINSTANCE h = ShellExecute(GetDesktopWindow(), "open", - b2_path, "", path, SW_SHOWNORMAL); - if ((int)h <= 32) - ok = false; - } - if (!ok) { - ErrorAlert("Coult not start " PROGRAM_NAME " executable"); - return 1; - } - } - - return 0; -} diff --git a/BasiliskII/src/Windows/prefs_windows.cpp b/BasiliskII/src/Windows/prefs_windows.cpp deleted file mode 100755 index ed837b86..00000000 --- a/BasiliskII/src/Windows/prefs_windows.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * prefs_windows.cpp - Preferences handling, Windows specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include - -#include -typedef std::basic_string tstring; - -#include "prefs.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { - {"keycodes", TYPE_BOOLEAN, false, "use keycodes rather than keysyms to decode keyboard"}, - {"keycodefile", TYPE_STRING, false, "path of keycode translation file"}, - {"mousewheelmode", TYPE_INT32, false, "mouse wheel support mode (0=page up/down, 1=cursor up/down)"}, - {"mousewheellines", TYPE_INT32, false, "number of lines to scroll in mouse wheel mode 1"}, -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - {"ignoresegv", TYPE_BOOLEAN, false, "ignore illegal memory accesses"}, -#endif - {"idlewait", TYPE_BOOLEAN, false, "sleep when idle"}, - {"enableextfs", TYPE_BOOLEAN, false, "enable extfs system"}, - {"debugextfs", TYPE_BOOLEAN, false, "debug extfs system"}, - {"extdrives", TYPE_STRING, false, "define allowed extfs drives"}, - {"pollmedia", TYPE_BOOLEAN, false, "poll for new media (e.g. cd, floppy)"}, - {"etherguid", TYPE_STRING, false, "GUID of the ethernet device to use"}, - {"etherpermanentaddress", TYPE_BOOLEAN, false, "use permanent NIC address to identify itself"}, - {"ethermulticastmode", TYPE_INT32, false, "how to multicast packets"}, - {"etherfakeaddress", TYPE_STRING, false, "optional fake hardware address"}, - {"routerenabled", TYPE_BOOLEAN, false, "enable NAT/Router module"}, - {"ftp_port_list", TYPE_STRING, false, "FTP ports list"}, - {"tcp_port", TYPE_STRING, false, "TCP ports list"}, - {"portfile0", TYPE_STRING, false, "output file for serial port 0"}, - {"portfile1", TYPE_STRING, false, "output file for serial port 1"}, - - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Prefs file name and path -const TCHAR PREFS_FILE_NAME[] = TEXT("BasiliskII_prefs"); -tstring UserPrefsPath; -static tstring prefs_path; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(const char *vmdir) -{ - // Construct prefs path - if (UserPrefsPath.empty()) { - int pwd_len = GetCurrentDirectory(0, NULL); - prefs_path.resize(pwd_len); - pwd_len = GetCurrentDirectory(pwd_len, &prefs_path.front()); - prefs_path[pwd_len] = TEXT('\\'); - prefs_path += PREFS_FILE_NAME; - } else - prefs_path = UserPrefsPath; - - // Read preferences from settings file - FILE *f = _tfopen(prefs_path.c_str(), TEXT("r")); - if (f != NULL) { - - // Prefs file found, load settings - LoadPrefsFromStream(f); - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - } -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = _tfopen(prefs_path.c_str(), TEXT("w"))) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsAddBool("keycodes", false); - PrefsReplaceBool("pollmedia", true); - PrefsReplaceBool("enableextfs", false); - PrefsReplaceString("extfs", ""); - PrefsReplaceString("extdrives", "CDEFGHIJKLMNOPQRSTUVWXYZ"); - PrefsReplaceInt32("mousewheelmode", 1); - PrefsReplaceInt32("mousewheellines", 3); -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - PrefsAddBool("ignoresegv", false); -#endif - PrefsAddBool("idlewait", true); - PrefsReplaceBool("etherpermanentaddress", true); - PrefsReplaceInt32("ethermulticastmode", 0); - PrefsReplaceString("ftp_port_list", "21"); - PrefsReplaceString("seriala", "COM1"); - PrefsReplaceString("serialb", "COM2"); - PrefsReplaceString("portfile0", "C:\\B2TEMP0.OUT"); - PrefsReplaceString("portfile1", "C:\\B2TEMP1.OUT"); -} diff --git a/BasiliskII/src/Windows/router/arp.cpp b/BasiliskII/src/Windows/router/arp.cpp deleted file mode 100755 index 69a11879..00000000 --- a/BasiliskII/src/Windows/router/arp.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * arp.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "cpu_emulation.h" -#include "prefs.h" -#include "ether_windows.h" -#include "ether.h" -#include "router.h" -#include "router_types.h" -#include "iphelp.h" -#include "arp.h" -#include "icmp.h" -#include "dump.h" - - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -// ARP queries can be replied immediately. - -bool write_arp( arp_t *req, int len ) -{ - D(bug("write_arp() len=%d, htype=%d, ptype=%04x, opcode=%d, halen=%d, palen=%d\r\n",len, ntohs(req->htype), ntohs(req->ptype), ntohs(req->opcode), req->halen, req->palen)); - - start_icmp_listen(); - - bool result = false; - - if( len >= sizeof(arp_t) && - req->htype == htons(arp_hwtype_enet) && - req->ptype == htons(mac_type_ip4) && - req->opcode == htons(arp_request) && - req->halen == 6 && - req->palen == 4 - ) - { - if(memcmp( req->srcp, req->dstp, 4 ) == 0) { - // No reply. MacOS is making sure that there are no duplicate ip addresses. - // Update localhost (==Mac) ip address (needed by incoming icmp) - macos_ip_address = ntohl( *((uint32 *)&req->srcp[0]) ); - D(bug("Mac ip: %02x %02x %02x %02x\r\n", req->srcp[0], req->srcp[1], req->srcp[2], req->srcp[3])); - } else { - arp_t arp; - - D(bug("Source NIC: %02x %02x %02x %02x\r\n", req->srcp[0], req->srcp[1], req->srcp[2], req->srcp[3])); - D(bug("Dest NIC: %02x %02x %02x %02x\r\n", req->dstp[0], req->dstp[1], req->dstp[2], req->dstp[3])); - - // memcpy( arp.mac.dest, req->mac.src, 6 ); - memcpy( arp.mac.dest, ether_addr, 6 ); - memcpy( arp.mac.src, router_mac_addr, 6 ); - arp.mac.type = htons(mac_type_arp); - arp.htype = htons(arp_hwtype_enet); - arp.ptype = htons(mac_type_ip4); - arp.halen = 6; - arp.palen = 4; - arp.opcode = htons(arp_reply); - memcpy( arp.srch, router_mac_addr, 6 ); - memcpy( arp.srcp, req->dstp, 4 ); - // memcpy( arp.dsth, req->srch, 6 ); - memcpy( arp.dsth, ether_addr, 6 ); - memcpy( arp.dstp, req->srcp, 4 ); - - // Update here, too, just in case. - macos_ip_address = ntohl( *((uint32 *)&req->srcp[0]) ); - - enqueue_packet( (uint8 *)&arp, sizeof(arp) ); - } - result = true; - } - return result; -} diff --git a/BasiliskII/src/Windows/router/arp.h b/BasiliskII/src/Windows/router/arp.h deleted file mode 100755 index c44443d9..00000000 --- a/BasiliskII/src/Windows/router/arp.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * arp.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ARP_H_ -#define _ARP_H_ - -bool write_arp( arp_t *req, int len ); - -#endif // _ARP_H_ diff --git a/BasiliskII/src/Windows/router/dump.cpp b/BasiliskII/src/Windows/router/dump.cpp deleted file mode 100755 index 4d3fe731..00000000 --- a/BasiliskII/src/Windows/router/dump.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * dump.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "dump.h" - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -void dump_bytes( uint8 *packet, int length ) -{ -#if DEBUG - char buf[1000], sm[10]; - - *buf = 0; - - if(length > 256) length = 256; - - for (int i=0; i -#include "dump.h" -#include "prefs.h" -#include "ftp.h" - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - -static int m_ftp_port_count = 0; -#define MAX_FTP_PORTS 100 -static uint16 m_ftp_ports[MAX_FTP_PORTS]; - -bool ftp_is_ftp_port( uint16 port ) -{ - for( int i=0; i> 24, - (ip >> 16) & 0xFF, - (ip >> 8) & 0xFF, - ip & 0xFF, - (port >> 8) & 0xFF, - port & 0xFF, - 0x0d, 0x0a - ); - - count = strlen(buf); - - D(bug("ftp_modify_port_command: \"%s\"\r\n", buf )); -} - -// this should be robust. rather skip it than do anything dangerous. -void ftp_parse_port_command( - char *buf, - uint32 count, - uint16 &ftp_data_port, - bool is_pasv -) -{ - ftp_data_port = 0; - - if( !count ) return; - - uint8 b[100]; - uint32 ftp_ip = 0; - - // make it a c-string - if( count >= sizeof(b) ) count = sizeof(b)-1; - memcpy( b, buf, count ); - b[ count ] = 0; - - for( uint32 i=0; i 'z' ) { - b[i] = ' '; - } else { - b[i] = tolower(b[i]); - } - } - - // D(bug("FTP: \"%s\"\r\n", b )); - - char *s = (char *)b; - - while( *s == ' ' ) s++; - - if(is_pasv) { - /* - LOCAL SERVER: ..227 Entering Passive Mode (192,168,0,2,6,236). 0d 0a - */ - if( atoi(s) == 227 && strstr(s,"passive") ) { - while( *s && *s != '(' ) s++; - if( *s++ == 0 ) s = 0; - } else { - s = 0; - } - } else { - /* - LOCAL CLIENT: PORT 192,168,0,1,14,147 0d 0a - */ - if( strncmp(s,"port ",5) == 0 ) { - s += 5; - } else { - s = 0; - } - } - - if(s && *s) { - // get remote ip (used only for verification) - for( uint32 i=0; i<4; i++ ) { - while( *s == ' ' ) s++; - if(!isdigit(*s)) { - ftp_ip = 0; - break; - } - ftp_ip = (ftp_ip << 8) + atoi(s); - while( *s && *s != ',' ) s++; - if(!*s) { - ftp_ip = 0; - break; - } - s++; - } - - if(ftp_ip) { - // get local port - for( uint32 i=0; i<2; i++ ) { - while( *s == ' ' ) s++; - if(!isdigit(*s)) { - ftp_data_port = 0; - break; - } - ftp_data_port = (ftp_data_port << 8) + atoi(s); - while( *s && *s != ',' && *s != ')' ) s++; - if(!*s) - break; - else - s++; - } - } - } - if(ftp_data_port) { - D(bug("ftp_parse_port_command: \"%s\"; port is %d\r\n", b, ftp_data_port )); - } -} diff --git a/BasiliskII/src/Windows/router/ftp.h b/BasiliskII/src/Windows/router/ftp.h deleted file mode 100755 index 5dc6dfda..00000000 --- a/BasiliskII/src/Windows/router/ftp.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ftp.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _FTP_H_ -#define _FTP_H_ - -// Read the preferences. -void init_ftp(); - -// Compares against a list provided by the user. -bool ftp_is_ftp_port( uint16 port ); - -// Determine whether this is a ftp client PORT command or ftp server entering to passive mode. -void ftp_parse_port_command( - char *buf, - uint32 count, - uint16 &ftp_data_port, - bool is_pasv -); - -// Build a new command using ip and port. -void ftp_modify_port_command( - char *buf, - int &count, - const uint32 max_size, - const uint32 ip, - const uint16 port, - const bool is_pasv -); - -#endif // _FTP_H_ diff --git a/BasiliskII/src/Windows/router/icmp.cpp b/BasiliskII/src/Windows/router/icmp.cpp deleted file mode 100755 index d6cb0e0e..00000000 --- a/BasiliskII/src/Windows/router/icmp.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - * icmp.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "cpu_emulation.h" -#include "ws2tcpip.h" -#include "prefs.h" -#include "ether_windows.h" -#include "ether.h" -#include "router.h" -#include "router_types.h" -#include "dynsockets.h" -#include "ipsocket.h" -#include "iphelp.h" -#include "icmp.h" -#include "dump.h" - - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -// Saved for cleanup. -static socket_t *icmp_incoming_s = 0; - - -void stop_icmp_listen() -{ - if(icmp_incoming_s) { - delete icmp_incoming_s; - icmp_incoming_s = 0; - } -} - -void start_icmp_listen() -{ - if(!icmp_incoming_s) { - icmp_incoming_s = new socket_t(IPPROTO_ICMP); - - icmp_incoming_s->permanent = TRUE; - icmp_incoming_s->s = _socket( AF_INET, SOCK_RAW, IPPROTO_ICMP ); - - memset( &icmp_incoming_s->from, 0, icmp_incoming_s->from_len ); - icmp_incoming_s->from.sin_family = AF_INET; - - if(icmp_incoming_s->s == INVALID_SOCKET) { - D(bug("Failed to create icmp listening socket (NT/no admin?)\r\n" )); - delete icmp_incoming_s; - icmp_incoming_s = 0; - } else { - D(bug("icmp listening socket created\r\n" )); - raw_sockets_available = true; - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - if( _bind ( icmp_incoming_s->s, (const struct sockaddr *)&to, sizeof(to) ) == SOCKET_ERROR ) { - D(bug("Listening to inbound icmp failed, error code = %d\r\n", _WSAGetLastError() )); - _closesocket( icmp_incoming_s->s ); - delete icmp_incoming_s; - icmp_incoming_s = 0; - } else { - D(bug("icmp listening socket bound\r\n" )); - if(!icmp_incoming_s->b_recfrom()) { - D(bug("b_recfrom() from inbound icmp failed, error code = %d\r\n", _WSAGetLastError() )); - // _closesocket( icmp_incoming_s->s ); - // delete icmp_incoming_s; - // icmp_incoming_s = 0; - } - } - } - } -} - -void CALLBACK icmp_read_completion( - DWORD error, - DWORD bytes_read, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -) -{ - D(bug("icmp_read_completion(error=0x%x, bytes_read=%d, flags=0x%x)\r\n", error, bytes_read, flags)); - - socket_t *cmpl = (socket_t *)lpOverlapped->hEvent; - - if(error == 0 && macos_ip_address != 0) { - if(bytes_read > 1460) { - D(bug("discarding oversized icmp packet, size = \r\n", bytes_read)); - } else { - int icmp_size = sizeof(mac_t) + bytes_read; - icmp_t *icmp = (icmp_t *)malloc( icmp_size ); - if(icmp) { - mac_t *mac = (mac_t *)icmp; - ip_t *ip = (ip_t *)icmp; - - memcpy( mac->dest, ether_addr, 6 ); - memcpy( mac->src, router_mac_addr, 6 ); - mac->type = htons(mac_type_ip4); - - // Copy payload (used by ICMP checksum) - memcpy( (char *)icmp + sizeof(mac_t), cmpl->buffers[0].buf, bytes_read ); - - switch( icmp->type ) { - // May need to patch the returned ip header. - case icmp_Destination_unreachable: - case icmp_Source_quench: - case icmp_Redirect: - case icmp_Time_exceeded: - case icmp_Parameter_problem: - ip_t *ip_if = (ip_t *)( (char *)icmp + sizeof(icmp_t) + sizeof(uint32) - sizeof(mac_t) ); - - // This would be needed (traceroute) - // ip_if->ident = ??; - - // Cannot fix some fields, this should be enough: - ip_if->src = htonl(macos_ip_address); - - if(ip_if->proto == ip_proto_udp) { - udp_t *udp_if = (udp_t *)ip_if; - // udp_if->src_port = ... don't know!; - } else if(ip_if->proto == ip_proto_tcp) { - tcp_t *tcp_if = (tcp_t *)ip_if; - // tcp_if->src_port = ... don't know!; - } - break; - } - - make_icmp_checksum( icmp, icmp_size ); - - // Replace the target ip address - ip->dest = htonl(macos_ip_address); - ip->ttl--; - make_ip4_checksum( ip ); - - dump_bytes( (uint8 *)icmp, icmp_size ); - - if( ip->ttl == 0 ) { - D(bug("icmp packet ttl expired\r\n")); - } else { - enqueue_packet( (uint8 *)icmp, icmp_size ); - } - free(icmp); - } - } - } - - memset( &cmpl->from, 0, cmpl->from_len ); - - if(is_router_shutting_down) { - delete cmpl; - } else if(cmpl->s == INVALID_SOCKET || !cmpl->b_recfrom()) { - // delete cmpl; - } -} - -void write_icmp( icmp_t *icmp, int len ) -{ - struct in_addr ia; - ia.s_addr = icmp->ip.dest; - D(bug("write_icmp(%s)\r\n", _inet_ntoa(ia) )); - - if(!raw_sockets_available) { - D(bug("write_icmp() cannot proceed, raw sockets not available\r\n" )); - return; - } - - if(len < sizeof(icmp_t)) { - D(bug("Too small icmp packet(%d), dropped\r\n", len)); - return; - } - - // must be updated, ttl changed - make_icmp_checksum( icmp, len ); - - SOCKET s = _socket( AF_INET, SOCK_RAW, IPPROTO_ICMP ); - if(s != INVALID_SOCKET) { - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - to.sin_addr.s_addr = icmp->ip.dest; - - char *data = (char *)icmp + sizeof(ip_t); - int dlen = len - sizeof(ip_t); - - int ttl = icmp->ip.ttl; - if(_setsockopt( s, IPPROTO_IP, IP_TTL, (const char *)&ttl, sizeof(int) ) == SOCKET_ERROR ) { - D(bug("could not set ttl to %d.\r\n", ttl)); - } else { - D(bug("ttl set to %d.\r\n", ttl)); - } - - if(SOCKET_ERROR == _sendto( s, data, dlen, 0, (struct sockaddr *)&to, sizeof(to) )) { - D(bug("Failed to send icmp via raw socket\r\n" )); - } - _closesocket(s); - } else { - D(bug("Could not create raw socket for icmp\r\n" )); - } -} diff --git a/BasiliskII/src/Windows/router/icmp.h b/BasiliskII/src/Windows/router/icmp.h deleted file mode 100755 index a3c30621..00000000 --- a/BasiliskII/src/Windows/router/icmp.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * icmp.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ICMP_H_ -#define _ICMP_H_ - -void start_icmp_listen(); -void stop_icmp_listen(); - -void write_icmp( icmp_t *icmp, int len ); - -void CALLBACK icmp_read_completion( - DWORD error, - DWORD bytes_read, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -); - -#endif // _ICMP_H_ diff --git a/BasiliskII/src/Windows/router/iphelp.cpp b/BasiliskII/src/Windows/router/iphelp.cpp deleted file mode 100755 index e77466e1..00000000 --- a/BasiliskII/src/Windows/router/iphelp.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * iphelp.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "cpu_emulation.h" -#include "ether_windows.h" -#include "ether.h" -#include "router.h" -#include "router_types.h" -#include "tcp.h" -#include "icmp.h" -#include "udp.h" -#include "iphelp.h" -#include "dump.h" - - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -void make_icmp_checksum( icmp_t *icmp, int len ) -{ - icmp->checksum = 0; - - uint16 sz = (len-sizeof(ip_t))/2; - uint16 *p = (uint16 *)( (uint8 *)icmp + sizeof(ip_t) ); - - uint32 sum32 = 0; - for( int i=0; ichecksum = htons((uint16)sum32); -} - -void make_tcp_checksum( tcp_t *tcp, int len ) -{ - tcp->checksum = 0; - - int tcp_len = len - sizeof(ip_t); - uint16 sz = tcp_len/2; - uint16 *p = (uint16 *)( (uint8 *)tcp + sizeof(ip_t) ); - - uint32 sum32 = 0; - for( int i=0; iip.src)); - pseudo.src_hi = HIWORD(ntohl(tcp->ip.src)); - pseudo.dest_lo = LOWORD(ntohl(tcp->ip.dest)); - pseudo.dest_hi = HIWORD(ntohl(tcp->ip.dest)); - pseudo.proto = (uint16)tcp->ip.proto; - pseudo.msg_len = tcp->header_len >> 2; - - int datalen = len - sizeof(tcp_t); - pseudo.msg_len += datalen; - - p = (uint16 *)&pseudo; - - for( int i=0; ichecksum = htons((uint16)sum32); -} - -void make_ip4_checksum( ip_t *ip ) -{ - ip->checksum = 0; - uint16 sz = ip->header_len * 2; - uint16 *p = (uint16 *)( (uint8 *)ip + sizeof(mac_t) ); - - uint32 sum32 = 0; - for( int i=0; ichecksum = htons((uint16)sum32); -} - -void make_udp_checksum( udp_t *udp ) -{ - udp->checksum = 0; - return; - - // UDP checksums are optional. - - /* - uint16 sz = ntohs(udp->msg_len) / 2; - uint16 *p = (uint16 *)( (uint8 *)udp + sizeof(ip_t) ); - - uint32 sum32 = 0; - for( int i=0; iip.src)); - pseudo.src_hi = HIWORD(ntohl(udp->ip.src)); - pseudo.dest_lo = LOWORD(ntohl(udp->ip.dest)); - pseudo.dest_hi = HIWORD(ntohl(udp->ip.dest)); - pseudo.proto = (uint16)udp->ip.proto; - pseudo.msg_len = ntohs(udp->msg_len); // ??? - - p = (uint16 *)&pseudo; - - for( i=0; ichecksum = htons((uint16)sum32); - */ -} - -void error_winsock_2_icmp( int err, ip_t *ip_err, int dlen_err ) -{ - int type = -1, code = -1, msg_size = 0; - - switch( err ) { - case WSAEHOSTUNREACH: - case WSAETIMEDOUT: - type = icmp_Destination_unreachable; - code = 1; // Host unreachable - msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits - break; - case WSAENETDOWN: - case WSAENETUNREACH: - type = icmp_Destination_unreachable; - code = 0; // Network unreachable - msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits - break; - case WSAETTLEXCEEDED: - type = icmp_Time_exceeded; - code = 0; // Transit TTL exceeded - msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits - break; - } - - if(type >= 0 && macos_ip_address != 0) { - D(bug("sending icmp error reply. type=%d, code=%d, msg_size=%d\r\n", type, code, msg_size)); - - int icmp_size = sizeof(icmp_t) + msg_size; - - icmp_t *icmp = (icmp_t *)malloc( icmp_size ); - if(icmp) { - mac_t *mac = (mac_t *)icmp; - ip_t *ip = (ip_t *)icmp; - - memcpy( mac->dest, ether_addr, 6 ); - memcpy( mac->src, router_mac_addr, 6 ); - mac->type = htons(mac_type_ip4); - - ip->version = 4; - ip->header_len = 5; - ip->tos = 0; - ip->total_len = htons(sizeof(icmp_t) - sizeof(mac_t) + msg_size); - - ip->ident = htons(next_ip_ident_number++); - ip->flags_n_frag_offset = 0; - ip->ttl = 128; - ip->proto = ip_proto_icmp; - ip->src = htonl(router_ip_address); - ip->dest = htonl(macos_ip_address); - make_ip4_checksum( ip ); - - icmp->type = type; - icmp->code = code; - - // zero out the unused field - memset( (char *)icmp + sizeof(icmp_t), 0, sizeof(uint32) ); - - // copy 64 bits of original message - memcpy( - (char *)icmp + sizeof(icmp_t) + sizeof(uint32), - (char *)ip_err + sizeof(mac_t), - msg_size - ); - - make_icmp_checksum( icmp, icmp_size ); - - dump_bytes( (uint8 *)icmp, icmp_size ); - - enqueue_packet( (uint8 *)icmp, icmp_size ); - free(icmp); - } - } -} diff --git a/BasiliskII/src/Windows/router/iphelp.h b/BasiliskII/src/Windows/router/iphelp.h deleted file mode 100755 index 513616da..00000000 --- a/BasiliskII/src/Windows/router/iphelp.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * iphelp.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _IPHELP_H_ -#define _IPHELP_H_ - -// Fake ttl exceeded code. -#define WSAETTLEXCEEDED (WSABASEERR + 1999 + 17) - -void error_winsock_2_icmp( int err, ip_t *ip_err, int dlen_err ); - -void make_icmp_checksum( icmp_t *icmp, int len ); -void make_ip4_checksum( ip_t *ip ); -void make_udp_checksum( udp_t *udp ); -void make_tcp_checksum( tcp_t *tcp, int len ); - -#endif // _IPHELP_H_ diff --git a/BasiliskII/src/Windows/router/ipsocket.cpp b/BasiliskII/src/Windows/router/ipsocket.cpp deleted file mode 100755 index 21fef9a9..00000000 --- a/BasiliskII/src/Windows/router/ipsocket.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * ipsocket.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "cpu_emulation.h" -#include "ws2tcpip.h" -#include "prefs.h" -#include "ether_windows.h" -#include "ether.h" -#include "router.h" -#include "router_types.h" -#include "dynsockets.h" -#include "ipsocket.h" -#include "icmp.h" -#include "tcp.h" -#include "udp.h" -#include "dump.h" - - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -socket_t::socket_t( int _proto ) -{ - s = INVALID_SOCKET; - proto = _proto; - - ip_src = ip_dest = 0; - src_port = dest_port = 0; - - memset( &overlapped, 0, sizeof(overlapped) ); - overlapped.hEvent = (HANDLE)this; - - bytes_received = 0; - flags = 0; - from_len = sizeof(struct sockaddr_in); - memset( &from, 0, sizeof(from) ); - from.sin_family = AF_INET; - - buffer_count = 1; - buffers[0].len = 1460; - buffers[0].buf = new char [buffers[0].len]; - - out_buffers[0].len = 1460; - out_buffers[0].buf = new char [out_buffers[0].len]; - - socket_ttl = GetTickCount() + 60000L; - permanent = false; -} - -socket_t::~socket_t() -{ - if(s != INVALID_SOCKET) { - _closesocket( s ); // slam! - s = INVALID_SOCKET; - } - delete [] out_buffers[0].buf; - delete [] buffers[0].buf; -} - -int socket_t::WSARecvFrom() -{ - return _WSARecvFrom( - s, - buffers, - buffer_count, - &bytes_received, - &flags, - (struct sockaddr *)&from, - &from_len, - &overlapped, - proto == IPPROTO_UDP ? udp_read_completion : icmp_read_completion - ); -} - -bool socket_t::b_recfrom() -{ - bool result; - - int ret = WSARecvFrom(); - - if(ret == SOCKET_ERROR) { - int socket_error = _WSAGetLastError(); - if(socket_error == WSA_IO_PENDING) { - D(bug("WSARecvFrom() i/o pending\r\n")); - result = true; - } else { - D(bug("_WSAGetLastError() returned %d\r\n", socket_error)); - result = false; - } - } else /*if(ret == 0) */ { - D(bug("WSARecvFrom() ok\r\n")); - // Completion routine call is already scheduled. - result = true; - } - return result; -} - -void socket_t::set_ttl( uint8 ttl ) -{ - int _ttl = ttl; // defensive programming, I know VCx - - if(_setsockopt( s, IPPROTO_IP, IP_TTL, (const char *)&_ttl, sizeof(int) ) == SOCKET_ERROR ) { - D(bug("could not set ttl to %d.\r\n", ttl)); - } else { - D(bug("ttl set to %d.\r\n", ttl)); - } -} - - -#define MAX_OPEN_SOCKETS 1024 -static socket_t *all_sockets[MAX_OPEN_SOCKETS]; -static int open_sockets = 0; - -int get_socket_index( uint16 src_port, uint16 dest_port, int proto ) -{ - int result = -1; - for( int i=0; isrc_port == src_port && cmpl->dest_port == dest_port && cmpl->proto == proto ) { - result = i; - break; - } - } - return result; -} - -int get_socket_index( uint16 src_port, int proto ) -{ - int result = -1; - for( int i=0; isrc_port == src_port && cmpl->proto == proto ) { - result = i; - break; - } - } - return result; -} - -int get_socket_index( socket_t *cmpl ) -{ - int result = -1; - for( int i=0; isrc_port, cmpl->dest_port)); - - EnterCriticalSection( &router_section ); - int i = get_socket_index( cmpl ); - if( i >= 0 ) { - delete all_sockets[i]; - all_sockets[i] = all_sockets[--open_sockets]; - } else { - D(bug("Deleted socket not in table!\r\n")); - // delete cmpl; - } - LeaveCriticalSection( &router_section ); -} - -socket_t *find_socket( uint16 src_port, uint16 dest_port, int proto ) -{ - socket_t *result = 0; - EnterCriticalSection( &router_section ); - int i = get_socket_index( src_port, dest_port, proto ); - if( i >= 0 ) { - result = all_sockets[i]; - } else { - i = get_socket_index( src_port, proto ); - if( i >= 0 ) { - delete_socket( all_sockets[i] ); - } - } - LeaveCriticalSection( &router_section ); - - D(bug("find_socket(%d,%d): %s\r\n", src_port, dest_port, result ? "found" : "not found")); - - return result; -} - -void add_socket( socket_t *cmpl ) -{ - D(bug("adding socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port)); - - EnterCriticalSection( &router_section ); - if( open_sockets < MAX_OPEN_SOCKETS ) { - all_sockets[open_sockets++] = cmpl; - } else { - // Urgchiyuppijee! (that's finnish language, meaning "do something about this") - delete all_sockets[0]; - all_sockets[0] = cmpl; - } - LeaveCriticalSection( &router_section ); -} - -void close_old_sockets() -{ - DWORD now = GetTickCount(); - - EnterCriticalSection( &router_section ); - for( int i=open_sockets-1; i>=0; i-- ) { - socket_t *cmpl = all_sockets[i]; - if( !cmpl->permanent && now >= cmpl->socket_ttl ) { - D(bug("expiring socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port)); - if(cmpl->s == INVALID_SOCKET) { - delete all_sockets[i]; - all_sockets[i] = all_sockets[--open_sockets]; - } else { - // read completion will deallocate - _closesocket( cmpl->s ); - } - } - } - LeaveCriticalSection( &router_section ); -} - -void close_all_sockets() -{ - D(bug("closing all(%d) sockets\r\n", open_sockets)); - - EnterCriticalSection( &router_section ); - for( int i=0; isrc_port, cmpl->dest_port)); - if(cmpl->s == INVALID_SOCKET) { - delete all_sockets[i]; - all_sockets[i] = all_sockets[--open_sockets]; - } else { - // read completion will deallocate - _closesocket( cmpl->s ); - } - } - LeaveCriticalSection( &router_section ); -} diff --git a/BasiliskII/src/Windows/router/ipsocket.h b/BasiliskII/src/Windows/router/ipsocket.h deleted file mode 100755 index 97005f12..00000000 --- a/BasiliskII/src/Windows/router/ipsocket.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ipsocket.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _IPSOCKET_H_ -#define _IPSOCKET_H_ - -class socket_t { -public: - socket_t( int _proto ); - ~socket_t(); - bool b_recfrom(); - void set_ttl( uint8 ttl ); - -protected: - int WSARecvFrom(); - -public: - SOCKET s; // Always a valid socket - BOOL permanent; // T: a user-defined listening socket, - int proto; // udp/icmp - WSABUF buffers[1]; - WSABUF out_buffers[1]; - DWORD buffer_count; - DWORD bytes_received; - DWORD flags; - struct sockaddr_in from; - int from_len; - WSAOVERLAPPED overlapped; - uint32 ip_src; - uint32 ip_dest; - uint16 src_port; - uint16 dest_port; - DWORD socket_ttl; -}; - - -int get_socket_index( uint16 src_port, uint16 dest_port, int proto ); -int get_socket_index( uint16 src_port, int proto ); -int get_socket_index( socket_t *cmpl ); -void delete_socket( socket_t *cmpl ); -socket_t *find_socket( uint16 src_port, uint16 dest_port, int proto ); -void add_socket( socket_t *cmpl ); -void close_old_sockets(); -void close_all_sockets(); - - -#endif // _IPSOCKET_H_ diff --git a/BasiliskII/src/Windows/router/mib/interfaces.cpp b/BasiliskII/src/Windows/router/mib/interfaces.cpp deleted file mode 100755 index d89d407d..00000000 --- a/BasiliskII/src/Windows/router/mib/interfaces.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * interfaces.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "interfaces.h" -#include "../dump.h" -#include "mibaccess.h" - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - -static UINT ip_array[100]; -static UINT ip_array_sz = 0; - -void init_interfaces() -{ - MibII _mibs(false); - - ip_array_sz = sizeof(ip_array) / sizeof(ip_array[0]); - - if(_mibs.Init()) { - _mibs.GetIPAddress( ip_array, ip_array_sz ); - } - - if(ip_array_sz == 0) { - ip_array_sz = 1; - ip_array[0] = 0; // localhost - } - - D(bug("init_interfaces() found %d interfaces.\r\n", ip_array_sz)); -} - -void final_interfaces() -{ - // Currently nothing to do. -} - -int get_ip_count() -{ - return ip_array_sz; -} - -uint32 get_ip_by_index( int index ) -{ - return index >= 0 && index < (int)ip_array_sz ? ip_array[index] : 0; -} diff --git a/BasiliskII/src/Windows/router/mib/interfaces.h b/BasiliskII/src/Windows/router/mib/interfaces.h deleted file mode 100755 index aeb15223..00000000 --- a/BasiliskII/src/Windows/router/mib/interfaces.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * intercafes.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _INTERFACES_H_ -#define _INTERFACES_H_ - -// A wrapper to the MibII class. Enumerates all ip interfaces -// currently in this computer. The interface list is not static. - -void init_interfaces(); -void final_interfaces(); - -int get_ip_count(); -uint32 get_ip_by_index( int index ); - -#endif // _INTERFACES_H_ diff --git a/BasiliskII/src/Windows/router/mib/mibaccess.cpp b/BasiliskII/src/Windows/router/mib/mibaccess.cpp deleted file mode 100755 index f877db9d..00000000 --- a/BasiliskII/src/Windows/router/mib/mibaccess.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* - * MibAccess.cpp - * - * The original code by Stas Khirman modified by Lauri Pesonen, December, 2000: - * - * SnmpUtilVarBindFree(), SnmpUtilOidNCmp() and SnmpUtilOidCpy() now loaded from - * "snmpapi.dll" dynamically instead of linking statically. - * - * MibII ctor now takes a parameter whether to load Winsock or not. - * WSAStartup maintains an internal reference counter so it would have been ok - * to let it load always. - * - * Fixed a bug where the return value of LoadLibrary() was compared against - * HINSTANCE_ERROR instead of NULL. - * - * Removed some type conversion warnings by casting. - * - * Added a check in MibExtLoad ctor that the function entry points were found. - * - * Added a check in GetIPMask() and GetIPAddress() that the library was loaded - * before accessing the functions. - * - * Changed the return type of GetIPAddress() and GetIPMask() from BOOL to void - * as they always returned TRUE. - * - */ - -/************************************************************************/ -/* Copyright (C) Stas Khirman 1998. All rights reserved. */ -/* Written by Stas Khirman (staskh@rocketmail.com). */ -/* and */ -/* Raz Galili (razgalili@hotmail.com) */ -/* */ -/* Free software: no warranty; use anywhere is ok; spread the */ -/* sources; note any modifications; share variations and */ -/* derivatives (including sending to staskh@rocketmail.com). */ -/* */ -/************************************************************************/ - -/* - * MibAccess.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "sysdeps.h" -#include "main.h" -#include "mibaccess.h" -#include "../dynsockets.h" -#include "../dump.h" - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - -MibExtLoad::MibExtLoad( LPCTSTR MibDllName, LPCTSTR SnmpDllName ) -{ - m_Init = NULL; - - m_InitEx = NULL; - m_Query = NULL; - m_Trap = NULL; - - m_hInst_snmputil = NULL; - - m_SnmpUtilVarBindFree = NULL; - m_SnmpUtilOidNCmp = NULL; - m_SnmpUtilOidCpy = NULL; - - m_hInst = LoadLibrary( MibDllName ); - if(!m_hInst) { - D(bug(TEXT("MIB: library %s could not be loaded.\r\n"), MibDllName)); - return; - } - D(bug(TEXT("MIB: library %s loaded ok.\r\n"), MibDllName)); - - m_Init = (pSnmpExtensionInit)GetProcAddress(m_hInst ,"SnmpExtensionInit"); - m_InitEx= (pSnmpExtensionInitEx)GetProcAddress(m_hInst ,"SnmpExtensionInitEx"); - m_Query = (pSnmpExtensionQuery)GetProcAddress(m_hInst ,"SnmpExtensionQuery"); - m_Trap = (pSnmpExtensionTrap)GetProcAddress(m_hInst ,"SnmpExtensionTrap"); - - if( !m_Init || !m_InitEx || !m_Query || !m_Trap ) - { - D(bug(TEXT("MIB: required entry points not found in library %s.\r\n"), MibDllName)); - FreeLibrary( m_hInst ); - m_hInst = NULL; - } - - m_hInst_snmputil = LoadLibrary( SnmpDllName ); - if(!m_hInst_snmputil){ - D(bug(TEXT("MIB: library %s could not be loaded.\r\n"), SnmpDllName)); - FreeLibrary( m_hInst ); - m_hInst = NULL; - return; - } - D(bug(TEXT("MIB: library %s loaded ok.\r\n"), SnmpDllName)); - - m_SnmpUtilVarBindFree = (VOID (SNMP_FUNC_TYPE *)(SnmpVarBind *))GetProcAddress( m_hInst_snmputil, "SnmpUtilVarBindFree" ); - m_SnmpUtilOidNCmp = (SNMPAPI (SNMP_FUNC_TYPE *)(AsnObjectIdentifier *, AsnObjectIdentifier *, UINT))GetProcAddress( m_hInst_snmputil, "SnmpUtilOidNCmp" ); - m_SnmpUtilOidCpy = (SNMPAPI (SNMP_FUNC_TYPE *)(AsnObjectIdentifier *, AsnObjectIdentifier *))GetProcAddress( m_hInst_snmputil, "SnmpUtilOidCpy" ); - - if( !m_SnmpUtilVarBindFree || !m_SnmpUtilOidNCmp || !m_SnmpUtilOidCpy ) - { - D(bug(TEXT("MIB: required entry points not found in library %s.\r\n"), SnmpDllName)); - FreeLibrary( m_hInst ); - FreeLibrary( m_hInst_snmputil ); - m_hInst = NULL; - m_hInst_snmputil = NULL; - } - - #undef SNMP_FreeVarBind - #undef SNMP_oidncmp - #undef SNMP_oidcpy - - #define SNMP_FreeVarBind m_SnmpUtilVarBindFree - #define SNMP_oidncmp m_SnmpUtilOidNCmp - #define SNMP_oidcpy m_SnmpUtilOidCpy -} - -MibExtLoad::~MibExtLoad() -{ - if( m_hInst ) { - FreeLibrary( m_hInst ); - m_hInst = NULL; - } - if( m_hInst_snmputil ) { - FreeLibrary( m_hInst_snmputil ); - m_hInst_snmputil = NULL; - } -} - -BOOL MibExtLoad::Init(DWORD dwTimeZeroReference,HANDLE *hPollForTrapEvent,AsnObjectIdentifier *supportedView) -{ - if(m_hInst && m_Init) - return m_Init(dwTimeZeroReference,hPollForTrapEvent,supportedView); - return FALSE; -} -BOOL MibExtLoad::InitEx(AsnObjectIdentifier *supportedView) -{ - if(m_hInst && m_InitEx) - return m_InitEx(supportedView); - - return FALSE; -} - -BOOL MibExtLoad::Query(BYTE requestType,OUT RFC1157VarBindList *variableBindings, - AsnInteger *errorStatus,AsnInteger *errorIndex) -{ - if(m_hInst && m_Query) - return m_Query(requestType,variableBindings,errorStatus,errorIndex); - - return FALSE; -} - -BOOL MibExtLoad::Trap(AsnObjectIdentifier *enterprise, AsnInteger *genericTrap, - AsnInteger *specificTrap, AsnTimeticks *timeStamp, - RFC1157VarBindList *variableBindings) -{ - if(m_hInst && m_Trap) - return m_Trap(enterprise, genericTrap,specificTrap, timeStamp, variableBindings); - - return FALSE; -} - -MibII::MibII(bool load_winsock) : MibExtLoad(TEXT("inetmib1.dll"), TEXT("snmpapi.dll")) -{ - WSADATA wsa; - m_load_winsock = load_winsock; - if(load_winsock) { - int err = _WSAStartup( 0x0101, &wsa ); - } -} - -MibII::~MibII() -{ - if(m_load_winsock) _WSACleanup(); -} - -BOOL MibII::Init() -{ - HANDLE PollForTrapEvent; - AsnObjectIdentifier SupportedView; - - return MibExtLoad::Init(GetTickCount(),&PollForTrapEvent,&SupportedView); - -} - - -void MibII::GetIPAddress( UINT IpArray[], UINT &IpArraySize ) -{ - if(!m_hInst) { - IpArraySize = 0; - return; - } - - UINT OID_ipAdEntAddr[] = { 1, 3, 6, 1, 2, 1, 4 , 20, 1 ,1 }; - AsnObjectIdentifier MIB_ipAdEntAddr = { sizeof(OID_ipAdEntAddr)/sizeof(UINT), OID_ipAdEntAddr }; - RFC1157VarBindList varBindList; - RFC1157VarBind varBind[1]; - AsnInteger errorStatus; - AsnInteger errorIndex; - AsnObjectIdentifier MIB_NULL = {0,0}; - BOOL Exit; - int ret; - int IpCount=0; - DWORD dtmp; - - varBindList.list = varBind; - varBindList.len = 1; - varBind[0].name = MIB_NULL; - SNMP_oidcpy(&varBind[0].name,&MIB_ipAdEntAddr); - Exit = FALSE; - - IpCount=0; - while(!Exit){ - ret = Query(ASN_RFC1157_GETNEXTREQUEST,&varBindList,&errorStatus,&errorIndex); - - if(!ret) - Exit=TRUE; - else{ - ret = SNMP_oidncmp(&varBind[0].name,&MIB_ipAdEntAddr,MIB_ipAdEntAddr.idLength); - if(ret!=0){ - Exit=TRUE; - } - else{ - dtmp = *((DWORD *)varBind[0].value.asnValue.address.stream); - IpArray[IpCount] = dtmp; - IpCount++; - if(IpCount>=(int)IpArraySize) - Exit = TRUE; - } - } - } - - IpArraySize = IpCount; - - SNMP_FreeVarBind(&varBind[0]); -} - -void MibII::GetIPMask( UINT IpArray[], UINT &IpArraySize ) -{ - if(!m_hInst) { - IpArraySize = 0; - return; - } - - UINT OID_ipAdEntMask[] = { 1, 3, 6, 1, 2, 1, 4 , 20, 1 ,3 }; - AsnObjectIdentifier MIB_ipAdEntMask = { sizeof(OID_ipAdEntMask)/sizeof(UINT), OID_ipAdEntMask }; - RFC1157VarBindList varBindList; - RFC1157VarBind varBind[1]; - AsnInteger errorStatus; - AsnInteger errorIndex; - AsnObjectIdentifier MIB_NULL = {0,0}; - BOOL Exit; - int ret; - int IpCount=0; - DWORD dtmp; - - varBindList.list = varBind; - varBindList.len = 1; - varBind[0].name = MIB_NULL; - SNMP_oidcpy(&varBind[0].name,&MIB_ipAdEntMask); - Exit = FALSE; - - IpCount=0; - while(!Exit){ - ret = Query(ASN_RFC1157_GETNEXTREQUEST,&varBindList,&errorStatus,&errorIndex); - - if(!ret) - Exit=TRUE; - else{ - ret = SNMP_oidncmp(&varBind[0].name,&MIB_ipAdEntMask,MIB_ipAdEntMask.idLength); - if(ret!=0){ - Exit=TRUE; - } - else{ - dtmp = *((DWORD *)varBind[0].value.asnValue.address.stream); - IpArray[IpCount] = dtmp; - IpCount++; - if(IpCount>=(int)IpArraySize) - Exit = TRUE; - } - } - } - - IpArraySize = IpCount; - - SNMP_FreeVarBind(&varBind[0]); -} diff --git a/BasiliskII/src/Windows/router/mib/mibaccess.h b/BasiliskII/src/Windows/router/mib/mibaccess.h deleted file mode 100755 index 385f5b85..00000000 --- a/BasiliskII/src/Windows/router/mib/mibaccess.h +++ /dev/null @@ -1,83 +0,0 @@ -////////////////////////////////////////////////////// -// FILE : MibAccess.h -// -// - -#ifndef _SNMP_ACCESS_H_ -#define _SNMP_ACCESS_H_ - -#include -#ifndef SNMP_FUNC_TYPE -#define SNMP_FUNC_TYPE WINAPI -#endif - -////////////////////////////////////////////////////////////// -// Definition of pointers to the four functions in the Mib Dll -// -typedef BOOL (WINAPI *pSnmpExtensionInit)( - IN DWORD dwTimeZeroReference, - OUT HANDLE *hPollForTrapEvent, - OUT AsnObjectIdentifier *supportedView); - -typedef BOOL (WINAPI *pSnmpExtensionTrap)( - OUT AsnObjectIdentifier *enterprise, - OUT AsnInteger *genericTrap, - OUT AsnInteger *specificTrap, - OUT AsnTimeticks *timeStamp, - OUT RFC1157VarBindList *variableBindings); - -typedef BOOL (WINAPI *pSnmpExtensionQuery)( - IN BYTE requestType, - IN OUT RFC1157VarBindList *variableBindings, - OUT AsnInteger *errorStatus, - OUT AsnInteger *errorIndex); - -typedef BOOL (WINAPI *pSnmpExtensionInitEx)(OUT AsnObjectIdentifier *supportedView); - - -class MibExtLoad -{ -public: - MibExtLoad( LPCTSTR MibDllName, LPCTSTR SnmpDllName ); - ~MibExtLoad(); - BOOL Init(DWORD dwTimeZeroReference,HANDLE *hPollForTrapEvent,AsnObjectIdentifier *supportedView); - BOOL InitEx(AsnObjectIdentifier *supportedView); - BOOL Query(BYTE requestType,OUT RFC1157VarBindList *variableBindings, - AsnInteger *errorStatus,AsnInteger *errorIndex); - - BOOL Trap(AsnObjectIdentifier *enterprise, AsnInteger *genericTrap, - AsnInteger *specificTrap, AsnTimeticks *timeStamp, - RFC1157VarBindList *variableBindings); - -public: - HINSTANCE m_hInst; - HINSTANCE m_hInst_snmputil; - -private: - pSnmpExtensionInit m_Init; - pSnmpExtensionInitEx m_InitEx; - pSnmpExtensionQuery m_Query; - pSnmpExtensionTrap m_Trap; - -public: - VOID (SNMP_FUNC_TYPE *m_SnmpUtilVarBindFree) (SnmpVarBind *); - SNMPAPI (SNMP_FUNC_TYPE *m_SnmpUtilOidNCmp) (AsnObjectIdentifier *, AsnObjectIdentifier *, UINT); - SNMPAPI (SNMP_FUNC_TYPE *m_SnmpUtilOidCpy) (AsnObjectIdentifier *, AsnObjectIdentifier *); -}; - - -class MibII: public MibExtLoad -{ -public: - MibII( bool load_winsock ); - ~MibII(); - BOOL Init(); - - void GetIPAddress(UINT IpArray[],UINT &IpArraySize); - void GetIPMask(UINT IpArray[],UINT &IpArraySize); - -protected: - bool m_load_winsock; -}; - -#endif diff --git a/BasiliskII/src/Windows/router/router.cpp b/BasiliskII/src/Windows/router/router.cpp deleted file mode 100755 index 10fe2fd7..00000000 --- a/BasiliskII/src/Windows/router/router.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * router.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * This could be implemented by writing three (9x,nt,2k) - * NDIS filter drivers. No thanks. - * But this is not easy either. - */ - -#include "sysdeps.h" -#include "main.h" - -#include - -#include "cpu_emulation.h" -#include "prefs.h" -#include "ether_windows.h" -#include "ether.h" -#include "router.h" -#include "router_types.h" -#include "dynsockets.h" -#include "ipsocket.h" -#include "iphelp.h" -#include "arp.h" -#include "icmp.h" -#include "udp.h" -#include "tcp.h" -#include "ftp.h" -#include "mib/interfaces.h" -#include "dump.h" - - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - - -uint16 next_ip_ident_number = 1; -uint32 macos_ip_address = 0; -const uint8 router_mac_addr[6] = { '4', '2', '6', '7', '7', '9' }; -uint32 router_ip_address = 0; -bool raw_sockets_available = false; - - - -// Protected data. -CRITICAL_SECTION router_section; -bool is_router_shutting_down = false; -static HANDLE r_handle = 0; -static unsigned int rh_tid = 0; - - -static void write_ip4( ip_t *ip, int len ) -{ - if(len < sizeof(ip_t)) { - D(bug("Too small ip packet(%d), dropped\r\n", len)); - } else { - uint8 proto = ip->proto; - - // This is a router, decrement the hop count - if( --ip->ttl == 0 ) { - // Most likely this is some Mac traceroute app - D(bug("ip packet ttl expired, proto=%d.\r\n", proto)); - error_winsock_2_icmp( WSAETTLEXCEEDED, ip, len ); - } else { - switch( proto ) { - case ip_proto_icmp: - write_icmp( (icmp_t *)ip, len ); - break; - case ip_proto_tcp: - write_tcp( (tcp_t *)ip, len ); - break; - case ip_proto_udp: - write_udp( (udp_t *)ip, len ); - break; - default: - D(bug("write_ip4() len=%d, proto=%d\r\n", len, proto)); - break; - } - } - } -} - -bool router_write_packet(uint8 *packet, int len) -{ - bool result = false; - - if( len >= 14 ) { - switch( ntohs( ((mac_t *)packet)->type ) ) { - case mac_type_ip4: - write_ip4( (ip_t *)packet, len ); - result = true; - break; - case mac_type_ip6: - D(bug("write_ip6() len=%d; unsupported.\r\n", len)); - result = true; - break; - case mac_type_arp: - result = write_arp( (arp_t *)packet, len ); - break; - } - } - return result; -} - -bool router_read_packet(uint8 *packet, int len) -{ - bool result = false; - - if( len >= 14 ) { - switch( ntohs( ((mac_t *)packet)->type ) ) { - case mac_type_ip4: - case mac_type_ip6: - case mac_type_arp: - result = true; - break; - } - } - return result; -} - -/* - This has nothing to do with TCP TIME_WAITs or CLOSE_WAITs, - the thread is needed to close down expired udp sockets. - Arguably an ugly hack, but needed since there is no way to - listen to all ports w/o writing another ndis filter driver -*/ -static unsigned int WINAPI router_expire_thread(void *arg) -{ - while(!is_router_shutting_down) { - close_old_sockets(); - Sleep(1000); - } - return 0; -} - -bool router_init(void) -{ - InitializeCriticalSection( &router_section ); - - if(dynsockets_init()) { - char me[128]; - if( _gethostname(me, sizeof(me)) == SOCKET_ERROR ) { - D(bug("gethostname() failed, error = %d\r\n", _WSAGetLastError())); - } else { - struct hostent *hent = _gethostbyname(me); - if( hent == NULL ) { - D(bug("gethostbyname() failed, error = %d\r\n", _WSAGetLastError())); - } else { - struct in_addr *ina = (struct in_addr *) *hent->h_addr_list; - router_ip_address = ntohl(ina->s_addr); - D(bug("router protocol address seems to be %s (used only in icmp error messages)\r\n", _inet_ntoa(*ina))); - } - } - is_router_shutting_down = false; - r_handle = (HANDLE)_beginthreadex( 0, 0, router_expire_thread, 0, 0, &rh_tid ); - init_interfaces(); - init_tcp(); - init_udp(); - init_ftp(); - return true; - } - - return false; -} - -void router_final(void) -{ - final_interfaces(); - stop_icmp_listen(); - close_all_sockets(); - if(r_handle) { - is_router_shutting_down = true; - WaitForSingleObject( r_handle, INFINITE ); - final_tcp(); - final_udp(); - dynsockets_final(); - } - DeleteCriticalSection( &router_section ); -} diff --git a/BasiliskII/src/Windows/router/router.h b/BasiliskII/src/Windows/router/router.h deleted file mode 100755 index 5d3e74b5..00000000 --- a/BasiliskII/src/Windows/router/router.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * router.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ROUTER_H_ -#define _ROUTER_H_ - -extern bool is_router_shutting_down; -extern CRITICAL_SECTION router_section; - -// Increased by one for each ip packet sent to the emulated enet interface. -extern uint16 next_ip_ident_number; - -// Used by incoming icmp packets and internal icmp messages. Host byte order. -extern uint32 macos_ip_address; - -// The magic constant -extern const uint8 router_mac_addr[6]; - -// Used by internal icmp messages. Host byte order. -extern uint32 router_ip_address; - -// False under NT/Win2k if the user has no admin rights -extern bool raw_sockets_available; - - - -// Interface exposed to ether_windows module. -bool router_init(void); -void router_final(void); - -// Both of these return true if the ethernet module should drop the packet. -bool router_write_packet(uint8 *packet, int len); -bool router_read_packet(uint8 *packet, int len); - -#endif // _ROUTER_H_ diff --git a/BasiliskII/src/Windows/router/router_types.h b/BasiliskII/src/Windows/router/router_types.h deleted file mode 100755 index 9dcc8e63..00000000 --- a/BasiliskII/src/Windows/router/router_types.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * router_types.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ROUTER_TYPES_H_ -#define _ROUTER_TYPES_H_ - -#pragma pack(push, 1) - - -// --------------------------- MAC --------------------------- -typedef struct { - uint8 dest[6]; - uint8 src[6]; - uint16 type; -} mac_t; - -enum { - mac_type_llc_ipx_limit = 0x05DC, // <= mac_type_llc_ipx_limit -->> 802.3 MAC frame - mac_type_ip4 = 0x0800, - mac_type_arp = 0x0806, - mac_type_rarp = 0x8035, - mac_type_ip6 = 0x86DD, - mac_type_loopback = 0x9000 -}; - -// --------------------------- ARP --------------------------- -typedef struct { - mac_t mac; - uint16 htype; - uint16 ptype; - uint8 halen; - uint8 palen; - uint16 opcode; - uint8 srch[6]; // size for ethernet - uint8 srcp[4]; // size for ip - uint8 dsth[6]; // size for ethernet - uint8 dstp[4]; // size for ip -} arp_t; - -enum { - arp_request = 1, - arp_reply = 2 -}; -enum { - arp_hwtype_enet = 1 -}; - -// --------------------------- IP4 --------------------------- -typedef struct { - mac_t mac; - uint8 header_len:4; - uint8 version:4; - uint8 tos; - uint16 total_len; - uint16 ident; - uint16 flags_n_frag_offset; // foffset 0..11, flags 12..15 - uint8 ttl; - uint8 proto; - uint16 checksum; - uint32 src; - uint32 dest; - // ip options, size = 4 * header_len - 20 -} ip_t; - -// Protocol STD numbers -enum { - ip_proto_icmp = IPPROTO_ICMP, - ip_proto_tcp = IPPROTO_TCP, - ip_proto_udp = IPPROTO_UDP -}; - -// --------------------------- ICMP --------------------------- -typedef struct { - ip_t ip; - uint8 type; - uint8 code; - uint16 checksum; - // data -} icmp_t; - -enum { - icmp_Echo_reply = 0, - icmp_Destination_unreachable = 3, - icmp_Source_quench = 4, - icmp_Redirect = 5, - icmp_Echo = 8, - icmp_Router_advertisement = 9, - icmp_Router_solicitation = 10, - icmp_Time_exceeded = 11, - icmp_Parameter_problem = 12, - icmp_Time_Stamp_request = 13, - icmp_Time_Stamp_reply = 14, - icmp_Information_request_obsolete = 15, - icmp_Information_reply_obsolete = 16, - icmp_Address_mask_request = 17, - icmp_Address_mask_reply = 18, - icmp_Traceroute = 30, - icmp_Datagram_conversion_error = 31, - icmp_Mobile_host_redirect = 32, - icmp_IPv6_Where_Are_You = 33, - icmp_IPv6_I_Am_Here = 34, - icmp_Mobile_registration_request = 35, - icmp_Mobile_registration_reply = 36, - icmp_Domain_name_request = 37, - icmp_Domain_name_reply = 38, - icmp_SKIP = 39, - icmp_Photuris = 40 -}; - -// --------------------------- TCP --------------------------- -typedef struct { - ip_t ip; - uint16 src_port; - uint16 dest_port; - uint32 seq; - uint32 ack; - uint8 header_len; // note: some reserved bits - uint8 flags; // note: some reserved bits - uint16 window; - uint16 checksum; - uint16 urgent_ptr; - // options + padding: size = dataoffset*4-20 - // data -} tcp_t; - -enum { - tcp_flags_URG = 0x20, // The urgent pointer field is significant in this segment. - tcp_flags_ACK = 0x10, // The acknowledgment field is significant in this segment. - tcp_flags_PSH = 0x08, // Push function. - tcp_flags_RST = 0x04, // Resets the connection. - tcp_flags_SYN = 0x02, // Synchronizes the sequence numbers. - tcp_flags_FIN = 0x01 // No more data from sender. -}; - -enum { - tcp_state_closed, - tcp_state_listen, - tcp_state_syn_sent, - tcp_state_syn_rcvd, - tcp_state_established, - tcp_state_close_wait, - tcp_state_last_ack, - tcp_state_finwait_1, - tcp_state_finwait_2, - tcp_state_closing, - tcp_state_time_wait -}; - -// --------------------------- UDP --------------------------- -typedef struct { - ip_t ip; - uint16 src_port; - uint16 dest_port; - uint16 msg_len; - uint16 checksum; - // data -} udp_t; - -typedef struct { - uint16 src_lo, src_hi; - uint16 dest_lo, dest_hi; - uint16 proto; - uint16 msg_len; -} pseudo_ip_t; - -#pragma pack(pop) - -#endif // _ROUTER_TYPES_H_ diff --git a/BasiliskII/src/Windows/router/tcp.cpp b/BasiliskII/src/Windows/router/tcp.cpp deleted file mode 100755 index 4b0800dd..00000000 --- a/BasiliskII/src/Windows/router/tcp.cpp +++ /dev/null @@ -1,1605 +0,0 @@ -/* - * tcp.cpp - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Features implemented: - * state machine, flow control, sequence numbers, RST/SYN/FIN/ACK/PSH - * - * Features not implemented: - * oob data, urgent pointer, window sliding, some options - * "Half-Nagle" implementation is a bit weird (mac-router interface; winsock has it on by default) - * - * - * All possible tcp state machine transitions: - * - * CLOSED -> LISTEN passive open - * CLOSED -> SYN_SENT active open SYN-> - * - * LISTEN -> SYN_SENT send data SYN-> - * LISTEN -> SYN_RCVD ->SYN SYN+ACK-> - * - * SYN_SENT -> SYN_RCVD ->SYN SYN+ACK-> - * SYN_SENT -> ESTABLISHED ->SYN+ACK ACK-> - * SYN_SENT -> CLOSED close/timeout - * - * SYN_RCVD -> CLOSED timeout RST-> - * SYN_RCVD -> LISTEN ->RST - * SYN_RCVD -> ESTABLISHED ->ACK - * SYN_RCVD -> FINWAIT_1 close FIN-> - * - * ESTABLISHED -> FINWAIT_1 close FIN-> - * ESTABLISHED -> CLOSE_WAIT ->FIN ACK-> - * - * CLOSE_WAIT -> LAST_ACK close FIN-> - * - * LAST_ACK -> CLOSED ->ACK - * - * FINWAIT_1 -> CLOSING ->FIN ACK-> - * FINWAIT_1 -> FINWAIT_2 ->ACK - * FINWAIT_1 -> TIME_WAIT ->FIN+ACK ACK-> - * - * FINWAIT_2 -> TIME_WAIT ->FIN ACK-> - * - * CLOSING -> TIME_WAIT ->ACK - * - * TIME_WAIT -> CLOSED timeout (2*msl) - * - */ - -#include "sysdeps.h" -#include "main.h" - -#include - -#include "cpu_emulation.h" -#include "ws2tcpip.h" -#include "ether_windows.h" -#include "ether.h" -#include "prefs.h" -#include "router.h" -#include "router_types.h" -#include "dynsockets.h" -#include "iphelp.h" -#include "tcp.h" -#include "dump.h" -#include "mib/interfaces.h" -#include "ftp.h" - -#if DEBUG -#pragma optimize("",off) -#endif - -#include "debug.h" - -// If you need more, use multiple threads. -#define MAX_SOCKETS MAXIMUM_WAIT_OBJECTS - -// If true, always sends the PSH tcp flag with data. -// Otherwise only when a full buffer was received. -#define PUSH_ALWAYS 0 - -// In milliseconds. A TCP implementation should implement -// this dynamically, adapting the timeout value to match to the -// averaged packet round-trip time. -#define RESEND_TIMEOUT 750 - -// Just time out incoming connections after 5 secs if Mac has no time to reply -// No backlogs. -#define SYN_FLOOD_PROTECTION_TIMEOUT 5000 - -const int MAX_SEGMENT_SIZE = 1460; - -// Shorthands -#define ISSET(f,x) ( ((f) & (x)) != 0 ) -#define ISCLEAR(f,x) ( ((f) & (x)) == 0 ) - -// Local aliases -#define URG tcp_flags_URG -#define ACK tcp_flags_ACK -#define PSH tcp_flags_PSH -#define RST tcp_flags_RST -#define SYN tcp_flags_SYN -#define FIN tcp_flags_FIN - -// Local aliases -#define CLOSED tcp_state_closed -#define LISTEN tcp_state_listen -#define SYN_SENT tcp_state_syn_sent -#define SYN_RCVD tcp_state_syn_rcvd -#define ESTABLISHED tcp_state_established -#define CLOSE_WAIT tcp_state_close_wait -#define LAST_ACK tcp_state_last_ack -#define FINWAIT_1 tcp_state_finwait_1 -#define FINWAIT_2 tcp_state_finwait_2 -#define CLOSING tcp_state_closing -#define TIME_WAIT tcp_state_time_wait - -// For debugging only -static const char *_tcp_state_name[] = { - "CLOSED", - "LISTEN", - "SYN_SENT", - "SYN_RCVD", - "ESTABLISHED", - "CLOSE_WAIT", - "LAST_ACK", - "FINWAIT_1", - "FINWAIT_2", - "CLOSING", - "TIME_WAIT" -}; -#define STATENAME(i) _tcp_state_name[i] - -static CRITICAL_SECTION tcp_section; - -typedef struct { - SOCKET s; - int state; - - uint32 ip_src; // "source" is the mac, dest is the remote host, - uint32 ip_dest; // no matter who opened the connection. - uint16 src_port; // all in host byte order. - uint16 dest_port; - - struct sockaddr_in from; // remote host address, network byte order. - int from_len; - - // note: no true windows sliding, only one buffer. - WSABUF buffers_read[1]; // data from remote host to Mac - DWORD buffer_count_read; - DWORD bytes_received; - DWORD flags_read; - WSAOVERLAPPED overlapped_read; - - WSABUF buffers_write[1]; // data from Mac to remote host - DWORD buffer_count_write; - DWORD bytes_written; - DWORD flags_write; - WSAOVERLAPPED overlapped_write; - - bool remote_closed; // remote will not send any more data - bool accept_more_data_from_mac; // are we ready to accept more data from mac - - uint32 seq_in; // will ack this mac sequence number - uint32 seq_out; // next sequence number to mac (unless a resend is needed) - uint32 mac_ack; // mac has acked this byte count. can be used to determined when to send some more data - - uint32 bytes_to_send; // total send block size - uint32 bytes_remaining_to_send; // unsent byte count - - uint16 mac_window; // mac tcp receive window, slides according to the window principle - uint16 our_window; // not really used - uint16 mac_mss; // maximum segment size that mac reported at SYN handshaking - - // resend info - uint32 last_seq_out; // remember last packet seq number if a resend is needed - uint32 resend_timeout; // currently set t0 0.75 secs but not updated - uint32 stream_to_mac_stalled_until; // tick count indicating resend time - - DWORD time_wait; // do a graceful close after MSL*2 - DWORD msl; - - int child; - - WSAEVENT ev; // used to signal remote-initiated close and host-initiated connect. - - bool in_use; -} tcp_socket_t; - -static tcp_socket_t sockets[MAX_SOCKETS]; - -typedef struct { - SOCKET s; - uint16 port; - uint32 ip; - uint32 iface; - bool once; - int parent; - WSAEVENT ev; -} tcp_listening_socket_t; - -static tcp_listening_socket_t l_sockets[MAX_SOCKETS]; - -static void CALLBACK tcp_read_completion( - DWORD error, - DWORD bytes_read, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -); - -static void CALLBACK tcp_write_completion( - DWORD error, - DWORD bytes_read, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -); - -// socket utilities assume that the critical section has already been entered. -static void free_socket( const int t ) -{ - _WSAResetEvent( sockets[t].ev ); - if(sockets[t].s != INVALID_SOCKET) { - _closesocket( sockets[t].s ); - sockets[t].s = INVALID_SOCKET; - } - sockets[t].state = CLOSED; - sockets[t].stream_to_mac_stalled_until = 0; - sockets[t].in_use = false; - sockets[t].time_wait = 0; - - // if there was an attached listening socket (ftp), close it. - int lst = sockets[t].child; - if( lst >= 0 ) { - if(l_sockets[lst].s != INVALID_SOCKET) { - D(bug(" closing listening socket %d\r\n", lst)); - _closesocket( l_sockets[lst].s ); - l_sockets[lst].s = INVALID_SOCKET; - } - l_sockets[lst].port = 0; - l_sockets[lst].parent = -1; - } - sockets[t].child = -1; -} - -static int alloc_socket() -{ - static int last_allocated_socket = -1; - - int i = last_allocated_socket; - for( int j=0; j= MAX_SOCKETS ) i = 0; - if( !sockets[i].in_use ) { - D(bug("<%d> Socket allocated\r\n", i)); - - last_allocated_socket = i; - sockets[i].in_use = true; - - sockets[i].s = INVALID_SOCKET; - sockets[i].state = CLOSED; - sockets[i].remote_closed = false; - - sockets[i].accept_more_data_from_mac = false; - - sockets[i].ip_src = sockets[i].ip_dest = 0; - // sockets[i].src_port = sockets[i].dest_port = 0; - - memset( &sockets[i].overlapped_read, 0, sizeof(sockets[i].overlapped_read) ); - sockets[i].overlapped_read.hEvent = (HANDLE)i; - memset( &sockets[i].overlapped_write, 0, sizeof(sockets[i].overlapped_write) ); - sockets[i].overlapped_write.hEvent = (HANDLE)i; - - sockets[i].bytes_received = 0; - sockets[i].bytes_written = 0; - - sockets[i].flags_read = 0; - sockets[i].flags_write = 0; - - // sockets[i].from_len = sizeof(struct sockaddr_in); - // memset( &sockets[i].from, 0, sizeof(sockets[i].from) ); - // sockets[i].from.sin_family = AF_INET; - - sockets[i].buffer_count_read = 1; - sockets[i].buffers_read[0].len = MAX_SEGMENT_SIZE; - if(!sockets[i].buffers_read[0].buf) { - sockets[i].buffers_read[0].buf = new char [sockets[i].buffers_read[0].len]; - } - - sockets[i].buffer_count_write = 1; - sockets[i].buffers_write[0].len = MAX_SEGMENT_SIZE; - if(!sockets[i].buffers_write[0].buf) { - sockets[i].buffers_write[0].buf = new char [sockets[i].buffers_write[0].len]; - } - - sockets[i].mac_window = MAX_SEGMENT_SIZE; // updated for all mac datagrams - sockets[i].our_window = MAX_SEGMENT_SIZE; // should use about 8-16 kB, really - sockets[i].mac_mss = 0; // not known yet - - sockets[i].time_wait = 0; - sockets[i].msl = 5000L; // The round-trip time can be hard to estimate. - - sockets[i].seq_in = 0; - sockets[i].seq_out = 0x00000001; - sockets[i].mac_ack = 0; - sockets[i].stream_to_mac_stalled_until = 0; - - sockets[i].resend_timeout = RESEND_TIMEOUT; - - sockets[i].child = -1; - - break; - } - } - if(i == MAX_SOCKETS) { - D(bug("Out of free sockets\r\n")); - i = -1; - } - return i; -} - -static int alloc_new_socket( const uint16 src_port, const uint16 dest_port, const uint32 ip_dest ) -{ - int t = alloc_socket(); - - if(t >= 0) { - sockets[t].s = _socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if(sockets[t].s == INVALID_SOCKET) { - free_socket( t ); - t = -1; - } else { - sockets[t].src_port = src_port; - sockets[t].dest_port = dest_port; - - sockets[t].from_len = sizeof(sockets[t].from); - memset( &sockets[t].from, 0, sockets[t].from_len ); - sockets[t].from.sin_family = AF_INET; - sockets[t].from.sin_port = htons(dest_port); - sockets[t].from.sin_addr.s_addr = htonl(ip_dest); - - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - - if( _bind ( sockets[t].s, (const struct sockaddr *)&to, sizeof(to) ) == 0 ) { - D(bug("<%d> socket bound\r\n", t)); - } else { - if( _WSAGetLastError() == WSAEINPROGRESS ) { - D(bug("<%d> bind: a blocking call is in progress.\r\n", t)); - } else { - D(bug("<%d> bind failed with error code %d\r\n", t, _WSAGetLastError())); - } - free_socket( t ); - t = -1; - } - } - } - return t; -} - -static int get_socket_index( const uint16 src_port, const uint16 dest_port ) -{ - for( int i=0; i= 0 ) { - if( sockets[i].s == INVALID_SOCKET ) { - D(bug("find_socket reusing slot %d...\r\n", i)); - sockets[i].in_use = false; - } else { - D(bug("find_socket forcing close %d...\r\n", i)); - free_socket( i ); - } - i = -1; - } - } - - D(bug("<%d> find_socket(%d,%d): %s\r\n", i, src_port, dest_port, i>=0 ? "found" : "not found")); - - return i; -} - -static int alloc_listen_socket( const uint16 port, const uint32 ip, const uint32 iface, const bool once ) -{ - static int last_allocated_socket = -1; - - int i = last_allocated_socket; - - for( int j=0; j= MAX_SOCKETS ) i = 0; - if( l_sockets[i].port == 0 ) { - D(bug("[%d] Slot allocated for listening port %d\r\n", i, port)); - l_sockets[i].port = port; - l_sockets[i].ip = ip; - l_sockets[i].iface = iface; - l_sockets[i].once = once; - l_sockets[i].parent = -1; - last_allocated_socket = i; - _WSAResetEvent( l_sockets[i].ev ); - return i; - } - } - return -1; -} - -static void tcp_start_listen( const int i ) -{ - if( l_sockets[i].port ) { - uint32 iface = l_sockets[i].iface; - - D(bug("[%d] binding to interface 0x%08X\r\n", i, iface)); - - l_sockets[i].s = _socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if(l_sockets[i].s != INVALID_SOCKET) { - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - to.sin_port = htons( l_sockets[i].port ); - to.sin_addr.s_addr = htonl( iface ); - - if( _bind ( l_sockets[i].s, (const struct sockaddr *)&to, sizeof(to) ) == 0 ) - { - D(bug("[%d] socket bound to port %d on interface 0x%08X\r\n", i, l_sockets[i].port, iface)); - if( _listen( l_sockets[i].s, SOMAXCONN ) == SOCKET_ERROR ) { - D(bug("[%d] listen() failed with error code %d\r\n", i, _WSAGetLastError())); - } else { - D(bug("[%d] listening to port %d\r\n", i, l_sockets[i].port)); - _WSAResetEvent( l_sockets[i].ev ); - if( SOCKET_ERROR == _WSAEventSelect( l_sockets[i].s, l_sockets[i].ev, FD_ACCEPT ) ) { - D(bug("[%d] WSAEventSelect() failed with error code %d\r\n", i, _WSAGetLastError())); - } - } - } else { - D(bug("[%d] bind to port %d failed with error code %d\r\n", i, l_sockets[i].port, _WSAGetLastError())); - } - } else { - D(bug("[%d] could not create a socket for port %d, error = %d\r\n", i, l_sockets[i].port, _WSAGetLastError())); - } - } -} - -static void set_ttl( const int t, const uint8 ttl ) -{ - int _ttl = ttl; // defensive programming, I know VCx - - if(_setsockopt( sockets[t].s, IPPROTO_IP, IP_TTL, (const char *)&_ttl, sizeof(int) ) == SOCKET_ERROR ) { - D(bug("<%d> could not set ttl to %d, error=%d\r\n", t, ttl, _WSAGetLastError())); - } else { - D(bug("<%d> ttl set to %d.\r\n", t, ttl)); - } -} - -static void tcp_reply( const int flags, const int t ) -{ - int tcp_size = sizeof(tcp_t); - - tcp_t *tcp = (tcp_t *)malloc( tcp_size ); - if(tcp) { - memcpy( tcp->ip.mac.dest, ether_addr, 6 ); - memcpy( tcp->ip.mac.src, router_mac_addr, 6 ); - tcp->ip.mac.type = htons(mac_type_ip4); - - tcp->ip.version = 4; - tcp->ip.header_len = 5; - tcp->ip.tos = 0; - tcp->ip.total_len = htons(tcp_size - sizeof(mac_t)); - tcp->ip.ident = htons(next_ip_ident_number++); - tcp->ip.flags_n_frag_offset = 0; - tcp->ip.ttl = 128; - tcp->ip.proto = ip_proto_tcp; - tcp->ip.src = htonl(sockets[t].ip_dest); - tcp->ip.dest = htonl(sockets[t].ip_src); - make_ip4_checksum( (ip_t *)tcp ); - - D(bug("<%d> Reply: Seq=%d, Ack=%d\r\n", t, sockets[t].seq_out, sockets[t].seq_in)); - - tcp->src_port = htons(sockets[t].dest_port); - tcp->dest_port = htons(sockets[t].src_port); - tcp->seq = htonl(sockets[t].seq_out); - tcp->ack = htonl(sockets[t].seq_in); - tcp->header_len = (uint8)( 20 << 2 ); - tcp->flags = flags; - tcp->window = htons( sockets[t].our_window ); - tcp->urgent_ptr = 0; - make_tcp_checksum( tcp, tcp_size ); - - // dump_bytes( (uint8 *)tcp, tcp_size ); - - enqueue_packet( (uint8 *)tcp, tcp_size ); - free(tcp); - } -} - -static bool has_mac_read_space( const int t ) -{ - uint32 pending_bytes = sockets[t].seq_out - sockets[t].mac_ack; - uint32 mac_can_accept_bytes = sockets[t].mac_window - pending_bytes; - - D(bug("<%d> mac_can_accept_bytes = %d\r\n", t, mac_can_accept_bytes)); - - // Modified Nagle, effectively disabling window sliding (which I don't support anyway): - return pending_bytes == 0; - - // Use more of window bandwidth - // Enabling this would require that the buffers seq numbers are stored somewhere - // return mac_can_accept_bytes >= sockets[t].buffers_read[0].len; -} - -static bool b_recfrom( const int t ) -{ - bool result; - - if( !has_mac_read_space(t) ) { - D(bug("<%d> read stalled, mac cannot accept any more data\r\n", t)); - - sockets[t].stream_to_mac_stalled_until = GetTickCount() + sockets[t].resend_timeout; - return true; - } - - int ret = _WSARecv( - sockets[t].s, - sockets[t].buffers_read, - sockets[t].buffer_count_read, - &sockets[t].bytes_received, - &sockets[t].flags_read, - &sockets[t].overlapped_read, - tcp_read_completion - ); - - if(ret == SOCKET_ERROR) { - int socket_error = _WSAGetLastError(); - if(socket_error == WSA_IO_PENDING) { - D(bug("<%d> WSARecv() i/o pending\r\n", t)); - result = true; - } else { - D(bug("<%d> WSARecv() returned error %d\r\n", t, socket_error)); - result = false; - } - } else /*if(ret == 0) */ { - D(bug("<%d> WSARecv() ok\r\n", t)); - // Completion routine call is already scheduled. - result = true; - } - return result; -} - -static bool b_send( const int t ) -{ - int ret = _WSASend( - sockets[t].s, - sockets[t].buffers_write, - sockets[t].buffer_count_write, - &sockets[t].bytes_written, - sockets[t].flags_write, - &sockets[t].overlapped_write, - tcp_write_completion - ); - - bool result; - if(ret == SOCKET_ERROR) { - int socket_error = _WSAGetLastError(); - if(socket_error == WSA_IO_PENDING) { - D(bug("<%d> WSASend() i/o pending\r\n", t)); - result = true; - } else { - D(bug("<%d> WSASend() returned %d\r\n", t, socket_error)); - result = false; - } - } else /*if(ret == 0) */ { - D(bug("<%d> WSASend() ok\r\n", t)); - // Completion routine call is already scheduled. - result = true; - } - return result; -} - -static void send_buffer( const int t, const bool resending ) -{ - if(resending) { - if(sockets[t].last_seq_out == 0) { - D(bug("<%d> resend failure\r\n", t )); - return; - } - sockets[t].seq_out = sockets[t].last_seq_out; - } else { - sockets[t].last_seq_out = sockets[t].seq_out; - } - - D(bug("<%d> %s data to Mac: Seq=%d, Ack=%d\r\n", t, (resending ? "resending" : "sending"), sockets[t].seq_out, sockets[t].seq_in)); - - uint32 bytes_read = sockets[t].bytes_received; - - if( sockets[t].mac_mss && bytes_read > sockets[t].mac_mss ) { - D(bug("<%d> impossible: %d bytes to send, Mac mss is only %d\r\n", t, sockets[t].mac_mss && bytes_read, sockets[t].mac_mss)); - } - - int tcp_size = sizeof(tcp_t) + bytes_read; - - tcp_t *tcp = (tcp_t *)malloc( tcp_size ); - if(tcp) { - // Build MAC - // memcpy( tcp->ip.mac.dest, sockets[t].mac_src, 6 ); - memcpy( tcp->ip.mac.dest, ether_addr, 6 ); - memcpy( tcp->ip.mac.src, router_mac_addr, 6 ); - tcp->ip.mac.type = htons(mac_type_ip4); - - // Build IP - tcp->ip.version = 4; - tcp->ip.header_len = 5; - tcp->ip.tos = 0; - tcp->ip.total_len = htons(sizeof(tcp_t) - sizeof(mac_t) + bytes_read); // no options - tcp->ip.ident = htons(next_ip_ident_number++); - tcp->ip.flags_n_frag_offset = 0; - tcp->ip.ttl = 128; // one hop actually! - tcp->ip.proto = ip_proto_tcp; - tcp->ip.src = htonl(sockets[t].ip_dest); - tcp->ip.dest = htonl(sockets[t].ip_src); - make_ip4_checksum( (ip_t *)tcp ); - - // Copy payload (used by tcp checksum) - memcpy( (char *)tcp + sizeof(tcp_t), sockets[t].buffers_read[0].buf, bytes_read ); - - // Build tcp - tcp->src_port = htons(sockets[t].dest_port); - tcp->dest_port = htons(sockets[t].src_port); - - tcp->seq = htonl(sockets[t].seq_out); - tcp->ack = htonl(sockets[t].seq_in); - - tcp->header_len = (uint8)( 20 << 2 ); -#if PUSH_ALWAYS - tcp->flags = ACK|PSH; -#else - tcp->flags = (bytes_read == MAX_SEGMENT_SIZE) ? ACK : (ACK|PSH); -#endif - tcp->window = htons( sockets[t].our_window ); - tcp->urgent_ptr = 0; - make_tcp_checksum( tcp, tcp_size ); - - sockets[t].seq_out += bytes_read; - - // dump_bytes( (uint8 *)tcp, tcp_size ); - - enqueue_packet( (uint8 *)tcp, tcp_size ); - free(tcp); - } -} - -static void CALLBACK tcp_read_completion( - DWORD error, - DWORD bytes_read, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -) -{ - EnterCriticalSection( &tcp_section ); - - const int t = (int)lpOverlapped->hEvent; - - sockets[t].bytes_received = bytes_read; - - D(bug("<%d> tcp_read_completion(error=%d, bytes_read=%d)\r\n", t, error, bytes_read)); - - D(bug("<%d> tcp_read_completion() start, old state = %s\r\n", t, STATENAME(sockets[t].state))); - - if(!sockets[t].in_use) { - D(bug("<%d> ignoring canceled read\r\n", t)); - } else { - if( error != 0 ) { - D(bug("<%d> resetting after read error\r\n", t)); - tcp_reply( RST, t ); - free_socket(t); - } else { - if(bytes_read == 0) { - _closesocket( sockets[t].s ); - sockets[t].s = INVALID_SOCKET; - } else if( bytes_read > 0) { - send_buffer( t, false ); - } - - switch( sockets[t].state ) { - case SYN_RCVD: - if( bytes_read == 0 ) { - D(bug("<%d> Closing: SYN_RCVD -> FINWAIT_1\r\n", t)); - tcp_reply( ACK|FIN, t ); - sockets[t].seq_out++; - sockets[t].state = FINWAIT_1; - } - break; - case ESTABLISHED: - if( bytes_read == 0 ) { - D(bug("<%d> Closing: ESTABLISHED -> FINWAIT_1\r\n", t)); - tcp_reply( ACK|FIN, t ); - sockets[t].seq_out++; - sockets[t].state = FINWAIT_1; - } - break; - case LISTEN: - tcp_reply( SYN, t ); - sockets[t].seq_out++; - sockets[t].state = SYN_SENT; - sockets[t].time_wait = GetTickCount() + SYN_FLOOD_PROTECTION_TIMEOUT; - D(bug("<%d> LISTEN -> SYN_SENT\r\n", t)); - break; - case CLOSE_WAIT: - if( bytes_read == 0) { - tcp_reply( ACK|FIN, t ); - sockets[t].seq_out++; - sockets[t].state = LAST_ACK; - D(bug("<%d> Closing: CLOSE_WAIT -> LAST_ACK\r\n", t)); - if(sockets[t].remote_closed) { - // Just in case that mac gets out of sync. - _closesocket(sockets[t].s); - sockets[t].s = INVALID_SOCKET; - } - } - break; - default: - break; - } - - if(!is_router_shutting_down && sockets[t].s != INVALID_SOCKET) { - if(sockets[t].state != LISTEN) { - b_recfrom(t); - } - } - } - } - - LeaveCriticalSection( &tcp_section ); -} - -static void CALLBACK tcp_write_completion( - DWORD error, - DWORD bytes_written, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -) -{ - EnterCriticalSection( &tcp_section ); - - const int t = (int)lpOverlapped->hEvent; - - sockets[t].bytes_written = bytes_written; - sockets[t].bytes_remaining_to_send -= bytes_written; - - D(bug("<%d> tcp_write_completion(error=%d, bytes_written=%d)\r\n", t, error, bytes_written)); - - if(!sockets[t].in_use) { - D(bug("<%d> ignoring canceled write\r\n", t)); - } else { - if(is_router_shutting_down || sockets[t].s == INVALID_SOCKET) { - D(bug("<%d> is not alive for sending.\r\n", t)); - } else { - if( sockets[t].bytes_remaining_to_send <= 0 ) { - D(bug("<%d> all data sent, accepting some more.\r\n", t)); - sockets[t].seq_in += sockets[t].bytes_to_send; - sockets[t].bytes_to_send = sockets[t].bytes_remaining_to_send = 0; // superfluous - tcp_reply( ACK, t ); - sockets[t].accept_more_data_from_mac = true; - } else { - D(bug("<%d> %d bytes (of %d total) remaining, sending.\r\n", t, sockets[t].bytes_remaining_to_send, sockets[t].bytes_to_send)); - sockets[t].buffers_write[0].len = sockets[t].bytes_remaining_to_send; - char *p = sockets[t].buffers_write[0].buf; - memmove( p, &p[bytes_written], sockets[t].bytes_remaining_to_send ); - if(!b_send(t)) { - } else { - } - } - } - } - - LeaveCriticalSection( &tcp_section ); -} - -static void tcp_connect_callback( const int t ) -{ - D(bug("<%d> tcp_connect_callback() start, old state = %s\r\n", t, STATENAME(sockets[t].state))); - - switch( sockets[t].state ) { - case LISTEN: - tcp_reply( SYN|ACK, t ); - sockets[t].seq_out++; - sockets[t].state = SYN_RCVD; - D(bug("<%d> Connect: LISTEN -> SYN_RCVD\r\n", t)); - break; - default: - break; - } - D(bug("<%d> tcp_connect_callback() end, new state = %s\r\n", t, STATENAME(sockets[t].state))); -} - -static void tcp_accept_callback( const int lst ) -{ - D(bug("[%d] tcp_accept_callback()\r\n", lst)); - - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - int tolen = sizeof(to); - - SOCKET s = _accept( l_sockets[lst].s, (struct sockaddr *)&to, &tolen ); - if( s == INVALID_SOCKET ) { - D(bug("[%d] connection not accepted, error code %d\r\n", lst, _WSAGetLastError())); - } else { - _WSAEventSelect( s, 0, 0 ); - - uint16 src_port = l_sockets[lst].port; - uint16 dest_port = ntohs(to.sin_port); - uint32 ip_dest = ntohl(to.sin_addr.s_addr); - - D(bug("[%d] connection accepted, local port:%d, remote %s:%d\r\n", lst, src_port, _inet_ntoa(to.sin_addr), dest_port)); - - if( l_sockets[lst].ip != 0 && l_sockets[lst].ip != ip_dest ) { - _closesocket( s ); - D(bug("[%d] authorization failure. connection closed.\r\n", lst )); - } else { - int t = alloc_new_socket( src_port, dest_port, ip_dest ); - if( t < 0 ) { - D(bug("<%d> out of slot space, connection dropped\r\n", t )); - free_socket(t); - } else { - sockets[t].s = s; - sockets[t].state = LISTEN; - sockets[t].src_port = src_port; - sockets[t].dest_port = dest_port; - sockets[t].ip_src = macos_ip_address; - sockets[t].ip_dest = ip_dest; - - sockets[t].seq_out = 0x00000001; - sockets[t].seq_in = 0; // not known yet - sockets[t].mac_ack = sockets[t].seq_out; // zero out pending bytes - - tcp_reply( SYN, t ); - sockets[t].seq_out++; - sockets[t].state = SYN_SENT; - sockets[t].time_wait = GetTickCount() + SYN_FLOOD_PROTECTION_TIMEOUT; - D(bug("<%d> Connect: LISTEN -> SYN_SENT\r\n", t)); - - _WSAResetEvent( sockets[t].ev ); - if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CLOSE ) ) { - D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError())); - } - - // No data from the remote host is needed until the connection is established. - // So don't initiate read yet. - } - } - } -} - -/* - MSS is the only option I care about, and since I'm on ethernet - I already pretty much know everything needed. - - AFAIK window scaling is not in effect unless both parties specify it, - and I'm not doing it. -*/ -static void process_options( const int t, const uint8 *opt, int len, uint32 &mss ) -{ - mss = 0; - - while( len > 0 ) { - switch( *opt ) { - case 0: // End of Option List - D(bug("<%d> End of Option List\r\n", t)); - len = 0; - break; - case 1: // No-Operation - D(bug("<%d> No-Operation\r\n", t)); - len--; - opt++; - break; - case 2: // Maximum Segment Size - { - mss = ntohs( *((uint16 *)&opt[2]) ); - D(bug("<%d> Maximum Segment Size = %d\r\n", t, mss)); - len -= 4; - opt += 4; - } - break; - case 3: // Window Scale - { - int wscale = opt[2]; - D(bug("<%d> Window Scale = %d\r\n", t, (int)wscale)); - len -= 3; - opt += 3; - } - break; - case 4: // Sack-Permitted - D(bug("<%d> Sack-Permitted option is set\r\n", t)); - len -= 2; - opt += 2; - break; - case 5: // Sack - { - int sack_len = opt[1]; - int hf = (sack_len-2) / 4; - D(bug("<%d> Sack, %d half-blocks\r\n", t, hf)); - len -= sack_len; - opt += sack_len; - } - break; - case 8: // Time Stamps - { - int valve = ntohl( *((uint32 *)&opt[2]) ); - int ereply = ntohl( *((uint32 *)&opt[6]) ); - D(bug("<%d> Time Stamps, TS valve = 0x%X, TS echo reply = 0x%X\r\n", t, valve, ereply)); - len -= 10; - opt += 10; - } - break; - default: - D(bug("<%d> Unknown tcp header option 0x%02x, breaking out\r\n", t, (int)*opt)); - len = 0; - break; - } - } -} - -void write_tcp( tcp_t *tcp, int len ) -{ - if(len < sizeof(tcp_t)) { - D(bug("<%d> Too small tcp packet(%d) on unknown slot, dropped\r\n", -1, len)); - return; - } - uint16 src_port = ntohs(tcp->src_port); - uint16 dest_port = ntohs(tcp->dest_port); - - BOOL ok = true; - BOOL handle_data = false; - BOOL initiate_read = false; - - EnterCriticalSection( &tcp_section ); - - int t = find_socket( src_port, dest_port ); - - if(t < 0) { - t = alloc_new_socket( src_port, dest_port, ntohl(tcp->ip.dest) ); - ok = t >= 0; - } - - if(ok) { - D(bug("<%d> write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port)); - } else { - D(bug("<%d> FAILED write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port)); - } - - if( ok && ISSET(tcp->flags,RST) ) { - D(bug("<%d> RST set, resetting socket\r\n", t)); - if( sockets[t].s != INVALID_SOCKET ) { - D(bug("<%d> doing an extra shutdown (ie4)\r\n", t)); - _shutdown( sockets[t].s, SD_BOTH ); - } - free_socket( t ); - ok = false; - } - - if(ok) { - D(bug("<%d> State machine start = %s\r\n", t, STATENAME(sockets[t].state))); - - // always update receive window - sockets[t].mac_window = ntohs(tcp->window); - - int header_len = tcp->header_len >> 2; - int option_bytes = header_len - 20; - char *data = (char *)tcp + sizeof(tcp_t) + option_bytes; - int dlen = len - sizeof(tcp_t) - option_bytes; - - if( !ISSET(tcp->flags,ACK) ) { - D(bug("<%d> ACK not set\r\n", t)); - } - if( ISSET(tcp->flags,SYN) ) { - D(bug("<%d> SYN set\r\n", t)); - - // Note that some options are valid even if there is no SYN. - // I don't care about those however. - - uint32 new_mss; - process_options( t, (uint8 *)data - option_bytes, option_bytes, new_mss ); - if(new_mss) { - sockets[t].mac_mss = (int)new_mss; - if( new_mss < sockets[t].buffers_read[0].len ) { - sockets[t].buffers_read[0].len = new_mss; - } - D(bug("<%d> Max segment size set to %d\r\n", t, new_mss)); - } - } - if( ISSET(tcp->flags,FIN) ) { - D(bug("<%d> FIN set\r\n", t)); - } - - // The sequence number Mac expects to see next time. - sockets[t].mac_ack = ntohl(tcp->ack); - - D(bug("<%d> From Mac: Seq=%d, Ack=%d, window=%d, router Seq=%d\r\n", t, ntohl(tcp->seq), sockets[t].mac_ack, sockets[t].mac_window, sockets[t].seq_out)); - - if( sockets[t].stream_to_mac_stalled_until && - sockets[t].mac_ack == sockets[t].seq_out && - (sockets[t].state == ESTABLISHED || sockets[t].state == CLOSE_WAIT) ) - { - if( has_mac_read_space(t) ) { - initiate_read = true; - sockets[t].stream_to_mac_stalled_until = 0; - D(bug("<%d> read resumed, mac can accept more data\r\n", t)); - } - } - - switch( sockets[t].state ) { - case CLOSED: - sockets[t].src_port = src_port; - sockets[t].dest_port = dest_port; - sockets[t].ip_src = ntohl(tcp->ip.src); - sockets[t].ip_dest = ntohl(tcp->ip.dest); - - if( ISSET(tcp->flags,SYN) ) { - - sockets[t].seq_out = 0x00000001; - sockets[t].seq_in = ntohl(tcp->seq) + 1; - - _WSAResetEvent( sockets[t].ev ); - if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CONNECT | FD_CLOSE ) ) { - D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError())); - } - - D(bug("<%d> connecting local port %d to remote %s:%d\r\n", t, src_port, _inet_ntoa(sockets[t].from.sin_addr), dest_port)); - - sockets[t].state = LISTEN; - if( _WSAConnect( - sockets[t].s, - (const struct sockaddr *)&sockets[t].from, - sockets[t].from_len, - NULL, NULL, - NULL, NULL - ) == SOCKET_ERROR ) - { - int connect_error = _WSAGetLastError(); - if( connect_error == WSAEWOULDBLOCK ) { - D(bug("<%d> WSAConnect() i/o pending.\r\n", t)); - } else { - D(bug("<%d> WSAConnect() failed with error %d.\r\n", t, connect_error)); - } - } else { - D(bug("<%d> WSAConnect() ok.\r\n", t)); - } - } else { - if( ISSET(tcp->flags,FIN) ) { - D(bug("<%d> No SYN but FIN on a closed socket.\r\n", t)); - free_socket(t); - } else { - D(bug("<%d> No SYN on a closed socket. resetting.\r\n", t)); - free_socket(t); - } - } - break; - case LISTEN: - // handled in connect callback - break; - case SYN_SENT: - if( ISSET(tcp->flags,SYN) && ISSET(tcp->flags,ACK) ) { - sockets[t].seq_in = ntohl(tcp->seq) + 1; - tcp_reply( ACK, t ); - sockets[t].state = ESTABLISHED; - initiate_read = true; - sockets[t].accept_more_data_from_mac = true; - sockets[t].time_wait = 0; - } else if( ISSET(tcp->flags,SYN) ) { - sockets[t].seq_in = ntohl(tcp->seq) + 1; - tcp_reply( ACK|SYN, t ); - sockets[t].seq_out++; - sockets[t].state = SYN_RCVD; - sockets[t].time_wait = 0; - } else if( ISSET(tcp->flags,ACK) ) { - // What was the bright idea here. - D(bug("<%d> State is SYN_SENT, but got only ACK from Mac??\r\n", t)); - sockets[t].state = FINWAIT_2; - sockets[t].time_wait = 0; - } - break; - case SYN_RCVD: - if( ISSET(tcp->flags,ACK) ) { - sockets[t].state = ESTABLISHED; - handle_data = true; - initiate_read = true; - sockets[t].accept_more_data_from_mac = true; - } - break; - case ESTABLISHED: - if( ISSET(tcp->flags,FIN) ) { - sockets[t].seq_in++; - tcp_reply( ACK, t ); - _shutdown( sockets[t].s, SD_SEND ); - sockets[t].state = CLOSE_WAIT; - } - handle_data = true; - break; - case CLOSE_WAIT: - // handled in tcp_read_completion - break; - case LAST_ACK: - if( ISSET(tcp->flags,ACK) ) { - D(bug("<%d> LAST_ACK received, socket closed\r\n", t)); - free_socket( t ); - } - break; - case FINWAIT_1: - if( ISSET(tcp->flags,FIN) && ISSET(tcp->flags,ACK) ) { - sockets[t].seq_in++; - tcp_reply( ACK, t ); - if(sockets[t].remote_closed) { - _closesocket(sockets[t].s); - sockets[t].s = INVALID_SOCKET; - } else { - _shutdown( sockets[t].s, SD_SEND ); - } - sockets[t].state = TIME_WAIT; - sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; - } else if( ISSET(tcp->flags,FIN) ) { - sockets[t].seq_in++; - tcp_reply( ACK, t ); - if(sockets[t].remote_closed) { - _closesocket(sockets[t].s); - sockets[t].s = INVALID_SOCKET; - } else { - _shutdown( sockets[t].s, SD_SEND ); - } - sockets[t].state = CLOSING; - } else if( ISSET(tcp->flags,ACK) ) { - sockets[t].state = FINWAIT_2; - } - break; - case FINWAIT_2: - if( ISSET(tcp->flags,FIN) ) { - sockets[t].seq_in++; - tcp_reply( ACK, t ); - if(sockets[t].remote_closed) { - _closesocket(sockets[t].s); - sockets[t].s = INVALID_SOCKET; - } else { - _shutdown( sockets[t].s, SD_SEND ); - } - sockets[t].state = TIME_WAIT; - sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; - } - break; - case CLOSING: - if( ISSET(tcp->flags,ACK) ) { - sockets[t].state = TIME_WAIT; - sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl; - } - break; - case TIME_WAIT: - // Catching stray packets: wait MSL * 2 seconds, -> CLOSED - // Timer already set since we might not get here at all. - // I'm using exceptionally low MSL value (5 secs). - D(bug("<%d> time wait, datagram discarded\r\n", t)); - break; - } - - // The "t" descriptor may already be freed. However, it's safe - // to peek the state value inside the critical section. - D(bug("<%d> State machine end = %s\r\n", t, STATENAME(sockets[t].state))); - - D(bug("<%d> handle_data=%d, initiate_read=%d\r\n", t, handle_data, initiate_read)); - - if( handle_data && dlen && sockets[t].accept_more_data_from_mac ) { - if( sockets[t].seq_in != ntohl(tcp->seq) ) { - D(bug("<%d> dropping duplicate datagram seq=%d, expected=%d\r\n", t, ntohl(tcp->seq), sockets[t].seq_in)); - } else { - set_ttl( t, tcp->ip.ttl ); - - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - to.sin_port = tcp->dest_port; - to.sin_addr.s_addr = tcp->ip.dest; - - D(bug("<%d> sending %d bytes to remote host\r\n", t, dlen)); - - sockets[t].accept_more_data_from_mac = false; - - if( dlen > MAX_SEGMENT_SIZE ) { - D(bug("<%d> IMPOSSIBLE: b_send() dropped %d bytes! \r\n", t, dlen-MAX_SEGMENT_SIZE)); - dlen = MAX_SEGMENT_SIZE; - } - - memcpy( sockets[t].buffers_write[0].buf, data, dlen ); - - sockets[t].buffers_write[0].len = dlen; - sockets[t].bytes_remaining_to_send = dlen; - sockets[t].bytes_to_send = dlen; - - bool send_now = false; - if( ISSET(tcp->flags,PSH) ) { - send_now = true; - } else { - // todo -- delayed send - send_now = true; - } - - if(send_now) { - - // Patch ftp server or client address if needed. - - int lst = 1; - bool is_pasv; - uint16 ftp_data_port = 0; - - if(ftp_is_ftp_port(sockets[t].src_port)) { - // Local ftp server may be entering to passive mode. - is_pasv = true; - ftp_parse_port_command( - sockets[t].buffers_write[0].buf, - dlen, - ftp_data_port, - is_pasv - ); - } else if(ftp_is_ftp_port(sockets[t].dest_port)) { - // Local ftp client may be using port command. - is_pasv = false; - ftp_parse_port_command( - sockets[t].buffers_write[0].buf, - dlen, - ftp_data_port, - is_pasv - ); - } - - if(ftp_data_port) { - D(bug("<%d> ftp %s command detected, port %d\r\n", t, (is_pasv ? "SERVER PASV REPLY" : "CLIENT PORT"), ftp_data_port )); - - // Note: for security reasons, only allow incoming connection from sockets[t].ip_dest - lst = alloc_listen_socket( ftp_data_port, sockets[t].ip_dest, 0/*iface*/, true ); - - if(lst < 0) { - D(bug("<%d> no more free slots\r\n", t)); - } else { - // First start listening (need to know the local name later) - tcp_start_listen( lst ); - - // When t is closed, lst must be closed too. - sockets[t].child = lst; - l_sockets[lst].parent = t; - - // Find out the local name - struct sockaddr_in name; - int namelen = sizeof(name); - memset( &name, 0, sizeof(name) ); - if( _getsockname( sockets[t].s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) { - D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() )); - } - - ftp_modify_port_command( - sockets[t].buffers_write[0].buf, - dlen, - MAX_SEGMENT_SIZE, - ntohl(name.sin_addr.s_addr), - ftp_data_port, - is_pasv - ); - - sockets[t].buffers_write[0].len = dlen; - sockets[t].bytes_remaining_to_send = dlen; - // Do not change "bytes_to_send" field as it is used for ack calculation - } - } // end of ftp patch - - if(!b_send(t)) { - // on error, close the ftp data listening socket if one was created - if(lst >= 0) { - D(bug("[%d] closing listening port %d after write error\r\n", t, l_sockets[lst].port)); - _closesocket( l_sockets[lst].s ); - l_sockets[lst].s = INVALID_SOCKET; - l_sockets[lst].port = 0; - l_sockets[lst].ip = 0; - l_sockets[lst].parent = -1; - sockets[t].child = -1; - } - } - } - } - } - - if(initiate_read) { - if(!b_recfrom(t)) { - // post icmp error message - } - } - } - - LeaveCriticalSection( &tcp_section ); -} - -/* - - Dispatch remote close and connect events. - - Expire time-waits. - - Handle resend timeouts. -*/ -static unsigned int WINAPI tcp_connect_close_thread(void *arg) -{ - WSAEVENT wait_handles[MAX_SOCKETS]; - - for( int i=0; i= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + MAX_SOCKETS ) { - const int t = ret - WAIT_OBJECT_0; - - D(bug("<%d> Event %d\r\n", t, ret)); - - if(sockets[t].in_use) { - WSANETWORKEVENTS what; - - if( _WSAEnumNetworkEvents( sockets[t].s, sockets[t].ev, &what ) != SOCKET_ERROR ) { - if( what.lNetworkEvents & FD_CONNECT ) { - if( what.iErrorCode[FD_CONNECT_BIT] == 0 ) { - D(bug("<%d> Connect ok\r\n", t)); - tcp_connect_callback(t); - } else { - D(bug("<%d> Connect error=%d\r\n", t, what.iErrorCode[FD_CONNECT_BIT])); - // Post icmp error - } - } else if( what.lNetworkEvents & FD_CLOSE ) { - if( what.iErrorCode[FD_CLOSE_BIT] == 0 ) { - D(bug("<%d> graceful close, state = %s\r\n", t, STATENAME(sockets[t].state))); - } else { - D(bug("<%d> abortive close, state = %s, code=%d\r\n", t, STATENAME(sockets[t].state), what.iErrorCode[FD_CLOSE_BIT])); - } - sockets[t].remote_closed = true; - } - } else { - int err = _WSAGetLastError(); - if( err == WSAENOTSOCK ) { - D(bug("<%d> WSAEnumNetworkEvents: socket is already closed\r\n", t)); - } else { - D(bug("<%d> WSAEnumNetworkEvents failed with error code %d, freeing slot\r\n", t, err)); - free_socket( t ); - } - } - } - _WSAResetEvent( sockets[t].ev ); - } else { - static int interval = 5; - if( !--interval ) { - for( int i=0; i= tmw ) { - if( sockets[i].state == SYN_SENT ) { - /* - A very basic SYN flood protection. Note that watching - SYN_SENT instead of SYN_RCVD, because the state codes are - from the point of view of the Mac-Router interface, not Router-Remote. - */ - D(bug("<%d> SYN_SENT time-out expired\r\n", i)); - } else { - D(bug("<%d> TIME_WAIT expired\r\n", i)); - } - free_socket( i ); - } - } else if( stl ) { - if( sockets[i].state == ESTABLISHED ) { - if( GetTickCount() >= stl ) { - D(bug("<%d> RESEND timeout expired\r\n", i)); - sockets[i].stream_to_mac_stalled_until = GetTickCount() + sockets[i].resend_timeout; - send_buffer( i, true ); - } - } else { - sockets[i].stream_to_mac_stalled_until = 0; - } - } - } - } - interval = 5; - } - } - LeaveCriticalSection( &tcp_section ); - } - return 0; -} - -static unsigned int WINAPI tcp_listen_thread(void *arg) -{ - WSAEVENT wait_handles[MAX_SOCKETS]; - - for( int i=0; i= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + MAX_SOCKETS ) { - const int lst = ret - WAIT_OBJECT_0; - - D(bug("[%d] connection attempt to port %d\r\n", lst, l_sockets[lst].port)); - - WSANETWORKEVENTS what; - - if( _WSAEnumNetworkEvents( l_sockets[lst].s, l_sockets[lst].ev, &what ) != SOCKET_ERROR ) { - if( what.lNetworkEvents & FD_ACCEPT ) { - if( what.iErrorCode[FD_ACCEPT_BIT] == 0 ) { - D(bug("[%d] Connect ok\r\n", lst)); - tcp_accept_callback(lst); - } else { - D(bug("[%d] Connect error=%d\r\n", lst, what.iErrorCode[FD_ACCEPT_BIT])); - // Post icmp error - } - } - } - - // close on errors too - if(l_sockets[lst].once) { - D(bug("[%d] once mode: closing listening socket on port %d\r\n", lst, l_sockets[lst].port)); - if( _closesocket( l_sockets[lst].s ) == SOCKET_ERROR ) { - int err = _WSAGetLastError(); - D(bug("[%d] close error %d\r\n", lst, err)); - } - - l_sockets[lst].s = INVALID_SOCKET; - l_sockets[lst].port = 0; - l_sockets[lst].ip = 0; - - int t = l_sockets[lst].parent; - if( t >= 0 ) { - sockets[t].child = -1; - } - l_sockets[lst].parent = -1; - } - - _WSAResetEvent( l_sockets[lst].ev ); - } - LeaveCriticalSection( &tcp_section ); - } - return 0; -} - -/* - tcp_port= [,] - tcp_port=21,192.168.0.1 -*/ - -static void init_tcp_listen_ports() -{ - int32 index = 0; - const char *port_str; - while ((port_str = PrefsFindString("tcp_port", index++)) != NULL) { - uint32 iface = 0; - const char *if_str = strchr(port_str,','); - if(if_str) { - if_str++; - uint32 if_net = _inet_addr( if_str ); - if(if_net == INADDR_NONE) if_net = INADDR_ANY; - iface = ntohl( if_net ); - } - uint16 port = (uint16)strtoul( port_str, 0, 0 ); - if( port ) { - uint32 ip = 0; - bool once = false; - alloc_listen_socket( port, ip, iface, once ); - } - } -} - -static HANDLE tcp_handle = 0; -static HANDLE tcp_l_handle = 0; - -void init_tcp() -{ - InitializeCriticalSection( &tcp_section ); - - for( int i=0; ihEvent; - - // It's not easy to know whether empty upd datagrams should be passed along. doh. - if(error == 0 && bytes_read > 0) { - - if(bytes_read > 1460) { - D(bug("discarding oversized udp packet, size = \r\n", bytes_read)); - } else { - struct sockaddr_in name; - int namelen = sizeof(name); - memset( &name, 0, sizeof(name) ); - if( _getsockname( cmpl->s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) { - D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() )); - } else { - D(bug("_getsockname(): port=%d\r\n", ntohs(name.sin_port) )); - } - - int udp_size = sizeof(udp_t) + bytes_read; - udp_t *udp = (udp_t *)malloc( udp_size ); - if(udp) { - mac_t *mac = (mac_t *)udp; - ip_t *ip = (ip_t *)udp; - - // Build MAC - // memcpy( udp->ip.mac.dest, cmpl->mac_src, 6 ); - memcpy( mac->dest, ether_addr, 6 ); - memcpy( mac->src, router_mac_addr, 6 ); - mac->type = htons(mac_type_ip4); - - // Build IP - ip->version = 4; - ip->header_len = 5; - ip->tos = 0; - ip->total_len = htons(sizeof(udp_t) - sizeof(mac_t) + bytes_read); // no options - ip->ident = htons(next_ip_ident_number++); // htons() might be a macro... but does not really matter here. - ip->flags_n_frag_offset = 0; - ip->ttl = 128; // one hop actually! - ip->proto = ip_proto_udp; - ip->src = htonl(cmpl->ip_dest); - ip->dest = htonl(cmpl->ip_src); - make_ip4_checksum( (ip_t *)udp ); - - // Copy payload (used by UDP checksum) - memcpy( (char *)udp + sizeof(udp_t), cmpl->buffers[0].buf, bytes_read ); - - // Build UDP - udp->src_port = htons(cmpl->dest_port); - udp->dest_port = htons(cmpl->src_port); - udp->msg_len = htons(sizeof(udp_t) - sizeof(ip_t) + bytes_read); // no options - make_udp_checksum( udp ); - - dump_bytes( (uint8 *)udp, udp_size ); - - enqueue_packet( (uint8 *)udp, udp_size ); - free(udp); - } - } - } - - if(!is_router_shutting_down && cmpl->s != INVALID_SOCKET && cmpl->b_recfrom()) { - cmpl->socket_ttl = GetTickCount() + 60000L; - } else { - delete_socket( cmpl ); - } -} - -void write_udp( udp_t *udp, int len ) -{ - if( len < sizeof(udp_t) ) { - D(bug("Too small udp packet(%d), dropped\r\n", len)); - return; - } - - uint16 src_port = ntohs(udp->src_port); - uint16 dest_port = ntohs(udp->dest_port); - - BOOL ok = true; - - socket_t *cmpl = find_socket( src_port, dest_port, IPPROTO_UDP ); - - BOOL old_socket_found = cmpl != 0; - - if(!cmpl) { - cmpl = new socket_t(IPPROTO_UDP); - if(cmpl) { - cmpl->s = _socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); - if(cmpl->s == INVALID_SOCKET) { - delete cmpl; - cmpl = 0; - ok = false; - } else { - cmpl->src_port = src_port; - cmpl->dest_port = dest_port; - add_socket( cmpl ); - } - } else { - ok = false; - } - } - - if(ok) { - cmpl->src_port = src_port; - cmpl->dest_port = dest_port; - cmpl->ip_src = ntohl(udp->ip.src); - cmpl->ip_dest = ntohl(udp->ip.dest); - - struct sockaddr_in to; - memset( &to, 0, sizeof(to) ); - to.sin_family = AF_INET; - to.sin_port = udp->dest_port; - to.sin_addr.s_addr = udp->ip.dest; - - char *data = (char *)udp + sizeof(udp_t); - int dlen = len - sizeof(udp_t); - - // ttl changed, update checksum - make_udp_checksum( udp ); - - cmpl->set_ttl( udp->ip.ttl ); - - bool please_close = true; - /* - Note that broadcast messages fill fail, no setsockopt(SO_BROADCAST). - That's exactly what I want. - */ - if(SOCKET_ERROR != _sendto( cmpl->s, data, dlen, 0, (struct sockaddr *)&to, sizeof(to) )) { - if(old_socket_found) { - // This socket is not overlapped. - please_close = false; - } else { - if(cmpl->b_recfrom()) please_close = false; - } - cmpl->socket_ttl = GetTickCount() + 60000L; - } else { - int socket_error = _WSAGetLastError(); - D(bug("_sendto() completed with error %d\r\n", socket_error)); - // TODO: check this out: error_winsock_2_icmp() uses router_ip_address - // as source ip; but it's probably allright - error_winsock_2_icmp( socket_error, (ip_t *)udp, len ); - } - if(please_close) { - delete_socket(cmpl); - } - } -} - -void init_udp() -{ -} - -void final_udp() -{ -} diff --git a/BasiliskII/src/Windows/router/udp.h b/BasiliskII/src/Windows/router/udp.h deleted file mode 100755 index b9a5f8a5..00000000 --- a/BasiliskII/src/Windows/router/udp.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * udp.h - ip router - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _UDP_H_ -#define _UDP_H_ - -void write_udp( udp_t *udp, int len ); - -void CALLBACK udp_read_completion( - DWORD error, - DWORD bytes_read, - LPWSAOVERLAPPED lpOverlapped, - DWORD flags -); - -void init_udp(); -void final_udp(); - -#endif // _UDP_H_ diff --git a/BasiliskII/src/Windows/serial_windows.cpp b/BasiliskII/src/Windows/serial_windows.cpp deleted file mode 100755 index 5a062b32..00000000 --- a/BasiliskII/src/Windows/serial_windows.cpp +++ /dev/null @@ -1,1198 +0,0 @@ -/* - * serial_windows.cpp - Serial device driver for Win32 - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// TODO: serial i/o threads should have high priority. -#include "sysdeps.h" - -#include -#include - -#include "main.h" -#include "util_windows.h" -#include "macos_util.h" -#include "prefs.h" -#include "serial.h" -#include "serial_defs.h" -#include "cpu_emulation.h" - -// This must be always on. -#define DEBUG 1 -#undef OutputDebugString -#define OutputDebugString serial_log_write -static void serial_log_write( char *s ); -#define SERIAL_LOG_FILE_NAME TEXT("serial.log") -#include "debug.h" -#undef D -#define D(x) if(debug_serial != DB_SERIAL_NONE) (x); - - -enum { - DB_SERIAL_NONE=0, - DB_SERIAL_NORMAL, - DB_SERIAL_LOUD -}; - -static int16 debug_serial = DB_SERIAL_NONE; - -static HANDLE serial_log_file = INVALID_HANDLE_VALUE; - -static void serial_log_open( LPCTSTR path ) -{ - if(debug_serial == DB_SERIAL_NONE) return; - - DeleteFile( path ); - serial_log_file = CreateFile( - path, - GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_FLAG_WRITE_THROUGH, - NULL - ); - if( serial_log_file == INVALID_HANDLE_VALUE ) { - ErrorAlert( "Could not create the serial log file." ); - } -} - -static void serial_log_close( void ) -{ - if(debug_serial == DB_SERIAL_NONE) return; - - if( serial_log_file != INVALID_HANDLE_VALUE ) { - CloseHandle( serial_log_file ); - serial_log_file = INVALID_HANDLE_VALUE; - } -} - -static void serial_log_write( char *s ) -{ - DWORD bytes_written; - - // should have been checked already. - if(debug_serial == DB_SERIAL_NONE) return; - - if( serial_log_file != INVALID_HANDLE_VALUE ) { - - DWORD count = strlen(s); - if (0 == WriteFile(serial_log_file, s, count, &bytes_written, NULL) || - (int)bytes_written != count) - { - serial_log_close(); - ErrorAlert( "serial log file write error (out of disk space?). Log closed." ); - } else { - FlushFileBuffers( serial_log_file ); - } - } -} - - -// Driver private variables -class XSERDPort : public SERDPort { -public: - XSERDPort(LPCTSTR dev, LPCTSTR suffix) - { - D(bug(TEXT("XSERDPort constructor %s\r\n"), dev)); - - read_pending = write_pending = false; - - if(dev) - _tcscpy( device_name, dev ); - else - *device_name = 0; - _tcsupr(device_name); - is_parallel = (_tcsncmp(device_name, TEXT("LPT"), 3) == 0); - is_file = (_tcsncmp(device_name, TEXT("FILE"), 4) == 0); - if(is_file) { - char entry_name[20]; - _snprintf( entry_name, lengthof(entry_name), "portfile%s", str(suffix).get() ); - const char *path = PrefsFindString(entry_name); - if(path) { - _tcscpy( output_file_name, tstr(path).get() ); - } else { - _tcscpy( output_file_name, TEXT("C:\\B2TEMP.OUT") ); - } - } - - is_serial = !is_parallel && !is_file; - - fd = INVALID_HANDLE_VALUE; - input_thread_active = output_thread_active = NULL; - } - - virtual ~XSERDPort() - { - D(bug("XSERDPort destructor \r\n")); - if (input_thread_active) { - D(bug("WARNING: brute TerminateThread(input)\r\n")); - TerminateThread(input_thread_active,0); - CloseHandle(input_signal); - input_thread_active = NULL; - } - if (output_thread_active) { - D(bug("WARNING: brute TerminateThread(output)\r\n")); - TerminateThread(output_thread_active,0); - CloseHandle(output_signal); - output_thread_active = NULL; - } - } - - virtual int16 open(uint16 config); - virtual int16 prime_in(uint32 pb, uint32 dce); - virtual int16 prime_out(uint32 pb, uint32 dce); - virtual int16 control(uint32 pb, uint32 dce, uint16 code); - virtual int16 status(uint32 pb, uint32 dce, uint16 code); - virtual int16 close(void); - -private: - bool configure(uint16 config); - void set_handshake(uint32 s, bool with_dtr); - static unsigned int WINAPI input_func(void *arg); - static unsigned int WINAPI output_func(void *arg); - static int acknowledge_error(HANDLE h, bool is_read); - bool set_timeouts(int bauds, int parity_bits, int stop_bits); - - TCHAR device_name[256]; - HANDLE fd; - - bool io_killed; // Flag: KillIO called, I/O threads must not call deferred tasks - bool quitting; // Flag: Quit threads - - HANDLE input_thread_active; // Handle: Input thread installed (was a bool) - unsigned int input_thread_id; - HANDLE input_signal; // Signal for input thread: execute command - uint32 input_pb, input_dce; // Command parameters for input thread - - HANDLE output_thread_active; // Handle: Output thread installed (was a bool) - unsigned int output_thread_id; - HANDLE output_signal; // Signal for output thread: execute command - uint32 output_pb, output_dce; // Command parameters for output thread - - DCB mode; // Terminal configuration - - bool is_serial; - bool is_parallel; // true if LPTx - - bool is_file; // true if FILE - TCHAR output_file_name[256]; -}; - -/* - * Initialization - */ - -void SerialInit(void) -{ - const char *port; - - debug_serial = PrefsFindInt32("debugserial"); - - serial_log_open( SERIAL_LOG_FILE_NAME ); - - // Read serial preferences and create structs for both ports - - port = PrefsFindString("seriala"); - if(port) { - D(bug("SerialInit seriala=%s\r\n",port)); - } - the_serd_port[0] = new XSERDPort(tstr(port).get(), TEXT("0")); - - port = PrefsFindString("serialb"); - if(port) { - D(bug("SerialInit serialb=%s\r\n",port)); - } - the_serd_port[1] = new XSERDPort(tstr(port).get(), TEXT("1")); -} - - -/* - * Deinitialization - */ - -void SerialExit(void) -{ - D(bug("SerialExit\r\n")); - if(the_serd_port[0]) delete (XSERDPort *)the_serd_port[0]; - if(the_serd_port[1]) delete (XSERDPort *)the_serd_port[1]; - D(bug("SerialExit done\r\n")); - - serial_log_close(); -} - - -/* - * Open serial port - */ - -int16 XSERDPort::open(uint16 config) -{ - // Don't open NULL name devices - if (!device_name || !*device_name) - return openErr; - - D(bug(TEXT("XSERDPort::open device=%s,config=0x%X\r\n"),device_name,(int)config)); - - // Init variables - io_killed = false; - quitting = false; - - // Open port - if(is_file) { - DeleteFile( output_file_name ); - fd = CreateFile( output_file_name, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ, - NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL - ); - } else { - fd = CreateFile( device_name, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 ); - } - if(fd == INVALID_HANDLE_VALUE) { - goto open_error; - D(bug(TEXT("XSERDPort::open failed to open port %s\r\n"),device_name)); - } - - if(is_serial) { - // Configure port for raw mode - memset( &mode, 0, sizeof(DCB) ); - mode.DCBlength = sizeof(mode); - if(!GetCommState( fd, &mode )) - goto open_error; - - mode.fBinary = TRUE; - if(!configure(config)) { - D(bug("XSERDPort::configure failed\r\n")); - goto open_error; - } - } - - // Start input/output threads - input_signal = CreateSemaphore( 0, 0, 1, NULL); - if(!input_signal) - goto open_error; - - output_signal = CreateSemaphore( 0, 0, 1, NULL); - if(!output_signal) - goto open_error; - - D(bug("Semaphores created\r\n")); - - input_thread_active = (HANDLE)_beginthreadex( 0, 0, input_func, (LPVOID)this, 0, &input_thread_id ); - output_thread_active = (HANDLE)_beginthreadex( 0, 0, output_func, (LPVOID)this, 0, &output_thread_id ); - - if (!input_thread_active || !output_thread_active) - goto open_error; - - D(bug("Threads created, Open returns success\r\n")); - return noErr; - -open_error: - D(bug("Open cleanup after failure\r\n")); - if (input_thread_active) { - TerminateThread(input_thread_active,0); - CloseHandle(input_signal); - input_thread_active = false; - } - if (output_thread_active) { - TerminateThread(output_thread_active,0); - CloseHandle(output_signal); - output_thread_active = false; - } - if(fd != INVALID_HANDLE_VALUE) { - CloseHandle(fd); - fd = 0; - } - return openErr; -} - -/* - * Read data from port - */ - -int16 XSERDPort::prime_in(uint32 pb, uint32 dce) -{ - D(bug("XSERDPort::prime_in\r\n")); - // Send input command to input_thread - read_done = false; - read_pending = true; - input_pb = pb; - input_dce = dce; - ReleaseSemaphore(input_signal,1,NULL); - return 1; // Command in progress -} - - -/* - * Write data to port - */ - -int16 XSERDPort::prime_out(uint32 pb, uint32 dce) -{ - D(bug("XSERDPort::prime_out\r\n")); - // Send output command to output_thread - write_done = false; - write_pending = true; - output_pb = pb; - output_dce = dce; - ReleaseSemaphore(output_signal,1,NULL); - return 1; // Command in progress -} - - -static DWORD get_comm_output_buf_size( HANDLE h ) -{ - DWORD size = 0; - COMMPROP cp; - - if(GetCommProperties(h,&cp)) { - size = cp.dwCurrentTxQueue; - } - return size; -} - -/* - * Control calls - */ - -int16 XSERDPort::control(uint32 pb, uint32 dce, uint16 code) -{ - D(bug("XSERDPort::control code=%d\r\n",(int)code)); - switch (code) { - - case kSERDClockMIDI: - /* http://til.info.apple.com/techinfo.nsf/artnum/n2425 - A MIDI interface operates at 31.25 Kbaud (+/- 1%) [== 31400] - asynchronously, using a data format of one start bit, eight - data bits, and one stop bit. This makes a total of 10 bits - for each 320 microsecond period per serial byte. - */ - D(bug("kSERDClockMIDI setting 38400,n,8,1\n")); - return noErr; - - /* - mode.BaudRate = 38400; - mode.ByteSize = 8; - mode.StopBits = ONESTOPBIT; - mode.Parity = NOPARITY; - if(!SetCommState( fd, &mode )) { - D(bug("kSERDClockMIDI SetCommState() failed\n")); - return controlErr; - } else { - if(!set_timeouts(38400,0,2)) { - D(bug("kSERDClockMIDI set_timeouts() failed\n")); - return controlErr; - } - D(bug("kSERDClockMIDI OK\n")); - return noErr; - } - */ - - case 1: // KillIO - io_killed = true; - - if(is_serial) { - // Make sure we won't hang waiting. There is something wrong - // in how read_pending & write_pending are handled. - DWORD endtime = GetTickCount() + 1000; - while ( (read_pending || write_pending) && (GetTickCount() < endtime) ) { - Sleep(20); - } - if(read_pending || write_pending) { - D(bug("Warning (KillIO): read_pending=%d, write_pending=%d\n", read_pending, write_pending)); - read_pending = write_pending = false; - } - // | PURGE_TXABORT | PURGE_RXABORT not needed, no overlapped i/o - PurgeComm(fd,PURGE_TXCLEAR|PURGE_RXCLEAR); - FlushFileBuffers(fd); - } - io_killed = false; - D(bug("KillIO done\n")); - return noErr; - - case kSERDConfiguration: - if (configure((uint16)ReadMacInt16(pb + csParam))) - return noErr; - else - return paramErr; - - case kSERDInputBuffer: - if(is_serial) { - - // SetupComm() wants both values, so we need to know the output size. - DWORD osize = get_comm_output_buf_size(fd); - - DWORD isize = ReadMacInt16(pb + csParam + 4) & 0xffffffc0; - - // 1k minimum - // Was this something Amiga specific -- do I need to do this? - if (isize < 1024) - isize = 1024; - - if(isize > 0 && osize > 0) { - if(SetupComm( fd, isize, osize )) { - D(bug(" buffer size is now %08lx\n", isize)); - return noErr; - } else { - D(bug(" SetupComm(%d,%d) failed, error = %08lx\n", isize, osize, GetLastError())); - } - } - } - // Always return ok. - return noErr; - - case kSERDSerHShake: - set_handshake(pb + csParam, false); - return noErr; - - case kSERDSetBreak: - if(is_serial) { - if(!SetCommBreak(fd)) return controlErr; - } - return noErr; - - case kSERDClearBreak: - if(is_serial) { - if(!ClearCommBreak(fd)) return controlErr; - } - return noErr; - - case kSERDBaudRate: { - if (is_serial) { - uint16 rate = (uint16)ReadMacInt16(pb + csParam); - int baud_rate; - if (rate <= 50) { - rate = 50; baud_rate = CBR_110; - } else if (rate <= 75) { - rate = 75; baud_rate = CBR_110; - } else if (rate <= 110) { - rate = 110; baud_rate = CBR_110; - } else if (rate <= 134) { - rate = 134; baud_rate = CBR_110; - } else if (rate <= 150) { - rate = 150; baud_rate = CBR_110; - } else if (rate <= 200) { - rate = 200; baud_rate = CBR_300; - } else if (rate <= 300) { - rate = 300; baud_rate = CBR_300; - } else if (rate <= 600) { - rate = 600; baud_rate = CBR_600; - } else if (rate <= 1200) { - rate = 1200; baud_rate = CBR_1200; - } else if (rate <= 1800) { - rate = 1800; baud_rate = CBR_2400; - } else if (rate <= 2400) { - rate = 2400; baud_rate = CBR_2400; - } else if (rate <= 4800) { - rate = 4800; baud_rate = CBR_4800; - } else if (rate <= 9600) { - rate = 9600; baud_rate = CBR_9600; - } else if (rate <= 19200) { - rate = 19200; baud_rate = CBR_19200; - } else if (rate <= 38400) { - rate = 38400; baud_rate = CBR_38400; - } else if (rate <= 57600) { - rate = 57600; baud_rate = CBR_57600; - } else { - rate = 57600; baud_rate = CBR_57600; - } - WriteMacInt16(pb + csParam, rate); - mode.BaudRate = baud_rate; - if(!SetCommState( fd, &mode )) return controlErr; - // TODO: save parity/stop values and use here (not critical) - if(!set_timeouts(rate,0,1)) return controlErr; - } - return noErr; - } - - case kSERDHandshake: - case kSERDHandshakeRS232: - set_handshake(pb + csParam, true); - return noErr; - - case kSERDMiscOptions: - if (ReadMacInt8(pb + csParam) & kOptionPreserveDTR) - mode.fDtrControl = DTR_CONTROL_ENABLE; // correct? - else - mode.fDtrControl = DTR_CONTROL_DISABLE; // correct? - if(is_serial) { - if(!SetCommState( fd, &mode )) return controlErr; - } - return noErr; - - case kSERDAssertDTR: { - if (is_serial) { - if(!EscapeCommFunction(fd,SETDTR)) return controlErr; - } - return noErr; - } - - case kSERDNegateDTR: { - if (is_serial) { - if(!EscapeCommFunction(fd,CLRDTR)) return controlErr; - } - return noErr; - } - - case kSERDSetPEChar: - case kSERDSetPEAltChar: - { - uint16 errChar = (uint16)ReadMacInt16(pb + csParam); - mode.fErrorChar = TRUE; - mode.ErrorChar = (char)errChar; - return noErr; - } - - case kSERDResetChannel: - if (is_serial) { - // | PURGE_TXABORT | PURGE_RXABORT not needed, no overlapped i/o - PurgeComm(fd,PURGE_TXCLEAR|PURGE_RXCLEAR); - FlushFileBuffers(fd); - } - return noErr; - - case kSERDAssertRTS: { - if (is_serial) { - if(!EscapeCommFunction(fd,SETRTS)) return controlErr; - } - return noErr; - } - - case kSERDNegateRTS: { - if (is_serial) { - if(!EscapeCommFunction(fd,CLRRTS)) return controlErr; - } - return noErr; - } - - case kSERD115KBaud: - if (is_serial) { - mode.BaudRate = CBR_115200; - if(!SetCommState( fd, &mode )) return controlErr; - } - return noErr; - - case kSERD230KBaud: - case kSERDSetHighSpeed: - if (is_serial) { - mode.BaudRate = CBR_256000; - if(!SetCommState( fd, &mode )) return controlErr; - } - return noErr; - - default: - D(bug("WARNING: SerialControl(): unimplemented control code %d\r\n", code)); - return controlErr; - } -} - -/* - * Status calls - */ - -int16 XSERDPort::status(uint32 pb, uint32 dce, uint16 code) -{ - // D(bug("XSERDPort::status code=%d\r\n",(int)code)); - - DWORD error_state; - COMSTAT comstat; - - switch (code) { - case kSERDInputCount: { - uint32 num = 0; - if (is_serial) { - if(!ClearCommError(fd,&error_state,&comstat)) return statusErr; - num = comstat.cbInQue; - } - WriteMacInt32(pb + csParam, num); - return noErr; - } - - case kSERDStatus: { - uint32 p = pb + csParam; - WriteMacInt8(p + staCumErrs, cum_errors); - cum_errors = 0; - DWORD status; - - if(is_serial) { - if(!GetCommModemStatus(fd,&status)) return statusErr; - } else { - status = MS_CTS_ON | MS_DSR_ON | MS_RLSD_ON; - D(bug("kSERDStatus: faking status for LPT port or FILE\r\n")); - } - - WriteMacInt8(p + staXOffSent, 0); - WriteMacInt8(p + staXOffHold, 0); - WriteMacInt8(p + staRdPend, read_pending); - WriteMacInt8(p + staWrPend, write_pending); - - WriteMacInt8(p + staCtsHold, status & MS_CTS_ON ? 0 : 1); - WriteMacInt8(p + staDsrHold, status & MS_DSR_ON ? 0 : 1); - - WriteMacInt8(p + staModemStatus, - (status & MS_DSR_ON ? dsrEvent : 0) - | (status & MS_RING_ON ? riEvent : 0) - | (status & MS_RLSD_ON ? dcdEvent : 0) // is this carrier detect? - | (status & MS_CTS_ON ? ctsEvent : 0)); - return noErr; - } - - default: - D(bug("WARNING: SerialStatus(): unimplemented status code %d\r\n", code)); - return statusErr; - } -} - - -/* - * Close serial port - */ - -int16 XSERDPort::close() -{ - D(bug("XSERDPort::close\r\n")); - - // Kill threads - if (input_thread_active) { - quitting = true; - ReleaseSemaphore(input_signal,1,NULL); - input_thread_active = false; - CloseHandle(input_signal); - } - if (output_thread_active) { - quitting = true; - ReleaseSemaphore(output_signal,1,NULL); - output_thread_active = false; - // bugfix: was: CloseHandle(&output_signal); - CloseHandle(output_signal); - } - - // Close port - if(fd != INVALID_HANDLE_VALUE) { - CloseHandle(fd); - fd = 0; - } - return noErr; -} - -bool XSERDPort::set_timeouts( - int bauds, int parity_bits, int stop_bits ) -{ - COMMTIMEOUTS timeouts; - uint32 bytes_per_sec; - uint32 msecs_per_ch; - bool result = false; - - // Should already been checked - if (!is_serial) - return true; - - bytes_per_sec = bauds / (mode.ByteSize + parity_bits + stop_bits); - - // 75% bytes_per_sec - // bytes_per_sec = (bytes_per_sec+bytes_per_sec+bytes_per_sec) >> 2; - - // 50% bytes_per_sec - bytes_per_sec = bytes_per_sec >> 1; - - msecs_per_ch = 1000 / bytes_per_sec; - if(msecs_per_ch == 0) msecs_per_ch = 1; - - if(GetCommTimeouts(fd,&timeouts)) { - D(bug("old timeout values: %ld %ld %ld %ld %ld\r\n", - timeouts.ReadIntervalTimeout, - timeouts.ReadTotalTimeoutMultiplier, - timeouts.ReadTotalTimeoutConstant, - timeouts.WriteTotalTimeoutMultiplier, - timeouts.WriteTotalTimeoutConstant - )); - - timeouts.WriteTotalTimeoutMultiplier = msecs_per_ch; - timeouts.WriteTotalTimeoutConstant = 10; - - /* - timeouts.ReadIntervalTimeout = msecs_per_ch; - timeouts.ReadTotalTimeoutMultiplier = msecs_per_ch; - timeouts.ReadTotalTimeoutConstant = 10; - */ - - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = 0; - timeouts.ReadTotalTimeoutConstant = 0; - - if(!SetCommTimeouts(fd,&timeouts)) { - D(bug("SetCommTimeouts() failed in configure()\r\n")); - } else { - D(bug("new timeout values: %ld %ld %ld %ld %ld\r\n", - timeouts.ReadIntervalTimeout, - timeouts.ReadTotalTimeoutMultiplier, - timeouts.ReadTotalTimeoutConstant, - timeouts.WriteTotalTimeoutMultiplier, - timeouts.WriteTotalTimeoutConstant - )); - result = true; - } - } else { - D(bug("GetCommTimeouts() failed in set_timeouts()\r\n")); - } - return(result); -} - -/* - * Configure serial port with MacOS config word - */ - -bool XSERDPort::configure(uint16 config) -{ - D(bug("XSERDPort::configure, config=%d\r\n",(int)config)); - - if (!is_serial) - return true; - - // needed to calculate optimal timeouts - uint32 bauds = 57600; - uint32 stop_bits = 1; - uint32 parity_bits = 0; - - // Not all of these can be set here anyway. - /* - mode.fOutxCtsFlow = TRUE; - mode.fOutxDsrFlow = FALSE; - mode.fDtrControl = DTR_CONTROL_ENABLE; // DTR_CONTROL_HANDSHAKE? - mode.fDsrSensitivity = FALSE; // ??? - mode.fOutX = FALSE; - mode.fInX = FALSE; - mode.fTXContinueOnXoff = FALSE; - mode.fErrorChar = FALSE; - mode.ErrorChar = 0; - mode.fNull = FALSE; - mode.fRtsControl = 2; // ??? - mode.fAbortOnError = FALSE; - mode.XonLim = 0x800; - mode.XoffLim = 0x200; - mode.XonChar = 0x11; - mode.XoffChar = 0x13; - mode.EofChar = 0; - mode.EvtChar = '\0'; - */ - - // Set baud rate - switch (config & 0x03ff) { - // no baud1800, CBR_14400, CBR_56000, CBR_115200, CBR_128000, CBR_256000 - case baud150: mode.BaudRate = CBR_110; bauds = 110; break; - case baud300: mode.BaudRate = CBR_300; bauds = 300; break; - case baud600: mode.BaudRate = CBR_600; bauds = 600; break; - case baud1200: mode.BaudRate = CBR_1200; bauds = 1200; break; - case baud1800: return false; - case baud2400: mode.BaudRate = CBR_2400; bauds = 2400; break; - case baud4800: mode.BaudRate = CBR_4800; bauds = 4800; break; - case baud9600: mode.BaudRate = CBR_9600; bauds = 9600; break; - case baud19200: mode.BaudRate = CBR_19200; bauds = 19200; break; - case baud38400: mode.BaudRate = CBR_38400; bauds = 38400; break; - case baud57600: mode.BaudRate = CBR_57600; bauds = 57600; break; - default: - return false; - } - - // Set number of stop bits - switch (config & 0xc000) { - case stop10: - mode.StopBits = ONESTOPBIT; - stop_bits = 1; - break; - case stop15: - mode.StopBits = ONE5STOPBITS; - stop_bits = 2; - break; - case stop20: - mode.StopBits = TWOSTOPBITS; - stop_bits = 2; - break; - default: - return false; - } - - // Set parity mode - switch (config & 0x3000) { - case noParity: - mode.Parity = NOPARITY; - mode.fParity = FALSE; - parity_bits = 0; - break; - case oddParity: - mode.Parity = ODDPARITY; - mode.fParity = TRUE; - parity_bits = 1; - break; - case evenParity: - mode.Parity = EVENPARITY; - mode.fParity = TRUE; - parity_bits = 1; - break; - // No MARKPARITY, SPACEPARITY - default: - return false; - } - - // Set number of data bits - switch (config & 0x0c00) { - // No data4 - case data5: - mode.ByteSize = 5; break; - case data6: - mode.ByteSize = 6; break; - case data7: - mode.ByteSize = 7; break; - case data8: - mode.ByteSize = 8; break; - default: - return false; - } - - D(bug("Interpreted configuration: %d,%d,%d,%d\r\n", - bauds, - mode.ByteSize, - stop_bits, - parity_bits - )); - - if(!SetCommState( fd, &mode )) { - D(bug("SetCommState failed in configure()\r\n")); - return false; - } - - if(!set_timeouts(bauds,parity_bits,stop_bits)) - return false; - - return true; -} - - -/* - * Set serial handshaking - */ - -void XSERDPort::set_handshake(uint32 s, bool with_dtr) -{ - D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\r\n", - ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3), - ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7))); - - if (!is_serial) - return; - - if (with_dtr) { - mode.fDtrControl = DTR_CONTROL_ENABLE; - if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR)) - mode.fOutxCtsFlow = TRUE; - else - mode.fOutxCtsFlow = FALSE; - } else { - mode.fDtrControl = DTR_CONTROL_DISABLE; - if (ReadMacInt8(s + shkFCTS)) - mode.fOutxCtsFlow = TRUE; - else - mode.fOutxCtsFlow = FALSE; - } - - // MIDI: set_handshake 00 00 f4 f5 21 00 00 00 - // shkFXOn = 0 - // shkFCTS = 0 - // shkXOn = f4 - // shkXOff = f5 - // shkErrs = 21 - // shkEvts = 0 - // shkFInX = 0 - // shkFDTR = 0 - if (ReadMacInt8(s + shkXOn) && ReadMacInt8(s + shkXOn)) { - mode.fOutX = 1; - mode.fInX = 1; - mode.XonChar = ReadMacInt8(s + shkXOn); - mode.XoffChar = ReadMacInt8(s + shkXOff); - } else { - mode.fOutX = 0; - mode.fInX = 0; - } - if (ReadMacInt8(s + shkErrs)) { - mode.ErrorChar = ReadMacInt8(s + shkErrs); - mode.fErrorChar = 1; - } else { - mode.fErrorChar = 0; - } - - (void)SetCommState( fd, &mode ); - - // D(bug(" %sware flow control\r\n", mode.c_cflag & CRTSCTS ? "hard" : "soft")); - // tcsetattr(fd, TCSANOW, &mode); -} - -/* - if mode.fAbortOnError is TRUE, ClearCommError() *MUST* be called - after any read or write errors. Otherwise no i/o will occur again - - These error codes should be translated but the Mac Device Manager - error code mnemonics are too cryptic to me. -*/ - -int XSERDPort::acknowledge_error(HANDLE h, bool is_read) -{ - DWORD error_state; - COMSTAT comstat; - int err; - - // default error code if cannot map correctly - err = is_read ? readErr : writErr; - - if(ClearCommError(h,&error_state,&comstat)) { - D(bug("A %s error 0x%X occured.\r\n", is_read ? "read" : "write", error_state)); - D(bug("There was %d bytes in input buffer and %d bytes in output buffer.\r\n",(int)comstat.cbInQue,(int)comstat.cbOutQue)); - if(error_state & CE_MODE) { - D(bug("The requested mode is not supported.\r\n")); - } else { - if(error_state & CE_BREAK) { - D(bug("The hardware detected a break condition.\r\n")); - } - if(error_state & CE_FRAME) { - D(bug("The hardware detected a framing error.\r\n")); - } - if(error_state & CE_IOE) { - D(bug("An I/O error occurred during communications with the device.\r\n")); - } - if(error_state & CE_RXOVER) { - D(bug("An input buffer overflow has occurred.\r\n")); - } - if(error_state & CE_RXPARITY) { - D(bug("The hardware detected a parity error.\r\n")); - err = badDCksum; - } - if(error_state & CE_TXFULL) { - D(bug("The application tried to transmit a character, but the output buffer was full.\r\n")); - } - - // Win95 specific errors - if(error_state & CE_OVERRUN) { - D(bug("A character-buffer overrun has occurred. The next character is lost.\r\n")); - if(!is_read) err = wrUnderrun; - } - - // Win95 parallel devices really. - if(error_state & CE_DNS) { - D(bug("A parallel device is not selected (Windows 95).\r\n")); - } - if(error_state & CE_OOP) { - D(bug("A parallel device signaled that it is out of paper (Windows 95 only).\r\n")); - err = unitEmptyErr; - } - if(error_state & CE_PTO) { - D(bug("A time-out occurred on a parallel device (Windows 95).\r\n")); - } - - } - } else { - D(bug("Failed to resume after %s operation.\r\n",is_read ? "read" : "write")); - } - return(err); -} - -#if DEBUG -static void dump_dirst_bytes( BYTE *buf, int32 actual ) -{ - if(debug_serial != DB_SERIAL_LOUD) return; - - BYTE b[256]; - int32 i, bytes = min(actual,sizeof(b)-3); - - for (i=0; idevice_name)); - - for (;;) { - - // Wait for commands - WaitForSingleObject(s->input_signal,INFINITE); - if (s->quitting) - break; - - // Execute command - void *buf = Mac2HostAddr(ReadMacInt32(s->input_pb + ioBuffer)); - uint32 length = ReadMacInt32(s->input_pb + ioReqCount); - D(bug("input_func waiting for %ld bytes of data...\r\n", length)); - - if(length & 0xFFFF0000) { - length &= 0x0000FFFF; - D(bug("byte count fixed to be %ld...\r\n", length)); - } - - int32 actual; - if(s->is_file) { - actual = -1; - error_code = readErr; - } else if(!ReadFile(s->fd, buf, length, (LPDWORD)&actual, 0)) { - actual = -1; - if(s->is_serial) - error_code = acknowledge_error(s->fd,true); - else - error_code = readErr; - } - D(bug(" %ld bytes received\r\n", actual)); - if(actual > 0) { - dump_dirst_bytes( (BYTE*)buf, actual ); - } - - // KillIO called? Then simply return - if (s->io_killed) { - - WriteMacInt16(s->input_pb + ioResult, abortErr); - WriteMacInt32(s->input_pb + ioActCount, 0); - s->read_pending = s->read_done = false; - - } else { - - // Set error code - if (actual >= 0) { - WriteMacInt32(s->input_pb + ioActCount, actual); - WriteMacInt32(s->input_dt + serdtResult, noErr); - } else { - WriteMacInt32(s->input_pb + ioActCount, 0); - WriteMacInt32(s->input_dt + serdtResult, error_code); - } - - // Trigger serial interrupt - D(bug(" triggering serial interrupt\r\n")); - WriteMacInt32(s->input_dt + serdtDCE, s->input_dce); - s->read_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - - D(bug("XSERDPort::input_func terminating gracefully\r\n")); - - _endthreadex( 0 ); - - return(0); -} - - -/* - * Data output thread - */ - -unsigned int XSERDPort::output_func(void *arg) -{ - XSERDPort *s = (XSERDPort *)arg; - int error_code; - -#if 0 - SetThreadPriority( GetCurrentThread(), threads[THREAD_SERIAL_OUT].priority_running ); - SetThreadAffinityMask( GetCurrentThread(), threads[THREAD_SERIAL_OUT].affinity_mask ); - set_desktop(); -#endif - - D(bug(TEXT("XSERDPort::output_func started for device %s\r\n"),s->device_name)); - - for (;;) { - - // Wait for commands - WaitForSingleObject(s->output_signal,INFINITE); - if (s->quitting) - break; - - // Execute command - void *buf = Mac2HostAddr(ReadMacInt32(s->output_pb + ioBuffer)); - uint32 length = ReadMacInt32(s->output_pb + ioReqCount); - D(bug("output_func transmitting %ld bytes of data...\r\n", length)); - - if(length & 0xFFFF0000) { - length &= 0x0000FFFF; - D(bug("byte count fixed to be %ld...\r\n", length)); - } - - int32 actual; - if(!WriteFile(s->fd, buf, length, (LPDWORD)&actual, 0)) { - actual = -1; - if(s->is_serial) - error_code = acknowledge_error(s->fd,false); - else - error_code = writErr; - } - D(bug(" %ld bytes transmitted\r\n", actual)); - if(actual > 0) { - dump_dirst_bytes( (BYTE*)buf, actual ); - } - - // KillIO called? Then simply return - if (s->io_killed) { - - WriteMacInt16(s->output_pb + ioResult, abortErr); - WriteMacInt32(s->output_pb + ioActCount, 0); - s->write_pending = s->write_done = false; - - } else { - - // Set error code - if (actual >= 0) { - WriteMacInt32(s->output_pb + ioActCount, actual); - WriteMacInt32(s->output_dt + serdtResult, noErr); - } else { - WriteMacInt32(s->output_pb + ioActCount, 0); - WriteMacInt32(s->output_dt + serdtResult, error_code); - } - - // Trigger serial interrupt - D(bug(" triggering serial interrupt\r\n")); - WriteMacInt32(s->output_dt + serdtDCE, s->output_dce); - s->write_done = true; - SetInterruptFlag(INTFLAG_SERIAL); - TriggerInterrupt(); - } - } - - D(bug("XSERDPort::output_func terminating gracefully\r\n")); - - _endthreadex( 0 ); - - return(0); -} diff --git a/BasiliskII/src/Windows/sys_windows.cpp b/BasiliskII/src/Windows/sys_windows.cpp deleted file mode 100755 index 21e2df0e..00000000 --- a/BasiliskII/src/Windows/sys_windows.cpp +++ /dev/null @@ -1,994 +0,0 @@ -/* - * sys_windows.cpp - System dependent routines, Windows implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include - -#include -typedef std::basic_string tstring; - -#include -using std::min; - -#include "main.h" -#include "util_windows.h" -#include "macos_util.h" -#include "prefs.h" -#include "user_strings.h" -#include "sys.h" - -#include "cd_defs.h" -#include "cdenable/ntcd.h" -#include "cdenable/cache.h" -#include "cdenable/eject_nt.h" - -#define DEBUG 0 -#include "debug.h" - - -// File handles are pointers to these structures -struct file_handle { - TCHAR *name; // Copy of device/file name - HANDLE fh; - bool is_file; // Flag: plain file or physical device? - bool is_floppy; // Flag: floppy device - bool is_cdrom; // Flag: CD-ROM device - bool read_only; // Copy of Sys_open() flag - loff_t start_byte; // Size of file header (if any) - loff_t file_size; // Size of file data (only valid if is_file is true) - cachetype cache; - bool is_media_present; -}; - -// Open file handles -struct open_file_handle { - file_handle *fh; - open_file_handle *next; -}; -static open_file_handle *open_file_handles = NULL; - -// File handle of first floppy drive (for SysMountFirstFloppy()) -static file_handle *first_floppy = NULL; - -// CD-ROM variables -static const int CD_READ_AHEAD_SECTORS = 16; -static char *sector_buffer = NULL; - -// Prototypes -static bool is_cdrom_readable(file_handle *fh); - - -/* - * Initialization - */ - -void SysInit(void) -{ - // Initialize CD-ROM driver - sector_buffer = (char *)VirtualAlloc(NULL, 8192, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - CdenableSysInstallStart(); -} - - -/* - * Deinitialization - */ - -void SysExit(void) -{ - if (sector_buffer) { - VirtualFree(sector_buffer, 0, MEM_RELEASE ); - sector_buffer = NULL; - } -} - - -/* - * Manage open file handles - */ - -static void sys_add_file_handle(file_handle *fh) -{ - open_file_handle *p = new open_file_handle; - p->fh = fh; - p->next = open_file_handles; - open_file_handles = p; -} - -static void sys_remove_file_handle(file_handle *fh) -{ - open_file_handle *p = open_file_handles; - open_file_handle *q = NULL; - - while (p) { - if (p->fh == fh) { - if (q) - q->next = p->next; - else - open_file_handles = p->next; - delete p; - break; - } - q = p; - p = p->next; - } -} - - -/* - * Mount removable media now - */ - -void mount_removable_media(int media) -{ - for (open_file_handle *p = open_file_handles; p != NULL; p = p->next) { - file_handle * const fh = p->fh; - - if (fh->is_cdrom && (media & MEDIA_CD)) { - cache_clear(&fh->cache); - fh->start_byte = 0; - - if (fh->fh && fh->fh != INVALID_HANDLE_VALUE) - CloseHandle(fh->fh); - - // Re-open device - TCHAR device_name[MAX_PATH]; - _sntprintf(device_name, lengthof(device_name), TEXT("\\\\.\\%c:"), fh->name[0]); - fh->fh = CreateFile( - device_name, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (fh->fh != INVALID_HANDLE_VALUE) { - fh->is_media_present = is_cdrom_readable(fh); - if (fh->is_media_present) - MountVolume(fh); - } else { - fh->is_media_present = false; - } - } - } -} - - -/* - * Account for media that has just arrived - */ - -void SysMediaArrived(void) -{ - mount_removable_media(MEDIA_REMOVABLE); -} - - -/* - * Account for media that has just been removed - */ - -void SysMediaRemoved(void) -{ -} - - -/* - * Mount first floppy disk - */ - -void SysMountFirstFloppy(void) -{ - if (first_floppy) - MountVolume(first_floppy); -} - - -/* - * This gets called when no "floppy" prefs items are found - * It scans for available floppy drives and adds appropriate prefs items - */ - -void SysAddFloppyPrefs(void) -{ -} - - -/* - * This gets called when no "disk" prefs items are found - * It scans for available HFS volumes and adds appropriate prefs items - */ - -void SysAddDiskPrefs(void) -{ -} - - -/* - * This gets called when no "cdrom" prefs items are found - * It scans for available CD-ROM drives and adds appropriate prefs items - */ - -void SysAddCDROMPrefs(void) -{ - // Don't scan for drives if nocdrom option given - if (PrefsFindBool("nocdrom")) - return; - - char rootdir[] = "C:\\"; - for (; rootdir[0] <= 'Z'; rootdir[0]++) { - if (GetDriveTypeA(rootdir) == DRIVE_CDROM) - PrefsAddString("cdrom", rootdir); - } -} - - -/* - * Add default serial prefs (must be added, even if no ports present) - */ - -void SysAddSerialPrefs(void) -{ - PrefsAddString("seriala", "COM1"); - PrefsAddString("serialb", "COM2"); -} - - -/* - * Read CD-ROM - * Must give cd some time to settle - * Can't give too much however, would be annoying, this is difficult.. - */ - -static inline int cd_read_with_retry(file_handle *fh, ULONG LBA, int count, char *buf ) -{ - if (!fh || !fh->fh) - return 0; - - return CdenableSysReadCdBytes(fh->fh, LBA, count, buf); -} - -static int cd_read(file_handle *fh, cachetype *cptr, ULONG LBA, int count, char *buf) -{ - ULONG l1, l2, cc; - int i, c_count, got_bytes = 0, nblocks, s_inx, ss, first_block; - int ok_bytes = 0; - char *ptr, *ttptr = 0, *tmpbuf; - - if (count <= 0) - return 0; - - if (!fh || !fh->fh) - return 0; - - ss = 2048; - l1 = (LBA / ss) * ss; - l2 = ((LBA + count - 1 + ss) / ss) * ss; - cc = l2 - l1; - nblocks = cc / ss; - first_block = LBA / ss; - - ptr = buf; - s_inx = LBA - l1; - c_count = ss - s_inx; - if (c_count > count) - c_count = count; - - for (i = 0; i < nblocks; i++) { - if (!cache_get(cptr, first_block + i, sector_buffer)) - break; - - memcpy(ptr, sector_buffer + s_inx, c_count); - ok_bytes += c_count; - ptr += c_count; - s_inx = 0; - c_count = ss; - if (c_count > count - ok_bytes) - c_count = count - ok_bytes; - } - - if (i != nblocks && count != ok_bytes) { - int bytes_left = count - ok_bytes; - int blocks_left = nblocks - i; - int alignedleft; - - // NEW read ahead code: - int ahead = CD_READ_AHEAD_SECTORS; - if (blocks_left < ahead) { - nblocks += (ahead - blocks_left); - blocks_left = ahead; - } - - alignedleft = blocks_left*ss; - - tmpbuf = (char *)VirtualAlloc( - NULL, alignedleft, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (tmpbuf) { - got_bytes = cd_read_with_retry(fh, (first_block + i) * ss, alignedleft, tmpbuf); - if (got_bytes != alignedleft) { - // should never happen - // Yes it does ... - if (got_bytes < 0) - got_bytes = 0; - if (c_count > got_bytes) - c_count = got_bytes; - if (c_count > 0) { - ttptr = tmpbuf; - memcpy(ptr, ttptr + s_inx, c_count); - ok_bytes += c_count; - } - VirtualFree(tmpbuf, 0, MEM_RELEASE ); - return ok_bytes; - } - ttptr = tmpbuf; - for ( ; i < nblocks; i++) { - if (c_count > 0) { - memcpy(ptr, ttptr + s_inx, c_count); - ok_bytes += c_count; - ptr += c_count; - } - s_inx = 0; - c_count = ss; - if (c_count > count - ok_bytes) - c_count = count - ok_bytes; - cache_put(cptr, first_block + i, ttptr, ss); - ttptr += ss; - } - VirtualFree(tmpbuf, 0, MEM_RELEASE ); - } - } - - return ok_bytes; -} - - -/* - * Check if file handle FH represents a readable CD-ROM - */ - -static bool is_cdrom_readable(file_handle *fh) -{ - if (!fh || !fh->fh) - return false; - - cache_clear(&fh->cache); - - DWORD dummy; - bool result = (0 != DeviceIoControl( - fh->fh, - IOCTL_STORAGE_CHECK_VERIFY, - NULL, 0, - NULL, 0, - &dummy, - NULL)); - if (!result) { - const size_t n_bytes = 2048; - char *buffer = (char *)VirtualAlloc(NULL, n_bytes, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (buffer) { - result = (cd_read_with_retry(fh, 0, n_bytes, buffer) == n_bytes); - VirtualFree(buffer, 0, MEM_RELEASE); - } - } - - return result; -} - - -/* - * Check if NAME represents a read-only file - */ - -static bool is_read_only_path(const TCHAR *name) -{ - DWORD attrib = GetFileAttributes(name); - return (attrib != INVALID_FILE_ATTRIBUTES && ((attrib & FILE_ATTRIBUTE_READONLY) != 0)); -} - - -/* - * Open file/device, create new file handle (returns NULL on error) - */ - -void *Sys_open(const char *path_name, bool read_only) -{ - file_handle * fh = NULL; - - // Parse path name and options - TCHAR name[MAX_PATH]; - tcslcpy(name, path_name, lengthof(name)); - - // Normalize floppy / cd path - int name_len = _tcslen(name); - if (name_len == 1 && _istalpha(name[0])) - _tcscat(name, TEXT(":\\")); - if (name_len > 0 && name[name_len - 1] == TEXT(':')) - _tcscat(name, TEXT("\\")); - name_len = _tcslen(name); - - D(bug(TEXT("Sys_open(%s, %s)\n"), name, read_only ? TEXT("read-only") : TEXT("read/write"))); - if (name_len > 0 && name[name_len - 1] == TEXT('\\')) { - int type = GetDriveType(name); - - if (type == DRIVE_CDROM) { - read_only = true; - TCHAR device_name[MAX_PATH]; - _sntprintf(device_name, lengthof(device_name), TEXT("\\\\.\\%c:"), name[0]); - - // Open device - HANDLE h = CreateFile( - device_name, - GENERIC_READ, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (h != INVALID_HANDLE_VALUE) { - fh = new file_handle; - fh->name = _tcsdup(name); - fh->fh = h; - fh->is_file = false; - fh->read_only = read_only; - fh->start_byte = 0; - fh->is_floppy = false; - fh->is_cdrom = true; - memset(&fh->cache, 0, sizeof(cachetype)); - cache_init(&fh->cache); - cache_clear(&fh->cache); - if (!PrefsFindBool("nocdrom")) - fh->is_media_present = is_cdrom_readable(fh); - } - } - } - - else { // Hard file - - // Check if write access is allowed, set read-only flag if not - if (!read_only && is_read_only_path(name)) - read_only = true; - - // Open file - HANDLE h = CreateFile( - name, - read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (h == INVALID_HANDLE_VALUE && !read_only) { - // Read-write failed, try read-only - read_only = true; - h = CreateFile( - name, - GENERIC_READ, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } - - if (h != INVALID_HANDLE_VALUE) { - fh = new file_handle; - fh->name = _tcsdup(name); - fh->fh = h; - fh->is_file = true; - fh->read_only = read_only; - fh->start_byte = 0; - fh->is_floppy = false; - fh->is_cdrom = false; - - // Detect disk image file layout - loff_t size = GetFileSize(h, NULL); - DWORD bytes_read; - uint8 data[256]; - ReadFile(h, data, sizeof(data), &bytes_read, NULL); - FileDiskLayout(size, data, fh->start_byte, fh->file_size); - } - } - - if (fh) { - if (fh->is_floppy && first_floppy == NULL) - first_floppy = fh; - sys_add_file_handle(fh); - } - - return fh; -} - - -/* - * Close file/device, delete file handle - */ - -void Sys_close(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - sys_remove_file_handle(fh); - - if (fh->is_cdrom) { - cache_final(&fh->cache); - SysAllowRemoval((void *)fh); - } - if (fh->fh != NULL) { - CloseHandle(fh->fh); - fh->fh = NULL; - } - if (fh->name) - free(fh->name); - - delete fh; -} - - -/* - * Read "length" bytes from file/device, starting at "offset", to "buffer", - * returns number of bytes read (or 0) - */ - -size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return 0; - - DWORD bytes_read = 0; - - if (fh->is_file) { - // Seek to position - LONG lo = (LONG)offset; - LONG hi = (LONG)(offset >> 32); - DWORD r = SetFilePointer(fh->fh, lo, &hi, FILE_BEGIN); - if (r == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) - return 0; - - // Read data - if (ReadFile(fh->fh, buffer, length, &bytes_read, NULL) == 0) - bytes_read = 0; - } - else if (fh->is_cdrom) { - int bytes_left, try_bytes, got_bytes; - char *b = (char *)buffer; - bytes_left = length; - while (bytes_left) { - try_bytes = min(bytes_left, 32768); - if (fh->is_cdrom) { - got_bytes = cd_read(fh, &fh->cache, (DWORD)offset, try_bytes, b); - if (got_bytes != try_bytes && !PrefsFindBool("nocdrom")) - fh->is_media_present = is_cdrom_readable(fh); - } - b += got_bytes; - offset += got_bytes; - bytes_read += got_bytes; - bytes_left -= got_bytes; - if (got_bytes != try_bytes) - bytes_left = 0; - } - } - // TODO: other media - - return bytes_read; -} - - -/* - * Write "length" bytes from "buffer" to file/device, starting at "offset", - * returns number of bytes written (or 0) - */ - -size_t Sys_write(void *arg, void *buffer, loff_t offset, size_t length) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return 0; - - DWORD bytes_written = 0; - - if (fh->is_file) { - // Seek to position - LONG lo = (LONG)offset; - LONG hi = (LONG)(offset >> 32); - DWORD r = SetFilePointer(fh->fh, lo, &hi, FILE_BEGIN); - if (r == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) - return 0; - - // Write data - if (WriteFile(fh->fh, buffer, length, &bytes_written, NULL) == 0) - bytes_written = 0; - } - // TODO: other media - - return bytes_written; -} - - -/* - * Return size of file/device (minus header) - */ - -loff_t SysGetFileSize(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (fh->is_file) - return fh->file_size; - else if (fh->is_cdrom) - return 0x28A00000; // FIXME: get real CD-ROM size - else { - // TODO: other media - return 0; - } -} - - -/* - * Eject volume (if applicable) - */ - -void SysEject(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (fh->is_cdrom && fh->fh) { - fh->is_media_present = false; - // Commented out because there was some problems, but can't remember - // exactly ... need to find out - // EjectVolume(toupper(*fh->name),false); - - // Preventing is cumulative, try to make sure it's indeed released now - for (int i = 0; i < 10; i++) - PreventRemovalOfVolume(fh->fh, false); - - if (!PrefsFindBool("nocdrom")) { - DWORD dummy; - DeviceIoControl( - fh->fh, - IOCTL_STORAGE_EJECT_MEDIA, - NULL, 0, - NULL, 0, - &dummy, - NULL - ); - } - cache_clear(&fh->cache); - fh->start_byte = 0; - } - // TODO: handle floppies -} - - -/* - * Format volume (if applicable) - */ - -bool SysFormat(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - //!! - return true; -} - - -/* - * Check if file/device is read-only (this includes the read-only flag on Sys_open()) - */ - -bool SysIsReadOnly(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - return fh->read_only; -} - - -/* - * Check if the given file handle refers to a fixed or a removable disk - */ - -bool SysIsFixedDisk(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return true; - - if (fh->is_file) - return true; - else if (fh->is_floppy || fh->is_cdrom) - return false; - else - return true; -} - - -/* - * Check if a disk is inserted in the drive (always true for files) - */ - -bool SysIsDiskInserted(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return false; - - if (fh->is_file) - return true; - else if (fh->is_cdrom && !PrefsFindBool("nocdrom")) { - if (PrefsFindBool("pollmedia")) - fh->is_media_present = is_cdrom_readable(fh); - return fh->is_media_present; - } - else { - // TODO: other media - } - - return false; -} - - -/* - * Prevent medium removal (if applicable) - */ - -void SysPreventRemoval(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (fh->is_cdrom && fh->fh) - PreventRemovalOfVolume(fh->fh, true); -} - - -/* - * Allow medium removal (if applicable) - */ - -void SysAllowRemoval(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - if (fh->is_cdrom && fh->fh) - PreventRemovalOfVolume(fh->fh, false); -} - - -/* - * Read CD-ROM TOC (binary MSF format, 804 bytes max.) - */ - -bool SysCDReadTOC(void *arg, uint8 *toc) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - DWORD dummy; - return DeviceIoControl(fh->fh, - IOCTL_CDROM_READ_TOC, - NULL, 0, - toc, min((int)sizeof(CDROM_TOC), 804), - &dummy, - NULL) != FALSE; -} - - -/* - * Read CD-ROM position data (Sub-Q Channel, 16 bytes, see SCSI standard) - */ - -bool SysCDGetPosition(void *arg, uint8 *pos) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - SUB_Q_CHANNEL_DATA q_data; - - CDROM_SUB_Q_DATA_FORMAT q_format; - q_format.Format = IOCTL_CDROM_CURRENT_POSITION; - q_format.Track = 0; // used only by ISRC reads - - DWORD dwBytesReturned = 0; - bool ok = DeviceIoControl(fh->fh, - IOCTL_CDROM_READ_Q_CHANNEL, - &q_format, sizeof(CDROM_SUB_Q_DATA_FORMAT), - &q_data, sizeof(SUB_Q_CHANNEL_DATA), - &dwBytesReturned, - NULL) != FALSE; - if (ok) - memcpy(pos, &q_data.CurrentPosition, sizeof(SUB_Q_CURRENT_POSITION)); - - return ok; -} - - -/* - * Play CD audio - */ - -bool SysCDPlay(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, uint8 end_m, uint8 end_s, uint8 end_f) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - CDROM_PLAY_AUDIO_MSF msf; - msf.StartingM = start_m; - msf.StartingS = start_s; - msf.StartingF = start_f; - msf.EndingM = end_m; - msf.EndingS = end_s; - msf.EndingF = end_f; - - DWORD dwBytesReturned = 0; - return DeviceIoControl(fh->fh, - IOCTL_CDROM_PLAY_AUDIO_MSF, - &msf, sizeof(CDROM_PLAY_AUDIO_MSF), - NULL, 0, - &dwBytesReturned, - NULL) != FALSE; -} - - -/* - * Pause CD audio - */ - -bool SysCDPause(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - DWORD dwBytesReturned = 0; - return DeviceIoControl(fh->fh, - IOCTL_CDROM_PAUSE_AUDIO, - NULL, 0, - NULL, 0, - &dwBytesReturned, - NULL) != FALSE; -} - - -/* - * Resume paused CD audio - */ - -bool SysCDResume(void *arg) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - DWORD dwBytesReturned = 0; - return DeviceIoControl(fh->fh, - IOCTL_CDROM_RESUME_AUDIO, - NULL, 0, - NULL, 0, - &dwBytesReturned, NULL) != FALSE; -} - - -/* - * Stop CD audio - */ - -bool SysCDStop(void *arg, uint8 lead_out_m, uint8 lead_out_s, uint8 lead_out_f) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - DWORD dwBytesReturned = 0; - return DeviceIoControl(fh->fh, - IOCTL_CDROM_STOP_AUDIO, - NULL, 0, - NULL, 0, - &dwBytesReturned, - NULL) != FALSE; -} - - -/* - * Perform CD audio fast-forward/fast-reverse operation starting from specified address - */ - -bool SysCDScan(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, bool reverse) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return false; - - CDROM_SEEK_AUDIO_MSF msf; - msf.M = start_m; - msf.S = start_s; - msf.F = start_f; - - DWORD dwBytesReturned = 0; - return DeviceIoControl(fh->fh, - IOCTL_CDROM_SEEK_AUDIO_MSF, - &msf, sizeof(CDROM_SEEK_AUDIO_MSF), - NULL, 0, - &dwBytesReturned, - NULL) != FALSE; -} - - -/* - * Set CD audio volume (0..255 each channel) - */ - -void SysCDSetVolume(void *arg, uint8 left, uint8 right) -{ - file_handle *fh = (file_handle *)arg; - if (!fh || !fh->fh || !fh->is_cdrom) - return; - - VOLUME_CONTROL vc; - vc.PortVolume[0] = left; - vc.PortVolume[1] = right; - vc.PortVolume[2] = left; - vc.PortVolume[3] = right; - - DWORD dwBytesReturned = 0; - DeviceIoControl(fh->fh, - IOCTL_CDROM_SET_VOLUME, - &vc, sizeof(VOLUME_CONTROL), - NULL, 0, - &dwBytesReturned, - NULL); -} - - -/* - * Get CD audio volume (0..255 each channel) - */ - -void SysCDGetVolume(void *arg, uint8 &left, uint8 &right) -{ - file_handle *fh = (file_handle *)arg; - if (!fh) - return; - - left = right = 0; - if (!fh->fh || !fh->is_cdrom) - return; - - VOLUME_CONTROL vc; - memset(&vc, 0, sizeof(vc)); - - DWORD dwBytesReturned = 0; - if (DeviceIoControl(fh->fh, - IOCTL_CDROM_GET_VOLUME, - NULL, 0, - &vc, sizeof(VOLUME_CONTROL), - &dwBytesReturned, - NULL)) - { - left = vc.PortVolume[0]; - right = vc.PortVolume[1]; - } -} diff --git a/BasiliskII/src/Windows/sysdeps.h b/BasiliskII/src/Windows/sysdeps.h deleted file mode 100755 index c1d7898f..00000000 --- a/BasiliskII/src/Windows/sysdeps.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * sysdeps.h - System dependent definitions for Windows - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -#if !defined _MSC_VER && !defined __STDC__ -#error "Your compiler is not ANSI. Get a real one." -#endif - -#include "config.h" -#include "user_strings_windows.h" - -#ifndef STDC_HEADERS -#error "You don't have ANSI C header files." -#endif - -#ifndef WIN32 -#define WIN32 -#endif - -#include -#include -#include -#include -#include -#include -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - - -/* Mac and host address space are distinct */ -#ifndef REAL_ADDRESSING -#define REAL_ADDRESSING 0 -#endif -#if REAL_ADDRESSING -#error "Real Addressing mode can't work without proper kernel support" -#endif - -/* Using 68k emulator */ -#define EMULATED_68K 1 - -/* The m68k emulator uses a prefetch buffer ? */ -#define USE_PREFETCH_BUFFER 0 - -/* Mac ROM is write protected when banked memory is used */ -#if REAL_ADDRESSING || DIRECT_ADDRESSING -# define ROM_IS_WRITE_PROTECTED 0 -# define USE_SCRATCHMEM_SUBTERFUGE 1 -#else -# define ROM_IS_WRITE_PROTECTED 1 -#endif - -/* Direct Addressing requires Video on SEGV signals in plain X11 mode */ -#if DIRECT_ADDRESSING && (!ENABLE_VOSF && !USE_SDL_VIDEO) -# undef ENABLE_VOSF -# define ENABLE_VOSF 1 -#endif - -/* ExtFS is supported */ -#define SUPPORTS_EXTFS 1 - -/* POSIX data types missing from Microsoft's CRT */ -#ifdef _MSC_VER -typedef ptrdiff_t ssize_t; -#endif - -/* Data types */ -typedef unsigned char uint8; -typedef signed char int8; -#if SIZEOF_SHORT == 2 -typedef unsigned short uint16; -typedef short int16; -#elif SIZEOF_INT == 2 -typedef unsigned int uint16; -typedef int int16; -#else -#error "No 2 byte type, you lose." -#endif -#if SIZEOF_INT == 4 -typedef unsigned int uint32; -typedef int int32; -#elif SIZEOF_LONG == 4 -typedef unsigned long uint32; -typedef long int32; -#else -#error "No 4 byte type, you lose." -#endif -#if SIZEOF_LONG == 8 -typedef unsigned long uint64; -typedef long int64; -#define VAL64(a) (a ## l) -#define UVAL64(a) (a ## ul) -#elif SIZEOF_LONG_LONG == 8 -typedef unsigned long long uint64; -typedef long long int64; -#define VAL64(a) (a ## LL) -#define UVAL64(a) (a ## uLL) -#else -#error "No 8 byte type, you lose." -#endif -#if SIZEOF_VOID_P == 4 -typedef uint32 uintptr; -typedef int32 intptr; -#elif SIZEOF_VOID_P == 8 -typedef uint64 uintptr; -typedef int64 intptr; -#else -#error "Unsupported size of pointer" -#endif - -#ifdef _WIN32 -typedef int64 loff_t; -#endif -#ifndef HAVE_CADDR_T -typedef char * caddr_t; -#endif - -#ifdef _MSC_VER -#ifdef _M_IX86 -#define __i386__ -#elif defined _M_AMD64 -#define __x86_64__ -#endif -#endif - -/* Time data type for Time Manager emulation */ -typedef int64 tm_time_t; - -/* Define codes for all the float formats that we know of. - * Though we only handle IEEE format. */ -#define UNKNOWN_FLOAT_FORMAT 0 -#define IEEE_FLOAT_FORMAT 1 -#define VAX_FLOAT_FORMAT 2 -#define IBM_FLOAT_FORMAT 3 -#define C4X_FLOAT_FORMAT 4 - -/* UAE CPU data types */ -#define uae_s8 int8 -#define uae_u8 uint8 -#define uae_s16 int16 -#define uae_u16 uint16 -#define uae_s32 int32 -#define uae_u32 uint32 -#define uae_s64 int64 -#define uae_u64 uint64 -typedef uae_u32 uaecptr; - -/* Timing functions */ -extern void timer_init(void); -extern uint64 GetTicks_usec(void); -extern void Delay_usec(uint32 usec); - -/* Spinlocks */ -#ifdef __GNUC__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - long int ret; - /* Note: the "xchg" instruction does not need a "lock" prefix */ - __asm__ __volatile__("xchgl %k0, %1" - : "=r" (ret), "=m" (*p) - : "0" (1), "m" (*p) - : "memory"); - return ret; -} -#endif /* __GNUC__ */ - -typedef volatile int spinlock_t; - -static const spinlock_t SPIN_LOCK_UNLOCKED = 0; - -#if HAVE_TEST_AND_SET -#define HAVE_SPINLOCKS 1 -static inline void spin_lock(spinlock_t *lock) -{ - while (testandset(lock)); -} - -static inline void spin_unlock(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return !testandset(lock); -} -#else -static inline void spin_lock(spinlock_t *lock) -{ -} - -static inline void spin_unlock(spinlock_t *lock) -{ -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return 1; -} -#endif - -#define X86_PPRO_OPT -#define HAVE_OPTIMIZED_BYTESWAP_32 -#define HAVE_OPTIMIZED_BYTESWAP_16 - -#ifdef _MSC_VER -static inline uae_u32 do_get_mem_long(uae_u32 *a) {return _byteswap_ulong(*a);} -static inline uae_u32 do_get_mem_word(uae_u16 *a) {return _byteswap_ushort(*a);} -static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {*a = _byteswap_ulong(v);} -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {*a = _byteswap_ushort(v);} -static inline uae_u32 do_byteswap_32_g(uae_u32 v) {return _byteswap_ulong(v);} -static inline uae_u32 do_byteswap_16_g(uae_u32 v) {return _byteswap_ushort(v);} -#else -/* Intel x86 */ -static inline uae_u32 do_get_mem_long(uae_u32 *a) {uint32 retval; __asm__ ("bswap %0" : "=r" (retval) : "0" (*a) : "cc"); return retval;} -#ifdef X86_PPRO_OPT -static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint32 retval; __asm__ ("movzwl %w1,%k0\n\tshll $16,%k0\n\tbswapl %k0\n" : "=&r" (retval) : "m" (*a) : "cc"); return retval;} -#else -static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint32 retval; __asm__ ("xorl %k0,%k0\n\tmovw %w1,%w0\n\trolw $8,%w0" : "=&r" (retval) : "m" (*a) : "cc"); return retval;} -#endif -static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {__asm__ ("bswap %0" : "=r" (v) : "0" (v) : "cc"); *a = v;} -#ifdef X86_PPRO_OPT -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {__asm__ ("bswapl %0" : "=&r" (v) : "0" (v << 16) : "cc"); *a = v;} -#else -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {__asm__ ("rolw $8,%0" : "=r" (v) : "0" (v) : "cc"); *a = v;} -#endif -/* bswap doesn't affect condition codes */ -static inline uae_u32 do_byteswap_32_g(uae_u32 v) {__asm__ ("bswap %0" : "=r" (v) : "0" (v)); return v;} -#ifdef X86_PPRO_OPT -static inline uae_u32 do_byteswap_16_g(uae_u32 v) {__asm__ ("bswapl %0" : "=&r" (v) : "0" (v << 16) : "cc"); return v;} -#else -static inline uae_u32 do_byteswap_16_g(uae_u32 v) {__asm__ ("rolw $8,%0" : "=r" (v) : "0" (v) : "cc"); return v;} -#endif -#endif - -#define HAVE_GET_WORD_UNSWAPPED -#define do_get_mem_word_unswapped(a) ((uae_u32)*((uae_u16 *)(a))) - -#ifndef HAVE_OPTIMIZED_BYTESWAP_32 -static inline uae_u32 do_byteswap_32_g(uae_u32 v) - { return (((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v & 0xff) << 24) | ((v & 0xff00) << 8)); } -#endif - -#ifndef HAVE_OPTIMIZED_BYTESWAP_16 -static inline uae_u32 do_byteswap_16_g(uae_u32 v) - { return (((v >> 8) & 0xff) | ((v & 0xff) << 8)); } -#endif - -#define do_byteswap_16_c(x) \ - ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) - -#define do_byteswap_32_c(x) \ - ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - -#if defined(__GNUC__) -#define do_byteswap_16(x) \ - (__extension__ \ - ({ register uint16 __v, __x = (x); \ - if (__builtin_constant_p(__x)) \ - __v = do_byteswap_16_c(__x); \ - else \ - __v = do_byteswap_16_g(__x); \ - __v; })) - -#define do_byteswap_32(x) \ - (__extension__ \ - ({ register uint32 __v, __x = (x); \ - if (__builtin_constant_p(__x)) \ - __v = do_byteswap_32_c(__x); \ - else \ - __v = do_byteswap_32_g(__x); \ - __v; })) -#else -#define do_byteswap_16(x) do_byteswap_16_g(x) -#define do_byteswap_32(x) do_byteswap_32_g(x) -#endif - -/* Byte-swapping routines */ -#if defined(__i386__) || defined(__x86_64__) -#define ntohl(x) do_byteswap_32(x) -#define ntohs(x) do_byteswap_16(x) -#define htonl(x) do_byteswap_32(x) -#define htons(x) do_byteswap_16(x) -#endif - -#define do_get_mem_byte(a) ((uae_u32)*((uae_u8 *)(a))) -#define do_put_mem_byte(a, v) (*(uae_u8 *)(a) = (v)) - -#define call_mem_get_func(func, addr) ((*func)(addr)) -#define call_mem_put_func(func, addr, v) ((*func)(addr, v)) -#define __inline__ inline -#define CPU_EMU_SIZE 0 -#undef NO_INLINE_MEMORY_ACCESS -#undef MD_HAVE_MEM_1_FUNCS -#define ENUMDECL typedef enum -#define ENUMNAME(name) name -#define write_log printf - -#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) -#define ASM_SYM(a) __asm__(a) -#else -#define ASM_SYM(a) -#endif - -#ifndef REGPARAM -# define REGPARAM -#endif -#define REGPARAM2 - -#ifdef _MSC_VER -#define ATTRIBUTE_PACKED -#endif - -#endif diff --git a/BasiliskII/src/Windows/timer_windows.cpp b/BasiliskII/src/Windows/timer_windows.cpp deleted file mode 100755 index d0aed8ac..00000000 --- a/BasiliskII/src/Windows/timer_windows.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * timer_windows.cpp - Time Manager emulation, Windows specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "main.h" -#include "macos_util.h" -#include "timer.h" - -#define DEBUG 0 -#include "debug.h" - - -// Helper time functions -#define MSECS2TICKS(MSECS) (((uint64)(MSECS) * frequency) / 1000) -#define USECS2TICKS(USECS) (((uint64)(USECS) * frequency) / 1000000) -#define TICKS2USECS(TICKS) (((uint64)(TICKS) * 1000000) / frequency) - -// From main_windows.cpp -extern HANDLE emul_thread; - -// Global variables -static uint32 frequency; // CPU frequency in Hz (< 4 GHz) -static tm_time_t mac_boot_ticks; -static tm_time_t mac_1904_ticks; -static tm_time_t mac_now_diff; - - -/* - * Initialize native Windows timers - */ - -void timer_init(void) -{ - D(bug("SysTimerInit\n")); - - LARGE_INTEGER tt; - if (!QueryPerformanceFrequency(&tt)) { - ErrorAlert("No high resolution timers available\n"); - QuitEmulator(); - } - frequency = tt.LowPart; - D(bug(" frequency %d\n", frequency)); - - // mac_boot_ticks is 1.18 us since Basilisk II was started - QueryPerformanceCounter(&tt); - mac_boot_ticks = tt.QuadPart; - - // mac_1904_ticks is 1.18 us since Mac time started 1904 - mac_1904_ticks = time(NULL) * frequency; - mac_now_diff = mac_1904_ticks - mac_boot_ticks; -} - - - /* - * Return microseconds since boot (64 bit) - */ - -void Microseconds(uint32 &hi, uint32 &lo) -{ - D(bug("Microseconds\n")); - LARGE_INTEGER tt; - QueryPerformanceCounter(&tt); - tt.QuadPart = TICKS2USECS(tt.QuadPart - mac_boot_ticks); - hi = tt.HighPart; - lo = tt.LowPart; -} - - -/* - * Return local date/time in Mac format (seconds since 1.1.1904) - */ - -uint32 TimerDateTime(void) -{ - return TimeToMacTime(time(NULL)); -} - - -/* - * Get current time - */ - -void timer_current_time(tm_time_t &t) -{ - LARGE_INTEGER tt; - QueryPerformanceCounter(&tt); - t = tt.QuadPart + mac_now_diff; -} - - -/* - * Add times - */ - -void timer_add_time(tm_time_t &res, tm_time_t a, tm_time_t b) -{ - res = a + b; -} - - -/* - * Subtract times - */ - -void timer_sub_time(tm_time_t &res, tm_time_t a, tm_time_t b) -{ - res = a - b; -} - - -/* - * Compare times (<0: a < b, =0: a = b, >0: a > b) - */ - -int timer_cmp_time(tm_time_t a, tm_time_t b) -{ - tm_time_t r = a - b; - return r < 0 ? -1 : (r > 0 ? 1 : 0); -} - - -/* - * Convert Mac time value (>0: microseconds, <0: microseconds) to tm_time_t - */ - -void timer_mac2host_time(tm_time_t &res, int32 mactime) -{ - if (mactime > 0) { - // Time in milliseconds - res = MSECS2TICKS(mactime); - } else { - // Time in negative microseconds - res = USECS2TICKS(-mactime); - } -} - - -/* - * Convert positive tm_time_t to Mac time value (>0: microseconds, <0: microseconds) - * A negative input value for hosttime results in a zero return value - * As long as the microseconds value fits in 32 bit, it must not be converted to milliseconds! - */ - -int32 timer_host2mac_time(tm_time_t hosttime) -{ - if (hosttime < 0) - return 0; - else { - uint64 t = TICKS2USECS(hosttime); - if (t > 0x7fffffff) - return int32(t / 1000); // Time in milliseconds - else - return -int32(t); // Time in negative microseconds - } -} - - -/* - * Get current value of microsecond timer - */ - -uint64 GetTicks_usec(void) -{ - LARGE_INTEGER tt; - QueryPerformanceCounter(&tt); - return TICKS2USECS(tt.QuadPart - mac_boot_ticks); -} - - -/* - * Delay by specified number of microseconds (<1 second) - */ - -void Delay_usec(uint32 usec) -{ - // FIXME: fortunately, Delay_usec() is generally used with - // millisecond resolution anyway - Sleep(usec / 1000); -} - - -/* - * Suspend emulator thread, virtual CPU in idle mode - */ - -struct idle_sentinel { - idle_sentinel(); - ~idle_sentinel(); -}; -static idle_sentinel idle_sentinel; - -static int idle_sem_ok = -1; -static HANDLE idle_sem = NULL; - -static HANDLE idle_lock = NULL; -#define LOCK_IDLE WaitForSingleObject(idle_lock, INFINITE) -#define UNLOCK_IDLE ReleaseMutex(idle_lock) - -idle_sentinel::idle_sentinel() -{ - idle_sem_ok = 1; - if ((idle_sem = CreateSemaphore(0, 0, 1, NULL)) == NULL) - idle_sem_ok = 0; - if ((idle_lock = CreateMutex(NULL, FALSE, NULL)) == NULL) - idle_sem_ok = 0; -} - -idle_sentinel::~idle_sentinel() -{ - if (idle_lock) { - ReleaseMutex(idle_lock); - CloseHandle(idle_lock); - } - if (idle_sem) { - ReleaseSemaphore(idle_sem, 1, NULL); - CloseHandle(idle_sem); - } -} - -void idle_wait(void) -{ - LOCK_IDLE; - if (idle_sem_ok > 0) { - idle_sem_ok++; - UNLOCK_IDLE; - WaitForSingleObject(idle_sem, INFINITE); - return; - } - UNLOCK_IDLE; - - // Fallback: sleep 10 ms (this should not happen though) - Delay_usec(10000); -} - - -/* - * Resume execution of emulator thread, events just arrived - */ - -void idle_resume(void) -{ - LOCK_IDLE; - if (idle_sem_ok > 1) { - idle_sem_ok--; - UNLOCK_IDLE; - ReleaseSemaphore(idle_sem, 1, NULL); - return; - } - UNLOCK_IDLE; -} diff --git a/BasiliskII/src/Windows/user_strings_windows.cpp b/BasiliskII/src/Windows/user_strings_windows.cpp deleted file mode 100755 index c2241250..00000000 --- a/BasiliskII/src/Windows/user_strings_windows.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * user_strings_windows.cpp - Windows-specific localizable strings - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "user_strings.h" - - -// Platform-specific string definitions -user_string_def platform_strings[] = { - // Common strings that have a platform-specific variant - {STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under Unix. Basilisk II will try to unmount it."}, - {STR_EXTFS_VOLUME_NAME, "My Computer"}, - - // Purely platform-specific strings - {STR_NO_XVISUAL_ERR, "Cannot obtain appropriate X visual."}, - {STR_VOSF_INIT_ERR, "Cannot initialize Video on SEGV signals."}, - {STR_SIG_INSTALL_ERR, "Cannot install %s handler (%s)."}, - {STR_TICK_THREAD_ERR, "Cannot create 60Hz thread (%s)."}, - {STR_SLIRP_NO_DNS_FOUND_WARN, "Cannot get DNS address. Ethernet will not be available."}, - {STR_NO_AUDIO_WARN, "No audio device found, audio output will be disabled."}, - {STR_KEYCODE_FILE_WARN, "Cannot open keycode translation file %s (%s)."}, - {STR_KEYCODE_VENDOR_WARN, "Cannot find vendor '%s' in keycode translation file %s."}, - {STR_WINDOW_TITLE_GRABBED, "Basilisk II (mouse grabbed, press Ctrl-F5 to release)"}, - {STR_NO_WIN32_NT_4, "Basilisk II does not run on Windows NT versions less than 4.0"}, - - {STR_PREFS_MENU_FILE_GTK, "/_File"}, - {STR_PREFS_ITEM_START_GTK, "/File/_Start Basilisk II"}, - {STR_PREFS_ITEM_ZAP_PRAM_GTK, "/File/_Zap PRAM File"}, - {STR_PREFS_ITEM_SEPL_GTK, "/File/sepl"}, - {STR_PREFS_ITEM_QUIT_GTK, "/File/_Quit Basilisk II"}, - {STR_HELP_MENU_GTK, "/_Help"}, - {STR_HELP_ITEM_ABOUT_GTK, "/Help/_About Basilisk II"}, - - {STR_ABOUT_BUTTON, "About"}, - {STR_FILE_CTRL, "File"}, - {STR_BROWSE_TITLE, "Browse file"}, - {STR_BROWSE_CTRL, "Browse..."}, - {STR_SERIAL_PANE_TITLE, "Serial"}, - {STR_NETWORK_PANE_TITLE, "Network"}, - {STR_INPUT_PANE_TITLE, "Keyboard/Mouse"}, - {STR_KEYCODES_CTRL, "Use Raw Keycodes"}, - {STR_KEYCODE_FILE_CTRL, "Keycode Translation File"}, - {STR_MOUSEWHEELMODE_CTRL, "Mouse Wheel Function"}, - {STR_MOUSEWHEELMODE_PAGE_LAB, "Page Up/Down"}, - {STR_MOUSEWHEELMODE_CURSOR_LAB, "Cursor Up/Down"}, - {STR_MOUSEWHEELLINES_CTRL, "Lines To Scroll"}, - {STR_POLLMEDIA_CTRL, "Try to automatically detect new removable media (enable polling)"}, - {STR_EXTFS_ENABLE_CTRL, "Enable \"My Computer\" icon on your Mac desktop (external file system)"}, - {STR_EXTFS_DRIVES_CTRL, "Mount drives"}, - {STR_ETHER_FTP_PORT_LIST_CTRL, "FTP ports"}, - {STR_ETHER_TCP_PORT_LIST_CTRL, "Server ports"}, - - {STR_IGNORESEGV_CTRL, "Ignore Illegal Memory Accesses"}, - - {-1, NULL} // End marker -}; - - -/* - * Search for main volume name - */ - -static const char *get_volume_name(void) -{ - HKEY hHelpKey; - DWORD key_type, cbData; - - static char volume[256]; - memset(volume, 0, sizeof(volume)); - - // Try Windows 2000 key first - if (ERROR_SUCCESS == RegOpenKey( - HKEY_CURRENT_USER, - TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), - &hHelpKey)) - { - cbData = sizeof(volume); - RegQueryValueEx( hHelpKey, 0, NULL, &key_type, (unsigned char *)volume, &cbData ); - RegCloseKey(hHelpKey); - } - - if (volume[0] == 0 && - ERROR_SUCCESS == RegOpenKey( - HKEY_CURRENT_USER, - TEXT("Software\\Classes\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), - &hHelpKey)) - { - cbData = sizeof(volume); - RegQueryValueEx( hHelpKey, 0, NULL, &key_type, (unsigned char *)volume, &cbData ); - RegCloseKey(hHelpKey); - } - - if (volume[0] == 0 && - ERROR_SUCCESS == RegOpenKey( - HKEY_CLASSES_ROOT, - TEXT("CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), - &hHelpKey)) - { - cbData = sizeof(volume); - RegQueryValueEx( hHelpKey, 0, NULL, &key_type, (unsigned char *)volume, &cbData ); - RegCloseKey(hHelpKey); - } - - // Fix the error that some "tweak" apps do. - if (_stricmp(volume, "%USERNAME% on %COMPUTER%") == 0) - volume[0] = '\0'; - - // No volume name found, default to "My Computer" - if (volume[0] == 0) - strcpy(volume, "My Computer"); - - return volume; -} - - -/* - * Fetch pointer to string, given the string number - */ - -const char *GetString(int num) -{ - // First, search for platform-specific variable string - switch (num) { - case STR_EXTFS_VOLUME_NAME: - return get_volume_name(); - } - - // Next, search for platform-specific constant string - int i = 0; - while (platform_strings[i].num >= 0) { - if (platform_strings[i].num == num) - return platform_strings[i].str; - i++; - } - - // Not found, search for common string - i = 0; - while (common_strings[i].num >= 0) { - if (common_strings[i].num == num) - return common_strings[i].str; - i++; - } - return NULL; -} - -/* - * Convert text to wide string, given the string number - */ -std::unique_ptr GetStringW(int num) -{ - auto str = GetString(num); - if (str == nullptr) - return nullptr; - - auto length = MultiByteToWideChar(CP_ACP, 0, str, -1, nullptr, 0); - if (length == 0) - return nullptr; - - auto p = std::unique_ptr(new wchar_t[length]); - MultiByteToWideChar(CP_ACP, 0, str, -1, p.get(), length); - return p; -} diff --git a/BasiliskII/src/Windows/user_strings_windows.h b/BasiliskII/src/Windows/user_strings_windows.h deleted file mode 100755 index ccf5ff54..00000000 --- a/BasiliskII/src/Windows/user_strings_windows.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * user_strings_windows.h - Windows-specific localizable strings - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_WINDOWS_H -#define USER_STRINGS_WINDOWS_H - -#ifdef __cplusplus -#if __cplusplus >= 201103L || _MSC_VER >= 1600 -#include - - // Convert text to wide string, given the string number -extern std::unique_ptr GetStringW(int num); -#endif -#endif - -enum { - STR_NO_XVISUAL_ERR = 10000, - STR_VOSF_INIT_ERR, - STR_SIG_INSTALL_ERR, - STR_TICK_THREAD_ERR, - STR_SLIRP_NO_DNS_FOUND_WARN, - STR_NO_AUDIO_WARN, - STR_KEYCODE_FILE_WARN, - STR_KEYCODE_VENDOR_WARN, - STR_WINDOW_TITLE_GRABBED, - STR_NO_WIN32_NT_4, - - STR_PREFS_MENU_FILE_GTK, - STR_PREFS_ITEM_START_GTK, - STR_PREFS_ITEM_ZAP_PRAM_GTK, - STR_PREFS_ITEM_SEPL_GTK, - STR_PREFS_ITEM_QUIT_GTK, - STR_HELP_MENU_GTK, - STR_HELP_ITEM_ABOUT_GTK, - - STR_ABOUT_BUTTON, - STR_FILE_CTRL, - STR_BROWSE_CTRL, - STR_BROWSE_TITLE, - STR_SERIAL_PANE_TITLE, - STR_NETWORK_PANE_TITLE, - STR_INPUT_PANE_TITLE, - STR_KEYCODES_CTRL, - STR_KEYCODE_FILE_CTRL, - STR_MOUSEWHEELMODE_CTRL, - STR_MOUSEWHEELMODE_PAGE_LAB, - STR_MOUSEWHEELMODE_CURSOR_LAB, - STR_MOUSEWHEELLINES_CTRL, - STR_POLLMEDIA_CTRL, - STR_EXTFS_ENABLE_CTRL, - STR_EXTFS_DRIVES_CTRL, - STR_ETHER_FTP_PORT_LIST_CTRL, - STR_ETHER_TCP_PORT_LIST_CTRL, - - STR_IGNORESEGV_CTRL, -}; - -#endif diff --git a/BasiliskII/src/Windows/util_windows.cpp b/BasiliskII/src/Windows/util_windows.cpp deleted file mode 100755 index ef29a06b..00000000 --- a/BasiliskII/src/Windows/util_windows.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* - * util_windows.cpp - Miscellaneous utilities for Win32 - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "util_windows.h" -#include "main.h" -#include -#include - -#include -using std::list; - -#include -using std::string; -using std::wstring; -typedef std::basic_string tstring; - -std::unique_ptr str(const wchar_t* s) -{ - auto length = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr); - if (length == -1) - return nullptr; - - std::unique_ptr p(new char[length]); - WideCharToMultiByte(CP_ACP, 0, s, -1, p.get(), length, nullptr, nullptr); - return p; -} - -std::unique_ptr wstr(const char* s) -{ - auto length = MultiByteToWideChar(CP_ACP, 0, s, -1, nullptr, 0); - if (length == -1) - return nullptr; - - std::unique_ptr p(new wchar_t[length]); - MultiByteToWideChar(CP_ACP, 0, s, -1, p.get(), length); - return p; -} - -string to_string(const wchar_t* s) -{ - auto wlen = wcslen(s); // length without null terminator - auto len = WideCharToMultiByte(CP_ACP, 0, s, wlen, nullptr, 0, nullptr, nullptr); - if (len == -1) - return string(); - - string str(len, '\0'); - WideCharToMultiByte(CP_ACP, 0, s, wlen, &str.front(), len, nullptr, nullptr); - return str; -} - -wstring to_wstring(const char* s) -{ - auto len = strlen(s); // length without null terminator - auto wlen = MultiByteToWideChar(CP_ACP, 0, s, len, nullptr, 0); - if (len == -1) - return wstring(); - - wstring str(wlen, L'\0'); - MultiByteToWideChar(CP_ACP, 0, s, len, &str.front(), wlen); - return str; -} - -size_t strlcpy(char* dst, const char* src, size_t size) -{ - size_t length = strlen(src); - if (size-- > 0) { - if (length < size) - size = length; - memcpy(dst, src, size); - dst[size] = '\0'; - } - return length; -} - -size_t strlcpy(char* dst, const wchar_t* src, size_t size) -{ - size_t length = WideCharToMultiByte(CP_ACP, 0, src, -1, dst, size, nullptr, nullptr); - if (size > 0) { - if (length == 0) - return strlcpy(dst, str(src).get(), size); - --length; - } - return length; -} - -size_t strlcat(char* dst, const char* src, size_t size) -{ - char* end = static_cast(memchr(dst, '\0', size)); - if (end == nullptr) - return size; - size_t length = end - dst; - return length + strlcpy(end, src, size - length); -} - -size_t strlcat(char* dst, const wchar_t* src, size_t size) -{ - char* end = static_cast(memchr(dst, '\0', size)); - if (end == nullptr) - return size; - size_t length = end - dst; - return length + strlcpy(end, src, size - length); -} - -size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t size) -{ - size_t length = wcslen(src); - if (size-- > 0) { - if (length < size) - size = length; - wmemcpy(dst, src, size); - dst[size] = '\0'; - } - return length; -} - -size_t wcslcpy(wchar_t* dst, const char* src, size_t size) -{ - size_t length = MultiByteToWideChar(CP_ACP, 0, src, -1, dst, size); - if (size > 0) { - if (length == 0) - return wcslcpy(dst, wstr(src).get(), size); - --length; - } - return length; -} - -size_t wcslcat(wchar_t* dst, const wchar_t* src, size_t size) -{ - wchar_t* end = wmemchr(dst, L'\0', size); - if (end == nullptr) - return size; - size_t length = end - dst; - return length + wcslcpy(end, src, size - length); -} - -size_t wcslcat(wchar_t* dst, const char* src, size_t size) -{ - wchar_t* end = wmemchr(dst, L'\0', size); - if (end == nullptr) - return size; - size_t length = end - dst; - return length + wcslcpy(end, src, size - length); -} - -BOOL exists( const TCHAR *path ) -{ - HFILE h; - bool ret = false; - - h = _topen( path, _O_RDONLY | _O_BINARY ); - if(h != -1) { - ret = true; - _close(h); - } - return(ret); -} - -BOOL create_file( const TCHAR *path, DWORD size ) -{ - HANDLE h; - bool ok = false; - - h = CreateFile( path, - GENERIC_READ | GENERIC_WRITE, - 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL - ); - if(h != INVALID_HANDLE_VALUE) { - if(size == 0) { - ok = true; - } else if(SetFilePointer( h, size, NULL, FILE_BEGIN) != 0xFFFFFFFF) { - if(SetEndOfFile(h)) { - ok = true; - if(SetFilePointer( h, 0, NULL, FILE_BEGIN) != 0xFFFFFFFF) { - DWORD written; - DWORD zeroed_size = size; - if (zeroed_size > 1024*1024) - zeroed_size = 1024*1024; - char *b = (char *)malloc(zeroed_size); - if(b) { - memset( b, 0, zeroed_size ); - WriteFile( h, b, zeroed_size, &written, NULL ); - free(b); - } - } - } - } - CloseHandle(h); - } - if(!ok) DeleteFile(path); - return(ok); -} - -int32 get_file_size( const TCHAR *path ) -{ - HANDLE h; - DWORD size = 0; - - h = CreateFile( path, - GENERIC_READ, - 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL - ); - if(h != INVALID_HANDLE_VALUE) { - size = GetFileSize( h, NULL ); - CloseHandle(h); - } - return(size); -} - - -/* - * Thread wrappers - */ - -HANDLE create_thread(LPTHREAD_START_ROUTINE start_routine, void *arg) -{ - DWORD dwThreadId; - return CreateThread(NULL, 0, start_routine, arg, 0, &dwThreadId); -} - -void wait_thread(HANDLE thread) -{ - WaitForSingleObject(thread, INFINITE); - CloseHandle(thread); -} - -void kill_thread(HANDLE thread) -{ - TerminateThread(thread, 0); -} - - -/* - * Check that drivers are installed - */ - -bool check_drivers(void) -{ - TCHAR path[_MAX_PATH]; - GetSystemDirectory(path, lengthof(path)); - _tcscat(path, TEXT("\\drivers\\cdenable.sys")); - - if (exists(path)) { - int32 size = get_file_size(path); - if (size != 6112) { - TCHAR str[256]; - _sntprintf(str, lengthof(str), TEXT("The CD-ROM driver file \"%s\" is too old or corrupted."), path); - ErrorAlert(str); - return false; - } - } - else { - TCHAR str[256]; - _sntprintf(str, lengthof(str), TEXT("The CD-ROM driver file \"%s\" is missing."), path); - WarningAlert(str); - } - - return true; -} - - -/* - * Network control panel helpers - */ - -struct panel_reg { - tstring name; - tstring guid; -}; - -static list network_registry; -typedef list::const_iterator network_registry_iterator; - -#define NETWORK_CONNECTIONS_KEY \ - TEXT("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}") - -static void get_network_registry(void) -{ - LONG status; - HKEY network_connections_key; - DWORD len; - int i = 0; - - if (network_registry.size() > 0) - return; - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - NETWORK_CONNECTIONS_KEY, - 0, - KEY_READ, - &network_connections_key); - - if (status != ERROR_SUCCESS) - return; - - while (true) { - TCHAR enum_name[256]; - TCHAR connection_string[256]; - HKEY connection_key; - TCHAR name_data[256]; - DWORD name_type; - const TCHAR name_string[] = TEXT("Name"); - - len = lengthof(enum_name); - status = RegEnumKeyEx( - network_connections_key, - i, - enum_name, - &len, - NULL, - NULL, - NULL, - NULL); - if (status != ERROR_SUCCESS) - break; - - _sntprintf (connection_string, lengthof(connection_string), - TEXT("%s\\%s\\Connection"), - NETWORK_CONNECTIONS_KEY, enum_name); - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - connection_string, - 0, - KEY_READ, - &connection_key); - - if (status == ERROR_SUCCESS) { - len = lengthof(name_data); - status = RegQueryValueEx( - connection_key, - name_string, - NULL, - &name_type, - (BYTE *)name_data, - &len); - - if (status == ERROR_SUCCESS && name_type == REG_SZ) { - panel_reg pr; - pr.name = name_data; - pr.guid = enum_name; - network_registry.push_back(pr); - } - RegCloseKey (connection_key); - } - ++i; - } - - RegCloseKey (network_connections_key); -} - -const TCHAR *ether_name_to_guid(const TCHAR *name) -{ - get_network_registry(); - - for (network_registry_iterator it = network_registry.begin(); it != network_registry.end(); it++) { - if (_tcscmp((*it).name.c_str(), name) == 0) - return (*it).guid.c_str(); - } - - return NULL; -} - -const TCHAR *ether_guid_to_name(const TCHAR *guid) -{ - get_network_registry(); - - for (network_registry_iterator it = network_registry.begin(); it != network_registry.end(); it++) { - if (_tcscmp((*it).guid.c_str(), guid) == 0) - return (*it).name.c_str(); - } - - return NULL; -} - - -/* - * Get TAP-Win32 adapters - */ - -#define ADAPTER_KEY TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}") - -#define TAP_COMPONENT_ID TEXT("tap0801") - -const TCHAR *ether_tap_devices(void) -{ - HKEY adapter_key; - LONG status; - DWORD len; - int i = 0; - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - ADAPTER_KEY, - 0, - KEY_READ, - &adapter_key); - - if (status != ERROR_SUCCESS) - return NULL; - - list devices; - - while (true) { - TCHAR enum_name[256]; - TCHAR unit_string[256]; - HKEY unit_key; - TCHAR component_id_string[] = TEXT("ComponentId"); - TCHAR component_id[256]; - TCHAR net_cfg_instance_id_string[] = TEXT("NetCfgInstanceId"); - TCHAR net_cfg_instance_id[256]; - DWORD data_type; - - len = lengthof(enum_name); - status = RegEnumKeyEx( - adapter_key, - i, - enum_name, - &len, - NULL, - NULL, - NULL, - NULL); - if (status != ERROR_SUCCESS) - break; - - _sntprintf (unit_string, lengthof(unit_string), TEXT("%s\\%s"), - ADAPTER_KEY, enum_name); - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - unit_string, - 0, - KEY_READ, - &unit_key); - - if (status == ERROR_SUCCESS) { - len = lengthof(component_id); - status = RegQueryValueEx( - unit_key, - component_id_string, - NULL, - &data_type, - (BYTE *)component_id, - &len); - - if (status == ERROR_SUCCESS && data_type == REG_SZ) { - len = lengthof(net_cfg_instance_id); - status = RegQueryValueEx( - unit_key, - net_cfg_instance_id_string, - NULL, - &data_type, - (BYTE *)net_cfg_instance_id, - &len); - - if (status == ERROR_SUCCESS && data_type == REG_SZ) { - if (!_tcscmp (component_id, TAP_COMPONENT_ID)) - devices.push_back(net_cfg_instance_id); - } - } - RegCloseKey (unit_key); - } - ++i; - } - - RegCloseKey (adapter_key); - - if (devices.empty()) - return NULL; - - // The result is a '\0' separated list of strings - list::const_iterator it; - len = 0; - for (it = devices.begin(); it != devices.end(); it++) - len += (*it).length() + 1; - - TCHAR *names = (TCHAR *)malloc(len * sizeof(TCHAR)); - if (names) { - TCHAR *p = names; - for (it = devices.begin(); it != devices.end(); it++) { - len = (*it).length(); - _tcscpy(p, (*it).c_str()); - p[len] = '\0'; - p += len + 1; - } - } - - return names; -} diff --git a/BasiliskII/src/Windows/util_windows.h b/BasiliskII/src/Windows/util_windows.h deleted file mode 100755 index 26435558..00000000 --- a/BasiliskII/src/Windows/util_windows.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * util_windows.h - Miscellaneous utilities for Win32 - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Windows platform specific code copyright (C) Lauri Pesonen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _UTIL_WINDOWS_H -#define _UTIL_WINDOWS_H - -#include -#include - -BOOL exists( const TCHAR *path ); -int32 get_file_size( const TCHAR *path ); -BOOL create_file( const TCHAR *path, DWORD size ); -bool check_drivers(void); - -// Thread wrappers -extern HANDLE create_thread(LPTHREAD_START_ROUTINE start_routine, void *arg = NULL); -extern void wait_thread(HANDLE thread); -extern void kill_thread(HANDLE thread); - -// Mutex wrappers -class mutex_t { - CRITICAL_SECTION cs; - public: - mutex_t() { InitializeCriticalSection(&cs); } - ~mutex_t() { DeleteCriticalSection(&cs); } - void lock() { EnterCriticalSection(&cs); } - void unlock() { LeaveCriticalSection(&cs); } -}; - -// Network control panel helpers -extern const TCHAR *ether_name_to_guid(const TCHAR *name); -extern const TCHAR *ether_guid_to_name(const TCHAR *guid); - -// Get TAP-Win32 devices (caller free()s returned buffer) -extern const TCHAR *ether_tap_devices(void); - -// Wide string versions of commonly used functions -extern void ErrorAlert(const wchar_t *text); -extern void WarningAlert(const wchar_t *text); - -// ----------------- String conversion functions ----------------- - -// Null deleter -- does nothing. Allows returning a non-owning -// unique_ptr. This should go away if observer_ptr makes it into -// the standard. -template struct null_delete { - constexpr null_delete() noexcept = default; - template null_delete(const null_delete&) noexcept { } - void operator ()(T*) const noexcept { } -}; -template struct null_delete { - constexpr null_delete() noexcept = default; - void operator ()(T*) const noexcept { } - template void operator ()(U*) const = delete; -}; - -// Functions returning null-terminated C strings -std::unique_ptr str(const wchar_t* s); -std::unique_ptr wstr(const char* s); - -inline std::unique_ptr> str(const char* s) -{ - return std::unique_ptr>(s); -} -inline std::unique_ptr> wstr(const wchar_t* s) -{ - return std::unique_ptr>(s); -} - -#ifdef _UNICODE -#define tstr wstr -#else -#define tstr str -#endif - -// Functions returning std::strings -std::string to_string(const wchar_t* s); -std::wstring to_wstring(const char* s); -inline std::string to_string(const char* s) { return std::string(s); } -inline std::wstring to_wstring(const wchar_t* s) { return std::wstring(s); } - -#ifdef _UNICODE -#define to_tstring to_wstring -#else -#define to_tstring to_string -#endif - -// BSD strlcpy/strlcat with overloads for converting between wide and narrow strings -size_t strlcpy(char* dst, const char* src, size_t size); -size_t strlcpy(char* dst, const wchar_t* src, size_t size); -size_t strlcat(char* dst, const char* src, size_t size); -size_t strlcat(char* dst, const wchar_t* src, size_t size); -size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t size); -size_t wcslcpy(wchar_t* dst, const char* src, size_t size); -size_t wcslcat(wchar_t* dst, const wchar_t* src, size_t size); -size_t wcslcat(wchar_t* dst, const char* src, size_t size); - -#ifdef _UNICODE -#define tcslcpy wcslcpy -#define tcslcat wcslcat -#else -#define tcslcpy strlcpy -#define tcslcat strlcat -#endif - -#endif // _UTIL_WINDOWS_H diff --git a/BasiliskII/src/Windows/xpram_windows.cpp b/BasiliskII/src/Windows/xpram_windows.cpp deleted file mode 100755 index 46c45040..00000000 --- a/BasiliskII/src/Windows/xpram_windows.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * xpram_windows.cpp - XPRAM handling, Windows specific stuff - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -typedef std::basic_string tstring; - -#include "xpram.h" - - -// XPRAM file name and path -#if POWERPC_ROM -const TCHAR XPRAM_FILE_NAME[] = TEXT("SheepShaver_nvram.dat"); -#else -const TCHAR XPRAM_FILE_NAME[] = TEXT("BasiliskII_xpram.dat"); -#endif -static tstring xpram_path; - - -/* - * Construct XPRAM path - */ - -static void build_xpram_path(void) -{ - xpram_path.clear(); - int pwd_len = GetCurrentDirectory(0, NULL); - TCHAR *pwd = new TCHAR[pwd_len]; - if (GetCurrentDirectory(pwd_len, pwd) == pwd_len - 1) - xpram_path = tstring(pwd) + TEXT('\\'); - delete[] pwd; - xpram_path += XPRAM_FILE_NAME; -} - - -/* - * Load XPRAM from settings file - */ - -void LoadXPRAM(const char *vmdir) -{ - // Construct XPRAM path - build_xpram_path(); - - // Load XPRAM from settings file - HANDLE fh = CreateFile(xpram_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (fh != INVALID_HANDLE_VALUE) { - DWORD bytesRead; - ReadFile(fh, XPRAM, XPRAM_SIZE, &bytesRead, NULL); - CloseHandle(fh); - } -} - - -/* - * Save XPRAM to settings file - */ - -void SaveXPRAM(void) -{ - HANDLE fh = CreateFile(xpram_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); - if (fh != INVALID_HANDLE_VALUE) { - DWORD bytesWritten; - WriteFile(fh, XPRAM, XPRAM_SIZE, &bytesWritten, NULL); - CloseHandle(fh); - } -} - - -/* - * Delete PRAM file - */ - -void ZapPRAM(void) -{ - // Construct PRAM path - build_xpram_path(); - - // Delete file - DeleteFile(xpram_path.c_str()); -} diff --git a/BasiliskII/src/emul_op.cpp b/BasiliskII/src/emul_op.cpp index 0f2b59fc..549d1de0 100644 --- a/BasiliskII/src/emul_op.cpp +++ b/BasiliskII/src/emul_op.cpp @@ -42,9 +42,6 @@ #include "extfs.h" #include "emul_op.h" -#ifdef ENABLE_MON -#include "mon.h" -#endif #define DEBUG 0 #include "debug.h" @@ -69,10 +66,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r) r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7], r->sr); VideoQuitFullScreen(); -#ifdef ENABLE_MON - const char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif + QuitEmulator(); break; } @@ -574,10 +568,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r) r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7], r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7], r->sr); -#ifdef ENABLE_MON - const char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif + QuitEmulator(); break; } diff --git a/BasiliskII/src/ether.cpp b/BasiliskII/src/ether.cpp index d5471029..e3f7e970 100644 --- a/BasiliskII/src/ether.cpp +++ b/BasiliskII/src/ether.cpp @@ -57,11 +57,8 @@ using std::map; #define MONITOR 0 -#ifdef __BEOS__ -#define CLOSESOCKET closesocket -#else + #define CLOSESOCKET close -#endif // Global variables @@ -138,12 +135,8 @@ void EtherInit(void) // Set socket options int on = 1; -#ifdef __BEOS__ - setsockopt(udp_socket, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(on)); -#else setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); ioctl(udp_socket, FIONBIO, &on); -#endif // Start thread for packet reception if (!ether_start_udp_thread(udp_socket)) { @@ -453,7 +446,6 @@ void ether_udp_read(uint32 packet, int length, struct sockaddr_in *from) * Ethernet packet allocator */ -#if SIZEOF_VOID_P != 4 || REAL_ADDRESSING == 0 static uint32 ether_packet = 0; // Ethernet packet (cached allocation) static uint32 n_ether_packets = 0; // Number of ethernet packets allocated so far (should be at most 1) @@ -485,4 +477,3 @@ EthernetPacket::~EthernetPacket() bug("WARNING: Nested allocation of ethernet packets!\n"); } } -#endif diff --git a/BasiliskII/src/extfs.cpp b/BasiliskII/src/extfs.cpp index f6ac09f1..fe421782 100644 --- a/BasiliskII/src/extfs.cpp +++ b/BasiliskII/src/extfs.cpp @@ -43,10 +43,8 @@ #include #include -#ifndef WIN32 #include #include -#endif #if defined __APPLE__ && defined __MACH__ #include @@ -61,10 +59,6 @@ #include "extfs.h" #include "extfs_defs.h" -#ifdef WIN32 -# include "posix_emu.h" -#endif - #define DEBUG 0 #include "debug.h" @@ -1049,9 +1043,7 @@ static int16 fs_volume_mount(uint32 pb) // Init VCB WriteMacInt16(vcb + vcbSigWord, 0x4244); -#if defined(__BEOS__) || defined(WIN32) - WriteMacInt32(vcb + vcbCrDate, TimeToMacTime(root_stat.st_crtime)); -#elif defined __APPLE__ && defined __MACH__ +#if defined __APPLE__ && defined __MACH__ WriteMacInt32(vcb + vcbCrDate, get_creation_time(RootPath)); #else WriteMacInt32(vcb + vcbCrDate, 0); @@ -1114,9 +1106,7 @@ static int16 fs_get_vol_info(uint32 pb, bool hfs) // Fill in struct if (ReadMacInt32(pb + ioNamePtr)) pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), VOLUME_NAME); -#if defined(__BEOS__) || defined(WIN32) - WriteMacInt32(pb + ioVCrDate, TimeToMacTime(root_stat.st_crtime)); -#elif defined __APPLE__ && defined __MACH__ +#if defined __APPLE__ && defined __MACH__ WriteMacInt32(pb + ioVCrDate, get_creation_time(RootPath)); #else WriteMacInt32(pb + ioVCrDate, 0); @@ -1308,9 +1298,7 @@ read_next_de: WriteMacInt8(pb + ioFlAttrib, access(full_path, W_OK) == 0 ? 0 : faLocked); WriteMacInt32(pb + ioDirID, fs_item->id); -#if defined(__BEOS__) || defined(WIN32) - WriteMacInt32(pb + ioFlCrDat, TimeToMacTime(st.st_crtime)); -#elif defined __APPLE__ && defined __MACH__ +#if defined __APPLE__ && defined __MACH__ WriteMacInt32(pb + ioFlCrDat, get_creation_time(full_path)); #else WriteMacInt32(pb + ioFlCrDat, 0); @@ -1432,9 +1420,7 @@ read_next_de: WriteMacInt8(pb + ioACUser, 0); WriteMacInt32(pb + ioDirID, fs_item->id); WriteMacInt32(pb + ioFlParID, fs_item->parent_id); -#if defined(__BEOS__) || defined(WIN32) - WriteMacInt32(pb + ioFlCrDat, TimeToMacTime(st.st_crtime)); -#elif defined __APPLE__ && defined __MACH__ +#if defined __APPLE__ && defined __MACH__ WriteMacInt32(pb + ioFlCrDat, get_creation_time(full_path)); #else WriteMacInt32(pb + ioFlCrDat, 0); diff --git a/BasiliskII/src/include/debug.h b/BasiliskII/src/include/debug.h index 414ad324..330d7f5b 100644 --- a/BasiliskII/src/include/debug.h +++ b/BasiliskII/src/include/debug.h @@ -21,92 +21,10 @@ #ifndef DEBUG_H #define DEBUG_H -#if defined(WIN32) && !defined(__CYGWIN__) - -// Windows debugging goes where it's supposed to go -#include -#include -#include -#include -#include - -static inline void _cdecl vwinbug(const char *s, va_list vargs) -{ - char msg[1024], date[50], hours[50]; - struct _timeb tstruct; - - _ftime( &tstruct ); - _strtime( hours ); - _strdate( date ); - _snprintf( msg, lengthof(msg), "B2: %s %s:%03u ", date, hours, tstruct.millitm ); - - char *rest = &msg[strlen(msg)]; - _vsnprintf( rest, lengthof(msg) - (rest - msg), s, vargs ); - - OutputDebugStringA(msg); -} -static inline void _cdecl vwwinbug( const wchar_t *s, va_list vargs) -{ - wchar_t msg[1024], date[50], hours[50]; - struct _timeb tstruct; - - _ftime( &tstruct ); - _wstrtime( hours ); - _wstrdate( date ); - _snwprintf( msg, lengthof(msg), L"B2: %s %s:%03u ", date, hours, tstruct.millitm ); - - wchar_t *rest = &msg[wcslen(msg)]; - _vsnwprintf( rest, lengthof(msg) - (rest - msg), s, vargs ); - - OutputDebugStringW(msg); -} -static inline void _cdecl winbug( const char *s, ...) -{ - va_list vargs; - va_start(vargs, s); - vwinbug(s, vargs); - va_end(vargs); -} -static inline void _cdecl wwinbug(const wchar_t *s, ...) -{ - va_list vargs; - va_start(vargs, s); - vwwinbug(s, vargs); - va_end(vargs); -} - -#ifdef __cplusplus -static inline void _cdecl winbug(wchar_t *s, ...) -{ - va_list vargs; - va_start(vargs, s); - vwwinbug(s, vargs); - va_end(vargs); -} -#endif -#define bug winbug -#define wbug wwinbug - -#elif defined(AMIGA) - -// Amiga debugging info goes to serial port (or sushi) -#ifdef __cplusplus -extern "C" { -#endif -extern void kprintf(const char *, ...); -#ifdef __cplusplus -} -#endif -#define bug kprintf - -#else - // Other systems just print it to stdout #include #define bug printf -#endif - #if DEBUG #define D(x) (x); #else diff --git a/BasiliskII/src/include/ether.h b/BasiliskII/src/include/ether.h index e1e988d0..7c02e020 100644 --- a/BasiliskII/src/include/ether.h +++ b/BasiliskII/src/include/ether.h @@ -63,17 +63,13 @@ extern uint32 ether_data; // Mac address of driver data in MacOS RAM // Ethernet packet allocator (optimized for 32-bit platforms in real addressing mode) class EthernetPacket { -#if SIZEOF_VOID_P == 4 && REAL_ADDRESSING - uint8 packet[1516]; - public: - uint32 addr(void) const { return (uint32)packet; } -#else + uint32 packet; public: EthernetPacket(); ~EthernetPacket(); uint32 addr(void) const { return packet; } -#endif + }; // Copy packet data from WDS to linear buffer (must hold at least 1514 bytes), diff --git a/BasiliskII/src/main.cpp b/BasiliskII/src/main.cpp index dcb86e9c..2982bee7 100644 --- a/BasiliskII/src/main.cpp +++ b/BasiliskII/src/main.cpp @@ -42,20 +42,6 @@ #define DEBUG 0 #include "debug.h" -#if ENABLE_MON -#include "mon.h" - -static uint32 mon_read_byte_b2(uintptr adr) -{ - return ReadMacInt8(adr); -} - -static void mon_write_byte_b2(uintptr adr, uint32 b) -{ - WriteMacInt8(adr, b); -} -#endif - /* * Initialize everything, returns false on error @@ -192,13 +178,6 @@ bool InitAll(const char *vmdir) return false; } -#if ENABLE_MON - // Initialize mon - mon_init(); - mon_read_byte = mon_read_byte_b2; - mon_write_byte = mon_write_byte_b2; -#endif - return true; } @@ -209,10 +188,6 @@ bool InitAll(const char *vmdir) void ExitAll(void) { -#if ENABLE_MON - // Deinitialize mon - mon_exit(); -#endif // Save XPRAM XPRAMExit(); diff --git a/BasiliskII/src/native_cpu/cpu_emulation.h b/BasiliskII/src/native_cpu/cpu_emulation.h deleted file mode 100644 index 822ee047..00000000 --- a/BasiliskII/src/native_cpu/cpu_emulation.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (native 68k version) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CPU_EMULATION_H -#define CPU_EMULATION_H - - -/* - * Memory system - */ - -// RAM and ROM pointers (allocated and set by main_*.cpp) -extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0 -extern uint8 *RAMBaseHost; // RAM base (host address space) -extern uint32 RAMSize; // Size of RAM - -extern uint32 ROMBaseMac; // ROM base (Mac address space) -extern uint8 *ROMBaseHost; // ROM base (host address space) -extern uint32 ROMSize; // Size of ROM - -// Mac memory access functions -static inline uint32 ReadMacInt32(uint32 addr) {return *(uint32 *)addr;} -static inline uint32 ReadMacInt16(uint32 addr) {return *(uint16 *)addr;} -static inline uint32 ReadMacInt8(uint32 addr) {return *(uint8 *)addr;} -static inline void WriteMacInt32(uint32 addr, uint32 l) {*(uint32 *)addr = l;} -static inline void WriteMacInt16(uint32 addr, uint32 w) {*(uint16 *)addr = w;} -static inline void WriteMacInt8(uint32 addr, uint32 b) {*(uint8 *)addr = b;} -static inline uint8 *Mac2HostAddr(uint32 addr) {return (uint8 *)addr;} -static inline uint32 Host2MacAddr(uint8 *addr) {return (uint32)addr;} -static inline void *Mac_memset(uint32 addr, int c, size_t n) {return memset(Mac2HostAddr(addr), c, n);} -static inline void *Mac2Host_memcpy(void *dest, uint32 src, size_t n) {return memcpy(dest, Mac2HostAddr(src), n);} -static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {return memcpy(Mac2HostAddr(dest), src, n);} -static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return memcpy(Mac2HostAddr(dest), Mac2HostAddr(src), n);} - - -/* - * 680x0 emulation - */ - -// 680x0 emulation functions -struct M68kRegisters; -extern void Start680x0(void); // Reset and start 680x0 -extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine -extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine - -// Interrupt functions -extern void TriggerInterrupt(void); // Trigger interrupt (InterruptFlag must be set first) -extern void TriggerNMI(void); // Trigger interrupt level 7 - -#endif diff --git a/BasiliskII/src/pict.c b/BasiliskII/src/pict.c deleted file mode 100644 index 715c8feb..00000000 --- a/BasiliskII/src/pict.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * pict.c - convert an image to PICT. - * - * Currently creates a bitmap PICT resource; vector graphics are not preserved. - * - * By Charles Srstka. - * - * Public Domain. Do with it as you wish. - * - */ - -/* - * PICT format: - * - * Size: 2 bytes - * Bounding Rect: 8 bytes - * - * This is followed by a series of opcodes. - * Each opcode is 1 byte long for a Version 1 PICT, or 2 bytes long for a Version 2 PICT. - * The ones we currently care about are: - * - * 0x0011 VersionOp: begins PICT version 2 - * 0x02ff Version: identifies PICT version 2 - * 0x0c00 HeaderOp: followed by 24 header bytes - * 4 bytes: 0xFFFFFFFF for regular v2 PICT or 0xFFFE0000 for extended v2 PICT - * 16 bytes: fixed-point bounding rectangle (or resolution, if an extended v2 PICT) - * 4 bytes: reserved - * - * 0x0001 Clip: set clipping region: followed by variable-sized region - * 0x001e DefHilite: set default highlight color - * 0x009b DirectBitsRgn: bitmap data - * pixMap: 50 bytes (PixMap) - * srcRect: 8 bytes (Rect) - * dstRect: 8 bytes (Rect) - * mode: 2 bytes (Mode) - * maskRgn: variable (Region) - * pixData: variable - * 0x00ff End of File - */ - -/* - * PixMap format: - * - * baseAddr: Ptr (4 bytes) - * rowBytes: Integer (2 bytes) - * bounds: Rect (8 bytes) - * pmVersion: Integer (2 bytes) - * packType: Integer (2 bytes) - * packSize: LongInt (4 bytes) - * hRes: Fixed (4 bytes) - * vRes: Fixed (4 bytes) - * pixelType: Integer (2 bytes) - * pixelSize: Integer (2 bytes) - * cmpCount: Integer (2 bytes) - * cmpSize: Integer (2 bytes) - * planeBytes: LongInt (4 bytes) - * pmTable: CTabHandle (4 bytes) - * pmReserved: LongInt (4 bytes) - */ - -#include -#include -#include -#include - -static ssize_t CompressUsingRLE(uint8_t *row, uint16_t uncmpLength, uint8_t *outBuf, size_t bufSize) -{ - int byteCountLength = 1 + (uncmpLength > 250); - - uint16_t cmpCursor = byteCountLength; - uint16_t cursor = 0; - - // enough to output the data uncompressed if we have to, plus the length bytes - size_t maxSize = byteCountLength + uncmpLength + (uncmpLength + 126) / 127; - - int outOfRoom = 0; - uint16_t cmpLength; - - if (row == NULL || outBuf == NULL || bufSize == 0) - return maxSize; - - while (cursor < uncmpLength) { - uint8_t byte = row[cursor++]; - uint8_t nextByte; - - if (cursor < uncmpLength && (nextByte = row[cursor]) == byte) { - int8_t matches = 1; - - while (++cursor < uncmpLength && matches < 127 && row[cursor] == byte) { - matches++; - } - - if(cmpCursor + 2 > bufSize) { - outOfRoom = 1; - break; - } - - outBuf[cmpCursor++] = -matches; - outBuf[cmpCursor++] = byte; - } else { - uint8_t literals = 0; - uint8_t i; - - while (cursor + literals + 1 < uncmpLength && literals < 127 && nextByte != (nextByte = row[cursor + literals + 1])) { - literals++; - } - - if(cmpCursor + 2 + literals > bufSize) { - outOfRoom = 1; - break; - } - - outBuf[cmpCursor++] = literals; - outBuf[cmpCursor++] = byte; - - for (i = 0; i < literals; i++) { - outBuf[cmpCursor++] = row[cursor++]; - } - } - } - - if(outOfRoom) { - // Trying to compress this just made it larger; just output the data uncompressed instead - - if(bufSize < maxSize) { - // sorry folks, don't have enough buffer - return -1; - } - - cursor = 0; - cmpCursor = byteCountLength; - - while (cursor < uncmpLength) { - uint8_t bytesToCopy = uncmpLength - cursor > 128 ? 128 : uncmpLength - cursor; - - outBuf[cmpCursor++] = bytesToCopy - 1; - memcpy(outBuf + cmpCursor, row + cursor, bytesToCopy); cmpCursor += bytesToCopy; cursor += bytesToCopy; - } - - cmpLength = cmpCursor - 1; - } - - cmpLength = cmpCursor - byteCountLength; - - if (byteCountLength == 2) { - outBuf[0] = cmpLength >> 8; - outBuf[1] = cmpLength & 0xff; - } else { - outBuf[0] = cmpLength; - } - - return cmpCursor; -} - -ssize_t ConvertRGBAToPICT(uint8_t *buf, unsigned long bufSize, uint8_t *rgbaPixels, uint16_t width, uint16_t height) -{ - unsigned long initialSize = (10 /* size + rect */ + - 6 /* initial opcodes */ + - 24 /* header */ + - 12 /* clip region */ + - 2 /* DefHilite */ + - 70 /* DirectBitsRgn - pixData - maskRgn */ + - 10 /* maskRgn */); - -#define RECT_SIZE 8 -#define REGION_SIZE 10 -#define FIXED_RECT_SIZE 16 - - char rect[RECT_SIZE] = {0, 0, 0, 0, height >> 8, height & 0xff, width >> 8, width & 0xff }; - char region[REGION_SIZE] = { 0x00, 0x0a, rect[0], rect[1], rect[2], rect[3], rect[4], rect[5], rect[6], rect[7] }; - char fixedRect[FIXED_RECT_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, width >> 8, width & 0xff, 0, 0, height >> 8, height & 0xff, 0, 0 }; - - uint32_t hDPI = htonl(0x00480000); // 72 dpi - uint32_t vDPI = hDPI; - - uint16_t bytesPerPixel = 4; // RGBA - uint16_t bytesPerRow = width * bytesPerPixel; - - unsigned long cursor = 2; // size bytes filled in at the end - - ssize_t cmpBufSize = CompressUsingRLE(NULL, bytesPerRow, NULL, 0); - uint8_t cmpBuf[cmpBufSize]; - - uint16_t i; - - if (buf == NULL || bufSize == 0) { - // Give an upper bound for the buffer size. - - return initialSize + height * cmpBufSize + 2; - } - - if (bufSize < initialSize) { - return -1; - } - - memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE; - - buf[cursor++] = 0x00; buf[cursor++] = 0x11; buf[cursor++] = 0x02; buf[cursor++] = 0xff; - - buf[cursor++] = 0x0c; buf[cursor++] = 0x00; - buf[cursor++] = 0xff; buf[cursor++] = 0xff; buf[cursor++] = 0xff; buf[cursor++] = 0xff; - memcpy(buf + cursor, fixedRect, FIXED_RECT_SIZE); cursor += FIXED_RECT_SIZE; - memset(buf + cursor, '\0', 4); cursor += 4; - - buf[cursor++] = 0x00; buf[cursor++] = 0x1e; - - buf[cursor++] = 0x00; buf[cursor++] = 0x01; - memcpy(buf + cursor, region, REGION_SIZE); cursor += REGION_SIZE; - - buf[cursor++] = 0x00; buf[cursor++] = 0x9b; - memset(buf + cursor, '\0', 4); cursor += 4; // I think this pointer isn't used - buf[cursor++] = (bytesPerRow >> 8) | 0x80; buf[cursor++] = bytesPerRow & 0xff; // rowBytes - memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE; //bounds - buf[cursor++] = 0x00; buf[cursor++] = 0x00; // pmVersion - buf[cursor++] = 0x00; buf[cursor++] = 0x04; // packType - buf[cursor++] = 0x00; buf[cursor++] = 0x00; buf[cursor++] = 0x00; buf[cursor++] = 0x00; // packSize is always 0 - memcpy(buf + cursor, &hDPI, 4); cursor += 4; // hRes - memcpy(buf + cursor, &vDPI, 4); cursor += 4; // vRes - buf[cursor++] = 0x00; buf[cursor++] = 0x10; // pixelType; direct device - buf[cursor++] = 0x00; buf[cursor++] = 0x20; // pixelSize; 32 bits per pixel - buf[cursor++] = bytesPerPixel >> 8; buf[cursor++] = bytesPerPixel & 0xff; // components per pixel - buf[cursor++] = 0x00; buf[cursor++] = 0x08; // 8 bits per component - memset(buf + cursor, '\0', 4); cursor += 4; // planeBytes isn't used - memset(buf + cursor, '\0', 4); cursor += 4; // don't think we need pmTable - memset(buf + cursor, '\0', 4); cursor += 4; // reserved - - memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE; - memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE; - buf[cursor++] = 0x00; buf[cursor++] = 0x00; // no transfer mode - memcpy(buf + cursor, region, REGION_SIZE); cursor += REGION_SIZE; - - for (i = 0; i < height; i++) { - uint8_t row[bytesPerRow]; - ssize_t cmpLength; - uint16_t j; - - for (j = 0; j < width; j++) { - row[j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel + 3]; - row[width + j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel]; - row[width * 2 + j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel + 1]; - row[width * 3 + j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel + 2]; - } - - cmpLength = CompressUsingRLE(row, bytesPerRow, cmpBuf, cmpBufSize); - - if (cmpLength < 0 || cursor + cmpLength > bufSize) - return -1; - - memcpy(buf + cursor, cmpBuf, cmpLength); cursor += cmpLength; - } - - // Fun fact: forgetting to put 0x00ff at the end of a PICT picture causes the entire - // Classic Mac OS to crash when it tries to read it! Don't ask me how I learned this. - if (cursor + 2 > bufSize) - return -1; - - buf[cursor++] = 0x00; buf[cursor++] = 0xff; - - if(cursor > UINT16_MAX) { - buf[0] = buf[1] = 0xff; - } else { - buf[0] = cursor >> 8; - buf[1] = cursor & 0xff; - } - - return cursor; -} diff --git a/BasiliskII/src/powerrom_cpu/cpu_emulation.h b/BasiliskII/src/powerrom_cpu/cpu_emulation.h deleted file mode 100644 index dbddfbbc..00000000 --- a/BasiliskII/src/powerrom_cpu/cpu_emulation.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (Apple PowerMac ROM 680x0 emulator version (BeOS/PPC)) - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CPU_EMULATION_H -#define CPU_EMULATION_H - - -/* - * Memory system - */ - -// RAM and ROM pointers (allocated and set by main_*.cpp) -extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0 -extern uint8 *RAMBaseHost; // RAM base (host address space) -extern uint32 RAMSize; // Size of RAM - -extern uint32 ROMBaseMac; // ROM base (Mac address space) -extern uint8 *ROMBaseHost; // ROM base (host address space) -extern uint32 ROMSize; // Size of ROM - -// Mac memory access functions -static inline uint32 ReadMacInt32(uint32 addr) {return ntohl(*(uint32 *)addr);} -static inline uint32 ReadMacInt16(uint32 addr) {return ntohs(*(uint16 *)addr);} -static inline uint32 ReadMacInt8(uint32 addr) {return *(uint8 *)addr;} -static inline void WriteMacInt32(uint32 addr, uint32 l) {*(uint32 *)addr = htonl(l);} -static inline void WriteMacInt16(uint32 addr, uint32 w) {*(uint16 *)addr = htons(w);} -static inline void WriteMacInt8(uint32 addr, uint32 b) {*(uint8 *)addr = b;} -static inline uint8 *Mac2HostAddr(uint32 addr) {return (uint8 *)addr;} -static inline uint32 Host2MacAddr(uint8 *addr) {return (uint32)addr;} - - -/* - * 680x0 emulation - */ - -// Initialization -extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation -extern void Exit680x0(void); - -// 680x0 emulation functions -struct M68kRegisters; -extern void Start680x0(void); // Reset and start 680x0 -extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine -extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine - -// Interrupt functions -extern void TriggerInterrupt(void); // Trigger interrupt (InterruptFlag must be set first) - -#endif diff --git a/BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp b/BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp deleted file mode 100644 index d91b9049..00000000 --- a/BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp +++ /dev/null @@ -1,1367 +0,0 @@ -/* - * powerrom_cpu.cpp - Using the 680x0 emulator in PowerMac ROMs for Basilisk II - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "emul_op.h" -#include "prefs.h" -#include "timer.h" -#include "user_strings.h" - -#include "sheep_driver.h" - -#define DEBUG 0 -#include "debug.h" - -// Save FP regs in Execute68k()? -#define SAVE_FP_EXEC_68K 0 - - -// Constants -const char ROM_FILE_NAME[] = "PowerROM"; -const char KERNEL_AREA_NAME[] = "Macintosh Kernel Data"; -const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache"; - -const uint32 ROM_BASE = 0x40800000; // Base address of ROM -const uint32 ROM_SIZE = 0x00400000; // Size of ROM file -const uint32 ROM_AREA_SIZE = 0x00500000; // Size of ROM area - -const uint32 DR_CACHE_BASE = 0x69000000; // Address of DR cache -const uint32 DR_CACHE_SIZE = 0x80000; // Size of DR Cache - -const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack - -// PowerPC opcodes -const uint32 POWERPC_NOP = 0x60000000; -const uint32 POWERPC_ILLEGAL = 0x00000000; -const uint32 POWERPC_BLR = 0x4e800020; -const uint32 POWERPC_BCTR = 0x4e800420; - -// Extra Low Memory Globals -#define MODE_68K 0 // 68k emulator active -#define MODE_EMUL_OP 1 // Within EMUL_OP routine - -#define XLM_RESET_STACK 0x2800 // Reset stack pointer -#define XLM_KERNEL_DATA 0x2804 // Pointer to Kernel Data -#define XLM_TOC 0x2808 // TOC pointer of emulator -#define XLM_RUN_MODE 0x2810 // Current run mode, see enum above -#define XLM_68K_R25 0x2814 // Contents of the 68k emulator's r25 (which contains the interrupt level), saved upon entering EMUL_OP mode, used by Execute68k() and the USR1 signal handler -#define XLM_IRQ_NEST 0x2818 // Interrupt disable nesting counter (>0: disabled) -#define XLM_PVR 0x281c // Theoretical PVR -#define XLM_EMUL_RETURN_PROC 0x2824 // Pointer to EMUL_RETURN routine -#define XLM_EXEC_RETURN_PROC 0x2828 // Pointer to EXEC_RETURN routine -#define XLM_EMUL_OP_PROC 0x282c // Pointer to EMUL_OP routine -#define XLM_EMUL_RETURN_STACK 0x2830 // Stack pointer for EMUL_RETURN - - -// RAM and ROM pointers -uint32 RAMBaseMac; // RAM base (Mac address space) -uint8 *RAMBaseHost; // RAM base (host address space) -uint32 RAMSize; // Size of RAM -uint32 ROMBaseMac; // ROM base (Mac address space) -uint8 *ROMBaseHost; // ROM base (host address space) -uint32 ROMSize; // Size of ROM - - -// Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - - -// Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - - -// Exceptions -class file_open_error {}; -class file_read_error {}; -class rom_size_error {}; - - -// Global variables -static void *TOC; // TOC pointer -static uint32 PVR; // Theoretical PVR -static int64 CPUClockSpeed; // Processor clock speed (Hz) -static int64 BusClockSpeed; // Bus clock speed (Hz) -static system_info SysInfo; // System information - -static area_id kernel_area = -1; // Kernel Data area ID -static KernelData *kernel_data = NULL; // Pointer to Kernel Data -static uint32 KernelDataAddr; // Address of Kernel Data -static EmulatorData *emulator_data = NULL; -static area_id dr_cache_area; // DR Cache area ID -static uint32 DRCacheAddr; // Address of DR Cache - -static struct sigaction sigusr1_action; // Interrupt signal (of emulator thread) -static bool ReadyForSignals = false; // Flag: emul_thread ready to receive signals - - -// Prototypes -static void sigusr1_handler(int sig, void *arg, vregs *r); - -// From main_beos.cpp -extern int sheep_fd; // fd of sheep driver -extern thread_id emul_thread; // Emulator thread - - -/* - * Load ROM file (upper 3MB) - * - * file_open_error: Cannot open ROM file (nor use built-in ROM) - * file_read_error: Cannot read ROM file - */ - -// Decode LZSS data -static void decode_lzss(const uint8 *src, uint8 *dest, int size) -{ - char dict[0x1000]; - int run_mask = 0, dict_idx = 0xfee; - for (;;) { - if (run_mask < 0x100) { - // Start new run - if (--size < 0) - break; - run_mask = *src++ | 0xff00; - } - bool bit = run_mask & 1; - run_mask >>= 1; - if (bit) { - // Verbatim copy - if (--size < 0) - break; - int c = *src++; - dict[dict_idx++] = c; - *dest++ = c; - dict_idx &= 0xfff; - } else { - // Copy from dictionary - if (--size < 0) - break; - int idx = *src++; - if (--size < 0) - break; - int cnt = *src++; - idx |= (cnt << 4) & 0xf00; - cnt = (cnt & 0x0f) + 3; - while (cnt--) { - char c = dict[idx++]; - dict[dict_idx++] = c; - *dest++ = c; - idx &= 0xfff; - dict_idx &= 0xfff; - } - } - } -} - -static void load_rom(void) -{ - // Get rom file path from preferences - const char *rom_path = PrefsFindString("powerrom"); - - // Try to open ROM file - BFile file(rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY); - if (file.InitCheck() != B_NO_ERROR) { - - // Failed, then ask sheep driver for ROM - uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work - ssize_t actual = read(sheep_fd, (void *)rom, ROM_SIZE); - if (actual == ROM_SIZE) { - // Copy upper 3MB - memcpy((void *)(ROM_BASE + 0x100000), rom + 0x100000, ROM_SIZE - 0x100000); - delete[] rom; - return; - } else - throw file_open_error(); - } - - printf(GetString(STR_READING_ROM_FILE)); - - // Get file size - off_t rom_size = 0; - file.GetSize(&rom_size); - - uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work - ssize_t actual = file.Read((void *)rom, ROM_SIZE); - if (actual == ROM_SIZE) { - // Plain ROM image, copy upper 3MB - memcpy((void *)(ROM_BASE + 0x100000), rom + 0x100000, ROM_SIZE - 0x100000); - delete[] rom; - } else { - if (strncmp((char *)rom, "", 11) == 0) { - // CHRP compressed ROM image - D(bug("CHRP ROM image\n")); - uint32 lzss_offset, lzss_size; - - char *s = strstr((char *)rom, "constant lzss-offset"); - if (s == NULL) - throw rom_size_error(); - s -= 7; - if (sscanf(s, "%06lx", &lzss_offset) != 1) - throw rom_size_error(); - s = strstr((char *)rom, "constant lzss-size"); - if (s == NULL) - throw rom_size_error(); - s -= 7; - if (sscanf(s, "%06lx", &lzss_size) != 1) - throw rom_size_error(); - D(bug("Offset of compressed data: %08lx\n", lzss_offset)); - D(bug("Size of compressed data: %08lx\n", lzss_size)); - - D(bug("Uncompressing ROM...\n")); - uint8 *decoded = new uint8[ROM_SIZE]; - decode_lzss(rom + lzss_offset, decoded, lzss_size); - memcpy((void *)(ROM_BASE + 0x100000), decoded + 0x100000, ROM_SIZE - 0x100000); - delete[] decoded; - delete[] rom; - } else if (rom_size != 4*1024*1024) - throw rom_size_error(); - else - throw file_read_error(); - } -} - - -/* - * Patch PowerMac ROM - */ - -// ROM type -enum { - ROMTYPE_TNT, - ROMTYPE_ALCHEMY, - ROMTYPE_ZANZIBAR, - ROMTYPE_GAZELLE, - ROMTYPE_NEWWORLD -}; -static int ROMType; - -// Nanokernel boot routine patches -static bool patch_nanokernel_boot(void) -{ - uint32 *lp; - int i; - - // Patch ConfigInfo - lp = (uint32 *)(ROM_BASE + 0x30d000); - lp[0x9c >> 2] = KernelDataAddr; // LA_InfoRecord - lp[0xa0 >> 2] = KernelDataAddr; // LA_KernelData - lp[0xa4 >> 2] = KernelDataAddr + 0x1000;// LA_EmulatorData - lp[0xa8 >> 2] = ROM_BASE + 0x480000; // LA_DispatchTable - lp[0xac >> 2] = ROM_BASE + 0x460000; // LA_EmulatorCode - lp[0x360 >> 2] = 0; // Physical RAM base (? on NewWorld ROM, this contains -1) - lp[0xfd8 >> 2] = ROM_BASE + 0x2a; // 68k reset vector - - // Skip SR/BAT/SDR init - if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_NEWWORLD) { - lp = (uint32 *)(ROM_BASE + 0x310000); - *lp++ = POWERPC_NOP; - *lp = 0x38000000; - } - static const uint32 sr_init_loc[] = {0x3101b0, 0x3101b0, 0x3101b0, 0x3101ec, 0x310200}; - lp = (uint32 *)(ROM_BASE + 0x310008); - *lp = 0x48000000 | (sr_init_loc[ROMType] - 8) & 0xffff; // b ROM_BASE+0x3101b0 - lp = (uint32 *)(ROM_BASE + sr_init_loc[ROMType]); - *lp++ = 0x80200000 + XLM_KERNEL_DATA; // lwz r1,(pointer to Kernel Data) - *lp++ = 0x3da0dead; // lis r13,0xdead (start of kernel memory) - *lp++ = 0x3dc00010; // lis r14,0x0010 (size of page table) - *lp = 0x3de00010; // lis r15,0x0010 (size of kernel memory) - - // Don't read PVR - static const uint32 pvr_loc[] = {0x3103b0, 0x3103b4, 0x3103b4, 0x310400, 0x310438}; - lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]); - *lp = 0x81800000 + XLM_PVR; // lwz r12,(theoretical PVR) - - // Set CPU specific data (even if ROM doesn't have support for that CPU) - lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]); - if (ntohl(lp[6]) != 0x2c0c0001) - return false; - uint32 ofs = lp[7] & 0xffff; - lp[8] = (lp[8] & 0xffff) | 0x48000000; // beq -> b - uint32 loc = (lp[8] & 0xffff) + (uint32)(lp+8) - ROM_BASE; - lp = (uint32 *)(ROM_BASE + ofs + 0x310000); - switch (PVR >> 16) { - case 1: // 601 - lp[0] = 0x1000; // Page size - lp[1] = 0x8000; // Data cache size - lp[2] = 0x8000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00010040; // Unified caches/Inst cache line size - lp[5] = 0x00400020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc - lp[8] = 0x01000002; // TLB total size/TLB assoc - break; - case 3: // 603 - lp[0] = 0x1000; // Page size - lp[1] = 0x2000; // Data cache size - lp[2] = 0x2000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00020002; // Inst cache assoc/Data cache assoc - lp[8] = 0x00400002; // TLB total size/TLB assoc - break; - case 4: // 604 - lp[0] = 0x1000; // Page size - lp[1] = 0x4000; // Data cache size - lp[2] = 0x4000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00040004; // Inst cache assoc/Data cache assoc - lp[8] = 0x00800002; // TLB total size/TLB assoc - break; -// case 5: // 740? - case 6: // 603e - case 7: // 603ev - lp[0] = 0x1000; // Page size - lp[1] = 0x4000; // Data cache size - lp[2] = 0x4000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00040004; // Inst cache assoc/Data cache assoc - lp[8] = 0x00400002; // TLB total size/TLB assoc - break; - case 8: // 750 - lp[0] = 0x1000; // Page size - lp[1] = 0x8000; // Data cache size - lp[2] = 0x8000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc - lp[8] = 0x00800002; // TLB total size/TLB assoc - break; - case 9: // 604e - case 10: // 604ev5 - lp[0] = 0x1000; // Page size - lp[1] = 0x8000; // Data cache size - lp[2] = 0x8000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00040004; // Inst cache assoc/Data cache assoc - lp[8] = 0x00800002; // TLB total size/TLB assoc - break; -// case 11: // X704? - case 12: // ??? - lp[0] = 0x1000; // Page size - lp[1] = 0x8000; // Data cache size - lp[2] = 0x8000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc - lp[8] = 0x00800002; // TLB total size/TLB assoc - break; - case 13: // ??? - lp[0] = 0x1000; // Page size - lp[1] = 0x8000; // Data cache size - lp[2] = 0x8000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00000020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc - lp[8] = 0x01000004; // TLB total size/TLB assoc - break; -// case 50: // 821 -// case 80: // 860 - case 96: // ??? - lp[0] = 0x1000; // Page size - lp[1] = 0x8000; // Data cache size - lp[2] = 0x8000; // Inst cache size - lp[3] = 0x00200020; // Coherency block size/Reservation granule size - lp[4] = 0x00010020; // Unified caches/Inst cache line size - lp[5] = 0x00200020; // Data cache line size/Data cache block size touch - lp[6] = 0x00200020; // Inst cache block size/Data cache block size - lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc - lp[8] = 0x00800004; // TLB total size/TLB assoc - break; - default: - printf("WARNING: Unknown CPU type\n"); - break; - } - - // Don't set SPRG3, don't test MQ - lp = (uint32 *)(ROM_BASE + loc + 0x20); - *lp++ = POWERPC_NOP; - lp++; - *lp++ = POWERPC_NOP; - lp++; - *lp = POWERPC_NOP; - - // Don't read MSR - lp = (uint32 *)(ROM_BASE + loc + 0x40); - *lp = 0x39c00000; // li r14,0 - - // Don't write to DEC - lp = (uint32 *)(ROM_BASE + loc + 0x70); - *lp++ = POWERPC_NOP; - loc = (lp[0] & 0xffff) + (uint32)lp - ROM_BASE; - - // Don't set SPRG3 - lp = (uint32 *)(ROM_BASE + loc + 0x2c); - *lp = POWERPC_NOP; - - // Don't read PVR - static const uint32 pvr_ofs[] = {0x138, 0x138, 0x138, 0x140, 0x148}; - lp = (uint32 *)(ROM_BASE + loc + pvr_ofs[ROMType]); - *lp = 0x82e00000 + XLM_PVR; // lwz r23,(theoretical PVR) - lp = (uint32 *)(ROM_BASE + loc + 0x170); - if (*lp == 0x7eff42a6) // NewWorld ROM - *lp = 0x82e00000 + XLM_PVR; // lwz r23,(theoretical PVR) - lp = (uint32 *)(ROM_BASE + 0x313134); - if (*lp == 0x7e5f42a6) - *lp = 0x82400000 + XLM_PVR; // lwz r18,(theoretical PVR) - lp = (uint32 *)(ROM_BASE + 0x3131f4); - if (*lp == 0x7e5f42a6) // NewWorld ROM - *lp = 0x82400000 + XLM_PVR; // lwz r18,(theoretical PVR) - - // Don't read SDR1 - static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c}; - lp = (uint32 *)(ROM_BASE + loc + sdr1_ofs[ROMType]); - *lp++ = 0x3d00dead; // lis r8,0xdead (pointer to page table) - *lp++ = 0x3ec0001f; // lis r22,0x001f (size of page table) - *lp = POWERPC_NOP; - - // Don't clear page table - static const uint32 pgtb_ofs[] = {0x198, 0x198, 0x198, 0x1a0, 0x1c4}; - lp = (uint32 *)(ROM_BASE + loc + pgtb_ofs[ROMType]); - *lp = POWERPC_NOP; - - // Don't invalidate TLB - static const uint32 tlb_ofs[] = {0x1a0, 0x1a0, 0x1a0, 0x1a8, 0x1cc}; - lp = (uint32 *)(ROM_BASE + loc + tlb_ofs[ROMType]); - *lp = POWERPC_NOP; - - // Don't create RAM descriptor table - static const uint32 desc_ofs[] = {0x350, 0x350, 0x350, 0x358, 0x37c}; - lp = (uint32 *)(ROM_BASE + loc + desc_ofs[ROMType]); - *lp = POWERPC_NOP; - - // Don't load SRs and BATs - static const uint32 sr_ofs[] = {0x3d8, 0x3d8, 0x3d8, 0x3e0, 0x404}; - lp = (uint32 *)(ROM_BASE + loc + sr_ofs[ROMType]); - *lp = POWERPC_NOP; - - // Don't mess with SRs - static const uint32 sr2_ofs[] = {0x312118, 0x312118, 0x312118, 0x312118, 0x3121b4}; - lp = (uint32 *)(ROM_BASE + sr2_ofs[ROMType]); - *lp = POWERPC_BLR; - - // Don't check performance monitor - static const uint32 pm_ofs[] = {0x313148, 0x313148, 0x313148, 0x313148, 0x313218}; - lp = (uint32 *)(ROM_BASE + pm_ofs[ROMType]); - while (*lp != 0x7e58eba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e78eaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e59eba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e79eaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e5aeba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e7aeaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e5beba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e7beaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e5feba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e7feaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e5ceba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e7ceaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e5deba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e7deaa6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e5eeba6) lp++; - *lp++ = POWERPC_NOP; - while (*lp != 0x7e7eeaa6) lp++; - *lp++ = POWERPC_NOP; - - // Jump to 68k emulator - static const uint32 jump68k_ofs[] = {0x40c, 0x40c, 0x40c, 0x414, 0x438}; - lp = (uint32 *)(ROM_BASE + loc + jump68k_ofs[ROMType]); - *lp++ = 0x80610634; // lwz r3,0x0634(r1) (pointer to Emulator Data) - *lp++ = 0x8081119c; // lwz r4,0x119c(r1) (pointer to opcode table) - *lp++ = 0x80011184; // lwz r0,0x1184(r1) (pointer to emulator entry) - *lp++ = 0x7c0903a6; // mtctr r0 - *lp = POWERPC_BCTR; - return true; -} - -// 68k emulator patches -static bool patch_68k_emul(void) -{ - uint32 *lp; - uint32 base; - - // Overwrite twi instructions - static const uint32 twi_loc[] = {0x36e680, 0x36e6c0, 0x36e6c0, 0x36e6c0, 0x36e740}; - base = twi_loc[ROMType]; - lp = (uint32 *)(ROM_BASE + base); - *lp++ = 0x48000000 + 0x36f900 - base; // b 0x36f900 (Emulator start) - *lp++ = POWERPC_ILLEGAL; - *lp++ = 0x48000000 + 0x36fb00 - base - 8; // b 0x36fb00 (Reset opcode) - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - *lp++ = POWERPC_ILLEGAL; - - // Set reset stack pointer - lp = (uint32 *)(ROM_BASE + base + 0xf0); - *lp++ = 0x80200000 + XLM_RESET_STACK; // lwz r1,XLM_RESET_STACK - - // Install EXEC_RETURN and EMUL_OP opcodes - lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EXEC_RETURN << 3)); - *lp++ = 0x80000000 + XLM_EXEC_RETURN_PROC; // lwz r0,XLM_EXEC_RETURN_PROC - *lp++ = 0x4bfb6ffc; // b 0x36f800 - for (int i=0; i> 16); // lis r0,xxx - *lp++ = 0x60000000 + ((ROM_BASE + 0x46d0a4) & 0xffff); // ori r0,r0,xxx - *lp++ = 0x7c0903a6; // mtctr r0 - *lp = POWERPC_BCTR; // bctr - return true; -} - -// Nanokernel patches -static bool patch_nanokernel(void) -{ - uint32 *lp; - - // Patch 68k emulator trap routine - lp = (uint32 *)(ROM_BASE + 0x312994); // Always restore FPU state - while (*lp != 0x39260040) lp++; - lp--; - *lp = 0x48000441; // bl 0x00312dd4 - lp = (uint32 *)(ROM_BASE + 0x312dd8); // Don't modify MSR to turn on FPU - while (*lp != 0x810600e4) lp++; - lp--; - *lp++ = POWERPC_NOP; - lp += 2; - *lp++ = POWERPC_NOP; - lp++; - *lp++ = POWERPC_NOP; - *lp++ = POWERPC_NOP; - *lp = POWERPC_NOP; - - // Patch trap return routine - lp = (uint32 *)(ROM_BASE + 0x312c20); - while (*lp != 0x7d5a03a6) lp++; - *lp++ = 0x7d4903a6; // mtctr r10 - *lp++ = 0x7daff120; // mtcr r13 - *lp++ = 0x48000000 + 0x8000 - ((uint32)lp & 0xffff); // b ROM_BASE+0x318000 - uint32 xlp = (uint32)lp & 0xffff; - - lp = (uint32 *)(ROM_BASE + 0x312c50); // Replace rfi - while (*lp != 0x4c000064) lp++; - *lp = POWERPC_BCTR; - - lp = (uint32 *)(ROM_BASE + 0x318000); - *lp++ = 0x81400000 + XLM_IRQ_NEST; // lwz r10,XLM_IRQ_NEST - *lp++ = 0x394affff; // subi r10,r10,1 - *lp++ = 0x91400000 + XLM_IRQ_NEST; // stw r10,XLM_IRQ_NEST - *lp = 0x48000000 + ((xlp - 0x800c) & 0x03fffffc); // b ROM_BASE+0x312c2c - return true; -} - -static bool patch_rom(void) -{ - // Detect ROM type - if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot TNT", 8)) - ROMType = ROMTYPE_TNT; - else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Alchemy", 12)) - ROMType = ROMTYPE_ALCHEMY; - else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Zanzibar", 13)) - ROMType = ROMTYPE_ZANZIBAR; - else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gazelle", 12)) - ROMType = ROMTYPE_GAZELLE; - else if (!memcmp((void *)(ROM_BASE + 0x30d064), "NewWorld", 8)) - ROMType = ROMTYPE_NEWWORLD; - else - return false; - - // Apply patches - if (!patch_nanokernel_boot()) return false; - if (!patch_68k_emul()) return false; - if (!patch_nanokernel()) return false; - - // Copy 68k emulator to 2MB boundary - memcpy((void *)(ROM_BASE + ROM_SIZE), (void *)(ROM_BASE + ROM_SIZE - 0x100000), 0x100000); - return true; -} - - -/* - * Initialize 680x0 emulation - */ - -static asm void *get_toc(void) -{ - mr r3,r2 - blr -} - -bool Init680x0(void) -{ - char str[256]; - - // Mac address space = host address space - RAMBaseMac = (uint32)RAMBaseHost; - ROMBaseMac = (uint32)ROMBaseHost; - - // Get TOC pointer - TOC = get_toc(); - - // Get system info - get_system_info(&SysInfo); - switch (SysInfo.cpu_type) { - case B_CPU_PPC_601: - PVR = 0x00010000; - break; - case B_CPU_PPC_603: - PVR = 0x00030000; - break; - case B_CPU_PPC_603e: - PVR = 0x00060000; - break; - case B_CPU_PPC_604: - PVR = 0x00040000; - break; - case B_CPU_PPC_604e: - PVR = 0x00090000; - break; - default: - PVR = 0x00040000; - break; - } - CPUClockSpeed = SysInfo.cpu_clock_speed; - BusClockSpeed = SysInfo.bus_clock_speed; - - // Delete old areas - area_id old_kernel_area = find_area(KERNEL_AREA_NAME); - if (old_kernel_area > 0) - delete_area(old_kernel_area); - area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME); - if (old_dr_cache_area > 0) - delete_area(old_dr_cache_area); - - // Create area for Kernel Data - kernel_data = (KernelData *)0x68ffe000; - kernel_area = create_area(KERNEL_AREA_NAME, &kernel_data, B_EXACT_ADDRESS, 0x2000, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (kernel_area < 0) { - sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area), kernel_area); - ErrorAlert(str); - return false; - } - emulator_data = &kernel_data->ed; - KernelDataAddr = (uint32)kernel_data; - D(bug("Kernel Data area %ld at %p, Emulator Data at %p\n", kernel_area, kernel_data, emulator_data)); - - // Load PowerMac ROM (upper 3MB) - try { - load_rom(); - } catch (file_open_error) { - ErrorAlert(STR_NO_ROM_FILE_ERR); - return false; - } catch (file_read_error) { - ErrorAlert(STR_ROM_FILE_READ_ERR); - return false; - } catch (rom_size_error) { - ErrorAlert(STR_ROM_SIZE_ERR); - return false; - } - - // Install ROM patches - if (!patch_rom()) { - ErrorAlert("Unsupported PowerMac ROM version"); - return false; - } - - // Create area for DR Cache - DRCacheAddr = DR_CACHE_BASE; - dr_cache_area = create_area(DR_CACHE_AREA_NAME, (void **)&DRCacheAddr, B_EXACT_ADDRESS, DR_CACHE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (dr_cache_area < 0) { - sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_cache_area), dr_cache_area); - ErrorAlert(str); - return false; - } - D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr)); - - // Initialize Kernel Data - memset(kernel_data, 0, sizeof(KernelData)); - if (ROMType == ROMTYPE_NEWWORLD) { - kernel_data->v[0xc20 >> 2] = RAMSize; - kernel_data->v[0xc24 >> 2] = RAMSize; - kernel_data->v[0xc30 >> 2] = RAMSize; - kernel_data->v[0xc34 >> 2] = RAMSize; - kernel_data->v[0xc38 >> 2] = 0x00010020; - kernel_data->v[0xc3c >> 2] = 0x00200001; - kernel_data->v[0xc40 >> 2] = 0x00010000; - kernel_data->v[0xc50 >> 2] = RAMBaseMac; - kernel_data->v[0xc54 >> 2] = RAMSize; - kernel_data->v[0xf60 >> 2] = PVR; - kernel_data->v[0xf64 >> 2] = CPUClockSpeed; - kernel_data->v[0xf68 >> 2] = BusClockSpeed; - kernel_data->v[0xf6c >> 2] = CPUClockSpeed; - } else { - kernel_data->v[0xc80 >> 2] = RAMSize; - kernel_data->v[0xc84 >> 2] = RAMSize; - kernel_data->v[0xc90 >> 2] = RAMSize; - kernel_data->v[0xc94 >> 2] = RAMSize; - kernel_data->v[0xc98 >> 2] = 0x00010020; - kernel_data->v[0xc9c >> 2] = 0x00200001; - kernel_data->v[0xca0 >> 2] = 0x00010000; - kernel_data->v[0xcb0 >> 2] = RAMBaseMac; - kernel_data->v[0xcb4 >> 2] = RAMSize; - kernel_data->v[0xf80 >> 2] = PVR; - kernel_data->v[0xf84 >> 2] = CPUClockSpeed; - kernel_data->v[0xf88 >> 2] = BusClockSpeed; - kernel_data->v[0xf8c >> 2] = CPUClockSpeed; - } - - // Initialize extra low memory - memset((void *)0x2000, 0, 0x1000); - *(uint32 *)XLM_RESET_STACK = 0x2000; // Reset stack pointer - *(KernelData **)XLM_KERNEL_DATA = kernel_data;// For trap replacement routines - *(void **)XLM_TOC = TOC; // TOC pointer of emulator - *(uint32 *)XLM_PVR = PVR; // Theoretical PVR - - // Clear caches (as we loaded and patched code) - clear_caches((void *)ROM_BASE, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); - return true; -} - - -/* - * Deinitialize 680x0 emulation - */ - -void Exit680x0(void) -{ - // Delete DR Cache area - if (dr_cache_area >= 0) - delete_area(dr_cache_area); - - // Delete Kernel Data area - if (kernel_area >= 0) - delete_area(kernel_area); -} - - -/* - * Quit emulator (must only be called from main thread) - */ - -asm void QuitEmulator(void) -{ - lwz r0,XLM_EMUL_RETURN_PROC - mtlr r0 - blr -} - - -/* - * Reset and start 680x0 emulation - */ - -static asm void jump_to_rom(register uint32 entry) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - mfcr r0 - stw r0,4(r1) - stwu r1,-(56+19*4+18*8)(r1) - - // Save PowerPC registers - stmw r13,56(r1) - stfd f14,56+19*4+0*8(r1) - stfd f15,56+19*4+1*8(r1) - stfd f16,56+19*4+2*8(r1) - stfd f17,56+19*4+3*8(r1) - stfd f18,56+19*4+4*8(r1) - stfd f19,56+19*4+5*8(r1) - stfd f20,56+19*4+6*8(r1) - stfd f21,56+19*4+7*8(r1) - stfd f22,56+19*4+8*8(r1) - stfd f23,56+19*4+9*8(r1) - stfd f24,56+19*4+10*8(r1) - stfd f25,56+19*4+11*8(r1) - stfd f26,56+19*4+12*8(r1) - stfd f27,56+19*4+13*8(r1) - stfd f28,56+19*4+14*8(r1) - stfd f29,56+19*4+15*8(r1) - stfd f30,56+19*4+16*8(r1) - stfd f31,56+19*4+17*8(r1) - - // Move entry address to ctr, get pointer to Emulator Data - mtctr r3 - lwz r3,emulator_data(r2) - - // Skip over EMUL_RETURN routine and get its address - bl @1 - - - /* - * EMUL_RETURN: Returned from emulator - */ - - // Restore PowerPC registers - lwz r1,XLM_EMUL_RETURN_STACK - lwz r2,XLM_TOC - lmw r13,56(r1) - lfd f14,56+19*4+0*8(r1) - lfd f15,56+19*4+1*8(r1) - lfd f16,56+19*4+2*8(r1) - lfd f17,56+19*4+3*8(r1) - lfd f18,56+19*4+4*8(r1) - lfd f19,56+19*4+5*8(r1) - lfd f20,56+19*4+6*8(r1) - lfd f21,56+19*4+7*8(r1) - lfd f22,56+19*4+8*8(r1) - lfd f23,56+19*4+9*8(r1) - lfd f24,56+19*4+10*8(r1) - lfd f25,56+19*4+11*8(r1) - lfd f26,56+19*4+12*8(r1) - lfd f27,56+19*4+13*8(r1) - lfd f28,56+19*4+14*8(r1) - lfd f29,56+19*4+15*8(r1) - lfd f30,56+19*4+16*8(r1) - lfd f31,56+19*4+17*8(r1) - - // Exiting from 68k emulator - li r0,1 - stw r0,XLM_IRQ_NEST - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE - - // Return to caller of jump_to_rom() - lwz r0,56+19*4+18*8+8(r1) - mtlr r0 - lwz r0,56+19*4+18*8+4(r1) - mtcrf 0xff,r0 - addi r1,r1,56+19*4+18*8 - blr - - - // Save address of EMUL_RETURN routine for 68k emulator patch -@1 mflr r0 - stw r0,XLM_EMUL_RETURN_PROC - - // Skip over EXEC_RETURN routine and get its address - bl @2 - - - /* - * EXEC_RETURN: Returned from 68k routine executed with Execute68k() - */ - - // Save r25 (contains current 68k interrupt level) - stw r25,XLM_68K_R25 - - // Reentering EMUL_OP mode - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE - - // Save 68k registers - lwz r4,56+19*4+18*8+12(r1) - stw r8,M68kRegisters.d[0](r4) - stw r9,M68kRegisters.d[1](r4) - stw r10,M68kRegisters.d[2](r4) - stw r11,M68kRegisters.d[3](r4) - stw r12,M68kRegisters.d[4](r4) - stw r13,M68kRegisters.d[5](r4) - stw r14,M68kRegisters.d[6](r4) - stw r15,M68kRegisters.d[7](r4) - stw r16,M68kRegisters.a[0](r4) - stw r17,M68kRegisters.a[1](r4) - stw r18,M68kRegisters.a[2](r4) - stw r19,M68kRegisters.a[3](r4) - stw r20,M68kRegisters.a[4](r4) - stw r21,M68kRegisters.a[5](r4) - stw r22,M68kRegisters.a[6](r4) - - // Restore PowerPC registers - lmw r13,56(r1) -#if SAVE_FP_EXEC_68K - lfd f14,56+19*4+0*8(r1) - lfd f15,56+19*4+1*8(r1) - lfd f16,56+19*4+2*8(r1) - lfd f17,56+19*4+3*8(r1) - lfd f18,56+19*4+4*8(r1) - lfd f19,56+19*4+5*8(r1) - lfd f20,56+19*4+6*8(r1) - lfd f21,56+19*4+7*8(r1) - lfd f22,56+19*4+8*8(r1) - lfd f23,56+19*4+9*8(r1) - lfd f24,56+19*4+10*8(r1) - lfd f25,56+19*4+11*8(r1) - lfd f26,56+19*4+12*8(r1) - lfd f27,56+19*4+13*8(r1) - lfd f28,56+19*4+14*8(r1) - lfd f29,56+19*4+15*8(r1) - lfd f30,56+19*4+16*8(r1) - lfd f31,56+19*4+17*8(r1) -#endif - - // Return to caller - lwz r0,56+19*4+18*8+8(r1) - mtlr r0 - addi r1,r1,56+19*4+18*8 - blr - - - // Stave address of EXEC_RETURN routine for 68k emulator patch -@2 mflr r0 - stw r0,XLM_EXEC_RETURN_PROC - - // Skip over EMUL_OP routine and get its address - bl @3 - - - /* - * EMUL_OP: Execute native routine, selector in r5 (my own private mode switch) - * - * 68k registers are stored in a M68kRegisters struct on the stack - * which the native routine may read and modify - */ - - // Save r25 (contains current 68k interrupt level) - stw r25,XLM_68K_R25 - - // Entering EMUL_OP mode within 68k emulator - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE - - // Create PowerPC stack frame, reserve space for M68kRegisters - mr r3,r1 - subi r1,r1,56 // Fake "caller" frame - rlwinm r1,r1,0,0,29 // Align stack - - mfcr r0 - rlwinm r0,r0,0,11,8 - stw r0,4(r1) - mfxer r0 - stw r0,16(r1) - stw r2,12(r1) - stwu r1,-(56+16*4+15*8)(r1) - lwz r2,XLM_TOC - - // Save 68k registers - stw r8,56+M68kRegisters.d[0](r1) - stw r9,56+M68kRegisters.d[1](r1) - stw r10,56+M68kRegisters.d[2](r1) - stw r11,56+M68kRegisters.d[3](r1) - stw r12,56+M68kRegisters.d[4](r1) - stw r13,56+M68kRegisters.d[5](r1) - stw r14,56+M68kRegisters.d[6](r1) - stw r15,56+M68kRegisters.d[7](r1) - stw r16,56+M68kRegisters.a[0](r1) - stw r17,56+M68kRegisters.a[1](r1) - stw r18,56+M68kRegisters.a[2](r1) - stw r19,56+M68kRegisters.a[3](r1) - stw r20,56+M68kRegisters.a[4](r1) - stw r21,56+M68kRegisters.a[5](r1) - stw r22,56+M68kRegisters.a[6](r1) - stw r3,56+M68kRegisters.a[7](r1) - stfd f0,56+16*4+0*8(r1) - stfd f1,56+16*4+1*8(r1) - stfd f2,56+16*4+2*8(r1) - stfd f3,56+16*4+3*8(r1) - stfd f4,56+16*4+4*8(r1) - stfd f5,56+16*4+5*8(r1) - stfd f6,56+16*4+6*8(r1) - stfd f7,56+16*4+7*8(r1) - mffs f0 - stfd f8,56+16*4+8*8(r1) - stfd f9,56+16*4+9*8(r1) - stfd f10,56+16*4+10*8(r1) - stfd f11,56+16*4+11*8(r1) - stfd f12,56+16*4+12*8(r1) - stfd f13,56+16*4+13*8(r1) - stfd f0,56+16*4+14*8(r1) - - // Execute native routine - mr r3,r5 - addi r4,r1,56 - bl EmulOp - - // Restore 68k registers - lwz r8,56+M68kRegisters.d[0](r1) - lwz r9,56+M68kRegisters.d[1](r1) - lwz r10,56+M68kRegisters.d[2](r1) - lwz r11,56+M68kRegisters.d[3](r1) - lwz r12,56+M68kRegisters.d[4](r1) - lwz r13,56+M68kRegisters.d[5](r1) - lwz r14,56+M68kRegisters.d[6](r1) - lwz r15,56+M68kRegisters.d[7](r1) - lwz r16,56+M68kRegisters.a[0](r1) - lwz r17,56+M68kRegisters.a[1](r1) - lwz r18,56+M68kRegisters.a[2](r1) - lwz r19,56+M68kRegisters.a[3](r1) - lwz r20,56+M68kRegisters.a[4](r1) - lwz r21,56+M68kRegisters.a[5](r1) - lwz r22,56+M68kRegisters.a[6](r1) - lwz r3,56+M68kRegisters.a[7](r1) - lfd f13,56+16*4+14*8(r1) - lfd f0,56+16*4+0*8(r1) - lfd f1,56+16*4+1*8(r1) - lfd f2,56+16*4+2*8(r1) - lfd f3,56+16*4+3*8(r1) - lfd f4,56+16*4+4*8(r1) - lfd f5,56+16*4+5*8(r1) - lfd f6,56+16*4+6*8(r1) - lfd f7,56+16*4+7*8(r1) - mtfsf 0xff,f13 - lfd f8,56+16*4+8*8(r1) - lfd f9,56+16*4+9*8(r1) - lfd f10,56+16*4+10*8(r1) - lfd f11,56+16*4+11*8(r1) - lfd f12,56+16*4+12*8(r1) - lfd f13,56+16*4+13*8(r1) - - // Delete PowerPC stack frame - lwz r2,56+16*4+15*8+12(r1) - lwz r0,56+16*4+15*8+16(r1) - mtxer r0 - lwz r0,56+16*4+15*8+4(r1) - mtcrf 0xff,r0 - mr r1,r3 - - // Reeintering 68k emulator - li r0,MODE_68K - stw r0,XLM_RUN_MODE - - // Set r0 to 0 for 68k emulator - li r0,0 - - // Execute next 68k opcode - rlwimi r29,r27,3,13,28 - lhau r27,2(r24) - mtlr r29 - blr - - - // Save address of EMUL_OP routine for 68k emulator patch -@3 mflr r0 - stw r0,XLM_EMUL_OP_PROC - - // Save stack pointer for EMUL_RETURN - stw r1,XLM_EMUL_RETURN_STACK - - // Preset registers for ROM boot routine - lis r3,0x40b0 // Pointer to ROM boot structure - ori r3,r3,0xd000 - - // 68k emulator is now active - li r0,MODE_68K - stw r0,XLM_RUN_MODE - - // Jump to ROM - bctr -} - -void Start680x0(void) -{ - // Install interrupt signal handler - sigemptyset(&sigusr1_action.sa_mask); - sigusr1_action.sa_handler = (__signal_func_ptr)(sigusr1_handler); - sigusr1_action.sa_flags = 0; - sigusr1_action.sa_userdata = NULL; - sigaction(SIGUSR1, &sigusr1_action, NULL); - - // Install signal stack - set_signal_stack(malloc(SIG_STACK_SIZE), SIG_STACK_SIZE); - - // We're now ready to receive signals - ReadyForSignals = true; - - D(bug("Jumping to ROM\n")); - jump_to_rom(ROM_BASE + 0x310000); - D(bug("Returned from ROM\n")); - - // We're no longer ready to receive signals - ReadyForSignals = false; -} - - -/* - * Trigger interrupt - */ - -void TriggerInterrupt(void) -{ - idle_resume(); - if (emul_thread > 0 && ReadyForSignals) - send_signal(emul_thread, SIGUSR1); -} - -void TriggerNMI(void) -{ - //!! not implemented yet -} - - -/* - * Execute 68k subroutine - * r->a[7] and r->sr are unused! - */ - -static asm void execute_68k(register uint32 addr, register M68kRegisters *r) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stw r4,12(r1) - stwu r1,-(56+19*4+18*8)(r1) - - // Save PowerPC registers - stmw r13,56(r1) -#if SAVE_FP_EXEC_68K - stfd f14,56+19*4+0*8(r1) - stfd f15,56+19*4+1*8(r1) - stfd f16,56+19*4+2*8(r1) - stfd f17,56+19*4+3*8(r1) - stfd f18,56+19*4+4*8(r1) - stfd f19,56+19*4+5*8(r1) - stfd f20,56+19*4+6*8(r1) - stfd f21,56+19*4+7*8(r1) - stfd f22,56+19*4+8*8(r1) - stfd f23,56+19*4+9*8(r1) - stfd f24,56+19*4+10*8(r1) - stfd f25,56+19*4+11*8(r1) - stfd f26,56+19*4+12*8(r1) - stfd f27,56+19*4+13*8(r1) - stfd f28,56+19*4+14*8(r1) - stfd f29,56+19*4+15*8(r1) - stfd f30,56+19*4+16*8(r1) - stfd f31,56+19*4+17*8(r1) -#endif - - // Set up registers for 68k emulator - lwz r31,XLM_KERNEL_DATA // Pointer to Kernel Data - addi r31,r31,0x1000 // points to Emulator Data - li r0,0 - mtcrf 0xff,r0 - creqv 11,11,11 // Supervisor mode - lwz r8,M68kRegisters.d[0](r4) - lwz r9,M68kRegisters.d[1](r4) - lwz r10,M68kRegisters.d[2](r4) - lwz r11,M68kRegisters.d[3](r4) - lwz r12,M68kRegisters.d[4](r4) - lwz r13,M68kRegisters.d[5](r4) - lwz r14,M68kRegisters.d[6](r4) - lwz r15,M68kRegisters.d[7](r4) - lwz r16,M68kRegisters.a[0](r4) - lwz r17,M68kRegisters.a[1](r4) - lwz r18,M68kRegisters.a[2](r4) - lwz r19,M68kRegisters.a[3](r4) - lwz r20,M68kRegisters.a[4](r4) - lwz r21,M68kRegisters.a[5](r4) - lwz r22,M68kRegisters.a[6](r4) - li r23,0 - mr r24,r3 - lwz r25,XLM_68K_R25 // MSB of SR - li r26,0 - li r28,0 // VBR - lwz r29,0x74(r31) // Pointer to opcode table - lwz r30,0x78(r31) // Address of emulator - - // Reentering 68k emulator - li r0,MODE_68K - stw r0,XLM_RUN_MODE - - // Set r0 to 0 for 68k emulator - li r0,0 - - // Execute 68k opcode - lha r27,0(r24) - rlwimi r29,r27,3,13,28 - lhau r27,2(r24) - mtlr r29 - blr -} - -void Execute68k(uint32 addr, M68kRegisters *r) -{ - uint16 proc[4] = {M68K_JSR, addr >> 16, addr & 0xffff, M68K_EXEC_RETURN}; - execute_68k((uint32)proc, r); -} - - -/* - * Execute MacOS 68k trap - * r->a[7] and r->sr are unused! - */ - -void Execute68kTrap(uint16 trap, struct M68kRegisters *r) -{ - uint16 proc[2] = {trap, M68K_EXEC_RETURN}; - execute_68k((uint32)proc, r); -} - - -/* - * USR1 handler - */ - -static void sigusr1_handler(int sig, void *arg, vregs *r) -{ - // Do nothing if interrupts are disabled - if ((*(int32 *)XLM_IRQ_NEST) > 0) - return; - - // 68k emulator active? Then trigger 68k interrupt level 1 - if (*(uint32 *)XLM_RUN_MODE == MODE_68K) { - *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1; - r->cr |= kernel_data->v[0x674 >> 2]; - } -} diff --git a/BasiliskII/src/prefs_items.cpp b/BasiliskII/src/prefs_items.cpp index 4a7f1a34..afb692b9 100644 --- a/BasiliskII/src/prefs_items.cpp +++ b/BasiliskII/src/prefs_items.cpp @@ -92,17 +92,7 @@ void AddPrefsDefaults(void) PrefsAddBool("noclipconversion", false); PrefsAddBool("nogui", false); -#if USE_JIT - // JIT compiler specific options - PrefsAddBool("jit", true); - PrefsAddBool("jitfpu", true); - PrefsAddBool("jitdebug", false); - PrefsAddInt32("jitcachesize", 8192); - PrefsAddBool("jitlazyflush", true); - PrefsAddBool("jitinline", true); -#else PrefsAddBool("jit", false); -#endif PrefsAddInt32("keyboardtype", 5); } diff --git a/BasiliskII/src/rom_patches.cpp b/BasiliskII/src/rom_patches.cpp index db404169..4b79f01c 100644 --- a/BasiliskII/src/rom_patches.cpp +++ b/BasiliskII/src/rom_patches.cpp @@ -827,7 +827,7 @@ bool CheckROM(void) // Read version ROMVersion = ntohs(*(uint16 *)(ROMBaseHost + 8)); -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING // Real and direct addressing modes require a 32-bit clean ROM return ROMVersion == ROM_VERSION_32; #else @@ -1254,15 +1254,6 @@ static bool patch_rom_32(void) *wp++ = htons(0x0cea); *wp = htons(M68K_RTS); -#if REAL_ADDRESSING - // Move system zone to start of Mac RAM - wp = (uint16 *)(ROMBaseHost + 0x50a); - *wp++ = htons(HiWord(RAMBaseMac + 0x2000)); - *wp++ = htons(LoWord(RAMBaseMac + 0x2000)); - *wp++ = htons(HiWord(RAMBaseMac + 0x3800)); - *wp = htons(LoWord(RAMBaseMac + 0x3800)); -#endif - #if !ROM_IS_WRITE_PROTECTED #if defined(USE_SCRATCHMEM_SUBTERFUGE) // Set fake handle at 0x0000 to scratch memory area (so broken Mac programs won't write into Mac ROM) @@ -1277,20 +1268,6 @@ static bool patch_rom_32(void) #endif #endif -#if REAL_ADDRESSING && defined(AMIGA) - // Don't overwrite SysBase under AmigaOS - wp = (uint16 *)(ROMBaseHost + 0xccb4); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); -#endif - -#if REAL_ADDRESSING && !defined(AMIGA) - // gb-- Temporary hack to get rid of crashes in Speedometer - wp = (uint16 *)(ROMBaseHost + 0xdba2); - if (ntohs(*wp) == 0x662c) // bne.b #$2c - *wp = htons(0x602c); // bra.b #$2c -#endif - // Don't write to VIA in InitTimeMgr wp = (uint16 *)(ROMBaseHost + 0xb0e2); *wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4 diff --git a/BasiliskII/src/rsrc_patches.cpp b/BasiliskII/src/rsrc_patches.cpp index cdff157e..5faeeb36 100644 --- a/BasiliskII/src/rsrc_patches.cpp +++ b/BasiliskII/src/rsrc_patches.cpp @@ -30,9 +30,6 @@ #include "audio_defs.h" #include "rsrc_patches.h" -#if ENABLE_MON -#include "mon.h" -#endif #define DEBUG 0 #include "debug.h" diff --git a/BasiliskII/src/slirp/COPYRIGHT b/BasiliskII/src/slirp/COPYRIGHT deleted file mode 100644 index b7d6568e..00000000 --- a/BasiliskII/src/slirp/COPYRIGHT +++ /dev/null @@ -1,61 +0,0 @@ -Slirp was written by Danny Gasparovski. -Copyright (c), 1995,1996 All Rights Reserved. - -Slirp is maintained by Kelly Price - -Slirp is free software; "free" as in you don't have to pay for it, and you -are free to do whatever you want with it. I do not accept any donations, -monetary or otherwise, for Slirp. Instead, I would ask you to pass this -potential donation to your favorite charity. In fact, I encourage -*everyone* who finds Slirp useful to make a small donation to their -favorite charity (for example, GreenPeace). This is not a requirement, but -a suggestion from someone who highly values the service they provide. - -The copyright terms and conditions: - ----BEGIN--- - - Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. 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. - - THIS SOFTWARE IS PROVIDED ``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 - DANNY GASPAROVSKI 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. - ----END--- - -This basically means you can do anything you want with the software, except -1) call it your own, and 2) claim warranty on it. There is no warranty for -this software. None. Nada. If you lose a million dollars while using -Slirp, that's your loss not mine. So, ***USE AT YOUR OWN RISK!***. - -If these conditions cannot be met due to legal restrictions (E.g. where it -is against the law to give out Software without warranty), you must cease -using the software and delete all copies you have. - -Slirp uses code that is copyrighted by the following people/organizations: - -Juha Pirkola. -Gregory M. Christy. -The Regents of the University of California. -Carnegie Mellon University. -The Australian National University. -RSA Data Security, Inc. - -Please read the top of each source file for the details on the various -copyrights. diff --git a/BasiliskII/src/slirp/VERSION b/BasiliskII/src/slirp/VERSION deleted file mode 100644 index 353ad940..00000000 --- a/BasiliskII/src/slirp/VERSION +++ /dev/null @@ -1 +0,0 @@ -qemu 0.9.0 (2007/02/05) diff --git a/BasiliskII/src/slirp/bootp.c b/BasiliskII/src/slirp/bootp.c deleted file mode 100644 index a51b80c9..00000000 --- a/BasiliskII/src/slirp/bootp.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * QEMU BOOTP/DHCP server - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include - -/* XXX: only DHCP is supported */ - -#define NB_ADDR 16 - -#define START_ADDR 15 - -#define LEASE_TIME (24 * 3600) - -typedef struct { - uint8_t allocated; - uint8_t macaddr[6]; -} BOOTPClient; - -BOOTPClient bootp_clients[NB_ADDR]; - -static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; - -static BOOTPClient *get_new_addr(struct in_addr *paddr) -{ - BOOTPClient *bc; - int i; - - for(i = 0; i < NB_ADDR; i++) { - if (!bootp_clients[i].allocated) - goto found; - } - return NULL; - found: - bc = &bootp_clients[i]; - bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); - return bc; -} - -static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr) -{ - BOOTPClient *bc; - int i; - - for(i = 0; i < NB_ADDR; i++) { - if (!memcmp(macaddr, bootp_clients[i].macaddr, 6)) - goto found; - } - return NULL; - found: - bc = &bootp_clients[i]; - bc->allocated = 1; - paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR)); - return bc; -} - -static void dhcp_decode(const uint8_t *buf, int size, - int *pmsg_type) -{ - const uint8_t *p, *p_end; - int len, tag; - - *pmsg_type = 0; - - p = buf; - p_end = buf + size; - if (size < 5) - return; - if (memcmp(p, rfc1533_cookie, 4) != 0) - return; - p += 4; - while (p < p_end) { - tag = p[0]; - if (tag == RFC1533_PAD) { - p++; - } else if (tag == RFC1533_END) { - break; - } else { - p++; - if (p >= p_end) - break; - len = *p++; - - switch(tag) { - case RFC2132_MSG_TYPE: - if (len >= 1) - *pmsg_type = p[0]; - break; - default: - break; - } - p += len; - } - } -} - -static void bootp_reply(struct bootp_t *bp) -{ - BOOTPClient *bc; - struct mbuf *m; - struct bootp_t *rbp; - struct sockaddr_in saddr, daddr; - struct in_addr dns_addr; - int dhcp_msg_type, val; - uint8_t *q; - - /* extract exact DHCP msg type */ - dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type); - - if (dhcp_msg_type == 0) - dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ - - if (dhcp_msg_type != DHCPDISCOVER && - dhcp_msg_type != DHCPREQUEST) - return; - /* XXX: this is a hack to get the client mac address */ - memcpy(client_ethaddr, bp->bp_hwaddr, 6); - - if ((m = m_get()) == NULL) - return; - m->m_data += if_maxlinkhdr; - rbp = (struct bootp_t *)m->m_data; - m->m_data += sizeof(struct udpiphdr); - memset(rbp, 0, sizeof(struct bootp_t)); - - if (dhcp_msg_type == DHCPDISCOVER) { - new_addr: - bc = get_new_addr(&daddr.sin_addr); - if (!bc) - return; - memcpy(bc->macaddr, client_ethaddr, 6); - } else { - bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); - if (!bc) { - /* if never assigned, behaves as if it was already - assigned (windows fix because it remembers its address) */ - goto new_addr; - } - } - - saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); - saddr.sin_port = htons(BOOTP_SERVER); - - daddr.sin_port = htons(BOOTP_CLIENT); - - rbp->bp_op = BOOTP_REPLY; - rbp->bp_xid = bp->bp_xid; - rbp->bp_htype = 1; - rbp->bp_hlen = 6; - memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6); - - rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */ - rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ - - q = rbp->bp_vend; - memcpy(q, rfc1533_cookie, 4); - q += 4; - - if (dhcp_msg_type == DHCPDISCOVER) { - *q++ = RFC2132_MSG_TYPE; - *q++ = 1; - *q++ = DHCPOFFER; - } else if (dhcp_msg_type == DHCPREQUEST) { - *q++ = RFC2132_MSG_TYPE; - *q++ = 1; - *q++ = DHCPACK; - } - - if (dhcp_msg_type == DHCPDISCOVER || - dhcp_msg_type == DHCPREQUEST) { - *q++ = RFC2132_SRV_ID; - *q++ = 4; - memcpy(q, &saddr.sin_addr, 4); - q += 4; - - *q++ = RFC1533_NETMASK; - *q++ = 4; - *q++ = 0xff; - *q++ = 0xff; - *q++ = 0xff; - *q++ = 0x00; - - *q++ = RFC1533_GATEWAY; - *q++ = 4; - memcpy(q, &saddr.sin_addr, 4); - q += 4; - - *q++ = RFC1533_DNS; - *q++ = 4; - dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); - memcpy(q, &dns_addr, 4); - q += 4; - - *q++ = RFC2132_LEASE_TIME; - *q++ = 4; - val = htonl(LEASE_TIME); - memcpy(q, &val, 4); - q += 4; - - if (*slirp_hostname) { - val = strlen(slirp_hostname); - *q++ = RFC1533_HOSTNAME; - *q++ = val; - memcpy(q, slirp_hostname, val); - q += val; - } - } - *q++ = RFC1533_END; - - m->m_len = sizeof(struct bootp_t) - - sizeof(struct ip) - sizeof(struct udphdr); - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); -} - -void bootp_input(struct mbuf *m) -{ - struct bootp_t *bp = mtod(m, struct bootp_t *); - - if (bp->bp_op == BOOTP_REQUEST) { - bootp_reply(bp); - } -} diff --git a/BasiliskII/src/slirp/bootp.h b/BasiliskII/src/slirp/bootp.h deleted file mode 100644 index 54a86ca2..00000000 --- a/BasiliskII/src/slirp/bootp.h +++ /dev/null @@ -1,121 +0,0 @@ -/* bootp/dhcp defines */ - -#define BOOTP_SERVER 67 -#define BOOTP_CLIENT 68 - -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -#define RFC1533_COOKIE 99, 130, 83, 99 -#define RFC1533_PAD 0 -#define RFC1533_NETMASK 1 -#define RFC1533_TIMEOFFSET 2 -#define RFC1533_GATEWAY 3 -#define RFC1533_TIMESERVER 4 -#define RFC1533_IEN116NS 5 -#define RFC1533_DNS 6 -#define RFC1533_LOGSERVER 7 -#define RFC1533_COOKIESERVER 8 -#define RFC1533_LPRSERVER 9 -#define RFC1533_IMPRESSSERVER 10 -#define RFC1533_RESOURCESERVER 11 -#define RFC1533_HOSTNAME 12 -#define RFC1533_BOOTFILESIZE 13 -#define RFC1533_MERITDUMPFILE 14 -#define RFC1533_DOMAINNAME 15 -#define RFC1533_SWAPSERVER 16 -#define RFC1533_ROOTPATH 17 -#define RFC1533_EXTENSIONPATH 18 -#define RFC1533_IPFORWARDING 19 -#define RFC1533_IPSOURCEROUTING 20 -#define RFC1533_IPPOLICYFILTER 21 -#define RFC1533_IPMAXREASSEMBLY 22 -#define RFC1533_IPTTL 23 -#define RFC1533_IPMTU 24 -#define RFC1533_IPMTUPLATEAU 25 -#define RFC1533_INTMTU 26 -#define RFC1533_INTLOCALSUBNETS 27 -#define RFC1533_INTBROADCAST 28 -#define RFC1533_INTICMPDISCOVER 29 -#define RFC1533_INTICMPRESPOND 30 -#define RFC1533_INTROUTEDISCOVER 31 -#define RFC1533_INTROUTESOLICIT 32 -#define RFC1533_INTSTATICROUTES 33 -#define RFC1533_LLTRAILERENCAP 34 -#define RFC1533_LLARPCACHETMO 35 -#define RFC1533_LLETHERNETENCAP 36 -#define RFC1533_TCPTTL 37 -#define RFC1533_TCPKEEPALIVETMO 38 -#define RFC1533_TCPKEEPALIVEGB 39 -#define RFC1533_NISDOMAIN 40 -#define RFC1533_NISSERVER 41 -#define RFC1533_NTPSERVER 42 -#define RFC1533_VENDOR 43 -#define RFC1533_NBNS 44 -#define RFC1533_NBDD 45 -#define RFC1533_NBNT 46 -#define RFC1533_NBSCOPE 47 -#define RFC1533_XFS 48 -#define RFC1533_XDM 49 - -#define RFC2132_REQ_ADDR 50 -#define RFC2132_LEASE_TIME 51 -#define RFC2132_MSG_TYPE 53 -#define RFC2132_SRV_ID 54 -#define RFC2132_PARAM_LIST 55 -#define RFC2132_MAX_SIZE 57 -#define RFC2132_RENEWAL_TIME 58 -#define RFC2132_REBIND_TIME 59 - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPACK 5 - -#define RFC1533_VENDOR_MAJOR 0 -#define RFC1533_VENDOR_MINOR 0 - -#define RFC1533_VENDOR_MAGIC 128 -#define RFC1533_VENDOR_ADDPARM 129 -#define RFC1533_VENDOR_ETHDEV 130 -#define RFC1533_VENDOR_HOWTO 132 -#define RFC1533_VENDOR_MNUOPTS 160 -#define RFC1533_VENDOR_SELECTION 176 -#define RFC1533_VENDOR_MOTD 184 -#define RFC1533_VENDOR_NUMOFMOTD 8 -#define RFC1533_VENDOR_IMG 192 -#define RFC1533_VENDOR_NUMOFIMG 16 - -#define RFC1533_END 255 -#define BOOTP_VENDOR_LEN 64 -#define DHCP_OPT_LEN 312 - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct bootp_t { - struct ip ip; - struct udphdr udp; - uint8_t bp_op; - uint8_t bp_htype; - uint8_t bp_hlen; - uint8_t bp_hops; - uint32_t bp_xid; - uint16_t bp_secs; - uint16_t unused; - struct in_addr bp_ciaddr; - struct in_addr bp_yiaddr; - struct in_addr bp_siaddr; - struct in_addr bp_giaddr; - uint8_t bp_hwaddr[16]; - uint8_t bp_sname[64]; - uint8_t bp_file[128]; - uint8_t bp_vend[DHCP_OPT_LEN]; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -void bootp_input(struct mbuf *m); diff --git a/BasiliskII/src/slirp/cksum.c b/BasiliskII/src/slirp/cksum.c deleted file mode 100644 index 66d3f230..00000000 --- a/BasiliskII/src/slirp/cksum.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 - * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp - */ - -#include - -/* - * Checksum routine for Internet Protocol family headers (Portable Version). - * - * This routine is very heavily used in the network - * code and should be modified for each CPU to be as fast as possible. - * - * XXX Since we will never span more than 1 mbuf, we can optimise this - */ - -#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) -#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} - -int cksum(struct mbuf *m, int len) -{ - register u_int16_t *w; - register int sum = 0; - register int mlen = 0; - int byte_swapped = 0; - - union { - u_int8_t c[2]; - u_int16_t s; - } s_util; - union { - u_int16_t s[2]; - u_int32_t l; - } l_util; - - if (m->m_len == 0) - goto cont; - w = mtod(m, u_int16_t *); - - mlen = m->m_len; - - if (len < mlen) - mlen = len; - len -= mlen; - /* - * Force to even boundary. - */ - if ((1 & (long) w) && (mlen > 0)) { - REDUCE; - sum <<= 8; - s_util.c[0] = *(u_int8_t *)w; - w = (u_int16_t *)((int8_t *)w + 1); - mlen--; - byte_swapped = 1; - } - /* - * Unroll the loop to make overhead from - * branches &c small. - */ - while ((mlen -= 32) >= 0) { - sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; - sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; - sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; - sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; - w += 16; - } - mlen += 32; - while ((mlen -= 8) >= 0) { - sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; - w += 4; - } - mlen += 8; - if (mlen == 0 && byte_swapped == 0) - goto cont; - REDUCE; - while ((mlen -= 2) >= 0) { - sum += *w++; - } - - if (byte_swapped) { - REDUCE; - sum <<= 8; - byte_swapped = 0; - if (mlen == -1) { - s_util.c[1] = *(u_int8_t *)w; - sum += s_util.s; - mlen = 0; - } else - - mlen = -1; - } else if (mlen == -1) - s_util.c[0] = *(u_int8_t *)w; - -cont: -#ifdef DEBUG - if (len) { - DEBUG_ERROR((dfd, "cksum: out of data\n")); - DEBUG_ERROR((dfd, " len = %d\n", len)); - } -#endif - if (mlen == -1) { - /* The last mbuf has odd # of bytes. Follow the - standard (the odd byte may be shifted left by 8 bits - or not as determined by endian-ness of the machine) */ - s_util.c[1] = 0; - sum += s_util.s; - } - REDUCE; - return (~sum & 0xffff); -} diff --git a/BasiliskII/src/slirp/ctl.h b/BasiliskII/src/slirp/ctl.h deleted file mode 100644 index 4a8576dc..00000000 --- a/BasiliskII/src/slirp/ctl.h +++ /dev/null @@ -1,7 +0,0 @@ -#define CTL_CMD 0 -#define CTL_EXEC 1 -#define CTL_ALIAS 2 -#define CTL_DNS 3 - -#define CTL_SPECIAL "10.0.2.0" -#define CTL_LOCAL "10.0.2.15" diff --git a/BasiliskII/src/slirp/debug.c b/BasiliskII/src/slirp/debug.c deleted file mode 100644 index 916b9a8e..00000000 --- a/BasiliskII/src/slirp/debug.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * Portions copyright (c) 2000 Kelly Price. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include - -FILE *dfd = NULL; -#ifdef DEBUG -int dostats = 1; -#else -int dostats = 0; -#endif -int slirp_debug = 0; - -/* Carry over one item from main.c so that the tty's restored. - * Only done when the tty being used is /dev/tty --RedWolf */ -extern struct termios slirp_tty_settings; -extern int slirp_tty_restore; - - -void -debug_init(file, dbg) - char *file; - int dbg; -{ - /* Close the old debugging file */ - if (dfd) - fclose(dfd); - - dfd = fopen(file,"w"); - if (dfd != NULL) { -#if 0 - fprintf(dfd,"Slirp %s - Debugging Started.\n", SLIRP_VERSION); -#endif - fprintf(dfd,"Debugging Started level %i.\r\n",dbg); - fflush(dfd); - slirp_debug = dbg; - } else { - lprint("Error: Debugging file \"%s\" could not be opened: %s\r\n", - file, strerror(errno)); - } -} - -/* - * Dump a packet in the same format as tcpdump -x - */ -#ifdef DEBUG -void -dump_packet(dat, n) - void *dat; - int n; -{ - u_char *pptr = (u_char *)dat; - int j,k; - - n /= 16; - n++; - DEBUG_MISC((dfd, "PACKET DUMPED: \n")); - for(j = 0; j < n; j++) { - for(k = 0; k < 6; k++) - DEBUG_MISC((dfd, "%02x ", *pptr++)); - DEBUG_MISC((dfd, "\n")); - fflush(dfd); - } -} -#endif - -#if 0 -/* - * Statistic routines - * - * These will print statistics to the screen, the debug file (dfd), or - * a buffer, depending on "type", so that the stats can be sent over - * the link as well. - */ - -void -ttystats(ttyp) - struct ttys *ttyp; -{ - struct slirp_ifstats *is = &ttyp->ifstats; - char buff[512]; - - lprint(" \r\n"); - - if (if_comp & IF_COMPRESS) - strcpy(buff, "on"); - else if (if_comp & IF_NOCOMPRESS) - strcpy(buff, "off"); - else - strcpy(buff, "off (for now)"); - lprint("Unit %d:\r\n", ttyp->unit); - lprint(" using %s encapsulation (VJ compression is %s)\r\n", ( -#ifdef USE_PPP - ttyp->proto==PROTO_PPP?"PPP": -#endif - "SLIP"), buff); - lprint(" %d baudrate\r\n", ttyp->baud); - lprint(" interface is %s\r\n", ttyp->up?"up":"down"); - lprint(" using fd %d, guardian pid is %d\r\n", ttyp->fd, ttyp->pid); -#ifndef FULL_BOLT - lprint(" towrite is %d bytes\r\n", ttyp->towrite); -#endif - if (ttyp->zeros) - lprint(" %d zeros have been typed\r\n", ttyp->zeros); - else if (ttyp->ones) - lprint(" %d ones have been typed\r\n", ttyp->ones); - lprint("Interface stats:\r\n"); - lprint(" %6d output packets sent (%d bytes)\r\n", is->out_pkts, is->out_bytes); - lprint(" %6d output packets dropped (%d bytes)\r\n", is->out_errpkts, is->out_errbytes); - lprint(" %6d input packets received (%d bytes)\r\n", is->in_pkts, is->in_bytes); - lprint(" %6d input packets dropped (%d bytes)\r\n", is->in_errpkts, is->in_errbytes); - lprint(" %6d bad input packets\r\n", is->in_mbad); -} - -void -allttystats() -{ - struct ttys *ttyp; - - for (ttyp = ttys; ttyp; ttyp = ttyp->next) - ttystats(ttyp); -} -#endif - -void -ipstats() -{ - lprint(" \r\n"); - - lprint("IP stats:\r\n"); - lprint(" %6d total packets received (%d were unaligned)\r\n", - ipstat.ips_total, ipstat.ips_unaligned); - lprint(" %6d with incorrect version\r\n", ipstat.ips_badvers); - lprint(" %6d with bad header checksum\r\n", ipstat.ips_badsum); - lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort); - lprint(" %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall); - lprint(" %6d with bad header length\r\n", ipstat.ips_badhlen); - lprint(" %6d with bad packet length\r\n", ipstat.ips_badlen); - lprint(" %6d fragments received\r\n", ipstat.ips_fragments); - lprint(" %6d fragments dropped\r\n", ipstat.ips_fragdropped); - lprint(" %6d fragments timed out\r\n", ipstat.ips_fragtimeout); - lprint(" %6d packets reassembled ok\r\n", ipstat.ips_reassembled); - lprint(" %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented); - lprint(" %6d total outgoing fragments\r\n", ipstat.ips_ofragments); - lprint(" %6d with bad protocol field\r\n", ipstat.ips_noproto); - lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); -} - -#if 0 -void -vjstats() -{ - lprint(" \r\n"); - - lprint("VJ compression stats:\r\n"); - - lprint(" %6d outbound packets (%d compressed)\r\n", - comp_s.sls_packets, comp_s.sls_compressed); - lprint(" %6d searches for connection stats (%d misses)\r\n", - comp_s.sls_searches, comp_s.sls_misses); - lprint(" %6d inbound uncompressed packets\r\n", comp_s.sls_uncompressedin); - lprint(" %6d inbound compressed packets\r\n", comp_s.sls_compressedin); - lprint(" %6d inbound unknown type packets\r\n", comp_s.sls_errorin); - lprint(" %6d inbound packets tossed due to error\r\n", comp_s.sls_tossed); -} -#endif - -void -tcpstats() -{ - lprint(" \r\n"); - - lprint("TCP stats:\r\n"); - - lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal); - lprint(" %6d data packets (%d bytes)\r\n", - tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte); - lprint(" %6d data packets retransmitted (%d bytes)\r\n", - tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte); - lprint(" %6d ack-only packets (%d delayed)\r\n", - tcpstat.tcps_sndacks, tcpstat.tcps_delack); - lprint(" %6d URG only packets\r\n", tcpstat.tcps_sndurg); - lprint(" %6d window probe packets\r\n", tcpstat.tcps_sndprobe); - lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup); - lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl); - lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin); - - lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); - lprint(" %6d acks (for %d bytes)\r\n", - tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte); - lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack); - lprint(" %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch); - lprint(" %6d packets received in sequence (%d bytes)\r\n", - tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte); - lprint(" %6d completely duplicate packets (%d bytes)\r\n", - tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte); - - lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n", - tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte); - lprint(" %6d out-of-order packets (%d bytes)\r\n", - tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte); - lprint(" %6d packets of data after window (%d bytes)\r\n", - tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin); - lprint(" %6d window probes\r\n", tcpstat.tcps_rcvwinprobe); - lprint(" %6d window update packets\r\n", tcpstat.tcps_rcvwinupd); - lprint(" %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose); - lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum); - lprint(" %6d discarded for bad header offset fields\r\n", - tcpstat.tcps_rcvbadoff); - - lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt); - lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts); - lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects); - lprint(" %6d connections closed (including %d drop)\r\n", - tcpstat.tcps_closed, tcpstat.tcps_drops); - lprint(" %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops); - lprint(" %6d segments we tried to get rtt (%d succeeded)\r\n", - tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated); - lprint(" %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo); - lprint(" %6d connections dropped by rxmt timeout\r\n", - tcpstat.tcps_timeoutdrop); - lprint(" %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo); - lprint(" %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo); - lprint(" %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe); - lprint(" %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops); - lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack); - lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat); - lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss); - - -/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */ -/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */ - -} - -void -udpstats() -{ - lprint(" \r\n"); - - lprint("UDP stats:\r\n"); - lprint(" %6d datagrams received\r\n", udpstat.udps_ipackets); - lprint(" %6d with packets shorter than header\r\n", udpstat.udps_hdrops); - lprint(" %6d with bad checksums\r\n", udpstat.udps_badsum); - lprint(" %6d with data length larger than packet\r\n", udpstat.udps_badlen); - lprint(" %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss); - lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); -} - -void -icmpstats() -{ - lprint(" \r\n"); - lprint("ICMP stats:\r\n"); - lprint(" %6d ICMP packets received\r\n", icmpstat.icps_received); - lprint(" %6d were too short\r\n", icmpstat.icps_tooshort); - lprint(" %6d with bad checksums\r\n", icmpstat.icps_checksum); - lprint(" %6d with type not supported\r\n", icmpstat.icps_notsupp); - lprint(" %6d with bad type feilds\r\n", icmpstat.icps_badtype); - lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); -} - -void -mbufstats() -{ - struct mbuf *m; - int i; - - lprint(" \r\n"); - - lprint("Mbuf stats:\r\n"); - - lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max); - - i = 0; - for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next) - i++; - lprint(" %6d mbufs on free list\r\n", i); - - i = 0; - for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) - i++; - lprint(" %6d mbufs on used list\r\n", i); - lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); -} - -void -sockstats() -{ - char addr[INET_ADDRSTRLEN]; - char buff[256]; - int n; - struct socket *so; - - lprint(" \r\n"); - - lprint( - "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); - - for (so = tcb.so_next; so != &tcb; so = so->so_next) { - - n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); - while (n < 17) - buff[n++] = ' '; - buff[17] = 0; - lprint("%s %3d %15s %5d ", - buff, so->s, - inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)), - ntohs(so->so_lport)); - lprint("%15s %5d %5d %5d\r\n", - inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)), - ntohs(so->so_fport), - so->so_rcv.sb_cc, so->so_snd.sb_cc); - } - - for (so = udb.so_next; so != &udb; so = so->so_next) { - - n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); - while (n < 17) - buff[n++] = ' '; - buff[17] = 0; - lprint("%s %3d %15s %5d ", - buff, so->s, - inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)), - ntohs(so->so_lport)); - lprint("%15s %5d %5d %5d\r\n", - inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)), - ntohs(so->so_fport), - so->so_rcv.sb_cc, so->so_snd.sb_cc); - } -} - -#if 0 -void -slirp_exit(exit_status) - int exit_status; -{ - struct ttys *ttyp; - - DEBUG_CALL("slirp_exit"); - DEBUG_ARG("exit_status = %d", exit_status); - - if (dostats) { - lprint_print = (int (*) _P((void *, const char *, va_list)))vfprintf; - if (!dfd) - debug_init("slirp_stats", 0xf); - lprint_arg = (char **)&dfd; - - ipstats(); - tcpstats(); - udpstats(); - icmpstats(); - mbufstats(); - sockstats(); - allttystats(); - vjstats(); - } - - for (ttyp = ttys; ttyp; ttyp = ttyp->next) - tty_detached(ttyp, 1); - - if (slirp_forked) { - /* Menendez time */ - if (kill(getppid(), SIGQUIT) < 0) - lprint("Couldn't kill parent process %ld!\n", - (long) getppid()); - } - - /* Restore the terminal if we gotta */ - if(slirp_tty_restore) - tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */ - exit(exit_status); -} -#endif diff --git a/BasiliskII/src/slirp/debug.h b/BasiliskII/src/slirp/debug.h deleted file mode 100644 index c5d42195..00000000 --- a/BasiliskII/src/slirp/debug.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#define PRN_STDERR 1 -#define PRN_SPRINTF 2 - -extern FILE *dfd; -extern FILE *lfd; -extern int dostats; -extern int slirp_debug; - -#define DBG_CALL 0x1 -#define DBG_MISC 0x2 -#define DBG_ERROR 0x4 -#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR - -#ifdef DEBUG -#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); } -#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); } -#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); } -#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); } -#define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); } - - -#else - -#define DEBUG_CALL(x) -#define DEBUG_ARG(x, y) -#define DEBUG_ARGS(x) -#define DEBUG_MISC(x) -#define DEBUG_ERROR(x) - -#endif - -void debug_init(char *, int); -//void ttystats(struct ttys *); -void allttystats(void); -void ipstats(void); -void vjstats(void); -void tcpstats(void); -void udpstats(void); -void icmpstats(void); -void mbufstats(void); -void sockstats(void); -void slirp_exit(int); - diff --git a/BasiliskII/src/slirp/icmp_var.h b/BasiliskII/src/slirp/icmp_var.h deleted file mode 100644 index 9af222fb..00000000 --- a/BasiliskII/src/slirp/icmp_var.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93 - * icmp_var.h,v 1.4 1995/02/16 00:27:40 wollman Exp - */ - -#ifndef _NETINET_ICMP_VAR_H_ -#define _NETINET_ICMP_VAR_H_ - -/* - * Variables related to this implementation - * of the internet control message protocol. - */ -struct icmpstat { -/* statistics related to input messages processed */ - u_long icps_received; /* #ICMP packets received */ - u_long icps_tooshort; /* packet < ICMP_MINLEN */ - u_long icps_checksum; /* bad checksum */ - u_long icps_notsupp; /* #ICMP packets not supported */ - u_long icps_badtype; /* #with bad type feild */ - u_long icps_reflect; /* number of responses */ -}; - -/* - * Names for ICMP sysctl objects - */ -#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */ -#define ICMPCTL_STATS 2 /* statistics (read-only) */ -#define ICMPCTL_MAXID 3 - -#define ICMPCTL_NAMES { \ - { 0, 0 }, \ - { "maskrepl", CTLTYPE_INT }, \ - { "stats", CTLTYPE_STRUCT }, \ -} - -extern struct icmpstat icmpstat; - -#endif diff --git a/BasiliskII/src/slirp/if.c b/BasiliskII/src/slirp/if.c deleted file mode 100644 index 9185dcf6..00000000 --- a/BasiliskII/src/slirp/if.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include - -size_t if_mtu, if_mru; -int if_comp; -int if_maxlinkhdr; -int if_queued = 0; /* Number of packets queued so far */ -int if_thresh = 10; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ - -struct mbuf if_fastq; /* fast queue (for interactive data) */ -struct mbuf if_batchq; /* queue for non-interactive data */ -struct mbuf *next_m; /* Pointer to next mbuf to output */ - -#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) - -void -ifs_insque(ifm, ifmhead) - struct mbuf *ifm, *ifmhead; -{ - ifm->ifs_next = ifmhead->ifs_next; - ifmhead->ifs_next = ifm; - ifm->ifs_prev = ifmhead; - ifm->ifs_next->ifs_prev = ifm; -} - -void -ifs_remque(ifm) - struct mbuf *ifm; -{ - ifm->ifs_prev->ifs_next = ifm->ifs_next; - ifm->ifs_next->ifs_prev = ifm->ifs_prev; -} - -void -if_init() -{ -#if 0 - /* - * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, - * and 8 bytes for PPP, but need to have it on an 8byte boundary - */ -#ifdef USE_PPP - if_maxlinkhdr = 48; -#else - if_maxlinkhdr = 40; -#endif -#else - /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ - if_maxlinkhdr = 2 + 14 + 40; -#endif - if_mtu = 1500; - if_mru = 1500; - if_comp = IF_AUTOCOMP; - if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; - if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; - // sl_compress_init(&comp_s); - next_m = &if_batchq; -} - -#if 0 -/* - * This shouldn't be needed since the modem is blocking and - * we don't expect any signals, but what the hell.. - */ -inline int -writen(fd, bptr, n) - int fd; - char *bptr; - int n; -{ - int ret; - int total; - - /* This should succeed most of the time */ - ret = send(fd, bptr, n,0); - if (ret == n || ret <= 0) - return ret; - - /* Didn't write everything, go into the loop */ - total = ret; - while (n > total) { - ret = send(fd, bptr+total, n-total,0); - if (ret <= 0) - return ret; - total += ret; - } - return total; -} - -/* - * if_input - read() the tty, do "top level" processing (ie: check for any escapes), - * and pass onto (*ttyp->if_input) - * - * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet. - */ -#define INBUFF_SIZE 2048 /* XXX */ -void -if_input(ttyp) - struct ttys *ttyp; -{ - u_char if_inbuff[INBUFF_SIZE]; - int if_n; - - DEBUG_CALL("if_input"); - DEBUG_ARG("ttyp = %lx", (long)ttyp); - - if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0); - - DEBUG_MISC((dfd, " read %d bytes\n", if_n)); - - if (if_n <= 0) { - int error = WSAGetLastError(); - if (if_n == 0 || (error != WSAEINTR && error != EAGAIN)) { - if (ttyp->up) - link_up--; - tty_detached(ttyp, 0); - } - return; - } - if (if_n == 1) { - if (*if_inbuff == '0') { - ttyp->ones = 0; - if (++ttyp->zeros >= 5) - slirp_exit(0); - return; - } - if (*if_inbuff == '1') { - ttyp->zeros = 0; - if (++ttyp->ones >= 5) - tty_detached(ttyp, 0); - return; - } - } - ttyp->ones = ttyp->zeros = 0; - - (*ttyp->if_input)(ttyp, if_inbuff, if_n); -} -#endif - -/* - * if_output: Queue packet into an output queue. - * There are 2 output queue's, if_fastq and if_batchq. - * Each output queue is a doubly linked list of double linked lists - * of mbufs, each list belonging to one "session" (socket). This - * way, we can output packets fairly by sending one packet from each - * session, instead of all the packets from one session, then all packets - * from the next session, etc. Packets on the if_fastq get absolute - * priority, but if one session hogs the link, it gets "downgraded" - * to the batchq until it runs out of packets, then it'll return - * to the fastq (eg. if the user does an ls -alR in a telnet session, - * it'll temporarily get downgraded to the batchq) - */ -void -if_output(so, ifm) - struct socket *so; - struct mbuf *ifm; -{ - struct mbuf *ifq; - int on_fastq = 1; - - DEBUG_CALL("if_output"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("ifm = %lx", (long)ifm); - - /* - * First remove the mbuf from m_usedlist, - * since we're gonna use m_next and m_prev ourselves - * XXX Shouldn't need this, gotta change dtom() etc. - */ - if (ifm->m_flags & M_USEDLIST) { - remque(ifm); - ifm->m_flags &= ~M_USEDLIST; - } - - /* - * See if there's already a batchq list for this session. - * This can include an interactive session, which should go on fastq, - * but gets too greedy... hence it'll be downgraded from fastq to batchq. - * We mustn't put this packet back on the fastq (or we'll send it out of order) - * XXX add cache here? - */ - for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) { - if (so == ifq->ifq_so) { - /* A match! */ - ifm->ifq_so = so; - ifs_insque(ifm, ifq->ifs_prev); - goto diddit; - } - } - - /* No match, check which queue to put it on */ - if (so && (so->so_iptos & IPTOS_LOWDELAY)) { - ifq = if_fastq.ifq_prev; - on_fastq = 1; - /* - * Check if this packet is a part of the last - * packet's session - */ - if (ifq->ifq_so == so) { - ifm->ifq_so = so; - ifs_insque(ifm, ifq->ifs_prev); - goto diddit; - } - } else - ifq = if_batchq.ifq_prev; - - /* Create a new doubly linked list for this session */ - ifm->ifq_so = so; - ifs_init(ifm); - insque(ifm, ifq); - -diddit: - ++if_queued; - - if (so) { - /* Update *_queued */ - so->so_queued++; - so->so_nqueued++; - /* - * Check if the interactive session should be downgraded to - * the batchq. A session is downgraded if it has queued 6 - * packets without pausing, and at least 3 of those packets - * have been sent over the link - * (XXX These are arbitrary numbers, probably not optimal..) - */ - if (on_fastq && ((so->so_nqueued >= 6) && - (so->so_nqueued - so->so_queued) >= 3)) { - - /* Remove from current queue... */ - remque(ifm->ifs_next); - - /* ...And insert in the new. That'll teach ya! */ - insque(ifm->ifs_next, &if_batchq); - } - } - -#ifndef FULL_BOLT - /* - * This prevents us from malloc()ing too many mbufs - */ - if (link_up) { - /* if_start will check towrite */ - if_start(); - } -#endif -} - -/* - * Send a packet - * We choose a packet based on it's position in the output queues; - * If there are packets on the fastq, they are sent FIFO, before - * everything else. Otherwise we choose the first packet from the - * batchq and send it. the next packet chosen will be from the session - * after this one, then the session after that one, and so on.. So, - * for example, if there are 3 ftp session's fighting for bandwidth, - * one packet will be sent from the first session, then one packet - * from the second session, then one packet from the third, then back - * to the first, etc. etc. - */ -void -if_start(void) -{ - struct mbuf *ifm, *ifqt; - - DEBUG_CALL("if_start"); - - if (if_queued == 0) - return; /* Nothing to do */ - - again: - /* check if we can really output */ - if (!slirp_can_output()) - return; - - /* - * See which queue to get next packet from - * If there's something in the fastq, select it immediately - */ - if (if_fastq.ifq_next != &if_fastq) { - ifm = if_fastq.ifq_next; - } else { - /* Nothing on fastq, see if next_m is valid */ - if (next_m != &if_batchq) - ifm = next_m; - else - ifm = if_batchq.ifq_next; - - /* Set which packet to send on next iteration */ - next_m = ifm->ifq_next; - } - /* Remove it from the queue */ - ifqt = ifm->ifq_prev; - remque(ifm); - --if_queued; - - /* If there are more packets for this session, re-queue them */ - if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { - insque(ifm->ifs_next, ifqt); - ifs_remque(ifm); - } - - /* Update so_queued */ - if (ifm->ifq_so) { - if (--ifm->ifq_so->so_queued == 0) - /* If there's no more queued, reset nqueued */ - ifm->ifq_so->so_nqueued = 0; - } - - /* Encapsulate the packet for sending */ - if_encap((uint8_t*)ifm->m_data, ifm->m_len); - - m_free(ifm); - - if (if_queued) - goto again; -} diff --git a/BasiliskII/src/slirp/if.h b/BasiliskII/src/slirp/if.h deleted file mode 100644 index a2564ab1..00000000 --- a/BasiliskII/src/slirp/if.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#ifndef _IF_H_ -#define _IF_H_ - -#define IF_COMPRESS 0x01 /* We want compression */ -#define IF_NOCOMPRESS 0x02 /* Do not do compression */ -#define IF_AUTOCOMP 0x04 /* Autodetect (default) */ -#define IF_NOCIDCOMP 0x08 /* CID compression */ - -/* Needed for FreeBSD */ -#undef if_mtu -extern size_t if_mtu; -extern size_t if_mru; /* MTU and MRU */ -extern int if_comp; /* Flags for compression */ -extern int if_maxlinkhdr; -extern int if_queued; /* Number of packets queued so far */ -extern int if_thresh; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ - -extern struct mbuf if_fastq; /* fast queue (for interactive data) */ -extern struct mbuf if_batchq; /* queue for non-interactive data */ -extern struct mbuf *next_m; - -#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) - -/* Interface statistics */ -struct slirp_ifstats { - u_int out_pkts; /* Output packets */ - u_int out_bytes; /* Output bytes */ - u_int out_errpkts; /* Output Error Packets */ - u_int out_errbytes; /* Output Error Bytes */ - u_int in_pkts; /* Input packets */ - u_int in_bytes; /* Input bytes */ - u_int in_errpkts; /* Input Error Packets */ - u_int in_errbytes; /* Input Error Bytes */ - - u_int bytes_saved; /* Number of bytes that compression "saved" */ - /* ie: number of bytes that didn't need to be sent over the link - * because of compression */ - - u_int in_mbad; /* Bad incoming packets */ -}; - -#endif diff --git a/BasiliskII/src/slirp/ip.h b/BasiliskII/src/slirp/ip.h deleted file mode 100644 index e0c7de96..00000000 --- a/BasiliskII/src/slirp/ip.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)ip.h 8.1 (Berkeley) 6/10/93 - * ip.h,v 1.3 1994/08/21 05:27:30 paul Exp - */ - -#ifndef _IP_H_ -#define _IP_H_ - -#ifdef WORDS_BIGENDIAN -# ifndef NTOHL -# define NTOHL(d) -# endif -# ifndef NTOHS -# define NTOHS(d) -# endif -# ifndef HTONL -# define HTONL(d) -# endif -# ifndef HTONS -# define HTONS(d) -# endif -#else -# ifndef NTOHL -# define NTOHL(d) ((d) = ntohl((d))) -# endif -# ifndef NTOHS -# define NTOHS(d) ((d) = ntohs((u_int16_t)(d))) -# endif -# ifndef HTONL -# define HTONL(d) ((d) = htonl((d))) -# endif -# ifndef HTONS -# define HTONS(d) ((d) = htons((u_int16_t)(d))) -# endif -#endif - -typedef u_int32_t n_long; /* long as received from the net */ - -/* - * Definitions for internet protocol version 4. - * Per RFC 791, September 1981. - */ -#define IPVERSION 4 - -/* - * Structure of an internet header, naked of options. - */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct ip { -#ifdef WORDS_BIGENDIAN - u_char ip_v:4, /* version */ - ip_hl:4; /* header length */ -#else - u_char ip_hl:4, /* header length */ - ip_v:4; /* version */ -#endif - u_int8_t ip_tos; /* type of service */ - u_int16_t ip_len; /* total length */ - u_int16_t ip_id; /* identification */ - u_int16_t ip_off; /* fragment offset field */ -#define IP_DF 0x4000 /* don't fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ - u_int8_t ip_ttl; /* time to live */ - u_int8_t ip_p; /* protocol */ - u_int16_t ip_sum; /* checksum */ - struct in_addr ip_src,ip_dst; /* source and dest address */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -#define IP_MAXPACKET 65535 /* maximum packet size */ - -/* - * Definitions for IP type of service (ip_tos) - */ -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 - -/* - * Definitions for options. - */ -#define IPOPT_COPIED(o) ((o)&0x80) -#define IPOPT_CLASS(o) ((o)&0x60) -#define IPOPT_NUMBER(o) ((o)&0x1f) - -#define IPOPT_CONTROL 0x00 -#define IPOPT_RESERVED1 0x20 -#define IPOPT_DEBMEAS 0x40 -#define IPOPT_RESERVED2 0x60 - -#define IPOPT_EOL 0 /* end of option list */ -#define IPOPT_NOP 1 /* no operation */ - -#define IPOPT_RR 7 /* record packet route */ -#define IPOPT_TS 68 /* timestamp */ -#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ -#define IPOPT_LSRR 131 /* loose source route */ -#define IPOPT_SATID 136 /* satnet id */ -#define IPOPT_SSRR 137 /* strict source route */ - -/* - * Offsets to fields in options other than EOL and NOP. - */ -#define IPOPT_OPTVAL 0 /* option ID */ -#define IPOPT_OLEN 1 /* option length */ -#define IPOPT_OFFSET 2 /* offset within option */ -#define IPOPT_MINOFF 4 /* min value of above */ - -/* - * Time stamp option structure. - */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct ip_timestamp { - u_int8_t ipt_code; /* IPOPT_TS */ - u_int8_t ipt_len; /* size of structure (variable) */ - u_int8_t ipt_ptr; /* index of current entry */ -#ifdef WORDS_BIGENDIAN - u_char ipt_oflw:4, /* overflow counter */ - ipt_flg:4; /* flags, see below */ -#else - u_char ipt_flg:4, /* flags, see below */ - ipt_oflw:4; /* overflow counter */ -#endif - union ipt_timestamp { - n_long ipt_time[1]; - struct ipt_ta { - struct in_addr ipt_addr; - n_long ipt_time; - } ipt_ta[1]; - } ipt_timestamp; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -/* flag bits for ipt_flg */ -#define IPOPT_TS_TSONLY 0 /* timestamps only */ -#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ -#define IPOPT_TS_PRESPEC 3 /* specified modules only */ - -/* bits for security (not byte swapped) */ -#define IPOPT_SECUR_UNCLASS 0x0000 -#define IPOPT_SECUR_CONFID 0xf135 -#define IPOPT_SECUR_EFTO 0x789a -#define IPOPT_SECUR_MMMM 0xbc4d -#define IPOPT_SECUR_RESTR 0xaf13 -#define IPOPT_SECUR_SECRET 0xd788 -#define IPOPT_SECUR_TOPSECRET 0x6bc5 - -/* - * Internet implementation parameters. - */ -#define MAXTTL 255 /* maximum time to live (seconds) */ -#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ -#define IPFRAGTTL 60 /* time to live for frags, slowhz */ -#define IPTTLDEC 1 /* subtracted when forwarding */ - -#define IP_MSS 576 /* default maximum segment size */ - -#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */ -#include -#else -#if SIZEOF_CHAR_P == 4 -typedef caddr_t caddr32_t; -#else -typedef u_int32_t caddr32_t; -#endif -#endif - -#if SIZEOF_CHAR_P == 4 -typedef struct ipq *ipqp_32; -typedef struct ipasfrag *ipasfragp_32; -#else -typedef caddr32_t ipqp_32; -typedef caddr32_t ipasfragp_32; -#endif - -/* - * Overlay for ip header used by other protocols (tcp, udp). - */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct ipovly { - caddr32_t ih_next, ih_prev; /* for protocol sequence q's */ - u_int8_t ih_x1; /* (unused) */ - u_int8_t ih_pr; /* protocol */ - u_int16_t ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -/* - * Ip reassembly queue structure. Each fragment - * being reassembled is attached to one of these structures. - * They are timed out after ipq_ttl drops to 0, and may also - * be reclaimed if memory becomes tight. - * size 28 bytes - */ -struct ipq { - ipqp_32 next,prev; /* to other reass headers */ - u_int8_t ipq_ttl; /* time for reass q to live */ - u_int8_t ipq_p; /* protocol of this fragment */ - u_int16_t ipq_id; /* sequence id for reassembly */ - ipasfragp_32 ipq_next,ipq_prev; - /* to ip headers of fragments */ - struct in_addr ipq_src,ipq_dst; -}; - -/* - * Ip header, when holding a fragment. - * - * Note: ipf_next must be at same offset as ipq_next above - */ -struct ipasfrag { -#ifdef WORDS_BIGENDIAN - u_char ip_v:4, - ip_hl:4; -#else - u_char ip_hl:4, - ip_v:4; -#endif - /* BUG : u_int changed to u_int8_t. - * sizeof(u_int)==4 on linux 2.0 - */ - u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit - * to avoid destroying tos (PPPDTRuu); - * copied from (ip_off&IP_MF) */ - u_int16_t ip_len; - u_int16_t ip_id; - u_int16_t ip_off; - u_int8_t ip_ttl; - u_int8_t ip_p; - u_int16_t ip_sum; - ipasfragp_32 ipf_next; /* next fragment */ - ipasfragp_32 ipf_prev; /* previous fragment */ -}; - -/* - * Structure stored in mbuf in inpcb.ip_options - * and passed to ip_output when ip options are in use. - * The actual length of the options (including ipopt_dst) - * is in m_len. - */ -#define MAX_IPOPTLEN 40 - -struct ipoption { - struct in_addr ipopt_dst; /* first-hop dst if source routed */ - int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ -}; - -/* - * Structure attached to inpcb.ip_moptions and - * passed to ip_output when IP multicast options are in use. - */ - -struct ipstat { - u_long ips_total; /* total packets received */ - u_long ips_badsum; /* checksum bad */ - u_long ips_tooshort; /* packet too short */ - u_long ips_toosmall; /* not enough data */ - u_long ips_badhlen; /* ip header length < data size */ - u_long ips_badlen; /* ip length < ip header length */ - u_long ips_fragments; /* fragments received */ - u_long ips_fragdropped; /* frags dropped (dups, out of space) */ - u_long ips_fragtimeout; /* fragments timed out */ - u_long ips_forward; /* packets forwarded */ - u_long ips_cantforward; /* packets rcvd for unreachable dest */ - u_long ips_redirectsent; /* packets forwarded on same net */ - u_long ips_noproto; /* unknown or unsupported protocol */ - u_long ips_delivered; /* datagrams delivered to upper level*/ - u_long ips_localout; /* total ip packets generated here */ - u_long ips_odropped; /* lost packets due to nobufs, etc. */ - u_long ips_reassembled; /* total packets reassembled ok */ - u_long ips_fragmented; /* datagrams successfully fragmented */ - u_long ips_ofragments; /* output fragments created */ - u_long ips_cantfrag; /* don't fragment flag was set, etc. */ - u_long ips_badoptions; /* error in option processing */ - u_long ips_noroute; /* packets discarded due to no route */ - u_long ips_badvers; /* ip version != 4 */ - u_long ips_rawout; /* total raw ip packets generated */ - u_long ips_unaligned; /* times the ip packet was not aligned */ -}; - -extern struct ipstat ipstat; -extern struct ipq ipq; /* ip reass. queue */ -extern u_int16_t ip_id; /* ip packet ctr, for ids */ -extern int ip_defttl; /* default IP ttl */ - -#endif diff --git a/BasiliskII/src/slirp/ip_icmp.c b/BasiliskII/src/slirp/ip_icmp.c deleted file mode 100644 index 75a4614a..00000000 --- a/BasiliskII/src/slirp/ip_icmp.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 - * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp - */ - -#include "slirp.h" -#include "ip_icmp.h" - -struct icmpstat icmpstat; - -/* The message sent when emulating PING */ -/* Be nice and tell them it's just a psuedo-ping packet */ -char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; - -/* list of actions for icmp_error() on RX of an icmp message */ -static int icmp_flush[19] = { -/* ECHO REPLY (0) */ 0, - 1, - 1, -/* DEST UNREACH (3) */ 1, -/* SOURCE QUENCH (4)*/ 1, -/* REDIRECT (5) */ 1, - 1, - 1, -/* ECHO (8) */ 0, -/* ROUTERADVERT (9) */ 1, -/* ROUTERSOLICIT (10) */ 1, -/* TIME EXCEEDED (11) */ 1, -/* PARAMETER PROBLEM (12) */ 1, -/* TIMESTAMP (13) */ 0, -/* TIMESTAMP REPLY (14) */ 0, -/* INFO (15) */ 0, -/* INFO REPLY (16) */ 0, -/* ADDR MASK (17) */ 0, -/* ADDR MASK REPLY (18) */ 0 -}; - -/* - * Process a received ICMP message. - */ -void -icmp_input(m, hlen) - struct mbuf *m; - int hlen; -{ - register struct icmp *icp; - register struct ip *ip=mtod(m, struct ip *); - int icmplen=ip->ip_len; - /* int code; */ - - DEBUG_CALL("icmp_input"); - DEBUG_ARG("m = %lx", (long )m); - DEBUG_ARG("m_len = %d", m->m_len); - - icmpstat.icps_received++; - - /* - * Locate icmp structure in mbuf, and check - * that its not corrupted and of at least minimum length. - */ - if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ - icmpstat.icps_tooshort++; - freeit: - m_freem(m); - goto end_error; - } - - m->m_len -= hlen; - m->m_data += hlen; - icp = mtod(m, struct icmp *); - if (cksum(m, icmplen)) { - icmpstat.icps_checksum++; - goto freeit; - } - m->m_len += hlen; - m->m_data -= hlen; - - /* icmpstat.icps_inhist[icp->icmp_type]++; */ - /* code = icp->icmp_code; */ - - DEBUG_ARG("icmp_type = %d", icp->icmp_type); - switch (icp->icmp_type) { - case ICMP_ECHO: - icp->icmp_type = ICMP_ECHOREPLY; - ip->ip_len += hlen; /* since ip_input subtracts this */ - if (ip->ip_dst.s_addr == alias_addr.s_addr) { - icmp_reflect(m); - } else { - struct socket *so; - struct sockaddr_in addr; - if ((so = socreate()) == NULL) goto freeit; - if(udp_attach(so) == -1) { - DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", - errno,strerror(errno))); - sofree(so); - m_free(m); - goto end_error; - } - so->so_m = m; - so->so_faddr = ip->ip_dst; - so->so_fport = htons(7); - so->so_laddr = ip->ip_src; - so->so_lport = htons(9); - so->so_iptos = ip->ip_tos; - so->so_type = IPPROTO_ICMP; - so->so_state = SS_ISFCONNECTED; - - /* Send the packet */ - addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { - /* It's an alias */ - switch(ntohl(so->so_faddr.s_addr) & 0xff) { - case CTL_DNS: - addr.sin_addr = dns_addr; - break; - case CTL_ALIAS: - default: - addr.sin_addr = loopback_addr; - break; - } - } else { - addr.sin_addr = so->so_faddr; - } - addr.sin_port = so->so_fport; - if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, - (struct sockaddr *)&addr, sizeof(addr)) == -1) { - DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", - errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); - udp_detach(so); - } - } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ - break; - case ICMP_UNREACH: - /* XXX? report error? close socket? */ - case ICMP_TIMXCEED: - case ICMP_PARAMPROB: - case ICMP_SOURCEQUENCH: - case ICMP_TSTAMP: - case ICMP_MASKREQ: - case ICMP_REDIRECT: - icmpstat.icps_notsupp++; - m_freem(m); - break; - - default: - icmpstat.icps_badtype++; - m_freem(m); - } /* swith */ - -end_error: - /* m is m_free()'d xor put in a socket xor or given to ip_send */ - return; -} - - -/* - * Send an ICMP message in response to a situation - * - * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do). - * MUST NOT change this header information. - * MUST NOT reply to a multicast/broadcast IP address. - * MUST NOT reply to a multicast/broadcast MAC address. - * MUST reply to only the first fragment. - */ -/* - * Send ICMP_UNREACH back to the source regarding msrc. - * mbuf *msrc is used as a template, but is NOT m_free()'d. - * It is reported as the bad ip packet. The header should - * be fully correct and in host byte order. - * ICMP fragmentation is illegal. All machines must accept 576 bytes in one - * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548 - */ - -#define ICMP_MAXDATALEN (IP_MSS-28) -void -icmp_error(msrc, type, code, minsize, message) - struct mbuf *msrc; - u_char type; - u_char code; - int minsize; - char *message; -{ - unsigned hlen, shlen, s_ip_len; - register struct ip *ip; - register struct icmp *icp; - register struct mbuf *m; - - DEBUG_CALL("icmp_error"); - DEBUG_ARG("msrc = %lx", (long )msrc); - DEBUG_ARG("msrc_len = %d", msrc->m_len); - - if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error; - - /* check msrc */ - if(!msrc) goto end_error; - ip = mtod(msrc, struct ip *); -#if DEBUG - { char bufa[INET_ADDRSTRLEN], bufb[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &ip->ip_src, bufa, sizeof(bufa)); - inet_ntop(AF_INET, &ip->ip_dst, bufb, sizeof(bufb)); - DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb)); - } -#endif - if(ip->ip_off & IP_OFFMASK) goto end_error; /* Only reply to fragment 0 */ - - shlen=ip->ip_hl << 2; - s_ip_len=ip->ip_len; - if(ip->ip_p == IPPROTO_ICMP) { - icp = (struct icmp *)((char *)ip + shlen); - /* - * Assume any unknown ICMP type is an error. This isn't - * specified by the RFC, but think about it.. - */ - if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error; - } - - /* make a copy */ - if(!(m=m_get())) goto end_error; /* get mbuf */ - { u_int new_m_size; - new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; - if(new_m_size>m->m_size) m_inc(m, new_m_size); - } - memcpy(m->m_data, msrc->m_data, msrc->m_len); - m->m_len = msrc->m_len; /* copy msrc to m */ - - /* make the header of the reply packet */ - ip = mtod(m, struct ip *); - hlen= sizeof(struct ip ); /* no options in reply */ - - /* fill in icmp */ - m->m_data += hlen; - m->m_len -= hlen; - - icp = mtod(m, struct icmp *); - - if(minsize) s_ip_len=shlen+ICMP_MINLEN; /* return header+8b only */ - else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */ - s_ip_len=ICMP_MAXDATALEN; - - m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */ - - /* min. size = 8+sizeof(struct ip)+8 */ - - icp->icmp_type = type; - icp->icmp_code = code; - icp->icmp_id = 0; - icp->icmp_seq = 0; - - memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */ - HTONS(icp->icmp_ip.ip_len); - HTONS(icp->icmp_ip.ip_id); - HTONS(icp->icmp_ip.ip_off); - -#if DEBUG - if(message) { /* DEBUG : append message to ICMP packet */ - int message_len; - char *cpnt; - message_len=strlen(message); - if(message_len>ICMP_MAXDATALEN) message_len=ICMP_MAXDATALEN; - cpnt=(char *)m->m_data+m->m_len; - memcpy(cpnt, message, message_len); - m->m_len+=message_len; - } -#endif - - icp->icmp_cksum = 0; - icp->icmp_cksum = cksum(m, m->m_len); - - m->m_data -= hlen; - m->m_len += hlen; - - /* fill in ip */ - ip->ip_hl = hlen >> 2; - ip->ip_len = (u_int16_t)m->m_len; - - ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ - - ip->ip_ttl = MAXTTL; - ip->ip_p = IPPROTO_ICMP; - ip->ip_dst = ip->ip_src; /* ip adresses */ - ip->ip_src = alias_addr; - - (void ) ip_output((struct socket *)NULL, m); - - icmpstat.icps_reflect++; - -end_error: - return; -} -#undef ICMP_MAXDATALEN - -/* - * Reflect the ip packet back to the source - */ -void -icmp_reflect(m) - struct mbuf *m; -{ - register struct ip *ip = mtod(m, struct ip *); - int hlen = ip->ip_hl << 2; - int optlen = hlen - sizeof(struct ip ); - register struct icmp *icp; - - /* - * Send an icmp packet back to the ip level, - * after supplying a checksum. - */ - m->m_data += hlen; - m->m_len -= hlen; - icp = mtod(m, struct icmp *); - - icp->icmp_cksum = 0; - icp->icmp_cksum = cksum(m, ip->ip_len - hlen); - - m->m_data -= hlen; - m->m_len += hlen; - - /* fill in ip */ - if (optlen > 0) { - /* - * Strip out original options by copying rest of first - * mbuf's data back, and adjust the IP length. - */ - memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen, - (unsigned )(m->m_len - hlen)); - hlen -= optlen; - ip->ip_hl = hlen >> 2; - ip->ip_len -= optlen; - m->m_len -= optlen; - } - - ip->ip_ttl = MAXTTL; - { /* swap */ - struct in_addr icmp_dst; - icmp_dst = ip->ip_dst; - ip->ip_dst = ip->ip_src; - ip->ip_src = icmp_dst; - } - - (void ) ip_output((struct socket *)NULL, m); - - icmpstat.icps_reflect++; -} diff --git a/BasiliskII/src/slirp/ip_icmp.h b/BasiliskII/src/slirp/ip_icmp.h deleted file mode 100644 index 683dc87f..00000000 --- a/BasiliskII/src/slirp/ip_icmp.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 - * ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp - */ - -#ifndef _NETINET_IP_ICMP_H_ -#define _NETINET_IP_ICMP_H_ - -/* - * Interface Control Message Protocol Definitions. - * Per RFC 792, September 1981. - */ - -typedef u_int32_t n_time; - -/* - * Structure of an icmp header. - */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct icmp { - u_char icmp_type; /* type of message, see below */ - u_char icmp_code; /* type sub code */ - u_short icmp_cksum; /* ones complement cksum of struct */ - union { - u_char ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ - struct ih_idseq { - u_short icd_id; - u_short icd_seq; - } ih_idseq; - int ih_void; - - /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ - struct ih_pmtu { - u_short ipm_void; - u_short ipm_nextmtu; - } ih_pmtu; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void -#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void -#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu - union { - struct id_ts { - n_time its_otime; - n_time its_rtime; - n_time its_ttime; - } id_ts; - struct id_ip { - struct ip idi_ip; - /* options and then 64 bits of data */ - } id_ip; - uint32_t id_mask; - char id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -/* - * Lower bounds on packet lengths for various types. - * For the error advice packets must first insure that the - * packet is large enought to contain the returned ip header. - * Only then can we do the check to see if 64 bits of packet - * data have been returned, since we need to check the returned - * ip header length. - */ -#define ICMP_MINLEN 8 /* abs minimum */ -#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ -#define ICMP_MASKLEN 12 /* address mask */ -#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ -#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) - /* N.B.: must separately check that ip_hl >= 5 */ - -/* - * Definition of type and code field values. - */ -#define ICMP_ECHOREPLY 0 /* echo reply */ -#define ICMP_UNREACH 3 /* dest unreachable, codes: */ -#define ICMP_UNREACH_NET 0 /* bad net */ -#define ICMP_UNREACH_HOST 1 /* bad host */ -#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ -#define ICMP_UNREACH_PORT 3 /* bad port */ -#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ -#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ -#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ -#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ -#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ -#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ -#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ -#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ -#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ -#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ -#define ICMP_REDIRECT 5 /* shorter route, codes: */ -#define ICMP_REDIRECT_NET 0 /* for network */ -#define ICMP_REDIRECT_HOST 1 /* for host */ -#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ -#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ -#define ICMP_ECHO 8 /* echo service */ -#define ICMP_ROUTERADVERT 9 /* router advertisement */ -#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ -#define ICMP_TIMXCEED 11 /* time exceeded, code: */ -#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ -#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ -#define ICMP_PARAMPROB 12 /* ip header bad */ -#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ -#define ICMP_TSTAMP 13 /* timestamp request */ -#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ -#define ICMP_IREQ 15 /* information request */ -#define ICMP_IREQREPLY 16 /* information reply */ -#define ICMP_MASKREQ 17 /* address mask request */ -#define ICMP_MASKREPLY 18 /* address mask reply */ - -#define ICMP_MAXTYPE 18 - -#define ICMP_INFOTYPE(type) \ - ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ - (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ - (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ - (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ - (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) - -void icmp_input(struct mbuf *, int); -void icmp_error(struct mbuf *, u_char, u_char, int, char *); -void icmp_reflect(struct mbuf *); - -#endif diff --git a/BasiliskII/src/slirp/ip_input.c b/BasiliskII/src/slirp/ip_input.c deleted file mode 100644 index d9426997..00000000 --- a/BasiliskII/src/slirp/ip_input.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp - */ - -/* - * Changes and additions relating to SLiRP are - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include -#include "ip_icmp.h" - -int ip_defttl; -struct ipstat ipstat; -struct ipq ipq; - -/* - * IP initialization: fill in IP protocol switch table. - * All protocols not implemented in kernel go to raw IP protocol handler. - */ -void -ip_init() -{ - ipq.next = ipq.prev = (ipqp_32)&ipq; - ip_id = tt.tv_sec & 0xffff; - udp_init(); - tcp_init(); - ip_defttl = IPDEFTTL; -} - -/* - * Ip input routine. Checksum and byte swap header. If fragmented - * try to reassemble. Process options. Pass to next level. - */ -void -ip_input(m) - struct mbuf *m; -{ - register struct ip *ip; - u_int hlen; - - DEBUG_CALL("ip_input"); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("m_len = %d", m->m_len); - - ipstat.ips_total++; - - if (m->m_len < sizeof (struct ip)) { - ipstat.ips_toosmall++; - return; - } - - ip = mtod(m, struct ip *); - - if (ip->ip_v != IPVERSION) { - ipstat.ips_badvers++; - goto bad; - } - - hlen = ip->ip_hl << 2; - if (hlenm->m_len) {/* min header length */ - ipstat.ips_badhlen++; /* or packet too short */ - goto bad; - } - - /* keep ip header intact for ICMP reply - * ip->ip_sum = cksum(m, hlen); - * if (ip->ip_sum) { - */ - if(cksum(m,hlen)) { - ipstat.ips_badsum++; - goto bad; - } - - /* - * Convert fields to host representation. - */ - NTOHS(ip->ip_len); - if (ip->ip_len < hlen) { - ipstat.ips_badlen++; - goto bad; - } - NTOHS(ip->ip_id); - NTOHS(ip->ip_off); - - /* - * Check that the amount of data in the buffers - * is as at least much as the IP header would have us expect. - * Trim mbufs if longer than we expect. - * Drop packet if shorter than we expect. - */ - if (m->m_len < ip->ip_len) { - ipstat.ips_tooshort++; - goto bad; - } - /* Should drop packet if mbuf too long? hmmm... */ - if (m->m_len > ip->ip_len) - m_adj(m, ip->ip_len - m->m_len); - - /* check ip_ttl for a correct ICMP reply */ - if(ip->ip_ttl==0 || ip->ip_ttl==1) { - icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); - goto bad; - } - - /* - * Process options and, if not destined for us, - * ship it on. ip_dooptions returns 1 when an - * error was detected (causing an icmp message - * to be sent and the original packet to be freed). - */ -/* We do no IP options */ -/* if (hlen > sizeof (struct ip) && ip_dooptions(m)) - * goto next; - */ - /* - * If offset or IP_MF are set, must reassemble. - * Otherwise, nothing need be done. - * (We could look in the reassembly queue to see - * if the packet was previously fragmented, - * but it's not worth the time; just let them time out.) - * - * XXX This should fail, don't fragment yet - */ - if (ip->ip_off &~ IP_DF) { - register struct ipq *fp; - /* - * Look for queue of fragments - * of this datagram. - */ - for (fp = (struct ipq *) ipq.next; fp != &ipq; - fp = (struct ipq *) fp->next) - if (ip->ip_id == fp->ipq_id && - ip->ip_src.s_addr == fp->ipq_src.s_addr && - ip->ip_dst.s_addr == fp->ipq_dst.s_addr && - ip->ip_p == fp->ipq_p) - goto found; - fp = 0; - found: - - /* - * Adjust ip_len to not reflect header, - * set ip_mff if more fragments are expected, - * convert offset of this to bytes. - */ - ip->ip_len -= hlen; - if (ip->ip_off & IP_MF) - ((struct ipasfrag *)ip)->ipf_mff |= 1; - else - ((struct ipasfrag *)ip)->ipf_mff &= ~1; - - ip->ip_off <<= 3; - - /* - * If datagram marked as having more fragments - * or if this is not the first fragment, - * attempt reassembly; if it succeeds, proceed. - */ - if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { - ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp); - if (ip == 0) - return; - ipstat.ips_reassembled++; - m = dtom(ip); - } else - if (fp) - ip_freef(fp); - - } else - ip->ip_len -= hlen; - - /* - * Switch out to protocol's input routine. - */ - ipstat.ips_delivered++; - switch (ip->ip_p) { - case IPPROTO_TCP: - tcp_input(m, hlen, (struct socket *)NULL); - break; - case IPPROTO_UDP: - udp_input(m, hlen); - break; - case IPPROTO_ICMP: - icmp_input(m, hlen); - break; - default: - ipstat.ips_noproto++; - m_free(m); - } - return; -bad: - m_freem(m); - return; -} - -/* - * Take incoming datagram fragment and try to - * reassemble it into whole datagram. If a chain for - * reassembly of this datagram already exists, then it - * is given as fp; otherwise have to make a chain. - */ -struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; -{ - register struct mbuf *m = dtom(ip); - register struct ipasfrag *q; - int hlen = ip->ip_hl << 2; - int i, next; - - DEBUG_CALL("ip_reass"); - DEBUG_ARG("ip = %lx", (long)ip); - DEBUG_ARG("fp = %lx", (long)fp); - DEBUG_ARG("m = %lx", (long)m); - - /* - * Presence of header sizes in mbufs - * would confuse code below. - * Fragment m_data is concatenated. - */ - m->m_data += hlen; - m->m_len -= hlen; - - /* - * If first fragment to arrive, create a reassembly queue. - */ - if (fp == 0) { - struct mbuf *t; - if ((t = m_get()) == NULL) goto dropfrag; - fp = mtod(t, struct ipq *); - insque_32(fp, &ipq); - fp->ipq_ttl = IPFRAGTTL; - fp->ipq_p = ip->ip_p; - fp->ipq_id = ip->ip_id; - fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp; - fp->ipq_src = ((struct ip *)ip)->ip_src; - fp->ipq_dst = ((struct ip *)ip)->ip_dst; - q = (struct ipasfrag *)fp; - goto insert; - } - - /* - * Find a segment which begins after this one does. - */ - for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; - q = (struct ipasfrag *)q->ipf_next) - if (q->ip_off > ip->ip_off) - break; - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if (q->ipf_prev != (ipasfragp_32)fp) { - i = ((struct ipasfrag *)(q->ipf_prev))->ip_off + - ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off; - if (i > 0) { - if (i >= ip->ip_len) - goto dropfrag; - m_adj(dtom(ip), i); - ip->ip_off += i; - ip->ip_len -= i; - } - } - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { - i = (ip->ip_off + ip->ip_len) - q->ip_off; - if (i < q->ip_len) { - q->ip_len -= i; - q->ip_off += i; - m_adj(dtom(q), i); - break; - } - q = (struct ipasfrag *) q->ipf_next; - m_freem(dtom((struct ipasfrag *) q->ipf_prev)); - ip_deq((struct ipasfrag *) q->ipf_prev); - } - -insert: - /* - * Stick new segment in its place; - * check for complete reassembly. - */ - ip_enq(ip, (struct ipasfrag *) q->ipf_prev); - next = 0; - for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; - q = (struct ipasfrag *) q->ipf_next) { - if (q->ip_off != next) - return (0); - next += q->ip_len; - } - if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1) - return (0); - - /* - * Reassembly is complete; concatenate fragments. - */ - q = (struct ipasfrag *) fp->ipq_next; - m = dtom(q); - - q = (struct ipasfrag *) q->ipf_next; - while (q != (struct ipasfrag *)fp) { - struct mbuf *t; - t = dtom(q); - q = (struct ipasfrag *) q->ipf_next; - m_cat(m, t); - } - - /* - * Create header for new ip packet by - * modifying header of first packet; - * dequeue and discard fragment reassembly header. - * Make header visible. - */ - ip = (struct ipasfrag *) fp->ipq_next; - - /* - * If the fragments concatenated to an mbuf that's - * bigger than the total size of the fragment, then and - * m_ext buffer was alloced. But fp->ipq_next points to - * the old buffer (in the mbuf), so we must point ip - * into the new buffer. - */ - if (m->m_flags & M_EXT) { - int delta; - delta = (char *)ip - m->m_dat; - ip = (struct ipasfrag *)(m->m_ext + delta); - } - - /* DEBUG_ARG("ip = %lx", (long)ip); - * ip=(struct ipasfrag *)m->m_data; */ - - ip->ip_len = next; - ip->ipf_mff &= ~1; - ((struct ip *)ip)->ip_src = fp->ipq_src; - ((struct ip *)ip)->ip_dst = fp->ipq_dst; - remque_32(fp); - (void) m_free(dtom(fp)); - m = dtom(ip); - m->m_len += (ip->ip_hl << 2); - m->m_data -= (ip->ip_hl << 2); - - return ((struct ip *)ip); - -dropfrag: - ipstat.ips_fragdropped++; - m_freem(m); - return (0); -} - -/* - * Free a fragment reassembly header and all - * associated datagrams. - */ -void -ip_freef(fp) - struct ipq *fp; -{ - register struct ipasfrag *q, *p; - - for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; - q = p) { - p = (struct ipasfrag *) q->ipf_next; - ip_deq(q); - m_freem(dtom(q)); - } - remque_32(fp); - (void) m_free(dtom(fp)); -} - -/* - * Put an ip fragment on a reassembly chain. - * Like insque, but pointers in middle of structure. - */ -void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; -{ - DEBUG_CALL("ip_enq"); - DEBUG_ARG("prev = %lx", (long)prev); - p->ipf_prev = (ipasfragp_32) prev; - p->ipf_next = prev->ipf_next; - ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; - prev->ipf_next = (ipasfragp_32) p; -} - -/* - * To ip_enq as remque is to insque. - */ -void -ip_deq(p) - register struct ipasfrag *p; -{ - ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; - ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; -} - -/* - * IP timer processing; - * if a timer expires on a reassembly - * queue, discard it. - */ -void -ip_slowtimo() -{ - register struct ipq *fp; - - DEBUG_CALL("ip_slowtimo"); - - fp = (struct ipq *) ipq.next; - if (fp == 0) - return; - - while (fp != &ipq) { - --fp->ipq_ttl; - fp = (struct ipq *) fp->next; - if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { - ipstat.ips_fragtimeout++; - ip_freef((struct ipq *) fp->prev); - } - } -} - -/* - * Do option processing on a datagram, - * possibly discarding it if bad options are encountered, - * or forwarding it if source-routed. - * Returns 1 if packet has been forwarded/freed, - * 0 if the packet should be processed further. - */ - -#ifdef notdef - -int -ip_dooptions(m) - struct mbuf *m; -{ - register struct ip *ip = mtod(m, struct ip *); - register u_char *cp; - register struct ip_timestamp *ipt; - register struct in_ifaddr *ia; -/* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */ - int opt, optlen, cnt, off, code, type, forward = 0; - struct in_addr *sin, dst; -typedef u_int32_t n_time; - n_time ntime; - - dst = ip->ip_dst; - cp = (u_char *)(ip + 1); - cnt = (ip->ip_hl << 2) - sizeof (struct ip); - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[IPOPT_OPTVAL]; - if (opt == IPOPT_EOL) - break; - if (opt == IPOPT_NOP) - optlen = 1; - else { - optlen = cp[IPOPT_OLEN]; - if (optlen <= 0 || optlen > cnt) { - code = &cp[IPOPT_OLEN] - (u_char *)ip; - goto bad; - } - } - switch (opt) { - - default: - break; - - /* - * Source routing with record. - * Find interface with current destination address. - * If none on this machine then drop if strictly routed, - * or do nothing if loosely routed. - * Record interface address and bring up next address - * component. If strictly routed make sure next - * address is on directly accessible net. - */ - case IPOPT_LSRR: - case IPOPT_SSRR: - if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { - code = &cp[IPOPT_OFFSET] - (u_char *)ip; - goto bad; - } - ipaddr.sin_addr = ip->ip_dst; - ia = (struct in_ifaddr *) - ifa_ifwithaddr((struct sockaddr *)&ipaddr); - if (ia == 0) { - if (opt == IPOPT_SSRR) { - type = ICMP_UNREACH; - code = ICMP_UNREACH_SRCFAIL; - goto bad; - } - /* - * Loose routing, and not at next destination - * yet; nothing to do except forward. - */ - break; - } - off--; / * 0 origin * / - if (off > optlen - sizeof(struct in_addr)) { - /* - * End of source route. Should be for us. - */ - save_rte(cp, ip->ip_src); - break; - } - /* - * locate outgoing interface - */ - bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, - sizeof(ipaddr.sin_addr)); - if (opt == IPOPT_SSRR) { -#define INA struct in_ifaddr * -#define SA struct sockaddr * - if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) - ia = (INA)ifa_ifwithnet((SA)&ipaddr); - } else - ia = ip_rtaddr(ipaddr.sin_addr); - if (ia == 0) { - type = ICMP_UNREACH; - code = ICMP_UNREACH_SRCFAIL; - goto bad; - } - ip->ip_dst = ipaddr.sin_addr; - bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), - (caddr_t)(cp + off), sizeof(struct in_addr)); - cp[IPOPT_OFFSET] += sizeof(struct in_addr); - /* - * Let ip_intr's mcast routing check handle mcast pkts - */ - forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); - break; - - case IPOPT_RR: - if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { - code = &cp[IPOPT_OFFSET] - (u_char *)ip; - goto bad; - } - /* - * If no space remains, ignore. - */ - off--; * 0 origin * - if (off > optlen - sizeof(struct in_addr)) - break; - bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, - sizeof(ipaddr.sin_addr)); - /* - * locate outgoing interface; if we're the destination, - * use the incoming interface (should be same). - */ - if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && - (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { - type = ICMP_UNREACH; - code = ICMP_UNREACH_HOST; - goto bad; - } - bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), - (caddr_t)(cp + off), sizeof(struct in_addr)); - cp[IPOPT_OFFSET] += sizeof(struct in_addr); - break; - - case IPOPT_TS: - code = cp - (u_char *)ip; - ipt = (struct ip_timestamp *)cp; - if (ipt->ipt_len < 5) - goto bad; - if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) { - if (++ipt->ipt_oflw == 0) - goto bad; - break; - } - sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); - switch (ipt->ipt_flg) { - - case IPOPT_TS_TSONLY: - break; - - case IPOPT_TS_TSANDADDR: - if (ipt->ipt_ptr + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) - goto bad; - ipaddr.sin_addr = dst; - ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr, - m->m_pkthdr.rcvif); - if (ia == 0) - continue; - bcopy((caddr_t)&IA_SIN(ia)->sin_addr, - (caddr_t)sin, sizeof(struct in_addr)); - ipt->ipt_ptr += sizeof(struct in_addr); - break; - - case IPOPT_TS_PRESPEC: - if (ipt->ipt_ptr + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) - goto bad; - bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, - sizeof(struct in_addr)); - if (ifa_ifwithaddr((SA)&ipaddr) == 0) - continue; - ipt->ipt_ptr += sizeof(struct in_addr); - break; - - default: - goto bad; - } - ntime = iptime(); - bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, - sizeof(n_time)); - ipt->ipt_ptr += sizeof(n_time); - } - } - if (forward) { - ip_forward(m, 1); - return (1); - } - } - } - return (0); -bad: - /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */ - -/* Not yet */ - icmp_error(m, type, code, 0, 0); - - ipstat.ips_badoptions++; - return (1); -} - -#endif /* notdef */ - -/* - * Strip out IP options, at higher - * level protocol in the kernel. - * Second argument is buffer to which options - * will be moved, and return value is their length. - * (XXX) should be deleted; last arg currently ignored. - */ -void -ip_stripoptions(m, mopt) - register struct mbuf *m; - struct mbuf *mopt; -{ - register int i; - struct ip *ip = mtod(m, struct ip *); - register caddr_t opts; - int olen; - - olen = (ip->ip_hl<<2) - sizeof (struct ip); - opts = (caddr_t)(ip + 1); - i = m->m_len - (sizeof (struct ip) + olen); - memcpy(opts, opts + olen, (unsigned)i); - m->m_len -= olen; - - ip->ip_hl = sizeof(struct ip) >> 2; -} diff --git a/BasiliskII/src/slirp/ip_output.c b/BasiliskII/src/slirp/ip_output.c deleted file mode 100644 index fb9a9420..00000000 --- a/BasiliskII/src/slirp/ip_output.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 - * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp - */ - -/* - * Changes and additions relating to SLiRP are - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include - -u_int16_t ip_id; - -/* - * IP output. The packet in mbuf chain m contains a skeletal IP - * header (with len, off, ttl, proto, tos, src, dst). - * The mbuf chain containing the packet will be freed. - * The mbuf opt, if present, will not be freed. - */ -int -ip_output(so, m0) - struct socket *so; - struct mbuf *m0; -{ - register struct ip *ip; - register struct mbuf *m = m0; - register u_int hlen = sizeof(struct ip); - u_int len, off; - int error = 0; - - DEBUG_CALL("ip_output"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("m0 = %lx", (long)m0); - - /* We do no options */ -/* if (opt) { - * m = ip_insertoptions(m, opt, &len); - * hlen = len; - * } - */ - ip = mtod(m, struct ip *); - /* - * Fill in IP header. - */ - ip->ip_v = IPVERSION; - ip->ip_off &= IP_DF; - ip->ip_id = htons(ip_id++); - ip->ip_hl = hlen >> 2; - ipstat.ips_localout++; - - /* - * Verify that we have any chance at all of being able to queue - * the packet or packet fragments - */ - /* XXX Hmmm... */ -/* if (if_queued > if_thresh && towrite <= 0) { - * error = ENOBUFS; - * goto bad; - * } - */ - - /* - * If small enough for interface, can just send directly. - */ - if ((u_int16_t)ip->ip_len <= if_mtu) { - ip->ip_len = htons((u_int16_t)ip->ip_len); - ip->ip_off = htons((u_int16_t)ip->ip_off); - ip->ip_sum = 0; - ip->ip_sum = cksum(m, hlen); - - if_output(so, m); - goto done; - } - - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - if (ip->ip_off & IP_DF) { - error = -1; - ipstat.ips_cantfrag++; - goto bad; - } - - len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ - if (len < 8) { - error = -1; - goto bad; - } - - { - int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_nextpkt; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { - register struct ip *mhip; - m = m_get(); - if (m == 0) { - error = -1; - ipstat.ips_odropped++; - goto sendorfree; - } - m->m_data += if_maxlinkhdr; - mhip = mtod(m, struct ip *); - *mhip = *ip; - - /* No options */ -/* if (hlen > sizeof (struct ip)) { - * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); - * mhip->ip_hl = mhlen >> 2; - * } - */ - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); - if (ip->ip_off & IP_MF) - mhip->ip_off |= IP_MF; - if (off + len >= (u_int16_t)ip->ip_len) - len = (u_int16_t)ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((u_int16_t)(len + mhlen)); - - if (m_copy(m, m0, off, len) < 0) { - error = -1; - goto sendorfree; - } - - mhip->ip_off = htons((u_int16_t)mhip->ip_off); - mhip->ip_sum = 0; - mhip->ip_sum = cksum(m, mhlen); - *mnext = m; - mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m = m0; - m_adj(m, hlen + firstlen - ip->ip_len); - ip->ip_len = htons((u_int16_t)m->m_len); - ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = cksum(m, hlen); -sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_nextpkt; - m->m_nextpkt = 0; - if (error == 0) - if_output(so, m); - else - m_freem(m); - } - - if (error == 0) - ipstat.ips_fragmented++; - } - -done: - return (error); - -bad: - m_freem(m0); - goto done; -} diff --git a/BasiliskII/src/slirp/libslirp.h b/BasiliskII/src/slirp/libslirp.h deleted file mode 100644 index 8a1aa31e..00000000 --- a/BasiliskII/src/slirp/libslirp.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _LIBSLIRP_H -#define _LIBSLIRP_H - -#ifdef _WIN32 -#include -int inet_aton(const char *cp, struct in_addr *ia); -#else -#include -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -int slirp_init(void); - -int slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds); - -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds); - -void slirp_input(const uint8 *pkt, int pkt_len); - -/* you must provide the following functions: */ -int slirp_can_output(void); -void slirp_output(const uint8 *pkt, int pkt_len); - -int slirp_redir(int is_udp, int host_port, - struct in_addr guest_addr, int guest_port); -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, - int guest_port); - -extern const char *tftp_prefix; -extern char slirp_hostname[33]; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/BasiliskII/src/slirp/main.h b/BasiliskII/src/slirp/main.h deleted file mode 100644 index 181b6ae8..00000000 --- a/BasiliskII/src/slirp/main.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#ifdef HAVE_SYS_SELECT_H -#include -#endif - -#define TOWRITEMAX 512 - -extern struct timeval tt; -extern int link_up; -extern int slirp_socket; -extern int slirp_socket_unit; -extern int slirp_socket_port; -extern u_int32_t slirp_socket_addr; -extern char *slirp_socket_passwd; -extern int ctty_closed; - -/* - * Get the difference in 2 times from updtim() - * Allow for wraparound times, "just in case" - * x is the greater of the 2 (current time) and y is - * what it's being compared against. - */ -#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y) - -extern char *slirp_tty; -extern char *exec_shell; -extern u_int curtime; -extern fd_set *global_readfds, *global_writefds, *global_xfds; -extern struct in_addr ctl_addr; -extern struct in_addr special_addr; -extern struct in_addr alias_addr; -extern struct in_addr our_addr; -extern struct in_addr loopback_addr; -extern struct in_addr dns_addr; -extern char *username; -extern char *socket_path; -extern int towrite_max; -extern int ppp_exit; -extern int so_options; -extern int tcp_keepintvl; -extern uint8_t client_ethaddr[6]; - -#define PROTO_SLIP 0x1 -#ifdef USE_PPP -#define PROTO_PPP 0x2 -#endif - -void if_encap(const uint8_t *ip_data, int ip_data_len); diff --git a/BasiliskII/src/slirp/mbuf.c b/BasiliskII/src/slirp/mbuf.c deleted file mode 100644 index 5a16fab8..00000000 --- a/BasiliskII/src/slirp/mbuf.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -/* - * mbuf's in SLiRP are much simpler than the real mbufs in - * FreeBSD. They are fixed size, determined by the MTU, - * so that one whole packet can fit. Mbuf's cannot be - * chained together. If there's more data than the mbuf - * could hold, an external malloced buffer is pointed to - * by m_ext (and the data pointers) and M_EXT is set in - * the flags - */ - -#include -#include - -struct mbuf *mbutl; -char *mclrefcnt; -int mbuf_alloced = 0; -struct mbuf m_freelist, m_usedlist; -int mbuf_thresh = 30; -int mbuf_max = 0; -size_t msize; - -void m_init() -{ - m_freelist.m_next = m_freelist.m_prev = &m_freelist; - m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; - msize_init(); -} - -void msize_init() -{ - /* - * Find a nice value for msize - * XXX if_maxlinkhdr already in mtu - */ - msize = (if_mtu>if_mru?if_mtu:if_mru) + - if_maxlinkhdr + sizeof(struct m_hdr ) + 6; -} - -/* - * Get an mbuf from the free list, if there are none - * malloc one - * - * Because fragmentation can occur if we alloc new mbufs and - * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, - * which tells m_free to actually free() it - */ -struct mbuf *m_get() -{ - register struct mbuf *m; - int flags = 0; - - DEBUG_CALL("m_get"); - - if (m_freelist.m_next == &m_freelist) { - m = (struct mbuf *)malloc(msize); - if (m == NULL) goto end_error; - mbuf_alloced++; - if (mbuf_alloced > mbuf_thresh) - flags = M_DOFREE; - if (mbuf_alloced > mbuf_max) - mbuf_max = mbuf_alloced; - } else { - m = m_freelist.m_next; - remque(m); - } - - /* Insert it in the used list */ - insque(m,&m_usedlist); - m->m_flags = (flags | M_USEDLIST); - - /* Initialise it */ - m->m_size = msize - sizeof(struct m_hdr); - m->m_data = m->m_dat; - m->m_len = 0; - m->m_nextpkt = 0; - m->m_prevpkt = 0; -end_error: - DEBUG_ARG("m = %lx", (long )m); - return m; -} - -void m_free(struct mbuf *m) -{ - - DEBUG_CALL("m_free"); - DEBUG_ARG("m = %lx", (long )m); - - if(m) { - /* Remove from m_usedlist */ - if (m->m_flags & M_USEDLIST) - remque(m); - - /* If it's M_EXT, free() it */ - if (m->m_flags & M_EXT) - free(m->m_ext); - - /* - * Either free() it or put it on the free list - */ - if (m->m_flags & M_DOFREE) { - free(m); - mbuf_alloced--; - } else if ((m->m_flags & M_FREELIST) == 0) { - insque(m,&m_freelist); - m->m_flags = M_FREELIST; /* Clobber other flags */ - } - } /* if(m) */ -} - -/* - * Copy data from one mbuf to the end of - * the other.. if result is too big for one mbuf, malloc() - * an M_EXT data segment - */ -void m_cat(register struct mbuf *m, register struct mbuf *n) -{ - /* - * If there's no room, realloc - */ - if (M_FREEROOM(m) < n->m_len) - m_inc(m,m->m_size+MINCSIZE); - - memcpy(m->m_data+m->m_len, n->m_data, n->m_len); - m->m_len += n->m_len; - - m_free(n); -} - - -/* make m size bytes large */ -void m_inc(struct mbuf *m, u_int size) -{ - int datasize; - - /* some compiles throw up on gotos. This one we can fake. */ - if(m->m_size>size) return; - - if (m->m_flags & M_EXT) { - datasize = m->m_data - m->m_ext; - m->m_ext = (char *)realloc(m->m_ext,size); -/* if (m->m_ext == NULL) - * return (struct mbuf *)NULL; - */ - m->m_data = m->m_ext + datasize; - } else { - char *dat; - datasize = m->m_data - m->m_dat; - dat = (char *)malloc(size); -/* if (dat == NULL) - * return (struct mbuf *)NULL; - */ - memcpy(dat, m->m_dat, m->m_size); - - m->m_ext = dat; - m->m_data = m->m_ext + datasize; - m->m_flags |= M_EXT; - } - - m->m_size = size; - -} - - - -void m_adj(struct mbuf *m, int len) -{ - if (m == NULL) - return; - if (len >= 0) { - /* Trim from head */ - m->m_data += len; - m->m_len -= len; - } else { - /* Trim from tail */ - len = -len; - m->m_len -= len; - } -} - - -/* - * Copy len bytes from m, starting off bytes into n - */ -int -m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len) -{ - if (len > M_FREEROOM(n)) - return -1; - - memcpy((n->m_data + n->m_len), (m->m_data + off), len); - n->m_len += len; - return 0; -} - - -/* - * Given a pointer into an mbuf, return the mbuf - * XXX This is a kludge, I should eliminate the need for it - * Fortunately, it's not used often - */ -struct mbuf *dtom(void *dat) -{ - struct mbuf *m; - - DEBUG_CALL("dtom"); - DEBUG_ARG("dat = %lx", (long )dat); - - /* bug corrected for M_EXT buffers */ - for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) { - if (m->m_flags & M_EXT) { - if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) - return m; - } else { - if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) ) - return m; - } - } - - DEBUG_ERROR((dfd, "dtom failed")); - - return (struct mbuf *)0; -} - diff --git a/BasiliskII/src/slirp/mbuf.h b/BasiliskII/src/slirp/mbuf.h deleted file mode 100644 index 11b252bb..00000000 --- a/BasiliskII/src/slirp/mbuf.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)mbuf.h 8.3 (Berkeley) 1/21/94 - * mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp - */ - -#ifndef _MBUF_H_ -#define _MBUF_H_ - -#define m_freem m_free - - -#define MINCSIZE 4096 /* Amount to increase mbuf if too small */ - -/* - * Macros for type conversion - * mtod(m,t) - convert mbuf pointer to data pointer of correct type - * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX) - */ -#define mtod(m,t) ((t)(m)->m_data) -/* #define dtom(x) ((struct mbuf *)((int)(x) & ~(M_SIZE-1))) */ - -/* XXX About mbufs for slirp: - * Only one mbuf is ever used in a chain, for each "cell" of data. - * m_nextpkt points to the next packet, if fragmented. - * If the data is too large, the M_EXT is used, and a larger block - * is alloced. Therefore, m_free[m] must check for M_EXT and if set - * free the m_ext. This is inefficient memory-wise, but who cares. - */ - -/* XXX should union some of these! */ -/* header at beginning of each mbuf: */ -struct m_hdr { - struct mbuf *mh_next; /* Linked list of mbufs */ - struct mbuf *mh_prev; - struct mbuf *mh_nextpkt; /* Next packet in queue/record */ - struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ - int mh_flags; /* Misc flags */ - - size_t mh_size; /* Size of data */ - struct socket *mh_so; - - caddr_t mh_data; /* Location of data */ - size_t mh_len; /* Amount of data in this mbuf */ -}; - -/* - * How much room is in the mbuf, from m_data to the end of the mbuf - */ -#define M_ROOM(m) ((m->m_flags & M_EXT)? \ - (((m)->m_ext + (m)->m_size) - (m)->m_data) \ - : \ - (((m)->m_dat + (m)->m_size) - (m)->m_data)) - -/* - * How much free room there is - */ -#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len) -#define M_TRAILINGSPACE M_FREEROOM - -struct mbuf { - struct m_hdr m_hdr; - union M_dat { - char m_dat_[1]; /* ANSI don't like 0 sized arrays */ - char *m_ext_; - } M_dat; -}; - -#define m_next m_hdr.mh_next -#define m_prev m_hdr.mh_prev -#define m_nextpkt m_hdr.mh_nextpkt -#define m_prevpkt m_hdr.mh_prevpkt -#define m_flags m_hdr.mh_flags -#define m_len m_hdr.mh_len -#define m_data m_hdr.mh_data -#define m_size m_hdr.mh_size -#define m_dat M_dat.m_dat_ -#define m_ext M_dat.m_ext_ -#define m_so m_hdr.mh_so - -#define ifq_prev m_prev -#define ifq_next m_next -#define ifs_prev m_prevpkt -#define ifs_next m_nextpkt -#define ifq_so m_so - -#define M_EXT 0x01 /* m_ext points to more (malloced) data */ -#define M_FREELIST 0x02 /* mbuf is on free list */ -#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */ -#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() - * it rather than putting it on the free list */ - -/* - * Mbuf statistics. XXX - */ - -struct mbstat { - int mbs_alloced; /* Number of mbufs allocated */ - -}; - -extern struct mbstat mbstat; -extern int mbuf_alloced; -extern struct mbuf m_freelist, m_usedlist; -extern int mbuf_max; - -void m_init(void); -void msize_init(void); -struct mbuf * m_get(void); -void m_free(struct mbuf *); -void m_cat(register struct mbuf *, register struct mbuf *); -void m_inc(struct mbuf *, u_int); -void m_adj(struct mbuf *, int); -int m_copy(struct mbuf *, struct mbuf *, u_int, u_int); -struct mbuf * dtom(void *); - -#endif diff --git a/BasiliskII/src/slirp/misc.c b/BasiliskII/src/slirp/misc.c deleted file mode 100644 index b80caf66..00000000 --- a/BasiliskII/src/slirp/misc.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#define WANT_SYS_IOCTL_H -#include -#include - -u_int curtime, time_fasttimo, last_slowtimo, detach_time; -u_int detach_wait = 600000; /* 10 minutes */ - -#if 0 -int x_port = -1; -int x_display = 0; -int x_screen = 0; - -int show_x(char *buff, struct socket *inso) -{ - if (x_port < 0) { - lprint("X Redir: X not being redirected.\r\n"); - } else { - lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n", - inet_ntoa(our_addr), x_port, x_screen); - lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n", - inet_ntoa(our_addr), x_port, x_screen); - if (x_display) - lprint("X Redir: Redirecting to display %d\r\n", x_display); - } - - return CFG_OK; -} - - -/* - * XXX Allow more than one X redirection? - */ -void redir_x(u_int32_t inaddr, int start_port, int display, int screen) -{ - int i; - - if (x_port >= 0) { - lprint("X Redir: X already being redirected.\r\n"); - show_x(0, 0); - } else { - for (i = 6001 + (start_port-1); i <= 6100; i++) { - if (solisten(htons(i), inaddr, htons(6000 + display), 0)) { - /* Success */ - x_port = i - 6000; - x_display = display; - x_screen = screen; - show_x(0, 0); - return; - } - } - lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n"); - } -} -#endif - -#ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *ia) -{ - return inet_pton(AF_INET, cp, &ia->s_addr); -} -#endif - -/* - * Get our IP address and put it in our_addr - */ -void getouraddr() -{ - char buff[256]; - - if (gethostname(buff, sizeof(buff)) == 0) - { - struct addrinfo hints = { 0 }; - hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = AF_INET; - struct addrinfo* ai; - if (getaddrinfo(buff, NULL, &hints, &ai) == 0) - { - our_addr = *(struct in_addr *)ai->ai_addr->sa_data; - freeaddrinfo(ai); - } - } - if (our_addr.s_addr == 0) - our_addr.s_addr = loopback_addr.s_addr; -} - -#if SIZEOF_CHAR_P == 8 - -struct quehead_32 { - u_int32_t qh_link; - u_int32_t qh_rlink; -}; - -inline void insque_32(void *a, void *b) -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - register struct quehead_32 *head = (struct quehead_32 *) b; - element->qh_link = head->qh_link; - head->qh_link = (u_int32_t)element; - element->qh_rlink = (u_int32_t)head; - ((struct quehead_32 *)(element->qh_link))->qh_rlink - = (u_int32_t)element; -} - -inline void remque_32(void *a) -{ - register struct quehead_32 *element = (struct quehead_32 *) a; - ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; - element->qh_rlink = 0; -} - -#endif /* SIZEOF_CHAR_P == 8 */ - -struct quehead { - struct quehead *qh_link; - struct quehead *qh_rlink; -}; - -void insque(void *a, void *b) -{ - register struct quehead *element = (struct quehead *) a; - register struct quehead *head = (struct quehead *) b; - element->qh_link = head->qh_link; - head->qh_link = (struct quehead *)element; - element->qh_rlink = (struct quehead *)head; - ((struct quehead *)(element->qh_link))->qh_rlink - = (struct quehead *)element; -} - -void remque(void *a) -{ - register struct quehead *element = (struct quehead *) a; - ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; - ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; - element->qh_rlink = NULL; - /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */ -} - -/* #endif */ - - -int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port) -{ - struct ex_list *tmp_ptr; - - /* First, check if the port is "bound" */ - for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { - if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) - return -1; - } - - tmp_ptr = *ex_ptr; - *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); - (*ex_ptr)->ex_fport = port; - (*ex_ptr)->ex_addr = addr; - (*ex_ptr)->ex_pty = do_pty; - (*ex_ptr)->ex_exec = strdup(exec); - (*ex_ptr)->ex_next = tmp_ptr; - return 0; -} - -#ifndef HAVE_STRERROR - -/* - * For systems with no strerror - */ - -extern int sys_nerr; -extern char *sys_errlist[]; - -char *strerror(int error) -{ - if (error < sys_nerr) - return sys_errlist[error]; - else - return "Unknown error."; -} - -#endif - - -#ifdef _WIN32 - -int fork_exec(struct socket *so, char *ex, int do_pty) -{ - /* not implemented */ - return 0; -} - -#else - -int slirp_openpty(int *amaster, int *aslave) -{ - register int master, slave; - -#ifdef HAVE_GRANTPT - char *ptr; - - if ((master = open("/dev/ptmx", O_RDWR)) < 0 || - grantpt(master) < 0 || - unlockpt(master) < 0 || - (ptr = ptsname(master)) == NULL) { - close(master); - return -1; - } - - if ((slave = open(ptr, O_RDWR)) < 0 || - ioctl(slave, I_PUSH, "ptem") < 0 || - ioctl(slave, I_PUSH, "ldterm") < 0 || - ioctl(slave, I_PUSH, "ttcompat") < 0) { - close(master); - close(slave); - return -1; - } - - *amaster = master; - *aslave = slave; - return 0; - -#else - - static char line[] = "/dev/ptyXX"; - register const char *cp1, *cp2; - - for (cp1 = "pqrsPQRS"; *cp1; cp1++) { - line[8] = *cp1; - for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { - line[9] = *cp2; - if ((master = open(line, O_RDWR, 0)) == -1) { - if (errno == ENOENT) - return (-1); /* out of ptys */ - } else { - line[5] = 't'; - /* These will fail */ - (void) chown(line, getuid(), 0); - (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); -#ifdef HAVE_REVOKE - (void) revoke(line); -#endif - if ((slave = open(line, O_RDWR, 0)) != -1) { - *amaster = master; - *aslave = slave; - return 0; - } - (void) close(master); - line[5] = 'p'; - } - } - } - errno = ENOENT; /* out of ptys */ - return (-1); -#endif -} - -/* - * XXX This is ugly - * We create and bind a socket, then fork off to another - * process, which connects to this socket, after which we - * exec the wanted program. If something (strange) happens, - * the accept() call could block us forever. - * - * do_pty = 0 Fork/exec inetd style - * do_pty = 1 Fork/exec using slirp.telnetd - * do_ptr = 2 Fork/exec using pty - */ -int fork_exec(struct socket *so, char *ex, int do_pty) -{ - int s; - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - int opt; - int master; - char *argv[256]; -#if 0 - char buff[256]; -#endif - /* don't want to clobber the original */ - char *bptr; - char *curarg; - int c, i, ret; - - DEBUG_CALL("fork_exec"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("ex = %lx", (long)ex); - DEBUG_ARG("do_pty = %lx", (long)do_pty); - - if (do_pty == 2) { - if (slirp_openpty(&master, &s) == -1) { - lprint("Error: openpty failed: %s\n", strerror(errno)); - return 0; - } - } else { - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = INADDR_ANY; - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || - bind(s, (struct sockaddr *)&addr, addrlen) < 0 || - listen(s, 1) < 0) { - lprint("Error: inet socket: %s\n", strerror(errno)); - closesocket(s); - - return 0; - } - } - - switch(fork()) { - case -1: - lprint("Error: fork failed: %s\n", strerror(errno)); - close(s); - if (do_pty == 2) - close(master); - return 0; - - case 0: - /* Set the DISPLAY */ - if (do_pty == 2) { - (void) close(master); -#ifdef TIOCSCTTY /* XXXXX */ - (void) setsid(); - ioctl(s, TIOCSCTTY, (char *)NULL); -#endif - } else { - getsockname(s, (struct sockaddr *)&addr, &addrlen); - close(s); - /* - * Connect to the socket - * XXX If any of these fail, we're in trouble! - */ - s = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = loopback_addr; - do { - ret = connect(s, (struct sockaddr *)&addr, addrlen); - } while (ret < 0 && errno == EINTR); - } - -#if 0 - if (x_port >= 0) { -#ifdef HAVE_SETENV - sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); - setenv("DISPLAY", buff, 1); -#else - sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); - putenv(buff); -#endif - } -#endif - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - for (s = 3; s <= 255; s++) - close(s); - - i = 0; - bptr = strdup(ex); /* No need to free() this */ - if (do_pty == 1) { - /* Setup "slirp.telnetd -x" */ - argv[i++] = "slirp.telnetd"; - argv[i++] = "-x"; - argv[i++] = bptr; - } else - do { - /* Change the string into argv[] */ - curarg = bptr; - while (*bptr != ' ' && *bptr != (char)0) - bptr++; - c = *bptr; - *bptr++ = (char)0; - argv[i++] = strdup(curarg); - } while (c); - - argv[i] = 0; - execvp(argv[0], argv); - - /* Ooops, failed, let's tell the user why */ - { - char buff[256]; - - sprintf(buff, "Error: execvp of %s failed: %s\n", - argv[0], strerror(errno)); - write(2, buff, strlen(buff)+1); - } - close(0); close(1); close(2); /* XXX */ - exit(1); - - default: - if (do_pty == 2) { - close(s); - so->s = master; - } else { - /* - * XXX this could block us... - * XXX Should set a timer here, and if accept() doesn't - * return after X seconds, declare it a failure - * The only reason this will block forever is if socket() - * of connect() fail in the child process - */ - do { - so->s = accept(s, (struct sockaddr *)&addr, &addrlen); - } while (so->s < 0 && errno == EINTR); - closesocket(s); - opt = 1; - setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); - opt = 1; - setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); - } - fd_nonblock(so->s); - - /* Append the telnet options now */ - if (so->so_m != 0 && do_pty == 1) { - sbappend(so, so->so_m); - so->so_m = 0; - } - - return 1; - } -} -#endif - -#ifndef HAVE_STRDUP -char *strdup(const char *str) -{ - char *bptr; - - bptr = (char *)malloc(strlen(str)+1); - strcpy(bptr, str); - - return bptr; -} -#endif - -#if 0 -void snooze_hup(int num) -{ - int s, ret; -#ifndef NO_UNIX_SOCKETS - struct sockaddr_un sock_un; -#endif - struct sockaddr_in sock_in; - char buff[256]; - - ret = -1; - if (slirp_socket_passwd) { - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) - slirp_exit(1); - sock_in.sin_family = AF_INET; - sock_in.sin_addr.s_addr = slirp_socket_addr; - sock_in.sin_port = htons(slirp_socket_port); - if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0) - slirp_exit(1); /* just exit...*/ - sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit); - write(s, buff, strlen(buff)+1); - } -#ifndef NO_UNIX_SOCKETS - else { - s = socket(AF_UNIX, SOCK_STREAM, 0); - if (s < 0) - slirp_exit(1); - sock_un.sun_family = AF_UNIX; - strcpy(sock_un.sun_path, socket_path); - if (connect(s, (struct sockaddr *)&sock_un, - sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0) - slirp_exit(1); - sprintf(buff, "kill none:%d", slirp_socket_unit); - write(s, buff, strlen(buff)+1); - } -#endif - slirp_exit(0); -} - - -void snooze() -{ - sigset_t s; - int i; - - /* Don't need our data anymore */ - /* XXX This makes SunOS barf */ -/* brk(0); */ - - /* Close all fd's */ - for (i = 255; i >= 0; i--) - close(i); - - signal(SIGQUIT, slirp_exit); - signal(SIGHUP, snooze_hup); - sigemptyset(&s); - - /* Wait for any signal */ - sigsuspend(&s); - - /* Just in case ... */ - exit(255); -} - -void relay(int s) -{ - char buf[8192]; - int n; - fd_set readfds; - struct ttys *ttyp; - - /* Don't need our data anymore */ - /* XXX This makes SunOS barf */ -/* brk(0); */ - - signal(SIGQUIT, slirp_exit); - signal(SIGHUP, slirp_exit); - signal(SIGINT, slirp_exit); - signal(SIGTERM, slirp_exit); - - /* Fudge to get term_raw and term_restore to work */ - if (NULL == (ttyp = tty_attach (0, slirp_tty))) { - lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); - slirp_exit (1); - } - ttyp->fd = 0; - ttyp->flags |= TTY_CTTY; - term_raw(ttyp); - - while (1) { - FD_ZERO(&readfds); - - FD_SET(0, &readfds); - FD_SET(s, &readfds); - - n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); - - if (n <= 0) - slirp_exit(0); - - if (FD_ISSET(0, &readfds)) { - n = read(0, buf, 8192); - if (n <= 0) - slirp_exit(0); - n = writen(s, buf, n); - if (n <= 0) - slirp_exit(0); - } - - if (FD_ISSET(s, &readfds)) { - n = read(s, buf, 8192); - if (n <= 0) - slirp_exit(0); - n = writen(0, buf, n); - if (n <= 0) - slirp_exit(0); - } - } - - /* Just in case.... */ - exit(1); -} -#endif - -int (*lprint_print)(void *, const char *, va_list); -char *lprint_ptr, *lprint_ptr2, **lprint_arg; - -void lprint(const char *format, ...) -{ - va_list args; - - va_start(args, format); -#if 0 - /* If we're printing to an sbuf, make sure there's enough room */ - /* XXX +100? */ - if (lprint_sb) { - if ((lprint_ptr - lprint_sb->sb_wptr) >= - (lprint_sb->sb_datalen - (strlen(format) + 100))) { - int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; - int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; - int deltap = lprint_ptr - lprint_sb->sb_data; - - lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, - lprint_sb->sb_datalen + TCP_SNDSPACE); - - /* Adjust all values */ - lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; - lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; - lprint_ptr = lprint_sb->sb_data + deltap; - - lprint_sb->sb_datalen += TCP_SNDSPACE; - } - } -#endif - if (lprint_print) - lprint_ptr += (*lprint_print)(*lprint_arg, format, args); - - /* Check if they want output to be logged to file as well */ - if (lfd) { - /* - * Remove \r's - * otherwise you'll get ^M all over the file - */ - int len = strlen(format); - char *bptr1, *bptr2; - - bptr1 = bptr2 = strdup(format); - - while (len--) { - if (*bptr1 == '\r') - memcpy(bptr1, bptr1+1, len+1); - else - bptr1++; - } - vfprintf(lfd, bptr2, args); - free(bptr2); - } - va_end(args); -} - -void add_emu(char *buff) -{ - u_int lport, fport; - u_int8_t tos = 0, emu = 0; - char buff1[256], buff2[256], buff4[128]; - char *buff3 = buff4; - struct emu_t *emup; - struct socket *so; - - if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { - lprint("Error: Bad arguments\r\n"); - return; - } - - if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { - lport = 0; - if (sscanf(buff1, "%d", &fport) != 1) { - lprint("Error: Bad first argument\r\n"); - return; - } - } - - if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { - buff3 = 0; - if (sscanf(buff2, "%256s", buff1) != 1) { - lprint("Error: Bad second argument\r\n"); - return; - } - } - - if (buff3) { - if (strcmp(buff3, "lowdelay") == 0) - tos = IPTOS_LOWDELAY; - else if (strcmp(buff3, "throughput") == 0) - tos = IPTOS_THROUGHPUT; - else { - lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n"); - return; - } - } - - if (strcmp(buff1, "ftp") == 0) - emu = EMU_FTP; - else if (strcmp(buff1, "irc") == 0) - emu = EMU_IRC; - else if (strcmp(buff1, "none") == 0) - emu = EMU_NONE; /* ie: no emulation */ - else { - lprint("Error: Unknown service\r\n"); - return; - } - - /* First, check that it isn't already emulated */ - for (emup = tcpemu; emup; emup = emup->next) { - if (emup->lport == lport && emup->fport == fport) { - lprint("Error: port already emulated\r\n"); - return; - } - } - - /* link it */ - emup = (struct emu_t *)malloc(sizeof (struct emu_t)); - emup->lport = (u_int16_t)lport; - emup->fport = (u_int16_t)fport; - emup->tos = tos; - emup->emu = emu; - emup->next = tcpemu; - tcpemu = emup; - - /* And finally, mark all current sessions, if any, as being emulated */ - for (so = tcb.so_next; so != &tcb; so = so->so_next) { - if ((lport && lport == ntohs(so->so_lport)) || - (fport && fport == ntohs(so->so_fport))) { - if (emu) - so->so_emu = emu; - if (tos) - so->so_iptos = tos; - } - } - - lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); -} - -#ifdef BAD_SPRINTF - -#undef vsprintf -#undef sprintf - -/* - * Some BSD-derived systems have a sprintf which returns char * - */ - -int vsprintf_len(char *string, const char *format, va_list args) -{ - vsprintf(string, format, args); - return strlen(string); -} - -int sprintf_len(char *string, const char *format, ...) -{ - va_list args; - va_start(args, format); - vsprintf(string, format, args); - va_end(args); - return strlen(string); -} - -#endif - -void u_sleep(int usec) -{ - struct timeval t; - fd_set fdset; - - FD_ZERO(&fdset); - - t.tv_sec = 0; - t.tv_usec = usec * 1000; - - select(0, &fdset, &fdset, &fdset, &t); -} - -/* - * Set fd blocking and non-blocking - */ - -void fd_nonblock(int fd) -{ -#if defined USE_FIONBIO && defined FIONBIO - ioctlsockopt_t opt = 1; - - ioctlsocket(fd, FIONBIO, &opt); -#else - int opt; - - opt = fcntl(fd, F_GETFL, 0); - opt |= O_NONBLOCK; - fcntl(fd, F_SETFL, opt); -#endif -} - -void fd_block(int fd) -{ -#if defined USE_FIONBIO && defined FIONBIO - ioctlsockopt_t opt = 0; - - ioctlsocket(fd, FIONBIO, &opt); -#else - int opt; - - opt = fcntl(fd, F_GETFL, 0); - opt &= ~O_NONBLOCK; - fcntl(fd, F_SETFL, opt); -#endif -} - - -#if 0 -/* - * invoke RSH - */ -int rsh_exec(struct socket *so, struct socket *ns, - char *user, char *host, char *args) -{ - int fd[2]; - int fd0[2]; - int s; - char buff[256]; - - DEBUG_CALL("rsh_exec"); - DEBUG_ARG("so = %lx", (long)so); - - if (pipe(fd)<0) { - lprint("Error: pipe failed: %s\n", strerror(errno)); - return 0; - } -/* #ifdef HAVE_SOCKETPAIR */ -#if 1 - if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) { - close(fd[0]); - close(fd[1]); - lprint("Error: openpty failed: %s\n", strerror(errno)); - return 0; - } -#else - if (slirp_openpty(&fd0[0], &fd0[1]) == -1) { - close(fd[0]); - close(fd[1]); - lprint("Error: openpty failed: %s\n", strerror(errno)); - return 0; - } -#endif - - switch(fork()) { - case -1: - lprint("Error: fork failed: %s\n", strerror(errno)); - close(fd[0]); - close(fd[1]); - close(fd0[0]); - close(fd0[1]); - return 0; - - case 0: - close(fd[0]); - close(fd0[0]); - - /* Set the DISPLAY */ - if (x_port >= 0) { -#ifdef HAVE_SETENV - sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); - setenv("DISPLAY", buff, 1); -#else - sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); - putenv(buff); -#endif - } - - dup2(fd0[1], 0); - dup2(fd0[1], 1); - dup2(fd[1], 2); - for (s = 3; s <= 255; s++) - close(s); - - execlp("rsh","rsh","-l", user, host, args, NULL); - - /* Ooops, failed, let's tell the user why */ - - sprintf(buff, "Error: execlp of %s failed: %s\n", - "rsh", strerror(errno)); - write(2, buff, strlen(buff)+1); - close(0); close(1); close(2); /* XXX */ - exit(1); - - default: - close(fd[1]); - close(fd0[1]); - ns->s=fd[0]; - so->s=fd0[0]; - - return 1; - } -} -#endif diff --git a/BasiliskII/src/slirp/misc.h b/BasiliskII/src/slirp/misc.h deleted file mode 100644 index 381f5f3e..00000000 --- a/BasiliskII/src/slirp/misc.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#ifndef _MISC_H_ -#define _MISC_H_ - -struct ex_list { - int ex_pty; /* Do we want a pty? */ - int ex_addr; /* The last byte of the address */ - int ex_fport; /* Port to telnet to */ - char *ex_exec; /* Command line of what to exec */ - struct ex_list *ex_next; -}; - -extern struct ex_list *exec_list; -extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; - -extern int (*lprint_print)(void *, const char *, va_list); -extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; -extern struct sbuf *lprint_sb; - -#ifndef HAVE_STRDUP -char *strdup(const char *); -#endif - -void do_wait(int); - -#define EMU_NONE 0x0 - -/* TCP emulations */ -#define EMU_CTL 0x1 -#define EMU_FTP 0x2 -#define EMU_KSH 0x3 -#define EMU_IRC 0x4 -#define EMU_REALAUDIO 0x5 -#define EMU_RLOGIN 0x6 -#define EMU_IDENT 0x7 -#define EMU_RSH 0x8 - -#define EMU_NOCONNECT 0x10 /* Don't connect */ - -/* UDP emulations */ -#define EMU_TALK 0x1 -#define EMU_NTALK 0x2 -#define EMU_CUSEEME 0x3 - -struct tos_t { - u_int16_t lport; - u_int16_t fport; - u_int8_t tos; - u_int8_t emu; -}; - -struct emu_t { - u_int16_t lport; - u_int16_t fport; - u_int8_t tos; - u_int8_t emu; - struct emu_t *next; -}; - -extern struct emu_t *tcpemu; - -extern int x_port, x_server, x_display; - -int show_x(char *, struct socket *); -void redir_x(u_int32_t, int, int, int); -void getouraddr(void); -void slirp_insque(void *, void *); -void slirp_remque(void *); -int add_exec(struct ex_list **, int, char *, int, int); -int slirp_openpty(int *, int *); -int fork_exec(struct socket *, char *, int); -void snooze_hup(int); -void snooze(void); -void relay(int); -void add_emu(char *); -void u_sleep(int); -void fd_nonblock(int); -void fd_block(int); -int rsh_exec(struct socket *, struct socket *, char *, char *, char *); - -#endif diff --git a/BasiliskII/src/slirp/sbuf.c b/BasiliskII/src/slirp/sbuf.c deleted file mode 100644 index 6af075e7..00000000 --- a/BasiliskII/src/slirp/sbuf.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include -#include - -/* Done as a macro in socket.h */ -/* int - * sbspace(struct sockbuff *sb) - * { - * return SB_DATALEN - sb->sb_cc; - * } - */ - -void sbfree(struct sbuf *sb) -{ - free(sb->sb_data); -} - -void sbdrop(struct sbuf *sb, u_int num) -{ - /* - * We can only drop how much we have - * This should never succeed - */ - if(num > sb->sb_cc) - num = sb->sb_cc; - sb->sb_cc -= num; - sb->sb_rptr += num; - if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) - sb->sb_rptr -= sb->sb_datalen; - -} - -void sbreserve(struct sbuf *sb, size_t size) -{ - if (sb->sb_data) { - /* Already alloced, realloc if necessary */ - if (sb->sb_datalen != size) { - sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size); - sb->sb_cc = 0; - if (sb->sb_wptr) - sb->sb_datalen = size; - else - sb->sb_datalen = 0; - } - } else { - sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); - sb->sb_cc = 0; - if (sb->sb_wptr) - sb->sb_datalen = size; - else - sb->sb_datalen = 0; - } -} - -/* - * Try and write() to the socket, whatever doesn't get written - * append to the buffer... for a host with a fast net connection, - * this prevents an unnecessary copy of the data - * (the socket is non-blocking, so we won't hang) - */ -void sbappend(struct socket *so, struct mbuf *m) -{ - int ret = 0; - - DEBUG_CALL("sbappend"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("m->m_len = %d", m->m_len); - - /* Shouldn't happen, but... e.g. foreign host closes connection */ - if (m->m_len <= 0) { - m_free(m); - return; - } - - /* - * If there is urgent data, call sosendoob - * if not all was sent, sowrite will take care of the rest - * (The rest of this function is just an optimisation) - */ - if (so->so_urgc) { - sbappendsb(&so->so_rcv, m); - m_free(m); - sosendoob(so); - return; - } - - /* - * We only write if there's nothing in the buffer, - * ottherwise it'll arrive out of order, and hence corrupt - */ - if (!so->so_rcv.sb_cc) - ret = send(so->s, m->m_data, m->m_len, 0); - - if (ret <= 0) { - /* - * Nothing was written - * It's possible that the socket has closed, but - * we don't need to check because if it has closed, - * it will be detected in the normal way by soread() - */ - sbappendsb(&so->so_rcv, m); - } else if (ret != m->m_len) { - /* - * Something was written, but not everything.. - * sbappendsb the rest - */ - m->m_len -= ret; - m->m_data += ret; - sbappendsb(&so->so_rcv, m); - } /* else */ - /* Whatever happened, we free the mbuf */ - m_free(m); -} - -/* - * Copy the data from m into sb - * The caller is responsible to make sure there's enough room - */ -void sbappendsb(struct sbuf *sb, struct mbuf *m) -{ - int len, n, nn; - - len = m->m_len; - - if (sb->sb_wptr < sb->sb_rptr) { - n = sb->sb_rptr - sb->sb_wptr; - if (n > len) n = len; - memcpy(sb->sb_wptr, m->m_data, n); - } else { - /* Do the right edge first */ - n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; - if (n > len) n = len; - memcpy(sb->sb_wptr, m->m_data, n); - len -= n; - if (len) { - /* Now the left edge */ - nn = sb->sb_rptr - sb->sb_data; - if (nn > len) nn = len; - memcpy(sb->sb_data,m->m_data+n,nn); - n += nn; - } - } - - sb->sb_cc += n; - sb->sb_wptr += n; - if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) - sb->sb_wptr -= sb->sb_datalen; -} - -/* - * Copy data from sbuf to a normal, straight buffer - * Don't update the sbuf rptr, this will be - * done in sbdrop when the data is acked - */ -void sbcopy(struct sbuf *sb, u_int off, u_int len, char *to) -{ - char *from; - - from = sb->sb_rptr + off; - if (from >= sb->sb_data + sb->sb_datalen) - from -= sb->sb_datalen; - - if (from < sb->sb_wptr) { - if (len > sb->sb_cc) len = sb->sb_cc; - memcpy(to,from,len); - } else { - /* re-use off */ - off = (sb->sb_data + sb->sb_datalen) - from; - if (off > len) off = len; - memcpy(to,from,off); - len -= off; - if (len) - memcpy(to+off,sb->sb_data,len); - } -} - diff --git a/BasiliskII/src/slirp/sbuf.h b/BasiliskII/src/slirp/sbuf.h deleted file mode 100644 index 04f7981c..00000000 --- a/BasiliskII/src/slirp/sbuf.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#ifndef _SBUF_H_ -#define _SBUF_H_ - -#include - -#define sbflush(sb) sbdrop((sb),(sb)->sb_cc) -#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) - -struct sbuf { - u_int sb_cc; /* actual chars in buffer */ - u_int sb_datalen; /* Length of data */ - char *sb_wptr; /* write pointer. points to where the next - * bytes should be written in the sbuf */ - char *sb_rptr; /* read pointer. points to where the next - * byte should be read from the sbuf */ - char *sb_data; /* Actual data */ -}; - -void sbfree(struct sbuf *); -void sbdrop(struct sbuf *, u_int); -void sbreserve(struct sbuf *, size_t); -void sbappend(struct socket *, struct mbuf *); -void sbappendsb(struct sbuf *, struct mbuf *); -void sbcopy(struct sbuf *, u_int, u_int, char *); - -#endif diff --git a/BasiliskII/src/slirp/slirp.c b/BasiliskII/src/slirp/slirp.c deleted file mode 100644 index d8f2a954..00000000 --- a/BasiliskII/src/slirp/slirp.c +++ /dev/null @@ -1,676 +0,0 @@ -#include "slirp.h" - -/* host address */ -struct in_addr our_addr; -/* host dns address */ -struct in_addr dns_addr; -/* host loopback address */ -struct in_addr loopback_addr; - -/* address for slirp virtual addresses */ -struct in_addr special_addr; -/* virtual address alias for host */ -struct in_addr alias_addr; - -const uint8_t special_ethaddr[6] = { - 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 -}; - -uint8_t client_ethaddr[6]; - -int do_slowtimo; -int link_up; -struct timeval tt; -FILE *lfd; -struct ex_list *exec_list; - -/* XXX: suppress those select globals */ -fd_set *global_readfds, *global_writefds, *global_xfds; - -char slirp_hostname[33]; - -#ifdef _WIN32 - -static int get_dns_addr(struct in_addr *pdns_addr) -{ - FIXED_INFO *FixedInfo=NULL; - ULONG BufLen; - DWORD ret; - IP_ADDR_STRING *pIPAddr; - struct in_addr tmp_addr; - - FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); - BufLen = sizeof(FIXED_INFO); - - if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) { - if (FixedInfo) { - GlobalFree(FixedInfo); - FixedInfo = NULL; - } - FixedInfo = GlobalAlloc(GPTR, BufLen); - } - - if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { - printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); - if (FixedInfo) { - GlobalFree(FixedInfo); - FixedInfo = NULL; - } - return -1; - } - - pIPAddr = &(FixedInfo->DnsServerList); - inet_aton(pIPAddr->IpAddress.String, &tmp_addr); - *pdns_addr = tmp_addr; -#if 0 - printf( "DNS Servers:\n" ); - printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String ); - - pIPAddr = FixedInfo -> DnsServerList.Next; - while ( pIPAddr ) { - printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String ); - pIPAddr = pIPAddr ->Next; - } -#endif - if (FixedInfo) { - GlobalFree(FixedInfo); - FixedInfo = NULL; - } - return 0; -} - -#else - -static int get_dns_addr(struct in_addr *pdns_addr) -{ - char buff[512]; - char buff2[256]; - FILE *f; - int found = 0; - struct in_addr tmp_addr; - - f = fopen("/etc/resolv.conf", "r"); - if (!f) - return -1; - - lprint("IP address of your DNS(s): "); - while (fgets(buff, 512, f) != NULL) { - if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { - if (!inet_aton(buff2, &tmp_addr)) - continue; - if (tmp_addr.s_addr == loopback_addr.s_addr) - tmp_addr = our_addr; - /* If it's the first one, set it to dns_addr */ - if (!found) - *pdns_addr = tmp_addr; - else - lprint(", "); - if (++found > 3) { - lprint("(more)"); - break; - } else - lprint("%s", inet_ntoa(tmp_addr)); - } - } - fclose(f); - if (!found) - return -1; - return 0; -} - -#endif - -#ifdef _WIN32 -void slirp_cleanup(void) -{ - WSACleanup(); -} -#endif - -int slirp_init(void) -{ - // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); - -#ifdef _WIN32 - { - WSADATA Data; - WSAStartup(MAKEWORD(2,0), &Data); - atexit(slirp_cleanup); - } -#endif - - link_up = 1; - - if_init(); - ip_init(); - - /* Initialise mbufs *after* setting the MTU */ - m_init(); - - /* set default addresses */ - inet_aton("127.0.0.1", &loopback_addr); - - if (get_dns_addr(&dns_addr) < 0) - return -1; - - inet_aton(CTL_SPECIAL, &special_addr); - alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); - getouraddr(); - return 0; -} - -#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) -#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) -#define UPD_NFDS(x) if (nfds < (x)) nfds = (x) - -/* - * curtime kept to an accuracy of 1ms - */ -#ifdef _WIN32 -static void updtime(void) -{ - struct _timeb tb; - - _ftime(&tb); - curtime = (u_int)tb.time * (u_int)1000; - curtime += (u_int)tb.millitm; -} -#else -static void updtime(void) -{ - gettimeofday(&tt, 0); - - curtime = (u_int)tt.tv_sec * (u_int)1000; - curtime += (u_int)tt.tv_usec / (u_int)1000; - - if ((tt.tv_usec % 1000) >= 500) - curtime++; -} -#endif - -int slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds) -{ - struct socket *so, *so_next; - int nfds; - int timeout, tmp_time; - - /* fail safe */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; - - nfds = *pnfds; - /* - * First, TCP sockets - */ - do_slowtimo = 0; - if (link_up) { - /* - * *_slowtimo needs calling if there are IP fragments - * in the fragment queue, or there are TCP connections active - */ - do_slowtimo = ((tcb.so_next != &tcb) || - ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); - - for (so = tcb.so_next; so != &tcb; so = so_next) { - so_next = so->so_next; - - /* - * See if we need a tcp_fasttimo - */ - if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) - time_fasttimo = curtime; /* Flag when we want a fasttimo */ - - /* - * NOFDREF can include still connecting to local-host, - * newly socreated() sockets etc. Don't want to select these. - */ - if (so->so_state & SS_NOFDREF || so->s == -1) - continue; - - /* - * Set for reading sockets which are accepting - */ - if (so->so_state & SS_FACCEPTCONN) { - FD_SET(so->s, readfds); - UPD_NFDS(so->s); - continue; - } - - /* - * Set for writing sockets which are connecting - */ - if (so->so_state & SS_ISFCONNECTING) { - FD_SET(so->s, writefds); - UPD_NFDS(so->s); - continue; - } - - /* - * Set for writing if we are connected, can send more, and - * we have something to send - */ - if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) { - FD_SET(so->s, writefds); - UPD_NFDS(so->s); - } - - /* - * Set for reading (and urgent data) if we are connected, can - * receive more, and we have room for it XXX /2 ? - */ - if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) { - FD_SET(so->s, readfds); - FD_SET(so->s, xfds); - UPD_NFDS(so->s); - } - } - - /* - * UDP sockets - */ - for (so = udb.so_next; so != &udb; so = so_next) { - so_next = so->so_next; - - /* - * See if it's timed out - */ - if (so->so_expire) { - if (so->so_expire <= curtime) { - udp_detach(so); - continue; - } else - do_slowtimo = 1; /* Let socket expire */ - } - - /* - * When UDP packets are received from over the - * link, they're sendto()'d straight away, so - * no need for setting for writing - * Limit the number of packets queued by this session - * to 4. Note that even though we try and limit this - * to 4 packets, the session could have more queued - * if the packets needed to be fragmented - * (XXX <= 4 ?) - */ - if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) { - FD_SET(so->s, readfds); - UPD_NFDS(so->s); - } - } - } - - /* - * Setup timeout to use minimum CPU usage, especially when idle - */ - - timeout = -1; - - /* - * If a slowtimo is needed, set timeout to 5ms from the last - * slow timeout. If a fast timeout is needed, set timeout within - * 2ms of when it was requested. - */ -# define SLOW_TIMO 5 -# define FAST_TIMO 2 - if (do_slowtimo) { - timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000; - if (timeout < 0) - timeout = 0; - else if (timeout > (SLOW_TIMO * 1000)) - timeout = SLOW_TIMO * 1000; - - /* Can only fasttimo if we also slowtimo */ - if (time_fasttimo) { - tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000; - if (tmp_time < 0) - tmp_time = 0; - - /* Choose the smallest of the 2 */ - if (tmp_time < timeout) - timeout = tmp_time; - } - } - *pnfds = nfds; - - /* - * Adjust the timeout to make the minimum timeout - * 2ms (XXX?) to lessen the CPU load - */ - if (timeout < (FAST_TIMO * 1000)) - timeout = FAST_TIMO * 1000; - - return timeout; -} - -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) -{ - struct socket *so, *so_next; - int ret; - - global_readfds = readfds; - global_writefds = writefds; - global_xfds = xfds; - - /* Update time */ - updtime(); - - /* - * See if anything has timed out - */ - if (link_up) { - if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) { - tcp_fasttimo(); - time_fasttimo = 0; - } - if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) { - ip_slowtimo(); - tcp_slowtimo(); - last_slowtimo = curtime; - } - } - - /* - * Check sockets - */ - if (link_up) { - /* - * Check TCP sockets - */ - for (so = tcb.so_next; so != &tcb; so = so_next) { - so_next = so->so_next; - - /* - * FD_ISSET is meaningless on these sockets - * (and they can crash the program) - */ - if (so->so_state & SS_NOFDREF || so->s == -1) - continue; - - /* - * Check for URG data - * This will soread as well, so no need to - * test for readfds below if this succeeds - */ - if (FD_ISSET(so->s, xfds)) - sorecvoob(so); - /* - * Check sockets for reading - */ - else if (FD_ISSET(so->s, readfds)) { - /* - * Check for incoming connections - */ - if (so->so_state & SS_FACCEPTCONN) { - tcp_connect(so); - continue; - } /* else */ - ret = soread(so); - - /* Output it if we read something */ - if (ret > 0) - tcp_output(sototcpcb(so)); - } - - /* - * Check sockets for writing - */ - if (FD_ISSET(so->s, writefds)) { - /* - * Check for non-blocking, still-connecting sockets - */ - if (so->so_state & SS_ISFCONNECTING) { - /* Connected */ - so->so_state &= ~SS_ISFCONNECTING; - - ret = send(so->s, (char*)&ret, 0, 0); - if (ret < 0) { - /* XXXXX Must fix, zero bytes is a NOP */ - int error = WSAGetLastError(); - if (error == EAGAIN || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS || error == WSAENOTCONN) - continue; - - /* else failed */ - so->so_state = SS_NOFDREF; - } - /* else so->so_state &= ~SS_ISFCONNECTING; */ - - /* - * Continue tcp_input - */ - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); - /* continue; */ - } - else - ret = sowrite(so); - /* - * XXXXX If we wrote something (a lot), there - * could be a need for a window update. - * In the worst case, the remote will send - * a window probe to get things going again - */ - } - - /* - * Probe a still-connecting, non-blocking socket - * to check if it's still alive - */ -#ifdef PROBE_CONN - if (so->so_state & SS_ISFCONNECTING) { - ret = recv(so->s, (char *)&ret, 0, 0); - - if (ret < 0) { - /* XXX */ - int error = WSAGetLastError(); - if (error == EAGAIN || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS || error == WSAENOTCONN) - continue; /* Still connecting, continue */ - - /* else failed */ - so->so_state = SS_NOFDREF; - - /* tcp_input will take care of it */ - } - else { - ret = send(so->s, &ret, 0, 0); - if (ret < 0) { - /* XXX */ - int error = WSAGetLastError(); - if (error == EAGAIN || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS || error == WSAENOTCONN) - continue; - /* else failed */ - so->so_state = SS_NOFDREF; - } - else - so->so_state &= ~SS_ISFCONNECTING; - - } - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); - } /* SS_ISFCONNECTING */ -#endif - } - - /* - * Now UDP sockets. - * Incoming packets are sent straight away, they're not buffered. - * Incoming UDP data isn't buffered either. - */ - for (so = udb.so_next; so != &udb; so = so_next) { - so_next = so->so_next; - - if (so->s != -1 && FD_ISSET(so->s, readfds)) { - sorecvfrom(so); - } - } -} - - /* - * See if we can start outputting - */ - if (if_queued && link_up) - if_start(); - - /* clear global file descriptor sets. - * these reside on the stack in vl.c - * so they're unusable if we're not in - * slirp_select_fill or slirp_select_poll. - */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; -} - -#define ETH_ALEN 6 -#define ETH_HLEN 14 - -#define ETH_P_IP 0x0800 /* Internet Protocol packet */ -#define ETH_P_ARP 0x0806 /* Address Resolution packet */ - -#define ARPOP_REQUEST 1 /* ARP request */ -#define ARPOP_REPLY 2 /* ARP reply */ - -struct ethhdr -{ - unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ - unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_proto; /* packet type ID field */ -}; - -struct arphdr -{ - unsigned short ar_hrd; /* format of hardware address */ - unsigned short ar_pro; /* format of protocol address */ - unsigned char ar_hln; /* length of hardware address */ - unsigned char ar_pln; /* length of protocol address */ - unsigned short ar_op; /* ARP opcode (command) */ - - /* - * Ethernet looks like this : This bit is variable sized however... - */ - unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ - unsigned char ar_sip[4]; /* sender IP address */ - unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ - unsigned char ar_tip[4]; /* target IP address */ -}; - -void arp_input(const uint8_t *pkt, int pkt_len) -{ - struct ethhdr *eh = (struct ethhdr *)pkt; - struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); - uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)]; - struct ethhdr *reh = (struct ethhdr *)arp_reply; - struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN); - int ar_op; - struct ex_list *ex_ptr; - - ar_op = ntohs(ah->ar_op); - switch(ar_op) { - case ARPOP_REQUEST: - if (!memcmp(ah->ar_tip, &special_addr, 3)) { - if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) - goto arp_ok; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_addr == ah->ar_tip[3]) - goto arp_ok; - } - return; - arp_ok: - /* XXX: make an ARP request to have the client address */ - memcpy(client_ethaddr, eh->h_source, ETH_ALEN); - - /* ARP request for alias/dns mac address */ - memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); - memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1); - reh->h_source[5] = ah->ar_tip[3]; - reh->h_proto = htons(ETH_P_ARP); - - rah->ar_hrd = htons(1); - rah->ar_pro = htons(ETH_P_IP); - rah->ar_hln = ETH_ALEN; - rah->ar_pln = 4; - rah->ar_op = htons(ARPOP_REPLY); - memcpy(rah->ar_sha, reh->h_source, ETH_ALEN); - memcpy(rah->ar_sip, ah->ar_tip, 4); - memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN); - memcpy(rah->ar_tip, ah->ar_sip, 4); - slirp_output(arp_reply, sizeof(arp_reply)); - } - break; - default: - break; - } -} - -void slirp_input(const uint8_t *pkt, int pkt_len) -{ - struct mbuf *m; - int proto; - - if (pkt_len < ETH_HLEN) - return; - - proto = (pkt[12] << 8) | pkt[13]; - switch(proto) { - case ETH_P_ARP: - arp_input(pkt, pkt_len); - break; - case ETH_P_IP: - m = m_get(); - if (!m) - return; - /* Note: we add to align the IP header */ - m->m_len = pkt_len + 2; - memcpy(m->m_data + 2, pkt, pkt_len); - - m->m_data += 2 + ETH_HLEN; - m->m_len -= 2 + ETH_HLEN; - - ip_input(m); - break; - default: - break; - } -} - -/* output the IP packet to the ethernet device */ -void if_encap(const uint8_t *ip_data, int ip_data_len) -{ - uint8_t buf[1600]; - struct ethhdr *eh = (struct ethhdr *)buf; - - if (ip_data_len + ETH_HLEN > sizeof(buf)) - return; - - memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); - memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1); - /* XXX: not correct */ - eh->h_source[5] = CTL_ALIAS; - eh->h_proto = htons(ETH_P_IP); - memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); - slirp_output(buf, ip_data_len + ETH_HLEN); -} - -int slirp_redir(int is_udp, int host_port, - struct in_addr guest_addr, int guest_port) -{ - if (is_udp) { - if (!udp_listen(htons(host_port), guest_addr.s_addr, - htons(guest_port), 0)) - return -1; - } else { - if (!solisten(htons(host_port), guest_addr.s_addr, - htons(guest_port), 0)) - return -1; - } - return 0; -} - -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, - int guest_port) -{ - return add_exec(&exec_list, do_pty, (char *)args, - addr_low_byte, htons(guest_port)); -} diff --git a/BasiliskII/src/slirp/slirp.h b/BasiliskII/src/slirp/slirp.h deleted file mode 100644 index b845caa7..00000000 --- a/BasiliskII/src/slirp/slirp.h +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef __COMMON_H__ -#define __COMMON_H__ - -#define CONFIG_QEMU - -#define DEBUG 1 - -#ifndef CONFIG_QEMU -#include "version.h" -#endif -#include "config.h" -#include "slirp_config.h" - -#ifdef _WIN32 -# include - -typedef uint8_t u_int8_t; -typedef uint16_t u_int16_t; -typedef uint32_t u_int32_t; -typedef uint64_t u_int64_t; -typedef char *caddr_t; -typedef int socklen_t; -typedef unsigned long ioctlsockopt_t; - -# include -# include -# include -# include - -# define USE_FIONBIO 1 - -/* Basilisk II Router defines those */ -# define udp_read_completion slirp_udp_read_completion -# define write_udp slirp_write_udp -# define init_udp slirp_init_udp -# define final_udp slirp_final_udp -#else -# define WSAGetLastError() (int)(errno) -# define WSASetLastError(e) (void)(errno = (e)) -# define WSAEWOULDBLOCK EWOULDBLOCK -# define WSAEINPROGRESS EINPROGRESS -# define WSAENOTCONN ENOTCONN -# define WSAEHOSTUNREACH EHOSTUNREACH -# define WSAENETUNREACH ENETUNREACH -# define WSAECONNREFUSED ECONNREFUSED -typedef int ioctlsockopt_t; -# define ioctlsocket ioctl -# define closesocket(s) close(s) -# define O_BINARY 0 -#endif - -#include -#ifdef HAVE_SYS_BITYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif - -#ifndef _WIN32 -#include -#endif - -#ifdef NEED_TYPEDEFS -typedef char int8_t; -typedef unsigned char u_int8_t; - -# if SIZEOF_SHORT == 2 - typedef short int16_t; - typedef unsigned short u_int16_t; -# else -# if SIZEOF_INT == 2 - typedef int int16_t; - typedef unsigned int u_int16_t; -# else - #error Cannot find a type with sizeof() == 2 -# endif -# endif - -# if SIZEOF_SHORT == 4 - typedef short int32_t; - typedef unsigned short u_int32_t; -# else -# if SIZEOF_INT == 4 - typedef int int32_t; - typedef unsigned int u_int32_t; -# else - #error Cannot find a type with sizeof() == 4 -# endif -# endif -#endif /* NEED_TYPEDEFS */ - -/* Basilisk II types glue */ -typedef u_int8_t uint8; -typedef u_int16_t uint16; -typedef u_int32_t uint32; - -#ifdef HAVE_UNISTD_H -# include -#endif - -#ifdef HAVE_STDLIB_H -# include -#endif - -#include -#include - -#ifndef HAVE_MEMMOVE -#define memmove(x, y, z) bcopy(y, x, z) -#endif - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - -#ifdef HAVE_STRING_H -# include -#else -# include -#endif - -#ifndef _WIN32 -#include -#include -#include -#endif - -#ifdef GETTIMEOFDAY_ONE_ARG -#define gettimeofday(x, y) gettimeofday(x) -#endif - -/* Systems lacking strdup() definition in . */ -#if defined(ultrix) -char *strdup(const char *); -#endif - -/* Systems lacking malloc() definition in . */ -#if defined(ultrix) || defined(hcx) -void *malloc(size_t arg); -void free(void *ptr); -#endif - -#ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *ia); -#endif - -#include -#ifdef _WIN32 -#include -#endif -#ifndef NO_UNIX_SOCKETS -#include -#endif -#include -#ifdef HAVE_SYS_SIGNAL_H -# include -#endif -#ifndef _WIN32 -#include -#endif - -#if defined(HAVE_SYS_IOCTL_H) -# include -#endif - -#ifdef HAVE_SYS_SELECT_H -# include -#endif - -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -#ifdef HAVE_SYS_FILIO_H -# include -#endif - -#ifdef USE_PPP -#include -#endif - -#include - -#include - -/* Avoid conflicting with the libc insque() and remque(), which - have different prototypes. */ -#define insque slirp_insque -#define remque slirp_remque - -#ifdef HAVE_SYS_STROPTS_H -#include -#endif - -#include "debug.h" - -#if defined __GNUC__ -#define PACKED__ __attribute__ ((packed)) -#elif defined _MSC_VER -#define PRAGMA_PACK_SUPPORTED 1 -#define PACK_RESET -#define PACKED__ -#elif defined __sgi -#define PRAGMA_PACK_SUPPORTED 1 -#define PACK_RESET 0 -#define PACKED__ -#else -#error "Packed attribute or pragma shall be supported" -#endif - -#include "ip.h" -#include "tcp.h" -#include "tcp_timer.h" -#include "tcp_var.h" -#include "tcpip.h" -#include "udp.h" -#include "icmp_var.h" -#include "mbuf.h" -#include "sbuf.h" -#include "socket.h" -#include "if.h" -#include "main.h" -#include "misc.h" -#include "ctl.h" -#ifdef USE_PPP -#include "ppp/pppd.h" -#include "ppp/ppp.h" -#endif - -#include "bootp.h" -#include "tftp.h" -#include "libslirp.h" - -extern struct ttys *ttys_unit[MAX_INTERFACES]; - -#ifndef NULL -#define NULL (void *)0 -#endif - -#ifndef FULL_BOLT -void if_start(void); -#else -void if_start(struct ttys *); -#endif - -#ifdef BAD_SPRINTF -# define vsprintf vsprintf_len -# define sprintf sprintf_len - extern int vsprintf_len(char *, const char *, va_list); - extern int sprintf_len(char *, const char *, ...); -#endif - -#ifdef DECLARE_SPRINTF -# ifndef BAD_SPRINTF - extern int vsprintf(char *, const char *, va_list); -# endif - extern int vfprintf(FILE *, const char *, va_list); -#endif - -#ifndef HAVE_STRERROR - extern char *strerror(int error); -#endif - -#ifndef HAVE_INDEX - char *index(const char *, int); -#endif - -#ifndef HAVE_GETHOSTID - long gethostid(void); -#endif - -void lprint(const char *, ...); - -extern int do_echo; - -#if SIZEOF_CHAR_P == 4 -# define insque_32 insque -# define remque_32 remque -#else - extern inline void insque_32(void *, void *); - extern inline void remque_32(void *); -#endif - -#ifndef _WIN32 -#include -#endif - -#define DEFAULT_BAUD 115200 - -/* cksum.c */ -int cksum(struct mbuf *m, int len); - -/* if.c */ -void if_init(void); -void if_output(struct socket *, struct mbuf *); - -/* ip_input.c */ -void ip_init(void); -void ip_input(struct mbuf *); -struct ip * ip_reass(register struct ipasfrag *, register struct ipq *); -void ip_freef(struct ipq *); -void ip_enq(register struct ipasfrag *, register struct ipasfrag *); -void ip_deq(register struct ipasfrag *); -void ip_slowtimo(void); -void ip_stripoptions(register struct mbuf *, struct mbuf *); - -/* ip_output.c */ -int ip_output(struct socket *, struct mbuf *); - -/* tcp_input.c */ -int tcp_reass(register struct tcpcb *, register struct tcpiphdr *, struct mbuf *); -void tcp_input(register struct mbuf *, int, struct socket *); -void tcp_dooptions(struct tcpcb *, u_char *, int, struct tcpiphdr *); -void tcp_xmit_timer(register struct tcpcb *, int); -u_int tcp_mss(register struct tcpcb *, u_int); - -/* tcp_output.c */ -int tcp_output(register struct tcpcb *); -void tcp_setpersist(register struct tcpcb *); - -/* tcp_subr.c */ -void tcp_init(void); -void tcp_template(struct tcpcb *); -void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int); -struct tcpcb * tcp_newtcpcb(struct socket *); -struct tcpcb * tcp_close(register struct tcpcb *); -void tcp_drain(void); -void tcp_sockclosed(struct tcpcb *); -int tcp_fconnect(struct socket *); -void tcp_connect(struct socket *); -int tcp_attach(struct socket *); -u_int8_t tcp_tos(struct socket *); -int tcp_emu(struct socket *, struct mbuf *); -int tcp_ctl(struct socket *); -struct tcpcb *tcp_drop(struct tcpcb *tp, int err); - -#ifdef USE_PPP -#define MIN_MRU MINMRU -#define MAX_MRU MAXMRU -#else -#define MIN_MRU 128 -#define MAX_MRU 16384 -#endif - -#ifndef _WIN32 -#define min(x,y) ((x) < (y) ? (x) : (y)) -#define max(x,y) ((x) > (y) ? (x) : (y)) -#endif - -#endif diff --git a/BasiliskII/src/slirp/slirp_config.h b/BasiliskII/src/slirp/slirp_config.h deleted file mode 100644 index 237268fa..00000000 --- a/BasiliskII/src/slirp/slirp_config.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * User definable configuration options - */ - -/* Undefine if you don't want talk emulation */ -#undef EMULATE_TALK - -/* Define if you want the connection to be probed */ -/* XXX Not working yet, so ignore this for now */ -#undef PROBE_CONN - -/* Define to 1 if you want KEEPALIVE timers */ -#define DO_KEEPALIVE 0 - -/* Define to MAX interfaces you expect to use at once */ -/* MAX_INTERFACES determines the max. TOTAL number of interfaces (SLIP and PPP) */ -/* MAX_PPP_INTERFACES determines max. number of PPP interfaces */ -#define MAX_INTERFACES 1 -#define MAX_PPP_INTERFACES 1 - -/* Define if you want slirp's socket in /tmp */ -/* XXXXXX Do this in ./configure */ -#undef USE_TMPSOCKET - -/* Define if you want slirp to use cfsetXspeed() on the terminal */ -#undef DO_CFSETSPEED - -/* Define this if you want slirp to write to the tty as fast as it can */ -/* This should only be set if you are using load-balancing, slirp does a */ -/* pretty good job on single modems already, and seting this will make */ -/* interactive sessions less responsive */ -/* XXXXX Talk about having fast modem as unit 0 */ -#undef FULL_BOLT - -/* - * Define if you want slirp to use less CPU - * You will notice a small lag in interactive sessions, but it's not that bad - * Things like Netscape/ftp/etc. are completely unaffected - * This is mainly for sysadmins who have many slirp users - */ -#undef USE_LOWCPU - -/*********************************************************/ -/* - * Autoconf defined configuration options - * You shouldn't need to touch any of these - */ - -/* Ignore this */ -#undef DUMMY_PPP - -/* XXX: Define according to how time.h should be included */ -#undef TIME_WITH_SYS_TIME -#define TIME_WITH_SYS_TIME 0 -#undef HAVE_SYS_TIME_H - -/* Define if your sprintf returns char * instead of int */ -#undef BAD_SPRINTF - -/* Define if you have readv */ -#undef HAVE_READV - -/* Define if iovec needs to be declared */ -#undef DECLARE_IOVEC -#ifdef _WIN32 -#define DECLARE_IOVEC -#endif - -/* Define if a declaration of sprintf/fprintf is needed */ -#undef DECLARE_SPRINTF - -/* Define if you have sys/stropts.h */ -#undef HAVE_SYS_STROPTS_H - -/* Define if you don't have u_int32_t etc. typedef'd */ -#undef NEED_TYPEDEFS -#ifdef __sun__ -#define NEED_TYPEDEFS -#endif - -/* Define to sizeof(char *) */ -#define SIZEOF_CHAR_P SIZEOF_VOID_P - -/* Define if you have random() */ -#undef HAVE_RANDOM - -/* Define if you have srandom() */ -#undef HAVE_SRANDOM - -/* Define if you have setenv */ -#undef HAVE_SETENV - -/* Define if you have index() */ -#undef HAVE_INDEX - -/* Define if you have bcmp() */ -#undef HAVE_BCMP - -/* Define if you have drand48 */ -#undef HAVE_DRAND48 - -/* Define if you have memmove */ -#define HAVE_MEMMOVE - -/* Define if you have gethostid */ -#undef HAVE_GETHOSTID - -/* Define if you DON'T have unix-domain sockets */ -#undef NO_UNIX_SOCKETS -#ifdef _WIN32 -#define NO_UNIX_SOCKETS -#endif - -/* Define if gettimeofday only takes one argument */ -#undef GETTIMEOFDAY_ONE_ARG - -/* Define if you have revoke() */ -#undef HAVE_REVOKE - -/* Define if you have the sysv method of opening pty's (/dev/ptmx, etc.) */ -#undef HAVE_GRANTPT - -/* Define if you have fchmod */ -#undef HAVE_FCHMOD - -/* Define if you have */ -#undef HAVE_SYS_TYPES32_H diff --git a/BasiliskII/src/slirp/socket.c b/BasiliskII/src/slirp/socket.c deleted file mode 100644 index 2c0e067e..00000000 --- a/BasiliskII/src/slirp/socket.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#define WANT_SYS_IOCTL_H -#include -#include -#include "ip_icmp.h" -#include "main.h" -#ifdef __sun__ -#include -#endif - -#ifdef _WIN32 -#define IS_EAGAIN(e) ((e) == WSAEINTR || (e) == EAGAIN) -#else -#define IS_EAGAIN(e) ((e) == EAGAIN) -#endif - -void -so_init() -{ - /* Nothing yet */ -} - - -struct socket * -solookup(head, laddr, lport, faddr, fport) - struct socket *head; - struct in_addr laddr; - u_int lport; - struct in_addr faddr; - u_int fport; -{ - struct socket *so; - - for (so = head->so_next; so != head; so = so->so_next) { - if (so->so_lport == lport && - so->so_laddr.s_addr == laddr.s_addr && - so->so_faddr.s_addr == faddr.s_addr && - so->so_fport == fport) - break; - } - - if (so == head) - return (struct socket *)NULL; - return so; - -} - -/* - * Create a new socket, initialise the fields - * It is the responsibility of the caller to - * insque() it into the correct linked-list - */ -struct socket * -socreate() -{ - struct socket *so; - - so = (struct socket *)malloc(sizeof(struct socket)); - if(so) { - memset(so, 0, sizeof(struct socket)); - so->so_state = SS_NOFDREF; - so->s = -1; - } - return(so); -} - -/* - * remque and free a socket, clobber cache - */ -void -sofree(so) - struct socket *so; -{ - if (so->so_emu==EMU_RSH && so->extra) { - sofree(so->extra); - so->extra=NULL; - } - if (so == tcp_last_so) - tcp_last_so = &tcb; - else if (so == udp_last_so) - udp_last_so = &udb; - - m_free(so->so_m); - - if(so->so_next && so->so_prev) - remque(so); /* crashes if so is not in a queue */ - - free(so); -} - -/* - * Read from so's socket into sb_snd, updating all relevant sbuf fields - * NOTE: This will only be called if it is select()ed for reading, so - * a read() of 0 (or less) means it's disconnected - */ -int -soread(so) - struct socket *so; -{ - int n, nn; - u_int lss, total; - struct sbuf *sb = &so->so_snd; - u_int len = sb->sb_datalen - sb->sb_cc; - struct iovec iov[2]; - u_int mss = so->so_tcpcb->t_maxseg; - - DEBUG_CALL("soread"); - DEBUG_ARG("so = %lx", (long )so); - - /* - * No need to check if there's enough room to read. - * soread wouldn't have been called if there weren't - */ - - len = sb->sb_datalen - sb->sb_cc; - - iov[0].iov_base = sb->sb_wptr; - if (sb->sb_wptr < sb->sb_rptr) { - iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; - /* Should never succeed, but... */ - if (iov[0].iov_len > len) - iov[0].iov_len = len; - if (iov[0].iov_len > mss) - iov[0].iov_len -= iov[0].iov_len%mss; - n = 1; - } else { - iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; - /* Should never succeed, but... */ - if (iov[0].iov_len > len) iov[0].iov_len = len; - len -= iov[0].iov_len; - if (len) { - iov[1].iov_base = sb->sb_data; - iov[1].iov_len = sb->sb_rptr - sb->sb_data; - if(iov[1].iov_len > len) - iov[1].iov_len = len; - total = iov[0].iov_len + iov[1].iov_len; - if (total > mss) { - lss = total%mss; - if (iov[1].iov_len > lss) { - iov[1].iov_len -= lss; - n = 2; - } else { - lss -= iov[1].iov_len; - iov[0].iov_len -= lss; - n = 1; - } - } else - n = 2; - } else { - if (iov[0].iov_len > mss) - iov[0].iov_len -= iov[0].iov_len%mss; - n = 1; - } - } - -#ifdef HAVE_READV - nn = readv(so->s, (struct iovec *)iov, n); - DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); -#else - nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); -#endif - if (nn <= 0) { - int error = WSAGetLastError(); - if (nn < 0 && IS_EAGAIN(error)) - return 0; - else { - DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); - sofcantrcvmore(so); - tcp_sockclosed(sototcpcb(so)); - return -1; - } - } - -#ifndef HAVE_READV - /* - * If there was no error, try and read the second time round - * We read again if n = 2 (ie, there's another part of the buffer) - * and we read as much as we could in the first read - * We don't test for <= 0 this time, because there legitimately - * might not be any more data (since the socket is non-blocking), - * a close will be detected on next iteration. - * A return of -1 wont (shouldn't) happen, since it didn't happen above - */ - if (n == 2 && nn == iov[0].iov_len) { - int ret; - ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0); - if (ret > 0) - nn += ret; - } - - DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); -#endif - - /* Update fields */ - sb->sb_cc += nn; - sb->sb_wptr += nn; - if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_wptr -= sb->sb_datalen; - return nn; -} - -/* - * Get urgent data - * - * When the socket is created, we set it SO_OOBINLINE, - * so when OOB data arrives, we soread() it and everything - * in the send buffer is sent as urgent data - */ -void -sorecvoob(so) - struct socket *so; -{ - struct tcpcb *tp = sototcpcb(so); - - DEBUG_CALL("sorecvoob"); - DEBUG_ARG("so = %lx", (long)so); - - /* - * We take a guess at how much urgent data has arrived. - * In most situations, when urgent data arrives, the next - * read() should get all the urgent data. This guess will - * be wrong however if more data arrives just after the - * urgent data, or the read() doesn't return all the - * urgent data. - */ - soread(so); - tp->snd_up = tp->snd_una + so->so_snd.sb_cc; - tp->t_force = 1; - tcp_output(tp); - tp->t_force = 0; -} - -/* - * Send urgent data - * There's a lot duplicated code here, but... - */ -int -sosendoob(so) - struct socket *so; -{ - struct sbuf *sb = &so->so_rcv; - char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ - - int n, len; - - DEBUG_CALL("sosendoob"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); - - if (so->so_urgc > 2048) - so->so_urgc = 2048; /* XXXX */ - - if (sb->sb_rptr < sb->sb_wptr) { - /* We can send it directly */ - n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ - so->so_urgc -= n; - - DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); - } else { - /* - * Since there's no sendv or sendtov like writev, - * we must copy all data to a linear buffer then - * send it all - */ - len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; - if (len > so->so_urgc) len = so->so_urgc; - memcpy(buff, sb->sb_rptr, len); - so->so_urgc -= len; - if (so->so_urgc) { - n = sb->sb_wptr - sb->sb_data; - if (n > so->so_urgc) n = so->so_urgc; - memcpy((buff + len), sb->sb_data, n); - so->so_urgc -= n; - len += n; - } - n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ -#ifdef DEBUG - if (n != len) - DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); -#endif - DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); - } - - sb->sb_cc -= n; - sb->sb_rptr += n; - if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_rptr -= sb->sb_datalen; - - return n; -} - -/* - * Write data from so_rcv to so's socket, - * updating all sbuf field as necessary - */ -int -sowrite(so) - struct socket *so; -{ - int n,nn; - struct sbuf *sb = &so->so_rcv; - u_int len = sb->sb_cc; - struct iovec iov[2]; - - DEBUG_CALL("sowrite"); - DEBUG_ARG("so = %lx", (long)so); - - if (so->so_urgc) { - sosendoob(so); - if (sb->sb_cc == 0) - return 0; - } - - /* - * No need to check if there's something to write, - * sowrite wouldn't have been called otherwise - */ - - len = sb->sb_cc; - - iov[0].iov_base = sb->sb_rptr; - if (sb->sb_rptr < sb->sb_wptr) { - iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; - /* Should never succeed, but... */ - if (iov[0].iov_len > len) iov[0].iov_len = len; - n = 1; - } else { - iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; - if (iov[0].iov_len > len) iov[0].iov_len = len; - len -= iov[0].iov_len; - if (len) { - iov[1].iov_base = sb->sb_data; - iov[1].iov_len = sb->sb_wptr - sb->sb_data; - if (iov[1].iov_len > len) iov[1].iov_len = len; - n = 2; - } else - n = 1; - } - /* Check if there's urgent data to send, and if so, send it */ - -#ifdef HAVE_READV - nn = writev(so->s, (const struct iovec *)iov, n); - - DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); -#else - nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); -#endif - /* This should never happen, but people tell me it does *shrug* */ - if (nn < 0) { - int error = WSAGetLastError(); - if (IS_EAGAIN(error)) - return 0; - } - - if (nn <= 0) { - DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", - so->so_state, errno)); - sofcantsendmore(so); - tcp_sockclosed(sototcpcb(so)); - return -1; - } - -#ifndef HAVE_READV - if (n == 2 && nn == iov[0].iov_len) { - int ret; - ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0); - if (ret > 0) - nn += ret; - } - DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); -#endif - - /* Update sbuf */ - sb->sb_cc -= nn; - sb->sb_rptr += nn; - if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) - sb->sb_rptr -= sb->sb_datalen; - - /* - * If in DRAIN mode, and there's no more data, set - * it CANTSENDMORE - */ - if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) - sofcantsendmore(so); - - return nn; -} - -/* - * recvfrom() a UDP socket - */ -void -sorecvfrom(so) - struct socket *so; -{ - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); - - DEBUG_CALL("sorecvfrom"); - DEBUG_ARG("so = %lx", (long)so); - - if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ - char buff[256]; - int len; - - len = recvfrom(so->s, buff, 256, 0, - (struct sockaddr *)&addr, &addrlen); - /* XXX Check if reply is "correct"? */ - - if(len == -1 || len == 0) { - u_char code=ICMP_UNREACH_PORT; - - int error = WSAGetLastError(); - if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST; - else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET; - - DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", - errno,strerror(errno))); - icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); - } else { - icmp_reflect(so->so_m); - so->so_m = 0; /* Don't m_free() it again! */ - } - /* No need for this socket anymore, udp_detach it */ - udp_detach(so); - } else { /* A "normal" UDP packet */ - struct mbuf *m; - u_int len; - ioctlsockopt_t n; - - if (!(m = m_get())) return; - m->m_data += if_maxlinkhdr; - - /* - * XXX Shouldn't FIONREAD packets destined for port 53, - * but I don't know the max packet size for DNS lookups - */ - len = M_FREEROOM(m); - /* if (so->so_fport != htons(53)) { */ - ioctlsocket(so->s, FIONREAD, &n); - - if (n > len) { - n = (m->m_data - m->m_dat) + m->m_len + n + 1; - m_inc(m, n); - len = M_FREEROOM(m); - } - /* } */ - - m->m_len = recvfrom(so->s, m->m_data, len, 0, - (struct sockaddr *)&addr, &addrlen); - DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", - m->m_len, errno,strerror(errno))); - if(m->m_len<0) { - u_char code=ICMP_UNREACH_PORT; - - int error = WSAGetLastError(); - if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST; - else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET; - - DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); - icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); - m_free(m); - } else { - /* - * Hack: domain name lookup will be used the most for UDP, - * and since they'll only be used once there's no need - * for the 4 minute (or whatever) timeout... So we time them - * out much quicker (10 seconds for now...) - */ - if (so->so_expire) { - if (so->so_fport == htons(53)) - so->so_expire = curtime + SO_EXPIREFAST; - else - so->so_expire = curtime + SO_EXPIRE; - } - - /* if (m->m_len == len) { - * m_inc(m, MINCSIZE); - * m->m_len = 0; - * } - */ - - /* - * If this packet was destined for CTL_ADDR, - * make it look like that's where it came from, done by udp_output - */ - udp_output(so, m, &addr); - } /* rx error */ - } /* if ping packet */ -} - -/* - * sendto() a socket - */ -int -sosendto(so, m) - struct socket *so; - struct mbuf *m; -{ - int ret; - struct sockaddr_in addr; - - DEBUG_CALL("sosendto"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("m = %lx", (long)m); - - addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { - /* It's an alias */ - switch(ntohl(so->so_faddr.s_addr) & 0xff) { - case CTL_DNS: - addr.sin_addr = dns_addr; - break; - case CTL_ALIAS: - default: - addr.sin_addr = loopback_addr; - break; - } - } else - addr.sin_addr = so->so_faddr; - addr.sin_port = so->so_fport; - - char addrstr[INET_ADDRSTRLEN]; - DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", - ntohs(addr.sin_port), inet_ntop(AF_INET, &addr.sin_addr, addrstr, sizeof(addrstr)))); - - /* Don't care what port we get */ - ret = sendto(so->s, m->m_data, m->m_len, 0, - (struct sockaddr *)&addr, sizeof (struct sockaddr)); - if (ret < 0) - return -1; - - /* - * Kill the socket if there's no reply in 4 minutes, - * but only if it's an expirable socket - */ - if (so->so_expire) - so->so_expire = curtime + SO_EXPIRE; - so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ - return 0; -} - -/* - * XXX This should really be tcp_listen - */ -struct socket * -solisten(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; -{ - struct sockaddr_in addr; - struct socket *so; - int s; - socklen_t addrlen = sizeof(addr); - int opt = 1; - - DEBUG_CALL("solisten"); - DEBUG_ARG("port = %d", port); - DEBUG_ARG("laddr = %x", laddr); - DEBUG_ARG("lport = %d", lport); - DEBUG_ARG("flags = %x", flags); - - if ((so = socreate()) == NULL) { - /* free(so); Not sofree() ??? free(NULL) == NOP */ - return NULL; - } - - /* Don't tcp_attach... we don't need so_snd nor so_rcv */ - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { - free(so); - return NULL; - } - insque(so,&tcb); - - /* - * SS_FACCEPTONCE sockets must time out. - */ - if (flags & SS_FACCEPTONCE) - so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; - - so->so_state = (SS_FACCEPTCONN|flags); - so->so_lport = lport; /* Kept in network format */ - so->so_laddr.s_addr = laddr; /* Ditto */ - - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = port; - - if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || - (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || - (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || - (listen(s,1) < 0)) { - int error = WSAGetLastError(); /* Don't clobber the real reason we failed */ - - close(s); - sofree(so); - /* Restore the real errno */ - WSASetLastError(error); - return NULL; - } - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); - - getsockname(s,(struct sockaddr *)&addr,&addrlen); - so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; - else - so->so_faddr = addr.sin_addr; - - so->s = s; - return so; -} - -/* - * Data is available in so_rcv - * Just write() the data to the socket - * XXX not yet... - */ -void -sorwakeup(so) - struct socket *so; -{ -/* sowrite(so); */ -/* FD_CLR(so->s,&writefds); */ -} - -/* - * Data has been freed in so_snd - * We have room for a read() if we want to - * For now, don't read, it'll be done in the main loop - */ -void -sowwakeup(so) - struct socket *so; -{ - /* Nothing, yet */ -} - -/* - * Various session state calls - * XXX Should be #define's - * The socket state stuff needs work, these often get call 2 or 3 - * times each when only 1 was needed - */ -void -soisfconnecting(so) - register struct socket *so; -{ - so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| - SS_FCANTSENDMORE|SS_FWDRAIN); - so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ -} - -void -soisfconnected(so) - register struct socket *so; -{ - so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); - so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ -} - -void -sofcantrcvmore(so) - struct socket *so; -{ - if ((so->so_state & SS_NOFDREF) == 0) { - shutdown(so->s,0); - if(global_writefds) { - FD_CLR(so->s,global_writefds); - } - } - so->so_state &= ~(SS_ISFCONNECTING); - if (so->so_state & SS_FCANTSENDMORE) - so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */ - else - so->so_state |= SS_FCANTRCVMORE; -} - -void -sofcantsendmore(so) - struct socket *so; -{ - if ((so->so_state & SS_NOFDREF) == 0) { - shutdown(so->s,1); /* send FIN to fhost */ - if (global_readfds) { - FD_CLR(so->s,global_readfds); - } - if (global_xfds) { - FD_CLR(so->s,global_xfds); - } - } - so->so_state &= ~(SS_ISFCONNECTING); - if (so->so_state & SS_FCANTRCVMORE) - so->so_state = SS_NOFDREF; /* as above */ - else - so->so_state |= SS_FCANTSENDMORE; -} - -void -soisfdisconnected(so) - struct socket *so; -{ -/* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ -/* close(so->s); */ -/* so->so_state = SS_ISFDISCONNECTED; */ - /* - * XXX Do nothing ... ? - */ -} - -/* - * Set write drain mode - * Set CANTSENDMORE once all data has been write()n - */ -void -sofwdrain(so) - struct socket *so; -{ - if (so->so_rcv.sb_cc) - so->so_state |= SS_FWDRAIN; - else - sofcantsendmore(so); -} - diff --git a/BasiliskII/src/slirp/socket.h b/BasiliskII/src/slirp/socket.h deleted file mode 100644 index 3b0fee16..00000000 --- a/BasiliskII/src/slirp/socket.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -/* MINE */ - -#ifndef _SLIRP_SOCKET_H_ -#define _SLIRP_SOCKET_H_ - -#define SO_EXPIRE 240000 -#define SO_EXPIREFAST 10000 - -/* - * Our socket structure - */ - -struct socket { - struct socket *so_next,*so_prev; /* For a linked list of sockets */ - - int s; /* The actual socket */ - - /* XXX union these with not-yet-used sbuf params */ - struct mbuf *so_m; /* Pointer to the original SYN packet, - * for non-blocking connect()'s, and - * PING reply's */ - struct tcpiphdr *so_ti; /* Pointer to the original ti within - * so_mconn, for non-blocking connections */ - int so_urgc; - struct in_addr so_faddr; /* foreign host table entry */ - struct in_addr so_laddr; /* local host table entry */ - u_int16_t so_fport; /* foreign port */ - u_int16_t so_lport; /* local port */ - - u_int8_t so_iptos; /* Type of service */ - u_int8_t so_emu; /* Is the socket emulated? */ - - u_char so_type; /* Type of socket, UDP or TCP */ - int so_state; /* internal state flags SS_*, below */ - - struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ - u_int so_expire; /* When the socket will expire */ - - int so_queued; /* Number of packets queued from this socket */ - int so_nqueued; /* Number of packets queued in a row - * Used to determine when to "downgrade" a session - * from fastq to batchq */ - - struct sbuf so_rcv; /* Receive buffer */ - struct sbuf so_snd; /* Send buffer */ - void * extra; /* Extra pointer */ -}; - - -/* - * Socket state bits. (peer means the host on the Internet, - * local host means the host on the other end of the modem) - */ -#define SS_NOFDREF 0x001 /* No fd reference */ - -#define SS_ISFCONNECTING 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */ -#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */ -#define SS_FCANTRCVMORE 0x008 /* Socket can't receive more from peer (for half-closes) */ -#define SS_FCANTSENDMORE 0x010 /* Socket can't send more to peer (for half-closes) */ -/* #define SS_ISFDISCONNECTED 0x020*/ /* Socket has disconnected from peer, in 2MSL state */ -#define SS_FWDRAIN 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */ - -#define SS_CTL 0x080 -#define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */ -#define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */ - -extern struct socket tcb; - - -#if defined(DECLARE_IOVEC) && !defined(HAVE_READV) -struct iovec { - char *iov_base; - size_t iov_len; -}; -#endif - -void so_init(void); -struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int); -struct socket * socreate(void); -void sofree(struct socket *); -int soread(struct socket *); -void sorecvoob(struct socket *); -int sosendoob(struct socket *); -int sowrite(struct socket *); -void sorecvfrom(struct socket *); -int sosendto(struct socket *, struct mbuf *); -struct socket * solisten(u_int, u_int32_t, u_int, int); -void sorwakeup(struct socket *); -void sowwakeup(struct socket *); -void soisfconnecting(register struct socket *); -void soisfconnected(register struct socket *); -void sofcantrcvmore(struct socket *); -void sofcantsendmore(struct socket *); -void soisfdisconnected(struct socket *); -void sofwdrain(struct socket *); - -#endif /* _SOCKET_H_ */ diff --git a/BasiliskII/src/slirp/tcp.h b/BasiliskII/src/slirp/tcp.h deleted file mode 100644 index 24e7914a..00000000 --- a/BasiliskII/src/slirp/tcp.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp.h 8.1 (Berkeley) 6/10/93 - * tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp - */ - -#ifndef _TCP_H_ -#define _TCP_H_ - -typedef u_int32_t tcp_seq; - -#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ -#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ - -extern size_t tcp_rcvspace; -extern size_t tcp_sndspace; -extern struct socket *tcp_last_so; - -#define TCP_SNDSPACE 8192 -#define TCP_RCVSPACE 8192 - -/* - * TCP header. - * Per RFC 793, September, 1981. - */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct tcphdr { - u_int16_t th_sport; /* source port */ - u_int16_t th_dport; /* destination port */ - tcp_seq th_seq; /* sequence number */ - tcp_seq th_ack; /* acknowledgement number */ -#ifdef WORDS_BIGENDIAN - u_char th_off:4, /* data offset */ - th_x2:4; /* (unused) */ -#else - u_char th_x2:4, /* (unused) */ - th_off:4; /* data offset */ -#endif - u_int8_t th_flags; -#define TH_FIN 0x01 -#define TH_SYN 0x02 -#define TH_RST 0x04 -#define TH_PUSH 0x08 -#define TH_ACK 0x10 -#define TH_URG 0x20 - u_int16_t th_win; /* window */ - u_int16_t th_sum; /* checksum */ - u_int16_t th_urp; /* urgent pointer */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -#include "tcp_var.h" - -#define TCPOPT_EOL 0 -#define TCPOPT_NOP 1 -#define TCPOPT_MAXSEG 2 -#define TCPOLEN_MAXSEG 4 -#define TCPOPT_WINDOW 3 -#define TCPOLEN_WINDOW 3 -#define TCPOPT_SACK_PERMITTED 4 /* Experimental */ -#define TCPOLEN_SACK_PERMITTED 2 -#define TCPOPT_SACK 5 /* Experimental */ -#define TCPOPT_TIMESTAMP 8 -#define TCPOLEN_TIMESTAMP 10 -#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ - -#define TCPOPT_TSTAMP_HDR \ - (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) - -/* - * Default maximum segment size for TCP. - * With an IP MSS of 576, this is 536, - * but 512 is probably more convenient. - * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). - * - * We make this 1460 because we only care about Ethernet in the qemu context. - */ -#define TCP_MSS 1460 - -#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ - -#define TCP_MAX_WINSHIFT 14 /* maximum window shift */ - -/* - * User-settable options (used with setsockopt). - * - * We don't use the system headers on unix because we have conflicting - * local structures. We can't avoid the system definitions on Windows, - * so we undefine them. - */ -#undef TCP_NODELAY -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#undef TCP_MAXSEG -/* #define TCP_MAXSEG 0x02 */ /* set maximum segment size */ - -/* - * TCP FSM state definitions. - * Per RFC793, September, 1981. - */ - -#define TCP_NSTATES 11 - -#define TCPS_CLOSED 0 /* closed */ -#define TCPS_LISTEN 1 /* listening for connection */ -#define TCPS_SYN_SENT 2 /* active, have sent syn */ -#define TCPS_SYN_RECEIVED 3 /* have send and received syn */ -/* states < TCPS_ESTABLISHED are those where connections not established */ -#define TCPS_ESTABLISHED 4 /* established */ -#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ -/* states > TCPS_CLOSE_WAIT are those where user has closed */ -#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ -#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ -#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ -/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ -#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ -#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ - -#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) -#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) -#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) - -/* - * TCP sequence numbers are 32 bit integers operated - * on with modular arithmetic. These macros can be - * used to compare such integers. - */ -#define SEQ_LT(a,b) ((int)((a)-(b)) < 0) -#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) -#define SEQ_GT(a,b) ((int)((a)-(b)) > 0) -#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0) - -/* - * Macros to initialize tcp sequence numbers for - * send and receive from initial send and receive - * sequence numbers. - */ -#define tcp_rcvseqinit(tp) \ - (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1 - -#define tcp_sendseqinit(tp) \ - (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = (tp)->iss - -#define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ - -extern tcp_seq tcp_iss; /* tcp initial send seq # */ - -extern char *tcpstates[]; - -#endif diff --git a/BasiliskII/src/slirp/tcp_input.c b/BasiliskII/src/slirp/tcp_input.c deleted file mode 100644 index 032e5378..00000000 --- a/BasiliskII/src/slirp/tcp_input.c +++ /dev/null @@ -1,1724 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp_input.c 8.5 (Berkeley) 4/10/94 - * tcp_input.c,v 1.10 1994/10/13 18:36:32 wollman Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include -#include -#include "ip_icmp.h" - -struct socket tcb; - -int tcprexmtthresh = 3; -struct socket *tcp_last_so = &tcb; - -tcp_seq tcp_iss; /* tcp initial send seq # */ - -#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) - -/* for modulo comparisons of timestamps */ -#define TSTMP_LT(a,b) ((int)((a)-(b)) < 0) -#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0) - -/* - * Insert segment ti into reassembly queue of tcp with - * control block tp. Return TH_FIN if reassembly now includes - * a segment with FIN. The macro form does the common case inline - * (segment is the next to be received on an established connection, - * and the queue is empty), avoiding linkage into and removal - * from the queue and repetition of various conversions. - * Set DELACK for segments received in order, but ack immediately - * when segments are out of order (so fast retransmit can work). - */ -#ifdef TCP_ACK_HACK -#define TCP_REASS(tp, ti, m, so, flags) {\ - if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) {\ - if (ti->ti_flags & TH_PUSH) \ - tp->t_flags |= TF_ACKNOW; \ - else \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ - if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend((so), (m)); \ - } else \ - sbappend((so), (m)); \ -/* sorwakeup(so); */ \ - } else {\ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ -} -#else -#define TCP_REASS(tp, ti, m, so, flags) { \ - if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (tcpiphdrp_32)(tp) && \ - (tp)->t_state == TCPS_ESTABLISHED) { \ - tp->t_flags |= TF_DELACK; \ - (tp)->rcv_nxt += (ti)->ti_len; \ - flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ - if (so->so_emu) { \ - if (tcp_emu((so),(m))) sbappend(so, (m)); \ - } else \ - sbappend((so), (m)); \ -/* sorwakeup(so); */ \ - } else { \ - (flags) = tcp_reass((tp), (ti), (m)); \ - tp->t_flags |= TF_ACKNOW; \ - } \ -} -#endif - -int -tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf *m) -{ - register struct tcpiphdr *q; - struct socket *so = tp->t_socket; - int flags; - - /* - * Call with ti==0 after become established to - * force pre-ESTABLISHED data up to user socket. - */ - if (ti == 0) - goto present; - - /* - * Find a segment which begins after this one does. - */ - for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) - if (SEQ_GT(q->ti_seq, ti->ti_seq)) - break; - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { - register int i; - q = (struct tcpiphdr *)q->ti_prev; - /* conversion to int (in i) handles seq wraparound */ - i = q->ti_seq + q->ti_len - ti->ti_seq; - if (i > 0) { - if (i >= ti->ti_len) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; - m_freem(m); - /* - * Try to present any queued data - * at the left window edge to the user. - * This is needed after the 3-WHS - * completes. - */ - goto present; /* ??? */ - } - m_adj(m, i); - ti->ti_len -= i; - ti->ti_seq += i; - } - q = (struct tcpiphdr *)(q->ti_next); - } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (q != (struct tcpiphdr *)tp) { - register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; - if (i <= 0) - break; - if (i < q->ti_len) { - q->ti_seq += i; - q->ti_len -= i; - m_adj((struct mbuf *) REASS_MBUF(q), i); - break; - } - q = (struct tcpiphdr *)q->ti_next; - m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque_32((void *)(q->ti_prev)); - m_freem(m); - } - - /* - * Stick new segment in its place. - */ - insque_32(ti, (void *)(q->ti_prev)); - -present: - /* - * Present data to user, advancing rcv_nxt through - * completed sequence space. - */ - if (!TCPS_HAVEESTABLISHED(tp->t_state)) - return (0); - ti = (struct tcpiphdr *) tp->seg_next; - if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) - return (0); - if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) - return (0); - do { - tp->rcv_nxt += ti->ti_len; - flags = ti->ti_flags & TH_FIN; - remque_32(ti); - m = (struct mbuf *) REASS_MBUF(ti); /* XXX */ - ti = (struct tcpiphdr *)ti->ti_next; -/* if (so->so_state & SS_FCANTRCVMORE) */ - if (so->so_state & SS_FCANTSENDMORE) - m_freem(m); - else { - if (so->so_emu) { - if (tcp_emu(so,m)) sbappend(so, m); - } else - sbappend(so, m); - } - } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); -/* sorwakeup(so); */ - return (flags); -} - -/* - * TCP input routine, follows pages 65-76 of the - * protocol specification dated September, 1981 very closely. - */ -void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) -{ - struct ip save_ip, *ip; - register struct tcpiphdr *ti; - caddr_t optp = NULL; - int optlen = 0; - int len, tlen, off; - register struct tcpcb *tp = 0; - register int tiflags; - struct socket *so = 0; - int todrop; - u_int acked; - int ourfinisacked, needoutput = 0; - /* int dropsocket = 0; */ - int iss = 0; - u_long tiwin; - int ret; - /* int ts_present = 0; */ - - DEBUG_CALL("tcp_input"); - DEBUG_ARGS((dfd, " m = %8lx iphlen = %2d inso = %lx\n", - (long)m, iphlen, (long)inso)); - - /* - * If called with m == 0, then we're continuing the connect - */ - if (m == NULL) { - so = inso; - - /* Re-set a few variables */ - tp = sototcpcb(so); - m = so->so_m; - so->so_m = 0; - ti = so->so_ti; - tiwin = ti->ti_win; - tiflags = ti->ti_flags; - - goto cont_conn; - } - - - tcpstat.tcps_rcvtotal++; - /* - * Get IP and TCP header together in first mbuf. - * Note: IP leaves IP header in first mbuf. - */ - ti = mtod(m, struct tcpiphdr *); - if (iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } - /* XXX Check if too short */ - - - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - ip = mtod(m, struct ip *); - save_ip = *ip; - save_ip.ip_len += iphlen; - - /* - * Checksum extended TCP header and data. - */ - tlen = ((struct ip *)ti)->ip_len; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; - ti->ti_len = htons((u_int16_t)tlen); - len = sizeof(struct ip) + tlen; - /* keep checksum for ICMP reply - * ti->ti_sum = cksum(m, len); - * if (ti->ti_sum) { */ - if (cksum(m, len)) { - tcpstat.tcps_rcvbadsum++; - goto drop; - } - - /* - * Check that TCP offset makes sense, - * pull out TCP options and adjust length. XXX - */ - off = ti->ti_off << 2; - if (off < sizeof(struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; - goto drop; - } - tlen -= off; - ti->ti_len = tlen; - if (off > sizeof(struct tcphdr)) { - optlen = off - sizeof(struct tcphdr); - optp = mtod(m, caddr_t) + sizeof(struct tcpiphdr); - - /* - * Do quick retrieval of timestamp options ("options - * prediction?"). If timestamp is the only option and it's - * formatted as recommended in RFC 1323 appendix A, we - * quickly get the values now and not bother calling - * tcp_dooptions(), etc. - */ - /* if ((optlen == TCPOLEN_TSTAMP_APPA || - * (optlen > TCPOLEN_TSTAMP_APPA && - * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && - * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && - * (ti->ti_flags & TH_SYN) == 0) { - * ts_present = 1; - * ts_val = ntohl(*(u_int32_t *)(optp + 4)); - * ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); - * optp = NULL; / * we've parsed the options * / - * } - */ - } - tiflags = ti->ti_flags; - - /* - * Convert TCP protocol specific fields to host format. - */ - NTOHL(ti->ti_seq); - NTOHL(ti->ti_ack); - NTOHS(ti->ti_win); - NTOHS(ti->ti_urp); - - /* - * Drop TCP, IP headers and TCP options. - */ - m->m_data += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - m->m_len -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - - /* - * Locate pcb for segment. - */ -findso: - so = tcp_last_so; - if (so->so_fport != ti->ti_dport || - so->so_lport != ti->ti_sport || - so->so_laddr.s_addr != ti->ti_src.s_addr || - so->so_faddr.s_addr != ti->ti_dst.s_addr) { - so = solookup(&tcb, ti->ti_src, ti->ti_sport, - ti->ti_dst, ti->ti_dport); - if (so) - tcp_last_so = so; - ++tcpstat.tcps_socachemiss; - } - - /* - * If the state is CLOSED (i.e., TCB does not exist) then - * all data in the incoming segment is discarded. - * If the TCB exists but is in CLOSED state, it is embryonic, - * but should either do a listen or a connect soon. - * - * state == CLOSED means we've done socreate() but haven't - * attached it to a protocol yet... - * - * XXX If a TCB does not exist, and the TH_SYN flag is - * the only flag set, then create a session, mark it - * as if it was LISTENING, and continue... - */ - if (so == 0) { - if ((tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) != TH_SYN) - goto dropwithreset; - - if ((so = socreate()) == NULL) - goto dropwithreset; - if (tcp_attach(so) < 0) { - free(so); /* Not sofree (if it failed, it's not insqued) */ - goto dropwithreset; - } - - sbreserve(&so->so_snd, tcp_sndspace); - sbreserve(&so->so_rcv, tcp_rcvspace); - - /* tcp_last_so = so; */ /* XXX ? */ - /* tp = sototcpcb(so); */ - - so->so_laddr = ti->ti_src; - so->so_lport = ti->ti_sport; - so->so_faddr = ti->ti_dst; - so->so_fport = ti->ti_dport; - - if ((so->so_iptos = tcp_tos(so)) == 0) - so->so_iptos = ((struct ip *)ti)->ip_tos; - - tp = sototcpcb(so); - tp->t_state = TCPS_LISTEN; - } - - /* - * If this is a still-connecting socket, this probably - * a retransmit of the SYN. Whether it's a retransmit SYN - * or something else, we nuke it. - */ - if (so->so_state & SS_ISFCONNECTING) - goto drop; - - tp = sototcpcb(so); - - /* XXX Should never fail */ - if (tp == 0) - goto dropwithreset; - if (tp->t_state == TCPS_CLOSED) - goto drop; - - /* Unscale the window into a 32-bit value. */ -/* if ((tiflags & TH_SYN) == 0) - * tiwin = ti->ti_win << tp->snd_scale; - * else - */ - tiwin = ti->ti_win; - - /* - * Segment received on connection. - * Reset idle time and keep-alive timer. - */ - tp->t_idle = 0; - if (so_options) - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; - else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - - /* - * Process options if not in LISTEN state, - * else do it below (after getting remote address). - */ - if (optp && tp->t_state != TCPS_LISTEN) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); - /* , */ - /* &ts_present, &ts_val, &ts_ecr); */ - - /* - * Header prediction: check for the two common cases - * of a uni-directional data xfer. If the packet has - * no control flags, is in-sequence, the window didn't - * change and we're not retransmitting, it's a - * candidate. If the length is zero and the ack moved - * forward, we're the sender side of the xfer. Just - * free the data acked & wake any higher level process - * that was blocked waiting for space. If the length - * is non-zero and the ack didn't move, we're the - * receiver side. If we're getting packets in-order - * (the reassembly queue is empty), add the data to - * the socket buffer and note that we need a delayed ack. - * - * XXX Some of these tests are not needed - * eg: the tiwin == tp->snd_wnd prevents many more - * predictions.. with no *real* advantage.. - */ - if (tp->t_state == TCPS_ESTABLISHED && - (tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) == TH_ACK && - /* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */ - ti->ti_seq == tp->rcv_nxt && - tiwin && tiwin == tp->snd_wnd && - tp->snd_nxt == tp->snd_max) { - /* - * If last ACK falls within this segment's sequence numbers, - * record the timestamp. - */ - /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && - * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { - * tp->ts_recent_age = tcp_now; - * tp->ts_recent = ts_val; - * } - */ - if (ti->ti_len == 0) { - if (SEQ_GT(ti->ti_ack, tp->snd_una) && - SEQ_LEQ(ti->ti_ack, tp->snd_max) && - tp->snd_cwnd >= tp->snd_wnd) { - /* - * this is a pure ack for outstanding data. - */ - ++tcpstat.tcps_predack; - /* if (ts_present) - * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); - * else - */ if (tp->t_rtt && -SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); - acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; - sbdrop(&so->so_snd, acked); - tp->snd_una = ti->ti_ack; - m_freem(m); - - /* - * If all outstanding data are acked, stop - * retransmit timer, otherwise restart timer - * using current (possibly backed-off) value. - * If process is waiting for space, - * wakeup/selwakeup/signal. If data - * are ready to send, let tcp_output - * decide between more output or persist. - */ - if (tp->snd_una == tp->snd_max) - tp->t_timer[TCPT_REXMT] = 0; - else if (tp->t_timer[TCPT_PERSIST] == 0) - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - - /* - * There's room in so_snd, sowwakup will read() - * from the socket if we can - */ - /* if (so->so_snd.sb_flags & SB_NOTIFY) - * sowwakeup(so); - */ - /* - * This is called because sowwakeup might have - * put data into so_snd. Since we don't so sowwakeup, - * we don't need this.. XXX??? - */ - if (so->so_snd.sb_cc) - (void) tcp_output(tp); - - return; - } - } - else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (tcpiphdrp_32)tp && - ti->ti_len <= sbspace(&so->so_rcv)) { - /* - * this is a pure, in-sequence data packet - * with nothing on the reassembly queue and - * we have enough buffer space to take it. - */ - ++tcpstat.tcps_preddat; - tp->rcv_nxt += ti->ti_len; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += ti->ti_len; - /* - * Add data to socket buffer. - */ - if (so->so_emu) { - if (tcp_emu(so, m)) sbappend(so, m); - } - else - sbappend(so, m); - - /* - * XXX This is called when data arrives. Later, check - * if we can actually write() to the socket - * XXX Need to check? It's be NON_BLOCKING - */ - /* sorwakeup(so); */ - - /* - * If this is a short packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - * - * It is better to not delay acks at all to maximize - * TCP throughput. See RFC 2581. - */ - tp->t_flags |= TF_ACKNOW; - tcp_output(tp); - return; - } - } /* header prediction */ - /* - * Calculate amount of space in receive window, - * and then do TCP input processing. - * Receive window is amount of space in rcv queue, - * but not less than advertised window. - */ - { int win; - win = sbspace(&so->so_rcv); - if (win < 0) - win = 0; - tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt)); - } - - switch (tp->t_state) { - - /* - * If the state is LISTEN then ignore segment if it contains an RST. - * If the segment contains an ACK then it is bad and send a RST. - * If it does not contain a SYN then it is not interesting; drop it. - * Don't bother responding if the destination was a broadcast. - * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial - * tp->iss, and send a segment: - * - * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. - * Fill in remote peer address fields if not previously specified. - * Enter SYN_RECEIVED state, and process any other fields of this - * segment in this state. - */ - case TCPS_LISTEN: { - - if (tiflags & TH_RST) - goto drop; - if (tiflags & TH_ACK) - goto dropwithreset; - if ((tiflags & TH_SYN) == 0) - goto drop; - - /* - * This has way too many gotos... - * But a bit of spaghetti code never hurt anybody :) - */ - - /* - * If this is destined for the control address, then flag to - * tcp_ctl once connected, otherwise connect - */ - if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { - int lastbyte = ntohl(so->so_faddr.s_addr) & 0xff; - if (lastbyte != CTL_ALIAS && lastbyte != CTL_DNS) { -#if 0 - if (lastbyte == CTL_CMD || lastbyte == CTL_EXEC) { - /* Command or exec adress */ - so->so_state |= SS_CTL; - } - else -#endif - { - /* May be an add exec */ - struct ex_list *ex_ptr; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_fport == so->so_fport && - lastbyte == ex_ptr->ex_addr) { - so->so_state |= SS_CTL; - break; - } - } - } - if (so->so_state & SS_CTL) goto cont_input; - } - /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ - } - - if (so->so_emu & EMU_NOCONNECT) { - so->so_emu &= ~EMU_NOCONNECT; - goto cont_input; - } - - if (tcp_fconnect(so) == -1) { - int error = WSAGetLastError(); - if ((error != WSAEINPROGRESS) && (error != WSAEWOULDBLOCK)) { - u_char code = ICMP_UNREACH_NET; - DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n", - errno, strerror(errno))); - if (error == WSAECONNREFUSED) { - /* ACK the SYN, send RST to refuse the connection */ - tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq)0, - TH_RST | TH_ACK); - } - else { - if (error == WSAEHOSTUNREACH) code = ICMP_UNREACH_HOST; - HTONL(ti->ti_seq); /* restore tcp header */ - HTONL(ti->ti_ack); - HTONS(ti->ti_win); - HTONS(ti->ti_urp); - m->m_data -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - m->m_len += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - *ip = save_ip; - icmp_error(m, ICMP_UNREACH, code, 0, strerror(errno)); - } - tp = tcp_close(tp); - m_free(m); - return; - } - } - - /* - * Haven't connected yet, save the current mbuf - * and ti, and return - * XXX Some OS's don't tell us whether the connect() - * succeeded or not. So we must time it out. - */ - so->so_m = m; - so->so_ti = ti; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->t_state = TCPS_SYN_RECEIVED; - return; - - cont_conn: - /* m==NULL - * Check if the connect succeeded - */ - if (so->so_state & SS_NOFDREF) { - tp = tcp_close(tp); - goto dropwithreset; - } - cont_input: - tcp_template(tp); - - if (optp) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); - /* , */ - /* &ts_present, &ts_val, &ts_ecr); */ - - if (iss) - tp->iss = iss; - else - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR / 2; - tp->irs = ti->ti_seq; - tcp_sendseqinit(tp); - tcp_rcvseqinit(tp); - tp->t_flags |= TF_ACKNOW; - tp->t_state = TCPS_SYN_RECEIVED; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tcpstat.tcps_accepts++; - goto trimthenstep6; - } /* case TCPS_LISTEN */ - - /* - * If the state is SYN_SENT: - * if seg contains an ACK, but not for our SYN, drop the input. - * if seg contains a RST, then drop the connection. - * if seg does not contain SYN, then drop it. - * Otherwise this is an acceptable SYN segment - * initialize tp->rcv_nxt and tp->irs - * if seg contains ack then advance tp->snd_una - * if SYN has been acked change to ESTABLISHED else SYN_RCVD state - * arrange for segment to be acked (eventually) - * continue processing rest of data/controls, beginning with URG - */ - case TCPS_SYN_SENT: - if ((tiflags & TH_ACK) && - (SEQ_LEQ(ti->ti_ack, tp->iss) || - SEQ_GT(ti->ti_ack, tp->snd_max))) - goto dropwithreset; - - if (tiflags & TH_RST) { - if (tiflags & TH_ACK) - tp = tcp_drop(tp, 0); /* XXX Check t_softerror! */ - goto drop; - } - - if ((tiflags & TH_SYN) == 0) - goto drop; - if (tiflags & TH_ACK) { - tp->snd_una = ti->ti_ack; - if (SEQ_LT(tp->snd_nxt, tp->snd_una)) - tp->snd_nxt = tp->snd_una; - } - - tp->t_timer[TCPT_REXMT] = 0; - tp->irs = ti->ti_seq; - tcp_rcvseqinit(tp); - tp->t_flags |= TF_ACKNOW; - if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { - tcpstat.tcps_connects++; - soisfconnected(so); - tp->t_state = TCPS_ESTABLISHED; - - /* Do window scaling on this connection? */ -/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == - * (TF_RCVD_SCALE|TF_REQ_SCALE)) { - * tp->snd_scale = tp->requested_s_scale; - * tp->rcv_scale = tp->request_r_scale; - * } - */ - (void)tcp_reass(tp, (struct tcpiphdr *)0, - (struct mbuf *)0); - /* - * if we didn't have to retransmit the SYN, - * use its rtt as our initial srtt & rtt var. - */ - if (tp->t_rtt) - tcp_xmit_timer(tp, tp->t_rtt); - } - else - tp->t_state = TCPS_SYN_RECEIVED; - - trimthenstep6: - /* - * Advance ti->ti_seq to correspond to first data byte. - * If data, trim to stay within window, - * dropping FIN if necessary. - */ - ti->ti_seq++; - if (ti->ti_len > tp->rcv_wnd) { - todrop = ti->ti_len - tp->rcv_wnd; - m_adj(m, -todrop); - ti->ti_len = tp->rcv_wnd; - tiflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; - } - tp->snd_wl1 = ti->ti_seq - 1; - tp->rcv_up = ti->ti_seq; - goto step6; - } /* switch tp->t_state */ - /* - * States other than LISTEN or SYN_SENT. - * First check timestamp, if present. - * Then check that at least some bytes of segment are within - * receive window. If segment begins before rcv_nxt, - * drop leading data (and SYN); if nothing left, just ack. - * - * RFC 1323 PAWS: If we have a timestamp reply on this segment - * and it's less than ts_recent, drop it. - */ - /* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && - * TSTMP_LT(ts_val, tp->ts_recent)) { - * - */ /* Check to see if ts_recent is over 24 days old. */ - /* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { - */ /* - * * Invalidate ts_recent. If this segment updates - * * ts_recent, the age will be reset later and ts_recent - * * will get a valid value. If it does not, setting - * * ts_recent to zero will at least satisfy the - * * requirement that zero be placed in the timestamp - * * echo reply when ts_recent isn't valid. The - * * age isn't reset until we get a valid ts_recent - * * because we don't want out-of-order segments to be - * * dropped when ts_recent is old. - * */ - /* tp->ts_recent = 0; - * } else { - * tcpstat.tcps_rcvduppack++; - * tcpstat.tcps_rcvdupbyte += ti->ti_len; - * tcpstat.tcps_pawsdrop++; - * goto dropafterack; - * } - * } - */ - - todrop = tp->rcv_nxt - ti->ti_seq; - if (todrop > 0) { - if (tiflags & TH_SYN) { - tiflags &= ~TH_SYN; - ti->ti_seq++; - if (ti->ti_urp > 1) - ti->ti_urp--; - else - tiflags &= ~TH_URG; - todrop--; - } - /* - * Following if statement from Stevens, vol. 2, p. 960. - */ - if (todrop > ti->ti_len - || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { - /* - * Any valid FIN must be to the left of the window. - * At this point the FIN must be a duplicate or out - * of sequence; drop it. - */ - tiflags &= ~TH_FIN; - - /* - * Send an ACK to resynchronize and drop any data. - * But keep on processing for RST or ACK. - */ - tp->t_flags |= TF_ACKNOW; - todrop = ti->ti_len; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; - } - else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; - } - m_adj(m, todrop); - ti->ti_seq += todrop; - ti->ti_len -= todrop; - if (ti->ti_urp > todrop) - ti->ti_urp -= todrop; - else { - tiflags &= ~TH_URG; - ti->ti_urp = 0; - } - } - /* - * If new data are received on a connection after the - * user processes are gone, then RST the other end. - */ - if ((so->so_state & SS_NOFDREF) && - tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { - tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; - goto dropwithreset; - } - - /* - * If segment ends after window, drop trailing data - * (and PUSH and FIN); if nothing left, just ACK. - */ - todrop = (ti->ti_seq + ti->ti_len) - (tp->rcv_nxt + tp->rcv_wnd); - if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; - if (todrop >= ti->ti_len) { - tcpstat.tcps_rcvbyteafterwin += ti->ti_len; - /* - * If a new connection request is received - * while in TIME_WAIT, drop the old connection - * and start over if the sequence numbers - * are above the previous ones. - */ - if (tiflags & TH_SYN && - tp->t_state == TCPS_TIME_WAIT && - SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { - iss = tp->rcv_nxt + TCP_ISSINCR; - tp = tcp_close(tp); - goto findso; - } - /* - * If window is closed can only take segments at - * window edge, and have to drop data and PUSH from - * incoming segments. Continue processing, but - * remember to ack. Otherwise, drop segment - * and ack. - */ - if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { - tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; - } - else - goto dropafterack; - } - else - tcpstat.tcps_rcvbyteafterwin += todrop; - m_adj(m, -todrop); - ti->ti_len -= todrop; - tiflags &= ~(TH_PUSH | TH_FIN); - } - - /* - * If last ACK falls within this segment's sequence numbers, - * record its timestamp. - */ - /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && - * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + - * ((tiflags & (TH_SYN|TH_FIN)) != 0))) { - * tp->ts_recent_age = tcp_now; - * tp->ts_recent = ts_val; - * } - */ - - /* - * If the RST bit is set examine the state: - * SYN_RECEIVED STATE: - * If passive open, return to LISTEN state. - * If active open, inform user that connection was refused. - * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: - * Inform user that connection was reset, and close tcb. - * CLOSING, LAST_ACK, TIME_WAIT STATES - * Close the tcb. - */ - if (tiflags&TH_RST) switch (tp->t_state) { - - case TCPS_SYN_RECEIVED: - /* so->so_error = ECONNREFUSED; */ - goto close; - - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - /* so->so_error = ECONNRESET; */ - close: - tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; - tp = tcp_close(tp); - goto drop; - - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - tp = tcp_close(tp); - goto drop; - } - - /* - * If a SYN is in the window, then this is an - * error and we send an RST and drop the connection. - */ - if (tiflags & TH_SYN) { - tp = tcp_drop(tp, 0); - goto dropwithreset; - } - - /* - * If the ACK bit is off we drop the segment and return. - */ - if ((tiflags & TH_ACK) == 0) goto drop; - - /* - * Ack processing. - */ - switch (tp->t_state) { - /* - * In SYN_RECEIVED state if the ack ACKs our SYN then enter - * ESTABLISHED state and continue processing, otherwise - * send an RST. una<=ack<=max - */ - case TCPS_SYN_RECEIVED: - - if (SEQ_GT(tp->snd_una, ti->ti_ack) || - SEQ_GT(ti->ti_ack, tp->snd_max)) - goto dropwithreset; - tcpstat.tcps_connects++; - tp->t_state = TCPS_ESTABLISHED; - /* - * The sent SYN is ack'ed with our sequence number +1 - * The first data byte already in the buffer will get - * lost if no correction is made. This is only needed for - * SS_CTL since the buffer is empty otherwise. - * tp->snd_una++; or: - */ - tp->snd_una = ti->ti_ack; - if (so->so_state & SS_CTL) { - /* So tcp_ctl reports the right state */ - ret = tcp_ctl(so); - if (ret == 1) { - soisfconnected(so); - so->so_state &= ~SS_CTL; /* success XXX */ - } - else if (ret == 2) { - so->so_state = SS_NOFDREF; /* CTL_CMD */ - } - else { - needoutput = 1; - tp->t_state = TCPS_FIN_WAIT_1; - } - } - else { - soisfconnected(so); - } - - /* Do window scaling? */ -/* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == - * (TF_RCVD_SCALE|TF_REQ_SCALE)) { - * tp->snd_scale = tp->requested_s_scale; - * tp->rcv_scale = tp->request_r_scale; - * } - */ - (void)tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); - tp->snd_wl1 = ti->ti_seq - 1; - /* Avoid ack processing; snd_una==ti_ack => dup ack */ - goto synrx_to_est; - /* fall into ... */ - - /* - * In ESTABLISHED state: drop duplicate ACKs; ACK out of range - * ACKs. If the ack is in the range - * tp->snd_una < ti->ti_ack <= tp->snd_max - * then advance tp->snd_una to ti->ti_ack and drop - * data from the retransmission queue. If this ACK reflects - * more up to date window information we update our window information. - */ - case TCPS_ESTABLISHED: - case TCPS_FIN_WAIT_1: - case TCPS_FIN_WAIT_2: - case TCPS_CLOSE_WAIT: - case TCPS_CLOSING: - case TCPS_LAST_ACK: - case TCPS_TIME_WAIT: - - if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { - if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; - DEBUG_MISC((dfd, " dup ack m = %lx so = %lx \n", - (long)m, (long)so)); - /* - * If we have outstanding data (other than - * a window probe), this is a completely - * duplicate ack (ie, window info didn't - * change), the ack is the biggest we've - * seen and we've seen exactly our rexmt - * threshold of them, assume a packet - * has been dropped and retransmit it. - * Kludge snd_nxt & the congestion - * window so we send only this one - * packet. - * - * We know we're losing at the current - * window size so do congestion avoidance - * (set ssthresh to half the current window - * and pull our congestion window back to - * the new ssthresh). - * - * Dup acks mean that packets have left the - * network (they're now cached at the receiver) - * so bump cwnd by the amount in the receiver - * to keep a constant cwnd packets in the - * network. - */ - if (tp->t_timer[TCPT_REXMT] == 0 || - ti->ti_ack != tp->snd_una) - tp->t_dupacks = 0; - else if (++tp->t_dupacks == tcprexmtthresh) { - tcp_seq onxt = tp->snd_nxt; - u_int win = - min(tp->snd_wnd, tp->snd_cwnd) / 2 / - tp->t_maxseg; - - if (win < 2) - win = 2; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_timer[TCPT_REXMT] = 0; - tp->t_rtt = 0; - tp->snd_nxt = ti->ti_ack; - tp->snd_cwnd = tp->t_maxseg; - (void)tcp_output(tp); - tp->snd_cwnd = tp->snd_ssthresh + - tp->t_maxseg * tp->t_dupacks; - if (SEQ_GT(onxt, tp->snd_nxt)) - tp->snd_nxt = onxt; - goto drop; - } - else if (tp->t_dupacks > tcprexmtthresh) { - tp->snd_cwnd += tp->t_maxseg; - (void)tcp_output(tp); - goto drop; - } - } - else - tp->t_dupacks = 0; - break; - } - synrx_to_est: - /* - * If the congestion window was inflated to account - * for the other side's cached packets, retract it. - */ - if (tp->t_dupacks > tcprexmtthresh && - tp->snd_cwnd > tp->snd_ssthresh) - tp->snd_cwnd = tp->snd_ssthresh; - tp->t_dupacks = 0; - if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; - goto dropafterack; - } - acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; - - /* - * If we have a timestamp reply, update smoothed - * round trip time. If no timestamp is present but - * transmit timer is running and timed sequence - * number was acked, update smoothed round trip time. - * Since we now have an rtt measurement, cancel the - * timer backoff (cf., Phil Karn's retransmit alg.). - * Recompute the initial retransmit timer. - */ - /* if (ts_present) - * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); - * else - */ - if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); - - /* - * If all outstanding data is acked, stop retransmit - * timer and remember to restart (more output or persist). - * If there is more data to be acked, restart retransmit - * timer, using current (possibly backed-off) value. - */ - if (ti->ti_ack == tp->snd_max) { - tp->t_timer[TCPT_REXMT] = 0; - needoutput = 1; - } - else if (tp->t_timer[TCPT_PERSIST] == 0) - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - /* - * When new data is acked, open the congestion window. - * If the window gives us less than ssthresh packets - * in flight, open exponentially (maxseg per packet). - * Otherwise open linearly: maxseg per window - * (maxseg^2 / cwnd per packet). - */ - { - register u_int cw = tp->snd_cwnd; - register u_int incr = tp->t_maxseg; - - if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; - tp->snd_cwnd = min(cw + incr, (u_int32_t) (TCP_MAXWIN << tp->snd_scale)); - } - if (acked > so->so_snd.sb_cc) { - tp->snd_wnd -= so->so_snd.sb_cc; - sbdrop(&so->so_snd, so->so_snd.sb_cc); - ourfinisacked = 1; - } - else { - sbdrop(&so->so_snd, acked); - tp->snd_wnd -= acked; - ourfinisacked = 0; - } - /* - * XXX sowwakup is called when data is acked and there's room for - * for more data... it should read() the socket - */ - /* if (so->so_snd.sb_flags & SB_NOTIFY) - * sowwakeup(so); - */ - tp->snd_una = ti->ti_ack; - if (SEQ_LT(tp->snd_nxt, tp->snd_una)) - tp->snd_nxt = tp->snd_una; - - switch (tp->t_state) { - - /* - * In FIN_WAIT_1 STATE in addition to the processing - * for the ESTABLISHED state if our FIN is now acknowledged - * then enter FIN_WAIT_2. - */ - case TCPS_FIN_WAIT_1: - if (ourfinisacked) { - /* - * If we can't receive any more - * data, then closing user can proceed. - * Starting the timer is contrary to the - * specification, but if we don't get a FIN - * we'll hang forever. - */ - if (so->so_state & SS_FCANTRCVMORE) { - soisfdisconnected(so); - tp->t_timer[TCPT_2MSL] = tcp_maxidle; - } - tp->t_state = TCPS_FIN_WAIT_2; - } - break; - - /* - * In CLOSING STATE in addition to the processing for - * the ESTABLISHED state if the ACK acknowledges our FIN - * then enter the TIME-WAIT state, otherwise ignore - * the segment. - */ - case TCPS_CLOSING: - if (ourfinisacked) { - tp->t_state = TCPS_TIME_WAIT; - tcp_canceltimers(tp); - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - soisfdisconnected(so); - } - break; - - /* - * In LAST_ACK, we may still be waiting for data to drain - * and/or to be acked, as well as for the ack of our FIN. - * If our FIN is now acknowledged, delete the TCB, - * enter the closed state and return. - */ - case TCPS_LAST_ACK: - if (ourfinisacked) { - tp = tcp_close(tp); - goto drop; - } - break; - - /* - * In TIME_WAIT state the only thing that should arrive - * is a retransmission of the remote FIN. Acknowledge - * it and restart the finack timer. - */ - case TCPS_TIME_WAIT: - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - goto dropafterack; - } - } /* switch(tp->t_state) */ - -step6: - /* - * Update window information. - * Don't look at window if no ACK: TAC's send garbage on first SYN. - */ - if ((tiflags & TH_ACK) && - (SEQ_LT(tp->snd_wl1, ti->ti_seq) || - (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || - (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { - /* keep track of pure window updates */ - if (ti->ti_len == 0 && - tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; - tp->snd_wnd = tiwin; - tp->snd_wl1 = ti->ti_seq; - tp->snd_wl2 = ti->ti_ack; - if (tp->snd_wnd > tp->max_sndwnd) - tp->max_sndwnd = tp->snd_wnd; - needoutput = 1; - } - - /* - * Process segments with URG. - */ - if ((tiflags & TH_URG) && ti->ti_urp && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { - /* - * This is a kludge, but if we receive and accept - * random urgent pointers, we'll crash in - * soreceive. It's hard to imagine someone - * actually wanting to send this much urgent data. - */ - if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) { - ti->ti_urp = 0; - tiflags &= ~TH_URG; - goto dodata; - } - /* - * If this segment advances the known urgent pointer, - * then mark the data stream. This should not happen - * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since - * a FIN has been received from the remote side. - * In these states we ignore the URG. - * - * According to RFC961 (Assigned Protocols), - * the urgent pointer points to the last octet - * of urgent data. We continue, however, - * to consider it to indicate the first octet - * of data past the urgent section as the original - * spec states (in one of two places). - */ - if (SEQ_GT(ti->ti_seq + ti->ti_urp, tp->rcv_up)) { - tp->rcv_up = ti->ti_seq + ti->ti_urp; - so->so_urgc = so->so_rcv.sb_cc + - (tp->rcv_up - tp->rcv_nxt); /* -1; */ - tp->rcv_up = ti->ti_seq + ti->ti_urp; - - } - } - else - /* - * If no out of band data is expected, - * pull receive urgent pointer along - * with the receive window. - */ - if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) - tp->rcv_up = tp->rcv_nxt; -dodata: - - /* - * Process the segment text, merging it into the TCP sequencing queue, - * and arranging for acknowledgment of receipt if necessary. - * This process logically involves adjusting tp->rcv_wnd as data - * is presented to the user (this happens in tcp_usrreq.c, - * case PRU_RCVD). If a FIN has already been received on this - * connection then we just ignore the text. - */ - if ((ti->ti_len || (tiflags&TH_FIN)) && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { - TCP_REASS(tp, ti, m, so, tiflags); - /* - * Note the amount of data that peer has sent into - * our window, in order to estimate the sender's - * buffer size. - */ - len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); - } - else { - m_free(m); - tiflags &= ~TH_FIN; - } - - /* - * If FIN is received ACK the FIN and let the user know - * that the connection is closing. - */ - if (tiflags & TH_FIN) { - if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { - /* - * If we receive a FIN we can't send more data, - * set it SS_FDRAIN - * Shutdown the socket if there is no rx data in the - * buffer. - * soread() is called on completion of shutdown() and - * will got to TCPS_LAST_ACK, and use tcp_output() - * to send the FIN. - */ - /* sofcantrcvmore(so); */ - sofwdrain(so); - - tp->t_flags |= TF_ACKNOW; - tp->rcv_nxt++; - } - switch (tp->t_state) { - - /* - * In SYN_RECEIVED and ESTABLISHED STATES - * enter the CLOSE_WAIT state. - */ - case TCPS_SYN_RECEIVED: - case TCPS_ESTABLISHED: - if (so->so_emu == EMU_CTL) /* no shutdown on socket */ - tp->t_state = TCPS_LAST_ACK; - else - tp->t_state = TCPS_CLOSE_WAIT; - break; - - /* - * If still in FIN_WAIT_1 STATE FIN has not been acked so - * enter the CLOSING state. - */ - case TCPS_FIN_WAIT_1: - tp->t_state = TCPS_CLOSING; - break; - - /* - * In FIN_WAIT_2 state enter the TIME_WAIT state, - * starting the time-wait timer, turning off the other - * standard timers. - */ - case TCPS_FIN_WAIT_2: - tp->t_state = TCPS_TIME_WAIT; - tcp_canceltimers(tp); - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - soisfdisconnected(so); - break; - - /* - * In TIME_WAIT state restart the 2 MSL time_wait timer. - */ - case TCPS_TIME_WAIT: - tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; - break; - } - } - - /* - * If this is a small packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - * - * See above. - */ - /* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { - */ - /* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg && - * (so->so_iptos & IPTOS_LOWDELAY) == 0) || - * ((so->so_iptos & IPTOS_LOWDELAY) && - * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { - */ - if (ti->ti_len && (unsigned)ti->ti_len <= 5 && - ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { - tp->t_flags |= TF_ACKNOW; - } - - /* - * Return any desired output. - */ - if (needoutput || (tp->t_flags & TF_ACKNOW)) { - (void)tcp_output(tp); - } - return; - -dropafterack: - /* - * Generate an ACK dropping incoming segment if it occupies - * sequence space, where the ACK reflects our state. - */ - if (tiflags & TH_RST) - goto drop; - m_freem(m); - tp->t_flags |= TF_ACKNOW; - (void)tcp_output(tp); - return; - -dropwithreset: - /* reuses m if m!=NULL, m_free() unnecessary */ - if (tiflags & TH_ACK) - tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); - else { - if (tiflags & TH_SYN) ti->ti_len++; - tcp_respond(tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq)0, - TH_RST | TH_ACK); - } - - return; - -drop: - /* - * Drop space held by incoming segment and return. - */ - m_free(m); - - return; -} - - /* , ts_present, ts_val, ts_ecr) */ -/* int *ts_present; - * u_int32_t *ts_val, *ts_ecr; - */ -void -tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) -{ - u_int16_t mss; - int opt, optlen; - - DEBUG_CALL("tcp_dooptions"); - DEBUG_ARGS((dfd," tp = %lx cnt=%i \n", (long )tp, cnt)); - - for (; cnt > 0; cnt -= optlen, cp += optlen) { - opt = cp[0]; - if (opt == TCPOPT_EOL) - break; - if (opt == TCPOPT_NOP) - optlen = 1; - else { - optlen = cp[1]; - if (optlen <= 0) - break; - } - switch (opt) { - - default: - continue; - - case TCPOPT_MAXSEG: - if (optlen != TCPOLEN_MAXSEG) - continue; - if (!(ti->ti_flags & TH_SYN)) - continue; - memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); - NTOHS(mss); - tcp_mss(tp, mss); /* sets t_maxseg */ - break; - -/* case TCPOPT_WINDOW: - * if (optlen != TCPOLEN_WINDOW) - * continue; - * if (!(ti->ti_flags & TH_SYN)) - * continue; - * tp->t_flags |= TF_RCVD_SCALE; - * tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); - * break; - */ -/* case TCPOPT_TIMESTAMP: - * if (optlen != TCPOLEN_TIMESTAMP) - * continue; - * *ts_present = 1; - * memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val)); - * NTOHL(*ts_val); - * memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); - * NTOHL(*ts_ecr); - * - */ /* - * * A timestamp received in a SYN makes - * * it ok to send timestamp requests and replies. - * */ -/* if (ti->ti_flags & TH_SYN) { - * tp->t_flags |= TF_RCVD_TSTMP; - * tp->ts_recent = *ts_val; - * tp->ts_recent_age = tcp_now; - * } - */ break; - } - } -} - - -/* - * Pull out of band byte out of a segment so - * it doesn't appear in the user's data queue. - * It is still reflected in the segment length for - * sequencing purposes. - */ - -#ifdef notdef - -void tcp_pulloutofband(struct socket *so, struct tcpiphdr *ti, register struct mbuf *m) -{ - int cnt = ti->ti_urp - 1; - - while (cnt >= 0) { - if (m->m_len > cnt) { - char *cp = mtod(m, caddr_t) + cnt; - struct tcpcb *tp = sototcpcb(so); - - tp->t_iobc = *cp; - tp->t_oobflags |= TCPOOB_HAVEDATA; - memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1)); - m->m_len--; - return; - } - cnt -= m->m_len; - m = m->m_next; /* XXX WRONG! Fix it! */ - if (m == 0) - break; - } - panic("tcp_pulloutofband"); -} - -#endif /* notdef */ - -/* - * Collect new round-trip time estimate - * and update averages and current timeout. - */ - -void tcp_xmit_timer(register struct tcpcb *tp, int rtt) -{ - register short delta; - - DEBUG_CALL("tcp_xmit_timer"); - DEBUG_ARG("tp = %lx", (long)tp); - DEBUG_ARG("rtt = %d", rtt); - - tcpstat.tcps_rttupdated++; - if (tp->t_srtt != 0) { - /* - * srtt is stored as fixed point with 3 bits after the - * binary point (i.e., scaled by 8). The following magic - * is equivalent to the smoothing algorithm in rfc793 with - * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed - * point). Adjust rtt to origin 0. - */ - delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); - if ((tp->t_srtt += delta) <= 0) - tp->t_srtt = 1; - /* - * We accumulate a smoothed rtt variance (actually, a - * smoothed mean difference), then set the retransmit - * timer to smoothed rtt + 4 times the smoothed variance. - * rttvar is stored as fixed point with 2 bits after the - * binary point (scaled by 4). The following is - * equivalent to rfc793 smoothing with an alpha of .75 - * (rttvar = rttvar*3/4 + |delta| / 4). This replaces - * rfc793's wired-in beta. - */ - if (delta < 0) - delta = -delta; - delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); - if ((tp->t_rttvar += delta) <= 0) - tp->t_rttvar = 1; - } else { - /* - * No rtt measurement yet - use the unsmoothed rtt. - * Set the variance to half the rtt (so our first - * retransmit happens at 3*rtt). - */ - tp->t_srtt = rtt << TCP_RTT_SHIFT; - tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); - } - tp->t_rtt = 0; - tp->t_rxtshift = 0; - - /* - * the retransmit should happen at rtt + 4 * rttvar. - * Because of the way we do the smoothing, srtt and rttvar - * will each average +1/2 tick of bias. When we compute - * the retransmit timer, we want 1/2 tick of rounding and - * 1 extra tick because of +-1/2 tick uncertainty in the - * firing of the timer. The bias will give us exactly the - * 1.5 tick we need. But, because the bias is - * statistical, we have to test that we don't drop below - * the minimum feasible timer (which is 2 ticks). - */ - TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), - (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ - - /* - * We received an ack for a packet that wasn't retransmitted; - * it is probably safe to discard any error indications we've - * received recently. This isn't quite right, but close enough - * for now (a route might have failed after we sent a segment, - * and the return path might not be symmetrical). - */ - tp->t_softerror = 0; -} - -/* - * Determine a reasonable value for maxseg size. - * If the route is known, check route for mtu. - * If none, use an mss that can be handled on the outgoing - * interface without forcing IP to fragment; if bigger than - * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES - * to utilize large mbufs. If no route is found, route has no mtu, - * or the destination isn't local, use a default, hopefully conservative - * size (usually 512 or the default IP max size, but no more than the mtu - * of the interface), as we can't discover anything about intervening - * gateways or networks. We also initialize the congestion/slow start - * window to be a single segment if the destination isn't local. - * While looking at the routing entry, we also initialize other path-dependent - * parameters from pre-set or cached values in the routing entry. - */ - -u_int tcp_mss(register struct tcpcb *tp, u_int offer) -{ - struct socket *so = tp->t_socket; - u_int mss; - - DEBUG_CALL("tcp_mss"); - DEBUG_ARG("tp = %lx", (long)tp); - DEBUG_ARG("offer = %d", offer); - - mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); - if (offer) - mss = min(mss, offer); - mss = max(mss, 32); - if (mss < tp->t_maxseg || offer != 0) - tp->t_maxseg = mss; - - tp->snd_cwnd = mss; - - sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); - sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); - - DEBUG_MISC((dfd, " returning mss = %d\n", mss)); - - return mss; -} diff --git a/BasiliskII/src/slirp/tcp_output.c b/BasiliskII/src/slirp/tcp_output.c deleted file mode 100644 index 0d5c0ce5..00000000 --- a/BasiliskII/src/slirp/tcp_output.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp_output.c 8.3 (Berkeley) 12/30/93 - * tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include - -/* - * Since this is only used in "stats socket", we give meaning - * names instead of the REAL names - */ -char *tcpstates[] = { -/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ - "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", - "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", - "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", -}; - -u_char tcp_outflags[TCP_NSTATES] = { - TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, - TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, - TH_FIN|TH_ACK, TH_ACK, TH_ACK, -}; - - -#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ - -/* - * Tcp output routine: figure out what should be sent and send it. - */ -int tcp_output(register struct tcpcb *tp) -{ - register struct socket *so = tp->t_socket; - register u_long len, win; - int off, flags, error; - register struct mbuf *m; - register struct tcpiphdr *ti; - u_char opt[MAX_TCPOPTLEN]; - unsigned optlen, hdrlen; - int idle, sendalot; - - DEBUG_CALL("tcp_output"); - DEBUG_ARG("tp = %lx", (long )tp); - - /* - * Determine length of data that should be transmitted, - * and flags that will be used. - * If there is some data or critical controls (SYN, RST) - * to send, then transmit; otherwise, investigate further. - */ - idle = (tp->snd_max == tp->snd_una); - if (idle && tp->t_idle >= tp->t_rxtcur) - /* - * We have been idle for "a while" and no acks are - * expected to clock out any data we send -- - * slow start to get ack "clock" running again. - */ - tp->snd_cwnd = tp->t_maxseg; -again: - sendalot = 0; - off = tp->snd_nxt - tp->snd_una; - win = min(tp->snd_wnd, tp->snd_cwnd); - - flags = tcp_outflags[tp->t_state]; - - DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags)); - - /* - * If in persist timeout with window of 0, send 1 byte. - * Otherwise, if window is small but nonzero - * and timer expired, we will send what we can - * and go to transmit state. - */ - if (tp->t_force) { - if (win == 0) { - /* - * If we still have some data to send, then - * clear the FIN bit. Usually this would - * happen below when it realizes that we - * aren't sending all the data. However, - * if we have exactly 1 byte of unset data, - * then it won't clear the FIN bit below, - * and if we are in persist state, we wind - * up sending the packet without recording - * that we sent the FIN bit. - * - * We can't just blindly clear the FIN bit, - * because if we don't have any more data - * to send then the probe will be the FIN - * itself. - */ - if (off < (int)so->so_snd.sb_cc) - flags &= ~TH_FIN; - win = 1; - } else { - tp->t_timer[TCPT_PERSIST] = 0; - tp->t_rxtshift = 0; - } - } - - len = min(so->so_snd.sb_cc, win) - off; - - if (len < 0) { - /* - * If FIN has been sent but not acked, - * but we haven't been called to retransmit, - * len will be -1. Otherwise, window shrank - * after we sent into it. If window shrank to 0, - * cancel pending retransmit and pull snd_nxt - * back to (closed) window. We will enter persist - * state below. If the window didn't close completely, - * just wait for an ACK. - */ - len = 0; - if (win == 0) { - tp->t_timer[TCPT_REXMT] = 0; - tp->snd_nxt = tp->snd_una; - } - } - - if (len > tp->t_maxseg) { - len = tp->t_maxseg; - sendalot = 1; - } - if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) - flags &= ~TH_FIN; - - win = sbspace(&so->so_rcv); - - /* - * Sender silly window avoidance. If connection is idle - * and can send all data, a maximum segment, - * at least a maximum default-size segment do it, - * or are forced, do it; otherwise don't bother. - * If peer's buffer is tiny, then send - * when window is at least half open. - * If retransmitting (possibly after persist timer forced us - * to send into a small window), then must resend. - */ - if (len) { - if (len == tp->t_maxseg) - goto send; - if ((1 || idle || tp->t_flags & TF_NODELAY) && - len + off >= so->so_snd.sb_cc) - goto send; - if (tp->t_force) - goto send; - if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) - goto send; - if (SEQ_LT(tp->snd_nxt, tp->snd_max)) - goto send; - } - - /* - * Compare available window to amount of window - * known to peer (as advertised window less - * next expected input). If the difference is at least two - * max size segments, or at least 50% of the maximum possible - * window, then want to send a window update to peer. - */ - if (win > 0) { - /* - * "adv" is the amount we can increase the window, - * taking into account that we are limited by - * TCP_MAXWIN << tp->rcv_scale. - */ - u_int adv = min(win, (u_int)TCP_MAXWIN << tp->rcv_scale) - - (tp->rcv_adv - tp->rcv_nxt); - - if (adv >= (u_int)(2 * tp->t_maxseg)) - goto send; - if (2 * adv >= so->so_rcv.sb_datalen) - goto send; - } - - /* - * Send if we owe peer an ACK. - */ - if (tp->t_flags & TF_ACKNOW) - goto send; - if (flags & (TH_SYN|TH_RST)) - goto send; - if (SEQ_GT(tp->snd_up, tp->snd_una)) - goto send; - /* - * If our state indicates that FIN should be sent - * and we have not yet done so, or we're retransmitting the FIN, - * then we need to send. - */ - if (flags & TH_FIN && - ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) - goto send; - - /* - * TCP window updates are not reliable, rather a polling protocol - * using ``persist'' packets is used to insure receipt of window - * updates. The three ``states'' for the output side are: - * idle not doing retransmits or persists - * persisting to move a small or zero window - * (re)transmitting and thereby not persisting - * - * tp->t_timer[TCPT_PERSIST] - * is set when we are in persist state. - * tp->t_force - * is set when we are called to send a persist packet. - * tp->t_timer[TCPT_REXMT] - * is set when we are retransmitting - * The output side is idle when both timers are zero. - * - * If send window is too small, there is data to transmit, and no - * retransmit or persist is pending, then go to persist state. - * If nothing happens soon, send when timer expires: - * if window is nonzero, transmit what we can, - * otherwise force out a byte. - */ - if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && - tp->t_timer[TCPT_PERSIST] == 0) { - tp->t_rxtshift = 0; - tcp_setpersist(tp); - } - - /* - * No reason to send a segment, just return. - */ - tcpstat.tcps_didnuttin++; - - return (0); - -send: - /* - * Before ESTABLISHED, force sending of initial options - * unless TCP set not to do any options. - * NOTE: we assume that the IP/TCP header plus TCP options - * always fit in a single mbuf, leaving room for a maximum - * link header, i.e. - * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN - */ - optlen = 0; - hdrlen = sizeof (struct tcpiphdr); - if (flags & TH_SYN) { - tp->snd_nxt = tp->iss; - if ((tp->t_flags & TF_NOOPT) == 0) { - u_int16_t mss; - - opt[0] = TCPOPT_MAXSEG; - opt[1] = 4; - mss = htons((u_int16_t) tcp_mss(tp, 0)); - memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss)); - optlen = 4; - -/* if ((tp->t_flags & TF_REQ_SCALE) && - * ((flags & TH_ACK) == 0 || - * (tp->t_flags & TF_RCVD_SCALE))) { - * *((u_int32_t *) (opt + optlen)) = htonl( - * TCPOPT_NOP << 24 | - * TCPOPT_WINDOW << 16 | - * TCPOLEN_WINDOW << 8 | - * tp->request_r_scale); - * optlen += 4; - * } - */ - } - } - - /* - * Send a timestamp and echo-reply if this is a SYN and our side - * wants to use timestamps (TF_REQ_TSTMP is set) or both our side - * and our peer have sent timestamps in our SYN's. - */ -/* if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && - * (flags & TH_RST) == 0 && - * ((flags & (TH_SYN|TH_ACK)) == TH_SYN || - * (tp->t_flags & TF_RCVD_TSTMP))) { - * u_int32_t *lp = (u_int32_t *)(opt + optlen); - * - * / * Form timestamp option as shown in appendix A of RFC 1323. * / - * *lp++ = htonl(TCPOPT_TSTAMP_HDR); - * *lp++ = htonl(tcp_now); - * *lp = htonl(tp->ts_recent); - * optlen += TCPOLEN_TSTAMP_APPA; - * } - */ - hdrlen += optlen; - - /* - * Adjust data length if insertion of options will - * bump the packet length beyond the t_maxseg length. - */ - if (len > tp->t_maxseg - optlen) { - len = tp->t_maxseg - optlen; - sendalot = 1; - } - - /* - * Grab a header mbuf, attaching a copy of data to - * be transmitted, and initialize the header from - * the template for sends on this connection. - */ - if (len) { - if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; - else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; - } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; - } - - m = m_get(); - if (m == NULL) { -/* error = ENOBUFS; */ - error = 1; - goto out; - } - m->m_data += if_maxlinkhdr; - m->m_len = hdrlen; - - /* - * This will always succeed, since we make sure our mbufs - * are big enough to hold one MSS packet + header + ... etc. - */ -/* if (len <= MHLEN - hdrlen - max_linkhdr) { */ - - sbcopy(&so->so_snd, off, len, mtod(m, caddr_t) + hdrlen); - m->m_len += len; - -/* } else { - * m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); - * if (m->m_next == 0) - * len = 0; - * } - */ - /* - * If we're sending everything we've got, set PUSH. - * (This will keep happy those implementations which only - * give data to the user when a buffer fills or - * a PUSH comes in.) - */ - if (off + len == so->so_snd.sb_cc) - flags |= TH_PUSH; - } else { - if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; - else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; - else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; - else - tcpstat.tcps_sndwinup++; - - m = m_get(); - if (m == NULL) { -/* error = ENOBUFS; */ - error = 1; - goto out; - } - m->m_data += if_maxlinkhdr; - m->m_len = hdrlen; - } - - ti = mtod(m, struct tcpiphdr *); - - memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr)); - - /* - * Fill in fields, remembering maximum advertised - * window for use in delaying messages about window sizes. - * If resending a FIN, be sure not to use a new sequence number. - */ - if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && - tp->snd_nxt == tp->snd_max) - tp->snd_nxt--; - /* - * If we are doing retransmissions, then snd_nxt will - * not reflect the first unsent octet. For ACK only - * packets, we do not want the sequence number of the - * retransmitted packet, we want the sequence number - * of the next unsent octet. So, if there is no data - * (and no SYN or FIN), use snd_max instead of snd_nxt - * when filling in ti_seq. But if we are in persist - * state, snd_max might reflect one byte beyond the - * right edge of the window, so use snd_nxt in that - * case, since we know we aren't doing a retransmission. - * (retransmit and persist are mutually exclusive...) - */ - if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST]) - ti->ti_seq = htonl(tp->snd_nxt); - else - ti->ti_seq = htonl(tp->snd_max); - ti->ti_ack = htonl(tp->rcv_nxt); - if (optlen) { - memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen); - ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; - } - ti->ti_flags = flags; - /* - * Calculate receive window. Don't shrink window, - * but avoid silly window syndrome. - */ - if (win < (so->so_rcv.sb_datalen / 4) && win < tp->t_maxseg) - win = 0; - if (win > (u_long) (TCP_MAXWIN << tp->rcv_scale)) - win = (u_long) (TCP_MAXWIN << tp->rcv_scale); - if (win < (tp->rcv_adv - tp->rcv_nxt)) - win = (tp->rcv_adv - tp->rcv_nxt); - ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale)); - - if (SEQ_GT(tp->snd_up, tp->snd_una)) { - ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq))); -#ifdef notdef - if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { - ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt)); -#endif - ti->ti_flags |= TH_URG; - } else - /* - * If no urgent pointer to send, then we pull - * the urgent pointer to the left edge of the send window - * so that it doesn't drift into the send window on sequence - * number wraparound. - */ - tp->snd_up = tp->snd_una; /* drag it along */ - - /* - * Put TCP length in extended header, and then - * checksum extended header and data. - */ - if (len + optlen) - ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + - optlen + len)); - ti->ti_sum = cksum(m, (int)(hdrlen + len)); - - /* - * In transmit state, time the transmission and arrange for - * the retransmit. In persist state, just set snd_max. - */ - if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { - tcp_seq startseq = tp->snd_nxt; - - /* - * Advance snd_nxt over sequence space of this segment. - */ - if (flags & (TH_SYN|TH_FIN)) { - if (flags & TH_SYN) - tp->snd_nxt++; - if (flags & TH_FIN) { - tp->snd_nxt++; - tp->t_flags |= TF_SENTFIN; - } - } - tp->snd_nxt += len; - if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { - tp->snd_max = tp->snd_nxt; - /* - * Time this transmission if not a retransmission and - * not currently timing anything. - */ - if (tp->t_rtt == 0) { - tp->t_rtt = 1; - tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; - } - } - - /* - * Set retransmit timer if not currently set, - * and not doing an ack or a keep-alive probe. - * Initial value for retransmit timer is smoothed - * round-trip time + 2 * round-trip time variance. - * Initialize shift counter which is used for backoff - * of retransmit time. - */ - if (tp->t_timer[TCPT_REXMT] == 0 && - tp->snd_nxt != tp->snd_una) { - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - if (tp->t_timer[TCPT_PERSIST]) { - tp->t_timer[TCPT_PERSIST] = 0; - tp->t_rxtshift = 0; - } - } - } else - if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) - tp->snd_max = tp->snd_nxt + len; - - /* - * Fill in IP length and desired time to live and - * send to IP level. There should be a better way - * to handle ttl and tos; we could keep them in - * the template, but need a way to checksum without them. - */ - m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */ - - { - - ((struct ip *)ti)->ip_len = (u_int16_t) m->m_len; - - ((struct ip *)ti)->ip_ttl = ip_defttl; - ((struct ip *)ti)->ip_tos = so->so_iptos; - -/* #if BSD >= 43 */ - /* Don't do IP options... */ -/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, - * so->so_options & SO_DONTROUTE, 0); - */ - error = ip_output(so, m); - -/* #else - * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, - * so->so_options & SO_DONTROUTE); - * #endif - */ - } - if (error) { -out: -/* if (error == ENOBUFS) { - * tcp_quench(tp->t_inpcb, 0); - * return (0); - * } - */ -/* if ((error == EHOSTUNREACH || error == ENETDOWN) - * && TCPS_HAVERCVDSYN(tp->t_state)) { - * tp->t_softerror = error; - * return (0); - * } - */ - return (error); - } - tcpstat.tcps_sndtotal++; - - /* - * Data sent (as far as we can tell). - * If this advertises a larger window than any other segment, - * then remember the size of the advertised window. - * Any pending ACK has now been sent. - */ - if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) - tp->rcv_adv = tp->rcv_nxt + win; - tp->last_ack_sent = tp->rcv_nxt; - tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); - if (sendalot) - goto again; - - return (0); -} - -void tcp_setpersist(register struct tcpcb *tp) -{ - int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; - -/* if (tp->t_timer[TCPT_REXMT]) - * panic("tcp_output REXMT"); - */ - /* - * Start/restart persistence timer. - */ - TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], - t * tcp_backoff[tp->t_rxtshift], - TCPTV_PERSMIN, TCPTV_PERSMAX); - if (tp->t_rxtshift < TCP_MAXRXTSHIFT) - tp->t_rxtshift++; -} diff --git a/BasiliskII/src/slirp/tcp_subr.c b/BasiliskII/src/slirp/tcp_subr.c deleted file mode 100644 index 70e04b5e..00000000 --- a/BasiliskII/src/slirp/tcp_subr.c +++ /dev/null @@ -1,1296 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93 - * tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#define WANT_SYS_IOCTL_H -#include -#include - -/* patchable/settable parameters for tcp */ -int tcp_mssdflt = TCP_MSS; -int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; -int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */ -size_t tcp_rcvspace; /* You may want to change this */ -size_t tcp_sndspace; /* Keep small if you have an error prone link */ - -/* - * Tcp initialization - */ -void tcp_init() -{ - tcp_iss = 1; /* wrong */ - tcb.so_next = tcb.so_prev = &tcb; - - /* tcp_rcvspace = our Window we advertise to the remote */ - tcp_rcvspace = TCP_RCVSPACE; - tcp_sndspace = TCP_SNDSPACE; - - /* Make sure tcp_sndspace is at least 2*MSS */ - if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr))) - tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)); -} - -/* - * Create template to be used to send tcp packets on a connection. - * Call after host entry created, fills - * in a skeletal tcp/ip header, minimizing the amount of work - * necessary when the connection is used. - */ -/* struct tcpiphdr * */ -void tcp_template(struct tcpcb *tp) -{ - struct socket *so = tp->t_socket; - register struct tcpiphdr *n = &tp->t_template; - - n->ti_next = n->ti_prev = 0; - n->ti_x1 = 0; - n->ti_pr = IPPROTO_TCP; - n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); - n->ti_src = so->so_faddr; - n->ti_dst = so->so_laddr; - n->ti_sport = so->so_fport; - n->ti_dport = so->so_lport; - - n->ti_seq = 0; - n->ti_ack = 0; - n->ti_x2 = 0; - n->ti_off = 5; - n->ti_flags = 0; - n->ti_win = 0; - n->ti_sum = 0; - n->ti_urp = 0; -} - -/* - * Send a single message to the TCP at address specified by - * the given TCP/IP header. If m == 0, then we make a copy - * of the tcpiphdr at ti and send directly to the addressed host. - * This is used to force keep alive messages out using the TCP - * template for a connection tp->t_template. If flags are given - * then we send a message back to the TCP which originated the - * segment ti, and discard the mbuf containing it and any other - * attached mbufs. - * - * In any case the ack and sequence number of the transmitted - * segment are as specified by the parameters. - */ -void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti, - register struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) -{ - register int tlen; - int win = 0; - - DEBUG_CALL("tcp_respond"); - DEBUG_ARG("tp = %lx", (long)tp); - DEBUG_ARG("ti = %lx", (long)ti); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("ack = %u", ack); - DEBUG_ARG("seq = %u", seq); - DEBUG_ARG("flags = %x", flags); - - if (tp) - win = sbspace(&tp->t_socket->so_rcv); - if (m == 0) { - if ((m = m_get()) == NULL) - return; -#ifdef TCP_COMPAT_42 - tlen = 1; -#else - tlen = 0; -#endif - m->m_data += if_maxlinkhdr; - *mtod(m, struct tcpiphdr *) = *ti; - ti = mtod(m, struct tcpiphdr *); - flags = TH_ACK; - } else { - /* - * ti points into m so the next line is just making - * the mbuf point to ti - */ - m->m_data = (caddr_t)ti; - - m->m_len = sizeof (struct tcpiphdr); - tlen = 0; -#define xchg(a,b,type) { type t; t=a; a=b; b=t; } - xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t); - xchg(ti->ti_dport, ti->ti_sport, u_int16_t); -#undef xchg - } - ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); - tlen += sizeof (struct tcpiphdr); - m->m_len = tlen; - - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; - ti->ti_seq = htonl(seq); - ti->ti_ack = htonl(ack); - ti->ti_x2 = 0; - ti->ti_off = sizeof (struct tcphdr) >> 2; - ti->ti_flags = flags; - if (tp) - ti->ti_win = htons((u_int16_t) (win >> tp->rcv_scale)); - else - ti->ti_win = htons((u_int16_t)win); - ti->ti_urp = 0; - ti->ti_sum = 0; - ti->ti_sum = cksum(m, tlen); - ((struct ip *)ti)->ip_len = tlen; - - if(flags & TH_RST) - ((struct ip *)ti)->ip_ttl = MAXTTL; - else - ((struct ip *)ti)->ip_ttl = ip_defttl; - - (void) ip_output((struct socket *)0, m); -} - -/* - * Create a new TCP control block, making an - * empty reassembly queue and hooking it to the argument - * protocol control block. - */ -struct tcpcb *tcp_newtcpcb(struct socket *so) -{ - register struct tcpcb *tp; - - tp = (struct tcpcb *)malloc(sizeof(*tp)); - if (tp == NULL) - return ((struct tcpcb *)0); - - memset((char *) tp, 0, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp; - tp->t_maxseg = tcp_mssdflt; - - tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; - tp->t_socket = so; - - /* - * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no - * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives - * reasonable initial retransmit time. - */ - tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2; - tp->t_rttmin = TCPTV_MIN; - - TCPT_RANGESET(tp->t_rxtcur, - ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1, - TCPTV_MIN, TCPTV_REXMTMAX); - - tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; - tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; - tp->t_state = TCPS_CLOSED; - - so->so_tcpcb = tp; - - return (tp); -} - -/* - * Drop a TCP connection, reporting - * the specified error. If connection is synchronized, - * then send a RST to peer. - */ -struct tcpcb *tcp_drop(struct tcpcb *tp, int err) -{ -/* tcp_drop(tp, errno) - register struct tcpcb *tp; - int errno; -{ -*/ - - DEBUG_CALL("tcp_drop"); - DEBUG_ARG("tp = %lx", (long)tp); - DEBUG_ARG("errno = %d", errno); - - if (TCPS_HAVERCVDSYN(tp->t_state)) { - tp->t_state = TCPS_CLOSED; - (void) tcp_output(tp); - tcpstat.tcps_drops++; - } else - tcpstat.tcps_conndrops++; -/* if (errno == ETIMEDOUT && tp->t_softerror) - * errno = tp->t_softerror; - */ -/* so->so_error = errno; */ - return (tcp_close(tp)); -} - -/* - * Close a TCP control block: - * discard all space held by the tcp - * discard internet protocol block - * wake up any sleepers - */ -struct tcpcb *tcp_close(register struct tcpcb *tp) -{ - register struct tcpiphdr *t; - struct socket *so = tp->t_socket; - register struct mbuf *m; - - DEBUG_CALL("tcp_close"); - DEBUG_ARG("tp = %lx", (long )tp); - - /* free the reassembly queue, if any */ - t = (struct tcpiphdr *) tp->seg_next; - while (t != (struct tcpiphdr *)tp) { - t = (struct tcpiphdr *)t->ti_next; - m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque_32((struct tcpiphdr *) t->ti_prev); - m_freem(m); - } - /* It's static */ -/* if (tp->t_template) - * (void) m_free(dtom(tp->t_template)); - */ -/* free(tp, M_PCB); */ - free(tp); - so->so_tcpcb = 0; - soisfdisconnected(so); - /* clobber input socket cache if we're closing the cached connection */ - if (so == tcp_last_so) - tcp_last_so = &tcb; - closesocket(so->s); - sbfree(&so->so_rcv); - sbfree(&so->so_snd); - sofree(so); - tcpstat.tcps_closed++; - return ((struct tcpcb *)0); -} - -void tcp_drain() -{ - /* XXX */ -} - -/* - * When a source quench is received, close congestion window - * to one segment. We will gradually open it again as we proceed. - */ - -#ifdef notdef - -void tcp_quench(int i, int errno) -{ - struct tcpcb *tp = intotcpcb(inp); - - if (tp) - tp->snd_cwnd = tp->t_maxseg; -} - -#endif /* notdef */ - -/* - * TCP protocol interface to socket abstraction. - */ - -/* - * User issued close, and wish to trail through shutdown states: - * if never received SYN, just forget it. If got a SYN from peer, - * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. - * If already got a FIN from peer, then almost done; go to LAST_ACK - * state. In all other cases, have already sent FIN to peer (e.g. - * after PRU_SHUTDOWN), and just have to play tedious game waiting - * for peer to send FIN or not respond to keep-alives, etc. - * We can let the user exit from the close as soon as the FIN is acked. - */ -void tcp_sockclosed(struct tcpcb *tp) -{ - - DEBUG_CALL("tcp_sockclosed"); - DEBUG_ARG("tp = %lx", (long)tp); - - switch (tp->t_state) { - - case TCPS_CLOSED: - case TCPS_LISTEN: - case TCPS_SYN_SENT: - tp->t_state = TCPS_CLOSED; - tp = tcp_close(tp); - break; - - case TCPS_SYN_RECEIVED: - case TCPS_ESTABLISHED: - tp->t_state = TCPS_FIN_WAIT_1; - break; - - case TCPS_CLOSE_WAIT: - tp->t_state = TCPS_LAST_ACK; - break; - } -/* soisfdisconnecting(tp->t_socket); */ - if (tp && tp->t_state >= TCPS_FIN_WAIT_2) - soisfdisconnected(tp->t_socket); - if (tp) - tcp_output(tp); -} - -/* - * Connect to a host on the Internet - * Called by tcp_input - * Only do a connect, the tcp fields will be set in tcp_input - * return 0 if there's a result of the connect, - * else return -1 means we're still connecting - * The return value is almost always -1 since the socket is - * nonblocking. Connect returns after the SYN is sent, and does - * not wait for ACK+SYN. - */ -int tcp_fconnect(struct socket *so) -{ - int ret=0; - - DEBUG_CALL("tcp_fconnect"); - DEBUG_ARG("so = %lx", (long )so); - - if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) { - int opt, s=so->s; - struct sockaddr_in addr; - memset(&addr, 0, sizeof(struct sockaddr_in)); - - fd_nonblock(s); - opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt )); - opt = 1; - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt )); - - addr.sin_family = AF_INET; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { - /* It's an alias */ - switch(ntohl(so->so_faddr.s_addr) & 0xff) { - case CTL_DNS: - addr.sin_addr = dns_addr; - break; - case CTL_ALIAS: - default: - addr.sin_addr = loopback_addr; - break; - } - } else - addr.sin_addr = so->so_faddr; - addr.sin_port = so->so_fport; - - char addrstr[INET_ADDRSTRLEN]; - DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, " - "addr.sin_addr.s_addr=%.16s\n", - ntohs(addr.sin_port), inet_ntop(AF_INET, &addr.sin_addr, - addrstr, sizeof(addrstr)))); - /* We don't care what port we get */ - ret = connect(s,(struct sockaddr *)&addr,sizeof (addr)); - - /* - * If it's not in progress, it failed, so we just return 0, - * without clearing SS_NOFDREF - */ - soisfconnecting(so); - } - - return(ret); -} - -/* - * Accept the socket and connect to the local-host - * - * We have a problem. The correct thing to do would be - * to first connect to the local-host, and only if the - * connection is accepted, then do an accept() here. - * But, a) we need to know who's trying to connect - * to the socket to be able to SYN the local-host, and - * b) we are already connected to the foreign host by - * the time it gets to accept(), so... We simply accept - * here and SYN the local-host. - */ -void tcp_connect(struct socket *inso) -{ - struct socket *so; - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); - struct tcpcb *tp; - int s, opt; - - DEBUG_CALL("tcp_connect"); - DEBUG_ARG("inso = %lx", (long)inso); - - /* - * If it's an SS_ACCEPTONCE socket, no need to socreate() - * another socket, just use the accept() socket. - */ - if (inso->so_state & SS_FACCEPTONCE) { - /* FACCEPTONCE already have a tcpcb */ - so = inso; - } else { - if ((so = socreate()) == NULL) { - /* If it failed, get rid of the pending connection */ - closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen)); - return; - } - if (tcp_attach(so) < 0) { - free(so); /* NOT sofree */ - return; - } - so->so_laddr = inso->so_laddr; - so->so_lport = inso->so_lport; - } - - tcp_mss(sototcpcb(so), 0); - - if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) { - tcp_close(sototcpcb(so)); /* This will sofree() as well */ - return; - } - fd_nonblock(s); - opt = 1; - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); - opt = 1; - setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); - opt = 1; - setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int)); - - so->so_fport = addr.sin_port; - so->so_faddr = addr.sin_addr; - /* Translate connections from localhost to the real hostname */ - if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; - - /* Close the accept() socket, set right state */ - if (inso->so_state & SS_FACCEPTONCE) { - closesocket(so->s); /* If we only accept once, close the accept() socket */ - so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */ - /* if it's not FACCEPTONCE, it's already NOFDREF */ - } - so->s = s; - - so->so_iptos = tcp_tos(so); - tp = sototcpcb(so); - - tcp_template(tp); - - /* Compute window scaling to request. */ -/* while (tp->request_r_scale < TCP_MAX_WINSHIFT && - * (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) - * tp->request_r_scale++; - */ - -/* soisconnecting(so); */ /* NOFDREF used instead */ - tcpstat.tcps_connattempt++; - - tp->t_state = TCPS_SYN_SENT; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; - tcp_sendseqinit(tp); - tcp_output(tp); -} - -/* - * Attach a TCPCB to a socket. - */ -int tcp_attach(struct socket *so) -{ - if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) - return -1; - - insque(so, &tcb); - - return 0; -} - -/* - * Set the socket's type of service field - */ -struct tos_t tcptos[] = { - {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */ - {21, 21, IPTOS_LOWDELAY, EMU_FTP}, /* ftp control */ - {0, 23, IPTOS_LOWDELAY, 0}, /* telnet */ - {0, 80, IPTOS_THROUGHPUT, 0}, /* WWW */ - {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT}, /* rlogin */ - {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT}, /* shell */ - {0, 544, IPTOS_LOWDELAY, EMU_KSH}, /* kshell */ - {0, 543, IPTOS_LOWDELAY, 0}, /* klogin */ - {0, 6667, IPTOS_THROUGHPUT, EMU_IRC}, /* IRC */ - {0, 6668, IPTOS_THROUGHPUT, EMU_IRC}, /* IRC undernet */ - {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */ - {0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */ - {0, 0, 0, 0} -}; - -struct emu_t *tcpemu = 0; - -/* - * Return TOS according to the above table - */ -u_int8_t tcp_tos(struct socket *so) -{ - int i = 0; - struct emu_t *emup; - - while(tcptos[i].tos) { - if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) || - (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) { - so->so_emu = tcptos[i].emu; - return tcptos[i].tos; - } - i++; - } - - /* Nope, lets see if there's a user-added one */ - for (emup = tcpemu; emup; emup = emup->next) { - if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) || - (emup->lport && (ntohs(so->so_lport) == emup->lport))) { - so->so_emu = emup->emu; - return emup->tos; - } - } - - return 0; -} - -int do_echo = -1; - -/* - * Emulate programs that try and connect to us - * This includes ftp (the data connection is - * initiated by the server) and IRC (DCC CHAT and - * DCC SEND) for now - * - * NOTE: It's possible to crash SLiRP by sending it - * unstandard strings to emulate... if this is a problem, - * more checks are needed here - * - * XXX Assumes the whole command came in one packet - * - * XXX Some ftp clients will have their TOS set to - * LOWDELAY and so Nagel will kick in. Because of this, - * we'll get the first letter, followed by the rest, so - * we simply scan for ORT instead of PORT... - * DCC doesn't have this problem because there's other stuff - * in the packet before the DCC command. - * - * Return 1 if the mbuf m is still valid and should be - * sbappend()ed - * - * NOTE: if you return 0 you MUST m_free() the mbuf! - */ -int tcp_emu(struct socket *so, struct mbuf *m) -{ - u_int n1, n2, n3, n4, n5, n6; - char buff[256]; - u_int32_t laddr; - u_int lport; - char *bptr; - - DEBUG_CALL("tcp_emu"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("m = %lx", (long)m); - - switch(so->so_emu) { - int x, i; - - case EMU_IDENT: - /* - * Identification protocol as per rfc-1413 - */ - - { - struct socket *tmpso; - struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); - struct sbuf *so_rcv = &so->so_rcv; - - memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); - so_rcv->sb_wptr += m->m_len; - so_rcv->sb_rptr += m->m_len; - m->m_data[m->m_len] = 0; /* NULL terminate */ - if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { - if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) { - HTONS(n1); - HTONS(n2); - /* n2 is the one on our host */ - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { - if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && - tmpso->so_lport == n2 && - tmpso->so_faddr.s_addr == so->so_faddr.s_addr && - tmpso->so_fport == n1) { - if (getsockname(tmpso->s, - (struct sockaddr *)&addr, &addrlen) == 0) - n2 = ntohs(addr.sin_port); - break; - } - } - } - so_rcv->sb_cc = sprintf(so_rcv->sb_data, "%d,%d\r\n", n1, n2); - so_rcv->sb_rptr = so_rcv->sb_data; - so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; - } - m_free(m); - return 0; - } - -#if 0 - case EMU_RLOGIN: - /* - * Rlogin emulation - * First we accumulate all the initial option negotiation, - * then fork_exec() rlogin according to the options - */ - { - int i, i2, n; - char *ptr; - char args[100]; - char term[100]; - struct sbuf *so_snd = &so->so_snd; - struct sbuf *so_rcv = &so->so_rcv; - - /* First check if they have a priveladged port, or too much data has arrived */ - if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 || - (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) { - memcpy(so_snd->sb_wptr, "Permission denied\n", 18); - so_snd->sb_wptr += 18; - so_snd->sb_cc += 18; - tcp_sockclosed(sototcpcb(so)); - m_free(m); - return 0; - } - - /* Append the current data */ - memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); - so_rcv->sb_wptr += m->m_len; - so_rcv->sb_rptr += m->m_len; - m_free(m); - - /* - * Check if we have all the initial options, - * and build argument list to rlogin while we're here - */ - n = 0; - ptr = so_rcv->sb_data; - args[0] = 0; - term[0] = 0; - while (ptr < so_rcv->sb_wptr) { - if (*ptr++ == 0) { - n++; - if (n == 2) { - sprintf(args, "rlogin -l %s %s", - ptr, inet_ntoa(so->so_faddr)); - } else if (n == 3) { - i2 = so_rcv->sb_wptr - ptr; - for (i = 0; i < i2; i++) { - if (ptr[i] == '/') { - ptr[i] = 0; -#ifdef HAVE_SETENV - sprintf(term, "%s", ptr); -#else - sprintf(term, "TERM=%s", ptr); -#endif - ptr[i] = '/'; - break; - } - } - } - } - } - - if (n != 4) - return 0; - - /* We have it, set our term variable and fork_exec() */ -#ifdef HAVE_SETENV - setenv("TERM", term, 1); -#else - putenv(term); -#endif - fork_exec(so, args, 2); - term[0] = 0; - so->so_emu = 0; - - /* And finally, send the client a 0 character */ - so_snd->sb_wptr[0] = 0; - so_snd->sb_wptr++; - so_snd->sb_cc++; - - return 0; - } - - case EMU_RSH: - /* - * rsh emulation - * First we accumulate all the initial option negotiation, - * then rsh_exec() rsh according to the options - */ - { - int n; - char *ptr; - char *user; - char *args; - struct sbuf *so_snd = &so->so_snd; - struct sbuf *so_rcv = &so->so_rcv; - - /* First check if they have a priveladged port, or too much data has arrived */ - if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 || - (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) { - memcpy(so_snd->sb_wptr, "Permission denied\n", 18); - so_snd->sb_wptr += 18; - so_snd->sb_cc += 18; - tcp_sockclosed(sototcpcb(so)); - m_free(m); - return 0; - } - - /* Append the current data */ - memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); - so_rcv->sb_wptr += m->m_len; - so_rcv->sb_rptr += m->m_len; - m_free(m); - - /* - * Check if we have all the initial options, - * and build argument list to rlogin while we're here - */ - n = 0; - ptr = so_rcv->sb_data; - user=""; - args=""; - if (so->extra==NULL) { - struct socket *ns; - struct tcpcb* tp; - int port=atoi(ptr); - if (port <= 0) return 0; - if (port > 1023 || port < 512) { - memcpy(so_snd->sb_wptr, "Permission denied\n", 18); - so_snd->sb_wptr += 18; - so_snd->sb_cc += 18; - tcp_sockclosed(sototcpcb(so)); - return 0; - } - if ((ns=socreate()) == NULL) - return 0; - if (tcp_attach(ns)<0) { - free(ns); - return 0; - } - - ns->so_laddr=so->so_laddr; - ns->so_lport=htons(port); - - tcp_mss(sototcpcb(ns), 0); - - ns->so_faddr=so->so_faddr; - ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */ - - if (ns->so_faddr.s_addr == 0 || - ns->so_faddr.s_addr == loopback_addr.s_addr) - ns->so_faddr = alias_addr; - - ns->so_iptos = tcp_tos(ns); - tp = sototcpcb(ns); - - tcp_template(tp); - - /* Compute window scaling to request. */ - /* while (tp->request_r_scale < TCP_MAX_WINSHIFT && - * (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) - * tp->request_r_scale++; - */ - - /*soisfconnecting(ns);*/ - - tcpstat.tcps_connattempt++; - - tp->t_state = TCPS_SYN_SENT; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/2; - tcp_sendseqinit(tp); - tcp_output(tp); - so->extra=ns; - } - while (ptr < so_rcv->sb_wptr) { - if (*ptr++ == 0) { - n++; - if (n == 2) { - user=ptr; - } else if (n == 3) { - args=ptr; - } - } - } - - if (n != 4) - return 0; - - rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args); - so->so_emu = 0; - so->extra=NULL; - - /* And finally, send the client a 0 character */ - so_snd->sb_wptr[0] = 0; - so_snd->sb_wptr++; - so_snd->sb_cc++; - - return 0; - } - - case EMU_CTL: - { - int num; - struct sbuf *so_snd = &so->so_snd; - struct sbuf *so_rcv = &so->so_rcv; - - /* - * If there is binary data here, we save it in so->so_m - */ - if (!so->so_m) { - int rxlen; - char *rxdata; - rxdata=mtod(m, char *); - for (rxlen=m->m_len; rxlen; rxlen--) { - if (*rxdata++ & 0x80) { - so->so_m = m; - return 0; - } - } - } /* if(so->so_m==NULL) */ - - /* - * Append the line - */ - sbappendsb(so_rcv, m); - - /* To avoid going over the edge of the buffer, we reset it */ - if (so_snd->sb_cc == 0) - so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data; - - /* - * A bit of a hack: - * If the first packet we get here is 1 byte long, then it - * was done in telnet character mode, therefore we must echo - * the characters as they come. Otherwise, we echo nothing, - * because in linemode, the line is already echoed - * XXX two or more control connections won't work - */ - if (do_echo == -1) { - if (m->m_len == 1) do_echo = 1; - else do_echo = 0; - } - if (do_echo) { - sbappendsb(so_snd, m); - m_free(m); - tcp_output(sototcpcb(so)); /* XXX */ - } else - m_free(m); - - num = 0; - while (num < so->so_rcv.sb_cc) { - if (*(so->so_rcv.sb_rptr + num) == '\n' || - *(so->so_rcv.sb_rptr + num) == '\r') { - int n; - - *(so_rcv->sb_rptr + num) = 0; - if (ctl_password && !ctl_password_ok) { - /* Need a password */ - if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) { - if (strcmp(buff, ctl_password) == 0) { - ctl_password_ok = 1; - n = sprintf(so_snd->sb_wptr, - "Password OK.\r\n"); - goto do_prompt; - } - } - n = sprintf(so_snd->sb_wptr, - "Error: Password required, log on with \"pass PASSWORD\"\r\n"); - goto do_prompt; - } - cfg_quitting = 0; - n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF); - if (!cfg_quitting) { - /* Register the printed data */ -do_prompt: - so_snd->sb_cc += n; - so_snd->sb_wptr += n; - /* Add prompt */ - n = sprintf(so_snd->sb_wptr, "Slirp> "); - so_snd->sb_cc += n; - so_snd->sb_wptr += n; - } - /* Drop so_rcv data */ - so_rcv->sb_cc = 0; - so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data; - tcp_output(sototcpcb(so)); /* Send the reply */ - } - num++; - } - return 0; - } -#endif - case EMU_FTP: /* ftp */ - *(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */ - if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { - /* - * Need to emulate the PORT command - */ - x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]", - &n1, &n2, &n3, &n4, &n5, &n6, buff); - if (x < 6) - return 1; - - laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); - lport = htons((n5 << 8) | (n6)); - - if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) - return 1; - - n6 = ntohs(so->so_fport); - - n5 = (n6 >> 8) & 0xff; - n6 &= 0xff; - - laddr = ntohl(so->so_faddr.s_addr); - - n1 = ((laddr >> 24) & 0xff); - n2 = ((laddr >> 16) & 0xff); - n3 = ((laddr >> 8) & 0xff); - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s", - n1, n2, n3, n4, n5, n6, x==7?buff:""); - return 1; - } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) { - /* - * Need to emulate the PASV response - */ - x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]", - &n1, &n2, &n3, &n4, &n5, &n6, buff); - if (x < 6) - return 1; - - laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); - lport = htons((n5 << 8) | (n6)); - - if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) - return 1; - - n6 = ntohs(so->so_fport); - - n5 = (n6 >> 8) & 0xff; - n6 &= 0xff; - - laddr = ntohl(so->so_faddr.s_addr); - - n1 = ((laddr >> 24) & 0xff); - n2 = ((laddr >> 16) & 0xff); - n3 = ((laddr >> 8) & 0xff); - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr,"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", - n1, n2, n3, n4, n5, n6, x==7?buff:""); - - return 1; - } - - return 1; - - case EMU_KSH: - /* - * The kshell (Kerberos rsh) and shell services both pass - * a local port port number to carry signals to the server - * and stderr to the client. It is passed at the beginning - * of the connection as a NUL-terminated decimal ASCII string. - */ - so->so_emu = 0; - for (lport = 0, i = 0; i < (int) (m->m_len-1); ++i) { - if (m->m_data[i] < '0' || m->m_data[i] > '9') - return 1; /* invalid number */ - lport *= 10; - lport += m->m_data[i] - '0'; - } - if (m->m_data[m->m_len-1] == '\0' && lport != 0 && - (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) - m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1; - return 1; - - case EMU_IRC: - /* - * Need to emulate DCC CHAT, DCC SEND and DCC MOVE - */ - *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */ - if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL) - return 1; - - /* The %256s is for the broken mIRC */ - if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) - return 1; - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n", - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), 1); - } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) - return 1; - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n", - buff, (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); - } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { - if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) - return 1; - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n", - buff, (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); - } - return 1; - - case EMU_REALAUDIO: - /* - * RealAudio emulation - JP. We must try to parse the incoming - * data and try to find the two characters that contain the - * port number. Then we redirect an udp port and replace the - * number with the real port we got. - * - * The 1.0 beta versions of the player are not supported - * any more. - * - * A typical packet for player version 1.0 (release version): - * - * 0000:50 4E 41 00 05 - * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P - * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH - * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v - * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB - * - * Now the port number 0x1BD7 is found at offset 0x04 of the - * Now the port number 0x1BD7 is found at offset 0x04 of the - * second packet. This time we received five bytes first and - * then the rest. You never know how many bytes you get. - * - * A typical packet for player version 2.0 (beta): - * - * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á. - * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0 - * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/ - * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas - * 0040:65 2E 72 61 79 53 00 00 06 36 42 e.rayS...6B - * - * Port number 0x1BC1 is found at offset 0x0d. - * - * This is just a horrible switch statement. Variable ra tells - * us where we're going. - */ - - bptr = m->m_data; - while (bptr < m->m_data + m->m_len) { - u_short p; - static int ra = 0; - char ra_tbl[4]; - - ra_tbl[0] = 0x50; - ra_tbl[1] = 0x4e; - ra_tbl[2] = 0x41; - ra_tbl[3] = 0; - - switch (ra) { - case 0: - case 2: - case 3: - if (*bptr++ != ra_tbl[ra]) { - ra = 0; - continue; - } - break; - - case 1: - /* - * We may get 0x50 several times, ignore them - */ - if (*bptr == 0x50) { - ra = 1; - bptr++; - continue; - } else if (*bptr++ != ra_tbl[ra]) { - ra = 0; - continue; - } - break; - - case 4: - /* - * skip version number - */ - bptr++; - break; - - case 5: - /* - * The difference between versions 1.0 and - * 2.0 is here. For future versions of - * the player this may need to be modified. - */ - if (*(bptr + 1) == 0x02) - bptr += 8; - else - bptr += 4; - break; - - case 6: - /* This is the field containing the port - * number that RA-player is listening to. - */ - lport = (((u_char*)bptr)[0] << 8) - + ((u_char *)bptr)[1]; - if (lport < 6970) - lport += 256; /* don't know why */ - if (lport < 6970 || lport > 7170) - return 1; /* failed */ - - /* try to get udp port between 6970 - 7170 */ - for (p = 6970; p < 7071; p++) { - if (udp_listen( htons(p), - so->so_laddr.s_addr, - htons(lport), - SS_FACCEPTONCE)) { - break; - } - } - if (p == 7071) - p = 0; - *(u_char *)bptr++ = (p >> 8) & 0xff; - *(u_char *)bptr++ = p & 0xff; - ra = 0; - return 1; /* port redirected, we're done */ - break; - - default: - ra = 0; - } - ra++; - } - return 1; - - default: - /* Ooops, not emulated, won't call tcp_emu again */ - so->so_emu = 0; - return 1; - } -} - -/* - * Do misc. config of SLiRP while its running. - * Return 0 if this connections is to be closed, 1 otherwise, - * return 2 if this is a command-line connection - */ -int tcp_ctl(struct socket *so) -{ - struct sbuf *sb = &so->so_snd; - int command; - struct ex_list *ex_ptr; - int do_pty; - // struct socket *tmpso; - - DEBUG_CALL("tcp_ctl"); - DEBUG_ARG("so = %lx", (long )so); - -#if 0 - /* - * Check if they're authorised - */ - if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) { - sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n"); - sb->sb_wptr += sb->sb_cc; - return 0; - } -#endif - command = (ntohl(so->so_faddr.s_addr) & 0xff); - - switch(command) { - default: /* Check for exec's */ - - /* - * Check if it's pty_exec - */ - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_fport == so->so_fport && - command == ex_ptr->ex_addr) { - do_pty = ex_ptr->ex_pty; - goto do_exec; - } - } - - /* - * Nothing bound.. - */ - /* tcp_fconnect(so); */ - - /* FALLTHROUGH */ - case CTL_ALIAS: - sb->sb_cc = sprintf(sb->sb_wptr, - "Error: No application configured.\r\n"); - sb->sb_wptr += sb->sb_cc; - return(0); - - do_exec: - DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec)); - return(fork_exec(so, ex_ptr->ex_exec, do_pty)); - -#if 0 - case CTL_CMD: - for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { - if (tmpso->so_emu == EMU_CTL && - !(tmpso->so_tcpcb? - (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK)) - :0)) { - /* Ooops, control connection already active */ - sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n"); - sb->sb_wptr += sb->sb_cc; - return 0; - } - } - so->so_emu = EMU_CTL; - ctl_password_ok = 0; - sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> "); - sb->sb_wptr += sb->sb_cc; - do_echo=-1; - return(2); -#endif - } -} diff --git a/BasiliskII/src/slirp/tcp_timer.c b/BasiliskII/src/slirp/tcp_timer.c deleted file mode 100644 index ab9aa580..00000000 --- a/BasiliskII/src/slirp/tcp_timer.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93 - * tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp - */ - -#include - -int tcp_keepidle = TCPTV_KEEP_IDLE; -int tcp_keepintvl = TCPTV_KEEPINTVL; -int tcp_maxidle; -int so_options = DO_KEEPALIVE; - -struct tcpstat tcpstat; /* tcp statistics */ -u_int32_t tcp_now; /* for RFC 1323 timestamps */ - -/* - * Fast timeout routine for processing delayed acks - */ -void -tcp_fasttimo() -{ - register struct socket *so; - register struct tcpcb *tp; - - DEBUG_CALL("tcp_fasttimo"); - - so = tcb.so_next; - if (so) - for (; so != &tcb; so = so->so_next) - if ((tp = (struct tcpcb *)so->so_tcpcb) && - (tp->t_flags & TF_DELACK)) { - tp->t_flags &= ~TF_DELACK; - tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; - (void) tcp_output(tp); - } -} - -/* - * Tcp protocol timeout routine called every 500 ms. - * Updates the timers in all active tcb's and - * causes finite state machine actions if timers expire. - */ -void -tcp_slowtimo() -{ - register struct socket *ip, *ipnxt; - register struct tcpcb *tp; - register int i; - - DEBUG_CALL("tcp_slowtimo"); - - tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; - /* - * Search through tcb's and update active timers. - */ - ip = tcb.so_next; - if (ip == 0) - return; - for (; ip != &tcb; ip = ipnxt) { - ipnxt = ip->so_next; - tp = sototcpcb(ip); - if (tp == 0) - continue; - for (i = 0; i < TCPT_NTIMERS; i++) { - if (tp->t_timer[i] && --tp->t_timer[i] == 0) { - tcp_timers(tp,i); - if (ipnxt->so_prev != ip) - goto tpgone; - } - } - tp->t_idle++; - if (tp->t_rtt) - tp->t_rtt++; -tpgone: - ; - } - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ -#ifdef TCP_COMPAT_42 - if ((int)tcp_iss < 0) - tcp_iss = 0; /* XXX */ -#endif - tcp_now++; /* for timestamps */ -} - -/* - * Cancel all timers for TCP tp. - */ -void -tcp_canceltimers(tp) - struct tcpcb *tp; -{ - register int i; - - for (i = 0; i < TCPT_NTIMERS; i++) - tp->t_timer[i] = 0; -} - -int tcp_backoff[TCP_MAXRXTSHIFT + 1] = - { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; - -/* - * TCP timer processing. - */ -struct tcpcb * -tcp_timers(tp, timer) - register struct tcpcb *tp; - int timer; -{ - register int rexmt; - - DEBUG_CALL("tcp_timers"); - - switch (timer) { - - /* - * 2 MSL timeout in shutdown went off. If we're closed but - * still waiting for peer to close and connection has been idle - * too long, or if 2MSL time is up from TIME_WAIT, delete connection - * control block. Otherwise, check again in a bit. - */ - case TCPT_2MSL: - if (tp->t_state != TCPS_TIME_WAIT && - tp->t_idle <= tcp_maxidle) - tp->t_timer[TCPT_2MSL] = tcp_keepintvl; - else - tp = tcp_close(tp); - break; - - /* - * Retransmission timer went off. Message has not - * been acked within retransmit interval. Back off - * to a longer retransmit interval and retransmit one segment. - */ - case TCPT_REXMT: - - /* - * XXXXX If a packet has timed out, then remove all the queued - * packets for that session. - */ - - if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { - /* - * This is a hack to suit our terminal server here at the uni of canberra - * since they have trouble with zeroes... It usually lets them through - * unharmed, but under some conditions, it'll eat the zeros. If we - * keep retransmitting it, it'll keep eating the zeroes, so we keep - * retransmitting, and eventually the connection dies... - * (this only happens on incoming data) - * - * So, if we were gonna drop the connection from too many retransmits, - * don't... instead halve the t_maxseg, which might break up the NULLs and - * let them through - * - * *sigh* - */ - - tp->t_maxseg >>= 1; - if (tp->t_maxseg < 32) { - /* - * We tried our best, now the connection must die! - */ - tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; - tp = tcp_drop(tp, tp->t_softerror); - /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ - return (tp); /* XXX */ - } - - /* - * Set rxtshift to 6, which is still at the maximum - * backoff time - */ - tp->t_rxtshift = 6; - } - tcpstat.tcps_rexmttimeo++; - rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; - TCPT_RANGESET(tp->t_rxtcur, rexmt, - (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ - tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; - /* - * If losing, let the lower level know and try for - * a better route. Also, if we backed off this far, - * our srtt estimate is probably bogus. Clobber it - * so we'll take the next rtt measurement as our srtt; - * move the current srtt into rttvar to keep the current - * retransmit times until then. - */ - if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { -/* in_losing(tp->t_inpcb); */ - tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); - tp->t_srtt = 0; - } - tp->snd_nxt = tp->snd_una; - /* - * If timing a segment in this window, stop the timer. - */ - tp->t_rtt = 0; - /* - * Close the congestion window down to one segment - * (we'll open it by one segment for each ack we get). - * Since we probably have a window's worth of unacked - * data accumulated, this "slow start" keeps us from - * dumping all that data as back-to-back packets (which - * might overwhelm an intermediate gateway). - * - * There are two phases to the opening: Initially we - * open by one mss on each ack. This makes the window - * size increase exponentially with time. If the - * window is larger than the path can handle, this - * exponential growth results in dropped packet(s) - * almost immediately. To get more time between - * drops but still "push" the network to take advantage - * of improving conditions, we switch from exponential - * to linear window opening at some threshold size. - * For a threshold, we use half the current window - * size, truncated to a multiple of the mss. - * - * (the minimum cwnd that will give us exponential - * growth is 2 mss. We don't allow the threshold - * to go below this.) - */ - { - u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; - if (win < 2) - win = 2; - tp->snd_cwnd = tp->t_maxseg; - tp->snd_ssthresh = win * tp->t_maxseg; - tp->t_dupacks = 0; - } - (void) tcp_output(tp); - break; - - /* - * Persistence timer into zero window. - * Force a byte to be output, if possible. - */ - case TCPT_PERSIST: - tcpstat.tcps_persisttimeo++; - tcp_setpersist(tp); - tp->t_force = 1; - (void) tcp_output(tp); - tp->t_force = 0; - break; - - /* - * Keep-alive timer went off; send something - * or drop connection if idle for too long. - */ - case TCPT_KEEP: - tcpstat.tcps_keeptimeo++; - if (tp->t_state < TCPS_ESTABLISHED) - goto dropit; - -/* if (tp->t_socket->so_options & SO_KEEPALIVE && */ - if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= tcp_keepidle + tcp_maxidle) - goto dropit; - /* - * Send a packet designed to force a response - * if the peer is up and reachable: - * either an ACK if the connection is still alive, - * or an RST if the peer has closed the connection - * due to timeout or reboot. - * Using sequence number tp->snd_una-1 - * causes the transmitted zero-length segment - * to lie outside the receive window; - * by the protocol spec, this requires the - * correspondent TCP to respond. - */ - tcpstat.tcps_keepprobe++; -#ifdef TCP_COMPAT_42 - /* - * The keepalive packet must have nonzero length - * to get a 4.2 host to respond. - */ - tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, - tp->rcv_nxt - 1, tp->snd_una - 1, 0); -#else - tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, - tp->rcv_nxt, tp->snd_una - 1, 0); -#endif - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; - } else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; - break; - - dropit: - tcpstat.tcps_keepdrops++; - tp = tcp_drop(tp, 0); /* ETIMEDOUT); */ - break; - } - - return (tp); -} diff --git a/BasiliskII/src/slirp/tcp_timer.h b/BasiliskII/src/slirp/tcp_timer.h deleted file mode 100644 index 73fe2089..00000000 --- a/BasiliskII/src/slirp/tcp_timer.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93 - * tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp - */ - -#ifndef _TCP_TIMER_H_ -#define _TCP_TIMER_H_ - -/* - * Definitions of the TCP timers. These timers are counted - * down PR_SLOWHZ times a second. - */ -#define TCPT_NTIMERS 4 - -#define TCPT_REXMT 0 /* retransmit */ -#define TCPT_PERSIST 1 /* retransmit persistence */ -#define TCPT_KEEP 2 /* keep alive */ -#define TCPT_2MSL 3 /* 2*msl quiet time timer */ - -/* - * The TCPT_REXMT timer is used to force retransmissions. - * The TCP has the TCPT_REXMT timer set whenever segments - * have been sent for which ACKs are expected but not yet - * received. If an ACK is received which advances tp->snd_una, - * then the retransmit timer is cleared (if there are no more - * outstanding segments) or reset to the base value (if there - * are more ACKs expected). Whenever the retransmit timer goes off, - * we retransmit one unacknowledged segment, and do a backoff - * on the retransmit timer. - * - * The TCPT_PERSIST timer is used to keep window size information - * flowing even if the window goes shut. If all previous transmissions - * have been acknowledged (so that there are no retransmissions in progress), - * and the window is too small to bother sending anything, then we start - * the TCPT_PERSIST timer. When it expires, if the window is nonzero, - * we go to transmit state. Otherwise, at intervals send a single byte - * into the peer's window to force him to update our window information. - * We do this at most as often as TCPT_PERSMIN time intervals, - * but no more frequently than the current estimate of round-trip - * packet time. The TCPT_PERSIST timer is cleared whenever we receive - * a window update from the peer. - * - * The TCPT_KEEP timer is used to keep connections alive. If an - * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time, - * but not yet established, then we drop the connection. Once the connection - * is established, if the connection is idle for TCPTV_KEEP_IDLE time - * (and keepalives have been enabled on the socket), we begin to probe - * the connection. We force the peer to send us a segment by sending: - * - * This segment is (deliberately) outside the window, and should elicit - * an ack segment in response from the peer. If, despite the TCPT_KEEP - * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE - * amount of time probing, then we drop the connection. - */ - -/* - * Time constants. - */ -#define TCPTV_MSL ( 5*PR_SLOWHZ) /* max seg lifetime (hah!) */ - -#define TCPTV_SRTTBASE 0 /* base roundtrip time; - if 0, no idea yet */ -#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */ - -#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */ -#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */ - -#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */ -#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */ -#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */ -#define TCPTV_KEEPCNT 8 /* max probes before drop */ - -#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ -/* #define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) */ /* max allowable REXMT value */ -#define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */ - -#define TCP_LINGERTIME 120 /* linger at most 2 minutes */ - -#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ - - -#ifdef TCPTIMERS -char *tcptimers[] = - { "REXMT", "PERSIST", "KEEP", "2MSL" }; -#endif - -/* - * Force a time value to be in a certain range. - */ -#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \ - (tv) = (value); \ - if ((tv) < (tvmin)) \ - (tv) = (tvmin); \ - else if ((tv) > (tvmax)) \ - (tv) = (tvmax); \ -} - -extern int tcp_keepidle; /* time before keepalive probes begin */ -extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ -extern int tcp_ttl; /* time to live for TCP segs */ -extern int tcp_backoff[]; - -struct tcpcb; - -void tcp_fasttimo(void); -void tcp_slowtimo(void); -void tcp_canceltimers(struct tcpcb *); -struct tcpcb * tcp_timers(register struct tcpcb *, int); - -#endif diff --git a/BasiliskII/src/slirp/tcp_var.h b/BasiliskII/src/slirp/tcp_var.h deleted file mode 100644 index c8e99ae0..00000000 --- a/BasiliskII/src/slirp/tcp_var.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcp_var.h 8.3 (Berkeley) 4/10/94 - * tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp - */ - -#ifndef _TCP_VAR_H_ -#define _TCP_VAR_H_ - -#include "tcpip.h" -#include "tcp_timer.h" - -#if SIZEOF_CHAR_P == 4 - typedef struct tcpiphdr *tcpiphdrp_32; -#else - typedef u_int32_t tcpiphdrp_32; -#endif - -/* - * Tcp control block, one per tcp; fields: - */ -struct tcpcb { - tcpiphdrp_32 seg_next; /* sequencing queue */ - tcpiphdrp_32 seg_prev; - short t_state; /* state of this connection */ - short t_timer[TCPT_NTIMERS]; /* tcp timers */ - short t_rxtshift; /* log(2) of rexmt exp. backoff */ - short t_rxtcur; /* current retransmit value */ - short t_dupacks; /* consecutive dup acks recd */ - u_short t_maxseg; /* maximum segment size */ - char t_force; /* 1 if forcing out a byte */ - u_short t_flags; -#define TF_ACKNOW 0x0001 /* ack peer immediately */ -#define TF_DELACK 0x0002 /* ack, but try to delay it */ -#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */ -#define TF_NOOPT 0x0008 /* don't use tcp options */ -#define TF_SENTFIN 0x0010 /* have sent FIN */ -#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */ -#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */ -#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */ -#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */ -#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */ - - /* Make it static for now */ -/* struct tcpiphdr *t_template; / * skeletal packet for transmit */ - struct tcpiphdr t_template; - - struct socket *t_socket; /* back pointer to socket */ -/* - * The following fields are used as in the protocol specification. - * See RFC783, Dec. 1981, page 21. - */ -/* send sequence variables */ - tcp_seq snd_una; /* send unacknowledged */ - tcp_seq snd_nxt; /* send next */ - tcp_seq snd_up; /* send urgent pointer */ - tcp_seq snd_wl1; /* window update seg seq number */ - tcp_seq snd_wl2; /* window update seg ack number */ - tcp_seq iss; /* initial send sequence number */ - u_int32_t snd_wnd; /* send window */ -/* receive sequence variables */ - u_int32_t rcv_wnd; /* receive window */ - tcp_seq rcv_nxt; /* receive next */ - tcp_seq rcv_up; /* receive urgent pointer */ - tcp_seq irs; /* initial receive sequence number */ -/* - * Additional variables for this implementation. - */ -/* receive variables */ - tcp_seq rcv_adv; /* advertised window */ -/* retransmit variables */ - tcp_seq snd_max; /* highest sequence number sent; - * used to recognize retransmits - */ -/* congestion control (for slow start, source quench, retransmit after loss) */ - u_int32_t snd_cwnd; /* congestion-controlled window */ - u_int32_t snd_ssthresh; /* snd_cwnd size threshold for - * for slow start exponential to - * linear switch - */ -/* - * transmit timing stuff. See below for scale of srtt and rttvar. - * "Variance" is actually smoothed difference. - */ - short t_idle; /* inactivity time */ - short t_rtt; /* round trip time */ - tcp_seq t_rtseq; /* sequence number being timed */ - short t_srtt; /* smoothed round-trip time */ - short t_rttvar; /* variance in round-trip time */ - u_short t_rttmin; /* minimum rtt allowed */ - u_int32_t max_sndwnd; /* largest window peer has offered */ - -/* out-of-band data */ - char t_oobflags; /* have some */ - char t_iobc; /* input character */ -#define TCPOOB_HAVEDATA 0x01 -#define TCPOOB_HADDATA 0x02 - short t_softerror; /* possible error not yet reported */ - -/* RFC 1323 variables */ - u_char snd_scale; /* window scaling for send window */ - u_char rcv_scale; /* window scaling for recv window */ - u_char request_r_scale; /* pending window scaling */ - u_char requested_s_scale; - u_int32_t ts_recent; /* timestamp echo data */ - u_int32_t ts_recent_age; /* when last updated */ - tcp_seq last_ack_sent; - -}; - -#define sototcpcb(so) ((so)->so_tcpcb) - -/* - * The smoothed round-trip time and estimated variance - * are stored as fixed point numbers scaled by the values below. - * For convenience, these scales are also used in smoothing the average - * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed). - * With these scales, srtt has 3 bits to the right of the binary point, - * and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the - * binary point, and is smoothed with an ALPHA of 0.75. - */ -#define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */ -#define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */ -#define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */ -#define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */ - -/* - * The initial retransmission should happen at rtt + 4 * rttvar. - * Because of the way we do the smoothing, srtt and rttvar - * will each average +1/2 tick of bias. When we compute - * the retransmit timer, we want 1/2 tick of rounding and - * 1 extra tick because of +-1/2 tick uncertainty in the - * firing of the timer. The bias will give us exactly the - * 1.5 tick we need. But, because the bias is - * statistical, we have to test that we don't drop below - * the minimum feasible timer (which is 2 ticks). - * This macro assumes that the value of TCP_RTTVAR_SCALE - * is the same as the multiplier for rttvar. - */ -#define TCP_REXMTVAL(tp) \ - (((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar) - -/* XXX - * We want to avoid doing m_pullup on incoming packets but that - * means avoiding dtom on the tcp reassembly code. That in turn means - * keeping an mbuf pointer in the reassembly queue (since we might - * have a cluster). As a quick hack, the source & destination - * port numbers (which are no longer needed once we've located the - * tcpcb) are overlayed with an mbuf pointer. - */ -#if SIZEOF_CHAR_P == 4 -typedef struct mbuf *mbufp_32; -#else -typedef u_int32_t mbufp_32; -#endif -#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) - -/* - * TCP statistics. - * Many of these should be kept per connection, - * but that's inconvenient at the moment. - */ -struct tcpstat { - u_long tcps_connattempt; /* connections initiated */ - u_long tcps_accepts; /* connections accepted */ - u_long tcps_connects; /* connections established */ - u_long tcps_drops; /* connections dropped */ - u_long tcps_conndrops; /* embryonic connections dropped */ - u_long tcps_closed; /* conn. closed (includes drops) */ - u_long tcps_segstimed; /* segs where we tried to get rtt */ - u_long tcps_rttupdated; /* times we succeeded */ - u_long tcps_delack; /* delayed acks sent */ - u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ - u_long tcps_rexmttimeo; /* retransmit timeouts */ - u_long tcps_persisttimeo; /* persist timeouts */ - u_long tcps_keeptimeo; /* keepalive timeouts */ - u_long tcps_keepprobe; /* keepalive probes sent */ - u_long tcps_keepdrops; /* connections dropped in keepalive */ - - u_long tcps_sndtotal; /* total packets sent */ - u_long tcps_sndpack; /* data packets sent */ - u_long tcps_sndbyte; /* data bytes sent */ - u_long tcps_sndrexmitpack; /* data packets retransmitted */ - u_long tcps_sndrexmitbyte; /* data bytes retransmitted */ - u_long tcps_sndacks; /* ack-only packets sent */ - u_long tcps_sndprobe; /* window probes sent */ - u_long tcps_sndurg; /* packets sent with URG only */ - u_long tcps_sndwinup; /* window update-only packets sent */ - u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ - - u_long tcps_rcvtotal; /* total packets received */ - u_long tcps_rcvpack; /* packets received in sequence */ - u_long tcps_rcvbyte; /* bytes received in sequence */ - u_long tcps_rcvbadsum; /* packets received with ccksum errs */ - u_long tcps_rcvbadoff; /* packets received with bad offset */ -/* u_long tcps_rcvshort; */ /* packets received too short */ - u_long tcps_rcvduppack; /* duplicate-only packets received */ - u_long tcps_rcvdupbyte; /* duplicate-only bytes received */ - u_long tcps_rcvpartduppack; /* packets with some duplicate data */ - u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ - u_long tcps_rcvoopack; /* out-of-order packets received */ - u_long tcps_rcvoobyte; /* out-of-order bytes received */ - u_long tcps_rcvpackafterwin; /* packets with data after window */ - u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */ - u_long tcps_rcvafterclose; /* packets rcvd after "close" */ - u_long tcps_rcvwinprobe; /* rcvd window probe packets */ - u_long tcps_rcvdupack; /* rcvd duplicate acks */ - u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */ - u_long tcps_rcvackpack; /* rcvd ack packets */ - u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */ - u_long tcps_rcvwinupd; /* rcvd window update packets */ -/* u_long tcps_pawsdrop; */ /* segments dropped due to PAWS */ - u_long tcps_predack; /* times hdr predict ok for acks */ - u_long tcps_preddat; /* times hdr predict ok for data pkts */ - u_long tcps_socachemiss; /* tcp_last_so misses */ - u_long tcps_didnuttin; /* Times tcp_output didn't do anything XXX */ -}; - -extern struct tcpstat tcpstat; /* tcp statistics */ -extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ - -#endif diff --git a/BasiliskII/src/slirp/tcpip.h b/BasiliskII/src/slirp/tcpip.h deleted file mode 100644 index dff5a3c9..00000000 --- a/BasiliskII/src/slirp/tcpip.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)tcpip.h 8.1 (Berkeley) 6/10/93 - * tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp - */ - -#ifndef _TCPIP_H_ -#define _TCPIP_H_ - -/* - * Tcp+ip header, after ip options removed. - */ -struct tcpiphdr { - struct ipovly ti_i; /* overlaid ip structure */ - struct tcphdr ti_t; /* tcp header */ -}; -#define ti_next ti_i.ih_next -#define ti_prev ti_i.ih_prev -#define ti_x1 ti_i.ih_x1 -#define ti_pr ti_i.ih_pr -#define ti_len ti_i.ih_len -#define ti_src ti_i.ih_src -#define ti_dst ti_i.ih_dst -#define ti_sport ti_t.th_sport -#define ti_dport ti_t.th_dport -#define ti_seq ti_t.th_seq -#define ti_ack ti_t.th_ack -#define ti_x2 ti_t.th_x2 -#define ti_off ti_t.th_off -#define ti_flags ti_t.th_flags -#define ti_win ti_t.th_win -#define ti_sum ti_t.th_sum -#define ti_urp ti_t.th_urp - -/* - * Just a clean way to get to the first byte - * of the packet - */ -struct tcpiphdr_2 { - struct tcpiphdr dummy; - char first_char; -}; - -#endif diff --git a/BasiliskII/src/slirp/tftp.c b/BasiliskII/src/slirp/tftp.c deleted file mode 100644 index e656c4f0..00000000 --- a/BasiliskII/src/slirp/tftp.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * tftp.c - a simple, read-only tftp server for qemu - * - * Copyright (c) 2004 Magnus Damm - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -struct tftp_session { - int in_use; - char filename[TFTP_FILENAME_MAX]; - - struct in_addr client_ip; - u_int16_t client_port; - - int timestamp; -}; - -struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; - -const char *tftp_prefix; - -static void tftp_session_update(struct tftp_session *spt) -{ - spt->timestamp = curtime; - spt->in_use = 1; -} - -static void tftp_session_terminate(struct tftp_session *spt) -{ - spt->in_use = 0; -} - -static int tftp_session_allocate(struct tftp_t *tp) -{ - struct tftp_session *spt; - int k; - - for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; - - if (!spt->in_use) - goto found; - - /* sessions time out after 5 inactive seconds */ - if ((int)(curtime - spt->timestamp) > 5000) - goto found; - } - - return -1; - - found: - memset(spt, 0, sizeof(*spt)); - memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); - spt->client_port = tp->udp.uh_sport; - - tftp_session_update(spt); - - return k; -} - -static int tftp_session_find(struct tftp_t *tp) -{ - struct tftp_session *spt; - int k; - - for (k = 0; k < TFTP_SESSIONS_MAX; k++) { - spt = &tftp_sessions[k]; - - if (spt->in_use) { - if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { - if (spt->client_port == tp->udp.uh_sport) { - return k; - } - } - } - } - - return -1; -} - -static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, - u_int8_t *buf, int len) -{ - int fd; - int bytes_read = 0; - - fd = open(spt->filename, O_RDONLY | O_BINARY); - - if (fd < 0) { - return -1; - } - - if (len) { - lseek(fd, block_nr * 512, SEEK_SET); - - bytes_read = read(fd, buf, len); - } - - close(fd); - - return bytes_read; -} - -static int tftp_send_error(struct tftp_session *spt, - u_int16_t errorcode, const char *msg, - struct tftp_t *recv_tp) -{ - struct sockaddr_in saddr, daddr; - struct mbuf *m; - struct tftp_t *tp; - int nobytes; - - m = m_get(); - - if (!m) { - return -1; - } - - memset(m->m_data, 0, m->m_size); - - m->m_data += if_maxlinkhdr; - tp = (void *)m->m_data; - m->m_data += sizeof(struct udpiphdr); - - tp->tp_op = htons(TFTP_ERROR); - tp->x.tp_error.tp_error_code = htons(errorcode); - strncpy((char *)tp->x.tp_error.tp_msg, msg, sizeof(tp->x.tp_error.tp_msg)); - tp->x.tp_error.tp_msg[sizeof(tp->x.tp_error.tp_msg)-1] = 0; - - saddr.sin_addr = recv_tp->ip.ip_dst; - saddr.sin_port = recv_tp->udp.uh_dport; - - daddr.sin_addr = spt->client_ip; - daddr.sin_port = spt->client_port; - - nobytes = 2; - - m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - - sizeof(struct ip) - sizeof(struct udphdr); - - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); - - tftp_session_terminate(spt); - - return 0; -} - -static int tftp_send_data(struct tftp_session *spt, - u_int16_t block_nr, - struct tftp_t *recv_tp) -{ - struct sockaddr_in saddr, daddr; - struct mbuf *m; - struct tftp_t *tp; - int nobytes; - - if (block_nr < 1) { - return -1; - } - - m = m_get(); - - if (!m) { - return -1; - } - - memset(m->m_data, 0, m->m_size); - - m->m_data += if_maxlinkhdr; - tp = (void *)m->m_data; - m->m_data += sizeof(struct udpiphdr); - - tp->tp_op = htons(TFTP_DATA); - tp->x.tp_data.tp_block_nr = htons(block_nr); - - saddr.sin_addr = recv_tp->ip.ip_dst; - saddr.sin_port = recv_tp->udp.uh_dport; - - daddr.sin_addr = spt->client_ip; - daddr.sin_port = spt->client_port; - - nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); - - if (nobytes < 0) { - m_free(m); - - /* send "file not found" error back */ - - tftp_send_error(spt, 1, "File not found", tp); - - return -1; - } - - m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - - sizeof(struct ip) - sizeof(struct udphdr); - - udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); - - if (nobytes == 512) { - tftp_session_update(spt); - } - else { - tftp_session_terminate(spt); - } - - return 0; -} - -static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) -{ - struct tftp_session *spt; - int s, k, n; - u_int8_t *src, *dst; - - s = tftp_session_allocate(tp); - - if (s < 0) { - return; - } - - spt = &tftp_sessions[s]; - - src = tp->x.tp_buf; - dst = (u_int8_t *)spt->filename; - n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); - - /* get name */ - - for (k = 0; k < n; k++) { - if (k < TFTP_FILENAME_MAX) { - dst[k] = src[k]; - } - else { - return; - } - - if (src[k] == '\0') { - break; - } - } - - if (k >= n) { - return; - } - - k++; - - /* check mode */ - if ((n - k) < 6) { - return; - } - - if (memcmp(&src[k], "octet\0", 6) != 0) { - tftp_send_error(spt, 4, "Unsupported transfer mode", tp); - return; - } - - /* do sanity checks on the filename */ - - if ((spt->filename[0] != '/') - || (spt->filename[strlen(spt->filename) - 1] == '/') - || strstr(spt->filename, "/../")) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - /* only allow exported prefixes */ - - if (!tftp_prefix - || (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } - - /* check if the file exists */ - - if (tftp_read_data(spt, 0, (u_int8_t *)spt->filename, 0) < 0) { - tftp_send_error(spt, 1, "File not found", tp); - return; - } - - tftp_send_data(spt, 1, tp); -} - -static void tftp_handle_ack(struct tftp_t *tp, int pktlen) -{ - int s; - - s = tftp_session_find(tp); - - if (s < 0) { - return; - } - - if (tftp_send_data(&tftp_sessions[s], - ntohs(tp->x.tp_data.tp_block_nr) + 1, - tp) < 0) { - return; - } -} - -void tftp_input(struct mbuf *m) -{ - struct tftp_t *tp = (struct tftp_t *)m->m_data; - - switch(ntohs(tp->tp_op)) { - case TFTP_RRQ: - tftp_handle_rrq(tp, m->m_len); - break; - - case TFTP_ACK: - tftp_handle_ack(tp, m->m_len); - break; - } -} diff --git a/BasiliskII/src/slirp/tftp.h b/BasiliskII/src/slirp/tftp.h deleted file mode 100644 index b150a049..00000000 --- a/BasiliskII/src/slirp/tftp.h +++ /dev/null @@ -1,40 +0,0 @@ -/* tftp defines */ - -#define TFTP_SESSIONS_MAX 3 - -#define TFTP_SERVER 69 - -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 - -#define TFTP_FILENAME_MAX 512 - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct tftp_t { - struct ip ip; - struct udphdr udp; - u_int16_t tp_op; - union { - struct { - u_int16_t tp_block_nr; - u_int8_t tp_buf[512]; - } tp_data; - struct { - u_int16_t tp_error_code; - u_int8_t tp_msg[512]; - } tp_error; - u_int8_t tp_buf[512 + 2]; - } x; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -void tftp_input(struct mbuf *m); diff --git a/BasiliskII/src/slirp/udp.c b/BasiliskII/src/slirp/udp.c deleted file mode 100644 index deedb1e7..00000000 --- a/BasiliskII/src/slirp/udp.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1988, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 - * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp - */ - -/* - * Changes and additions relating to SLiRP - * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the - * terms and conditions of the copyright. - */ - -#include -#include -#include "ip_icmp.h" - -struct udpstat udpstat; - -struct socket udb; - -/* - * UDP protocol implementation. - * Per RFC 768, August, 1980. - */ -#ifndef COMPAT_42 -int udpcksum = 1; -#else -int udpcksum = 0; /* XXX */ -#endif - -struct socket *udp_last_so = &udb; - -void -udp_init() -{ - udb.so_next = udb.so_prev = &udb; -} -/* m->m_data points at ip packet header - * m->m_len length ip packet - * ip->ip_len length data (IPDU) - */ -void -udp_input(m, iphlen) - register struct mbuf *m; - int iphlen; -{ - register struct ip *ip; - register struct udphdr *uh; -/* struct mbuf *opts = 0;*/ - int len; - struct ip save_ip; - struct socket *so; - - DEBUG_CALL("udp_input"); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("iphlen = %d", iphlen); - - udpstat.udps_ipackets++; - - /* - * Strip IP options, if any; should skip this, - * make available to user, and use on returned packets, - * but we don't yet have a way to check the checksum - * with options still present. - */ - if(iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } - - /* - * Get IP and UDP header together in first mbuf. - */ - ip = mtod(m, struct ip *); - uh = (struct udphdr *)((caddr_t)ip + iphlen); - - /* - * Make mbuf data length reflect UDP length. - * If not enough data to reflect UDP length, drop. - */ - len = ntohs((u_int16_t)uh->uh_ulen); - - if (ip->ip_len != len) { - if (len > ip->ip_len) { - udpstat.udps_badlen++; - goto bad; - } - m_adj(m, len - ip->ip_len); - ip->ip_len = len; - } - - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip = *ip; - save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ - - /* - * Checksum extended UDP header and data. - */ - if (udpcksum && uh->uh_sum) { - ((struct ipovly *)ip)->ih_next = 0; - ((struct ipovly *)ip)->ih_prev = 0; - ((struct ipovly *)ip)->ih_x1 = 0; - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - /* keep uh_sum for ICMP reply - * uh->uh_sum = cksum(m, len + sizeof (struct ip)); - * if (uh->uh_sum) { - */ - if(cksum(m, len + sizeof(struct ip))) { - udpstat.udps_badsum++; - goto bad; - } - } - - /* - * handle DHCP/BOOTP - */ - if (ntohs(uh->uh_dport) == BOOTP_SERVER) { - bootp_input(m); - goto bad; - } - - /* - * handle TFTP - */ - if (ntohs(uh->uh_dport) == TFTP_SERVER) { - tftp_input(m); - goto bad; - } - - /* - * Locate pcb for datagram. - */ - so = udp_last_so; - if (so->so_lport != uh->uh_sport || - so->so_laddr.s_addr != ip->ip_src.s_addr) { - struct socket *tmp; - - for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { - if (tmp->so_lport == uh->uh_sport && - tmp->so_laddr.s_addr == ip->ip_src.s_addr) { - tmp->so_faddr.s_addr = ip->ip_dst.s_addr; - tmp->so_fport = uh->uh_dport; - so = tmp; - break; - } - } - if (tmp == &udb) { - so = NULL; - } else { - udpstat.udpps_pcbcachemiss++; - udp_last_so = so; - } - } - - if (so == NULL) { - /* - * If there's no socket for this packet, - * create one - */ - if ((so = socreate()) == NULL) goto bad; - if(udp_attach(so) == -1) { - DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", - errno,strerror(errno))); - sofree(so); - goto bad; - } - - /* - * Setup fields - */ - /* udp_last_so = so; */ - so->so_laddr = ip->ip_src; - so->so_lport = uh->uh_sport; - - if ((so->so_iptos = udp_tos(so)) == 0) - so->so_iptos = ip->ip_tos; - - /* - * XXXXX Here, check if it's in udpexec_list, - * and if it is, do the fork_exec() etc. - */ - } - - so->so_faddr = ip->ip_dst; /* XXX */ - so->so_fport = uh->uh_dport; /* XXX */ - - iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_data += iphlen; - - /* - * Now we sendto() the packet. - */ - if (so->so_emu) - udp_emu(so, m); - - if(sosendto(so,m) == -1) { - m->m_len += iphlen; - m->m_data -= iphlen; - *ip=save_ip; - DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); - } - - m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ - - /* restore the orig mbuf packet */ - m->m_len += iphlen; - m->m_data -= iphlen; - *ip=save_ip; - so->so_m=m; /* ICMP backup */ - - return; -bad: - m_freem(m); - /* if (opts) m_freem(opts); */ - return; -} - -int udp_output2(struct socket *so, struct mbuf *m, - struct sockaddr_in *saddr, struct sockaddr_in *daddr, - int iptos) -{ - register struct udpiphdr *ui; - int error = 0; - - DEBUG_CALL("udp_output"); - DEBUG_ARG("so = %lx", (long)so); - DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr); - DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr); - - /* - * Adjust for header - */ - m->m_data -= sizeof(struct udpiphdr); - m->m_len += sizeof(struct udpiphdr); - - /* - * Fill in mbuf with extended UDP header - * and addresses and length put into network format. - */ - ui = mtod(m, struct udpiphdr *); - ui->ui_next = ui->ui_prev = 0; - ui->ui_x1 = 0; - ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */ - /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ - ui->ui_src = saddr->sin_addr; - ui->ui_dst = daddr->sin_addr; - ui->ui_sport = saddr->sin_port; - ui->ui_dport = daddr->sin_port; - ui->ui_ulen = ui->ui_len; - - /* - * Stuff checksum and output datagram. - */ - ui->ui_sum = 0; - if (udpcksum) { - if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) - ui->ui_sum = 0xffff; - } - ((struct ip *)ui)->ip_len = (u_int16_t) m->m_len; - - ((struct ip *)ui)->ip_ttl = ip_defttl; - ((struct ip *)ui)->ip_tos = iptos; - - udpstat.udps_opackets++; - - error = ip_output(so, m); - - return (error); -} - -int udp_output(struct socket *so, struct mbuf *m, - struct sockaddr_in *addr) - -{ - struct sockaddr_in saddr, daddr; - - saddr = *addr; - if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { - saddr.sin_addr.s_addr = so->so_faddr.s_addr; - if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff)) - saddr.sin_addr.s_addr = alias_addr.s_addr; - } - daddr.sin_addr = so->so_laddr; - daddr.sin_port = so->so_lport; - - return udp_output2(so, m, &saddr, &daddr, so->so_iptos); -} - -int -udp_attach(so) - struct socket *so; -{ - struct sockaddr_in addr; - - if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { - /* - * Here, we bind() the socket. Although not really needed - * (sendto() on an unbound socket will bind it), it's done - * here so that emulation of ytalk etc. don't have to do it - */ - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = INADDR_ANY; - if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) { - int error = WSAGetLastError(); - closesocket(so->s); - so->s=-1; - WSASetLastError(error); - } else { - /* success, insert in queue */ - so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); - } - } - return(so->s); -} - -void -udp_detach(so) - struct socket *so; -{ - closesocket(so->s); - /* if (so->so_m) m_free(so->so_m); done by sofree */ - - sofree(so); -} - -struct tos_t udptos[] = { - {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ - {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ - {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ - {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */ - {0, 0, 0, 0} -}; - -u_int8_t -udp_tos(so) - struct socket *so; -{ - int i = 0; - - while(udptos[i].tos) { - if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || - (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { - so->so_emu = udptos[i].emu; - return udptos[i].tos; - } - i++; - } - - return 0; -} - -#ifdef EMULATE_TALK -#include "talkd.h" -#endif - -/* - * Here, talk/ytalk/ntalk requests must be emulated - */ -void -udp_emu(so, m) - struct socket *so; - struct mbuf *m; -{ - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); -#ifdef EMULATE_TALK - CTL_MSG_OLD *omsg; - CTL_MSG *nmsg; - char buff[sizeof(CTL_MSG)]; - u_char type; - -struct talk_request { - struct talk_request *next; - struct socket *udp_so; - struct socket *tcp_so; -} *req; - - static struct talk_request *req_tbl = 0; - -#endif - -struct cu_header { - uint16_t d_family; // destination family - uint16_t d_port; // destination port - uint32_t d_addr; // destination address - uint16_t s_family; // source family - uint16_t s_port; // source port - uint32_t so_addr; // source address - uint32_t seqn; // sequence number - uint16_t message; // message - uint16_t data_type; // data type - uint16_t pkt_len; // packet length -} *cu_head; - - switch(so->so_emu) { - -#ifdef EMULATE_TALK - case EMU_TALK: - case EMU_NTALK: - /* - * Talk emulation. We always change the ctl_addr to get - * some answers from the daemon. When an ANNOUNCE comes, - * we send LEAVE_INVITE to the local daemons. Also when a - * DELETE comes, we send copies to the local daemons. - */ - if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) - return; - -#define IS_OLD (so->so_emu == EMU_TALK) - -#define COPY_MSG(dest, src) { dest->type = src->type; \ - dest->id_num = src->id_num; \ - dest->pid = src->pid; \ - dest->addr = src->addr; \ - dest->ctl_addr = src->ctl_addr; \ - memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \ - memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \ - memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); } - -#define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field) -/* old_sockaddr to sockaddr_in */ - - - if (IS_OLD) { /* old talk */ - omsg = mtod(m, CTL_MSG_OLD*); - nmsg = (CTL_MSG *) buff; - type = omsg->type; - OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; - OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; - strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); - } else { /* new talk */ - omsg = (CTL_MSG_OLD *) buff; - nmsg = mtod(m, CTL_MSG *); - type = nmsg->type; - OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; - strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); - } - - if (type == LOOK_UP) - return; /* for LOOK_UP this is enough */ - - if (IS_OLD) { /* make a copy of the message */ - COPY_MSG(nmsg, omsg); - nmsg->vers = 1; - nmsg->answer = 0; - } else - COPY_MSG(omsg, nmsg); - - /* - * If if is an ANNOUNCE message, we go through the - * request table to see if a tcp port has already - * been redirected for this socket. If not, we solisten() - * a new socket and add this entry to the table. - * The port number of the tcp socket and our IP - * are put to the addr field of the message structures. - * Then a LEAVE_INVITE is sent to both local daemon - * ports, 517 and 518. This is why we have two copies - * of the message, one in old talk and one in new talk - * format. - */ - - if (type == ANNOUNCE) { - int s; - u_short temp_port; - - for(req = req_tbl; req; req = req->next) - if (so == req->udp_so) - break; /* found it */ - - if (!req) { /* no entry for so, create new */ - req = (struct talk_request *) - malloc(sizeof(struct talk_request)); - req->udp_so = so; - req->tcp_so = solisten(0, - OTOSIN(omsg, addr)->sin_addr.s_addr, - OTOSIN(omsg, addr)->sin_port, - SS_FACCEPTONCE); - req->next = req_tbl; - req_tbl = req; - } - - /* replace port number in addr field */ - addrlen = sizeof(addr); - getsockname(req->tcp_so->s, - (struct sockaddr *) &addr, - &addrlen); - OTOSIN(omsg, addr)->sin_port = addr.sin_port; - OTOSIN(omsg, addr)->sin_addr = our_addr; - OTOSIN(nmsg, addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, addr)->sin_addr = our_addr; - - /* send LEAVE_INVITEs */ - temp_port = OTOSIN(omsg, ctl_addr)->sin_port; - OTOSIN(omsg, ctl_addr)->sin_port = 0; - OTOSIN(nmsg, ctl_addr)->sin_port = 0; - omsg->type = nmsg->type = LEAVE_INVITE; - - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - addr.sin_addr = our_addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(517); - sendto(s, (char *)omsg, sizeof(*omsg), 0, - (struct sockaddr *)&addr, sizeof(addr)); - addr.sin_port = htons(518); - sendto(s, (char *)nmsg, sizeof(*nmsg), 0, - (struct sockaddr *) &addr, sizeof(addr)); - closesocket(s) ; - - omsg->type = nmsg->type = ANNOUNCE; - OTOSIN(omsg, ctl_addr)->sin_port = temp_port; - OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; - } - - /* - * If it is a DELETE message, we send a copy to the - * local daemons. Then we delete the entry corresponding - * to our socket from the request table. - */ - - if (type == DELETE) { - struct talk_request *temp_req, *req_next; - int s; - u_short temp_port; - - temp_port = OTOSIN(omsg, ctl_addr)->sin_port; - OTOSIN(omsg, ctl_addr)->sin_port = 0; - OTOSIN(nmsg, ctl_addr)->sin_port = 0; - - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - addr.sin_addr = our_addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(517); - sendto(s, (char *)omsg, sizeof(*omsg), 0, - (struct sockaddr *)&addr, sizeof(addr)); - addr.sin_port = htons(518); - sendto(s, (char *)nmsg, sizeof(*nmsg), 0, - (struct sockaddr *)&addr, sizeof(addr)); - closesocket(s); - - OTOSIN(omsg, ctl_addr)->sin_port = temp_port; - OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; - - /* delete table entry */ - if (so == req_tbl->udp_so) { - temp_req = req_tbl; - req_tbl = req_tbl->next; - free(temp_req); - } else { - temp_req = req_tbl; - for(req = req_tbl->next; req; req = req_next) { - req_next = req->next; - if (so == req->udp_so) { - temp_req->next = req_next; - free(req); - break; - } else { - temp_req = req; - } - } - } - } - - return; -#endif - - case EMU_CUSEEME: - - /* - * Cu-SeeMe emulation. - * Hopefully the packet is more that 16 bytes long. We don't - * do any other tests, just replace the address and port - * fields. - */ - if (m->m_len >= sizeof (*cu_head)) { - if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) - return; - cu_head = mtod(m, struct cu_header *); - cu_head->s_port = addr.sin_port; - cu_head->so_addr = our_addr.s_addr; - } - - return; - } -} - -struct socket * -udp_listen(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; -{ - struct sockaddr_in addr; - struct socket *so; - socklen_t addrlen = sizeof(struct sockaddr_in); - int opt = 1; - - if ((so = socreate()) == NULL) { - free(so); - return NULL; - } - so->s = socket(AF_INET,SOCK_DGRAM,0); - so->so_expire = curtime + SO_EXPIRE; - insque(so,&udb); - - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = port; - - if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { - udp_detach(so); - return NULL; - } - setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); -/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ - - getsockname(so->s,(struct sockaddr *)&addr,&addrlen); - so->so_fport = addr.sin_port; - if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) - so->so_faddr = alias_addr; - else - so->so_faddr = addr.sin_addr; - - so->so_lport = lport; - so->so_laddr.s_addr = laddr; - if (flags != SS_FACCEPTONCE) - so->so_expire = 0; - - so->so_state = SS_ISFCONNECTED; - - return so; -} diff --git a/BasiliskII/src/slirp/udp.h b/BasiliskII/src/slirp/udp.h deleted file mode 100644 index 7d844efe..00000000 --- a/BasiliskII/src/slirp/udp.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. - * - * @(#)udp.h 8.1 (Berkeley) 6/10/93 - * udp.h,v 1.3 1994/08/21 05:27:41 paul Exp - */ - -#ifndef _UDP_H_ -#define _UDP_H_ - -#define UDP_TTL 0x60 -#define UDP_UDPDATALEN 16192 - -extern struct socket *udp_last_so; - -/* - * Udp protocol header. - * Per RFC 768, September, 1981. - */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -struct udphdr { - u_int16_t uh_sport; /* source port */ - u_int16_t uh_dport; /* destination port */ - int16_t uh_ulen; /* udp length */ - u_int16_t uh_sum; /* udp checksum */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif - -/* - * UDP kernel structures and variables. - */ -struct udpiphdr { - struct ipovly ui_i; /* overlaid ip structure */ - struct udphdr ui_u; /* udp header */ -}; -#define ui_next ui_i.ih_next -#define ui_prev ui_i.ih_prev -#define ui_x1 ui_i.ih_x1 -#define ui_pr ui_i.ih_pr -#define ui_len ui_i.ih_len -#define ui_src ui_i.ih_src -#define ui_dst ui_i.ih_dst -#define ui_sport ui_u.uh_sport -#define ui_dport ui_u.uh_dport -#define ui_ulen ui_u.uh_ulen -#define ui_sum ui_u.uh_sum - -struct udpstat { - /* input statistics: */ - u_long udps_ipackets; /* total input packets */ - u_long udps_hdrops; /* packet shorter than header */ - u_long udps_badsum; /* checksum error */ - u_long udps_badlen; /* data length larger than packet */ - u_long udps_noport; /* no socket on port */ - u_long udps_noportbcast; /* of above, arrived as broadcast */ - u_long udps_fullsock; /* not delivered, input socket full */ - u_long udpps_pcbcachemiss; /* input packets missing pcb cache */ - /* output statistics: */ - u_long udps_opackets; /* total output packets */ -}; - -/* - * Names for UDP sysctl objects - */ -#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ -#define UDPCTL_MAXID 2 - -extern struct udpstat udpstat; -extern struct socket udb; -struct mbuf; - -void udp_init(void); -void udp_input(register struct mbuf *, int); -int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *); -int udp_attach(struct socket *); -void udp_detach(struct socket *); -u_int8_t udp_tos(struct socket *); -void udp_emu(struct socket *, struct mbuf *); -struct socket * udp_listen(u_int, u_int32_t, u_int, int); -int udp_output2(struct socket *so, struct mbuf *m, - struct sockaddr_in *saddr, struct sockaddr_in *daddr, - int iptos); -#endif diff --git a/BasiliskII/src/sony.cpp b/BasiliskII/src/sony.cpp index 804239b7..a8d8220d 100644 --- a/BasiliskII/src/sony.cpp +++ b/BasiliskII/src/sony.cpp @@ -50,11 +50,7 @@ using std::vector; // Check for inserted disks by polling? -#ifdef AMIGA -#define DISK_INSERT_CHECK 1 -#else #define DISK_INSERT_CHECK 0 -#endif // Floppy disk icon diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index b29c7702..8dd7d173 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -30,7 +30,6 @@ #include "memory.h" #include "readcpu.h" #include "newcpu.h" -#include "compiler/compemu.h" // RAM and ROM pointers @@ -41,21 +40,15 @@ uint32 ROMBaseMac; // ROM base (Mac address space) uint8 *ROMBaseHost; // ROM base (host address space) uint32 ROMSize; // Size of ROM -#if !REAL_ADDRESSING // Mac frame buffer uint8 *MacFrameBaseHost; // Frame buffer base (host address space) uint32 MacFrameSize; // Size of frame buffer int MacFrameLayout; // Frame buffer layout -#endif #if DIRECT_ADDRESSING uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equivalent #endif -#if USE_JIT -bool UseJIT = false; -#endif - // From newcpu.cpp extern bool quit_program; @@ -66,42 +59,15 @@ extern bool quit_program; bool Init680x0(void) { -#if REAL_ADDRESSING - // Mac address space = host address space - RAMBaseMac = (uintptr)RAMBaseHost; - ROMBaseMac = (uintptr)ROMBaseHost; -#elif DIRECT_ADDRESSING +#if DIRECT_ADDRESSING // Mac address space = host address space minus constant offset (MEMBaseDiff) // NOTE: MEMBaseDiff is set up in main_unix.cpp/main() RAMBaseMac = 0; ROMBaseMac = Host2MacAddr(ROMBaseHost); -#else - // Initialize UAE memory banks - RAMBaseMac = 0; - switch (ROMVersion) { - case ROM_VERSION_64K: - case ROM_VERSION_PLUS: - case ROM_VERSION_CLASSIC: - ROMBaseMac = 0x00400000; - break; - case ROM_VERSION_II: - ROMBaseMac = 0x00a00000; - break; - case ROM_VERSION_32: - ROMBaseMac = 0x40800000; - break; - default: - return false; - } - memory_init(); #endif init_m68k(); -#if USE_JIT - UseJIT = compiler_use_jit(); - if (UseJIT) - compiler_init(); -#endif + return true; } @@ -112,10 +78,7 @@ bool Init680x0(void) void Exit680x0(void) { -#if USE_JIT - if (UseJIT) - compiler_exit(); -#endif + exit_m68k(); } @@ -126,9 +89,7 @@ void Exit680x0(void) void InitFrameBufferMapping(void) { -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING - memory_init(); -#endif + } /* @@ -138,11 +99,7 @@ void InitFrameBufferMapping(void) void Start680x0(void) { m68k_reset(); -#if USE_JIT - if (UseJIT) - m68k_compile_execute(); - else -#endif + m68k_execute(); } diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index 8ec3ab55..af5cac92 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -72,15 +72,7 @@ int main(int argc, char **argv) printf ("#include \"sysdeps.h\"\n"); printf ("#include \"readcpu.h\"\n"); printf ("struct instr_def defs68k[] = {\n"); -#ifdef WIN32 - tablef = fopen(argc > 1 ? argv[1] : "table68k","r"); - if (tablef == NULL) { - fprintf(stderr, "table68k not found\n"); - exit(1); - } -#else tablef = stdin; -#endif getnextch(); while (nextch != EOF) { int cpulevel, plevel, sduse; diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp deleted file mode 100644 index f03c4f3c..00000000 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp +++ /dev/null @@ -1,4758 +0,0 @@ -/* - * compiler/codegen_x86.cpp - IA-32 code generator - * - * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer - * - * Adaptation for Basilisk II and improvements, copyright 2000-2005 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This should eventually end up in machdep/, but for now, x86 is the - only target, and it's easier this way... */ - -#include "flags_x86.h" - -/************************************************************************* - * Some basic information about the the target CPU * - *************************************************************************/ - -#define EAX_INDEX 0 -#define ECX_INDEX 1 -#define EDX_INDEX 2 -#define EBX_INDEX 3 -#define ESP_INDEX 4 -#define EBP_INDEX 5 -#define ESI_INDEX 6 -#define EDI_INDEX 7 -#if defined(__x86_64__) -#define R8_INDEX 8 -#define R9_INDEX 9 -#define R10_INDEX 10 -#define R11_INDEX 11 -#define R12_INDEX 12 -#define R13_INDEX 13 -#define R14_INDEX 14 -#define R15_INDEX 15 -#endif -/* XXX this has to match X86_Reg8H_Base + 4 */ -#define AH_INDEX (0x10+4+EAX_INDEX) -#define CH_INDEX (0x10+4+ECX_INDEX) -#define DH_INDEX (0x10+4+EDX_INDEX) -#define BH_INDEX (0x10+4+EBX_INDEX) - -/* The register in which subroutines return an integer return value */ -#define REG_RESULT EAX_INDEX - -/* The registers subroutines take their first and second argument in */ -#if defined( _MSC_VER ) && !USE_NORMAL_CALLING_CONVENTION -/* Handle the _fastcall parameters of ECX and EDX */ -#define REG_PAR1 ECX_INDEX -#define REG_PAR2 EDX_INDEX -#elif defined(__x86_64__) -#define REG_PAR1 EDI_INDEX -#define REG_PAR2 ESI_INDEX -#else -#define REG_PAR1 EAX_INDEX -#define REG_PAR2 EDX_INDEX -#endif - -#define REG_PC_PRE EAX_INDEX /* The register we use for preloading regs.pc_p */ -#if defined( _MSC_VER ) && !USE_NORMAL_CALLING_CONVENTION -#define REG_PC_TMP EAX_INDEX -#else -#define REG_PC_TMP ECX_INDEX /* Another register that is not the above */ -#endif - -#define SHIFTCOUNT_NREG ECX_INDEX /* Register that can be used for shiftcount. - -1 if any reg will do */ -#define MUL_NREG1 EAX_INDEX /* %eax will hold the low 32 bits after a 32x32 mul */ -#define MUL_NREG2 EDX_INDEX /* %edx will hold the high 32 bits */ - -#define STACK_ALIGN 16 -#define STACK_OFFSET sizeof(void *) - -uae_s8 always_used[]={4,-1}; -#if defined(__x86_64__) -uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; -uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; -#else -uae_s8 can_byte[]={0,1,2,3,-1}; -uae_s8 can_word[]={0,1,2,3,5,6,7,-1}; -#endif - -#if USE_OPTIMIZED_CALLS -/* Make sure interpretive core does not use cpuopti */ -uae_u8 call_saved[]={0,0,0,1,1,1,1,1}; -#error FIXME: code not ready -#else -/* cpuopti mutate instruction handlers to assume registers are saved - by the caller */ -uae_u8 call_saved[]={0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}; -#endif - -/* This *should* be the same as call_saved. But: - - We might not really know which registers are saved, and which aren't, - so we need to preserve some, but don't want to rely on everyone else - also saving those registers - - Special registers (such like the stack pointer) should not be "preserved" - by pushing, even though they are "saved" across function calls -*/ -#if defined(__x86_64__) -/* callee-saved registers as defined by Linux AMD64 ABI: rbx, rbp, rsp, r12 - r15 */ -/* preserve r11 because it's generally used to hold pointers to functions */ -static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,0,0,0,0,0,1,1,1,1,1}; -#else -/* callee-saved registers as defined by System V IA-32 ABI: edi, esi, ebx, ebp */ -static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1}; -#endif - -/* Whether classes of instructions do or don't clobber the native flags */ -#define CLOBBER_MOV -#define CLOBBER_LEA -#define CLOBBER_CMOV -#define CLOBBER_POP -#define CLOBBER_PUSH -#define CLOBBER_SUB clobber_flags() -#define CLOBBER_SBB clobber_flags() -#define CLOBBER_CMP clobber_flags() -#define CLOBBER_ADD clobber_flags() -#define CLOBBER_ADC clobber_flags() -#define CLOBBER_AND clobber_flags() -#define CLOBBER_OR clobber_flags() -#define CLOBBER_XOR clobber_flags() - -#define CLOBBER_ROL clobber_flags() -#define CLOBBER_ROR clobber_flags() -#define CLOBBER_SHLL clobber_flags() -#define CLOBBER_SHRL clobber_flags() -#define CLOBBER_SHRA clobber_flags() -#define CLOBBER_TEST clobber_flags() -#define CLOBBER_CL16 -#define CLOBBER_CL8 -#define CLOBBER_SE32 -#define CLOBBER_SE16 -#define CLOBBER_SE8 -#define CLOBBER_ZE32 -#define CLOBBER_ZE16 -#define CLOBBER_ZE8 -#define CLOBBER_SW16 clobber_flags() -#define CLOBBER_SW32 -#define CLOBBER_SETCC -#define CLOBBER_MUL clobber_flags() -#define CLOBBER_BT clobber_flags() -#define CLOBBER_BSF clobber_flags() - -/* The older code generator is now deprecated. */ -#define USE_NEW_RTASM 1 - -#if USE_NEW_RTASM - -#if defined(__x86_64__) -#define X86_TARGET_64BIT 1 -/* The address override prefix causes a 5 cycles penalty on Intel Core - processors. Another solution would be to decompose the load in an LEA, - MOV (to zero-extend), MOV (from memory): is it better? */ -#define ADDR32 x86_emit_byte(0x67), -#else -#define ADDR32 /**/ -#endif -#define X86_FLAT_REGISTERS 0 -#define X86_OPTIMIZE_ALU 1 -#define X86_OPTIMIZE_ROTSHI 1 -#include "codegen_x86.h" - -#define x86_emit_byte(B) emit_byte(B) -#define x86_emit_word(W) emit_word(W) -#define x86_emit_long(L) emit_long(L) -#define x86_emit_quad(Q) emit_quad(Q) -#define x86_get_target() get_target() -#define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__) - -static void jit_fail(const char *msg, const char *file, int line, const char *function) -{ - fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n", - function, file, line, msg); - abort(); -} - -LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) -{ -#if defined(__x86_64__) - PUSHQr(r); -#else - PUSHLr(r); -#endif -} -LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) - -LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) -{ -#if defined(__x86_64__) - POPQr(r); -#else - POPLr(r); -#endif -} -LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) - -LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) -{ -#if defined(__x86_64__) - POPQm(d, X86_NOREG, X86_NOREG, 1); -#else - POPLm(d, X86_NOREG, X86_NOREG, 1); -#endif -} -LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) - -LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) -{ - BTLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) -{ - BTLrr(b, r); -} -LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) -{ - BTCLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) -{ - BTCLrr(b, r); -} -LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) -{ - BTRLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) -{ - BTRLrr(b, r); -} -LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) -{ - BTSLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) -{ - BTSLrr(b, r); -} -LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) -{ - SUBWir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) - -LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) -{ - MOVLmr(s, X86_NOREG, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) -{ - MOVLim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) -{ - MOVWim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) -{ - MOVBim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) -{ - ROLBim(i, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) -{ - ROLBir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) -{ - ROLWir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) -{ - ROLLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) -{ - ROLLrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) -{ - ROLWrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) -{ - ROLBrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) -{ - SHLLrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) -{ - SHLWrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) -{ - SHLBrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) -{ - RORBir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) -{ - RORWir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) -{ - ORLmr(s, X86_NOREG, X86_NOREG, 1, d); -} -LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) - -LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) -{ - RORLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) -{ - RORLrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) -{ - RORWrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) -{ - RORBrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) -{ - SHRLrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) -{ - SHRWrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) -{ - SHRBrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) -{ - SARLrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) -{ - SARWrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) -{ - SARBrr(r, d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) -{ - SHLLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) -{ - SHLWir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) -{ - SHLBir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) -{ - SHRLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) -{ - SHRWir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) -{ - SHRBir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) -{ - SARLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) -{ - SARWir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) -{ - SARBir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) -{ - SAHF(); -} -LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) - -LOWFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) -{ - CPUID(); -} -LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) - -LOWFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) -{ - LAHF(); -} -LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) - -LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) -{ - SETCCir(cc, d); -} -LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) - -LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) -{ - SETCCim(cc, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_b_rr,(RW1 d, R1 s, IMM cc)) -{ - /* replacement using branch and mov */ - int8 *target_p = (int8 *)x86_get_target() + 1; - JCCSii(cc^1, 0); - MOVBrr(s, d); - *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); -} -LENDFUNC(READ,NONE,3,raw_cmov_b_rr,(RW1 d, R1 s, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_w_rr,(RW2 d, R2 s, IMM cc)) -{ - if (have_cmov) - CMOVWrr(cc, s, d); - else { /* replacement using branch and mov */ - int8 *target_p = (int8 *)x86_get_target() + 1; - JCCSii(cc^1, 0); - MOVWrr(s, d); - *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); - } -} -LENDFUNC(READ,NONE,3,raw_cmov_w_rr,(RW2 d, R2 s, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) -{ - if (have_cmov) - CMOVLrr(cc, s, d); - else { /* replacement using branch and mov */ - int8 *target_p = (int8 *)x86_get_target() + 1; - JCCSii(cc^1, 0); - MOVLrr(s, d); - *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); - } -} -LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) - -LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) -{ - BSFLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) -{ - MOVSLQrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) -{ - MOVSWLrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) -{ - MOVSBLrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) -{ - MOVZWLrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) - -LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) -{ - MOVZBLrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) -{ - IMULLrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) -{ - if (d!=MUL_NREG1 || s!=MUL_NREG2) { - write_log("Bad register in IMUL: d=%d, s=%d\n",d,s); - abort(); - } - IMULLr(s); -} -LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) - -LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) -{ - if (d!=MUL_NREG1 || s!=MUL_NREG2) { - write_log("Bad register in MUL: d=%d, s=%d\n",d,s); - abort(); - } - MULLr(s); -} -LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) - -LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) -{ - abort(); /* %^$&%^$%#^ x86! */ -} -LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) -{ - MOVBrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) -{ - MOVWrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) - -LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) -{ - ADDR32 MOVLmr(0, baser, index, factor, d); -} -LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) -{ - ADDR32 MOVWmr(0, baser, index, factor, d); -} -LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) -{ - ADDR32 MOVBmr(0, baser, index, factor, d); -} -LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) -{ - ADDR32 MOVLrm(s, 0, baser, index, factor); -} -LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) - -LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) -{ - ADDR32 MOVWrm(s, 0, baser, index, factor); -} -LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) - -LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) -{ - ADDR32 MOVBrm(s, 0, baser, index, factor); -} -LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) -{ - ADDR32 MOVLrm(s, base, baser, index, factor); -} -LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) -{ - ADDR32 MOVWrm(s, base, baser, index, factor); -} -LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) -{ - ADDR32 MOVBrm(s, base, baser, index, factor); -} -LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) - -LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - ADDR32 MOVLmr(base, baser, index, factor, d); -} -LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - ADDR32 MOVWmr(base, baser, index, factor, d); -} -LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - ADDR32 MOVBmr(base, baser, index, factor, d); -} -LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) -{ - ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); -} -LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) -{ - if (have_cmov) - ADDR32 CMOVLmr(cond, base, X86_NOREG, index, factor, d); - else { /* replacement using branch and mov */ - int8 *target_p = (int8 *)x86_get_target() + 1; - JCCSii(cond^1, 0); - ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); - *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); - } -} -LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) - -LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) -{ - if (have_cmov) - CMOVLmr(cond, mem, X86_NOREG, X86_NOREG, 1, d); - else { /* replacement using branch and mov */ - int8 *target_p = (int8 *)x86_get_target() + 1; - JCCSii(cond^1, 0); - MOVLmr(mem, X86_NOREG, X86_NOREG, 1, d); - *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); - } -} -LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) - -LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) -{ - ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) -{ - ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) -{ - ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) -{ - ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) -{ - ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) -{ - ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) -{ - ADDR32 MOVLim(i, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) -{ - ADDR32 MOVWim(i, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) -{ - ADDR32 MOVBim(i, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) -{ - ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) -{ - ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) -{ - ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) - -LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) -{ - LEALmr(offset, s, X86_NOREG, 1, d); -} -LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) -{ - LEALmr(offset, s, index, factor, d); -} -LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) - -LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) -{ - LEALmr(0, s, index, factor, d); -} -LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) - -LOWFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) -{ - LEALmr(0, X86_NOREG, index, factor, d); -} -LENDFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) -{ - ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) -{ - ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) -{ - ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) - -LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) -{ - BSWAPLr(r); -} -LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) - -LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) -{ - ROLWir(8, r); -} -LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) - -LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) -{ - MOVLrr(s, d); -} -LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) -{ - MOVLrm(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) -{ - MOVWrm(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) - -LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) -{ - MOVWmr(s, X86_NOREG, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) -{ - MOVBrm(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) - -LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) -{ - MOVBmr(s, X86_NOREG, X86_NOREG, 1, d); -} -LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) -{ - MOVLir(s, d); -} -LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) -{ - MOVWir(s, d); -} -LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) -{ - MOVBir(s, d); -} -LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) - -LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) -{ - ADCLim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) -{ - ADDLim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) -{ - ADDWim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) -{ - ADDBim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) -{ - TESTLir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) -{ - TESTLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) -{ - TESTWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) -{ - TESTBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) -{ - XORLir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) -{ - ANDLir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) -{ - ANDWir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) -{ - ANDLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) -{ - ANDWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) -{ - ANDBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) -{ - ORLir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) -{ - ORLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) -{ - ORWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) -{ - ORBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) -{ - ADCLrr(s, d); -} -LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) -{ - ADCWrr(s, d); -} -LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) -{ - ADCBrr(s, d); -} -LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) -{ - ADDLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) -{ - ADDWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) -{ - ADDBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) -{ - SUBLir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) -{ - SUBBir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) -{ - ADDLir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) -{ - ADDWir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) -{ - ADDBir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) - -LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) -{ - SBBLrr(s, d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) - -LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) -{ - SBBWrr(s, d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) - -LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) -{ - SBBBrr(s, d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) -{ - SUBLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) -{ - SUBWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) -{ - SUBBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) -{ - CMPLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) -{ - CMPLir(i, r); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) -{ - CMPWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) - -LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) -{ - CMPBim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) -{ - CMPBir(i, d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) -{ - CMPBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) - -LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) -{ - ADDR32 CMPLmr(offset, X86_NOREG, index, factor, d); -} -LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) - -LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) -{ - XORLrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) -{ - XORWrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) -{ - XORBrr(s, d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) -{ - SUBLim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) - -LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) -{ - CMPLim(s, d, X86_NOREG, X86_NOREG, 1); -} -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) -{ - XCHGLrr(r2, r1); -} -LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) - -LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) -{ - XCHGBrr(r2, r1); -} -LENDFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) - -LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) -{ - PUSHF(); -} -LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) - -LOWFUNC(WRITE,READ,0,raw_popfl,(void)) -{ - POPF(); -} -LENDFUNC(WRITE,READ,0,raw_popfl,(void)) - -/* Generate floating-point instructions */ -static inline void x86_fadd_m(MEMR s) -{ - FADDDm(s,X86_NOREG,X86_NOREG,1); -} - -#else - -const bool optimize_accum = true; -const bool optimize_imm8 = true; -const bool optimize_shift_once = true; - -/************************************************************************* - * Actual encoding of the instructions on the target CPU * - *************************************************************************/ - -static __inline__ int isaccum(int r) -{ - return (r == EAX_INDEX); -} - -static __inline__ int isbyte(uae_s32 x) -{ - return (x>=-128 && x<=127); -} - -static __inline__ int isword(uae_s32 x) -{ - return (x>=-32768 && x<=32767); -} - -LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) -{ - emit_byte(0x50+r); -} -LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) - -LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) -{ - emit_byte(0x58+r); -} -LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) - -LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) -{ - emit_byte(0x8f); - emit_byte(0x05); - emit_long(d); -} -LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) - -LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xe0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xa3); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xf8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xbb); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) - - -LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xf0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xb3); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xe8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xab); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) -{ - emit_byte(0x66); - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe8+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x2d); - else { - emit_byte(0x81); - emit_byte(0xe8+d); - } - emit_word(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) - - -LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) -{ - emit_byte(0x8b); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) -{ - emit_byte(0xc7); - emit_byte(0x05); - emit_long(d); - emit_long(s); -} -LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0xc7); - emit_byte(0x05); - emit_long(d); - emit_word(s); -} -LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) -{ - emit_byte(0xc6); - emit_byte(0x05); - emit_long(d); - emit_byte(s); -} -LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0x05); - emit_long(d); - } - else { - emit_byte(0xc0); - emit_byte(0x05); - emit_long(d); - emit_byte(i); - } -} -LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xc0+r); - } - else { - emit_byte(0xc0); - emit_byte(0xc0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xc0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xc0+r); - } - else { - emit_byte(0xc1); - emit_byte(0xc0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xc0+d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xc0+d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xc0+d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xe0+d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xe0+d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xe0+d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xc8+r); - } - else { - emit_byte(0xc0); - emit_byte(0xc8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xc8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) - -// gb-- used for making an fpcr value in compemu_fpp.cpp -LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) -{ - emit_byte(0x0b); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) - -LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xc8+r); - } - else { - emit_byte(0xc1); - emit_byte(0xc8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xc8+d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xc8+d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xc8+d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xe8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xe8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xe8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xf8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xf8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xf8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xe0+r); - } - else { - emit_byte(0xc1); - emit_byte(0xe0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xe0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xe0+r); - } - else { - emit_byte(0xc0); - emit_byte(0xe0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xe8+r); - } - else { - emit_byte(0xc1); - emit_byte(0xe8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xe8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xe8+r); - } - else { - emit_byte(0xc0); - emit_byte(0xe8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xf8+r); - } - else { - emit_byte(0xc1); - emit_byte(0xf8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xf8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xf8+r); - } - else { - emit_byte(0xc0); - emit_byte(0xf8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) -{ - emit_byte(0x9e); -} -LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) - -LOWFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) -{ - emit_byte(0x0f); - emit_byte(0xa2); -} -LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) - -LOWFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) -{ - emit_byte(0x9f); -} -LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) - -LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) -{ - emit_byte(0x0f); - emit_byte(0x90+cc); - emit_byte(0xc0+d); -} -LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) - -LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) -{ - emit_byte(0x0f); - emit_byte(0x90+cc); - emit_byte(0x05); - emit_long(d); -} -LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_b_rr,(RW1 d, R1 s, IMM cc)) -{ - /* replacement using branch and mov */ - int uncc=(cc^1); - emit_byte(0x70+uncc); - emit_byte(3); /* skip next 2 bytes if not cc=true */ - emit_byte(0x88); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(READ,NONE,3,raw_cmov_b_rr,(RW1 d, R1 s, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_w_rr,(RW2 d, R2 s, IMM cc)) -{ - if (have_cmov) { - emit_byte(0x66); - emit_byte(0x0f); - emit_byte(0x40+cc); - emit_byte(0xc0+8*d+s); - } - else { /* replacement using branch and mov */ - int uncc=(cc^1); - emit_byte(0x70+uncc); - emit_byte(3); /* skip next 3 bytes if not cc=true */ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0xc0+8*s+d); - } -} -LENDFUNC(READ,NONE,3,raw_cmov_w_rr,(RW2 d, R2 s, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) -{ - if (have_cmov) { - emit_byte(0x0f); - emit_byte(0x40+cc); - emit_byte(0xc0+8*d+s); - } - else { /* replacement using branch and mov */ - int uncc=(cc^1); - emit_byte(0x70+uncc); - emit_byte(2); /* skip next 2 bytes if not cc=true */ - emit_byte(0x89); - emit_byte(0xc0+8*s+d); - } -} -LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) - -LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) -{ - emit_byte(0x0f); - emit_byte(0xbc); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) -{ - emit_byte(0x0f); - emit_byte(0xbf); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) -{ - emit_byte(0x0f); - emit_byte(0xbe); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) -{ - emit_byte(0x0f); - emit_byte(0xb7); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) - -LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) -{ - emit_byte(0x0f); - emit_byte(0xb6); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) -{ - emit_byte(0x0f); - emit_byte(0xaf); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) -{ - if (d!=MUL_NREG1 || s!=MUL_NREG2) - abort(); - emit_byte(0xf7); - emit_byte(0xea); -} -LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) - -LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) -{ - if (d!=MUL_NREG1 || s!=MUL_NREG2) { - printf("Bad register in MUL: d=%d, s=%d\n",d,s); - abort(); - } - emit_byte(0xf7); - emit_byte(0xe2); -} -LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) - -LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) -{ - abort(); /* %^$&%^$%#^ x86! */ - emit_byte(0x0f); - emit_byte(0xaf); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) -{ - emit_byte(0x88); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) - -LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) -{ - int isebp=(baser==5)?0x40:0; - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - - emit_byte(0x8b); - emit_byte(0x04+8*d+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x04+8*d+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x8a); - emit_byte(0x04+8*d+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - - isebp=(baser==5)?0x40:0; - - emit_byte(0x89); - emit_byte(0x04+8*s+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) - -LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x04+8*s+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) - -LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x88); - emit_byte(0x04+8*s+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x89); - emit_byte(0x84+8*s); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x84+8*s); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x88); - emit_byte(0x84+8*s); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) - -LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x8b); - emit_byte(0x84+8*d); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x84+8*d); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x8a); - emit_byte(0x84+8*d); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) -{ - int fi; - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: - fprintf(stderr,"Bad factor %d in mov_l_rm_indexed!\n",factor); - abort(); - } - emit_byte(0x8b); - emit_byte(0x04+8*d); - emit_byte(0x05+8*index+64*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) -{ - int fi; - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: - fprintf(stderr,"Bad factor %d in mov_l_rm_indexed!\n",factor); - abort(); - } - if (have_cmov) { - emit_byte(0x0f); - emit_byte(0x40+cond); - emit_byte(0x04+8*d); - emit_byte(0x05+8*index+64*fi); - emit_long(base); - } - else { /* replacement using branch and mov */ - int uncc=(cond^1); - emit_byte(0x70+uncc); - emit_byte(7); /* skip next 7 bytes if not cc=true */ - emit_byte(0x8b); - emit_byte(0x04+8*d); - emit_byte(0x05+8*index+64*fi); - emit_long(base); - } -} -LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) - -LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) -{ - if (have_cmov) { - emit_byte(0x0f); - emit_byte(0x40+cond); - emit_byte(0x05+8*d); - emit_long(mem); - } - else { /* replacement using branch and mov */ - int uncc=(cond^1); - emit_byte(0x70+uncc); - emit_byte(6); /* skip next 6 bytes if not cc=true */ - emit_byte(0x8b); - emit_byte(0x05+8*d); - emit_long(mem); - } -} -LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) - -LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x8b); - emit_byte(0x40+8*d+s); - emit_byte(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x40+8*d+s); - emit_byte(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x8a); - emit_byte(0x40+8*d+s); - emit_byte(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) -{ - emit_byte(0x8b); - emit_byte(0x80+8*d+s); - emit_long(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) -{ - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x80+8*d+s); - emit_long(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) -{ - emit_byte(0x8a); - emit_byte(0x80+8*d+s); - emit_long(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0xc7); - emit_byte(0x40+d); - emit_byte(offset); - emit_long(i); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x66); - emit_byte(0xc7); - emit_byte(0x40+d); - emit_byte(offset); - emit_word(i); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0xc6); - emit_byte(0x40+d); - emit_byte(offset); - emit_byte(i); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x89); - emit_byte(0x40+8*s+d); - emit_byte(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x40+8*s+d); - emit_byte(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x88); - emit_byte(0x40+8*s+d); - emit_byte(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) - -LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) -{ - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x8d); - emit_byte(0x40+8*d+s); - emit_byte(offset); - } - else { - emit_byte(0x8d); - emit_byte(0x80+8*d+s); - emit_long(offset); - } -} -LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x8d); - emit_byte(0x44+8*d); - emit_byte(0x40*fi+8*index+s); - emit_byte(offset); - } - else { - emit_byte(0x8d); - emit_byte(0x84+8*d); - emit_byte(0x40*fi+8*index+s); - emit_long(offset); - } -} -LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) - -LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) -{ - int isebp=(s==5)?0x40:0; - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x8d); - emit_byte(0x04+8*d+isebp); - emit_byte(0x40*fi+8*index+s); - if (isebp) - emit_byte(0); -} -LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) -{ - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x89); - emit_byte(0x40+8*s+d); - emit_byte(offset); - } - else { - emit_byte(0x89); - emit_byte(0x80+8*s+d); - emit_long(offset); - } -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) -{ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x80+8*s+d); - emit_long(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) -{ - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x88); - emit_byte(0x40+8*s+d); - emit_byte(offset); - } - else { - emit_byte(0x88); - emit_byte(0x80+8*s+d); - emit_long(offset); - } -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) - -LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) -{ - emit_byte(0x0f); - emit_byte(0xc8+r); -} -LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) - -LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xc0+r); - emit_byte(0x08); -} -LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) - -LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) -{ - emit_byte(0x89); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) -{ - emit_byte(0x89); - emit_byte(0x05+8*s); - emit_long(d); -} -LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x05+8*s); - emit_long(d); -} -LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) - -LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) -{ - emit_byte(0x88); - emit_byte(0x05+8*(s&0xf)); /* XXX this handles %ah case (defined as 0x10+4) and others */ - emit_long(d); -} -LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) - -LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) -{ - emit_byte(0x8a); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) -{ - emit_byte(0xb8+d); - emit_long(s); -} -LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0xb8+d); - emit_word(s); -} -LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) -{ - emit_byte(0xb0+d); - emit_byte(s); -} -LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) - -LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) -{ - emit_byte(0x81); - emit_byte(0x15); - emit_long(d); - emit_long(s); -} -LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) -{ - if (optimize_imm8 && isbyte(s)) { - emit_byte(0x83); - emit_byte(0x05); - emit_long(d); - emit_byte(s); - } - else { - emit_byte(0x81); - emit_byte(0x05); - emit_long(d); - emit_long(s); - } -} -LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0x81); - emit_byte(0x05); - emit_long(d); - emit_word(s); -} -LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) -{ - emit_byte(0x80); - emit_byte(0x05); - emit_long(d); - emit_byte(s); -} -LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0xa9); - else { - emit_byte(0xf7); - emit_byte(0xc0+d); - } - emit_long(i); -} -LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) -{ - emit_byte(0x85); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x85); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) -{ - emit_byte(0x84); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) -{ - emit_byte(0x81); - emit_byte(0xf0+d); - emit_long(i); -} -LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) -{ - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x25); - else { - emit_byte(0x81); - emit_byte(0xe0+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) -{ - emit_byte(0x66); - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x25); - else { - emit_byte(0x81); - emit_byte(0xe0+d); - } - emit_word(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) -{ - emit_byte(0x21); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x21); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) -{ - emit_byte(0x20); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) -{ - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xc8+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x0d); - else { - emit_byte(0x81); - emit_byte(0xc8+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) -{ - emit_byte(0x09); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x09); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) -{ - emit_byte(0x08); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) -{ - emit_byte(0x11); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x11); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) -{ - emit_byte(0x10); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) -{ - emit_byte(0x01); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x01); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) -{ - emit_byte(0x00); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) -{ - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe8+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x2d); - else { - emit_byte(0x81); - emit_byte(0xe8+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0x2c); - else { - emit_byte(0x80); - emit_byte(0xe8+d); - } - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) -{ - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xc0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x05); - else { - emit_byte(0x81); - emit_byte(0xc0+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) -{ - emit_byte(0x66); - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xc0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x05); - else { - emit_byte(0x81); - emit_byte(0xc0+d); - } - emit_word(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0x04); - else { - emit_byte(0x80); - emit_byte(0xc0+d); - } - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) - -LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) -{ - emit_byte(0x19); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) - -LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x19); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) - -LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) -{ - emit_byte(0x18); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) -{ - emit_byte(0x29); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x29); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) -{ - emit_byte(0x28); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) -{ - emit_byte(0x39); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) -{ - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xf8+r); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(r)) - emit_byte(0x3d); - else { - emit_byte(0x81); - emit_byte(0xf8+r); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x39); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) - -LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) -{ - emit_byte(0x80); - emit_byte(0x3d); - emit_long(d); - emit_byte(s); -} -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0x3c); - else { - emit_byte(0x80); - emit_byte(0xf8+d); - } - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) -{ - emit_byte(0x38); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) - -LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - emit_byte(0x39); - emit_byte(0x04+8*d); - emit_byte(5+8*index+0x40*fi); - emit_long(offset); -} -LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) - -LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) -{ - emit_byte(0x31); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x31); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) -{ - emit_byte(0x30); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) -{ - if (optimize_imm8 && isbyte(s)) { - emit_byte(0x83); - emit_byte(0x2d); - emit_long(d); - emit_byte(s); - } - else { - emit_byte(0x81); - emit_byte(0x2d); - emit_long(d); - emit_long(s); - } -} -LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) - -LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) -{ - if (optimize_imm8 && isbyte(s)) { - emit_byte(0x83); - emit_byte(0x3d); - emit_long(d); - emit_byte(s); - } - else { - emit_byte(0x81); - emit_byte(0x3d); - emit_long(d); - emit_long(s); - } -} -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) -{ - emit_byte(0x87); - emit_byte(0xc0+8*r1+r2); -} -LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) - -LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) -{ - emit_byte(0x86); - emit_byte(0xc0+8*(r1&0xf)+(r2&0xf)); /* XXX this handles upper-halves registers (e.g. %ah defined as 0x10+4) */ -} -LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) - -/************************************************************************* - * FIXME: mem access modes probably wrong * - *************************************************************************/ - -LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) -{ - emit_byte(0x9c); -} -LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) - -LOWFUNC(WRITE,READ,0,raw_popfl,(void)) -{ - emit_byte(0x9d); -} -LENDFUNC(WRITE,READ,0,raw_popfl,(void)) - -/* Generate floating-point instructions */ -static inline void x86_fadd_m(MEMR s) -{ - emit_byte(0xdc); - emit_byte(0x05); - emit_long(s); -} - -#endif - -/************************************************************************* - * Unoptimizable stuff --- jump * - *************************************************************************/ - -static __inline__ void raw_call_r(R4 r) -{ -#if USE_NEW_RTASM - CALLsr(r); -#else - emit_byte(0xff); - emit_byte(0xd0+r); -#endif -} - -static __inline__ void raw_call_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) -{ -#if USE_NEW_RTASM - CALLsm(base, X86_NOREG, r, m); -#else - int mu; - switch(m) { - case 1: mu=0; break; - case 2: mu=1; break; - case 4: mu=2; break; - case 8: mu=3; break; - default: abort(); - } - emit_byte(0xff); - emit_byte(0x14); - emit_byte(0x05+8*r+0x40*mu); - emit_long(base); -#endif -} - -static __inline__ void raw_jmp_r(R4 r) -{ -#if USE_NEW_RTASM - JMPsr(r); -#else - emit_byte(0xff); - emit_byte(0xe0+r); -#endif -} - -static __inline__ void raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) -{ -#if USE_NEW_RTASM - JMPsm(base, X86_NOREG, r, m); -#else - int mu; - switch(m) { - case 1: mu=0; break; - case 2: mu=1; break; - case 4: mu=2; break; - case 8: mu=3; break; - default: abort(); - } - emit_byte(0xff); - emit_byte(0x24); - emit_byte(0x05+8*r+0x40*mu); - emit_long(base); -#endif -} - -static __inline__ void raw_jmp_m(uae_u32 base) -{ - emit_byte(0xff); - emit_byte(0x25); - emit_long(base); -} - - -static __inline__ void raw_call(uae_u32 t) -{ -#if USE_NEW_RTASM - CALLm(t); -#else - emit_byte(0xe8); - emit_long(t-(uae_u32)target-4); -#endif -} - -static __inline__ void raw_jmp(uae_u32 t) -{ -#if USE_NEW_RTASM - JMPm(t); -#else - emit_byte(0xe9); - emit_long(t-(uae_u32)target-4); -#endif -} - -static __inline__ void raw_jl(uae_u32 t) -{ - emit_byte(0x0f); - emit_byte(0x8c); - emit_long(t-(uintptr)target-4); -} - -static __inline__ void raw_jz(uae_u32 t) -{ - emit_byte(0x0f); - emit_byte(0x84); - emit_long(t-(uintptr)target-4); -} - -static __inline__ void raw_jnz(uae_u32 t) -{ - emit_byte(0x0f); - emit_byte(0x85); - emit_long(t-(uintptr)target-4); -} - -static __inline__ void raw_jnz_l_oponly(void) -{ - emit_byte(0x0f); - emit_byte(0x85); -} - -static __inline__ void raw_jcc_l_oponly(int cc) -{ - emit_byte(0x0f); - emit_byte(0x80+cc); -} - -static __inline__ void raw_jnz_b_oponly(void) -{ - emit_byte(0x75); -} - -static __inline__ void raw_jz_b_oponly(void) -{ - emit_byte(0x74); -} - -static __inline__ void raw_jcc_b_oponly(int cc) -{ - emit_byte(0x70+cc); -} - -static __inline__ void raw_jmp_l_oponly(void) -{ - emit_byte(0xe9); -} - -static __inline__ void raw_jmp_b_oponly(void) -{ - emit_byte(0xeb); -} - -static __inline__ void raw_ret(void) -{ - emit_byte(0xc3); -} - -static __inline__ void raw_nop(void) -{ - emit_byte(0x90); -} - -static __inline__ void raw_emit_nop_filler(int nbytes) -{ - /* Source: GNU Binutils 2.12.90.0.15 */ - /* Various efficient no-op patterns for aligning code labels. - Note: Don't try to assemble the instructions in the comments. - 0L and 0w are not legal. */ - static const uae_u8 f32_1[] = - {0x90}; /* nop */ - static const uae_u8 f32_2[] = - {0x89,0xf6}; /* movl %esi,%esi */ - static const uae_u8 f32_3[] = - {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ - static const uae_u8 f32_4[] = - {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const uae_u8 f32_5[] = - {0x90, /* nop */ - 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const uae_u8 f32_6[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ - static const uae_u8 f32_7[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const uae_u8 f32_8[] = - {0x90, /* nop */ - 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const uae_u8 f32_9[] = - {0x89,0xf6, /* movl %esi,%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uae_u8 f32_10[] = - {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uae_u8 f32_11[] = - {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uae_u8 f32_12[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ - static const uae_u8 f32_13[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uae_u8 f32_14[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uae_u8 f32_15[] = - {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const uae_u8 f32_16[] = - {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const uae_u8 *const f32_patt[] = { - f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, - f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 - }; - static const uae_u8 prefixes[4] = { 0x66, 0x66, 0x66, 0x66 }; - -#if defined(__x86_64__) - /* The recommended way to pad 64bit code is to use NOPs preceded by - maximally four 0x66 prefixes. Balance the size of nops. */ - if (nbytes == 0) - return; - - int i; - int nnops = (nbytes + 3) / 4; - int len = nbytes / nnops; - int remains = nbytes - nnops * len; - - for (i = 0; i < remains; i++) { - emit_block(prefixes, len); - raw_nop(); - } - for (; i < nnops; i++) { - emit_block(prefixes, len - 1); - raw_nop(); - } -#else - int nloops = nbytes / 16; - while (nloops-- > 0) - emit_block(f32_16, sizeof(f32_16)); - - nbytes %= 16; - if (nbytes) - emit_block(f32_patt[nbytes - 1], nbytes); -#endif -} - - -/************************************************************************* - * Flag handling, to and fro UAE flag register * - *************************************************************************/ - -static __inline__ void raw_flags_evicted(int r) -{ - //live.state[FLAGTMP].status=CLEAN; - live.state[FLAGTMP].status=INMEM; - live.state[FLAGTMP].realreg=-1; - /* We just "evicted" FLAGTMP. */ - if (live.nat[r].nholds!=1) { - /* Huh? */ - abort(); - } - live.nat[r].nholds=0; -} - -#define FLAG_NREG1_FLAGREG 0 /* Set to -1 if any register will do */ -static __inline__ void raw_flags_to_reg_FLAGREG(int r) -{ - raw_lahf(0); /* Most flags in AH */ - //raw_setcc(r,0); /* V flag in AL */ - raw_setcc_m((uintptr)live.state[FLAGTMP].mem,0); - -#if 1 /* Let's avoid those nasty partial register stalls */ - //raw_mov_b_mr((uintptr)live.state[FLAGTMP].mem,r); - raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,AH_INDEX); - raw_flags_evicted(r); -#endif -} - -#define FLAG_NREG2_FLAGREG 0 /* Set to -1 if any register will do */ -static __inline__ void raw_reg_to_flags_FLAGREG(int r) -{ - raw_cmp_b_ri(r,-127); /* set V */ - raw_sahf(0); -} - -#define FLAG_NREG3_FLAGREG 0 /* Set to -1 if any register will do */ -static __inline__ void raw_flags_set_zero_FLAGREG(int s, int tmp) -{ - raw_mov_l_rr(tmp,s); - raw_lahf(s); /* flags into ah */ - raw_and_l_ri(s,0xffffbfff); - raw_and_l_ri(tmp,0x00004000); - raw_xor_l_ri(tmp,0x00004000); - raw_or_l(s,tmp); - raw_sahf(s); -} - -static __inline__ void raw_flags_init_FLAGREG(void) { } - -#define FLAG_NREG1_FLAGSTK -1 /* Set to -1 if any register will do */ -static __inline__ void raw_flags_to_reg_FLAGSTK(int r) -{ - raw_pushfl(); - raw_pop_l_r(r); - raw_mov_l_mr((uintptr)live.state[FLAGTMP].mem,r); - raw_flags_evicted(r); -} - -#define FLAG_NREG2_FLAGSTK -1 /* Set to -1 if any register will do */ -static __inline__ void raw_reg_to_flags_FLAGSTK(int r) -{ - raw_push_l_r(r); - raw_popfl(); -} - -#define FLAG_NREG3_FLAGSTK -1 /* Set to -1 if any register will do */ -static __inline__ void raw_flags_set_zero_FLAGSTK(int s, int tmp) -{ - raw_mov_l_rr(tmp,s); - raw_pushfl(); - raw_pop_l_r(s); - raw_and_l_ri(s,0xffffffbf); - raw_and_l_ri(tmp,0x00000040); - raw_xor_l_ri(tmp,0x00000040); - raw_or_l(s,tmp); - raw_push_l_r(s); - raw_popfl(); -} - -static __inline__ void raw_flags_init_FLAGSTK(void) { } - -#if defined(__x86_64__) -/* Try to use the LAHF/SETO method on x86_64 since it is faster. - This can't be the default because some older CPUs don't support - LAHF/SAHF in long mode. */ -static int FLAG_NREG1_FLAGGEN = 0; -static __inline__ void raw_flags_to_reg_FLAGGEN(int r) -{ - if (have_lahf_lm) { - // NOTE: the interpreter uses the normal EFLAGS layout - // pushf/popf CF(0) ZF( 6) SF( 7) OF(11) - // sahf/lahf CF(8) ZF(14) SF(15) OF( 0) - assert(r == 0); - raw_setcc(r,0); /* V flag in AL */ - raw_lea_l_r_scaled(0,0,8); /* move it to its EFLAGS location */ - raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,0); - raw_lahf(0); /* most flags in AH */ - raw_mov_b_mr((uintptr)live.state[FLAGTMP].mem,AH_INDEX); - raw_flags_evicted(r); - } - else - raw_flags_to_reg_FLAGSTK(r); -} - -static int FLAG_NREG2_FLAGGEN = 0; -static __inline__ void raw_reg_to_flags_FLAGGEN(int r) -{ - if (have_lahf_lm) { - raw_xchg_b_rr(0,AH_INDEX); - raw_cmp_b_ri(r,-120); /* set V */ - raw_sahf(0); - } - else - raw_reg_to_flags_FLAGSTK(r); -} - -static int FLAG_NREG3_FLAGGEN = 0; -static __inline__ void raw_flags_set_zero_FLAGGEN(int s, int tmp) -{ - if (have_lahf_lm) - raw_flags_set_zero_FLAGREG(s, tmp); - else - raw_flags_set_zero_FLAGSTK(s, tmp); -} - -static __inline__ void raw_flags_init_FLAGGEN(void) -{ - if (have_lahf_lm) { - FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGREG; - FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGREG; - FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGREG; - } - else { - FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGSTK; - FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGSTK; - FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGSTK; - } -} -#endif - -#ifdef SAHF_SETO_PROFITABLE -#define FLAG_SUFFIX FLAGREG -#elif defined __x86_64__ -#define FLAG_SUFFIX FLAGGEN -#else -#define FLAG_SUFFIX FLAGSTK -#endif - -#define FLAG_GLUE_2(x, y) x ## _ ## y -#define FLAG_GLUE_1(x, y) FLAG_GLUE_2(x, y) -#define FLAG_GLUE(x) FLAG_GLUE_1(x, FLAG_SUFFIX) - -#define raw_flags_init FLAG_GLUE(raw_flags_init) -#define FLAG_NREG1 FLAG_GLUE(FLAG_NREG1) -#define raw_flags_to_reg FLAG_GLUE(raw_flags_to_reg) -#define FLAG_NREG2 FLAG_GLUE(FLAG_NREG2) -#define raw_reg_to_flags FLAG_GLUE(raw_reg_to_flags) -#define FLAG_NREG3 FLAG_GLUE(FLAG_NREG3) -#define raw_flags_set_zero FLAG_GLUE(raw_flags_set_zero) - -/* Apparently, there are enough instructions between flag store and - flag reload to avoid the partial memory stall */ -static __inline__ void raw_load_flagreg(uae_u32 target, uae_u32 r) -{ -#if 1 - raw_mov_l_rm(target,(uintptr)live.state[r].mem); -#else - raw_mov_b_rm(target,(uintptr)live.state[r].mem); - raw_mov_b_rm(target+4,((uintptr)live.state[r].mem)+1); -#endif -} - -/* FLAGX is byte sized, and we *do* write it at that size */ -static __inline__ void raw_load_flagx(uae_u32 target, uae_u32 r) -{ - if (live.nat[target].canbyte) - raw_mov_b_rm(target,(uintptr)live.state[r].mem); - else if (live.nat[target].canword) - raw_mov_w_rm(target,(uintptr)live.state[r].mem); - else - raw_mov_l_rm(target,(uintptr)live.state[r].mem); -} - -static __inline__ void raw_dec_sp(int off) -{ - if (off) raw_sub_l_ri(ESP_INDEX,off); -} - -static __inline__ void raw_inc_sp(int off) -{ - if (off) raw_add_l_ri(ESP_INDEX,off); -} - -/************************************************************************* - * Handling mistaken direct memory access * - *************************************************************************/ - -// gb-- I don't need that part for JIT Basilisk II -#if defined(NATMEM_OFFSET) && 0 -#include -#include - -#define SIG_READ 1 -#define SIG_WRITE 2 - -static int in_handler=0; -static uae_u8 veccode[256]; - -static void vec(int x, struct sigcontext sc) -{ - uae_u8* i=(uae_u8*)sc.eip; - uae_u32 addr=sc.cr2; - int r=-1; - int size=4; - int dir=-1; - int len=0; - int j; - - write_log("fault address is %08x at %08x\n",sc.cr2,sc.eip); - if (!canbang) - write_log("Not happy! Canbang is 0 in SIGSEGV handler!\n"); - if (in_handler) - write_log("Argh --- Am already in a handler. Shouldn't happen!\n"); - - if (canbang && i>=compiled_code && i<=current_compile_p) { - if (*i==0x66) { - i++; - size=2; - len++; - } - - switch(i[0]) { - case 0x8a: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - size=1; - len+=6; - break; - } - break; - case 0x88: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - size=1; - len+=6; - break; - } - break; - case 0x8b: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=6; - break; - } - if ((i[1]&0xc0)==0x40) { - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=3; - break; - } - break; - case 0x89: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=6; - break; - } - if ((i[1]&0xc0)==0x40) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=3; - break; - } - break; - } - } - - if (r!=-1) { - void* pr=NULL; - write_log("register was %d, direction was %d, size was %d\n",r,dir,size); - - switch(r) { - case 0: pr=&(sc.eax); break; - case 1: pr=&(sc.ecx); break; - case 2: pr=&(sc.edx); break; - case 3: pr=&(sc.ebx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(sc.eax))+1); break; - case 5: pr=(size>1)? - (void*)(&(sc.ebp)): - (void*)(((uae_u8*)&(sc.ecx))+1); break; - case 6: pr=(size>1)? - (void*)(&(sc.esi)): - (void*)(((uae_u8*)&(sc.edx))+1); break; - case 7: pr=(size>1)? - (void*)(&(sc.edi)): - (void*)(((uae_u8*)&(sc.ebx))+1); break; - default: abort(); - } - if (pr) { - blockinfo* bi; - - if (currprefs.comp_oldsegv) { - addr-=NATMEM_OFFSET; - - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log("Suspicious address in %x SEGV handler.\n",addr); - } - if (dir==SIG_READ) { - switch(size) { - case 1: *((uae_u8*)pr)=get_byte(addr); break; - case 2: *((uae_u16*)pr)=get_word(addr); break; - case 4: *((uae_u32*)pr)=get_long(addr); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte(addr,*((uae_u8*)pr)); break; - case 2: put_word(addr,*((uae_u16*)pr)); break; - case 4: put_long(addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - write_log("Handled one access!\n"); - fflush(stdout); - segvcount++; - sc.eip+=len; - } - else { - void* tmp=target; - int i; - uae_u8 vecbuf[5]; - - addr-=NATMEM_OFFSET; - - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log("Suspicious address in %x SEGV handler.\n",addr); - } - - target=(uae_u8*)sc.eip; - for (i=0;i<5;i++) - vecbuf[i]=target[i]; - emit_byte(0xe9); - emit_long((uintptr)veccode-(uintptr)target-4); - write_log("Create jump to %p\n",veccode); - - write_log("Handled one access!\n"); - fflush(stdout); - segvcount++; - - target=veccode; - - if (dir==SIG_READ) { - switch(size) { - case 1: raw_mov_b_ri(r,get_byte(addr)); break; - case 2: raw_mov_w_ri(r,get_byte(addr)); break; - case 4: raw_mov_l_ri(r,get_byte(addr)); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte(addr,*((uae_u8*)pr)); break; - case 2: put_word(addr,*((uae_u16*)pr)); break; - case 4: put_long(addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - for (i=0;i<5;i++) - raw_mov_b_mi(sc.eip+i,vecbuf[i]); - raw_mov_l_mi((uintptr)&in_handler,0); - emit_byte(0xe9); - emit_long(sc.eip+len-(uintptr)target-4); - in_handler=1; - target=tmp; - } - bi=active; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log("deleted trigger (%p<%p<%p) %p\n", - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - /* Not found in the active list. Might be a rom routine that - is in the dormant list */ - bi=dormant; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log("deleted trigger (%p<%p<%p) %p\n", - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - write_log("Huh? Could not find trigger!\n"); - return; - } - } - write_log("Can't handle access!\n"); - for (j=0;j<10;j++) { - write_log("instruction byte %2d is %02x\n",j,i[j]); - } - write_log("Please send the above info (starting at \"fault address\") to\n" - "bmeyer@csse.monash.edu.au\n" - "This shouldn't happen ;-)\n"); - fflush(stdout); - signal(SIGSEGV,SIG_DFL); /* returning here will cause a "real" SEGV */ -} -#endif - - -/************************************************************************* - * Checking for CPU features * - *************************************************************************/ - -struct cpuinfo_x86 { - uae_u8 x86; // CPU family - uae_u8 x86_vendor; // CPU vendor - uae_u8 x86_processor; // CPU canonical processor type - uae_u8 x86_brand_id; // CPU BrandID if supported, yield 0 otherwise - uae_u32 x86_hwcap; - uae_u8 x86_model; - uae_u8 x86_mask; - int cpuid_level; // Maximum supported CPUID level, -1=no CPUID - char x86_vendor_id[16]; -}; -struct cpuinfo_x86 cpuinfo; - -enum { - X86_VENDOR_INTEL = 0, - X86_VENDOR_CYRIX = 1, - X86_VENDOR_AMD = 2, - X86_VENDOR_UMC = 3, - X86_VENDOR_NEXGEN = 4, - X86_VENDOR_CENTAUR = 5, - X86_VENDOR_RISE = 6, - X86_VENDOR_TRANSMETA = 7, - X86_VENDOR_NSC = 8, - X86_VENDOR_UNKNOWN = 0xff -}; - -enum { - X86_PROCESSOR_I386, /* 80386 */ - X86_PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */ - X86_PROCESSOR_PENTIUM, - X86_PROCESSOR_PENTIUMPRO, - X86_PROCESSOR_K6, - X86_PROCESSOR_ATHLON, - X86_PROCESSOR_PENTIUM4, - X86_PROCESSOR_X86_64, - X86_PROCESSOR_max -}; - -static const char * x86_processor_string_table[X86_PROCESSOR_max] = { - "80386", - "80486", - "Pentium", - "PentiumPro", - "K6", - "Athlon", - "Pentium4", - "x86-64" -}; - -static struct ptt { - const int align_loop; - const int align_loop_max_skip; - const int align_jump; - const int align_jump_max_skip; - const int align_func; -} -x86_alignments[X86_PROCESSOR_max] = { - { 4, 3, 4, 3, 4 }, - { 16, 15, 16, 15, 16 }, - { 16, 7, 16, 7, 16 }, - { 16, 15, 16, 7, 16 }, - { 32, 7, 32, 7, 32 }, - { 16, 7, 16, 7, 16 }, - { 0, 0, 0, 0, 0 }, - { 16, 7, 16, 7, 16 } -}; - -static void -x86_get_cpu_vendor(struct cpuinfo_x86 *c) -{ - char *v = c->x86_vendor_id; - - if (!strcmp(v, "GenuineIntel")) - c->x86_vendor = X86_VENDOR_INTEL; - else if (!strcmp(v, "AuthenticAMD")) - c->x86_vendor = X86_VENDOR_AMD; - else if (!strcmp(v, "CyrixInstead")) - c->x86_vendor = X86_VENDOR_CYRIX; - else if (!strcmp(v, "Geode by NSC")) - c->x86_vendor = X86_VENDOR_NSC; - else if (!strcmp(v, "UMC UMC UMC ")) - c->x86_vendor = X86_VENDOR_UMC; - else if (!strcmp(v, "CentaurHauls")) - c->x86_vendor = X86_VENDOR_CENTAUR; - else if (!strcmp(v, "NexGenDriven")) - c->x86_vendor = X86_VENDOR_NEXGEN; - else if (!strcmp(v, "RiseRiseRise")) - c->x86_vendor = X86_VENDOR_RISE; - else if (!strcmp(v, "GenuineTMx86") || - !strcmp(v, "TransmetaCPU")) - c->x86_vendor = X86_VENDOR_TRANSMETA; - else - c->x86_vendor = X86_VENDOR_UNKNOWN; -} - -static void -cpuid(uae_u32 op, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) -{ - const int CPUID_SPACE = 4096; - uae_u8* cpuid_space = (uae_u8 *)vm_acquire(CPUID_SPACE); - if (cpuid_space == VM_MAP_FAILED) - abort(); - vm_protect(cpuid_space, CPUID_SPACE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE); - - static uae_u32 s_op, s_eax, s_ebx, s_ecx, s_edx; - uae_u8* tmp=get_target(); - - s_op = op; - set_target(cpuid_space); - raw_push_l_r(0); /* eax */ - raw_push_l_r(1); /* ecx */ - raw_push_l_r(2); /* edx */ - raw_push_l_r(3); /* ebx */ - raw_mov_l_rm(0,(uintptr)&s_op); - raw_cpuid(0); - raw_mov_l_mr((uintptr)&s_eax,0); - raw_mov_l_mr((uintptr)&s_ebx,3); - raw_mov_l_mr((uintptr)&s_ecx,1); - raw_mov_l_mr((uintptr)&s_edx,2); - raw_pop_l_r(3); - raw_pop_l_r(2); - raw_pop_l_r(1); - raw_pop_l_r(0); - raw_ret(); - set_target(tmp); - - ((cpuop_func*)cpuid_space)(0); - if (eax != NULL) *eax = s_eax; - if (ebx != NULL) *ebx = s_ebx; - if (ecx != NULL) *ecx = s_ecx; - if (edx != NULL) *edx = s_edx; - - vm_release(cpuid_space, CPUID_SPACE); -} - -static void -raw_init_cpu(void) -{ - struct cpuinfo_x86 *c = &cpuinfo; - - /* Defaults */ - c->x86_processor = X86_PROCESSOR_max; - c->x86_vendor = X86_VENDOR_UNKNOWN; - c->cpuid_level = -1; /* CPUID not detected */ - c->x86_model = c->x86_mask = 0; /* So far unknown... */ - c->x86_vendor_id[0] = '\0'; /* Unset */ - c->x86_hwcap = 0; - - /* Get vendor name */ - c->x86_vendor_id[12] = '\0'; - cpuid(0x00000000, - (uae_u32 *)&c->cpuid_level, - (uae_u32 *)&c->x86_vendor_id[0], - (uae_u32 *)&c->x86_vendor_id[8], - (uae_u32 *)&c->x86_vendor_id[4]); - x86_get_cpu_vendor(c); - - /* Intel-defined flags: level 0x00000001 */ - c->x86_brand_id = 0; - if ( c->cpuid_level >= 0x00000001 ) { - uae_u32 tfms, brand_id; - cpuid(0x00000001, &tfms, &brand_id, NULL, &c->x86_hwcap); - c->x86 = (tfms >> 8) & 15; - if (c->x86 == 0xf) - c->x86 += (tfms >> 20) & 0xff; /* extended family */ - c->x86_model = (tfms >> 4) & 15; - if (c->x86_model == 0xf) - c->x86_model |= (tfms >> 12) & 0xf0; /* extended model */ - c->x86_brand_id = brand_id & 0xff; - c->x86_mask = tfms & 15; - } else { - /* Have CPUID level 0 only - unheard of */ - c->x86 = 4; - } - - /* AMD-defined flags: level 0x80000001 */ - uae_u32 xlvl; - cpuid(0x80000000, &xlvl, NULL, NULL, NULL); - if ( (xlvl & 0xffff0000) == 0x80000000 ) { - if ( xlvl >= 0x80000001 ) { - uae_u32 features, extra_features; - cpuid(0x80000001, NULL, NULL, &extra_features, &features); - if (features & (1 << 29)) { - /* Assume x86-64 if long mode is supported */ - c->x86_processor = X86_PROCESSOR_X86_64; - } - if (extra_features & (1 << 0)) - have_lahf_lm = true; - } - } - - /* Canonicalize processor ID */ - switch (c->x86) { - case 3: - c->x86_processor = X86_PROCESSOR_I386; - break; - case 4: - c->x86_processor = X86_PROCESSOR_I486; - break; - case 5: - if (c->x86_vendor == X86_VENDOR_AMD) - c->x86_processor = X86_PROCESSOR_K6; - else - c->x86_processor = X86_PROCESSOR_PENTIUM; - break; - case 6: - if (c->x86_vendor == X86_VENDOR_AMD) - c->x86_processor = X86_PROCESSOR_ATHLON; - else - c->x86_processor = X86_PROCESSOR_PENTIUMPRO; - break; - case 15: - if (c->x86_processor == X86_PROCESSOR_max) { - switch (c->x86_vendor) { - case X86_VENDOR_INTEL: - c->x86_processor = X86_PROCESSOR_PENTIUM4; - break; - case X86_VENDOR_AMD: - /* Assume a 32-bit Athlon processor if not in long mode */ - c->x86_processor = X86_PROCESSOR_ATHLON; - break; - } - } - break; - } - if (c->x86_processor == X86_PROCESSOR_max) { - c->x86_processor = X86_PROCESSOR_I386; - fprintf(stderr, "Error: unknown processor type, assuming i386\n"); - fprintf(stderr, " Family : %d\n", c->x86); - fprintf(stderr, " Model : %d\n", c->x86_model); - fprintf(stderr, " Mask : %d\n", c->x86_mask); - fprintf(stderr, " Vendor : %s [%d]\n", c->x86_vendor_id, c->x86_vendor); - if (c->x86_brand_id) - fprintf(stderr, " BrandID : %02x\n", c->x86_brand_id); - } - - /* Have CMOV support? */ - have_cmov = (c->x86_hwcap & (1 << 15)) != 0; -#if defined(__x86_64__) - if (!have_cmov) { - write_log("x86-64 implementations are bound to have CMOV!\n"); - abort(); - } -#endif - - /* Can the host CPU suffer from partial register stalls? */ - have_rat_stall = (c->x86_vendor == X86_VENDOR_INTEL); -#if 1 - /* It appears that partial register writes are a bad idea even on - AMD K7 cores, even though they are not supposed to have the - dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */ - if (c->x86_processor == X86_PROCESSOR_ATHLON) - have_rat_stall = true; -#endif - - /* Alignments */ - if (tune_alignment) { - align_loops = x86_alignments[c->x86_processor].align_loop; - align_jumps = x86_alignments[c->x86_processor].align_jump; - } - - write_log("Max CPUID level=%d Processor is %s [%s]\n", - c->cpuid_level, c->x86_vendor_id, - x86_processor_string_table[c->x86_processor]); - - raw_flags_init(); -} - -static bool target_check_bsf(void) -{ - bool mismatch = false; - for (int g_ZF = 0; g_ZF <= 1; g_ZF++) { - for (int g_CF = 0; g_CF <= 1; g_CF++) { - for (int g_OF = 0; g_OF <= 1; g_OF++) { - for (int g_SF = 0; g_SF <= 1; g_SF++) { - for (int value = -1; value <= 1; value++) { - unsigned long flags = (g_SF << 7) | (g_OF << 11) | (g_ZF << 6) | g_CF; - unsigned long tmp = value; -#ifdef _MSC_VER - __writeeflags(flags); - _BitScanForward(&tmp, value); - flags = __readeflags(); -#else - __asm__ __volatile__ ("push %0; popf; bsf %1,%1; pushf; pop %0" - : "+r" (flags), "+r" (tmp) : : "cc"); -#endif - int OF = (flags >> 11) & 1; - int SF = (flags >> 7) & 1; - int ZF = (flags >> 6) & 1; - int CF = flags & 1; - tmp = (value == 0); - if (ZF != tmp || SF != g_SF || OF != g_OF || CF != g_CF) - mismatch = true; - } - }}}} - if (mismatch) - write_log("Target CPU defines all flags on BSF instruction\n"); - return !mismatch; -} - - -/************************************************************************* - * FPU stuff * - *************************************************************************/ - - -static __inline__ void raw_fp_init(void) -{ - int i; - - for (i=0;i1) { - emit_byte(0x9b); - emit_byte(0xdb); - emit_byte(0xe3); - live.tos=-1; - } -#endif - while (live.tos>=1) { - emit_byte(0xde); - emit_byte(0xd9); - live.tos-=2; - } - while (live.tos>=0) { - emit_byte(0xdd); - emit_byte(0xd8); - live.tos--; - } - raw_fp_init(); -} - -static __inline__ void make_tos(int r) -{ - int p,q; - - if (live.spos[r]<0) { /* Register not yet on stack */ - emit_byte(0xd9); - emit_byte(0xe8); /* Push '1' on the stack, just to grow it */ - live.tos++; - live.spos[r]=live.tos; - live.onstack[live.tos]=r; - return; - } - /* Register is on stack */ - if (live.tos==live.spos[r]) - return; - p=live.spos[r]; - q=live.onstack[live.tos]; - - emit_byte(0xd9); - emit_byte(0xc8+live.tos-live.spos[r]); /* exchange it with top of stack */ - live.onstack[live.tos]=r; - live.spos[r]=live.tos; - live.onstack[p]=q; - live.spos[q]=p; -} - -static __inline__ void make_tos2(int r, int r2) -{ - int q; - - make_tos(r2); /* Put the reg that's supposed to end up in position2 - on top */ - - if (live.spos[r]<0) { /* Register not yet on stack */ - make_tos(r); /* This will extend the stack */ - return; - } - /* Register is on stack */ - emit_byte(0xd9); - emit_byte(0xc9); /* Move r2 into position 2 */ - - q=live.onstack[live.tos-1]; - live.onstack[live.tos]=q; - live.spos[q]=live.tos; - live.onstack[live.tos-1]=r2; - live.spos[r2]=live.tos-1; - - make_tos(r); /* And r into 1 */ -} - -static __inline__ int stackpos(int r) -{ - if (live.spos[r]<0) - abort(); - if (live.tos=0) { - /* source is on top of stack, and we already have the dest */ - int dd=stackpos(d); - emit_byte(0xdd); - emit_byte(0xd0+dd); - } - else { - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source on tos */ - tos_make(d); /* store to destination, pop if necessary */ - } -} -LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) - -LOWFUNC(NONE,READ,4,raw_fldcw_m_indexed,(R4 index, IMM base)) -{ - emit_byte(0xd9); - emit_byte(0xa8+index); - emit_long(base); -} -LENDFUNC(NONE,READ,4,raw_fldcw_m_indexed,(R4 index, IMM base)) - - -LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) -{ - int ds; - - if (d!=s) { - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xfa); /* take square root */ - tos_make(d); /* store to destination */ - } - else { - make_tos(d); - emit_byte(0xd9); - emit_byte(0xfa); /* take square root */ - } -} -LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) -{ - int ds; - - if (d!=s) { - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xe1); /* take fabs */ - tos_make(d); /* store to destination */ - } - else { - make_tos(d); - emit_byte(0xd9); - emit_byte(0xe1); /* take fabs */ - } -} -LENDFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) -{ - int ds; - - if (d!=s) { - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xfc); /* take frndint */ - tos_make(d); /* store to destination */ - } - else { - make_tos(d); - emit_byte(0xd9); - emit_byte(0xfc); /* take frndint */ - } -} -LENDFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) -{ - int ds; - - if (d!=s) { - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xff); /* take cos */ - tos_make(d); /* store to destination */ - } - else { - make_tos(d); - emit_byte(0xd9); - emit_byte(0xff); /* take cos */ - } -} -LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) -{ - int ds; - - if (d!=s) { - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xfe); /* take sin */ - tos_make(d); /* store to destination */ - } - else { - make_tos(d); - emit_byte(0xd9); - emit_byte(0xfe); /* take sin */ - } -} -LENDFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) - -static const double one=1; -LOWFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) -{ - int ds; - - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - - emit_byte(0xd9); - emit_byte(0xc0); /* duplicate top of stack. Now up to 8 high */ - emit_byte(0xd9); - emit_byte(0xfc); /* rndint */ - emit_byte(0xd9); - emit_byte(0xc9); /* swap top two elements */ - emit_byte(0xd8); - emit_byte(0xe1); /* subtract rounded from original */ - emit_byte(0xd9); - emit_byte(0xf0); /* f2xm1 */ - x86_fadd_m((uintptr)&one); /* Add '1' without using extra stack space */ - emit_byte(0xd9); - emit_byte(0xfd); /* and scale it */ - emit_byte(0xdd); - emit_byte(0xd9); /* take he rounded value off */ - tos_make(d); /* store to destination */ -} -LENDFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) -{ - int ds; - - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xea); /* fldl2e */ - emit_byte(0xde); - emit_byte(0xc9); /* fmulp --- multiply source by log2(e) */ - - emit_byte(0xd9); - emit_byte(0xc0); /* duplicate top of stack. Now up to 8 high */ - emit_byte(0xd9); - emit_byte(0xfc); /* rndint */ - emit_byte(0xd9); - emit_byte(0xc9); /* swap top two elements */ - emit_byte(0xd8); - emit_byte(0xe1); /* subtract rounded from original */ - emit_byte(0xd9); - emit_byte(0xf0); /* f2xm1 */ - x86_fadd_m((uintptr)&one); /* Add '1' without using extra stack space */ - emit_byte(0xd9); - emit_byte(0xfd); /* and scale it */ - emit_byte(0xdd); - emit_byte(0xd9); /* take he rounded value off */ - tos_make(d); /* store to destination */ -} -LENDFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) -{ - int ds; - - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xe8); /* push '1' */ - emit_byte(0xd9); - emit_byte(0xc9); /* swap top two */ - emit_byte(0xd9); - emit_byte(0xf1); /* take 1*log2(x) */ - tos_make(d); /* store to destination */ -} -LENDFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) - - -LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) -{ - int ds; - - if (d!=s) { - usereg(s); - ds=stackpos(s); - emit_byte(0xd9); - emit_byte(0xc0+ds); /* duplicate source */ - emit_byte(0xd9); - emit_byte(0xe0); /* take fchs */ - tos_make(d); /* store to destination */ - } - else { - make_tos(d); - emit_byte(0xd9); - emit_byte(0xe0); /* take fchs */ - } -} -LENDFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - if (live.spos[s]==live.tos) { - /* Source is on top of stack */ - ds=stackpos(d); - emit_byte(0xdc); - emit_byte(0xc0+ds); /* add source to dest*/ - } - else { - make_tos(d); - ds=stackpos(s); - - emit_byte(0xd8); - emit_byte(0xc0+ds); /* add source to dest*/ - } -} -LENDFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - if (live.spos[s]==live.tos) { - /* Source is on top of stack */ - ds=stackpos(d); - emit_byte(0xdc); - emit_byte(0xe8+ds); /* sub source from dest*/ - } - else { - make_tos(d); - ds=stackpos(s); - - emit_byte(0xd8); - emit_byte(0xe0+ds); /* sub src from dest */ - } -} -LENDFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - make_tos(d); - ds=stackpos(s); - - emit_byte(0xdd); - emit_byte(0xe0+ds); /* cmp dest with source*/ -} -LENDFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - if (live.spos[s]==live.tos) { - /* Source is on top of stack */ - ds=stackpos(d); - emit_byte(0xdc); - emit_byte(0xc8+ds); /* mul dest by source*/ - } - else { - make_tos(d); - ds=stackpos(s); - - emit_byte(0xd8); - emit_byte(0xc8+ds); /* mul dest by source*/ - } -} -LENDFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - if (live.spos[s]==live.tos) { - /* Source is on top of stack */ - ds=stackpos(d); - emit_byte(0xdc); - emit_byte(0xf8+ds); /* div dest by source */ - } - else { - make_tos(d); - ds=stackpos(s); - - emit_byte(0xd8); - emit_byte(0xf0+ds); /* div dest by source*/ - } -} -LENDFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - make_tos2(d,s); - ds=stackpos(s); - - if (ds!=1) { - printf("Failed horribly in raw_frem_rr! ds is %d\n",ds); - abort(); - } - emit_byte(0xd9); - emit_byte(0xf8); /* take rem from dest by source */ -} -LENDFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) - -LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) -{ - int ds; - - usereg(s); - usereg(d); - - make_tos2(d,s); - ds=stackpos(s); - - if (ds!=1) { - printf("Failed horribly in raw_frem1_rr! ds is %d\n",ds); - abort(); - } - emit_byte(0xd9); - emit_byte(0xf5); /* take rem1 from dest by source */ -} -LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) - - -LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) -{ - make_tos(r); - emit_byte(0xd9); /* ftst */ - emit_byte(0xe4); -} -LENDFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) - -/* %eax register is clobbered if target processor doesn't support fucomi */ -#define FFLAG_NREG_CLOBBER_CONDITION !have_cmov -#define FFLAG_NREG EAX_INDEX - -static __inline__ void raw_fflags_into_flags(int r) -{ - int p; - - usereg(r); - p=stackpos(r); - - emit_byte(0xd9); - emit_byte(0xee); /* Push 0 */ - emit_byte(0xd9); - emit_byte(0xc9+p); /* swap top two around */ - if (have_cmov) { - // gb-- fucomi is for P6 cores only, not K6-2 then... - emit_byte(0xdb); - emit_byte(0xe9+p); /* fucomi them */ - } - else { - emit_byte(0xdd); - emit_byte(0xe1+p); /* fucom them */ - emit_byte(0x9b); - emit_byte(0xdf); - emit_byte(0xe0); /* fstsw ax */ - raw_sahf(0); /* sahf */ - } - emit_byte(0xdd); - emit_byte(0xd9+p); /* store value back, and get rid of 0 */ -} diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.h b/BasiliskII/src/uae_cpu/compiler/codegen_x86.h deleted file mode 100644 index 08538b7a..00000000 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.h +++ /dev/null @@ -1,2565 +0,0 @@ -/******************** -*- mode: C; tab-width: 8 -*- ******************** - * - * Run-time assembler for IA-32 and AMD64 - * - ***********************************************************************/ - - -/*********************************************************************** - * - * This file is derived from CCG. - * - * Copyright 1999, 2000, 2001, 2002, 2003 Ian Piumarta - * - * Adaptations and enhancements for AMD64 support, Copyright 2003-2008 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ***********************************************************************/ - -#ifndef X86_RTASM_H -#define X86_RTASM_H - -/* NOTES - * - * o Best viewed on a 1024x768 screen with fixed-6x10 font ;-) - * - * TODO - * - * o Fix FIXMEs - * o SSE instructions - * o Optimize for cases where register numbers are not integral constants - */ - -/* --- Configuration ------------------------------------------------------- */ - -/* Define to settle a "flat" register set, i.e. different regno for - each size variant. */ -#ifndef X86_FLAT_REGISTERS -#define X86_FLAT_REGISTERS 1 -#endif - -/* Define to generate x86-64 code. */ -#ifndef X86_TARGET_64BIT -#define X86_TARGET_64BIT 0 -#endif - -/* Define to optimize ALU instructions. */ -#ifndef X86_OPTIMIZE_ALU -#define X86_OPTIMIZE_ALU 1 -#endif - -/* Define to optimize rotate/shift instructions. */ -#ifndef X86_OPTIMIZE_ROTSHI -#define X86_OPTIMIZE_ROTSHI 1 -#endif - -/* Define to optimize absolute addresses for RIP relative addressing. */ -#ifndef X86_RIP_RELATIVE_ADDR -#define X86_RIP_RELATIVE_ADDR 1 -#endif - - -/* --- Macros -------------------------------------------------------------- */ - -/* Functions used to emit code. - * - * x86_emit_byte(B) - * x86_emit_word(W) - * x86_emit_long(L) - */ - -/* Get pointer to current code - * - * x86_get_target() - */ - -/* Abort assembler, fatal failure. - * - * x86_emit_failure(MSG) - */ - -#define x86_emit_failure0(MSG) (x86_emit_failure(MSG),0) - - -/* --- Register set -------------------------------------------------------- */ - -enum { - X86_RIP = -2, -#if X86_FLAT_REGISTERS - X86_NOREG = 0, - X86_Reg8L_Base = 0x10, - X86_Reg8H_Base = 0x20, - X86_Reg16_Base = 0x30, - X86_Reg32_Base = 0x40, - X86_Reg64_Base = 0x50, - X86_RegMMX_Base = 0x60, - X86_RegXMM_Base = 0x70, - X86_RegFPU_Base = 0x80 -#else - X86_NOREG = -1, - X86_Reg8L_Base = 0, - X86_Reg8H_Base = 16, - X86_Reg16_Base = 0, - X86_Reg32_Base = 0, - X86_Reg64_Base = 0, - X86_RegMMX_Base = 0, - X86_RegXMM_Base = 0, - X86_RegFPU_Base = 0 -#endif -}; - -enum { - X86_AL = X86_Reg8L_Base, - X86_CL, X86_DL, X86_BL, - X86_SPL, X86_BPL, X86_SIL, X86_DIL, - X86_R8B, X86_R9B, X86_R10B, X86_R11B, - X86_R12B, X86_R13B, X86_R14B, X86_R15B, - X86_AH = X86_Reg8H_Base + 4, - X86_CH, X86_DH, X86_BH -}; - -enum { - X86_AX = X86_Reg16_Base, - X86_CX, X86_DX, X86_BX, - X86_SP, X86_BP, X86_SI, X86_DI, - X86_R8W, X86_R9W, X86_R10W, X86_R11W, - X86_R12W, X86_R13W, X86_R14W, X86_R15W -}; - -enum { - X86_EAX = X86_Reg32_Base, - X86_ECX, X86_EDX, X86_EBX, - X86_ESP, X86_EBP, X86_ESI, X86_EDI, - X86_R8D, X86_R9D, X86_R10D, X86_R11D, - X86_R12D, X86_R13D, X86_R14D, X86_R15D -}; - -enum { - X86_RAX = X86_Reg64_Base, - X86_RCX, X86_RDX, X86_RBX, - X86_RSP, X86_RBP, X86_RSI, X86_RDI, - X86_R8, X86_R9, X86_R10, X86_R11, - X86_R12, X86_R13, X86_R14, X86_R15 -}; - -enum { - X86_MM0 = X86_RegMMX_Base, - X86_MM1, X86_MM2, X86_MM3, - X86_MM4, X86_MM5, X86_MM6, X86_MM7, -}; - -enum { - X86_XMM0 = X86_RegXMM_Base, - X86_XMM1, X86_XMM2, X86_XMM3, - X86_XMM4, X86_XMM5, X86_XMM6, X86_XMM7, - X86_XMM8, X86_XMM9, X86_XMM10, X86_XMM11, - X86_XMM12, X86_XMM13, X86_XMM14, X86_XMM15 -}; - -enum { - X86_ST0 = X86_RegFPU_Base, - X86_ST1, X86_ST2, X86_ST3, - X86_ST4, X86_ST5, X86_ST6, X86_ST7 -}; - -/* Register control and access - * - * _r0P(R) Null register? - * _rIP(R) RIP register? - * _rXP(R) Extended register? - * - * _rC(R) Class of register (only valid if X86_FLAT_REGISTERS) - * _rR(R) Full register number - * _rN(R) Short register number for encoding - * - * _r1(R) 8-bit register ID - * _r2(R) 16-bit register ID - * _r4(R) 32-bit register ID - * _r8(R) 64-bit register ID - * _rM(R) MMX register ID - * _rX(R) XMM register ID - * _rF(R) FPU register ID - * _rA(R) Address register ID used for EA calculation - */ - -#define _rST0P(R) ((int)(R) == (int)X86_ST0) -#define _r0P(R) ((int)(R) == (int)X86_NOREG) -#define _rIP(R) (X86_TARGET_64BIT ? ((int)(R) == (int)X86_RIP) : 0) - -#if X86_FLAT_REGISTERS -#define _rC(R) ((R) & 0xf0) -#define _rR(R) ((R) & 0x0f) -#define _rN(R) ((R) & 0x07) -#define _rXP(R) (((R) > 0 && _rR(R) > 7) ? 1 : 0) -#else -#define _rN(R) ((R) & 0x07) -#define _rR(R) (int(R)) -#define _rXP(R) ((_rR(R) > 7 && _rR(R) < 16) ? 1 : 0) -#endif - -#if !defined(_ASM_SAFETY) || ! X86_FLAT_REGISTERS -#define _r1(R) _rN(R) -#define _r2(R) _rN(R) -#define _r4(R) _rN(R) -#define _r8(R) _rN(R) -#define _rA(R) _rN(R) -#define _rM(R) _rN(R) -#define _rX(R) _rN(R) -#define _rF(R) _rN(R) -#else -#define _r1(R) ( ((_rC(R) & (X86_Reg8L_Base | X86_Reg8H_Base)) != 0) ? _rN(R) : x86_emit_failure0( "8-bit register required")) -#define _r2(R) ( (_rC(R) == X86_Reg16_Base) ? _rN(R) : x86_emit_failure0("16-bit register required")) -#define _r4(R) ( (_rC(R) == X86_Reg32_Base) ? _rN(R) : x86_emit_failure0("32-bit register required")) -#define _r8(R) ( (_rC(R) == X86_Reg64_Base) ? _rN(R) : x86_emit_failure0("64-bit register required")) -#define _rA(R) ( X86_TARGET_64BIT ? \ - ( (_rC(R) == X86_Reg64_Base) ? _rN(R) : x86_emit_failure0("not a valid 64-bit base/index expression")) : \ - ( (_rC(R) == X86_Reg32_Base) ? _rN(R) : x86_emit_failure0("not a valid 32-bit base/index expression")) ) -#define _rM(R) ( (_rC(R) == X86_RegMMX_Base) ? _rN(R) : x86_emit_failure0("MMX register required")) -#define _rX(R) ( (_rC(R) == X86_RegXMM_Base) ? _rN(R) : x86_emit_failure0("SSE register required")) -#define _rF(R) ( (_rC(R) == X86_RegFPU_Base) ? _rN(R) : x86_emit_failure0("FPU register required")) -#endif - -#define _rSP() (X86_TARGET_64BIT ? (int)X86_RSP : (int)X86_ESP) -#define _r1e8lP(R) (int(R) >= X86_SPL && int(R) <= X86_DIL) -#define _rbpP(R) (_rR(R) == _rR(X86_RBP)) -#define _rspP(R) (_rR(R) == _rR(X86_RSP)) -#define _rbp13P(R) (_rN(R) == _rN(X86_RBP)) -#define _rsp12P(R) (_rN(R) == _rN(X86_RSP)) - - -/* ========================================================================= */ -/* --- UTILITY ------------------------------------------------------------- */ -/* ========================================================================= */ - -typedef signed char _sc; -typedef unsigned char _uc; -typedef signed short _ss; -typedef unsigned short _us; -typedef signed int _sl; -typedef unsigned int _ul; - -#define _UC(X) ((_uc )(unsigned long)(X)) -#define _US(X) ((_us )(unsigned long)(X)) -#define _SL(X) ((_sl )(unsigned long)(X)) -#define _UL(X) ((_ul )(unsigned long)(X)) - -#define _PUC(X) ((_uc *)(X)) -#define _PUS(X) ((_us *)(X)) -#define _PSL(X) ((_sl *)(X)) -#define _PUL(X) ((_ul *)(X)) - -#define _B(B) x86_emit_byte((B)) -#define _W(W) x86_emit_word((W)) -#define _L(L) x86_emit_long((L)) -#define _Q(Q) x86_emit_quad((Q)) - -#define _MASK(N) ((unsigned)((1<<(N)))-1) -#define _siP(N,I) (!((((unsigned)(I))^(((unsigned)(I))<<1))&~_MASK(N))) -#define _uiP(N,I) (!(((unsigned)(I))&~_MASK(N))) -#define _suiP(N,I) (_siP(N,I) | _uiP(N,I)) - -#ifndef _ASM_SAFETY -#define _ck_s(W,I) (_UL(I) & _MASK(W)) -#define _ck_u(W,I) (_UL(I) & _MASK(W)) -#define _ck_su(W,I) (_UL(I) & _MASK(W)) -#define _ck_d(W,I) (_UL(I) & _MASK(W)) -#else -#define _ck_s(W,I) (_siP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0( "signed integer `"#I"' too large for "#W"-bit field")) -#define _ck_u(W,I) (_uiP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0("unsigned integer `"#I"' too large for "#W"-bit field")) -#define _ck_su(W,I) (_suiP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0( "integer `"#I"' too large for "#W"-bit field")) -#define _ck_d(W,I) (_siP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0( "displacement `"#I"' too large for "#W"-bit field")) -#endif - -#define _s0P(I) ((I)==0) -#define _s8P(I) _siP(8,I) -#define _s16P(I) _siP(16,I) -#define _u8P(I) _uiP(8,I) -#define _u16P(I) _uiP(16,I) - -#define _su8(I) _ck_su(8,I) -#define _su16(I) _ck_su(16,I) - -#define _s1(I) _ck_s( 1,I) -#define _s2(I) _ck_s( 2,I) -#define _s3(I) _ck_s( 3,I) -#define _s4(I) _ck_s( 4,I) -#define _s5(I) _ck_s( 5,I) -#define _s6(I) _ck_s( 6,I) -#define _s7(I) _ck_s( 7,I) -#define _s8(I) _ck_s( 8,I) -#define _s9(I) _ck_s( 9,I) -#define _s10(I) _ck_s(10,I) -#define _s11(I) _ck_s(11,I) -#define _s12(I) _ck_s(12,I) -#define _s13(I) _ck_s(13,I) -#define _s14(I) _ck_s(14,I) -#define _s15(I) _ck_s(15,I) -#define _s16(I) _ck_s(16,I) -#define _s17(I) _ck_s(17,I) -#define _s18(I) _ck_s(18,I) -#define _s19(I) _ck_s(19,I) -#define _s20(I) _ck_s(20,I) -#define _s21(I) _ck_s(21,I) -#define _s22(I) _ck_s(22,I) -#define _s23(I) _ck_s(23,I) -#define _s24(I) _ck_s(24,I) -#define _s25(I) _ck_s(25,I) -#define _s26(I) _ck_s(26,I) -#define _s27(I) _ck_s(27,I) -#define _s28(I) _ck_s(28,I) -#define _s29(I) _ck_s(29,I) -#define _s30(I) _ck_s(30,I) -#define _s31(I) _ck_s(31,I) -#define _u1(I) _ck_u( 1,I) -#define _u2(I) _ck_u( 2,I) -#define _u3(I) _ck_u( 3,I) -#define _u4(I) _ck_u( 4,I) -#define _u5(I) _ck_u( 5,I) -#define _u6(I) _ck_u( 6,I) -#define _u7(I) _ck_u( 7,I) -#define _u8(I) _ck_u( 8,I) -#define _u9(I) _ck_u( 9,I) -#define _u10(I) _ck_u(10,I) -#define _u11(I) _ck_u(11,I) -#define _u12(I) _ck_u(12,I) -#define _u13(I) _ck_u(13,I) -#define _u14(I) _ck_u(14,I) -#define _u15(I) _ck_u(15,I) -#define _u16(I) _ck_u(16,I) -#define _u17(I) _ck_u(17,I) -#define _u18(I) _ck_u(18,I) -#define _u19(I) _ck_u(19,I) -#define _u20(I) _ck_u(20,I) -#define _u21(I) _ck_u(21,I) -#define _u22(I) _ck_u(22,I) -#define _u23(I) _ck_u(23,I) -#define _u24(I) _ck_u(24,I) -#define _u25(I) _ck_u(25,I) -#define _u26(I) _ck_u(26,I) -#define _u27(I) _ck_u(27,I) -#define _u28(I) _ck_u(28,I) -#define _u29(I) _ck_u(29,I) -#define _u30(I) _ck_u(30,I) -#define _u31(I) _ck_u(31,I) - -/* ========================================================================= */ -/* --- ASSEMBLER ----------------------------------------------------------- */ -/* ========================================================================= */ - -#define _b00 0 -#define _b01 1 -#define _b10 2 -#define _b11 3 - -#define _b000 0 -#define _b001 1 -#define _b010 2 -#define _b011 3 -#define _b100 4 -#define _b101 5 -#define _b110 6 -#define _b111 7 - -#define _OFF4(D) (_UL(D) - _UL(x86_get_target())) -#define _CKD8(D) _ck_d(8, ((_uc) _OFF4(D)) ) - -#define _D8(D) (_B(0), ((*(_PUC(x86_get_target())-1))= _CKD8(D))) -#define _D32(D) (_L(0), ((*(_PUL(x86_get_target())-1))= _OFF4(D))) - -#ifndef _ASM_SAFETY -# define _M(M) (M) -# define _r(R) (R) -# define _m(M) (M) -# define _s(S) (S) -# define _i(I) (I) -# define _b(B) (B) -#else -# define _M(M) (((M)>3) ? x86_emit_failure0("internal error: mod = " #M) : (M)) -# define _r(R) (((R)>7) ? x86_emit_failure0("internal error: reg = " #R) : (R)) -# define _m(M) (((M)>7) ? x86_emit_failure0("internal error: r/m = " #M) : (M)) -# define _s(S) (((S)>3) ? x86_emit_failure0("internal error: memory scale = " #S) : (S)) -# define _i(I) (((I)>7) ? x86_emit_failure0("internal error: memory index = " #I) : (I)) -# define _b(B) (((B)>7) ? x86_emit_failure0("internal error: memory base = " #B) : (B)) -#endif - -#define _Mrm(Md,R,M) _B((_M(Md)<<6)|(_r(R)<<3)|_m(M)) -#define _SIB(Sc,I, B) _B((_s(Sc)<<6)|(_i(I)<<3)|_b(B)) - -#define _SCL(S) ((((S)==1) ? _b00 : \ - (((S)==2) ? _b01 : \ - (((S)==4) ? _b10 : \ - (((S)==8) ? _b11 : x86_emit_failure0("illegal scale: " #S)))))) - - -/* --- Memory subformats - urgh! ------------------------------------------- */ - -/* _r_D() is RIP addressing mode if X86_TARGET_64BIT, use _r_DSIB() instead */ -#define _r_D( R, D ) (_Mrm(_b00,_rN(R),_b101 ) ,_L((_sl)(D))) -#define _r_DSIB(R, D ) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(1),_b100 ,_b101 ),_L((_sl)(D))) -#define _r_0B( R, B ) (_Mrm(_b00,_rN(R),_rA(B)) ) -#define _r_0BIS(R, B,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)) ) -#define _r_1B( R, D,B ) (_Mrm(_b01,_rN(R),_rA(B)) ,_B((_sc)(D))) -#define _r_1BIS(R, D,B,I,S) (_Mrm(_b01,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_B((_sc)(D))) -#define _r_4B( R, D,B ) (_Mrm(_b10,_rN(R),_rA(B)) ,_L((_sl)(D))) -#define _r_4IS( R, D,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_b101 ),_L((_sl)(D))) -#define _r_4BIS(R, D,B,I,S) (_Mrm(_b10,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_L((_sl)(D))) - -#define _r_DB( R, D,B ) ((_s0P(D) && (!_rbp13P(B)) ? _r_0B (R, B ) : (_s8P(D) ? _r_1B( R,D,B ) : _r_4B( R,D,B )))) -#define _r_DBIS(R, D,B,I,S) ((_s0P(D) && (!_rbp13P(B)) ? _r_0BIS(R, B,I,S) : (_s8P(D) ? _r_1BIS(R,D,B,I,S) : _r_4BIS(R,D,B,I,S)))) - -/* Use RIP-addressing in 64-bit mode, if possible */ -#define _x86_RIP_addressing_possible(D,O) (X86_RIP_RELATIVE_ADDR && \ - ((uintptr)x86_get_target() + 4 + (O) - (D) <= 0xffffffff)) - -#define _r_X( R, D,B,I,S,O) (_r0P(I) ? (_r0P(B) ? (!X86_TARGET_64BIT ? _r_D(R,D) : \ - (_x86_RIP_addressing_possible(D, O) ? \ - _r_D(R, (D) - ((uintptr)x86_get_target() + 4 + (O))) : \ - _r_DSIB(R,D))) : \ - (_rIP(B) ? _r_D (R,D ) : \ - (_rsp12P(B) ? _r_DBIS(R,D,_rSP(),_rSP(),1) : \ - _r_DB (R,D, B )))) : \ - (_r0P(B) ? _r_4IS (R,D, I,S) : \ - (!_rspP(I) ? _r_DBIS(R,D, B, I,S) : \ - x86_emit_failure("illegal index register: %esp")))) - - -/* --- Instruction formats ------------------------------------------------- */ - -#define _m32only(X) (! X86_TARGET_64BIT ? X : x86_emit_failure("invalid instruction in 64-bit mode")) -#define _m64only(X) ( X86_TARGET_64BIT ? X : x86_emit_failure("invalid instruction in 32-bit mode")) -#define _m64(X) ( X86_TARGET_64BIT ? X : ((void)0) ) - -/* _format Opcd ModR/M dN(rB,rI,Sc) imm... */ - -#define _d16() ( _B(0x66 ) ) -#define _O( OP ) ( _B( OP ) ) -#define _Or( OP,R ) ( _B( (OP)|_r(R)) ) -#define _OO( OP ) ( _B((OP)>>8), _B(( (OP) )&0xff) ) -#define _OOr( OP,R ) ( _B((OP)>>8), _B(( (OP)|_r(R))&0xff) ) -#define _Os( OP,B ) ( _s8P(B) ? _B(((OP)|_b10)) : _B(OP) ) -#define _sW( W ) ( _s8P(W) ? _B(W):_W(W) ) -#define _sL( L ) ( _s8P(L) ? _B(L):_L(L) ) -#define _sWO( W ) ( _s8P(W) ? 1 : 2 ) -#define _sLO( L ) ( _s8P(L) ? 1 : 4 ) -#define _O_B( OP ,B ) ( _O ( OP ) ,_B(B) ) -#define _O_W( OP ,W ) ( _O ( OP ) ,_W(W) ) -#define _O_L( OP ,L ) ( _O ( OP ) ,_L(L) ) -#define _OO_L( OP ,L ) ( _OO ( OP ) ,_L(L) ) -#define _O_D8( OP ,D ) ( _O ( OP ) ,_D8(D) ) -#define _O_D32( OP ,D ) ( _O ( OP ) ,_D32(D) ) -#define _OO_D32( OP ,D ) ( _OO ( OP ) ,_D32(D) ) -#define _Os_sW( OP ,W ) ( _Os ( OP,W) ,_sW(W) ) -#define _Os_sL( OP ,L ) ( _Os ( OP,L) ,_sL(L) ) -#define _O_W_B( OP ,W,B) ( _O ( OP ) ,_W(W),_B(B)) -#define _Or_B( OP,R ,B ) ( _Or ( OP,R) ,_B(B) ) -#define _Or_W( OP,R ,W ) ( _Or ( OP,R) ,_W(W) ) -#define _Or_L( OP,R ,L ) ( _Or ( OP,R) ,_L(L) ) -#define _Or_Q( OP,R ,Q ) ( _Or ( OP,R) ,_Q(Q) ) -#define _O_Mrm( OP ,MO,R,M ) ( _O ( OP ),_Mrm(MO,R,M ) ) -#define _OO_Mrm( OP ,MO,R,M ) ( _OO ( OP ),_Mrm(MO,R,M ) ) -#define _O_Mrm_B( OP ,MO,R,M ,B ) ( _O ( OP ),_Mrm(MO,R,M ) ,_B(B) ) -#define _O_Mrm_W( OP ,MO,R,M ,W ) ( _O ( OP ),_Mrm(MO,R,M ) ,_W(W) ) -#define _O_Mrm_L( OP ,MO,R,M ,L ) ( _O ( OP ),_Mrm(MO,R,M ) ,_L(L) ) -#define _OO_Mrm_B( OP ,MO,R,M ,B ) ( _OO ( OP ),_Mrm(MO,R,M ) ,_B(B) ) -#define _Os_Mrm_sW(OP ,MO,R,M ,W ) ( _Os ( OP,W),_Mrm(MO,R,M ),_sW(W) ) -#define _Os_Mrm_sL(OP ,MO,R,M ,L ) ( _Os ( OP,L),_Mrm(MO,R,M ),_sL(L) ) -#define _O_r_X( OP ,R ,MD,MB,MI,MS ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,0) ) -#define _OO_r_X( OP ,R ,MD,MB,MI,MS ) ( _OO ( OP ),_r_X( R ,MD,MB,MI,MS,0) ) -#define _O_r_X_B( OP ,R ,MD,MB,MI,MS,B ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,1) ,_B(B) ) -#define _O_r_X_W( OP ,R ,MD,MB,MI,MS,W ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,2) ,_W(W) ) -#define _O_r_X_L( OP ,R ,MD,MB,MI,MS,L ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,4) ,_L(L) ) -#define _OO_r_X_B( OP ,R ,MD,MB,MI,MS,B ) ( _OO ( OP ),_r_X( R ,MD,MB,MI,MS,1) ,_B(B) ) -#define _Os_r_X_sW(OP ,R ,MD,MB,MI,MS,W ) ( _Os ( OP,W),_r_X( R ,MD,MB,MI,MS,_sWO(W)),_sW(W)) -#define _Os_r_X_sL(OP ,R ,MD,MB,MI,MS,L ) ( _Os ( OP,L),_r_X( R ,MD,MB,MI,MS,_sLO(L)),_sL(L)) -#define _O_X_B( OP ,MD,MB,MI,MS,B ) ( _O_r_X_B( OP ,0 ,MD,MB,MI,MS ,B) ) -#define _O_X_W( OP ,MD,MB,MI,MS,W ) ( _O_r_X_W( OP ,0 ,MD,MB,MI,MS ,W) ) -#define _O_X_L( OP ,MD,MB,MI,MS,L ) ( _O_r_X_L( OP ,0 ,MD,MB,MI,MS ,L) ) - - -/* --- REX prefixes -------------------------------------------------------- */ - -#define _VOID() ((void)0) -#define _BIT(X) ((X) ? 1 : 0) -#define _d64(W,R,X,B) (_B(0x40|(W)<<3|(R)<<2|(X)<<1|(B))) - -#define __REXwrxb(L,W,R,X,B) ((W|R|X|B) || (L) ? _d64(W,R,X,B) : _VOID()) -#define __REXwrx_(L,W,R,X,MR) (__REXwrxb(L,W,R,X,_BIT(_rIP(MR)?0:_rXP(MR)))) -#define __REXw_x_(L,W,R,X,MR) (__REXwrx_(L,W,_BIT(_rXP(R)),X,MR)) -#define __REX_reg(RR) (__REXwrxb(0,0,0,00,_BIT(_rXP(RR)))) -#define __REX_mem(MB,MI) (__REXwrxb(0,0,0,_BIT(_rXP(MI)),_BIT(_rXP(MB)))) - -// FIXME: can't mix new (SPL,BPL,SIL,DIL) with (AH,BH,CH,DH) -#define _REXBrr(RR,MR) _m64(__REXw_x_(_r1e8lP(RR)||_r1e8lP(MR),0,RR,0,MR)) -#define _REXBmr(MB,MI,RD) _m64(__REXw_x_(_r1e8lP(RD)||_r1e8lP(MB),0,RD,_BIT(_rXP(MI)),MB)) -#define _REXBrm(RS,MB,MI) _REXBmr(MB,MI,RS) - -#define _REXBLrr(RR,MR) _m64(__REXw_x_(_r1e8lP(MR),0,RR,0,MR)) -#define _REXLrr(RR,MR) _m64(__REXw_x_(0,0,RR,0,MR)) -#define _REXLmr(MB,MI,RD) _m64(__REXw_x_(0,0,RD,_BIT(_rXP(MI)),MB)) -#define _REXLrm(RS,MB,MI) _REXLmr(MB,MI,RS) -#define _REXLr(RR) _m64(__REX_reg(RR)) -#define _REXLm(MB,MI) _m64(__REX_mem(MB,MI)) - -#define _REXQrr(RR,MR) _m64only(__REXw_x_(0,1,RR,0,MR)) -#define _REXQmr(MB,MI,RD) _m64only(__REXw_x_(0,1,RD,_BIT(_rXP(MI)),MB)) -#define _REXQrm(RS,MB,MI) _REXQmr(MB,MI,RS) -#define _REXQr(RR) _m64only(__REX_reg(RR)) -#define _REXQm(MB,MI) _m64only(__REX_mem(MB,MI)) - - -/* ========================================================================= */ -/* --- Fully-qualified intrinsic instructions ------------------------------ */ -/* ========================================================================= */ - -/* OPCODE + i = immediate operand - * + r = register operand - * + m = memory operand (disp,base,index,scale) - * + sr/sm = a star preceding a register or memory - * + 0 = top of stack register (for FPU instructions) - * - * NOTE in x86-64 mode: a memory operand with only a valid - * displacement value will lead to the expect absolute mode. If - * RIP addressing is necessary, X86_RIP shall be used as the base - * register argument. - */ - -/* --- ALU instructions ---------------------------------------------------- */ - -enum { - X86_ADD = 0, - X86_OR = 1, - X86_ADC = 2, - X86_SBB = 3, - X86_AND = 4, - X86_SUB = 5, - X86_XOR = 6, - X86_CMP = 7, -}; - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define _ALUBrr(OP,RS, RD) (_REXBrr(RS, RD), _O_Mrm (((OP) << 3) ,_b11,_r1(RS),_r1(RD) )) -#define _ALUBmr(OP, MD, MB, MI, MS, RD) (_REXBmr(MB, MI, RD), _O_r_X (((OP) << 3) + 2 ,_r1(RD) ,MD,MB,MI,MS )) -#define _ALUBrm(OP, RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (((OP) << 3) ,_r1(RS) ,MD,MB,MI,MS )) -#define _ALUBir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AL) ? \ - (_REXBrr(0, RD), _O_B (((OP) << 3) + 4 ,_su8(IM))) : \ - (_REXBrr(0, RD), _O_Mrm_B (0x80 ,_b11,OP ,_r1(RD) ,_su8(IM))) ) -#define _ALUBim(OP, IM, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X_B (0x80 ,OP ,MD,MB,MI,MS ,_su8(IM))) - -#define _ALUWrr(OP, RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (((OP) << 3) + 1,_b11,_r2(RS),_r2(RD) )) -#define _ALUWmr(OP, MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _O_r_X (((OP) << 3) + 3 ,_r2(RD) ,MD,MB,MI,MS )) -#define _ALUWrm(OP, RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (((OP) << 3) + 1 ,_r2(RS) ,MD,MB,MI,MS )) -#define _ALUWir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AX) ? \ - (_d16(), _REXLrr(0, RD), _O_W (((OP) << 3) + 5 ,_su16(IM))) : \ - (_d16(), _REXLrr(0, RD), _Os_Mrm_sW (0x81 ,_b11,OP ,_r2(RD) ,_su16(IM))) ) -#define _ALUWim(OP, IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _Os_r_X_sW (0x81 ,OP ,MD,MB,MI,MS ,_su16(IM))) - -#define _ALULrr(OP, RS, RD) (_REXLrr(RS, RD), _O_Mrm (((OP) << 3) + 1,_b11,_r4(RS),_r4(RD) )) -#define _ALULmr(OP, MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (((OP) << 3) + 3 ,_r4(RD) ,MD,MB,MI,MS )) -#define _ALULrm(OP, RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (((OP) << 3) + 1 ,_r4(RS) ,MD,MB,MI,MS )) -#define _ALULir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_EAX) ? \ - (_REXLrr(0, RD), _O_L (((OP) << 3) + 5 ,IM )) : \ - (_REXLrr(0, RD), _Os_Mrm_sL (0x81 ,_b11,OP ,_r4(RD) ,IM )) ) -#define _ALULim(OP, IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _Os_r_X_sL (0x81 ,OP ,MD,MB,MI,MS ,IM )) - -#define _ALUQrr(OP, RS, RD) (_REXQrr(RS, RD), _O_Mrm (((OP) << 3) + 1,_b11,_r8(RS),_r8(RD) )) -#define _ALUQmr(OP, MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (((OP) << 3) + 3 ,_r8(RD) ,MD,MB,MI,MS )) -#define _ALUQrm(OP, RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (((OP) << 3) + 1 ,_r8(RS) ,MD,MB,MI,MS )) -#define _ALUQir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_RAX) ? \ - (_REXQrr(0, RD), _O_L (((OP) << 3) + 5 ,IM )) : \ - (_REXQrr(0, RD), _Os_Mrm_sL (0x81 ,_b11,OP ,_r8(RD) ,IM )) ) -#define _ALUQim(OP, IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _Os_r_X_sL (0x81 ,OP ,MD,MB,MI,MS ,IM )) - -#define ADCBrr(RS, RD) _ALUBrr(X86_ADC, RS, RD) -#define ADCBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_ADC, MD, MB, MI, MS, RD) -#define ADCBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_ADC, RS, MD, MB, MI, MS) -#define ADCBir(IM, RD) _ALUBir(X86_ADC, IM, RD) -#define ADCBim(IM, MD, MB, MI, MS) _ALUBim(X86_ADC, IM, MD, MB, MI, MS) - -#define ADCWrr(RS, RD) _ALUWrr(X86_ADC, RS, RD) -#define ADCWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_ADC, MD, MB, MI, MS, RD) -#define ADCWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_ADC, RS, MD, MB, MI, MS) -#define ADCWir(IM, RD) _ALUWir(X86_ADC, IM, RD) -#define ADCWim(IM, MD, MB, MI, MS) _ALUWim(X86_ADC, IM, MD, MB, MI, MS) - -#define ADCLrr(RS, RD) _ALULrr(X86_ADC, RS, RD) -#define ADCLmr(MD, MB, MI, MS, RD) _ALULmr(X86_ADC, MD, MB, MI, MS, RD) -#define ADCLrm(RS, MD, MB, MI, MS) _ALULrm(X86_ADC, RS, MD, MB, MI, MS) -#define ADCLir(IM, RD) _ALULir(X86_ADC, IM, RD) -#define ADCLim(IM, MD, MB, MI, MS) _ALULim(X86_ADC, IM, MD, MB, MI, MS) - -#define ADCQrr(RS, RD) _ALUQrr(X86_ADC, RS, RD) -#define ADCQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_ADC, MD, MB, MI, MS, RD) -#define ADCQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_ADC, RS, MD, MB, MI, MS) -#define ADCQir(IM, RD) _ALUQir(X86_ADC, IM, RD) -#define ADCQim(IM, MD, MB, MI, MS) _ALUQim(X86_ADC, IM, MD, MB, MI, MS) - -#define ADDBrr(RS, RD) _ALUBrr(X86_ADD, RS, RD) -#define ADDBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_ADD, MD, MB, MI, MS, RD) -#define ADDBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_ADD, RS, MD, MB, MI, MS) -#define ADDBir(IM, RD) _ALUBir(X86_ADD, IM, RD) -#define ADDBim(IM, MD, MB, MI, MS) _ALUBim(X86_ADD, IM, MD, MB, MI, MS) - -#define ADDWrr(RS, RD) _ALUWrr(X86_ADD, RS, RD) -#define ADDWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_ADD, MD, MB, MI, MS, RD) -#define ADDWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_ADD, RS, MD, MB, MI, MS) -#define ADDWir(IM, RD) _ALUWir(X86_ADD, IM, RD) -#define ADDWim(IM, MD, MB, MI, MS) _ALUWim(X86_ADD, IM, MD, MB, MI, MS) - -#define ADDLrr(RS, RD) _ALULrr(X86_ADD, RS, RD) -#define ADDLmr(MD, MB, MI, MS, RD) _ALULmr(X86_ADD, MD, MB, MI, MS, RD) -#define ADDLrm(RS, MD, MB, MI, MS) _ALULrm(X86_ADD, RS, MD, MB, MI, MS) -#define ADDLir(IM, RD) _ALULir(X86_ADD, IM, RD) -#define ADDLim(IM, MD, MB, MI, MS) _ALULim(X86_ADD, IM, MD, MB, MI, MS) - -#define ADDQrr(RS, RD) _ALUQrr(X86_ADD, RS, RD) -#define ADDQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_ADD, MD, MB, MI, MS, RD) -#define ADDQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_ADD, RS, MD, MB, MI, MS) -#define ADDQir(IM, RD) _ALUQir(X86_ADD, IM, RD) -#define ADDQim(IM, MD, MB, MI, MS) _ALUQim(X86_ADD, IM, MD, MB, MI, MS) - -#define ANDBrr(RS, RD) _ALUBrr(X86_AND, RS, RD) -#define ANDBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_AND, MD, MB, MI, MS, RD) -#define ANDBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_AND, RS, MD, MB, MI, MS) -#define ANDBir(IM, RD) _ALUBir(X86_AND, IM, RD) -#define ANDBim(IM, MD, MB, MI, MS) _ALUBim(X86_AND, IM, MD, MB, MI, MS) - -#define ANDWrr(RS, RD) _ALUWrr(X86_AND, RS, RD) -#define ANDWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_AND, MD, MB, MI, MS, RD) -#define ANDWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_AND, RS, MD, MB, MI, MS) -#define ANDWir(IM, RD) _ALUWir(X86_AND, IM, RD) -#define ANDWim(IM, MD, MB, MI, MS) _ALUWim(X86_AND, IM, MD, MB, MI, MS) - -#define ANDLrr(RS, RD) _ALULrr(X86_AND, RS, RD) -#define ANDLmr(MD, MB, MI, MS, RD) _ALULmr(X86_AND, MD, MB, MI, MS, RD) -#define ANDLrm(RS, MD, MB, MI, MS) _ALULrm(X86_AND, RS, MD, MB, MI, MS) -#define ANDLir(IM, RD) _ALULir(X86_AND, IM, RD) -#define ANDLim(IM, MD, MB, MI, MS) _ALULim(X86_AND, IM, MD, MB, MI, MS) - -#define ANDQrr(RS, RD) _ALUQrr(X86_AND, RS, RD) -#define ANDQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_AND, MD, MB, MI, MS, RD) -#define ANDQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_AND, RS, MD, MB, MI, MS) -#define ANDQir(IM, RD) _ALUQir(X86_AND, IM, RD) -#define ANDQim(IM, MD, MB, MI, MS) _ALUQim(X86_AND, IM, MD, MB, MI, MS) - -#define CMPBrr(RS, RD) _ALUBrr(X86_CMP, RS, RD) -#define CMPBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_CMP, MD, MB, MI, MS, RD) -#define CMPBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_CMP, RS, MD, MB, MI, MS) -#define CMPBir(IM, RD) _ALUBir(X86_CMP, IM, RD) -#define CMPBim(IM, MD, MB, MI, MS) _ALUBim(X86_CMP, IM, MD, MB, MI, MS) - -#define CMPWrr(RS, RD) _ALUWrr(X86_CMP, RS, RD) -#define CMPWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_CMP, MD, MB, MI, MS, RD) -#define CMPWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_CMP, RS, MD, MB, MI, MS) -#define CMPWir(IM, RD) _ALUWir(X86_CMP, IM, RD) -#define CMPWim(IM, MD, MB, MI, MS) _ALUWim(X86_CMP, IM, MD, MB, MI, MS) - -#define CMPLrr(RS, RD) _ALULrr(X86_CMP, RS, RD) -#define CMPLmr(MD, MB, MI, MS, RD) _ALULmr(X86_CMP, MD, MB, MI, MS, RD) -#define CMPLrm(RS, MD, MB, MI, MS) _ALULrm(X86_CMP, RS, MD, MB, MI, MS) -#define CMPLir(IM, RD) _ALULir(X86_CMP, IM, RD) -#define CMPLim(IM, MD, MB, MI, MS) _ALULim(X86_CMP, IM, MD, MB, MI, MS) - -#define CMPQrr(RS, RD) _ALUQrr(X86_CMP, RS, RD) -#define CMPQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_CMP, MD, MB, MI, MS, RD) -#define CMPQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_CMP, RS, MD, MB, MI, MS) -#define CMPQir(IM, RD) _ALUQir(X86_CMP, IM, RD) -#define CMPQim(IM, MD, MB, MI, MS) _ALUQim(X86_CMP, IM, MD, MB, MI, MS) - -#define ORBrr(RS, RD) _ALUBrr(X86_OR, RS, RD) -#define ORBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_OR, MD, MB, MI, MS, RD) -#define ORBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_OR, RS, MD, MB, MI, MS) -#define ORBir(IM, RD) _ALUBir(X86_OR, IM, RD) -#define ORBim(IM, MD, MB, MI, MS) _ALUBim(X86_OR, IM, MD, MB, MI, MS) - -#define ORWrr(RS, RD) _ALUWrr(X86_OR, RS, RD) -#define ORWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_OR, MD, MB, MI, MS, RD) -#define ORWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_OR, RS, MD, MB, MI, MS) -#define ORWir(IM, RD) _ALUWir(X86_OR, IM, RD) -#define ORWim(IM, MD, MB, MI, MS) _ALUWim(X86_OR, IM, MD, MB, MI, MS) - -#define ORLrr(RS, RD) _ALULrr(X86_OR, RS, RD) -#define ORLmr(MD, MB, MI, MS, RD) _ALULmr(X86_OR, MD, MB, MI, MS, RD) -#define ORLrm(RS, MD, MB, MI, MS) _ALULrm(X86_OR, RS, MD, MB, MI, MS) -#define ORLir(IM, RD) _ALULir(X86_OR, IM, RD) -#define ORLim(IM, MD, MB, MI, MS) _ALULim(X86_OR, IM, MD, MB, MI, MS) - -#define ORQrr(RS, RD) _ALUQrr(X86_OR, RS, RD) -#define ORQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_OR, MD, MB, MI, MS, RD) -#define ORQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_OR, RS, MD, MB, MI, MS) -#define ORQir(IM, RD) _ALUQir(X86_OR, IM, RD) -#define ORQim(IM, MD, MB, MI, MS) _ALUQim(X86_OR, IM, MD, MB, MI, MS) - -#define SBBBrr(RS, RD) _ALUBrr(X86_SBB, RS, RD) -#define SBBBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_SBB, MD, MB, MI, MS, RD) -#define SBBBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_SBB, RS, MD, MB, MI, MS) -#define SBBBir(IM, RD) _ALUBir(X86_SBB, IM, RD) -#define SBBBim(IM, MD, MB, MI, MS) _ALUBim(X86_SBB, IM, MD, MB, MI, MS) - -#define SBBWrr(RS, RD) _ALUWrr(X86_SBB, RS, RD) -#define SBBWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_SBB, MD, MB, MI, MS, RD) -#define SBBWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_SBB, RS, MD, MB, MI, MS) -#define SBBWir(IM, RD) _ALUWir(X86_SBB, IM, RD) -#define SBBWim(IM, MD, MB, MI, MS) _ALUWim(X86_SBB, IM, MD, MB, MI, MS) - -#define SBBLrr(RS, RD) _ALULrr(X86_SBB, RS, RD) -#define SBBLmr(MD, MB, MI, MS, RD) _ALULmr(X86_SBB, MD, MB, MI, MS, RD) -#define SBBLrm(RS, MD, MB, MI, MS) _ALULrm(X86_SBB, RS, MD, MB, MI, MS) -#define SBBLir(IM, RD) _ALULir(X86_SBB, IM, RD) -#define SBBLim(IM, MD, MB, MI, MS) _ALULim(X86_SBB, IM, MD, MB, MI, MS) - -#define SBBQrr(RS, RD) _ALUQrr(X86_SBB, RS, RD) -#define SBBQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_SBB, MD, MB, MI, MS, RD) -#define SBBQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_SBB, RS, MD, MB, MI, MS) -#define SBBQir(IM, RD) _ALUQir(X86_SBB, IM, RD) -#define SBBQim(IM, MD, MB, MI, MS) _ALUQim(X86_SBB, IM, MD, MB, MI, MS) - -#define SUBBrr(RS, RD) _ALUBrr(X86_SUB, RS, RD) -#define SUBBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_SUB, MD, MB, MI, MS, RD) -#define SUBBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_SUB, RS, MD, MB, MI, MS) -#define SUBBir(IM, RD) _ALUBir(X86_SUB, IM, RD) -#define SUBBim(IM, MD, MB, MI, MS) _ALUBim(X86_SUB, IM, MD, MB, MI, MS) - -#define SUBWrr(RS, RD) _ALUWrr(X86_SUB, RS, RD) -#define SUBWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_SUB, MD, MB, MI, MS, RD) -#define SUBWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_SUB, RS, MD, MB, MI, MS) -#define SUBWir(IM, RD) _ALUWir(X86_SUB, IM, RD) -#define SUBWim(IM, MD, MB, MI, MS) _ALUWim(X86_SUB, IM, MD, MB, MI, MS) - -#define SUBLrr(RS, RD) _ALULrr(X86_SUB, RS, RD) -#define SUBLmr(MD, MB, MI, MS, RD) _ALULmr(X86_SUB, MD, MB, MI, MS, RD) -#define SUBLrm(RS, MD, MB, MI, MS) _ALULrm(X86_SUB, RS, MD, MB, MI, MS) -#define SUBLir(IM, RD) _ALULir(X86_SUB, IM, RD) -#define SUBLim(IM, MD, MB, MI, MS) _ALULim(X86_SUB, IM, MD, MB, MI, MS) - -#define SUBQrr(RS, RD) _ALUQrr(X86_SUB, RS, RD) -#define SUBQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_SUB, MD, MB, MI, MS, RD) -#define SUBQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_SUB, RS, MD, MB, MI, MS) -#define SUBQir(IM, RD) _ALUQir(X86_SUB, IM, RD) -#define SUBQim(IM, MD, MB, MI, MS) _ALUQim(X86_SUB, IM, MD, MB, MI, MS) - -#define XORBrr(RS, RD) _ALUBrr(X86_XOR, RS, RD) -#define XORBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_XOR, MD, MB, MI, MS, RD) -#define XORBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_XOR, RS, MD, MB, MI, MS) -#define XORBir(IM, RD) _ALUBir(X86_XOR, IM, RD) -#define XORBim(IM, MD, MB, MI, MS) _ALUBim(X86_XOR, IM, MD, MB, MI, MS) - -#define XORWrr(RS, RD) _ALUWrr(X86_XOR, RS, RD) -#define XORWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_XOR, MD, MB, MI, MS, RD) -#define XORWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_XOR, RS, MD, MB, MI, MS) -#define XORWir(IM, RD) _ALUWir(X86_XOR, IM, RD) -#define XORWim(IM, MD, MB, MI, MS) _ALUWim(X86_XOR, IM, MD, MB, MI, MS) - -#define XORLrr(RS, RD) _ALULrr(X86_XOR, RS, RD) -#define XORLmr(MD, MB, MI, MS, RD) _ALULmr(X86_XOR, MD, MB, MI, MS, RD) -#define XORLrm(RS, MD, MB, MI, MS) _ALULrm(X86_XOR, RS, MD, MB, MI, MS) -#define XORLir(IM, RD) _ALULir(X86_XOR, IM, RD) -#define XORLim(IM, MD, MB, MI, MS) _ALULim(X86_XOR, IM, MD, MB, MI, MS) - -#define XORQrr(RS, RD) _ALUQrr(X86_XOR, RS, RD) -#define XORQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_XOR, MD, MB, MI, MS, RD) -#define XORQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_XOR, RS, MD, MB, MI, MS) -#define XORQir(IM, RD) _ALUQir(X86_XOR, IM, RD) -#define XORQim(IM, MD, MB, MI, MS) _ALUQim(X86_XOR, IM, MD, MB, MI, MS) - - -/* --- Shift/Rotate instructions ------------------------------------------- */ - -enum { - X86_ROL = 0, - X86_ROR = 1, - X86_RCL = 2, - X86_RCR = 3, - X86_SHL = 4, - X86_SHR = 5, - X86_SAR = 7, -}; - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define _ROTSHIBir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_REXBrr(0, RD), _O_Mrm (0xd0 ,_b11,OP,_r1(RD) )) : \ - (_REXBrr(0, RD), _O_Mrm_B (0xc0 ,_b11,OP,_r1(RD) ,_u8(IM))) ) -#define _ROTSHIBim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_REXBrm(0, MB, MI), _O_r_X (0xd0 ,OP ,MD,MB,MI,MS )) : \ - (_REXBrm(0, MB, MI), _O_r_X_B (0xc0 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) -#define _ROTSHIBrr(OP,RS,RD) (((RS) == X86_CL) ? \ - (_REXBrr(RS, RD), _O_Mrm (0xd2 ,_b11,OP,_r1(RD) )) : \ - x86_emit_failure("source register must be CL" ) ) -#define _ROTSHIBrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ - (_REXBrm(RS, MB, MI), _O_r_X (0xd2 ,OP ,MD,MB,MI,MS )) : \ - x86_emit_failure("source register must be CL" ) ) - -#define _ROTSHIWir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_d16(), _REXLrr(0, RD), _O_Mrm (0xd1 ,_b11,OP,_r2(RD) )) : \ - (_d16(), _REXLrr(0, RD), _O_Mrm_B (0xc1 ,_b11,OP,_r2(RD) ,_u8(IM))) ) -#define _ROTSHIWim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_d16(), _REXLrm(0, MB, MI), _O_r_X (0xd1 ,OP ,MD,MB,MI,MS )) : \ - (_d16(), _REXLrm(0, MB, MI), _O_r_X_B (0xc1 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) -#define _ROTSHIWrr(OP,RS,RD) (((RS) == X86_CL) ? \ - (_d16(), _REXLrr(RS, RD), _O_Mrm (0xd3 ,_b11,OP,_r2(RD) )) : \ - x86_emit_failure("source register must be CL" ) ) -#define _ROTSHIWrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ - (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0xd3 ,OP ,MD,MB,MI,MS )) : \ - x86_emit_failure("source register must be CL" ) ) - -#define _ROTSHILir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_REXLrr(0, RD), _O_Mrm (0xd1 ,_b11,OP,_r4(RD) )) : \ - (_REXLrr(0, RD), _O_Mrm_B (0xc1 ,_b11,OP,_r4(RD) ,_u8(IM))) ) -#define _ROTSHILim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_REXLrm(0, MB, MI), _O_r_X (0xd1 ,OP ,MD,MB,MI,MS )) : \ - (_REXLrm(0, MB, MI), _O_r_X_B (0xc1 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) -#define _ROTSHILrr(OP,RS,RD) (((RS) == X86_CL) ? \ - (_REXLrr(RS, RD), _O_Mrm (0xd3 ,_b11,OP,_r4(RD) )) : \ - x86_emit_failure("source register must be CL" ) ) -#define _ROTSHILrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ - (_REXLrm(RS, MB, MI), _O_r_X (0xd3 ,OP ,MD,MB,MI,MS )) : \ - x86_emit_failure("source register must be CL" ) ) - -#define _ROTSHIQir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_REXQrr(0, RD), _O_Mrm (0xd1 ,_b11,OP,_r8(RD) )) : \ - (_REXQrr(0, RD), _O_Mrm_B (0xc1 ,_b11,OP,_r8(RD) ,_u8(IM))) ) -#define _ROTSHIQim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ - (_REXQrm(0, MB, MI), _O_r_X (0xd1 ,OP ,MD,MB,MI,MS )) : \ - (_REXQrm(0, MB, MI), _O_r_X_B (0xc1 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) -#define _ROTSHIQrr(OP,RS,RD) (((RS) == X86_CL) ? \ - (_REXQrr(RS, RD), _O_Mrm (0xd3 ,_b11,OP,_r8(RD) )) : \ - x86_emit_failure("source register must be CL" ) ) -#define _ROTSHIQrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ - (_REXQrm(RS, MB, MI), _O_r_X (0xd3 ,OP ,MD,MB,MI,MS )) : \ - x86_emit_failure("source register must be CL" ) ) - -#define ROLBir(IM, RD) _ROTSHIBir(X86_ROL, IM, RD) -#define ROLBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_ROL, IM, MD, MB, MI, MS) -#define ROLBrr(RS, RD) _ROTSHIBrr(X86_ROL, RS, RD) -#define ROLBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_ROL, RS, MD, MB, MI, MS) - -#define ROLWir(IM, RD) _ROTSHIWir(X86_ROL, IM, RD) -#define ROLWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_ROL, IM, MD, MB, MI, MS) -#define ROLWrr(RS, RD) _ROTSHIWrr(X86_ROL, RS, RD) -#define ROLWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_ROL, RS, MD, MB, MI, MS) - -#define ROLLir(IM, RD) _ROTSHILir(X86_ROL, IM, RD) -#define ROLLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_ROL, IM, MD, MB, MI, MS) -#define ROLLrr(RS, RD) _ROTSHILrr(X86_ROL, RS, RD) -#define ROLLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_ROL, RS, MD, MB, MI, MS) - -#define ROLQir(IM, RD) _ROTSHIQir(X86_ROL, IM, RD) -#define ROLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_ROL, IM, MD, MB, MI, MS) -#define ROLQrr(RS, RD) _ROTSHIQrr(X86_ROL, RS, RD) -#define ROLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_ROL, RS, MD, MB, MI, MS) - -#define RORBir(IM, RD) _ROTSHIBir(X86_ROR, IM, RD) -#define RORBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_ROR, IM, MD, MB, MI, MS) -#define RORBrr(RS, RD) _ROTSHIBrr(X86_ROR, RS, RD) -#define RORBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_ROR, RS, MD, MB, MI, MS) - -#define RORWir(IM, RD) _ROTSHIWir(X86_ROR, IM, RD) -#define RORWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_ROR, IM, MD, MB, MI, MS) -#define RORWrr(RS, RD) _ROTSHIWrr(X86_ROR, RS, RD) -#define RORWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_ROR, RS, MD, MB, MI, MS) - -#define RORLir(IM, RD) _ROTSHILir(X86_ROR, IM, RD) -#define RORLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_ROR, IM, MD, MB, MI, MS) -#define RORLrr(RS, RD) _ROTSHILrr(X86_ROR, RS, RD) -#define RORLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_ROR, RS, MD, MB, MI, MS) - -#define RORQir(IM, RD) _ROTSHIQir(X86_ROR, IM, RD) -#define RORQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_ROR, IM, MD, MB, MI, MS) -#define RORQrr(RS, RD) _ROTSHIQrr(X86_ROR, RS, RD) -#define RORQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_ROR, RS, MD, MB, MI, MS) - -#define RCLBir(IM, RD) _ROTSHIBir(X86_RCL, IM, RD) -#define RCLBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_RCL, IM, MD, MB, MI, MS) -#define RCLBrr(RS, RD) _ROTSHIBrr(X86_RCL, RS, RD) -#define RCLBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_RCL, RS, MD, MB, MI, MS) - -#define RCLWir(IM, RD) _ROTSHIWir(X86_RCL, IM, RD) -#define RCLWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_RCL, IM, MD, MB, MI, MS) -#define RCLWrr(RS, RD) _ROTSHIWrr(X86_RCL, RS, RD) -#define RCLWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_RCL, RS, MD, MB, MI, MS) - -#define RCLLir(IM, RD) _ROTSHILir(X86_RCL, IM, RD) -#define RCLLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_RCL, IM, MD, MB, MI, MS) -#define RCLLrr(RS, RD) _ROTSHILrr(X86_RCL, RS, RD) -#define RCLLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_RCL, RS, MD, MB, MI, MS) - -#define RCLQir(IM, RD) _ROTSHIQir(X86_RCL, IM, RD) -#define RCLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_RCL, IM, MD, MB, MI, MS) -#define RCLQrr(RS, RD) _ROTSHIQrr(X86_RCL, RS, RD) -#define RCLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_RCL, RS, MD, MB, MI, MS) - -#define RCRBir(IM, RD) _ROTSHIBir(X86_RCR, IM, RD) -#define RCRBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_RCR, IM, MD, MB, MI, MS) -#define RCRBrr(RS, RD) _ROTSHIBrr(X86_RCR, RS, RD) -#define RCRBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_RCR, RS, MD, MB, MI, MS) - -#define RCRWir(IM, RD) _ROTSHIWir(X86_RCR, IM, RD) -#define RCRWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_RCR, IM, MD, MB, MI, MS) -#define RCRWrr(RS, RD) _ROTSHIWrr(X86_RCR, RS, RD) -#define RCRWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_RCR, RS, MD, MB, MI, MS) - -#define RCRLir(IM, RD) _ROTSHILir(X86_RCR, IM, RD) -#define RCRLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_RCR, IM, MD, MB, MI, MS) -#define RCRLrr(RS, RD) _ROTSHILrr(X86_RCR, RS, RD) -#define RCRLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_RCR, RS, MD, MB, MI, MS) - -#define RCRQir(IM, RD) _ROTSHIQir(X86_RCR, IM, RD) -#define RCRQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_RCR, IM, MD, MB, MI, MS) -#define RCRQrr(RS, RD) _ROTSHIQrr(X86_RCR, RS, RD) -#define RCRQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_RCR, RS, MD, MB, MI, MS) - -#define SHLBir(IM, RD) _ROTSHIBir(X86_SHL, IM, RD) -#define SHLBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_SHL, IM, MD, MB, MI, MS) -#define SHLBrr(RS, RD) _ROTSHIBrr(X86_SHL, RS, RD) -#define SHLBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_SHL, RS, MD, MB, MI, MS) - -#define SHLWir(IM, RD) _ROTSHIWir(X86_SHL, IM, RD) -#define SHLWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_SHL, IM, MD, MB, MI, MS) -#define SHLWrr(RS, RD) _ROTSHIWrr(X86_SHL, RS, RD) -#define SHLWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_SHL, RS, MD, MB, MI, MS) - -#define SHLLir(IM, RD) _ROTSHILir(X86_SHL, IM, RD) -#define SHLLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_SHL, IM, MD, MB, MI, MS) -#define SHLLrr(RS, RD) _ROTSHILrr(X86_SHL, RS, RD) -#define SHLLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_SHL, RS, MD, MB, MI, MS) - -#define SHLQir(IM, RD) _ROTSHIQir(X86_SHL, IM, RD) -#define SHLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SHL, IM, MD, MB, MI, MS) -#define SHLQrr(RS, RD) _ROTSHIQrr(X86_SHL, RS, RD) -#define SHLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SHL, RS, MD, MB, MI, MS) - -#define SHRBir(IM, RD) _ROTSHIBir(X86_SHR, IM, RD) -#define SHRBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_SHR, IM, MD, MB, MI, MS) -#define SHRBrr(RS, RD) _ROTSHIBrr(X86_SHR, RS, RD) -#define SHRBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_SHR, RS, MD, MB, MI, MS) - -#define SHRWir(IM, RD) _ROTSHIWir(X86_SHR, IM, RD) -#define SHRWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_SHR, IM, MD, MB, MI, MS) -#define SHRWrr(RS, RD) _ROTSHIWrr(X86_SHR, RS, RD) -#define SHRWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_SHR, RS, MD, MB, MI, MS) - -#define SHRLir(IM, RD) _ROTSHILir(X86_SHR, IM, RD) -#define SHRLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_SHR, IM, MD, MB, MI, MS) -#define SHRLrr(RS, RD) _ROTSHILrr(X86_SHR, RS, RD) -#define SHRLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_SHR, RS, MD, MB, MI, MS) - -#define SHRQir(IM, RD) _ROTSHIQir(X86_SHR, IM, RD) -#define SHRQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SHR, IM, MD, MB, MI, MS) -#define SHRQrr(RS, RD) _ROTSHIQrr(X86_SHR, RS, RD) -#define SHRQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SHR, RS, MD, MB, MI, MS) - -#define SALBir SHLBir -#define SALBim SHLBim -#define SALBrr SHLBrr -#define SALBrm SHLBrm - -#define SALWir SHLWir -#define SALWim SHLWim -#define SALWrr SHLWrr -#define SALWrm SHLWrm - -#define SALLir SHLLir -#define SALLim SHLLim -#define SALLrr SHLLrr -#define SALLrm SHLLrm - -#define SALQir SHLQir -#define SALQim SHLQim -#define SALQrr SHLQrr -#define SALQrm SHLQrm - -#define SARBir(IM, RD) _ROTSHIBir(X86_SAR, IM, RD) -#define SARBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_SAR, IM, MD, MB, MI, MS) -#define SARBrr(RS, RD) _ROTSHIBrr(X86_SAR, RS, RD) -#define SARBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_SAR, RS, MD, MB, MI, MS) - -#define SARWir(IM, RD) _ROTSHIWir(X86_SAR, IM, RD) -#define SARWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_SAR, IM, MD, MB, MI, MS) -#define SARWrr(RS, RD) _ROTSHIWrr(X86_SAR, RS, RD) -#define SARWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_SAR, RS, MD, MB, MI, MS) - -#define SARLir(IM, RD) _ROTSHILir(X86_SAR, IM, RD) -#define SARLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_SAR, IM, MD, MB, MI, MS) -#define SARLrr(RS, RD) _ROTSHILrr(X86_SAR, RS, RD) -#define SARLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_SAR, RS, MD, MB, MI, MS) - -#define SARQir(IM, RD) _ROTSHIQir(X86_SAR, IM, RD) -#define SARQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SAR, IM, MD, MB, MI, MS) -#define SARQrr(RS, RD) _ROTSHIQrr(X86_SAR, RS, RD) -#define SARQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SAR, RS, MD, MB, MI, MS) - - -/* --- Bit test instructions ----------------------------------------------- */ - -enum { - X86_BT = 4, - X86_BTS = 5, - X86_BTR = 6, - X86_BTC = 7, -}; - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define _BTWir(OP, IM, RD) (_d16(), _REXLrr(0, RD), _OO_Mrm_B (0x0fba ,_b11,OP ,_r2(RD) ,_u8(IM))) -#define _BTWim(OP, IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _OO_r_X_B (0x0fba ,OP ,MD,MB,MI,MS ,_u8(IM))) -#define _BTWrr(OP, RS, RD) (_d16(), _REXLrr(RS, RD), _OO_Mrm (0x0f83|((OP)<<3),_b11,_r2(RS),_r2(RD) )) -#define _BTWrm(OP, RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _OO_r_X (0x0f83|((OP)<<3) ,_r2(RS) ,MD,MB,MI,MS )) - -#define _BTLir(OP, IM, RD) (_REXLrr(0, RD), _OO_Mrm_B (0x0fba ,_b11,OP ,_r4(RD) ,_u8(IM))) -#define _BTLim(OP, IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _OO_r_X_B (0x0fba ,OP ,MD,MB,MI,MS ,_u8(IM))) -#define _BTLrr(OP, RS, RD) (_REXLrr(RS, RD), _OO_Mrm (0x0f83|((OP)<<3),_b11,_r4(RS),_r4(RD) )) -#define _BTLrm(OP, RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0f83|((OP)<<3) ,_r4(RS) ,MD,MB,MI,MS )) - -#define _BTQir(OP, IM, RD) (_REXQrr(0, RD), _OO_Mrm_B (0x0fba ,_b11,OP ,_r8(RD) ,_u8(IM))) -#define _BTQim(OP, IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _OO_r_X_B (0x0fba ,OP ,MD,MB,MI,MS ,_u8(IM))) -#define _BTQrr(OP, RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0f83|((OP)<<3),_b11,_r8(RS),_r8(RD) )) -#define _BTQrm(OP, RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f83|((OP)<<3) ,_r8(RS) ,MD,MB,MI,MS )) - -#define BTWir(IM, RD) _BTWir(X86_BT, IM, RD) -#define BTWim(IM, MD, MB, MI, MS) _BTWim(X86_BT, IM, MD, MB, MI, MS) -#define BTWrr(RS, RD) _BTWrr(X86_BT, RS, RD) -#define BTWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BT, RS, MD, MB, MI, MS) - -#define BTLir(IM, RD) _BTLir(X86_BT, IM, RD) -#define BTLim(IM, MD, MB, MI, MS) _BTLim(X86_BT, IM, MD, MB, MI, MS) -#define BTLrr(RS, RD) _BTLrr(X86_BT, RS, RD) -#define BTLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BT, RS, MD, MB, MI, MS) - -#define BTQir(IM, RD) _BTQir(X86_BT, IM, RD) -#define BTQim(IM, MD, MB, MI, MS) _BTQim(X86_BT, IM, MD, MB, MI, MS) -#define BTQrr(RS, RD) _BTQrr(X86_BT, RS, RD) -#define BTQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BT, RS, MD, MB, MI, MS) - -#define BTCWir(IM, RD) _BTWir(X86_BTC, IM, RD) -#define BTCWim(IM, MD, MB, MI, MS) _BTWim(X86_BTC, IM, MD, MB, MI, MS) -#define BTCWrr(RS, RD) _BTWrr(X86_BTC, RS, RD) -#define BTCWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BTC, RS, MD, MB, MI, MS) - -#define BTCLir(IM, RD) _BTLir(X86_BTC, IM, RD) -#define BTCLim(IM, MD, MB, MI, MS) _BTLim(X86_BTC, IM, MD, MB, MI, MS) -#define BTCLrr(RS, RD) _BTLrr(X86_BTC, RS, RD) -#define BTCLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BTC, RS, MD, MB, MI, MS) - -#define BTCQir(IM, RD) _BTQir(X86_BTC, IM, RD) -#define BTCQim(IM, MD, MB, MI, MS) _BTQim(X86_BTC, IM, MD, MB, MI, MS) -#define BTCQrr(RS, RD) _BTQrr(X86_BTC, RS, RD) -#define BTCQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTC, RS, MD, MB, MI, MS) - -#define BTRWir(IM, RD) _BTWir(X86_BTR, IM, RD) -#define BTRWim(IM, MD, MB, MI, MS) _BTWim(X86_BTR, IM, MD, MB, MI, MS) -#define BTRWrr(RS, RD) _BTWrr(X86_BTR, RS, RD) -#define BTRWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BTR, RS, MD, MB, MI, MS) - -#define BTRLir(IM, RD) _BTLir(X86_BTR, IM, RD) -#define BTRLim(IM, MD, MB, MI, MS) _BTLim(X86_BTR, IM, MD, MB, MI, MS) -#define BTRLrr(RS, RD) _BTLrr(X86_BTR, RS, RD) -#define BTRLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BTR, RS, MD, MB, MI, MS) - -#define BTRQir(IM, RD) _BTQir(X86_BTR, IM, RD) -#define BTRQim(IM, MD, MB, MI, MS) _BTQim(X86_BTR, IM, MD, MB, MI, MS) -#define BTRQrr(RS, RD) _BTQrr(X86_BTR, RS, RD) -#define BTRQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTR, RS, MD, MB, MI, MS) - -#define BTSWir(IM, RD) _BTWir(X86_BTS, IM, RD) -#define BTSWim(IM, MD, MB, MI, MS) _BTWim(X86_BTS, IM, MD, MB, MI, MS) -#define BTSWrr(RS, RD) _BTWrr(X86_BTS, RS, RD) -#define BTSWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BTS, RS, MD, MB, MI, MS) - -#define BTSLir(IM, RD) _BTLir(X86_BTS, IM, RD) -#define BTSLim(IM, MD, MB, MI, MS) _BTLim(X86_BTS, IM, MD, MB, MI, MS) -#define BTSLrr(RS, RD) _BTLrr(X86_BTS, RS, RD) -#define BTSLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BTS, RS, MD, MB, MI, MS) - -#define BTSQir(IM, RD) _BTQir(X86_BTS, IM, RD) -#define BTSQim(IM, MD, MB, MI, MS) _BTQim(X86_BTS, IM, MD, MB, MI, MS) -#define BTSQrr(RS, RD) _BTQrr(X86_BTS, RS, RD) -#define BTSQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTS, RS, MD, MB, MI, MS) - - -/* --- Move instructions --------------------------------------------------- */ - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define MOVBrr(RS, RD) (_REXBrr(RS, RD), _O_Mrm (0x88 ,_b11,_r1(RS),_r1(RD) )) -#define MOVBmr(MD, MB, MI, MS, RD) (_REXBmr(MB, MI, RD), _O_r_X (0x8a ,_r1(RD) ,MD,MB,MI,MS )) -#define MOVBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (0x88 ,_r1(RS) ,MD,MB,MI,MS )) -#define MOVBir(IM, R) (_REXBrr(0, R), _Or_B (0xb0,_r1(R) ,_su8(IM))) -#define MOVBim(IM, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_X_B (0xc6 ,MD,MB,MI,MS ,_su8(IM))) - -#define MOVWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (0x89 ,_b11,_r2(RS),_r2(RD) )) -#define MOVWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _O_r_X (0x8b ,_r2(RD) ,MD,MB,MI,MS )) -#define MOVWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0x89 ,_r2(RS) ,MD,MB,MI,MS )) -#define MOVWir(IM, R) (_d16(), _REXLrr(0, R), _Or_W (0xb8,_r2(R) ,_su16(IM))) -#define MOVWim(IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_X_W (0xc7 ,MD,MB,MI,MS ,_su16(IM))) - -#define MOVLrr(RS, RD) (_REXLrr(RS, RD), _O_Mrm (0x89 ,_b11,_r4(RS),_r4(RD) )) -#define MOVLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (0x8b ,_r4(RD) ,MD,MB,MI,MS )) -#define MOVLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (0x89 ,_r4(RS) ,MD,MB,MI,MS )) -#define MOVLir(IM, R) (_REXLrr(0, R), _Or_L (0xb8,_r4(R) ,IM )) -#define MOVLim(IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_X_L (0xc7 ,MD,MB,MI,MS ,IM )) - -#define MOVQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x89 ,_b11,_r8(RS),_r8(RD) )) -#define MOVQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (0x8b ,_r8(RD) ,MD,MB,MI,MS )) -#define MOVQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x89 ,_r8(RS) ,MD,MB,MI,MS )) -#define MOVQir(IM, R) (_REXQrr(0, R), _Or_Q (0xb8,_r8(R) ,IM )) -#define MOVQim(IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_X_L (0xc7 ,MD,MB,MI,MS ,IM )) - - -/* --- Unary and Multiply/Divide instructions ------------------------------ */ - -enum { - X86_NOT = 2, - X86_NEG = 3, - X86_MUL = 4, - X86_IMUL = 5, - X86_DIV = 6, - X86_IDIV = 7, -}; - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define _UNARYBr(OP, RS) (_REXBrr(0, RS), _O_Mrm (0xf6 ,_b11,OP ,_r1(RS) )) -#define _UNARYBm(OP, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X (0xf6 ,OP ,MD,MB,MI,MS )) -#define _UNARYWr(OP, RS) (_d16(), _REXLrr(0, RS), _O_Mrm (0xf7 ,_b11,OP ,_r2(RS) )) -#define _UNARYWm(OP, MD, MB, MI, MS) (_d16(), _REXLmr(MB, MI, 0), _O_r_X (0xf7 ,OP ,MD,MB,MI,MS )) -#define _UNARYLr(OP, RS) (_REXLrr(0, RS), _O_Mrm (0xf7 ,_b11,OP ,_r4(RS) )) -#define _UNARYLm(OP, MD, MB, MI, MS) (_REXLmr(MB, MI, 0), _O_r_X (0xf7 ,OP ,MD,MB,MI,MS )) -#define _UNARYQr(OP, RS) (_REXQrr(0, RS), _O_Mrm (0xf7 ,_b11,OP ,_r8(RS) )) -#define _UNARYQm(OP, MD, MB, MI, MS) (_REXQmr(MB, MI, 0), _O_r_X (0xf7 ,OP ,MD,MB,MI,MS )) - -#define NOTBr(RS) _UNARYBr(X86_NOT, RS) -#define NOTBm(MD, MB, MI, MS) _UNARYBm(X86_NOT, MD, MB, MI, MS) -#define NOTWr(RS) _UNARYWr(X86_NOT, RS) -#define NOTWm(MD, MB, MI, MS) _UNARYWm(X86_NOT, MD, MB, MI, MS) -#define NOTLr(RS) _UNARYLr(X86_NOT, RS) -#define NOTLm(MD, MB, MI, MS) _UNARYLm(X86_NOT, MD, MB, MI, MS) -#define NOTQr(RS) _UNARYQr(X86_NOT, RS) -#define NOTQm(MD, MB, MI, MS) _UNARYQm(X86_NOT, MD, MB, MI, MS) - -#define NEGBr(RS) _UNARYBr(X86_NEG, RS) -#define NEGBm(MD, MB, MI, MS) _UNARYBm(X86_NEG, MD, MB, MI, MS) -#define NEGWr(RS) _UNARYWr(X86_NEG, RS) -#define NEGWm(MD, MB, MI, MS) _UNARYWm(X86_NEG, MD, MB, MI, MS) -#define NEGLr(RS) _UNARYLr(X86_NEG, RS) -#define NEGLm(MD, MB, MI, MS) _UNARYLm(X86_NEG, MD, MB, MI, MS) -#define NEGQr(RS) _UNARYQr(X86_NEG, RS) -#define NEGQm(MD, MB, MI, MS) _UNARYQm(X86_NEG, MD, MB, MI, MS) - -#define MULBr(RS) _UNARYBr(X86_MUL, RS) -#define MULBm(MD, MB, MI, MS) _UNARYBm(X86_MUL, MD, MB, MI, MS) -#define MULWr(RS) _UNARYWr(X86_MUL, RS) -#define MULWm(MD, MB, MI, MS) _UNARYWm(X86_MUL, MD, MB, MI, MS) -#define MULLr(RS) _UNARYLr(X86_MUL, RS) -#define MULLm(MD, MB, MI, MS) _UNARYLm(X86_MUL, MD, MB, MI, MS) -#define MULQr(RS) _UNARYQr(X86_MUL, RS) -#define MULQm(MD, MB, MI, MS) _UNARYQm(X86_MUL, MD, MB, MI, MS) - -#define IMULBr(RS) _UNARYBr(X86_IMUL, RS) -#define IMULBm(MD, MB, MI, MS) _UNARYBm(X86_IMUL, MD, MB, MI, MS) -#define IMULWr(RS) _UNARYWr(X86_IMUL, RS) -#define IMULWm(MD, MB, MI, MS) _UNARYWm(X86_IMUL, MD, MB, MI, MS) -#define IMULLr(RS) _UNARYLr(X86_IMUL, RS) -#define IMULLm(MD, MB, MI, MS) _UNARYLm(X86_IMUL, MD, MB, MI, MS) -#define IMULQr(RS) _UNARYQr(X86_IMUL, RS) -#define IMULQm(MD, MB, MI, MS) _UNARYQm(X86_IMUL, MD, MB, MI, MS) - -#define DIVBr(RS) _UNARYBr(X86_DIV, RS) -#define DIVBm(MD, MB, MI, MS) _UNARYBm(X86_DIV, MD, MB, MI, MS) -#define DIVWr(RS) _UNARYWr(X86_DIV, RS) -#define DIVWm(MD, MB, MI, MS) _UNARYWm(X86_DIV, MD, MB, MI, MS) -#define DIVLr(RS) _UNARYLr(X86_DIV, RS) -#define DIVLm(MD, MB, MI, MS) _UNARYLm(X86_DIV, MD, MB, MI, MS) -#define DIVQr(RS) _UNARYQr(X86_DIV, RS) -#define DIVQm(MD, MB, MI, MS) _UNARYQm(X86_DIV, MD, MB, MI, MS) - -#define IDIVBr(RS) _UNARYBr(X86_IDIV, RS) -#define IDIVBm(MD, MB, MI, MS) _UNARYBm(X86_IDIV, MD, MB, MI, MS) -#define IDIVWr(RS) _UNARYWr(X86_IDIV, RS) -#define IDIVWm(MD, MB, MI, MS) _UNARYWm(X86_IDIV, MD, MB, MI, MS) -#define IDIVLr(RS) _UNARYLr(X86_IDIV, RS) -#define IDIVLm(MD, MB, MI, MS) _UNARYLm(X86_IDIV, MD, MB, MI, MS) -#define IDIVQr(RS) _UNARYQr(X86_IDIV, RS) -#define IDIVQm(MD, MB, MI, MS) _UNARYQm(X86_IDIV, MD, MB, MI, MS) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define IMULWrr(RS, RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r2(RD),_r2(RS) )) -#define IMULWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0faf ,_r2(RD) ,MD,MB,MI,MS )) - -#define IMULWirr(IM,RS,RD) (_d16(), _REXLrr(RS, RD), _Os_Mrm_sW (0x69 ,_b11,_r2(RS),_r2(RD) ,_su16(IM) )) -#define IMULWimr(IM,MD,MB,MI,MS,RD) (_d16(), _REXLmr(MB, MI, RD), _Os_r_X_sW (0x69 ,_r2(RD) ,MD,MB,MI,MS ,_su16(IM) )) - -#define IMULLir(IM, RD) (_REXLrr(0, RD), _Os_Mrm_sL (0x69 ,_b11,_r4(RD),_r4(RD) ,IM )) -#define IMULLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r4(RD),_r4(RS) )) -#define IMULLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0faf ,_r4(RD) ,MD,MB,MI,MS )) - -#define IMULQir(IM, RD) (_REXQrr(0, RD), _Os_Mrm_sL (0x69 ,_b11,_r8(RD),_r8(RD) ,IM )) -#define IMULQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r8(RD),_r8(RS) )) -#define IMULQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0faf ,_r8(RD) ,MD,MB,MI,MS )) - -#define IMULLirr(IM,RS,RD) (_REXLrr(RS, RD), _Os_Mrm_sL (0x69 ,_b11,_r4(RS),_r4(RD) ,IM )) -#define IMULLimr(IM,MD,MB,MI,MS,RD) (_REXLmr(MB, MI, RD), _Os_r_X_sL (0x69 ,_r4(RD) ,MD,MB,MI,MS ,IM )) - -#define IMULQirr(IM,RS,RD) (_REXQrr(RS, RD), _Os_Mrm_sL (0x69 ,_b11,_r8(RS),_r8(RD) ,IM )) -#define IMULQimr(IM,MD,MB,MI,MS,RD) (_REXQmr(MB, MI, RD), _Os_r_X_sL (0x69 ,_r8(RD) ,MD,MB,MI,MS ,IM )) - - -/* --- Control Flow related instructions ----------------------------------- */ - -enum { - X86_CC_O = 0x0, - X86_CC_NO = 0x1, - X86_CC_NAE = 0x2, - X86_CC_B = 0x2, - X86_CC_C = 0x2, - X86_CC_AE = 0x3, - X86_CC_NB = 0x3, - X86_CC_NC = 0x3, - X86_CC_E = 0x4, - X86_CC_Z = 0x4, - X86_CC_NE = 0x5, - X86_CC_NZ = 0x5, - X86_CC_BE = 0x6, - X86_CC_NA = 0x6, - X86_CC_A = 0x7, - X86_CC_NBE = 0x7, - X86_CC_S = 0x8, - X86_CC_NS = 0x9, - X86_CC_P = 0xa, - X86_CC_PE = 0xa, - X86_CC_NP = 0xb, - X86_CC_PO = 0xb, - X86_CC_L = 0xc, - X86_CC_NGE = 0xc, - X86_CC_GE = 0xd, - X86_CC_NL = 0xd, - X86_CC_LE = 0xe, - X86_CC_NG = 0xe, - X86_CC_G = 0xf, - X86_CC_NLE = 0xf, -}; - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -// FIXME: no prefix is availble to encode a 32-bit operand size in 64-bit mode -#define CALLm(M) _O_D32 (0xe8 ,(int)(M) ) -#define _CALLLsr(R) (_REXLrr(0, R), _O_Mrm (0xff ,_b11,_b010,_r4(R) )) -#define _CALLQsr(R) (_REXLrr(0, R), _O_Mrm (0xff ,_b11,_b010,_r8(R) )) -#define CALLsr(R) ( X86_TARGET_64BIT ? _CALLQsr(R) : _CALLLsr(R)) -#define CALLsm(D,B,I,S) (_REXLrm(0, B, I), _O_r_X (0xff ,_b010 ,(int)(D),B,I,S )) - -// FIXME: no prefix is availble to encode a 32-bit operand size in 64-bit mode -#define JMPSm(M) _O_D8 (0xeb ,(int)(M) ) -#define JMPm(M) _O_D32 (0xe9 ,(int)(M) ) -#define _JMPLsr(R) (_REXLrr(0, R), _O_Mrm (0xff ,_b11,_b100,_r4(R) )) -#define _JMPQsr(R) (_REXLrr(0, R), _O_Mrm (0xff ,_b11,_b100,_r8(R) )) -#define JMPsr(R) ( X86_TARGET_64BIT ? _JMPQsr(R) : _JMPLsr(R)) -#define JMPsm(D,B,I,S) (_REXLrm(0, B, I), _O_r_X (0xff ,_b100 ,(int)(D),B,I,S )) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ -#define JCCSii(CC, D) _O_B (0x70|(CC) ,(_sc)(int)(D) ) -#define JCCSim(CC, D) _O_D8 (0x70|(CC) ,(int)(D) ) -#define JOSm(D) JCCSim(X86_CC_O, D) -#define JNOSm(D) JCCSim(X86_CC_NO, D) -#define JBSm(D) JCCSim(X86_CC_B, D) -#define JNAESm(D) JCCSim(X86_CC_NAE, D) -#define JNBSm(D) JCCSim(X86_CC_NB, D) -#define JAESm(D) JCCSim(X86_CC_AE, D) -#define JESm(D) JCCSim(X86_CC_E, D) -#define JZSm(D) JCCSim(X86_CC_Z, D) -#define JNESm(D) JCCSim(X86_CC_NE, D) -#define JNZSm(D) JCCSim(X86_CC_NZ, D) -#define JBESm(D) JCCSim(X86_CC_BE, D) -#define JNASm(D) JCCSim(X86_CC_NA, D) -#define JNBESm(D) JCCSim(X86_CC_NBE, D) -#define JASm(D) JCCSim(X86_CC_A, D) -#define JSSm(D) JCCSim(X86_CC_S, D) -#define JNSSm(D) JCCSim(X86_CC_NS, D) -#define JPSm(D) JCCSim(X86_CC_P, D) -#define JPESm(D) JCCSim(X86_CC_PE, D) -#define JNPSm(D) JCCSim(X86_CC_NP, D) -#define JPOSm(D) JCCSim(X86_CC_PO, D) -#define JLSm(D) JCCSim(X86_CC_L, D) -#define JNGESm(D) JCCSim(X86_CC_NGE, D) -#define JNLSm(D) JCCSim(X86_CC_NL, D) -#define JGESm(D) JCCSim(X86_CC_GE, D) -#define JLESm(D) JCCSim(X86_CC_LE, D) -#define JNGSm(D) JCCSim(X86_CC_NG, D) -#define JNLESm(D) JCCSim(X86_CC_NLE, D) -#define JGSm(D) JCCSim(X86_CC_G, D) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ -#define JCCii(CC, D) _OO_L (0x0f80|(CC) ,(int)(D) ) -#define JCCim(CC, D) _OO_D32 (0x0f80|(CC) ,(int)(D) ) -#define JOm(D) JCCim(X86_CC_O, D) -#define JNOm(D) JCCim(X86_CC_NO, D) -#define JBm(D) JCCim(X86_CC_B, D) -#define JNAEm(D) JCCim(X86_CC_NAE, D) -#define JNBm(D) JCCim(X86_CC_NB, D) -#define JAEm(D) JCCim(X86_CC_AE, D) -#define JEm(D) JCCim(X86_CC_E, D) -#define JZm(D) JCCim(X86_CC_Z, D) -#define JNEm(D) JCCim(X86_CC_NE, D) -#define JNZm(D) JCCim(X86_CC_NZ, D) -#define JBEm(D) JCCim(X86_CC_BE, D) -#define JNAm(D) JCCim(X86_CC_NA, D) -#define JNBEm(D) JCCim(X86_CC_NBE, D) -#define JAm(D) JCCim(X86_CC_A, D) -#define JSm(D) JCCim(X86_CC_S, D) -#define JNSm(D) JCCim(X86_CC_NS, D) -#define JPm(D) JCCim(X86_CC_P, D) -#define JPEm(D) JCCim(X86_CC_PE, D) -#define JNPm(D) JCCim(X86_CC_NP, D) -#define JPOm(D) JCCim(X86_CC_PO, D) -#define JLm(D) JCCim(X86_CC_L, D) -#define JNGEm(D) JCCim(X86_CC_NGE, D) -#define JNLm(D) JCCim(X86_CC_NL, D) -#define JGEm(D) JCCim(X86_CC_GE, D) -#define JLEm(D) JCCim(X86_CC_LE, D) -#define JNGm(D) JCCim(X86_CC_NG, D) -#define JNLEm(D) JCCim(X86_CC_NLE, D) -#define JGm(D) JCCim(X86_CC_G, D) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ -#define SETCCir(CC, RD) (_REXBrr(0, RD), _OO_Mrm (0x0f90|(CC) ,_b11,_b000,_r1(RD) )) -#define SETOr(RD) SETCCir(X86_CC_O, RD) -#define SETNOr(RD) SETCCir(X86_CC_NO, RD) -#define SETBr(RD) SETCCir(X86_CC_B, RD) -#define SETNAEr(RD) SETCCir(X86_CC_NAE, RD) -#define SETNBr(RD) SETCCir(X86_CC_NB, RD) -#define SETAEr(RD) SETCCir(X86_CC_AE, RD) -#define SETEr(RD) SETCCir(X86_CC_E, RD) -#define SETZr(RD) SETCCir(X86_CC_Z, RD) -#define SETNEr(RD) SETCCir(X86_CC_NE, RD) -#define SETNZr(RD) SETCCir(X86_CC_NZ, RD) -#define SETBEr(RD) SETCCir(X86_CC_BE, RD) -#define SETNAr(RD) SETCCir(X86_CC_NA, RD) -#define SETNBEr(RD) SETCCir(X86_CC_NBE, RD) -#define SETAr(RD) SETCCir(X86_CC_A, RD) -#define SETSr(RD) SETCCir(X86_CC_S, RD) -#define SETNSr(RD) SETCCir(X86_CC_NS, RD) -#define SETPr(RD) SETCCir(X86_CC_P, RD) -#define SETPEr(RD) SETCCir(X86_CC_PE, RD) -#define SETNPr(RD) SETCCir(X86_CC_NP, RD) -#define SETPOr(RD) SETCCir(X86_CC_PO, RD) -#define SETLr(RD) SETCCir(X86_CC_L, RD) -#define SETNGEr(RD) SETCCir(X86_CC_NGE, RD) -#define SETNLr(RD) SETCCir(X86_CC_NL, RD) -#define SETGEr(RD) SETCCir(X86_CC_GE, RD) -#define SETLEr(RD) SETCCir(X86_CC_LE, RD) -#define SETNGr(RD) SETCCir(X86_CC_NG, RD) -#define SETNLEr(RD) SETCCir(X86_CC_NLE, RD) -#define SETGr(RD) SETCCir(X86_CC_G, RD) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ -#define SETCCim(CC,MD,MB,MI,MS) (_REXBrm(0, MB, MI), _OO_r_X (0x0f90|(CC) ,_b000 ,MD,MB,MI,MS )) -#define SETOm(D, B, I, S) SETCCim(X86_CC_O, D, B, I, S) -#define SETNOm(D, B, I, S) SETCCim(X86_CC_NO, D, B, I, S) -#define SETBm(D, B, I, S) SETCCim(X86_CC_B, D, B, I, S) -#define SETNAEm(D, B, I, S) SETCCim(X86_CC_NAE, D, B, I, S) -#define SETNBm(D, B, I, S) SETCCim(X86_CC_NB, D, B, I, S) -#define SETAEm(D, B, I, S) SETCCim(X86_CC_AE, D, B, I, S) -#define SETEm(D, B, I, S) SETCCim(X86_CC_E, D, B, I, S) -#define SETZm(D, B, I, S) SETCCim(X86_CC_Z, D, B, I, S) -#define SETNEm(D, B, I, S) SETCCim(X86_CC_NE, D, B, I, S) -#define SETNZm(D, B, I, S) SETCCim(X86_CC_NZ, D, B, I, S) -#define SETBEm(D, B, I, S) SETCCim(X86_CC_BE, D, B, I, S) -#define SETNAm(D, B, I, S) SETCCim(X86_CC_NA, D, B, I, S) -#define SETNBEm(D, B, I, S) SETCCim(X86_CC_NBE, D, B, I, S) -#define SETAm(D, B, I, S) SETCCim(X86_CC_A, D, B, I, S) -#define SETSm(D, B, I, S) SETCCim(X86_CC_S, D, B, I, S) -#define SETNSm(D, B, I, S) SETCCim(X86_CC_NS, D, B, I, S) -#define SETPm(D, B, I, S) SETCCim(X86_CC_P, D, B, I, S) -#define SETPEm(D, B, I, S) SETCCim(X86_CC_PE, D, B, I, S) -#define SETNPm(D, B, I, S) SETCCim(X86_CC_NP, D, B, I, S) -#define SETPOm(D, B, I, S) SETCCim(X86_CC_PO, D, B, I, S) -#define SETLm(D, B, I, S) SETCCim(X86_CC_L, D, B, I, S) -#define SETNGEm(D, B, I, S) SETCCim(X86_CC_NGE, D, B, I, S) -#define SETNLm(D, B, I, S) SETCCim(X86_CC_NL, D, B, I, S) -#define SETGEm(D, B, I, S) SETCCim(X86_CC_GE, D, B, I, S) -#define SETLEm(D, B, I, S) SETCCim(X86_CC_LE, D, B, I, S) -#define SETNGm(D, B, I, S) SETCCim(X86_CC_NG, D, B, I, S) -#define SETNLEm(D, B, I, S) SETCCim(X86_CC_NLE, D, B, I, S) -#define SETGm(D, B, I, S) SETCCim(X86_CC_G, D, B, I, S) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ -#define CMOVWrr(CC,RS,RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r2(RD),_r2(RS) )) -#define CMOVWmr(CC,MD,MB,MI,MS,RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r2(RD) ,MD,MB,MI,MS )) -#define CMOVLrr(CC,RS,RD) (_REXLrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r4(RD),_r4(RS) )) -#define CMOVLmr(CC,MD,MB,MI,MS,RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r4(RD) ,MD,MB,MI,MS )) -#define CMOVQrr(CC,RS,RD) (_REXQrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r8(RD),_r8(RS) )) -#define CMOVQmr(CC,MD,MB,MI,MS,RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r8(RD) ,MD,MB,MI,MS )) - - -/* --- Push/Pop instructions ----------------------------------------------- */ - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define POPWr(RD) _m32only((_d16(), _Or (0x58,_r2(RD) ))) -#define POPWm(MD, MB, MI, MS) _m32only((_d16(), _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS ))) - -#define POPLr(RD) _m32only( _Or (0x58,_r4(RD) )) -#define POPLm(MD, MB, MI, MS) _m32only( _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS )) - -#define POPQr(RD) _m64only((_REXQr(RD), _Or (0x58,_r8(RD) ))) -#define POPQm(MD, MB, MI, MS) _m64only((_REXQm(MB, MI), _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS ))) - -#define PUSHWr(RS) _m32only((_d16(), _Or (0x50,_r2(RS) ))) -#define PUSHWm(MD, MB, MI, MS) _m32only((_d16(), _O_r_X (0xff, ,_b110 ,MD,MB,MI,MS ))) -#define PUSHWi(IM) _m32only((_d16(), _Os_sW (0x68 ,IM ))) - -#define PUSHLr(RS) _m32only( _Or (0x50,_r4(RS) )) -#define PUSHLm(MD, MB, MI, MS) _m32only( _O_r_X (0xff ,_b110 ,MD,MB,MI,MS )) -#define PUSHLi(IM) _m32only( _Os_sL (0x68 ,IM )) - -#define PUSHQr(RS) _m64only((_REXQr(RS), _Or (0x50,_r8(RS) ))) -#define PUSHQm(MD, MB, MI, MS) _m64only((_REXQm(MB, MI), _O_r_X (0xff ,_b110 ,MD,MB,MI,MS ))) -#define PUSHQi(IM) _m64only( _Os_sL (0x68 ,IM )) - -#define POPA() (_d16(), _O (0x61 )) -#define POPAD() _O (0x61 ) - -#define PUSHA() (_d16(), _O (0x60 )) -#define PUSHAD() _O (0x60 ) - -#define POPF() _O (0x9d ) -#define PUSHF() _O (0x9c ) - - -/* --- Test instructions --------------------------------------------------- */ - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define TESTBrr(RS, RD) (_REXBrr(RS, RD), _O_Mrm (0x84 ,_b11,_r1(RS),_r1(RD) )) -#define TESTBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (0x84 ,_r1(RS) ,MD,MB,MI,MS )) -#define TESTBir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AL) ? \ - (_REXBrr(0, RD), _O_B (0xa8 ,_u8(IM))) : \ - (_REXBrr(0, RD), _O_Mrm_B (0xf6 ,_b11,_b000 ,_r1(RD) ,_u8(IM))) ) -#define TESTBim(IM, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X_B (0xf6 ,_b000 ,MD,MB,MI,MS ,_u8(IM))) - -#define TESTWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (0x85 ,_b11,_r2(RS),_r2(RD) )) -#define TESTWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0x85 ,_r2(RS) ,MD,MB,MI,MS )) -#define TESTWir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AX) ? \ - (_d16(), _REXLrr(0, RD), _O_W (0xa9 ,_u16(IM))) : \ - (_d16(), _REXLrr(0, RD), _O_Mrm_W (0xf7 ,_b11,_b000 ,_r2(RD) ,_u16(IM))) ) -#define TESTWim(IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_r_X_W (0xf7 ,_b000 ,MD,MB,MI,MS ,_u16(IM))) - -#define TESTLrr(RS, RD) (_REXLrr(RS, RD), _O_Mrm (0x85 ,_b11,_r4(RS),_r4(RD) )) -#define TESTLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (0x85 ,_r4(RS) ,MD,MB,MI,MS )) -#define TESTLir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_EAX) ? \ - (_REXLrr(0, RD), _O_L (0xa9 ,IM )) : \ - (_REXLrr(0, RD), _O_Mrm_L (0xf7 ,_b11,_b000 ,_r4(RD) ,IM )) ) -#define TESTLim(IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X_L (0xf7 ,_b000 ,MD,MB,MI,MS ,IM )) - -#define TESTQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x85 ,_b11,_r8(RS),_r8(RD) )) -#define TESTQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x85 ,_r8(RS) ,MD,MB,MI,MS )) -#define TESTQir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_RAX) ? \ - (_REXQrr(0, RD), _O_L (0xa9 ,IM )) : \ - (_REXQrr(0, RD), _O_Mrm_L (0xf7 ,_b11,_b000 ,_r8(RD) ,IM )) ) -#define TESTQim(IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X_L (0xf7 ,_b000 ,MD,MB,MI,MS ,IM )) - - -/* --- Exchange instructions ----------------------------------------------- */ - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define CMPXCHGBrr(RS, RD) (_REXBrr(RS, RD), _OO_Mrm (0x0fb0 ,_b11,_r1(RS),_r1(RD) )) -#define CMPXCHGBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _OO_r_X (0x0fb0 ,_r1(RS) ,MD,MB,MI,MS )) - -#define CMPXCHGWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r2(RS),_r2(RD) )) -#define CMPXCHGWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r2(RS) ,MD,MB,MI,MS )) - -#define CMPXCHGLrr(RS, RD) (_REXLrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r4(RS),_r4(RD) )) -#define CMPXCHGLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r4(RS) ,MD,MB,MI,MS )) - -#define CMPXCHGQrr(RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r8(RS),_r8(RD) )) -#define CMPXCHGQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r8(RS) ,MD,MB,MI,MS )) - -#define XADDBrr(RS, RD) (_REXBrr(RS, RD), _OO_Mrm (0x0fc0 ,_b11,_r1(RS),_r1(RD) )) -#define XADDBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _OO_r_X (0x0fc0 ,_r1(RS) ,MD,MB,MI,MS )) - -#define XADDWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r2(RS),_r2(RD) )) -#define XADDWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r2(RS) ,MD,MB,MI,MS )) - -#define XADDLrr(RS, RD) (_REXLrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r4(RS),_r4(RD) )) -#define XADDLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r4(RS) ,MD,MB,MI,MS )) - -#define XADDQrr(RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r8(RS),_r8(RD) )) -#define XADDQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r8(RS) ,MD,MB,MI,MS )) - -#define XCHGBrr(RS, RD) (_REXBrr(RS, RD), _O_Mrm (0x86 ,_b11,_r1(RS),_r1(RD) )) -#define XCHGBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (0x86 ,_r1(RS) ,MD,MB,MI,MS )) - -#define XCHGWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (0x87 ,_b11,_r2(RS),_r2(RD) )) -#define XCHGWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0x87 ,_r2(RS) ,MD,MB,MI,MS )) - -#define XCHGLrr(RS, RD) (_REXLrr(RS, RD), _O_Mrm (0x87 ,_b11,_r4(RS),_r4(RD) )) -#define XCHGLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (0x87 ,_r4(RS) ,MD,MB,MI,MS )) - -#define XCHGQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x87 ,_b11,_r8(RS),_r8(RD) )) -#define XCHGQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x87 ,_r8(RS) ,MD,MB,MI,MS )) - - -/* --- Increment/Decrement instructions ------------------------------------ */ - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define DECBm(MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X (0xfe ,_b001 ,MD,MB,MI,MS )) -#define DECBr(RD) (_REXBrr(0, RD), _O_Mrm (0xfe ,_b11,_b001 ,_r1(RD) )) - -#define DECWm(MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS )) -#define DECWr(RD) (! X86_TARGET_64BIT ? (_d16(), _Or (0x48,_r2(RD) )) : \ - (_d16(), _REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r2(RD) ))) - -#define DECLm(MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS )) -#define DECLr(RD) (! X86_TARGET_64BIT ? _Or (0x48,_r4(RD) ) : \ - (_REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r4(RD) ))) - -#define DECQm(MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS )) -#define DECQr(RD) (_REXQrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r8(RD) )) - -#define INCBm(MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X (0xfe ,_b000 ,MD,MB,MI,MS )) -#define INCBr(RD) (_REXBrr(0, RD), _O_Mrm (0xfe ,_b11,_b000 ,_r1(RD) )) - -#define INCWm(MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS )) -#define INCWr(RD) (! X86_TARGET_64BIT ? (_d16(), _Or (0x40,_r2(RD) )) : \ - (_d16(), _REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r2(RD) )) ) - -#define INCLm(MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS )) -#define INCLr(RD) (! X86_TARGET_64BIT ? _Or (0x40,_r4(RD) ) : \ - (_REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r4(RD) ))) - -#define INCQm(MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS )) -#define INCQr(RD) (_REXQrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r8(RD) )) - - -/* --- Misc instructions --------------------------------------------------- */ - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define BSFWrr(RS, RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r2(RD),_r2(RS) )) -#define BSFWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r2(RD) ,MD,MB,MI,MS )) -#define BSRWrr(RS, RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r2(RD),_r2(RS) )) -#define BSRWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r2(RD) ,MD,MB,MI,MS )) - -#define BSFLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r4(RD),_r4(RS) )) -#define BSFLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r4(RD) ,MD,MB,MI,MS )) -#define BSRLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r4(RD),_r4(RS) )) -#define BSRLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r4(RD) ,MD,MB,MI,MS )) - -#define BSFQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r8(RD),_r8(RS) )) -#define BSFQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r8(RD) ,MD,MB,MI,MS )) -#define BSRQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r8(RD),_r8(RS) )) -#define BSRQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r8(RD) ,MD,MB,MI,MS )) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define MOVSBWrr(RS, RD) (_d16(), _REXBLrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r2(RD),_r1(RS) )) -#define MOVSBWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r2(RD) ,MD,MB,MI,MS )) -#define MOVZBWrr(RS, RD) (_d16(), _REXBLrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r2(RD),_r1(RS) )) -#define MOVZBWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r2(RD) ,MD,MB,MI,MS )) - -#define MOVSBLrr(RS, RD) (_REXBLrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r4(RD),_r1(RS) )) -#define MOVSBLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r4(RD) ,MD,MB,MI,MS )) -#define MOVZBLrr(RS, RD) (_REXBLrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r4(RD),_r1(RS) )) -#define MOVZBLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r4(RD) ,MD,MB,MI,MS )) - -#define MOVSBQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r8(RD),_r1(RS) )) -#define MOVSBQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r8(RD) ,MD,MB,MI,MS )) -#define MOVZBQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r8(RD),_r1(RS) )) -#define MOVZBQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r8(RD) ,MD,MB,MI,MS )) - -#define MOVSWLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fbf ,_b11,_r4(RD),_r2(RS) )) -#define MOVSWLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbf ,_r4(RD) ,MD,MB,MI,MS )) -#define MOVZWLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fb7 ,_b11,_r4(RD),_r2(RS) )) -#define MOVZWLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fb7 ,_r4(RD) ,MD,MB,MI,MS )) - -#define MOVSWQrr(RS, RD) _m64only((_REXQrr(RD, RS), _OO_Mrm (0x0fbf ,_b11,_r8(RD),_r2(RS) ))) -#define MOVSWQmr(MD, MB, MI, MS, RD) _m64only((_REXQmr(MB, MI, RD), _OO_r_X (0x0fbf ,_r8(RD) ,MD,MB,MI,MS ))) -#define MOVZWQrr(RS, RD) _m64only((_REXQrr(RD, RS), _OO_Mrm (0x0fb7 ,_b11,_r8(RD),_r2(RS) ))) -#define MOVZWQmr(MD, MB, MI, MS, RD) _m64only((_REXQmr(MB, MI, RD), _OO_r_X (0x0fb7 ,_r8(RD) ,MD,MB,MI,MS ))) - -#define MOVSLQrr(RS, RD) _m64only((_REXQrr(RD, RS), _O_Mrm (0x63 ,_b11,_r8(RD),_r4(RS) ))) -#define MOVSLQmr(MD, MB, MI, MS, RD) _m64only((_REXQmr(MB, MI, RD), _O_r_X (0x63 ,_r8(RD) ,MD,MB,MI,MS ))) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define LEALmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (0x8d ,_r4(RD) ,MD,MB,MI,MS )) -#define LEAQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (0x8d ,_r4(RD) ,MD,MB,MI,MS )) - -#define BSWAPLr(R) (_REXLrr(0, R), _OOr (0x0fc8,_r4(R) )) -#define BSWAPQr(R) (_REXQrr(0, R), _OOr (0x0fc8,_r8(R) )) - -#define CLC() _O (0xf8 ) -#define STC() _O (0xf9 ) -#define CMC() _O (0xf5 ) - -#define CLD() _O (0xfc ) -#define STD() _O (0xfd ) - -#define CBTW() (_d16(), _O (0x98 )) -#define CWTL() _O (0x98 ) -#define CLTQ() _m64only(_REXQrr(0, 0), _O (0x98 )) - -#define CBW CBTW -#define CWDE CWTL -#define CDQE CLTQ - -#define CWTD() (_d16(), _O (0x99 )) -#define CLTD() _O (0x99 ) -#define CQTO() _m64only(_REXQrr(0, 0), _O (0x99 )) - -#define CWD CWTD -#define CDQ CLTD -#define CQO CQTO - -#define LAHF() _O (0x9f ) -#define SAHF() _O (0x9e ) - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define CPUID() _OO (0x0fa2 ) -#define RDTSC() _OO (0xff31 ) - -#define ENTERii(W, B) _O_W_B (0xc8 ,_su16(W),_su8(B)) - -#define LEAVE() _O (0xc9 ) -#define RET() _O (0xc3 ) -#define RETi(IM) _O_W (0xc2 ,_su16(IM)) - -#define NOP() _O (0x90 ) - - -/* --- Media 64-bit instructions ------------------------------------------- */ - -enum { - X86_MMX_PABSB = 0x1c, // 2P - X86_MMX_PABSW = 0x1d, // 2P - X86_MMX_PABSD = 0x1e, // 2P - X86_MMX_PACKSSWB = 0x63, - X86_MMX_PACKSSDW = 0x6b, - X86_MMX_PACKUSWB = 0x67, - X86_MMX_PADDB = 0xfc, - X86_MMX_PADDW = 0xfd, - X86_MMX_PADDD = 0xfe, - X86_MMX_PADDQ = 0xd4, - X86_MMX_PADDSB = 0xec, - X86_MMX_PADDSW = 0xed, - X86_MMX_PADDUSB = 0xdc, - X86_MMX_PADDUSW = 0xdd, - X86_MMX_PAND = 0xdb, - X86_MMX_PANDN = 0xdf, - X86_MMX_PAVGB = 0xe0, - X86_MMX_PAVGW = 0xe3, - X86_MMX_PCMPEQB = 0x74, - X86_MMX_PCMPEQW = 0x75, - X86_MMX_PCMPEQD = 0x76, - X86_MMX_PCMPGTB = 0x64, - X86_MMX_PCMPGTW = 0x65, - X86_MMX_PCMPGTD = 0x66, - X86_MMX_PEXTRW = 0xc5, // 64, /r ib - X86_MMX_PHADDW = 0x01, // 2P - X86_MMX_PHADDD = 0x02, // 2P - X86_MMX_PHADDSW = 0x03, // 2P - X86_MMX_PHSUBW = 0x05, // 2P - X86_MMX_PHSUBD = 0x06, // 2P - X86_MMX_PHSUBSW = 0x07, // 2P - X86_MMX_PINSRW = 0xc4, // 64, /r ib - X86_MMX_PMADDUBSW = 0x04, // 2P - X86_MMX_PMADDWD = 0xf5, - X86_MMX_PMAXSW = 0xee, - X86_MMX_PMAXUB = 0xde, - X86_MMX_PMINSW = 0xea, - X86_MMX_PMINUB = 0xda, - X86_MMX_PMOVMSKB = 0xd7, // 64 - X86_MMX_PMULHRSW = 0x0b, // 2P - X86_MMX_PMULHUW = 0xe4, - X86_MMX_PMULHW = 0xe5, - X86_MMX_PMULLW = 0xd5, - X86_MMX_PMULUDQ = 0xf4, - X86_MMX_POR = 0xeb, - X86_MMX_PSADBW = 0xf6, - X86_MMX_PSHUFB = 0x00, // 2P - X86_MMX_PSHUFW = 0x70, // /r ib - X86_MMX_PSIGNB = 0x08, // 2P - X86_MMX_PSIGNW = 0x09, // 2P - X86_MMX_PSIGND = 0x0a, // 2P - X86_MMX_PSLLW = 0xf1, - X86_MMX_PSLLWi = 0x71, // /6 ib - X86_MMX_PSLLD = 0xf2, - X86_MMX_PSLLDi = 0x72, // /6 ib - X86_MMX_PSLLQ = 0xf3, - X86_MMX_PSLLQi = 0x73, // /6 ib - X86_MMX_PSRAW = 0xe1, - X86_MMX_PSRAWi = 0x71, // /4 ib - X86_MMX_PSRAD = 0xe2, - X86_MMX_PSRADi = 0x72, // /4 ib - X86_MMX_PSRLW = 0xd1, - X86_MMX_PSRLWi = 0x71, // /2 ib - X86_MMX_PSRLD = 0xd2, - X86_MMX_PSRLDi = 0x72, // /2 ib - X86_MMX_PSRLQ = 0xd3, - X86_MMX_PSRLQi = 0x73, // /2 ib - X86_MMX_PSUBB = 0xf8, - X86_MMX_PSUBW = 0xf9, - X86_MMX_PSUBD = 0xfa, - X86_MMX_PSUBQ = 0xfb, - X86_MMX_PSUBSB = 0xe8, - X86_MMX_PSUBSW = 0xe9, - X86_MMX_PSUBUSB = 0xd8, - X86_MMX_PSUBUSW = 0xd9, - X86_MMX_PUNPCKHBW = 0x68, - X86_MMX_PUNPCKHWD = 0x69, - X86_MMX_PUNPCKHDQ = 0x6a, - X86_MMX_PUNPCKLBW = 0x60, - X86_MMX_PUNPCKLWD = 0x61, - X86_MMX_PUNPCKLDQ = 0x62, - X86_MMX_PXOR = 0xef, -}; - -#define __MMXLrr(OP,RS,RSA,RD,RDA) (_REXLrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) )) -#define __MMXLmr(OP,MD,MB,MI,MS,RD,RDA) (_REXLmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS )) -#define __MMXLrm(OP,RS,RSA,MD,MB,MI,MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS )) -#define __MMXLirr(OP,IM,RS,RSA,RD,RDA) (_REXLrr(RD, RS), _OO_Mrm_B (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) ,_u8(IM))) -#define __MMXLimr(OP,IM,MD,MB,MI,MS,RD,RDA) (_REXLmr(MB, MI, RS), _OO_r_X_B (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS ,_u8(IM))) -#define __MMXQrr(OP,RS,RSA,RD,RDA) (_REXQrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) )) -#define __MMXQmr(OP,MD,MB,MI,MS,RD,RDA) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS )) -#define __MMXQrm(OP,RS,RSA,MD,MB,MI,MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS )) -#define __MMXQirr(OP,IM,RS,RSA,RD,RDA) (_REXQrr(RD, RS), _OO_Mrm_B (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) ,_u8(IM))) -#define __MMXQimr(OP,IM,MD,MB,MI,MS,RD,RDA) (_REXQmr(MB, MI, RS), _OO_r_X_B (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS ,_u8(IM))) -#define __MMX1Lrr(PX,OP,RS,RSA,RD,RDA) (_REXLrr(RD, RS), _B(0x0f),_OO_Mrm(((PX)<<8)|(OP) ,_b11,RDA(RD),RSA(RS) )) -#define __MMX1Lmr(PX,OP,MD,MB,MI,MS,RD,RDA) (_REXLmr(MB, MI, RD), _B(0x0f),_OO_r_X(((PX)<<8)|(OP) ,RDA(RD) ,MD,MB,MI,MS )) -#define __MMX1Lrm(PX,OP,RS,RSA,MD,MB,MI,MS) (_REXLrm(RS, MB, MI), _B(0x0f),_OO_r_X(((PX)<<8)|(OP) ,RSA(RS) ,MD,MB,MI,MS )) - -#define _MMXLrr(OP,RS,RD) __MMXLrr(OP,RS,_rM,RD,_rM) -#define _MMXLmr(OP,MD,MB,MI,MS,RD) __MMXLmr(OP,MD,MB,MI,MS,RD,_rM) -#define _MMXLrm(OP,RS,MD,MB,MI,MS) __MMXLrm(OP,RS,_rM,MD,MB,MI,MS) -#define _MMXQrr(OP,RS,RD) __MMXQrr(OP,RS,_rM,RD,_rM) -#define _MMXQmr(OP,MD,MB,MI,MS,RD) __MMXQmr(OP,MD,MB,MI,MS,RD,_rM) -#define _MMXQrm(OP,RS,MD,MB,MI,MS) __MMXQrm(OP,RS,_rM,MD,MB,MI,MS) -#define _2P_MMXLrr(OP,RS,RD) __MMX1Lrr(0x38, OP,RS,_rM,RD,_rM) -#define _2P_MMXLmr(OP,MD,MB,MI,MS,RD) __MMX1Lmr(0x38, OP,MD,MB,MI,MS,RD,_rM) -#define _2P_MMXLrm(OP,RS,MD,MB,MI,MS) __MMX1Lrm(0x38, OP,RS,_rM,MD,MB,MI,MS) - -#define MMX_MOVDMDrr(RS, RD) __MMXLrr(0x6e, RS,_r4, RD,_rM) -#define MMX_MOVQMDrr(RS, RD) __MMXQrr(0x6e, RS,_r8, RD,_rM) -#define MMX_MOVDMSrr(RS, RD) __MMXLrr(0x7e, RD,_r4, RS,_rM) -#define MMX_MOVQMSrr(RS, RD) __MMXQrr(0x7e, RD,_r8, RS,_rM) - -#define MMX_MOVDmr(MD, MB, MI, MS, RD) _MMXLmr(0x6e, MD, MB, MI, MS, RD) -#define MMX_MOVDrm(RS, MD, MB, MI, MS) _MMXLrm(0x7e, RS, MD, MB, MI, MS) -#define MMX_MOVQrr(RS, RD) _MMXLrr(0x6f, RS, RD) -#define MMX_MOVQmr(MD, MB, MI, MS, RD) _MMXLmr(0x6f, MD, MB, MI, MS, RD) -#define MMX_MOVQrm(RS, MD, MB, MI, MS) _MMXLrm(0x7f, RS, MD, MB, MI, MS) - -// Original MMX instructions -#define MMX_PACKSSWBrr(RS, RD) _MMXLrr(X86_MMX_PACKSSWB,RS,RD) -#define MMX_PACKSSWBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PACKSSWB, MD, MB, MI, MS, RD) -#define MMX_PACKSSDWrr(RS, RD) _MMXLrr(X86_MMX_PACKSSDW,RS,RD) -#define MMX_PACKSSDWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PACKSSDW, MD, MB, MI, MS, RD) -#define MMX_PACKUSWBrr(RS, RD) _MMXLrr(X86_MMX_PACKUSWB,RS,RD) -#define MMX_PACKUSWBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PACKUSWB, MD, MB, MI, MS, RD) -#define MMX_PADDBrr(RS, RD) _MMXLrr(X86_MMX_PADDB,RS,RD) -#define MMX_PADDBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDB, MD, MB, MI, MS, RD) -#define MMX_PADDWrr(RS, RD) _MMXLrr(X86_MMX_PADDW,RS,RD) -#define MMX_PADDWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDW, MD, MB, MI, MS, RD) -#define MMX_PADDDrr(RS, RD) _MMXLrr(X86_MMX_PADDD,RS,RD) -#define MMX_PADDDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDD, MD, MB, MI, MS, RD) -#define MMX_PADDQrr(RS, RD) _MMXLrr(X86_MMX_PADDQ,RS,RD) -#define MMX_PADDQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDQ, MD, MB, MI, MS, RD) -#define MMX_PADDSBrr(RS, RD) _MMXLrr(X86_MMX_PADDSB,RS,RD) -#define MMX_PADDSBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDSB, MD, MB, MI, MS, RD) -#define MMX_PADDSWrr(RS, RD) _MMXLrr(X86_MMX_PADDSW,RS,RD) -#define MMX_PADDSWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDSW, MD, MB, MI, MS, RD) -#define MMX_PADDUSBrr(RS, RD) _MMXLrr(X86_MMX_PADDUSB,RS,RD) -#define MMX_PADDUSBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDUSB, MD, MB, MI, MS, RD) -#define MMX_PADDUSWrr(RS, RD) _MMXLrr(X86_MMX_PADDUSW,RS,RD) -#define MMX_PADDUSWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PADDUSW, MD, MB, MI, MS, RD) -#define MMX_PANDrr(RS, RD) _MMXLrr(X86_MMX_PAND,RS,RD) -#define MMX_PANDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PAND, MD, MB, MI, MS, RD) -#define MMX_PANDNrr(RS, RD) _MMXLrr(X86_MMX_PANDN,RS,RD) -#define MMX_PANDNmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PANDN, MD, MB, MI, MS, RD) -#define MMX_PAVGBrr(RS, RD) _MMXLrr(X86_MMX_PAVGB,RS,RD) -#define MMX_PAVGBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PAVGB, MD, MB, MI, MS, RD) -#define MMX_PAVGWrr(RS, RD) _MMXLrr(X86_MMX_PAVGW,RS,RD) -#define MMX_PAVGWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PAVGW, MD, MB, MI, MS, RD) -#define MMX_PCMPEQBrr(RS, RD) _MMXLrr(X86_MMX_PCMPEQB,RS,RD) -#define MMX_PCMPEQBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PCMPEQB, MD, MB, MI, MS, RD) -#define MMX_PCMPEQWrr(RS, RD) _MMXLrr(X86_MMX_PCMPEQW,RS,RD) -#define MMX_PCMPEQWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PCMPEQW, MD, MB, MI, MS, RD) -#define MMX_PCMPEQDrr(RS, RD) _MMXLrr(X86_MMX_PCMPEQD,RS,RD) -#define MMX_PCMPEQDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PCMPEQD, MD, MB, MI, MS, RD) -#define MMX_PCMPGTBrr(RS, RD) _MMXLrr(X86_MMX_PCMPGTB,RS,RD) -#define MMX_PCMPGTBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PCMPGTB, MD, MB, MI, MS, RD) -#define MMX_PCMPGTWrr(RS, RD) _MMXLrr(X86_MMX_PCMPGTW,RS,RD) -#define MMX_PCMPGTWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PCMPGTW, MD, MB, MI, MS, RD) -#define MMX_PCMPGTDrr(RS, RD) _MMXLrr(X86_MMX_PCMPGTD,RS,RD) -#define MMX_PCMPGTDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PCMPGTD, MD, MB, MI, MS, RD) -#define MMX_PMADDWDrr(RS, RD) _MMXLrr(X86_MMX_PMADDWD,RS,RD) -#define MMX_PMADDWDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMADDWD, MD, MB, MI, MS, RD) -#define MMX_PMAXSWrr(RS, RD) _MMXLrr(X86_MMX_PMAXSW,RS,RD) -#define MMX_PMAXSWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMAXSW, MD, MB, MI, MS, RD) -#define MMX_PMAXUBrr(RS, RD) _MMXLrr(X86_MMX_PMAXUB,RS,RD) -#define MMX_PMAXUBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMAXUB, MD, MB, MI, MS, RD) -#define MMX_PMINSWrr(RS, RD) _MMXLrr(X86_MMX_PMINSW,RS,RD) -#define MMX_PMINSWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMINSW, MD, MB, MI, MS, RD) -#define MMX_PMINUBrr(RS, RD) _MMXLrr(X86_MMX_PMINUB,RS,RD) -#define MMX_PMINUBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMINUB, MD, MB, MI, MS, RD) -#define MMX_PMULHUWrr(RS, RD) _MMXLrr(X86_MMX_PMULHUW,RS,RD) -#define MMX_PMULHUWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMULHUW, MD, MB, MI, MS, RD) -#define MMX_PMULHWrr(RS, RD) _MMXLrr(X86_MMX_PMULHW,RS,RD) -#define MMX_PMULHWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMULHW, MD, MB, MI, MS, RD) -#define MMX_PMULLWrr(RS, RD) _MMXLrr(X86_MMX_PMULLW,RS,RD) -#define MMX_PMULLWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMULLW, MD, MB, MI, MS, RD) -#define MMX_PMULUDQrr(RS, RD) _MMXLrr(X86_MMX_PMULUDQ,RS,RD) -#define MMX_PMULUDQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PMULUDQ, MD, MB, MI, MS, RD) -#define MMX_PORrr(RS, RD) _MMXLrr(X86_MMX_POR,RS,RD) -#define MMX_PORmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_POR, MD, MB, MI, MS, RD) -#define MMX_PSADBWrr(RS, RD) _MMXLrr(X86_MMX_PSADBW,RS,RD) -#define MMX_PSADBWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSADBW, MD, MB, MI, MS, RD) -#define MMX_PSLLWir(IM, RD) __MMXLirr(X86_MMX_PSLLWi, IM, RD,_rM, _b110,_rN) -#define MMX_PSLLWrr(RS, RD) _MMXLrr(X86_MMX_PSLLW,RS,RD) -#define MMX_PSLLWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSLLW, MD, MB, MI, MS, RD) -#define MMX_PSLLDir(IM, RD) __MMXLirr(X86_MMX_PSLLDi, IM, RD,_rM, _b110,_rN) -#define MMX_PSLLDrr(RS, RD) _MMXLrr(X86_MMX_PSLLD,RS,RD) -#define MMX_PSLLDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSLLD, MD, MB, MI, MS, RD) -#define MMX_PSLLQir(IM, RD) __MMXLirr(X86_MMX_PSLLQi, IM, RD,_rM, _b110,_rN) -#define MMX_PSLLQrr(RS, RD) _MMXLrr(X86_MMX_PSLLQ,RS,RD) -#define MMX_PSLLQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSLLQ, MD, MB, MI, MS, RD) -#define MMX_PSRAWir(IM, RD) __MMXLirr(X86_MMX_PSRAWi, IM, RD,_rM, _b100,_rN) -#define MMX_PSRAWrr(RS, RD) _MMXLrr(X86_MMX_PSRAW,RS,RD) -#define MMX_PSRAWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSRAW, MD, MB, MI, MS, RD) -#define MMX_PSRADir(IM, RD) __MMXLirr(X86_MMX_PSRADi, IM, RD,_rM, _b100,_rN) -#define MMX_PSRADrr(RS, RD) _MMXLrr(X86_MMX_PSRAD,RS,RD) -#define MMX_PSRADmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSRAD, MD, MB, MI, MS, RD) -#define MMX_PSRLWir(IM, RD) __MMXLirr(X86_MMX_PSRLWi, IM, RD,_rM, _b010,_rN) -#define MMX_PSRLWrr(RS, RD) _MMXLrr(X86_MMX_PSRLW,RS,RD) -#define MMX_PSRLWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSRLW, MD, MB, MI, MS, RD) -#define MMX_PSRLDir(IM, RD) __MMXLirr(X86_MMX_PSRLDi, IM, RD,_rM, _b010,_rN) -#define MMX_PSRLDrr(RS, RD) _MMXLrr(X86_MMX_PSRLD,RS,RD) -#define MMX_PSRLDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSRLD, MD, MB, MI, MS, RD) -#define MMX_PSRLQir(IM, RD) __MMXLirr(X86_MMX_PSRLQi, IM, RD,_rM, _b010,_rN) -#define MMX_PSRLQrr(RS, RD) _MMXLrr(X86_MMX_PSRLQ,RS,RD) -#define MMX_PSRLQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSRLQ, MD, MB, MI, MS, RD) -#define MMX_PSUBBrr(RS, RD) _MMXLrr(X86_MMX_PSUBB,RS,RD) -#define MMX_PSUBBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBB, MD, MB, MI, MS, RD) -#define MMX_PSUBWrr(RS, RD) _MMXLrr(X86_MMX_PSUBW,RS,RD) -#define MMX_PSUBWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBW, MD, MB, MI, MS, RD) -#define MMX_PSUBDrr(RS, RD) _MMXLrr(X86_MMX_PSUBD,RS,RD) -#define MMX_PSUBDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBD, MD, MB, MI, MS, RD) -#define MMX_PSUBQrr(RS, RD) _MMXLrr(X86_MMX_PSUBQ,RS,RD) -#define MMX_PSUBQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBQ, MD, MB, MI, MS, RD) -#define MMX_PSUBSBrr(RS, RD) _MMXLrr(X86_MMX_PSUBSB,RS,RD) -#define MMX_PSUBSBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBSB, MD, MB, MI, MS, RD) -#define MMX_PSUBSWrr(RS, RD) _MMXLrr(X86_MMX_PSUBSW,RS,RD) -#define MMX_PSUBSWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBSW, MD, MB, MI, MS, RD) -#define MMX_PSUBUSBrr(RS, RD) _MMXLrr(X86_MMX_PSUBUSB,RS,RD) -#define MMX_PSUBUSBmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBUSB, MD, MB, MI, MS, RD) -#define MMX_PSUBUSWrr(RS, RD) _MMXLrr(X86_MMX_PSUBUSW,RS,RD) -#define MMX_PSUBUSWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PSUBUSW, MD, MB, MI, MS, RD) -#define MMX_PUNPCKHBWrr(RS, RD) _MMXLrr(X86_MMX_PUNPCKHBW,RS,RD) -#define MMX_PUNPCKHBWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PUNPCKHBW, MD, MB, MI, MS, RD) -#define MMX_PUNPCKHWDrr(RS, RD) _MMXLrr(X86_MMX_PUNPCKHWD,RS,RD) -#define MMX_PUNPCKHWDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PUNPCKHWD, MD, MB, MI, MS, RD) -#define MMX_PUNPCKHDQrr(RS, RD) _MMXLrr(X86_MMX_PUNPCKHDQ,RS,RD) -#define MMX_PUNPCKHDQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PUNPCKHDQ, MD, MB, MI, MS, RD) -#define MMX_PUNPCKLBWrr(RS, RD) _MMXLrr(X86_MMX_PUNPCKLBW,RS,RD) -#define MMX_PUNPCKLBWmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PUNPCKLBW, MD, MB, MI, MS, RD) -#define MMX_PUNPCKLWDrr(RS, RD) _MMXLrr(X86_MMX_PUNPCKLWD,RS,RD) -#define MMX_PUNPCKLWDmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PUNPCKLWD, MD, MB, MI, MS, RD) -#define MMX_PUNPCKLDQrr(RS, RD) _MMXLrr(X86_MMX_PUNPCKLDQ,RS,RD) -#define MMX_PUNPCKLDQmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PUNPCKLDQ, MD, MB, MI, MS, RD) -#define MMX_PXORrr(RS, RD) _MMXLrr(X86_MMX_PXOR,RS,RD) -#define MMX_PXORmr(MD,MB,MI,MS,RD) _MMXLmr(X86_MMX_PXOR, MD, MB, MI, MS, RD) - -#define MMX_PSHUFWirr(IM, RS, RD) __MMXLirr(X86_MMX_PSHUFW, IM, RS,_rM, RD,_rM) -#define MMX_PSHUFWimr(IM, MD, MB, MI, MS, RD) __MMXLimr(X86_MMX_PSHUFW, IM, MD, MB, MI, MS, RD,_rM) -#define MMX_PEXTRWLirr(IM, RS, RD) __MMXLirr(X86_MMX_PEXTRW, IM, RS,_rM, RD,_r4) -#define MMX_PEXTRWQirr(IM, RS, RD) __MMXQirr(X86_MMX_PEXTRW, IM, RS,_rM, RD,_r8) -#define MMX_PINSRWLirr(IM, RS, RD) __MMXLirr(X86_MMX_PINSRW, IM, RS,_r4, RD,_rM) -#define MMX_PINSRWLimr(IM, MD, MB, MI, MS, RD) __MMXLimr(X86_MMX_PINSRW, IM, MD, MB, MI, MS, RD,_r4) -#define MMX_PINSRWQirr(IM, RS, RD) __MMXQirr(X86_MMX_PINSRW, IM, RS,_r4, RD,_rM) -#define MMX_PINSRWQimr(IM, MD, MB, MI, MS, RD) __MMXQimr(X86_MMX_PINSRW, IM, MD, MB, MI, MS, RD,_r8) - -// Additionnal MMX instructions, brought by SSSE3 ISA -#define MMX_PABSBrr(RS, RD) _2P_MMXLrr(X86_MMX_PABSB,RS,RD) -#define MMX_PABSBmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PABSB, MD, MB, MI, MS, RD) -#define MMX_PABSWrr(RS, RD) _2P_MMXLrr(X86_MMX_PABSW,RS,RD) -#define MMX_PABSWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PABSW, MD, MB, MI, MS, RD) -#define MMX_PABSDrr(RS, RD) _2P_MMXLrr(X86_MMX_PABSD,RS,RD) -#define MMX_PABSDmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PABSD, MD, MB, MI, MS, RD) -#define MMX_PHADDWrr(RS, RD) _2P_MMXLrr(X86_MMX_PHADDW,RS,RD) -#define MMX_PHADDWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PHADDW, MD, MB, MI, MS, RD) -#define MMX_PHADDDrr(RS, RD) _2P_MMXLrr(X86_MMX_PHADDD,RS,RD) -#define MMX_PHADDDmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PHADDD, MD, MB, MI, MS, RD) -#define MMX_PHADDSWrr(RS, RD) _2P_MMXLrr(X86_MMX_PHADDSW,RS,RD) -#define MMX_PHADDSWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PHADDSW, MD, MB, MI, MS, RD) -#define MMX_PHSUBWrr(RS, RD) _2P_MMXLrr(X86_MMX_PHSUBW,RS,RD) -#define MMX_PHSUBWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PHSUBW, MD, MB, MI, MS, RD) -#define MMX_PHSUBDrr(RS, RD) _2P_MMXLrr(X86_MMX_PHSUBD,RS,RD) -#define MMX_PHSUBDmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PHSUBD, MD, MB, MI, MS, RD) -#define MMX_PHSUBSWrr(RS, RD) _2P_MMXLrr(X86_MMX_PHSUBSW,RS,RD) -#define MMX_PHSUBSWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PHSUBSW, MD, MB, MI, MS, RD) -#define MMX_PMADDUBSWrr(RS, RD) _2P_MMXLrr(X86_MMX_PMADDUBSW,RS,RD) -#define MMX_PMADDUBSWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PMADDUBSW, MD, MB, MI, MS, RD) -#define MMX_PMULHRSWrr(RS, RD) _2P_MMXLrr(X86_MMX_PMULHRSW,RS,RD) -#define MMX_PMULHRSWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PMULHRSW, MD, MB, MI, MS, RD) -#define MMX_PSHUFBrr(RS, RD) _2P_MMXLrr(X86_MMX_PSHUFB,RS,RD) -#define MMX_PSHUFBmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PSHUFB, MD, MB, MI, MS, RD) -#define MMX_PSIGNBrr(RS, RD) _2P_MMXLrr(X86_MMX_PSIGNB,RS,RD) -#define MMX_PSIGNBmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PSIGNB, MD, MB, MI, MS, RD) -#define MMX_PSIGNWrr(RS, RD) _2P_MMXLrr(X86_MMX_PSIGNW,RS,RD) -#define MMX_PSIGNWmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PSIGNW, MD, MB, MI, MS, RD) -#define MMX_PSIGNDrr(RS, RD) _2P_MMXLrr(X86_MMX_PSIGND,RS,RD) -#define MMX_PSIGNDmr(MD,MB,MI,MS,RD) _2P_MMXLmr(X86_MMX_PSIGND, MD, MB, MI, MS, RD) - -#define EMMS() _OO (0x0f77 ) - - -/* --- Media 128-bit instructions ------------------------------------------ */ - -enum { - X86_SSE_CC_EQ = 0, - X86_SSE_CC_LT = 1, - X86_SSE_CC_GT = 1, - X86_SSE_CC_LE = 2, - X86_SSE_CC_GE = 2, - X86_SSE_CC_U = 3, - X86_SSE_CC_NEQ = 4, - X86_SSE_CC_NLT = 5, - X86_SSE_CC_NGT = 5, - X86_SSE_CC_NLE = 6, - X86_SSE_CC_NGE = 6, - X86_SSE_CC_O = 7 -}; - -enum { - X86_SSE_UCOMI = 0x2e, - X86_SSE_COMI = 0x2f, - X86_SSE_CMP = 0xc2, - X86_SSE_SQRT = 0x51, - X86_SSE_RSQRT = 0x52, - X86_SSE_RCP = 0x53, - X86_SSE_AND = 0x54, - X86_SSE_ANDN = 0x55, - X86_SSE_OR = 0x56, - X86_SSE_XOR = 0x57, - X86_SSE_ADD = 0x58, - X86_SSE_MUL = 0x59, - X86_SSE_SUB = 0x5c, - X86_SSE_MIN = 0x5d, - X86_SSE_DIV = 0x5e, - X86_SSE_MAX = 0x5f, - X86_SSE_CVTDQ2PD = 0xe6, - X86_SSE_CVTDQ2PS = 0x5b, - X86_SSE_CVTPD2DQ = 0xe6, - X86_SSE_CVTPD2PI = 0x2d, - X86_SSE_CVTPD2PS = 0x5a, - X86_SSE_CVTPI2PD = 0x2a, - X86_SSE_CVTPI2PS = 0x2a, - X86_SSE_CVTPS2DQ = 0x5b, - X86_SSE_CVTPS2PD = 0x5a, - X86_SSE_CVTPS2PI = 0x2d, - X86_SSE_CVTSD2SI = 0x2d, - X86_SSE_CVTSD2SS = 0x5a, - X86_SSE_CVTSI2SD = 0x2a, - X86_SSE_CVTSI2SS = 0x2a, - X86_SSE_CVTSS2SD = 0x5a, - X86_SSE_CVTSS2SI = 0x2d, - X86_SSE_CVTTPD2PI = 0x2c, - X86_SSE_CVTTPD2DQ = 0xe6, - X86_SSE_CVTTPS2DQ = 0x5b, - X86_SSE_CVTTPS2PI = 0x2c, - X86_SSE_CVTTSD2SI = 0x2c, - X86_SSE_CVTTSS2SI = 0x2c, - X86_SSE_MOVMSK = 0x50, - X86_SSE_PACKSSDW = 0x6b, - X86_SSE_PACKSSWB = 0x63, - X86_SSE_PACKUSWB = 0x67, - X86_SSE_PADDB = 0xfc, - X86_SSE_PADDD = 0xfe, - X86_SSE_PADDQ = 0xd4, - X86_SSE_PADDSB = 0xec, - X86_SSE_PADDSW = 0xed, - X86_SSE_PADDUSB = 0xdc, - X86_SSE_PADDUSW = 0xdd, - X86_SSE_PADDW = 0xfd, - X86_SSE_PAND = 0xdb, - X86_SSE_PANDN = 0xdf, - X86_SSE_PAVGB = 0xe0, - X86_SSE_PAVGW = 0xe3, - X86_SSE_PCMPEQB = 0x74, - X86_SSE_PCMPEQD = 0x76, - X86_SSE_PCMPEQW = 0x75, - X86_SSE_PCMPGTB = 0x64, - X86_SSE_PCMPGTD = 0x66, - X86_SSE_PCMPGTW = 0x65, - X86_SSE_PMADDWD = 0xf5, - X86_SSE_PMAXSW = 0xee, - X86_SSE_PMAXUB = 0xde, - X86_SSE_PMINSW = 0xea, - X86_SSE_PMINUB = 0xda, - X86_SSE_PMOVMSKB = 0xd7, - X86_SSE_PMULHUW = 0xe4, - X86_SSE_PMULHW = 0xe5, - X86_SSE_PMULLW = 0xd5, - X86_SSE_PMULUDQ = 0xf4, - X86_SSE_POR = 0xeb, - X86_SSE_PSADBW = 0xf6, - X86_SSE_PSLLD = 0xf2, - X86_SSE_PSLLQ = 0xf3, - X86_SSE_PSLLW = 0xf1, - X86_SSE_PSRAD = 0xe2, - X86_SSE_PSRAW = 0xe1, - X86_SSE_PSRLD = 0xd2, - X86_SSE_PSRLQ = 0xd3, - X86_SSE_PSRLW = 0xd1, - X86_SSE_PSUBB = 0xf8, - X86_SSE_PSUBD = 0xfa, - X86_SSE_PSUBQ = 0xfb, - X86_SSE_PSUBSB = 0xe8, - X86_SSE_PSUBSW = 0xe9, - X86_SSE_PSUBUSB = 0xd8, - X86_SSE_PSUBUSW = 0xd9, - X86_SSE_PSUBW = 0xf9, - X86_SSE_PUNPCKHBW = 0x68, - X86_SSE_PUNPCKHDQ = 0x6a, - X86_SSE_PUNPCKHQDQ = 0x6d, - X86_SSE_PUNPCKHWD = 0x69, - X86_SSE_PUNPCKLBW = 0x60, - X86_SSE_PUNPCKLDQ = 0x62, - X86_SSE_PUNPCKLQDQ = 0x6c, - X86_SSE_PUNPCKLWD = 0x61, - X86_SSE_PXOR = 0xef, - X86_SSSE3_PSHUFB = 0x00, -}; - -/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ - -#define _SSSE3Lrr(OP1,OP2,RS,RSA,RD,RDA) (_B(0x66), _REXLrr(RD,RD), _B(0x0f), _OO_Mrm (((OP1)<<8)|(OP2) ,_b11,RDA(RD),RSA(RS) )) -#define _SSSE3Lmr(OP1,OP2,MD,MB,MI,MS,RD,RDA) (_B(0x66), _REXLmr(MB, MI, RD), _B(0x0f), _OO_r_X (((OP1)<<8)|(OP2) ,RDA(RD) ,MD,MB,MI,MS )) -#define _SSSE3Lirr(OP1,OP2,IM,RS,RD) (_B(0x66), _REXLrr(RD, RS), _B(0x0f), _OO_Mrm_B (((OP1)<<8)|(OP2) ,_b11,_rX(RD),_rX(RS) ,_u8(IM))) -#define _SSSE3Limr(OP1,OP2,IM,MD,MB,MI,MS,RD) (_B(0x66), _REXLmr(MB, MI, RD), _B(0x0f), _OO_r_X_B (((OP1)<<8)|(OP2) ,_rX(RD) ,MD,MB,MI,MS ,_u8(IM))) - -#define __SSELir(OP,MO,IM,RD) (_REXLrr(0, RD), _OO_Mrm_B (0x0f00|(OP) ,_b11,MO ,_rX(RD) ,_u8(IM))) -#define __SSELim(OP,MO,IM,MD,MB,MI,MS) (_REXLrm(0, MB, MI), _OO_r_X_B (0x0f00|(OP) ,MO ,MD,MB,MI,MS ,_u8(IM))) -#define __SSELrr(OP,RS,RSA,RD,RDA) (_REXLrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) )) -#define __SSELmr(OP,MD,MB,MI,MS,RD,RDA) (_REXLmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS )) -#define __SSELrm(OP,RS,RSA,MD,MB,MI,MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS )) -#define __SSELirr(OP,IM,RS,RD) (_REXLrr(RD, RS), _OO_Mrm_B (0x0f00|(OP) ,_b11,_rX(RD),_rX(RS) ,_u8(IM))) -#define __SSELimr(OP,IM,MD,MB,MI,MS,RD) (_REXLmr(MB, MI, RD), _OO_r_X_B (0x0f00|(OP) ,_rX(RD) ,MD,MB,MI,MS ,_u8(IM))) - -#define __SSEQrr(OP,RS,RSA,RD,RDA) (_REXQrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) )) -#define __SSEQmr(OP,MD,MB,MI,MS,RD,RDA) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS )) -#define __SSEQrm(OP,RS,RSA,MD,MB,MI,MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS )) - -#define _SSELrr(PX,OP,RS,RSA,RD,RDA) (_B(PX), __SSELrr(OP, RS, RSA, RD, RDA)) -#define _SSELmr(PX,OP,MD,MB,MI,MS,RD,RDA) (_B(PX), __SSELmr(OP, MD, MB, MI, MS, RD, RDA)) -#define _SSELrm(PX,OP,RS,RSA,MD,MB,MI,MS) (_B(PX), __SSELrm(OP, RS, RSA, MD, MB, MI, MS)) -#define _SSELir(PX,OP,MO,IM,RD) (_B(PX), __SSELir(OP, MO, IM, RD)) -#define _SSELim(PX,OP,MO,IM,MD,MB,MI,MS) (_B(PX), __SSELim(OP, MO, IM, MD, MB, MI, MS)) -#define _SSELirr(PX,OP,IM,RS,RD) (_B(PX), __SSELirr(OP, IM, RS, RD)) -#define _SSELimr(PX,OP,IM,MD,MB,MI,MS,RD) (_B(PX), __SSELimr(OP, IM, MD, MB, MI, MS, RD)) - -#define _SSEQrr(PX,OP,RS,RSA,RD,RDA) (_B(PX), __SSEQrr(OP, RS, RSA, RD, RDA)) -#define _SSEQmr(PX,OP,MD,MB,MI,MS,RD,RDA) (_B(PX), __SSEQmr(OP, MD, MB, MI, MS, RD, RDA)) -#define _SSEQrm(PX,OP,RS,RSA,MD,MB,MI,MS) (_B(PX), __SSEQrm(OP, RS, RSA, MD, MB, MI, MS)) - -#define _SSEPSrr(OP,RS,RD) __SSELrr( OP, RS,_rX, RD,_rX) -#define _SSEPSmr(OP,MD,MB,MI,MS,RD) __SSELmr( OP, MD, MB, MI, MS, RD,_rX) -#define _SSEPSrm(OP,RS,MD,MB,MI,MS) __SSELrm( OP, RS,_rX, MD, MB, MI, MS) -#define _SSEPSirr(OP,IM,RS,RD) __SSELirr( OP, IM, RS, RD) -#define _SSEPSimr(OP,IM,MD,MB,MI,MS,RD) __SSELimr( OP, IM, MD, MB, MI, MS, RD) - -#define _SSEPDrr(OP,RS,RD) _SSELrr(0x66, OP, RS,_rX, RD,_rX) -#define _SSEPDmr(OP,MD,MB,MI,MS,RD) _SSELmr(0x66, OP, MD, MB, MI, MS, RD,_rX) -#define _SSEPDrm(OP,RS,MD,MB,MI,MS) _SSELrm(0x66, OP, RS,_rX, MD, MB, MI, MS) -#define _SSEPDirr(OP,IM,RS,RD) _SSELirr(0x66, OP, IM, RS, RD) -#define _SSEPDimr(OP,IM,MD,MB,MI,MS,RD) _SSELimr(0x66, OP, IM, MD, MB, MI, MS, RD) - -#define _SSESSrr(OP,RS,RD) _SSELrr(0xf3, OP, RS,_rX, RD,_rX) -#define _SSESSmr(OP,MD,MB,MI,MS,RD) _SSELmr(0xf3, OP, MD, MB, MI, MS, RD,_rX) -#define _SSESSrm(OP,RS,MD,MB,MI,MS) _SSELrm(0xf3, OP, RS,_rX, MD, MB, MI, MS) -#define _SSESSirr(OP,IM,RS,RD) _SSELirr(0xf3, OP, IM, RS, RD) -#define _SSESSimr(OP,IM,MD,MB,MI,MS,RD) _SSELimr(0xf3, OP, IM, MD, MB, MI, MS, RD) - -#define _SSESDrr(OP,RS,RD) _SSELrr(0xf2, OP, RS,_rX, RD,_rX) -#define _SSESDmr(OP,MD,MB,MI,MS,RD) _SSELmr(0xf2, OP, MD, MB, MI, MS, RD,_rX) -#define _SSESDrm(OP,RS,MD,MB,MI,MS) _SSELrm(0xf2, OP, RS,_rX, MD, MB, MI, MS) -#define _SSESDirr(OP,IM,RS,RD) _SSELirr(0xf2, OP, IM, RS, RD) -#define _SSESDimr(OP,IM,MD,MB,MI,MS,RD) _SSELimr(0xf2, OP, IM, MD, MB, MI, MS, RD) - -#define ADDPSrr(RS, RD) _SSEPSrr(X86_SSE_ADD, RS, RD) -#define ADDPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_ADD, MD, MB, MI, MS, RD) -#define ADDPDrr(RS, RD) _SSEPDrr(X86_SSE_ADD, RS, RD) -#define ADDPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_ADD, MD, MB, MI, MS, RD) - -#define ADDSSrr(RS, RD) _SSESSrr(X86_SSE_ADD, RS, RD) -#define ADDSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_ADD, MD, MB, MI, MS, RD) -#define ADDSDrr(RS, RD) _SSESDrr(X86_SSE_ADD, RS, RD) -#define ADDSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_ADD, MD, MB, MI, MS, RD) - -#define ANDNPSrr(RS, RD) _SSEPSrr(X86_SSE_ANDN, RS, RD) -#define ANDNPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_ANDN, MD, MB, MI, MS, RD) -#define ANDNPDrr(RS, RD) _SSEPDrr(X86_SSE_ANDN, RS, RD) -#define ANDNPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_ANDN, MD, MB, MI, MS, RD) - -#define ANDPSrr(RS, RD) _SSEPSrr(X86_SSE_AND, RS, RD) -#define ANDPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_AND, MD, MB, MI, MS, RD) -#define ANDPDrr(RS, RD) _SSEPDrr(X86_SSE_AND, RS, RD) -#define ANDPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_AND, MD, MB, MI, MS, RD) - -#define CMPPSrr(IM, RS, RD) _SSEPSirr(X86_SSE_CMP, IM, RS, RD) -#define CMPPSmr(IM, MD, MB, MI, MS, RD) _SSEPSimr(X86_SSE_CMP, IM, MD, MB, MI, MS, RD) -#define CMPPDrr(IM, RS, RD) _SSEPDirr(X86_SSE_CMP, IM, RS, RD) -#define CMPPDmr(IM, MD, MB, MI, MS, RD) _SSEPDimr(X86_SSE_CMP, IM, MD, MB, MI, MS, RD) - -#define CMPSSrr(IM, RS, RD) _SSESSirr(X86_SSE_CMP, IM, RS, RD) -#define CMPSSmr(IM, MD, MB, MI, MS, RD) _SSESSimr(X86_SSE_CMP, IM, MD, MB, MI, MS, RD) -#define CMPSDrr(IM, RS, RD) _SSESDirr(X86_SSE_CMP, IM, RS, RD) -#define CMPSDmr(IM, MD, MB, MI, MS, RD) _SSESDimr(X86_SSE_CMP, IM, MD, MB, MI, MS, RD) - -#define DIVPSrr(RS, RD) _SSEPSrr(X86_SSE_DIV, RS, RD) -#define DIVPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_DIV, MD, MB, MI, MS, RD) -#define DIVPDrr(RS, RD) _SSEPDrr(X86_SSE_DIV, RS, RD) -#define DIVPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_DIV, MD, MB, MI, MS, RD) - -#define DIVSSrr(RS, RD) _SSESSrr(X86_SSE_DIV, RS, RD) -#define DIVSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_DIV, MD, MB, MI, MS, RD) -#define DIVSDrr(RS, RD) _SSESDrr(X86_SSE_DIV, RS, RD) -#define DIVSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_DIV, MD, MB, MI, MS, RD) - -#define MAXPSrr(RS, RD) _SSEPSrr(X86_SSE_MAX, RS, RD) -#define MAXPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_MAX, MD, MB, MI, MS, RD) -#define MAXPDrr(RS, RD) _SSEPDrr(X86_SSE_MAX, RS, RD) -#define MAXPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_MAX, MD, MB, MI, MS, RD) - -#define MAXSSrr(RS, RD) _SSESSrr(X86_SSE_MAX, RS, RD) -#define MAXSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_MAX, MD, MB, MI, MS, RD) -#define MAXSDrr(RS, RD) _SSESDrr(X86_SSE_MAX, RS, RD) -#define MAXSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_MAX, MD, MB, MI, MS, RD) - -#define MINPSrr(RS, RD) _SSEPSrr(X86_SSE_MIN, RS, RD) -#define MINPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_MIN, MD, MB, MI, MS, RD) -#define MINPDrr(RS, RD) _SSEPDrr(X86_SSE_MIN, RS, RD) -#define MINPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_MIN, MD, MB, MI, MS, RD) - -#define MINSSrr(RS, RD) _SSESSrr(X86_SSE_MIN, RS, RD) -#define MINSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_MIN, MD, MB, MI, MS, RD) -#define MINSDrr(RS, RD) _SSESDrr(X86_SSE_MIN, RS, RD) -#define MINSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_MIN, MD, MB, MI, MS, RD) - -#define MULPSrr(RS, RD) _SSEPSrr(X86_SSE_MUL, RS, RD) -#define MULPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_MUL, MD, MB, MI, MS, RD) -#define MULPDrr(RS, RD) _SSEPDrr(X86_SSE_MUL, RS, RD) -#define MULPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_MUL, MD, MB, MI, MS, RD) - -#define MULSSrr(RS, RD) _SSESSrr(X86_SSE_MUL, RS, RD) -#define MULSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_MUL, MD, MB, MI, MS, RD) -#define MULSDrr(RS, RD) _SSESDrr(X86_SSE_MUL, RS, RD) -#define MULSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_MUL, MD, MB, MI, MS, RD) - -#define ORPSrr(RS, RD) _SSEPSrr(X86_SSE_OR, RS, RD) -#define ORPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_OR, MD, MB, MI, MS, RD) -#define ORPDrr(RS, RD) _SSEPDrr(X86_SSE_OR, RS, RD) -#define ORPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_OR, MD, MB, MI, MS, RD) - -#define RCPPSrr(RS, RD) _SSEPSrr(X86_SSE_RCP, RS, RD) -#define RCPPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_RCP, MD, MB, MI, MS, RD) -#define RCPSSrr(RS, RD) _SSESSrr(X86_SSE_RCP, RS, RD) -#define RCPSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_RCP, MD, MB, MI, MS, RD) - -#define RSQRTPSrr(RS, RD) _SSEPSrr(X86_SSE_RSQRT, RS, RD) -#define RSQRTPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_RSQRT, MD, MB, MI, MS, RD) -#define RSQRTSSrr(RS, RD) _SSESSrr(X86_SSE_RSQRT, RS, RD) -#define RSQRTSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_RSQRT, MD, MB, MI, MS, RD) - -#define SQRTPSrr(RS, RD) _SSEPSrr(X86_SSE_SQRT, RS, RD) -#define SQRTPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) -#define SQRTPDrr(RS, RD) _SSEPDrr(X86_SSE_SQRT, RS, RD) -#define SQRTPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) - -#define SQRTSSrr(RS, RD) _SSESSrr(X86_SSE_SQRT, RS, RD) -#define SQRTSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) -#define SQRTSDrr(RS, RD) _SSESDrr(X86_SSE_SQRT, RS, RD) -#define SQRTSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) - -#define SUBPSrr(RS, RD) _SSEPSrr(X86_SSE_SUB, RS, RD) -#define SUBPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_SUB, MD, MB, MI, MS, RD) -#define SUBPDrr(RS, RD) _SSEPDrr(X86_SSE_SUB, RS, RD) -#define SUBPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_SUB, MD, MB, MI, MS, RD) - -#define SUBSSrr(RS, RD) _SSESSrr(X86_SSE_SUB, RS, RD) -#define SUBSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_SUB, MD, MB, MI, MS, RD) -#define SUBSDrr(RS, RD) _SSESDrr(X86_SSE_SUB, RS, RD) -#define SUBSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_SUB, MD, MB, MI, MS, RD) - -#define XORPSrr(RS, RD) _SSEPSrr(X86_SSE_XOR, RS, RD) -#define XORPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_XOR, MD, MB, MI, MS, RD) -#define XORPDrr(RS, RD) _SSEPDrr(X86_SSE_XOR, RS, RD) -#define XORPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_XOR, MD, MB, MI, MS, RD) - -#define COMISSrr(RS, RD) _SSEPSrr(X86_SSE_COMI, RS, RD) -#define COMISSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_COMI, MD, MB, MI, MS, RD) -#define COMISDrr(RS, RD) _SSEPDrr(X86_SSE_COMI, RS, RD) -#define COMISDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_COMI, MD, MB, MI, MS, RD) - -#define UCOMISSrr(RS, RD) _SSEPSrr(X86_SSE_UCOMI, RS, RD) -#define UCOMISSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD) -#define UCOMISDrr(RS, RD) _SSEPDrr(X86_SSE_UCOMI, RS, RD) -#define UCOMISDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD) - -#define MOVAPSrr(RS, RD) _SSEPSrr(0x28, RS, RD) -#define MOVAPSmr(MD, MB, MI, MS, RD) _SSEPSmr(0x28, MD, MB, MI, MS, RD) -#define MOVAPSrm(RS, MD, MB, MI, MS) _SSEPSrm(0x29, RS, MD, MB, MI, MS) - -#define MOVAPDrr(RS, RD) _SSEPDrr(0x28, RS, RD) -#define MOVAPDmr(MD, MB, MI, MS, RD) _SSEPDmr(0x28, MD, MB, MI, MS, RD) -#define MOVAPDrm(RS, MD, MB, MI, MS) _SSEPDrm(0x29, RS, MD, MB, MI, MS) - -#define CVTDQ2PDrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTDQ2PD, RS,_rX, RD,_rX) -#define CVTDQ2PDmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTDQ2PD, MD, MB, MI, MS, RD,_rX) -#define CVTDQ2PSrr(RS, RD) __SSELrr( X86_SSE_CVTDQ2PS, RS,_rX, RD,_rX) -#define CVTDQ2PSmr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTDQ2PS, MD, MB, MI, MS, RD,_rX) -#define CVTPD2DQrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTPD2DQ, RS,_rX, RD,_rX) -#define CVTPD2DQmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTPD2DQ, MD, MB, MI, MS, RD,_rX) -#define CVTPD2PIrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTPD2PI, RS,_rX, RD,_rM) -#define CVTPD2PImr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTPD2PI, MD, MB, MI, MS, RD,_rM) -#define CVTPD2PSrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTPD2PS, RS,_rX, RD,_rX) -#define CVTPD2PSmr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTPD2PS, MD, MB, MI, MS, RD,_rX) -#define CVTPI2PDrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTPI2PD, RS,_rM, RD,_rX) -#define CVTPI2PDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTPI2PD, MD, MB, MI, MS, RD,_rX) -#define CVTPI2PSrr(RS, RD) __SSELrr( X86_SSE_CVTPI2PS, RS,_rM, RD,_rX) -#define CVTPI2PSmr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTPI2PS, MD, MB, MI, MS, RD,_rX) -#define CVTPS2DQrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTPS2DQ, RS,_rX, RD,_rX) -#define CVTPS2DQmr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTPS2DQ, MD, MB, MI, MS, RD,_rX) -#define CVTPS2PDrr(RS, RD) __SSELrr( X86_SSE_CVTPS2PD, RS,_rX, RD,_rX) -#define CVTPS2PDmr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTPS2PD, MD, MB, MI, MS, RD,_rX) -#define CVTPS2PIrr(RS, RD) __SSELrr( X86_SSE_CVTPS2PI, RS,_rX, RD,_rM) -#define CVTPS2PImr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTPS2PI, MD, MB, MI, MS, RD,_rM) -#define CVTSD2SILrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTSD2SI, RS,_rX, RD,_r4) -#define CVTSD2SILmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTSD2SI, MD, MB, MI, MS, RD,_r4) -#define CVTSD2SIQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTSD2SI, RS,_rX, RD,_r8) -#define CVTSD2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTSD2SI, MD, MB, MI, MS, RD,_r8) -#define CVTSD2SSrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTSD2SS, RS,_rX, RD,_rX) -#define CVTSD2SSmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTSD2SS, MD, MB, MI, MS, RD,_rX) -#define CVTSI2SDLrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTSI2SD, RS,_r4, RD,_rX) -#define CVTSI2SDLmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTSI2SD, MD, MB, MI, MS, RD,_rX) -#define CVTSI2SDQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTSI2SD, RS,_r8, RD,_rX) -#define CVTSI2SDQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTSI2SD, MD, MB, MI, MS, RD,_rX) -#define CVTSI2SSLrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTSI2SS, RS,_r4, RD,_rX) -#define CVTSI2SSLmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTSI2SS, MD, MB, MI, MS, RD,_rX) -#define CVTSI2SSQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTSI2SS, RS,_r8, RD,_rX) -#define CVTSI2SSQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTSI2SS, MD, MB, MI, MS, RD,_rX) -#define CVTSS2SDrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTSS2SD, RS,_rX, RD,_rX) -#define CVTSS2SDmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTSS2SD, MD, MB, MI, MS, RD,_rX) -#define CVTSS2SILrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTSS2SI, RS,_rX, RD,_r4) -#define CVTSS2SILmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTSS2SI, MD, MB, MI, MS, RD,_r4) -#define CVTSS2SIQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTSS2SI, RS,_rX, RD,_r8) -#define CVTSS2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTSS2SI, MD, MB, MI, MS, RD,_r8) -#define CVTTPD2PIrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTTPD2PI, RS,_rX, RD,_rM) -#define CVTTPD2PImr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTTPD2PI, MD, MB, MI, MS, RD,_rM) -#define CVTTPD2DQrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTTPD2DQ, RS,_rX, RD,_rX) -#define CVTTPD2DQmr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTTPD2DQ, MD, MB, MI, MS, RD,_rX) -#define CVTTPS2DQrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTTPS2DQ, RS,_rX, RD,_rX) -#define CVTTPS2DQmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTTPS2DQ, MD, MB, MI, MS, RD,_rX) -#define CVTTPS2PIrr(RS, RD) __SSELrr( X86_SSE_CVTTPS2PI, RS,_rX, RD,_rM) -#define CVTTPS2PImr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTTPS2PI, MD, MB, MI, MS, RD,_rM) -#define CVTTSD2SILrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTTSD2SI, RS,_rX, RD,_r4) -#define CVTTSD2SILmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTTSD2SI, MD, MB, MI, MS, RD,_r4) -#define CVTTSD2SIQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTTSD2SI, RS,_rX, RD,_r8) -#define CVTTSD2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTTSD2SI, MD, MB, MI, MS, RD,_r8) -#define CVTTSS2SILrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTTSS2SI, RS,_rX, RD,_r4) -#define CVTTSS2SILmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTTSS2SI, MD, MB, MI, MS, RD,_r4) -#define CVTTSS2SIQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTTSS2SI, RS,_rX, RD,_r8) -#define CVTTSS2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTTSS2SI, MD, MB, MI, MS, RD,_r8) - -#define MOVDXDrr(RS, RD) _SSELrr(0x66, 0x6e, RS,_r4, RD,_rX) -#define MOVDXDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX) -#define MOVQXDrr(RS, RD) _SSEQrr(0x66, 0x6e, RS,_r8, RD,_rX) -#define MOVQXDmr(MD, MB, MI, MS, RD) _SSEQmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX) - -#define MOVDXSrr(RS, RD) _SSELrr(0x66, 0x7e, RD,_r4, RS,_rX) -#define MOVDXSrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS) -#define MOVQXSrr(RS, RD) _SSEQrr(0x66, 0x7e, RD,_r8, RS,_rX) -#define MOVQXSrm(RS, MD, MB, MI, MS) _SSEQrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS) - -#define MOVDLMrr(RS, RD) __SSELrr( 0x6e, RS,_r4, RD,_rM) -#define MOVDLMmr(MD, MB, MI, MS, RD) __SSELmr( 0x6e, MD, MB, MI, MS, RD,_rM) -#define MOVDQMrr(RS, RD) __SSEQrr( 0x6e, RS,_r8, RD,_rM) -#define MOVDQMmr(MD, MB, MI, MS, RD) __SSEQmr( 0x6e, MD, MB, MI, MS, RD,_rM) - -#define MOVDMLrr(RS, RD) __SSELrr( 0x7e, RS,_rM, RD,_r4) -#define MOVDMLrm(RS, MD, MB, MI, MS) __SSELrm( 0x7e, RS,_rM, MD, MB, MI, MS) -#define MOVDMQrr(RS, RD) __SSEQrr( 0x7e, RS,_rM, RD,_r8) -#define MOVDMQrm(RS, MD, MB, MI, MS) __SSEQrm( 0x7e, RS,_rM, MD, MB, MI, MS) - -#define MOVDQ2Qrr(RS, RD) _SSELrr(0xf2, 0xd6, RS,_rX, RD,_rM) -#define MOVMSKPSrr(RS, RD) __SSELrr( 0x50, RS,_rX, RD,_r4) -#define MOVMSKPDrr(RS, RD) _SSELrr(0x66, 0x50, RS,_rX, RD,_r4) - -#define MOVHLPSrr(RS, RD) __SSELrr( 0x12, RS,_rX, RD,_rX) -#define MOVLHPSrr(RS, RD) __SSELrr( 0x16, RS,_rX, RD,_rX) - -#define MOVDQArr(RS, RD) _SSELrr(0x66, 0x6f, RS,_rX, RD,_rX) -#define MOVDQAmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x6f, MD, MB, MI, MS, RD,_rX) -#define MOVDQArm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x7f, RS,_rX, MD, MB, MI, MS) - -#define MOVDQUrr(RS, RD) _SSELrr(0xf3, 0x6f, RS,_rX, RD,_rX) -#define MOVDQUmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, 0x6f, MD, MB, MI, MS, RD,_rX) -#define MOVDQUrm(RS, MD, MB, MI, MS) _SSELrm(0xf3, 0x7f, RS,_rX, MD, MB, MI, MS) - -#define MOVHPDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x16, MD, MB, MI, MS, RD,_rX) -#define MOVHPDrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x17, RS,_rX, MD, MB, MI, MS) -#define MOVHPSmr(MD, MB, MI, MS, RD) __SSELmr( 0x16, MD, MB, MI, MS, RD,_rX) -#define MOVHPSrm(RS, MD, MB, MI, MS) __SSELrm( 0x17, RS,_rX, MD, MB, MI, MS) - -#define MOVLPDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x12, MD, MB, MI, MS, RD,_rX) -#define MOVLPDrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x13, RS,_rX, MD, MB, MI, MS) -#define MOVLPSmr(MD, MB, MI, MS, RD) __SSELmr( 0x12, MD, MB, MI, MS, RD,_rX) -#define MOVLPSrm(RS, MD, MB, MI, MS) __SSELrm( 0x13, RS,_rX, MD, MB, MI, MS) - - -/* --- Floating-Point instructions ----------------------------------------- */ - -enum { - X86_F2XM1 = 0xd9f0, - X86_FABS = 0xd9e1, - X86_FADD = 0xd8c0, // m32fp, m64fp, sti0, st0i, pst0i - X86_FIADD = 0xda00, // m32int, m16int - X86_FBLD = 0xdf04, // mem - X86_FBSTP = 0xdf06, // mem - X86_FCHS = 0xd9e0, - X86_FCMOVB = 0xdac0, // sti0 - X86_FCMOVE = 0xdac8, // sti0 - X86_FCMOVBE = 0xdad0, // sti0 - X86_FCMOVU = 0xdad8, // sti0 - X86_FCMOVNB = 0xdbc0, // sti0 - X86_FCMOVNE = 0xdbc8, // sti0 - X86_FCMOVNBE = 0xdbd0, // sti0 - X86_FCMOVNU = 0xdbd8, // sti0 - X86_FCOM = 0xd8d2, // m32fp, m64fp, sti - X86_FCOMP = 0xd8db, // m32fp, m64fp, sti - X86_FCOMPP = 0xded9, - X86_FCOMI = 0xdbf0, // sti0 - X86_FCOMIP = 0xdff0, // sti0 - X86_FUCOMI = 0xdbe8, // sti0 - X86_FUCOMIP = 0xdfe8, // sti0 - X86_FCOS = 0xd9ff, - X86_FDECSTP = 0xd9f6, - X86_FDIV = 0xd8f6, // m32fp, m64fp, sti0, st0i, pst0i - X86_FIDIV = 0xda06, // m32int, m16int - X86_FDIVR = 0xd8ff, // m32fp, m64fp, sti0, st0i, pst0i - X86_FIDIVR = 0xda07, // m32int, m16int - X86_FFREE = 0xddc0, // sti - X86_FICOM = 0xda02, // m32int, m16int - X86_FICOMP = 0xda03, // m32int, m16int - X86_FILD = 0xdb00, // m32int, m16int - X86_FILDQ = 0xdf05, // mem - X86_FINCSTP = 0xd9f7, - X86_FIST = 0xdb02, // m32int, m16int - X86_FISTP = 0xdb03, // m32int, m16int - X86_FISTPQ = 0xdf07, // mem - X86_FISTTP = 0xdb01, // m32int, m16int - X86_FISTTPQ = 0xdd01, // mem - X86_FLD = 0xd900, // m32fp, m64fp - X86_FLDT = 0xdb05, // mem - X86_FLD1 = 0xd9e8, - X86_FLDL2T = 0xd9e9, - X86_FLDL2E = 0xd9ea, - X86_FLDPI = 0xd9eb, - X86_FLDLG2 = 0xd9ec, - X86_FLDLN2 = 0xd9ed, - X86_FLDZ = 0xd9ee, - X86_FMUL = 0xd8c9, // m32fp, m64fp, sti0, st0i, pst0i - X86_FIMUL = 0xda01, // m32int, m16int - X86_FNOP = 0xd9d0, - X86_FPATAN = 0xd9f3, - X86_FPREM = 0xd9f8, - X86_FPREM1 = 0xd9f5, - X86_FPTAN = 0xd9f2, - X86_FRNDINT = 0xd9fc, - X86_FSCALE = 0xd9fd, - X86_FSIN = 0xd9fe, - X86_FSINCOS = 0xd9fb, - X86_FSQRT = 0xd9fa, - X86_FSTS = 0xd902, // mem - X86_FSTD = 0xdd02, // mem - X86_FST = 0xddd0, // sti - X86_FSTPS = 0xd903, // mem - X86_FSTPD = 0xdd03, // mem - X86_FSTPT = 0xdb07, // mem - X86_FSTP = 0xddd8, // sti - X86_FSUB = 0xd8e4, // m32fp, m64fp, sti0, st0i, pst0i - X86_FISUB = 0xda04, // m32int, m16int - X86_FSUBR = 0xd8ed, // m32fp, m64fp, sti0, st0i, pst0i - X86_FISUBR = 0xda05, // m32int, m16int - X86_FTST = 0xd9e4, - X86_FUCOM = 0xdde0, // sti - X86_FUCOMP = 0xdde8, // sti - X86_FUCOMPP = 0xdae9, - X86_FXAM = 0xd9e5, - X86_FXCH = 0xd9c8, // sti - X86_FXTRACT = 0xd9f4, - X86_FYL2X = 0xd9f1, - X86_FYL2XP1 = 0xd9f9, -}; - -#define _FPU(OP) _OO(OP) -#define _FPUm(OP, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X((OP)>>8, (OP)&7, MD, MB, MI, MS)) -#define _FPUSm(OP, MD, MB, MI, MS) _FPUm(OP, MD, MB, MI, MS) -#define _FPUDm(OP, MD, MB, MI, MS) _FPUm((OP)|0x400, MD, MB, MI, MS) -#define _FPULm(OP, MD, MB, MI, MS) _FPUm(OP, MD, MB, MI, MS) -#define _FPUWm(OP, MD, MB, MI, MS) _FPUm((OP)|0x400, MD, MB, MI, MS) -#define _FPUr(OP, RR) _OOr((OP)&0xfff8, _rF(RR)) -#define _FPU0r(OP, RD) _FPUr((OP)|0x400, RD) -#define _FPUr0(OP, RS) _FPUr((OP) , RS) -#define _FPUrr(OP, RS, RD) (_rST0P(RS) ? _FPU0r(OP, RD) : (_rST0P(RD) ? _FPUr0(OP, RS) : x86_emit_failure("FPU instruction without st0"))) -#define _FPUP0r(OP, RD) _FPU0r((OP)|0x200, RD) - -#define F2XM1() _FPU(X86_F2XM1) -#define FABS() _FPU(X86_FABS) -#define FADDSm(MD, MB, MI, MS) _FPUSm(X86_FADD, MD, MB, MI, MS) -#define FADDDm(MD, MB, MI, MS) _FPUDm(X86_FADD, MD, MB, MI, MS) -#define FADDP0r(RD) _FPUP0r(X86_FADD, RD) -#define FADDrr(RS, RD) _FPUrr(X86_FADD, RS, RD) -#define FADD0r(RD) _FPU0r(X86_FADD, RD) -#define FADDr0(RS) _FPUr0(X86_FADD, RS) -#define FIADDWm(MD, MB, MI, MS) _FPUWm(X86_FIADD, MD, MB, MI, MS) -#define FIADDLm(MD, MB, MI, MS) _FPULm(X86_FIADD, MD, MB, MI, MS) -#define FBLDm(MD, MB, MI, MS) _FPUm(X86_FBLD, MD, MB, MI, MS) -#define FBSTPm(MD, MB, MI, MS) _FPUm(X86_FBSTP, MD, MB, MI, MS) -#define FCHS() _FPU(X86_FCHS) -#define FCMOVBr0(RS) _FPUr0(X86_FCMOVB, RS) -#define FCMOVEr0(RS) _FPUr0(X86_FCMOVE, RS) -#define FCMOVBEr0(RS) _FPUr0(X86_FCMOVBE, RS) -#define FCMOVUr0(RS) _FPUr0(X86_FCMOVU, RS) -#define FCMOVNBr0(RS) _FPUr0(X86_FCMOVNB, RS) -#define FCMOVNEr0(RS) _FPUr0(X86_FCMOVNE, RS) -#define FCMOVNBEr0(RS) _FPUr0(X86_FCMOVNBE, RS) -#define FCMOVNUr0(RS) _FPUr0(X86_FCMOVNU, RS) -#define FCOMSm(MD, MB, MI, MS) _FPUSm(X86_FCOM, MD, MB, MI, MS) -#define FCOMDm(MD, MB, MI, MS) _FPUDm(X86_FCOM, MD, MB, MI, MS) -#define FCOMr(RD) _FPUr(X86_FCOM, RD) -#define FCOMPSm(MD, MB, MI, MS) _FPUSm(X86_FCOMP, MD, MB, MI, MS) -#define FCOMPDm(MD, MB, MI, MS) _FPUDm(X86_FCOMP, MD, MB, MI, MS) -#define FCOMPr(RD) _FPUr(X86_FCOMP, RD) -#define FCOMPP() _FPU(X86_FCOMPP) -#define FCOMIr0(RS) _FPUr0(X86_FCOMI, RS) -#define FCOMIPr0(RS) _FPUr0(X86_FCOMIP, RS) -#define FUCOMIr0(RS) _FPUr0(X86_FUCOMI, RS) -#define FUCOMIPr0(RS) _FPUr0(X86_FUCOMIP, RS) -#define FCOS() _FPU(X86_FCOS) -#define FDECSTP() _FPU(X86_FDECSTP) -#define FDIVSm(MD, MB, MI, MS) _FPUSm(X86_FDIV, MD, MB, MI, MS) -#define FDIVDm(MD, MB, MI, MS) _FPUDm(X86_FDIV, MD, MB, MI, MS) -#define FDIVP0r(RD) _FPUP0r(X86_FDIV, RD) -#define FDIVrr(RS, RD) _FPUrr(X86_FDIV, RS, RD) -#define FDIV0r(RD) _FPU0r(X86_FDIV, RD) -#define FDIVr0(RS) _FPUr0(X86_FDIV, RS) -#define FIDIVWm(MD, MB, MI, MS) _FPUWm(X86_FIDIV, MD, MB, MI, MS) -#define FIDIVLm(MD, MB, MI, MS) _FPULm(X86_FIDIV, MD, MB, MI, MS) -#define FDIVRSm(MD, MB, MI, MS) _FPUSm(X86_FDIVR, MD, MB, MI, MS) -#define FDIVRDm(MD, MB, MI, MS) _FPUDm(X86_FDIVR, MD, MB, MI, MS) -#define FDIVRP0r(RD) _FPUP0r(X86_FDIVR, RD) -#define FDIVRrr(RS, RD) _FPUrr(X86_FDIVR, RS, RD) -#define FDIVR0r(RD) _FPU0r(X86_FDIVR, RD) -#define FDIVRr0(RS) _FPUr0(X86_FDIVR, RS) -#define FIDIVRWm(MD, MB, MI, MS) _FPUWm(X86_FIDIVR, MD, MB, MI, MS) -#define FIDIVRLm(MD, MB, MI, MS) _FPULm(X86_FIDIVR, MD, MB, MI, MS) -#define FFREEr(RD) _FPUr(X86_FFREE, RD) -#define FICOMWm(MD, MB, MI, MS) _FPUWm(X86_FICOM, MD, MB, MI, MS) -#define FICOMLm(MD, MB, MI, MS) _FPULm(X86_FICOM, MD, MB, MI, MS) -#define FICOMPWm(MD, MB, MI, MS) _FPUWm(X86_FICOMP, MD, MB, MI, MS) -#define FICOMPLm(MD, MB, MI, MS) _FPULm(X86_FICOMP, MD, MB, MI, MS) -#define FILDWm(MD, MB, MI, MS) _FPUWm(X86_FILD, MD, MB, MI, MS) -#define FILDLm(MD, MB, MI, MS) _FPULm(X86_FILD, MD, MB, MI, MS) -#define FILDQm(MD, MB, MI, MS) _FPUm(X86_FILDQ, MD, MB, MI, MS) -#define FINCSTP() _FPU(X86_FINCSTP) -#define FISTWm(MD, MB, MI, MS) _FPUWm(X86_FIST, MD, MB, MI, MS) -#define FISTLm(MD, MB, MI, MS) _FPULm(X86_FIST, MD, MB, MI, MS) -#define FISTPWm(MD, MB, MI, MS) _FPUWm(X86_FISTP, MD, MB, MI, MS) -#define FISTPLm(MD, MB, MI, MS) _FPULm(X86_FISTP, MD, MB, MI, MS) -#define FISTPQm(MD, MB, MI, MS) _FPUm(X86_FISTPQ, MD, MB, MI, MS) -#define FISTTPWm(MD, MB, MI, MS) _FPUWm(X86_FISTTP, MD, MB, MI, MS) -#define FISTTPLm(MD, MB, MI, MS) _FPULm(X86_FISTTP, MD, MB, MI, MS) -#define FISTTPQm(MD, MB, MI, MS) _FPUm(X86_FISTTPQ, MD, MB, MI, MS) -#define FLDSm(MD, MB, MI, MS) _FPUSm(X86_FLD, MD, MB, MI, MS) -#define FLDDm(MD, MB, MI, MS) _FPUDm(X86_FLD, MD, MB, MI, MS) -#define FLDTm(MD, MB, MI, MS) _FPUm(X86_FLDT, MD, MB, MI, MS) -#define FLD1() _FPU(X86_FLD1) -#define FLDL2T() _FPU(X86_FLDL2T) -#define FLDL2E() _FPU(X86_FLDL2E) -#define FLDPI() _FPU(X86_FLDPI) -#define FLDLG2() _FPU(X86_FLDLG2) -#define FLDLN2() _FPU(X86_FLDLN2) -#define FLDZ() _FPU(X86_FLDZ) -#define FMULSm(MD, MB, MI, MS) _FPUSm(X86_FMUL, MD, MB, MI, MS) -#define FMULDm(MD, MB, MI, MS) _FPUDm(X86_FMUL, MD, MB, MI, MS) -#define FMULP0r(RD) _FPUP0r(X86_FMUL, RD) -#define FMULrr(RS, RD) _FPUrr(X86_FMUL, RS, RD) -#define FMUL0r(RD) _FPU0r(X86_FMUL, RD) -#define FMULr0(RS) _FPUr0(X86_FMUL, RS) -#define FIMULWm(MD, MB, MI, MS) _FPUWm(X86_FIMUL, MD, MB, MI, MS) -#define FIMULLm(MD, MB, MI, MS) _FPULm(X86_FIMUL, MD, MB, MI, MS) -#define FNOP() _FPU(X86_FNOP) -#define FPATAN() _FPU(X86_FPATAN) -#define FPREM() _FPU(X86_FPREM) -#define FPREM1() _FPU(X86_FPREM1) -#define FPTAN() _FPU(X86_FPTAN) -#define FRNDINT() _FPU(X86_FRNDINT) -#define FSCALE() _FPU(X86_FSCALE) -#define FSIN() _FPU(X86_FSIN) -#define FSINCOS() _FPU(X86_FSINCOS) -#define FSQRT() _FPU(X86_FSQRT) -#define FSTSm(MD, MB, MI, MS) _FPUm(X86_FSTS, MD, MB, MI, MS) -#define FSTDm(MD, MB, MI, MS) _FPUm(X86_FSTD, MD, MB, MI, MS) -#define FSTr(RD) _FPUr(X86_FST, RD) -#define FSTPSm(MD, MB, MI, MS) _FPUm(X86_FSTPS, MD, MB, MI, MS) -#define FSTPDm(MD, MB, MI, MS) _FPUm(X86_FSTPD, MD, MB, MI, MS) -#define FSTPTm(MD, MB, MI, MS) _FPUm(X86_FSTPT, MD, MB, MI, MS) -#define FSTPr(RD) _FPUr(X86_FSTP, RD) -#define FSUBSm(MD, MB, MI, MS) _FPUSm(X86_FSUB, MD, MB, MI, MS) -#define FSUBDm(MD, MB, MI, MS) _FPUDm(X86_FSUB, MD, MB, MI, MS) -#define FSUBP0r(RD) _FPUP0r(X86_FSUB, RD) -#define FSUBrr(RS, RD) _FPUrr(X86_FSUB, RS, RD) -#define FSUB0r(RD) _FPU0r(X86_FSUB, RD) -#define FSUBr0(RS) _FPUr0(X86_FSUB, RS) -#define FISUBWm(MD, MB, MI, MS) _FPUWm(X86_FISUB, MD, MB, MI, MS) -#define FISUBLm(MD, MB, MI, MS) _FPULm(X86_FISUB, MD, MB, MI, MS) -#define FSUBRSm(MD, MB, MI, MS) _FPUSm(X86_FSUBR, MD, MB, MI, MS) -#define FSUBRDm(MD, MB, MI, MS) _FPUDm(X86_FSUBR, MD, MB, MI, MS) -#define FSUBRP0r(RD) _FPUP0r(X86_FSUBR, RD) -#define FSUBRrr(RS, RD) _FPUrr(X86_FSUBR, RS, RD) -#define FSUBR0r(RD) _FPU0r(X86_FSUBR, RD) -#define FSUBRr0(RS) _FPUr0(X86_FSUBR, RS) -#define FISUBRWm(MD, MB, MI, MS) _FPUWm(X86_FISUBR, MD, MB, MI, MS) -#define FISUBRLm(MD, MB, MI, MS) _FPULm(X86_FISUBR, MD, MB, MI, MS) -#define FTST() _FPU(X86_FTST) -#define FUCOMr(RD) _FPUr(X86_FUCOM, RD) -#define FUCOMPr(RD) _FPUr(X86_FUCOMP, RD) -#define FUCOMPP() _FPU(X86_FUCOMPP) -#define FXAM() _FPU(X86_FXAM) -#define FXCHr(RD) _FPUr(X86_FXCH, RD) -#define FXTRACT() _FPU(X86_FXTRACT) -#define FYL2X() _FPU(X86_FYL2X) -#define FYL2XP1() _FPU(X86_FYL2XP1) - -#endif /* X86_RTASM_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h deleted file mode 100644 index 9a612fb2..00000000 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ /dev/null @@ -1,609 +0,0 @@ -/* - * compiler/compemu.h - Public interface and definitions - * - * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer - * - * Adaptation for Basilisk II and improvements, copyright 2000-2005 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef COMPEMU_H -#define COMPEMU_H - -#include "newcpu.h" - -#if USE_JIT - -#if defined __i386__ || defined __x86_64__ -#include "flags_x86.h" -#else -#error "Unsupported JIT compiler for this architecture" -#endif - -#if JIT_DEBUG -/* dump some information (m68k block, x86 block addresses) about the compiler state */ -extern void compiler_dumpstate(void); -#endif - -/* Now that we do block chaining, and also have linked lists on each tag, - TAGMASK can be much smaller and still do its job. Saves several megs - of memory! */ -#define TAGMASK 0x0000ffff -#define TAGSIZE (TAGMASK+1) -#define MAXRUN 1024 -#define cacheline(x) (((uintptr)x)&TAGMASK) - -extern uae_u8* start_pc_p; -extern uae_u32 start_pc; - -struct blockinfo_t; - -struct cpu_history { - uae_u16 * location; -}; - -union cacheline { - cpuop_func * handler; - blockinfo_t * bi; -}; - -/* Use new spill/reload strategy when calling external functions */ -#define USE_OPTIMIZED_CALLS 0 -#if USE_OPTIMIZED_CALLS -#error implementation in progress -#endif - -/* (gb) When on, this option can save save up to 30% compilation time - * when many lazy flushes occur (e.g. apps in MacOS 8.x). - */ -#define USE_SEPARATE_BIA 1 - -/* Use chain of checksum_info_t to compute the block checksum */ -#define USE_CHECKSUM_INFO 1 - -/* Use code inlining, aka follow-up of constant jumps */ -#define USE_INLINING 1 - -/* Inlining requires the chained checksuming information */ -#if USE_INLINING -#undef USE_CHECKSUM_INFO -#define USE_CHECKSUM_INFO 1 -#endif - -/* Does flush_icache_range() only check for blocks falling in the requested range? */ -#define LAZY_FLUSH_ICACHE_RANGE 0 - -#define USE_F_ALIAS 1 -#define USE_OFFSET 1 -#define COMP_DEBUG 1 - -#if COMP_DEBUG -#define Dif(x) if (x) -#else -#define Dif(x) if (0) -#endif - -#define SCALE 2 - -#define BYTES_PER_INST 10240 /* paranoid ;-) */ -#define LONGEST_68K_INST 16 /* The number of bytes the longest possible - 68k instruction takes */ -#define MAX_CHECKSUM_LEN 2048 /* The maximum size we calculate checksums - for. Anything larger will be flushed - unconditionally even with SOFT_FLUSH */ -#define MAX_HOLD_BI 3 /* One for the current block, and up to two - for jump targets */ - -#define INDIVIDUAL_INST 0 -#if 1 -// gb-- my format from readcpu.cpp is not the same -#define FLAG_X 0x0010 -#define FLAG_N 0x0008 -#define FLAG_Z 0x0004 -#define FLAG_V 0x0002 -#define FLAG_C 0x0001 -#else -#define FLAG_C 0x0010 -#define FLAG_V 0x0008 -#define FLAG_Z 0x0004 -#define FLAG_N 0x0002 -#define FLAG_X 0x0001 -#endif -#define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V) -#define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V) - -#define KILLTHERAT 1 /* Set to 1 to avoid some partial_rat_stalls */ - -#if defined(__x86_64__) -#define N_REGS 16 /* really only 15, but they are numbered 0-3,5-15 */ -#else -#define N_REGS 8 /* really only 7, but they are numbered 0,1,2,3,5,6,7 */ -#endif -#define N_FREGS 6 /* That leaves us two positions on the stack to play with */ - -/* Functions exposed to newcpu, or to what was moved from newcpu.c to - * compemu_support.c */ -extern void compiler_init(void); -extern void compiler_exit(void); -extern bool compiler_use_jit(void); -extern void init_comp(void); -extern void flush(int save_regs); -extern void small_flush(int save_regs); -extern void set_target(uae_u8* t); -extern uae_u8* get_target(void); -extern void freescratch(void); -extern void build_comp(void); -extern void set_cache_state(int enabled); -extern int get_cache_state(void); -extern uae_u32 get_jitted_size(void); -extern void (*flush_icache)(int n); -extern void alloc_cache(void); -extern int check_for_cache_miss(void); - -/* JIT FPU compilation */ -extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra); -extern void comp_fbcc_opp (uae_u32 opcode); -extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra); - -extern uae_u32 needed_flags; -extern cacheline cache_tags[]; -extern uae_u8* comp_pc_p; -extern void* pushall_call_handler; - -#define VREGS 32 -#define VFREGS 16 - -#define INMEM 1 -#define CLEAN 2 -#define DIRTY 3 -#define UNDEF 4 -#define ISCONST 5 - -typedef struct { - uae_u32* mem; - uae_u32 val; - uae_u8 is_swapped; - uae_u8 status; - uae_s8 realreg; /* gb-- realreg can hold -1 */ - uae_u8 realind; /* The index in the holds[] array */ - uae_u8 needflush; - uae_u8 validsize; - uae_u8 dirtysize; - uae_u8 dummy; -} reg_status; - -typedef struct { - uae_u32* mem; - double val; - uae_u8 status; - uae_s8 realreg; /* gb-- realreg can hold -1 */ - uae_u8 realind; - uae_u8 needflush; -} freg_status; - -#define PC_P 16 -#define FLAGX 17 -#define FLAGTMP 18 -#define NEXT_HANDLER 19 -#define S1 20 -#define S2 21 -#define S3 22 -#define S4 23 -#define S5 24 -#define S6 25 -#define S7 26 -#define S8 27 -#define S9 28 -#define S10 29 -#define S11 30 -#define S12 31 - -#define FP_RESULT 8 -#define FS1 9 -#define FS2 10 -#define FS3 11 - -typedef struct { - uae_u32 touched; - uae_s8 holds[VREGS]; - uae_u8 nholds; - uae_u8 canbyte; - uae_u8 canword; - uae_u8 locked; -} n_status; - -typedef struct { - uae_u32 touched; - uae_s8 holds[VFREGS]; - uae_u8 nholds; - uae_u8 locked; -} fn_status; - -/* For flag handling */ -#define NADA 1 -#define TRASH 2 -#define VALID 3 - -/* needflush values */ -#define NF_SCRATCH 0 -#define NF_TOMEM 1 -#define NF_HANDLER 2 - -typedef struct { - /* Integer part */ - reg_status state[VREGS]; - n_status nat[N_REGS]; - uae_u32 flags_on_stack; - uae_u32 flags_in_flags; - uae_u32 flags_are_important; - /* FPU part */ - freg_status fate[VFREGS]; - fn_status fat[N_FREGS]; - - /* x86 FPU part */ - uae_s8 spos[N_FREGS]; - uae_s8 onstack[6]; - uae_s8 tos; -} bigstate; - -typedef struct { - /* Integer part */ - char virt[VREGS]; - char nat[N_REGS]; -} smallstate; - -extern bigstate live; -extern int touchcnt; - - -#define IMM uae_s32 -#define R1 uae_u32 -#define R2 uae_u32 -#define R4 uae_u32 -#define W1 uae_u32 -#define W2 uae_u32 -#define W4 uae_u32 -#define RW1 uae_u32 -#define RW2 uae_u32 -#define RW4 uae_u32 -#define MEMR uae_u32 -#define MEMW uae_u32 -#define MEMRW uae_u32 - -#define FW uae_u32 -#define FR uae_u32 -#define FRW uae_u32 - -#define MIDFUNC(nargs,func,args) void func args -#define MENDFUNC(nargs,func,args) -#define COMPCALL(func) func - -#define LOWFUNC(flags,mem,nargs,func,args) static __inline__ void func args -#define LENDFUNC(flags,mem,nargs,func,args) - -/* What we expose to the outside */ -#define DECLARE_MIDFUNC(func) extern void func -DECLARE_MIDFUNC(bt_l_ri(R4 r, IMM i)); -DECLARE_MIDFUNC(bt_l_rr(R4 r, R4 b)); -DECLARE_MIDFUNC(btc_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(btc_l_rr(RW4 r, R4 b)); -DECLARE_MIDFUNC(bts_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(bts_l_rr(RW4 r, R4 b)); -DECLARE_MIDFUNC(btr_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(btr_l_rr(RW4 r, R4 b)); -DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s)); -DECLARE_MIDFUNC(call_r(R4 r)); -DECLARE_MIDFUNC(sub_l_mi(IMM d, IMM s)); -DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s)); -DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s)); -DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s)); -DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i)); -DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i)); -DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(rol_l_rr(RW4 d, R1 r)); -DECLARE_MIDFUNC(rol_w_rr(RW2 d, R1 r)); -DECLARE_MIDFUNC(rol_b_rr(RW1 d, R1 r)); -DECLARE_MIDFUNC(shll_l_rr(RW4 d, R1 r)); -DECLARE_MIDFUNC(shll_w_rr(RW2 d, R1 r)); -DECLARE_MIDFUNC(shll_b_rr(RW1 d, R1 r)); -DECLARE_MIDFUNC(ror_b_ri(R1 r, IMM i)); -DECLARE_MIDFUNC(ror_w_ri(R2 r, IMM i)); -DECLARE_MIDFUNC(ror_l_ri(R4 r, IMM i)); -DECLARE_MIDFUNC(ror_l_rr(R4 d, R1 r)); -DECLARE_MIDFUNC(ror_w_rr(R2 d, R1 r)); -DECLARE_MIDFUNC(ror_b_rr(R1 d, R1 r)); -DECLARE_MIDFUNC(shrl_l_rr(RW4 d, R1 r)); -DECLARE_MIDFUNC(shrl_w_rr(RW2 d, R1 r)); -DECLARE_MIDFUNC(shrl_b_rr(RW1 d, R1 r)); -DECLARE_MIDFUNC(shra_l_rr(RW4 d, R1 r)); -DECLARE_MIDFUNC(shra_w_rr(RW2 d, R1 r)); -DECLARE_MIDFUNC(shra_b_rr(RW1 d, R1 r)); -DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i)); -DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i)); -DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i)); -DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i)); -DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i)); -DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i)); -DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i)); -DECLARE_MIDFUNC(setcc(W1 d, IMM cc)); -DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc)); -DECLARE_MIDFUNC(cmov_b_rr(RW1 d, R1 s, IMM cc)); -DECLARE_MIDFUNC(cmov_w_rr(RW2 d, R2 s, IMM cc)); -DECLARE_MIDFUNC(cmov_l_rr(RW4 d, R4 s, IMM cc)); -DECLARE_MIDFUNC(cmov_l_rm(RW4 d, IMM s, IMM cc)); -DECLARE_MIDFUNC(bsf_l_rr(W4 d, R4 s)); -DECLARE_MIDFUNC(pop_m(IMM d)); -DECLARE_MIDFUNC(push_m(IMM d)); -DECLARE_MIDFUNC(pop_l(W4 d)); -DECLARE_MIDFUNC(push_l_i(IMM i)); -DECLARE_MIDFUNC(push_l(R4 s)); -DECLARE_MIDFUNC(clear_16(RW4 r)); -DECLARE_MIDFUNC(clear_8(RW4 r)); -DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, R2 s)); -DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, R1 s)); -DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, R2 s)); -DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, R1 s)); -DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s)); -DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s)); -DECLARE_MIDFUNC(imul_32_32(RW4 d, R4 s)); -DECLARE_MIDFUNC(mul_32_32(RW4 d, R4 s)); -DECLARE_MIDFUNC(mov_b_rr(W1 d, R1 s)); -DECLARE_MIDFUNC(mov_w_rr(W2 d, R2 s)); -DECLARE_MIDFUNC(mov_l_rrm_indexed(W4 d,R4 baser, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_w_rrm_indexed(W2 d, R4 baser, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_b_rrm_indexed(W1 d, R4 baser, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_l_mrr_indexed(R4 baser, R4 index, IMM factor, R4 s)); -DECLARE_MIDFUNC(mov_w_mrr_indexed(R4 baser, R4 index, IMM factor, R2 s)); -DECLARE_MIDFUNC(mov_b_mrr_indexed(R4 baser, R4 index, IMM factor, R1 s)); -DECLARE_MIDFUNC(mov_l_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R4 s)); -DECLARE_MIDFUNC(mov_w_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R2 s)); -DECLARE_MIDFUNC(mov_b_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R1 s)); -DECLARE_MIDFUNC(mov_l_brrm_indexed(W4 d, IMM base, R4 baser, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_w_brrm_indexed(W2 d, IMM base, R4 baser, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_b_brrm_indexed(W1 d, IMM base, R4 baser, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_l_rR(W4 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_w_rR(W2 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_b_rR(W1 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_l_brR(W4 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_w_brR(W2 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_b_brR(W1 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_l_Ri(R4 d, IMM i, IMM offset)); -DECLARE_MIDFUNC(mov_w_Ri(R4 d, IMM i, IMM offset)); -DECLARE_MIDFUNC(mov_b_Ri(R4 d, IMM i, IMM offset)); -DECLARE_MIDFUNC(mov_l_Rr(R4 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_w_Rr(R4 d, R2 s, IMM offset)); -DECLARE_MIDFUNC(mov_b_Rr(R4 d, R1 s, IMM offset)); -DECLARE_MIDFUNC(lea_l_brr(W4 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, R4 s, R4 index, IMM factor, IMM offset)); -DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, R4 s, R4 index, IMM factor)); -DECLARE_MIDFUNC(mov_l_bRr(R4 d, R4 s, IMM offset)); -DECLARE_MIDFUNC(mov_w_bRr(R4 d, R2 s, IMM offset)); -DECLARE_MIDFUNC(mov_b_bRr(R4 d, R1 s, IMM offset)); -DECLARE_MIDFUNC(bswap_32(RW4 r)); -DECLARE_MIDFUNC(bswap_16(RW2 r)); -DECLARE_MIDFUNC(mov_l_rr(W4 d, R4 s)); -DECLARE_MIDFUNC(mov_l_mr(IMM d, R4 s)); -DECLARE_MIDFUNC(mov_w_mr(IMM d, R2 s)); -DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s)); -DECLARE_MIDFUNC(mov_b_mr(IMM d, R1 s)); -DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s)); -DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s)); -DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s)); -DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s)); -DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s) ); -DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s) ); -DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s) ); -DECLARE_MIDFUNC(test_l_ri(R4 d, IMM i)); -DECLARE_MIDFUNC(test_l_rr(R4 d, R4 s)); -DECLARE_MIDFUNC(test_w_rr(R2 d, R2 s)); -DECLARE_MIDFUNC(test_b_rr(R1 d, R1 s)); -DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i)); -DECLARE_MIDFUNC(and_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(and_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(and_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(or_l_rm(RW4 d, IMM s)); -DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i)); -DECLARE_MIDFUNC(or_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(or_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(or_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(adc_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(adc_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(adc_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(add_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(add_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(add_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i)); -DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i)); -DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i)); -DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i)); -DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i)); -DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i)); -DECLARE_MIDFUNC(sbb_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(sbb_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(sbb_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(sub_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(sub_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(sub_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(cmp_l(R4 d, R4 s)); -DECLARE_MIDFUNC(cmp_l_ri(R4 r, IMM i)); -DECLARE_MIDFUNC(cmp_w(R2 d, R2 s)); -DECLARE_MIDFUNC(cmp_b(R1 d, R1 s)); -DECLARE_MIDFUNC(xor_l(RW4 d, R4 s)); -DECLARE_MIDFUNC(xor_w(RW2 d, R2 s)); -DECLARE_MIDFUNC(xor_b(RW1 d, R1 s)); -DECLARE_MIDFUNC(live_flags(void)); -DECLARE_MIDFUNC(dont_care_flags(void)); -DECLARE_MIDFUNC(duplicate_carry(void)); -DECLARE_MIDFUNC(restore_carry(void)); -DECLARE_MIDFUNC(start_needflags(void)); -DECLARE_MIDFUNC(end_needflags(void)); -DECLARE_MIDFUNC(make_flags_live(void)); -DECLARE_MIDFUNC(call_r_11(R4 r, W4 out1, R4 in1, IMM osize, IMM isize)); -DECLARE_MIDFUNC(call_r_02(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2)); -DECLARE_MIDFUNC(forget_about(W4 r)); -DECLARE_MIDFUNC(nop(void)); - -DECLARE_MIDFUNC(f_forget_about(FW r)); -DECLARE_MIDFUNC(fmov_pi(FW r)); -DECLARE_MIDFUNC(fmov_log10_2(FW r)); -DECLARE_MIDFUNC(fmov_log2_e(FW r)); -DECLARE_MIDFUNC(fmov_loge_2(FW r)); -DECLARE_MIDFUNC(fmov_1(FW r)); -DECLARE_MIDFUNC(fmov_0(FW r)); -DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmov_ext_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmov_rr(FW d, FR s)); -DECLARE_MIDFUNC(fldcw_m_indexed(R4 index, IMM base)); -DECLARE_MIDFUNC(ftst_r(FR r)); -DECLARE_MIDFUNC(dont_care_fflags(void)); -DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s)); -DECLARE_MIDFUNC(fabs_rr(FW d, FR s)); -DECLARE_MIDFUNC(frndint_rr(FW d, FR s)); -DECLARE_MIDFUNC(fsin_rr(FW d, FR s)); -DECLARE_MIDFUNC(fcos_rr(FW d, FR s)); -DECLARE_MIDFUNC(ftwotox_rr(FW d, FR s)); -DECLARE_MIDFUNC(fetox_rr(FW d, FR s)); -DECLARE_MIDFUNC(flog2_rr(FW d, FR s)); -DECLARE_MIDFUNC(fneg_rr(FW d, FR s)); -DECLARE_MIDFUNC(fadd_rr(FRW d, FR s)); -DECLARE_MIDFUNC(fsub_rr(FRW d, FR s)); -DECLARE_MIDFUNC(fmul_rr(FRW d, FR s)); -DECLARE_MIDFUNC(frem_rr(FRW d, FR s)); -DECLARE_MIDFUNC(frem1_rr(FRW d, FR s)); -DECLARE_MIDFUNC(fdiv_rr(FRW d, FR s)); -DECLARE_MIDFUNC(fcmp_rr(FR d, FR s)); -DECLARE_MIDFUNC(fflags_into_flags(W2 tmp)); -#undef DECLARE_MIDFUNC - -extern int failure; -#define FAIL(x) do { failure|=x; } while (0) - -/* Convenience functions exposed to gencomp */ -extern uae_u32 m68k_pc_offset; -extern void readbyte(int address, int dest, int tmp); -extern void readword(int address, int dest, int tmp); -extern void readlong(int address, int dest, int tmp); -extern void writebyte(int address, int source, int tmp); -extern void writeword(int address, int source, int tmp); -extern void writelong(int address, int source, int tmp); -extern void writeword_clobber(int address, int source, int tmp); -extern void writelong_clobber(int address, int source, int tmp); -extern void get_n_addr(int address, int dest, int tmp); -extern void get_n_addr_jmp(int address, int dest, int tmp); -extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp); -/* Set native Z flag only if register is zero */ -extern void set_zero(int r, int tmp); -extern int kill_rodent(int r); -extern void sync_m68k_pc(void); -extern uae_u32 get_const(int r); -extern int is_const(int r); -extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond); - -#define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1)) -#define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o))) -#define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o))) - -struct blockinfo_t; - -typedef struct dep_t { - uae_u32* jmp_off; - struct blockinfo_t* target; - struct blockinfo_t* source; - struct dep_t** prev_p; - struct dep_t* next; -} dependency; - -typedef struct checksum_info_t { - uae_u8 *start_p; - uae_u32 length; - struct checksum_info_t *next; -} checksum_info; - -typedef struct blockinfo_t { - uae_s32 count; - cpuop_func* direct_handler_to_use; - cpuop_func* handler_to_use; - /* The direct handler does not check for the correct address */ - - cpuop_func* handler; - cpuop_func* direct_handler; - - cpuop_func* direct_pen; - cpuop_func* direct_pcc; - - uae_u8* pc_p; - - uae_u32 c1; - uae_u32 c2; -#if USE_CHECKSUM_INFO - checksum_info *csi; -#else - uae_u32 len; - uae_u32 min_pcp; -#endif - - struct blockinfo_t* next_same_cl; - struct blockinfo_t** prev_same_cl_p; - struct blockinfo_t* next; - struct blockinfo_t** prev_p; - - uae_u8 optlevel; - uae_u8 needed_flags; - uae_u8 status; - uae_u8 havestate; - - dependency dep[2]; /* Holds things we depend on */ - dependency* deplist; /* List of things that depend on this */ - smallstate env; - -#if JIT_DEBUG - /* (gb) size of the compiled block (direct handler) */ - uae_u32 direct_handler_size; -#endif -} blockinfo; - -#define BI_INVALID 0 -#define BI_ACTIVE 1 -#define BI_NEED_RECOMP 2 -#define BI_NEED_CHECK 3 -#define BI_CHECKING 4 -#define BI_COMPILING 5 -#define BI_FINALIZING 6 - -void execute_normal(void); -void exec_nostats(void); -void do_nothing(void); - -#else - -static __inline__ void flush_icache(int) { } -static __inline__ void build_comp() { } - -#endif /* !USE_JIT */ - -#endif /* COMPEMU_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp deleted file mode 100644 index bb536634..00000000 --- a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp +++ /dev/null @@ -1,1637 +0,0 @@ -/* - * compiler/compemu_fpp.cpp - Dynamic translation of FPU instructions - * - * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer - * - * Adaptation for Basilisk II and improvements, copyright 2000-2005 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * UAE - The Un*x Amiga Emulator - * - * MC68881 emulation - * - * Copyright 1996 Herman ten Brugge - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - */ - -#include "sysdeps.h" - -#include -#include - -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#include "main.h" -#include "compiler/compemu.h" -#include "fpu/fpu.h" -#include "fpu/flags.h" -#include "fpu/exceptions.h" -#include "fpu/rounding.h" - -#define DEBUG 0 -#include "debug.h" - -// gb-- WARNING: get_fpcr() and set_fpcr() support is experimental -#define HANDLE_FPCR 0 - -// - IEEE-based fpu core must be used -#if defined(FPU_IEEE) -# define CAN_HANDLE_FPCR -#endif - -// - Generic rounding mode and precision modes are supported if set together -#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION) -# define CAN_HANDLE_FPCR -#endif - -// - X86 rounding mode and precision modes are *not* supported but might work (?!) -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) -# define CAN_HANDLE_FPCR -#endif - -#if HANDLE_FPCR && !defined(CAN_HANDLE_FPCR) -# warning "Can't handle FPCR, will FAIL(1) at runtime" -# undef HANDLE_FPCR -# define HANDLE_FPCR 0 -#endif - -#define STATIC_INLINE static inline -#define MAKE_FPSR(r) do { fmov_rr(FP_RESULT,r); } while (0) - -#define delay nop() ;nop() -#define delay2 nop() ;nop() - -#define UNKNOWN_EXTRA 0xFFFFFFFF -static void fpuop_illg(uae_u32 opcode, uae_u32 extra) -{ -/* - if (extra == UNKNOWN_EXTRA) - printf("FPU opcode %x, extra UNKNOWN_EXTRA\n",opcode & 0xFFFF); - else - printf("FPU opcode %x, extra %x\n",opcode & 0xFFFF,extra & 0xFFFF); -*/ - op_illg(opcode); -} - -static uae_s32 temp_fp[4]; /* To convert between FP/integer */ - -/* return register number, or -1 for failure */ -STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra) -{ - uaecptr tmppc; - uae_u16 tmp; - int size; - int mode; - int reg; - double* src; - uae_u32 ad = 0; - static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; - static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; - - if ((extra & 0x4000) == 0) { - return ((extra >> 10) & 7); - } - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - switch (mode) { - case 0: - switch (size) { - case 6: - sign_extend_8_rr(S1,reg); - mov_l_mr((uintptr)temp_fp,S1); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - return FS1; - case 4: - sign_extend_16_rr(S1,reg); - mov_l_mr((uintptr)temp_fp,S1); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - return FS1; - case 0: - mov_l_mr((uintptr)temp_fp,reg); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - return FS1; - case 1: - mov_l_mr((uintptr)temp_fp,reg); - delay2; - fmovs_rm(FS1,(uintptr)temp_fp); - return FS1; - default: - return -1; - } - return -1; /* Should be unreachable */ - case 1: - return -1; /* Genuine invalid instruction */ - default: - break; - } - /* OK, we *will* have to load something from an address. Let's make - sure we know how to handle that, or quit early --- i.e. *before* - we do any postincrement/predecrement that we may regret */ - - switch (size) { - case 3: - return -1; - case 0: - case 1: - case 2: - case 4: - case 5: - case 6: - break; - default: - return -1; - } - - switch (mode) { - case 2: - ad=S1; /* We will change it, anyway ;-) */ - mov_l_rr(ad,reg+8); - break; - case 3: - ad=S1; - mov_l_rr(ad,reg+8); - lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size])); - break; - case 4: - ad=S1; - - lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size])); - mov_l_rr(ad,reg+8); - break; - case 5: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_rr(ad,reg+8); - lea_l_brr(ad,ad,off); - break; - } - case 6: - { - uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - calc_disp_ea_020(reg+8,dp,ad,S2); - break; - } - case 7: - switch (reg) { - case 0: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 1: - { - uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 2: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ - m68k_pc_offset; - uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2) --2); - ad=S1; - mov_l_ri(ad,address+PC16off); - break; - } - case 3: - return -1; - tmppc = m68k_getpc (); - tmp = next_iword (); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ m68k_pc_offset; - ad=S1; - // Immediate addressing mode && Operation Length == Byte -> - // Use the low-order byte of the extension word. - if (size == 6) address++; - mov_l_ri(ad,address); - m68k_pc_offset+=sz2[size]; - break; - } - default: - return -1; - } - } - - switch (size) { - case 0: - readlong(ad,S2,S3); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - break; - case 1: - readlong(ad,S2,S3); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovs_rm(FS1,(uintptr)temp_fp); - break; - case 2: - readword(ad,S2,S3); - mov_w_mr(((uintptr)temp_fp)+8,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp)+4,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - delay2; - fmov_ext_rm(FS1,(uintptr)(temp_fp)); - break; - case 3: - return -1; /* Some silly "packed" stuff */ - case 4: - readword(ad,S2,S3); - sign_extend_16_rr(S2,S2); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - break; - case 5: - readlong(ad,S2,S3); - mov_l_mr(((uintptr)temp_fp)+4,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - delay2; - fmov_rm(FS1,(uintptr)(temp_fp)); - break; - case 6: - readbyte(ad,S2,S3); - sign_extend_8_rr(S2,S2); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - break; - default: - return -1; - } - return FS1; -} - -/* return of -1 means failure, >=0 means OK */ -STATIC_INLINE int put_fp_value (int val, uae_u32 opcode, uae_u16 extra) -{ - uae_u16 tmp; - uaecptr tmppc; - int size; - int mode; - int reg; - uae_u32 ad; - static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; - static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; - - if ((extra & 0x4000) == 0) { - const int dest_reg = (extra >> 10) & 7; - fmov_rr(dest_reg, val); - // gb-- status register is affected - MAKE_FPSR(dest_reg); - return 0; - } - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - ad = (uae_u32)-1; - switch (mode) { - case 0: - switch (size) { - case 6: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_b_rm(reg,(uintptr)temp_fp); - return 0; - case 4: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_w_rm(reg,(uintptr)temp_fp); - return 0; - case 0: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(reg,(uintptr)temp_fp); - return 0; - case 1: - fmovs_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(reg,(uintptr)temp_fp); - return 0; - default: - return -1; - } - case 1: - return -1; /* genuine invalid instruction */ - default: break; - } - - /* Let's make sure we get out *before* doing something silly if - we can't handle the size */ - switch (size) { - case 0: - case 4: - case 5: - case 6: - case 2: - case 1: - break; - case 3: - default: - return -1; - } - - switch (mode) { - case 2: - ad=S1; - mov_l_rr(ad,reg+8); - break; - case 3: - ad=S1; - mov_l_rr(ad,reg+8); - lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size])); - break; - case 4: - ad=S1; - lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size])); - mov_l_rr(ad,reg+8); - break; - case 5: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_rr(ad,reg+8); - add_l_ri(ad,off); - break; - } - case 6: - { - uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - calc_disp_ea_020(reg+8,dp,ad,S2); - break; - } - case 7: - switch (reg) { - case 0: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 1: - { - uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 2: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ - m68k_pc_offset; - uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,address+PC16off); - break; - } - case 3: - return -1; - tmppc = m68k_getpc (); - tmp = next_iword (); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ - m68k_pc_offset; - ad=S1; - mov_l_ri(ad,address); - m68k_pc_offset+=sz2[size]; - break; - } - default: - return -1; - } - } - switch (size) { - case 0: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 1: - fmovs_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 2: - fmov_ext_mr((uintptr)temp_fp,val); - delay; - mov_w_rm(S2,(uintptr)temp_fp+8); - writeword_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 3: return -1; /* Packed */ - - case 4: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writeword_clobber(ad,S2,S3); - break; - case 5: - fmov_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 6: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writebyte(ad,S2,S3); - break; - default: - return -1; - } - return 0; -} - -/* return -1 for failure, or register number for success */ -STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad) -{ - uae_u16 tmp; - uaecptr tmppc; - int mode; - int reg; - uae_s32 off; - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) { - case 0: - case 1: - return -1; - case 2: - case 3: - case 4: - mov_l_rr(S1,8+reg); - return S1; - *ad = m68k_areg (regs, reg); - break; - case 5: - off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - - mov_l_rr(S1,8+reg); - add_l_ri(S1,off); - return S1; - case 6: - return -1; - break; - case 7: - switch (reg) { - case 0: - off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - mov_l_ri(S1,off); - return S1; - case 1: - off=comp_get_ilong((m68k_pc_offset+=4)-4); - mov_l_ri(S1,off); - return S1; - case 2: - return -1; -// *ad = m68k_getpc (); -// *ad += (uae_s32) (uae_s16) next_iword (); - off=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset; - off+=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - mov_l_ri(S1,off); - return S1; - case 3: - return -1; - tmppc = m68k_getpc (); - tmp = next_iword (); - *ad = get_disp_ea_020 (tmppc, tmp); - break; - default: - return -1; - } - } - abort(); -} - -void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra) -{ - FAIL(1); - return; -} - -void comp_fscc_opp (uae_u32 opcode, uae_u16 extra) -{ - uae_u32 ad; - int cc; - int reg; - -#if DEBUG_FPP - printf ("fscc_opp at %08lx\n", m68k_getpc ()); - fflush (stdout); -#endif - - - if (extra&0x20) { /* only cc from 00 to 1f are defined */ - FAIL(1); - return; - } - if ((opcode & 0x38) != 0) { /* We can only do to integer register */ - FAIL(1); - return; - } - - fflags_into_flags(S2); - reg=(opcode&7); - - mov_l_ri(S1,255); - mov_l_ri(S4,0); - switch(extra&0x0f) { /* according to fpp.c, the 0x10 bit is ignored - */ - case 0: break; /* set never */ - case 1: mov_l_rr(S2,S4); - cmov_l_rr(S4,S1,4); - cmov_l_rr(S4,S2,10); break; - case 2: cmov_l_rr(S4,S1,7); break; - case 3: cmov_l_rr(S4,S1,3); break; - case 4: mov_l_rr(S2,S4); - cmov_l_rr(S4,S1,2); - cmov_l_rr(S4,S2,10); break; - case 5: mov_l_rr(S2,S4); - cmov_l_rr(S4,S1,6); - cmov_l_rr(S4,S2,10); break; - case 6: cmov_l_rr(S4,S1,5); break; - case 7: cmov_l_rr(S4,S1,11); break; - case 8: cmov_l_rr(S4,S1,10); break; - case 9: cmov_l_rr(S4,S1,4); break; - case 10: cmov_l_rr(S4,S1,10); cmov_l_rr(S4,S1,7); break; - case 11: cmov_l_rr(S4,S1,4); cmov_l_rr(S4,S1,3); break; - case 12: cmov_l_rr(S4,S1,2); break; - case 13: cmov_l_rr(S4,S1,6); break; - case 14: cmov_l_rr(S4,S1,5); cmov_l_rr(S4,S1,10); break; - case 15: mov_l_rr(S4,S1); break; - } - - if ((opcode & 0x38) == 0) { - mov_b_rr(reg,S4); - } else { - abort(); - if (get_fp_ad (opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - fpuop_illg (opcode,extra); - } else - put_byte (ad, cc ? 0xff : 0x00); - } -} - -void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc) -{ - int cc; - - FAIL(1); - return; -} - -void comp_fbcc_opp (uae_u32 opcode) -{ - uae_u32 start_68k_offset=m68k_pc_offset; - uae_u32 off; - uae_u32 v1; - uae_u32 v2; - uae_u32 nh; - int cc; - - // comp_pc_p is expected to be bound to 32-bit addresses - assert((uintptr)comp_pc_p <= 0xffffffffUL); - - if (opcode&0x20) { /* only cc from 00 to 1f are defined */ - FAIL(1); - return; - } - if ((opcode&0x40)==0) { - off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - } - else { - off=comp_get_ilong((m68k_pc_offset+=4)-4); - } - mov_l_ri(S1,(uintptr) - (comp_pc_p+off-(m68k_pc_offset-start_68k_offset))); - mov_l_ri(PC_P,(uintptr)comp_pc_p); - - /* Now they are both constant. Might as well fold in m68k_pc_offset */ - add_l_ri(S1,m68k_pc_offset); - add_l_ri(PC_P,m68k_pc_offset); - m68k_pc_offset=0; - - /* according to fpp.c, the 0x10 bit is ignored - (it handles exception handling, which we don't - do, anyway ;-) */ - cc=opcode&0x0f; - v1=get_const(PC_P); - v2=get_const(S1); - fflags_into_flags(S2); - - switch(cc) { - case 0: break; /* jump never */ - case 1: - mov_l_rr(S2,PC_P); - cmov_l_rr(PC_P,S1,4); - cmov_l_rr(PC_P,S2,10); break; - case 2: register_branch(v1,v2,7); break; - case 3: register_branch(v1,v2,3); break; - case 4: - mov_l_rr(S2,PC_P); - cmov_l_rr(PC_P,S1,2); - cmov_l_rr(PC_P,S2,10); break; - case 5: - mov_l_rr(S2,PC_P); - cmov_l_rr(PC_P,S1,6); - cmov_l_rr(PC_P,S2,10); break; - case 6: register_branch(v1,v2,5); break; - case 7: register_branch(v1,v2,11); break; - case 8: register_branch(v1,v2,10); break; - case 9: register_branch(v1,v2,4); break; - case 10: - cmov_l_rr(PC_P,S1,10); - cmov_l_rr(PC_P,S1,7); break; - case 11: - cmov_l_rr(PC_P,S1,4); - cmov_l_rr(PC_P,S1,3); break; - case 12: register_branch(v1,v2,2); break; - case 13: register_branch(v1,v2,6); break; - case 14: - cmov_l_rr(PC_P,S1,5); - cmov_l_rr(PC_P,S1,10); break; - case 15: mov_l_rr(PC_P,S1); break; - } -} - - /* Floating point conditions - The "NotANumber" part could be problematic; Howver, when NaN is - encountered, the ftst instruction sets bot N and Z to 1 on the x87, - so quite often things just fall into place. This is probably not - accurate wrt the 68k FPU, but it is *as* accurate as this was before. - However, some more thought should go into fixing this stuff up so - it accurately emulates the 68k FPU. ->==> 13) & 0x7) { - case 3: /* 2nd most common */ - if (put_fp_value ((extra >> 7)&7 , opcode, extra) < 0) { - FAIL(1); - return; - - } - return; - case 6: - case 7: - { - uae_u32 ad, list = 0; - int incr = 0; - if (extra & 0x2000) { - uae_u32 ad; - - /* FMOVEM FPP->memory */ - switch ((extra >> 11) & 3) { /* Get out early if failure */ - case 0: - case 2: - break; - case 1: - case 3: - default: - FAIL(1); return; - } - ad=get_fp_ad (opcode, &ad); - if (ad<0) { - abort(); - m68k_setpc (m68k_getpc () - 4); - fpuop_illg (opcode,extra); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 1: /* dynamic pred */ - case 3: /* dynamic postinc */ - abort(); - } - if (incr < 0) { /* Predecrement */ - for (reg = 7; reg >= 0; reg--) { - if (list & 0x80) { - fmov_ext_mr((uintptr)temp_fp,reg); - delay; - sub_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - sub_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - sub_l_ri(ad,4); - mov_w_rm(S2,(uintptr)temp_fp+8); - writeword_clobber(ad,S2,S3); - } - list <<= 1; - } - } - else { /* Postincrement */ - for (reg = 0; reg < 8; reg++) { - if (list & 0x80) { - fmov_ext_mr((uintptr)temp_fp,reg); - delay; - mov_w_rm(S2,(uintptr)temp_fp+8); - writeword_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) - mov_l_rr((opcode & 7)+8,ad); - if ((opcode & 0x38) == 0x20) - mov_l_rr((opcode & 7)+8,ad); - } else { - /* FMOVEM memory->FPP */ - - uae_u32 ad; - switch ((extra >> 11) & 3) { /* Get out early if failure */ - case 0: - case 2: - break; - case 1: - case 3: - default: - FAIL(1); return; - } - ad=get_fp_ad (opcode, &ad); - if (ad<0) { - abort(); - m68k_setpc (m68k_getpc () - 4); - write_log("no ad\n"); - fpuop_illg (opcode,extra); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 1: /* dynamic pred */ - case 3: /* dynamic postinc */ - abort(); - } - - if (incr < 0) { - // not reached - for (reg = 7; reg >= 0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if (list & 0x80) { - sub_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - sub_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp)+4,S2); - sub_l_ri(ad,4); - readword(ad,S2,S3); - mov_w_mr(((uintptr)temp_fp)+8,S2); - delay2; - fmov_ext_rm(reg,(uintptr)(temp_fp)); - } - list <<= 1; - } - } - else { - for (reg = 0; reg < 8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if (list & 0x80) { - readword(ad,S2,S3); - mov_w_mr(((uintptr)temp_fp)+8,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp)+4,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - add_l_ri(ad,4); - delay2; - fmov_ext_rm(reg,(uintptr)(temp_fp)); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) - mov_l_rr((opcode & 7)+8,ad); - if ((opcode & 0x38) == 0x20) - mov_l_rr((opcode & 7)+8,ad); - } - } - return; - - case 4: - case 5: /* rare */ - if ((opcode & 0x30) == 0) { - if (extra & 0x2000) { - if (extra & 0x1000) { -#if HANDLE_FPCR - mov_l_rm(opcode & 15, (uintptr)&fpu.fpcr.rounding_mode); - or_l_rm(opcode & 15, (uintptr)&fpu.fpcr.rounding_precision); -#else - FAIL(1); - return; -#endif - } - if (extra & 0x0800) { - FAIL(1); - return; - } - if (extra & 0x0400) { - mov_l_rm(opcode & 15,(uintptr)&fpu.instruction_address); - return; - } - } else { - // gb-- moved here so that we may FAIL() without generating any code - if (extra & 0x0800) { - // set_fpsr(m68k_dreg (regs, opcode & 15)); - FAIL(1); - return; - } - if (extra & 0x1000) { -#if HANDLE_FPCR -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) - FAIL(1); - return; -#endif - mov_l_rr(S1,opcode & 15); - mov_l_rr(S2,opcode & 15); - and_l_ri(S1,FPCR_ROUNDING_PRECISION); - and_l_ri(S2,FPCR_ROUNDING_MODE); - mov_l_mr((uintptr)&fpu.fpcr.rounding_precision,S1); - mov_l_mr((uintptr)&fpu.fpcr.rounding_mode,S2); -#else - FAIL(1); - return; -#endif -// return; gb-- FMOVEM could also operate on fpiar - } - if (extra & 0x0400) { - mov_l_mr((uintptr)&fpu.instruction_address,opcode & 15); -// return; gb-- we have to process all FMOVEM bits before returning - } - return; - } - } else if ((opcode & 0x3f) == 0x3c) { - if ((extra & 0x2000) == 0) { - // gb-- moved here so that we may FAIL() without generating any code - if (extra & 0x0800) { - FAIL(1); - return; - } - if (extra & 0x1000) { - uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4); -#if HANDLE_FPCR -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) - FAIL(1); - return; -#endif -// mov_l_mi((uintptr)®s.fpcr,val); - mov_l_ri(S1,val); - mov_l_ri(S2,val); - and_l_ri(S1,FPCR_ROUNDING_PRECISION); - and_l_ri(S2,FPCR_ROUNDING_MODE); - mov_l_mr((uintptr)&fpu.fpcr.rounding_precision,S1); - mov_l_mr((uintptr)&fpu.fpcr.rounding_mode,S2); -#else - FAIL(1); - return; -#endif -// return; gb-- FMOVEM could also operate on fpiar - } - if (extra & 0x0400) { - uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4); - mov_l_mi((uintptr)&fpu.instruction_address,val); -// return; gb-- we have to process all FMOVEM bits before returning - } - return; - } - FAIL(1); - return; - } else if (extra & 0x2000) { - FAIL(1); - return; - } else { - FAIL(1); - return; - } - FAIL(1); - return; - - case 0: - case 2: /* Extremely common */ - reg = (extra >> 7) & 7; - if ((extra & 0xfc00) == 0x5c00) { - switch (extra & 0x7f) { - case 0x00: - fmov_pi(reg); - break; - case 0x0b: - fmov_log10_2(reg); - break; - case 0x0c: -#if USE_LONG_DOUBLE - fmov_ext_rm(reg,(uintptr)&const_e); -#else - fmov_rm(reg,(uintptr)&const_e); -#endif - break; - case 0x0d: - fmov_log2_e(reg); - break; - case 0x0e: -#if USE_LONG_DOUBLE - fmov_ext_rm(reg,(uintptr)&const_log10_e); -#else - fmov_rm(reg,(uintptr)&const_log10_e); -#endif - break; - case 0x0f: - fmov_0(reg); - break; - case 0x30: - fmov_loge_2(reg); - break; - case 0x31: -#if USE_LONG_DOUBLE - fmov_ext_rm(reg,(uintptr)&const_loge_10); -#else - fmov_rm(reg,(uintptr)&const_loge_10); -#endif - break; - case 0x32: - fmov_1(reg); - break; - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: -#if USE_LONG_DOUBLE - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: - fmov_ext_rm(reg,(uintptr)(power10+(extra & 0x7f)-0x32)); -#else - fmov_rm(reg,(uintptr)(power10+(extra & 0x7f)-0x32)); -#endif - break; - default: - /* This is not valid, so we fail */ - FAIL(1); - return; - } - return; - } - - switch (extra & 0x7f) { - case 0x00: /* FMOVE */ - case 0x40: /* Explicit rounding. This is just a quick fix. Same - * for all other cases that have three choices */ - case 0x44: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fmov_rr(reg,src); - MAKE_FPSR (src); - break; - case 0x01: /* FINT */ - FAIL(1); - return; - dont_care_fflags(); - case 0x02: /* FSINH */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x03: /* FINTRZ */ -#if USE_X86_FPUCW - /* If we have control over the CW, we can do this */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - mov_l_ri(S1,16); /* Switch to "round to zero" mode */ - fldcw_m_indexed(S1,(uae_u32)x86_fpucw); - - frndint_rr(reg,src); - - /* restore control word */ - mov_l_rm(S1,(uintptr)®s.fpcr); - and_l_ri(S1,0x000000f0); - fldcw_m_indexed(S1,(uintptr)x86_fpucw); - - MAKE_FPSR (reg); - break; -#endif - FAIL(1); - return; - break; - case 0x04: /* FSQRT */ - case 0x41: - case 0x45: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fsqrt_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x06: /* FLOGNP1 */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x08: /* FETOXM1 */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x09: /* FTANH */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0a: /* FATAN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0c: /* FASIN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0d: /* FATANH */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0e: /* FSIN */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fsin_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x0f: /* FTAN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x10: /* FETOX */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fetox_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x11: /* FTWOTOX */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - ftwotox_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x12: /* FTENTOX */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x14: /* FLOGN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x15: /* FLOG10 */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x16: /* FLOG2 */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - flog2_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x18: /* FABS */ - case 0x58: - case 0x5c: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fabs_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x19: /* FCOSH */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x1a: /* FNEG */ - case 0x5a: - case 0x5e: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fneg_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x1c: /* FACOS */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x1d: /* FCOS */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fcos_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x1e: /* FGETEXP */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x1f: /* FGETMAN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x20: /* FDIV */ - case 0x60: - case 0x64: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fdiv_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x21: /* FMOD */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - frem_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x22: /* FADD */ - case 0x62: - case 0x66: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fadd_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x23: /* FMUL */ - case 0x63: - case 0x67: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fmul_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x24: /* FSGLDIV */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fdiv_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x25: /* FREM */ - // gb-- disabled because the quotient byte must be computed - // otherwise, free rotation in ClarisWorks doesn't work. - FAIL(1); - return; - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - frem1_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x26: /* FSCALE */ - dont_care_fflags(); - FAIL(1); - return; - break; - case 0x27: /* FSGLMUL */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fmul_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x28: /* FSUB */ - case 0x68: - case 0x6c: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fsub_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x30: /* FSINCOS */ - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x38: /* FCMP */ - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fmov_rr(FP_RESULT,reg); - fsub_rr(FP_RESULT,src); /* Right way? */ - break; - case 0x3a: /* FTST */ - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fmov_rr(FP_RESULT,src); - break; - default: - FAIL(1); - return; - break; - } - return; - } - m68k_setpc (m68k_getpc () - 4); - fpuop_illg (opcode,extra); -} diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp deleted file mode 100644 index f31febce..00000000 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ /dev/null @@ -1,7129 +0,0 @@ -/* - * compiler/compemu_support.cpp - Core dynamic translation engine - * - * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer - * - * Adaptation for Basilisk II and improvements, copyright 2000-2005 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING -#error "Only Real or Direct Addressing is supported with the JIT Compiler" -#endif - -#if X86_ASSEMBLY && !SAHF_SETO_PROFITABLE -#error "Only [LS]AHF scheme to [gs]et flags is supported with the JIT Compiler" -#endif - -/* NOTE: support for AMD64 assumes translation cache and other code - * buffers are allocated into a 32-bit address space because (i) B2/JIT - * code is not 64-bit clean and (ii) it's faster to resolve branches - * that way. - */ -#if !defined(__i386__) && !defined(__x86_64__) -#error "Only IA-32 and X86-64 targets are supported with the JIT Compiler" -#endif - -#define USE_MATCH 0 - -/* kludge for Brian, so he can compile under MSVC++ */ -#define USE_NORMAL_CALLING_CONVENTION 1 && defined(_MSC_VER) - -#ifndef WIN32 -#include -#include -#include -#endif - -#include -#include -#include - -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "user_strings.h" -#include "vm_alloc.h" - -#include "m68k.h" -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#include "comptbl.h" -#include "compiler/compemu.h" -#include "fpu/fpu.h" -#include "fpu/flags.h" - -#define DEBUG 1 -#include "debug.h" - -#ifdef ENABLE_MON -#include "mon.h" -#endif - -#ifndef WIN32 -#define PROFILE_COMPILE_TIME 1 -#define PROFILE_UNTRANSLATED_INSNS 1 -#endif - -#if defined(__x86_64__) && 0 -#define RECORD_REGISTER_USAGE 1 -#endif - -#ifdef WIN32 -#undef write_log -#define write_log dummy_write_log -static void dummy_write_log(const char *, ...) { } -#endif - -#if JIT_DEBUG -#undef abort -#define abort() do { \ - fprintf(stderr, "Abort in file %s at line %d\n", __FILE__, __LINE__); \ - exit(EXIT_FAILURE); \ -} while (0) -#endif - -#if RECORD_REGISTER_USAGE -static uint64 reg_count[16]; -static int reg_count_local[16]; - -static int reg_count_compare(const void *ap, const void *bp) -{ - const int a = *((int *)ap); - const int b = *((int *)bp); - return reg_count[b] - reg_count[a]; -} -#endif - -#if PROFILE_COMPILE_TIME -#include -static uae_u32 compile_count = 0; -static clock_t compile_time = 0; -static clock_t emul_start_time = 0; -static clock_t emul_end_time = 0; -#endif - -#if PROFILE_UNTRANSLATED_INSNS -const int untranslated_top_ten = 20; -static uae_u32 raw_cputbl_count[65536] = { 0, }; -static uae_u16 opcode_nums[65536]; - -static int untranslated_compfn(const void *e1, const void *e2) -{ - return raw_cputbl_count[*(const uae_u16 *)e1] < raw_cputbl_count[*(const uae_u16 *)e2]; -} -#endif - -static compop_func *compfunctbl[65536]; -static compop_func *nfcompfunctbl[65536]; -static cpuop_func *nfcpufunctbl[65536]; -uae_u8* comp_pc_p; - -// From newcpu.cpp -extern bool quit_program; - -// gb-- Extra data for Basilisk II/JIT -#if JIT_DEBUG -static bool JITDebug = false; // Enable runtime disassemblers through mon? -#else -const bool JITDebug = false; // Don't use JIT debug mode at all -#endif -#if USE_INLINING -static bool follow_const_jumps = true; // Flag: translation through constant jumps -#else -const bool follow_const_jumps = false; -#endif - -const uae_u32 MIN_CACHE_SIZE = 1024; // Minimal translation cache size (1 MB) -static uae_u32 cache_size = 0; // Size of total cache allocated for compiled blocks -static uae_u32 current_cache_size = 0; // Cache grows upwards: how much has been consumed already -static bool lazy_flush = true; // Flag: lazy translation cache invalidation -static bool avoid_fpu = true; // Flag: compile FPU instructions ? -static bool have_cmov = false; // target has CMOV instructions ? -static bool have_lahf_lm = true; // target has LAHF supported in long mode ? -static bool have_rat_stall = true; // target has partial register stalls ? -const bool tune_alignment = true; // Tune code alignments for running CPU ? -const bool tune_nop_fillers = true; // Tune no-op fillers for architecture -static bool setzflg_uses_bsf = false; // setzflg virtual instruction can use native BSF instruction correctly? -static int align_loops = 32; // Align the start of loops -static int align_jumps = 32; // Align the start of jumps -static int optcount[10] = { - 10, // How often a block has to be executed before it is translated - 0, // How often to use naive translation - 0, 0, 0, 0, - -1, -1, -1, -1 -}; - -struct op_properties { - uae_u8 use_flags; - uae_u8 set_flags; - uae_u8 is_addx; - uae_u8 cflow; -}; -static op_properties prop[65536]; - -static inline int end_block(uae_u32 opcode) -{ - return (prop[opcode].cflow & fl_end_block); -} - -static inline bool is_const_jump(uae_u32 opcode) -{ - return (prop[opcode].cflow == fl_const_jump); -} - -static inline bool may_trap(uae_u32 opcode) -{ - return (prop[opcode].cflow & fl_trap) != 0; -} - -static inline unsigned int cft_map (unsigned int f) -{ -#ifndef HAVE_GET_WORD_UNSWAPPED - return f; -#else - return ((f >> 8) & 255) | ((f & 255) << 8); -#endif -} - -uae_u8* start_pc_p; -uae_u32 start_pc; -uae_u32 current_block_pc_p; -static uintptr current_block_start_target; -uae_u32 needed_flags; -static uintptr next_pc_p; -static uintptr taken_pc_p; -static int branch_cc; -static int redo_current_block; - -int segvcount=0; -int soft_flush_count=0; -int hard_flush_count=0; -int checksum_count=0; -static uae_u8* current_compile_p=NULL; -static uae_u8* max_compile_start; -static uae_u8* compiled_code=NULL; -static uae_s32 reg_alloc_run; -const int POPALLSPACE_SIZE = 1024; /* That should be enough space */ -static uae_u8* popallspace=NULL; - -void* pushall_call_handler=NULL; -static void* popall_do_nothing=NULL; -static void* popall_exec_nostats=NULL; -static void* popall_execute_normal=NULL; -static void* popall_cache_miss=NULL; -static void* popall_recompile_block=NULL; -static void* popall_check_checksum=NULL; - -/* The 68k only ever executes from even addresses. So right now, we - * waste half the entries in this array - * UPDATE: We now use those entries to store the start of the linked - * lists that we maintain for each hash result. - */ -cacheline cache_tags[TAGSIZE]; -int letit=0; -blockinfo* hold_bi[MAX_HOLD_BI]; -blockinfo* active; -blockinfo* dormant; - -/* 68040 */ -extern struct cputbl op_smalltbl_0_nf[]; -extern struct comptbl op_smalltbl_0_comp_nf[]; -extern struct comptbl op_smalltbl_0_comp_ff[]; - -/* 68020 + 68881 */ -extern struct cputbl op_smalltbl_1_nf[]; - -/* 68020 */ -extern struct cputbl op_smalltbl_2_nf[]; - -/* 68010 */ -extern struct cputbl op_smalltbl_3_nf[]; - -/* 68000 */ -extern struct cputbl op_smalltbl_4_nf[]; - -/* 68000 slow but compatible. */ -extern struct cputbl op_smalltbl_5_nf[]; - -static void flush_icache_hard(int n); -static void flush_icache_lazy(int n); -static void flush_icache_none(int n); -void (*flush_icache)(int n) = flush_icache_none; - - - -bigstate live; -smallstate empty_ss; -smallstate default_ss; -static int optlev; - -static int writereg(int r, int size); -static void unlock2(int r); -static void setlock(int r); -static int readreg_specific(int r, int size, int spec); -static int writereg_specific(int r, int size, int spec); -static void prepare_for_call_1(void); -static void prepare_for_call_2(void); -static void align_target(uae_u32 a); - -static uae_s32 nextused[VREGS]; - -uae_u32 m68k_pc_offset; - -/* Some arithmetic ooperations can be optimized away if the operands - * are known to be constant. But that's only a good idea when the - * side effects they would have on the flags are not important. This - * variable indicates whether we need the side effects or not - */ -uae_u32 needflags=0; - -/* Flag handling is complicated. - * - * x86 instructions create flags, which quite often are exactly what we - * want. So at times, the "68k" flags are actually in the x86 flags. - * - * Then again, sometimes we do x86 instructions that clobber the x86 - * flags, but don't represent a corresponding m68k instruction. In that - * case, we have to save them. - * - * We used to save them to the stack, but now store them back directly - * into the regflags.cznv of the traditional emulation. Thus some odd - * names. - * - * So flags can be in either of two places (used to be three; boy were - * things complicated back then!); And either place can contain either - * valid flags or invalid trash (and on the stack, there was also the - * option of "nothing at all", now gone). A couple of variables keep - * track of the respective states. - * - * To make things worse, we might or might not be interested in the flags. - * by default, we are, but a call to dont_care_flags can change that - * until the next call to live_flags. If we are not, pretty much whatever - * is in the register and/or the native flags is seen as valid. - */ - -static __inline__ blockinfo* get_blockinfo(uae_u32 cl) -{ - return cache_tags[cl+1].bi; -} - -static __inline__ blockinfo* get_blockinfo_addr(void* addr) -{ - blockinfo* bi=get_blockinfo(cacheline(addr)); - - while (bi) { - if (bi->pc_p==addr) - return bi; - bi=bi->next_same_cl; - } - return NULL; -} - - -/******************************************************************* - * All sorts of list related functions for all of the lists * - *******************************************************************/ - -static __inline__ void remove_from_cl_list(blockinfo* bi) -{ - uae_u32 cl=cacheline(bi->pc_p); - - if (bi->prev_same_cl_p) - *(bi->prev_same_cl_p)=bi->next_same_cl; - if (bi->next_same_cl) - bi->next_same_cl->prev_same_cl_p=bi->prev_same_cl_p; - if (cache_tags[cl+1].bi) - cache_tags[cl].handler=cache_tags[cl+1].bi->handler_to_use; - else - cache_tags[cl].handler=(cpuop_func *)popall_execute_normal; -} - -static __inline__ void remove_from_list(blockinfo* bi) -{ - if (bi->prev_p) - *(bi->prev_p)=bi->next; - if (bi->next) - bi->next->prev_p=bi->prev_p; -} - -static __inline__ void remove_from_lists(blockinfo* bi) -{ - remove_from_list(bi); - remove_from_cl_list(bi); -} - -static __inline__ void add_to_cl_list(blockinfo* bi) -{ - uae_u32 cl=cacheline(bi->pc_p); - - if (cache_tags[cl+1].bi) - cache_tags[cl+1].bi->prev_same_cl_p=&(bi->next_same_cl); - bi->next_same_cl=cache_tags[cl+1].bi; - - cache_tags[cl+1].bi=bi; - bi->prev_same_cl_p=&(cache_tags[cl+1].bi); - - cache_tags[cl].handler=bi->handler_to_use; -} - -static __inline__ void raise_in_cl_list(blockinfo* bi) -{ - remove_from_cl_list(bi); - add_to_cl_list(bi); -} - -static __inline__ void add_to_active(blockinfo* bi) -{ - if (active) - active->prev_p=&(bi->next); - bi->next=active; - - active=bi; - bi->prev_p=&active; -} - -static __inline__ void add_to_dormant(blockinfo* bi) -{ - if (dormant) - dormant->prev_p=&(bi->next); - bi->next=dormant; - - dormant=bi; - bi->prev_p=&dormant; -} - -static __inline__ void remove_dep(dependency* d) -{ - if (d->prev_p) - *(d->prev_p)=d->next; - if (d->next) - d->next->prev_p=d->prev_p; - d->prev_p=NULL; - d->next=NULL; -} - -/* This block's code is about to be thrown away, so it no longer - depends on anything else */ -static __inline__ void remove_deps(blockinfo* bi) -{ - remove_dep(&(bi->dep[0])); - remove_dep(&(bi->dep[1])); -} - -static __inline__ void adjust_jmpdep(dependency* d, cpuop_func* a) -{ - *(d->jmp_off)=(uintptr)a-((uintptr)d->jmp_off+4); -} - -/******************************************************************** - * Soft flush handling support functions * - ********************************************************************/ - -static __inline__ void set_dhtu(blockinfo* bi, cpuop_func* dh) -{ - //write_log("bi is %p\n",bi); - if (dh!=bi->direct_handler_to_use) { - dependency* x=bi->deplist; - //write_log("bi->deplist=%p\n",bi->deplist); - while (x) { - //write_log("x is %p\n",x); - //write_log("x->next is %p\n",x->next); - //write_log("x->prev_p is %p\n",x->prev_p); - - if (x->jmp_off) { - adjust_jmpdep(x,dh); - } - x=x->next; - } - bi->direct_handler_to_use=dh; - } -} - -static __inline__ void invalidate_block(blockinfo* bi) -{ - int i; - - bi->optlevel=0; - bi->count=optcount[0]-1; - bi->handler=NULL; - bi->handler_to_use=(cpuop_func *)popall_execute_normal; - bi->direct_handler=NULL; - set_dhtu(bi,bi->direct_pen); - bi->needed_flags=0xff; - bi->status=BI_INVALID; - for (i=0;i<2;i++) { - bi->dep[i].jmp_off=NULL; - bi->dep[i].target=NULL; - } - remove_deps(bi); -} - -static __inline__ void create_jmpdep(blockinfo* bi, int i, uae_u32* jmpaddr, uae_u32 target) -{ - blockinfo* tbi=get_blockinfo_addr((void*)(uintptr)target); - - Dif(!tbi) { - write_log("Could not create jmpdep!\n"); - abort(); - } - bi->dep[i].jmp_off=jmpaddr; - bi->dep[i].source=bi; - bi->dep[i].target=tbi; - bi->dep[i].next=tbi->deplist; - if (bi->dep[i].next) - bi->dep[i].next->prev_p=&(bi->dep[i].next); - bi->dep[i].prev_p=&(tbi->deplist); - tbi->deplist=&(bi->dep[i]); -} - -static __inline__ void block_need_recompile(blockinfo * bi) -{ - uae_u32 cl = cacheline(bi->pc_p); - - set_dhtu(bi, bi->direct_pen); - bi->direct_handler = bi->direct_pen; - - bi->handler_to_use = (cpuop_func *)popall_execute_normal; - bi->handler = (cpuop_func *)popall_execute_normal; - if (bi == cache_tags[cl + 1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; - bi->status = BI_NEED_RECOMP; -} - -static __inline__ void mark_callers_recompile(blockinfo * bi) -{ - dependency *x = bi->deplist; - - while (x) { - dependency *next = x->next; /* This disappears when we mark for - * recompilation and thus remove the - * blocks from the lists */ - if (x->jmp_off) { - blockinfo *cbi = x->source; - - Dif(cbi->status == BI_INVALID) { - // write_log("invalid block in dependency list\n"); // FIXME? - // abort(); - } - if (cbi->status == BI_ACTIVE || cbi->status == BI_NEED_CHECK) { - block_need_recompile(cbi); - mark_callers_recompile(cbi); - } - else if (cbi->status == BI_COMPILING) { - redo_current_block = 1; - } - else if (cbi->status == BI_NEED_RECOMP) { - /* nothing */ - } - else { - //write_log("Status %d in mark_callers\n",cbi->status); // FIXME? - } - } - x = next; - } -} - -static __inline__ blockinfo* get_blockinfo_addr_new(void* addr, int setstate) -{ - blockinfo* bi=get_blockinfo_addr(addr); - int i; - - if (!bi) { - for (i=0;ipc_p=(uae_u8 *)addr; - invalidate_block(bi); - add_to_active(bi); - add_to_cl_list(bi); - - } - } - } - if (!bi) { - write_log("Looking for blockinfo, can't find free one\n"); - abort(); - } - return bi; -} - -static void prepare_block(blockinfo* bi); - -/* Managment of blockinfos. - - A blockinfo struct is allocated whenever a new block has to be - compiled. If the list of free blockinfos is empty, we allocate a new - pool of blockinfos and link the newly created blockinfos altogether - into the list of free blockinfos. Otherwise, we simply pop a structure - off the free list. - - Blockinfo are lazily deallocated, i.e. chained altogether in the - list of free blockinfos whenvever a translation cache flush (hard or - soft) request occurs. -*/ - -template< class T > -class LazyBlockAllocator -{ - enum { - kPoolSize = 1 + 4096 / sizeof(T) - }; - struct Pool { - T chunk[kPoolSize]; - Pool * next; - }; - Pool * mPools; - T * mChunks; -public: - LazyBlockAllocator() : mPools(0), mChunks(0) { } - ~LazyBlockAllocator(); - T * acquire(); - void release(T * const); -}; - -template< class T > -LazyBlockAllocator::~LazyBlockAllocator() -{ - Pool * currentPool = mPools; - while (currentPool) { - Pool * deadPool = currentPool; - currentPool = currentPool->next; - free(deadPool); - } -} - -template< class T > -T * LazyBlockAllocator::acquire() -{ - if (!mChunks) { - // There is no chunk left, allocate a new pool and link the - // chunks into the free list - Pool * newPool = (Pool *)malloc(sizeof(Pool)); - for (T * chunk = &newPool->chunk[0]; chunk < &newPool->chunk[kPoolSize]; chunk++) { - chunk->next = mChunks; - mChunks = chunk; - } - newPool->next = mPools; - mPools = newPool; - } - T * chunk = mChunks; - mChunks = chunk->next; - return chunk; -} - -template< class T > -void LazyBlockAllocator::release(T * const chunk) -{ - chunk->next = mChunks; - mChunks = chunk; -} - -template< class T > -class HardBlockAllocator -{ -public: - T * acquire() { - T * data = (T *)current_compile_p; - current_compile_p += sizeof(T); - return data; - } - - void release(T * const chunk) { - // Deallocated on invalidation - } -}; - -#if USE_SEPARATE_BIA -static LazyBlockAllocator BlockInfoAllocator; -static LazyBlockAllocator ChecksumInfoAllocator; -#else -static HardBlockAllocator BlockInfoAllocator; -static HardBlockAllocator ChecksumInfoAllocator; -#endif - -static __inline__ checksum_info *alloc_checksum_info(void) -{ - checksum_info *csi = ChecksumInfoAllocator.acquire(); - csi->next = NULL; - return csi; -} - -static __inline__ void free_checksum_info(checksum_info *csi) -{ - csi->next = NULL; - ChecksumInfoAllocator.release(csi); -} - -static __inline__ void free_checksum_info_chain(checksum_info *csi) -{ - while (csi != NULL) { - checksum_info *csi2 = csi->next; - free_checksum_info(csi); - csi = csi2; - } -} - -static __inline__ blockinfo *alloc_blockinfo(void) -{ - blockinfo *bi = BlockInfoAllocator.acquire(); -#if USE_CHECKSUM_INFO - bi->csi = NULL; -#endif - return bi; -} - -static __inline__ void free_blockinfo(blockinfo *bi) -{ -#if USE_CHECKSUM_INFO - free_checksum_info_chain(bi->csi); - bi->csi = NULL; -#endif - BlockInfoAllocator.release(bi); -} - -static __inline__ void alloc_blockinfos(void) -{ - int i; - blockinfo* bi; - - for (i=0;i>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v<<24)&0xff000000); -#endif -} - -/******************************************************************** - * Getting the information about the target CPU * - ********************************************************************/ - -#include "codegen_x86.cpp" - -void set_target(uae_u8* t) -{ - target=t; -} - -static __inline__ uae_u8* get_target_noopt(void) -{ - return target; -} - -__inline__ uae_u8* get_target(void) -{ - return get_target_noopt(); -} - - -/******************************************************************** - * Flags status handling. EMIT TIME! * - ********************************************************************/ - -static void bt_l_ri_noclobber(R4 r, IMM i); - -static void make_flags_live_internal(void) -{ - if (live.flags_in_flags==VALID) - return; - Dif (live.flags_on_stack==TRASH) { - write_log("Want flags, got something on stack, but it is TRASH\n"); - abort(); - } - if (live.flags_on_stack==VALID) { - int tmp; - tmp=readreg_specific(FLAGTMP,4,FLAG_NREG2); - raw_reg_to_flags(tmp); - unlock2(tmp); - - live.flags_in_flags=VALID; - return; - } - write_log("Huh? live.flags_in_flags=%d, live.flags_on_stack=%d, but need to make live\n", - live.flags_in_flags,live.flags_on_stack); - abort(); -} - -static void flags_to_stack(void) -{ - if (live.flags_on_stack==VALID) - return; - if (!live.flags_are_important) { - live.flags_on_stack=VALID; - return; - } - Dif (live.flags_in_flags!=VALID) - abort(); - else { - int tmp; - tmp=writereg_specific(FLAGTMP,4,FLAG_NREG1); - raw_flags_to_reg(tmp); - unlock2(tmp); - } - live.flags_on_stack=VALID; -} - -static __inline__ void clobber_flags(void) -{ - if (live.flags_in_flags==VALID && live.flags_on_stack!=VALID) - flags_to_stack(); - live.flags_in_flags=TRASH; -} - -/* Prepare for leaving the compiled stuff */ -static __inline__ void flush_flags(void) -{ - flags_to_stack(); - return; -} - -int touchcnt; - -/******************************************************************** - * Partial register flushing for optimized calls * - ********************************************************************/ - -struct regusage { - uae_u16 rmask; - uae_u16 wmask; -}; - -static inline void ru_set(uae_u16 *mask, int reg) -{ -#if USE_OPTIMIZED_CALLS - *mask |= 1 << reg; -#endif -} - -static inline bool ru_get(const uae_u16 *mask, int reg) -{ -#if USE_OPTIMIZED_CALLS - return (*mask & (1 << reg)); -#else - /* Default: instruction reads & write to register */ - return true; -#endif -} - -static inline void ru_set_read(regusage *ru, int reg) -{ - ru_set(&ru->rmask, reg); -} - -static inline void ru_set_write(regusage *ru, int reg) -{ - ru_set(&ru->wmask, reg); -} - -static inline bool ru_read_p(const regusage *ru, int reg) -{ - return ru_get(&ru->rmask, reg); -} - -static inline bool ru_write_p(const regusage *ru, int reg) -{ - return ru_get(&ru->wmask, reg); -} - -static void ru_fill_ea(regusage *ru, int reg, amodes mode, - wordsizes size, int write_mode) -{ - switch (mode) { - case Areg: - reg += 8; - /* fall through */ - case Dreg: - ru_set(write_mode ? &ru->wmask : &ru->rmask, reg); - break; - case Ad16: - /* skip displacment */ - m68k_pc_offset += 2; - case Aind: - case Aipi: - case Apdi: - ru_set_read(ru, reg+8); - break; - case Ad8r: - ru_set_read(ru, reg+8); - /* fall through */ - case PC8r: { - uae_u16 dp = comp_get_iword((m68k_pc_offset+=2)-2); - reg = (dp >> 12) & 15; - ru_set_read(ru, reg); - if (dp & 0x100) - m68k_pc_offset += (((dp & 0x30) >> 3) & 7) + ((dp & 3) * 2); - break; - } - case PC16: - case absw: - case imm0: - case imm1: - m68k_pc_offset += 2; - break; - case absl: - case imm2: - m68k_pc_offset += 4; - break; - case immi: - m68k_pc_offset += (size == sz_long) ? 4 : 2; - break; - } -} - -/* TODO: split into a static initialization part and a dynamic one - (instructions depending on extension words) */ -static void ru_fill(regusage *ru, uae_u32 opcode) -{ - m68k_pc_offset += 2; - - /* Default: no register is used or written to */ - ru->rmask = 0; - ru->wmask = 0; - - uae_u32 real_opcode = cft_map(opcode); - struct instr *dp = &table68k[real_opcode]; - - bool rw_dest = true; - bool handled = false; - - /* Handle some instructions specifically */ - uae_u16 ext; - switch (dp->mnemo) { - case i_BFCHG: - case i_BFCLR: - case i_BFEXTS: - case i_BFEXTU: - case i_BFFFO: - case i_BFINS: - case i_BFSET: - case i_BFTST: - ext = comp_get_iword((m68k_pc_offset+=2)-2); - if (ext & 0x800) ru_set_read(ru, (ext >> 6) & 7); - if (ext & 0x020) ru_set_read(ru, ext & 7); - ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1); - if (dp->dmode == Dreg) - ru_set_read(ru, dp->dreg); - switch (dp->mnemo) { - case i_BFEXTS: - case i_BFEXTU: - case i_BFFFO: - ru_set_write(ru, (ext >> 12) & 7); - break; - case i_BFINS: - ru_set_read(ru, (ext >> 12) & 7); - /* fall through */ - case i_BFCHG: - case i_BFCLR: - case i_BSET: - if (dp->dmode == Dreg) - ru_set_write(ru, dp->dreg); - break; - } - handled = true; - rw_dest = false; - break; - - case i_BTST: - rw_dest = false; - break; - - case i_CAS: - { - ext = comp_get_iword((m68k_pc_offset+=2)-2); - int Du = ext & 7; - ru_set_read(ru, Du); - int Dc = (ext >> 6) & 7; - ru_set_read(ru, Dc); - ru_set_write(ru, Dc); - break; - } - case i_CAS2: - { - int Dc1, Dc2, Du1, Du2, Rn1, Rn2; - ext = comp_get_iword((m68k_pc_offset+=2)-2); - Rn1 = (ext >> 12) & 15; - Du1 = (ext >> 6) & 7; - Dc1 = ext & 7; - ru_set_read(ru, Rn1); - ru_set_read(ru, Du1); - ru_set_read(ru, Dc1); - ru_set_write(ru, Dc1); - ext = comp_get_iword((m68k_pc_offset+=2)-2); - Rn2 = (ext >> 12) & 15; - Du2 = (ext >> 6) & 7; - Dc2 = ext & 7; - ru_set_read(ru, Rn2); - ru_set_read(ru, Du2); - ru_set_write(ru, Dc2); - break; - } - case i_DIVL: case i_MULL: - m68k_pc_offset += 2; - break; - case i_LEA: - case i_MOVE: case i_MOVEA: case i_MOVE16: - rw_dest = false; - break; - case i_PACK: case i_UNPK: - rw_dest = false; - m68k_pc_offset += 2; - break; - case i_TRAPcc: - m68k_pc_offset += (dp->size == sz_long) ? 4 : 2; - break; - case i_RTR: - /* do nothing, just for coverage debugging */ - break; - /* TODO: handle EXG instruction */ - } - - /* Handle A-Traps better */ - if ((real_opcode & 0xf000) == 0xa000) { - handled = true; - } - - /* Handle EmulOps better */ - if ((real_opcode & 0xff00) == 0x7100) { - handled = true; - ru->rmask = 0xffff; - ru->wmask = 0; - } - - if (dp->suse && !handled) - ru_fill_ea(ru, dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); - - if (dp->duse && !handled) - ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1); - - if (rw_dest) - ru->rmask |= ru->wmask; - - handled = handled || dp->suse || dp->duse; - - /* Mark all registers as used/written if the instruction may trap */ - if (may_trap(opcode)) { - handled = true; - ru->rmask = 0xffff; - ru->wmask = 0xffff; - } - - if (!handled) { - write_log("ru_fill: %04x = { %04x, %04x }\n", - real_opcode, ru->rmask, ru->wmask); - abort(); - } -} - -/******************************************************************** - * register allocation per block logging * - ********************************************************************/ - -static uae_s8 vstate[VREGS]; -static uae_s8 vwritten[VREGS]; -static uae_s8 nstate[N_REGS]; - -#define L_UNKNOWN -127 -#define L_UNAVAIL -1 -#define L_NEEDED -2 -#define L_UNNEEDED -3 - -static __inline__ void big_to_small_state(bigstate * b, smallstate * s) -{ - int i; - - for (i = 0; i < VREGS; i++) - s->virt[i] = vstate[i]; - for (i = 0; i < N_REGS; i++) - s->nat[i] = nstate[i]; -} - -static __inline__ int callers_need_recompile(bigstate * b, smallstate * s) -{ - int i; - int reverse = 0; - - for (i = 0; i < VREGS; i++) { - if (vstate[i] != L_UNNEEDED && s->virt[i] == L_UNNEEDED) - return 1; - if (vstate[i] == L_UNNEEDED && s->virt[i] != L_UNNEEDED) - reverse++; - } - for (i = 0; i < N_REGS; i++) { - if (nstate[i] >= 0 && nstate[i] != s->nat[i]) - return 1; - if (nstate[i] < 0 && s->nat[i] >= 0) - reverse++; - } - if (reverse >= 2 && USE_MATCH) - return 1; /* In this case, it might be worth recompiling the - * callers */ - return 0; -} - -static __inline__ void log_startblock(void) -{ - int i; - - for (i = 0; i < VREGS; i++) { - vstate[i] = L_UNKNOWN; - vwritten[i] = 0; - } - for (i = 0; i < N_REGS; i++) - nstate[i] = L_UNKNOWN; -} - -/* Using an n-reg for a temp variable */ -static __inline__ void log_isused(int n) -{ - if (nstate[n] == L_UNKNOWN) - nstate[n] = L_UNAVAIL; -} - -static __inline__ void log_visused(int r) -{ - if (vstate[r] == L_UNKNOWN) - vstate[r] = L_NEEDED; -} - -static __inline__ void do_load_reg(int n, int r) -{ - if (r == FLAGTMP) - raw_load_flagreg(n, r); - else if (r == FLAGX) - raw_load_flagx(n, r); - else - raw_mov_l_rm(n, (uintptr) live.state[r].mem); -} - -static __inline__ void check_load_reg(int n, int r) -{ - raw_mov_l_rm(n, (uintptr) live.state[r].mem); -} - -static __inline__ void log_vwrite(int r) -{ - vwritten[r] = 1; -} - -/* Using an n-reg to hold a v-reg */ -static __inline__ void log_isreg(int n, int r) -{ - static int count = 0; - - if (nstate[n] == L_UNKNOWN && r < 16 && !vwritten[r] && USE_MATCH) - nstate[n] = r; - else { - do_load_reg(n, r); - if (nstate[n] == L_UNKNOWN) - nstate[n] = L_UNAVAIL; - } - if (vstate[r] == L_UNKNOWN) - vstate[r] = L_NEEDED; -} - -static __inline__ void log_clobberreg(int r) -{ - if (vstate[r] == L_UNKNOWN) - vstate[r] = L_UNNEEDED; -} - -/* This ends all possibility of clever register allocation */ - -static __inline__ void log_flush(void) -{ - int i; - - for (i = 0; i < VREGS; i++) - if (vstate[i] == L_UNKNOWN) - vstate[i] = L_NEEDED; - for (i = 0; i < N_REGS; i++) - if (nstate[i] == L_UNKNOWN) - nstate[i] = L_UNAVAIL; -} - -static __inline__ void log_dump(void) -{ - int i; - - return; - - write_log("----------------------\n"); - for (i = 0; i < N_REGS; i++) { - switch (nstate[i]) { - case L_UNKNOWN: - write_log("Nat %d : UNKNOWN\n", i); - break; - case L_UNAVAIL: - write_log("Nat %d : UNAVAIL\n", i); - break; - default: - write_log("Nat %d : %d\n", i, nstate[i]); - break; - } - } - for (i = 0; i < VREGS; i++) { - if (vstate[i] == L_UNNEEDED) - write_log("Virt %d: UNNEEDED\n", i); - } -} - -/******************************************************************** - * register status handling. EMIT TIME! * - ********************************************************************/ - -static __inline__ void set_status(int r, int status) -{ - if (status == ISCONST) - log_clobberreg(r); - live.state[r].status=status; -} - -static __inline__ int isinreg(int r) -{ - return live.state[r].status==CLEAN || live.state[r].status==DIRTY; -} - -static __inline__ void adjust_nreg(int r, uae_u32 val) -{ - if (!val) - return; - raw_lea_l_brr(r,r,val); -} - -static void tomem(int r) -{ - int rr=live.state[r].realreg; - - if (isinreg(r)) { - if (live.state[r].val && live.nat[rr].nholds==1 - && !live.nat[rr].locked) { - // write_log("RemovingA offset %x from reg %d (%d) at %p\n", - // live.state[r].val,r,rr,target); - adjust_nreg(rr,live.state[r].val); - live.state[r].val=0; - live.state[r].dirtysize=4; - set_status(r,DIRTY); - } - } - - if (live.state[r].status==DIRTY) { - switch (live.state[r].dirtysize) { - case 1: raw_mov_b_mr((uintptr)live.state[r].mem,rr); break; - case 2: raw_mov_w_mr((uintptr)live.state[r].mem,rr); break; - case 4: raw_mov_l_mr((uintptr)live.state[r].mem,rr); break; - default: abort(); - } - log_vwrite(r); - set_status(r,CLEAN); - live.state[r].dirtysize=0; - } -} - -static __inline__ int isconst(int r) -{ - return live.state[r].status==ISCONST; -} - -int is_const(int r) -{ - return isconst(r); -} - -static __inline__ void writeback_const(int r) -{ - if (!isconst(r)) - return; - Dif (live.state[r].needflush==NF_HANDLER) { - write_log("Trying to write back constant NF_HANDLER!\n"); - abort(); - } - - raw_mov_l_mi((uintptr)live.state[r].mem,live.state[r].val); - log_vwrite(r); - live.state[r].val=0; - set_status(r,INMEM); -} - -static __inline__ void tomem_c(int r) -{ - if (isconst(r)) { - writeback_const(r); - } - else - tomem(r); -} - -static void evict(int r) -{ - int rr; - - if (!isinreg(r)) - return; - tomem(r); - rr=live.state[r].realreg; - - Dif (live.nat[rr].locked && - live.nat[rr].nholds==1) { - write_log("register %d in nreg %d is locked!\n",r,live.state[r].realreg); - abort(); - } - - live.nat[rr].nholds--; - if (live.nat[rr].nholds!=live.state[r].realind) { /* Was not last */ - int topreg=live.nat[rr].holds[live.nat[rr].nholds]; - int thisind=live.state[r].realind; - - live.nat[rr].holds[thisind]=topreg; - live.state[topreg].realind=thisind; - } - live.state[r].realreg=-1; - set_status(r,INMEM); -} - -static __inline__ void free_nreg(int r) -{ - int i=live.nat[r].nholds; - - while (i) { - int vr; - - --i; - vr=live.nat[r].holds[i]; - evict(vr); - } - Dif (live.nat[r].nholds!=0) { - write_log("Failed to free nreg %d, nholds is %d\n",r,live.nat[r].nholds); - abort(); - } -} - -/* Use with care! */ -static __inline__ void isclean(int r) -{ - if (!isinreg(r)) - return; - live.state[r].validsize=4; - live.state[r].dirtysize=0; - live.state[r].val=0; - set_status(r,CLEAN); -} - -static __inline__ void disassociate(int r) -{ - isclean(r); - evict(r); -} - -static __inline__ void set_const(int r, uae_u32 val) -{ - disassociate(r); - live.state[r].val=val; - set_status(r,ISCONST); -} - -static __inline__ uae_u32 get_offset(int r) -{ - return live.state[r].val; -} - -static int alloc_reg_hinted(int r, int size, int willclobber, int hint) -{ - int bestreg; - uae_s32 when; - int i; - uae_s32 badness=0; /* to shut up gcc */ - bestreg=-1; - when=2000000000; - - /* XXX use a regalloc_order table? */ - for (i=0;i0) { - free_nreg(bestreg); - } - if (isinreg(r)) { - int rr=live.state[r].realreg; - /* This will happen if we read a partially dirty register at a - bigger size */ - Dif (willclobber || live.state[r].validsize>=size) - abort(); - Dif (live.nat[rr].nholds!=1) - abort(); - if (size==4 && live.state[r].validsize==2) { - log_isused(bestreg); - log_visused(r); - raw_mov_l_rm(bestreg,(uintptr)live.state[r].mem); - raw_bswap_32(bestreg); - raw_zero_extend_16_rr(rr,rr); - raw_zero_extend_16_rr(bestreg,bestreg); - raw_bswap_32(bestreg); - raw_lea_l_brr_indexed(rr,rr,bestreg,1,0); - live.state[r].validsize=4; - live.nat[rr].touched=touchcnt++; - return rr; - } - if (live.state[r].validsize==1) { - /* Nothing yet */ - } - evict(r); - } - - if (!willclobber) { - if (live.state[r].status!=UNDEF) { - if (isconst(r)) { - raw_mov_l_ri(bestreg,live.state[r].val); - live.state[r].val=0; - live.state[r].dirtysize=4; - set_status(r,DIRTY); - log_isused(bestreg); - } - else { - log_isreg(bestreg, r); /* This will also load it! */ - live.state[r].dirtysize=0; - set_status(r,CLEAN); - } - } - else { - live.state[r].val=0; - live.state[r].dirtysize=0; - set_status(r,CLEAN); - log_isused(bestreg); - } - live.state[r].validsize=4; - } - else { /* this is the easiest way, but not optimal. FIXME! */ - /* Now it's trickier, but hopefully still OK */ - if (!isconst(r) || size==4) { - live.state[r].validsize=size; - live.state[r].dirtysize=size; - live.state[r].val=0; - set_status(r,DIRTY); - if (size == 4) { - log_clobberreg(r); - log_isused(bestreg); - } - else { - log_visused(r); - log_isused(bestreg); - } - } - else { - if (live.state[r].status!=UNDEF) - raw_mov_l_ri(bestreg,live.state[r].val); - live.state[r].val=0; - live.state[r].validsize=4; - live.state[r].dirtysize=4; - set_status(r,DIRTY); - log_isused(bestreg); - } - } - live.state[r].realreg=bestreg; - live.state[r].realind=live.nat[bestreg].nholds; - live.nat[bestreg].touched=touchcnt++; - live.nat[bestreg].holds[live.nat[bestreg].nholds]=r; - live.nat[bestreg].nholds++; - - return bestreg; -} - -static int alloc_reg(int r, int size, int willclobber) -{ - return alloc_reg_hinted(r,size,willclobber,-1); -} - -static void unlock2(int r) -{ - Dif (!live.nat[r].locked) - abort(); - live.nat[r].locked--; -} - -static void setlock(int r) -{ - live.nat[r].locked++; -} - - -static void mov_nregs(int d, int s) -{ - int ns=live.nat[s].nholds; - int nd=live.nat[d].nholds; - int i; - - if (s==d) - return; - - if (nd>0) - free_nreg(d); - - log_isused(d); - raw_mov_l_rr(d,s); - - for (i=0;i=size) { - n=live.state[r].realreg; - switch(size) { - case 1: - if (live.nat[n].canbyte || spec>=0) { - answer=n; - } - break; - case 2: - if (live.nat[n].canword || spec>=0) { - answer=n; - } - break; - case 4: - answer=n; - break; - default: abort(); - } - if (answer<0) - evict(r); - } - /* either the value was in memory to start with, or it was evicted and - is in memory now */ - if (answer<0) { - answer=alloc_reg_hinted(r,spec>=0?4:size,0,spec); - } - - if (spec>=0 && spec!=answer) { - /* Too bad */ - mov_nregs(spec,answer); - answer=spec; - } - live.nat[answer].locked++; - live.nat[answer].touched=touchcnt++; - return answer; -} - - - -static int readreg(int r, int size) -{ - return readreg_general(r,size,-1,0); -} - -static int readreg_specific(int r, int size, int spec) -{ - return readreg_general(r,size,spec,0); -} - -static int readreg_offset(int r, int size) -{ - return readreg_general(r,size,-1,1); -} - -/* writereg_general(r, size, spec) - * - * INPUT - * - r : mid-layer register - * - size : requested size (1/2/4) - * - spec : -1 if find or make a register free, otherwise specifies - * the physical register to use in any case - * - * OUTPUT - * - hard (physical, x86 here) register allocated to virtual register r - */ -static __inline__ int writereg_general(int r, int size, int spec) -{ - int n; - int answer=-1; - - record_register(r); - if (size<4) { - remove_offset(r,spec); - } - - make_exclusive(r,size,spec); - if (isinreg(r)) { - int nvsize=size>live.state[r].validsize?size:live.state[r].validsize; - int ndsize=size>live.state[r].dirtysize?size:live.state[r].dirtysize; - n=live.state[r].realreg; - - Dif (live.nat[n].nholds!=1) - abort(); - switch(size) { - case 1: - if (live.nat[n].canbyte || spec>=0) { - live.state[r].dirtysize=ndsize; - live.state[r].validsize=nvsize; - answer=n; - } - break; - case 2: - if (live.nat[n].canword || spec>=0) { - live.state[r].dirtysize=ndsize; - live.state[r].validsize=nvsize; - answer=n; - } - break; - case 4: - live.state[r].dirtysize=ndsize; - live.state[r].validsize=nvsize; - answer=n; - break; - default: abort(); - } - if (answer<0) - evict(r); - } - /* either the value was in memory to start with, or it was evicted and - is in memory now */ - if (answer<0) { - answer=alloc_reg_hinted(r,size,1,spec); - } - if (spec>=0 && spec!=answer) { - mov_nregs(spec,answer); - answer=spec; - } - if (live.state[r].status==UNDEF) - live.state[r].validsize=4; - live.state[r].dirtysize=size>live.state[r].dirtysize?size:live.state[r].dirtysize; - live.state[r].validsize=size>live.state[r].validsize?size:live.state[r].validsize; - - live.nat[answer].locked++; - live.nat[answer].touched=touchcnt++; - if (size==4) { - live.state[r].val=0; - } - else { - Dif (live.state[r].val) { - write_log("Problem with val\n"); - abort(); - } - } - set_status(r,DIRTY); - return answer; -} - -static int writereg(int r, int size) -{ - return writereg_general(r,size,-1); -} - -static int writereg_specific(int r, int size, int spec) -{ - return writereg_general(r,size,spec); -} - -static __inline__ int rmw_general(int r, int wsize, int rsize, int spec) -{ - int n; - int answer=-1; - - record_register(r); - if (live.state[r].status==UNDEF) { - write_log("WARNING: Unexpected read of undefined register %d\n",r); - } - remove_offset(r,spec); - make_exclusive(r,0,spec); - - Dif (wsize=rsize) { - n=live.state[r].realreg; - Dif (live.nat[n].nholds!=1) - abort(); - - switch(rsize) { - case 1: - if (live.nat[n].canbyte || spec>=0) { - answer=n; - } - break; - case 2: - if (live.nat[n].canword || spec>=0) { - answer=n; - } - break; - case 4: - answer=n; - break; - default: abort(); - } - if (answer<0) - evict(r); - } - /* either the value was in memory to start with, or it was evicted and - is in memory now */ - if (answer<0) { - answer=alloc_reg_hinted(r,spec>=0?4:rsize,0,spec); - } - - if (spec>=0 && spec!=answer) { - /* Too bad */ - mov_nregs(spec,answer); - answer=spec; - } - if (wsize>live.state[r].dirtysize) - live.state[r].dirtysize=wsize; - if (wsize>live.state[r].validsize) - live.state[r].validsize=wsize; - set_status(r,DIRTY); - - live.nat[answer].locked++; - live.nat[answer].touched=touchcnt++; - - Dif (live.state[r].val) { - write_log("Problem with val(rmw)\n"); - abort(); - } - return answer; -} - -static int rmw(int r, int wsize, int rsize) -{ - return rmw_general(r,wsize,rsize,-1); -} - -static int rmw_specific(int r, int wsize, int rsize, int spec) -{ - return rmw_general(r,wsize,rsize,spec); -} - - -/* needed for restoring the carry flag on non-P6 cores */ -static void bt_l_ri_noclobber(R4 r, IMM i) -{ - int size=4; - if (i<16) - size=2; - r=readreg(r,size); - raw_bt_l_ri(r,i); - unlock2(r); -} - -/******************************************************************** - * FPU register status handling. EMIT TIME! * - ********************************************************************/ - -static void f_tomem(int r) -{ - if (live.fate[r].status==DIRTY) { -#if USE_LONG_DOUBLE - raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); -#else - raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); -#endif - live.fate[r].status=CLEAN; - } -} - -static void f_tomem_drop(int r) -{ - if (live.fate[r].status==DIRTY) { -#if USE_LONG_DOUBLE - raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); -#else - raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); -#endif - live.fate[r].status=INMEM; - } -} - - -static __inline__ int f_isinreg(int r) -{ - return live.fate[r].status==CLEAN || live.fate[r].status==DIRTY; -} - -static void f_evict(int r) -{ - int rr; - - if (!f_isinreg(r)) - return; - rr=live.fate[r].realreg; - if (live.fat[rr].nholds==1) - f_tomem_drop(r); - else - f_tomem(r); - - Dif (live.fat[rr].locked && - live.fat[rr].nholds==1) { - write_log("FPU register %d in nreg %d is locked!\n",r,live.fate[r].realreg); - abort(); - } - - live.fat[rr].nholds--; - if (live.fat[rr].nholds!=live.fate[r].realind) { /* Was not last */ - int topreg=live.fat[rr].holds[live.fat[rr].nholds]; - int thisind=live.fate[r].realind; - live.fat[rr].holds[thisind]=topreg; - live.fate[topreg].realind=thisind; - } - live.fate[r].status=INMEM; - live.fate[r].realreg=-1; -} - -static __inline__ void f_free_nreg(int r) -{ - int i=live.fat[r].nholds; - - while (i) { - int vr; - - --i; - vr=live.fat[r].holds[i]; - f_evict(vr); - } - Dif (live.fat[r].nholds!=0) { - write_log("Failed to free nreg %d, nholds is %d\n",r,live.fat[r].nholds); - abort(); - } -} - - -/* Use with care! */ -static __inline__ void f_isclean(int r) -{ - if (!f_isinreg(r)) - return; - live.fate[r].status=CLEAN; -} - -static __inline__ void f_disassociate(int r) -{ - f_isclean(r); - f_evict(r); -} - - - -static int f_alloc_reg(int r, int willclobber) -{ - int bestreg; - uae_s32 when; - int i; - uae_s32 badness; - bestreg=-1; - when=2000000000; - for (i=N_FREGS;i--;) { - badness=live.fat[i].touched; - if (live.fat[i].nholds==0) - badness=0; - - if (!live.fat[i].locked && badness0) { - f_free_nreg(bestreg); - } - if (f_isinreg(r)) { - f_evict(r); - } - - if (!willclobber) { - if (live.fate[r].status!=UNDEF) { -#if USE_LONG_DOUBLE - raw_fmov_ext_rm(bestreg,(uintptr)live.fate[r].mem); -#else - raw_fmov_rm(bestreg,(uintptr)live.fate[r].mem); -#endif - } - live.fate[r].status=CLEAN; - } - else { - live.fate[r].status=DIRTY; - } - live.fate[r].realreg=bestreg; - live.fate[r].realind=live.fat[bestreg].nholds; - live.fat[bestreg].touched=touchcnt++; - live.fat[bestreg].holds[live.fat[bestreg].nholds]=r; - live.fat[bestreg].nholds++; - - return bestreg; -} - -static void f_unlock(int r) -{ - Dif (!live.fat[r].locked) - abort(); - live.fat[r].locked--; -} - -static void f_setlock(int r) -{ - live.fat[r].locked++; -} - -static __inline__ int f_readreg(int r) -{ - int n; - int answer=-1; - - if (f_isinreg(r)) { - n=live.fate[r].realreg; - answer=n; - } - /* either the value was in memory to start with, or it was evicted and - is in memory now */ - if (answer<0) - answer=f_alloc_reg(r,0); - - live.fat[answer].locked++; - live.fat[answer].touched=touchcnt++; - return answer; -} - -static __inline__ void f_make_exclusive(int r, int clobber) -{ - freg_status oldstate; - int rr=live.fate[r].realreg; - int nr; - int nind; - int ndirt=0; - int i; - - if (!f_isinreg(r)) - return; - if (live.fat[rr].nholds==1) - return; - for (i=0;i>=i; - return; - } - CLOBBER_SHRL; - r=rmw(r,4,4); - raw_shrl_l_ri(r,i); - unlock2(r); -} -MENDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) - -MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) -{ - if (!i && !needflags) - return; - CLOBBER_SHRL; - r=rmw(r,2,2); - raw_shrl_w_ri(r,i); - unlock2(r); -} -MENDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) - -MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) -{ - if (!i && !needflags) - return; - CLOBBER_SHRL; - r=rmw(r,1,1); - raw_shrl_b_ri(r,i); - unlock2(r); -} -MENDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) - -MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) -{ - if (!i && !needflags) - return; - CLOBBER_SHRA; - r=rmw(r,4,4); - raw_shra_l_ri(r,i); - unlock2(r); -} -MENDFUNC(2,shra_l_ri,(RW4 r, IMM i)) - -MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) -{ - if (!i && !needflags) - return; - CLOBBER_SHRA; - r=rmw(r,2,2); - raw_shra_w_ri(r,i); - unlock2(r); -} -MENDFUNC(2,shra_w_ri,(RW2 r, IMM i)) - -MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) -{ - if (!i && !needflags) - return; - CLOBBER_SHRA; - r=rmw(r,1,1); - raw_shra_b_ri(r,i); - unlock2(r); -} -MENDFUNC(2,shra_b_ri,(RW1 r, IMM i)) - -MIDFUNC(2,shra_l_rr,(RW4 d, R1 r)) -{ - if (isconst(r)) { - COMPCALL(shra_l_ri)(d,(uae_u8)live.state[r].val); - return; - } - CLOBBER_SHRA; - r=readreg_specific(r,1,SHIFTCOUNT_NREG); - d=rmw(d,4,4); - Dif (r!=1) { - write_log("Illegal register %d in raw_rol_b\n",r); - abort(); - } - raw_shra_l_rr(d,r) ; - unlock2(r); - unlock2(d); -} -MENDFUNC(2,shra_l_rr,(RW4 d, R1 r)) - -MIDFUNC(2,shra_w_rr,(RW2 d, R1 r)) -{ /* Can only do this with r==1, i.e. cl */ - - if (isconst(r)) { - COMPCALL(shra_w_ri)(d,(uae_u8)live.state[r].val); - return; - } - CLOBBER_SHRA; - r=readreg_specific(r,1,SHIFTCOUNT_NREG); - d=rmw(d,2,2); - Dif (r!=1) { - write_log("Illegal register %d in raw_shra_b\n",r); - abort(); - } - raw_shra_w_rr(d,r) ; - unlock2(r); - unlock2(d); -} -MENDFUNC(2,shra_w_rr,(RW2 d, R1 r)) - -MIDFUNC(2,shra_b_rr,(RW1 d, R1 r)) -{ /* Can only do this with r==1, i.e. cl */ - - if (isconst(r)) { - COMPCALL(shra_b_ri)(d,(uae_u8)live.state[r].val); - return; - } - - CLOBBER_SHRA; - r=readreg_specific(r,1,SHIFTCOUNT_NREG); - d=rmw(d,1,1); - Dif (r!=1) { - write_log("Illegal register %d in raw_shra_b\n",r); - abort(); - } - raw_shra_b_rr(d,r) ; - unlock2(r); - unlock2(d); -} -MENDFUNC(2,shra_b_rr,(RW1 d, R1 r)) - - -MIDFUNC(2,setcc,(W1 d, IMM cc)) -{ - CLOBBER_SETCC; - d=writereg(d,1); - raw_setcc(d,cc); - unlock2(d); -} -MENDFUNC(2,setcc,(W1 d, IMM cc)) - -MIDFUNC(2,setcc_m,(IMM d, IMM cc)) -{ - CLOBBER_SETCC; - raw_setcc_m(d,cc); -} -MENDFUNC(2,setcc_m,(IMM d, IMM cc)) - -MIDFUNC(3,cmov_b_rr,(RW1 d, R1 s, IMM cc)) -{ - if (d==s) - return; - CLOBBER_CMOV; - s=readreg(s,1); - d=rmw(d,1,1); - raw_cmov_b_rr(d,s,cc); - unlock2(s); - unlock2(d); -} -MENDFUNC(3,cmov_b_rr,(RW1 d, R1 s, IMM cc)) - -MIDFUNC(3,cmov_w_rr,(RW2 d, R2 s, IMM cc)) -{ - if (d==s) - return; - CLOBBER_CMOV; - s=readreg(s,2); - d=rmw(d,2,2); - raw_cmov_w_rr(d,s,cc); - unlock2(s); - unlock2(d); -} -MENDFUNC(3,cmov_w_rr,(RW2 d, R2 s, IMM cc)) - -MIDFUNC(3,cmov_l_rr,(RW4 d, R4 s, IMM cc)) -{ - if (d==s) - return; - CLOBBER_CMOV; - s=readreg(s,4); - d=rmw(d,4,4); - raw_cmov_l_rr(d,s,cc); - unlock2(s); - unlock2(d); -} -MENDFUNC(3,cmov_l_rr,(RW4 d, R4 s, IMM cc)) - -MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) -{ - CLOBBER_CMOV; - d=rmw(d,4,4); - raw_cmov_l_rm(d,s,cc); - unlock2(d); -} -MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) - -MIDFUNC(2,bsf_l_rr,(W4 d, W4 s)) -{ - CLOBBER_BSF; - s = readreg(s, 4); - d = writereg(d, 4); - raw_bsf_l_rr(d, s); - unlock2(s); - unlock2(d); -} -MENDFUNC(2,bsf_l_rr,(W4 d, W4 s)) - -/* Set the Z flag depending on the value in s. Note that the - value has to be 0 or -1 (or, more precisely, for non-zero - values, bit 14 must be set)! */ -MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) -{ - CLOBBER_BSF; - s=rmw_specific(s,4,4,FLAG_NREG3); - tmp=writereg(tmp,4); - raw_flags_set_zero(s, tmp); - unlock2(tmp); - unlock2(s); -} -MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) - -MIDFUNC(2,imul_32_32,(RW4 d, R4 s)) -{ - CLOBBER_MUL; - s=readreg(s,4); - d=rmw(d,4,4); - raw_imul_32_32(d,s); - unlock2(s); - unlock2(d); -} -MENDFUNC(2,imul_32_32,(RW4 d, R4 s)) - -MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) -{ - CLOBBER_MUL; - s=rmw_specific(s,4,4,MUL_NREG2); - d=rmw_specific(d,4,4,MUL_NREG1); - raw_imul_64_32(d,s); - unlock2(s); - unlock2(d); -} -MENDFUNC(2,imul_64_32,(RW4 d, RW4 s)) - -MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) -{ - CLOBBER_MUL; - s=rmw_specific(s,4,4,MUL_NREG2); - d=rmw_specific(d,4,4,MUL_NREG1); - raw_mul_64_32(d,s); - unlock2(s); - unlock2(d); -} -MENDFUNC(2,mul_64_32,(RW4 d, RW4 s)) - -MIDFUNC(2,mul_32_32,(RW4 d, R4 s)) -{ - CLOBBER_MUL; - s=readreg(s,4); - d=rmw(d,4,4); - raw_mul_32_32(d,s); - unlock2(s); - unlock2(d); -} -MENDFUNC(2,mul_32_32,(RW4 d, R4 s)) - -#if SIZEOF_VOID_P == 8 -MIDFUNC(2,sign_extend_32_rr,(W4 d, R2 s)) -{ - int isrmw; - - if (isconst(s)) { - set_const(d,(uae_s32)live.state[s].val); - return; - } - - CLOBBER_SE32; - isrmw=(s==d); - if (!isrmw) { - s=readreg(s,4); - d=writereg(d,4); - } - else { /* If we try to lock this twice, with different sizes, we - are int trouble! */ - s=d=rmw(s,4,4); - } - raw_sign_extend_32_rr(d,s); - if (!isrmw) { - unlock2(d); - unlock2(s); - } - else { - unlock2(s); - } -} -MENDFUNC(2,sign_extend_32_rr,(W4 d, R2 s)) -#endif - -MIDFUNC(2,sign_extend_16_rr,(W4 d, R2 s)) -{ - int isrmw; - - if (isconst(s)) { - set_const(d,(uae_s32)(uae_s16)live.state[s].val); - return; - } - - CLOBBER_SE16; - isrmw=(s==d); - if (!isrmw) { - s=readreg(s,2); - d=writereg(d,4); - } - else { /* If we try to lock this twice, with different sizes, we - are int trouble! */ - s=d=rmw(s,4,2); - } - raw_sign_extend_16_rr(d,s); - if (!isrmw) { - unlock2(d); - unlock2(s); - } - else { - unlock2(s); - } -} -MENDFUNC(2,sign_extend_16_rr,(W4 d, R2 s)) - -MIDFUNC(2,sign_extend_8_rr,(W4 d, R1 s)) -{ - int isrmw; - - if (isconst(s)) { - set_const(d,(uae_s32)(uae_s8)live.state[s].val); - return; - } - - isrmw=(s==d); - CLOBBER_SE8; - if (!isrmw) { - s=readreg(s,1); - d=writereg(d,4); - } - else { /* If we try to lock this twice, with different sizes, we - are int trouble! */ - s=d=rmw(s,4,1); - } - - raw_sign_extend_8_rr(d,s); - - if (!isrmw) { - unlock2(d); - unlock2(s); - } - else { - unlock2(s); - } -} -MENDFUNC(2,sign_extend_8_rr,(W4 d, R1 s)) - - -MIDFUNC(2,zero_extend_16_rr,(W4 d, R2 s)) -{ - int isrmw; - - if (isconst(s)) { - set_const(d,(uae_u32)(uae_u16)live.state[s].val); - return; - } - - isrmw=(s==d); - CLOBBER_ZE16; - if (!isrmw) { - s=readreg(s,2); - d=writereg(d,4); - } - else { /* If we try to lock this twice, with different sizes, we - are int trouble! */ - s=d=rmw(s,4,2); - } - raw_zero_extend_16_rr(d,s); - if (!isrmw) { - unlock2(d); - unlock2(s); - } - else { - unlock2(s); - } -} -MENDFUNC(2,zero_extend_16_rr,(W4 d, R2 s)) - -MIDFUNC(2,zero_extend_8_rr,(W4 d, R1 s)) -{ - int isrmw; - if (isconst(s)) { - set_const(d,(uae_u32)(uae_u8)live.state[s].val); - return; - } - - isrmw=(s==d); - CLOBBER_ZE8; - if (!isrmw) { - s=readreg(s,1); - d=writereg(d,4); - } - else { /* If we try to lock this twice, with different sizes, we - are int trouble! */ - s=d=rmw(s,4,1); - } - - raw_zero_extend_8_rr(d,s); - - if (!isrmw) { - unlock2(d); - unlock2(s); - } - else { - unlock2(s); - } -} -MENDFUNC(2,zero_extend_8_rr,(W4 d, R1 s)) - -MIDFUNC(2,mov_b_rr,(W1 d, R1 s)) -{ - if (d==s) - return; - if (isconst(s)) { - COMPCALL(mov_b_ri)(d,(uae_u8)live.state[s].val); - return; - } - - CLOBBER_MOV; - s=readreg(s,1); - d=writereg(d,1); - raw_mov_b_rr(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,mov_b_rr,(W1 d, R1 s)) - -MIDFUNC(2,mov_w_rr,(W2 d, R2 s)) -{ - if (d==s) - return; - if (isconst(s)) { - COMPCALL(mov_w_ri)(d,(uae_u16)live.state[s].val); - return; - } - - CLOBBER_MOV; - s=readreg(s,2); - d=writereg(d,2); - raw_mov_w_rr(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,mov_w_rr,(W2 d, R2 s)) - - -MIDFUNC(4,mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) -{ - CLOBBER_MOV; - baser=readreg(baser,4); - index=readreg(index,4); - d=writereg(d,4); - - raw_mov_l_rrm_indexed(d,baser,index,factor); - unlock2(d); - unlock2(baser); - unlock2(index); -} -MENDFUNC(4,mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) - -MIDFUNC(4,mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) -{ - CLOBBER_MOV; - baser=readreg(baser,4); - index=readreg(index,4); - d=writereg(d,2); - - raw_mov_w_rrm_indexed(d,baser,index,factor); - unlock2(d); - unlock2(baser); - unlock2(index); -} -MENDFUNC(4,mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) - -MIDFUNC(4,mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) -{ - CLOBBER_MOV; - baser=readreg(baser,4); - index=readreg(index,4); - d=writereg(d,1); - - raw_mov_b_rrm_indexed(d,baser,index,factor); - - unlock2(d); - unlock2(baser); - unlock2(index); -} -MENDFUNC(4,mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) - - -MIDFUNC(4,mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) -{ - CLOBBER_MOV; - baser=readreg(baser,4); - index=readreg(index,4); - s=readreg(s,4); - - Dif (baser==s || index==s) - abort(); - - - raw_mov_l_mrr_indexed(baser,index,factor,s); - unlock2(s); - unlock2(baser); - unlock2(index); -} -MENDFUNC(4,mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) - -MIDFUNC(4,mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) -{ - CLOBBER_MOV; - baser=readreg(baser,4); - index=readreg(index,4); - s=readreg(s,2); - - raw_mov_w_mrr_indexed(baser,index,factor,s); - unlock2(s); - unlock2(baser); - unlock2(index); -} -MENDFUNC(4,mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) - -MIDFUNC(4,mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) -{ - CLOBBER_MOV; - s=readreg(s,1); - baser=readreg(baser,4); - index=readreg(index,4); - - raw_mov_b_mrr_indexed(baser,index,factor,s); - unlock2(s); - unlock2(baser); - unlock2(index); -} -MENDFUNC(4,mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) - - -MIDFUNC(5,mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) -{ - int basereg=baser; - int indexreg=index; - - CLOBBER_MOV; - s=readreg(s,4); - baser=readreg_offset(baser,4); - index=readreg_offset(index,4); - - base+=get_offset(basereg); - base+=factor*get_offset(indexreg); - - raw_mov_l_bmrr_indexed(base,baser,index,factor,s); - unlock2(s); - unlock2(baser); - unlock2(index); -} -MENDFUNC(5,mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) - -MIDFUNC(5,mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) -{ - int basereg=baser; - int indexreg=index; - - CLOBBER_MOV; - s=readreg(s,2); - baser=readreg_offset(baser,4); - index=readreg_offset(index,4); - - base+=get_offset(basereg); - base+=factor*get_offset(indexreg); - - raw_mov_w_bmrr_indexed(base,baser,index,factor,s); - unlock2(s); - unlock2(baser); - unlock2(index); -} -MENDFUNC(5,mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) - -MIDFUNC(5,mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) -{ - int basereg=baser; - int indexreg=index; - - CLOBBER_MOV; - s=readreg(s,1); - baser=readreg_offset(baser,4); - index=readreg_offset(index,4); - - base+=get_offset(basereg); - base+=factor*get_offset(indexreg); - - raw_mov_b_bmrr_indexed(base,baser,index,factor,s); - unlock2(s); - unlock2(baser); - unlock2(index); -} -MENDFUNC(5,mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) - - - -/* Read a long from base+baser+factor*index */ -MIDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int basereg=baser; - int indexreg=index; - - CLOBBER_MOV; - baser=readreg_offset(baser,4); - index=readreg_offset(index,4); - base+=get_offset(basereg); - base+=factor*get_offset(indexreg); - d=writereg(d,4); - raw_mov_l_brrm_indexed(d,base,baser,index,factor); - unlock2(d); - unlock2(baser); - unlock2(index); -} -MENDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) - - -MIDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int basereg=baser; - int indexreg=index; - - CLOBBER_MOV; - remove_offset(d,-1); - baser=readreg_offset(baser,4); - index=readreg_offset(index,4); - base+=get_offset(basereg); - base+=factor*get_offset(indexreg); - d=writereg(d,2); - raw_mov_w_brrm_indexed(d,base,baser,index,factor); - unlock2(d); - unlock2(baser); - unlock2(index); -} -MENDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) - - -MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int basereg=baser; - int indexreg=index; - - CLOBBER_MOV; - remove_offset(d,-1); - baser=readreg_offset(baser,4); - index=readreg_offset(index,4); - base+=get_offset(basereg); - base+=factor*get_offset(indexreg); - d=writereg(d,1); - raw_mov_b_brrm_indexed(d,base,baser,index,factor); - unlock2(d); - unlock2(baser); - unlock2(index); -} -MENDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) - -/* Read a long from base+factor*index */ -MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) -{ - int indexreg=index; - - if (isconst(index)) { - COMPCALL(mov_l_rm)(d,base+factor*live.state[index].val); - return; - } - - CLOBBER_MOV; - index=readreg_offset(index,4); - base+=get_offset(indexreg)*factor; - d=writereg(d,4); - - raw_mov_l_rm_indexed(d,base,index,factor); - unlock2(index); - unlock2(d); -} -MENDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) - - -/* read the long at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_l_rR,(W4 d, R4 s, IMM offset)) -{ - if (isconst(s)) { - COMPCALL(mov_l_rm)(d,live.state[s].val+offset); - return; - } - CLOBBER_MOV; - s=readreg(s,4); - d=writereg(d,4); - - raw_mov_l_rR(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_l_rR,(W4 d, R4 s, IMM offset)) - -/* read the word at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_w_rR,(W2 d, R4 s, IMM offset)) -{ - if (isconst(s)) { - COMPCALL(mov_w_rm)(d,live.state[s].val+offset); - return; - } - CLOBBER_MOV; - s=readreg(s,4); - d=writereg(d,2); - - raw_mov_w_rR(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_w_rR,(W2 d, R4 s, IMM offset)) - -/* read the word at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_b_rR,(W1 d, R4 s, IMM offset)) -{ - if (isconst(s)) { - COMPCALL(mov_b_rm)(d,live.state[s].val+offset); - return; - } - CLOBBER_MOV; - s=readreg(s,4); - d=writereg(d,1); - - raw_mov_b_rR(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_b_rR,(W1 d, R4 s, IMM offset)) - -/* read the long at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_l_brR,(W4 d, R4 s, IMM offset)) -{ - int sreg=s; - if (isconst(s)) { - COMPCALL(mov_l_rm)(d,live.state[s].val+offset); - return; - } - CLOBBER_MOV; - s=readreg_offset(s,4); - offset+=get_offset(sreg); - d=writereg(d,4); - - raw_mov_l_brR(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_l_brR,(W4 d, R4 s, IMM offset)) - -/* read the word at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_w_brR,(W2 d, R4 s, IMM offset)) -{ - int sreg=s; - if (isconst(s)) { - COMPCALL(mov_w_rm)(d,live.state[s].val+offset); - return; - } - CLOBBER_MOV; - remove_offset(d,-1); - s=readreg_offset(s,4); - offset+=get_offset(sreg); - d=writereg(d,2); - - raw_mov_w_brR(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_w_brR,(W2 d, R4 s, IMM offset)) - -/* read the word at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_b_brR,(W1 d, R4 s, IMM offset)) -{ - int sreg=s; - if (isconst(s)) { - COMPCALL(mov_b_rm)(d,live.state[s].val+offset); - return; - } - CLOBBER_MOV; - remove_offset(d,-1); - s=readreg_offset(s,4); - offset+=get_offset(sreg); - d=writereg(d,1); - - raw_mov_b_brR(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_b_brR,(W1 d, R4 s, IMM offset)) - -MIDFUNC(3,mov_l_Ri,(R4 d, IMM i, IMM offset)) -{ - int dreg=d; - if (isconst(d)) { - COMPCALL(mov_l_mi)(live.state[d].val+offset,i); - return; - } - - CLOBBER_MOV; - d=readreg_offset(d,4); - offset+=get_offset(dreg); - raw_mov_l_Ri(d,i,offset); - unlock2(d); -} -MENDFUNC(3,mov_l_Ri,(R4 d, IMM i, IMM offset)) - -MIDFUNC(3,mov_w_Ri,(R4 d, IMM i, IMM offset)) -{ - int dreg=d; - if (isconst(d)) { - COMPCALL(mov_w_mi)(live.state[d].val+offset,i); - return; - } - - CLOBBER_MOV; - d=readreg_offset(d,4); - offset+=get_offset(dreg); - raw_mov_w_Ri(d,i,offset); - unlock2(d); -} -MENDFUNC(3,mov_w_Ri,(R4 d, IMM i, IMM offset)) - -MIDFUNC(3,mov_b_Ri,(R4 d, IMM i, IMM offset)) -{ - int dreg=d; - if (isconst(d)) { - COMPCALL(mov_b_mi)(live.state[d].val+offset,i); - return; - } - - CLOBBER_MOV; - d=readreg_offset(d,4); - offset+=get_offset(dreg); - raw_mov_b_Ri(d,i,offset); - unlock2(d); -} -MENDFUNC(3,mov_b_Ri,(R4 d, IMM i, IMM offset)) - - /* Warning! OFFSET is byte sized only! */ -MIDFUNC(3,mov_l_Rr,(R4 d, R4 s, IMM offset)) -{ - if (isconst(d)) { - COMPCALL(mov_l_mr)(live.state[d].val+offset,s); - return; - } - if (isconst(s)) { - COMPCALL(mov_l_Ri)(d,live.state[s].val,offset); - return; - } - - CLOBBER_MOV; - s=readreg(s,4); - d=readreg(d,4); - - raw_mov_l_Rr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_l_Rr,(R4 d, R4 s, IMM offset)) - -MIDFUNC(3,mov_w_Rr,(R4 d, R2 s, IMM offset)) -{ - if (isconst(d)) { - COMPCALL(mov_w_mr)(live.state[d].val+offset,s); - return; - } - if (isconst(s)) { - COMPCALL(mov_w_Ri)(d,(uae_u16)live.state[s].val,offset); - return; - } - - CLOBBER_MOV; - s=readreg(s,2); - d=readreg(d,4); - raw_mov_w_Rr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_w_Rr,(R4 d, R2 s, IMM offset)) - -MIDFUNC(3,mov_b_Rr,(R4 d, R1 s, IMM offset)) -{ - if (isconst(d)) { - COMPCALL(mov_b_mr)(live.state[d].val+offset,s); - return; - } - if (isconst(s)) { - COMPCALL(mov_b_Ri)(d,(uae_u8)live.state[s].val,offset); - return; - } - - CLOBBER_MOV; - s=readreg(s,1); - d=readreg(d,4); - raw_mov_b_Rr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_b_Rr,(R4 d, R1 s, IMM offset)) - -MIDFUNC(3,lea_l_brr,(W4 d, R4 s, IMM offset)) -{ - if (isconst(s)) { - COMPCALL(mov_l_ri)(d,live.state[s].val+offset); - return; - } -#if USE_OFFSET - if (d==s) { - add_offset(d,offset); - return; - } -#endif - CLOBBER_LEA; - s=readreg(s,4); - d=writereg(d,4); - raw_lea_l_brr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,lea_l_brr,(W4 d, R4 s, IMM offset)) - -MIDFUNC(5,lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) -{ - if (!offset) { - COMPCALL(lea_l_rr_indexed)(d,s,index,factor); - return; - } - CLOBBER_LEA; - s=readreg(s,4); - index=readreg(index,4); - d=writereg(d,4); - - raw_lea_l_brr_indexed(d,s,index,factor,offset); - unlock2(d); - unlock2(index); - unlock2(s); -} -MENDFUNC(5,lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) - -MIDFUNC(4,lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) -{ - CLOBBER_LEA; - s=readreg(s,4); - index=readreg(index,4); - d=writereg(d,4); - - raw_lea_l_rr_indexed(d,s,index,factor); - unlock2(d); - unlock2(index); - unlock2(s); -} -MENDFUNC(4,lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) - -/* write d to the long at the address contained in s+offset */ -MIDFUNC(3,mov_l_bRr,(R4 d, R4 s, IMM offset)) -{ - int dreg=d; - if (isconst(d)) { - COMPCALL(mov_l_mr)(live.state[d].val+offset,s); - return; - } - - CLOBBER_MOV; - s=readreg(s,4); - d=readreg_offset(d,4); - offset+=get_offset(dreg); - - raw_mov_l_bRr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_l_bRr,(R4 d, R4 s, IMM offset)) - -/* write the word at the address contained in s+offset and store in d */ -MIDFUNC(3,mov_w_bRr,(R4 d, R2 s, IMM offset)) -{ - int dreg=d; - - if (isconst(d)) { - COMPCALL(mov_w_mr)(live.state[d].val+offset,s); - return; - } - - CLOBBER_MOV; - s=readreg(s,2); - d=readreg_offset(d,4); - offset+=get_offset(dreg); - raw_mov_w_bRr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_w_bRr,(R4 d, R2 s, IMM offset)) - -MIDFUNC(3,mov_b_bRr,(R4 d, R1 s, IMM offset)) -{ - int dreg=d; - if (isconst(d)) { - COMPCALL(mov_b_mr)(live.state[d].val+offset,s); - return; - } - - CLOBBER_MOV; - s=readreg(s,1); - d=readreg_offset(d,4); - offset+=get_offset(dreg); - raw_mov_b_bRr(d,s,offset); - unlock2(d); - unlock2(s); -} -MENDFUNC(3,mov_b_bRr,(R4 d, R1 s, IMM offset)) - -MIDFUNC(1,bswap_32,(RW4 r)) -{ - int reg=r; - - if (isconst(r)) { - uae_u32 oldv=live.state[r].val; - live.state[r].val=reverse32(oldv); - return; - } - - CLOBBER_SW32; - r=rmw(r,4,4); - raw_bswap_32(r); - unlock2(r); -} -MENDFUNC(1,bswap_32,(RW4 r)) - -MIDFUNC(1,bswap_16,(RW2 r)) -{ - if (isconst(r)) { - uae_u32 oldv=live.state[r].val; - live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) | - (oldv&0xffff0000); - return; - } - - CLOBBER_SW16; - r=rmw(r,2,2); - - raw_bswap_16(r); - unlock2(r); -} -MENDFUNC(1,bswap_16,(RW2 r)) - - - -MIDFUNC(2,mov_l_rr,(W4 d, R4 s)) -{ - int olds; - - if (d==s) { /* How pointless! */ - return; - } - if (isconst(s)) { - COMPCALL(mov_l_ri)(d,live.state[s].val); - return; - } - olds=s; - disassociate(d); - s=readreg_offset(s,4); - live.state[d].realreg=s; - live.state[d].realind=live.nat[s].nholds; - live.state[d].val=live.state[olds].val; - live.state[d].validsize=4; - live.state[d].dirtysize=4; - set_status(d,DIRTY); - - live.nat[s].holds[live.nat[s].nholds]=d; - live.nat[s].nholds++; - log_clobberreg(d); - /* write_log("Added %d to nreg %d(%d), now holds %d regs\n", - d,s,live.state[d].realind,live.nat[s].nholds); */ - unlock2(s); -} -MENDFUNC(2,mov_l_rr,(W4 d, R4 s)) - -MIDFUNC(2,mov_l_mr,(IMM d, R4 s)) -{ - if (isconst(s)) { - COMPCALL(mov_l_mi)(d,live.state[s].val); - return; - } - CLOBBER_MOV; - s=readreg(s,4); - - raw_mov_l_mr(d,s); - unlock2(s); -} -MENDFUNC(2,mov_l_mr,(IMM d, R4 s)) - - -MIDFUNC(2,mov_w_mr,(IMM d, R2 s)) -{ - if (isconst(s)) { - COMPCALL(mov_w_mi)(d,(uae_u16)live.state[s].val); - return; - } - CLOBBER_MOV; - s=readreg(s,2); - - raw_mov_w_mr(d,s); - unlock2(s); -} -MENDFUNC(2,mov_w_mr,(IMM d, R2 s)) - -MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) -{ - CLOBBER_MOV; - d=writereg(d,2); - - raw_mov_w_rm(d,s); - unlock2(d); -} -MENDFUNC(2,mov_w_rm,(W2 d, IMM s)) - -MIDFUNC(2,mov_b_mr,(IMM d, R1 s)) -{ - if (isconst(s)) { - COMPCALL(mov_b_mi)(d,(uae_u8)live.state[s].val); - return; - } - - CLOBBER_MOV; - s=readreg(s,1); - - raw_mov_b_mr(d,s); - unlock2(s); -} -MENDFUNC(2,mov_b_mr,(IMM d, R1 s)) - -MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) -{ - CLOBBER_MOV; - d=writereg(d,1); - - raw_mov_b_rm(d,s); - unlock2(d); -} -MENDFUNC(2,mov_b_rm,(W1 d, IMM s)) - -MIDFUNC(2,mov_l_ri,(W4 d, IMM s)) -{ - set_const(d,s); - return; -} -MENDFUNC(2,mov_l_ri,(W4 d, IMM s)) - -MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) -{ - CLOBBER_MOV; - d=writereg(d,2); - - raw_mov_w_ri(d,s); - unlock2(d); -} -MENDFUNC(2,mov_w_ri,(W2 d, IMM s)) - -MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) -{ - CLOBBER_MOV; - d=writereg(d,1); - - raw_mov_b_ri(d,s); - unlock2(d); -} -MENDFUNC(2,mov_b_ri,(W1 d, IMM s)) - - -MIDFUNC(2,add_l_mi,(IMM d, IMM s)) -{ - CLOBBER_ADD; - raw_add_l_mi(d,s) ; -} -MENDFUNC(2,add_l_mi,(IMM d, IMM s)) - -MIDFUNC(2,add_w_mi,(IMM d, IMM s)) -{ - CLOBBER_ADD; - raw_add_w_mi(d,s) ; -} -MENDFUNC(2,add_w_mi,(IMM d, IMM s)) - -MIDFUNC(2,add_b_mi,(IMM d, IMM s)) -{ - CLOBBER_ADD; - raw_add_b_mi(d,s) ; -} -MENDFUNC(2,add_b_mi,(IMM d, IMM s)) - - -MIDFUNC(2,test_l_ri,(R4 d, IMM i)) -{ - CLOBBER_TEST; - d=readreg(d,4); - - raw_test_l_ri(d,i); - unlock2(d); -} -MENDFUNC(2,test_l_ri,(R4 d, IMM i)) - -MIDFUNC(2,test_l_rr,(R4 d, R4 s)) -{ - CLOBBER_TEST; - d=readreg(d,4); - s=readreg(s,4); - - raw_test_l_rr(d,s);; - unlock2(d); - unlock2(s); -} -MENDFUNC(2,test_l_rr,(R4 d, R4 s)) - -MIDFUNC(2,test_w_rr,(R2 d, R2 s)) -{ - CLOBBER_TEST; - d=readreg(d,2); - s=readreg(s,2); - - raw_test_w_rr(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,test_w_rr,(R2 d, R2 s)) - -MIDFUNC(2,test_b_rr,(R1 d, R1 s)) -{ - CLOBBER_TEST; - d=readreg(d,1); - s=readreg(s,1); - - raw_test_b_rr(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,test_b_rr,(R1 d, R1 s)) - - -MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) -{ - if (isconst(d) && !needflags) { - live.state[d].val &= i; - return; - } - - CLOBBER_AND; - d=rmw(d,4,4); - - raw_and_l_ri(d,i); - unlock2(d); -} -MENDFUNC(2,and_l_ri,(RW4 d, IMM i)) - -MIDFUNC(2,and_l,(RW4 d, R4 s)) -{ - CLOBBER_AND; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_and_l(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,and_l,(RW4 d, R4 s)) - -MIDFUNC(2,and_w,(RW2 d, R2 s)) -{ - CLOBBER_AND; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_and_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,and_w,(RW2 d, R2 s)) - -MIDFUNC(2,and_b,(RW1 d, R1 s)) -{ - CLOBBER_AND; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_and_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,and_b,(RW1 d, R1 s)) - -// gb-- used for making an fpcr value in compemu_fpp.cpp -MIDFUNC(2,or_l_rm,(RW4 d, IMM s)) -{ - CLOBBER_OR; - d=rmw(d,4,4); - - raw_or_l_rm(d,s); - unlock2(d); -} -MENDFUNC(2,or_l_rm,(RW4 d, IMM s)) - -MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) -{ - if (isconst(d) && !needflags) { - live.state[d].val|=i; - return; - } - CLOBBER_OR; - d=rmw(d,4,4); - - raw_or_l_ri(d,i); - unlock2(d); -} -MENDFUNC(2,or_l_ri,(RW4 d, IMM i)) - -MIDFUNC(2,or_l,(RW4 d, R4 s)) -{ - if (isconst(d) && isconst(s) && !needflags) { - live.state[d].val|=live.state[s].val; - return; - } - CLOBBER_OR; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_or_l(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,or_l,(RW4 d, R4 s)) - -MIDFUNC(2,or_w,(RW2 d, R2 s)) -{ - CLOBBER_OR; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_or_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,or_w,(RW2 d, R2 s)) - -MIDFUNC(2,or_b,(RW1 d, R1 s)) -{ - CLOBBER_OR; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_or_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,or_b,(RW1 d, R1 s)) - -MIDFUNC(2,adc_l,(RW4 d, R4 s)) -{ - CLOBBER_ADC; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_adc_l(d,s); - - unlock2(d); - unlock2(s); -} -MENDFUNC(2,adc_l,(RW4 d, R4 s)) - -MIDFUNC(2,adc_w,(RW2 d, R2 s)) -{ - CLOBBER_ADC; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_adc_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,adc_w,(RW2 d, R2 s)) - -MIDFUNC(2,adc_b,(RW1 d, R1 s)) -{ - CLOBBER_ADC; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_adc_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,adc_b,(RW1 d, R1 s)) - -MIDFUNC(2,add_l,(RW4 d, R4 s)) -{ - if (isconst(s)) { - COMPCALL(add_l_ri)(d,live.state[s].val); - return; - } - - CLOBBER_ADD; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_add_l(d,s); - - unlock2(d); - unlock2(s); -} -MENDFUNC(2,add_l,(RW4 d, R4 s)) - -MIDFUNC(2,add_w,(RW2 d, R2 s)) -{ - if (isconst(s)) { - COMPCALL(add_w_ri)(d,(uae_u16)live.state[s].val); - return; - } - - CLOBBER_ADD; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_add_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,add_w,(RW2 d, R2 s)) - -MIDFUNC(2,add_b,(RW1 d, R1 s)) -{ - if (isconst(s)) { - COMPCALL(add_b_ri)(d,(uae_u8)live.state[s].val); - return; - } - - CLOBBER_ADD; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_add_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,add_b,(RW1 d, R1 s)) - -MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) -{ - if (!i && !needflags) - return; - if (isconst(d) && !needflags) { - live.state[d].val-=i; - return; - } -#if USE_OFFSET - if (!needflags) { - add_offset(d,-i); - return; - } -#endif - - CLOBBER_SUB; - d=rmw(d,4,4); - - raw_sub_l_ri(d,i); - unlock2(d); -} -MENDFUNC(2,sub_l_ri,(RW4 d, IMM i)) - -MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) -{ - if (!i && !needflags) - return; - - CLOBBER_SUB; - d=rmw(d,2,2); - - raw_sub_w_ri(d,i); - unlock2(d); -} -MENDFUNC(2,sub_w_ri,(RW2 d, IMM i)) - -MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) -{ - if (!i && !needflags) - return; - - CLOBBER_SUB; - d=rmw(d,1,1); - - raw_sub_b_ri(d,i); - - unlock2(d); -} -MENDFUNC(2,sub_b_ri,(RW1 d, IMM i)) - -MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) -{ - if (!i && !needflags) - return; - if (isconst(d) && !needflags) { - live.state[d].val+=i; - return; - } -#if USE_OFFSET - if (!needflags) { - add_offset(d,i); - return; - } -#endif - CLOBBER_ADD; - d=rmw(d,4,4); - raw_add_l_ri(d,i); - unlock2(d); -} -MENDFUNC(2,add_l_ri,(RW4 d, IMM i)) - -MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) -{ - if (!i && !needflags) - return; - - CLOBBER_ADD; - d=rmw(d,2,2); - - raw_add_w_ri(d,i); - unlock2(d); -} -MENDFUNC(2,add_w_ri,(RW2 d, IMM i)) - -MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) -{ - if (!i && !needflags) - return; - - CLOBBER_ADD; - d=rmw(d,1,1); - - raw_add_b_ri(d,i); - - unlock2(d); -} -MENDFUNC(2,add_b_ri,(RW1 d, IMM i)) - -MIDFUNC(2,sbb_l,(RW4 d, R4 s)) -{ - CLOBBER_SBB; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_sbb_l(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,sbb_l,(RW4 d, R4 s)) - -MIDFUNC(2,sbb_w,(RW2 d, R2 s)) -{ - CLOBBER_SBB; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_sbb_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,sbb_w,(RW2 d, R2 s)) - -MIDFUNC(2,sbb_b,(RW1 d, R1 s)) -{ - CLOBBER_SBB; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_sbb_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,sbb_b,(RW1 d, R1 s)) - -MIDFUNC(2,sub_l,(RW4 d, R4 s)) -{ - if (isconst(s)) { - COMPCALL(sub_l_ri)(d,live.state[s].val); - return; - } - - CLOBBER_SUB; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_sub_l(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,sub_l,(RW4 d, R4 s)) - -MIDFUNC(2,sub_w,(RW2 d, R2 s)) -{ - if (isconst(s)) { - COMPCALL(sub_w_ri)(d,(uae_u16)live.state[s].val); - return; - } - - CLOBBER_SUB; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_sub_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,sub_w,(RW2 d, R2 s)) - -MIDFUNC(2,sub_b,(RW1 d, R1 s)) -{ - if (isconst(s)) { - COMPCALL(sub_b_ri)(d,(uae_u8)live.state[s].val); - return; - } - - CLOBBER_SUB; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_sub_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,sub_b,(RW1 d, R1 s)) - -MIDFUNC(2,cmp_l,(R4 d, R4 s)) -{ - CLOBBER_CMP; - s=readreg(s,4); - d=readreg(d,4); - - raw_cmp_l(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,cmp_l,(R4 d, R4 s)) - -MIDFUNC(2,cmp_l_ri,(R4 r, IMM i)) -{ - CLOBBER_CMP; - r=readreg(r,4); - - raw_cmp_l_ri(r,i); - unlock2(r); -} -MENDFUNC(2,cmp_l_ri,(R4 r, IMM i)) - -MIDFUNC(2,cmp_w,(R2 d, R2 s)) -{ - CLOBBER_CMP; - s=readreg(s,2); - d=readreg(d,2); - - raw_cmp_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,cmp_w,(R2 d, R2 s)) - -MIDFUNC(2,cmp_b,(R1 d, R1 s)) -{ - CLOBBER_CMP; - s=readreg(s,1); - d=readreg(d,1); - - raw_cmp_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,cmp_b,(R1 d, R1 s)) - - -MIDFUNC(2,xor_l,(RW4 d, R4 s)) -{ - CLOBBER_XOR; - s=readreg(s,4); - d=rmw(d,4,4); - - raw_xor_l(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,xor_l,(RW4 d, R4 s)) - -MIDFUNC(2,xor_w,(RW2 d, R2 s)) -{ - CLOBBER_XOR; - s=readreg(s,2); - d=rmw(d,2,2); - - raw_xor_w(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,xor_w,(RW2 d, R2 s)) - -MIDFUNC(2,xor_b,(RW1 d, R1 s)) -{ - CLOBBER_XOR; - s=readreg(s,1); - d=rmw(d,1,1); - - raw_xor_b(d,s); - unlock2(d); - unlock2(s); -} -MENDFUNC(2,xor_b,(RW1 d, R1 s)) - -MIDFUNC(5,call_r_11,(W4 out1, R4 r, R4 in1, IMM osize, IMM isize)) -{ - clobber_flags(); - remove_all_offsets(); - if (osize==4) { - if (out1!=in1 && out1!=r) { - COMPCALL(forget_about)(out1); - } - } - else { - tomem_c(out1); - } - - in1=readreg_specific(in1,isize,REG_PAR1); - r=readreg(r,4); - prepare_for_call_1(); /* This should ensure that there won't be - any need for swapping nregs in prepare_for_call_2 - */ -#if USE_NORMAL_CALLING_CONVENTION - raw_push_l_r(in1); -#endif - unlock2(in1); - unlock2(r); - - prepare_for_call_2(); - raw_call_r(r); - -#if USE_NORMAL_CALLING_CONVENTION - raw_inc_sp(4); -#endif - - - live.nat[REG_RESULT].holds[0]=out1; - live.nat[REG_RESULT].nholds=1; - live.nat[REG_RESULT].touched=touchcnt++; - - live.state[out1].realreg=REG_RESULT; - live.state[out1].realind=0; - live.state[out1].val=0; - live.state[out1].validsize=osize; - live.state[out1].dirtysize=osize; - set_status(out1,DIRTY); -} -MENDFUNC(5,call_r_11,(W4 out1, R4 r, R4 in1, IMM osize, IMM isize)) - -MIDFUNC(5,call_r_02,(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2)) -{ - clobber_flags(); - remove_all_offsets(); - in1=readreg_specific(in1,isize1,REG_PAR1); - in2=readreg_specific(in2,isize2,REG_PAR2); - r=readreg(r,4); - prepare_for_call_1(); /* This should ensure that there won't be - any need for swapping nregs in prepare_for_call_2 - */ -#if USE_NORMAL_CALLING_CONVENTION - raw_push_l_r(in2); - raw_push_l_r(in1); -#endif - unlock2(r); - unlock2(in1); - unlock2(in2); - prepare_for_call_2(); - raw_call_r(r); -#if USE_NORMAL_CALLING_CONVENTION - raw_inc_sp(8); -#endif -} -MENDFUNC(5,call_r_02,(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2)) - -/* forget_about() takes a mid-layer register */ -MIDFUNC(1,forget_about,(W4 r)) -{ - if (isinreg(r)) - disassociate(r); - live.state[r].val=0; - set_status(r,UNDEF); -} -MENDFUNC(1,forget_about,(W4 r)) - -MIDFUNC(0,nop,(void)) -{ - raw_nop(); -} -MENDFUNC(0,nop,(void)) - - -MIDFUNC(1,f_forget_about,(FW r)) -{ - if (f_isinreg(r)) - f_disassociate(r); - live.fate[r].status=UNDEF; -} -MENDFUNC(1,f_forget_about,(FW r)) - -MIDFUNC(1,fmov_pi,(FW r)) -{ - r=f_writereg(r); - raw_fmov_pi(r); - f_unlock(r); -} -MENDFUNC(1,fmov_pi,(FW r)) - -MIDFUNC(1,fmov_log10_2,(FW r)) -{ - r=f_writereg(r); - raw_fmov_log10_2(r); - f_unlock(r); -} -MENDFUNC(1,fmov_log10_2,(FW r)) - -MIDFUNC(1,fmov_log2_e,(FW r)) -{ - r=f_writereg(r); - raw_fmov_log2_e(r); - f_unlock(r); -} -MENDFUNC(1,fmov_log2_e,(FW r)) - -MIDFUNC(1,fmov_loge_2,(FW r)) -{ - r=f_writereg(r); - raw_fmov_loge_2(r); - f_unlock(r); -} -MENDFUNC(1,fmov_loge_2,(FW r)) - -MIDFUNC(1,fmov_1,(FW r)) -{ - r=f_writereg(r); - raw_fmov_1(r); - f_unlock(r); -} -MENDFUNC(1,fmov_1,(FW r)) - -MIDFUNC(1,fmov_0,(FW r)) -{ - r=f_writereg(r); - raw_fmov_0(r); - f_unlock(r); -} -MENDFUNC(1,fmov_0,(FW r)) - -MIDFUNC(2,fmov_rm,(FW r, MEMR m)) -{ - r=f_writereg(r); - raw_fmov_rm(r,m); - f_unlock(r); -} -MENDFUNC(2,fmov_rm,(FW r, MEMR m)) - -MIDFUNC(2,fmovi_rm,(FW r, MEMR m)) -{ - r=f_writereg(r); - raw_fmovi_rm(r,m); - f_unlock(r); -} -MENDFUNC(2,fmovi_rm,(FW r, MEMR m)) - -MIDFUNC(2,fmovi_mr,(MEMW m, FR r)) -{ - r=f_readreg(r); - raw_fmovi_mr(m,r); - f_unlock(r); -} -MENDFUNC(2,fmovi_mr,(MEMW m, FR r)) - -MIDFUNC(2,fmovs_rm,(FW r, MEMR m)) -{ - r=f_writereg(r); - raw_fmovs_rm(r,m); - f_unlock(r); -} -MENDFUNC(2,fmovs_rm,(FW r, MEMR m)) - -MIDFUNC(2,fmovs_mr,(MEMW m, FR r)) -{ - r=f_readreg(r); - raw_fmovs_mr(m,r); - f_unlock(r); -} -MENDFUNC(2,fmovs_mr,(MEMW m, FR r)) - -MIDFUNC(2,fmov_ext_mr,(MEMW m, FR r)) -{ - r=f_readreg(r); - raw_fmov_ext_mr(m,r); - f_unlock(r); -} -MENDFUNC(2,fmov_ext_mr,(MEMW m, FR r)) - -MIDFUNC(2,fmov_mr,(MEMW m, FR r)) -{ - r=f_readreg(r); - raw_fmov_mr(m,r); - f_unlock(r); -} -MENDFUNC(2,fmov_mr,(MEMW m, FR r)) - -MIDFUNC(2,fmov_ext_rm,(FW r, MEMR m)) -{ - r=f_writereg(r); - raw_fmov_ext_rm(r,m); - f_unlock(r); -} -MENDFUNC(2,fmov_ext_rm,(FW r, MEMR m)) - -MIDFUNC(2,fmov_rr,(FW d, FR s)) -{ - if (d==s) { /* How pointless! */ - return; - } -#if USE_F_ALIAS - f_disassociate(d); - s=f_readreg(s); - live.fate[d].realreg=s; - live.fate[d].realind=live.fat[s].nholds; - live.fate[d].status=DIRTY; - live.fat[s].holds[live.fat[s].nholds]=d; - live.fat[s].nholds++; - f_unlock(s); -#else - s=f_readreg(s); - d=f_writereg(d); - raw_fmov_rr(d,s); - f_unlock(s); - f_unlock(d); -#endif -} -MENDFUNC(2,fmov_rr,(FW d, FR s)) - -MIDFUNC(2,fldcw_m_indexed,(R4 index, IMM base)) -{ - index=readreg(index,4); - - raw_fldcw_m_indexed(index,base); - unlock2(index); -} -MENDFUNC(2,fldcw_m_indexed,(R4 index, IMM base)) - -MIDFUNC(1,ftst_r,(FR r)) -{ - r=f_readreg(r); - raw_ftst_r(r); - f_unlock(r); -} -MENDFUNC(1,ftst_r,(FR r)) - -MIDFUNC(0,dont_care_fflags,(void)) -{ - f_disassociate(FP_RESULT); -} -MENDFUNC(0,dont_care_fflags,(void)) - -MIDFUNC(2,fsqrt_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_fsqrt_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fsqrt_rr,(FW d, FR s)) - -MIDFUNC(2,fabs_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_fabs_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fabs_rr,(FW d, FR s)) - -MIDFUNC(2,fsin_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_fsin_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fsin_rr,(FW d, FR s)) - -MIDFUNC(2,fcos_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_fcos_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fcos_rr,(FW d, FR s)) - -MIDFUNC(2,ftwotox_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_ftwotox_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,ftwotox_rr,(FW d, FR s)) - -MIDFUNC(2,fetox_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_fetox_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fetox_rr,(FW d, FR s)) - -MIDFUNC(2,frndint_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_frndint_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,frndint_rr,(FW d, FR s)) - -MIDFUNC(2,flog2_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_flog2_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,flog2_rr,(FW d, FR s)) - -MIDFUNC(2,fneg_rr,(FW d, FR s)) -{ - s=f_readreg(s); - d=f_writereg(d); - raw_fneg_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fneg_rr,(FW d, FR s)) - -MIDFUNC(2,fadd_rr,(FRW d, FR s)) -{ - s=f_readreg(s); - d=f_rmw(d); - raw_fadd_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fadd_rr,(FRW d, FR s)) - -MIDFUNC(2,fsub_rr,(FRW d, FR s)) -{ - s=f_readreg(s); - d=f_rmw(d); - raw_fsub_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fsub_rr,(FRW d, FR s)) - -MIDFUNC(2,fcmp_rr,(FR d, FR s)) -{ - d=f_readreg(d); - s=f_readreg(s); - raw_fcmp_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fcmp_rr,(FR d, FR s)) - -MIDFUNC(2,fdiv_rr,(FRW d, FR s)) -{ - s=f_readreg(s); - d=f_rmw(d); - raw_fdiv_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fdiv_rr,(FRW d, FR s)) - -MIDFUNC(2,frem_rr,(FRW d, FR s)) -{ - s=f_readreg(s); - d=f_rmw(d); - raw_frem_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,frem_rr,(FRW d, FR s)) - -MIDFUNC(2,frem1_rr,(FRW d, FR s)) -{ - s=f_readreg(s); - d=f_rmw(d); - raw_frem1_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,frem1_rr,(FRW d, FR s)) - -MIDFUNC(2,fmul_rr,(FRW d, FR s)) -{ - s=f_readreg(s); - d=f_rmw(d); - raw_fmul_rr(d,s); - f_unlock(s); - f_unlock(d); -} -MENDFUNC(2,fmul_rr,(FRW d, FR s)) - -/******************************************************************** - * Support functions exposed to gencomp. CREATE time * - ********************************************************************/ - -void set_zero(int r, int tmp) -{ - if (setzflg_uses_bsf) - bsf_l_rr(r,r); - else - simulate_bsf(tmp,r); -} - -int kill_rodent(int r) -{ - return KILLTHERAT && - have_rat_stall && - (live.state[r].status==INMEM || - live.state[r].status==CLEAN || - live.state[r].status==ISCONST || - live.state[r].dirtysize==4); -} - -uae_u32 get_const(int r) -{ - Dif (!isconst(r)) { - write_log("Register %d should be constant, but isn't\n",r); - abort(); - } - return live.state[r].val; -} - -void sync_m68k_pc(void) -{ - if (m68k_pc_offset) { - add_l_ri(PC_P,m68k_pc_offset); - comp_pc_p+=m68k_pc_offset; - m68k_pc_offset=0; - } -} - -/******************************************************************** - * Scratch registers management * - ********************************************************************/ - -struct scratch_t { - uae_u32 regs[VREGS]; - fpu_register fregs[VFREGS]; -}; - -static scratch_t scratch; - -/******************************************************************** - * Support functions exposed to newcpu * - ********************************************************************/ - -static inline const char *str_on_off(bool b) -{ - return b ? "on" : "off"; -} - -void compiler_init(void) -{ - static bool initialized = false; - if (initialized) - return; - -#if JIT_DEBUG - // JIT debug mode ? - JITDebug = PrefsFindBool("jitdebug"); -#endif - write_log(" : enable runtime disassemblers : %s\n", JITDebug ? "yes" : "no"); - -#ifdef USE_JIT_FPU - // Use JIT compiler for FPU instructions ? - avoid_fpu = !PrefsFindBool("jitfpu"); -#else - // JIT FPU is always disabled - avoid_fpu = true; -#endif - write_log(" : compile FPU instructions : %s\n", !avoid_fpu ? "yes" : "no"); - - // Get size of the translation cache (in KB) - cache_size = PrefsFindInt32("jitcachesize"); - write_log(" : requested translation cache size : %d KB\n", cache_size); - - // Initialize target CPU (check for features, e.g. CMOV, rat stalls) - raw_init_cpu(); - setzflg_uses_bsf = target_check_bsf(); - write_log(" : target processor has CMOV instructions : %s\n", have_cmov ? "yes" : "no"); - write_log(" : target processor can suffer from partial register stalls : %s\n", have_rat_stall ? "yes" : "no"); - write_log(" : alignment for loops, jumps are %d, %d\n", align_loops, align_jumps); - - // Translation cache flush mechanism - lazy_flush = PrefsFindBool("jitlazyflush"); - write_log(" : lazy translation cache invalidation : %s\n", str_on_off(lazy_flush)); - flush_icache = lazy_flush ? flush_icache_lazy : flush_icache_hard; - - // Compiler features - write_log(" : register aliasing : %s\n", str_on_off(1)); - write_log(" : FP register aliasing : %s\n", str_on_off(USE_F_ALIAS)); - write_log(" : lazy constant offsetting : %s\n", str_on_off(USE_OFFSET)); -#if USE_INLINING - follow_const_jumps = PrefsFindBool("jitinline"); -#endif - write_log(" : translate through constant jumps : %s\n", str_on_off(follow_const_jumps)); - write_log(" : separate blockinfo allocation : %s\n", str_on_off(USE_SEPARATE_BIA)); - - // Build compiler tables - build_comp(); - - initialized = true; - -#if PROFILE_UNTRANSLATED_INSNS - write_log(" : gather statistics on untranslated insns count\n"); -#endif - -#if PROFILE_COMPILE_TIME - write_log(" : gather statistics on translation time\n"); - emul_start_time = clock(); -#endif -} - -void compiler_exit(void) -{ -#if PROFILE_COMPILE_TIME - emul_end_time = clock(); -#endif - - // Deallocate translation cache - if (compiled_code) { - vm_release(compiled_code, cache_size * 1024); - compiled_code = 0; - } - - // Deallocate popallspace - if (popallspace) { - vm_release(popallspace, POPALLSPACE_SIZE); - popallspace = 0; - } - -#if PROFILE_COMPILE_TIME - write_log("### Compile Block statistics\n"); - write_log("Number of calls to compile_block : %d\n", compile_count); - uae_u32 emul_time = emul_end_time - emul_start_time; - write_log("Total emulation time : %.1f sec\n", double(emul_time)/double(CLOCKS_PER_SEC)); - write_log("Total compilation time : %.1f sec (%.1f%%)\n", double(compile_time)/double(CLOCKS_PER_SEC), - 100.0*double(compile_time)/double(emul_time)); - write_log("\n"); -#endif - -#if PROFILE_UNTRANSLATED_INSNS - uae_u64 untranslated_count = 0; - for (int i = 0; i < 65536; i++) { - opcode_nums[i] = i; - untranslated_count += raw_cputbl_count[i]; - } - write_log("Sorting out untranslated instructions count...\n"); - qsort(opcode_nums, 65536, sizeof(uae_u16), untranslated_compfn); - write_log("\nRank Opc Count Name\n"); - for (int i = 0; i < untranslated_top_ten; i++) { - uae_u32 count = raw_cputbl_count[opcode_nums[i]]; - struct instr *dp; - struct mnemolookup *lookup; - if (!count) - break; - dp = table68k + opcode_nums[i]; - for (lookup = lookuptab; lookup->mnemo != dp->mnemo; lookup++) - ; - write_log("%03d: %04x %10lu %s\n", i, opcode_nums[i], count, lookup->name); - } -#endif - -#if RECORD_REGISTER_USAGE - int reg_count_ids[16]; - uint64 tot_reg_count = 0; - for (int i = 0; i < 16; i++) { - reg_count_ids[i] = i; - tot_reg_count += reg_count[i]; - } - qsort(reg_count_ids, 16, sizeof(int), reg_count_compare); - uint64 cum_reg_count = 0; - for (int i = 0; i < 16; i++) { - int r = reg_count_ids[i]; - cum_reg_count += reg_count[r]; - printf("%c%d : %16ld %2.1f%% [%2.1f]\n", r < 8 ? 'D' : 'A', r % 8, - reg_count[r], - 100.0*double(reg_count[r])/double(tot_reg_count), - 100.0*double(cum_reg_count)/double(tot_reg_count)); - } -#endif -} - -bool compiler_use_jit(void) -{ - // Check for the "jit" prefs item - if (!PrefsFindBool("jit")) - return false; - - // Don't use JIT if translation cache size is less then MIN_CACHE_SIZE KB - if (PrefsFindInt32("jitcachesize") < MIN_CACHE_SIZE) { - write_log(" : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE); - return false; - } - - // Enable JIT for 68020+ emulation only - if (CPUType < 2) { - write_log(" : JIT is not supported in 680%d0 emulation mode, disabling.\n", CPUType); - return false; - } - - return true; -} - -void init_comp(void) -{ - int i; - uae_s8* cb=can_byte; - uae_s8* cw=can_word; - uae_s8* au=always_used; - -#if RECORD_REGISTER_USAGE - for (i=0;i<16;i++) - reg_count_local[i] = 0; -#endif - - for (i=0;i= (uintptr)ROMBaseHost) && (addr < (uintptr)ROMBaseHost + ROMSize)); -} - -static void flush_all(void) -{ - int i; - - log_flush(); - for (i=0;i0) - free_nreg(i); - - for (i=0;i0) - f_free_nreg(i); - - live.flags_in_flags=TRASH; /* Note: We assume we already rescued the - flags at the very start of the call_r - functions! */ -} - -/******************************************************************** - * Memory access and related functions, CREATE time * - ********************************************************************/ - -void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond) -{ - next_pc_p=not_taken; - taken_pc_p=taken; - branch_cc=cond; -} - - -static uae_u32 get_handler_address(uae_u32 addr) -{ - uae_u32 cl=cacheline(addr); - blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0); - return (uintptr)&(bi->direct_handler_to_use); -} - -static uae_u32 get_handler(uae_u32 addr) -{ - uae_u32 cl=cacheline(addr); - blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0); - return (uintptr)bi->direct_handler_to_use; -} - -static void load_handler(int reg, uae_u32 addr) -{ - mov_l_rm(reg,get_handler_address(addr)); -} - -/* This version assumes that it is writing *real* memory, and *will* fail - * if that assumption is wrong! No branches, no second chances, just - * straight go-for-it attitude */ - -static void writemem_real(int address, int source, int size, int tmp, int clobber) -{ - int f=tmp; - - if (clobber) - f=source; - - switch(size) { - case 1: mov_b_bRr(address,source,MEMBaseDiff); break; - case 2: mov_w_rr(f,source); bswap_16(f); mov_w_bRr(address,f,MEMBaseDiff); break; - case 4: mov_l_rr(f,source); bswap_32(f); mov_l_bRr(address,f,MEMBaseDiff); break; - } - forget_about(tmp); - forget_about(f); -} - -void writebyte(int address, int source, int tmp) -{ - writemem_real(address,source,1,tmp,0); -} - -static __inline__ void writeword_general(int address, int source, int tmp, - int clobber) -{ - writemem_real(address,source,2,tmp,clobber); -} - -void writeword_clobber(int address, int source, int tmp) -{ - writeword_general(address,source,tmp,1); -} - -void writeword(int address, int source, int tmp) -{ - writeword_general(address,source,tmp,0); -} - -static __inline__ void writelong_general(int address, int source, int tmp, - int clobber) -{ - writemem_real(address,source,4,tmp,clobber); -} - -void writelong_clobber(int address, int source, int tmp) -{ - writelong_general(address,source,tmp,1); -} - -void writelong(int address, int source, int tmp) -{ - writelong_general(address,source,tmp,0); -} - - - -/* This version assumes that it is reading *real* memory, and *will* fail - * if that assumption is wrong! No branches, no second chances, just - * straight go-for-it attitude */ - -static void readmem_real(int address, int dest, int size, int tmp) -{ - int f=tmp; - - if (size==4 && address!=dest) - f=dest; - - switch(size) { - case 1: mov_b_brR(dest,address,MEMBaseDiff); break; - case 2: mov_w_brR(dest,address,MEMBaseDiff); bswap_16(dest); break; - case 4: mov_l_brR(dest,address,MEMBaseDiff); bswap_32(dest); break; - } - forget_about(tmp); -} - -void readbyte(int address, int dest, int tmp) -{ - readmem_real(address,dest,1,tmp); -} - -void readword(int address, int dest, int tmp) -{ - readmem_real(address,dest,2,tmp); -} - -void readlong(int address, int dest, int tmp) -{ - readmem_real(address,dest,4,tmp); -} - -void get_n_addr(int address, int dest, int tmp) -{ - // a is the register containing the virtual address - // after the offset had been fetched - int a=tmp; - - // f is the register that will contain the offset - int f=tmp; - - // a == f == tmp if (address == dest) - if (address!=dest) { - a=address; - f=dest; - } - -#if REAL_ADDRESSING - mov_l_rr(dest, address); -#elif DIRECT_ADDRESSING - lea_l_brr(dest,address,MEMBaseDiff); -#endif - forget_about(tmp); -} - -void get_n_addr_jmp(int address, int dest, int tmp) -{ - /* For this, we need to get the same address as the rest of UAE - would --- otherwise we end up translating everything twice */ - get_n_addr(address,dest,tmp); -} - - -/* base is a register, but dp is an actual value. - target is a register, as is tmp */ -void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp) -{ - int reg = (dp >> 12) & 15; - int regd_shift=(dp >> 9) & 3; - - if (dp & 0x100) { - int ignorebase=(dp&0x80); - int ignorereg=(dp&0x40); - int addbase=0; - int outer=0; - - if ((dp & 0x30) == 0x20) addbase = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - if ((dp & 0x30) == 0x30) addbase = comp_get_ilong((m68k_pc_offset+=4)-4); - - if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - if ((dp & 0x3) == 0x3) outer = comp_get_ilong((m68k_pc_offset+=4)-4); - - if ((dp & 0x4) == 0) { /* add regd *before* the get_long */ - if (!ignorereg) { - if ((dp & 0x800) == 0) - sign_extend_16_rr(target,reg); - else - mov_l_rr(target,reg); - shll_l_ri(target,regd_shift); - } - else - mov_l_ri(target,0); - - /* target is now regd */ - if (!ignorebase) - add_l(target,base); - add_l_ri(target,addbase); - if (dp&0x03) readlong(target,target,tmp); - } else { /* do the getlong first, then add regd */ - if (!ignorebase) { - mov_l_rr(target,base); - add_l_ri(target,addbase); - } - else - mov_l_ri(target,addbase); - if (dp&0x03) readlong(target,target,tmp); - - if (!ignorereg) { - if ((dp & 0x800) == 0) - sign_extend_16_rr(tmp,reg); - else - mov_l_rr(tmp,reg); - shll_l_ri(tmp,regd_shift); - /* tmp is now regd */ - add_l(target,tmp); - } - } - add_l_ri(target,outer); - } - else { /* 68000 version */ - if ((dp & 0x800) == 0) { /* Sign extend */ - sign_extend_16_rr(target,reg); - lea_l_brr_indexed(target,base,target,1<= CODE_ALLOC_MAX_ATTEMPTS) - return NULL; - - return do_alloc_code(size, depth + 1); -#else - uint8 *code = (uint8 *)vm_acquire(size); - return code == VM_MAP_FAILED ? NULL : code; -#endif -} - -static inline uint8 *alloc_code(uint32 size) -{ - uint8 *ptr = do_alloc_code(size, 0); - /* allocated code must fit in 32-bit boundaries */ - assert((uintptr)ptr <= 0xffffffff); - return ptr; -} - -void alloc_cache(void) -{ - if (compiled_code) { - flush_icache_hard(6); - vm_release(compiled_code, cache_size * 1024); - compiled_code = 0; - } - - if (cache_size == 0) - return; - - while (!compiled_code && cache_size) { - if ((compiled_code = alloc_code(cache_size * 1024)) == NULL) { - compiled_code = 0; - cache_size /= 2; - } - } - vm_protect(compiled_code, cache_size * 1024, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE); - - if (compiled_code) { - write_log(" : actual translation cache size : %d KB at 0x%08X\n", cache_size, compiled_code); - max_compile_start = compiled_code + cache_size*1024 - BYTES_PER_INST; - current_compile_p = compiled_code; - current_cache_size = 0; - } -} - - - -extern void op_illg_1 (uae_u32 opcode) REGPARAM; - -static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2) -{ - uae_u32 k1 = 0; - uae_u32 k2 = 0; - -#if USE_CHECKSUM_INFO - checksum_info *csi = bi->csi; - Dif(!csi) abort(); - while (csi) { - uae_s32 len = csi->length; - uintptr tmp = (uintptr)csi->start_p; -#else - uae_s32 len = bi->len; - uintptr tmp = (uintptr)bi->min_pcp; -#endif - uae_u32*pos; - - len += (tmp & 3); - tmp &= ~((uintptr)3); - pos = (uae_u32 *)tmp; - - if (len >= 0 && len <= MAX_CHECKSUM_LEN) { - while (len > 0) { - k1 += *pos; - k2 ^= *pos; - pos++; - len -= 4; - } - } - -#if USE_CHECKSUM_INFO - csi = csi->next; - } -#endif - - *c1 = k1; - *c2 = k2; -} - -#if 0 -static void show_checksum(CSI_TYPE* csi) -{ - uae_u32 k1=0; - uae_u32 k2=0; - uae_s32 len=CSI_LENGTH(csi); - uae_u32 tmp=(uintptr)CSI_STARTcsi - uae_u32* pos; - - len+=(tmp&3); - tmp&=(~3); - pos=(uae_u32*)tmp; - - if (len<0 || len>MAX_CHECKSUM_LEN) { - return; - } - else { - while (len>0) { - write_log("%08x ",*pos); - pos++; - len-=4; - } - write_log(" bla\n"); - } -} -#endif - - -int check_for_cache_miss(void) -{ - blockinfo* bi=get_blockinfo_addr(regs.pc_p); - - if (bi) { - int cl=cacheline(regs.pc_p); - if (bi!=cache_tags[cl+1].bi) { - raise_in_cl_list(bi); - return 1; - } - } - return 0; -} - - -static void recompile_block(void) -{ - /* An existing block's countdown code has expired. We need to make - sure that execute_normal doesn't refuse to recompile due to a - perceived cache miss... */ - blockinfo* bi=get_blockinfo_addr(regs.pc_p); - - Dif (!bi) - abort(); - raise_in_cl_list(bi); - execute_normal(); - return; -} -static void cache_miss(void) -{ - blockinfo* bi=get_blockinfo_addr(regs.pc_p); - uae_u32 cl=cacheline(regs.pc_p); - blockinfo* bi2=get_blockinfo(cl); - - if (!bi) { - execute_normal(); /* Compile this block now */ - return; - } - Dif (!bi2 || bi==bi2) { - write_log("Unexplained cache miss %p %p\n",bi,bi2); - abort(); - } - raise_in_cl_list(bi); - return; -} - -static int called_check_checksum(blockinfo* bi); - -static inline int block_check_checksum(blockinfo* bi) -{ - uae_u32 c1,c2; - bool isgood; - - if (bi->status!=BI_NEED_CHECK) - return 1; /* This block is in a checked state */ - - checksum_count++; - - if (bi->c1 || bi->c2) - calc_checksum(bi,&c1,&c2); - else { - c1=c2=1; /* Make sure it doesn't match */ - } - - isgood=(c1==bi->c1 && c2==bi->c2); - - if (isgood) { - /* This block is still OK. So we reactivate. Of course, that - means we have to move it into the needs-to-be-flushed list */ - bi->handler_to_use=bi->handler; - set_dhtu(bi,bi->direct_handler); - bi->status=BI_CHECKING; - isgood=called_check_checksum(bi) != 0; - } - if (isgood) { - /* write_log("reactivate %p/%p (%x %x/%x %x)\n",bi,bi->pc_p, - c1,c2,bi->c1,bi->c2);*/ - remove_from_list(bi); - add_to_active(bi); - raise_in_cl_list(bi); - bi->status=BI_ACTIVE; - } - else { - /* This block actually changed. We need to invalidate it, - and set it up to be recompiled */ - /* write_log("discard %p/%p (%x %x/%x %x)\n",bi,bi->pc_p, - c1,c2,bi->c1,bi->c2); */ - invalidate_block(bi); - raise_in_cl_list(bi); - } - return isgood; -} - -static int called_check_checksum(blockinfo* bi) -{ - dependency* x=bi->deplist; - int isgood=1; - int i; - - for (i=0;i<2 && isgood;i++) { - if (bi->dep[i].jmp_off) { - isgood=block_check_checksum(bi->dep[i].target); - } - } - return isgood; -} - -static void check_checksum(void) -{ - blockinfo* bi=get_blockinfo_addr(regs.pc_p); - uae_u32 cl=cacheline(regs.pc_p); - blockinfo* bi2=get_blockinfo(cl); - - /* These are not the droids you are looking for... */ - if (!bi) { - /* Whoever is the primary target is in a dormant state, but - calling it was accidental, and we should just compile this - new block */ - execute_normal(); - return; - } - if (bi!=bi2) { - /* The block was hit accidentally, but it does exist. Cache miss */ - cache_miss(); - return; - } - - if (!block_check_checksum(bi)) - execute_normal(); -} - -static __inline__ void match_states(blockinfo* bi) -{ - int i; - smallstate* s=&(bi->env); - - if (bi->status==BI_NEED_CHECK) { - block_check_checksum(bi); - } - if (bi->status==BI_ACTIVE || - bi->status==BI_FINALIZING) { /* Deal with the *promises* the - block makes (about not using - certain vregs) */ - for (i=0;i<16;i++) { - if (s->virt[i]==L_UNNEEDED) { - // write_log("unneeded reg %d at %p\n",i,target); - COMPCALL(forget_about)(i); // FIXME - } - } - } - flush(1); - - /* And now deal with the *demands* the block makes */ - for (i=0;inat[i]; - if (v>=0) { - // printf("Loading reg %d into %d at %p\n",v,i,target); - readreg_specific(v,4,i); - // do_load_reg(i,v); - // setlock(i); - } - } - for (i=0;inat[i]; - if (v>=0) { - unlock2(i); - } - } -} - -static __inline__ void create_popalls(void) -{ - int i,r; - - if ((popallspace = alloc_code(POPALLSPACE_SIZE)) == NULL) { - write_log("FATAL: Could not allocate popallspace!\n"); - abort(); - } - vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE); - - int stack_space = STACK_OFFSET; - for (i=0;idirect_pen=(cpuop_func *)get_target(); - raw_mov_l_rm(0,(uintptr)&(bi->pc_p)); - raw_mov_l_mr((uintptr)®s.pc_p,0); - raw_jmp((uintptr)popall_execute_normal); - - align_target(align_jumps); - bi->direct_pcc=(cpuop_func *)get_target(); - raw_mov_l_rm(0,(uintptr)&(bi->pc_p)); - raw_mov_l_mr((uintptr)®s.pc_p,0); - raw_jmp((uintptr)popall_check_checksum); - current_compile_p=get_target(); - - bi->deplist=NULL; - for (i=0;i<2;i++) { - bi->dep[i].prev_p=NULL; - bi->dep[i].next=NULL; - } - bi->env=default_ss; - bi->status=BI_INVALID; - bi->havestate=0; - //bi->env=empty_ss; -} - -// OPCODE is in big endian format, use cft_map() beforehand, if needed. -static inline void reset_compop(int opcode) -{ - compfunctbl[opcode] = NULL; - nfcompfunctbl[opcode] = NULL; -} - -static int read_opcode(const char *p) -{ - int opcode = 0; - for (int i = 0; i < 4; i++) { - int op = p[i]; - switch (op) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - opcode = (opcode << 4) | (op - '0'); - break; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - opcode = (opcode << 4) | ((op - 'a') + 10); - break; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - opcode = (opcode << 4) | ((op - 'A') + 10); - break; - default: - return -1; - } - } - return opcode; -} - -static bool merge_blacklist() -{ - const char *blacklist = PrefsFindString("jitblacklist"); - if (blacklist) { - const char *p = blacklist; - for (;;) { - if (*p == 0) - return true; - - int opcode1 = read_opcode(p); - if (opcode1 < 0) - return false; - p += 4; - - int opcode2 = opcode1; - if (*p == '-') { - p++; - opcode2 = read_opcode(p); - if (opcode2 < 0) - return false; - p += 4; - } - - if (*p == 0 || *p == ',' || *p == ';') { - write_log(" : blacklist opcodes : %04x-%04x\n", opcode1, opcode2); - for (int opcode = opcode1; opcode <= opcode2; opcode++) - reset_compop(cft_map(opcode)); - - if (*p == ',' || *p++ == ';') - continue; - - return true; - } - - return false; - } - } - return true; -} - -void build_comp(void) -{ - int i; - int jumpcount=0; - unsigned long opcode; - struct comptbl* tbl=op_smalltbl_0_comp_ff; - struct comptbl* nftbl=op_smalltbl_0_comp_nf; - int count; - unsigned int cpu_level = 0; // 68000 (default) - if (CPUType == 4) - cpu_level = 4; // 68040 with FPU - else { - if (FPUType) - cpu_level = 3; // 68020 with FPU - else if (CPUType >= 2) - cpu_level = 2; // 68020 - else if (CPUType == 1) - cpu_level = 1; - } - struct cputbl *nfctbl = ( - cpu_level == 4 ? op_smalltbl_0_nf - : cpu_level == 3 ? op_smalltbl_1_nf - : cpu_level == 2 ? op_smalltbl_2_nf - : cpu_level == 1 ? op_smalltbl_3_nf - : op_smalltbl_4_nf); - - write_log (" : building compiler function tables\n"); - - for (opcode = 0; opcode < 65536; opcode++) { - reset_compop(opcode); - nfcpufunctbl[opcode] = op_illg_1; - prop[opcode].use_flags = 0x1f; - prop[opcode].set_flags = 0x1f; - prop[opcode].cflow = fl_trap; // ILLEGAL instructions do trap - } - - for (i = 0; tbl[i].opcode < 65536; i++) { - int cflow = table68k[tbl[i].opcode].cflow; - if (follow_const_jumps && (tbl[i].specific & 16)) - cflow = fl_const_jump; - else - cflow &= ~fl_const_jump; - prop[cft_map(tbl[i].opcode)].cflow = cflow; - - int uses_fpu = tbl[i].specific & 32; - if (uses_fpu && avoid_fpu) - compfunctbl[cft_map(tbl[i].opcode)] = NULL; - else - compfunctbl[cft_map(tbl[i].opcode)] = tbl[i].handler; - } - - for (i = 0; nftbl[i].opcode < 65536; i++) { - int uses_fpu = tbl[i].specific & 32; - if (uses_fpu && avoid_fpu) - nfcompfunctbl[cft_map(nftbl[i].opcode)] = NULL; - else - nfcompfunctbl[cft_map(nftbl[i].opcode)] = nftbl[i].handler; - - nfcpufunctbl[cft_map(nftbl[i].opcode)] = nfctbl[i].handler; - } - - for (i = 0; nfctbl[i].handler; i++) { - nfcpufunctbl[cft_map(nfctbl[i].opcode)] = nfctbl[i].handler; - } - - for (opcode = 0; opcode < 65536; opcode++) { - compop_func *f; - compop_func *nff; - cpuop_func *nfcf; - int isaddx,cflow; - - if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) - continue; - - if (table68k[opcode].handler != -1) { - f = compfunctbl[cft_map(table68k[opcode].handler)]; - nff = nfcompfunctbl[cft_map(table68k[opcode].handler)]; - nfcf = nfcpufunctbl[cft_map(table68k[opcode].handler)]; - cflow = prop[cft_map(table68k[opcode].handler)].cflow; - isaddx = prop[cft_map(table68k[opcode].handler)].is_addx; - prop[cft_map(opcode)].cflow = cflow; - prop[cft_map(opcode)].is_addx = isaddx; - compfunctbl[cft_map(opcode)] = f; - nfcompfunctbl[cft_map(opcode)] = nff; - Dif (nfcf == op_illg_1) - abort(); - nfcpufunctbl[cft_map(opcode)] = nfcf; - } - prop[cft_map(opcode)].set_flags = table68k[opcode].flagdead; - prop[cft_map(opcode)].use_flags = table68k[opcode].flaglive; - /* Unconditional jumps don't evaluate condition codes, so they - * don't actually use any flags themselves */ - if (prop[cft_map(opcode)].cflow & fl_const_jump) - prop[cft_map(opcode)].use_flags = 0; - } - for (i = 0; nfctbl[i].handler != NULL; i++) { - if (nfctbl[i].specific) - nfcpufunctbl[cft_map(tbl[i].opcode)] = nfctbl[i].handler; - } - - /* Merge in blacklist */ - if (!merge_blacklist()) - write_log(" : blacklist merge failure!\n"); - - count=0; - for (opcode = 0; opcode < 65536; opcode++) { - if (compfunctbl[cft_map(opcode)]) - count++; - } - write_log(" : supposedly %d compileable opcodes!\n",count); - - /* Initialise state */ - create_popalls(); - alloc_cache(); - reset_lists(); - - for (i=0;ipc_p)].handler=(cpuop_func *)popall_execute_normal; - cache_tags[cacheline(bi->pc_p)+1].bi=NULL; - dbi=bi; bi=bi->next; - free_blockinfo(dbi); - } - bi=dormant; - while(bi) { - cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func *)popall_execute_normal; - cache_tags[cacheline(bi->pc_p)+1].bi=NULL; - dbi=bi; bi=bi->next; - free_blockinfo(dbi); - } - - reset_lists(); - if (!compiled_code) - return; - current_compile_p=compiled_code; - SPCFLAGS_SET( SPCFLAG_JIT_EXEC_RETURN ); /* To get out of compiled code */ -} - - -/* "Soft flushing" --- instead of actually throwing everything away, - we simply mark everything as "needs to be checked". -*/ - -static inline void flush_icache_lazy(int n) -{ - blockinfo* bi; - blockinfo* bi2; - - soft_flush_count++; - if (!active) - return; - - bi=active; - while (bi) { - uae_u32 cl=cacheline(bi->pc_p); - if (bi->status==BI_INVALID || - bi->status==BI_NEED_RECOMP) { - if (bi==cache_tags[cl+1].bi) - cache_tags[cl].handler=(cpuop_func *)popall_execute_normal; - bi->handler_to_use=(cpuop_func *)popall_execute_normal; - set_dhtu(bi,bi->direct_pen); - bi->status=BI_INVALID; - } - else { - if (bi==cache_tags[cl+1].bi) - cache_tags[cl].handler=(cpuop_func *)popall_check_checksum; - bi->handler_to_use=(cpuop_func *)popall_check_checksum; - set_dhtu(bi,bi->direct_pcc); - bi->status=BI_NEED_CHECK; - } - bi2=bi; - bi=bi->next; - } - /* bi2 is now the last entry in the active list */ - bi2->next=dormant; - if (dormant) - dormant->prev_p=&(bi2->next); - - dormant=active; - active->prev_p=&dormant; - active=NULL; -} - -void flush_icache_range(uae_u8 *start_p, uae_u32 length) -{ - if (!active) - return; - -#if LAZY_FLUSH_ICACHE_RANGE - blockinfo *bi = active; - while (bi) { -#if USE_CHECKSUM_INFO - bool candidate = false; - for (checksum_info *csi = bi->csi; csi; csi = csi->next) { - if (((start_p - csi->start_p) < csi->length) || - ((csi->start_p - start_p) < length)) { - candidate = true; - break; - } - } -#else - // Assume system is consistent and would invalidate the right range - const bool candidate = (bi->pc_p - start_p) < length; -#endif - blockinfo *dbi = bi; - bi = bi->next; - if (candidate) { - uae_u32 cl = cacheline(dbi->pc_p); - if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) { - if (dbi == cache_tags[cl+1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; - dbi->handler_to_use = (cpuop_func *)popall_execute_normal; - set_dhtu(dbi, dbi->direct_pen); - dbi->status = BI_INVALID; - } - else { - if (dbi == cache_tags[cl+1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_check_checksum; - dbi->handler_to_use = (cpuop_func *)popall_check_checksum; - set_dhtu(dbi, dbi->direct_pcc); - dbi->status = BI_NEED_CHECK; - } - remove_from_list(dbi); - add_to_dormant(dbi); - } - } - return; -#endif - flush_icache(-1); -} - -static void catastrophe(void) -{ - abort(); -} - -int failure; - -#define TARGET_M68K 0 -#define TARGET_POWERPC 1 -#define TARGET_X86 2 -#define TARGET_X86_64 3 -#if defined(i386) || defined(__i386__) -#define TARGET_NATIVE TARGET_X86 -#endif -#if defined(powerpc) || defined(__powerpc__) -#define TARGET_NATIVE TARGET_POWERPC -#endif -#if defined(x86_64) || defined(__x86_64__) -#define TARGET_NATIVE TARGET_X86_64 -#endif - -#ifdef ENABLE_MON -static uae_u32 mon_read_byte_jit(uintptr addr) -{ - uae_u8 *m = (uae_u8 *)addr; - return (uintptr)(*m); -} - -static void mon_write_byte_jit(uintptr addr, uae_u32 b) -{ - uae_u8 *m = (uae_u8 *)addr; - *m = b; -} -#endif - -void disasm_block(int target, uint8 * start, size_t length) -{ - if (!JITDebug) - return; - -#if defined(JIT_DEBUG) && defined(ENABLE_MON) - char disasm_str[200]; - sprintf(disasm_str, "%s $%x $%x", - target == TARGET_M68K ? "d68" : - target == TARGET_X86 ? "d86" : - target == TARGET_X86_64 ? "d8664" : - target == TARGET_POWERPC ? "d" : "x", - start, start + length - 1); - - uae_u32 (*old_mon_read_byte)(uintptr) = mon_read_byte; - void (*old_mon_write_byte)(uintptr, uae_u32) = mon_write_byte; - - mon_read_byte = mon_read_byte_jit; - mon_write_byte = mon_write_byte_jit; - - char *arg[5] = {"mon", "-m", "-r", disasm_str, NULL}; - mon(4, arg); - - mon_read_byte = old_mon_read_byte; - mon_write_byte = old_mon_write_byte; -#endif -} - -static void disasm_native_block(uint8 *start, size_t length) -{ - disasm_block(TARGET_NATIVE, start, length); -} - -static void disasm_m68k_block(uint8 *start, size_t length) -{ - disasm_block(TARGET_M68K, start, length); -} - -#ifdef HAVE_GET_WORD_UNSWAPPED -# define DO_GET_OPCODE(a) (do_get_mem_word_unswapped((uae_u16 *)(a))) -#else -# define DO_GET_OPCODE(a) (do_get_mem_word((uae_u16 *)(a))) -#endif - -#if JIT_DEBUG -static uae_u8 *last_regs_pc_p = 0; -static uae_u8 *last_compiled_block_addr = 0; - -void compiler_dumpstate(void) -{ - if (!JITDebug) - return; - - write_log("### Host addresses\n"); - write_log("MEM_BASE : %x\n", MEMBaseDiff); - write_log("PC_P : %p\n", ®s.pc_p); - write_log("SPCFLAGS : %p\n", ®s.spcflags); - write_log("D0-D7 : %p-%p\n", ®s.regs[0], ®s.regs[7]); - write_log("A0-A7 : %p-%p\n", ®s.regs[8], ®s.regs[15]); - write_log("\n"); - - write_log("### M68k processor state\n"); - m68k_dumpstate(0); - write_log("\n"); - - write_log("### Block in Mac address space\n"); - write_log("M68K block : %p\n", - (void *)(uintptr)get_virtual_address(last_regs_pc_p)); - write_log("Native block : %p (%d bytes)\n", - (void *)(uintptr)get_virtual_address(last_compiled_block_addr), - get_blockinfo_addr(last_regs_pc_p)->direct_handler_size); - write_log("\n"); -} -#endif - -static void compile_block(cpu_history* pc_hist, int blocklen) -{ - if (letit && compiled_code) { -#if PROFILE_COMPILE_TIME - compile_count++; - clock_t start_time = clock(); -#endif -#if JIT_DEBUG - bool disasm_block = false; -#endif - - /* OK, here we need to 'compile' a block */ - int i; - int r; - int was_comp=0; - uae_u8 liveflags[MAXRUN+1]; -#if USE_CHECKSUM_INFO - bool trace_in_rom = isinrom((uintptr)pc_hist[0].location); - uintptr max_pcp=(uintptr)pc_hist[blocklen - 1].location; - uintptr min_pcp=max_pcp; -#else - uintptr max_pcp=(uintptr)pc_hist[0].location; - uintptr min_pcp=max_pcp; -#endif - uae_u32 cl=cacheline(pc_hist[0].location); - void* specflags=(void*)®s.spcflags; - blockinfo* bi=NULL; - blockinfo* bi2; - int extra_len=0; - - redo_current_block=0; - if (current_compile_p>=max_compile_start) - flush_icache_hard(7); - - alloc_blockinfos(); - - bi=get_blockinfo_addr_new(pc_hist[0].location,0); - bi2=get_blockinfo(cl); - - optlev=bi->optlevel; - if (bi->status!=BI_INVALID) { - Dif (bi!=bi2) { - /* I don't think it can happen anymore. Shouldn't, in - any case. So let's make sure... */ - write_log("WOOOWOO count=%d, ol=%d %p %p\n", - bi->count,bi->optlevel,bi->handler_to_use, - cache_tags[cl].handler); - abort(); - } - - Dif (bi->count!=-1 && bi->status!=BI_NEED_RECOMP) { - write_log("bi->count=%d, bi->status=%d\n",bi->count,bi->status); - /* What the heck? We are not supposed to be here! */ - abort(); - } - } - if (bi->count==-1) { - optlev++; - while (!optcount[optlev]) - optlev++; - bi->count=optcount[optlev]-1; - } - current_block_pc_p=(uintptr)pc_hist[0].location; - - remove_deps(bi); /* We are about to create new code */ - bi->optlevel=optlev; - bi->pc_p=(uae_u8*)pc_hist[0].location; -#if USE_CHECKSUM_INFO - free_checksum_info_chain(bi->csi); - bi->csi = NULL; -#endif - - liveflags[blocklen]=0x1f; /* All flags needed afterwards */ - i=blocklen; - while (i--) { - uae_u16* currpcp=pc_hist[i].location; - uae_u32 op=DO_GET_OPCODE(currpcp); - -#if USE_CHECKSUM_INFO - trace_in_rom = trace_in_rom && isinrom((uintptr)currpcp); - if (follow_const_jumps && is_const_jump(op)) { - checksum_info *csi = alloc_checksum_info(); - csi->start_p = (uae_u8 *)min_pcp; - csi->length = max_pcp - min_pcp + LONGEST_68K_INST; - csi->next = bi->csi; - bi->csi = csi; - max_pcp = (uintptr)currpcp; - } - min_pcp = (uintptr)currpcp; -#else - if ((uintptr)currpcpmax_pcp) - max_pcp=(uintptr)currpcp; -#endif - - liveflags[i]=((liveflags[i+1]& - (~prop[op].set_flags))| - prop[op].use_flags); - if (prop[op].is_addx && (liveflags[i+1]&FLAG_Z)==0) - liveflags[i]&= ~FLAG_Z; - } - -#if USE_CHECKSUM_INFO - checksum_info *csi = alloc_checksum_info(); - csi->start_p = (uae_u8 *)min_pcp; - csi->length = max_pcp - min_pcp + LONGEST_68K_INST; - csi->next = bi->csi; - bi->csi = csi; -#endif - - bi->needed_flags=liveflags[0]; - - align_target(align_loops); - was_comp=0; - - bi->direct_handler=(cpuop_func *)get_target(); - set_dhtu(bi,bi->direct_handler); - bi->status=BI_COMPILING; - current_block_start_target=(uintptr)get_target(); - - log_startblock(); - - if (bi->count>=0) { /* Need to generate countdown code */ - raw_mov_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); - raw_sub_l_mi((uintptr)&(bi->count),1); - raw_jl((uintptr)popall_recompile_block); - } - if (optlev==0) { /* No need to actually translate */ - /* Execute normally without keeping stats */ - raw_mov_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); - raw_jmp((uintptr)popall_exec_nostats); - } - else { - reg_alloc_run=0; - next_pc_p=0; - taken_pc_p=0; - branch_cc=0; - - comp_pc_p=(uae_u8*)pc_hist[0].location; - init_comp(); - was_comp=1; - -#ifdef USE_CPU_EMUL_SERVICES - raw_sub_l_mi((uintptr)&emulated_ticks,blocklen); - raw_jcc_b_oponly(NATIVE_CC_GT); - uae_s8 *branchadd=(uae_s8*)get_target(); - emit_byte(0); - raw_call((uintptr)cpu_do_check_ticks); - *branchadd=(uintptr)get_target()-((uintptr)branchadd+1); -#endif - -#if JIT_DEBUG - if (JITDebug) { - raw_mov_l_mi((uintptr)&last_regs_pc_p,(uintptr)pc_hist[0].location); - raw_mov_l_mi((uintptr)&last_compiled_block_addr,current_block_start_target); - } -#endif - - for (i=0;i1) { - failure=0; - if (!was_comp) { - comp_pc_p=(uae_u8*)pc_hist[i].location; - init_comp(); - } - was_comp=1; - - comptbl[opcode](opcode); - freescratch(); - if (!(liveflags[i+1] & FLAG_CZNV)) { - /* We can forget about flags */ - dont_care_flags(); - } -#if INDIVIDUAL_INST - flush(1); - nop(); - flush(1); - was_comp=0; -#endif - } - - if (failure) { - if (was_comp) { - flush(1); - was_comp=0; - } - raw_mov_l_ri(REG_PAR1,(uae_u32)opcode); -#if USE_NORMAL_CALLING_CONVENTION - raw_push_l_r(REG_PAR1); -#endif - raw_mov_l_mi((uintptr)®s.pc_p, - (uintptr)pc_hist[i].location); - raw_call((uintptr)cputbl[opcode]); -#if PROFILE_UNTRANSLATED_INSNS - // raw_cputbl_count[] is indexed with plain opcode (in m68k order) - raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1); -#endif -#if USE_NORMAL_CALLING_CONVENTION - raw_inc_sp(4); -#endif - - if (i < blocklen - 1) { - uae_s8* branchadd; - - raw_mov_l_rm(0,(uintptr)specflags); - raw_test_l_rr(0,0); - raw_jz_b_oponly(); - branchadd=(uae_s8 *)get_target(); - emit_byte(0); - raw_jmp((uintptr)popall_do_nothing); - *branchadd=(uintptr)get_target()-(uintptr)branchadd-1; - } - } - } -#if 1 /* This isn't completely kosher yet; It really needs to be - be integrated into a general inter-block-dependency scheme */ - if (next_pc_p && taken_pc_p && - was_comp && taken_pc_p==current_block_pc_p) { - blockinfo* bi1=get_blockinfo_addr_new((void*)next_pc_p,0); - blockinfo* bi2=get_blockinfo_addr_new((void*)taken_pc_p,0); - uae_u8 x=bi1->needed_flags; - - if (x==0xff || 1) { /* To be on the safe side */ - uae_u16* next=(uae_u16*)next_pc_p; - uae_u32 op=DO_GET_OPCODE(next); - - x=0x1f; - x&=(~prop[op].set_flags); - x|=prop[op].use_flags; - } - - x|=bi2->needed_flags; - if (!(x & FLAG_CZNV)) { - /* We can forget about flags */ - dont_care_flags(); - extra_len+=2; /* The next instruction now is part of this - block */ - } - - } -#endif - log_flush(); - - if (next_pc_p) { /* A branch was registered */ - uintptr t1=next_pc_p; - uintptr t2=taken_pc_p; - int cc=branch_cc; - - uae_u32* branchadd; - uae_u32* tba; - bigstate tmp; - blockinfo* tbi; - - if (taken_pc_penv))) { - mark_callers_recompile(bi); - } - - big_to_small_state(&live,&(bi->env)); -#endif - -#if USE_CHECKSUM_INFO - remove_from_list(bi); - if (trace_in_rom) { - // No need to checksum that block trace on cache invalidation - free_checksum_info_chain(bi->csi); - bi->csi = NULL; - add_to_dormant(bi); - } - else { - calc_checksum(bi,&(bi->c1),&(bi->c2)); - add_to_active(bi); - } -#else - if (next_pc_p+extra_len>=max_pcp && - next_pc_p+extra_lenlen=max_pcp-min_pcp; - bi->min_pcp=min_pcp; - - remove_from_list(bi); - if (isinrom(min_pcp) && isinrom(max_pcp)) { - add_to_dormant(bi); /* No need to checksum it on cache flush. - Please don't start changing ROMs in - flight! */ - } - else { - calc_checksum(bi,&(bi->c1),&(bi->c2)); - add_to_active(bi); - } -#endif - - current_cache_size += get_target() - (uae_u8 *)current_compile_p; - -#if JIT_DEBUG - if (JITDebug) - bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target; - - if (JITDebug && disasm_block) { - uaecptr block_addr = start_pc + ((char *)pc_hist[0].location - (char *)start_pc_p); - D(bug("M68K block @ 0x%08x (%d insns)\n", block_addr, blocklen)); - uae_u32 block_size = ((uae_u8 *)pc_hist[blocklen - 1].location - (uae_u8 *)pc_hist[0].location) + 1; - disasm_m68k_block((uae_u8 *)pc_hist[0].location, block_size); - D(bug("Compiled block @ 0x%08x\n", pc_hist[0].location)); - disasm_native_block((uae_u8 *)current_block_start_target, bi->direct_handler_size); - getchar(); - } -#endif - - log_dump(); - align_target(align_jumps); - - /* This is the non-direct handler */ - bi->handler= - bi->handler_to_use=(cpuop_func *)get_target(); - raw_cmp_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); - raw_jnz((uintptr)popall_cache_miss); - comp_pc_p=(uae_u8*)pc_hist[0].location; - - bi->status=BI_FINALIZING; - init_comp(); - match_states(bi); - flush(1); - - raw_jmp((uintptr)bi->direct_handler); - - current_compile_p=get_target(); - raise_in_cl_list(bi); - - /* We will flush soon, anyway, so let's do it now */ - if (current_compile_p>=max_compile_start) - flush_icache_hard(7); - - bi->status=BI_ACTIVE; - if (redo_current_block) - block_need_recompile(bi); - -#if PROFILE_COMPILE_TIME - compile_time += (clock() - start_time); -#endif - } - - /* Account for compilation time */ - cpu_do_check_ticks(); -} - -void do_nothing(void) -{ - /* What did you expect this to do? */ -} - -void exec_nostats(void) -{ - for (;;) { - uae_u32 opcode = GET_OPCODE; -#if FLIGHT_RECORDER - m68k_record_step(m68k_getpc()); -#endif - (*cpufunctbl[opcode])(opcode); - cpu_check_ticks(); - if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL)) { - return; /* We will deal with the spcflags in the caller */ - } - } -} - -void execute_normal(void) -{ - if (!check_for_cache_miss()) { - cpu_history pc_hist[MAXRUN]; - int blocklen = 0; -#if REAL_ADDRESSING || DIRECT_ADDRESSING - start_pc_p = regs.pc_p; - start_pc = get_virtual_address(regs.pc_p); -#else - start_pc_p = regs.pc_oldp; - start_pc = regs.pc; -#endif - for (;;) { /* Take note: This is the do-it-normal loop */ - pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p; - uae_u32 opcode = GET_OPCODE; -#if FLIGHT_RECORDER - m68k_record_step(m68k_getpc()); -#endif - (*cpufunctbl[opcode])(opcode); - cpu_check_ticks(); - if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL) || blocklen>=MAXRUN) { - compile_block(pc_hist, blocklen); - return; /* We will deal with the spcflags in the caller */ - } - /* No need to check regs.spcflags, because if they were set, - we'd have ended up inside that "if" */ - } - } -} - -typedef void (*compiled_handler)(void); - -static void m68k_do_compile_execute(void) -{ - for (;;) { - ((compiled_handler)(pushall_call_handler))(); - /* Whenever we return from that, we should check spcflags */ - if (SPCFLAGS_TEST(SPCFLAG_ALL)) { - if (m68k_do_specialties ()) - return; - } - } -} - -void m68k_compile_execute (void) -{ - for (;;) { - if (quit_program) - break; - m68k_do_compile_execute(); - } -} diff --git a/BasiliskII/src/uae_cpu/compiler/flags_x86.h b/BasiliskII/src/uae_cpu/compiler/flags_x86.h deleted file mode 100644 index 4247f10a..00000000 --- a/BasiliskII/src/uae_cpu/compiler/flags_x86.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * compiler/flags_x86.h - Native flags definitions for IA-32 - * - * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer - * - * Adaptation for Basilisk II and improvements, copyright 2000-2005 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef NATIVE_FLAGS_X86_H -#define NATIVE_FLAGS_X86_H - -/* Native integer code conditions */ -enum { - NATIVE_CC_HI = 7, - NATIVE_CC_LS = 6, - NATIVE_CC_CC = 3, - NATIVE_CC_CS = 2, - NATIVE_CC_NE = 5, - NATIVE_CC_EQ = 4, - NATIVE_CC_VC = 11, - NATIVE_CC_VS = 10, - NATIVE_CC_PL = 9, - NATIVE_CC_MI = 8, - NATIVE_CC_GE = 13, - NATIVE_CC_LT = 12, - NATIVE_CC_GT = 15, - NATIVE_CC_LE = 14 -}; - -#endif /* NATIVE_FLAGS_X86_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c deleted file mode 100644 index 2e16972d..00000000 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ /dev/null @@ -1,3072 +0,0 @@ -/* - * compiler/gencomp.c - MC680x0 compilation generator - * - * Based on work Copyright 1995, 1996 Bernd Schmidt - * Changes for UAE-JIT Copyright 2000 Bernd Meyer - * - * Adaptation for Basilisk II and improvements, copyright 2000-2005 - * Gwenole Beauchesne - * - * Basilisk II (C) 1997-2005 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include "sysdeps.h" -#include "../readcpu.h" - -#define BOOL_TYPE "int" -#define failure global_failure=1 -#define FAILURE global_failure=1 -#define isjump global_isjump=1 -#define is_const_jump global_iscjump=1; -#define isaddx global_isaddx=1 -#define uses_cmov global_cmov=1 -#define mayfail global_mayfail=1 -#define uses_fpu global_fpu=1 - -int hack_opcode; - -static int global_failure; -static int global_isjump; -static int global_iscjump; -static int global_isaddx; -static int global_cmov; -static int long_opcode; -static int global_mayfail; -static int global_fpu; - -static char endstr[1000]; -static char lines[100000]; -static int comp_index=0; - -static int cond_codes_x86[]={-1,-1,7,6,3,2,5,4,-1,-1,9,8,13,12,15,14}; - -static void comprintf(const char* format, ...) -{ - va_list args; - - va_start(args,format); - comp_index+=vsprintf(lines+comp_index,format,args); -} - -static void com_discard(void) -{ - comp_index=0; -} - -static void com_flush(void) -{ - int i; - for (i=0;i 0); - n_braces--; - comprintf ("}"); -} - -static void -finish_braces (void) -{ - while (n_braces > 0) - close_brace (); -} - -static void -pop_braces (int to) -{ - while (n_braces > to) - close_brace (); -} - -static int -bit_size (int size) -{ - switch (size) - { - case sz_byte: - return 8; - case sz_word: - return 16; - case sz_long: - return 32; - default: - abort (); - } - return 0; -} - -static const char * -bit_mask (int size) -{ - switch (size) - { - case sz_byte: - return "0xff"; - case sz_word: - return "0xffff"; - case sz_long: - return "0xffffffff"; - default: - abort (); - } - return 0; -} - -static __inline__ void gen_update_next_handler(void) -{ - return; /* Can anything clever be done here? */ -} - -static void gen_writebyte(char* address, char* source) -{ - comprintf("\twritebyte(%s,%s,scratchie);\n",address,source); -} - -static void gen_writeword(char* address, char* source) -{ - comprintf("\twriteword(%s,%s,scratchie);\n",address,source); -} - -static void gen_writelong(char* address, char* source) -{ - comprintf("\twritelong(%s,%s,scratchie);\n",address,source); -} - -static void gen_readbyte(char* address, char* dest) -{ - comprintf("\treadbyte(%s,%s,scratchie);\n",address,dest); -} - -static void gen_readword(char* address, char* dest) -{ - comprintf("\treadword(%s,%s,scratchie);\n",address,dest); -} - -static void gen_readlong(char* address, char* dest) -{ - comprintf("\treadlong(%s,%s,scratchie);\n",address,dest); -} - - - -static const char * -gen_nextilong (void) -{ - static char buffer[80]; - - sprintf (buffer, "comp_get_ilong((m68k_pc_offset+=4)-4)"); - insn_n_cycles += 4; - - long_opcode=1; - return buffer; -} - -static const char * -gen_nextiword (void) -{ - static char buffer[80]; - - sprintf (buffer, "comp_get_iword((m68k_pc_offset+=2)-2)"); - insn_n_cycles+=2; - - long_opcode=1; - return buffer; -} - -static const char * -gen_nextibyte (void) -{ - static char buffer[80]; - - sprintf (buffer, "comp_get_ibyte((m68k_pc_offset+=2)-2)"); - insn_n_cycles += 2; - - long_opcode=1; - return buffer; -} - -static void -swap_opcode (void) -{ - comprintf("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - comprintf("\topcode = do_byteswap_16(opcode);\n"); - comprintf("#endif\n"); -} - -static void -sync_m68k_pc (void) -{ - comprintf("\t if (m68k_pc_offset>100) sync_m68k_pc();\n"); -} - - -/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, - * the calling routine handles Apdi and Aipi modes. - * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ -static void -genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) -{ - start_brace (); - switch (mode) - { - case Dreg: /* Do we need to check dodgy here? */ - if (movem) - abort (); - if (getv == 1 || getv==2) { - /* We generate the variable even for getv==2, so we can use - it as a destination for MOVE */ - comprintf ("\tint %s=%s;\n",name,reg); - } - return; - - case Areg: - if (movem) - abort (); - if (getv == 1 || getv==2) { - /* see above */ - comprintf ("\tint %s=dodgy?scratchie++:%s+8;\n",name,reg); - if (getv==1) { - comprintf ("\tif (dodgy) \n"); - comprintf ("\t\tmov_l_rr(%s,%s+8);\n",name, reg); - } - } - return; - - case Aind: - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf ("\tif (dodgy) \n"); - comprintf ("\t\tmov_l_rr(%sa,%s+8);\n",name, reg); - break; - case Aipi: - comprintf ("\tint %sa=scratchie++;\n",name,reg); - comprintf ("\tmov_l_rr(%sa,%s+8);\n",name, reg); - break; - case Apdi: - switch (size) - { - case sz_byte: - if (movem) { - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf ("\tif (dodgy) \n"); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - } - else { - start_brace(); - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf("\tlea_l_brr(%s+8,%s+8,(uae_s32)-areg_byteinc[%s]);\n",reg,reg,reg); - comprintf ("\tif (dodgy) \n"); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - } - break; - case sz_word: - if (movem) { - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf ("\tif (dodgy) \n"); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - } - else { - start_brace(); - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf("\tlea_l_brr(%s+8,%s+8,-2);\n",reg,reg); - comprintf ("\tif (dodgy) \n"); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - } - break; - case sz_long: - if (movem) { - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf ("\tif (dodgy) \n"); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - } - else { - start_brace(); - comprintf ("\tint %sa=dodgy?scratchie++:%s+8;\n",name,reg); - comprintf("\tlea_l_brr(%s+8,%s+8,-4);\n",reg,reg); - comprintf ("\tif (dodgy) \n"); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - } - break; - default: - abort (); - } - break; - case Ad16: - comprintf("\tint %sa=scratchie++;\n",name); - comprintf("\tmov_l_rr(%sa,8+%s);\n",name,reg); - comprintf("\tlea_l_brr(%sa,%sa,(uae_s32)(uae_s16)%s);\n",name,name,gen_nextiword()); - break; - case Ad8r: - comprintf("\tint %sa=scratchie++;\n",name); - comprintf("\tcalc_disp_ea_020(%s+8,%s,%sa,scratchie);\n", - reg,gen_nextiword(),name); - break; - - case PC16: - comprintf("\tint %sa=scratchie++;\n",name); - comprintf("\tuae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); - comprintf ("\tuae_s32 PC16off = (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); - comprintf("\tmov_l_ri(%sa,address+PC16off);\n",name); - break; - - case PC8r: - comprintf("\tint pctmp=scratchie++;\n"); - comprintf("\tint %sa=scratchie++;\n",name); - comprintf("\tuae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); - start_brace(); - comprintf("\tmov_l_ri(pctmp,address);\n"); - - comprintf("\tcalc_disp_ea_020(pctmp,%s,%sa,scratchie);\n", - gen_nextiword(),name); - break; - case absw: - comprintf ("\tint %sa = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%sa,(uae_s32)(uae_s16)%s);\n", name, gen_nextiword ()); - break; - case absl: - comprintf ("\tint %sa = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%sa,%s); /* absl */\n", name, gen_nextilong ()); - break; - case imm: - if (getv != 1) - abort (); - switch (size) - { - case sz_byte: - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,(uae_s32)(uae_s8)%s);\n", name, gen_nextibyte ()); - break; - case sz_word: - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,(uae_s32)(uae_s16)%s);\n", name, gen_nextiword ()); - break; - case sz_long: - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,%s);\n", name, gen_nextilong ()); - break; - default: - abort (); - } - return; - case imm0: - if (getv != 1) - abort (); - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,(uae_s32)(uae_s8)%s);\n", name, gen_nextibyte ()); - return; - case imm1: - if (getv != 1) - abort (); - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,(uae_s32)(uae_s16)%s);\n", name, gen_nextiword ()); - return; - case imm2: - if (getv != 1) - abort (); - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,%s);\n", name, gen_nextilong ()); - return; - case immi: - if (getv != 1) - abort (); - comprintf ("\tint %s = scratchie++;\n",name); - comprintf ("\tmov_l_ri(%s,%s);\n", name, reg); - return; - default: - abort (); - } - - /* We get here for all non-reg non-immediate addressing modes to - * actually fetch the value. */ - if (getv == 1) - { - char astring[80]; - sprintf(astring,"%sa",name); - switch (size) - { - case sz_byte: - insn_n_cycles += 2; - break; - case sz_word: - insn_n_cycles += 2; - break; - case sz_long: - insn_n_cycles += 4; - break; - default: - abort (); - } - start_brace (); - comprintf("\tint %s=scratchie++;\n",name); - switch (size) - { - case sz_byte: - gen_readbyte(astring,name); - break; - case sz_word: - gen_readword(astring,name); - break; - case sz_long: - gen_readlong(astring,name); - break; - default: - abort (); - } - } - - /* We now might have to fix up the register for pre-dec or post-inc - * addressing modes. */ - if (!movem) { - switch (mode) - { - case Aipi: - switch (size) - { - case sz_byte: - comprintf("\tlea_l_brr(%s+8,%s+8,areg_byteinc[%s]);\n",reg,reg,reg); - break; - case sz_word: - comprintf("\tlea_l_brr(%s+8,%s+8,2);\n",reg,reg,reg); - break; - case sz_long: - comprintf("\tlea_l_brr(%s+8,%s+8,4);\n",reg,reg); - break; - default: - abort (); - } - break; - case Apdi: - break; - default: - break; - } - } -} - -static void -genastore (char *from, amodes mode, char *reg, wordsizes size, char *to) -{ - switch (mode) - { - case Dreg: - switch (size) - { - case sz_byte: - comprintf("\tif(%s!=%s)\n",reg,from); - comprintf ("\t\tmov_b_rr(%s,%s);\n", reg, from); - break; - case sz_word: - comprintf("\tif(%s!=%s)\n",reg,from); - comprintf ("\t\tmov_w_rr(%s,%s);\n", reg, from); - break; - case sz_long: - comprintf("\tif(%s!=%s)\n",reg,from); - comprintf ("\t\tmov_l_rr(%s,%s);\n", reg, from); - break; - default: - abort (); - } - break; - case Areg: - switch (size) - { - case sz_word: - comprintf("\tif(%s+8!=%s)\n",reg,from); - comprintf ("\t\tmov_w_rr(%s+8,%s);\n", reg, from); - break; - case sz_long: - comprintf("\tif(%s+8!=%s)\n",reg,from); - comprintf ("\t\tmov_l_rr(%s+8,%s);\n", reg, from); - break; - default: - abort (); - } - break; - - case Apdi: - case absw: - case PC16: - case PC8r: - case Ad16: - case Ad8r: - case Aipi: - case Aind: - case absl: - { - char astring[80]; - sprintf(astring,"%sa",to); - - switch (size) - { - case sz_byte: - insn_n_cycles += 2; - gen_writebyte(astring,from); - break; - case sz_word: - insn_n_cycles += 2; - gen_writeword(astring,from); - break; - case sz_long: - insn_n_cycles += 4; - gen_writelong(astring,from); - break; - default: - abort (); - } - } - break; - case imm: - case imm0: - case imm1: - case imm2: - case immi: - abort (); - break; - default: - abort (); - } -} - -static void genmov16(uae_u32 opcode, struct instr *curi) -{ - comprintf("\tint src=scratchie++;\n"); - comprintf("\tint dst=scratchie++;\n"); - - if ((opcode & 0xfff8) == 0xf620) { - /* MOVE16 (Ax)+,(Ay)+ */ - comprintf("\tuae_u16 dstreg=((%s)>>12)&0x07;\n", gen_nextiword()); - comprintf("\tmov_l_rr(src,8+srcreg);\n"); - comprintf("\tmov_l_rr(dst,8+dstreg);\n"); - } - else { - /* Other variants */ - genamode (curi->smode, "srcreg", curi->size, "src", 0, 2); - genamode (curi->dmode, "dstreg", curi->size, "dst", 0, 2); - comprintf("\tmov_l_rr(src,srca);\n"); - comprintf("\tmov_l_rr(dst,dsta);\n"); - } - - /* Align on 16-byte boundaries */ - comprintf("\tand_l_ri(src,~15);\n"); - comprintf("\tand_l_ri(dst,~15);\n"); - - if ((opcode & 0xfff8) == 0xf620) { - comprintf("\tif (srcreg != dstreg)\n"); - comprintf("\tadd_l_ri(srcreg+8,16);\n"); - comprintf("\tadd_l_ri(dstreg+8,16);\n"); - } - else if ((opcode & 0xfff8) == 0xf600) - comprintf("\tadd_l_ri(srcreg+8,16);\n"); - else if ((opcode & 0xfff8) == 0xf608) - comprintf("\tadd_l_ri(dstreg+8,16);\n"); - - comprintf("\tint tmp=scratchie;\n"); - comprintf("\tscratchie+=4;\n"); - - comprintf("\tget_n_addr(src,src,scratchie);\n" - "\tget_n_addr(dst,dst,scratchie);\n" - "\tmov_l_rR(tmp+0,src,0);\n" - "\tmov_l_rR(tmp+1,src,4);\n" - "\tmov_l_rR(tmp+2,src,8);\n" - "\tmov_l_rR(tmp+3,src,12);\n" - "\tmov_l_Rr(dst,tmp+0,0);\n" - "\tforget_about(tmp+0);\n" - "\tmov_l_Rr(dst,tmp+1,4);\n" - "\tforget_about(tmp+1);\n" - "\tmov_l_Rr(dst,tmp+2,8);\n" - "\tforget_about(tmp+2);\n" - "\tmov_l_Rr(dst,tmp+3,12);\n"); -} - -static void -genmovemel (uae_u16 opcode) -{ - comprintf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); - comprintf ("\tint native=scratchie++;\n"); - comprintf ("\tint i;\n"); - comprintf ("\tsigned char offset=0;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); - comprintf("\tget_n_addr(srca,native,scratchie);\n"); - - comprintf("\tfor (i=0;i<16;i++) {\n" - "\t\tif ((mask>>i)&1) {\n"); - switch(table68k[opcode].size) { - case sz_long: - comprintf("\t\t\tmov_l_rR(i,native,offset);\n" - "\t\t\tbswap_32(i);\n" - "\t\t\toffset+=4;\n"); - break; - case sz_word: - comprintf("\t\t\tmov_w_rR(i,native,offset);\n" - "\t\t\tbswap_16(i);\n" - "\t\t\tsign_extend_16_rr(i,i);\n" - "\t\t\toffset+=2;\n"); - break; - default: abort(); - } - comprintf("\t\t}\n" - "\t}"); - if (table68k[opcode].dmode == Aipi) { - comprintf("\t\t\tlea_l_brr(8+dstreg,srca,offset);\n"); - } -} - - -static void -genmovemle (uae_u16 opcode) -{ - comprintf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); - comprintf ("\tint native=scratchie++;\n"); - comprintf ("\tint i;\n"); - comprintf ("\tint tmp=scratchie++;\n"); - comprintf ("\tsigned char offset=0;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); - - comprintf("\tget_n_addr(srca,native,scratchie);\n"); - - if (table68k[opcode].dmode!=Apdi) { - comprintf("\tfor (i=0;i<16;i++) {\n" - "\t\tif ((mask>>i)&1) {\n"); - switch(table68k[opcode].size) { - case sz_long: - comprintf("\t\t\tmov_l_rr(tmp,i);\n" - "\t\t\tbswap_32(tmp);\n" - "\t\t\tmov_l_Rr(native,tmp,offset);\n" - "\t\t\toffset+=4;\n"); - break; - case sz_word: - comprintf("\t\t\tmov_l_rr(tmp,i);\n" - "\t\t\tbswap_16(tmp);\n" - "\t\t\tmov_w_Rr(native,tmp,offset);\n" - "\t\t\toffset+=2;\n"); - break; - default: abort(); - } - } - else { /* Pre-decrement */ - comprintf("\tfor (i=0;i<16;i++) {\n" - "\t\tif ((mask>>i)&1) {\n"); - switch(table68k[opcode].size) { - case sz_long: - comprintf("\t\t\toffset-=4;\n" - "\t\t\tmov_l_rr(tmp,15-i);\n" - "\t\t\tbswap_32(tmp);\n" - "\t\t\tmov_l_Rr(native,tmp,offset);\n" - ); - break; - case sz_word: - comprintf("\t\t\toffset-=2;\n" - "\t\t\tmov_l_rr(tmp,15-i);\n" - "\t\t\tbswap_16(tmp);\n" - "\t\t\tmov_w_Rr(native,tmp,offset);\n" - ); - break; - default: abort(); - } - } - - - comprintf("\t\t}\n" - "\t}"); - if (table68k[opcode].dmode == Apdi) { - comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n"); - } -} - - -static void -duplicate_carry (void) -{ - comprintf ("\tif (needed_flags&FLAG_X) duplicate_carry();\n"); -} - -typedef enum -{ - flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, - flag_addx, flag_subx, flag_zn, flag_av, flag_sv, flag_and, flag_or, - flag_eor, flag_mov -} -flagtypes; - - -static void -genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst) -{ - if (noflags) { - switch(type) { - case flag_cmp: - comprintf("\tdont_care_flags();\n"); - comprintf("/* Weird --- CMP with noflags ;-) */\n"); - return; - case flag_add: - case flag_sub: - comprintf("\tdont_care_flags();\n"); - { - char* op; - switch(type) { - case flag_add: op="add"; break; - case flag_sub: op="sub"; break; - default: abort(); - } - switch (size) - { - case sz_byte: - comprintf("\t%s_b(%s,%s);\n",op,dst,src); - break; - case sz_word: - comprintf("\t%s_w(%s,%s);\n",op,dst,src); - break; - case sz_long: - comprintf("\t%s_l(%s,%s);\n",op,dst,src); - break; - } - return; - } - break; - - case flag_and: - comprintf("\tdont_care_flags();\n"); - switch (size) - { - case sz_byte: - comprintf("if (kill_rodent(dst)) {\n"); - comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src); - comprintf("\tor_l_ri(scratchie,0xffffff00);\n"); - comprintf("\tand_l(%s,scratchie);\n",dst); - comprintf("\tforget_about(scratchie);\n"); - comprintf("\t} else \n" - "\tand_b(%s,%s);\n",dst,src); - break; - case sz_word: - comprintf("if (kill_rodent(dst)) {\n"); - comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src); - comprintf("\tor_l_ri(scratchie,0xffff0000);\n"); - comprintf("\tand_l(%s,scratchie);\n",dst); - comprintf("\tforget_about(scratchie);\n"); - comprintf("\t} else \n" - "\tand_w(%s,%s);\n",dst,src); - break; - case sz_long: - comprintf("\tand_l(%s,%s);\n",dst,src); - break; - } - return; - - case flag_mov: - comprintf("\tdont_care_flags();\n"); - switch (size) - { - case sz_byte: - comprintf("if (kill_rodent(dst)) {\n"); - comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src); - comprintf("\tand_l_ri(%s,0xffffff00);\n",dst); - comprintf("\tor_l(%s,scratchie);\n",dst); - comprintf("\tforget_about(scratchie);\n"); - comprintf("\t} else \n" - "\tmov_b_rr(%s,%s);\n",dst,src); - break; - case sz_word: - comprintf("if (kill_rodent(dst)) {\n"); - comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src); - comprintf("\tand_l_ri(%s,0xffff0000);\n",dst); - comprintf("\tor_l(%s,scratchie);\n",dst); - comprintf("\tforget_about(scratchie);\n"); - comprintf("\t} else \n" - "\tmov_w_rr(%s,%s);\n",dst,src); - break; - case sz_long: - comprintf("\tmov_l_rr(%s,%s);\n",dst,src); - break; - } - return; - - case flag_or: - case flag_eor: - comprintf("\tdont_care_flags();\n"); - start_brace(); - { - char* op; - switch(type) { - case flag_or: op="or"; break; - case flag_eor: op="xor"; break; - default: abort(); - } - switch (size) - { - case sz_byte: - comprintf("if (kill_rodent(dst)) {\n"); - comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src); - comprintf("\t%s_l(%s,scratchie);\n",op,dst); - comprintf("\tforget_about(scratchie);\n"); - comprintf("\t} else \n" - "\t%s_b(%s,%s);\n",op,dst,src); - break; - case sz_word: - comprintf("if (kill_rodent(dst)) {\n"); - comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src); - comprintf("\t%s_l(%s,scratchie);\n",op,dst); - comprintf("\tforget_about(scratchie);\n"); - comprintf("\t} else \n" - "\t%s_w(%s,%s);\n",op,dst,src); - break; - case sz_long: - comprintf("\t%s_l(%s,%s);\n",op,dst,src); - break; - } - close_brace(); - return; - } - - - case flag_addx: - case flag_subx: - comprintf("\tdont_care_flags();\n"); - { - char* op; - switch(type) { - case flag_addx: op="adc"; break; - case flag_subx: op="sbb"; break; - default: abort(); - } - comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ - switch (size) - { - case sz_byte: - comprintf("\t%s_b(%s,%s);\n",op,dst,src); - break; - case sz_word: - comprintf("\t%s_w(%s,%s);\n",op,dst,src); - break; - case sz_long: - comprintf("\t%s_l(%s,%s);\n",op,dst,src); - break; - } - return; - } - break; - default: return; - } - } - - /* Need the flags, but possibly not all of them */ - switch (type) - { - case flag_logical_noclobber: - failure; - - case flag_and: - case flag_or: - case flag_eor: - comprintf("\tdont_care_flags();\n"); - start_brace(); - { - char* op; - switch(type) { - case flag_and: op="and"; break; - case flag_or: op="or"; break; - case flag_eor: op="xor"; break; - default: abort(); - } - switch (size) - { - case sz_byte: - comprintf("\tstart_needflags();\n" - "\t%s_b(%s,%s);\n",op,dst,src); - break; - case sz_word: - comprintf("\tstart_needflags();\n" - "\t%s_w(%s,%s);\n",op,dst,src); - break; - case sz_long: - comprintf("\tstart_needflags();\n" - "\t%s_l(%s,%s);\n",op,dst,src); - break; - } - comprintf("\tlive_flags();\n"); - comprintf("\tend_needflags();\n"); - close_brace(); - return; - } - - case flag_mov: - comprintf("\tdont_care_flags();\n"); - start_brace(); - { - switch (size) - { - case sz_byte: - comprintf("\tif (%s!=%s) {\n",src,dst); - comprintf("\tmov_b_ri(%s,0);\n" - "\tstart_needflags();\n",dst); - comprintf("\tor_b(%s,%s);\n",dst,src); - comprintf("\t} else {\n"); - comprintf("\tmov_b_rr(%s,%s);\n",dst,src); - comprintf("\ttest_b_rr(%s,%s);\n",dst,dst); - comprintf("\t}\n"); - break; - case sz_word: - comprintf("\tif (%s!=%s) {\n",src,dst); - comprintf("\tmov_w_ri(%s,0);\n" - "\tstart_needflags();\n",dst); - comprintf("\tor_w(%s,%s);\n",dst,src); - comprintf("\t} else {\n"); - comprintf("\tmov_w_rr(%s,%s);\n",dst,src); - comprintf("\ttest_w_rr(%s,%s);\n",dst,dst); - comprintf("\t}\n"); - break; - case sz_long: - comprintf("\tif (%s!=%s) {\n",src,dst); - comprintf("\tmov_l_ri(%s,0);\n" - "\tstart_needflags();\n",dst); - comprintf("\tor_l(%s,%s);\n",dst,src); - comprintf("\t} else {\n"); - comprintf("\tmov_l_rr(%s,%s);\n",dst,src); - comprintf("\ttest_l_rr(%s,%s);\n",dst,dst); - comprintf("\t}\n"); - break; - } - comprintf("\tlive_flags();\n"); - comprintf("\tend_needflags();\n"); - close_brace(); - return; - } - - case flag_logical: - comprintf("\tdont_care_flags();\n"); - start_brace(); - switch (size) - { - case sz_byte: - comprintf("\tstart_needflags();\n" - "\ttest_b_rr(%s,%s);\n",value,value); - break; - case sz_word: - comprintf("\tstart_needflags();\n" - "\ttest_w_rr(%s,%s);\n",value,value); - break; - case sz_long: - comprintf("\tstart_needflags();\n" - "\ttest_l_rr(%s,%s);\n",value,value); - break; - } - comprintf("\tlive_flags();\n"); - comprintf("\tend_needflags();\n"); - close_brace(); - return; - - - case flag_add: - case flag_sub: - case flag_cmp: - comprintf("\tdont_care_flags();\n"); - { - char* op; - switch(type) { - case flag_add: op="add"; break; - case flag_sub: op="sub"; break; - case flag_cmp: op="cmp"; break; - default: abort(); - } - switch (size) - { - case sz_byte: - comprintf("\tstart_needflags();\n" - "\t%s_b(%s,%s);\n",op,dst,src); - break; - case sz_word: - comprintf("\tstart_needflags();\n" - "\t%s_w(%s,%s);\n",op,dst,src); - break; - case sz_long: - comprintf("\tstart_needflags();\n" - "\t%s_l(%s,%s);\n",op,dst,src); - break; - } - comprintf("\tlive_flags();\n"); - comprintf("\tend_needflags();\n"); - if (type!=flag_cmp) { - duplicate_carry(); - } - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - - return; - } - - case flag_addx: - case flag_subx: - uses_cmov; - comprintf("\tdont_care_flags();\n"); - { - char* op; - switch(type) { - case flag_addx: op="adc"; break; - case flag_subx: op="sbb"; break; - default: abort(); - } - start_brace(); - comprintf("\tint zero=scratchie++;\n" - "\tint one=scratchie++;\n" - "\tif (needed_flags&FLAG_Z) {\n" - "\tmov_l_ri(zero,0);\n" - "\tmov_l_ri(one,-1);\n" - "\tmake_flags_live();\n" - "\tcmov_l_rr(zero,one,5);\n" - "\t}\n"); - comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ - switch (size) - { - case sz_byte: - comprintf("\tstart_needflags();\n" - "\t%s_b(%s,%s);\n",op,dst,src); - break; - case sz_word: - comprintf("\tstart_needflags();\n" - "\t%s_w(%s,%s);\n",op,dst,src); - break; - case sz_long: - comprintf("\tstart_needflags();\n" - "\t%s_l(%s,%s);\n",op,dst,src); - break; - } - comprintf("\tlive_flags();\n"); - comprintf("\tif (needed_flags&FLAG_Z) {\n" - "\tcmov_l_rr(zero,one,5);\n" - "\tset_zero(zero, one);\n" /* No longer need one */ - "\tlive_flags();\n" - "\t}\n"); - comprintf("\tend_needflags();\n"); - duplicate_carry(); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - return; - } - default: - failure; - break; - } -} - -static void -force_range_for_rox (const char *var, wordsizes size) -{ - /* Could do a modulo operation here... which one is faster? */ - switch (size) - { - case sz_long: - comprintf ("\tif (%s >= 33) %s -= 33;\n", var, var); - break; - case sz_word: - comprintf ("\tif (%s >= 34) %s -= 34;\n", var, var); - comprintf ("\tif (%s >= 17) %s -= 17;\n", var, var); - break; - case sz_byte: - comprintf ("\tif (%s >= 36) %s -= 36;\n", var, var); - comprintf ("\tif (%s >= 18) %s -= 18;\n", var, var); - comprintf ("\tif (%s >= 9) %s -= 9;\n", var, var); - break; - } -} - -static const char * -cmask (wordsizes size) -{ - switch (size) - { - case sz_byte: - return "0x80"; - case sz_word: - return "0x8000"; - case sz_long: - return "0x80000000"; - default: - abort (); - } -} - -static int -source_is_imm1_8 (struct instr *i) -{ - return i->stype == 3; -} - -static int /* returns zero for success, non-zero for failure */ -gen_opcode (unsigned long int opcode) -{ - struct instr *curi = table68k + opcode; - char* ssize=NULL; - - insn_n_cycles = 2; - global_failure=0; - long_opcode=0; - global_isjump=0; - global_iscjump=0; - global_isaddx=0; - global_cmov=0; - global_fpu=0; - global_mayfail=0; - hack_opcode=opcode; - endstr[0]=0; - - start_brace (); - comprintf("\tuae_u8 scratchie=S1;\n"); - switch (curi->plev) - { - case 0: /* not privileged */ - break; - case 1: /* unprivileged only on 68000 */ - if (cpu_level == 0) - break; - if (next_cpu_level < 0) - next_cpu_level = 0; - - /* fall through */ - case 2: /* priviledged */ - failure; /* Easy ones first */ - break; - case 3: /* privileged if size == word */ - if (curi->size == sz_byte) - break; - failure; - break; - } - switch (curi->size) { - case sz_byte: ssize="b"; break; - case sz_word: ssize="w"; break; - case sz_long: ssize="l"; break; - default: abort(); - } - - switch (curi->mnemo) - { - case i_OR: - case i_AND: - case i_EOR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - switch(curi->mnemo) { - case i_OR: genflags (flag_or, curi->size, "", "src", "dst"); break; - case i_AND: genflags (flag_and, curi->size, "", "src", "dst"); break; - case i_EOR: genflags (flag_eor, curi->size, "", "src", "dst"); break; - } - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - break; - - case i_ORSR: - case i_EORSR: - failure; - isjump; - break; - case i_ANDSR: - failure; - isjump; - break; - case i_SUB: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - genflags (flag_sub, curi->size, "", "src", "dst"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - break; - case i_SUBA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - start_brace(); - comprintf("\tint tmp=scratchie++;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break; - case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break; - case sz_long: comprintf("\ttmp=src;\n"); break; - default: abort(); - } - comprintf("\tsub_l(dst,tmp);\n"); - genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); - break; - case i_SUBX: - isaddx; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - genflags (flag_subx, curi->size, "", "src", "dst"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - break; - case i_SBCD: - failure; - /* I don't think so! */ - break; - case i_ADD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - genflags (flag_add, curi->size, "", "src", "dst"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - break; - case i_ADDA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - start_brace(); - comprintf("\tint tmp=scratchie++;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break; - case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break; - case sz_long: comprintf("\ttmp=src;\n"); break; - default: abort(); - } - comprintf("\tadd_l(dst,tmp);\n"); - genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); - break; - case i_ADDX: - isaddx; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - start_brace(); - genflags (flag_addx, curi->size, "", "src", "dst"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - break; - case i_ABCD: - failure; - /* No BCD maths for me.... */ - break; - case i_NEG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - start_brace (); - comprintf("\tint dst=scratchie++;\n"); - comprintf("\tmov_l_ri(dst,0);\n"); - genflags (flag_sub, curi->size, "", "src", "dst"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - break; - case i_NEGX: - isaddx; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - start_brace (); - comprintf("\tint dst=scratchie++;\n"); - comprintf("\tmov_l_ri(dst,0);\n"); - genflags (flag_subx, curi->size, "", "src", "dst"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - break; - - case i_NBCD: - failure; - /* Nope! */ - break; - case i_CLR: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); - start_brace(); - comprintf("\tint dst=scratchie++;\n"); - comprintf("\tmov_l_ri(dst,0);\n"); - genflags (flag_logical, curi->size, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - break; - case i_NOT: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - start_brace (); - comprintf("\tint dst=scratchie++;\n"); - comprintf("\tmov_l_ri(dst,0xffffffff);\n"); - genflags (flag_eor, curi->size, "", "src", "dst"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - break; - case i_TST: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genflags (flag_logical, curi->size, "src", "", ""); - break; - case i_BCHG: - case i_BCLR: - case i_BSET: - case i_BTST: -/* failure; /* NEW: from "Ipswitch Town" release */ - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - start_brace(); - comprintf("\tint s=scratchie++;\n" - "\tint tmp=scratchie++;\n" - "\tmov_l_rr(s,src);\n"); - if (curi->size == sz_byte) - comprintf("\tand_l_ri(s,7);\n"); - else - comprintf("\tand_l_ri(s,31);\n"); - - { - char* op; - int need_write=1; - - switch(curi->mnemo) { - case i_BCHG: op="btc"; break; - case i_BCLR: op="btr"; break; - case i_BSET: op="bts"; break; - case i_BTST: op="bt"; need_write=0; break; - default: abort(); - } - comprintf("\t%s_l_rr(dst,s);\n" /* Answer now in C */ - "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ - "\tmake_flags_live();\n" /* Get the flags back */ - "\tdont_care_flags();\n",op); - if (!noflags) { - comprintf("\tstart_needflags();\n" - "\tset_zero(s,tmp);\n" - "\tlive_flags();\n" - "\tend_needflags();\n"); - } - if (need_write) - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - } - break; - - case i_CMPM: - case i_CMP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - start_brace (); - genflags (flag_cmp, curi->size, "", "src", "dst"); - break; - case i_CMPA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - start_brace(); - comprintf("\tint tmps=scratchie++;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tsign_extend_8_rr(tmps,src);\n"); break; - case sz_word: comprintf("\tsign_extend_16_rr(tmps,src);\n"); break; - case sz_long: comprintf("tmps=src;\n"); break; - default: abort(); - } - genflags (flag_cmp, sz_long, "", "tmps", "dst"); - break; - /* The next two are coded a little unconventional, but they are doing - * weird things... */ - case i_MVPRM: - isjump; - failure; - break; - case i_MVPMR: - isjump; - failure; - break; - case i_MOVE: - switch(curi->dmode) { - case Dreg: - case Areg: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genflags (flag_mov, curi->size, "", "src", "dst"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); - break; - default: /* It goes to memory, not a register */ - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); - break; - } - break; - case i_MOVEA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - - start_brace(); - comprintf("\tint tmps=scratchie++;\n"); - switch(curi->size) { - case sz_word: comprintf("\tsign_extend_16_rr(dst,src);\n"); break; - case sz_long: comprintf("\tmov_l_rr(dst,src);\n"); break; - default: abort(); - } - genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); - break; - - case i_MVSR2: - isjump; - failure; - break; - case i_MV2SR: - isjump; - failure; - break; - case i_SWAP: - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); - comprintf("\tdont_care_flags();\n"); - comprintf("\trol_l_ri(src,16);\n"); - genflags (flag_logical, sz_long, "src", "", ""); - genastore ("src", curi->smode, "srcreg", sz_long, "src"); - break; - case i_EXG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tmov_l_rr(tmp,src);\n"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - genastore ("tmp", curi->dmode, "dstreg", curi->size, "dst"); - break; - case i_EXT: - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); - comprintf("\tdont_care_flags();\n"); - start_brace (); - switch (curi->size) - { - case sz_byte: - comprintf ("\tint dst = src;\n" - "\tsign_extend_8_rr(src,src);\n"); - break; - case sz_word: - comprintf ("\tint dst = scratchie++;\n" - "\tsign_extend_8_rr(dst,src);\n"); - break; - case sz_long: - comprintf ("\tint dst = src;\n" - "\tsign_extend_16_rr(src,src);\n"); - break; - default: - abort (); - } - genflags (flag_logical, - curi->size == sz_word ? sz_word : sz_long, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", - curi->size == sz_word ? sz_word : sz_long, "src"); - break; - case i_MVMEL: - genmovemel ((uae_u16)opcode); - break; - case i_MVMLE: - genmovemle ((uae_u16)opcode); - break; - case i_TRAP: - isjump; - failure; - break; - case i_MVR2USP: - isjump; - failure; - break; - case i_MVUSP2R: - isjump; - failure; - break; - case i_RESET: - isjump; - failure; - break; - case i_NOP: - break; - case i_STOP: - isjump; - failure; - break; - case i_RTE: - isjump; - failure; - break; - case i_RTD: -/* failure; /* NEW: from "Ipswitch Town" release */ - genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); - /* offs is constant */ - comprintf("\tadd_l_ri(offs,4);\n"); - start_brace(); - comprintf("\tint newad=scratchie++;\n" - "\treadlong(15,newad,scratchie);\n" - "\tmov_l_mr((uintptr)®s.pc,newad);\n" - "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" - "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" - "\tm68k_pc_offset=0;\n" - "\tadd_l(15,offs);\n"); - gen_update_next_handler(); - isjump; - break; - case i_LINK: -/* failure; /* NEW: from "Ipswitch Town" release */ - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); - comprintf("\tsub_l_ri(15,4);\n" - "\twritelong_clobber(15,src,scratchie);\n" - "\tmov_l_rr(src,15);\n"); - if (curi->size==sz_word) - comprintf("\tsign_extend_16_rr(offs,offs);\n"); - comprintf("\tadd_l(15,offs);\n"); - genastore ("src", curi->smode, "srcreg", sz_long, "src"); - break; - case i_UNLK: -/* failure; /* NEW: from "Ipswitch Town" release */ - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - comprintf("\tmov_l_rr(15,src);\n" - "\treadlong(15,src,scratchie);\n" - "\tadd_l_ri(15,4);\n"); - genastore ("src", curi->smode, "srcreg", curi->size, "src"); - break; - case i_RTS: - comprintf("\tint newad=scratchie++;\n" - "\treadlong(15,newad,scratchie);\n" - "\tmov_l_mr((uintptr)®s.pc,newad);\n" - "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" - "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" - "\tm68k_pc_offset=0;\n" - "\tlea_l_brr(15,15,4);\n"); - gen_update_next_handler(); - isjump; - break; - case i_TRAPV: - isjump; - failure; - break; - case i_RTR: - isjump; - failure; - break; - case i_JSR: - isjump; - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - start_brace(); - comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); - comprintf("\tint ret=scratchie++;\n" - "\tmov_l_ri(ret,retadd);\n" - "\tsub_l_ri(15,4);\n" - "\twritelong_clobber(15,ret,scratchie);\n"); - comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" - "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" - "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" - "\tm68k_pc_offset=0;\n"); - gen_update_next_handler(); - break; - case i_JMP: - isjump; - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" - "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" - "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" - "\tm68k_pc_offset=0;\n"); - gen_update_next_handler(); - break; - case i_BSR: - is_const_jump; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - start_brace(); - comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); - comprintf("\tint ret=scratchie++;\n" - "\tmov_l_ri(ret,retadd);\n" - "\tsub_l_ri(15,4);\n" - "\twritelong_clobber(15,ret,scratchie);\n"); - comprintf("\tadd_l_ri(src,m68k_pc_offset_thisinst+2);\n"); - comprintf("\tm68k_pc_offset=0;\n"); - comprintf("\tadd_l(PC_P,src);\n"); - - comprintf("\tcomp_pc_p=(uae_u8*)get_const(PC_P);\n"); - break; - case i_Bcc: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - /* That source is an immediate, so we can clobber it with abandon */ - switch(curi->size) { - case sz_byte: comprintf("\tsign_extend_8_rr(src,src);\n"); break; - case sz_word: comprintf("\tsign_extend_16_rr(src,src);\n"); break; - case sz_long: break; - } - comprintf("\tsub_l_ri(src,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); - /* Leave the following as "add" --- it will allow it to be optimized - away due to src being a constant ;-) */ - comprintf("\tadd_l_ri(src,(uintptr)comp_pc_p);\n"); - comprintf("\tmov_l_ri(PC_P,(uintptr)comp_pc_p);\n"); - /* Now they are both constant. Might as well fold in m68k_pc_offset */ - comprintf("\tadd_l_ri(src,m68k_pc_offset);\n"); - comprintf("\tadd_l_ri(PC_P,m68k_pc_offset);\n"); - comprintf("\tm68k_pc_offset=0;\n"); - - if (curi->cc>=2) { - comprintf("\tuae_u32 v1=get_const(PC_P);\n" - "\tuae_u32 v2=get_const(src);\n" - "\tregister_branch(v1,v2,%d);\n", - cond_codes_x86[curi->cc]); - comprintf("\tmake_flags_live();\n"); /* Load the flags */ - isjump; - } - else { - is_const_jump; - } - - switch(curi->cc) { - case 0: /* Unconditional jump */ - comprintf("\tmov_l_rr(PC_P,src);\n"); - comprintf("\tcomp_pc_p=(uae_u8*)get_const(PC_P);\n"); - break; - case 1: break; /* This is silly! */ - case 8: failure; break; /* Work out details! FIXME */ - case 9: failure; break; /* Not critical, though! */ - - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - break; - default: abort(); - } - break; - case i_LEA: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); - break; - case i_PEA: - if (table68k[opcode].smode==Areg || - table68k[opcode].smode==Aind || - table68k[opcode].smode==Aipi || - table68k[opcode].smode==Apdi || - table68k[opcode].smode==Ad16 || - table68k[opcode].smode==Ad8r) - comprintf("if (srcreg==7) dodgy=1;\n"); - - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (Apdi, "7", sz_long, "dst", 2, 0); - genastore ("srca", Apdi, "7", sz_long, "dst"); - break; - case i_DBcc: - isjump; - uses_cmov; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); - - /* That offs is an immediate, so we can clobber it with abandon */ - switch(curi->size) { - case sz_word: comprintf("\tsign_extend_16_rr(offs,offs);\n"); break; - default: abort(); /* Seems this only comes in word flavour */ - } - comprintf("\tsub_l_ri(offs,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); - comprintf("\tadd_l_ri(offs,(uintptr)comp_pc_p);\n"); /* New PC, - once the - offset_68k is - * also added */ - /* Let's fold in the m68k_pc_offset at this point */ - comprintf("\tadd_l_ri(offs,m68k_pc_offset);\n"); - comprintf("\tadd_l_ri(PC_P,m68k_pc_offset);\n"); - comprintf("\tm68k_pc_offset=0;\n"); - - start_brace(); - comprintf("\tint nsrc=scratchie++;\n"); - - if (curi->cc>=2) { - comprintf("\tmake_flags_live();\n"); /* Load the flags */ - } - - if (curi->size!=sz_word) - abort(); - - - switch(curi->cc) { - case 0: /* This is an elaborate nop? */ - break; - case 1: - comprintf("\tstart_needflags();\n"); - comprintf("\tsub_w_ri(src,1);\n"); - comprintf("\t end_needflags();\n"); - start_brace(); - comprintf("\tuae_u32 v1=get_const(PC_P);\n"); - comprintf("\tuae_u32 v2=get_const(offs);\n" - "\tregister_branch(v1,v2,3);\n"); - break; - - case 8: failure; break; /* Work out details! FIXME */ - case 9: failure; break; /* Not critical, though! */ - - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - comprintf("\tmov_l_rr(nsrc,src);\n"); - comprintf("\tlea_l_brr(scratchie,src,(uae_s32)-1);\n" - "\tmov_w_rr(src,scratchie);\n"); - comprintf("\tcmov_l_rr(offs,PC_P,%d);\n", - cond_codes_x86[curi->cc]); - comprintf("\tcmov_l_rr(src,nsrc,%d);\n", - cond_codes_x86[curi->cc]); - /* OK, now for cc=true, we have src==nsrc and offs==PC_P, - so whether we move them around doesn't matter. However, - if cc=false, we have offs==jump_pc, and src==nsrc-1 */ - - comprintf("\t start_needflags();\n"); - comprintf("\ttest_w_rr(nsrc,nsrc);\n"); - comprintf("\t end_needflags();\n"); - comprintf("\tcmov_l_rr(PC_P,offs,5);\n"); - break; - default: abort(); - } - genastore ("src", curi->smode, "srcreg", curi->size, "src"); - gen_update_next_handler(); - break; - - case i_Scc: -/* failure; /* NEW: from "Ipswitch Town" release */ - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); - start_brace (); - comprintf ("\tint val = scratchie++;\n"); - - /* We set val to 0 if we really should use 255, and to 1 for real 0 */ - switch(curi->cc) { - case 0: /* Unconditional set */ - comprintf("\tmov_l_ri(val,0);\n"); - break; - case 1: - /* Unconditional not-set */ - comprintf("\tmov_l_ri(val,1);\n"); - break; - case 8: failure; break; /* Work out details! FIXME */ - case 9: failure; break; /* Not critical, though! */ - - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - comprintf("\tmake_flags_live();\n"); /* Load the flags */ - /* All condition codes can be inverted by changing the LSB */ - comprintf("\tsetcc(val,%d);\n", - cond_codes_x86[curi->cc]^1); break; - default: abort(); - } - comprintf("\tsub_b_ri(val,1);\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "src"); - break; - case i_DIVU: - isjump; - failure; - break; - case i_DIVS: - isjump; - failure; - break; - case i_MULU: -/* failure; /* NEW: from "Ipswitch Town" release */ - comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); - /* To do 16x16 unsigned multiplication, we actually use - 32x32 signed, and zero-extend the registers first. - That solves the problem of MUL needing dedicated registers - on the x86 */ - comprintf("\tzero_extend_16_rr(scratchie,src);\n" - "\tzero_extend_16_rr(dst,dst);\n" - "\timul_32_32(dst,scratchie);\n"); - genflags (flag_logical, sz_long, "dst", "", ""); - genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); - break; - case i_MULS: -/* failure; /* NEW: from "Ipswitch Town" release */ - comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); - comprintf("\tsign_extend_16_rr(scratchie,src);\n" - "\tsign_extend_16_rr(dst,dst);\n" - "\timul_32_32(dst,scratchie);\n"); - genflags (flag_logical, sz_long, "dst", "", ""); - genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); - break; - case i_CHK: - isjump; - failure; - break; - - case i_CHK2: - isjump; - failure; - break; - - case i_ASR: - mayfail; - if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - start_brace(); - } - comprintf("\tdont_care_flags();\n"); - - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { -/* failure; /* UNTESTED: NEW: from "Ipswitch Town" release */ - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint sdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(sdata,data);\n" - "\tmov_l_rr(cdata,data);\n" - "\tmov_l_rr(tmpcnt,cnt);\n"); - switch (curi->size) { - case sz_byte: comprintf("\tshra_b_ri(sdata,7);\n"); break; - case sz_word: comprintf("\tshra_w_ri(sdata,15);\n"); break; - case sz_long: comprintf("\tshra_l_ri(sdata,31);\n"); break; - default: abort(); - } - /* sdata is now the MSB propagated to all bits for the - register of specified size */ - comprintf("\tand_l_ri(tmpcnt,63);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,tmpcnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshra_w_rr(data,tmpcnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshra_l_rr(data,tmpcnt);\n" - "\thighmask=0x20;\n"); - break; - } - comprintf("\ttest_l_ri(tmpcnt,highmask);\n"); - switch (curi->size) { - case sz_byte: comprintf("\tcmov_b_rr(data,sdata,NATIVE_CC_NE);\n"); break; - case sz_word: comprintf("\tcmov_w_rr(data,sdata,NATIVE_CC_NE);\n"); break; - case sz_long: comprintf("\tcmov_l_rr(data,sdata,NATIVE_CC_NE);\n"); break; - } - - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - /* NOTE: carry bit is cleared if shift count is zero */ - comprintf("\tmov_l_ri(scratchie,0);\n" - "\ttest_l_rr(tmpcnt,tmpcnt);\n" - "\tcmov_l_rr(sdata,scratchie,NATIVE_CC_EQ);\n" - "\tforget_about(scratchie);\n"); - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(cdata,tmpcnt);\n");break; - case sz_word: comprintf("\tshra_w_rr(cdata,tmpcnt);\n");break; - case sz_long: comprintf("\tshra_l_rr(cdata,tmpcnt);\n");break; - default: abort(); - } - /* If the shift count was higher than the width, we need - to pick up the sign from original data (sdata) */ - /* NOTE: for shift count of zero, the following holds - true and cdata contains 0 so that carry bit is cleared */ - comprintf("\ttest_l_ri(tmpcnt,highmask);\n" - "\tforget_about(tmpcnt);\n" - "\tcmov_l_rr(cdata,sdata,NATIVE_CC_NE);\n"); - - /* And create the flags (preserve X flag if shift count is zero) */ - comprintf("\ttest_l_ri(cnt,63);\n" - "\tcmov_l_rr(FLAGX,cdata,NATIVE_CC_NE);\n"); - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint width;\n" - "\tint highshift=scratchie++;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,cnt);\n" - "\thighmask=0x38;\n" - "\twidth=8;\n"); - break; - case sz_word: comprintf("\tshra_w_rr(data,cnt);\n" - "\thighmask=0x30;\n" - "\twidth=16;\n"); - break; - case sz_long: comprintf("\tshra_l_rr(data,cnt);\n" - "\thighmask=0x20;\n" - "\twidth=32;\n"); - break; - default: abort(); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(highshift,0);\n" - "mov_l_ri(scratchie,width/2);\n" - "cmov_l_rr(highshift,scratchie,5);\n"); - /* The x86 masks out bits, so we now make sure that things - really get shifted as much as planned */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; - case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; - case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; - default: abort(); - } - /* And again */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; - case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; - case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; - default: abort(); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - } - else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_word: comprintf("\tshra_w_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_long: comprintf("\tshra_l_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - default: abort(); - } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - break; - - case i_ASL: -/* failure; /* NEW: from "Ipswitch Town" release */ - mayfail; - if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - start_brace(); - } - comprintf("\tdont_care_flags();\n"); - /* Except for the handling of the V flag, this is identical to - LSL. The handling of V is, uhm, unpleasant, so if it's needed, - let the normal emulation handle it. Shoulders of giants kinda - thing ;-) */ - comprintf("if (needed_flags & FLAG_V) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,5);\n"); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: abort(); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,4);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: abort(); - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break; - case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break; - case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break; - default: abort(); - } - comprintf("test_l_ri(tmpcnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(cdata,scratchie,5);\n"); - /* And create the flags */ - comprintf("\tstart_needflags();\n"); - - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,7);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,15);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,31);\n"); break; - } - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: abort(); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,4);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: abort(); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - } - else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n" - "\tbp=8-srcreg;\n"); break; - case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n" - "\tbp=16-srcreg;\n"); break; - case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n" - "\tbp=32-srcreg;\n"); break; - default: abort(); - } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - break; - - case i_LSR: -/* failure; /* NEW: from "Ipswitch Town" release */ - mayfail; - if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - start_brace(); - } - comprintf("\tdont_care_flags();\n"); - - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,NATIVE_CC_NE);\n"); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_rr(data,tmpcnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshrl_w_rr(data,tmpcnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshrl_l_rr(data,tmpcnt);\n" - "\thighmask=0x20;\n"); - break; - default: abort(); - } - comprintf("\ttest_l_ri(tmpcnt,highmask);\n" - "\rmov_l_ri(scratchie,0);\n"); - if (curi->size == sz_long) - comprintf("\tcmov_l_rr(data,scratchie,NATIVE_CC_NE);\n"); - else { - comprintf("\tcmov_l_rr(scratchie,data,NATIVE_CC_EQ);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - default: abort(); - } - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - comprintf("\tshrl_l_rr(cdata,tmpcnt);\n"); - comprintf("\ttest_l_ri(tmpcnt,highmask);\n"); - comprintf("\tforget_about(tmpcnt);\n"); - if (curi->size != sz_long) /* scratchie is still live for LSR.L */ - comprintf("\tmov_l_ri(scratchie,0);\n"); - comprintf("\tcmov_l_rr(cdata,scratchie,NATIVE_CC_NE);\n"); - comprintf("\tforget_about(scratchie);\n"); - /* And create the flags (preserve X flag if shift count is zero) */ - comprintf("\ttest_l_ri(cnt,63);\n" - "\tcmov_l_rr(FLAGX,cdata,NATIVE_CC_NE);\n"); - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshrl_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: abort(); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,4);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: abort(); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - } - else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_word: comprintf("\tshrl_w_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_long: comprintf("\tshrl_l_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - default: abort(); - } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - break; - - case i_LSL: - mayfail; - if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - start_brace(); - } - comprintf("\tdont_care_flags();\n"); - - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { -/* failure; /* UNTESTED: NEW: from "Ipswitch Town" release */ - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,NATIVE_CC_NE);\n"); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,tmpcnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,tmpcnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,tmpcnt);\n" - "\thighmask=0x20;\n"); - break; - default: abort(); - } - comprintf("\ttest_l_ri(tmpcnt,highmask);\n" - "\tmov_l_ri(scratchie,0);\n"); - if (curi->size == sz_long) - comprintf("\tcmov_l_rr(data,scratchie,NATIVE_CC_NE);\n"); - else { - comprintf("\tcmov_l_rr(scratchie,data,NATIVE_CC_EQ);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - default: abort(); - } - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - comprintf("\tshll_l_rr(cdata,tmpcnt);\n"); - comprintf("\ttest_l_ri(tmpcnt,highmask);\n"); - comprintf("\tforget_about(tmpcnt);\n"); - if (curi->size != sz_long) /* scratchie is still live for LSL.L */ - comprintf("\tmov_l_ri(scratchie,0);\n"); - comprintf("\tcmov_l_rr(cdata,scratchie,NATIVE_CC_NE);\n"); - comprintf("\tforget_about(scratchie);\n"); - /* And create the flags (preserve X flag if shift count is zero) */ - switch (curi->size) { - case sz_byte: comprintf("\tshrl_l_ri(cdata,7);\n"); break; - case sz_word: comprintf("\tshrl_l_ri(cdata,15);\n"); break; - case sz_long: comprintf("\tshrl_l_ri(cdata,31);\n"); break; - } - comprintf("\ttest_l_ri(cnt,63);\n" - "\tcmov_l_rr(FLAGX,cdata,NATIVE_CC_NE);\n"); - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(cdata,0);\n"); - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: abort(); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,4);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: abort(); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - } - else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n" - "\tbp=8-srcreg;\n"); break; - case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n" - "\tbp=16-srcreg;\n"); break; - case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n" - "\tbp=32-srcreg;\n"); break; - default: abort(); - } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - break; - - case i_ROL: - mayfail; - if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - start_brace(); - } - comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - start_brace (); - - switch(curi->size) { - case sz_long: comprintf("\t rol_l_rr(data,cnt);\n"); break; - case sz_word: comprintf("\t rol_w_rr(data,cnt);\n"); break; - case sz_byte: comprintf("\t rol_b_rr(data,cnt);\n"); break; - } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(data,0x00);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - break; - - case i_ROR: - mayfail; - if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " return;\n" - "} \n"); - start_brace(); - } - comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - start_brace (); - - switch(curi->size) { - case sz_long: comprintf("\t ror_l_rr(data,cnt);\n"); break; - case sz_word: comprintf("\t ror_w_rr(data,cnt);\n"); break; - case sz_byte: comprintf("\t ror_b_rr(data,cnt);\n"); break; - } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - switch(curi->size) { - case sz_byte: comprintf("\t bt_l_ri(data,0x07);\n"); break; - case sz_word: comprintf("\t bt_l_ri(data,0x0f);\n"); break; - case sz_long: comprintf("\t bt_l_ri(data,0x1f);\n"); break; - } - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - break; - - case i_ROXL: - failure; - break; - case i_ROXR: - failure; - break; - case i_ASRW: - failure; - break; - case i_ASLW: - failure; - break; - case i_LSRW: - failure; - break; - case i_LSLW: - failure; - break; - case i_ROLW: - failure; - break; - case i_RORW: - failure; - break; - case i_ROXLW: - failure; - break; - case i_ROXRW: - failure; - break; - case i_MOVEC2: - isjump; - failure; - break; - case i_MOVE2C: - isjump; - failure; - break; - case i_CAS: - failure; - break; - case i_CAS2: - failure; - break; - case i_MOVES: /* ignore DFC and SFC because we have no MMU */ - isjump; - failure; - break; - case i_BKPT: /* only needed for hardware emulators */ - isjump; - failure; - break; - case i_CALLM: /* not present in 68030 */ - isjump; - failure; - break; - case i_RTM: /* not present in 68030 */ - isjump; - failure; - break; - case i_TRAPcc: - isjump; - failure; - break; - case i_DIVL: - isjump; - failure; - break; - case i_MULL: -/* failure; /* NEW: from "Ipswitch Town" release */ - if (!noflags) { - failure; - break; - } - comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); - comprintf("\tint r2=(extra>>12)&7;\n" - "\tint tmp=scratchie++;\n"); - - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - /* The two operands are in dst and r2 */ - comprintf("\tif (extra&0x0400) {\n" /* Need full 64 bit result */ - "\tint r3=(extra&7);\n" - "\tmov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ - comprintf("\tif (extra&0x0800) { \n" /* signed */ - "\t\timul_64_32(r2,r3);\n" - "\t} else { \n" - "\t\tmul_64_32(r2,r3);\n" - "\t} \n"); - /* The result is in r2/tmp, with r2 holding the lower 32 bits */ - comprintf("\t} else {\n"); /* Only want 32 bit result */ - /* operands in dst and r2, result foes into r2 */ - /* shouldn't matter whether it's signed or unsigned?!? */ - comprintf("\timul_32_32(r2,dst);\n" - "\t}\n"); - break; - - case i_BFTST: - case i_BFEXTU: - case i_BFCHG: - case i_BFEXTS: - case i_BFCLR: - case i_BFFFO: - case i_BFSET: - case i_BFINS: - failure; - break; - case i_PACK: - failure; - break; - case i_UNPK: - failure; - break; - case i_TAS: - failure; - break; - case i_FPP: - uses_fpu; -#ifdef USE_JIT_FPU - mayfail; - comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); - swap_opcode(); - comprintf("\tcomp_fpp_opp(opcode,extra);\n"); -#else - failure; -#endif - break; - case i_FBcc: - uses_fpu; -#ifdef USE_JIT_FPU - isjump; - uses_cmov; - mayfail; - swap_opcode(); - comprintf("\tcomp_fbcc_opp(opcode);\n"); -#else - isjump; - failure; -#endif - break; - case i_FDBcc: - uses_fpu; - isjump; - failure; - break; - case i_FScc: - uses_fpu; -#ifdef USE_JIT_FPU - mayfail; - uses_cmov; - comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); - swap_opcode(); - comprintf("\tcomp_fscc_opp(opcode,extra);\n"); -#else - failure; -#endif - break; - case i_FTRAPcc: - uses_fpu; - isjump; - failure; - break; - case i_FSAVE: - uses_fpu; - failure; - break; - case i_FRESTORE: - uses_fpu; - failure; - break; - - case i_CINVL: - case i_CINVP: - case i_CINVA: - isjump; /* Not really, but it's probably a good idea to stop - translating at this point */ - failure; - comprintf ("\tflush_icache();\n"); /* Differentiate a bit more? */ - break; - case i_CPUSHL: - case i_CPUSHP: - case i_CPUSHA: - isjump; /* Not really, but it's probably a good idea to stop - translating at this point */ - failure; - break; - case i_MOVE16: - genmov16(opcode, curi); - break; - - case i_EMULOP_RETURN: - isjump; - failure; - break; - - case i_EMULOP: - failure; - break; - - case i_MMUOP: - isjump; - failure; - break; - default: - abort (); - break; - } - comprintf("%s",endstr); - finish_braces (); - sync_m68k_pc (); - if (global_mayfail) - comprintf("\tif (failure) m68k_pc_offset=m68k_pc_offset_thisinst;\n"); - return global_failure; -} - -static void -generate_includes (FILE * f) -{ - fprintf (f, "#include \"sysdeps.h\"\n"); - fprintf (f, "#include \"m68k.h\"\n"); - fprintf (f, "#include \"memory.h\"\n"); - fprintf (f, "#include \"readcpu.h\"\n"); - fprintf (f, "#include \"newcpu.h\"\n"); - fprintf (f, "#include \"comptbl.h\"\n"); -} - -static int postfix; - -static void -generate_one_opcode (int rp, int noflags) -{ - uae_u16 smsk, dmsk; - const long int opcode = opcode_map[rp]; - const char *opcode_str; - int aborted=0; - int have_srcreg=0; - int have_dstreg=0; - - if (table68k[opcode].mnemo == i_ILLG - || table68k[opcode].clev > cpu_level) - return; - - if (table68k[opcode].handler != -1) - return; - - switch (table68k[opcode].stype) - { - case 0: - smsk = 7; - break; - case 1: - smsk = 255; - break; - case 2: - smsk = 15; - break; - case 3: - smsk = 7; - break; - case 4: - smsk = 7; - break; - case 5: - smsk = 63; - break; - case 6: - smsk = 255; - break; - case 7: - smsk = 3; - break; - default: - abort (); - } - dmsk = 7; - - next_cpu_level = -1; - if (table68k[opcode].suse - && table68k[opcode].smode != imm && table68k[opcode].smode != imm0 - && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2 - && table68k[opcode].smode != absw && table68k[opcode].smode != absl - && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16) - { - have_srcreg=1; - if (table68k[opcode].spos == -1) - { - if (((int) table68k[opcode].sreg) >= 128) - comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg); - else - comprintf ("\tuae_s32 srcreg = %d;\n", (int) table68k[opcode].sreg); - } - else - { - char source[100]; - int pos = table68k[opcode].spos; - - comprintf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - - if (pos < 8 && (smsk >> (8 - pos)) != 0) - sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)", - pos ^ 8, 8 - pos, dmsk); - else if (pos != 8) - sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk); - else - sprintf (source, "(opcode & %d)", smsk); - - if (table68k[opcode].stype == 3) - comprintf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); - else if (table68k[opcode].stype == 1) - comprintf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); - else - comprintf ("\tuae_u32 srcreg = %s;\n", source); - - comprintf ("#else\n"); - - if (pos) - sprintf (source, "((opcode >> %d) & %d)", pos, smsk); - else - sprintf (source, "(opcode & %d)", smsk); - - if (table68k[opcode].stype == 3) - comprintf ("\tuae_s32 srcreg = imm8_table[%s];\n", source); - else if (table68k[opcode].stype == 1) - comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%s;\n", source); - else - comprintf ("\tuae_s32 srcreg = %s;\n", source); - - comprintf ("#endif\n"); - } - } - if (table68k[opcode].duse - /* Yes, the dmode can be imm, in case of LINK or DBcc */ - && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0 - && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2 - && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl) - { - have_dstreg=1; - if (table68k[opcode].dpos == -1) - { - if (((int) table68k[opcode].dreg) >= 128) - comprintf ("\tuae_s32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg); - else - comprintf ("\tuae_s32 dstreg = %d;\n", (int) table68k[opcode].dreg); - } - else - { - int pos = table68k[opcode].dpos; - - comprintf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - - if (pos < 8 && (dmsk >> (8 - pos)) != 0) - comprintf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", - pos ^ 8, 8 - pos, dmsk); - else if (pos != 8) - comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", - pos ^ 8, dmsk); - else - comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); - - comprintf ("#else\n"); - - if (pos) - comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", - pos, dmsk); - else - comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); - - comprintf ("#endif\n"); - } - } - - if (have_srcreg && have_dstreg && - (table68k[opcode].dmode==Areg || - table68k[opcode].dmode==Aind || - table68k[opcode].dmode==Aipi || - table68k[opcode].dmode==Apdi || - table68k[opcode].dmode==Ad16 || - table68k[opcode].dmode==Ad8r) && - (table68k[opcode].smode==Areg || - table68k[opcode].smode==Aind || - table68k[opcode].smode==Aipi || - table68k[opcode].smode==Apdi || - table68k[opcode].smode==Ad16 || - table68k[opcode].smode==Ad8r) - ) { - comprintf("\tuae_u32 dodgy=(srcreg==(uae_s32)dstreg);\n"); - } - else { - comprintf("\tuae_u32 dodgy=0;\n"); - } - comprintf("\tuae_u32 m68k_pc_offset_thisinst=m68k_pc_offset;\n"); - comprintf("\tm68k_pc_offset+=2;\n"); - - opcode_str = get_instruction_string (opcode); - - aborted=gen_opcode (opcode); - { - int flags=0; - if (global_isjump) flags|=1; - if (long_opcode) flags|=2; - if (global_cmov) flags|=4; - if (global_isaddx) flags|=8; - if (global_iscjump) flags|=16; - if (global_fpu) flags|=32; - - comprintf ("}\n"); - - if (aborted) { - fprintf (stblfile, "{ NULL, 0x%08x, %ld }, /* %s */\n", flags, opcode, opcode_str); - com_discard(); - } - else { - if (noflags) { - fprintf (stblfile, "{ op_%lx_%d_comp_nf, 0x%08x, %ld }, /* %s */\n", opcode, postfix, flags, opcode, opcode_str); - fprintf (headerfile, "extern compop_func op_%lx_%d_comp_nf;\n", opcode, postfix); - printf ("void REGPARAM2 op_%lx_%d_comp_nf(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, opcode_str); - } - else { - fprintf (stblfile, "{ op_%lx_%d_comp_ff, 0x%08x, %ld }, /* %s */\n", opcode, postfix, flags, opcode, opcode_str); - fprintf (headerfile, "extern compop_func op_%lx_%d_comp_ff;\n", opcode, postfix); - printf ("void REGPARAM2 op_%lx_%d_comp_ff(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, opcode_str); - } - com_flush(); - } - } - opcode_next_clev[rp] = next_cpu_level; - opcode_last_postfix[rp] = postfix; -} - -static void -generate_func (int noflags) -{ - int i, j, rp; - - using_prefetch = 0; - using_exception_3 = 0; - for (i = 0; i < 1; i++) /* We only do one level! */ - { - cpu_level = 4 - i; - postfix = i; - - if (noflags) - fprintf (stblfile, "struct comptbl op_smalltbl_%d_comp_nf[] = {\n", postfix); - else - fprintf (stblfile, "struct comptbl op_smalltbl_%d_comp_ff[] = {\n", postfix); - - - /* sam: this is for people with low memory (eg. me :)) */ - printf ("\n" - "#if !defined(PART_1) && !defined(PART_2) && " - "!defined(PART_3) && !defined(PART_4) && " - "!defined(PART_5) && !defined(PART_6) && " - "!defined(PART_7) && !defined(PART_8)" - "\n" - "#define PART_1 1\n" - "#define PART_2 1\n" - "#define PART_3 1\n" - "#define PART_4 1\n" - "#define PART_5 1\n" - "#define PART_6 1\n" - "#define PART_7 1\n" - "#define PART_8 1\n" - "#endif\n\n"); - - rp = 0; - for (j = 1; j <= 8; ++j) - { - int k = (j * nr_cpuop_funcs) / 8; - printf ("#ifdef PART_%d\n", j); - for (; rp < k; rp++) - generate_one_opcode (rp,noflags); - printf ("#endif\n\n"); - } - - fprintf (stblfile, "{ 0, 0,65536 }};\n"); - } - -} - -int -main (int argc, char **argv) -{ - read_table68k (); - do_merges (); - - opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs); - opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs); - opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs); - counts = (unsigned long *) malloc (65536 * sizeof (unsigned long)); - read_counts (); - - /* It would be a lot nicer to put all in one file (we'd also get rid of - * cputbl.h that way), but cpuopti can't cope. That could be fixed, but - * I don't dare to touch the 68k version. */ - - headerfile = fopen ("comptbl.h", "wb"); - stblfile = fopen ("compstbl.cpp", "wb"); - freopen ("compemu.cpp", "wb", stdout); - - generate_includes (stdout); - generate_includes (stblfile); - - printf("#include \"compiler/compemu.h\"\n"); - - noflags=0; - generate_func (noflags); - - free(opcode_map); - free(opcode_last_postfix); - free(opcode_next_clev); - free(counts); - - opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs); - opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs); - opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs); - counts = (unsigned long *) malloc (65536 * sizeof (unsigned long)); - read_counts (); - noflags=1; - generate_func (noflags); - - free(opcode_map); - free(opcode_last_postfix); - free(opcode_next_clev); - free(counts); - - free (table68k); - fclose (stblfile); - fclose (headerfile); - fflush (stdout); - return 0; -} diff --git a/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp deleted file mode 100644 index 236a2d5e..00000000 --- a/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp +++ /dev/null @@ -1,2254 +0,0 @@ -/******************** -*- mode: C; tab-width: 8 -*- ******************** - * - * Dumb and Brute Force Run-time assembler verifier for IA-32 and AMD64 - * - ***********************************************************************/ - - -/*********************************************************************** - * - * Copyright 2004-2008 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ***********************************************************************/ - -/* - * STATUS: 26M variations covering unary register based operations, - * reg/reg operations, imm/reg operations. - * - * TODO: - * - Rewrite to use internal BFD/opcodes format instead of string compares - * - Add reg/mem, imm/mem variations - */ - -#define _BSD_SOURCE 1 -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" - -static int verbose = 2; - -#define TEST_INST_ALU 1 -#define TEST_INST_FPU 1 -#define TEST_INST_MMX 1 -#define TEST_INST_SSE 1 -#if TEST_INST_ALU -#define TEST_INST_ALU_REG 1 -#define TEST_INST_ALU_REG_REG 1 -#define TEST_INST_ALU_CNT_REG 1 -#define TEST_INST_ALU_IMM_REG 1 -#define TEST_INST_ALU_MEM_REG 1 -#endif -#if TEST_INST_FPU -#define TEST_INST_FPU_UNARY 1 -#define TEST_INST_FPU_REG 1 -#define TEST_INST_FPU_MEM 1 -#endif -#if TEST_INST_MMX -#define TEST_INST_MMX_REG_REG 1 -#define TEST_INST_MMX_IMM_REG 1 -#define TEST_INST_MMX_MEM_REG 1 -#endif -#if TEST_INST_SSE -#define TEST_INST_SSE_REG 1 -#define TEST_INST_SSE_REG_REG 1 -#define TEST_INST_SSE_MEM_REG 1 -#endif - -#undef abort -#define abort() do { \ - fprintf(stderr, "ABORT: %s, line %d\n", __FILE__, __LINE__); \ - (abort)(); \ -} while (0) - -#define X86_TARGET_64BIT 1 -#define X86_FLAT_REGISTERS 0 -#define X86_OPTIMIZE_ALU 1 -#define X86_OPTIMIZE_ROTSHI 1 -#define X86_RIP_RELATIVE_ADDR 0 -#include "compiler/codegen_x86.h" - -#if X86_TARGET_64BIT -#define X86_MAX_ALU_REGS 16 -#define X86_MAX_SSE_REGS 16 -#else -#define X86_MAX_ALU_REGS 8 -#define X86_MAX_SSE_REGS 8 -#endif -#define X86_MAX_FPU_REGS 8 -#define X86_MAX_MMX_REGS 8 - -#define VALID_REG(r, b, n) (((unsigned)((r) - X86_##b)) < (n)) -#if X86_TARGET_64BIT -#define VALID_REG8(r) (VALID_REG(r, AL, 16) || VALID_REG(r, AH, 4)) -#define VALID_REG64(r) VALID_REG(r, RAX, X86_MAX_ALU_REGS) -#else -#define VALID_REG8(r) (VALID_REG(r, AL, 4) || VALID_REG(r, AH, 4)) -#define VALID_REG64(r) (0) -#endif -#define VALID_REG16(r) VALID_REG(r, AX, X86_MAX_ALU_REGS) -#define VALID_REG32(r) VALID_REG(r, EAX, X86_MAX_ALU_REGS) - -#define x86_emit_byte(B) emit_byte(B) -#define x86_emit_word(W) emit_word(W) -#define x86_emit_long(L) emit_long(L) -#define x86_emit_quad(Q) emit_quad(Q) -#define x86_get_target() get_target() -#define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__) - -static void jit_fail(const char *msg, const char *file, int line, const char *function) -{ - fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n", - function, file, line, msg); - abort(); -} - -static uint8 *target; - -static inline void emit_byte(uint8 x) -{ - *target++ = x; -} - -static inline void emit_word(uint16 x) -{ - *((uint16 *)target) = x; - target += 2; -} - -static inline void emit_long(uint32 x) -{ - *((uint32 *)target) = x; - target += 4; -} - -static inline void emit_quad(uint64 x) -{ - *((uint64 *)target) = x; - target += 8; -} - -static inline void set_target(uint8 *t) -{ - target = t; -} - -static inline uint8 *get_target(void) -{ - return target; -} - -static uint32 mon_read_byte(uintptr addr) -{ - uint8 *m = (uint8 *)addr; - return (uint32)(*m); -} - -extern "C" { -#include "disass/dis-asm.h" - -int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info) -{ - while (length--) - *to++ = mon_read_byte(from++); - return 0; -} - -void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info) -{ - info->fprintf_func(info->stream, "Unknown error %d\n", status); -} - -void generic_print_address(bfd_vma addr, struct disassemble_info *info) -{ - if (addr >= UVAL64(0x100000000)) - info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr); - else - info->fprintf_func(info->stream, "$%08x", (uint32)addr); -} - -int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info) -{ - return 0; -} -} - -struct SFILE { - char *buffer; - char *current; -}; - -static int mon_sprintf(SFILE *f, const char *format, ...) -{ - int n; - va_list args; - va_start(args, format); - vsprintf(f->current, format, args); - f->current += n = strlen(f->current); - va_end(args); - return n; -} - -static int disass_x86(char *buf, uintptr adr) -{ - disassemble_info info; - SFILE sfile; - sfile.buffer = buf; - sfile.current = buf; - INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf); - info.mach = X86_TARGET_64BIT ? bfd_mach_x86_64 : bfd_mach_i386_i386; - info.disassembler_options = "suffix"; - return print_insn_i386(adr, &info); -} - -enum { - op_disp, - op_reg, - op_base, - op_index, - op_scale, - op_imm, -}; -struct operand_t { - int32 disp; - int8 reg; - int8 base; - int8 index; - int8 scale; - int64 imm; - - void clear() { - disp = imm = 0; - reg = base = index = -1; - scale = 1; - } - - void fill(int optype, int value) { - switch (optype) { - case op_disp: disp = value; break; - case op_reg: reg = value; break; - case op_base: base = value; break; - case op_index: index = value; break; - case op_scale: scale = value; break; - case op_imm: imm = value; break; - default: abort(); - } - } -}; - -#define MAX_INSNS 1024 -#define MAX_INSN_LENGTH 16 -#define MAX_INSN_OPERANDS 3 - -struct insn_t { - char name[16]; - int n_operands; - operand_t operands[MAX_INSN_OPERANDS]; - - void clear() { - memset(name, 0, sizeof(name)); - n_operands = 0; - for (int i = 0; i < MAX_INSN_OPERANDS; i++) - operands[i].clear(); - } - - void pretty_print() { - printf("%s, %d operands\n", name, n_operands); - for (int i = 0; i < n_operands; i++) { - operand_t *op = &operands[i]; - if (op->reg != -1) - printf(" reg r%d\n", op->reg); - else { - printf(" mem 0x%08x(", op->disp); - if (op->base != -1) - printf("r%d", op->base); - printf(","); - if (op->index != -1) - printf("r%d", op->index); - printf(","); - if (op->base != -1 || op->index != -1) - printf("%d", op->scale); - printf(")\n"); - } - } - } -}; - -static inline char *find_blanks(char *p) -{ - while (*p && !isspace(*p)) - ++p; - return p; -} - -static inline char *skip_blanks(char *p) -{ - while (*p && isspace(*p)) - ++p; - return p; -} - -static int parse_reg(operand_t *op, int optype, char *buf) -{ - int reg = X86_NOREG; - int len = 0; - char *p = buf; - switch (p[0]) { - case 'a': case 'A': - len = 2; - switch (p[1]) { - case 'l': case 'L': reg = X86_AL; break; - case 'h': case 'H': reg = X86_AH; break; - case 'x': case 'X': reg = X86_AX; break; - } - break; - case 'b': case 'B': - len = 2; - switch (p[1]) { - case 'l': case 'L': reg = X86_BL; break; - case 'h': case 'H': reg = X86_BH; break; - case 'x': case 'X': reg = X86_BX; break; - case 'p': case 'P': - switch (p[2]) { -#if X86_TARGET_64BIT - case 'l': case 'L': reg = X86_BPL, ++len; break; -#endif - default: reg = X86_BP; break; - } - break; - } - break; - case 'c': case 'C': - len = 2; - switch (p[1]) { - case 'l': case 'L': reg = X86_CL; break; - case 'h': case 'H': reg = X86_CH; break; - case 'x': case 'X': reg = X86_CX; break; - } - break; - case 'd': case 'D': - len = 2; - switch (p[1]) { - case 'l': case 'L': reg = X86_DL; break; - case 'h': case 'H': reg = X86_DH; break; - case 'x': case 'X': reg = X86_DX; break; - case 'i': case 'I': - switch (p[2]) { -#if X86_TARGET_64BIT - case 'l': case 'L': reg = X86_DIL; ++len; break; -#endif - default: reg = X86_DI; break; - } - break; - } - break; - case 's': case 'S': - len = 2; - switch (p[2]) { -#if X86_TARGET_64BIT - case 'l': case 'L': - ++len; - switch (p[1]) { - case 'p': case 'P': reg = X86_SPL; break; - case 'i': case 'I': reg = X86_SIL; break; - } - break; -#endif - case '(': - if ((p[1] == 't' || p[1] == 'T') && isdigit(p[3]) && p[4] == ')') - len += 3, reg = X86_ST0 + (p[3] - '0'); - break; - default: - switch (p[1]) { - case 't': case 'T': reg = X86_ST0; break; - case 'p': case 'P': reg = X86_SP; break; - case 'i': case 'I': reg = X86_SI; break; - } - break; - } - break; - case 'e': case 'E': - len = 3; - switch (p[2]) { - case 'x': case 'X': - switch (p[1]) { - case 'a': case 'A': reg = X86_EAX; break; - case 'b': case 'B': reg = X86_EBX; break; - case 'c': case 'C': reg = X86_ECX; break; - case 'd': case 'D': reg = X86_EDX; break; - } - break; - case 'i': case 'I': - switch (p[1]) { - case 's': case 'S': reg = X86_ESI; break; - case 'd': case 'D': reg = X86_EDI; break; - } - break; - case 'p': case 'P': - switch (p[1]) { - case 'b': case 'B': reg = X86_EBP; break; - case 's': case 'S': reg = X86_ESP; break; - } - break; - } - break; -#if X86_TARGET_64BIT - case 'r': case 'R': - len = 3; - switch (p[2]) { - case 'x': case 'X': - switch (p[1]) { - case 'a': case 'A': reg = X86_RAX; break; - case 'b': case 'B': reg = X86_RBX; break; - case 'c': case 'C': reg = X86_RCX; break; - case 'd': case 'D': reg = X86_RDX; break; - } - break; - case 'i': case 'I': - switch (p[1]) { - case 's': case 'S': reg = X86_RSI; break; - case 'd': case 'D': reg = X86_RDI; break; - } - break; - case 'p': case 'P': - switch (p[1]) { - case 'b': case 'B': reg = X86_RBP; break; - case 's': case 'S': reg = X86_RSP; break; - } - break; - case 'b': case 'B': - switch (p[1]) { - case '8': reg = X86_R8B; break; - case '9': reg = X86_R9B; break; - } - break; - case 'w': case 'W': - switch (p[1]) { - case '8': reg = X86_R8W; break; - case '9': reg = X86_R9W; break; - } - break; - case 'd': case 'D': - switch (p[1]) { - case '8': reg = X86_R8D; break; - case '9': reg = X86_R9D; break; - } - break; - case '0': case '1': case '2': case '3': case '4': case '5': - if (p[1] == '1') { - const int r = p[2] - '0'; - switch (p[3]) { - case 'b': case 'B': reg = X86_R10B + r, ++len; break; - case 'w': case 'W': reg = X86_R10W + r, ++len; break; - case 'd': case 'D': reg = X86_R10D + r, ++len; break; - default: reg = X86_R10 + r; break; - } - } - break; - default: - switch (p[1]) { - case '8': reg = X86_R8, len = 2; break; - case '9': reg = X86_R9, len = 2; break; - } - break; - } - break; -#endif - case 'm': case 'M': - if ((p[1] == 'm' || p[1] == 'M') && isdigit(p[2])) - reg = X86_MM0 + (p[2] - '0'), len = 3; - break; - case 'x': case 'X': - if ((p[1] == 'm' || p[1] == 'M') && (p[2] == 'm' || p[2] == 'M')) { -#if X86_TARGET_64BIT - if (p[3] == '1' && isdigit(p[4])) - reg = X86_XMM10 + (p[4] - '0'), len = 5; - else -#endif - if (isdigit(p[3])) - reg = X86_XMM0 + (p[3] - '0'), len = 4; - } - break; - } - - if (len > 0 && reg != X86_NOREG) { - op->fill(optype, reg); - return len; - } - - return X86_NOREG; -} - -static unsigned long parse_imm(char *nptr, char **endptr, int base = 0) -{ - errno = 0; -#if X86_TARGET_64BIT - if (sizeof(unsigned long) != 8) { - unsigned long long val = strtoull(nptr, endptr, 0); - if (errno == 0) - return val; - abort(); - } -#endif - unsigned long val = strtoul(nptr, endptr, 0); - if (errno == 0) - return val; - abort(); - return 0; -} - -static int parse_mem(operand_t *op, char *buf) -{ - char *p = buf; - - if (strncmp(buf, "0x", 2) == 0) - op->disp = parse_imm(buf, &p, 16); - - if (*p == '(') { - p++; - - if (*p == '%') { - p++; - - int n = parse_reg(op, op_base, p); - if (n <= 0) - return -3; - p += n; - } - - if (*p == ',') { - p++; - - if (*p == '%') { - int n = parse_reg(op, op_index, ++p); - if (n <= 0) - return -4; - p += n; - - if (*p != ',') - return -5; - p++; - - goto do_parse_scale; - } - else if (isdigit(*p)) { - do_parse_scale: - long val = strtol(p, &p, 10); - if (val == 0 && errno == EINVAL) - abort(); - op->scale = val; - } - } - - if (*p != ')') - return -6; - p++; - } - - return p - buf; -} - -static void parse_insn(insn_t *ii, char *buf) -{ - char *p = buf; - ii->clear(); - -#if 0 - printf("BUF: %s\n", buf); -#endif - - if (strncmp(p, "rex64", 5) == 0) { - char *q = find_blanks(p); - if (verbose > 1) { - char prefix[16]; - memset(prefix, 0, sizeof(prefix)); - memcpy(prefix, p, q - p); - fprintf(stderr, "Instruction '%s', skip REX prefix '%s'\n", buf, prefix); - } - p = skip_blanks(q); - } - - if (strncmp(p, "rep", 3) == 0) { - char *q = find_blanks(p); - if (verbose > 1) { - char prefix[16]; - memset(prefix, 0, sizeof(prefix)); - memcpy(prefix, p, q - p); - fprintf(stderr, "Instruction '%s', skip REP prefix '%s'\n", buf, prefix); - } - p = skip_blanks(q); - } - - for (int i = 0; !isspace(*p); i++) - ii->name[i] = *p++; - - while (*p && isspace(*p)) - p++; - if (*p == '\0') - return; - - int n_operands = 0; - int optype = op_reg; - bool done = false; - while (!done) { - int n; - switch (*p) { - case '%': - n = parse_reg(&ii->operands[n_operands], optype, ++p); - if (n <= 0) { - fprintf(stderr, "parse_reg(%s) error %d\n", p, n); - abort(); - } - p += n; - break; - case '0': case '(': - n = parse_mem(&ii->operands[n_operands], p); - if (n <= 0) { - fprintf(stderr, "parse_mem(%s) error %d\n", p, n); - abort(); - } - p += n; - break; - case '$': { - ii->operands[n_operands].imm = parse_imm(++p, &p, 0); - break; - } - case '*': - p++; - break; - case ',': - n_operands++; - p++; - break; - case ' ': case '\t': - p++; - break; - case '\0': - done = true; - break; - default: - fprintf(stderr, "parse error> %s\n", p); - abort(); - } - } - ii->n_operands = n_operands + 1; -} - -static unsigned long n_tests, n_failures; -static unsigned long n_all_tests, n_all_failures; - -static bool check_unary(insn_t *ii, const char *name) -{ - if (strcasecmp(ii->name, name) != 0) { - fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); - return false; - } - - if (ii->n_operands != 0) { - fprintf(stderr, "ERROR: instruction expected 0 operand, got %d\n", ii->n_operands); - return false; - } - - return true; -} - -static bool check_reg(insn_t *ii, const char *name, int r) -{ - if (strcasecmp(ii->name, name) != 0) { - fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); - return false; - } - - if (ii->n_operands != 1) { - fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands); - return false; - } - - int reg = ii->operands[0].reg; - - if (reg != r) { - fprintf(stderr, "ERROR: instruction expected r%d as source, got ", r); - if (reg == -1) - fprintf(stderr, "nothing\n"); - else - fprintf(stderr, "r%d\n", reg); - return false; - } - - return true; -} - -static bool check_reg_reg(insn_t *ii, const char *name, int s, int d) -{ - if (strcasecmp(ii->name, name) != 0) { - fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); - return false; - } - - if (ii->n_operands != 2) { - fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands); - return false; - } - - int srcreg = ii->operands[0].reg; - int dstreg = ii->operands[1].reg; - - if (srcreg != s) { - fprintf(stderr, "ERROR: instruction expected r%d as source, got ", s); - if (srcreg == -1) - fprintf(stderr, "nothing\n"); - else - fprintf(stderr, "r%d\n", srcreg); - return false; - } - - if (dstreg != d) { - fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d); - if (dstreg == -1) - fprintf(stderr, "nothing\n"); - else - fprintf(stderr, "r%d\n", dstreg); - return false; - } - - return true; -} - -static bool check_imm_reg(insn_t *ii, const char *name, uint32 v, int d, int mode = -1) -{ - if (strcasecmp(ii->name, name) != 0) { - fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); - return false; - } - - if (ii->n_operands != 2) { - fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands); - return false; - } - - uint32 imm = ii->operands[0].imm; - int dstreg = ii->operands[1].reg; - - if (mode == -1) { - char suffix = name[strlen(name) - 1]; - switch (suffix) { - case 'b': mode = 1; break; - case 'w': mode = 2; break; - case 'l': mode = 4; break; - case 'q': mode = 8; break; - } - } - switch (mode) { - case 1: v &= 0xff; break; - case 2: v &= 0xffff; break; - } - - if (imm != v) { - fprintf(stderr, "ERROR: instruction expected 0x%08x as immediate, got ", v); - if (imm == -1) - fprintf(stderr, "nothing\n"); - else - fprintf(stderr, "0x%08x\n", imm); - return false; - } - - if (dstreg != d) { - fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d); - if (dstreg == -1) - fprintf(stderr, "nothing\n"); - else - fprintf(stderr, "%d\n", dstreg); - return false; - } - - return true; -} - -static bool do_check_mem(insn_t *ii, uint32 D, int B, int I, int S, int Mpos) -{ - operand_t *mem = &ii->operands[Mpos]; - uint32 d = mem->disp; - int b = mem->base; - int i = mem->index; - int s = mem->scale; - - if (d != D) { - fprintf(stderr, "ERROR: instruction expected 0x%08x as displacement, got 0x%08x\n", D, d); - return false; - } - - if (b != B) { - fprintf(stderr, "ERROR: instruction expected r%d as base, got r%d\n", B, b); - return false; - } - - if (i != I) { - fprintf(stderr, "ERROR: instruction expected r%d as index, got r%d\n", I, i); - return false; - } - - if (s != S) { - fprintf(stderr, "ERROR: instruction expected %d as scale factor, got %d\n", S, s); - return false; - } - - return true; -} - -static bool check_mem(insn_t *ii, const char *name, uint32 D, int B, int I, int S) -{ - if (strcasecmp(ii->name, name) != 0) { - fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); - return false; - } - - if (ii->n_operands != 1) { - fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands); - return false; - } - - return do_check_mem(ii, D, B, I, S, 0); -} - -static bool check_mem_reg(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R, int Rpos = 1) -{ - if (strcasecmp(ii->name, name) != 0) { - fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); - return false; - } - - if (ii->n_operands != 2) { - fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands); - return false; - } - - if (!do_check_mem(ii, D, B, I, S, Rpos ^ 1)) - return false; - - int r = ii->operands[Rpos].reg; - - if (r != R) { - fprintf(stderr, "ERROR: instruction expected r%d as reg operand, got r%d\n", R, r); - return false; - } - - return true; -} - -static inline bool check_reg_mem(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R) -{ - return check_mem_reg(ii, name, D, B, I, S, R, 0); -} - -static void show_instruction(const char *buffer, const uint8 *bytes) -{ - if (verbose > 1) { - if (1) { - for (int j = 0; j < MAX_INSN_LENGTH; j++) - fprintf(stderr, "%02x ", bytes[j]); - fprintf(stderr, "| "); - } - fprintf(stderr, "%s\n", buffer); - } -} - -static void show_status(unsigned long n_tests) -{ -#if 1 - const unsigned long N_STEPS = 100000; - static const char cursors[] = { '-', '\\', '|', '/' }; - if ((n_tests % N_STEPS) == 0) { - printf(" %c (%d)\r", cursors[(n_tests/N_STEPS)%sizeof(cursors)], n_tests); - fflush(stdout); - } -#else - const unsigned long N_STEPS = 1000000; - if ((n_tests % N_STEPS) == 0) - printf(" ... %d\n", n_tests); -#endif -} - -int main(void) -{ - static char buffer[1024]; - static uint8 block[MAX_INSNS * MAX_INSN_LENGTH]; - static char *insns[MAX_INSNS]; - static int modes[MAX_INSNS]; - n_all_tests = n_all_failures = 0; - -#if TEST_INST_ALU_REG - printf("Testing reg forms\n"); - n_tests = n_failures = 0; - for (int r = 0; r < X86_MAX_ALU_REGS; r++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##r(r); \ -} while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ -} while (0) -#define GENA(INSN, GENOP) do { \ - if (VALID_REG8(r)) \ - GEN(INSN "b", GENOP##B); \ - GEN(INSN "w", GENOP##W); \ - GEN(INSN "l", GENOP##L); \ - GEN64(INSN "q", GENOP##Q); \ -} while (0) - GENA("not", NOT); - GENA("neg", NEG); - GENA("mul", MUL); - GENA("imul", IMUL); - GENA("div", DIV); - GENA("idiv", IDIV); - GENA("dec", DEC); - GENA("inc", INC); - if (X86_TARGET_64BIT) { - GEN("callq", CALLs); - GEN("jmpq", JMPs); - GEN("pushq", PUSHQ); - GEN("popq", POPQ); - } - else { - GEN("calll", CALLs); - GEN("jmpl", JMPs); - GEN("pushl", PUSHL); - GEN("popl", POPL); - } - GEN("bswap", BSWAPL); // FIXME: disass bug? no suffix - GEN64("bswap", BSWAPQ); // FIXME: disass bug? no suffix - if (VALID_REG8(r)) { - GEN("seto", SETO); - GEN("setno", SETNO); - GEN("setb", SETB); - GEN("setae", SETAE); - GEN("sete", SETE); - GEN("setne", SETNE); - GEN("setbe", SETBE); - GEN("seta", SETA); - GEN("sets", SETS); - GEN("setns", SETNS); - GEN("setp", SETP); - GEN("setnp", SETNP); - GEN("setl", SETL); - GEN("setge", SETGE); - GEN("setle", SETLE); - GEN("setg", SETG); - } -#undef GENA -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_reg(&ii, insns[i], r)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_ALU_REG_REG - printf("Testing reg,reg forms\n"); - n_tests = n_failures = 0; - for (int s = 0; s < X86_MAX_ALU_REGS; s++) { - for (int d = 0; d < X86_MAX_ALU_REGS; d++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##rr(s, d); \ -} while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ -} while (0) -#define GEN1(INSN, GENOP, OP) do { \ - insns[i++] = INSN; \ - GENOP##rr(OP, s, d); \ -} while (0) -#define GENA(INSN, GENOP) do { \ - if (VALID_REG8(s) && VALID_REG8(d)) \ - GEN(INSN "b", GENOP##B); \ - GEN(INSN "w", GENOP##W); \ - GEN(INSN "l", GENOP##L); \ - GEN64(INSN "q", GENOP##Q); \ -} while (0) - GENA("adc", ADC); - GENA("add", ADD); - GENA("and", AND); - GENA("cmp", CMP); - GENA("or", OR); - GENA("sbb", SBB); - GENA("sub", SUB); - GENA("xor", XOR); - GENA("mov", MOV); - GEN("btw", BTW); - GEN("btl", BTL); - GEN64("btq", BTQ); - GEN("btcw", BTCW); - GEN("btcl", BTCL); - GEN64("btcq", BTCQ); - GEN("btrw", BTRW); - GEN("btrl", BTRL); - GEN64("btrq", BTRQ); - GEN("btsw", BTSW); - GEN("btsl", BTSL); - GEN64("btsq", BTSQ); - GEN("imulw", IMULW); - GEN("imull", IMULL); - GEN64("imulq", IMULQ); - GEN1("cmove", CMOVW, X86_CC_Z); - GEN1("cmove", CMOVL, X86_CC_Z); - if (X86_TARGET_64BIT) - GEN1("cmove", CMOVQ, X86_CC_Z); - GENA("test", TEST); - GENA("cmpxchg", CMPXCHG); - GENA("xadd", XADD); - GENA("xchg", XCHG); - GEN("bsfw", BSFW); - GEN("bsfl", BSFL); - GEN64("bsfq", BSFQ); - GEN("bsrw", BSRW); - GEN("bsrl", BSRL); - GEN64("bsrq", BSRQ); - if (VALID_REG8(s)) { - GEN("movsbw", MOVSBW); - GEN("movsbl", MOVSBL); - GEN64("movsbq", MOVSBQ); - GEN("movzbw", MOVZBW); - GEN("movzbl", MOVZBL); - GEN64("movzbq", MOVZBQ); - } - GEN("movswl", MOVSWL); - GEN64("movswq", MOVSWQ); - GEN("movzwl", MOVZWL); - GEN64("movzwq", MOVZWQ); - GEN64("movslq", MOVSLQ); -#undef GENA -#undef GEN1 -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_reg_reg(&ii, insns[i], s, d)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_ALU_CNT_REG - printf("Testing cl,reg forms\n"); - n_tests = n_failures = 0; - for (int d = 0; d < X86_MAX_ALU_REGS; d++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##rr(X86_CL, d); \ -} while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ -} while (0) -#define GENA(INSN, GENOP) do { \ - if (VALID_REG8(d)) \ - GEN(INSN "b", GENOP##B); \ - GEN(INSN "w", GENOP##W); \ - GEN(INSN "l", GENOP##L); \ - GEN64(INSN "q", GENOP##Q); \ -} while (0) - GENA("rol", ROL); - GENA("ror", ROR); - GENA("rcl", RCL); - GENA("rcr", RCR); - GENA("shl", SHL); - GENA("shr", SHR); - GENA("sar", SAR); -#undef GENA -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_reg_reg(&ii, insns[i], X86_CL, d)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - - static const uint32 imm_table[] = { - 0x00000000, 0x00000001, 0x00000002, 0x00000004, - 0x00000008, 0x00000010, 0x00000020, 0x00000040, - 0x00000080, 0x000000fe, 0x000000ff, 0x00000100, - 0x00000101, 0x00000102, 0xfffffffe, 0xffffffff, - 0x00000000, 0x10000000, 0x20000000, 0x30000000, - 0x40000000, 0x50000000, 0x60000000, 0x70000000, - 0x80000000, 0x90000000, 0xa0000000, 0xb0000000, - 0xc0000000, 0xd0000000, 0xe0000000, 0xf0000000, - 0xfffffffd, 0xfffffffe, 0xffffffff, 0x00000001, - 0x00000002, 0x00000003, 0x11111111, 0x22222222, - 0x33333333, 0x44444444, 0x55555555, 0x66666666, - 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa, - 0xbbbbbbbb, 0xcccccccc, 0xdddddddd, 0xeeeeeeee, - }; - const int n_imm_tab_count = sizeof(imm_table)/sizeof(imm_table[0]); - -#if TEST_INST_ALU_IMM_REG - printf("Testing imm,reg forms\n"); - n_tests = n_failures = 0; - for (int j = 0; j < n_imm_tab_count; j++) { - const uint32 value = imm_table[j]; - for (int d = 0; d < X86_MAX_ALU_REGS; d++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = -1; \ - i++; GENOP##ir(value, d); \ - } while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ - } while (0) -#define GENM(INSN, GENOP, MODE) do { \ - insns[i] = INSN; \ - modes[i] = MODE; \ - i++; GENOP##ir(value, d); \ - } while (0) -#define GENM64(INSN, GENOP, MODE) do { \ - if (X86_TARGET_64BIT) \ - GENM(INSN, GENOP, MODE); \ - } while (0) -#define GENA(INSN, GENOP) do { \ - if (VALID_REG8(d)) \ - GEN(INSN "b", GENOP##B); \ - GEN(INSN "w", GENOP##W); \ - GEN(INSN "l", GENOP##L); \ - GEN64(INSN "q", GENOP##Q); \ - } while (0) -#define GENAM(INSN, GENOP, MODE) do { \ - if (VALID_REG8(d)) \ - GENM(INSN "b", GENOP##B, MODE); \ - GENM(INSN "w", GENOP##W, MODE); \ - GENM(INSN "l", GENOP##L, MODE); \ - GENM64(INSN "q", GENOP##Q, MODE); \ - } while (0) - GENA("adc", ADC); - GENA("add", ADD); - GENA("and", AND); - GENA("cmp", CMP); - GENA("or", OR); - GENA("sbb", SBB); - GENA("sub", SUB); - GENA("xor", XOR); - GENA("mov", MOV); - GENM("btw", BTW, 1); - GENM("btl", BTL, 1); - GENM64("btq", BTQ, 1); - GENM("btcw", BTCW, 1); - GENM("btcl", BTCL, 1); - GENM64("btcq", BTCQ, 1); - GENM("btrw", BTRW, 1); - GENM("btrl", BTRL, 1); - GENM64("btrq", BTRQ, 1); - GENM("btsw", BTSW, 1); - GENM("btsl", BTSL, 1); - GENM64("btsq", BTSQ, 1); - if (value != 1) { - GENAM("rol", ROL, 1); - GENAM("ror", ROR, 1); - GENAM("rcl", RCL, 1); - GENAM("rcr", RCR, 1); - GENAM("shl", SHL, 1); - GENAM("shr", SHR, 1); - GENAM("sar", SAR, 1); - } - GENA("test", TEST); -#undef GENAM -#undef GENA -#undef GENM64 -#undef GENM -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - - static const uint32 off_table[] = { - 0x00000000, - 0x00000001, - 0x00000040, - 0x00000080, - 0x000000ff, - 0x00000100, - 0xfffffffe, - 0xffffffff, - }; - const int off_table_count = sizeof(off_table) / sizeof(off_table[0]); - -#if TEST_INST_ALU_MEM_REG - printf("Testing mem,reg forms\n"); - n_tests = n_failures = 0; - for (int d = 0; d < off_table_count; d++) { - const uint32 D = off_table[d]; - for (int B = -1; B < X86_MAX_ALU_REGS; B++) { - for (int I = -1; I < X86_MAX_ALU_REGS; I++) { - if (I == X86_RSP) - continue; - for (int S = 1; S < 16; S *= 2) { - if (I == -1 && S > 1) - continue; - for (int r = 0; r < X86_MAX_ALU_REGS; r++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##mr(D, B, I, S, r); \ - } while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ - } while (0) -#define GENA(INSN, GENOP) do { \ - if (VALID_REG8(r)) \ - GEN(INSN "b", GENOP##B); \ - GEN(INSN "w", GENOP##W); \ - GEN(INSN "l", GENOP##L); \ - GEN64(INSN "q", GENOP##Q); \ - } while (0) - GENA("adc", ADC); - GENA("add", ADD); - GENA("and", AND); - GENA("cmp", CMP); - GENA("or", OR); - GENA("sbb", SBB); - GENA("sub", SUB); - GENA("xor", XOR); - GENA("mov", MOV); - GEN("imulw", IMULW); - GEN("imull", IMULL); - GEN64("imulq", IMULQ); - GEN("bsfw", BSFW); - GEN("bsfl", BSFL); - GEN64("bsfq", BSFQ); - GEN("bsrw", BSRW); - GEN("bsrl", BSRL); - GEN64("bsrq", BSRQ); - GEN("movsbw", MOVSBW); - GEN("movsbl", MOVSBL); - GEN64("movsbq", MOVSBQ); - GEN("movzbw", MOVZBW); - GEN("movzbl", MOVZBL); - GEN64("movzbq", MOVZBQ); - GEN("movswl", MOVSWL); - GEN64("movswq", MOVSWQ); - GEN("movzwl", MOVZWL); - GEN64("movzwq", MOVZWQ); - GEN64("movslq", MOVSLQ); -#undef GENA -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - show_status(n_tests); - } - if (i != last_insn) - abort(); - } - } - } - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_FPU_UNARY - printf("Testing FPU unary forms\n"); - n_tests = n_failures = 0; - { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP(); \ -} while (0) - GEN("f2xm1", F2XM1); - GEN("fabs", FABS); - GEN("fchs", FCHS); - GEN("fcompp", FCOMPP); - GEN("fcos", FCOS); - GEN("fdecstp", FDECSTP); - GEN("fincstp", FINCSTP); - GEN("fld1", FLD1); - GEN("fldl2t", FLDL2T); - GEN("fldl2e", FLDL2E); - GEN("fldpi", FLDPI); - GEN("fldlg2", FLDLG2); - GEN("fldln2", FLDLN2); - GEN("fldz", FLDZ); - GEN("fnop", FNOP); - GEN("fpatan", FPATAN); - GEN("fprem", FPREM); - GEN("fprem1", FPREM1); - GEN("fptan", FPTAN); - GEN("frndint", FRNDINT); - GEN("fscale", FSCALE); - GEN("fsin", FSIN); - GEN("fsincos", FSINCOS); - GEN("fsqrt", FSQRT); - GEN("ftst", FTST); - GEN("fucompp", FUCOMPP); - GEN("fxam", FXAM); - GEN("fxtract", FXTRACT); - GEN("fyl2x", FYL2X); - GEN("fyl2xp1", FYL2XP1); -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_unary(&ii, insns[i])) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_FPU_REG - printf("Testing FPU reg forms\n"); - n_tests = n_failures = 0; - for (int r = 0; r < X86_MAX_FPU_REGS; r++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GENr(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = 0; \ - i++, GENOP##r(r); \ -} while (0) -#define GENr0(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = 1; \ - i++, GENOP##r0(r); \ -} while (0) -#define GEN0r(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = 2; \ - i++, GENOP##0r(r); \ -} while (0) - GENr("fcom", FCOM); - GENr("fcomp", FCOMP); - GENr("ffree", FFREE); - GENr("fxch", FXCH); - GENr("fst", FST); - GENr("fstp", FSTP); - GENr("fucom", FUCOM); - GENr("fucomp", FUCOMP); - GENr0("fadd", FADD); - GENr0("fcmovb", FCMOVB); - GENr0("fcmove", FCMOVE); - GENr0("fcmovbe", FCMOVBE); - GENr0("fcmovu", FCMOVU); - GENr0("fcmovnb", FCMOVNB); - GENr0("fcmovne", FCMOVNE); - GENr0("fcmovnbe", FCMOVNBE); - GENr0("fcmovnu", FCMOVNU); - GENr0("fcomi", FCOMI); - GENr0("fcomip", FCOMIP); - GENr0("fucomi", FUCOMI); - GENr0("fucomip", FUCOMIP); - GENr0("fdiv", FDIV); - GENr0("fdivr", FDIVR); - GENr0("fmul", FMUL); - GENr0("fsub", FSUB); - GENr0("fsubr", FSUBR); -#undef GEN0r -#undef GENr0 -#undef GENr - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - switch (modes[i]) { - case 0: - if (!check_reg(&ii, insns[i], r)) { - show_instruction(buffer, p); - n_failures++; - } - break; - case 1: - if (!check_reg_reg(&ii, insns[i], r, 0)) { - show_instruction(buffer, p); - n_failures++; - } - break; - case 2: - if (!check_reg_reg(&ii, insns[i], 0, r)) { - show_instruction(buffer, p); - n_failures++; - } - break; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_FPU_MEM - printf("Testing FPU mem forms\n"); - n_tests = n_failures = 0; - for (int d = 0; d < off_table_count; d++) { - const uint32 D = off_table[d]; - for (int B = -1; B < X86_MAX_ALU_REGS; B++) { - for (int I = -1; I < X86_MAX_ALU_REGS; I++) { - if (I == X86_RSP) - continue; - for (int S = 1; S < 16; S *= 2) { - if (I == -1 && S > 1) - continue; - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##m(D, B, I, S); \ -} while (0) - GEN("fadds", FADDS); - GEN("faddl", FADDD); - GEN("fiadd", FIADDW); - GEN("fiaddl", FIADDL); - GEN("fbld", FBLD); - GEN("fbstp", FBSTP); - GEN("fcoms", FCOMS); - GEN("fcoml", FCOMD); - GEN("fcomps", FCOMPS); - GEN("fcompl", FCOMPD); - GEN("fdivs", FDIVS); - GEN("fdivl", FDIVD); - GEN("fidiv", FIDIVW); - GEN("fidivl", FIDIVL); - GEN("fdivrs", FDIVRS); - GEN("fdivrl", FDIVRD); - GEN("fidivr", FIDIVRW); - GEN("fidivrl", FIDIVRL); - GEN("ficom", FICOMW); - GEN("ficoml", FICOML); - GEN("ficomp", FICOMPW); - GEN("ficompl", FICOMPL); - GEN("fild", FILDW); - GEN("fildl", FILDL); - GEN("fildll", FILDQ); - GEN("fist", FISTW); - GEN("fistl", FISTL); - GEN("fistp", FISTPW); - GEN("fistpl", FISTPL); - GEN("fistpll", FISTPQ); - GEN("fisttp", FISTTPW); - GEN("fisttpl", FISTTPL); - GEN("fisttpll", FISTTPQ); - GEN("flds", FLDS); - GEN("fldl", FLDD); - GEN("fldt", FLDT); - GEN("fmuls", FMULS); - GEN("fmull", FMULD); - GEN("fimul", FIMULW); - GEN("fimull", FIMULL); - GEN("fsts", FSTS); - GEN("fstl", FSTD); - GEN("fstps", FSTPS); - GEN("fstpl", FSTPD); - GEN("fstpt", FSTPT); - GEN("fsubs", FSUBS); - GEN("fsubl", FSUBD); - GEN("fisub", FISUBW); - GEN("fisubl", FISUBL); - GEN("fsubrs", FSUBRS); - GEN("fsubrl", FSUBRD); - GEN("fisubr", FISUBRW); - GEN("fisubrl", FISUBRL); -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_mem(&ii, insns[i], D, B, I, S)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - show_status(n_tests); - } - if (i != last_insn) - abort(); - } - } - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_MMX_REG_REG - printf("Testing MMX reg,reg forms\n"); - n_tests = n_failures = 0; - for (int s = 0; s < X86_MAX_MMX_REGS; s++) { - for (int d = 0; d < X86_MAX_MMX_REGS; d++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - MMX_##GENOP##rr(s, d); \ -} while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ -} while (0) - GEN("movq", MOVQ); - GEN("packsswb", PACKSSWB); - GEN("packssdw", PACKSSDW); - GEN("packuswb", PACKUSWB); - GEN("paddb", PADDB); - GEN("paddw", PADDW); - GEN("paddd", PADDD); - GEN("paddq", PADDQ); - GEN("paddsb", PADDSB); - GEN("paddsw", PADDSW); - GEN("paddusb", PADDUSB); - GEN("paddusw", PADDUSW); - GEN("pand", PAND); - GEN("pandn", PANDN); - GEN("pavgb", PAVGB); - GEN("pavgw", PAVGW); - GEN("pcmpeqb", PCMPEQB); - GEN("pcmpeqw", PCMPEQW); - GEN("pcmpeqd", PCMPEQD); - GEN("pcmpgtb", PCMPGTB); - GEN("pcmpgtw", PCMPGTW); - GEN("pcmpgtd", PCMPGTD); - GEN("pmaddwd", PMADDWD); - GEN("pmaxsw", PMAXSW); - GEN("pmaxub", PMAXUB); - GEN("pminsw", PMINSW); - GEN("pminub", PMINUB); - GEN("pmulhuw", PMULHUW); - GEN("pmulhw", PMULHW); - GEN("pmullw", PMULLW); - GEN("pmuludq", PMULUDQ); - GEN("por", POR); - GEN("psadbw", PSADBW); - GEN("psllw", PSLLW); - GEN("pslld", PSLLD); - GEN("psllq", PSLLQ); - GEN("psraw", PSRAW); - GEN("psrad", PSRAD); - GEN("psrlw", PSRLW); - GEN("psrld", PSRLD); - GEN("psrlq", PSRLQ); - GEN("psubb", PSUBB); - GEN("psubw", PSUBW); - GEN("psubd", PSUBD); - GEN("psubq", PSUBQ); - GEN("psubsb", PSUBSB); - GEN("psubsw", PSUBSW); - GEN("psubusb", PSUBUSB); - GEN("psubusw", PSUBUSW); - GEN("punpckhbw", PUNPCKHBW); - GEN("punpckhwd", PUNPCKHWD); - GEN("punpckhdq", PUNPCKHDQ); - GEN("punpcklbw", PUNPCKLBW); - GEN("punpcklwd", PUNPCKLWD); - GEN("punpckldq", PUNPCKLDQ); - GEN("pxor", PXOR); - GEN("pabsb", PABSB); - GEN("pabsw", PABSW); - GEN("pabsd", PABSD); - GEN("phaddw", PHADDW); - GEN("phaddd", PHADDD); - GEN("phaddsw", PHADDSW); - GEN("phsubw", PHSUBW); - GEN("phsubd", PHSUBD); - GEN("phsubsw", PHSUBSW); - GEN("pmaddubsw", PMADDUBSW); - GEN("pmulhrsw", PMULHRSW); - GEN("pshufb", PSHUFB); - GEN("psignb", PSIGNB); - GEN("psignw", PSIGNW); - GEN("psignd", PSIGND); -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_reg_reg(&ii, insns[i], s, d)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - - static const uint8 imm8_table[] = { - 0x00, 0x01, 0x02, 0x03, - 0x06, 0x07, 0x08, 0x09, - 0x0e, 0x0f, 0x10, 0x11, - 0x1e, 0x1f, 0x20, 0x21, - 0xfc, 0xfd, 0xfe, 0xff, - }; - const int n_imm8_tab_count = sizeof(imm8_table)/sizeof(imm8_table[0]); - -#if TEST_INST_MMX_IMM_REG - printf("Testing imm,reg forms\n"); - n_tests = n_failures = 0; - for (int j = 0; j < n_imm8_tab_count; j++) { - const uint8 value = imm8_table[j]; - for (int d = 0; d < X86_MAX_MMX_REGS; d++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = 1; \ - i++; MMX_##GENOP##ir(value, d); \ -} while (0) - GEN("psllw", PSLLW); - GEN("pslld", PSLLD); - GEN("psllq", PSLLQ); - GEN("psraw", PSRAW); - GEN("psrad", PSRAD); - GEN("psrlw", PSRLW); - GEN("psrld", PSRLD); - GEN("psrlq", PSRLQ); -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_MMX_MEM_REG - printf("Testing MMX mem,reg forms\n"); - n_tests = n_failures = 0; - for (int d = 0; d < off_table_count; d++) { - const uint32 D = off_table[d]; - for (int B = -1; B < X86_MAX_ALU_REGS; B++) { - for (int I = -1; I < X86_MAX_ALU_REGS; I++) { - if (I == X86_RSP) - continue; - for (int S = 1; S < 16; S *= 2) { - if (I == -1 && S > 1) - continue; - for (int r = 0; r < X86_MAX_MMX_REGS; r++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define _GENrm(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = 0; \ - i++; MMX_##GENOP##rm(r, D, B, I, S); \ -} while (0) -#define _GENmr(INSN, GENOP) do { \ - insns[i] = INSN; \ - modes[i] = 1; \ - i++; MMX_##GENOP##mr(D, B, I, S, r); \ -} while (0) -#define GEN(INSN, GENOP) do { \ - _GENmr(INSN, GENOP); \ -} while (0) - _GENmr("movd", MOVD); - _GENrm("movd", MOVD); - _GENmr("movq", MOVQ); - _GENrm("movq", MOVQ); - GEN("packsswb", PACKSSWB); - GEN("packssdw", PACKSSDW); - GEN("packuswb", PACKUSWB); - GEN("paddb", PADDB); - GEN("paddw", PADDW); - GEN("paddd", PADDD); - GEN("paddq", PADDQ); - GEN("paddsb", PADDSB); - GEN("paddsw", PADDSW); - GEN("paddusb", PADDUSB); - GEN("paddusw", PADDUSW); - GEN("pand", PAND); - GEN("pandn", PANDN); - GEN("pavgb", PAVGB); - GEN("pavgw", PAVGW); - GEN("pcmpeqb", PCMPEQB); - GEN("pcmpeqw", PCMPEQW); - GEN("pcmpeqd", PCMPEQD); - GEN("pcmpgtb", PCMPGTB); - GEN("pcmpgtw", PCMPGTW); - GEN("pcmpgtd", PCMPGTD); - GEN("pmaddwd", PMADDWD); - GEN("pmaxsw", PMAXSW); - GEN("pmaxub", PMAXUB); - GEN("pminsw", PMINSW); - GEN("pminub", PMINUB); - GEN("pmulhuw", PMULHUW); - GEN("pmulhw", PMULHW); - GEN("pmullw", PMULLW); - GEN("pmuludq", PMULUDQ); - GEN("por", POR); - GEN("psadbw", PSADBW); - GEN("psllw", PSLLW); - GEN("pslld", PSLLD); - GEN("psllq", PSLLQ); - GEN("psraw", PSRAW); - GEN("psrad", PSRAD); - GEN("psrlw", PSRLW); - GEN("psrld", PSRLD); - GEN("psrlq", PSRLQ); - GEN("psubb", PSUBB); - GEN("psubw", PSUBW); - GEN("psubd", PSUBD); - GEN("psubq", PSUBQ); - GEN("psubsb", PSUBSB); - GEN("psubsw", PSUBSW); - GEN("psubusb", PSUBUSB); - GEN("psubusw", PSUBUSW); - GEN("punpckhbw", PUNPCKHBW); - GEN("punpckhwd", PUNPCKHWD); - GEN("punpckhdq", PUNPCKHDQ); - GEN("punpcklbw", PUNPCKLBW); - GEN("punpcklwd", PUNPCKLWD); - GEN("punpckldq", PUNPCKLDQ); - GEN("pxor", PXOR); - GEN("pabsb", PABSB); - GEN("pabsw", PABSW); - GEN("pabsd", PABSD); - GEN("phaddw", PHADDW); - GEN("phaddd", PHADDD); - GEN("phaddsw", PHADDSW); - GEN("phsubw", PHSUBW); - GEN("phsubd", PHSUBD); - GEN("phsubsw", PHSUBSW); - GEN("pmaddubsw", PMADDUBSW); - GEN("pmulhrsw", PMULHRSW); - GEN("pshufb", PSHUFB); - GEN("psignb", PSIGNB); - GEN("psignw", PSIGNW); - GEN("psignd", PSIGND); -#undef GEN -#undef _GENmr -#undef _GENrm - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_mem_reg(&ii, insns[i], D, B, I, S, r, modes[i])) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - show_status(n_tests); - } - if (i != last_insn) - abort(); - } - } - } - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_SSE_REG_REG - printf("Testing SSE reg,reg forms\n"); - n_tests = n_failures = 0; - for (int s = 0; s < X86_MAX_SSE_REGS; s++) { - for (int d = 0; d < X86_MAX_SSE_REGS; d++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##rr(s, d); \ -} while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ -} while (0) -#define GEN1(INSN, GENOP) do { \ - GEN(INSN "s", GENOP##S); \ - GEN(INSN "d", GENOP##D); \ -} while (0) -#define GENA(INSN, GENOP) do { \ - GEN1(INSN "s", GENOP##S); \ - GEN1(INSN "p", GENOP##P); \ -} while (0) -#define GENI(INSN, GENOP, IMM) do { \ - insns[i++] = INSN; \ - GENOP##rr(IMM, s, d); \ -} while (0) -#define GENI1(INSN, GENOP, IMM) do { \ - GENI(INSN "s", GENOP##S, IMM); \ - GENI(INSN "d", GENOP##D, IMM); \ -} while (0) -#define GENIA(INSN, GENOP, IMM) do { \ - GENI1(INSN "s", GENOP##S, IMM); \ - GENI1(INSN "p", GENOP##P, IMM); \ -} while (0) - GEN1("andp", ANDP); - GEN1("andnp", ANDNP); - GEN1("orp", ORP); - GEN1("xorp", XORP); - GENA("add", ADD); - GENA("sub", SUB); - GENA("mul", MUL); - GENA("div", DIV); - GEN1("comis", COMIS); - GEN1("ucomis", UCOMIS); - GENA("min", MIN); - GENA("max", MAX); - GEN("rcpss", RCPSS); - GEN("rcpps", RCPPS); - GEN("rsqrtss", RSQRTSS); - GEN("rsqrtps", RSQRTPS); - GENA("sqrt", SQRT); - GENIA("cmpeq", CMP, X86_SSE_CC_EQ); - GENIA("cmplt", CMP, X86_SSE_CC_LT); - GENIA("cmple", CMP, X86_SSE_CC_LE); - GENIA("cmpunord", CMP, X86_SSE_CC_U); - GENIA("cmpneq", CMP, X86_SSE_CC_NEQ); - GENIA("cmpnlt", CMP, X86_SSE_CC_NLT); - GENIA("cmpnle", CMP, X86_SSE_CC_NLE); - GENIA("cmpord", CMP, X86_SSE_CC_O); - GEN1("movap", MOVAP); - GEN("movdqa", MOVDQA); - GEN("movdqu", MOVDQU); - GEN("movd", MOVDXD); - GEN64("movd", MOVQXD); // FIXME: disass bug? "movq" expected - GEN("movd", MOVDXS); - GEN64("movd", MOVQXS); // FIXME: disass bug? "movq" expected - GEN("cvtdq2pd", CVTDQ2PD); - GEN("cvtdq2ps", CVTDQ2PS); - GEN("cvtpd2dq", CVTPD2DQ); - GEN("cvtpd2ps", CVTPD2PS); - GEN("cvtps2dq", CVTPS2DQ); - GEN("cvtps2pd", CVTPS2PD); - GEN("cvtsd2si", CVTSD2SIL); - GEN64("cvtsd2siq", CVTSD2SIQ); - GEN("cvtsd2ss", CVTSD2SS); - GEN("cvtsi2sd", CVTSI2SDL); - GEN64("cvtsi2sdq", CVTSI2SDQ); - GEN("cvtsi2ss", CVTSI2SSL); - GEN64("cvtsi2ssq", CVTSI2SSQ); - GEN("cvtss2sd", CVTSS2SD); - GEN("cvtss2si", CVTSS2SIL); - GEN64("cvtss2siq", CVTSS2SIQ); - GEN("cvttpd2dq", CVTTPD2DQ); - GEN("cvttps2dq", CVTTPS2DQ); - GEN("cvttsd2si", CVTTSD2SIL); - GEN64("cvttsd2siq", CVTTSD2SIQ); - GEN("cvttss2si", CVTTSS2SIL); - GEN64("cvttss2siq", CVTTSS2SIQ); - if (s < 8) { - // MMX source register - GEN("cvtpi2pd", CVTPI2PD); - GEN("cvtpi2ps", CVTPI2PS); - } - if (d < 8) { - // MMX dest register - GEN("cvtpd2pi", CVTPD2PI); - GEN("cvtps2pi", CVTPS2PI); - GEN("cvttpd2pi", CVTTPD2PI); - GEN("cvttps2pi", CVTTPS2PI); - } -#undef GENIA -#undef GENI1 -#undef GENI -#undef GENA -#undef GEN1 -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_reg_reg(&ii, insns[i], s, d)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - } - if (i != last_insn) - abort(); - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - -#if TEST_INST_SSE_MEM_REG - printf("Testing SSE mem,reg forms\n"); - n_tests = n_failures = 0; - for (int d = 0; d < off_table_count; d++) { - const uint32 D = off_table[d]; - for (int B = -1; B < X86_MAX_ALU_REGS; B++) { - for (int I = -1; I < X86_MAX_ALU_REGS; I++) { - if (I == X86_RSP) - continue; - for (int S = 1; S < 16; S *= 2) { - if (I == -1 && S > 1) - continue; - for (int r = 0; r < X86_MAX_SSE_REGS; r++) { - set_target(block); - uint8 *b = get_target(); - int i = 0; -#define GEN(INSN, GENOP) do { \ - insns[i++] = INSN; \ - GENOP##mr(D, B, I, S, r); \ -} while (0) -#define GEN64(INSN, GENOP) do { \ - if (X86_TARGET_64BIT) \ - GEN(INSN, GENOP); \ -} while (0) -#define GEN1(INSN, GENOP) do { \ - GEN(INSN "s", GENOP##S); \ - GEN(INSN "d", GENOP##D); \ -} while (0) -#define GENA(INSN, GENOP) do { \ - GEN1(INSN "s", GENOP##S); \ - GEN1(INSN "p", GENOP##P); \ -} while (0) -#define GENI(INSN, GENOP, IMM) do { \ - insns[i++] = INSN; \ - GENOP##mr(IMM, D, B, I, S, r); \ -} while (0) -#define GENI1(INSN, GENOP, IMM) do { \ - GENI(INSN "s", GENOP##S, IMM); \ - GENI(INSN "d", GENOP##D, IMM); \ -} while (0) -#define GENIA(INSN, GENOP, IMM) do { \ - GENI1(INSN "s", GENOP##S, IMM); \ - GENI1(INSN "p", GENOP##P, IMM); \ -} while (0) - GEN1("andp", ANDP); - GEN1("andnp", ANDNP); - GEN1("orp", ORP); - GEN1("xorp", XORP); - GENA("add", ADD); - GENA("sub", SUB); - GENA("mul", MUL); - GENA("div", DIV); - GEN1("comis", COMIS); - GEN1("ucomis", UCOMIS); - GENA("min", MIN); - GENA("max", MAX); - GEN("rcpss", RCPSS); - GEN("rcpps", RCPPS); - GEN("rsqrtss", RSQRTSS); - GEN("rsqrtps", RSQRTPS); - GENA("sqrt", SQRT); - GENIA("cmpeq", CMP, X86_SSE_CC_EQ); - GENIA("cmplt", CMP, X86_SSE_CC_LT); - GENIA("cmple", CMP, X86_SSE_CC_LE); - GENIA("cmpunord", CMP, X86_SSE_CC_U); - GENIA("cmpneq", CMP, X86_SSE_CC_NEQ); - GENIA("cmpnlt", CMP, X86_SSE_CC_NLT); - GENIA("cmpnle", CMP, X86_SSE_CC_NLE); - GENIA("cmpord", CMP, X86_SSE_CC_O); - GEN1("movap", MOVAP); - GEN("movdqa", MOVDQA); - GEN("movdqu", MOVDQU); -#if 0 - // FIXME: extraneous REX bits generated - GEN("movd", MOVDXD); - GEN64("movd", MOVQXD); // FIXME: disass bug? "movq" expected -#endif - GEN("cvtdq2pd", CVTDQ2PD); - GEN("cvtdq2ps", CVTDQ2PS); - GEN("cvtpd2dq", CVTPD2DQ); - GEN("cvtpd2ps", CVTPD2PS); - GEN("cvtps2dq", CVTPS2DQ); - GEN("cvtps2pd", CVTPS2PD); - GEN("cvtsd2si", CVTSD2SIL); - GEN64("cvtsd2siq", CVTSD2SIQ); - GEN("cvtsd2ss", CVTSD2SS); - GEN("cvtsi2sd", CVTSI2SDL); - GEN64("cvtsi2sdq", CVTSI2SDQ); - GEN("cvtsi2ss", CVTSI2SSL); - GEN64("cvtsi2ssq", CVTSI2SSQ); - GEN("cvtss2sd", CVTSS2SD); - GEN("cvtss2si", CVTSS2SIL); - GEN64("cvtss2siq", CVTSS2SIQ); - GEN("cvttpd2dq", CVTTPD2DQ); - GEN("cvttps2dq", CVTTPS2DQ); - GEN("cvttsd2si", CVTTSD2SIL); - GEN64("cvttsd2siq", CVTTSD2SIQ); - GEN("cvttss2si", CVTTSS2SIL); - GEN64("cvttss2siq", CVTTSS2SIQ); - if (r < 8) { - // MMX dest register - GEN("cvtpd2pi", CVTPD2PI); - GEN("cvtps2pi", CVTPS2PI); - GEN("cvttpd2pi", CVTTPD2PI); - GEN("cvttps2pi", CVTTPS2PI); - } -#undef GENIA -#undef GENI1 -#undef GENI -#undef GENA -#undef GEN1 -#undef GEN64 -#undef GEN - int last_insn = i; - uint8 *e = get_target(); - - uint8 *p = b; - i = 0; - while (p < e) { - int n = disass_x86(buffer, (uintptr)p); - insn_t ii; - parse_insn(&ii, buffer); - - if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) { - show_instruction(buffer, p); - n_failures++; - } - - p += n; - i += 1; - n_tests++; - show_status(n_tests); - } - if (i != last_insn) - abort(); - } - } - } - } - } - printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); - n_all_tests += n_tests; - n_all_failures += n_failures; -#endif - - printf("\n"); - printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures); -} diff --git a/BasiliskII/src/uae_cpu/cpu_emulation.h b/BasiliskII/src/uae_cpu/cpu_emulation.h index cd588ec1..809959c9 100644 --- a/BasiliskII/src/uae_cpu/cpu_emulation.h +++ b/BasiliskII/src/uae_cpu/cpu_emulation.h @@ -37,14 +37,6 @@ extern uint32 ROMBaseMac; // ROM base (Mac address space) extern uint8 *ROMBaseHost; // ROM base (host address space) extern uint32 ROMSize; // Size of ROM -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING -// If we are not using real or direct addressing, the Mac frame buffer gets -// mapped to this location. The memory must be allocated by VideoInit(). -// If multiple monitors are used, they must share the frame buffer -const uint32 MacFrameBaseMac = 0xa0000000; -extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space) -extern uint32 MacFrameSize; // Size of frame buffer -#endif extern int MacFrameLayout; // Frame buffer layout (see defines below) // Possible frame buffer layouts @@ -82,13 +74,6 @@ extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType extern void Exit680x0(void); extern void InitFrameBufferMapping(void); -// 680x0 dynamic recompilation activation flag -#if USE_JIT -extern bool UseJIT; -#else -const bool UseJIT = false; -#endif - // 680x0 emulation functions struct M68kRegisters; extern void Start680x0(void); // Reset and start 680x0 diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h index 7c0c5b74..5983e15e 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.h +++ b/BasiliskII/src/uae_cpu/fpu/flags.h @@ -66,12 +66,6 @@ # define FPU_USE_LAZY_FLAGS #endif -/* JIT Compilation for FPU only works with lazy evaluation of FPU flags */ -#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) && defined(USE_JIT_FPU) -# undef FPU_USE_GENERIC_FLAGS -# define FPU_USE_LAZY_FLAGS -#endif - #ifdef FPU_IMPLEMENTATION /* -------------------------------------------------------------------------- */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp deleted file mode 100644 index f5a1aeb4..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp +++ /dev/null @@ -1,2152 +0,0 @@ -/* - * fpu/fpu_ieee.cpp - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Following fixes by Lauri Pesonen, July 1999: - * - * FMOVEM list handling: - * The lookup tables did not work correctly, rewritten. - * FINT: - * (int) cast does not work, fixed. - * Further, now honors the FPU fpcr rounding modes. - * FINTRZ: - * (int) cast cannot be used, fixed. - * FGETEXP: - * Input argument value 0 returned erroneous value. - * FMOD: - * (int) cast cannot be used. Replaced by proper rounding. - * Quotient byte handling was missing. - * FREM: - * (int) cast cannot be used. Replaced by proper rounding. - * Quotient byte handling was missing. - * FSCALE: - * Input argument value 0 was not handled correctly. - * FMOVEM Control Registers to/from address FPU registers An: - * A bug caused the code never been called. - * FMOVEM Control Registers pre-decrement: - * Moving of control regs from memory to FPP was not handled properly, - * if not all of the three FPU registers were moved. - * Condition code "Not Greater Than or Equal": - * Returned erroneous value. - * FSINCOS: - * Cosine must be loaded first if same register. - * FMOVECR: - * Status register was not updated (yes, this affects it). - * FMOVE -> reg: - * Status register was not updated (yes, this affects it). - * FMOVE reg -> reg: - * Status register was not updated. - * FDBcc: - * The loop termination condition was wrong. - * Possible leak from int16 to int32 fixed. - * get_fp_value: - * Immediate addressing mode && Operation Length == Byte -> - * Use the low-order byte of the extension word. - * Now FPU fpcr high 16 bits are always read as zeroes, no matter what was - * written to them. - * - * Other: - * - Optimized single/double/extended to/from conversion functions. - * Huge speed boost, but not (necessarily) portable to other systems. - * Enabled/disabled by #define FPU_HAVE_IEEE_DOUBLE 1 - * - Optimized versions of FSCALE, FGETEXP, FGETMAN - * - Conversion routines now handle NaN and infinity better. - * - Some constants precalculated. Not all compilers can optimize the - * expressions previously used. - * - * TODO: - * - Floating point exceptions. - * - More Infinity/NaN/overflow/underflow checking. - * - FPU instruction_address (only needed when exceptions are implemented) - * - Should be written in assembly to support long doubles. - * - Precision rounding single/double - */ - -#include "sysdeps.h" -#include -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#include "main.h" -#define FPU_IMPLEMENTATION -#include "fpu/fpu.h" -#include "fpu/fpu_ieee.h" - -/* Global FPU context */ -fpu_t fpu; - -/* -------------------------------------------------------------------------- */ -/* --- Scopes Definition --- */ -/* -------------------------------------------------------------------------- */ - -#undef PUBLIC -#define PUBLIC /**/ - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* -------------------------------------------------------------------------- */ -/* --- Native Support --- */ -/* -------------------------------------------------------------------------- */ - -#include "fpu/mathlib.h" -#include "fpu/flags.h" -#include "fpu/exceptions.h" -#include "fpu/rounding.h" -#include "fpu/impl.h" - -#include "fpu/mathlib.cpp" -#include "fpu/flags.cpp" -#include "fpu/exceptions.cpp" -#include "fpu/rounding.cpp" - -/* -------------------------------------------------------------------------- */ -/* --- Debugging --- */ -/* -------------------------------------------------------------------------- */ - -PUBLIC void FFPU fpu_dump_registers(void) -{ - for (int i = 0; i < 8; i++){ - printf ("FP%d: %g ", i, fpu_get_register(i)); - if ((i & 3) == 3) - printf ("\n"); - } -} - -PUBLIC void FFPU fpu_dump_flags(void) -{ - printf ("N=%d Z=%d I=%d NAN=%d\n", - (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, - (get_fpsr() & FPSR_CCB_ZERO)!= 0, - (get_fpsr() & FPSR_CCB_INFINITY) != 0, - (get_fpsr() & FPSR_CCB_NAN) != 0); -} - -PRIVATE void FFPU dump_registers(const char * str) -{ -#if FPU_DEBUG && FPU_DUMP_REGISTERS - char temp_str[512]; - - sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", - str, - fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), - fpu_get_register(3), fpu_get_register(4), fpu_get_register(5), - fpu_get_register(6), fpu_get_register(7) ); - - fpu_debug((temp_str)); -#endif -} - -PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) -{ -#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES - char temp_buf1[256], temp_buf2[10]; - int bytes = sizeof(temp_buf1)/3-1-3; - if (actual < bytes) - bytes = actual; - - temp_buf1[0] = 0; - for (int i = 0; i < bytes; i++) { - sprintf(temp_buf2, "%02x ", (uae_u32)buffer[i]); - strcat(temp_buf1, temp_buf2); - } - - strcat(temp_buf1, "\n"); - fpu_debug((temp_buf1)); -#endif -} - -// Quotient Byte is loaded with the sign and least significant -// seven bits of the quotient. -PRIVATE inline void FFPU make_quotient(fpu_register const & quotient, uae_u32 sign) -{ - uae_u32 lsb = (uae_u32)fp_fabs(quotient) & 0x7f; - FPU fpsr.quotient = sign | (lsb << 16); -} - -// to_single -PRIVATE inline fpu_register FFPU make_single(uae_u32 value) -{ -#if 1 - // Use a single, otherwise some checks for NaN, Inf, Zero would have to - // be performed - fpu_single result = 0; // = 0 to workaround a compiler bug on SPARC - fp_declare_init_shape(srp, result, single); - srp->ieee.negative = (value >> 31) & 1; - srp->ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; - srp->ieee.mantissa = value & 0x007fffff; - fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); - return result; -#elif 0 /* Original code */ - if ((value & 0x7fffffff) == 0) - return (0.0); - - fpu_register result; - uae_u32 * p = (uae_u32 *)&result; - - uae_u32 sign = (value & 0x80000000); - uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - - p[FLO] = value << 29; - p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); - - fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); - - return(result); -#endif -} - -// from_single -PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) -{ -#if 1 - fpu_single input = (fpu_single) src; - fp_declare_init_shape(sip, input, single); - uae_u32 result = (sip->ieee.negative << 31) - | (sip->ieee.exponent << 23) - | sip->ieee.mantissa; - fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); - return result; -#elif 0 /* Original code */ - if (src == 0.0) - return 0; - - uae_u32 result; - uae_u32 *p = (uae_u32 *)&src; - - uae_u32 sign = (p[FHI] & 0x80000000); - uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; - - if(exp + 127 < 1023) { - exp = 0; - } else if(exp > 1023 + 127) { - exp = 255; - } else { - exp = exp + 127 - 1023; - } - - result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); - - fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); - - return (result); -#endif -} - -// to_exten -PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - // is it zero? - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return 0.0; - - fpu_register result; -#if USE_QUAD_DOUBLE - // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { - make_nan(result); - return result; - } - // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { - if ((wrd1 & 0x80000000) == 0) - make_inf_positive(result); - else - make_inf_negative(result); - return result; - } - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp->ieee.mantissa3 = 0; -#elif USE_LONG_DOUBLE - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = wrd2; - srp->ieee.mantissa1 = wrd3; -#else - uae_u32 sgn = (wrd1 >> 31) & 1; - uae_u32 exp = (wrd1 >> 16) & 0x7fff; - - // the explicit integer bit is not set, must normalize - if ((wrd2 & 0x80000000) == 0) { - fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3)); - if (wrd2 | wrd3) { - // mantissa, not fraction. - uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; - while (exp > 0 && (man & UVAL64(0x8000000000000000)) == 0) { - man <<= 1; - exp--; - } - wrd2 = (uae_u32)(man >> 32); - wrd3 = (uae_u32)(man & 0xFFFFFFFF); - } - else if (exp != 0x7fff) // zero - exp = FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; - } - - if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) - exp = 0; - else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) - exp = FP_DOUBLE_EXP_MAX; - else - exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - - fp_declare_init_shape(srp, result, double); - srp->ieee.negative = sgn; - srp->ieee.exponent = exp; - // drop the explicit integer bit - srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); -#endif - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); - return result; -} - -/* - Would be so much easier with full size floats :( - ... this is so vague. -*/ -// make_extended_no_normalize -PRIVATE inline void FFPU make_extended_no_normalize( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result -) -{ - // is it zero? - if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - make_zero_positive(result); - return; - } - // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { - make_nan(result); - return; - } -#if USE_QUAD_DOUBLE - // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { - if ((wrd1 & 0x80000000) == 0) - make_inf_positive(result); - else - make_inf_negative(result); - return; - } - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp->ieee.mantissa3 = 0; -#elif USE_LONG_DOUBLE - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = wrd2; - srp->ieee.mantissa1 = wrd3; -#else - uae_u32 exp = (wrd1 >> 16) & 0x7fff; - if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) - exp = 0; - else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) - exp = FP_DOUBLE_EXP_MAX; - else - exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - - fp_declare_init_shape(srp, result, double); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = exp; - // drop the explicit integer bit - srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); -#endif - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); -} - -// from_exten -PRIVATE inline void FFPU extract_extended(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -) -{ - if (src == 0.0) { - *wrd1 = *wrd2 = *wrd3 = 0; - return; - } -#if USE_QUAD_DOUBLE - // FIXME: deal with denormals? - fp_declare_init_shape(srp, src, extended); - *wrd1 = (srp->ieee.negative << 31) | (srp->ieee.exponent << 16); - // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 15) | ((srp->ieee.mantissa1 & 0xfffe0000) >> 17); - *wrd3 = (srp->ieee.mantissa1 << 15) | ((srp->ieee.mantissa2 & 0xfffe0000) >> 17); -#elif USE_LONG_DOUBLE - uae_u32 *p = (uae_u32 *)&src; -#ifdef WORDS_BIGENDIAN - *wrd1 = p[0]; - *wrd2 = p[1]; - *wrd3 = p[2]; -#else - *wrd3 = p[0]; - *wrd2 = p[1]; - *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; -#endif -#else - fp_declare_init_shape(srp, src, double); - fpu_debug(("extract_extended (%d,%d,%X,%X)\n", - srp->ieee.negative , srp->ieee.exponent, - srp->ieee.mantissa0, srp->ieee.mantissa1)); - - uae_u32 exp = srp->ieee.exponent; - - if (exp == FP_DOUBLE_EXP_MAX) - exp = FP_EXTENDED_EXP_MAX; - else - exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; - - *wrd1 = (srp->ieee.negative << 31) | (exp << 16); - // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21); - *wrd3 = srp->ieee.mantissa1 << 11; -#endif - fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); -} - -// to_double -PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) -{ - union { - fpu_double value; - uae_u32 parts[2]; - } dest; -#ifdef WORDS_BIGENDIAN - dest.parts[0] = wrd1; - dest.parts[1] = wrd2; -#else - dest.parts[0] = wrd2; - dest.parts[1] = wrd1; -#endif - fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,dest.value)); - return (fpu_register)(dest.value); -} - -// from_double -PRIVATE inline void FFPU extract_double(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2 -) -{ - union { - fpu_double value; - uae_u32 parts[2]; - } dest; - dest.value = (fpu_double)src; -#ifdef WORDS_BIGENDIAN - *wrd1 = dest.parts[0]; - *wrd2 = dest.parts[1]; -#else - *wrd2 = dest.parts[0]; - *wrd1 = dest.parts[1]; -#endif - fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); -} - -// to_pack -PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - fpu_double d; - char *cp; - char str[100]; - - cp = str; - if (wrd1 & 0x80000000) - *cp++ = '-'; - *cp++ = (char)((wrd1 & 0xf) + '0'); - *cp++ = '.'; - *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); - *cp++ = 'E'; - if (wrd1 & 0x40000000) - *cp++ = '-'; - *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); - *cp = 0; - sscanf(str, "%le", &d); - - fpu_debug(("make_packed str = %s\n",str)); - - fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); - return d; -} - -// from_pack -PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) -{ - int i; - int t; - char *cp; - char str[100]; - - sprintf(str, "%.16e", src); - - fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); - - cp = str; - *wrd1 = *wrd2 = *wrd3 = 0; - if (*cp == '-') { - cp++; - *wrd1 = 0x80000000; - } - if (*cp == '+') - cp++; - *wrd1 |= (*cp++ - '0'); - if (*cp == '.') - cp++; - for (i = 0; i < 8; i++) { - *wrd2 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd2 |= *cp++ - '0'; - } - for (i = 0; i < 8; i++) { - *wrd3 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd3 |= *cp++ - '0'; - } - if (*cp == 'e' || *cp == 'E') { - cp++; - if (*cp == '-') { - cp++; - *wrd1 |= 0x40000000; - } - if (*cp == '+') - cp++; - t = 0; - for (i = 0; i < 3; i++) { - if (*cp >= '0' && *cp <= '9') - t = (t << 4) | (*cp++ - '0'); - } - *wrd1 |= t << 16; - } - - fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); -} - -PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register & src) -{ - uaecptr tmppc; - uae_u16 tmp; - int size; - int mode; - int reg; - uae_u32 ad = 0; - static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - // fpu_debug(("get_fp_value(%X,%X)\n",(int)opcode,(int)extra)); - // dump_first_bytes( regs.pc_p-4, 16 ); - - if ((extra & 0x4000) == 0) { - src = FPU registers[(extra >> 10) & 7]; - return 1; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - - fpu_debug(("get_fp_value mode=%d, reg=%d, size=%d\n",(int)mode,(int)reg,(int)size)); - - switch (mode) { - case 0: - switch (size) { - case 6: - src = (fpu_register) (uae_s8) m68k_dreg (regs, reg); - break; - case 4: - src = (fpu_register) (uae_s16) m68k_dreg (regs, reg); - break; - case 0: - src = (fpu_register) (uae_s32) m68k_dreg (regs, reg); - break; - case 1: - src = make_single(m68k_dreg (regs, reg)); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - fpu_debug(("get_fp_value next_iword()=%X\n",ad-m68k_getpc()-2)); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - // Immediate addressing mode && Operation Length == Byte -> - // Use the low-order byte of the extension word. - if(size == 6) ad++; - break; - default: - return 0; - } - } - - fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); - fpu_debug(("get_fp_value ad=%X\n",ad)); - fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); - dump_first_bytes( get_real_address(ad)-64, 64 ); - dump_first_bytes( get_real_address(ad), 64 ); - - switch (size) { - case 0: - src = (fpu_register) (uae_s32) get_long (ad); - break; - case 1: - src = make_single(get_long (ad)); - break; - case 2: { - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - src = make_extended(wrd1, wrd2, wrd3); - break; - } - case 3: { - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - src = make_packed(wrd1, wrd2, wrd3); - break; - } - case 4: - src = (fpu_register) (uae_s16) get_word(ad); - break; - case 5: { - uae_u32 wrd1, wrd2; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - src = make_double(wrd1, wrd2); - break; - } - case 6: - src = (fpu_register) (uae_s8) get_byte(ad); - break; - default: - return 0; - } - - // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); - return 1; -} - -/* Convert the FP value to integer according to the current m68k rounding mode */ -PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) -{ - fpu_register result; - switch (get_fpcr() & 0x30) { - case FPCR_ROUND_ZERO: - result = fp_round_to_zero(src); - break; - case FPCR_ROUND_MINF: - result = fp_round_to_minus_infinity(src); - break; - case FPCR_ROUND_NEAR: - result = fp_round_to_nearest(src); - break; - case FPCR_ROUND_PINF: - result = fp_round_to_plus_infinity(src); - break; - default: - result = src; /* should never be reached */ - break; - } - return (uae_s32)result; -} - -PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) -{ - uae_u16 tmp; - uaecptr tmppc; - int size; - int mode; - int reg; - uae_u32 ad; - static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - // fpu_debug(("put_fp_value(%.04f,%X,%X)\n",(float)value,(int)opcode,(int)extra)); - - if ((extra & 0x4000) == 0) { - int dest_reg = (extra >> 10) & 7; - FPU registers[dest_reg] = value; - make_fpsr(FPU registers[dest_reg]); - return 1; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - ad = 0xffffffff; - switch (mode) { - case 0: - switch (size) { - case 6: - m68k_dreg (regs, reg) = ((toint(value) & 0xff) - | (m68k_dreg (regs, reg) & ~0xff)); - break; - case 4: - m68k_dreg (regs, reg) = ((toint(value) & 0xffff) - | (m68k_dreg (regs, reg) & ~0xffff)); - break; - case 0: - m68k_dreg (regs, reg) = toint(value); - break; - case 1: - m68k_dreg (regs, reg) = extract_single(value); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - break; - default: - return 0; - } - } - switch (size) { - case 0: - put_long (ad, toint(value)); - break; - case 1: - put_long (ad, extract_single(value)); - break; - case 2: { - uae_u32 wrd1, wrd2, wrd3; - extract_extended(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - break; - } - case 3: { - uae_u32 wrd1, wrd2, wrd3; - extract_packed(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - break; - } - case 4: - put_word(ad, (uae_s16) toint(value)); - break; - case 5: { - uae_u32 wrd1, wrd2; - extract_double(value, &wrd1, &wrd2); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - break; - } - case 6: - put_byte(ad, (uae_s8) toint(value)); - break; - default: - return 0; - } - return 1; -} - -PRIVATE inline int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) -{ - uae_u16 tmp; - uaecptr tmppc; - int mode; - int reg; - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) { - case 0: - case 1: - return 0; - case 2: - *ad = m68k_areg (regs, reg); - break; - case 3: - *ad = m68k_areg (regs, reg); - break; - case 4: - *ad = m68k_areg (regs, reg); - break; - case 5: - *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - *ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - *ad = next_ilong(); - break; - case 2: - *ad = m68k_getpc (); - *ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - *ad = get_disp_ea_020 (tmppc, tmp); - break; - default: - return 0; - } - } - return 1; -} - -#if FPU_DEBUG -# define CONDRET(s,x) fpu_debug(("fpp_cond %s = %d\n",s,(uint32)(x))); return (x) -#else -# define CONDRET(s,x) return (x) -#endif - -PRIVATE inline int FFPU fpp_cond(int condition) -{ - int N = (FPU result < 0.0); - int Z = (FPU result == 0.0); - int NaN = isnan(FPU result); - - if (NaN) - N = Z = 0; - - switch (condition) { - case 0x00: CONDRET("False",0); - case 0x01: CONDRET("Equal",Z); - case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); - case 0x03: CONDRET("Ordered Greater Than or Equal",Z || !(NaN || N)); - case 0x04: CONDRET("Ordered Less Than",N && !(NaN || Z)); - case 0x05: CONDRET("Ordered Less Than or Equal",Z || (N && !NaN)); - case 0x06: CONDRET("Ordered Greater or Less Than",!(NaN || Z)); - case 0x07: CONDRET("Ordered",!NaN); - case 0x08: CONDRET("Unordered",NaN); - case 0x09: CONDRET("Unordered or Equal",NaN || Z); - case 0x0a: CONDRET("Unordered or Greater Than",NaN || !(N || Z)); - case 0x0b: CONDRET("Unordered or Greater or Equal",NaN || Z || !N); - case 0x0c: CONDRET("Unordered or Less Than",NaN || (N && !Z)); - case 0x0d: CONDRET("Unordered or Less or Equal",NaN || Z || N); - case 0x0e: CONDRET("Not Equal",!Z); - case 0x0f: CONDRET("True",1); - case 0x10: CONDRET("Signaling False",0); - case 0x11: CONDRET("Signaling Equal",Z); - case 0x12: CONDRET("Greater Than",!(NaN || Z || N)); - case 0x13: CONDRET("Greater Than or Equal",Z || !(NaN || N)); - case 0x14: CONDRET("Less Than",N && !(NaN || Z)); - case 0x15: CONDRET("Less Than or Equal",Z || (N && !NaN)); - case 0x16: CONDRET("Greater or Less Than",!(NaN || Z)); - case 0x17: CONDRET("Greater, Less or Equal",!NaN); - case 0x18: CONDRET("Not Greater, Less or Equal",NaN); - case 0x19: CONDRET("Not Greater or Less Than",NaN || Z); - case 0x1a: CONDRET("Not Less Than or Equal",NaN || !(N || Z)); - case 0x1b: CONDRET("Not Less Than",NaN || Z || !N); - case 0x1c: CONDRET("Not Greater Than or Equal", NaN || (N && !Z)); - case 0x1d: CONDRET("Not Greater Than",NaN || Z || N); - case 0x1e: CONDRET("Signaling Not Equal",!Z); - case 0x1f: CONDRET("Signaling True",1); - default: CONDRET("",-1); - } -} - -void FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) -{ - fpu_debug(("fdbcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - uaecptr pc = (uae_u32) m68k_getpc (); - uae_s32 disp = (uae_s32) (uae_s16) next_iword(); - int cc = fpp_cond(extra & 0x3f); - if (cc == -1) { - m68k_setpc (pc - 4); - op_illg (opcode); - } else if (!cc) { - int reg = opcode & 0x7; - - // this may have leaked. - /* - m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) - | ((m68k_dreg (regs, reg) - 1) & 0xffff)); - */ - m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000) - | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff)); - - - // condition reversed. - // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) - if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) - m68k_setpc (pc + disp); - } -} - -void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) -{ - fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - uae_u32 ad; - int cc = fpp_cond(extra & 0x3f); - if (cc == -1) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - else if ((opcode & 0x38) == 0) { - m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | - (cc ? 0xff : 0x00); - } - else if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - else - put_byte(ad, cc ? 0xff : 0x00); -} - -void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) -{ - fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); - - int cc = fpp_cond(opcode & 0x3f); - if (cc == -1) { - m68k_setpc (oldpc); - op_illg (opcode); - } - if (cc) - Exception(7, oldpc - 2); -} - -// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) -void FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) -{ - fpu_debug(("fbcc_opp %X, %X at %08lx, jumpto=%X\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); - - int cc = fpp_cond(opcode & 0x3f); - if (cc == -1) { - m68k_setpc (pc); - op_illg (opcode); - } - else if (cc) { - if ((opcode & 0x40) == 0) - extra = (uae_s32) (uae_s16) extra; - m68k_setpc (pc + extra); - } -} - -// FSAVE has no post-increment -// 0x1f180000 == IDLE state frame, coprocessor version number 1F -void FFPU fpuop_save(uae_u32 opcode) -{ - fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); - - uae_u32 ad; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - int i; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - if (CPUType == 4) { - // Put 4 byte 68040 IDLE frame. - if (incr < 0) { - ad -= 4; - put_long (ad, 0x41000000); - } - else { - put_long (ad, 0x41000000); - ad += 4; - } - } else { - // Put 28 byte 68881 IDLE frame. - if (incr < 0) { - fpu_debug(("fsave_opp pre-decrement\n")); - ad -= 4; - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); - } - ad -= 4; - put_long (ad, 0x1f180000); // IDLE, vers 1f - } - else { - put_long (ad, 0x1f180000); // IDLE, vers 1f - ad += 4; - for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); - ad += 4; - } - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - ad += 4; - } - } - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - fpu_debug(("PROBLEM: fsave_opp post-increment\n")); - } - if ((opcode & 0x38) == 0x20) { - m68k_areg (regs, opcode & 7) = ad; - fpu_debug(("fsave_opp pre-decrement %X -> A%d\n",ad,opcode & 7)); - } -} - -// FRESTORE has no pre-decrement -void FFPU fpuop_restore(uae_u32 opcode) -{ - fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); - - uae_u32 ad; - uae_u32 d; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - if (CPUType == 4) { - // 68040 - if (incr < 0) { - fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0) { // IDLE - fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); - } - else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); - ad -= 44; - } - else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); - ad -= 92; - } - } - } - else { - d = get_long (ad); - fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); - ad += 4; - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0) { // IDLE - fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); - } - else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); - ad += 44; - } - else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); - ad += 92; - } - } - } - } - else { - // 68881 - if (incr < 0) { - fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad -= 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad -= 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad -= 45 * 4; - } - } - else { - d = get_long (ad); - fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); - ad += 4; - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0x00180000) { // IDLE - fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); - ad += 6 * 4; - } - else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? - ad += 14 * 4; - fpu_debug(("PROBLEM: frestore_opp found UNIMP? frame at %X\n",ad-4)); - } - else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY - fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); - ad += 45 * 4; - } - } - } - } - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; - fpu_debug(("frestore_opp post-increment %X -> A%d\n",ad,opcode & 7)); - } - if ((opcode & 0x38) == 0x20) { - m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - fpu_debug(("PROBLEM: frestore_opp pre-decrement\n")); - } -} - -void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) -{ - int reg; - fpu_register src; - - fpu_debug(("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, - m68k_getpc () - 4)); - - dump_registers( "START"); - - switch ((extra >> 13) & 0x7) { - case 3: - fpu_debug(("FMOVE -> \n")); - if (put_fp_value (opcode, extra, FPU registers[(extra >> 7) & 7]) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - dump_registers( "END "); - return; - case 4: - case 5: - if ((opcode & 0x38) == 0) { - if (extra & 0x2000) { // dr bit - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; - fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); - } - if (extra & 0x0800) { - m68k_dreg (regs, opcode & 7) = get_fpsr(); - fpu_debug(("FMOVEM FPU fpsr (%X) -> D%d\n", get_fpsr(), opcode & 7)); - } - if (extra & 0x0400) { - m68k_dreg (regs, opcode & 7) = FPU instruction_address; - fpu_debug(("FMOVEM FPU instruction_address (%X) -> D%d\n", FPU instruction_address, opcode & 7)); - } - } - else { - if (extra & 0x1000) { - set_fpcr( m68k_dreg (regs, opcode & 7) ); - fpu_debug(("FMOVEM D%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); - } - if (extra & 0x0800) { - set_fpsr( m68k_dreg (regs, opcode & 7) ); - fpu_debug(("FMOVEM D%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); - } - if (extra & 0x0400) { - FPU instruction_address = m68k_dreg (regs, opcode & 7); - fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); - } - } -// } else if ((opcode & 0x38) == 1) { - } - else if ((opcode & 0x38) == 8) { - if (extra & 0x2000) { // dr bit - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; - fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); - } - if (extra & 0x0800) { - m68k_areg (regs, opcode & 7) = get_fpsr(); - fpu_debug(("FMOVEM FPU fpsr (%X) -> A%d\n", get_fpsr(), opcode & 7)); - } - if (extra & 0x0400) { - m68k_areg (regs, opcode & 7) = FPU instruction_address; - fpu_debug(("FMOVEM FPU instruction_address (%X) -> A%d\n", FPU instruction_address, opcode & 7)); - } - } else { - if (extra & 0x1000) { - set_fpcr( m68k_areg (regs, opcode & 7) ); - fpu_debug(("FMOVEM A%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); - } - if (extra & 0x0800) { - set_fpsr( m68k_areg (regs, opcode & 7) ); - fpu_debug(("FMOVEM A%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); - } - if (extra & 0x0400) { - FPU instruction_address = m68k_areg (regs, opcode & 7); - fpu_debug(("FMOVEM A%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); - } - } - } - else if ((opcode & 0x3f) == 0x3c) { - if ((extra & 0x2000) == 0) { - if (extra & 0x1000) { - set_fpcr( next_ilong() ); - fpu_debug(("FMOVEM #<%X> -> FPU fpcr\n", get_fpcr())); - } - if (extra & 0x0800) { - set_fpsr( next_ilong() ); - fpu_debug(("FMOVEM #<%X> -> FPU fpsr\n", get_fpsr())); - } - if (extra & 0x0400) { - FPU instruction_address = next_ilong(); - fpu_debug(("FMOVEM #<%X> -> FPU instruction_address\n", FPU instruction_address)); - } - } - } - else if (extra & 0x2000) { - /* FMOVEM FPP->memory */ - uae_u32 ad; - int incr = 0; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - if ((opcode & 0x38) == 0x20) { - if (extra & 0x1000) - incr += 4; - if (extra & 0x0800) - incr += 4; - if (extra & 0x0400) - incr += 4; - } - ad -= incr; - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - put_long (ad, get_fpcr() & 0xFFFF); - fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); - ad += 4; - } - if (extra & 0x0800) { - put_long (ad, get_fpsr()); - fpu_debug(("FMOVEM FPU fpsr (%X) -> mem %X\n", get_fpsr(), ad )); - ad += 4; - } - if (extra & 0x0400) { - put_long (ad, FPU instruction_address); - fpu_debug(("FMOVEM FPU instruction_address (%X) -> mem %X\n", FPU instruction_address, ad )); - ad += 4; - } - ad -= incr; - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - else { - /* FMOVEM memory->FPP */ - uae_u32 ad; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - - // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; - int incr = 0; - if((opcode & 0x38) == 0x20) { - if (extra & 0x1000) - incr += 4; - if (extra & 0x0800) - incr += 4; - if (extra & 0x0400) - incr += 4; - ad = ad - incr; - } - - if (extra & 0x1000) { - set_fpcr( get_long (ad) ); - fpu_debug(("FMOVEM mem %X (%X) -> FPU fpcr\n", ad, get_fpcr() )); - ad += 4; - } - if (extra & 0x0800) { - set_fpsr( get_long (ad) ); - fpu_debug(("FMOVEM mem %X (%X) -> FPU fpsr\n", ad, get_fpsr() )); - ad += 4; - } - if (extra & 0x0400) { - FPU instruction_address = get_long (ad); - fpu_debug(("FMOVEM mem %X (%X) -> FPU instruction_address\n", ad, FPU instruction_address )); - ad += 4; - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? -// m68k_areg (regs, opcode & 7) = ad - 12; - m68k_areg (regs, opcode & 7) = ad - incr; - } - dump_registers( "END "); - return; - case 6: - case 7: { - uae_u32 ad, list = 0; - int incr = 0; - if (extra & 0x2000) { - /* FMOVEM FPP->memory */ - fpu_debug(("FMOVEM FPP->memory\n")); - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 1: /* dynamic pred */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 3: /* dynamic postinc */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = 1; - break; - } - - if (incr < 0) { - for(reg=7; reg>=0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - } - else { - for(reg=0; reg<8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - else { - /* FMOVEM memory->FPP */ - fpu_debug(("FMOVEM memory->FPP\n")); - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); - list = extra & 0xff; - incr = -1; - break; - case 1: /* dynamic pred */ - fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 3: /* dynamic postinc */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = 1; - break; - } - - /**/ - if (incr < 0) { - // not reached - for(reg=7; reg>=0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); - make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); - } - list <<= 1; - } - } - else { - for(reg=0; reg<8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); - make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - dump_registers( "END "); - return; - } - case 0: - case 2: - reg = (extra >> 7) & 7; - if ((extra & 0xfc00) == 0x5c00) { - fpu_debug(("FMOVECR memory->FPP\n")); - switch (extra & 0x7f) { - case 0x00: - // FPU registers[reg] = 4.0 * atan(1.0); - FPU registers[reg] = 3.1415926535897932384626433832795; - fpu_debug(("FP const: Pi\n")); - break; - case 0x0b: - // FPU registers[reg] = log10 (2.0); - FPU registers[reg] = 0.30102999566398119521373889472449; - fpu_debug(("FP const: Log 10 (2)\n")); - break; - case 0x0c: - // FPU registers[reg] = exp (1.0); - FPU registers[reg] = 2.7182818284590452353602874713527; - fpu_debug(("FP const: e\n")); - break; - case 0x0d: - // FPU registers[reg] = log (exp (1.0)) / log (2.0); - FPU registers[reg] = 1.4426950408889634073599246810019; - fpu_debug(("FP const: Log 2 (e)\n")); - break; - case 0x0e: - // FPU registers[reg] = log (exp (1.0)) / log (10.0); - FPU registers[reg] = 0.43429448190325182765112891891661; - fpu_debug(("FP const: Log 10 (e)\n")); - break; - case 0x0f: - FPU registers[reg] = 0.0; - fpu_debug(("FP const: zero\n")); - break; - case 0x30: - // FPU registers[reg] = log (2.0); - FPU registers[reg] = 0.69314718055994530941723212145818; - fpu_debug(("FP const: ln(2)\n")); - break; - case 0x31: - // FPU registers[reg] = log (10.0); - FPU registers[reg] = 2.3025850929940456840179914546844; - fpu_debug(("FP const: ln(10)\n")); - break; - case 0x32: - // ?? - FPU registers[reg] = 1.0e0; - fpu_debug(("FP const: 1.0e0\n")); - break; - case 0x33: - FPU registers[reg] = 1.0e1; - fpu_debug(("FP const: 1.0e1\n")); - break; - case 0x34: - FPU registers[reg] = 1.0e2; - fpu_debug(("FP const: 1.0e2\n")); - break; - case 0x35: - FPU registers[reg] = 1.0e4; - fpu_debug(("FP const: 1.0e4\n")); - break; - case 0x36: - FPU registers[reg] = 1.0e8; - fpu_debug(("FP const: 1.0e8\n")); - break; - case 0x37: - FPU registers[reg] = 1.0e16; - fpu_debug(("FP const: 1.0e16\n")); - break; - case 0x38: - FPU registers[reg] = 1.0e32; - fpu_debug(("FP const: 1.0e32\n")); - break; - case 0x39: - FPU registers[reg] = 1.0e64; - fpu_debug(("FP const: 1.0e64\n")); - break; - case 0x3a: - FPU registers[reg] = 1.0e128; - fpu_debug(("FP const: 1.0e128\n")); - break; - case 0x3b: - FPU registers[reg] = 1.0e256; - fpu_debug(("FP const: 1.0e256\n")); - break; -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - case 0x3c: - FPU registers[reg] = 1.0e512L; - fpu_debug(("FP const: 1.0e512\n")); - break; - case 0x3d: - FPU registers[reg] = 1.0e1024L; - fpu_debug(("FP const: 1.0e1024\n")); - break; - case 0x3e: - FPU registers[reg] = 1.0e2048L; - fpu_debug(("FP const: 1.0e2048\n")); - break; - case 0x3f: - FPU registers[reg] = 1.0e4096L; - fpu_debug(("FP const: 1.0e4096\n")); -#endif - break; - default: - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - break; - } - // these *do* affect the status reg - make_fpsr(FPU registers[reg]); - dump_registers( "END "); - return; - } - - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); - - if (FPU is_integral) { - // 68040-specific operations - switch (extra & 0x7f) { - case 0x40: /* FSMOVE */ - fpu_debug(("FSMOVE %.04f\n",(double)src)); - FPU registers[reg] = (float)src; - make_fpsr(FPU registers[reg]); - break; - case 0x44: /* FDMOVE */ - fpu_debug(("FDMOVE %.04f\n",(double)src)); - FPU registers[reg] = (double)src; - make_fpsr(FPU registers[reg]); - break; - case 0x41: /* FSSQRT */ - fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = (float)fp_sqrt (src); - make_fpsr(FPU registers[reg]); - break; - case 0x45: /* FDSQRT */ - fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = (double)fp_sqrt (src); - make_fpsr(FPU registers[reg]); - break; - case 0x58: /* FSABS */ - fpu_debug(("FSABS %.04f\n",(double)src)); - FPU registers[reg] = (float)fp_fabs(src); - make_fpsr(FPU registers[reg]); - break; - case 0x5c: /* FDABS */ - fpu_debug(("FDABS %.04f\n",(double)src)); - FPU registers[reg] = (double)fp_fabs(src); - make_fpsr(FPU registers[reg]); - break; - case 0x5a: /* FSNEG */ - fpu_debug(("FSNEG %.04f\n",(double)src)); - FPU registers[reg] = (float)-src; - make_fpsr(FPU registers[reg]); - break; - case 0x5e: /* FDNEG */ - fpu_debug(("FDNEG %.04f\n",(double)src)); - FPU registers[reg] = (double)-src; - make_fpsr(FPU registers[reg]); - break; - case 0x60: /* FSDIV */ - fpu_debug(("FSDIV %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] / src); - make_fpsr(FPU registers[reg]); - break; - case 0x64: /* FDDIV */ - fpu_debug(("FDDIV %.04f\n",(double)src)); - FPU registers[reg] = (double)(FPU registers[reg] / src); - make_fpsr(FPU registers[reg]); - break; - case 0x62: /* FSADD */ - fpu_debug(("FSADD %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] + src); - make_fpsr(FPU registers[reg]); - break; - case 0x66: /* FDADD */ - fpu_debug(("FDADD %.04f\n",(double)src)); - FPU registers[reg] = (double)(FPU registers[reg] + src); - make_fpsr(FPU registers[reg]); - break; - case 0x68: /* FSSUB */ - fpu_debug(("FSSUB %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] - src); - make_fpsr(FPU registers[reg]); - break; - case 0x6c: /* FDSUB */ - fpu_debug(("FDSUB %.04f\n",(double)src)); - FPU registers[reg] = (double)(FPU registers[reg] - src); - make_fpsr(FPU registers[reg]); - break; - case 0x63: /* FSMUL */ - case 0x67: /* FDMUL */ - fpu_debug(("FMUL %.04f\n",(double)src)); - get_dest_flags(FPU registers[reg]); - get_source_flags(src); - if(fl_dest.in_range && fl_source.in_range) { - if ((extra & 0x7f) == 0x63) - FPU registers[reg] = (float)(FPU registers[reg] * src); - else - FPU registers[reg] = (double)(FPU registers[reg] * src); - } - else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); - } - else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } - } - else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } - } - make_fpsr(FPU registers[reg]); - break; - default: - // Continue decode-execute 6888x instructions below - goto process_6888x_instructions; - } - fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); - dump_registers( "END "); - return; - } - - process_6888x_instructions: - switch (extra & 0x7f) { - case 0x00: /* FMOVE */ - fpu_debug(("FMOVE %.04f\n",(double)src)); - FPU registers[reg] = src; - make_fpsr(FPU registers[reg]); - break; - case 0x01: /* FINT */ - fpu_debug(("FINT %.04f\n",(double)src)); - FPU registers[reg] = toint(src); - make_fpsr(FPU registers[reg]); - break; - case 0x02: /* FSINH */ - fpu_debug(("FSINH %.04f\n",(double)src)); - FPU registers[reg] = fp_sinh (src); - make_fpsr(FPU registers[reg]); - break; - case 0x03: /* FINTRZ */ - fpu_debug(("FINTRZ %.04f\n",(double)src)); - FPU registers[reg] = fp_round_to_zero(src); - make_fpsr(FPU registers[reg]); - break; - case 0x04: /* FSQRT */ - fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = fp_sqrt (src); - make_fpsr(FPU registers[reg]); - break; - case 0x06: /* FLOGNP1 */ - fpu_debug(("FLOGNP1 %.04f\n",(double)src)); - FPU registers[reg] = fp_log (src + 1.0); - make_fpsr(FPU registers[reg]); - break; - case 0x08: /* FETOXM1 */ - fpu_debug(("FETOXM1 %.04f\n",(double)src)); - FPU registers[reg] = fp_exp (src) - 1.0; - make_fpsr(FPU registers[reg]); - break; - case 0x09: /* FTANH */ - fpu_debug(("FTANH %.04f\n",(double)src)); - FPU registers[reg] = fp_tanh (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0a: /* FATAN */ - fpu_debug(("FATAN %.04f\n",(double)src)); - FPU registers[reg] = fp_atan (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0c: /* FASIN */ - fpu_debug(("FASIN %.04f\n",(double)src)); - FPU registers[reg] = fp_asin (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0d: /* FATANH */ - fpu_debug(("FATANH %.04f\n",(double)src)); - FPU registers[reg] = fp_atanh (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0e: /* FSIN */ - fpu_debug(("FSIN %.04f\n",(double)src)); - FPU registers[reg] = fp_sin (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0f: /* FTAN */ - fpu_debug(("FTAN %.04f\n",(double)src)); - FPU registers[reg] = fp_tan (src); - make_fpsr(FPU registers[reg]); - break; - case 0x10: /* FETOX */ - fpu_debug(("FETOX %.04f\n",(double)src)); - FPU registers[reg] = fp_exp (src); - make_fpsr(FPU registers[reg]); - break; - case 0x11: /* FTWOTOX */ - fpu_debug(("FTWOTOX %.04f\n",(double)src)); - FPU registers[reg] = fp_pow(2.0, src); - make_fpsr(FPU registers[reg]); - break; - case 0x12: /* FTENTOX */ - fpu_debug(("FTENTOX %.04f\n",(double)src)); - FPU registers[reg] = fp_pow(10.0, src); - make_fpsr(FPU registers[reg]); - break; - case 0x14: /* FLOGN */ - fpu_debug(("FLOGN %.04f\n",(double)src)); - FPU registers[reg] = fp_log (src); - make_fpsr(FPU registers[reg]); - break; - case 0x15: /* FLOG10 */ - fpu_debug(("FLOG10 %.04f\n",(double)src)); - FPU registers[reg] = fp_log10 (src); - make_fpsr(FPU registers[reg]); - break; - case 0x16: /* FLOG2 */ - fpu_debug(("FLOG2 %.04f\n",(double)src)); - FPU registers[reg] = fp_log (src) / fp_log (2.0); - make_fpsr(FPU registers[reg]); - break; - case 0x18: /* FABS */ - fpu_debug(("FABS %.04f\n",(double)src)); - FPU registers[reg] = fp_fabs(src); - make_fpsr(FPU registers[reg]); - break; - case 0x19: /* FCOSH */ - fpu_debug(("FCOSH %.04f\n",(double)src)); - FPU registers[reg] = fp_cosh(src); - make_fpsr(FPU registers[reg]); - break; - case 0x1a: /* FNEG */ - fpu_debug(("FNEG %.04f\n",(double)src)); - FPU registers[reg] = -src; - make_fpsr(FPU registers[reg]); - break; - case 0x1c: /* FACOS */ - fpu_debug(("FACOS %.04f\n",(double)src)); - FPU registers[reg] = fp_acos(src); - make_fpsr(FPU registers[reg]); - break; - case 0x1d: /* FCOS */ - fpu_debug(("FCOS %.04f\n",(double)src)); - FPU registers[reg] = fp_cos(src); - make_fpsr(FPU registers[reg]); - break; - case 0x1e: /* FGETEXP */ - fpu_debug(("FGETEXP %.04f\n",(double)src)); - if( isinf(src) ) { - make_nan( FPU registers[reg] ); - } - else { - FPU registers[reg] = fast_fgetexp( src ); - } - make_fpsr(FPU registers[reg]); - break; - case 0x1f: /* FGETMAN */ - fpu_debug(("FGETMAN %.04f\n",(double)src)); - if( src == 0 ) { - FPU registers[reg] = 0; - } - else if( isinf(src) ) { - make_nan( FPU registers[reg] ); - } - else { - FPU registers[reg] = src; - fast_remove_exponent( FPU registers[reg] ); - } - make_fpsr(FPU registers[reg]); - break; - case 0x20: /* FDIV */ - fpu_debug(("FDIV %.04f\n",(double)src)); - FPU registers[reg] /= src; - make_fpsr(FPU registers[reg]); - break; - case 0x21: /* FMOD */ - fpu_debug(("FMOD %.04f\n",(double)src)); - // FPU registers[reg] = FPU registers[reg] - (fpu_register) ((int) (FPU registers[reg] / src)) * src; - { - fpu_register quot = fp_round_to_zero(FPU registers[reg] / src); - uae_u32 sign = get_quotient_sign(FPU registers[reg],src); - FPU registers[reg] = FPU registers[reg] - quot * src; - make_fpsr(FPU registers[reg]); - make_quotient(quot, sign); - } - break; - case 0x23: /* FMUL */ - fpu_debug(("FMUL %.04f\n",(double)src)); - get_dest_flags(FPU registers[reg]); - get_source_flags(src); - if(fl_dest.in_range && fl_source.in_range) { - FPU registers[reg] *= src; - } - else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); - } - else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } - } - else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } - } - make_fpsr(FPU registers[reg]); - break; - case 0x24: /* FSGLDIV */ - fpu_debug(("FSGLDIV %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] / src); - make_fpsr(FPU registers[reg]); - break; - case 0x25: /* FREM */ - fpu_debug(("FREM %.04f\n",(double)src)); - // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; - { - fpu_register quot = fp_round_to_nearest(FPU registers[reg] / src); - uae_u32 sign = get_quotient_sign(FPU registers[reg],src); - FPU registers[reg] = FPU registers[reg] - quot * src; - make_fpsr(FPU registers[reg]); - make_quotient(quot,sign); - } - break; - - case 0x26: /* FSCALE */ - fpu_debug(("FSCALE %.04f\n",(double)src)); - // TODO: overflow flags - get_dest_flags(FPU registers[reg]); - get_source_flags(src); - if (fl_source.in_range && fl_dest.in_range) { - // When the absolute value of the source operand is >= 2^14, - // an overflow or underflow always results. - // Here (int) cast is okay. - int scale_factor = (int)fp_round_to_zero(src); -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, FPU registers[reg], extended); - sxp->ieee.exponent += scale_factor; -#else - fp_declare_init_shape(sxp, FPU registers[reg], double); - uae_u32 exp = sxp->ieee.exponent + scale_factor; - if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) - exp = 0; - else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) - exp = FP_DOUBLE_EXP_MAX; - else - exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - sxp->ieee.exponent = exp; -#endif - } - else if (fl_source.infinity) { - // Returns NaN for any Infinity source - make_nan( FPU registers[reg] ); - } - make_fpsr(FPU registers[reg]); - break; - case 0x27: /* FSGLMUL */ - fpu_debug(("FSGLMUL %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] * src); - make_fpsr(FPU registers[reg]); - break; - case 0x28: /* FSUB */ - fpu_debug(("FSUB %.04f\n",(double)src)); - FPU registers[reg] -= src; - make_fpsr(FPU registers[reg]); - break; - case 0x22: /* FADD */ - fpu_debug(("FADD %.04f\n",(double)src)); - FPU registers[reg] += src; - make_fpsr(FPU registers[reg]); - break; - case 0x30: /* FSINCOS */ - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - fpu_debug(("FSINCOS %.04f\n",(double)src)); - // Cosine must be calculated first if same register - FPU registers[extra & 7] = fp_cos(src); - FPU registers[reg] = fp_sin (src); - // Set FPU fpsr according to the sine result - make_fpsr(FPU registers[reg]); - break; - case 0x38: /* FCMP */ - fpu_debug(("FCMP %.04f\n",(double)src)); - set_fpsr(0); - make_fpsr(FPU registers[reg] - src); - break; - case 0x3a: /* FTST */ - fpu_debug(("FTST %.04f\n",(double)src)); - set_fpsr(0); - make_fpsr(src); - break; - default: - fpu_debug(("ILLEGAL F OP %X\n",opcode)); - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - break; - } - fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); - dump_registers( "END "); - return; - } - - fpu_debug(("ILLEGAL F OP 2 %X\n",opcode)); - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); -} - -/* -------------------------- Initialization -------------------------- */ - -PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 - -PUBLIC void FFPU fpu_init (bool integral_68040) -{ - fpu_debug(("fpu_init\n")); - - static bool initialized_lookup_tables = false; - if (!initialized_lookup_tables) { - fpu_init_native_fflags(); - fpu_init_native_exceptions(); - fpu_init_native_accrued_exceptions(); - initialized_lookup_tables = true; - } - - FPU is_integral = integral_68040; - FPU instruction_address = 0; - FPU fpsr.quotient = 0; - set_fpcr(0); - set_fpsr(0); - -#if defined(FPU_USE_X86_ROUNDING) - // Initial state after boot, reset and frestore(null frame) - x86_control_word = CW_INITIAL; -#elif defined(USE_X87_ASSEMBLY) - volatile unsigned short int cw; - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); - cw &= ~0x0300; cw |= 0x0300; // CW_PC_EXTENDED - cw &= ~0x0C00; cw |= 0x0000; // CW_RC_NEAR - __asm__ __volatile__("fldcw %0" : : "m" (cw)); -#endif - - FPU result = 1; - - for (int i = 0; i < 8; i++) - make_nan(FPU registers[i]); -} - -PUBLIC void FFPU fpu_exit (void) -{ - fpu_debug(("fpu_exit\n")); -} - -PUBLIC void FFPU fpu_reset (void) -{ - fpu_debug(("fpu_reset\n")); - fpu_exit(); - fpu_init(FPU is_integral); -} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h deleted file mode 100644 index 89501956..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_IEEE_H -#define FPU_IEEE_H - -/* NOTE: this file shall be included from fpu/fpu_uae.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -// Lauri-- full words to avoid partial register stalls. -struct double_flags { - uae_u32 in_range; - uae_u32 zero; - uae_u32 infinity; - uae_u32 nan; - uae_u32 negative; -}; -PRIVATE double_flags fl_source; -PRIVATE double_flags fl_dest; -PRIVATE inline void FFPU get_dest_flags(fpu_register const & r); -PRIVATE inline void FFPU get_source_flags(fpu_register const & r); - -PRIVATE inline void FFPU make_nan(fpu_register & r); -PRIVATE inline void FFPU make_zero_positive(fpu_register & r); -PRIVATE inline void FFPU make_zero_negative(fpu_register & r); -PRIVATE inline void FFPU make_inf_positive(fpu_register & r); -PRIVATE inline void FFPU make_inf_negative(fpu_register & r); - -PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); -PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); - -// May be optimized for particular processors -#ifndef FPU_USE_NATIVE_FLAGS -PRIVATE inline void FFPU make_fpsr(fpu_register const & r); -#endif - -// Normalize to range 1..2 -PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r); - -// The sign of the quotient is the exclusive-OR of the sign bits -// of the source and destination operands. -PRIVATE inline uae_u32 FFPU get_quotient_sign( - fpu_register const & ra, fpu_register const & rb -); - -// Quotient Byte is loaded with the sign and least significant -// seven bits of the quotient. -PRIVATE inline void FFPU make_quotient( - fpu_register const & quotient, uae_u32 sign -); - -// to_single -PRIVATE inline fpu_register FFPU make_single( - uae_u32 value -); - -// from_single -PRIVATE inline uae_u32 FFPU extract_single( - fpu_register const & src -); - -// to_exten -PRIVATE inline fpu_register FFPU make_extended( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 -); - -/* - Would be so much easier with full size floats :( - ... this is so vague. -*/ -// to_exten_no_normalize -PRIVATE inline void FFPU make_extended_no_normalize( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result -); - -// from_exten -PRIVATE inline void FFPU extract_extended(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -); - -// to_double -PRIVATE inline fpu_register FFPU make_double( - uae_u32 wrd1, uae_u32 wrd2 -); - -// from_double -PRIVATE inline void FFPU extract_double(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2 -); - -PRIVATE inline fpu_register FFPU make_packed( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 -); - -PRIVATE inline void FFPU extract_packed( - fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -); - -PRIVATE inline int FFPU get_fp_value( - uae_u32 opcode, uae_u16 extra, fpu_register & src -); - -PRIVATE inline int FFPU put_fp_value( - uae_u32 opcode, uae_u16 extra, fpu_register const & value -); - -PRIVATE inline int FFPU get_fp_ad( - uae_u32 opcode, uae_u32 * ad -); - -PRIVATE inline int FFPU fpp_cond( - int condition -); - -#endif /* FPU_IEEE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp deleted file mode 100644 index 70e59086..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp +++ /dev/null @@ -1,6126 +0,0 @@ -/* - * fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Based on UAE FPU, original copyright 1996 Herman ten Brugge, - * rewritten for x86 by Lauri Pesonen 1999-2000, - * accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Interface - * Almost the same as original. Please see the comments in "fpu.h". - * - * - * Why assembly? - * The reason is not really speed, but to get infinities, - * NANs and flags finally working. - * - * - * How to maintain Mac and x86 FPU flags -- plan B - * - * regs.piar is not updated. - * - * regs.FPU fpcr always contains the real 68881/68040 control word. - * - * regs.FPU fpsr is not kept up-to-date, for efficiency reasons. - * Most of the FPU commands update this in a way or another, but it is not - * read nearly that often. Therefore, three host-specific words hold the - * status byte and exception byte ("x86_status_word"), accrued exception - * byte ("x86_status_word_accrued") and the quotient byte ("FPU fpsr.quotient"), - * as explained below. - * - * CONDITION CODE - QUOTIENT - EXCEPTION STATUS - ACCRUED EXCEPTION - * CONDITION CODE (N,Z,I,NAN) - * - updated after each opcode, if needed. - * - x86 assembly opcodes call FXAM and store the status word to - * "x86_status_word". - * - When regs.FPU fpsr is actually used, the value of "x86_status_word" - * is translated. - * QUOTIENT BYTE - * - Updated by frem, fmod, frestore(null frame) - * - Stored in "FPU fpsr.quotient" in correct bit position, combined when - * regs.FPU fpsr is actually used. - * EXCEPTION STATUS (BSUN,SNAN,OPERR,OVFL,UNFL,DZ,INEX2,INEX1) - * - updated after each opcode, if needed. - * - Saved in x86 form in "x86_status_word". - * - When regs.FPU fpsr is actually used, the value of "x86_status_word" - * is translated. - * - Only fcc_op can set BSUN - * ACCRUED EXCEPTION (ACCR_IOP,ACCR_OVFL,ACCR_UNFL,ACCR_DZ,ACCR_INEX) - * - updated after each opcode, if needed. - * - Logically OR'ed in x86 form to "x86_status_word_accrued". - * - When regs.FPU fpsr is actually used, the value of - * "x86_status_word_accrued" is translated. - * - * When "x86_status_word" and "x86_status_word_accrued" are stored, - * all pending x86 FPU exceptions are cleared, if there are any. - * - * Writing to "regs.FPU fpsr" reverse-maps to x86 status/exception values and - * stores the values in "x86_status_word", "x86_status_word_accrued" - * and "FPU fpsr.quotient". - * - * So, "x86_status_word" and "x86_status_word_accrued" are not in - * correct bit positions and have x86 values, but "FPU fpsr.quotient" is at - * correct position. - * - * Note that it does not matter that the reverse-mapping is not exact - * (both SW_IE and SW_DE are mapped to ACCR_IOP, but ACCR_IOP maps to - * SW_IE only), the MacOS always sees the correct exception bits. - * - * Also note the usage of the fake BSUN flag SW_FAKE_BSUN. If you change - * the x86 FPU code, you must make sure that you don't generate any FPU - * stack faults. - * - * - * x86 co-processor initialization: - * - * Bit Code Use - * 0 IM Invalid operation exception mask 1 Disabled - * 1 DM Denormalized operand exception mask 1 Disabled - * 2 ZM Zerodivide exception mask 1 Disabled - * 3 OM Overflow exception mask 1 Disabled - * 4 UM Underflow exception mask 1 Disabled - * 5 PM Precision exception mask 1 Disabled - * 6 - - - - - * 7 IEM Interrupt enable mask 0 Enabled - * 8 PC Precision control\ 1 - 64 bits - * 9 PC Precision control/ 1 / - * 10 RC Rounding control\ 0 - Nearest even - * 11 RC Rounding control/ 0 / - * 12 IC Infinity control 1 Affine - * 13 - - - - - * 14 - - - - - * 15 - - - - - * - * - * TODO: - * - Exceptions are not implemented. - * - All tbyte variables should be aligned to 16-byte boundaries. - * (for best efficiency). - * - FTRAPcc code looks like broken. - * - If USE_3_BIT_QUOTIENT is 0, exceptions should be checked after - * float -> int rounding (frem,fmod). - * - The speed can be greatly improved. Do this only after you are sure - * that there are no major bugs. - * - Support for big-endian byte order (but all assembly code needs to - * be rewritten anyway) - * I have some non-portable code like *((uae_u16 *)&m68k_dreg(regs, reg)) = newv; - * Sorry about that, you need to change these. I could do it myself, but better - * not, I would have no way to test them out. - * I tried to mark all spots with a comment TODO_BIGENDIAN. - * - to_double() may need renormalization code. Or then again, maybe not. - * - Signaling NANs should be handled better. The current mapping of - * signaling nan exception to denormalized operand exception is only - * based on the idea that the (possible) handler sees that "something - * seriously wrong" and takes the same action. Should not really get (m)any - * of those since normalization is handled on to_exten() - * - */ - -#include -#include -#include -#include - -#include "sysdeps.h" -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#define FPU_IMPLEMENTATION -#include "fpu/fpu.h" -#include "fpu/fpu_x86.h" -#include "fpu/fpu_x86_asm.h" - -/* Global FPU context */ -fpu_t fpu; - -/* -------------------------------------------------------------------------- */ -/* --- Native Support --- */ -/* -------------------------------------------------------------------------- */ - -#include "fpu/flags.h" -#include "fpu/exceptions.h" -#include "fpu/rounding.h" -#include "fpu/impl.h" - -#include "fpu/flags.cpp" -#include "fpu/exceptions.cpp" -#include "fpu/rounding.cpp" - -/* -------------------------------------------------------------------------- */ -/* --- Scopes Definition --- */ -/* -------------------------------------------------------------------------- */ - -#undef PUBLIC -#define PUBLIC /**/ - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* ---------------------------- Compatibility ---------------------------- */ - -#define BYTE uint8 -#define WORD uint16 -#define DWORD uint32 -#define min(a, b) (((a) < (b)) ? (a) : (b)) - -/* ---------------------------- Configuration ---------------------------- */ - -/* -If USE_3_BIT_QUOTIENT is set to 1, FREM and FMOD use a faster version -with only 3 quotient bits (those provided by the x86 FPU). If set to 0, -they calculate the same 7 bits that m68k does. It seems (as for now) that -3 bits suffice for all Mac programs I have tried. - -If you decide that you need all 7 bits (USE_3_BIT_QUOTIENT is 0), -consider checking the host exception flags after FISTP (search for -"TODO:Quotient". The result may be too large to fit into a dword. -*/ -/* -gb-- I only tested the following configurations: - USE_3_BIT_QUOTIENT 1 -- still changes to apply if no 3-bit quotient - FPU_DEBUG 1 or 0 - USE_CONSISTENCY_CHECKING 0 - I3_ON_ILLEGAL_FPU_OP 0 -- and this won't change - I3_ON_FTRAPCC 0 -- and this won't change -*/ -#define USE_3_BIT_QUOTIENT 1 - -//#define FPU_DEBUG 0 -- now defined in "fpu/fpu.h" -#define USE_CONSISTENCY_CHECKING 0 - -#define I3_ON_ILLEGAL_FPU_OP 0 -#define I3_ON_FTRAPCC 0 - -/* ---------------------------- Debugging ---------------------------- */ - -PUBLIC void FFPU fpu_dump_registers(void) -{ - for (int i = 0; i < 8; i++){ - printf ("FP%d: %g ", i, fpu_get_register(i)); - if ((i & 3) == 3) - printf ("\n"); - } -} - -PUBLIC void FFPU fpu_dump_flags(void) -{ - printf ("N=%d Z=%d I=%d NAN=%d\n", - (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, - (get_fpsr() & FPSR_CCB_ZERO)!= 0, - (get_fpsr() & FPSR_CCB_INFINITY) != 0, - (get_fpsr() & FPSR_CCB_NAN) != 0); -} - -#include "debug.h" - -#if FPU_DEBUG -#undef __inline__ -#define __inline__ - -PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual) -{ - char bb[10]; - int32 i, bytes = min(actual,100); - - *b = 0; - for (i=0; i= 10) _ix = 0; - - sprintf( _s[_ix], "%.04f", (float)f ); - return( _s[_ix] ); -} - -PUBLIC void FFPU dump_registers(const char *s) -{ - char b[512]; - - sprintf( - b, - "%s: %s, %s, %s, %s, %s, %s, %s, %s\r\n", - s, - etos(FPU registers[0]), - etos(FPU registers[1]), - etos(FPU registers[2]), - etos(FPU registers[3]), - etos(FPU registers[4]), - etos(FPU registers[5]), - etos(FPU registers[6]), - etos(FPU registers[7]) - ); - D(bug((char*)b)); -} - -#else - -PUBLIC void FFPU dump_registers(const char *) -{ -} - -PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32) -{ -} - -#endif - - -/* ---------------------------- FPU consistency ---------------------------- */ - -#if USE_CONSISTENCY_CHECKING -PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void) -{ -/* _asm { - FNSTSW checked_sw_atstart - } */ - __asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_atstart)); -} - -PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name) -{ - uae_u16 checked_sw_atend; -// _asm FNSTSW checked_sw_atend - __asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_attend)); - char msg[256]; - - // Check for FPU stack overflows/underflows. - if( (checked_sw_atend & 0x3800) != (checked_sw_atstart & 0x3800) ) { - wsprintf( - msg, - "FPU stack leak at %s, %X, %X\r\n", - name, - (int)(checked_sw_atstart & 0x3800) >> 11, - (int)(checked_sw_atend & 0x3800) >> 11 - ); - OutputDebugString(msg); - } - - // Observe status mapping. - /* - if(checked_sw_atstart != 0x400 || checked_sw_atend != 0x400) { - wsprintf( - msg, "Op %s, x86_status_word before=%X, x86_status_word after=%X\r\n", - name, (int)checked_sw_atstart, (int)checked_sw_atend - ); - OutputDebugString(msg); - } - */ -} -#else -PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void) -{ -} - -PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *) -{ -} -#endif - - -/* ---------------------------- Status byte ---------------------------- */ - -// Map x86 FXAM codes -> m68k fpu status byte -#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3) -#define SW_Z (SW_C3) -#define SW_I (SW_C0|SW_C2) -#define SW_NAN (SW_C0) -#define SW_FINITE (SW_C2) -#define SW_EMPTY_REGISTER (SW_C0|SW_C3) -#define SW_DENORMAL (SW_C2|SW_C3) -#define SW_UNSUPPORTED (0) -#define SW_N (SW_C1) - -// Initial state after boot, reset and frestore(null frame) -#define SW_INITIAL SW_FINITE - - -/* ---------------------------- Status functions ---------------------------- */ - -PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN () -{ - if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) { - x86_status_word |= SW_FAKE_BSUN; - x86_status_word_accrued |= SW_IE; - } -} - -PRIVATE void __inline__ FFPU build_ex_status () -{ - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } -} - -// TODO_BIGENDIAN; all of these. -/* ---------------------------- Type functions ---------------------------- */ - -/* -When the FPU creates a NAN, the NAN always contains the same bit pattern -in the mantissa. All bits of the mantissa are ones for any precision. -When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa. -*/ -PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f) -{ - // Make it non-signaling. - uae_u8 * p = (uae_u8 *) &f; - memset( p, 0xFF, sizeof(fpu_register) - 1 ); - p[9] = 0x7F; -} - -/* -For single- and double-precision infinities the fraction is a zero. -For extended-precision infinities, the mantissa’s MSB, the explicit -integer bit, can be either one or zero. -*/ -PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f) -{ - uae_u8 * p = (uae_u8 *) &f; - if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { - if ((*((uae_u32 *)&p[0]) == 0) && - ((*((uae_u32 *)&p[4]) & 0x7FFFFFFF) == 0)) - return(1); - } - return(0); -} - -PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f) -{ - uae_u8 * p = (uae_u8 *) &f; - if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { - if ((*((uae_u32 *)&p[0]) == 0) && - ((*((uae_u32 *)&p[4]) & 0x7FFFFFFF) != 0)) - return(1); - } - return(0); -} - -PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f) -{ - uae_u8 * p = (uae_u8 *) &f; - return *((uae_u32 *)p) == 0 && - *((uae_u32 *)&p[4]) == 0 && - ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0; -} - -PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f) -{ - uae_u8 * p = (uae_u8 *) &f; - memset( p, 0, sizeof(fpu_register)-2 ); - *((uae_u16 *)&p[8]) = 0x7FFF; -} - -PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f) -{ - uae_u8 * p = (uae_u8 *) &f; - memset( p, 0, sizeof(fpu_register)-2 ); - *((uae_u16 *)&p[8]) = 0xFFFF; -} - -PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) -{ - uae_u32 * const p = (uae_u32 *) &f; - memset( p, 0, sizeof(fpu_register) ); -} - -PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) -{ - uae_u32 * const p = (uae_u32 *) &f; - memset( p, 0, sizeof(fpu_register) ); - *((uae_u32 *)&p[4]) = 0x80000000; -} - -PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) -{ - uae_u8 * p = (uae_u8 *) &f; - return( (p[9] & 0x80) != 0 ); -} - - -/* ---------------------------- Conversions ---------------------------- */ - -PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - -/* _asm { - MOV ESI, [f] - FILD DWORD PTR [x] - FSTP TBYTE PTR [ESI] - } */ - - __asm__ __volatile__("fildl %1\n\tfstpt %0" : "=m" (f) : "m" (x)); - D(bug("signed_to_extended (%X) = %s\r\n",(int)x,etos(f))); - FPU_CONSISTENCY_CHECK_STOP("signed_to_extended"); -} - -PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - volatile uae_s32 tmp; - volatile WORD sw_temp; - -/* _asm { - MOV EDI, [f] - FLD TBYTE PTR [EDI] - FISTP DWORD PTR tmp - FNSTSW sw_temp - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fistpl %0\n" - "fnstsw %1\n" - : "=m" (tmp), "=m" (sw_temp) - : "m" (f) - ); - - if(sw_temp & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. - x86_status_word |= SW_IE; - x86_status_word_accrued |= SW_IE; - // Setting the value to zero might not be the right way to go, - // but I'll leave it like this for now. - tmp = 0; - } - if(sw_temp & SW_PE) { - x86_status_word |= SW_PE; - x86_status_word_accrued |= SW_PE; - } - } - - D(bug("extended_to_signed_32 (%s) = %X\r\n",etos(f),(int)tmp)); - FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_32"); - return tmp; -} - -PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - volatile uae_s16 tmp; - volatile WORD sw_temp; - -/* _asm { - MOV EDI, [f] - FLD TBYTE PTR [EDI] - FISTP WORD PTR tmp - FNSTSW sw_temp - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fistp %0\n" - "fnstsw %1\n" - : "=m" (tmp), "=m" (sw_temp) - : "m" (f) - ); - - if(sw_temp & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. - x86_status_word |= SW_IE; - x86_status_word_accrued |= SW_IE; - tmp = 0; - } - if(sw_temp & SW_PE) { - x86_status_word |= SW_PE; - x86_status_word_accrued |= SW_PE; - } - } - - D(bug("extended_to_signed_16 (%s) = %X\r\n",etos(f),(int)tmp)); - FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_16"); - return tmp; -} - -PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - volatile uae_s16 tmp; - volatile WORD sw_temp; - -/* _asm { - MOV EDI, [f] - FLD TBYTE PTR [EDI] - FISTP WORD PTR tmp - FNSTSW sw_temp - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fistp %0\n" - "fnstsw %1\n" - : "=m" (tmp), "=m" (sw_temp) - : "m" (f) - ); - - if(sw_temp & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. - x86_status_word |= SW_IE; - x86_status_word_accrued |= SW_IE; - tmp = 0; - } - if(sw_temp & SW_PE) { - x86_status_word |= SW_PE; - x86_status_word_accrued |= SW_PE; - } - } - - if(tmp > 127 || tmp < -128) { // OPERR - x86_status_word |= SW_IE; - x86_status_word_accrued |= SW_IE; - } - - D(bug("extended_to_signed_8 (%s) = %X\r\n",etos(f),(int)tmp)); - FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_8"); - return (uae_s8)tmp; -} - -PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - -/* _asm { - MOV EDI, [f] - FLD QWORD PTR [x] - FSTP TBYTE PTR [EDI] - } */ - - __asm__ __volatile__( - "fldl %1\n" - "fstpt %0\n" - : "=m" (f) - : "m" (x) - ); - - FPU_CONSISTENCY_CHECK_STOP("double_to_extended"); -} - -PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - double result; - -/* _asm { - MOV ESI, [f] - FLD TBYTE PTR [ESI] - FSTP QWORD PTR result - } */ - - __asm__ __volatile__( - "fldt %1\n" - "fstpl %0\n" - : "=m" (result) - : "m" (f) - ); - - FPU_CONSISTENCY_CHECK_STOP("extended_to_double"); - return result; -} - -PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [f] - FLD DWORD PTR src - FSTP TBYTE PTR [ESI] - } */ - - __asm__ __volatile__( - "flds %1\n" - "fstpt %0\n" - : "=m" (f) - : "m" (src) - ); - - D(bug("to_single (%X) = %s\r\n",src,etos(f))); - FPU_CONSISTENCY_CHECK_STOP("to_single"); -} - -// TODO_BIGENDIAN -PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - uae_u32 *p = (uae_u32 *)&f; - - uae_u32 sign = (wrd1 & 0x80000000) >> 16; - uae_u32 exp = (wrd1 >> 16) & 0x7fff; - p[0] = wrd3; - p[1] = wrd2; - *((uae_u16 *)&p[2]) = (uae_u16)(sign | exp); - - D(bug("to_exten_no_normalize (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f))); - FPU_CONSISTENCY_CHECK_STOP("to_exten_no_normalize"); -} - -PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - uae_u32 *p = (uae_u32 *)&f; - - uae_u32 sign = (wrd1 & 0x80000000) >> 16; - uae_u32 exp = (wrd1 >> 16) & 0x7fff; - - // The explicit integer bit is not set, must normalize. - // Don't do it for zeroes, infinities or nans. - if( (wrd2 & 0x80000000) == 0 && exp != 0 && exp != 0x7FFF ) { - D(bug("to_exten denormalized mantissa (%X,%X,%X)\r\n",wrd1,wrd2,wrd3)); - if( wrd2 | wrd3 ) { - // mantissa, not fraction. - uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; - while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) { - man <<= 1; - exp--; - } - wrd2 = (uae_u32)( man >> 32 ); - wrd3 = (uae_u32)( man & 0xFFFFFFFF ); - if( exp == 0 || (wrd2 & 0x80000000) == 0 ) { - // underflow - wrd2 = wrd3 = exp = 0; - sign = 0; - } - } else { - if(exp != 0x7FFF && exp != 0) { - // Make a non-signaling nan. - exp = 0x7FFF; - sign = 0; - wrd2 = 0x80000000; - } - } - } - - p[0] = wrd3; - p[1] = wrd2; - *((uae_u16 *)&p[2]) = (uae_u16)(sign | exp); - - D(bug("to_exten (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f))); - FPU_CONSISTENCY_CHECK_STOP("to_exten"); -} - -PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - - // gb-- make GCC happy - union { - uae_u64 q; - uae_u32 l[2]; - } src; - - // Should renormalize if needed. I'm not sure that x86 and m68k FPU's - // do it the sama way. This should be extremely rare however. - // to_exten() is often called with denormalized values. - - src.l[0] = wrd2; - src.l[1] = wrd1; - -/* _asm { - FLD QWORD PTR src - MOV EDI, [f] - FSTP TBYTE PTR [EDI] - } */ - - __asm__ __volatile__( - "fldl %1\n" - "fstpt %0\n" - : "=m" (f) - : "m" (src.q) - ); - - D(bug("to_double (%X,%X) = %s\r\n",wrd1,wrd2,etos(f))); - FPU_CONSISTENCY_CHECK_STOP("to_double"); -} - -PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) -{ - FPU_CONSISTENCY_CHECK_START(); - volatile uae_u32 dest; - volatile WORD sw_temp; - -/* _asm { - MOV EDI, [f] - FLD TBYTE PTR [EDI] - FSTP DWORD PTR dest - FNSTSW sw_temp - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fstps %0\n" - "fnstsw %1\n" - : "=m" (dest), "=m" (sw_temp) - : "m" (f) - ); - - sw_temp &= SW_EXCEPTION_MASK; - if(sw_temp) { -// _asm FNCLEX - asm("fnclex"); - x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp; - x86_status_word_accrued |= sw_temp; - } - - D(bug("from_single (%s) = %X\r\n",etos(f),dest)); - FPU_CONSISTENCY_CHECK_STOP("from_single"); - return dest; -} - -// TODO_BIGENDIAN -PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) -{ - FPU_CONSISTENCY_CHECK_START(); - uae_u32 *p = (uae_u32 *)&f; - *wrd3 = p[0]; - *wrd2 = p[1]; - *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; - - D(bug("from_exten (%s) = %X,%X,%X\r\n",etos(f),*wrd1,*wrd2,*wrd3)); - FPU_CONSISTENCY_CHECK_STOP("from_exten"); -} - -PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) -{ - FPU_CONSISTENCY_CHECK_START(); - volatile uae_u32 dest[2]; - volatile WORD sw_temp; - -/* _asm { - MOV EDI, [f] - FLD TBYTE PTR [EDI] - FSTP QWORD PTR dest - FNSTSW sw_temp - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fstpl %0\n" - "fnstsw %1\n" - : "=m" (dest), "=m" (sw_temp) - : "m" (f) - ); - - sw_temp &= SW_EXCEPTION_MASK; - if(sw_temp) { -// _asm FNCLEX - asm("fnclex"); - x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp; - x86_status_word_accrued |= sw_temp; - } - - // TODO: There is a partial memory stall, nothing happens until FSTP retires. - // On PIII, could use MMX move w/o any penalty. - *wrd2 = dest[0]; - *wrd1 = dest[1]; - - D(bug("from_double (%s) = %X,%X\r\n",etos(f),dest[1],dest[0])); - FPU_CONSISTENCY_CHECK_STOP("from_double"); -} - -PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fmove"); -} - -/* -PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FSTP TBYTE PTR [EDI] - } - FPU_CONSISTENCY_CHECK_STOP("do_fmove_no_status"); -} -*/ - - -/* ---------------------------- Operations ---------------------------- */ - -PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FRNDINT - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "frndint\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fint"); -} - -PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - WORD cw_temp; - -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FSTCW cw_temp - and cw_temp, ~X86_ROUNDING_MODE - or cw_temp, CW_RC_ZERO - FLDCW cw_temp - FLD TBYTE PTR [ESI] - FRNDINT - FXAM - FNSTSW x86_status_word - FLDCW x86_control_word - FSTP TBYTE PTR [EDI] - } */ - - __asm__ __volatile__( - "fstcw %0\n" - "andl $(~X86_ROUNDING_MODE), %0\n" - "orl $CW_RC_ZERO, %0\n" - "fldcw %0\n" - "fldt %3\n" - "frndint\n" - "fxam \n" - "fnstsw %1\n" - "fldcw %4\n" - "fstpt %2\n" - : "+m" (cw_temp), "=m" (x86_status_word), "=m" (dest) - : "m" (src), "m" (x86_control_word) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fintrz"); -} - -PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FSQRT - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - - __asm__ __volatile__( - "fldt %2\n" - "fsqrt \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsqrt"); -} - -PRIVATE void FFPU do_ftst ( fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - FLD TBYTE PTR [ESI] - FXAM - FNSTSW x86_status_word - FSTP ST(0) - } */ - - __asm__ __volatile__( - "fldt %1\n" - "fxam \n" - "fnstsw %0\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word) - : "m" (src) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_ftst"); -} - -// These functions are calculated in 53 bits accuracy only. -// Exception checking is not complete. -PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = sinh(x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fsinh"); -} - -PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = log (x + 1.0); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_flognp1"); -} - -PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = exp (x) - 1.0; - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fetoxm1"); -} - -PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = tanh (x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_ftanh"); -} - -PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = atan (x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fatan"); -} - -PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = asin (x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fasin"); -} - -PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = log ((1 + x) / (1 - x)) / 2; - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fatanh"); -} - -PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = exp (x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fetox"); -} - -PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = pow(2.0, x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_ftwotox"); -} - -PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = pow(10.0, x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_ftentox"); -} - -PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = log (x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_flogn"); -} - -PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = log10 (x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_flog10"); -} - -PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = log (x) / log (2.0); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_flog2"); -} - -PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = acos(x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_facos"); -} - -PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - double x, y; - x = extended_to_double( src ); - y = cosh(x); - double_to_extended( y, dest ); - do_ftst( dest ); - FPU_CONSISTENCY_CHECK_STOP("do_fcosh"); -} - -PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FSIN - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fsin \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsin"); -} - -// TODO: Should check for out-of-range condition (partial tangent) -PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FPTAN - FSTP ST(0) ; pop 1.0 (the 8087/287 compatibility thing) - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fptan \n" - "fstp %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE - SW_UE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_ftan"); -} - -PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FABS - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fabs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fabs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fabs"); -} - -PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FCHS - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fchs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fchs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fneg"); -} - -PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FCOS - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fcos \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fcos"); -} - -PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FXTRACT - FSTP ST(0) ; pop mantissa - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fxtract\n" - "fstp %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fgetexp"); -} - -PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FXTRACT - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) ; pop exponent - } */ - __asm__ __volatile__( - "fldt %2\n" - "fxtract\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fgetman"); -} - -PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FDIV ST(0),ST(1) - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } */ - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fdiv %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdiv"); -} - -// The sign of the quotient is the exclusive-OR of the sign bits -// of the source and destination operands. -// Quotient Byte is loaded with the sign and least significant -// seven bits of the quotient. - -PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - - volatile uint16 status; - uae_u32 quot; -#if !USE_3_BIT_QUOTIENT - WORD cw_temp; -#endif - - uae_u8 * dest_p = (uae_u8 *)&dest; - uae_u8 * src_p = (uae_u8 *)&src; - uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; - -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - -#if !USE_3_BIT_QUOTIENT - MOV CX, x86_control_word - AND CX, ~X86_ROUNDING_MODE - OR CX, CW_RC_ZERO - MOV cw_temp, CX - FLDCW cw_temp - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FDIV ST(0),ST(1) - FABS - FISTP DWORD PTR quot - FSTP ST(0) - FLDCW x86_control_word - // TODO:Quotient - // Should clear any possible exceptions here -#endif - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - -// loop until the remainder is not partial any more. -partial_loop: - FPREM - FNSTSW status - TEST status, SW_C2 - JNE partial_loop - - - FXAM - FNSTSW x86_status_word - - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } */ - -#if !USE_3_BIT_QUOTIENT - - __asm__ __volatile__( - "movl %6, %%ecx\n" // %6: x86_control_word (read) - "andl $(~X86_ROUNDING_MODE), %%ecx\n" - "orl $CW_RC_ZERO, %%ecx\n" - "movl %%ecx, %0\n" // %0: cw_temp (read/write) - "fldcw %0\n" - "fldt %5\n" - "fldt %4\n" - "fdiv %%st(1), %%st(0)\n" - "fabs \n" - "fistpl %1\n" // %1: quot (read/write) - "fstp %%st(0)\n" - "fldcw %6\n" - "fldt %5\n" - "fldt %4\n" - "0:\n" // partial_loop - "fprem \n" - "fnstsw %2\n" // %2: status (read/write) - "testl $SW_C2, %2\n" - "jne 0b\n" - "fxam \n" - "fnstsw %3\n" // %3: x86_status_word (write) - "fstpt %4\n" - "fstp %%st(0)\n" - : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest) - : "m" (src), "m" (x86_control_word) - : "ecx" - ); - -#else - - __asm__ __volatile__( - "fldt %3\n" - "fldt %2\n" - "0:\n" // partial_loop - "fprem \n" - "fnstsw %0\n" // %0: status (read/write) - "testl $SW_C2, %0\n" - "jne 0b\n" - "fxam \n" - "fnstsw %1\n" // %1: x86_status_word (write) - "fstpt %2\n" - "fstp %%st(0)\n" - : "+m" (status), "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - -#endif - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - x86_status_word_accrued |= x86_status_word; - } - -#if USE_3_BIT_QUOTIENT - // SW_C1 Set to least significant bit of quotient (Q0). - // SW_C3 Set to bit 1 (Q1) of the quotient. - // SW_C0 Set to bit 2 (Q2) of the quotient. - quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9); - FPU fpsr.quotient = (sign | quot) << 16; -#else - FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; -#endif - - FPU_CONSISTENCY_CHECK_STOP("do_fmod"); -} - -PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - - volatile uint16 status; - uae_u32 quot; -#if !USE_3_BIT_QUOTIENT - WORD cw_temp; -#endif - - uae_u8 * dest_p = (uae_u8 *)&dest; - uae_u8 * src_p = (uae_u8 *)&src; - uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; - -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - -#if !USE_3_BIT_QUOTIENT - MOV CX, x86_control_word - AND CX, ~X86_ROUNDING_MODE - OR CX, CW_RC_NEAR - MOV cw_temp, CX - FLDCW cw_temp - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FDIV ST(0),ST(1) - FABS - FISTP DWORD PTR quot - FSTP ST(0) - FLDCW x86_control_word - // TODO:Quotient - // Should clear any possible exceptions here -#endif - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - -// loop until the remainder is not partial any more. -partial_loop: - FPREM1 - FNSTSW status - TEST status, SW_C2 - JNE partial_loop - - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } */ - -#if !USE_3_BIT_QUOTIENT - - __asm__ __volatile__( - "movl %6, %%ecx\n" // %6: x86_control_word (read) - "andl $(~X86_ROUNDING_MODE), %%ecx\n" - "orl $CW_RC_NEAR, %%ecx\n" - "movl %%ecx, %0\n" // %0: cw_temp (read/write) - "fldcw %0\n" - "fldt %5\n" - "fldt %4\n" - "fdiv %%st(1), %%st(0)\n" - "fabs \n" - "fistpl %1\n" // %1: quot (read/write) - "fstp %%st(0)\n" - "fldcw %6\n" - "fldt %5\n" - "fldt %4\n" - "0:\n" // partial_loop - "fprem1 \n" - "fnstsw %2\n" // %2: status (read/write) - "testl $SW_C2, %2\n" - "jne 0b\n" - "fxam \n" - "fnstsw %3\n" // %3: x86_status_word (write) - "fstpt %4\n" - "fstp %%st(0)\n" - : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest) - : "m" (src), "m" (x86_control_word) - : "ecx" - ); - -#else - - __asm__ __volatile__( - "fldt %3\n" - "fldt %2\n" - "0:\n" // partial_loop - "fprem1 \n" - "fnstsw %0\n" // %0: status (read/write) - "testl $SW_C2, %0\n" - "jne 0b\n" - "fxam \n" - "fnstsw %1\n" // %1: x86_status_word (write) - "fstpt %2\n" - "fstp %%st(0)\n" - : "+m" (status), "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - -#endif - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - x86_status_word_accrued |= x86_status_word; - } - -#if USE_3_BIT_QUOTIENT - // SW_C1 Set to least significant bit of quotient (Q0). - // SW_C3 Set to bit 1 (Q1) of the quotient. - // SW_C0 Set to bit 2 (Q2) of the quotient. - quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9); - FPU fpsr.quotient = (sign | quot) << 16; -#else - FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; -#endif - - FPU_CONSISTENCY_CHECK_STOP("do_frem"); -} - -// Faster versions. The current rounding mode is already correct. -#if !USE_3_BIT_QUOTIENT -PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - - volatile uint16 status; - uae_u32 quot; - - uae_u8 * dest_p = (uae_u8 *)&dest; - uae_u8 * src_p = (uae_u8 *)&src; - uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; - - _asm { - MOV ESI, [src] - MOV EDI, [dest] - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FDIV ST(0),ST(1) - FABS - FISTP DWORD PTR quot - FSTP ST(0) - // TODO:Quotient - // Should clear any possible exceptions here - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - -// loop until the remainder is not partial any more. -partial_loop: - FPREM - FNSTSW status - TEST status, SW_C2 - JNE partial_loop - - FXAM - FNSTSW x86_status_word - - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } - if(x86_status_word & SW_EXCEPTION_MASK) { - _asm FNCLEX - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - x86_status_word_accrued |= x86_status_word; - } - FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; - FPU_CONSISTENCY_CHECK_STOP("do_fmod_dont_set_cw"); -} - -PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - - volatile uint16 status; - uae_u32 quot; - - uae_u8 * dest_p = (uae_u8 *)&dest; - uae_u8 * src_p = (uae_u8 *)&src; - uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; - - _asm { - MOV ESI, [src] - MOV EDI, [dest] - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FDIV ST(0),ST(1) - FABS - FISTP DWORD PTR quot - FSTP ST(0) - // TODO:Quotient - // Should clear any possible exceptions here - - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - -// loop until the remainder is not partial any more. -partial_loop: - FPREM1 - FNSTSW status - TEST status, SW_C2 - JNE partial_loop - - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } - if(x86_status_word & SW_EXCEPTION_MASK) { - _asm FNCLEX - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); - x86_status_word_accrued |= x86_status_word; - } - FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; - FPU_CONSISTENCY_CHECK_STOP("do_frem_dont_set_cw"); -} -#endif //USE_3_BIT_QUOTIENT - -PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FADD - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fadd \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fadd"); -} - -PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FMUL - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fmul \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fmul"); -} - -PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - WORD cw_temp; -/* _asm { - FSTCW cw_temp - and cw_temp, ~X86_ROUNDING_PRECISION - or cw_temp, PRECISION_CONTROL_SINGLE - FLDCW cw_temp - - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FDIV ST(0),ST(1) - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - FLDCW x86_control_word - } */ - __asm__ __volatile__( - "fstcw %0\n" - "andl $(~X86_ROUNDING_PRECISION), %0\n" - "orl $PRECISION_CONTROL_SINGLE, %0\n" - "fldcw %0\n" - "fldt %3\n" - "fldt %2\n" - "fdiv %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %1\n" - "fstpt %2\n" - "fstp %%st(0)\n" - "fldcw %4\n" - : "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest) - : "m" (src), "m" (x86_control_word) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsgldiv"); -} - -PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FSCALE - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } */ - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fscale \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_UE - SW_OE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fscale"); -} - -PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - WORD cw_temp; - -/* _asm { - FSTCW cw_temp - and cw_temp, ~X86_ROUNDING_PRECISION - or cw_temp, PRECISION_CONTROL_SINGLE - FLDCW cw_temp - - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FMUL - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - - FLDCW x86_control_word - } */ - __asm__ __volatile__( - "fstcw %0\n" - "andl $(~X86_ROUNDING_PRECISION), %0\n" - "orl $PRECISION_CONTROL_SINGLE, %0\n" - "fldcw %0\n" - "fldt %3\n" - "fldt %2\n" - "fmul \n" - "fxam \n" - "fnstsw %1\n" - "fstpt %2\n" - "fldcw %4\n" - : "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest) - : "m" (src), "m" (x86_status_word) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsglmul"); -} - -PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FSUB ST(0),ST(1) - FXAM - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } */ - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fsub %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsub"); -} - -PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest_cos] - FLD TBYTE PTR [ESI] - FSINCOS - FSTP TBYTE PTR [EDI] - FXAM - MOV EDI, [dest_sin] - FNSTSW x86_status_word - FSTP TBYTE PTR [EDI] - FSTP ST(0) - } */ - __asm__ __volatile__( - "fldt %3\n" - "fsincos\n" - "fstpt %1\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %2\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "=m" (dest_cos), "=m" (dest_sin) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsincos"); -} - -PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - MOV ESI, [src] - MOV EDI, [dest] - FLD TBYTE PTR [ESI] - FLD TBYTE PTR [EDI] - FSUB ST(0),ST(1) - FXAM - FNSTSW x86_status_word - FSTP ST(0) - FSTP ST(0) - } */ - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fsub %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstp %%st(0)\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word) - : "m" (dest), "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fcmp"); -} - -// More or less original. Should be reviewed. -PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - FPU_CONSISTENCY_CHECK_START(); - - double d; - char *cp; - char str[100]; - - cp = str; - if (wrd1 & 0x80000000) - *cp++ = '-'; - *cp++ = (char)((wrd1 & 0xf) + '0'); - *cp++ = '.'; - *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); - *cp++ = 'E'; - if (wrd1 & 0x40000000) - *cp++ = '-'; - *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); - *cp = 0; - sscanf(str, "%le", &d); - - D(bug("to_pack str = %s\r\n",str)); - - D(bug("to_pack(%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)d)); - - FPU_CONSISTENCY_CHECK_STOP("to_pack"); - - return d; -} - -// More or less original. Should be reviewed. -PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) -{ - FPU_CONSISTENCY_CHECK_START(); - - int i; - int t; - char *cp; - char str[100]; - int exponent_digit_count = 0; - - sprintf(str, "%.16e", src); - - D(bug("from_pack(%.04f,%s)\r\n",(float)src,str)); - - cp = str; - *wrd1 = *wrd2 = *wrd3 = 0; - if (*cp == '-') { - cp++; - *wrd1 = 0x80000000; - } - if (*cp == '+') - cp++; - *wrd1 |= (*cp++ - '0'); - if (*cp == '.') - cp++; - for (i = 0; i < 8; i++) { - *wrd2 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd2 |= *cp++ - '0'; - } - for (i = 0; i < 8; i++) { - *wrd3 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd3 |= *cp++ - '0'; - } - if (*cp == 'e' || *cp == 'E') { - cp++; - if (*cp == '-') { - cp++; - *wrd1 |= 0x40000000; - } - if (*cp == '+') - cp++; - t = 0; - for (i = 0; i < 3; i++) { - if (*cp >= '0' && *cp <= '9') { - t = (t << 4) | (*cp++ - '0'); - exponent_digit_count++; - } - } - *wrd1 |= t << 16; - } - - D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); - - WORD sw_temp; -// _asm FNSTSW sw_temp - __asm__ __volatile__("fnstsw %0" : "=m" (sw_temp)); - if(sw_temp & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - if(sw_temp & SW_PE) { - x86_status_word |= SW_PE; - x86_status_word_accrued |= SW_PE; - } - } - - /* - OPERR is set if the k-factor > + 17 or the magnitude of - the decimal exponent exceeds three digits; - cleared otherwise. - */ - if(exponent_digit_count > 3) { - x86_status_word |= SW_IE; - x86_status_word_accrued |= SW_IE; - } - - FPU_CONSISTENCY_CHECK_STOP("from_pack"); -} - -PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) -{ - static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - // D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra)); - // dump_first_bytes( regs.pc_p-4, 16 ); - - if ((extra & 0x4000) == 0) { - memcpy( &src, &FPU registers[(extra >> 10) & 7], sizeof(fpu_register) ); -// do_fmove_no_status( src, FPU registers[(extra >> 10) & 7] ); - return 1; - } - - int mode = (opcode >> 3) & 7; - int reg = opcode & 7; - int size = (extra >> 10) & 7; - uae_u32 ad = 0; - - // D(bug("get_fp_value mode=%d, reg=%d, size=%d\r\n",(int)mode,(int)reg,(int)size)); - - switch ((uae_u8)mode) { - case 0: - switch ((uae_u8)size) { - case 6: - signed_to_extended( (uae_s32)(uae_s8) m68k_dreg (regs, reg), src ); - break; - case 4: - signed_to_extended( (uae_s32)(uae_s16) m68k_dreg (regs, reg), src ); - break; - case 0: - signed_to_extended( (uae_s32) m68k_dreg (regs, reg), src ); - break; - case 1: - to_single( m68k_dreg (regs, reg), src ); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch ((uae_u8)reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: { - uaecptr tmppc = m68k_getpc (); - uae_u16 tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - } - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - - /* - +0000 000004 FSCALE.B #$01,FP2 | F23C 5926 0001 - F23C 1111001000111100 - 5926 0101100100100110 - 0001 0000000000000001 - mode = 7 - reg = 4 - size = 6 - */ - // Immediate addressing mode && Operation Length == Byte -> - // Use the low-order byte of the extension word. - - if(size == 6) ad++; - - // May be faster on a PII(I), sz2[size] is already in register - // ad += sz2[size] - sz1[size]; - - break; - default: - return 0; - } - } - - switch ((uae_u8)size) { - case 0: - signed_to_extended( (uae_s32) get_long (ad), src ); - break; - case 1: - to_single( get_long (ad), src ); - break; - - case 2:{ - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - to_exten( wrd1, wrd2, wrd3, src ); - } - break; - case 3:{ - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - double_to_extended( to_pack(wrd1, wrd2, wrd3), src ); - } - break; - case 4: - signed_to_extended( (uae_s32)(uae_s16) get_word(ad), src ); - break; - case 5:{ - uae_u32 wrd1, wrd2; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - to_double(wrd1, wrd2, src); - } - break; - case 6: - signed_to_extended( (uae_s32)(uae_s8) get_byte(ad), src ); - break; - default: - return 0; - } - - // D(bug("get_fp_value result = %.04f\r\n",(float)src)); - - return 1; -} - -PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) -{ - static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra)); - - if ((extra & 0x4000) == 0) { - int dest_reg = (extra >> 10) & 7; - do_fmove( FPU registers[dest_reg], value ); - build_ex_status(); - return 1; - } - - int mode = (opcode >> 3) & 7; - int reg = opcode & 7; - int size = (extra >> 10) & 7; - uae_u32 ad = 0xffffffff; - - // Clear exception status - x86_status_word &= ~SW_EXCEPTION_MASK; - - switch ((uae_u8)mode) { - case 0: - switch ((uae_u8)size) { - case 6: - *((uae_u8 *)&m68k_dreg(regs, reg)) = extended_to_signed_8(value); - break; - case 4: - // TODO_BIGENDIAN - *((uae_u16 *)&m68k_dreg(regs, reg)) = extended_to_signed_16(value); - break; - case 0: - m68k_dreg (regs, reg) = extended_to_signed_32(value); - break; - case 1: - m68k_dreg (regs, reg) = from_single(value); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch ((uae_u8)reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: { - uaecptr tmppc = m68k_getpc (); - uae_u16 tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - } - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - break; - default: - return 0; - } - } - switch ((uae_u8)size) { - case 0: - put_long (ad, (uae_s32) extended_to_signed_32(value)); - break; - case 1: - put_long (ad, from_single(value)); - break; - case 2: { - uae_u32 wrd1, wrd2, wrd3; - from_exten(value, &wrd1, &wrd2, &wrd3); - - x86_status_word &= ~SW_EXCEPTION_MASK; - if(wrd3) { // TODO: not correct! Just a "smart" guess. - x86_status_word |= SW_PE; - x86_status_word_accrued |= SW_PE; - } - - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - } - break; - case 3: { - uae_u32 wrd1, wrd2, wrd3; - from_pack(extended_to_double(value), &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - } - break; - case 4: - put_word(ad, extended_to_signed_16(value)); - break; - case 5:{ - uae_u32 wrd1, wrd2; - from_double(value, &wrd1, &wrd2); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - } - break; - case 6: - put_byte(ad, extended_to_signed_8(value)); - - break; - default: - return 0; - } - return 1; -} - -PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) -{ - int mode = (opcode >> 3) & 7; - int reg = opcode & 7; - switch ( (uae_u8)mode ) { - case 0: - case 1: - if( (opcode & 0xFF00) == 0xF300 ) { - // fsave, frestore - m68k_setpc (m68k_getpc () - 2); - } else { - m68k_setpc (m68k_getpc () - 4); - } - op_illg (opcode); - dump_registers( "END "); - return 0; - case 2: - *ad = m68k_areg (regs, reg); - break; - case 3: - *ad = m68k_areg (regs, reg); - break; - case 4: - *ad = m68k_areg (regs, reg); - break; - case 5: - *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch ( (uae_u8)reg ) { - case 0: - *ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - *ad = next_ilong(); - break; - case 2: - *ad = m68k_getpc (); - *ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: { - uaecptr tmppc = m68k_getpc (); - uae_u16 tmp = (uae_u16)next_iword(); - *ad = get_disp_ea_020 (tmppc, tmp); - } - break; - default: - if( (opcode & 0xFF00) == 0xF300 ) { - // fsave, frestore - m68k_setpc (m68k_getpc () - 2); - } else { - m68k_setpc (m68k_getpc () - 4); - } - op_illg (opcode); - dump_registers( "END "); - return 0; - } - } - return 1; -} - -#if FPU_DEBUG -#define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x) -#else -#define CONDRET(s,x) return (x) -#endif - -PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) -{ - -#define N (x86_status_word & SW_N) -#define Z ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_Z) -#define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I)) -#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN) - - switch (condition) { - // Common Tests, no BSUN - case 0x01: - CONDRET("Equal",Z); - case 0x0e: - CONDRET("Not Equal",!Z); - - // IEEE Nonaware Tests, BSUN - case 0x12: - SET_BSUN_ON_NAN(); - CONDRET("Greater Than",!(NotANumber || Z || N)); - case 0x1d: - SET_BSUN_ON_NAN(); - CONDRET("Not Greater Than",NotANumber || Z || N); - case 0x13: - SET_BSUN_ON_NAN(); - CONDRET("Greater Than or Equal",Z || !(NotANumber || N)); - case 0x1c: - SET_BSUN_ON_NAN(); - CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N)); - case 0x14: - SET_BSUN_ON_NAN(); - CONDRET("Less Than",N && !(NotANumber || Z)); - case 0x1b: - SET_BSUN_ON_NAN(); - CONDRET("Not Less Than",NotANumber || Z || !N); - case 0x15: - SET_BSUN_ON_NAN(); - CONDRET("Less Than or Equal",Z || (N && !NotANumber)); - case 0x1a: - SET_BSUN_ON_NAN(); - CONDRET("Not Less Than or Equal",NotANumber || !(N || Z)); - case 0x16: - SET_BSUN_ON_NAN(); - CONDRET("Greater or Less Than",!(NotANumber || Z)); - case 0x19: - SET_BSUN_ON_NAN(); - CONDRET("Not Greater or Less Than",NotANumber || Z); - case 0x17: - CONDRET("Greater, Less or Equal",!NotANumber); - case 0x18: - SET_BSUN_ON_NAN(); - CONDRET("Not Greater, Less or Equal",NotANumber); - - // IEEE Aware Tests, no BSUN - case 0x02: - CONDRET("Ordered Greater Than",!(NotANumber || Z || N)); - case 0x0d: - CONDRET("Unordered or Less or Equal",NotANumber || Z || N); - case 0x03: - CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N)); - case 0x0c: - CONDRET("Unordered or Less Than",NotANumber || (N && !Z)); - case 0x04: - CONDRET("Ordered Less Than",N && !(NotANumber || Z)); - case 0x0b: - CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N); - case 0x05: - CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber)); - case 0x0a: - CONDRET("Unordered or Greater Than",NotANumber || !(N || Z)); - case 0x06: - CONDRET("Ordered Greater or Less Than",!(NotANumber || Z)); - case 0x09: - CONDRET("Unordered or Equal",NotANumber || Z); - case 0x07: - CONDRET("Ordered",!NotANumber); - case 0x08: - CONDRET("Unordered",NotANumber); - - // Miscellaneous Tests, no BSUN - case 0x00: - CONDRET("False",0); - case 0x0f: - CONDRET("True",1); - - // Miscellaneous Tests, BSUN - case 0x10: - SET_BSUN_ON_NAN(); - CONDRET("Signaling False",0); - case 0x1f: - SET_BSUN_ON_NAN(); - CONDRET("Signaling True",1); - case 0x11: - SET_BSUN_ON_NAN(); - CONDRET("Signaling Equal",Z); - case 0x1e: - SET_BSUN_ON_NAN(); - CONDRET("Signaling Not Equal",!Z); - } - CONDRET("",-1); - -#undef N -#undef Z -#undef I -#undef NotANumber - -} - -PUBLIC void REGPARAM2 FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) -{ - uaecptr pc = (uae_u32) m68k_getpc (); - uae_s32 disp = (uae_s32) (uae_s16) next_iword(); - int cc; - - D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - cc = fpp_cond(opcode, extra & 0x3f); - if (cc < 0) { - m68k_setpc (pc - 4); - op_illg (opcode); - } else if (!cc) { - int reg = opcode & 0x7; - - // TODO_BIGENDIAN - uae_u16 newv = (uae_u16)(m68k_dreg (regs, reg) & 0xffff) - 1; - *((uae_u16 *)&m68k_dreg(regs, reg)) = newv; - - if (newv != 0xffff) - m68k_setpc (pc + disp); - } -} - -PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) -{ - uae_u32 ad; - int cc; - - D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - cc = fpp_cond(opcode, extra & 0x3f); - if (cc < 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } else if ((opcode & 0x38) == 0) { - // TODO_BIGENDIAN - m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | - (cc ? 0xff : 0x00); - } else { - if (get_fp_ad(opcode, &ad)) { - put_byte(ad, cc ? 0xff : 0x00); - } - } -} - -PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) -{ - int cc; - - D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ())); - -#if I3_ON_FTRAPCC -#error "FIXME: _asm int 3" - _asm int 3 -#endif - - // This must be broken. - cc = fpp_cond(opcode, opcode & 0x3f); - - if (cc < 0) { - m68k_setpc (oldpc); - op_illg (opcode); - } else if (cc) - Exception(7, oldpc - 2); -} - -// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) -PUBLIC void REGPARAM2 FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) -{ - int cc; - - D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); - - cc = fpp_cond(opcode, opcode & 0x3f); - if (cc < 0) { - m68k_setpc (pc); - op_illg (opcode); - } else if (cc) { - if ((opcode & 0x40) == 0) - extra = (uae_s32) (uae_s16) extra; - m68k_setpc (pc + extra); - } -} - -// FSAVE has no post-increment -// 0x1f180000 == IDLE state frame, coprocessor version number 1F -PUBLIC void REGPARAM2 FFPU fpuop_save(uae_u32 opcode) -{ - uae_u32 ad; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - int i; - - D(bug("fsave_opp at %08lx\r\n", m68k_getpc ())); - - if (get_fp_ad(opcode, &ad)) { - if (FPU is_integral) { - // Put 4 byte 68040 IDLE frame. - if (incr < 0) { - ad -= 4; - put_long (ad, 0x41000000); - } else { - put_long (ad, 0x41000000); - ad += 4; - } - } else { - // Put 28 byte 68881 IDLE frame. - if (incr < 0) { - D(bug("fsave_opp pre-decrement\r\n")); - ad -= 4; - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); - } - ad -= 4; - put_long (ad, 0x1f180000); // IDLE, vers 1f - } else { - put_long (ad, 0x1f180000); // IDLE, vers 1f - ad += 4; - for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); - ad += 4; - } - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - ad += 4; - } - } - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - D(bug("PROBLEM: fsave_opp post-increment\r\n")); - } - if ((opcode & 0x38) == 0x20) { - m68k_areg (regs, opcode & 7) = ad; - D(bug("fsave_opp pre-decrement %X -> A%d\r\n",ad,opcode & 7)); - } - } -} - -PRIVATE void FFPU do_null_frestore () -{ - // A null-restore operation sets FP7-FP0 positive, nonsignaling NANs. - for( int i=0; i<8; i++ ) { - MAKE_NAN( FPU registers[i] ); - } - - FPU instruction_address = 0; - set_fpcr(0); - set_fpsr(0); - - x86_status_word = SW_INITIAL; - x86_status_word_accrued = 0; - FPU fpsr.quotient = 0; - - x86_control_word = CW_INITIAL; -/* _asm FLDCW x86_control_word - _asm FNCLEX */ - __asm__ __volatile__("fldcw %0\n\tfnclex" : : "m" (x86_control_word)); -} - -// FSAVE has no pre-decrement -PUBLIC void REGPARAM2 FFPU fpuop_restore(uae_u32 opcode) -{ - uae_u32 ad; - uae_u32 d; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - - D(bug("frestore_opp at %08lx\r\n", m68k_getpc ())); - - if (get_fp_ad(opcode, &ad)) { - if (FPU is_integral) { - // 68040 - if (incr < 0) { - D(bug("PROBLEM: frestore_opp incr < 0\r\n")); - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) == 0) { // NULL - D(bug("frestore_opp found NULL frame at %X\r\n",ad-4)); - do_null_frestore(); - } else if ((d & 0x00ff0000) == 0) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); - ad -= 44; - } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); - ad -= 92; - } else { - D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d)); - } - } else { - d = get_long (ad); - D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); - ad += 4; - if ((d & 0xff000000) == 0) { // NULL - D(bug("frestore_opp found NULL frame at %X\r\n",ad-4)); - do_null_frestore(); - } else if ((d & 0x00ff0000) == 0) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); - ad += 44; - } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); - ad += 92; - } else { - D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d)); - } - } - } else { - // 68881 - if (incr < 0) { - D(bug("PROBLEM: frestore_opp incr < 0\r\n")); - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) == 0) { // NULL - do_null_frestore(); - } else if ((d & 0x00ff0000) == 0x00180000) { - ad -= 6 * 4; - } else if ((d & 0x00ff0000) == 0x00380000) { - ad -= 14 * 4; - } else if ((d & 0x00ff0000) == 0x00b40000) { - ad -= 45 * 4; - } - } else { - d = get_long (ad); - D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); - ad += 4; - if ((d & 0xff000000) == 0) { // NULL - D(bug("frestore_opp found NULL frame at %X\r\n",ad-4)); - do_null_frestore(); - } else if ((d & 0x00ff0000) == 0x00180000) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); - ad += 6 * 4; - } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? - ad += 14 * 4; - D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); - ad += 45 * 4; - } else { - D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d)); - } - } - } - - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; - D(bug("frestore_opp post-increment %X -> A%d\r\n",ad,opcode & 7)); - } - if ((opcode & 0x38) == 0x20) { - m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - D(bug("PROBLEM: frestore_opp pre-decrement\r\n")); - } - } -} - - -/* ---------------------------- Old-style interface ---------------------------- */ - -// #ifndef OPTIMIZED_8BIT_MEMORY_ACCESS -PUBLIC void REGPARAM2 FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) -{ - uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4); - (*fpufunctbl[mask])(opcode,extra); -} -// #endif - - -/* ---------------------------- Illegal ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("ILLEGAL F OP 2 %X\r\n",opcode)); - -#if I3_ON_ILLEGAL_FPU_OP -#error "FIXME: asm int 3" - _asm int 3 -#endif - - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); -} - - -/* ---------------------------- FPP -> ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVE -> \r\n")); - - if (put_fp_value (FPU registers[(extra >> 7) & 7], opcode, extra) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - - /* - Needed (among other things) by some Pack5/Elems68k transcendental - functions, they require the ACCR_INEX flag after a "MOVE.D, Dreg". - However, now put_fp_value() is responsible of clearing the exceptions - and merging statuses. - */ - - /* - WORD sw_temp; - _asm FNSTSW sw_temp - if(sw_temp & SW_PE) { - _asm FNCLEX - x86_status_word |= SW_PE; - x86_status_word_accrued |= SW_PE; - } - */ - - dump_registers( "END "); -} - - -/* ---------------------------- CONTROL REGS -> Dreg ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM control(none) -> D%d\r\n", opcode & 7)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); - m68k_dreg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpsr(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpcr(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpsr(); - D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); - m68k_dreg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpcr(); - D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); - m68k_dreg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpcr(); - D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpsr(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpcr(); - D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); - m68k_dreg (regs, opcode & 7) = get_fpsr(); - D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); - m68k_dreg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - - -/* ---------------------------- Dreg -> CONTROL REGS ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM D%d -> control(none)\r\n", opcode & 7)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - FPU instruction_address = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra ) -{ - set_fpsr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - set_fpsr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - FPU instruction_address = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - FPU instruction_address = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - set_fpsr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - set_fpsr( m68k_dreg (regs, opcode & 7) ); - D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - FPU instruction_address = m68k_dreg (regs, opcode & 7); - D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - - -/* ---------------------------- CONTROL REGS -> Areg ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM control(none) -> A%d\r\n", opcode & 7)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); - m68k_areg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpsr(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpcr(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpsr(); - D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); - m68k_areg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpcr(); - D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); - m68k_areg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpcr(); - D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpsr(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpcr(); - D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); - m68k_areg (regs, opcode & 7) = get_fpsr(); - D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); - m68k_areg (regs, opcode & 7) = FPU instruction_address; - dump_registers( "END "); -} - - -/* ---------------------------- Areg -> CONTROL REGS ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM A%d -> control(none)\r\n", opcode & 7)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - FPU instruction_address = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra ) -{ - set_fpsr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - set_fpsr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - FPU instruction_address = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - FPU instruction_address = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - set_fpsr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) -{ - set_fpcr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); - set_fpsr( m68k_areg (regs, opcode & 7) ); - D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); - FPU instruction_address = m68k_areg (regs, opcode & 7); - D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); - dump_registers( "END "); -} - - -/* ---------------------------- CONTROL REGS -> --MEMORY---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM Control regs (none) -> mem\r\n" )); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 4; - put_long (ad, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 4; - put_long (ad, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 8; - put_long (ad, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); - put_long (ad+4, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 4; - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 8; - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 8; - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 12; - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); - put_long (ad+8, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - - -/* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM Control regs (none) -> mem\r\n" )); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); - m68k_areg (regs, opcode & 7) = ad+4; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); - m68k_areg (regs, opcode & 7) = ad+4; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); - put_long (ad+4, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); - m68k_areg (regs, opcode & 7) = ad+8; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - m68k_areg (regs, opcode & 7) = ad+4; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); - m68k_areg (regs, opcode & 7) = ad+8; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - dump_registers( "END "); - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); - m68k_areg (regs, opcode & 7) = ad+8; - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); - put_long (ad+8, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); - m68k_areg (regs, opcode & 7) = ad+12; - dump_registers( "END "); - } -} - - -/* ---------------------------- CONTROL REGS -> MEMORY ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM Control regs (none) -> mem\r\n" )); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); - put_long (ad+4, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - put_long (ad, get_fpcr()); - D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); - put_long (ad+4, get_fpsr()); - D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); - put_long (ad+8, FPU instruction_address); - D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); - dump_registers( "END "); - } -} - - -/* ---------------------------- --MEMORY -> CONTROL REGS ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM --Mem -> control(none)\r\n")); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 4; - FPU instruction_address = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 4; - set_fpsr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 8; - set_fpsr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); - FPU instruction_address = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 4; - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 8; - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - FPU instruction_address = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 8; - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - set_fpsr( get_long (ad+4) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - ad -= 12; - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - set_fpsr( get_long (ad+4) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); - FPU instruction_address = get_long (ad+8); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - - -/* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM Mem++ -> control(none)\r\n")); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - FPU instruction_address = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad+4; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpsr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); - m68k_areg (regs, opcode & 7) = ad+4; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpsr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); - FPU instruction_address = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad+8; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - m68k_areg (regs, opcode & 7) = ad+4; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - FPU instruction_address = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad+8; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - set_fpsr( get_long (ad+4) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); - m68k_areg (regs, opcode & 7) = ad+8; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - set_fpsr( get_long (ad+4) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); - FPU instruction_address = get_long (ad+8); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); - m68k_areg (regs, opcode & 7) = ad+12; - dump_registers( "END "); - } -} - - -/* ---------------------------- MEMORY -> CONTROL REGS ---------------------------- */ -/* ---------------------------- and ---------------------------- */ -/* ---------------------------- IMMEDIATE -> CONTROL REGS ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVEM Mem -> control(none)\r\n")); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - FPU instruction_address = next_ilong(); - D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - FPU instruction_address = get_long (ad); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); - } - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - set_fpsr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpsr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); - } - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - set_fpsr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); - FPU instruction_address = next_ilong(); - D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpsr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); - FPU instruction_address = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); - } - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - set_fpcr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - } - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - set_fpcr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); - FPU instruction_address = next_ilong(); - D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - FPU instruction_address = get_long (ad+4); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); - } - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - set_fpcr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); - set_fpsr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - set_fpsr( get_long (ad+4) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); - } - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) -{ - if ((opcode & 0x3f) == 0x3c) { - set_fpcr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); - set_fpsr( next_ilong() ); - D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); - FPU instruction_address = next_ilong(); - D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); - } else { - uae_u32 ad; - if (get_fp_ad(opcode, &ad)) { - set_fpcr( get_long (ad) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); - set_fpsr( get_long (ad+4) ); - D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); - FPU instruction_address = get_long (ad+8); - D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); - } - } - dump_registers( "END "); -} - - -/* ---------------------------- FMOVEM MEMORY -> FPP ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM memory->FPP\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); - } - list <<= 1; - } - dump_registers( "END "); - } -} - - -/* ---------------------------- FPP -> FMOVEM MEMORY ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=7; reg>=0; reg-- ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = extra & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - m68k_areg (regs, opcode & 7) = ad; - dump_registers( "END "); - } -} -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra ) -{ - uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - D(bug("FMOVEM FPP->memory\r\n")); - if (get_fp_ad(opcode, &ad)) { - for( int reg=0; reg<8; reg++ ) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - dump_registers( "END "); - } -} - - -/* ---------------------------- FMOVEM CONSTANT ROM -> FPP ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: Pi\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_pi, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: Log 10 (2)\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_lg2, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: e\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_e, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: Log 2 (e)\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_l2e, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: Log 10 (e)\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_log_10_e, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: zero\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_z, sizeof(fpu_register) ); - x86_status_word = SW_Z; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: ln(2)\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_ln2, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: ln(10)\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_ln_10, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e0\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1, sizeof(fpu_register) ); - x86_status_word = SW_FINITE; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e1\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e1, sizeof(fpu_register) ); - x86_status_word = SW_FINITE; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e2\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e2, sizeof(fpu_register) ); - x86_status_word = SW_FINITE; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e4\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e4, sizeof(fpu_register) ); - x86_status_word = SW_FINITE; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e8\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e8, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; // Is it really FPSR_EXCEPTION_INEX2? - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e16\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e16, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e32\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e32, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e64\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e64, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e128\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e128, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e256\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e256, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e512\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e512, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e1024\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e1024, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e2048\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e2048, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra ) -{ - D(bug("FMOVECR memory->FPP FP const: 1.0e4096\r\n")); - memcpy( &FPU registers[(extra>>7) & 7], &const_1e4096, sizeof(fpu_register) ); - x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; - dump_registers( "END "); -} - - -/* ---------------------------- ALU ---------------------------- */ - -PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FMOVE %s\r\n",etos(src))); - do_fmove( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FINT %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); - do_fint( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSINH %s\r\n",etos(src))); - do_fsinh( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FINTRZ %s\r\n",etos(src))); - do_fintrz( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSQRT %s\r\n",etos(src))); - do_fsqrt( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FLOGNP1 %s\r\n",etos(src))); - do_flognp1( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FETOXM1 %s\r\n",etos(src))); - do_fetoxm1( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FTANH %s\r\n",etos(src))); - do_ftanh( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FATAN %s\r\n",etos(src))); - do_fatan( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FASIN %s\r\n",etos(src))); - do_fasin( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FATANH %s\r\n",etos(src))); - do_fatanh( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSIN %s\r\n",etos(src))); - do_fsin( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FTAN %s\r\n",etos(src))); - do_ftan( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FETOX %s\r\n",etos(src))); - do_fetox( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FTWOTOX %s\r\n",etos(src))); - do_ftwotox( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FTENTOX %s\r\n",etos(src))); - do_ftentox( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FLOGN %s\r\n",etos(src))); - do_flogn( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FLOG10 %s\r\n",etos(src))); - do_flog10( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FLOG2 %s\r\n",etos(src))); - do_flog2( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FABS %s\r\n",etos(src))); - do_fabs( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FCOSH %s\r\n",etos(src))); - do_fcosh( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FNEG %s\r\n",etos(src))); - do_fneg( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FACOS %s\r\n",etos(src))); - do_facos( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FCOS %s\r\n",etos(src))); - do_fcos( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FGETEXP %s\r\n",etos(src))); - - if( IS_INFINITY(src) ) { - MAKE_NAN( FPU registers[reg] ); - do_ftst( FPU registers[reg] ); - x86_status_word |= SW_IE; - } else { - do_fgetexp( FPU registers[reg], src ); - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FGETMAN %s\r\n",etos(src))); - if( IS_INFINITY(src) ) { - MAKE_NAN( FPU registers[reg] ); - do_ftst( FPU registers[reg] ); - x86_status_word |= SW_IE; - } else { - do_fgetman( FPU registers[reg], src ); - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDIV %s\r\n",etos(src))); - do_fdiv( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FMOD %s\r\n",etos(src))); - -#if USE_3_BIT_QUOTIENT - do_fmod( FPU registers[reg], src ); -#else - if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_ZERO ) { - do_fmod_dont_set_cw( FPU registers[reg], src ); - } else { - do_fmod( FPU registers[reg], src ); - } -#endif - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FREM %s\r\n",etos(src))); -#if USE_3_BIT_QUOTIENT - do_frem( FPU registers[reg], src ); -#else - if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_NEAR ) { - do_frem_dont_set_cw( FPU registers[reg], src ); - } else { - do_frem( FPU registers[reg], src ); - } -#endif - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FADD %s\r\n",etos(src))); - do_fadd( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FMUL %s\r\n",etos(src))); - do_fmul( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSGLDIV %s\r\n",etos(src))); - do_fsgldiv( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); - if( IS_INFINITY(FPU registers[reg]) ) { - MAKE_NAN( FPU registers[reg] ); - do_ftst( FPU registers[reg] ); - x86_status_word |= SW_IE; - } else { - // When the absolute value of the source operand is >= 2^14, - // an overflow or underflow always results. - do_fscale( FPU registers[reg], src ); - } - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSGLMUL %s\r\n",etos(src))); - do_fsglmul( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSUB %s\r\n",etos(src))); - do_fsub( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSINCOS %s\r\n",etos(src))); - do_fsincos( FPU registers[reg], FPU registers[extra & 7], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FCMP %s\r\n",etos(src))); - - if( IS_INFINITY(src) ) { - if( IS_NEGATIVE(src) ) { - if( IS_INFINITY(FPU registers[reg]) && IS_NEGATIVE(FPU registers[reg]) ) { - x86_status_word = SW_Z | SW_N; - D(bug("-INF FCMP -INF -> NZ\r\n")); - } else { - x86_status_word = SW_FINITE; - D(bug("X FCMP -INF -> None\r\n")); - } - } else { - if( IS_INFINITY(FPU registers[reg]) && !IS_NEGATIVE(FPU registers[reg]) ) { - x86_status_word = SW_Z; - D(bug("+INF FCMP +INF -> Z\r\n")); - } else { - x86_status_word = SW_N; - D(bug("X FCMP +INF -> N\r\n")); - } - } - } else if( IS_INFINITY(FPU registers[reg]) ) { - if( IS_NEGATIVE(FPU registers[reg]) ) { - x86_status_word = SW_N; - D(bug("-INF FCMP X -> Negative\r\n")); - } else { - x86_status_word = SW_FINITE; - D(bug("+INF FCMP X -> None\r\n")); - } - } else { - do_fcmp( FPU registers[reg], src ); - } - - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FTST %s\r\n",etos(src))); - do_ftst( src ); - build_ex_status(); - dump_registers( "END "); -} - - - -/* ---------------------------- SETUP TABLES ---------------------------- */ - -PRIVATE void FFPU build_fpp_opp_lookup_table () -{ - for( uae_u32 opcode=0; opcode<=0x38; opcode+=8 ) { - for( uae_u32 extra=0; extra<65536; extra++ ) { - uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4); - fpufunctbl[mask] = & FFPU fpuop_illg; - - switch ((extra >> 13) & 0x7) { - case 3: - fpufunctbl[mask] = & FFPU fpuop_fmove_2_ea; - break; - case 4: - case 5: - if ((opcode & 0x38) == 0) { - if (extra & 0x2000) { // dr bit - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Dreg; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Dreg; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Dreg; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Dreg; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg; - break; - } - } else { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_none; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpiar; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar; - break; - } - } - } else if ((opcode & 0x38) == 8) { - if (extra & 0x2000) { // dr bit - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Areg; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Areg; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Areg; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Areg; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Areg; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Areg; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Areg; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg; - break; - } - } else { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_none; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpiar; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr_fpiar; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpiar; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar; - break; - } - } - } else if (extra & 0x2000) { - if ((opcode & 0x38) == 0x20) { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_predecrement; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_predecrement; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_predecrement; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_predecrement; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement; - break; - } - } else if ((opcode & 0x38) == 0x18) { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_postincrement; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_postincrement; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_postincrement; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_postincrement; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement; - break; - } - } else { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem; - break; - } - } - } else { - if ((opcode & 0x38) == 0x20) { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_predecrement; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_predecrement; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_predecrement; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_predecrement; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement; - break; - } - } else if ((opcode & 0x38) == 0x18) { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_postincrement; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_postincrement; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_postincrement; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_postincrement; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement; - break; - } - } else { - switch( extra & 0x1C00 ) { - case 0x0000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_2_Mem; - break; - case 0x0400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem; - break; - case 0x0800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem; - break; - case 0x0C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem; - break; - case 0x1000: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem; - break; - case 0x1400: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem; - break; - case 0x1800: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem; - break; - case 0x1C00: - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem; - break; - } - } - break; - case 6: - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred; - break; - case 1: /* dynamic pred */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred; - break; - case 2: /* static postinc */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc; - break; - case 3: /* dynamic postinc */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc; - break; - } - break; - case 7: - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred; - break; - case 1: /* dynamic pred */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred; - break; - case 2: /* static postinc */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc; - break; - case 3: /* dynamic postinc */ - if ((opcode & 0x38) == 0x18) // post-increment? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement; - else if ((opcode & 0x38) == 0x20) // pre-decrement? - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement; - else - fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc; - break; - } - break; - case 0: - case 2: - if ((extra & 0xfc00) == 0x5c00) { - switch (extra & 0x7f) { - case 0x00: - fpufunctbl[mask] = & FFPU fpuop_do_fldpi; - break; - case 0x0b: - fpufunctbl[mask] = & FFPU fpuop_do_fldlg2; - break; - case 0x0c: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_e; - break; - case 0x0d: - fpufunctbl[mask] = & FFPU fpuop_do_fldl2e; - break; - case 0x0e: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_log_10_e; - break; - case 0x0f: - fpufunctbl[mask] = & FFPU fpuop_do_fldz; - break; - case 0x30: - fpufunctbl[mask] = & FFPU fpuop_do_fldln2; - break; - case 0x31: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_ln_10; - break; - case 0x32: - fpufunctbl[mask] = & FFPU fpuop_do_fld1; - break; - case 0x33: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1; - break; - case 0x34: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2; - break; - case 0x35: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4; - break; - case 0x36: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e8; - break; - case 0x37: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e16; - break; - case 0x38: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e32; - break; - case 0x39: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e64; - break; - case 0x3a: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e128; - break; - case 0x3b: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e256; - break; - case 0x3c: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e512; - break; - case 0x3d: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1024; - break; - case 0x3e: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2048; - break; - case 0x3f: - fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4096; - break; - } - break; - } - - switch (extra & 0x7f) { - case 0x00: - fpufunctbl[mask] = & FFPU fpuop_do_fmove; - break; - case 0x01: - fpufunctbl[mask] = & FFPU fpuop_do_fint; - break; - case 0x02: - fpufunctbl[mask] = & FFPU fpuop_do_fsinh; - break; - case 0x03: - fpufunctbl[mask] = & FFPU fpuop_do_fintrz; - break; - case 0x04: - fpufunctbl[mask] = & FFPU fpuop_do_fsqrt; - break; - case 0x06: - fpufunctbl[mask] = & FFPU fpuop_do_flognp1; - break; - case 0x08: - fpufunctbl[mask] = & FFPU fpuop_do_fetoxm1; - break; - case 0x09: - fpufunctbl[mask] = & FFPU fpuop_do_ftanh; - break; - case 0x0a: - fpufunctbl[mask] = & FFPU fpuop_do_fatan; - break; - case 0x0c: - fpufunctbl[mask] = & FFPU fpuop_do_fasin; - break; - case 0x0d: - fpufunctbl[mask] = & FFPU fpuop_do_fatanh; - break; - case 0x0e: - fpufunctbl[mask] = & FFPU fpuop_do_fsin; - break; - case 0x0f: - fpufunctbl[mask] = & FFPU fpuop_do_ftan; - break; - case 0x10: - fpufunctbl[mask] = & FFPU fpuop_do_fetox; - break; - case 0x11: - fpufunctbl[mask] = & FFPU fpuop_do_ftwotox; - break; - case 0x12: - fpufunctbl[mask] = & FFPU fpuop_do_ftentox; - break; - case 0x14: - fpufunctbl[mask] = & FFPU fpuop_do_flogn; - break; - case 0x15: - fpufunctbl[mask] = & FFPU fpuop_do_flog10; - break; - case 0x16: - fpufunctbl[mask] = & FFPU fpuop_do_flog2; - break; - case 0x18: - fpufunctbl[mask] = & FFPU fpuop_do_fabs; - break; - case 0x19: - fpufunctbl[mask] = & FFPU fpuop_do_fcosh; - break; - case 0x1a: - fpufunctbl[mask] = & FFPU fpuop_do_fneg; - break; - case 0x1c: - fpufunctbl[mask] = & FFPU fpuop_do_facos; - break; - case 0x1d: - fpufunctbl[mask] = & FFPU fpuop_do_fcos; - break; - case 0x1e: - fpufunctbl[mask] = & FFPU fpuop_do_fgetexp; - break; - case 0x1f: - fpufunctbl[mask] = & FFPU fpuop_do_fgetman; - break; - case 0x20: - fpufunctbl[mask] = & FFPU fpuop_do_fdiv; - break; - case 0x21: - fpufunctbl[mask] = & FFPU fpuop_do_fmod; - break; - case 0x22: - fpufunctbl[mask] = & FFPU fpuop_do_fadd; - break; - case 0x23: - fpufunctbl[mask] = & FFPU fpuop_do_fmul; - break; - case 0x24: - fpufunctbl[mask] = & FFPU fpuop_do_fsgldiv; - break; - case 0x25: - fpufunctbl[mask] = & FFPU fpuop_do_frem; - break; - case 0x26: - fpufunctbl[mask] = & FFPU fpuop_do_fscale; - break; - case 0x27: - fpufunctbl[mask] = & FFPU fpuop_do_fsglmul; - break; - case 0x28: - fpufunctbl[mask] = & FFPU fpuop_do_fsub; - break; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - fpufunctbl[mask] = & FFPU fpuop_do_fsincos; - break; - case 0x38: - fpufunctbl[mask] = & FFPU fpuop_do_fcmp; - break; - case 0x3a: - fpufunctbl[mask] = & FFPU fpuop_do_ftst; - break; - } - } - } - } - } -} - -/* ---------------------------- CONSTANTS ---------------------------- */ - -PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ) -{ - FPU_CONSISTENCY_CHECK_START(); - if(mult == 1) { -/* _asm { - MOV ESI, [f] - FLD QWORD PTR [value] - FSTP TBYTE PTR [ESI] - } */ - __asm__ __volatile__( - "fldl %1\n" - "fstpt %0\n" - : "=m" (f) - : "m" (value) - ); - } else { -/* _asm { - MOV ESI, [f] - FILD DWORD PTR [mult] - FLD QWORD PTR [value] - FMUL - FSTP TBYTE PTR [ESI] - } */ - __asm__ __volatile__( - "fildl %2\n" - "fldl %1\n" - "fmul \n" - "fstpt %0\n" - : "=m" (f) - : "m" (value), "m" (mult) - ); - } - D(bug("set_constant (%s,%.04f) = %s\r\n",name,(float)value,etos(f))); - FPU_CONSISTENCY_CHECK_STOP( mult==1 ? "set_constant(mult==1)" : "set_constant(mult>1)" ); -} - -PRIVATE void FFPU do_fldpi ( fpu_register & dest ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - FLDPI - FXAM - FNSTSW x86_status_word - MOV EDI, [dest] - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldpi \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fldpi"); -} - -PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - FLDLG2 - FXAM - FNSTSW x86_status_word - MOV EDI, [dest] - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldlg2 \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fldlg2"); -} - -PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - FLDL2E - FXAM - FNSTSW x86_status_word - MOV EDI, [dest] - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldl2e \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fldl2e"); -} - -PRIVATE void FFPU do_fldz ( fpu_register & dest ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - FLDZ - FXAM - FNSTSW x86_status_word - MOV EDI, [dest] - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldz \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fldz"); -} - -PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - FLDLN2 - FXAM - FNSTSW x86_status_word - MOV EDI, [dest] - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fldln2 \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fldln2"); -} - -PRIVATE void FFPU do_fld1 ( fpu_register & dest ) -{ - FPU_CONSISTENCY_CHECK_START(); -/* _asm { - FLD1 - FXAM - FNSTSW x86_status_word - MOV EDI, [dest] - FSTP TBYTE PTR [EDI] - } */ - __asm__ __volatile__( - "fld1 \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fld1"); -} - - -/* ---------------------------- MAIN INIT ---------------------------- */ - -#ifdef HAVE_SIGACTION -// Mega hackaround-that-happens-to-work: the following way to handle -// SIGFPE just happens to make the "fsave" below in fpu_init() *NOT* -// to abort with a floating point exception. However, we never -// actually reach sigfpe_handler(). -static void sigfpe_handler(int code, siginfo_t *sip, void *) -{ - if (code == SIGFPE && sip->si_code == FPE_FLTINV) { - fprintf(stderr, "Invalid floating point operation\n"); - abort(); - } -} -#endif - -PUBLIC void FFPU fpu_init( bool integral_68040 ) -{ - static bool done_first_time_initialization = false; - if (!done_first_time_initialization) { - fpu_init_native_fflags(); - fpu_init_native_exceptions(); - fpu_init_native_accrued_exceptions(); -#ifdef HAVE_SIGACTION - struct sigaction fpe_sa; - sigemptyset(&fpe_sa.sa_mask); - fpe_sa.sa_sigaction = sigfpe_handler; - fpe_sa.sa_flags = SA_SIGINFO; - sigaction(SIGFPE, &fpe_sa, 0); -#endif - done_first_time_initialization = true; - } - - __asm__ __volatile__("fsave %0" : "=m" (m_fpu_state_original)); - - FPU is_integral = integral_68040; - FPU instruction_address = 0; - set_fpcr(0); - set_fpsr(0); - - x86_control_word = CW_INITIAL; - x86_status_word = SW_INITIAL; - x86_status_word_accrued = 0; - FPU fpsr.quotient = 0; - - for( int i=0; i<8; i++ ) { - MAKE_NAN( FPU registers[i] ); - } - - build_fpp_opp_lookup_table(); - - __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); - - do_fldpi( const_pi ); - do_fldlg2( const_lg2 ); - do_fldl2e( const_l2e ); - do_fldz( const_z ); - do_fldln2( const_ln2 ); - do_fld1( const_1 ); - - set_constant( const_e, "e", exp (1.0), 1 ); - set_constant( const_log_10_e, "Log 10 (e)", log (exp (1.0)) / log (10.0), 1 ); - set_constant( const_ln_10, "ln(10)", log (10.0), 1 ); - set_constant( const_1e1, "1.0e1", 1.0e1, 1 ); - set_constant( const_1e2, "1.0e2", 1.0e2, 1 ); - set_constant( const_1e4, "1.0e4", 1.0e4, 1 ); - set_constant( const_1e8, "1.0e8", 1.0e8, 1 ); - set_constant( const_1e16, "1.0e16", 1.0e16, 1 ); - set_constant( const_1e32, "1.0e32", 1.0e32, 1 ); - set_constant( const_1e64, "1.0e64", 1.0e64, 1 ) ; - set_constant( const_1e128, "1.0e128", 1.0e128, 1 ); - set_constant( const_1e256, "1.0e256", 1.0e256, 1 ); - set_constant( const_1e512, "1.0e512", 1.0e256, 10 ); - set_constant( const_1e1024, "1.0e1024", 1.0e256, 100 ); - set_constant( const_1e2048, "1.0e2048", 1.0e256, 1000 ); - set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 ); - - // Just in case. - __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); -} - -PUBLIC void FFPU fpu_exit( void ) -{ - __asm__ __volatile__("frstor %0" : : "m" (m_fpu_state_original)); -} - -PUBLIC void FFPU fpu_reset( void ) -{ - fpu_exit(); - fpu_init(FPU is_integral); -} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h deleted file mode 100644 index 96f1d959..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_X86_H -#define FPU_X86_H - -/* NOTE: this file shall be included from fpu/fpu_x86.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -// Status word -PRIVATE uae_u32 x86_status_word; -PRIVATE uae_u32 x86_status_word_accrued; - -// FPU jump table -typedef void REGPARAM2 ( *fpuop_func )( uae_u32, uae_u32 ); -PRIVATE fpuop_func fpufunctbl[65536]; - -// FPU consistency -PRIVATE uae_u32 checked_sw_atstart; - -// FMOVECR constants supported byt x86 FPU -PRIVATE fpu_register const_pi; -PRIVATE fpu_register const_lg2; -PRIVATE fpu_register const_l2e; -PRIVATE fpu_register const_z; -PRIVATE fpu_register const_ln2; -PRIVATE fpu_register const_1; - -// FMOVECR constants not not suported by x86 FPU -PRIVATE fpu_register const_e; -PRIVATE fpu_register const_log_10_e; -PRIVATE fpu_register const_ln_10; -PRIVATE fpu_register const_1e1; -PRIVATE fpu_register const_1e2; -PRIVATE fpu_register const_1e4; -PRIVATE fpu_register const_1e8; -PRIVATE fpu_register const_1e16; -PRIVATE fpu_register const_1e32; -PRIVATE fpu_register const_1e64; -PRIVATE fpu_register const_1e128; -PRIVATE fpu_register const_1e256; -PRIVATE fpu_register const_1e512; -PRIVATE fpu_register const_1e1024; -PRIVATE fpu_register const_1e2048; -PRIVATE fpu_register const_1e4096; - -// Saved host FPU state -PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 - -/* -------------------------------------------------------------------------- */ -/* --- Methods --- */ -/* -------------------------------------------------------------------------- */ - -// Debug support functions -PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual); -PRIVATE char * FFPU etos(fpu_register const & e) REGPARAM; - -// FPU consistency -PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void); -PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name); - -// Get special floating-point value class -PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f); -PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f); -PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f); -PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f); - -// Make a special floating-point value -PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f); - -// Conversion from extended floating-point values -PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM; -PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) REGPARAM; -PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) REGPARAM; -PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) REGPARAM; -PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) REGPARAM; -PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM; -PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM; -PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM; - -// Conversion to extended floating-point values -PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) REGPARAM; -PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) REGPARAM; -PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) REGPARAM; -PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM; -PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM; -PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) REGPARAM; -PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM; - -// Atomic floating-point arithmetic operations -PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_ftst ( fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) REGPARAM; -PRIVATE void FFPU do_fldpi ( fpu_register & dest ) REGPARAM; -PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) REGPARAM; -PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) REGPARAM; -PRIVATE void FFPU do_fldz ( fpu_register & dest ) REGPARAM; -PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) REGPARAM; -PRIVATE void FFPU do_fld1 ( fpu_register & dest ) REGPARAM; - -// Instructions handlers -PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ); - -// Get & Put floating-point values -PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM; -PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM; -PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM; - -// Floating-point condition-based instruction handlers -PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM; - -// Misc functions -PRIVATE void __inline__ FFPU set_host_fpu_control_word (); -PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN (); -PRIVATE void __inline__ FFPU build_ex_status (); -PRIVATE void FFPU do_null_frestore (); -PRIVATE void FFPU build_fpp_opp_lookup_table (); -PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ); - -#endif /* FPU_X86_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h deleted file mode 100644 index ecdecfbc..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h +++ /dev/null @@ -1,72 +0,0 @@ -#define DEFINE_X86_MACRO(name, value) \ - asm(".local " #name "\n\t" #name " = " #value) - -DEFINE_X86_MACRO(BSUN, 0x00008000); -DEFINE_X86_MACRO(SNAN, 0x00004000); -DEFINE_X86_MACRO(OPERR, 0x00002000); -DEFINE_X86_MACRO(OVFL, 0x00001000); -DEFINE_X86_MACRO(UNFL, 0x00000800); -DEFINE_X86_MACRO(DZ, 0x00000400); -DEFINE_X86_MACRO(INEX2, 0x00000200); -DEFINE_X86_MACRO(INEX1, 0x00000100); -DEFINE_X86_MACRO(ACCR_IOP, 0x80); -DEFINE_X86_MACRO(ACCR_OVFL, 0x40); -DEFINE_X86_MACRO(ACCR_UNFL, 0x20); -DEFINE_X86_MACRO(ACCR_DZ, 0x10); -DEFINE_X86_MACRO(ACCR_INEX, 0x08); -DEFINE_X86_MACRO(ROUND_CONTROL_MASK, 0x30); -DEFINE_X86_MACRO(ROUND_TO_NEAREST, 0); -DEFINE_X86_MACRO(ROUND_TO_ZERO, 0x10); -DEFINE_X86_MACRO(ROUND_TO_NEGATIVE_INFINITY, 0x20); -DEFINE_X86_MACRO(ROUND_TO_POSITIVE_INFINITY, 0x30); -DEFINE_X86_MACRO(PRECISION_CONTROL_MASK, 0xC0); -DEFINE_X86_MACRO(PRECISION_CONTROL_EXTENDED, 0); -DEFINE_X86_MACRO(PRECISION_CONTROL_DOUBLE, 0x80); -DEFINE_X86_MACRO(PRECISION_CONTROL_SINGLE, 0x40); -DEFINE_X86_MACRO(PRECISION_CONTROL_UNDEFINED, 0xC0); -DEFINE_X86_MACRO(CW_RESET, 0x0040); -DEFINE_X86_MACRO(CW_FINIT, 0x037F); -DEFINE_X86_MACRO(SW_RESET, 0x0000); -DEFINE_X86_MACRO(SW_FINIT, 0x0000); -DEFINE_X86_MACRO(TW_RESET, 0x5555); -DEFINE_X86_MACRO(TW_FINIT, 0x0FFF); -DEFINE_X86_MACRO(CW_X, 0x1000); -DEFINE_X86_MACRO(CW_RC_ZERO, 0x0C00); -DEFINE_X86_MACRO(CW_RC_UP, 0x0800); -DEFINE_X86_MACRO(CW_RC_DOWN, 0x0400); -DEFINE_X86_MACRO(CW_RC_NEAR, 0x0000); -DEFINE_X86_MACRO(CW_PC_EXTENDED, 0x0300); -DEFINE_X86_MACRO(CW_PC_DOUBLE, 0x0200); -DEFINE_X86_MACRO(CW_PC_RESERVED, 0x0100); -DEFINE_X86_MACRO(CW_PC_SINGLE, 0x0000); -DEFINE_X86_MACRO(CW_PM, 0x0020); -DEFINE_X86_MACRO(CW_UM, 0x0010); -DEFINE_X86_MACRO(CW_OM, 0x0008); -DEFINE_X86_MACRO(CW_ZM, 0x0004); -DEFINE_X86_MACRO(CW_DM, 0x0002); -DEFINE_X86_MACRO(CW_IM, 0x0001); -DEFINE_X86_MACRO(SW_B, 0x8000); -DEFINE_X86_MACRO(SW_C3, 0x4000); -DEFINE_X86_MACRO(SW_TOP_7, 0x3800); -DEFINE_X86_MACRO(SW_TOP_6, 0x3000); -DEFINE_X86_MACRO(SW_TOP_5, 0x2800); -DEFINE_X86_MACRO(SW_TOP_4, 0x2000); -DEFINE_X86_MACRO(SW_TOP_3, 0x1800); -DEFINE_X86_MACRO(SW_TOP_2, 0x1000); -DEFINE_X86_MACRO(SW_TOP_1, 0x0800); -DEFINE_X86_MACRO(SW_TOP_0, 0x0000); -DEFINE_X86_MACRO(SW_C2, 0x0400); -DEFINE_X86_MACRO(SW_C1, 0x0200); -DEFINE_X86_MACRO(SW_C0, 0x0100); -DEFINE_X86_MACRO(SW_ES, 0x0080); -DEFINE_X86_MACRO(SW_SF, 0x0040); -DEFINE_X86_MACRO(SW_PE, 0x0020); -DEFINE_X86_MACRO(SW_UE, 0x0010); -DEFINE_X86_MACRO(SW_OE, 0x0008); -DEFINE_X86_MACRO(SW_ZE, 0x0004); -DEFINE_X86_MACRO(SW_DE, 0x0002); -DEFINE_X86_MACRO(SW_IE, 0x0001); -DEFINE_X86_MACRO(X86_ROUNDING_MODE, 0x0C00); -DEFINE_X86_MACRO(X86_ROUNDING_PRECISION, 0x0300); - -#undef DEFINE_X86_MACRO diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h index 2363af56..755c43d9 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.h +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -49,12 +49,6 @@ // Use ISO C99 extended-precision math functions (glibc 2.1+) #define FPU_USE_ISO_C99 1 -// NOTE: this is irrelevant on Win32 platforms since the MS libraries -// don't support extended-precision floating-point computations -#if defined(WIN32) && USE_LONG_DOUBLE -#undef FPU_USE_ISO_C99 -#endif - // Use faster implementation of math functions, but this could cause // some incorrect results (?) #ifdef _MSC_VER diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 1653adab..3030258f 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -2188,15 +2188,13 @@ static void gen_opcode (unsigned long int opcode) case i_CINVP: case i_CINVA: /* gb-- srcreg now contains the cache field */ - printf ("\tif (srcreg&0x2)\n"); - printf ("\t\tflush_icache(%d);\n", 30 + ((opcode >> 3) & 3)); + break; case i_CPUSHL: case i_CPUSHP: case i_CPUSHA: /* gb-- srcreg now contains the cache field */ - printf ("\tif (srcreg&0x2)\n"); - printf ("\t\tflush_icache(%d);\n", 40 + ((opcode >> 3) & 3)); + break; case i_MOVE16: if ((opcode & 0xfff8) == 0xf620) { @@ -2262,7 +2260,6 @@ static void generate_includes (FILE * f) fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); - fprintf (f, "#include \"compiler/compemu.h\"\n"); fprintf (f, "#include \"fpu/fpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); @@ -2541,18 +2538,5 @@ int main (int argc, char **argv) fclose (stblfile); fflush (out); - /* For build systems (IDEs mainly) that don't make it easy to compile the - * same file twice with different settings. */ - stblfile = fopen ("cpustbl_nf.cpp", "w"); - out = freopen ("cpuemu_nf.cpp", "w", stdout); - - fprintf (stblfile, "#define NOFLAGS\n"); - fprintf (stblfile, "#include \"cpustbl.cpp\"\n"); - fclose (stblfile); - - printf ("#define NOFLAGS\n"); - printf ("#include \"cpuemu.cpp\"\n"); - fflush (out); - return 0; } diff --git a/BasiliskII/src/uae_cpu/memory.cpp b/BasiliskII/src/uae_cpu/memory.cpp deleted file mode 100644 index 676a2436..00000000 --- a/BasiliskII/src/uae_cpu/memory.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * Memory management - * - * (c) 1995 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "sysdeps.h" - -#include "cpu_emulation.h" -#include "main.h" -#include "video.h" - -#include "m68k.h" -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" - -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING - -static bool illegal_mem = false; - -#ifdef SAVE_MEMORY_BANKS -addrbank *mem_banks[65536]; -#else -addrbank mem_banks[65536]; -#endif - -#ifdef WORDS_BIGENDIAN -# define swap_words(X) (X) -#else -# define swap_words(X) (((X) >> 16) | ((X) << 16)) -#endif - -#ifdef NO_INLINE_MEMORY_ACCESS -uae_u32 longget (uaecptr addr) -{ - return call_mem_get_func (get_mem_bank (addr).lget, addr); -} -uae_u32 wordget (uaecptr addr) -{ - return call_mem_get_func (get_mem_bank (addr).wget, addr); -} -uae_u32 byteget (uaecptr addr) -{ - return call_mem_get_func (get_mem_bank (addr).bget, addr); -} -void longput (uaecptr addr, uae_u32 l) -{ - call_mem_put_func (get_mem_bank (addr).lput, addr, l); -} -void wordput (uaecptr addr, uae_u32 w) -{ - call_mem_put_func (get_mem_bank (addr).wput, addr, w); -} -void byteput (uaecptr addr, uae_u32 b) -{ - call_mem_put_func (get_mem_bank (addr).bput, addr, b); -} -#endif - -/* A dummy bank that only contains zeros */ - -static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM; -static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM; -static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM; -static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM; - -uae_u32 REGPARAM2 dummy_lget (uaecptr addr) -{ - if (illegal_mem) - write_log ("Illegal lget at %08lx\n", addr); - - return 0; -} - -uae_u32 REGPARAM2 dummy_wget (uaecptr addr) -{ - if (illegal_mem) - write_log ("Illegal wget at %08lx\n", addr); - - return 0; -} - -uae_u32 REGPARAM2 dummy_bget (uaecptr addr) -{ - if (illegal_mem) - write_log ("Illegal bget at %08lx\n", addr); - - return 0; -} - -void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l) -{ - if (illegal_mem) - write_log ("Illegal lput at %08lx\n", addr); -} -void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w) -{ - if (illegal_mem) - write_log ("Illegal wput at %08lx\n", addr); -} -void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal bput at %08lx\n", addr); -} - -/* Mac RAM (32 bit addressing) */ - -static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM; -static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM; -static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM; - -static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac - -uae_u32 REGPARAM2 ram_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + addr); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 ram_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + addr); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 ram_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr); -} - -void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + addr); - do_put_mem_long(m, l); -} - -void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + addr); - do_put_mem_word(m, w); -} - -void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b) -{ - *(uae_u8 *)(RAMBaseDiff + addr) = b; -} - -uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) -{ - return (uae_u8 *)(RAMBaseDiff + addr); -} - -/* Mac RAM (24 bit addressing) */ - -static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM; -static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM; -static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM; - -uae_u32 REGPARAM2 ram24_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 ram24_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 ram24_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)); -} - -void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); - do_put_mem_long(m, l); -} - -void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); - do_put_mem_word(m, w); -} - -void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b) -{ - *(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b; -} - -uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) -{ - return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)); -} - -/* Mac ROM (32 bit addressing) */ - -static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM; -static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM; -static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM; - -static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac - -uae_u32 REGPARAM2 rom_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(ROMBaseDiff + addr); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 rom_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(ROMBaseDiff + addr); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 rom_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr); -} - -void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal ROM lput at %08lx\n", addr); -} - -void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal ROM wput at %08lx\n", addr); -} - -void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal ROM bput at %08lx\n", addr); -} - -uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) -{ - return (uae_u8 *)(ROMBaseDiff + addr); -} - -/* Mac ROM (24 bit addressing) */ - -static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM; -static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM; - -uae_u32 REGPARAM2 rom24_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff)); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 rom24_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff)); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 rom24_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff)); -} - -uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) -{ - return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff)); -} - -/* Frame buffer */ - -static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM; -static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM; - -static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM; -static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM; - -static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM; -static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM; - -static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM; -static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM; - -static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM; - -static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac - -uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr); -} - -void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - do_put_mem_long(m, l); -} - -void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - do_put_mem_word(m, w); -} - -void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b) -{ - *(uae_u8 *)(FrameBaseDiff + addr) = b; -} - -uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr) -{ - uae_u32 *m, l; - m = (uae_u32 *)(FrameBaseDiff + addr); - l = *m; - return swap_words(l); -} - -uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - return *m; -} - -void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - *m = swap_words(l); -} - -void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - *m = w; -} - -uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr) -{ - uae_u32 *m, l; - m = (uae_u32 *)(FrameBaseDiff + addr); - l = *m; - l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0); - return swap_words(l); -} - -uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr) -{ - uae_u16 *m, w; - m = (uae_u16 *)(FrameBaseDiff + addr); - w = *m; - return (w & 0x1f) | ((w >> 1) & 0x7fe0); -} - -void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0); - *m = swap_words(l); -} - -void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - *m = (w & 0x1f) | ((w << 1) & 0xffc0); -} - -uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr) -{ - uae_u32 *m, l; - m = (uae_u32 *)(FrameBaseDiff + addr); - return *m; -} - -void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac); - *m = l; -} - -uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) -{ - return (uae_u8 *)(FrameBaseDiff + addr); -} - -/* Default memory access functions */ - -uae_u8 *REGPARAM2 default_xlate (uaecptr a) -{ - write_log("Your Mac program just did something terribly stupid\n"); - return NULL; -} - -/* Address banks */ - -addrbank dummy_bank = { - dummy_lget, dummy_wget, dummy_bget, - dummy_lput, dummy_wput, dummy_bput, - default_xlate -}; - -addrbank ram_bank = { - ram_lget, ram_wget, ram_bget, - ram_lput, ram_wput, ram_bput, - ram_xlate -}; - -addrbank ram24_bank = { - ram24_lget, ram24_wget, ram24_bget, - ram24_lput, ram24_wput, ram24_bput, - ram24_xlate -}; - -addrbank rom_bank = { - rom_lget, rom_wget, rom_bget, - rom_lput, rom_wput, rom_bput, - rom_xlate -}; - -addrbank rom24_bank = { - rom24_lget, rom24_wget, rom24_bget, - rom_lput, rom_wput, rom_bput, - rom24_xlate -}; - -addrbank frame_direct_bank = { - frame_direct_lget, frame_direct_wget, frame_direct_bget, - frame_direct_lput, frame_direct_wput, frame_direct_bput, - frame_xlate -}; - -addrbank frame_host_555_bank = { - frame_host_555_lget, frame_host_555_wget, frame_direct_bget, - frame_host_555_lput, frame_host_555_wput, frame_direct_bput, - frame_xlate -}; - -addrbank frame_host_565_bank = { - frame_host_565_lget, frame_host_565_wget, frame_direct_bget, - frame_host_565_lput, frame_host_565_wput, frame_direct_bput, - frame_xlate -}; - -addrbank frame_host_888_bank = { - frame_host_888_lget, frame_direct_wget, frame_direct_bget, - frame_host_888_lput, frame_direct_wput, frame_direct_bput, - frame_xlate -}; - -void memory_init(void) -{ - for(long i=0; i<65536; i++) - put_mem_bank(i<<16, &dummy_bank); - - // Limit RAM size to not overlap ROM - uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize; - - RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac; - ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac; - FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac; - - // Map RAM and ROM - if (TwentyFourBitAddressing) { - map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16); - map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16); - } else { - map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16); - map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16); - } - - // Map frame buffer - switch (MacFrameLayout) { - case FLAYOUT_DIRECT: - map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - case FLAYOUT_HOST_555: - map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - case FLAYOUT_HOST_565: - map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - case FLAYOUT_HOST_888: - map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - } -} - -void map_banks(addrbank *bank, int start, int size) -{ - int bnr; - unsigned long int hioffs = 0, endhioffs = 0x100; - - if (start >= 0x100) { - for (bnr = start; bnr < start + size; bnr++) - put_mem_bank (bnr << 16, bank); - return; - } - if (TwentyFourBitAddressing) endhioffs = 0x10000; - for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) - for (bnr = start; bnr < start+size; bnr++) - put_mem_bank((bnr + hioffs) << 16, bank); -} - -#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */ - diff --git a/BasiliskII/src/uae_cpu/memory.h b/BasiliskII/src/uae_cpu/memory.h index 75a6303b..670c2ee7 100644 --- a/BasiliskII/src/uae_cpu/memory.h +++ b/BasiliskII/src/uae_cpu/memory.h @@ -23,107 +23,11 @@ #ifndef UAE_MEMORY_H #define UAE_MEMORY_H -#if !DIRECT_ADDRESSING && !REAL_ADDRESSING - -/* Enabling this adds one additional native memory reference per 68k memory - * access, but saves one shift (on the x86). Enabling this is probably - * better for the cache. My favourite benchmark (PP2) doesn't show a - * difference, so I leave this enabled. */ - -#if 1 || defined SAVE_MEMORY -#define SAVE_MEMORY_BANKS -#endif - -typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM; -typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM; -typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM; - -#undef DIRECT_MEMFUNCS_SUCCESSFUL - -#ifndef CAN_MAP_MEMORY -#undef USE_COMPILER -#endif - -#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY) -#define USE_MAPPED_MEMORY -#endif - -typedef struct { - /* These ones should be self-explanatory... */ - mem_get_func lget, wget, bget; - mem_put_func lput, wput, bput; - /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can - * be used to address memory without calling the wget/wput functions. - * This doesn't work for all memory banks, so this function may call - * abort(). */ - xlate_func xlateaddr; -} addrbank; - -extern uae_u8 filesysory[65536]; - -extern addrbank ram_bank; // Mac RAM -extern addrbank rom_bank; // Mac ROM -extern addrbank frame_bank; // Frame buffer - -/* Default memory access functions */ - -extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM; - -#define bankindex(addr) (((uaecptr)(addr)) >> 16) - -#ifdef SAVE_MEMORY_BANKS -extern addrbank *mem_banks[65536]; -#define get_mem_bank(addr) (*mem_banks[bankindex(addr)]) -#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b)) -#else -extern addrbank mem_banks[65536]; -#define get_mem_bank(addr) (mem_banks[bankindex(addr)]) -#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b)) -#endif - -extern void memory_init(void); -extern void map_banks(addrbank *bank, int first, int count); - -#ifndef NO_INLINE_MEMORY_ACCESS - -#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr)) -#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr)) -#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr)) -#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l)) -#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w)) -#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b)) - -#else - -extern uae_u32 longget(uaecptr addr); -extern uae_u32 wordget(uaecptr addr); -extern uae_u32 byteget(uaecptr addr); -extern void longput(uaecptr addr, uae_u32 l); -extern void wordput(uaecptr addr, uae_u32 w); -extern void byteput(uaecptr addr, uae_u32 b); - -#endif - -#ifndef MD_HAVE_MEM_1_FUNCS - -#define longget_1 longget -#define wordget_1 wordget -#define byteget_1 byteget -#define longput_1 longput -#define wordput_1 wordput -#define byteput_1 byteput - -#endif - -#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */ - -#if REAL_ADDRESSING -const uintptr MEMBaseDiff = 0; -#elif DIRECT_ADDRESSING +#if DIRECT_ADDRESSING extern uintptr MEMBaseDiff; #endif -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING static __inline__ uae_u8 *do_get_real_address(uaecptr addr) { return (uae_u8 *)MEMBaseDiff + addr; @@ -170,38 +74,7 @@ static __inline__ uae_u32 get_virtual_address(uae_u8 *addr) { return do_get_virtual_address(addr); } -#else -static __inline__ uae_u32 get_long(uaecptr addr) -{ - return longget_1(addr); -} -static __inline__ uae_u32 get_word(uaecptr addr) -{ - return wordget_1(addr); -} -static __inline__ uae_u32 get_byte(uaecptr addr) -{ - return byteget_1(addr); -} -static __inline__ void put_long(uaecptr addr, uae_u32 l) -{ - longput_1(addr, l); -} -static __inline__ void put_word(uaecptr addr, uae_u32 w) -{ - wordput_1(addr, w); -} -static __inline__ void put_byte(uaecptr addr, uae_u32 b) -{ - byteput_1(addr, b); -} -static __inline__ uae_u8 *get_real_address(uaecptr addr) -{ - return get_mem_bank(addr).xlateaddr(addr); -} -/* gb-- deliberately not implemented since it shall not be used... */ -extern uae_u32 get_virtual_address(uae_u8 *addr); -#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */ +#endif /* DIRECT_ADDRESSING */ #endif /* MEMORY_H */ diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index 4e45817b..a88ebf5e 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -36,17 +36,12 @@ extern int intlev(void); // From baisilisk_glue.cpp #include "memory.h" #include "readcpu.h" #include "newcpu.h" -#include "compiler/compemu.h" #include "fpu/fpu.h" #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) B2_mutex *spcflags_lock = NULL; #endif -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif bool quit_program = false; struct flag_struct regflags; @@ -122,20 +117,12 @@ static void dump_log(void) #else fprintf(f, " | "); #endif -#if ENABLE_MON - disass_68k(f, pc); -#endif + } fclose(f); } #endif -#if ENABLE_MON -static void dump_regs(void) -{ - m68k_dumpstate(NULL); -} -#endif #define COUNT_INSTRS 0 @@ -308,7 +295,7 @@ static int backup_pointer = 0; static long int m68kpc_offset; int lastint_no; -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING #define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1) #define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o)) #define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o)) @@ -860,16 +847,7 @@ int m68k_move2c (int regno, uae_u32 *regp) case 1: regs.dfc = *regp & 7; break; case 2: cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); -#if USE_JIT - if (CPUType < 4) { - set_cache_state(cacr&1); - if (*regp & 0x08) - flush_icache(1); - } - else { - set_cache_state(cacr&0x8000); - } -#endif + break; case 3: tc = *regp & 0xc000; break; case 4: itt0 = *regp & 0xffffe364; break; @@ -1209,17 +1187,6 @@ void m68k_reset (void) memset(log, 0, sizeof(log)); #endif -#if ENABLE_MON - static bool first_time = true; - if (first_time) { - first_time = false; - mon_add_command("regs", dump_regs, "regs Dump m68k emulator registers\n"); -#if FLIGHT_RECORDER - // Install "log" command in mon - mon_add_command("log", dump_log, "log Dump m68k emulation log\n"); -#endif - } -#endif } void m68k_emulop_return(void) @@ -1263,9 +1230,6 @@ void REGPARAM2 op_illg (uae_u32 opcode) } write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); -#if USE_JIT && JIT_DEBUG - compiler_dumpstate(); -#endif Exception (4,0); return; @@ -1323,18 +1287,7 @@ static void do_trace (void) int m68k_do_specialties (void) { -#if USE_JIT - // Block was compiled - SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE ); - // Retain the request to get out of compiled code until - // we reached the toplevel execution, i.e. the one that - // can compile then run compiled code. This also means - // we processed all (nested) EmulOps - if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN )) - SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN ); -#endif - if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { Exception (9,last_trace_ad); } @@ -1389,17 +1342,13 @@ void m68k_do_execute (void) void m68k_execute (void) { -#if USE_JIT - ++m68k_execute_depth; -#endif + for (;;) { if (quit_program) break; m68k_do_execute(); } -#if USE_JIT - --m68k_execute_depth; -#endif + } static void m68k_verify (uaecptr addr, uaecptr *nextpc) diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index 1d07c36b..a15d79d8 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -63,16 +63,6 @@ struct cputbl { extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl"); -#if USE_JIT -typedef void compop_func (uae_u32) REGPARAM; - -struct comptbl { - compop_func *handler; - uae_u32 specific; - uae_u32 opcode; -}; -#endif - extern void REGPARAM2 op_illg (uae_u32) REGPARAM; typedef char flagtype; @@ -200,7 +190,7 @@ static __inline__ uae_u32 next_ilong (void) static __inline__ void m68k_setpc (uaecptr newpc) { -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING regs.pc_p = get_real_address(newpc); #else regs.pc_p = regs.pc_oldp = get_real_address(newpc); @@ -210,7 +200,7 @@ static __inline__ void m68k_setpc (uaecptr newpc) static __inline__ uaecptr m68k_getpc (void) { -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING return get_virtual_address(regs.pc_p); #else return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); @@ -300,9 +290,7 @@ extern void m68k_record_step(uaecptr) REGPARAM; #endif extern void m68k_do_execute(void); extern void m68k_execute(void); -#if USE_JIT -extern void m68k_compile_execute(void); -#endif + #ifdef USE_CPU_EMUL_SERVICES extern int32 emulated_ticks; extern void cpu_do_check_ticks(void); diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h index 3c3fc032..494f4fcc 100644 --- a/BasiliskII/src/uae_cpu/spcflags.h +++ b/BasiliskII/src/uae_cpu/spcflags.h @@ -32,14 +32,10 @@ enum { SPCFLAG_TRACE = 0x08, SPCFLAG_DOTRACE = 0x10, SPCFLAG_DOINT = 0x20, -#if USE_JIT - SPCFLAG_JIT_END_COMPILE = 0x40, - SPCFLAG_JIT_EXEC_RETURN = 0x80, -#else + SPCFLAG_JIT_END_COMPILE = 0, SPCFLAG_JIT_EXEC_RETURN = 0, -#endif - + SPCFLAG_ALL = SPCFLAG_STOP | SPCFLAG_INT | SPCFLAG_BRK diff --git a/BasiliskII/src/user_strings.cpp b/BasiliskII/src/user_strings.cpp index f4861825..81614a24 100644 --- a/BasiliskII/src/user_strings.cpp +++ b/BasiliskII/src/user_strings.cpp @@ -33,11 +33,7 @@ #include "sysdeps.h" #include "user_strings.h" -#ifdef __BEOS__ -#define ELLIPSIS "\xE2\x80\xA6" -#else #define ELLIPSIS "..." -#endif // Common string definitions From 76d285a6f2e0080082c09d4c670c6d85401d71e4 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 15 Apr 2018 15:59:59 -0500 Subject: [PATCH 02/20] Convert buildsystem to CMake --- BasiliskII/src/CrossPlatform/sigsegv.cpp | 7 +- BasiliskII/src/CrossPlatform/vm_alloc.cpp | 7 +- BasiliskII/src/Unix/CMakeLists.txt | 94 + BasiliskII/src/Unix/Makefile.in | 145 -- BasiliskII/src/Unix/acinclude.m4 | 28 - BasiliskII/src/Unix/autogen.sh | 61 - BasiliskII/src/Unix/config.guess | 1409 ----------- BasiliskII/src/Unix/config.sub | 1469 ------------ BasiliskII/src/Unix/configure.ac | 953 -------- BasiliskII/src/Unix/cpr.sh | 59 - BasiliskII/src/Unix/install-sh | 251 -- BasiliskII/src/Unix/m4/egrep.m4 | 13 - BasiliskII/src/Unix/m4/esd.m4 | 194 -- BasiliskII/src/Unix/m4/gettext.m4 | 2576 --------------------- BasiliskII/src/Unix/m4/gtk-2.0.m4 | 196 -- BasiliskII/src/Unix/m4/gtk.m4 | 194 -- BasiliskII/src/Unix/mkinstalldirs | 99 - BasiliskII/src/Unix/sysdeps.h | 540 ++++- BasiliskII/src/Unix/tunconfig | 102 - BasiliskII/src/uae_cpu/fpu/types.h | 24 - 20 files changed, 550 insertions(+), 7871 deletions(-) create mode 100644 BasiliskII/src/Unix/CMakeLists.txt delete mode 100644 BasiliskII/src/Unix/Makefile.in delete mode 100644 BasiliskII/src/Unix/acinclude.m4 delete mode 100755 BasiliskII/src/Unix/autogen.sh delete mode 100755 BasiliskII/src/Unix/config.guess delete mode 100755 BasiliskII/src/Unix/config.sub delete mode 100644 BasiliskII/src/Unix/configure.ac delete mode 100755 BasiliskII/src/Unix/cpr.sh delete mode 100755 BasiliskII/src/Unix/install-sh delete mode 100644 BasiliskII/src/Unix/m4/egrep.m4 delete mode 100644 BasiliskII/src/Unix/m4/esd.m4 delete mode 100644 BasiliskII/src/Unix/m4/gettext.m4 delete mode 100644 BasiliskII/src/Unix/m4/gtk-2.0.m4 delete mode 100644 BasiliskII/src/Unix/m4/gtk.m4 delete mode 100755 BasiliskII/src/Unix/mkinstalldirs delete mode 100755 BasiliskII/src/Unix/tunconfig diff --git a/BasiliskII/src/CrossPlatform/sigsegv.cpp b/BasiliskII/src/CrossPlatform/sigsegv.cpp index 41a5d04e..13c498b7 100644 --- a/BasiliskII/src/CrossPlatform/sigsegv.cpp +++ b/BasiliskII/src/CrossPlatform/sigsegv.cpp @@ -27,14 +27,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define NEED_CONFIG_H_ONLY +#include "sysdeps.h" + #ifdef HAVE_UNISTD_H #include #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include #include diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.cpp b/BasiliskII/src/CrossPlatform/vm_alloc.cpp index 0dde455c..d529337f 100644 --- a/BasiliskII/src/CrossPlatform/vm_alloc.cpp +++ b/BasiliskII/src/CrossPlatform/vm_alloc.cpp @@ -19,13 +19,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#define NEED_CONFIG_H_ONLY +#include "sysdeps.h" -#ifdef HAVE_FCNTL_H #include -#endif #include #include diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt new file mode 100644 index 00000000..0d3f9b9d --- /dev/null +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -0,0 +1,94 @@ +cmake_minimum_required(VERSION 3.0.0) +project(BasiliskII) + + +find_package(SDL REQUIRED) +find_library(COREFOUNDATION_LIBRARY CoreFoundation) +find_library(IOKIT_LIBRARY IOKit) +include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL_INCLUDE_DIR}) + +add_executable(build68k ../uae_cpu/build68k.c) + +add_custom_command(OUTPUT cpudefs.cpp + COMMAND build68k < ${CMAKE_CURRENT_SOURCE_DIR}/../uae_cpu/table68k > cpudefs.cpp + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../uae_cpu/table68k build68k) + +add_executable(gencpu ../uae_cpu/gencpu.c ../uae_cpu/readcpu.cpp cpudefs.cpp) + +add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp COMMAND gencpu DEPENDS gencpu) + +set(BasiliskII_SRCS + ../main.cpp + ../prefs.cpp + ../prefs_items.cpp + sys_unix.cpp + ../rom_patches.cpp + ../slot_rom.cpp + ../rsrc_patches.cpp + ../emul_op.cpp + ../macos_util.cpp + ../xpram.cpp + xpram_unix.cpp + ../timer.cpp + timer_unix.cpp + ../adb.cpp + ../serial.cpp + ../ether.cpp + ../sony.cpp + ../disk.cpp + ../cdrom.cpp + ../scsi.cpp + ../video.cpp + ../audio.cpp + ../extfs.cpp + ../user_strings.cpp + user_strings_unix.cpp + rpc_unix.cpp + # XPLAT_SRCS + ../CrossPlatform/vm_alloc.cpp + ../CrossPlatform/sigsegv.cpp + ../CrossPlatform/video_blit.cpp + #SYSSRC + #SDL USE_SDL USE_SDL_VIDEO USE_SDL_AUDIO + #video src + ../SDL/video_sdl.cpp + #EXTFSSRC + extfs_unix.cpp + #Serial src + ../dummy/serial_dummy.cpp + #ether src + ../dummy/ether_dummy.cpp + #scsi src + ../dummy/scsi_dummy.cpp + #audio src + ../SDL/audio_sdl.cpp + #sem src: posix_sem.cpp + #ui src + ../dummy/prefs_editor_dummy.cpp + #extra sys + Darwin/sys_darwin.cpp + main_unix.cpp + prefs_unix.cpp + ../dummy/clip_dummy.cpp + + #CPU srcs + #add define -DFPU_UAE + ../uae_cpu/basilisk_glue.cpp + ../uae_cpu/newcpu.cpp + ../uae_cpu/readcpu.cpp + ../uae_cpu/fpu/fpu_uae.cpp + cpustbl.cpp + cpudefs.cpp + cpuemu.cpp + #addressing mode =direct -DDIRECT_ADDRESSING + #includes +) + +add_executable(BasiliskII ${BasiliskII_SRCS}) + +set_source_files_properties(${BasiliskII_SRCS} + PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"") + +target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY}) + +#keycodes -> ../SDL/keycodes diff --git a/BasiliskII/src/Unix/Makefile.in b/BasiliskII/src/Unix/Makefile.in deleted file mode 100644 index 389e8eed..00000000 --- a/BasiliskII/src/Unix/Makefile.in +++ /dev/null @@ -1,145 +0,0 @@ -# Unix makefile for Basilisk II - -## System specific configuration -@SET_MAKE@ -SHELL = /bin/sh - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -datadir = @datadir@ -mandir = @mandir@ -man1dir = $(mandir)/man1 - -KEYCODES = @KEYCODES@ - -DESTDIR = - -CC = @CC@ -CXX = @CXX@ -CFLAGS = @CFLAGS@ -CXXFLAGS = @CXXFLAGS@ -CPUINCLUDES_FLAGS=@CPUINCLUDES@ -CPUINCLUDES_FLAGS:=$(CPUINCLUDES_FLAGS:-I%=-I@top_srcdir@/%) -CPPFLAGS = @CPPFLAGS@ -I@top_srcdir@/../include -I@top_srcdir@/. -I. -I@top_srcdir@/../CrossPlatform $(CPUINCLUDES_FLAGS) -DEFS = @DEFS@ @DEFINES@ -D_REENTRANT -DDATADIR=\"$(datadir)/$(APP)\" -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -SYSSRCS = @SYSSRCS@ -CPUSRCS = @CPUSRCS@ -BLESS = @BLESS@ -EXEEXT = @EXEEXT@ -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ - -XPLAT_SRCS = ../CrossPlatform/vm_alloc.cpp ../CrossPlatform/sigsegv.cpp ../CrossPlatform/video_blit.cpp - -## Files -SRCS = ../main.cpp ../prefs.cpp ../prefs_items.cpp \ - sys_unix.cpp ../rom_patches.cpp ../slot_rom.cpp ../rsrc_patches.cpp \ - ../emul_op.cpp ../macos_util.cpp ../xpram.cpp xpram_unix.cpp ../timer.cpp \ - timer_unix.cpp ../adb.cpp ../serial.cpp ../ether.cpp \ - ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp \ - ../audio.cpp ../extfs.cpp \ - ../user_strings.cpp user_strings_unix.cpp rpc_unix.cpp \ - $(XPLAT_SRCS) $(SYSSRCS) $(CPUSRCS) -APP_FLAVOR ?= -ifneq ($(APP_FLAVOR),) - CURR_APP_FLAVOR := -$(APP_FLAVOR) -else - CURR_APP_FLAVOR := -endif -APP_BASENAME = BasiliskII -APP = $(APP_BASENAME)$(CURR_APP_FLAVOR) - -PROGS = $(APP)$(EXEEXT) - -## Rules -.PHONY: install installdirs uninstall mostlyclean clean distclean depend dep -.SUFFIXES: -.SUFFIXES: .c .cpp .s .o .h - -all: $(PROGS) - -OBJ_DIR = obj -$(OBJ_DIR):: - @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 - -define SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ - $(basename $(notdir $(file)))))) -endef -OBJS := $(SRCS_LIST_TO_OBJS) -SRCS := $(SRCS:%=@top_srcdir@/%) - -SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) -VPATH := -VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) - -## Documentation files - -$(APP)$(EXEEXT): $(OBJ_DIR) $(OBJS) - $(CXX) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) - $(BLESS) $(APP)$(EXEEXT) - -install: $(PROGS) installdirs - $(INSTALL_PROGRAM) $(APP)$(EXEEXT) $(DESTDIR)$(bindir)/$(APP)$(EXEEXT) - -$(INSTALL_DATA) @top_srcdir@/$(APP_BASENAME).1 $(DESTDIR)$(man1dir)/$(APP).1 - $(INSTALL_DATA) @top_srcdir@/$(KEYCODES) $(DESTDIR)$(datadir)/$(APP)/keycodes - $(INSTALL_DATA) @top_srcdir@/fbdevices $(DESTDIR)$(datadir)/$(APP)/fbdevices - $(INSTALL_DATA) @top_srcdir@/tunconfig $(DESTDIR)$(datadir)/$(APP)/tunconfig - -installdirs: - $(SHELL) @top_srcdir@/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) $(DESTDIR)$(datadir)/$(APP) - -uninstall: - rm -f $(DESTDIR)$(bindir)/$(APP)$(EXEEXT) - rm -f $(DESTDIR)$(man1dir)/$(APP).1 - rm -f $(DESTDIR)$(datadir)/$(APP)/keycodes - rm -f $(DESTDIR)$(datadir)/$(APP)/fbdevices - rm -f $(DESTDIR)$(datadir)/$(APP)/tunconfig - rmdir $(DESTDIR)$(datadir)/$(APP) - -mostlyclean: - rm -f $(PROGS) $(OBJ_DIR)/* core* *.core *~ *.bak - -clean: mostlyclean - rm -f cpuemu.cpp cpudefs.cpp cputmp*.s cpufast*.s cpustbl.cpp cputbl.h - -distclean: clean - rm -rf $(OBJ_DIR) - rm -rf autom4te.cache - rm -f Makefile - rm -f config.cache config.log config.status config.h - rm -f Darwin/lowmem Darwin/pagezero - -depend dep: - makedepend $(CPPFLAGS) -Y. $(SRCS) 2>/dev/null - -$(OBJ_DIR)/%.o : %.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.m - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.mm - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.s - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ - -$(OBJ_DIR)/build68k$(EXEEXT): $(OBJ_DIR)/build68k.o - $(CC) $(LDFLAGS) -o $(OBJ_DIR)/build68k$(EXEEXT) $(OBJ_DIR)/build68k.o -$(OBJ_DIR)/gencpu$(EXEEXT): $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o - $(CXX) $(LDFLAGS) -o $(OBJ_DIR)/gencpu$(EXEEXT) $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o - -cpudefs.cpp: $(OBJ_DIR)/build68k$(EXEEXT) @top_srcdir@/../uae_cpu/table68k - $(OBJ_DIR)/build68k$(EXEEXT) <@top_srcdir@/../uae_cpu/table68k >cpudefs.cpp -cpustbl.cpp: cpuemu.cpp -cputbl.h: cpuemu.cpp - -cpuemu.cpp: $(OBJ_DIR)/gencpu$(EXEEXT) - $(OBJ_DIR)/gencpu$(EXEEXT) - -#------------------------------------------------------------------------- -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/BasiliskII/src/Unix/acinclude.m4 b/BasiliskII/src/Unix/acinclude.m4 deleted file mode 100644 index cd5479ec..00000000 --- a/BasiliskII/src/Unix/acinclude.m4 +++ /dev/null @@ -1,28 +0,0 @@ -dnl Additional macros for Basilisk II - - -dnl Check for libgnomeui -dnl B2_PATH_GNOMEUI([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Test to see if libgnomeui is installed, and define GNOMEUI_CFLAGS, LIBS -AC_DEFUN([B2_PATH_GNOMEUI], -[dnl -dnl Get the cflags and libraries from the gnome-config script -dnl -AC_ARG_WITH(gnome-config, -[ --with-gnome-config=GNOME_CONFIG Location of gnome-config], -GNOME_CONFIG="$withval") - -AC_PATH_PROG(GNOME_CONFIG, gnome-config, no) -AC_MSG_CHECKING(for libgnomeui) -if test "$GNOME_CONFIG" = "no"; then - AC_MSG_RESULT(no) - ifelse([$2], , :, [$2]) -else - AC_MSG_RESULT(yes) - GNOMEUI_CFLAGS=`$GNOME_CONFIG --cflags gnomeui` - GNOMEUI_LIBS=`$GNOME_CONFIG --libs gnomeui` - ifelse([$1], , :, [$1]) -fi -AC_SUBST(GNOMEUI_CFLAGS) -AC_SUBST(GNOMEUI_LIBS) -]) diff --git a/BasiliskII/src/Unix/autogen.sh b/BasiliskII/src/Unix/autogen.sh deleted file mode 100755 index e77a310b..00000000 --- a/BasiliskII/src/Unix/autogen.sh +++ /dev/null @@ -1,61 +0,0 @@ -#! /bin/sh -# Run this to generate all the initial makefiles, etc. -# This was lifted from the Gimp, and adapted slightly by -# Christian Bauer. - -DIE=0 - -PROG="Basilisk II" - -# Check how echo works in this /bin/sh -case `echo -n` in --n) _echo_n= _echo_c='\c';; -*) _echo_n=-n _echo_c=;; -esac - -(autoconf --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "You must have autoconf installed to compile $PROG." - echo "Download the appropriate package for your distribution," - echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" - DIE=1 -} - -(aclocal --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "**Error**: Missing aclocal. The version of automake" - echo "installed doesn't appear recent enough." - echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz" - echo "(or a newer version if it is available)" - DIE=1 -} - -if test "$DIE" -eq 1; then - exit 1 -fi - -if test -z "$ACLOCAL_FLAGS"; then - ACLOCAL_FLAGS="-I `aclocal --print-ac-dir` -I `dirname $0`/m4" -fi - -aclocalinclude="$ACLOCAL_FLAGS"; \ -(echo $_echo_n " + Running aclocal: $_echo_c"; \ - aclocal $aclocalinclude; \ - echo "done.") && \ -(echo $_echo_n " + Running autoheader: $_echo_c"; \ - autoheader; \ - echo "done.") && \ -(echo $_echo_n " + Running autoconf: $_echo_c"; \ - autoconf; \ - echo "done.") - -rm -f config.cache - -if [ x"$NO_CONFIGURE" = "x" ]; then - echo " + Running 'configure $@':" - if [ -z "$*" ]; then - echo " ** If you wish to pass arguments to ./configure, please" - echo " ** specify them on the command line." - fi - ./configure "$@" -fi diff --git a/BasiliskII/src/Unix/config.guess b/BasiliskII/src/Unix/config.guess deleted file mode 100755 index 78f6b92c..00000000 --- a/BasiliskII/src/Unix/config.guess +++ /dev/null @@ -1,1409 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -timestamp='2003-01-10' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - macppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvmeppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mipseb-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sun3:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:MicroBSD:*:*) - echo ${UNAME_MACHINE}-unknown-microbsd${UNAME_RELEASE} - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - eval $set_cc_for_build - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null - if test "$?" = 0 ; then - case `$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - 3-1307) - UNAME_MACHINE="alphaev7" - ;; - esac - fi - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit 0;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - DRS?6000:UNIX_SV:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7 && exit 0 ;; - esac ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c \ - && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && exit 0 - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit 0 ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - # avoid double evaluation of $set_cc_for_build - test -n "$CC_FOR_BUILD" || eval $set_cc_for_build - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - *:UNICOS/mp:*:*) - echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - # Determine whether the default compiler uses glibc. - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #if __GLIBC__ >= 2 - LIBC=gnu - #else - LIBC= - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - x86:Interix*:3*) - echo i586-pc-interix3 - exit 0 ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #ifdef __INTEL_COMPILER - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit 0 ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i*86:*:5:[78]*) - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit 0 ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - case `uname -p` in - *86) UNAME_PROCESSOR=i686 ;; - powerpc) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/BasiliskII/src/Unix/config.sub b/BasiliskII/src/Unix/config.sub deleted file mode 100755 index d6d67c3f..00000000 --- a/BasiliskII/src/Unix/config.sub +++ /dev/null @@ -1,1469 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - -timestamp='2003-01-03' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | msp430 \ - | ns16k | ns32k \ - | openrisc | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | s390 | s390x \ - | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xscale | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* \ - | m32r-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | s390-* | s390x-* \ - | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - or32 | or32-*) - basic_machine=or32-unknown - os=-coff - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2) - basic_machine=i686-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic4x | c4x*) - basic_machine=tic4x-unknown - os=-coff - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) - basic_machine=sh-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -microbsd*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/BasiliskII/src/Unix/configure.ac b/BasiliskII/src/Unix/configure.ac deleted file mode 100644 index ffba2f41..00000000 --- a/BasiliskII/src/Unix/configure.ac +++ /dev/null @@ -1,953 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -dnl Written in 2002 by Christian Bauer et al. - -AC_INIT([Basilisk II], 1.0, [Christian.Bauer@uni-mainz.de], BasiliskII) -AC_CONFIG_SRCDIR(main_unix.cpp) -AC_PREREQ(2.52) -AC_CONFIG_HEADER(config.h) - -AC_USE_SYSTEM_EXTENSIONS - -dnl Aliases for PACKAGE and VERSION macros. -AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE_NAME", [Define this program name.]) -AC_DEFINE_UNQUOTED(VERSION, "$PACKAGE_VERSION", [Define this program version.]) - -dnl Some systems do not put corefiles in the currect directory, avoid saving -dnl cores for the configure tests since some are intended to dump core. -ulimit -c 0 - -dnl Video options. -AC_ARG_ENABLE(vosf, [ --enable-vosf enable video on SEGV signals [default=yes]], [WANT_VOSF=$enableval], [WANT_VOSF=yes]) - -dnl SDL options. -AC_ARG_ENABLE(sdl-static, [ --enable-sdl-static use SDL static libraries for linking [default=no]], [WANT_SDL_STATIC=$enableval], [WANT_SDL_STATIC=no]) -AC_ARG_ENABLE(sdl-video, [ --enable-sdl-video use SDL for video graphics [default=no]], [WANT_SDL_VIDEO=$enableval], [WANT_SDL_VIDEO=no]) -AC_ARG_ENABLE(sdl-audio, [ --enable-sdl-audio use SDL for audio [default=no]], [WANT_SDL_AUDIO=$enableval], [WANT_SDL_AUDIO=no]) - -dnl FPU emulation core. -AC_ARG_ENABLE(fpe, -[ --enable-fpe=FPE specify which fpu emulator to use [default=auto]], -[ case "$enableval" in - dnl default is always ieee, if architecture has this fp format - uae) FPE_CORE_TEST_ORDER="uae";; - *) AC_MSG_ERROR([--enable-fpe takes only one of the following values: auto, x86, ieee, uae]);; - esac -], -[ FPE_CORE_TEST_ORDER="ieee uae" -]) - -dnl Addressing modes. -AC_ARG_ENABLE(addressing, -[ --enable-addressing=AM specify the addressing mode to use [default=fastest]], -[ case "$enableval" in - real) ADDRESSING_TEST_ORDER="real";; - direct) ADDRESSING_TEST_ORDER="direct";; - banks) ADDRESSING_TEST_ORDER="banks";; - fastest)ADDRESSING_TEST_ORDER="direct banks";; - *) AC_MSG_ERROR([--enable-addressing takes only one of the following values: fastest, real, direct, banks]);; - esac -], -[ ADDRESSING_TEST_ORDER="direct banks" -]) - -dnl Canonical system information. -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -dnl Target OS type (target is host if not cross-compiling). -case "$target_os" in - darwin*) OS_TYPE=darwin;; - *) OS_TYPE=`echo $target_os | sed -e 's/-/_/g' | sed -e 's/\./_/g'`;; -esac -DEFINES="$DEFINES -DOS_$OS_TYPE" - -dnl Target CPU type. -HAVE_I386=no -HAVE_X86_64=no -case "$target_cpu" in - i386* | i486* | i586* | i686* | i786* ) HAVE_I386=yes;; - x86_64* | amd64* ) HAVE_X86_64=yes;; -esac - -dnl Check if we should really be assuming x86_64 even if we detected HAVE_I386 above. -if [[ "x$HAVE_I386" = "xyes" ]]; then - AC_TRY_RUN([ - int main(void) { - #if defined(__x86_64__) - return 0; - #else - return 1; - #endif - } - ], [ - HAVE_I386=no - HAVE_X86_64=yes - ]) -fi - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CC_C_O -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_MAKE_SET -AC_PROG_INSTALL -AC_PROG_EGREP - -dnl Checks for libraries. -AC_CHECK_LIB(posix4, sem_init) -AC_CHECK_LIB(rt, timer_create) -AC_CHECK_LIB(rt, shm_open) -AC_CHECK_LIB(m, cos) - - -dnl Do we need SDL? -WANT_SDL=no -if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then - WANT_SDL=yes - SDL_SUPPORT="$SDL_SUPPORT video" -fi -if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then - WANT_SDL=yes - SDL_SUPPORT="$SDL_SUPPORT audio" -fi -if [[ "x$WANT_SDL" = "xyes" ]]; then - - AC_PATH_PROG(sdl_config, "sdl-config") - if [[ -n "$sdl_config" ]]; then - case $target_os in - *) - sdl_cflags=`$sdl_config --cflags` - if [[ "x$WANT_SDL_STATIC" = "xyes" ]]; then - sdl_libs=`$sdl_config --static-libs` - else - sdl_libs=`$sdl_config --libs` - fi - ;; - esac - CFLAGS="$CFLAGS $sdl_cflags" - CXXFLAGS="$CXXFLAGS $sdl_cflags" - LIBS="$LIBS $sdl_libs" - else - WANT_SDL=no - fi - - SDL_SUPPORT=`echo "$SDL_SUPPORT" | sed -e "s/^ //"` -else - SDL_SUPPORT="none" -fi - -dnl We want pthreads. Try libpthread first, then PTL. -HAVE_PTHREADS=yes -AC_CHECK_LIB(pthread, pthread_create, , [ - AC_CHECK_LIB(PTL, pthread_create, , [ - HAVE_PTHREADS=no - ]) -]) -if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then - AC_DEFINE(HAVE_PTHREADS, 1, [Define if pthreads are available.]) -fi -AC_CHECK_FUNCS(pthread_cond_init) -AC_CHECK_FUNCS(pthread_cancel pthread_testcancel) -AC_CHECK_FUNCS(pthread_mutexattr_setprotocol) -AC_CHECK_FUNCS(pthread_mutexattr_settype) -AC_CHECK_FUNCS(pthread_mutexattr_setpshared) - -dnl If POSIX.4 semaphores are not available, we emulate them with pthread mutexes. -SEMSRC= -AC_CHECK_FUNCS(sem_init, , [ - if test "x$HAVE_PTHREADS" = "xyes"; then - SEMSRC=posix_sem.cpp - fi -]) - -UISRCS=../dummy/prefs_editor_dummy.cpp - -dnl We use 64-bit file size support if possible. -AC_SYS_LARGEFILE - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(stdlib.h stdint.h) -AC_CHECK_HEADERS(unistd.h fcntl.h sys/types.h sys/time.h sys/mman.h mach/mach.h) -AC_CHECK_HEADERS(readline.h history.h readline/readline.h readline/history.h) -AC_CHECK_HEADERS(sys/socket.h sys/ioctl.h sys/filio.h sys/bitypes.h sys/wait.h) -AC_CHECK_HEADERS(sys/poll.h sys/select.h) -AC_CHECK_HEADERS(arpa/inet.h) -AC_CHECK_HEADERS(AvailabilityMacros.h) -AC_CHECK_HEADERS(IOKit/storage/IOBlockStorageDevice.h) -AC_CHECK_HEADERS(sys/stropts.h stropts.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_BIGENDIAN -AC_C_CONST -AC_C_INLINE -AC_CHECK_SIZEOF(short, 2) -AC_CHECK_SIZEOF(int, 4) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_SIZEOF(long long, 8) -AC_CHECK_SIZEOF(float, 4) -AC_CHECK_SIZEOF(double, 8) -AC_CHECK_SIZEOF(long double, 12) -AC_CHECK_SIZEOF(void *, 4) -AC_TYPE_OFF_T -AC_CHECK_TYPES(loff_t) -AC_CHECK_TYPES(caddr_t) -AC_TYPE_SIZE_T -AC_TYPE_SIGNAL -AC_HEADER_TIME -AC_STRUCT_TM - -dnl Check whether sys/socket.h defines type socklen_t. -dnl (extracted from ac-archive/Miscellaneous) -AC_CACHE_CHECK([for socklen_t], - ac_cv_type_socklen_t, [ - AC_TRY_COMPILE([ - #include - #include - ], [socklen_t len = 42; return 0;], - ac_cv_type_socklen_t=yes, ac_cv_type_socklen_t=no, - dnl When cross-compiling, do not assume anything. - ac_cv_type_socklen_t="guessing no" - ) -]) -if [[ "x$ac_cv_type_socklen_t" != "xyes" ]]; then - AC_DEFINE(socklen_t, int, [Define to 'int' if doesn't define.]) -fi - -dnl Checks for library functions. -AC_CHECK_FUNCS(strdup strerror cfmakeraw) -AC_CHECK_FUNCS(clock_gettime timer_create) -AC_CHECK_FUNCS(sigaction signal) -AC_CHECK_FUNCS(mmap mprotect munmap) -AC_CHECK_FUNCS(vm_allocate vm_deallocate vm_protect) -AC_CHECK_FUNCS(poll inet_aton) - -dnl Darwin seems to define mach_task_self() instead of task_self(). -AC_CHECK_FUNCS(mach_task_self task_self) - -dnl Check for systems where POSIX-style non-blocking I/O (O_NONBLOCK) -dnl doesn't work or is unimplemented. On these systems (mostly older -dnl ones), use the old BSD-style FIONBIO approach instead. [tcl.m4] -AC_CACHE_CHECK([FIONBIO vs. O_NONBLOCK for non-blocking I/O], - ac_cv_nonblocking_io, [ - case "$host" in - *-*-osf*) - ac_cv_nonblocking_io=FIONBIO - ;; - *-*-sunos4*) - ac_cv_nonblocking_io=FIONBIO - ;; - *-*-ultrix*) - ac_cv_nonblocking_io=FIONBIO - ;; - *) - ac_cv_nonblocking_io=O_NONBLOCK - ;; - esac -]) -if [[ "$ac_cv_nonblocking_io" = "FIONBIO" ]]; then - AC_DEFINE(USE_FIONBIO, 1, [Define if BSD-style non-blocking I/O is to be used]) -fi - -dnl Check whether compiler supports byte bit-fields -AC_CACHE_CHECK([whether compiler supports byte bit-fields], - ac_cv_have_byte_bitfields, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - struct A { - unsigned char b1:4; - unsigned char b2:4; - unsigned char c; - unsigned short s; - unsigned char a[4]; - }; - - int main(void) { - A a; - return ! (sizeof(A) == 8 && &a.c == ((unsigned char *)&a + 1)); - }], - [ac_cv_have_byte_bitfields=yes], - [ac_cv_have_byte_bitfields=no], - dnl When cross-compiling, assume only GCC supports this - [if [[ "$GCC" = "yes" ]]; then - ac_cv_have_byte_bitfields="guessing yes" - else - ac_cv_have_byte_bitfields="guessing no" - fi] - ) - AC_LANG_RESTORE -]) - -dnl AC_CHECK_FRAMEWORK($1=NAME, $2=INCLUDES) -AC_DEFUN([AC_CHECK_FRAMEWORK], [ - AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1])dnl - AC_CACHE_CHECK([whether compiler supports framework $1], - ac_Framework, [ - saved_LIBS="$LIBS" - LIBS="$LIBS -framework $1" - AC_TRY_LINK( - [$2], [], - [AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no); LIBS="$saved_LIBS"] - ) - ]) - AS_IF([test AS_VAR_GET(ac_Framework) = yes], - [AC_DEFINE(AS_TR_CPP(HAVE_FRAMEWORK_$1), 1, [Define if framework $1 is available.])] - ) - AS_VAR_POPDEF([ac_Framework])dnl -]) - -dnl Check for some MacOS X frameworks -AC_CHECK_FRAMEWORK(AppKit, []) -AC_CHECK_FRAMEWORK(Carbon, [#include ]) -AC_CHECK_FRAMEWORK(IOKit, [#include ]) -AC_CHECK_FRAMEWORK(CoreFoundation, [#include ]) - -dnl Select system-dependant source files. -SERIALSRC=../dummy/serial_dummy.cpp -ETHERSRC=../dummy/ether_dummy.cpp -SCSISRC=../dummy/scsi_dummy.cpp -AUDIOSRC=../dummy/audio_dummy.cpp -EXTFSSRC=extfs_unix.cpp -EXTRASYSSRCS= -case "$target_os" in -darwin*) - if [[ "x$ac_cv_framework_IOKit" = "xyes" -a "x$ac_cv_framework_CoreFoundation" = "xyes" ]]; then - EXTRASYSSRCS="Darwin/sys_darwin.cpp" - fi - ;; -esac - -EXTRASYSSRCS="$EXTRASYSSRCS main_unix.cpp prefs_unix.cpp" - -dnl SDL overrides -if [[ "x$WANT_SDL" = "xyes" ]]; then - AC_DEFINE(USE_SDL, 1, [Define to enble SDL support]) -fi -if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then - AC_DEFINE(USE_SDL_VIDEO, 1, [Define to enable SDL video graphics support]) - VIDEOSRCS="../SDL/video_sdl.cpp" - KEYCODES="../SDL/keycodes" - case "$target_os" in - *) - EXTRASYSSRCS="$EXTRASYSSRCS ../dummy/clip_dummy.cpp" - ;; - esac -fi -if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then - AC_DEFINE(USE_SDL_AUDIO, 1, [Define to enable SDL audio support]) - AUDIOSRC="../SDL/audio_sdl.cpp" -fi - -if [[ "x$HAVE_PTHREADS" = "xno" ]]; then - dnl Serial, ethernet and audio support needs pthreads - AC_MSG_WARN([You don't have pthreads, disabling serial, ethernet and audio support.]) - SERIALSRC=../dummy/serial_dummy.cpp - ETHERSRC=../dummy/ether_dummy.cpp - AUDIOSRC=../dummy/audio_dummy.cpp -fi -SYSSRCS="$VIDEOSRCS $EXTFSSRC $SERIALSRC $ETHERSRC $SCSISRC $AUDIOSRC $SEMSRC $UISRCS $EXTRASYSSRCS" - -dnl Define a macro that translates a yesno-variable into a C macro definition -dnl to be put into the config.h file -dnl $1 -- the macro to define -dnl $2 -- the value to translate -dnl $3 -- template name -AC_DEFUN([AC_TRANSLATE_DEFINE], [ - if [[ "x$2" = "xyes" -o "x$2" = "xguessing yes" ]]; then - AC_DEFINE($1, 1, $3) - fi -]) - -dnl Check that the host supports TUN/TAP devices -AC_CACHE_CHECK([whether TUN/TAP is supported], - ac_cv_tun_tap_support, [ - AC_TRY_COMPILE([ - #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_IF_TUN_H) - #include - #include - #endif - ], [ - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - ], - ac_cv_tun_tap_support=yes, ac_cv_tun_tap_support=no - ) -]) -AC_TRANSLATE_DEFINE(ENABLE_TUNTAP, "$ac_cv_tun_tap_support", - [Define if your system supports TUN/TAP devices.]) - -dnl Various checks if the system supports vm_allocate() and the like functions. -have_mach_vm=no -if [[ "x$ac_cv_func_vm_allocate" = "xyes" -a "x$ac_cv_func_vm_deallocate" = "xyes" -a \ - "x$ac_cv_func_vm_protect" = "xyes" ]]; then - have_mach_vm=yes -fi -AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm", - [Define if your system has a working vm_allocate()-based memory allocator.]) - -dnl Check that vm_allocate(), vm_protect() work -if [[ "x$have_mach_vm" = "xyes" ]]; then - -AC_CACHE_CHECK([whether vm_protect works], - ac_cv_vm_protect_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_cv_vm_protect_works=yes - dnl First the tests that should segfault - for test_def in NONE_READ NONE_WRITE READ_WRITE; do - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_$test_def - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_vm_protect_works=no, rm -f core, - dnl When cross-compiling, do not assume anything - ac_cv_vm_protect_works="guessing no" - ) - done - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_RDWR_WRITE - #include "../CrossPlatform/vm_alloc.cpp" - ], , ac_cv_vm_protect_works=no, - dnl When cross-compiling, do not assume anything - ac_cv_vm_protect_works="guessing no" - ) - AC_LANG_RESTORE - ] -) - -dnl Remove support for vm_allocate() if vm_protect() does not work -if [[ "x$have_mach_vm" = "xyes" ]]; then - case $ac_cv_vm_protect_works in - *yes) have_mach_vm=yes;; - *no) have_mach_vm=no;; - esac -fi -AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm", - [Define if your system has a working vm_allocate()-based memory allocator.]) - -fi dnl HAVE_MACH_VM - -dnl Various checks if the system supports mmap() and the like functions. -dnl ... and Mach memory allocators are not supported -have_mmap_vm=no -if [[ "x$ac_cv_func_mmap" = "xyes" -a "x$ac_cv_func_munmap" = "xyes" -a \ - "x$ac_cv_func_mprotect" = "xyes" ]]; then - if [[ "x$have_mach_vm" = "xno" ]]; then - have_mmap_vm=yes - fi -fi -AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, "$have_mmap_vm", - [Define if your system has a working mmap()-based memory allocator.]) - -dnl Check that mmap() and associated functions work. -if [[ "x$have_mmap_vm" = "xyes" ]]; then - -dnl Check if we have a working anonymous mmap() -AC_CACHE_CHECK([whether mmap supports MAP_ANON], - ac_cv_mmap_anon, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_MMAP_ANON - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_MMAP_ANON - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_mmap_anon=yes, ac_cv_mmap_anon=no, - dnl When cross-compiling, do not assume anything. - ac_cv_mmap_anon="guessing no" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_MMAP_ANON, "$ac_cv_mmap_anon", - [Define if defines MAP_ANON and mmap()'ing with MAP_ANON works.]) - -AC_CACHE_CHECK([whether mmap supports MAP_ANONYMOUS], - ac_cv_mmap_anonymous, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_MMAP_ANONYMOUS - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_MMAP_ANON - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_mmap_anonymous=yes, ac_cv_mmap_anonymous=no, - dnl When cross-compiling, do not assume anything. - ac_cv_mmap_anonymous="guessing no" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_MMAP_ANONYMOUS, "$ac_cv_mmap_anonymous", - [Define if defines MAP_ANONYMOUS and mmap()'ing with MAP_ANONYMOUS works.]) - -AC_CACHE_CHECK([whether mprotect works], - ac_cv_mprotect_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_cv_mprotect_works=yes - dnl First the tests that should segfault - for test_def in NONE_READ NONE_WRITE READ_WRITE; do - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_$test_def - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_mprotect_works=no, rm -f core, - dnl When cross-compiling, do not assume anything - ac_cv_mprotect_works="guessing no" - ) - done - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_RDWR_WRITE - #include "../CrossPlatform/vm_alloc.cpp" - ], , ac_cv_mprotect_works=no, - dnl When cross-compiling, do not assume anything - ac_cv_mprotect_works="guessing no" - ) - AC_LANG_RESTORE - ] -) - -dnl Remove support for mmap() if mprotect() does not work -if [[ "x$have_mmap_vm" = "xyes" ]]; then - case $ac_cv_mprotect_works in - *yes) have_mmap_vm=yes;; - *no) have_mmap_vm=no;; - esac -fi -AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, $have_mmap_vm, - [Define if your system has a working mmap()-based memory allocator.]) - -fi dnl HAVE_MMAP_VM - -dnl Check if we can modify the __PAGEZERO segment for use as Low Memory -AC_CACHE_CHECK([whether __PAGEZERO can be Low Memory area 0x0000-0x2000], - ac_cv_pagezero_hack, [ - ac_cv_pagezero_hack=no - if AC_TRY_COMMAND([Darwin/testlmem.sh 0x2000]); then - ac_cv_pagezero_hack=yes - dnl might as well skip the test for mmap-able low memory - ac_cv_can_map_lm=no - fi -]) -AC_TRANSLATE_DEFINE(PAGEZERO_HACK, "$ac_cv_pagezero_hack", - [Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this system.]) - -dnl Check if we can mmap 0x2000 bytes from 0x0000 -AC_CACHE_CHECK([whether we can map Low Memory area 0x0000-0x2000], - ac_cv_can_map_lm, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #include "../CrossPlatform/vm_alloc.cpp" - int main(void) { /* returns 0 if we could map the lowmem globals */ - volatile char * lm = 0; - if (vm_init() < 0) exit(1); - if (vm_acquire_fixed(0, 0x2000) < 0) exit(1); - lm[0] = 'z'; - if (vm_release((char *)lm, 0x2000) < 0) exit(1); - vm_exit(); exit(0); - } - ], ac_cv_can_map_lm=yes, ac_cv_can_map_lm=no, - dnl When cross-compiling, do not assume anything. - ac_cv_can_map_lm="guessing no" - ) - AC_LANG_RESTORE - ] -) - -dnl Check signal handlers need to be reinstalled -AC_CACHE_CHECK([whether signal handlers need to be reinstalled], - ac_cv_signal_need_reinstall, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #include - #ifdef HAVE_UNISTD_H - #include - #endif - #include - static int handled_signal = 0; - RETSIGTYPE sigusr1_handler(int) { handled_signal++; } - int main(void) { /* returns 0 if signals need not to be reinstalled */ - signal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1); - exit(handled_signal == 2); - } - ], ac_cv_signal_need_reinstall=yes, ac_cv_signal_need_reinstall=no, - dnl When cross-compiling, do not assume anything. - ac_cv_signal_need_reinstall="guessing yes" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(SIGNAL_NEED_REINSTALL, "$ac_cv_signal_need_reinstall", - [Define if your system requires signals to be reinstalled.]) - -dnl Check if sigaction handlers need to be reinstalled -AC_CACHE_CHECK([whether sigaction handlers need to be reinstalled], - ac_cv_sigaction_need_reinstall, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #include - #ifdef HAVE_UNISTD_H - #include - #endif - #include - static int handled_signal = 0; - RETSIGTYPE sigusr1_handler(int) { handled_signal++; } - typedef RETSIGTYPE (*signal_handler)(int); - static signal_handler mysignal(int sig, signal_handler handler) { - struct sigaction old_sa; - struct sigaction new_sa; - new_sa.sa_handler = handler; - return ((sigaction(sig,&new_sa,&old_sa) < 0) ? SIG_IGN : old_sa.sa_handler); - } - int main(void) { /* returns 0 if signals need not to be reinstalled */ - mysignal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1); - exit(handled_signal == 2); - } - ], ac_cv_sigaction_need_reinstall=yes, ac_cv_sigaction_need_reinstall=no, - dnl When cross-compiling, do not assume anything. - ac_cv_sigaction_need_reinstall="guessing yes" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(SIGACTION_NEED_REINSTALL, "$ac_cv_sigaction_need_reinstall", - [Define if your system requires sigactions to be reinstalled.]) - -dnl Check if Mach exceptions supported. -AC_CACHE_CHECK([whether your system supports Mach exceptions], - ac_cv_have_mach_exceptions, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_UNISTD_H 1 - #define HAVE_MACH_VM 1 - #define HAVE_MACH_TASK_SELF 1 - #define HAVE_MACH_EXCEPTIONS 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], [ - sigsegv_recovery=mach - ac_cv_have_mach_exceptions=yes - ], - ac_cv_have_mach_exceptions=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_mach_exceptions=no - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_MACH_EXCEPTIONS, "$ac_cv_have_mach_exceptions", - [Define if your system supports Mach exceptions.]) - -dnl Otherwise, check if extended signals are supported with . -if [[ -z "$sigsegv_recovery" ]]; then - AC_CACHE_CHECK([whether your system supports extended signal handlers via asm], - ac_cv_have_asm_extended_signals, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #ifdef HAVE_UNISTD_H - #include - #endif - #define HAVE_ASM_UCONTEXT 1 - #define HAVE_SIGINFO_T 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], [ - sigsegv_recovery=siginfo - ac_cv_have_asm_extended_signals=yes - ], - ac_cv_have_asm_extended_signals=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_asm_extended_signals=no - ) - AC_LANG_RESTORE - ] - ) - AC_TRANSLATE_DEFINE(HAVE_ASM_UCONTEXT, "$ac_cv_have_asm_extended_signals", - [Define if your system has header.]) - AC_TRANSLATE_DEFINE(HAVE_SIGINFO_T, "$ac_cv_have_asm_extended_signals", - [Define if your system supports extended signals.]) -fi - -if [[ -z "$sigsegv_recovery" ]]; then - AC_CACHE_CHECK([whether your system supports extended signal handlers], - ac_cv_have_extended_signals, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #ifdef HAVE_UNISTD_H - #include - #endif - #define HAVE_SIGINFO_T 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], [ - sigsegv_recovery=siginfo - ac_cv_have_extended_signals=yes - ], - ac_cv_have_extended_signals=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_extended_signals=no - ) - AC_LANG_RESTORE - ] - ) - AC_TRANSLATE_DEFINE(HAVE_SIGINFO_T, "$ac_cv_have_extended_signals", - [Define if your system supports extended signals.]) -fi - -dnl Otherwise, check for subterfuges. -if [[ -z "$sigsegv_recovery" ]]; then - AC_CACHE_CHECK([whether we then have a subterfuge for your system], - ac_cv_have_sigcontext_hack, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGCONTEXT_SUBTERFUGE 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], [ - sigsegv_recovery=sigcontext - ac_cv_have_sigcontext_hack=yes - ], - ac_cv_have_sigcontext_hack=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_sigcontext_hack=no - ) - AC_LANG_RESTORE - ]) - AC_TRANSLATE_DEFINE(HAVE_SIGCONTEXT_SUBTERFUGE, "$ac_cv_have_sigcontext_hack", - [Define if we know a hack to replace siginfo_t->si_addr member.]) -fi - -dnl Check if we can ignore the fault (instruction skipping in SIGSEGV handler) -AC_CACHE_CHECK([whether we can skip instruction in SIGSEGV handler], - ac_cv_have_skip_instruction, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], ac_cv_have_skip_instruction=yes, ac_cv_have_skip_instruction=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_skip_instruction=no - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_SIGSEGV_SKIP_INSTRUCTION, "$ac_cv_have_skip_instruction", - [Define if we can ignore the fault (instruction skipping in SIGSEGV handler).]) - -dnl Can we do Video on SEGV Signals ? -CAN_VOSF=no -if [[ -n "$sigsegv_recovery" ]]; then - CAN_VOSF=yes -fi - -dnl A dummy program that returns always true -AC_PATH_PROG([BLESS], "true") - -dnl Check for linker script support -case $target_os:$target_cpu in -darwin*:*) LINKER_SCRIPT_FLAGS="-Wl,-seg1addr,0x78048000";; -esac -if [[ -n "$LINKER_SCRIPT_FLAGS" ]]; then - AC_CACHE_CHECK([whether linker script is usable], - ac_cv_linker_script_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - saved_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $LINKER_SCRIPT_FLAGS" - AC_TRY_RUN( - [int main() {if ((char *)&main < (char *)0x70000000) return 1;}], - [ac_cv_linker_script_works=yes], - [ac_cv_linker_script_works=no], - dnl When cross-compiling, assume it works - [ac_cv_linker_script_works="guessing yes"] - ) - AC_LANG_RESTORE - if [[ "$ac_cv_linker_script_works" = "no" ]]; then - LDFLAGS="$saved_LDFLAGS" - LINKER_SCRIPT_FLAGS="" - fi - ]) -fi -AC_TRANSLATE_DEFINE(HAVE_LINKER_SCRIPT, "$ac_cv_linker_script_works", - [Define if there is a linker script to relocate the executable above 0x70000000.]) - -dnl Determine the addressing mode to use - -ADDRESSING_MODE="" -AC_MSG_CHECKING([for the addressing mode to use]) -for am in $ADDRESSING_TEST_ORDER; do - case $am in - real) - dnl Requires ability to mmap() Low Memory globals - if [[ "x$ac_cv_can_map_lm$ac_cv_pagezero_hack" = "xnono" ]]; then - continue - fi - dnl Requires VOSF screen updates - if [[ "x$CAN_VOSF" = "xno" ]]; then - continue - fi - dnl Real addressing will probably work. - ADDRESSING_MODE="real" - WANT_VOSF=yes dnl we can use VOSF and we need it actually - DEFINES="$DEFINES -DREAL_ADDRESSING" - if [[ "x$ac_cv_pagezero_hack" = "xyes" ]]; then - BLESS=Darwin/lowmem - LDFLAGS="$LDFLAGS -pagezero_size 0x2000" - fi - break - ;; - direct) - dnl Requires VOSF screen updates - if [[ "x$CAN_VOSF" = "xyes" ]]; then - ADDRESSING_MODE="direct" - WANT_VOSF=yes dnl we can use VOSF and we need it actually - DEFINES="$DEFINES -DDIRECT_ADDRESSING" - break - fi - ;; - banks) - dnl Default addressing mode - ADDRESSING_MODE="memory banks" - break - ;; - *) - AC_MSG_ERROR([Internal configure.in script error for $am addressing mode]) - esac -done -AC_MSG_RESULT($ADDRESSING_MODE) -if [[ "x$ADDRESSING_MODE" = "x" ]]; then - AC_MSG_WARN([Sorry, no suitable addressing mode in $ADDRESSING_TEST_ORDER]) - ADDRESSING_MODE="memory banks" -fi - -dnl Enable VOSF screen updates with this feature is requested and feasible -if [[ "x$WANT_VOSF" = "xyes" -a "x$CAN_VOSF" = "xyes" ]]; then - AC_DEFINE(ENABLE_VOSF, 1, [Define if using video enabled on SEGV signals.]) -else - WANT_VOSF=no -fi - -dnl Check for GCC 2.7 or higher. -HAVE_GCC27=no -AC_MSG_CHECKING(for GCC 2.7 or higher) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if ! (__GNUC__ - 1 > 1 || __GNUC_MINOR__ - 1 > 5) - # error gcc < 2.7 - #endif - ]])], - [AC_MSG_RESULT(yes); HAVE_GCC27=yes], - [AC_MSG_RESULT(no)]) - -dnl Check for GCC 3.0 or higher. -HAVE_GCC30=no -AC_MSG_CHECKING(for GCC 3.0 or higher) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if ! (__GNUC__ >= 3) - # error gcc < 3 - #endif - ]])], - [AC_MSG_RESULT(yes); HAVE_GCC30=yes], - [AC_MSG_RESULT(no)]) - -dnl Check for ICC. -AC_MSG_CHECKING(for ICC) -HAVE_ICC=no -if $CXX -V -v 2>&1 | grep -q "Intel(R) C++ Compiler"; then - HAVE_ICC=yes -fi -AC_MSG_RESULT($HAVE_ICC) - -dnl Set "-fomit-frame-pointer" on i386 GCC 2.7 or higher. -dnl Also set "-fno-exceptions" for C++ because exception handling requires -dnl the frame pointer. -if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_I386" = "xyes" ]]; then - CFLAGS="$CFLAGS -fomit-frame-pointer" - CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -fno-exceptions" -fi - - -dnl Add -mdynamic-no-pic for MacOS X (XXX icc10 will support MacOS X) -if [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -mdynamic-no-pic" - AC_CACHE_CHECK([whether the compiler supports -mdynamic-no-pic], - ac_cv_gcc_mdynamic_no_pic, [ - AC_TRY_COMPILE([],[],[ac_cv_gcc_mdynamic_no_pic=yes],[ac_cv_gcc_mdynamic_no_pic=no]) - ]) - if [[ "x$ac_cv_gcc_mdynamic_no_pic" = "xyes" ]]; then - CXXFLAGS="$CXXFLAGS -mdynamic-no-pic" - else - CFLAGS="$SAVED_CFLAGS" - fi -fi - -dnl Select appropriate CPU source and REGPARAM define. -CPUSRCS="cpuemu.cpp" - -dnl Select appropriate FPU source. -AC_CHECK_HEADERS(ieee754.h ieeefp.h floatingpoint.h nan.h) - -for fpe in $FPE_CORE_TEST_ORDER; do - case $fpe in - uae) - FPE_CORE="uae fpu core" - DEFINES="$DEFINES -DFPU_UAE" - FPUSRCS="../uae_cpu/fpu/fpu_uae.cpp" - break - ;; - *) - AC_MSG_ERROR([Internal configure.in script error for $fpe fpu core]) - ;; - esac -done -if [[ "x$FPE_CORE" = "x" ]]; then - AC_MSG_ERROR([Sorry, no suitable FPU core found in $FPE_CORE_TEST_ORDER]) -fi - -dnl Check for certain math functions -AC_CHECK_FUNCS(atanh) -AC_CHECK_FUNCS(isnan isinf finite isnormal signbit) - -dnl UAE CPU sources for all non-m68k-native architectures. -CPUINCLUDES="-I../uae_cpu" -CPUSRCS="../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp $FPUSRCS cpustbl.cpp cpudefs.cpp $CPUSRCS" - -dnl Generate Makefile. -AC_SUBST(DEFINES) -AC_SUBST(SYSSRCS) -AC_SUBST(CPUINCLUDES) -AC_SUBST(CPUSRCS) -AC_SUBST(BLESS) -AC_SUBST(KEYCODES) -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT - -dnl Print summary. -echo -echo Basilisk II configuration summary: -echo -echo SDL support ............................ : $SDL_SUPPORT -echo Enable video on SEGV signals ........... : $WANT_VOSF -echo Floating-Point emulation core .......... : $FPE_CORE -echo Addressing mode ........................ : $ADDRESSING_MODE -echo Bad memory access recovery type ........ : $sigsegv_recovery -echo -echo "Configuration done. Now type \"make\" (or \"gmake\")." diff --git a/BasiliskII/src/Unix/cpr.sh b/BasiliskII/src/Unix/cpr.sh deleted file mode 100755 index 66223894..00000000 --- a/BasiliskII/src/Unix/cpr.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -# A script to copy recursively ignoring detritus. -# I based this off of a script I had that copied over ssh. -# source can be a file or directory. -# Mike Sliczniak 2009 - -# Don't copy resource forks or extended attributes on Mac OS X 10.4. -COPY_EXTENDED_ATTRIBUTES_DISABLE=true; export COPY_EXTENDED_ATTRIBUTES_DISABLE - -# Don't copy resource forks or extended attributes on Mac OS X 10.5. -COPYFILE_DISABLE=true; export COPYFILE_DISABLE - -case $# in - 2) - ;; - *) - echo "Usage: cpr source destdir" >&2 - exit 2 - ;; -esac - -# dir and base names of the source -d=`dirname "$1"` || exit -b=`basename "$1"` || exit - -# handle relative and absolute destination dirs -case "$2" in - /*) - p=$2 - ;; - *) - p="$PWD"/"$2" - ;; -esac - -# cd into the source dir -cd "$d" || exit - -# This is only for Mac OS X, but some systems do not have gtar, find -# sometimes lacks -f, and other systems use test -a. - -# List all interesting files for tar to copy: -# The first clause skips directories used for revision control. -# The second clause ignores detritus files from revision control and OSs. -# The third clause ignores ._ style files created by Mac OS X on file systems -# that do not have native resource forks or extended attributes. It checks to -# see that the file it is associated with exists. -find -f "$b" \( \! \( -type d \( \ - -name CVS -o -name RCS -o -name SCCS -o -name .git -o -name .svn \ -\) -prune \) \) \ -\ -\( \! \( -type f \( \ - -name .DS_Store -o -name Thumbs.db -o -name .cvsignore -o -name .gitignore \ -\) \) \) \ -\ -\( \! \( \ - -type f -name '._*' -execdir /bin/sh -c \ - 'f=`echo "$1" | sed "s:^\._:./:"`; [ -e "$f" ]' /bin/sh '{}' \; \ -\) \) -print0 | tar -c -f - --null -T - --no-recursion | tar -x -C "$p" -f - diff --git a/BasiliskII/src/Unix/install-sh b/BasiliskII/src/Unix/install-sh deleted file mode 100755 index 11870f1b..00000000 --- a/BasiliskII/src/Unix/install-sh +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - : -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - chmodcmd="" - else - instcmd=$mkdirprog - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f "$src" ] || [ -d "$src" ] - then - : - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - : - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - : - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' - ' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - : - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - : - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/BasiliskII/src/Unix/m4/egrep.m4 b/BasiliskII/src/Unix/m4/egrep.m4 deleted file mode 100644 index 051d7f5a..00000000 --- a/BasiliskII/src/Unix/m4/egrep.m4 +++ /dev/null @@ -1,13 +0,0 @@ -# AC_PROG_EGREP -# ------------- -# This is predefined starting with Autoconf 2.54, so this conditional -# definition can be removed once we require Autoconf 2.54 or later. -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], -[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], - [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi]) - EGREP=$ac_cv_prog_egrep - AC_SUBST([EGREP]) -])]) diff --git a/BasiliskII/src/Unix/m4/esd.m4 b/BasiliskII/src/Unix/m4/esd.m4 deleted file mode 100644 index 24666c96..00000000 --- a/BasiliskII/src/Unix/m4/esd.m4 +++ /dev/null @@ -1,194 +0,0 @@ -# Configure paths for ESD -# Manish Singh 98-9-30 -# stolen back from Frank Belew -# stolen from Manish Singh -# Shamelessly stolen from Owen Taylor - -dnl AM_PATH_ESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS -dnl -AC_DEFUN([AM_PATH_ESD], -[dnl -dnl Get the cflags and libraries from the esd-config script -dnl -AC_ARG_WITH(esd-prefix,[ --with-esd-prefix=PFX Prefix where ESD is installed (optional)], - esd_prefix="$withval", esd_prefix="") -AC_ARG_WITH(esd-exec-prefix,[ --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)], - esd_exec_prefix="$withval", esd_exec_prefix="") -AC_ARG_ENABLE(esdtest, [ --disable-esdtest Do not try to compile and run a test ESD program], - , enable_esdtest=yes) - - if test x$esd_exec_prefix != x ; then - esd_args="$esd_args --exec-prefix=$esd_exec_prefix" - if test x${ESD_CONFIG+set} != xset ; then - ESD_CONFIG=$esd_exec_prefix/bin/esd-config - fi - fi - if test x$esd_prefix != x ; then - esd_args="$esd_args --prefix=$esd_prefix" - if test x${ESD_CONFIG+set} != xset ; then - ESD_CONFIG=$esd_prefix/bin/esd-config - fi - fi - - AC_PATH_PROG(ESD_CONFIG, esd-config, no) - min_esd_version=ifelse([$1], ,0.2.7,$1) - AC_MSG_CHECKING(for ESD - version >= $min_esd_version) - no_esd="" - if test "$ESD_CONFIG" = "no" ; then - no_esd=yes - else - AC_LANG_SAVE - AC_LANG_C - ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags` - ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs` - - esd_major_version=`$ESD_CONFIG $esd_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - esd_minor_version=`$ESD_CONFIG $esd_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_esdtest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $ESD_CFLAGS" - LIBS="$LIBS $ESD_LIBS" -dnl -dnl Now check if the installed ESD is sufficiently new. (Also sanity -dnl checks the results of esd-config to some extent -dnl - rm -f conf.esdtest - AC_TRY_RUN([ -#include -#include -#include -#include - -char* -my_strdup (char *str) -{ - char *new_str; - - if (str) - { - new_str = malloc ((strlen (str) + 1) * sizeof(char)); - strcpy (new_str, str); - } - else - new_str = NULL; - - return new_str; -} - -int main () -{ - int major, minor, micro; - char *tmp_version; - - system ("touch conf.esdtest"); - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = my_strdup("$min_esd_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_esd_version"); - exit(1); - } - - if (($esd_major_version > major) || - (($esd_major_version == major) && ($esd_minor_version > minor)) || - (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version); - printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro); - printf("*** best to upgrade to the required version.\n"); - printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n"); - printf("*** to point to the correct copy of esd-config, and remove the file\n"); - printf("*** config.cache before re-running configure\n"); - return 1; - } -} - -],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - AC_LANG_RESTORE - fi - fi - if test "x$no_esd" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$ESD_CONFIG" = "no" ; then - echo "*** The esd-config script installed by ESD could not be found" - echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the ESD_CONFIG environment variable to the" - echo "*** full path to esd-config." - else - if test -f conf.esdtest ; then - : - else - echo "*** Could not run ESD test program, checking why..." - CFLAGS="$CFLAGS $ESD_CFLAGS" - LIBS="$LIBS $ESD_LIBS" - AC_LANG_SAVE - AC_LANG_C - AC_TRY_LINK([ -#include -#include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding ESD or finding the wrong" - echo "*** version of ESD. If it is not finding ESD, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means ESD was incorrectly installed" - echo "*** or that you have moved ESD since it was installed. In the latter case, you" - echo "*** may want to edit the esd-config script: $ESD_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - AC_LANG_RESTORE - fi - fi - ESD_CFLAGS="" - ESD_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(ESD_CFLAGS) - AC_SUBST(ESD_LIBS) - rm -f conf.esdtest -]) - -dnl AM_ESD_SUPPORTS_MULTIPLE_RECORD([ACTION-IF-SUPPORTS [, ACTION-IF-NOT-SUPPORTS]]) -dnl Test, whether esd supports multiple recording clients (version >=0.2.21) -dnl -AC_DEFUN([AM_ESD_SUPPORTS_MULTIPLE_RECORD], -[dnl - AC_MSG_NOTICE([whether installed esd version supports multiple recording clients]) - ac_save_ESD_CFLAGS="$ESD_CFLAGS" - ac_save_ESD_LIBS="$ESD_LIBS" - AM_PATH_ESD(0.2.21, - ifelse([$1], , [ - AM_CONDITIONAL(ESD_SUPPORTS_MULTIPLE_RECORD, true) - AC_DEFINE(ESD_SUPPORTS_MULTIPLE_RECORD, 1, - [Define if you have esound with support of multiple recording clients.])], - [$1]), - ifelse([$2], , [AM_CONDITIONAL(ESD_SUPPORTS_MULTIPLE_RECORD, false)], [$2]) - if test "x$ac_save_ESD_CFLAGS" != x ; then - ESD_CFLAGS="$ac_save_ESD_CFLAGS" - fi - if test "x$ac_save_ESD_LIBS" != x ; then - ESD_LIBS="$ac_save_ESD_LIBS" - fi - ) -]) diff --git a/BasiliskII/src/Unix/m4/gettext.m4 b/BasiliskII/src/Unix/m4/gettext.m4 deleted file mode 100644 index fbc5b5ba..00000000 --- a/BasiliskII/src/Unix/m4/gettext.m4 +++ /dev/null @@ -1,2576 +0,0 @@ -# codeset.m4 serial AM1 (gettext-0.10.40) -dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -AC_DEFUN([AM_LANGINFO_CODESET], -[ - AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, - [AC_TRY_LINK([#include ], - [char* cs = nl_langinfo(CODESET);], - am_cv_langinfo_codeset=yes, - am_cv_langinfo_codeset=no) - ]) - if test $am_cv_langinfo_codeset = yes; then - AC_DEFINE(HAVE_LANGINFO_CODESET, 1, - [Define if you have and nl_langinfo(CODESET).]) - fi -]) -# gettext.m4 serial 28 (gettext-0.13) -dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. -dnl -dnl This file can can be used in projects which are not available under -dnl the GNU General Public License or the GNU Library General Public -dnl License but which still want to provide support for the GNU gettext -dnl functionality. -dnl Please note that the actual code of the GNU gettext library is covered -dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. -dnl They are *not* in the public domain. - -dnl Authors: -dnl Ulrich Drepper , 1995-2000. -dnl Bruno Haible , 2000-2003. - -dnl Macro to add for using GNU gettext. - -dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). -dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The -dnl default (if it is not specified or empty) is 'no-libtool'. -dnl INTLSYMBOL should be 'external' for packages with no intl directory, -dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. -dnl If INTLSYMBOL is 'use-libtool', then a libtool library -dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, -dnl depending on --{enable,disable}-{shared,static} and on the presence of -dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library -dnl $(top_builddir)/intl/libintl.a will be created. -dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext -dnl implementations (in libc or libintl) without the ngettext() function -dnl will be ignored. If NEEDSYMBOL is specified and is -dnl 'need-formatstring-macros', then GNU gettext implementations that don't -dnl support the ISO C 99 formatstring macros will be ignored. -dnl INTLDIR is used to find the intl libraries. If empty, -dnl the value `$(top_builddir)/intl/' is used. -dnl -dnl The result of the configuration is one of three cases: -dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled -dnl and used. -dnl Catalog format: GNU --> install in $(datadir) -dnl Catalog extension: .mo after installation, .gmo in source tree -dnl 2) GNU gettext has been found in the system's C library. -dnl Catalog format: GNU --> install in $(datadir) -dnl Catalog extension: .mo after installation, .gmo in source tree -dnl 3) No internationalization, always use English msgid. -dnl Catalog format: none -dnl Catalog extension: none -dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. -dnl The use of .gmo is historical (it was needed to avoid overwriting the -dnl GNU format catalogs when building on a platform with an X/Open gettext), -dnl but we keep it in order not to force irrelevant filename changes on the -dnl maintainers. -dnl -AC_DEFUN([AM_GNU_GETTEXT], -[ - dnl Argument checking. - ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , - [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT -])])])])]) - ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , - [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT -])])])]) - define(gt_included_intl, ifelse([$1], [external], [no], [yes])) - define(gt_libtool_suffix_prefix, ifelse([$1], [use-libtool], [l], [])) - - AC_REQUIRE([AM_PO_SUBDIRS])dnl - ifelse(gt_included_intl, yes, [ - AC_REQUIRE([AM_INTL_SUBDIR])dnl - ]) - - dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - AC_REQUIRE([AC_LIB_RPATH]) - - dnl Sometimes libintl requires libiconv, so first search for libiconv. - dnl Ideally we would do this search only after the - dnl if test "$USE_NLS" = "yes"; then - dnl if test "$gt_cv_func_gnugettext_libc" != "yes"; then - dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT - dnl the configure script would need to contain the same shell code - dnl again, outside any 'if'. There are two solutions: - dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. - dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. - dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not - dnl documented, we avoid it. - ifelse(gt_included_intl, yes, , [ - AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) - ]) - - dnl Set USE_NLS. - AM_NLS - - ifelse(gt_included_intl, yes, [ - BUILD_INCLUDED_LIBINTL=no - USE_INCLUDED_LIBINTL=no - ]) - LIBINTL= - LTLIBINTL= - POSUB= - - dnl If we use NLS figure out what method - if test "$USE_NLS" = "yes"; then - gt_use_preinstalled_gnugettext=no - ifelse(gt_included_intl, yes, [ - AC_MSG_CHECKING([whether included gettext is requested]) - AC_ARG_WITH(included-gettext, - [ --with-included-gettext use the GNU gettext library included here], - nls_cv_force_use_gnu_gettext=$withval, - nls_cv_force_use_gnu_gettext=no) - AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) - - nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" - if test "$nls_cv_force_use_gnu_gettext" != "yes"; then - ]) - dnl User does not insist on using GNU NLS library. Figure out what - dnl to use. If GNU gettext is available we use this. Else we have - dnl to fall back to GNU NLS library. - - dnl Add a version number to the cache macros. - define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1))) - define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) - define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) - - AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, - [AC_TRY_LINK([#include -]ifelse([$2], [need-formatstring-macros], -[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION -#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) -#endif -changequote(,)dnl -typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; -changequote([,])dnl -], [])[extern int _nl_msg_cat_cntr; -extern int *_nl_domain_bindings;], - [bindtextdomain ("", ""); -return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings], - gt_cv_func_gnugettext_libc=yes, - gt_cv_func_gnugettext_libc=no)]) - - if test "$gt_cv_func_gnugettext_libc" != "yes"; then - dnl Sometimes libintl requires libiconv, so first search for libiconv. - ifelse(gt_included_intl, yes, , [ - AM_ICONV_LINK - ]) - dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL - dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) - dnl because that would add "-liconv" to LIBINTL and LTLIBINTL - dnl even if libiconv doesn't exist. - AC_LIB_LINKFLAGS_BODY([intl]) - AC_CACHE_CHECK([for GNU gettext in libintl], - gt_cv_func_gnugettext_libintl, - [gt_save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $INCINTL" - gt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBINTL" - dnl Now see whether libintl exists and does not depend on libiconv. - AC_TRY_LINK([#include -]ifelse([$2], [need-formatstring-macros], -[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION -#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) -#endif -changequote(,)dnl -typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; -changequote([,])dnl -], [])[extern int _nl_msg_cat_cntr; -extern -#ifdef __cplusplus -"C" -#endif -const char *_nl_expand_alias ();], - [bindtextdomain ("", ""); -return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)], - gt_cv_func_gnugettext_libintl=yes, - gt_cv_func_gnugettext_libintl=no) - dnl Now see whether libintl exists and depends on libiconv. - if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then - LIBS="$LIBS $LIBICONV" - AC_TRY_LINK([#include -]ifelse([$2], [need-formatstring-macros], -[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION -#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) -#endif -changequote(,)dnl -typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; -changequote([,])dnl -], [])[extern int _nl_msg_cat_cntr; -extern -#ifdef __cplusplus -"C" -#endif -const char *_nl_expand_alias ();], - [bindtextdomain ("", ""); -return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)], - [LIBINTL="$LIBINTL $LIBICONV" - LTLIBINTL="$LTLIBINTL $LTLIBICONV" - gt_cv_func_gnugettext_libintl=yes - ]) - fi - CPPFLAGS="$gt_save_CPPFLAGS" - LIBS="$gt_save_LIBS"]) - fi - - dnl If an already present or preinstalled GNU gettext() is found, - dnl use it. But if this macro is used in GNU gettext, and GNU - dnl gettext is already preinstalled in libintl, we update this - dnl libintl. (Cf. the install rule in intl/Makefile.in.) - if test "$gt_cv_func_gnugettext_libc" = "yes" \ - || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ - && test "$PACKAGE" != gettext-runtime \ - && test "$PACKAGE" != gettext-tools; }; then - gt_use_preinstalled_gnugettext=yes - else - dnl Reset the values set by searching for libintl. - LIBINTL= - LTLIBINTL= - INCINTL= - fi - - ifelse(gt_included_intl, yes, [ - if test "$gt_use_preinstalled_gnugettext" != "yes"; then - dnl GNU gettext is not found in the C library. - dnl Fall back on included GNU gettext library. - nls_cv_use_gnu_gettext=yes - fi - fi - - if test "$nls_cv_use_gnu_gettext" = "yes"; then - dnl Mark actions used to generate GNU NLS library. - BUILD_INCLUDED_LIBINTL=yes - USE_INCLUDED_LIBINTL=yes - LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV" - LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV" - LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` - fi - - if test "$gt_use_preinstalled_gnugettext" = "yes" \ - || test "$nls_cv_use_gnu_gettext" = "yes"; then - dnl Mark actions to use GNU gettext tools. - CATOBJEXT=.gmo - fi - ]) - - if test "$gt_use_preinstalled_gnugettext" = "yes" \ - || test "$nls_cv_use_gnu_gettext" = "yes"; then - AC_DEFINE(ENABLE_NLS, 1, - [Define to 1 if translation of program messages to the user's native language - is requested.]) - else - USE_NLS=no - fi - fi - - AC_MSG_CHECKING([whether to use NLS]) - AC_MSG_RESULT([$USE_NLS]) - if test "$USE_NLS" = "yes"; then - AC_MSG_CHECKING([where the gettext function comes from]) - if test "$gt_use_preinstalled_gnugettext" = "yes"; then - if test "$gt_cv_func_gnugettext_libintl" = "yes"; then - gt_source="external libintl" - else - gt_source="libc" - fi - else - gt_source="included intl directory" - fi - AC_MSG_RESULT([$gt_source]) - fi - - if test "$USE_NLS" = "yes"; then - - if test "$gt_use_preinstalled_gnugettext" = "yes"; then - if test "$gt_cv_func_gnugettext_libintl" = "yes"; then - AC_MSG_CHECKING([how to link with libintl]) - AC_MSG_RESULT([$LIBINTL]) - AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) - fi - - dnl For backward compatibility. Some packages may be using this. - AC_DEFINE(HAVE_GETTEXT, 1, - [Define if the GNU gettext() function is already present or preinstalled.]) - AC_DEFINE(HAVE_DCGETTEXT, 1, - [Define if the GNU dcgettext() function is already present or preinstalled.]) - fi - - dnl We need to process the po/ directory. - POSUB=po - fi - - ifelse(gt_included_intl, yes, [ - dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL - dnl to 'yes' because some of the testsuite requires it. - if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then - BUILD_INCLUDED_LIBINTL=yes - fi - - dnl Make all variables we use known to autoconf. - AC_SUBST(BUILD_INCLUDED_LIBINTL) - AC_SUBST(USE_INCLUDED_LIBINTL) - AC_SUBST(CATOBJEXT) - - dnl For backward compatibility. Some configure.ins may be using this. - nls_cv_header_intl= - nls_cv_header_libgt= - - dnl For backward compatibility. Some Makefiles may be using this. - DATADIRNAME=share - AC_SUBST(DATADIRNAME) - - dnl For backward compatibility. Some Makefiles may be using this. - INSTOBJEXT=.mo - AC_SUBST(INSTOBJEXT) - - dnl For backward compatibility. Some Makefiles may be using this. - GENCAT=gencat - AC_SUBST(GENCAT) - - dnl For backward compatibility. Some Makefiles may be using this. - if test "$USE_INCLUDED_LIBINTL" = yes; then - INTLOBJS="\$(GETTOBJS)" - fi - AC_SUBST(INTLOBJS) - - dnl Enable libtool support if the surrounding package wishes it. - INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix - AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) - ]) - - dnl For backward compatibility. Some Makefiles may be using this. - INTLLIBS="$LIBINTL" - AC_SUBST(INTLLIBS) - - dnl Make all documented variables known to autoconf. - AC_SUBST(LIBINTL) - AC_SUBST(LTLIBINTL) - AC_SUBST(POSUB) -]) - - -dnl Checks for all prerequisites of the intl subdirectory, -dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, -dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. -AC_DEFUN([AM_INTL_SUBDIR], -[ - AC_REQUIRE([AC_PROG_INSTALL])dnl - AC_REQUIRE([AM_MKINSTALLDIRS])dnl - AC_REQUIRE([AC_PROG_CC])dnl - AC_REQUIRE([AC_CANONICAL_HOST])dnl - AC_REQUIRE([AC_PROG_RANLIB])dnl - AC_REQUIRE([AC_ISC_POSIX])dnl - AC_REQUIRE([AC_HEADER_STDC])dnl - AC_REQUIRE([AC_C_CONST])dnl - AC_REQUIRE([bh_C_SIGNED])dnl - AC_REQUIRE([AC_C_INLINE])dnl - AC_REQUIRE([AC_TYPE_OFF_T])dnl - AC_REQUIRE([AC_TYPE_SIZE_T])dnl - AC_REQUIRE([jm_AC_TYPE_LONG_LONG])dnl - AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl - AC_REQUIRE([gt_TYPE_WCHAR_T])dnl - AC_REQUIRE([gt_TYPE_WINT_T])dnl - AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) - AC_REQUIRE([jm_AC_HEADER_STDINT_H]) - AC_REQUIRE([gt_TYPE_INTMAX_T]) - AC_REQUIRE([gt_PRINTF_POSIX]) - AC_REQUIRE([AC_FUNC_ALLOCA])dnl - AC_REQUIRE([AC_FUNC_MMAP])dnl - AC_REQUIRE([jm_GLIBC21])dnl - AC_REQUIRE([gt_INTDIV0])dnl - AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])dnl - AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl - AC_REQUIRE([gt_INTTYPES_PRI])dnl - AC_REQUIRE([gl_XSIZE])dnl - - AC_CHECK_TYPE([ptrdiff_t], , - [AC_DEFINE([ptrdiff_t], [long], - [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) - ]) - AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ -stdlib.h string.h unistd.h sys/param.h]) - AC_CHECK_FUNCS([asprintf fwprintf getcwd getegid geteuid getgid getuid \ -mempcpy munmap putenv setenv setlocale snprintf stpcpy strcasecmp strdup \ -strtoul tsearch wcslen __argz_count __argz_stringify __argz_next \ -__fsetlocking]) - - dnl Use the _snprintf function only if it is declared (because on NetBSD it - dnl is defined as a weak alias of snprintf; we prefer to use the latter). - gt_CHECK_DECL(_snprintf, [#include ]) - gt_CHECK_DECL(_snwprintf, [#include ]) - - dnl Use the *_unlocked functions only if they are declared. - dnl (because some of them were defined without being declared in Solaris - dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built - dnl on Solaris 2.5.1 to run on Solaris 2.6). - dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. - gt_CHECK_DECL(feof_unlocked, [#include ]) - gt_CHECK_DECL(fgets_unlocked, [#include ]) - gt_CHECK_DECL(getc_unlocked, [#include ]) - - case $gt_cv_func_printf_posix in - *yes) HAVE_POSIX_PRINTF=1 ;; - *) HAVE_POSIX_PRINTF=0 ;; - esac - AC_SUBST([HAVE_POSIX_PRINTF]) - if test "$ac_cv_func_asprintf" = yes; then - HAVE_ASPRINTF=1 - else - HAVE_ASPRINTF=0 - fi - AC_SUBST([HAVE_ASPRINTF]) - if test "$ac_cv_func_snprintf" = yes; then - HAVE_SNPRINTF=1 - else - HAVE_SNPRINTF=0 - fi - AC_SUBST([HAVE_SNPRINTF]) - if test "$ac_cv_func_wprintf" = yes; then - HAVE_WPRINTF=1 - else - HAVE_WPRINTF=0 - fi - AC_SUBST([HAVE_WPRINTF]) - - AM_ICONV - AM_LANGINFO_CODESET - if test $ac_cv_header_locale_h = yes; then - AM_LC_MESSAGES - fi - - dnl intl/plural.c is generated from intl/plural.y. It requires bison, - dnl because plural.y uses bison specific features. It requires at least - dnl bison-1.26 because earlier versions generate a plural.c that doesn't - dnl compile. - dnl bison is only needed for the maintainer (who touches plural.y). But in - dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put - dnl the rule in general Makefile. Now, some people carelessly touch the - dnl files or have a broken "make" program, hence the plural.c rule will - dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not - dnl present or too old. - AC_CHECK_PROGS([INTLBISON], [bison]) - if test -z "$INTLBISON"; then - ac_verc_fail=yes - else - dnl Found it, now check the version. - AC_MSG_CHECKING([version of bison]) -changequote(<<,>>)dnl - ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` - case $ac_prog_version in - '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; - 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) -changequote([,])dnl - ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; - *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; - esac - AC_MSG_RESULT([$ac_prog_version]) - fi - if test $ac_verc_fail = yes; then - INTLBISON=: - fi -]) - - -dnl gt_CHECK_DECL(FUNC, INCLUDES) -dnl Check whether a function is declared. -AC_DEFUN([gt_CHECK_DECL], -[ - AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, - [AC_TRY_COMPILE([$2], [ -#ifndef $1 - char *p = (char *) $1; -#endif -], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) - if test $ac_cv_have_decl_$1 = yes; then - gt_value=1 - else - gt_value=0 - fi - AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], - [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) -]) - - -dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) -AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) -# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40) -dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -# Test for the GNU C Library, version 2.1 or newer. -# From Bruno Haible. - -AC_DEFUN([jm_GLIBC21], - [ - AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, - ac_cv_gnu_library_2_1, - [AC_EGREP_CPP([Lucky GNU user], - [ -#include -#ifdef __GNU_LIBRARY__ - #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) - Lucky GNU user - #endif -#endif - ], - ac_cv_gnu_library_2_1=yes, - ac_cv_gnu_library_2_1=no) - ] - ) - AC_SUBST(GLIBC21) - GLIBC21="$ac_cv_gnu_library_2_1" - ] -) -# iconv.m4 serial AM4 (gettext-0.11.3) -dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], -[ - dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - AC_REQUIRE([AC_LIB_RPATH]) - - dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV - dnl accordingly. - AC_LIB_LINKFLAGS_BODY([iconv]) -]) - -AC_DEFUN([AM_ICONV_LINK], -[ - dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and - dnl those with the standalone portable GNU libiconv installed). - - dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV - dnl accordingly. - AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) - - dnl Add $INCICONV to CPPFLAGS before performing the following checks, - dnl because if the user has installed libiconv and not disabled its use - dnl via --without-libiconv-prefix, he wants to use it. The first - dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. - am_save_CPPFLAGS="$CPPFLAGS" - AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) - - AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ - am_cv_func_iconv="no, consider installing GNU libiconv" - am_cv_lib_iconv=no - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - am_cv_func_iconv=yes) - if test "$am_cv_func_iconv" != yes; then - am_save_LIBS="$LIBS" - LIBS="$LIBS $LIBICONV" - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - am_cv_lib_iconv=yes - am_cv_func_iconv=yes) - LIBS="$am_save_LIBS" - fi - ]) - if test "$am_cv_func_iconv" = yes; then - AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) - fi - if test "$am_cv_lib_iconv" = yes; then - AC_MSG_CHECKING([how to link with libiconv]) - AC_MSG_RESULT([$LIBICONV]) - else - dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV - dnl either. - CPPFLAGS="$am_save_CPPFLAGS" - LIBICONV= - LTLIBICONV= - fi - AC_SUBST(LIBICONV) - AC_SUBST(LTLIBICONV) -]) - -AC_DEFUN([AM_ICONV], -[ - AM_ICONV_LINK - if test "$am_cv_func_iconv" = yes; then - AC_MSG_CHECKING([for iconv declaration]) - AC_CACHE_VAL(am_cv_proto_iconv, [ - AC_TRY_COMPILE([ -#include -#include -extern -#ifdef __cplusplus -"C" -#endif -#if defined(__STDC__) || defined(__cplusplus) -size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); -#else -size_t iconv(); -#endif -], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") - am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) - am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` - AC_MSG_RESULT([$]{ac_t:- - }[$]am_cv_proto_iconv) - AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, - [Define as const if the declaration of iconv() needs const.]) - fi -]) -# intdiv0.m4 serial 1 (gettext-0.11.3) -dnl Copyright (C) 2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -AC_DEFUN([gt_INTDIV0], -[ - AC_REQUIRE([AC_PROG_CC])dnl - AC_REQUIRE([AC_CANONICAL_HOST])dnl - - AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], - gt_cv_int_divbyzero_sigfpe, - [ - AC_TRY_RUN([ -#include -#include - -static void -#ifdef __cplusplus -sigfpe_handler (int sig) -#else -sigfpe_handler (sig) int sig; -#endif -{ - /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ - exit (sig != SIGFPE); -} - -int x = 1; -int y = 0; -int z; -int nan; - -int main () -{ - signal (SIGFPE, sigfpe_handler); -/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ -#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) - signal (SIGTRAP, sigfpe_handler); -#endif -/* Linux/SPARC yields signal SIGILL. */ -#if defined (__sparc__) && defined (__linux__) - signal (SIGILL, sigfpe_handler); -#endif - - z = x / y; - nan = y / y; - exit (1); -} -], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, - [ - # Guess based on the CPU. - case "$host_cpu" in - alpha* | i[34567]86 | m68k | s390*) - gt_cv_int_divbyzero_sigfpe="guessing yes";; - *) - gt_cv_int_divbyzero_sigfpe="guessing no";; - esac - ]) - ]) - case "$gt_cv_int_divbyzero_sigfpe" in - *yes) value=1;; - *) value=0;; - esac - AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, - [Define if integer division by zero raises signal SIGFPE.]) -]) -# intmax.m4 serial 1 (gettext-0.12) -dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. -dnl Test whether the system has the 'intmax_t' type, but don't attempt to -dnl find a replacement if it is lacking. - -AC_DEFUN([gt_TYPE_INTMAX_T], -[ - AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) - AC_REQUIRE([jm_AC_HEADER_STDINT_H]) - AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, - [AC_TRY_COMPILE([ -#include -#include -#if HAVE_STDINT_H_WITH_UINTMAX -#include -#endif -#if HAVE_INTTYPES_H_WITH_UINTMAX -#include -#endif -], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)]) - if test $gt_cv_c_intmax_t = yes; then - AC_DEFINE(HAVE_INTMAX_T, 1, - [Define if you have the 'intmax_t' type in or .]) - fi -]) -# inttypes-pri.m4 serial 1 (gettext-0.11.4) -dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -# Define PRI_MACROS_BROKEN if exists and defines the PRI* -# macros to non-string values. This is the case on AIX 4.3.3. - -AC_DEFUN([gt_INTTYPES_PRI], -[ - AC_REQUIRE([gt_HEADER_INTTYPES_H]) - if test $gt_cv_header_inttypes_h = yes; then - AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], - gt_cv_inttypes_pri_broken, - [ - AC_TRY_COMPILE([#include -#ifdef PRId32 -char *p = PRId32; -#endif -], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) - ]) - fi - if test "$gt_cv_inttypes_pri_broken" = yes; then - AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, - [Define if exists and defines unusable PRI* macros.]) - fi -]) -# inttypes.m4 serial 1 (gettext-0.11.4) -dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Paul Eggert. - -# Define HAVE_INTTYPES_H if exists and doesn't clash with -# . - -AC_DEFUN([gt_HEADER_INTTYPES_H], -[ - AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h, - [ - AC_TRY_COMPILE( - [#include -#include ], - [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no) - ]) - if test $gt_cv_header_inttypes_h = yes; then - AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, - [Define if exists and doesn't clash with .]) - fi -]) -# inttypes_h.m4 serial 5 (gettext-0.12) -dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Paul Eggert. - -# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, -# doesn't clash with , and declares uintmax_t. - -AC_DEFUN([jm_AC_HEADER_INTTYPES_H], -[ - AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h, - [AC_TRY_COMPILE( - [#include -#include ], - [uintmax_t i = (uintmax_t) -1;], - jm_ac_cv_header_inttypes_h=yes, - jm_ac_cv_header_inttypes_h=no)]) - if test $jm_ac_cv_header_inttypes_h = yes; then - AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, - [Define if exists, doesn't clash with , - and declares uintmax_t. ]) - fi -]) -# lcmessage.m4 serial 3 (gettext-0.11.3) -dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. -dnl -dnl This file can can be used in projects which are not available under -dnl the GNU General Public License or the GNU Library General Public -dnl License but which still want to provide support for the GNU gettext -dnl functionality. -dnl Please note that the actual code of the GNU gettext library is covered -dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. -dnl They are *not* in the public domain. - -dnl Authors: -dnl Ulrich Drepper , 1995. - -# Check whether LC_MESSAGES is available in . - -AC_DEFUN([AM_LC_MESSAGES], -[ - AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, - [AC_TRY_LINK([#include ], [return LC_MESSAGES], - am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) - if test $am_cv_val_LC_MESSAGES = yes; then - AC_DEFINE(HAVE_LC_MESSAGES, 1, - [Define if your file defines LC_MESSAGES.]) - fi -]) -# longdouble.m4 serial 1 (gettext-0.12) -dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. -dnl Test whether the compiler supports the 'long double' type. -dnl Prerequisite: AC_PROG_CC - -AC_DEFUN([gt_TYPE_LONGDOUBLE], -[ - AC_CACHE_CHECK([for long double], gt_cv_c_long_double, - [if test "$GCC" = yes; then - gt_cv_c_long_double=yes - else - AC_TRY_COMPILE([ - /* The Stardent Vistra knows sizeof(long double), but does not support it. */ - long double foo = 0.0; - /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ - int array [2*(sizeof(long double) >= sizeof(double)) - 1]; - ], , - gt_cv_c_long_double=yes, gt_cv_c_long_double=no) - fi]) - if test $gt_cv_c_long_double = yes; then - AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) - fi -]) -# longlong.m4 serial 4 -dnl Copyright (C) 1999-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Paul Eggert. - -# Define HAVE_LONG_LONG if 'long long' works. - -AC_DEFUN([jm_AC_TYPE_LONG_LONG], -[ - AC_CACHE_CHECK([for long long], ac_cv_type_long_long, - [AC_TRY_LINK([long long ll = 1LL; int i = 63;], - [long long llmax = (long long) -1; - return ll << i | ll >> i | llmax / ll | llmax % ll;], - ac_cv_type_long_long=yes, - ac_cv_type_long_long=no)]) - if test $ac_cv_type_long_long = yes; then - AC_DEFINE(HAVE_LONG_LONG, 1, - [Define if you have the 'long long' type.]) - fi -]) -# nls.m4 serial 1 (gettext-0.12) -dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. -dnl -dnl This file can can be used in projects which are not available under -dnl the GNU General Public License or the GNU Library General Public -dnl License but which still want to provide support for the GNU gettext -dnl functionality. -dnl Please note that the actual code of the GNU gettext library is covered -dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. -dnl They are *not* in the public domain. - -dnl Authors: -dnl Ulrich Drepper , 1995-2000. -dnl Bruno Haible , 2000-2003. - -AC_DEFUN([AM_NLS], -[ - AC_MSG_CHECKING([whether NLS is requested]) - dnl Default is enabled NLS - AC_ARG_ENABLE(nls, - [ --disable-nls do not use Native Language Support], - USE_NLS=$enableval, USE_NLS=yes) - AC_MSG_RESULT($USE_NLS) - AC_SUBST(USE_NLS) -]) - -AC_DEFUN([AM_MKINSTALLDIRS], -[ - dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly - dnl find the mkinstalldirs script in another subdir but $(top_srcdir). - dnl Try to locate it. - MKINSTALLDIRS= - if test -n "$ac_aux_dir"; then - case "$ac_aux_dir" in - /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; - *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; - esac - fi - if test -z "$MKINSTALLDIRS"; then - MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" - fi - AC_SUBST(MKINSTALLDIRS) -]) -# po.m4 serial 3 (gettext-0.14) -dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. -dnl -dnl This file can can be used in projects which are not available under -dnl the GNU General Public License or the GNU Library General Public -dnl License but which still want to provide support for the GNU gettext -dnl functionality. -dnl Please note that the actual code of the GNU gettext library is covered -dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. -dnl They are *not* in the public domain. - -dnl Authors: -dnl Ulrich Drepper , 1995-2000. -dnl Bruno Haible , 2000-2003. - -dnl Checks for all prerequisites of the po subdirectory. -AC_DEFUN([AM_PO_SUBDIRS], -[ - AC_REQUIRE([AC_PROG_MAKE_SET])dnl - AC_REQUIRE([AC_PROG_INSTALL])dnl - AC_REQUIRE([AM_MKINSTALLDIRS])dnl - AC_REQUIRE([AM_NLS])dnl - - dnl Perform the following tests also if --disable-nls has been given, - dnl because they are needed for "make dist" to work. - - dnl Search for GNU msgfmt in the PATH. - dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. - dnl The second test excludes FreeBSD msgfmt. - AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, - [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 && - (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], - :) - AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) - - dnl Search for GNU xgettext 0.12 or newer in the PATH. - dnl The first test excludes Solaris xgettext and early GNU xgettext versions. - dnl The second test excludes FreeBSD xgettext. - AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, - [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && - (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], - :) - dnl Remove leftover from FreeBSD xgettext call. - rm -f messages.po - - dnl Search for GNU msgmerge 0.11 or newer in the PATH. - AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, - [$ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1], :) - - dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. - dnl Test whether we really found GNU msgfmt. - if test "$GMSGFMT" != ":"; then - dnl If it is no GNU msgfmt we define it as : so that the - dnl Makefiles still can work. - if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && - (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then - : ; - else - GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` - AC_MSG_RESULT( - [found $GMSGFMT program is not GNU msgfmt; ignore it]) - GMSGFMT=":" - fi - fi - - dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. - dnl Test whether we really found GNU xgettext. - if test "$XGETTEXT" != ":"; then - dnl If it is no GNU xgettext we define it as : so that the - dnl Makefiles still can work. - if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && - (if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then - : ; - else - AC_MSG_RESULT( - [found xgettext program is not GNU xgettext; ignore it]) - XGETTEXT=":" - fi - dnl Remove leftover from FreeBSD xgettext call. - rm -f messages.po - fi - - AC_OUTPUT_COMMANDS([ - for ac_file in $CONFIG_FILES; do - # Support "outfile[:infile[:infile...]]" - case "$ac_file" in - *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - esac - # PO directories have a Makefile.in generated from Makefile.in.in. - case "$ac_file" in */Makefile.in) - # Adjust a relative srcdir. - ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" - ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` - # In autoconf-2.13 it is called $ac_given_srcdir. - # In autoconf-2.50 it is called $srcdir. - test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" - case "$ac_given_srcdir" in - .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; - /*) top_srcdir="$ac_given_srcdir" ;; - *) top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then - rm -f "$ac_dir/POTFILES" - test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" - cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" - POMAKEFILEDEPS="POTFILES.in" - # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend - # on $ac_dir but don't depend on user-specified configuration - # parameters. - if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then - # The LINGUAS file contains the set of available languages. - if test -n "$OBSOLETE_ALL_LINGUAS"; then - test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" - fi - ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"` - # Hide the ALL_LINGUAS assigment from automake. - eval 'ALL_LINGUAS''=$ALL_LINGUAS_' - POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" - else - # The set of available languages was given in configure.in. - eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' - fi - # Compute POFILES - # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) - # Compute UPDATEPOFILES - # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) - # Compute DUMMYPOFILES - # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) - # Compute GMOFILES - # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) - case "$ac_given_srcdir" in - .) srcdirpre= ;; - *) srcdirpre='$(srcdir)/' ;; - esac - POFILES= - UPDATEPOFILES= - DUMMYPOFILES= - GMOFILES= - for lang in $ALL_LINGUAS; do - POFILES="$POFILES $srcdirpre$lang.po" - UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" - DUMMYPOFILES="$DUMMYPOFILES $lang.nop" - GMOFILES="$GMOFILES $srcdirpre$lang.gmo" - done - # CATALOGS depends on both $ac_dir and the user's LINGUAS - # environment variable. - INST_LINGUAS= - if test -n "$ALL_LINGUAS"; then - for presentlang in $ALL_LINGUAS; do - useit=no - if test "%UNSET%" != "$LINGUAS"; then - desiredlanguages="$LINGUAS" - else - desiredlanguages="$ALL_LINGUAS" - fi - for desiredlang in $desiredlanguages; do - # Use the presentlang catalog if desiredlang is - # a. equal to presentlang, or - # b. a variant of presentlang (because in this case, - # presentlang can be used as a fallback for messages - # which are not translated in the desiredlang catalog). - case "$desiredlang" in - "$presentlang"*) useit=yes;; - esac - done - if test $useit = yes; then - INST_LINGUAS="$INST_LINGUAS $presentlang" - fi - done - fi - CATALOGS= - if test -n "$INST_LINGUAS"; then - for lang in $INST_LINGUAS; do - CATALOGS="$CATALOGS $lang.gmo" - done - fi - test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" - sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" - for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do - if test -f "$f"; then - case "$f" in - *.orig | *.bak | *~) ;; - *) cat "$f" >> "$ac_dir/Makefile" ;; - esac - fi - done - fi - ;; - esac - done], - [# Capture the value of obsolete ALL_LINGUAS because we need it to compute - # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it - # from automake. - eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' - # Capture the value of LINGUAS because we need it to compute CATALOGS. - LINGUAS="${LINGUAS-%UNSET%}" - ]) -]) - -dnl Postprocesses a Makefile in a directory containing PO files. -AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], -[ - # When this code is run, in config.status, two variables have already been - # set: - # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, - # - LINGUAS is the value of the environment variable LINGUAS at configure - # time. - -changequote(,)dnl - # Adjust a relative srcdir. - ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` - ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" - ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` - # In autoconf-2.13 it is called $ac_given_srcdir. - # In autoconf-2.50 it is called $srcdir. - test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" - case "$ac_given_srcdir" in - .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; - /*) top_srcdir="$ac_given_srcdir" ;; - *) top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - - # Find a way to echo strings without interpreting backslash. - if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then - gt_echo='echo' - else - if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then - gt_echo='printf %s\n' - else - echo_func () { - cat < "$ac_file.tmp" - if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then - # Add dependencies that cannot be formulated as a simple suffix rule. - for lang in $ALL_LINGUAS; do - frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` - cat >> "$ac_file.tmp" < /dev/null; then - # Add dependencies that cannot be formulated as a simple suffix rule. - for lang in $ALL_LINGUAS; do - frobbedlang=`echo $lang | sed -e 's/_/-/g'` - cat >> "$ac_file.tmp" <> "$ac_file.tmp" < -#include -/* The string "%2$d %1$d", with dollar characters protected from the shell's - dollar expansion (possibly an autoconf bug). */ -static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; -static char buf[100]; -int main () -{ - sprintf (buf, format, 33, 55); - return (strcmp (buf, "55 33") != 0); -}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, - [ - AC_EGREP_CPP(notposix, [ -#if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ - notposix -#endif - ], gt_cv_func_printf_posix="guessing no", - gt_cv_func_printf_posix="guessing yes") - ]) - ]) - case $gt_cv_func_printf_posix in - *yes) - AC_DEFINE(HAVE_POSIX_PRINTF, 1, - [Define if your printf() function supports format strings with positions.]) - ;; - esac -]) -# progtest.m4 serial 3 (gettext-0.12) -dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. -dnl -dnl This file can can be used in projects which are not available under -dnl the GNU General Public License or the GNU Library General Public -dnl License but which still want to provide support for the GNU gettext -dnl functionality. -dnl Please note that the actual code of the GNU gettext library is covered -dnl by the GNU Library General Public License, and the rest of the GNU -dnl gettext package package is covered by the GNU General Public License. -dnl They are *not* in the public domain. - -dnl Authors: -dnl Ulrich Drepper , 1996. - -# Search path for a program which passes the given test. - -dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, -dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) -AC_DEFUN([AM_PATH_PROG_WITH_TEST], -[ -# Prepare PATH_SEPARATOR. -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Find out how to test for executable files. Don't use a zero-byte file, -# as systems may use methods other than mode bits to determine executability. -cat >conf$$.file <<_ASEOF -#! /bin/sh -exit 0 -_ASEOF -chmod +x conf$$.file -if test -x conf$$.file >/dev/null 2>&1; then - ac_executable_p="test -x" -else - ac_executable_p="test -f" -fi -rm -f conf$$.file - -# Extract the first word of "$2", so it can be a program name with args. -set dummy $2; ac_word=[$]2 -AC_MSG_CHECKING([for $ac_word]) -AC_CACHE_VAL(ac_cv_path_$1, -[case "[$]$1" in - [[\\/]]* | ?:[[\\/]]*) - ac_cv_path_$1="[$]$1" # Let the user override the test with a path. - ;; - *) - ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in ifelse([$5], , $PATH, [$5]); do - IFS="$ac_save_IFS" - test -z "$ac_dir" && ac_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then - if [$3]; then - ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" - break 2 - fi - fi - done - done - IFS="$ac_save_IFS" -dnl If no 4th arg is given, leave the cache variable unset, -dnl so AC_PATH_PROGS will keep looking. -ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" -])dnl - ;; -esac])dnl -$1="$ac_cv_path_$1" -if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then - AC_MSG_RESULT([$]$1) -else - AC_MSG_RESULT(no) -fi -AC_SUBST($1)dnl -]) -# signed.m4 serial 1 (gettext-0.10.40) -dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -AC_DEFUN([bh_C_SIGNED], -[ - AC_CACHE_CHECK([for signed], bh_cv_c_signed, - [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) - if test $bh_cv_c_signed = no; then - AC_DEFINE(signed, , - [Define to empty if the C compiler doesn't support this keyword.]) - fi -]) -# size_max.m4 serial 2 -dnl Copyright (C) 2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -AC_DEFUN([gl_SIZE_MAX], -[ - AC_CHECK_HEADERS(stdint.h) - dnl First test whether the system already has SIZE_MAX. - AC_MSG_CHECKING([for SIZE_MAX]) - result= - AC_EGREP_CPP([Found it], [ -#include -#if HAVE_STDINT_H -#include -#endif -#ifdef SIZE_MAX -Found it -#endif -], result=yes) - if test -z "$result"; then - dnl Define it ourselves. Here we assume that the type 'size_t' is not wider - dnl than the type 'unsigned long'. - dnl The _AC_COMPUTE_INT macro works up to LONG_MAX, since it uses 'expr', - dnl which is guaranteed to work from LONG_MIN to LONG_MAX. - _AC_COMPUTE_INT([~(size_t)0 / 10], res_hi, - [#include ], result=?) - _AC_COMPUTE_INT([~(size_t)0 % 10], res_lo, - [#include ], result=?) - _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, - [#include ], result=?) - if test "$fits_in_uint" = 1; then - dnl Even though SIZE_MAX fits in an unsigned int, it must be of type - dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. - AC_TRY_COMPILE([#include - extern size_t foo; - extern unsigned long foo; - ], [], fits_in_uint=0) - fi - if test -z "$result"; then - if test "$fits_in_uint" = 1; then - result="$res_hi$res_lo"U - else - result="$res_hi$res_lo"UL - fi - else - dnl Shouldn't happen, but who knows... - result='~(size_t)0' - fi - fi - AC_MSG_RESULT([$result]) - if test "$result" != yes; then - AC_DEFINE_UNQUOTED([SIZE_MAX], [$result], - [Define as the maximum value of type 'size_t', if the system doesn't define it.]) - fi -]) -# stdint_h.m4 serial 3 (gettext-0.12) -dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Paul Eggert. - -# Define HAVE_STDINT_H_WITH_UINTMAX if exists, -# doesn't clash with , and declares uintmax_t. - -AC_DEFUN([jm_AC_HEADER_STDINT_H], -[ - AC_CACHE_CHECK([for stdint.h], jm_ac_cv_header_stdint_h, - [AC_TRY_COMPILE( - [#include -#include ], - [uintmax_t i = (uintmax_t) -1;], - jm_ac_cv_header_stdint_h=yes, - jm_ac_cv_header_stdint_h=no)]) - if test $jm_ac_cv_header_stdint_h = yes; then - AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, - [Define if exists, doesn't clash with , - and declares uintmax_t. ]) - fi -]) -# uintmax_t.m4 serial 7 (gettext-0.12) -dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Paul Eggert. - -AC_PREREQ(2.13) - -# Define uintmax_t to 'unsigned long' or 'unsigned long long' -# if it is not already defined in or . - -AC_DEFUN([jm_AC_TYPE_UINTMAX_T], -[ - AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) - AC_REQUIRE([jm_AC_HEADER_STDINT_H]) - if test $jm_ac_cv_header_inttypes_h = no && test $jm_ac_cv_header_stdint_h = no; then - AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG]) - test $ac_cv_type_unsigned_long_long = yes \ - && ac_type='unsigned long long' \ - || ac_type='unsigned long' - AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, - [Define to unsigned long or unsigned long long - if and don't define.]) - else - AC_DEFINE(HAVE_UINTMAX_T, 1, - [Define if you have the 'uintmax_t' type in or .]) - fi -]) -# ulonglong.m4 serial 3 -dnl Copyright (C) 1999-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Paul Eggert. - -# Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. - -AC_DEFUN([jm_AC_TYPE_UNSIGNED_LONG_LONG], -[ - AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, - [AC_TRY_LINK([unsigned long long ull = 1ULL; int i = 63;], - [unsigned long long ullmax = (unsigned long long) -1; - return ull << i | ull >> i | ullmax / ull | ullmax % ull;], - ac_cv_type_unsigned_long_long=yes, - ac_cv_type_unsigned_long_long=no)]) - if test $ac_cv_type_unsigned_long_long = yes; then - AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, - [Define if you have the 'unsigned long long' type.]) - fi -]) -# wchar_t.m4 serial 1 (gettext-0.12) -dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. -dnl Test whether has the 'wchar_t' type. -dnl Prerequisite: AC_PROG_CC - -AC_DEFUN([gt_TYPE_WCHAR_T], -[ - AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, - [AC_TRY_COMPILE([#include - wchar_t foo = (wchar_t)'\0';], , - gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) - if test $gt_cv_c_wchar_t = yes; then - AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) - fi -]) -# wint_t.m4 serial 1 (gettext-0.12) -dnl Copyright (C) 2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. -dnl Test whether has the 'wint_t' type. -dnl Prerequisite: AC_PROG_CC - -AC_DEFUN([gt_TYPE_WINT_T], -[ - AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, - [AC_TRY_COMPILE([#include - wint_t foo = (wchar_t)'\0';], , - gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) - if test $gt_cv_c_wint_t = yes; then - AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) - fi -]) -# xsize.m4 serial 2 -dnl Copyright (C) 2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -AC_DEFUN([gl_XSIZE], -[ - dnl Prerequisites of lib/xsize.h. - AC_REQUIRE([gl_SIZE_MAX]) - AC_CHECK_HEADERS(stdint.h) -]) -# lib-link.m4 serial 4 (gettext-0.12) -dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and -dnl the libraries corresponding to explicit and implicit dependencies. -dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and -dnl augments the CPPFLAGS variable. -AC_DEFUN([AC_LIB_LINKFLAGS], -[ - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - AC_REQUIRE([AC_LIB_RPATH]) - define([Name],[translit([$1],[./-], [___])]) - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) - AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ - AC_LIB_LINKFLAGS_BODY([$1], [$2]) - ac_cv_lib[]Name[]_libs="$LIB[]NAME" - ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" - ac_cv_lib[]Name[]_cppflags="$INC[]NAME" - ]) - LIB[]NAME="$ac_cv_lib[]Name[]_libs" - LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" - INC[]NAME="$ac_cv_lib[]Name[]_cppflags" - AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) - AC_SUBST([LIB]NAME) - AC_SUBST([LTLIB]NAME) - dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the - dnl results of this search when this library appears as a dependency. - HAVE_LIB[]NAME=yes - undefine([Name]) - undefine([NAME]) -]) - -dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) -dnl searches for libname and the libraries corresponding to explicit and -dnl implicit dependencies, together with the specified include files and -dnl the ability to compile and link the specified testcode. If found, it -dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and -dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and -dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs -dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. -AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], -[ - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - AC_REQUIRE([AC_LIB_RPATH]) - define([Name],[translit([$1],[./-], [___])]) - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) - - dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME - dnl accordingly. - AC_LIB_LINKFLAGS_BODY([$1], [$2]) - - dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, - dnl because if the user has installed lib[]Name and not disabled its use - dnl via --without-lib[]Name-prefix, he wants to use it. - ac_save_CPPFLAGS="$CPPFLAGS" - AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) - - AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ - ac_save_LIBS="$LIBS" - LIBS="$LIBS $LIB[]NAME" - AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) - LIBS="$ac_save_LIBS" - ]) - if test "$ac_cv_lib[]Name" = yes; then - HAVE_LIB[]NAME=yes - AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) - AC_MSG_CHECKING([how to link with lib[]$1]) - AC_MSG_RESULT([$LIB[]NAME]) - else - HAVE_LIB[]NAME=no - dnl If $LIB[]NAME didn't lead to a usable library, we don't need - dnl $INC[]NAME either. - CPPFLAGS="$ac_save_CPPFLAGS" - LIB[]NAME= - LTLIB[]NAME= - fi - AC_SUBST([HAVE_LIB]NAME) - AC_SUBST([LIB]NAME) - AC_SUBST([LTLIB]NAME) - undefine([Name]) - undefine([NAME]) -]) - -dnl Determine the platform dependent parameters needed to use rpath: -dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, -dnl hardcode_direct, hardcode_minus_L. -AC_DEFUN([AC_LIB_RPATH], -[ - AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS - AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld - AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host - AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir - AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ - CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ - ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh - . ./conftest.sh - rm -f ./conftest.sh - acl_cv_rpath=done - ]) - wl="$acl_cv_wl" - libext="$acl_cv_libext" - shlibext="$acl_cv_shlibext" - hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" - hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" - hardcode_direct="$acl_cv_hardcode_direct" - hardcode_minus_L="$acl_cv_hardcode_minus_L" - dnl Determine whether the user wants rpath handling at all. - AC_ARG_ENABLE(rpath, - [ --disable-rpath do not hardcode runtime library paths], - :, enable_rpath=yes) -]) - -dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and -dnl the libraries corresponding to explicit and implicit dependencies. -dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. -AC_DEFUN([AC_LIB_LINKFLAGS_BODY], -[ - define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], - [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) - dnl By default, look in $includedir and $libdir. - use_additional=yes - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - AC_LIB_ARG_WITH([lib$1-prefix], -[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib - --without-lib$1-prefix don't search for lib$1 in includedir and libdir], -[ - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - else - additional_includedir="$withval/include" - additional_libdir="$withval/lib" - fi - fi -]) - dnl Search the library and its dependencies in $additional_libdir and - dnl $LDFLAGS. Using breadth-first-seach. - LIB[]NAME= - LTLIB[]NAME= - INC[]NAME= - rpathdirs= - ltrpathdirs= - names_already_handled= - names_next_round='$1 $2' - while test -n "$names_next_round"; do - names_this_round="$names_next_round" - names_next_round= - for name in $names_this_round; do - already_handled= - for n in $names_already_handled; do - if test "$n" = "$name"; then - already_handled=yes - break - fi - done - if test -z "$already_handled"; then - names_already_handled="$names_already_handled $name" - dnl See if it was already located by an earlier AC_LIB_LINKFLAGS - dnl or AC_LIB_HAVE_LINKFLAGS call. - uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` - eval value=\"\$HAVE_LIB$uppername\" - if test -n "$value"; then - if test "$value" = yes; then - eval value=\"\$LIB$uppername\" - test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" - eval value=\"\$LTLIB$uppername\" - test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" - else - dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined - dnl that this library doesn't exist. So just drop it. - : - fi - else - dnl Search the library lib$name in $additional_libdir and $LDFLAGS - dnl and the already constructed $LIBNAME/$LTLIBNAME. - found_dir= - found_la= - found_so= - found_a= - if test $use_additional = yes; then - if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then - found_dir="$additional_libdir" - found_so="$additional_libdir/lib$name.$shlibext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - else - if test -f "$additional_libdir/lib$name.$libext"; then - found_dir="$additional_libdir" - found_a="$additional_libdir/lib$name.$libext" - if test -f "$additional_libdir/lib$name.la"; then - found_la="$additional_libdir/lib$name.la" - fi - fi - fi - fi - if test "X$found_dir" = "X"; then - for x in $LDFLAGS $LTLIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - case "$x" in - -L*) - dir=`echo "X$x" | sed -e 's/^X-L//'` - if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then - found_dir="$dir" - found_so="$dir/lib$name.$shlibext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - else - if test -f "$dir/lib$name.$libext"; then - found_dir="$dir" - found_a="$dir/lib$name.$libext" - if test -f "$dir/lib$name.la"; then - found_la="$dir/lib$name.la" - fi - fi - fi - ;; - esac - if test "X$found_dir" != "X"; then - break - fi - done - fi - if test "X$found_dir" != "X"; then - dnl Found the library. - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" - if test "X$found_so" != "X"; then - dnl Linking with a shared library. We attempt to hardcode its - dnl directory into the executable's runpath, unless it's the - dnl standard /usr/lib. - if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then - dnl No hardcoding is needed. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - else - dnl Use an explicit option to hardcode DIR into the resulting - dnl binary. - dnl Potentially add DIR to ltrpathdirs. - dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $found_dir" - fi - dnl The hardcoding into $LIBNAME is system dependent. - if test "$hardcode_direct" = yes; then - dnl Using DIR/libNAME.so during linking hardcodes DIR into the - dnl resulting binary. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - else - if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then - dnl Use an explicit option to hardcode DIR into the resulting - dnl binary. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - dnl Potentially add DIR to rpathdirs. - dnl The rpathdirs will be appended to $LIBNAME at the end. - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $found_dir" - fi - else - dnl Rely on "-L$found_dir". - dnl But don't add it if it's already contained in the LDFLAGS - dnl or the already constructed $LIBNAME - haveit= - for x in $LDFLAGS $LIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$found_dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" - fi - if test "$hardcode_minus_L" != no; then - dnl FIXME: Not sure whether we should use - dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" - dnl here. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" - else - dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH - dnl here, because this doesn't fit in flags passed to the - dnl compiler. So give up. No hardcoding. This affects only - dnl very old systems. - dnl FIXME: Not sure whether we should use - dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" - dnl here. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" - fi - fi - fi - fi - else - if test "X$found_a" != "X"; then - dnl Linking with a static library. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" - else - dnl We shouldn't come here, but anyway it's good to have a - dnl fallback. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" - fi - fi - dnl Assume the include files are nearby. - additional_includedir= - case "$found_dir" in - */lib | */lib/) - basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` - additional_includedir="$basedir/include" - ;; - esac - if test "X$additional_includedir" != "X"; then - dnl Potentially add $additional_includedir to $INCNAME. - dnl But don't add it - dnl 1. if it's the standard /usr/include, - dnl 2. if it's /usr/local/include and we are using GCC on Linux, - dnl 3. if it's already present in $CPPFLAGS or the already - dnl constructed $INCNAME, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux*) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - for x in $CPPFLAGS $INC[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - dnl Really add $additional_includedir to $INCNAME. - INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" - fi - fi - fi - fi - fi - dnl Look for dependencies. - if test -n "$found_la"; then - dnl Read the .la file. It defines the variables - dnl dlname, library_names, old_library, dependency_libs, current, - dnl age, revision, installed, dlopen, dlpreopen, libdir. - save_libdir="$libdir" - case "$found_la" in - */* | *\\*) . "$found_la" ;; - *) . "./$found_la" ;; - esac - libdir="$save_libdir" - dnl We use only dependency_libs. - for dep in $dependency_libs; do - case "$dep" in - -L*) - additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` - dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. - dnl But don't add it - dnl 1. if it's the standard /usr/lib, - dnl 2. if it's /usr/local/lib and we are using GCC on Linux, - dnl 3. if it's already present in $LDFLAGS or the already - dnl constructed $LIBNAME, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_libdir" != "X/usr/lib"; then - haveit= - if test "X$additional_libdir" = "X/usr/local/lib"; then - if test -n "$GCC"; then - case $host_os in - linux*) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - haveit= - for x in $LDFLAGS $LIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - dnl Really add $additional_libdir to $LIBNAME. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" - fi - fi - haveit= - for x in $LDFLAGS $LTLIB[]NAME; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - dnl Really add $additional_libdir to $LTLIBNAME. - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" - fi - fi - fi - fi - ;; - -R*) - dir=`echo "X$dep" | sed -e 's/^X-R//'` - if test "$enable_rpath" != no; then - dnl Potentially add DIR to rpathdirs. - dnl The rpathdirs will be appended to $LIBNAME at the end. - haveit= - for x in $rpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - rpathdirs="$rpathdirs $dir" - fi - dnl Potentially add DIR to ltrpathdirs. - dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. - haveit= - for x in $ltrpathdirs; do - if test "X$x" = "X$dir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - ltrpathdirs="$ltrpathdirs $dir" - fi - fi - ;; - -l*) - dnl Handle this in the next round. - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` - ;; - *.la) - dnl Handle this in the next round. Throw away the .la's - dnl directory; it is already contained in a preceding -L - dnl option. - names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` - ;; - *) - dnl Most likely an immediate library name. - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" - ;; - esac - done - fi - else - dnl Didn't find the library; assume it is in the system directories - dnl known to the linker and runtime loader. (All the system - dnl directories known to the linker should also be known to the - dnl runtime loader, otherwise the system is severely misconfigured.) - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" - fi - fi - fi - done - done - if test "X$rpathdirs" != "X"; then - if test -n "$hardcode_libdir_separator"; then - dnl Weird platform: only the last -rpath option counts, the user must - dnl pass all path elements in one option. We can arrange that for a - dnl single library, but not when more than one $LIBNAMEs are used. - alldirs= - for found_dir in $rpathdirs; do - alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" - done - dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. - acl_save_libdir="$libdir" - libdir="$alldirs" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" - else - dnl The -rpath options are cumulative. - for found_dir in $rpathdirs; do - acl_save_libdir="$libdir" - libdir="$found_dir" - eval flag=\"$hardcode_libdir_flag_spec\" - libdir="$acl_save_libdir" - LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" - done - fi - fi - if test "X$ltrpathdirs" != "X"; then - dnl When using libtool, the option that works for both libraries and - dnl executables is -R. The -R options are cumulative. - for found_dir in $ltrpathdirs; do - LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" - done - fi -]) - -dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, -dnl unless already present in VAR. -dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes -dnl contains two or three consecutive elements that belong together. -AC_DEFUN([AC_LIB_APPENDTOVAR], -[ - for element in [$2]; do - haveit= - for x in $[$1]; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - [$1]="${[$1]}${[$1]:+ }$element" - fi - done -]) -# lib-prefix.m4 serial 3 (gettext-0.13) -dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl From Bruno Haible. - -dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and -dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't -dnl require excessive bracketing. -ifdef([AC_HELP_STRING], -[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], -[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) - -dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed -dnl to access previously installed libraries. The basic assumption is that -dnl a user will want packages to use other packages he previously installed -dnl with the same --prefix option. -dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate -dnl libraries, but is otherwise very convenient. -AC_DEFUN([AC_LIB_PREFIX], -[ - AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) - AC_REQUIRE([AC_PROG_CC]) - AC_REQUIRE([AC_CANONICAL_HOST]) - AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) - dnl By default, look in $includedir and $libdir. - use_additional=yes - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - AC_LIB_ARG_WITH([lib-prefix], -[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib - --without-lib-prefix don't search for libraries in includedir and libdir], -[ - if test "X$withval" = "Xno"; then - use_additional=no - else - if test "X$withval" = "X"; then - AC_LIB_WITH_FINAL_PREFIX([ - eval additional_includedir=\"$includedir\" - eval additional_libdir=\"$libdir\" - ]) - else - additional_includedir="$withval/include" - additional_libdir="$withval/lib" - fi - fi -]) - if test $use_additional = yes; then - dnl Potentially add $additional_includedir to $CPPFLAGS. - dnl But don't add it - dnl 1. if it's the standard /usr/include, - dnl 2. if it's already present in $CPPFLAGS, - dnl 3. if it's /usr/local/include and we are using GCC on Linux, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_includedir" != "X/usr/include"; then - haveit= - for x in $CPPFLAGS; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-I$additional_includedir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test "X$additional_includedir" = "X/usr/local/include"; then - if test -n "$GCC"; then - case $host_os in - linux*) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - if test -d "$additional_includedir"; then - dnl Really add $additional_includedir to $CPPFLAGS. - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" - fi - fi - fi - fi - dnl Potentially add $additional_libdir to $LDFLAGS. - dnl But don't add it - dnl 1. if it's the standard /usr/lib, - dnl 2. if it's already present in $LDFLAGS, - dnl 3. if it's /usr/local/lib and we are using GCC on Linux, - dnl 4. if it doesn't exist as a directory. - if test "X$additional_libdir" != "X/usr/lib"; then - haveit= - for x in $LDFLAGS; do - AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) - if test "X$x" = "X-L$additional_libdir"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - if test "X$additional_libdir" = "X/usr/local/lib"; then - if test -n "$GCC"; then - case $host_os in - linux*) haveit=yes;; - esac - fi - fi - if test -z "$haveit"; then - if test -d "$additional_libdir"; then - dnl Really add $additional_libdir to $LDFLAGS. - LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" - fi - fi - fi - fi - fi -]) - -dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, -dnl acl_final_exec_prefix, containing the values to which $prefix and -dnl $exec_prefix will expand at the end of the configure script. -AC_DEFUN([AC_LIB_PREPARE_PREFIX], -[ - dnl Unfortunately, prefix and exec_prefix get only finally determined - dnl at the end of configure. - if test "X$prefix" = "XNONE"; then - acl_final_prefix="$ac_default_prefix" - else - acl_final_prefix="$prefix" - fi - if test "X$exec_prefix" = "XNONE"; then - acl_final_exec_prefix='${prefix}' - else - acl_final_exec_prefix="$exec_prefix" - fi - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" - prefix="$acl_save_prefix" -]) - -dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the -dnl variables prefix and exec_prefix bound to the values they will have -dnl at the end of the configure script. -AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], -[ - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - $1 - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" -]) -# lib-ld.m4 serial 3 (gettext-0.13) -dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. -dnl This file is free software, distributed under the terms of the GNU -dnl General Public License. As a special exception to the GNU General -dnl Public License, this file may be distributed as part of a program -dnl that contains a configuration script generated by Autoconf, under -dnl the same distribution terms as the rest of that program. - -dnl Subroutines of libtool.m4, -dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision -dnl with libtool.m4. - -dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. -AC_DEFUN([AC_LIB_PROG_LD_GNU], -[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, -[# I'd rather use --version here, but apparently some GNU ld's only accept -v. -case `$LD -v 2>&1 conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by GCC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]* | [A-Za-z]:[\\/]*)] - [re_direlt='/[^/][^/]*/\.\./'] - # Canonicalize the path of ld - ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(acl_cv_path_LD, -[if test -z "$LD"; then - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" - for ac_dir in $PATH; do - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - acl_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in - *GNU* | *'with BFD'*) - test "$with_gnu_ld" != no && break ;; - *) - test "$with_gnu_ld" != yes && break ;; - esac - fi - done - IFS="$ac_save_ifs" -else - acl_cv_path_LD="$LD" # Let the user override the test with a path. -fi]) -LD="$acl_cv_path_LD" -if test -n "$LD"; then - AC_MSG_RESULT($LD) -else - AC_MSG_RESULT(no) -fi -test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) -AC_LIB_PROG_LD_GNU -]) diff --git a/BasiliskII/src/Unix/m4/gtk-2.0.m4 b/BasiliskII/src/Unix/m4/gtk-2.0.m4 deleted file mode 100644 index 3deba01b..00000000 --- a/BasiliskII/src/Unix/m4/gtk-2.0.m4 +++ /dev/null @@ -1,196 +0,0 @@ -# Configure paths for GTK+ -# Owen Taylor 1997-2001 - -dnl AM_PATH_GTK_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) -dnl Test for GTK+, and define GTK_CFLAGS and GTK_LIBS, if gthread is specified in MODULES, -dnl pass to pkg-config -dnl -AC_DEFUN([AM_PATH_GTK_2_0], -[dnl -dnl Get the cflags and libraries from pkg-config -dnl -AC_ARG_ENABLE(gtktest, [ --disable-gtktest do not try to compile and run a test GTK+ program], - , enable_gtktest=yes) - - pkg_config_args=gtk+-2.0 - for module in . $4 - do - case "$module" in - gthread) - pkg_config_args="$pkg_config_args gthread-2.0" - ;; - esac - done - - no_gtk="" - - AC_PATH_PROG(PKG_CONFIG, pkg-config, no) - - if test x$PKG_CONFIG != xno ; then - if pkg-config --atleast-pkgconfig-version 0.7 ; then - : - else - echo "*** pkg-config too old; version 0.7 or better required." - no_gtk=yes - PKG_CONFIG=no - fi - else - no_gtk=yes - fi - - min_gtk_version=ifelse([$1], ,2.0.0,$1) - AC_MSG_CHECKING(for GTK+ - version >= $min_gtk_version) - - if test x$PKG_CONFIG != xno ; then - ## don't try to run the test against uninstalled libtool libs - if $PKG_CONFIG --uninstalled $pkg_config_args; then - echo "Will use uninstalled version of GTK+ found in PKG_CONFIG_PATH" - enable_gtktest=no - fi - - if $PKG_CONFIG --atleast-version $min_gtk_version $pkg_config_args; then - : - else - no_gtk=yes - fi - fi - - if test x"$no_gtk" = x ; then - GTK_CFLAGS=`$PKG_CONFIG $pkg_config_args --cflags` - GTK_LIBS=`$PKG_CONFIG $pkg_config_args --libs` - gtk_config_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - gtk_config_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - gtk_config_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_gtktest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $GTK_CFLAGS" - LIBS="$GTK_LIBS $LIBS" -dnl -dnl Now check if the installed GTK+ is sufficiently new. (Also sanity -dnl checks the results of pkg-config to some extent) -dnl - rm -f conf.gtktest - AC_TRY_RUN([ -#include -#include -#include - -int -main () -{ - int major, minor, micro; - char *tmp_version; - - system ("touch conf.gtktest"); - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = g_strdup("$min_gtk_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_gtk_version"); - exit(1); - } - - if ((gtk_major_version != $gtk_config_major_version) || - (gtk_minor_version != $gtk_config_minor_version) || - (gtk_micro_version != $gtk_config_micro_version)) - { - printf("\n*** 'pkg-config --modversion gtk+-2.0' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", - $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, - gtk_major_version, gtk_minor_version, gtk_micro_version); - printf ("*** was found! If pkg-config was correct, then it is best\n"); - printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); - printf("*** to point to the correct configuration files\n"); - } - else if ((gtk_major_version != GTK_MAJOR_VERSION) || - (gtk_minor_version != GTK_MINOR_VERSION) || - (gtk_micro_version != GTK_MICRO_VERSION)) - { - printf("*** GTK+ header files (version %d.%d.%d) do not match\n", - GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); - printf("*** library (version %d.%d.%d)\n", - gtk_major_version, gtk_minor_version, gtk_micro_version); - } - else - { - if ((gtk_major_version > major) || - ((gtk_major_version == major) && (gtk_minor_version > minor)) || - ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", - gtk_major_version, gtk_minor_version, gtk_micro_version); - printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of GTK+, but you can also set the PKG_CONFIG environment to point to the\n"); - printf("*** correct copy of pkg-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} -],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - if test "x$no_gtk" = x ; then - AC_MSG_RESULT(yes (version $gtk_config_major_version.$gtk_config_minor_version.$gtk_config_micro_version)) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$PKG_CONFIG" = "no" ; then - echo "*** A new enough version of pkg-config was not found." - echo "*** See http://pkgconfig.sourceforge.net" - else - if test -f conf.gtktest ; then - : - else - echo "*** Could not run GTK+ test program, checking why..." - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $GTK_CFLAGS" - LIBS="$LIBS $GTK_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding GTK+ or finding the wrong" - echo "*** version of GTK+. If it is not finding GTK+, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means GTK+ is incorrectly installed."]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - GTK_CFLAGS="" - GTK_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) - rm -f conf.gtktest -]) diff --git a/BasiliskII/src/Unix/m4/gtk.m4 b/BasiliskII/src/Unix/m4/gtk.m4 deleted file mode 100644 index f2dd4721..00000000 --- a/BasiliskII/src/Unix/m4/gtk.m4 +++ /dev/null @@ -1,194 +0,0 @@ -# Configure paths for GTK+ -# Owen Taylor 97-11-3 - -dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) -dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS -dnl -AC_DEFUN([AM_PATH_GTK], -[dnl -dnl Get the cflags and libraries from the gtk-config script -dnl -AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)], - gtk_config_prefix="$withval", gtk_config_prefix="") -AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)], - gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="") -AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program], - , enable_gtktest=yes) - - for module in . $4 - do - case "$module" in - gthread) - gtk_config_args="$gtk_config_args gthread" - ;; - esac - done - - if test x$gtk_config_exec_prefix != x ; then - gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix" - if test x${GTK_CONFIG+set} != xset ; then - GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config - fi - fi - if test x$gtk_config_prefix != x ; then - gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix" - if test x${GTK_CONFIG+set} != xset ; then - GTK_CONFIG=$gtk_config_prefix/bin/gtk-config - fi - fi - - AC_PATH_PROG(GTK_CONFIG, gtk-config, no) - min_gtk_version=ifelse([$1], ,0.99.7,$1) - AC_MSG_CHECKING(for GTK - version >= $min_gtk_version) - no_gtk="" - if test "$GTK_CONFIG" = "no" ; then - no_gtk=yes - else - GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags` - GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs` - gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_gtktest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $GTK_CFLAGS" - LIBS="$GTK_LIBS $LIBS" -dnl -dnl Now check if the installed GTK is sufficiently new. (Also sanity -dnl checks the results of gtk-config to some extent -dnl - rm -f conf.gtktest - AC_TRY_RUN([ -#include -#include -#include - -int -main () -{ - int major, minor, micro; - char *tmp_version; - - system ("touch conf.gtktest"); - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = g_strdup("$min_gtk_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_gtk_version"); - exit(1); - } - - if ((gtk_major_version != $gtk_config_major_version) || - (gtk_minor_version != $gtk_config_minor_version) || - (gtk_micro_version != $gtk_config_micro_version)) - { - printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", - $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, - gtk_major_version, gtk_minor_version, gtk_micro_version); - printf ("*** was found! If gtk-config was correct, then it is best\n"); - printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n"); - printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n"); - printf("*** before re-running configure\n"); - } -#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION) - else if ((gtk_major_version != GTK_MAJOR_VERSION) || - (gtk_minor_version != GTK_MINOR_VERSION) || - (gtk_micro_version != GTK_MICRO_VERSION)) - { - printf("*** GTK+ header files (version %d.%d.%d) do not match\n", - GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); - printf("*** library (version %d.%d.%d)\n", - gtk_major_version, gtk_minor_version, gtk_micro_version); - } -#endif /* defined (GTK_MAJOR_VERSION) ... */ - else - { - if ((gtk_major_version > major) || - ((gtk_major_version == major) && (gtk_minor_version > minor)) || - ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", - gtk_major_version, gtk_minor_version, gtk_micro_version); - printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the gtk-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n"); - printf("*** correct copy of gtk-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} -],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - if test "x$no_gtk" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$GTK_CONFIG" = "no" ; then - echo "*** The gtk-config script installed by GTK could not be found" - echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the GTK_CONFIG environment variable to the" - echo "*** full path to gtk-config." - else - if test -f conf.gtktest ; then - : - else - echo "*** Could not run GTK test program, checking why..." - CFLAGS="$CFLAGS $GTK_CFLAGS" - LIBS="$LIBS $GTK_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding GTK or finding the wrong" - echo "*** version of GTK. If it is not finding GTK, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" - echo "***" - echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" - echo "*** came with the system with the command" - echo "***" - echo "*** rpm --erase --nodeps gtk gtk-devel" ], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means GTK was incorrectly installed" - echo "*** or that you have moved GTK since it was installed. In the latter case, you" - echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - GTK_CFLAGS="" - GTK_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) - rm -f conf.gtktest -]) diff --git a/BasiliskII/src/Unix/mkinstalldirs b/BasiliskII/src/Unix/mkinstalldirs deleted file mode 100755 index 8ab885ec..00000000 --- a/BasiliskII/src/Unix/mkinstalldirs +++ /dev/null @@ -1,99 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -errstatus=0 -dirmode="" - -usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." - -# process command line arguments -while test $# -gt 0 ; do - case "${1}" in - -h | --help | --h* ) # -h for help - echo "${usage}" 1>&2; exit 0 ;; - -m ) # -m PERM arg - shift - test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } - dirmode="${1}" - shift ;; - -- ) shift; break ;; # stop option processing - -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option - * ) break ;; # first non-opt arg - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in -0) exit 0 ;; -esac - -case $dirmode in -'') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi ;; -*) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi ;; -esac - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 3 -# End: -# mkinstalldirs ends here diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index 285b5e63..8dd77b1d 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -21,16 +21,448 @@ #ifndef SYSDEPS_H #define SYSDEPS_H -#ifndef __STDC__ -#error "Your compiler is not ANSI. Get a real one." + + + +#if 1 +//Too lazy to port the checks to cmake right now +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define if your system supports TUN/TAP devices. */ +/* #undef ENABLE_TUNTAP */ + +/* Define if using video enabled on SEGV signals. */ +#define ENABLE_VOSF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define if your system has header. */ +/* #undef HAVE_ASM_UCONTEXT */ + +/* Define to 1 if you have the `atanh' function. */ +#define HAVE_ATANH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_AVAILABILITYMACROS_H 1 + +/* Define to 1 if the system has the type `caddr_t'. */ +#define HAVE_CADDR_T 1 + +/* Define to 1 if you have the `cfmakeraw' function. */ +#define HAVE_CFMAKERAW 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `finite' function. */ +#define HAVE_FINITE 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FLOATINGPOINT_H */ + +/* Define if framework AppKit is available. */ +#define HAVE_FRAMEWORK_APPKIT 1 + +/* Define if framework Carbon is available. */ +#define HAVE_FRAMEWORK_CARBON 1 + +/* Define if framework CoreFoundation is available. */ +#define HAVE_FRAMEWORK_COREFOUNDATION 1 + +/* Define if framework IOKit is available. */ +#define HAVE_FRAMEWORK_IOKIT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_HISTORY_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IEEE754_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header + file. */ +#define HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDEVICE_H 1 + +/* Define to 1 if you have the `isinf' function. */ +#define HAVE_ISINF 1 + +/* Define to 1 if you have the `isnan' function. */ +#define HAVE_ISNAN 1 + +/* Define to 1 if you have the `isnormal' function. */ +/* #undef HAVE_ISNORMAL */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `posix4' library (-lposix4). */ +/* #undef HAVE_LIBPOSIX4 */ + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `PTL' library (-lPTL). */ +/* #undef HAVE_LIBPTL */ + +/* Define to 1 if you have the `rt' library (-lrt). */ +/* #undef HAVE_LIBRT */ + +/* Define if there is a linker script to relocate the executable above + 0x70000000. */ +/* #undef HAVE_LINKER_SCRIPT */ + +/* Define to 1 if the system has the type `loff_t'. */ +/* #undef HAVE_LOFF_T */ + +/* Define if your system supports Mach exceptions. */ +#define HAVE_MACH_EXCEPTIONS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MACH_MACH_H 1 + +/* Define to 1 if you have the `mach_task_self' function. */ +#define HAVE_MACH_TASK_SELF 1 + +/* Define if your system has a working vm_allocate()-based memory allocator. + */ +#define HAVE_MACH_VM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define if defines MAP_ANON and mmap()'ing with MAP_ANON works. + */ +/* #undef HAVE_MMAP_ANON */ + +/* Define if defines MAP_ANONYMOUS and mmap()'ing with + MAP_ANONYMOUS works. */ +/* #undef HAVE_MMAP_ANONYMOUS */ + +/* Define if your system has a working mmap()-based memory allocator. */ +/* #undef HAVE_MMAP_VM */ + +/* Define to 1 if you have the `mprotect' function. */ +#define HAVE_MPROTECT 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NAN_H */ + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define if pthreads are available. */ +#define HAVE_PTHREADS 1 + +/* Define to 1 if you have the `pthread_cancel' function. */ +#define HAVE_PTHREAD_CANCEL 1 + +/* Define to 1 if you have the `pthread_cond_init' function. */ +#define HAVE_PTHREAD_COND_INIT 1 + +/* Define to 1 if you have the `pthread_mutexattr_setprotocol' function. */ +#define HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL 1 + +/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */ +#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1 + +/* Define to 1 if you have the `pthread_mutexattr_settype' function. */ +#define HAVE_PTHREAD_MUTEXATTR_SETTYPE 1 + +/* Define to 1 if you have the `pthread_testcancel' function. */ +#define HAVE_PTHREAD_TESTCANCEL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_READLINE_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_READLINE_HISTORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_READLINE_READLINE_H 1 + +/* Define to 1 if you have the `sem_init' function. */ +#define HAVE_SEM_INIT 1 + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define if we know a hack to replace siginfo_t->si_addr member. */ +/* #undef HAVE_SIGCONTEXT_SUBTERFUGE */ + +/* Define if your system supports extended signals. */ +/* #undef HAVE_SIGINFO_T */ + +/* Define to 1 if you have the `signal' function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the `signbit' function. */ +/* #undef HAVE_SIGNBIT */ + +/* Define if we can ignore the fault (instruction skipping in SIGSEGV + handler). */ +#define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BITYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STROPTS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the `task_self' function. */ +/* #undef HAVE_TASK_SELF */ + +/* Define to 1 if you have the `timer_create' function. */ +/* #undef HAVE_TIMER_CREATE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vm_allocate' function. */ +#define HAVE_VM_ALLOCATE 1 + +/* Define to 1 if you have the `vm_deallocate' function. */ +#define HAVE_VM_DEALLOCATE 1 + +/* Define to 1 if you have the `vm_protect' function. */ +#define HAVE_VM_PROTECT 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Define this program name. */ +#define PACKAGE "Basilisk II" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "Christian.Bauer@uni-mainz.de" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Basilisk II" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Basilisk II 1.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "BasiliskII" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.0" + +/* Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this + system. */ +/* #undef PAGEZERO_HACK */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define if your system requires sigactions to be reinstalled. */ +/* #undef SIGACTION_NEED_REINSTALL */ + +/* Define if your system requires signals to be reinstalled. */ +/* #undef SIGNAL_NEED_REINSTALL */ + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `float', as computed by sizeof. */ +#define SIZEOF_FLOAT 4 + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define if BSD-style non-blocking I/O is to be used */ +/* #undef USE_FIONBIO */ + +/* Define to enble SDL support */ +#define USE_SDL 1 + +/* Define to enable SDL audio support */ +#define USE_SDL_AUDIO 1 + +/* Define to enable SDL video graphics support */ +#define USE_SDL_VIDEO 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 #endif + +/* Define this program version. */ +#define VERSION "1.0" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to 'int' if doesn't define. */ +/* #undef socklen_t */ +#else #include "config.h" -#include "user_strings_unix.h" - -#ifndef STDC_HEADERS -#error "You don't have ANSI C header files." #endif +//Checks end +#ifndef NEED_CONFIG_H_ONLY + +#include "user_strings_unix.h" #ifdef HAVE_UNISTD_H # include @@ -42,6 +474,7 @@ #include #include #include +#include #ifdef HAVE_PTHREADS # include @@ -96,54 +529,21 @@ /* Data types */ -typedef unsigned char uint8; -typedef signed char int8; -#if SIZEOF_SHORT == 2 -typedef unsigned short uint16; -typedef short int16; -#elif SIZEOF_INT == 2 -typedef unsigned int uint16; -typedef int int16; -#else -#error "No 2 byte type, you lose." -#endif -#if SIZEOF_INT == 4 -typedef unsigned int uint32; -typedef int int32; -#elif SIZEOF_LONG == 4 -typedef unsigned long uint32; -typedef long int32; -#else -#error "No 4 byte type, you lose." -#endif -#if SIZEOF_LONG == 8 +typedef uint8_t uint8; +typedef int8_t int8; +typedef uint16_t uint16; +typedef int16_t int16; +typedef uint32_t uint32; +typedef int32_t int32; +typedef uint64_t uint64; +typedef int64_t int64; #ifndef _UINT64 -typedef unsigned long uint64; #define _UINT64 #endif -typedef long int64; -#define VAL64(a) (a ## l) -#define UVAL64(a) (a ## ul) -#elif SIZEOF_LONG_LONG == 8 -#ifndef _UINT64 -typedef unsigned long long uint64; -#define _UINT64 -#endif -typedef long long int64; #define VAL64(a) (a ## LL) #define UVAL64(a) (a ## uLL) -#else -#error "No 8 byte type, you lose." -#endif -#if SIZEOF_VOID_P == 4 -typedef uint32 uintptr; -typedef int32 intptr; -#elif SIZEOF_VOID_P == 8 -typedef uint64 uintptr; -typedef int64 intptr; -#else -#error "Unsupported size of pointer" -#endif +typedef uintptr_t uintptr; +typedef intptr_t intptr; #ifndef HAVE_LOFF_T typedef off_t loff_t; @@ -231,44 +631,6 @@ void Set_pthread_attr(pthread_attr_t *attr, int priority); #endif /* UAE CPU defines */ -#ifdef WORDS_BIGENDIAN - -#ifdef CPU_CAN_ACCESS_UNALIGNED - -/* Big-endian CPUs which can do unaligned accesses */ -static inline uae_u32 do_get_mem_long(uae_u32 *a) {return *a;} -static inline uae_u32 do_get_mem_word(uae_u16 *a) {return *a;} -static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {*a = v;} -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {*a = v;} - -#else /* CPU_CAN_ACCESS_UNALIGNED */ - -#ifdef sgi -/* The SGI MIPSPro compilers can do unaligned accesses given enough hints. - * They will automatically inline these routines. */ -#ifdef __cplusplus -extern "C" { /* only the C compiler does unaligned accesses */ -#endif -extern uae_u32 do_get_mem_long(uae_u32 *a); -extern uae_u32 do_get_mem_word(uae_u16 *a); -extern void do_put_mem_long(uae_u32 *a, uae_u32 v); -extern void do_put_mem_word(uae_u16 *a, uae_u32 v); -#ifdef __cplusplus -} -#endif - -#else /* sgi */ - -/* Big-endian CPUs which can not do unaligned accesses (this is not the most efficient way to do this...) */ -static inline uae_u32 do_get_mem_long(uae_u32 *a) {uint8 *b = (uint8 *)a; return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];} -static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint8 *b = (uint8 *)a; return (b[0] << 8) | b[1];} -static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {uint8 *b = (uint8 *)a; b[0] = v >> 24; b[1] = v >> 16; b[2] = v >> 8; b[3] = v;} -static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {uint8 *b = (uint8 *)a; b[0] = v >> 8; b[1] = v;} -#endif /* sgi */ - -#endif /* CPU_CAN_ACCESS_UNALIGNED */ - -#else /* WORDS_BIGENDIAN */ #if defined(__i386__) || defined(__x86_64__) @@ -316,8 +678,6 @@ static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {uint8 *b = (uint8 *)a #endif /* CPU_CAN_ACCESS_UNALIGNED */ -#endif /* WORDS_BIGENDIAN */ - #ifndef HAVE_OPTIMIZED_BYTESWAP_32 static inline uae_u32 do_byteswap_32(uae_u32 v) { return (((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v & 0xff) << 24) | ((v & 0xff00) << 8)); } @@ -352,4 +712,6 @@ static inline uae_u32 do_byteswap_16(uae_u32 v) #endif #define REGPARAM2 +#endif /* NEED_CONFIG_H_ONLY */ + #endif diff --git a/BasiliskII/src/Unix/tunconfig b/BasiliskII/src/Unix/tunconfig deleted file mode 100755 index c2ec8fb3..00000000 --- a/BasiliskII/src/Unix/tunconfig +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -########################################################################### -# Configuration of the tunN devices for usage with Basilisk II. -# (derived MOL tunconfig script) -# -# This script should be named /usr/share/BasiliskII/tunconfig (unless -# the default name has been changed with the 'etherconfig' keyword). -# -# Usage: tunconfig iface up|down -# -# If the linux box is configured as a firewall, the rules below might -# need some adjustments. -# -# The IP Tunnel driver requires IP forwarding to be enabled. Run as root: -# -# echo 1 >/proc/sys/net/ipv4/ip_forward -# -########################################################################### - -SUDO=/usr/bin/sudo -IFCONFIG=/sbin/ifconfig -IPTABLES=/sbin/iptables - -######################################################### - -[[ "x$1" = "x-n" ]] && { - DONT_EXECUTE=yes - shift 1 -} - -TUN_DEV=$1 -ACTION=$2 - -TUN_NUM=`echo $TUN_DEV | sed s/[^0-9]//g` -NET_NUM=`expr 40 + $TUN_NUM` -TUN_NET=172.20.$NET_NUM.0/24 -TUN_HOST=172.20.$NET_NUM.1 - -######################################################### -# Misc Checks -######################################################### - -[[ $# = 2 ]] || { - echo "Usage: tunconfig [-n] iface up|down" - exit 2 -} - -[[ "`id -u`" = "0" ]] && { - echo "---> $SUDO not necessary." 1>&2 - SUDO="" -} - -[[ -x $IPTABLES ]] || { - echo "---> $IPTABLES not found." 1>&2 - exit 1 -} - -if [ -n "$SUDO" ]; then - $SUDO -l | grep -q "NOPASSWD: $IFCONFIG" || { - echo "---> Missing sudo NOPASSWD: $IFCONFIG." 1>&2 - exit 1 - } - $SUDO -l | grep -q "NOPASSWD: $IPTABLES" || { - echo "---> Missing sudo NOPASSWD: $IPTABLES." 1>&2 - exit 1 - } - IFCONFIG="$SUDO $IFCONFIG" - IPTABLES="$SUDO $IPTABLES" -fi - -[[ "x$DONT_EXECUTE" = "xyes" ]] && exit 0 - -$IPTABLES -L -n -t nat > /dev/null || exit 1 - -######################################################### -# Remove old (possibly stale) ruleset -######################################################### - -{ - $IPTABLES -t nat -D POSTROUTING -s $TUN_NET -d ! $TUN_NET -j MASQUERADE -} >& /dev/null - -######################################################### -# Bring down interface -######################################################### - -[[ "$ACTION" = down ]] && { - $IFCONFIG $TUN_DEV down -} - -######################################################### -# Configure interface -######################################################### - -[[ "$ACTION" = up ]] && { - $IFCONFIG $TUN_DEV $TUN_HOST - - # masquerade the tun network - $IPTABLES -t nat -A POSTROUTING -s $TUN_NET -d ! $TUN_NET -j MASQUERADE -} - -exit 0 diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h index c0a64192..5f708048 100644 --- a/BasiliskII/src/uae_cpu/fpu/types.h +++ b/BasiliskII/src/uae_cpu/fpu/types.h @@ -41,22 +41,10 @@ #if defined(FPU_UAE) /* 4-byte floats */ -#if SIZEOF_FLOAT == 4 typedef float uae_f32; -#elif SIZEOF_DOUBLE == 4 -typedef double uae_f32; -#else -#error "No 4 byte float type, you lose." -#endif /* 8-byte floats */ -#if SIZEOF_DOUBLE == 8 typedef double uae_f64; -#elif SIZEOF_LONG_DOUBLE == 8 -typedef long double uae_f64; -#else -#error "No 8 byte float type, you lose." -#endif /* Original UAE FPU registers are only 8 bytes long */ typedef uae_f64 fpu_register; @@ -71,22 +59,10 @@ typedef uae_f32 fpu_single; #elif defined(FPU_X86) /* 4-byte floats */ -#if SIZEOF_FLOAT == 4 typedef float uae_f32; -#elif SIZEOF_DOUBLE == 4 -typedef double uae_f32; -#else -#error "No 4 byte float type, you lose." -#endif /* 8-byte floats */ -#if SIZEOF_DOUBLE == 8 -typedef float uae_f64; -#elif SIZEOF_LONG_DOUBLE == 8 typedef double uae_f64; -#else -#error "No 8 byte float type, you lose." -#endif /* At least 10-byte floats are required */ #if SIZEOF_LONG_DOUBLE >= 10 From 023251dee1fcd948b1d78640474cc9d74f03ae45 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 15 Apr 2018 16:00:38 -0500 Subject: [PATCH 03/20] Get rid of cxmon and SheepShaver (focus is on BasiliskII) --- SheepShaver/COPYING | 340 - SheepShaver/Makefile | 104 - SheepShaver/NEWS | 105 - SheepShaver/doc/BeOS/acknowledgements.html | 24 - SheepShaver/doc/BeOS/contact.html | 47 - SheepShaver/doc/BeOS/graphics.gif | Bin 8854 -> 0 bytes SheepShaver/doc/BeOS/history.html | 59 - SheepShaver/doc/BeOS/icon.gif | Bin 2011 -> 0 bytes SheepShaver/doc/BeOS/iconsmall.gif | Bin 1297 -> 0 bytes SheepShaver/doc/BeOS/index.html | 28 - SheepShaver/doc/BeOS/installation.html | 25 - SheepShaver/doc/BeOS/introduction.html | 45 - SheepShaver/doc/BeOS/memory.gif | Bin 5510 -> 0 bytes SheepShaver/doc/BeOS/quickstart.html | 38 - SheepShaver/doc/BeOS/serial.gif | Bin 4844 -> 0 bytes SheepShaver/doc/BeOS/settings.html | 127 - SheepShaver/doc/BeOS/troubleshooting.html | 79 - SheepShaver/doc/BeOS/using.html | 76 - SheepShaver/doc/BeOS/volumes.gif | Bin 7456 -> 0 bytes SheepShaver/doc/Linux/acknowledgements.html | 24 - SheepShaver/doc/Linux/contact.html | 47 - SheepShaver/doc/Linux/graphics.gif | Bin 5480 -> 0 bytes SheepShaver/doc/Linux/history.html | 25 - SheepShaver/doc/Linux/icon.gif | Bin 2011 -> 0 bytes SheepShaver/doc/Linux/iconsmall.gif | Bin 1297 -> 0 bytes SheepShaver/doc/Linux/index.html | 28 - SheepShaver/doc/Linux/installation.html | 25 - SheepShaver/doc/Linux/introduction.html | 44 - SheepShaver/doc/Linux/memory.gif | Bin 5697 -> 0 bytes SheepShaver/doc/Linux/quickstart.html | 39 - SheepShaver/doc/Linux/serial.gif | Bin 5325 -> 0 bytes SheepShaver/doc/Linux/settings.html | 117 - SheepShaver/doc/Linux/troubleshooting.html | 65 - SheepShaver/doc/Linux/using.html | 113 - SheepShaver/doc/Linux/volumes.gif | Bin 7705 -> 0 bytes SheepShaver/doc/PowerPC-Testsuite.txt | 28 - .../src/BeOS/CreatePCIDrivers/Ethernet.cpp | 256 - .../src/BeOS/CreatePCIDrivers/Makefile | 25 - .../src/BeOS/CreatePCIDrivers/Video.cpp | 78 - .../src/BeOS/CreatePCIDrivers/hexconv.cpp | 34 - SheepShaver/src/BeOS/Makefile | 117 - SheepShaver/src/BeOS/NetPeek/Makefile | 110 - SheepShaver/src/BeOS/NetPeek/NetPeek.cpp | 49 - SheepShaver/src/BeOS/SaveROM/Makefile | 110 - SheepShaver/src/BeOS/SaveROM/README | 8 - SheepShaver/src/BeOS/SaveROM/SaveROM.cpp | 128 - SheepShaver/src/BeOS/SaveROM/SaveROM.rsrc | Bin 4323 -> 0 bytes SheepShaver/src/BeOS/SheepDriver | 1 - SheepShaver/src/BeOS/SheepNet | 1 - SheepShaver/src/BeOS/SheepShaver.rsrc | Bin 4247 -> 0 bytes SheepShaver/src/BeOS/about_window_beos.cpp | 289 - SheepShaver/src/BeOS/audio_beos.cpp | 1 - SheepShaver/src/BeOS/clip_beos.cpp | 374 -- SheepShaver/src/BeOS/ether_beos.cpp | 400 -- SheepShaver/src/BeOS/extfs_beos.cpp | 1 - SheepShaver/src/BeOS/main_beos.cpp | 2015 ------ SheepShaver/src/BeOS/prefs_beos.cpp | 112 - SheepShaver/src/BeOS/prefs_editor_beos.cpp | 877 --- SheepShaver/src/BeOS/scsi_beos.cpp | 1 - SheepShaver/src/BeOS/serial_beos.cpp | 1 - SheepShaver/src/BeOS/sys_beos.cpp | 1 - SheepShaver/src/BeOS/sysdeps.h | 74 - SheepShaver/src/BeOS/timer_beos.cpp | 1 - SheepShaver/src/BeOS/user_strings_beos.cpp | 73 - SheepShaver/src/BeOS/user_strings_beos.h | 37 - SheepShaver/src/BeOS/video_beos.cpp | 787 --- SheepShaver/src/BeOS/video_screen.h | 262 - SheepShaver/src/BeOS/video_window.h | 523 -- SheepShaver/src/BeOS/xpram_beos.cpp | 1 - SheepShaver/src/CrossPlatform/sigsegv.cpp | 1 - SheepShaver/src/CrossPlatform/sigsegv.h | 1 - SheepShaver/src/CrossPlatform/video_blit.cpp | 1 - SheepShaver/src/CrossPlatform/video_blit.h | 1 - SheepShaver/src/CrossPlatform/video_vosf.h | 1 - SheepShaver/src/CrossPlatform/vm_alloc.cpp | 1 - SheepShaver/src/CrossPlatform/vm_alloc.h | 1 - .../src/EthernetDriver/.finf/Ethernet.mcp | Bin 32 -> 0 bytes .../src/EthernetDriver/.finf/ethernet.ndrv | Bin 32 -> 0 bytes .../src/EthernetDriver/.rsrc/ethernet.ndrv | Bin 398 -> 0 bytes .../Ethernet Data/.finf/CWSettingsMacOS.stg | Bin 32 -> 0 bytes .../.finf/PPC Debug MacOS Toolbox | Bin 32 -> 0 bytes .../.finf/PPC Final MacOS Toolbox | Bin 32 -> 0 bytes .../Ethernet Data/CWSettingsMacOS.stg | Bin 4344 -> 0 bytes .../.finf/TargetDataMacOS.tdt | Bin 32 -> 0 bytes .../.rsrc/TargetDataMacOS.tdt | Bin 286 -> 0 bytes .../TargetDataMacOS.tdt | Bin 46180 -> 0 bytes .../.finf/TargetDataMacOS.tdt | Bin 32 -> 0 bytes .../.rsrc/TargetDataMacOS.tdt | Bin 286 -> 0 bytes .../TargetDataMacOS.tdt | Bin 46304 -> 0 bytes SheepShaver/src/EthernetDriver/Ethernet.cpp | 308 - SheepShaver/src/EthernetDriver/Ethernet.mcp | Bin 103293 -> 0 bytes .../src/EthernetDriver/cpu_emulation.h | 1 - SheepShaver/src/EthernetDriver/debug.h | 1 - SheepShaver/src/EthernetDriver/ether.cpp | 1738 ------ SheepShaver/src/EthernetDriver/ether.h | 113 - SheepShaver/src/EthernetDriver/ether_defs.h | 552 -- SheepShaver/src/EthernetDriver/ethernet.ndrv | Bin 11780 -> 0 bytes SheepShaver/src/EthernetDriver/macos_util.cpp | 1 - SheepShaver/src/EthernetDriver/macos_util.h | 1 - SheepShaver/src/EthernetDriver/sysdeps.h | 1 - SheepShaver/src/EthernetDriver/xlowmem.h | 64 - SheepShaver/src/EthernetDriverFull.i | 737 --- SheepShaver/src/EthernetDriverStub.i | 43 - SheepShaver/src/MacOSX/.gitignore | 7 - SheepShaver/src/MacOSX/AudioBackEnd.cpp | 1 - SheepShaver/src/MacOSX/AudioBackEnd.h | 1 - SheepShaver/src/MacOSX/AudioDevice.cpp | 1 - SheepShaver/src/MacOSX/AudioDevice.h | 1 - SheepShaver/src/MacOSX/Info.plist.in | 56 - .../src/MacOSX/Launcher/AppController.h | 30 - .../src/MacOSX/Launcher/AppController.mm | 44 - SheepShaver/src/MacOSX/Launcher/DiskType.h | 23 - SheepShaver/src/MacOSX/Launcher/DiskType.m | 35 - .../Launcher/English.lproj/InfoPlist.strings | Bin 276 -> 0 bytes .../English.lproj/MainMenu.nib/classes.nib | 32 - .../English.lproj/MainMenu.nib/info.nib | 18 - .../MainMenu.nib/keyedobjects.nib | Bin 12048 -> 0 bytes .../VMListWindow.nib/designable.nib | 713 --- .../VMListWindow.nib/keyedobjects.nib | Bin 8475 -> 0 bytes .../VMSettingsWindow.nib/designable.nib | 4438 ------------- .../VMSettingsWindow.nib/keyedobjects.nib | Bin 43067 -> 0 bytes SheepShaver/src/MacOSX/Launcher/Info.plist | 28 - .../src/MacOSX/Launcher/LauncherPrefix.h | 42 - .../project.pbxproj | 399 -- .../src/MacOSX/Launcher/VMListController.h | 49 - .../src/MacOSX/Launcher/VMListController.mm | 390 -- .../MacOSX/Launcher/VMSettingsController.h | 87 - .../MacOSX/Launcher/VMSettingsController.mm | 480 -- SheepShaver/src/MacOSX/Launcher/main.m | 26 - SheepShaver/src/MacOSX/MacOSX_sound_if.cpp | 1 - SheepShaver/src/MacOSX/MacOSX_sound_if.h | 1 - .../English.lproj/InfoPlist.strings | Bin 216 -> 0 bytes .../English.lproj/MainMenu.nib/classes.nib | 50 - .../English.lproj/MainMenu.nib/info.nib | 23 - .../MainMenu.nib/keyedobjects.nib | Bin 39269 -> 0 bytes SheepShaver/src/MacOSX/PrefsEditor/Info.plist | 28 - .../src/MacOSX/PrefsEditor/PrefsEditor.h | 70 - .../src/MacOSX/PrefsEditor/PrefsEditor.mm | 347 -- .../project.pbxproj | 309 - SheepShaver/src/MacOSX/PrefsEditor/main.m | 26 - .../English.lproj/InfoPlist.strings | Bin 90 -> 0 bytes .../English.lproj/MainMenu.nib/classes.nib | 103 - .../English.lproj/MainMenu.nib/info.nib | 16 - .../MainMenu.nib/keyedobjects.nib | Bin 31674 -> 0 bytes SheepShaver/src/MacOSX/SheepShaver.icns | Bin 59840 -> 0 bytes .../SheepShaver.xcodeproj/project.pbxproj | 2445 -------- SheepShaver/src/MacOSX/XcodeBuildHowTo.txt | 26 - SheepShaver/src/MacOSX/audio_macosx.cpp | 1 - SheepShaver/src/MacOSX/autorelease.h | 1 - SheepShaver/src/MacOSX/clip_macosx.cpp | 1 - SheepShaver/src/MacOSX/clip_macosx64.mm | 1 - .../src/MacOSX/config/config-macosx-ppc_32.h | 513 -- .../src/MacOSX/config/config-macosx-x86_32.h | 527 -- .../src/MacOSX/config/config-macosx-x86_64.h | 527 -- SheepShaver/src/MacOSX/config/config.h | 9 - SheepShaver/src/MacOSX/extfs_macosx.cpp | 1 - SheepShaver/src/MacOSX/macos_util_macosx.h | 1 - SheepShaver/src/MacOSX/prefs_macosx.mm | 131 - SheepShaver/src/MacOSX/sys_darwin.cpp | 1 - SheepShaver/src/MacOSX/utils_macosx.h | 1 - SheepShaver/src/MacOSX/utils_macosx.mm | 1 - SheepShaver/src/SDL | 1 - SheepShaver/src/Unix/.gitignore | 25 - SheepShaver/src/Unix/Darwin/.gitignore | 3 - SheepShaver/src/Unix/Darwin/lowmem.c | 1 - SheepShaver/src/Unix/Darwin/mkstandalone | 1 - SheepShaver/src/Unix/Darwin/pagezero.c | 1 - SheepShaver/src/Unix/Darwin/testlmem.sh | 1 - SheepShaver/src/Unix/Irix/audio_irix.cpp | 1 - SheepShaver/src/Unix/Linux/NetDriver | 1 - SheepShaver/src/Unix/Linux/scsi_linux.cpp | 1 - SheepShaver/src/Unix/Linux/sheepthreads.c | 445 -- SheepShaver/src/Unix/Makefile.in | 260 - SheepShaver/src/Unix/NetBSD/sheepthreads.c | 462 -- SheepShaver/src/Unix/SheepShaver.1 | 29 - SheepShaver/src/Unix/about_window_unix.cpp | 30 - SheepShaver/src/Unix/audio_oss_esd.cpp | 1 - SheepShaver/src/Unix/autogen.sh | 61 - SheepShaver/src/Unix/bincue_unix.cpp | 1 - SheepShaver/src/Unix/bincue_unix.h | 1 - SheepShaver/src/Unix/clip_unix.cpp | 1 - SheepShaver/src/Unix/config.guess | 1 - SheepShaver/src/Unix/config.sub | 1 - SheepShaver/src/Unix/configure.ac | 1687 ----- SheepShaver/src/Unix/cpr.sh | 1 - SheepShaver/src/Unix/disk_sparsebundle.cpp | 1 - SheepShaver/src/Unix/disk_unix.h | 1 - SheepShaver/src/Unix/ether_unix.cpp | 1 - SheepShaver/src/Unix/extfs_unix.cpp | 1 - SheepShaver/src/Unix/install-sh | 238 - SheepShaver/src/Unix/keycodes | 1 - SheepShaver/src/Unix/ldscripts | 1 - SheepShaver/src/Unix/m4 | 1 - SheepShaver/src/Unix/main_unix.cpp | 2292 ------- SheepShaver/src/Unix/mkinstalldirs | 40 - SheepShaver/src/Unix/paranoia.cpp | 346 -- SheepShaver/src/Unix/posix_sem.cpp | 1 - SheepShaver/src/Unix/ppc_asm.S | 932 --- SheepShaver/src/Unix/ppc_asm.tmpl | 156 - SheepShaver/src/Unix/prefs_editor_gtk.cpp | 1594 ----- SheepShaver/src/Unix/prefs_unix.cpp | 140 - SheepShaver/src/Unix/rpc.h | 1 - SheepShaver/src/Unix/rpc_unix.cpp | 1 - SheepShaver/src/Unix/semaphore.h | 1 - SheepShaver/src/Unix/serial_unix.cpp | 1 - SheepShaver/src/Unix/sigregs.h | 128 - SheepShaver/src/Unix/sshpty.c | 1 - SheepShaver/src/Unix/sshpty.h | 1 - SheepShaver/src/Unix/strlcpy.c | 1 - SheepShaver/src/Unix/strlcpy.h | 1 - SheepShaver/src/Unix/sys_unix.cpp | 1 - SheepShaver/src/Unix/sysdeps.h | 491 -- SheepShaver/src/Unix/timer_unix.cpp | 1 - SheepShaver/src/Unix/tinyxml2.cpp | 1 - SheepShaver/src/Unix/tinyxml2.h | 1 - SheepShaver/src/Unix/tunconfig | 1 - SheepShaver/src/Unix/user_strings_unix.cpp | 117 - SheepShaver/src/Unix/user_strings_unix.h | 86 - SheepShaver/src/Unix/vhd_unix.cpp | 1 - SheepShaver/src/Unix/video_x.cpp | 2584 -------- SheepShaver/src/Unix/xpram_unix.cpp | 1 - SheepShaver/src/VideoDriverStub.i | 24 - SheepShaver/src/Windows/Makefile.in | 221 - SheepShaver/src/Windows/SheepShaver.ico | Bin 2238 -> 0 bytes SheepShaver/src/Windows/SheepShaver.rc | 1 - SheepShaver/src/Windows/SheepShaverGUI.ico | Bin 1078 -> 0 bytes SheepShaver/src/Windows/SheepShaverGUI.rc | 2 - .../src/Windows/about_window_windows.cpp | 30 - SheepShaver/src/Windows/b2ether | 1 - SheepShaver/src/Windows/cd_defs.h | 1 - SheepShaver/src/Windows/cdenable | 1 - SheepShaver/src/Windows/clip_windows.cpp | 1 - SheepShaver/src/Windows/configure.ac | 266 - SheepShaver/src/Windows/ether_windows.cpp | 1 - SheepShaver/src/Windows/ether_windows.h | 1 - SheepShaver/src/Windows/extfs_windows.cpp | 1 - SheepShaver/src/Windows/kernel_windows.cpp | 1 - SheepShaver/src/Windows/kernel_windows.h | 1 - SheepShaver/src/Windows/main_windows.cpp | 828 --- SheepShaver/src/Windows/posix_emu.cpp | 1 - SheepShaver/src/Windows/posix_emu.h | 1 - SheepShaver/src/Windows/prefs_editor_gtk.cpp | 1 - SheepShaver/src/Windows/prefs_windows.cpp | 146 - SheepShaver/src/Windows/router | 1 - SheepShaver/src/Windows/serial_windows.cpp | 1 - SheepShaver/src/Windows/sys_windows.cpp | 1 - SheepShaver/src/Windows/sysdeps.h | 400 -- SheepShaver/src/Windows/timer_windows.cpp | 1 - .../src/Windows/user_strings_windows.cpp | 166 - .../src/Windows/user_strings_windows.h | 72 - SheepShaver/src/Windows/util_windows.cpp | 1 - SheepShaver/src/Windows/util_windows.h | 1 - SheepShaver/src/Windows/xpram_windows.cpp | 1 - SheepShaver/src/adb.cpp | 1 - SheepShaver/src/audio.cpp | 1 - SheepShaver/src/cdrom.cpp | 1 - SheepShaver/src/disk.cpp | 1 - SheepShaver/src/dummy/audio_dummy.cpp | 1 - SheepShaver/src/dummy/clip_dummy.cpp | 1 - SheepShaver/src/dummy/ether_dummy.cpp | 92 - SheepShaver/src/dummy/prefs_dummy.cpp | 38 - SheepShaver/src/dummy/prefs_editor_dummy.cpp | 1 - SheepShaver/src/dummy/scsi_dummy.cpp | 1 - SheepShaver/src/dummy/serial_dummy.cpp | 1 - SheepShaver/src/emul_op.cpp | 496 -- SheepShaver/src/emul_ppc/emul_ppc.cpp | 1661 ----- SheepShaver/src/ether.cpp | 1738 ------ SheepShaver/src/extfs.cpp | 1 - SheepShaver/src/gfxaccel.cpp | 461 -- SheepShaver/src/include/about_window.h | 26 - SheepShaver/src/include/adb.h | 1 - SheepShaver/src/include/audio.h | 1 - SheepShaver/src/include/audio_defs.h | 1 - SheepShaver/src/include/cdrom.h | 1 - SheepShaver/src/include/clip.h | 1 - SheepShaver/src/include/cpu_emulation.h | 123 - SheepShaver/src/include/debug.h | 1 - SheepShaver/src/include/disk.h | 1 - SheepShaver/src/include/emul_op.h | 113 - SheepShaver/src/include/ether.h | 101 - SheepShaver/src/include/ether_defs.h | 563 -- SheepShaver/src/include/extfs.h | 1 - SheepShaver/src/include/extfs_defs.h | 1 - SheepShaver/src/include/macos_util.h | 376 -- SheepShaver/src/include/main.h | 80 - SheepShaver/src/include/name_registry.h | 27 - SheepShaver/src/include/pict.h | 1 - SheepShaver/src/include/prefs.h | 1 - SheepShaver/src/include/prefs_editor.h | 30 - SheepShaver/src/include/rom_patches.h | 42 - SheepShaver/src/include/rsrc_patches.h | 28 - SheepShaver/src/include/scsi.h | 1 - SheepShaver/src/include/serial.h | 1 - SheepShaver/src/include/serial_defs.h | 1 - SheepShaver/src/include/sony.h | 1 - SheepShaver/src/include/sys.h | 1 - SheepShaver/src/include/thunks.h | 222 - SheepShaver/src/include/timer.h | 1 - SheepShaver/src/include/user_strings.h | 194 - SheepShaver/src/include/version.h | 27 - SheepShaver/src/include/video.h | 162 - SheepShaver/src/include/video_defs.h | 413 -- SheepShaver/src/include/xlowmem.h | 66 - SheepShaver/src/include/xpram.h | 1 - SheepShaver/src/kpx_cpu/dis-asm.h | 483 -- SheepShaver/src/kpx_cpu/include/a.out-defs.h | 443 -- .../src/kpx_cpu/include/basic-blockinfo.hpp | 118 - SheepShaver/src/kpx_cpu/include/basic-cpu.hpp | 89 - .../src/kpx_cpu/include/basic-plugin.hpp | 29 - .../src/kpx_cpu/include/block-alloc.hpp | 126 - SheepShaver/src/kpx_cpu/include/elf-defs.h | 2360 ------- SheepShaver/src/kpx_cpu/include/nvmemfun.hpp | 167 - .../src/kpx_cpu/include/task-plugin.hpp | 53 - SheepShaver/src/kpx_cpu/ppc-dis.c | 5489 ----------------- SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp | 1235 ---- .../src/kpx_cpu/src/cpu/block-cache.hpp | 277 - .../src/cpu/jit/amd64/dyngen-target-exec.h | 94 - .../src/cpu/jit/amd64/jit-target-cache.hpp | 1 - .../src/cpu/jit/amd64/jit-target-codegen.hpp | 108 - .../kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp | 481 -- .../src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp | 183 - .../src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp | 374 -- .../src/kpx_cpu/src/cpu/jit/cxxdemangle.cpp | 4495 -------------- .../src/kpx_cpu/src/cpu/jit/cxxdemangle.h | 55 - .../src/cpu/jit/dummy/jit-target-cache.hpp | 28 - .../src/kpx_cpu/src/cpu/jit/dyngen-exec.h | 182 - SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c | 3027 --------- .../src/kpx_cpu/src/cpu/jit/jit-cache.cpp | 149 - .../src/kpx_cpu/src/cpu/jit/jit-cache.hpp | 126 - .../src/kpx_cpu/src/cpu/jit/jit-codegen.hpp | 39 - .../src/kpx_cpu/src/cpu/jit/jit-config.hpp | 62 - .../kpx_cpu/src/cpu/jit/jit-target-dispatch.h | 70 - .../src/cpu/jit/mips/dyngen-target-exec.h | 45 - .../src/cpu/jit/mips/jit-target-cache.hpp | 34 - .../src/cpu/jit/ppc/dyngen-target-exec.h | 71 - .../src/cpu/jit/ppc/jit-target-cache.hpp | 44 - .../src/kpx_cpu/src/cpu/jit/x86/codegen_x86.h | 1 - .../src/cpu/jit/x86/dyngen-target-exec.h | 55 - .../src/cpu/jit/x86/jit-target-cache.hpp | 1 - .../src/cpu/jit/x86/jit-target-codegen.hpp | 760 --- .../src/kpx_cpu/src/cpu/ppc/genexec.pl | 52 - .../src/kpx_cpu/src/cpu/ppc/ppc-bitfields.hpp | 229 - .../src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp | 84 - .../src/kpx_cpu/src/cpu/ppc/ppc-config.hpp | 150 - .../src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp | 825 --- .../src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp | 514 -- .../src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp | 1869 ------ .../kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp | 1769 ------ .../src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp | 313 - .../src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp | 260 - .../src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp | 1787 ------ .../src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp | 380 -- .../kpx_cpu/src/cpu/ppc/ppc-instructions.hpp | 366 -- .../src/kpx_cpu/src/cpu/ppc/ppc-jit.cpp | 942 --- .../src/kpx_cpu/src/cpu/ppc/ppc-jit.hpp | 106 - .../src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp | 591 -- .../kpx_cpu/src/cpu/ppc/ppc-operations.hpp | 405 -- .../src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp | 251 - .../src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp | 1589 ----- SheepShaver/src/kpx_cpu/src/cpu/spcflags.hpp | 66 - SheepShaver/src/kpx_cpu/src/cpu/vm.hpp | 298 - .../src/kpx_cpu/src/mathlib/ieeefp-i386.cpp | 111 - .../src/kpx_cpu/src/mathlib/ieeefp-i386.hpp | 58 - .../src/kpx_cpu/src/mathlib/ieeefp-mips.hpp | 58 - .../src/kpx_cpu/src/mathlib/ieeefp.cpp | 29 - .../src/kpx_cpu/src/mathlib/ieeefp.hpp | 123 - .../src/kpx_cpu/src/mathlib/mathlib-i386.cpp | 38 - .../src/kpx_cpu/src/mathlib/mathlib-i386.hpp | 52 - .../src/kpx_cpu/src/mathlib/mathlib-ppc.hpp | 63 - .../kpx_cpu/src/mathlib/mathlib-x86_64.hpp | 33 - .../src/kpx_cpu/src/mathlib/mathlib.cpp | 228 - .../src/kpx_cpu/src/mathlib/mathlib.hpp | 339 - .../src/kpx_cpu/src/test/test-powerpc.cpp | 2242 ------- .../src/kpx_cpu/src/utils/utils-cpuinfo.cpp | 151 - .../src/kpx_cpu/src/utils/utils-cpuinfo.hpp | 51 - .../src/kpx_cpu/src/utils/utils-sentinel.hpp | 47 - SheepShaver/src/macos_util.cpp | 354 -- SheepShaver/src/main.cpp | 326 - SheepShaver/src/name_registry.cpp | 368 -- SheepShaver/src/pict.c | 1 - SheepShaver/src/prefs.cpp | 1 - SheepShaver/src/prefs_items.cpp | 95 - SheepShaver/src/rom_patches.cpp | 2499 -------- SheepShaver/src/rsrc_patches.cpp | 1051 ---- SheepShaver/src/scsi.cpp | 1 - SheepShaver/src/serial.cpp | 315 - SheepShaver/src/slirp | 1 - SheepShaver/src/sony.cpp | 1 - SheepShaver/src/thunks.cpp | 406 -- SheepShaver/src/timer.cpp | 677 -- SheepShaver/src/user_strings.cpp | 186 - SheepShaver/src/video.cpp | 1097 ---- SheepShaver/src/xpram.cpp | 1 - cxmon/.gitignore | 26 - cxmon/AUTHORS | 8 - cxmon/COPYING | 340 - cxmon/ChangeLog | 20 - cxmon/INSTALL | 182 - cxmon/Makefile.am | 17 - cxmon/README | 437 -- cxmon/bootstrap | 2 - cxmon/configure.ac | 47 - cxmon/cxmon.1 | 56 - cxmon/cxmon.spec.in | 42 - cxmon/src/Makefile.am | 10 - cxmon/src/disass/Makefile.am | 8 - cxmon/src/disass/ansidecl.h | 295 - cxmon/src/disass/bfd.h | 66 - cxmon/src/disass/dis-asm.h | 315 - cxmon/src/disass/floatformat.c | 401 -- cxmon/src/disass/floatformat.h | 111 - cxmon/src/disass/i386-dis.c | 4146 ------------- cxmon/src/disass/m68k-dis.c | 1248 ---- cxmon/src/disass/m68k-opc.c | 2066 ------- cxmon/src/disass/m68k.h | 315 - cxmon/src/disass/opintl.h | 34 - cxmon/src/main.cpp | 118 - cxmon/src/mon.cpp | 1255 ---- cxmon/src/mon.h | 100 - cxmon/src/mon_6502.cpp | 232 - cxmon/src/mon_atraps.h | 1212 ---- cxmon/src/mon_cmd.cpp | 669 -- cxmon/src/mon_cmd.h | 46 - cxmon/src/mon_disass.cpp | 204 - cxmon/src/mon_disass.h | 30 - cxmon/src/mon_lowmem.cpp | 579 -- cxmon/src/mon_lowmem.h | 32 - cxmon/src/mon_ppc.cpp | 1129 ---- cxmon/src/mon_z80.cpp | 604 -- cxmon/src/sysdeps.h | 96 - 430 files changed, 107195 deletions(-) delete mode 100644 SheepShaver/COPYING delete mode 100644 SheepShaver/Makefile delete mode 100644 SheepShaver/NEWS delete mode 100644 SheepShaver/doc/BeOS/acknowledgements.html delete mode 100644 SheepShaver/doc/BeOS/contact.html delete mode 100644 SheepShaver/doc/BeOS/graphics.gif delete mode 100644 SheepShaver/doc/BeOS/history.html delete mode 100644 SheepShaver/doc/BeOS/icon.gif delete mode 100644 SheepShaver/doc/BeOS/iconsmall.gif delete mode 100644 SheepShaver/doc/BeOS/index.html delete mode 100644 SheepShaver/doc/BeOS/installation.html delete mode 100644 SheepShaver/doc/BeOS/introduction.html delete mode 100644 SheepShaver/doc/BeOS/memory.gif delete mode 100644 SheepShaver/doc/BeOS/quickstart.html delete mode 100644 SheepShaver/doc/BeOS/serial.gif delete mode 100644 SheepShaver/doc/BeOS/settings.html delete mode 100644 SheepShaver/doc/BeOS/troubleshooting.html delete mode 100644 SheepShaver/doc/BeOS/using.html delete mode 100644 SheepShaver/doc/BeOS/volumes.gif delete mode 100644 SheepShaver/doc/Linux/acknowledgements.html delete mode 100644 SheepShaver/doc/Linux/contact.html delete mode 100644 SheepShaver/doc/Linux/graphics.gif delete mode 100644 SheepShaver/doc/Linux/history.html delete mode 100644 SheepShaver/doc/Linux/icon.gif delete mode 100644 SheepShaver/doc/Linux/iconsmall.gif delete mode 100644 SheepShaver/doc/Linux/index.html delete mode 100644 SheepShaver/doc/Linux/installation.html delete mode 100644 SheepShaver/doc/Linux/introduction.html delete mode 100644 SheepShaver/doc/Linux/memory.gif delete mode 100644 SheepShaver/doc/Linux/quickstart.html delete mode 100644 SheepShaver/doc/Linux/serial.gif delete mode 100644 SheepShaver/doc/Linux/settings.html delete mode 100644 SheepShaver/doc/Linux/troubleshooting.html delete mode 100644 SheepShaver/doc/Linux/using.html delete mode 100644 SheepShaver/doc/Linux/volumes.gif delete mode 100644 SheepShaver/doc/PowerPC-Testsuite.txt delete mode 100644 SheepShaver/src/BeOS/CreatePCIDrivers/Ethernet.cpp delete mode 100644 SheepShaver/src/BeOS/CreatePCIDrivers/Makefile delete mode 100644 SheepShaver/src/BeOS/CreatePCIDrivers/Video.cpp delete mode 100644 SheepShaver/src/BeOS/CreatePCIDrivers/hexconv.cpp delete mode 100644 SheepShaver/src/BeOS/Makefile delete mode 100644 SheepShaver/src/BeOS/NetPeek/Makefile delete mode 100644 SheepShaver/src/BeOS/NetPeek/NetPeek.cpp delete mode 100644 SheepShaver/src/BeOS/SaveROM/Makefile delete mode 100644 SheepShaver/src/BeOS/SaveROM/README delete mode 100644 SheepShaver/src/BeOS/SaveROM/SaveROM.cpp delete mode 100644 SheepShaver/src/BeOS/SaveROM/SaveROM.rsrc delete mode 120000 SheepShaver/src/BeOS/SheepDriver delete mode 120000 SheepShaver/src/BeOS/SheepNet delete mode 100644 SheepShaver/src/BeOS/SheepShaver.rsrc delete mode 100644 SheepShaver/src/BeOS/about_window_beos.cpp delete mode 120000 SheepShaver/src/BeOS/audio_beos.cpp delete mode 100644 SheepShaver/src/BeOS/clip_beos.cpp delete mode 100644 SheepShaver/src/BeOS/ether_beos.cpp delete mode 120000 SheepShaver/src/BeOS/extfs_beos.cpp delete mode 100644 SheepShaver/src/BeOS/main_beos.cpp delete mode 100644 SheepShaver/src/BeOS/prefs_beos.cpp delete mode 100644 SheepShaver/src/BeOS/prefs_editor_beos.cpp delete mode 120000 SheepShaver/src/BeOS/scsi_beos.cpp delete mode 120000 SheepShaver/src/BeOS/serial_beos.cpp delete mode 120000 SheepShaver/src/BeOS/sys_beos.cpp delete mode 100644 SheepShaver/src/BeOS/sysdeps.h delete mode 120000 SheepShaver/src/BeOS/timer_beos.cpp delete mode 100644 SheepShaver/src/BeOS/user_strings_beos.cpp delete mode 100644 SheepShaver/src/BeOS/user_strings_beos.h delete mode 100644 SheepShaver/src/BeOS/video_beos.cpp delete mode 100644 SheepShaver/src/BeOS/video_screen.h delete mode 100644 SheepShaver/src/BeOS/video_window.h delete mode 120000 SheepShaver/src/BeOS/xpram_beos.cpp delete mode 120000 SheepShaver/src/CrossPlatform/sigsegv.cpp delete mode 120000 SheepShaver/src/CrossPlatform/sigsegv.h delete mode 120000 SheepShaver/src/CrossPlatform/video_blit.cpp delete mode 120000 SheepShaver/src/CrossPlatform/video_blit.h delete mode 120000 SheepShaver/src/CrossPlatform/video_vosf.h delete mode 120000 SheepShaver/src/CrossPlatform/vm_alloc.cpp delete mode 120000 SheepShaver/src/CrossPlatform/vm_alloc.h delete mode 100644 SheepShaver/src/EthernetDriver/.finf/Ethernet.mcp delete mode 100644 SheepShaver/src/EthernetDriver/.finf/ethernet.ndrv delete mode 100644 SheepShaver/src/EthernetDriver/.rsrc/ethernet.ndrv delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/.finf/CWSettingsMacOS.stg delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/.finf/PPC Debug MacOS Toolbox delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/.finf/PPC Final MacOS Toolbox delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/CWSettingsMacOS.stg delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/.finf/TargetDataMacOS.tdt delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/.rsrc/TargetDataMacOS.tdt delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/TargetDataMacOS.tdt delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/.finf/TargetDataMacOS.tdt delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/.rsrc/TargetDataMacOS.tdt delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/TargetDataMacOS.tdt delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet.cpp delete mode 100644 SheepShaver/src/EthernetDriver/Ethernet.mcp delete mode 100644 SheepShaver/src/EthernetDriver/cpu_emulation.h delete mode 100644 SheepShaver/src/EthernetDriver/debug.h delete mode 100644 SheepShaver/src/EthernetDriver/ether.cpp delete mode 100644 SheepShaver/src/EthernetDriver/ether.h delete mode 100644 SheepShaver/src/EthernetDriver/ether_defs.h delete mode 100644 SheepShaver/src/EthernetDriver/ethernet.ndrv delete mode 100644 SheepShaver/src/EthernetDriver/macos_util.cpp delete mode 100644 SheepShaver/src/EthernetDriver/macos_util.h delete mode 100644 SheepShaver/src/EthernetDriver/sysdeps.h delete mode 100644 SheepShaver/src/EthernetDriver/xlowmem.h delete mode 100644 SheepShaver/src/EthernetDriverFull.i delete mode 100644 SheepShaver/src/EthernetDriverStub.i delete mode 100644 SheepShaver/src/MacOSX/.gitignore delete mode 120000 SheepShaver/src/MacOSX/AudioBackEnd.cpp delete mode 120000 SheepShaver/src/MacOSX/AudioBackEnd.h delete mode 120000 SheepShaver/src/MacOSX/AudioDevice.cpp delete mode 120000 SheepShaver/src/MacOSX/AudioDevice.h delete mode 100644 SheepShaver/src/MacOSX/Info.plist.in delete mode 100644 SheepShaver/src/MacOSX/Launcher/AppController.h delete mode 100644 SheepShaver/src/MacOSX/Launcher/AppController.mm delete mode 100755 SheepShaver/src/MacOSX/Launcher/DiskType.h delete mode 100755 SheepShaver/src/MacOSX/Launcher/DiskType.m delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/InfoPlist.strings delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/classes.nib delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/info.nib delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/keyedobjects.nib delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/designable.nib delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/keyedobjects.nib delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/VMSettingsWindow.nib/designable.nib delete mode 100755 SheepShaver/src/MacOSX/Launcher/English.lproj/VMSettingsWindow.nib/keyedobjects.nib delete mode 100644 SheepShaver/src/MacOSX/Launcher/Info.plist delete mode 100644 SheepShaver/src/MacOSX/Launcher/LauncherPrefix.h delete mode 100644 SheepShaver/src/MacOSX/Launcher/SheepShaverLauncher.xcodeproj/project.pbxproj delete mode 100644 SheepShaver/src/MacOSX/Launcher/VMListController.h delete mode 100644 SheepShaver/src/MacOSX/Launcher/VMListController.mm delete mode 100755 SheepShaver/src/MacOSX/Launcher/VMSettingsController.h delete mode 100755 SheepShaver/src/MacOSX/Launcher/VMSettingsController.mm delete mode 100644 SheepShaver/src/MacOSX/Launcher/main.m delete mode 120000 SheepShaver/src/MacOSX/MacOSX_sound_if.cpp delete mode 120000 SheepShaver/src/MacOSX/MacOSX_sound_if.h delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/English.lproj/InfoPlist.strings delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/classes.nib delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/info.nib delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/keyedobjects.nib delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/Info.plist delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.h delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.mm delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/SheepShaverPrefs.xcodeproj/project.pbxproj delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/main.m delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/InfoPlist.strings delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/classes.nib delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/info.nib delete mode 100644 SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/keyedobjects.nib delete mode 100644 SheepShaver/src/MacOSX/SheepShaver.icns delete mode 100644 SheepShaver/src/MacOSX/SheepShaver.xcodeproj/project.pbxproj delete mode 100644 SheepShaver/src/MacOSX/XcodeBuildHowTo.txt delete mode 120000 SheepShaver/src/MacOSX/audio_macosx.cpp delete mode 120000 SheepShaver/src/MacOSX/autorelease.h delete mode 120000 SheepShaver/src/MacOSX/clip_macosx.cpp delete mode 120000 SheepShaver/src/MacOSX/clip_macosx64.mm delete mode 100644 SheepShaver/src/MacOSX/config/config-macosx-ppc_32.h delete mode 100644 SheepShaver/src/MacOSX/config/config-macosx-x86_32.h delete mode 100644 SheepShaver/src/MacOSX/config/config-macosx-x86_64.h delete mode 100644 SheepShaver/src/MacOSX/config/config.h delete mode 120000 SheepShaver/src/MacOSX/extfs_macosx.cpp delete mode 120000 SheepShaver/src/MacOSX/macos_util_macosx.h delete mode 100644 SheepShaver/src/MacOSX/prefs_macosx.mm delete mode 120000 SheepShaver/src/MacOSX/sys_darwin.cpp delete mode 120000 SheepShaver/src/MacOSX/utils_macosx.h delete mode 120000 SheepShaver/src/MacOSX/utils_macosx.mm delete mode 120000 SheepShaver/src/SDL delete mode 100644 SheepShaver/src/Unix/.gitignore delete mode 100644 SheepShaver/src/Unix/Darwin/.gitignore delete mode 120000 SheepShaver/src/Unix/Darwin/lowmem.c delete mode 120000 SheepShaver/src/Unix/Darwin/mkstandalone delete mode 120000 SheepShaver/src/Unix/Darwin/pagezero.c delete mode 120000 SheepShaver/src/Unix/Darwin/testlmem.sh delete mode 120000 SheepShaver/src/Unix/Irix/audio_irix.cpp delete mode 120000 SheepShaver/src/Unix/Linux/NetDriver delete mode 120000 SheepShaver/src/Unix/Linux/scsi_linux.cpp delete mode 100644 SheepShaver/src/Unix/Linux/sheepthreads.c delete mode 100644 SheepShaver/src/Unix/Makefile.in delete mode 100644 SheepShaver/src/Unix/NetBSD/sheepthreads.c delete mode 100644 SheepShaver/src/Unix/SheepShaver.1 delete mode 100644 SheepShaver/src/Unix/about_window_unix.cpp delete mode 120000 SheepShaver/src/Unix/audio_oss_esd.cpp delete mode 100755 SheepShaver/src/Unix/autogen.sh delete mode 120000 SheepShaver/src/Unix/bincue_unix.cpp delete mode 120000 SheepShaver/src/Unix/bincue_unix.h delete mode 120000 SheepShaver/src/Unix/clip_unix.cpp delete mode 120000 SheepShaver/src/Unix/config.guess delete mode 120000 SheepShaver/src/Unix/config.sub delete mode 100644 SheepShaver/src/Unix/configure.ac delete mode 120000 SheepShaver/src/Unix/cpr.sh delete mode 120000 SheepShaver/src/Unix/disk_sparsebundle.cpp delete mode 120000 SheepShaver/src/Unix/disk_unix.h delete mode 120000 SheepShaver/src/Unix/ether_unix.cpp delete mode 120000 SheepShaver/src/Unix/extfs_unix.cpp delete mode 100755 SheepShaver/src/Unix/install-sh delete mode 120000 SheepShaver/src/Unix/keycodes delete mode 120000 SheepShaver/src/Unix/ldscripts delete mode 120000 SheepShaver/src/Unix/m4 delete mode 100644 SheepShaver/src/Unix/main_unix.cpp delete mode 100755 SheepShaver/src/Unix/mkinstalldirs delete mode 100644 SheepShaver/src/Unix/paranoia.cpp delete mode 120000 SheepShaver/src/Unix/posix_sem.cpp delete mode 100644 SheepShaver/src/Unix/ppc_asm.S delete mode 100644 SheepShaver/src/Unix/ppc_asm.tmpl delete mode 100644 SheepShaver/src/Unix/prefs_editor_gtk.cpp delete mode 100644 SheepShaver/src/Unix/prefs_unix.cpp delete mode 120000 SheepShaver/src/Unix/rpc.h delete mode 120000 SheepShaver/src/Unix/rpc_unix.cpp delete mode 120000 SheepShaver/src/Unix/semaphore.h delete mode 120000 SheepShaver/src/Unix/serial_unix.cpp delete mode 100644 SheepShaver/src/Unix/sigregs.h delete mode 120000 SheepShaver/src/Unix/sshpty.c delete mode 120000 SheepShaver/src/Unix/sshpty.h delete mode 120000 SheepShaver/src/Unix/strlcpy.c delete mode 120000 SheepShaver/src/Unix/strlcpy.h delete mode 120000 SheepShaver/src/Unix/sys_unix.cpp delete mode 100644 SheepShaver/src/Unix/sysdeps.h delete mode 120000 SheepShaver/src/Unix/timer_unix.cpp delete mode 120000 SheepShaver/src/Unix/tinyxml2.cpp delete mode 120000 SheepShaver/src/Unix/tinyxml2.h delete mode 120000 SheepShaver/src/Unix/tunconfig delete mode 100644 SheepShaver/src/Unix/user_strings_unix.cpp delete mode 100644 SheepShaver/src/Unix/user_strings_unix.h delete mode 120000 SheepShaver/src/Unix/vhd_unix.cpp delete mode 100644 SheepShaver/src/Unix/video_x.cpp delete mode 120000 SheepShaver/src/Unix/xpram_unix.cpp delete mode 100644 SheepShaver/src/VideoDriverStub.i delete mode 100755 SheepShaver/src/Windows/Makefile.in delete mode 100755 SheepShaver/src/Windows/SheepShaver.ico delete mode 100755 SheepShaver/src/Windows/SheepShaver.rc delete mode 100755 SheepShaver/src/Windows/SheepShaverGUI.ico delete mode 100644 SheepShaver/src/Windows/SheepShaverGUI.rc delete mode 100755 SheepShaver/src/Windows/about_window_windows.cpp delete mode 120000 SheepShaver/src/Windows/b2ether delete mode 120000 SheepShaver/src/Windows/cd_defs.h delete mode 120000 SheepShaver/src/Windows/cdenable delete mode 120000 SheepShaver/src/Windows/clip_windows.cpp delete mode 100755 SheepShaver/src/Windows/configure.ac delete mode 120000 SheepShaver/src/Windows/ether_windows.cpp delete mode 120000 SheepShaver/src/Windows/ether_windows.h delete mode 120000 SheepShaver/src/Windows/extfs_windows.cpp delete mode 120000 SheepShaver/src/Windows/kernel_windows.cpp delete mode 120000 SheepShaver/src/Windows/kernel_windows.h delete mode 100755 SheepShaver/src/Windows/main_windows.cpp delete mode 120000 SheepShaver/src/Windows/posix_emu.cpp delete mode 120000 SheepShaver/src/Windows/posix_emu.h delete mode 120000 SheepShaver/src/Windows/prefs_editor_gtk.cpp delete mode 100755 SheepShaver/src/Windows/prefs_windows.cpp delete mode 120000 SheepShaver/src/Windows/router delete mode 120000 SheepShaver/src/Windows/serial_windows.cpp delete mode 120000 SheepShaver/src/Windows/sys_windows.cpp delete mode 100755 SheepShaver/src/Windows/sysdeps.h delete mode 120000 SheepShaver/src/Windows/timer_windows.cpp delete mode 100755 SheepShaver/src/Windows/user_strings_windows.cpp delete mode 100755 SheepShaver/src/Windows/user_strings_windows.h delete mode 120000 SheepShaver/src/Windows/util_windows.cpp delete mode 120000 SheepShaver/src/Windows/util_windows.h delete mode 120000 SheepShaver/src/Windows/xpram_windows.cpp delete mode 120000 SheepShaver/src/adb.cpp delete mode 120000 SheepShaver/src/audio.cpp delete mode 120000 SheepShaver/src/cdrom.cpp delete mode 120000 SheepShaver/src/disk.cpp delete mode 120000 SheepShaver/src/dummy/audio_dummy.cpp delete mode 120000 SheepShaver/src/dummy/clip_dummy.cpp delete mode 100644 SheepShaver/src/dummy/ether_dummy.cpp delete mode 100644 SheepShaver/src/dummy/prefs_dummy.cpp delete mode 120000 SheepShaver/src/dummy/prefs_editor_dummy.cpp delete mode 120000 SheepShaver/src/dummy/scsi_dummy.cpp delete mode 120000 SheepShaver/src/dummy/serial_dummy.cpp delete mode 100644 SheepShaver/src/emul_op.cpp delete mode 100644 SheepShaver/src/emul_ppc/emul_ppc.cpp delete mode 100644 SheepShaver/src/ether.cpp delete mode 120000 SheepShaver/src/extfs.cpp delete mode 100644 SheepShaver/src/gfxaccel.cpp delete mode 100644 SheepShaver/src/include/about_window.h delete mode 120000 SheepShaver/src/include/adb.h delete mode 120000 SheepShaver/src/include/audio.h delete mode 120000 SheepShaver/src/include/audio_defs.h delete mode 120000 SheepShaver/src/include/cdrom.h delete mode 120000 SheepShaver/src/include/clip.h delete mode 100644 SheepShaver/src/include/cpu_emulation.h delete mode 120000 SheepShaver/src/include/debug.h delete mode 120000 SheepShaver/src/include/disk.h delete mode 100644 SheepShaver/src/include/emul_op.h delete mode 100644 SheepShaver/src/include/ether.h delete mode 100644 SheepShaver/src/include/ether_defs.h delete mode 120000 SheepShaver/src/include/extfs.h delete mode 120000 SheepShaver/src/include/extfs_defs.h delete mode 100644 SheepShaver/src/include/macos_util.h delete mode 100644 SheepShaver/src/include/main.h delete mode 100644 SheepShaver/src/include/name_registry.h delete mode 120000 SheepShaver/src/include/pict.h delete mode 120000 SheepShaver/src/include/prefs.h delete mode 100644 SheepShaver/src/include/prefs_editor.h delete mode 100644 SheepShaver/src/include/rom_patches.h delete mode 100644 SheepShaver/src/include/rsrc_patches.h delete mode 120000 SheepShaver/src/include/scsi.h delete mode 120000 SheepShaver/src/include/serial.h delete mode 120000 SheepShaver/src/include/serial_defs.h delete mode 120000 SheepShaver/src/include/sony.h delete mode 120000 SheepShaver/src/include/sys.h delete mode 100644 SheepShaver/src/include/thunks.h delete mode 120000 SheepShaver/src/include/timer.h delete mode 100644 SheepShaver/src/include/user_strings.h delete mode 100644 SheepShaver/src/include/version.h delete mode 100644 SheepShaver/src/include/video.h delete mode 100644 SheepShaver/src/include/video_defs.h delete mode 100644 SheepShaver/src/include/xlowmem.h delete mode 120000 SheepShaver/src/include/xpram.h delete mode 100644 SheepShaver/src/kpx_cpu/dis-asm.h delete mode 100644 SheepShaver/src/kpx_cpu/include/a.out-defs.h delete mode 100644 SheepShaver/src/kpx_cpu/include/basic-blockinfo.hpp delete mode 100644 SheepShaver/src/kpx_cpu/include/basic-cpu.hpp delete mode 100644 SheepShaver/src/kpx_cpu/include/basic-plugin.hpp delete mode 100644 SheepShaver/src/kpx_cpu/include/block-alloc.hpp delete mode 100644 SheepShaver/src/kpx_cpu/include/elf-defs.h delete mode 100644 SheepShaver/src/kpx_cpu/include/nvmemfun.hpp delete mode 100644 SheepShaver/src/kpx_cpu/include/task-plugin.hpp delete mode 100644 SheepShaver/src/kpx_cpu/ppc-dis.c delete mode 100644 SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/block-cache.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/dyngen-target-exec.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-cache.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-codegen.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/dummy/jit-target-cache.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/jit-codegen.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/jit-config.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/jit-target-dispatch.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/mips/dyngen-target-exec.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/mips/jit-target-cache.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/dyngen-target-exec.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/jit-target-cache.hpp delete mode 120000 SheepShaver/src/kpx_cpu/src/cpu/jit/x86/codegen_x86.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/x86/dyngen-target-exec.h delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-cache.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-codegen.hpp delete mode 100755 SheepShaver/src/kpx_cpu/src/cpu/ppc/genexec.pl delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-bitfields.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-instructions.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operations.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/spcflags.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/cpu/vm.hpp delete mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp delete mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-mips.hpp delete mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp delete mode 100755 SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/mathlib-ppc.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/mathlib-x86_64.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/mathlib.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/mathlib/mathlib.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.cpp delete mode 100644 SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.hpp delete mode 100644 SheepShaver/src/kpx_cpu/src/utils/utils-sentinel.hpp delete mode 100644 SheepShaver/src/macos_util.cpp delete mode 100644 SheepShaver/src/main.cpp delete mode 100644 SheepShaver/src/name_registry.cpp delete mode 120000 SheepShaver/src/pict.c delete mode 120000 SheepShaver/src/prefs.cpp delete mode 100644 SheepShaver/src/prefs_items.cpp delete mode 100644 SheepShaver/src/rom_patches.cpp delete mode 100644 SheepShaver/src/rsrc_patches.cpp delete mode 120000 SheepShaver/src/scsi.cpp delete mode 100644 SheepShaver/src/serial.cpp delete mode 120000 SheepShaver/src/slirp delete mode 120000 SheepShaver/src/sony.cpp delete mode 100644 SheepShaver/src/thunks.cpp delete mode 100644 SheepShaver/src/timer.cpp delete mode 100644 SheepShaver/src/user_strings.cpp delete mode 100644 SheepShaver/src/video.cpp delete mode 120000 SheepShaver/src/xpram.cpp delete mode 100644 cxmon/.gitignore delete mode 100644 cxmon/AUTHORS delete mode 100644 cxmon/COPYING delete mode 100644 cxmon/ChangeLog delete mode 100644 cxmon/INSTALL delete mode 100644 cxmon/Makefile.am delete mode 100644 cxmon/README delete mode 100755 cxmon/bootstrap delete mode 100644 cxmon/configure.ac delete mode 100644 cxmon/cxmon.1 delete mode 100644 cxmon/cxmon.spec.in delete mode 100644 cxmon/src/Makefile.am delete mode 100644 cxmon/src/disass/Makefile.am delete mode 100644 cxmon/src/disass/ansidecl.h delete mode 100644 cxmon/src/disass/bfd.h delete mode 100644 cxmon/src/disass/dis-asm.h delete mode 100644 cxmon/src/disass/floatformat.c delete mode 100644 cxmon/src/disass/floatformat.h delete mode 100644 cxmon/src/disass/i386-dis.c delete mode 100644 cxmon/src/disass/m68k-dis.c delete mode 100644 cxmon/src/disass/m68k-opc.c delete mode 100644 cxmon/src/disass/m68k.h delete mode 100644 cxmon/src/disass/opintl.h delete mode 100644 cxmon/src/main.cpp delete mode 100644 cxmon/src/mon.cpp delete mode 100644 cxmon/src/mon.h delete mode 100644 cxmon/src/mon_6502.cpp delete mode 100644 cxmon/src/mon_atraps.h delete mode 100644 cxmon/src/mon_cmd.cpp delete mode 100644 cxmon/src/mon_cmd.h delete mode 100644 cxmon/src/mon_disass.cpp delete mode 100644 cxmon/src/mon_disass.h delete mode 100644 cxmon/src/mon_lowmem.cpp delete mode 100644 cxmon/src/mon_lowmem.h delete mode 100644 cxmon/src/mon_ppc.cpp delete mode 100644 cxmon/src/mon_z80.cpp delete mode 100644 cxmon/src/sysdeps.h diff --git a/SheepShaver/COPYING b/SheepShaver/COPYING deleted file mode 100644 index 60549be5..00000000 --- a/SheepShaver/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. 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. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/SheepShaver/Makefile b/SheepShaver/Makefile deleted file mode 100644 index 2fec37a1..00000000 --- a/SheepShaver/Makefile +++ /dev/null @@ -1,104 +0,0 @@ -# Makefile for creating SheepShaver distributions -# Written in 1999 by Christian Bauer - -VERSION := 2.3 -VERNAME := SheepShaver-$(VERSION) -CVSDATE := $(shell date "+%Y%m%d") - -SRCARCHIVE := $(VERNAME)-$(CVSDATE).tar.gz - -TMPDIR := $(shell date +/tmp/build%m%s) -ISODATE := $(shell date "+%Y-%m-%d %H:%M") -DOCS := NEWS -SRCS := src - -# Where Basilisk II directory can be found -B2_TOPDIR := ../BasiliskII - -default: help - -help: - @echo "This top-level Makefile is for creating SheepShaver distributions." - @echo "The following targets are available:" - @echo " tarball source tarball ($(SRCARCHIVE))" - @echo " links create links to Basilisk II sources" - -clean: - -rm -f $(SRCARCHIVE) - -# -# Source tarball -# -tarball: $(SRCARCHIVE) - -$(SRCARCHIVE): $(SRCS) $(DOCS) - -rm -rf $(TMPDIR) - mkdir $(TMPDIR) - cd $(TMPDIR); cvs export -D "$(ISODATE)" BasiliskII SheepShaver - cd $(TMPDIR)/SheepShaver/src/Unix && mkdir Darwin - cd $(TMPDIR)/SheepShaver && make links - cd $(TMPDIR)/SheepShaver/src/Unix && NO_CONFIGURE=1 ./autogen.sh - cd $(TMPDIR)/SheepShaver/src/Windows && NO_CONFIGURE=1 ../Unix/autogen.sh - rm $(TMPDIR)/SheepShaver/Makefile - cp -aL $(TMPDIR)/SheepShaver $(TMPDIR)/$(VERNAME) - cd $(TMPDIR); tar cfz $@ $(VERNAME) - mv $(TMPDIR)/$@ . - rm -rf $(TMPDIR) - -# -# Links to Basilisk II sources -# -links: - @list='adb.cpp audio.cpp cdrom.cpp disk.cpp extfs.cpp pict.c \ - prefs.cpp scsi.cpp sony.cpp xpram.cpp \ - include/adb.h include/audio.h include/audio_defs.h \ - include/cdrom.h include/clip.h include/debug.h include/disk.h \ - include/extfs.h include/extfs_defs.h include/pict.h \ - include/prefs.h include/scsi.h include/serial.h \ - include/serial_defs.h include/sony.h include/sys.h \ - include/timer.h include/xpram.h \ - BeOS/audio_beos.cpp BeOS/extfs_beos.cpp BeOS/scsi_beos.cpp \ - BeOS/serial_beos.cpp BeOS/sys_beos.cpp BeOS/timer_beos.cpp \ - BeOS/xpram_beos.cpp BeOS/SheepDriver BeOS/SheepNet \ - CrossPlatform/sigsegv.h CrossPlatform/sigsegv.cpp CrossPlatform/vm_alloc.h CrossPlatform/vm_alloc.cpp \ - CrossPlatform/video_vosf.h CrossPlatform/video_blit.h CrossPlatform/video_blit.cpp \ - Unix/audio_oss_esd.cpp Unix/bincue_unix.cpp Unix/bincue_unix.h \ - Unix/vhd_unix.cpp \ - Unix/extfs_unix.cpp Unix/serial_unix.cpp \ - Unix/sshpty.h Unix/sshpty.c Unix/strlcpy.h Unix/strlcpy.c \ - Unix/sys_unix.cpp Unix/timer_unix.cpp Unix/xpram_unix.cpp \ - Unix/semaphore.h Unix/posix_sem.cpp Unix/config.sub Unix/config.guess Unix/m4 \ - Unix/keycodes Unix/tunconfig Unix/clip_unix.cpp Unix/Irix/audio_irix.cpp \ - Unix/Linux/scsi_linux.cpp Unix/Linux/NetDriver Unix/ether_unix.cpp \ - Unix/rpc.h Unix/rpc_unix.cpp Unix/ldscripts \ - Unix/tinyxml2.h Unix/tinyxml2.cpp Unix/disk_unix.h \ - Unix/disk_sparsebundle.cpp Unix/Darwin/mkstandalone \ - Unix/Darwin/lowmem.c Unix/Darwin/pagezero.c Unix/Darwin/testlmem.sh \ - dummy/audio_dummy.cpp dummy/clip_dummy.cpp dummy/serial_dummy.cpp \ - dummy/prefs_editor_dummy.cpp dummy/scsi_dummy.cpp SDL slirp \ - MacOSX/sys_darwin.cpp MacOSX/clip_macosx.cpp MacOSX/clip_macosx64.mm \ - MacOSX/macos_util_macosx.h Unix/cpr.sh \ - MacOSX/extfs_macosx.cpp Windows/clip_windows.cpp \ - MacOSX/MacOSX_sound_if.cpp MacOSX/MacOSX_sound_if.h \ - MacOSX/AudioBackEnd.cpp MacOSX/AudioBackEnd.h \ - MacOSX/AudioDevice.cpp MacOSX/AudioDevice.h MacOSX/audio_macosx.cpp \ - MacOSX/utils_macosx.mm MacOSX/utils_macosx.h \ - Windows/cd_defs.h Windows/cdenable Windows/extfs_windows.cpp \ - Windows/posix_emu.cpp Windows/posix_emu.h Windows/sys_windows.cpp \ - Windows/timer_windows.cpp Windows/util_windows.cpp \ - Windows/util_windows.h Windows/xpram_windows.cpp \ - Windows/kernel_windows.h Windows/kernel_windows.cpp \ - Windows/serial_windows.cpp Windows/router Windows/b2ether \ - Windows/ether_windows.h Windows/ether_windows.cpp \ - Windows/serial_windows.cpp Windows/prefs_editor_gtk.cpp \ - uae_cpu/compiler/codegen_x86.h'; \ - PREFIX="../"; case $(B2_TOPDIR) in /*) PREFIX="";; esac; \ - for i in $$list; do \ - if test "$$i" != "\\"; then \ - echo $$i; o=$$i; \ - case $$i in *codegen_x86.h) o=kpx_cpu/src/cpu/jit/x86/codegen_x86.h;; esac; \ - SUB=`echo $$o | sed 's;[^/]*/;../;g' | sed 's;[^/]*$$;;'` ;\ - ln -sf "$$PREFIX$$SUB$(B2_TOPDIR)/src/$$i" src/$$o; \ - fi; \ - done; \ - ln -sf ../../../../../SheepShaver/src/Unix/config.h $(B2_TOPDIR)/src/Unix/Linux/NetDriver/config.h diff --git a/SheepShaver/NEWS b/SheepShaver/NEWS deleted file mode 100644 index 42719c15..00000000 --- a/SheepShaver/NEWS +++ /dev/null @@ -1,105 +0,0 @@ -SheepShaver NEWS -- history of user-visible changes. 2006-05-14 -Copyright (C) 1997-2006 Christian Bauer and Marc Hellwig - -Version 2.3 (snapshot) - 14.May.2006 -* Handle up to 1 GB of Mac memory -* Improve SLiRP network emulation performance -* Fix Native QuickDraw acceleration -* Fix a crash during MacOS 9 installation -* Fix a crash in the AppleShare extension -* Fix support for MacOS 7.5.3 Revision 2.2 -* Fix gigantic window dimensions on first boot -* Fix extfs volume name to "Unix" (Toshimitsu Tanaka) -* Fix unaligned accesses in SLiRP network emulation (Brian J. Johnson) -* Initial port to IRIX/mips -* MacOS X: - o Port to MacOS X for Intel, including the JIT - o Add a primitive graphical preferences editor - o Add support for run-time CD-ROM auto-detection - o Fix clipboard (copy/paste of text from/to the host OS) - o Fix extfs to preserve native folder attributes - o Fix extfs to handle file/folder creation times - o Fix SLiRP network emulation (workaround MacOS X bugs) - o Improve overall performance on PowerPC (by a factor 2) -* Windows: - o Add SLiRP network emulation ("ether slirp") - o Add TAP-Win32 network emulation ("ether tap") - o Fix CD-ROM auto-detection ("pollmedia" now works) - o Fix idle sleep ("idlewait" now works) - o Fix native cursor to be updated as soon as MacOS modified it - o Improve GUI for network configuration - -Version 2.3 (snapshot) - 30.Nov.2005 -* Add fullscreen DGA mode via fbdev in Linux -* Add "screen" prefs item a-la Basilisk II -* Add missing lvsl/lvsr instructions in AltiVec emulation (Adobe FrameMaker) -* Add support for old toolchain (gcc "2.96", glibc 2.2) -* Add user-space network emulation ("ether slirp" in prefs file) -* Add Ethernet and Serial support to Windows -* Add GTK+2 based GUI to Windows -* Add initial port to Darwin/x86 with JIT -* Improve portability of FPU emulation code to non C99 capable systems -* Improve interrupt processing in emulated mode -* Improve idle wait on Linux platforms -* Properly fail to load MacOS < 8.1 with NewWorld ROMs -* Fix native execution in Linux/PowerPC -* Fix PowerPC test-and-set implementation (fix clipboard) -* Fix Ethernet support in Linux, avoid hangs -* Fix occasional hangs during interrupt processing -* Fix High Resolution Timing code for Linux -* Fix support for 4+ GB hard disk images -* Fix SDL/x11 native cursor acceleration -* Fix sheep_net driver to properly work with Linux kernels up to 2.6.11 - -Version 2.3 (snapshot) - 21.Mar.2005 -* Implement high-precision timings on POSIX systems -* Add other SDL keysym translations -* Add some SSE2 optimizations to the AltiVec emulation core -* Add port to FreeBSD 5.3 and NetBSD 2.0 systems (x86 tested) -* Add initial port to Windows with SDL graphics -* Fix interrupt handling, registers are now fully preserved -* Fix support for native execution on recent Linux/PPC systems -* Fix support for Gossamer ROMs (PowerMac G3 Beige) -* Fix crash in Apple Personal Diagnostics on MacOS 9 -* Fix crash in Power Management on MacOS 9 - -Version 2.3 (snapshot) - 07.Jul.2004 -* Add support for MacOS 9.0.4 -* Add native port to MacOS X with SDL graphics -* Fix timebase emulation. UpTime() is now more accurate -* Fix hardware cursor acceleration in X11 -* Fix 'r' and key mappings for Apple X11 servers -* Fix video thread cancellation on MacOS X -* Fix detection of PowerPC 750FX and 970 processors - -Version 2.3 (snapshot) - 09.Jun.2004 -* Improve generic JIT engine to reach around 1/8-th of native speeds -* Improve 68k audio processing with "reentrant" JIT generated code -* Add Native QuickDraw acceleration for BitBlt (srcCopy) and FillRect -* Add TUN/TAP device support on Linux systems -* Add run-time depth switching. Support at least 1-bpp screens -* Add "idlewait" option to pause SheepShaver when MacOS is idle -* Fix ethernet support on little endian and 64-bit systems -* Fix initialization of NVRAM on first-time use - -Version 2.3 (snapshot) - 25.Feb.2004 -* Improved generic JIT, FPU instructions are now translated -* Add AltiVec emulation, emulated CPU is now a PowerPC 7400 (G4) -* Add initial port to MacOS X with an X11 server - -Version 2.3 (snapshot) - 14.Jan.2004 -* Fix several CPU emulation bugs, extended testsuite -* Fix FPU emulation, "scrollbar" & Graphing Calculator bugs are gone -* Add support for 64-bit platforms, more precisely AMD64 with JIT -* Add support for copy-paste of text on Unix/X11 systems -* Add support for wheel mice -* Better support for PowerMac PCI ROMs with more generic patches -* Better support for audio output (with pre-G3 PowerMac PCI ROMs) -* Improve native Linux/PPC port - -Version 2.3 (snapshot) - 25.Nov.2003 -* Initial public release with PowerPC CPU emulator for testing - -Version 2.2 (release) - 04.Feb.2002 -* Source released under GPL -* Integrated code from Basilisk II diff --git a/SheepShaver/doc/BeOS/acknowledgements.html b/SheepShaver/doc/BeOS/acknowledgements.html deleted file mode 100644 index 204e8d20..00000000 --- a/SheepShaver/doc/BeOS/acknowledgements.html +++ /dev/null @@ -1,24 +0,0 @@ - - -Acknowledgements - - - -

Acknowledgements

- -The following persons/companies deserve special thanks from us as they -made a significant contribution to the development of SheepShaver: - -

-

- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/contact.html b/SheepShaver/doc/BeOS/contact.html deleted file mode 100644 index b4c00075..00000000 --- a/SheepShaver/doc/BeOS/contact.html +++ /dev/null @@ -1,47 +0,0 @@ - - -Contact Information - - - -

Contact Information and Copyright

- -SheepShaver was brought to you by - - -

SheepShaver WWW Site:

-
-www.sheepshaver.com
-
- -

EMail:

-
-Christian.Bauer@uni-mainz.de
-
- -

License

- -

SheepShaver is available under the terms of the GNU General Public License. -See the file "COPYING" that is included in the distribution for details. - -

© Copyright 1997-2004 Christian Bauer and Marc Hellwig - -

Names of hardware and software items mentioned in this manual and -in program texts are in most cases registered trade marks of the respective -companies and not marked as such. So the lack of such a note may not be -used as an indication that these names are free. - -

SheepShaver is not designed, intended, or authorized for use as a component -in systems intended for surgical implant within the body, or other applications intended -to support or sustain life, or for any other application in which the failure of SheepShaver -could create a situation where personal injury or death may occur (so-called "killer application"). - -


-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/graphics.gif b/SheepShaver/doc/BeOS/graphics.gif deleted file mode 100644 index 10a33553808ea9b69dd054448f4fe53f5cb227ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8854 zcmV;HB5B=6Nk%w1VVeO{0mJ|R|NsC0|7QRHGymg8|H}aXuM_C#=-AlU%a{Pbz`(e; zxS*h*n3$NDm;jh&0Emc)fPjE_cz9-J0AOHXSXfv41ejEjAQkdcy;k%kSIn3(Lsq@9ODr*V65?e%=260B`6DH?E*LJ;x9bK(K5dqJ#?@&VvP!;lwxj zF3MVyEuhDbwZ8o-xaMFUbQhriDRYJ)83GB%B&c~Ab0r215)`6TDeqWI0x*5Do4AZ7 z&Xo+=>||q9X3u%fph^|G5a!K!4V+z2c&8)CuV5jGB*&(JNjyd`I6%q}1JGw#Wx~94 zG-2GT$JDab;C7}lw=k8-g}6&eaU|b97XWQ`7(xwP zdz+3bF{kc7ew|@P)^z#>iuN{88y?Y^^)hrL)d{5T3#$>vNDg14J zyGPw;kAAwvCQVT5@yCY$LjvaKUmJ~WXWCqo@im)9bY%A4h8rd)4s-O4c1KpnIG~Vg zM$v{>iSpc(lNuxjXC78JT{V+Z z=-ftfI7H=@81;q7l1+9QRw|l=IVF~ESV<<8%fRH+mc)7Kre?adBIlVH?MUZFF}|1x zmv8pzk0EykDyX1*`e`UGfDWqYqS#C@!=sQ!D(R$@R%+>^jskGNrkr-_>8GHED(a}D zmTKy$sHUpws-Yh0DnJip%Id7N)@tjmxaO+suDtf@>#xA78Y=^uK49#z$R?}ovdlK? z?6c5DEA6z@R%`A5wb*8>?Y7)@>+QGR7AxxmmzHbpx#*^=?z-%@>+ZY69x!aN3>aYV zz4+#<@4o!@>+in+2Q2Ww1Q%@Z!3Za;@WKo??C`@2$2+gQ^#*J4#TaL-@x~l?>@lhm zk6ZD_B$sUR$tb6+GOHm=Jo3sg$1L;AG}mlu%k&yx^Ugf??DNmQ;!Ls5pDGZQ0zfCN z^wLbPEHt@9d#V8gn=+t*s8?^Ab=FOH?e*7Shx+u(opMbo*Jg*U_S$UwJa*KbT8%WP zMmvMFGY8;(wFY(19l>r_AylFJ$K-FbGmijS6h8R1Q-Z@Q{;lD zjrixFhc34NxGuw8GzL^tmpSL0?=3m&f&Wdx+@jZRd+3Uv&3f6dM~*h^St~$+1`*tD z{PAq(E_LIUPhIuoT1Wpo<_ajVIpL5aul@E)E8pqh*dM*A1zD5td+&eqef8knx9>jB z-e>Ij`}EhZa{RwqP`uH_+wcGXCc~evtjCxB0q}qb%$NWZ$iN0BZES+8o&+aI!3tXN zf*8!81~@P#mpp$un8!y1}^bo6qd4tEGN z2=efUK$MvegGj_8l5B`ZOrjDkhQuX0@rk%^J6yBy`>B*#l_{>q!2vRdOXhs;$4j&R}J z=BVJQHKgS;Rl(aE;j-DgRdI7u{G^=Z4mzuQqK%>Ztl29&8BC->Zkp%w9pG-Vzhl<_ zjRFz%Wjp&RP~wr4aLy?bK-xUC`i^SNliE&?Syr0b)p^4UX{cuUx}PRfu9J&^1u|OH$QkW! zFg-x?`d7}b)>5yotL#}Hdr!RXt$$-h?D;bLP02pft0)8OWtYjiYZeuHB_(R!EI`dq z<&>9dy&T?J`&xo(fVQUnUS8K~R^D3nmV#?uRCt@d$%S)k4&Ck62j1?_|hf7kc8Wp9x8)tAWOEdM3 z3d4J4>DB(GR-rlrq;IWorxI#fz*RPV=2IVt&xg?%1CON`WpO!IdQ;nOH^t#Q21uuO zj2s&`xPyDC`HV~04+}P!qK$HVp9)#J4fJ=t^)XkMD$#VN3b`huaXo7V(OjwdR&B=E zn|%dlU!gaEX6_};=6tF+pN!9719Yy2C*xk-xnw4unV{9S=&m)|XNNxjVxCWh=8`@7 zYnNVHrgs+UkAbz)CIdAq6?wQ$ckI(P6Ls56jp;qe>&K&q!=eiZ$1;EVi=UhgxAT``OxSHnJ%S?P`lo+VT?FsD^FrZfiQ&(+;b* z$9?N#XWM1lCbzmH3GQ>}kd5n(cc9xnF;T)Bj4x!hyn%)7dXMyuTC5ku0Hy$a@7vDw z*7m)tNVba={ND%XSicqCs(_o$Vh@kFr4x?sg;TNN7XBmulrKmpI4&UtUO4Igh>ntfoQt zDs_NjdBLo`70C4_vcuN10heS3uSThrb}m$F11 zGsse|QI;08@6QB#*yX%*vcp_=r1jlj2`u8gVmO(6?cLTW%U#LYb)kMQdfR^va_LPN z^SeC&1`54Xkq=(%g}3+NN5$SD_m;SKRo_3w8{6+{ZMn1UvezxwT*>1;Rh`eK*X4@3 z8BgH&ixm9ngEe;5H{Dc!D_-=8E8@VG6~idj{DYs2S);o)du?YK-y1*t$VDBR$ETa= zmw&P5<6PWF58vEe-#58y-<@xNY1_5z2x8;+6s}g+w_V;(OWntg5e(cA5srPk9bJ`FBpZ=)DMDaN2D~0z13HZB|X{Y zVqGSA9u`_0mUzCii@w-bm)D9a!-v#{g_UTDw75+FMO&LFeArcVxz&3xC3|KAKD}sk zK9yD9cw?bQQG*|yxC3LzDKAx$@ph0aDLAOLg)Z4`Fo|Xg@B=l;emA+3HQAFsS&~2*l;=2< zMA?c)d6asXluF5kOxcu9_>@q2gi<+`L0FalR@s7BsYM*5G+miAUkPa^d4|N6g*Ql( zC1aL0h?XRymNm$h9kZ2Gg?$N@k*ShCv=dHs69J^BmmEnvq^B`qsFHB$F@vcCF*!4b znFEOlGjjQKfpdOY2YhK2JezYlo``b<)K67KPuSF!3dx3RxLta8bGay(p~;Y=8B0R< zdlY$^z!HX+$c~u!J%6cFuNi(wSWMxTn0X~)C8c(OLy{p@Tb{_7firpwcAWiqR#*p` z>==j*S&K7gcjcEcve}N)$#c$`bvI>>s*;`3xth>eRfGdy)>(7ANr=4(YG)@si+2Fl zH(|`wjpAc_9{G53HFUiQp1Lxambj4r+r?jQ*LNHPpw3vEtR+6_SyB$yjI%g~py+*6 z=b-O2mVFp=i8qa~H%{89kLKxJ)rn%%F_+F+WQHk=v-ytAbbIkgkSeF53#p)(^?5G3 zWB!RMhdGNhx=_^gQ#Y!63>b+_hmxc+ebZN5fW?n=`J)J?O#+5s+1ENV7o{hIpb<)) z&lym#i7{AuiDPJs4eE^{sG3cyn zt0qaS4p^8#RB$KgGsxvR5>O^7rGwG_VQ}{FIxUiPHVFNQj=9(C$%ceD~S5ES#npt+}r4VYjSo4i{YMwr|s?q7UgVmj0*HbV{w%W?9Qlq$X z>RO)np_Z4lmWz+`x3rr3oFB8JD@scIIfpNrqpae&Gis^?3ba~x%r4_ohu^GQs zyP$Y0y`*a@U7NrE9@ejg%DflaxX`T6x4syn!~HMC;l!Pb|aj>chOLgtbbRn~JaZs)bv8mO%5E zuKAC^La@MuzGi2qX3Vz{d#`KEux(7m>}kctS}M;}m%So47j>BC?K zpVhglf+)ZLAR4vw+q|hP$b*ZU={dHCteuJ6USPYt>dCl2T%=fBO&_^mAx58+*P)K{ zospM|a4V!WCbt%Rbk%#p?KOM#ySRiKpwf(43|!57%eu&$&9+HZA;!(mY-9%f!s8%3r3>yJfSFBre^A}ip+@jX}|cKsNlS)vzN@}jHWWG&ph{|an;Y2 zY)(pCb+02}e)PV*+mquGf3AD%Eb(e+KU}GjeRy@oM969mj+AJpF*(bd%ksz zn5JFQx_#HZo!5|^q0lRJSG`PC`p0`5Hz4b=$sMCC8_5hz$;Exa&pp+^G<0l@c2G?# zkUZ6rjI(XM-KuiQ+LXykw#oK4RIzJ}mwPp%EY3)6qJV76gDTQoO3P?X-$%xESI5f# z`7NlDYPn%M()dlg!CkS-#M5V6w0Tp^a|^O<>&(2h(Xv~4;@waz9pKa~xYk_K*xb~r zJEk4J(#{*u6*_+@ZJ{1q#ol|sQ>)He!_N5UUET%H?JeKEOQj>)SGks_T@?wYNb|M*B>6z zt-QTMZqlY2z4d$H_LSkbb<{)y`AZknZNEBHBdM-D(Zq+6~r+-l?WK!Jl5|rB~hmogR*& zTk71);vhWbTm8oBYQiU7GjsjLcb-LjE!@ib*9;rjdzR}}RM;w+*u{>**xECij@i$) z?98rg&i?Gg7VXk*M%2DToNY7NZtI}UX~Hh8TAbQmEbeQG>j&Pm+}X``95gF6+d3tg zs;*l}Cd)HR>nfZwx9-Mxz1s2A+N}5QrtYF43z_n$Io#Bmf5qeVj_O@q*4iELl*sTd z+sxTr$Pl0JwmH-eZ}Cv>>Oc(ZSx#P>JXPQA$(XgdoWq>&Ew!+Vwr3#{}g6-dyH9zu}78 z%^nWYjvnHWKH>|%?+Yx>Njok3fG2V@>MdPYSb4RONWQBX#mrpy+xnB>^ zJu3ATj_KTe&?Y{Qt1jd{{@V$z(1WkiKyUVQtUJ78<-9}DC|%xIW~G!0VPD2el^*v~ zul2@#<^&9}YQFVsF1UWLqxK%>S(Ckre)^y`#RXqf;fn z)QJB1G9UW$-ROUNiI3|TW|dpOt^;cWf}~# zjg0*U&iKGS{j%Qc>F?L;U&G%%MZ1pRF#NqV6aVP${z1Rn2}JDwhzSCRIFhA#qN%zn zfcwJkI@7f+wy}QmeLbldfWu=VBr;S(AG7IvLZi|twQ9X$o50ku*iELE*)h3nKBLp> zwP=g#8ix-sO3c3F^ZGr%Pja8YeJS}B8Xh7hDjoou2+Gl&*ey~rDO_S^Vpg7LdR}sx ze0qkCG?qLf5tg#jC``b{%1%s%zRu3pa^B*`>Mov=q|U9XXdEA#XdEn?F*F}MMkGU zTNVKWvm^@}ile0tUI}gl2O>+->|hypJAO%f<`3gBjrh#}c#J`jgvEr%1pX_@>|_>s zBIp%M!EfWtYR4#S(-zR@%b-P(MbJlLpHP9zFeGG#&7jnvRjox-w@z8qfjIJUB$E=x z%B28dF8!Leqr`W$G$g@Fkg8X!b+OotCMS-nFf*tD<+*R>z$DVT(d_9pAXa5*;Z9qc z)Eeb!8ZZn#2`#LYvE|+x2CJ4SXDps&oFjdard(#p#J2sILax)btw&zTi_`Clotg=2 zuz<~XOn}sYE4@q8Af3uA_eCYx*mP`_wM4FVeKawe(_2yO3vG5gVc1&BnnjD4Btf1v zgX|r|+gJ&OgGEC=th_u;j`+p%Ls@&5Kt@%8;bk@d(OX@ymRV`kotIjDwmFDWb!45> z7;_U^8-Hw=lClu_Y;gO(NEp?8&N z9ddUDkP_xMWNZ9oailVFWhUd24?dw=e30bSik6~W_?al$uxHW%7EoD*li(SZ9W`Q- z$yS749(7!pgthr07gzRG$Ci6?`KFdIsBWnx`bH!Wyfrp}v9Vh^5Y&tFF7|!K#S$ zl+Y=!!xCF86TTYysx7AMi>!ZrZ z`PdoKu-NV~;k-cjju63VLFE&M#bV9wW)I|s$78O)> zX%<~=2QVbC4f)PY;aV9_{9S!#B{vO9G>SA?I>ok*&8`dC)nn z9AelFH{($1jV&3*oh2P)l17uJhQ^xFOW19%g)AEiv~l5+Wgvez zM@d{={xMm!flxYk((g};u6o=H@~n4-b|25O*`pON@xEV*up!;iMJ1-i; zb81GNy3;%~DX=(fN}VMh_?$T5267X8kEmLuG6Nnk4|hX{1z9n|L}(9JA-sd5wzrE& z{RxKrBA~y5wL(37>O7kQ)edzy!w#Cug*O}`5qFisl@&3GN`%!BLAb;xLXl5Rv|$vh zXvH7aYE(7U+7-nyEg#w9i_)6^7OetdtE`PcSY7nNwtAt)LbMSVZ)BFZ#)U;QYVm_q zGzRB>kMwxQMA|g*#=8C0%{+~y-p#I;!2tsCaC>xKf6U3a-mynD z%gdiJ0oRz|O%4ppOkOkpOZmCe!4jJoqNI30YRg#m^PkKZraMELJ#eB?1Y4Vs?fwI{ z{Sb$Dkip9Eh9^&Tk)Wpty5~R<@=WLfP^4Z$Q#7G@Qt1`-In_&8U8WQ}n9eSm1sRHB zz(=xo!U#sT1m^qR$3BLf&mU!d7Z{C)Px?7EmHjK_VoC~7xpuCUJB<>DtjfVGdN8Iz zTB9PP8bJ-xsgh3^Autyxf(AB8mNd)YD;cQRA7E98gk3CMD{(?aeD)Byl<8(;nbmg4 z(1fXlWM)-Z+GcWUj(y1CM0!};J38Wwr+qDNdpm{E4%WBA9j+Eyi$vlgH@TQiXaN_h z+~-2q1i+PTbgN7M*y*xBjMm+560xg-IOc-8;vJ%QXVcm7qSuJVbz+~QN{w{t(wieV zED!jB9W)B;vgs{idH<%@uLxGFr6GtkEGdj6Wi7w^6>fh!@n7imQkV$Y&SA4dBY#fj zC19b0etL2i@&t6juWfL9SJ_l}whSoxvFBHg0-&DBB?&4LaEvyh;^paA#499mMIKBf zW(a4iuTdxbMA2b~cFk-Y#&Keptm6@{*SRJ3+ghF>rr$J112;zTQvNqL`*cml`LOad zOhOkM-}KB+hB9-vn9J|#^l+eLwzS>}s_mIPlvfX#8jj{8ew>sz?ui02U zX32STh3G{8D{;~DUG1t6#q*uow*v5Rf&V!|%G%i8_NBDV?Qd_%+u$B|D8x%radp7$E$P49a7 z<02n9$x9A#j(7aIA8$j*4bbnG%Oc_^PdQ#-4s$20oDm_PfXRFAbCL7h05hlg)qZaD zqf1=>;m%IMz#-1_*g`$(Qs)!{faVe*`3{N;U+d8aFW^n>?2S4 zUF)463PfMYX+ZTsT=-qz{sG|o`JDFI0QdP`@g1M|(yV+ zC7=QP-wP_=622b3W(tx{@xqg; z7s4SSq8}hOq8{GhJoKRo{NV~tVhuhbB--5=ZlcI3;tViiD01Q;dg2d&qA6nk+$gR< zDY9b8Nnt96;VQ;r#ku0r8KCB|f(_E5DpD67?BVuZBGV-v10Z8ED&sOTV>3GAGeToD zcH%E$q5(wXHDY5nYU40YU@`7u#MvCo$y_B8VmQ7W&UxdiwA?M~o%vB?2-O}twj(*d zW3;8CbRk?m>f=7TV?8cQ&M|^H3M4)HW2^vVLBiWXA|$&hSWYukw&_n7d${v3gu7|WlIXl4V)iTnGRFJNhEL2mk;8 diff --git a/SheepShaver/doc/BeOS/history.html b/SheepShaver/doc/BeOS/history.html deleted file mode 100644 index 8d016a73..00000000 --- a/SheepShaver/doc/BeOS/history.html +++ /dev/null @@ -1,59 +0,0 @@ - - -Revision History - - - -

SheepShaver Revision History

- -

V2.2 (04-Feb-2002)

-
    -
  • Integrated code from Basilisk II -
  • Source released under GPL -
- -

V2.1 (31-Mar-2001)

-
    -
  • Support for MacOS 8.5 and 8.6 -
  • Support for G3 ROMs -
  • It's possible to select which video modes are to be used by MacOS -
  • SheepShaver will not use up all CPU time when "nothing" is running -
  • More stable networking -
  • 16 and 32 bit window modes -
  • Small bug fixes -
- -

V2.0 (20-Jan-1999)

-
    -
  • "BeOS" icon on the Mac desktop to access files on BeOS volumes from Mac applications. -
  • Handling of removable media (i.e. automatic detection of disk insertion) -
  • More flexible parallel port selection on BeBox -
  • Greatly improved Time Manager (higher accuracy) -
  • Fixed "audio lags" -
  • Option to ignore illegal memory accesses -
  • Adapted for (and requires) BeOS R4 -
  • MacOS 7.5.5/7.6/7.6.1 run better on some systems -
  • Small bug fixes -
- -

V1.1 (13-Jul-1998)

-
    -
  • Support for more machine types (esp. PowerMac 4400) -
  • Corrected time zone handling -
  • Volume list in preferences handles dropped volumes and files -
  • BeBox: 16/24 bit modes have correct colors with a Millennium II -
  • Video/SetEntries didn't set last palette entry -
  • Mac programs trying to use the (non-existant) SCSI Manager shouldn't crash any longer -
- -

V1.0 (18-May-1998)

-
    -
  • Initial release -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/icon.gif b/SheepShaver/doc/BeOS/icon.gif deleted file mode 100644 index 51368b117dcc38bde6f0ac4457387bad5fd31efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2011 zcmaJ=X;@QN8a`ma0F_2r3>syr9YKRdt|&{30R{<-bXXM(#fag`B9wN_V^q{=A+nS) zsfZV0#voXrBBWwjq{C8V8oAmAiW&hU$f^ipfwK6(o$vCizvetio}BZ2@B6*)d+zn~ z-{b0bh=+J+7SW5zWU^Q+Hk)l@V`Fb`@8sm<>gvkl@%VgxP*6}rM1)W%jEjp)NlB4N zBvPp~BO^mDmlFh`R4U8L%2X;|kNQ7=9l#h_~&oxl?|H}kMQ4~pkNRlE*3MVOyq!2+- z1Vs`QK~OkBVFZP6ioz)prwE+FaSFpJ1W1e`F$ySfjKVMq0fy!P5Ol#YfdGbZ5~$%z zk_1V@1|vyCchP%-AaR1k2okzrHk1jR#BmbCNd!8e6(b3Z#4!@XNCXOKfuIN^z)T$Y z2?Xu5R-gku_zws~OQ6|d;RJyZ&_z3eVX((>0s|blg27P32pl6Yj6lOOM7yU8U=ch4 zKZbAwwrSxs9@K#xMEj$)0v+%H0jK~`P=^Cp7>*;FgLVSLV2@!qTm?m;<#g#>FsjN7 ze!wS$NT))p0RVVKba=FL5C?cr2SUIx42Nkz2YiSYNaq4|IDm!d`=PUdxPcZNf(Yn? zXM-Zqa_SH>j2zfQz+Iu`oah9h6MFgwh`9o2M@W?i-#R zic7x%^t*tVP&4B2RmzsHm}XlzOr@cy==DG&aQ87d8f;)d}O`ax5d5+ zmSaSjy0a+YoMZTxj7;aD_B`&vrR?}a!}qTmgztQW&0Ci<*+gX&99V;ZCKXNIro zUx}_mv&SxUWQBW5obpD4+sd(8U5{6`|Pg#`jX8>{Fac7IeC4C*4yGZGV_lkcxjp&WfAFXJ(c~kUE;ak3$_VG zO3O`lB3+u|d+qx%*Ie!he5O7t)uy`WB!^}0OS8Rcp87`3AwK#+C8EbOUzO|(=sZ$< zWv}I(flH!24lPHf%DZ%zk0z&-Twx1?I?fkvA1p~TKQK3tA9_IktwG}5@*B#eb!$fo z4?Z>ul`e|Ph+WO))@6wFdjTFoewti<>^!DY;RHgAey7hB+_vXsW6Yg$F=foLdePM*x!$6%ppr4(*sW=> zV3}7Xc^#Nf+U-1%nC!VRcwSl>65=u0V2EX{_47OH+kQ&+u4rIq zXPVV7DNcp?_~me&o5Xs;NZ;{&Y3vrmeg=B5VaKNGl{-!es~@_(c^&kt>0+<5@57mH zdFQ&7K6>8tmrqu5IL2rAFEHOm{k6M}omu#@a(DRU z|K8nL8u@mGv~i&ZV=f`p`o%-iv)n{A_3DVnUu~{`c-SFOkFvet>R)x%BED}$NN^im7Uc>;BI}E)Gt^X6-P!)J4+j7_sV6a_ti!lzWIs!y(ZnM@L%sW zH~9IOYFR5>D|F9n#JSOr_F4x%@RL0rzMCgBxqu4!KE$Zr<}ItTKFfV!GIPjr>lT## zUY8v@slDlNz9aidJ>m6g-|CtEAUi<`&-@wN*W#D2WB;*9uwm@@&l#^LL!y2(H5sa7 z)%R;WSZ+|`ltE>Hf ze^XOab8~Yb5a{ge4242Mh;TR@iA18&==k_}EEbE$PrG%0~ z38A=9Oeo??aV5DDTyd@#SAw2&Q9n$(VSHJ-e0AK-9 zh~of@aZVaTD?u~t8RHm*Qncc(_Jyg>*Wd>_VWM_Lvq1s0k~U8(2RYP(9f&|Nnxh-w zfJd63_62bqV3D4W_5yYT779TEdAJ)&(u(V_87+S;6POjP_@o^~DpbPG6=jg3D^Ujn zR=8*v00a~e)f)8V^)N7R+#OY@zX1I$kOi>^a?7LPiB{Y@cRV`ers@2`w|z$NdKVSu zRr)zusO5s2V#@MZSOtSoH9>iRo|bV zekHGGdGe0Azx4dlm1MOi-BxxafA6$sXM2nJla!EA*N;l3hOp zJwvy8{hJo|RP=w*ej~c^P*0bq>w3mV-mT87Gsh24Wj%R!WJ_l3Vn*ceO}?LPDYL&! z6wHsf4h*;58aGugpNsnUcMY3%E?qh}ai_JSyZ6nz*LDwG8@<1olCG0irOo93Pf$`zLPS zun~xEtHSRbi8rRR3R1L0OEq;8>8ab8se(l_z z`a$1~Zx6Ow2QJQeDtDw^+HLaJ8^OlWd(|JC;tNliPj4?af)719mRDxoVl;R%il3{! Kyw<#mUj7$_>qdM4 diff --git a/SheepShaver/doc/BeOS/index.html b/SheepShaver/doc/BeOS/index.html deleted file mode 100644 index 52328333..00000000 --- a/SheepShaver/doc/BeOS/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - -The SheepShaver User's Guide - - - -

SheepShaver V2.2 Installation and User's Guide (BeOS)

- -

Contents

- - - -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/installation.html b/SheepShaver/doc/BeOS/installation.html deleted file mode 100644 index 105d9c8f..00000000 --- a/SheepShaver/doc/BeOS/installation.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Installation - - - -

Installation

- -You need BeOS/PowerPC R4. R3 or earlier versions will not work. - -
    -
  1. Unpack the SheepShaver package (if you are reading this, you probably have already done this) -
  2. On a BeBox, you need a copy of a PCI PowerMac ROM (4MB) in a file -called "ROM" in the same folder SheepShaver is in (but you can select a different -location in the settings window). SheepShaver can also use the "Mac OS ROM" file -that comes with MacOS 8.5/8.6 (look in the System Folder on your MacOS CD). In -order to legally use SheepShaver, you have to own the ROM the image file was taken from. -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/introduction.html b/SheepShaver/doc/BeOS/introduction.html deleted file mode 100644 index f3356787..00000000 --- a/SheepShaver/doc/BeOS/introduction.html +++ /dev/null @@ -1,45 +0,0 @@ - - -Introduction - - - -

Introduction

- -SheepShaver is a MacOS run-time environment for BeOS that allows you -to run MacOS applications at native speed inside the BeOS multitasking -environment on PowerPC-based BeOS systems. This means that both BeOS -and MacOS applications can run at the same time and data can be exchanged -between them. - -

SheepShaver is neither a MacOS replacement nor an emulator. It runs an -unmodified PowerPC MacOS under control of the BeOS at full speed without -any kind of emulation. So it also uses the MacOS 68k emulator to run 68k -applications. In this way, SheepShaver is comparable to the "Blue Box" of -Apple's Rhapsody operating system. - -

Some of SheepShaver's features:

- -
    -
  • Compatibility: SheepShaver runs MacOS 7.5.2 thru 8.6 with all system - extensions like AppleGuide, AppleScript, QuickTime, QuickTime VR, - QuickDraw 3D, Open Transport, PPP, Language Kits, ColorSync, etc. -
  • Graphics: The MacOS user interface is displayed in a BeOS window or - full-screen (with QuickDraw acceleration) in resolutions up to - 1600x1200 in 24 bit. -
  • Sound: CD-quality stereo sound output -
  • Networking: SheepShaver supports Internet and LAN networking via - Ethernet and PPP with all Open Transport compatible MacOS applications. -
  • Volumes: Any HFS or HFS+ volume can be used with SheepShaver (this - includes Zip/Jaz/SyQuest drives etc.). It also features a built-in - CD-ROM driver and a driver for HD floppy disks. -
  • Data Exchange: You can access BeOS files from the MacOS via a "BeOS" - icon on the Mac desktop and copy and paste text between BeOS and MacOS -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/memory.gif b/SheepShaver/doc/BeOS/memory.gif deleted file mode 100644 index 9867b003e7f6922b967f969903d0154343e986f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5510 zcmV;16?y7MNk%w1VVeO{0mJ|R|NsC0|7QRHGymg8|H}aXuM_C#=-AlU%a{Pj$jHFJ zz__@$u&}V8prDwTn3$LVm}UTwkdTOoh=72AczAebnEz&G0AOHXSXfv41ejEjAQkdcy;k%kYKn3(L&u@9ODr*V65?e%=260B`6DH?E*LJ;x9bK(K5dqJ#?@&VvP!;lwxj zF3MVyEuhDbwZ8o-xaMFUbQ_@mDRagl83GH(EU0-Ib0r5478IgXDeqWI0x*5Do4AZ7 z&Xo+=>||q9X3u%fph^|G5a!K!51egKc&8)CuV5jGB*&(JNjye3KtRfn1JGw#Wx~94 zG-2GT$JDa*;C7}lw=k8-g}6&eaU|b97XWQ`7(x$R zdz+3bF{kc7ew|@P)^z#>iuN{88y?Y^^)hrL)d{5T3#$>vNDg14J zyGPw;kAAwvCQVT5@yCY$LjvaKUmJ~WXWCqo@im)9bY%A4h8rd)4s-O4c1KpnK%kIo zM$v{>iSpc(lNuxjXC78JT{V+Z z=-ftfI7H=@81;q7l1+9QRw|l=IVF~ESV<<8%fRH+mc)7Kre?adBIlVH?MUZFF}|1x zmv8pzk0EykDyX1*`e`UGfDWqYqS#z8!=sQ!D(R$@R%+>^jskGNrkr-_>8GHED(a}D zmTKy$sHUpws-Yh0DnJrs%Id7N)@tjmxaO+suDtf@>#xA78mj}EN?`1<$R?}ovdlK? z?6c5DEA6z@R%`A5wb*8>?Y7)@>+QGR7Ava+mzHbpx#*^=?z-%@>+ZY69x!aN4j5qX zz4+#<@4o!@>+in+2Q2Ww1Q%@Z!3Za;@WKo??C`@2$2+gQ^#*J4#TaL-@x~l?>@lhm zk6ZD_B$sUR$tb6+GOHm=Jo3sg$1L;AG}mlu%k&yx^Ugf??DNmQ;!Ls5pDqy90zfCN z^wLbPEHt@9d+LD$n>yfus8?^Ab=FOH?e*7Shx+u(opMbo*Jg*U_S$UwJa*KbT8%WP zMmvMFGY8;(wFh<2O~ElnA5b^nZ5M9%;k>>r_AylFJ$K-FbGmijS6h7m1sn)|Q{;lD zjrixFhc34NxGuw8GzU~umpSL0?=3m&f&Y!c+@jZRd+3Uv&3f6dM~*h^SucQr2Nc|H z{PAq(E_LIUPhIuoT1Wpo<_j#aIpL5aul@E)E8pqh*dM*A23eEud+&eqef8knx9>jB z-e>Ij`}EhZa{Rw)P`uH_+wcGXCc~evtjCxB0q}qb%$NWZ$iN0BZES+8o&+aI!3tXN zf*8!81~@P#mpp$un8!y1}^bo6qd4tEGN z2=efUK$MvegGj_8l5B`ZOrjDkhQuX0@rk%^J6yBy`>B*#l_{>q!2vRdOXhs;$4j&R}J z=BVJQHKgS;Rl(aE;j-DgRdI7u{G^=Z4mzuQqK%>Ztl29&8BC->Zkp%w9pG-Vzhl<_ z4FeJNWjp&RP~wr4aLy?bK-xUC`i^SNliE&?Syr0b)p^4UX{cuUx}PRfu9KsH1~OXI$QkW! zFg-x?`d7}b)>5yotL#}Hdr!RXt$$-h?D;bLP02pft0)8OWtYjiYZeuHB_(R!G(gQy z<&>9dy&T?J`&xo}fVQUnUS8K~R^D3nmV#?uRCt@d$%S)k4&Ck62j1?_|hf7kc8Wp9x8)tAWOEdM3 z3d4J4>DB(GR-rlrq;IWorxI#fz*RPV=2IVt&xg?%1CON`WpO!IdQ;nOH^t#Q21uuO zj2s&`xPyDC`HV~04+}P!qK$HVp9)#J4fJ=t^)XkMD$#VN3b`huaXo7V(OjwdR&B=E zn|%dlU!gaEX6_};=6tF+pN!9719Yy2C*xk-xnw4unV{9S=&m)|XNNxjVxCWh=8`@7 zYnNVHrgs+UkAbz)X+~bB!3JukjhbVhw%Mr}ZM#xyy2O(vm8&f+YSGR5)u5D@$VT<5 zUT-LLZJNZW(s=7L8k>`1jrARm&20Cfme|dXw)UQ_Y*%?( zzfJD8QG44tWMjG49m#N`8;j~@x4bd!?um&q-t*2ku1ELod$&s808iSv?LE?E2mIhX z8~CpAjWu$f%9y_#vrn-p+sFdb%PL0r`!FhTY$}&=rBXPz8D7nY-VCcT9dUyL`el<# z&YynPIO3dlPo%+jp*Rm{$m_lEf1eGjCGFo#9j;St;uo<%FB>)gW6NcN%G_`@m#fy2 zu5(g}Jl#GY6=@F}Sq^`gr3(f7cS(!!9Up)LU3U7@3kP^l5TSe~X$9fI9?*1bB` z?2+whK4Xq}rqMjXucJKYimYA8_q>p$`Yw)FI#7r=uH)RzJ@k+qc)V$u^rh$7P!GT5 zs1)4DuCF`ngU@`AT^-(bZ@%;|_I!UYfBM)DR`riR?(BPiSKF8T_s8#Mx?}zNLxj!T{}| zi1&hrzSfDpCW3BAf(92lnusrW2!PuIgoB7UikJZZuK0?s2z;nWZ=tw_N7gnJkc+yw zi@7L^v)DAMIEpjpg1?w;fv9||Sd8=+jMk=%|Hq8o=Zxu_bp1sXfW0QUzs^akq2uNPtqq zko%QUte278lQoOiPYYI(<#du3riJlXO(gkwf#-QBiI3SNVC}?AH`$UT7Lji_k)VQm zuSJeIsgu;vQtPNqG=-E9Ns0Yti`|%%`X-S7R*8LBnU&JFm0ZbuUip=!7nWkVc4S$W zGIy3}iEwJUmI2q6Zh4h5DUxvsaBx|d@&=b2gqOyqmlyDtfEk!xz?Wy_mpqV-gh@q) z*#RA31B|IDq~wcthkB-xOb%x;6_=RnH<$7!Oo##1Z3TAkj zxpm(4I(Zjj7FnOYMO^%eWT2N#OF3KrbMsqwvs?n&oSYeip81@i`Iy_Ko$zU%dMBM3 z7FmJCOz7D;KiNA2re80YHUkA*J8F=b}vC>SGz{oH=ld_#~Nq26H9Dq^uc$QaON~`8}u=OAv>V zx{{?ILugTIX9=2&()0sgx@rbOwc*w&_UI!1I_r(blZcxt9_ z+Ki&ImwUQIekquOS(Sn6KS+uLhZ`qLqnRjEa0hDT;nNSbo5sc2ugKH+&pP ze22xH9amdA_o{g%Vl@SY$Mcl~raoQ-)*?fHXv^ zoDu7eX)`z{D^1}upkJ3?yZ5X;HKQ7Pt5iuU3lMBJu&A}lKz=!sLCZsWNv1^`M0%RE zf(o$J$h3Cqv_K2BQ?#`IR9i$=+dz@HwOre^DkPxp{X4Yzo=36!^c8@RX7w^D1UcEI|z)cvqT$AP-%O6r*ac#nr(BrnR~itu(?wzh;d4qfrELNS8?-+ zWrt(BsC&C&pt@mOiBo&5<7klC`m8nURUa~VgWrWqAWmYr);yvJL; zLXf<1!@Hm+ULq!*i@sH(z6h+q5PSm+ELjdrMFJeb);qz= zJ4HR4wD-%obeTj8fWajE!K;gmt$VdqEVKta!&)T6Hhe%hoWuXK z!#r$1KK#S<6U0L7Y&BfOPDI2=oQg-h#7U&YPJBF29L2_X!V;OQR7^xuoW-KE#axVR zAk48}+(2GD#)nhJX3R=WoW?P{#%xT(_?yCS3_xf+$6-^)c1(+5?6`T1sBYZHejLYG z49GqF$Amn@hJ46IEXVsdgM7-y)5)w1Gp_u~Dih1Hj54%b%b}LZQ;W;yX3D(mNxuBccO1;ZtjDR0 ztBqXDYOKqKtIU#2%+73T&>YQ5bIa5$XVZMmKV!|>tbN(s%?bC-;QYzVJkGsb&gKlv z=$y{Oyw2=w%)2|4o%_!FcFa3V&+x3g6^zfoD9-#WOaA=Ne-_XJO>6F4(9e9(2wlkv zz0l#@&<;(`dz`-!y=Men(Hg_e7=0=lz0n{!(Q@q3vwYDa?adHf(j$G+C~eCmz0!u( z(k=~tFdft7r_wb2F&%x=2sP6>-I_ez)8_QkK)ov5NVi6P)JUDwO1;!f-PBI~)KDGO zZY#C_Lk&N?Th%+GT3D@1^1RjEbJbowNnjn;gEZD;&DB(T)>hrsYQ5HJ-PUEs)^Huy zZ_QRxeb<2b&#H9+UMoVY_RD*{01z|S1k=Iz9N2`N*Z^bL^o-c{g4a!bFN|H6kj>P! z;@B6U*qZ&=_A=RSnc17I*ni!?a?MtPZ2*}KC!p=wYnj?#GTIbe+97w^uKg8~wc4<) zjkOIDw@oXUZ2&b8+7ENvot@j(=-R^VFugr1za8Ak%`n7m0IZFc$o6wV-t|2&=dCLL z^j$Ct;0y|2FCGvu1)ebXZQRnR-v-kF&d>n+a^MH9F#Vk>|4lF+FyIbO;08|N?JeC3 z?u-mhFb)pkCEhO+j^N?#+uDs#-0j>LKH&G_3;?VTs>P;{Kehe~>N{u*PIRG z0KVZ~J^?iDSx(toelS6901A)+IbP&o?%`rC+g9h~1~cb5?&Sp@=qZlm1(V?K zZRQ1Y;!oFw=lkU6050J6k^u#-<{qHwY;FLa?&ct#=udty4t@;(8?NSe zp6P~u=#q}!V{YmD&EFr6-{>0W30Kr3vmP*ruH}jz?Eb>*4;SlYUh2kv z?6n@^%J}2Wt}n=bGs=$IxIXRtGVE|(?Ao3$)m|zW{_Xq1?QtpX_;Ue|rj*)|jdJr3vh4g>Sfy7m6pm95m04eik$@JW5y*PiYLW9!}Q*a~0R1Ru(Q z-Pa%#@t&;J1|QXW&E#|KFCpYlwE@+==LEwt}4Kl3zS z^EQ9;k`hWKyz@LC3GepuH8U*WGW0}W^hSU5NT2jdzw}Js^vja*P#^URQa|-nU-edB I^&tQNJBtH3EC2ui diff --git a/SheepShaver/doc/BeOS/quickstart.html b/SheepShaver/doc/BeOS/quickstart.html deleted file mode 100644 index 62f9be15..00000000 --- a/SheepShaver/doc/BeOS/quickstart.html +++ /dev/null @@ -1,38 +0,0 @@ - - -Quick Start - - - -

Quick Start

- -The following is a step-by-step guide that shows you how to get SheepShaver -up and running in the quickest possible way. We assume that you are running -on a PowerMac that already has MacOS installed on a partition of your hard drive -and that you have booted into BeOS. - -

-

    -
  1. Double-click the SheepShaver icon. The "SheepShaver Settings" window will appear. -
  2. Click on "Start". SheepShaver will try to detect on which partition MacOS is installed and should then start booting MacOS. -
  3. If this is the first time you start SheepShaver you will be asked if you want your -network configuration to be modified to enable Ethernet networking under SheepShaver. -If you want to use Ethernet with SheepShaver you should press "OK" (this will change the -file /boot/home/config/settings/network; a backup of the the original file will -be stored in network.orig). -
  4. To quit SheepShaver, select "Shutdown" from the Finder's "Special" menu. -
- -

One word of caution:

- -Volumes which are used by SheepShaver must not also be mounted under BeOS -while SheepShaver is running. You will lose data and corrupt the -volume if you do this! Don't press the "Mount all disks now" button in the -BeOS "Disk Mount Settings" window while SheepShaver is running! - -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/serial.gif b/SheepShaver/doc/BeOS/serial.gif deleted file mode 100644 index b491d769dea310cfd695607bf91ca7b1749fd6cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4844 zcmV41ejEjAQkdcy;k%kSIn3(Lpp@9ODr*V65?e%=260B`6DH?E*LJ;x9bK(K5dqJ#?@&VvP!;lwxj zF3MVyEuhDbwZ8o-xaMFUbQhriDRYJ)83GB%B&c~Ab0vlh5)`6TDeqWI0x*5Do4AZ7 z&Xo+=>||q9X3u%fph^|G5a!K!4V+z2c&8)CuV5jGB*&(JNjyd`I6%q}1JGw#Wx~94 zG-2GT$JDaT;C7}lw=k8-g}6&eaU|b97XWQ`7{Ux( zdz+3bF{kc7ew|@P)^z#>iuN{88y?Y^^)hrL)d{5T3#$>vNDg14J zyGPw;kAAwvCQVT5@yCY$LjvaKUmJ~WXWCqo@im)9bY%A4h8rd)4s-O4c1KpnIG~Vg zM$v{>iSpc(lNuxjXC78JT{V+Z z=-ftfI7H=@81;q7l1+9QRw|l=IVF~ESV<<8%fRH+mc)7Kre?adBIlVH?MUZFF}|1x zmv8pzk0EykDyX1*`e`UGfDWqYqS#C@!=sQ!D(R$@R%+>^jskGNrkr-_>8GHED(a}D zmTKy$sHUpws-Yh0DnJip%Id7N)@tjmxaO+suDtf@>#xA78Y=^uK49#z$R?}ovdlK? z?6c5DEA6z@R%`A5wb*8>?Y7)@>+QGR7AxxmmzHbpx#*^=?z-%@>+ZY69x!aN3>aYV zz4+#<@4o!@>+in+2Q2Ww1Q%@Z!3Za;@WKo??C`@2$2+gQ^#*J4#TaL-@x~l?>@lhm zk6ZD_B$sUR$tb6+GOHm=Jo3sg$1L;AG}mlu%k&yx^Ugf??DNmQ;!Ls5pDGZQ0zfCN z^wLbPEHt@9dzt|Qn=+7rs8?^Ab=FOH?e*7Shx+u(opMbo*Jg*U_S$UwJa*KbT8%WP zMmvMFGY8;(bq00M9l>r_AylFJ$K-FbGmijS6h8R1Q-Z@Q{;lD zjrixFhc34NxGuw8GzL^tmpSL0?=3m&f&Wdx+@jZRd+3Uv&3f6dM~*h^St~$61`*tD z{PAq(E_LIUPhIuoT1Wpo<_ajVIpL5aul@E)E8pqh*dM*A1zD5td+&eqef8knx9>jB z-e>Ij`}EhZa{RwqP`uH_+wcGXCc~evtjCxB0q}qb%$NWZ$iN0BZES+8o&+aI!3tXN zf*8!81~@P#mpp$un8!y1}^bo6qd4tEGN z2=efUK$MvegGj_8l5B`ZOrjDkhQuX0@rk%^J6yBy`>B*#l_{>q!2vRdOXhs;$4j&R}J z=BVJQHKgS;Rl(aE;j-DgRdI7u{G^=Z4mzuQqK%>Ztl29&8BC->Zkp%w9pG-Vzhl<_ zjRFz%Wjp&RP~wr4aLy?bK-xUC`i^SNliE&?Syr0b)p^4UX{cuUx}PRfu9J&^1u|OH$QkW! zFg-x?`d7}b)>5yotL#}Hdr!RXt$$-h?D;bLP02pft0)8OWtYjiYZeuHB_(R!EI`dq z<&>9dy&T?J`&xo#fVQUnUS8K~R^D3nmV#?uRCt@d$%S)k4&Ck62j1?_|hf7kc8Wp9x8)tAWOEdM3 z3d4J4>DB(GR-rlrq;IWorxI#fz*RPV=2IVt&xg?%1CON`WpO!IdQ;nOH^t#Q21uuO zj2s&`xPyDC`HV~04+}P!qK$HVp9)#J4fJ=t^)XkMD$#VN3b`huaXo7V(OjwdR&B=E zn|%dlU!gaEX6_};=6tF+pN!9719Yy2C*xk-xnw4unV{9S=&m)|XNNxjVxCWh=8`@7 zYnNVHrgs+UkAbz)X+|EX8GX1;ckI(PGxgd=9X3@1&D9#4D61`Pyji!p)RUZaC12GZ zIHc>n@K)8&;U0sy#KE0yfUA4pC)4=Glcw-=Gu(X`@0iF({(?-drh?3b)k%l z>|_htE3n%gz;m~5S_gk(wXdCLK)<)tM-_JkOV7I+mTN)fyL6D5?z^siyxt-|fzEe+ zr-na#s-gb!x5vD5knJmh6Z~Di>z(qz0=sBce*n7A7kUW&Jm_yO`ck$%>ZUKci-Bz8 zr!G12*{t&TDu1)fXW660*K+H-`MuEhUeTlv`r_M{a*j3q`u@(o;)9QJovYmX;1B=r zOJB*0o8SBBPk+M2&-){5uU;!8Vf^Kfvc%WF+ok4t0yu#G1XzFucz_33fBg3`{`YYg zr*8|Wexvhl+DCp7c!9gpfI^3X9B3;VxP9DHLkHJ^c1C{=SbhXYFa}40^S6E#*nS}Q zaQnxC9rJ+}7=rJIG2cgnHE4nxxINvcgEPp38e@Yn*l;;`F*`_vMd*Vd7)&;YbM6## zQCM`r5`?Ukg{-oKOekkgc!M-|bVzr43&waCgN1NMD_q!x7Gs10S9JH(Q#FM*Q`I|M zr(#}rg_qYij+0r(pi)Fthl4eQY#1zVSZ!38cZTIS_$7ItB{fmlR|dp1Zd67Jrks8T@964AU)R74H zkxYk>5h;>iM3P1GYc@cSC~0jfnRYy|T~R?<%~*_(C|x+|OfQK`1<8z^$dYzMN&(f7 zy*P^6M2YU$lP&j?E-5%dsVPM1Wsap}K1Esod{}nBs5gJeWqo*+Ub$OLsWdTJeKR?g z++|H#BaGICcd`XtxrK>@2WCn+mZ7$f|3@kYca~b%V!+j0j;K*$`CzXFi!`-d-DsDH z=agu+mped{&yza5!%SotJ*r;W0Sw5v0 zjn8M52QX!w$#xUyaX)C5k9m@_=|p8oH>jnXyQxIIxl=z7oY6L%#wl^gnVkK$oXjb2 z&iS0{7M;>bZq!+w-gceX36qSuoh+xF-pOp>8J@;Ap5%E(=6RlDl%DFDlHJ*!(D|P5 zIi2!3pVnEQ_L-gdnV;PGnYYQG%f_Dn018C{I-tC{p9Wf<2%4bixu6WXo(}q;?&+UT zD4}9hpcWcL7@DC!w4ofjLmv8}4iusy%0MJqq6l=NC<;I-x}yHmqAprLFdC!pGov)x zJ~n!z+moX@>T40&qeR4`K#Fa(>301%q)8;CNGdu?x}?Weq`-HiPO70lI;A68rB-U9 zSem6Nx}{voqF(x?FB+y|Dx+jtrZsw|Xo{n1x~4nYrf%w^6bgoM3Z`=^rFHs0O`4}o zv!{H@aZt*B-hh(V#s(Ndn`joBuq{Sp|p&F~kld87bf2^9TeY&f>3aGP6 zfu)+MzsjV(TCA^jtjJ26!D^cox~#0EtkC*&uL_*g`g78Ht$UWO+A1@++O1w#t>B7l z;ySL;TCV2WZs?k>q_(c?N^kD^u09#B^4hEPTCc$RDbI$ln8vOA>M`H?uecJh0_%bP zTCh!cuLvut&1$5ky0Fwrs(A^qBzLeBYls$mv7o518tbhY+p)^{u^>B4B0I7JTe2o= zupFDRy1KF~dzTUmnlI~nG5eo03$qOyr4M_vwC1ur+k-y)vl~OOLQ8!?TeRU?v(JjO zwTQAzODaT*v{75MQ!BLpRr|A7%d=T~vs*i}UHh_M%d%mcvSVwqWjnHG3$kh3v1_Zb zZF{kAOR;eav2(kyb&IffTd;X6uzUNjeao+Zi?0y5kc3;fhI_b(o4AU*xQyGlj{CTf z8@ZA@xdiBxPrEa!b-B7EtVXH1gG8&ITV|Xax(@`pqzg);d%A98x~jXm&f2;*lew_# zF|s?m9Fw_}o4W}qu&Oly0QtKeG=jF;y9$tk#tSej$gjkEyv)ll$&0VcYcIMxz4!9G z&pExiTPx8!0nN+2-20EhJCNVoy(xHb+iL)D^1arZoZOqfv~s>-AzA7hzWLa`U?IQn z%eod;yar&uWV892=0P|a&1yTre3h#7<1a zMoh&?T*JG`!~)~QP>ja?GQ~)2zC4UjK3oF^)5ZAW3w^ z#itU(K>Wr3mka@Re94=9!VkQ}pUlNjoB$QD$D{npZQRJO%T{p=!UQwO2C&DMT*So8 z#)>?{W30mIXvP7f#+8i7tX#|u?8c7l%UT@BlPtvcQUOKG${FCzu519}49kBk%i4S} zPJ9es%*wdj&B?6H*4)db0?E#d!}~(R%p8vQTrlHnyrz6JZwyVpjL$B-%zzBc2K_Gq zT`H)&(Eg&&2@TOX%*Y8m(Dppb6s<23jm`?a(Hw2j6@1P0T+krRFCFd4>3q`o($HLl z(Q*7U2#wA%JjaO_kz8-TfO_t&qO`B+6&VxZ7^hPuF>1n z1M}2z<4U~1d({|p)S8OBNuAWZJJ7a!YG57K8&kVvjWK3@)=V_kYJG-m-PTw5)^PoG zyX4b$eb;!M*LuCzF%U|?_Sb+N*rPy!b4@eD0xpQ1*owW_jNRCd{n(Hl*^<31U0vCh Sec70u*_yrCoISlE0029JP30i~ diff --git a/SheepShaver/doc/BeOS/settings.html b/SheepShaver/doc/BeOS/settings.html deleted file mode 100644 index 7c05c2a9..00000000 --- a/SheepShaver/doc/BeOS/settings.html +++ /dev/null @@ -1,127 +0,0 @@ - - -Setting up SheepShaver - - - -

Setting up SheepShaver

- -In the "SheepShaver Settings" window that pops up when you double-click on -the SheepShaver icon, you can configure certain features of SheepShaver. -When you click on "Start", the current settings are saved to disk and will be -available next time you start SheepShaver. - -

The settings are divided into four groups: Volumes, Graphics/Sound, Serial/Network and Memory/Misc. - -

Volumes

- - - -

The main part of the volumes pane is a list that contains all volumes to be mounted -by SheepShaver. If this list is empty, SheepShaver will try to detect and mount all HFS partitions -it can find. CD-ROM drives are always automatically detected and used. - -

SheepShaver can use HFS partitions, whole HFS formatted drives, and it can also -emulate hard disks in single BeOS files ("hardfiles"). - -

To add a Mac volume to the list, mount it on the BeOS side, click on "Add...", go to the "Disks" -level in the topmost popup menu of the file panel, click once on the volume you want and -click on "Add". A line beginning with "/dev/disk/" should then appear in the volume list. -After adding volumes to the list, you should unmount them on the BeOS side again.To remove -a Mac volume, select it in the list and click on "Remove". - -

You can create a new, empty hardfile by clicking on "Create...". Enter the file -name and the size of the hardfile and click on "Create". The hardfile will be created (this may -take some seconds) and added to the volume list. The so-created hardfile will have to be -formatted under MacOS before you can store something in it. If you start up SheepShaver, -the Finder will display a message about an "unreadable" volume being found and give you the -option to format it. - -

Double-clicking on an entry in the volume list will add or remove a "*" in front of the -device name. Volumes marked with a "*" are read-only for the MacOS under SheepShaver. - -

SheepShaver will show a "BeOS" disk icon on the Mac desktop that allows access to BeOS -files from Mac applications. In "BeOS Root" you specify which BeOS directory will -be at the root of this virtual "BeOS" disk. You can enter a path name here or drag and drop a -Tracker folder onto it. The default setting of "/boot" means that the "BeOS" icon in the MacOS -Finder will correspond to your BeOS boot volume. If you want to access files on other BeOS -volumes, you should enter "/" here. The "BeOS" disk will then contain folders for each BeOS -volume (among other things). The MacOS will create files and folders like "Desktop", "Trash", -"OpenFolderListDF" etc. in the directory you specify as "BeOS Root". If they annoy you, you -can delete them. - -

To boot from CD-ROM, set the "Boot From" setting to "CD-ROM". -The "Disable CD-ROM Driver" box is used to disable SheepShaver's built-in CD-ROM driver. -This is currently of not much use and you should leave the box unselected. - -

Graphics/Sound

- - - -

WIth "Window Refresh Rate" you can set the refresh rate of the MacOS window. -Higher rates mean faster screen updates and less "sluggish" behaviour, but also require more CPU time. - -

The "QuickDraw Acceleration" box should always be enabled. It allows for faster graphics in -full-screen modes. But if your machine uses the "IXMicro" BeOS video driver, you have to disable the -QuickDraw acceleration or full-screen modes won't work (this is because of BeOS bug #981112-032247). - -

The main part of the window is occupied by a list of checkboxes that allows you to select -which graphics modes are available for displaying the MacOS desktop. You can, for -example, disable the modes that your monitor or graphics card can't display, or disable the -window modes when you want to run some Mac programs in full-screen mode that would otherwise -erroneously switch to a window mode. The actual mode to be used is selected in the "Monitors" -control panel under MacOS. - -

The "Disable Sound Output" box allows you to disable all sound output by SheepShaver. -This is useful if the sound takes too much CPU time on your machine or to get rid of warning -messages if SheepShaver can't use your audio hardware. - -

Serial/Network

- - - -

You can select to which ports the MacOS modem and printer ports are redirected. -This doesn't make much sense on a PowerMac, but on a BeBox you can assign the modem -and printer ports to any of the four serial ports (or com3/com4) or even parallel ports of -the BeBox (useful for printing if you have Mac drivers for parallel printers, like the PowerPrint -package from www.gdt.com). - -

If you don't want SheepShaver's Ethernet support to be enabled for some reason, you -can use the "Disable Ethernet" checkbox to disable it (this will also get rid of the annoying -"no network hardware" messages if your Mac is not equipped with Ethernet). - -

Memory/Misc

- - - -

With "MacOS RAM Size" you select how much RAM will be available to the MacOS -(and all MacOS applications running under it). SheepShaver uses the BeOS virtual memory system, -so you can select more RAM than you physically have in your machine. The MacOS virtual memory -system is not available under SheepShaver (i.e. if you have 32MB of RAM in your computer and -select 64MB to be used for MacOS in the SheepShaver settings, MacOS will behave as if it's running on -a computer that has 64MB of RAM but no virtual memory). - -

The "Ignore Illegal Memory Accesses" option is there to make some broken Mac -programs work that access addresses where there is no RAM or ROM. With this option unchecked, -SheepShaver will in this case display an error message and quit. When the option is activated, -SheepShaver will try to continue as if the illegal access never happened (writes are ignored, reads -return 0). This may or may not make the program work (when a program performs an illegal access, -it is most likely that something else went wrong). When a Mac program behaves strangely or hangs, -you can quit SheepShaver, uncheck this option and retry. If you get an "illegal access" message, -you will know that something is broken. - -

If the "Don't Use CPU When Idle" option is enabled, SheepShaver will try to reduce -CPU usage to a minimum when the MacOS is doing "nothing" but waiting for user input. This doesn't -work with all programs and it may confuse the timing of some games but in general you should -leave it enabled. - -

"ROM File" specifies the path name of the Mac ROM file to be used. If it is left -blank, SheepShaver expects the ROM file to be called "ROM" and be in the same directory as -the SheepShaver application. - -


-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/troubleshooting.html b/SheepShaver/doc/BeOS/troubleshooting.html deleted file mode 100644 index b46aa585..00000000 --- a/SheepShaver/doc/BeOS/troubleshooting.html +++ /dev/null @@ -1,79 +0,0 @@ - - -Troubleshooting - - - -

Troubleshooting

- -

SheepShaver doesn't boot

- -SheepShaver should boot all MacOS versions >=7.5.2, except MacOS X. However, -your mileage may vary. If it doesn't boot, try again with extensions disabled -(by pressing the shift key) and then remove some of these extensions: -"MacOS Licensing Extension", Speed Doubler, 68k FPU extensions and MacsBug. - -

The colors are wrong in 16 or 32 bit graphics modes

- -If you're running SheepShaver on a BeBox, the only graphics modes that have -the right colors are the 8 bit modes (this is actually a hardware problem -and has to do with frame buffers being little-endian on the BeBox), unless -you are using a Matrox Milennium I/II. -

You should also be aware that not all graphics cards support 16 bit modes -under BeOS (especially S3 cards don't). Check the BeOS "Screen" preferences -application to see if your card does. - -

SheepShaver appears to be very slow

- -
    -
  • Don't use the window modes, the fullscreen modes are much faster. -
  • If you nevertheless want (or have) to use a window mode, you should set the -color depth in MacOS to the same as the BeOS workspace you are running SheepShaver on -(e.g. if you are on a 16-bit workspace, set the color depth in MacOS to "Thousands"). -Also, set the window refresh rate to a low value (high values like 30Hz will make SheepShaver -(and BeOS) slower, not faster!). -
- -

Full-screen mode doesn't work

- -If your machine uses the "IXMicro" BeOS video driver (TwinTurbo cards), you -will have to disable the "QuickDraw Acceleration" in the "Video" pane of the -SheepShaver settings. - -

Ethernet doesn't work

- -
    -
  • Is the Ethernet set up under BeOS? Ethernet will not work in SheepShaver if you didn't set it up in the BeOS "Network" preferences. -
  • If you're using TCP/IP on the MacOS side, you have to set up different IP addresses for the BeOS and for the MacOS. -
  • Try disabling AppleTalk in the BeOS Network preferences (there might be conflicts between BeOS AppleTalk and SheepShaver networking). -
- -

SheepShaver crashes, but yesterday it worked

- -Try the "Zap PRAM File" item in the main menu of the SheepShaver preferences editor. -When you are using a ROM file and switching to a different ROM version, you have -to zap the PRAM file or SheepShaver might behave very weird. - -

Known incompatibilities

- -
    -
  • MacOS programs or drivers which access Mac hardware directly are not supported by SheepShaver. -
  • Speed Doubler, RAM Doubler, 68k FPU emulators and similar programs don't run under SheepShaver. -
  • MacsBug is not compatible with SheepShaver. -
  • If you want to run RealPC on a BeBox, you have to disable one CPU in the "Pulse" application or it will crash. -
- -

Known bugs

- -
    -
  • The QuickTime 2.5 Cinepak codec crashes the emulator. -
  • Programs that use InputSprockets crash the emulator when in window mode. -
  • The mouse cursor hotspot in window mode is not correct. -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/using.html b/SheepShaver/doc/BeOS/using.html deleted file mode 100644 index 8f9395bc..00000000 --- a/SheepShaver/doc/BeOS/using.html +++ /dev/null @@ -1,76 +0,0 @@ - - -Using SheepShaver - - - -

Using SheepShaver

- -

Changing the display mode

- -SheepShaver can display the MacOS user interface in a BeOS window or full-screen -(much faster) in several resolutions and color depths. You select the display mode -as usual under MacOS in the "Monitors" control panel (under System 7.x, click on "Options"). -The "75Hz" modes are full-screen modes, the "60Hz" modes are window modes -(this doesn't mean that the video refresh rate is 75 or 60Hz in the respective modes; -the rate displayed has no meaning; it's simply there to distinguish full screen modes -from window modes). - -

Window mode

- -The SheepShaver window has a menu at the bottom that allows you to change the -graphics refresh rate and to mount floppy disks (see below). The window refresh is -disabled as long as the "Scroll Lock" key is pressed (the graphics output is then frozen). - -

Full-screen mode

- -The full-screen mode uses a whole BeOS workspace for displaying the MacOS user -interface. You can switch workspaces with Command-F1/F2/F3/etc. Please note that -the MacOS (and all MacOS applications) will be suspended when you switch to a different -workspace. It will only be resumed when you go back to the SheepShaver workspace. - -

Networking

- -SheepShaver only supports Ethernet networking (and PPP via the serial -ports). If there are multiple Ethernet cards installed, only the first -card will be used. The Ethernet support is implemented at the data-link -level. This implies that the "Mac" and the "Be" side must have two different -network addresses. - -

Using floppy disks

- -Floppy disks are not automatically detected when they are inserted. They have to be -mounted explicitly. After inserting a floppy disk, select the "Mount Floppy" item in the -"SheepShaver" menu (when running in window mode), or press Ctrl-F1 (when running in -full-screen mode). BeBox users should note that floppy disks also have to be unmounted -under MacOS before ejecting them from the drive. - -

Accessing BeOS files

- -SheepShaver will display a "BeOS" disk icon on the Mac desktop that allows you -to access any BeOS files/folders which are in the directory specified as "BeOS Root" -in the "Volumes" pane of the SheepShaver settings. You can open and save files on the -"BeOS" disk from Mac applications, copy, move or rename files from the Finder etc. -Putting files/folder to the trash may however not always work. SheepShaver translates -some BeOS file types to MacOS types and vice versa, so e.g. JPEG and PDF files will -show up the correct icons in the Finder. To store Mac resources and other additional -data, SheepShaver uses the following BeOS file attributes: - -
    -
  • MACOS:RFORK contains the complete Mac resource fork of the file -
  • MACOS:HFS_FLAGS contains Finder flags -
  • MACOS:CREATOR contains the MacOS creator application ID -
- -

Copying text via the clipboard

- -SheepShaver tries to keep the BeOS and MacOS clipboards synchronized. That means, -when you copy a piece of text under BeOS, you can paste it into a MacOS application -and vice versa. - -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/BeOS/volumes.gif b/SheepShaver/doc/BeOS/volumes.gif deleted file mode 100644 index 857dd0a21e5144e9ab9a4de2309c827b8c3193ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7456 zcmcJ~1y>Uc!+_yY0)mK03y7eAq;wF(|xF*-&HjM3elgV9Kb z`_B6#zUv3v=iCa4U&O>sGjKFE7Pn{QUg*`1nvN z0EI$zb#*m2H^brZ($do0+}zav0i;?0LPJCS{QNvTJgls&EGz&fCMLSNx@u}_Kp;?7 zR#r?*Oi&QO!NI}I%uGv5OHNJ>_RWF^~wE2D<%fQN=`{lOOJi&8DVmyFS}NPxJ37m&>w9|p zkj9O;gG0kZU1Q@DL>CQj$w0V{z17~_RQFVUayzAu(M?0lA=Fwc+tC+ z5mC^7W6|O~Gtk6UYZu6DiRPRw;-<4RH`BJB3p-vPq(V?&X2K|zp=zFG?Bkt&ro``1 zrGDzl79W*mhcxi#A)ZB_+TBFVw_DMaf@~We<>LKnGm60m3ye$f^w*m187^i25kzS% z`BcjG5-R)R9jvMVIn;3p0$$Gs>E+u*ImaZ-fEil;AP$DR*=puJ+Z9Gq5UaeJEjBLG zw^v6fM4P7&)|Uog@4@hu!UypxhD)&O?Dn*M3;hpgL*t&eJ17Twy~4icFY4bk?|~NH z%cbpjUu)!eWEVg8eHXaH@NH9i7Mo{oX=oJ}yeQAEs!QUG3RPmU*fV9VJhEIit8)^` z0wr!=tw&21vy*#Ml0g)W(8{^-E*9z`;5Z7yq$HOAf-RYibXJ6u{1mlASQC$FTMFZ; zNAR;F%@?$&Kh1&jSz~O|Q%Kb*pX{%K;+y|NXNkE552o8)(di1b;!Ch+N6#yAWF5%v z%w})j?w8sx3bF3ziP`W_nq3isVL@W6E#LKJ>xhNX~cc}Rfx^s5ixYd-%+XSL%~{s=LUbr{-d$Gm;ka@3f0LCNnK2;DezoQf77wEouYhg zaye@NIl7!%{jO3s+bKe>gJ)7wd9`TE$0O2hcK`JgKH`gP0333X4q3IkKDu7>BfP(w zYCl)uUJE9yy4j5MmiAa~UyKr|wm<|nN)nm)iV`QO+INdvu&Rlpqf+ee_LpUNZ^T_K zWjy!N{k|2VTj)dB3Wu+3{hd!FVr~8nrJXPVyPtCM1gxFQ-VSTaka(R2e(A|=I_ys) z3pfqp7)~S7ME#*IwsXvf<&ated*~NWgT;pP$RMa5rn}P+S<-y+5MVD0{aGkbIiDgz zOe|FVEKDsjpRxql$4T$+LFtl5-9#ip>wFerl9*1@14If?*hN|>7tq@UBZXVfqUNnx z8PGt5TvKeEh1+leQ`ozH={x=y=tBYX8ZAnWelqemcd|^78|N2^!8kIE9t&exJ?G6} zd}q(wYM}u!5KC8rEuQ%_8!@+`JP%$*JrgIy{Ofe(c|xT3&NT2Arpy|dy zH=q#-d7E16?5U({^gO9oh*3c4TB&rRR%bwYQ6T20veB0*hY?r(5Beb$R;?${uJqi- zVq$It7z7S}iLR#h82wrH5@-8jX0Mc{g4p*YV`+=2Zgl|WK^>jZct5)fz_k4|{~NHx zu!}M4SAqHt<+Ro6A2^1Ln*WY=#aThanaf4%&4s`lOAPzx3+?7-E;?9RmEQFi*ya1>RBt_#wOZsoMt><=o-OmF)}V9RArLF7_i}-Wc$17N;5-F zH7CxBKsLML3QFyJy^y&~`zqhegYt*Sq#45~zG}8e<6XZ+nO?6L`=f*v zi^LjUeAiZ8tXW%E=SS$QH#?tp5}6;xF~9fn+wUBjjP$FTs1I^*8fU}47*~IWwwnGuoYNK*foXvc zS;o?JyZ+U~(<+C-GWYR1ewTHPBX%~VTyYaJh0U-K1IL*AWisyThP<$2_XE`xikFM< zKS#%2gk-CNFWFd+Mo!i@^jGhXo4Q~;^KMhF>qMQ`P0yI-gCrT|NMf3%b{|i}n~v6A zJ{PM=Mx8}_KWs5SZ$T-5oTF(-w!qUjah0g^WW>YHhmh};>d^{GBrqKQv6fND=--rI z8-N$A)FYQG+&?zj&_LDJ$rO7o0PXs|T1+brE%`+%wZZ0lKChbSQS3#P_v3*Hd&+b_ z=rT<~YVC7-;Y7>_QI`64Vh5T}&?s_9i_-LwV(C5kMfCO4%pZ7E^O6-eqgO;XS@?c5 z4;wFIf=I|^4r5D_rV2Xz20peQvVWB9YUprcy=f**F2u?$8>KRcAZntR=THTK%)y2<$Z?M;Vd z<1gs(5aU08_FsTdD6q@B7vdMM;Q0g&7|?P1Pee*r$7K}af_1(A^XjVe{L(#Jz>D7t{~x5D6X z#Ss$)iv^fk1!#o^I>iNO=m!7bfH(pnb~l0UH~7h-K_tK+GN6@CNRWuA-ngazJ0JuX z7|KHQ`w{JZN#*@}&pi_8C&m%BNP}Y}<{Kv#u-oLtQyReF5%w4DoxA4^91nzegnJUX zdFci{*9DP6EX)G~cKUyjq-$fY3Wpd{ZJ^JB7$(4>DwE#4k&z zkQJn-Gy?7CizJFv3H=pT5*ZreTjUYG+>D=464DRxgq9lrYW6IucP|trDAx5-g-7q} z`jhB>Xa0^bdH5o_xJIc#0h?4{sA2675j08#L>ixNgdyl!WPmSZ@CM>akX^f)kL;p zkc=)*&KA$apfHW#H1`~EMt4glR3I}WEhQ@~lW;C&7@Q>)5K;n8YHx{~UC1Ka%v9IO zJax@fEX`c?%#LMA+Gxpm(U6rJmVHW0xlZi1DegMC;J8bdb9ejV@2%^lVzxgKcV|lu z{$LJ9G3O90dYqO+u$U|7l>09&7hBtqo3x)x?M3?d6M!vCxh9S{PfVbp&+m=RdqtnM z1I}Yf&kw-Kqvy=456kDIFDUBDe;1zqPBCrzeSw4*(OXPDWqN@mePO_O!Gd_k$JX>u z>4pBXh2uX9l)?&t<%JrU=R%kQ{)M~_;(X24BGazIFMEX!X_+4ei_FRij26QeJ&V|% z7Md>>v#1xz4`x`?=ho~MyN454rYD+6qC*zkiE&+W6<^CMI-eHx zV=CJ8U{=XUn^(m;}7Ucj?yY?7Auw|DrU<|n(hi)Br10}3&ySU^Er)snUtBSC$*dDBY^r{L-uQJsuz2}6}V5*-Cl@PsxKSjXtVWrQMN^iuA zU+Cw~)0NFjl-)h8p*ueB*RanDUb;hr9OubXoyz4j8>n)YUSu+|}(vqLfH=0G%8+h0Fer=i= zNHPqI@kncOKr}IhH~JoA3E9*JXB34k)srvQmE6_6K4^#;%8Yo`z_-|x;+?_0AD`}B zNW9e2CElb9Pl&W>^m$cLxRjoD(0KE-2`1TEdC(dMYw&`#hHy1CM6_JfHV1lFws^zq z5cTb^(%rclJ-FI_!w}KlZABU3wp=aMUt7LKG>;FZ+vulHAHZf|^~o9SDPav`ip@1k z%~6~k`HCGshT6~vZTql}Ev5S2wANk(Lf^dg{2-+o+?glYupZHV4@<4K>CoUp++-Nx zMYc8Bbdu?}VK)$6&fuR=>=x?e)Z{!fm=w5$YdY`g9)zN)vIw%Y8-_eWw?F-=&ZYfd;&!b*56?`aXaI1k&{<^1VR| zM<3GSy}rFqntLYFJguLqtz}le-;4oeoY`++KoH=A3Q$J*MWP~y1$-i_%)L89wNZd^ zRC0wtxGgHBZGbmnAZd6YmsB9e03P?yg-{yE%N%6d8Yo{LWbGNOVi+n=t|>a~PH02b z91ddPnL}-v{D|eDT&W@6`)a<(!LH1~PM_hH%;CXh)Stt;-bf^p8-<4Rzm4Ues~8+! z?wjrhuqBMtGT=ZS`kZiZMuz#vq*^8_{&@MINFB*mBS+3FMmCp6e~{w5T^}JQ$6Xs9 zT6z#zco;>u@$Vb7A8_|yF`yP0#!r1lPBO>V83wUFeYcS#xR2vhP+#gTGD5$Jv*Cf4 zD*~h|6UXZ#?-+4s6edr7094S4cPdDNqjo}QJFyCqqE_HnC)3Fr(_f{L{7~c}!}Rya2`nAs z3~*)e&9m_{?r|U^4WTSlePq)9acb+ZZ=qtwK5JT%an74(j^SwLa=AZW(p-fHNu@H$ zy)qRB1xQ5ADpwACj~vso8?}t$Co^1-QJE8t>a#qW@@k*g<(W~;Lis-%=&>1WB3=05 zGtGH4Nxm{;khS1vIQPTHV|RFlQw7)H5V{cQ-!jtIEWKFQzCg)1Lp#!!b2LHyd1mN{ ztcwR}%-Ao)Gm966`f0c_`Y@jpxiV|GSm?9Z$nE-jWX0cSWm{#j9=iJBXr-QXRdh*b zt8z84V&%MYVcKvF%&;QJ&~zQOrfa+UZ>0~ww9Zkmwl=h8d-y3P3TVIl3416#EJ6Z* z#CLtgO<-fN(dfKE`w!o-ZH;`nSDj&#MP^f+bn~t6CI@JfEqjxDbyHfZ&zGS`fVYS6 z--e*?mL%RRQPh@{y`ThWN}6dqnQcXgd;5zF=s%_=g^umn^DX(&ZM6<=P}R1&(N4d> zj){q;hvJ4y*LVeMQao(3a=c0vHz>0Tq~Xx8^&hWDt8>Ck=^P0TGj z+9w^jt0k~&BKSo^Bmuny!Ys?|&)O5j*<)6!2>u+eQgj?nyfa%*>?|oV-Ja2tNI=h# z?bG-j#a10HM4uiTo#;EB{D@x6=>XquW2%m2blg-0k)~s0N7;armSZh={Q;m0=i>NO z8*p}_wA&ZI@1hMU&QvCBN2bP#qwU66aE+qSJF#Iq7=*N%GFM^ma0^2{z zJ6r_#T>zAKoT_ZKnZADSIHz!sV;;W9RlAh>b*YKH)F3;?LddR+9nfaKu5@^>sOmpx z#9T@IxT5^VZ)m$~-}%$}^)<49$6__lO;yMdD;reD~x*W+$vU#Wg5u-#UuZl!>BHapJtv&EchEb1H1Le0Svc(>!`;BGgU zuGbHZyLTR+&$f6^bJbq-oTQJtia(j5W`}nH*#|EEh zwV;Kx#lPx{Tg-EOqK#NxA*Q%~Wr`O#%p7#=LVtV&eq-PAlr7GSkQ?#PZoGLhwwITR z59+LO66bg3D6S*&Xtpz`D%!;-Bqn+G{KZQu8oH#^;(TUUd=)(pAISmfSv);1zuaee z1w|!7Y%Ft8HV0cAr^*jHVM5_MxRjwe#M2vUt{(I4U8Qdn+DgtPCM_c?=aC7lQx=|= zcR*j?)PiX5M0~979~j~fj0y(3MVX911vhul`v*rS3u~9xw*?8)Fm=o|*C)9^!WV4c zN*zr;hwP41;mi*%evY8wx3Hy-8x{JFD;!KI9$&~3{h4i-b#s)c+5Vj=GEwokFgB4Y z&ZCtkW=A>aqknMuLhqJDrh*iXTC3~(fNZ(EFG*Ml%RQCYEP)R*m}wL>1@*bfMj>Iu zZ$7U^KlwUy4g5y1L5m?wzB0WGQlQO4e@azVp_fssyd}RASM%fDRTy&s_iMwzvF1t^ zx+8KPcjB!XA00kQYs%`~2a=nxbz#fV&)7C(vmIo{bt4I-`#H&RVAcC!y|`BpH_M5e;WT>7n4b`>hbc{Y;y2Rp{X=6kYh`5L=WHNp?ch_?OSGk1qX^Ub%4k02@ z7~JmE&CPr6jTw7*ZNs87A>t-9(pyK*RyX~4IGJT`?i);Ueopl(gint|;*YcHUKc_> z{;PDbn0eWIX@ZoBAW$Xg(KLAsP5F3o8)J{t8;9Qjfp5P1;4kCCEU-!wax)Q$vw|=o zID~XRo8-C#5XS?jqDoIz4^`wN;<9k%+5oUL5~|s z^^KV{DHU-A<^8Rzn}_58cH+6_dVF|`LuW4bg?*66CpChF?}?Zo`e&Z^hl@Ae<3ut5 z_g)7#jl365C4JcTGg_w$?7}E_Q{U`mT<8Qdxw9ANG{KRD!ypbqBE9o?xY{xh3GM`^`9cnb0k~>_vwEp=(VwqjzcrIjlBo6HaVd2V=#^{4A%47Ve;{uTsdtKL zR>q$Q1}kT{#t|pzqXhHlRDOb{m;;5_K9I?(*x4s!5UR7O`-U|Hltr4cA=ogeecojL zI?Xpr=F7_-qhIAtvm7Hzq}~v;LXQ%19`XA{&u)uziFvXJ2&`l$gw%p~DSvO6?S1CS zQws%sGa@V6lcy2?&*XbzfzPy+f}HhN_h6yI_xrnw>ggIuRf$DBZu?56^qOg-iN$=v z$qSC@npww*CDNDss`CEy-}1=ZN}zA|)oaL!pK>RaskmV@^XRq8KuP6V4H&JObgfGJ lB$(kPMyH!zyCyoR!rZ)EZX#W~p(?4;&h0>7iy9vw`G5Dj1)~4} diff --git a/SheepShaver/doc/Linux/acknowledgements.html b/SheepShaver/doc/Linux/acknowledgements.html deleted file mode 100644 index 5d8c9fd6..00000000 --- a/SheepShaver/doc/Linux/acknowledgements.html +++ /dev/null @@ -1,24 +0,0 @@ - - -Acknowledgements - - - -

Acknowledgements

- -The following persons/companies deserve special thanks from us as they -made a significant contribution to the development of SheepShaver: - -

-

- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/contact.html b/SheepShaver/doc/Linux/contact.html deleted file mode 100644 index f8a640e1..00000000 --- a/SheepShaver/doc/Linux/contact.html +++ /dev/null @@ -1,47 +0,0 @@ - - -Contact Information - - - -

Contact Information and Copyright

- -SheepShaver was brought to you by - - -

SheepShaver WWW Site:

-
-www.sheepshaver.com
-
- -

EMail:

-
-sheep@sheepshaver.com
-
- -

License

- -

SheepShaver is available under the terms of the GNU General Public License. -See the file "COPYING" that is included in the distribution for details. - -

© Copyright 1997-2004 Christian Bauer and Marc Hellwig - -

Names of hardware and software items mentioned in this manual and -in program texts are in most cases registered trade marks of the respective -companies and not marked as such. So the lack of such a note may not be -used as an indication that these names are free. - -

SheepShaver is not designed, intended, or authorized for use as a component -in systems intended for surgical implant within the body, or other applications intended -to support or sustain life, or for any other application in which the failure of SheepShaver -could create a situation where personal injury or death may occur (so-called "killer application"). - -


-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/graphics.gif b/SheepShaver/doc/Linux/graphics.gif deleted file mode 100644 index 267a4f9e23bfbc42241480af5595afebb54cecb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5480 zcmajhWm^+~7QpeTfFo3z5rWb&Km=)|Q$RtG(J7;bf^;{dV>F{*Bw~zqB z-~0Vf%l|Zi1pK4Hf9m?DvVTJU9{?os@7V&7e=p+i{Qt@J{{Yz9{xy@oQ~D>Ve-aS^ z{3Foc0RWr-4DfH@|Be5*3kpC2U>C@uQCHX#4y55X8?Gzri>BnzvI7Su3hlnN)IV98Q2!whGeV^aa~gWfaG6-0q>&Ty325a<)7H-CXmzMcjYzf`MFU6m5C< z*KVs{AI%bVULI>}fR2X{7m&$8Zl}yv z#Nf_(xSO(&Ql@>}k1yGF7ptFp$HJJsf6aA=le6h|w(hSDBLplbI@=C6r%Ij`=yplJ zohiAM*=%7J-x|Cs?M7gG{-N{yaBH^8GMH7yQRe5`XuCFpU z3I>o!T7^!M`Y?q8i_0HSQP7`Rg^%s>K!UNVTRE_gpS+l&8v{YBaF*VUZ}Jn3YRC|# zAow?D4r+|4E_2)Yhk&L~u zmaH5F#Upw`x5|>$!W`C8HJCK4BbQ!#e{&bq$8BWO#{XA@Cbt`(wsTkwsjeXxu;%r#kPw)H_)4hAaAKXRl%@5eAw$*D4 zZQ}hQukeec@=ZPID;wRbb;-3dR2MgM5*r%G(Xu?a@JqfUV#~C1bwfpn>iY?aX^RN^ z&hL-9^g{w}@i$%edVsgl)ed#k$h|&FbqZAXXzg}gKL}cl@gx6?{W-uK4L%r-(jVI! z>Z8*>z=Gf4F*$)@_=7RA4ww2NdX(AWgsk!(_de-U@X^%Jb^JlG3QtXAtwdkIPUtgr z!6u~IX8h3{1R7{LFLJx)c+mi0Mx|N}lzJ){ra77}a zw_(&^Ep5P!+;d~DU|#JaGNZGUsWf3ZaC{L3)IlBz+l-V%niOl#mR$o#P2t5e2?Tc) zPB+N5Ow0bOyP2SheUbf`C-2y4QLT^pu6H#+H}x~8`pQP-*8=({#&Nns*2+ZqMi89s_yp8*ZdX4AMConoI0e?;0lYGIS=;^nbGS~4&e%SjVgasDj}N5}8huc4)njq!1~ z#RhVudeZU8sO{ufNIm7H<*!w{|wsC%*N8*2;n(;`!M#3 zf;VJ~^hqd_Msu8>pI((j;x zrf}&vdZ?ghGQ^|Hgc2O@KVOoxOEf5d5Xq2@Rm2{87FrHzAqy&f>}`B(0^R-Zjc+lGOS6 z5O!hIs>r)efP%{kVblkld<>1uH?cHX9R0KA4SArp<3TAqc;e}^Ai!#{sj`^6G~~C; z>=KrSLJtpm*5}+2T+`)Vnjsl_wS_2fG8$c47)%Nhi?4Bk`lntI+K9NXszv~_t3;~Z zB$V_KmT!WY%@*%U@N~n-O-;y6m!wbIrijTeymsV&XqEACFKOPu?A-WzGc2O}SjZ<+ zskhyVL40YR)O%pnv}BAcEOzUc{0Et@MJnr^#A(8T2y!~gpk%Onwy<~0>v-D|cJ;ug{hLd}>FU!Dz}d@gW~*8a}Ud@jU8RG*rOWSDt-Jn|y3J`JV4 z&To2-g-q0Ew2Z9_`Jazkl{@M9I+!&5qSSio!a=nL*$B!1L@;hKgGM97`gPZVY8|A| z-0U;^^D(!{?`wuxw{^CZm@lT_x{bvQ;|^#n-IPe6Sg9%hw(4}URsFzG(i1sl-S<de0frhD*A1oFeT=hL95rX%zD>`TTIOOTqA9>C#+CHP4x4A zZ)SA=d2U497G937^+UVr9@Fbw%QY2-cDFKDg*>MD41!@(w_*OlVfBS}9MJ(fb?kf2 zXW2-ln$1#yoVoTphnvD*9VfTBpB)>_G%A187LBx zCSsF};A0J9RPFt|P|Jr6m72E`B|i!7cQ=z|)kwtZsn zi*(_SS+T(%I7);A`Sm|uyy$#-l3j7NyIFU+9Q=@Q*7y9wK7uV^Ltg&Z%=@5W%*U%Z zfB8Q&JcM(G+Ut|sEZ2u0TdocZT(3`qU1>sY4hM*-nq-R^5T6B(qXNh!L++e~NUDTT z<0Pmcq3hnEAb1c{Yv|5mDC<_x15nt$L>Q+=Ft<pOYE{STm%>HhR{`Fm@qme42~`A)x$Lc9-&FA-E7mD1 z(VkTOP_v6B8?PIPWiA9-6>&@;roA#WQ?XCwJx3^%rz%oeYbu(Fh;Vg#n(ZIk(Aq1q zW>`o$D)vXF(b~~!IV$R;DC&)*iP&4R8Q5~Crb#Z)oV`}i|AtV=&H!?!UDGJ2@L6-& z*}89As$(p`R5pfumUMHpx(Z4h+=?TwX?z@Q@2h0KV>J6zM(r{pJkR~mRjf?c@YNl%4|l?ED^74q%n;QsiL|FL&zhm zA5CUTn5=}hT+ySfdnDEf_T#9Hd1UZ<-sRp{|I7I%5L-6dbcDO>zjAR zkuu$uhv$$97Sv2D0ERpyiAYzFN*!c6ZVZu#QjPnb4sMi^5=O=Qf5n@ zVkLAyrIw z{b-cSwQbA!qsz~zVu|(L{oLKbQ1IK>7bZ^kU2@o5f2gW7`kHaRt(s=bv(g!LD;`3* z)$Hqpw|j=DsJ$V~Jp?fMdCpb%(6V{Qvibh^Zm&?_zq9Kz__t;HLyCpJWT-{kc?$Wl z?;j`^I>GYDoL%kIHtnETHU7NYFoh%KeGiU%IZSQb965e()oya~9iVb!s|t_MB`qGU zP$B&T7)!kln(0x$d!;!$Ne;GhMuii0s`*}A9i>*i(rj;}?>$q>+0y>zD%I@`t>DB5hYOd`ZFw>&zaSjLH45^n@4UVi@)8Gvthy5tE)>^;1UIG>)R%5NDS0;Wx zg2`|~o%fxSwx=IUhtqqComdwecbaD?_X~_OfBlhOVBp`_ujFgS)!D`oK3Px2>D&pGX5n2Im{JlPPjgzqzI8C*c)#B<7|J}Q*!Bb*gE>{{FKQ2Z~80<5~5n7yDM+2QPZ`j%m>rIr<*x!?;)%lT!7sW@btD zkDU^4_8!(=__bZ|0-1~dpELqsq8#A*7a zHTqRu`eb+NG+0DL@%@>0{qn#8(!+iO*?N6&xe-gRF}}fcY(NVc{_@WN!Dhe?tY<#f z55@O6YDYMm4LS?Wv7tbg!KW1iA^1*z_r6Gq{xE`U zggi zsXcD1Jt-tHdFG;jqCI>G9=Z54$@F>B0z3t{GfDCV1XW&t;dtGyre!{s;Nlf=A;b&5f(yDz3y3Z0q_)7a z&N68aT=D8l>i(>qY*d1{!wXpF6WHv$-q({|zKXoBB3)nq=*%XB=iPj|LgXq>LGu-u Uze4t5g<^T-ZlVK - -Revision History - - - -

SheepShaver Revision History

- -

V2.2 (04-Feb-2002)

-
    -
  • Integrated code from Basilisk II -
  • Source released under GPL -
- -

V2.1 (31-Mar-2001)

-
    -
  • Initial Linux PPC release -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/icon.gif b/SheepShaver/doc/Linux/icon.gif deleted file mode 100644 index 51368b117dcc38bde6f0ac4457387bad5fd31efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2011 zcmaJ=X;@QN8a`ma0F_2r3>syr9YKRdt|&{30R{<-bXXM(#fag`B9wN_V^q{=A+nS) zsfZV0#voXrBBWwjq{C8V8oAmAiW&hU$f^ipfwK6(o$vCizvetio}BZ2@B6*)d+zn~ z-{b0bh=+J+7SW5zWU^Q+Hk)l@V`Fb`@8sm<>gvkl@%VgxP*6}rM1)W%jEjp)NlB4N zBvPp~BO^mDmlFh`R4U8L%2X;|kNQ7=9l#h_~&oxl?|H}kMQ4~pkNRlE*3MVOyq!2+- z1Vs`QK~OkBVFZP6ioz)prwE+FaSFpJ1W1e`F$ySfjKVMq0fy!P5Ol#YfdGbZ5~$%z zk_1V@1|vyCchP%-AaR1k2okzrHk1jR#BmbCNd!8e6(b3Z#4!@XNCXOKfuIN^z)T$Y z2?Xu5R-gku_zws~OQ6|d;RJyZ&_z3eVX((>0s|blg27P32pl6Yj6lOOM7yU8U=ch4 zKZbAwwrSxs9@K#xMEj$)0v+%H0jK~`P=^Cp7>*;FgLVSLV2@!qTm?m;<#g#>FsjN7 ze!wS$NT))p0RVVKba=FL5C?cr2SUIx42Nkz2YiSYNaq4|IDm!d`=PUdxPcZNf(Yn? zXM-Zqa_SH>j2zfQz+Iu`oah9h6MFgwh`9o2M@W?i-#R zic7x%^t*tVP&4B2RmzsHm}XlzOr@cy==DG&aQ87d8f;)d}O`ax5d5+ zmSaSjy0a+YoMZTxj7;aD_B`&vrR?}a!}qTmgztQW&0Ci<*+gX&99V;ZCKXNIro zUx}_mv&SxUWQBW5obpD4+sd(8U5{6`|Pg#`jX8>{Fac7IeC4C*4yGZGV_lkcxjp&WfAFXJ(c~kUE;ak3$_VG zO3O`lB3+u|d+qx%*Ie!he5O7t)uy`WB!^}0OS8Rcp87`3AwK#+C8EbOUzO|(=sZ$< zWv}I(flH!24lPHf%DZ%zk0z&-Twx1?I?fkvA1p~TKQK3tA9_IktwG}5@*B#eb!$fo z4?Z>ul`e|Ph+WO))@6wFdjTFoewti<>^!DY;RHgAey7hB+_vXsW6Yg$F=foLdePM*x!$6%ppr4(*sW=> zV3}7Xc^#Nf+U-1%nC!VRcwSl>65=u0V2EX{_47OH+kQ&+u4rIq zXPVV7DNcp?_~me&o5Xs;NZ;{&Y3vrmeg=B5VaKNGl{-!es~@_(c^&kt>0+<5@57mH zdFQ&7K6>8tmrqu5IL2rAFEHOm{k6M}omu#@a(DRU z|K8nL8u@mGv~i&ZV=f`p`o%-iv)n{A_3DVnUu~{`c-SFOkFvet>R)x%BED}$NN^im7Uc>;BI}E)Gt^X6-P!)J4+j7_sV6a_ti!lzWIs!y(ZnM@L%sW zH~9IOYFR5>D|F9n#JSOr_F4x%@RL0rzMCgBxqu4!KE$Zr<}ItTKFfV!GIPjr>lT## zUY8v@slDlNz9aidJ>m6g-|CtEAUi<`&-@wN*W#D2WB;*9uwm@@&l#^LL!y2(H5sa7 z)%R;WSZ+|`ltE>Hf ze^XOab8~Yb5a{ge4242Mh;TR@iA18&==k_}EEbE$PrG%0~ z38A=9Oeo??aV5DDTyd@#SAw2&Q9n$(VSHJ-e0AK-9 zh~of@aZVaTD?u~t8RHm*Qncc(_Jyg>*Wd>_VWM_Lvq1s0k~U8(2RYP(9f&|Nnxh-w zfJd63_62bqV3D4W_5yYT779TEdAJ)&(u(V_87+S;6POjP_@o^~DpbPG6=jg3D^Ujn zR=8*v00a~e)f)8V^)N7R+#OY@zX1I$kOi>^a?7LPiB{Y@cRV`ers@2`w|z$NdKVSu zRr)zusO5s2V#@MZSOtSoH9>iRo|bV zekHGGdGe0Azx4dlm1MOi-BxxafA6$sXM2nJla!EA*N;l3hOp zJwvy8{hJo|RP=w*ej~c^P*0bq>w3mV-mT87Gsh24Wj%R!WJ_l3Vn*ceO}?LPDYL&! z6wHsf4h*;58aGugpNsnUcMY3%E?qh}ai_JSyZ6nz*LDwG8@<1olCG0irOo93Pf$`zLPS zun~xEtHSRbi8rRR3R1L0OEq;8>8ab8se(l_z z`a$1~Zx6Ow2QJQeDtDw^+HLaJ8^OlWd(|JC;tNliPj4?af)719mRDxoVl;R%il3{! Kyw<#mUj7$_>qdM4 diff --git a/SheepShaver/doc/Linux/index.html b/SheepShaver/doc/Linux/index.html deleted file mode 100644 index 3fb408d0..00000000 --- a/SheepShaver/doc/Linux/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - -The SheepShaver User's Guide - - - -

SheepShaver V2.2 Installation and User's Guide (Linux)

- -

Contents

- - - -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/installation.html b/SheepShaver/doc/Linux/installation.html deleted file mode 100644 index 75f588fc..00000000 --- a/SheepShaver/doc/Linux/installation.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Installation - - - -

Installation

- -You need at least a 2.2.x kernel, glibc 2.1 and GTK+ 1.2. Earlier versions will not work. - -
    -
  1. Unpack the SheepShaver archive (if you are reading this, you probably have already done this) -
  2. Even when running on a PowerMac, you need a copy of a PCI PowerMac ROM (4MB) in -a file called "ROM" in the same folder SheepShaver is in (but you can select a different location -in the settings window). SheepShaver can also use the "Mac OS ROM" file that comes with -MacOS 8.5/8.6 (look in the System Folder on your MacOS CD). In order to legally use SheepShaver, -you have to own the ROM the image file was taken from. -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/introduction.html b/SheepShaver/doc/Linux/introduction.html deleted file mode 100644 index 42d78a4e..00000000 --- a/SheepShaver/doc/Linux/introduction.html +++ /dev/null @@ -1,44 +0,0 @@ - - -Introduction - - - -

Introduction

- -SheepShaver is a MacOS run-time environment for Linux that allows you -to run MacOS applications at native speed inside the Linux multitasking -environment on PowerPC-based Linux systems. This means that both Linux -and MacOS applications can run at the same time and data can be exchanged -between them. - -

SheepShaver is neither a MacOS replacement nor an emulator. It runs an -unmodified PowerPC MacOS under control of Linux at full speed without any -kind of emulation. So it also uses the MacOS 68k emulator to run 68k -applications. In this way, SheepShaver is comparable to the "Blue Box" of -Apple's Rhapsody operating system. - -

Some of SheepShaver's features:

- -
    -
  • Compatibility: SheepShaver runs MacOS 7.5.2 thru 8.6 with all system - extensions like AppleGuide, AppleScript, QuickTime, QuickTime VR, - QuickDraw 3D, Open Transport, PPP, Language Kits, ColorSync, etc. -
  • Graphics: The MacOS user interface is displayed in an X11 window or - full-screen (requires DGA) -
  • Sound: CD-quality stereo sound output -
  • Networking: SheepShaver supports Internet and LAN networking via - Ethernet and PPP with all Open Transport compatible MacOS applications. -
  • Volumes: Any HFS or HFS+ volume can be used with SheepShaver (this - includes Zip/Jaz/SyQuest drives etc.). It also features a built-in - CD-ROM driver and a driver for HD floppy disks. -
  • Data Exchange: You can access Linux files from the MacOS via a "Linux" - icon on the Mac desktop and copy and paste text between Linux and MacOS -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/memory.gif b/SheepShaver/doc/Linux/memory.gif deleted file mode 100644 index f09a46076f5524ad6585b455fffd104826784efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5697 zcmajecRUn;|HpAjWkhA3z1JC;$5~~B>}(=*arUZg$v$M9v&oFJ!&!%uy~#Lx?<2~} zD(?IH{-5vf`FQ>Jc|6|#ebk<-N`q}OZ#}tnMnHi7e?ai~eDK2ne=sj^KX~{O|3*zwne8Pw3PkUegyX~zL~1_C?XO;$iO>(RFQT%{u=C%{#N;W z=F`wiZ2$4HUY-$P*-LW12k)Tr&M2VmSHea6kA$f zG2a04Kf3HC6CNzJI^JCzZ1}Y#OW@~&RxYSo?SxSYyc%k(Uhhrd)XdgG*K7`^i90O~ zp;6G`k9Q_W<JAaD)VcnlD*NusGVf6lqZ3`u1)oE!wT<=2& zSdFxxkGDq)G;?$?GVbFAw^Qq1Es&vuHdH+Dth%i&7st4XGOHjK*&W%v^}!t7Z>?8< z&I_BTDRO*Q{&tLo%moqLm9`H4PU6E5Oq^e2{op?BxpnB!KCfxez%yKi%ePrChRE7L zz#5FHV{7#ZwpKOkBf|&SsuSmF)k__YXrI?GmZFIK=+5eyMaSB7K!J<+63jeKa;bxZIJ+sJUza>GpQo>#6ex0Z&tA8J*?s(q|TY>fr+viY9W- z!^0wgj=8FpUi`(c%r7$$-RyJQ#Z^6c;E(cCdcTaaE+K{m$Fh^%A79(<3hY&N(K_u_ z_gy<~)(nAu?4d?g1@>#P#!mZnGj?VB^$T9j6_phA8C(8e$4i%zaO3troA$<`Wsd7d zCaxZ6%L|)02|s(c=D(+dt}e->r_AoVcfo6|^3eheX!PZegU*NXm%^2u!HkF90BHGA z*J0(XySK3scBGG1afaLF;8AB@GLzCko{wpM>6ci3&gX@RC3AgZgM4MDM->88d&PtD zYCu#{=4)_Ck5+2$VaL&jg%hlyiO}N2tKxnn*4TUh_jJ2W#rynrv-_vB_J0IGoixb( z(|NkD%Ggf*AAPdN*ipRavdzb8H0mcDqtk)(EZ z-jWQh1iw#xi@Dg&6_`e^UhI@-Dm1NC^uD_MQ8Vq@>`uL0+58jDsTM;Q zK6W&F5KE$~Jk<u%7uJNEjNXKdPdCG4mwBBR<`+hchRjtK(&SI%5?& zFYRmzdRO7ym>Y>4`R46Wxx*DYp6l}m(?R%yU;a9Ovn0OZ>GguXujdf1PFJ@H9Rz2- z{jOo|nL?V_EesgSy(`t%Uc1u$nC*TZu^MqlRV@*ZBz^l`RT0A4Vs2hp@PMvgNM&9c zj!%qBgThQnxnSiW0u)A0f%nMoWFdS6RM=yG5Ic@2I(NVQ@!^`Gf_ewg{4m<|MBSdP zFF=nXC&G~}R1#sI595Lu*jUcaLGnk3@z%$j zdre{NY@he!EasA<2)&px6?x%|GBh3oNnA#XKNH@G(I<(h^lOMA5yegh?WFbDM1&d% zwtuL&@@^08lcKOp;VhPm&rM`l5`__kBFV2b>VgOJ1eHjLXRyX$Xwi&%ZP`TDSr}#_*eN++;R7Q+ybf(SBVW@h zszn@cdBeot|6=gmkkjcwW{)HKr*)5OVJNiD7ceuM-S9rC&A*X1+x_7`=>1WrE)?b&aIp*rh|OE zto!YPtdrdQn?!cyXlmy!@e<8pzUk)5q>9kk0xJ`JtL_nU6!fjLanzB&*ckY{P){N=xMd|_DB=3>q$0JM)Izo0|w9O~;Ue@9)JEn7jx5T8M zVBya@&)`Wv^?VpUE4}-x*Zf}Pz5U=xcHwaG=uV->{5!NIvn_k=D_ighu&dA6V~WJQK546_Hx@$N**;09^~6)nI1u|8Td zEbA~sanJtwgqg5+)G>;J<%m?pkJUmRU$1(6)!mUooK0;P{3uJl+HhG0ays3^6Lhcw z$S1E6;>vjJbUe$#yJb)8y^_p!U9qFolh43rsju*_cIomh(2Gbf+#9c*NPcN02~enr z`!r)pJ^oDTE(vq!&>vNPVnc1ghu#EMKa!DJ`FY<*8Sq(heIf<&MpEU=K` zqL6BX5Mg^+5kP2-c&NmT49F)Gi3pXEmKB@{g?5ELJqIgEhh-RqshWb-)4~v_Fs(jm zo%678s&IX2X+zWSz_;P1K2qk5;qNEHU!8-j0TB-35pR4zc0LhShzQ3SNz=&)G6@HF zds$EE$eP;@6PzY^h^dz;n@_P>`jnZoQNZsB>vxk(LF)2b1(C~~umHTYk9{{R)dOZv z>4m0c`)Ep!&y^2JrbvjyeoSfA*F*HP((Fb_%k z83a{U-~EMS6MS1tqAj4!GEV=MIJFs^))x*)hclqzTg8;52XHp} zL=JEwmsui@Zz5lMA`qP@IGZSZk;t?2MqUabK|-L`^F|tBrR|Xmc~Z$ zQL+ZyLR6HyyW8UTGYFtwg|o=Ul3wMaJLO52&EfA9krNfrhQ$F*>g9W7Rf%MsQHb^% z4pA)QxIS&?8J*r62s$c*v5owRC>_Yos+GjD!NKai zs6{J@b%{g99WU$KcFBrk8DG(#O{p`fR5Nwah#7oT(sNMuCw|02diEk%vE^CP&*#}l zk{tCZORfmTxsvSj9XcugoWHX<%!V{%^tpsGxkP>s9gpIJBx3J0<=&smrMS#}NSbF8 zkxSqZ^;$LW?*tUy6#!t6VaTwHCCX>kkY@GsXz^n7I#mVbd#P|h&9>ij%1CniiG8M4 z+nMJ3S|lbyRiGta(CVR+mG8kK<`KKbE>6hV+Fl?gleeo#zFS|Qp&=>GP*@Sl_sFl% zG^5bGsn9~^;k9~Uok67aob+p%q8NiBJB@s+j3OjwB+VF`n}!3F5_x+(uI zWrO%>5m&j4r+lv11z{mqzMDX(#GiW{-5Rc}XW|*2;yi><;>H3g$_m=)GAVP;r->Z- zm*us$oUc+1>wp0sT?}8_#WyY=h*0sTA)RV#N-$ex_w6NAIC$O}zyC>F`rZ7?i?atq zr9l+Z!6cj-Ua0|UkP0UvT|HhGq@Vgvwddgf8+5<->f_g6(ZFLF&mdm@wDD@Sj?$Bi zGSXev$J@vT4a3x3VFa+`F_~Vl$yX=5Ba`?`=48i`ts0a_CdveYYRX`GT80vr(hAY9 zRTL2LDy&u2EK&c%tJ7RtMX2qZ5&p!dE}%2QoKe7HzOHH`pj6qwItJ7NE%PH}ys~jJ zh;%9z6*=qpz^~yBa8!3@Z1C`}utNGOI~hKQx~33{4;rg0Dp#{4LYXP6j3R+3xTg^x zlvhc@;9jFhlV?C?%^LxU5`C`hclpNN?0VZSF<&a%MFFpsD6T}g-xN1(tMGJ8d$04< zf1?hp*6{oj&9S}Z#_QLhvFt;_28NHS1|TS%9Ge>&-=ZST>+RF(Mt^{; zWHEXI&C4f-Q)HmYX3XPA%qTw9e>qKf<7MlXe=9Dtb+@^7Z@%^CpVkA$Z%4A$7-+tI7h@K6MqAqLtQyPP$rB zCmZI<^b~;{`!WI9G2QIuok|8hgWf&EbloU{R(m-~0lD6@7rkBqZ$-0u>1evr2YV?( zdp|OQ&4rplw2ES9CM@8B4?gpqxLXbEExnbG#8%bBHoe6fSDg-` z-NqxnKm-Fw&)hmsouiwbQJ{fkV>R25##Vp+5@%=EmoD|jF4V>S?SuWF{}yc_B_R4k zrEBU|`i!|9=*iMbYq6U5c0+G98!AehYR9;y%Uw|LVaRFVI`0P#&JS=Vu2U~puu_Y~ zrxE;?`|wcDmjKVR6i?fh#vP5v0mFf$wTxGvck$xt!ZB8vI*cwzmx zU|{X_Uc+PNdLBHcUA$skl(|PLwpbW5QG=aOSnL1?jwuFWB$-E_k@InW#->YPJ%_L& zf!Lt?lS)F9c&*8ZT`XnnWJJLv-|%DtDb{-N#VckMB(V2&;1p-_l%sZ^^Ws#V@l@pf z>3hzTV%pR8LeoBrlU@}Q{@PQ4+Snj+l%MSENLWqAA28U}WH1vskU z-CpF}!7Tq}UYavqCR_qs#WI~#EW@j#B-%{caez=G`g6;b`wH~90tNaJ0F{pErlko! zHfl(Fm?M_>6D2{?1MhDWEWx!W@t5+T`t$cd6zHn^HyR?dUvD$RD z1g~Cg;xh}P`Si4Pi8T(!&H}piVdWG1M!nibO10b&WPS8_!%}ihUtyC-VdL)gW>nrL zhJ5pt&Xz69mXX4iqbtDf)f9)$6N%BnJ7a5iT(^nXV@9vG5=9rOt|I9Ig!cC_{S^y) tJRUe$B};TG4mXC2b7k>Q%t?B+lX6W%CXUN!-N{ - -Quick Start - - - -

Quick Start

- -The following is a step-by-step guide that shows you how to get SheepShaver -up and running in the quickest possible way. We assume that you are running -on a PowerMac that already has MacOS installed on a partition of your hard drive -and that you have booted into Linux. - -

-

    -
  1. Start the "SheepShaver" program. The "SheepShaver Settings" window will appear. -
  2. Click on "Start". SheepShaver will try to detect on which partition MacOS is installed and should then start booting MacOS. -
  3. To quit SheepShaver, select "Shutdown" from the Finder's "Special" menu. -
- -When SheepShaver hangs or crashes in fullscreen mode, pressing Ctrl-Esc should -quit it and restore the display. - -

In fullscreen mode, press Ctrl-Tab to suspend SheepShaver and return to the -normal X11 destop. Press space inside the "SheepShaver suspended" window to -reactivate it. - -

One word of caution:

- -Volumes which are used by SheepShaver must not also be mounted under Linux -while SheepShaver is running. You will lose data and corrupt the -volume if you do this! - -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/serial.gif b/SheepShaver/doc/Linux/serial.gif deleted file mode 100644 index 49ca90f95d9d0525684991a2611d9fecb741dc77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5325 zcma*m=Q|sU!^Uy6wd!;!O^mkou1)OPn;uk+D79zpO_kVUZ;2KWu}AD3i5Z(B6sKy| zsI7|1bN&8+<2;}1`|^H!t81!(q~5_u6-a-PkP!cy4Uu?5!bIYYjgb&liX1MjXH0Hyb=6Akig;po(&27-;2Ca@QrN#1Bs2zzh-tLr5j1zNLZNU zh5$Dr`G4U5-{yZ`cu7el`Ax~BQCrXhp`_&n57rjqVji$**-{o1^(6pAofik|5Ch52 zmE)N-(ZxgQ9KZQVNF%hOsQGR1K0Ng$y1B&bznyYvRmNd2As1hUj{kX8sF8keNppQu z7p0e}rK*La!&jKpJ1^lIE8ZmVnzj`yHC3AC8BUiZmN!*>ZI%fBei3u`#c;Xh@%GYi z^Zr|Tl8l0tV?^x=E|!+>?MO@A>Ocyc_9vZI^!jj)sLS$5YrVth$2;xRa_2E=)1{dQ zzhgMX^WakEIAf8^XM1y%`swj*jQ&5rU?6v&>20N_$Kp zZe=&UWlC%d+t%$H&5es1? zNw^ ziVGWWow*)se1LWA(~{_-cw8M}$+;mHfN&FCjx|dX|6aP9%0s`2@ZiEa7NvrUNLN#o zqa7C0d&0MnDQXdpt7#ex8t#ULYa z`lUzFO?1XY-_3W@)PL_}wufrxl)wkkJ)3uIPB>ezsR)JhIX>RNJNQUS{JNiyX5L@& z{Y4BVH21f5+AS)KSp04G7PF!Hj`(sGWM96N-@LrfaPOtP7lt#&I$7b9>DmOQizJ3>m`#TOsMEpnHQDa%rI;iuM$z#~O-o7Uzhe?fWU$g^IjO z8m7gsVlunD8GD2(BDjlFwhRWb@l~}^LSVw()+|K>J8C&F^_a624zc$9N2EJs!h;wx zt;`Kf{afmADJ>&infYC;=}R%a$NJMMYNn}{HF@s{8yqUzIuDJlSFHiQv#Mv5tCD(n z>-{WxoWwTXRceyv_W@`yT#LOLlsLyVJ=IYC8RHtl&B;VF%XrbHOcWJ9HDpR3cb zpmHa4;L9dyY62Z~E6nEb9h-6oRUU~u znw6W6a;$1Nm$mQGJtt*U?sX3g-rKR9XCT1O8wFfVE6msNgnnsye%!Fj89QHQNsc4e zw|aicbLUv%@67s77I@;ewJE{Mm@AL&u4SUglQTu@dg7L=Ys{m}DPqL^CbS&C(HTks zJ;>3NH@d5Ud59Tc_|@W$+_5mlc5WCL^Ad-t*!3>wu-B`Nv!QN!U66zW)n9F229)hx}1r(`Mdgb5ukL5|8H6T2q?2oAdG3sl)$VtBnV_{#E;tLg!mMC0jK_8pjc6#P~hF#6fA=yqWM9E16gGyh8pIiHPW|4CgOD!YGx+HNS`%1;*lm zrV!Cd`e>2~v7ySNJ7e%8x$>~>la1`xJI#;k4bIv!)U)stDPCJLE8CIL| zAVsp}gK~i@XIhv|h_mUT&-HW#AjY8R4YS*FuZ)Br@hvMCkW3y zv13)%-x@-<-38OpP+PYW<#L@!^|nCUTvruy8FjrkX{)z1Rp)$`c23FLXMXXhcewp2 z`b^OY@p+*)Lvg%Uoy@Xp^AC1@T0W|&JM@lsP4Jzgu3z1katFR#S1X3q=lu?hN9oB; z>!P1s$HKbiiUj{u{@s0H)GmL9Ecvr1S#`Or&OkiJxi=i96CE}b!p5d*u3>fEe}sb- zu7>-A0>>22PX{jkB!4E#{`^dQt*%-8D=dgD>^4D|Jm4c^`bTOFVH(26zm7jXXc2k@ z3cqa_PVXrEhe8_&3S}gOW0dWl2S~7jBHU>GqLe`VcG3!V5qBQhH5!6=`z+;s{jBVy z#I}qIArbCuhJ1|?DTc2(RfCo8M9Lu{b)rG{)*+dP_Y>+3rBaQg3aOwFBPm~?xJD#z z6i~$uAdWOj^o~+=gnTQC)W=0;q=KXlBS$7cpws(qEk@A~V@$Xs1!4otV}ZHpwBk{Q z#wGwCP_&F=v`%EST0mr)awks{k;%_Qk5 zsnwmVr0td@w>ry>^P~ex68!0-6O-hV!KCw?WYUeKLqako3jDklEXtB%@Xn+q^R3^z z6nIpMBQmA_&f|7*6SDr~Ym?OLJ1L5XU`-YiVPTFBuT5%Z-cHdeEc%+=2P#CYr|#Q4 zehyU7RaD^ON!wR7zYw+LJW4$y&d@f|$r~u9(*I8Hk4l}#$uUq_kf>N{44JE^n(-f6 z@KKo`Og}a{P*|CfkFlfG)3iKCWN7|=lZ~X8r^>MAd80H0{;HgDyX-OX*evArlaszT zvQ*}tRPu;BWG+xppEnIjLIGjudD+)J z2~B~pmRwkKDQ7jMGFd4M1B7Fx;Jv2sekT~qER4F>245yK66eOLrjc)(Ej$Sk3%w7|kJf__^RkXJ}= zRLCSP&UjHM%oag6`JBVd&cUnbR+{~3VbNV|(dtUk12V)H76eMkPOMG$noCEfT$5=K zq0pw&=;dyE<{FTO7`H7}iZ5O)j3rSjo}1*BUA0lPE3TM)#?s4VwBR;0#Q-Zp`lHl; zG&nLV@k|`525)%1cp`STQOJT~oW(f2VExqR#dzH0GEA=G6vW_g;&e3R(%qzJ{GFp* zA|S}Qc(b1+tw}|JD5mArrg#*{wwbHHqekr+ucb!D&f|qlE-wxBao%ZCPmnByER;2n zI!5HFxoO1?t#DO7M0vL<#v7r;$OEG0_>85!K67fo=}Ud_EKz1kF>Q_q;V6PrDY7`A zN7^Z?AL;+gM>CDJ7(?MmQqdOA0k!ws$zt6v3D|3`lolx~^hdns^?OuQY-RS8*srZq zj@S!g`Yv5vNQM-JRBv8XAJ3x@{54E3>a1;qa!s#!00I<5Nv+%!$>l)E@zDj^ZP$Yp1?Tz-^@eF8-L6dP=GiC=3 zWd|faQZ*-1`y2Yy;|tL_M=UN3O#H#YaVU0-7V5xLji6Qj<4kkTxj-7mgjR7%Xf9Qe zbW&!o@0V;?jAt7TYM5Z)ggcZQ!+b2vDhL<(HZTD~bR%vP?SQTS@vuQL{Vq#$ z-DcDKDQKRCmXdb!a~YAKug}@d(Fv1r1(Ge4WXL;mrmT4gc_{;#XJ> z8JgC6T82rhI?n2&H(O#UT9dz*MmV6XT-d^-9ph#jQp=yB*D9b3ZO?p~2u|L`3Eo-3 zmCEWIvt`!0!>zUzYz;1s<5(wqSQ7!=^ugRS{xTwDz_0zQ=j3H^TJW=sOWQfvvyjV# zapG5xCB~L(`?fW6;nm^Li#nl>E^25uKNv^8*&`joE4YaBDZ;vC;a-A8WWl}s z-n|;TT3Q{wq`^48%38f$oUUx&xpAK{P4O$)UITcaCV%gnImFwmK69piMd^N9eq3c< zx8q2!mF!2i#X9%hF3&421=)W8-M&D0U$ARmsBB-@Zf|%;F9g~f1@4WZ>5U^U;u0!x ziC|nZ4K8&Nn-0Zhg0b2B*xaig*ho)4yyvrPPoZoNf~E(#h(SRyWnfGN4W??byQZ?c z4&049>1+xaZh;TCbqseb4(FbS`;G{(FpNZqjP%lQ_lJxGrj6j?Xex8@E?1}_Q(W{V zF!n3<3%}$fG#(DByW2Qgsu4fVWauRdxw4B{2EPIYjM?UlLQO`KQlkQ4F$XljVUrCSwsG9i$=gWt70^B=z1T1zH!#$Q&(!G|D@ic*Qtr zWE)FoVI;i-(#V`t6PS*poOrAYWb2I9jxzKznbHWIx(lBY8Jzel6u?{+^ehw@GA$`v z#U)>LTbM9o>c${CIwKxB8~t#0;N67D=&X5ui_7S&kk;9fYB4{^FH_w*4_}&}TosIGUMP}VD7IKA O30 - -Setting up SheepShaver - - - -

Setting up SheepShaver

- -In the "SheepShaver Settings" window that pops up when you start SheepShaver, -you can configure certain features of SheepShaver. When you click on "Start", -the current settings are saved to disk and will be available next time you start -SheepShaver. - -

The settings are divided into four groups: Volumes, Graphics/Sound, Serial/Network and Memory/Misc. - -

Volumes

- - - -

The main part of the volumes pane is a list that contains all volumes to be mounted -by SheepShaver. If this list is empty, SheepShaver will try to detect and mount all -HFS partitions it can find. A CD-ROM drive is always automatically detected and used. - -

SheepShaver can use HFS partitions, whole HFS formatted drives, and it can also -emulate hard disks in single Linux files ("hardfiles"). - -

To add a Mac volume to the list, click on "Add...", go to the "/dev" directory -in the file panel, click once on the partition you want and click on "OK". The selected -partition device name should then appear in the volume list. After adding volumes to -the list, you should unmount them on the Linux side. To remove a Mac volume, select it -in the list and click on "Remove". - -

You can create a new, empty hardfile by clicking on "Create...". Enter the file -name and the size of the hardfile and click on "Create". The hardfile will be created (this may -take some seconds) and added to the volume list. The so-created hardfile will have to be -formatted under MacOS before you can store something in it. If you start up SheepShaver, -the Finder will display a message about an "unreadable" volume being found and give you the -option to format it. - -

Double-clicking on an entry in the volume list will add or remove a "*" in front of the -device name. Volumes marked with a "*" are read-only for the MacOS under SheepShaver. - -

SheepShaver will show a "Linux" disk icon on the Mac desktop that allows access to Linux -files from Mac applications. In "Linux Root" you specify which Linux directory will -be at the root of this virtual "Linux" disk. The default setting of "/" means that the -"Linux" icon in the MacOS Finder will correspond to your Linux root directory. The MacOS -will try to create files and folders like "Desktop", "Trash", "OpenFolderListDF" etc. -in the directory you specify as "Linux Root" (provided that you have access rights -to that directory). If they annoy you, you can delete them. - -

To boot from CD-ROM, set the "Boot From" setting to "CD-ROM". -The "Disable CD-ROM Driver" box is used to disable SheepShaver's built-in CD-ROM driver. -This is currently of not much use and you should leave the box unselected. - -

Graphics/Sound

- - - -

With "Window Refresh Rate" you can set the refresh rate of the MacOS window. -Higher rates mean faster screen updates and less "sluggish" behaviour, but also require more CPU time. - -

The "Enabled Video Modes" controls allow you to select which graphics modes -are available for displaying the MacOS desktop. You can, for example, disable the window modes -when you want to run some Mac programs in full-screen mode that would otherwise erroneously -switch to a window mode. If your X server doesn't support DGA you should disable the Fullscreen -mode. The actual mode to be used is selected in the "Monitors" control panel under MacOS. The -color depth is always that of the X11 screen and cannot be changed. - -

The "Disable Sound Output" box allows you to disable all sound output by SheepShaver. -This is useful if the sound takes too much CPU time on your machine or to get rid of warning -messages if SheepShaver can't use your audio hardware. - -

Serial/Network

- - - -

You can select to which devices the MacOS modem and printer ports are redirected. -You can assign them to any serial ports you have (/dev/ttyS*), or even to parallel -ports (/dev/lp*, useful for printing if you have Mac drivers for parallel printers, -like the PowerPrint package from www.gdt.com). - -

With "Ethernet Interface" you select which Ethernet card is to be used for -networking. It can either be the name of a real Ethernet card (e.g. "eth0") or of an ethertap -interface (e.g. "tap0"). Using a real Ethernet card requires the "sheep_net" driver to be installed -and accessible. See Using SheepShaver for more -information about setting up networking. - -

Memory/Misc

- - - -

With "MacOS RAM Size" you select how much RAM will be available to the MacOS -(and all MacOS applications running under it). SheepShaver uses the Linux virtual memory system, -so you can select more RAM than you physically have in your machine. The MacOS virtual memory -system is not available under SheepShaver (i.e. if you have 32MB of RAM in your computer and -select 64MB to be used for MacOS in the SheepShaver settings, MacOS will behave as if it's running on -a computer that has 64MB of RAM but no virtual memory). - -

"ROM File" specifies the path name of the Mac ROM file to be used. If it is left -blank, SheepShaver expects the ROM file to be called "ROM" and be in the same directory as -the SheepShaver application. - -

The "Ignore Illegal Memory Accesses" option is there to make some broken Mac -programs work that access addresses where there is no RAM or ROM. With this option unchecked, -SheepShaver will in this case display an error message and quit. When the option is activated, -SheepShaver will try to continue as if the illegal access never happened (writes are ignored, reads -return 0). This may or may not make the program work (when a program performs an illegal access, -it is most likely that something else went wrong). When a Mac program behaves strangely or hangs, -you can quit SheepShaver, uncheck this option and retry. If you get an "illegal access" message, -you will know that something is broken. - -


-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/troubleshooting.html b/SheepShaver/doc/Linux/troubleshooting.html deleted file mode 100644 index 4dc3e293..00000000 --- a/SheepShaver/doc/Linux/troubleshooting.html +++ /dev/null @@ -1,65 +0,0 @@ - - -Troubleshooting - - - -

Troubleshooting

- -

SheepShaver doesn't boot

- -SheepShaver should boot all MacOS versions >=7.5.2, except MacOS X. However, -your mileage may vary. If it doesn't boot, try again with extensions disabled -(by pressing the shift key) and then remove some of these extensions: -"MacOS Licensing Extension", Speed Doubler, 68k FPU extensions and MacsBug. - -

The colors are wrong in 16 or 32 bit graphics modes

- -If you're running SheepShaver on a something other than a PowerMac, it may be -that 16 or 32 bit graphics modes show false colors due to the frame buffer being -little-endian. Apart from patching the X server, there's unfortunately nothing -that you or SheepShaver can do about this. - -

Full-screen mode doesn't work

- -Some X servers on Linux PPC don't support DGA and full-screen mode cannot be used -with these (in this case, you should disable it in the "Graphics" settings). If you -are seeing a message like "cannot map /dev/kmem (permission denied)", you have to -either run SheepShaver as root (not recommended) or give yourself appropriate access -rights to /dev/kmem if you can login as root. - -

Ethernet doesn't work

- -
    -
  • You have to either install the sheep_net driver or configure the ethertap device in the Linux kernel to use Ethernet. See Using SheepShaver for more information. -
  • If you're using TCP/IP on the MacOS side, you have to set up different IP addresses for Linux and for the MacOS. -
- -

SheepShaver crashes, but yesterday it worked

- -Try the "Zap PRAM File" item in the main menu of the SheepShaver preferences editor. -When you are using a ROM file and switching to a different ROM version, you have -to zap the PRAM file or SheepShaver might behave very weird. - -

Known incompatibilities

- -
    -
  • MacOS programs or drivers which access Mac hardware directly are not supported by SheepShaver. -
  • Speed Doubler, RAM Doubler, 68k FPU emulators and similar programs don't run under SheepShaver. -
  • MacsBug is not compatible with SheepShaver. -
- -

Known bugs

- -
    -
  • The QuickTime 2.5 Cinepak codec crashes the emulator. -
  • Programs that use InputSprockets crash the emulator when in window mode. -
  • The mouse cursor hotspot in window mode is not correct. -
- -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/using.html b/SheepShaver/doc/Linux/using.html deleted file mode 100644 index 9fbceec5..00000000 --- a/SheepShaver/doc/Linux/using.html +++ /dev/null @@ -1,113 +0,0 @@ - - -Using SheepShaver - - - -

Using SheepShaver

- -

Changing the display mode

- -SheepShaver can display the MacOS user interface in an X11 window or full-screen -(much faster). You select the display mode as usual under MacOS in the "Monitors" -control panel (under System 7.x, click on "Options"). The "75Hz" modes are full-screen -modes, the "60Hz" modes are window modes (this doesn't mean that the video refresh -rate is 75 or 60Hz in the respective modes; the rate displayed has no meaning; it's -simply there to distinguish full screen modes from window modes). - -

Full-screen mode

- -The full-screen mode uses the whole X11 screen for displaying the MacOS user interface. -You can temporarily switch back to the X11 desktop by pressing Ctrl-Tab. The MacOS (and -all MacOS applications) will now be suspended. You can resume SheepShaver by activating -the "SheepShaver suspended" window and pressing the space key. Using full-screen mode -requires a DGA capable X server. - -

Networking

- -There are three approaches to networking with SheepShaver: - -
    -
  1. Direct access to an Ethernet card via the "sheep_net" driver. -In this case, the "ethernet card description" must be the name -of a real Ethernet card, e.g. "eth0". It also requires the "sheep_net" -driver to be installed and accessible. This approach will allow you -to run all networking protocols under MacOS (TCP/IP, AppleTalk, IPX -etc.) but there is no connection between Linux networking and MacOS -networking. MacOS will only be able to talk to other machines on -the Ethernet, but not to other networks that your Linux box routes -(e.g. a second Ethernet or a PPP connection to the Internet). - -
  2. Putting SheepShaver on a virtual Ethernet via the "ethertap" device. -In this case, the "ethernet card description" must be the name -of an ethertap interface, e.g. "tap0". It also requires that you -configure your kernel to enable routing and the ethertap device: -under "Networking options", enable "Kernel/User netlink socket" and -"Netlink device emulation", under "Network device support", activate -"Ethertap network tap". You also have to modify devices/net/ethertap.c -a bit before compiling the new kernel: - -
      -
    • insert #define CONFIG_ETHERTAP_MC 1 near the top (after the #include lines) -
    • comment out the line dev->flags|=IFF_NOARP; in ethertap_probe() -
    - -

    -Next, see /usr/src/linux/Documentation/networking/ethertap.txt for -information on how to set up /dev/tap* device nodes and activate the -ethertap interface. Under MacOS, select an IP address that is on the -virtual network and set the default gateway to the IP address of the -ethertap interface. This approach will let you access all networks -that your Linux box has access to (especially, if your Linux box has -a dial-up Internet connection and is configured for IP masquerading, -you can access the Internet from MacOS). The drawback is that you -can only use network protocols that Linux can route, so you have to -install and configure netatalk if you want to use AppleTalk. Here is -an example /etc/atalk/atalkd.conf for a LAN: - -

    -eth0 -seed -phase 2 -net 1 -addr 1.47 -zone "Ethernet"
    -tap0 -seed -phase 2 -net 2 -addr 2.47 -zone "Sheepnet"
    -
    - -(the "47" is an arbitrary node number). This will set up a zone -"Ethernet" (net 1) for the Ethernet and a zone "Sheepnet" (net 2) -for the internal network connection of the ethertap interface. -MacOS should automatically recognize the nets and zones upon startup. -If you are in an existing AppleTalk network, you should contact -your network administrator about the nets and zones you can use -(instead of the ones given in the example above). - -
  3. Networking protocols for serial connections (PPP and SLIP, for example) -can be used provided that you have the appropriate MacOS system components -installed (e.g. Open Transport/PPP). -
- -

Using floppy disks

- -Floppy disks are not automatically detected when they are inserted. They have to be -mounted explicitly: after inserting a floppy disk, press Ctrl-F1. - -

Accessing Linux files

- -SheepShaver will display a "Linux" disk icon on the Mac desktop that allows you -to access any Linux files which are in the directory specified as "Linux Root" -in the "Volumes" pane of the SheepShaver settings. You can open and save files on the -"Linux" disk from Mac applications, copy, move or rename files from the Finder etc. -SheepShaver translates some file name extensions to MacOS types and vice versa, -so e.g. *.jpg and *.pdf files will show the correct icons in the Finder. MacOS -resources and Finder attributes are stored in hidden .rsrc and -.finf directories. - -

Copying text via the clipboard

- -SheepShaver tries to keep the Linux and MacOS clipboards synchronized. That means, -when you copy a piece of text under Linux, you can paste it into a MacOS application -and vice versa. - -
-
-SheepShaver User's Guide -
- - diff --git a/SheepShaver/doc/Linux/volumes.gif b/SheepShaver/doc/Linux/volumes.gif deleted file mode 100644 index 676248b7acd71ad6e381e0c209561415e925aeca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7705 zcmZ|TRag^%8pd%DQIrr+knTFyp~lG0rR1`GzH$LQ`Z>5`BR>F&;*=iDAS zzvqAT-M=@Vl#C=VpK%(p5b`w=65{_dMIins4g}(#Mv)NzR*H@IHz*R~pRS*C{G8?I zOh0GzUr?mcf9ics>vL+KQ~I2|=Rlu_1cm;SDH8Ob5}y%UhJ>T?Te)lizJb$f(<0l9#Rx21w^2{W-%RfWvqrPKoCzH07$jy zSekIq-PFMOic+?80@l*N#a@><2&Xjz&jI<+mKbqa_}8MXE>-lW;P4Xij8zDKUoq`u1=DGfWD>l+&bN7uDfV0F9Unh7EDm3dQ3S;Ay88*V zp%z7hBJ*|-p8j+WD9FpORw_jJ^N$x-^dgw{OKPUAnZ*eS1LASA?L4hgk8dLujq34j z4#ZT+iVv!WzwFyqlAkv106dFcvG{e7@uV0oy6qp<{|#k6lJWPMDo$vR#Ak7u%&0qT zIO%0RZn>CFQ*Ig?q0Jw?s)mp_M~$w5atm3aF=G~cxVuQ^6P`9El0x( zmzoMlH)U$6)3E`|SwBrOiApcA9f@8o8A=K3AYC8J`S9!RpAO9|hRyIHiUs-eG2z!s zrDOOq-g={ZCPU}3qCAHelZM$P`x27(vU)?^5_&t+dhUnZzS7st_S3q(O5>JR`K4F$ zkU}~N1`Cvqt3}tDk-CK)gVOVMGXVr){gMm9RNPqd;l0>uATiKmHH2{aX5D`*hG)@I zY8kT5!GJ})2z2-5wGHwk<6lE`*fm;u92dJ!2wXp2?pO4&HG3KhJe(dZY8T!gwOk+F zA9uWFe>nN|(c$5=pT7LzY?#OIYj<%}Y0Z9*r^n`xxFWERy)fCXJ>*wFra?QtXHc$P zzzFzT3{uCd%X=j;G@m|iAq?nr1H06>hllI$pa+uoSkoVpg!Zv}znU;-z4#aoosWs} z@2kv6NmR@Ito_^Dlq&uwRs-d1KRl453z{9A5Z|f5a;r18=8e zS0s-2ei98S`Jxqj1npY|&X^s-X88d?lwM*0(NOi*G!B_kz{q$J52 zMtyiQQQc9f9!4%fpB5?mSxmH*d@j)lX9suFX^f+qB5^D{q$}mfHH|~ReXYOm=w$eCh@49JvrZdqe!xt|nSwF(CpN4rLS#lj|5Txy*u5 z&(4<14Rsa*Kh=yUOI8GM9PY+P%aWRd>?Wuu3r`@qyfj22nnOB) zg>_W0AK3csR+?}`?NwdFkJ7F!>v??1OY=s|GRM_R9i(4iooYc-J5_FrS z1n+57)Pu&^5jM@7A>F%5#m4qSh+CiBa^k_2)l@5~%h1sB75tz@O3h7DXu=oWFqji{A$r#a12by9<;KKY8l3#t3Zj9>UnOx<7LQ2DYY;%BOcalc>t8#nL`d6e~oGchC??+Nqtj;fP=Qc2L?zEL81sVJG7&>_Uk z^?PU}Pb^_lJ@sw=I1q~g)-7j*>oq@VGE!4O*syyS7@f&K6&G=5O3c`0DfzpA3db8I zO$TW^jGT(=om7pc209&&>QpVnuas(Kwy7xh$h2@g^}xa=b!-$^mzYgNzpZ^g-{ewM zQ~xM~tf`VHVo+sFL5QO3-0V+|?{1vRBIPjoW>GpL8t2m+J`IthWiVxZ~|?7E=8BiyQzDhm&6A2x}wP6ZnU)(A8ULOze4#zkVL3}Q6)ODUe2 zedZk7K!m{MjHpIZjW}85DPG#%RVbSE{@mhbza4QAJ+G?>*`SwdbW>k;PSdO2Q3XUs zxaBD1X$o)o^wW=Ivt8zGRI|y3VNU*7bFJ)OWN_i2r_6YYElBoZP#$RdGGKp|A(oeM zK@+7ncys|rtP|aT@EQ!bJ+s!CO!di>{pKPXUOMx08$lqj)|ZiR++dOx^u1*@_Vdkg zmg??;-cJE@+}p1Djr|DAff)&hG0!?PHZc3(d_JygtI)?(+St|u%kTHiS@W0WGgx)* zWB1GVPuCsq+D^j0Kdc!x`z9PUoT<(!fqgIXx+Sm9@`Vbv)*VTOxyJcH;>yR$%98LZ zF2rS@ANl@})ZNB+A@8pi4_D2I$CKFhhwbl(Ek?b^8^gbk=VOSu!}hkzE;bZue=0Hm z3lsknkkI`{>$7-uogRP7HGdCW<6C7X$14BTNg_>VV|0h}xaS|&Dks1p_jUY0#AnYxFW(Fz}Y3ex?YT=w9N|VLMeD+<3VO?|YW$}i#_U+A&k=!NJ684Sdrs<&>8>0(RJ}|;EBYW*8R}~cubBAsIr~Ti!5VM{~a3n zvd*YRE2_>T>J2{YL{H?0eg@P^ERYgYTn|&Qy7mj?=&l=0eRY0M)VH%?!JvxhT#;xu zikL{$=;S2r4iBwatLWb;F`!ze)$phdEnpU&&ch$WW`Za4L!o>LAL;zv(dKFkh8k|3yv`?Gt6~Un$k!Yt4F4ao% z=1W-=O;+p$U6_MCWm2LGKZf3ht9T|y@+r`4muGb#S|(%>6s4hwy)Yu6WOI0k4WeEWSWKuCZK1&t>A?5hD1q@tX)S`1P@LK)7`AWOo_^x7k!h8Y7L_a)eL@9r6~B2*&xGsmh!} zSM#PhJ#UK~2Y`7!4->7ECFeXBw{aN z&p{(ka4*;HMQ$QZu4byPP!lBL7U~2;)sNIah7cKZ%ZyA!uocnk3`#|OAxoKtSDeEI zE^VYz^Q!|yqyi;W2#6^fL^uHkucD&2s$cd%Wt5Rw1=c*XFyUI8Ze^M(j$%1f ziLt(7kt#L8KY@}>MeK=1<%2kymp=3pG!k7t+tvBxDz@)~16z72S@URI3Q7p30*pjU z3ihC_3`9%2rFPaO8(w9uFUnXV%a#YD4(`epPyJ5#%ZDh-FTBbFeM}Seve51-(>F3IVC7XC6{oKVBN1u@Zuls9pz7$vY8ttUN9!tIwd#Zb z89ot*bWum%p-hldWvQ$*7jgEUMwO@lDFd^;B09`?p1S%1U~pe+L|kVgP-kjGAfj74 zB2s7FTxVNc_lc&Od7{o)px$*KU^S$C4vcgaFi z*#drPa#ImAKD%;rolSFjT5}VzcO`T4D=}9*e^(A157|x^+j>to;})f`7Rvk<%hw+q zl3l81n%nkue$uya2DHiqxNvaLa@D(-BCb7y>lK0ZKgOCBdAD14%|85XR#aG3+-7de z4s*Lu^P)RzEtq+4U9X@b()!1Sy~D=UKfhH4$8+Di1D@ZmY}^5V?e%u}-z_LR$) z&JIWV);B*p30u5M!kQ519Ww$7zV5E}@!w79U4D#rY>0b3*!*x+My8W@V=U>Ebix$k z_;}9j!usIC5#41r({(1^&CT=CN6B69+C_A=oxB80N%G$B+WpsllXOdSHBS#|%P(%1 z*81k2m%~jO@;#KvKVmiIWutq3)ixPHd#%4ZtK&4-AM{%1)H{D=!8-4C``PCK?Ry>Y z(`B)*z}VN9rO!W_sBKj}0HZueuW%L7oga3P6R}uaLRUKK_01amW?`GuL?t99+9}o+ z##URZb>zA#S!=MSX(D`7! z7s+tf*I}}^^=;Apy+4N!QtJoh^M@CQfzaXK2c>64mS`p;C{<+}0VC)+Bj=qX*lQ!x z$fJL4$v20UCJu`57+|@O)le|6*B3(0A3sIxhQpRE>MaHB+AtiwzVFKVV z0~2bEE+TU@s?-)yS`VV3e#$0XK(S`xp>}BYIas# z4*iJ_uyA1z)m!~3u5=MkG&M#$3zqah3<|`e!IL_3j#n&j{v1@gLn`Z6RL$ApF5%)K z1jcV!CA6GrBW}b^ss7k5P3ntU*u?z7Qy53}nHGH%Q5P&}7>DtJs31nK&FrRKOD8<+ zV2sYTM)-8Pf)X;V>2duP1E*u_<73zz2aG5PX=cCiLVC=C{>5lZ%xJ1l?&PB1R_fwy{o-(`@95*=#>b^V zWxr{krP=hQ`PQYTTu1?e5N5)f`0MNP#$zuz4oYibZTl{8b7}dAG``6r{$v-tcM$cm zQaiE-`$iBLzZv&Xx&jaM877Er#gDC}_?v6|7tI%YIDF;!@$U$Txf!%<)U@n=$xzHe zemxXlA-y)OO$J}=EoiPn7)#rzQ%I226ooQHdr67VutbQoW;N$ zqY_>!qvv);Q`ut&ZDPJa-XJ7f^ZTJKhs7j4x*?OXri8^Py{s++-0)K0q$t~zvB$=I zTKPh@RizToXCJ>TxZ>Y9hC025i@b%ty7l&S<$-nE#9$k$&LtVQ?PZYq;b}>Cf8C92 zC$Np>)Mx9f@8Tswp}zsp>kN2p^&4B@sZY>XKe{X}He%k_ezjP8H`8+$vuJs}Xa|~+ zmQj|S^^|o~wUhgll&82P*0>ilx3?#|TVW5WdaAi*;i$FW_wj^-fII1LlA9G%>V5Y} zywbW2AUy`F*%^BSWc#h((!!1w=pzrt6c5G?l81qNO}>ZTjR%nBgQcUxn2f_Pz`>tU zhK;AgEiB0D=wW%=QOWXA3UI5iaI1*znC#8b71r`i*|F2W@ucEPC)+YoCin$ne+sy` z=X+uVIU(oX?btjyX9IKH9`!Asd~is@&V-<6?u@pbl6*hTY&#@m-=jKCB+Z1s&peZ8 zJi}#AVMDYh0I_yM%T8Wq?w@`;ryod*Cp+yZJHH)0*P=`HYTLH(J$-!Iu2H=B)M)qt za$y*A4ge-7mM4^JZ>bz7%a!j&d0yVLt*T9K>$4vTyt^vfKIeINL2h_54ZJcw#;Gbi zB*;7p#<+HFydujyUu9kTEx4~s)fgyr6TH%ZrE(LVc@ueDr#g1^le{b}xJMHImK>wn z)$r<_SMA59TL~~!eCRgon1FC^F_rud-cEq$byswp3HCdpbGXiHzbnqXt1`ULeRspG zQaKdCyY5LK@10#!4rRN#uN^ZhJw8hDJF8?*hrV8 zTp;MOQiC7=dfqoIU!ULJPDH$duRn~kKkk2jcrW|d8}SI7dVq940y!PK{T1e|QwSEV&XiSOEM*Xx`TW$bD)<|wY!9HiNHJ5; z=S9-|pMA{=;~pTb?sUl*OmD2rd|~=fx8Y@ieV*)Ok$#Cltv%|WnPbC_0MvJMdb20S zzasG1Efxt*g!|%Yzr*$B&Nj+EnQF8~XzndHWJ|=->CayPrV7=){~UnM|BMxzkHHc8 z3s-iF#kwDV9`f1P|LqKUM{n@;!oJZ>U_07w@z!N$Ja4~D*QF8M!Xffq)9(Dt{baQ# zmfrB&!&T;=z3N8uNj-N>zlzg4j6t`>DM z+g?y7I*Pt!t~n9KK>g}Szwv4>MzFQ*&hnRERYH__NezWEdZ085PKn<#3hg%%$(JXY z7%o#zQe@u4j@>Ezi2#um(F>;DR1-BPaeTu>#$G=y*EceF31$<63^pXnU(k>{PBRJB zFI3QxennTwleAtqDSTOQby1+u$DN?25}8sI4=8fQ8EiQa{+usl^HW7BAd3WT03oaz z^c(AQr?|_o)Yu2r5gz8+3l;h6sOl^}pIh^(lT4w!24`S$mOghu^sHDW1THlG087vSD|Cy ze0jA{Ur{?cC(y}#t>-#vuF>ff#iF@XePA?5=doYQBj`3Wc{S(V14^DvyThB+bGk$Y zQy9NqF3BA)QMp;QMt{OnD=bL-kuT2fcC-=*HXAYy7jsiGan_f;QBpU&sFqCEp!=|i zqwq+dAgUXxf{y1jox%mwq~#i9(j1+jkCXVq&ktJSCLE*Dz6u}9M`vYNM~K-yY482< z0uQL=k~e8sh8enOS-CC|iWd zov5y13D((Js?O*0IO!%bu**>|kG-UC9-C0Akc+wVn(_C=kr8sRtbJNU4Ut5L`1B&a z(;U7dnxHni!I1vgk;I~BB#CBPsBUu6vb#9L7ErRw~OW+M;{TX{geU`jx>vpE-}S8 z3hxInI)i8cF!FAK9%(l71QJFV?Yjt>9V_QVqFowoGR7p1US$x`Z5WP;f2bb|O)}mb zEj_cRj2h4uOwvh9WPkh4R1%g<3)s{$XiQQ9(ojoM#Iu?{RSetgso-LC(lPsa4jK_j zCDph}v$+El^>bj5r#sk9P9u(4uYc<9@YdJr0fmG_+>}-MjZZu(!#2~O(?G)8g6DHm znsx7^j`cPrFWxBnVp&4z_|R0R3Bi`m;n|q_13c9HB@xbvR3B00B!g;{<8?N&$?@O} zsya9z-yWEAB#hM7OBK4MmM^dg`0jHz8F`eDH_F%lJ;qB7Mu(R@s= 4.0.1 is used. The more accurate engine is enabled with ''PPC_ENABLE_FPU_EXCEPTIONS''. - -===== Features ===== - - * Self-contained. No guest OS nor any complicated run-time environment is required. Your CPU emulator simply needs to support a special opcode (''0x18000000'', OP=6) that terminates execution of the current basic block. - - * Supports several CPU cores: SheepShaver, [[http://microlib.org/projects/ppc750sim/|Microlib PPC 750 Simulator]], [[http://model3emu.sourceforge.net/|Sega Model 3 Arcade Emulator]], [[http://www.qemu.org/|QEMU]]. - - * Supports the AltiVec ISA. - - * Generates more than 2 million tests with specific values to trigger condition codes changes, unspecified results (matches a PowerPC 7410, aka my Powerbook G4). - -===== Downloads ===== - - * The primary source is available in SheepShaver CVS. - - * It is recommended that you first run the tester on a native PowerPC platform to generate a results file. For reference, here is the [[this>projects/ppctester/files/ppc-testresults.dat.bz2|PowerPC Emulator Tester results file]] I use for SheepShaver. This was generated with AltiVec tests enabled. This is for revision 1.30+ of the file. md5sum is: ''3e29432abb6e21e625a2eef8cf2f0840''. - -===== Links ===== - - * [[http://www.valgrind.org/|Valgrind]] contains an interesting testsuite for the VEX. - * [[http://perso.magic.fr/l_indien/qemu-ppc/|Qemu-PPC]] contains part of the original ALU tests used in VEX. \ No newline at end of file diff --git a/SheepShaver/src/BeOS/CreatePCIDrivers/Ethernet.cpp b/SheepShaver/src/BeOS/CreatePCIDrivers/Ethernet.cpp deleted file mode 100644 index c6c0fbf4..00000000 --- a/SheepShaver/src/BeOS/CreatePCIDrivers/Ethernet.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Ethernet.cpp - SheepShaver ethernet PCI driver stub - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include -#include "xlowmem.h" -#include "ether_defs.h" - - -/* - * Driver Description structure - */ - -struct DriverDescription { - uint32 driverDescSignature; - uint32 driverDescVersion; - char nameInfoStr[32]; - uint32 version; - uint32 driverRuntime; - char driverName[32]; - uint32 driverDescReserved[8]; - uint32 nServices; - uint32 serviceCategory; - uint32 serviceType; - uint32 serviceVersion; -}; - -#pragma export on -DriverDescription TheDriverDescription = { - 'mtej', - 0, - "\pSheepShaver Ethernet", - 0x01008000, // V1.0.0final - 4, // kDriverIsUnderExpertControl - "\penet", - 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 'otan', - 0x000a0b01, // Ethernet, Framing: Ethernet/EthernetIPX/802.2, IsDLPI - 0x01000000, // V1.0.0 -}; -#pragma export off - - -/* - * install_info and related structures - */ - -static int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds); -static int ether_close(queue_t *rdq, int flag, void *creds); -static int ether_wput(queue_t *q, msgb *mp); -static int ether_wsrv(queue_t *q); -static int ether_rput(queue_t *q, msgb *mp); -static int ether_rsrv(queue_t *q); - -struct ot_module_info { - uint16 mi_idnum; - char *mi_idname; - int32 mi_minpsz; // Minimum packet size - int32 mi_maxpsz; // Maximum packet size - uint32 mi_hiwat; // Queue hi-water mark - uint32 mi_lowat; // Queue lo-water mark -}; - -static ot_module_info module_information = { - kEnetModuleID, - "SheepShaver Ethernet", - 0, - kEnetTSDU, - 6000, - 5000 -}; - -typedef int (*putp_t)(queue_t *, msgb *); -typedef int (*srvp_t)(queue_t *); -typedef int (*openp_t)(queue_t *, void *, int, int, void *); -typedef int (*closep_t)(queue_t *, int, void *); - -struct qinit { - putp_t qi_putp; - srvp_t qi_srvp; - openp_t qi_qopen; - closep_t qi_qclose; - void *qi_qadmin; - struct ot_module_info *qi_minfo; - void *qi_mstat; -}; - -static qinit read_side = { - NULL, - ether_rsrv, - ether_open, - ether_close, - NULL, - &module_information, - NULL -}; - -static qinit write_side = { - ether_wput, - NULL, - ether_open, - ether_close, - NULL, - &module_information, - NULL -}; - -struct streamtab { - struct qinit *st_rdinit; - struct qinit *st_wrinit; - struct qinit *st_muxrinit; - struct qinit *st_muxwinit; -}; - -static streamtab the_streamtab = { - &read_side, - &write_side, - NULL, - NULL -}; - -struct install_info { - struct streamtab *install_str; - uint32 install_flags; - uint32 install_sqlvl; - char *install_buddy; - void *ref_load; - uint32 ref_count; -}; - -enum { - kOTModIsDriver = 0x00000001, - kOTModUpperIsDLPI = 0x00002000, - SQLVL_MODULE = 3, -}; - -static install_info the_install_info = { - &the_streamtab, - kOTModIsDriver /*| kOTModUpperIsDLPI */, - SQLVL_MODULE, - NULL, - NULL, - 0 -}; - - -// Prototypes for exported functions -extern "C" { -#pragma export on -extern uint32 ValidateHardware(void *theID); -extern install_info* GetOTInstallInfo(); -extern uint8 InitStreamModule(void *theID); -extern void TerminateStreamModule(void); -#pragma export off -} - - -/* - * Validate that our hardware is available (always available) - */ - -uint32 ValidateHardware(void *theID) -{ - return 0; -} - - -/* - * Return pointer to install_info structure - */ - -install_info *GetOTInstallInfo(void) -{ - return &the_install_info; -} - - -/* - * Init module - */ - -asm uint8 InitStreamModule(register void *theID) -{ - lwz r2,XLM_TOC - lwz r0,XLM_ETHER_INIT - mtctr r0 - bctr -} - - -/* - * Terminate module - */ - -asm void TerminateStreamModule(void) -{ - lwz r2,XLM_TOC - lwz r0,XLM_ETHER_TERM - mtctr r0 - bctr -} - - -/* - * DLPI functions - */ - -static asm int ether_open(register queue_t *rdq, register void *dev, register int flag, register int sflag, register void *creds) -{ - lwz r2,XLM_TOC - lwz r0,XLM_ETHER_OPEN - mtctr r0 - bctr -} - -static asm int ether_close(register queue_t *rdq, register int flag, register void *creds) -{ - lwz r2,XLM_TOC - lwz r0,XLM_ETHER_CLOSE - mtctr r0 - bctr -} - -static asm int ether_wput(register queue_t *q, register msgb *mp) -{ - lwz r2,XLM_TOC - lwz r0,XLM_ETHER_WPUT - mtctr r0 - bctr -} - -static asm int ether_rsrv(register queue_t *q) -{ - lwz r2,XLM_TOC - lwz r0,XLM_ETHER_RSRV - mtctr r0 - bctr -} diff --git a/SheepShaver/src/BeOS/CreatePCIDrivers/Makefile b/SheepShaver/src/BeOS/CreatePCIDrivers/Makefile deleted file mode 100644 index f9f12eee..00000000 --- a/SheepShaver/src/BeOS/CreatePCIDrivers/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -all: ../../EthernetDriverStub.i ../../VideoDriverStub.i - -clean: - -rm *.o hexconv Ethernet Video - -../../EthernetDriverStub.i: Ethernet hexconv - hexconv $< $@ - -../../VideoDriverStub.i: Video hexconv - hexconv $< $@ - -hexconv: hexconv.cpp - mwcc -o hexconv hexconv.cpp - -Ethernet.o: Ethernet.cpp - mwcc -I.. -I../../include -o $@ -c $< - -Video.o: Video.cpp - mwcc -I.. -I../../include -o $@ -c $< - -Ethernet: Ethernet.o - mwldppc -xms -export pragma -nostdentry -nostdlib -o $@ $< - -Video: Video.o - mwldppc -xms -export pragma -nostdentry -nostdlib -o $@ $< diff --git a/SheepShaver/src/BeOS/CreatePCIDrivers/Video.cpp b/SheepShaver/src/BeOS/CreatePCIDrivers/Video.cpp deleted file mode 100644 index 1e1c9b24..00000000 --- a/SheepShaver/src/BeOS/CreatePCIDrivers/Video.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Video.cpp - SheepShaver video PCI driver stub - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "xlowmem.h" - - -/* - * Driver Description structure - */ - -struct DriverDescription { - uint32 driverDescSignature; - uint32 driverDescVersion; - char nameInfoStr[32]; - uint32 version; - uint32 driverRuntime; - char driverName[32]; - uint32 driverDescReserved[8]; - uint32 nServices; - uint32 serviceCategory; - uint32 serviceType; - uint32 serviceVersion; -}; - -#pragma export on -struct DriverDescription TheDriverDescription = { - 'mtej', - 0, - "\pvideo", - 0x01008000, // V1.0.0final - 6, // kDriverIsUnderExpertControl, kDriverIsOpenedUponLoad - "\pDisplay_Video_Apple_Sheep", - 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 'ndrv', - 'vido', - 0x01000000, // V1.0.0 -}; -#pragma export off - - -// Prototypes for exported functions -extern "C" { -#pragma export on -extern int16 DoDriverIO(void *spaceID, void *commandID, void *commandContents, uint32 commandCode, uint32 commandKind); -#pragma export off -} - - -/* - * Do driver IO - */ - -asm int16 DoDriverIO(void *spaceID, void *commandID, void *commandContents, uint32 commandCode, uint32 commandKind) -{ - lwz r2,XLM_TOC - lwz r0,XLM_VIDEO_DOIO - mtctr r0 - bctr -} diff --git a/SheepShaver/src/BeOS/CreatePCIDrivers/hexconv.cpp b/SheepShaver/src/BeOS/CreatePCIDrivers/hexconv.cpp deleted file mode 100644 index 59a0a3e0..00000000 --- a/SheepShaver/src/BeOS/CreatePCIDrivers/hexconv.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include - -int main(int argc, char **argv) -{ - if (argc != 3) { - printf("Usage: %s \n", argv[0]); - return 0; - } - - FILE *fin = fopen(argv[1], "rb"); - if (fin == NULL) { - printf("Can't open '%s' for reading\n", argv[1]); - return 0; - } - - FILE *fout = fopen(argv[2], "w"); - if (fout == NULL) { - printf("Can't open '%s' for writing\n", argv[2]); - return 0; - } - - unsigned char buf[16]; - while (!feof(fin)) { - fprintf(fout, "\t"); - int actual = fread(buf, 1, 16, fin); - for (int i=0; i@ - -# specify the source files to use -# full paths or paths relative to the makefile can be included -# all files, regardless of directory, will have their object -# files created in the common object directory. -# Note that this means this makefile will not work correctly -# if two source files with the same name (source.c or source.cpp) -# are included from different directories. Also note that spaces -# in folder names do not work well with this makefile. -SRCS= ../main.cpp main_beos.cpp ../prefs.cpp ../prefs_items.cpp prefs_beos.cpp \ - prefs_editor_beos.cpp sys_beos.cpp ../rom_patches.cpp ../rsrc_patches.cpp \ - ../emul_op.cpp ../name_registry.cpp ../macos_util.cpp ../timer.cpp \ - timer_beos.cpp ../xpram.cpp xpram_beos.cpp ../adb.cpp clip_beos.cpp \ - ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp scsi_beos.cpp \ - ../video.cpp video_beos.cpp ../audio.cpp audio_beos.cpp ../ether.cpp \ - ether_beos.cpp ../serial.cpp serial_beos.cpp ../extfs.cpp extfs_beos.cpp \ - about_window_beos.cpp ../user_strings.cpp user_strings_beos.cpp ../thunks.cpp - -# specify the resource files to use -# full path or a relative path to the resource file can be used. -RSRCS= SheepShaver.rsrc - -# @<-src@ -#%} - -# end support for Pe and Eddie - -# specify additional libraries to link against -# there are two acceptable forms of library specifications -# - if your library follows the naming pattern of: -# libXXX.so or libXXX.a you can simply specify XXX -# library: libbe.so entry: be -# -# - if your library does not follow the standard library -# naming scheme you need to specify the path to the library -# and it's name -# library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS= be tracker game media translation textencoding device GL - -# specify additional paths to directories following the standard -# libXXX.so or libXXX.a naming scheme. You can specify full paths -# or paths relative to the makefile. The paths included may not -# be recursive, so include all of the paths where libraries can -# be found. Directories where source files are found are -# automatically included. -LIBPATHS= - -# additional paths to look for system headers -# thes use the form: #include
-# source file directories are NOT auto-included here -SYSTEM_INCLUDE_PATHS = - -# additional paths to look for local headers -# thes use the form: #include "header" -# source file directories are automatically included -LOCAL_INCLUDE_PATHS = ../include SheepDriver SheepNet - -# specify the level of optimization that you desire -# NONE, SOME, FULL -OPTIMIZE= FULL - -# specify any preprocessor symbols to be defined. The symbols will not -# have their values set automatically; you must supply the value (if any) -# to use. For example, setting DEFINES to "DEBUG=1" will cause the -# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" -# would pass "-DDEBUG" on the compiler's command line. -DEFINES= - -# specify special warning levels -# if unspecified default warnings will be used -# NONE = supress all warnings -# ALL = enable all warnings -WARNINGS = - -# specify whether image symbols will be created -# so that stack crawls in the debugger are meaningful -# if TRUE symbols will be created -SYMBOLS = - -# specify debug settings -# if TRUE will allow application to be run from a source-level -# debugger. Note that this will disable all optimzation. -DEBUGGER = - -# specify additional compiler flags for all files -COMPILER_FLAGS = -prefix BeHeaders - -# specify additional linker flags -LINKER_FLAGS = - - -## include the makefile-engine -include /boot/develop/etc/makefile-engine - diff --git a/SheepShaver/src/BeOS/NetPeek/Makefile b/SheepShaver/src/BeOS/NetPeek/Makefile deleted file mode 100644 index 233c7e5f..00000000 --- a/SheepShaver/src/BeOS/NetPeek/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -## BeOS Generic Makefile v2.1 ## - -## Fill in this file to specify the project being created, and the referenced -## makefile-engine will do all of the hard work for you. This handles both -## Intel and PowerPC builds of the BeOS. - -## Application Specific Settings --------------------------------------------- - -# specify the name of the binary -NAME= NetPeek - -# specify the type of binary -# APP: Application -# SHARED: Shared library or add-on -# STATIC: Static library archive -# DRIVER: Kernel Driver -TYPE= APP - -# add support for new Pe and Eddie features -# to fill in generic makefile - -#%{ -# @src->@ - -# specify the source files to use -# full paths or paths relative to the makefile can be included -# all files, regardless of directory, will have their object -# files created in the common object directory. -# Note that this means this makefile will not work correctly -# if two source files with the same name (source.c or source.cpp) -# are included from different directories. Also note that spaces -# in folder names do not work well with this makefile. -SRCS= NetPeek.cpp - -# specify the resource files to use -# full path or a relative path to the resource file can be used. -RSRCS= - -# @<-src@ -#%} - -# end support for Pe and Eddie - -# specify additional libraries to link against -# there are two acceptable forms of library specifications -# - if your library follows the naming pattern of: -# libXXX.so or libXXX.a you can simply specify XXX -# library: libbe.so entry: be -# -# - if your library does not follow the standard library -# naming scheme you need to specify the path to the library -# and it's name -# library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS= - -# specify additional paths to directories following the standard -# libXXX.so or libXXX.a naming scheme. You can specify full paths -# or paths relative to the makefile. The paths included may not -# be recursive, so include all of the paths where libraries can -# be found. Directories where source files are found are -# automatically included. -LIBPATHS= - -# additional paths to look for system headers -# thes use the form: #include
-# source file directories are NOT auto-included here -SYSTEM_INCLUDE_PATHS = - -# additional paths to look for local headers -# thes use the form: #include "header" -# source file directories are automatically included -LOCAL_INCLUDE_PATHS = ../ ../../include ../NetAddOn - -# specify the level of optimization that you desire -# NONE, SOME, FULL -OPTIMIZE= FULL - -# specify any preprocessor symbols to be defined. The symbols will not -# have their values set automatically; you must supply the value (if any) -# to use. For example, setting DEFINES to "DEBUG=1" will cause the -# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" -# would pass "-DDEBUG" on the compiler's command line. -DEFINES= - -# specify special warning levels -# if unspecified default warnings will be used -# NONE = supress all warnings -# ALL = enable all warnings -WARNINGS = - -# specify whether image symbols will be created -# so that stack crawls in the debugger are meaningful -# if TRUE symbols will be created -SYMBOLS = - -# specify debug settings -# if TRUE will allow application to be run from a source-level -# debugger. Note that this will disable all optimzation. -DEBUGGER = - -# specify additional compiler flags for all files -COMPILER_FLAGS = - -# specify additional linker flags -LINKER_FLAGS = - - -## include the makefile-engine -include /boot/develop/etc/makefile-engine - diff --git a/SheepShaver/src/BeOS/NetPeek/NetPeek.cpp b/SheepShaver/src/BeOS/NetPeek/NetPeek.cpp deleted file mode 100644 index ccf5629a..00000000 --- a/SheepShaver/src/BeOS/NetPeek/NetPeek.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * NetPeek.cpp - Utility program for monitoring SheepNet add-on - */ - -#include "sysdeps.h" -#include "sheep_net.h" - -#include - -static area_id buffer_area; // Packet buffer area -static net_buffer *net_buffer_ptr; // Pointer to packet buffer - -int main(void) -{ - area_id handler_buffer; - if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) { - printf("Can't find packet buffer\n"); - return 10; - } - if ((buffer_area = clone_area("local packet buffer", &net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) { - printf("Can't clone packet buffer\n"); - return 10; - } - - uint8 *p = net_buffer_ptr->ether_addr; - printf("Ethernet address : %02x %02x %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3], p[4], p[5]); - printf("read_sem : %d\n", net_buffer_ptr->read_sem); - printf("read_ofs : %d\n", net_buffer_ptr->read_ofs); - printf("read_packet_size : %d\n", net_buffer_ptr->read_packet_size); - printf("read_packet_count : %d\n", net_buffer_ptr->read_packet_count); - printf("write_sem : %d\n", net_buffer_ptr->write_sem); - printf("write_ofs : %d\n", net_buffer_ptr->write_ofs); - printf("write_packet_size : %d\n", net_buffer_ptr->write_packet_size); - printf("write_packet_count: %d\n", net_buffer_ptr->write_packet_count); - - printf("\nRead packets:\n"); - for (int i=0; iread[i]; - printf("cmd : %08lx\n", p->cmd); - printf("length: %d\n", p->length); - } - printf("\nWrite packets:\n"); - for (int i=0; iwrite[i]; - printf("cmd : %08lx\n", p->cmd); - printf("length: %d\n", p->length); - } - return 0; -} diff --git a/SheepShaver/src/BeOS/SaveROM/Makefile b/SheepShaver/src/BeOS/SaveROM/Makefile deleted file mode 100644 index cba232e1..00000000 --- a/SheepShaver/src/BeOS/SaveROM/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -## BeOS Generic Makefile v2.1 ## - -## Fill in this file to specify the project being created, and the referenced -## makefile-engine will do all of the hard work for you. This handles both -## Intel and PowerPC builds of the BeOS. - -## Application Specific Settings --------------------------------------------- - -# specify the name of the binary -NAME= SaveROM - -# specify the type of binary -# APP: Application -# SHARED: Shared library or add-on -# STATIC: Static library archive -# DRIVER: Kernel Driver -TYPE= APP - -# add support for new Pe and Eddie features -# to fill in generic makefile - -#%{ -# @src->@ - -# specify the source files to use -# full paths or paths relative to the makefile can be included -# all files, regardless of directory, will have their object -# files created in the common object directory. -# Note that this means this makefile will not work correctly -# if two source files with the same name (source.c or source.cpp) -# are included from different directories. Also note that spaces -# in folder names do not work well with this makefile. -SRCS= SaveROM.cpp - -# specify the resource files to use -# full path or a relative path to the resource file can be used. -RSRCS= SaveROM.rsrc - -# @<-src@ -#%} - -# end support for Pe and Eddie - -# specify additional libraries to link against -# there are two acceptable forms of library specifications -# - if your library follows the naming pattern of: -# libXXX.so or libXXX.a you can simply specify XXX -# library: libbe.so entry: be -# -# - if your library does not follow the standard library -# naming scheme you need to specify the path to the library -# and it's name -# library: my_lib.a entry: my_lib.a or path/my_lib.a -LIBS= be - -# specify additional paths to directories following the standard -# libXXX.so or libXXX.a naming scheme. You can specify full paths -# or paths relative to the makefile. The paths included may not -# be recursive, so include all of the paths where libraries can -# be found. Directories where source files are found are -# automatically included. -LIBPATHS= - -# additional paths to look for system headers -# thes use the form: #include
-# source file directories are NOT auto-included here -SYSTEM_INCLUDE_PATHS = - -# additional paths to look for local headers -# thes use the form: #include "header" -# source file directories are automatically included -LOCAL_INCLUDE_PATHS = ../ ../../include ../NetAddOn - -# specify the level of optimization that you desire -# NONE, SOME, FULL -OPTIMIZE= FULL - -# specify any preprocessor symbols to be defined. The symbols will not -# have their values set automatically; you must supply the value (if any) -# to use. For example, setting DEFINES to "DEBUG=1" will cause the -# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" -# would pass "-DDEBUG" on the compiler's command line. -DEFINES= - -# specify special warning levels -# if unspecified default warnings will be used -# NONE = supress all warnings -# ALL = enable all warnings -WARNINGS = - -# specify whether image symbols will be created -# so that stack crawls in the debugger are meaningful -# if TRUE symbols will be created -SYMBOLS = - -# specify debug settings -# if TRUE will allow application to be run from a source-level -# debugger. Note that this will disable all optimzation. -DEBUGGER = - -# specify additional compiler flags for all files -COMPILER_FLAGS = - -# specify additional linker flags -LINKER_FLAGS = - - -## include the makefile-engine -include /boot/develop/etc/makefile-engine - diff --git a/SheepShaver/src/BeOS/SaveROM/README b/SheepShaver/src/BeOS/SaveROM/README deleted file mode 100644 index 37214b34..00000000 --- a/SheepShaver/src/BeOS/SaveROM/README +++ /dev/null @@ -1,8 +0,0 @@ -"SaveROM" is a program that allows you to save the ROM of -a PowerMac running under BeOS to a file. - -1. Copy "sheep_driver" to ~/config/add-ons/kernel/drivers. -2. Double-click the "SaveROM" icon. - -This will create a file called "ROM" which should be 4MB -in size. diff --git a/SheepShaver/src/BeOS/SaveROM/SaveROM.cpp b/SheepShaver/src/BeOS/SaveROM/SaveROM.cpp deleted file mode 100644 index 5796ad5d..00000000 --- a/SheepShaver/src/BeOS/SaveROM/SaveROM.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SaveROM - Save Mac ROM to file - * - * Copyright (C) 1998-2004 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include -#include - - -// Constants -const char APP_SIGNATURE[] = "application/x-vnd.cebix-SaveROM"; -const char ROM_FILE_NAME[] = "ROM"; - -// Global variables -static uint8 buf[0x400000]; - -// Application object -class SaveROM : public BApplication { -public: - SaveROM() : BApplication(APP_SIGNATURE) - { - // Find application directory and cwd to it - app_info the_info; - GetAppInfo(&the_info); - BEntry the_file(&the_info.ref); - BEntry the_dir; - the_file.GetParent(&the_dir); - BPath the_path; - the_dir.GetPath(&the_path); - chdir(the_path.Path()); - } - virtual void ReadyToRun(void); -}; - - -/* - * Create application object and start it - */ - -int main(int argc, char **argv) -{ - SaveROM *the_app = new SaveROM(); - the_app->Run(); - delete the_app; - return 0; -} - - -/* - * Display error alert - */ - -static void ErrorAlert(const char *text) -{ - BAlert *alert = new BAlert("SaveROM Error", text, "Quit", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); - alert->Go(); -} - - -/* - * Display OK alert - */ - -static void InfoAlert(const char *text) -{ - BAlert *alert = new BAlert("SaveROM Message", text, "Quit", NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); - alert->Go(); -} - - -/* - * Main program - */ - -void SaveROM::ReadyToRun(void) -{ - int fd = open("/dev/sheep", 0); - if (fd < 0) { - ErrorAlert("Cannot open '/dev/sheep'."); - goto done; - } - - if (read(fd, buf, 0x400000) != 0x400000) { - ErrorAlert("Cannot read ROM."); - close(fd); - goto done; - } - - FILE *f = fopen(ROM_FILE_NAME, "wb"); - if (f == NULL) { - ErrorAlert("Cannot open ROM file."); - close(fd); - goto done; - } - - if (fwrite(buf, 1, 0x400000, f) != 0x400000) { - ErrorAlert("Cannot write ROM."); - fclose(f); - close(fd); - goto done; - } - - InfoAlert("ROM saved."); - - fclose(f); - close(fd); -done: - PostMessage(B_QUIT_REQUESTED); -} diff --git a/SheepShaver/src/BeOS/SaveROM/SaveROM.rsrc b/SheepShaver/src/BeOS/SaveROM/SaveROM.rsrc deleted file mode 100644 index a61919ba80a170f7ce863bf1ad107b503bfc093d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4323 zcmeHJzfV(96h6f&rP24E(N+frH8D6QW?ns-6xt+7^FW7WT>UY0}-HVCQy(3rt zn>hVvJNZ83w3D0s5Rv~eBL7oF{%2gJO0i(alx@S-quaErI*MKyc5>5*x50OwMdZJT z$bS`)|E7U|PWonzY{R#%tGi>0;l%5r}tv*2g^iobY&t+cS@Q$4o6e5-HKUno~HUTNK*Di-)c^gjl+ zkMf_H%YE6tEL-~SJyXW`f_E12x1ilD#UTT}sLKuO)+AO1Y`M z86@CTx;2BvkqsELc^4%vVNeW*M!99uSC^+GL@q89kCT8I z#b8wWA|O!VTNdtCqe34Ms|TOy@H}t>kE8IE579&+KRkie$2>#M^^u}CP#Ey0b94FO z;zW=q9LY*6)_5~(XmWBCI{cdRDPZ)XSqM9`-#4?%nOTr}u>bP2 z!|3_Xr}Zy>JZXP}lZ7{<)35&eE|9=ca$>@jrPD)QZDjqh2rcIqF!>jk!NLe_rS(z|5;$w|?bZI$ZLZFFPmG z_?Opj)7(yTJMDpK5BxtpAn(!-i{h)SX=r{E@D*CREsDH{ueYga8LH`Kv)2_Ip9|1* zAu?N{H#BTpWrE4Lp<9534DHHPdfv~VZ4RHPqdmShVbQR1GxcceMx&wmfuTJyGZ$@N zx8Vb+m&g(269g{z@e;u+A*0g&rSbs}#LoL6B~=u~%s|B#aRomPf*>YK#VWp59Hhwa zB4Wb%;L@C+%%PHeo5V8}IlLCH<(n%o;bs1vyY zvc4tkYA+$&!np9y>zxO7wUauD>!39je}|6<=^rQ_%+rp69iDS+`~{anAoY<32vT}W zuDLem)H1kvhy-gXJ4m>+v&=DQg(p4|j~!(|=S&P&l0g4NDD*8YFfqi}Xck_g?wloaMkdy>tbcIubgmNmjvgZtc<(~xJCZOBj z-3(U_Ukq1AgJ+Sfe4L#3Ux|iCgTwvdvuHS4*}ir2+m8!2Wlu9uWT4x*`-rM^WDN`7 zZES|OySKx~>rXm&Hy@QZF*8QankiTh-)D6@-H>sl_phK~Vm -#include -#include -#include - -#include "about_window.h" -#include "video.h" -#include "version.h" -#include "user_strings.h" - - -// About window dimensions -static const BRect about_frame = BRect(0, 0, 383, 99); - -// Special colors -const rgb_color fill_color = {216, 216, 216, 0}; - -// SheepShaver icon -static const uint8 sheep_icon[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xda, 0x15, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xff, 0x00, 0x00, 0x00, 0x16, 0xda, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, - 0x00, 0x1d, 0xda, 0x1e, 0x1e, 0x1e, 0xda, 0x16, 0x00, 0x00, 0x16, 0xda, 0x16, 0xda, 0x08, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x0b, 0xff, 0xff, 0x11, 0x00, 0xda, - 0x1d, 0xda, 0x1e, 0xda, 0x1e, 0xda, 0x1e, 0xda, 0x1e, 0x16, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, - 0xff, 0x0b, 0x00, 0x00, 0x16, 0x16, 0x00, 0x12, 0xfd, 0x1d, 0x0b, 0x00, 0x00, 0x1d, 0xfd, 0x1d, - 0xfd, 0x1e, 0xda, 0x1e, 0xda, 0x1e, 0xda, 0x3f, 0xda, 0x3f, 0xda, 0x15, 0x00, 0xff, 0xff, 0xff, - 0x16, 0x00, 0x17, 0x16, 0x00, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x16, 0x0f, 0x0b, 0x1d, - 0x1e, 0xfd, 0x1e, 0xda, 0x1e, 0xda, 0x3f, 0xda, 0x3f, 0xda, 0x1d, 0x5a, 0x15, 0xff, 0xff, 0xff, - 0x05, 0x17, 0x16, 0x00, 0x12, 0x1d, 0x00, 0x1d, 0xfd, 0x00, 0xfd, 0x00, 0x00, 0x16, 0x0b, 0x00, - 0x00, 0x0e, 0x1d, 0x3f, 0xda, 0x3f, 0xda, 0x1d, 0xda, 0x1b, 0x5a, 0x1b, 0x0f, 0x1d, 0xff, 0xff, - 0xff, 0x05, 0x00, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x1a, 0xfd, 0x00, 0x0f, 0x14, 0x14, - 0x16, 0x00, 0x15, 0xfd, 0x1d, 0xda, 0x1b, 0xda, 0x1b, 0x5a, 0x1b, 0x5a, 0x0f, 0x14, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x1a, 0xfd, 0x12, 0x00, 0x16, 0x00, 0x0f, - 0x00, 0x1b, 0xfd, 0x1e, 0xfd, 0x1b, 0xda, 0x1b, 0x5a, 0x1b, 0x5a, 0x1b, 0x5a, 0x14, 0xff, 0xff, - 0xff, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x1a, 0xfd, 0x12, 0x00, 0x16, 0x1b, 0x16, 0x0e, - 0x1b, 0xfd, 0x1b, 0xfd, 0x1b, 0xfd, 0x1b, 0x5a, 0x18, 0x00, 0x00, 0x5a, 0x1b, 0x00, 0xff, 0xff, - 0xff, 0x00, 0xfd, 0x14, 0xfd, 0x14, 0xfd, 0x1d, 0xfd, 0x12, 0x00, 0x16, 0xfd, 0x1b, 0xfd, 0x1b, - 0xfd, 0x1b, 0xfd, 0x1e, 0xfd, 0x1b, 0x5a, 0x18, 0x5a, 0x00, 0x00, 0x1b, 0x9b, 0x00, 0xff, 0xff, - 0xff, 0x00, 0x0f, 0xfd, 0x1d, 0xfd, 0x0f, 0xfd, 0x12, 0x00, 0x16, 0xfd, 0x1b, 0xfd, 0x1b, 0xfd, - 0x1b, 0xfd, 0x18, 0xfd, 0x1b, 0xf9, 0x18, 0x5a, 0x00, 0x12, 0x00, 0x9b, 0x1b, 0x00, 0xff, 0xff, - 0xff, 0x00, 0xfd, 0x0a, 0x0a, 0x0a, 0xfd, 0x10, 0x00, 0x1b, 0xfd, 0x1b, 0xfd, 0x1b, 0xfd, 0x18, - 0xfd, 0x15, 0xfa, 0x15, 0xf9, 0x18, 0x15, 0x00, 0x12, 0x9b, 0x00, 0x1b, 0x9b, 0x00, 0x15, 0x15, - 0xff, 0xff, 0x00, 0xfd, 0x1d, 0xfd, 0x1d, 0x00, 0x16, 0x00, 0x1b, 0xfd, 0x1b, 0xfd, 0x15, 0xfd, - 0x15, 0xfa, 0x15, 0xf9, 0x15, 0x16, 0x00, 0x0f, 0x9b, 0x12, 0x00, 0x9b, 0x1b, 0x00, 0x15, 0x15, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x1d, 0x00, 0xfa, 0x1e, 0x00, 0x1e, 0xfa, 0x15, - 0xfa, 0x15, 0x16, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x12, 0x15, 0x15, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1d, 0xf9, 0x00, 0x3f, 0xfa, 0x00, 0xfa, 0x1b, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x12, 0x15, 0x15, 0x15, 0x15, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf9, 0x1d, 0x00, 0xf9, 0x1b, 0x00, 0x1b, 0xf9, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1d, 0xf9, 0x00, 0x3f, 0xf9, 0x00, 0xf9, 0x1b, 0x00, - 0xff, 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x16, 0x1d, 0x00, 0xf9, 0x1b, 0x00, 0x1b, 0xf9, 0x00, - 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x16, 0xf9, 0x00, 0x1b, 0x16, 0x00, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, - 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x15, 0x00, 0x0a, 0x19, 0x0a, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x00, 0x16, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x19, 0x1c, 0x18, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, - 0x0f, 0xff, 0xff, 0xff, 0x00, 0x18, 0x11, 0x00, 0x15, 0x00, 0x1c, 0x18, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00, 0x00, 0x0b, 0x0b, - 0x00, 0x00, 0x0f, 0xff, 0x12, 0x00, 0x18, 0x19, 0x00, 0x15, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00, 0x14, 0x1e, 0xfd, 0x01, 0xfd, 0x14, - 0xfa, 0xf9, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x19, 0x1c, 0x00, 0x18, 0x1c, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x14, 0xfd, 0x1e, 0xf9, 0x1e, 0xfa, 0x1e, 0xf9, - 0x14, 0xfa, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x18, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x14, 0x1e, 0xf9, 0x14, 0xfa, 0x1e, 0xf9, 0x1e, - 0xfd, 0x1e, 0x00, 0x15, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0x00, 0x00, 0x18, 0x00, 0x1c, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x00, 0xfd, 0x1e, 0xfd, 0x14, 0xfd, 0x1e, 0xfd, - 0x1e, 0x01, 0x00, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x1c, 0x00, 0x15, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x14, 0xfa, 0x01, 0xf9, 0x1e, 0xf9, 0x14, - 0x14, 0x00, 0x0f, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x15, 0x15, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - - -// View class -class AboutViewT : public BView { -public: - AboutViewT(BRect r) : BView(r, "", B_FOLLOW_NONE, B_WILL_DRAW) {} - - virtual void Draw(BRect update) - { - char str[256]; - sprintf(str, GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - - SetFont(be_bold_font); - SetDrawingMode(B_OP_OVER); - MovePenTo(20, 20); - DrawString(str); - SetFont(be_plain_font); - MovePenTo(20, 40); - DrawString(GetString(STR_ABOUT_TEXT2)); - MovePenTo(20, 60); - DrawString(B_UTF8_COPYRIGHT "1997-2008 Christian Bauer and Marc Hellwig"); - } - - virtual void MouseDown(BPoint point) - { - Window()->PostMessage(B_QUIT_REQUESTED); - } -}; - - -// 3D view class -class AboutView3D : public BGLView { -public: - AboutView3D(BRect r) : BGLView(r, "", B_FOLLOW_NONE, 0, BGL_RGB | BGL_DOUBLE) - { - rot_x = rot_y = 0; - - if (!VideoSnapshot(64, 64, texture)) { - uint8 *p = texture; - const uint8 *q = sheep_icon; - const color_map *cm = system_colors(); - for (int i=0; i<32*32; i++) { - uint8 red = cm->color_list[*q].red; - uint8 green = cm->color_list[*q].green; - uint8 blue = cm->color_list[*q++].blue; - p[0] = p[3] = p[64*3] = p[65*3] = red; - p[1] = p[4] = p[64*3+1] = p[65*3+1] = green; - p[2] = p[5] = p[64*3+2] = p[65*3+2] = blue; - p += 6; - if ((i & 31) == 31) - p += 64*3; - } - } - } - - virtual void AttachedToWindow(void) - { - BGLView::AttachedToWindow(); - LockGL(); - - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - - glShadeModel(GL_SMOOTH); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(30, 1, 0.5, 20); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - GLfloat light_color[4] = {1, 1, 1, 1}; - GLfloat light_dir[4] = {1, 2, 1.5, 1}; - glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color); - glLightfv(GL_LIGHT0, GL_POSITION, light_dir); - glEnable(GL_LIGHT0); - glEnable(GL_LIGHTING); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexImage2D(GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); - glEnable(GL_TEXTURE_2D); - - UnlockGL(); - - tick_thread_active = true; - tick_thread = spawn_thread(tick_func, "OpenGL Animation", B_NORMAL_PRIORITY, this); - resume_thread(tick_thread); - } - - virtual void DetachedFromWindow(void) - { - status_t l; - tick_thread_active = false; - wait_for_thread(tick_thread, &l); - - BGLView::DetachedFromWindow(); - } - - virtual void Draw(BRect update) - { - LockGL(); - glClear(GL_COLOR_BUFFER_BIT); - glBegin(GL_QUADS); - glNormal3d(0, 0, 1); - glTexCoord2f(0, 0); - glVertex3d(-1, 1, 0); - glTexCoord2f(1, 0); - glVertex3d(1, 1, 0); - glTexCoord2f(1, 1); - glVertex3d(1, -1, 0); - glTexCoord2f(0, 1); - glVertex3d(-1, -1, 0); - glEnd(); - SwapBuffers(); - UnlockGL(); - } - - static status_t tick_func(void *arg) - { - AboutView3D *obj = (AboutView3D *)arg; - while (obj->tick_thread_active) { - obj->rot_x += 2; - obj->rot_y += 2; - obj->LockGL(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0, 0, -5); - glRotatef(obj->rot_x, 1, 0, 0); - glRotatef(obj->rot_y, 0, 1, 0); - obj->UnlockGL(); - if (obj->LockLooperWithTimeout(20000) == B_OK) { - obj->Draw(obj->Bounds()); - obj->UnlockLooper(); - } - snooze(16667); - } - return 0; - } - -private: - thread_id tick_thread; - bool tick_thread_active; - - float rot_x, rot_y; - uint8 texture[64*64*3]; -}; - - -// Window class -class AboutWindowT : public BWindow { -public: - AboutWindowT() : BWindow(about_frame, NULL, B_MODAL_WINDOW_LOOK, B_FLOATING_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK) - { - Lock(); - MoveTo(100, 100); - BRect r = Bounds(); - r.right = 100; - AboutView3D *view_3d = new AboutView3D(r); - AddChild(view_3d); - r = Bounds(); - r.left = 100; - AboutViewT *view = new AboutViewT(r); - AddChild(view); - view->SetHighColor(0, 0, 0); - view->SetViewColor(fill_color); - view->MakeFocus(); - Unlock(); - Show(); - } -}; - - -/* - * Open "About" window - */ - -void OpenAboutWindow(void) -{ - new AboutWindowT; -} diff --git a/SheepShaver/src/BeOS/audio_beos.cpp b/SheepShaver/src/BeOS/audio_beos.cpp deleted file mode 120000 index ce433abb..00000000 --- a/SheepShaver/src/BeOS/audio_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/audio_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/BeOS/clip_beos.cpp b/SheepShaver/src/BeOS/clip_beos.cpp deleted file mode 100644 index 953ed804..00000000 --- a/SheepShaver/src/BeOS/clip_beos.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * clip_beos.cpp - Clipboard handling, BeOS implementation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "clip.h" -#include "main.h" -#include "cpu_emulation.h" -#include "emul_op.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static bool we_put_this_data = false; // Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the Be side -static BTranslatorRoster *roster; -static float input_cap = 0; -static translator_info input_info; -static float output_cap = 0; -static translator_id output_trans = 0; - - -/* - * Clipboard manager thread (for calling clipboard functions; this is not safe - * under R4 when running on the MacOS stack in kernel space) - */ - -// Message constants -const uint32 MSG_QUIT_CLIP_MANAGER = 'quit'; -const uint32 MSG_PUT_TEXT = 'ptxt'; - -static thread_id cm_thread = -1; -static sem_id cm_done_sem = -1; - -// Argument passing -static void *cm_scrap; -static int32 cm_length; - -static status_t clip_manager(void *arg) -{ - for (;;) { - - // Receive message - thread_id sender; - uint32 code = receive_data(&sender, NULL, 0); - D(bug("Clipboard manager received %08lx\n", code)); - switch (code) { - case MSG_QUIT_CLIP_MANAGER: - return 0; - - case MSG_PUT_TEXT: - if (be_clipboard->Lock()) { - be_clipboard->Clear(); - BMessage *clipper = be_clipboard->Data(); - - // Convert text from Mac charset to UTF-8 - int32 dest_length = cm_length * 3; - int32 state = 0; - char *inbuf = new char[cm_length]; - memcpy(inbuf, cm_scrap, cm_length); // Copy to user space - char *outbuf = new char[dest_length]; - if (convert_to_utf8(B_MAC_ROMAN_CONVERSION, inbuf, &cm_length, outbuf, &dest_length, &state) == B_OK) { - for (int i=0; iAddData("text/plain", B_MIME_TYPE, outbuf, dest_length); - be_clipboard->Commit(); - } else { - D(bug(" text conversion failed\n")); - } - delete[] outbuf; - delete[] inbuf; - be_clipboard->Unlock(); - } - break; - } - - // Acknowledge - release_sem(cm_done_sem); - } -} - - -/* - * Initialize clipboard - */ - -void ClipInit(void) -{ - // check if there is a translator that can handle the pict datatype - roster = BTranslatorRoster::Default(); - int32 num_translators, i,j; - translator_id *translators; - const char *translator_name, *trans_info; - int32 translator_version; - const translation_format *t_formats; - long t_num; - - roster->GetAllTranslators(&translators, &num_translators); - for (i=0;iGetTranslatorInfo(translators[i], &translator_name, - &trans_info, &translator_version); - D(bug("found translator %s: %s (%.2f)\n", translator_name, trans_info, - translator_version/100.)); - // does this translator support the pict datatype ? - roster->GetInputFormats(translators[i], &t_formats,&t_num); - //printf(" supports %d input formats \n",t_num); - for (j=0;jinput_cap) { - input_info.type = t_formats[j].type; - input_info.group = t_formats[j].group; - input_info.quality = t_formats[j].quality; - input_info.capability = t_formats[j].capability; - strcpy(input_info.MIME,t_formats[j].MIME); - strcpy(input_info.name,t_formats[j].name); - input_info.translator=translators[i]; - input_cap = t_formats[j].capability; - } - D(bug("matching input translator found:type:%c%c%c%c group:%c%c%c%c quality:%f capability:%f MIME:%s name:%s\n", - t_formats[j].type>>24,t_formats[j].type>>16,t_formats[j].type>>8,t_formats[j].type, - t_formats[j].group>>24,t_formats[j].group>>16,t_formats[j].group>>8,t_formats[j].group, - t_formats[j].quality, - t_formats[j].capability,t_formats[j].MIME, - t_formats[j].name)); - } - - } - roster->GetOutputFormats(translators[i], &t_formats,&t_num); - //printf("and %d output formats \n",t_num); - for (j=0;joutput_cap) { - output_trans = translators[i]; - output_cap = t_formats[j].capability; - } - D(bug("matching output translator found:type:%c%c%c%c group:%c%c%c%c quality:%f capability:%f MIME:%s name:%s\n", - t_formats[j].type>>24,t_formats[j].type>>16,t_formats[j].type>>8,t_formats[j].type, - t_formats[j].group>>24,t_formats[j].group>>16,t_formats[j].group>>8,t_formats[j].group, - t_formats[j].quality, - t_formats[j].capability,t_formats[j].MIME, - t_formats[j].name)); - } - } - } - delete [] translators; // clean up our droppings - - // Start clipboard manager thread - cm_done_sem = create_sem(0, "Clipboard Manager Done"); - cm_thread = spawn_thread(clip_manager, "Clipboard Manager", B_NORMAL_PRIORITY, NULL); - resume_thread(cm_thread); -} - - -/* - * Deinitialize clipboard - */ - -void ClipExit(void) -{ - // Stop clipboard manager - if (cm_thread > 0) { - status_t l; - send_data(cm_thread, MSG_QUIT_CLIP_MANAGER, NULL, 0); - while (wait_for_thread(cm_thread, &l) == B_INTERRUPTED) ; - } - - // Delete semaphores - delete_sem(cm_done_sem); -} - - -/* - * Mac application wrote to clipboard - */ - -void PutScrap(uint32 type, void *scrap, int32 length) -{ - D(bug("PutScrap type %08lx, data %p, length %ld\n", type, scrap, length)); - if (we_put_this_data) { - we_put_this_data = false; - return; - } - if (length <= 0) - return; - - switch (type) { - case 'TEXT': - D(bug(" clipping TEXT\n")); - cm_scrap = scrap; - cm_length = length; - while (send_data(cm_thread, MSG_PUT_TEXT, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(cm_done_sem) == B_INTERRUPTED) ; - break; - - case 'PICT': - D(bug(" clipping PICT\n")); - //!! this has to be converted to use the Clipboard Manager -#if 0 - if (be_clipboard->Lock()) { - be_clipboard->Clear(); - BMessage *clipper = be_clipboard->Data(); - // Waaaah! This crashes! - if (input_cap > 0) { // if there is an converter for PICT datatype convert data to bitmap. - BMemoryIO *in_buffer = new BMemoryIO(scrap, length); - BMallocIO *out_buffer = new BMallocIO(); - status_t result=roster->Translate(in_buffer,&input_info,NULL,out_buffer,B_TRANSLATOR_BITMAP); - clipper->AddData("image/x-be-bitmap", B_MIME_TYPE, out_buffer->Buffer(), out_buffer->BufferLength()); - D(bug("conversion result:%08x buffer_size:%d\n",result,out_buffer->BufferLength())); - delete in_buffer; - delete out_buffer; - } - clipper->AddData("image/pict", B_MIME_TYPE, scrap, length); - be_clipboard->Commit(); - be_clipboard->Unlock(); - } -#endif - break; - } -} - -/* - * Mac application zeroes clipboard - */ - -void ZeroScrap() -{ - -} - -/* - * Mac application reads clipboard - */ - -void GetScrap(void **handle, uint32 type, int32 offset) -{ - M68kRegisters r; - D(bug("GetScrap handle %p, type %08lx, offset %ld\n", handle, type, offset)); - return; //!! GetScrap is currently broken (should use Clipboard Manager) - //!! replace with clipboard notification in BeOS R4.1 - - switch (type) { - case 'TEXT': - D(bug(" clipping TEXT\n")); - if (be_clipboard->Lock()) { - BMessage *clipper = be_clipboard->Data(); - char *clip; - ssize_t length; - - // Check if we already copied this data - if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE)) - return; - bigtime_t cookie = system_time(); - clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t)); - - // No, is there text in it? - if (clipper->FindData("text/plain", B_MIME_TYPE, &clip, &length) == B_OK) { - D(bug(" text/plain found\n")); - - // Convert text from UTF-8 to Mac charset - int32 src_length = length; - int32 dest_length = length; - int32 state = 0; - char *outbuf = new char[dest_length]; - if (convert_from_utf8(B_MAC_ROMAN_CONVERSION, clip, &src_length, outbuf, &dest_length, &state) == B_OK) { - for (int i=0; iCommit(); - be_clipboard->Unlock(); - } - break; - - case 'PICT': - D(bug(" clipping PICT\n")); - if (be_clipboard->Lock()) { - BMessage *clipper = be_clipboard->Data(); - char *clip; - ssize_t length; - - // Check if we already copied this data - if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE)) - return; - bigtime_t cookie = system_time(); - clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t)); - - static uint16 proc2[] = { - 0x598f, // subq.l #4,sp - 0xa9fc, // ZeroScrap() - 0x2f3c, 0, 0, // move.l #length,-(sp) - 0x2f3c, 'PI', 'CT', // move.l #'PICT',-(sp) - 0x2f3c, 0, 0, // move.l #buf,-(sp) - 0xa9fe, // PutScrap() - 0x588f, // addq.l #4,sp - M68K_RTS - }; - - // No, is there a pict ? - if (clipper->FindData("image/pict", B_MIME_TYPE, &clip, &length) == B_OK ) { - D(bug(" image/pict found\n")); - - // Add pict to Mac clipboard - *(int32 *)(proc2 + 3) = length; - *(char **)(proc2 + 9) = clip; - we_put_this_data = true; - Execute68k((uint32)proc2, &r); -#if 0 - // No, is there a bitmap ? - } else if (clipper->FindData("image/x-be-bitmap", B_MIME_TYPE, &clip, &length) == B_OK || output_cap > 0) { - D(bug(" image/x-be-bitmap found\nstarting conversion to PICT\n")); - - BMemoryIO *in_buffer = new BMemoryIO(clip, length); - BMallocIO *out_buffer = new BMallocIO(); - status_t result=roster->Translate(output_trans,in_buffer,NULL,out_buffer,'PICT'); - D(bug("result of conversion:%08x buffer_size:%d\n",result,out_buffer->BufferLength())); - - // Add pict to Mac clipboard - *(int32 *)(proc2 + 3) = out_buffer->BufferLength(); - *(char **)(proc2 + 9) = (char *)out_buffer->Buffer(); - we_put_this_data = true; - Execute68k(proc2, &r); - - delete in_buffer; - delete out_buffer; -#endif - } - be_clipboard->Commit(); - be_clipboard->Unlock(); - } - break; - } -} diff --git a/SheepShaver/src/BeOS/ether_beos.cpp b/SheepShaver/src/BeOS/ether_beos.cpp deleted file mode 100644 index 740f9638..00000000 --- a/SheepShaver/src/BeOS/ether_beos.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * ether_beos.cpp - SheepShaver Ethernet Device Driver (DLPI), BeOS specific stuff - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "ether.h" -#include "ether_defs.h" -#include "prefs.h" -#include "xlowmem.h" -#include "main.h" -#include "user_strings.h" -#include "sheep_net.h" - -#define DEBUG 0 -#include "debug.h" - -#define STATISTICS 0 -#define MONITOR 0 - - -// Global variables -static thread_id read_thread; // Packet receiver thread -static bool ether_thread_active = true; // Flag for quitting the receiver thread - -static area_id buffer_area; // Packet buffer area -static net_buffer *net_buffer_ptr; // Pointer to packet buffer -static sem_id read_sem, write_sem; // Semaphores to trigger packet reading/writing -static uint32 rd_pos; // Current read position in packet buffer -static uint32 wr_pos; // Current write position in packet buffer - -static bool net_open = false; // Flag: initialization succeeded, network device open - - -// Prototypes -static status_t AO_receive_thread(void *data); - - -/* - * Initialize ethernet - */ - -void EtherInit(void) -{ - // Do nothing if the user disabled the network - if (PrefsFindBool("nonet")) - return; - - // find net-server team -i_wanna_try_that_again: - bool found_add_on = false; - team_info t_info; - int32 t_cookie = 0; - image_info i_info; - int32 i_cookie = 0; - while (get_next_team_info(&t_cookie, &t_info) == B_NO_ERROR) { - if (strstr(t_info.args,"net_server")!=NULL) { - // check if sheep_net add-on is loaded - while (get_next_image_info(t_info.team,&i_cookie,&i_info) == B_NO_ERROR) { - if (strstr(i_info.name,"sheep_net")!=NULL) { - found_add_on = true; - break; - } - } - } - if (found_add_on) break; - } - if (!found_add_on) { - - // Search for sheep_net in network config file - char str[1024]; - bool sheep_net_found = false; - FILE *fin = fopen("/boot/home/config/settings/network", "r"); - while (!feof(fin)) { - fgets(str, 1024, fin); - if (strstr(str, "PROTOCOLS")) - if (strstr(str, "sheep_net")) - sheep_net_found = true; - } - fclose(fin); - - // It was found, so something else must be wrong - if (sheep_net_found) { - WarningAlert(GetString(STR_NO_NET_ADDON_WARN)); - return; - } - - // Not found, inform the user - if (!ChoiceAlert(GetString(STR_NET_CONFIG_MODIFY_WARN), GetString(STR_OK_BUTTON), GetString(STR_CANCEL_BUTTON))) - return; - - // Change the network config file and restart the network - fin = fopen("/boot/home/config/settings/network", "r"); - FILE *fout = fopen("/boot/home/config/settings/network.2", "w"); - bool global_found = false; - bool modified = false; - while (!feof(fin)) { - str[0] = 0; - fgets(str, 1024, fin); - if (!global_found && strstr(str, "GLOBAL:")) { - global_found = true; - } else if (global_found && !modified && strstr(str, "PROTOCOLS")) { - str[strlen(str)-1] = 0; - strcat(str, " sheep_net\n"); - modified = true; - } else if (global_found && !modified && strlen(str) > 2 && str[strlen(str) - 2] == ':') { - fputs("\tPROTOCOLS = sheep_net\n", fout); - modified = true; - } - fputs(str, fout); - } - if (!modified) - fputs("\tPROTOCOLS = sheep_net\n", fout); - fclose(fout); - fclose(fin); - remove("/boot/home/config/settings/network.orig"); - rename("/boot/home/config/settings/network", "/boot/home/config/settings/network.orig"); - rename("/boot/home/config/settings/network.2", "/boot/home/config/settings/network"); - - app_info ai; - if (be_roster->GetAppInfo("application/x-vnd.Be-NETS", &ai) == B_OK) { - BMessenger msg(NULL, ai.team); - if (msg.IsValid()) { - while (be_roster->IsRunning("application/x-vnd.Be-NETS")) { - msg.SendMessage(B_QUIT_REQUESTED); - snooze(500000); - } - } - } - BPath path; - find_directory(B_BEOS_BOOT_DIRECTORY, &path); - path.Append("Netscript"); - char *argv[3] = {"/bin/sh", (char *)path.Path(), NULL}; - thread_id net_server = load_image(2, argv, environ); - resume_thread(net_server); - status_t l; - wait_for_thread(net_server, &l); - goto i_wanna_try_that_again; - } - - // Set up communications with add-on - area_id handler_buffer; - if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) { - WarningAlert(GetString(STR_NET_ADDON_INIT_FAILED)); - return; - } - if ((buffer_area = clone_area("local packet buffer", &net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) { - D(bug("EtherInit: couldn't clone packet area\n")); - WarningAlert(GetString(STR_NET_ADDON_CLONE_FAILED)); - return; - } - if ((read_sem = create_sem(0, "ether read")) < B_NO_ERROR) { - printf("FATAL: can't create Ethernet semaphore\n"); - return; - } - net_buffer_ptr->read_sem = read_sem; - write_sem = net_buffer_ptr->write_sem; - read_thread = spawn_thread(AO_receive_thread, "ether read", B_URGENT_DISPLAY_PRIORITY, NULL); - resume_thread(read_thread); - for (int i=0; iwrite[i].cmd = IN_USE | (ACTIVATE_SHEEP_NET << 8); - rd_pos = wr_pos = 0; - release_sem(write_sem); - - // Everything OK - net_open = true; -} - - -/* - * Exit ethernet - */ - -void EtherExit(void) -{ - if (net_open) { - - // Close communications with add-on - for (int i=0; iwrite[i].cmd = IN_USE | (DEACTIVATE_SHEEP_NET << 8); - release_sem(write_sem); - - // Quit receiver thread - ether_thread_active = false; - status_t result; - release_sem(read_sem); - while (wait_for_thread(read_thread, &result) == B_INTERRUPTED) ; - - delete_sem(read_sem); - delete_area(buffer_area); - } - -#if STATISTICS - // Show statistics - printf("%ld messages put on write queue\n", num_wput); - printf("%ld error acks\n", num_error_acks); - printf("%ld packets transmitted (%ld raw, %ld normal)\n", num_tx_packets, num_tx_raw_packets, num_tx_normal_packets); - printf("%ld tx packets dropped because buffer full\n", num_tx_buffer_full); - printf("%ld packets received\n", num_rx_packets); - printf("%ld packets passed upstream (%ld Fast Path, %ld normal)\n", num_rx_fastpath + num_unitdata_ind, num_rx_fastpath, num_unitdata_ind); - printf("EtherIRQ called %ld times\n", num_ether_irq); - printf("%ld rx packets dropped due to low memory\n", num_rx_no_mem); - printf("%ld rx packets dropped because no stream found\n", num_rx_dropped); - printf("%ld rx packets dropped because stream not ready\n", num_rx_stream_not_ready); - printf("%ld rx packets dropped because no memory for unitdata_ind\n", num_rx_no_unitdata_mem); -#endif -} - - -/* - * Ask add-on for ethernet hardware address - */ - -void AO_get_ethernet_address(uint32 arg) -{ - uint8 *addr = Mac2HostAddr(arg); - if (net_open) { - OTCopy48BitAddress(net_buffer_ptr->ether_addr, addr); - } else { - addr[0] = 0x12; - addr[1] = 0x34; - addr[2] = 0x56; - addr[3] = 0x78; - addr[4] = 0x9a; - addr[5] = 0xbc; - } - D(bug("AO_get_ethernet_address: got address %02x%02x%02x%02x%02x%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])); -} - - -/* - * Tell add-on to enable multicast address - */ - -void AO_enable_multicast(uint32 addr) -{ - D(bug("AO_enable_multicast\n")); - if (net_open) { - net_packet *p = &net_buffer_ptr->write[wr_pos]; - if (p->cmd & IN_USE) { - D(bug("WARNING: couldn't enable multicast address\n")); - } else { - Mac2host_memcpy(p->data, addr, 6); - p->length = 6; - p->cmd = IN_USE | (ADD_MULTICAST << 8); - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - release_sem(write_sem); - } - } -} - - -/* - * Tell add-on to disable multicast address - */ - -void AO_disable_multicast(uint32 addr) -{ - D(bug("AO_disable_multicast\n")); - if (net_open) { - net_packet *p = &net_buffer_ptr->write[wr_pos]; - if (p->cmd & IN_USE) { - D(bug("WARNING: couldn't enable multicast address\n")); - } else { - Mac2host_memcpy(p->data, addr, 6); - p->length = 6; - p->cmd = IN_USE | (REMOVE_MULTICAST << 8); - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - release_sem(write_sem); - } - D(bug("WARNING: couldn't disable multicast address\n")); - } -} - - -/* - * Tell add-on to transmit one packet - */ - -void AO_transmit_packet(uint32 mp_arg) -{ - D(bug("AO_transmit_packet\n")); - if (net_open) { - net_packet *p = &net_buffer_ptr->write[wr_pos]; - if (p->cmd & IN_USE) { - D(bug("WARNING: couldn't transmit packet (buffer full)\n")); - num_tx_buffer_full++; - } else { - D(bug(" write packet pos %d\n", i)); - num_tx_packets++; - - // Copy packet to buffer - uint8 *start; - uint8 *bp = start = p->data; - mblk_t *mp = Mac2HostAddr(mp_arg); - while (mp) { - uint32 size = mp->b_wptr - mp->b_rptr; - memcpy(bp, mp->b_rptr, size); - bp += size; - mp = mp->b_cont; - } - -#if MONITOR - bug("Sending Ethernet packet:\n"); - for (int i=0; i<(uint32)(bp - start); i++) { - bug("%02lx ", start[i]); - } - bug("\n"); -#endif - - // Notify add-on - p->length = (uint32)(bp - start); - p->cmd = IN_USE | (SHEEP_PACKET << 8); - wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT; - release_sem(write_sem); - } - } -} - - -/* - * Packet reception thread - */ - -static status_t AO_receive_thread(void *data) -{ - while (ether_thread_active) { - if (net_buffer_ptr->read[rd_pos].cmd & IN_USE) { - if (ether_driver_opened) { - D(bug(" packet received, triggering Ethernet interrupt\n")); - SetInterruptFlag(INTFLAG_ETHER); - TriggerInterrupt(); - } - } - acquire_sem_etc(read_sem, 1, B_TIMEOUT, 25000); - } - return 0; -} - - -/* - * Ethernet interrupt - */ - -void EtherIRQ(void) -{ - D(bug("EtherIRQ\n")); - num_ether_irq++; - OTEnterInterrupt(); - - // Send received packets to OpenTransport - net_packet *p = &net_buffer_ptr->read[rd_pos]; - while (p->cmd & IN_USE) { - if ((p->cmd >> 8) == SHEEP_PACKET) { - num_rx_packets++; - D(bug(" read packet pos %d\n", i)); - uint32 size = p->length; - -#if MONITOR - bug("Receiving Ethernet packet:\n"); - for (int i=0; idata[i]); - } - bug("\n"); -#endif - - // Wrap packet in message block - //!! maybe use esballoc() - mblk_t *mp; - if ((mp = allocb(size, 0)) != NULL) { - D(bug(" packet data at %p\n", (void *)mp->b_rptr)); - memcpy(mp->b_rptr, p->data, size); - mp->b_wptr += size; - ether_packet_received(mp); - } else { - D(bug("WARNING: Cannot allocate mblk for received packet\n")); - num_rx_no_mem++; - } - } - p->cmd = 0; // Free packet - rd_pos = (rd_pos + 1) % READ_PACKET_COUNT; - p = &net_buffer_ptr->read[rd_pos]; - } - OTLeaveInterrupt(); -} diff --git a/SheepShaver/src/BeOS/extfs_beos.cpp b/SheepShaver/src/BeOS/extfs_beos.cpp deleted file mode 120000 index e7cec3dc..00000000 --- a/SheepShaver/src/BeOS/extfs_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/extfs_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/BeOS/main_beos.cpp b/SheepShaver/src/BeOS/main_beos.cpp deleted file mode 100644 index 551cd518..00000000 --- a/SheepShaver/src/BeOS/main_beos.cpp +++ /dev/null @@ -1,2015 +0,0 @@ -/* - * main_beos.cpp - Emulation core, BeOS implementation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - * SheepShaver uses three run-time environments, reflected by the value of XLM_RUN_MODE. - * The two modes which are also present in the original MacOS, are: - * MODE_68K - 68k emulator is active - * MODE_NATIVE - 68k emulator is inactive - * In the original MacOS, these two modes have different memory mappings and exception - * tables. Under SheepShaver, the only difference is the handling of interrupts (see below). - * SheepShaver extends the 68k emulator with special opcodes (EMUL_OP) to perform faster - * mode switches when patching 68k routines with PowerPC code and adds a third run mode: - * MODE_EMUL_OP - 68k emulator active, but native register usage - * - * Switches between MODE_68K and MODE_NATIVE are only done with the Mixed Mode Manager - * (via nanokernel patches). The switch from MODE_68K to MODE_EMUL_OP occurs when executin - * one of the EMUL_OP 68k opcodes. When the opcode routine is done, it returns to MODE_68K. - * - * The Execute68k() routine allows EMUL_OP routines to execute 68k subroutines. It switches - * from MODE_EMUL_OP back to MODE_68K, so it must not be used by native routines (executing - * in MODE_NATIVE) nor by any other thread than the emul_thread (because the 68k emulator - * is not reentrant). When the 68k subroutine returns, it switches back to MODE_EMUL_OP. - * It is OK for a 68k routine called with Execute68k() to contain an EMUL_OP opcode. - * - * The handling of interrupts depends on the current run mode: - * MODE_68K - The USR1 signal handler sets one bit in the processor's CR. The 68k emulator - * will then execute the 68k interrupt routine when fetching the next instruction. - * MODE_NATIVE - The USR1 signal handler switches back to the original stack (signals run - * on a separate signal stack) and enters the External Interrupt routine in the - * nanokernel. - * MODE_EMUL_OP - The USR1 signal handler directly executes the 68k interrupt routine - * with Execute68k(). Before doing this, it must first check the current 68k interrupt - * level which is stored in XLM_68K_R25. This variable is set to the current level - * when entering EMUL_OP mode. Execute68k() also uses it to restore the level so that - * Execute68k()'d routines will run at the same interrupt level as the EMUL_OP routine - * it was called from. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "version.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "xlowmem.h" -#include "xpram.h" -#include "timer.h" -#include "adb.h" -#include "video.h" -#include "sys.h" -#include "macos_util.h" -#include "rom_patches.h" -#include "user_strings.h" - -#include "sheep_driver.h" - -#define DEBUG 0 -#include "debug.h" - -// Enable Execute68k() safety checks? -#define SAFE_EXEC_68K 0 - -// Save FP regs in Execute68k()? -#define SAVE_FP_EXEC_68K 0 - -// Interrupts in EMUL_OP mode? -#define INTERRUPTS_IN_EMUL_OP_MODE 1 - -// Interrupts in native mode? -#define INTERRUPTS_IN_NATIVE_MODE 1 - - -// Constants -const char APP_SIGNATURE[] = "application/x-vnd.cebix-SheepShaver"; -const char ROM_FILE_NAME[] = "ROM"; -const char ROM_FILE_NAME2[] = "Mac OS ROM"; -const char KERNEL_AREA_NAME[] = "Macintosh Kernel Data"; -const char KERNEL_AREA2_NAME[] = "Macintosh Kernel Data 2"; -const char RAM_AREA_NAME[] = "Macintosh RAM"; -const char ROM_AREA_NAME[] = "Macintosh ROM"; -const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache"; -const char DR_EMULATOR_AREA_NAME[] = "Macintosh DR Emulator"; -const char SHEEP_AREA_NAME[] = "SheepShaver Virtual Stack"; - -const uintptr ROM_BASE = 0x40800000; // Base address of ROM - -const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack - -const uint32 MSG_START = 'strt'; // Emulator start message - - -// Application object -class SheepShaver : public BApplication { -public: - SheepShaver() : BApplication(APP_SIGNATURE) - { - // Find application directory and cwd to it - app_info the_info; - GetAppInfo(&the_info); - BEntry the_file(&the_info.ref); - BEntry the_dir; - the_file.GetParent(&the_dir); - BPath the_path; - the_dir.GetPath(&the_path); - chdir(the_path.Path()); - - // Initialize other variables - sheep_fd = -1; - emulator_data = NULL; - kernel_area = kernel_area2 = rom_area = ram_area = dr_cache_area = dr_emulator_area = -1; - emul_thread = nvram_thread = tick_thread = -1; - ReadyForSignals = false; - AllowQuitting = true; - NVRAMThreadActive = true; - TickThreadActive = true; - memset(last_xpram, 0, XPRAM_SIZE); - } - virtual void ReadyToRun(void); - virtual void MessageReceived(BMessage *msg); - void StartEmulator(void); - virtual bool QuitRequested(void); - virtual void Quit(void); - - thread_id emul_thread; // Emulator thread - thread_id nvram_thread; // NVRAM watchdog thread - thread_id tick_thread; // 60Hz thread - - KernelData *kernel_data; // Pointer to Kernel Data - EmulatorData *emulator_data; - - bool ReadyForSignals; // Flag: emul_thread ready to receive signals - bool AllowQuitting; // Flag: Alt-Q quitting allowed - bool NVRAMThreadActive; // nvram_thread will exit when this is false - bool TickThreadActive; // tick_thread will exit when this is false - - uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes - -private: - static status_t emul_func(void *arg); - static status_t nvram_func(void *arg); - static status_t tick_func(void *arg); - static void sigusr1_invoc(int sig, void *arg, vregs *r); - void sigusr1_handler(vregs *r); - static void sigsegv_invoc(int sig, void *arg, vregs *r); - static void sigill_invoc(int sig, void *arg, vregs *r); - void jump_to_rom(uint32 entry); - - void init_rom(void); - void load_rom(void); - - int sheep_fd; // FD of sheep driver - - area_id kernel_area; // Kernel Data area ID - area_id kernel_area2; // Alternate Kernel Data area ID - area_id rom_area; // ROM area ID - area_id ram_area; // RAM area ID - area_id dr_cache_area; // DR Cache area ID - area_id dr_emulator_area; // DR Emulator area ID - - struct sigaction sigusr1_action; // Interrupt signal (of emulator thread) - struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) - struct sigaction sigill_action; // Illegal instruction exception signal (of emulator thread) - - // Exceptions - class area_error {}; - class file_open_error {}; - class file_read_error {}; - class rom_size_error {}; -}; - - -// Global variables -SheepShaver *the_app; // Pointer to application object -#if !EMULATED_PPC -void *TOC; // TOC pointer -#endif -uint32 RAMBase; // Base address of Mac RAM -uint32 RAMSize; // Size of Mac RAM -uint32 ROMBase; // Base address of Mac ROM -uint32 KernelDataAddr; // Address of Kernel Data -uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM -uint32 DRCacheAddr; // Address of DR Cache -uint32 DREmulatorAddr; // Address of DR Emulator -uint32 PVR; // Theoretical PVR -int64 CPUClockSpeed; // Processor clock speed (Hz) -int64 BusClockSpeed; // Bus clock speed (Hz) -int64 TimebaseSpeed; // Timebase clock speed (Hz) -system_info SysInfo; // System information -uint8 *RAMBaseHost; // Base address of Mac RAM (host address space) -uint8 *ROMBaseHost; // Base address of Mac ROM (host address space) - -static void *sig_stack = NULL; // Stack for signal handlers -static void *extra_stack = NULL; // Stack for SIGSEGV inside interrupt handler -uint32 SheepMem::page_size; // Size of a native page -uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros -uintptr SheepMem::base; // Address of SheepShaver data -uintptr SheepMem::proc; // Bottom address of SheepShave procedures -uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) -static area_id SheepMemArea; // SheepShaver data area ID - - -// Prototypes -static void sigsegv_handler(vregs *r); -static void sigill_handler(vregs *r); - - -/* - * Create application object and start it - */ - -int main(int argc, char **argv) -{ - tzset(); - the_app = new SheepShaver(); - the_app->Run(); - delete the_app; - return 0; -} - - -/* - * Run application - */ - -#if !EMULATED_PPC -static asm void *get_toc(void) -{ - mr r3,r2 - blr -} -#endif - -void SheepShaver::ReadyToRun(void) -{ - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - -#if !EMULATED_PPC - // Get TOC pointer - TOC = get_toc(); -#endif - - // Get system info - get_system_info(&SysInfo); - switch (SysInfo.cpu_type) { - case B_CPU_PPC_601: - PVR = 0x00010000; - break; - case B_CPU_PPC_603: - PVR = 0x00030000; - break; - case B_CPU_PPC_603e: - PVR = 0x00060000; - break; - case B_CPU_PPC_604: - PVR = 0x00040000; - break; - case B_CPU_PPC_604e: - PVR = 0x00090000; - break; - case B_CPU_PPC_750: - PVR = 0x00080000; - break; - default: - PVR = 0x00040000; - break; - } - CPUClockSpeed = SysInfo.cpu_clock_speed; - BusClockSpeed = SysInfo.bus_clock_speed; - TimebaseSpeed = BusClockSpeed / 4; - - // Delete old areas - area_id old_kernel_area = find_area(KERNEL_AREA_NAME); - if (old_kernel_area > 0) - delete_area(old_kernel_area); - area_id old_kernel2_area = find_area(KERNEL_AREA2_NAME); - if (old_kernel2_area > 0) - delete_area(old_kernel2_area); - area_id old_ram_area = find_area(RAM_AREA_NAME); - if (old_ram_area > 0) - delete_area(old_ram_area); - area_id old_rom_area = find_area(ROM_AREA_NAME); - if (old_rom_area > 0) - delete_area(old_rom_area); - area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME); - if (old_dr_cache_area > 0) - delete_area(old_dr_cache_area); - area_id old_dr_emulator_area = find_area(DR_EMULATOR_AREA_NAME); - if (old_dr_emulator_area > 0) - delete_area(old_dr_emulator_area); - - // Read preferences - int argc = 0; - char **argv = NULL; - PrefsInit(NULL, argc, argv); - - // Init system routines - SysInit(); - - // Test amount of RAM available for areas - if (SysInfo.max_pages * B_PAGE_SIZE < 16 * 1024 * 1024) { - ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR)); - PostMessage(B_QUIT_REQUESTED); - return; - } - - // Show preferences editor (or start emulator directly) - if (!PrefsFindBool("nogui")) - PrefsEditor(MSG_START); - else - PostMessage(MSG_START); -} - - -/* - * Message received - */ - -void SheepShaver::MessageReceived(BMessage *msg) -{ - switch (msg->what) { - case MSG_START: - StartEmulator(); - break; - default: - BApplication::MessageReceived(msg); - } -} - - -/* - * Start emulator - */ - -void SheepShaver::StartEmulator(void) -{ - char str[256]; - - // Open sheep driver and remap low memory - sheep_fd = open("/dev/sheep", 0); - if (sheep_fd < 0) { - sprintf(str, GetString(STR_NO_SHEEP_DRIVER_ERR), strerror(sheep_fd), sheep_fd); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - status_t res = ioctl(sheep_fd, SHEEP_UP); - if (res < 0) { - sprintf(str, GetString(STR_SHEEP_UP_ERR), strerror(res), res); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - - // Create areas for Kernel Data - kernel_data = (KernelData *)KERNEL_DATA_BASE; - kernel_area = create_area(KERNEL_AREA_NAME, &kernel_data, B_EXACT_ADDRESS, KERNEL_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (kernel_area < 0) { - sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area), kernel_area); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - emulator_data = &kernel_data->ed; - KernelDataAddr = (uint32)kernel_data; - D(bug("Kernel Data area %ld at %p, Emulator Data at %p\n", kernel_area, kernel_data, emulator_data)); - - void *kernel_data2 = (void *)KERNEL_DATA2_BASE; - kernel_area2 = clone_area(KERNEL_AREA2_NAME, &kernel_data2, B_EXACT_ADDRESS, B_READ_AREA | B_WRITE_AREA, kernel_area); - if (kernel_area2 < 0) { - sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area2), kernel_area2); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - D(bug("Kernel Data 2 area %ld at %p\n", kernel_area2, kernel_data2)); - - // Create area for SheepShaver data - if (!SheepMem::Init()) { - sprintf(str, GetString(STR_NO_SHEEP_MEM_AREA_ERR), strerror(SheepMemArea), SheepMemArea); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - - // Create area for Mac RAM - RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary - if (RAMSize < 8*1024*1024) { - WarningAlert(GetString(STR_SMALL_RAM_WARN)); - RAMSize = 8*1024*1024; - } - - RAMBase = 0x10000000; - ram_area = create_area(RAM_AREA_NAME, (void **)&RAMBase, B_BASE_ADDRESS, RAMSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (ram_area < 0) { - sprintf(str, GetString(STR_NO_RAM_AREA_ERR), strerror(ram_area), ram_area); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - RAMBaseHost = (uint8 *)RAMBase; - D(bug("RAM area %ld at %p\n", ram_area, RAMBaseHost)); - - // Create area and load Mac ROM - try { - init_rom(); - } catch (area_error) { - ErrorAlert(GetString(STR_NO_ROM_AREA_ERR)); - PostMessage(B_QUIT_REQUESTED); - return; - } catch (file_open_error) { - ErrorAlert(GetString(STR_NO_ROM_FILE_ERR)); - PostMessage(B_QUIT_REQUESTED); - return; - } catch (file_read_error) { - ErrorAlert(GetString(STR_ROM_FILE_READ_ERR)); - PostMessage(B_QUIT_REQUESTED); - return; - } catch (rom_size_error) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - PostMessage(B_QUIT_REQUESTED); - return; - } - - // Create area for DR Cache - DRCacheAddr = DR_CACHE_BASE; - dr_cache_area = create_area(DR_CACHE_AREA_NAME, (void **)&DRCacheAddr, B_EXACT_ADDRESS, DR_CACHE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (dr_cache_area < 0) { - sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_cache_area), dr_cache_area); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr)); - - // Create area for DR Emulator - DREmulatorAddr = DR_EMULATOR_BASE; - dr_emulator_area = create_area(DR_EMULATOR_AREA_NAME, (void **)&DREmulatorAddr, B_EXACT_ADDRESS, DR_EMULATOR_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (dr_emulator_area < 0) { - sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_emulator_area), dr_emulator_area); - ErrorAlert(str); - PostMessage(B_QUIT_REQUESTED); - return; - } - D(bug("DR Emulator area %ld at %p\n", dr_emulator_area, DREmulatorAddr)); - - // Initialize everything - if (!InitAll(NULL)) { - PostMessage(B_QUIT_REQUESTED); - return; - } - D(bug("Initialization complete\n")); - - // Clear caches (as we loaded and patched code) and write protect ROM -#if !EMULATED_PPC - clear_caches(ROMBaseHost, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); -#endif - set_area_protection(rom_area, B_READ_AREA); - - // Initialize extra low memory - D(bug("Initializing extra Low Memory...\n")); - WriteMacInt32(XLM_SHEEP_OBJ, (uint32)this); // Pointer to SheepShaver object - D(bug("Extra Low Memory initialized\n")); - - // Disallow quitting with Alt-Q from now on - AllowQuitting = false; - - // Start 60Hz interrupt - tick_thread = spawn_thread(tick_func, "60Hz", B_URGENT_DISPLAY_PRIORITY, this); - resume_thread(tick_thread); - - // Start NVRAM watchdog thread - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - nvram_thread = spawn_thread(nvram_func, "NVRAM Watchdog", B_LOW_PRIORITY, this); - resume_thread(nvram_thread); - - // Start emulator thread - emul_thread = spawn_thread(emul_func, "MacOS", B_NORMAL_PRIORITY, this); - resume_thread(emul_thread); -} - - -/* - * Quit requested - */ - -bool SheepShaver::QuitRequested(void) -{ - if (AllowQuitting) - return BApplication::QuitRequested(); - else - return false; -} - -void SheepShaver::Quit(void) -{ - status_t l; - - // Stop 60Hz interrupt - if (tick_thread > 0) { - TickThreadActive = false; - wait_for_thread(tick_thread, &l); - } - - // Stop NVRAM watchdog - if (nvram_thread > 0) { - status_t l; - NVRAMThreadActive = false; - suspend_thread(nvram_thread); // Wake thread up from snooze() - snooze(1000); - resume_thread(nvram_thread); - while (wait_for_thread(nvram_thread, &l) == B_INTERRUPTED) ; - } - - // Wait for emulator thread to finish - if (emul_thread > 0) - wait_for_thread(emul_thread, &l); - - // Deinitialize everything - ExitAll(); - - // Delete SheepShaver globals - SheepMem::Exit(); - - // Delete DR Emulator area - if (dr_emulator_area >= 0) - delete_area(dr_emulator_area); - - // Delete DR Cache area - if (dr_cache_area >= 0) - delete_area(dr_cache_area); - - // Delete ROM area - if (rom_area >= 0) - delete_area(rom_area); - - // Delete RAM area - if (ram_area >= 0) - delete_area(ram_area); - - // Delete Kernel Data area2 - if (kernel_area2 >= 0) - delete_area(kernel_area2); - if (kernel_area >= 0) - delete_area(kernel_area); - - // Unmap low memory and close sheep driver - if (sheep_fd >= 0) { - ioctl(sheep_fd, SHEEP_DOWN); - close(sheep_fd); - } - - // Exit system routines - SysExit(); - - // Exit preferences - PrefsExit(); - - BApplication::Quit(); -} - - -/* - * Create area for ROM (sets rom_area) and load ROM file - * - * area_error : Cannot create area - * file_open_error: Cannot open ROM file - * file_read_error: Cannot read ROM file - */ - -void SheepShaver::init_rom(void) -{ - // Size of a native page - page_size = B_PAGE_SIZE; - - // Create area for ROM - ROMBase = ROM_BASE; - rom_area = create_area(ROM_AREA_NAME, (void **)&ROMBase, B_EXACT_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (rom_area < 0) - throw area_error(); - ROMBaseHost = (uint8 *)ROMBase; - D(bug("ROM area %ld at %p\n", rom_area, rom_addr)); - - // Load ROM - load_rom(); -} - - -/* - * Load ROM file - * - * file_open_error: Cannot open ROM file (nor use built-in ROM) - * file_read_error: Cannot read ROM file - */ - -void SheepShaver::load_rom(void) -{ - // Get rom file path from preferences - const char *rom_path = PrefsFindString("rom"); - - // Try to open ROM file - BFile file(rom_path && *rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY); - if (file.InitCheck() != B_NO_ERROR) { - - // Failed, then ask memory_mess driver for ROM - uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work - ssize_t actual = read(sheep_fd, (void *)rom, ROM_SIZE); - if (actual == ROM_SIZE) { - memcpy(ROMBaseHost, rom, ROM_SIZE); - delete[] rom; - return; - } else - throw file_open_error(); - } - - printf(GetString(STR_READING_ROM_FILE)); - - // Get file size - off_t rom_size = 0; - file.GetSize(&rom_size); - - uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work - ssize_t actual = file.Read((void *)rom, ROM_SIZE); - - // Decode Mac ROM - if (!DecodeROM(rom, actual)) { - if (rom_size != 4*1024*1024) - throw rom_size_error(); - else - throw file_read_error(); - } - delete[] rom; -} - - -/* - * Emulator thread function - */ - -status_t SheepShaver::emul_func(void *arg) -{ - SheepShaver *obj = (SheepShaver *)arg; - - // Install interrupt signal handler - sigemptyset(&obj->sigusr1_action.sa_mask); - obj->sigusr1_action.sa_handler = (__signal_func_ptr)(obj->sigusr1_invoc); - obj->sigusr1_action.sa_flags = 0; - obj->sigusr1_action.sa_userdata = arg; - sigaction(SIGUSR1, &obj->sigusr1_action, NULL); - - // Install data access signal handler - sigemptyset(&obj->sigsegv_action.sa_mask); - obj->sigsegv_action.sa_handler = (__signal_func_ptr)(obj->sigsegv_invoc); - obj->sigsegv_action.sa_flags = 0; - obj->sigsegv_action.sa_userdata = arg; - sigaction(SIGSEGV, &obj->sigsegv_action, NULL); - -#if !EMULATED_PPC - // Install illegal instruction signal handler - sigemptyset(&obj->sigill_action.sa_mask); - obj->sigill_action.sa_handler = (__signal_func_ptr)(obj->sigill_invoc); - obj->sigill_action.sa_flags = 0; - obj->sigill_action.sa_userdata = arg; - sigaction(SIGILL, &obj->sigill_action, NULL); -#endif - - // Exceptions will send signals - disable_debugger(true); - - // Install signal stack - sig_stack = malloc(SIG_STACK_SIZE); - extra_stack = malloc(SIG_STACK_SIZE); - set_signal_stack(sig_stack, SIG_STACK_SIZE); - - // We're now ready to receive signals - obj->ReadyForSignals = true; - - // Jump to ROM boot routine - D(bug("Jumping to ROM\n")); - obj->jump_to_rom(ROMBase + 0x310000); - D(bug("Returned from ROM\n")); - - // We're no longer ready to receive signals - obj->ReadyForSignals = false; - obj->AllowQuitting = true; - - // Quit program - be_app->PostMessage(B_QUIT_REQUESTED); - return 0; -} - - -/* - * Jump into Mac ROM, start 680x0 emulator - * (also contains other EMUL_RETURN and EMUL_OP routines) - */ - -#if EMULATED_PPC -extern void emul_ppc(uint32 start); -extern void init_emul_ppc(void); -void SheepShaver::jump_to_rom(uint32 entry) -{ - init_emul_ppc(); - emul_ppc(entry); -} -#else -asm void SheepShaver::jump_to_rom(register uint32 entry) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - mfcr r0 - stw r0,4(r1) - stwu r1,-(56+19*4+18*8)(r1) - - // Save PowerPC registers - stmw r13,56(r1) - stfd f14,56+19*4+0*8(r1) - stfd f15,56+19*4+1*8(r1) - stfd f16,56+19*4+2*8(r1) - stfd f17,56+19*4+3*8(r1) - stfd f18,56+19*4+4*8(r1) - stfd f19,56+19*4+5*8(r1) - stfd f20,56+19*4+6*8(r1) - stfd f21,56+19*4+7*8(r1) - stfd f22,56+19*4+8*8(r1) - stfd f23,56+19*4+9*8(r1) - stfd f24,56+19*4+10*8(r1) - stfd f25,56+19*4+11*8(r1) - stfd f26,56+19*4+12*8(r1) - stfd f27,56+19*4+13*8(r1) - stfd f28,56+19*4+14*8(r1) - stfd f29,56+19*4+15*8(r1) - stfd f30,56+19*4+16*8(r1) - stfd f31,56+19*4+17*8(r1) - - // Move entry address to ctr, get pointer to Emulator Data - mtctr r4 - lwz r4,SheepShaver.emulator_data(r3) - - // Skip over EMUL_RETURN routine and get its address - bl @1 - - - /* - * EMUL_RETURN: Returned from emulator - */ - - // Restore PowerPC registers - lwz r1,XLM_EMUL_RETURN_STACK - lwz r2,XLM_TOC - lmw r13,56(r1) - lfd f14,56+19*4+0*8(r1) - lfd f15,56+19*4+1*8(r1) - lfd f16,56+19*4+2*8(r1) - lfd f17,56+19*4+3*8(r1) - lfd f18,56+19*4+4*8(r1) - lfd f19,56+19*4+5*8(r1) - lfd f20,56+19*4+6*8(r1) - lfd f21,56+19*4+7*8(r1) - lfd f22,56+19*4+8*8(r1) - lfd f23,56+19*4+9*8(r1) - lfd f24,56+19*4+10*8(r1) - lfd f25,56+19*4+11*8(r1) - lfd f26,56+19*4+12*8(r1) - lfd f27,56+19*4+13*8(r1) - lfd f28,56+19*4+14*8(r1) - lfd f29,56+19*4+15*8(r1) - lfd f30,56+19*4+16*8(r1) - lfd f31,56+19*4+17*8(r1) - - // Exiting from 68k emulator - li r0,1 - stw r0,XLM_IRQ_NEST - li r0,MODE_NATIVE - stw r0,XLM_RUN_MODE - - // Return to caller of jump_to_rom() - lwz r0,56+19*4+18*8+8(r1) - mtlr r0 - lwz r0,56+19*4+18*8+4(r1) - mtcrf 0xff,r0 - addi r1,r1,56+19*4+18*8 - blr - - - // Save address of EMUL_RETURN routine for 68k emulator patch -@1 mflr r0 - stw r0,XLM_EMUL_RETURN_PROC - - // Skip over EXEC_RETURN routine and get its address - bl @2 - - - /* - * EXEC_RETURN: Returned from 68k routine executed with Execute68k() - */ - - // Save r25 (contains current 68k interrupt level) - stw r25,XLM_68K_R25 - - // Reentering EMUL_OP mode - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE - - // Save 68k registers - lwz r4,56+19*4+18*8+12(r1) - stw r8,M68kRegisters.d[0](r4) - stw r9,M68kRegisters.d[1](r4) - stw r10,M68kRegisters.d[2](r4) - stw r11,M68kRegisters.d[3](r4) - stw r12,M68kRegisters.d[4](r4) - stw r13,M68kRegisters.d[5](r4) - stw r14,M68kRegisters.d[6](r4) - stw r15,M68kRegisters.d[7](r4) - stw r16,M68kRegisters.a[0](r4) - stw r17,M68kRegisters.a[1](r4) - stw r18,M68kRegisters.a[2](r4) - stw r19,M68kRegisters.a[3](r4) - stw r20,M68kRegisters.a[4](r4) - stw r21,M68kRegisters.a[5](r4) - stw r22,M68kRegisters.a[6](r4) - - // Restore PowerPC registers - lmw r13,56(r1) -#if SAVE_FP_EXEC_68K - lfd f14,56+19*4+0*8(r1) - lfd f15,56+19*4+1*8(r1) - lfd f16,56+19*4+2*8(r1) - lfd f17,56+19*4+3*8(r1) - lfd f18,56+19*4+4*8(r1) - lfd f19,56+19*4+5*8(r1) - lfd f20,56+19*4+6*8(r1) - lfd f21,56+19*4+7*8(r1) - lfd f22,56+19*4+8*8(r1) - lfd f23,56+19*4+9*8(r1) - lfd f24,56+19*4+10*8(r1) - lfd f25,56+19*4+11*8(r1) - lfd f26,56+19*4+12*8(r1) - lfd f27,56+19*4+13*8(r1) - lfd f28,56+19*4+14*8(r1) - lfd f29,56+19*4+15*8(r1) - lfd f30,56+19*4+16*8(r1) - lfd f31,56+19*4+17*8(r1) -#endif - - // Return to caller - lwz r0,56+19*4+18*8+8(r1) - mtlr r0 - addi r1,r1,56+19*4+18*8 - blr - - - // Stave address of EXEC_RETURN routine for 68k emulator patch -@2 mflr r0 - stw r0,XLM_EXEC_RETURN_PROC - - // Skip over EMUL_BREAK/EMUL_OP routine and get its address - bl @3 - - - /* - * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch) - * - * 68k registers are stored in a M68kRegisters struct on the stack - * which the native routine may read and modify - */ - - // Save r25 (contains current 68k interrupt level) - stw r25,XLM_68K_R25 - - // Entering EMUL_OP mode within 68k emulator - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE - - // Create PowerPC stack frame, reserve space for M68kRegisters - mr r3,r1 - subi r1,r1,56 // Fake "caller" frame - rlwinm r1,r1,0,0,29 // Align stack - - mfcr r0 - rlwinm r0,r0,0,11,8 - stw r0,4(r1) - mfxer r0 - stw r0,16(r1) - stw r2,12(r1) - stwu r1,-(56+16*4+15*8)(r1) - lwz r2,XLM_TOC - - // Save 68k registers - stw r8,56+M68kRegisters.d[0](r1) - stw r9,56+M68kRegisters.d[1](r1) - stw r10,56+M68kRegisters.d[2](r1) - stw r11,56+M68kRegisters.d[3](r1) - stw r12,56+M68kRegisters.d[4](r1) - stw r13,56+M68kRegisters.d[5](r1) - stw r14,56+M68kRegisters.d[6](r1) - stw r15,56+M68kRegisters.d[7](r1) - stw r16,56+M68kRegisters.a[0](r1) - stw r17,56+M68kRegisters.a[1](r1) - stw r18,56+M68kRegisters.a[2](r1) - stw r19,56+M68kRegisters.a[3](r1) - stw r20,56+M68kRegisters.a[4](r1) - stw r21,56+M68kRegisters.a[5](r1) - stw r22,56+M68kRegisters.a[6](r1) - stw r3,56+M68kRegisters.a[7](r1) - stfd f0,56+16*4+0*8(r1) - stfd f1,56+16*4+1*8(r1) - stfd f2,56+16*4+2*8(r1) - stfd f3,56+16*4+3*8(r1) - stfd f4,56+16*4+4*8(r1) - stfd f5,56+16*4+5*8(r1) - stfd f6,56+16*4+6*8(r1) - stfd f7,56+16*4+7*8(r1) - mffs f0 - stfd f8,56+16*4+8*8(r1) - stfd f9,56+16*4+9*8(r1) - stfd f10,56+16*4+10*8(r1) - stfd f11,56+16*4+11*8(r1) - stfd f12,56+16*4+12*8(r1) - stfd f13,56+16*4+13*8(r1) - stfd f0,56+16*4+14*8(r1) - - // Execute native routine - addi r3,r1,56 - mr r4,r24 - bl EmulOp - - // Restore 68k registers - lwz r8,56+M68kRegisters.d[0](r1) - lwz r9,56+M68kRegisters.d[1](r1) - lwz r10,56+M68kRegisters.d[2](r1) - lwz r11,56+M68kRegisters.d[3](r1) - lwz r12,56+M68kRegisters.d[4](r1) - lwz r13,56+M68kRegisters.d[5](r1) - lwz r14,56+M68kRegisters.d[6](r1) - lwz r15,56+M68kRegisters.d[7](r1) - lwz r16,56+M68kRegisters.a[0](r1) - lwz r17,56+M68kRegisters.a[1](r1) - lwz r18,56+M68kRegisters.a[2](r1) - lwz r19,56+M68kRegisters.a[3](r1) - lwz r20,56+M68kRegisters.a[4](r1) - lwz r21,56+M68kRegisters.a[5](r1) - lwz r22,56+M68kRegisters.a[6](r1) - lwz r3,56+M68kRegisters.a[7](r1) - lfd f13,56+16*4+14*8(r1) - lfd f0,56+16*4+0*8(r1) - lfd f1,56+16*4+1*8(r1) - lfd f2,56+16*4+2*8(r1) - lfd f3,56+16*4+3*8(r1) - lfd f4,56+16*4+4*8(r1) - lfd f5,56+16*4+5*8(r1) - lfd f6,56+16*4+6*8(r1) - lfd f7,56+16*4+7*8(r1) - mtfsf 0xff,f13 - lfd f8,56+16*4+8*8(r1) - lfd f9,56+16*4+9*8(r1) - lfd f10,56+16*4+10*8(r1) - lfd f11,56+16*4+11*8(r1) - lfd f12,56+16*4+12*8(r1) - lfd f13,56+16*4+13*8(r1) - - // Delete PowerPC stack frame - lwz r2,56+16*4+15*8+12(r1) - lwz r0,56+16*4+15*8+16(r1) - mtxer r0 - lwz r0,56+16*4+15*8+4(r1) - mtcrf 0xff,r0 - mr r1,r3 - - // Reeintering 68k emulator - li r0,MODE_68K - stw r0,XLM_RUN_MODE - - // Set r0 to 0 for 68k emulator - li r0,0 - - // Execute next 68k opcode - rlwimi r29,r27,3,13,28 - lhau r27,2(r24) - mtlr r29 - blr - - - // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch -@3 mflr r0 - stw r0,XLM_EMUL_OP_PROC - - // Save stack pointer for EMUL_RETURN - stw r1,XLM_EMUL_RETURN_STACK - - // Preset registers for ROM boot routine - lis r3,0x40b0 // Pointer to ROM boot structure - ori r3,r3,0xd000 - - // 68k emulator is now active - li r0,MODE_68K - stw r0,XLM_RUN_MODE - - // Jump to ROM - bctr -} -#endif - - -#if !EMULATED_PPC -/* - * Execute 68k subroutine (must be ended with RTS) - * This must only be called by the emul_thread when in EMUL_OP mode - * r->a[7] is unused, the routine runs on the caller's stack - */ - -#if SAFE_EXEC_68K -void execute_68k(uint32 pc, M68kRegisters *r); - -void Execute68k(uint32 pc, M68kRegisters *r) -{ - if (*(uint32 *)XLM_RUN_MODE != MODE_EMUL_OP) - printf("FATAL: Execute68k() not called from EMUL_OP mode\n"); - if (find_thread(NULL) != the_app->emul_thread) - printf("FATAL: Execute68k() not called from emul_thread\n"); - execute_68k(pc, r); -} - -asm void execute_68k(register uint32 pc, register M68kRegisters *r) -#else -asm void Execute68k(register uint32 pc, register M68kRegisters *r) -#endif -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stw r4,12(r1) - stwu r1,-(56+19*4+18*8)(r1) - - // Save PowerPC registers - stmw r13,56(r1) -#if SAVE_FP_EXEC_68K - stfd f14,56+19*4+0*8(r1) - stfd f15,56+19*4+1*8(r1) - stfd f16,56+19*4+2*8(r1) - stfd f17,56+19*4+3*8(r1) - stfd f18,56+19*4+4*8(r1) - stfd f19,56+19*4+5*8(r1) - stfd f20,56+19*4+6*8(r1) - stfd f21,56+19*4+7*8(r1) - stfd f22,56+19*4+8*8(r1) - stfd f23,56+19*4+9*8(r1) - stfd f24,56+19*4+10*8(r1) - stfd f25,56+19*4+11*8(r1) - stfd f26,56+19*4+12*8(r1) - stfd f27,56+19*4+13*8(r1) - stfd f28,56+19*4+14*8(r1) - stfd f29,56+19*4+15*8(r1) - stfd f30,56+19*4+16*8(r1) - stfd f31,56+19*4+17*8(r1) -#endif - - // Set up registers for 68k emulator - lwz r31,XLM_KERNEL_DATA // Pointer to Kernel Data - addi r31,r31,0x1000 - li r0,0 - mtcrf 0xff,r0 - creqv 11,11,11 // Supervisor mode - lwz r8,M68kRegisters.d[0](r4) - lwz r9,M68kRegisters.d[1](r4) - lwz r10,M68kRegisters.d[2](r4) - lwz r11,M68kRegisters.d[3](r4) - lwz r12,M68kRegisters.d[4](r4) - lwz r13,M68kRegisters.d[5](r4) - lwz r14,M68kRegisters.d[6](r4) - lwz r15,M68kRegisters.d[7](r4) - lwz r16,M68kRegisters.a[0](r4) - lwz r17,M68kRegisters.a[1](r4) - lwz r18,M68kRegisters.a[2](r4) - lwz r19,M68kRegisters.a[3](r4) - lwz r20,M68kRegisters.a[4](r4) - lwz r21,M68kRegisters.a[5](r4) - lwz r22,M68kRegisters.a[6](r4) - li r23,0 - mr r24,r3 - lwz r25,XLM_68K_R25 // MSB of SR - li r26,0 - li r28,0 // VBR - lwz r29,0x74(r31) // Pointer to opcode table - lwz r30,0x78(r31) // Address of emulator - - // Push return address (points to EXEC_RETURN opcode) on stack - li r0,XLM_EXEC_RETURN_OPCODE - stwu r0,-4(r1) - - // Reentering 68k emulator - li r0,MODE_68K - stw r0,XLM_RUN_MODE - - // Set r0 to 0 for 68k emulator - li r0,0 - - // Execute 68k opcode - lha r27,0(r24) - rlwimi r29,r27,3,13,28 - lhau r27,2(r24) - mtlr r29 - blr -} - - -/* - * Execute 68k A-Trap from EMUL_OP routine - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68kTrap(uint16 trap, M68kRegisters *r) -{ - uint16 proc[2] = {trap, M68K_RTS}; - Execute68k((uint32)proc, r); -} - - -/* - * Quit emulator (must only be called from main thread) - */ - -asm void QuitEmulator(void) -{ - lwz r0,XLM_EMUL_RETURN_PROC - mtlr r0 - blr -} -#endif - - -/* - * Dump 68k registers - */ - -void Dump68kRegs(M68kRegisters *r) -{ - // Display 68k registers - for (int i=0; i<8; i++) { - printf("d%d: %08lx", i, r->d[i]); - if (i == 3 || i == 7) - printf("\n"); - else - printf(", "); - } - for (int i=0; i<8; i++) { - printf("a%d: %08lx", i, r->a[i]); - if (i == 3 || i == 7) - printf("\n"); - else - printf(", "); - } -} - - -/* - * Make code executable - */ - -void MakeExecutable(int dummy, uint32 start, uint32 length) -{ - if ((start >= ROMBase) && (start < (ROMBase + ROM_SIZE))) - return; - clear_caches((void *)start, length, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE); -} - - -/* - * NVRAM watchdog thread (saves NVRAM every minute) - */ - -status_t SheepShaver::nvram_func(void *arg) -{ - SheepShaver *obj = (SheepShaver *)arg; - - while (obj->NVRAMThreadActive) { - snooze(60*1000000); - if (memcmp(obj->last_xpram, XPRAM, XPRAM_SIZE)) { - memcpy(obj->last_xpram, XPRAM, XPRAM_SIZE); - SaveXPRAM(); - } - } - return 0; -} - - -/* - * 60Hz thread (really 60.15Hz) - */ - -status_t SheepShaver::tick_func(void *arg) -{ - SheepShaver *obj = (SheepShaver *)arg; - int tick_counter = 0; - bigtime_t current = system_time(); - - while (obj->TickThreadActive) { - - // Wait - current += 16625; - snooze_until(current, B_SYSTEM_TIMEBASE); - - // Pseudo Mac 1Hz interrupt, update local time - if (++tick_counter > 60) { - tick_counter = 0; - WriteMacInt32(0x20c, TimerDateTime()); - } - - // 60Hz interrupt - if (ReadMacInt32(XLM_IRQ_NEST) == 0) { - SetInterruptFlag(INTFLAG_VIA); - TriggerInterrupt(); - } - } - return 0; -} - - -/* - * Trigger signal USR1 from another thread - */ - -void TriggerInterrupt(void) -{ - idle_resume(); -#if 0 - WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); -#else - if (the_app->emul_thread > 0 && the_app->ReadyForSignals) - send_signal(the_app->emul_thread, SIGUSR1); -#endif -} - - -/* - * Mutexes - */ - -struct B2_mutex { - int dummy; //!! -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - - -/* - * Set/clear interrupt flags (must be done atomically!) - */ - -volatile uint32 InterruptFlags = 0; - -void SetInterruptFlag(uint32 flag) -{ - atomic_or((int32 *)&InterruptFlags, flag); -} - -void ClearInterruptFlag(uint32 flag) -{ - atomic_and((int32 *)&InterruptFlags, ~flag); -} - - -/* - * Disable interrupts - */ - -void DisableInterrupt(void) -{ - atomic_add((int32 *)XLM_IRQ_NEST, 1); -} - - -/* - * Enable interrupts - */ - -void EnableInterrupt(void) -{ - atomic_add((int32 *)XLM_IRQ_NEST, -1); -} - - -/* - * USR1 handler - */ - -void SheepShaver::sigusr1_invoc(int sig, void *arg, vregs *r) -{ - ((SheepShaver *)arg)->sigusr1_handler(r); -} - -#if !EMULATED_PPC -static asm void ppc_interrupt(register uint32 entry) -{ - fralloc - - // Get address of return routine - bl @1 - - // Return routine - frfree - blr - -@1 - // Prepare registers for nanokernel interrupt routine - mtctr r1 - lwz r1,XLM_KERNEL_DATA - stw r6,0x018(r1) - mfctr r6 - stw r6,0x004(r1) - lwz r6,0x65c(r1) - stw r7,0x13c(r6) - stw r8,0x144(r6) - stw r9,0x14c(r6) - stw r10,0x154(r6) - stw r11,0x15c(r6) - stw r12,0x164(r6) - stw r13,0x16c(r6) - - mflr r10 - mfcr r13 - lwz r7,0x660(r1) - mflr r12 - rlwimi. r7,r7,8,0,0 - li r11,0 - ori r11,r11,0xf072 // MSR (SRR1) - mtcrf 0x70,r11 - li r8,0 - - // Enter nanokernel - mtlr r3 - blr -} -#endif - -void SheepShaver::sigusr1_handler(vregs *r) -{ - // Do nothing if interrupts are disabled - if ((*(int32 *)XLM_IRQ_NEST) > 0) - return; - - // Interrupt action depends on current run mode - switch (*(uint32 *)XLM_RUN_MODE) { - case MODE_68K: - // 68k emulator active, trigger 68k interrupt level 1 - *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1; - r->cr |= kernel_data->v[0x674 >> 2]; - break; - -#if INTERRUPTS_IN_NATIVE_MODE - case MODE_NATIVE: - // 68k emulator inactive, in nanokernel? - if (r->r1 != KernelDataAddr) { - // No, prepare for 68k interrupt level 1 - *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1; - *(uint32 *)(kernel_data->v[0x658 >> 2] + 0xdc) |= kernel_data->v[0x674 >> 2]; - - // Execute nanokernel interrupt routine (this will activate the 68k emulator) - atomic_add((int32 *)XLM_IRQ_NEST, 1); - if (ROMType == ROMTYPE_NEWWORLD) - ppc_interrupt(ROMBase + 0x312b1c); - else - ppc_interrupt(ROMBase + 0x312a3c); - } - break; -#endif - -#if INTERRUPTS_IN_EMUL_OP_MODE - case MODE_EMUL_OP: - // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0 - if ((*(uint32 *)XLM_68K_R25 & 7) == 0) { - - // Set extra stack for SIGSEGV handler - set_signal_stack(extra_stack, SIG_STACK_SIZE); -#if 1 - // Execute full 68k interrupt routine - M68kRegisters r; - uint32 old_r25 = *(uint32 *)XLM_68K_R25; // Save interrupt level - *(uint32 *)XLM_68K_R25 = 0x21; // Execute with interrupt level 1 - static const uint16 proc[] = { - 0x3f3c, 0x0000, // move.w #$0000,-(sp) (fake format word) - 0x487a, 0x000a, // pea @1(pc) (return address) - 0x40e7, // move sr,-(sp) (saved SR) - 0x2078, 0x0064, // move.l $64,a0 - 0x4ed0, // jmp (a0) - M68K_RTS // @1 - }; - Execute68k((uint32)proc, &r); - *(uint32 *)XLM_68K_R25 = old_r25; // Restore interrupt level -#else - // Only update cursor - if (HasMacStarted()) { - if (InterruptFlags & INTFLAG_VIA) { - ClearInterruptFlag(INTFLAG_VIA); - ADBInterrupt(); - ExecuteNative(NATIVE_VIDEO_VBL); - } - } -#endif - // Reset normal signal stack - set_signal_stack(sig_stack, SIG_STACK_SIZE); - } - break; -#endif - } -} - - -/* - * SIGSEGV handler - */ - -static uint32 segv_r[32]; - -#if !EMULATED_PPC -asm void SheepShaver::sigsegv_invoc(register int sig, register void *arg, register vregs *r) -{ - mflr r0 - stw r0,8(r1) - stwu r1,-56(r1) - - lwz r3,segv_r(r2) - stmw r13,13*4(r3) - - mr r3,r5 - bl sigsegv_handler - - lwz r3,segv_r(r2) - lmw r13,13*4(r3) - - lwz r0,56+8(r1) - mtlr r0 - addi r1,r1,56 - blr -} -#endif - -static void sigsegv_handler(vregs *r) -{ - char str[256]; - - // Fetch volatile registers - segv_r[0] = r->r0; - segv_r[1] = r->r1; - segv_r[2] = r->r2; - segv_r[3] = r->r3; - segv_r[4] = r->r4; - segv_r[5] = r->r5; - segv_r[6] = r->r6; - segv_r[7] = r->r7; - segv_r[8] = r->r8; - segv_r[9] = r->r9; - segv_r[10] = r->r10; - segv_r[11] = r->r11; - segv_r[12] = r->r12; - - // Get opcode and divide into fields - uint32 opcode = *(uint32 *)r->pc; - uint32 primop = opcode >> 26; - uint32 exop = (opcode >> 1) & 0x3ff; - uint32 ra = (opcode >> 16) & 0x1f; - uint32 rb = (opcode >> 11) & 0x1f; - uint32 rd = (opcode >> 21) & 0x1f; - uint32 imm = opcode & 0xffff; - - // Fault in Mac ROM or RAM? - bool mac_fault = (r->pc >= ROMBase) && (r->pc < (ROMBase + ROM_AREA_SIZE)) || (r->pc >= RAMBase) && (r->pc < (RAMBase + RAMSize)); - if (mac_fault) { - - // "VM settings" during MacOS 8 installation - if (r->pc == ROMBase + 0x488160 && segv_r[20] == 0xf8000000) { - r->pc += 4; - segv_r[8] = 0; - goto rti; - - // MacOS 8.5 installation - } else if (r->pc == ROMBase + 0x488140 && segv_r[16] == 0xf8000000) { - r->pc += 4; - segv_r[8] = 0; - goto rti; - - // MacOS 8 serial drivers on startup - } else if (r->pc == ROMBase + 0x48e080 && (segv_r[8] == 0xf3012002 || segv_r[8] == 0xf3012000)) { - r->pc += 4; - segv_r[8] = 0; - goto rti; - - // MacOS 8.1 serial drivers on startup - } else if (r->pc == ROMBase + 0x48c5e0 && (segv_r[20] == 0xf3012002 || segv_r[20] == 0xf3012000)) { - r->pc += 4; - goto rti; - } else if (r->pc == ROMBase + 0x4a10a0 && (segv_r[20] == 0xf3012002 || segv_r[20] == 0xf3012000)) { - r->pc += 4; - goto rti; - } - } - - // Analyze opcode - enum { - TYPE_UNKNOWN, - TYPE_LOAD, - TYPE_STORE - } transfer_type = TYPE_UNKNOWN; - enum { - SIZE_UNKNOWN, - SIZE_BYTE, - SIZE_HALFWORD, - SIZE_WORD - } transfer_size = SIZE_UNKNOWN; - enum { - MODE_UNKNOWN, - MODE_NORM, - MODE_U, - MODE_X, - MODE_UX - } addr_mode = MODE_UNKNOWN; - switch (primop) { - case 31: - switch (exop) { - case 23: // lwzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 55: // lwzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 87: // lbzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 119: // lbzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 151: // stwx - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 183: // stwux - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 215: // stbx - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 247: // stbux - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 279: // lhzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 311: // lhzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - case 343: // lhax - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 375: // lhaux - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - case 407: // sthx - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 439: // sthux - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - } - break; - - case 32: // lwz - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 33: // lwzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 34: // lbz - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 35: // lbzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 36: // stw - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 37: // stwu - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 38: // stb - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 39: // stbu - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 40: // lhz - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 41: // lhzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - case 42: // lha - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 43: // lhau - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - case 44: // sth - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 45: // sthu - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - } - - // Calculate effective address - uint32 addr = 0; - switch (addr_mode) { - case MODE_X: - case MODE_UX: - if (ra == 0) - addr = segv_r[rb]; - else - addr = segv_r[ra] + segv_r[rb]; - break; - case MODE_NORM: - case MODE_U: - if (ra == 0) - addr = (int32)(int16)imm; - else - addr = segv_r[ra] + (int32)(int16)imm; - break; - default: - break; - } - - // Ignore ROM writes - if (transfer_type == TYPE_STORE && addr >= ROMBase && addr < ROMBase + ROM_SIZE) { - D(bug("WARNING: %s write access to ROM at %p, pc %p\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc)); - if (addr_mode == MODE_U || addr_mode == MODE_UX) - segv_r[ra] = addr; - r->pc += 4; - goto rti; - } - - // Fault in Mac ROM or RAM? - if (mac_fault) { - - // Ignore illegal memory accesses? - if (PrefsFindBool("ignoresegv")) { - if (addr_mode == MODE_U || addr_mode == MODE_UX) - segv_r[ra] = addr; - if (transfer_type == TYPE_LOAD) - segv_r[rd] = 0; - r->pc += 4; - goto rti; - } - - // In GUI mode, show error alert - if (!PrefsFindBool("nogui")) { - if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE) - sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->pc, segv_r[24], segv_r[1]); - else - sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc, segv_r[24], segv_r[1], opcode); - ErrorAlert(str); - QuitEmulator(); - return; - } - } - - // For all other errors, jump into debugger - sprintf(str, "SIGSEGV\n" - " pc %08lx lr %08lx ctr %08lx msr %08lx\n" - " xer %08lx cr %08lx fpscr %08lx\n" - " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n" - " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n" - " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n" - " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n" - " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n" - " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n" - " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n" - " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", - r->pc, r->lr, r->ctr, r->msr, - r->xer, r->cr, r->fpscr, - r->r0, r->r1, r->r2, r->r3, - r->r4, r->r5, r->r6, r->r7, - r->r8, r->r9, r->r10, r->r11, - r->r12, segv_r[13], segv_r[14], segv_r[15], - segv_r[16], segv_r[17], segv_r[18], segv_r[19], - segv_r[20], segv_r[21], segv_r[22], segv_r[23], - segv_r[24], segv_r[25], segv_r[26], segv_r[27], - segv_r[28], segv_r[29], segv_r[30], segv_r[31]); - VideoQuitFullScreen(); - disable_debugger(false); - debugger(str); - exit(1); - return; - -rti: - // Restore volatile registers - r->r0 = segv_r[0]; - r->r1 = segv_r[1]; - r->r2 = segv_r[2]; - r->r3 = segv_r[3]; - r->r4 = segv_r[4]; - r->r5 = segv_r[5]; - r->r6 = segv_r[6]; - r->r7 = segv_r[7]; - r->r8 = segv_r[8]; - r->r9 = segv_r[9]; - r->r10 = segv_r[10]; - r->r11 = segv_r[11]; - r->r12 = segv_r[12]; -} - - -/* - * SIGILL handler - */ - -#if !EMULATED_PPC -asm void SheepShaver::sigill_invoc(register int sig, register void *arg, register vregs *r) -{ - mflr r0 - stw r0,8(r1) - stwu r1,-56(r1) - - lwz r3,segv_r(r2) - stmw r13,13*4(r3) - - mr r3,r5 - bl sigill_handler - - lwz r3,segv_r(r2) - lmw r13,13*4(r3) - - lwz r0,56+8(r1) - mtlr r0 - addi r1,r1,56 - blr -} -#endif - -static void sigill_handler(vregs *r) -{ - char str[256]; - - // Fetch volatile registers - segv_r[0] = r->r0; - segv_r[1] = r->r1; - segv_r[2] = r->r2; - segv_r[3] = r->r3; - segv_r[4] = r->r4; - segv_r[5] = r->r5; - segv_r[6] = r->r6; - segv_r[7] = r->r7; - segv_r[8] = r->r8; - segv_r[9] = r->r9; - segv_r[10] = r->r10; - segv_r[11] = r->r11; - segv_r[12] = r->r12; - - // Get opcode and divide into fields - uint32 opcode = *(uint32 *)r->pc; - uint32 primop = opcode >> 26; - uint32 exop = (opcode >> 1) & 0x3ff; - uint32 ra = (opcode >> 16) & 0x1f; - uint32 rb = (opcode >> 11) & 0x1f; - uint32 rd = (opcode >> 21) & 0x1f; - uint32 imm = opcode & 0xffff; - - // Fault in Mac ROM or RAM? - bool mac_fault = (r->pc >= ROMBase) && (r->pc < (ROMBase + ROM_AREA_SIZE)) || (r->pc >= RAMBase) && (r->pc < (RAMBase + RAMSize)); - if (mac_fault) { - - switch (primop) { - case 9: // POWER instructions - case 22: -power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->pc, segv_r[1], opcode); - ErrorAlert(str); - QuitEmulator(); - return; - - case 31: - switch (exop) { - case 83: // mfmsr - segv_r[rd] = 0xf072; - r->pc += 4; - goto rti; - - case 210: // mtsr - case 242: // mtsrin - case 306: // tlbie - r->pc += 4; - goto rti; - - case 339: { // mfspr - int spr = ra | (rb << 5); - switch (spr) { - case 0: // MQ - case 22: // DEC - case 952: // MMCR0 - case 953: // PMC1 - case 954: // PMC2 - case 955: // SIA - case 956: // MMCR1 - case 957: // PMC3 - case 958: // PMC4 - case 959: // SDA - r->pc += 4; - goto rti; - case 25: // SDR1 - segv_r[rd] = 0xdead001f; - r->pc += 4; - goto rti; - case 287: // PVR - segv_r[rd] = PVR; - r->pc += 4; - goto rti; - } - break; - } - - case 467: { // mtspr - int spr = ra | (rb << 5); - switch (spr) { - case 0: // MQ - case 22: // DEC - case 275: // SPRG3 - case 528: // IBAT0U - case 529: // IBAT0L - case 530: // IBAT1U - case 531: // IBAT1L - case 532: // IBAT2U - case 533: // IBAT2L - case 534: // IBAT3U - case 535: // IBAT3L - case 536: // DBAT0U - case 537: // DBAT0L - case 538: // DBAT1U - case 539: // DBAT1L - case 540: // DBAT2U - case 541: // DBAT2L - case 542: // DBAT3U - case 543: // DBAT3L - case 952: // MMCR0 - case 953: // PMC1 - case 954: // PMC2 - case 955: // SIA - case 956: // MMCR1 - case 957: // PMC3 - case 958: // PMC4 - case 959: // SDA - r->pc += 4; - goto rti; - } - break; - } - - case 29: case 107: case 152: case 153: // POWER instructions - case 184: case 216: case 217: case 248: - case 264: case 277: case 331: case 360: - case 363: case 488: case 531: case 537: - case 541: case 664: case 665: case 696: - case 728: case 729: case 760: case 920: - case 921: case 952: - goto power_inst; - } - } - - // In GUI mode, show error alert - if (!PrefsFindBool("nogui")) { - sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc, segv_r[24], segv_r[1], opcode); - ErrorAlert(str); - QuitEmulator(); - return; - } - } - - // For all other errors, jump into debugger - sprintf(str, "SIGILL\n" - " pc %08lx lr %08lx ctr %08lx msr %08lx\n" - " xer %08lx cr %08lx fpscr %08lx\n" - " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n" - " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n" - " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n" - " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n" - " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n" - " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n" - " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n" - " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", - r->pc, r->lr, r->ctr, r->msr, - r->xer, r->cr, r->fpscr, - r->r0, r->r1, r->r2, r->r3, - r->r4, r->r5, r->r6, r->r7, - r->r8, r->r9, r->r10, r->r11, - r->r12, segv_r[13], segv_r[14], segv_r[15], - segv_r[16], segv_r[17], segv_r[18], segv_r[19], - segv_r[20], segv_r[21], segv_r[22], segv_r[23], - segv_r[24], segv_r[25], segv_r[26], segv_r[27], - segv_r[28], segv_r[29], segv_r[30], segv_r[31]); - VideoQuitFullScreen(); - disable_debugger(false); - debugger(str); - exit(1); - return; - -rti: - // Restore volatile registers - r->r0 = segv_r[0]; - r->r1 = segv_r[1]; - r->r2 = segv_r[2]; - r->r3 = segv_r[3]; - r->r4 = segv_r[4]; - r->r5 = segv_r[5]; - r->r6 = segv_r[6]; - r->r7 = segv_r[7]; - r->r8 = segv_r[8]; - r->r9 = segv_r[9]; - r->r10 = segv_r[10]; - r->r11 = segv_r[11]; - r->r12 = segv_r[12]; -} - - -/* - * Helpers to share 32-bit addressable data with MacOS - */ - -bool SheepMem::Init(void) -{ - // Delete old area - area_id old_sheep_area = find_area(SHEEP_AREA_NAME); - if (old_sheep_area > 0) - delete_area(old_sheep_area); - - // Create area for SheepShaver data - proc = base = 0x60000000; - SheepMemArea = create_area(SHEEP_AREA_NAME, (void **)&base, B_BASE_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (SheepMemArea < 0) - return false; - - // Create read-only area with all bits set to 0 - static const uint8 const_zero_page[4096] = {0,}; - zero_page = const_zero_page; - - D(bug("SheepShaver area %ld at %p\n", SheepMemArea, base)); - data = base + size; - return true; -} - -void SheepMem::Exit(void) -{ - if (SheepMemArea >= 0) - delete_area(SheepMemArea); -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - if (PrefsFindBool("nogui")) { - printf(GetString(STR_SHELL_ERROR_PREFIX), text); - return; - } - char str[256]; - sprintf(str, GetString(STR_GUI_ERROR_PREFIX), text); - VideoQuitFullScreen(); - BAlert *alert = new BAlert(GetString(STR_ERROR_ALERT_TITLE), str, GetString(STR_QUIT_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); - alert->Go(); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - if (PrefsFindBool("nogui")) { - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return; - } - char str[256]; - sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text); - BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, GetString(STR_OK_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); - alert->Go(); -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - char str[256]; - sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text); - BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, pos, neg, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); - return alert->Go() == 0; -} diff --git a/SheepShaver/src/BeOS/prefs_beos.cpp b/SheepShaver/src/BeOS/prefs_beos.cpp deleted file mode 100644 index cad4a888..00000000 --- a/SheepShaver/src/BeOS/prefs_beos.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * prefs_beos.cpp - Preferences handling, BeOS specific things - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "prefs.h" -#include "main.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { - {"bitbang", TYPE_BOOLEAN, false, "draw Mac desktop directly on screen in window mode"}, - {"idlewait", TYPE_BOOLEAN, false, "sleep when idle"}, - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Preferences file name and path -const char PREFS_FILE_NAME[] = "SheepShaver_prefs"; -static BPath prefs_path; - -// Modification date of prefs file -time_t PrefsFileDate = 0; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(const char *vmdir) -{ - // Construct prefs path - find_directory(B_USER_SETTINGS_DIRECTORY, &prefs_path, true); - prefs_path.Append(PREFS_FILE_NAME); - - // Read preferences from settings file - FILE *f = fopen(prefs_path.Path(), "r"); - if (f == NULL) // Not found in settings directory, look in app directory - f = fopen(PREFS_FILE_NAME, "r"); - if (f != NULL) { - LoadPrefsFromStream(f); - - struct stat s; - fstat(fileno(f), &s); - PrefsFileDate = s.st_ctime; - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - PrefsFileDate = real_time_clock(); - } -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = fopen(prefs_path.Path(), "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsReplaceString("extfs", "/boot"); - PrefsAddInt32("windowmodes", - B_8_BIT_640x480 | B_15_BIT_640x480 | B_32_BIT_640x480 | - B_8_BIT_800x600 | B_15_BIT_800x600 | B_32_BIT_800x600 - ); - PrefsAddInt32("screenmodes", - B_8_BIT_640x480 | B_15_BIT_640x480 | B_32_BIT_640x480 | - B_8_BIT_800x600 | B_15_BIT_800x600 | B_32_BIT_800x600 | - B_8_BIT_1024x768 | B_15_BIT_1024x768 - ); - PrefsAddBool("bitbang", false); - PrefsAddBool("idlewait", true); -} diff --git a/SheepShaver/src/BeOS/prefs_editor_beos.cpp b/SheepShaver/src/BeOS/prefs_editor_beos.cpp deleted file mode 100644 index 847700c2..00000000 --- a/SheepShaver/src/BeOS/prefs_editor_beos.cpp +++ /dev/null @@ -1,877 +0,0 @@ -/* - * prefs_editor_beos.cpp - Preferences editor, BeOS implementation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -#include "prefs_editor.h" -#include "prefs.h" -#include "main.h" -#include "cdrom.h" -#include "xpram.h" -#include "about_window.h" -#include "user_strings.h" - - -// Special colors -const rgb_color fill_color = {216, 216, 216, 0}; -const rgb_color slider_fill_color = {102, 152, 255, 0}; - - -// Window messages -const uint32 MSG_OK = 'okok'; // "Start" clicked -const uint32 MSG_CANCEL = 'cncl'; // "Quit" clicked -const uint32 MSG_ZAP_PRAM = 'zprm'; - -const int NUM_PANES = 4; - -const uint32 MSG_VOLUME_SELECTED = 'volu'; // "Volumes" pane -const uint32 MSG_VOLUME_INVOKED = 'voli'; -const uint32 MSG_ADD_VOLUME = 'addv'; -const uint32 MSG_CREATE_VOLUME = 'crev'; -const uint32 MSG_REMOVE_VOLUME = 'remv'; -const uint32 MSG_ADD_VOLUME_PANEL = 'advp'; -const uint32 MSG_CREATE_VOLUME_PANEL = 'crvp'; -const uint32 MSG_DEVICE_NAME = 'devn'; -const uint32 MSG_BOOT_ANY = 'bany'; -const uint32 MSG_BOOT_CDROM = 'bcdr'; -const uint32 MSG_NOCDROM = 'nocd'; - -const uint32 MSG_REF_5HZ = ' 5Hz'; // "Graphics" pane -const uint32 MSG_REF_7_5HZ = ' 7Hz'; -const uint32 MSG_REF_10HZ = '10Hz'; -const uint32 MSG_REF_15HZ = '15Hz'; -const uint32 MSG_REF_30HZ = '30Hz'; -const uint32 MSG_GFXACCEL = 'gfac'; -const uint32 MSG_WINDOW_MODE = 'wmod'; -const uint32 MSG_SCREEN_MODE = 'smod'; -const uint32 MSG_NOSOUND = 'nosn'; - -const uint32 MSG_SER_A = 'sera'; // "Serial"/"Network" pane -const uint32 MSG_SER_B = 'serb'; -const uint32 MSG_NONET = 'noet'; - -const uint32 MSG_RAMSIZE = 'rmsz'; // "Memory" pane -const uint32 MSG_IGNORESEGV = 'isgv'; -const uint32 MSG_IDLEWAIT = 'idlw'; - - -// RAM size slider class -class RAMSlider : public BSlider { -public: - RAMSlider(BRect frame, const char *name, const char *label, BMessage *message, - int32 minValue, int32 maxValue, thumb_style thumbType = B_BLOCK_THUMB, - uint32 resizingMode = B_FOLLOW_LEFT | - B_FOLLOW_TOP, - uint32 flags = B_NAVIGABLE | B_WILL_DRAW | - B_FRAME_EVENTS) : BSlider(frame, name, label, message, minValue, maxValue, thumbType, resizingMode, flags) - { - update_text = (char *)malloc(256); - } - - virtual ~RAMSlider() - { - if (update_text) - free(update_text); - } - - virtual char *UpdateText(void) const - { - if (update_text) { - sprintf(update_text, GetString(STR_RAMSIZE_FMT), Value()); - } - return update_text; - } - -private: - char *update_text; -}; - - -// Volumes list view class -class VolumeListView : public BListView { -public: - VolumeListView(BRect frame, const char *name, list_view_type type = B_SINGLE_SELECTION_LIST, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE) - : BListView(frame, name, type, resizeMask, flags) - {} - - // Handle dropped files and volumes - virtual void MessageReceived(BMessage *msg) - { - if (msg->what == B_SIMPLE_DATA) { - BMessage msg2(MSG_ADD_VOLUME_PANEL); - entry_ref ref; - for (int i=0; msg->FindRef("refs", i, &ref) == B_NO_ERROR; i++) - msg2.AddRef("refs", &ref); - Window()->PostMessage(&msg2); - } else - BListView::MessageReceived(msg); - } -}; - - -// Number-entry BTextControl -class NumberControl : public BTextControl { -public: - NumberControl(BRect frame, float divider, const char *name, const char *label, long value, BMessage *message) - : BTextControl(frame, name, label, NULL, message, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE) - { - SetDivider(divider); - for (int c=0; c<256; c++) - if (!isdigit(c) && c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW) - ((BTextView *)ChildAt(0))->DisallowChar(c); - SetValue(value); - } - - // Set integer value - void SetValue(long value) - { - char str[32]; - sprintf(str, "%ld", value); - SetText(str); - } - - // Get integer value - long Value(void) - { - return atol(Text()); - } -}; - - -// Path-entry BTextControl -class PathControl : public BTextControl { -public: - PathControl(bool dir_ctrl_, BRect frame, const char *name, const char *label, const char *text, BMessage *message) : BTextControl(frame, name, label, text, message), dir_ctrl(dir_ctrl_) - { - for (int c=0; c<' '; c++) - if (c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW) - ((BTextView *)ChildAt(0))->DisallowChar(c); - } - - virtual void MessageReceived(BMessage *msg) - { - if (msg->what == B_SIMPLE_DATA) { - entry_ref the_ref; - BEntry the_entry; - - // Look for dropped refs - if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) { - if (the_entry.SetTo(&the_ref) == B_NO_ERROR && (dir_ctrl&& the_entry.IsDirectory() || !dir_ctrl && the_entry.IsFile())) { - BPath the_path; - the_entry.GetPath(&the_path); - SetText(the_path.Path()); - } - } else - BTextControl::MessageReceived(msg); - - MakeFocus(); - } else - BTextControl::MessageReceived(msg); - } - -private: - bool dir_ctrl; -}; - - -// Preferences window class -class PrefsWindow : public BWindow { -public: - PrefsWindow(uint32 msg); - virtual ~PrefsWindow(); - virtual void MessageReceived(BMessage *msg); - -private: - BView *create_volumes_pane(void); - BView *create_graphics_pane(void); - BView *create_serial_pane(void); - BView *create_memory_pane(void); - - uint32 ok_message; - bool send_quit_on_close; - - BMessenger this_messenger; - BView *top; - BRect top_frame; - BTabView *pane_tabs; - BView *panes[NUM_PANES]; - int current_pane; - - VolumeListView *volume_list; - BCheckBox *nocdrom_checkbox; - BCheckBox *gfxaccel_checkbox; - BCheckBox *nosound_checkbox; - BCheckBox *nonet_checkbox; - BCheckBox *ignoresegv_checkbox; - BCheckBox *idlewait_checkbox; - RAMSlider *ramsize_slider; - PathControl *extfs_control; - PathControl *rom_control; - - BFilePanel *add_volume_panel; - BFilePanel *create_volume_panel; - - uint32 max_ramsize; // In MB -}; - - -/* - * Show preferences editor - * When the user clicks on "OK", the message given as parameter is sent - * to the application; if he clicks on "Quit", B_QUIT_REQUESTED is sent - */ - -void PrefsEditor(uint32 msg) -{ - new PrefsWindow(msg); -} - - -/* - * Preferences window constructor - */ - -PrefsWindow::PrefsWindow(uint32 msg) : BWindow(BRect(0, 0, 400, 289), GetString(STR_PREFS_TITLE), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS), this_messenger(this) -{ - int i; - ok_message = msg; - send_quit_on_close = true; - - // Move window to right position - Lock(); - MoveTo(80, 80); - - // Set up menus - BMenuBar *bar = new BMenuBar(Bounds(), "menu"); - BMenu *menu = new BMenu(GetString(STR_PREFS_MENU)); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ABOUT), new BMessage(B_ABOUT_REQUESTED))); - menu->AddItem(new BSeparatorItem); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_START), new BMessage(MSG_OK))); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ZAP_PRAM), new BMessage(MSG_ZAP_PRAM))); - menu->AddItem(new BSeparatorItem); - menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_QUIT), new BMessage(MSG_CANCEL), 'Q')); - bar->AddItem(menu); - AddChild(bar); - SetKeyMenuBar(bar); - int mbar_height = bar->Bounds().bottom + 1; - - // Resize window to fit menu bar - ResizeBy(0, mbar_height); - - // Light gray background - BRect b = Bounds(); - top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, B_WILL_DRAW); - AddChild(top); - top->SetViewColor(fill_color); - top_frame = top->Bounds(); - - // Create panes - panes[0] = create_volumes_pane(); - panes[1] = create_graphics_pane(); - panes[2] = create_serial_pane(); - panes[3] = create_memory_pane(); - - // Prefs item tab view - pane_tabs = new BTabView(BRect(10, 10, top_frame.right-10, top_frame.bottom-50), "items", B_WIDTH_FROM_LABEL); - for (i=0; iAddTab(panes[i]); - top->AddChild(pane_tabs); - - volume_list->Select(0); - - // Create volume file panels - add_volume_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_ADD_VOLUME_PANEL)); - add_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_ADD_VOLUME_PANEL_BUTTON)); - add_volume_panel->Window()->SetTitle(GetString(STR_ADD_VOLUME_TITLE)); - create_volume_panel = new BFilePanel(B_SAVE_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_CREATE_VOLUME_PANEL)); - create_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_CREATE_VOLUME_PANEL_BUTTON)); - create_volume_panel->Window()->SetTitle(GetString(STR_CREATE_VOLUME_TITLE)); - - create_volume_panel->Window()->Lock(); - BView *background = create_volume_panel->Window()->ChildAt(0); - background->FindView("PoseView")->ResizeBy(0, -30); - background->FindView("VScrollBar")->ResizeBy(0, -30); - background->FindView("CountVw")->MoveBy(0, -30); - BView *v = background->FindView("HScrollBar"); - if (v) - v->MoveBy(0, -30); - else { - i = 0; - while ((v = background->ChildAt(i++)) != NULL) { - if (v->Name() == NULL || v->Name()[0] == 0) { - v->MoveBy(0, -30); // unnamed horizontal scroll bar - break; - } - } - } - BView *filename = background->FindView("text view"); - BRect fnr(filename->Frame()); - fnr.OffsetBy(0, -30); - NumberControl *nc = new NumberControl(fnr, 80, "hardfile_size", GetString(STR_HARDFILE_SIZE_CTRL), 40, NULL); - background->AddChild(nc); - create_volume_panel->Window()->Unlock(); - - // "Start" button - BButton *button = new BButton(BRect(20, top_frame.bottom-35, 90, top_frame.bottom-10), "start", GetString(STR_START_BUTTON), new BMessage(MSG_OK)); - top->AddChild(button); - SetDefaultButton(button); - - // "Quit" button - top->AddChild(new BButton(BRect(top_frame.right-90, top_frame.bottom-35, top_frame.right-20, top_frame.bottom-10), "cancel", GetString(STR_QUIT_BUTTON), new BMessage(MSG_CANCEL))); - - Unlock(); - Show(); -} - - -/* - * Preferences window destructor - */ - -PrefsWindow::~PrefsWindow() -{ - delete add_volume_panel; - if (send_quit_on_close) - be_app->PostMessage(B_QUIT_REQUESTED); -} - - -/* - * Create "Volumes" pane - */ - -BView *PrefsWindow::create_volumes_pane(void) -{ - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_VOLUMES_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - const char *str; - int32 index = 0; - volume_list = new VolumeListView(BRect(15, 10, pane->Bounds().right-30, 108), "volumes"); - while ((str = PrefsFindString("disk", index++)) != NULL) - volume_list->AddItem(new BStringItem(str)); - volume_list->SetSelectionMessage(new BMessage(MSG_VOLUME_SELECTED)); - volume_list->SetInvocationMessage(new BMessage(MSG_VOLUME_INVOKED)); - pane->AddChild(new BScrollView("volumes_border", volume_list, B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true)); - - pane->AddChild(new BButton(BRect(10, 113, pane->Bounds().right/3, 133), "add_volume", GetString(STR_ADD_VOLUME_BUTTON), new BMessage(MSG_ADD_VOLUME))); - pane->AddChild(new BButton(BRect(pane->Bounds().right/3, 113, pane->Bounds().right*2/3, 133), "create_volume", GetString(STR_CREATE_VOLUME_BUTTON), new BMessage(MSG_CREATE_VOLUME))); - pane->AddChild(new BButton(BRect(pane->Bounds().right*2/3, 113, pane->Bounds().right-11, 133), "remove_volume", GetString(STR_REMOVE_VOLUME_BUTTON), new BMessage(MSG_REMOVE_VOLUME))); - - extfs_control = new PathControl(true, BRect(10, 145, right, 160), "extfs", GetString(STR_EXTFS_CTRL), PrefsFindString("extfs"), NULL); - extfs_control->SetDivider(90); - pane->AddChild(extfs_control); - - BMenuField *menu_field; - BPopUpMenu *menu = new BPopUpMenu(""); - menu_field = new BMenuField(BRect(10, 165, right, 180), "bootdriver", GetString(STR_BOOTDRIVER_CTRL), menu); - menu_field->SetDivider(90); - menu->AddItem(new BMenuItem(GetString(STR_BOOT_ANY_LAB), new BMessage(MSG_BOOT_ANY))); - menu->AddItem(new BMenuItem(GetString(STR_BOOT_CDROM_LAB), new BMessage(MSG_BOOT_CDROM))); - pane->AddChild(menu_field); - int16 i16 = PrefsFindInt32("bootdriver"); - BMenuItem *item; - if (i16 == 0) { - if ((item = menu->FindItem(GetString(STR_BOOT_ANY_LAB))) != NULL) - item->SetMarked(true); - } else if (i16 == CDROMRefNum) { - if ((item = menu->FindItem(GetString(STR_BOOT_CDROM_LAB))) != NULL) - item->SetMarked(true); - } - - nocdrom_checkbox = new BCheckBox(BRect(10, 185, right, 200), "nocdrom", GetString(STR_NOCDROM_CTRL), new BMessage(MSG_NOCDROM)); - pane->AddChild(nocdrom_checkbox); - nocdrom_checkbox->SetValue(PrefsFindBool("nocdrom") ? B_CONTROL_ON : B_CONTROL_OFF); - - return pane; -} - - -/* - * Create "Graphics/Sound" pane - */ - -struct video_mode_box { - uint32 mode; - int mode_string_id, bit_string_id; - float left, top; - BCheckBox *box; -}; - -const int NUM_WINDOW_MODES = 6; -const int NUM_SCREEN_MODES = 18; - -static video_mode_box window_mode_boxes[NUM_SCREEN_MODES] = { - {B_8_BIT_640x480, STR_W_640x480_CTRL, STR_8_BIT_CTRL, 140, 48, NULL}, - {B_15_BIT_640x480, STR_W_640x480_CTRL, STR_16_BIT_CTRL, 220, 48, NULL}, - {B_32_BIT_640x480, STR_W_640x480_CTRL, STR_32_BIT_CTRL, 300, 48, NULL}, - {B_8_BIT_800x600, STR_W_800x600_CTRL, STR_8_BIT_CTRL, 140, 65, NULL}, - {B_15_BIT_800x600, STR_W_800x600_CTRL, STR_16_BIT_CTRL, 220, 65, NULL}, - {B_32_BIT_800x600, STR_W_800x600_CTRL, STR_32_BIT_CTRL, 300, 65, NULL}, -}; - -static video_mode_box screen_mode_boxes[NUM_SCREEN_MODES] = { - {B_8_BIT_640x480, STR_640x480_CTRL, STR_8_BIT_CTRL, 140, 82, NULL}, - {B_15_BIT_640x480, STR_640x480_CTRL, STR_16_BIT_CTRL, 220, 82, NULL}, - {B_32_BIT_640x480, STR_640x480_CTRL, STR_32_BIT_CTRL, 300, 82, NULL}, - {B_8_BIT_800x600, STR_800x600_CTRL, STR_8_BIT_CTRL, 140, 99, NULL}, - {B_15_BIT_800x600, STR_800x600_CTRL, STR_16_BIT_CTRL, 220, 99, NULL}, - {B_32_BIT_800x600, STR_800x600_CTRL, STR_32_BIT_CTRL, 300, 99, NULL}, - {B_8_BIT_1024x768, STR_1024x768_CTRL, STR_8_BIT_CTRL, 140, 116, NULL}, - {B_15_BIT_1024x768, STR_1024x768_CTRL, STR_16_BIT_CTRL, 220, 116, NULL}, - {B_32_BIT_1024x768, STR_1024x768_CTRL, STR_32_BIT_CTRL, 300, 116, NULL}, - {B_8_BIT_1152x900, STR_1152x900_CTRL, STR_8_BIT_CTRL, 140, 133, NULL}, - {B_15_BIT_1152x900, STR_1152x900_CTRL, STR_16_BIT_CTRL, 220, 133, NULL}, - {B_32_BIT_1152x900, STR_1152x900_CTRL, STR_32_BIT_CTRL, 300, 133, NULL}, - {B_8_BIT_1280x1024, STR_1280x1024_CTRL, STR_8_BIT_CTRL, 140, 150, NULL}, - {B_15_BIT_1280x1024, STR_1280x1024_CTRL, STR_16_BIT_CTRL, 220, 150, NULL}, - {B_32_BIT_1280x1024, STR_1280x1024_CTRL, STR_32_BIT_CTRL, 300, 150, NULL}, - {B_8_BIT_1600x1200, STR_1600x1200_CTRL, STR_8_BIT_CTRL, 140, 167, NULL}, - {B_15_BIT_1600x1200, STR_1600x1200_CTRL, STR_16_BIT_CTRL, 220, 167, NULL}, - {B_32_BIT_1600x1200, STR_1600x1200_CTRL, STR_32_BIT_CTRL, 300, 167, NULL} -}; - -BView *PrefsWindow::create_graphics_pane(void) -{ - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_GRAPHICS_SOUND_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - BMenuField *menu_field; - BPopUpMenu *menu = new BPopUpMenu(""); - menu_field = new BMenuField(BRect(10, 5, right, 20), "frameskip", GetString(STR_FRAMESKIP_CTRL), menu); - menu_field->SetDivider(120); - menu->AddItem(new BMenuItem(GetString(STR_REF_5HZ_LAB), new BMessage(MSG_REF_5HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_7_5HZ_LAB), new BMessage(MSG_REF_7_5HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_10HZ_LAB), new BMessage(MSG_REF_10HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_15HZ_LAB), new BMessage(MSG_REF_15HZ))); - menu->AddItem(new BMenuItem(GetString(STR_REF_30HZ_LAB), new BMessage(MSG_REF_30HZ))); - pane->AddChild(menu_field); - int32 i32 = PrefsFindInt32("frameskip"); - BMenuItem *item; - if (i32 == 12) { - if ((item = menu->FindItem(GetString(STR_REF_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 8) { - if ((item = menu->FindItem(GetString(STR_REF_7_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 6) { - if ((item = menu->FindItem(GetString(STR_REF_10HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 4) { - if ((item = menu->FindItem(GetString(STR_REF_15HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (i32 == 2) { - if ((item = menu->FindItem(GetString(STR_REF_30HZ_LAB))) != NULL) - item->SetMarked(true); - } - - gfxaccel_checkbox = new BCheckBox(BRect(10, 25, right, 40), "gfxaccel", GetString(STR_GFXACCEL_CTRL), new BMessage(MSG_GFXACCEL)); - pane->AddChild(gfxaccel_checkbox); - gfxaccel_checkbox->SetValue(PrefsFindBool("gfxaccel") ? B_CONTROL_ON : B_CONTROL_OFF); - - uint32 window_modes = PrefsFindInt32("windowmodes"); - for (int i=0; ibit_string_id == STR_8_BIT_CTRL) { - BStringView *text = new BStringView(BRect(10, p->top, 120, p->top + 15), "", GetString(p->mode_string_id)); - pane->AddChild(text); - } - p->box = new BCheckBox(BRect(p->left, p->top, p->left + 80, p->top + 15), "", GetString(p->bit_string_id), new BMessage(MSG_WINDOW_MODE)); - pane->AddChild(p->box); - p->box->SetValue(window_modes & p->mode ? B_CONTROL_ON : B_CONTROL_OFF); - } - uint32 screen_modes = PrefsFindInt32("screenmodes"); - for (int i=0; ibit_string_id == STR_8_BIT_CTRL) { - BStringView *text = new BStringView(BRect(10, p->top, 120, p->top + 15), "", GetString(p->mode_string_id)); - pane->AddChild(text); - } - p->box = new BCheckBox(BRect(p->left, p->top, p->left + 80, p->top + 15), "", GetString(p->bit_string_id), new BMessage(MSG_SCREEN_MODE)); - pane->AddChild(p->box); - p->box->SetValue(screen_modes & p->mode ? B_CONTROL_ON : B_CONTROL_OFF); - } - - nosound_checkbox = new BCheckBox(BRect(10, 185, right, 200), "nosound", GetString(STR_NOSOUND_CTRL), new BMessage(MSG_NOSOUND)); - pane->AddChild(nosound_checkbox); - nosound_checkbox->SetValue(PrefsFindBool("nosound") ? B_CONTROL_ON : B_CONTROL_OFF); - - return pane; -} - - -/* - * Create "Serial/Network" pane - */ - -static void add_serial_names(BPopUpMenu *menu, uint32 msg) -{ - BSerialPort *port = new BSerialPort; - char name[B_PATH_NAME_LENGTH]; - for (int i=0; iCountDevices(); i++) { - port->GetDeviceName(i, name); - menu->AddItem(new BMenuItem(name, new BMessage(msg))); - } - if (SysInfo.platform_type == B_BEBOX_PLATFORM) { - BDirectory dir; - BEntry entry; - dir.SetTo("/dev/parallel"); - if (dir.InitCheck() == B_NO_ERROR) { - dir.Rewind(); - while (dir.GetNextEntry(&entry) >= 0) { - if (!entry.IsDirectory()) { - entry.GetName(name); - menu->AddItem(new BMenuItem(name, new BMessage(msg))); - } - } - } - } - delete port; -} - -static void set_serial_label(BPopUpMenu *menu, const char *prefs_name) -{ - const char *str; - BMenuItem *item; - if ((str = PrefsFindString(prefs_name)) != NULL) - if ((item = menu->FindItem(str)) != NULL) - item->SetMarked(true); -} - -BView *PrefsWindow::create_serial_pane(void) -{ - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_SERIAL_NETWORK_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - BMenuField *menu_field; - BPopUpMenu *menu_a = new BPopUpMenu(""); - add_serial_names(menu_a, MSG_SER_A); - menu_field = new BMenuField(BRect(10, 5, right, 20), "seriala", GetString(STR_SERPORTA_CTRL), menu_a); - menu_field->SetDivider(90); - pane->AddChild(menu_field); - set_serial_label(menu_a, "seriala"); - - BPopUpMenu *menu_b = new BPopUpMenu(""); - add_serial_names(menu_b, MSG_SER_B); - menu_field = new BMenuField(BRect(10, 26, right, 41), "serialb", GetString(STR_SERPORTB_CTRL), menu_b); - menu_field->SetDivider(90); - pane->AddChild(menu_field); - set_serial_label(menu_b, "serialb"); - - nonet_checkbox = new BCheckBox(BRect(10, 47, right, 62), "nonet", GetString(STR_NONET_CTRL), new BMessage(MSG_NONET)); - pane->AddChild(nonet_checkbox); - nonet_checkbox->SetValue(PrefsFindBool("nonet") ? B_CONTROL_ON : B_CONTROL_OFF); - - return pane; -} - - -/* - * Create "Memory/Misc" pane - */ - -BView *PrefsWindow::create_memory_pane(void) -{ - char str[256], str2[256]; - BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_MEMORY_MISC_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW); - pane->SetViewColor(fill_color); - float right = pane->Bounds().right-10; - - BEntry entry("/boot/var/swap"); - off_t swap_space; - if (entry.GetSize(&swap_space) == B_NO_ERROR) - max_ramsize = swap_space / (1024 * 1024) - 8; - else - max_ramsize = SysInfo.max_pages * B_PAGE_SIZE / (1024 * 1024) - 8; - - int32 value = PrefsFindInt32("ramsize") / (1024 * 1024); - - ramsize_slider = new RAMSlider(BRect(10, 5, right, 55), "ramsize", GetString(STR_RAMSIZE_SLIDER), new BMessage(MSG_RAMSIZE), 8, max_ramsize, B_TRIANGLE_THUMB); - ramsize_slider->SetValue(value); - ramsize_slider->UseFillColor(true, &slider_fill_color); - sprintf(str, GetString(STR_RAMSIZE_FMT), 8); - sprintf(str2, GetString(STR_RAMSIZE_FMT), max_ramsize); - ramsize_slider->SetLimitLabels(str, str2); - pane->AddChild(ramsize_slider); - - ignoresegv_checkbox = new BCheckBox(BRect(10, 60, right, 75), "ignoresegv", GetString(STR_IGNORESEGV_CTRL), new BMessage(MSG_IGNORESEGV)); - pane->AddChild(ignoresegv_checkbox); - ignoresegv_checkbox->SetValue(PrefsFindBool("ignoresegv") ? B_CONTROL_ON : B_CONTROL_OFF); - - idlewait_checkbox = new BCheckBox(BRect(10, 80, right, 95), "idlewait", GetString(STR_IDLEWAIT_CTRL), new BMessage(MSG_IDLEWAIT)); - pane->AddChild(idlewait_checkbox); - idlewait_checkbox->SetValue(PrefsFindBool("idlewait") ? B_CONTROL_ON : B_CONTROL_OFF); - - rom_control = new PathControl(false, BRect(10, 100, right, 115), "rom", GetString(STR_ROM_FILE_CTRL), PrefsFindString("rom"), NULL); - rom_control->SetDivider(117); - pane->AddChild(rom_control); - - return pane; -} - - -/* - * Message from controls/menus received - */ - -void PrefsWindow::MessageReceived(BMessage *msg) -{ - switch (msg->what) { - case MSG_OK: // "Start" button clicked - PrefsReplaceString("extfs", extfs_control->Text()); - const char *str = rom_control->Text(); - if (strlen(str)) - PrefsReplaceString("rom", str); - else - PrefsRemoveItem("rom"); - SavePrefs(); - send_quit_on_close = false; - PostMessage(B_QUIT_REQUESTED); - be_app->PostMessage(ok_message); - break; - - case MSG_CANCEL: // "Quit" button clicked - send_quit_on_close = false; - PostMessage(B_QUIT_REQUESTED); - be_app->PostMessage(B_QUIT_REQUESTED); - break; - - case B_ABOUT_REQUESTED: // "About" menu item selected - OpenAboutWindow(); - break; - - case MSG_ZAP_PRAM: // "Zap PRAM File" menu item selected - ZapPRAM(); - break; - - case MSG_VOLUME_INVOKED: { // Double-clicked on volume name, toggle read-only flag - int selected = volume_list->CurrentSelection(); - if (selected >= 0) { - const char *str = PrefsFindString("disk", selected); - BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected); - delete item; - char newstr[256]; - if (str[0] == '*') - strcpy(newstr, str+1); - else { - strcpy(newstr, "*"); - strcat(newstr, str); - } - PrefsReplaceString("disk", newstr, selected); - volume_list->AddItem(new BStringItem(newstr), selected); - volume_list->Select(selected); - } - break; - } - - case MSG_ADD_VOLUME: - add_volume_panel->Show(); - break; - - case MSG_CREATE_VOLUME: - create_volume_panel->Show(); - break; - - case MSG_ADD_VOLUME_PANEL: { - entry_ref ref; - if (msg->FindRef("refs", &ref) == B_NO_ERROR) { - BEntry entry(&ref, true); - BPath path; - entry.GetPath(&path); - if (entry.IsFile()) { - PrefsAddString("disk", path.Path()); - volume_list->AddItem(new BStringItem(path.Path())); - } else if (entry.IsDirectory()) { - BVolume volume; - if (path.Path()[0] == '/' && strchr(path.Path()+1, '/') == NULL && entry.GetVolume(&volume) == B_NO_ERROR) { - int32 i = 0; - dev_t d; - fs_info info; - while ((d = next_dev(&i)) >= 0) { - fs_stat_dev(d, &info); - if (volume.Device() == info.dev) { - PrefsAddString("disk", info.device_name); - volume_list->AddItem(new BStringItem(info.device_name)); - } - } - } - } - } - break; - } - - case MSG_CREATE_VOLUME_PANEL: { - entry_ref dir; - if (msg->FindRef("directory", &dir) == B_NO_ERROR) { - BEntry entry(&dir, true); - BPath path; - entry.GetPath(&path); - path.Append(msg->FindString("name")); - - create_volume_panel->Window()->Lock(); - BView *background = create_volume_panel->Window()->ChildAt(0); - NumberControl *v = (NumberControl *)background->FindView("hardfile_size"); - int size = v->Value(); - - char cmd[1024]; - sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", path.Path(), size); - int ret = system(cmd); - if (ret == 0) { - PrefsAddString("disk", path.Path()); - volume_list->AddItem(new BStringItem(path.Path())); - } else { - sprintf(cmd, GetString(STR_CREATE_VOLUME_WARN), strerror(ret)); - WarningAlert(cmd); - } - } - break; - } - - case MSG_REMOVE_VOLUME: { - int selected = volume_list->CurrentSelection(); - if (selected >= 0) { - PrefsRemoveItem("disk", selected); - BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected); - delete item; - volume_list->Select(selected); - } - break; - } - - case MSG_BOOT_ANY: - PrefsReplaceInt32("bootdriver", 0); - break; - - case MSG_BOOT_CDROM: - PrefsReplaceInt32("bootdriver", CDROMRefNum); - break; - - case MSG_NOCDROM: - PrefsReplaceBool("nocdrom", nocdrom_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_GFXACCEL: - PrefsReplaceBool("gfxaccel", gfxaccel_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_NOSOUND: - PrefsReplaceBool("nosound", nosound_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_WINDOW_MODE: { - BCheckBox *source = NULL; - msg->FindPointer("source", &source); - if (source == NULL) - break; - for (int i=0; ibox == source) { - if (p->box->Value() == B_CONTROL_ON) - PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") | p->mode); - else - PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") & ~(p->mode)); - break; - } - } - break; - } - - case MSG_SCREEN_MODE: { - BCheckBox *source = NULL; - msg->FindPointer("source", &source); - if (source == NULL) - break; - for (int i=0; ibox == source) { - if (p->box->Value() == B_CONTROL_ON) - PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | p->mode); - else - PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~(p->mode)); - break; - } - } - break; - } - - case MSG_REF_5HZ: - PrefsReplaceInt32("frameskip", 12); - break; - - case MSG_REF_7_5HZ: - PrefsReplaceInt32("frameskip", 8); - break; - - case MSG_REF_10HZ: - PrefsReplaceInt32("frameskip", 6); - break; - - case MSG_REF_15HZ: - PrefsReplaceInt32("frameskip", 4); - break; - - case MSG_REF_30HZ: - PrefsReplaceInt32("frameskip", 2); - break; - - case MSG_SER_A: { - BMenuItem *source = NULL; - msg->FindPointer("source", &source); - if (source) - PrefsReplaceString("seriala", source->Label()); - break; - } - - case MSG_SER_B: { - BMenuItem *source = NULL; - msg->FindPointer("source", &source); - if (source) - PrefsReplaceString("serialb", source->Label()); - break; - } - - case MSG_NONET: - PrefsReplaceBool("nonet", nonet_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_IGNORESEGV: - PrefsReplaceBool("ignoresegv", ignoresegv_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_IDLEWAIT: - PrefsReplaceBool("idlewait", idlewait_checkbox->Value() == B_CONTROL_ON); - break; - - case MSG_RAMSIZE: - PrefsReplaceInt32("ramsize", ramsize_slider->Value() * 1024 * 1024); - break; - - default: - BWindow::MessageReceived(msg); - } -} diff --git a/SheepShaver/src/BeOS/scsi_beos.cpp b/SheepShaver/src/BeOS/scsi_beos.cpp deleted file mode 120000 index c495dce0..00000000 --- a/SheepShaver/src/BeOS/scsi_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/scsi_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/BeOS/serial_beos.cpp b/SheepShaver/src/BeOS/serial_beos.cpp deleted file mode 120000 index 2231c6d0..00000000 --- a/SheepShaver/src/BeOS/serial_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/serial_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/BeOS/sys_beos.cpp b/SheepShaver/src/BeOS/sys_beos.cpp deleted file mode 120000 index 4e238dac..00000000 --- a/SheepShaver/src/BeOS/sys_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/sys_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/BeOS/sysdeps.h b/SheepShaver/src/BeOS/sysdeps.h deleted file mode 100644 index 6a7861a5..00000000 --- a/SheepShaver/src/BeOS/sysdeps.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * sysdeps.h - System dependent definitions for BeOS - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -// Do we have std namespace? -#ifdef __POWERPC__ -#define NO_STD_NAMESPACE -#endif - -#include -#include -#include - -#include "user_strings_beos.h" - -// Are we using a PPC emulator or the real thing? -#ifdef __POWERPC__ -#define EMULATED_PPC 0 -#define WORDS_BIGENDIAN 1 -#define SYSTEM_CLOBBERS_R2 1 -#else -#define EMULATED_PPC 1 -#undef WORDS_BIGENDIAN -#endif - -// High precision timing -#define PRECISE_TIMING 1 -#define PRECISE_TIMING_BEOS 1 - -#define POWERPC_ROM 1 - -// Time data type for Time Manager emulation -typedef bigtime_t tm_time_t; - -// 64 bit file offsets -typedef off_t loff_t; - -// Data types -typedef uint32 uintptr; -typedef int32 intptr; - -// Timing functions -extern void Delay_usec(uint32 usec); - -// Macro for calling MacOS routines -#define CallMacOS(type, proc) (*(type)proc)() -#define CallMacOS1(type, proc, arg1) (*(type)proc)(arg1) -#define CallMacOS2(type, proc, arg1, arg2) (*(type)proc)(arg1, arg2) -#define CallMacOS3(type, proc, arg1, arg2, arg3) (*(type)proc)(arg1, arg2, arg3) -#define CallMacOS4(type, proc, arg1, arg2, arg3, arg4) (*(type)proc)(arg1, arg2, arg3, arg4) -#define CallMacOS5(type, proc, arg1, arg2, arg3, arg4, arg5) (*(type)proc)(arg1, arg2, arg3, arg4, arg5) -#define CallMacOS6(type, proc, arg1, arg2, arg3, arg4, arg5, arg6) (*(type)proc)(arg1, arg2, arg3, arg4, arg5, arg6) -#define CallMacOS7(type, proc, arg1, arg2, arg3, arg4, arg5, arg6, arg7) (*(type)proc)(arg1, arg2, arg3, arg4, arg5, arg6, arg7) - -#endif diff --git a/SheepShaver/src/BeOS/timer_beos.cpp b/SheepShaver/src/BeOS/timer_beos.cpp deleted file mode 120000 index 0d9e8014..00000000 --- a/SheepShaver/src/BeOS/timer_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/timer_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/BeOS/user_strings_beos.cpp b/SheepShaver/src/BeOS/user_strings_beos.cpp deleted file mode 100644 index 0f7b1367..00000000 --- a/SheepShaver/src/BeOS/user_strings_beos.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * user_strings_beos.cpp - Localizable strings, BeOS specific strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "user_strings.h" - - -// Platform-specific string definitions -user_string_def platform_strings[] = { - // Common strings that have a platform-specific variant - {STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under BeOS. Basilisk II will try to unmount it."}, - {STR_EXTFS_CTRL, "BeOS Root"}, - {STR_EXTFS_NAME, "BeOS Directory Tree"}, - {STR_EXTFS_VOLUME_NAME, "BeOS"}, - - // Purely platform-specific strings - {STR_NO_SHEEP_DRIVER_ERR, "Cannot open /dev/sheep: %s (%08x). SheepShaver is not properly installed."}, - {STR_NO_RAM_AREA_ERR, "Not enough memory to create RAM area: %s (%08x)."}, - {STR_NO_ROM_AREA_ERR, "Not enough memory to create ROM area."}, - {STR_NO_SHEEP_MEM_AREA_ERR, "Not enough memory to create SheepShaver area."}, - {STR_SHEEP_UP_ERR, "Cannot allocate Low Memory Globals: %s (%08x)."}, - {STR_NO_NET_ADDON_WARN, "The SheepShaver net server add-on cannot be found. Ethernet will not be available."}, - {STR_NET_CONFIG_MODIFY_WARN, "To enable Ethernet networking for SheepShaver, your network configuration has to be modified and the network restarted. Do you want this to be done now (selecting \"Cancel\" will disable Ethernet under SheepShaver)?."}, - {STR_NET_ADDON_INIT_FAILED, "SheepShaver net server add-on found\nbut there seems to be no network hardware.\nPlease check your network preferences."}, - {STR_NET_ADDON_CLONE_FAILED, "Cloning of the network transfer area failed."}, - {STR_NO_SHEEP_MEM_AREA_ERR, "Cannot create SheepShaver Globals area: %s (%08x)."}, - {STR_NO_DR_CACHE_AREA_ERR, "Cannot create DR Cache area: %s (%08x)."}, - {STR_NO_DR_EMULATOR_AREA_ERR, "Cannot create DR Emulator area: %s (%08x)."}, - - {-1, NULL} // End marker -}; - - -/* - * Fetch pointer to string, given the string number - */ - -const char *GetString(int num) -{ - // First search for platform-specific string - int i = 0; - while (platform_strings[i].num >= 0) { - if (platform_strings[i].num == num) - return platform_strings[i].str; - i++; - } - - // Not found, search for common string - i = 0; - while (common_strings[i].num >= 0) { - if (common_strings[i].num == num) - return common_strings[i].str; - i++; - } - return NULL; -} diff --git a/SheepShaver/src/BeOS/user_strings_beos.h b/SheepShaver/src/BeOS/user_strings_beos.h deleted file mode 100644 index b8248110..00000000 --- a/SheepShaver/src/BeOS/user_strings_beos.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * user_strings_beos.h - BeOS-specific localizable strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_BEOS_H -#define USER_STRINGS_BEOS_H - -enum { - STR_NO_SHEEP_DRIVER_ERR = 10000, - STR_NO_ROM_AREA_ERR, - STR_SHEEP_UP_ERR, - STR_NO_NET_ADDON_WARN, - STR_NET_CONFIG_MODIFY_WARN, - STR_NET_ADDON_INIT_FAILED, - STR_NET_ADDON_CLONE_FAILED, - STR_NO_SHEEP_MEM_AREA_ERR, - STR_NO_DR_CACHE_AREA_ERR, - STR_NO_DR_EMULATOR_AREA_ERR -}; - -#endif diff --git a/SheepShaver/src/BeOS/video_beos.cpp b/SheepShaver/src/BeOS/video_beos.cpp deleted file mode 100644 index aa4f2496..00000000 --- a/SheepShaver/src/BeOS/video_beos.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* - * video_beos.cpp - Video/graphics emulation, BeOS specific things - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "video.h" -#include "video_defs.h" -#include "main.h" -#include "adb.h" -#include "prefs.h" -#include "user_strings.h" -#include "about_window.h" -#include "version.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static sem_id video_lock = -1; // Protection during mode changes -static sem_id mac_os_lock = -1; // This is used to stop the MacOS thread when the SheepShaver workspace is switched out - -// Prototypes -static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter); - -// From sys_beos.cpp -extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg); -extern void SysMountVolume(const char *name); - - -#include "video_window.h" -#include "video_screen.h" - - -/* - * Display manager thread (for opening and closing windows and screens; - * this is not safe under R4 when running on the MacOS stack in kernel - * space) - */ - -// Message constants -const uint32 MSG_OPEN_WINDOW = 'owin'; -const uint32 MSG_CLOSE_WINDOW = 'cwin'; -const uint32 MSG_OPEN_SCREEN = 'oscr'; -const uint32 MSG_CLOSE_SCREEN = 'cscr'; -const uint32 MSG_QUIT_DISPLAY_MANAGER = 'quit'; - -static thread_id dm_thread = -1; -static sem_id dm_done_sem = -1; - -static status_t display_manager(void *arg) -{ - for (;;) { - - // Receive message - thread_id sender; - uint32 code = receive_data(&sender, NULL, 0); - D(bug("Display manager received %08lx\n", code)); - switch (code) { - case MSG_QUIT_DISPLAY_MANAGER: - return 0; - - case MSG_OPEN_WINDOW: - D(bug("Opening window\n")); - the_window = new MacWindow(BRect(0, 0, VModes[cur_mode].viXsize-1, VModes[cur_mode].viYsize-1)); - D(bug("Opened\n")); - break; - - case MSG_CLOSE_WINDOW: - if (the_window != NULL) { - D(bug("Posting quit to window\n")); - the_window->PostMessage(B_QUIT_REQUESTED); - D(bug("Posted, waiting\n")); - while (the_window) - snooze(200000); - D(bug("Window closed\n")); - } - break; - - case MSG_OPEN_SCREEN: { - D(bug("Opening screen\n")); - long scr_mode = 0; - switch (VModes[cur_mode].viAppleMode) { - case APPLE_8_BIT: - switch (VModes[cur_mode].viAppleID) { - case APPLE_640x480: - scr_mode = B_8_BIT_640x480; - break; - case APPLE_800x600: - scr_mode = B_8_BIT_800x600; - break; - case APPLE_1024x768: - scr_mode = B_8_BIT_1024x768; - break; - case APPLE_1152x900: - scr_mode = B_8_BIT_1152x900; - break; - case APPLE_1280x1024: - scr_mode = B_8_BIT_1280x1024; - break; - case APPLE_1600x1200: - scr_mode = B_8_BIT_1600x1200; - break; - } - break; - case APPLE_16_BIT: - switch (VModes[cur_mode].viAppleID) { - case APPLE_640x480: - scr_mode = B_15_BIT_640x480; - break; - case APPLE_800x600: - scr_mode = B_15_BIT_800x600; - break; - case APPLE_1024x768: - scr_mode = B_15_BIT_1024x768; - break; - case APPLE_1152x900: - scr_mode = B_15_BIT_1152x900; - break; - case APPLE_1280x1024: - scr_mode = B_15_BIT_1280x1024; - break; - case APPLE_1600x1200: - scr_mode = B_15_BIT_1600x1200; - break; - } - break; - case APPLE_32_BIT: - switch (VModes[cur_mode].viAppleID) { - case APPLE_640x480: - scr_mode = B_32_BIT_640x480; - break; - case APPLE_800x600: - scr_mode = B_32_BIT_800x600; - break; - case APPLE_1024x768: - scr_mode = B_32_BIT_1024x768; - break; - case APPLE_1152x900: - scr_mode = B_32_BIT_1152x900; - break; - case APPLE_1280x1024: - scr_mode = B_32_BIT_1280x1024; - break; - case APPLE_1600x1200: - scr_mode = B_32_BIT_1600x1200; - break; - } - break; - } - the_screen = new MacScreen(GetString(STR_WINDOW_TITLE), scr_mode); - D(bug("Opened, error %08lx\n", screen_error)); - if (screen_error != B_NO_ERROR) { - D(bug("Error, posting quit to screen\n")); - the_screen->PostMessage(B_QUIT_REQUESTED); - D(bug("Posted, waiting\n")); - while (the_screen) - snooze(200000); - D(bug("Screen closed\n")); - break; - } - - // Wait for video mem access - D(bug("Showing screen\n")); - the_screen->Show(); - D(bug("Shown, waiting for frame buffer access\n")); - while (!drawing_enable) - snooze(200000); - D(bug("Access granted\n")); - break; - } - - case MSG_CLOSE_SCREEN: - if (the_screen != NULL) { - D(bug("Posting quit to screen\n")); - the_screen->PostMessage(B_QUIT_REQUESTED); - D(bug("Posted, waiting\n")); - while (the_screen) - snooze(200000); - D(bug("Screen closed\n")); - } - break; - } - - // Acknowledge - release_sem(dm_done_sem); - } -} - - -/* - * Open display (window or screen) - */ - -static void open_display(void) -{ - D(bug("entering open_display()\n")); - display_type = VModes[cur_mode].viType; - if (display_type == DIS_SCREEN) { - while (send_data(dm_thread, MSG_OPEN_SCREEN, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; - } else if (display_type == DIS_WINDOW) { - while (send_data(dm_thread, MSG_OPEN_WINDOW, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; - } - D(bug("exiting open_display()\n")); -} - - -/* - * Close display - */ - -static void close_display(void) -{ - D(bug("entering close_display()\n")); - if (display_type == DIS_SCREEN) { - while (send_data(dm_thread, MSG_CLOSE_SCREEN, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; - } else if (display_type == DIS_WINDOW) { - while (send_data(dm_thread, MSG_CLOSE_WINDOW, NULL, 0) == B_INTERRUPTED) ; - while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; - } - D(bug("exiting close_display()\n")); -} - - -/* - * Initialization - */ - -static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type) -{ - if (allow & test) { - p->viType = type; - switch (apple_id) { - case APPLE_W_640x480: - case APPLE_640x480: - p->viXsize = 640; - p->viYsize = 480; - break; - case APPLE_W_800x600: - case APPLE_800x600: - p->viXsize = 800; - p->viYsize = 600; - break; - case APPLE_1024x768: - p->viXsize = 1024; - p->viYsize = 768; - break; - case APPLE_1152x900: - p->viXsize = 1152; - p->viYsize = 900; - break; - case APPLE_1280x1024: - p->viXsize = 1280; - p->viYsize = 1024; - break; - case APPLE_1600x1200: - p->viXsize = 1600; - p->viYsize = 1200; - break; - } - switch (apple_mode) { - case APPLE_8_BIT: - p->viRowBytes = p->viXsize; - break; - case APPLE_16_BIT: - p->viRowBytes = p->viXsize * 2; - break; - case APPLE_32_BIT: - p->viRowBytes = p->viXsize * 4; - break; - } - p->viAppleMode = apple_mode; - p->viAppleID = apple_id; - p++; - } -} - -bool VideoInit(void) -{ - // Init variables, create semaphores - private_data = NULL; - cur_mode = 0; // Window 640x480 - video_lock = create_sem(1, "Video Lock"); - mac_os_lock = create_sem(0, "MacOS Frame Buffer Lock"); - dm_done_sem = create_sem(0, "Display Manager Done"); - - // Construct video mode table - VideoInfo *p = VModes; - uint32 window_modes = PrefsFindInt32("windowmodes"); - uint32 screen_modes = PrefsFindInt32("screenmodes"); - if (window_modes == 0 && screen_modes == 0) - window_modes |= B_8_BIT_640x480 | B_8_BIT_800x600; // Allow at least 640x480 and 800x600 window modes - add_mode(p, window_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_W_640x480, DIS_WINDOW); - add_mode(p, window_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_W_800x600, DIS_WINDOW); - add_mode(p, window_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_W_640x480, DIS_WINDOW); - add_mode(p, window_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_W_800x600, DIS_WINDOW); - add_mode(p, window_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_W_640x480, DIS_WINDOW); - add_mode(p, window_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_W_800x600, DIS_WINDOW); - add_mode(p, screen_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_640x480, DIS_SCREEN); - add_mode(p, screen_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_800x600, DIS_SCREEN); - add_mode(p, screen_modes, B_8_BIT_1024x768, APPLE_8_BIT, APPLE_1024x768, DIS_SCREEN); - add_mode(p, screen_modes, B_8_BIT_1152x900, APPLE_8_BIT, APPLE_1152x900, DIS_SCREEN); - add_mode(p, screen_modes, B_8_BIT_1280x1024, APPLE_8_BIT, APPLE_1280x1024, DIS_SCREEN); - add_mode(p, screen_modes, B_8_BIT_1600x1200, APPLE_8_BIT, APPLE_1600x1200, DIS_SCREEN); - add_mode(p, screen_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_640x480, DIS_SCREEN); - add_mode(p, screen_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_800x600, DIS_SCREEN); - add_mode(p, screen_modes, B_15_BIT_1024x768, APPLE_16_BIT, APPLE_1024x768, DIS_SCREEN); - add_mode(p, screen_modes, B_15_BIT_1152x900, APPLE_16_BIT, APPLE_1152x900, DIS_SCREEN); - add_mode(p, screen_modes, B_15_BIT_1280x1024, APPLE_16_BIT, APPLE_1280x1024, DIS_SCREEN); - add_mode(p, screen_modes, B_15_BIT_1600x1200, APPLE_16_BIT, APPLE_1600x1200, DIS_SCREEN); - add_mode(p, screen_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_640x480, DIS_SCREEN); - add_mode(p, screen_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_800x600, DIS_SCREEN); - add_mode(p, screen_modes, B_32_BIT_1024x768, APPLE_32_BIT, APPLE_1024x768, DIS_SCREEN); - add_mode(p, screen_modes, B_32_BIT_1152x900, APPLE_32_BIT, APPLE_1152x900, DIS_SCREEN); - add_mode(p, screen_modes, B_32_BIT_1280x1024, APPLE_32_BIT, APPLE_1280x1024, DIS_SCREEN); - add_mode(p, screen_modes, B_32_BIT_1600x1200, APPLE_32_BIT, APPLE_1600x1200, DIS_SCREEN); - p->viType = DIS_INVALID; // End marker - p->viRowBytes = 0; - p->viXsize = p->viYsize = 0; - p->viAppleMode = 0; - p->viAppleID = 0; - - // Start display manager thread - dm_thread = spawn_thread(display_manager, "Display Manager", B_NORMAL_PRIORITY, NULL); - resume_thread(dm_thread); - - // Open window/screen - open_display(); - if (display_type == DIS_SCREEN && the_screen == NULL) { - char str[256]; - sprintf(str, GetString(STR_FULL_SCREEN_ERR), strerror(screen_error), screen_error); - ErrorAlert(str); - return false; - } - return true; -} - - -/* - * Deinitialization - */ - -void VideoExit(void) -{ - if (dm_thread >= 0) { - - // Close display - acquire_sem(video_lock); - close_display(); - if (private_data != NULL) { - delete private_data->gammaTable; - delete private_data; - } - - // Stop display manager - status_t l; - send_data(dm_thread, MSG_QUIT_DISPLAY_MANAGER, NULL, 0); - while (wait_for_thread(dm_thread, &l) == B_INTERRUPTED) ; - } - - // Delete semaphores - delete_sem(video_lock); - delete_sem(mac_os_lock); - delete_sem(dm_done_sem); -} - - -/* - * Close screen in full-screen mode - */ - -void VideoQuitFullScreen(void) -{ - D(bug("VideoQuitFullScreen()\n")); - if (display_type == DIS_SCREEN) { - acquire_sem(video_lock); - close_display(); - release_sem(video_lock); - } -} - - -/* - * Execute video VBL routine - */ - -void VideoVBL(void) -{ - release_sem(mac_os_lock); - if (private_data != NULL && private_data->interruptsEnabled) - VSLDoInterruptService(private_data->vslServiceID); - while (acquire_sem(mac_os_lock) == B_INTERRUPTED) ; -} - - -/* - * Filter function for receiving mouse and keyboard events - */ - -#define MENU_IS_POWER 0 - -// Be -> Mac raw keycode translation table -static const uint8 keycode2mac[0x80] = { - 0xff, 0x35, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, // inv Esc F1 F2 F3 F4 F5 F6 - 0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b, // F7 F8 F9 F10 F11 F12 F13 F14 - 0x71, 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, // F15 ` 1 2 3 4 5 6 - 0x1a, 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x33, 0x72, // 7 8 9 0 - = BSP INS - 0x73, 0x74, 0x47, 0x4b, 0x43, 0x4e, 0x30, 0x0c, // HOM PUP NUM / * - TAB Q - 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, 0x1f, // W E R T Y U I O - 0x23, 0x21, 0x1e, 0x2a, 0x75, 0x77, 0x79, 0x59, // P [ ] \ DEL END PDN 7 - 0x5b, 0x5c, 0x45, 0x39, 0x00, 0x01, 0x02, 0x03, // 8 9 + CAP A S D F - 0x05, 0x04, 0x26, 0x28, 0x25, 0x29, 0x27, 0x24, // G H J K L ; ' RET - 0x56, 0x57, 0x58, 0x38, 0x06, 0x07, 0x08, 0x09, // 4 5 6 SHL Z X C V - 0x0b, 0x2d, 0x2e, 0x2b, 0x2f, 0x2c, 0x38, 0x3e, // B N M , . / SHR CUP - 0x53, 0x54, 0x55, 0x4c, 0x36, 0x37, 0x31, 0x37, // 1 2 3 ENT CTL ALT SPC ALT - 0x36, 0x3b, 0x3d, 0x3c, 0x52, 0x41, 0x3a, 0x3a, // CTR CLF CDN CRT 0 . CMD CMD -#if MENU_IS_POWER - 0x7f, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv -#else - 0x32, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv -#endif - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv -}; - -static const uint8 modifier2mac[0x20] = { -#if MENU_IS_POWER - 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x7f, // SHF CMD inv CAP F14 NUM OPT MNU -#else - 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x32, // SHF CMD CTR CAP F14 NUM OPT MNU -#endif - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv -}; - -static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter) -{ -// msg->PrintToStream(); - switch (msg->what) { - case B_KEY_DOWN: - case B_KEY_UP: { - uint32 be_code = msg->FindInt32("key") & 0xff; - uint32 mac_code = keycode2mac[be_code]; - - // Intercept Ctrl-F1 (mount floppy disk shortcut) - uint32 mods = msg->FindInt32("modifiers"); - if (be_code == 0x02 && (mods & B_CONTROL_KEY)) - SysMountVolume("/dev/disk/floppy/raw"); - - if (mac_code == 0xff) - return B_DISPATCH_MESSAGE; - if (msg->what == B_KEY_DOWN) - ADBKeyDown(mac_code); - else - ADBKeyUp(mac_code); - return B_SKIP_MESSAGE; - } - - case B_MODIFIERS_CHANGED: { - uint32 mods = msg->FindInt32("modifiers"); - uint32 old_mods = msg->FindInt32("be:old_modifiers"); - uint32 changed = mods ^ old_mods; - uint32 mask = 1; - for (int i=0; i<32; i++, mask<<=1) - if (changed & mask) { - uint32 mac_code = modifier2mac[i]; - if (mac_code == 0xff) - continue; - if (mods & mask) - ADBKeyDown(mac_code); - else - ADBKeyUp(mac_code); - } - return B_SKIP_MESSAGE; - } - - case B_MOUSE_MOVED: { - BPoint point; - msg->FindPoint("where", &point); - ADBMouseMoved(int(point.x), int(point.y)); - return B_DISPATCH_MESSAGE; // Otherwise BitmapView::MouseMoved() wouldn't be called - } - - case B_MOUSE_DOWN: { - uint32 buttons = msg->FindInt32("buttons"); - if (buttons & B_PRIMARY_MOUSE_BUTTON) - ADBMouseDown(0); - if (buttons & B_SECONDARY_MOUSE_BUTTON) - ADBMouseDown(1); - if (buttons & B_TERTIARY_MOUSE_BUTTON) - ADBMouseDown(2); - return B_SKIP_MESSAGE; - } - - case B_MOUSE_UP: // B_MOUSE_UP means "all buttons released" - ADBMouseUp(0); - ADBMouseUp(1); - ADBMouseUp(2); - return B_SKIP_MESSAGE; - - default: - return B_DISPATCH_MESSAGE; - } -} - - -/* - * Install graphics acceleration - */ - -// Rectangle blitting -static void accl_bitblt(accl_params *p) -{ - D(bug("accl_bitblt\n")); - - // Get blitting parameters - int16 src_X = p->src_rect[1] - p->src_bounds[1]; - int16 src_Y = p->src_rect[0] - p->src_bounds[0]; - int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; - int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; - int16 width = p->dest_rect[3] - p->dest_rect[1] - 1; - int16 height = p->dest_rect[2] - p->dest_rect[0] - 1; - D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); - D(bug(" width %d, height %d\n", width, height)); - - // And perform the blit - bitblt_hook(src_X, src_Y, dest_X, dest_Y, width, height); -} - -static bool accl_bitblt_hook(accl_params *p) -{ - D(bug("accl_draw_hook %p\n", p)); - - // Check if we can accelerate this bitblt - if (p->src_base_addr == screen_base && p->dest_base_addr == screen_base && - display_type == DIS_SCREEN && bitblt_hook != NULL && - ((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 && - ((uint32 *)p)[0x130 >> 2] == 0 && - p->transfer_mode == 0 && - p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) { - - // Yes, set function pointer - p->draw_proc = (uint32)accl_bitblt; - return true; - } - return false; -} - -// Rectangle filling/inversion -static void accl_fillrect8(accl_params *p) -{ - D(bug("accl_fillrect8\n")); - - // Get filling parameters - int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; - int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; - int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; - int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; - uint8 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen; - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); - - // And perform the fill - fillrect8_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color); -} - -static void accl_fillrect32(accl_params *p) -{ - D(bug("accl_fillrect32\n")); - - // Get filling parameters - int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; - int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; - int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; - int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; - uint32 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen; - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); - - // And perform the fill - fillrect32_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color); -} - -static void accl_invrect(accl_params *p) -{ - D(bug("accl_invrect\n")); - - // Get inversion parameters - int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; - int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; - int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; - int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); - - //!!?? pen_mode == 14 - - // And perform the inversion - invrect_hook(dest_X, dest_Y, dest_X_max, dest_Y_max); -} - -static bool accl_fillrect_hook(accl_params *p) -{ - D(bug("accl_fillrect_hook %p\n", p)); - - // Check if we can accelerate this fillrect - if (p->dest_base_addr == screen_base && ((uint32 *)p)[0x284 >> 2] != 0 && display_type == DIS_SCREEN) { - if (p->transfer_mode == 8) { - // Fill - if (p->dest_pixel_size == 8 && fillrect8_hook != NULL) { - p->draw_proc = (uint32)accl_fillrect8; - return true; - } else if (p->dest_pixel_size == 32 && fillrect32_hook != NULL) { - p->draw_proc = (uint32)accl_fillrect32; - return true; - } - } else if (p->transfer_mode == 10 && invrect_hook != NULL) { - // Invert - p->draw_proc = (uint32)accl_invrect; - return true; - } - } - return false; -} - -// Dummy for testing -/* -static void do_nothing(accl_params *p) {} -static bool accl_foobar_hook(accl_params *p) -{ - printf("accl_foobar_hook %p\n", p); - printf(" src_base_addr %p, dest_base_addr %p\n", p->src_base_addr, p->dest_base_addr); - printf(" src_row_bytes %d, dest_row_bytes %d\n", p->src_row_bytes, p->dest_row_bytes); - printf(" src_pixel_size %d, dest_pixel_size %d\n", p->src_pixel_size, p->dest_pixel_size); - printf(" src_bounds (%d,%d,%d,%d), dest_bounds (%d,%d,%d,%d)\n", p->src_bounds[0], p->src_bounds[1], p->src_bounds[2], p->src_bounds[3], p->dest_bounds[0], p->dest_bounds[1], p->dest_bounds[2], p->dest_bounds[3]); - printf(" src_rect (%d,%d,%d,%d), dest_rect (%d,%d,%d,%d)\n", p->src_rect[0], p->src_rect[1], p->src_rect[2], p->src_rect[3], p->dest_rect[0], p->dest_rect[1], p->dest_rect[2], p->dest_rect[3]); - printf(" transfer mode %d\n", p->transfer_mode); - printf(" pen mode %d\n", p->pen_mode); - printf(" fore_pen %08x, back_pen %08x\n", p->fore_pen, p->back_pen); - printf(" val1 %08x, val2 %08x\n", ((uint32 *)p)[0x18 >> 2], ((uint32 *)p)[0x128 >> 2]); - printf(" val3 %08x\n", ((uint32 *)p)[0x130 >> 2]); - printf(" val4 %08x\n", ((uint32 *)p)[0x15c >> 2]); - printf(" val5 %08x\n", ((uint32 *)p)[0x160 >> 2]); - printf(" val6 %08x\n", ((uint32 *)p)[0x1b4 >> 2]); - printf(" val7 %08x\n", ((uint32 *)p)[0x284 >> 2]); - p->draw_proc = (uint32)do_nothing; - return true; -} -static struct accl_hook_info foobar_hook_info = {(uint32)accl_foobar_hook, (uint32)accl_sync_hook, 6}; -*/ - -// Wait for graphics operation to finish -static bool accl_sync_hook(void *arg) -{ - D(bug("accl_sync_hook %p\n", arg)); - if (sync_hook != NULL) - sync_hook(); - return true; -} - -static struct accl_hook_info bitblt_hook_info = {(uint32)accl_bitblt_hook, (uint32)accl_sync_hook, ACCL_BITBLT}; -static struct accl_hook_info fillrect_hook_info = {(uint32)accl_fillrect_hook, (uint32)accl_sync_hook, ACCL_FILLRECT}; - -void VideoInstallAccel(void) -{ - // Install acceleration hooks - if (PrefsFindBool("gfxaccel")) { - D(bug("Video: Installing acceleration hooks\n")); - NQDMisc(6, (uintptr)&bitblt_hook_info); - NQDMisc(6, (uintptr)&fillrect_hook_info); - } -} - - -/* - * Change video mode - */ - -int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr) -{ - /* return if no mode change */ - if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) && - (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr; - - /* first find video mode in table */ - for (int i=0; VModes[i].viType != DIS_INVALID; i++) { - if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) && - (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) { - csSave->saveMode = ReadMacInt16(ParamPtr + csMode); - csSave->saveData = ReadMacInt32(ParamPtr + csData); - csSave->savePage = ReadMacInt16(ParamPtr + csPage); - - while (acquire_sem(video_lock) == B_INTERRUPTED) ; - DisableInterrupt(); - - /* close old display */ - close_display(); - - /* open new display */ - cur_mode = i; - open_display(); - - /* opening the screen failed? Then bail out */ - if (display_type == DIS_SCREEN && the_screen == NULL) { - release_sem(video_lock); - ErrorAlert(GetString(STR_FULL_SCREEN_ERR)); - QuitEmulator(); - } - - WriteMacInt32(ParamPtr + csBaseAddr, screen_base); - csSave->saveBaseAddr=screen_base; - csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ - csSave->saveMode=VModes[cur_mode].viAppleMode; - - EnableInterrupt(); - release_sem(video_lock); - return noErr; - } - } - return paramErr; -} - - -/* - * Set color palette - */ - -void video_set_palette(void) -{ - if (display_type == DIS_SCREEN && the_screen != NULL) - the_screen->palette_changed = true; - else { // remap colors to BeOS-Palette - BScreen screen; - for (int i=0;i<256;i++) - remap_mac_be[i]=screen.IndexForColor(mac_pal[i].red,mac_pal[i].green,mac_pal[i].blue); - } -} - - -/* - * Can we set the MacOS cursor image into the window? - */ - -bool video_can_change_cursor(void) -{ - return (display_type != DIS_SCREEN); -} - - -/* - * Set cursor image for window - */ - -void video_set_cursor(void) -{ - the_window->cursor_changed = true; // Inform window (don't set cursor directly because this may run at interrupt (i.e. signal handler) time) -} - - -/* - * Record dirty area from NQD - */ - -void video_set_dirty_area(int x, int y, int w, int h) -{ -} diff --git a/SheepShaver/src/BeOS/video_screen.h b/SheepShaver/src/BeOS/video_screen.h deleted file mode 100644 index a3b5f268..00000000 --- a/SheepShaver/src/BeOS/video_screen.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * video_screen.h - Full screen video modes - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -static bool drawing_enable = false; // This flag indicated if the access to the screen is allowed -static int page_num; // Index of the currently displayed buffer - - -// Blitter functions -typedef void (*bitblt_ptr)(int32, int32, int32, int32, int32, int32); -static bitblt_ptr bitblt_hook; -typedef void (*fillrect8_ptr)(int32, int32, int32, int32, uint8); -static fillrect8_ptr fillrect8_hook; -typedef void (*fillrect32_ptr)(int32, int32, int32, int32, uint32); -static fillrect32_ptr fillrect32_hook; -typedef void (*invrect_ptr)(int32, int32, int32, int32); -static invrect_ptr invrect_hook; -typedef void (*sync_ptr)(void); -static sync_ptr sync_hook; - - -class MacScreen : public BWindowScreen { -public: - MacScreen(const char *name, uint32 space); - virtual ~MacScreen(); - virtual void Quit(void); - virtual void ScreenConnected(bool active); - - bool palette_changed; - -private: - static status_t tick_func(void *arg); - - BView *view; // Main view for GetMouse() - - uint8 *frame_backup; // Frame buffer backup when switching from/to different workspace - bool quitting; // Flag for ScreenConnected: We are quitting, don't pause emulator thread - bool first; // Flag for ScreenConnected: This is the first time we become active - - thread_id tick_thread; - bool tick_thread_active; -}; - - -// Pointer to our screen -static MacScreen *the_screen = NULL; - -// Error code from BWindowScreen constructor -static status_t screen_error; - -// to enable debugger mode. -#define SCREEN_DEBUG false - - -/* - * Screen constructor - */ - -MacScreen::MacScreen(const char *name, uint32 space) : BWindowScreen(name, space, &screen_error, SCREEN_DEBUG), tick_thread(-1) -{ - D(bug("Screen constructor\n")); - - // Set all variables - frame_backup = NULL; - palette_changed = false; - quitting = false; - first = true; - drawing_enable = false; - ADBSetRelMouseMode(true); - - // Create view to poll the mouse - view = new BView (BRect(0,0,VModes[cur_mode].viXsize-1,VModes[cur_mode].viYsize-1),NULL,B_FOLLOW_NONE,0); - AddChild(view); - - // Start 60Hz interrupt - tick_thread_active = true; - tick_thread = spawn_thread(tick_func, "Polling sucks...", B_DISPLAY_PRIORITY, this); - RegisterThread(tick_thread); - resume_thread(tick_thread); - - // Add filter for keyboard and mouse events - BMessageFilter *filter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, filter_func); - AddCommonFilter(filter); - D(bug("Screen constructor done\n")); -} - - -/* - * Screen destructor - */ - -MacScreen::~MacScreen() -{ - D(bug("Screen destructor, quitting tick thread\n")); - - // Stop 60Hz interrupt - if (tick_thread > 0) { - status_t l; - tick_thread_active = false; - while (wait_for_thread(tick_thread, &l) == B_INTERRUPTED) ; - } - D(bug("tick thread quit\n")); - - // Tell the emulator that we're done - the_screen = NULL; - D(bug("Screen destructor done\n")); -} - - -/* - * Screen closed - */ - -void MacScreen::Quit(void) -{ - // Tell ScreenConnected() that we are quitting - quitting = true; - D(bug("MacScreen::Quit(), disconnecting\n")); - Disconnect(); - D(bug("disconnected\n")); - BWindowScreen::Quit(); -} - - -/* - * Screen connected/disconnected - */ - -void MacScreen::ScreenConnected(bool active) -{ - D(bug("ScreenConnected(%d)\n", active)); - graphics_card_info *info = CardInfo(); - D(bug(" card_info %p\n", info)); - - if (active) { - - // Read graphics parameters - D(bug(" active\n")); - screen_base = (uint32)info->frame_buffer; - D(bug(" screen_base %p\n", screen_base)); - VModes[cur_mode].viRowBytes = info->bytes_per_row; - D(bug(" xmod %d\n", info->bytes_per_row)); - - // Get acceleration functions - if (PrefsFindBool("gfxaccel")) { - bitblt_hook = (bitblt_ptr)CardHookAt(7); - D(bug(" bitblt_hook %p\n", bitblt_hook)); - fillrect8_hook = (fillrect8_ptr)CardHookAt(5); - D(bug(" fillrect8_hook %p\n", fillrect8_hook)); - fillrect32_hook = (fillrect32_ptr)CardHookAt(6); - D(bug(" fillrect32_hook %p\n", fillrect32_hook)); - invrect_hook = (invrect_ptr)CardHookAt(11); - D(bug(" invrect_hook %p\n", invrect_hook)); - sync_hook = (sync_ptr)CardHookAt(10); - D(bug(" sync_hook %p\n", sync_hook)); - } else { - bitblt_hook = NULL; - fillrect8_hook = NULL; - fillrect32_hook = NULL; - invrect_hook = NULL; - sync_hook = NULL; - } - - // The first time we got the screen, we need to init the Window - if (first) { - D(bug(" first time\n")); - first = false; - page_num = 0; // current display : page 0 - } else { // we get our screen back - D(bug(" not first time\n")); - // copy from backup bitmap to framebuffer - memcpy((void *)screen_base, frame_backup, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - // delete backup bitmap - delete[] frame_backup; - frame_backup = NULL; - // restore palette - if (info->bits_per_pixel == 8) - SetColorList(mac_pal); - // restart emul thread - release_sem(mac_os_lock); - } - - // allow the drawing in the frame buffer - D(bug(" enabling frame buffer access\n")); - drawing_enable = true; - video_activated = true; - - } else { - - drawing_enable = false; // stop drawing. - video_activated = false; - if (!quitting) { - // stop emul thread - acquire_sem(mac_os_lock); - // create bitmap and store frame buffer into - frame_backup = new uint8[VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize]; - memcpy(frame_backup, (void *)screen_base, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - } - } - D(bug("ScreenConnected() done\n")); -} - - -/* - * 60Hz interrupt routine - */ - -status_t MacScreen::tick_func(void *arg) -{ - MacScreen *obj = (MacScreen *)arg; - while (obj->tick_thread_active) { - - // Wait - snooze(16667); - - // Workspace activated? Then poll the mouse and change the palette if needed - if (video_activated) { - BPoint pt; - uint32 button = 0; - if (obj->LockWithTimeout(200000) == B_OK) { - if (obj->palette_changed) { - obj->palette_changed = false; - obj->SetColorList(mac_pal); - } - obj->view->GetMouse(&pt, &button); - obj->Unlock(); - set_mouse_position(320, 240); - ADBMouseMoved(int(pt.x) - 320, int(pt.y) - 240); - if (button & B_PRIMARY_MOUSE_BUTTON) - ADBMouseDown(0); - if (!(button & B_PRIMARY_MOUSE_BUTTON)) - ADBMouseUp(0); - if (button & B_SECONDARY_MOUSE_BUTTON) - ADBMouseDown(1); - if (!(button & B_SECONDARY_MOUSE_BUTTON)) - ADBMouseUp(1); - if (button & B_TERTIARY_MOUSE_BUTTON) - ADBMouseDown(2); - if (!(button & B_TERTIARY_MOUSE_BUTTON)) - ADBMouseUp(2); - } - } - } - return 0; -} diff --git a/SheepShaver/src/BeOS/video_window.h b/SheepShaver/src/BeOS/video_window.h deleted file mode 100644 index 60c4e1bf..00000000 --- a/SheepShaver/src/BeOS/video_window.h +++ /dev/null @@ -1,523 +0,0 @@ -/* - * video_window.h - Window video modes - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - - -// Messages -static const uint32 MSG_REDRAW = 'draw'; -static const uint32 MSG_ABOUT_REQUESTED = B_ABOUT_REQUESTED; -static const uint32 MSG_REF_5HZ = ' 5Hz'; -static const uint32 MSG_REF_7_5HZ = ' 7Hz'; -static const uint32 MSG_REF_10HZ = '10Hz'; -static const uint32 MSG_REF_15HZ = '15Hz'; -static const uint32 MSG_REF_30HZ = '30Hz'; -static const uint32 MSG_REF_60HZ = '60Hz'; -static const uint32 MSG_MOUNT = 'moun'; - -static bool mouse_in_view; // Flag: Mouse pointer within bitmap view - -// From sys_beos.cpp -extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg); -extern void SysMountVolume(const char *name); - - -/* - * A simple view class for blitting a bitmap on the screen - */ - -class BitmapView : public BView { -public: - BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "bitmap", B_FOLLOW_NONE, B_WILL_DRAW) - { - the_bitmap = bitmap; - } - virtual void Draw(BRect update) - { - if (the_bitmap) - DrawBitmap(the_bitmap, update, update); - } - virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); - -private: - BBitmap *the_bitmap; -}; - - -/* - * Window class - */ - -class MacWindow : public BDirectWindow { -public: - MacWindow(BRect frame); - virtual ~MacWindow(); - virtual void MessageReceived(BMessage *msg); - virtual void DirectConnected(direct_buffer_info *info); - virtual void WindowActivated(bool active); - - int32 frame_skip; - bool cursor_changed; // Flag: set new cursor image in tick function - -private: - static status_t tick_func(void *arg); - - BitmapView *main_view; - BBitmap *the_bitmap; - uint8 *the_buffer; - - uint32 old_scroll_lock_state; - - thread_id tick_thread; - bool tick_thread_active; - - bool supports_direct_mode; - bool bit_bang; - sem_id drawing_sem; - - color_space mode; - void *bits; - int32 bytes_per_row; - color_space pixel_format; - bool unclipped; -}; - - -// Pointer to our window -static MacWindow *the_window = NULL; - - -/* - * Window constructor - */ - -MacWindow::MacWindow(BRect frame) : BDirectWindow(frame, GetString(STR_WINDOW_TITLE), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE) -{ - D(bug("Window constructor\n")); - supports_direct_mode = SupportsWindowMode(); - cursor_changed = false; - bit_bang = supports_direct_mode && PrefsFindBool("bitbang"); - - // Move window to right position - Lock(); - MoveTo(80, 60); - - // Allocate bitmap - { - BScreen scr(this); - mode = B_COLOR_8_BIT; - switch (VModes[cur_mode].viAppleMode) { - case APPLE_8_BIT: - mode = B_COLOR_8_BIT; - bit_bang = false; - break; - case APPLE_16_BIT: - mode = B_RGB_16_BIT; - if (scr.ColorSpace() != B_RGB15_BIG && scr.ColorSpace() != B_RGBA15_BIG) - bit_bang = false; - break; - case APPLE_32_BIT: - mode = B_RGB_32_BIT; - if (scr.ColorSpace() != B_RGB32_BIG && scr.ColorSpace() != B_RGBA32_BIG) - bit_bang = false; - break; - } - } - if (bit_bang) { - the_bitmap = NULL; - the_buffer = NULL; - } else { - the_bitmap = new BBitmap(frame, mode); - the_buffer = new uint8[VModes[cur_mode].viRowBytes * (VModes[cur_mode].viYsize + 2)]; // ("height + 2" for safety) - screen_base = (uint32)the_buffer; - } - - // Create bitmap view - main_view = new BitmapView(frame, the_bitmap); - AddChild(main_view); - main_view->MakeFocus(); - - // Read frame skip prefs - frame_skip = PrefsFindInt32("frameskip"); - - // Set up menus - BRect bounds = Bounds(); - bounds.OffsetBy(0, bounds.IntegerHeight() + 1); - BMenuItem *item; - BMenuBar *bar = new BMenuBar(bounds, "menu"); - BMenu *menu = new BMenu(GetString(STR_WINDOW_MENU)); - menu->AddItem(new BMenuItem(GetString(STR_WINDOW_ITEM_ABOUT), new BMessage(MSG_ABOUT_REQUESTED))); - menu->AddItem(new BSeparatorItem); - BMenu *submenu = new BMenu(GetString(STR_WINDOW_ITEM_REFRESH)); - submenu->AddItem(new BMenuItem(GetString(STR_REF_5HZ_LAB), new BMessage(MSG_REF_5HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_7_5HZ_LAB), new BMessage(MSG_REF_7_5HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_10HZ_LAB), new BMessage(MSG_REF_10HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_15HZ_LAB), new BMessage(MSG_REF_15HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_30HZ_LAB), new BMessage(MSG_REF_30HZ))); - submenu->AddItem(new BMenuItem(GetString(STR_REF_60HZ_LAB), new BMessage(MSG_REF_60HZ))); - submenu->SetRadioMode(true); - if (frame_skip == 12) { - if ((item = submenu->FindItem(GetString(STR_REF_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 8) { - if ((item = submenu->FindItem(GetString(STR_REF_7_5HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 6) { - if ((item = submenu->FindItem(GetString(STR_REF_10HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 4) { - if ((item = submenu->FindItem(GetString(STR_REF_15HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 2) { - if ((item = submenu->FindItem(GetString(STR_REF_30HZ_LAB))) != NULL) - item->SetMarked(true); - } else if (frame_skip == 1) { - if ((item = submenu->FindItem(GetString(STR_REF_60HZ_LAB))) != NULL) - item->SetMarked(true); - } - menu->AddItem(submenu); - submenu = new BMenu(GetString(STR_WINDOW_ITEM_MOUNT)); - SysCreateVolumeMenu(submenu, MSG_MOUNT); - menu->AddItem(submenu); - bar->AddItem(menu); - AddChild(bar); - SetKeyMenuBar(bar); - int mbar_height = bar->Frame().IntegerHeight() + 1; - - // Resize window to fit menu bar - ResizeBy(0, mbar_height); - - // Set mouse mode and scroll lock state - ADBSetRelMouseMode(false); - mouse_in_view = true; - old_scroll_lock_state = modifiers() & B_SCROLL_LOCK; - if (old_scroll_lock_state) - SetTitle(GetString(STR_WINDOW_TITLE_FROZEN)); - else - SetTitle(GetString(STR_WINDOW_TITLE)); - - // Clear Mac cursor image - memset(MacCursor + 4, 0, 64); - - // Keep window aligned to 8-byte frame buffer boundaries for faster blitting - SetWindowAlignment(B_BYTE_ALIGNMENT, 8); - - // Create drawing semaphore (for direct mode) - drawing_sem = create_sem(0, "direct frame buffer access"); - - // Start 60Hz interrupt - tick_thread_active = true; - tick_thread = spawn_thread(tick_func, "Window Redraw", B_DISPLAY_PRIORITY, this); - resume_thread(tick_thread); - - // Add filter for keyboard and mouse events - BMessageFilter *filter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, filter_func); - main_view->AddFilter(filter); - - // Show window - Unlock(); - Show(); - Sync(); - D(bug("Window constructor done\n")); -} - - -/* - * Window destructor - */ - -MacWindow::~MacWindow() -{ - // Restore cursor - mouse_in_view = false; - be_app->SetCursor(B_HAND_CURSOR); - - // Hide window - D(bug("Window destructor, hiding window\n")); - Hide(); - Sync(); - - // Stop 60Hz interrupt - D(bug("Quitting tick thread\n")); - status_t l; - tick_thread_active = false; - delete_sem(drawing_sem); - while (wait_for_thread(tick_thread, &l) == B_INTERRUPTED) ; - D(bug("tick thread quit\n")); - - // dispose allocated memory - delete the_bitmap; - delete[] the_buffer; - - // Tell emulator that we're done - the_window = NULL; - D(bug("Window destructor done\n")); -} - - -/* - * Window connected/disconnected - */ - -void MacWindow::DirectConnected(direct_buffer_info *info) -{ - D(bug("DirectConnected, state %d\n", info->buffer_state)); - switch (info->buffer_state & B_DIRECT_MODE_MASK) { - case B_DIRECT_STOP: - acquire_sem(drawing_sem); - break; - case B_DIRECT_MODIFY: - acquire_sem(drawing_sem); - case B_DIRECT_START: - bits = (void *)((uint8 *)info->bits + info->window_bounds.top * info->bytes_per_row + info->window_bounds.left * info->bits_per_pixel / 8); - bytes_per_row = info->bytes_per_row; - pixel_format = info->pixel_format; - unclipped = false; - if (info->clip_list_count == 1) - if (memcmp(&info->clip_bounds, &info->window_bounds, sizeof(clipping_rect)) == 0) - unclipped = true; - if (bit_bang) { - screen_base = (uint32)bits; - VModes[cur_mode].viRowBytes = bytes_per_row; - } - release_sem(drawing_sem); - break; - } - D(bug("DirectConnected done\n")); -} - - -/* - * Handles redraw messages - */ - -void MacWindow::MessageReceived(BMessage *msg) -{ - BMessage *msg2; - - switch (msg->what) { - case MSG_REDRAW: { - - // Prevent backlog of messages - MessageQueue()->Lock(); - while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) { - MessageQueue()->RemoveMessage(msg2); - delete msg2; - } - MessageQueue()->Unlock(); - - // Convert Mac screen buffer to BeOS palette and blit - uint32 length = VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize; - if (mode == B_COLOR_8_BIT) { - // Palette conversion - uint8 *source = the_buffer - 1; - uint8 *dest = (uint8 *)the_bitmap->Bits() - 1; - for (int i=0; iBits() - 1; - for (int i=0; iBits() - 1; - for (int i=0; iDrawBitmapAsync(the_bitmap, update_rect, update_rect); - break; - } - - case MSG_ABOUT_REQUESTED: - OpenAboutWindow(); - break; - - case MSG_REF_5HZ: - PrefsReplaceInt32("frameskip", frame_skip = 12); - break; - - case MSG_REF_7_5HZ: - PrefsReplaceInt32("frameskip", frame_skip = 8); - break; - - case MSG_REF_10HZ: - PrefsReplaceInt32("frameskip", frame_skip = 6); - break; - - case MSG_REF_15HZ: - PrefsReplaceInt32("frameskip", frame_skip = 4); - break; - - case MSG_REF_30HZ: - PrefsReplaceInt32("frameskip", frame_skip = 2); - break; - - case MSG_REF_60HZ: - PrefsReplaceInt32("frameskip", frame_skip = 1); - break; - - case MSG_MOUNT: { - BMenuItem *source = NULL; - msg->FindPointer("source", (void **)&source); - if (source) - SysMountVolume(source->Label()); - break; - } - - default: - BDirectWindow::MessageReceived(msg); - } -} - - -/* - * Window activated/deactivated - */ - -void MacWindow::WindowActivated(bool active) -{ - video_activated = active; - if (active) - frame_skip = PrefsFindInt32("frameskip"); - else - frame_skip = 12; // 5Hz in background - BDirectWindow::WindowActivated(active); -} - - -/* - * 60Hz interrupt routine - */ - -status_t MacWindow::tick_func(void *arg) -{ - MacWindow *obj = (MacWindow *)arg; - static int tick_counter = 0; - while (obj->tick_thread_active) { - - // Wait - snooze(16667); - - // Refresh window - if (!obj->bit_bang) - tick_counter++; - if (tick_counter >= obj->frame_skip) { - tick_counter = 0; - - // Window title is determined by Scroll Lock state - uint32 scroll_lock_state = modifiers() & B_SCROLL_LOCK; - if (scroll_lock_state != obj->old_scroll_lock_state) { - if (scroll_lock_state) - obj->SetTitle(GetString(STR_WINDOW_TITLE_FROZEN)); - else - obj->SetTitle(GetString(STR_WINDOW_TITLE)); - obj->old_scroll_lock_state = scroll_lock_state; - } - - // Refresh display unless Scroll Lock is down - if (!scroll_lock_state) { - - // If direct frame buffer access is supported and the content area is completely visible, - // convert the Mac screen buffer directly. Otherwise, send a message to the window to do - // it into a bitmap - if (obj->supports_direct_mode) { - if (acquire_sem_etc(obj->drawing_sem, 1, B_TIMEOUT, 200000) == B_NO_ERROR) { - if (obj->unclipped && obj->mode == B_COLOR_8_BIT && obj->pixel_format == B_CMAP8) { - uint8 *source = obj->the_buffer - 1; - uint8 *dest = (uint8 *)obj->bits; - uint32 bytes_per_row = obj->bytes_per_row; - int xsize = VModes[cur_mode].viXsize; - int ysize = VModes[cur_mode].viYsize; - for (int y=0; yunclipped && obj->mode == B_RGB_16_BIT && (obj->pixel_format == B_RGB15_BIG || obj->pixel_format == B_RGBA15_BIG)) { - uint8 *source = obj->the_buffer; - uint8 *dest = (uint8 *)obj->bits; - uint32 sbpr = VModes[cur_mode].viRowBytes; - uint32 dbpr = obj->bytes_per_row; - int xsize = VModes[cur_mode].viXsize; - int ysize = VModes[cur_mode].viYsize; - for (int y=0; yunclipped && obj->mode == B_RGB_32_BIT && (obj->pixel_format == B_RGB32_BIG || obj->pixel_format == B_RGBA32_BIG)) { - uint8 *source = obj->the_buffer; - uint8 *dest = (uint8 *)obj->bits; - uint32 sbpr = VModes[cur_mode].viRowBytes; - uint32 dbpr = obj->bytes_per_row; - int xsize = VModes[cur_mode].viXsize; - int ysize = VModes[cur_mode].viYsize; - for (int y=0; yPostMessage(MSG_REDRAW); - release_sem(obj->drawing_sem); - } - } else - obj->PostMessage(MSG_REDRAW); - } - } - - // Set new cursor image if desired - if (obj->cursor_changed) { - if (mouse_in_view) - be_app->SetCursor(MacCursor); - obj->cursor_changed = false; - } - } - return 0; -} - - -/* - * Mouse moved - */ - -void BitmapView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) -{ - switch (transit) { - case B_ENTERED_VIEW: - mouse_in_view = true; - be_app->SetCursor(MacCursor); - break; - case B_EXITED_VIEW: - mouse_in_view = false; - be_app->SetCursor(B_HAND_CURSOR); - break; - } -} diff --git a/SheepShaver/src/BeOS/xpram_beos.cpp b/SheepShaver/src/BeOS/xpram_beos.cpp deleted file mode 120000 index e5d7f965..00000000 --- a/SheepShaver/src/BeOS/xpram_beos.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/BeOS/xpram_beos.cpp \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/sigsegv.cpp b/SheepShaver/src/CrossPlatform/sigsegv.cpp deleted file mode 120000 index a41f4a06..00000000 --- a/SheepShaver/src/CrossPlatform/sigsegv.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/sigsegv.cpp \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/sigsegv.h b/SheepShaver/src/CrossPlatform/sigsegv.h deleted file mode 120000 index 213fb61d..00000000 --- a/SheepShaver/src/CrossPlatform/sigsegv.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/sigsegv.h \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/video_blit.cpp b/SheepShaver/src/CrossPlatform/video_blit.cpp deleted file mode 120000 index 15297235..00000000 --- a/SheepShaver/src/CrossPlatform/video_blit.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/video_blit.cpp \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/video_blit.h b/SheepShaver/src/CrossPlatform/video_blit.h deleted file mode 120000 index 7fe63598..00000000 --- a/SheepShaver/src/CrossPlatform/video_blit.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/video_blit.h \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/video_vosf.h b/SheepShaver/src/CrossPlatform/video_vosf.h deleted file mode 120000 index 4c552311..00000000 --- a/SheepShaver/src/CrossPlatform/video_vosf.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/video_vosf.h \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/vm_alloc.cpp b/SheepShaver/src/CrossPlatform/vm_alloc.cpp deleted file mode 120000 index cc80e1bc..00000000 --- a/SheepShaver/src/CrossPlatform/vm_alloc.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/vm_alloc.cpp \ No newline at end of file diff --git a/SheepShaver/src/CrossPlatform/vm_alloc.h b/SheepShaver/src/CrossPlatform/vm_alloc.h deleted file mode 120000 index ef65a561..00000000 --- a/SheepShaver/src/CrossPlatform/vm_alloc.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/CrossPlatform/vm_alloc.h \ No newline at end of file diff --git a/SheepShaver/src/EthernetDriver/.finf/Ethernet.mcp b/SheepShaver/src/EthernetDriver/.finf/Ethernet.mcp deleted file mode 100644 index 07b9b6a81ae87b1e58a60cacb95bb48fc00bd657..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 XcmebE4JdLB_jF}sU}#_j66gQ`Qp5uY diff --git a/SheepShaver/src/EthernetDriver/.finf/ethernet.ndrv b/SheepShaver/src/EthernetDriver/.finf/ethernet.ndrv deleted file mode 100644 index f58fce9b794bfb4a4fe810ef7c7136631e5979df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 WcmXTU$VsvX0!9WP023ev0ssI_8v>{R diff --git a/SheepShaver/src/EthernetDriver/.rsrc/ethernet.ndrv b/SheepShaver/src/EthernetDriver/.rsrc/ethernet.ndrv deleted file mode 100644 index 63653eda90f5d8e837d4382137fe949f517a6ea2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 398 zcmZQzU}RumV2lA0AZ!H0BMn3#c^DKJ=zy`HydW7}5Xi?=Yr&gZl95`Jms+Bimr_&) lQGy6txx~E(7>a;8WkBJaoK}<$WOFev{QnO!T`p<94gfd$5i0-y diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/.finf/CWSettingsMacOS.stg b/SheepShaver/src/EthernetDriver/Ethernet Data/.finf/CWSettingsMacOS.stg deleted file mode 100644 index 2c25cdbdb1112cee1ca86ec8cff8942b51e4be7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 RcmWG>aSU+|_jF~z0RTd#0#*P3 diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/.finf/PPC Debug MacOS Toolbox b/SheepShaver/src/EthernetDriver/Ethernet Data/.finf/PPC Debug MacOS Toolbox deleted file mode 100644 index 4e4e4935707a596987ec1cc32e3d0d587dbe4f04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 KcmZQzzz+ZbAOHaX diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/.finf/PPC Final MacOS Toolbox b/SheepShaver/src/EthernetDriver/Ethernet Data/.finf/PPC Final MacOS Toolbox deleted file mode 100644 index 4e4e4935707a596987ec1cc32e3d0d587dbe4f04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 KcmZQzzz+ZbAOHaX diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/CWSettingsMacOS.stg b/SheepShaver/src/EthernetDriver/Ethernet Data/CWSettingsMacOS.stg deleted file mode 100644 index 7848ef0bfd9293284e5d924000b90d76e0b1cf39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4344 zcmeHK&o9J46n^d2mJlR}#Hlyp;OruiEH+}X*C5i#Xz#nBG-4J_`pDuG8fyVwB%NX8< zv`f$}(q4kjN?WO)F_7}jobo&{=PB1ei}<}>JbxCRb@|&Ywa)AiH6Pv3YpjnrX|!}L zaBec^Oun>Gl=oAV@YIt6s^MI7ol7 zn6oCtN>sIyQ@MgOe8t<2hG3G7UQUmvlJ2V$P#HJ8M>zkw}l eKoc>Iy~O`E4_wyX9ZhsyX1wj<(g%)ui|7Rrv4Twi diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/.finf/TargetDataMacOS.tdt b/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/.finf/TargetDataMacOS.tdt deleted file mode 100644 index 2c25cdbdb1112cee1ca86ec8cff8942b51e4be7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 RcmWG>aSU+|_jF~z0RTd#0#*P3 diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/.rsrc/TargetDataMacOS.tdt b/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/.rsrc/TargetDataMacOS.tdt deleted file mode 100644 index 7c9986b9e0bcfb616df3c616ba39e2f18aa1a8a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 ecmZQzU}RtbV<5%AAO|K#6oJG4G7NJ6{{sLh?E-lK diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/TargetDataMacOS.tdt b/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Debug MacOS Toolbox/TargetDataMacOS.tdt deleted file mode 100644 index 48fe5d703923e17c899a20b29a62202c67d6bb8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46180 zcmeHQeQ;dWb-!3JR2|uge=>HDlRQ+O9BiMS}Zvd7_e5mPtuyz?y~!2 z3x~!FIN%T`5!9J6#K4A_)PMtO>rR+917e!AX`9Zd?M$08OweR9V5Y$MkNnX;Jh;De z@7dkAlJ>pz?z1AKJ<@yU-gD1A=iYPAd-vnreJ>P`M}-hxA+&WuykQFQ=20PhzXWZQ z=Fxx@v<5?M?RrNr*=Lw~Q_u`%6XpmG1RC`wqi3*BXG_3tJ@KKaVOT!U@~TFW92ff1}+{r zLClC2)!jB|CI(IYwrJ3%Vad%J<6+}=BUV(9g@-)0|Hd|3)}}}*m`WJ~J$8m6nYTyd zJ;A8nmVk>!&_K3QTOzTC99U2`9XFOP{aknh$@p$Kg{|&D^KJI&&N8;71{|6T1xXl5 z^AVIjRlGRcjeX8u*BOazr)G6<&Y^~z9ot^=wB1&`{=`sHixXq>P{=@Q;{tRr1~HfH z9>na>qWBeo`g|m;tKLDP`;dg=ObNEBx1uCp9 z1767CO~8vd+zGsx!v}yb;P46HB^>@w;H4b?9GGMQJXE&jGAKN4z%?Ak*iNkA@Dbn( zIs6a67jgI#;FT)u{UhLuIeZK7mpI%Hyo$r$2fl>Ee+x``0N($>=~5XKUMky{RoHhm z@MRp{27Eb(6Tnw+_%QI59447MhkpaST7~D4J=Soz0r)Bo?*t|tRdC+|&^5t+BCjX%6Y>x8 z3-SjY2em)7JGVDN(*!M%9(~(DBAzsL41>hhU^E(!$MidlXhO7h>O5vd3L*g`85QXC zY5ajPgy?ESXKc-lv57U>Z1x+;m|@n161WZwipk(WFceSi8Z;wO8Qm5$jbv{yWS}f! z{f<~)*(QLTY?UE|B= z?{~cS!9*KOj+5PdWH))OOl7ypd8(AE1*#UPTA*ryss*YRs9KgkL0+GTe`&-V81jdnWRNb81>Y4w$UbHLtPDytPO1IqgBhQrv1f=`l5 z*>E@~Nj(F$Zs07W1di#t#*(R|!yTi9!aA^Yb9!AUiXYY#XLh4~NP6AANTRqFjN>cx z1M)XD7r43MuHrYS%eMpqEq3K_Bdr@kwj>;G#x5u#J*}-RTb)E%_6EZ^PTW(cw+32n zn>r;=bwy8SV^dz@`3ZGHY}?j5btmbqfzIqU=(6n=Xo>eY>8Uim8v>@akLu~SEpox; z^C>u;(kV+ReIf1{YF~TVt&`Pr!wpjuGe>eykNs`kJw3L!TDsS|WH;A^ph4l za7w4VvVBrUpPd{x(!%kO{RGJcCEbuQU1P~qf7G#`v;3^6>^nB?&vr768+u4b9U93= zS0(8I&RiF_m*U1agf!IQ8M~wL?2BTX+RdqT=h^8iu5@?Z!dBMO<|}Bq;s6Nm#v4?&Xjq(8~!HiGmGZ! zc#Yhqjk@LSY7_hf(N(tsCX)*(Z9TiQ&t@R3Fs;;>8mriI=kDo6w3I$pvFkZ3W1@=n zlsG1;SdZ;cCBIf)xgJ|ZuC-6tIPV(>q`%p&{8#P=xiOLLNX1P(B|ZZx(+_g>!JAX< zuhhy@vtv9vNtOCr8p5-B?CuEe>6xyvq~m=@zCpB@ZA%&BNxLQS9%CCIB}R(7hAH?; z(GzLewsnfE1tiN}ha#R`z&>Rpf=vihCRm7W^m8Px&S8s{8}*TTrt6tW6fc>x0oUr| z@NCAl_KEkpJfyj_Cq3xm_NFUG!W&yV%##sa61FHE--zLe`n*5@47jVse* zU!mOCtK$0DPF-BITZv=vit95pWNFq(LD%dy1J|d^@weRErPR4tneCI;bAJ6Gujl;w zK~7IJG(B^2o3&?ha@YKNz+RDSdhncL(#2^ZRH`QpS?4r|Ez_^9dh9IcW_|3M$UQw# z+YYGUs~!1IZsc09AU#Jd45;>r+HPPgkW+~sho|IDduN=|sb;c1dmnQ8U0gq>2cTtN1L?u4)wt`D%V6P zbrbir?K4fJZ2P(Pej{pIp@|io5KnV_I`*@Ysyh4Xh)U}ttFs7i)WLrhsurkPV9r^< zgLkXVFX8z?*B9|;j$Zx?F7nNHpb1IJu`>v#Y9PZFg<;kr%m$+7snoqgwFfXUX zwfG|T$;okH-;=aYscXVT%9BQgvvTtLmag=JTmVjXPJ>&?scc_TPL9K?a!?-IeMeMy zS)K~_6_Fgb_6@nYFUV=_uhe}qmF}qykbwYo4r^*9m&akvtknH7b#Cmtp`jAqLnwAW zyg=-K_n53GQ7Hb6hE}n>+_&zqB!%dEadx2e?QO`KTJkPT+hxh8(L34mF$#HKS8>KW z<8({1g3_0;kkBvgmr^F3SE%8nSYnx9Ont{zwzLREP;<^!m|?cXmRc+1l@anc3#`9h zPZ_2eiS?!Qi2M$$5!QQ?@c}&^4eM*<77V>580#Ah_8DvRL@;JV_3PI!U3yidS6{tr zS6qHVeO)4Hgw!YAuR}^K6dep3`WkDatHV$7173)j>LKmKZ9*&!NBOGN@-8TCW2UxyZLByYRg5!mimn$JSXfam98T-0c$ zX401;p#^PRdvKi)KNG(OJ)>o;bQ}JY;{Ckj4PEsDK5`~csjY|hC|Xl_z#Z&KhoIj= zf!-rxG@olj7Ya2jj!&RO3;hN>lCnAHktpX8VX3?Hn@4lnr5__#7+z}e$Oa+0LAgvE z#2=E;_VR1z-1e6W0JZ%(p{;~nRL&7q6RlRuUK684=@QZt>p?#*)@g5PZ;5*Cly*w^ zwKJY>(cnpV5@V#m zUnI0ka%3qolOj#NhrzrPfxhiZ-;YJ@sEz5+E)!ba#+!bNSQflH&pvP<8v*uqesFJ( zHQxSC&xXDa_Mc6ySgBKb+e`b;H1}P+e(%{BoLG3(@?$pp|i$^l-~Z%*N^T$yZ`Lo8g}0Gw3)G#&O3I2X74O=WGK2DzEVFMaRZ|f@GR{;$t8r%V4^${F zkWXlfn}>|hpc(9mmbV=v*YnZcK?1q5JCN;1mgmb@-s9VRkK|6lzJOAy-{1KHHkyk? z_SCI+QQ8+zl(yxIS7tX$yh=U|lRJWX;zN2<^VS`=(~pPT)KQf+gDrr;dKIRy07ltQ8U?`~s$&mP9edcjNHw)W3uttODj81Ka)p|z*{c?q*%t7kc(gOH zBzWc%bJ;T|&1J)H;W&jXb(w$u{CAmW|2vR*_U}$-R($-k%!*Im@_5INd%XXe&aC*~ zS{#oed<3)%__0vQuycPpu{RN_M>MnIY^}MJLKJQo7TSZ)iF*>`V(~{O#XS#SfN;I# z85I^tmYxPHVJd@H?8L&R5MKwW2bci$`O`6>tva4PeDi#MnUXzeJJNU#fmPCrPU3i9 zlAnPrg4_~J>QKX|=bD57u2=Yv(+c0r^qad?{41P(6Q^(D^i4G?eIxU2V0!(CqSuWn zd?V+(A&WWRb@eL!+HuBAzlP;p)2--NalSRDReViA;nmEyn)B(*eM+ANH&C1m{a|JkIer$73UkFQzLz!1)J+iboR)KQzXe^X+E7 z-OLy1R_PIr_h(eR->-1rIO8;9UE$tQ#@&pC!o~<=rW-XX9%g#jui~L``8?uKh|3eI zSM;7S#%ab(4>CQ-`MWbJ{lQ^{lieKG6@Gx@_cPzl(~7<`t?+$JznA&C5{ll*_-i97 zzGGP74$jw6uj1PS3J=yOY_dF)(^I30{{3;rOn;W~_jICf7T-;)^zWQz98mZW<8O2N z(=6v{ze@jBM&W~;@2OE0e@ZC)B=Q;hkaYcWQ`JU5N{4X;K|CrNX@vHbTjvr%r zKN?l^9}P3^W?au$DE#sm;|${f;~Is3m|$GbnDb>uR6LVr9AK;~{L*R0ql||ccQa=G zmze)W=6{j-Uu6ClC4VAHS3h0tu^S#OOH#q+r-75VJ=Kl$&|D;~gPjLK1LdAc|@t?}L zpPmD^h=BMd{_YU(YfJF73y=M9FSs9lNkBfXuz93SwwepD^4i9>rsiw)Yn!%oYyk>v zYwWmoE>t{QN9S?UA|69za}dsrClK=D`5hi_DUbo2vY5$!!lVk%Mm$&$$UfGR9>~J- zGKtv=RzIC*(QV~9m#{~c`CM`o<3*VZij6%(j^HPbtbG(-e0SU3TUwjzn!B1EvrolP zP==`(sJJW1@Jj0adaR^7qTv=oj&39BLY|~G(Yx_ zAw*It0g_Ie5eQ#^gJyLUm-y|^)}jp0UypbJ(AJ77%xw!`s5i&Iss8q-r+{0*R z_JcWH`>RoVwEw*QLdb`JSBv|WkAtR(`<60ZK8z^V+!l&~lsVxIFpEI<5-IwqL98i%O9RVC;o-lB;C8{L?iW3Jd9jDf==sxMgQn)pz|DI9eNyJjiP^b0Ccss zC~C2ZLLLu73l8_7?&kJAu=sirJg*>nBZA*DvD$y!<3wjLU!V zry#(e2#!6A6WigvcM-mvsGy(3=?W$PE|ghZK~&KH1E-CO-bn=Pv?X}OhZC276NPmg zfLBNl`@_GJ->xPq=r`lU<*Ao#B+25Ht-voT`LDqy;wq+(!*AIRjbvMD55TJpF diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/.finf/TargetDataMacOS.tdt b/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/.finf/TargetDataMacOS.tdt deleted file mode 100644 index 2c25cdbdb1112cee1ca86ec8cff8942b51e4be7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 RcmWG>aSU+|_jF~z0RTd#0#*P3 diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/.rsrc/TargetDataMacOS.tdt b/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/.rsrc/TargetDataMacOS.tdt deleted file mode 100644 index 7c9986b9e0bcfb616df3c616ba39e2f18aa1a8a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 ecmZQzU}RtbV<5%AAO|K#6oJG4G7NJ6{{sLh?E-lK diff --git a/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/TargetDataMacOS.tdt b/SheepShaver/src/EthernetDriver/Ethernet Data/PPC Final MacOS Toolbox/TargetDataMacOS.tdt deleted file mode 100644 index cdb3ae7c538a7cb15e14bbe16d1b473ea3eb2c97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46304 zcmeHQ3t$w-dEPsngv86dY%u1rU~FUqhXTeSt{*2P@s!XR$wd@Wbaz^$!>7CR-N^_- zgG^`>+r*)<-71DUYHeJCWt$|V!HG+8lBOheQc^$a;Mj4R1luj4q;V4GQIqeVnZ1Wj zH+#BUsc_nn{{3hF`S<^4{`qI;v2(k=P$-}%N|B=2$`$45^NMn0ilR79g0|RZw*m1` z=ke7ysEwXTs}@tMJu#1-Fif!9U8OGf2R#8*SORwQhB|L*2z5k!n%WrAw5XDasnX}u zqEXfDiM3^Bs@A+6t*u%_UDpwe`P;RO(nKXRXt9_-*qT}3a(_TWZo^?I*Rl?Ophd0e zj72<|MaA>Rb!W`lI;}kv(^STuk*TsH7FrNvo|KsfmfpSt#;6JfgPJeq4+S&luBsy% z3$?3jwC&qMkroNx!m4@mAhA6R%S1Bju3~KNh!&27sNOhkECMB&8k8z+6pb0QBV>Od2HK)dMRtQKkA7_wRW$}FeGzDAml|O zs1L(M{iq0#2#SjD`^EuasGu0cNSBCo4~F@9npilals_X8J;`18OeB7O#V1drRs0+)*T zV&F0nUk^M|#P(a zQN+&zPvY^SD}gT;@tc9K5b-wP$s+zRFvg1%ioS#cU4u~ceH^B;s8U3EyNbshbAYFb z_$uJ(A|3{wA>t1K&lGWzsfzd;z_WO~nCvlI#FqkJE#e!2Nrx58w*dJ*`6u}+`8Cx6 z`6Brs`6{&s@^SKi@-Vaw+QXqpOvNxrS>_1@LZP6#QVWEYy7j6UGa>~iZY>f}(CO3o z17irKsS2HO^3@odB%jvA+O$Yei#dH^v;&RKShU^a3q?0~#QXtvx+)mcB3nE@4S7)( z-VyZQtwo}qz(SlxJQ2SZUDy!o@W#)E$S{@~%L2p40(1|gK=(Gi|EK$u-v3{RINkp! zd;p;L|4R_p`+w?7MgOnVAujrVWfS6}|5yBoi~e8Pin!?i73#x9|F3)uanb)P`w$oX zKVpR$$Tn17sspkO*-f_v*@xVa%acBgvKZH{Pu0fKA*vN5Zp#+s%^E|I&z@pGfj z7;9kevlo2KU+kAn?&*6Cbl3spU#!jtQBM){Q2)$qIEZ>2&_iPYR(DZ!QFZPH)h3$H zSMNCe!@f31KPS66$Zo8y^k=v9Yb=Uo0m}lG1uP3#7O*T}S-`S@WdX|qd0K!5;`%%* zPfTLE%Gd2o*0%dp6{LQA=ZX%i$hP?&IM=l_^$P#w=1>bwn&=ID!Ys*W> zEWjV(&X)0F^N3AxwoDx-mh71& zoGqn21#c2OW#Ypp+W9DUs}+2qtpZvWNLYY8zn^{Y35G(CS##?`ui=4}uUHweHWbth zE-I?4b4Lt#@=kU^0zJ2P`sAYUgObLE24BP8+OT zwIXRBM&VF(a)d~`?;i_Rporg zrv2$grZGbg>2RWwjCAFb?iLq2Lvkr*j6+C+6MGB{jVI5FG__fzItSV5NDm+DvsX3< zt!b#N(8l`1ag1lQHkS20-C#Oq)JGZV>4N*QzGDdbs6lRCtRXeyn9V(%G3R;6;u+p> zpSRO*nsW*RoVVw$XNczQLwXPNL=0MUPF0d}5xZwxZ1d?1Uce@eDY;KSVde43W*uy; zFY$Z)bP-DSdgQ~i`1~gC^2n#3ChCzYGEL9LHlNP1eg-_B&QVVne3bch*w-fW?0oAd zp{LO1)BQB^BoeBHUc-?wWV2pK@9@YdKqRES=fmiNe$t2eygfq;>c>!hNCTX==d6d+ zUM%x=GyIK}r-0_|c#YoTMQYO9<@)#uPAA`nkWNme)O)w;&t@PjH7(mSK30))$M5MG zv}8Y4k@Xx&W1_tEWH~0vTaR?8l2|LxUyoFgY4y{h4f+NG=5NxK|NQ+RJ|>cmRLs*|pqk0H*^Kd+-6D98 zvm}rbEh@T(e)zJ{4KS$!623xGmC=b&! zRL@KTc*&k5m{uNxXEUbNPsmH}5z83N(8JeRo9G3JnRZCcFSKVSb=4aT_j|!EZS|7f zsM(D1>aw_Jn4%|({a&W%$zs2kDSE7RWj=}RTPiJRRwWdW)v)e_uKAnrd#pf>B&c$-9 zpM;*l^@D_-!S#c4K~Q&0%x&>tsDL z%b8goSrwV5Cm`*BQodS}_~b~u22;}G)YJ&CpMZ1&TZ)`~^cXxPH`+U6lujjM<=J+p z(eL_FjgZ4xp*`Or6By0?%^1fsJwrA3Z`m%L{hL-EsTTALCd?a|-3-XA=^#dL$=Q}9F_KS4Q*OLTA;oK>~r2F&WB<@E2(nIi=*UQ9#)((yio}M zRHr^$nY= zJP~gwxEWs~-3&q`6m?3+8HHmBv941>C1QgF{rfnDQ$(vId0D^)w`lkHgLw(L)Gwy? zvF<024Q4T#A>0~6rCT_wv5obNG~I9plxCz4{I@kTT?S&)lAA$cYk5QU+ZyW`soIoO z3)!?ERzE)J5_R%35w;MP`!nBgQtr~D`L4N>L|&djd^ScyCA^1F+4#{{6h~~Bj1|-C zioWKz>jKf!j^kjfd zX>UH;BSsbKsIFbn`R#POE}rSbWRO}uq?lnK0)wJ z68Lgp3Rj44EYP>EiBAs{Com(wB!~QgaDVwFI{5=(@(05G<(KI6U2ejC^NTi8jP_G} z(q3NDiFQ$rw(wcNR{$>qejaM|jt0yHQ~}Ulyb-{s08atF1vnFG^%VoI0aOD%4A=?S z4}cusYk=RNtxX4fDAc;)ynv;^;NRc|YyzAG!~k6Yw8;%UfL_3J07^>+l97Bai?<2h z7l3~N8w@y9230K*2}RV9&({%&Xf5itw)A^gyiE!DyM8^*H*U{34?iutW7jYB#!Zwl z`Jca>ERSiyNaE=;$_+(mCj75>Nt5FG+#$tfb8-B@9L4pZTX7u(JyObX)k==bPbscX zA5dIlk+$mu$G2jXHC7qnK!ZcaLCv1LhzI>1LT3&%Na|SO{4Pi;REi+FL;XKz4V7n~*wE&I=VE(1zA3-mY49XGr3CDR`akhr z4;N3>yP|a7fl~C^pOBizfxoUK(Ju`&3kAb(efy_isxqg7*qsY=x~@6T1J8st_E4;`$H3jj zx?%tpuu%);{6=kg08%Yh%L1341!yJI-gnI@Q!!pY)hET-GwK(;Hf6-#$@CkW>^=lW z({!7%i?1dr8=vXIIjsTNZ|ij{x4jfr2)k}!>jI_9#wQ+S{5yHN>)vw3RaBw49(xaD z^u`;XIRVVBcU3G^T*pr;u5HH{27NTr-;Ag4$Ep>je;&HAa)mHf*?5F7Upjc5jd?ac z^+h64=sDJMzGwWIw*kF9`rC@jaDZojFS%TxP#Gi6kmVbJl^`|1t6qmxm^bwfNUgRh)8Btm`a@6QCV=o&we!|2_ zmtQe?%9T^Enl^pLOm)`mtLI#E?cDO~uAeu5fpcNS2No^9VabgjT>7D#{^;ggZoSRr z@%r$Bq}De7);k03!BF_F2wv!R_qNXMJ2r0m@SkpO&Yb>{oqzVxU0wI={@9*B|BH`* z;@^h^KnlZQa^>_wDN%8t?ey^-UZ8gqJ^adQRmJ2hjQz#kBHQ38%ML z%x$t)To1SoFdz4~3V@UDa|Zwq>3n({(a&)oJKZ1b;sN)>_S1Si>6%ydYm#WMf%c3pNubeL9b>n_=n~?1~%xL%&ZYQh0~K$)vee_0=_V)w$J`jg>&|RaK31he5gH zMNEEH6(^=d%KBM1;iC&;qi?8>L?0&ti{PMRL3R-)RTu-=u^_-7lM4?N!V)rxIXT$k z;_10|X1?TWWN|yovy3C#G~^{EJNj-0+4U|;)a}FZ$hGxrE9+{UHBB|LD>J60K>J`+0A^6Et%`j|Mel=l6#&68hYkR>gtpr_lp+^S5U{f9;yZ1`Rg9X; zfuz%>2Ew#sr%0SLeEi(C7cN|Q1c+cOr}Xw{tk2t5%0Mq7dO+vocr@rXq6bsy zV?cKZIYmE9q>U&3E-ojTKH(5}hz>c)^oigfqqN7iKyT4I2{|h0;E!#=ds|cJTuy9D zIF&w2=WpplC;rlKMB7r<`z&9RWJ+dX0kLEgr$2fgBr!)QM-Nmyj?=FqI`uvX3#Ng8 z5~m-f5is>q2#YHe`e7D!_X17j{I48GTjDbKJW`Uy^nknaj|##KJq6nzjyZU5T|?~+_w*hkz9_=kN8BQg8m2&qd9#Z*>e(6 zL4N{=Z*%(b1&E71y7z|>Kfvjyn-Qlyun2om?h$7>-9x%)Pb|WNSeUj6JA9eSHHDFt zhf$7_Q;h$~-+m1=agW{qCius4IhC{$F_rTlIG6B~w{8JVjGrEZf7wO;pI-qw{E5Or zva7Je&btt&Hj8ku0*4t~{@U+SoT#9$#bFVrFL?oR(Y6nEAujU2hHRw*5Ds?ZApGH_ z`w^c-RM5YGgUC-aeN%EaQ9&o4d6dhqco*@jiK-}1Y=Yl%JM^w`f -#include "xlowmem.h" -#include "ether_defs.h" - - -// Macro for tail-calling native code from assembly functions -#define ASM_TAIL_CALL_NATIVE(NAME) \ - lwz r0,XLM_##NAME(r0) ;\ - lwz r2,XLM_TOC(r0) ;\ - mtctr r0 ;\ - bctr - -// Macro for calling native code from assembly functions -#define ASM_CALL_NATIVE(NAME) \ - mflr r0 ;\ - stw r2,12(r1) ;\ - stw r0,8(r1) ;\ - stwu r1,-64(r1) ;\ - lwz r0,XLM_##NAME(r0) ;\ - lwz r2,XLM_TOC(r0) ;\ - mtlr r0 ;\ - blrl ;\ - lwz r0,64+8(r1) ;\ - lwz r2,64+12(r1) ;\ - mtlr r0 ;\ - addi r1,r1,64 ;\ - blr - - -/* - * Driver Description structure - */ - -struct DriverDescription { - uint32 driverDescSignature; - uint32 driverDescVersion; - char nameInfoStr[32]; - uint32 version; - uint32 driverRuntime; - char driverName[32]; - uint32 driverDescReserved[8]; - uint32 nServices; - uint32 serviceCategory; - uint32 serviceType; - uint32 serviceVersion; -}; - -#pragma export on -DriverDescription TheDriverDescription = { - 'mtej', - 0, - "\pSheepShaver Ethernet", - 0x01008000, // V1.0.0final - 4, // kDriverIsUnderExpertControl - "\penet", - 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 'otan', - 0x000a0b01, // Ethernet, Framing: Ethernet/EthernetIPX/802.2, IsDLPI - 0x01000000, // V1.0.0 -}; -#pragma export off - - -/* - * install_info and related structures - */ - -#ifdef BUILD_ETHER_FULL_DRIVER -#define ETHERDECL extern -#else -#define ETHERDECL static -#endif - -ETHERDECL int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds); -ETHERDECL int ether_close(queue_t *rdq, int flag, void *creds); -ETHERDECL int ether_wput(queue_t *q, msgb *mp); -ETHERDECL int ether_wsrv(queue_t *q); -ETHERDECL int ether_rput(queue_t *q, msgb *mp); -ETHERDECL int ether_rsrv(queue_t *q); - -struct ot_module_info { - uint16 mi_idnum; - char *mi_idname; - int32 mi_minpsz; // Minimum packet size - int32 mi_maxpsz; // Maximum packet size - uint32 mi_hiwat; // Queue hi-water mark - uint32 mi_lowat; // Queue lo-water mark -}; - -static ot_module_info module_information = { - kEnetModuleID, - "SheepShaver Ethernet", - 0, - kEnetTSDU, - 6000, - 5000 -}; - -typedef int (*putp_t)(queue_t *, msgb *); -typedef int (*srvp_t)(queue_t *); -typedef int (*openp_t)(queue_t *, void *, int, int, void *); -typedef int (*closep_t)(queue_t *, int, void *); - -struct qinit { - putp_t qi_putp; - srvp_t qi_srvp; - openp_t qi_qopen; - closep_t qi_qclose; - void *qi_qadmin; - struct ot_module_info *qi_minfo; - void *qi_mstat; -}; - -static qinit read_side = { - NULL, - ether_rsrv, - ether_open, - ether_close, - NULL, - &module_information, - NULL -}; - -static qinit write_side = { - ether_wput, - NULL, - ether_open, - ether_close, - NULL, - &module_information, - NULL -}; - -struct streamtab { - struct qinit *st_rdinit; - struct qinit *st_wrinit; - struct qinit *st_muxrinit; - struct qinit *st_muxwinit; -}; - -static streamtab the_streamtab = { - &read_side, - &write_side, - NULL, - NULL -}; - -struct install_info { - struct streamtab *install_str; - uint32 install_flags; - uint32 install_sqlvl; - char *install_buddy; - void *ref_load; - uint32 ref_count; -}; - -enum { - kOTModIsDriver = 0x00000001, - kOTModUpperIsDLPI = 0x00002000, - SQLVL_MODULE = 3, -}; - -static install_info the_install_info = { - &the_streamtab, - kOTModIsDriver /*| kOTModUpperIsDLPI */, - SQLVL_MODULE, - NULL, - NULL, - 0 -}; - - -// Prototypes for exported functions -extern "C" { -#pragma export on -extern uint32 ValidateHardware(void *theID); -extern install_info* GetOTInstallInfo(); -extern uint8 InitStreamModule(void *theID); -extern void TerminateStreamModule(void); -#pragma export off -} - - -/* - * Validate that our hardware is available (always available) - */ - -uint32 ValidateHardware(void *theID) -{ - return 0; -} - - -/* - * Return pointer to install_info structure - */ - -install_info *GetOTInstallInfo(void) -{ - return &the_install_info; -} - -/* - * Init module - */ - -#ifdef BUILD_ETHER_FULL_DRIVER -asm bool NativeInitStreamModule(register void *theID) -{ - ASM_CALL_NATIVE(ETHER_INIT) -} -#else -asm uint8 InitStreamModule(register void *theID) -{ - ASM_TAIL_CALL_NATIVE(ETHER_INIT) -} -#endif - - -/* - * Terminate module - */ - -#ifdef BUILD_ETHER_FULL_DRIVER -asm void NativeTerminateStreamModule(void) -{ - ASM_CALL_NATIVE(ETHER_TERM) -} -#else -asm void TerminateStreamModule(void) -{ - ASM_TAIL_CALL_NATIVE(ETHER_TERM) -} -#endif - - -/* - * DLPI functions - */ - -#ifndef BUILD_ETHER_FULL_DRIVER -static asm int ether_open(register queue_t *rdq, register void *dev, register int flag, register int sflag, register void *creds) -{ - ASM_TAIL_CALL_NATIVE(ETHER_OPEN) -} - -static asm int ether_close(register queue_t *rdq, register int flag, register void *creds) -{ - ASM_TAIL_CALL_NATIVE(ETHER_CLOSE) -} - -static asm int ether_wput(register queue_t *q, register msgb *mp) -{ - ASM_TAIL_CALL_NATIVE(ETHER_WPUT) -} - -static asm int ether_rsrv(register queue_t *q) -{ - ASM_TAIL_CALL_NATIVE(ETHER_RSRV) -} -#endif - - -/* - * Hooks to add-on low-level functions - */ - -asm void AO_get_ethernet_address(register uint32) -{ - ASM_CALL_NATIVE(ETHER_AO_GET_HWADDR) -} - -asm void AO_enable_multicast(register uint32 addr) -{ - ASM_CALL_NATIVE(ETHER_AO_ADD_MULTI) -} - -asm void AO_disable_multicast(register uint32 addr) -{ - ASM_CALL_NATIVE(ETHER_AO_DEL_MULTI) -} - -asm void AO_transmit_packet(register uint32 mp) -{ - ASM_CALL_NATIVE(ETHER_AO_SEND_PACKET) -} diff --git a/SheepShaver/src/EthernetDriver/Ethernet.mcp b/SheepShaver/src/EthernetDriver/Ethernet.mcp deleted file mode 100644 index 6e14f02ef295d82326ff6262c91b74de8ce5dc08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103293 zcmeI52Y?mT)yHSvF5BouP%J!9K?HUe1q4K88?d-5D~m!bk!AM*3)`|qu|zi}8Z|{t zOroi#_rz2alNe$&F{W9Pn3y8AG-LftVv6DWoqO-RH}l?<2W*V6bK%VW&$(yL+>__08h_dDq8{?+p$Sh?SMq;A6KTR* z@fA7eB;6MK5b!||$(D9aR?xB+kxwaj`tD`$v6*!+=eif%43=XsqJ1{`RB1i9i_M{e zz?ZN&OhLC-{1A9L`5^QHc!qU^O)n+H zu17+o1jkrMLC1iRwT`yz3);bz;F+`+*~BT}Sr93)feo@Bqdc(D|2la&M2i#mkyjLc<@s~Ke+E}37T&W{Tm(EH zlRpcd1U?QT6^M@G6|@TK$QKy=YVw5!pHD7!Cly@H<^<}q9Qe*o52EUJ7+Dt0?6q}TSR?)5Gn+^UE`4)qJMZVSGKa;l` z{8#dA2ERnUUE^Z0e}}>NoF(-m70+VRrJz+Te%)=b_*##_(uc3nc)#4*)Osz^Zj%^- zR2$e92q=V-2{zCKmD$cX$6j{gDCEXKW1(@-c(kI^)@sE{gIE=hE0JT_|MVvWknG(r zS;gh!9=sc@&dQJ`!`cKHdoJ58B01X;Qe~3XJ|e+^U~@(}BE2K6D$#Q02;p%3QHKiV zRAX1SoZnK@(bCtK>MOsf-Sn@LQ=7Buo06-m&a7gmkV6WT3boP3f-ieCTeX0Ct7~Ji z;fn&gE!8oJvzr|Ul~O|QhWDFQx^~SPGeT%h1uNH{VTKs1u(-K< zptm*EM^V9w`i45JHOA!QOg`2nZ;z=ut+_tg(7vg+rMF!jX1R(JqZ?aVJ*Bo$GJa`o zYSX}$n7J zk}*S!D`Sp~M>5{a_%7GQ`H+nJa?RuVB-c7M?#ne~H8dNN@oElqBy=n^36imX6;ua_ z?}>MnLGz#rXgVZmG$iAfjQcXi%h)d03>iCR{Fm`g#=q@QEhN_pX^mWKW$c&h?-WSJ zei(HDlXW|KI=XvPy?bVo z`jkGbJhemOBu>N50y4BmrOb3kW?1{05?nUq!nE&6>H>{uDeoTW4^g*V%H&!j8^5xkcmN)@T|a~kKcI)y1Nd?gUjT+M2=-4^@daT2?6+4` zt*cx5+FO(B_`~L=?j6a-fsX!mYejo+Uw^VWwWTxF)o(4;^IIOLCF?tTx_kSRix!`1 zH8!nx?^d^TbaZ!jC0C_7daTCv$(o9qIdin&`eai}Uu#Q;+FP5t$ZD!v;XTw{gGGzC zTT4xKz-nqu9b4Peb!=*?vAnewj;ngIo34V{F;$Q~sH(5i+EBA*MY??1zTsysey{(qI58m9;nxYz3V@v;5l{Yse*A8^`w|AyQiNmTX_w3D? zli8O?jO85}6&O0XqUD$c?G=mLW~UVxofM{7HRWm1^W36zf=`LpdMm2dSxXyJy<1Yr zHQdKI?S`$|oz)j+*RhIetN+=X>(`vILC&A9r{*~AcTVN*bIRORu$Fo&TU%Fs#!5VC zdzK4i_`U~-RzF3;*AI4`2%xrDLp|$tSdMO-K7j9gK(21BNVU+b$>*fGN9S^M&w1)3 ztd%XDDR~1SS<~HheyW!zG}ela)DGT6NcHq~^BldeyVt62?;~72tVaA*JJK=7wP)PT z@u3V;`?vIYnkPH@;kl<}5^TPFkzdi?#i)=g@5iTIS&~&fJss_>E&c7?T@w7}Q9s&T zkM^_v4zSb}wylh`Xs+6Yuz`D}*e3RBbDHQk+^-CavPq3MIuX>=pqm8F^{k<)Hmg=xA{3SylW9dPgcJ*)!r%_`#@3C}g zMeCY4MOUiBs$ZL2)5EaVei2e;WKADs_S1(+y~P_>rnnA%t2n%k1>e&}|?|$#{;cA$; z-BvAsL(KMz&fA|p;-=lZKP7)kjnibza$y+d@ZG^nMZQkTkZ|J}+RudvsEJBhP;N->F zB4{L329-diW{Zx}%#E}@WDmFLo|IY?);6r%(7L_7P3FVvo4Hq&%Wpz$^U*8Pkx849 zZ9&!@vU(P@H2Yq|dl#)`Jog`d0@?Q@ell72DY=iOmU`}8{8Y$IrE{whR9@@8{Rk2= z_gO*3&h3d`dDcBtut@p_$ya1WBaQLx5YNq*-?8!@p*+dy;bBf-c~}#af-@U^57q;f zc5;0)=y!_jd%_TzP&3F~URZ}pd1Qx*P)LVLvD|n1)=|pL_ZtD_nfp^e0na_FpTPR| zuC>xeb6e{tvSab0P$NirNc*JNX@kl23yux#ec2AebG3+o7m1K?m*VhX7m2V?m-3K6 zm*U_scS=Ki!V&Scm{aK3%iA4N8XDdifdH>o0)C+_1tEbg#lc~nE)A}>e@M%LQ2{M7 z;o@@!%b`A@+3&#ZoupAr`zET_-ydn@Bx=v|ei`-$08+!l# z;TNP?64^nTRqPX_SrR!xnpK`1q*=vTLF!YQ9i%=Y8SD5Ix_ULMG&e|n1>D}6Esze< ztb*(y%_`0cQoqvRYP*6o>pLU`^X|5pkIV{*N*+H6h zaCVSp73T(NmOxgJ`jiH?C@V-^e@LayenFZgksYL2#XdorC6N=PS>@S5npKs1bA!}Z!0oNs0_h;lD##Aftm3R7^(zgowkt@p4)hJuEE%65^_K`~ zc2SJ|cmg<_c1u!-DOS9i&+YX9sCkac+=i31kJSPibI_f`gPlDnXQyLPaj)<>yoI?LzmD124%?Jc|s}k@FQYi=tQYj7&(sXHX zwf%!s4vY#?kqHk{mqbXjgM(BZA0DKRNMNV=2dQ&duw6oeR1OXaQYj7%QV|FaQl~Vq zMZrPpJPeJxGtJ0_1Z+kqJZv*^VZob`3JKwiP;el7WkSN)E9h%YuZX`dWMo1EJX1^ zB|`Z{mq_LlT`sxE+9MnA7&GHrB9mADh+stjh)C{pUGKS~`VSpJkB2gfJkh1?>%2LL zPv*o`u7oF|a*MNLDObW9MY-jk_{lAHM~;7~r%(JvOmFxXI(E)2&5Dp9fwXt|2Qv5^z9|Dh<}e{WJ2R1TP(oqTw;E)ktq&| zkc^Oaj^H@SNQOsCj$CBzgCobKD?EO@f)V}WA4^^pQT-PZR~bc-(S??X>xNb)a*@#` zLit3O$VEq&NJU1M2t`GgBNG{2j$ladIU-@bBQkkJS4J$8%zLr%o-3;V(2<#s1t|)NE{>0gE0G9^C@Bt) zC6Ne=A}J4vA1Mxw9H%s-PaF~7-f#;2?JT9C5t0!I@Gd3b7Zp+v5)V=w6$v5}9s@3k zkoqAN;P>kIaF2IH0i%hsryCg#DCtl}& zkD-na_i0BY(7K{M*QcGsg6$sS({gZ#PiLk|<})?**^$?)Gcx+)wonoGUlW4VC>j6O zWX|RMWg$pO)-&=TG53@5Fd5%I$<)UE)Z9;v3>{Gx6qyJMib#|N(=uTeObhXLVNiYZ zu%M`kvY;aqVnIj5zs8JMA-0p!K&we%u)Wfy!RPh&GC45RIwBBk7pK(MB2J-yoy1bX zek7%VwvfVLTck^a&+BgsIWW`~A`ol~r_|RLPN7pLY~%M0YtB_SNX~QZ4HC+}0td-? zufsu7o~vU&j3A+`VI)Y*J(z^aM6_MhIBiolRV&VVE`~V+OOTvrUH90mjummac3@kxHSp!Run0sIe zlZj}%dti|O^jSqCXJ84E^9(FOLfHdLkeqj536k;*EI~rTcl;?##xt;l3AzSrKYPic zj=uz{$$GjFE|!j%K(Wk>#jir1fh9(4xkxifoJ2W- ziY52J5_nRSML2@!a%L=k{i4cUGnN3E%)k;<7tg>FB$PF<1c|u^mN1!!wz~%wX{TS? zvL8SO$$18rAffDmB}mRYumnkY29_WpF^}UjNoEf$5pt1clH;QsL1glB1QCpI1QBs& zEPnl>%FVzcI6x*dumlNt29_Y9tbrv+%ssG#$wai>J+SaV*t@=0&Riu|!ZVoU7H1D5 zxf0$1B)8l%bmSJh2MzyHkC*t17#sN)I&qX+nl(5C38ekqM?engLODm{NW3k@C}(Uban#Z{V%miu7u9 zVYRC5ZuMMe{mv*YtlQC=Vnw^|E?GrSmbeq8evR;}o}ZkzdVUgOj_m6B$pu!=uPrhp zTm2GApa3m++W+? zLjD|7(x$L2Kb=(y>|nX2N^lvFpXO3Ob2{<@EptBnQHFm#c=V3`(e=oD5j^I6S(4ha z?+1@fb)@(yE&Kn#<4{AL6Y>*X;|*R2o}kZ_ke?ZwSl^%Gr^OPl1yAbl?x_O54}4In zs)L^&O56dS+}%}0-4c(0r?hGQOW=c9t(5Z?91cEYM}HaiC^#8BwXI|&#}>%XeI1(W zuce*^mxB+J#X!Ly0w3N#vXM3xdcGWZN;qeb70eH(;#>O zct%%SstqhZmv*Eq*a8;&9Fca4VZ@_g zevVcAK~~1H=4*c_l5-xX{h??z_;~FPMY62d0__h)qJN?8qoPlM7wLX4lD;@W`$N$# z@M6Q?4PK)Cq4)^!Qtc1LvRv7T+8>I~1uxS+P<#>iB!h1RpRCVSd>i-_?GMGj0x#G8 zQ2Z}&m9~G0{3Kkp_J_p+xkr(Ed>JRWMN@{!sED zc$M~tk{7}C+8;`#FIH=RD3w?^Rr^D!{1jh<_J>mWDZEDLI>P3S_=?v4 zWGz_w;!2sAfhF$VD2q^oZvqszebNg z3HU8~{24F)_*RHCUi4q9$Di@<0$-=cpYdM+U$4iX@jnH>O^-k0p9a5Ok3SP6E^g4{ z&xCUDJM@?^p#l6(J+xseufZRLNRtw5KBS;EX*T(X4aPsz&ySXg#!xuYz%;0a6i{FqY{ejIV6toT+N&ZQL7m$C-V6m-?DWrogVDlLTt%Ke}{#k=} zl7G(NC&q$%P9UsKSUvXT7j21~!(X0WvT8wUT7{F?@gUwupCgAXUa-QYTMu@UKD>Fb?> zz;9#o9R;m}rCxU!{B!c}8vGCPJ2gH;u0eMhTtogngHz<+H&|lrZiA(s(q_^jB72X5 z)*(-jOT9@`3)uWfL2K$v@*f*4`hQ|@3%U3=Y3k){?p4s5`eAa3E7DZ4!TkzaQ^l_y zFnBll&on-CI=Qrsbg1b6g@V?hqW?jIrT&ank`DbKn_nqt9V+&I$Y9~gIY@`T$mTZ+ zT8B*`|EXT?f8?yFOmOQ<0EE~KWXq9^1m2-0r^t~zlU7L5z-NNvUx^9>j*i| zvl>q;CV$T0Ipoh9+(a(d8`87^HZLe>O?w~tUkw&t`5J4fLgTZ+wu095E5HeZ z83XJBgYg%;&|vCfkI;C=3~-UbbzrdtX+{cMV(``AQiB;w>@tJ#O?#xl*ux&B@sX3j zGQN50(gAKkGe2Bqc08ceo^dD-l=s!&3qow|b8$2H@;|1yHQ^C^=ZU-j~z6w0u;E#i` zsidRnNBc;F@nu_LfHV{P*+(0EELg@1(#(4BEQ7azk1_Zf@N9!cKgUR#c^6pxRWLDR z&((NVF?gQANpQKr#Ijvsa4Wdd;48qiQ_?Kaf1JUhANxw0CG}sR@i8O73k}8|HhnDV zn3KRK7<>+RvB4LEml*s3@KS^C0H0{E)PI@Av+*e#U6N+gKKo>Y*Mez-q}k_#mn&$^ zz6o4q@VCI#1~VqvH5wm_@7uKoV^_P*;70HYgFC@14ZZ=q%HXeo=^IJM{u;d6;N4(+ zLed=k#m4^>rhPVg72W_o&EN~bYYe^~++^?w54lXV8;3-%cX zQ+NAJgWJIC4SqeCb4!~0KJcpyz8!p)!M_2YZSX(9^qHi2#E^Zi!Pwh=wZWqQJcHj1 z-e|DYzs2AO!J7>J7Z^X2RDKkg;}yoncFN%G;LQfV4ZOwRuYkR%R_vbY$>8@Gd@}gG2IHsp`wYGs z{C&7X1Qzvx3&5e}F%z@d<~6KV)z%_`?R{r}jq-#(p;SlXSx8!5=gD0r1BS zei8f$jTavb#zvABSA#!gFmYgi+F)#Ef5zaif~l*d#Seo&r}2^mnDa?mG6Q^z!7IRD zFj(sOMT6-d`%4Dj3jVUezXpHB;QxR*pQNRt6FG%fgTH1lF=v0>VEV_t&ERi=zhUsB z;BRVtViA}!Nhel-Z#Q@?7@w1L;`!j63R)-9SN3-dz7u?h!HBvpyO{l(y|V8#wfRc{18 zZScpy&lpTU+vt^4MP2OYG*&;8^Sr@H`2T0{3NY=IRNVpotHC#b|7I|8VE^4h4-(&Ohqgi6A@QY7s0-?bdZ5=py-*+24-G){ zvCK1Mej)P;nNP?yO0G?EO|ox>Bv#)GeGvK(^kL{m=snO!ppQZl10RPz0eun@U;8xl z8Hj6!Tr1=nA=d`ECdjo?t_N}*knvxQ`_=St4O9!&K_^315HVt{gjPW(LCc|fXf<>y z)BrU?r$K9=Cg^l%Ez}IHgNOE62rYxKsfDdAY;9p{3!7Tl z)VdkM*6MlRyU4MXdftbv)$=`Ut)Ay$YxVpNTdU`F*jhcGqrcSiHSDUMr!ju0=X2Ow zJxBW*`PU)(L_MFojr<$XH=%Dqw?p5Cc0%8Q?ts1v-3ifu)}_#8&>-|W=pyK~(B;tU zp*KJmLYF{SKvzOKvSVZp~IlVp^Z=r zv4cXJPUTOg;Ph zEBOj&CA12vhh{>vpktuf&posgC;{~Kxabhp()V85b+|UL^OE znA5W9H<_2nJ*C`B$~~mamE`_W?i=NPQRWzOuPFD3GUt)|L%A=M`$4%6l>0xKpUAzj z-2cgapUkmjjwAPda=$0{5OVJz^CY=%koyI>50U!}xnHn%Lf?VD%5h>Z{6_9aWKJgc z3NlBMd7jLVU&LC~`1Ex?ElpTOr*-qOM_4LoY;5Wc6Ue7* zIYR5|Hmoae4VUJdignG+t-b9%{egl?Pftf+xfC?6Ps-O2fii=XsLx2kE`%eKr1F-5 zKrK?Rx@v8*zEkGkDPJosM@H${(!N>bgHk?v);6!L2|7Ms{ze3cv?sRqcLv)zx>h_C z(e>HJw^$+K^r&=Lh=kG88EWRxmNc7J5O}kMntN5A_6^HjU{>-8yl*lM7cpSk<4rD zr}|4bHZ`p9FUfH8(zCv%Hgm+@p^Y52rh0WU>gdL%^^xsrYUth+r6;Oi5*Asr7L{H?LMYYR!p5a)K7~~V3 zsHF7tsV@wpL_^Elx?97iN1;dS!i{7@b*1dv+7UU9u{J>Dc-YrJFeG}Uh2 z=D_mqa1Hs4^P-`gr^S(t3pv$BQ&zr@ohEwpOhT=i$G^xP*>Px#bu5A=j8%3IINJy#8|&mPZJ1N02ykjf8xTDRskSB=#3 zN}H>?BQ6)y9M*2i<-0i>YSu*FyNgVEb{Jrz{d~?F&?>H!dp73{)FU>3x#qn2^p~p7 zD`?KkN@2$zmz0Hx0-l~tIfdl*TtB>K(>CWW2339%&XvHw%;Ba-%s?%Up0II6JvY>M z<&k>wyrM+v3B3?xo)Sds300K0ecDp{{NP!Q;GxefqV1f%qJ&-t_C!z5KG`Q-pYGl^ z$LIDocdl?@$4B+oAO|~o!aO>EJwtV+jEoDl#9&z4Rl9mqA%7*{CH(fTwW&TcbOb1C zZ>X;hC`z+kPq_mltewZx=>q~lKI51iS|0wVA1j~wC_O{aHvFX^kL!hctKXwU-XMz8zFFYB^ZNQ*WZ|;^T~cp<{qIg6pZS$wfyUSwjpo{sL`6#w?5ZuQ(Z%VFiI9Vtr=-;;x5*#p7?1FP%T9S{wP8xdPzZ!J)4 ztEthx%#YN(;D0$eDB0V_AK=IFeb*HI=bm-l-5r~{cO><%y}F)w$rBp=mq~k&&$S?H zIUhIgB>(Rw+x2WH!57!O(X0ObchCBY*FI@h&6?V}S;<+oRqLwAn(AxT&3eVxdI&36 zh!^Z@O7I0YUx^GslDZV|@#1M~POECHE3ey7=dX0Ru=z|=ZJbUN_9;7iIAmlY4E(1MWbVU&LQb9&o)IH)u~Sz%7s857+Fe zn*CQko=fh(efQs}`3SBMa*>ErfCWnAc?33+0>y#surL}d< zy|k-T^@V#s#(Qpo|K&4UQ(Ie}l8luPGi&5C&{SXfww9c~y`5Fxlx$poR+BnLMOmr( zvLd-=U@!mroQ^JW(Zbq>l^a^Ox3|epXs&POb@5{DUX<-)`k()Wd<3hmrTVw3KaG}m zwe_B#`v6I7F;pKD?2);=k9=j}r^Fr|A0!;D1qs!+X2jNtdX5Ey2@L-J1cs6 zyW0j@`}-=kwQaAMUp~Kr7oqwpT6)?mhUT2FBrP}3u6o9{W;9nWv+l${2UXo>KX{As zKf8s+{*L}!<+L-_DE}*&w#?GJcMGqgY}F2{w0f43x+=}FS6A4h&fHmR)$gpZq-^F_ z(`5Bi zoikZUPG%Oz!~HmUEx<@w?AXP1MSSJ`Va8QCZwutQVhYEYfj?N*eW;d_tAyv860a^3 z@PfaxUA($XKI{C%tIN0pEsY03L-mEMD2-Q_5i9IX+Q>oi>N2waRq(1g@#->j<^)@3 z55KPpc|@kZ|7eZ;jwE#T6o~+R zl%AJ+t{PCEJ)Wxu=ouu`oH=h;&qvuOqvw@2SM`o1*?X8JUR@^JD6W0ioHxLO;?-qb z=E{K^4QD7;RE$@b$uX~skshG}*Q{`^aG@81%-wyoo=`=3*C$?G#&?aQ^c5~%UB>0* z88`@3SMG>~=<&mNb(xIWa**o|BqZX8aNV;5adnxY`L-~pZ(_#&V}W=LlKrQzUdc6$ z*C2T%_fA~5m&F3{`VVO{5Bv2WUcS{9)G`fe!w+kq-g}Jgk@f*)j}fw)LFvL6#1_ym z3deScEf8BE+yV!sL#04}O6%;)9d!7iap{3>f#Lpnmle-34s;ja`}R2l<=$(EkBlua z94rveF@{4g?`0c@{Tw6gIx+#HZZRLbHtX4lwa$`tNLe(-tf6|QDPM2Ox0?M8X8%>z zXeED^*+0+Z8_hSkn@!%rXT_2>sl{_FtJTQ08GR|0yO(Hi*W7kJp7LO&Gv34&h%FFX zVE9_VwO~Q%>gw)+uC}V6?-kQagUL&0EMz9@3h!oFjP>=W)piYZgul`}d@UTee7IS_ zJ^vVPZI9cVu|UwAG$RqC*aEQyVhao(3%KvWb6f4VfLQR=)IGlPu)r(?tJd9(r?t7p zjXALe_Qe9hfw(VP<74+f3plG^ibu#uE6-TvPtrw@JggPoND6K1*3CP?`X{dR<6+qy znlwafG!9K=VlA-+Vhil|7LZ4qPAZ&#rByip6J}Qy_kO;|r#z_^_n!8Z9?F}XVF z+*k^_^N^E4qbCo!@yH#Vk#lBQ-qUkl`Rn^@@{p4WS3d2?S8gQwW(S-%V_C6e|?U>v{f4WEm!t( zhl#RhYU8K*>0R2JRC4Nh5PRaGPd~g%?ER#r-c>=*-!4hpI()tub&X;n0I7xkb5Kys_mP?o0&sw)`U9RfsD5ESb z=kPqa=-;gT3$?eH_Nq##lZb9Pr%Lv9qTkV{eiA2LmQl(*TwdcJa(Rt^$c;mL1|hsS+3&5XcmL^mUeAP*0i*4 zO)afWZ5r6Z4>EV8lGSx}wbeD%b+wcUMv?Wx{m^M!r=*LJ#V z9pl&n`)YwY*yYylq&xaOTcr7z>v7@|DlC zm09IYg_SGDsjqyFJ!GepJI6{c$Gi7qJTw-Fzw)Vi#RcAkVi}FAB zS3cr@@mD^3_?3^m#TDNn4NauRT4D>t7TC`%5Z@u~=N%YVKeoWoS-^7#6t9CYbcP*5 zP4OL)>kestybi*u^%WKNq!w0Wo_k4!+z*wk>bAzo{;W-v(-db9)inJ|F%egYY}N{OitR@d@E~dHMD+>>mTa-OE4h0a;X9>o53Yrp#`V zb)~d^H^1yNQbDcX%`d(!quojrY=*Ug`aeF_(J_HUv7ZhonJ@3OP0p|9U6 zI9=K>P1k7@=e5dvdQ+RNg7>@wJWumSvm$n3z2+}`R%A54xI**CpH6<1 z<`+!_FE#uD@-odoXA1a4!@rFDZJPfMky)ns6XdJu)rz0EM?S$hN%M;@Ay0Pp_esBG zW_NZS{W8Mp?Ca&#KNNhvaN(cL#@Oef=fD>T*RrO3j*YR; z6zP*4!ev2?7v6_*U_w@ST2i@yjM@zUoI8zgX;3qW$W$FY>fx3Hzkt zjci6KzWsB2+cth%CiXG%)eZ2g*(a5q!^X%zhi}<6ifxr`B{%Z7u7H24;rFEF6Eil# zN0+2B@n<9dN$PCN`AFpturd1odK3IJ6x*6}Jo!{r&xT)r7XHPWf8)c9CmS^X8NM8| zMK9?CC%~Vi_>EWn3I1y}|D)9Fh;f=f4xRR;nm?xzT&(%W;(PXGnqMOJ(0Ura*$jVB z^NVjG*Z$D>_K(7Uo#vMscj7zt+cdv?kX(-s4G+Ew{@XSGr=<*o#%@cB;NM{6v6VGL*WZ2| zzKQpFe}QlO>I`gPn|QzPAozM5XgnI-wu$%qJ`R7IuFv;2!k2y}6+h2L`*Y)aPlJD} zVq5n!{u_U8+38_M@#lue8o}St{Dve}3x>_}?;oDK~z2J2tj&H~f3R#-Fb#0DoKacil^_{kd@ob+dPB ze#t0ut*7ChbKrkR^B<8uHU9kV0q`A)Z=Y~5x$c*SyT$(B)$))2ja>V4<6LZI->KzG zv4`W&=Zc=Yw0ubux$)=ESHb_D=0A1}x$);0rCr}weEXyla^ufWJ_Y}7!(UEr{JHo! z_&-p5t7IyfH=aU_*gsW#dwglepJ&OKBmF^oVigDzIlw&+u=&2>yQz z9~no!`APV@72hhIl;O`y(nig;XVoze)YsFS)(*h8Re?RX5&k*Ko;R)eFnoQ0J^zzw zJvSZkX872PWY7OfM$c#P;Y6Y4pKw%0Pw6A@=>w5pB;$l`*G;e61fMZf(i7X*==v;r z;C%SSifx}neG0XoEZRbhCnVlTPYl9OsCq8Cjj=O #define bug printf #endif /* DEBUG_H */ \ No newline at end of file diff --git a/SheepShaver/src/EthernetDriver/ether.cpp b/SheepShaver/src/EthernetDriver/ether.cpp deleted file mode 100644 index 7382ad4f..00000000 --- a/SheepShaver/src/EthernetDriver/ether.cpp +++ /dev/null @@ -1,1738 +0,0 @@ -/* - * ether.cpp - SheepShaver Ethernet Device Driver (DLPI) - * - * SheepShaver (C) 1997-2005 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * TODO - * - 802.2 TEST/XID - * - MIB statistics - */ - -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "ether.h" -#include "ether_defs.h" -#include "macos_util.h" - -#define DEBUG 0 -#include "debug.h" - -// Packet types -enum { - kPktDIX = 0, - kPkt8022SAP = 1, - kPkt8022GroupSAP = 2, - kPkt8022SNAP = 3, - kPktIPX = 4, - kPktUnknown = 5 -}; - - -/* - * Stream private data structure - */ - -static const int kGroupSAPMapSize = 128/32; // Number of 32-bit values we need for 128 bits -static const int kGSshift = 6; -static const int kGSmask = 0x1F; - -struct multicast_node { - nw_multicast_node_p next; - uint8 addr[kEnetPhysicalAddressLength]; -}; - -struct DLPIStream { - void SetGroupSAP(uint8 sap) - { - group_sap[sap >> kGSshift] |= (1L << ((sap >> 1) & kGSmask)); - } - - void ClearGroupSAP(uint8 sap) - { - group_sap[sap >> kGSshift] &= ~(1L << ((sap >> 1) & kGSmask)); - } - - void ClearAllGroupSAPs(void) - { - for (int i=0; i> kGSshift] & (1L << ((sap >> 1) & kGSmask)); - } - - void AddMulticast(uint8 *addr) - { - multicast_node *n = (multicast_node *)Mac2HostAddr(Mac_sysalloc(sizeof(multicast_node))); - memcpy(n->addr, addr, kEnetPhysicalAddressLength); - n->next = multicast_list; - multicast_list = n; - } - - void RemoveMulticast(uint8 *addr) - { - multicast_node *p = multicast_list; - while (p) { - if (memcmp(addr, p->addr, kEnetPhysicalAddressLength) == 0) - goto found; - p = p->next; - } - return; - found: - multicast_node *q = (multicast_node *)&multicast_list; - while (q) { - if (q->next == p) { - q->next = p->next; - Mac_sysfree(Host2MacAddr((uint8 *)p)); - return; - } - q = q->next; - } - } - - uint8 *IsMulticastRegistered(uint8 *addr) - { - multicast_node *n = multicast_list; - while (n) { - if (memcmp(addr, n->addr, kEnetPhysicalAddressLength) == 0) - return n->addr; - n = n->next; - } - return NULL; - } - - nw_uint32 minor_num; // Minor device number of this stream - nw_uint32 dlpi_state; // DLPI state of this stream - nw_uint32 flags; // Flags - nw_uint16 dlsap; // SAP bound to this stream - nw_bool framing_8022; // Using 802.2 framing? This is only used to report the MAC type for DL_INFO_ACK and can be set with an ioctl() call - nw_bool raw_mode; // Using raw mode? Header is treated as data - nw_queue_p rdq; // Read queue for this stream - nw_uint32 group_sap[kGroupSAPMapSize]; // Map of bound group SAPs - uint8 snap[k8022SNAPLength]; // SNAP bound to this stream - nw_multicast_node_p multicast_list; // List of enabled multicast addresses -}; - -// Hack to make DLPIStream list initialization early to NULL (do we really need this?) -struct DLPIStreamInit { - DLPIStreamInit(nw_DLPIStream_p *dlpi_stream_p) { *dlpi_stream_p = NULL; } -}; - -// Stream flags -enum { - kSnapStream = 0x00000001, - kAcceptMulticasts = 0x00000002, - kAcceptAll8022Packets = 0x00000004, - kFastPathMode = 0x00000008 -}; - -// List of opened streams (used internally by OpenTransport) -static nw_DLPIStream_p dlpi_stream_list; -static DLPIStreamInit dlpi_stream_init(&dlpi_stream_list); - -// Are we open? -bool ether_driver_opened = false; - -// Our ethernet hardware address -static uint8 hardware_address[6] = {0, 0, 0, 0, 0, 0}; - -// Statistics -int32 num_wput = 0; -int32 num_error_acks = 0; -int32 num_tx_packets = 0; -int32 num_tx_raw_packets = 0; -int32 num_tx_normal_packets = 0; -int32 num_tx_buffer_full = 0; -int32 num_rx_packets = 0; -int32 num_ether_irq = 0; -int32 num_unitdata_ind = 0; -int32 num_rx_fastpath = 0; -int32 num_rx_no_mem = 0; -int32 num_rx_dropped = 0; -int32 num_rx_stream_not_ready = 0; -int32 num_rx_no_unitdata_mem = 0; - - -// Function pointers of imported functions -typedef mblk_t *(*allocb_ptr)(size_t size, int pri); -static uint32 allocb_tvect = 0; -mblk_t *allocb(size_t arg1, int arg2) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2)); -} -typedef void (*freeb_ptr)(mblk_t *); -static uint32 freeb_tvect = 0; -static inline void freeb(mblk_t *arg1) -{ - CallMacOS1(freeb_ptr, freeb_tvect, arg1); -} -typedef int16 (*freemsg_ptr)(mblk_t *); -static uint32 freemsg_tvect = 0; -static inline int16 freemsg(mblk_t *arg1) -{ - return (int16)CallMacOS1(freemsg_ptr, freemsg_tvect, arg1); -} -typedef mblk_t *(*copyb_ptr)(mblk_t *); -static uint32 copyb_tvect = 0; -static inline mblk_t *copyb(mblk_t *arg1) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(copyb_ptr, copyb_tvect, arg1)); -} -typedef mblk_t *(*dupmsg_ptr)(mblk_t *); -static uint32 dupmsg_tvect = 0; -static inline mblk_t *dupmsg(mblk_t *arg1) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1)); -} -typedef mblk_t *(*getq_ptr)(queue_t *); -static uint32 getq_tvect = 0; -static inline mblk_t *getq(queue_t *arg1) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(getq_ptr, getq_tvect, arg1)); -} -typedef int (*putq_ptr)(queue_t *, mblk_t *); -static uint32 putq_tvect = 0; -static inline int putq(queue_t *arg1, mblk_t *arg2) -{ - return (int)CallMacOS2(putq_ptr, putq_tvect, arg1, arg2); -} -typedef int (*putnext_ptr)(queue_t *, mblk_t *); -static uint32 putnext_tvect = 0; -static inline int putnext(queue_t *arg1, mblk_t *arg2) -{ - return (int)CallMacOS2(putnext_ptr, putnext_tvect, arg1, arg2); -} -typedef int (*putnextctl1_ptr)(queue_t *, int type, int c); -static uint32 putnextctl1_tvect = 0; -static inline int putnextctl1(queue_t *arg1, int arg2, int arg3) -{ - return (int)CallMacOS3(putnextctl1_ptr, putnextctl1_tvect, arg1, arg2, arg3); -} -typedef int (*canputnext_ptr)(queue_t *); -static uint32 canputnext_tvect = 0; -static inline int canputnext(queue_t *arg1) -{ - return (int)CallMacOS1(canputnext_ptr, canputnext_tvect, arg1); -} -typedef int (*qreply_ptr)(queue_t *, mblk_t *); -static uint32 qreply_tvect = 0; -static inline int qreply(queue_t *arg1, mblk_t *arg2) -{ - return (int)CallMacOS2(qreply_ptr, qreply_tvect, arg1, arg2); -} -typedef void (*flushq_ptr)(queue_t *, int flag); -static uint32 flushq_tvect = 0; -static inline void flushq(queue_t *arg1, int arg2) -{ - CallMacOS2(flushq_ptr, flushq_tvect, arg1, arg2); -} -typedef int (*msgdsize_ptr)(const mblk_t *); -static uint32 msgdsize_tvect = 0; -static inline int msgdsize(const mblk_t *arg1) -{ - return (int)CallMacOS1(msgdsize_ptr, msgdsize_tvect, arg1); -} -typedef void (*otenterint_ptr)(void); -static uint32 otenterint_tvect = 0; -void OTEnterInterrupt(void) -{ - CallMacOS(otenterint_ptr, otenterint_tvect); -} -typedef void (*otleaveint_ptr)(void); -static uint32 otleaveint_tvect = 0; -void OTLeaveInterrupt(void) -{ - CallMacOS(otleaveint_ptr, otleaveint_tvect); -} -typedef int (*mi_open_comm_ptr)(DLPIStream **mi_opp_orig, size_t size, queue_t *q, void *dev, int flag, int sflag, void *credp); -static uint32 mi_open_comm_tvect = 0; -static inline int mi_open_comm(DLPIStream **arg1, size_t arg2, queue_t *arg3, void *arg4, int arg5, int arg6, void *arg7) -{ - return (int)CallMacOS7(mi_open_comm_ptr, mi_open_comm_tvect, arg1, arg2, arg3, arg4, arg5, arg6, arg7); -} -typedef int (*mi_close_comm_ptr)(DLPIStream **mi_opp_orig, queue_t *q); -static uint32 mi_close_comm_tvect = 0; -static inline int mi_close_comm(DLPIStream **arg1, queue_t *arg2) -{ - return (int)CallMacOS2(mi_close_comm_ptr, mi_close_comm_tvect, arg1, arg2); -} -typedef DLPIStream *(*mi_next_ptr_ptr)(DLPIStream *); -static uint32 mi_next_ptr_tvect = 0; -static inline DLPIStream *mi_next_ptr(DLPIStream *arg1) -{ - return (DLPIStream *)Mac2HostAddr((uint32)CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1)); -} -#ifdef USE_ETHER_FULL_DRIVER -typedef void (*ether_dispatch_packet_ptr)(uint32 p, uint32 size); -static uint32 ether_dispatch_packet_tvect = 0; -#endif - -// Prototypes -static void ether_ioctl(DLPIStream *the_stream, queue_t* q, mblk_t* mp); -static void ether_flush(queue_t* q, mblk_t* mp); -static mblk_t *build_tx_packet_header(DLPIStream *the_stream, mblk_t *mp, bool fast_path); -static void transmit_packet(mblk_t *mp); -static void DLPI_error_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim, uint32 err, uint32 uerr); -static void DLPI_ok_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim); -static void DLPI_info(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_phys_addr(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_subs_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_subs_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp); - - -/* - * Initialize ethernet stream module - */ - -static uint8 InitStreamModuleImpl(void *theID) -{ - D(bug("InitStreamModule\n")); - - // Don't re-open if already open - if (ether_driver_opened) - return true; - ether_driver_opened = false; - - // Import functions from OTKernelLib - allocb_tvect = FindLibSymbol("\013OTKernelLib", "\006allocb"); - D(bug("allocb TVECT at %08lx\n", allocb_tvect)); - if (allocb_tvect == 0) - return false; - freeb_tvect = FindLibSymbol("\013OTKernelLib", "\005freeb"); - D(bug("freeb TVECT at %08lx\n", freeb_tvect)); - if (freeb_tvect == 0) - return false; - freemsg_tvect = FindLibSymbol("\013OTKernelLib", "\007freemsg"); - D(bug("freemsg TVECT at %08lx\n", freemsg_tvect)); - if (freemsg_tvect == 0) - return false; - copyb_tvect = FindLibSymbol("\013OTKernelLib", "\005copyb"); - D(bug("copyb TVECT at %08lx\n", copyb_tvect)); - if (copyb_tvect == 0) - return false; - dupmsg_tvect = FindLibSymbol("\013OTKernelLib", "\006dupmsg"); - D(bug("dupmsg TVECT at %08lx\n", dupmsg_tvect)); - if (dupmsg_tvect == 0) - return false; - getq_tvect = FindLibSymbol("\013OTKernelLib", "\004getq"); - D(bug("getq TVECT at %08lx\n", getq_tvect)); - if (getq_tvect == 0) - return false; - putq_tvect = FindLibSymbol("\013OTKernelLib", "\004putq"); - D(bug("putq TVECT at %08lx\n", putq_tvect)); - if (putq_tvect == 0) - return false; - putnext_tvect = FindLibSymbol("\013OTKernelLib", "\007putnext"); - D(bug("putnext TVECT at %08lx\n", putnext_tvect)); - if (putnext_tvect == 0) - return false; - putnextctl1_tvect = FindLibSymbol("\013OTKernelLib", "\013putnextctl1"); - D(bug("putnextctl1 TVECT at %08lx\n", putnextctl1_tvect)); - if (putnextctl1_tvect == 0) - return false; - canputnext_tvect = FindLibSymbol("\013OTKernelLib", "\012canputnext"); - D(bug("canputnext TVECT at %08lx\n", canputnext_tvect)); - if (canputnext_tvect == 0) - return false; - qreply_tvect = FindLibSymbol("\013OTKernelLib", "\006qreply"); - D(bug("qreply TVECT at %08lx\n", qreply_tvect)); - if (qreply_tvect == 0) - return false; - flushq_tvect = FindLibSymbol("\013OTKernelLib", "\006flushq"); - D(bug("flushq TVECT at %08lx\n", flushq_tvect)); - if (flushq_tvect == 0) - return false; - msgdsize_tvect = FindLibSymbol("\013OTKernelLib", "\010msgdsize"); - D(bug("msgdsize TVECT at %08lx\n", msgdsize_tvect)); - if (msgdsize_tvect == 0) - return false; - otenterint_tvect = FindLibSymbol("\017OTKernelUtilLib", "\020OTEnterInterrupt"); - D(bug("OTEnterInterrupt TVECT at %08lx\n", otenterint_tvect)); - if (otenterint_tvect == 0) - return false; - otleaveint_tvect = FindLibSymbol("\017OTKernelUtilLib", "\020OTLeaveInterrupt"); - D(bug("OTLeaveInterrupt TVECT at %08lx\n", otleaveint_tvect)); - if (otleaveint_tvect == 0) - return false; - mi_open_comm_tvect = FindLibSymbol("\013OTKernelLib", "\014mi_open_comm"); - D(bug("mi_open_comm TVECT at %08lx\n", mi_open_comm_tvect)); - if (mi_open_comm_tvect == 0) - return false; - mi_close_comm_tvect = FindLibSymbol("\013OTKernelLib", "\015mi_close_comm"); - D(bug("mi_close_comm TVECT at %08lx\n", mi_close_comm_tvect)); - if (mi_close_comm_tvect == 0) - return false; - mi_next_ptr_tvect = FindLibSymbol("\013OTKernelLib", "\013mi_next_ptr"); - D(bug("mi_next_ptr TVECT at %08lx\n", mi_next_ptr_tvect)); - if (mi_next_ptr_tvect == 0) - return false; - -#ifndef USE_ETHER_FULL_DRIVER - // Initialize stream list (which might be leftover) - dlpi_stream_list = NULL; - - // Ask add-on for ethernet hardware address - AO_get_ethernet_address(Host2MacAddr(hardware_address)); -#endif - - // Yes, we're open - ether_driver_opened = true; - return true; -} - -uint8 InitStreamModule(void *theID) -{ - // Common initialization code - bool net_open = InitStreamModuleImpl(theID); - - // Call InitStreamModule() in native side -#ifdef BUILD_ETHER_FULL_DRIVER - extern bool NativeInitStreamModule(void *); - if (!NativeInitStreamModule((void *)ether_dispatch_packet)) - net_open = false; -#endif - - // Import functions from the Ethernet driver -#ifdef USE_ETHER_FULL_DRIVER - ether_dispatch_packet_tvect = (uintptr)theID; - D(bug("ether_dispatch_packet TVECT at %08lx\n", ether_dispatch_packet_tvect)); - if (ether_dispatch_packet_tvect == 0) - net_open = false; -#endif - - return net_open; -} - - -/* - * Terminate ethernet stream module - */ - -static void TerminateStreamModuleImpl(void) -{ - D(bug("TerminateStreamModule\n")); - -#ifndef USE_ETHER_FULL_DRIVER - // This happens sometimes. I don't know why. - if (dlpi_stream_list != NULL) - printf("FATAL: TerminateStreamModule() called, but streams still open\n"); -#endif - - // Sorry, we're closed - ether_driver_opened = false; -} - -void TerminateStreamModule(void) -{ - // Common termination code - TerminateStreamModuleImpl(); - - // Call TerminateStreamModule() in native side -#ifdef BUILD_ETHER_FULL_DRIVER - extern void NativeTerminateStreamModule(void); - NativeTerminateStreamModule(); -#endif -} - - -/* - * Open new stream - */ - -int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds) -{ - D(bug("ether_open(%p,%p,%d,%d,%p)\n", rdq, dev, flag, sflag, creds)); - - // Return if driver was closed - if (!ether_driver_opened) { - printf("FATAL: ether_open(): Ethernet driver not opened\n"); - return MAC_ENXIO; - } - - // If we're being reopened, just return - if (rdq->q_ptr != NULL) - return 0; - - // Allocate DLPIStream structure - int err = mi_open_comm((DLPIStream **)&dlpi_stream_list, sizeof(DLPIStream), rdq, dev, flag, sflag, creds); - if (err) - return err; - DLPIStream *the_stream = (DLPIStream *)rdq->q_ptr; - the_stream->rdq = rdq; - the_stream->dlpi_state = DL_UNBOUND; - the_stream->flags = 0; - the_stream->dlsap = 0; - the_stream->framing_8022 = false; - the_stream->raw_mode = false; - the_stream->multicast_list = NULL; - return 0; -} - - -/* - * Close stream - */ - -int ether_close(queue_t *rdq, int flag, void *creds) -{ - D(bug("ether_close(%p,%d,%p)\n", rdq, flag, creds)); - - // Return if driver was closed - if (!ether_driver_opened) { - printf("FATAL: ether_close(): Ethernet driver not opened\n"); - return MAC_ENXIO; - } - - // Get stream - DLPIStream *the_stream = (DLPIStream *)rdq->q_ptr; - - // Don't close if never opened - if (the_stream == NULL) - return 0; - - // Disable all registered multicast addresses - while (the_stream->multicast_list) { - AO_disable_multicast(Host2MacAddr(the_stream->multicast_list->addr)); - the_stream->RemoveMulticast(the_stream->multicast_list->addr); - } - the_stream->multicast_list = NULL; - - // Delete the DLPIStream - return mi_close_comm((DLPIStream **)&dlpi_stream_list, rdq); -} - - -/* - * Put something on the write queue - */ - -int ether_wput(queue_t *q, mblk_t *mp) -{ - D(bug("ether_wput(%p,%p)\n", q, mp)); - - // Return if driver was closed - if (!ether_driver_opened) { - printf("FATAL: ether_wput(): Ethernet driver not opened\n"); - return MAC_ENXIO; - } - - // Get stream - DLPIStream *the_stream = (DLPIStream *)q->q_ptr; - if (the_stream == NULL) - return MAC_ENXIO; - - D(bug(" db_type %d\n", (int)mp->b_datap->db_type)); - switch (mp->b_datap->db_type) { - - case M_DATA: - // Transmit raw packet - D(bug(" raw packet\n")); - num_tx_raw_packets++; - transmit_packet(mp); - break; - - case M_PROTO: - case M_PCPROTO: { - union DL_primitives *dlp = (union DL_primitives *)(void *)mp->b_rptr; - uint32 prim = dlp->dl_primitive; - D(bug(" dl_primitive %d\n", prim)); - switch (prim) { - case DL_UNITDATA_REQ: - // Transmit normal packet - num_tx_normal_packets++; - DLPI_unit_data(the_stream, q, mp); - break; - - case DL_INFO_REQ: - DLPI_info(the_stream, q, mp); - break; - - case DL_PHYS_ADDR_REQ: - DLPI_phys_addr(the_stream, q, mp); - break; - - case DL_BIND_REQ: - DLPI_bind(the_stream, q, mp); - break; - - case DL_UNBIND_REQ: - DLPI_unbind(the_stream, q, mp); - break; - - case DL_SUBS_BIND_REQ: - DLPI_subs_bind(the_stream, q, mp); - break; - - case DL_SUBS_UNBIND_REQ: - DLPI_subs_unbind(the_stream, q, mp); - break; - - case DL_ENABMULTI_REQ: - DLPI_enable_multi(the_stream, q, mp); - break; - - case DL_DISABMULTI_REQ: - DLPI_disable_multi(the_stream, q, mp); - break; - - default: - D(bug("WARNING: ether_wsrv(): Unknown primitive\n")); - DLPI_error_ack(the_stream, q, mp, prim, DL_NOTSUPPORTED, 0); - break; - } - break; - } - - case M_IOCTL: - ether_ioctl(the_stream, q, mp); - break; - - case M_FLUSH: - ether_flush(q, mp); - break; - - default: - D(bug("WARNING: ether_wput(): Unknown message type\n")); - freemsg(mp); - break; - } - num_wput++; - return 0; -} - - -/* - * Dequeue and process messages from the read queue - */ - -int ether_rsrv(queue_t *q) -{ - mblk_t *mp; - while ((mp = getq(q)) != NULL) { - if (canputnext(q)) - putnext(q, mp); - else { - freemsg(mp); - flushq(q, FLUSHDATA); - break; - } - } - return 0; -} - - -/* - * Handle ioctl calls - */ - -static void ether_ioctl(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - struct iocblk *ioc = (struct iocblk *)(void *)mp->b_rptr; - D(bug(" ether_ioctl(%p,%p) cmd %d\n", q, mp, (int)ioc->ioc_cmd)); - - switch (ioc->ioc_cmd) { - - case I_OTSetFramingType: { // Toggles what the general info primitive returns for dl_mac_type in dl_info_ack_t structure - mblk_t *info_mp = mp->b_cont; - if (info_mp == NULL || ((info_mp->b_wptr - info_mp->b_rptr) != sizeof(uint32))) { - ioc->ioc_error = MAC_EINVAL; - goto ioctl_error; - } - uint32 framing_type = ntohl(*(uint32 *)(void *)info_mp->b_rptr); - D(bug(" I_OTSetFramingType type %d\n", framing_type)); - if (framing_type != kOTGetFramingValue) - the_stream->framing_8022 = (framing_type == kOTFraming8022); - mp->b_cont = NULL; - freemsg(info_mp); - if (the_stream->framing_8022) - ioc->ioc_rval = kOTFraming8022; - else - ioc->ioc_rval = kOTFramingEthernet; - goto ioctl_ok; - } - - case DL_IOC_HDR_INFO: { // Special Mentat call, for fast transmits - D(bug(" DL_IOC_HDR_INFO\n")); - mblk_t *info_mp = mp->b_cont; - - // Copy DL_UNITDATA_REQ block - mblk_t *unitdata_mp = copyb(info_mp); - if (unitdata_mp == NULL) { - ioc->ioc_error = MAC_ENOMEM; - goto ioctl_error; - } - unitdata_mp->b_datap->db_type = M_PROTO; - - // Construct header (converts DL_UNITDATA_REQ -> M_DATA) - mblk_t *header_mp = build_tx_packet_header(the_stream, unitdata_mp, true); - - if (header_mp == NULL) { - // Could not allocate a message block large enough - ioc->ioc_error = MAC_ENOMEM; - goto ioctl_error; - } - - // Attach header block at the end - mp->b_cont->b_cont = header_mp; - the_stream->flags |= kFastPathMode; - goto ioctl_ok; - } - - case I_OTSetRawMode: { - mblk_t *info_mp = mp->b_cont; - dl_recv_control_t *dlrc; - if (info_mp == NULL || ((info_mp->b_wptr - info_mp->b_rptr) != sizeof(dlrc->dl_primitive))) { - ioc->ioc_error = MAC_EINVAL; - goto ioctl_error; - } - dlrc = (dl_recv_control_t *)(void *)info_mp->b_rptr; - D(bug(" I_OTSetRawMode primitive %d\n", (int)dlrc->dl_primitive)); - the_stream->raw_mode = true; - goto ioctl_ok; - } - - default: - D(bug("WARNING: Unknown ether_ioctl() call\n")); - ioc->ioc_error = MAC_EINVAL; - goto ioctl_error; - } - -ioctl_ok: - ioc->ioc_count = 0; - for (mblk_t *mp1 = mp; (mp1 = mp1->b_cont) != NULL;) - ioc->ioc_count += mp1->b_wptr - mp1->b_rptr; - ioc->ioc_error = 0; - mp->b_datap->db_type = M_IOCACK; - qreply(q, mp); - return; - -ioctl_error: - mp->b_datap->db_type = M_IOCNAK; - qreply(q, mp); - return; -} - - -/* - * Flush call, send it up to the read side of the stream - */ - -static void ether_flush(queue_t* q, mblk_t* mp) -{ - D(bug(" ether_flush(%p,%p)\n", q, mp)); - - uint8 *rptr = mp->b_rptr; - if (*rptr & FLUSHW) - flushq(q, FLUSHALL); - if (*rptr & FLUSHR) { - flushq(RD(q), FLUSHALL); - *rptr &= ~FLUSHW; - qreply(q, mp); - } else - freemsg(mp); -} - - -/* - * Classify packet into the different types of protocols - */ - -static uint16 classify_packet_type(uint16 primarySAP, uint16 secondarySAP) -{ - if (primarySAP >= kMinDIXSAP) - return kPktDIX; - - if ((primarySAP == kIPXSAP) && (secondarySAP == kIPXSAP)) - return kPktIPX; - - if (primarySAP == kSNAPSAP) - return kPkt8022SNAP; - - if (primarySAP <= k8022GlobalSAP) - return kPkt8022SAP; - - return kPktUnknown; -} - - -/* - * Check if the address is a multicast, broadcast or standard address - */ - -static int32 get_address_type(uint8 *addr) -{ - if (addr[0] & 1) { // Multicast/broadcast flag - if (OTIs48BitBroadcastAddress(addr)) - return keaBroadcast; - else - return keaMulticast; - } else - return keaStandardAddress; -} - - -/* - * Reuse a message block, make room for more data - */ - -static mblk_t *reuse_message_block(mblk_t *mp, uint16 needed_size) -{ - mblk_t *nmp; - - if ((mp->b_datap->db_ref == 1) && ((mp->b_datap->db_lim - mp->b_datap->db_base) >= needed_size)) { - mp->b_datap->db_type = M_DATA; - mp->b_rptr = mp->b_datap->db_base; - mp->b_wptr = mp->b_datap->db_base + needed_size; - } else { - nmp = mp->b_cont; // Grab the M_DATA blocks - mp->b_cont = NULL; // Detach the M_(PC)PROTO - freemsg(mp); // Free the M_(PC)PROTO - mp = nmp; // Point to the M_DATA blocks - - // Try to get space on the first M_DATA block - if (mp && (mp->b_datap->db_ref == 1) && ((mp->b_rptr - mp->b_datap->db_base) >= needed_size)) - mp->b_rptr -= needed_size; - else { - // Try to allocate a new message - if ((nmp = allocb(needed_size, BPRI_HI)) == NULL) { - // Could not get a new message block so lets forget about the message altogether - freemsg(mp); // Free the original M_DATA portion of the message - mp = NULL; // Indicates the reuse failed - } else { - nmp->b_cont = mp; // Attach the new message block as the head - nmp->b_wptr += needed_size; - mp = nmp; - } - } - } - - return mp; -} - - -/* - * Built header for packet to be transmitted (convert DL_UNITDATA_REQ -> M_DATA) - * The passed-in message has the header info in the first message block and the data - * in the following blocks - */ - -static mblk_t *build_tx_packet_header(DLPIStream *the_stream, mblk_t *mp, bool fast_path) -{ - // Only handle unit_data requests - dl_unitdata_req_t *req = (dl_unitdata_req_t *)(void *)mp->b_rptr; - if (req->dl_primitive != DL_UNITDATA_REQ) { - freemsg(mp); - return NULL; - } - - // Extract destination address and its length - uint8 *destAddrOrig = ((uint8 *)req) + req->dl_dest_addr_offset; - uint32 destAddrLen = req->dl_dest_addr_length; - uint8 ctrl = 0x03; - - // Extract DLSAP - uint16 dlsap; - switch (destAddrLen) { - case kEnetPhysicalAddressLength: - dlsap = the_stream->dlsap; - break; - case kEnetAndSAPAddressLength: - dlsap = ntohs(*(uint16 *)(destAddrOrig + kEnetPhysicalAddressLength)); - break; - case kEnetPhysicalAddressLength + k8022DLSAPLength + k8022SNAPLength: // SNAP SAP - dlsap = ntohs(*(uint16 *)(destAddrOrig + kEnetPhysicalAddressLength)); - break; - default: - dlsap = the_stream->dlsap; - break; - } - - // Extract data size (excluding header info) and packet type - uint16 datasize = msgdsize(mp); - uint16 packetType = classify_packet_type(the_stream->dlsap, dlsap); - - // Calculate header size and protocol type/size field - uint16 hdrsize, proto; - switch (packetType) { - case kPktDIX: - hdrsize = kEnetPacketHeaderLength; - proto = dlsap; - break; - case kPkt8022SAP: - hdrsize = kEnetPacketHeaderLength + k8022BasicHeaderLength; - if (fast_path) - proto = 0; - else - proto = datasize + k8022BasicHeaderLength; - break; - case kPkt8022SNAP: - hdrsize = kEnetPacketHeaderLength + k8022SNAPHeaderLength; - if (fast_path) - proto = 0; - else - proto = datasize + k8022SNAPHeaderLength; - break; - case kPktIPX: - hdrsize = kEnetPacketHeaderLength; - if (fast_path) - proto = 0; - else - proto = datasize; - break; - default: - hdrsize = kEnetPacketHeaderLength; - proto = dlsap; - break; - } - - // We need to copy the dest address info in the message before we can reuse it - uint8 destAddrCopy[kMaxBoundAddrLength]; - memcpy(destAddrCopy, destAddrOrig, destAddrLen); - - // Resize header info in message block - if ((mp = reuse_message_block(mp, hdrsize)) == NULL) - return NULL; - struct T8022FullPacketHeader *packetHeader = (struct T8022FullPacketHeader *)(void *)mp->b_rptr; - - // Set protocol type/size field - packetHeader->fEnetPart.fProto = proto; - - // Set destination ethernet address - OTCopy48BitAddress(destAddrCopy, packetHeader->fEnetPart.fDestAddr); - - // Set other header fields - switch (packetType) { - case kPkt8022SAP: - packetHeader->f8022Part.fDSAP = (uint8)dlsap; - packetHeader->f8022Part.fSSAP = (uint8)the_stream->dlsap; - packetHeader->f8022Part.fCtrl = ctrl; - break; - case kPkt8022SNAP: { - uint8 *snapStart; - packetHeader->f8022Part.fDSAP = (uint8)dlsap; - packetHeader->f8022Part.fSSAP = (uint8)the_stream->dlsap; - packetHeader->f8022Part.fCtrl = ctrl; - if (destAddrLen >= kEnetAndSAPAddressLength + k8022SNAPLength) - snapStart = destAddrCopy + kEnetAndSAPAddressLength; - else - snapStart = the_stream->snap; - OTCopy8022SNAP(snapStart, packetHeader->f8022Part.fSNAP); - break; - } - } - - // Return updated message - return mp; -} - - -/* - * Transmit packet - */ - -static void transmit_packet(mblk_t *mp) -{ - EnetPacketHeader *enetHeader = (EnetPacketHeader *)(void *)mp->b_rptr; - - // Fill in length in 802.3 packets - if (enetHeader->fProto == 0) - enetHeader->fProto = msgdsize(mp) - sizeof(EnetPacketHeader); - - // Fill in ethernet source address - OTCopy48BitAddress(hardware_address, enetHeader->fSourceAddr); - - // Tell add-on to transmit packet - AO_transmit_packet(Host2MacAddr((uint8 *)mp)); - freemsg(mp); -} - - -/* - * Handle incoming packet (one stream), construct DL_UNITDATA_IND message - */ - -static void handle_received_packet(DLPIStream *the_stream, mblk_t *mp, uint16 packet_type, int32 dest_addr_type) -{ - // Find address and header length - uint32 addr_len; - uint32 header_len; - switch (packet_type) { - case kPkt8022SAP: - addr_len = kEnetAndSAPAddressLength; - header_len = kEnetPacketHeaderLength + k8022BasicHeaderLength; - break; - case kPkt8022SNAP: - addr_len = kEnetAndSAPAddressLength + k8022SNAPLength; - header_len = kEnetPacketHeaderLength + k8022SNAPHeaderLength; - break; - default: // DIX and IPX - addr_len = kEnetAndSAPAddressLength; - header_len = kEnetPacketHeaderLength; - break; - } - - // In Fast Path mode, don't send DL_UNITDATA_IND messages for unicast packets - if ((the_stream->flags & kFastPathMode) && dest_addr_type == keaStandardAddress) { - if (the_stream->raw_mode == false) - mp->b_rptr += header_len; - num_rx_fastpath++; - putq(the_stream->rdq, mp); - return; - } - - // Allocate the dl_unitdata_ind_t message - mblk_t *nmp; - if ((nmp = allocb(sizeof(dl_unitdata_ind_t) + 2*addr_len, BPRI_HI)) == NULL) { - freemsg(mp); - num_rx_no_unitdata_mem++; - return; - } - - // Set message type - nmp->b_datap->db_type = M_PROTO; - dl_unitdata_ind_t *ind = (dl_unitdata_ind_t*)(void *)nmp->b_rptr; - ind->dl_primitive = DL_UNITDATA_IND; - nmp->b_wptr += (sizeof(dl_unitdata_ind_t) + 2*addr_len); - - // Link M_DATA block - nmp->b_cont = mp; - - // Set address fields - ind->dl_dest_addr_length = addr_len; - ind->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t); - ind->dl_src_addr_length = addr_len; - ind->dl_src_addr_offset = sizeof(dl_unitdata_ind_t) + addr_len; - - // Set address type - ind->dl_group_address = dest_addr_type; - - // Set address fields - T8022FullPacketHeader *packetHeader = (T8022FullPacketHeader *)(void *)mp->b_rptr; - T8022AddressStruct *destAddr = ((T8022AddressStruct*)(nmp->b_rptr + ind->dl_dest_addr_offset)); - T8022AddressStruct *srcAddr = ((T8022AddressStruct*)(nmp->b_rptr + ind->dl_src_addr_offset)); - - OTCopy48BitAddress(packetHeader->fEnetPart.fDestAddr, destAddr->fHWAddr); - OTCopy48BitAddress(packetHeader->fEnetPart.fSourceAddr, srcAddr->fHWAddr); - - destAddr->fSAP = packetHeader->f8022Part.fDSAP; - srcAddr->fSAP = packetHeader->f8022Part.fSSAP; - - if (packet_type == kPkt8022SNAP) { - OTCopy8022SNAP(packetHeader->f8022Part.fSNAP, destAddr->fSNAP); - OTCopy8022SNAP(packetHeader->f8022Part.fSNAP, srcAddr->fSNAP); - } - - // "Hide" the ethernet and protocol header(s) - if (the_stream->raw_mode == false) - mp->b_rptr += header_len; - - // Pass message up the stream - num_unitdata_ind++; - putq(the_stream->rdq, nmp); - return; -} - - -/* - * Packet received, distribute it to the streams that want it - */ - -void ether_packet_received(mblk_t *mp) -{ - // Extract address and types - EnetPacketHeader *pkt = (EnetPacketHeader *)(void *)mp->b_rptr; - T8022FullPacketHeader *fullpkt = (T8022FullPacketHeader *)pkt; - uint16 sourceSAP, destSAP; - destSAP = fullpkt->fEnetPart.fProto; - if (destSAP >= kMinDIXSAP) { - // Classic ethernet - sourceSAP = destSAP; - } else { - destSAP = fullpkt->f8022Part.fDSAP; - sourceSAP = fullpkt->f8022Part.fSSAP; - } - uint16 packetType = classify_packet_type(sourceSAP, destSAP); - int32 destAddressType = get_address_type(pkt->fDestAddr); - - // Look which streams want it - DLPIStream *the_stream, *found_stream = NULL; - uint16 found_packetType = 0; - int32 found_destAddressType = 0; - for (the_stream = dlpi_stream_list; the_stream != NULL; the_stream = mi_next_ptr(the_stream)) { - - // Don't send to unbound streams - if (the_stream->dlpi_state == DL_UNBOUND) - continue; - - // Does this stream want all 802.2 packets? - if ((the_stream->flags & kAcceptAll8022Packets) && (destSAP <= 0xff)) - goto type_found; - - // No, check SAP/SNAP - if (destSAP == the_stream->dlsap) { - if (the_stream->flags & kSnapStream) { - // Check SNAPs if necessary - uint8 sum = fullpkt->f8022Part.fSNAP[0] ^ the_stream->snap[0]; - sum |= fullpkt->f8022Part.fSNAP[1] ^ the_stream->snap[1]; - sum |= fullpkt->f8022Part.fSNAP[2] ^ the_stream->snap[2]; - sum |= fullpkt->f8022Part.fSNAP[3] ^ the_stream->snap[3]; - sum |= fullpkt->f8022Part.fSNAP[4] ^ the_stream->snap[4]; - if (sum == 0) - goto type_found; - } else { - // No SNAP, found a match since saps match - goto type_found; - } - } else { - // Check for an 802.3 Group/Global (odd) - if (((packetType == kPkt8022SAP) || (packetType == kPkt8022SNAP)) && (destSAP & 1) && the_stream->TestGroupSAP(destSAP)) - goto type_found; - } - - // No stream for this SAP/SNAP found - continue; - -type_found: - // If it's a multicast packet, it must be in the stream's multicast list - if ((destAddressType == keaMulticast) && (the_stream->flags & kAcceptMulticasts) && (!the_stream->IsMulticastRegistered(pkt->fDestAddr))) - continue; - - // Send packet to stream - // found_stream keeps a pointer to the previously found stream, so that only the last - // stream gets the original message, the other ones get duplicates - if (found_stream) - handle_received_packet(found_stream, dupmsg(mp), found_packetType, found_destAddressType); - found_stream = the_stream; - found_packetType = packetType; - found_destAddressType = destAddressType; - } - - // Send original message to last found stream - if (found_stream) - handle_received_packet(found_stream, mp, found_packetType, found_destAddressType); - else { - freemsg(mp); // Nobody wants it *snief* - num_rx_dropped++; - } -} - -void ether_dispatch_packet(uint32 p, uint32 size) -{ -#ifdef USE_ETHER_FULL_DRIVER - // Call handler from the Ethernet driver - D(bug("ether_dispatch_packet\n")); - D(bug(" packet data at %p, %d bytes\n", p, size)); - CallMacOS2(ether_dispatch_packet_ptr, ether_dispatch_packet_tvect, p, size); -#else - // Wrap packet in message block - num_rx_packets++; - mblk_t *mp; - if ((mp = allocb(size, 0)) != NULL) { - D(bug(" packet data at %p\n", (void *)mp->b_rptr)); - Mac2Host_memcpy(mp->b_rptr, p, size); - mp->b_wptr += size; - ether_packet_received(mp); - } else { - D(bug("WARNING: Cannot allocate mblk for received packet\n")); - num_rx_no_mem++; - } -#endif -} - - -/* - * Build and send an error acknowledge - */ - -static void DLPI_error_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim, uint32 err, uint32 uerr) -{ - D(bug(" DLPI_error_ack(%p,%p) prim %d, err %d, uerr %d\n", the_stream, ack_mp, prim, err, uerr)); - num_error_acks++; - - if (ack_mp != NULL) - freemsg(ack_mp); - if ((ack_mp = allocb(sizeof(dl_error_ack_t), BPRI_HI)) == NULL) - return; - - ack_mp->b_datap->db_type = M_PCPROTO; - dl_error_ack_t *errp = (dl_error_ack_t *)(void *)ack_mp->b_wptr; - errp->dl_primitive = DL_ERROR_ACK; - errp->dl_error_primitive = prim; - errp->dl_errno = err; - errp->dl_unix_errno = uerr; - ack_mp->b_wptr += sizeof(dl_error_ack_t); - qreply(q, ack_mp); -} - - -/* - * Build and send an OK acknowledge - */ - -static void DLPI_ok_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim) -{ - if (ack_mp->b_datap->db_ref != 1) { - // Message already in use, create a new one - freemsg(ack_mp); - if ((ack_mp = allocb(sizeof(dl_error_ack_t), BPRI_HI)) == NULL) - return; - } else { - // Message free - if (ack_mp->b_cont != NULL) { - freemsg(ack_mp->b_cont); - ack_mp->b_cont = NULL; - } - } - - ack_mp->b_datap->db_type = M_PCPROTO; - dl_ok_ack_t *ackp = (dl_ok_ack_t *)(void *)ack_mp->b_rptr; - ackp->dl_primitive = DL_OK_ACK; - ackp->dl_correct_primitive = prim; - ack_mp->b_wptr = ack_mp->b_rptr + sizeof(dl_ok_ack_t); - qreply(q, ack_mp); -} - - -/* - * Handle DL_INFO_REQ (report general information) - */ - -static void DLPI_info(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_info(%p)\n", the_stream)); - uint32 saplen = 0; - uint32 addrlen = kEnetPhysicalAddressLength; - uint32 bcastlen = kEnetPhysicalAddressLength; - uint32 hdrlen = kEnetPacketHeaderLength; - - // Calculate header length - if (the_stream->dlpi_state != DL_UNBOUND) { - saplen = (the_stream->flags & kSnapStream) ? k8022DLSAPLength+k8022SNAPLength : k8022DLSAPLength; - if (the_stream->dlsap == kSNAPSAP) - hdrlen = kEnetPacketHeaderLength + k8022SNAPHeaderLength; // SNAP address - else if ((the_stream->dlsap <= kMax8022SAP) || (the_stream->dlsap == kIPXSAP)) - hdrlen = kEnetPacketHeaderLength + k8022BasicHeaderLength; // SAP or IPX - else - hdrlen = kEnetPacketHeaderLength; // Basic Ethernet - } - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_info_ack_t) + addrlen + saplen + bcastlen, BPRI_LO)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_INFO_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_info_ack_t *ackp = (dl_info_ack_t *)(void *)ack_mp->b_rptr; - ackp->dl_primitive = DL_INFO_ACK; - - // Info/version fields - ackp->dl_service_mode = DL_CLDLS; - ackp->dl_provider_style = DL_STYLE1; - ackp->dl_version = DL_VERSION_2; - ackp->dl_current_state = the_stream->dlpi_state; - ackp->dl_mac_type = the_stream->framing_8022 ? DL_CSMACD : DL_ETHER; - ackp->dl_reserved = 0; - ackp->dl_qos_length = 0; - ackp->dl_qos_offset = (uint32)DL_UNKNOWN; - ackp->dl_qos_range_length = 0; - ackp->dl_qos_range_offset = (uint32)DL_UNKNOWN; - ackp->dl_growth = 0; - ackp->dl_min_sdu = 1; - ackp->dl_max_sdu = kEnetTSDU - hdrlen; - - // Address fields - ackp->dl_sap_length = -saplen; // Negative to indicate sap follows physical address - ackp->dl_addr_length = addrlen + saplen; - ackp->dl_addr_offset = sizeof(dl_info_ack_t); - T8022AddressStruct *boundAddr = ((T8022AddressStruct *)(ack_mp->b_rptr + ackp->dl_addr_offset)); - OTCopy48BitAddress(hardware_address, boundAddr->fHWAddr); - if (saplen) { - boundAddr->fSAP = the_stream->dlsap; - if (the_stream->flags & kSnapStream) - OTCopy8022SNAP(the_stream->snap, boundAddr->fSNAP); - } - ackp->dl_brdcst_addr_length = bcastlen; - ackp->dl_brdcst_addr_offset = sizeof(dl_info_ack_t) + addrlen + saplen; - OTSet48BitBroadcastAddress(ack_mp->b_rptr + ackp->dl_brdcst_addr_offset); - - // Advance write pointer - ack_mp->b_wptr += sizeof(dl_info_ack_t) + addrlen + saplen + bcastlen; - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_PHYS_ADDR_REQ (report physical address) - */ - -static void DLPI_phys_addr(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_phys_addr(%p,%p)\n", the_stream, mp)); - dl_phys_addr_req_t *req = (dl_phys_addr_req_t *)(void *)mp->b_rptr; - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_phys_addr_ack_t) + kEnetPhysicalAddressLength, BPRI_HI)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_PHYS_ADDR_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_phys_addr_ack_t *ackp = (dl_phys_addr_ack_t *)(void *)ack_mp->b_wptr; - ackp->dl_primitive = DL_PHYS_ADDR_ACK; - - // Fill in address - ackp->dl_addr_length = kEnetPhysicalAddressLength; - ackp->dl_addr_offset = sizeof(dl_phys_addr_ack_t); - ack_mp->b_wptr += sizeof(dl_phys_addr_ack_t) + kEnetPhysicalAddressLength; - if (req->dl_addr_type == DL_CURR_PHYS_ADDR || req->dl_addr_type == DL_FACT_PHYS_ADDR) - OTCopy48BitAddress(hardware_address, ack_mp->b_rptr + ackp->dl_addr_offset); - else { - DLPI_error_ack(the_stream, q, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0); - return; - } - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_BIND_REQ (bind a stream) - */ - -static void DLPI_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_bind_req_t *req = (dl_bind_req_t *)(void *)mp->b_rptr; - uint32 sap = req->dl_sap; - D(bug(" DLPI_bind(%p,%p) SAP %04x\n", the_stream, mp, sap)); - - // Stream must be unbound - if (the_stream->dlpi_state != DL_UNBOUND) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_OUTSTATE, 0); - return; - } - - // We only support connectionless data link services - if (req->dl_service_mode != DL_CLDLS || req->dl_max_conind != 0) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0); - return; - } - - // Don't bind to 802.2 group saps, can't check 802.2 global sap (0xFF) - // because it looks like IPX - if ((sap <= kMax8022SAP) && (sap & 1)) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_BADADDR, 0); - return; - } - - if (classify_packet_type(sap, sap) == kPktUnknown) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_BADADDR, 0); - return; - } - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_bind_ack_t) + kEnetAndSAPAddressLength, BPRI_HI)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_bind_ack_t *ackp = (dl_bind_ack_t *)(void *)ack_mp->b_rptr; - ackp->dl_primitive = DL_BIND_ACK; - - // Fill in other fields - ackp->dl_sap = sap; - ackp->dl_addr_length = kEnetAndSAPAddressLength; - ackp->dl_addr_offset = sizeof(dl_bind_ack_t); - ackp->dl_max_conind = 0; - ackp->dl_xidtest_flg = 0; - - T8022AddressStruct *addrInfo = (T8022AddressStruct *)(ack_mp->b_rptr + sizeof(dl_bind_ack_t)); - OTCopy48BitAddress(hardware_address, addrInfo->fHWAddr); - addrInfo->fSAP = sap; - - // Must move b_wptr past the address info data - ack_mp->b_wptr = ack_mp->b_rptr + sizeof(dl_bind_ack_t) + kEnetAndSAPAddressLength; - - // Set group SAP if necessary - the_stream->ClearAllGroupSAPs(); - if (sap <= kMax8022SAP) - the_stream->SetGroupSAP(k8022GlobalSAP); - - // The stream is now bound and idle - the_stream->dlpi_state = DL_IDLE; - the_stream->dlsap = sap; - the_stream->flags &= ~kSnapStream; - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_UNBIND_REQ (unbind a stream) - */ - -static void DLPI_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_unbind(%p,%p)\n", the_stream, mp)); - - // Stream must be bound and idle - if (the_stream->dlpi_state != DL_IDLE) { - DLPI_error_ack(the_stream, q, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0); - return; - } - - // Stream is now unbound - the_stream->dlpi_state = DL_UNBOUND; - the_stream->dlsap = 0; - - // Flush all pending outbound messages - flushq(q, FLUSHDATA); - - // Flush all inbound messages pending on the stream - flushq(RD(q), FLUSHDATA); - putnextctl1(RD(q), M_FLUSH, FLUSHRW); - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_UNBIND_REQ); - return; -} - - -/* - * Handle DL_SUBS_BIND_REQ (register 802.2 SAP group addresses and SNAPs) - */ - -static void DLPI_subs_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_subs_bind_req_t *req = (dl_subs_bind_req_t *)(void *)mp->b_rptr; - uint8 *sap = ((uint8 *)req) + req->dl_subs_sap_offset; - int32 length = req->dl_subs_sap_length; - uint16 theSap = ntohs(*((uint16 *)sap)); - int32 error = 0; - D(bug(" DLPI_subs_bind(%p,%p) SAP %02x%02x%02x%02x%02x\n", the_stream, mp, sap[0], sap[1], sap[2], sap[3], sap[4])); - - // Stream must be idle - if (the_stream->dlpi_state != DL_IDLE) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, DL_OUTSTATE, 0); - return; - } - - // Check if address is valid - switch (req->dl_subs_bind_class) { - case DL_PEER_BIND: // Bind a group address - if (the_stream->dlsap <= kMax8022SAP) { - if ((theSap & 1) && (length == sizeof(theSap))) - the_stream->SetGroupSAP(theSap); - else - if (theSap == 0x0000) // special case to receive all 802.2 packets - the_stream->flags |= kAcceptAll8022Packets; - else - error = DL_BADADDR; - } else - error = DL_UNSUPPORTED; - break; - - case DL_HIERARCHICAL_BIND: // Bind an additional SNAP - if (the_stream->dlsap == kSNAPSAP) { - if (the_stream->flags & kSnapStream) - error = DL_TOOMANY; // only one SNAP binding allowed - else { - OTCopy8022SNAP(sap, the_stream->snap); - the_stream->flags |= kSnapStream; - } - } else - error = DL_BADADDR; - break; - - default: - error = DL_UNSUPPORTED; - break; - } - if (error) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, error, 0); - return; - } - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_subs_bind_ack_t) + length, BPRI_HI)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_subs_bind_ack_t *ackp = (dl_subs_bind_ack_t *)(void *)ack_mp->b_wptr; - memset(ackp, 0, sizeof(dl_subs_bind_ack_t) + length); - ackp->dl_primitive = DL_SUBS_BIND_ACK; - - // Fill in other fields - ackp->dl_subs_sap_length = length; - ackp->dl_subs_sap_offset = length ? sizeof(dl_subs_bind_ack_t) : 0; - ack_mp->b_wptr += sizeof(dl_subs_bind_ack_t); - if (length) - memcpy(ack_mp->b_wptr, sap, length); - ack_mp->b_wptr += length; - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_SUBS_UNBIND_REQ (unregister 802.2 SAP group addresses and snaps) - */ - -static void DLPI_subs_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_subs_unbind_req_t *req = (dl_subs_unbind_req_t *)(void *)mp->b_rptr; - uint8 *sap = ((uint8 *)req) + req->dl_subs_sap_offset; - int32 length = req->dl_subs_sap_length; - int32 error = 0; - D(bug(" DLPI_subs_unbind(%p,%p) SAP %02x%02x%02x%02x%02x\n", the_stream, mp, sap[0], sap[1], sap[2], sap[3], sap[4])); - - // Stream must be idle - if (the_stream->dlpi_state != DL_IDLE) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ, DL_OUTSTATE, 0); - return; - } - - // Check if we are unbinding from an address we are bound to - if (length == k8022SAPLength) { - if ((*sap & 1) && (*sap != kIPXSAP)) { - if (the_stream->dlsap <= kMax8022SAP) - the_stream->ClearGroupSAP(*sap); - else - error = DL_UNSUPPORTED; - } else - error = DL_BADADDR; - } else if (length == k8022SNAPLength) { - if (the_stream->dlsap == kSNAPSAP) { - if (the_stream->flags & kSnapStream) { - if (memcmp(the_stream->snap, sap, length) != 0) - error = DL_BADADDR; - } else - error = DL_BADADDR; - } else - error = DL_UNSUPPORTED; - } - if (error) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ, error, 0); - return; - } - - // Stream is no longer bound to SNAP - the_stream->flags &= ~kSnapStream; - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ); - return; -} - - -/* - * Handles DL_ENABMULTI_REQ (enable multicast address) - */ - -static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_enabmulti_req_t* req = (dl_enabmulti_req_t*)(void *)mp->b_rptr; - uint8 *reqaddr = (uint8 *)(mp->b_rptr + req->dl_addr_offset); - D(bug(" DLPI_enable_multi(%p,%p) addr %02x%02x%02x%02x%02x%02x\n", the_stream, mp, reqaddr[0], reqaddr[1], reqaddr[2], reqaddr[3], reqaddr[4], reqaddr[5])); - - // Address must be a multicast address - if (get_address_type(reqaddr) != keaMulticast) { - DLPI_error_ack(the_stream, q, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Address already in multicast list? - if (the_stream->IsMulticastRegistered(reqaddr)) { - DLPI_error_ack(the_stream, q, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Tell add-on to enable multicast address - AO_enable_multicast(Host2MacAddr((uint8 *)reqaddr)); - - // Add new address to multicast list - uint8 *addr = Mac2HostAddr(Mac_sysalloc(kEnetPhysicalAddressLength)); - OTCopy48BitAddress(reqaddr, addr); - the_stream->AddMulticast(addr); - - // On receive now check multicast packets - the_stream->flags |= kAcceptMulticasts; - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_ENABMULTI_REQ); - return; -} - - -/* - * Handles DL_DISABMULTI_REQ (disable multicast address) - */ - -static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_disabmulti_req_t *req = (dl_disabmulti_req_t*)(void *)mp->b_rptr; - uint8 *reqaddr = (uint8 *)(mp->b_rptr + req->dl_addr_offset); - D(bug(" DLPI_disable_multi(%p,%p) addr %02x%02x%02x%02x%02x%02x\n", the_stream, mp, reqaddr[0], reqaddr[1], reqaddr[2], reqaddr[3], reqaddr[4], reqaddr[5])); - - // Address must be a multicast address - if (get_address_type(reqaddr) != keaMulticast) { - DLPI_error_ack(the_stream, q, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Find address in multicast list - uint8 *addr = the_stream->IsMulticastRegistered(reqaddr); - if (addr == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Found, then remove - the_stream->RemoveMulticast(addr); - Mac_sysfree(Host2MacAddr(addr)); - - // Tell add-on to disable multicast address - AO_disable_multicast(Host2MacAddr((uint8 *)reqaddr)); - - // No longer check multicast packets if no multicast addresses are registered - if (the_stream->multicast_list == NULL) - the_stream->flags &= ~kAcceptMulticasts; - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_DISABMULTI_REQ); - return; -} - - -/* - * Handle DL_UNITDATA_REQ (transmit packet) - */ - -static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_unit_data(%p,%p)\n", the_stream, mp)); - dl_unitdata_req_t *req = (dl_unitdata_req_t *)(void *)mp->b_rptr; - - // Stream must be idle - if (the_stream->dlpi_state != DL_IDLE) { - - // Not idle, send error response - dl_uderror_ind_t *errp; - mblk_t *bp; - - int i = sizeof(dl_uderror_ind_t) + req->dl_dest_addr_length; - if ((bp = allocb(i, BPRI_HI)) == NULL) { - freemsg(mp); - return; - } - bp->b_datap->db_type = M_PROTO; - errp = (dl_uderror_ind_t *)(void *)bp->b_wptr; - errp->dl_primitive = DL_UDERROR_IND; - errp->dl_errno = DL_OUTSTATE; - errp->dl_unix_errno = 0; - errp->dl_dest_addr_length = req->dl_dest_addr_length; - errp->dl_dest_addr_offset = sizeof(dl_uderror_ind_t); - bp->b_wptr += sizeof(dl_uderror_ind_t); - memcpy((uint8 *)bp->b_wptr, ((uint8 *)req) + req->dl_dest_addr_offset, req->dl_dest_addr_length); - bp->b_wptr += req->dl_dest_addr_length; - qreply(q, bp); - - freemsg(mp); - return; - } - - // Build packet header and transmit packet - if ((mp = build_tx_packet_header(the_stream, mp, false)) != NULL) - transmit_packet(mp); -} - - -/* - * Ethernet packet allocator - */ - -#if SIZEOF_VOID_P != 4 || REAL_ADDRESSING == 0 -static uint32 ether_packet = 0; // Ethernet packet (cached allocation) -static uint32 n_ether_packets = 0; // Number of ethernet packets allocated so far (should be at most 1) - -EthernetPacket::EthernetPacket() -{ - ++n_ether_packets; - if (ether_packet && n_ether_packets == 1) - packet = ether_packet; - else { - packet = Mac_sysalloc(1516); - assert(packet != 0); - Mac_memset(packet, 0, 1516); - if (ether_packet == 0) - ether_packet = packet; - } -} - -EthernetPacket::~EthernetPacket() -{ - --n_ether_packets; - if (packet != ether_packet) - Mac_sysfree(packet); - if (n_ether_packets > 0) { - bug("WARNING: Nested allocation of ethernet packets!\n"); - } -} -#endif diff --git a/SheepShaver/src/EthernetDriver/ether.h b/SheepShaver/src/EthernetDriver/ether.h deleted file mode 100644 index 7ea2c881..00000000 --- a/SheepShaver/src/EthernetDriver/ether.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ether.h - SheepShaver Ethernet Device Driver - * - * SheepShaver (C) 1997-2005 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ETHER_H -#define ETHER_H - -struct queue; -struct msgb; -typedef struct queue queue_t; -typedef struct msgb mblk_t; - -// Prototypes for exported functions -extern "C" { -#pragma export on -extern uint32 ValidateHardware(void *theID); -struct install_info; -extern install_info* GetOTInstallInfo(); -extern uint8 InitStreamModule(void *theID); -extern void TerminateStreamModule(void); -#pragma export off -} - -extern bool NativeInitStreamModule(void *); -extern void NativeTerminateStreamModule(void); - -extern int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds); -extern int ether_close(queue_t *rdq, int flag, void *creds); -extern int ether_wput(queue_t *q, mblk_t *mp); -extern int ether_rsrv(queue_t *q); - -// System specific and internal functions/data -extern void EtherInit(void); -extern void EtherExit(void); - -extern void EtherIRQ(void); - -extern void AO_get_ethernet_address(uint32 addr); -extern void AO_enable_multicast(uint32 addr); -extern void AO_disable_multicast(uint32 addr); -extern void AO_transmit_packet(uint32 mp); - -extern mblk_t *allocb(size_t size, int pri); -extern void OTEnterInterrupt(void); -extern void OTLeaveInterrupt(void); - -extern void ether_dispatch_packet(uint32 p, uint32 length); -extern void ether_packet_received(mblk_t *mp); - -extern bool ether_driver_opened; - -// Ethernet packet allocator (optimized for 32-bit platforms in real addressing mode) -class EthernetPacket { -#if SIZEOF_VOID_P == 4 && REAL_ADDRESSING - uint8 packet[1516]; - public: - uint32 addr(void) const { return (uint32)packet; } -#else - uint32 packet; - public: - EthernetPacket(); - ~EthernetPacket(); - uint32 addr(void) const { return packet; } -#endif -}; - -// Copy packet data from message block to linear buffer (must hold at -// least 1514 bytes), returns packet length -static inline int ether_msgb_to_buffer(uint32 mp, uint8 *p) -{ - int len = 0; - while (mp) { - uint32 size = ReadMacInt32(mp + 16) - ReadMacInt32(mp + 12); - Mac2Host_memcpy(p, ReadMacInt32(mp + 12), size); - len += size; - p += size; - mp = ReadMacInt32(mp + 8); - } - return len; -} - -extern int32 num_wput; -extern int32 num_error_acks; -extern int32 num_tx_packets; -extern int32 num_tx_raw_packets; -extern int32 num_tx_normal_packets; -extern int32 num_tx_buffer_full; -extern int32 num_rx_packets; -extern int32 num_ether_irq; -extern int32 num_unitdata_ind; -extern int32 num_rx_fastpath; -extern int32 num_rx_no_mem; -extern int32 num_rx_dropped; -extern int32 num_rx_stream_not_ready; -extern int32 num_rx_no_unitdata_mem; - -#endif diff --git a/SheepShaver/src/EthernetDriver/ether_defs.h b/SheepShaver/src/EthernetDriver/ether_defs.h deleted file mode 100644 index 72bb58ed..00000000 --- a/SheepShaver/src/EthernetDriver/ether_defs.h +++ /dev/null @@ -1,552 +0,0 @@ -/* - * ether_defs.h - Definitions for DLPI Ethernet Driver - * - * SheepShaver (C) 1997-2005 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ETHER_DEFS_H -#define ETHER_DEFS_H - - -#if __MWERKS__ && __POWERPC__ -#ifndef PRAGMA_ALIGN_SUPPORTED -#define PRAGMA_ALIGN_SUPPORTED 1 -#endif -#define PACKED__ -#else -#define PACKED__ __attribute__ ((packed)) -#endif - - -/* - * Macros - */ - -// Get pointer to the read queue, assumes 'q' is a write queue ptr -#define RD(q) (&q[-1]) - -// Get pointer to the write queue, assumes 'q' is a read queue ptr -#define WR(q) (&q[1]) - -#define OTCompare48BitAddresses(p1, p2) \ - (*(const uint32*)((const uint8*)(p1)) == *(const uint32*)((const uint8*)(p2)) && \ - *(const uint16*)(((const uint8*)(p1))+4) == *(const uint16*)(((const uint8*)(p2))+4) ) - -#define OTCopy48BitAddress(p1, p2) \ - (*(uint32*)((uint8*)(p2)) = *(const uint32*)((const uint8*)(p1)), \ - *(uint16*)(((uint8*)(p2))+4) = *(const uint16*)(((const uint8*)(p1))+4) ) - -#define OTClear48BitAddress(p1) \ - (*(uint32*)((uint8*)(p1)) = 0, \ - *(uint16*)(((uint8*)(p1))+4) = 0 ) - -#define OTCompare8022SNAP(p1, p2) \ - (*(const uint32*)((const uint8*)(p1)) == *(const uint32*)((const uint8*)(p2)) && \ - *(((const uint8*)(p1))+4) == *(((const uint8*)(p2))+4) ) - -#define OTCopy8022SNAP(p1, p2) \ - (*(uint32*)((uint8*)(p2)) = *(const uint32*)((const uint8*)(p1)), \ - *(((uint8*)(p2))+4) = *(((const uint8*)(p1))+4) ) - -#define OTIs48BitBroadcastAddress(p1) \ - (*(uint32*)((uint8*)(p1)) == 0xffffffff && \ - *(uint16*)(((uint8*)(p1))+4) == 0xffff ) - -#define OTSet48BitBroadcastAddress(p1) \ - (*(uint32*)((uint8*)(p1)) = 0xffffffff, \ - *(uint16*)(((uint8*)(p1))+4) = 0xffff ) - -#define OTIs48BitZeroAddress(p1) \ - (*(uint32*)((uint8*)(p1)) == 0 && \ - *(uint16*)(((uint8*)(p1))+4) == 0 ) - - -/* - * Constants - */ - -enum { - // Address and packet lengths - kEnetPhysicalAddressLength = 6, - k8022SAPLength = 1, - k8022DLSAPLength = 2, - k8022SNAPLength = 5, - kMaxBoundAddrLength = 6 + 2 + 5, // addr/SAP/SNAP - kEnetAndSAPAddressLength = kEnetPhysicalAddressLength + k8022DLSAPLength, - kEnetPacketHeaderLength = (2 * kEnetPhysicalAddressLength) + k8022DLSAPLength, - k8022BasicHeaderLength = 3, // SSAP/DSAP/Control - k8022SNAPHeaderLength = k8022SNAPLength + k8022BasicHeaderLength, - kMinDIXSAP = 1501, - kEnetTSDU = 1514, - - // Special addresses - kSNAPSAP = 0xaa, - kMax8022SAP = 0xfe, - k8022GlobalSAP = 0xff, - kIPXSAP = 0xff, - - // DLPI interface states - DL_UNBOUND = 0, - - // Message types - M_DATA = 0, - M_PROTO = 1, - M_IOCTL = 14, - M_IOCACK = 129, - M_IOCNAK = 130, - M_PCPROTO = 131, // priority message - M_FLUSH = 134, - FLUSHDATA = 0, - FLUSHALL = 1, - FLUSHR = 1, - FLUSHW = 2, - FLUSHRW = 3, - - // DLPI primitives - DL_INFO_REQ = 0, - DL_BIND_REQ = 1, - DL_PEER_BIND = 1, - DL_HIERARCHICAL_BIND = 2, - DL_UNBIND_REQ = 2, - DL_INFO_ACK = 3, - DL_BIND_ACK = 4, - DL_ERROR_ACK = 5, - DL_OK_ACK = 6, - DL_UNITDATA_REQ = 7, - DL_UNITDATA_IND = 8, - DL_UDERROR_IND = 9, - DL_SUBS_UNBIND_REQ = 21, - DL_SUBS_BIND_REQ = 27, - DL_SUBS_BIND_ACK = 28, - DL_ENABMULTI_REQ = 29, - DL_DISABMULTI_REQ = 30, - DL_PHYS_ADDR_REQ = 49, - DL_PHYS_ADDR_ACK = 50, - DL_FACT_PHYS_ADDR = 1, - DL_CURR_PHYS_ADDR = 2, - - // DLPI states - DL_IDLE = 3, - - // DLPI error codes - DL_BADADDR = 1, // improper address format - DL_OUTSTATE = 3, // improper state - DL_SYSERR = 4, // UNIX system error - DL_UNSUPPORTED = 7, // service unsupported - DL_BADPRIM = 9, // primitive unknown - DL_NOTSUPPORTED = 18, // primitive not implemented - DL_TOOMANY = 19, // limit exceeded - - // errnos - MAC_ENXIO = 6, - MAC_ENOMEM = 12, - MAC_EINVAL = 22, - - // Various DLPI constants - DL_CLDLS = 2, // connectionless data link service - DL_STYLE1 = 0x500, - DL_VERSION_2 = 2, - DL_CSMACD = 0, - DL_ETHER = 4, - DL_UNKNOWN = -1, - - // ioctl() codes - I_OTSetFramingType = (('O' << 8) | 2), - kOTGetFramingValue = -1, - kOTFramingEthernet = 1, - kOTFramingEthernetIPX = 2, - kOTFramingEthernet8023 = 4, - kOTFraming8022 = 8, - I_OTSetRawMode = (('O' << 8) | 3), - DL_IOC_HDR_INFO = (('l' << 8) | 10), - - // Buffer allocation priority - BPRI_LO = 1, - BPRI_HI = 3, - - // Misc constants - kEnetModuleID = 7101 -}; - -enum EAddrType { - keaStandardAddress = 0, - keaMulticast, - keaBroadcast, - keaBadAddress -}; - - -/* - * Data member wrappers - */ - -// Forward declarations -struct datab; -struct msgb; -struct queue; -struct multicast_node; -struct DLPIStream; - -// Optimize for 32-bit big endian targets -#if defined(WORDS_BIGENDIAN) && (SIZEOF_VOID_P == 4) - -// Predefined member types -typedef int8 nw_int8; -typedef int16 nw_int16; -typedef int32 nw_int32; -typedef uint8 nw_uint8; -typedef uint16 nw_uint16; -typedef uint32 nw_uint32; -typedef int nw_bool; -typedef uint8 * nw_uint8_p; -typedef void * nw_void_p; -typedef datab * nw_datab_p; -typedef msgb * nw_msgb_p; -typedef queue * nw_queue_p; -typedef multicast_node *nw_multicast_node_p; -typedef DLPIStream * nw_DLPIStream_p; - -#else - -// Big-endian memory accessor -template< int nbytes > -struct nw_memory_helper; - -template<> -struct nw_memory_helper<1> { - static inline uint8 load(void *ptr) { return *((uint8 *)ptr); } - static inline void store(void *ptr, uint8 val) { *((uint8 *)ptr) = val; } -}; - -template<> -struct nw_memory_helper<2> { - static inline uint16 load(void *ptr) { return ntohs(*((uint16 *)ptr)); } - static inline void store(void *ptr, uint16 val) { *((uint16 *)ptr) = htons(val); } -}; - -template<> -struct nw_memory_helper<4> { - static inline uint32 load(void *ptr) { return ntohl(*((uint32 *)ptr)); } - static inline void store(void *ptr, uint32 val) { *((uint32 *)ptr) = htonl(val); } -}; - -// Scalar data member wrapper (specialise for pointer member types?) -template< class type, class public_type > -class nw_scalar_member_helper { - uint8 _pad[sizeof(type)]; -public: - operator public_type () const { - return (public_type)(uintptr)nw_memory_helper::load((void *)this); - } - public_type operator -> () const { - return this->operator public_type (); - } - nw_scalar_member_helper & operator = (public_type val) { - nw_memory_helper::store((void *)this, (type)(uintptr)val); - return *this; - } - nw_scalar_member_helper & operator += (int val) { - *this = *this + val; - return *this; - } - nw_scalar_member_helper & operator -= (int val) { - *this = *this - val; - return *this; - } - nw_scalar_member_helper & operator &= (int val) { - *this = *this & val; - return *this; - } - nw_scalar_member_helper & operator |= (int val) { - *this = *this | val; - return *this; - } -}; - -// Predefined member types -typedef nw_scalar_member_helper nw_int8; -typedef nw_scalar_member_helper nw_int16; -typedef nw_scalar_member_helper nw_int32; -typedef nw_scalar_member_helper nw_uint8; -typedef nw_scalar_member_helper nw_uint16; -typedef nw_scalar_member_helper nw_uint32; -typedef nw_scalar_member_helper nw_bool; -typedef nw_scalar_member_helper nw_uint8_p; -typedef nw_scalar_member_helper nw_void_p; -typedef nw_scalar_member_helper nw_datab_p; -typedef nw_scalar_member_helper nw_msgb_p; -typedef nw_scalar_member_helper nw_queue_p; -typedef nw_scalar_member_helper nw_multicast_node_p; -typedef nw_scalar_member_helper nw_DLPIStream_p; - -#endif - - -/* - * Structures - */ - -// Data block -struct datab { - nw_datab_p db_freep; - nw_uint8_p db_base; - nw_uint8_p db_lim; - nw_uint8 db_ref; - nw_uint8 db_type; - // ... -}; - -// Message block -struct msgb { - nw_msgb_p b_next; - nw_msgb_p b_prev; - nw_msgb_p b_cont; - nw_uint8_p b_rptr; - nw_uint8_p b_wptr; - nw_datab_p b_datap; - // ... -}; - -// Queue (full structure required because of size) -struct queue { - nw_void_p q_qinfo; - nw_msgb_p q_first; - nw_msgb_p q_last; - nw_queue_p q_next; - nw_queue_p q_link; - nw_DLPIStream_p q_ptr; - nw_uint32 q_count; - nw_int32 q_minpsz; - nw_int32 q_maxpsz; - nw_uint32 q_hiwat; - nw_uint32 q_lowat; - nw_void_p q_bandp; - nw_uint16 q_flag; - nw_uint8 q_nband; - uint8 _q_pad1[1]; - nw_void_p q_osx; - nw_queue_p q_ffcp; - nw_queue_p q_bfcp; -}; -typedef struct queue queue_t; - -// M_IOCTL parameters -struct iocblk { - nw_int32 ioc_cmd; - nw_void_p ioc_cr; - nw_uint32 ioc_id; - nw_uint32 ioc_count; - nw_int32 ioc_error; - nw_int32 ioc_rval; - int32 _ioc_filler[4]; -}; - -// Priority specification -struct dl_priority_t { - nw_int32 dl_min, dl_max; -}; - -// DPLI primitives -struct dl_info_req_t { - nw_uint32 dl_primitive; // DL_INFO_REQ -}; - -struct dl_info_ack_t { - nw_uint32 dl_primitive; // DL_INFO_ACK - nw_uint32 dl_max_sdu; - nw_uint32 dl_min_sdu; - nw_uint32 dl_addr_length; - nw_uint32 dl_mac_type; - nw_uint32 dl_reserved; - nw_uint32 dl_current_state; - nw_int32 dl_sap_length; - nw_uint32 dl_service_mode; - nw_uint32 dl_qos_length; - nw_uint32 dl_qos_offset; - nw_uint32 dl_qos_range_length; - nw_uint32 dl_qos_range_offset; - nw_uint32 dl_provider_style; - nw_uint32 dl_addr_offset; - nw_uint32 dl_version; - nw_uint32 dl_brdcst_addr_length; - nw_uint32 dl_brdcst_addr_offset; - nw_uint32 dl_growth; -}; - -struct dl_bind_req_t { - nw_uint32 dl_primitive; // DL_BIND_REQ - nw_uint32 dl_sap; - nw_uint32 dl_max_conind; - nw_uint16 dl_service_mode; - nw_uint16 dl_conn_mgmt; - nw_uint32 dl_xidtest_flg; -}; - -struct dl_bind_ack_t { - nw_uint32 dl_primitive; // DL_BIND_ACK - nw_uint32 dl_sap; - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; - nw_uint32 dl_max_conind; - nw_uint32 dl_xidtest_flg; -}; - -struct dl_error_ack_t { - nw_uint32 dl_primitive; // DL_ERROR_ACK - nw_uint32 dl_error_primitive; - nw_uint32 dl_errno; - nw_uint32 dl_unix_errno; -}; - -struct dl_ok_ack_t { - nw_uint32 dl_primitive; // DL_ERROR_ACK - nw_uint32 dl_correct_primitive; -}; - -struct dl_unitdata_req_t { - nw_uint32 dl_primitive; // DL_UNITDATA_REQ - nw_uint32 dl_dest_addr_length; - nw_uint32 dl_dest_addr_offset; - dl_priority_t dl_priority; -}; - -struct dl_unitdata_ind_t { - nw_uint32 dl_primitive; // DL_UNITDATA_IND - nw_uint32 dl_dest_addr_length; - nw_uint32 dl_dest_addr_offset; - nw_uint32 dl_src_addr_length; - nw_uint32 dl_src_addr_offset; - nw_uint32 dl_group_address; -}; - -struct dl_uderror_ind_t { - nw_uint32 dl_primitive; // DL_UDERROR_IND - nw_uint32 dl_dest_addr_length; - nw_uint32 dl_dest_addr_offset; - nw_uint32 dl_unix_errno; - nw_uint32 dl_errno; -}; - -struct dl_subs_bind_req_t { - nw_uint32 dl_primitive; // DL_SUBS_BIND_REQ - nw_uint32 dl_subs_sap_offset; - nw_uint32 dl_subs_sap_length; - nw_uint32 dl_subs_bind_class; -}; - -struct dl_subs_bind_ack_t { - nw_uint32 dl_primitive; // DL_SUBS_BIND_ACK - nw_uint32 dl_subs_sap_offset; - nw_uint32 dl_subs_sap_length; -}; - -struct dl_subs_unbind_req_t { - nw_uint32 dl_primitive; // DL_SUBS_UNBIND_REQ - nw_uint32 dl_subs_sap_offset; - nw_uint32 dl_subs_sap_length; -}; - -struct dl_enabmulti_req_t { - nw_uint32 dl_primitive; // DL_ENABMULTI_REQ - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; -}; - -struct dl_disabmulti_req_t { - nw_uint32 dl_primitive; // DL_DISABMULTI_REQ - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; -}; - -struct dl_phys_addr_req_t { - nw_uint32 dl_primitive; // DL_PHYS_ADDR_REQ - nw_uint32 dl_addr_type; -}; - -struct dl_phys_addr_ack_t { - nw_uint32 dl_primitive; // DL_PHYS_ADDR_ACK - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; -}; - -// Parameters for I_OTSetRawMode/kOTSetRecvMode ioctl() -struct dl_recv_control_t { - nw_uint32 dl_primitive; - nw_uint32 dl_flags; - nw_uint32 dl_truncation_length; -}; - -union DL_primitives { - nw_uint32 dl_primitive; - dl_info_req_t info_req; - dl_info_ack_t info_ack; - dl_bind_req_t bind_req; - dl_bind_ack_t bind_ack; - dl_error_ack_t error_ack; - dl_ok_ack_t ok_ack; - dl_unitdata_req_t unitdata_req; - dl_unitdata_ind_t unitdata_ind; - dl_uderror_ind_t uderror_ind; - dl_subs_bind_req_t subs_bind_req; - dl_subs_bind_ack_t subs_bind_ack; - dl_subs_unbind_req_t subs_unbind_req; - dl_enabmulti_req_t enabmulti_req; - dl_disabmulti_req_t disabmulti_req; - dl_phys_addr_req_t phys_addr_req; - dl_phys_addr_ack_t phys_addr_ack; -}; - -#ifdef PRAGMA_ALIGN_SUPPORTED -#pragma options align=mac68k -#endif - -// Packet headers -struct EnetPacketHeader { - uint8 fDestAddr[6]; - uint8 fSourceAddr[6]; - nw_uint16 fProto; -} PACKED__; - -struct T8022Header { - uint8 fDSAP; - uint8 fSSAP; - uint8 fCtrl; -} PACKED__; - -struct T8022SNAPHeader { - uint8 fDSAP; - uint8 fSSAP; - uint8 fCtrl; - uint8 fSNAP[k8022SNAPLength]; -} PACKED__; - -struct T8022FullPacketHeader { - EnetPacketHeader fEnetPart; - T8022SNAPHeader f8022Part; -} PACKED__; - -struct T8022AddressStruct { - uint8 fHWAddr[6]; - nw_uint16 fSAP; - uint8 fSNAP[k8022SNAPLength]; -} PACKED__; - -#ifdef PRAGMA_ALIGN_SUPPORTED -#pragma options align=reset -#endif - -#endif diff --git a/SheepShaver/src/EthernetDriver/ethernet.ndrv b/SheepShaver/src/EthernetDriver/ethernet.ndrv deleted file mode 100644 index 02eed8b3dcb9d381caebfc70ef1d7e81740c7458..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11780 zcmb_i4RBOdmOk&NI~{1Ckp>zPpgY8|m6iz_s~!Y1i9|O{Kym4r;1;X-Ya}}%iJ=)9 ze9$knK&;i7wqV>if;Iwb?dVpfbgEeS3lc`HVXE8}s~klL0>UU&1Io-GVtT)G-+P^= z4TH61r(W*Qx%b?2&;Pye{kUyapgpo=N&Cw7Mk12_=h@D+C2cu6{_!~R z18@YM@puAweu$?6PmRDvG?EAX*m2iQM$J90`~%V)s>I)2;_2*st7697)@Y<-Nqu8v zUULK8)za4Zvww+nw9&nhl?$RB3s)^S`{uX(JW^F3t*3vAL>Dft?}#*Ect?H5D!Qk+ zwQ1q1WesgDRMot^y={2}^C%qYSk~NHAB`-Gc0}rz&2MX3(Gm$SjZ}3s|2)!B6A?`T?yb&0@nQo$3I6g(=8 zeQ-T__x6+LmyeO>zy5zf1VUW0iaBL zmZv3W|Nd?1i!8&kPaIVCf_$v(O}W9+i5_DLQ3x`wTt{x`l~hggQVnfwo!k~b_+=~! zcr_K(CxJVtz;MlR=#wijW+jgSyb|zBIdDJVYb|&H@QXQcUSp#LmjFM1HC*Zk{1+xX za02jiIq+VX4Kav9{zzA2yvLUlOqgkE=&T z3{c5~$BU=brk#0Z`v^?S{PuUI&kOqX0<7hrjITg?kVW^a)f8y9=-!ps1G*=PJ$3Q= zpl1gjU27y2{Q7O;V=65hAQgT7_(|;HIa09)?AiamwFhtF7_ykjj3eETaTVHDDn(fW zbVyEsjLuhpXN3mFu-;)WSZ8tsW4t_u{a_G%n194rL#3uZrVZvveErE-auSs?@4(MJ znD;99VCtaQ@1PFy-nBO&vu4Q8^0Pv2$Y`?me;l-1`f$??*j>F~#WjYHz9+_3hJQ#siIRwoY+d$^q%Y>(cGc5<*iW)0fLVB0$h?e@X;xLeV#8*Go~ z@e2mqK3>1VZfpH?!%WDjn%uuaf6(qn{e3(>#G5~&^gwnO^&QjT^9r|WFQ`{o*NpWR zZ;*l7x}B}p`wyfq34LB$kg-AFng?7T#QQjY72eOf0-pQO*Ux?N(_eG{;}}=WYsOEB z_RXlj%W&u}Xf14J+R%5_!jli1Uj_YpS|&#lXtqL95ZOIoUcZ7okEk?Ee_ER?6k{nlnOwZrYAUES(8u~|;c)>E)`yNkf35l} z7<-;+!1&R66YpE#ahq$>S))(*BPpIZ$^4SKVGGryM65W$^x0$gFrH)+)-NO%MCt-f z?9-~h`yMGKXe$(SX6>Eo&`RwGJl|ML-fo3PVBbezKg)p2&wUuT&K{EmpMNd?V&`M}bMWbFGCJ9lI7RL* z$UaPYds#+U=Uv9jysM@O-&in~Un#@1t?6D1c7kCx4VZtq8*P)$35P(Zup3iHCqy!I z4H0|6DhfBM@|b1GqpB_HJ^iSHToA|U0&0JwHLs?SpTYO_o?NYK?=vPn)Jmx zEPG%-V)>cz2ROIESl_0TpdI@Joxt&h7deWDr#d`>~(Hrr#WQA-qa0Ppu_)yy`vd`I~LwHPE9;Bm>VA?AuUhUxWC^ zagSnXvkzN@b_?1i@dw_El_8Fz-W2i?p*|XLcbQ-CX@NF@l<)+#9Pla&J}wJh0=Ub9 z7h7<|Wb#?_S>A5O&+Eh=I~j{dK8k7eoMVk&&-{+72bu22P5*A%1?FsKAHw^1tr+`7 zTE;m^N}}04$i0BS9rSwumryeA>UdwMFG9WW*(w?d{Zg1O-Ay#A8~z*pv+e#M_?!(B z_E=997~|5`BHx1?vEFFtpNhF-Exm{#uWsKhbimAMGWG&rQ}zk+aq~W)CvlM6smVfj z;qycsJIp?$n#NXYO8Sc)z&IB183MZNOidvbeZy+f7iI`uHOG#%b#bU%p77frNS|VT z4F9)Uu0L833r!$d-vYh-_;y<_Q{a^*cr_uzt02ZPul(4r2ln79>!s1C`%oW&`Z(0x zR{ux?`U;;i6L_k@W8O~%`n(*&Q1>9NxP|?oL{4>z^Fi$4RCZovJj*)mMgAd$YEQam zYp~I>IpmAaVVynyq-CdOJ^&rT*a_M?^#j-xX^5?6K8l!l5HX>jBrOFw8RXNZkgxkw z92fe=!uPpF8)pO2 zR?)sTug>Zb_@5zpHKrM|UkZJz+bv{l>f63Rx=;8Y_$^D<4A!;n``A{@xMH45$^Gy9 zXk^z~8pV27lm6;)9rqdR7xhAg+kZ;j1*0-Zs!a_Hu>DKT@XL;9iG)CV!k=xVtGt*)i=k0ofeyArV#=>U= ze5`(^fZ-+jp<6_sej525!(Vci>n96h;fI|+!Wt#e+g+h?;vC>csbKw=Lt};iOKGdA zP+#twt~aJwmy__d9LvI1PB3rXtidx8^GSQkK1YptlFv~X>(NGwbC$0TJXkja4tuo7 zX^wC#Gx=t>D$lpi5gR`PX=o4M`!iRa_ z!^L?KboA%Yan1V(J74GAkp0%oBJ~pcE`6XZwr0wlL7JK^KaekYn{`$hbwR6xT;NYY z>)o&?rnLh3iC62T1mxo2nA3d_IY|WPbjWejc2YMTgg=14;6C^l5A2t5BKI7{_YXs! zT_Ix1_&0G5;<4XJqIfA_vXnFEQkI&rB6DOMhcptSkjP zH)y1#11ZEm%g$+@;e)S5zG&r@T+d7S;PatBhyfx$#axaVe7+ul4{+OgEc!XFxEOcY z$KWgcjhUN$_6&TE;6q$F7>gIfHtv2e2APr8Pb$ufgt0XI4Y_}3$LsE8dL z%gr1m$b8~B0a`eQvLE!K9>O?Rmyb%2Tez{Vb2j*rRB$gdiT+vZ2W@@nH2VYeRf#oF z>ZhgY$bm&0GFSCO%5=mQGj~O4>W}*b>w(}W@~mna!S5o>IFgmOkoDVNnLaDx349Lg zbJ;q1u@2pajBfzX6x$~xa34~WK6~2A(TX{4+d2uk%ovo}72KatkFnp0kI>&jdo%4r`Er{oF@R-jT3G6>YuGAh2CTc#yOKUFVCEJ`Olaa z#(8J}_fP)XUZFcSZpj*h^QTl&dl0b}@ddf#&TySLLps>M2pL_C+n)C%cybAH@w1F; z(q~4%mQ7n^xn4cTvc<~}U``+I{!ClMJqXJjG`sYCTgKX@1pcYiw_>; z9Kj|sD2Wm}rLb>DU489C;N*M+IX>Ffc{2ZfA#2{xPR_lD4d&BB$QmLcJ0970M{EnW z4Ol)AcSp!Od*O#NGXCmL@MaO{;k#qP{fgSd`6ccVswsb4**ADU$ae~WnP;~AC(%C2 zb@XijE(PP>;k%qHo05^E{VJoIIrpeoO8o5nU*C&(gdC1zDCn~9l~bLZkFt(J4ngoM z0a?V)-sVjm7y8HhC>Y$wr4`VpJ%-EFRqRv88KD=xTtdlrMz5y|1dMfZQP|YU63B-2 zIvDOdGYdK;>AQ=(;ogA(+#MF`b;#KaB?enB#Qa#eSN##jdSUB)7o{dqqQ4F_;2s7% z?58}G3#@fGwrD)o@||wL#{ga;^rry1Bz$dm0oo=$$-?Kc@VOXY2zRpBi$C57J%GNj zF7Uoh8~S@E@V#C3Aau`wK8f?l$#3*kmObRm0Y1wf{yrD;lEy071597UE(3QTxWh_3 zfV>EJaF=`<{3!HK#=zBx4|S5bm(!s>A@ptf5Ox9G1rFACcX9%GK&O}6tQ&kU1|0PU z`dKf;84Gpj4)O%&S16B&{oMEmjLVw|UHR5|;VON$a+b3GjDGYOr!D<>%hZp~JlOMF zxAENs>&95@*Yab3WBb1tazPhxchI$gU!Dk`RE2v|j%%}1(0Pvk(2Za?ab{N7z`0_} zM6b{Z=mBy<)(3vKz`9TeI#||=P_pb705|)sY737kd)!r8vM<*AZjY^T%!z3_g|OeR ztalrHX65;Oj^&cyUFC(QSpGH3rs8K{Z`hM5_rE@lvBd`P=h)p?;X}}0lm6SFzqpqD zWyep%hpS=(Vy1!IEWTa#@|g_zX#_O$JBnQ2JPCZZeDlQ%pzBEDvN(%`c%JsWeGbWU zWX>VbdyMnJhA5H7*#rCKcQfpRf_Sd82K)bZlcxRv0@c-NI z+OJEzoiBiQm(`D$w2YL}ZJTXY%{26#FaHVN{Y=ugkjweCB(3+!e!D)>D<(!!|Kj0}uW>#5fnm z%{C+n=T&LJQ16`W{fN72e+M zYv452!kvO-47C=vd)4;Aq3B83*7qgz> z3?4<@jXa6qOC)V)I&HldJpYf@vGqkeBw~E1Ylr!+OLrh|01&o=_p=K2Oa3~v1@6ay z|M$R;do0ApciFbG-{oK!B|CAJ--a{C0V+{FW|e^a6`xD znL5Vr|IzQdMn7GnU%f`Z`x^b8q57F_`!^ByW$Wad)PD7xdQ?5DexROGuc+tMi&B+? zOT2y|c)E2F8m5PTAmn5Zhs2OTe!CtjUI_xZRd?pu-ZWEY_%BJKe(Plx-49|VxyZHlK@s(}I ziuS0)UGpMf++f$O?q$snwY5iDA8Kq{woIBn0?o!2d`WAzL&MQ#!X9dmc1Zs6dn&_~ z^Je*n{KPhRv%e7xh%|-#4J)Gl<>KqxMbLKLIae>U5*)nF6s5>DZ=GD?YQZ #include #include #define DEBUG 0 #include "debug.h" /* * Find symbol in shared library (using CFM) * lib and sym must be Pascal strings! */ typedef OpaqueCFragConnectionID * ConnectionID; typedef unsigned char SymClass; static uint32 FindLibSymbol(Str63 lib, Str255 sym) { ConnectionID conn_id = 0; Ptr main_addr = NULL; Str255 err = ""; Ptr sym_addr = NULL; SymClass sym_class = 0; int16 res; res = GetSharedLibrary(lib, FOURCC('p','w','p','c'), 1, &conn_id, &main_addr, err); D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", res, conn_id, main_addr)); if (res) return NULL; res = FindSymbol(conn_id, sym, &sym_addr, &sym_class); D(bug(" FindSymbol: ret %d, sym_addr %p, sym_class %ld\n", res, sym_addr, sym_class));//!!?? CloseConnection(&conn_id); if (res) return NULL; else return (uint32)sym_addr; } uint32 FindLibSymbol(char *lib_name, char *sym_name) { Str63 lib; memcpy(&lib[0], lib_name, lib_name[0]+1); Str255 sym; memcpy(&sym[0], sym_name, sym_name[0]+1); return FindLibSymbol(lib, sym); } /* * Memory allocators in MacOS system heap zone */ uint32 Mac_sysalloc(uint32 size) { return (uint32)NewPtrSys(size); } void Mac_sysfree(uint32 addr) { DisposePtr((char *)addr); } /* * Glue for calling MacOS routines */ #define prolog ;\ mflr r0 ;\ stw r0,8(r1) ;\ stw r2,12(r1) ;\ stwu r1,-64(r1) ;\ lwz r0,0(r3) ;\ lwz r2,4(r3) ;\ mtctr r0 #define epilog ;\ bctrl ;\ lwz r0,64+8(r1) ;\ lwz r2,64+12(r1);\ mtlr r0 ;\ addi r1,r1,64 ;\ blr asm uint32 call_macos(register uint32 tvect) { prolog epilog } asm uint32 call_macos1(register uint32 tvect, register uint32 arg1) { prolog mr r3,r4 epilog } asm uint32 call_macos2(register uint32 tvect, register uint32 arg1, register uint32 arg2) { prolog mr r3,r4 mr r4,r5 epilog } asm uint32 call_macos3(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3) { prolog mr r3,r4 mr r4,r5 mr r5,r6 epilog } asm uint32 call_macos4(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4) { prolog mr r3,r4 mr r4,r5 mr r5,r6 mr r6,r7 epilog } asm uint32 call_macos5(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4, register uint32 arg5) { prolog mr r3,r4 mr r4,r5 mr r5,r6 mr r6,r7 mr r7,r8 epilog } asm uint32 call_macos6(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4, register uint32 arg5, register uint32 arg6) { prolog mr r3,r4 mr r4,r5 mr r5,r6 mr r6,r7 mr r7,r8 mr r8,r9 epilog } asm uint32 call_macos7(register uint32 tvect, register uint32 arg1, register uint32 arg2, register uint32 arg3, register uint32 arg4, register uint32 arg5, register uint32 arg6, register uint32 arg7) { prolog mr r3,r4 mr r4,r5 mr r5,r6 mr r6,r7 mr r7,r8 mr r8,r9 mr r9,r10 epilog } /* * Some standard C library implementations */ extern "C" void *memcpy(void *dest, const void *src, size_t n); void *memcpy(void *dest, const void *src, size_t n) { BlockMoveData(src, dest, n); return dest; } extern "C" void *memset(void *s, int c, size_t n); void *memset(void *s, int c, size_t n) { if (c == 0) BlockZero(s, n); else { char *p = (char *)s; n++; while (--n) *p++ = c; } return s; } extern "C" int memcmp(const void *s1, const void *s2, size_t n); int memcmp(const void *s1, const void *s2, size_t n) { const unsigned char *d = (const unsigned char *)s1; const unsigned char *s = (const unsigned char *)s2; n++; while (--n) { int r; if (r = (*d - *s)) return r; ++d; ++s; } return 0; } extern "C" int printf(const char *format, ...); int printf(const char *format, ...) { return 0; } \ No newline at end of file diff --git a/SheepShaver/src/EthernetDriver/macos_util.h b/SheepShaver/src/EthernetDriver/macos_util.h deleted file mode 100644 index 20cc5ec4..00000000 --- a/SheepShaver/src/EthernetDriver/macos_util.h +++ /dev/null @@ -1 +0,0 @@ -#ifndef MACOS_UTIL_H #define MACOS_UTIL_H // Macro for calling MacOS routines #define CallMacOS(type, tvect) call_macos((uintptr)tvect) #define CallMacOS1(type, tvect, arg1) call_macos1((uintptr)tvect, (uintptr)arg1) #define CallMacOS2(type, tvect, arg1, arg2) call_macos2((uintptr)tvect, (uintptr)arg1, (uintptr)arg2) #define CallMacOS3(type, tvect, arg1, arg2, arg3) call_macos3((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3) #define CallMacOS4(type, tvect, arg1, arg2, arg3, arg4) call_macos4((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4) #define CallMacOS5(type, tvect, arg1, arg2, arg3, arg4, arg5) call_macos5((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5) #define CallMacOS6(type, tvect, arg1, arg2, arg3, arg4, arg5, arg6) call_macos6((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5, (uintptr)arg6) #define CallMacOS7(type, tvect, arg1, arg2, arg3, arg4, arg5, arg6, arg7) call_macos7((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5, (uintptr)arg6, (uintptr)arg7) #ifdef __cplusplus extern "C" { #endif extern uint32 call_macos(uint32 tvect); extern uint32 call_macos1(uint32 tvect, uint32 arg1); extern uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2); extern uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3); extern uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4); extern uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5); extern uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6); extern uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7); #ifdef __cplusplus } #endif // Construct four-character-code from string #define FOURCC(a,b,c,d) (((uint32)(a) << 24) | ((uint32)(b) << 16) | ((uint32)(c) << 8) | (uint32)(d)) extern uint32 FindLibSymbol(char *lib, char *sym); // Find symbol in shared library extern uint32 Mac_sysalloc(uint32 size); // Allocate block in MacOS system heap zone extern void Mac_sysfree(uint32 addr); // Release block occupied by the nonrelocatable block p #endif /* MACOS_UTIL_H */ \ No newline at end of file diff --git a/SheepShaver/src/EthernetDriver/sysdeps.h b/SheepShaver/src/EthernetDriver/sysdeps.h deleted file mode 100644 index ffd90e06..00000000 --- a/SheepShaver/src/EthernetDriver/sysdeps.h +++ /dev/null @@ -1 +0,0 @@ -#ifndef SYSDEPS_H #define SYSDEPS_H #include #define SIZEOF_VOID_P 4 #define WORDS_BIGENDIAN 1 #define REAL_ADDRESSING 1 /* Define to build the Ethernet driver completly in MacOS space */ #define BUILD_ETHER_FULL_DRIVER 1 #define ntohl(x) ((uint32)(x)) #define ntohs(x) ((uint16)(x)) #define assert(expr) typedef int bool; typedef signed char int8; typedef signed short int16; typedef signed int int32; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef uint32 uintptr; #endif /* SYSDEPS_H */ \ No newline at end of file diff --git a/SheepShaver/src/EthernetDriver/xlowmem.h b/SheepShaver/src/EthernetDriver/xlowmem.h deleted file mode 100644 index a37282b3..00000000 --- a/SheepShaver/src/EthernetDriver/xlowmem.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * xlowmem.h - Definitions for extra Low Memory globals (0x2800..) - * - * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef XLOWMEM_H -#define XLOWMEM_H - -// Modes for XLM_RUN_MODE -#define MODE_68K 0 // 68k emulator active -#define MODE_NATIVE 1 // Switched to native mode -#define MODE_EMUL_OP 2 // 68k emulator active, within EMUL_OP routine - -#define XLM_SIGNATURE 0x2800 // SheepShaver signature -#define XLM_KERNEL_DATA 0x2804 // Pointer to Kernel Data -#define XLM_TOC 0x2808 // TOC pointer of emulator -#define XLM_SHEEP_OBJ 0x280c // Pointer to SheepShaver object -#define XLM_RUN_MODE 0x2810 // Current run mode, see enum above -#define XLM_68K_R25 0x2814 // Contents of the 68k emulator's r25 (which contains the interrupt level), saved upon entering EMUL_OP mode, used by Execute68k() and the USR1 signal handler -#define XLM_IRQ_NEST 0x2818 // Interrupt disable nesting counter (>0: disabled) -#define XLM_PVR 0x281c // Theoretical PVR -#define XLM_BUS_CLOCK 0x2820 // Bus clock speed in Hz (for DriverServicesLib patch) -#define XLM_EMUL_RETURN_PROC 0x2824 // Pointer to EMUL_RETURN routine -#define XLM_EXEC_RETURN_PROC 0x2828 // Pointer to EXEC_RETURN routine -#define XLM_EMUL_OP_PROC 0x282c // Pointer to EMUL_OP routine -#define XLM_EMUL_RETURN_STACK 0x2830 // Stack pointer for EMUL_RETURN -#define XLM_RES_LIB_TOC 0x2834 // TOC pointer of Resources library -#define XLM_GET_RESOURCE 0x2838 // Pointer to native GetResource() routine -#define XLM_GET_1_RESOURCE 0x283c // Pointer to native Get1Resource() routine -#define XLM_GET_IND_RESOURCE 0x2840 // Pointer to native GetIndResource() routine -#define XLM_GET_1_IND_RESOURCE 0x2844 // Pointer to native Get1IndResource() routine -#define XLM_R_GET_RESOURCE 0x2848 // Pointer to native RGetResource() routine -#define XLM_EXEC_RETURN_OPCODE 0x284c // EXEC_RETURN opcode for Execute68k() -#define XLM_ZERO_PAGE 0x2850 // Pointer to read-only page with all bits set to 0 -#define XLM_R13 0x2854 // Pointer to .sdata section (Linux) - -#define XLM_ETHER_AO_GET_HWADDR 0x28b0 // Pointer to ethernet A0_get_ethernet_address() function -#define XLM_ETHER_AO_ADD_MULTI 0x28b4 // Pointer to ethernet A0_enable_multicast() function -#define XLM_ETHER_AO_DEL_MULTI 0x28b8 // Pointer to ethernet A0_disable_multicast() function -#define XLM_ETHER_AO_SEND_PACKET 0x28bc // Pointer to ethernet A0_transmit_packet() function -#define XLM_ETHER_INIT 0x28c0 // Pointer to ethernet InitStreamModule() function -#define XLM_ETHER_TERM 0x28c4 // Pointer to ethernet TerminateStreamModule() function -#define XLM_ETHER_OPEN 0x28c8 // Pointer to ethernet ether_open() function -#define XLM_ETHER_CLOSE 0x28cc // Pointer to ethernet ether_close() function -#define XLM_ETHER_WPUT 0x28d0 // Pointer to ethernet ether_wput() function -#define XLM_ETHER_RSRV 0x28d4 // Pointer to ethernet ether_rsrv() function -#define XLM_VIDEO_DOIO 0x28d8 // Pointer to video DoDriverIO() function - -#endif diff --git a/SheepShaver/src/EthernetDriverFull.i b/SheepShaver/src/EthernetDriverFull.i deleted file mode 100644 index 80df6395..00000000 --- a/SheepShaver/src/EthernetDriverFull.i +++ /dev/null @@ -1,737 +0,0 @@ - 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66, 0x70, 0x77, 0x70, 0x63, 0x00, 0x00, 0x00, 0x01, - 0xd1, 0x9b, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x28, 0xa4, 0x00, 0x00, 0x28, 0xa4, 0x00, 0x00, 0x28, 0xa4, 0x00, 0x00, 0x02, 0x20, - 0x00, 0x04, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, - 0x00, 0x00, 0x04, 0xd8, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x2a, 0xd0, 0x02, 0x01, 0x04, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x96, 0x00, 0x00, 0x00, 0x80, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x01, 0x40, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x17, 0x02, 0x00, 0x00, 0x21, 0x02, 0x00, 0x00, 0x2f, - 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x4b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x00, 0x00, 0x4a, 0x05, 0x42, 0x27, 0x80, 0x4b, 0x46, 0x08, 0x09, 0xc1, 0x01, 0x43, - 0x00, 0x41, 0x00, 0x41, 0x00, 0x42, 0x00, 0x41, 0x00, 0x42, 0x00, 0x81, 0x81, 0xc7, 0x40, 0x31, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4c, 0x69, 0x62, 0x00, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x5a, 0x65, 0x72, 0x6f, 0x00, 0x4e, 0x65, 0x77, 0x50, 0x74, 0x72, 0x53, 0x79, 0x73, - 0x00, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x6f, 0x76, 0x65, 0x44, 0x61, 0x74, 0x61, 0x00, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, - 0x46, 0x69, 0x6e, 0x64, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x00, 0x44, 0x69, 0x73, 0x70, 0x6f, - 0x73, 0x65, 0x50, 0x74, 0x72, 0x00, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x68, 0x65, 0x44, 0x72, - 0x69, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x6e, 0x69, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x47, - 0x65, 0x74, 0x4f, 0x54, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, - 0x00, 0x15, 0x5e, 0x85, 0x00, 0x14, 0xbd, 0xe0, 0x00, 0x10, 0x8f, 0x84, 0x00, 0x10, 0xae, 0x97, - 0x00, 0x10, 0x4e, 0x3c, 0x02, 0x00, 0x00, 0x56, 0x00, 0x00, 0x01, 0x34, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x01, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x3c, - 0x00, 0x01, 0x02, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x01, 0x04, 0x00, 0x01, 0x02, 0x00, 0x00, 0x9f, - 0x00, 0x00, 0x01, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x60, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x62, 0x02, 0x44, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x41, 0x00, 0x0c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x00, 0x28, 0xc0, 0x80, 0x40, 0x28, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, - 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x41, 0x00, 0x0c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x00, 0x28, 0xc4, 0x80, 0x40, 0x28, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, - 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x41, 0x00, 0x0c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x00, 0x28, 0xb0, 0x80, 0x40, 0x28, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, - 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x41, 0x00, 0x0c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x00, 0x28, 0xb4, 0x80, 0x40, 0x28, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, - 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x41, 0x00, 0x0c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x00, 0x28, 0xb8, 0x80, 0x40, 0x28, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, - 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x41, 0x00, 0x0c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x00, 0x28, 0xbc, 0x80, 0x40, 0x28, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, - 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, - 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x85, 0x23, 0x78, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x60, 0x1b, 0x78, - 0x7c, 0x04, 0x03, 0x78, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x62, 0x00, 0xfc, 0x48, 0x00, 0x23, 0xd5, - 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, - 0xbf, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x02, 0xa6, 0x3b, 0xe2, 0x05, 0x00, 0x3b, 0xa2, 0x02, 0xde, - 0x3b, 0xc2, 0x02, 0x62, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x1f, 0x00, 0x00, - 0x2c, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x01, 0x48, 0x00, 0x02, 0x68, - 0x38, 0x00, 0x00, 0x00, 0x38, 0x82, 0x02, 0x6f, 0x7f, 0xc3, 0xf3, 0x78, 0x90, 0x1f, 0x00, 0x00, - 0x48, 0x00, 0x22, 0x61, 0x90, 0x62, 0x00, 0xfc, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x02, 0x40, 0x38, 0x82, 0x02, 0x77, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x22, 0x41, 0x90, 0x62, 0x00, 0xf8, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x02, 0x20, 0x38, 0x82, 0x02, 0x7e, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x22, 0x21, 0x90, 0x62, 0x00, 0xf4, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x02, 0x00, 0x38, 0x82, 0x02, 0x87, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x22, 0x01, 0x90, 0x62, 0x00, 0xf0, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0xe0, 0x38, 0x82, 0x02, 0x8e, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0xe1, 0x90, 0x62, 0x00, 0xec, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0xc0, 0x38, 0x82, 0x02, 0x96, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0xc1, 0x90, 0x62, 0x00, 0xe8, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0xa0, 0x38, 0x82, 0x02, 0x9c, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0xa1, 0x90, 0x62, 0x00, 0xe4, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0x80, 0x38, 0x82, 0x02, 0xa2, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0x81, 0x90, 0x62, 0x00, 0xe0, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0x60, 0x38, 0x82, 0x02, 0xab, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0x61, 0x90, 0x62, 0x00, 0xdc, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0x40, 0x38, 0x82, 0x02, 0xb8, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0x41, 0x90, 0x62, 0x00, 0xd8, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0x20, 0x38, 0x82, 0x02, 0xc4, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0x21, 0x90, 0x62, 0x00, 0xd4, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0x00, 0x38, 0x82, 0x02, 0xcc, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x21, 0x01, 0x90, 0x62, 0x00, 0xd0, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0xe0, 0x38, 0x82, 0x02, 0xd4, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x20, 0xe1, 0x90, 0x62, 0x00, 0xcc, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0xc0, 0x38, 0x82, 0x02, 0xef, 0x7f, 0xa3, 0xeb, 0x78, - 0x48, 0x00, 0x20, 0xc1, 0x90, 0x62, 0x00, 0xc8, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0xa0, 0x38, 0x82, 0x03, 0x01, 0x7f, 0xa3, 0xeb, 0x78, - 0x48, 0x00, 0x20, 0xa1, 0x90, 0x62, 0x00, 0xc4, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x80, 0x38, 0x82, 0x03, 0x13, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x20, 0x81, 0x90, 0x62, 0x00, 0xc0, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x60, 0x38, 0x82, 0x03, 0x21, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x20, 0x61, 0x90, 0x62, 0x00, 0xbc, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x40, 0x38, 0x82, 0x03, 0x30, 0x7f, 0xc3, 0xf3, 0x78, - 0x48, 0x00, 0x20, 0x41, 0x90, 0x62, 0x00, 0xb8, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x38, 0x62, 0x02, 0x5c, - 0x90, 0x02, 0x01, 0x00, 0x4b, 0xff, 0xfc, 0x0d, 0x38, 0x00, 0x00, 0x01, 0x38, 0x60, 0x00, 0x01, - 0x90, 0x1f, 0x00, 0x00, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0xa1, 0xff, 0xf4, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0xff, 0xfc, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, - 0x4b, 0xff, 0xfd, 0x41, 0x54, 0x7f, 0x06, 0x3e, 0x80, 0x62, 0x00, 0x40, 0x4b, 0xff, 0xfb, 0x25, - 0x2c, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x08, 0x3b, 0xe0, 0x00, 0x00, 0x57, 0xe3, 0x06, 0x3e, - 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, 0x83, 0xe1, 0xff, 0xfc, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x02, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0c, 0x38, 0x62, 0x03, 0x3d, 0x48, 0x00, 0x22, 0xa5, - 0x38, 0x62, 0x05, 0x00, 0x38, 0x00, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x48, - 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x4b, 0xff, 0xff, 0xb5, - 0x4b, 0xff, 0xfa, 0xf1, 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x93, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7f, 0x1b, 0x78, 0x7c, 0xc9, 0x33, 0x78, - 0x39, 0x02, 0x05, 0x00, 0x7c, 0xea, 0x3b, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, - 0x80, 0x08, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x40, 0x82, 0x00, 0x14, 0x38, 0x62, 0x03, 0x7c, - 0x48, 0x00, 0x22, 0x21, 0x38, 0x60, 0x00, 0x06, 0x48, 0x00, 0x00, 0x68, 0x80, 0x1f, 0x00, 0x14, - 0x28, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x54, - 0x80, 0x62, 0x00, 0xc0, 0x7c, 0x87, 0x23, 0x78, 0x7c, 0xa8, 0x2b, 0x78, 0x7f, 0xe6, 0xfb, 0x78, - 0x38, 0x82, 0x01, 0x00, 0x38, 0xa0, 0x00, 0x38, 0x48, 0x00, 0x20, 0x89, 0x2c, 0x03, 0x00, 0x00, - 0x41, 0x82, 0x00, 0x08, 0x48, 0x00, 0x00, 0x2c, 0x80, 0x9f, 0x00, 0x14, 0x38, 0x00, 0x00, 0x00, - 0x38, 0x60, 0x00, 0x00, 0x93, 0xe4, 0x00, 0x18, 0x90, 0x04, 0x00, 0x04, 0x90, 0x04, 0x00, 0x08, - 0xb0, 0x04, 0x00, 0x0c, 0x90, 0x04, 0x00, 0x10, 0x90, 0x04, 0x00, 0x14, 0x90, 0x04, 0x00, 0x34, - 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x83, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7c, 0x1b, 0x78, 0x38, 0x82, 0x05, 0x00, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x04, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, - 0x40, 0x82, 0x00, 0x14, 0x38, 0x62, 0x03, 0xad, 0x48, 0x00, 0x21, 0x69, 0x38, 0x60, 0x00, 0x06, - 0x48, 0x00, 0x00, 0xb8, 0x83, 0xbc, 0x00, 0x14, 0x28, 0x1d, 0x00, 0x00, 0x40, 0x82, 0x00, 0x88, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0xa4, 0x48, 0x00, 0x00, 0x7c, 0x38, 0x63, 0x00, 0x04, - 0x4b, 0xff, 0xfa, 0xb1, 0x83, 0xdd, 0x00, 0x34, 0x3b, 0xfe, 0x00, 0x04, 0x48, 0x00, 0x00, 0x20, - 0x7f, 0xe3, 0xfb, 0x78, 0x38, 0x9e, 0x00, 0x04, 0x38, 0xa0, 0x00, 0x06, 0x48, 0x00, 0x20, 0xd5, - 0x2c, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x83, 0xde, 0x00, 0x00, 0x28, 0x1e, 0x00, 0x00, - 0x40, 0x82, 0xff, 0xe0, 0x48, 0x00, 0x00, 0x40, 0x38, 0x9d, 0x00, 0x34, 0x48, 0x00, 0x00, 0x30, - 0x60, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x7c, 0x00, 0xf0, 0x40, 0x40, 0x82, 0x00, 0x1c, - 0x80, 0x1e, 0x00, 0x00, 0x7f, 0xc3, 0xf3, 0x78, 0x90, 0x04, 0x00, 0x00, 0x48, 0x00, 0x1e, 0x65, - 0x48, 0x00, 0x00, 0x14, 0x60, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x03, 0x78, 0x28, 0x04, 0x00, 0x00, - 0x40, 0x82, 0xff, 0xd4, 0x80, 0x7d, 0x00, 0x34, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0xff, 0x80, - 0x38, 0x00, 0x00, 0x00, 0x7f, 0x85, 0xe3, 0x78, 0x90, 0x1d, 0x00, 0x34, 0x38, 0x82, 0x01, 0x00, - 0x80, 0x62, 0x00, 0xbc, 0x48, 0x00, 0x1e, 0xad, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, - 0xbb, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x38, 0xc2, 0x05, 0x00, 0x7c, 0x69, 0x1b, 0x78, 0x7c, 0x85, 0x23, 0x78, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x06, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, - 0x40, 0x82, 0x00, 0x14, 0x38, 0x62, 0x03, 0xdf, 0x48, 0x00, 0x20, 0x69, 0x38, 0x60, 0x00, 0x06, - 0x48, 0x00, 0x01, 0x8c, 0x81, 0x09, 0x00, 0x14, 0x28, 0x08, 0x00, 0x00, 0x40, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x06, 0x48, 0x00, 0x01, 0x78, 0x80, 0xc5, 0x00, 0x14, 0x88, 0x06, 0x00, 0x0d, - 0x2c, 0x00, 0x00, 0x0e, 0x41, 0x82, 0x01, 0x30, 0x40, 0x80, 0x00, 0x1c, 0x2c, 0x00, 0x00, 0x01, - 0x41, 0x82, 0x00, 0x48, 0x40, 0x80, 0x01, 0x38, 0x2c, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x20, - 0x48, 0x00, 0x01, 0x2c, 0x2c, 0x00, 0x00, 0x86, 0x41, 0x82, 0x01, 0x1c, 0x40, 0x80, 0x01, 0x20, - 0x2c, 0x00, 0x00, 0x83, 0x41, 0x82, 0x00, 0x24, 0x48, 0x00, 0x01, 0x14, 0x38, 0xc2, 0x04, 0xf4, - 0x7c, 0xa3, 0x2b, 0x78, 0x80, 0x86, 0x00, 0x00, 0x38, 0x04, 0x00, 0x01, 0x90, 0x06, 0x00, 0x00, - 0x48, 0x00, 0x08, 0x31, 0x48, 0x00, 0x01, 0x04, 0x80, 0x65, 0x00, 0x0c, 0x80, 0xc3, 0x00, 0x00, - 0x28, 0x06, 0x00, 0x31, 0x41, 0x81, 0x00, 0xb8, 0x38, 0x62, 0x04, 0x10, 0x54, 0xc0, 0x10, 0x3a, - 0x7c, 0x63, 0x00, 0x2e, 0x7c, 0x69, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x38, 0xe2, 0x04, 0xf0, - 0x7d, 0x03, 0x43, 0x78, 0x7d, 0x24, 0x4b, 0x78, 0x80, 0xc7, 0x00, 0x00, 0x38, 0x06, 0x00, 0x01, - 0x90, 0x07, 0x00, 0x00, 0x48, 0x00, 0x1a, 0xad, 0x48, 0x00, 0x00, 0xc0, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x0e, 0x8d, 0x48, 0x00, 0x00, 0xb0, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x10, 0x8d, 0x48, 0x00, 0x00, 0xa0, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x11, 0x9d, 0x48, 0x00, 0x00, 0x90, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x13, 0x7d, 0x48, 0x00, 0x00, 0x80, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x14, 0x1d, 0x48, 0x00, 0x00, 0x70, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x16, 0x2d, 0x48, 0x00, 0x00, 0x60, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x17, 0x7d, 0x48, 0x00, 0x00, 0x50, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x18, 0xad, 0x48, 0x00, 0x00, 0x40, 0x7d, 0x03, 0x43, 0x78, - 0x7d, 0x24, 0x4b, 0x78, 0x38, 0xe0, 0x00, 0x12, 0x39, 0x00, 0x00, 0x00, 0x48, 0x00, 0x0c, 0x95, - 0x48, 0x00, 0x00, 0x28, 0x7d, 0x03, 0x43, 0x78, 0x7d, 0x24, 0x4b, 0x78, 0x48, 0x00, 0x00, 0xd5, - 0x48, 0x00, 0x00, 0x18, 0x48, 0x00, 0x02, 0xcd, 0x48, 0x00, 0x00, 0x10, 0x80, 0x62, 0x00, 0xf4, - 0x7c, 0xa4, 0x2b, 0x78, 0x48, 0x00, 0x1c, 0x9d, 0x38, 0xa2, 0x04, 0xfc, 0x38, 0x60, 0x00, 0x00, - 0x80, 0x85, 0x00, 0x00, 0x38, 0x04, 0x00, 0x01, 0x90, 0x05, 0x00, 0x00, 0x80, 0x01, 0x00, 0x48, - 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0xc1, 0xff, 0xf8, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7e, 0x1b, 0x78, 0x90, 0x01, 0x00, 0x08, - 0x94, 0x21, 0xff, 0xc0, 0x48, 0x00, 0x00, 0x4c, 0x80, 0x62, 0x00, 0xd8, 0x7f, 0xc4, 0xf3, 0x78, - 0x48, 0x00, 0x1c, 0x51, 0x28, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x18, 0x80, 0x62, 0x00, 0xe0, - 0x7f, 0xc4, 0xf3, 0x78, 0x7f, 0xe5, 0xfb, 0x78, 0x48, 0x00, 0x1c, 0x89, 0x48, 0x00, 0x00, 0x24, - 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xe4, 0xfb, 0x78, 0x48, 0x00, 0x1c, 0x29, 0x80, 0x62, 0x00, 0xd0, - 0x7f, 0xc4, 0xf3, 0x78, 0x38, 0xa0, 0x00, 0x00, 0x48, 0x00, 0x1c, 0x69, 0x48, 0x00, 0x00, 0x18, - 0x80, 0x62, 0x00, 0xe8, 0x7f, 0xc4, 0xf3, 0x78, 0x48, 0x00, 0x1c, 0x09, 0x7c, 0x7f, 0x1b, 0x79, - 0x40, 0x82, 0xff, 0xa8, 0x38, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, - 0x7c, 0x08, 0x03, 0xa6, 0xbb, 0xc1, 0xff, 0xf8, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0xbe, 0x2b, 0x78, 0x7c, 0x7c, 0x1b, 0x78, - 0x7c, 0x9d, 0x23, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x83, 0xe5, 0x00, 0x0c, - 0x80, 0x1f, 0x00, 0x00, 0x2c, 0x00, 0x4f, 0x03, 0x41, 0x82, 0x01, 0x04, 0x40, 0x80, 0x00, 0x10, - 0x2c, 0x00, 0x4f, 0x02, 0x40, 0x80, 0x00, 0x14, 0x48, 0x00, 0x01, 0x2c, 0x2c, 0x00, 0x6c, 0x0a, - 0x41, 0x82, 0x00, 0x88, 0x48, 0x00, 0x01, 0x20, 0x80, 0x9e, 0x00, 0x08, 0x28, 0x04, 0x00, 0x00, - 0x41, 0x82, 0x00, 0x18, 0x80, 0x64, 0x00, 0x0c, 0x80, 0x04, 0x00, 0x10, 0x7c, 0x03, 0x00, 0x50, - 0x28, 0x00, 0x00, 0x04, 0x41, 0x82, 0x00, 0x10, 0x38, 0x00, 0x00, 0x16, 0x90, 0x1f, 0x00, 0x10, - 0x48, 0x00, 0x01, 0x5c, 0x80, 0x63, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x01, 0x28, 0x00, 0xff, 0xff, - 0x41, 0x82, 0x00, 0x14, 0x20, 0x03, 0x00, 0x08, 0x7c, 0x00, 0x00, 0x34, 0x54, 0x00, 0xd9, 0x7e, - 0x90, 0x1c, 0x00, 0x10, 0x38, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x00, 0x08, 0x80, 0x62, 0x00, 0xf4, - 0x48, 0x00, 0x1b, 0x41, 0x80, 0x1c, 0x00, 0x10, 0x2c, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, - 0x38, 0x00, 0x00, 0x08, 0x90, 0x1f, 0x00, 0x14, 0x48, 0x00, 0x00, 0xb8, 0x38, 0x00, 0x00, 0x01, - 0x90, 0x1f, 0x00, 0x14, 0x48, 0x00, 0x00, 0xac, 0x80, 0x62, 0x00, 0xf0, 0x80, 0x9e, 0x00, 0x08, - 0x48, 0x00, 0x1b, 0x11, 0x7c, 0x64, 0x1b, 0x79, 0x40, 0x82, 0x00, 0x10, 0x38, 0x00, 0x00, 0x0c, - 0x90, 0x1f, 0x00, 0x10, 0x48, 0x00, 0x00, 0xe8, 0x80, 0xc4, 0x00, 0x14, 0x38, 0x00, 0x00, 0x01, - 0x7f, 0x83, 0xe3, 0x78, 0x38, 0xa0, 0x00, 0x01, 0x98, 0x06, 0x00, 0x0d, 0x48, 0x00, 0x03, 0x65, - 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x10, 0x38, 0x00, 0x00, 0x0c, 0x90, 0x1f, 0x00, 0x10, - 0x48, 0x00, 0x00, 0xbc, 0x80, 0x9e, 0x00, 0x08, 0x90, 0x64, 0x00, 0x08, 0x80, 0x1c, 0x00, 0x08, - 0x60, 0x00, 0x00, 0x08, 0x90, 0x1c, 0x00, 0x08, 0x48, 0x00, 0x00, 0x48, 0x80, 0x9e, 0x00, 0x08, - 0x28, 0x04, 0x00, 0x00, 0x41, 0x82, 0x00, 0x18, 0x80, 0x64, 0x00, 0x0c, 0x80, 0x04, 0x00, 0x10, - 0x7c, 0x03, 0x00, 0x50, 0x28, 0x00, 0x00, 0x04, 0x41, 0x82, 0x00, 0x10, 0x38, 0x00, 0x00, 0x16, - 0x90, 0x1f, 0x00, 0x10, 0x48, 0x00, 0x00, 0x78, 0x38, 0x00, 0x00, 0x01, 0x90, 0x1c, 0x00, 0x14, - 0x48, 0x00, 0x00, 0x10, 0x38, 0x00, 0x00, 0x16, 0x90, 0x1f, 0x00, 0x10, 0x48, 0x00, 0x00, 0x60, - 0x38, 0x00, 0x00, 0x00, 0x7f, 0xc5, 0xf3, 0x78, 0x90, 0x1f, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x1c, - 0x80, 0x65, 0x00, 0x0c, 0x80, 0x05, 0x00, 0x10, 0x80, 0x9f, 0x00, 0x0c, 0x7c, 0x03, 0x00, 0x50, - 0x7c, 0x04, 0x02, 0x14, 0x90, 0x1f, 0x00, 0x0c, 0x80, 0xa5, 0x00, 0x08, 0x28, 0x05, 0x00, 0x00, - 0x40, 0x82, 0xff, 0xe0, 0x38, 0x60, 0x00, 0x00, 0x38, 0x00, 0x00, 0x81, 0x90, 0x7f, 0x00, 0x10, - 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, 0x80, 0x7e, 0x00, 0x14, 0x98, 0x03, 0x00, 0x0d, - 0x80, 0x62, 0x00, 0xd4, 0x48, 0x00, 0x1a, 0x6d, 0x48, 0x00, 0x00, 0x20, 0x80, 0x7e, 0x00, 0x14, - 0x38, 0x00, 0x00, 0x82, 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, 0x98, 0x03, 0x00, 0x0d, - 0x80, 0x62, 0x00, 0xd4, 0x48, 0x00, 0x1a, 0x4d, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, - 0xbb, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x9e, 0x23, 0x78, 0x7c, 0x7d, 0x1b, 0x78, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x83, 0xe4, 0x00, 0x0c, 0x88, 0x1f, 0x00, 0x00, - 0x54, 0x00, 0x07, 0xbd, 0x41, 0x82, 0x00, 0x14, 0x80, 0x62, 0x00, 0xd0, 0x7f, 0xa4, 0xeb, 0x78, - 0x38, 0xa0, 0x00, 0x01, 0x48, 0x00, 0x19, 0xfd, 0x88, 0x1f, 0x00, 0x00, 0x54, 0x00, 0x07, 0xff, - 0x41, 0x82, 0x00, 0x34, 0x80, 0x62, 0x00, 0xd0, 0x38, 0x9d, 0xff, 0xc0, 0x38, 0xa0, 0x00, 0x01, - 0x48, 0x00, 0x19, 0xe1, 0x88, 0x1f, 0x00, 0x00, 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, - 0x54, 0x00, 0x07, 0xfa, 0x98, 0x1f, 0x00, 0x00, 0x80, 0x62, 0x00, 0xd4, 0x48, 0x00, 0x19, 0xc5, - 0x48, 0x00, 0x00, 0x10, 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xc4, 0xf3, 0x78, 0x48, 0x00, 0x19, 0x65, - 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x54, 0x63, 0x04, 0x3e, 0x2c, 0x03, 0x05, 0xdd, 0x41, 0x80, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x00, - 0x4e, 0x80, 0x00, 0x20, 0x2c, 0x03, 0x00, 0xff, 0x40, 0x82, 0x00, 0x18, 0x54, 0x80, 0x04, 0x3e, - 0x2c, 0x00, 0x00, 0xff, 0x40, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x04, 0x4e, 0x80, 0x00, 0x20, - 0x2c, 0x03, 0x00, 0xaa, 0x40, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x03, 0x4e, 0x80, 0x00, 0x20, - 0x2c, 0x03, 0x00, 0xff, 0x38, 0x60, 0x00, 0x05, 0x4d, 0x81, 0x00, 0x20, 0x38, 0x60, 0x00, 0x01, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x88, 0x03, 0x00, 0x00, 0x54, 0x00, 0x07, 0xff, 0x41, 0x82, 0x00, 0x30, 0x80, 0x83, 0x00, 0x00, - 0x3c, 0x04, 0x00, 0x01, 0x28, 0x00, 0xff, 0xff, 0x40, 0x82, 0x00, 0x18, 0xa0, 0x03, 0x00, 0x04, - 0x28, 0x00, 0xff, 0xff, 0x40, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x02, 0x4e, 0x80, 0x00, 0x20, - 0x38, 0x60, 0x00, 0x01, 0x4e, 0x80, 0x00, 0x20, 0x38, 0x60, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, - 0xbf, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7f, 0x1b, 0x78, 0x7c, 0x9d, 0x23, 0x78, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0xa3, 0x00, 0x14, 0x88, 0x05, 0x00, 0x0c, - 0x28, 0x00, 0x00, 0x01, 0x40, 0x82, 0x00, 0x44, 0x80, 0x65, 0x00, 0x04, 0x57, 0xa4, 0x04, 0x3e, - 0x80, 0x05, 0x00, 0x08, 0x7c, 0x03, 0x00, 0x50, 0x7c, 0x00, 0x20, 0x00, 0x41, 0x80, 0x00, 0x2c, - 0x38, 0x00, 0x00, 0x00, 0x98, 0x05, 0x00, 0x0d, 0x80, 0x7f, 0x00, 0x14, 0x80, 0x03, 0x00, 0x04, - 0x90, 0x1f, 0x00, 0x0c, 0x80, 0x7f, 0x00, 0x14, 0x80, 0x03, 0x00, 0x04, 0x7c, 0x00, 0x22, 0x14, - 0x90, 0x1f, 0x00, 0x10, 0x48, 0x00, 0x00, 0x9c, 0x83, 0xdf, 0x00, 0x08, 0x38, 0x00, 0x00, 0x00, - 0x7f, 0xe4, 0xfb, 0x78, 0x90, 0x1f, 0x00, 0x08, 0x80, 0x62, 0x00, 0xf4, 0x48, 0x00, 0x18, 0x25, - 0x28, 0x1e, 0x00, 0x00, 0x7f, 0xdf, 0xf3, 0x78, 0x41, 0x82, 0x00, 0x38, 0x80, 0x7e, 0x00, 0x14, - 0x88, 0x03, 0x00, 0x0c, 0x28, 0x00, 0x00, 0x01, 0x40, 0x82, 0x00, 0x28, 0x80, 0x63, 0x00, 0x04, - 0x57, 0xa0, 0x04, 0x3e, 0x80, 0x9e, 0x00, 0x0c, 0x7c, 0x63, 0x20, 0x50, 0x7c, 0x03, 0x00, 0x00, - 0x41, 0x80, 0x00, 0x10, 0x7c, 0x00, 0x20, 0x50, 0x90, 0x1e, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x44, - 0x57, 0xbe, 0x04, 0x3e, 0x38, 0x80, 0x00, 0x03, 0x7f, 0xc3, 0xf3, 0x78, 0x4b, 0xff, 0xf4, 0x35, - 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x18, 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xe4, 0xfb, 0x78, - 0x48, 0x00, 0x17, 0xc1, 0x3b, 0xe0, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, 0x93, 0xe3, 0x00, 0x08, - 0x7c, 0x7f, 0x1b, 0x78, 0x80, 0x03, 0x00, 0x10, 0x7c, 0x00, 0xf2, 0x14, 0x90, 0x03, 0x00, 0x10, - 0x7f, 0xe3, 0xfb, 0x78, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0x7c, 0x08, 0x03, 0xa6, - 0xbb, 0xa1, 0xff, 0xf4, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x01, 0xff, 0xe0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7e, 0x1b, 0x78, 0x7c, 0x9f, 0x23, 0x78, - 0x7c, 0xb8, 0x2b, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0x90, 0x80, 0x64, 0x00, 0x0c, - 0x80, 0x03, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x41, 0x82, 0x00, 0x14, 0x80, 0x62, 0x00, 0xf4, - 0x48, 0x00, 0x17, 0x51, 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x01, 0xc4, 0x83, 0x63, 0x00, 0x04, - 0x80, 0x03, 0x00, 0x08, 0x2c, 0x1b, 0x00, 0x08, 0x7f, 0x83, 0x02, 0x14, 0x41, 0x82, 0x00, 0x28, - 0x40, 0x80, 0x00, 0x10, 0x2c, 0x1b, 0x00, 0x06, 0x41, 0x82, 0x00, 0x14, 0x48, 0x00, 0x00, 0x28, - 0x2c, 0x1b, 0x00, 0x0d, 0x41, 0x82, 0x00, 0x18, 0x48, 0x00, 0x00, 0x1c, 0xa3, 0x5e, 0x00, 0x0c, - 0x48, 0x00, 0x00, 0x18, 0xa3, 0x5c, 0x00, 0x06, 0x48, 0x00, 0x00, 0x10, 0xa3, 0x5c, 0x00, 0x06, - 0x48, 0x00, 0x00, 0x08, 0xa3, 0x5e, 0x00, 0x0c, 0x80, 0x62, 0x00, 0xcc, 0x7f, 0xe4, 0xfb, 0x78, - 0x48, 0x00, 0x16, 0xf1, 0x54, 0x79, 0x04, 0x3e, 0xa0, 0x7e, 0x00, 0x0c, 0x7f, 0x44, 0xd3, 0x78, - 0x4b, 0xff, 0xfd, 0xa1, 0x54, 0x7d, 0x04, 0x3e, 0x2c, 0x1d, 0x00, 0x02, 0x41, 0x82, 0x00, 0x8c, - 0x40, 0x80, 0x00, 0x14, 0x2c, 0x1d, 0x00, 0x00, 0x41, 0x82, 0x00, 0x1c, 0x40, 0x80, 0x00, 0x24, - 0x48, 0x00, 0x00, 0x78, 0x2c, 0x1d, 0x00, 0x04, 0x41, 0x82, 0x00, 0x58, 0x40, 0x80, 0x00, 0x6c, - 0x48, 0x00, 0x00, 0x30, 0x7f, 0x59, 0xd3, 0x78, 0x3b, 0x00, 0x00, 0x0e, 0x48, 0x00, 0x00, 0x64, - 0x2c, 0x18, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x11, 0x41, 0x82, 0x00, 0x0c, 0x3b, 0x20, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x50, 0x38, 0x19, 0x00, 0x03, 0x54, 0x19, 0x04, 0x3e, 0x48, 0x00, 0x00, 0x44, - 0x2c, 0x18, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x16, 0x41, 0x82, 0x00, 0x0c, 0x3b, 0x20, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x30, 0x38, 0x19, 0x00, 0x08, 0x54, 0x19, 0x04, 0x3e, 0x48, 0x00, 0x00, 0x24, - 0x2c, 0x18, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x0e, 0x41, 0x82, 0x00, 0x18, 0x3b, 0x20, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x0c, 0x3b, 0x00, 0x00, 0x0e, 0x7f, 0x59, 0xd3, 0x78, - 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0x65, 0xdb, 0x78, 0x38, 0x61, 0x00, 0x38, 0x48, 0x00, 0x17, 0x85, - 0x7f, 0xe3, 0xfb, 0x78, 0x7f, 0x04, 0xc3, 0x78, 0x4b, 0xff, 0xfd, 0x89, 0x7c, 0x7f, 0x1b, 0x79, - 0x40, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x94, 0x80, 0x9f, 0x00, 0x0c, - 0x2c, 0x1d, 0x00, 0x02, 0xb3, 0x24, 0x00, 0x0c, 0x80, 0x01, 0x00, 0x38, 0x90, 0x04, 0x00, 0x00, - 0xa0, 0x01, 0x00, 0x3c, 0xb0, 0x04, 0x00, 0x04, 0x41, 0x82, 0x00, 0x70, 0x40, 0x80, 0x00, 0x10, - 0x2c, 0x1d, 0x00, 0x01, 0x40, 0x80, 0x00, 0x14, 0x48, 0x00, 0x00, 0x60, 0x2c, 0x1d, 0x00, 0x04, - 0x40, 0x80, 0x00, 0x58, 0x48, 0x00, 0x00, 0x1c, 0x9b, 0x44, 0x00, 0x0e, 0x38, 0x00, 0x00, 0x03, - 0xa0, 0x7e, 0x00, 0x0c, 0x98, 0x64, 0x00, 0x0f, 0x98, 0x04, 0x00, 0x10, 0x48, 0x00, 0x00, 0x3c, - 0x9b, 0x44, 0x00, 0x0e, 0x38, 0x00, 0x00, 0x03, 0x28, 0x1b, 0x00, 0x0d, 0xa0, 0x7e, 0x00, 0x0c, - 0x98, 0x64, 0x00, 0x0f, 0x98, 0x04, 0x00, 0x10, 0x41, 0x80, 0x00, 0x0c, 0x38, 0x61, 0x00, 0x40, - 0x48, 0x00, 0x00, 0x08, 0x38, 0x7e, 0x00, 0x2c, 0x80, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x11, - 0x88, 0x03, 0x00, 0x04, 0x98, 0x04, 0x00, 0x15, 0x7f, 0xe3, 0xfb, 0x78, 0x80, 0x01, 0x00, 0x78, - 0x38, 0x21, 0x00, 0x70, 0xbb, 0x01, 0xff, 0xe0, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, - 0xbf, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7d, 0x1b, 0x78, 0x3b, 0xe2, 0x02, 0x5c, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x83, 0xc3, 0x00, 0x0c, 0xa0, 0x1e, 0x00, 0x0c, - 0x28, 0x00, 0x00, 0x00, 0x40, 0x82, 0x00, 0x18, 0x80, 0x62, 0x00, 0xcc, 0x7f, 0xa4, 0xeb, 0x78, - 0x48, 0x00, 0x15, 0x41, 0x38, 0x03, 0xff, 0xf2, 0xb0, 0x1e, 0x00, 0x0c, 0x80, 0x1f, 0x00, 0x00, - 0x7f, 0xa3, 0xeb, 0x78, 0x90, 0x1e, 0x00, 0x06, 0xa0, 0x1f, 0x00, 0x04, 0xb0, 0x1e, 0x00, 0x0a, - 0x4b, 0xff, 0xf1, 0x31, 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xa4, 0xeb, 0x78, 0x48, 0x00, 0x15, 0x15, - 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x21, 0xff, 0xe4, 0x7c, 0x08, 0x02, 0xa6, 0x54, 0xb9, 0x04, 0x3e, 0x7c, 0x7b, 0x1b, 0x78, - 0x2c, 0x19, 0x00, 0x02, 0x7c, 0x9c, 0x23, 0x78, 0x7c, 0xdd, 0x33, 0x78, 0x90, 0x01, 0x00, 0x08, - 0x94, 0x21, 0xff, 0xa0, 0x41, 0x82, 0x00, 0x38, 0x40, 0x80, 0x00, 0x10, 0x2c, 0x19, 0x00, 0x01, - 0x40, 0x80, 0x00, 0x14, 0x48, 0x00, 0x00, 0x28, 0x2c, 0x19, 0x00, 0x04, 0x40, 0x80, 0x00, 0x20, - 0x48, 0x00, 0x00, 0x10, 0x3b, 0xe0, 0x00, 0x08, 0x3b, 0xc0, 0x00, 0x11, 0x48, 0x00, 0x00, 0x18, - 0x3b, 0xe0, 0x00, 0x0d, 0x3b, 0xc0, 0x00, 0x16, 0x48, 0x00, 0x00, 0x0c, 0x3b, 0xe0, 0x00, 0x08, - 0x3b, 0xc0, 0x00, 0x0e, 0x80, 0x1b, 0x00, 0x08, 0x54, 0x00, 0x07, 0x39, 0x41, 0x82, 0x00, 0x48, - 0x2c, 0x1d, 0x00, 0x00, 0x40, 0x82, 0x00, 0x40, 0x80, 0x1b, 0x00, 0x14, 0x2c, 0x00, 0x00, 0x00, - 0x40, 0x82, 0x00, 0x10, 0x80, 0x1c, 0x00, 0x0c, 0x7c, 0x00, 0xf2, 0x14, 0x90, 0x1c, 0x00, 0x0c, - 0x38, 0xc2, 0x04, 0xe4, 0x7f, 0x85, 0xe3, 0x78, 0x80, 0x62, 0x00, 0xe4, 0x80, 0x86, 0x00, 0x00, - 0x38, 0x04, 0x00, 0x01, 0x90, 0x06, 0x00, 0x00, 0x80, 0x9b, 0x00, 0x18, 0x48, 0x00, 0x14, 0x95, - 0x48, 0x00, 0x01, 0x2c, 0x57, 0xe3, 0x08, 0x3c, 0x38, 0x80, 0x00, 0x03, 0x3b, 0x43, 0x00, 0x18, - 0x7f, 0x43, 0xd3, 0x78, 0x4b, 0xff, 0xf0, 0x8d, 0x28, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x24, - 0x80, 0x62, 0x00, 0xf4, 0x7f, 0x84, 0xe3, 0x78, 0x48, 0x00, 0x14, 0x19, 0x38, 0x82, 0x04, 0xd8, - 0x80, 0x64, 0x00, 0x00, 0x38, 0x03, 0x00, 0x01, 0x90, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0xf0, - 0x80, 0xc3, 0x00, 0x14, 0x38, 0xe0, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x08, 0x38, 0x80, 0x00, 0x18, - 0x38, 0x1f, 0x00, 0x18, 0x98, 0xe6, 0x00, 0x0d, 0x2c, 0x19, 0x00, 0x03, 0x80, 0xe3, 0x00, 0x0c, - 0x90, 0xa7, 0x00, 0x00, 0x80, 0xa3, 0x00, 0x10, 0x7c, 0xa5, 0xd2, 0x14, 0x90, 0xa3, 0x00, 0x10, - 0x93, 0x83, 0x00, 0x08, 0x93, 0xe7, 0x00, 0x04, 0x90, 0x87, 0x00, 0x08, 0x93, 0xe7, 0x00, 0x0c, - 0x90, 0x07, 0x00, 0x10, 0x93, 0xa7, 0x00, 0x14, 0x81, 0x1c, 0x00, 0x0c, 0x80, 0xc3, 0x00, 0x0c, - 0x80, 0xa7, 0x00, 0x08, 0x80, 0x87, 0x00, 0x10, 0x80, 0x08, 0x00, 0x00, 0x7c, 0xa6, 0x2a, 0x14, - 0x7c, 0x86, 0x22, 0x14, 0x90, 0x05, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x04, 0xb0, 0x05, 0x00, 0x04, - 0x80, 0x08, 0x00, 0x06, 0x90, 0x04, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x0a, 0xb0, 0x04, 0x00, 0x04, - 0x88, 0x08, 0x00, 0x0e, 0xb0, 0x05, 0x00, 0x06, 0x88, 0x08, 0x00, 0x0f, 0xb0, 0x04, 0x00, 0x06, - 0x40, 0x82, 0x00, 0x24, 0x80, 0x08, 0x00, 0x11, 0x90, 0x05, 0x00, 0x08, 0x88, 0x08, 0x00, 0x15, - 0x98, 0x05, 0x00, 0x0c, 0x80, 0x08, 0x00, 0x11, 0x90, 0x04, 0x00, 0x08, 0x88, 0x08, 0x00, 0x15, - 0x98, 0x04, 0x00, 0x0c, 0x80, 0x1b, 0x00, 0x14, 0x2c, 0x00, 0x00, 0x00, 0x40, 0x82, 0x00, 0x10, - 0x80, 0x1c, 0x00, 0x0c, 0x7c, 0x00, 0xf2, 0x14, 0x90, 0x1c, 0x00, 0x0c, 0x38, 0xc2, 0x04, 0xe8, - 0x7c, 0x65, 0x1b, 0x78, 0x80, 0x62, 0x00, 0xe4, 0x80, 0x86, 0x00, 0x00, 0x38, 0x04, 0x00, 0x01, - 0x90, 0x06, 0x00, 0x00, 0x80, 0x9b, 0x00, 0x18, 0x48, 0x00, 0x13, 0x69, 0x80, 0x01, 0x00, 0x68, - 0x38, 0x21, 0x00, 0x60, 0xbb, 0x21, 0xff, 0xe4, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, - 0xbe, 0x21, 0xff, 0xc4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7f, 0x1b, 0x78, 0x90, 0x01, 0x00, 0x08, - 0x94, 0x21, 0xff, 0x80, 0x83, 0xc3, 0x00, 0x0c, 0xa3, 0xbe, 0x00, 0x0c, 0x2c, 0x1d, 0x05, 0xdd, - 0x41, 0x80, 0x00, 0x0c, 0x7f, 0xa3, 0xeb, 0x78, 0x48, 0x00, 0x00, 0x0c, 0x8b, 0xbe, 0x00, 0x0e, - 0x88, 0x7e, 0x00, 0x0f, 0x7f, 0xa4, 0xeb, 0x78, 0x4b, 0xff, 0xf9, 0x89, 0x7c, 0x60, 0x1b, 0x78, - 0x7f, 0xc3, 0xf3, 0x78, 0x7c, 0x1c, 0x03, 0x78, 0x4b, 0xff, 0xf9, 0xd9, 0x83, 0x42, 0x01, 0x00, - 0x38, 0x80, 0x00, 0x01, 0x57, 0xa0, 0xfe, 0xfe, 0x7c, 0x7b, 0x1b, 0x78, 0x7f, 0xf2, 0xfb, 0x78, - 0x57, 0x96, 0x04, 0x3e, 0x57, 0xb5, 0x07, 0xfe, 0x7c, 0x94, 0x00, 0x30, 0x57, 0xb3, 0xe7, 0x3a, - 0x3b, 0x20, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0xe0, 0x00, 0x00, 0x48, 0x00, 0x01, 0x6c, - 0x80, 0x1a, 0x00, 0x04, 0x28, 0x00, 0x00, 0x00, 0x41, 0x82, 0x01, 0x50, 0x80, 0x1a, 0x00, 0x08, - 0x54, 0x03, 0x07, 0x7b, 0x41, 0x82, 0x00, 0x10, 0x57, 0xa3, 0x04, 0x3e, 0x28, 0x03, 0x00, 0xff, - 0x40, 0x81, 0x00, 0xac, 0xa0, 0x7a, 0x00, 0x0c, 0x57, 0xa4, 0x04, 0x3e, 0x7c, 0x04, 0x18, 0x40, - 0x40, 0x82, 0x00, 0x74, 0x54, 0x03, 0x07, 0xff, 0x41, 0x82, 0x00, 0x94, 0x88, 0xde, 0x00, 0x11, - 0x88, 0x9a, 0x00, 0x2c, 0x88, 0xbe, 0x00, 0x12, 0x7c, 0xc4, 0x22, 0x78, 0x88, 0x7a, 0x00, 0x2d, - 0x54, 0x87, 0x06, 0x3e, 0x88, 0x9e, 0x00, 0x13, 0x7c, 0xa5, 0x1a, 0x78, 0x88, 0x7a, 0x00, 0x2e, - 0x7c, 0xe7, 0x2b, 0x78, 0x88, 0xde, 0x00, 0x14, 0x88, 0xba, 0x00, 0x2f, 0x7c, 0x83, 0x1a, 0x78, - 0x54, 0xe7, 0x06, 0x3e, 0x88, 0x9e, 0x00, 0x15, 0x7c, 0xe7, 0x1b, 0x78, 0x88, 0x7a, 0x00, 0x30, - 0x7c, 0xc5, 0x2a, 0x78, 0x54, 0xe7, 0x06, 0x3e, 0x7c, 0xe5, 0x2b, 0x78, 0x7c, 0x83, 0x1a, 0x78, - 0x54, 0xa7, 0x06, 0x3e, 0x7c, 0xe3, 0x1b, 0x78, 0x54, 0x67, 0x06, 0x3f, 0x41, 0x82, 0x00, 0x30, - 0x48, 0x00, 0x00, 0xb8, 0x2c, 0x16, 0x00, 0x01, 0x41, 0x82, 0x00, 0x0c, 0x2c, 0x16, 0x00, 0x03, - 0x40, 0x82, 0x00, 0xa8, 0x2c, 0x15, 0x00, 0x00, 0x41, 0x82, 0x00, 0xa0, 0x38, 0x7a, 0x00, 0x1c, - 0x7c, 0x73, 0x18, 0x2e, 0x7c, 0x63, 0xa0, 0x39, 0x41, 0x82, 0x00, 0x90, 0x2c, 0x1b, 0x00, 0x01, - 0x40, 0x82, 0x00, 0x54, 0x54, 0x00, 0x07, 0xbd, 0x41, 0x82, 0x00, 0x4c, 0x82, 0x3a, 0x00, 0x34, - 0x48, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x7f, 0xc3, 0xf3, 0x78, 0x38, 0x91, 0x00, 0x04, - 0x38, 0xa0, 0x00, 0x06, 0x48, 0x00, 0x13, 0x8d, 0x2c, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x10, - 0x38, 0x11, 0x00, 0x04, 0x48, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x00, 0x82, 0x31, 0x00, 0x00, - 0x28, 0x11, 0x00, 0x00, 0x40, 0x82, 0xff, 0xd4, 0x38, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x41, 0x82, 0x00, 0x38, 0x28, 0x19, 0x00, 0x00, 0x41, 0x82, 0x00, 0x24, 0x80, 0x62, 0x00, 0xec, - 0x7e, 0x44, 0x93, 0x78, 0x48, 0x00, 0x11, 0x4d, 0x7c, 0x64, 0x1b, 0x78, 0x7f, 0x23, 0xcb, 0x78, - 0x7f, 0x05, 0xc3, 0x78, 0x7e, 0xe6, 0xbb, 0x78, 0x4b, 0xff, 0xfc, 0x49, 0x7f, 0x59, 0xd3, 0x78, - 0x7f, 0x98, 0xe3, 0x78, 0x7f, 0x77, 0xdb, 0x78, 0x80, 0x62, 0x00, 0xb8, 0x7f, 0x44, 0xd3, 0x78, - 0x48, 0x00, 0x11, 0x21, 0x7c, 0x7a, 0x1b, 0x78, 0x28, 0x1a, 0x00, 0x00, 0x40, 0x82, 0xfe, 0x94, - 0x28, 0x19, 0x00, 0x00, 0x41, 0x82, 0x00, 0x1c, 0x7f, 0x23, 0xcb, 0x78, 0x7f, 0xe4, 0xfb, 0x78, - 0x7f, 0x05, 0xc3, 0x78, 0x7e, 0xe6, 0xbb, 0x78, 0x4b, 0xff, 0xfc, 0x09, 0x48, 0x00, 0x00, 0x20, - 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xe4, 0xfb, 0x78, 0x48, 0x00, 0x10, 0xe9, 0x38, 0x82, 0x04, 0xdc, - 0x80, 0x64, 0x00, 0x00, 0x38, 0x03, 0x00, 0x01, 0x90, 0x04, 0x00, 0x00, 0x80, 0x01, 0x00, 0x88, - 0x38, 0x21, 0x00, 0x80, 0xba, 0x21, 0xff, 0xc4, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, - 0xbf, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x9f, 0x23, 0x78, 0x7c, 0x7d, 0x1b, 0x78, - 0x38, 0xc2, 0x04, 0xec, 0x38, 0x80, 0x00, 0x00, 0x7f, 0xe3, 0xfb, 0x78, 0x90, 0x01, 0x00, 0x08, - 0x94, 0x21, 0xff, 0xb0, 0x80, 0xa6, 0x00, 0x00, 0x38, 0x05, 0x00, 0x01, 0x90, 0x06, 0x00, 0x00, - 0x4b, 0xff, 0xec, 0xf1, 0x7c, 0x7e, 0x1b, 0x79, 0x41, 0x82, 0x00, 0x2c, 0x80, 0x7e, 0x00, 0x0c, - 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xe5, 0xfb, 0x78, 0x48, 0x00, 0x11, 0xc9, 0x80, 0x1e, 0x00, 0x10, - 0x7f, 0xc3, 0xf3, 0x78, 0x7c, 0x00, 0xfa, 0x14, 0x90, 0x1e, 0x00, 0x10, 0x4b, 0xff, 0xfd, 0x65, - 0x48, 0x00, 0x00, 0x14, 0x38, 0x82, 0x04, 0xe0, 0x80, 0x64, 0x00, 0x00, 0x38, 0x03, 0x00, 0x01, - 0x90, 0x04, 0x00, 0x00, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0xa1, 0xff, 0xf4, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x02, 0xa6, 0x28, 0x05, 0x00, 0x00, 0x7c, 0x9c, 0x23, 0x78, - 0x39, 0x22, 0x04, 0xf8, 0x7c, 0xdd, 0x33, 0x78, 0x7c, 0xfe, 0x3b, 0x78, 0x7d, 0x1f, 0x43, 0x78, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x69, 0x00, 0x00, 0x38, 0x03, 0x00, 0x01, - 0x90, 0x09, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, 0x80, 0x62, 0x00, 0xf4, 0x7c, 0xa4, 0x2b, 0x78, - 0x48, 0x00, 0x0f, 0xf1, 0x38, 0x60, 0x00, 0x10, 0x38, 0x80, 0x00, 0x03, 0x4b, 0xff, 0xec, 0x45, - 0x7c, 0x65, 0x1b, 0x79, 0x41, 0x82, 0x00, 0x40, 0x80, 0x65, 0x00, 0x14, 0x38, 0xc0, 0x00, 0x83, - 0x38, 0x00, 0x00, 0x05, 0x7f, 0x84, 0xe3, 0x78, 0x98, 0xc3, 0x00, 0x0d, 0x80, 0x65, 0x00, 0x10, - 0x90, 0x03, 0x00, 0x00, 0x93, 0xa3, 0x00, 0x04, 0x93, 0xc3, 0x00, 0x08, 0x93, 0xe3, 0x00, 0x0c, - 0x80, 0x65, 0x00, 0x10, 0x38, 0x03, 0x00, 0x10, 0x90, 0x05, 0x00, 0x10, 0x80, 0x62, 0x00, 0xd4, - 0x48, 0x00, 0x0f, 0xf1, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x81, 0xff, 0xf0, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0xa1, 0xff, 0xf4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0xbe, 0x2b, 0x78, 0x7c, 0x9d, 0x23, 0x78, - 0x7c, 0xdf, 0x33, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x65, 0x00, 0x14, - 0x88, 0x03, 0x00, 0x0c, 0x28, 0x00, 0x00, 0x01, 0x41, 0x82, 0x00, 0x28, 0x80, 0x62, 0x00, 0xf4, - 0x7f, 0xc4, 0xf3, 0x78, 0x48, 0x00, 0x0f, 0x4d, 0x38, 0x60, 0x00, 0x10, 0x38, 0x80, 0x00, 0x03, - 0x4b, 0xff, 0xeb, 0xa1, 0x7c, 0x7e, 0x1b, 0x79, 0x40, 0x82, 0x00, 0x24, 0x48, 0x00, 0x00, 0x58, - 0x80, 0x9e, 0x00, 0x08, 0x28, 0x04, 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x80, 0x62, 0x00, 0xf4, - 0x48, 0x00, 0x0f, 0x21, 0x38, 0x00, 0x00, 0x00, 0x90, 0x1e, 0x00, 0x08, 0x80, 0x7e, 0x00, 0x14, - 0x38, 0xc0, 0x00, 0x83, 0x38, 0x00, 0x00, 0x06, 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, - 0x98, 0xc3, 0x00, 0x0d, 0x80, 0x7e, 0x00, 0x0c, 0x90, 0x03, 0x00, 0x00, 0x93, 0xe3, 0x00, 0x04, - 0x80, 0x7e, 0x00, 0x0c, 0x38, 0x03, 0x00, 0x08, 0x90, 0x1e, 0x00, 0x10, 0x80, 0x62, 0x00, 0xd4, - 0x48, 0x00, 0x0f, 0x31, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0xa1, 0xff, 0xf4, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x01, 0xff, 0xe0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x78, 0x1b, 0x78, 0x7c, 0x99, 0x23, 0x78, - 0x3b, 0xe2, 0x02, 0x5c, 0x7c, 0xba, 0x2b, 0x78, 0x3b, 0xa0, 0x00, 0x00, 0x3b, 0x80, 0x00, 0x0e, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xa0, 0x80, 0x03, 0x00, 0x04, 0x28, 0x00, 0x00, 0x00, - 0x41, 0x82, 0x00, 0x4c, 0x80, 0x18, 0x00, 0x08, 0x38, 0x60, 0x00, 0x02, 0x54, 0x00, 0x07, 0xff, - 0x41, 0x82, 0x00, 0x08, 0x38, 0x60, 0x00, 0x07, 0xa0, 0x18, 0x00, 0x0c, 0x7c, 0x7d, 0x1b, 0x78, - 0x2c, 0x00, 0x00, 0xaa, 0x40, 0x82, 0x00, 0x0c, 0x3b, 0x80, 0x00, 0x16, 0x48, 0x00, 0x00, 0x20, - 0x2c, 0x00, 0x00, 0xfe, 0x40, 0x81, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0xff, 0x40, 0x82, 0x00, 0x0c, - 0x3b, 0x80, 0x00, 0x11, 0x48, 0x00, 0x00, 0x08, 0x3b, 0x80, 0x00, 0x0e, 0x3b, 0xdd, 0x00, 0x58, - 0x38, 0x80, 0x00, 0x01, 0x7f, 0xc3, 0xf3, 0x78, 0x4b, 0xff, 0xea, 0x99, 0x7c, 0x7b, 0x1b, 0x79, - 0x40, 0x82, 0x00, 0x24, 0x7f, 0x03, 0xc3, 0x78, 0x7f, 0x24, 0xcb, 0x78, 0x7f, 0x45, 0xd3, 0x78, - 0x38, 0xc0, 0x00, 0x00, 0x38, 0xe0, 0x00, 0x04, 0x39, 0x00, 0x00, 0x0c, 0x4b, 0xff, 0xfd, 0xe5, - 0x48, 0x00, 0x01, 0x44, 0x80, 0x7b, 0x00, 0x14, 0x38, 0x80, 0x00, 0x83, 0x38, 0xc0, 0x00, 0x03, - 0x38, 0xa0, 0x00, 0x02, 0x38, 0x00, 0x05, 0x00, 0x98, 0x83, 0x00, 0x0d, 0x38, 0x80, 0x00, 0x04, - 0x80, 0x7b, 0x00, 0x0c, 0x90, 0xc3, 0x00, 0x00, 0x90, 0xa3, 0x00, 0x20, 0x90, 0x03, 0x00, 0x34, - 0x90, 0xa3, 0x00, 0x3c, 0x80, 0x18, 0x00, 0x04, 0x90, 0x03, 0x00, 0x18, 0x80, 0x18, 0x00, 0x10, - 0x2c, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x08, 0x38, 0x80, 0x00, 0x00, 0x7c, 0x80, 0x07, 0x34, - 0x39, 0x20, 0x00, 0x00, 0x90, 0x03, 0x00, 0x10, 0x39, 0x00, 0xff, 0xff, 0x38, 0xe0, 0x00, 0x01, - 0x20, 0xdc, 0x05, 0xea, 0x7c, 0xbd, 0x00, 0xd0, 0x38, 0x9d, 0x00, 0x06, 0x38, 0x00, 0x00, 0x4c, - 0x91, 0x23, 0x00, 0x14, 0x28, 0x1d, 0x00, 0x00, 0x91, 0x23, 0x00, 0x24, 0x91, 0x03, 0x00, 0x28, - 0x91, 0x23, 0x00, 0x2c, 0x91, 0x03, 0x00, 0x30, 0x91, 0x23, 0x00, 0x48, 0x90, 0xe3, 0x00, 0x08, - 0x90, 0xc3, 0x00, 0x04, 0x90, 0xa3, 0x00, 0x1c, 0x90, 0x83, 0x00, 0x0c, 0x90, 0x03, 0x00, 0x38, - 0x80, 0xbb, 0x00, 0x0c, 0x80, 0x83, 0x00, 0x38, 0x80, 0x1f, 0x00, 0x00, 0x7c, 0x85, 0x22, 0x14, - 0x90, 0x04, 0x00, 0x00, 0xa0, 0x1f, 0x00, 0x04, 0xb0, 0x04, 0x00, 0x04, 0x41, 0x82, 0x00, 0x28, - 0xa0, 0x18, 0x00, 0x0c, 0xb0, 0x04, 0x00, 0x06, 0x80, 0x18, 0x00, 0x08, 0x54, 0x00, 0x07, 0xff, - 0x41, 0x82, 0x00, 0x14, 0x80, 0x18, 0x00, 0x2c, 0x90, 0x04, 0x00, 0x08, 0x88, 0x18, 0x00, 0x30, - 0x98, 0x04, 0x00, 0x0c, 0x38, 0x00, 0x00, 0x06, 0x3c, 0x80, 0x00, 0x01, 0x90, 0x03, 0x00, 0x40, - 0x38, 0x1d, 0x00, 0x52, 0x38, 0xe0, 0xff, 0xff, 0x38, 0xc4, 0xff, 0xff, 0x7f, 0x44, 0xd3, 0x78, - 0x90, 0x03, 0x00, 0x44, 0x80, 0xbb, 0x00, 0x0c, 0x80, 0x03, 0x00, 0x44, 0x7c, 0xe5, 0x01, 0x2e, - 0x80, 0x63, 0x00, 0x44, 0x80, 0xbb, 0x00, 0x0c, 0x38, 0x03, 0x00, 0x04, 0x7c, 0xc5, 0x03, 0x2e, - 0x80, 0x1b, 0x00, 0x10, 0x7c, 0x00, 0xf2, 0x14, 0x90, 0x1b, 0x00, 0x10, 0x80, 0x62, 0x00, 0xf4, - 0x48, 0x00, 0x0c, 0xe1, 0x80, 0x62, 0x00, 0xd4, 0x7f, 0x24, 0xcb, 0x78, 0x7f, 0x65, 0xdb, 0x78, - 0x48, 0x00, 0x0d, 0x21, 0x80, 0x01, 0x00, 0x68, 0x38, 0x21, 0x00, 0x60, 0xbb, 0x01, 0xff, 0xe0, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x41, 0xff, 0xe8, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7a, 0x1b, 0x78, 0x7c, 0x9d, 0x23, 0x78, - 0x3b, 0x82, 0x02, 0x5c, 0x7c, 0xbe, 0x2b, 0x78, 0x38, 0x60, 0x00, 0x12, 0x38, 0x80, 0x00, 0x03, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x83, 0x65, 0x00, 0x0c, 0x4b, 0xff, 0xe8, 0xe5, - 0x7c, 0x7f, 0x1b, 0x79, 0x40, 0x82, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0xa4, 0xeb, 0x78, - 0x7f, 0xc5, 0xf3, 0x78, 0x38, 0xc0, 0x00, 0x31, 0x38, 0xe0, 0x00, 0x04, 0x39, 0x00, 0x00, 0x0c, - 0x4b, 0xff, 0xfc, 0x31, 0x48, 0x00, 0x00, 0xb0, 0x80, 0xbf, 0x00, 0x14, 0x38, 0xc0, 0x00, 0x83, - 0x38, 0x80, 0x00, 0x32, 0x38, 0x60, 0x00, 0x06, 0x38, 0x00, 0x00, 0x0c, 0x98, 0xc5, 0x00, 0x0d, - 0x80, 0xbf, 0x00, 0x10, 0x90, 0x85, 0x00, 0x00, 0x90, 0x65, 0x00, 0x04, 0x90, 0x05, 0x00, 0x08, - 0x80, 0x7f, 0x00, 0x10, 0x38, 0x03, 0x00, 0x12, 0x90, 0x1f, 0x00, 0x10, 0x80, 0x1b, 0x00, 0x04, - 0x28, 0x00, 0x00, 0x02, 0x41, 0x82, 0x00, 0x0c, 0x28, 0x00, 0x00, 0x01, 0x40, 0x82, 0x00, 0x2c, - 0x80, 0x9c, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x0c, 0x80, 0x05, 0x00, 0x08, 0x7c, 0x83, 0x01, 0x2e, - 0x80, 0x65, 0x00, 0x08, 0xa0, 0xbc, 0x00, 0x04, 0x80, 0x9f, 0x00, 0x0c, 0x38, 0x03, 0x00, 0x04, - 0x7c, 0xa4, 0x03, 0x2e, 0x48, 0x00, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0xa4, 0xeb, 0x78, - 0x7f, 0xc5, 0xf3, 0x78, 0x38, 0xc0, 0x00, 0x31, 0x38, 0xe0, 0x00, 0x09, 0x39, 0x00, 0x00, 0x00, - 0x4b, 0xff, 0xfb, 0xa1, 0x48, 0x00, 0x00, 0x20, 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xc4, 0xf3, 0x78, - 0x48, 0x00, 0x0b, 0xc1, 0x80, 0x62, 0x00, 0xd4, 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xe5, 0xfb, 0x78, - 0x48, 0x00, 0x0c, 0x01, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x41, 0xff, 0xe8, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x41, 0xff, 0xe8, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7a, 0x1b, 0x78, 0x7c, 0xbc, 0x2b, 0x78, - 0x3b, 0xe2, 0x02, 0x5c, 0x7c, 0x9b, 0x23, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, - 0x80, 0x03, 0x00, 0x04, 0x80, 0xc5, 0x00, 0x0c, 0x28, 0x00, 0x00, 0x00, 0x83, 0xc6, 0x00, 0x04, - 0x41, 0x82, 0x00, 0x18, 0x38, 0xc0, 0x00, 0x01, 0x38, 0xe0, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, - 0x4b, 0xff, 0xfb, 0x21, 0x48, 0x00, 0x01, 0x8c, 0xa0, 0x06, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0x02, - 0x40, 0x82, 0x00, 0x10, 0x80, 0x06, 0x00, 0x08, 0x28, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x24, - 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x01, - 0x38, 0xe0, 0x00, 0x07, 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xfa, 0xe9, 0x48, 0x00, 0x01, 0x54, - 0x28, 0x1e, 0x00, 0xfe, 0x41, 0x81, 0x00, 0x20, 0x57, 0xc0, 0x07, 0xff, 0x41, 0x82, 0x00, 0x18, - 0x38, 0xc0, 0x00, 0x01, 0x38, 0xe0, 0x00, 0x01, 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xfa, 0xc5, - 0x48, 0x00, 0x01, 0x30, 0x57, 0xc3, 0x04, 0x3e, 0x7c, 0x64, 0x1b, 0x78, 0x4b, 0xff, 0xf1, 0xa5, - 0x54, 0x60, 0x04, 0x3e, 0x2c, 0x00, 0x00, 0x05, 0x40, 0x82, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, - 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x01, 0x38, 0xe0, 0x00, 0x01, - 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xfa, 0x8d, 0x48, 0x00, 0x00, 0xf8, 0x38, 0x60, 0x00, 0x20, - 0x38, 0x80, 0x00, 0x03, 0x4b, 0xff, 0xe7, 0x0d, 0x7c, 0x7d, 0x1b, 0x79, 0x40, 0x82, 0x00, 0x24, - 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x01, - 0x38, 0xe0, 0x00, 0x04, 0x39, 0x00, 0x00, 0x0c, 0x4b, 0xff, 0xfa, 0x59, 0x48, 0x00, 0x00, 0xc4, - 0x80, 0x7d, 0x00, 0x14, 0x38, 0x80, 0x00, 0x83, 0x38, 0x00, 0x00, 0x04, 0x38, 0xe0, 0x00, 0x04, - 0x38, 0xc0, 0x00, 0x08, 0x7c, 0x09, 0x03, 0xa6, 0x98, 0x83, 0x00, 0x0d, 0x38, 0xa0, 0x00, 0x00, - 0x38, 0x80, 0x00, 0x18, 0x7c, 0xa3, 0x2b, 0x78, 0x81, 0x1d, 0x00, 0x0c, 0x90, 0xe8, 0x00, 0x00, - 0x93, 0xc8, 0x00, 0x04, 0x90, 0xc8, 0x00, 0x08, 0x90, 0x88, 0x00, 0x0c, 0x90, 0xa8, 0x00, 0x10, - 0x90, 0xa8, 0x00, 0x14, 0x80, 0x9d, 0x00, 0x0c, 0x80, 0x1f, 0x00, 0x00, 0x90, 0x04, 0x00, 0x18, - 0xa0, 0x1f, 0x00, 0x04, 0xb0, 0x04, 0x00, 0x1c, 0xb3, 0xc4, 0x00, 0x1e, 0x80, 0x9d, 0x00, 0x0c, - 0x38, 0x04, 0x00, 0x20, 0x90, 0x1d, 0x00, 0x10, 0x38, 0x03, 0x00, 0x1c, 0x38, 0x63, 0x00, 0x04, - 0x7c, 0xba, 0x01, 0x2e, 0x42, 0x00, 0xff, 0xf4, 0x28, 0x1e, 0x00, 0xfe, 0x41, 0x81, 0x00, 0x10, - 0x80, 0x1a, 0x00, 0x28, 0x64, 0x00, 0x80, 0x00, 0x90, 0x1a, 0x00, 0x28, 0x38, 0x00, 0x00, 0x03, - 0x7f, 0x84, 0xe3, 0x78, 0x90, 0x1a, 0x00, 0x04, 0xb3, 0xda, 0x00, 0x0c, 0x80, 0x1a, 0x00, 0x08, - 0x54, 0x00, 0x00, 0x3c, 0x90, 0x1a, 0x00, 0x08, 0x80, 0x62, 0x00, 0xf4, 0x48, 0x00, 0x09, 0xd5, - 0x80, 0x62, 0x00, 0xd4, 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 0x48, 0x00, 0x0a, 0x15, - 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x41, 0xff, 0xe8, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7c, 0x1b, 0x78, 0x7c, 0x9d, 0x23, 0x78, - 0x7c, 0xbe, 0x2b, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x03, 0x00, 0x04, - 0x28, 0x00, 0x00, 0x03, 0x41, 0x82, 0x00, 0x18, 0x38, 0xc0, 0x00, 0x02, 0x38, 0xe0, 0x00, 0x03, - 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xf9, 0x3d, 0x48, 0x00, 0x00, 0x58, 0x38, 0x00, 0x00, 0x00, - 0x38, 0xa0, 0x00, 0x00, 0x90, 0x1c, 0x00, 0x04, 0xb0, 0x1c, 0x00, 0x0c, 0x80, 0x62, 0x00, 0xd0, - 0x48, 0x00, 0x09, 0xa1, 0x3b, 0xfd, 0xff, 0xc0, 0x80, 0x62, 0x00, 0xd0, 0x38, 0xa0, 0x00, 0x00, - 0x7f, 0xe4, 0xfb, 0x78, 0x48, 0x00, 0x09, 0x8d, 0x80, 0x62, 0x00, 0xdc, 0x7f, 0xe4, 0xfb, 0x78, - 0x38, 0xa0, 0x00, 0x86, 0x38, 0xc0, 0x00, 0x03, 0x48, 0x00, 0x09, 0xc9, 0x7f, 0x83, 0xe3, 0x78, - 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, 0x38, 0xc0, 0x00, 0x02, 0x4b, 0xff, 0xf9, 0x95, - 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x21, 0xff, 0xe4, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0xbd, 0x2b, 0x78, 0x7c, 0x7b, 0x1b, 0x78, - 0x7c, 0x9c, 0x23, 0x78, 0x38, 0xe0, 0x00, 0x00, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xa0, - 0x81, 0x05, 0x00, 0x0c, 0x80, 0x03, 0x00, 0x04, 0x80, 0xc8, 0x00, 0x04, 0x28, 0x00, 0x00, 0x03, - 0x83, 0xc8, 0x00, 0x08, 0x7f, 0xe8, 0x32, 0x14, 0xa0, 0xdf, 0x00, 0x00, 0x41, 0x82, 0x00, 0x18, - 0x38, 0xc0, 0x00, 0x1b, 0x38, 0xe0, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xf8, 0x75, - 0x48, 0x00, 0x01, 0xbc, 0x80, 0x08, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0x02, 0x41, 0x82, 0x00, 0x7c, - 0x40, 0x80, 0x00, 0xc0, 0x2c, 0x00, 0x00, 0x01, 0x40, 0x80, 0x00, 0x08, 0x48, 0x00, 0x00, 0xb4, - 0xa0, 0x1b, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0xfe, 0x41, 0x81, 0x00, 0x58, 0x54, 0xc0, 0x07, 0xff, - 0x41, 0x82, 0x00, 0x30, 0x28, 0x1e, 0x00, 0x02, 0x40, 0x82, 0x00, 0x28, 0x54, 0xc4, 0xe7, 0x3a, - 0x38, 0x60, 0x00, 0x01, 0x7c, 0xbb, 0x22, 0x14, 0x54, 0xc0, 0xfe, 0xfe, 0x80, 0x85, 0x00, 0x1c, - 0x7c, 0x60, 0x00, 0x30, 0x7c, 0x80, 0x03, 0x78, 0x90, 0x05, 0x00, 0x1c, 0x48, 0x00, 0x00, 0x78, - 0x54, 0xc0, 0x04, 0x3f, 0x40, 0x82, 0x00, 0x14, 0x80, 0x1b, 0x00, 0x08, 0x60, 0x00, 0x00, 0x04, - 0x90, 0x1b, 0x00, 0x08, 0x48, 0x00, 0x00, 0x60, 0x38, 0xe0, 0x00, 0x01, 0x48, 0x00, 0x00, 0x58, - 0x38, 0xe0, 0x00, 0x07, 0x48, 0x00, 0x00, 0x50, 0xa0, 0x1b, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0xaa, - 0x40, 0x82, 0x00, 0x38, 0x80, 0x1b, 0x00, 0x08, 0x54, 0x00, 0x07, 0xff, 0x41, 0x82, 0x00, 0x0c, - 0x38, 0xe0, 0x00, 0x13, 0x48, 0x00, 0x00, 0x30, 0x80, 0x1f, 0x00, 0x00, 0x90, 0x1b, 0x00, 0x2c, - 0x88, 0x1f, 0x00, 0x04, 0x98, 0x1b, 0x00, 0x30, 0x80, 0x1b, 0x00, 0x08, 0x60, 0x00, 0x00, 0x01, - 0x90, 0x1b, 0x00, 0x08, 0x48, 0x00, 0x00, 0x10, 0x38, 0xe0, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, - 0x38, 0xe0, 0x00, 0x07, 0x2c, 0x07, 0x00, 0x00, 0x41, 0x82, 0x00, 0x20, 0x7f, 0x63, 0xdb, 0x78, - 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x1b, 0x39, 0x00, 0x00, 0x00, - 0x4b, 0xff, 0xf7, 0x81, 0x48, 0x00, 0x00, 0xc8, 0x3b, 0x5e, 0x00, 0x0c, 0x38, 0x80, 0x00, 0x03, - 0x7f, 0x43, 0xd3, 0x78, 0x4b, 0xff, 0xe3, 0xfd, 0x7c, 0x79, 0x1b, 0x79, 0x40, 0x82, 0x00, 0x24, - 0x7f, 0x63, 0xdb, 0x78, 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0xa5, 0xeb, 0x78, 0x38, 0xc0, 0x00, 0x1b, - 0x38, 0xe0, 0x00, 0x04, 0x39, 0x00, 0x00, 0x0c, 0x4b, 0xff, 0xf7, 0x49, 0x48, 0x00, 0x00, 0x90, - 0x80, 0x79, 0x00, 0x14, 0x38, 0x00, 0x00, 0x83, 0x7f, 0x45, 0xd3, 0x78, 0x38, 0x80, 0x00, 0x00, - 0x98, 0x03, 0x00, 0x0d, 0x83, 0x59, 0x00, 0x10, 0x7f, 0x43, 0xd3, 0x78, 0x48, 0x00, 0x08, 0xe5, - 0x38, 0x60, 0x00, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x90, 0x7a, 0x00, 0x00, 0x7c, 0x60, 0x01, 0x10, - 0x38, 0x00, 0x00, 0x0c, 0x7c, 0x00, 0x18, 0x38, 0x2c, 0x1e, 0x00, 0x00, 0x93, 0xda, 0x00, 0x08, - 0x90, 0x1a, 0x00, 0x04, 0x80, 0x79, 0x00, 0x10, 0x38, 0x03, 0x00, 0x0c, 0x90, 0x19, 0x00, 0x10, - 0x41, 0x82, 0x00, 0x14, 0x80, 0x79, 0x00, 0x10, 0x7f, 0xe4, 0xfb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, - 0x48, 0x00, 0x08, 0x61, 0x80, 0x19, 0x00, 0x10, 0x7f, 0xa4, 0xeb, 0x78, 0x7c, 0x00, 0xf2, 0x14, - 0x90, 0x19, 0x00, 0x10, 0x80, 0x62, 0x00, 0xf4, 0x48, 0x00, 0x06, 0xf9, 0x80, 0x62, 0x00, 0xd4, - 0x7f, 0x84, 0xe3, 0x78, 0x7f, 0x25, 0xcb, 0x78, 0x48, 0x00, 0x07, 0x39, 0x80, 0x01, 0x00, 0x68, - 0x38, 0x21, 0x00, 0x60, 0xbb, 0x21, 0xff, 0xe4, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, - 0xbf, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7c, 0x1b, 0x78, 0x7c, 0xbe, 0x2b, 0x78, - 0x7c, 0x9d, 0x23, 0x78, 0x3b, 0xe0, 0x00, 0x00, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, - 0x80, 0xe5, 0x00, 0x0c, 0x80, 0x03, 0x00, 0x04, 0x80, 0xc7, 0x00, 0x04, 0x28, 0x00, 0x00, 0x03, - 0x81, 0x07, 0x00, 0x08, 0x7c, 0xc7, 0x32, 0x14, 0x41, 0x82, 0x00, 0x18, 0x38, 0xc0, 0x00, 0x15, - 0x38, 0xe0, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xf6, 0x59, 0x48, 0x00, 0x00, 0xf4, - 0x2c, 0x08, 0x00, 0x01, 0x40, 0x82, 0x00, 0x58, 0x88, 0x86, 0x00, 0x00, 0x54, 0x80, 0x07, 0xff, - 0x41, 0x82, 0x00, 0x44, 0x28, 0x04, 0x00, 0xff, 0x41, 0x82, 0x00, 0x3c, 0xa0, 0x1c, 0x00, 0x0c, - 0x2c, 0x00, 0x00, 0xfe, 0x41, 0x81, 0x00, 0x28, 0x54, 0x83, 0xe7, 0x3a, 0x54, 0x80, 0xfe, 0xfe, - 0x7c, 0x9c, 0x1a, 0x14, 0x38, 0x60, 0x00, 0x01, 0x7c, 0x60, 0x00, 0x30, 0x80, 0x64, 0x00, 0x1c, - 0x7c, 0x60, 0x00, 0x78, 0x90, 0x04, 0x00, 0x1c, 0x48, 0x00, 0x00, 0x60, 0x3b, 0xe0, 0x00, 0x07, - 0x48, 0x00, 0x00, 0x58, 0x3b, 0xe0, 0x00, 0x01, 0x48, 0x00, 0x00, 0x50, 0x2c, 0x08, 0x00, 0x05, - 0x40, 0x82, 0x00, 0x48, 0xa0, 0x1c, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0xaa, 0x40, 0x82, 0x00, 0x38, - 0x80, 0x1c, 0x00, 0x08, 0x54, 0x00, 0x07, 0xff, 0x41, 0x82, 0x00, 0x24, 0x7c, 0xc4, 0x33, 0x78, - 0x7d, 0x05, 0x43, 0x78, 0x38, 0x7c, 0x00, 0x2c, 0x48, 0x00, 0x07, 0xf9, 0x2c, 0x03, 0x00, 0x00, - 0x41, 0x82, 0x00, 0x18, 0x3b, 0xe0, 0x00, 0x01, 0x48, 0x00, 0x00, 0x10, 0x3b, 0xe0, 0x00, 0x01, - 0x48, 0x00, 0x00, 0x08, 0x3b, 0xe0, 0x00, 0x07, 0x2c, 0x1f, 0x00, 0x00, 0x41, 0x82, 0x00, 0x24, - 0x7f, 0x83, 0xe3, 0x78, 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, 0x7f, 0xe7, 0xfb, 0x78, - 0x38, 0xc0, 0x00, 0x15, 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xf5, 0x89, 0x48, 0x00, 0x00, 0x24, - 0x80, 0x1c, 0x00, 0x08, 0x7f, 0x83, 0xe3, 0x78, 0x7f, 0xa4, 0xeb, 0x78, 0x7f, 0xc5, 0xf3, 0x78, - 0x38, 0xc0, 0x00, 0x15, 0x54, 0x00, 0x00, 0x3c, 0x90, 0x1c, 0x00, 0x08, 0x4b, 0xff, 0xf6, 0x15, - 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x41, 0xff, 0xe8, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7a, 0x1b, 0x78, 0x7c, 0xbc, 0x2b, 0x78, - 0x7c, 0x9b, 0x23, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x65, 0x00, 0x0c, - 0x80, 0x03, 0x00, 0x08, 0x7f, 0xa3, 0x02, 0x14, 0x7f, 0xa3, 0xeb, 0x78, 0x4b, 0xff, 0xec, 0x65, - 0x2c, 0x03, 0x00, 0x01, 0x41, 0x82, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0x64, 0xdb, 0x78, - 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x1d, 0x38, 0xe0, 0x00, 0x01, 0x39, 0x00, 0x00, 0x00, - 0x4b, 0xff, 0xf4, 0xf1, 0x48, 0x00, 0x00, 0xd4, 0x83, 0xfa, 0x00, 0x34, 0x48, 0x00, 0x00, 0x2c, - 0x7f, 0xa3, 0xeb, 0x78, 0x38, 0x9f, 0x00, 0x04, 0x38, 0xa0, 0x00, 0x06, 0x48, 0x00, 0x07, 0x05, - 0x2c, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x10, 0x38, 0x1f, 0x00, 0x04, 0x48, 0x00, 0x00, 0x18, - 0x60, 0x00, 0x00, 0x00, 0x83, 0xff, 0x00, 0x00, 0x28, 0x1f, 0x00, 0x00, 0x40, 0x82, 0xff, 0xd4, - 0x38, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, - 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x1d, 0x38, 0xe0, 0x00, 0x01, - 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xf4, 0x8d, 0x48, 0x00, 0x00, 0x70, 0x7f, 0xa3, 0xeb, 0x78, - 0x4b, 0xff, 0xe0, 0x21, 0x38, 0x60, 0x00, 0x06, 0x48, 0x00, 0x04, 0x49, 0x80, 0x1d, 0x00, 0x00, - 0x7c, 0x7e, 0x1b, 0x78, 0x38, 0x60, 0x00, 0x0c, 0x90, 0x1e, 0x00, 0x00, 0xa0, 0x1d, 0x00, 0x04, - 0xb0, 0x1e, 0x00, 0x04, 0x48, 0x00, 0x04, 0x2d, 0x7c, 0x7f, 0x1b, 0x78, 0x7f, 0xc4, 0xf3, 0x78, - 0x38, 0x7f, 0x00, 0x04, 0x38, 0xa0, 0x00, 0x06, 0x48, 0x00, 0x05, 0xc9, 0x80, 0x1a, 0x00, 0x34, - 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x1d, - 0x90, 0x1f, 0x00, 0x00, 0x93, 0xfa, 0x00, 0x34, 0x80, 0x1a, 0x00, 0x08, 0x60, 0x00, 0x00, 0x02, - 0x90, 0x1a, 0x00, 0x08, 0x4b, 0xff, 0xf4, 0xcd, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, - 0xbb, 0x41, 0xff, 0xe8, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x41, 0xff, 0xe8, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x7a, 0x1b, 0x78, 0x7c, 0xbc, 0x2b, 0x78, - 0x7c, 0x9b, 0x23, 0x78, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x65, 0x00, 0x0c, - 0x80, 0x03, 0x00, 0x08, 0x7f, 0xa3, 0x02, 0x14, 0x7f, 0xa3, 0xeb, 0x78, 0x4b, 0xff, 0xeb, 0x25, - 0x2c, 0x03, 0x00, 0x01, 0x41, 0x82, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0x64, 0xdb, 0x78, - 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x1e, 0x38, 0xe0, 0x00, 0x01, 0x39, 0x00, 0x00, 0x00, - 0x4b, 0xff, 0xf3, 0xb1, 0x48, 0x00, 0x01, 0x10, 0x83, 0xfa, 0x00, 0x34, 0x48, 0x00, 0x00, 0x2c, - 0x7f, 0xa3, 0xeb, 0x78, 0x38, 0x9f, 0x00, 0x04, 0x38, 0xa0, 0x00, 0x06, 0x48, 0x00, 0x05, 0xc5, - 0x2c, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0x10, 0x3b, 0xff, 0x00, 0x04, 0x48, 0x00, 0x00, 0x18, - 0x60, 0x00, 0x00, 0x00, 0x83, 0xff, 0x00, 0x00, 0x28, 0x1f, 0x00, 0x00, 0x40, 0x82, 0xff, 0xd4, - 0x3b, 0xe0, 0x00, 0x00, 0x28, 0x1f, 0x00, 0x00, 0x40, 0x82, 0x00, 0x24, 0x7f, 0x43, 0xd3, 0x78, - 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x1e, 0x38, 0xe0, 0x00, 0x01, - 0x39, 0x00, 0x00, 0x00, 0x4b, 0xff, 0xf3, 0x4d, 0x48, 0x00, 0x00, 0xac, 0x83, 0xda, 0x00, 0x34, - 0x48, 0x00, 0x00, 0x20, 0x7f, 0xe3, 0xfb, 0x78, 0x38, 0x9e, 0x00, 0x04, 0x38, 0xa0, 0x00, 0x06, - 0x48, 0x00, 0x05, 0x61, 0x2c, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x83, 0xde, 0x00, 0x00, - 0x28, 0x1e, 0x00, 0x00, 0x40, 0x82, 0xff, 0xe0, 0x48, 0x00, 0x00, 0x40, 0x38, 0x9a, 0x00, 0x34, - 0x48, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x7c, 0x00, 0xf0, 0x40, - 0x40, 0x82, 0x00, 0x1c, 0x80, 0x1e, 0x00, 0x00, 0x7f, 0xc3, 0xf3, 0x78, 0x90, 0x04, 0x00, 0x00, - 0x48, 0x00, 0x02, 0xf1, 0x48, 0x00, 0x00, 0x14, 0x60, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x03, 0x78, - 0x28, 0x04, 0x00, 0x00, 0x40, 0x82, 0xff, 0xd4, 0x7f, 0xe3, 0xfb, 0x78, 0x48, 0x00, 0x02, 0xd5, - 0x7f, 0xa3, 0xeb, 0x78, 0x4b, 0xff, 0xde, 0xbd, 0x80, 0x1a, 0x00, 0x34, 0x28, 0x00, 0x00, 0x00, - 0x40, 0x82, 0x00, 0x10, 0x80, 0x1a, 0x00, 0x08, 0x54, 0x00, 0x07, 0xfa, 0x90, 0x1a, 0x00, 0x08, - 0x7f, 0x43, 0xd3, 0x78, 0x7f, 0x64, 0xdb, 0x78, 0x7f, 0x85, 0xe3, 0x78, 0x38, 0xc0, 0x00, 0x1e, - 0x4b, 0xff, 0xf3, 0x51, 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x41, 0xff, 0xe8, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbf, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0xbf, 0x2b, 0x78, 0x7c, 0x9e, 0x23, 0x78, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xb0, 0x80, 0x03, 0x00, 0x04, 0x83, 0xa5, 0x00, 0x0c, - 0x28, 0x00, 0x00, 0x03, 0x41, 0x82, 0x00, 0xb4, 0x80, 0x7d, 0x00, 0x04, 0x38, 0x80, 0x00, 0x03, - 0x38, 0x63, 0x00, 0x14, 0x4b, 0xff, 0xde, 0xdd, 0x7c, 0x7c, 0x1b, 0x79, 0x40, 0x82, 0x00, 0x14, - 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xe4, 0xfb, 0x78, 0x48, 0x00, 0x02, 0x69, 0x48, 0x00, 0x00, 0xa4, - 0x80, 0xdc, 0x00, 0x14, 0x38, 0x00, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x09, 0x38, 0x80, 0x00, 0x03, - 0x38, 0x60, 0x00, 0x00, 0x98, 0x06, 0x00, 0x0d, 0x38, 0x00, 0x00, 0x14, 0x80, 0xdc, 0x00, 0x10, - 0x90, 0xa6, 0x00, 0x00, 0x90, 0x86, 0x00, 0x10, 0x90, 0x66, 0x00, 0x0c, 0x80, 0x7d, 0x00, 0x04, - 0x90, 0x66, 0x00, 0x04, 0x90, 0x06, 0x00, 0x08, 0x80, 0x7c, 0x00, 0x10, 0x38, 0x03, 0x00, 0x14, - 0x90, 0x1c, 0x00, 0x10, 0x80, 0x1d, 0x00, 0x08, 0x80, 0x7c, 0x00, 0x10, 0x80, 0xbd, 0x00, 0x04, - 0x7c, 0x9d, 0x02, 0x14, 0x48, 0x00, 0x03, 0x5d, 0x80, 0x7c, 0x00, 0x10, 0x7f, 0xc4, 0xf3, 0x78, - 0x7f, 0x85, 0xe3, 0x78, 0x80, 0x1d, 0x00, 0x04, 0x7c, 0x03, 0x02, 0x14, 0x90, 0x1c, 0x00, 0x10, - 0x80, 0x62, 0x00, 0xd4, 0x48, 0x00, 0x02, 0x3d, 0x80, 0x62, 0x00, 0xf4, 0x7f, 0xe4, 0xfb, 0x78, - 0x48, 0x00, 0x01, 0xe1, 0x48, 0x00, 0x00, 0x1c, 0x7f, 0xe4, 0xfb, 0x78, 0x38, 0xa0, 0x00, 0x00, - 0x4b, 0xff, 0xea, 0x51, 0x28, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x08, 0x4b, 0xff, 0xec, 0x55, - 0x80, 0x01, 0x00, 0x58, 0x38, 0x21, 0x00, 0x50, 0xbb, 0x81, 0xff, 0xf0, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x93, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x02, 0xa6, 0x38, 0xa0, 0x00, 0x00, 0x7c, 0x9f, 0x23, 0x78, - 0x38, 0xc2, 0x05, 0x04, 0x90, 0x01, 0x00, 0x08, 0x38, 0x00, 0x00, 0x20, 0x38, 0x86, 0xff, 0xf8, - 0x7c, 0x09, 0x03, 0xa6, 0x94, 0x21, 0xfe, 0xb0, 0x90, 0xa1, 0x00, 0x44, 0x90, 0xa1, 0x00, 0x40, - 0x38, 0xa1, 0x00, 0x40, 0x60, 0x00, 0x00, 0x00, 0x84, 0x04, 0x00, 0x08, 0x94, 0x05, 0x00, 0x08, - 0x80, 0x04, 0x00, 0x04, 0x90, 0x05, 0x00, 0x04, 0x42, 0x00, 0xff, 0xf0, 0x38, 0x00, 0x00, 0x00, - 0x3c, 0x80, 0x70, 0x77, 0x90, 0x01, 0x00, 0x3c, 0x38, 0xc1, 0x00, 0x44, 0x38, 0xe1, 0x00, 0x40, - 0x98, 0x01, 0x00, 0x38, 0x38, 0x84, 0x70, 0x63, 0x39, 0x01, 0x00, 0x48, 0x38, 0xa0, 0x00, 0x01, - 0x48, 0x00, 0x04, 0x05, 0x80, 0x41, 0x00, 0x14, 0x7c, 0x60, 0x07, 0x35, 0x41, 0x82, 0x00, 0x0c, - 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x30, 0x80, 0x61, 0x00, 0x44, 0x7f, 0xe4, 0xfb, 0x78, - 0x38, 0xa1, 0x00, 0x3c, 0x38, 0xc1, 0x00, 0x38, 0x48, 0x00, 0x03, 0xf5, 0x80, 0x41, 0x00, 0x14, - 0x7c, 0x60, 0x07, 0x35, 0x41, 0x82, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, - 0x80, 0x61, 0x00, 0x3c, 0x80, 0x01, 0x01, 0x58, 0x38, 0x21, 0x01, 0x50, 0x83, 0xe1, 0xff, 0xfc, - 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x93, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x02, 0xa6, 0x7c, 0x9f, 0x23, 0x78, 0x7c, 0x64, 0x1b, 0x78, - 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xfe, 0x80, 0x88, 0x03, 0x00, 0x00, 0x38, 0x61, 0x00, 0x38, - 0x7c, 0x05, 0x07, 0x74, 0x38, 0xa5, 0x00, 0x01, 0x48, 0x00, 0x01, 0xf9, 0x88, 0x1f, 0x00, 0x00, - 0x7f, 0xe4, 0xfb, 0x78, 0x38, 0x61, 0x00, 0x78, 0x7c, 0x05, 0x07, 0x74, 0x38, 0xa5, 0x00, 0x01, - 0x48, 0x00, 0x01, 0xe1, 0x38, 0x61, 0x00, 0x38, 0x38, 0x81, 0x00, 0x78, 0x4b, 0xff, 0xfe, 0xe5, - 0x80, 0x01, 0x01, 0x88, 0x38, 0x21, 0x01, 0x80, 0x83, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x48, 0x00, 0x03, 0x11, - 0x80, 0x41, 0x00, 0x14, 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, 0x48, 0x00, 0x02, 0x99, - 0x80, 0x41, 0x00, 0x14, 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, - 0x90, 0x41, 0x00, 0x0c, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x03, 0x00, 0x00, 0x80, 0x43, 0x00, 0x04, - 0x7c, 0x09, 0x03, 0xa6, 0x7c, 0x83, 0x23, 0x78, 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x48, - 0x80, 0x41, 0x00, 0x4c, 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, - 0x80, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, - 0x90, 0x41, 0x00, 0x0c, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x03, 0x00, 0x00, 0x80, 0x43, 0x00, 0x04, - 0x7c, 0x09, 0x03, 0xa6, 0x7c, 0x83, 0x23, 0x78, 0x7c, 0xa4, 0x2b, 0x78, 0x4e, 0x80, 0x04, 0x21, - 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, 0x7c, 0x08, 0x03, 0xa6, 0x38, 0x21, 0x00, 0x40, - 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x03, 0xa6, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, - 0x90, 0x41, 0x00, 0x0c, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x03, 0x00, 0x00, 0x80, 0x43, 0x00, 0x04, - 0x7c, 0x09, 0x03, 0xa6, 0x7c, 0x83, 0x23, 0x78, 0x7c, 0xa4, 0x2b, 0x78, 0x7c, 0xc5, 0x33, 0x78, - 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, 0x7c, 0x08, 0x03, 0xa6, - 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x03, 0xa6, - 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x02, 0xa6, 0x90, 0x01, 0x00, 0x08, - 0x90, 0x41, 0x00, 0x0c, 0x94, 0x21, 0xff, 0xc0, 0x80, 0x03, 0x00, 0x00, 0x80, 0x43, 0x00, 0x04, - 0x7c, 0x09, 0x03, 0xa6, 0x7c, 0x83, 0x23, 0x78, 0x7c, 0xa4, 0x2b, 0x78, 0x7c, 0xc5, 0x33, 0x78, - 0x7c, 0xe6, 0x3b, 0x78, 0x7d, 0x07, 0x43, 0x78, 0x7d, 0x28, 0x4b, 0x78, 0x7d, 0x49, 0x53, 0x78, - 0x4e, 0x80, 0x04, 0x21, 0x80, 0x01, 0x00, 0x48, 0x80, 0x41, 0x00, 0x4c, 0x7c, 0x08, 0x03, 0xa6, - 0x38, 0x21, 0x00, 0x40, 0x4e, 0x80, 0x00, 0x20, 0x80, 0x01, 0x00, 0x08, 0x7c, 0x08, 0x03, 0xa6, - 0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0xff, 0xfc, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, - 0x7c, 0x7f, 0x1b, 0x78, 0x7c, 0x83, 0x23, 0x78, 0x7f, 0xe4, 0xfb, 0x78, 0x48, 0x00, 0x01, 0x21, - 0x80, 0x41, 0x00, 0x14, 0x7f, 0xe3, 0xfb, 0x78, 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, - 0x83, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x08, 0x02, 0xa6, 0x93, 0xe1, 0xff, 0xfc, 0x90, 0x01, 0x00, 0x08, 0x94, 0x21, 0xff, 0xc0, - 0x7c, 0x7f, 0x1b, 0x78, 0x2c, 0x04, 0x00, 0x00, 0x40, 0x82, 0x00, 0x14, 0x7c, 0xa4, 0x2b, 0x78, - 0x48, 0x00, 0x00, 0xf5, 0x80, 0x41, 0x00, 0x14, 0x48, 0x00, 0x00, 0x24, 0x38, 0xa5, 0x00, 0x01, - 0x7c, 0x80, 0x07, 0x74, 0x48, 0x00, 0x00, 0x0c, 0x98, 0x03, 0x00, 0x00, 0x38, 0x63, 0x00, 0x01, - 0x38, 0xa5, 0xff, 0xff, 0x28, 0x05, 0x00, 0x00, 0x40, 0x82, 0xff, 0xf0, 0x7f, 0xe3, 0xfb, 0x78, - 0x80, 0x01, 0x00, 0x48, 0x38, 0x21, 0x00, 0x40, 0x83, 0xe1, 0xff, 0xfc, 0x7c, 0x08, 0x03, 0xa6, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0xc5, 0x00, 0x01, 0x48, 0x00, 0x00, 0x2c, 0x88, 0xa4, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00, - 0x7c, 0x05, 0x00, 0x50, 0x2c, 0x00, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, 0x7c, 0x03, 0x03, 0x78, - 0x4e, 0x80, 0x00, 0x20, 0x60, 0x00, 0x00, 0x00, 0x38, 0x63, 0x00, 0x01, 0x38, 0x84, 0x00, 0x01, - 0x38, 0xc6, 0xff, 0xff, 0x28, 0x06, 0x00, 0x00, 0x40, 0x82, 0xff, 0xd0, 0x38, 0x60, 0x00, 0x00, - 0x4e, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x81, 0x00, 0x1c, 0x90, 0xa1, 0x00, 0x20, 0x90, 0xc1, 0x00, 0x24, 0x90, 0xe1, 0x00, 0x28, - 0x91, 0x01, 0x00, 0x2c, 0x91, 0x21, 0x00, 0x30, 0x91, 0x41, 0x00, 0x34, 0x38, 0x60, 0x00, 0x00, - 0x4e, 0x80, 0x00, 0x20, 0x81, 0x82, 0x00, 0x14, 0x90, 0x41, 0x00, 0x14, 0x80, 0x0c, 0x00, 0x00, - 0x80, 0x4c, 0x00, 0x04, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x81, 0x82, 0x00, 0x08, - 0x90, 0x41, 0x00, 0x14, 0x80, 0x0c, 0x00, 0x00, 0x80, 0x4c, 0x00, 0x04, 0x7c, 0x09, 0x03, 0xa6, - 0x4e, 0x80, 0x04, 0x20, 0x81, 0x82, 0x00, 0x00, 0x90, 0x41, 0x00, 0x14, 0x80, 0x0c, 0x00, 0x00, - 0x80, 0x4c, 0x00, 0x04, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x81, 0x82, 0x00, 0x04, - 0x90, 0x41, 0x00, 0x14, 0x80, 0x0c, 0x00, 0x00, 0x80, 0x4c, 0x00, 0x04, 0x7c, 0x09, 0x03, 0xa6, - 0x4e, 0x80, 0x04, 0x20, 0x81, 0x82, 0x00, 0x0c, 0x90, 0x41, 0x00, 0x14, 0x80, 0x0c, 0x00, 0x00, - 0x80, 0x4c, 0x00, 0x04, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, 0x81, 0x82, 0x00, 0x10, - 0x90, 0x41, 0x00, 0x14, 0x80, 0x0c, 0x00, 0x00, 0x80, 0x4c, 0x00, 0x04, 0x7c, 0x09, 0x03, 0xa6, - 0x4e, 0x80, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0x22, 0x04, 0xf8, 0x82, 0x02, 0x27, 0x04, 0xe0, 0x04, 0xec, 0x04, 0xdc, 0x04, 0xe8, 0x04, - 0xd8, 0x04, 0xe4, 0x04, 0xfc, 0x04, 0xf0, 0x04, 0xf4, 0x01, 0x44, 0x05, 0x00, 0x02, 0x44, 0x04, - 0x10, 0x03, 0xdf, 0x03, 0xad, 0x03, 0x7c, 0x03, 0x3d, 0x02, 0x5c, 0x03, 0x30, 0x03, 0x21, 0x03, - 0x13, 0x03, 0x01, 0x02, 0xef, 0x02, 0xde, 0x02, 0xd4, 0x02, 0xcc, 0x02, 0xc4, 0x02, 0xb8, 0x02, - 0xab, 0x02, 0xa2, 0x02, 0x9c, 0x02, 0x96, 0x02, 0x8e, 0x02, 0x87, 0x02, 0x7e, 0x02, 0x77, 0x02, - 0x6f, 0x02, 0x62, 0x05, 0x04, 0x00, 0x4d, 0x21, 0x10, 0x0e, 0x22, 0x09, 0x30, 0x86, 0x02, 0x05, - 0x07, 0x60, 0x06, 0x60, 0x05, 0xa0, 0x05, 0x70, 0x04, 0xe0, 0x22, 0x14, 0xe0, 0x04, 0x24, 0x6d, - 0x74, 0x65, 0x6a, 0x04, 0x35, 0x14, 0x53, 0x68, 0x65, 0x65, 0x70, 0x53, 0x68, 0x61, 0x76, 0x65, - 0x72, 0x20, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x0b, 0x21, 0x01, 0x01, 0x21, 0x80, - 0x04, 0x26, 0x04, 0x04, 0x65, 0x6e, 0x65, 0x74, 0x00, 0x3e, 0x25, 0x01, 0x6f, 0x74, 0x61, 0x6e, - 0x01, 0x24, 0x0a, 0x0b, 0x01, 0x01, 0x03, 0x34, 0x53, 0x68, 0x65, 0x65, 0x70, 0x53, 0x68, 0x61, - 0x76, 0x65, 0x72, 0x20, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x04, 0x22, 0x1b, 0xbd, - 0x04, 0x22, 0x01, 0xcc, 0x06, 0x22, 0x05, 0xea, 0x02, 0x22, 0x17, 0x70, 0x02, 0x22, 0x13, 0x88, - 0x06, 0x22, 0x01, 0x14, 0x02, 0x22, 0x01, 0x2c, 0x02, 0x22, 0x01, 0x24, 0x86, 0x02, 0x02, 0x01, - 0xe4, 0x01, 0x1c, 0x22, 0x01, 0x2c, 0x02, 0x22, 0x01, 0x24, 0x86, 0x02, 0x01, 0x01, 0xe4, 0x22, - 0x01, 0xfc, 0x02, 0x22, 0x02, 0x18, 0x0a, 0x22, 0x02, 0x34, 0x03, 0x21, 0x01, 0x03, 0x21, 0x03, - 0x12, 0x2c, 0x0b, 0x4f, 0x54, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4c, 0x69, 0x62, 0x01, 0x27, - 0x06, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x62, 0x01, 0x26, 0x05, 0x66, 0x72, 0x65, 0x65, 0x62, 0x01, - 0x28, 0x07, 0x66, 0x72, 0x65, 0x65, 0x6d, 0x73, 0x67, 0x01, 0x26, 0x05, 0x63, 0x6f, 0x70, 0x79, - 0x62, 0x01, 0x27, 0x06, 0x64, 0x75, 0x70, 0x6d, 0x73, 0x67, 0x01, 0x25, 0x04, 0x67, 0x65, 0x74, - 0x71, 0x01, 0x25, 0x04, 0x70, 0x75, 0x74, 0x71, 0x01, 0x28, 0x07, 0x70, 0x75, 0x74, 0x6e, 0x65, - 0x78, 0x74, 0x01, 0x2c, 0x0b, 0x70, 0x75, 0x74, 0x6e, 0x65, 0x78, 0x74, 0x63, 0x74, 0x6c, 0x31, - 0x01, 0x2b, 0x0a, 0x63, 0x61, 0x6e, 0x70, 0x75, 0x74, 0x6e, 0x65, 0x78, 0x74, 0x01, 0x27, 0x06, - 0x71, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x01, 0x27, 0x06, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x71, 0x01, - 0x29, 0x08, 0x6d, 0x73, 0x67, 0x64, 0x73, 0x69, 0x7a, 0x65, 0x01, 0x30, 0x0f, 0x4f, 0x54, 0x4b, - 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x55, 0x74, 0x69, 0x6c, 0x4c, 0x69, 0x62, 0x01, 0x31, 0x10, 0x4f, - 0x54, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x01, - 0x31, 0x10, 0x4f, 0x54, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, - 0x70, 0x74, 0x01, 0x2d, 0x0c, 0x6d, 0x69, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x01, 0x2e, 0x0d, 0x6d, 0x69, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x01, 0x2c, 0x0b, 0x6d, 0x69, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x74, 0x72, 0x01, - 0x20, 0x3e, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x3a, 0x20, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x28, 0x29, - 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x73, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x0a, - 0x01, 0x20, 0x30, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x3a, 0x20, 0x65, 0x74, 0x68, 0x65, 0x72, 0x5f, - 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x29, 0x3a, 0x20, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, - 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, - 0x65, 0x64, 0x0a, 0x01, 0x20, 0x31, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x3a, 0x20, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x29, 0x3a, 0x20, 0x45, 0x74, 0x68, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, - 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x0a, 0x01, 0x20, 0x30, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x3a, - 0x20, 0x65, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x77, 0x70, 0x75, 0x74, 0x28, 0x29, 0x3a, 0x20, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x0a, 0x03, 0x22, 0x08, 0x4c, 0x82, 0x02, - 0x30, 0x08, 0x6c, 0x08, 0x7c, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0x2c, 0x08, - 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, - 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0x9c, 0x08, 0xcc, 0x08, 0xcc, 0x08, - 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0x8c, 0x08, 0xcc, 0x08, 0xac, 0x08, 0xbc, 0x08, 0xcc, 0x08, - 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, - 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xcc, 0x08, - 0xcc, 0x22, 0x08, 0x5c, diff --git a/SheepShaver/src/EthernetDriverStub.i b/SheepShaver/src/EthernetDriverStub.i deleted file mode 100644 index fa381407..00000000 --- a/SheepShaver/src/EthernetDriverStub.i +++ /dev/null @@ -1,43 +0,0 @@ - 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66, 0x70, 0x77, 0x70, 0x63, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0x90, - 0x00, 0x04, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x58, - 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x04, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x80, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xb4, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x46, 0x07, 0x09, 0xc1, 0x01, 0x43, 0x00, 0x41, 0x00, 0x41, - 0x00, 0x42, 0x00, 0x41, 0x00, 0x42, 0x00, 0x81, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x68, 0x65, - 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x6e, 0x69, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x47, 0x65, 0x74, 0x4f, 0x54, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x49, 0x6e, 0x66, - 0x6f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, - 0x65, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x15, 0x5e, 0x85, 0x00, 0x14, 0xbd, 0xe0, 0x00, 0x10, 0x8f, 0x84, - 0x00, 0x10, 0xae, 0x97, 0x00, 0x10, 0x4e, 0x3c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x44, 0x00, 0x01, 0x02, 0x00, 0x00, 0x29, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x02, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, - 0x02, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x60, 0x00, 0x00, 0x4e, 0x80, 0x00, 0x20, 0x38, 0x62, 0x01, 0x3c, 0x4e, 0x80, 0x00, 0x20, - 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xc0, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, - 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xc4, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, - 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xc8, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, - 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xcc, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, - 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xd0, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, - 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xd4, 0x7c, 0x09, 0x03, 0xa6, 0x4e, 0x80, 0x04, 0x20, - 0x02, 0x22, 0x01, 0x3c, 0x03, 0x21, 0x20, 0x86, 0x02, 0x02, 0x00, 0x10, 0x00, 0x08, 0x09, 0x21, - 0x50, 0x86, 0x02, 0x02, 0x00, 0x60, 0x00, 0x30, 0x01, 0x21, 0x40, 0x04, 0x24, 0x6d, 0x74, 0x65, - 0x6a, 0x04, 0x35, 0x14, 0x53, 0x68, 0x65, 0x65, 0x70, 0x53, 0x68, 0x61, 0x76, 0x65, 0x72, 0x20, - 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x0b, 0x21, 0x01, 0x01, 0x21, 0x80, 0x04, 0x26, - 0x04, 0x04, 0x65, 0x6e, 0x65, 0x74, 0x00, 0x3e, 0x25, 0x01, 0x6f, 0x74, 0x61, 0x6e, 0x01, 0x24, - 0x0a, 0x0b, 0x01, 0x01, 0x03, 0x34, 0x53, 0x68, 0x65, 0x65, 0x70, 0x53, 0x68, 0x61, 0x76, 0x65, - 0x72, 0x20, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x04, 0x22, 0x1b, 0xbd, 0x05, 0x21, - 0xc4, 0x06, 0x22, 0x05, 0xea, 0x02, 0x22, 0x17, 0x70, 0x02, 0x22, 0x13, 0x88, 0x07, 0x21, 0x2c, - 0x03, 0x21, 0x34, 0x03, 0x21, 0x3c, 0x86, 0x02, 0x02, 0x00, 0xdc, 0x00, 0x24, 0x01, 0x21, 0x34, - 0x03, 0x21, 0x3c, 0x86, 0x02, 0x01, 0x00, 0xdc, 0x01, 0x21, 0xf4, 0x02, 0x22, 0x01, 0x10, 0x0a, - 0x22, 0x01, 0x2c, 0x03, 0x21, 0x01, 0x03, 0x21, 0x03, 0x0c, diff --git a/SheepShaver/src/MacOSX/.gitignore b/SheepShaver/src/MacOSX/.gitignore deleted file mode 100644 index 687d4ec0..00000000 --- a/SheepShaver/src/MacOSX/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Xcode build files -build/* -SheepShaver.xcodeproj/*.mode1v3 -SheepShaver.xcodeproj/*.pbxuser - -# autoconf build generated Info.plist file -Info.plist diff --git a/SheepShaver/src/MacOSX/AudioBackEnd.cpp b/SheepShaver/src/MacOSX/AudioBackEnd.cpp deleted file mode 120000 index d0d8a5ca..00000000 --- a/SheepShaver/src/MacOSX/AudioBackEnd.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/AudioBackEnd.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/AudioBackEnd.h b/SheepShaver/src/MacOSX/AudioBackEnd.h deleted file mode 120000 index e4f493db..00000000 --- a/SheepShaver/src/MacOSX/AudioBackEnd.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/AudioBackEnd.h \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/AudioDevice.cpp b/SheepShaver/src/MacOSX/AudioDevice.cpp deleted file mode 120000 index b56f3a4c..00000000 --- a/SheepShaver/src/MacOSX/AudioDevice.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/AudioDevice.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/AudioDevice.h b/SheepShaver/src/MacOSX/AudioDevice.h deleted file mode 120000 index 7892391b..00000000 --- a/SheepShaver/src/MacOSX/AudioDevice.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/AudioDevice.h \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/Info.plist.in b/SheepShaver/src/MacOSX/Info.plist.in deleted file mode 100644 index 1324ba8b..00000000 --- a/SheepShaver/src/MacOSX/Info.plist.in +++ /dev/null @@ -1,56 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - SheepShaver - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - @PACKAGE_VERSION@ - CFBundleShortVersionString - @PACKAGE_VERSION@ - CFBundleIconFile - SheepShaver.icns - CSResourcesFileMapped - - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - sheepvm - - CFBundleTypeIconFile - SheepShaver.icns - CFBundleTypeName - SheepShaver VM - CFBundleTypeRole - Editor - LSTypeIsPackage - - - - LSArchitecturePriority - - i386 - x86_64 - ppc - - LSMinimumSystemVersionByArchitecture - - i386 - 10.4.0 - x86_64 - 10.6.0 - ppc - 10.4.0 - - - diff --git a/SheepShaver/src/MacOSX/Launcher/AppController.h b/SheepShaver/src/MacOSX/Launcher/AppController.h deleted file mode 100644 index bbe989fb..00000000 --- a/SheepShaver/src/MacOSX/Launcher/AppController.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * AppController.h - Cocoa SheepShaver launcher for Mac OS X - * - * Copyright (C) 2009 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -@interface AppController : NSObject { -} - -- (void) awakeFromNib; - -- (IBAction) openVirtualMachinesList: (id) sender; - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/AppController.mm b/SheepShaver/src/MacOSX/Launcher/AppController.mm deleted file mode 100644 index 46e862ce..00000000 --- a/SheepShaver/src/MacOSX/Launcher/AppController.mm +++ /dev/null @@ -1,44 +0,0 @@ -/* - * AppController.mm - Cocoa SheepShaver launcher for Mac OS X - * - * Copyright (C) 2009 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "AppController.h" -#import "VMListController.h" - -@implementation AppController - -- (void) awakeFromNib -{ - [self openVirtualMachinesList:self]; - [NSApp setDelegate:self]; -} - -- (IBAction) openVirtualMachinesList: (id) sender -{ - [[VMListController sharedInstance] showWindow:sender]; -} - -- (BOOL) applicationShouldHandleReopen: (NSApplication *) app hasVisibleWindows: (BOOL) hasVisible -{ - if (!hasVisible) - [self openVirtualMachinesList:self]; - return YES; -} - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/DiskType.h b/SheepShaver/src/MacOSX/Launcher/DiskType.h deleted file mode 100755 index 8f74d8a0..00000000 --- a/SheepShaver/src/MacOSX/Launcher/DiskType.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// DiskType.h -// SheepShaver -// -// Created by maximilian on 01.02.14. -// Copyright 2014 __MyCompanyName__. All rights reserved. -// - -#import - - -@interface DiskType : NSObject { - NSString* _path; - BOOL _isCDROM; -} - --(NSString*)path; --(BOOL)isCDROM; - --(void)setPath:(NSString*)thePath; --(void)setIsCDROM:(BOOL)cdrom; - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/DiskType.m b/SheepShaver/src/MacOSX/Launcher/DiskType.m deleted file mode 100755 index ec21d458..00000000 --- a/SheepShaver/src/MacOSX/Launcher/DiskType.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// DiskType.m -// SheepShaver -// -// Created by maximilian on 01.02.14. -// Copyright 2014 __MyCompanyName__. All rights reserved. -// - -#import "DiskType.h" - - -@implementation DiskType --(NSString*)path -{ - return _path; -} --(BOOL)isCDROM -{ - return _isCDROM; -} - --(void)setPath:(NSString*)thePath -{ - _path = [thePath copy]; -} --(void)setIsCDROM:(BOOL)cdrom -{ - _isCDROM=cdrom; -} - --(NSString*)description { - return [NSString stringWithFormat:@"DiskType, path:%@ isCDROM:%@", _path, _isCDROM]; -} - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/English.lproj/InfoPlist.strings b/SheepShaver/src/MacOSX/Launcher/English.lproj/InfoPlist.strings deleted file mode 100755 index f1842244c9c07de454abd8747d5422b605935efe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 276 zcmW-cF%E)25Ji9ODK?Z8dH`dg7HXmv5<4115CQ@LQStEVW3tK2?BAL9XMf+Bd^zn^ zD^{dZxjssCMSGH4btttevLmO&9k-Nvs>b>|Jx~j}2kY`R(}Z(Wpsjk{;Z{2F9>I-t zVJguYLc>H0|EA0s3pgGxnW-Z;w^^qZxwn0sDdT - - - - IBClasses - - - CLASS - FirstResponder - LANGUAGE - ObjC - SUPERCLASS - NSObject - - - ACTIONS - - openVirtualMachinesList - id - - CLASS - AppController - LANGUAGE - ObjC - SUPERCLASS - NSObject - - - IBVersion - 1 - - diff --git a/SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/info.nib b/SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/info.nib deleted file mode 100755 index d1a1a5e6..00000000 --- a/SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/info.nib +++ /dev/null @@ -1,18 +0,0 @@ - - - - - IBFramework Version - 677 - IBLastKnownRelativeProjectPath - ../SheepShaverLauncher.xcodeproj - IBOldestOS - 4 - IBOpenObjects - - IBSystem Version - 9J61 - targetFramework - IBCocoaFramework - - diff --git a/SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/keyedobjects.nib b/SheepShaver/src/MacOSX/Launcher/English.lproj/MainMenu.nib/keyedobjects.nib deleted file mode 100755 index 0e197efef29fe489df10acfa8a1ddcc725f4d37a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12048 zcmcI~d3+Pa`|!-}Y??cpZ0_{PX2VgC`@Si6!2+e_K5A$K6xyaVEl?1d1w0V}QIJcZ z2*@QOB40!<0Ra&a5fK#>6cM}+L`3BGY?9Ix%je@C?@LLtJ3I5-=gf{SF31m;Hg5b8 z!iYgEB8WpOq(Ryt{z<`-aDJ#L+g}YLRkSRTwvi!It}#(7AG^r#7Hf!d(Xs4MD*dZ7o=cvOsLqQ}t_ z=t=Ypnuq42g=jH)0WCwz(JJ&3+Jv^ESJ5`~8u}mFkKRE?&{1>@oj_;M$LK8j3|&H3 z(6{I+x`uv2f1n%aPxLotaROFj4c1~KwqZMVU?)z*687U-xHhhbo8YFn8E%f-;LbP= zcfs9p58M;?!C5#P55z<9LpXp(<6Jxz7vT^t#uITFei%>3kKh@2HlBl@#&huk`~qH% zSKt@%O1uVd#INA3_*J|O@4#>2J$NsE8y~~(;^X)|d^9OT>naUzo#hO?rT)EgJ*2|`{ z^-ycJ0dovSTC%O!PHZo@N@oYMgV+?f%3&X3N3%=W(?m}U#7InpCuU+H02J%AdZhNuy0Jg9HhfKaG(kUzH|5Dt&*o7FGsVBkUF zh%0qf#)IKOfr7FijJWz{rRC-Z!{PkV`33o<<^A&WV$Wc0*HBRrcqjO6czEBezJbDE zSb+oAJxbtaa;Rj2GAjyEc`^*}0RZI^9z+)04^a$us6?6BBUDtH5hx0b4VL8aeBZ1= z`9M!WaBzN6UTAWZ?ie4H;2bs3t)LwWXoFKqfr=4PTA~XmBja4URK|K4kER;>5mm`p zCu0LWBjblCq6zf0j00x8M8?JsK^09=Gt?XyjWDM$LOIGR4_cyDs5M||7%nZzFB(e; zke^lzfiE|p24Fto(q8CK~V-4znI-*VyJ!F)X27tw^2$Ugxv+iC* z8I8h8LtQFR7u0DK5KQzxN>8SS_ z)Eo6doj@p+h=ZjA0c)@{x-tXxrAxN*9@G!@N112<%0k&_AR2@QqakQ08it0W5ojbD zg>ukCD1b(zT$G1`Xbc*Q#-V(wrB0em{j@G^NSo5uv;*xzd(ysi03A$6&;Sk633MVY zqf_Z4bQXP_&Y|<^bEkpk38(-Sq9PPhL=Y+~$qf$foAqE|bg+OrsE*pt!JLVx1cgy4 zDnpadWHbepqp4^bdKgVdkDwWdA{mxs=a&`)b9i$kS9G6PmOm*Yl$Q|*PXKv@ahzGPNms3e7=Jqq(5R z0l{#D&4^7|C{N8meFSsVEC5p1alzaPg@KX@QSB{2&sLyk6|(`)h?+qqka*yWr~=Iz znWfMZVJWLLP#TPaS%Q{Uprxo22&9tS9NtkJEEy9jDO3pVA1DeIq($7lZFI>B^x_)y zB3h~7wt-{ij|Q(TEeRFebzWd7I;zBpP)U_WE6^HHpo=Db@-GFJqjjLZ^)dBr1Q~m1 zVnnj;D!Fb!uYfFf(p{q>((q;#2MY?o-!j{c%2mWudEfRUfWJLvMk(kGv=g-4Ef_A% zFN*jh5W&zCD%C{Bn`k$BD@MjXAVai3yhYR(p~b5Jo`?=aw0sa9LWjXJB1&6L-=!z$ zd&7I>=LNm}O2%}woHM)$x0b%c> z2k8DB-qJ;hYu>bi0&i)^+oJ?D-XBaeP*M^o8XHV6ij3SN_8-uX5kWViO==?JmpC#M zK{t+(;T@7SE;Ly|1>!3!QUnOs_YvP;=oa8;MqAZ{;UBme^VXdBwT22_|w)3CWxPk^c|Z5P!NM4#Se zg~f{0q8K0@WRB0_lX8ParNNTBW9db)^p;i<48&n|V-H~MNYiS%WIF)aJ|-8%*3xP32*`R6I|k*Kl$Hewycq$g`-_5M?}N}MWIh;6w7452 z*9S*}-ecjVKq&*9q2eG&DzdP0ow6*B#q@|r^}CNp;S8XtZ>6U20HCQq&5Y`b$3aMz z`H*<>ytOmO+;t~B7!Ls^v*@6jSR4)jN5n}jn+}Xh4Z?D1=9KK*vUuu(cnp9VLWkD` zDj)5}L0kLOnUIFOw-I#gEb%^DXB7H5qMK;H*W5h}?GmPBF+*oq|GNPfmk@iOrGm2}m>t_7iR zFmv+A7?Y9PI7F*)1t2P*#Wf*X3y9Xm5N!ZNMKlyaR9F>WHsdXT=q=D%!w~3{%Q%eN@#}!GgqGHXac5k}R8nL(CQf$_@2;K^y@9ZIXsFDaU0w_YP;zN# z?AU^!;z;>LWsoZ(i88VRqIw+m{rCW2pG3=R!hQ(&JsfA9lj)SGb!HC;=7lnc4J?75 zdu-z*{r~_nbQ+yr6UfuRP<*m|xH8Xzyds%2PG|#_Ob|!w=lDE;oSYfLg$hT+Oi{V6g2)ht1Bg%4c{M;})My%`iE@h+yO>L# ziE!)Ahl;%zD)IvOQ{viKh-+;jZ!3n^6I#9SJ)Xr_BEfUPeS#-r2Skn-BFcCG)w6VA z1eKmofOI`D9IQ%nUZ^3xN{NygtX7XPBI5&I82UVYp(bu>0g~D=Buda&L>EU;c)=(# z%krzmjLeC{Ad40%bzLx8pE3=ZMr)WxOyfv{6zgl!piU`=k~;Dm>1~*%Of&l7R=x$( z9G_%b;v48MrVY~;&t%%;ARf$gVmf06htV5MH;{b~yd9{vFul=5yckvBx_ATAAF`hw zuV%9GJiH%mWQHJ$)6qF}9A85}Fgf^hRD@eGxlA6~huzFrW*l7xZcqVM(TuL48zEe7 zf;^B#H`6V&ImGA`x()RECiwpIbOGH>>(Q}LDtD!Y^bN?bZ6FG*gOE3gy6M|gPy0c2 zR|^cb5j_Mxpo9GTDqT*!P$|4mk9~@a%=qdZ5;FmnXKA=(lEB%-EK0Gto%z`SO(LQDoEL%rkiZSS=Ylmb7OD5&RZbv+) zOPOWNa^Q45-9TSfSb+|oSzN`{YPw_<_)(71EJs%>?bCndO7Z$C((C=lWs%rZwXFGn zTo#EjRm=V>Hl(;-)iQ6T5ROrj-90bAa)*Fm#b6^`<>T-ay@;mGD_3!V5&uVl?;4W zrNy7=lC|KoMd&zV!HQ4mz^4|_Hb7sEh&G}v)e!vyh}_VRM*FAc^nXJtJJ6W*vkYCb zh9M9!wu5iGXvu%%{9fVThakKGZ>}PU$zvTrP$ASCQG%A!J=scmQAvzPamCfNASMYm zg_1$h-L%RXKDuNb4&xh4TXc@;gj+#adICaKDg>!sqrli>dvA)ZD@$NMjC}yg^n>@K zk6{~Eqpt`l#SBGNvZn#!HdYJn@D8UUgcEg8(kwTEt zSh#)z?zX{wJ@_b)mczGlr_4GA-^=OpN)DGR9JZ{=wLnX?YzuUC#$llQjsFkXmboY2 zHU}M#1j;?7<_Dl96dx`yu{hGbZe#2g2 zzh$qo*Vyma@7W*NAK9PSpV?p7U)kT--`VTzAM6eGPxdDJ7ki8So4w8c!`>l?V8RfV z5W*1^Gl{5)hG>b7eoW8OPv|-NDgBIoPS4W|^b7hWy+|+7ujtqGGW~{Lq2JQ0^cww+ zeoud(KhmG*&-54iEB%fBPOsBH=neWOy-EL~x9H#WHvNa*kuj1nmND#(voaiYtL<^CtM+12 zM<~GSguVSH7bzX0wc4y`=8cEl6q?AmDgWv*Q-|KABZn8`X4cqV16iiHInd9?<7zfM z@~p0s4dcgKR422tnFe6hg;taYLykE35uru*4pT$C4P`*(UIZK5UX%_cQV_Ppy{PWL zD|!@e(Zag6XmmG)n-#f1`!4)^5+Ac6Wv&21%HmERI z&2eJ;t1ujIkr6wtKBP3uFv}JPF@jAw#eng62dZ&5FWxenR8m$qPVfLEUcwPCgt2%Q zVwP0hRpLR!qA%%6KU`IL-6QTgU5Uz>aDp`^nt#wZrQ55_KyaGXPwDyK>?#KjM)@ef zbVAum_XnQ#5Ojc#Hj+(bGuc93AzR6-WE**nY$vai9pnwNll+hDB5#u2?QliesX}kO%9Sn&UpSj8kP?Psa6S z{D6!b$he`58_Bq_jGM@~sf?S+xVem5$hf79TgkY!jN8b#t&H2rxV?-!$hf17JIT1S zjMHS?MaEra+)c*aW!yu?J!RZW#_2NdE#p2ieo)34GVUwmelqSa<4hS3ka3obvt>L` z#)D)$SjIzSJXFTRWISBPBV;^M#-n6-F=j9S4xhz8#y`)$%OB=9^RxI7d|UoFf0TcP ze~*8GKftfz=kWW@cmcnJpU-dL>+n-~2mdU;fPb0a&Clca@!R<)_|^Pa-pSW8;}`f$ zehzEN`5KN@fG|t{7d{I zehvR3zut`J^UL`o{Hy#4K8fGKx8XPO0^d4fO(=s)gI+pjSzNa&zvX&HuAyG$(z)Ih zT<^$+PI{N^AlU6k%7` z-=KWb!+Rwy;a!lyB%jP8bIDS&91M6hnC^No+D%}vuY#fO026%^%yTao<{>c155Uwe zfSFx|_eQS6n<095^TP{ocC>+aHTrPb+)!>DH;tRk&Epnu&vMJS3T`X6gWJpP=WcSh zxZB(v6;`n-PL-h2sB|iW%A_)@1eHzYP`OkdRgx-2C8{JRfeDU8;Umy-@wUda-(mdYSqy^L1iM)weWOji`|{wKR1!4{G{q`fCPgvNeM=Lo~xQ z<22(nlQrdohNGHfnZj_GtEL4rmT)KGB@he5d(a^N$v387+YYU^toXd7vpXxnPDv=3=VYxA^Yw2y0_)Xve))y~r{&@R-j(pG3+(yr5P({9)9 z)gITL(4N$u(*CObUHgajPwijYzqSA9EIO;Mxh_rDRo7kDQ#VdGURR(i(iQ7Ubfvnf zx`%bMbn|u3>Ymdr((Tmk((Tsm(e2Y6&>hqr)xE3xKzC91mF}|citegjtJmv|dR}kQ zTlIE*Lw#d?8+|){2Yny?7=2h@rk|`Y*T1M=rLWMxq+h3hS-(-gS-(@iOaG4ksQz93 zd-@;rKk0wb|E9mLzoEaWzpcMxAO^ERFxU(ZLu*4@LwiFL7QVH0cOOiq*AaEXm@~}%%*EysbE$cfd5U?e`C;=s^8)i4^Q-39%&(i@Fn?w~ zZ~nr3(fpP9viXYns)ex-i_PM&xGWw^lBJ`iv!#oro27@Pm!-F5q$S5P-V(Mv*7gj^vgj1}^Q2|}R|5+({^VY#qQ z*eYxjwhKFiox(0*x3EXpCww4$D10P*EPNuI7rqy+3pcFD%2+vTf|a-0tR1ZnT8CPP zTSr<)Ss$_nthv^pb*y#1^;zq4)n{V4?+ilxp+iTlzJ77C#J8U~*`@r_0?X2xf+a=pA+ilw&JGQfS&Yob`*mZV; z-DEf01$%pYM|)>`n!T&No4tp|5>I?Az_1+b`I^v|qA+ZU4spt^Jz)d;4|!KMv$baA+Jlhr!X((c010(azDq z(b3V_(Z$itQRoOcCOX27GRI^`xnr7Rx?`qej$^K4zT;WPGRF$XOO7p$t&X=GdmZ~7 zZ#xb--fgjHW~bn^IUP=y)8kBX)^;{>HgUFhc64@jc5!xd_Hc%r z6P;manRBwU+&RrT-8sWK$N8Ldk#mD{lXHu6t8<%kyK{$gr*oHcxAUm;7w2!z>&_d_ zo6cL#+s->K>@v9QE|1Ias_k0ndfv6zwZyf|wZgU1wc54Dwbr%XwZXN?wZ*m7wavBN zwZpa3wac~Jwa2y3b-;Ddb=Y;pb%8j=*G1P?uFI|~ zuB)!^TtB#ea{c1^&2`;%!*$bj%XQnWa;x2w-R16S?&7E%L*)z-YsONFdlb$)Axt@8R1)hbT=RJ!(OFYXwD?BSb zt37KxYdz~d8$6plTRdAm+dQv(c6#3Q?D6dP9Q3^7IqEs?dEax&^O5IDqAJmnSSzt( zVxPp(iA9OeB)*XNR^t1KpC*2j_-m3TDKV*KQf^Wx>4l`7NuMYElyo~;lUzHwO>+0- z5y=yh=Ok}Tek=Kd%JJUN`Ocm>k4a7!b6S0}tLTn|r5!;C!#7<(G*j4N<_7u~_K4OO0Ps|jv z#DU^qai}<494Y3A0Wnt$ietrmae`PVhQx_tSS%AKi{;`pak@A|l*L)%qvGS@lj0n4 zt~gIzATAW27Z;05#AV_NaizFgTqCX(*NYp(P2v`DtGG?vF76O_io3+!;vR9IctAWT z9u|*?$He2}N8-o6X}(8%vTwHUaoc2Y+vP3k7~lzK}UQhzB+8YB&s zMo2l*XelU-lO{+-Qn6Gbl}eMODbiHwVd)WxN;9R|(qqyS(o@pY(lgS0=~?MHX_2%< zS|+WKR!Xa-HPTvXy|h8vByEwlO53FE(hg~-v`gA8?UD9NZ%c=ycci1zyV42iq;yI; zEuE3hO6R1{r1R1j(naYj>9X{r^t1G<^t<$j^r!Tf^tbenANd(S=TGo!{5rqEZ}OY{ ug5TzM_+5UV-|w&GZ|HCAZ{lz3Z}0Em@8R!*BL5gB`pd=cqjw1Thy5Q=ZbjMv diff --git a/SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/designable.nib b/SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/designable.nib deleted file mode 100755 index c71e47ba..00000000 --- a/SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/designable.nib +++ /dev/null @@ -1,713 +0,0 @@ - - - - 1050 - 9J61 - 677 - 949.46 - 353.00 - - YES - - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - - - YES - - YES - - - YES - - - - YES - - VMListController - - - FirstResponder - - - NSApplication - - - 15 - 2 - {{196, 309}, {412, 201}} - 536870912 - SheepShaver Virtual Machines - NSWindow - - {3.40282e+38, 3.40282e+38} - {412, 201} - - - 256 - - YES - - - 274 - - YES - - - 2304 - - YES - - - 256 - {374, 94} - - YES - - - 256 - {{375, 0}, {16, 17}} - - - YES - - 3.710000e+02 - 4.000000e+01 - 1.000000e+03 - - 75628032 - 0 - - - LucidaGrande - 1.100000e+01 - 3100 - - - 3 - MC4zMzMzMzI5OQA - - - 6 - System - headerTextColor - - 3 - MAA - - - - - 337772096 - 2048 - - LucidaGrande - 1.300000e+01 - 1044 - - - - 6 - System - controlBackgroundColor - - 3 - MC42NjY2NjY2OQA - - - - 6 - System - controlTextColor - - - - - - - 3.000000e+00 - 2.000000e+00 - - 3 - MQA - - - 6 - System - gridColor - - 3 - MC41AA - - - 1.700000e+01 - 316669952 - 2 - 4 - 15 - 0 - YES - - - {{1, 1}, {355, 94}} - - - - - 4 - - - - 256 - {{356, 1}, {15, 94}} - - - _doScroller: - 3.947369e-01 - - - - 256 - {{-100, -100}, {374, 15}} - - YES - 1 - - _doScroller: - 9.904762e-01 - - - {{20, 60}, {372, 96}} - - - 146 - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 293 - {{302, 12}, {96, 32}} - - YES - - 604110336 - 134217728 - Launch - - - -2038284033 - 129 - - - 200 - 25 - - - - - 293 - {{206, 12}, {96, 32}} - - YES - - 604110336 - 134217728 - Settings... - - - -2038284033 - 129 - - - 200 - 25 - - - - - 293 - {{14, 12}, {96, 32}} - - YES - - 67239424 - 134217728 - New... - - - -2038284033 - 129 - - - 200 - 25 - - - - - 268 - {{17, 164}, {147, 17}} - - YES - - 68288064 - 272630784 - Virtual Machine List: - - - - 6 - System - controlColor - - - - - - - - 293 - {{110, 12}, {96, 32}} - - YES - - 67239424 - 134217728 - Import... - - - -2038284033 - 129 - - - 200 - 25 - - - - {412, 201} - - - {{0, 0}, {1680, 1028}} - {412, 223} - {3.40282e+38, 3.40282e+38} - - - - - YES - - - delegate - - - - 46 - - - - newVirtualMachine: - - - - 48 - - - - importVirtualMachine: - - - - 49 - - - - editVirtualMachineSettings: - - - - 50 - - - - vmList - - - - 51 - - - - window - - - - 52 - - - - launchVirtualMachine: - - - - 53 - - - - importButton - - - - 54 - - - - launchButton - - - - 55 - - - - newButton - - - - 56 - - - - settingsButton - - - - 57 - - - - - YES - - 0 - - YES - - - - - - -2 - - - RmlsZSdzIE93bmVyA - - - -1 - - - First Responder - - - -3 - - - Application - - - 1 - - - YES - - - - - - 2 - - - YES - - - - - - - - - - - 13 - - - YES - - - - - - - - 14 - - - YES - - - - - - 15 - - - - - 16 - - - - - 17 - - - YES - - - - - - 21 - - - YES - - - - - - 22 - - - - - 23 - - - YES - - - - - - 24 - - - - - 25 - - - YES - - - - - - 26 - - - - - 18 - - - - - 31 - - - YES - - - - - - 32 - - - - - 43 - - - YES - - - - - - 44 - - - - - - - YES - - YES - -1.IBPluginDependency - -2.IBPluginDependency - -3.IBPluginDependency - 1.IBEditorWindowLastContentRect - 1.IBWindowTemplateEditedContentRect - 1.NSWindowTemplate.visibleAtLaunch - 1.WindowOrigin - 1.editorWindowContentRectSynchronizationRect - 1.windowTemplate.hasMinSize - 1.windowTemplate.minSize - 13.IBPluginDependency - 13.ImportedFromIB2 - 14.IBPluginDependency - 14.ImportedFromIB2 - 15.IBPluginDependency - 15.IBShouldRemoveOnLegacySave - 16.IBPluginDependency - 16.IBShouldRemoveOnLegacySave - 17.IBPluginDependency - 17.ImportedFromIB2 - 18.IBPluginDependency - 18.IBShouldRemoveOnLegacySave - 2.IBPluginDependency - 21.IBPluginDependency - 22.IBPluginDependency - 23.IBPluginDependency - 24.IBPluginDependency - 25.IBPluginDependency - 26.IBPluginDependency - 31.IBPluginDependency - 32.IBPluginDependency - 43.IBPluginDependency - 44.IBPluginDependency - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{308, 569}, {412, 201}} - {{308, 569}, {412, 201}} - - {196, 240} - {{357, 418}, {480, 270}} - - {412, 201} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 57 - - - - YES - - VMListController - NSWindowController - - YES - - YES - deleteVirtualMachine: - editVirtualMachineSettings: - importVirtualMachine: - launchVirtualMachine: - newVirtualMachine: - - - YES - id - id - id - id - id - - - - YES - - YES - importButton - launchButton - newButton - settingsButton - vmList - - - YES - NSButton - NSButton - NSButton - NSButton - NSTableView - - - - IBProjectSource - VMListController.h - - - - - 0 - ../SheepShaverLauncher.xcodeproj - 3 - - diff --git a/SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/keyedobjects.nib b/SheepShaver/src/MacOSX/Launcher/English.lproj/VMListWindow.nib/keyedobjects.nib deleted file mode 100755 index 23a3b0ba362478e433d32016b175d4ea49491895..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8475 zcmbVR2Y6J)+WuzF_Il3lo|BvdNMfkcQfQ$_LJ2h?kPtd?NtR?~lMTC@1PH+q+f}fk z*ib}@1yn%nV)@l;;iA_oU_-H8MMXsAVxh?Y%{jY}SpMgK?(&eGGiTL71V@8*zP%Ivf)|YolL>p#y3C5~w!`L;WOLYFlp{hjO2jt52 z{{k!6=8hlP*XXPcCW4Gqir$j4iJ>K->cZrtZQ?F)f(vqB01Sj-FdRn0Jg9_=APDoJ z3g0!r61Wa-hK+C^yaKPnKVT313--h3a1_3WU*K0bMJO>7H}McJ@sV_rNxG3`VD`E&>!K?~>@T0|$(NpwC9(FL@YE~jhggY+T#Fx^JC(;f5? zx|2RiAES@cC+L&(Df%>hhVG)z(&y;&^ac77eT9A{I7p4)6kLK^@CaT(6eO4>_yoTY z5M)6S(u8zD6*QrP&{60loF{Y^GRT!erf|NH1+#@NLRX=O&`an$txJ7lB=WK712=fU z3nED113v^n1_ja}9aPYu19XH=a2|Aq49JA@Aq%=dSLg=ap$GJY3!oSDhCa|2`ayO@ zN!iqBG*Qu|DiVyx=a!UBHsS#t9@jlTiuZ@&6~Rbj2z%6$vcjsWP&^) zD0_x2Ww)@WS&&`A%xn$2l`-}t17=~%*;C?BcH7(Nfn3Og{-~d>6UWa?Oh8B##gi}* z5pyCIjYLARw_y+rhI|+@!!UFxKFes-X1BJ|b5Jut4(J%&zU@VM-@h|}%Mwc>q2geC zAs=suLF04C`dZA*Dw&hbVRl~z05Au0F&mpFQqjxiGN=^OTUv7R2lmd$%g%4@ozc=i zC%1P-Zgx&;?*SCLm?%>=| zue`x1>D)u>taAe2g=+Le2o^vM(qb)y;bK?_5vapfR9BHl-PBOLAzEJ@ilHOR8s|5m z9(<`L-HfTM;kLqdSz|*e#z!y@o6Wou0X7qxvy5O^1TmIJT0&cF|{Hpj%hhu0t{nf1zZM~!xeBPTm^qae5J4wR>3MYKE!By@F540OC*Ro?&bRyHH%sq{*UKh(6N)--h4# zUm`wK$jt^bAM>Tux`AbHL^La51@;bR!w%?%ZGknqac@CIZbeltLCtT6J76u`33tId zRAN2$tivd&GK`6>(a|an0$U@;j*3R2F|^PiHc&J%zhnm%z_oi~S0J_WW|n;qtYd+X z#Q?5(Kbr3W*aBPOL3jurhHbiQx8wRd;1NWy6CQ=f5a<)|Bs>LA!!xi8o<%&*q0^to zr!c&TskRDU#&r98rPvwq#DX<77~W;k##oge)J4%)Nwj`av?>@ul;s9;J^Fbj)Wo8V z_0>A^O3{aO7KtF&l`m-sm4zahLgzk?_W2>Z0gKq^u!Wg)2=DS0`$9 z3P&l8b@hdfiD)bo4=?2?cxGXO{BhQ}P`IX+C+L{^AaZOqdV6dvoC1P-1O9Y2F_Ff~ z`7mPzq~eZ$p{cGW%9lEV6q*Zl#79&W)9^{UotWlV0n8Tc0&ZYI-R9eih&j!GoW`yHc$B+%>JA~t*r(jzX5M< zf;Zux@D>c6TiMotSQoh+IlxqsrUGLx4~%_Gdly6E9e5YsgZJSBH~=5QM{p26hEL#A zScl#i7Ybr(k3#!n`slXDG#`z7D&B=nB(PL3a-ZJB<#g-m+0u`7$SP>g*7aoFvkFEV z8fO(;UtshF-i3c7hAr>~dTFQ4hs-+*;v8LT7g#Lh3>hl~6GKf*Ei4;+V|;Ab=rXC?gNB@anqfxZgs zoK?`x0LjjiTpj03YOD%Z2gk;O$Z>|jPr%6ya1w^%R9?gPqU6)?8=N6Ph#tV0mpocS z++?-kM2KaI!o=*pdHj=`pAWhiA`sICVuGPKN=LjOJotE;Scny6*@=TViHjS6=Q+p7 zi3lwpiPrEZmdUz`7S@GjRg^7>Cqi||$hEq+&f1_YGKpo5%ucTCCxOi*KxCqjG#IKU zr|z+H&eqwT%P9(nBGudls92%CE8-8RIsZzz?n|O_*Ab0$fc2yktRtOCMv^v>dwC%E z0-3)Ru)fGnJy<}p0qfnyAtVcaB3-%VFF0#?Q=q*)dZ0ae5*KRSi(SC7up(C(8V!ixScBqZI+=krAWUXqdk*GGc`#NJN?^l?30$+3vvhp|i;u{L zvV7#YAxz8~@&2fJ41H=4*Z|I3I)Npz%&Dx7ri$(m!+;l&;ARp`DTB~b@3Ckmp)Esj zShU)~TR>_MAeJZ{Vk8M;xJWqL>PU|6IGLd%QCnL2? zJh1)?Q*K04HX5enn&H3ks8!MIvQQ#{`-ynpzJ323&K9z@9h`}5QW6dp>Kq=mW~CBwB>^c2Xb=J#*k8}Q z{=AKQhxg8v-6VUzOgfNP$g2pVnd~MRK9i&~_Ea_n0hIW}0u!<}hVJjq6&d`HIHWzd za1KGi*K!v08R9i?Djuz+x=Hn%H8jsgzJk1!}^3lf~4EDLgt9$5;;X z3k}RMW2276Xi{)~D8j1oj$j(ALbbxW%1PfQkBkN-QwMc!q)zJM+Q_(F3eQg#82sW_ zCD9m?i_vR5o`d1Rb6jUCu^K$XQMO=aeW=;Ua@`0tK;?~8HY5jh8Iv3F7|!n;elLkD zl%Sf9xPXNbNkpfb-yv?hbOM*oz@-at>4kHQ;l}E1N3FwA-EdR@N7Yp{)$wpX_nt4? zNPFwc7BM{ab_i966YUpGvBi*c(>yq>kmjOT%B*bBjA}gH)S&Orjo^Zt=wMy&1jacV zZPQ+EJ9&!{=7lJ48cJ-OV|eS2$~5Ar(KxCIM>WrjCu!`D;|g)y1RQ6@aZ4(i^(!Ym z=x8x5VXfOlKNKPjG~rh64*fV@3j62`@+`VDj;DhaWGm*)2e1+al(3O#yK(wK-OV)C z!b;KEBI}OlR|3|58NmbL%|Etbhql#>236OdIw!g z@1%Fpb@Xn!p58+@(2aBx-AwPL_tE?519S`B$}VLq*k$Z;b_KhVUB&*!u4dP;m24He zmR-lLXE(4L*=lwZyLnDgI1=g}&zRhd2jfbyt3f9jJ^ruDo}QIrR#^f~T$RE1vl%^- zp_RG~GFTf&1&rXx;B`5phf%(HX%|ecGp$Vt3wj!Uux4%o>4PVo6M2X7#?Fo)fvXFO@V2HC*{o|ss@KOYgH)*M@C|*poGtW8Pa}1GK=O=#fR@mU=rVc@y#=#5Vi`B3(p9}4MHd*eq+;7=pdDilRdd2V)@MKwW`)EYaeSrYmPO~I>0)}I>b86dZD$zI?_7YT5O$cooX$&-e-N? zy4QNhddg3Wp~@XcFFFyUtrI(53^6OPqELnFR<6z7uxIW*Vu2h-)-Mwf6V@ZeUJT3 z`&;(+?Fa1twjZ${b+{bqjx0wX#}G%6W1^$jG1)Q2QRbNDsBqLc>K%=a2|8l?#`ahUd}$we$E`{VCMwqbmvUx z9B0Vc;Jn;jBpjt`}Udy54aebRBjbaeePLyRB}!+v#?@ z)7)L$-Q2z0{oNznD}dh$-Bq9-}{;O zu=gkL8O+S{#V%quv4_|bbG45+Mr;xni%Z32;&QwsSRq~~ZWDKiJH^MuC&VYkr^Q|3 zUdbfcC8y+;ypkmOC0Xhy4VOkph0-W#j5JOfFHMw+r3KPe(kkgX=>}=FbhC7ev{t%H zdQ93a?UCM;-jd#yK9;_cj!9>H8NTyj(eeL_+ciJ!bU4DD`4{@@{89fRf84*)f3ttBf2aRN|6c!o|GWP8{RjMC_`mZX54ZxI0-XbyfviB+ z!0wZM}AX&OMY8EAb%u(EFY17l20lo#iI06 za+Ew}fHFwQSB5IXl@UszGD;bvj8(=f6P03RvNA;}Q>H2Nl#7&=%C*Y%%8klR${OWX z<#uJQa+h+qa*wi6*{s~BJfLh<9#Xa`JCvQuF6BApYvr(VL^-Pbpd3?^i}B_ z(s!l5o_-+xX!b2_i>W%6h>YeIG>c{G*>gVbg>LK-O^{{$G zJ*xho9#fC2KdZm0C)LyH8I5RyX4b5lU2|$~&8tb8Uz4>oP1QPRowUwcrk163)w*jv zwO(2ut)G^o - - - 1050 - 10K549 - 851 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 851 - - - YES - - - - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - VMSettingsController - - - FirstResponder - - - NSApplication - - - - 256 - - YES - - - 256 - {{145, 20}, {43, 22}} - - YES - - -1804468671 - 71304192 - 40 - - LucidaGrande - 13 - 1044 - - - YES - - 6 - System - textBackgroundColor - - 3 - MQA - - - - 6 - System - textColor - - 3 - MAA - - - - - - - 256 - {{193, 17}, {19, 27}} - - 1 - YES - - 917024 - 0 - - 1 - 40 - 1 - 10000 - 1 - YES - YES - - - - - 256 - {{17, 22}, {114, 17}} - - YES - - 67239424 - 272629760 - Volume Size (MB) - - - - 6 - System - controlColor - - 3 - MC42NjY2NjY2NjY3AA - - - - 6 - System - controlTextColor - - - - - - {229, 62} - - NSView - NSResponder - - - 13 - 2 - {{217, 242}, {580, 460}} - 1886912512 - Virtual Machine Settings - - NSWindow - - - View - - {1.79769e+308, 1.79769e+308} - {580, 460} - - - 256 - - YES - - - 274 - {{13, 59}, {554, 395}} - - - YES - - 1 - - - 256 - - YES - - - 258 - {{95, 50}, {327, 22}} - - YES - - -1804468671 - 272630784 - - - - YES - - - - - - - 258 - {{95, 78}, {327, 22}} - - YES - - -1804468671 - 272630784 - - - - YES - - - - - - - 256 - {{14, 52}, {77, 17}} - - YES - - 67239424 - 71303168 - Unix Root: - - - - - - - - - 256 - {{20, 80}, {71, 17}} - - YES - - 67239424 - 71303168 - ROM File: - - - - - - - - - 274 - - YES - - - 256 - - YES - - - 292 - {{10, 5}, {82, 32}} - - YES - - 67239424 - 134217728 - Add... - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - - 293 - {{211, 5}, {94, 32}} - - YES - - 67239424 - 134217728 - Create... - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - - 289 - {{417, 5}, {90, 32}} - - YES - - 67239424 - 134217728 - Remove - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - - 274 - - YES - - - 2304 - - YES - - - 256 - {468, 136} - - YES - - - 256 - {468, 17} - - - - - - 256 - {{469, 0}, {16, 17}} - - - - YES - - pathCol - 371 - 40 - 1000 - - 75628096 - 2048 - File - - LucidaGrande - 11 - 3100 - - - 3 - MC4zMzMzMzI5OQA - - - 6 - System - headerTextColor - - - - - 337772096 - 2048 - - - - 6 - System - controlBackgroundColor - - - - - - - - isCDROMcol - 64 - 10 - 3.4028234663852886e+38 - - 75628096 - 2048 - CDROM - - - 6 - System - headerColor - - - - - - 67239424 - 0 - - - - 1215058431 - 2 - - NSImage - NSSwitch - - - NSSwitch - - - - 200 - 25 - - 3 - YES - YES - - - - 3 - 2 - - - 6 - System - gridColor - - 3 - MC41AA - - - 17 - 312475648 - - - 2 - 4 - 15 - 0 - YES - 0 - - - {{1, 17}, {468, 136}} - - - - - 4 - - - - 256 - {{469, 17}, {15, 136}} - - - _doScroller: - 0.99350649350649356 - - - - -2147483392 - {{-100, -100}, {374, 15}} - - 1 - - _doScroller: - 0.99047620000000003 - - - - 2304 - - YES - - - {{1, 0}, {468, 17}} - - - - - 4 - - - - {{16, 42}, {485, 154}} - - - 18 - - - - - - QSAAAEEgAABBmAAAQZgAAA - - - {{2, 2}, {518, 209}} - - - - {{6, 123}, {522, 226}} - - {0, 0} - - 67239424 - 0 - Volumes - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - - 256 - {{14, 22}, {77, 17}} - - YES - - 67239424 - 71303168 - Boot From: - - - - - - - - - 256 - {{95, 18}, {94, 26}} - - YES - - 343014976 - 272630784 - Any - - - YES - - - 5 - YES - - YES - Any - CD-ROM - - - - - 274 - {13, 42} - - - YES - - YES - - - 10 - 10 - 1000 - - 75628032 - 0 - - - - - LucidaGrande - 12 - 16 - - - 3 - MC4zMzMzMzI5OQA - - - - - 338820672 - 1024 - CD-ROM - - - YES - - - - 3 - YES - - - - 3 - 2 - - - 19 - tableViewAction: - -765427712 - - - - 1 - 15 - 0 - YES - 0 - - - - - - 256 - {{390, 22}, {129, 18}} - - YES - - 67239424 - 0 - Disable CD-ROM - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{355, 17}, {22, 28}} - - YES - - -2146566624 - 0 - - 19 - 4 - 1024 - 1 - YES - - - - - 256 - {{309, 20}, {41, 22}} - - YES - - -1804468671 - 71304192 - 64 - - - YES - - - - - - - 256 - {{200, 20}, {104, 19}} - - YES - - 67239424 - 71303168 - RAM Size (MB): - - - - - - - - - 289 - {{425, 72}, {98, 32}} - - YES - - 67239424 - 134217728 - Browse... - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - - 289 - {{425, 44}, {98, 32}} - - YES - - 67239424 - 134217728 - Browse... - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - {{10, 33}, {534, 349}} - - - Setup - - - - - 2 - - - 256 - - YES - - - 266 - - YES - - - 256 - - YES - - - 270 - {{125, 20}, {218, 18}} - - YES - - -2080244224 - 0 - Enable QuickDraw Acceleration - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 266 - {{206, 132}, {143, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - LucidaGrande - 13 - 16 - - - - - - 400 - 75 - - - Window - - 1048576 - 2147483647 - 1 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - _popUpItemAction: - 1 - - - YES - - - OtherViews - - - YES - - - - Fullscreen - - 1048576 - 2147483647 - - - _popUpItemAction: - 2 - - - - - 3 - YES - YES - 1 - - - - - 266 - {{206, 104}, {143, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - - - - - 400 - 75 - - - 30 Hz - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - YES - - - 5 Hz - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 7.5 Hz - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 10 Hz - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 15 Hz - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - - 60 Hz - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - Dynamic - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 4 - 3 - YES - YES - 1 - - - - - 268 - {{118, 80}, {86, 17}} - - YES - - 67239424 - 71303168 - Width: - - - - - - - - - 268 - {{118, 52}, {86, 17}} - - YES - - 67239424 - 71303168 - Height: - - - - - - - - - 266 - {{209, 76}, {140, 26}} - - YES - - 343014976 - 272630784 - 800 - - - YES - - - 5 - YES - - YES - 512 - 640 - 800 - 1024 - Maximum - - - - - 274 - {13, 105} - - - YES - - YES - - - 10 - 10 - 1000 - - 75628032 - 0 - - - - - - 3 - MC4zMzMzMzI5OQA - - - - - 1412562496 - 1024 - 800 - - - YES - - - - 3 - YES - - - - 3 - 2 - - - 19 - tableViewAction: - -765427712 - - - - 1 - 15 - 0 - YES - 0 - - - - - - 266 - {{209, 48}, {140, 26}} - - YES - - 343014976 - 272630784 - 600 - - - YES - - - 5 - YES - - YES - 384 - 480 - 600 - 768 - Maximum - - - - - 274 - {13, 105} - - - YES - - YES - - - 10 - 10 - 1000 - - 75628032 - 0 - - - - - - 3 - MC4zMzMzMzI5OQA - - - - - 1412562496 - 1024 - 600 - - - YES - - - - 3 - YES - - - - 3 - 2 - - - 19 - tableViewAction: - -765427712 - - - - 1 - 15 - 0 - YES - 0 - - - - - - 268 - {{118, 136}, {86, 19}} - - YES - - 67239424 - 71303168 - Video Type: - - - - - - - - - 268 - {{112, 108}, {92, 19}} - - YES - - 67239424 - 71303168 - Refresh Rate: - - - - - - - - {{2, 2}, {518, 177}} - - - - {{6, 155}, {522, 194}} - - {0, 0} - - 67239424 - 0 - Video Settings - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - - 266 - - YES - - - 256 - - YES - - - 264 - {{15, 96}, {172, 18}} - - YES - - 67239424 - 0 - Disable Audio Output - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 266 - {{118, 59}, {379, 22}} - - YES - - -1804468671 - 272630784 - /dev/dsp - - - YES - - - - - - - 266 - {{118, 29}, {379, 22}} - - YES - - -1804468671 - 272630784 - /dev/mixer - - - YES - - - - - - - 264 - {{14, 61}, {99, 17}} - - YES - - 67239424 - 71303168 - Output Device: - - - - - - - - - 264 - {{14, 31}, {99, 17}} - - YES - - 67239424 - 71303168 - Mixer Device: - - - - - - - - {{2, 2}, {518, 134}} - - - - {{6, 0}, {522, 151}} - - {0, 0} - - 67239424 - 0 - Audio Settings - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - {{10, 33}, {534, 349}} - - Audio / Video - - - - - Item 4 - - - 256 - - YES - - - 266 - - YES - - - 256 - - YES - - - 256 - {{13, 75}, {130, 17}} - - YES - - 70385217 - 71304192 - Modem Port Device: - - - - - - - - - 256 - {{18, 43}, {125, 17}} - - YES - - 70385217 - 71304192 - Printer Port Device: - - - - - - - - - 256 - {{18, 13}, {126, 17}} - - YES - - 70385217 - 71304192 - Ethernet Interface: - - - - - - - - - 266 - {{146, 73}, {351, 22}} - - YES - - -1804468671 - 4195328 - - - - YES - - - - - - - 266 - {{146, 41}, {351, 22}} - - YES - - -1804468671 - 4195328 - - - - YES - - - - - - - 266 - {{146, 10}, {351, 22}} - - YES - - -1804468671 - 4195328 - slirp - - - YES - - - - - - {{2, 2}, {518, 106}} - - - - {{6, 4}, {522, 123}} - - {0, 0} - - 67239424 - 0 - Serial/Network - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - - 266 - - YES - - - 256 - - YES - - - 256 - {{15, 51}, {150, 18}} - - YES - - -2080244224 - 0 - Enable JIT Compiler - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{15, 11}, {333, 18}} - - YES - - 67239424 - 0 - Enable built-in 68k DR Emulator (EXPERIMENTAL) - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{15, 31}, {236, 18}} - - YES - - 67239424 - 0 - Allow Emulated CPU to Idle - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 265 - {{269, 51}, {220, 18}} - - YES - - 67239424 - 0 - Ignore Illegal Instructions - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 265 - {{269, 31}, {220, 18}} - - YES - - 67239424 - 0 - Ignore Illegal Memory Accesses - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {{2, 2}, {518, 77}} - - - - {{6, 255}, {522, 94}} - - {0, 0} - - 67239424 - 0 - CPU Options - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - - 266 - - YES - - - 256 - - YES - - - 256 - {{22, 70}, {142, 18}} - - YES - - 67239424 - 0 - Use Raw Keycodes: - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 266 - {{170, 69}, {239, 22}} - - YES - - -1804468671 - 272630784 - - - - YES - - - - - - - 256 - {{14, 43}, {151, 17}} - - YES - - 67239424 - 71303168 - Mouse Wheel Function: - - - - - - - - - 256 - {{66, 15}, {99, 17}} - - YES - - 67239424 - 71303168 - Lines to Scroll: - - - - - - - - - 256 - {{170, 13}, {29, 22}} - - YES - - -1804468671 - 272630784 - 3 - - - YES - - - - - - - 256 - {{167, 37}, {163, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - - - - - 400 - 75 - - - Page Up/Down - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - YES - - - - Cursor Up/Down - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 3 - YES - YES - 1 - - - - - 256 - {{204, 10}, {19, 27}} - - YES - - 917024 - 0 - - 59 - 1 - YES - YES - - - - - 289 - {{411, 63}, {96, 32}} - - YES - - 67239424 - 134217728 - Browse... - - - -2038284033 - 129 - - - 200 - 25 - - - - {{2, 2}, {518, 103}} - - - - {{6, 131}, {522, 120}} - - {0, 0} - - 67239424 - 0 - Mouse/Keyboard - - - - 3 - MCAwLjgwMDAwMDAxAA - - - - 3 - 0 - 2 - NO - - - {{10, 33}, {534, 349}} - - Miscellaneous - - - - - - - 0 - YES - YES - - YES - - - - - - 289 - {{374, 20}, {96, 32}} - - YES - - 67239424 - 134217728 - Cancel - - - -2038284033 - 129 - - - 200 - 25 - - - - - 289 - {{470, 20}, {96, 32}} - - YES - - 67239424 - 134217728 - Save - - - -2038284033 - 129 - - - 200 - 25 - - - - {580, 460} - - - {{0, 0}, {1440, 878}} - {580, 482} - {1.79769e+308, 1.79769e+308} - - - - 268 - - YES - - - 268 - {{18, 18}, {85, 18}} - - YES - - 67239424 - 0 - Is CDROM - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {121, 54} - - NSView - - - - - YES - - - takeIntValueFrom: - - - - 282 - - - - initialFirstResponder - - - - 283 - - - - takeIntValueFrom: - - - - 291 - - - - takeIntValueFrom: - - - - 310 - - - - takeIntValueFrom: - - - - 311 - - - - takeIntValueFrom: - - - - 313 - - - - takeIntValueFrom: - - - - 314 - - - - window - - - - 318 - - - - bootFrom - - - - 319 - - - - disableCdrom - - - - 320 - - - - disableSound - - - - 321 - - - - dontUseCPUWhenIdle - - - - 322 - - - - enable68kDREmulator - - - - 323 - - - - enableJIT - - - - 324 - - - - unixRoot - - - - 325 - - - - romFile - - - - 326 - - - - browseForROMFileClicked: - - - - 327 - - - - addDisk: - - - - 328 - - - - createDisk: - - - - 329 - - - - removeDisk: - - - - 330 - - - - useRawKeyCodesClicked: - - - - 331 - - - - rawKeyCodes - - - - 332 - - - - useRawKeyCodes - - - - 333 - - - - modemPort - - - - 334 - - - - mouseWheel - - - - 335 - - - - printerPort - - - - 336 - - - - ramSize - - - - 337 - - - - ramSizeStepper - - - - 338 - - - - mixDevice - - - - 339 - - - - outDevice - - - - 340 - - - - qdAccel - - - - 341 - - - - height - - - - 342 - - - - width - - - - 343 - - - - videoType - - - - 344 - - - - refreshRate - - - - 345 - - - - scrollLines - - - - 346 - - - - scrollLinesStepper - - - - 347 - - - - ignoreIllegalMemoryAccesses - - - - 348 - - - - ethernetInterface - - - - 349 - - - - diskSaveSizeField - - - - 351 - - - - diskSaveSize - - - - 353 - - - - delegate - - - - 355 - - - - disks - - - - 368 - - - - browseForUnixRootClicked: - - - - 369 - - - - ignoreIllegalInstructions - - - - 372 - - - - saveChanges: - - - - 373 - - - - cancelEdit: - - - - 374 - - - - browseForKeyCodesFileClicked: - - - - 378 - - - - browseRawKeyCodesButton - - - - 379 - - - - isCDROM - - - - 383 - - - - isCDROMcheckbox - - - - 384 - - - - - YES - - 0 - - YES - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 141 - - - YES - - - - - - DiskSize - - - 142 - - - YES - - - - PrefsWindow - - - 143 - - - YES - - - - - - - - 144 - - - YES - - - - - - - - 145 - - - YES - - - - - - 147 - - - YES - - - - - - 148 - - - YES - - - - - - - 157 - - - YES - - - - - - - - - - - - - - 230 - - - YES - - - - - - - - - - - - - - - - - - 231 - - - YES - - - - - - 232 - - - YES - - - - - - 233 - - - YES - - - - - - 234 - - - YES - - - - - - 235 - - - YES - - - - - - 236 - - - YES - - - - - - 237 - - - YES - - - - - - 238 - - - YES - - - - - - 239 - - - YES - - - - - - 240 - - - YES - - - - - - - - - 241 - - - YES - - - - - - 242 - - - YES - - - - - - 243 - - - - - 244 - - - - - 245 - - - YES - - - - - - 246 - - - YES - - - - - - 247 - - - YES - - - - - - 248 - - - YES - - - - - - - - - 249 - - - - - 250 - - - - - 251 - - - YES - - - - - - - 252 - - - YES - - - - - - 253 - - - - - 254 - - - - - 255 - - - - - 256 - - - - - 257 - - - - - 258 - - - - - 259 - - - - - 260 - - - - - 261 - - - - - 262 - - - - - 263 - - - - - 264 - - - - - 265 - - - - - 266 - - - YES - - - - - - 267 - - - YES - - - - - - 268 - - - YES - - - - - - 269 - - - - - 270 - - - - - 271 - - - - - 358 - - - YES - - - - - - 359 - - - YES - - - - - - - - 360 - - - YES - - - - - - 361 - - - - - 362 - - - YES - - - - - - 363 - - - - - 364 - - - YES - - - - - - 365 - - - - - 195 - - - YES - - - - - - - - - - 192 - - - YES - - - - - - 370 - - - YES - - - - - - 190 - - - YES - - - - - - 193 - - - YES - - - - - - 191 - - - YES - - - - - - 228 - - - - - 226 - - - - - 229 - - - - - 371 - - - - - 227 - - - - - 194 - - - YES - - - - - - - - - - - 214 - - - YES - - - - - - 225 - - - - - 215 - - - YES - - - - - - 224 - - - - - 216 - - - YES - - - - - - 223 - - - - - 217 - - - YES - - - - - - 222 - - - - - 218 - - - YES - - - - - - 221 - - - - - 219 - - - YES - - - - - - 220 - - - - - 203 - - - YES - - - - - - - - - - - - - 196 - - - YES - - - - - - 197 - - - YES - - - - - - 198 - - - YES - - - - - - 199 - - - YES - - - - - - 200 - - - YES - - - - - - 201 - - - YES - - - - - - 202 - - - YES - - - - - - 204 - - - - - 205 - - - YES - - - - - - 206 - - - YES - - - - - - - 207 - - - - - 208 - - - - - 209 - - - - - 210 - - - - - 211 - - - - - 212 - - - - - 213 - - - - - 150 - - - YES - - - - - - - - - - 158 - - - YES - - - - - - 161 - - - YES - - - - - - 164 - - - YES - - - - - - 159 - - - YES - - - - - - 160 - - - YES - - - - - - 169 - - - - - 170 - - - - - 165 - - - - - 168 - - - - - 171 - - - - - 153 - - - YES - - - - - - 182 - - - - - 151 - - - YES - - - - - - 184 - - - YES - - - - - - 185 - - - YES - - - - - - - 187 - - - - - 186 - - - - - 156 - - - YES - - - - - - 172 - - - YES - - - - - - 173 - - - YES - - - - - - - - - - - - 179 - - - - - 178 - - - - - 177 - - - - - 176 - - - - - 175 - - - - - 174 - - - - - 152 - - - YES - - - - - - 183 - - - - - 162 - - - YES - - - - - - 167 - - - - - 154 - - - YES - - - - - - 181 - - - - - 149 - - - YES - - - - - - 188 - - - - - 155 - - - YES - - - - - - 180 - - - - - 163 - - - YES - - - - - - 166 - - - - - 375 - - - - - 376 - - - YES - - - - - - 377 - - - - - 380 - - - YES - - - - IsCDROM - - - 381 - - - YES - - - - - - 382 - - - - - 388 - - - YES - - - - - - 390 - - - - - 391 - - - - - - - YES - - YES - -3.IBPluginDependency - 141.IBEditorWindowLastContentRect - 141.IBPluginDependency - 141.ImportedFromIB2 - 142.IBEditorWindowLastContentRect - 142.IBPluginDependency - 142.IBWindowTemplateEditedContentRect - 142.ImportedFromIB2 - 142.NSWindowTemplate.visibleAtLaunch - 142.windowTemplate.hasMinSize - 142.windowTemplate.minSize - 143.IBPluginDependency - 143.ImportedFromIB2 - 144.IBPluginDependency - 144.ImportedFromIB2 - 145.IBPluginDependency - 145.ImportedFromIB2 - 147.IBPluginDependency - 147.ImportedFromIB2 - 148.IBPluginDependency - 148.ImportedFromIB2 - 149.IBPluginDependency - 149.ImportedFromIB2 - 150.IBPluginDependency - 150.ImportedFromIB2 - 151.IBPluginDependency - 151.ImportedFromIB2 - 152.IBPluginDependency - 152.ImportedFromIB2 - 153.IBPluginDependency - 153.ImportedFromIB2 - 154.IBPluginDependency - 154.ImportedFromIB2 - 155.IBPluginDependency - 155.ImportedFromIB2 - 156.IBPluginDependency - 156.ImportedFromIB2 - 157.IBPluginDependency - 157.ImportedFromIB2 - 158.IBPluginDependency - 158.ImportedFromIB2 - 159.IBPluginDependency - 159.ImportedFromIB2 - 160.IBPluginDependency - 160.ImportedFromIB2 - 161.IBPluginDependency - 161.ImportedFromIB2 - 162.IBPluginDependency - 162.ImportedFromIB2 - 163.IBPluginDependency - 163.ImportedFromIB2 - 164.IBPluginDependency - 164.ImportedFromIB2 - 165.IBPluginDependency - 166.IBPluginDependency - 167.IBPluginDependency - 168.IBPluginDependency - 169.IBPluginDependency - 170.IBPluginDependency - 171.IBPluginDependency - 172.IBPluginDependency - 173.IBEditorWindowLastContentRect - 173.IBPluginDependency - 173.ImportedFromIB2 - 174.IBPluginDependency - 174.ImportedFromIB2 - 175.IBPluginDependency - 175.ImportedFromIB2 - 176.IBPluginDependency - 176.ImportedFromIB2 - 177.IBPluginDependency - 177.ImportedFromIB2 - 178.IBPluginDependency - 178.ImportedFromIB2 - 179.IBPluginDependency - 179.ImportedFromIB2 - 180.IBPluginDependency - 181.IBPluginDependency - 182.IBPluginDependency - 183.IBPluginDependency - 184.IBPluginDependency - 185.IBEditorWindowLastContentRect - 185.IBPluginDependency - 185.ImportedFromIB2 - 186.IBPluginDependency - 186.ImportedFromIB2 - 187.IBPluginDependency - 187.ImportedFromIB2 - 188.IBPluginDependency - 190.IBPluginDependency - 190.ImportedFromIB2 - 191.IBPluginDependency - 191.ImportedFromIB2 - 192.IBPluginDependency - 192.ImportedFromIB2 - 193.IBPluginDependency - 193.ImportedFromIB2 - 194.IBPluginDependency - 194.ImportedFromIB2 - 195.IBPluginDependency - 195.ImportedFromIB2 - 196.IBPluginDependency - 196.ImportedFromIB2 - 197.IBPluginDependency - 197.ImportedFromIB2 - 198.IBPluginDependency - 198.ImportedFromIB2 - 199.IBPluginDependency - 199.ImportedFromIB2 - 200.IBPluginDependency - 200.ImportedFromIB2 - 201.IBPluginDependency - 201.ImportedFromIB2 - 202.IBPluginDependency - 202.ImportedFromIB2 - 203.IBPluginDependency - 203.ImportedFromIB2 - 204.IBPluginDependency - 205.IBPluginDependency - 206.IBPluginDependency - 206.ImportedFromIB2 - 207.IBPluginDependency - 207.ImportedFromIB2 - 208.IBPluginDependency - 208.ImportedFromIB2 - 209.IBPluginDependency - 210.IBPluginDependency - 211.IBPluginDependency - 212.IBPluginDependency - 213.IBPluginDependency - 214.IBPluginDependency - 214.ImportedFromIB2 - 215.IBPluginDependency - 215.ImportedFromIB2 - 216.IBPluginDependency - 216.ImportedFromIB2 - 217.IBPluginDependency - 217.ImportedFromIB2 - 218.IBPluginDependency - 218.ImportedFromIB2 - 219.IBPluginDependency - 219.ImportedFromIB2 - 220.IBPluginDependency - 221.IBPluginDependency - 222.IBPluginDependency - 223.IBPluginDependency - 224.IBPluginDependency - 225.IBPluginDependency - 226.IBPluginDependency - 227.IBPluginDependency - 228.IBPluginDependency - 229.IBPluginDependency - 230.IBPluginDependency - 230.ImportedFromIB2 - 231.IBPluginDependency - 231.ImportedFromIB2 - 232.IBPluginDependency - 232.ImportedFromIB2 - 233.IBPluginDependency - 233.ImportedFromIB2 - 234.IBPluginDependency - 234.ImportedFromIB2 - 235.IBPluginDependency - 235.ImportedFromIB2 - 236.IBPluginDependency - 236.ImportedFromIB2 - 237.IBPluginDependency - 237.ImportedFromIB2 - 238.IBPluginDependency - 238.ImportedFromIB2 - 239.IBPluginDependency - 239.ImportedFromIB2 - 240.IBPluginDependency - 240.ImportedFromIB2 - 241.IBPluginDependency - 241.ImportedFromIB2 - 242.IBPluginDependency - 242.ImportedFromIB2 - 243.IBPluginDependency - 244.IBPluginDependency - 245.IBPluginDependency - 245.ImportedFromIB2 - 246.IBPluginDependency - 246.ImportedFromIB2 - 247.IBPluginDependency - 247.ImportedFromIB2 - 248.IBPluginDependency - 248.ImportedFromIB2 - 249.IBPluginDependency - 249.IBShouldRemoveOnLegacySave - 250.IBPluginDependency - 250.IBShouldRemoveOnLegacySave - 251.IBPluginDependency - 251.ImportedFromIB2 - 252.IBPluginDependency - 252.ImportedFromIB2 - 253.IBPluginDependency - 253.IBShouldRemoveOnLegacySave - 254.IBPluginDependency - 255.IBPluginDependency - 256.IBPluginDependency - 257.IBPluginDependency - 258.IBPluginDependency - 259.IBPluginDependency - 260.IBPluginDependency - 261.IBPluginDependency - 262.IBPluginDependency - 263.IBPluginDependency - 264.IBPluginDependency - 265.IBPluginDependency - 266.IBPluginDependency - 266.ImportedFromIB2 - 267.IBPluginDependency - 267.ImportedFromIB2 - 268.IBPluginDependency - 268.ImportedFromIB2 - 269.IBPluginDependency - 270.IBPluginDependency - 271.IBPluginDependency - 358.IBPluginDependency - 359.IBPluginDependency - 360.IBPluginDependency - 361.IBPluginDependency - 362.IBPluginDependency - 363.IBPluginDependency - 364.IBPluginDependency - 364.ImportedFromIB2 - 365.IBPluginDependency - 370.IBPluginDependency - 370.ImportedFromIB2 - 371.IBPluginDependency - 375.IBPluginDependency - 375.ImportedFromIB2 - 376.IBPluginDependency - 377.IBPluginDependency - 380.IBEditorWindowLastContentRect - 380.IBPluginDependency - 381.IBPluginDependency - 382.IBPluginDependency - 388.IBPluginDependency - 390.IBPluginDependency - 391.IBPluginDependency - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - {{899, 941}, {229, 62}} - com.apple.InterfaceBuilder.CocoaPlugin - - {{739, 322}, {580, 460}} - com.apple.InterfaceBuilder.CocoaPlugin - {{739, 322}, {580, 460}} - - - - {580, 460} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{601, 517}, {143, 143}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{196, 720}, {138, 43}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{705, 948}, {121, 54}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 391 - - - - YES - - VMSettingsController - NSWindowController - - YES - - YES - addDisk: - browseForKeyCodesFileClicked: - browseForROMFileClicked: - browseForUnixRootClicked: - cancelEdit: - createDisk: - removeDisk: - saveChanges: - useRawKeyCodesClicked: - - - YES - id - id - id - id - id - id - id - id - id - - - - YES - - YES - addDisk: - browseForKeyCodesFileClicked: - browseForROMFileClicked: - browseForUnixRootClicked: - cancelEdit: - createDisk: - removeDisk: - saveChanges: - useRawKeyCodesClicked: - - - YES - - addDisk: - id - - - browseForKeyCodesFileClicked: - id - - - browseForROMFileClicked: - id - - - browseForUnixRootClicked: - id - - - cancelEdit: - id - - - createDisk: - id - - - removeDisk: - id - - - saveChanges: - id - - - useRawKeyCodesClicked: - id - - - - - YES - - YES - bootFrom - browseRawKeyCodesButton - disableCdrom - disableSound - diskSaveSize - diskSaveSizeField - disks - dontUseCPUWhenIdle - enable68kDREmulator - enableJIT - ethernetInterface - height - ignoreIllegalInstructions - ignoreIllegalMemoryAccesses - isCDROM - isCDROMcheckbox - mixDevice - modemPort - mouseWheel - outDevice - printerPort - qdAccel - ramSize - ramSizeStepper - rawKeyCodes - refreshRate - romFile - scrollLines - scrollLinesStepper - unixRoot - useRawKeyCodes - videoType - width - - - YES - NSComboBox - NSButton - NSButton - NSButton - NSView - NSTextField - NSTableView - NSButton - NSButton - NSButton - NSTextField - NSComboBox - NSButton - NSButton - NSView - NSButton - NSTextField - NSTextField - NSPopUpButton - NSTextField - NSTextField - NSButton - NSTextField - NSStepper - NSTextField - NSPopUpButton - NSTextField - NSTextField - NSStepper - NSTextField - NSButton - NSPopUpButton - NSComboBox - - - - YES - - YES - bootFrom - browseRawKeyCodesButton - disableCdrom - disableSound - diskSaveSize - diskSaveSizeField - disks - dontUseCPUWhenIdle - enable68kDREmulator - enableJIT - ethernetInterface - height - ignoreIllegalInstructions - ignoreIllegalMemoryAccesses - isCDROM - isCDROMcheckbox - mixDevice - modemPort - mouseWheel - outDevice - printerPort - qdAccel - ramSize - ramSizeStepper - rawKeyCodes - refreshRate - romFile - scrollLines - scrollLinesStepper - unixRoot - useRawKeyCodes - videoType - width - - - YES - - bootFrom - NSComboBox - - - browseRawKeyCodesButton - NSButton - - - disableCdrom - NSButton - - - disableSound - NSButton - - - diskSaveSize - NSView - - - diskSaveSizeField - NSTextField - - - disks - NSTableView - - - dontUseCPUWhenIdle - NSButton - - - enable68kDREmulator - NSButton - - - enableJIT - NSButton - - - ethernetInterface - NSTextField - - - height - NSComboBox - - - ignoreIllegalInstructions - NSButton - - - ignoreIllegalMemoryAccesses - NSButton - - - isCDROM - NSView - - - isCDROMcheckbox - NSButton - - - mixDevice - NSTextField - - - modemPort - NSTextField - - - mouseWheel - NSPopUpButton - - - outDevice - NSTextField - - - printerPort - NSTextField - - - qdAccel - NSButton - - - ramSize - NSTextField - - - ramSizeStepper - NSStepper - - - rawKeyCodes - NSTextField - - - refreshRate - NSPopUpButton - - - romFile - NSTextField - - - scrollLines - NSTextField - - - scrollLinesStepper - NSStepper - - - unixRoot - NSTextField - - - useRawKeyCodes - NSButton - - - videoType - NSPopUpButton - - - width - NSComboBox - - - - - IBProjectSource - Launcher/VMSettingsController.h - - - - - 0 - IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES - ../../SheepShaver.xcodeproj - 3 - - YES - - YES - NSMenuCheckmark - NSMenuMixedState - NSSwitch - - - YES - {9, 8} - {7, 2} - {15, 15} - - - - diff --git a/SheepShaver/src/MacOSX/Launcher/English.lproj/VMSettingsWindow.nib/keyedobjects.nib b/SheepShaver/src/MacOSX/Launcher/English.lproj/VMSettingsWindow.nib/keyedobjects.nib deleted file mode 100755 index b27171c4a97d2a2cd2d63e32abc20b9d5d0c5c32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43067 zcmbq+2YeL8_xP0E+j6u^?4N zrHUwu9Z_sx0R#aR>X=$G# zj0mDgLNaohEzFj~noRapR2G$$4r@|2?iOD`Rpsy|`4t5dir{i?ld7`vaD?Zq*kIC6 zk%Clo6-q}Lr~~SVu0>tZ6f_IniynkK525GLHnbDHirzr)qYu!B=o9ogI)o0Rqv$v~ zfqp;=_QHqZNOTc5!&l*S+zxlb*Ww;H8|UC$JQR<_V{id3#N+V8TeLg;XCm? z_LR*K8WOkxpE=8(DMZnB1K zCC`&r$Zqm3`G9;%ek4DUljIL_fn206s?ad%rI9p>CefDkN}562(hjsE;6kCj=nb?V z9Y}}KvGgWdOiO4ft)w&Pt#lrpPZ!Wd^g;R%T}#)|C+V~FdHOPag}y^~(|75I^mF

X^=En%8`aiH%a+Y zsZ=JFOV!Z&HtBY0fpoX@kn}M8S}r{zJt3`>)=3+rjnYff4(Vm-b?IH{J?T^FGwBQI zYv~*5oQz~DN6GPWf}A3!%1z{^ax=N5+*(eTuaU2nuampVz2zI^e)2$hm^@rAkPBs> ze2ZKmSIRTx+vM5u0{L$FA^Bl>xx7MtN`6}2DnBo8lXu8($#2Ua${)#}%7^7I{{k}+_l2>v}?WV8P_J)i>{YkZ@Auc?RM>T?Q$I3-bOuC!8GD_1FLN;{>C(pBlEbXWQ)1C>F_Smh>Vf>Na1 zqD(}JV!?+icPjTP4=4{Qk0@)Eb;^^PB^w zx>bEueNBB`eM|jN{Yd>p{Z#!-J)j;`52=UMFV*Af3H5vRC-o2YPxYdDNmDgV3)dpF zL@i0XQoBlPuVraHwBA}Dt*S7{MrdO+pLVlWtWDBx)hz99?S5^k_L%m#woZFe z+oWyQUeb1GZ)tC9A7~$H`?UkwLG26eEA4CTgmy~%Lp!fax~v3Rpfqkg^KQy-}3>Z5g^ezRVtm+MpYY5MK@Y<+=#x4u+=KwqXms6Vc+ z&{yft>6`VJ^d0)k`kVS&`aAkQ{d4^*{RjO={j~mveqO)ecDWU|>ek%MZMq}fQAlw| zyW`!B-A&x-?hJQl_ciXm?i=80KlhF9{_bq|AopPRQ1>wRX!jU*fxFN>!Cm4mbyvEl zx@Wp?ch7d;<(}tW=)Tu|zk8|sVfW+i)$TR!r`_w_8{M1S+uSdN4G0??mJ>E4>=(}* zBgIHH8W~p@jg2NoQ=^&D+-PC6G_EvS8Lf@0j5fyAMw*dsWEgFYOrxFA-pDdK7#)pH zMrY$1<67f7<9efu(bec?bT@h!J&j&QZ=;XV*SNvxXWVG?H?oZZ#z13`G1$m4a*ZKI zo-x!IW(+q*7$c2Q#%N=VG1j=r$T!9r1xBIaGj2A<8xxEo;}&D0QEZeLrAC=iZcH*N zj7p=*s5T}WQ;ey`G-J9k!?@L$Y20SaGAx4|w;QvKJB&MxImTS$E@PfC-&kPWZQNrl zH10JP8TT2BjU~qY#!}+}W0~=w@sRPbvD|pXc+_~zc-&ZFJYlRfRvD{}HO5+Fo$;jc zl<~B&-gw4%)_Bg?U~Dut8JmqQ##ZBbW4p1#JD26KTsDN|v7u}j8_q_sk!%zj&Bm~? z>?W4a#<2oc$b9T(Hl9sjMeG(fkrlHNR?5m)Ih({PSS71s)oe1G!ltrmY&x64Ze=ss zZEO~^7-zS$+3XH>C!53Ovb)$kHlHnEce8ugLUu1(#O`B@*%Ed?Tgo0_%h-eLA@(p^ z&K_Zpvd7rtYz2FQtz@g%YPN>0W$W0J>?!s%ThE?h&$8#(2DXuHVw>3(wv|24wy_u3 zcJ?BBiS1x7vsc(o_9}agz0TfXZ?d=8+iVwmhwWzXviH~?_CEW7eaJpyAG5t|ANz!T z%06SCv;FJ?AwI zeq+D0)9erSCp*LbVt=!<>>qZHoo5%=MRv(VCN_ylP05r^m#LVlshPUzHp5JhX_#J< znWhf=oRMZGvff}PGs3~fOnxht|CAt!|LaoQLnCzUc1qHs! z%A#>a#YI)q1{4)m_VZ1v9LrdCPF@jQF7^#ADlIIVQaL(1XMkfzI1RknIo*r%D=U4K zdHKcFzRHo=IlU_KOMFwxDkkP-=L{|@s~XGVLiF!6hwl83i|$52=Pm#%8LS4nk5kI2i_=d`Jdab^QaQPWlZl*uY#~mH_W}CbpsP_D z;J}`g=**HVI+jJ|_0REDRTY(vuY|#?D$0tBeHHsqTa<~~q4p!3nU+HHVa``y$F;f!$|x*ky5zq%?P z77_qig|0(gP}Y#_9Qffp*$s8Kk~Xlms0ZqadZFH^59*6g5-s6Wa^1JFP;2n|L# zC>ISud1xpahK8dNXe1hiMx!xkEV>Ehqj9JJ6(S$H8I4C1P!YNXO+>}01eKyPRE{R0 z3RH=zP&JxtX;vqzhc(C=W>r~}t!36@)@ti%Ym>Fx`q28+I%<7oeP{j5vBa^?v6tg0 zjuSXe<+v%w-8t^VaW=;}91r7o496uL-_A)NPHy1jMotEBGKiDGoaAtl%Sj$5!#Eki z$tX@nb25gLn>ZQAN#Un}v#DqrnvQ0mThUCEIy5`y#{6-n$dpd%p>Swv>ZKx9z~C#$I%M(1X_t!q19*&473)lLrYyr~{JmM>@^0T>Mmpqsibe}7b8u$(v>t0q|Rsq-sq?VUe zRKcS?e8s-;`BlEL%!D5m`BN&pmnh|^1=cq zTd@|ibj@mSMdWlXohIny1+*Q#h+aZF(97r*SWUs(@SmKb={{Jko9#JU;g;FB%azFf zXG)QyZmcdSD$MU)kq?XNaN=v|b$Ck1oR#P`l=T^U6Z(D&y^VIEchGM1E_x5`5yB0y zSzI<=3?h&!W+}c4{E6>5<@p6ZAT4JGkyeZq#avc&Ue2^iK=oJ_Q3bfEH_=aEptsRS zFvwoC51t)5p{UAd#W30}9XYUliarbUxe|Ta5V(T?+!vM@EzXJu5mewvvfRKr1dnjU zis_aH{R*Mf4Si)Ltpo!42C$o$*S*J8g9r3?hWr+N2ZGKon7UR}p^{Q?yEEA+VZ7qtoaQV8=hv8T1!0#^1n(|Dbc|Ji34` zqD$b5A~X*ZOtFMz?1Jwqnu~Sp#$nK6E-YPce#LlS6=2!sQ?Z`5z5>)%my~v`t}3hW zRTfPL$(>U*tr+g5*km<+ytraZh5q@K6MMn>l$G9C24p;zH4dUvpg_B6kT~)86PumW z7pNS>N^!ARPw20YuW0-P0m|UADb9Bw?c9KnNW9Fz_NYJ^f&(3hpoiWSMTItXzzn0;fXUZUsfOESR7lX3TomLL&q8QXHNTE~{hcj%YFl4p1+F3^9 zE)Jn1t5M@FZJqBCm*C&Nn=Hh<@I<<1Wj5}jI=8GVtQ2k7jP$mxQ!_JW`Y8j4TS-sg z2&?fII0{FD>Ed)7JbaRofLa>CuhGw+_0gz@j zZQSKvXNHZtH1SWNNzK>&ATu8Yc^Pg?%eA;UP+AMz679jQaO-f1Uqn_j>q;xyYGJj6 zx#BkXYMchE*`~6p0!Fu*540HoXW+KB91ZAZ`|c{ZoN2539Q$`2`GY&)j*g&d;XuV$ z5aZ!%teAdjZQ6=|867)1oQ+u`E_Y!!_1o2{50X>Hme5Q$X*{p5_<$r-5#-(p+R-OEbG zmDvLd6}A>n#KpKogrx-j!P2gKAGo-tEl`f%ZUn6R^Z9BcJVilf=XW5{@y_%~*HW+GkT7@6R%kd-lQT!Nw9It@?t;DnOYP1or z#p`S-InY;8R90A2V2jns`ND4OR$Wz9R_Zr_B7`6X84q@(PpqG?X>6_nAExJ|>LPdq zE;)vjzbmj`@~6Ra1@)7`;=(0-5!u3Z&h1?;g$t2tb%Fm~518s|F>qn|@NN|#v3+gY zwDF6U_4pZBXQv-Q4y*Bc{49R%-&kTJ-URx>d1MXV7+85w9pmiI2j@=#$h(&n`YN49 z!K?Q?-e#}fK&xj+6B)mRccA(B6}&*0$ePv5>g`yz-GpTe{61qw+m2~qlxB#9NzdqL zTdFgU1g{K!Q>+bs3uKM6I&b4$_#KeFVs+lbd+;{=fxSW>xxyf}c|ziv?I7e~Q}R&+zAXKdcb&pRNCe zVP@TE^|NjO6=HV`ILw(+R8=s+VTnWdu*2TAKNomxB|e0*glaf~kK$v%QTC&DX9KM4 zdR=^jkAqbgSQ@*fqv}`UZ(uyyf~8XK&{YBQ?9@$hVF89pOJ zh~)Odc89nXxsA*MTsSc*VUesRw>hSa;KhkK`ICKOkRWM9W|JhF7ps9<2^gHg?Q9b> zxbZwP-){VXHN_%FS!_ceklaHS*7||uUcV=J1{nM=^fy^V?jwuI67T}|0GTZ%58%CI z8F>&bBoCA2H|cL3UH+kWPL@UjAdD-eM&-V0t8CIAB|loyCi*?QdXKou92i`zgM&fTsh zRU-P`C(ssFeku#+c$+nq;}fS`pMx)eT+aZ;x~3vze;$PY!iVFhIo@oC=`z~` ztJ!KH9Sl^#@($DeOnwqHw_&2mXziI+dV?76$T%w3#+>%l%QCT>^ zT}%~ObHE3lXU($I2zTd+wo(Y*&QP@EHTKdqDEauww|D(;WavKz6eHn zC)lpP@Jeh}ali}sq-$w3je*HJ{wR2(jU4c%_$6cOL!rVCG#SmMsRBo|F>OMdqP?^k zZI0%`iubMTSy*H{dz!V_#@fQhy-!}cbPT3a6C<$hY20O?GdFESQDyfY5cVo)fH~TV zwx(D4F_&J0xqJPXTQtOeuKx7f!}RyqZs~ni^hjs&_Qe0yT&A69XL?P*?!qfzZnn8h zdj{EE#WmJ&7nqsf?y|{`_NIM+!fU+JHMDO)$pv2?A_RM7kT9qHX|^rQAGIC~VTaPe zG>7KWA$S4J)vSlDsyA2gg!- zmQ)vmUsssgec+JPsm{?^!9tsoHbTVLK zs)LCY))O_DsF_~6Jw1r-IMe(0<(^4zqq73bO=r_d{^hh&GrNtGz(^fe zT~u6kRZ(eb`wkORdkpr^x~w9#MbBXadk*f~zh`!C*Be`ccjB`%9?-1EUl)6yojvpPcHkn4h5h%LKTMa?M`~uif-dyWe2tj7 zZ9U%s4oI-;_awkoGy4et>~H9sn+m~@au8k>!<`AjrQm5jP1oDg+Gwp0HLVSFBi%$d zlV)_2W<6^?XFX$L9UOpX>XP<0Anon+MfmLCB-SQv%_eP)6SwUer)LU+wpBvgb`ZX} zjH^I*(pTwgbbTmS0SQ-O1Hc(@6^2w67gdylGWJzXfFOmh%8p~)47r8i8SbI)+cSK} z+8kT~P4{WmR_l3di~B+PSIpOc4k8ujCXxN{^wZ=vN@6zoGBb6C&6Mu-eHf>jgWl<4@{r1JGZ#lRBH7 zq)z*^G{1_ZC#|G4^c4LK`Z!Jhu(n$-THCCbtQ|RRJ7nf$c1X*~YTscf#FC3js!RUQ z*$BYRIeH$Qr#0CKx>v#yk*Fj|GTkdIP)U{7V(`eh>QQWQObQ>9obPKp;1b}3P_-Uei) zS#Jc{0Zkk=W;Ll%ZuRuPl#DJ)DNX=fYU~8S-vkvV0^o0nCbcHnOClq;l4d&)6&%W`oj85bkYrm{M*BX+-ZK!C|HwSEZ&=V9qfJWo0*9TS<2U#*iOvjM7+Sl2j!wucZ09YL5gM1imwu3b1i8Ch`U&loewKcbeuYV#l75p8 zNT)&R{E0S7e}S%?i_S~`p!0V4V_=2vW?w~xudrv~c#&D{?<=hqwHsja*8UJ_CrAi) zEe56(fjLM>iFS5A1nk~Q@qkDNiHqP!+adSLoGQB{1In}@t6w%{U|D66sH|cA98;|8 z#V+A4NNfm~v5WPabqdh*yJnrXn28r@8pjZL4=TZsE=rf`)LJm+S1~dH6>|vvDNC{} zeJ8u1b|730eeTB0mtvw*iI-%Yafl z*bc}Dw1GMGF9iuzT2ug;ckl)K19=wOt>C%bBFK4JXTuSL(A#P2Pgu);tS;fRAT4hF zW&QDq91Q^Ja*P}+i%4?-!eMYExZn;YJUf<{tXSxT zu-r%P3yT}n)mphvZ4zumNm+HJ4}3abaS&_E{bk#=9xoahX36mD=YQAA@;&lGxkf9?OJu)R zmTj#Z%75fILI77|)Fk;m$U)Ub1rtRbnr+X38)=sm4xLme4468U^r-xpGs}36qeEs; z<(2X(G+$mrn%Nmtj$=5Eb#kcVoE$17x7!Lg%AZoYyq_qqm!FZJl^+YWFe0VIah!l6 zurh<&XF}qoq+Uc{-Y&oBfSkf{VrYfuaO>pkdru0c0e9q3vxSQDcSlh1JZ{X z;N62S;3SP|QbyVGE>Kn%<=yg&@_X_gk|%#)uY*-5*#mGi?y|`7RvLE!AuRrhWRJf< zX^ejs{xnT6C-0T_Ig@F^p{$@`{ek?sydTe#4+1C811h_M&4_!O;FF|Kvd1jpJsapgk#{0-pF?I%e}k zbBK1&wM|H$WLFe2oOwmC7^MWo;G3YQEucpF`c-?VV5$Usj*B_xEy zn{nI|@pYFU;MyVW|8Fyx=qe5xpaKS{;<)SO z2k0`i$F$P?lA?l8#5fWx^$K6*gu!4|2T29jbk__=D)i>KM@WI}n&q<4eAn$YI;1DZ zy@Ws}Ajj-F9MB=6N<7QGY39h?b^MKc8{F@-_Q6tEPf=>`g0{M&XUH7|| zI^Y7e^bH}zTo1V(#`9c{_(kpw9QU(bBS+){py@*7rrR!@NKRkI=X5>cTIpKlT6#G^ zIlfVh9}u~N+K#NWYte5kD)j~DFKodjei3mmgdnfx=xogr0M~g66t5xLzZ9^~)Jx=*C_8TYk+3epe8%4b__K zZPzXb=Aj(th9-&kTzh~dKBysyAsi|zLy$x}C;a?xB=L#sQy__5m&3G>>bW(D9#&mi zG*#>n3MS#Bu44|oqdA6}od#uquH&u~faCA%GC+<&42*Pe426IWj=_Y;a!{Q4zZ4_6 zes=xh`ZW-NasBQ(=0spze}#&`a6C%DRb%Iw;Pa+JU0fkz0*J%v62|H+SKLY%UZEJ$Z>|f9 ziRLO1XrmHkD{ng%5Yj8>c${?#pys#$jGw|<&)lz`l>|`FhaJzGTvy*GRFafrum{d7 z5wf8Wp`w*0a)bhAz|DRMSSVC(v8 z0iLU3Dw!|^j*ILlK?q3OD_MAN5S-TnoY!+a@$zuqGNKo3$OA6)`AS1UHGFbWp|4ET z(g)Fk(o^Z>&;sYUG!!k|p!5S;=x--hI4^S zt1=T>%mt)yJk>6&m?DxU@Vh2!!tt~kv){HcoqY)ckLf_dR!!oBW2jo0(lB+R%!WX) zatFsVE|WV^<|@N*sxn_$pxiBTC(1(Tca}g~8ppT(U(zSaB6Lx?&q<#sOYQUt$1|P$ z3CFhu==#CB2^3}deLGoIL30DCc@>!G=Ux*z9`y?YbFb7ExsJFs=&shavQj)64poxRpDyeu*!Ti+yIlt`S~AZDBRIkB~LFI( zN-6|+a=~Qg_+Ad%2JkYDUxST+u(XK~2I2TEj(2nXeu#{as;U~AuexiDr$rp!=L9(X z_B8Ce6m^^J?6uDVG6-40shVoI8ljx4Tfr%H5p=W|z;YPXDjqQeY^GFUG<6CEO`@6v z(4^Erb3eyR>q8?FdL3*7DGLHbp`mH2HdC7`=R-mB0AMHp&2UIRr3$OQ(-HM*HLbSp zPEAL5su`lfT5YRlqKj%fwLSSt?Et`af(?lC@m{o0y;i+Wy&l*P_Nxf(2!bFNwn|o( z=T|rdzun3zU^|z%Wyig3`4C7Qh=L;#YZoD1=wiUlH&^a76# zZ2+^S4zyvv<6mH3Enr^-D0W~U-n{|}!^JL_0Qh%Z2K)u;-2nc=8t~V0yv_z6whZ|( z58!7Cx$J-sYw%y-->)uJA5fP8_zwa2%hf?P_>cb!_)iJ&pA_U_7mwu)hRo4qUjX)1 z0DFL_)`Cd|b*bNwAD|TXQBgArrJ|dmR8(kxA&k}M1mVuNKS}efQy+Q|w#ahyqx!rpw(VW(>NfQSvO#?jK0DNxMKvuj5^QNI0Pf>> zBgY%8S&gqh`QC?(u5Z=RF0$o#lc=+`%}={T)d|{)?H{7Fc;=|Fg=L_F?b8jMy>IFp z>YD&g;NlwfjX=d9#Cb%aZher@d36^6v>QI}IY8NVz*P^X&wDf;ZpUBRe@%(yGevwGwfJJJ3GuR z(ztmu0Om9(%C57WR6PO`^C<4Cenlm;)h_1e_!aAFj(1vft%#vc6@O(=Esgq}*b14N z)&`7p@z1}fTm3=(5q4{UfL*Qr;D8c})qhcc1;Ko(Mr*vz@f-EEhR|UUUjfu!UWc7g z|5E=}E{4(?ZwifS8=IiRx`Fyi6-nYyI!wbFLGv}K2Aa1y-c<)0z-5M5YbVQ*ZpTyr z=?!*8Xu9Us!c-axo_9d02jCeqxNHB~EfFDMiqfJ1rda>pHICoq_&ouW*nb#^nq`VC zQVoEdaHv zwKM=ZqXy&;IQ}ps$eDHu;C}(RgVs^&q;&?6ueCvzZIHYF3&!*N3B zIxNvvsEm)rSdZKO6zSRu8>=}OJn z0Tgtp;aK_FIIVzy%(S~E631XuAAr6ygn$c2cYu++NE?q9YelG)HjxtwriHM#L4JMV zmrq(LL?`G$e8#SbJpE-zbE?Le(kkgbwF3-01?|r^SNhm5I6diN3gOGrswl8T9Xv?$* zwK<^}6)d$Q0Y-(;4|t@V8Upczwi1S4?FZr;j*o``!m+?F55!a2)7pA%ZYUs502Ts3 z40VoX2m!@b?RkLW1wRzuar}J{6d<&0R0u^WEIomXkV5Na?G$J$lsi zW%OVt8v$|9DqknN3a*YyOwS5vSTX5#wz*}i!1RuwVe9EW?GU=C9majNBSE_FH=+A} z7rGBTfmCPa0Z%zd3u?#fYr+5GqwnxZn~xxuY4g!9+OIYrU9xiO^3flh0JjF52<>;^ zBVe|i03V$J>ka=PXG?3ef3$NJeycr@)yT{J3DXfQaZo8 z*xs(K=m<%IkQ}4CbVXOSe?l$ISr|94G-I6ov8hf8NJB!=O+6f7iS)yAj^pzUVQ~sU zFAqzc9!M+S+VjFP|kwDdLeIn7DqKkSn+*fZ= zOC$sXkq{z?WQ?;nI0S|0ZR%6VW%bZ#r<1E4a%&*<^-R5;-o94qx93FR#AOxdiJ(Sm zW{~LDJE6t;HK>(-9VZZ?^oxF?`iV#H3JMKM|3~6QoInHvwzD+-54zQR(@kmz0H7b* ztGB~@_5OOcpj#4WJtOFrC_?@VfZ%U@E#2yah5X-SJrfu@&q`XW57me1!=+c{33NRt zVVp2dBCYR5WzPBr#H)|hZ=##@aUfYX0jv-)GDKyN*wp-tBkw_TXW1;C-WIfbXzCrW zPtc3>p|#YT?%&GHi5EZ!Pz)rupd=5lDJp^jgwqhD3cV6Qs`i6qauQw-B+x*awv~}C zOtjD-P1k4Wx9a{tsSvxhAVmO5YC(z|=u|2F2T*tFa{#Ej{6Ix<65S9eCv%yeaXG!H z-=iroK21;m77nNthYBjOha;3AP6L-Cz+tx4=WrN!B@H<2A>gow zfx{jN;;;n4VTm?}<@hR!@{6y|_Em|K{(@w%zOp`t{TD5-p}96KKjo+8_4+e5EjO}6 zASZ~HlR3E}h?X}BTF$i|3efUakim2zokX*xj#3_M=Xo6VY`trJWP5yd6q2Klz&HWK zX9Ve^5b8*O1@N#F@bFp?9vTZgG!b|hDK>u%D7TLx3`WAP|0@#S#q(?=eBejINBYM$ z64I?}>LQ^TCmBIV_*5vOdDb-nBpk4ko^&0P_vwf9!>*;$0oMjR8xodKQp8CMPFjmZ zH|XvGR_BI%^o@QT&(ptkvhAcLCs)?Xwu2?^=Oa<`7n+ZL(tp-}(GS&N81h}%P~l62yvvmIi$BW4g`x8=JXSaCe>j(`B+L9>Eq z4C#P6ux5(#kpC6dYu(qmuXlH`VePIQwPEe;?(;9O0=U-(V9gaL9t34v?A3zNokE0; z_9mLNc2LOD}nXjZ=>^fcP9)Pm)rr2k)24(2nxhPdx z4?7JAl+!?tZdjrJIK<#KBOnK2w}BuxWISfWvKEy>J$`<1ucC^|+EXZNo^g+L--J?K z$2iI6q`&BRI83i@nF9nI3nuysov5GN=e`+wwNHT(NjiuK!hghZt#Aw!+#G-TW1wKH zTcGY`sXf*}5L6(rAp2I8KhX!8%|7SD4jcsocZ+MOYeV3HzVJ+)oAP5a>=Xvbp|@yA z=+wOl3828uM7SS(a~4WfCHv+OG3VWot#gh+g46yW?;+A2fmsJXb|*YGzSa)Wlah_h(y zb_3ybje_8zZh`Yvz@!uifP-pA1>brCsO5-#3#w6o@kSQd3@7%s*MW8&v^#3I%NOmg z9aRa$-hD!T>3FDj3GVP&09Upf76@?Phocm0P$m*rB5xH6XIoGzs3`%X&mvamu`H?P zu|V-_FuHAJ=icsybuHS!mco7x?tWRH0|^Tc@yU<5lSq>5ghohXdB1X=W}_wgajm~f zU3**)lhZDRu6H$2j<}l3r^q+%cK8RnQCq3z$uBDX4#bcs|+Q(>3+WFYhUea~s2l=et zPPw3+qm%SQBpLteY5{fs+w{ZQ^ZIbt4C#P6P#>lomFK|84qc^@+PyAI{z?56_EhcA z=Fo+54j9&p^l*jXGh_o~WOw4(TC{da`$xHGofM%RG9Ii^$mYPQJ+}y+Af2sIP(~%f ztZ+tEt%lnv*EO&$4Pr}U!P|husqlaB&vt>% zAlP#tB3Q(L_#T`rGQrN@6j|U=F0~feu}te-D6)l}gwKO@Bm9;3MODHVATU5cSpd(E zkivz4Uq|bA5xz03A8m00VXWP7cpLyxYVCm(3zP>7Pf6r_|FIqyCQ5-d1Zs7K3*XbW zn7#*78$_kBn^xG~(Y0cS!E8AFXfK4jpnlRWXnq4WuJsndsx`33!}g<^f;SCCO&p)L zX4#?2`4%YD_rTw`BLlAqGH!#e4jW{Fn3({9$FAk@8V|^IgCS%KfAoD=?n-eSs-NJ) zhWZKq06mCO_2KG3luA<2eB}u7xQ?lmBtZ@Pd^%FusULzff#*ZIdnuVOpQYR7v&v2= zKm7>^;wU~tA&hn!0$!ce9;eHq+EdUcY3zLB_+1h#{)kKw3fAj4c?Bm?09T>v?@68FU4X0VC`mj1M0g0Dq7 z71~0T6fjV0@HPlA2vLB7aK2!(gYb-K0A!UY{73QC`po8nLw3LS+EfQLS!k0b+=obZ zm;hmxfDfq1=9(oI*zZ8upV&|WNJ+piq$zX(i3egGu)jAI!KOoS0qCri&1*pVK(;`E z;%aBX&xgPlg4^H($O4$tqCe6UWWZp1cBkQ@X#cIfiaM{KKkmlNE2rMxq=;0B>R4up3o!TqZ6Amx2@uj>j`mhM#6 zyN-b~^`C;<<{=Q=Ai)36f?FRd=g@^haO2rRbSo!-S9jJE+(2sMLke!O83kl_Xu-YS z7Txs(H^^)ux<#lQG<863Lv_M`h;AXblmAO}gU}WX0MVh#iSF-(XD+x8gm)ScxRBe9 zquTfXAi5oX6Ovod@c*~yw)sy10WKKfyb#txcmwYV#sNNfua4;MlLJdb)F^E~cZ;d#Qd(zD95 z+Ox*9*0av@q~|Hm)1LL7XFSh(p7U(*Z1imMZ1!yNZ1p_v+2(n{v)%Ke=Oxb$&&!@y zJUczFdS3Iq?s>!Wrspls+n!yXcRag2?|RPhtP9||u!AT{DKq{%` zWHKjHIGM`HG)|^-GJ}&_Iho1HZJdDcwK(CN+|CIImOD7P6W-*+$y`og73P6*;A8vXPTboPapq!pT-np66s6Cogca zof9xkU*cp3CogmI3MV@`d6kpbIC-6uH#m8dleai|o0DCfyu-B$H^z0e9FmZaI6_8`#Axj4~EefoPhW}%*mIW9O2|BC&xGxHj%G6 z`G%9@oSfhUr1^K8e9y@boczeiPn`VB$uFGz%E?JiPI2-ZC%?7F1R%h^=MI+Y)*3()vtE;{G68~m z*HT;9<(Hc)pTuVL0Z)5815(5ok7>&x(m1+ycPmo5V~zJbX#Z_9(1*ZeTorW zjDxYoX}$Kz{i!Vi2VImE!#z`M0Z(;cvbXrvyJl}kgKLokt1Bl2$hw6Sf2!Bi-uDI9 z;zRL3P2YjHTKMCLz6v1NAfO#u2tXcQhmJ%f3HnbBT2dfsdu|Rootz#tiEGfKKR4ZS zlyH}uSEde_0%ukZ_iqcjDjg2x*=cH51T@xMs+6T zmjJ;BYPB5N*Etk#WKc_3DqCU%#nqv&Yl2$TNR$8ZXfk-*S^XBZhZ(@N2%92;uU#cx zNn#IPFT)J2!-MF@*&GQMW9txeZDB6ls!K;Th-=nh!9pdIT8{BAm@NyhN*_`CRQ;Zv zdO|T^5VZsjhJnl8+U0HmhhDWDU598#)pjf?RF*X_)zI>92ZkATi zgNUJa>kmvcKIlf>b1mRzLW3Cw3-AVWYFA&wbqk#D-ZD?f?yE9_SFbGy>0k=D{P|G; z$(5IHS?}znmce5Py;Mt1j`R>T1>xzSd5dkga4DvaAgzTR0>^cDxrSCpiqmH*9rA$X z3<9yCUL6yJ$`(Q&G^AYn{0lfU$X5Zk6Y4BEL~@#JWYmUSMkcZ^r?!DIknM4z&XqUn$ffXyy}a$tv$0m4o}%k9?`|EqK# zZA&G8MJ$X{cdhG`oCqlFrK%(KVfe;%5F6UI8S0nGp#AF1`ZB878OSj>{2RGp_^4pQ z4II$|*W-icAL!6|>j2!WE2ctd+N7Xf9k#4X8;$BrFO+2+%;ta(ZyhZm$fPbi*BaY^ zjXIr&RA-<8>QJZOz-d(nkN@Q&MAxY^!k2>Q(*{L zZ@`KT@d8&G3ZB~9X6Pi?8GP^on;htQBfN)4tIL}w{MbQa1Y z1HojoQ{A*QOr)Wbug_VR6+l2e33cenZ(H~+fxwWCX&WfnvdP}RSFF}uaoEZBS)f59 zXMYf!!0X5pze`gqyIYR(?-2Cs`^(BfSjdKsTHVSy7_YAH(%^PoYcPlm{9#W60s}=W z0zV))Q2PS{1dzviSDql3ARpZexuIQ<5gMedm$`bk`m1XL`4i=#o8jb!NqQyf>1vK{ zkt)$J2)vtUG&xODv@|IXWy48RJG9-TG3txADFoikI35jve9%tFjkSYt{9p*$kI?^; z4k+hPFI9tW^s~`Ts1n}Um@kb~^B~-Q4lPkBBolsz(E45Q2FU&r*P^8_QI$9X*3|;_ zhO|Nnnu#Vt65&_kb6r7~=;3gj+z@!rNRF!s93MCcm1}cgcU>kbrR$}RaQf{?IOCzh zwTCQ|=b&QgRmjSHLz494Xe88;9fUyX9OWVu?7Rg*)_!uDbR8-}H^|u#?B6FnO_G%p z?j$r%J_Wh91==_?l%_(WpdTvJheNXBy!@heFJ$H(BR`-quBPw~%3OVz>tT77ItfjN z(`jx*16_(XSGxqe?uTptsIm)Q$AQMl`%w=l9)I55&b1W^o^w#ODxnFk8IS`^f{<&3 zewcJs2fB{Y$p|9z5GjW=)a`IIDFQ`WapaQYB*O5MxZ`ACG?zZXXg|M z+C#txvH?*d9t%l~do2jO-zN?`fT(1)c#EZY@nw$4Ks{=QDx)Ln;d* zP$TSsKSWoHILU)^gWnY~V+i;674Ol6BO<0l8Vp{tDN=8{AQcGN6p=AZ5GgxxtZyqj z%lH};Vf`qgyXDpe$hVOJ)?|?|5aHBDaE2t{27+6iEqDarf^^G|cH~$RsYBUXX1}^K zQY2ND*g@)JkaiIn7m>E>ZlA2v$AXX-EJi<(c7z>j1Qx9syiXLe4gk#8cEon9{SMJH zb{?gzNUjVM@p2e!Kh$VL7#z;&5ZS=x99|2GcZ+w3io%HFBGWiaz(gi;Jw>>k9VQ>Uhg9Becr|1CEokJOT7EEm^uFbN+q=vAj(4~BUGIC|J>K`dA9z3X ze&qewyVtwV`-%5c?`Pi6z5Bffya&Bscn^6Gd%yG^@gDUa^M2+1+WU?7xc7wjTkm(? z@4Y{GfAs$3{n`7A_gC*p?2L5s&VSU*RtRK6P^=H{^02{~#vB8`woT{8^oa&sqISu2~!>Pfkms7^6 z$!R#J5u8SH8pUZer!kzyavH~JJf{hqCUTm@X)>oNoThTxh|?=LZOmyCPMdPtjML_v zw&1iSr&n^?iqqDdUd3q}POs)Pjni~aGdOL_X(p%bIBm~q7N;FJ?Z{~-PCIjY4X4*~ zdL5_NbJ~T|uAFw`v^%FgIPJ-4FHU=N+K1D=oZi4`KTdDtv_GfWoDSf0Ag6;kg*oPM zn#<`BPV+b&%IPpphjTiD(~+Ex;&e2pV>lhl=}nyGb2^UG0!|A#^>KPLr{g)Dz-bYu zw{SX<(_&6bI4$M0jMH*XCvjTAX(gvsoK|x>nbRqpPUUnOr_(u|!Rf7>&gAqqPG@my zamqQpozvNz-ofdeoX+8NE~j^KI*-%&oG#$>ZcgvvbRnnra=M7q`#4?9=@L%w=X5Ej z4{*AS(+4?yh|`BTUC!wvoIc9wW1K$D=?YGt;B+OYt2kZF=^9Sga=MPwCpmqJ)2BHU zEz@T>eU{VbINiYMMou?zx|!20oNndxc}}-+`U0ohIen4SmpB};PG9Eq6;5|@`YNZd zar!!^Z*cl1r*CokHmAEdeTUQCoW9HHdz|j!^nFf0;PgXIKY}-b!>Pg7!OO(Y!K=QP z!|S~l!t2Q|nplB%h+i=A023FOn3}jTJ7(e;Y=enAnfO){4}^D%zhvU!CcXn|vrSyW zUNiA%w%)`NTWeyEiO0el#J8LHMiVEPIFG#wFXOT|I>OnZ(D8Wot%+x`&rLiC-cJ55 z`_05%;1%O=`Y@b-G1A17O+3uRJ=r%Z*SX&dFJXVu#BO$>W5d5?-7Lv2})x|zvVQowdI8wJ^JW)tTJoJMLkGn>O<27S9Zuk04@C0%JY z6Yq9}BPXDY$yeC50uFhY?5o&oUTL-(-M5?nMcswa(!xlE7q(x4TEUyXJE800^n~Bk zYt%foNS&h2gMG)3sN2L=T&g?dO`DQ30jucQ_Iovv|+GuZHxx#Y|W=l&?ai7 z+9a(?n+&_cZq;UKT)RWNM|((Hu05)4h0R5~VNcI7?S%HLj&)s+(qr^ky^-Dqb`x~g zd+5FN4f-a1i~hX+g8rhuLw`koRexQ7Q-523M}Jq}qko`(r0>-~(Ld7}Fp&B*bo#ak+H->W1mhRS20-E7&=kDds zc8?O(fbJsqM0bgMq5DDi3imqq7Wd2U58eCS2i#w{54(@JzjA-$KH>f@ObYXcg@;9j z#fBw>C5NSkH4f_(RvC6@*nMGZ!?uL&3HvoWEmZe&c<~{Z)1RwYZMt1jS{2Gm}J~x+-EE?9xxs^o-o!LPa01f zn~ax?ca4vY1Kuoe7w?VU31A{@1SP%S`xPiq52(Z|K%w0*j!-V#q56e09yvaWhGn9*0Oa#(=W0ez(%hDGyQE+lbH!Xa_!7+<_%^)v%fjO z9AxI0qfDPU-YhroF&CTnn-7=|nh%?gm}|@p<|cEqxx@Ux{M7u?{M9^V{%)Q#FNEvi zVd1gijl$c7cL~o8zd5`ze0uof;j6>fg+CR(KK$A64dI)@H-~Qxe>Z$j_y^%1h3^gj zG5oLavk^)Ji-?P87I9TX`-mP9eIv$1+!Qe`qA=p-i1LV;5wjxhh*%b}B4SI#YZ0GB z9F6!P;#9=>NI5bxG9|K2War3kk^Lg`A`2o*Bd15sj=Vc^Rpir=FGju>`F`Ywksn9y zi#!>5D)RTpKO)aWo{c;gc_At~DlRH9DkbWQsHRaZqPj#)ikcI3f7H`aFGqbC^<~u2 zsN+$;MExH1N7R|9zoY(%Iv;g08by=nuxL+obadnB*3liKyF~Ym9vnS7dP?+N(etD4 zj$RnOD0)-$=IE`_+oHEe?}&aS`qk*yqrZrWh-nm)8Ph(db4-_*ZZSP#dd2jKxgqAp znCzH=F@s}rV+vx*V`jzhnAtIR#@rM0K+NMYn`2&xc`fGsm=9wG+cUOz>#8B=%VB*RjWAzm5Gq_EKC}TvA+0T%)+gaZTfHh|7x`7B?bpRNUCO{J4TR zU)=b(qPU8G3n;XT|gQ+40NccgKGg z|5g02@n;jHgs=oNAv_@=Au%C2p?N}DLPkR8gdPcl6GkQ!B}`73nJ_0|QNr?sH3_>C z-br{jVNb#b2_GlyOZYV5^Mqd$y@`>Dafu0uNr@?mjS?FtHcjl1*gtVV;-JKw#36~} z5{nb76K_vkkoaKYQ;F*npH1A5xGC}N#Lp8CBz}>2IPpkQ*QA`Jo03YB%91LQs*)xr zO--7fbZgRWNpq9tB`r=`mh@24@}x(T9#2}4^idn1WMiik#9TrGLuEl<_IkQ|6{DNm-h*Eajn; zM^YY3c_L+X%DR;QSJQp}H&w8000-Ga1VJ`7qghSTq)F54q-mRGG_%=h(u8w3=}AsX zcWEg(;fx?W@PJG~h9FD!lBpmvMD{34hU|?fAc8DkKkxf_f4Q%J;=Zo$>a2BH8?rWK z9mqPAbtLOX*2AnSnM0XN z`I54LvWT*nvYfJwvV*dVvY+x3rJZt)a)a_0M*L0X7bNsH3rv?khk+7#Lh+EUtb+Dh6g+8Wx=w8ONc zwBxjsv@^7`wDYvzY0qdcXs>8*Xz%GA=|ku?x`Xba2k9YtB|S<9=%eT{I!sT{Kcg?8 zucL3EZ=!FZZ>681x6{wjFVKIXU!ng>zfOOZotG`nmSwB6wb{Dt;%t4kA={K)mTk?p zXOGXGlf5!~RrZ?fb=e!Tk7XavKAC+wyFL4S_QmW=+0PhU2A@&DP%_jEEknmBX6P9P zhKW(eurfeKH3MagXW$HyF@dp^v5c{T@eN}&V;y4yV-w>D<2d6Kqn&Y{@eAV$;{|gl zlg?x_bC^74E>p-9F~v*?Q^~Y5qfCG~iWy_V%nWk^b0YIU%qh%i%<0UT%(cu7%+1WL z%pJ_{n0uHPSbbR^vj(w-vqrG8SX36B#bB{m999mC$I4}iSW1?fWn`II7M6|WV3o7H ztRSnB6=NM_9bz439b=tfonoC~on>8RU1Qy6J!L&-yJ!tY3wq#g>7Ry*yU_DJIs!;VRjvRDtjh-Hv0?qJobF{LiP&wH|$mHZR{QF1MCOv zC+w%}=j<2km+ZgUZ`g0y?>YTAgE<@ym&4}>IC&f!$IfwbTpSO_&k1ruoF>kC&PL8w z&MwaPoIRYqoPC@FoS!&9bB=J1aUSM$%^8$4BxhL8h@7k(RgOAGo1@Dq&MD0?=9qK9 zoCP_Ha+cHgj9JW4YtFX)eYkxEbyO?m6xS?iKD0?k(;e?mg}U?j!DR z+~2uRxzD+8d0lyZcv(CukIrN8SUfq;%(L)pJO{6wSHr92)$%%W1pgGjoqwKxk^eNeFt5 z^bqtC^cKhkR)I$l5hMgHf{ft5f@y+Tf;ob@f-eON1d9Yq1Xwx3ib&O3JwX* z3T_B)3GN8)3H}y#6?PZ)6!sQo3B^K{&>*x3Jwl%l5F)~AVZE?X*ev`?xJ0-@_>FM2 zaIJ8?aHDXmaJz7)@Mqx_;T_>);Zx!3ygqru@^bQ|d73;!o+l5;tIk97#^(`v6Y?hJ zEzet#w<>RK-uk>vd0XE>ej! zq6$$+6cGWUQKBkQT!e^7(JIkq(RR^J(f6V~qP?PhqWz+SqSK-@d{rSQCP<}W+k`Lr3^4s!L`Q!76 z{7n9e{FV8u^Vj8X$lsj*ZT`0W9r>s7U*x~f|3}hY(n~TxGD4CiVN0YEqr@z+N*t1M zNsXjd(jaM;v`E?{DM?x~SF&63ljNx6xa5@NjO483yySx97s(yTUy@gnHZL}hO$ta6X|=RPib)CS4C!p? zTe zE$<`mCm$r|%H49GJS30EN6JUZV{%wtEw7Q+%Uk4Aua&!$mzCF*Hrh0X(L)dTcu5CliC_>owh;Sq8+PEX(wtIXjf>rYjwsE7QQZgr|Y2Wr0b&Vrt7KeuN$b#(y?_pI=)Vz6Y9h|l}@WG(iQ8h zIIKGRLqP1a4-eXg6STcBI6TdCWqJFYvUJEyy#`$czI_p9!n?t$*1?xpVU zqAo=_MS>zxk)%jgq$pAqX^ON(x*~T`um~xtE~+j1*QzgCU-Vtk;iC4U>qQTXI~DgW z<`gT7^~J8@NO41Pb8&0&xZ-p%UYseOSUkCSYVpkCImPpe=NE4)K3#mN_)77e;wQy_ z6u&4LP?A-mD$$k{mFPO2?F9rMpTGl%6TQR{FH`ouQkdyP=n% zkD;HTzhR(ZuwkfSgn?q98+e9XL!Keu;54`mK10wDHbf180Wyp>)EZh1;|ys7ZXgZI z4J!<*3~LP=44Vz#8nzpD8crHJ8@n2N83!1L7>5}@HByXpBh$z><`{WKu~B8z7`4Wz zainpSvC5b*RvT-K^~OfyWaD1rKI0+dDdRcg1>+^-72`GIP2+9jUE_V@GvgcMJL7v( zmWg7bo0uk!iD$|+<(b4Lvng%DOcPAgOtVaLO!G|hO^ZxROiNA6O)E|7P1{X7O}k9{ zO$SYzhAc36I~T(VrXT({h`+_BuVJg_{ncD6FCIaYyHWR+N@ zR=HJaRa-6AYU^lgowd>0Y;Co+SyR@u^$Y7U>j`VS^@{a|^_KOn^}h9?^*8J9)~D9z z*0)_BPKVp!a|9h>N7Mm0AP4NoI3_qIIi@(KI;J~jI%Yf8IZim* z9Ty#!9ltuRJ8n8|JMKDubM|!ha`tidbM|)*bPje7b&8xWr{5WNMxCG&a#lIxPQ=;Z z{MtPnAzD|GNCU@{8qH%deN;EWcBJulzyz8&`K%PuF0V z)n#)zU9NxS=zuHainst5+`K}$Vov!a)Ke&E$ z9dP~R`q_2O-ND_(-P8S{yRZ9W_W<`m_h2{6UE^}E`<>?lPZv)&Pft&8Pan?+PmYJ@QFvUQk)E-hlxMt$@J#Sb z@=W&3@T~N#_N?=4^lbKQ_3ZKN^&IjX@f`P@@^@;) zJ?lO1edO!z>*4F|`^eYNH^4X0H`piiIelJVg|E^#(g*q=UzIQJ8}D1_TjX2fTjpEg zTjg8hTjx9IyX$-8`@{F#_m}UL@3rr(@4bJ3pX)F3NBpDwRsOg?=^yQ{^{4$){8Rl4 z{HOhA{O9}^{FnS!{n!1s{CE8i{Ez)F{4f2l{ci(Z0^I^12L=QN1_lR)28IVj0dt@# zkPOrW>H>{{=0Hn;3``Hq3@izp4_pXb3S0?X3)~Fc3EU4n3Oors4ZIG#4g3@A80;DB z9UKv)1nEI$kQ3wubAx$7anKQT2HinlFc1s{D}&KsOK@IrQE+K+MQ~McO>kXsLvT~@ zaPV&MUhrY?x8U!=XTd*%e^q=~ky|0IkX0xvG!=yvMHM9#r4@mS+KNdPD=OAhtgqNu zv87^b#rBGyD%vZ~Rotq08|oSA9~u#2hJ+z!s66Be`9l?<%1|@}hM-U?v_7;kv^BIR zv_Et(bSQKrbUbu2bUM@?Iv2VUdKY>h?ilVI?iTJD?j8Op+%L=t2g9N8$Z#TD6Rrz4 zgqy>y;kIxpoDO5*3E}DC)#0t-v*D}ZKf*7;ZlR4giOMBfxRs6wnTw2Yvyr0M~#Uz%Ae|@BnxOJOTay zo&zs{m%wY_E$|-f2zCOyf<3@qU>~p_*dH7S4hDyUBfu<>24;gykOT5S0hkAh!2(bQ zDnSjX14}>yXaX&u4RnAm&r<>HDEp12sVQ)U>k^n7)XK>z=_~w z@W0^a;7o81I1gL^eg!T8mw_w6Rp4511GpL73hn{-g8RYK;3e=HcprQO4Tgq7BcLpZ z1~DKO#DTa_E+mA+Pyr-^l#m)K{CAwU6f!|&kPUJ|F31Z7pb!*+00@GrpafJ6)j;)7 z6Ep@I3#Fj(5Dt;h1ZWa88JY@x4$Xw-Ky#t_&?0CFv=mwaeFLq5)UGsSxC7h?{qAHz@Jr|@(5FZgfx z4g5adG2S`eE#4#EE8ZvGFWx^sFg_$cJf0P&#jOyXSPV&Zb**Tjv)?Zmyr!^CfiKN8OqecAUdQ3F(78diZ~D#;za^T2#Fv70wFMhAfu5w zq!Af|j73t&c!WSEAd`?O$TVaIG8>tT%tsa>OOR#AN@O*%4%vuoLAD_~k?)ZokbTHO ztRu7kPj@Mt(=0Auo_u$Q$H+vSYGyvRkre^221`WdG#A zWLA=vWF*;1ZZbESm&{K}lZvD|S(q$NmL^R}OVXY!PkNI6WJR(vIWjpaS(QvA ztCQ1{yOVd4Ppf-X52%(`msJDRjn#9icUB*-zFqx(G;4Hd^n}qXMjsq~Vf1e`AJlwW zBdRH_3D?xsOs)C4=KGq{HGkIjtsPOzs@44KL?&ye*KV!dU3<9pYTfWUVO?omWnDwv z)Vk$$C+e=&-LLzneqcSjzM#Ii9;k1vpI^VR{)hUz^^fZRX~=32H@F*+2C`vE!w(JZ z4Zk(~+1Rm>+vsnE8pkzGYh2a1ukl3Vlg4*V!zfWX{nB)+>7V9d z&C+I|xv_b1^S0*Q&9BFFAHy7@8Uu_;jF~oO`Iy~fE{%E9GOR`0Vri*tX=z#5vbp7Y z%ipbCTP3ZI)={m^t+QJvK zYD#KqYI4IQl6{Md>I5WurML9~Gh^RD#M-1*$@|s17YbOHm_gMlGlvb)qiRiw4jT z8bJYc6dFTe6hTL$b!a2njJBfVP!z>b5}klfLZ_h9&>84#bS^p{U5I{#EnSTmZgO zNtdQgX-nFkE>C;X{&X-MPDj%~8cM_IM7lcNoNmSXVEwQG*dS~uHUgtybc~5{Fdinr zM3@AVVM97*afSEBX=D=K-7Ykq^EP??TguxhsjmGM*Mr;f=7E58{F#?-_O~R&N z)36!XY-}zzA6tYi!IohwvDMf*Y$LV>+lKALzQ=yR_F)IHpRuFZ3G6g>7Q295!meW1 zv0K<(>;d)|`yG3Ry}({!Z?N}xN4zuM4eyD6i1)?&;{)*__;5T6r{N5ojdSr_JP*&u zrMLoD61^y+z5MPWh#aG~~@U{2`d^5fk-+_OJ@458#LJBlvOr6yA=X$A7`E;Mee* z_#ON{{s@19KgIvVU*fOvcSHxG6Va9ELG&g*B0eTQAqEq}h))SBkxj6O9D+{>2{BPX z$O#ppC5i|=VI;~38{s6}gpUXkVIoR^M2v_N2vJSc67@tQ(M+@uV~KGDN{lB6B13#e z{D=52@i{S*m`%(jz9beBi;1Pga$+U1npj6{B(@M+i5QnxSWy8Fq%7;b#OH zQ6@iAkdbAS8Fi*GQ - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - SheepShaver.icns - CFBundleIdentifier - net.sourceforge.SheepShaverLauncher - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - SheepShaver - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 2.3 - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/SheepShaver/src/MacOSX/Launcher/LauncherPrefix.h b/SheepShaver/src/MacOSX/Launcher/LauncherPrefix.h deleted file mode 100644 index 992c034d..00000000 --- a/SheepShaver/src/MacOSX/Launcher/LauncherPrefix.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * LauncherPrefix.h - * - * Copyright (C) 2010 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LAUNCHERPREFIX_H -#define LAUNCHERPREFIX_H - -#define CONFIG_H -#define STDC_HEADERS -#define SIZEOF_DOUBLE 8 -#define SIZEOF_FLOAT 4 -#define SIZEOF_INT 4 -#define SIZEOF_LONG_LONG 8 -#define SIZEOF_SHORT 2 - -#ifdef __LP64__ -#define SIZEOF_VOID_P 8 -#define SIZEOF_LONG 8 -#else -#define SIZEOF_VOID_P 4 -#define SIZEOF_LONG 4 -#endif - -#define loff_t off_t - -#endif /* LAUNCHERPREFIX_H */ diff --git a/SheepShaver/src/MacOSX/Launcher/SheepShaverLauncher.xcodeproj/project.pbxproj b/SheepShaver/src/MacOSX/Launcher/SheepShaverLauncher.xcodeproj/project.pbxproj deleted file mode 100644 index fe382f61..00000000 --- a/SheepShaver/src/MacOSX/Launcher/SheepShaverLauncher.xcodeproj/project.pbxproj +++ /dev/null @@ -1,399 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 084186B10B3A0515004B1F63 /* VMSettingsController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 084186B00B3A0515004B1F63 /* VMSettingsController.mm */; }; - 088EBBB61B41AEBB0066D352 /* DiskType.m in Sources */ = {isa = PBXBuildFile; fileRef = 088EBBB51B41AEBB0066D352 /* DiskType.m */; }; - 08AAB16D102614D5007E1230 /* SheepShaver.icns in Resources */ = {isa = PBXBuildFile; fileRef = 08AAB16C102614D5007E1230 /* SheepShaver.icns */; }; - 08AAB1B310261691007E1230 /* SheepShaver in Copy SheepShaver */ = {isa = PBXBuildFile; fileRef = 08AAB1B11026168B007E1230 /* SheepShaver */; }; - 08B5FAFD102497FA0047FD1B /* VMSettingsWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 08B5FAFB102497FA0047FD1B /* VMSettingsWindow.nib */; }; - 08B5FB01102498B00047FD1B /* VMListWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 08B5FAFF102498B00047FD1B /* VMListWindow.nib */; }; - 08B5FB221024FE320047FD1B /* AppController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08B5FB211024FE320047FD1B /* AppController.mm */; }; - 08DC90BD0B67074C00799A45 /* prefs_items.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08DC90BC0B67074C00799A45 /* prefs_items.cpp */; }; - 08DC90BF0B67075D00799A45 /* prefs_unix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08DC90BE0B67075D00799A45 /* prefs_unix.cpp */; }; - 08DC90C10B67077300799A45 /* prefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08DC90C00B67077300799A45 /* prefs.cpp */; }; - 08F4D174102601C500C6436D /* VMListController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08F4D173102601C500C6436D /* VMListController.mm */; }; - 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; }; - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; - 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 08AAB19E1026164C007E1230 /* Copy SheepShaver */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 6; - files = ( - 08AAB1B310261691007E1230 /* SheepShaver in Copy SheepShaver */, - ); - name = "Copy SheepShaver"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 084186AF0B3A0515004B1F63 /* VMSettingsController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VMSettingsController.h; sourceTree = ""; }; - 084186B00B3A0515004B1F63 /* VMSettingsController.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = VMSettingsController.mm; sourceTree = ""; }; - 085339D612C9874400345D35 /* LauncherPrefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LauncherPrefix.h; sourceTree = SOURCE_ROOT; }; - 088EBB6F1B41ABDA0066D352 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../config/config.h; sourceTree = SOURCE_ROOT; }; - 088EBB701B41ABE40066D352 /* config-macosx-ppc_32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "config-macosx-ppc_32.h"; path = "../config/config-macosx-ppc_32.h"; sourceTree = SOURCE_ROOT; }; - 088EBB711B41ABE40066D352 /* config-macosx-x86_32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "config-macosx-x86_32.h"; path = "../config/config-macosx-x86_32.h"; sourceTree = SOURCE_ROOT; }; - 088EBB721B41ABE40066D352 /* config-macosx-x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "config-macosx-x86_64.h"; path = "../config/config-macosx-x86_64.h"; sourceTree = SOURCE_ROOT; }; - 088EBBB41B41AEBB0066D352 /* DiskType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiskType.h; sourceTree = SOURCE_ROOT; }; - 088EBBB51B41AEBB0066D352 /* DiskType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiskType.m; sourceTree = SOURCE_ROOT; }; - 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; - 08AAB16C102614D5007E1230 /* SheepShaver.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = SheepShaver.icns; path = ../SheepShaver.icns; sourceTree = SOURCE_ROOT; }; - 08AAB1B11026168B007E1230 /* SheepShaver */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = SheepShaver; path = ../../Unix/SheepShaver; sourceTree = SOURCE_ROOT; }; - 08B5FAFC102497FA0047FD1B /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/VMSettingsWindow.nib; sourceTree = ""; }; - 08B5FB00102498B00047FD1B /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/VMListWindow.nib; sourceTree = ""; }; - 08B5FB201024FE320047FD1B /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = ""; }; - 08B5FB211024FE320047FD1B /* AppController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppController.mm; sourceTree = ""; }; - 08DC90BC0B67074C00799A45 /* prefs_items.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = prefs_items.cpp; path = ../../prefs_items.cpp; sourceTree = SOURCE_ROOT; }; - 08DC90BE0B67075D00799A45 /* prefs_unix.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = prefs_unix.cpp; path = ../../Unix/prefs_unix.cpp; sourceTree = SOURCE_ROOT; }; - 08DC90C00B67077300799A45 /* prefs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = prefs.cpp; path = ../../prefs.cpp; sourceTree = SOURCE_ROOT; }; - 08DC90C20B67078300799A45 /* prefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = prefs.h; path = ../../include/prefs.h; sourceTree = SOURCE_ROOT; }; - 08DC90C40B67079800799A45 /* sys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sys.h; path = ../../include/sys.h; sourceTree = SOURCE_ROOT; }; - 08DC90C50B6707AC00799A45 /* user_strings_unix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = user_strings_unix.h; path = ../../Unix/user_strings_unix.h; sourceTree = SOURCE_ROOT; }; - 08DC90C70B6707BE00799A45 /* sysdeps.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sysdeps.h; path = ../../Unix/sysdeps.h; sourceTree = SOURCE_ROOT; }; - 08F4D172102601C500C6436D /* VMListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMListController.h; sourceTree = ""; }; - 08F4D173102601C500C6436D /* VMListController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = VMListController.mm; sourceTree = ""; }; - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = ""; }; - 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; - 8D1107320486CEB800E47090 /* SheepShaverLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SheepShaverLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 8D11072E0486CEB800E47090 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - ); - name = Classes; - sourceTree = ""; - }; - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { - isa = PBXGroup; - children = ( - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, - ); - name = "Linked Frameworks"; - sourceTree = ""; - }; - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - 29B97324FDCFA39411CA2CEA /* AppKit.framework */, - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, - 29B97325FDCFA39411CA2CEA /* Foundation.framework */, - ); - name = "Other Frameworks"; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 8D1107320486CEB800E47090 /* SheepShaverLauncher.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* SheepShaverLauncher */ = { - isa = PBXGroup; - children = ( - 085339D612C9874400345D35 /* LauncherPrefix.h */, - 08DC90C20B67078300799A45 /* prefs.h */, - 08DC90C40B67079800799A45 /* sys.h */, - 08DC90C50B6707AC00799A45 /* user_strings_unix.h */, - 088EBB6F1B41ABDA0066D352 /* config.h */, - 088EBB701B41ABE40066D352 /* config-macosx-ppc_32.h */, - 088EBB711B41ABE40066D352 /* config-macosx-x86_32.h */, - 088EBB721B41ABE40066D352 /* config-macosx-x86_64.h */, - 08DC90C70B6707BE00799A45 /* sysdeps.h */, - 08DC90BC0B67074C00799A45 /* prefs_items.cpp */, - 08DC90BE0B67075D00799A45 /* prefs_unix.cpp */, - 08DC90C00B67077300799A45 /* prefs.cpp */, - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - 08B5FB201024FE320047FD1B /* AppController.h */, - 08B5FB211024FE320047FD1B /* AppController.mm */, - 088EBBB41B41AEBB0066D352 /* DiskType.h */, - 088EBBB51B41AEBB0066D352 /* DiskType.m */, - 084186AF0B3A0515004B1F63 /* VMSettingsController.h */, - 084186B00B3A0515004B1F63 /* VMSettingsController.mm */, - 08F4D172102601C500C6436D /* VMListController.h */, - 08F4D173102601C500C6436D /* VMListController.mm */, - ); - name = SheepShaverLauncher; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 08AAB1B11026168B007E1230 /* SheepShaver */, - 08AAB16C102614D5007E1230 /* SheepShaver.icns */, - 8D1107310486CEB800E47090 /* Info.plist */, - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, - 29B97318FDCFA39411CA2CEA /* MainMenu.nib */, - 08B5FAFB102497FA0047FD1B /* VMSettingsWindow.nib */, - 08B5FAFF102498B00047FD1B /* VMListWindow.nib */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 8D1107260486CEB800E47090 /* SheepShaver Launcher */ = { - isa = PBXNativeTarget; - buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "SheepShaver Launcher" */; - buildPhases = ( - 8D1107290486CEB800E47090 /* Resources */, - 8D11072C0486CEB800E47090 /* Sources */, - 8D11072E0486CEB800E47090 /* Frameworks */, - 08AAB19E1026164C007E1230 /* Copy SheepShaver */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "SheepShaver Launcher"; - productInstallPath = "$(HOME)/Applications"; - productName = SheepShaverLauncher; - productReference = 8D1107320486CEB800E47090 /* SheepShaverLauncher.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SheepShaverLauncher" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* SheepShaverLauncher */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 8D1107260486CEB800E47090 /* SheepShaver Launcher */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 8D1107290486CEB800E47090 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */, - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, - 08B5FAFD102497FA0047FD1B /* VMSettingsWindow.nib in Resources */, - 08B5FB01102498B00047FD1B /* VMListWindow.nib in Resources */, - 08AAB16D102614D5007E1230 /* SheepShaver.icns in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 8D11072C0486CEB800E47090 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072D0486CEB800E47090 /* main.m in Sources */, - 084186B10B3A0515004B1F63 /* VMSettingsController.mm in Sources */, - 08DC90BD0B67074C00799A45 /* prefs_items.cpp in Sources */, - 08DC90BF0B67075D00799A45 /* prefs_unix.cpp in Sources */, - 08DC90C10B67077300799A45 /* prefs.cpp in Sources */, - 08B5FB221024FE320047FD1B /* AppController.mm in Sources */, - 08F4D174102601C500C6436D /* VMListController.mm in Sources */, - 088EBBB61B41AEBB0066D352 /* DiskType.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 089C165DFE840E0CC02AAC07 /* English */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - 08B5FAFB102497FA0047FD1B /* VMSettingsWindow.nib */ = { - isa = PBXVariantGroup; - children = ( - 08B5FAFC102497FA0047FD1B /* English */, - ); - name = VMSettingsWindow.nib; - sourceTree = ""; - }; - 08B5FAFF102498B00047FD1B /* VMListWindow.nib */ = { - isa = PBXVariantGroup; - children = ( - 08B5FB00102498B00047FD1B /* English */, - ); - name = VMListWindow.nib; - sourceTree = ""; - }; - 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = { - isa = PBXVariantGroup; - children = ( - 29B97319FDCFA39411CA2CEA /* English */, - ); - name = MainMenu.nib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - C01FCF4B08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - PREFS_EDITOR, - STANDALONE_PREFS, - ); - GCC_VERSION = 4.0; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - OTHER_CFLAGS = "$(inherited)"; - PRODUCT_NAME = SheepShaverLauncher; - WRAPPER_EXTENSION = app; - ZERO_LINK = YES; - }; - name = Debug; - }; - C01FCF4C08A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - ppc, - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; - GCC_MODEL_TUNING = G5; - GCC_PREPROCESSOR_DEFINITIONS = ( - PREFS_EDITOR, - STANDALONE_PREFS, - ); - GCC_VERSION = 4.0; - "GCC_VERSION[arch=x86_64]" = 4.2; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.5; - OTHER_CFLAGS = "$(inherited)"; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = SheepShaverLauncher; - "SDKROOT[arch=x86_64]" = macosx10.6; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREFIX_HEADER = LauncherPrefix.h; - GCC_VERSION = 4.0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "SheepShaver Launcher" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4B08A954540054247B /* Debug */, - C01FCF4C08A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SheepShaverLauncher" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/SheepShaver/src/MacOSX/Launcher/VMListController.h b/SheepShaver/src/MacOSX/Launcher/VMListController.h deleted file mode 100644 index 70b453d9..00000000 --- a/SheepShaver/src/MacOSX/Launcher/VMListController.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * VMListController.h - SheepShaver VM manager in Cocoa on Mac OS X - * - * Copyright (C) 2009 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -@interface VMListController : NSWindowController -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 - -#endif -{ - IBOutlet NSTableView *vmList; - IBOutlet NSButton *newButton; - IBOutlet NSButton *importButton; - IBOutlet NSButton *settingsButton; - IBOutlet NSButton *launchButton; - NSMutableDictionary *tasks; - NSMutableArray *vmArray; - NSString *vmBeingDragged; -} - -+ (id) sharedInstance; - -- (id) init; -- (void) awakeFromNib; - -- (IBAction) newVirtualMachine: (id) sender; -- (IBAction) importVirtualMachine: (id) sender; -- (IBAction) editVirtualMachineSettings: (id) sender; -- (IBAction) launchVirtualMachine: (id) sender; -- (IBAction) deleteVirtualMachine: (id) sender; - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/VMListController.mm b/SheepShaver/src/MacOSX/Launcher/VMListController.mm deleted file mode 100644 index d5b48ab3..00000000 --- a/SheepShaver/src/MacOSX/Launcher/VMListController.mm +++ /dev/null @@ -1,390 +0,0 @@ -/* - * VMListController.mm - SheepShaver VM manager in Cocoa on Mac OS X - * - * Copyright (C) 2009 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "VMListController.h" -#import "VMSettingsController.h" - -// NSInteger was added in 10.5 SDK. -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - #if __LP64__ || NS_BUILD_32_LIKE_64 - typedef long NSInteger; - #else - typedef int NSInteger; - #endif -#endif - -/* - -TODO: - -Drag VM from Finder to import -When choosing things like rom file and keycode files - have a checkbox to copy -selected file into the bundle. -Copy path! - - */ - -@interface NSObject (TableViewContextMenu) -- (NSMenu *) tableView: (NSTableView *) tableView menuForEvent: (NSEvent *) event; -@end - -@implementation NSTableView (ContextMenu) -- (NSMenu *) menuForEvent: (NSEvent *) event -{ - if ([[self delegate] respondsToSelector:@selector(tableView:menuForEvent:)]) - return [[self delegate] tableView:self menuForEvent:event]; - return nil; -} -@end - -#define VM_DRAG_TYPE @"sheepvm" - -@implementation VMListController - -+ (id) sharedInstance -{ - static VMListController *_sharedInstance = nil; - if (!_sharedInstance) { - _sharedInstance = [[VMListController allocWithZone:[self zone]] init]; - } - return _sharedInstance; -} - -- (id) init -{ - self = [super initWithWindowNibName:@"VMListWindow"]; - - NSArray *vms = [[NSUserDefaults standardUserDefaults] stringArrayForKey:@"vm_list"]; - vmArray = [[NSMutableArray alloc] initWithCapacity:[vms count]]; - [vmArray addObjectsFromArray:vms]; - - tasks = [[NSMutableDictionary alloc] init]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(onTaskTerminated:) - name:NSTaskDidTerminateNotification - object:nil]; - - return self; -} - -- (void) awakeFromNib -{ - [[[vmList tableColumns] objectAtIndex:0] setEditable:YES]; - [vmList setDataSource: self]; - [vmList setDelegate: self]; - [vmList reloadData]; - [vmList registerForDraggedTypes:[NSArray arrayWithObjects:VM_DRAG_TYPE, nil]]; -} - -- (void) _showNotFoundAlert -{ - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"The virtual machine cannot be found."]; - [alert setAlertStyle:NSWarningAlertStyle]; - [alert beginSheetModalForWindow:[self window] - modalDelegate:self - didEndSelector:nil - contextInfo:nil]; -} - -- (void) reloadDataAndSave -{ - [vmList reloadData]; - [[NSUserDefaults standardUserDefaults] setObject:vmArray forKey:@"vm_list"]; -} - -- (void) keyDown: (NSEvent *) event -{ - if ([event type] == NSKeyDown && [[event characters] length] > 0) { - unichar key = [[event characters] characterAtIndex:0]; - if (key == NSDeleteFunctionKey || key == NSDeleteCharacter) { - [self deleteVirtualMachine:self]; - } - } -} - -- (NSInteger) numberOfRowsInTableView: (NSTableView *) table -{ - return [vmArray count]; -} - -- (id) tableView: (NSTableView *) table objectValueForTableColumn: (NSTableColumn *) c row: (NSInteger) r -{ - return [[[vmArray objectAtIndex: r] lastPathComponent] stringByDeletingPathExtension]; -} - -- (void) tableView: (NSTableView *) table setObjectValue: (id) value forTableColumn: (NSTableColumn *) c row: (NSInteger) r -{ - NSString *currentPath = [vmArray objectAtIndex: r]; - NSString *newPath = [[NSString stringWithFormat:@"%@/%@.sheepvm", - [currentPath stringByDeletingLastPathComponent], value] retain]; - if (![currentPath isEqual:newPath]) { - if ([[NSFileManager defaultManager] fileExistsAtPath:currentPath]) { - NSFileManager *manager = [NSFileManager defaultManager]; - if ([manager movePath: currentPath toPath: newPath handler:nil]) { - [vmArray replaceObjectAtIndex: r withObject: newPath]; - [currentPath release]; - } - } else { - [self _showNotFoundAlert]; - } - } -} - -- (void) tableViewSelectionDidChange: (NSNotification *) notification -{ - if ([vmList selectedRow] >= 0) { - [settingsButton setEnabled:YES]; - [launchButton setEnabled:YES]; - } else { - [settingsButton setEnabled:NO]; - [launchButton setEnabled:NO]; - } -} - -- (BOOL) tableView: (NSTableView *) table writeRowsWithIndexes: (NSIndexSet *) rows toPasteboard: (NSPasteboard *) pboard -{ - vmBeingDragged = [vmArray objectAtIndex:[rows firstIndex]]; - [pboard declareTypes:[NSArray arrayWithObject:VM_DRAG_TYPE] owner:self]; - [pboard setString:VM_DRAG_TYPE forType:VM_DRAG_TYPE]; - return YES; -} - -- (NSDragOperation) tableView: (NSTableView *) table validateDrop: (id ) info proposedRow: (NSInteger) row proposedDropOperation: (NSTableViewDropOperation) op -{ - if (op == NSTableViewDropAbove && row != -1) { - return NSDragOperationPrivate; - } else { - return NSDragOperationNone; - } -} - -- (BOOL) tableView: (NSTableView *) table acceptDrop: (id ) info row: (NSInteger) row dropOperation: (NSTableViewDropOperation) op -{ - if ([[[info draggingPasteboard] availableTypeFromArray:[NSArray arrayWithObject:VM_DRAG_TYPE]] isEqualToString:VM_DRAG_TYPE]) { - [vmList deselectAll:nil]; - int index = [vmArray indexOfObject:vmBeingDragged]; - if (index != row) { - [vmArray insertObject:vmBeingDragged atIndex:row]; - if (row <= index) { - index += 1; - } else { - row -= 1; - } - [vmArray removeObjectAtIndex: index]; - } - [self reloadDataAndSave]; - [vmList selectRow:row byExtendingSelection:NO]; - return YES; - } - - return NO; -} - -- (NSMenu *) tableView: (NSTableView *) table menuForEvent: (NSEvent *) event -{ - NSMenu *menu = nil; - int row = [table rowAtPoint:[table convertPoint:[event locationInWindow] fromView:nil]]; - if (row >= 0) { - [table selectRow:row byExtendingSelection:NO]; - menu = [[[NSMenu alloc] initWithTitle: @"Contextual Menu"] autorelease]; - [menu addItemWithTitle: @"Launch Virtual Machine" - action: @selector(launchVirtualMachine:) keyEquivalent: @""]; - [menu addItemWithTitle: @"Edit VM Settings..." - action: @selector(editVirtualMachineSettings:) keyEquivalent: @""]; - [menu addItemWithTitle: @"Reveal VM in Finder" - action: @selector(revealVirtualMachineInFinder:) keyEquivalent: @""]; - [menu addItemWithTitle: @"Remove VM from List" - action: @selector(deleteVirtualMachine:) keyEquivalent: @""]; - } - return menu; -} - -- (NSString *) tableView: (NSTableView *) table toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect - tableColumn: (NSTableColumn *) c row: (NSInteger) r mouseLocation: (NSPoint) loc -{ - return [vmArray objectAtIndex: r]; -} - -- (IBAction) newVirtualMachine: (id) sender -{ - [vmList abortEditing]; - NSSavePanel *save = [NSSavePanel savePanel]; - [save setMessage: @"New SheepShaver Virtual Machine:"]; - [save setRequiredFileType: @"sheepvm"]; - [save setCanSelectHiddenExtension: YES]; - [save setExtensionHidden: NO]; - [save beginSheetForDirectory: nil - file: @"New.sheepvm" - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_newVirtualMachineDone: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (IBAction) _newVirtualMachineDone: (NSSavePanel *) save returnCode: (int) returnCode contextInfo: (void *) contextInfo -{ - if (returnCode == NSOKButton) { - NSFileManager *manager = [NSFileManager defaultManager]; - [manager createDirectoryAtPath:[save filename] attributes:nil]; - [manager createFileAtPath:[[save filename] stringByAppendingPathComponent:@"prefs"] contents:nil attributes:nil]; - [vmArray addObject:[save filename]]; - [vmList reloadData]; - [vmList selectRow:([vmArray count] - 1) byExtendingSelection:NO]; - [[VMSettingsController sharedInstance] editSettingsForNewVM:[save filename] sender:self]; - if ([[VMSettingsController sharedInstance] cancelWasClicked]) { - [manager removeFileAtPath:[save filename] handler:nil]; - [vmArray removeObjectAtIndex:([vmArray count] - 1)]; - } - [self reloadDataAndSave]; - } -} - -- (IBAction) importVirtualMachine: (id) sender -{ - [vmList abortEditing]; - NSOpenPanel *open = [NSOpenPanel openPanel]; - [open setMessage:@"Import SheepShaver Virtual Machine:"]; - [open setResolvesAliases:YES]; - // Curiously, bundles are treated as "files" not "directories" by NSOpenPanel. - [open setCanChooseDirectories:NO]; - [open setCanChooseFiles:YES]; - [open setAllowsMultipleSelection:NO]; - [open beginSheetForDirectory: nil - file: nil - types: [NSArray arrayWithObject:@"sheepvm"] - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_importVirtualMachineDone: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _importVirtualMachineDone: (NSOpenPanel *) open returnCode: (int) returnCode contextInfo: (void *) contextInfo -{ - if (returnCode == NSOKButton) { - [vmArray addObject:[open filename]]; - [self reloadDataAndSave]; - } -} - -- (IBAction) editVirtualMachineSettings: (id) sender -{ - [vmList abortEditing]; - int selectedRow = [vmList selectedRow]; - if (selectedRow >= 0) { - NSString *path = [vmArray objectAtIndex:selectedRow]; - if ([tasks objectForKey:path]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Cannot edit virtual machine settings while it's running."]; - [alert setAlertStyle:NSWarningAlertStyle]; - [alert beginSheetModalForWindow:[self window] - modalDelegate:self - didEndSelector:nil - contextInfo:nil]; - } else if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { - [[VMSettingsController sharedInstance] editSettingsFor:path sender:sender]; - } else { - [self _showNotFoundAlert]; - } - } -} - -- (IBAction) launchVirtualMachine: (id) sender -{ - [vmList abortEditing]; - int selectedRow = [vmList selectedRow]; - if (selectedRow >= 0) { - NSString *path = [vmArray objectAtIndex:selectedRow]; - if ([tasks objectForKey:path]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"The selected virtual machine is already running."]; - [alert setAlertStyle:NSWarningAlertStyle]; - [alert beginSheetModalForWindow:[self window] - modalDelegate:self - didEndSelector:nil - contextInfo:nil]; - } else if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { - NSTask *sheep = [[NSTask alloc] init]; - [sheep setLaunchPath:[[NSBundle mainBundle] pathForAuxiliaryExecutable:@"SheepShaver"]]; - [sheep setArguments:[NSArray arrayWithObject:path]]; - [sheep launch]; - [tasks setObject:sheep forKey:path]; - } else { - [self _showNotFoundAlert]; - } - } -} - -- (void) onTaskTerminated: (NSNotification *) notification -{ - NSArray *paths = [tasks allKeys]; - NSEnumerator *enumerator = [paths objectEnumerator]; - NSString *path; - while ((path = [enumerator nextObject])) { - NSTask *task = [tasks objectForKey:path]; - if (![task isRunning]) { - [tasks removeObjectForKey:path]; - [task release]; - } - } -} - -- (IBAction) deleteVirtualMachine: (id) sender -{ - [vmList abortEditing]; - int selectedRow = [vmList selectedRow]; - if (selectedRow >= 0) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Do you wish to remove the selected virtual machine from the list?"]; - [alert addButtonWithTitle:@"Remove"]; - [alert addButtonWithTitle:@"Cancel"]; - [alert setAlertStyle:NSWarningAlertStyle]; - [alert beginSheetModalForWindow:[self window] - modalDelegate:self - didEndSelector:@selector(_deleteVirtualMachineDone: returnCode: contextInfo:) - contextInfo:nil]; - } -} - -- (void) _deleteVirtualMachineDone: (NSAlert *) alert returnCode: (int) returnCode contextInfo: (void *) contextInfo -{ - if (returnCode == NSAlertFirstButtonReturn) { - [vmArray removeObjectAtIndex:[vmList selectedRow]]; - [vmList deselectAll:self]; - [self reloadDataAndSave]; - } -} - -- (IBAction) revealVirtualMachineInFinder: (id) sender -{ - [vmList abortEditing]; - int selectedRow = [vmList selectedRow]; - if (selectedRow >= 0) { - NSString *path = [vmArray objectAtIndex:selectedRow]; - if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { - [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: @""]; - } else { - [self _showNotFoundAlert]; - } - } -} - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/VMSettingsController.h b/SheepShaver/src/MacOSX/Launcher/VMSettingsController.h deleted file mode 100755 index d8b4ed5a..00000000 --- a/SheepShaver/src/MacOSX/Launcher/VMSettingsController.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * VMSettingsController.h - Preferences editing in Cocoa on Mac OS X - * - * Copyright (C) 2006-2009 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -@interface VMSettingsController : NSWindowController -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 - -#endif -{ - BOOL cancelWasClicked; - - IBOutlet NSView *diskSaveSize; - IBOutlet NSTextField *diskSaveSizeField; - NSMutableArray *diskArray; - IBOutlet NSView *isCDROM; - IBOutlet NSButton *isCDROMcheckbox; - // Setup - IBOutlet NSTableView *disks; - IBOutlet NSComboBox *bootFrom; - IBOutlet NSButton *disableCdrom; - IBOutlet NSTextField *ramSize; - IBOutlet NSStepper *ramSizeStepper; - IBOutlet NSTextField *romFile; - IBOutlet NSTextField *unixRoot; - // Audio/Video - IBOutlet NSPopUpButton *videoType; - IBOutlet NSPopUpButton *refreshRate; - IBOutlet NSComboBox *width; - IBOutlet NSComboBox *height; - IBOutlet NSButton *qdAccel; - IBOutlet NSButton *disableSound; - IBOutlet NSTextField *outDevice; - IBOutlet NSTextField *mixDevice; - // Keyboard/Mouse - IBOutlet NSButton *useRawKeyCodes; - IBOutlet NSTextField *rawKeyCodes; - IBOutlet NSButton *browseRawKeyCodesButton; - IBOutlet NSPopUpButton *mouseWheel; - IBOutlet NSTextField *scrollLines; - IBOutlet NSStepper *scrollLinesStepper; - // CPU/Misc - IBOutlet NSButton *ignoreIllegalMemoryAccesses; - IBOutlet NSButton *ignoreIllegalInstructions; - IBOutlet NSButton *dontUseCPUWhenIdle; - IBOutlet NSButton *enableJIT; - IBOutlet NSButton *enable68kDREmulator; - IBOutlet NSTextField *modemPort; - IBOutlet NSTextField *printerPort; - IBOutlet NSTextField *ethernetInterface; -} - -+ (id) sharedInstance; -- (id) init; -- (void) setupGUI; -- (void) editSettingsFor: (NSString *) vmdir sender: (id) sender; -- (void) editSettingsForNewVM: (NSString *) vmdir sender: (id) sender; -- (IBAction) addDisk: (id) sender; -- (IBAction) removeDisk: (id) sender; -- (IBAction) createDisk: (id) sender; -- (IBAction) useRawKeyCodesClicked: (id) sender; -- (IBAction) browseForROMFileClicked: (id) sender; -- (IBAction) browseForUnixRootClicked: (id) sender; -- (IBAction) browseForKeyCodesFileClicked: (id) sender; -- (void) cancelEdit: (id) sender; -- (void) saveChanges: (id) sender; -- (BOOL) cancelWasClicked; -- (void) dealloc; - -@end diff --git a/SheepShaver/src/MacOSX/Launcher/VMSettingsController.mm b/SheepShaver/src/MacOSX/Launcher/VMSettingsController.mm deleted file mode 100755 index 9a5ddf9c..00000000 --- a/SheepShaver/src/MacOSX/Launcher/VMSettingsController.mm +++ /dev/null @@ -1,480 +0,0 @@ -/* - * VMSettingsController.mm - Preferences editing in Cocoa on Mac OS X - * - * Copyright (C) 2006-2010 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "sysdeps.h" -#import "prefs.h" - -// The _UINT64 define is needed to guard against a typedef mismatch with Snow Leopard headers. -#define _UINT64 - -#import "VMSettingsController.h" - -#import "DiskType.h" - -#include - -// NSInteger was added in 10.5 SDK. -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - #if __LP64__ || NS_BUILD_32_LIKE_64 - typedef long NSInteger; - #else - typedef int NSInteger; - #endif -#endif - -const int CDROMRefNum = -62; // RefNum of driver - -#ifdef STANDALONE_PREFS -void prefs_init() -{ -} - -void prefs_exit() -{ -} -#endif - -@implementation VMSettingsController - -+ (id) sharedInstance -{ - static VMSettingsController *_sharedInstance = nil; - if (!_sharedInstance) { - _sharedInstance = [[VMSettingsController allocWithZone:[self zone]] init]; - } - return _sharedInstance; -} - -- (id) init -{ - self = [super initWithWindowNibName:@"VMSettingsWindow"]; - - cancelWasClicked = NO; - - return self; -} - -- (NSInteger) numberOfRowsInTableView: (NSTableView *) table -{ - return [diskArray count]; -} - -- (id) tableView: (NSTableView *) table objectValueForTableColumn: (NSTableColumn *) col row: (NSInteger) row -{ - DiskType *d = (DiskType*)[diskArray objectAtIndex:row]; - - if ([[col identifier] isEqualTo:@"isCDROMcol"]) { - return [NSString stringWithFormat:@"%d", [d isCDROM]]; - } - - return [d path]; -} - -- (void) tableView: (NSTableView *) table setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn row: (NSInteger) row -{ - if ([[tableColumn identifier] isEqual:@"isCDROMcol"]) { - DiskType *d = (DiskType*)[diskArray objectAtIndex:row]; - [d setIsCDROM:![d isCDROM]]; - } -} - -static NSString *getStringFromPrefs(const char *key) -{ - const char *value = PrefsFindString(key); - if (value == NULL) - return @""; - return [NSString stringWithUTF8String: value]; -} - -- (void) setupGUI -{ - diskArray = [[NSMutableArray alloc] init]; - - const char *dsk; - int index = 0; - while ((dsk = PrefsFindString("disk", index++)) != NULL) { - DiskType *disk = [[DiskType alloc] init]; - [disk setPath:[NSString stringWithUTF8String: dsk ]]; - [disk setIsCDROM:NO]; - - [diskArray addObject:disk]; - } - - /* Fetch all CDROMs */ - index = 0; - while ((dsk = PrefsFindString("cdrom", index++)) != NULL) { - DiskType *disk = [[DiskType alloc] init]; - [disk setPath:[NSString stringWithUTF8String: dsk ]]; - [disk setIsCDROM:YES]; - - [diskArray addObject:disk]; - } - - [disks setDataSource: self]; - [disks reloadData]; - - int bootdriver = PrefsFindInt32("bootdriver"), active = 0; - switch (bootdriver) { - case 0: active = 0; break; - case CDROMRefNum: active = 1; break; - } - [bootFrom selectItemAtIndex: active ]; - - [romFile setStringValue: getStringFromPrefs("rom") ]; - [unixRoot setStringValue: getStringFromPrefs("extfs") ]; - [disableCdrom setIntValue: PrefsFindBool("nocdrom") ]; - [ramSize setIntValue: PrefsFindInt32("ramsize") / (1024*1024) ]; - [ramSizeStepper setIntValue: PrefsFindInt32("ramsize") / (1024*1024) ]; - - int display_type = 0; - int dis_width = 640; - int dis_height = 480; - - const char *str = PrefsFindString("screen"); - if (str != NULL) { - if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2) - display_type = 0; - else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2) - display_type = 1; - } - - [videoType selectItemAtIndex: display_type ]; - [width setIntValue: dis_width ]; - [height setIntValue: dis_height ]; - - int frameskip = PrefsFindInt32("frameskip"); - int item = -1; - switch (frameskip) { - case 12: item = 0; break; - case 8: item = 1; break; - case 6: item = 2; break; - case 4: item = 3; break; - case 2: item = 4; break; - case 1: item = 5; break; - case 0: item = 6; break; - } - if (item >= 0) - [refreshRate selectItemAtIndex: item ]; - - [qdAccel setIntValue: PrefsFindBool("gfxaccel") ]; - - [disableSound setIntValue: PrefsFindBool("nosound") ]; - [outDevice setStringValue: getStringFromPrefs("dsp") ]; - [mixDevice setStringValue: getStringFromPrefs("mixer") ]; - - [useRawKeyCodes setIntValue: PrefsFindBool("keycodes") ]; - [rawKeyCodes setStringValue: getStringFromPrefs("keycodefile") ]; - [rawKeyCodes setEnabled:[useRawKeyCodes intValue]]; - [browseRawKeyCodesButton setEnabled:[useRawKeyCodes intValue]]; - - int wheelmode = PrefsFindInt32("mousewheelmode"), wheel = 0; - switch (wheelmode) { - case 0: wheel = 0; break; - case 1: wheel = 1; break; - } - [mouseWheel selectItemAtIndex: wheel ]; - - [scrollLines setIntValue: PrefsFindInt32("mousewheellines") ]; - [scrollLinesStepper setIntValue: PrefsFindInt32("mousewheellines") ]; - - [ignoreIllegalMemoryAccesses setIntValue: PrefsFindBool("ignoresegv") ]; - [ignoreIllegalInstructions setIntValue: PrefsFindBool("ignoreillegal") ]; - [dontUseCPUWhenIdle setIntValue: PrefsFindBool("idlewait") ]; - [enableJIT setIntValue: PrefsFindBool("jit") ]; - [enable68kDREmulator setIntValue: PrefsFindBool("jit68k") ]; - - [modemPort setStringValue: getStringFromPrefs("seriala") ]; - [printerPort setStringValue: getStringFromPrefs("serialb") ]; - [ethernetInterface setStringValue: getStringFromPrefs("ether") ]; -} - -- (void) editSettingsFor: (NSString *) vmdir sender: (id) sender -{ - chdir([vmdir fileSystemRepresentation]); - AddPrefsDefaults(); - AddPlatformPrefsDefaults(); - LoadPrefs([vmdir fileSystemRepresentation]); - NSWindow *window = [self window]; - [self setupGUI]; - [NSApp runModalForWindow:window]; -} - -- (void) editSettingsForNewVM: (NSString *) vmdir sender: (id) sender -{ - chdir([vmdir fileSystemRepresentation]); - AddPrefsDefaults(); - AddPlatformPrefsDefaults(); - LoadPrefs([vmdir fileSystemRepresentation]); - PrefsReplaceString("screen", "win/800/600"); - PrefsReplaceString("extfs", ""); - PrefsReplaceString("ether", "slirp"); - PrefsReplaceInt32("ramsize", 64 << 20); - PrefsReplaceInt32("frameskip", 2); - PrefsReplaceBool("jit", true); - NSWindow *window = [self window]; - [self setupGUI]; - [NSApp runModalForWindow:window]; -} - -static NSString *makeRelativeIfNecessary(NSString *path) -{ - char cwd[1024], filename[1024]; - int cwdlen; - strlcpy(filename, [path fileSystemRepresentation], sizeof(filename)); - getcwd(cwd, sizeof(cwd)); - cwdlen = strlen(cwd); - if (!strncmp(cwd, filename, cwdlen)) { - if (cwdlen >= 0 && cwd[cwdlen-1] != '/') - cwdlen++; - return [NSString stringWithUTF8String: filename + cwdlen]; - } - return path; -} - -- (IBAction) addDisk: (id) sender -{ - NSOpenPanel *open = [NSOpenPanel openPanel]; - [open setCanChooseDirectories:YES]; - [open setAccessoryView:isCDROM]; - [open setAllowsMultipleSelection:NO]; - [open setTreatsFilePackagesAsDirectories:YES]; - [open beginSheetForDirectory: [[NSFileManager defaultManager] currentDirectoryPath] - file: @"Unknown" - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_addDiskEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _addDiskEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - DiskType *d = [[DiskType alloc] init]; - [d setPath:makeRelativeIfNecessary([open filename])]; - - [d setIsCDROM:([isCDROMcheckbox state] == NSOnState)]; - - [diskArray addObject: d]; - [disks reloadData]; - } -} - -- (IBAction) removeDisk: (id) sender -{ - int selectedRow = [disks selectedRow]; - if (selectedRow >= 0) { - [diskArray removeObjectAtIndex: selectedRow]; - [disks reloadData]; - } -} - -- (IBAction) createDisk: (id) sender -{ - NSSavePanel *save = [NSSavePanel savePanel]; - [save setAccessoryView: diskSaveSize]; - [save setTreatsFilePackagesAsDirectories:YES]; - [save beginSheetForDirectory: [[NSFileManager defaultManager] currentDirectoryPath] - file: @"New.dsk" - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_createDiskEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _createDiskEnd: (NSSavePanel *) save returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - int size = [diskSaveSizeField intValue]; - if (size >= 0 && size <= 10000) { - char cmd[1024]; - snprintf(cmd, sizeof(cmd), "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", [[save filename] UTF8String], [diskSaveSizeField intValue]); - int ret = system(cmd); - if (ret == 0) { - DiskType *d = [[DiskType alloc] init]; - [d setPath:makeRelativeIfNecessary([save filename])]; - [d setIsCDROM:NO]; - - [diskArray addObject: d]; - [disks reloadData]; - } - } - } - [(NSData *)theContextInfo release]; -} - -- (IBAction) useRawKeyCodesClicked: (id) sender -{ - [rawKeyCodes setEnabled:[useRawKeyCodes intValue]]; - [browseRawKeyCodesButton setEnabled:[useRawKeyCodes intValue]]; -} - -- (IBAction) browseForROMFileClicked: (id) sender -{ - NSOpenPanel *open = [NSOpenPanel openPanel]; - [open setCanChooseDirectories:NO]; - [open setAllowsMultipleSelection:NO]; - [open setTreatsFilePackagesAsDirectories:YES]; - [open beginSheetForDirectory: @"" - file: [romFile stringValue] - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_browseForROMFileEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _browseForROMFileEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - [romFile setStringValue: makeRelativeIfNecessary([open filename])]; - } -} - -- (IBAction) browseForUnixRootClicked: (id) sender -{ - NSOpenPanel *open = [NSOpenPanel openPanel]; - [open setCanChooseDirectories:YES]; - [open setCanChooseFiles:NO]; - [open setAllowsMultipleSelection:NO]; - [open beginSheetForDirectory: @"" - file: [unixRoot stringValue] - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_browseForUnixRootEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _browseForUnixRootEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - [unixRoot setStringValue: makeRelativeIfNecessary([open filename])]; - } -} - -- (IBAction) browseForKeyCodesFileClicked: (id) sender -{ - NSOpenPanel *open = [NSOpenPanel openPanel]; - [open setCanChooseDirectories:NO]; - [open setAllowsMultipleSelection:NO]; - [open setTreatsFilePackagesAsDirectories:YES]; - [open beginSheetForDirectory: @"" - file: [unixRoot stringValue] - modalForWindow: [self window] - modalDelegate: self - didEndSelector: @selector(_browseForKeyCodesFileEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _browseForKeyCodesFileEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - [rawKeyCodes setStringValue: makeRelativeIfNecessary([open filename])]; - } -} - -- (void) cancelEdit: (id) sender -{ -#ifdef STANDALONE_PREFS - PrefsExit(); -#endif - [[self window] close]; - [NSApp stopModal]; - cancelWasClicked = YES; -} - -- (void) saveChanges: (id) sender -{ - // Remove all disks - while (PrefsFindString("disk")) - PrefsRemoveItem("disk"); - // Remove all cdroms - while (PrefsFindString("cdrom")) - PrefsRemoveItem("cdrom"); - - - // Write all disks - for (int i = 0; i < [diskArray count]; i++) { - DiskType *d = [diskArray objectAtIndex:i]; - PrefsAddString([d isCDROM] ? "cdrom" : "disk", [[d path] UTF8String]); - } - - PrefsReplaceInt32("bootdriver", ([bootFrom indexOfSelectedItem] == 1 ? CDROMRefNum : 0)); - PrefsReplaceString("rom", [[romFile stringValue] UTF8String]); - PrefsReplaceString("extfs", [[unixRoot stringValue] UTF8String]); - PrefsReplaceBool("nocdrom", [disableCdrom intValue]); - PrefsReplaceInt32("ramsize", [ramSize intValue] << 20); - - char pref[256]; - snprintf(pref, sizeof(pref), "%s/%d/%d", [videoType indexOfSelectedItem] == 0 ? "win" : "dga", [width intValue], [height intValue]); - PrefsReplaceString("screen", pref); - - int rate = 8; - switch ([refreshRate indexOfSelectedItem]) { - case 0: rate = 12; break; - case 1: rate = 8; break; - case 2: rate = 6; break; - case 3: rate = 4; break; - case 4: rate = 2; break; - case 5: rate = 1; break; - case 6: rate = 0; break; - } - PrefsReplaceInt32("frameskip", rate); - PrefsReplaceBool("gfxaccel", [qdAccel intValue]); - - PrefsReplaceBool("nosound", [disableSound intValue]); - PrefsReplaceString("dsp", [[outDevice stringValue] UTF8String]); - PrefsReplaceString("mixer", [[mixDevice stringValue] UTF8String]); - - PrefsReplaceBool("keycodes", [useRawKeyCodes intValue]); - PrefsReplaceString("keycodefile", [[rawKeyCodes stringValue] UTF8String]); - - PrefsReplaceInt32("mousewheelmode", [mouseWheel indexOfSelectedItem]); - PrefsReplaceInt32("mousewheellines", [scrollLines intValue]); - - PrefsReplaceBool("ignoresegv", [ignoreIllegalMemoryAccesses intValue]); - PrefsReplaceBool("ignoreillegal", [ignoreIllegalInstructions intValue]); - PrefsReplaceBool("idlewait", [dontUseCPUWhenIdle intValue]); - PrefsReplaceBool("jit", [enableJIT intValue]); - PrefsReplaceBool("jit68k", [enable68kDREmulator intValue]); - - PrefsReplaceString("seriala", [[modemPort stringValue] UTF8String]); - PrefsReplaceString("serialb", [[printerPort stringValue] UTF8String]); - PrefsReplaceString("ether", [[ethernetInterface stringValue] UTF8String]); - SavePrefs(); -#ifdef STANDALONE_PREFS - PrefsExit(); -#endif - - [[self window] close]; - [NSApp stopModal]; - cancelWasClicked = NO; -} - -- (BOOL) cancelWasClicked -{ - return cancelWasClicked; -} - -- (void) dealloc -{ - [super dealloc]; -} - -@end - diff --git a/SheepShaver/src/MacOSX/Launcher/main.m b/SheepShaver/src/MacOSX/Launcher/main.m deleted file mode 100644 index 88f92937..00000000 --- a/SheepShaver/src/MacOSX/Launcher/main.m +++ /dev/null @@ -1,26 +0,0 @@ -/* - * main.m - Cocoa SheepShaver launcher for Mac OS X - * - * Copyright (C) 2006-2009 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -int main(int argc, char *argv[]) -{ - return NSApplicationMain(argc, (const char **) argv); -} diff --git a/SheepShaver/src/MacOSX/MacOSX_sound_if.cpp b/SheepShaver/src/MacOSX/MacOSX_sound_if.cpp deleted file mode 120000 index da209f87..00000000 --- a/SheepShaver/src/MacOSX/MacOSX_sound_if.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/MacOSX_sound_if.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/MacOSX_sound_if.h b/SheepShaver/src/MacOSX/MacOSX_sound_if.h deleted file mode 120000 index 63bcdb27..00000000 --- a/SheepShaver/src/MacOSX/MacOSX_sound_if.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/MacOSX_sound_if.h \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/InfoPlist.strings b/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/InfoPlist.strings deleted file mode 100644 index 4e36ad6e3d71e03ba045089894ea15f9a30b450a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 216 zcmZvWO%A~T5JunHDVi?3P_eKP3$Y;)3q3*6(v-Go5!}cn@zS+SGC$vZ^D^I0Ohmw% znms9J3SML!)b7@nPNk-@2G-oXa?0(8G`+v$s#@xP_O6JSfw3WB$&HKLimm%pZpzN9 qjD>{8i&p-TQ_q;m3IA^1ZpMs^iQT*>Jfsv(iJunUm*z?>WXcagJtnyT diff --git a/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/classes.nib b/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/classes.nib deleted file mode 100644 index ddaaa18e..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/classes.nib +++ /dev/null @@ -1,50 +0,0 @@ -{ - IBClasses = ( - {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - { - ACTIONS = { - addDisk = id; - browseForROMFileClicked = id; - createDisk = id; - removeDisk = id; - useRawKeyCodesClicked = id; - }; - CLASS = PrefsEditor; - LANGUAGE = ObjC; - OUTLETS = { - bootFrom = NSComboBox; - disableCdrom = NSButton; - disableSound = NSButton; - diskSaveSize = NSView; - diskSaveSizeField = NSTextField; - disks = NSTableView; - dontUseCPUWhenIdle = NSButton; - enable68kDREmulator = NSButton; - enableJIT = NSButton; - ethernetInterface = NSTextField; - height = NSComboBox; - ignoreIllegalMemoryAccesses = NSButton; - mixDevice = NSTextField; - modemPort = NSTextField; - mouseWheel = NSPopUpButton; - outDevice = NSTextField; - printerPort = NSTextField; - qdAccel = NSButton; - ramSize = NSTextField; - ramSizeStepper = NSStepper; - rawKeyCodes = NSTextField; - refreshRate = NSPopUpButton; - romFile = NSTextField; - scrollLines = NSTextField; - scrollLinesStepper = NSStepper; - unixRoot = NSTextField; - useRawKeyCodes = NSButton; - videoType = NSPopUpButton; - width = NSComboBox; - window = NSWindow; - }; - SUPERCLASS = NSObject; - } - ); - IBVersion = 1; -} \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/info.nib b/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/info.nib deleted file mode 100644 index b92e8621..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/info.nib +++ /dev/null @@ -1,23 +0,0 @@ - - - - - IBDocumentLocation - 135 142 356 240 0 0 1680 1028 - IBEditorPositions - - 29 - 132 352 305 44 0 0 1680 1028 - 342 - 715 652 249 104 0 0 1680 1028 - - IBFramework Version - 446.1 - IBOpenObjects - - 29 - - IBSystem Version - 8R2218 - - diff --git a/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/keyedobjects.nib b/SheepShaver/src/MacOSX/PrefsEditor/English.lproj/MainMenu.nib/keyedobjects.nib deleted file mode 100644 index 20efaaf1d540bbe1b9e3a1f47807916e3497353e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39269 zcmbS!2VfM%_y3gL+ughD?OqybB$tAK(o%o~3xp;hErf&sff$kl0%@dBMRw>2Vh0pZ zsuc^0y&`r&l%gPAR1g(KL=g-BH?w!i(fs=V0SQ-T=e?Qt=Dp8*^JaHcb$MBBUAuO> z5Jm)1Bq13&kb;~;Q;KU!#+FU=)fA+_uiCPz%E2jhRn-M4RinoFO6qEhOrwA9O};6< z(rkajP=x2M`V6T^8_~OK8@pL)ab2;6pY}*u$b~{sDr%3iP#4q<^+Y$J5>$$OXe=6! zYSAQg8(NI+MQhPh=xOv8+KfI#AEB-2bMyt;gASlW=xg*1I*xuor_nj|C#G1!E*yd* za3qe!aX0~|;AXfLZjCc=d)yQE!2|ISJQ5e-T3m-G;;DE#o{i_=+wo$2Ctiw|;Z=Aw zUW+&3SMUdTEB+QA!{6f{@K5+O!9*oGF-Zi8B+(?1Tt%9bt4SM@PBKVG(urJ4ZXmr$ zA954vPx9gaA*6r|Cxv7rDIzzM(PRu6M=D4isVBFP>0~yULza?d@UxOUh+O0u_}NIF zNAt*AU6(Q$M62dS&nUFs+0z^8+x!O{q6G`t!kRm1NI(p308O_~kA=SYj;_Z`v_X{oeIS}i>) zJtl3Go|RsfUXk9Gwn!gIA4@x=ozj=mKItpzsB}X5Uiw8kEuEA8l!;7br|goO$WgKv zekaOFa8t?+UpRT2}d6PM4WHUtTQV zDc=n(@0VA}tK~=K$K+?^jq*$K%ko?DX8B`UAa9ko$-Cs;@|W`W@)`LL`5*Z_DRLl( z!=X4dN0_6DBhJwjK8bgvIGQ<{JK8wfIx-zujxLUDM<2&cjzNxG$8blXqr_3_sBly| zCOd9%%ycYt-0ir>vBI&^vCgsHvBB}AW0T`~$7_z)9q%~ab!>C&a_n{-aD46f#_^-$ zB=r817(4F3{rBHk;=_V znNlH{N~Kb*)GN2bs~O5%Wgab17AtoscPV!(_bB%&_bJPi70TDjcgoMo8Ra+ScjcV& zk4jWcb*j4RQKQs2wW%7fCaTTVHfp+>p|)2u)$7&nY7e!S+E2|>^VK10fjUAhg;zdx zv^rj`QESyYb+S4`ou$rJ=cx15Me053z3P4HGIfQzR$ZsAS07b3sL!dJ)aTWg)YsH4 z>O1PY>Idppb*H*Z-L39X_p3+MW9o7BJM{-jN^7pQ&{}EfT87qM%hI}N-L)QCPwhtSCT)WqFLHJZN9cZyG^@8yIZ?QyH{JPtQtSY)9o~z z;m!zWj5F5hbtXEma<+E1cXn`I=j`U}?(FOA=j;zZxy}OTNT<&^+F9YOM5oX%&MIe( zvlhOY3_sJIGo7=X^PLNvi=B5k?{(hie89OJK3@et>z$7~pKw0o+~|D4`J(eR=j+b5 zom-qAI6riL;@s{kbd7e6ca_6Wg?6`Vf@_9rzUvOxovyoF_q*1>=WAV$x*m5u>3Yib zg6j>}o30OCTV0>JK6CAb*5$6RTpz*j?_Iyb?=!C7LmVMSNK{Cot2`trBqgL(NPBqI zKBPm)b&?FPdW75<(m!NC$iR?6A&2w==LAx&f2Qxycf#*o`fmMm{R@4M_;j!SC26Ve zqr3F|=#+kd7UN&hDRM+VpdZu^iBERwU+G8nuk~;BWBPG)Qa_=8um7N*#J9lvpW(Vw zQfugMul|dETK^S#KcoMq|E`~fKK_8&JEfn~|AbFJ)A#6q>3_pFyYzqb^ZM`F-OdSa zL@Ve{H-=t!LEDqi=6iI?P23bdl}I_=g>P}oZU<2MLf;FteswDpT1u_mD*S)a?R2}~ z)17cd2z;lzO?R04TjOQp72{RoHRE;T4YJsH(|F6+Y`kr3G2SuWHQqDcH$E^vG(Ivu zHntkuj8Ba1#;3+-#tvhrvCG(Pd~SSU>@oHlUmE+2{l)>~pmE4JY#cGZGL9Nw8{Zh; z8pn*|#&^aE<9p)=^n~%Fankt7_}MsR{9>Foel^Y*zZt(9XN^CMbH<;>U&i0YKgM|z znb;&IH6>Fv9j0Qcre-=#ml+-!_5dY(rjWznbBs98EeLwP0e^S z!StGmW|Em~rkKsltIXzR3$vwpwRw%%%4}`6G25E$%v3YYOgA&k_GSmOqnT-DnVrmQ z&FjqT%^S?lW*0Nt>}qy1yPG}Cp5~2aFSEDV$GpkxYxXnyn*+>&W{x??%rys_d1k&j z#4Ip}n#0WDW}!L49BCGrH=D)gC|qrpn5CxA9Bqy<$C_p4ICH#NZdRC;W|diOPB3fC zTC>iqHz%5t%*o~ybE-Mbyv3Yu-fGS;Et8ou%~|GbbB;ORTxc%NOR20cFF$04A|1Jr zflTB5#z zpth);fII_i_>*5;Uhe}C6x}~JyQIWdTU$1&th}slO1G-YN`OaIH8w!%R$g3N>#Ma} z59^;hpschOKvV7T{<-~&D}3Vhi2k|$X8fB=yX4o{9TeIf1ZbQ6bMwo9aJg?tS!HR} zq}u$H5>AhIXtM#RjlUD5?5p6Ne*`wMCKvG^#9+@F;BZn^&3L$`XH{igzv9Z`F}|9i z(4TK|9W>1EpF60ks*aKGnbe-qQH+)_@&lvAOzOyJsiiO}li{}*`H_*Qnbg5@SjdC# zu*eRW|1^}2GGH3S&^d#aY|$O41ANsHWde~lwRJURm1BT-b~T{XlHxiTjV0|sozS)D zI&^)3Jy>7uF#AO%^syFQk8VJng`oP?*A>Imc_dYt5I)DW%$kgs4wb=`lA78 zAj(05P%avb@}PA-8iESYP&5n;M}=qv8i|U~&8QfSDl$F&b8Y$M)=eq*^((F&FZj1V z>snkg9%cdNqhDENZrM~H%!mEW;Ig{%#&=>GK|k#827wB~o7|EbpRba?;nx>W=GQm0 z$uILwf{%v`?pa3)E>w;xP$hg;1q*Hhs)6~o>a@FHm0VkzOoc%c<@9q!=Pe8m(*&OY3cCyS*wX=J!8TUUbZ&cLs-a% zu*mXQMZ5h2;B#^Zs)xUKqZ%s|MrT-02S$7!nz#WiK}*pxbU%6kEk`TRO7tLl2(3b^ ztuQOaYGI{X?X5}HH0y3_rM1R-*m~S5`U0kU3e3qmv>rNt7%hUokHLIAfi|Egf$JWX zeD#!qxNP=ejNN?Y<-nE43fDXsS;-Gf2O;x%vqQ(s+GQwNFw z7Ol=#S?4!ybv0GxeD=8k0j|UZgJw6pPP1aH1gnV^X@zN4QrLO;bMJ(IvO~=-63S`2 z3%!lD09WszchP(3ee?kgj;{^)k6R)b^JvjyQuaWEtSBqmBZU|CtuHAnExxg)7?jU8 z9v`D=Ye2I)??&6uCulqR6uSHj?La%xF0>oeGcX|WKkt}x$OoBQU0lMKZa0XI%d5r+ z>(|tZGaXi}6`!9wr51Fm$PBB4iMVKbcA~vNC=z{%_6ZV0#+KFjx~3wNTJbhh2hp}Q zz|RFt9Y#lNrmRHE%V`YdT?;BScgua??E$cbIPUCv&>gs%I6pc zl3l{>F@Iyz{Slpf7@b5vp`SUXMVv!yEDfK<6Gxd3gO11%dC_2snkH@{Z? zA#|^q28wr8qvB)4HEV-ptS>o^RDTdl0Npo`bQLQD#k@IMID5TT)Y zm1UE?+<^w^4{m~^{Gw`OwdSHKEU_mmSX#I#m)1?~+H|o0WP#X%IzfkVVuQTf@lL>v z`MYUYT$dYl3;(FE5u;AyqfT!eb(UD-9aH~()Tv;Ef=8VJ#wTg$paK27J-Cw zs@gKHfLzVEBjkz*nl)hb=vtpJ5`$r()>apT_o?G6&9)xgWI(H~Rg-ydRtGW8T5Ez; zqgoxUiNgHi8^QeI?(ja?{NkIyv_63QgZa$_W7^)T@|$0rgC?%SgK#b$jPtB4tBcjc z>T`*C#ogiWFh0Gw5RZVqJ6fGItFv`2EOSt*cHlp`N@b?C@}`6NJb-V;#kTpxqi_i> zh57NJ=kaLt0v-cKbT%FbB+GFHuEbTi8i%3txJFD4pt>Ft>dPh;m&3q8?A)o<`D!Y` zq4ll+_y%66Ykgf^Ri!X+X+>se|J;GTnzE|WvXb6lVQb(@n6IEVqT4`|?!NNkDZq13 zxBjWEwXO#pZ(?0%WkE0!Ellp*nO)9XH<%w-%|lg$P=0o4X`41}gxkjyW%|J!o`ff_ z$CL3C+uCq}3l6zRM}XyMd?zdoo`!E(k8cUs88Fs%gNqbe%(&&B@mXTVv-ym7Ei%LT zGS2i*c~-{%p7Ob3$`^o)FPd_zyBKpfkopZ)^P$~pd@#=!4)Jnq-Q#C#iD0WIXX{46 zR(cwkF`)@rpc4N}6YdvmtpLTln62J|tzMvtz*hbsUq#hK@L7Pi>}d}y!ga6!*Q53L zVf+Zb7QTEGKPIMa1AY=e1*-Zqeg<#A&*JAmBRKW~vzVsW6b@)~M8h#xR3*Z&}2F`=OoAKN5^A3I&zlY!F>-t7vCE-=~suKTNFR|f^ z)elx>AFIDrX!SQGtJI?*3#J5sJpPcc_s#HC5yXmk8~y}uM-})}{25@Q>1YauXa(=Y zyYO!OIsO7{{d&9yzXN7!1O5{4Lo@IJcy$OL24i&ue}#|YuK@%+0Z6!iu2@hdpvK(c z1BxF~R$4b!1bDz_eMMzaOYSxsh6*8%ve~?aWJx) z;xS`*`>Ohy5)m!*tg7i-RZ?6IxcpL*fh!ZPaAp6hN^voWtXox0rLV>>U;(W;CISXH zLth?15Jv^!VR2b$+t`IiR6|SEULWzXV69-YyJZp$m zVC7rQtzn@O`v*{=A9fOr!%h;Cl-&;c;P^5m&JVFZP#v$ z6{BhJ>|)|b6B4zaL^VP}L)OMgHt;feor z@u(;WVBjVsxdEk&u(^oz1B{CRtIbRc(sB)Hi8_NF5lq+$WPf)JX|Rw&cFn==M&hyU7Pj+EK4%+uMgv2NmjsR2sj$h z2HOFH%5mKjirTTgU-`&&jy94`OY2~_tRdrU< zkbG{4e6<15kL9B8*UsCnO=dgsC$&Kb#*^}Oq}(Q-2cDv8@?VuQ46>Nqfo7AtAQ>1L`9{pg)ty(;3|$aRJT-_IC$XRp(Xrg&ksU5V>81+{YMzI3R+y z)=bTmtr=h>ZndUq)->zR(C`WWbji)GoFYs!xgSkjLmnW@Ez4q7QGU1Xtsx3HWJYio zOR~vB+{uE2U57ujoh(^^caqM2H#^$zXv@heGK;JsYsorrwfo2#e26?kX2I_1Eb=%$ zN;Z%u@!RBS&_d3l?G&xW)^uxDQnrPVfT25XwvcAcvhIM7r(3hZE6ug$ScM)OS}-jY zbTqvKI2%9$t z?tqWprLf$~Mwj_&;Je-F~U-*o;0STgW?p*RjZIYAv*G zvxWuXwnhi?p>QBuld`+m4#YGAYe4u9D?SjEHl$x{^UhTR4E*Qh3%`M%2@!B;cq&+U z2|>6}7ch&qvGN<9FUh_~$i83`Dk6(+RTZPE8r-UFqYjXR>&d}@+kqJnjbOQPcWO5| zOpZK4js)ilxNYTqU13#z!&fCPB*(?-xQD~#dxZ%}<0w8g!-fqa90wC}kjGBs`^!g9 z;F*6UCt+dy3^}p_TtR*b#7}4*2f0->6~*NuPy(<0fVBj)`#$UL&|cT&Kp9@aMwMc2I&MDWwu18quL3vD{iA`lAl2tf30;4MH?K zE)uQmg>f0vLtT7wsZQNuav#*J)z(A8^kk#~XiM!NqLDOidSGt%QV-fhLunZB5RRUw z5s=oKfgU7lX%vm7F*KIOp?RUm z+~rOr{#dJ$yO{P%*uDA3o80+l`<*??c$%<|CfMO3NG-R{R}C531`VT$G-*9e3OGt| z!u}SQ8~;^&{AdGhDaOB+oBVZR{OKLR75Vd;8UHJ-N!vocRb-cFx<9+L-de-gmefT; zgHk(Oj&!D<^tFQYBb@Z3f^=F3py$srW%=Q7U_tYYYEYJmW<#1c*xft^>D{D}gR=X1 zIePcD=-0L7~ZtKre+FXmj&zVe?+0QKaWCb4qAOl6#A5i zLZ5_eGY^it*1!(cMZvKk$g>~m=>iAv^l^G7_&ECujvvJ0&gckVWN=P|p{BzjOhmKj z2s#q-=Pxikz$*G2Z6hzzVmb2$n+LG1M9XQ#8d?#+sr(x54=?Vz8oI8bwR9|W^rB@j+~0Z$dP-~9zo3&) z8#)D2MGz@4+|QpWqPL)lPn#y4PH&|%s6`o_NoUd7bPkHRqtS#17 z>nrO|>pa7hVTEBA!$2mC;U)~XVmO=O9t`)kiUNWBCD}B32k=)5aHxRZP4A)i;%;;a z&!$rX7{*)I5SG}4pf%io`M&sK8k-+A3`Vfra75MwQReb@pOHbvt zAtOud_)MGDk(&oUf=uNmxdVvs5)4Pz6Nx_3fZ^T-47b@z0-WK^FDvy`c|i_!5ZGRb z=B)TDkMYTdF+M{#(r00eo5UF35o7$&df)m$wcZVk@kKtyP4GTwjJJX)UWYMmfxquv zc8u);%E-sqQD|wp7-Cxb<%YNghWKv75I=??egvyAyS}vSisQS;GVn3cZG3Uk?etSI zl5LuG#QMYr&6zx11>rH^>s0=l145p*D2D9dC|pW+LQTVHx*M{Ek>~~bIogD8M$ghO za0%T*_tGzMIo(J1(*x){+D8x3!}JK60m}F_tl=5-80IPYe!j|jZmr=zuKYF*6dQRp zzS170WBA5}$SKz5)&Ue0;4u&OxOrm^aQTJeA_(59CI#}e)^-8KW@rD?CDg&wf;+6w ztmYnkr*#-|gHSUFD*q{Lg_$=sfE;^shHT{lau5jG4`Vz@f1*FrQ}h>lnslbWg0`L^ z*)Xo(=~)=zAM_kLPd}x9(|_RIdEmESC8WSA%Ss^CAvT=?S<-%0r5v?^VGv`1|3xwx zOvZpp;WuF-0&T&q^(&j~D;1wZ2r;;LjI|?l2J9?_LTLfAc3QgtGkjuwZtb=9?4)3Y zBrJhCNZeHiX0z7%(mG`A%eS{c{jfn&IBc+XbDSV%j<@bM)>ksVqPS*!piziu^o89B zumW!+81jq3Q&i2-Iu}DQc#}fut~GQQ>MW*E3P+j42GotU^E|cwy=wSHJ?-I)0WxdvT!nPnuU+RI4F5X3rWh7I^psQmXalP4lE@h$-riDZ`d@PY;CuWS>J+^9M-_Re*@Yc zq}G8+zd)@?wv=TnwbYYOyOhC|TIvh^92b-RwNSV30_xTu)NP=30#xk#{EltfdwWf7 zka|GWd1&IpQohtlDv*Xs!=&NX55Uq-)-To>>ny}Qmx?~XgH#m6fe$$NF^GecgE_H( zySgms>MFSU=b)=k<)ya!AD7n#T|NaaKOJ=WuX(Bei~97S%V)vmzXe_XdtUngqCPL^ z^4sC^KY}hlm)C(`emVWS+s0VZeM0~K;u!01TmLdRv}x}TT)?xW{@1`oT0z;xflEWE z@(*AJ5v7C&q7=aWm8ISR^>x+tb(iB1f@+R_rAIi241*a?W*FN%@-2u|*v#jyhNq|g zbzfh4lFo#_#J;`_fEgy%c|gDgZA*O<+m_Z=UylCse)=4g0DVc&mu>XN>1X{{@^8>t z7n64YdII{x1pNvy-8Glv;5|PFAKDzKf&)z?eKI-pPP4aTI3~XGUaz#B&JIT53_Ah0 zf#*F%IXhUi#cmf3HnHM9|j-+T!%H{uB8_bk2q3-GCXbq!HXd)chOu zZ~fH2v#Fbcx<`zj2Oenv(|H%tjRcSkX+e9_<8p*$2Olt*DQh<2C`h$29PM`syrijvt#O%< z@cd87HrdUSZL*1G%b|2Wps4wFvW=(67*2%xsaOk8dkkQAc-_RhGq*!VI}ydm(P-j& zIYy3^T@mhT#{V;h}gY4(pvhTp~bwc)?FO~fQA^SxE+23Hx{`&um?0JzzP=b@; z4p)#pPmF`>lOM8W-&L5PZVe^~w&J&U~|E1N!fJ-zKh6Vx5Tb1P}M9n$hDlgpZ+ z4SwQJ+r*&+0Q@f000it`)_<|P^7C}zg~WS7VgStkAm3=%Rvzme1o7Er$wT^@Cx7HO zZSs8pnJ|2lADZx}GF8w|6FWHn6`IKJ(M65WME($f@w@;uVYn|(SlnO-flva)bE%Oz z^<^dFdBLQY*HA+>fvE8vVTa3Y?X@LGl+VR+NOWM1SSFpg@X_{;l;IvZ=^9i+{$No7$B8?RrR&Lwh-)&sw%E24H#OnqxLU3 z7>6@3T8Hj%I}F^-;ju?MA~4!f41@hBhS84nkJb?mqjh-r2SKAfARlnV@X>+<;9t?@ zM++&yhS8>V5F2CmXj35>bxF#};f2vAHIBBFkG2GsXSacQ-T~FTfb8OQ(?xEA56^M6 zy<8lv17jL37R(rdQ!`-RVV_>W1MGUS7e>jeaI!Fm}BdT4|BFuN4j+o$(n zFKm-kLmA!0NLFxpou5ls%C?@36I?gd%F+v_Nb^YFNQJ~Z;KuU1A7eW-LFUg!P$LVUT&KE`v+ii55FtL z0IC`WkPboyo1B);fjLa`zm&=GjUF`HF+@ImS?0k9SHlvwS&tEQ-+oSgrCzQabyeQp zrRBcMv03D26BOI#v_`NACF=fpPPaFT)5MDW&)QHXAGs{6um{C(9T+2<+4$aLDxqk| z+Z(E{#uS%(`$1-_W{NPN{G`bhv!#xzhLu|5sCCrAN}Xu0)QN#{+{G|B{X1c$P718l zDSV|ugGm<@Lpr8|>HNxJ@zpw6*hnywi~VNSF$*#bj@gbmj=7F`j`@xS3{PQrI>U_N zISkKdc;O}Gk&cP*cQKz=w7~&vOcMX53a>a#ctyTX+fg{B)O5bcuI!Q>OC1o4IUaB< zx9e^hz6ChoJ29zH0FGcg22z%g`14hG2UgY8`J&w@F!U_yB6JA5D=w7h3;`i!-Z3o+{bF1ff>X+MgaGU}+ zce>Hd-NW77-Qd)7p|ZEQylsD99Y4o)kyF1&m)D0kP=v-wU=R0(QSz+W`M=}g+w0kM{SU( zN%M4xf(eJ<2PhWjW3;?ZuJB^P2Vvu{17~ zf0KmLQ$BW~Bp7}e;5LXNC;f6-Ag}`6uGk(Jem@G?eTEnF5n_0MGG%*dFe-zINQ!-!4vy=JCD4tJNa(FUd0iXwcJ;^i5 zz(3FDGyIf4p|6aSr~(-4Y3mTf&lC=X0)B5^b=&S$lPWJx>?;#s4@b#YYJo3?H(nu? zZ*!nb3Zf658R$QI0sZGjcB`+c1<>Xvb~y>~bT1T+DB#m=Av_PYBMiSFgb#&%T==%F z;KJuRD2hj*bVQjSC>@c%Qx?)_NRtE#M?_V~kecG^TA0^O$zA$cqVB_5r9m#U7GlKm z;z}PxDq=H9xsw*Jqs4YnpD?1Z@B~5(K9LBZ3;=_jYVVNAu|qpv$}$X&FmfE6mIVPt z%(V128SrtM?;38{g5KC=$jTCB=^ACJze>k{{?b=b4agRX$YEbgxnFr;t@41f9ChaV zg#M$azB(@Q`RdFD~~9TDvv3TD^DmJlqZ#^ zl&6(vl#R->%5%yl<$2`=t`B>SiY*Ri_wkw}1pD8<(oysm{xAM92g|bK4t9+^KQ}!zdl!MA4<*;%@`HJDq z41d7zR)%*lyocfa48s!omf;f&|IF|ihR-p4o)L)=jS+*9a7LmSiDx8TmkuHq%V5AQteHrP`$UsI0F*2Bud`1cw8OBHI4gG9xn?na#)@jNHY@J&fGP$Wlh`XJk1eD;ar+k=2Z>Wn?`gk1+BW zBTq2$q*b&Nia#QiZ`$rzrZ^Dm62~56rmkr!C zjOM&@OvMa;EC%u66$YV7d_^}5;v=y?1!DlH+m)Z9_CkomjX7-4SAsgiNf6b=IW~%+ z(zKuDpT1|i>-?d};L5K2cU}Be=WXlq@Q&WJEt6;CU zyRR0?L+n%FgyAm)V>>Tptc75#B`|i4%^2{sn=|(L1wvKZs_lTeG)7)v5awo(e{MqIHVBB}gM5Mx@d+B<3yN{PqC}uJ2a3}p$HIH@HfT<2I|Yw^ z7|<=`biWaFzq%}4P!`xgR*M^Ca+H%4``4fsf@qL(RdSPUQ%Bdw9*y;LD=c|RS-ONC4!5A;GGQwf8hjA zbAovTi{ZF%4xC-&i+Tyl%&+Dj1oeME^bgs~KSck(U8(;Eq5oA4{r}GUKg;_cJjhpC zm19>Ss}G~hJg5Sy3hMna=p6tD7*DXVe_pBgr=a&|8hZbW_x?BUeVAP!!3C33Y!BfD zSZB53j6Hl9MCfH8^eQ8i6C&tJgx&x`Zv_Yu41@>~!^nd>WaQZ85bAp{4A>VB9>#~z z`^Stx?gM(4uhjb|(7UKBV)zF}9K3f$^xmzidP+`-J%G=l_Y!y?#QR?8eIFxk(Yy1~ z-VX?!ItaZV7Q7P|BO$zZo%bFvreA|jfd@Lmb?U1!l#8n2_G#ttw+ssQ#(1yFfpTrG z1Sf=L=jQZAxJOBCz*Gbj{6}EsCq}{qGv<|;`30EywSgHAXC{<0Gg1^Ld2_1)i-BXw zxz?t64rPuk;U!CfFM>w@HxN9}NE1OY;tB*c(y(y(=p!5LW6XsVy~VZOp;h%>`#f-b zUDcQ|{6rem+*j5EG8FX16~J95|ClwWa!dVU$ zjtdfi79mls2_qkH0eqO(t-Pw%mosUE-|36D4FuzWAONLAK``MGf~v40T4KYPxjuOV zW6tO2Eb4qiO2vN-eYS)?uVJK_=rj3}K5aOowQ1~g3nM9kJ_ir0s;VgT^U7a0blU;C z&1B>n(QWg+7o#M4M(ZSI=USMZ>-p?pz-%oTY02m3>frgwhWY8n$bLRQ2YjffP|Q+L z%+U~*`APSLTh$1S^cSfGB-9JI0Qd+2El8;KmAU8#Tnyk`Ai$NtMH|jVTh7H$-ZePy z$#pqn0=?!zuR|DtjcVvM?aI9lgI)_oudqy^*L2=%2Jdx*=oMVk#4^yXoErl@kAj{7 z$HKlS^xW~vJ&%E&%S6w>2lSlDd(PrLgD2wo4%-4kpzj6f2#4e=OLKeyB2_?S0wa*o z2O`&9B5}W9>VU*VPC^j4o)fsiCgAB)Ur{ZBcwtb1NX|IG6#PJ%ucm=;?@IsSpKLh4 z+@KcIf%XhWU_TRRXJ0~_Yp^;%n+ddM3))syY}ygRF?j*Ac>5K@fd{WR)0&eH z^?t%bW!DZYFD|R(#}muj2fHG)Ls`og7pRMamKo#4c@H%C^&>@c8s4e z=-c?(h8Egl?X+?XL!8@_kuq2&R#riAX(^Q6jc-(FX!Hj(0(nBC@w`!&;ZPh4W4xpt z1bVPX%-g}%^ZQm0m=Jz$|H5{tw^J5usf<+lIiCbJqiRwEU-A*B%N`w=4*18#US!6W ziG3sgwvoMSWZ${W*El5ku+w8-TER$d;L^}i@UCF0U|$SUla+j5tdZD3XA}Dhn8$ki zilIJn?;zN(Y;1PO+0<@U#>k{V$6}(EyTiTf@Tg*a|TkJ0p|Nc@2uer33zwi|1 zzok!|y_`vQ`ZRF-h!G1WPP38*Wx##wJaxt6A;zy0={0WQ8Wq&p%sCLIISIIBWR{rb z>5VdI?#vTn7MnoU51Yc>3W**NGllk@} z^NKsW;7*h*Tsc$i9Oo>&AX7~iaFRSzZ65+|Jnl4fS{lzcLm{8=3C?Qggmumdc9sy5 zbM|>Uezu2Ox$(Jhr?QL8uoFT+^pFK+_)fkM*ECEAddN8yzIxCCD}FcsYGuP$Fc&lI znS$B4H=y92U<%^yM-3Nfi=A`0*%AwW30z>Q1sw13F}^k8OE|O{2}LHb!2|m{-T3|v zoTx7u?<;N8M)|1oNt;2K!*w=;BQLzBfr9+C^EtaM%*@07QA06Np!3Ft$DJ?R4Ig3T zQM=)=3SRFbc3K+S9do{Ew}Zhx?(YzeGQf>a#BNAq!|$B$+6`gg8|;RVX$xw4vBQSh z_!u+?Y!aCFr?~1o4!7$VC62_w{X5`bG=~d;>9CjBr>@~oo427^=zgt_dY;af_tO#1 zJyO29Q2vTecg&}?I8Xjo8$vDlw0w{*(ypOP=mLC7Z6Osn3+W8UTx|v&iB@Z+P@26I zt;D%t-p@j9(jw=duf?Tg?(GwLMy7`;uYMax}r^j61gSAw&-79tIIB}3(F5n85>qs-OPbv2#kYK6P2 zuc9UL5%qu?svLJ^$ls`@V;J;g&Ll0<)!Wra zJ}zas`k{xE6H+JjC&wJvJ*=0aUHNF0s{n6SKenE=QXxoSBto2y%Y`F=mvY1UUzRV8Y=V5ucrukotO!3^)RAOxOkLGGIYy5%PbLEs&&^KiSo zyDiwy0{{08Y;0H_MnLD6@q0UNuzq1Aff48e5+2~hu4DK^Zu;<776cfe3Negq6o>Ty zNo@sDTW5Hl0KNDMqsyzGP2j|2zd_+!glcKE`}lB`Zgo)ipsQYuyJnf;P4;+Wx~+r~ ztH8-Y*fAnJ7a_<7sw{Z}@$x0EG0g+9w03DUBrbQ|M$fqx+0oE0Mqc63(5rmh<#0F98c5cRh9CZa zCEWYohiV}*ZuOsdxsdv0C1DT1Rp43?7=mjxTm}MUgL<62|iqKnV}6KLWps|fZB;1)cA4)_VJ{{#2`hf4~9D$mvWILV+x zMy|K$X|9JZ%g%iW@y)RJLC_5F^}TBWJ@e!GrCh&3ej5A&dDsW9TpvL$mfKzb*(ldG z&@!GTinfXh`ax{U$=T|*1B$aLe`LHP$p>|=^zE$$l3 zcVcW=|Jo?)vv5CA^;LDbtDiba{a9V7&Cue(8zi_|xst&Gfr$Z&!3`Oh1+chaJ;5qs zFjX)wu=EZ#Ob0gg0X<%F}j+5#<-cet)b?Px7%v=Pt_JMb8t0!0DgFH$<95>3AF{#4h5cP zxLQGL;1@=8D|`>*g4XaYaNZpdPA7gnytDY#u0GKB0mnq(wutTreipfU<2-c=xJ-}8 zzq$B9wj3x-CmX@Ha{r&hKbd5`01g~VB}fbYHrN007C2r15_hp%xg(w`TJlw4_Xc0_ z`|XPBz?K6_c~)#v=kSd%?z(yR@c9N_gvq@>D8f|kEIfkJc8l;1VbyPhSI|G~^F!-N zq6P0Yz}yCY!LA141k8-+9O$bJUxC@$D7xcl=LbKDgJAyzOVDqQ040+wFpdCuegHti zhwFl~_0W4E^aZ@|X7CDD5k!N)Fz=Lq1Rk1qNse+h0o?$PIe>z|!fxarzs}(tjN^o@ zhKIQtPL#g`fxe0d(|K^1HQJS|#mfhjJZCddIVK;$ryO&jgr_$Yq%TMHc(Y?7S|NX{ zE(b;0MCYmpQQZoYJxad!#x=+S3k!*`MB0cKB(@4D7H|k#ktZj zbiaI<&UYn%(w=tARG5P>sGX2JyLax@zab{q0$_!AB*@8$LlZ{sumI3P|C2{-d|K+(AE!;s$r>jYAp z%du-0I4_*aVKQz4hM(&afNX%mI|W$m$hBu7SJvemRf1Ol>;_h_C)|JfEJy2Ld_eb3 z@skw*qsewqa=0Y`I2EoVfKvgKx8R@@v^oNAstUqy1-KbB>25fp4hH;XIJW#6SF~q@ z7Y57xKFVeWYHb->etwqx2HJRQKtl^)dQb zy-XjckJrof3cXUV(yR3edW~MI*Xi~8M17JzS)Za$)u-vV=+pIE^%-#QZl=%FXX&%` zIr?0Eo<3h+px>r1)EDWu>x=a}^gH#t^t<(Y^n3OD^dd)%W>6`TD^%wLP^_TRQ^;h&) z_1E;*^*8i4^|$oR`rG;z{T=;X{XPAC{R90&{UiNjeJfo5i4N%GBqKjD@-ri+7y(%W z0{E4YGmL=y{+*GtjQqjKIYz*7|Ha7PjKKE6c}5YVm{Gzg+@C~ZRA$t{sKThqsK%(1 zQ5T~jjOvWK88sL+8TBw4%4is);fzKw8p&uAMxz*wW;BM;SVrR*ZOUjoqX~?98BJs~ ziP2<6Qy6W==v9n1XS4;QEg8L<(Q6oO#b|3r+c4Ue(RPfcGMdI{I-?nk!gB^XFba8JB?ZIeIMsH-a7o)uy?ZfCzjP_-; zAEW&l9l+>7MspY)#Aq&~gBi_ZG@sESj219Dl+j^~4rjEG(GiS}6#W-53Z+aZg6`~) z24RnV1A{b(9Qdw=$oHhB2enD%wPE08`8^s^gTKgt`)zgsg8OI( zZyHAAZ&c44HS)$Ys)3=U3zFD>hhNx{c74hlLw!@w{Tfo?Z9|_>RUCAEhXS7S=1I9= zx{VW@3Zo6sf-5f=duk&~7fb_x(?G7{;8ge%d|ifMr}2*d!R&MlVl6Z1&J;j8xLH;s z1fs zqFtlBqkQh_rwvi|%KMdv}Nu8jIaur%64OO0j*yz0S zK7fo3P^ozWK*R%%*~%v8pIRwo$L7ihmDgM@sNdYJ7Aha0mCCcKsXpOs<|?3blrO2} zEL0DmS>WQAx!g)EosQ~xPHQbsXz^0Z{@fcvcIgi8$Gh-SN^ox+JyGuev%p&d)N9Ri zJrJ}bKuX~K!OoX+*VqSq^9wwm1*vGr0qg(|4|ooG0IZP5{VjK|j|g8qNECh^;FXx* zK}k4Aq6NGXlvG1LjYo7&o(GqpJQF-Ksk4BI0UV`G6D6PPc`yjIqPzezUqphH9J=vh z&(}CWRe5bF6p{k4JqxKfveW`x2jK_6!yNA3A>sjyD#}g)_RZ$bdjmils7fUhd4ldS z0UXu};0idR53fJvxila*jAIVK5D#$_!{ZsS$M!h^Ks0$`uuxiMZ&3c%nU28E{p zFSc@E0664bM(z^$2|VEIP(8{ER{?lHWh+nD0ThBX+%k?(A-oTR(p3&x}D-8;s6I7bDx~YIHNY8$FDk#*IcVqqot=xXI{i^fUS!1B`)2jxor{H3l1b zM!qq`C@_W^!;IlZp)tZ3X%rbZ8^y*bqr@mRe8y;Fj4{?IGsYR?jdG*Hs5GjKYGZ;? zW7HaTM!hl7m}E>grWjL=X~r$abmLZI20T`U88eMp#%yDbG1r)9%r_Pow;2nKMaJ#M zV&e|uPU9})ZsQ)~UgJJviLumJX54Q)U@SLQ7%Pnjjfad?#%g1YvDR2;tT!Gu9x)y@ z9y1;{o-j5TPa01dPaDq|8;xg;=ZsCp^TrFti;Vgh9nI(%M#nN*#^^Xk$1_^aXa%E{ zj8-vP&FBP1YZ$F%w2skwMkg{liP6c7PGNK^qth6@h0*DZ-pc36cQAS3A3dM~5*F}j4&rHn3P^nOMk zV01a7D;QnL=!1+t#ONwUS2MbX(Y1`OV{|>E4>S4*qmMHB7^9Cf`UImJ7=4n_rx<;j z(PtRl$mp|-KF8=LMxST&1x8`uFERQuqpvXfDxk45Tl0~J;LZ$j2>n5Yev6e^jk)cF?yWQ?-)J7==Y5N!03;Ro@DeV zMt^4X6r;Z|dYaK+89l@3Z;bxV=vhYpVDucLe=_5 zl7mU`AS{(h8k3w%axp1{Njj6jDV#|WOp0Vu6DCD5DVj+!Op0Yv z9Fv+dDV|9QO!6`*kx5BRN@h|DlbSK@?|b{-sJW_hsFgI(rf4_3_6<|F1= zcpTh==5`O(%qKj!hsiwnIu9o1&mMfc2M_V!dGMsQy=IOF-{8U39z54v?!l!Ve47bG zTAPc_yF9qN`Iq^Y2Vd{O8Rp#{+}C`{eAV1#KJUT(%u^oR-#lo34Ns=qX>Rl21?H3H zGakIigHz3|9^BJ|OFX!Pd4~tzYJOsVY(DG3`5sI?*x|ty=5Bb9-J|9==9lIsc(mLy zbBPBRnxA{{4D)xhxd#vMVC=yQ&DTA6y1CZ8--DCP%^p0)gDnqkZyqoo^WaSDJ5na90oZnXkc<`No<1J$S77Av_#!wfT+Y4^PC~;K2pvOb=E)c$WFM2M;x0Ha{~TFprv<9t@I_%})g~H0O%!z5RMY z5HK_s1>QiW&%DFDbB%eYxD9*nuJ&`#_&t^3=6um88MQ*GaL}bMJk%^7m7>w`=+3XS z)>>z6I6P)^vNjtYsQDB;HuDoG>p2RK#yszghT4F1=k@U5%Nw12;Ng`6;lY>r&Y{ji zc=%q>XEcijLRgneE8T{*6qt|jnD%V%A0xju32a~*g6;yNFqg+zoj35gDg3yBZ$ z!lNsjg|rB{I;3q#T1W;wuCgqoCS+R3^pLqB3qx)Xc`)R$kXJ*tguEN_e#l25TSIn- z>KOMq-2BAI=^yfp6e>;Tt%OI3r31R#u2+m)E!2C4` z%HP)y!^153qb!fZV=Unzmio`|*venwft6?VbM7YYMEBM1RCl_&y}P43(|xV`dUt1c zfqT09F850JBkpJ2Z@IU+_qzAF54aDxkGPMzzjl8MPWxB)Z{UjE;Bw=^wKfB{dNsJt zF5n`EfwQXw_q70A)a~G&?gH2J063Y~;X#xiz#}NP!UHG2gvUpof=5T5F@A^VvbaqT zEVVdT)g9qcjs4&ejHBU^iqqktiFd-vd)nLxn!U+~J6dB%9kJmWnTo+{4-&qU8O&m7MKo)w-4J*zxxJWqRG^L*g> z$aBbZ#BTxgTf=+M~ErlIkn-q57bPNBm?M}!uI7KfIE`a;KqP6%BS`gG{# z&~2e#gnkoxI`r?*^IL*H5jREjix?7dbHu2K84)aER>Yi$xe@atZi`qQ@p;6ah%Y1d zM;wee9Pw4e*Ad@G{2K9FWb?@Ok=c=bBJ(3lB7Ko#BFiGjM^;2uMNWvUjjWHH6nR_Z zJ&_MYu84dva#iG-$d4m;M;?m&F7o@xA0vN?JQaC5@=WCKk$*(~75PsSrHQjiNE3IH zp-pO=+|guplP8;OZE`G1i;9d&ifR*eeN@+|?oqv?Zi?y~l@pa4RS-2SsxWF~)Xh<& zqDrGGqHc|{qGm?Tj#?hIF6zmsSEJsEdOzyJsE?zLNBtU&qeG&@qZ6X9j&2p*COSPj zGrCiB=jiO{kAB4#MsHPQ)6$5 zWwEnjABcS<_LI+NZir5AL7o${n<3CX-w0&rtwV^nkF_)ZhCFg!lome z-rRIl)6%A+n~rT-+w{(+cQ?Ja>5`^Po8I4adDBfze~g#oW8z!IcZ|=9zc&8*_#5K8 z#CMJF9^W&*SA6gIo8tS$4~ox^FN!aXA00n7eq8*7_z&WD$A1yOH-2CI;rQ?3PsINa ze=`2(_+R3GjsGqFZ2YOsD$il^m5YMNuMU|P5L_NWU?z+ zPd1W0$)U;N$&txzlLsf~Cl@3SOD;?vnOu}yoIEr75FR#-@x*sY{uj zG9zVK%EpveQZ}b-NqINrgOra_j;8#Wawg^Xls{7bO!+(Id^6mPHq)AgHfz$XS+g6O zb!pbMS@&i)HtXH&re^(`jcj&vvr)}_|F5RAeskhrpmlLrY=I($(o$%$@nqxK&Bk}) zw(;yvluTwP8!|&iaHqJtyStX+QgjQ&i)(Qy@L)%AtL3>5}AMGve9qm8bN7^Ua7kV9f z0lhiBCA}5BEB$9Woz9@M=vsOuy%)U?y&ru5eGq*JeJXtseF^;?A&Kk;^!CKDRz}n3^!Fs@Y#CpPd#(K_r!Ft7R#;#;%**P}G z&a(+N#qP!K!|ul(z#hmR$sW!AmHiug7kdwTANv6N5c@FuDEmD7BKs2i3i~$uG5aa| z4W}-rKBpn4F{gmjjMIWs$Wd@gIb|F*N6XQ3$~i`knd9J4oZg(ioc^4FoWY!-oZ*}i zoN=7(oE@Bd@W=5d@F(-9@Tc)-@;C5L z^Uw0n^Dpu*^RMx5@Sh5r2$~9-3kn6T1Z@QE1U!LL;1+lUK0#1WDF6lC1%m}c1;Yg+ z1)~IG1mgwE1xE$P1+{{cg42R?f(wG{g8u{`1)q!S6xS`TU)-qpr{ZvNRdJ*^UYsaS z6{m}l;%sq`Vyrk{Ocf6*9#cHNcvA7y;u*!Wi{}tB@vS2w6grP$^UkbwYzMD@28PAt5A%y@h>+Glg@6^Mnh8i-k*t>x3JG zyM=p&H-)!_cZK(a4~36}PehGH1)^r6mZCyYYf)PfUj&N~QH>}kLPdEIA?hXSE9xg2 zC>kspE*dYIC7LT*AX+S1CR!<4Em|+yEZQz^E-nHR2uOo#LzF>*AZ@+v2~) z_rwn*^(74@jU`Pb%_J=(tt3o|MPidUBrb_Z;+F&^-6ex1LnXr{BPF9GV2|-qOC(snW&L zUD7?${nCTd!_s5Y6VgAV*QK|lcck~E52P<-&1HqMHnMiI?_}T0ew1~U(PRu6TgHiotOBa?dE?ru>ymVFR+S2u< z8%xh9>na;4zk+1S7Rpx2Zt8mtY*X3RvR}(~mhCFrQ?|eCQrY{m4`rXqzNqS|8mJnn zI;%=lWh#wIuQI3rm06WgjZlqJjZuwLO;Al%O;Jr#ZB}hl?NIGf?N;qo9Z+3SeNop@ z*Hbr8H&Pd|CA5A~a0L>uH5Y2GSNX=-?Sj_^>Zp}W; zLCs;!5zR48t>&J#K-)~)LR+Y9t!=Aqr|qDXXyw{ctxBubYPAL}s2!jkq#dFirX8Uj ztsSdfsy(3nU3*k}LR+gnsXeWIsB5BYs%x%mscWrkt81@g>5Mvy&aQLm+&YiWugmGC z>Za>v>SpWa=@#l1>6Yl0=?>}+>yGJab${qi>CWh$=%sqOzErQ$YxFw3UJvNadaK^1 z_vr)rVfqpJ(fYCa@%l;nDf(&pnfhh=mHO5Cb^4w9L;Az|Q~GoIi~7s@tA_f9Muq}I zGeZkQD?=MYTSEs!k-=av8Y~98!C`P2Jcb&>IKyni9K(FW3d1VHYQql00mBKyZNq=% z4a&Qgv&#kL`f^*jr#w~;mFLPomVW{20u6x1KvSRv&DbAb84B48=70$2^K12zI%fbGCvqsS;R%8gp1-e@x>jNOe{BW@gPoMT*RTw`2s++;j!ykNX! zykfj&ykWd$d}I7=5A)1nP*m*OU*X3!|XPD z%>grRrp$fJ{mcW*gUmzB)6EOa`^*Q-XU*r$f0?hCubV$x>R1|Dnpm1zT38A#tt~%T zx>ytzi^XPfS}H6)3u)1P>W8EhG98E% z^2qYa+SJ;?+R6HZ^(U*&T5dI2EmphLX?0s8*0?okg{+9R#!6WGSo>K=S;tx@SSMSz zShrh$v+lC)weGhbv>vmbu%5GCv0k%2vOcx`V|`_7V{2#o&eqBHgRP6LtF6e!v*(g7JD3i(gXa)9gbuAk z@31*49iRhoWF4p@@0jYC;h621>zMCY=veI7=eXr~=6Ko!gu{oV%RYoHw0! zoPRs-J0Ch9JO6QhbTx4`bG3A}cF9~Nt}>U}rE?ivfXn0ZyMnGt7vzFnLtGPFlU>tX zGhKUJ`(1}zhh4{9CtQEHF1jwc?ztYip17X7+qm1gzjJqT|KRT8?&=n}g>JQ5=Pq}f z+*vp3&btYBFLxhzKle2E4EIv^3ioRFI`=8}8TWbjMfYX*RrhuGOZV%FHWghex>e9C zm=%@^dxfi_qQX}Zs0dYH75R!06*DVlSInzeSh1vHZN>VEO%;18PE?$$xKi=bQ`b}9 z)5ufcY3^y~De^Eq91q_k^ptvR9*4*6@p=NDs0a1*^bnq2p1z);o~fSco>`u`o&}!u zo_(H!p2MDFo?6cZ&wbBB&lAsc&r8n-Z!>QTZ!7P&-uB*~y%Mk7Tk2JLwO+F~?5*-f zy$Ns1oAVCx4)G56j`WW4&hW1EuJNw-Zt`yR?)27rPkK*#&v`F+pLsuj)uz_>eTAfa zt$ba5Kl_S&EFae=@)>+apT%eQIekH2wXepP^Y!%MzCpf8zNx+$zS+LHzLmb;e7k&m zeFuEM`)YmHd^de}eD{10{SE!?{T=PP)~Kk4u7@8_TF zU*ccxU*%ux-{3#(Kj**bzwE!_zvjQ`e;249XcQ<2Gz+v0v<|cla0B5$WuPh$4Zr~; zFd{HIFfK4LFexx4Fg>t7a4v8m@K@k+;9B5j;8x&H;9lT;uprnxSQu;*Y!@sFvVz>8 zASendgZdy4GzV=#M=%rY5yXOckO)%2KEcVsEx~QUUxU8|cL(7j7SBgxO(UxHv2hmxoPZYuFKXhZEsc7!GH` zJ;EcxGsAPj^TUh6OT$~jzlV>8PlQi~PlvCCpM_t9Ux(j@-&fYJY+Ko(vQy;`l|NN- zD^-=+N<*cw(oz|%L@V=^WM%KlzLnD}7gTMp+EKN$YERYvszX&rs*Y9FR-LRmU3ISN zLe-_JD^=I3ZdTo?`n&2u)#IvXRWGVuRlTYDx9Y#Dk5ym5I$(XU5m*2=16zWvz&2o8 zuszrj>30kS|Y$Ona>1eAlNpbFH22G9taK^y1!S&!Ka0|E{ z{0-aPRM%jpQOdBSRy< zL`Fr%M8-#^L>5QZMAk<(MYcqCN6tkqMlMILMQ%p!MD9f%MxI2TM_xw$7kL})6lF#^ zQC?IK6-LETX;c;sMk~L9v$1G0nu?~QgQ7#CE268TYoqI<8>5?}Tcg{eH=?(re@7og zA4Q);pGE(PzKVW`HH)>3wT^uoYai

l$OnI5A#K6HCS57!s?A^@yRdp0RvvW^7Ju zUTi^ZQEW+US!{W1OYB=!+7I(tN6F^_VMrHUE}Py zG_Hs%rfWW0C0Z@hneV0>_VSbSZ4V|+_|dwfTHXMA^jZ~Q>~ar{~Q zMf`RAP5j^Z`}l|W=S00kvqXzT`-C7NN=OrmgfgK{=n~}#Q^J~XB-{ya!k-wJ7?K#4 z_$4tSF)A@8F)lGa@oQpdVs~P1VqfAw;!xsn;z;73#H+-c#Jj|QiI0iT$#0VNl8uwC zl5LXTCySD-BsVEYijvZ#JQ+`RPo|SdvL@Lhi6(m{iR6Ifh~)U>q~z4(jO483!Q|oO zv1D!XWb)7CndG_T#pKQ8?d0R+>*U+y`{c*um+p1C7k2-?JFPpbyC`Kz*;0;_JLOIJ zQ=wF4Dw2w&k|`(!r!rp!bGcN{6p^A*eNz2X15-m%!&1MbMyAH3#-%2vCa0#QW~OGR z=B5^;7NwS?mZestR;SjbHl{YGwxxEYcBb~E_N5M{4yTT#YE!3DXHw@=f2A&`uBC3K zZl~_1?x!B5o}`|oUZh^9-lpECKBPWD-$3=C22f+D0BR1kgjz#wq4rQm=zHi#=qIQf zM1vR*3*tfoNC-(F8B_u(AvL6f${`bEg&dF@@*CunN|~ z2G|IjVH@m(D_|cSgu^fhN8tqA9ZtgtoP|-iCyc`++#Bu(4}^!n!{L$eXm~6<9-ahG zfv3Z>;JNU8coDo5UJkE>*TC!Hjqql8E4&^44c-Osf%m}&;luDTxE4MIpMlT87vanB zHTWic2Yyn0rTTjHt?Ikg_p2XOKdt_!`c?It>UY&2sy`!jkorg?qyTA-6e4YqcF1?g z_sEY(SA>Qz5H`X?iV-m)LrRb`M1$xN05Kyr#EDcOJ|u`#A`v8xbVt$%f@BdC$s;7v z8|jA(M1~;4k&(z4WIQqnnTpInW+U^Eg~$?QIkE~_i)=tPBioQ2$S!0rasc@qIf|S> zP9mp~bI3*HGI9;MiQGZ%ArFx!$aCZ+@;~HXodDE$1)c)cQa2j z?=v52>ejTZ=}^|-Q&yv{vDEl$qBZdvq^72(Z_VhM=`{;#*4AvV`Mu_B&Gnkc zHUHLp%ob$7%hIyNSxwfK4P>EgK07!&E;}hZJ3BYKI=dr#B>QLfboN~KTK0POR`yYD zY;JsRQf_K)Ms9X)Zf-$tac)^|MQ(L&U2bD;OKy8^M{Z|scWz(qK<@Y4(cJM|ZSGX= zOzwQ{V(wDzO72?jX6{bzUhYBeaqemEpWLh5o7}tHhumkh4q6{=gchL9(L%H}+7|7A zc0xO&UC?eQ4P~Hgl#2>bAu2)TXbD<|YEV52pk~yDI?;-+Myw!OiAK;EnnWSA8qJ_t z6h(WY1lkMji}ptcp+nK(=ty)7Iv$;fPC=)kGtoKdJai$t1YM4F*?S?*ccBh#>AKmE5XVz4W`Ec%#7JEC+5bySO5!Ql~@Fe zW8JYdhG1C?#qt=5^}_mM1F*r^Fl+=i8XJdA#HL`=v02z$Yyq|iTZ*l~R%7e1jo21! zJGKMch3&=mV~4QA*fFdYJBj^?oyD%^2jmCmhvi4)N9V`oC+4T*r{`zo=jIpW7w4Dd zSLWB`*XK9ox8{G%@67MX@6R8~AITrj|B?SQe>Q(1e<^=8eT;C zx8p9{gZuFiUWG^T1pal0jA!s3IELdmh4;bxDy zDZT<?)gKa3y4Yw=U~8T>r{7k&l5j^D!X;`i}K_*48J{1yHN ze}{j-KNEF``a~n5fM`w>5^acf#COE^#E(Q*f<`b1Ho+r`2{9ofN{BK-L+A;BFcUVy zNmLL%B1lvc5h6}>C(;B$WC@hW6C}}_=tm4Bh7iMvk;E8cJTZxwO3WZ;6Z43L#1djT zv5HtrY#=rh+lU>+E@CfnfcTv_N}M205~qoC#6{vVagDf1+#&7}4~ZwlbK)iOns`gR zCq59L$#2MdU(c}{lTFDMWFgsxY)5t=JCU8qAIYD{ZX}H?B3UGdw z9cdr|(nMNG2k9m~q@N6tm1KmBkqI(IrpaouhRl%|iIXJRi|j-8BL|X$$zkL#oUA2J zl7EtC$@Ao2A zHdH&R1J#N8f%=K+M$st-#iF>BfD%#?N=7NDQc6W>DLqwA87T{8qnwnR@=!i1NQJ2? zDniAmBn440m7#i27?r0;su$Il8bA%AhET((U#OAPXlfiak(x|RrKVFesX5d - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - net.sourceforge.SheepShaverPrefs - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0.1 - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.h b/SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.h deleted file mode 100644 index a69834bd..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * PrefsEditor.h - Preferences editing in Cocoa on Mac OS X - * - * Copyright (C) 2006-2007 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -@interface PrefsEditor : NSObject -{ - IBOutlet NSWindow *window; - IBOutlet NSView *diskSaveSize; - IBOutlet NSTextField *diskSaveSizeField; - NSMutableArray *diskArray; - - // Setup - IBOutlet NSTableView *disks; - IBOutlet NSComboBox *bootFrom; - IBOutlet NSButton *disableCdrom; - IBOutlet NSTextField *ramSize; - IBOutlet NSStepper *ramSizeStepper; - IBOutlet NSTextField *romFile; - IBOutlet NSTextField *unixRoot; - // Audio/Video - IBOutlet NSPopUpButton *videoType; - IBOutlet NSPopUpButton *refreshRate; - IBOutlet NSComboBox *width; - IBOutlet NSComboBox *height; - IBOutlet NSButton *qdAccel; - IBOutlet NSButton *disableSound; - IBOutlet NSTextField *outDevice; - IBOutlet NSTextField *mixDevice; - // Keyboard/Mouse - IBOutlet NSButton *useRawKeyCodes; - IBOutlet NSTextField *rawKeyCodes; - IBOutlet NSPopUpButton *mouseWheel; - IBOutlet NSTextField *scrollLines; - IBOutlet NSStepper *scrollLinesStepper; - // CPU/Misc - IBOutlet NSButton *ignoreIllegalMemoryAccesses; - IBOutlet NSButton *dontUseCPUWhenIdle; - IBOutlet NSButton *enableJIT; - IBOutlet NSButton *enable68kDREmulator; - IBOutlet NSTextField *modemPort; - IBOutlet NSTextField *printerPort; - IBOutlet NSTextField *ethernetInterface; -} -- (id) init; -- (IBAction) addDisk:(id)sender; -- (IBAction) removeDisk:(id)sender; -- (IBAction) createDisk:(id)sender; -- (IBAction) useRawKeyCodesClicked:(id)sender; -- (IBAction) browseForROMFileClicked:(id)sender; -- (void) windowWillClose: (NSNotification *) aNotification; -- (void) dealloc; -@end diff --git a/SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.mm b/SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.mm deleted file mode 100644 index 29b48305..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/PrefsEditor.mm +++ /dev/null @@ -1,347 +0,0 @@ -/* - * PrefsEditor.m - Preferences editing in Cocoa on Mac OS X - * - * Copyright (C) 2006-2007 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import "PrefsEditor.h" - -#import "sysdeps.h" -#import "prefs.h" - -const int CDROMRefNum = -62; // RefNum of driver - -#ifdef STANDALONE_PREFS -void prefs_init() -{ -} - -void prefs_exit() -{ -} -#endif - -@implementation PrefsEditor - -- (id) init -{ - self = [super init]; - -#ifdef STANDALONE_PREFS - AddPrefsDefaults(); - AddPlatformPrefsDefaults(); - - // Load preferences from settings file - LoadPrefs(NULL); - chdir([[[NSBundle mainBundle] bundlePath] UTF8String]); - chdir(".."); -#endif - - return self; -} - -- (int)numberOfRowsInTableView:(NSTableView *)aTable -{ - return [diskArray count]; -} - -- (id)tableView:(NSTableView *)aTable objectValueForTableColumn:(NSTableColumn *)aCol row:(int)aRow -{ - return [diskArray objectAtIndex: aRow]; -} - -NSString *getStringFromPrefs(const char *key) -{ - const char *value = PrefsFindString(key); - if (value == NULL) - return @""; - return [NSString stringWithCString: value]; -} - -- (void) awakeFromNib -{ - diskArray = [[NSMutableArray alloc] init]; - - const char *dsk; - int index = 0; - while ((dsk = PrefsFindString("disk", index++)) != NULL) - [diskArray addObject: [NSString stringWithCString: dsk ]]; - - [disks setDataSource: self]; - [disks reloadData]; - - int bootdriver = PrefsFindInt32("bootdriver"), active = 0; - switch (bootdriver) { - case 0: active = 0; break; - case CDROMRefNum: active = 1; break; - } - [bootFrom selectItemAtIndex: active ]; - - [romFile setStringValue: getStringFromPrefs("rom") ]; - [unixRoot setStringValue: getStringFromPrefs("extfs") ]; - [disableCdrom setIntValue: PrefsFindBool("nocdrom") ]; - [ramSize setIntValue: PrefsFindInt32("ramsize") / (1024*1024) ]; - [ramSizeStepper setIntValue: PrefsFindInt32("ramsize") / (1024*1024) ]; - - int display_type = 0; - int dis_width = 640; - int dis_height = 480; - - const char *str = PrefsFindString("screen"); - if (str != NULL) { - if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2) - display_type = 0; - else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2) - display_type = 1; - } - - [videoType selectItemAtIndex: display_type ]; - [width setIntValue: dis_width ]; - [height setIntValue: dis_height ]; - - int frameskip = PrefsFindInt32("frameskip"); - int item = -1; - switch (frameskip) { - case 12: item = 0; break; - case 8: item = 1; break; - case 6: item = 2; break; - case 4: item = 3; break; - case 2: item = 4; break; - case 1: item = 5; break; - case 0: item = 6; break; - } - if (item >= 0) - [refreshRate selectItemAtIndex: item ]; - - [qdAccel setIntValue: PrefsFindBool("gfxaccel") ]; - - [disableSound setIntValue: PrefsFindBool("nosound") ]; - [outDevice setStringValue: getStringFromPrefs("dsp") ]; - [mixDevice setStringValue: getStringFromPrefs("mixer") ]; - - [useRawKeyCodes setIntValue: PrefsFindBool("keycodes") ]; - [rawKeyCodes setStringValue: getStringFromPrefs("keycodefile") ]; - [rawKeyCodes setEnabled:[useRawKeyCodes intValue]]; - - int wheelmode = PrefsFindInt32("mousewheelmode"), wheel = 0; - switch (wheelmode) { - case 0: wheel = 0; break; - case 1: wheel = 1; break; - } - [mouseWheel selectItemAtIndex: wheel ]; - - [scrollLines setIntValue: PrefsFindInt32("mousewheellines") ]; - [scrollLinesStepper setIntValue: PrefsFindInt32("mousewheellines") ]; - - [ignoreIllegalMemoryAccesses setIntValue: PrefsFindBool("ignoresegv") ]; - [dontUseCPUWhenIdle setIntValue: PrefsFindBool("idlewait") ]; - [enableJIT setIntValue: PrefsFindBool("jit") ]; - [enable68kDREmulator setIntValue: PrefsFindBool("jit68k") ]; - - [modemPort setStringValue: getStringFromPrefs("seriala") ]; - [printerPort setStringValue: getStringFromPrefs("serialb") ]; - [ethernetInterface setStringValue: getStringFromPrefs("ether") ]; -} - -- (IBAction) addDisk:(id)sender -{ - NSOpenPanel *open = [NSOpenPanel openPanel]; - [open setCanChooseDirectories:NO]; - [open setAllowsMultipleSelection:NO]; - [open beginSheetForDirectory: @"" - file: @"Unknown" - modalForWindow: window - modalDelegate: self - didEndSelector: @selector(_addDiskEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _addDiskEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - char cwd[1024], filename[1024]; - int cwdlen; - strlcpy(filename, [[open filename] UTF8String], sizeof(filename)); - getcwd(cwd, sizeof(cwd)); - cwdlen = strlen(cwd); - if (!strncmp(cwd, filename, cwdlen)) { - if (cwdlen >= 0 && cwd[cwdlen-1] != '/') - cwdlen++; - [diskArray addObject: [NSString stringWithCString: filename + cwdlen ]]; - } else { - [diskArray addObject: [open filename]]; - } - [disks reloadData]; - } - [(NSData *)theContextInfo release]; -} - -- (IBAction) removeDisk:(id)sender -{ - int selectedRow = [disks selectedRow]; - if (selectedRow >= 0) { - [diskArray removeObjectAtIndex: selectedRow]; - [disks reloadData]; - } -} - -- (IBAction) createDisk:(id)sender -{ - NSSavePanel *save = [NSSavePanel savePanel]; - [save setAccessoryView: diskSaveSize]; - [save beginSheetForDirectory: @"" - file: @"New.dsk" - modalForWindow: window - modalDelegate: self - didEndSelector: @selector(_createDiskEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _createDiskEnd: (NSSavePanel *) save returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - int size = [diskSaveSizeField intValue]; - if (size >= 0 && size <= 10000) { - char cmd[1024]; - snprintf(cmd, sizeof(cmd), "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", [[save filename] UTF8String], [diskSaveSizeField intValue]); - int ret = system(cmd); - if (ret == 0) { - char cwd[1024], filename[1024]; - int cwdlen; - strlcpy(filename, [[save filename] UTF8String], sizeof(filename)); - getcwd(cwd, sizeof(cwd)); - cwdlen = strlen(cwd); - if (!strncmp(cwd, filename, cwdlen)) { - if (cwdlen >= 0 && cwd[cwdlen-1] != '/') - cwdlen++; - [diskArray addObject: [NSString stringWithCString: filename + cwdlen ]]; - } else { - [diskArray addObject: [save filename]]; - } - [disks reloadData]; - } - } - } - [(NSData *)theContextInfo release]; -} - -- (IBAction) useRawKeyCodesClicked:(id)sender -{ - [rawKeyCodes setEnabled:[useRawKeyCodes intValue]]; -} - -- (IBAction) browseForROMFileClicked:(id)sender -{ - NSOpenPanel *open = [NSOpenPanel openPanel]; - NSString *dir = @""; - NSString *file = [romFile stringValue]; - [open setCanChooseDirectories:NO]; - [open setAllowsMultipleSelection:NO]; - [open beginSheetForDirectory: dir - file: file - modalForWindow: window - modalDelegate: self - didEndSelector: @selector(_browseForROMFileEnd: returnCode: contextInfo:) - contextInfo: nil]; -} - -- (void) _browseForROMFileEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo -{ - if (theReturnCode == NSOKButton) { - char cwd[1024], filename[1024]; - int cwdlen; - strlcpy(filename, [[open filename] UTF8String], sizeof(filename)); - getcwd(cwd, sizeof(cwd)); - cwdlen = strlen(cwd); - if (!strncmp(cwd, filename, cwdlen)) { - if (cwdlen >= 0 && cwd[cwdlen-1] != '/') - cwdlen++; - [romFile setStringValue: [NSString stringWithCString: filename + cwdlen ]]; - } else { - [romFile setStringValue: [open filename]]; - } - } - [(NSData *)theContextInfo release]; -} - -- (void) windowWillClose: (NSNotification *) aNotification; -{ - while (PrefsFindString("disk")) - PrefsRemoveItem("disk"); - - for (int i = 0; i < [diskArray count]; i++) { - PrefsAddString("disk", [[diskArray objectAtIndex:i] UTF8String]); - } - PrefsReplaceInt32("bootdriver", ([bootFrom indexOfSelectedItem] == 1 ? CDROMRefNum : 0)); - PrefsReplaceString("rom", [[romFile stringValue] UTF8String]); - PrefsReplaceString("extfs", [[unixRoot stringValue] UTF8String]); - PrefsReplaceBool("nocdrom", [disableCdrom intValue]); - PrefsReplaceInt32("ramsize", [ramSize intValue] << 20); - - char pref[256]; - snprintf(pref, sizeof(pref), "%s/%d/%d", [videoType indexOfSelectedItem] == 0 ? "win" : "dga", [width intValue], [height intValue]); - PrefsReplaceString("screen", pref); - - int rate = 8; - switch ([refreshRate indexOfSelectedItem]) { - case 0: rate = 12; break; - case 1: rate = 8; break; - case 2: rate = 6; break; - case 3: rate = 4; break; - case 4: rate = 2; break; - case 5: rate = 1; break; - case 6: rate = 0; break; - } - PrefsReplaceInt32("frameskip", rate); - PrefsReplaceBool("gfxaccel", [qdAccel intValue]); - - PrefsReplaceBool("nosound", [disableSound intValue]); - PrefsReplaceString("dsp", [[outDevice stringValue] UTF8String]); - PrefsReplaceString("mixer", [[mixDevice stringValue] UTF8String]); - - PrefsReplaceBool("keycodes", [useRawKeyCodes intValue]); - PrefsReplaceString("keycodefile", [[rawKeyCodes stringValue] UTF8String]); - - PrefsReplaceInt32("mousewheelmode", [mouseWheel indexOfSelectedItem]); - PrefsReplaceInt32("mousewheellines", [scrollLines intValue]); - - PrefsReplaceBool("ignoresegv", [ignoreIllegalMemoryAccesses intValue]); - PrefsReplaceBool("idlewait", [dontUseCPUWhenIdle intValue]); - PrefsReplaceBool("jit", [enableJIT intValue]); - PrefsReplaceBool("jit68k", [enable68kDREmulator intValue]); - - PrefsReplaceString("seriala", [[modemPort stringValue] UTF8String]); - PrefsReplaceString("serialb", [[printerPort stringValue] UTF8String]); - PrefsReplaceString("ether", [[ethernetInterface stringValue] UTF8String]); - - SavePrefs(); - -#ifdef STANDALONE_PREFS - PrefsExit(); - exit(0); -#else - [NSApp stopModal]; -#endif -} - -- (void) dealloc -{ - [super dealloc]; -} - -@end - diff --git a/SheepShaver/src/MacOSX/PrefsEditor/SheepShaverPrefs.xcodeproj/project.pbxproj b/SheepShaver/src/MacOSX/PrefsEditor/SheepShaverPrefs.xcodeproj/project.pbxproj deleted file mode 100644 index 92ed7a0e..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/SheepShaverPrefs.xcodeproj/project.pbxproj +++ /dev/null @@ -1,309 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 42; - objects = { - -/* Begin PBXBuildFile section */ - 084186B10B3A0515004B1F63 /* PrefsEditor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 084186B00B3A0515004B1F63 /* PrefsEditor.mm */; }; - 08DC90BD0B67074C00799A45 /* prefs_items.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08DC90BC0B67074C00799A45 /* prefs_items.cpp */; }; - 08DC90BF0B67075D00799A45 /* prefs_unix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08DC90BE0B67075D00799A45 /* prefs_unix.cpp */; }; - 08DC90C10B67077300799A45 /* prefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08DC90C00B67077300799A45 /* prefs.cpp */; }; - 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; }; - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; - 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 084186AF0B3A0515004B1F63 /* PrefsEditor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PrefsEditor.h; sourceTree = ""; }; - 084186B00B3A0515004B1F63 /* PrefsEditor.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = PrefsEditor.mm; sourceTree = ""; }; - 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; - 08DC90BC0B67074C00799A45 /* prefs_items.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = prefs_items.cpp; path = ../../prefs_items.cpp; sourceTree = SOURCE_ROOT; }; - 08DC90BE0B67075D00799A45 /* prefs_unix.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = prefs_unix.cpp; path = ../../Unix/prefs_unix.cpp; sourceTree = SOURCE_ROOT; }; - 08DC90C00B67077300799A45 /* prefs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = prefs.cpp; path = ../../prefs.cpp; sourceTree = SOURCE_ROOT; }; - 08DC90C20B67078300799A45 /* prefs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = prefs.h; path = ../../include/prefs.h; sourceTree = SOURCE_ROOT; }; - 08DC90C40B67079800799A45 /* sys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sys.h; path = ../../include/sys.h; sourceTree = SOURCE_ROOT; }; - 08DC90C50B6707AC00799A45 /* user_strings_unix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = user_strings_unix.h; path = ../../Unix/user_strings_unix.h; sourceTree = SOURCE_ROOT; }; - 08DC90C60B6707B400799A45 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../../Unix/config.h; sourceTree = SOURCE_ROOT; }; - 08DC90C70B6707BE00799A45 /* sysdeps.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sysdeps.h; path = ../../Unix/sysdeps.h; sourceTree = SOURCE_ROOT; }; - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = ""; }; - 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; - 32CA4F630368D1EE00C91783 /* SheepShaverPrefs_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SheepShaverPrefs_Prefix.pch; sourceTree = ""; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; - 8D1107320486CEB800E47090 /* SheepShaverPrefs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SheepShaverPrefs.app; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 8D11072E0486CEB800E47090 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 080E96DDFE201D6D7F000001 /* Classes */ = { - isa = PBXGroup; - children = ( - ); - name = Classes; - sourceTree = ""; - }; - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { - isa = PBXGroup; - children = ( - 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, - ); - name = "Linked Frameworks"; - sourceTree = ""; - }; - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - 29B97324FDCFA39411CA2CEA /* AppKit.framework */, - 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, - 29B97325FDCFA39411CA2CEA /* Foundation.framework */, - ); - name = "Other Frameworks"; - sourceTree = ""; - }; - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 8D1107320486CEB800E47090 /* SheepShaverPrefs.app */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* SheepShaverPrefs */ = { - isa = PBXGroup; - children = ( - 08DC90C20B67078300799A45 /* prefs.h */, - 08DC90C40B67079800799A45 /* sys.h */, - 08DC90C50B6707AC00799A45 /* user_strings_unix.h */, - 08DC90C60B6707B400799A45 /* config.h */, - 08DC90C70B6707BE00799A45 /* sysdeps.h */, - 08DC90BC0B67074C00799A45 /* prefs_items.cpp */, - 08DC90BE0B67075D00799A45 /* prefs_unix.cpp */, - 08DC90C00B67077300799A45 /* prefs.cpp */, - 080E96DDFE201D6D7F000001 /* Classes */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - 084186AF0B3A0515004B1F63 /* PrefsEditor.h */, - 084186B00B3A0515004B1F63 /* PrefsEditor.mm */, - ); - name = SheepShaverPrefs; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* SheepShaverPrefs_Prefix.pch */, - 29B97316FDCFA39411CA2CEA /* main.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - 8D1107310486CEB800E47090 /* Info.plist */, - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, - 29B97318FDCFA39411CA2CEA /* MainMenu.nib */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, - 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 8D1107260486CEB800E47090 /* SheepShaverPrefs */ = { - isa = PBXNativeTarget; - buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "SheepShaverPrefs" */; - buildPhases = ( - 8D1107290486CEB800E47090 /* Resources */, - 8D11072C0486CEB800E47090 /* Sources */, - 8D11072E0486CEB800E47090 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SheepShaverPrefs; - productInstallPath = "$(HOME)/Applications"; - productName = SheepShaverPrefs; - productReference = 8D1107320486CEB800E47090 /* SheepShaverPrefs.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SheepShaverPrefs" */; - hasScannedForEncodings = 1; - mainGroup = 29B97314FDCFA39411CA2CEA /* SheepShaverPrefs */; - projectDirPath = ""; - targets = ( - 8D1107260486CEB800E47090 /* SheepShaverPrefs */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 8D1107290486CEB800E47090 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */, - 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 8D11072C0486CEB800E47090 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8D11072D0486CEB800E47090 /* main.m in Sources */, - 084186B10B3A0515004B1F63 /* PrefsEditor.mm in Sources */, - 08DC90BD0B67074C00799A45 /* prefs_items.cpp in Sources */, - 08DC90BF0B67075D00799A45 /* prefs_unix.cpp in Sources */, - 08DC90C10B67077300799A45 /* prefs.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 089C165DFE840E0CC02AAC07 /* English */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = { - isa = PBXVariantGroup; - children = ( - 29B97319FDCFA39411CA2CEA /* English */, - ); - name = MainMenu.nib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - C01FCF4B08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - PREFS_EDITOR, - STANDALONE_PREFS, - ); - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - OTHER_CFLAGS = "$(inherited)"; - PRODUCT_NAME = SheepShaverPrefs; - WRAPPER_EXTENSION = app; - ZERO_LINK = YES; - }; - name = Debug; - }; - C01FCF4C08A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = ( - ppc, - i386, - ); - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; - GCC_MODEL_TUNING = G5; - GCC_PREPROCESSOR_DEFINITIONS = ( - PREFS_EDITOR, - STANDALONE_PREFS, - ); - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(HOME)/Applications"; - OTHER_CFLAGS = "$(inherited)"; - PRODUCT_NAME = SheepShaverPrefs; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "SheepShaverPrefs" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4B08A954540054247B /* Debug */, - C01FCF4C08A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SheepShaverPrefs" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/SheepShaver/src/MacOSX/PrefsEditor/main.m b/SheepShaver/src/MacOSX/PrefsEditor/main.m deleted file mode 100644 index 07ccbdbe..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/main.m +++ /dev/null @@ -1,26 +0,0 @@ -/* - * main.m - Preferences editing in Cocoa on Mac OS X - * - * Copyright (C) 2006-2007 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#import - -int main(int argc, char *argv[]) -{ - return NSApplicationMain(argc, (const char **) argv); -} diff --git a/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/InfoPlist.strings b/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/InfoPlist.strings deleted file mode 100644 index 74d3187406a26213f9d2bcbfa9662776e5535127..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90 zcmW-XK?;B%6a{DPDO|hIa|B%?G9i+TjKB_GJ>2~HZiT(X<$)+ - - - - IBClasses - - - ACTIONS - - addDisk - id - browseForROMFileClicked - id - createDisk - id - removeDisk - id - useRawKeyCodesClicked - id - - CLASS - PrefsEditor - LANGUAGE - ObjC - OUTLETS - - bootFrom - NSComboBox - disableCdrom - NSButton - disableSound - NSButton - diskSaveSize - NSView - diskSaveSizeField - NSTextField - disks - NSTableView - dontUseCPUWhenIdle - NSButton - enable68kDREmulator - NSButton - enableJIT - NSButton - ethernetInterface - NSTextField - height - NSComboBox - ignoreIllegalMemoryAccesses - NSButton - mixDevice - NSTextField - modemPort - NSTextField - mouseWheel - NSPopUpButton - outDevice - NSTextField - printerPort - NSTextField - qdAccel - NSButton - ramSize - NSTextField - ramSizeStepper - NSStepper - rawKeyCodes - NSTextField - refreshRate - NSPopUpButton - romFile - NSTextField - scrollLines - NSTextField - scrollLinesStepper - NSStepper - unixRoot - NSTextField - useRawKeyCodes - NSButton - videoType - NSPopUpButton - width - NSComboBox - window - NSWindow - - SUPERCLASS - NSObject - - - CLASS - FirstResponder - LANGUAGE - ObjC - SUPERCLASS - NSObject - - - IBVersion - 1 - - diff --git a/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/info.nib b/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/info.nib deleted file mode 100644 index 33a60200..00000000 --- a/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/info.nib +++ /dev/null @@ -1,16 +0,0 @@ - - - - - IBFramework Version - 629 - IBOldestOS - 5 - IBOpenObjects - - IBSystem Version - 9D34 - targetFramework - IBCocoaFramework - - diff --git a/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/keyedobjects.nib b/SheepShaver/src/MacOSX/PrefsEditor/standalone_nib/English.lproj/MainMenu.nib/keyedobjects.nib deleted file mode 100644 index 3d6ff6f1c3cf3b57922e9a3ad9cc143eaee9824c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31674 zcmbrn2VfM%_c*>YyVv$EAm;lav}5KtWV`uNJI` zC`AxO5s;2_5f#OPqNs@Qf3uqlmwC|yVAJqNEVXT|4h(vH)lo*lD2Ej1 zL`gU6YT9Z9RIRl)Rh3#MSn9GnUfQZ-m5iFvFa{=`NoKN`TqchxV#=6_%yi~y<~inh zW+U?=^BS|Ad51Z`e9RnWjxi^hOUz~F3+8L)8uJ75Bl9!!EAu<^2XhA@q(nWCJ#s_7 zNRL8M7>Y(l6pK<&Cdxups5csb2BP7p7S$mO8i5{R)M!5ZK8>Db)}!_4CA1a2iQYy# z&^~kkeT+UuN6-m$5}iSxqx0wzx`Mt$U!&{j7xV}E6TN~lX0a06V`uDw!*Do`#4$J) z$Khn0g|l%vHsLDV8~4He;d3yq#>21$H{db29goH1@MJs#KZfVxd3Zj47QcvJ!Y|{k z_;vg?eiwg?58?CpOMDf7k8k2%@g4j(i&>WCSvBjxI+e&uyyPs>^OE3JBNLeozFhaE@Yo)SFr2Y&FqWptL$s+4)$GkC%cP%pZ$bA$bQNm zVNbJX*w5MX>;?7`dzt-${f529UT1$~e`9a4f3tTv87Jo)I7iNnb7$0C2>ga}kz5>? z!liK;=nR+7m2u@pbp4-B` z$!+I$a=Wk20A|DdT0{GJjcsELavIi;zXi zqGU0$SXq)R8?JL?d9or|sjQc*N;XV3TsB(P1b3TdEwah7nQ-;EY(9KGEn5tqOJr-| zbDivE_NtK}NG zqufdEDff~G$OGl!@(6jXJWie^&z2X9_GN`+40pm0}sDEt)xib#b)k)p^}AjNP+t>O{I zXhn;nRWV61T`@!Pq~a;XT*X4gvx?^w%M~jW8x@-rTNSS=wkvik_9#A598erle5N?9 zIHS0vxUBeI@uT8*#b2^W#T~_6C9BlPBDsl5J7o{0R;g1uC>@nfN>`B?Ek zCzNxQ^OOsf&ng!ymnc^%S1H#kHz;3JzNCCj`MUCL<#y#x*el9gG=lK`-#rzU}DZh+g&adEC@~imO{2G2O zzm8weZ{RoboA}NA7XC&4CH`gp6@DxKD*qb)I{ya$CjS<{jencp&cDO&;NRun<9G7A z_}%;-{(XKgzmNZb-_L)@f5ac)KjuH-5AvV#hxo(%5&kp&D1VGU&Y$2<@~7}?{AvCS z|2cn_KgXZvFYp)nFZiqK2KBG%-_*C%zpMXH|Ea#M{!4vF{kQtA`ksc-APv^A8crkA z$TbR$QlrxF8ns5FvD5U>*lV;JoyI}qsBzLbYg{z08aIu*#zW(&@zQu}d^Elqy~a=D zuL;luYIO{gYJ6RwHSL~5cm(V7^IL1Wa!YT`8UngmUvCP|a5NztTg(lqIs z3{9pcOOvh1(d26KH2InWO`)bpQ>-b`lxoT}$pkUMOb8RogfZbv1QW?bG0{v+UsF}Drlz*Ofwc`at*t{$ zRTYw<0!!2?nxtHM-_qK*rlH*ecic@?*|oKn*4Fyr^$qoH6DsQKI-bG1xlN6YVCBI6 zwGJ{>nQF#ZT4_IUUC;tw#x=E!rmdtN>63vl9&|u2;eq(VKMmB;cT)>(SU`ql$H4VHfOjde}qB)B`~VeQWKA#l@S2f(nF@ofObUnAc09_ zl3=8$*0z@V#*qRCQ^;-xC!)57BI_8F!lW{3OnQHb3YOM^(nTZmv6e|^GMG$}7Uk`2 zH89O8v6ud)s?G~(vQj_UOwJl6hshiYfV8)^HI0!T0-lO-?%y?#kzzcywq|i?oDvT1^g-HS-=re*oC+HkO7YMpU&=&-KPtcD9-5}@} zf_^3F7D0aybeo_%1l=W=As7?P5e&3b63i21V1cs~K)-5CR09pced3Gc(}L z$C#PSgs37V4~Lp=jSg)e6`kP(j=oXAwqA6H%y7pPckG&=#7a}rkr730B9F8OPHn1GG;lmf?3I| zVpapJYhljonR%3t0WJ|HxGrw2ZLy58G`0aZh$7OjrKXw6Z+Xpl@jGA%M6|7?si7}` z0IfRTHo}+e_O_-LOS7e>4K&wXy;LbM4%zrND&xE5on|cG)|fFxro3W%)88cA_8|ZyO`a~9_D>!FS8FA zXFs6wqiU_rRFzXxJ9=bGQ+s1wZc{^33*d}`1*oL71`0PfwX}&1^IB@gwcc+H;PwWN z5npn=2S3j~dN*6p3vPmw;4J7Iv{@W5gLh>t<=9V{gUqMQA?7f1g!v43s;YjX1^!Si z1gteeB%|OOkQF9jU2xHHPJ_$ZYwPQ33R`M`AthWMXHKkPPB5A9D%G(kq32V~Y32;` zIdhgd$DC&_Fc*PyMVKg!>4d79Yicc&UFa7&AY}!JX&RbFib~K+@YKo$55c`})r8hI z%b04dV;jut{zSzWkHb)>nJX~NRpu)gqTi_cHjCh;WpfM=)=&lc4RdM@K$F=OsP6!% z>&!*LOYjwZ1or{7>jyf#A$aA)bae9zb8{VYQ{pXAEGd!;>Mad*_gU&U=GJ=VmX)PC z2qCrsLbcV5wiGwEiCkaM(ljPT0`E`e_FCpP^B2|C&Vc#);T_xuf2dV#Y5|Qb-Ic!D zDw?~@J%)fL2^D%iph*yB<{%EqC~qPx1c4?97D7})&?y@=@B~sZ3y~UWn7K$L%oaWn zeh{7%K<|M3#~EXRePbo|1x_|50sA6thXz=Rbdm-@4w4Q)PRJR+0UZEj5NAonyuMMq z49JS<;2`^etf!^RfGlmty`HLWas{xzfjp5{C+vPgm=F%Ii-5%@fG`Z*8PS?w zR}Tc~4s0BXM+qoV1U61E2)zZP5UUal-SjO=M;XjqNy)Yex2mU=-eD(r_=UEyoBWv0$ zB8!@vn)@`DLCzr$Zh(CP6MgFNMeYH6c9O05Rfb0Ys0)wK4tw6uYX(NI+jTDif} zBE&d2J$g4wr~(xd2gr*N5>;B6kggKqtKyPk9*`^4uS2d91b1*BY9;kf#YGgb4krK& z7Sh(EA*cjZqhY8_C(w8_ z0Zl}S@NWv_DW;-nfIxz#qZx2#CVCvcJ%MJUIp|4fH5bhTZP>e}Wu&DIly7gzngn%2<;pv{^Z%bEa#BFeKH8o;^iJ)zlB1+=LJo$X5PVw(k=frbXE z1>yC6^>uBdL^m05)IO$BGJLJ|6KU6N6B>Y?ZV$dyWT_uHikenRUkL&rsOTS1MGi1a zt}R?h)(@T*w$w`orCRIt58#WigVqr_LxP7o??0~FT>FIz;2C80S;-^>{Vu6sh8Z8uZ&Z0$3 z5A+;*9=(7Tqa|o5T88p~9xKpFvxfYoL#Nt*k%`jEU!+?h(OAYu)9R|O+ z4vb~}h5}?9OQBX+K4ux&1eg#z;g~9xyuMeLZOf^6bPPlir~$oR|L*%V|LMN%n|ekwXY!^ z1Gs3lHWm$S6TC`eqGIWfF*#YXL})vDXFYo7zAXY@L8R3E$xB|^j{7bKdY9P)9KH{k z(H^QO9Gnaw(0ZW+#5r9@{ek!{VvP1P=h26v7?%m9RE%9Z#Q2}hFFGg!n;`vIfjxu{ zuR(`Jcg%*Jx(;>}20JDWW)>>I7LT;Ds4Xf^3to9KQSl6Dls2ozl9*aDr06U!Qx5E5ZPa&^ zD0EU+SJ78%(N~i3b`s5WMSEL=1r%L}?Y1>8*TA@Z2gap87?&a4ZOHdv@P0%;i8kbW zVE{Oi1BF2zf2UL%sD41TBP1(JmU|sKXv3x|?y-mi(K)iS7V9 zTtoLd?c!kIh5inVWEa6-v9yh{v@}}UL{&8ce6`NGFjG+^mSY7t9#KNIFtXcRunO~7 zjlrd0=3$jEOc){52*cr`%UrOQS%@95BQqCkg~i}_>=Tv>i^0hQqZkvR7rl-o@H%2) z5*MhbVOQ*i-LVJul$>Ym#Vp6(*a!QfJJ=6$B>Qjx4unrR4#puk6uJVn*8qAJA}|Y3 zMD(3Sm29@O)Hl`D*NRgcTSJvWPJ3HhQ={nb8b!|Oe6x5Ax;;Wz}T@5439Q zMk!`CP$~_lQ%W(jA$%DjJR*#?hA(kIhS=C-k)4ciZ2xb~Dg-00z-C;Ddr2x>464O|p;>4Yn!pthM*yT$jjL~~9VH>OFYdPn z_oF^GqyjE~+=`bAVPzQ7v3v`&+jSke^#iMY&DE-t`_Y=kmi48}$iEqxE^c^!a1j z8*0D_*N5cyH|O^%F3&gh&Mu?UZV~ez&@8W)wUNzCVV(={LYQfkFrA3@^tk@JhT2uf}WeTD%Ug#~biQVC7ACGu{GXC^=Idc?$53EtbY!;LrhU zOHX>&gYF0auwQRck96J_6MLQS(^sGo_!!hj6V-_HIyJ4}j)*b6bVv03sCz=&*EiDk zz@!uau}fhVL5B(0-Nzi7$1{vDQOJ!&S%Q;JJf}PIPyFVG4Xq-0TNp$7@BX|$vlB~;$48C=I6O(4}0AggxkG9m=yg^a%vG9}dBQVb#l`u;s z+_1uQkirB)W&M6cNP7tn$4Buod>m`>Nqh>QhPd@EK8w$RbUr1_7Z!m*Iw%|wE<;!y zDqIz=brTFxUN7OxHu5@GnAb&KljB9b8UMfJm6~CE)J9&Z8GZ`n^NX!9W@1l$uppbzK= zJyj50-81k7S*F7md{%HD+~Em|!Q4ZjWaX^F2FmAz=et0eEGn`@a8LdPO11|;dAt+K z7XZpd0AR0*a(zL4gN47q%wV0E9;`F-80$j$i*;q)Sa;?L)&pp>p7mnASs&Jy)dL_` zSujTkV-*MyIC(S>10fP+m0DDg(%z8CYHh9o8KALLPE!lS5VRS*P%&aetEEj^8W3MG zH?`K& z0kz8pC==Ji!iNJ+O)$#13YMutV8ub{J?T6+4`*1u7R= za~R+bw2Dd@2rS*p9@9pH+P>Bn;HT~u_6qN79fXY)T5YzTVZ`4T;4l2b<9CHkRx*wd z($=!IFvuWb6WrhZxs+04M~l4Jz>Wd9qSz+3nSGRPVO!ZYG>we{cB<`6*5@_VQpTY? zStv@9utC@%yrboW%{mn$Y=O{hgLSkCz(j1Du;r505z-rw*Z{o>sSS3rl-v+?@+>r# zog$_+#-RypEy%z$R)Ey&Jaz^m?4xJ~Gnah~Lcck<004giJ;}}nROB{+hu=a05$zDo z4RqQZnAvs*hdnTLPnGbJ@S;jE!L6+USq4V@889g}5m+!We#(iCgd(geuyfgYVvg$- z;boCuV-vybh#`rnqd+lu=K+3%jskVj0I_pJr*3SvAo)(hFx05xkNGJgX+&)0=FsfW;! z1ZOueN7zj?8V~B|#6_p^vW-C@9PgqU8OS2DuXJR)-lAc${U|X5(V6VBM&j0V|1S1* z8i})S0nfLw+i4{3*Aa=o4J^M!r=*IQzOL_d_u2PQ-g;yc*U}IP)F(ACRuXhzbvL_b z9lJ-uDveni>YFKX&j8zureXuE(hjV-7nn1O-OqjqOz{z1eGF^}F;OijKw!fS!Y<)G zVW+SmAoKIwp~C{A9;*ELziM+(B(L+s)8>|twU0w7qQgM>&RfaG=s z;y8qE5*VjC2HztM{?luJ>BYg_Cryep#DHF*pPjQd00iI;NX9Qt!bURSC9#vo&a&s$ zvF9XgbjrQN?4U_$Mw@olk>)m7IrAd3b*=P{l%WOF3M*k!OKMxG3)OcLKoc{i8;?;7 z%e>EC6?yDy(fd9CJoa(FzBH#NMK2v|73_C{S9y#+CMqdL{OMS%V83U7SjYY#4G(Lk zV6VEVVd{FYKeNA3H7sWJ{e(}2LtQMa6tevfKY;xcEbPfn3ws!t@1PJrFbAx^o~};t z4~&cAImF@4aeE7&2}irQJh7t7V@RNg{a;yZd`ikpfZ*E>Bcm@B*#4qQ;VGegs{KB1?oF6lf z3*Z82;ul&4qj|z9;VAs0IZpUyKG{1OG$Q3RMC%dr{f@~s}z$HrAL{L{3g!A1JiQN>FRnv4XD_V1YoV}Fu z>qz%eY(79+%yUItaVKp@2ww2^?ywRa8*F#(+|XXUjltEg8)Ou zg68w|5+(I{Ewu9S0SK8lxPjcDP6+*kuY|9y5E`jZWRTcCnR>$i?EZ4Y0hY6!Z2t|w za8-yO+AF(UPopb+NO?}^gRBqed4wC?Irs?STj4wF;IVWC%8(@b-Za|!KlnaeE7u0# zoa^HId@o!Fpso$bX@OOPZZ4UW<)aRk7}CYX!_cuwAZyYC8ib4bF)k4v#8F7BGBXt% z7JPscI3nB-px|NbDX^-~Gh4YC%qeCH_ZT-5VWh&hxY=L|I^rtfrtmZPva=yf_@&a& z2kJN4n?>Wz&E@8;;pSPBx>TdmsI7aK&!9N5%SF)9Z?G%|9TC)CX|%$$m{x&kxh33E zZW*_nTfwd5R&lGjHQZWm9k(7ua2vTz+-Bi-;T}N{(|Qw>Oi(&O*#zYiR7_AgL6rpc z5n>1$MNk7l&Hok`#L>8bdzpKM_2pg#T1s(29QOu*_K9#u_)97L0nWQY_|ppDHY(3= z2!C4F@xa^UmM{yscbU1|5`gOi;kNL*XdA7zB-Q{Pks&Tw46-LpN~HHYOqPN2Xadlx zo1{xdgWF4u2KRwzH2wyoaTk0Eec$>zOOqZD4^<>1#pIWb`S{;+J;;3ub3JS`*Q0c< z1aSnhN`e?VU4kI@E=KR%2|C}SaKm=OOJTyF!-SU#_h`Nu3y`I=v7XY5W2`(#XPhW9 zXRJ73W9&ao__8?RD|EsH$%NMlk`K*pudDyZ`F2+caojcTTkboU-8=-Vt^|1z1d~#! z1cPL_lYkbnpbMztqSw?YQ5X6J?kDaB%_c*NLdqw<$NkJK<9^|8a=+57GWQ$y=59f^ z)6pI7PwqCF&i%zfoX*|lmO+`pJZ7E@v)g5?jH}jqKxW3$*iQMM7KuP^C%XYMg0$pC zbg5xovT2+(Xas-A+E{!jrCwSrb@_EP#SH7SeV}HJ_C-xFZ3kKt+BoqmJ>m#R5XfdQ}Dye>&IK_#4q6C^sX5RJ&Lmf+7aYLP!9(N z3Il|}4%47`g&=!^bTAu&9KqrNq&_lVnO^1xv6~f_tps@x1haSPE9K2>(!{bL0rJ8G zX+?z7H*!Z=YDbT$X&G(XDqL#iAm)c@D-lQ$ESP9@GhIlhbg^A=l0|bruK~`<>_Df? zC~yNS=&A|Th+;Aga$>T0>aN_CC5psxJ@;^Yi`Y)>g6%9^V8w`=FxUnU?gI;;n6p*P zKZ^QTmdpLNhWm{I0tGL!d|AN;S%Iw3x_}^3N-PDqzm5R;HY@fz;|y7`tYm|%mp`ZfCV#Tt-6c>qfY~P-#4Wdxz-k$Xri+BN zrUZ+jBncAdfG$ZW^i(MPz<8*DxBPAR{^4|RkW~QJTWsi1Eqeq(zSvjf%z*oJ@Fytn zK0l6;0gC|-_9Q5%Z(>xuzG$KiQ_xGw32j2!Mp?UTkZhc6yljGOqHGdD!6JBJ1Vs`A zb}W{lgtHH25enF}E`U8|1uLWrSfRb?@c-P&>@JwNnbm_&|C-&cA+1RC*m#n?Sb?GI(Pr|?V@>-W(wpn{g?9xk8 zzq|>JHDl^)ACLyj%ifi}XO#wF1VJeTrFIGfUAQsCOTs{n41L4`(#$xH^{(g5pAqOT88 z{=Y6Y$xZ@9EAOYS3Cg0dKwXe`|L8i)*yy^}<_FLO09=$^vIQWApj;6EC^<7w0FwXf z_+P{Lt8B;5qvL18_yfi9$AF=EAd;Xc_(>+^(P^<3paAr2p$Gva6Ow5BV3abM)Up5P zP(lWobZ)gZlpv^x4xSIegoJv1o@H!(t>uAWf{uSr&e&q0grHJ!eDJI2_{slec)0?G zUvq!>GCF**5I=-ku9klpU2ZSe+Kz4_sKPpX8a)}oNd@|gi1_E(%UxmkwfBcN)8Wg7 zc(A}w$@H*U%YEfE9pA}#y$Gu6GOm=v`CsD(!?^42kK3D$TPei%lS-2w92mvRqvbK3 z1NSDVFG2mpfjjH(5+siMPxW^YnTYjw@+1IcJ+oh)3R9|(r^6@As1HqD5Y(SS)rX(~ zV0DJj^hH8kOotVa=R)0^JWrk^FOV0a8iEEwbAkpDD2Pj~iZ>XmASKk>5Mzw{KPENg ztU)ni5(Bn~pS~{6Ojz&cWaeSj#?EAk`JMvXxwM}P*hkOHowOKMsQdH7W^dgKA zptOUaRtje`q$eud>uX2TN_DZ81FA~JT@gd1h%Z`-bh{-GpICEqRI!%UO!WdwpI5JU)?Eleh8t^jm@ zhM*S-+DZ__o7)74D|QI#e+i^vHwGjP{ZrB9U@@>pQ`AKH396XB&G?E68CUgm<<7nNJAqFC5Y3-hVlXPO7 zm{u^x{6j1)KTl(6`9&#~o+iNDgrVh4?X8w*2*-vu)wI;nSm(dx4mzg%mHca%@->?& zUzeu*I6*UE%G0GO&#+GUM>^%}1kJFW^4l=wn=s|KfeLiW;IWd2O&JnZol`a@h^ahu(^ZB6>(x(3VtlodsgBAE46gx+Ty^u5G5n+VznjI)3;jxeBuZxqqMH_)Q< zd#sSQK@q2jS0pGB6-nqCLC+Ed;l(n7RuQyT=--W$2nr_^=?W;U2Lmh?P7<_;py!}; zQd%4WzdKRXaE4e)$%pB8MJ}z3P!urx6mjSttjTc(amNg#E1#z*c~*#raLn(h4%K&-hdvY? zjfy5)Fjf<^Mg)WU`m|bA$`u;_Q?;rhv1_#|aKuCEWGFvORZO!Tbsa(LyNoJn)&DqZ zQuk4z=)wD8TFjaQ6>B9$I(O*pf69R>o~BAnu|QH{o2e4pGPDXxN^2UTO_nyg@AW_E zvBiodbh1o`9)s}rWm_F#G)QZ^&`ATp-#_7S% z)Pj7pb`uFOCT}QSRJ_y)Ab4M|67-q~py+->jAiU7S*8n3{~B=8S}FOi`vD)U-~$+2 zA7lb?*mo6TG%n%=hJAyeH?4SyrIB5dB#QC>UWugG2V?HO?|8jMhkTuifU{^}_5Glf zu0dY_Rch4mba%l-NDeAKwM76}!|fs@5N^^U9z(pSpOXJQ+*BL~K=#}RgZ zp!Yj-a*96{x5b>?UV`=wHbV`!zE5*>Ueh?(H!Y4x)3qH|2#PM!)+oMFViB$n9-2F& zP$=cLP$<<_81{F8;lrW1?JccPq1rJXMC7ftP-#}vXaS#0%+V_Cxf$zV?M>WzI`DpN zrf9OjOi6j7I9h?71az4)aFS8nEn`duN6BMSY*bu~G0A8Nr$TM>MXCZ(IxAh)C|x>= zojXcXEn}LYY}V4hu48{#XJsriRq3Jhq`L?SI!Vw`!5^wc07IQSl4Uxj4>L!pSNc%~ zQusI!!h1Fro1xg4IDGw0zWj94GV(}5BxCY*d#j6B;bsvk8_NFRC zj8-1zRZ!m@-%_>!4oBSAWM5MZekp1)sZi$rQv3kegbq9b`58%UCMYMaQ%;n`hL*31 z2NlrO7CPh6RZ!1NSMhCU>;W?t=!{R&8UFxlA+{~Wy}35cxy{i0aoW6@Hvg&Lqjj{F zzoD}U-TJ~tD4!CyzJO2q^B`D;0l9+YYnN>ou;VmRxc~?fO8dD9yWYoigA6Z#7B4`H z>9oafeaDH1P;?H2!sR=m!3qk?i?qe>Lm{36Q~MC=bIYOSI@;2kw)}GtRCLp%0L=;5 zbjS$MYzvI2rmg-0m)3?UJ2t;}HWw!vseDzOD7bBZL#MPDv-?Eld!f^9bnG3p*LwrU z(701Hie37W?^M1=`=aqThEuCty3PhF)oMpu>TGweaLb_Qy|iZqyoT8UW9e!*O|x`% z3}SW<8XbT+^`vcNLp$)?eKshZTLBFZ)83M4ONCWL#B8}uhulhNcY?M{r|nb&n%di> zOs-8MsOOASo`q4j&^GEml%=|e<59doc^RHRB}^yS4zx^tBUBC7G!)dgwBA39BbuptY)M~E$fSsH0cD#yqtRFCjMs*Zn zqApbVs{#lP+^QYGtyjcx0wc&0u@>^&a-}D1mW!YTD)JqQZGpWlNQt%AhVF4+WT8n*-wXQQ~Ks=oLD z6l5QTQ2!LS8P)|^?kES^f_p=L2rq#A!AYeDw@x+=PXG_99d;-j=T<0vlvt4@-=;{E z??G|gGPX@Np1UjGOI3Ft8mj&(fLr1!K;T&}R8xE2pVr4@i#0QI!M_1XxhBjOKzBna zO#;n{H3;*?0-706>~mQF_q-TTgZ#zCNKkPQd=p`o06M^17(kWLFfn@uIkXr+?(eW= zVgpp@V1FnqS_TZS5srZN6jwFvpp*nkjp$CrKOq?gvH;{fD4Li`g2HH04qUci;HE`l zZO<_RXX2o>V%83V{cW_ULm_Mt*G3_|wgapLr4pQ%qnakj2o4a90$8B>HFQ(Bm4c5+ z6ol%d@8NWV*)kSNo8qtvjNkWg5B@Q;6+kPX)++i$Rt;&!IC=%tI)E_S1}%KK<+5sM z|2@!V0an5Dn{cHCcYe0DJ-y5L0vD(d92Fz=1cgjX>6qLSNcZ_dzZgapN09G@{$Nb{ z4vY@{(qB$MacmTD3(L$_`oL<`03Z!a)ecBupol&OcMRe`xVszf1_3GH8PEqXZICW$ zO;-@;B7=a%GAVy}X#hN)4n^zG@)@{X48PEW^(DA3U>Itc5CjD3=#V1&9vxr!ou(); zT)@*~9fOJZ_lKqwG8kvKI0PN$SGci3WEeX-#xW}$E{k;NElCo$mJyVmu-`^5OZ;Dw z1Xzm1r@1xkbKT_#(z`Y?#4Tl`BpCusZiXE_r$iY738K=Y^uQ;r(!=;l@}u+t3F?p^ zp!XiD{3u7r_gdwL3J!?SQNS6TMU?}c8LC35gdd@`TH zr}AlhI-kL3@>zT~pTp|0Ka71cwqFMsPU6 z5d=pP3>rI{;244p1RDvCB{+`Yc!CoMhS?<%oJ?>E!KnnN5u8qN2EmyGXAzt&zqsOK?Ae`x88X z;DH1WB6u*tLkJ#9a5cfh2(BS`IKj09*AZ+Xcm%;C2_8joJ;9F+M6a0|h$1h)~~PViWQ#}Pc9;0Xjzgo+k%x49n5zx5%obO^f}^|ThLzE&@84G4KK z7YR+gp>7ivQY_>2v{FeQ(q(N0o;!8vLRzN{9nj$_MH>5cTn!ON?I>BNubJCneMu@E zf=@zbiW=cbg&4Z=vPO=MrzxMz*!;ip6mSv`jBW^CLk`;!xOJA@O529 zhsQx;;g*Dxe@;+CLpK}9Y~%j>bEVY|U1rr;Yzwa&dp9-fJ5d=Tmc2&kyC5?{-zB7f z0QRos#PHbpfk{Jc1l)JD0kxyB1n!2}%=F*)LqlWFE?Dcb90*TcyFBgO;0I6KyF9U3 z!wl_9c_L=%X-#L0%-uaJY+rF#;;iuE~g&#wz) z4@opb8~-kC9+niRor|1ovnmuixMRR%&TYGaS%S-iKaNo-YAK8=^`Q0b&5DeVPE^w_}rkVQ9u$NoOJ`Vdjqx^*Gs{Vg%j*tyH2j+zs= zZ%atAat`jLJUH}!+{_LyKLjDh!8EE0Zq-+egH3yo_q9PJEwh8Sy3ECp0C&17fX)rH zq5WwfPg4?LT5RC7in(nO8T8^|GgQ~)W*3f*wen%t#pf<<;^2^nE=cU2y@uhs37|wv z;44v`Q0>$W;T^NL<*bf(x)0Vp!32YOc9r%n7Q^a0QCD`A^~;yGU%nQ-s+kXli%boi zQaO%!6kTK5Yy!uTjM+ALWCk;hG=PNjFNf10k{N+8({ewIlwZFeNHRm%NT#_L$_Qwn0gw1*gHn(#} zA>gzLHkm=9!`#eFfQY}z8g?>OOobu|&fpvh!A)PLT?#>&TFHrK2L5XpN>AFPXKBJ| znGOQ@QLbI1QaE-~2<#e~(xW=DMhZ~d;grsfDD@5mCD^HJpgNrG?LEJo_WT zmA~psg6OXkdUU9-0PbuLn^+f)C^#=7u^(OUZ^%nJu>X+0nt6x!XRlll!P5rw1 z4fUJqx76FzZ>zVf-%;;SzpH*vy;HqQy<5FU{l0pydY}3O^?vn->W|b1)E}!qQ6E%) zsy?JXtUjXtOnp>+OnqE^LVZ$wN_|>=M*X?^tooe#y!wLrqWY5hvib}474?_utLm@R zU#q`SUsHdp{!V>e{k{4J^^fYG)Hl>WtAA17BzPLZ0>MB($hplR7}5YU34Wa5Sp+{p z@N9zT5Da0(Qv}Z?cpky?34WU3X9!+E@Ir#0C3q3R&k_7Q!7mWJnBXM@FC};x!OIC= zLGVg~R}s9L;57sT(bf^Xp5P4xZzOmV!J7%*Lhy?OzeMoM1iwP?R)Sw8_%(uGC-@D5 z-z4}gg0~U;Ho@Boeuv;41iwr0dj#(!co)ID3Eo5S`vmVLcpt$Z5WJt@4+;K=-~$AI zOze@5_8f{zh=oZu4#pCtGc!KVp6L-6MWpC$Ml!RHCSK=4I^ zL7YI3eL?UQg1;pAD#2e7{58Sf5PXf`Zwda6;Ohi`Pw)=}|48sp1m7U|XM#a;0lmKx z{2Rfy2>zX5keWXUzD@971m7X}Z-VaYh|I(pR+8a7FUHiNCy!KD+ zWgY6TLlHV;(4j#(6r)2Ub*QKI7aiht$WHsU4hcFmM~8-LPw3EG?PuCkI;7B{eLAGq zp)BopI;7E|KpiU3eyP2qL;2ccI^?fCqeB@wq|_k~?Oh#uREJm{s?#Bh4mE3!=+I#8 zMI9>B{;fl`Iy6ChL5Fg5=t&)#q(gZ+WYVFDI)rs-iVn$iC{c$Zbtq1IPKO@Tp)~DH z9jeixA=;y2WgF~8`CEHQ`?>Zj?Q!jG9pbdNbSPVURfmS_P?HWlr9%U?hjl1khZ1y1 zuKh;)s}4P`J*h+ebV#j3Nc*D>P1B*-I@G8`W3*>=XrA`84#8%fzB)v7C|8GO=+Foq znx#X-bZDjyRp?N;4%O?>WbMy7^n~^|9ZJ{U)1g%DA38Kuhpa_28aN=pYMnHbZLE_9 zM1tBa*cGB7n(1pa)5W6`i*uy2o#|P4j1rFi_Gg0O{}z$LWHNbR8hSG$pkh*xAB6Mt zKbLH;V5RKPYY}eo_1eC*R*z z{Hdz@JC@;e4^gk;9QXx2xUZb+8Myl#nqg7*6O{zy#t*Um_IMqbe6gZcDhU#(EY}He$ z`Kkq~MXDE6OI0gWt5xe%8&z9WFRNZvy`kEsdPnu1YPV{yYQO4$>Y(bd>Zt03>a^;t z>VoP=)g4~O+wu0ij(6mpc_XAh${@)x7*ZH5kg6C9X^M$rf%X z{Z;-3e@CrSJE{HE(dsmHwmMf`rY=|aRrgm9R1Z?usmFlweFBu~GEkSVfg z_6O|0vj4{ZTl?$wKiL0he?u$NDzqxCM%zOhqOH+3Xs2oyYFBFC*1n_NrQM_5tNlRx zq4t3G6YW9mA?*=R2FJ9gwAZyiXn)fF400*g+3R#VFP)E0uk+Uh>VkA(x+tAdm!iwn zmFNcOYIN`E_Un%5es+*M=pE7=`Z?4&G&@XinC>vo;bn*S91b{q;_#`%VTaQWpF5m$ zIPdV4!#55$9DZ^5&Ea>4KOAm5+;O<;$T(t0&e6`%)lu*0@7U8Z*wO4*?bzTr!I3yV z<+#*wgX3$CuRFf!xXp39L96xnD?0DVrhT|`ezdGJ>{KN6K6YC^%k~_INxjXqg z1v&*e#X7}1WjmEP^>M0qn&ULz=^3YmPK%tLcUt1K)M>fX>rQVvZFAc0w8QDR(`BbC zPCq*R?sUhQclLGma}IFs=^X5AaL#bfa?W?|?_A^D=uDjFI4^Qu=lrts4(I*OpE{p( zKJR?fg>#X+C|!6LjZ3IYxJ#r>kyWDkUT-{wgUAUHx1GT$5cJ zT_1B@?7GSIUDrddmt22v{l)cH*ITZCxZZZX<9gSPal>w$o660>&E3u4Ezm8}Ex|3< zt<0^T+c39!w~20(-KM$;ZqwaXx~+Cw>$cu)quVC8EpGeV?zr>r8uuRVT6YI`CwCWj zH+K(rFLyup9QO+Mq3*-nhr8FgH@LUEPj#Q+{+#I~ard7+um|TM z_fUH99>E@=9^oF59?>2#9!8H+k7kb+k2a679^*YGdQ9?|;xWzR36I4dOFfo*tn^sz zvCCtR$6k*QJU;aJ$m3&=E1sU7-k!dmex3oIJw1axLp{Si2Ya@7&hVV+Im>gl=Tn|L zJwNe0?fI4GPo95!@m@||L0&0dd0u9(US55?`g;xZs`je!s`VP-HOgzW*BGx^UaP&f zc)jHHme<=}?|B{dI_`DS>$KNduP?p6^19~rowuiVn0K!CAnzgG!@P%k*Ljcd9_3x{ zJ=(j$yU}}`_XO|B-c!A2dC&G<_v_wodT;aI?!CkNwD;%U z=e#d?U-G`}eZ~7PAH9#iPoPhbPl!*LPqNkIBdE)61vIr;pDVpLsq{`z-Kz z*5^5&7krlctn}IJv&(0X&t9Jod_MF!?sLQE7oT5!Zu$J-^QX^WzK*_ez6ribzA3(G zz8St*z9qiXd}sSE@?Gous_zcpPkqn&p7*`zd)fDj@0Y$``F`X3t?zZ;Uwv=+{^|Rd zp3}?q_IjP(QSYpG)yL@*^hx>@eVRU9pQ-Pwe^NhJKVSchexZJm{(1dk{aXD?`d9P^ z^@sFF^hfo_^(XYF^gsCd`vv+1`Gxp}`9=6e`NjAp`epg$_%-=W@_Wqh8NcOzEB#jc zt@T^)x6yC2-+O+${Py_m^*iWy$nS*TDZev*XZ`N^tNb1Pz5RXt{rm&`d-@0ahxteN zNBPJ2C;O-RXZUCN&-Y*E|BC;s{;&JL?f;Jd4*&Q3clq!3f8T$f|9=0&{%8EZ^}p`_ zga1zf@&Nk)w}7C4=m0}NTtGrVRY0GBegVS*h6jue7!xoj;HiLl0Z#`k2zWMNeZaGI5O68ri-4PfPJ!-$o`K$hzJY#$0f9k*A%Vug)WCwk!GV^* z#=r@IO9IygZV22IxFztVz*hoa4SXl?v%m|1UkCmic&Ddd&w!pidj|Im?HS%PvS&ii zUOgY_+1hh*&)Gd!_1xU^)t;a9JlgZeo;P~_((~7zw|f2#|*#~(C1qDS1#Rv5Y z>K)WKsDIGFpg}=Hg4%)ZonEqTrI?ir~uNs^EdaZw0>{{7&$@!8?O@2k!~q z8~j1={@{;-KMp<^d?@%x@R{H*g1-#@I`~?MF2o_kDa0kjEyN?lD51Y6f!7eNXXO>A!K^UVN zh1!SeLLEcHLyJO7Ld!x;q2|!a(5lde(7B=WL!Sv<7`iC*`Ow9on?m=8eiZs~=)urK zp@&013;j0CCrlsa9~KxE6c!Q|78Vhf5SAI19X2qmHEeR&)UcUhv%+SFJr%Y-Y-`wS zVQ+-J74~-6J7MpJ?F`!&_G#GBuuEZogxwCi6LvS83CH2Ga7DN_+#x(ZJTW{uJS{vk zJSRLqyePah+!S6J-aEWs_<-=i;nm^8!=Ddd9KJMsdHBlkRpD#G*M)Bg-xU5@_#5Hd z!ncPX3O^ElH2iq@$?)$ZA|o;*$|6h=Ga_b2%!-&3F*jmf#4`~K zBNj!x5V1O9ZN!F%%@MmI_C)NB*dOsx#Knl;Bb_2$BHbcABfTT_k!?t5jirlK5|CnvB;mIP?RRhCn`27JE|zEGOAZp@2I{}1EK~;RY%oC)kTer8WmL^ z)ezMb)fP1~YF5OTS4PP3*HvC|?W%$F0jI7bY=xlT|dK!I#j7yCxjH`@mjT?-cjV~ErH=Z+IG=5>cYW&*xt?_%~PsU%2f5iI5 z2F3=*hQ&t2M#Ju*_}HY_jM$N}kHn6NZH{e;ZI2xvJ1KT*>|?Pn$G#f-M(noO?XmC1 z?uvas_Ji0@W512P9{WS=jo6#9zsBB*)5aCYmBy9FRm4@sRmJs<>mN5Lt|e}M+%s_t z%k;~nCi;$7oC;yvTN;}hZs#Se+E zjvpRh7e6w7RQx0H?ePoZpN)SmesTP=_~r2{(lff-juf+%I83!k~nq3BwX<6D$d>2~Q_1NO(5k`Gh42OB0qSyp?b&;Y`BW zgbN9m60Rg%O}L(@OymL~~-V#6F4r5(g#@POM8Li8B&sCO(n) zWa3ka^Aa~Devx=J@$1BEiPsZ9=HuWT#};WRGO8WS`{Vl@C#FtLot8>cA4{E;Iwy5*>eHzUQWvE@pZaO) z;ndGkkEfnWJ)L?s^?d5Z)Gt!MOZ`6er_^846lr{#Ce1$0AuTj5H*Hwj@U*(Lk!kg5 z4QZ3oo=BUMwma?pw0&tGrhT0DN!p>bBWXv|PNZE(yOee%?W?rgX@95POULQ5bg%S; z^s4ke>HX3NrVmc9P9L2y_^jqnFq~A`zlYTdY$zU^N z8OjWwjMR+ujLeLjjQos(jG~O1jOQ|5$XJrGEMrB+>WsA+8#4A~{E=}x<4(rCOq|JP z$}^Rje5NMTIny=MBhxFhXJ&9_TxMcsN@jXyR%UKye&+DZy37%o^_dNsV=|jEXJu~6 zd^vM#=4+X6W^T)TC-dFR&oY0={3-M2%wIEq&-^3vc9ug{Y*u_$Vpd94T2^LOc2@ta z_N;MP6S5{}P0JFpre`h5dN*rl*6ysmSs!G5l=X4erK~$yce9ynHd~&p$W~?hXBTD{ zXP0J|XIEtR%C5@pliiZtmOVCmLiXhBDcRGqU&!8>y*vB;?0wn$vkzo{oP99+O7>ql zZaE$~UOB!wemQ|Tu{l{eIXTriH9568BXa6<9?5CQnVGXIXHU-FoDXt7%sG&AFy~Ot zXE|TyGPyXH%T?s^x$0cI+~C}@TvM(&w^wfO+&dgKM=73LM^mFAi9%z0ILeey=-&CHvX zHz#jy-qU%{~^eAvG@GnRy$S)XPFuI_*U`D}H1cSp{y28-HzJ>h@2NVu3v=ojgoKg6A;S+^V7S1c2U$~%fOW~2iqlL!{ zPZgdiJXd(W@M7T?g})U3T6nAQkHWu-6h&@D9!1_ozD52;Aw|hWsYMw@Sw*=;6-C2} zh8NWpjVP)w8e250Xm-(4Me~ZDDOysrtY~e~hN8_yFBN@U^l8!IqN7D8icS`tDY{Xt zD|Re)E_N&SDE2P)EjAXX73UY5iU$>sDxOe0sd#F!P&}jf`QlB*TZ&&U-dg;6@s8qy z#fOTI6dx@k$?TFROXiiVEqSwKTgmp49VI(UJ}x<1a=zqJ$rmM8OMWV4N^vPy zswm}414`pc6H1dyQ%f^Si%JKS4k{f|T3tH4^wHAkrH_@)DxF>WRO#ZjwW|citwx(=d*@m)BWiOV!S+>9Iqq2|74wfA%yI6L)>`K|yvTw?M zDu)w%%Vp(?a=zTRJf_@O9$%hVo>HDy-lx1@`M~la<<;fQMwmvKMw`Z%noTXHcGEc11k+^GG}Cm`Ow%mWY}1pbxu&O0 z3r&kmFPN5?mYY_Y)|l3rHkdY>UNpU8dd>8v>21>v(|e{}ruR+zOdpyKm=2l_n~s`} zn@*Zen?5(4GhH-YHeE4YHGOTmX1Z?r(e$(FSJUsN+on6FdlhhgT!p+sRiUY{uh3OE zRk&8TS9n(VRQOc{Rs>gsRYX?AR2VDbD-tVGD$*;mDsn5zDohoX6$2}(D@Ij}HtWs) z=0J0hIm8@pjxn6u5f=6rLZx!7E4Hkr-lUgqBBzUBeuLFOUm zYIBXb);z*oZys%iVnXwy=2mmNdAxa|d9rz`SuoEq&os|6&o)14o@<_Oe#X4eyvY25 zd5L+Md8K)cd7XKKd6RjI`DOD~^K0fe%-hV{&F`9bn)jIZnfIGNGJkA7Xg+NI%zVsz z!hFhn#(dU%-h9b?#eCKLjroT8X61^?)s^ciH&kw}e6jMC%2z92uY9ZW?aFs5->ckR zxwmqEf zi(GQ27QXM-`+NI*zOVQD^?EyXa;MzJnwBxQVOE>X7}jDOorcpG(=fxyVNAzu3|X$Z z0u*&<%P(Pv{N(U;qq$IntU0BftR?++YC$!DvW@F)$t`K{`x>nJ^nN zAq(chd{_ueU>U4{Tv!RKU=6H;JlFu6U<(w&HYkFfup5eD9~^)~Py$EcIGlu2a2C$P zMJR)ExDL1A4phQJsDh_ZBWp{486X2?kPMcMWiuHfTgx^wTt>(!*-N6#lsR&Z%$M6` ziM%53IqNt>oxPnY&MfC5XP)znv&t3higbZ%ifgfJgR8)G!gbg6+}+R};U4au=+1U8 zbLYGFxX*j)c!E9cJl#A=9?LVulj&LLS?Ag1+2^_Hsr34LL%f~5BfY8KbZ?F~-@Dg) z##>=^uoA3fi>!2OiIr>Zuu84VR<-?_-QMnJC)&!+uygFK_AYymU2Gq+OY9?dseRh_ zkMElArmwG!nZIC!?7JkViZPWN9=;# zu?P0Vc6FigT^9Ek!Yy3s;J!qJ$DX*doi;3Q1PsW=1Q#}9B0X5&0ufQxY{ zF2@y^iz{&zuEw>v9`i6Cf56RHfQ7gfw__3R#NAkod+|3sh==hA9>e2!5>Me7{0sla z%XkH^;tj08J6MSi@i9KZ=c<2LJ6 zdcFQ$Z`7N0f&Ni%*FWi>^)LEYy0_2><1Knt7r|aqdeL`n`jFa(l#ohowS>Z zX&)V+LsUXX={TLFQ*@Tj(?u$ya=K2p=r-M>`}Bya=m|Ze8m`U$9KeAb#KGK{n{o?o z#i1O=Z8?&oIGSU)6L;lUj^lXl!wEc)hwv~?hB`)J~zRtJ!Hs9s@{E(~oDc6`aF znP}6|bTQq{yQY`vZTgx1W{??ThMOca!Z?g&d+X=1Y786q_#*49Eh1kO02#oI7`< zE9pv>KZx5`Y|y=T?#!H-bIzPIXXdZ*jDr8GA>`}rGYT~02_a9DfeN1Q6o2_SypmVm zQr;TUsq9pKrQAK@^RC{{&`f!ZkOBX_kSMfjJsIdVYqgv@!Dw*lU3nU{$aUQx|wTIB$-XXg%%@cb?ns^?E!Sjh5(bX1mJc^|;+0 zlR=|#60KHK&|!7CO!+F)bd{MS!?jwkMys{EoLa5f&XJ)7+76AzZ8by6Tr$*}Z7fh( z&G|Wb8a+ucsnl*VJx}G-7Ls8eyEYbdZPIRfoOYW* z+D)rUl_%+@Q>&UjJG;L1WO`Fwj&a<2Bb{ljvpXjv)gUV{NS@mjdL4LlI6cpqZ zn2g$d75t_O-OSC^V?y#{akA{?;_{iudAw9@2Ov{2xgFcfz%0Am2&g z+6XOZA^$Mq1{qRvgG}?@Q1G5x3jS=Tg7@(XzGWKWTa@ts9x|;F8`H1!XUs%f7Qe~_ zTv`PTFqaTw)4_ij`!;?N8E7LOp7X}@HbShtji0WEcN`h1BE&#=5ATKF4&DoI3ku0t zNVQpsf%oJSDCWU8!ut;1Tu8>*h}}xlJ-kf|mQHxz0iPb;%8^l7P}b;$f&}Dgg}T&W zDEYx2-p#u-9*&I5W~E&`(VEOwXpx6^!LOUwn&*44mjIV|Gcun?J8Xs* zL%cks0+D%Sh?x+h)oivxDrR>H4I|dM=0TWhF7jt~bA&SwwwkS&KA()RiMfHNkZ3j= z1PR93pm|ovIRKKt;u{x`ktk#MwLvZrl$GQ=@*uO3g917-I3H3R9{XZ45WK0TkPLR{ ziJ7?V3kflCWLQ23ObZ;bJBfJ#843zz^78S}CBBfvje5q?b(wc7~VZHlDbMmw;@l_Rg+ zPKOC(nJcf|4%F^kC@ZhsPSoxk1Idxs?%aTOJLR<7=^;+gZkW&nYd2(e5~qxIJ1{q7 z4$^Mtcck6U5bbt?b~}Q#+X>nY$=%X!P`v)pZj)fUO&(*1oOYW$@J6uRCVU^R-9};r zNl@Dzrrky??J|nC+vEw-Zj;yOF*=Q+?KXN%ZmD)dK`#^)ZMVr~!eJq5ccCc-YKDTs zU~rkd@KVt20@Q7&NeeG+SO#Ah-9*rBHR`qrEVmIXHw+?|$!;M zftuB1278CPtu~MX)a@cN)I$guZb%mlx0LbZCJ34Azbii0T?{vH$YN1Q;06r%3}pWaRhPM#zkUe;-fCfTx8-rSLh;|2gM2RDdy< z@YzY`tby2T4pt<7;w|4Id}2HYQQaKLr&4k+O_$um`VjsoC7&aNdol+vl24!x3EKmo zjSy5q3MZyuvF$_wp<)XJTA#xwQR1h9zX_ky;1i-n{u|-*#+**LhiDT&rwN}5_Bn#T z1pyL%{)70bfHL&wE`KOzWcV}V-!al1^_OZg2x3@0Zy|Adtu|k+ttJEYyfuG0EOtR? zp|HWcU|_zD*BeQi*QGT(As4L9Y1OKHwO$4PjBb-bTS^ka4Qn98^>%n6RD>D+5GzD? zE>OcYjCAsLeo;R?h^THb?kFz{ub`W0IG1%kMt5rFsxmX)VCcsJ($usaB9uAmovF{;!WXp0x? z@8AnN3cUji4w%k7lC8Ew?FPFS8=xgTFf!kk5ADg(VExz(h;$+Fc4@61SV1smbL1X) z0SthDE{N=NwVZjh6+%g;nBoTJL0txjVFo*mBv<40avch92j{uhC^*}ng`ZLyJ3Bm15U$7N$jeu8u6VcI3=6fulR_`&9*iNd z*Q1$>HS;bL4|9BIi^D)vR^ICti9UC$^cid3uM?5W=|zLHG^pEcxSk zP&yz7T}L+9K{iRZG~|F|C|ND%?`D-gL92>x?EP1Ha}mbEy&fH9V8c&HV;C0SWhtq8z#v=!hk7VAuN(WQ*OPl`X?%@$R0xP+l7UptbMLa;e<7VRFxIG7EUKZoQSU8KMPtH5R;3QH9EL$XQs^a8a;UqX^V7O2T8D|}MIXj$?} zzQK{74HOJ{Fs`gFSRBcQL@QL}cG`({2^s1z>$R#}uuyjQTrzyRJ}(cXQs8mf379g4 zT?=MMV}~~dcGSFl;&wW)oWck-a$sSGY3&5w*d0!&7sRJuNbYxo_0xm7(@uvVKns>I z*F-@22D3v`paLsFrt23Fg%g&D;!QBF^zks-IQ||2hCz!>c58^k>0ShSKuk{20)j~~ z;R0SU8IljdRROebK8c65BqxkeCqK6%4n{jL5ZbF(7v>Mh&eL!O12h_aF&U*LW``GO z;20PF5fy0KAQuXVBZKTJ;?~S3qnxlXgw#Zu+IW(0o=4(Qr8I6R0yTM@MD6Ub>s`1J z;&c|o=c+M_%a~7c)%jXjG`ct6gdKwBy3D3LqBVdTDxiD9>eAb=_mexH44SS5A-xSt zP;hZAAaQmRXryXx{$N$U#%Ol9-X?`E;#~ye4cDX!%>zLjoJ)w*326$b6H+_FoRFh{ zIiUg#Iw9aWIw6%>Ww3)Vm=kii(Fr;2Fi3}39Zsv=8RmovoF13c>!$x8a)+!kPH3p; zgsg6_SLY_Kx$Za@(CoqqIo)1p0SFB?m7KONosiq%b;Gudqr(HMi6(SHc7w4?9|Vms+1w^O ztkA{egX~81L3yUGeGum*cFsB&a;xn6=`naAqtyXA45KPHwM#GLbU3U=^g^jQU3wv> z(_uqPQvjAgKfOyY<0b|d&3F&J_f!3jn2LnenqpKsUai@}gq?~U$Wde&V216#B-QfszL%<88!(*~JO~ybd zWOR5L$0aEALJ7BX9bIv_2qHmgacH>m-J0dA;3OY(58MuQ=f z27)1z0fQl=4Q|+KH^R=Q$_$fEbVFJ-yi(^-HUSkAmscHCDTF4$Ob_` z1Hdj2kE?TK+|N)U2%;1UNrFra1cM=}_fe_-M!ZiVi-Gd8<01BiI5?vB!5GMt7cb2A z5<^2EVQ?fu>@XwkY`CtXu**8lG;Nm79T_MhdqXt3d<0h z5LzItgCPaN^Fs>DBfeyh^eR(Ak^$dJ9^qCdza*37RxBoyKcvEt$Djhi?}Vq2_5?Rb zE`LaYF6)O3!PQ7g1izq9VfiIZijY4dfk^pexXU$!LPI@{Q|`w68o zGbK5BvV&`cq_aO(DxcWh*yt)NE!98DDIuv*30usKJl|GZU0s^Y5t*dzmblK2_V(5@ zrHu(^THD(@IxUu4XLXHc_RUrWB4q#*Q6zb>=Ch%7iKAy1E@57R%Wm z>y(M(1`;x+qONZH)wZ@{nL@_)x{VuGrIeC{lvNuy*0ozKjml#70QhKSjG4At5^38S z8&BG|Yv_@TOc=$DaZQ(+o3Gr~ zS<*VM`F!3pjg4P^0^HBZ$oOHyrAwD@b#~sq#`y|cINyY8w>vxAQ8bTbW@boObNqv< zs!gpte`)5k&(6FAbyJ2EE90_XnmKd!6`f_mwaR77iXT-ffAnR0yRV_X{$R)L+qZxo zR(adk(&ED_(BaxMuDK2!s$U!6T=omEyz=H1p1*ww*#osxwiJ`NVZV6pxtYy6%T(X8 z`SV{-qAEzUAs3-mV4~dh;#O1}0G$>Q^%^0jVpqXU=>nTc=b^G3)A*-+MSEW&CTiXD>Y5*m&AmUvGc;x#ymls8de( z;m%X1PJh+d*z`5fxhau=l+JCgv+xGjnRLtN^2e(x zO~&%K=grgoVdl&?k6*m_b&CukK|+*qiMK&znp@l2zFt#WT7C_PZA?U|j9I&N>y}Ma z%YPCo4JH*FNHufbc;k=%`rLD`xPX{fZpiq1#V4|YD6QJI@0!?}Cl^0BX3WEtTef^y zCXS_X85vV-)SBSf`5M#}bsMi}XqV~c%+W&UUbffQ?>l(t(9ve@D(6k`p^+7al+d@^ zpn*3NzrnHh&CQ!F)`|-2HSTtih0D!-%D8rI<%Uh0${wO4YW|M;dfODyG{OLC0#}Fw z7q93TvX|A=ta%AW+XOCy%S?FqkA;PcPksG$b31pV5JwfCf%3Wx^lvtvI@S2i?c3kL zwPC^R*@jb?uD5UxX8)*)$&QY$)u%6Btj`Ge2j*KhT?=`;V)ts?0DDibnxTYX0ig=Eh5x8h#kU zRQI>vx`C;-WiZ)wAX7VT-o$GI zbW(r#tFO-9gifBH)$mV0`q9+%l$6l}2uc6!^ywzxeaFFI)o~v?dh{3!LY$F|cy-R4 zxyI$omn||F7Oz;fYW{uq+%tYPPBOsM$;gnA#cT8YH{O_CSyQvQt=JNGe)@wCj*ruk z>`0^V+oKH)N593{3Q(Q##v5;~)|Ka0e1KyY`d*47jX6ImJ|;%#)e9uwT3ueguC-rC z=3ab$`t%>c`r5#;0XYiZ3M?AFEe=l6oR(rN>uM9;=(-vF8?+rItwYE4<$ z0?;?qrDYRGkIs7at+!qs4>P%HyM5MB&bW@BgLS=}=@d6Y0>D%9N$IuIo3V#goXrnPoDyF4rJ-KXmG!!W7E&#)*ClkcG>Npec9Of)oGgV$|{3l zm9NrGI+uwLgDox9_?x68pBZ^IM5wK;o^= z-MeeQ&!uz9#2VB9(TyJf?4pR|!MPB33!QsjTi$Rb5$noPx>~(dUir#wb?S_D{ zZ4Bix2-XKY-XQe#6y@*^XndK#^_^aCkGITDeQlH~WG`x`Pc9(Qit}W`}gliXyE)1+nlWBS+qg zjx>bFvyg7m>+|O?^#t_EvvmIaW!~GjeW6nQN}@j!;(`=A0%Mj*^%U5HhyQc->_31B zRfedPKp5@oe1Ir3fuc{u=U4^H1jz)>p0QIH<)AGO9k=~U7+Gy}U%KQue)Q;Z&!tOl zBe4E#OG^{j;{TkOo<13uPeSDja%=^2_|>(xHt+u3yZ3wB+ODA}B(@mkJKjJ&rj*s0 z$MkKSC4p&|`%m2O3JbX3z4#|U@ts{=Qo?18961p^suu=rhGti*g|EK)Z}-y~i{G`0 z!$vC0E3l0A@s+kVcD=gmlTYeal$OrDZ^VeKg=J;co^bxsz9zA?zFb)Np(>@jH1)v4 z_uiWY?iHtK%$KuikyMsanpZy7)n;M%d*5$n%=mNDwQHX0aAiWGdODLrp|VknSB!Sp ztcl5l$uv}!(&w5Dfti+cUOjQ-$O%i4 z$#GP&oU$;Z5Eh>lkMHIhxu&FDFmcA=jegYiczXKdE?9tTOJn%q8W0u`>C`rz{rqOmuym#*PE-vXHd(t7&Di3Srcx6_b##2;qQE?iPt zy0p@4uCnN>jg}`&Z_1_}J6oh#lpL5=-1wVVxfMOxbJby9z@4cQZ+t zfJyxIz;UoJjBIOfS$H+>!p7?Ar4Q;Dw~DJ3HJi9vqa|DDLx@Ch(FA9aQs0pNN%4s| z1q|5YM}h4%f)Sq_D)tlOdA9x z!J)-^E|kAoTZz4`jHE-clp43Isp;Ie61~2e7Akif+wCn^uU^<#f;}z4o>p3NP|hi9 zw`}?3Y+&Tc$r+2|oMBT96yJ2Y1Up)3nIsg40DDUlbsN&&G1ozdgT->SwiG+MrKhFN zOrhIB<-6+ZYt!hi6;5*mm4u)kW0d1yFftC(UdEZ1p~ZkbmNPBau3d)>uSwUd#ElJD zxg0C*XW=+NO~ z($XgWdH(#;qp(tUtJ0FqHrQ}o7FYfTjHdf<}g5H3QshGgU!#Xc5xTeip)b+ z{*Bxo&YAGV`s(Us;H-aqc7r93Mm^v`shX5nCZL`mAF%(7FKHY0?5T%&$f=#UFoAsO zUD4|hh=0=7tM=3mApC1pX|krxk|Hf;C^W;8)9 z=)8XITFV(-W75GlX3Y3a7TrRf1nRU5R)&O*-~f4l&g-wMvnU(%52mF(25byev&|BR z5#Wpw;O1y(C>Bkv-oCxAgzgwJKH!|GPl^KjI$N(__d(<1u<^ehqZ>AL%&+MTjWWVw zIWrk&X4Td2m6ntgPE1RCP)~XB@CQ40?hxY=K@zPS-g~d~`#NPDvUAMObic^{*%&(e zqRar3xEMmc@1>?b0-@fPO&d0tz+RwQ=pW|Baj9|1IIlsOUVm@JilR~Qy|Q7y&^@QX zExats6pMw$$HX%-8 z@wo?e$}F72YOh!VU0H#b%+U%u9*Ys}g8(1;O}nk*JnDO`C*{hRsmo;|yF?cDjn z!=Qg4hjlx4?pzPrKX4ol9;ljf3+%^eLwWi87wC+&>4Et82b$Qzk&cfO{7R$FlEFq6 zS{NKnIMYLJ?u50Ho#OIqF=xg5?{B_HHw@1{`M?8Dp6%>x zg*CPhn_FAkVEdT0Hyfjn?>$MaYOUCJxF=!HL>|aSY?8+n$@3x;l{2B=mfYlZd@8l4cY#O1GIWnE^4P% zQ~!@#UIzdIwzL*{WlMIHKrxLllF^pEaT6vw~6bf58Uxol)z$G#O zFCd?7t(~1Xo6kJf*4Eysv&12vGgFGG!T&!W?%cUyQflf$%b@pg0K~qEbNn@ zWuD-QkjIn&pf7-00)`?eq;2g`GjiBfR$Q8l=70FuapNAvS|3VHowNa{{D4!guuS#W zEb1@gVkmc6WQJm?g)J*ZTP@6+(S0VO5+hr2%&CKeF=%T0w&L1kTxr00hoD!$*&N`(2M=?}D=dj@c;qxuxpA#og0_OB0u1)~ zj!l~|A#0GN-p=;owq)E>#|a1y2Z66SXpFd0-~u%eXj=nXE63l%6XN5CC|Jd%mN*Q1 zk+lhwrTB)cz5^8|pmkg_8kEt6Tuj8_da{=4=xqerv?g7sB?QC7AD^D~)2hdH;uE5Fw`@`6$z-631siA4oh!M&+ z(Y%3*12@Kls=JR+XL5A8&XD+~a>R&?S8;JeYy)KxgskW~Fj_TPlCEfBo}#2?7@gZ7 zSQIG)Pp8OC){Rb7!ZO&at1BuhEn*dvClIDCGgnt*glb}wmDO~zGP^>Dp~`A;FxIw# z|Ddy($Qcq42KDDjXmXY(C*BVLAZ&8YCNvpP5e^jyxz<<`Zu^lv%S#iNmeY1^x{O8( z@}cTOY-K^xYp@Z=WbQUvT6_}xV1)b2K8hcFEG;dS;Rk&Je(*8a?EPT5h#&L`<`uVa zcf$-;zz>EeZTE%Z2Yo(2eh{azJ2$RhzZ|fKkdaQx{rEwj&yOEWDcii+whK3=gp3qQ z=Eo2Ee181k<~T-0_wmP7Qvg5c zOJXs^6MLGPzT8?{`;ij>gwBs@Yd0Xy1p*1g9U_3RYy(Xz{|q9T7k>H60t68Hf&hf) z4gj#I832UMfU?`O86!e5NWvar0$xA867(!nH z!w^ob<@OZTa|fm#_R#u{TyAN(e1y{R?AxcVUIMLL?|iPNau)51%=A?n_v(S!oo|g+3W{ z;jcp_#Wr%Hp$nywWRhc79DnYL6)RR%p|b?eh9es9Jk7qs8fIMMt4^cD?OK z9r}8MI-D9n9R?3YW=QwDjvsF*U$LURAqaZdPegl*Kb#uCA3}GJ2Bg{0bnaYJ!~Xrw z0}TydRF#)kA&+%_5TcJe|I5AvA>Q&ZiDn#aIB=lhsLRzLQbp>k-|}M+eSL^QM8}Bo zbnT~CCRe-~-}GY;`-5a(V-PPK1X%)Ck2-^8DsZ>(%{L1v+|t+A7(|4E3p7I{iu$w% z&Rkgbt^f!0y@v69B;(6KrEG1Ft&U?b6$yhVCsQ1=DBG25`i*F@?~lUvbsu98PadFR z-TPiy+1fh0{UbwBQHg^N-LewEAkO#A!u6ZJh9I_scyXXsZr!%cGC4hc?C4RWCM>4r zV(TLU2GMuNFo-D1vTY&;aa0kt$sz`^U#a#n2C*G5)q-HRY}@wU7+A={RfhLI{rvNF zu$Tq7Jla=fA7c=YTBumJti?rapgQ)WhK5g{fBNZZ2~w)CWW<(=*ppuVd!)F6L77%%T zi9tj|QE%V24W(-M-l$Rc!NLk+5EG_7{q(aR22`rgp@3+Qzu2*TI~8mIgE)B7lqpYt z?#B-M`j>EDVGw;M!R^(5@x`7`sVzqN-uEZH{*Qp~ld@XCAo}_agJ}C=|NecS?bz`N zU=UY4K*jr~|21ve6GLDRN1|H-29eUmMc-aw5ZCXfl9gf*_0#Bx#hrXMdIelw|IlPW zwO(NmFWc6y->`G{ZpWtq3}WUiyLzV2Hk6!Vn+EMJt3MCNUV|JwpZ$PJ9A&3H}n%;Dm(K z^mIQA5tpQU4ny?$1Q;SpY|>yU4DpUt8w5lA7J|Dyh|a|ArPyGIJ|BZ2ram-j(t~jT z90`FT`V>Jh#0!TH9QX*f`eTD3CZ2Bf`4|kbFqIq3k;E_*qECQ|VN8N?B0{91pb&jB zD8$}ZAm9ea?SWAI5ba*(5rAI7_l_7G4d)U64O@sJ4AJL{21E1-)unxO;J_h>?olFR zw;Vip=*s{M5oZSvF(5Y^vR$QDcMk7;=&acO8bz8$5@$AK{yPNRuHTXbcqPNDDApX z0mC8ov{(+#I1z~GmWW=yxhVAzBqCKkL?YVVOw`D&v~X^rkVAlozAzx7w0psl_4ybO zv8Sa%frz;MwHKBPu&DyAFDQy9A`sCR21LY-v5#OXBO5Fw``ecEKxFIL>w!1(?)}!745&NW$J_REB`VNQ) z*Z|>cumK>VFIFI8uZl(kBGMMb07QgMP7#QBZx|49KCK1EM;ACmUlSw|T$$<|NDskU%#ui9TT>!Ei~^jc0bA5N=;O%oMYTlMY-_6vB;2n8Z6# z zWa0_m~4FHJah=LVb*uTv57E~6yTduY@#n5o0!6-0X8vBkt%~t1V1U@ zHKo`@HVX-X9*W};u!&t|DEGxjfhN+yg3v@?RA?gAeS{_=WeQD{x!dS#;TbgXy3C!I z4+kak;h;qN)k%!v{Gi0}r0sktC=vd0`&sc&!yr&19|}t3d3jJGFQU`@phWsbSmB^2 z8e{<|F_uhQ`Cfn$`Cft&`JRIkdtP)olSTlP$oC~Ek;yOsO62{M5tq zmEn?Pctmy$!6o(&%{4P3oq_1EP-z~9fw1JT+l^Ob@3N3H5WiSmTKeueueUqEM4rpd zj&u~_R0kF5k_mugSyEB4WCChZLhwn58QHJQnx#Ma_1E3QCGuV15>dQGc#0q(SrGaV zbQ)q$af$szG#r;$34eUkF*PGY%Hi)VUbAK~fDn@K>rO%EBKmQOP0g1tUxd9KhBEB} zm&nWD5?wGvEe?orB|5cu``*3V7Z(-Hg8leNha-Ma_1=5yPsNH$-iG5L1Sy=g9pbelWg`Xt9A3C zvJ<5pEiUOWavFYu4}Yp+p6-q7y}!@0yi? zE1NS(hpTmUWD!b-tt>8a@2rAL|2zq{0EEQ7h}(ehxCu3sDA zDB~<%QG``!7h%v=er&hb0X8rcn3%S4@7_gAVb?e*gl`Fq;RApMV>RrHw*E|9TY}5pBiCNkO3;qlK-hhKnC z((KgK?4?yzOCNz&F5{}Xbr}qp_~!qeIrF!PfSr)&mHt?QW2v_ab_GUS`@JqoH%R7%P-GdKxbmo(c8adadLwa#x{%ELPW=79s#GuNDU*l&lS=jS zCJ8u^|2dN`E@O>@FJ<6$ESy||h$1{GaUh@zf3WZT`F%g2*ZRrH$rFtMu`XM`VZ$mQ zJ75%I6yqpHksHAcPfmS-s+3~b@ZtBQNid4II$c8I5Fu5c0Vnd{*@*0nM7Ht8h9;F8 zEDtJA@Vo#{M2V?}OTmeKU!Nb9hzGmlpISgc;4wLmZ##5oE8@tu9y+uQJkdjNNDrRy z5Ma7+I3mw8RAS~YRjPj)7LH2f1ytfBJTeE@Iq|P6AlK7BIdNjgKP>84{a3&UG zhj3;!!ynqy@wB273wb~Iu$#Gsp2yNufc)_?phMc%FintQolrqI=rDrJ5~!?U=81F} z)UbP*{Q$!~5cBz!RJLg-&=7zjFBC^3_OWob1RY0mQp6D+hA^a?Pxw7Pdeou#MIWi) z1k=E}M&a;78W70r{BJo$;3*3u}e;E!_ zxp6FISM$nYZ9DB*bOKl>#yWo zLtJB>H#R^!>YV;C)*`KaS#!Vunp3MnoM{?OB?j0cv#|Ne&khYsz7^|O-nAw$wj zDl5z3o7r!TA3b{H0O3?c9p4?`AfL^SnOisyc8gD5xUm0+nVCO?IsM)Yg(73``SbOU zjvhT8&N|d4iPd)lHYhIL!558j1r1liq*Hk|wMR&iVYEg^2G*2 zNjZJSVS@Yh`+pL2mLcB-VvzSE262UfE#R_+VD^mHkh2W=2#CQuP$4_ZaMV1iKzo+V zn^(Lr&~;=*#p$rq4Ee~ALBK|drx}hipvJ?gv}3c@35P z1E2~8RDtm~#^D1-hM#2!ZZHfl$R-&fctLSE0$#A|3{lTAq+%B|g&w;3Xx>GOx)ceAT z^sJGr2|X*_2c^UY^g&HMtKu$wfdf5bULTZV3fNym;4Xc}fj$ss52|3)>9q$H^s>lb z5B*+tq=&@={qJD~y)1T@KI1?y8QH_)jQU;s+d~HSve;ezGY<5Ukv%NVsQNuErXJLS#Nnq0CHtlbCI5F%zwc!bqfABq-=!ZTzhc(<80(Yp zUwRuenV^i)8t8q{Yq^K;B0`E>)~?gSE9yh72KpSHS3X~8YIwP>QbKD8eh!ol zPLK2y$RF!nq?%}YpqA+Q*xNw-w-Y9ODqbmaTH^ds{|`X<2FXm`>QvE9eYf2=JUW%@2Qn$leTPaj(@ZBgX= zJJbKa9s0H9!_xx3iv2+c)n3Qdjp zEJs*Oi&!S=i@y%~*ovslWG}_O%3WBN?p*^l#Z)ekJ?t)~@?n_*)r7s0O9*5SyOYb_ zby}dBuJb~UK=!b^n97G`3ads)2+PJ2~*>dnkj*72c&U!-2@`>T~{Mg~2W8f_PZ|;L`F>(d!H@6Fo1!4bC6SQ}jB6Ylxor juYo>mVQ{-6J+a( \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\necho \"\t#include \\\"basic-dyngen-ops-x86_64.hpp\\\"\" >> \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\necho \"#elif defined(__i386__)\" >> \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\necho \"\t#include \\\"basic-dyngen-ops-x86_32.hpp\\\"\" >> \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\necho \"#else\" >> \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\necho \"\t#error Unknown platform\" >> \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\necho \"#endif\" >> \"${SRCROOT}/../Unix/basic-dyngen-ops.hpp\"\n"; - }; - 0873A66914AB8A40004F12B7 /* Run dyngen */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(BUILT_PRODUCTS_DIR)/dyngen", - "$(OBJECT_FILE_DIR)-$(CURRENT_VARIANT)/i386/ppc-dyngen-ops.o", - "$(OBJECT_FILE_DIR)-$(CURRENT_VARIANT)/x86_64/ppc-dyngen-ops.o", - ); - name = "Run dyngen"; - outputPaths = ( - "$(SRCROOT)/../Unix/ppc-dyngen-ops-x86_32.hpp", - "$(SRCROOT)/../Unix/ppc-dyngen-ops-x86_64.hpp", - "$(SRCROOT)/../Unix/ppc-dyngen-ops.hpp", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "arch -x86_64 \"${BUILT_PRODUCTS_DIR}/dyngen\" -o \"${SRCROOT}/../Unix/ppc-dyngen-ops-x86_64.hpp\" \"${OBJECT_FILE_DIR}-${CURRENT_VARIANT}/x86_64/ppc-dyngen-ops.o\"\narch -i386 \"${BUILT_PRODUCTS_DIR}/dyngen\" -o \"${SRCROOT}/../Unix/ppc-dyngen-ops-x86_32.hpp\" \"${OBJECT_FILE_DIR}-${CURRENT_VARIANT}/i386/ppc-dyngen-ops.o\"\n\necho \"#if defined(__x86_64__)\" > \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\necho \"\t#include \\\"ppc-dyngen-ops-x86_64.hpp\\\"\" >> \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\necho \"#elif defined(__i386__)\" >> \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\necho \"\t#include \\\"ppc-dyngen-ops-x86_32.hpp\\\"\" >> \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\necho \"#else\" >> \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\necho \"\t#error Unknown platform\" >> \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\necho \"#endif\" >> \"${SRCROOT}/../Unix/ppc-dyngen-ops.hpp\"\n"; - }; - 0873A67214AB8AE9004F12B7 /* Run genexec */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/../kpx_cpu/src/cpu/ppc/ppc-decode.cpp", - "$(SRCROOT)/../kpx_cpu/src/cpu/ppc/genexec.pl", - ); - name = "Run genexec"; - outputPaths = ( - "$(SRCROOT)/../Unix/ppc-execute-impl.cpp", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "gcc -E \"-I${SRCROOT}/config\" \"-I${SRCROOT}/../include\" \"-I${SRCROOT}/../kpx_cpu/include\" \"-I${SRCROOT}/../kpx_cpu/src\" \"-I${SRCROOT}/../Unix\" -DUSE_JIT -DGENEXEC \"${SRCROOT}/../kpx_cpu/src/cpu/ppc/ppc-decode.cpp\" | perl \"${SRCROOT}/../kpx_cpu/src/cpu/ppc/genexec.pl\" > \"${SRCROOT}/../Unix/ppc-execute-impl.cpp\"\n"; - }; - 08CD3F3214B665E1009CA2A2 /* Preprocess Info.plist */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Preprocess Info.plist"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "sed -i '' 's/@PACKAGE_VERSION@/2.4/g' \"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\""; - }; - 08CD43CF14B7BD01009CA2A2 /* Change SDL load path */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Change SDL load path"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "install_name_tool -change @rpath/SDL.framework/Versions/A/SDL @executable_path/../Frameworks/SDL.framework/Versions/A/SDL \"${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 082AC24F14AA59B600071F5E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 082AC26214AA59F000071F5E /* lowmem.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0846E49714B124DE00574779 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0846E4B114B1264700574779 /* ieeefp.cpp in Sources */, - 0846E4B314B1264F00574779 /* mathlib.cpp in Sources */, - 0846E4B514B1265500574779 /* utils-cpuinfo.cpp in Sources */, - 0846E4B614B1265A00574779 /* ppc-translate.cpp in Sources */, - 0846E4B814B1266000574779 /* ppc-jit.cpp in Sources */, - 0846E4B914B1266600574779 /* ppc-execute.cpp in Sources */, - 0846E4BC14B1267200574779 /* ppc-dyngen.cpp in Sources */, - 0846E4BE14B1267A00574779 /* ppc-decode.cpp in Sources */, - 0846E4C014B1267F00574779 /* ppc-cpu.cpp in Sources */, - 0846E4C114B1268B00574779 /* jit-cache.cpp in Sources */, - 0846E4C214B1269600574779 /* basic-dyngen.cpp in Sources */, - 0846E51314B128ED00574779 /* sheepshaver_glue.cpp in Sources */, - 08163340158C125800C449F9 /* ppc-dis.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0846E52514B129EE00574779 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0846E52B14B12A0800574779 /* ppc_asm.S in Sources */, - 0846E55314B12B0D00574779 /* paranoia.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0856CCBE14A99E1C000B1711 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0856CFC114A99EF0000B1711 /* adb.cpp in Sources */, - 0856CFC214A99EF0000B1711 /* audio.cpp in Sources */, - 0856CFE214A99EF0000B1711 /* cdrom.cpp in Sources */, - 0856CFE614A99EF0000B1711 /* disk.cpp in Sources */, - 0856CFEC14A99EF0000B1711 /* scsi_dummy.cpp in Sources */, - 0856CFEE14A99EF0000B1711 /* emul_op.cpp in Sources */, - 0856CFF014A99EF0000B1711 /* ether.cpp in Sources */, - 0856CFF314A99EF0000B1711 /* extfs.cpp in Sources */, - 0856CFF414A99EF0000B1711 /* gfxaccel.cpp in Sources */, - 0856D00914A99EF0000B1711 /* macos_util.cpp in Sources */, - 0856D02514A99EF0000B1711 /* extfs_macosx.cpp in Sources */, - 0856D05014A99EF1000B1711 /* prefs_macosx.mm in Sources */, - 0856D05A14A99EF1000B1711 /* sys_darwin.cpp in Sources */, - 0856D05B14A99EF1000B1711 /* main.cpp in Sources */, - 0856D05C14A99EF1000B1711 /* name_registry.cpp in Sources */, - 0856D05D14A99EF1000B1711 /* prefs_items.cpp in Sources */, - 0856D05E14A99EF1000B1711 /* prefs.cpp in Sources */, - 0856D05F14A99EF1000B1711 /* rom_patches.cpp in Sources */, - 0856D06014A99EF1000B1711 /* rsrc_patches.cpp in Sources */, - 0856D06114A99EF1000B1711 /* scsi.cpp in Sources */, - 0856D06214A99EF1000B1711 /* audio_sdl.cpp in Sources */, - 0856D06414A99EF1000B1711 /* SDLMain.m in Sources */, - 0856D06514A99EF1000B1711 /* video_sdl.cpp in Sources */, - 0856D06614A99EF1000B1711 /* serial.cpp in Sources */, - 0856D06714A99EF1000B1711 /* bootp.c in Sources */, - 0856D06814A99EF1000B1711 /* cksum.c in Sources */, - 0856D06A14A99EF1000B1711 /* debug.c in Sources */, - 0856D06B14A99EF1000B1711 /* if.c in Sources */, - 0856D06C14A99EF1000B1711 /* ip_icmp.c in Sources */, - 0856D06D14A99EF1000B1711 /* ip_input.c in Sources */, - 0856D06E14A99EF1000B1711 /* ip_output.c in Sources */, - 0856D06F14A99EF1000B1711 /* mbuf.c in Sources */, - 0856D07014A99EF1000B1711 /* misc.c in Sources */, - 0856D07114A99EF1000B1711 /* sbuf.c in Sources */, - 0856D07214A99EF1000B1711 /* slirp.c in Sources */, - 0856D07314A99EF1000B1711 /* socket.c in Sources */, - 0856D07414A99EF1000B1711 /* tcp_input.c in Sources */, - 0856D07514A99EF1000B1711 /* tcp_output.c in Sources */, - 0856D07614A99EF1000B1711 /* tcp_subr.c in Sources */, - 0856D07714A99EF1000B1711 /* tcp_timer.c in Sources */, - 0856D07814A99EF1000B1711 /* tftp.c in Sources */, - 0856D07914A99EF1000B1711 /* udp.c in Sources */, - 0856D07B14A99EF1000B1711 /* sony.cpp in Sources */, - 0856D07C14A99EF1000B1711 /* thunks.cpp in Sources */, - 0856D07D14A99EF1000B1711 /* timer.cpp in Sources */, - 0856D07E14A99EF1000B1711 /* about_window_unix.cpp in Sources */, - 0856D08714A99EF1000B1711 /* bincue_unix.cpp in Sources */, - 0856D09814A99EF1000B1711 /* ether_unix.cpp in Sources */, - 0856D0AA14A99EF1000B1711 /* main_unix.cpp in Sources */, - 0856D10614A99EF1000B1711 /* prefs_unix.cpp in Sources */, - 0856D10714A99EF1000B1711 /* rpc_unix.cpp in Sources */, - 0856D10814A99EF1000B1711 /* serial_unix.cpp in Sources */, - 0856D10C14A99EF1000B1711 /* sshpty.c in Sources */, - 0856D10D14A99EF1000B1711 /* strlcpy.c in Sources */, - 0856D10E14A99EF1000B1711 /* sys_unix.cpp in Sources */, - 0856D10F14A99EF1000B1711 /* timer_unix.cpp in Sources */, - 0856D11114A99EF1000B1711 /* user_strings_unix.cpp in Sources */, - 0856D11614A99EF1000B1711 /* xpram_unix.cpp in Sources */, - 0856D11714A99EF1000B1711 /* user_strings.cpp in Sources */, - 0856D11814A99EF1000B1711 /* video.cpp in Sources */, - 0856D13F14A99EF1000B1711 /* xpram.cpp in Sources */, - 0856D33914A9A704000B1711 /* VMSettingsController.mm in Sources */, - 082AC22D14AA52E900071F5E /* prefs_editor_dummy.cpp in Sources */, - 0873A80214AC515D004F12B7 /* utils_macosx.mm in Sources */, - 083E370C16EFE85000CCCA59 /* disk_sparsebundle.cpp in Sources */, - 083E372216EFE87200CCCA59 /* tinyxml2.cpp in Sources */, - A7B1921418C35D4700791D8D /* DiskType.m in Sources */, - 087B91BE1B780FFC00825F7F /* sigsegv.cpp in Sources */, - 087B91BF1B780FFC00825F7F /* video_blit.cpp in Sources */, - 087B91C01B780FFC00825F7F /* vm_alloc.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0873A52F14AAF05A004F12B7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0873A54214AAF18E004F12B7 /* cxxdemangle.cpp in Sources */, - 0873A54314AAF18E004F12B7 /* dyngen.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0873A5C214AB8038004F12B7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0873A5D614AB80CA004F12B7 /* basic-dyngen-ops.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0873A5C914AB806D004F12B7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0873A5D814AB80E3004F12B7 /* ppc-dyngen-ops.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0885A51E1593E3B6005C4F7B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 08C99DA11593E79F00898E41 /* clip_macosx.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0885A52D1593E47F005C4F7B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 08D93A16159FE174003B04EC /* clip_macosx64.mm in Sources */, - 0879BD5E15A88F7600DC277D /* pict.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 082AC26814AA5A4800071F5E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 082AC25114AA59B600071F5E /* lowmem */; - targetProxy = 082AC26714AA5A4800071F5E /* PBXContainerItemProxy */; - }; - 0846E4A714B1253500574779 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0846E49914B124DE00574779 /* kpx_cpu */; - targetProxy = 0846E4A614B1253500574779 /* PBXContainerItemProxy */; - }; - 0846E4C614B126B600574779 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0873A5CB14AB806D004F12B7 /* ppc-dyngen-ops */; - targetProxy = 0846E4C514B126B600574779 /* PBXContainerItemProxy */; - }; - 0846E4C814B126B800574779 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0873A67314AB8AE9004F12B7 /* ppc-execute-impl */; - targetProxy = 0846E4C714B126B800574779 /* PBXContainerItemProxy */; - }; - 0846E52E14B12A2E00574779 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0846E52714B129EE00574779 /* ppc_asm */; - targetProxy = 0846E52D14B12A2E00574779 /* PBXContainerItemProxy */; - }; - 0873A60314AB83CC004F12B7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0873A5C414AB8038004F12B7 /* basic-dyngen-ops */; - targetProxy = 0873A60214AB83CC004F12B7 /* PBXContainerItemProxy */; - }; - 0873A62714AB869A004F12B7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0873A53114AAF05A004F12B7 /* dyngen */; - targetProxy = 0873A62614AB869A004F12B7 /* PBXContainerItemProxy */; - }; - 0885A53A1593E4BC005C4F7B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0885A5201593E3B6005C4F7B /* clip */; - targetProxy = 0885A5391593E4BC005C4F7B /* PBXContainerItemProxy */; - }; - 0885A53C1593E4BC005C4F7B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0885A52B1593E47F005C4F7B /* clip64 */; - targetProxy = 0885A53B1593E4BC005C4F7B /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 0856D30714A9A704000B1711 /* VMSettingsWindow.nib */ = { - isa = PBXVariantGroup; - children = ( - 0856D30814A9A704000B1711 /* English */, - ); - name = VMSettingsWindow.nib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 082AC25414AA59B700071F5E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_PASCAL_STRINGS = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ""; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = lowmem; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - 082AC25514AA59B700071F5E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_ENABLE_PASCAL_STRINGS = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ""; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = lowmem; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0846E49B14B124DF00574779 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = ""; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DATADIR=", - HAVE_CONFIG_H, - USE_JIT, - "_GNU_SOURCE=1", - _THREAD_SAFE, - _REENTRANT, - ); - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRODUCT_NAME = kpx_cpu; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; - }; - name = Debug; - }; - 0846E49C14B124DF00574779 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_AUTO_VECTORIZATION = YES; - GCC_DYNAMIC_NO_PIC = YES; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_ENABLE_SSE3_EXTENSIONS = YES; - GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; - GCC_MODEL_TUNING = ""; - GCC_OPTIMIZATION_LEVEL = 3; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DATADIR=", - HAVE_CONFIG_H, - USE_JIT, - "_GNU_SOURCE=1", - _THREAD_SAFE, - _REENTRANT, - ); - GCC_VERSION = 4.0; - "GCC_VERSION[arch=x86_64]" = 4.2; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.6; - PREBINDING = NO; - PRODUCT_NAME = kpx_cpu; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0846E52914B129EF00574779 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ppc; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = __ASSEMBLY__; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - ../Unix, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRODUCT_NAME = ppc_asm; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - 0846E52A14B129EF00574779 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ppc; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_PREPROCESSOR_DEFINITIONS = __ASSEMBLY__; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - ../Unix, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRODUCT_NAME = ppc_asm; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0856CCAF14A99DE0000B1711 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - }; - name = Debug; - }; - 0856CCB014A99DE0000B1711 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - }; - name = Release; - }; - 0856CCC514A99E1C000B1711 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - ppc, - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; - GCC_CW_ASM_SYNTAX = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_ENABLE_PASCAL_STRINGS = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_ENABLE_TRIGRAPHS = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DATADIR=", - HAVE_CONFIG_H, - USE_JIT, - "_GNU_SOURCE=1", - _THREAD_SAFE, - _REENTRANT, - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_VERSION = 4.0; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INFOPLIST_FILE = Info.plist.in; - INFOPLIST_PREFIX_HEADER = ""; - INFOPLIST_PREPROCESS = NO; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.4; - "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.5; - OTHER_CFLAGS = ""; - OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ( - "-pagezero_size", - 0x3000, - "-Wl,-seg1addr,0x78048000", - "-lkpx_cpu", - "-lclip", - ); - "OTHER_LDFLAGS[arch=ppc]" = ( - "-pagezero_size", - 0x3000, - "-Wl,-seg1addr,0x78048000", - "-lppc_asm", - "-lclip", - ); - "OTHER_LDFLAGS[arch=x86_64]" = ( - "-pagezero_size", - 0x3000, - "-Wl,-seg1addr,0x78048000", - "-lkpx_cpu", - "-lclip64", - ); - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = SheepShaver; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; - WARNING_LDFLAGS = ""; - }; - name = Debug; - }; - 0856CCC614A99E1C000B1711 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - ppc, - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; - GCC_AUTO_VECTORIZATION = YES; - GCC_CW_ASM_SYNTAX = NO; - GCC_DYNAMIC_NO_PIC = YES; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_ENABLE_PASCAL_STRINGS = NO; - GCC_ENABLE_SSE3_EXTENSIONS = YES; - GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_ENABLE_TRIGRAPHS = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 3; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DATADIR=", - HAVE_CONFIG_H, - USE_JIT, - "_GNU_SOURCE=1", - _THREAD_SAFE, - _REENTRANT, - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_VERSION = 4.0; - "GCC_VERSION[arch=x86_64]" = 4.2; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INFOPLIST_EXPAND_BUILD_SETTINGS = NO; - INFOPLIST_FILE = Info.plist.in; - INFOPLIST_PREFIX_HEADER = ""; - INFOPLIST_PREPROCESS = NO; - INSTALL_PATH = "$(HOME)/Applications"; - MACOSX_DEPLOYMENT_TARGET = 10.4; - "MACOSX_DEPLOYMENT_TARGET[arch=x86_64]" = 10.5; - OTHER_CFLAGS = ""; - OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; - OTHER_LDFLAGS = ( - "-pagezero_size", - 0x3000, - "-Wl,-seg1addr,0x78048000", - "-lkpx_cpu", - "-lclip", - ); - "OTHER_LDFLAGS[arch=ppc]" = ( - "-pagezero_size", - 0x3000, - "-Wl,-seg1addr,0x78048000", - "-lppc_asm", - "-lclip", - ); - "OTHER_LDFLAGS[arch=x86_64]" = ( - "-pagezero_size", - 0x3000, - "-Wl,-seg1addr,0x78048000", - "-lkpx_cpu", - "-lclip64", - ); - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = SheepShaver; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0873A53414AAF05A004F12B7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - INSTALL_PATH = /usr/local/bin; - OTHER_CFLAGS = "-mdynamic-no-pic"; - OTHER_LDFLAGS = ""; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = dyngen; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - 0873A53514AAF05A004F12B7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - INSTALL_PATH = /usr/local/bin; - OTHER_LDFLAGS = ""; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = dyngen; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0873A5C614AB8038004F12B7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - GCC_CW_ASM_SYNTAX = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_ENABLE_PASCAL_STRINGS = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 2; - GCC_PRECOMPILE_PREFIX_HEADER = ""; - GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - USE_JIT, - HAVE_CONFIG_H, - _REENTRANT, - _THREAD_SAFE, - "_GNU_SOURCE=1", - ); - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - ../kpx_cpu/src, - ../kpx_cpu/include, - ); - INSTALL_PATH = /usr/local/lib; - OTHER_CFLAGS = ( - "-mdynamic-no-pic", - "-fomit-frame-pointer", - "-fno-align-functions", - "-finline-functions", - "-finline-limit=10000", - "-fno-exceptions", - "-g0", - "-fno-reorder-blocks", - "-fno-optimize-sibling-calls", - ); - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - ); - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = "basic-dyngen-ops"; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - 0873A5C714AB8038004F12B7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - "GCC_VERSION[arch=x86_64]" = 4.2; - HEADER_SEARCH_PATHS = ( - ../kpx_cpu/src, - ../kpx_cpu/include, - ); - INSTALL_PATH = /usr/local/lib; - OTHER_CFLAGS = ( - "-mdynamic-no-pic", - "-fomit-frame-pointer", - "-fno-align-functions", - "-finline-functions", - "-finline-limit=10000", - "-fno-exceptions", - "-g0", - "-fno-reorder-blocks", - "-fno-optimize-sibling-calls", - ); - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - ); - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = "basic-dyngen-ops"; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0873A5CD14AB806E004F12B7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 2; - GCC_PRECOMPILE_PREFIX_HEADER = ""; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - ../kpx_cpu/src, - ../kpx_cpu/include, - ); - INSTALL_PATH = /usr/local/lib; - OTHER_CFLAGS = ( - "-mdynamic-no-pic", - "-fomit-frame-pointer", - "-fno-align-functions", - "-finline-functions", - "-finline-limit=10000", - "-fno-exceptions", - "-g0", - "-fno-reorder-blocks", - "-fno-optimize-sibling-calls", - ); - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - ); - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = "ppc-dyngen-ops"; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - 0873A5CE14AB806E004F12B7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - i386, - x86_64, - ); - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ""; - GCC_VERSION = 4.0; - "GCC_VERSION[arch=x86_64]" = 4.2; - HEADER_SEARCH_PATHS = ( - ../kpx_cpu/src, - ../kpx_cpu/include, - ); - INSTALL_PATH = /usr/local/lib; - OTHER_CFLAGS = ( - "-mdynamic-no-pic", - "-fomit-frame-pointer", - "-fno-align-functions", - "-finline-functions", - "-finline-limit=10000", - "-fno-exceptions", - "-g0", - "-fno-reorder-blocks", - "-fno-optimize-sibling-calls", - ); - OTHER_LDFLAGS = ( - "-framework", - Foundation, - "-framework", - AppKit, - ); - PREBINDING = NO; - PRODUCT_NAME = "ppc-dyngen-ops"; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0873A67414AB8AE9004F12B7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - PRODUCT_NAME = "ppc-execute-impl"; - }; - name = Debug; - }; - 0873A67514AB8AE9004F12B7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - PRODUCT_NAME = "ppc-execute-impl"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0885A5221593E3B6005C4F7B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - ppc, - i386, - ); - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = clip; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - }; - name = Debug; - }; - 0885A5231593E3B6005C4F7B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = ( - ppc, - i386, - ); - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = clip; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; - 0885A5321593E47F005C4F7B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)"; - ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = clip64; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; - }; - name = Debug; - }; - 0885A5331593E47F005C4F7B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)"; - ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_MODEL_TUNING = G5; - GCC_VERSION = 4.0; - HEADER_SEARCH_PATHS = ( - /Library/Frameworks/SDL.framework/Versions/A/Headers/, - ./config/, - ../Unix, - ../MacOSX/Launcher, - ../slirp, - ../kpx_cpu/src, - ../kpx_cpu/include, - ../include, - ); - INSTALL_PATH = /usr/local/lib; - PREBINDING = NO; - PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; - PRODUCT_NAME = clip64; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk"; - ZERO_LINK = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 082AC25714AA59DB00071F5E /* Build configuration list for PBXNativeTarget "lowmem" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 082AC25414AA59B700071F5E /* Debug */, - 082AC25514AA59B700071F5E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0846E4A114B1251400574779 /* Build configuration list for PBXNativeTarget "kpx_cpu" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0846E49B14B124DF00574779 /* Debug */, - 0846E49C14B124DF00574779 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0846E52C14B12A2600574779 /* Build configuration list for PBXNativeTarget "ppc_asm" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0846E52914B129EF00574779 /* Debug */, - 0846E52A14B129EF00574779 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0856CCB114A99DE0000B1711 /* Build configuration list for PBXProject "SheepShaver" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0856CCAF14A99DE0000B1711 /* Debug */, - 0856CCB014A99DE0000B1711 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0856CCC714A99E1D000B1711 /* Build configuration list for PBXNativeTarget "SheepShaver" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0856CCC514A99E1C000B1711 /* Debug */, - 0856CCC614A99E1C000B1711 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0873A53E14AAF076004F12B7 /* Build configuration list for PBXNativeTarget "dyngen" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0873A53414AAF05A004F12B7 /* Debug */, - 0873A53514AAF05A004F12B7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0873A5D314AB8099004F12B7 /* Build configuration list for PBXNativeTarget "basic-dyngen-ops" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0873A5C614AB8038004F12B7 /* Debug */, - 0873A5C714AB8038004F12B7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0873A5D414AB8099004F12B7 /* Build configuration list for PBXNativeTarget "ppc-dyngen-ops" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0873A5CD14AB806E004F12B7 /* Debug */, - 0873A5CE14AB806E004F12B7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0873A67B14AB8AEC004F12B7 /* Build configuration list for PBXAggregateTarget "ppc-execute-impl" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0873A67414AB8AE9004F12B7 /* Debug */, - 0873A67514AB8AE9004F12B7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0885A5241593E450005C4F7B /* Build configuration list for PBXNativeTarget "clip" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0885A5221593E3B6005C4F7B /* Debug */, - 0885A5231593E3B6005C4F7B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0885A5311593E47F005C4F7B /* Build configuration list for PBXNativeTarget "clip64" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0885A5321593E47F005C4F7B /* Debug */, - 0885A5331593E47F005C4F7B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 0856CCAE14A99DE0000B1711 /* Project object */; -} diff --git a/SheepShaver/src/MacOSX/XcodeBuildHowTo.txt b/SheepShaver/src/MacOSX/XcodeBuildHowTo.txt deleted file mode 100644 index 2a8899ba..00000000 --- a/SheepShaver/src/MacOSX/XcodeBuildHowTo.txt +++ /dev/null @@ -1,26 +0,0 @@ -The Xcode SheepShaver project makes it easier to build SheepShaver as a -Universal Binary (with 3 architectures: i386, x86_64 and ppc). - -This is an optional build system that does not affect the existing -autogen/configure based build system, which is still fully supported. -The Xcode project will build SheepShaver with configuration -"--enable-sdl-audio --enable-sdl-video --disable-vosf". - -The Xcode project lives in has been tested to work on Snow Leopard -64-bit with Xcode 3.2.6 and the 10.4 SDK installed. It may not work -under newer versions of Xcode or Mac OS X. - -To use it, you need the following: - -1. A complete 'macemu' git checkout of SheepShaver and BasiliskII. -2. SDL installed as a framework in /Library/Frameworks/SDL.framework. -3. You do not need to run autogen.sh / configure to use the Xcode -project. If you've done so already, you should remove or temporarily -move/rename src/Unix/config.h, as the presence of that file currently -conflicts with the Xcode build and will cause errors in Xcode. - -With the above all set, you should be able to launch the Xcode project -and build SheepShaver, resulting in a UB build containing SDL as a -private framework in the bundle. The result will be located in either -SheepShaver/src/MacOSX/build/Debug or SheepShaver/src/MacOSX/build/Release -directories, depending if you do a Debug or Release build. diff --git a/SheepShaver/src/MacOSX/audio_macosx.cpp b/SheepShaver/src/MacOSX/audio_macosx.cpp deleted file mode 120000 index 418b23c5..00000000 --- a/SheepShaver/src/MacOSX/audio_macosx.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/audio_macosx.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/autorelease.h b/SheepShaver/src/MacOSX/autorelease.h deleted file mode 120000 index 154cdead..00000000 --- a/SheepShaver/src/MacOSX/autorelease.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/autorelease.h \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/clip_macosx.cpp b/SheepShaver/src/MacOSX/clip_macosx.cpp deleted file mode 120000 index 7f731e4d..00000000 --- a/SheepShaver/src/MacOSX/clip_macosx.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/clip_macosx.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/clip_macosx64.mm b/SheepShaver/src/MacOSX/clip_macosx64.mm deleted file mode 120000 index 18640812..00000000 --- a/SheepShaver/src/MacOSX/clip_macosx64.mm +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/clip_macosx64.mm \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/config/config-macosx-ppc_32.h b/SheepShaver/src/MacOSX/config/config-macosx-ppc_32.h deleted file mode 100644 index 93c2dde3..00000000 --- a/SheepShaver/src/MacOSX/config/config-macosx-ppc_32.h +++ /dev/null @@ -1,513 +0,0 @@ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -#ifndef CONFIG_H -#define CONFIG_H - - -/* Define if using a PowerPC CPU emulator. */ -/* #undef EMULATED_PPC */ - -/* Define to enable dyngen engine */ -/* #undef ENABLE_DYNGEN */ - -/* Define is using ESD. */ -/* #undef ENABLE_ESD */ - -/* Define if using Linux fbdev extension. */ -/* #undef ENABLE_FBDEV_DGA */ - -/* Define if using GTK. */ -/* #undef ENABLE_GTK */ - -/* Define if using "mon". */ -/* #undef ENABLE_MON */ - -/* Define if your system supports TUN/TAP devices. */ -/* #undef ENABLE_TUNTAP */ - -/* Define if using video enabled on SEGV signals. */ -/* #undef ENABLE_VOSF */ - -/* Define if using XFree86 DGA extension. */ -/* #undef ENABLE_XF86_DGA */ - -/* Define if using XFree86 DGA extension. */ -/* #undef ENABLE_XF86_VIDMODE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_AVAILABILITYMACROS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BYTESWAP_H */ - -/* Define to 1 if you have the `ceil' function. */ -#define HAVE_CEIL 1 - -/* Define to 1 if you have the `ceilf' function. */ -#define HAVE_CEILF 1 - -/* Define to 1 if you have the `cfmakeraw' function. */ -#define HAVE_CFMAKERAW 1 - -/* Define to 1 if you have the `clock_gettime' function. */ -/* #undef HAVE_CLOCK_GETTIME */ - -/* Define to 1 if you have the `clock_nanosleep' function. */ -/* #undef HAVE_CLOCK_NANOSLEEP */ - -/* Define if you have /dev/ptmx. */ -/* #undef HAVE_DEV_PTMX */ - -/* Define if you have /dev/ptc. */ -/* #undef HAVE_DEV_PTS_AND_PTC */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you have the `exp2' function. */ -#define HAVE_EXP2 1 - -/* Define to 1 if you have the `exp2f' function. */ -#define HAVE_EXP2F 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FENV_H 1 - -/* Define to 1 if you have the `floor' function. */ -#define HAVE_FLOOR 1 - -/* Define to 1 if you have the `floorf' function. */ -#define HAVE_FLOORF 1 - -/* Define if framework AppKit is available. */ -#define HAVE_FRAMEWORK_APPKIT 1 - -/* Define if framework AudioToolbox is available. */ -#define HAVE_FRAMEWORK_AUDIOTOOLBOX 1 - -/* Define if framework AudioUnit is available. */ -#define HAVE_FRAMEWORK_AUDIOUNIT 1 - -/* Define if framework Carbon is available. */ -#define HAVE_FRAMEWORK_CARBON 1 - -/* Define if framework CoreAudio is available. */ -#define HAVE_FRAMEWORK_COREAUDIO 1 - -/* Define if framework CoreFoundation is available. */ -#define HAVE_FRAMEWORK_COREFOUNDATION 1 - -/* Define if framework IOKit is available. */ -#define HAVE_FRAMEWORK_IOKIT 1 - -/* Define if framework SDL is available. */ -/* #undef HAVE_FRAMEWORK_SDL */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_HISTORY_H */ - -/* Define to 1 if you have the `inet_aton' function. */ -#define HAVE_INET_ATON 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define to 1 if you have the header - file. */ -#define HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDEVICE_H 1 - -/* Define to 1 if you have the `curses' library (-lcurses). */ -/* #undef HAVE_LIBCURSES */ - -/* Define to 1 if you have the `c_r' library (-lc_r). */ -/* #undef HAVE_LIBC_R */ - -/* Define to 1 if you have the `Hcurses' library (-lHcurses). */ -/* #undef HAVE_LIBHCURSES */ - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `ncurses' library (-lncurses). */ -/* #undef HAVE_LIBNCURSES */ - -/* Define to 1 if you have the `posix4' library (-lposix4). */ -/* #undef HAVE_LIBPOSIX4 */ - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#define HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `PTL' library (-lPTL). */ -/* #undef HAVE_LIBPTL */ - -/* Define to 1 if you have the `readline' library (-lreadline). */ -/* #undef HAVE_LIBREADLINE */ - -/* Define to 1 if you have the `termcap' library (-ltermcap). */ -/* #undef HAVE_LIBTERMCAP */ - -/* Define to 1 if you have the `terminfo' library (-lterminfo). */ -/* #undef HAVE_LIBTERMINFO */ - -/* Define to 1 if you have the `termlib' library (-ltermlib). */ -/* #undef HAVE_LIBTERMLIB */ - -/* Define to 1 if you have the `vhd' library (-lvhd). */ -/* #undef HAVE_LIBVHD */ - -/* Define if there is a linker script to relocate the executable above - 0x70000000. */ -#define HAVE_LINKER_SCRIPT 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_IF_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_IF_TUN_H */ - -/* Define to 1 if you have the `log2' function. */ -#define HAVE_LOG2 1 - -/* Define to 1 if you have the `log2f' function. */ -#define HAVE_LOG2F 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LOGIN_H */ - -/* Define if your system supports Mach exceptions. */ -#define HAVE_MACH_EXCEPTIONS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_MACH_INIT_H 1 - -/* Define to 1 if you have the `mach_task_self' function. */ -#define HAVE_MACH_TASK_SELF 1 - -/* Define if your system has a working vm_allocate()-based memory allocator. - */ -#define HAVE_MACH_VM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_VM_MAP_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MALLOC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MEMORY_H */ - -/* Define to 1 if you have the `mmap' function. */ -#define HAVE_MMAP 1 - -/* Define if defines MAP_ANON and mmap()'ing with MAP_ANON works. - */ -/* #undef HAVE_MMAP_ANON */ - -/* Define if defines MAP_ANONYMOUS and mmap()'ing with - MAP_ANONYMOUS works. */ -/* #undef HAVE_MMAP_ANONYMOUS */ - -/* Define if your system has a working mmap()-based memory allocator. */ -/* #undef HAVE_MMAP_VM */ - -/* Define to 1 if you have the `mprotect' function. */ -#define HAVE_MPROTECT 1 - -/* Define to 1 if you have the `munmap' function. */ -#define HAVE_MUNMAP 1 - -/* Define to 1 if you have the `nanosleep' function. */ -#define HAVE_NANOSLEEP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NET_IF_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NET_IF_TUN_H */ - -/* Define if you are on NEWS-OS (additions from openssh-3.2.2p1, for - sshpty.c). */ -/* #undef HAVE_NEWS4 */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define if pthreads are available. */ -#define HAVE_PTHREADS 1 - -/* Define to 1 if you have the `pthread_cancel' function. */ -#define HAVE_PTHREAD_CANCEL 1 - -/* Define to 1 if you have the `pthread_cond_init' function. */ -#define HAVE_PTHREAD_COND_INIT 1 - -/* Define to 1 if you have the `pthread_mutexattr_setprotocol' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL 1 - -/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1 - -/* Define to 1 if you have the `pthread_mutexattr_settype' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETTYPE 1 - -/* Define to 1 if you have the `pthread_testcancel' function. */ -#define HAVE_PTHREAD_TESTCANCEL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PTY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_READLINE_H */ - -/* Define to 1 if you have the `round' function. */ -#define HAVE_ROUND 1 - -/* Define to 1 if you have the `roundf' function. */ -#define HAVE_ROUNDF 1 - -/* Define to 1 if you have the `sem_init' function. */ -#define HAVE_SEM_INIT 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define if we know a hack to replace siginfo_t->si_addr member. */ -/* #undef HAVE_SIGCONTEXT_SUBTERFUGE */ - -/* Define if your system support extended signals. */ -/* #undef HAVE_SIGINFO_T */ - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define if sa_restorer is available in struct sigaction. */ -/* #undef HAVE_SIGNAL_SA_RESTORER */ - -/* Define if we can ignore the fault (instruction skipping in SIGSEGV - handler). */ -#define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - -/* Define if slirp library is supported */ -#define HAVE_SLIRP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDLIB_H */ - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRING_H */ - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BSDTTY_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_FILIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_MMAN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_POLL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have the `task_self' function. */ -/* #undef HAVE_TASK_SELF */ - -/* Define to 1 if you have the `trunc' function. */ -#define HAVE_TRUNC 1 - -/* Define to 1 if you have the `truncf' function. */ -#define HAVE_TRUNCF 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UTIL_H 1 - -/* Define to 1 if you have the `vhangup' function. */ -/* #undef HAVE_VHANGUP */ - -/* Define to 1 if you have the `vm_allocate' function. */ -#define HAVE_VM_ALLOCATE 1 - -/* Define to 1 if you have the `vm_deallocate' function. */ -#define HAVE_VM_DEALLOCATE 1 - -/* Define to 1 if you have the `vm_protect' function. */ -#define HAVE_VM_PROTECT 1 - -/* Define if your system supports Windows exceptions. */ -/* #undef HAVE_WIN32_EXCEPTIONS */ - -/* Define to 1 if you have the `_getpty' function. */ -/* #undef HAVE__GETPTY */ - -/* Define to the floating point format of the host machine. */ -#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* Define to 1 if the host machine stores floating point numbers in memory - with the word containing the sign bit at the lowest address, or to 0 if it - does it the other way around. This macro should not be defined if the - ordering is the same as for multi-word integers. */ -/* #undef HOST_FLOAT_WORDS_BIG_ENDIAN */ - -/* Define constant offset for Mac address translation */ -/* #undef NATMEM_OFFSET */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "Christian.Bauer@uni-mainz.de" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "SheepShaver" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "SheepShaver 2.4" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "SheepShaver" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.4" - -/* Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this - system. */ -#define PAGEZERO_HACK 1 - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define if your system requires sigactions to be reinstalled. */ -/* #undef SIGACTION_NEED_REINSTALL */ - -/* Define if your system requires signals to be reinstalled. */ -/* #undef SIGNAL_NEED_REINSTALL */ - -/* The size of a `double', as computed by sizeof. */ -#define SIZEOF_DOUBLE 8 - -/* The size of a `float', as computed by sizeof. */ -#define SIZEOF_FLOAT 4 - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of a `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of a `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* The size of a `void *', as computed by sizeof. */ -#define SIZEOF_VOID_P 4 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define if BSD-style non-blocking I/O is to be used */ -/* #undef USE_FIONBIO */ - -/* Define to enble SDL support. */ -#define USE_SDL 1 - -/* Define to enable SDL audio support */ -#define USE_SDL_AUDIO 1 - -/* Define to enable SDL video graphics support. */ -#define USE_SDL_VIDEO 1 - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#define WORDS_BIGENDIAN 1 - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `off_t' if does not define. */ -#define loff_t off_t - -/* Define to `long' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned' if does not define. */ -/* #undef size_t */ - -/* Define to 'int' if doesn't define. */ -/* #undef socklen_t */ - -#endif /* CONFIG_H */ - diff --git a/SheepShaver/src/MacOSX/config/config-macosx-x86_32.h b/SheepShaver/src/MacOSX/config/config-macosx-x86_32.h deleted file mode 100644 index 030f42a7..00000000 --- a/SheepShaver/src/MacOSX/config/config-macosx-x86_32.h +++ /dev/null @@ -1,527 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -#ifndef CONFIG_H -#define CONFIG_H - - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if using a PowerPC CPU emulator. */ -#define EMULATED_PPC 1 - -/* Define to enable dyngen engine */ -#define ENABLE_DYNGEN 1 - -/* Define is using ESD. */ -/* #undef ENABLE_ESD */ - -/* Define if using Linux fbdev extension. */ -/* #undef ENABLE_FBDEV_DGA */ - -/* Define if using GTK. */ -/* #undef ENABLE_GTK */ - -/* Define if using "mon". */ -/* #undef ENABLE_MON */ - -/* Define if your system supports TUN/TAP devices. */ -/* #undef ENABLE_TUNTAP */ - -/* Define if using video enabled on SEGV signals. */ -/* #undef ENABLE_VOSF */ - -/* Define if using XFree86 DGA extension. */ -/* #undef ENABLE_XF86_DGA */ - -/* Define if using XFree86 DGA extension. */ -/* #undef ENABLE_XF86_VIDMODE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_AVAILABILITYMACROS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BYTESWAP_H */ - -/* Define to 1 if you have the `ceil' function. */ -#define HAVE_CEIL 1 - -/* Define to 1 if you have the `ceilf' function. */ -#define HAVE_CEILF 1 - -/* Define to 1 if you have the `cfmakeraw' function. */ -#define HAVE_CFMAKERAW 1 - -/* Define to 1 if you have the `clock_gettime' function. */ -/* #undef HAVE_CLOCK_GETTIME */ - -/* Define to 1 if you have the `clock_nanosleep' function. */ -/* #undef HAVE_CLOCK_NANOSLEEP */ - -/* Define if you have /dev/ptmx. */ -/* #undef HAVE_DEV_PTMX */ - -/* Define if you have /dev/ptc. */ -/* #undef HAVE_DEV_PTS_AND_PTC */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you have the `exp2' function. */ -#define HAVE_EXP2 1 - -/* Define to 1 if you have the `exp2f' function. */ -#define HAVE_EXP2F 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FENV_H 1 - -/* Define to 1 if you have the `floor' function. */ -#define HAVE_FLOOR 1 - -/* Define to 1 if you have the `floorf' function. */ -#define HAVE_FLOORF 1 - -/* Define if framework AppKit is available. */ -#define HAVE_FRAMEWORK_APPKIT 1 - -/* Define if framework AudioToolbox is available. */ -#define HAVE_FRAMEWORK_AUDIOTOOLBOX 1 - -/* Define if framework AudioUnit is available. */ -#define HAVE_FRAMEWORK_AUDIOUNIT 1 - -/* Define if framework Carbon is available. */ -#define HAVE_FRAMEWORK_CARBON 1 - -/* Define if framework CoreAudio is available. */ -#define HAVE_FRAMEWORK_COREAUDIO 1 - -/* Define if framework CoreFoundation is available. */ -#define HAVE_FRAMEWORK_COREFOUNDATION 1 - -/* Define if framework IOKit is available. */ -#define HAVE_FRAMEWORK_IOKIT 1 - -/* Define if framework SDL is available. */ -/* #undef HAVE_FRAMEWORK_SDL */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_HISTORY_H */ - -/* Define to 1 if you have the `inet_aton' function. */ -#define HAVE_INET_ATON 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define to 1 if you have the header - file. */ -#define HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDEVICE_H 1 - -/* Define to 1 if you have the `curses' library (-lcurses). */ -/* #undef HAVE_LIBCURSES */ - -/* Define to 1 if you have the `c_r' library (-lc_r). */ -/* #undef HAVE_LIBC_R */ - -/* Define to 1 if you have the `Hcurses' library (-lHcurses). */ -/* #undef HAVE_LIBHCURSES */ - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `ncurses' library (-lncurses). */ -/* #undef HAVE_LIBNCURSES */ - -/* Define to 1 if you have the `posix4' library (-lposix4). */ -/* #undef HAVE_LIBPOSIX4 */ - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#define HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `PTL' library (-lPTL). */ -/* #undef HAVE_LIBPTL */ - -/* Define to 1 if you have the `readline' library (-lreadline). */ -/* #undef HAVE_LIBREADLINE */ - -/* Define to 1 if you have the `termcap' library (-ltermcap). */ -/* #undef HAVE_LIBTERMCAP */ - -/* Define to 1 if you have the `terminfo' library (-lterminfo). */ -/* #undef HAVE_LIBTERMINFO */ - -/* Define to 1 if you have the `termlib' library (-ltermlib). */ -/* #undef HAVE_LIBTERMLIB */ - -/* Define to 1 if you have the `vhd' library (-lvhd). */ -/* #undef HAVE_LIBVHD */ - -/* Define if there is a linker script to relocate the executable above - 0x70000000. */ -#define HAVE_LINKER_SCRIPT 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_IF_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_IF_TUN_H */ - -/* Define to 1 if you have the `log2' function. */ -#define HAVE_LOG2 1 - -/* Define to 1 if you have the `log2f' function. */ -#define HAVE_LOG2F 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LOGIN_H */ - -/* Define if your system supports Mach exceptions. */ -#define HAVE_MACH_EXCEPTIONS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_MACH_INIT_H 1 - -/* Define to 1 if you have the `mach_task_self' function. */ -#define HAVE_MACH_TASK_SELF 1 - -/* Define if your system has a working vm_allocate()-based memory allocator. - */ -#define HAVE_MACH_VM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_VM_MAP_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MALLOC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MEMORY_H */ - -/* Define to 1 if you have the `mmap' function. */ -#define HAVE_MMAP 1 - -/* Define if defines MAP_ANON and mmap()'ing with MAP_ANON works. - */ -/* #undef HAVE_MMAP_ANON */ - -/* Define if defines MAP_ANONYMOUS and mmap()'ing with - MAP_ANONYMOUS works. */ -/* #undef HAVE_MMAP_ANONYMOUS */ - -/* Define if your system has a working mmap()-based memory allocator. */ -/* #undef HAVE_MMAP_VM */ - -/* Define to 1 if you have the `mprotect' function. */ -#define HAVE_MPROTECT 1 - -/* Define to 1 if you have the `munmap' function. */ -#define HAVE_MUNMAP 1 - -/* Define to 1 if you have the `nanosleep' function. */ -#define HAVE_NANOSLEEP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NET_IF_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NET_IF_TUN_H */ - -/* Define if you are on NEWS-OS (additions from openssh-3.2.2p1, for - sshpty.c). */ -/* #undef HAVE_NEWS4 */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define if pthreads are available. */ -#define HAVE_PTHREADS 1 - -/* Define to 1 if you have the `pthread_cancel' function. */ -#define HAVE_PTHREAD_CANCEL 1 - -/* Define to 1 if you have the `pthread_cond_init' function. */ -#define HAVE_PTHREAD_COND_INIT 1 - -/* Define to 1 if you have the `pthread_mutexattr_setprotocol' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL 1 - -/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1 - -/* Define to 1 if you have the `pthread_mutexattr_settype' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETTYPE 1 - -/* Define to 1 if you have the `pthread_testcancel' function. */ -#define HAVE_PTHREAD_TESTCANCEL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PTY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_READLINE_H */ - -/* Define to 1 if you have the `round' function. */ -#define HAVE_ROUND 1 - -/* Define to 1 if you have the `roundf' function. */ -#define HAVE_ROUNDF 1 - -/* Define to 1 if you have the `sem_init' function. */ -#define HAVE_SEM_INIT 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define if we know a hack to replace siginfo_t->si_addr member. */ -/* #undef HAVE_SIGCONTEXT_SUBTERFUGE */ - -/* Define if your system support extended signals. */ -/* #undef HAVE_SIGINFO_T */ - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define if sa_restorer is available in struct sigaction. */ -/* #undef HAVE_SIGNAL_SA_RESTORER */ - -/* Define if we can ignore the fault (instruction skipping in SIGSEGV - handler). */ -#define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - -/* Define if slirp library is supported */ -#define HAVE_SLIRP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDLIB_H */ - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRING_H */ - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BSDTTY_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_FILIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_MMAN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_POLL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have the `task_self' function. */ -/* #undef HAVE_TASK_SELF */ - -/* Define to 1 if you have the `trunc' function. */ -#define HAVE_TRUNC 1 - -/* Define to 1 if you have the `truncf' function. */ -#define HAVE_TRUNCF 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UTIL_H 1 - -/* Define to 1 if you have the `vhangup' function. */ -/* #undef HAVE_VHANGUP */ - -/* Define to 1 if you have the `vm_allocate' function. */ -#define HAVE_VM_ALLOCATE 1 - -/* Define to 1 if you have the `vm_deallocate' function. */ -#define HAVE_VM_DEALLOCATE 1 - -/* Define to 1 if you have the `vm_protect' function. */ -#define HAVE_VM_PROTECT 1 - -/* Define if your system supports Windows exceptions. */ -/* #undef HAVE_WIN32_EXCEPTIONS */ - -/* Define to 1 if you have the `_getpty' function. */ -/* #undef HAVE__GETPTY */ - -/* Define to the floating point format of the host machine. */ -#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* Define to 1 if the host machine stores floating point numbers in memory - with the word containing the sign bit at the lowest address, or to 0 if it - does it the other way around. This macro should not be defined if the - ordering is the same as for multi-word integers. */ -/* #undef HOST_FLOAT_WORDS_BIG_ENDIAN */ - -/* Define constant offset for Mac address translation */ -/* #undef NATMEM_OFFSET */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "Christian.Bauer@uni-mainz.de" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "SheepShaver" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "SheepShaver 2.4" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "SheepShaver" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.4" - -/* Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this - system. */ -#define PAGEZERO_HACK 1 - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define if your system requires sigactions to be reinstalled. */ -/* #undef SIGACTION_NEED_REINSTALL */ - -/* Define if your system requires signals to be reinstalled. */ -/* #undef SIGNAL_NEED_REINSTALL */ - -/* The size of `double', as computed by sizeof. */ -#define SIZEOF_DOUBLE 8 - -/* The size of `float', as computed by sizeof. */ -#define SIZEOF_FLOAT 4 - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* The size of `void *', as computed by sizeof. */ -#define SIZEOF_VOID_P 4 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define if BSD-style non-blocking I/O is to be used */ -/* #undef USE_FIONBIO */ - -/* Define to enble SDL support. */ -#define USE_SDL 1 - -/* Define to enable SDL audio support */ -#define USE_SDL_AUDIO 1 - -/* Define to enable SDL video graphics support. */ -#define USE_SDL_VIDEO 1 - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `off_t' if does not define. */ -#define loff_t off_t - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define to 'int' if doesn't define. */ -/* #undef socklen_t */ - -#endif /* CONFIG_H */ - diff --git a/SheepShaver/src/MacOSX/config/config-macosx-x86_64.h b/SheepShaver/src/MacOSX/config/config-macosx-x86_64.h deleted file mode 100644 index 760e6450..00000000 --- a/SheepShaver/src/MacOSX/config/config-macosx-x86_64.h +++ /dev/null @@ -1,527 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -#ifndef CONFIG_H -#define CONFIG_H - - -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ - -/* Define if using a PowerPC CPU emulator. */ -#define EMULATED_PPC 1 - -/* Define to enable dyngen engine */ -#define ENABLE_DYNGEN 1 - -/* Define is using ESD. */ -/* #undef ENABLE_ESD */ - -/* Define if using Linux fbdev extension. */ -/* #undef ENABLE_FBDEV_DGA */ - -/* Define if using GTK. */ -/* #undef ENABLE_GTK */ - -/* Define if using "mon". */ -/* #undef ENABLE_MON */ - -/* Define if your system supports TUN/TAP devices. */ -/* #undef ENABLE_TUNTAP */ - -/* Define if using video enabled on SEGV signals. */ -/* #undef ENABLE_VOSF */ - -/* Define if using XFree86 DGA extension. */ -/* #undef ENABLE_XF86_DGA */ - -/* Define if using XFree86 DGA extension. */ -/* #undef ENABLE_XF86_VIDMODE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_AVAILABILITYMACROS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BYTESWAP_H */ - -/* Define to 1 if you have the `ceil' function. */ -#define HAVE_CEIL 1 - -/* Define to 1 if you have the `ceilf' function. */ -#define HAVE_CEILF 1 - -/* Define to 1 if you have the `cfmakeraw' function. */ -#define HAVE_CFMAKERAW 1 - -/* Define to 1 if you have the `clock_gettime' function. */ -/* #undef HAVE_CLOCK_GETTIME */ - -/* Define to 1 if you have the `clock_nanosleep' function. */ -/* #undef HAVE_CLOCK_NANOSLEEP */ - -/* Define if you have /dev/ptmx. */ -/* #undef HAVE_DEV_PTMX */ - -/* Define if you have /dev/ptc. */ -/* #undef HAVE_DEV_PTS_AND_PTC */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you have the `exp2' function. */ -#define HAVE_EXP2 1 - -/* Define to 1 if you have the `exp2f' function. */ -#define HAVE_EXP2F 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FENV_H 1 - -/* Define to 1 if you have the `floor' function. */ -#define HAVE_FLOOR 1 - -/* Define to 1 if you have the `floorf' function. */ -#define HAVE_FLOORF 1 - -/* Define if framework AppKit is available. */ -#define HAVE_FRAMEWORK_APPKIT 1 - -/* Define if framework AudioToolbox is available. */ -#define HAVE_FRAMEWORK_AUDIOTOOLBOX 1 - -/* Define if framework AudioUnit is available. */ -#define HAVE_FRAMEWORK_AUDIOUNIT 1 - -/* Define if framework Carbon is available. */ -#define HAVE_FRAMEWORK_CARBON 1 - -/* Define if framework CoreAudio is available. */ -#define HAVE_FRAMEWORK_COREAUDIO 1 - -/* Define if framework CoreFoundation is available. */ -#define HAVE_FRAMEWORK_COREFOUNDATION 1 - -/* Define if framework IOKit is available. */ -#define HAVE_FRAMEWORK_IOKIT 1 - -/* Define if framework SDL is available. */ -/* #undef HAVE_FRAMEWORK_SDL */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_HISTORY_H */ - -/* Define to 1 if you have the `inet_aton' function. */ -#define HAVE_INET_ATON 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define to 1 if you have the header - file. */ -#define HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDEVICE_H 1 - -/* Define to 1 if you have the `curses' library (-lcurses). */ -/* #undef HAVE_LIBCURSES */ - -/* Define to 1 if you have the `c_r' library (-lc_r). */ -/* #undef HAVE_LIBC_R */ - -/* Define to 1 if you have the `Hcurses' library (-lHcurses). */ -/* #undef HAVE_LIBHCURSES */ - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `ncurses' library (-lncurses). */ -/* #undef HAVE_LIBNCURSES */ - -/* Define to 1 if you have the `posix4' library (-lposix4). */ -/* #undef HAVE_LIBPOSIX4 */ - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#define HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `PTL' library (-lPTL). */ -/* #undef HAVE_LIBPTL */ - -/* Define to 1 if you have the `readline' library (-lreadline). */ -/* #undef HAVE_LIBREADLINE */ - -/* Define to 1 if you have the `termcap' library (-ltermcap). */ -/* #undef HAVE_LIBTERMCAP */ - -/* Define to 1 if you have the `terminfo' library (-lterminfo). */ -/* #undef HAVE_LIBTERMINFO */ - -/* Define to 1 if you have the `termlib' library (-ltermlib). */ -/* #undef HAVE_LIBTERMLIB */ - -/* Define to 1 if you have the `vhd' library (-lvhd). */ -/* #undef HAVE_LIBVHD */ - -/* Define if there is a linker script to relocate the executable above - 0x70000000. */ -#define HAVE_LINKER_SCRIPT 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_IF_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_IF_TUN_H */ - -/* Define to 1 if you have the `log2' function. */ -#define HAVE_LOG2 1 - -/* Define to 1 if you have the `log2f' function. */ -#define HAVE_LOG2F 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LOGIN_H */ - -/* Define if your system supports Mach exceptions. */ -#define HAVE_MACH_EXCEPTIONS 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_MACH_INIT_H 1 - -/* Define to 1 if you have the `mach_task_self' function. */ -#define HAVE_MACH_TASK_SELF 1 - -/* Define if your system has a working vm_allocate()-based memory allocator. - */ -#define HAVE_MACH_VM 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_VM_MAP_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MALLOC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MEMORY_H */ - -/* Define to 1 if you have the `mmap' function. */ -#define HAVE_MMAP 1 - -/* Define if defines MAP_ANON and mmap()'ing with MAP_ANON works. - */ -/* #undef HAVE_MMAP_ANON */ - -/* Define if defines MAP_ANONYMOUS and mmap()'ing with - MAP_ANONYMOUS works. */ -/* #undef HAVE_MMAP_ANONYMOUS */ - -/* Define if your system has a working mmap()-based memory allocator. */ -/* #undef HAVE_MMAP_VM */ - -/* Define to 1 if you have the `mprotect' function. */ -#define HAVE_MPROTECT 1 - -/* Define to 1 if you have the `munmap' function. */ -#define HAVE_MUNMAP 1 - -/* Define to 1 if you have the `nanosleep' function. */ -#define HAVE_NANOSLEEP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_NET_IF_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NET_IF_TUN_H */ - -/* Define if you are on NEWS-OS (additions from openssh-3.2.2p1, for - sshpty.c). */ -/* #undef HAVE_NEWS4 */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define if pthreads are available. */ -#define HAVE_PTHREADS 1 - -/* Define to 1 if you have the `pthread_cancel' function. */ -#define HAVE_PTHREAD_CANCEL 1 - -/* Define to 1 if you have the `pthread_cond_init' function. */ -#define HAVE_PTHREAD_COND_INIT 1 - -/* Define to 1 if you have the `pthread_mutexattr_setprotocol' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL 1 - -/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1 - -/* Define to 1 if you have the `pthread_mutexattr_settype' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETTYPE 1 - -/* Define to 1 if you have the `pthread_testcancel' function. */ -#define HAVE_PTHREAD_TESTCANCEL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PTY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_READLINE_H */ - -/* Define to 1 if you have the `round' function. */ -#define HAVE_ROUND 1 - -/* Define to 1 if you have the `roundf' function. */ -#define HAVE_ROUNDF 1 - -/* Define to 1 if you have the `sem_init' function. */ -#define HAVE_SEM_INIT 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define if we know a hack to replace siginfo_t->si_addr member. */ -/* #undef HAVE_SIGCONTEXT_SUBTERFUGE */ - -/* Define if your system support extended signals. */ -/* #undef HAVE_SIGINFO_T */ - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define if sa_restorer is available in struct sigaction. */ -/* #undef HAVE_SIGNAL_SA_RESTORER */ - -/* Define if we can ignore the fault (instruction skipping in SIGSEGV - handler). */ -#define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - -/* Define if slirp library is supported */ -#define HAVE_SLIRP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDLIB_H */ - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRING_H */ - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BSDTTY_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_FILIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_MMAN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_POLL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to 1 if you have the `task_self' function. */ -/* #undef HAVE_TASK_SELF */ - -/* Define to 1 if you have the `trunc' function. */ -#define HAVE_TRUNC 1 - -/* Define to 1 if you have the `truncf' function. */ -#define HAVE_TRUNCF 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UTIL_H 1 - -/* Define to 1 if you have the `vhangup' function. */ -/* #undef HAVE_VHANGUP */ - -/* Define to 1 if you have the `vm_allocate' function. */ -#define HAVE_VM_ALLOCATE 1 - -/* Define to 1 if you have the `vm_deallocate' function. */ -#define HAVE_VM_DEALLOCATE 1 - -/* Define to 1 if you have the `vm_protect' function. */ -#define HAVE_VM_PROTECT 1 - -/* Define if your system supports Windows exceptions. */ -/* #undef HAVE_WIN32_EXCEPTIONS */ - -/* Define to 1 if you have the `_getpty' function. */ -/* #undef HAVE__GETPTY */ - -/* Define to the floating point format of the host machine. */ -#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* Define to 1 if the host machine stores floating point numbers in memory - with the word containing the sign bit at the lowest address, or to 0 if it - does it the other way around. This macro should not be defined if the - ordering is the same as for multi-word integers. */ -/* #undef HOST_FLOAT_WORDS_BIG_ENDIAN */ - -/* Define constant offset for Mac address translation */ -/* #undef NATMEM_OFFSET */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "Christian.Bauer@uni-mainz.de" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "SheepShaver" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "SheepShaver 2.4" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "SheepShaver" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.4" - -/* Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this - system. */ -#define PAGEZERO_HACK 1 - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define if your system requires sigactions to be reinstalled. */ -/* #undef SIGACTION_NEED_REINSTALL */ - -/* Define if your system requires signals to be reinstalled. */ -/* #undef SIGNAL_NEED_REINSTALL */ - -/* The size of `double', as computed by sizeof. */ -#define SIZEOF_DOUBLE 8 - -/* The size of `float', as computed by sizeof. */ -#define SIZEOF_FLOAT 4 - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* The size of `void *', as computed by sizeof. */ -#define SIZEOF_VOID_P 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define if BSD-style non-blocking I/O is to be used */ -/* #undef USE_FIONBIO */ - -/* Define to enble SDL support. */ -#define USE_SDL 1 - -/* Define to enable SDL audio support */ -#define USE_SDL_AUDIO 1 - -/* Define to enable SDL video graphics support. */ -#define USE_SDL_VIDEO 1 - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -/* # undef WORDS_BIGENDIAN */ -# endif -#endif - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `off_t' if does not define. */ -#define loff_t off_t - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define to 'int' if doesn't define. */ -/* #undef socklen_t */ - -#endif /* CONFIG_H */ - diff --git a/SheepShaver/src/MacOSX/config/config.h b/SheepShaver/src/MacOSX/config/config.h deleted file mode 100644 index bb5a0781..00000000 --- a/SheepShaver/src/MacOSX/config/config.h +++ /dev/null @@ -1,9 +0,0 @@ -#if defined(__x86_64__) - #include "config-macosx-x86_64.h" -#elif defined(__i386__) - #include "config-macosx-x86_32.h" -#elif defined(__ppc__) - #include "config-macosx-ppc_32.h" -#else - #error Unknown platform -#endif \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/extfs_macosx.cpp b/SheepShaver/src/MacOSX/extfs_macosx.cpp deleted file mode 120000 index 1afcd4b1..00000000 --- a/SheepShaver/src/MacOSX/extfs_macosx.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/extfs_macosx.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/macos_util_macosx.h b/SheepShaver/src/MacOSX/macos_util_macosx.h deleted file mode 120000 index cef14874..00000000 --- a/SheepShaver/src/MacOSX/macos_util_macosx.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/macos_util_macosx.h \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/prefs_macosx.mm b/SheepShaver/src/MacOSX/prefs_macosx.mm deleted file mode 100644 index e8b77924..00000000 --- a/SheepShaver/src/MacOSX/prefs_macosx.mm +++ /dev/null @@ -1,131 +0,0 @@ -/* - * $Id$ - * - * prefs_macosx.mm - Enables access to SheepShaver preferences while - * SheepShaver is running (on Mac OS X). - * - * Copyright (C) 2007 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "sysdeps.h" - -// The _UINT64 define is needed to guard against a typedef mismatch with Snow Leopard headers. -#define _UINT64 - -#include -#include "VMSettingsController.h" - - -@interface SheepShaverMain : NSObject -{ - NSArray *nibObjects; - NSWindow *prefsWindow; -} -@end - -@implementation SheepShaverMain - - -- (NSArray*) loadPrefsNibFile -{ - NSNib *nib = [[NSNib alloc] initWithNibNamed:@"VMSettingsWindow" bundle:nil]; - NSArray *objects = nil; - - if (![nib instantiateNibWithOwner:[VMSettingsController sharedInstance] topLevelObjects:&objects]) { - NSLog(@"Could not load Prefs NIB file!\n"); - return nil; - } - - NSLog(@"%d objects loaded\n", [objects count]); - - // Release the raw nib data. - [nib release]; - - // Release the top-level objects so that they are just owned by the array. - [objects makeObjectsPerformSelector:@selector(release)]; - - prefsWindow = nil; - for (int i = 0; i < [objects count]; i++) { - NSObject *object = [objects objectAtIndex:i]; - NSLog(@"Got %@", object); - - if ([object isKindOfClass:[NSWindow class]]) { - prefsWindow = (NSWindow *) object; - break; - } - } - - if (prefsWindow == nil) { - NSLog(@"Could not find NSWindow in Prefs NIB file!\n"); - return nil; - } - - return objects; -} - - -- (void) openPreferences:(id)sender -{ - NSAutoreleasePool *pool; - - if (nibObjects == nil) { - nibObjects = [self loadPrefsNibFile]; - if (nibObjects == nil) - return; - [nibObjects retain]; - } - - pool = [[NSAutoreleasePool alloc] init]; - [[VMSettingsController sharedInstance] setupGUI]; - [NSApp runModalForWindow:prefsWindow]; - [pool release]; -} - -@end - -/* - * Initialization - */ - -void prefs_init(void) -{ - NSAutoreleasePool *pool; - NSMenu *appMenu; - NSMenuItem *menuItem; - - pool = [[NSAutoreleasePool alloc] init]; - - appMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Preferences..." action:@selector(openPreferences:) keyEquivalent:@","]; - [appMenu insertItem:menuItem atIndex:2]; - [appMenu insertItem:[NSMenuItem separatorItem] atIndex:3]; - [menuItem release]; - - [NSApp setDelegate:[[SheepShaverMain alloc] init]]; - - [pool release]; -} - - -/* - * Deinitialization - */ - -void prefs_exit(void) -{ -} diff --git a/SheepShaver/src/MacOSX/sys_darwin.cpp b/SheepShaver/src/MacOSX/sys_darwin.cpp deleted file mode 120000 index 28b80318..00000000 --- a/SheepShaver/src/MacOSX/sys_darwin.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/sys_darwin.cpp \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/utils_macosx.h b/SheepShaver/src/MacOSX/utils_macosx.h deleted file mode 120000 index c8777733..00000000 --- a/SheepShaver/src/MacOSX/utils_macosx.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/utils_macosx.h \ No newline at end of file diff --git a/SheepShaver/src/MacOSX/utils_macosx.mm b/SheepShaver/src/MacOSX/utils_macosx.mm deleted file mode 120000 index 19064958..00000000 --- a/SheepShaver/src/MacOSX/utils_macosx.mm +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/MacOSX/utils_macosx.mm \ No newline at end of file diff --git a/SheepShaver/src/SDL b/SheepShaver/src/SDL deleted file mode 120000 index 48cb61eb..00000000 --- a/SheepShaver/src/SDL +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/SDL \ No newline at end of file diff --git a/SheepShaver/src/Unix/.gitignore b/SheepShaver/src/Unix/.gitignore deleted file mode 100644 index 0461f22e..00000000 --- a/SheepShaver/src/Unix/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Object files -obj/* -SheepShaver - -# Autotools generated files -Makefile -aclocal.m4 -autom4te.cache/* -config.h -config.h.in -config.log -config.status -configure - -# Generated files for CPU emulation -basic-dyngen-ops.hpp -ppc-dyngen-ops.hpp -ppc-execute-impl.cpp -dyngen - -# Generated files from the Xcode build -basic-dyngen-ops-x86_32.hpp -basic-dyngen-ops-x86_64.hpp -ppc-dyngen-ops-x86_32.hpp -ppc-dyngen-ops-x86_64.hpp diff --git a/SheepShaver/src/Unix/Darwin/.gitignore b/SheepShaver/src/Unix/Darwin/.gitignore deleted file mode 100644 index 0535c467..00000000 --- a/SheepShaver/src/Unix/Darwin/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Darwin built utils -lowmem -pagezero diff --git a/SheepShaver/src/Unix/Darwin/lowmem.c b/SheepShaver/src/Unix/Darwin/lowmem.c deleted file mode 120000 index 7e0a359c..00000000 --- a/SheepShaver/src/Unix/Darwin/lowmem.c +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Darwin/lowmem.c \ No newline at end of file diff --git a/SheepShaver/src/Unix/Darwin/mkstandalone b/SheepShaver/src/Unix/Darwin/mkstandalone deleted file mode 120000 index acfe13f6..00000000 --- a/SheepShaver/src/Unix/Darwin/mkstandalone +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Darwin/mkstandalone \ No newline at end of file diff --git a/SheepShaver/src/Unix/Darwin/pagezero.c b/SheepShaver/src/Unix/Darwin/pagezero.c deleted file mode 120000 index ae53c815..00000000 --- a/SheepShaver/src/Unix/Darwin/pagezero.c +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Darwin/pagezero.c \ No newline at end of file diff --git a/SheepShaver/src/Unix/Darwin/testlmem.sh b/SheepShaver/src/Unix/Darwin/testlmem.sh deleted file mode 120000 index 1137ef89..00000000 --- a/SheepShaver/src/Unix/Darwin/testlmem.sh +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Darwin/testlmem.sh \ No newline at end of file diff --git a/SheepShaver/src/Unix/Irix/audio_irix.cpp b/SheepShaver/src/Unix/Irix/audio_irix.cpp deleted file mode 120000 index 2e7ef88f..00000000 --- a/SheepShaver/src/Unix/Irix/audio_irix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Irix/audio_irix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/Linux/NetDriver b/SheepShaver/src/Unix/Linux/NetDriver deleted file mode 120000 index 6e756eb3..00000000 --- a/SheepShaver/src/Unix/Linux/NetDriver +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Linux/NetDriver \ No newline at end of file diff --git a/SheepShaver/src/Unix/Linux/scsi_linux.cpp b/SheepShaver/src/Unix/Linux/scsi_linux.cpp deleted file mode 120000 index 9ebba5fd..00000000 --- a/SheepShaver/src/Unix/Linux/scsi_linux.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../../BasiliskII/src/Unix/Linux/scsi_linux.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/Linux/sheepthreads.c b/SheepShaver/src/Unix/Linux/sheepthreads.c deleted file mode 100644 index a286d067..00000000 --- a/SheepShaver/src/Unix/Linux/sheepthreads.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * sheepthreads.c - Minimal pthreads implementation (libpthreads doesn't - * like nonstandard stacks) - * - * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - pthread_cancel() kills the thread immediately - * - Semaphores are VERY restricted: the only supported use is to have one - * thread sem_wait() on the semaphore while other threads sem_post() it - * (i.e. to use the semaphore as a signal) - */ - -#include -#include -#include -#include -#include -#include -#include - - -/* Thread stack size */ -#define STACK_SIZE 65536 - -/* From asm_linux.S */ -extern int atomic_add(int *var, int add); -extern int atomic_and(int *var, int and); -extern int atomic_or(int *var, int or); -extern int test_and_set(int *var, int val); - -/* Linux kernel calls */ -extern int __clone(int (*fn)(void *), void *, int, void *); - -/* libc no longer provides struct _pthread_fastlock in pthread.h */ -struct fastlock { - int status; - int spinlock; -}; - -typedef struct { - struct fastlock sem_lock; - int sem_value; - int sem_waiting; -} sem_t; - -#define SEM_VALUE_MAX 64 - -/* Wait for "clone" children only (Linux 2.4+ specific) */ -#ifndef __WCLONE -#define __WCLONE 0 -#endif - - -/* - * Return pthread ID of self - */ - -pthread_t pthread_self(void) -{ - return getpid(); -} - - -/* - * Test whether two pthread IDs are equal - */ - -int pthread_equal(pthread_t t1, pthread_t t2) -{ - return t1 == t2; -} - - -/* - * Send signal to thread - */ - -int pthread_kill(pthread_t thread, int sig) -{ - if (kill(thread, sig) == -1) - return errno; - else - return 0; -} - - -/* - * Create pthread - */ - -struct new_thread { - void *(*fn)(void *); - void *arg; -}; - -static int start_thread(void *arg) -{ - struct new_thread *nt = (struct new_thread *)arg; - nt->fn(nt->arg); - return 0; -} - -int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) -{ - struct new_thread *nt; - void *stack; - int pid; - - nt = (struct new_thread *)malloc(sizeof(struct new_thread)); - nt->fn = start_routine; - nt->arg = arg; - stack = malloc(STACK_SIZE); - - pid = __clone(start_thread, (char *)stack + STACK_SIZE - 16, CLONE_VM | CLONE_FS | CLONE_FILES, nt); - if (pid == -1) { - free(stack); - free(nt); - return errno; - } else { - *thread = pid; - return 0; - } -} - - -/* - * Join pthread - */ - -int pthread_join(pthread_t thread, void **ret) -{ - do { - if (waitpid(thread, NULL, __WCLONE) >= 0); - break; - } while (errno == EINTR); - if (ret) - *ret = NULL; - return 0; -} - - -/* - * Cancel thread - */ - -int pthread_cancel(pthread_t thread) -{ - kill(thread, SIGINT); - return 0; -} - - -/* - * Test for cancellation - */ - -void pthread_testcancel(void) -{ -} - - -/* - * Spinlocks - */ - -/* For multiprocessor systems, we want to ensure all memory accesses - are completed before we reset a lock. On other systems, we still - need to make sure that the compiler has flushed everything to memory. */ -#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") - -static void fastlock_init(struct fastlock *lock) -{ - lock->status = 0; - lock->spinlock = 0; -} - -static int fastlock_try_acquire(struct fastlock *lock) -{ - int res = EBUSY; - if (test_and_set(&lock->spinlock, 1) == 0) { - if (lock->status == 0) { - lock->status = 1; - MEMORY_BARRIER(); - res = 0; - } - lock->spinlock = 0; - } - return res; -} - -static void fastlock_acquire(struct fastlock *lock) -{ - MEMORY_BARRIER(); - while (test_and_set(&lock->spinlock, 1)) - usleep(0); -} - -static void fastlock_release(struct fastlock *lock) -{ - MEMORY_BARRIER(); - lock->spinlock = 0; - __asm__ __volatile__ ("" : "=m" (lock->spinlock) : "m" (lock->spinlock)); -} - - -/* - * Initialize mutex - */ - -int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr) -{ - fastlock_init((struct fastlock *)mutex); - return 0; -} - - -/* - * Destroy mutex - */ - -int pthread_mutex_destroy(pthread_mutex_t *mutex) -{ - return (((struct fastlock *)mutex)->status != 0) ? EBUSY : 0; -} - - -/* - * Lock mutex - */ - -int pthread_mutex_lock(pthread_mutex_t *mutex) -{ - fastlock_acquire((struct fastlock *)mutex); - return 0; -} - - -/* - * Try to lock mutex - */ - -int pthread_mutex_trylock(pthread_mutex_t *mutex) -{ - return fastlock_try_acquire((struct fastlock *)mutex); -} - - -/* - * Unlock mutex - */ - -int pthread_mutex_unlock(pthread_mutex_t *mutex) -{ - fastlock_release((struct fastlock *)mutex); - return 0; -} - - -/* - * Create mutex attribute - */ - -int pthread_mutexattr_init(pthread_mutexattr_t *attr) -{ - return 0; -} - - -/* - * Destroy mutex attribute - */ - -int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) -{ - return 0; -} - - -/* - * Init semaphore - */ - -int sem_init(sem_t *sem, int pshared, unsigned int value) -{ - if (sem == NULL || value > SEM_VALUE_MAX) { - errno = EINVAL; - return -1; - } - if (pshared) { - errno = ENOSYS; - return -1; - } - fastlock_init(&sem->sem_lock); - sem->sem_value = value; - sem->sem_waiting = 0; - return 0; -} - - -/* - * Delete remaphore - */ - -int sem_destroy(sem_t *sem) -{ - if (sem == NULL) { - errno = EINVAL; - return -1; - } - if (sem->sem_waiting) { - errno = EBUSY; - return -1; - } - sem->sem_value = 0; - sem->sem_waiting = 0; - return 0; -} - - -/* - * Wait on semaphore - */ - -int sem_wait(sem_t *sem) -{ - if (sem == NULL) { - errno = EINVAL; - return -1; - } - fastlock_acquire(&sem->sem_lock); - if (sem->sem_value > 0) { - sem->sem_value--; - fastlock_release(&sem->sem_lock); - return 0; - } - sem->sem_waiting++; - while (sem->sem_value == 0) { - fastlock_release(&sem->sem_lock); - usleep(0); - fastlock_acquire(&sem->sem_lock); - } - sem->sem_value--; - fastlock_release(&sem->sem_lock); - return 0; -} - - -/* - * Post semaphore - */ - -int sem_post(sem_t *sem) -{ - if (sem == NULL) { - errno = EINVAL; - return -1; - } - fastlock_acquire(&sem->sem_lock); - if (sem->sem_waiting) - sem->sem_waiting--; - else { - if (sem->sem_value >= SEM_VALUE_MAX) { - errno = ERANGE; - fastlock_release(&sem->sem_lock); - return -1; - } - } - sem->sem_value++; - fastlock_release(&sem->sem_lock); - return 0; -} - - -/* - * Simple producer/consumer test program - */ - -#ifdef TEST -#include - -static sem_t p_sem, c_sem; -static int data = 0; - -static void *producer_func(void *arg) -{ - int i, n = (int)arg; - for (i = 0; i < n; i++) { - sem_wait(&p_sem); - data++; - sem_post(&c_sem); - } - return NULL; -} - -static void *consumer_func(void *arg) -{ - int i, n = (int)arg; - for (i = 0; i < n; i++) { - sem_wait(&c_sem); - printf("data: %d\n", data); - sem_post(&p_sem); - } - sleep(1); // for testing pthread_join() - return NULL; -} - -int main(void) -{ - pthread_t producer_thread, consumer_thread; - static const int N = 5; - - if (sem_init(&c_sem, 0, 0) < 0) - return 1; - if (sem_init(&p_sem, 0, 1) < 0) - return 2; - if (pthread_create(&producer_thread, NULL, producer_func, (void *)N) != 0) - return 3; - if (pthread_create(&consumer_thread, NULL, consumer_func, (void *)N) != 0) - return 4; - pthread_join(producer_thread, NULL); - pthread_join(consumer_thread, NULL); - sem_destroy(&p_sem); - sem_destroy(&c_sem); - if (data != N) - return 5; - return 0; -} -#endif \ No newline at end of file diff --git a/SheepShaver/src/Unix/Makefile.in b/SheepShaver/src/Unix/Makefile.in deleted file mode 100644 index b2c3b892..00000000 --- a/SheepShaver/src/Unix/Makefile.in +++ /dev/null @@ -1,260 +0,0 @@ -# Unix makefile for SheepShaver - -## System specific configuration -@SET_MAKE@ -SHELL = /bin/sh - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -datadir = @datadir@ -mandir = @mandir@ -man1dir = $(mandir)/man1 - -DESTDIR = - -CC = @CC@ -CXX = @CXX@ -CFLAGS = @CFLAGS@ -CXXFLAGS = @CXXFLAGS@ -CPPFLAGS = @CPPFLAGS@ -I../include -I. -I../CrossPlatform -I../slirp -DEFS = @DEFS@ -D_REENTRANT -DDATADIR=\"$(datadir)/$(APP)\" -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -SYSSRCS = @SYSSRCS@ -CPUSRCS = @CPUSRCS@ -MONSRCS = @MONSRCS@ -PERL = @PERL@ -USE_DYNGEN = @USE_DYNGEN@ -DYNGENSRCS = @DYNGENSRCS@ -DYNGEN_CC = @DYNGEN_CC@ -DYNGEN_CFLAGS = @DYNGEN_CFLAGS@ -DYNGEN_CXXFLAGS = @DYNGEN_CXXFLAGS@ -DYNGEN_OP_FLAGS = @DYNGEN_OP_FLAGS@ -BLESS = @BLESS@ -EXEEXT = @EXEEXT@ -KEYCODES = @KEYCODES@ -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ - -SLIRP_CFLAGS = @SLIRP_CFLAGS@ -SLIRP_SRCS = @SLIRP_SRCS@ -SLIRP_OBJS = $(SLIRP_SRCS:../slirp/%.c=obj/%.o) - -STANDALONE_GUI = @STANDALONE_GUI@ -GUI_CFLAGS = @GUI_CFLAGS@ -GUI_LIBS = @GUI_LIBS@ -GUI_SRCS = ../prefs.cpp prefs_unix.cpp prefs_editor_gtk.cpp ../prefs_items.cpp \ - ../user_strings.cpp user_strings_unix.cpp xpram_unix.cpp sys_unix.cpp rpc_unix.cpp \ - ../dummy/prefs_dummy.cpp - -XPLAT_SRCS = ../CrossPlatform/vm_alloc.cpp ../CrossPlatform/sigsegv.cpp ../CrossPlatform/video_blit.cpp - -# Append disassembler to dyngen, if available -ifneq (:no,$(MONSRCS):$(USE_DYNGEN)) -DYNGENSRCS += $(filter %i386-dis.c,$(MONSRCS)) -endif - -## Files -SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp sys_unix.cpp \ - ../rom_patches.cpp ../rsrc_patches.cpp ../emul_op.cpp ../name_registry.cpp \ - ../macos_util.cpp ../timer.cpp timer_unix.cpp ../xpram.cpp xpram_unix.cpp \ - ../adb.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp \ - ../gfxaccel.cpp ../video.cpp ../audio.cpp ../ether.cpp ../thunks.cpp \ - ../serial.cpp ../extfs.cpp disk_sparsebundle.cpp tinyxml2.cpp \ - about_window_unix.cpp ../user_strings.cpp user_strings_unix.cpp rpc_unix.cpp \ - sshpty.c strlcpy.c $(XPLAT_SRCS) $(SYSSRCS) $(CPUSRCS) $(MONSRCS) $(SLIRP_SRCS) -APP = SheepShaver -APP_EXE = $(APP)$(EXEEXT) -APP_APP = $(APP).app - -PROGS = $(APP_EXE) -ifeq ($(STANDALONE_GUI),yes) -GUI_APP = SheepShaverGUI -GUI_APP_EXE = $(GUI_APP)$(EXEEXT) -GUI_APP_APP = $(GUI_APP).app -PROGS += $(GUI_APP_EXE) -else -CXXFLAGS += $(GUI_CFLAGS) -LIBS += $(GUI_LIBS) -endif - -## Rules -.PHONY: modules install uninstall clean distclean depend dep -.SUFFIXES: -.SUFFIXES: .c .cpp .S .o .h - -all: $(PROGS) - -OBJ_DIR = obj -$(OBJ_DIR):: - @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 - -define SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ - $(basename $(notdir $(file)))))) -endef -OBJS = $(SRCS_LIST_TO_OBJS) - -define GUI_SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .guio, $(foreach file, $(GUI_SRCS), \ - $(basename $(notdir $(file)))))) -endef -GUI_OBJS = $(GUI_SRCS_LIST_TO_OBJS) - -define DYNGENSRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .dgo, $(foreach file, $(DYNGENSRCS), \ - $(basename $(notdir $(file)))))) -endef -DYNGENOBJS = $(DYNGENSRCS_LIST_TO_OBJS) - -SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) -VPATH := -VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) - -$(APP_EXE): $(OBJ_DIR) $(OBJS) - $(CXX) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) - $(BLESS) $(APP_EXE) - -$(GUI_APP_EXE): $(OBJ_DIR) $(GUI_OBJS) - $(CXX) -o $@ $(LDFLAGS) $(GUI_OBJS) $(GUI_LIBS) - -$(APP)_app: $(APP) ../MacOSX/Info.plist ../MacOSX/$(APP).icns - rm -rf $(APP_APP)/Contents - mkdir -p $(APP_APP)/Contents - ./cpr.sh ../MacOSX/Info.plist $(APP_APP)/Contents/ - echo -n 'APPL????' > $(APP_APP)/Contents/PkgInfo - mkdir -p $(APP_APP)/Contents/MacOS - ./cpr.sh $(APP) $(APP_APP)/Contents/MacOS/ - strip -x $(APP_APP)/Contents/MacOS/$(APP) - mkdir -p $(APP_APP)/Contents/Resources - mkdir -p $(APP_APP)/Contents/Resources/English.lproj - ./cpr.sh ../MacOSX/Launcher/English.lproj/VMSettingsWindow.nib $(APP_APP)/Contents/Resources/English.lproj - ./cpr.sh ../MacOSX/SheepShaver.icns $(APP_APP)/Contents/Resources/ - -$(GUI_APP)_app: $(GUI_APP) ../MacOSX/Info.plist ../MacOSX/$(APP).icns - rm -rf $(GUI_APP_APP)/Contents - mkdir -p $(GUI_APP_APP)/Contents - sed -e "s/$(APP)/$(GUI_APP)/" < ../MacOSX/Info.plist > $(GUI_APP_APP)/Contents/Info.plist - echo -n 'APPL????' > $(GUI_APP_APP)/Contents/PkgInfo - mkdir -p $(GUI_APP_APP)/Contents/MacOS - ./cpr.sh $(GUI_APP) $(GUI_APP_APP)/Contents/MacOS/ - strip -x $(GUI_APP_APP)/Contents/MacOS/$(GUI_APP) - mkdir -p $(GUI_APP_APP)/Contents/Resources - ./cpr.sh ../MacOSX/$(APP).icns $(GUI_APP_APP)/Contents/Resources/$(GUI_APP).icns - -modules: - cd Linux/NetDriver; make - -install: $(PROGS) installdirs - $(INSTALL_PROGRAM) $(APP_EXE) $(DESTDIR)$(bindir)/$(APP_EXE) - if test -f "$(GUI_APP_EXE)"; then \ - $(INSTALL_PROGRAM) $(GUI_APP_EXE) $(DESTDIR)$(bindir)/$(GUI_APP_EXE); \ - fi - -$(INSTALL_DATA) $(APP).1 $(DESTDIR)$(man1dir)/$(APP).1 - $(INSTALL_DATA) $(KEYCODES) $(DESTDIR)$(datadir)/$(APP)/keycodes - $(INSTALL_DATA) tunconfig $(DESTDIR)$(datadir)/$(APP)/tunconfig - chmod 755 $(DESTDIR)$(datadir)/$(APP)/tunconfig - -installdirs: - $(SHELL) mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) $(DESTDIR)$(datadir)/$(APP) - -uninstall: - rm -f $(DESTDIR)$(bindir)/$(APP_EXE) - rm -f $(DESTDIR)$(bindir)/$(GUI_APP_EXE) - rm -f $(DESTDIR)$(man1dir)/$(APP).1 - rm -f $(DESTDIR)$(datadir)/$(APP)/keycodes - rm -f $(DESTDIR)$(datadir)/$(APP)/tunconfig - rmdir $(DESTDIR)$(datadir)/$(APP) - -clean: - rm -f $(PROGS) $(OBJ_DIR)/* core* *.core *~ *.bak ppc-execute-impl.cpp - rm -f dyngen basic-dyngen-ops.hpp ppc-dyngen-ops.hpp ppc_asm.out.s - rm -rf $(APP_APP) $(GUI_APP_APP) - -distclean: clean - rm -rf $(OBJ_DIR) - rm -f Makefile - rm -f config.cache config.log config.status config.h - rm -f ../MacOSX/Info.plist - -depend dep: - makedepend $(CPPFLAGS) -Y. $(SRCS) 2>/dev/null - -$(OBJ_DIR)/SDLMain.o : SDLMain.m - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : ../slirp/%.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(SLIRP_CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/DiskType.o : DiskType.m - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.mm - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.S - $(CPP) $(CPPFLAGS) -D__ASSEMBLY__ $< -o $*.out.s - $(AS) $(ASFLAGS) -o $@ $*.out.s - rm $*.out.s -$(OBJ_DIR)/%.guio : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) $(GUI_CFLAGS) -DSTANDALONE_GUI -c $< -o $@ - -# Kheperix CPU emulator -kpxsrcdir = ../kpx_cpu/src -GENEXECPL = $(kpxsrcdir)/cpu/ppc/genexec.pl -DYNGEN = dyngen$(EXEEXT) - -ifeq ($(USE_DYNGEN),yes) -DYNGENDEPS = basic-dyngen-ops.hpp ppc-dyngen-ops.hpp - -# Only GCC is supported for generating synthetic opcodes -$(DYNGEN): $(DYNGENOBJS) - $(DYNGEN_CC) -o $@ $(LDFLAGS) $(DYNGENOBJS) - -$(OBJ_DIR)/%.dgo : %.c - $(DYNGEN_CC) -xc $(CPPFLAGS) $(DEFS) $(DYNGEN_CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.dgo : %.cpp - $(DYNGEN_CC) $(CPPFLAGS) $(DEFS) $(DYNGEN_CXXFLAGS) -c $< -o $@ - -$(OBJ_DIR)/basic-dyngen.o: basic-dyngen-ops.hpp -$(OBJ_DIR)/basic-dyngen-ops.o: $(kpxsrcdir)/cpu/jit/basic-dyngen-ops.cpp - $(DYNGEN_CC) $(CPPFLAGS) $(DEFS) $(DYNGEN_CXXFLAGS) $(DYNGEN_OP_FLAGS) -c $< -o $@ -basic-dyngen-ops.hpp: $(OBJ_DIR)/basic-dyngen-ops.o $(DYNGEN) - ./$(DYNGEN) -o $@ $< - -$(OBJ_DIR)/ppc-dyngen.o: ppc-dyngen-ops.hpp -$(OBJ_DIR)/ppc-dyngen-ops.o: $(kpxsrcdir)/cpu/ppc/ppc-dyngen-ops.cpp basic-dyngen-ops.hpp - $(DYNGEN_CC) $(CPPFLAGS) $(DEFS) $(DYNGEN_CXXFLAGS) $(DYNGEN_OP_FLAGS) -c $< -o $@ -ppc-dyngen-ops.hpp: $(OBJ_DIR)/ppc-dyngen-ops.o $(DYNGEN) - ./$(DYNGEN) -o $@ $< - -$(OBJ_DIR)/sheepshaver_glue.o $(OBJ_DIR)/ppc-cpu.o $(OBJ_DIR)/ppc-decode.o $(OBJ_DIR)/ppc-translate.o $(OBJ_DIR)/ppc-jit.o: basic-dyngen-ops.hpp ppc-dyngen-ops.hpp -endif - -$(OBJ_DIR)/ppc-execute.o: ppc-execute-impl.cpp -ppc-execute-impl.cpp: $(kpxsrcdir)/cpu/ppc/ppc-decode.cpp $(GENEXECPL) $(DYNGENDEPS) - $(CPP) $(CPPFLAGS) -DGENEXEC $< | $(PERL) $(GENEXECPL) > $@ - -# PowerPC CPU tester -TESTSRCS_ = mathlib/ieeefp.cpp mathlib/mathlib.cpp cpu/ppc/ppc-cpu.cpp cpu/ppc/ppc-decode.cpp cpu/ppc/ppc-execute.cpp cpu/ppc/ppc-translate.cpp test/test-powerpc.cpp $(MONSRCS) vm_alloc.cpp utils/utils-cpuinfo.cpp -ifeq ($(USE_DYNGEN),yes) -TESTSRCS_ += cpu/jit/jit-cache.cpp cpu/jit/basic-dyngen.cpp cpu/ppc/ppc-dyngen.cpp cpu/ppc/ppc-jit.cpp -endif -TESTSRCS = $(TESTSRCS_:%.cpp=$(kpxsrcdir)/%.cpp) - -define TESTSRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(TESTSRCS), \ - $(basename $(notdir $(file)))))) -endef -TESTOBJS = $(TESTSRCS_LIST_TO_OBJS) - -$(OBJ_DIR)/test-powerpc.o: $(kpxsrcdir)/test/test-powerpc.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -DEMU_KHEPERIX -c $< -o $@ - -test-powerpc$(EXEEXT): $(TESTOBJS) - $(CXX) -o $@ $(LDFLAGS) $(TESTOBJS) $(LIBS) - -#------------------------------------------------------------------------- -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SheepShaver/src/Unix/NetBSD/sheepthreads.c b/SheepShaver/src/Unix/NetBSD/sheepthreads.c deleted file mode 100644 index 404a692f..00000000 --- a/SheepShaver/src/Unix/NetBSD/sheepthreads.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * sheepthreads.c - Minimal pthreads implementation (libpthread doesn't - * like sigaltstack) - * - * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - pthread_cancel() kills the thread immediately - * - Semaphores are VERY restricted: the only supported use is to have one - * thread sem_wait() on the semaphore while other threads sem_post() it - * (i.e. to use the semaphore as a signal) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Thread descriptor */ -struct __pthread_st { - unsigned int tid; -}; - -/* Thread stack size */ -#define STACK_SIZE 65536 - -/* From asm_linux.S */ -extern int atomic_add(int *var, int add); -extern int atomic_and(int *var, int and); -extern int atomic_or(int *var, int or); -extern int test_and_set(int *var, int val); - -/* Linux kernel calls */ -extern int __clone(int (*fn)(void *), void *, int, void *); - -/* struct sem_t */ -struct _sem_st { -#define SEM_MAGIC 0x09fa4012 - unsigned int sem_magic; - struct { - int status; - int spinlock; - } sem_lock; - int sem_value; - pid_t sem_waiting; -}; - -/* Wait for "clone" children only (Linux 2.4+ specific) */ -#ifndef __WCLONE -#define __WCLONE 0 -#endif - - -/* - * Return pthread ID of self - */ - -pthread_t pthread_self(void) -{ - static struct __pthread_st self_st; - static pthread_t self = NULL; - if (self == NULL) { - self = &self_st; - self->tid = getpid(); - } - return self; -} - - -/* - * Test whether two pthread IDs are equal - */ - -int pthread_equal(pthread_t t1, pthread_t t2) -{ - return t1 == t2; -} - - -/* - * Send signal to thread - */ - -int pthread_kill(pthread_t thread, int sig) -{ - if (kill(thread->tid, sig) == -1) - return errno; - else - return 0; -} - - -/* - * Create pthread - */ - -struct new_thread { - void *(*fn)(void *); - void *arg; -}; - -static int start_thread(void *arg) -{ - struct new_thread *nt = (struct new_thread *)arg; - nt->fn(nt->arg); - return 0; -} - -int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) -{ - struct new_thread *nt; - void *stack; - int pid; - - nt = (struct new_thread *)malloc(sizeof(struct new_thread)); - nt->fn = start_routine; - nt->arg = arg; - stack = malloc(STACK_SIZE); - - pid = __clone(start_thread, (char *)stack + STACK_SIZE - 16, CLONE_VM | CLONE_FS | CLONE_FILES, nt); - if (pid == -1) { - free(stack); - free(nt); - return errno; - } else { - *thread = malloc(sizeof(**thread)); - if (*thread == NULL) - return -1; - (*thread)->tid = pid; - return 0; - } -} - - -/* - * Join pthread - */ - -int pthread_join(pthread_t thread, void **ret) -{ - do { - if (waitpid(thread->tid, NULL, __WCLONE) >= 0); - break; - } while (errno == EINTR); - if (ret) - *ret = NULL; - return 0; -} - - -/* - * Cancel thread - */ - -int pthread_cancel(pthread_t thread) -{ - kill(thread->tid, SIGINT); - thread->tid = (unsigned int)-1; - free(thread); - return 0; -} - - -/* - * Test for cancellation - */ - -void pthread_testcancel(void) -{ -} - - -/* - * Spinlocks - */ - -static int try_acquire_spinlock(int *lock) -{ - return test_and_set(lock, 1) == 0; -} - -static void acquire_spinlock(volatile int *lock) -{ - do { - while (*lock) ; - } while (test_and_set((int *)lock, 1) != 0); -} - -static void release_spinlock(int *lock) -{ - *lock = 0; -} - - -/* - * Initialize mutex - */ - -int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr) -{ - mutex->ptm_magic = _PT_MUTEX_MAGIC; - mutex->ptm_lock = 0; - mutex->ptm_owner = NULL; - return 0; -} - - -/* - * Destroy mutex - */ - -int pthread_mutex_destroy(pthread_mutex_t *mutex) -{ - if (mutex->ptm_magic != _PT_MUTEX_MAGIC) - return EINVAL; - if (mutex->ptm_lock != 0) - return EBUSY; - - mutex->ptm_magic = _PT_MUTEX_DEAD; - return 0; -} - - -/* - * Lock mutex - */ - -int pthread_mutex_lock(pthread_mutex_t *mutex) -{ - if (mutex->ptm_magic != _PT_MUTEX_MAGIC) - return EINVAL; - - acquire_spinlock(&mutex->ptm_lock); - return 0; -} - - -/* - * Try to lock mutex - */ - -int pthread_mutex_trylock(pthread_mutex_t *mutex) -{ - if (mutex->ptm_magic != _PT_MUTEX_MAGIC) - return EINVAL; - - if (!try_acquire_spinlock(&mutex->ptm_lock)) - return EBUSY; - return 0; -} - - -/* - * Unlock mutex - */ - -int pthread_mutex_unlock(pthread_mutex_t *mutex) -{ - if (mutex->ptm_magic != _PT_MUTEX_MAGIC) - return EINVAL; - - release_spinlock(&mutex->ptm_lock); - return 0; -} - - -/* - * Create mutex attribute - */ - -int pthread_mutexattr_init(pthread_mutexattr_t *attr) -{ - attr->ptma_magic = _PT_MUTEXATTR_MAGIC; - return 0; -} - - -/* - * Destroy mutex attribute - */ - -int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) -{ - if (attr->ptma_magic != _PT_MUTEXATTR_MAGIC) - return EINVAL; - return 0; -} - - -/* - * Init semaphore - */ - -int sem_init(sem_t *psem, int pshared, unsigned int value) -{ - sem_t sem = malloc(sizeof(*sem)); - if (sem == NULL) { - errno = ENOSPC; - return 0; - } - *psem = sem; - sem->sem_magic = SEM_MAGIC; - sem->sem_lock.status = 0; - sem->sem_lock.spinlock = 0; - sem->sem_value = value; - sem->sem_waiting = 0; - return 0; -} - - -/* - * Delete remaphore - */ - -int sem_destroy(sem_t *sem) -{ - if (sem == NULL || *sem == NULL || (*sem)->sem_magic != SEM_MAGIC) { - errno = EINVAL; - return -1; - } - - free(*sem); - return 0; -} - - -/* - * Wait on semaphore - */ - -void null_handler(int sig) -{ -} - -int sem_wait(sem_t *psem) -{ - sem_t sem; - if (psem == NULL || (sem = *psem) == NULL || sem->sem_magic != SEM_MAGIC) { - errno = EINVAL; - return -1; - } - acquire_spinlock(&sem->sem_lock.spinlock); - if (sem->sem_value > 0) - atomic_add(&sem->sem_value, -1); - else { - sigset_t mask; - if (!sem->sem_lock.status) { - struct sigaction sa; - sem->sem_lock.status = SIGUSR2; - sa.sa_handler = null_handler; - sa.sa_flags = SA_RESTART; - sigemptyset(&sa.sa_mask); - sigaction(sem->sem_lock.status, &sa, NULL); - } - sem->sem_waiting = getpid(); - sigemptyset(&mask); - sigsuspend(&mask); - sem->sem_waiting = 0; - } - release_spinlock(&sem->sem_lock.spinlock); - return 0; -} - - -/* - * Post semaphore - */ - -int sem_post(sem_t *psem) -{ - sem_t sem; - if (psem == NULL || (sem = *psem) == NULL || sem->sem_magic != SEM_MAGIC) { - errno = EINVAL; - return -1; - } - acquire_spinlock(&sem->sem_lock.spinlock); - if (sem->sem_waiting == 0) - atomic_add(&sem->sem_value, 1); - else - kill(sem->sem_waiting, sem->sem_lock.status); - release_spinlock(&sem->sem_lock.spinlock); - return 0; -} - - -/* - * Simple producer/consumer test program - */ - -#ifdef TEST -#include - -static sem_t p_sem, c_sem; -static int data = 0; - -static void *producer_func(void *arg) -{ - int i, n = (int)arg; - for (i = 0; i < n; i++) { - sem_wait(&p_sem); - data++; - sem_post(&c_sem); - } - return NULL; -} - -static void *consumer_func(void *arg) -{ - int i, n = (int)arg; - for (i = 0; i < n; i++) { - sem_wait(&c_sem); - printf("data: %d\n", data); - sem_post(&p_sem); - } - sleep(1); // for testing pthread_join() - return NULL; -} - -int main(void) -{ - pthread_t producer_thread, consumer_thread; - static const int N = 5; - - if (sem_init(&c_sem, 0, 0) < 0) - return 1; - if (sem_init(&p_sem, 0, 1) < 0) - return 2; - if (pthread_create(&producer_thread, NULL, producer_func, (void *)N) != 0) - return 3; - if (pthread_create(&consumer_thread, NULL, consumer_func, (void *)N) != 0) - return 4; - pthread_join(producer_thread, NULL); - pthread_join(consumer_thread, NULL); - sem_destroy(&p_sem); - sem_destroy(&c_sem); - if (data != N) - return 5; - return 0; -} -#endif diff --git a/SheepShaver/src/Unix/SheepShaver.1 b/SheepShaver/src/Unix/SheepShaver.1 deleted file mode 100644 index 12358963..00000000 --- a/SheepShaver/src/Unix/SheepShaver.1 +++ /dev/null @@ -1,29 +0,0 @@ -.TH SheepShaver 1 "April, 2000" -.SH NAME -SheepShaver \- Macintosh emulator -.SH SYNOPSIS -.B SheepShaver -[\-display -.IR display-name ] -.SH DESCRIPTION -.B SheepShaver -is a Macintosh emulator for PowerPC-based Linux systems. -For more information, see the included documentation. -.SH OPTIONS -.TP -.BI "\-display " display-name -specifies the display to use; see -.BR X (1) -.SH FILES -.TP -.I ~/.sheepshaver_prefs -User-specific configuration file. -.TP -.I ~/.sheeshaver_nvram -Contents of Mac non-volatile RAM. -.SH SEE ALSO -http://www.sheepshaver.com/ (Official SheepShaver homepage) -.SH AUTHORS -Christian Bauer -.br -Marc Hellwig diff --git a/SheepShaver/src/Unix/about_window_unix.cpp b/SheepShaver/src/Unix/about_window_unix.cpp deleted file mode 100644 index 3d4127fd..00000000 --- a/SheepShaver/src/Unix/about_window_unix.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * about_window_unix.cpp - "About" window, Unix implementation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "about_window.h" - - -/* - * Open "About" window - */ - -void OpenAboutWindow(void) -{ -} diff --git a/SheepShaver/src/Unix/audio_oss_esd.cpp b/SheepShaver/src/Unix/audio_oss_esd.cpp deleted file mode 120000 index acf070c1..00000000 --- a/SheepShaver/src/Unix/audio_oss_esd.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/audio_oss_esd.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/autogen.sh b/SheepShaver/src/Unix/autogen.sh deleted file mode 100755 index f6b732ad..00000000 --- a/SheepShaver/src/Unix/autogen.sh +++ /dev/null @@ -1,61 +0,0 @@ -#! /bin/sh -# Run this to generate all the initial makefiles, etc. -# This was lifted from the Gimp, and adapted slightly by -# Christian Bauer. - -DIE=0 - -PROG="SheepShaver" - -# Check how echo works in this /bin/sh -case `echo -n` in --n) _echo_n= _echo_c='\c';; -*) _echo_n=-n _echo_c=;; -esac - -(autoconf --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "You must have autoconf installed to compile $PROG." - echo "Download the appropriate package for your distribution," - echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" - DIE=1 -} - -(aclocal --version) < /dev/null > /dev/null 2>&1 || { - echo - echo "**Error**: Missing aclocal. The version of automake" - echo "installed doesn't appear recent enough." - echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz" - echo "(or a newer version if it is available)" - DIE=1 -} - -if test "$DIE" -eq 1; then - exit 1 -fi - -if test -z "$ACLOCAL_FLAGS"; then - ACLOCAL_FLAGS="-I `aclocal --print-ac-dir` -I m4" -fi - -aclocalinclude="$ACLOCAL_FLAGS"; \ -(echo $_echo_n " + Running aclocal: $_echo_c"; \ - aclocal $aclocalinclude; \ - echo "done.") && \ -(echo $_echo_n " + Running autoheader: $_echo_c"; \ - autoheader; \ - echo "done.") && \ -(echo $_echo_n " + Running autoconf: $_echo_c"; \ - autoconf; \ - echo "done.") - -rm -f config.cache - -if [ x"$NO_CONFIGURE" = "x" ]; then - echo " + Running 'configure $@':" - if [ -z "$*" ]; then - echo " ** If you wish to pass arguments to ./configure, please" - echo " ** specify them on the command line." - fi - ./configure "$@" -fi diff --git a/SheepShaver/src/Unix/bincue_unix.cpp b/SheepShaver/src/Unix/bincue_unix.cpp deleted file mode 120000 index f9ed574d..00000000 --- a/SheepShaver/src/Unix/bincue_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/bincue_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/bincue_unix.h b/SheepShaver/src/Unix/bincue_unix.h deleted file mode 120000 index 9c7e8c5c..00000000 --- a/SheepShaver/src/Unix/bincue_unix.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/bincue_unix.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/clip_unix.cpp b/SheepShaver/src/Unix/clip_unix.cpp deleted file mode 120000 index bd5316ec..00000000 --- a/SheepShaver/src/Unix/clip_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/clip_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/config.guess b/SheepShaver/src/Unix/config.guess deleted file mode 120000 index d7e5917c..00000000 --- a/SheepShaver/src/Unix/config.guess +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/config.guess \ No newline at end of file diff --git a/SheepShaver/src/Unix/config.sub b/SheepShaver/src/Unix/config.sub deleted file mode 120000 index 5458c713..00000000 --- a/SheepShaver/src/Unix/config.sub +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/config.sub \ No newline at end of file diff --git a/SheepShaver/src/Unix/configure.ac b/SheepShaver/src/Unix/configure.ac deleted file mode 100644 index 11e4c10a..00000000 --- a/SheepShaver/src/Unix/configure.ac +++ /dev/null @@ -1,1687 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -dnl Written in 2002 by Christian Bauer - -AC_INIT([SheepShaver], 2.4, [Christian.Bauer@uni-mainz.de], SheepShaver) -AC_CONFIG_SRCDIR(main_unix.cpp) -AC_PREREQ(2.52) -AC_CONFIG_HEADER(config.h) -AH_TOP( -#ifndef CONFIG_H -#define CONFIG_H -) -AH_BOTTOM( -#endif /* CONFIG_H */ -) - -dnl Canonical system information. -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -dnl Some systems do not put corefiles in the currect directory, avoid saving -dnl cores for the configure tests since some are intended to dump core. -ulimit -c 0 - -dnl Invite Cygwin users to build within the Windows/ directory -case $target_os in -*cygwin* | *mingw32*) - AC_MSG_ERROR([You can only build the Windows version from its directory, Cygwin/X11 is not supported.]) - ;; -esac - -dnl Options. -AC_ARG_ENABLE(jit, [ --enable-jit enable JIT compiler [default=yes]], [WANT_JIT=$enableval], [WANT_JIT=yes]) -AC_ARG_ENABLE(ppc-emulator, [ --enable-ppc-emulator use the selected PowerPC emulator [default=auto]], [WANT_EMULATED_PPC=$enableval], [WANT_EMULATED_PPC=auto]) -AC_ARG_ENABLE(fbdev-dga, [ --enable-fbdev-dga use direct frame buffer access via /dev/fb0 [default=yes]], [WANT_FBDEV_DGA=$enableval], [WANT_FBDEV_DGA=yes]) -AC_ARG_ENABLE(xf86-dga, [ --enable-xf86-dga use the XFree86 DGA extension [default=yes]], [WANT_XF86_DGA=$enableval], [WANT_XF86_DGA=yes]) -AC_ARG_ENABLE(xf86-vidmode, [ --enable-xf86-vidmode use the XFree86 VidMode extension [default=yes]], [WANT_XF86_VIDMODE=$enableval], [WANT_XF86_VIDMODE=yes]) -AC_ARG_ENABLE(vosf, [ --enable-vosf enable video on SEGV signals [default=yes]], [WANT_VOSF=$enableval], [WANT_VOSF=yes]) -AC_ARG_ENABLE(standalone-gui,[ --enable-standalone-gui enable a standalone GUI prefs editor [default=no]], [WANT_STANDALONE_GUI=$enableval], [WANT_STANDALONE_GUI=no]) -AC_ARG_WITH(esd, [ --with-esd support ESD for sound under Linux/FreeBSD [default=yes]], [WANT_ESD=$withval], [WANT_ESD=yes]) -AC_ARG_WITH(gtk, [ --with-gtk use GTK user interface [default=yes]], - [case "$withval" in - gtk1) WANT_GTK="gtk";; - gtk|gtk2) WANT_GTK="$withval";; - yes) WANT_GTK="gtk2 gtk";; - *) WANT_GTK="no";; - esac], - [WANT_GTK="gtk2 gtk"]) -AC_ARG_WITH(mon, [ --with-mon use mon as debugger [default=yes]], [WANT_MON=$withval], [WANT_MON=yes]) -AC_ARG_WITH(dgcc, [ --with-dgcc=COMPILER use C++ COMPILER to compile synthetic opcodes], [DYNGEN_CC=$withval]) - -AC_ARG_WITH(bincue, - AS_HELP_STRING([--with-bincue], [Allow cdrom image files in bin/cue mode])) - -AC_ARG_WITH(libvhd, - AS_HELP_STRING([--with-libvhd], [Enable VHD disk images])) - - -dnl Addressing mode -AC_ARG_ENABLE(addressing, - [ --enable-addressing=AM set the addressing mode to use [default=real]], - [case "$enableval" in - real) WANT_ADDRESSING_MODE="real";; - direct) WANT_ADDRESSING_MODE="direct";; - direct,0x*) WANT_ADDRESSING_MODE="direct"; NATMEM_OFFSET=`echo "$enableval" | sed -n '/direct,\(0[[xX]][[0-9A-Fa-f]]*\([[UuLl]]\{1,2\}\)\?\)$/s//\1/p'`;; - esac], - [WANT_ADDRESSING_MODE="real"] -) - -dnl SDL options. -AC_ARG_ENABLE(sdl-static, [ --enable-sdl-static use SDL static libraries for linking [default=no]], [WANT_SDL_STATIC=$enableval], [WANT_SDL_STATIC=no]) -AC_ARG_ENABLE(sdl-video, [ --enable-sdl-video use SDL for video graphics [default=no]], [WANT_SDL_VIDEO=$enableval], [WANT_SDL_VIDEO=no]) -AC_ARG_ENABLE(sdl-audio, [ --enable-sdl-audio use SDL for audio [default=no]], [WANT_SDL_AUDIO=$enableval], [WANT_SDL_AUDIO=no]) -AC_ARG_ENABLE(sdl-framework, [ --enable-sdl-framework use SDL framework [default=no]], [WANT_SDL_FRAMEWORK=$enableval], [WANT_SDL_FRAMEWORK=no]) -AC_ARG_ENABLE(sdl-framework-prefix, [ --enable-sdl-framework-prefix=PFX default=/Library/Frameworks], [SDL_FRAMEWORK="$enableval"], [SDL_FRAMEWORK=/Library/Frameworks]) - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_MAKE_SET -AC_PROG_INSTALL -AC_PROG_EGREP -AC_PATH_PROGS(FILE, [file false]) -AC_PATH_PROG(PERL, [perl]) - -dnl Check for PowerPC target CPU. -HAVE_PPC=no -AC_MSG_CHECKING(for PowerPC target CPU) -AC_EGREP_CPP(yes, -[ -#ifdef __powerpc__ - yes -#endif -#ifdef __ppc__ - yes -#endif -], [AC_MSG_RESULT(yes); HAVE_PPC=yes], AC_MSG_RESULT(no)) - -dnl We use native CPU if possible. -EMULATED_PPC=yes -case $WANT_EMULATED_PPC in - auto) [[ "x$HAVE_PPC" = "xyes" ]] && EMULATED_PPC=no;; - no) EMULATED_PPC=no;; -esac -if [[ "x$EMULATED_PPC" = "xyes" ]]; then - AC_DEFINE(EMULATED_PPC, 1, [Define if using a PowerPC CPU emulator.]) -fi - -dnl We use mon if possible. -MONSRCS= -case "x$WANT_MON" in -x/* | x.*) - mon_srcdir=$WANT_MON - WANT_MON=yes - ;; -xyes) - mon_srcdir=../../../mon/src - ;; -esac -if [[ "x$WANT_MON" = "xyes" ]]; then - AC_MSG_CHECKING(for mon) - if grep mon_init $mon_srcdir/mon.h >/dev/null 2>/dev/null; then - AC_MSG_RESULT(yes) - AC_DEFINE(ENABLE_MON, 1, [Define if using "mon".]) - MONSRCS="$mon_srcdir/mon.cpp $mon_srcdir/mon_6502.cpp $mon_srcdir/mon_z80.cpp $mon_srcdir/mon_cmd.cpp $mon_srcdir/mon_lowmem.cpp $mon_srcdir/mon_disass.cpp $mon_srcdir/mon_ppc.cpp $mon_srcdir/disass/floatformat.c $mon_srcdir/disass/i386-dis.c $mon_srcdir/disass/m68k-dis.c $mon_srcdir/disass/m68k-opc.c $mon_srcdir/disass/mips-dis.c $mon_srcdir/disass/mips-opc.c $mon_srcdir/disass/mips16-opc.c" - CXXFLAGS="$CXXFLAGS -I$mon_srcdir -I$mon_srcdir/disass" - AC_CHECK_LIB(ncurses, tgetent, , - [AC_CHECK_LIB(termcap, tgetent, , - [AC_CHECK_LIB(termlib, tgetent, , - [AC_CHECK_LIB(terminfo, tgetent, , - [AC_CHECK_LIB(Hcurses, tgetent, , - [AC_CHECK_LIB(curses, tgetent)])])])])]) - AC_CHECK_LIB(readline, readline) - AC_CHECK_HEADERS(readline.h history.h readline/readline.h readline/history.h) - else - AC_MSG_RESULT(no) - AC_MSG_WARN([Could not find mon, ignoring --with-mon.]) - WANT_MON=no - fi -fi -AC_SUBST(MONSRCS) - -dnl Checks for libraries. -AC_CHECK_LIB(posix4, sem_init) -AC_CHECK_LIB(m, cos) - -dnl AC_CHECK_SDLFRAMEWORK($1=NAME, $2=INCLUDES) -dnl AC_TRY_LINK uses main() but SDL needs main to take args, -dnl therefore main is undefined with #undef. -dnl Framework can be in an custom location. -AC_DEFUN([AC_CHECK_SDLFRAMEWORK], [ - AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1]) - AC_CACHE_CHECK([whether compiler supports framework $1], - ac_Framework, [ - saved_LIBS="$LIBS" - LIBS="$LIBS -framework $1" - if [[ "x$SDL_FRAMEWORK" != "x/Library/Frameworks" ]]; then - if [[ "x$SDL_FRAMEWORK" != "x/System/Library/Frameworks" ]]; then - LIBS="$saved_LIBS -F$SDL_FRAMEWORK -framework $1" - fi - fi - saved_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -I$SDL_FRAMEWORK/SDL.framework/Headers" - AC_TRY_LINK( - [$2 -#undef main], [], - [AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no); -LIBS="$saved_LIBS"; CPPFLAGS="$saved_CPPFLAGS"] - ) - ]) - AS_IF([test AS_VAR_GET(ac_Framework) = yes], - [AC_DEFINE(AS_TR_CPP(HAVE_FRAMEWORK_$1), 1, [Define if framework $1 is available.])] - ) - AS_VAR_POPDEF([ac_Framework]) -]) - -dnl Do we need SDL? -WANT_SDL=no -if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then - WANT_SDL=yes - WANT_XF86_DGA=no - WANT_XF86_VIDMODE=no - WANT_FBDEV_DGA=no - SDL_SUPPORT="$SDL_SUPPORT video" -fi -if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then - WANT_SDL=yes - SDL_SUPPORT="$SDL_SUPPORT audio" -fi -if [[ "x$WANT_SDL" = "xyes" ]]; then - if [[ "x$WANT_SDL_FRAMEWORK" = "xyes" ]]; then - AC_CHECK_SDLFRAMEWORK(SDL, [#include ]) - else - ac_cv_framework_SDL=no - fi - if [[ "x$ac_cv_framework_SDL" = "xno" ]]; then - AC_PATH_PROG(sdl_config, "sdl-config") - if [[ -n "$sdl_config" ]]; then - sdl_cflags=`$sdl_config --cflags` - if [[ "x$WANT_SDL_STATIC" = "xyes" ]]; then - sdl_libs=`$sdl_config --static-libs` - else - sdl_libs=`$sdl_config --libs` - fi - CFLAGS="$CFLAGS $sdl_cflags" - CXXFLAGS="$CXXFLAGS $sdl_cflags" - LIBS="$LIBS $sdl_libs" - else - WANT_SDL=no - WANT_SDL_VIDEO=no - WANT_SDL_AUDIO=no - fi - fi - SDL_SUPPORT=`echo "$SDL_SUPPORT" | sed -e "s/^ //"` -else - SDL_SUPPORT="none" -fi - -dnl We need X11, if not using SDL. -if [[ "x$WANT_SDL_VIDEO" != "xyes" ]]; then - AC_PATH_XTRA - if [[ "x$no_x" = "xyes" ]]; then - AC_MSG_ERROR([You need X11 to run SheepShaver.]) - fi - CFLAGS="$CFLAGS $X_CFLAGS" - CXXFLAGS="$CXXFLAGS $X_CFLAGS" - LIBS="$LIBS $X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS" -fi - - - -dnl We need pthreads on non-PowerPC systems. Try libpthread first, then libc_r (FreeBSD), then PTL. -HAVE_PTHREADS=yes -case $EMULATED_PPC:$target_os in -no:linux*|no:netbsd*) - dnl We do have our own pthread_cancel() implementation - AC_DEFINE(HAVE_PTHREAD_CANCEL, 1, [Define if you have the pthread_cancel function.]) - ;; -*:*) - AC_CHECK_LIB(pthread, pthread_create, , [ - AC_CHECK_LIB(c_r, pthread_create, , [ - AC_CHECK_LIB(PTL, pthread_create, , [ - dnl XXX remove when no pthreads case is merged - AC_MSG_ERROR([You need pthreads to run SheepShaver.]) - HAVE_PTHREADS=no - ]) - ]) - ]) - AC_CHECK_FUNCS(pthread_cancel) - AC_CHECK_FUNCS(pthread_cond_init pthread_testcancel) - AC_CHECK_FUNCS(pthread_mutexattr_setprotocol) - AC_CHECK_FUNCS(pthread_mutexattr_settype) - AC_CHECK_FUNCS(pthread_mutexattr_setpshared) - dnl If POSIX.4 semaphores are not available, we emulate them with pthread mutexes. - SEMSRC= - AC_CHECK_FUNCS(sem_init, , [ - if test "x$HAVE_PTHREADS" = "xyes"; then - SEMSRC=posix_sem.cpp - fi - ]) - ;; -esac -if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then - AC_DEFINE(HAVE_PTHREADS, 1, [Define if pthreads are available.]) -fi - -dnl We use FBDev DGA if possible. -if [[ "x$WANT_FBDEV_DGA" = "xyes" ]]; then - AC_CHECK_HEADER(linux/fb.h, [ - AC_DEFINE(ENABLE_FBDEV_DGA, 1, [Define if using Linux fbdev extension.]) - ], [ - AC_MSG_WARN([Could not find Linux FBDev extension, ignoring --enable-fbdev-dga.]) - WANT_FBDEV_DGA=no - ]) -fi - -dnl We use XFree86 DGA if possible. -if [[ "x$WANT_XF86_DGA" = "xyes" ]]; then - AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension, [ - AC_DEFINE(ENABLE_XF86_DGA, 1, [Define if using XFree86 DGA extension.]) - LIBS="$LIBS -lXxf86dga" - ], [ - AC_MSG_WARN([Could not find XFree86 DGA extension, ignoring --enable-xf86-dga.]) - WANT_XF86_DGA=no - ]) -fi - -dnl We use XFree86 VidMode if possible. -if [[ "x$WANT_XF86_VIDMODE" = "xyes" ]]; then - AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension, [ - AC_DEFINE(ENABLE_XF86_VIDMODE, 1, [Define if using XFree86 DGA extension.]) - LIBS="$LIBS -lXxf86vm" - ], [ - AC_MSG_WARN([Could not find XFree86 VidMode extension, ignoring --enable-xf86-vidmode.]) - WANT_XF86_VIDMODE=no - ]) -fi - -dnl We use GTK+ if possible. -UISRCS=../dummy/prefs_editor_dummy.cpp -case "x$WANT_GTK" in -xgtk2*) - WANT_GTK=no - AM_PATH_GTK_2_0(1.3.15, [ - GUI_CFLAGS="$GTK_CFLAGS" - GUI_LIBS="$GTK_LIBS" - WANT_GTK=gtk2 - ], [ - case "x${WANT_GTK}x" in - *gtkx) - AC_MSG_WARN([Could not find GTK+ 2.0, trying with GTK+ 1.2.]) - WANT_GTK=gtk - ;; - *) - AC_MSG_WARN([Could not find GTK+, disabling user interface.]) - WANT_GTK=no - ;; - esac - ]) - ;; -esac -if [[ "x$WANT_GTK" = "xgtk" ]]; then - WANT_GTK=no - AM_PATH_GTK(1.2.0, [ - GUI_CFLAGS="$GTK_CFLAGS" - GUI_LIBS="$GTK_LIBS" - WANT_GTK=gtk - ], [ - AC_MSG_WARN([Could not find GTK+, disabling user interface.]) - ]) -fi -if [[ "x$WANT_GTK" != "xno" -a "x$WANT_STANDALONE_GUI" = "xno" ]]; then - AC_DEFINE(ENABLE_GTK, 1, [Define if using GTK.]) - UISRCS=prefs_editor_gtk.cpp -fi -AC_SUBST(GUI_CFLAGS) -AC_SUBST(GUI_LIBS) - -dnl Build external GUI if requested. -if [[ "$WANT_STANDALONE_GUI" != "yes" ]]; then - WANT_STANDALONE_GUI=no -fi -if [[ "$WANT_GTK" = "no" ]]; then - WANT_STANDALONE_GUI=no -fi -AC_SUBST(STANDALONE_GUI, [$WANT_STANDALONE_GUI]) - -dnl We use ESD if possible. -if [[ "x$WANT_ESD" = "xyes" ]]; then - WANT_ESD=no - AM_PATH_ESD(0.2.8, [ - AC_DEFINE(ENABLE_ESD, 1, [Define is using ESD.]) - CFLAGS="$CFLAGS $ESD_CFLAGS" - CXXFLAGS="$CXXFLAGS $ESD_CFLAGS" - LIBS="$LIBS $ESD_LIBS" - WANT_ESD=yes - ], [ - AC_MSG_WARN([Could not find ESD, disabling ESD support.]) - ]) -fi - -dnl We use 64-bit file size support if possible. -AC_SYS_LARGEFILE - -dnl Checks for header files. -AC_HEADER_STDC -AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(malloc.h stdint.h) -AC_CHECK_HEADERS(mach/vm_map.h mach/mach_init.h sys/mman.h) -AC_CHECK_HEADERS(unistd.h fcntl.h byteswap.h dirent.h) -AC_CHECK_HEADERS(sys/socket.h sys/ioctl.h sys/filio.h sys/bitypes.h sys/wait.h) -AC_CHECK_HEADERS(sys/time.h sys/poll.h sys/select.h arpa/inet.h) -AC_CHECK_HEADERS(netinet/in.h linux/if.h linux/if_tun.h net/if.h net/if_tun.h, [], [], [ -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -]) -AC_CHECK_HEADERS(AvailabilityMacros.h) -AC_CHECK_HEADERS(IOKit/storage/IOBlockStorageDevice.h) -AC_CHECK_HEADERS(fenv.h) -AC_CHECK_HEADERS(sys/stropts.h stropts.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_BIGENDIAN -AC_C_CONST -AC_C_INLINE -AC_CHECK_SIZEOF(short, 2) -AC_CHECK_SIZEOF(int, 4) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_SIZEOF(long long, 8) -AC_CHECK_SIZEOF(float, 4) -AC_CHECK_SIZEOF(double, 8) -AC_CHECK_SIZEOF(void *, 4) -AC_TYPE_OFF_T -AC_CHECK_TYPE(loff_t, off_t) -AC_TYPE_SIZE_T -AC_TYPE_SIGNAL -AC_HEADER_TIME -AC_STRUCT_TM - -dnl Check whether sys/socket.h defines type socklen_t. -dnl (extracted from ac-archive/Miscellaneous) -AC_CACHE_CHECK([for socklen_t], - ac_cv_type_socklen_t, [ - AC_TRY_COMPILE([ - #include - #include - ], [socklen_t len = 42; return 0;], - ac_cv_type_socklen_t=yes, ac_cv_type_socklen_t=no, - dnl When cross-compiling, do not assume anything. - ac_cv_type_socklen_t="guessing no" - ) -]) -if [[ "x$ac_cv_type_socklen_t" != "xyes" ]]; then - AC_DEFINE(socklen_t, int, [Define to 'int' if doesn't define.]) -fi - -dnl Check whether struct sigaction has sa_restorer member. -AC_CACHE_CHECK([whether struct sigaction has sa_restorer], - ac_cv_signal_sa_restorer, [ - AC_TRY_COMPILE([ - #include - ], [struct sigaction sa; sa.sa_restorer = 0;], - ac_cv_signal_sa_restorer=yes, ac_cv_signal_sa_restorer=no, - dnl When cross-compiling, do not assume anything. - ac_cv_signal_sa_restorer=no - ) -]) -if [[ "x$ac_cv_signal_sa_restorer" = "xyes" ]]; then - AC_DEFINE(HAVE_SIGNAL_SA_RESTORER, 1, [Define if sa_restorer is available in struct sigaction.]) -fi - -dnl Checks for library functions. -AC_CHECK_FUNCS(strdup strerror strlcpy cfmakeraw) -AC_CHECK_FUNCS(nanosleep) -AC_CHECK_FUNCS(sigaction signal) -AC_CHECK_FUNCS(mmap mprotect munmap) -AC_CHECK_FUNCS(vm_allocate vm_deallocate vm_protect) -AC_CHECK_FUNCS(exp2f log2f exp2 log2) -AC_CHECK_FUNCS(floorf roundf ceilf truncf floor round ceil trunc) -AC_CHECK_FUNCS(poll inet_aton) - -dnl Darwin seems to define mach_task_self() instead of task_self(). -AC_CHECK_FUNCS(mach_task_self task_self) - -dnl We need clock_gettime() for better performance but it may drag -dnl libpthread in, which we don't want for native ppc mode -case $EMULATED_PPC:$target_os in -no:linux*) - ;; -*:*) - AC_SEARCH_LIBS(clock_gettime, [rt posix4]) - AC_CHECK_FUNCS(clock_gettime clock_nanosleep) - ;; -esac - -dnl Check for headers and functions related to pty support (sshpty.c) -dnl From openssh-3.2.2p1 configure.ac -AC_CHECK_HEADERS(strings.h login.h sys/bsdtty.h sys/stat.h util.h pty.h) -AC_CHECK_FUNCS(_getpty vhangup strlcpy) - -case "$host" in -*-*-hpux10.26) - disable_ptmx_check=yes - ;; -*-*-linux*) - no_dev_ptmx=1 - ;; -mips-sony-bsd|mips-sony-newsos4) - AC_DEFINE(HAVE_NEWS4, 1, [Define if you are on NEWS-OS (additions from openssh-3.2.2p1, for sshpty.c).]) - ;; -*-*-sco3.2v4*) - no_dev_ptmx=1 - ;; -*-*-sco3.2v5*) - no_dev_ptmx=1 - ;; -*-*-cygwin*) - no_dev_ptmx=1 - ;; -*-*-darwin*) - no_dev_ptmx=1 - ;; -*-*-freebsd*) - no_dev_ptmx=1 - ;; -esac - -if test -z "$no_dev_ptmx" ; then - if test "x$disable_ptmx_check" != "xyes" ; then - AC_CHECK_FILE([/dev/ptmx], - [ - AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX, 1, [Define if you have /dev/ptmx.]) - have_dev_ptmx=1 - ] - ) - fi -fi -AC_CHECK_FILE([/dev/ptc], - [ - AC_DEFINE_UNQUOTED(HAVE_DEV_PTS_AND_PTC, 1, [Define if you have /dev/ptc.]) - have_dev_ptc=1 - ] -) -dnl (end of code from openssh-3.2.2p1 configure.ac) - -dnl Check for systems where POSIX-style non-blocking I/O (O_NONBLOCK) -dnl doesn't work or is unimplemented. On these systems (mostly older -dnl ones), use the old BSD-style FIONBIO approach instead. [tcl.m4] -AC_CACHE_CHECK([FIONBIO vs. O_NONBLOCK for non-blocking I/O], - ac_cv_nonblocking_io, [ - case "$host" in - *-*-osf*) - ac_cv_nonblocking_io=FIONBIO - ;; - *-*-sunos4*) - ac_cv_nonblocking_io=FIONBIO - ;; - *-*-ultrix*) - ac_cv_nonblocking_io=FIONBIO - ;; - *) - ac_cv_nonblocking_io=O_NONBLOCK - ;; - esac -]) -if [[ "$ac_cv_nonblocking_io" = "FIONBIO" ]]; then - AC_DEFINE(USE_FIONBIO, 1, [Define if BSD-style non-blocking I/O is to be used]) -fi - -dnl Check whether compiler supports byte bit-fields -AC_CACHE_CHECK([whether compiler supports byte bit-fields], - ac_cv_have_byte_bitfields, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - struct A { - unsigned char b1:4; - unsigned char b2:4; - unsigned char c; - unsigned short s; - unsigned char a[4]; - }; - - int main(void) { - A a; - return ! (sizeof(A) == 8 && &a.c == ((unsigned char *)&a + 1)); - }], - [ac_cv_have_byte_bitfields=yes], - [ac_cv_have_byte_bitfields=no], - dnl When cross-compiling, assume only GCC supports this - [if [[ "$GCC" = "yes" ]]; then - ac_cv_have_byte_bitfields="guessing yes" - else - ac_cv_have_byte_bitfields="guessing no" - fi] - ) - AC_LANG_RESTORE -]) - -dnl AC_CHECK_FRAMEWORK($1=NAME, $2=INCLUDES) -AC_DEFUN([AC_CHECK_FRAMEWORK], [ - AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1])dnl - AC_CACHE_CHECK([whether compiler supports framework $1], - ac_Framework, [ - saved_LIBS="$LIBS" - LIBS="$LIBS -framework $1" - AC_TRY_LINK( - [$2], [], - [AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no); LIBS="$saved_LIBS"] - ) - ]) - AS_IF([test AS_VAR_GET(ac_Framework) = yes], - [AC_DEFINE(AS_TR_CPP(HAVE_FRAMEWORK_$1), 1, [Define if framework $1 is available.])] - ) - AS_VAR_POPDEF([ac_Framework])dnl -]) - -dnl Check for some MacOS X frameworks -AC_CHECK_FRAMEWORK(Carbon, [#include ]) -AC_CHECK_FRAMEWORK(IOKit, [#include ]) -AC_CHECK_FRAMEWORK(CoreFoundation, [#include ]) -AC_CHECK_FRAMEWORK(CoreAudio, [#include ]) -AC_CHECK_FRAMEWORK(AudioUnit, [#include ]) -AC_CHECK_FRAMEWORK(AudioToolbox, [#include ]) -AC_CHECK_FRAMEWORK(AppKit, []) - -dnl Select system-dependant sources. -SERIALSRC=serial_unix.cpp -ETHERSRC=../dummy/ether_dummy.cpp -SCSISRC=../dummy/scsi_dummy.cpp -AUDIOSRC=../dummy/audio_dummy.cpp -PREFSSRC=../dummy/prefs_dummy.cpp -EXTFSSRC=extfs_unix.cpp -EXTRASYSSRCS= -case "$target_os" in -linux*) - ETHERSRC=ether_unix.cpp - AUDIOSRC=audio_oss_esd.cpp - SCSISRC=Linux/scsi_linux.cpp - if [[ "x$EMULATED_PPC" = "xno" ]]; then - EXTRASYSSRCS="paranoia.cpp Linux/sheepthreads.c ppc_asm.S" - fi - ;; -freebsd*) - ETHERSRC=ether_unix.cpp - ;; -netbsd*) - ETHERSRC=ether_unix.cpp - if [[ "x$EMULATED_PPC" = "xno" ]]; then - EXTRASYSSRCS="paranoia.cpp NetBSD/sheepthreads.c ppc_asm.S" - fi - ;; -darwin*) - ETHERSRC=ether_unix.cpp - if [[ "x$EMULATED_PPC" = "xno" ]]; then - EXTRASYSSRCS="paranoia.cpp ppc_asm.S" - fi - if [[ "x$ac_cv_framework_IOKit" = "xyes" -a "x$ac_cv_framework_CoreFoundation" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/sys_darwin.cpp" - fi - if [[ "x$ac_cv_framework_Carbon" = "xyes" ]]; then - EXTFSSRC=../MacOSX/extfs_macosx.cpp - if [[ "x$ac_cv_framework_AppKit" = "xyes" -a "x$WANT_GTK" = "xno" ]]; then - PREFSSRC="../MacOSX/prefs_macosx.mm ../MacOSX/Launcher/VMSettingsController.mm ../MacOSX/Launcher/DiskType.m" - CPPFLAGS="$CPPFLAGS -I../MacOSX/Launcher" - fi - fi - if [[ "x$WANT_ESD" = "xno" -a "x$ac_cv_framework_CoreAudio" = "xyes" -a "x$WANT_SDL_AUDIO" = "xno" ]]; then - AUDIOSRC="../MacOSX/audio_macosx.cpp ../MacOSX/AudioBackEnd.cpp ../MacOSX/AudioDevice.cpp ../MacOSX/MacOSX_sound_if.cpp" - OSX_CORE_AUDIO="-DOSX_CORE_AUDIO" - fi - ;; -irix*) - AUDIOSRC=Irix/audio_irix.cpp - LIBS="$LIBS -laudio" - WANT_ESD=no - - dnl Check if our compiler supports -IPA (MIPSPro) - HAVE_IPA=no - ocflags="$CFLAGS" - CFLAGS=`echo " $CFLAGS -IPA" | sed -e "s/ -g //g"` - AC_MSG_CHECKING(if "-IPA" works) - dnl Do a test compile of an empty function - AC_TRY_COMPILE([#if defined __GNUC__ - # error GCC does not support IPA yet - #endif],, [AC_MSG_RESULT(yes); HAVE_IPA=yes], AC_MSG_RESULT(no)) - CFLAGS="$ocflags" - ;; -esac - -dnl BINCUE -AS_IF([test "x$with_bincue" = "xyes" ], [have_bincue=yes], [have_bincue=no]) -AS_IF([test "x$have_bincue" = "xyes" ], [ - if [[ "xOSX_CORE_AUDIO" = "xno" -a "x$WANT_SDL_AUDIO"="xno" ]]; then - AC_MSG_ERROR([You need SDL or OSX Core Audio to use BINCUE support.]) - else - CPPFLAGS="$CPPFLAGS -DBINCUE $OSX_CORE_AUDIO" - fi -]) - -dnl LIBVHD -AS_IF([test "x$with_libvhd" = "xyes" ], [have_libvhd=yes], [have_libvhd=no]) -AS_IF([test "x$have_libvhd" = "xyes" ], [ - CPPFLAGS="$CPPFLAGS -DHAVE_LIBVHD" - LIBS="$LIBS -lvhd" - case $target_os in - linux*) - LIBS="$LIBS -luuid" - esac - AC_CHECK_LIB(vhd, vhd_open) - AC_CHECK_LIB(vhd, vhd_io_read) - AC_CHECK_LIB(vhd, vhd_io_write) - AC_CHECK_LIB(vhd, vhd_close) -]) - - - - -dnl Is the slirp library supported? -case "$ac_cv_have_byte_bitfields" in -yes|"guessing yes") - CAN_SLIRP=yes - ETHERSRC=ether_unix.cpp - ;; -esac -if [[ -n "$CAN_SLIRP" ]]; then - AC_DEFINE(HAVE_SLIRP, 1, [Define if slirp library is supported]) - SLIRP_SRCS="\ - ../slirp/bootp.c ../slirp/ip_output.c ../slirp/tcp_input.c \ - ../slirp/cksum.c ../slirp/mbuf.c ../slirp/tcp_output.c \ - ../slirp/debug.c ../slirp/misc.c ../slirp/tcp_subr.c \ - ../slirp/if.c ../slirp/sbuf.c ../slirp/tcp_timer.c \ - ../slirp/ip_icmp.c ../slirp/slirp.c ../slirp/tftp.c \ - ../slirp/ip_input.c ../slirp/socket.c ../slirp/udp.c" -fi -AC_SUBST(SLIRP_SRCS) - -dnl SDL overrides -if [[ "x$WANT_SDL" = "xyes" ]]; then - AC_DEFINE(USE_SDL, 1, [Define to enble SDL support.]) - if [[ "x$WANT_SDL_FRAMEWORK" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS ../SDL/SDLMain.m" - fi -fi -if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then - AC_DEFINE(USE_SDL_VIDEO, 1, [Define to enable SDL video graphics support.]) - VIDEOSRCS="../SDL/video_sdl.cpp" - KEYCODES="../SDL/keycodes" - if [[ "x$ac_cv_framework_Carbon" = "xyes" ]]; then - AC_MSG_CHECKING([whether __LP64__ is defined]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if !defined(__LP64__) - # error __LP64__ not defined - #endif - ]])], - [AC_MSG_RESULT(yes); LP64_DEFINED=yes], - [AC_MSG_RESULT(no)]) - if [[ "x$LP64_DEFINED" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm ../pict.c" - else - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx.cpp" - fi - EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/utils_macosx.mm" - CPPFLAGS="$CPPFLAGS -I../MacOSX" - else - EXTRASYSSRCS="$EXTRASYSSRCS ../dummy/clip_dummy.cpp" - fi -else - VIDEOSRCS="video_x.cpp" - KEYCODES="keycodes" - EXTRASYSSRCS="$EXTRASYSSRCS clip_unix.cpp" -fi -if [[ "x$WANT_SDL_AUDIO" = "xyes" ]]; then - AC_DEFINE(USE_SDL_AUDIO, 1, [Define to enable SDL audio support]) - AUDIOSRC="../SDL/audio_sdl.cpp" -fi - -dnl BINCUE overrides - -if [[ "x$have_bincue" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS bincue_unix.cpp" -fi - -dnl libvhd overrides - -if [[ "x$have_libvhd" = "xyes" ]]; then - EXTRASYSSRCS="$EXTRASYSSRCS vhd_unix.cpp" -fi - - -SYSSRCS="$VIDEOSRCS $EXTFSSRC $PREFSSRC $SERIALSRC $ETHERSRC $SCSISRC $AUDIOSRC $SEMSRC $UISRCS $EXTRASYSSRCS" - -dnl Define a macro that translates a yesno-variable into a C macro definition -dnl to be put into the config.h file -dnl $1 -- the macro to define -dnl $2 -- the value to translate -dnl $3 -- template name -AC_DEFUN([AC_TRANSLATE_DEFINE], [ - if [[ "x$2" = "xyes" -o "x$2" = "xguessing yes" ]]; then - AC_DEFINE($1, 1, $3) - fi -]) - -dnl Check that the host supports TUN/TAP devices -AC_CACHE_CHECK([whether TUN/TAP is supported], - ac_cv_tun_tap_support, [ - AC_TRY_COMPILE([ - #if defined(HAVE_NETINET_IN_H) - #include - #endif - #if defined(HAVE_LINUX_IF_H) && defined(HAVE_LINUX_IF_TUN_H) - #include - #include - #endif - #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_IF_TUN_H) - #include - #include - #endif - ], [ - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - ], - ac_cv_tun_tap_support=yes, ac_cv_tun_tap_support=no - ) -]) -AC_TRANSLATE_DEFINE(ENABLE_TUNTAP, "$ac_cv_tun_tap_support", - [Define if your system supports TUN/TAP devices.]) - -dnl Various checks if the system supports vm_allocate() and the like functions. -have_mach_vm=no -if [[ "x$ac_cv_func_vm_allocate" = "xyes" -a "x$ac_cv_func_vm_deallocate" = "xyes" -a \ - "x$ac_cv_func_vm_protect" = "xyes" ]]; then - have_mach_vm=yes -fi -AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm", - [Define if your system has a working vm_allocate()-based memory allocator.]) - -dnl Check that vm_allocate(), vm_protect() work -if [[ "x$have_mach_vm" = "xyes" ]]; then - -AC_CACHE_CHECK([whether vm_protect works], - ac_cv_vm_protect_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_cv_vm_protect_works=yes - dnl First the tests that should segfault - for test_def in NONE_READ NONE_WRITE READ_WRITE; do - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_$test_def - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_vm_protect_works=no, rm -f core, - dnl When cross-compiling, do not assume anything - ac_cv_vm_protect_works="guessing no" - ) - done - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_RDWR_WRITE - #include "../CrossPlatform/vm_alloc.cpp" - ], , ac_cv_vm_protect_works=no, - dnl When cross-compiling, do not assume anything - ac_cv_vm_protect_works="guessing no" - ) - AC_LANG_RESTORE - ] -) - -dnl Remove support for vm_allocate() if vm_protect() does not work -if [[ "x$have_mach_vm" = "xyes" ]]; then - case $ac_cv_vm_protect_works in - *yes) have_mach_vm=yes;; - *no) have_mach_vm=no;; - esac -fi -AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm", - [Define if your system has a working vm_allocate()-based memory allocator.]) - -fi dnl HAVE_MACH_VM - -dnl Various checks if the system supports mmap() and the like functions. -dnl ... and Mach memory allocators are not supported -have_mmap_vm=no -if [[ "x$ac_cv_func_mmap" = "xyes" -a "x$ac_cv_func_munmap" = "xyes" -a \ - "x$ac_cv_func_mprotect" = "xyes" ]]; then - if [[ "x$have_mach_vm" = "xno" ]]; then - have_mmap_vm=yes - fi -fi -AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, "$have_mmap_vm", - [Define if your system has a working mmap()-based memory allocator.]) - -dnl Check that mmap() and associated functions work. -if [[ "x$have_mmap_vm" = "xyes" ]]; then - -dnl Check if we have a working anonymous mmap() -AC_CACHE_CHECK([whether mmap supports MAP_ANON], - ac_cv_mmap_anon, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_MMAP_ANON - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_MMAP_ANON - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_mmap_anon=yes, ac_cv_mmap_anon=no, - dnl When cross-compiling, do not assume anything. - ac_cv_mmap_anon="guessing no" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_MMAP_ANON, "$ac_cv_mmap_anon", - [Define if defines MAP_ANON and mmap()'ing with MAP_ANON works.]) - -AC_CACHE_CHECK([whether mmap supports MAP_ANONYMOUS], - ac_cv_mmap_anonymous, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_MMAP_ANONYMOUS - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_MMAP_ANON - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_mmap_anonymous=yes, ac_cv_mmap_anonymous=no, - dnl When cross-compiling, do not assume anything. - ac_cv_mmap_anonymous="guessing no" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_MMAP_ANONYMOUS, "$ac_cv_mmap_anonymous", - [Define if defines MAP_ANONYMOUS and mmap()'ing with MAP_ANONYMOUS works.]) - -AC_CACHE_CHECK([whether mprotect works], - ac_cv_mprotect_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_cv_mprotect_works=yes - dnl First the tests that should segfault - for test_def in NONE_READ NONE_WRITE READ_WRITE; do - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_$test_def - #include "../CrossPlatform/vm_alloc.cpp" - ], ac_cv_mprotect_works=no, rm -f core, - dnl When cross-compiling, do not assume anything - ac_cv_mprotect_works="guessing no" - ) - done - AC_TRY_RUN([ - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_RDWR_WRITE - #include "../CrossPlatform/vm_alloc.cpp" - ], , ac_cv_mprotect_works=no, - dnl When cross-compiling, do not assume anything - ac_cv_mprotect_works="guessing no" - ) - AC_LANG_RESTORE - ] -) - -dnl Remove support for mmap() if mprotect() does not work -if [[ "x$have_mmap_vm" = "xyes" ]]; then - case $ac_cv_mprotect_works in - *yes) have_mmap_vm=yes;; - *no) have_mmap_vm=no;; - esac -fi -AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, $have_mmap_vm, - [Define if your system has a working mmap()-based memory allocator.]) - -fi dnl HAVE_MMAP_VM - -dnl Check if we can disable position-independent code -AC_CACHE_CHECK([how to disable position-independent code], - ac_cv_no_pie, [ - ac_cv_no_pie='-Wl,-no_pie' - saved_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $ac_cv_no_pie" - AC_TRY_LINK(,,,[ac_cv_no_pie="cannot"]) - if [[ "$ac_cv_no_pie" = "cannot" ]]; then - LDFLAGS="$saved_LDFLAGS" - fi -]) - -dnl Check if we can modify the __PAGEZERO segment for use as Low Memory -AC_CACHE_CHECK([whether __PAGEZERO can be Low Memory area 0x0000-0x3000], - ac_cv_pagezero_hack, [ - ac_cv_pagezero_hack=no - if AC_TRY_COMMAND([Darwin/testlmem.sh 0x3000]); then - ac_cv_pagezero_hack=yes - dnl might as well skip the test for mmap-able low memory - ac_cv_can_map_lm=no - fi -]) -AC_TRANSLATE_DEFINE(PAGEZERO_HACK, "$ac_cv_pagezero_hack", - [Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this system.]) - -dnl Check if we can mmap 0x3000 bytes from 0x0000 -AC_CACHE_CHECK([whether we can map Low Memory area 0x0000-0x3000], - ac_cv_can_map_lm, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #include "../CrossPlatform/vm_alloc.cpp" - int main(void) { /* returns 0 if we could map the lowmem globals */ - volatile char * lm = 0; - if (vm_init() < 0) exit(1); - if (vm_acquire_fixed(0, 0x2000) < 0) exit(1); - lm[0] = 'z'; - if (vm_release((char *)lm, 0x2000) < 0) exit(1); - vm_exit(); exit(0); - } - ], ac_cv_can_map_lm=yes, ac_cv_can_map_lm=no, - dnl When cross-compiling, do not assume anything. - ac_cv_can_map_lm="guessing no" - ) - AC_LANG_RESTORE - ] -) - -dnl Check signal handlers need to be reinstalled -AC_CACHE_CHECK([whether signal handlers need to be reinstalled], - ac_cv_signal_need_reinstall, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #include - #ifdef HAVE_UNISTD_H - #include - #endif - #include - static int handled_signal = 0; - RETSIGTYPE sigusr1_handler(int) { handled_signal++; } - int main(void) { /* returns 0 if signals need not to be reinstalled */ - signal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1); - exit(handled_signal == 2); - } - ], ac_cv_signal_need_reinstall=yes, ac_cv_signal_need_reinstall=no, - dnl When cross-compiling, do not assume anything. - ac_cv_signal_need_reinstall="guessing yes" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(SIGNAL_NEED_REINSTALL, "$ac_cv_signal_need_reinstall", - [Define if your system requires signals to be reinstalled.]) - -dnl Check if sigaction handlers need to be reinstalled -AC_CACHE_CHECK([whether sigaction handlers need to be reinstalled], - ac_cv_sigaction_need_reinstall, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #include - #ifdef HAVE_UNISTD_H - #include - #endif - #include - static int handled_signal = 0; - RETSIGTYPE sigusr1_handler(int) { handled_signal++; } - typedef RETSIGTYPE (*signal_handler)(int); - static signal_handler mysignal(int sig, signal_handler handler) { - struct sigaction old_sa; - struct sigaction new_sa; - new_sa.sa_handler = handler; - return ((sigaction(sig,&new_sa,&old_sa) < 0) ? SIG_IGN : old_sa.sa_handler); - } - int main(void) { /* returns 0 if signals need not to be reinstalled */ - mysignal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1); - exit(handled_signal == 2); - } - ], ac_cv_sigaction_need_reinstall=yes, ac_cv_sigaction_need_reinstall=no, - dnl When cross-compiling, do not assume anything. - ac_cv_sigaction_need_reinstall="guessing yes" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(SIGACTION_NEED_REINSTALL, "$ac_cv_sigaction_need_reinstall", - [Define if your system requires sigactions to be reinstalled.]) - -dnl Check if Mach exceptions supported. -AC_CACHE_CHECK([whether your system supports Mach exceptions], - ac_cv_have_mach_exceptions, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_MACH_EXCEPTIONS 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], - ac_cv_have_mach_exceptions=yes, - ac_cv_have_mach_exceptions=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_mach_exceptions=no - ) - AC_LANG_RESTORE - ] -) -if [[ "$ac_cv_have_mach_exceptions" = "yes" ]]; then - sigsegv_recovery=mach -fi -AC_TRANSLATE_DEFINE(HAVE_MACH_EXCEPTIONS, "$ac_cv_have_mach_exceptions", - [Define if your system supports Mach exceptions.]) - -dnl Check if Windows exceptions are supported. -AC_CACHE_CHECK([whether your system supports Windows exceptions], - ac_cv_have_win32_exceptions, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_WIN32_EXCEPTIONS 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], [ - sigsegv_recovery=win32 - ac_cv_have_win32_exceptions=yes - ], - ac_cv_have_win32_exceptions=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_win32_exceptions=no - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_WIN32_EXCEPTIONS, "$ac_cv_have_win32_exceptions", - [Define if your system supports Windows exceptions.]) - -dnl Otherwise, check if extended signals are supported. -if [[ -z "$sigsegv_recovery" ]]; then - AC_CACHE_CHECK([whether your system supports extended signal handlers], - ac_cv_have_extended_signals, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGINFO_T 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], - ac_cv_have_extended_signals=yes, - ac_cv_have_extended_signals=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_extended_signals=no - ) - AC_LANG_RESTORE - ] - ) - if [[ "$ac_cv_have_extended_signals" = "yes" ]]; then - sigsegv_recovery=siginfo - fi - AC_TRANSLATE_DEFINE(HAVE_SIGINFO_T, "$ac_cv_have_extended_signals", - [Define if your system support extended signals.]) -fi - -dnl Otherwise, check for subterfuges. -if [[ -z "$sigsegv_recovery" ]]; then - AC_CACHE_CHECK([whether we then have a subterfuge for your system], - ac_cv_have_sigcontext_hack, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGCONTEXT_SUBTERFUGE 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], - ac_cv_have_sigcontext_hack=yes, - ac_cv_have_sigcontext_hack=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_sigcontext_hack=no - ) - AC_LANG_RESTORE - ]) - if [[ "$ac_cv_have_sigcontext_hack" = "yes" ]]; then - sigsegv_recovery=sigcontext - fi - AC_TRANSLATE_DEFINE(HAVE_SIGCONTEXT_SUBTERFUGE, "$ac_cv_have_sigcontext_hack", - [Define if we know a hack to replace siginfo_t->si_addr member.]) -fi - -dnl Check if we can ignore the fault (instruction skipping in SIGSEGV handler) -AC_CACHE_CHECK([whether we can skip instruction in SIGSEGV handler], - ac_cv_have_skip_instruction, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../CrossPlatform/vm_alloc.cpp" - #include "../CrossPlatform/sigsegv.cpp" - ], ac_cv_have_skip_instruction=yes, ac_cv_have_skip_instruction=no, - dnl When cross-compiling, do not assume anything. - ac_cv_have_skip_instruction=no - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_SIGSEGV_SKIP_INSTRUCTION, "$ac_cv_have_skip_instruction", - [Define if we can ignore the fault (instruction skipping in SIGSEGV handler).]) - -dnl Can we do Video on SEGV Signals ? -CAN_VOSF=no -if [[ -n "$sigsegv_recovery" ]]; then - CAN_VOSF=yes -fi - -dnl Enable VOSF screen updates with this feature is requested and feasible -if [[ "x$WANT_VOSF" = "xyes" -a "x$CAN_VOSF" = "xyes" ]]; then - AC_DEFINE(ENABLE_VOSF, 1, [Define if using video enabled on SEGV signals.]) -else - WANT_VOSF=no -fi - -dnl Check addressing mode to use -AC_MSG_CHECKING([for addressing mode to use]) -if [[ "$EMULATED_PPC" != "yes" ]]; then - if [[ "$WANT_ADDRESSING_MODE" != "real" ]]; then - AC_MSG_WARN([Running in native PowerPC mode, force use of Real Addressing.]) - WANT_ADDRESSING_MODE="real" - fi -fi -if [[ "$WANT_ADDRESSING_MODE" = "direct" ]]; then - if [[ -n "$NATMEM_OFFSET" ]]; then - NATMEM_OFFSET_DEF="-DNATMEM_OFFSET=$NATMEM_OFFSET" - fi - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - cat confdefs.h > conftest.$ac_ext - cat >> conftest.$ac_ext << EOF -#include -#include -#include "../CrossPlatform/vm_alloc.cpp" - -int main(void) -{ - if (vm_init() < 0) - return 1; - - static const struct { - unsigned long base; - unsigned int size; - } ranges[[]] = { - { 0x00000000, 0x0003000 }, - { 0x10000000, 0x2000000 }, - { 0x40800000, 0x0400000 }, - { 0x68070000, 0x0010000 }, - { 0x69000000, 0x0080000 }, - { 0x68ffe000, 0x0002000 }, - { 0x5fffe000, 0x0002000 }, - { 0x60000000, 0x0040000 }, - }; - const int n_ranges = sizeof(ranges)/ sizeof(ranges[[0]]); - -#ifdef NATMEM_OFFSET - unsigned long ofs = NATMEM_OFFSET; -#else - for (unsigned long ofs = 0x10000000; ofs <= 0x90000000; ofs += 0x10000000) -#endif - for (int i = 0; i < n_ranges; i++) { - char *m = (char *)(ranges[[i]].base + ofs); - if (vm_acquire_fixed(m, ranges[[i]].size) != 0) - break; - memset(m, 0, ranges[[i]].size); - vm_release(m, ranges[[i]].size); - if (i == n_ranges - 1) { - if (sizeof(void *) == 8 && ofs > 0xffffffff) - printf("0x%lxul\n", ofs); - else - printf("0x%08x\n", ofs); - return 0; - } - } - - vm_exit(); - return 1; -} -EOF - doit='$CXX conftest.$ac_ext -o conftest.$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS $LIBS $NATMEM_OFFSET_DEF >& AS_MESSAGE_LOG_FD' - if AC_TRY_EVAL(doit); then - NATMEM_OFFSET=`./conftest.$ac_exeext` - else - NATMEM_OFFSET= - fi - rm -f conftest* - AC_LANG_RESTORE - - if [[ -z "$NATMEM_OFFSET" ]]; then - AC_MSG_ERROR([could not determine a sensible NATMEM_OFFSET value]) - else - WANT_ADDRESSING_MODE="direct,$NATMEM_OFFSET" - AC_DEFINE_UNQUOTED(NATMEM_OFFSET, $NATMEM_OFFSET, - [Define constant offset for Mac address translation]) - fi -fi -AC_MSG_RESULT($WANT_ADDRESSING_MODE) - -dnl Utility macro used by next two tests. -dnl AC_EXAMINE_OBJECT(C source code, -dnl commands examining object file, -dnl [commands to run if compile failed]): -dnl -dnl Compile the source code to an object file; then convert it into a -dnl printable representation. All unprintable characters and -dnl asterisks (*) are replaced by dots (.). All white space is -dnl deleted. Newlines (ASCII 0x10) in the input are preserved in the -dnl output, but runs of newlines are compressed to a single newline. -dnl Finally, line breaks are forcibly inserted so that no line is -dnl longer than 80 columns and the file ends with a newline. The -dnl result of all this processing is in the file conftest.dmp, which -dnl may be examined by the commands in the second argument. -dnl -AC_DEFUN([gcc_AC_EXAMINE_OBJECT], -[AC_LANG_SAVE -AC_LANG_C -dnl Next bit cribbed from AC_TRY_COMPILE. -cat > conftest.$ac_ext < conftest.dmp - $2 -ifelse($3, , , else - $3 -)dnl -fi -rm -rf conftest* -AC_LANG_RESTORE]) - -dnl Floating point format probe. -dnl The basic concept is the same as the above: grep the object -dnl file for an interesting string. We have to watch out for -dnl rounding changing the values in the object, however; this is -dnl handled by ignoring the least significant byte of the float. -dnl -dnl Does not know about VAX G-float or C4x idiosyncratic format. -dnl It does know about PDP-10 idiosyncratic format, but this is -dnl not presently supported by GCC. S/390 "binary floating point" -dnl is in fact IEEE (but maybe we should have that in EBCDIC as well -dnl as ASCII?) -dnl -AC_DEFUN([gcc_AC_C_FLOAT_FORMAT], -[AC_CACHE_CHECK(floating point format, ac_cv_c_float_format, -[gcc_AC_EXAMINE_OBJECT( -[/* This will not work unless sizeof(double) == 8. */ -extern char sizeof_double_must_be_8 [sizeof(double) == 8 ? 1 : -1]; - -/* This structure must have no internal padding. */ -struct possibility { - char prefix[8]; - double candidate; - char postfix[8]; -}; - -#define C(cand) { "\nformat:", cand, ":tamrof\n" } -struct possibility table [] = -{ - C( 3.25724264705901305206e+01), /* @@IEEEFP - IEEE 754 */ - C( 3.53802595280598432000e+18), /* D__float - VAX */ - C( 5.32201830133125317057e-19), /* D.PDP-10 - PDP-10 - the dot is 0x13a */ - C( 1.77977764695171661377e+10), /* IBMHEXFP - s/390 format, ascii */ - C(-5.22995989424860458374e+10) /* IBMHEXFP - s/390 format, EBCDIC */ -};], - [if grep 'format:.@IEEEF.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (big-endian)' - elif grep 'format:.I@@PFE.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (big-endian)' - elif grep 'format:.FEEEI@.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (little-endian)' - elif grep 'format:.EFP@@I.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IEEE (little-endian)' - elif grep 'format:.__floa.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='VAX D-float' - elif grep 'format:..PDP-1.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='PDP-10' - elif grep 'format:.BMHEXF.:tamrof' conftest.dmp >/dev/null 2>&1; then - ac_cv_c_float_format='IBM 370 hex' - else - AC_MSG_ERROR(Unknown floating point format) - fi], - [AC_MSG_ERROR(compile failed)]) -]) -# IEEE is the default format. If the float endianness isn't the same -# as the integer endianness, we have to set FLOAT_WORDS_BIG_ENDIAN -# (which is a tristate: yes, no, default). This is only an issue with -# IEEE; the other formats are only supported by a few machines each, -# all with the same endianness. -format=IEEE_FLOAT_FORMAT -fbigend= -case $ac_cv_c_float_format in - 'IEEE (big-endian)' ) - if test $ac_cv_c_bigendian = no; then - fbigend=1 - fi - ;; - 'IEEE (little-endian)' ) - if test $ac_cv_c_bigendian = yes; then - fbigend=0 - fi - ;; - 'VAX D-float' ) - format=VAX_FLOAT_FORMAT - ;; - 'PDP-10' ) - format=PDP10_FLOAT_FORMAT - ;; - 'IBM 370 hex' ) - format=IBM_FLOAT_FORMAT - ;; -esac -AC_DEFINE_UNQUOTED(HOST_FLOAT_FORMAT, $format, - [Define to the floating point format of the host machine.]) -if test -n "$fbigend"; then - AC_DEFINE_UNQUOTED(HOST_FLOAT_WORDS_BIG_ENDIAN, $fbigend, - [Define to 1 if the host machine stores floating point numbers in - memory with the word containing the sign bit at the lowest address, - or to 0 if it does it the other way around. - - This macro should not be defined if the ordering is the same as for - multi-word integers.]) -fi -]) - -dnl Check for host float format -gcc_AC_C_FLOAT_FORMAT - -dnl Platform specific binary postprocessor -AC_PATH_PROG(BLESS, "true") -if [[ "x$ac_cv_pagezero_hack" = "xyes" ]]; then - BLESS=Darwin/lowmem - LDFLAGS="$LDFLAGS -pagezero_size 0x3000" -fi - -dnl Check for GCC 2.7 or higher. -HAVE_GCC27=no -AC_MSG_CHECKING(for GCC 2.7 or higher) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if ! (__GNUC__ - 1 > 1 || __GNUC_MINOR__ - 1 > 5) - # error gcc < 2.7 - typedef syntax error; - #endif - ]])], - [AC_MSG_RESULT(yes); HAVE_GCC27=yes], - [AC_MSG_RESULT(no)]) - -dnl Check for GCC 3.0 or higher. -HAVE_GCC30=no -AC_MSG_CHECKING(for GCC 3.0 or higher) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#if ! (__GNUC__ >= 3) - # error gcc < 3 - typedef syntax error; - #endif - ]])], - [AC_MSG_RESULT(yes); HAVE_GCC30=yes], - [AC_MSG_RESULT(no)]) - -dnl Check for ICC. -AC_MSG_CHECKING(for ICC) -HAVE_ICC=no -if $CXX -V -v 2>&1 | grep -q "Intel(R) C++ Compiler"; then - HAVE_ICC=yes -fi -AC_MSG_RESULT($HAVE_ICC) - -dnl Determine the generated object format -AC_CACHE_CHECK([the format of compiler generated objects], - ac_cv_object_format, [ - echo 'int i;' > conftest.$ac_ext - ac_cv_object_format=no - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *"ELF"*) - ac_cv_object_format=elf - ;; - *"Mach-O"*) - ac_cv_object_format=mach - ;; - *) - ac_cv_object_format=unknown - ;; - esac - fi - rm -rf conftest* -]) - -dnl Add -fno-strict-aliasing for slirp sources -if [[ "x$HAVE_GCC30" = "xyes" ]]; then - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-strict-aliasing" - AC_CACHE_CHECK([whether the compiler supports -fno-strict-aliasing], - ac_cv_gcc_no_strict_aliasing, [ - AC_TRY_COMPILE([],[],[ac_cv_gcc_no_strict_aliasing=yes],[ac_cv_gcc_no_strict_aliasing=no]) - ]) - if [[ "x$ac_cv_gcc_no_strict_aliasing" = "xyes" ]]; then - AC_SUBST(SLIRP_CFLAGS, "-fno-strict-aliasing") - fi - CFLAGS="$SAVED_CFLAGS" -fi - -dnl Add -mdynamic-no-pic for MacOS X (XXX icc10 will support MacOS X) -if [[ "x$HAVE_GCC30" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -mdynamic-no-pic" - AC_CACHE_CHECK([whether the compiler supports -mdynamic-no-pic], - ac_cv_gcc_mdynamic_no_pic, [ - AC_TRY_COMPILE([],[],[ac_cv_gcc_mdynamic_no_pic=yes],[ac_cv_gcc_mdynamic_no_pic=no]) - ]) - if [[ "x$ac_cv_gcc_mdynamic_no_pic" = "xyes" ]]; then - CXXFLAGS="$CXXFLAGS -mdynamic-no-pic" - else - CFLAGS="$SAVED_CFLAGS" - fi -fi - -dnl CPU emulator sources -if [[ "x$EMULATED_PPC" = "xyes" ]]; then - CPUSRCS="\ - ../kpx_cpu/src/mathlib/ieeefp.cpp \ - ../kpx_cpu/src/mathlib/mathlib.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-cpu.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-decode.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-execute.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-translate.cpp \ - ../kpx_cpu/src/utils/utils-cpuinfo.cpp" - CPPFLAGS="$CPPFLAGS -I../kpx_cpu/include -I../kpx_cpu/src" - - dnl Enable JIT compiler, if possible - if [[ "x$WANT_JIT" = "xyes" ]]; then - AC_CACHE_CHECK([whether dyngen can be used], - ac_cv_use_dyngen, [ - case $host_cpu:$ac_cv_object_format in - powerpc:elf) - ac_cv_use_dyngen=yes - ;; - x86_64:elf) - ac_cv_use_dyngen=yes - ;; - i?86:elf) - ac_cv_use_dyngen=yes - ;; - mips:elf) - ac_cv_use_dyngen=yes - ;; - powerpc:mach) - ac_cv_use_dyngen=yes - ;; - x86_64:mach) - ac_cv_use_dyngen=yes - ;; - i?86:mach) - ac_cv_use_dyngen=yes - ;; - *:*) - ac_cv_use_dyngen=no - ;; - esac - dnl Check for a suitable synthetic opcodes compiler (icc is faking itself as gcc 3.2.2) - if [[ -z "$DYNGEN_CC" ]]; then - if [[ "x$HAVE_GCC27" = "xyes" -a "x$HAVE_ICC" = "xno" ]]; then - DYNGEN_CC=$CXX - else - for p in /usr/bin /usr/local/bin /usr/freeware/bin; do - gxx="$p/g++" - if [[ -x "$gxx" ]]; then - DYNGEN_CC="$gxx" - fi - done - fi - fi - if [[ -z "$DYNGEN_CC" ]]; then - ac_cv_use_dyngen=no - fi - ]) - if [[ "x$ac_cv_use_dyngen" = "xyes" ]]; then - case $host_cpu in - i?86) - DYNGEN_OP_FLAGS="-fomit-frame-pointer" - ;; - mips) - DYNGEN_OP_FLAGS="-fno-delayed-branch -mno-abicalls" - ;; - powerpc) - if [[ "x$ac_cv_object_format" = "xmach" ]]; then - DYNGEN_OP_FLAGS="-mdynamic-no-pic" - fi - ;; - esac - have_dyngen_gcc3=no - case "x`$DYNGEN_CC -dumpversion`" in - x[12].*) ;; - x*) have_dyngen_gcc3=yes ;; - esac - if [[ "x$have_dyngen_gcc3" = "xyes" ]]; then - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -fno-align-functions" - else - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -malign-functions=0" - fi - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -finline-functions -finline-limit=10000 -fno-exceptions -g0" - if [[ "x$have_dyngen_gcc3" = "xyes" ]]; then - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -fno-reorder-blocks -fno-optimize-sibling-calls" - fi - if [[ "x$DYNGEN_CC" != "x$CXX" ]]; then - DYNGEN_CFLAGS="-O2 $CFLAGS" - DYNGEN_CXXFLAGS="-O2 $CXXFLAGS" - else - DYNGEN_CFLAGS="\$(CFLAGS)" - DYNGEN_CXXFLAGS="\$(CXXFLAGS)" - fi - else - WANT_JIT=no - fi - AC_TRANSLATE_DEFINE(ENABLE_DYNGEN, $ac_cv_use_dyngen, [Define to enable dyngen engine]) - if [[ "x$WANT_JIT" = "xyes" ]]; then - DYNGENSRCS="\ - ../kpx_cpu/src/cpu/jit/dyngen.c \ - ../kpx_cpu/src/cpu/jit/cxxdemangle.cpp" - CPUSRCS="\ - ../kpx_cpu/src/cpu/jit/jit-cache.cpp \ - ../kpx_cpu/src/cpu/jit/basic-dyngen.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-jit.cpp $CPUSRCS" - fi - fi - CPUSRCS="$CPUSRCS ../kpx_cpu/sheepshaver_glue.cpp ../kpx_cpu/ppc-dis.c" -else - WANT_JIT=no -fi -if [[ "x$WANT_JIT" = "xyes" ]]; then - CPPFLAGS="$CPPFLAGS -DUSE_JIT" -fi - -dnl Higher level optimizations with MIPSPro compilers are possible -if [[ "x$HAVE_IPA" = "xyes" ]]; then - CFLAGS="`echo $CFLAGS | sed -e 's/-g//g'` -O3 -OPT:Olimit=0 -IPA" - CXXFLAGS="`echo $CXXFLAGS | sed -e 's/-g//g'` -O3 -OPT:Olimit=0 -IPA" - CXXFLAGS="-LANG:std $CXXFLAGS" - LDFLAGS="$LDFLAGS -O3 -OPT:Olimit=0 -IPA" -fi - -dnl Check for linker script support -case $target_os:$target_cpu in -linux*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-i386.ld";; -linux*:x86_64) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-x86_64.ld";; -linux*:powerpc) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-ppc.ld";; -netbsd*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/linux-i386.ld";; -freebsd*:i?86) LINKER_SCRIPT_FLAGS="-Wl,-T,ldscripts/freebsd-i386.ld";; -darwin*:*) LINKER_SCRIPT_FLAGS="-Wl,-seg1addr,0x78048000";; -esac -if [[ -n "$LINKER_SCRIPT_FLAGS" ]]; then - AC_CACHE_CHECK([whether linker script is usable], - ac_cv_linker_script_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - saved_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $LINKER_SCRIPT_FLAGS" - AC_TRY_RUN( - [int main() {if ((char *)&main < (char *)0x70000000) return 1;}], - [ac_cv_linker_script_works=yes], - [ac_cv_linker_script_works=no], - dnl When cross-compiling, assume it works - [ac_cv_linker_script_works="guessing yes"] - ) - AC_LANG_RESTORE - if [[ "$ac_cv_linker_script_works" = "no" ]]; then - LDFLAGS="$saved_LDFLAGS" - LINKER_SCRIPT_FLAGS="" - fi - ]) -fi -AC_TRANSLATE_DEFINE(HAVE_LINKER_SCRIPT, "$ac_cv_linker_script_works", - [Define if there is a linker script to relocate the executable above 0x70000000.]) - -dnl Generate Makefile. -AC_SUBST(PERL) -AC_SUBST(USE_DYNGEN, [$ac_cv_use_dyngen]) -AC_SUBST(DYNGENSRCS) -AC_SUBST(DYNGEN_CC) -AC_SUBST(DYNGEN_CFLAGS) -AC_SUBST(DYNGEN_CXXFLAGS) -AC_SUBST(DYNGEN_OP_FLAGS) -AC_SUBST(SYSSRCS) -AC_SUBST(CPUSRCS) -AC_SUBST(BLESS) -AC_SUBST(KEYCODES) -AC_OUTPUT([ -Makefile -../MacOSX/Info.plist -]) - -dnl Print summary. -echo -echo SheepShaver configuration summary: -echo -echo SDL support ...................... : $SDL_SUPPORT -echo BINCUE support ................... : $have_bincue -echo LIBVHD support ................... : $have_libvhd -echo FBDev DGA support ................ : $WANT_FBDEV_DGA -echo XFree86 DGA support .............. : $WANT_XF86_DGA -echo XFree86 VidMode support .......... : $WANT_XF86_VIDMODE -echo Using PowerPC emulator ........... : $EMULATED_PPC -echo Enable JIT compiler .............. : $WANT_JIT -echo Enable video on SEGV signals ..... : $WANT_VOSF -echo ESD sound support ................ : $WANT_ESD -echo GTK user interface ............... : $WANT_GTK -echo mon debugger support ............. : $WANT_MON -echo Addressing mode .................. : $WANT_ADDRESSING_MODE -echo Bad memory access recovery type .. : $sigsegv_recovery -echo -echo "Configuration done. Now type \"make\"." diff --git a/SheepShaver/src/Unix/cpr.sh b/SheepShaver/src/Unix/cpr.sh deleted file mode 120000 index 29f13000..00000000 --- a/SheepShaver/src/Unix/cpr.sh +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/cpr.sh \ No newline at end of file diff --git a/SheepShaver/src/Unix/disk_sparsebundle.cpp b/SheepShaver/src/Unix/disk_sparsebundle.cpp deleted file mode 120000 index 7e368ca7..00000000 --- a/SheepShaver/src/Unix/disk_sparsebundle.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/disk_sparsebundle.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/disk_unix.h b/SheepShaver/src/Unix/disk_unix.h deleted file mode 120000 index 87d10dfd..00000000 --- a/SheepShaver/src/Unix/disk_unix.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/disk_unix.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/ether_unix.cpp b/SheepShaver/src/Unix/ether_unix.cpp deleted file mode 120000 index b2a75d72..00000000 --- a/SheepShaver/src/Unix/ether_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/ether_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/extfs_unix.cpp b/SheepShaver/src/Unix/extfs_unix.cpp deleted file mode 120000 index 6a67ad61..00000000 --- a/SheepShaver/src/Unix/extfs_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/extfs_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/install-sh b/SheepShaver/src/Unix/install-sh deleted file mode 100755 index 89fc9b09..00000000 --- a/SheepShaver/src/Unix/install-sh +++ /dev/null @@ -1,238 +0,0 @@ -#! /bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. -# - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -tranformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/SheepShaver/src/Unix/keycodes b/SheepShaver/src/Unix/keycodes deleted file mode 120000 index da89edcf..00000000 --- a/SheepShaver/src/Unix/keycodes +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/keycodes \ No newline at end of file diff --git a/SheepShaver/src/Unix/ldscripts b/SheepShaver/src/Unix/ldscripts deleted file mode 120000 index 39626083..00000000 --- a/SheepShaver/src/Unix/ldscripts +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/ldscripts \ No newline at end of file diff --git a/SheepShaver/src/Unix/m4 b/SheepShaver/src/Unix/m4 deleted file mode 120000 index a20fe840..00000000 --- a/SheepShaver/src/Unix/m4 +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/m4 \ No newline at end of file diff --git a/SheepShaver/src/Unix/main_unix.cpp b/SheepShaver/src/Unix/main_unix.cpp deleted file mode 100644 index 3d0ee43e..00000000 --- a/SheepShaver/src/Unix/main_unix.cpp +++ /dev/null @@ -1,2292 +0,0 @@ -/* - * main_unix.cpp - Emulation core, Unix implementation - * - * SheepShaver (C) Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - * See main_beos.cpp for a description of the three operating modes. - * - * In addition to that, we have to handle the fact that the MacOS ABI - * is slightly different from the SysV ABI used by Linux: - * - Stack frames are different (e.g. LR is stored in 8(r1) under - * MacOS, but in 4(r1) under Linux) - * - There is a pointer to Thread Local Storage (TLS) under Linux with - * recent enough glibc. This is r2 in 32-bit mode and r13 in - * 64-bit mode (PowerOpen/AIX ABI) - * - r13 is used as a small data pointer under Linux (but appearently - * it is not used this way? To be sure, we specify -msdata=none - * in the Makefile) - * - There are no TVECTs under Linux; function pointers point - * directly to the function code - * The Execute*() functions have to account for this. Additionally, we - * cannot simply call MacOS functions by getting their TVECT and jumping - * to it. Such calls are done via the call_macos*() functions in - * asm_linux.S that create a MacOS stack frame, load the TOC pointer - * and put the arguments into the right registers. - * - * As on the BeOS, we have to specify an alternate signal stack because - * interrupts (and, under Linux, Low Memory accesses) may occur when r1 - * is pointing to the Kernel Data or to Low Memory. There is one - * problem, however, due to the alternate signal stack being global to - * all signal handlers. Consider the following scenario: - * - The main thread is executing some native PPC MacOS code in - * MODE_NATIVE, running on the MacOS stack (somewhere in the Mac RAM). - * - A SIGUSR2 interrupt occurs. The kernel switches to the signal - * stack and starts executing the SIGUSR2 signal handler. - * - The signal handler sees the MODE_NATIVE and calls ppc_interrupt() - * to handle a native interrupt. - * - ppc_interrupt() sets r1 to point to the Kernel Data and jumps to - * the nanokernel. - * - The nanokernel accesses a Low Memory global (most likely one of - * the XLMs), a SIGSEGV occurs. - * - The kernel sees that r1 does not point to the signal stack and - * switches to the signal stack again, thus overwriting the data that - * the SIGUSR2 handler put there. - * The same problem arises when calling ExecutePPC() inside the MODE_EMUL_OP - * interrupt handler. - * - * The solution is to set the signal stack to a second, "extra" stack - * inside the SIGUSR2 handler before entering the Nanokernel or calling - * ExecutePPC (or any function that might cause a mode switch). The signal - * stack is restored before exiting the SIGUSR2 handler. - * - * Note that POSIX standard says you can't modify the alternate - * signal stack while the process is executing on it. There is a - * hackaround though: we install a trampoline SIGUSR2 handler that - * sets up an alternate stack itself and calls the real handler. - * Then, when we call sigaltstack() there, we no longer get an EPERM, - * i.e. it now works. - * - * TODO: - * check if SIGSEGV handler works for all registers (including FP!) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "main.h" -#include "version.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "xlowmem.h" -#include "xpram.h" -#include "timer.h" -#include "adb.h" -#include "video.h" -#include "sys.h" -#include "macos_util.h" -#include "rom_patches.h" -#include "user_strings.h" -#include "vm_alloc.h" -#include "sigsegv.h" -#include "sigregs.h" -#include "rpc.h" - -#define DEBUG 0 -#include "debug.h" - - -#ifdef HAVE_DIRENT_H -#include -#endif - -#ifdef USE_SDL -#include -#endif - -#ifndef USE_SDL_VIDEO -#include -#endif - -#ifdef ENABLE_GTK -#include -#endif - -#ifdef ENABLE_XF86_DGA -#include -#include -#include -#endif - -#ifdef ENABLE_MON -#include "mon.h" -#endif - - -// Enable emulation of unaligned lmw/stmw? -#define EMULATE_UNALIGNED_LOADSTORE_MULTIPLE 1 - -// Enable Execute68k() safety checks? -#define SAFE_EXEC_68K 0 - -// Interrupts in EMUL_OP mode? -#define INTERRUPTS_IN_EMUL_OP_MODE 1 - -// Interrupts in native mode? -#define INTERRUPTS_IN_NATIVE_MODE 1 - - -// Constants -const char ROM_FILE_NAME[] = "ROM"; -const char ROM_FILE_NAME2[] = "Mac OS ROM"; - -#if !REAL_ADDRESSING -// FIXME: needs to be >= 0x04000000 -const uintptr RAM_BASE = 0x10000000; // Base address of RAM -#endif -const uintptr ROM_BASE = 0x40800000; // Base address of ROM -#if REAL_ADDRESSING -const uint32 ROM_ALIGNMENT = 0x100000; // ROM must be aligned to a 1MB boundary -#endif -const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack - - -// Global variables (exported) -#if !EMULATED_PPC -void *TOC = NULL; // Pointer to Thread Local Storage (r2) -void *R13 = NULL; // Pointer to .sdata section (r13 under Linux) -#endif -uint32 RAMBase; // Base address of Mac RAM -uint32 RAMSize; // Size of Mac RAM -uint32 ROMBase; // Base address of Mac ROM -uint32 KernelDataAddr; // Address of Kernel Data -uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM -uint32 DRCacheAddr; // Address of DR Cache -uint32 PVR; // Theoretical PVR -int64 CPUClockSpeed; // Processor clock speed (Hz) -int64 BusClockSpeed; // Bus clock speed (Hz) -int64 TimebaseSpeed; // Timebase clock speed (Hz) -uint8 *RAMBaseHost; // Base address of Mac RAM (host address space) -uint8 *ROMBaseHost; // Base address of Mac ROM (host address space) - - -// Global variables -#ifndef USE_SDL_VIDEO -char *x_display_name = NULL; // X11 display name -Display *x_display = NULL; // X11 display handle -#ifdef X11_LOCK_TYPE -X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock -#endif -#endif - -static int zero_fd = 0; // FD of /dev/zero -static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped -static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped -static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped -static bool dr_cache_area_mapped = false; // Flag: Mac DR Cache mmap()ped -static bool dr_emulator_area_mapped = false;// Flag: Mac DR Emulator mmap()ped -static KernelData *kernel_data; // Pointer to Kernel Data -static EmulatorData *emulator_data; - -static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes - -static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed -static volatile bool nvram_thread_cancel; // Flag: Cancel NVRAM thread -static pthread_t nvram_thread; // NVRAM watchdog -static bool tick_thread_active = false; // Flag: MacOS thread installed -static volatile bool tick_thread_cancel; // Flag: Cancel 60Hz thread -static pthread_t tick_thread; // 60Hz thread -static pthread_t emul_thread; // MacOS thread - -static bool ready_for_signals = false; // Handler installed, signals can be sent - -#if EMULATED_PPC -static uintptr sig_stack = 0; // Stack for PowerPC interrupt routine -#else -static struct sigaction sigusr2_action; // Interrupt signal (of emulator thread) -static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) -static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread) -static stack_t sig_stack; // Stack for signal handlers -static stack_t extra_stack; // Stack for SIGSEGV inside interrupt handler -static bool emul_thread_fatal = false; // Flag: MacOS thread crashed, tick thread shall dump debug output -static sigregs sigsegv_regs; // Register dump when crashed -static const char *crash_reason = NULL; // Reason of the crash (SIGSEGV, SIGBUS, SIGILL) -#endif - -static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI -static const char *gui_connection_path = NULL; // GUI connection identifier - -uint32 SheepMem::page_size; // Size of a native page -uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros -uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data -uintptr SheepMem::proc; // Bottom address of SheepShave procedures -uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) - - -// Prototypes -static bool kernel_data_init(void); -static bool shm_map_address(int kernel_area, uint32 addr); -static void Quit(void); -static void *emul_func(void *arg); -static void *nvram_func(void *arg); -static void *tick_func(void *arg); -#if EMULATED_PPC -extern void emul_ppc(uint32 start); -extern void init_emul_ppc(void); -extern void exit_emul_ppc(void); -sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip); -#else -extern "C" void sigusr2_handler_init(int sig, siginfo_t *sip, void *scp); -extern "C" void sigusr2_handler(int sig, siginfo_t *sip, void *scp); -static void sigsegv_handler(int sig, siginfo_t *sip, void *scp); -static void sigill_handler(int sig, siginfo_t *sip, void *scp); -#endif - - -// From asm_linux.S -#if !EMULATED_PPC -extern "C" void *get_sp(void); -extern "C" void *get_r2(void); -extern "C" void set_r2(void *); -extern "C" void *get_r13(void); -extern "C" void set_r13(void *); -extern "C" void flush_icache_range(uint32 start, uint32 end); -extern "C" void jump_to_rom(uint32 entry, uint32 context); -extern "C" void quit_emulator(void); -extern "C" void execute_68k(uint32 pc, M68kRegisters *r); -extern "C" void ppc_interrupt(uint32 entry, uint32 kernel_data); -extern "C" int atomic_add(int *var, int v); -extern "C" int atomic_and(int *var, int v); -extern "C" int atomic_or(int *var, int v); -extern void paranoia_check(void); -#endif - - -#if EMULATED_PPC -/* - * Return signal stack base - */ - -uintptr SignalStackBase(void) -{ - return sig_stack + SIG_STACK_SIZE; -} - - -/* - * Atomic operations - */ - -#if HAVE_SPINLOCKS -static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED; -#else -#define spin_lock(LOCK) -#define spin_unlock(LOCK) -#endif - -int atomic_add(int *var, int v) -{ - spin_lock(&atomic_ops_lock); - int ret = *var; - *var += v; - spin_unlock(&atomic_ops_lock); - return ret; -} - -int atomic_and(int *var, int v) -{ - spin_lock(&atomic_ops_lock); - int ret = *var; - *var &= v; - spin_unlock(&atomic_ops_lock); - return ret; -} - -int atomic_or(int *var, int v) -{ - spin_lock(&atomic_ops_lock); - int ret = *var; - *var |= v; - spin_unlock(&atomic_ops_lock); - return ret; -} -#endif - - -/* - * Memory management helpers - */ - -static inline uint8 *vm_mac_acquire(uint32 size) -{ - return (uint8 *)vm_acquire(size); -} - -static inline int vm_mac_acquire_fixed(uint32 addr, uint32 size) -{ - return vm_acquire_fixed(Mac2HostAddr(addr), size); -} - -static inline int vm_mac_release(uint32 addr, uint32 size) -{ - return vm_release(Mac2HostAddr(addr), size); -} - - -/* - * Main program - */ - -static void usage(const char *prg_name) -{ - printf("Usage: %s [OPTION...]\n", prg_name); - printf("\nUnix options:\n"); - printf(" --display STRING\n X display to use\n"); - PrefsPrintUsage(); - exit(0); -} - -static bool valid_vmdir(const char *path) -{ - const int suffix_len = sizeof(".sheepvm") - 1; - int len = strlen(path); - if (len && path[len - 1] == '/') // to support both ".sheepvm" and ".sheepvm/" - len--; - if (len > suffix_len && !strncmp(path + len - suffix_len, ".sheepvm", suffix_len)) { - struct stat d; - if (!stat(path, &d) && S_ISDIR(d.st_mode)) { - return true; - } - } - return false; -} - -static void get_system_info(void) -{ -#if !EMULATED_PPC - FILE *proc_file; -#endif - - PVR = 0x00040000; // Default: 604 - CPUClockSpeed = 100000000; // Default: 100MHz - BusClockSpeed = 100000000; // Default: 100MHz - TimebaseSpeed = 25000000; // Default: 25MHz - -#if EMULATED_PPC - PVR = 0x000c0000; // Default: 7400 (with AltiVec) -#elif defined(__APPLE__) && defined(__MACH__) - proc_file = popen("ioreg -c IOPlatformDevice", "r"); - if (proc_file) { - char line[256]; - bool powerpc_node = false; - while (fgets(line, sizeof(line) - 1, proc_file)) { - // Read line - int len = strlen(line); - if (len == 0) - continue; - line[len - 1] = 0; - - // Parse line - if (strstr(line, "o PowerPC,")) - powerpc_node = true; - else if (powerpc_node) { - uint32 value; - char head[256]; - if (sscanf(line, "%[ |]\"cpu-version\" = <%x>", head, &value) == 2) - PVR = value; - else if (sscanf(line, "%[ |]\"clock-frequency\" = <%x>", head, &value) == 2) - CPUClockSpeed = value; - else if (sscanf(line, "%[ |]\"bus-frequency\" = <%x>", head, &value) == 2) - BusClockSpeed = value; - else if (sscanf(line, "%[ |]\"timebase-frequency\" = <%x>", head, &value) == 2) - TimebaseSpeed = value; - else if (strchr(line, '}')) - powerpc_node = false; - } - } - fclose(proc_file); - } else { - char str[256]; - sprintf(str, GetString(STR_PROC_CPUINFO_WARN), strerror(errno)); - WarningAlert(str); - } -#else - proc_file = fopen("/proc/cpuinfo", "r"); - if (proc_file) { - // CPU specs from Linux kernel - // TODO: make it more generic with features (e.g. AltiVec) and - // cache information and friends for NameRegistry - static const struct { - uint32 pvr_mask; - uint32 pvr_value; - const char *cpu_name; - } - cpu_specs[] = { - { 0xffff0000, 0x00010000, "601" }, - { 0xffff0000, 0x00030000, "603" }, - { 0xffff0000, 0x00060000, "603e" }, - { 0xffff0000, 0x00070000, "603ev" }, - { 0xffff0000, 0x00040000, "604" }, - { 0xfffff000, 0x00090000, "604e" }, - { 0xffff0000, 0x00090000, "604r" }, - { 0xffff0000, 0x000a0000, "604ev" }, - { 0xffffffff, 0x00084202, "740/750" }, - { 0xfffff000, 0x00083000, "745/755" }, - { 0xfffffff0, 0x00080100, "750CX" }, - { 0xfffffff0, 0x00082200, "750CX" }, - { 0xfffffff0, 0x00082210, "750CXe" }, - { 0xffffff00, 0x70000100, "750FX" }, - { 0xffffffff, 0x70000200, "750FX" }, - { 0xffff0000, 0x70000000, "750FX" }, - { 0xffff0000, 0x70020000, "750GX" }, - { 0xffff0000, 0x00080000, "740/750" }, - { 0xffffffff, 0x000c1101, "7400 (1.1)" }, - { 0xffff0000, 0x000c0000, "7400" }, - { 0xffff0000, 0x800c0000, "7410" }, - { 0xffffffff, 0x80000200, "7450" }, - { 0xffffffff, 0x80000201, "7450" }, - { 0xffff0000, 0x80000000, "7450" }, - { 0xffffff00, 0x80010100, "7455" }, - { 0xffffffff, 0x80010200, "7455" }, - { 0xffff0000, 0x80010000, "7455" }, - { 0xffff0000, 0x80020000, "7457" }, - { 0xffff0000, 0x80030000, "7447A" }, - { 0xffff0000, 0x80040000, "7448" }, - { 0x7fff0000, 0x00810000, "82xx" }, - { 0x7fff0000, 0x00820000, "8280" }, - { 0xffff0000, 0x00400000, "Power3 (630)" }, - { 0xffff0000, 0x00410000, "Power3 (630+)" }, - { 0xffff0000, 0x00360000, "I-star" }, - { 0xffff0000, 0x00370000, "S-star" }, - { 0xffff0000, 0x00350000, "Power4" }, - { 0xffff0000, 0x00390000, "PPC970" }, - { 0xffff0000, 0x003c0000, "PPC970FX" }, - { 0xffff0000, 0x00440000, "PPC970MP" }, - { 0xffff0000, 0x003a0000, "POWER5 (gr)" }, - { 0xffff0000, 0x003b0000, "POWER5+ (gs)" }, - { 0xffff0000, 0x003e0000, "POWER6" }, - { 0xffff0000, 0x00700000, "Cell Broadband Engine" }, - { 0x7fff0000, 0x00900000, "PA6T" }, - { 0, 0, 0 } - }; - - char line[256]; - while(fgets(line, 255, proc_file)) { - // Read line - int len = strlen(line); - if (len == 0) - continue; - line[len-1] = 0; - - // Parse line - int i; - float f; - char value[256]; - if (sscanf(line, "cpu : %[^,]", value) == 1) { - // Search by name - const char *cpu_name = NULL; - for (int i = 0; cpu_specs[i].pvr_mask != 0; i++) { - if (strcmp(cpu_specs[i].cpu_name, value) == 0) { - cpu_name = cpu_specs[i].cpu_name; - PVR = cpu_specs[i].pvr_value; - break; - } - } - if (cpu_name == NULL) - printf("WARNING: Unknown CPU type '%s', assuming 604\n", value); - else - printf("Found a PowerPC %s processor\n", cpu_name); - } - if (sscanf(line, "clock : %fMHz", &f) == 1) - CPUClockSpeed = BusClockSpeed = ((int64)f) * 1000000; - else if (sscanf(line, "clock : %dMHz", &i) == 1) - CPUClockSpeed = BusClockSpeed = i * 1000000; - } - fclose(proc_file); - } else { - char str[256]; - sprintf(str, GetString(STR_PROC_CPUINFO_WARN), strerror(errno)); - WarningAlert(str); - } - - // Get actual bus frequency - proc_file = fopen("/proc/device-tree/clock-frequency", "r"); - if (proc_file) { - union { uint8 b[4]; uint32 l; } value; - if (fread(value.b, sizeof(value), 1, proc_file) == 1) - BusClockSpeed = value.l; - fclose(proc_file); - } - - // Get actual timebase frequency - TimebaseSpeed = BusClockSpeed / 4; - DIR *cpus_dir; - if ((cpus_dir = opendir("/proc/device-tree/cpus")) != NULL) { - struct dirent *cpu_entry; - while ((cpu_entry = readdir(cpus_dir)) != NULL) { - if (strstr(cpu_entry->d_name, "PowerPC,") == cpu_entry->d_name) { - char timebase_freq_node[256]; - sprintf(timebase_freq_node, "/proc/device-tree/cpus/%s/timebase-frequency", cpu_entry->d_name); - proc_file = fopen(timebase_freq_node, "r"); - if (proc_file) { - union { uint8 b[4]; uint32 l; } value; - if (fread(value.b, sizeof(value), 1, proc_file) == 1) - TimebaseSpeed = value.l; - fclose(proc_file); - } - } - } - closedir(cpus_dir); - } -#endif - - // Remap any newer G4/G5 processor to plain G4 for compatibility - switch (PVR >> 16) { - case 0x8000: // 7450 - case 0x8001: // 7455 - case 0x8002: // 7457 - case 0x8003: // 7447A - case 0x8004: // 7448 - case 0x0039: // 970 - case 0x003c: // 970FX - case 0x0044: // 970MP - PVR = 0x000c0000; // 7400 - break; - } - D(bug("PVR: %08x (assumed)\n", PVR)); -} - -static bool load_mac_rom(void) -{ - uint32 rom_size, actual; - uint8 *rom_tmp; - const char *rom_path = PrefsFindString("rom"); - int rom_fd = open(rom_path && *rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY); - if (rom_fd < 0) { - rom_fd = open(ROM_FILE_NAME2, O_RDONLY); - if (rom_fd < 0) { - ErrorAlert(GetString(STR_NO_ROM_FILE_ERR)); - return false; - } - } - printf("%s", GetString(STR_READING_ROM_FILE)); - rom_size = lseek(rom_fd, 0, SEEK_END); - lseek(rom_fd, 0, SEEK_SET); - rom_tmp = new uint8[ROM_SIZE]; - actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE); - close(rom_fd); - - // Decode Mac ROM - if (!DecodeROM(rom_tmp, actual)) { - if (rom_size != 4*1024*1024) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - return false; - } else { - ErrorAlert(GetString(STR_ROM_FILE_READ_ERR)); - return false; - } - } - delete[] rom_tmp; - return true; -} - -static bool install_signal_handlers(void) -{ - char str[256]; -#if !EMULATED_PPC - // Create and install stacks for signal handlers - sig_stack.ss_sp = malloc(SIG_STACK_SIZE); - D(bug("Signal stack at %p\n", sig_stack.ss_sp)); - if (sig_stack.ss_sp == NULL) { - ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR)); - return false; - } - sig_stack.ss_flags = 0; - sig_stack.ss_size = SIG_STACK_SIZE; - if (sigaltstack(&sig_stack, NULL) < 0) { - sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno)); - ErrorAlert(str); - return false; - } - extra_stack.ss_sp = malloc(SIG_STACK_SIZE); - D(bug("Extra stack at %p\n", extra_stack.ss_sp)); - if (extra_stack.ss_sp == NULL) { - ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR)); - return false; - } - extra_stack.ss_flags = 0; - extra_stack.ss_size = SIG_STACK_SIZE; - - // Install SIGSEGV and SIGBUS handlers - sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling - sigaddset(&sigsegv_action.sa_mask, SIGUSR2); - sigsegv_action.sa_sigaction = sigsegv_handler; - sigsegv_action.sa_flags = SA_ONSTACK | SA_SIGINFO; -#ifdef HAVE_SIGNAL_SA_RESTORER - sigsegv_action.sa_restorer = NULL; -#endif - if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno)); - ErrorAlert(str); - return false; - } - if (sigaction(SIGBUS, &sigsegv_action, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGBUS", strerror(errno)); - ErrorAlert(str); - return false; - } -#else - // Install SIGSEGV handler for CPU emulator - if (!sigsegv_install_handler(sigsegv_handler)) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno)); - ErrorAlert(str); - return false; - } -#endif - return true; -} - -#ifdef USE_SDL -static bool init_sdl() -{ - int sdl_flags = 0; -#ifdef USE_SDL_VIDEO - sdl_flags |= SDL_INIT_VIDEO; -#endif -#ifdef USE_SDL_AUDIO - sdl_flags |= SDL_INIT_AUDIO; -#endif - assert(sdl_flags != 0); - -#ifdef USE_SDL_VIDEO - // Don't let SDL block the screensaver - setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", true); - - // Make SDL pass through command-clicks and option-clicks unaltered - setenv("SDL_HAS3BUTTONMOUSE", "1", true); -#endif - - if (SDL_Init(sdl_flags) == -1) { - char str[256]; - sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError()); - ErrorAlert(str); - return false; - } - atexit(SDL_Quit); - - // Don't let SDL catch SIGINT and SIGTERM signals - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - return true; -} -#endif - -int main(int argc, char **argv) -{ - char str[256]; - bool memory_mapped_from_zero, ram_rom_areas_contiguous; - const char *vmdir = NULL; - - // Initialize variables - RAMBase = 0; - tzset(); - - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - -#if !EMULATED_PPC -#ifdef SYSTEM_CLOBBERS_R2 - // Get TOC pointer - TOC = get_r2(); -#endif -#ifdef SYSTEM_CLOBBERS_R13 - // Get r13 register - R13 = get_r13(); -#endif -#endif - - // Parse command line arguments - for (int i=1; i i) { - k -= i; - for (int j=i+k; jed; - KernelDataAddr = KERNEL_DATA_BASE; - D(bug("Kernel Data at %p (%08x)\n", kernel_data, KERNEL_DATA_BASE)); - D(bug("Emulator Data at %p (%08x)\n", emulator_data, KERNEL_DATA_BASE + offsetof(KernelData, ed))); - - // Create area for DR Cache - if (vm_mac_acquire_fixed(DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) { - sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - dr_emulator_area_mapped = true; - if (vm_mac_acquire_fixed(DR_CACHE_BASE, DR_CACHE_SIZE) < 0) { - sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - dr_cache_area_mapped = true; -#if !EMULATED_PPC - if (vm_protect((char *)DR_CACHE_BASE, DR_CACHE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { - sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } -#endif - DRCacheAddr = DR_CACHE_BASE; - D(bug("DR Cache at %p\n", DRCacheAddr)); - - // Create area for SheepShaver data - if (!SheepMem::Init()) { - sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - - // Create area for Mac RAM - RAMSize = PrefsFindInt32("ramsize"); - if (RAMSize < 8*1024*1024) { - WarningAlert(GetString(STR_SMALL_RAM_WARN)); - RAMSize = 8*1024*1024; - } - memory_mapped_from_zero = false; - ram_rom_areas_contiguous = false; -#if REAL_ADDRESSING && HAVE_LINKER_SCRIPT - if (vm_mac_acquire_fixed(0, RAMSize) == 0) { - D(bug("Could allocate RAM from 0x0000\n")); - RAMBase = 0; - RAMBaseHost = Mac2HostAddr(RAMBase); - memory_mapped_from_zero = true; - } -#endif - if (!memory_mapped_from_zero) { -#ifndef PAGEZERO_HACK - // Create Low Memory area (0x0000..0x3000) - if (vm_mac_acquire_fixed(0, 0x3000) < 0) { - sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - lm_area_mapped = true; -#endif -#if REAL_ADDRESSING - // Allocate RAM at any address. Since ROM must be higher than RAM, allocate the RAM - // and ROM areas contiguously, plus a little extra to allow for ROM address alignment. - RAMBaseHost = vm_mac_acquire(RAMSize + ROM_AREA_SIZE + ROM_ALIGNMENT); - if (RAMBaseHost == VM_MAP_FAILED) { - sprintf(str, GetString(STR_RAM_ROM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - RAMBase = Host2MacAddr(RAMBaseHost); - ROMBase = (RAMBase + RAMSize + ROM_ALIGNMENT -1) & -ROM_ALIGNMENT; - ROMBaseHost = Mac2HostAddr(ROMBase); - ram_rom_areas_contiguous = true; -#else - if (vm_mac_acquire_fixed(RAM_BASE, RAMSize) < 0) { - sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - RAMBase = RAM_BASE; - RAMBaseHost = Mac2HostAddr(RAMBase); -#endif - } -#if !EMULATED_PPC - if (vm_protect(RAMBaseHost, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { - sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } -#endif - ram_area_mapped = true; - D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase)); - - if (RAMBase > KernelDataAddr) { - ErrorAlert(GetString(STR_RAM_AREA_TOO_HIGH_ERR)); - goto quit; - } - - // Create area for Mac ROM - if (!ram_rom_areas_contiguous) { - if (vm_mac_acquire_fixed(ROM_BASE, ROM_AREA_SIZE) < 0) { - sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - ROMBase = ROM_BASE; - ROMBaseHost = Mac2HostAddr(ROMBase); - } -#if !EMULATED_PPC - if (vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { - sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } -#endif - rom_area_mapped = true; - D(bug("ROM area at %p (%08x)\n", ROMBaseHost, ROMBase)); - - if (RAMBase > ROMBase) { - ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR)); - goto quit; - } - - // Load Mac ROM - if (!load_mac_rom()) - goto quit; - - // Initialize everything - if (!InitAll(vmdir)) - goto quit; - D(bug("Initialization complete\n")); - - // Clear caches (as we loaded and patched code) and write protect ROM -#if !EMULATED_PPC - flush_icache_range(ROMBase, ROMBase + ROM_AREA_SIZE); -#endif - vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE); - - // Start 60Hz thread - tick_thread_cancel = false; - tick_thread_active = (pthread_create(&tick_thread, NULL, tick_func, NULL) == 0); - D(bug("Tick thread installed (%ld)\n", tick_thread)); - - // Start NVRAM watchdog thread - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - nvram_thread_cancel = false; - nvram_thread_active = (pthread_create(&nvram_thread, NULL, nvram_func, NULL) == 0); - D(bug("NVRAM thread installed (%ld)\n", nvram_thread)); - -#if !EMULATED_PPC - // Install SIGILL handler - sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling - sigaddset(&sigill_action.sa_mask, SIGUSR2); - sigill_action.sa_sigaction = sigill_handler; - sigill_action.sa_flags = SA_ONSTACK | SA_SIGINFO; -#ifdef HAVE_SIGNAL_SA_RESTORER - sigill_action.sa_restorer = NULL; -#endif - if (sigaction(SIGILL, &sigill_action, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno)); - ErrorAlert(str); - goto quit; - } -#endif - -#if !EMULATED_PPC - // Install interrupt signal handler - sigemptyset(&sigusr2_action.sa_mask); - sigusr2_action.sa_sigaction = sigusr2_handler_init; - sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; -#ifdef HAVE_SIGNAL_SA_RESTORER - sigusr2_action.sa_restorer = NULL; -#endif - if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno)); - ErrorAlert(str); - goto quit; - } -#endif - - // Get my thread ID and execute MacOS thread function - emul_thread = pthread_self(); - D(bug("MacOS thread is %ld\n", emul_thread)); - emul_func(NULL); - -quit: - Quit(); - return 0; -} - - -/* - * Cleanup and quit - */ - -static void Quit(void) -{ -#if EMULATED_PPC - // Exit PowerPC emulation - exit_emul_ppc(); -#endif - - // Stop 60Hz thread - if (tick_thread_active) { - tick_thread_cancel = true; - pthread_cancel(tick_thread); - pthread_join(tick_thread, NULL); - } - - // Stop NVRAM watchdog thread - if (nvram_thread_active) { - nvram_thread_cancel = true; - pthread_cancel(nvram_thread); - pthread_join(nvram_thread, NULL); - } - -#if !EMULATED_PPC - // Uninstall SIGSEGV and SIGBUS handlers - sigemptyset(&sigsegv_action.sa_mask); - sigsegv_action.sa_handler = SIG_DFL; - sigsegv_action.sa_flags = 0; - sigaction(SIGSEGV, &sigsegv_action, NULL); - sigaction(SIGBUS, &sigsegv_action, NULL); - - // Uninstall SIGILL handler - sigemptyset(&sigill_action.sa_mask); - sigill_action.sa_handler = SIG_DFL; - sigill_action.sa_flags = 0; - sigaction(SIGILL, &sigill_action, NULL); - - // Delete stacks for signal handlers - if (sig_stack.ss_sp) - free(sig_stack.ss_sp); - if (extra_stack.ss_sp) - free(extra_stack.ss_sp); -#endif - - // Deinitialize everything - ExitAll(); - - // Delete SheepShaver globals - SheepMem::Exit(); - - // Delete RAM area - if (ram_area_mapped) - vm_mac_release(RAMBase, RAMSize); - - // Delete ROM area - if (rom_area_mapped) - vm_mac_release(ROMBase, ROM_AREA_SIZE); - - // Delete DR cache areas - if (dr_emulator_area_mapped) - vm_mac_release(DR_EMULATOR_BASE, DR_EMULATOR_SIZE); - if (dr_cache_area_mapped) - vm_mac_release(DR_CACHE_BASE, DR_CACHE_SIZE); - - // Delete Low Memory area - if (lm_area_mapped) - vm_mac_release(0, 0x3000); - - // Close /dev/zero - if (zero_fd > 0) - close(zero_fd); - - // Exit system routines - SysExit(); - - // Exit preferences - PrefsExit(); - -#ifdef ENABLE_MON - // Exit mon - mon_exit(); -#endif - - // Close X11 server connection -#ifndef USE_SDL_VIDEO - if (x_display) - XCloseDisplay(x_display); -#endif - - // Notify GUI we are about to leave - if (gui_connection) { - if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) - rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID); - } - - exit(0); -} - - -/* - * Initialize Kernel Data segments - */ - -static bool kernel_data_init(void) -{ - int error_string = STR_KD_SHMGET_ERR; - uint32 kernel_area_size = (KERNEL_AREA_SIZE + SHMLBA - 1) & -SHMLBA; - int kernel_area = shmget(IPC_PRIVATE, kernel_area_size, 0600); - if (kernel_area != -1) { - bool mapped = - shm_map_address(kernel_area, KERNEL_DATA_BASE & -SHMLBA) && - shm_map_address(kernel_area, KERNEL_DATA2_BASE & -SHMLBA); - - // Mark the shared memory segment for removal. This is safe to do - // because the deletion is not performed while the memory is still - // mapped and so will only be done once the process exits. - shmctl(kernel_area, IPC_RMID, NULL); - if (mapped) - return true; - - error_string = STR_KD_SHMAT_ERR; - } - - char str[256]; - sprintf(str, GetString(error_string), strerror(errno)); - ErrorAlert(str); - return false; -} - - -/* - * Maps the memory identified by kernel_area at the specified addr - */ - -static bool shm_map_address(int kernel_area, uint32 addr) -{ - void *kernel_addr = Mac2HostAddr(addr); - return shmat(kernel_area, kernel_addr, 0) == kernel_addr; -} - - -/* - * Jump into Mac ROM, start 680x0 emulator - */ - -#if EMULATED_PPC -void jump_to_rom(uint32 entry) -{ - init_emul_ppc(); - emul_ppc(entry); -} -#endif - - -/* - * Emulator thread function - */ - -static void *emul_func(void *arg) -{ - // We're now ready to receive signals - ready_for_signals = true; - - // Decrease priority, so more time-critical things like audio will work better - nice(1); - - // Jump to ROM boot routine - D(bug("Jumping to ROM\n")); -#if EMULATED_PPC - jump_to_rom(ROMBase + 0x310000); -#else - jump_to_rom(ROMBase + 0x310000, (uint32)emulator_data); -#endif - D(bug("Returned from ROM\n")); - - // We're no longer ready to receive signals - ready_for_signals = false; - return NULL; -} - - -#if !EMULATED_PPC -/* - * Execute 68k subroutine (must be ended with RTS) - * This must only be called by the emul_thread when in EMUL_OP mode - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68k(uint32 pc, M68kRegisters *r) -{ -#if SAFE_EXEC_68K - if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP) - printf("FATAL: Execute68k() not called from EMUL_OP mode\n"); - if (!pthread_equal(pthread_self(), emul_thread)) - printf("FATAL: Execute68k() not called from emul_thread\n"); -#endif - execute_68k(pc, r); -} - - -/* - * Execute 68k A-Trap from EMUL_OP routine - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68kTrap(uint16 trap, M68kRegisters *r) -{ - uint16 proc[2] = {trap, M68K_RTS}; - Execute68k((uint32)proc, r); -} -#endif - - -/* - * Quit emulator (cause return from jump_to_rom) - */ - -void QuitEmulator(void) -{ -#if EMULATED_PPC - Quit(); -#else - quit_emulator(); -#endif -} - - -/* - * Dump 68k registers - */ - -void Dump68kRegs(M68kRegisters *r) -{ - // Display 68k registers - for (int i=0; i<8; i++) { - printf("d%d: %08x", i, r->d[i]); - if (i == 3 || i == 7) - printf("\n"); - else - printf(", "); - } - for (int i=0; i<8; i++) { - printf("a%d: %08x", i, r->a[i]); - if (i == 3 || i == 7) - printf("\n"); - else - printf(", "); - } -} - - -/* - * Make code executable - */ - -void MakeExecutable(int dummy, uint32 start, uint32 length) -{ - if ((start >= ROMBase) && (start < (ROMBase + ROM_SIZE))) - return; -#if EMULATED_PPC - FlushCodeCache(start, start + length); -#else - flush_icache_range(start, start + length); -#endif -} - - -/* - * NVRAM watchdog thread (saves NVRAM every minute) - */ - -static void nvram_watchdog(void) -{ - if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - SaveXPRAM(); - } -} - -static void *nvram_func(void *arg) -{ - while (!nvram_thread_cancel) { - for (int i=0; i<60 && !nvram_thread_cancel; i++) - Delay_usec(999999); // Only wait 1 second so we quit promptly when nvram_thread_cancel becomes true - nvram_watchdog(); - } - return NULL; -} - - -/* - * 60Hz thread (really 60.15Hz) - */ - -static void *tick_func(void *arg) -{ - int tick_counter = 0; - uint64 start = GetTicks_usec(); - int64 ticks = 0; - uint64 next = GetTicks_usec(); - - while (!tick_thread_cancel) { - - // Wait - next += 16625; - int64 delay = next - GetTicks_usec(); - if (delay > 0) - Delay_usec(delay); - else if (delay < -16625) - next = GetTicks_usec(); - ticks++; - -#if !EMULATED_PPC - // Did we crash? - if (emul_thread_fatal) { - - // Yes, dump registers - sigregs *r = &sigsegv_regs; - char str[256]; - if (crash_reason == NULL) - crash_reason = "SIGSEGV"; - sprintf(str, "%s\n" - " pc %08lx lr %08lx ctr %08lx msr %08lx\n" - " xer %08lx cr %08lx \n" - " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n" - " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n" - " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n" - " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n" - " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n" - " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n" - " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n" - " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", - crash_reason, - r->nip, r->link, r->ctr, r->msr, - r->xer, r->ccr, - r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3], - r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7], - r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11], - r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15], - r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19], - r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23], - r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27], - r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]); - printf(str); - VideoQuitFullScreen(); - -#ifdef ENABLE_MON - // Start up mon in real-mode - printf("Welcome to the sheep factory.\n"); - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif - return NULL; - } -#endif - - // Pseudo Mac 1Hz interrupt, update local time - if (++tick_counter > 60) { - tick_counter = 0; - WriteMacInt32(0x20c, TimerDateTime()); - } - - // Trigger 60Hz interrupt - if (ReadMacInt32(XLM_IRQ_NEST) == 0) { - SetInterruptFlag(INTFLAG_VIA); - TriggerInterrupt(); - } - } - - uint64 end = GetTicks_usec(); - D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); - return NULL; -} - - -/* - * Pthread configuration - */ - -void Set_pthread_attr(pthread_attr_t *attr, int priority) -{ -#ifdef HAVE_PTHREADS - pthread_attr_init(attr); -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - // Some of these only work for superuser - if (geteuid() == 0) { - pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); - pthread_attr_setschedpolicy(attr, SCHED_FIFO); - struct sched_param fifo_param; - fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) + - sched_get_priority_max(SCHED_FIFO)) / 2 + - priority); - pthread_attr_setschedparam(attr, &fifo_param); - } - if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) { -#ifdef PTHREAD_SCOPE_BOUND_NP - // If system scope is not available (eg. we're not running - // with CAP_SCHED_MGT capability on an SGI box), try bound - // scope. It exposes pthread scheduling to the kernel, - // without setting realtime priority. - pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP); -#endif - } -#endif -#endif -} - - -/* - * Mutexes - */ - -#ifdef HAVE_PTHREADS - -struct B2_mutex { - B2_mutex() { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - // Initialize the mutex for priority inheritance -- - // required for accurate timing. -#if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__) - pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); -#endif -#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL) - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); -#endif -#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); -#endif - pthread_mutex_init(&m, &attr); - pthread_mutexattr_destroy(&attr); - } - ~B2_mutex() { - pthread_mutex_trylock(&m); // Make sure it's locked before - pthread_mutex_unlock(&m); // unlocking it. - pthread_mutex_destroy(&m); - } - pthread_mutex_t m; -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ - pthread_mutex_lock(&mutex->m); -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ - pthread_mutex_unlock(&mutex->m); -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - -#else - -struct B2_mutex { - int dummy; -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - -#endif - - -/* - * Trigger signal USR2 from another thread - */ - -#if !EMULATED_PPC -void TriggerInterrupt(void) -{ - if (ready_for_signals) { - idle_resume(); - pthread_kill(emul_thread, SIGUSR2); - } -} -#endif - - -/* - * Interrupt flags (must be handled atomically!) - */ - -volatile uint32 InterruptFlags = 0; - -void SetInterruptFlag(uint32 flag) -{ - atomic_or((int *)&InterruptFlags, flag); -} - -void ClearInterruptFlag(uint32 flag) -{ - atomic_and((int *)&InterruptFlags, ~flag); -} - - -/* - * Disable interrupts - */ - -void DisableInterrupt(void) -{ -#if EMULATED_PPC - WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) + 1); -#else - atomic_add((int *)XLM_IRQ_NEST, 1); -#endif -} - - -/* - * Enable interrupts - */ - -void EnableInterrupt(void) -{ -#if EMULATED_PPC - WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) - 1); -#else - atomic_add((int *)XLM_IRQ_NEST, -1); -#endif -} - - -/* - * USR2 handler - */ - -#if !EMULATED_PPC -void sigusr2_handler(int sig, siginfo_t *sip, void *scp) -{ - machine_regs *r = MACHINE_REGISTERS(scp); - -#ifdef SYSTEM_CLOBBERS_R2 - // Restore pointer to Thread Local Storage - set_r2(TOC); -#endif -#ifdef SYSTEM_CLOBBERS_R13 - // Restore pointer to .sdata section - set_r13(R13); -#endif - -#ifdef USE_SDL_VIDEO - // We must fill in the events queue in the same thread that did call SDL_SetVideoMode() - SDL_PumpEvents(); -#endif - - // Do nothing if interrupts are disabled - if (*(int32 *)XLM_IRQ_NEST > 0) - return; - - // Disable MacOS stack sniffer - WriteMacInt32(0x110, 0); - - // Interrupt action depends on current run mode - switch (ReadMacInt32(XLM_RUN_MODE)) { - case MODE_68K: - // 68k emulator active, trigger 68k interrupt level 1 - WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1); - r->cr() |= ntohl(kernel_data->v[0x674 >> 2]); - break; - -#if INTERRUPTS_IN_NATIVE_MODE - case MODE_NATIVE: - // 68k emulator inactive, in nanokernel? - if (r->gpr(1) != KernelDataAddr) { - - // Set extra stack for SIGSEGV handler - sigaltstack(&extra_stack, NULL); - - // Prepare for 68k interrupt level 1 - WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1); - WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2])); - - // Execute nanokernel interrupt routine (this will activate the 68k emulator) - DisableInterrupt(); - if (ROMType == ROMTYPE_NEWWORLD) - ppc_interrupt(ROMBase + 0x312b1c, KernelDataAddr); - else - ppc_interrupt(ROMBase + 0x312a3c, KernelDataAddr); - - // Reset normal stack - sigaltstack(&sig_stack, NULL); - } - break; -#endif - -#if INTERRUPTS_IN_EMUL_OP_MODE - case MODE_EMUL_OP: - // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0 - if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) { - - // Set extra stack for SIGSEGV handler - sigaltstack(&extra_stack, NULL); -#if 1 - // Execute full 68k interrupt routine - M68kRegisters r; - uint32 old_r25 = ReadMacInt32(XLM_68K_R25); // Save interrupt level - WriteMacInt32(XLM_68K_R25, 0x21); // Execute with interrupt level 1 - static const uint16 proc[] = { - 0x3f3c, 0x0000, // move.w #$0000,-(sp) (fake format word) - 0x487a, 0x000a, // pea @1(pc) (return address) - 0x40e7, // move sr,-(sp) (saved SR) - 0x2078, 0x0064, // move.l $64,a0 - 0x4ed0, // jmp (a0) - M68K_RTS // @1 - }; - Execute68k((uint32)proc, &r); - WriteMacInt32(XLM_68K_R25, old_r25); // Restore interrupt level -#else - // Only update cursor - if (HasMacStarted()) { - if (InterruptFlags & INTFLAG_VIA) { - ClearInterruptFlag(INTFLAG_VIA); - ADBInterrupt(); - ExecuteNative(NATIVE_VIDEO_VBL); - } - } -#endif - // Reset normal stack - sigaltstack(&sig_stack, NULL); - } - break; -#endif - } -} -#endif - - -/* - * SIGSEGV handler - */ - -#if !EMULATED_PPC -static void sigsegv_handler(int sig, siginfo_t *sip, void *scp) -{ - machine_regs *r = MACHINE_REGISTERS(scp); - - // Get effective address - uint32 addr = r->dar(); - -#ifdef SYSTEM_CLOBBERS_R2 - // Restore pointer to Thread Local Storage - set_r2(TOC); -#endif -#ifdef SYSTEM_CLOBBERS_R13 - // Restore pointer to .sdata section - set_r13(R13); -#endif - -#if ENABLE_VOSF - // Handle screen fault -#if SIGSEGV_CHECK_VERSION(1,0,0) - sigsegv_info_t si; - si.addr = (sigsegv_address_t)addr; - si.pc = (sigsegv_address_t)r->pc(); -#endif - extern bool Screen_fault_handler(sigsegv_info_t *sip); - if (Screen_fault_handler(&si)) - return; -#endif - - // Fault in Mac ROM or RAM or DR Cache? - bool mac_fault = (r->pc() >= ROMBase) && (r->pc() < (ROMBase + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize)) || (r->pc() >= DR_CACHE_BASE && r->pc() < (DR_CACHE_BASE + DR_CACHE_SIZE)); - if (mac_fault) { - - // "VM settings" during MacOS 8 installation - if (r->pc() == ROMBase + 0x488160 && r->gpr(20) == 0xf8000000) { - r->pc() += 4; - r->gpr(8) = 0; - return; - - // MacOS 8.5 installation - } else if (r->pc() == ROMBase + 0x488140 && r->gpr(16) == 0xf8000000) { - r->pc() += 4; - r->gpr(8) = 0; - return; - - // MacOS 8 serial drivers on startup - } else if (r->pc() == ROMBase + 0x48e080 && (r->gpr(8) == 0xf3012002 || r->gpr(8) == 0xf3012000)) { - r->pc() += 4; - r->gpr(8) = 0; - return; - - // MacOS 8.1 serial drivers on startup - } else if (r->pc() == ROMBase + 0x48c5e0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) { - r->pc() += 4; - return; - } else if (r->pc() == ROMBase + 0x4a10a0 && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) { - r->pc() += 4; - return; - - // MacOS 8.6 serial drivers on startup (with DR Cache and OldWorld ROM) - } else if ((r->pc() - DR_CACHE_BASE) < DR_CACHE_SIZE && (r->gpr(16) == 0xf3012002 || r->gpr(16) == 0xf3012000)) { - r->pc() += 4; - return; - } else if ((r->pc() - DR_CACHE_BASE) < DR_CACHE_SIZE && (r->gpr(20) == 0xf3012002 || r->gpr(20) == 0xf3012000)) { - r->pc() += 4; - return; - } - - // Get opcode and divide into fields - uint32 opcode = *((uint32 *)r->pc()); - uint32 primop = opcode >> 26; - uint32 exop = (opcode >> 1) & 0x3ff; - uint32 ra = (opcode >> 16) & 0x1f; - uint32 rb = (opcode >> 11) & 0x1f; - uint32 rd = (opcode >> 21) & 0x1f; - int32 imm = (int16)(opcode & 0xffff); - - // Analyze opcode - enum { - TYPE_UNKNOWN, - TYPE_LOAD, - TYPE_STORE - } transfer_type = TYPE_UNKNOWN; - enum { - SIZE_UNKNOWN, - SIZE_BYTE, - SIZE_HALFWORD, - SIZE_WORD - } transfer_size = SIZE_UNKNOWN; - enum { - MODE_UNKNOWN, - MODE_NORM, - MODE_U, - MODE_X, - MODE_UX - } addr_mode = MODE_UNKNOWN; - switch (primop) { - case 31: - switch (exop) { - case 23: // lwzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 55: // lwzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 87: // lbzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 119: // lbzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 151: // stwx - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break; - case 183: // stwux - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break; - case 215: // stbx - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break; - case 247: // stbux - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break; - case 279: // lhzx - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 311: // lhzux - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - case 343: // lhax - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 375: // lhaux - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - case 407: // sthx - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break; - case 439: // sthux - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break; - } - break; - - case 32: // lwz - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 33: // lwzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 34: // lbz - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 35: // lbzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 36: // stw - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break; - case 37: // stwu - transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break; - case 38: // stb - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break; - case 39: // stbu - transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break; - case 40: // lhz - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 41: // lhzu - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - case 42: // lha - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 43: // lhau - transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; - case 44: // sth - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break; - case 45: // sthu - transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; -#if EMULATE_UNALIGNED_LOADSTORE_MULTIPLE - case 46: // lmw - if ((addr % 4) != 0) { - uint32 ea = addr; - D(bug("WARNING: unaligned lmw to EA=%08x from IP=%08x\n", ea, r->pc())); - for (int i = rd; i <= 31; i++) { - r->gpr(i) = ReadMacInt32(ea); - ea += 4; - } - r->pc() += 4; - goto rti; - } - break; - case 47: // stmw - if ((addr % 4) != 0) { - uint32 ea = addr; - D(bug("WARNING: unaligned stmw to EA=%08x from IP=%08x\n", ea, r->pc())); - for (int i = rd; i <= 31; i++) { - WriteMacInt32(ea, r->gpr(i)); - ea += 4; - } - r->pc() += 4; - goto rti; - } - break; -#endif - } - - // Ignore ROM writes (including to the zero page, which is read-only) - if (transfer_type == TYPE_STORE && - ((addr >= ROMBase && addr < ROMBase + ROM_SIZE) || - (addr >= SheepMem::ZeroPage() && addr < SheepMem::ZeroPage() + SheepMem::PageSize()))) { -// D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc())); - if (addr_mode == MODE_U || addr_mode == MODE_UX) - r->gpr(ra) = addr; - r->pc() += 4; - goto rti; - } - - // Ignore illegal memory accesses? - if (PrefsFindBool("ignoresegv")) { - if (addr_mode == MODE_U || addr_mode == MODE_UX) - r->gpr(ra) = addr; - if (transfer_type == TYPE_LOAD) - r->gpr(rd) = 0; - r->pc() += 4; - goto rti; - } - - // In GUI mode, show error alert - if (!PrefsFindBool("nogui")) { - char str[256]; - if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE) - sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->pc(), r->gpr(24), r->gpr(1)); - else - sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode); - ErrorAlert(str); - QuitEmulator(); - return; - } - } - - // For all other errors, jump into debugger (sort of...) - crash_reason = (sig == SIGBUS) ? "SIGBUS" : "SIGSEGV"; - if (!ready_for_signals) { - printf("%s\n"); - printf(" sigcontext %p, machine_regs %p\n", scp, r); - printf( - " pc %08lx lr %08lx ctr %08lx msr %08lx\n" - " xer %08lx cr %08lx \n" - " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n" - " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n" - " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n" - " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n" - " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n" - " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n" - " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n" - " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", - crash_reason, - r->pc(), r->lr(), r->ctr(), r->msr(), - r->xer(), r->cr(), - r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3), - r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7), - r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11), - r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15), - r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19), - r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23), - r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27), - r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31)); - exit(1); - QuitEmulator(); - return; - } else { - // We crashed. Save registers, tell tick thread and loop forever - build_sigregs(&sigsegv_regs, r); - emul_thread_fatal = true; - for (;;) ; - } -rti:; -} - - -/* - * SIGILL handler - */ - -static void sigill_handler(int sig, siginfo_t *sip, void *scp) -{ - machine_regs *r = MACHINE_REGISTERS(scp); - char str[256]; - -#ifdef SYSTEM_CLOBBERS_R2 - // Restore pointer to Thread Local Storage - set_r2(TOC); -#endif -#ifdef SYSTEM_CLOBBERS_R13 - // Restore pointer to .sdata section - set_r13(R13); -#endif - - // Fault in Mac ROM or RAM? - bool mac_fault = (r->pc() >= ROMBase) && (r->pc() < (ROMBase + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize)); - if (mac_fault) { - - // Get opcode and divide into fields - uint32 opcode = *((uint32 *)r->pc()); - uint32 primop = opcode >> 26; - uint32 exop = (opcode >> 1) & 0x3ff; - uint32 ra = (opcode >> 16) & 0x1f; - uint32 rb = (opcode >> 11) & 0x1f; - uint32 rd = (opcode >> 21) & 0x1f; - int32 imm = (int16)(opcode & 0xffff); - - switch (primop) { - case 9: // POWER instructions - case 22: -power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->pc(), r->gpr(1), opcode); - ErrorAlert(str); - QuitEmulator(); - return; - - case 31: - switch (exop) { - case 83: // mfmsr - r->gpr(rd) = 0xf072; - r->pc() += 4; - goto rti; - - case 210: // mtsr - case 242: // mtsrin - case 306: // tlbie - r->pc() += 4; - goto rti; - - case 339: { // mfspr - int spr = ra | (rb << 5); - switch (spr) { - case 0: // MQ - case 22: // DEC - case 952: // MMCR0 - case 953: // PMC1 - case 954: // PMC2 - case 955: // SIA - case 956: // MMCR1 - case 957: // PMC3 - case 958: // PMC4 - case 959: // SDA - r->pc() += 4; - goto rti; - case 25: // SDR1 - r->gpr(rd) = 0xdead001f; - r->pc() += 4; - goto rti; - case 287: // PVR - r->gpr(rd) = PVR; - r->pc() += 4; - goto rti; - } - break; - } - - case 467: { // mtspr - int spr = ra | (rb << 5); - switch (spr) { - case 0: // MQ - case 22: // DEC - case 275: // SPRG3 - case 528: // IBAT0U - case 529: // IBAT0L - case 530: // IBAT1U - case 531: // IBAT1L - case 532: // IBAT2U - case 533: // IBAT2L - case 534: // IBAT3U - case 535: // IBAT3L - case 536: // DBAT0U - case 537: // DBAT0L - case 538: // DBAT1U - case 539: // DBAT1L - case 540: // DBAT2U - case 541: // DBAT2L - case 542: // DBAT3U - case 543: // DBAT3L - case 952: // MMCR0 - case 953: // PMC1 - case 954: // PMC2 - case 955: // SIA - case 956: // MMCR1 - case 957: // PMC3 - case 958: // PMC4 - case 959: // SDA - r->pc() += 4; - goto rti; - } - break; - } - - case 29: case 107: case 152: case 153: // POWER instructions - case 184: case 216: case 217: case 248: - case 264: case 277: case 331: case 360: - case 363: case 488: case 531: case 537: - case 541: case 664: case 665: case 696: - case 728: case 729: case 760: case 920: - case 921: case 952: - goto power_inst; - } - } - - // In GUI mode, show error alert - if (!PrefsFindBool("nogui")) { - sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc(), r->gpr(24), r->gpr(1), opcode); - ErrorAlert(str); - QuitEmulator(); - return; - } - } - - // For all other errors, jump into debugger (sort of...) - crash_reason = "SIGILL"; - if (!ready_for_signals) { - printf("%s\n"); - printf(" sigcontext %p, machine_regs %p\n", scp, r); - printf( - " pc %08lx lr %08lx ctr %08lx msr %08lx\n" - " xer %08lx cr %08lx \n" - " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n" - " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n" - " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n" - " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n" - " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n" - " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n" - " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n" - " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n", - crash_reason, - r->pc(), r->lr(), r->ctr(), r->msr(), - r->xer(), r->cr(), - r->gpr(0), r->gpr(1), r->gpr(2), r->gpr(3), - r->gpr(4), r->gpr(5), r->gpr(6), r->gpr(7), - r->gpr(8), r->gpr(9), r->gpr(10), r->gpr(11), - r->gpr(12), r->gpr(13), r->gpr(14), r->gpr(15), - r->gpr(16), r->gpr(17), r->gpr(18), r->gpr(19), - r->gpr(20), r->gpr(21), r->gpr(22), r->gpr(23), - r->gpr(24), r->gpr(25), r->gpr(26), r->gpr(27), - r->gpr(28), r->gpr(29), r->gpr(30), r->gpr(31)); - exit(1); - QuitEmulator(); - return; - } else { - // We crashed. Save registers, tell tick thread and loop forever - build_sigregs(&sigsegv_regs, r); - emul_thread_fatal = true; - for (;;) ; - } -rti:; -} -#endif - - -/* - * Helpers to share 32-bit addressable data with MacOS - */ - -bool SheepMem::Init(void) -{ - // Size of a native page - page_size = getpagesize(); - - // Allocate SheepShaver globals - proc = base; - if (vm_mac_acquire_fixed(base, size) < 0) - return false; - - // Allocate page with all bits set to 0, right in the middle - // This is also used to catch undesired overlaps between proc and data areas - zero_page = proc + (size / 2); - Mac_memset(zero_page, 0, page_size); - if (vm_protect(Mac2HostAddr(zero_page), page_size, VM_PAGE_READ) < 0) - return false; - -#if EMULATED_PPC - // Allocate alternate stack for PowerPC interrupt routine - sig_stack = base + size; - if (vm_mac_acquire_fixed(sig_stack, SIG_STACK_SIZE) < 0) - return false; -#endif - - data = base + size; - return true; -} - -void SheepMem::Exit(void) -{ - if (data) { - // Delete SheepShaver globals - vm_mac_release(base, size); - -#if EMULATED_PPC - // Delete alternate stack for PowerPC interrupt routine - vm_mac_release(sig_stack, SIG_STACK_SIZE); -#endif - } -} - - -/* - * Display alert - */ - -#ifdef ENABLE_GTK -static void dl_destroyed(void) -{ - gtk_main_quit(); -} - -static void dl_quit(GtkWidget *dialog) -{ - gtk_widget_destroy(dialog); -} - -void display_alert(int title_id, int prefix_id, int button_id, const char *text) -{ - char str[256]; - sprintf(str, GetString(prefix_id), text); - - GtkWidget *dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL); - - GtkWidget *label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - GtkWidget *button = gtk_button_new_with_label(GetString(button_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - gtk_widget_show(dialog); - - gtk_main(); -} -#endif - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - if (gui_connection) { - if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR && - rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) - return; - } -#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) - if (PrefsFindBool("nogui") || x_display == NULL) { - printf(GetString(STR_SHELL_ERROR_PREFIX), text); - return; - } - VideoQuitFullScreen(); - display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text); -#else - printf(GetString(STR_SHELL_ERROR_PREFIX), text); -#endif -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - if (gui_connection) { - if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR && - rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) - return; - } -#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) - if (PrefsFindBool("nogui") || x_display == NULL) { - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return; - } - display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text); -#else - printf(GetString(STR_SHELL_WARNING_PREFIX), text); -#endif -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return false; //!! -} diff --git a/SheepShaver/src/Unix/mkinstalldirs b/SheepShaver/src/Unix/mkinstalldirs deleted file mode 100755 index 6b3b5fc5..00000000 --- a/SheepShaver/src/Unix/mkinstalldirs +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id$ - -errstatus=0 - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff --git a/SheepShaver/src/Unix/paranoia.cpp b/SheepShaver/src/Unix/paranoia.cpp deleted file mode 100644 index da18ad1e..00000000 --- a/SheepShaver/src/Unix/paranoia.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - * paranoia.cpp - Check undocumented features of the underlying - * kernel that SheepShaver relies upon - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * TODO - * - Check for nested signal handlers vs. sigaltstack() - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "sigregs.h" -#include "main.h" -#include "user_strings.h" - -#define DEBUG 1 -#include "debug.h" - - -// Constants -const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack - -// Prototypes -extern "C" void *get_sp(void); -extern "C" void *get_r2(void); -extern "C" void set_r2(void *); -extern "C" void *get_r13(void); -extern "C" void set_r13(void *); -extern void paranoia_check(void); -static void sigusr2_handler(int sig, siginfo_t *sip, void *scp); -static void *tick_func(void *); -static void *emul_func(void *); - -// Global variables -static void *sig_stack = NULL; - -static int err = 0; -static void *sig_sp = NULL; -static void *sig_r5 = NULL; -static int sig_sc_signal = 0; -static void *sig_sc_regs = NULL; -static uint32 sig_r2 = 0; - -static pthread_t tick_thread; -static pthread_t emul_thread; -static volatile uint32 tick_thread_ready = 0; -static volatile uint32 emul_thread_regs[32] = { 0, }; -static volatile uint32 &emul_thread_ready = emul_thread_regs[0]; - - -void paranoia_check(void) -{ - char str[256]; - - printf("Paranoia checks...\n"); - - // Create and install stack for signal handler - sig_stack = malloc(SIG_STACK_SIZE); - if (sig_stack == NULL) { - ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR)); - exit(1); - } - - stack_t old_stack; - stack_t new_stack; - new_stack.ss_sp = (char *)sig_stack; - new_stack.ss_flags = 0; - new_stack.ss_size = SIG_STACK_SIZE; - if (sigaltstack(&new_stack, &old_stack) < 0) { - sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno)); - ErrorAlert(str); - exit(1); - } - - // Install SIGUSR2 signal handler - static struct sigaction old_action; - static struct sigaction sigusr2_action; - sigemptyset(&sigusr2_action.sa_mask); - sigusr2_action.sa_sigaction = sigusr2_handler; - sigusr2_action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; - if (sigaction(SIGUSR2, &sigusr2_action, &old_action) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno)); - ErrorAlert(str); - exit(1); - } - - // Start tick thread that will trigger only one SIGUSR2 - pthread_create(&tick_thread, NULL, tick_func, NULL); - - // Get my thread ID and execute MacOS thread function - emul_thread = pthread_self(); - emul_func(NULL); - - // Check error code - switch (err) { - case 1: - printf("FATAL: sigaltstack() doesn't seem to work (sp in signal handler was %p, expected %p..%p)\n", sig_sp, sig_stack, (uintptr)sig_stack + SIG_STACK_SIZE); - break; - case 2: - printf("FATAL: r5 in signal handler (%p) doesn't point to stack\n", sig_r5); - break; - case 3: - printf("FATAL: machine registers in signal handler (%p) doesn't point to stack\n", sig_sc_regs); - break; - case 4: - printf("FATAL: register file in signal handler is corrupted\n"); - break; - } - if (err) { - printf("Maybe you need a different kernel?\n"); - exit(1); - } - - // Clean up - printf("...passed\n"); - sigaction(SIGUSR2, &old_action, NULL); - sigaltstack(&old_stack, NULL); - free(sig_stack); -} - -static void *tick_func(void *) -{ - tick_thread_ready = true; - - // Wait for emul thread to initialize - D(bug("[tick_thread] waiting for emul thread to initialize\n")); - while (!emul_thread_ready) - usleep(0); - - // Trigger interrupt and terminate - D(bug("[tick_thread] trigger interrupt\n")); - pthread_kill(emul_thread, SIGUSR2); - return NULL; -} - -static void *emul_func(void *) -{ - // Wait for tick thread to initialize - D(bug("[emul_thread] waiting for tick thread to initialize\n")); - while (!tick_thread_ready) - usleep(0); - - // Fill in register and wait for an interrupt from the tick thread - D(bug("[emul_thread] filling in registers and waiting for interrupt\n")); -#if defined(__APPLE__) && defined(__MACH__) -#define REG(n) "r" #n -#else -#define REG(n) #n -#endif - asm volatile ("stw " REG(2) ",2*4(%0)\n" - "mr " REG(2) ",%0\n" -#define SAVE_REG(n) \ - "stw " REG(n) "," #n "*4(" REG(2) ")\n" \ - "addi " REG(n) "," REG(2) ","#n"\n" - SAVE_REG(1) - SAVE_REG(3) - SAVE_REG(4) - SAVE_REG(5) - SAVE_REG(6) - SAVE_REG(7) - SAVE_REG(8) - SAVE_REG(9) - SAVE_REG(10) - SAVE_REG(11) - SAVE_REG(12) - SAVE_REG(13) - SAVE_REG(14) - SAVE_REG(15) - SAVE_REG(16) - SAVE_REG(17) - SAVE_REG(18) - SAVE_REG(19) - SAVE_REG(20) - SAVE_REG(21) - SAVE_REG(22) - SAVE_REG(23) - SAVE_REG(24) - SAVE_REG(25) - SAVE_REG(26) - SAVE_REG(27) - SAVE_REG(28) - SAVE_REG(29) - SAVE_REG(30) - SAVE_REG(31) -#undef SAVE_REG - " li " REG(0) ",1\n" - " stw " REG(0) ",0(" REG(2) ")\n" // regs[0] == emul_thread_ready - "0: lwz " REG(0) ",0(" REG(2) ")\n" - " cmpi 0," REG(0) ",0\n" - " bne+ 0b\n" -#define LOAD_REG(n) \ - "lwz " REG(n) "," #n "*4(" REG(2) ")\n" - LOAD_REG(1) - LOAD_REG(3) - LOAD_REG(4) - LOAD_REG(5) - LOAD_REG(6) - LOAD_REG(7) - LOAD_REG(8) - LOAD_REG(9) - LOAD_REG(10) - LOAD_REG(11) - LOAD_REG(12) - LOAD_REG(13) - LOAD_REG(14) - LOAD_REG(15) - LOAD_REG(16) - LOAD_REG(17) - LOAD_REG(18) - LOAD_REG(19) - LOAD_REG(20) - LOAD_REG(21) - LOAD_REG(22) - LOAD_REG(23) - LOAD_REG(24) - LOAD_REG(25) - LOAD_REG(26) - LOAD_REG(27) - LOAD_REG(28) - LOAD_REG(29) - LOAD_REG(30) - LOAD_REG(31) - LOAD_REG(2) -#undef LOAD_REG - : : "r" ((uintptr)&emul_thread_regs[0]) : "r0"); -#undef REG -} - - -void sigusr2_handler(int sig, siginfo_t *sip, void *scp) -{ - machine_regs *r = MACHINE_REGISTERS(scp); - -#ifdef SYSTEM_CLOBBERS_R2 - // Restore pointer to Thread Local Storage - set_r2(TOC); -#endif - -#ifdef SYSTEM_CLOBBERS_R13 - // Restore pointer to .sdata section - set_r13(R13); -#endif - - ucontext_t *ucp = (ucontext_t *)scp; - D(bug("SIGUSR2 caught\n")); - - // Check whether sigaltstack works - sig_sp = get_sp(); - if (sig_sp < sig_stack || sig_sp >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) { - err = 1; - goto ret; - } - - // Check whether r5 points to info on the stack - sig_r5 = ucp; - if (sig_r5 < sig_stack || sig_r5 >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) { - err = 2; - goto ret; - } - - // Check whether context regs points to info on the stack - sig_sc_regs = &r->gpr(0); - if (sig_sc_regs < sig_stack || sig_sc_regs >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) { - err = 3; - goto ret; - } - - // Check whether registers still hold the values we set them to - for (int n = 0; n < 32; n++) { - uint32 expected = (uintptr)&emul_thread_regs[0]; - if (n == 0) - expected = 1; - else if (n != 2) - expected += n; - if (r->gpr(n) != expected) { - D(bug("Register corruption: r%d was %08x, expected %08x\n", n, r->gpr(n), expected)); - err = 4; - goto ret; - } - } - - ret: - // Tell emul_func() to exit - emul_thread_ready = false; -} - - -#ifdef TEST -void *TOC; -void *R13; - -extern "C" void EmulOp(void *r, uint32 pc, int selector); -void EmulOp(void *r, uint32 pc, int selector) -{ -} - -extern "C" void check_load_invoc(uint32 type, int16 id, uint32 h); -void check_load_invoc(uint32 type, int16 id, uint32 h) -{ -} - -void ErrorAlert(const char *text) -{ - printf(GetString(STR_SHELL_ERROR_PREFIX), text); -} - -int main(void) -{ -#ifdef SYSTEM_CLOBBERS_R2 - // Get TOC pointer - TOC = get_r2(); -#endif - -#ifdef SYSTEM_CLOBBERS_R13 - // Get r13 register - R13 = get_r13(); -#endif - - // Check some things - paranoia_check(); -} -#endif diff --git a/SheepShaver/src/Unix/posix_sem.cpp b/SheepShaver/src/Unix/posix_sem.cpp deleted file mode 120000 index f530e6db..00000000 --- a/SheepShaver/src/Unix/posix_sem.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/posix_sem.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/ppc_asm.S b/SheepShaver/src/Unix/ppc_asm.S deleted file mode 100644 index 8c1dfede..00000000 --- a/SheepShaver/src/Unix/ppc_asm.S +++ /dev/null @@ -1,932 +0,0 @@ -/* - * asm_linux.S - Assembly routines - * - * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#define SAVE_FP_EXEC_68K 1 - - -/* - * void *get_sp(void) - Get stack pointer - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_sp) -C_SYMBOL_NAME(get_sp): - mr r3,r1 - blr - - -/* - * void *get_r2(void) - Get r2 - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r2) -C_SYMBOL_NAME(get_r2): - mr r3,r2 - blr - - -/* - * void set_r2(void *val {r3}) - Set r2 - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r2) -C_SYMBOL_NAME(set_r2): - mr r2,r3 - blr - - -/* - * void *get_r13(void) - Get r13 (small data pointer under Linux) - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r13) -C_SYMBOL_NAME(get_r13): - mr r3,r13 - blr - -/* - * void set_r13(void *val {r3}) - Set r13 (small data pointer under Linux) - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r13) -C_SYMBOL_NAME(set_r13): - mr r13,r3 - blr - - -/* - * void flush_icache_range(void *start {r3}, void *end {r3}) - Flush D and I cache - */ - -CACHE_LINE_SIZE = 32 -LG_CACHE_LINE_SIZE = 5 - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(flush_icache_range) -C_SYMBOL_NAME(flush_icache_range): - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,LG_CACHE_LINE_SIZE - beqlr - mtctr r4 - mr r6,r3 -1: dcbst 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbst's to get to ram */ - mtctr r4 -2: icbi 0,r6 - addi r6,r6,CACHE_LINE_SIZE - bdnz 2b - sync - isync - blr - - -/* - * long atomic_add(long *var{r3}, long add{r4}) - Atomic add operation - * long atomic_and(long *var{r3}, long and{r4}) - Atomic and operation - * long atomic_or(long *var{r3}, long or{r4}) - Atomic or operation - * int test_and_set(int *var{r3}, int val{r4}) - Atomic test-and-set - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_add) -C_SYMBOL_NAME(atomic_add): -0: dcbf 0,r3 - sync - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - isync - lwarx r5,0,r3 - add r0,r4,r5 - stwcx. r0,0,r3 - bne- 0b - mr r3,r5 - isync - blr - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_and) -C_SYMBOL_NAME(atomic_and): -0: dcbf 0,r3 - sync - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - isync - lwarx r5,0,r3 - and r0,r4,r5 - stwcx. r0,0,r3 - bne- 0b - mr r3,r5 - isync - blr - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_or) -C_SYMBOL_NAME(atomic_or): -0: dcbf 0,r3 - sync - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - isync - lwarx r5,0,r3 - or r0,r4,r5 - stwcx. r0,0,r3 - bne- 0b - mr r3,r5 - isync - blr - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(test_and_set) -C_SYMBOL_NAME(test_and_set): -0: dcbf 0,r3 - sync - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - ori r0,r0,1 - isync - lwarx r5,0,r3 - cmpi 0,r5,0x0000 - bne 1f - stwcx. r4,0,r3 - bne- 0b -1: isync - mr r3,r5 - blr - - -/* - * void quit_emulator(void) - Jump to XLM_EMUL_RETURN_PROC - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(quit_emulator) -C_SYMBOL_NAME(quit_emulator): - lwz r0,XLM_EMUL_RETURN_PROC(0) - mtlr r0 - blr - - -/* - * void jump_to_rom(uint32 entry {r3}, uint32 emulator_data {r4}) - Jump to Mac ROM - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(jump_to_rom) -C_SYMBOL_NAME(jump_to_rom): - // Create stack frame - mflr r0 - stw r0,4(r1) - stwu r1,-(20+19*4+18*8)(r1) // maintain 16 byte alignment - - // Save PowerPC registers - stmw r13,20(r1) - stfd f14,20+19*4+0*8(r1) - stfd f15,20+19*4+1*8(r1) - stfd f16,20+19*4+2*8(r1) - stfd f17,20+19*4+3*8(r1) - stfd f18,20+19*4+4*8(r1) - stfd f19,20+19*4+5*8(r1) - stfd f20,20+19*4+6*8(r1) - stfd f21,20+19*4+7*8(r1) - stfd f22,20+19*4+8*8(r1) - stfd f23,20+19*4+9*8(r1) - stfd f24,20+19*4+10*8(r1) - stfd f25,20+19*4+11*8(r1) - stfd f26,20+19*4+12*8(r1) - stfd f27,20+19*4+13*8(r1) - stfd f28,20+19*4+14*8(r1) - stfd f29,20+19*4+15*8(r1) - stfd f30,20+19*4+16*8(r1) - stfd f31,20+19*4+17*8(r1) - - // Move entry address to ctr - mtctr r3 - - // Skip over EMUL_RETURN routine and get its address - bl 1f - - - /* - * EMUL_RETURN: Returned from emulator - */ - - // Restore PowerPC registers - lwz r1,XLM_EMUL_RETURN_STACK(0) - RESTORE_SYSTEM_R2 - lmw r13,20(r1) - lfd f14,20+19*4+0*8(r1) - lfd f15,20+19*4+1*8(r1) - lfd f16,20+19*4+2*8(r1) - lfd f17,20+19*4+3*8(r1) - lfd f18,20+19*4+4*8(r1) - lfd f19,20+19*4+5*8(r1) - lfd f20,20+19*4+6*8(r1) - lfd f21,20+19*4+7*8(r1) - lfd f22,20+19*4+8*8(r1) - lfd f23,20+19*4+9*8(r1) - lfd f24,20+19*4+10*8(r1) - lfd f25,20+19*4+11*8(r1) - lfd f26,20+19*4+12*8(r1) - lfd f27,20+19*4+13*8(r1) - lfd f28,20+19*4+14*8(r1) - lfd f29,20+19*4+15*8(r1) - lfd f30,20+19*4+16*8(r1) - lfd f31,20+19*4+17*8(r1) - - // Exiting from 68k emulator - li r0,1 - stw r0,XLM_IRQ_NEST(0) - li r0,MODE_NATIVE - stw r0,XLM_RUN_MODE(0) - - // Return to caller of jump_to_rom() - lwz r0,20+19*4+18*8+4(r1) - mtlr r0 - addi r1,r1,20+19*4+18*8 - blr - - - // Save address of EMUL_RETURN routine for 68k emulator patch -1: mflr r0 - stw r0,XLM_EMUL_RETURN_PROC(0) - - // Skip over EXEC_RETURN routine and get its address - bl 2f - - - /* - * EXEC_RETURN: Returned from 68k routine executed with Execute68k() - */ - - // Save r25 (contains current 68k interrupt level) - stw r25,XLM_68K_R25(0) - - // Reentering EMUL_OP mode - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE(0) - - // Save 68k registers - lwz r4,48(r1) // Pointer to M68kRegisters - stw r8,0*4(r4) // d[0]...d[7] - stw r9,1*4(r4) - stw r10,2*4(r4) - stw r11,3*4(r4) - stw r12,4*4(r4) - stw r13,5*4(r4) - stw r14,6*4(r4) - stw r15,7*4(r4) - stw r16,8*4(r4) // a[0]..a[6] - stw r17,9*4(r4) - stw r18,10*4(r4) - stw r19,11*4(r4) - stw r20,12*4(r4) - stw r21,13*4(r4) - stw r22,14*4(r4) - - // Restore PowerPC registers - lmw r13,56(r1) -#if SAVE_FP_EXEC_68K - lfd f14,56+19*4+0*8(r1) - lfd f15,56+19*4+1*8(r1) - lfd f16,56+19*4+2*8(r1) - lfd f17,56+19*4+3*8(r1) - lfd f18,56+19*4+4*8(r1) - lfd f19,56+19*4+5*8(r1) - lfd f20,56+19*4+6*8(r1) - lfd f21,56+19*4+7*8(r1) - lfd f22,56+19*4+8*8(r1) - lfd f23,56+19*4+9*8(r1) - lfd f24,56+19*4+10*8(r1) - lfd f25,56+19*4+11*8(r1) - lfd f26,56+19*4+12*8(r1) - lfd f27,56+19*4+13*8(r1) - lfd f28,56+19*4+14*8(r1) - lfd f29,56+19*4+15*8(r1) - lfd f30,56+19*4+16*8(r1) - lfd f31,56+19*4+17*8(r1) -#endif - - // Return to caller - lwz r0,52(r1) - mtcrf 0xff,r0 - lwz r0,56+19*4+18*8+4(r1) - mtlr r0 - addi r1,r1,56+19*4+18*8 - RESTORE_SYSTEM_R2 - RESTORE_SYSTEM_R13 - blr - - - // Save address of EXEC_RETURN routine for 68k emulator patch -2: mflr r0 - stw r0,XLM_EXEC_RETURN_PROC(0) - - // Skip over EMUL_BREAK/EMUL_OP routine and get its address - bl 3f - - - /* - * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch) - * - * 68k registers are stored in a M68kRegisters struct on the stack - * which the native routine may read and modify - */ - - // Save r25 (contains current 68k interrupt level) - stw r25,XLM_68K_R25(0) - - // Entering EMUL_OP mode within 68k emulator - li r0,MODE_EMUL_OP - stw r0,XLM_RUN_MODE(0) - - // Create PowerPC stack frame, reserve space for M68kRegisters - mr r3,r1 - subi r1,r1,64 // Fake "caller" frame - rlwinm r1,r1,0,0,27 // Align stack - - mfcr r0 - rlwinm r0,r0,0,11,8 - stw r0,4(r1) - mfxer r0 - stw r0,16(r1) - stw r2,12(r1) - stwu r1,-(56+16*4+15*8)(r1) - - // Save 68k registers (M68kRegisters) - stw r8,56+0*4(r1) // d[0]..d[7] - stw r9,56+1*4(r1) - stw r10,56+2*4(r1) - stw r11,56+3*4(r1) - stw r12,56+4*4(r1) - stw r13,56+5*4(r1) - stw r14,56+6*4(r1) - stw r15,56+7*4(r1) - stw r16,56+8*4(r1) // a[0]..a[7] - stw r17,56+9*4(r1) - stw r18,56+10*4(r1) - stw r19,56+11*4(r1) - stw r20,56+12*4(r1) - stw r21,56+13*4(r1) - stw r22,56+14*4(r1) - stw r3,56+15*4(r1) - stfd f0,56+16*4+0*8(r1) - stfd f1,56+16*4+1*8(r1) - stfd f2,56+16*4+2*8(r1) - stfd f3,56+16*4+3*8(r1) - stfd f4,56+16*4+4*8(r1) - stfd f5,56+16*4+5*8(r1) - stfd f6,56+16*4+6*8(r1) - stfd f7,56+16*4+7*8(r1) - mffs f0 - stfd f8,56+16*4+8*8(r1) - stfd f9,56+16*4+9*8(r1) - stfd f10,56+16*4+10*8(r1) - stfd f11,56+16*4+11*8(r1) - stfd f12,56+16*4+12*8(r1) - stfd f13,56+16*4+13*8(r1) - stfd f0,56+16*4+14*8(r1) - - // Execute native routine - RESTORE_SYSTEM_R2 - RESTORE_SYSTEM_R13 - addi r3,r1,56 - mr r4,r24 - bl C_SYMBOL_NAME(EmulOp) - - // Restore 68k registers (M68kRegisters) - lwz r8,56+0*4(r1) // d[0]..d[7] - lwz r9,56+1*4(r1) - lwz r10,56+2*4(r1) - lwz r11,56+3*4(r1) - lwz r12,56+4*4(r1) - lwz r13,56+5*4(r1) - lwz r14,56+6*4(r1) - lwz r15,56+7*4(r1) - lwz r16,56+8*4(r1) // a[0]..a[7] - lwz r17,56+9*4(r1) - lwz r18,56+10*4(r1) - lwz r19,56+11*4(r1) - lwz r20,56+12*4(r1) - lwz r21,56+13*4(r1) - lwz r22,56+14*4(r1) - lwz r3,56+15*4(r1) - lfd f13,56+16*4+14*8(r1) - lfd f0,56+16*4+0*8(r1) - lfd f1,56+16*4+1*8(r1) - lfd f2,56+16*4+2*8(r1) - lfd f3,56+16*4+3*8(r1) - lfd f4,56+16*4+4*8(r1) - lfd f5,56+16*4+5*8(r1) - lfd f6,56+16*4+6*8(r1) - lfd f7,56+16*4+7*8(r1) - mtfsf 0xff,f13 - lfd f8,56+16*4+8*8(r1) - lfd f9,56+16*4+9*8(r1) - lfd f10,56+16*4+10*8(r1) - lfd f11,56+16*4+11*8(r1) - lfd f12,56+16*4+12*8(r1) - lfd f13,56+16*4+13*8(r1) - - // Delete PowerPC stack frame - lwz r2,56+16*4+15*8+12(r1) - lwz r0,56+16*4+15*8+16(r1) - mtxer r0 - lwz r0,56+16*4+15*8+4(r1) - mtcrf 0xff,r0 - mr r1,r3 - - // Reentering 68k emulator - li r0,MODE_68K - stw r0,XLM_RUN_MODE(0) - - // Set r0 to 0 for 68k emulator - li r0,0 - - // Execute next 68k opcode - rlwimi r29,r27,3,13,28 - lhau r27,2(r24) - mtlr r29 - blr - - - // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch -3: mflr r0 - stw r0,XLM_EMUL_OP_PROC(0) - - // Save stack pointer for EMUL_RETURN - stw r1,XLM_EMUL_RETURN_STACK(0) - - // Preset registers for ROM boot routine - lis r3,ASM_HA16(C_SYMBOL_NAME(ROMBase)) // Pointer to ROM boot structure: - lwz r3,ASM_LO16(C_SYMBOL_NAME(ROMBase))(r3) // r3 = ROMBase + 0x30d000 - addis r3,r3,ASM_HA16(0x30d000) - addi r3,r3,ASM_LO16(0x30d000) - - // 68k emulator is now active - li r0,MODE_68K - stw r0,XLM_RUN_MODE(0) - - // Jump to ROM - bctr - - -/* - * void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k) -C_SYMBOL_NAME(execute_68k): - // Create MacOS stack frame - mflr r0 - stw r0,4(r1) - stwu r1,-(56+19*4+18*8)(r1) - mfcr r0 - stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN - stw r0,52(r1) // save CR - - // Save PowerPC registers - stmw r13,56(r1) -#if SAVE_FP_EXEC_68K - stfd f14,56+19*4+0*8(r1) - stfd f15,56+19*4+1*8(r1) - stfd f16,56+19*4+2*8(r1) - stfd f17,56+19*4+3*8(r1) - stfd f18,56+19*4+4*8(r1) - stfd f19,56+19*4+5*8(r1) - stfd f20,56+19*4+6*8(r1) - stfd f21,56+19*4+7*8(r1) - stfd f22,56+19*4+8*8(r1) - stfd f23,56+19*4+9*8(r1) - stfd f24,56+19*4+10*8(r1) - stfd f25,56+19*4+11*8(r1) - stfd f26,56+19*4+12*8(r1) - stfd f27,56+19*4+13*8(r1) - stfd f28,56+19*4+14*8(r1) - stfd f29,56+19*4+15*8(r1) - stfd f30,56+19*4+16*8(r1) - stfd f31,56+19*4+17*8(r1) -#endif - - // Set up registers for 68k emulator - lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data - addi r31,r31,0x1000 - li r0,0 - mtcrf 0xff,r0 - creqv 11,11,11 // Supervisor mode - lwz r8,0*4(r4) // d[0]..d[7] - lwz r9,1*4(r4) - lwz r10,2*4(r4) - lwz r11,3*4(r4) - lwz r12,4*4(r4) - lwz r13,5*4(r4) - lwz r14,6*4(r4) - lwz r15,7*4(r4) - lwz r16,8*4(r4) // a[0]..a[6] - lwz r17,9*4(r4) - lwz r18,10*4(r4) - lwz r19,11*4(r4) - lwz r20,12*4(r4) - lwz r21,13*4(r4) - lwz r22,14*4(r4) - li r23,0 - mr r24,r3 - lwz r25,XLM_68K_R25(0) // MSB of SR - li r26,0 - li r28,0 // VBR - lwz r29,0x74(r31) // Pointer to opcode table - lwz r30,0x78(r31) // Address of emulator - - // Push return address (points to EXEC_RETURN opcode) on stack - li r0,XLM_EXEC_RETURN_OPCODE - stwu r0,-4(r1) - - // Reentering 68k emulator - li r0,MODE_68K - stw r0,XLM_RUN_MODE(0) - - // Set r0 to 0 for 68k emulator - li r0,0 - - // Execute 68k opcode - lha r27,0(r24) - rlwimi r29,r27,3,13,28 - lhau r27,2(r24) - mtlr r29 - blr - - -/* - * uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines - */ - -ASM_MACRO_START prolog - mflr r0 - stw r0,4(r1) - stwu r1,-64(r1) -ASM_MACRO_END - -ASM_MACRO_START epilog - lwz r0,64+4(r1) - mtlr r0 - addi r1,r1,64 - RESTORE_SYSTEM_R2 - RESTORE_SYSTEM_R13 - blr -ASM_MACRO_END - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos) -C_SYMBOL_NAME(call_macos): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1) -C_SYMBOL_NAME(call_macos1): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2) -C_SYMBOL_NAME(call_macos2): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - mr r4,r5 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3) -C_SYMBOL_NAME(call_macos3): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - mr r4,r5 - mr r5,r6 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4) -C_SYMBOL_NAME(call_macos4): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - mr r4,r5 - mr r5,r6 - mr r6,r7 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5) -C_SYMBOL_NAME(call_macos5): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - mr r4,r5 - mr r5,r6 - mr r6,r7 - mr r7,r8 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6) -C_SYMBOL_NAME(call_macos6): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - mr r4,r5 - mr r5,r6 - mr r6,r7 - mr r7,r8 - mr r8,r9 - bctrl - epilog - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7) -C_SYMBOL_NAME(call_macos7): - prolog - lwz r0,0(r3) // Get routine address - lwz r2,4(r3) // Load TOC pointer - mtctr r0 - mr r3,r4 - mr r4,r5 - mr r5,r6 - mr r6,r7 - mr r7,r8 - mr r8,r9 - mr r9,r10 - bctrl - epilog - - -/* - * Native resource manager patches - */ - -ASM_MACRO_START do_get_resource ASM_MACRO_ARG0_DEF - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,ASM_MACRO_ARG0(0) - lwz r2,XLM_RES_LIB_TOC(0) - mtctr r0 - bctrl - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - RESTORE_SYSTEM_R2 - RESTORE_SYSTEM_R13 - lwz r3,56(r1) - lha r4,56+6(r1) - lwz r5,56+8(r1) - bl C_SYMBOL_NAME(check_load_invoc) - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -ASM_MACRO_END - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource) -C_SYMBOL_NAME(get_resource): - do_get_resource XLM_GET_RESOURCE - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource) -C_SYMBOL_NAME(get_1_resource): - do_get_resource XLM_GET_1_RESOURCE - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource) -C_SYMBOL_NAME(get_ind_resource): - do_get_resource XLM_GET_IND_RESOURCE - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource) -C_SYMBOL_NAME(get_1_ind_resource): - do_get_resource XLM_GET_1_IND_RESOURCE - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource) -C_SYMBOL_NAME(r_get_resource): - do_get_resource XLM_R_GET_RESOURCE - -ASM_MACRO_START do_get_named_resource ASM_MACRO_ARG0_DEF - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,ASM_MACRO_ARG0(0) - lwz r2,XLM_RES_LIB_TOC(0) - mtctr r0 - bctrl - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - RESTORE_SYSTEM_R2 - RESTORE_SYSTEM_R13 - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl C_SYMBOL_NAME(named_check_load_invoc) - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -ASM_MACRO_END - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_named_resource) -C_SYMBOL_NAME(get_named_resource): - do_get_named_resource XLM_GET_NAMED_RESOURCE - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_named_resource) -C_SYMBOL_NAME(get_1_named_resource): - do_get_named_resource XLM_GET_1_NAMED_RESOURCE - - -/* - * void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt - */ - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt) -C_SYMBOL_NAME(ppc_interrupt): - mflr r0 - stw r0,4(r1) - stwu r1,-64(r1) - - // Get address of return routine - bl 1f - - // Return routine - lwz r0,64+4(r1) - mtlr r0 - addi r1,r1,64 - blr - - // Prepare registers for nanokernel interrupt routine -1: mtctr r1 - mr r1,r4 - stw r6,0x018(r1) - mfctr r6 - stw r6,0x004(r1) - lwz r6,0x65c(r1) - stw r7,0x13c(r6) - stw r8,0x144(r6) - stw r9,0x14c(r6) - stw r10,0x154(r6) - stw r11,0x15c(r6) - stw r12,0x164(r6) - stw r13,0x16c(r6) - - mflr r10 - mfcr r13 - lwz r7,0x660(r1) - mflr r12 - rlwimi. r7,r7,8,0,0 - li r11,0 - ori r11,r11,0xf072 // MSR (SRR1) - mtcrf 0x70,r11 - li r8,0 - - // Enter nanokernel - mtlr r3 - blr - - -/* - * Define signal handlers with alternate stack initialization magic - */ - -#define SIG_STACK_SIZE 0x10000 - -ASM_MACRO_START do_define_signal_handler \ - ASM_MACRO_ARG0_DEF /* name */ \ - ASM_MACRO_ARG1_DEF /* stack */ \ - ASM_MACRO_ARG2_DEF /* stack id */ \ - ASM_MACRO_ARG3_DEF /* signal handler */ - - // Alternate stack lower base for this signal handler - .lcomm ASM_MACRO_ARG1,SIG_STACK_SIZE,ASM_ALIGN_2(4) - ASM_TYPE(ASM_MACRO_ARG1,@object) - - // Represents the current nest level for this signal handler - // Note that in SheepShaver, SIGUSR2 signals are blocked while - // handling other signals so, it's unlikely we ever get a nest - // level greater than 1 - .lcomm ASM_MACRO_ARG2,4,ASM_ALIGN_2(2) - ASM_TYPE(ASM_MACRO_ARG2,@object) - - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ASM_MACRO_ARG0) -C_SYMBOL_NAME(ASM_MACRO_ARG0): - // Preserve args in scratch registers - mflr r14 - mr r15,r3 - mr r16,r4 - mr r17,r5 - mr r18,r1 - - // Atomically increase stack_id - lis r19,ASM_HA16(ASM_MACRO_ARG2) - la r19,ASM_LO16(ASM_MACRO_ARG2)(r19) - li r4,1 - mr r3,r19 - bl C_SYMBOL_NAME(atomic_add) - cmpwi r3,0 - bne- 1f - - // ID was 0, we can use the local stack - lis r9,ASM_HA16(ASM_MACRO_ARG1) - lis r3,(SIG_STACK_SIZE>>16) - la r9,ASM_LO16(ASM_MACRO_ARG1)(r9) - addi r3,r3,((SIG_STACK_SIZE&0xffff)-64) - add r1,r9,r3 - -1: // Invoke signal handler - stwu r1,-16(r1) - mr r3,r15 - mr r4,r16 - mr r5,r17 - bl C_SYMBOL_NAME(ASM_MACRO_ARG3) - addi r1,r1,16 - - // Atomically decrease stack id - mr r3,r19 - li r4,-1 - bl C_SYMBOL_NAME(atomic_add) - - // Restore kernel stack and return - mtlr r14 - mr r1,r18 - blr -ASM_MACRO_END - -#define DEFINE_SIGNAL_HANDLER(NAME) \ - do_define_signal_handler \ - NAME##_handler_init ASM_MACRO_ARG_SEP \ - NAME##_stack ASM_MACRO_ARG_SEP \ - NAME##_stack_id ASM_MACRO_ARG_SEP \ - NAME##_handler - -DEFINE_SIGNAL_HANDLER(sigusr2) diff --git a/SheepShaver/src/Unix/ppc_asm.tmpl b/SheepShaver/src/Unix/ppc_asm.tmpl deleted file mode 100644 index 75c03860..00000000 --- a/SheepShaver/src/Unix/ppc_asm.tmpl +++ /dev/null @@ -1,156 +0,0 @@ -/* Define usage of "reserved" registers */ -#if defined(__linux__) -#define SYSTEM_CLOBBERS_R2 1 /* Pointer to Thread Local Storage */ -#define SYSTEM_CLOBBERS_R13 1 /* Pointer to .sdata section */ -#endif - -#ifdef __ASSEMBLY__ -/* Helper macros */ -#ifdef SYSTEM_CLOBBERS_R2 -#define RESTORE_SYSTEM_R2 lwz r2,XLM_TOC(0) -#define SAVE_SYSTEM_R2 stw r2,XLM_TOC(0) -#else -#define RESTORE_SYSTEM_R2 -#define SAVE_SYSTEM_R2 -#endif -#ifdef SYSTEM_CLOBBERS_R13 -#define RESTORE_SYSTEM_R13 lwz r13,XLM_R13(0) -#define SAVE_SYSTEM_R13 stw r13,XLM_R13(0) -#else -#define RESTORE_SYSTEM_R13 -#define SAVE_SYSTEM_R13 -#endif - -/* Helper macros */ -#define xglue(x, y) x ## y -#define glue(x, y) xglue(x, y) - -/* Apple assembler perticularities */ -#if (defined(__APPLE__) && defined(__MACH__)) -#define C_SYMBOL_NAME(NAME) glue(_, NAME) -#define ASM_TYPE(NAME, TYPE) /* nothing */ -#define ASM_ALIGN_2(EXP) EXP -#define ASM_HA16(VAR) ha16(VAR) -#define ASM_LO16(VAR) lo16(VAR) -#define ASM_MACRO_END .endmacro -#define ASM_MACRO_ARG_SEP , -#define ASM_MACRO_ARG0_DEF /* nothing! */ -#define ASM_MACRO_ARG0 $0 -#define ASM_MACRO_ARG1_DEF /* nothing! */ -#define ASM_MACRO_ARG1 $1 -#define ASM_MACRO_ARG2_DEF /* nothing! */ -#define ASM_MACRO_ARG2 $2 -#define ASM_MACRO_ARG3_DEF /* nothing! */ -#define ASM_MACRO_ARG3 $3 -#endif - -/* Defaults for GNU assembler */ -#ifndef ASM_TYPE -#define ASM_TYPE(NAME, TYPE) .type NAME, TYPE -#endif -#ifndef ASM_ALIGN_2 -#define ASM_ALIGN_2(EXP) (1 << (EXP)) -#endif -#ifndef ASM_HA16 -#define ASM_HA16(VAR) VAR@ha -#endif -#ifndef ASM_LO16 -#define ASM_LO16(VAR) VAR@l -#endif -#ifndef ASM_MACRO_START -#define ASM_MACRO_START .macro -#endif -#ifndef ASM_MACRO_END -#define ASM_MACRO_END .endm -#endif -#ifndef ASM_MACRO_ARG_SEP -#define ASM_MACRO_ARG_SEP -#endif -#ifndef ASM_MACRO_ARG0_DEF -#define ASM_MACRO_ARG0_DEF __asm_macro_arg0 -#define ASM_MACRO_ARG0 \__asm_macro_arg0 -#define ASM_MACRO_ARG1_DEF , __asm_macro_arg1 -#define ASM_MACRO_ARG1 \__asm_macro_arg1 -#define ASM_MACRO_ARG2_DEF , __asm_macro_arg2 -#define ASM_MACRO_ARG2 \__asm_macro_arg2 -#define ASM_MACRO_ARG3_DEF , __asm_macro_arg3 -#define ASM_MACRO_ARG3 \__asm_macro_arg3 -#endif -#ifndef C_SYMBOL_NAME -#define C_SYMBOL_NAME(NAME) NAME -#endif -#ifndef ASM_GLOBAL_DIRECTIVE -#define ASM_GLOBAL_DIRECTIVE .globl -#endif - -/* Register names */ -#if defined(__linux__) || defined(__NetBSD__) -#define r0 0 -#define r1 1 -#define r2 2 -#define r3 3 -#define r4 4 -#define r5 5 -#define r6 6 -#define r7 7 -#define r8 8 -#define r9 9 -#define r10 10 -#define r11 11 -#define r12 12 -#define r13 13 -#define r14 14 -#define r15 15 -#define r16 16 -#define r17 17 -#define r18 18 -#define r19 19 -#define r20 20 -#define r21 21 -#define r22 22 -#define r23 23 -#define r24 24 -#define r25 25 -#define r26 26 -#define r27 27 -#define r28 28 -#define r29 29 -#define r30 30 -#define r31 31 -#endif - -#if defined(__linux__) || defined(__NetBSD__) -#define f0 0 -#define f1 1 -#define f2 2 -#define f3 3 -#define f4 4 -#define f5 5 -#define f6 6 -#define f7 7 -#define f8 8 -#define f9 9 -#define f10 10 -#define f11 11 -#define f12 12 -#define f13 13 -#define f14 14 -#define f15 15 -#define f16 16 -#define f17 17 -#define f18 18 -#define f19 19 -#define f20 20 -#define f21 21 -#define f22 22 -#define f23 23 -#define f24 24 -#define f25 25 -#define f26 26 -#define f27 27 -#define f28 28 -#define f29 29 -#define f30 30 -#define f31 31 -#endif -#endif diff --git a/SheepShaver/src/Unix/prefs_editor_gtk.cpp b/SheepShaver/src/Unix/prefs_editor_gtk.cpp deleted file mode 100644 index b092e824..00000000 --- a/SheepShaver/src/Unix/prefs_editor_gtk.cpp +++ /dev/null @@ -1,1594 +0,0 @@ -/* - * prefs_editor_linux.cpp - Preferences editor, Linux implementation using GTK+ - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "user_strings.h" -#include "version.h" -#include "cdrom.h" -#include "xpram.h" -#include "prefs.h" -#include "prefs_editor.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -static GtkWidget *win; // Preferences window -static bool start_clicked = false; // Return value of PrefsEditor() function -static int screen_width, screen_height; // Screen dimensions - - -// Prototypes -static void create_volumes_pane(GtkWidget *top); -static void create_graphics_pane(GtkWidget *top); -static void create_input_pane(GtkWidget *top); -static void create_serial_pane(GtkWidget *top); -static void create_memory_pane(GtkWidget *top); -static void create_jit_pane(GtkWidget *top); -static void read_settings(void); - - -/* - * Utility functions - */ - -#if ! GLIB_CHECK_VERSION(2,0,0) -#define G_OBJECT(obj) GTK_OBJECT(obj) -#define g_object_get_data(obj, key) gtk_object_get_data((obj), (key)) -#define g_object_set_data(obj, key, data) gtk_object_set_data((obj), (key), (data)) -#endif - -struct opt_desc { - int label_id; - GtkSignalFunc func; -}; - -struct combo_desc { - int label_id; -}; - -struct file_req_assoc { - file_req_assoc(GtkWidget *r, GtkWidget *e) : req(r), entry(e) {} - GtkWidget *req; - GtkWidget *entry; -}; - -static void cb_browse_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (char *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - gtk_entry_set_text(GTK_ENTRY(assoc->entry), file); - gtk_widget_destroy(assoc->req); - delete assoc; -} - -static void cb_browse(GtkWidget *widget, void *user_data) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_BROWSE_TITLE)); - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(cb_browse_ok), new file_req_assoc(req, (GtkWidget *)user_data)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -static GtkWidget *make_browse_button(GtkWidget *entry) -{ - GtkWidget *button; - - button = gtk_button_new_with_label(GetString(STR_BROWSE_CTRL)); - gtk_widget_show(button); - gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc)cb_browse, (void *)entry); - return button; -} - -static void add_menu_item(GtkWidget *menu, int label_id, GtkSignalFunc func) -{ - GtkWidget *item = gtk_menu_item_new_with_label(GetString(label_id)); - gtk_widget_show(item); - gtk_signal_connect(GTK_OBJECT(item), "activate", func, NULL); - gtk_menu_append(GTK_MENU(menu), item); -} - -static GtkWidget *make_pane(GtkWidget *notebook, int title_id) -{ - GtkWidget *frame, *label, *box; - - frame = gtk_frame_new(NULL); - gtk_container_border_width(GTK_CONTAINER(frame), 4); - - box = gtk_vbox_new(FALSE, 4); - gtk_container_set_border_width(GTK_CONTAINER(box), 4); - gtk_container_add(GTK_CONTAINER(frame), box); - - gtk_widget_show_all(frame); - - label = gtk_label_new(GetString(title_id)); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); - return box; -} - -static GtkWidget *make_button_box(GtkWidget *top, int border, const opt_desc *buttons) -{ - GtkWidget *bb, *button; - - bb = gtk_hbutton_box_new(); - gtk_widget_show(bb); - gtk_container_set_border_width(GTK_CONTAINER(bb), border); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bb), GTK_BUTTONBOX_DEFAULT_STYLE); - gtk_button_box_set_spacing(GTK_BUTTON_BOX(bb), 4); - gtk_box_pack_start(GTK_BOX(top), bb, FALSE, FALSE, 0); - - while (buttons->label_id) { - button = gtk_button_new_with_label(GetString(buttons->label_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", buttons->func, NULL); - gtk_box_pack_start(GTK_BOX(bb), button, TRUE, TRUE, 0); - buttons++; - } - return bb; -} - -static GtkWidget *make_separator(GtkWidget *top) -{ - GtkWidget *sep = gtk_hseparator_new(); - gtk_box_pack_start(GTK_BOX(top), sep, FALSE, FALSE, 0); - gtk_widget_show(sep); - return sep; -} - -static GtkWidget *make_table(GtkWidget *top, int x, int y) -{ - GtkWidget *table = gtk_table_new(x, y, FALSE); - gtk_widget_show(table); - gtk_box_pack_start(GTK_BOX(top), table, FALSE, FALSE, 0); - return table; -} - -static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active) -{ - GtkWidget *label, *opt, *menu; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - - while (options->label_id) { - add_menu_item(menu, options->label_id, options->func); - options++; - } - gtk_menu_set_active(GTK_MENU(menu), active); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - return menu; -} - -static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist) -{ - GtkWidget *label, *combo; - char str[32]; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - return combo; -} - -static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options) -{ - GList *glist = NULL; - while (options->label_id) { - glist = g_list_append(glist, (void *)GetString(options->label_id)); - options++; - } - - return table_make_combobox(table, row, label_id, default_value, glist); -} - -static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false) -{ - GtkWidget *box, *label, *entry, *button; - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - const char *str = PrefsFindString(prefs_item); - if (str == NULL) - str = ""; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - entry = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_widget_show(entry); - gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); - - button = make_browse_button(entry); - gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(entry), "chooser_button", button); - return entry; -} - -static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active) -{ - GtkWidget *box, *label, *opt, *menu; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - - while (options->label_id) { - add_menu_item(menu, options->label_id, options->func); - options++; - } - gtk_menu_set_active(GTK_MENU(menu), active); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_box_pack_start(GTK_BOX(box), opt, FALSE, FALSE, 0); - return menu; -} - -static GtkWidget *make_entry(GtkWidget *top, int label_id, const char *prefs_item) -{ - GtkWidget *box, *label, *entry; - - box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_box_pack_start(GTK_BOX(top), box, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(label_id)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - entry = gtk_entry_new(); - gtk_widget_show(entry); - const char *str = PrefsFindString(prefs_item); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); - return entry; -} - -static const gchar *get_file_entry_path(GtkWidget *entry) -{ - return gtk_entry_get_text(GTK_ENTRY(entry)); -} - -static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func) -{ - GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id)); - gtk_widget_show(button); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), PrefsFindBool(prefs_item)); - gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button); - gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0); - return button; -} - -static GtkWidget *make_checkbox(GtkWidget *top, int label_id, bool active, GtkSignalFunc func) -{ - GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id)); - gtk_widget_show(button); - gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), active); - gtk_signal_connect(GTK_OBJECT(button), "toggled", func, button); - gtk_box_pack_start(GTK_BOX(top), button, FALSE, FALSE, 0); - return button; -} - - -/* - * Show preferences editor - * Returns true when user clicked on "Start", false otherwise - */ - -// Window closed -static gint window_closed(void) -{ - return FALSE; -} - -// Window destroyed -static void window_destroyed(void) -{ - gtk_main_quit(); -} - -// "Start" button clicked -static void cb_start(...) -{ - start_clicked = true; - read_settings(); - SavePrefs(); - gtk_widget_destroy(win); -} - -// "Quit" button clicked -static void cb_quit(...) -{ - start_clicked = false; - gtk_widget_destroy(win); -} - -// "OK" button of "About" dialog clicked -static void dl_quit(GtkWidget *dialog) -{ - gtk_widget_destroy(dialog); -} - -// "About" selected -static void mn_about(...) -{ - GtkWidget *dialog, *label, *button; - - char str[512]; - sprintf(str, - "SheepShaver\nVersion %d.%d\n\n" - "Copyright (C) 1997-2008 Christian Bauer and Marc Hellwig\n" - "E-mail: cb@cebix.net\n" - "http://sheepshaver.cebix.net/\n\n" - "SheepShaver comes with ABSOLUTELY NO\n" - "WARRANTY. This is free software, and\n" - "you are welcome to redistribute it\n" - "under the terms of the GNU General\n" - "Public License.\n", - VERSION_MAJOR, VERSION_MINOR - ); - - dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(STR_ABOUT_TITLE)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - - label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - button = gtk_button_new_with_label(GetString(STR_OK_BUTTON)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - gtk_widget_show(dialog); -} - -// "Zap NVRAM" selected -static void mn_zap_pram(...) -{ - ZapPRAM(); -} - -// Menu item descriptions -static GtkItemFactoryEntry menu_items[] = { - {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "S", GTK_SIGNAL_FUNC(cb_start), 0, NULL}, - {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(mn_zap_pram), 0, NULL}, - {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL}, - {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(mn_about), 0, NULL} -}; - -bool PrefsEditor(void) -{ - // Get screen dimensions - screen_width = gdk_screen_width(); - screen_height = gdk_screen_height(); - - // Create window - win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(win), GetString(STR_PREFS_TITLE)); - gtk_signal_connect(GTK_OBJECT(win), "delete_event", GTK_SIGNAL_FUNC(window_closed), NULL); - gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(window_destroyed), NULL); - - // Create window contents - GtkWidget *box = gtk_vbox_new(FALSE, 4); - gtk_widget_show(box); - gtk_container_add(GTK_CONTAINER(win), box); - - GtkAccelGroup *accel_group = gtk_accel_group_new(); - GtkItemFactory *item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "

", accel_group); - gtk_item_factory_create_items(item_factory, sizeof(menu_items) / sizeof(menu_items[0]), menu_items, NULL); -#if GTK_CHECK_VERSION(1,3,15) - gtk_window_add_accel_group(GTK_WINDOW(win), accel_group); -#else - gtk_accel_group_attach(accel_group, GTK_OBJECT(win)); -#endif - GtkWidget *menu_bar = gtk_item_factory_get_widget(item_factory, "
"); - gtk_widget_show(menu_bar); - gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, TRUE, 0); - - GtkWidget *notebook = gtk_notebook_new(); - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); - gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), FALSE); - gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0); - gtk_widget_realize(notebook); - - create_volumes_pane(notebook); - create_graphics_pane(notebook); - create_input_pane(notebook); - create_serial_pane(notebook); - create_memory_pane(notebook); - create_jit_pane(notebook); - gtk_widget_show(notebook); - - static const opt_desc buttons[] = { - {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)}, - {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)}, - {0, NULL} - }; - make_button_box(box, 4, buttons); - - // Show window and enter main loop - gtk_widget_show(win); - gtk_main(); - return start_clicked; -} - - -/* - * "Volumes" pane - */ - -static GtkWidget *volume_list, *w_extfs; -static int selected_volume; - -// Volume in list selected -static void cl_selected(GtkWidget *list, int row, int column) -{ - selected_volume = row; -} - -// Volume selected for addition -static void add_volume_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - gtk_clist_append(GTK_CLIST(volume_list), &file); - gtk_widget_destroy(assoc->req); - delete assoc; -} - -// Volume selected for creation -static void create_volume_ok(GtkWidget *button, file_req_assoc *assoc) -{ - gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); - - const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry)); - int size = atoi(str); - - char cmd[1024]; - sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size); - int ret = system(cmd); - if (ret == 0) - gtk_clist_append(GTK_CLIST(volume_list), &file); - gtk_widget_destroy(GTK_WIDGET(assoc->req)); - delete assoc; -} - -// "Add Volume" button clicked -static void cb_add_volume(...) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_ADD_VOLUME_TITLE)); - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(add_volume_ok), new file_req_assoc(req, NULL)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -// "Create Hardfile" button clicked -static void cb_create_volume(...) -{ - GtkWidget *req = gtk_file_selection_new(GetString(STR_CREATE_VOLUME_TITLE)); - - GtkWidget *box = gtk_hbox_new(FALSE, 4); - gtk_widget_show(box); - GtkWidget *label = gtk_label_new(GetString(STR_HARDFILE_SIZE_CTRL)); - gtk_widget_show(label); - GtkWidget *entry = gtk_entry_new(); - gtk_widget_show(entry); - char str[32]; - sprintf(str, "%d", 40); - gtk_entry_set_text(GTK_ENTRY(entry), str); - gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(req)->main_vbox), box, FALSE, FALSE, 0); - - gtk_signal_connect_object(GTK_OBJECT(req), "delete_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(req)->ok_button), "clicked", GTK_SIGNAL_FUNC(create_volume_ok), new file_req_assoc(req, entry)); - gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(req)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(req)); - gtk_widget_show(req); -} - -// "Remove Volume" button clicked -static void cb_remove_volume(...) -{ - gtk_clist_remove(GTK_CLIST(volume_list), selected_volume); -} - -// "Boot From" selected -static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);} -static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);} - -// "No CD-ROM Driver" button toggled -static void tb_nocdrom(GtkWidget *widget) -{ - PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Read settings from widgets and set preferences -static void read_volumes_settings(void) -{ - while (PrefsFindString("disk")) - PrefsRemoveItem("disk"); - - for (int i=0; irows; i++) { - char *str; - gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str); - PrefsAddString("disk", str); - } - - PrefsReplaceString("extfs", gtk_entry_get_text(GTK_ENTRY(w_extfs))); -} - -// Create "Volumes" pane -static void create_volumes_pane(GtkWidget *top) -{ - GtkWidget *box, *scroll, *menu; - - box = make_pane(top, STR_VOLUMES_PANE_TITLE); - - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_show(scroll); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - volume_list = gtk_clist_new(1); - gtk_widget_show(volume_list); - gtk_clist_set_selection_mode(GTK_CLIST(volume_list), GTK_SELECTION_SINGLE); - gtk_clist_set_shadow_type(GTK_CLIST(volume_list), GTK_SHADOW_NONE); - gtk_clist_set_reorderable(GTK_CLIST(volume_list), true); - gtk_signal_connect(GTK_OBJECT(volume_list), "select_row", GTK_SIGNAL_FUNC(cl_selected), NULL); - char *str; - int32 index = 0; - while ((str = (char *)PrefsFindString("disk", index++)) != NULL) - gtk_clist_append(GTK_CLIST(volume_list), &str); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), volume_list); - gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0); - selected_volume = 0; - - static const opt_desc buttons[] = { - {STR_ADD_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_add_volume)}, - {STR_CREATE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_create_volume)}, - {STR_REMOVE_VOLUME_BUTTON, GTK_SIGNAL_FUNC(cb_remove_volume)}, - {0, NULL}, - }; - make_button_box(box, 0, buttons); - make_separator(box); - - w_extfs = make_entry(box, STR_EXTFS_CTRL, "extfs"); - - static const opt_desc options[] = { - {STR_BOOT_ANY_LAB, GTK_SIGNAL_FUNC(mn_boot_any)}, - {STR_BOOT_CDROM_LAB, GTK_SIGNAL_FUNC(mn_boot_cdrom)}, - {0, NULL} - }; - int bootdriver = PrefsFindInt32("bootdriver"), active = 0; - switch (bootdriver) { - case 0: active = 0; break; - case CDROMRefNum: active = 1; break; - } - menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active); - - make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom)); -} - - -/* - * "JIT Compiler" pane - */ - -// Are we running a JIT capable CPU? -static bool is_jit_capable(void) -{ -#if USE_JIT - return true; -#elif defined __APPLE__ && defined __MACH__ - // XXX run-time detect so that we can use a PPC GUI prefs editor - static char cpu[10]; - if (cpu[0] == 0) { - FILE *fp = popen("uname -p", "r"); - if (fp == NULL) - return false; - fgets(cpu, sizeof(cpu) - 1, fp); - fclose(fp); - } - if (cpu[0] == 'i' && cpu[2] == '8' && cpu[3] == '6') // XXX assuming i?86 - return true; -#endif - return false; -} - -// Set sensitivity of widgets -static void set_jit_sensitive(void) -{ - const bool jit_enabled = PrefsFindBool("jit"); -} - -// "Use JIT Compiler" button toggled -static void tb_jit(GtkWidget *widget) -{ - PrefsReplaceBool("jit", GTK_TOGGLE_BUTTON(widget)->active); - set_jit_sensitive(); -} - -// Read settings from widgets and set preferences -static void read_jit_settings(void) -{ - bool jit_enabled = is_jit_capable() && PrefsFindBool("jit"); -} - -// "Use built-in 68k DR emulator" button toggled -static void tb_jit_68k(GtkWidget *widget) -{ - PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Create "JIT Compiler" pane -static void create_jit_pane(GtkWidget *top) -{ - GtkWidget *box, *table, *label, *menu; - char str[32]; - - box = make_pane(top, STR_JIT_PANE_TITLE); - - if (is_jit_capable()) { - make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit)); - set_jit_sensitive(); - } - - make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k)); -} - - -/* - * "Graphics/Sound" pane - */ - -// Display types -enum { - DISPLAY_WINDOW, - DISPLAY_SCREEN -}; - -static GtkWidget *w_frameskip, *w_display_x, *w_display_y; -static GtkWidget *l_frameskip, *l_display_x, *l_display_y; -static int display_type; -static int dis_width, dis_height; -static bool is_fbdev_dga_mode = false; - -static GtkWidget *w_dspdevice_file, *w_mixerdevice_file; - -// Hide/show graphics widgets -static void hide_show_graphics_widgets(void) -{ - switch (display_type) { - case DISPLAY_WINDOW: - gtk_widget_show(w_frameskip); gtk_widget_show(l_frameskip); - break; - case DISPLAY_SCREEN: - gtk_widget_hide(w_frameskip); gtk_widget_hide(l_frameskip); - break; - } -} - -// "Window" video type selected -static void mn_window(...) -{ - display_type = DISPLAY_WINDOW; - hide_show_graphics_widgets(); -} - -// "Fullscreen" video type selected -static void mn_fullscreen(...) -{ - display_type = DISPLAY_SCREEN; - hide_show_graphics_widgets(); -} - -// "5 Hz".."60Hz" selected -static void mn_5hz(...) {PrefsReplaceInt32("frameskip", 12);} -static void mn_7hz(...) {PrefsReplaceInt32("frameskip", 8);} -static void mn_10hz(...) {PrefsReplaceInt32("frameskip", 6);} -static void mn_15hz(...) {PrefsReplaceInt32("frameskip", 4);} -static void mn_30hz(...) {PrefsReplaceInt32("frameskip", 2);} -static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);} - -// QuickDraw acceleration -static void tb_gfxaccel(GtkWidget *widget) -{ - PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Set sensitivity of widgets -static void set_graphics_sensitive(void) -{ - const bool sound_enabled = !PrefsFindBool("nosound"); - gtk_widget_set_sensitive(w_dspdevice_file, sound_enabled); - gtk_widget_set_sensitive(w_mixerdevice_file, sound_enabled); -} - -// "Disable Sound Output" button toggled -static void tb_nosound(GtkWidget *widget) -{ - PrefsReplaceBool("nosound", GTK_TOGGLE_BUTTON(widget)->active); - set_graphics_sensitive(); -} - -// Read and convert graphics preferences -static void parse_graphics_prefs(void) -{ - display_type = DISPLAY_WINDOW; - dis_width = 640; - dis_height = 480; - - const char *str = PrefsFindString("screen"); - if (str) { - if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2) - display_type = DISPLAY_WINDOW; - else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2) - display_type = DISPLAY_SCREEN; -#ifdef ENABLE_FBDEV_DGA - else if (sscanf(str, "fbdev/%d/%d", &dis_width, &dis_height) == 2) { - is_fbdev_dga_mode = true; - display_type = DISPLAY_SCREEN; - } -#endif - } - else { - uint32 window_modes = PrefsFindInt32("windowmodes"); - uint32 screen_modes = PrefsFindInt32("screenmodes"); - if (screen_modes) { - display_type = DISPLAY_SCREEN; - static const struct { - int id; - int width; - int height; - } - modes[] = { - { 1, 640, 480 }, - { 2, 800, 600 }, - { 4, 1024, 768 }, - { 64, 1152, 768 }, - { 8, 1152, 900 }, - { 16, 1280, 1024 }, - { 32, 1600, 1200 }, - { 0, } - }; - for (int i = 0; modes[i].id != 0; i++) { - if (screen_modes & modes[i].id) { - if (modes[i].width <= screen_width && modes[i].height <= screen_height) { - dis_width = modes[i].width; - dis_height = modes[i].height; - } - } - } - } - else if (window_modes) { - display_type = DISPLAY_WINDOW; - if (window_modes & 1) - dis_width = 640, dis_height = 480; - if (window_modes & 2) - dis_width = 800, dis_height = 600; - } - } - if (dis_width == screen_width) - dis_width = 0; - if (dis_height == screen_height) - dis_height = 0; -} - -// Read settings from widgets and set preferences -static void read_graphics_settings(void) -{ - const char *str; - - str = gtk_entry_get_text(GTK_ENTRY(w_display_x)); - dis_width = atoi(str); - - str = gtk_entry_get_text(GTK_ENTRY(w_display_y)); - dis_height = atoi(str); - - char pref[256]; - bool use_screen_mode = true; - switch (display_type) { - case DISPLAY_WINDOW: - sprintf(pref, "win/%d/%d", dis_width, dis_height); - break; - case DISPLAY_SCREEN: - sprintf(pref, "dga/%d/%d", dis_width, dis_height); - break; - default: - use_screen_mode = false; - PrefsRemoveItem("screen"); - return; - } - if (use_screen_mode) { - PrefsReplaceString("screen", pref); - // Old prefs are now migrated - PrefsRemoveItem("windowmodes"); - PrefsRemoveItem("screenmodes"); - } - - PrefsReplaceString("dsp", get_file_entry_path(w_dspdevice_file)); - PrefsReplaceString("mixer", get_file_entry_path(w_mixerdevice_file)); -} - -// Create "Graphics/Sound" pane -static void create_graphics_pane(GtkWidget *top) -{ - GtkWidget *box, *table, *label, *opt, *menu, *combo; - char str[32]; - - parse_graphics_prefs(); - - box = make_pane(top, STR_GRAPHICS_SOUND_PANE_TITLE); - table = make_table(box, 2, 4); - - label = gtk_label_new(GetString(STR_VIDEO_TYPE_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - opt = gtk_option_menu_new(); - gtk_widget_show(opt); - menu = gtk_menu_new(); - add_menu_item(menu, STR_WINDOW_CTRL, GTK_SIGNAL_FUNC(mn_window)); - add_menu_item(menu, STR_FULLSCREEN_CTRL, GTK_SIGNAL_FUNC(mn_fullscreen)); - switch (display_type) { - case DISPLAY_WINDOW: - gtk_menu_set_active(GTK_MENU(menu), 0); - break; - case DISPLAY_SCREEN: - gtk_menu_set_active(GTK_MENU(menu), 1); - break; - } - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - - l_frameskip = gtk_label_new(GetString(STR_FRAMESKIP_CTRL)); - gtk_widget_show(l_frameskip); - gtk_table_attach(GTK_TABLE(table), l_frameskip, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - w_frameskip = gtk_option_menu_new(); - gtk_widget_show(w_frameskip); - menu = gtk_menu_new(); - add_menu_item(menu, STR_REF_5HZ_LAB, GTK_SIGNAL_FUNC(mn_5hz)); - add_menu_item(menu, STR_REF_7_5HZ_LAB, GTK_SIGNAL_FUNC(mn_7hz)); - add_menu_item(menu, STR_REF_10HZ_LAB, GTK_SIGNAL_FUNC(mn_10hz)); - add_menu_item(menu, STR_REF_15HZ_LAB, GTK_SIGNAL_FUNC(mn_15hz)); - add_menu_item(menu, STR_REF_30HZ_LAB, GTK_SIGNAL_FUNC(mn_30hz)); - add_menu_item(menu, STR_REF_60HZ_LAB, GTK_SIGNAL_FUNC(mn_60hz)); - int frameskip = PrefsFindInt32("frameskip"); - int item = -1; - switch (frameskip) { - case 12: item = 0; break; - case 8: item = 1; break; - case 6: item = 2; break; - case 4: item = 3; break; - case 2: item = 4; break; - case 1: item = 5; break; - case 0: item = 5; break; - } - if (item >= 0) - gtk_menu_set_active(GTK_MENU(menu), item); - gtk_option_menu_set_menu(GTK_OPTION_MENU(w_frameskip), menu); - gtk_table_attach(GTK_TABLE(table), w_frameskip, 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - - l_display_x = gtk_label_new(GetString(STR_DISPLAY_X_CTRL)); - gtk_widget_show(l_display_x); - gtk_table_attach(GTK_TABLE(table), l_display_x, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - GList *glist1 = NULL; - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_512_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_640_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_800_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_1024_LAB)); - glist1 = g_list_append(glist1, (void *)GetString(STR_SIZE_MAX_LAB)); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist1); - if (dis_width) - sprintf(str, "%d", dis_width); - else - strcpy(str, GetString(STR_SIZE_MAX_LAB)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - w_display_x = GTK_COMBO(combo)->entry; - - l_display_y = gtk_label_new(GetString(STR_DISPLAY_Y_CTRL)); - gtk_widget_show(l_display_y); - gtk_table_attach(GTK_TABLE(table), l_display_y, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - GList *glist2 = NULL; - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_384_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_480_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_600_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_768_LAB)); - glist2 = g_list_append(glist2, (void *)GetString(STR_SIZE_MAX_LAB)); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist2); - if (dis_height) - sprintf(str, "%d", dis_height); - else - strcpy(str, GetString(STR_SIZE_MAX_LAB)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); - w_display_y = GTK_COMBO(combo)->entry; - - make_checkbox(box, STR_GFXACCEL_CTRL, PrefsFindBool("gfxaccel"), GTK_SIGNAL_FUNC(tb_gfxaccel)); - - make_separator(box); - make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound)); - w_dspdevice_file = make_entry(box, STR_DSPDEVICE_FILE_CTRL, "dsp"); - w_mixerdevice_file = make_entry(box, STR_MIXERDEVICE_FILE_CTRL, "mixer"); - - set_graphics_sensitive(); - - hide_show_graphics_widgets(); -} - - -/* - * "Input" pane - */ - -static GtkWidget *w_keycode_file; -static GtkWidget *w_mouse_wheel_lines; - -// Set sensitivity of widgets -static void set_input_sensitive(void) -{ - const bool use_keycodes = PrefsFindBool("keycodes"); - gtk_widget_set_sensitive(w_keycode_file, use_keycodes); - gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes); - gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1); -} - -// "Use Raw Keycodes" button toggled -static void tb_keycodes(GtkWidget *widget) -{ - PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active); - set_input_sensitive(); -} - -// "Mouse Wheel Mode" selected -static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();} -static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();} - -// Read settings from widgets and set preferences -static void read_input_settings(void) -{ - const char *str = get_file_entry_path(w_keycode_file); - if (str && strlen(str)) - PrefsReplaceString("keycodefile", str); - else - PrefsRemoveItem("keycodefile"); - - PrefsReplaceInt32("mousewheellines", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w_mouse_wheel_lines))); -} - -// Create "Input" pane -static void create_input_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *menu, *label, *button; - GtkObject *adj; - - box = make_pane(top, STR_INPUT_PANE_TITLE); - - make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes)); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_KEYCODES_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - const char *str = PrefsFindString("keycodefile"); - if (str == NULL) - str = ""; - - w_keycode_file = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str); - gtk_widget_show(w_keycode_file); - gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0); - - button = make_browse_button(w_keycode_file); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button); - - make_separator(box); - - static const opt_desc options[] = { - {STR_MOUSEWHEELMODE_PAGE_LAB, GTK_SIGNAL_FUNC(mn_wheel_page)}, - {STR_MOUSEWHEELMODE_CURSOR_LAB, GTK_SIGNAL_FUNC(mn_wheel_cursor)}, - {0, NULL} - }; - int wheelmode = PrefsFindInt32("mousewheelmode"), active = 0; - switch (wheelmode) { - case 0: active = 0; break; - case 1: active = 1; break; - } - menu = make_option_menu(box, STR_MOUSEWHEELMODE_CTRL, options, active); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); - - label = gtk_label_new(GetString(STR_MOUSEWHEELLINES_CTRL)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - adj = gtk_adjustment_new(PrefsFindInt32("mousewheellines"), 1, 1000, 1, 5, 0); - w_mouse_wheel_lines = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 0.0, 0); - gtk_widget_show(w_mouse_wheel_lines); - gtk_box_pack_start(GTK_BOX(hbox), w_mouse_wheel_lines, FALSE, FALSE, 0); - - set_input_sensitive(); -} - - -/* - * "Serial/Network" pane - */ - -static GtkWidget *w_seriala, *w_serialb, *w_ether; - -// Read settings from widgets and set preferences -static void read_serial_settings(void) -{ - const char *str; - - str = gtk_entry_get_text(GTK_ENTRY(w_seriala)); - PrefsReplaceString("seriala", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_serialb)); - PrefsReplaceString("serialb", str); - - str = gtk_entry_get_text(GTK_ENTRY(w_ether)); - if (str && strlen(str)) - PrefsReplaceString("ether", str); - else - PrefsRemoveItem("ether"); -} - -// Add names of serial devices -static gint gl_str_cmp(gconstpointer a, gconstpointer b) -{ - return strcmp((char *)a, (char *)b); -} - -static GList *add_serial_names(void) -{ - GList *glist = NULL; - - // Search /dev for ttyS* and lp* - DIR *d = opendir("/dev"); - if (d) { - struct dirent *de; - while ((de = readdir(d)) != NULL) { -#if defined(__linux__) - if (strncmp(de->d_name, "ttyS", 4) == 0 || strncmp(de->d_name, "lp", 2) == 0) { -#elif defined(__FreeBSD__) - if (strncmp(de->d_name, "cuaa", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) { -#elif defined(__NetBSD__) - if (strncmp(de->d_name, "tty0", 4) == 0 || strncmp(de->d_name, "lpt", 3) == 0) { -#elif defined(sgi) - if (strncmp(de->d_name, "ttyf", 4) == 0 || strncmp(de->d_name, "plp", 3) == 0) { -#else - if (false) { -#endif - char *str = new char[64]; - sprintf(str, "/dev/%s", de->d_name); - glist = g_list_append(glist, str); - } - } - closedir(d); - } - if (glist) - g_list_sort(glist, gl_str_cmp); - else - glist = g_list_append(glist, (void *)""); - return glist; -} - -// Add names of ethernet interfaces -static GList *add_ether_names(void) -{ - GList *glist = NULL; - - // Get list of all Ethernet interfaces - int s = socket(PF_INET, SOCK_DGRAM, 0); - if (s >= 0) { - char inbuf[8192]; - struct ifconf ifc; - ifc.ifc_len = sizeof(inbuf); - ifc.ifc_buf = inbuf; - if (ioctl(s, SIOCGIFCONF, &ifc) == 0) { - struct ifreq req, *ifr = ifc.ifc_req; - for (int i=0; iifr_name, 63); - glist = g_list_append(glist, str); - } - } - } - close(s); - } -#ifdef HAVE_SLIRP - static char s_slirp[] = "slirp"; - glist = g_list_append(glist, s_slirp); -#endif - if (glist) - g_list_sort(glist, gl_str_cmp); - else - glist = g_list_append(glist, (void *)""); - return glist; -} - -// Create "Serial/Network" pane -static void create_serial_pane(GtkWidget *top) -{ - GtkWidget *box, *table, *label, *combo; - GList *glist = add_serial_names(); - - box = make_pane(top, STR_SERIAL_NETWORK_PANE_TITLE); - table = make_table(box, 2, 3); - - label = gtk_label_new(GetString(STR_SERPORTA_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - const char *str = PrefsFindString("seriala"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_seriala = GTK_COMBO(combo)->entry; - - label = gtk_label_new(GetString(STR_SERPORTB_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - str = PrefsFindString("serialb"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_serialb = GTK_COMBO(combo)->entry; - - label = gtk_label_new(GetString(STR_ETHERNET_IF_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - glist = add_ether_names(); - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - str = PrefsFindString("ether"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - w_ether = GTK_COMBO(combo)->entry; -} - - -/* - * "Memory/Misc" pane - */ - -static GtkWidget *w_ramsize; -static GtkWidget *w_rom_file; - -// Don't use CPU when idle? -static void tb_idlewait(GtkWidget *widget) -{ - PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active); -} - -// "Ignore SEGV" button toggled -static void tb_ignoresegv(GtkWidget *widget) -{ - PrefsReplaceBool("ignoresegv", GTK_TOGGLE_BUTTON(widget)->active); -} - -// Read settings from widgets and set preferences -static void read_memory_settings(void) -{ - const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry)); - PrefsReplaceInt32("ramsize", atoi(str) << 20); - - str = gtk_entry_get_text(GTK_ENTRY(w_rom_file)); - if (str && strlen(str)) - PrefsReplaceString("rom", str); - else - PrefsRemoveItem("rom"); -} - -// Create "Memory/Misc" pane -static void create_memory_pane(GtkWidget *top) -{ - GtkWidget *box, *hbox, *table, *label, *menu; - - box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE); - table = make_table(box, 2, 5); - - static const combo_desc options[] = { - STR_RAMSIZE_4MB_LAB, - STR_RAMSIZE_8MB_LAB, - STR_RAMSIZE_16MB_LAB, - STR_RAMSIZE_32MB_LAB, - STR_RAMSIZE_64MB_LAB, - STR_RAMSIZE_128MB_LAB, - STR_RAMSIZE_256MB_LAB, - STR_RAMSIZE_512MB_LAB, - STR_RAMSIZE_1024MB_LAB, - 0 - }; - char default_ramsize[16]; - sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20); - w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options); - - w_rom_file = table_make_file_entry(table, 1, STR_ROM_FILE_CTRL, "rom"); - - make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv)); - make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait)); -} - - -/* - * Read settings from widgets and set preferences - */ - -static void read_settings(void) -{ - read_volumes_settings(); - read_graphics_settings(); - read_input_settings(); - read_serial_settings(); - read_memory_settings(); - read_jit_settings(); -} - - -#ifdef STANDALONE_GUI -#include -#include -#include "rpc.h" - -/* - * Fake unused data and functions - */ - -uint8 XPRAM[XPRAM_SIZE]; -void MountVolume(void *fh) { } -void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { } - -#if defined __APPLE__ && defined __MACH__ -void DarwinSysInit(void) { } -void DarwinSysExit(void) { } -void DarwinAddFloppyPrefs(void) { } -void DarwinAddSerialPrefs(void) { } -bool DarwinCDReadTOC(char *, uint8 *) { } -#endif - - -/* - * Display alert - */ - -static void dl_destroyed(void) -{ - gtk_main_quit(); -} - -static void display_alert(int title_id, int prefix_id, int button_id, const char *text) -{ - char str[256]; - sprintf(str, GetString(prefix_id), text); - - GtkWidget *dialog = gtk_dialog_new(); - gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id)); - gtk_container_border_width(GTK_CONTAINER(dialog), 5); - gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150); - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL); - - GtkWidget *label = gtk_label_new(str); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); - - GtkWidget *button = gtk_button_new_with_label(GetString(button_id)); - gtk_widget_show(button); - gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_widget_grab_default(button); - gtk_widget_show(dialog); - - gtk_main(); -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text); -} - - -/* - * RPC handlers - */ - -static GMainLoop *g_gui_loop; - -static int handle_ErrorAlert(rpc_connection_t *connection) -{ - D(bug("handle_ErrorAlert\n")); - - int error; - char *str; - if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0) - return error; - - ErrorAlert(str); - free(str); - return RPC_ERROR_NO_ERROR; -} - -static int handle_WarningAlert(rpc_connection_t *connection) -{ - D(bug("handle_WarningAlert\n")); - - int error; - char *str; - if ((error = rpc_method_get_args(connection, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID)) < 0) - return error; - - WarningAlert(str); - free(str); - return RPC_ERROR_NO_ERROR; -} - -static int handle_Exit(rpc_connection_t *connection) -{ - D(bug("handle_Exit\n")); - - g_main_quit(g_gui_loop); - return RPC_ERROR_NO_ERROR; -} - - -/* - * SIGCHLD handler - */ - -static char g_app_path[PATH_MAX]; -static rpc_connection_t *g_gui_connection = NULL; - -static void sigchld_handler(int sig, siginfo_t *sip, void *) -{ - D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status)); - - // XXX perform a new wait because sip->si_status is sometimes not - // the exit _value_ on MacOS X but rather the usual status field - // from waitpid() -- we could arrange this code in some other way... - int status; - if (waitpid(sip->si_pid, &status, 0) < 0) - status = sip->si_status; - if (WIFEXITED(status)) - status = WEXITSTATUS(status); - if (status & 0x80) - status |= -1 ^0xff; - - if (status < 0) { // negative -> execlp/-errno - char str[256]; - sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status)); - ErrorAlert(str); - status = 1; - } - - if (status != 0) { - if (g_gui_connection) - rpc_exit(g_gui_connection); - exit(status); - } -} - - -/* - * Start standalone GUI - */ - -int main(int argc, char *argv[]) -{ - // Init GTK - gtk_set_locale(); - gtk_init(&argc, &argv); - - // Read preferences - PrefsInit(0, argc, argv); - - // Show preferences editor - bool start = PrefsEditor(); - - // Exit preferences - PrefsExit(); - - // Transfer control to the executable - if (start) { - char gui_connection_path[64]; - sprintf(gui_connection_path, "/org/SheepShaver/GUI/%d", getpid()); - - // Catch exits from the child process - struct sigaction sigchld_sa, old_sigchld_sa; - sigemptyset(&sigchld_sa.sa_mask); - sigchld_sa.sa_sigaction = sigchld_handler; - sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; - if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) { - char str[256]; - sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno)); - ErrorAlert(str); - return 1; - } - - // Search and run the SheepShaver executable - char *p; - strcpy(g_app_path, argv[0]); - if ((p = strstr(g_app_path, "SheepShaverGUI.app/Contents/MacOS")) != NULL) { - strcpy(p, "SheepShaver.app/Contents/MacOS/SheepShaver"); - if (access(g_app_path, X_OK) < 0) { - char str[256]; - sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(errno)); - WarningAlert(str); - strcpy(g_app_path, "/Applications/SheepShaver.app/Contents/MacOS/SheepShaver"); - } - } else { - p = strrchr(g_app_path, '/'); - p = p ? p + 1 : g_app_path; - strcpy(p, "SheepShaver"); - } - - int pid = fork(); - if (pid == 0) { - D(bug("Trying to execute %s\n", g_app_path)); - execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL); -#ifdef _POSIX_PRIORITY_SCHEDULING - // XXX get a chance to run the parent process so that to not confuse/upset GTK... - sched_yield(); -#endif - _exit(-errno); - } - - // Establish a connection to Basilisk II - if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) { - printf("ERROR: failed to initialize GUI-side RPC server connection\n"); - return 1; - } - static const rpc_method_descriptor_t vtable[] = { - { RPC_METHOD_ERROR_ALERT, handle_ErrorAlert }, - { RPC_METHOD_WARNING_ALERT, handle_WarningAlert }, - { RPC_METHOD_EXIT, handle_Exit } - }; - if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) { - printf("ERROR: failed to setup GUI method callbacks\n"); - return 1; - } - int socket; - if ((socket = rpc_listen_socket(g_gui_connection)) < 0) { - printf("ERROR: failed to initialize RPC server thread\n"); - return 1; - } - - g_gui_loop = g_main_new(TRUE); - while (g_main_is_running(g_gui_loop)) { - - // Process a few events pending - const int N_EVENTS_DISPATCH = 10; - for (int i = 0; i < N_EVENTS_DISPATCH; i++) { - if (!g_main_iteration(FALSE)) - break; - } - - // Check for RPC events (100 ms timeout) - int ret = rpc_wait_dispatch(g_gui_connection, 100000); - if (ret == 0) - continue; - if (ret < 0) - break; - rpc_dispatch(g_gui_connection); - } - - rpc_exit(g_gui_connection); - return 0; - } - - return 0; -} -#endif diff --git a/SheepShaver/src/Unix/prefs_unix.cpp b/SheepShaver/src/Unix/prefs_unix.cpp deleted file mode 100644 index 7f89a107..00000000 --- a/SheepShaver/src/Unix/prefs_unix.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * prefs_unix.cpp - Preferences handling, Unix specific things - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include - -#include "prefs.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { - {"ether", TYPE_STRING, false, "device name of Mac ethernet adapter"}, - {"etherconfig", TYPE_STRING, false, "path of network config script"}, - {"keycodes", TYPE_BOOLEAN, false, "use keycodes rather than keysyms to decode keyboard"}, - {"keycodefile", TYPE_STRING, false, "path of keycode translation file"}, - {"mousewheelmode", TYPE_INT32, false, "mouse wheel support mode (0=page up/down, 1=cursor up/down)"}, - {"mousewheellines", TYPE_INT32, false, "number of lines to scroll in mouse wheel mode 1"}, - {"dsp", TYPE_STRING, false, "audio output (dsp) device name"}, - {"mixer", TYPE_STRING, false, "audio mixer device name"}, -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - {"ignoresegv", TYPE_BOOLEAN, false, "ignore illegal memory accesses"}, -#endif - {"idlewait", TYPE_BOOLEAN, false, "sleep when idle"}, - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Prefs file name and path -const char PREFS_FILE_NAME[] = ".sheepshaver_prefs"; -static char prefs_path[1024]; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(const char *vmdir) -{ - if (vmdir) { - snprintf(prefs_path, sizeof(prefs_path), "%s/prefs", vmdir); - FILE *prefs = fopen(prefs_path, "r"); - if (!prefs) { - printf("No file at %s found.\n", prefs_path); - exit(1); - } - LoadPrefsFromStream(prefs); - fclose(prefs); - return; - } - - // Construct prefs path - prefs_path[0] = 0; - char *home = getenv("HOME"); - if (home != NULL && strlen(home) < 1000) { - strncpy(prefs_path, home, 1000); - strcat(prefs_path, "/"); - } - strcat(prefs_path, PREFS_FILE_NAME); - - // Read preferences from settings file - FILE *f = fopen(prefs_path, "r"); - if (f != NULL) { - - // Prefs file found, load settings - LoadPrefsFromStream(f); - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - } -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = fopen(prefs_path, "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsAddBool("keycodes", false); - PrefsReplaceString("extfs", "/"); - PrefsReplaceInt32("mousewheelmode", 1); - PrefsReplaceInt32("mousewheellines", 3); -#ifdef __linux__ - if (access("/dev/sound/dsp", F_OK) == 0) { - PrefsReplaceString("dsp", "/dev/sound/dsp"); - } else { - PrefsReplaceString("dsp", "/dev/dsp"); - } - if (access("/dev/sound/mixer", F_OK) == 0) { - PrefsReplaceString("mixer", "/dev/sound/mixer"); - } else { - PrefsReplaceString("mixer", "/dev/mixer"); - } -#else - PrefsReplaceString("dsp", "/dev/dsp"); - PrefsReplaceString("mixer", "/dev/mixer"); -#endif -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - PrefsAddBool("ignoresegv", false); -#endif - PrefsAddBool("idlewait", true); -} diff --git a/SheepShaver/src/Unix/rpc.h b/SheepShaver/src/Unix/rpc.h deleted file mode 120000 index 98cf8a08..00000000 --- a/SheepShaver/src/Unix/rpc.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/rpc.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/rpc_unix.cpp b/SheepShaver/src/Unix/rpc_unix.cpp deleted file mode 120000 index a960f0b7..00000000 --- a/SheepShaver/src/Unix/rpc_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/rpc_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/semaphore.h b/SheepShaver/src/Unix/semaphore.h deleted file mode 120000 index 9e87a545..00000000 --- a/SheepShaver/src/Unix/semaphore.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/semaphore.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/serial_unix.cpp b/SheepShaver/src/Unix/serial_unix.cpp deleted file mode 120000 index ccda34be..00000000 --- a/SheepShaver/src/Unix/serial_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/serial_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/sigregs.h b/SheepShaver/src/Unix/sigregs.h deleted file mode 100644 index 44fd9117..00000000 --- a/SheepShaver/src/Unix/sigregs.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * sigregs.h - Extract machine registers from a signal frame - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SIGREGS_H -#define SIGREGS_H - -#ifndef EMULATED_PPC - -// Common representation of machine registers -struct sigregs { - uint32 nip; - uint32 link; - uint32 ctr; - uint32 msr; - uint32 xer; - uint32 ccr; - uint32 gpr[32]; -}; - -// Extract machine registers from Linux signal frame -#if defined(__linux__) -#include -#define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext.regs)) - -struct machine_regs : public pt_regs -{ - u_long & cr() { return pt_regs::ccr; } - uint32 cr() const { return pt_regs::ccr; } - uint32 lr() const { return pt_regs::link; } - uint32 ctr() const { return pt_regs::ctr; } - uint32 xer() const { return pt_regs::xer; } - uint32 msr() const { return pt_regs::msr; } - uint32 dar() const { return pt_regs::dar; } - u_long & pc() { return pt_regs::nip; } - uint32 pc() const { return pt_regs::nip; } - u_long & gpr(int i) { return pt_regs::gpr[i]; } - uint32 gpr(int i) const { return pt_regs::gpr[i]; } -}; -#endif - -// Extract machine registers from NetBSD signal frame -#if defined(__NetBSD__) -#include -#define MACHINE_REGISTERS(scp) ((machine_regs *)&(((ucontext_t *)scp)->uc_mcontext)) - -struct machine_regs : public mcontext_t -{ - long & cr() { return __gregs[_REG_CR]; } - uint32 cr() const { return __gregs[_REG_CR]; } - uint32 lr() const { return __gregs[_REG_LR]; } - uint32 ctr() const { return __gregs[_REG_CTR]; } - uint32 xer() const { return __gregs[_REG_XER]; } - uint32 msr() const { return __gregs[_REG_MSR]; } - uint32 dar() const { return (uint32)(((siginfo_t *)(((unsigned long)this) - offsetof(ucontext_t, uc_mcontext))) - 1)->si_addr; } /* HACK */ - long & pc() { return __gregs[_REG_PC]; } - uint32 pc() const { return __gregs[_REG_PC]; } - long & gpr(int i) { return __gregs[_REG_R0 + i]; } - uint32 gpr(int i) const { return __gregs[_REG_R0 + i]; } -}; -#endif - -// Extract machine registers from Darwin signal frame -#if defined(__APPLE__) && defined(__MACH__) -#include - -#define MACHINE_REGISTERS(scp) ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext)) - -#if __DARWIN_UNIX03 -#define __(x) __CONCAT(__,x) -#else -#define __(x) x -#endif - -#include - -#if __DARWIN_UNIX03 -struct machine_regs : public __darwin_mcontext -#else -struct machine_regs : public mcontext -#endif -{ - uint32 & cr() { return __(ss).__(cr); } - uint32 cr() const { return __(ss).__(cr); } - uint32 lr() const { return __(ss).__(lr); } - uint32 ctr() const { return __(ss).__(ctr); } - uint32 xer() const { return __(ss).__(xer); } - uint32 msr() const { return __(ss).__(srr1); } - uint32 dar() const { return __(es).__(dar); } - uint32 & pc() { return __(ss).__(srr0); } - uint32 pc() const { return __(ss).__(srr0); } - uint32 & gpr(int i) { return (&__(ss).__(r0))[i]; } - uint32 gpr(int i) const { return (&__(ss).__(r0))[i]; } -}; -#endif - -// Convert system-dependent machine registers to generic sigregs -static void build_sigregs(sigregs *srp, machine_regs *mrp) -{ - srp->nip = mrp->pc(); - srp->link = mrp->lr(); - srp->ctr = mrp->ctr(); - srp->msr = mrp->msr(); - srp->xer = mrp->xer(); - srp->ccr = mrp->cr(); - for (int i = 0; i < 32; i++) - srp->gpr[i] = mrp->gpr(i); -} - -#endif - -#endif /* SIGREGS_H */ diff --git a/SheepShaver/src/Unix/sshpty.c b/SheepShaver/src/Unix/sshpty.c deleted file mode 120000 index ffaa2bfc..00000000 --- a/SheepShaver/src/Unix/sshpty.c +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/sshpty.c \ No newline at end of file diff --git a/SheepShaver/src/Unix/sshpty.h b/SheepShaver/src/Unix/sshpty.h deleted file mode 120000 index 9132736a..00000000 --- a/SheepShaver/src/Unix/sshpty.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/sshpty.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/strlcpy.c b/SheepShaver/src/Unix/strlcpy.c deleted file mode 120000 index 59e61670..00000000 --- a/SheepShaver/src/Unix/strlcpy.c +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/strlcpy.c \ No newline at end of file diff --git a/SheepShaver/src/Unix/strlcpy.h b/SheepShaver/src/Unix/strlcpy.h deleted file mode 120000 index 1c551aac..00000000 --- a/SheepShaver/src/Unix/strlcpy.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/strlcpy.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/sys_unix.cpp b/SheepShaver/src/Unix/sys_unix.cpp deleted file mode 120000 index e5769e8d..00000000 --- a/SheepShaver/src/Unix/sys_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/sys_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/sysdeps.h b/SheepShaver/src/Unix/sysdeps.h deleted file mode 100644 index 0099527b..00000000 --- a/SheepShaver/src/Unix/sysdeps.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * sysdeps.h - System dependent definitions for Linux - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -#ifndef __STDC__ -#error "Your compiler is not ANSI. Get a real one." -#endif - -#include "config.h" -#include "user_strings_unix.h" - -#ifndef STDC_HEADERS -#error "You don't have ANSI C header files." -#endif - -#ifdef HAVE_UNISTD_H -# include -# include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_PTHREADS -# include -#endif - -#ifdef HAVE_FCNTL_H -# include -#endif - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - -#ifdef __MACH__ -#include -#endif - -// Fix offsetof() on FreeBSD and GCC >= 3.4 -#if defined(__FreeBSD__) && defined(__cplusplus) && __GNUC__ < 4 -#undef offsetof -/* The cast to "char &" below avoids problems with user-defined - "operator &", which can appear in a POD type. */ -#define offsetof(TYPE, MEMBER) \ - (__offsetof__ (reinterpret_cast \ - (&reinterpret_cast \ - (static_cast (0)->MEMBER)))) -#endif - -// Define for external components -#define SHEEPSHAVER 1 - -// Always use Real Addressing mode on native architectures -// Otherwise, use Direct Addressing mode if NATMEM_OFFSET is set -#if !defined(EMULATED_PPC) -#define REAL_ADDRESSING 1 -#include "ppc_asm.tmpl" -#elif defined(NATMEM_OFFSET) -#define DIRECT_ADDRESSING 1 -#else -#define REAL_ADDRESSING 1 -#endif - -// Always use the complete non-stubs Ethernet driver -#define USE_ETHER_FULL_DRIVER 1 - -#define POWERPC_ROM 1 - -#if EMULATED_PPC -// Mac ROM is write protected when banked memory is used -#if REAL_ADDRESSING || DIRECT_ADDRESSING -# define ROM_IS_WRITE_PROTECTED 0 -# define USE_SCRATCHMEM_SUBTERFUGE 1 -#else -# define ROM_IS_WRITE_PROTECTED 1 -#endif -// Configure PowerPC emulator -#define PPC_REENTRANT_JIT 1 -#define PPC_CHECK_INTERRUPTS 1 -#define PPC_DECODE_CACHE 1 -#define PPC_FLIGHT_RECORDER 1 -#define PPC_PROFILE_COMPILE_TIME 0 -#define PPC_PROFILE_GENERIC_CALLS 0 -#define PPC_PROFILE_REGS_USE 0 -#define KPX_MAX_CPUS 1 -#if ENABLE_DYNGEN -#define PPC_ENABLE_JIT 1 -#endif -#if defined(__i386__) || defined(__x86_64__) -#define DYNGEN_ASM_OPTS 1 -#endif -#else -// Mac ROM is write protected -#define ROM_IS_WRITE_PROTECTED 1 -#define USE_SCRATCHMEM_SUBTERFUGE 0 -#endif - -// Data types -typedef unsigned char uint8; -typedef signed char int8; -#if SIZEOF_SHORT == 2 -typedef unsigned short uint16; -typedef short int16; -#elif SIZEOF_INT == 2 -typedef unsigned int uint16; -typedef int int16; -#else -#error "No 2 byte type, you lose." -#endif -#if SIZEOF_INT == 4 -typedef unsigned int uint32; -typedef int int32; -#elif SIZEOF_LONG == 4 -typedef unsigned long uint32; -typedef long int32; -#else -#error "No 4 byte type, you lose." -#endif -#if SIZEOF_LONG == 8 -typedef unsigned long uint64; -typedef long int64; -#define VAL64(a) (a ## l) -#define UVAL64(a) (a ## ul) -#elif SIZEOF_LONG_LONG == 8 -typedef unsigned long long uint64; -typedef long long int64; -#define VAL64(a) (a ## LL) -#define UVAL64(a) (a ## uLL) -#else -#error "No 8 byte type, you lose." -#endif -#if SIZEOF_VOID_P == 4 -typedef uint32 uintptr; -typedef int32 intptr; -#elif SIZEOF_VOID_P == 8 -typedef uint64 uintptr; -typedef int64 intptr; -#else -#error "Unsupported size of pointer" -#endif - -// Define if the host processor supports fast unaligned load/stores -#if defined __i386__ || defined __x86_64__ -#define UNALIGNED_PROFITABLE 1 -#endif - - -/** - * Helper functions to byteswap data - **/ - -#if defined(__GNUC__) -#if defined(__x86_64__) || defined(__i386__) -// Linux/AMD64 currently has no asm optimized bswap_32() in -#define opt_bswap_32 do_opt_bswap_32 -static inline uint32 do_opt_bswap_32(uint32 x) -{ - uint32 v; - __asm__ __volatile__ ("bswap %0" : "=r" (v) : "0" (x)); - return v; -} -#endif -#endif - -#ifdef HAVE_BYTESWAP_H -#include -#endif - -#ifdef opt_bswap_16 -#undef bswap_16 -#define bswap_16 opt_bswap_16 -#endif -#ifndef bswap_16 -#define bswap_16 generic_bswap_16 -#endif - -static inline uint16 generic_bswap_16(uint16 x) -{ - return ((x & 0xff) << 8) | ((x >> 8) & 0xff); -} - -#ifdef opt_bswap_32 -#undef bswap_32 -#define bswap_32 opt_bswap_32 -#endif -#ifndef bswap_32 -#define bswap_32 generic_bswap_32 -#endif - -static inline uint32 generic_bswap_32(uint32 x) -{ - return (((x & 0xff000000) >> 24) | - ((x & 0x00ff0000) >> 8) | - ((x & 0x0000ff00) << 8) | - ((x & 0x000000ff) << 24) ); -} - -#if defined(__i386__) -#define opt_bswap_64 do_opt_bswap_64 -static inline uint64 do_opt_bswap_64(uint64 x) -{ - return (bswap_32(x >> 32) | (((uint64)bswap_32((uint32)x)) << 32)); -} -#endif - -#ifdef opt_bswap_64 -#undef bswap_64 -#define bswap_64 opt_bswap_64 -#endif -#ifndef bswap_64 -#define bswap_64 generic_bswap_64 -#endif - -static inline uint64 generic_bswap_64(uint64 x) -{ - return (((x & UVAL64(0xff00000000000000)) >> 56) | - ((x & UVAL64(0x00ff000000000000)) >> 40) | - ((x & UVAL64(0x0000ff0000000000)) >> 24) | - ((x & UVAL64(0x000000ff00000000)) >> 8) | - ((x & UVAL64(0x00000000ff000000)) << 8) | - ((x & UVAL64(0x0000000000ff0000)) << 24) | - ((x & UVAL64(0x000000000000ff00)) << 40) | - ((x & UVAL64(0x00000000000000ff)) << 56) ); -} - -#ifdef WORDS_BIGENDIAN -static inline uint16 tswap16(uint16 x) { return x; } -static inline uint32 tswap32(uint32 x) { return x; } -static inline uint64 tswap64(uint64 x) { return x; } -#else -static inline uint16 tswap16(uint16 x) { return bswap_16(x); } -static inline uint32 tswap32(uint32 x) { return bswap_32(x); } -static inline uint64 tswap64(uint64 x) { return bswap_64(x); } -#endif - -// spin locks -#ifdef __GNUC__ - -#if defined(__powerpc__) || defined(__ppc__) -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - __asm__ __volatile__("0: lwarx %0,0,%1\n" - " xor. %0,%3,%0\n" - " bne 1f\n" - " stwcx. %2,0,%1\n" - " bne- 0b\n" - "1: " - : "=&r" (ret) - : "r" (p), "r" (1), "r" (0) - : "cr0", "memory"); - return ret; -} -#endif - -#if defined(__i386__) || defined(__x86_64__) -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - long int ret; - /* Note: the "xchg" instruction does not need a "lock" prefix */ - __asm__ __volatile__("xchgl %k0, %1" - : "=r" (ret), "=m" (*p) - : "0" (1), "m" (*p) - : "memory"); - return ret; -} -#endif - -#ifdef __s390__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - - __asm__ __volatile__("0: cs %0,%1,0(%2)\n" - " jl 0b" - : "=&d" (ret) - : "r" (1), "a" (p), "0" (*p) - : "cc", "memory" ); - return ret; -} -#endif - -#ifdef __alpha__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - unsigned long one; - - __asm__ __volatile__("0: mov 1,%2\n" - " ldl_l %0,%1\n" - " stl_c %2,%1\n" - " beq %2,1f\n" - ".subsection 2\n" - "1: br 0b\n" - ".previous" - : "=r" (ret), "=m" (*p), "=r" (one) - : "m" (*p)); - return ret; -} -#endif - -#ifdef __sparc__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - - __asm__ __volatile__("ldstub [%1], %0" - : "=r" (ret) - : "r" (p) - : "memory"); - - return (ret ? 1 : 0); -} -#endif - -#ifdef __arm__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - register unsigned int ret; - __asm__ __volatile__("swp %0, %1, [%2]" - : "=r"(ret) - : "0"(1), "r"(p)); - - return ret; -} -#endif - -#endif /* __GNUC__ */ - -typedef volatile int spinlock_t; - -static const spinlock_t SPIN_LOCK_UNLOCKED = 0; - -#if defined(HAVE_TEST_AND_SET) && defined(HAVE_PTHREADS) -// There is nothing to lock if we are not in an multithreaded environment -#define HAVE_SPINLOCKS 1 -static inline void spin_lock(spinlock_t *lock) -{ - while (testandset(lock)); -} - -static inline void spin_unlock(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return !testandset(lock); -} -#else -static inline void spin_lock(spinlock_t *lock) -{ -} - -static inline void spin_unlock(spinlock_t *lock) -{ -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return 1; -} -#endif - -// Time data type for Time Manager emulation -#ifdef HAVE_CLOCK_GETTIME -typedef struct timespec tm_time_t; -#elif defined(__MACH__) -typedef mach_timespec_t tm_time_t; -#else -typedef struct timeval tm_time_t; -#endif - -/* Define codes for all the float formats that we know of. - * Though we only handle IEEE format. */ -#define UNKNOWN_FLOAT_FORMAT 0 -#define IEEE_FLOAT_FORMAT 1 -#define VAX_FLOAT_FORMAT 2 -#define IBM_FLOAT_FORMAT 3 -#define C4X_FLOAT_FORMAT 4 - -// High-precision timing -#if defined(HAVE_PTHREADS) && defined(HAVE_CLOCK_NANOSLEEP) -#define PRECISE_TIMING 1 -#define PRECISE_TIMING_POSIX 1 -#elif defined(HAVE_PTHREADS) && defined(__MACH__) -#define PRECISE_TIMING 1 -#define PRECISE_TIMING_MACH 1 -#endif - -// Timing functions -extern uint64 GetTicks_usec(void); -extern void Delay_usec(uint32 usec); - -#ifdef HAVE_PTHREADS -// Setup pthread attributes -extern void Set_pthread_attr(pthread_attr_t *attr, int priority); -#endif - -// Various definitions -typedef struct rgb_color { - uint8 red; - uint8 green; - uint8 blue; - uint8 alpha; -} rgb_color; - -// X11 display fast locks -#if defined(HAVE_PTHREADS) -#define X11_LOCK_TYPE pthread_mutex_t -#define X11_LOCK_INIT PTHREAD_MUTEX_INITIALIZER -#define XDisplayLock() pthread_mutex_lock(&x_display_lock); -#define XDisplayUnlock() pthread_mutex_unlock(&x_display_lock); -#elif defined(HAVE_SPINLOCKS) -#define X11_LOCK_TYPE spinlock_t -#define X11_LOCK_INIT SPIN_LOCK_UNLOCKED -#define XDisplayLock() spin_lock(&x_display_lock) -#define XDisplayUnlock() spin_unlock(&x_display_lock) -#else -#define XDisplayLock() -#define XDisplayUnlock() -#endif -#ifdef X11_LOCK_TYPE -extern X11_LOCK_TYPE x_display_lock; -#endif - -// Macro for calling MacOS routines -#define CallMacOS(type, tvect) call_macos((uintptr)tvect) -#define CallMacOS1(type, tvect, arg1) call_macos1((uintptr)tvect, (uintptr)arg1) -#define CallMacOS2(type, tvect, arg1, arg2) call_macos2((uintptr)tvect, (uintptr)arg1, (uintptr)arg2) -#define CallMacOS3(type, tvect, arg1, arg2, arg3) call_macos3((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3) -#define CallMacOS4(type, tvect, arg1, arg2, arg3, arg4) call_macos4((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4) -#define CallMacOS5(type, tvect, arg1, arg2, arg3, arg4, arg5) call_macos5((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5) -#define CallMacOS6(type, tvect, arg1, arg2, arg3, arg4, arg5, arg6) call_macos6((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5, (uintptr)arg6) -#define CallMacOS7(type, tvect, arg1, arg2, arg3, arg4, arg5, arg6, arg7) call_macos7((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5, (uintptr)arg6, (uintptr)arg7) - -#ifdef __cplusplus -extern "C" { -#endif -extern uint32 call_macos(uint32 tvect); -extern uint32 call_macos1(uint32 tvect, uint32 arg1); -extern uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2); -extern uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3); -extern uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4); -extern uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5); -extern uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6); -extern uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7); -#ifdef __cplusplus -} -#endif - -#endif diff --git a/SheepShaver/src/Unix/timer_unix.cpp b/SheepShaver/src/Unix/timer_unix.cpp deleted file mode 120000 index db93bbd3..00000000 --- a/SheepShaver/src/Unix/timer_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/timer_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/tinyxml2.cpp b/SheepShaver/src/Unix/tinyxml2.cpp deleted file mode 120000 index 0609bdc8..00000000 --- a/SheepShaver/src/Unix/tinyxml2.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/tinyxml2.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/tinyxml2.h b/SheepShaver/src/Unix/tinyxml2.h deleted file mode 120000 index d90c30e2..00000000 --- a/SheepShaver/src/Unix/tinyxml2.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/tinyxml2.h \ No newline at end of file diff --git a/SheepShaver/src/Unix/tunconfig b/SheepShaver/src/Unix/tunconfig deleted file mode 120000 index 615f7fe9..00000000 --- a/SheepShaver/src/Unix/tunconfig +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/tunconfig \ No newline at end of file diff --git a/SheepShaver/src/Unix/user_strings_unix.cpp b/SheepShaver/src/Unix/user_strings_unix.cpp deleted file mode 100644 index 5a3b21f5..00000000 --- a/SheepShaver/src/Unix/user_strings_unix.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * user_strings_unix.cpp - Localizable strings, Unix specific strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "user_strings.h" - - -// Platform-specific string definitions -user_string_def platform_strings[] = { - // Common strings that have a platform-specific variant - {STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under Linux. Basilisk II will try to unmount it."}, - {STR_EXTFS_CTRL, "Unix Root"}, - {STR_EXTFS_NAME, "Unix Directory Tree"}, - {STR_EXTFS_VOLUME_NAME, "Unix"}, - - // Purely platform-specific strings - {STR_NO_DEV_ZERO_ERR, "Cannot open /dev/zero: %s."}, - {STR_LOW_MEM_MMAP_ERR, "Cannot map Low Memory Globals: %s."}, - {STR_KD_SHMGET_ERR, "Cannot create SHM segment for Kernel Data: %s."}, - {STR_KD_SHMAT_ERR, "Cannot map first Kernel Data area: %s."}, - {STR_KD2_SHMAT_ERR, "Cannot map second Kernel Data area: %s."}, - {STR_ROM_MMAP_ERR, "Cannot map ROM: %s."}, - {STR_RAM_MMAP_ERR, "Cannot map RAM: %s."}, - {STR_RAM_ROM_MMAP_ERR, "Cannot map area for RAM and ROM: %s."}, - {STR_RAM_AREA_TOO_HIGH_ERR, "Cannot map usable RAM area. Try to decrease the MacOS RAM size."}, - {STR_DR_CACHE_MMAP_ERR, "Cannot map DR Cache: %s."}, - {STR_DR_EMULATOR_MMAP_ERR, "Cannot map DR Emulator: %s."}, - {STR_SHEEP_MEM_MMAP_ERR, "Cannot map SheepShaver Data area: %s."}, - {STR_SIGALTSTACK_ERR, "Cannot install alternate signal stack (%s). It seems that you need a newer kernel."}, - {STR_SIG_INSTALL_ERR, "Cannot install %s handler (%s)."}, - {STR_NO_XSERVER_ERR, "Cannot connect to X server %s."}, - {STR_NO_XVISUAL_ERR, "Cannot obtain appropriate X visual."}, - {STR_UNSUPP_DEPTH_ERR, "Unsupported color depth of screen."}, - {STR_PROC_CPUINFO_WARN, "Cannot open /proc/cpuinfo (%s). Assuming 100MHz PowerPC 604."}, - {STR_BLOCKING_NET_SOCKET_WARN, "Cannot set non-blocking I/O to net socket (%s). Ethernet will not be available."}, - {STR_NO_SHEEP_NET_DRIVER_WARN, "Cannot open %s (%s). Ethernet will not be available."}, - {STR_SHEEP_NET_ATTACH_WARN, "Cannot attach to Ethernet card (%s). Ethernet will not be available."}, - {STR_TUN_TAP_CONFIG_WARN, "Cannot configure TUN/TAP device (%s). Ethernet will not be available."}, - {STR_SLIRP_NO_DNS_FOUND_WARN, "Cannot get DNS address. Ethernet will not be available."}, - {STR_NO_AUDIO_DEV_WARN, "Cannot open %s (%s). Audio output will be disabled."}, - {STR_NO_AUDIO_WARN, "No audio device found, audio output will be disabled."}, - {STR_NO_ESD_WARN, "Cannot open ESD connection. Audio output will be disabled."}, - {STR_AUDIO_FORMAT_WARN, "/dev/dsp doesn't support signed 16 bit format. Audio output will be disabled."}, - {STR_SCSI_DEVICE_OPEN_WARN, "Cannot open %s (%s). SCSI Manager access to this device will be disabled."}, - {STR_SCSI_DEVICE_NOT_SCSI_WARN, "%s doesn't seem to comply to the Generic SCSI API. SCSI Manager access to this device will be disabled."}, - {STR_KEYCODE_FILE_WARN, "Cannot open keycode translation file %s (%s)."}, - {STR_KEYCODE_VENDOR_WARN, "Cannot find vendor '%s' in keycode translation file %s."}, - {STR_PREFS_MENU_FILE_GTK, "/_File"}, - {STR_PREFS_ITEM_START_GTK, "/File/_Start SheepShaver"}, - {STR_PREFS_ITEM_ZAP_PRAM_GTK, "/File/_Zap PRAM File"}, - {STR_PREFS_ITEM_SEPL_GTK, "/File/sepl"}, - {STR_PREFS_ITEM_QUIT_GTK, "/File/_Quit SheepShaver"}, - {STR_HELP_MENU_GTK, "/_Help"}, - {STR_HELP_ITEM_ABOUT_GTK, "/Help/_About SheepShaver"}, - {STR_DSPDEVICE_FILE_CTRL, "Audio Output Device"}, - {STR_MIXERDEVICE_FILE_CTRL, "Audio Mixer Device"}, - {STR_BROWSE_TITLE, "Browse file"}, - {STR_BROWSE_CTRL, "Browse..."}, - {STR_INPUT_PANE_TITLE, "Keyboard/Mouse"}, - {STR_KEYCODES_CTRL, "Use Raw Keycodes"}, - {STR_KEYCODE_FILE_CTRL, "Keycode Translation File"}, - {STR_MOUSEWHEELMODE_CTRL, "Mouse Wheel Function"}, - {STR_MOUSEWHEELMODE_PAGE_LAB, "Page Up/Down"}, - {STR_MOUSEWHEELMODE_CURSOR_LAB, "Cursor Up/Down"}, - {STR_MOUSEWHEELLINES_CTRL, "Lines To Scroll"}, - {STR_SUSPEND_WINDOW_TITLE, "SheepShaver suspended. Press Space to reactivate."}, - {STR_VOSF_INIT_ERR, "Cannot initialize Video on SEGV signals."}, - - {STR_OPEN_WINDOW_ERR, "Cannot open Mac window."}, - {STR_WINDOW_TITLE_GRABBED, "SheepShaver (mouse grabbed, press Ctrl-F5 to release)"}, - - {STR_NO_B2_EXE_FOUND, "Could not start %s (%s)."}, - - {-1, NULL} // End marker -}; - - -/* - * Fetch pointer to string, given the string number - */ - -const char *GetString(int num) -{ - // First search for platform-specific string - int i = 0; - while (platform_strings[i].num >= 0) { - if (platform_strings[i].num == num) - return platform_strings[i].str; - i++; - } - - // Not found, search for common string - i = 0; - while (common_strings[i].num >= 0) { - if (common_strings[i].num == num) - return common_strings[i].str; - i++; - } - return NULL; -} diff --git a/SheepShaver/src/Unix/user_strings_unix.h b/SheepShaver/src/Unix/user_strings_unix.h deleted file mode 100644 index be9ea0bb..00000000 --- a/SheepShaver/src/Unix/user_strings_unix.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * user_strings_unix.h - Unix-specific localizable strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_LINUX_H -#define USER_STRINGS_LINUX_H - -enum { - STR_NO_DEV_ZERO_ERR = 10000, - STR_LOW_MEM_MMAP_ERR, - STR_KD_SHMGET_ERR, - STR_KD_SHMAT_ERR, - STR_KD2_SHMAT_ERR, - STR_ROM_MMAP_ERR, - STR_RAM_MMAP_ERR, - STR_RAM_ROM_MMAP_ERR, - STR_RAM_AREA_TOO_HIGH_ERR, - STR_DR_CACHE_MMAP_ERR, - STR_DR_EMULATOR_MMAP_ERR, - STR_SHEEP_MEM_MMAP_ERR, - STR_SIGALTSTACK_ERR, - STR_SIG_INSTALL_ERR, - STR_NO_XSERVER_ERR, - STR_NO_XVISUAL_ERR, - STR_UNSUPP_DEPTH_ERR, - STR_VOSF_INIT_ERR, - - STR_PROC_CPUINFO_WARN, - STR_BLOCKING_NET_SOCKET_WARN, - STR_NO_SHEEP_NET_DRIVER_WARN, - STR_SHEEP_NET_ATTACH_WARN, - STR_TUN_TAP_CONFIG_WARN, - STR_SLIRP_NO_DNS_FOUND_WARN, - STR_NO_AUDIO_DEV_WARN, - STR_NO_AUDIO_WARN, - STR_NO_ESD_WARN, - STR_AUDIO_FORMAT_WARN, - STR_SCSI_DEVICE_OPEN_WARN, - STR_SCSI_DEVICE_NOT_SCSI_WARN, - STR_KEYCODE_FILE_WARN, - STR_KEYCODE_VENDOR_WARN, - - STR_PREFS_MENU_FILE_GTK, - STR_PREFS_ITEM_START_GTK, - STR_PREFS_ITEM_ZAP_PRAM_GTK, - STR_PREFS_ITEM_SEPL_GTK, - STR_PREFS_ITEM_QUIT_GTK, - STR_HELP_MENU_GTK, - STR_HELP_ITEM_ABOUT_GTK, - STR_SUSPEND_WINDOW_TITLE, - STR_DSPDEVICE_FILE_CTRL, - STR_MIXERDEVICE_FILE_CTRL, - - STR_BROWSE_CTRL, - STR_BROWSE_TITLE, - STR_INPUT_PANE_TITLE, - STR_KEYCODES_CTRL, - STR_KEYCODE_FILE_CTRL, - STR_MOUSEWHEELMODE_CTRL, - STR_MOUSEWHEELMODE_PAGE_LAB, - STR_MOUSEWHEELMODE_CURSOR_LAB, - STR_MOUSEWHEELLINES_CTRL, - - STR_OPEN_WINDOW_ERR, - STR_WINDOW_TITLE_GRABBED, - - STR_NO_B2_EXE_FOUND -}; - -#endif diff --git a/SheepShaver/src/Unix/vhd_unix.cpp b/SheepShaver/src/Unix/vhd_unix.cpp deleted file mode 120000 index a0c73d90..00000000 --- a/SheepShaver/src/Unix/vhd_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/vhd_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/Unix/video_x.cpp b/SheepShaver/src/Unix/video_x.cpp deleted file mode 100644 index f7374740..00000000 --- a/SheepShaver/src/Unix/video_x.cpp +++ /dev/null @@ -1,2584 +0,0 @@ -/* - * video_x.cpp - Video/graphics emulation, X11 specific stuff - * - * SheepShaver (C) Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * The Ctrl key works like a qualifier for special actions: - * Ctrl-Tab = suspend DGA mode - * Ctrl-Esc = emergency quit - * Ctrl-F1 = mount floppy - * Ctrl-F5 = grab mouse (in windowed mode) - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef ENABLE_FBDEV_DGA -# include -# include -#endif - -#ifdef ENABLE_XF86_DGA -# include -#endif - -#ifdef ENABLE_XF86_VIDMODE -# include -#endif - -#ifdef ENABLE_FBDEV_DGA -# include -#endif - -#include "main.h" -#include "adb.h" -#include "prefs.h" -#include "user_strings.h" -#include "about_window.h" -#include "video.h" -#include "video_defs.h" -#include "video_blit.h" - -#define DEBUG 0 -#include "debug.h" - -#ifndef NO_STD_NAMESPACE -using std::sort; -#endif - - -// Constants -const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; -static const bool hw_mac_cursor_accl = true; // Flag: Enable MacOS to X11 copy of cursor? - -// Global variables -static int32 frame_skip; -static int16 mouse_wheel_mode; -static int16 mouse_wheel_lines; -static bool redraw_thread_active = false; // Flag: Redraw thread installed -static pthread_attr_t redraw_thread_attr; // Redraw thread attributes -static volatile bool redraw_thread_cancel; // Flag: Cancel Redraw thread -static pthread_t redraw_thread; // Redraw thread - -static volatile bool thread_stop_req = false; -static sem_t thread_stop_ack; -static sem_t thread_resume_req; - -static bool local_X11; // Flag: X server running on local machine? -static bool has_dga = false; // Flag: Video DGA capable -static bool has_vidmode = false; // Flag: VidMode extension available - -#ifdef ENABLE_VOSF -static bool use_vosf = true; // Flag: VOSF enabled -#else -static const bool use_vosf = false; // VOSF not possible -#endif - -static bool palette_changed = false; // Flag: Palette changed, redraw thread must update palette -static bool ctrl_down = false; // Flag: Ctrl key pressed -static bool caps_on = false; // Flag: Caps Lock on -static bool quit_full_screen = false; // Flag: DGA close requested from redraw thread -static volatile bool quit_full_screen_ack = false; // Acknowledge for quit_full_screen -static bool emerg_quit = false; // Flag: Ctrl-Esc pressed, emergency quit requested from MacOS thread - -static bool emul_suspended = false; // Flag: emulator suspended -static Window suspend_win; // "Suspend" window -static void *fb_save = NULL; // Saved frame buffer for suspend -static bool use_keycodes = false; // Flag: Use keycodes rather than keysyms -static int keycode_table[256]; // X keycode -> Mac keycode translation table - -// X11 variables -static int screen; // Screen number -static int xdepth; // Depth of X screen -static int depth; // Depth of Mac frame buffer -static Window rootwin, the_win; // Root window and our window -static int num_depths = 0; // Number of available X depths -static int *avail_depths = NULL; // List of available X depths -static VisualFormat visualFormat; -static XVisualInfo visualInfo; -static Visual *vis; -static int color_class; -static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of DirectColor/TrueColor modes -static Colormap cmap[2]; // Two colormaps (DGA) for 8-bit mode -static XColor x_palette[256]; // Color palette to be used as CLUT and gamma table -static int orig_accel_numer, orig_accel_denom, orig_threshold; // Original mouse acceleration - -static XColor black, white; -static unsigned long black_pixel, white_pixel; -static int eventmask; -static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask; -static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask; - -// Variables for window mode -static GC the_gc; -static XImage *img = NULL; -static XShmSegmentInfo shminfo; -static XImage *cursor_image, *cursor_mask_image; -static Pixmap cursor_map, cursor_mask_map; -static Cursor mac_cursor; -static GC cursor_gc, cursor_mask_gc; -static bool cursor_changed = false; // Flag: Cursor changed, window_func must update cursor -static bool have_shm = false; // Flag: SHM present and usable -static uint8 *the_buffer = NULL; // Pointer to Mac frame buffer -static uint8 *the_buffer_copy = NULL; // Copy of Mac frame buffer -static uint32 the_buffer_size; // Size of allocated the_buffer - -// Variables for DGA mode -static bool is_fbdev_dga_mode = false; // Flag: Use FBDev DGA mode? -static int current_dga_cmap; - -#ifdef ENABLE_FBDEV_DGA -static int fb_dev_fd = -1; // Handle to fb device name -static struct fb_fix_screeninfo fb_finfo; // Fixed info -static struct fb_var_screeninfo fb_vinfo; // Variable info -static struct fb_var_screeninfo fb_orig_vinfo; // Variable info to restore later -static struct fb_cmap fb_oldcmap; // Colormap to restore later -#endif - -#ifdef ENABLE_XF86_VIDMODE -// Variables for XF86 VidMode support -static XF86VidModeModeInfo **x_video_modes; // Array of all available modes -static int num_x_video_modes; -#endif - -// Mutex to protect palette -#if defined(HAVE_PTHREADS) -static pthread_mutex_t x_palette_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_PALETTE pthread_mutex_lock(&x_palette_lock) -#define UNLOCK_PALETTE pthread_mutex_unlock(&x_palette_lock) -#elif defined(HAVE_SPINLOCKS) -static spinlock_t x_palette_lock = SPIN_LOCK_UNLOCKED; -#define LOCK_PALETTE spin_lock(&x_palette_lock) -#define UNLOCK_PALETTE spin_unlock(&x_palette_lock) -#else -#define LOCK_PALETTE -#define UNLOCK_PALETTE -#endif - -// Mutex to protect frame buffer -#if defined(HAVE_PTHREADS) -static pthread_mutex_t frame_buffer_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_FRAME_BUFFER pthread_mutex_lock(&frame_buffer_lock); -#define UNLOCK_FRAME_BUFFER pthread_mutex_unlock(&frame_buffer_lock); -#elif defined(HAVE_SPINLOCKS) -static spinlock_t frame_buffer_lock = SPIN_LOCK_UNLOCKED; -#define LOCK_FRAME_BUFFER spin_lock(&frame_buffer_lock) -#define UNLOCK_FRAME_BUFFER spin_unlock(&frame_buffer_lock) -#else -#define LOCK_FRAME_BUFFER -#define UNLOCK_FRAME_BUFFER -#endif - - -// Prototypes -static void *redraw_func(void *arg); - - -// From main_unix.cpp -extern char *x_display_name; -extern Display *x_display; - -// From sys_unix.cpp -extern void SysMountFirstFloppy(void); - -// From clip_unix.cpp -extern void ClipboardSelectionClear(XSelectionClearEvent *); -extern void ClipboardSelectionRequest(XSelectionRequestEvent *); - - -// Video acceleration through SIGSEGV -#ifdef ENABLE_VOSF -# include "video_vosf.h" -#endif - - -/* - * Utility functions - */ - -// Get current video mode -static inline int get_current_mode(void) -{ - return VModes[cur_mode].viAppleMode; -} - -// Find palette size for given color depth -static int palette_size(int mode) -{ - switch (mode) { - case APPLE_1_BIT: return 2; - case APPLE_2_BIT: return 4; - case APPLE_4_BIT: return 16; - case APPLE_8_BIT: return 256; - case APPLE_16_BIT: return 32; - case APPLE_32_BIT: return 256; - default: return 0; - } -} - -// Return bits per pixel for requested depth -static inline int bytes_per_pixel(int depth) -{ - int bpp; - switch (depth) { - case 8: - bpp = 1; - break; - case 15: case 16: - bpp = 2; - break; - case 24: case 32: - bpp = 4; - break; - default: - abort(); - } - return bpp; -} - -// Map video_mode depth ID to numerical depth value -static inline int depth_of_video_mode(int mode) -{ - int depth; - switch (mode) { - case APPLE_1_BIT: - depth = 1; - break; - case APPLE_2_BIT: - depth = 2; - break; - case APPLE_4_BIT: - depth = 4; - break; - case APPLE_8_BIT: - depth = 8; - break; - case APPLE_16_BIT: - depth = 16; - break; - case APPLE_32_BIT: - depth = 32; - break; - default: - abort(); - } - return depth; -} - -// Map RGB color to pixel value (this only works in TrueColor/DirectColor visuals) -static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue) -{ - return ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift); -} - - -// Do we have a visual for handling the specified Mac depth? If so, set the -// global variables "xdepth", "visualInfo", "vis" and "color_class". -static bool find_visual_for_depth(int depth) -{ - D(bug("have_visual_for_depth(%d)\n", depth_of_video_mode(depth))); - - // 1-bit works always and uses default visual - if (depth == APPLE_1_BIT) { - vis = DefaultVisual(x_display, screen); - visualInfo.visualid = XVisualIDFromVisual(vis); - int num = 0; - XVisualInfo *vi = XGetVisualInfo(x_display, VisualIDMask, &visualInfo, &num); - visualInfo = vi[0]; - XFree(vi); - xdepth = visualInfo.depth; - color_class = visualInfo.c_class; - D(bug(" found visual ID 0x%02x, depth %d\n", visualInfo.visualid, xdepth)); - return true; - } - - // Calculate minimum and maximum supported X depth - int min_depth = 1, max_depth = 32; - switch (depth) { -#ifdef ENABLE_VOSF - case APPLE_2_BIT: - case APPLE_4_BIT: // VOSF blitters can convert 2/4/8-bit -> 8/16/32-bit - case APPLE_8_BIT: - min_depth = 8; - max_depth = 32; - break; -#else - case APPLE_2_BIT: - case APPLE_4_BIT: // 2/4-bit requires VOSF blitters - return false; - case APPLE_8_BIT: // 8-bit without VOSF requires an 8-bit visual - min_depth = 8; - max_depth = 8; - break; -#endif - case APPLE_16_BIT: // 16-bit requires a 15/16-bit visual - min_depth = 15; - max_depth = 16; - break; - case APPLE_32_BIT: // 32-bit requires a 24/32-bit visual - min_depth = 24; - max_depth = 32; - break; - } - D(bug(" minimum required X depth is %d, maximum supported X depth is %d\n", min_depth, max_depth)); - - // Try to find a visual for one of the color depths - bool visual_found = false; - for (int i=0; i max_depth) - continue; - - // Determine best color class for this depth - switch (xdepth) { - case 1: // Try StaticGray or StaticColor - if (XMatchVisualInfo(x_display, screen, xdepth, StaticGray, &visualInfo) - || XMatchVisualInfo(x_display, screen, xdepth, StaticColor, &visualInfo)) - visual_found = true; - break; - case 8: // Need PseudoColor - if (XMatchVisualInfo(x_display, screen, xdepth, PseudoColor, &visualInfo)) - visual_found = true; - break; - case 15: - case 16: - case 24: - case 32: // Try DirectColor first, as this will allow gamma correction - if (XMatchVisualInfo(x_display, screen, xdepth, DirectColor, &visualInfo) - || XMatchVisualInfo(x_display, screen, xdepth, TrueColor, &visualInfo)) - visual_found = true; - break; - default: - D(bug(" not a supported depth\n")); - break; - } - } - if (!visual_found) - return false; - - // Visual was found - vis = visualInfo.visual; - color_class = visualInfo.c_class; - D(bug(" found visual ID 0x%02x, depth %d, class ", visualInfo.visualid, xdepth)); -#if DEBUG - switch (color_class) { - case StaticGray: D(bug("StaticGray\n")); break; - case GrayScale: D(bug("GrayScale\n")); break; - case StaticColor: D(bug("StaticColor\n")); break; - case PseudoColor: D(bug("PseudoColor\n")); break; - case TrueColor: D(bug("TrueColor\n")); break; - case DirectColor: D(bug("DirectColor\n")); break; - } -#endif - return true; -} - - -/* - * Open display (window or fullscreen) - */ - -// Set window name and class -static void set_window_name(Window w, int name) -{ - const char *str = GetString(name); - XStoreName(x_display, w, str); - XSetIconName(x_display, w, str); - - XClassHint *hints; - hints = XAllocClassHint(); - if (hints) { - hints->res_name = "SheepShaver"; - hints->res_class = "SheepShaver"; - XSetClassHint(x_display, w, hints); - XFree(hints); - } -} - -// Set window input focus flag -static void set_window_focus(Window w) -{ - XWMHints *hints = XAllocWMHints(); - if (hints) { - hints->input = True; - hints->initial_state = NormalState; - hints->flags = InputHint | StateHint; - XSetWMHints(x_display, w, hints); - XFree(hints); - } -} - -// Set WM_DELETE_WINDOW protocol on window (preventing it from being destroyed by the WM when clicking on the "close" widget) -static Atom WM_DELETE_WINDOW = (Atom)0; -static void set_window_delete_protocol(Window w) -{ - WM_DELETE_WINDOW = XInternAtom(x_display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(x_display, w, &WM_DELETE_WINDOW, 1); -} - -// Wait until window is mapped/unmapped -static void wait_mapped(Window w) -{ - XEvent e; - do { - XMaskEvent(x_display, StructureNotifyMask, &e); - } while ((e.type != MapNotify) || (e.xmap.event != w)); -} - -static void wait_unmapped(Window w) -{ - XEvent e; - do { - XMaskEvent(x_display, StructureNotifyMask, &e); - } while ((e.type != UnmapNotify) || (e.xmap.event != w)); -} - -// Disable mouse acceleration -static void disable_mouse_accel(void) -{ - XChangePointerControl(x_display, True, False, 1, 1, 0); -} - -// Restore mouse acceleration to original value -static void restore_mouse_accel(void) -{ - XChangePointerControl(x_display, True, True, orig_accel_numer, orig_accel_denom, orig_threshold); -} - -// Trap SHM errors -static bool shm_error = false; -static int (*old_error_handler)(Display *, XErrorEvent *); - -static int error_handler(Display *d, XErrorEvent *e) -{ - if (e->error_code == BadAccess) { - shm_error = true; - return 0; - } else - return old_error_handler(d, e); -} - -// Open window -static bool open_window(int width, int height) -{ - int aligned_width = (width + 15) & ~15; - int aligned_height = (height + 15) & ~15; - - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - // Create window - XSetWindowAttributes wattr; - wattr.event_mask = eventmask = win_eventmask; - wattr.background_pixel = (vis == DefaultVisual(x_display, screen) ? black_pixel : 0); - wattr.border_pixel = 0; - wattr.backing_store = NotUseful; - wattr.colormap = (depth == 1 ? DefaultColormap(x_display, screen) : cmap[0]); - the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth, - InputOutput, vis, CWEventMask | CWBackPixel | CWBorderPixel | CWBackingStore | CWColormap, &wattr); - - // Set window name/class - set_window_name(the_win, STR_WINDOW_TITLE); - - // Indicate that we want keyboard input - set_window_focus(the_win); - - // Set delete protocol property - set_window_delete_protocol(the_win); - - // Make window unresizable - XSizeHints *hints; - if ((hints = XAllocSizeHints()) != NULL) { - hints->min_width = width; - hints->max_width = width; - hints->min_height = height; - hints->max_height = height; - hints->flags = PMinSize | PMaxSize; - XSetWMNormalHints(x_display, the_win, hints); - XFree((char *)hints); - } - - // Show window - XMapWindow(x_display, the_win); - wait_mapped(the_win); - - // 1-bit mode is big-endian; if the X server is little-endian, we can't - // use SHM because that doesn't allow changing the image byte order - bool need_msb_image = (depth == 1 && XImageByteOrder(x_display) == LSBFirst); - - // Try to create and attach SHM image - have_shm = false; - if (local_X11 && !need_msb_image && XShmQueryExtension(x_display)) { - - // Create SHM image ("height + 2" for safety) - img = XShmCreateImage(x_display, vis, depth == 1 ? 1 : xdepth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height); - shminfo.shmid = shmget(IPC_PRIVATE, (aligned_height + 2) * img->bytes_per_line, IPC_CREAT | 0777); - D(bug(" shm image created\n")); - the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0); - shminfo.shmaddr = img->data = (char *)the_buffer_copy; - shminfo.readOnly = False; - - // Try to attach SHM image, catching errors - shm_error = false; - old_error_handler = XSetErrorHandler(error_handler); - XShmAttach(x_display, &shminfo); - XSync(x_display, false); - XSetErrorHandler(old_error_handler); - if (shm_error) { - shmdt(shminfo.shmaddr); - XDestroyImage(img); - shminfo.shmid = -1; - } else { - have_shm = true; - shmctl(shminfo.shmid, IPC_RMID, 0); - } - D(bug(" shm image attached\n")); - } - - // Create normal X image if SHM doesn't work ("height + 2" for safety) - if (!have_shm) { - int bytes_per_row = depth == 1 ? aligned_width/8 : TrivialBytesPerRow(aligned_width, DepthModeForPixelDepth(xdepth)); - the_buffer_copy = (uint8 *)malloc((aligned_height + 2) * bytes_per_row); - img = XCreateImage(x_display, vis, depth == 1 ? 1 : xdepth, depth == 1 ? XYBitmap : ZPixmap, 0, (char *)the_buffer_copy, aligned_width, aligned_height, 32, bytes_per_row); - D(bug(" X image created\n")); - } - - // 1-Bit mode is big-endian - if (need_msb_image) { - img->byte_order = MSBFirst; - img->bitmap_bit_order = MSBFirst; - } - -#ifdef ENABLE_VOSF - use_vosf = true; - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - the_host_buffer = the_buffer_copy; - the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line); - the_buffer = (uint8 *)vm_acquire(the_buffer_size); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); -#else - // Allocate memory for frame buffer - the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line); - D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); -#endif - screen_base = Host2MacAddr(the_buffer); - - // Create GC - the_gc = XCreateGC(x_display, the_win, 0, 0); - XSetState(x_display, the_gc, black_pixel, white_pixel, GXcopy, AllPlanes); - - // Create cursor - if (hw_mac_cursor_accl) { - cursor_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)MacCursor + 4, 16, 16, 16, 2); - cursor_image->byte_order = MSBFirst; - cursor_image->bitmap_bit_order = MSBFirst; - cursor_mask_image = XCreateImage(x_display, vis, 1, XYPixmap, 0, (char *)MacCursor + 36, 16, 16, 16, 2); - cursor_mask_image->byte_order = MSBFirst; - cursor_mask_image->bitmap_bit_order = MSBFirst; - cursor_map = XCreatePixmap(x_display, the_win, 16, 16, 1); - cursor_mask_map = XCreatePixmap(x_display, the_win, 16, 16, 1); - cursor_gc = XCreateGC(x_display, cursor_map, 0, 0); - cursor_mask_gc = XCreateGC(x_display, cursor_mask_map, 0, 0); - mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, 0, 0); - cursor_changed = false; - } - - // Create no_cursor - else { - mac_cursor = XCreatePixmapCursor(x_display, - XCreatePixmap(x_display, the_win, 1, 1, 1), - XCreatePixmap(x_display, the_win, 1, 1, 1), - &black, &white, 0, 0); - XDefineCursor(x_display, the_win, mac_cursor); - } - - // Init blitting routines - bool native_byte_order; -#ifdef WORDS_BIGENDIAN - native_byte_order = (XImageByteOrder(x_display) == MSBFirst); -#else - native_byte_order = (XImageByteOrder(x_display) == LSBFirst); -#endif -#ifdef ENABLE_VOSF - Screen_blitter_init(visualFormat, native_byte_order, depth); -#endif - - // Set bytes per row - XSync(x_display, false); - return true; -} - -// Open FBDev DGA display -static bool open_fbdev_dga(int width, int height) -{ -#ifdef ENABLE_FBDEV_DGA -#ifdef ENABLE_XF86_VIDMODE - // Switch to best mode - if (has_vidmode) { - int best = -1; - for (int i = 0; i < num_x_video_modes; i++) { - if (x_video_modes[i]->hdisplay == width && x_video_modes[i]->vdisplay == height) { - best = i; - break; - } - }; - assert(best != -1); - XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]); - XF86VidModeSetViewPort(x_display, screen, 0, 0); - D(bug("[fbdev] VideoMode %d: %d x %d @ %d\n", best, - x_video_modes[best]->hdisplay, x_video_modes[best]->vdisplay, - 1000 * x_video_modes[best]->dotclock / (x_video_modes[best]->htotal * x_video_modes[best]->vtotal))); - } -#endif - - if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo) != 0) { - D(bug("[fbdev] Can't get FSCREENINFO: %s\n", strerror(errno))); - return false; - } - D(bug("[fbdev] Device ID: %s\n", fb_finfo.id)); - D(bug("[fbdev] smem_start: %p [%d bytes]\n", fb_finfo.smem_start, fb_finfo.smem_len)); - - int fb_type = fb_finfo.type; - const char *fb_type_str = NULL; - switch (fb_type) { - case FB_TYPE_PACKED_PIXELS: fb_type_str = "Packed Pixels"; break; - case FB_TYPE_PLANES: fb_type_str = "Non interleaved planes"; break; - case FB_TYPE_INTERLEAVED_PLANES: fb_type_str = "Interleaved planes"; break; - case FB_TYPE_TEXT: fb_type_str = "Text/attributes"; break; - case FB_TYPE_VGA_PLANES: fb_type_str = "EGA/VGA planes"; break; - default: fb_type_str = ""; break; - } - D(bug("[fbdev] type: %s\n", fb_type_str)); - - if (fb_type != FB_TYPE_PACKED_PIXELS) { - D(bug("[fbdev] type '%s' not supported\n", fb_type_str)); - return false; - } - - int fb_visual = fb_finfo.visual; - const char *fb_visual_str; - switch (fb_visual) { - case FB_VISUAL_MONO01: fb_visual_str = "Monochrome 1=Black 0=White"; break; - case FB_VISUAL_MONO10: fb_visual_str = "Monochrome 1=While 0=Black"; break; - case FB_VISUAL_TRUECOLOR: fb_visual_str = "True color"; break; - case FB_VISUAL_PSEUDOCOLOR: fb_visual_str = "Pseudo color (like atari)"; break; - case FB_VISUAL_DIRECTCOLOR: fb_visual_str = "Direct color"; break; - case FB_VISUAL_STATIC_PSEUDOCOLOR: fb_visual_str = "Pseudo color readonly"; break; - default: fb_visual_str = ""; break; - } - D(bug("[fbdev] visual: %s\n", fb_visual_str)); - - if (fb_visual != FB_VISUAL_TRUECOLOR && fb_visual != FB_VISUAL_DIRECTCOLOR) { - D(bug("[fbdev] visual '%s' not supported\n", fb_visual_str)); - return false; - } - - // Map frame buffer - the_buffer = (uint8 *)mmap(NULL, fb_finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_dev_fd, 0); - if (the_buffer == MAP_FAILED) { - D(bug("[fbdev] Can't mmap /dev/fb0: %s\n", strerror(errno))); - return false; - } - - // Set absolute mouse mode - ADBSetRelMouseMode(false); - - // Create window - XSetWindowAttributes wattr; - wattr.event_mask = eventmask = dga_eventmask; - wattr.override_redirect = True; - the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth, - InputOutput, DefaultVisual(x_display, screen), - CWEventMask | CWOverrideRedirect, &wattr); - - // Show window - XMapRaised(x_display, the_win); - wait_mapped(the_win); - - // Grab mouse and keyboard - XGrabKeyboard(x_display, the_win, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, the_win, True, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, the_win, None, CurrentTime); - disable_mouse_accel(); - - // Create no_cursor - mac_cursor = XCreatePixmapCursor(x_display, - XCreatePixmap(x_display, the_win, 1, 1, 1), - XCreatePixmap(x_display, the_win, 1, 1, 1), - &black, &white, 0, 0); - XDefineCursor(x_display, the_win, mac_cursor); - - // Init blitting routines - int bytes_per_row = TrivialBytesPerRow((width + 7) & ~7, DepthModeForPixelDepth(depth)); -#if ENABLE_VOSF - // Extract current screen color masks (we are in True Color mode) - VisualFormat visualFormat; - visualFormat.depth = xdepth = DefaultDepth(x_display, screen); - XMatchVisualInfo(x_display, screen, xdepth, TrueColor, &visualInfo); - assert(visualFormat.depth == visualInfo.depth); - visualFormat.Rmask = visualInfo.red_mask; - visualFormat.Gmask = visualInfo.green_mask; - visualFormat.Bmask = visualInfo.blue_mask; - D(bug("[fbdev] %d bpp, (%08x,%08x,%08x)\n", - visualFormat.depth, - visualFormat.Rmask, visualFormat.Gmask, visualFormat.Bmask)); - D(bug("[fbdev] Mac depth %d bpp\n", depth)); - - // Screen_blitter_init() returns TRUE if VOSF is mandatory - // i.e. the framebuffer update function is not Blit_Copy_Raw -#ifdef WORDS_BIGENDIAN - const bool native_byte_order = (XImageByteOrder(x_display) == MSBFirst); -#else - const bool native_byte_order = (XImageByteOrder(x_display) == LSBFirst); -#endif - Screen_blitter_init(visualFormat, native_byte_order, depth); - - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - use_vosf = true; - the_host_buffer = the_buffer; - the_buffer_size = page_extend((height + 2) * bytes_per_row); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - the_buffer = (uint8 *)vm_acquire(the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); -#endif - - // Set frame buffer base - D(bug("the_buffer = %p, use_vosf = %d\n", the_buffer, use_vosf)); - screen_base = Host2MacAddr(the_buffer); - VModes[cur_mode].viRowBytes = bytes_per_row; - return true; -#else - ErrorAlert("SheepShaver has been compiled with DGA support disabled."); - return false; -#endif -} - -// Open XF86 DGA display (!! should use X11 VidMode extensions to set mode) -static bool open_xf86_dga(int width, int height) -{ - if (is_fbdev_dga_mode) - return false; - -#ifdef ENABLE_XF86_DGA - // Set relative mouse mode - ADBSetRelMouseMode(true); - - // Create window - XSetWindowAttributes wattr; - wattr.event_mask = eventmask = dga_eventmask; - wattr.override_redirect = True; - wattr.colormap = (depth == 1 ? DefaultColormap(x_display, screen) : cmap[0]); - the_win = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth, - InputOutput, vis, CWEventMask | CWOverrideRedirect | - (color_class == DirectColor ? CWColormap : 0), &wattr); - - // Show window - XMapRaised(x_display, the_win); - wait_mapped(the_win); - -#ifdef ENABLE_XF86_VIDMODE - // Switch to best mode - if (has_vidmode) { - int best = 0; - for (int i=1; ihdisplay >= width && x_video_modes[i]->vdisplay >= height && - x_video_modes[i]->hdisplay <= x_video_modes[best]->hdisplay && x_video_modes[i]->vdisplay <= x_video_modes[best]->vdisplay) { - best = i; - } - } - XF86VidModeSwitchToMode(x_display, screen, x_video_modes[best]); - XF86VidModeSetViewPort(x_display, screen, 0, 0); - } -#endif - - // Establish direct screen connection - XMoveResizeWindow(x_display, the_win, 0, 0, width, height); - XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0); - XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - - int v_width, v_bank, v_size; - XF86DGAGetVideo(x_display, screen, (char **)&the_buffer, &v_width, &v_bank, &v_size); - XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse); - XF86DGASetViewPort(x_display, screen, 0, 0); - XF86DGASetVidPage(x_display, screen, 0); - - // Set colormap - if (!IsDirectMode(get_current_mode())) { - XSetWindowColormap(x_display, the_win, cmap[current_dga_cmap = 0]); - XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); - } - XSync(x_display, false); - - // Init blitting routines - int bytes_per_row = TrivialBytesPerRow((v_width + 7) & ~7, DepthModeForPixelDepth(depth)); -#if ENABLE_VOSF - bool native_byte_order; -#ifdef WORDS_BIGENDIAN - native_byte_order = (XImageByteOrder(x_display) == MSBFirst); -#else - native_byte_order = (XImageByteOrder(x_display) == LSBFirst); -#endif -#if REAL_ADDRESSING || DIRECT_ADDRESSING - // Screen_blitter_init() returns TRUE if VOSF is mandatory - // i.e. the framebuffer update function is not Blit_Copy_Raw - use_vosf = Screen_blitter_init(visualFormat, native_byte_order, depth); - - if (use_vosf) { - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - the_host_buffer = the_buffer; - the_buffer_size = page_extend((height + 2) * bytes_per_row); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - the_buffer = (uint8 *)vm_acquire(the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); - } -#else - use_vosf = false; -#endif -#endif - - // Set frame buffer base - D(bug("the_buffer = %p, use_vosf = %d\n", the_buffer, use_vosf)); - screen_base = Host2MacAddr(the_buffer); - VModes[cur_mode].viRowBytes = bytes_per_row; - return true; -#else - ErrorAlert("SheepShaver has been compiled with DGA support disabled."); - return false; -#endif -} - -// Open DGA display -static bool open_dga(int width, int height) -{ - bool display_open; - - display_open = open_xf86_dga(width, height); -#ifdef ENABLE_FBDEV_DGA - // Try to fallback to FBDev DGA mode - if (!display_open) { - is_fbdev_dga_mode = true; - display_open = open_fbdev_dga(width, height); - } -#endif - - // Common DGA display initialization - if (display_open) { - - // Fake image to get display bounds in the refresh function - if ((img = (XImage *)malloc(sizeof(*img))) == NULL) - return false; - img->width = DisplayWidth(x_display, screen); - img->height = DisplayHeight(x_display, screen); - img->depth = is_fbdev_dga_mode ? xdepth : depth; - img->bytes_per_line = TrivialBytesPerRow(img->width, DepthModeForPixelDepth(img->depth)); - } - - return display_open; -} - -static bool open_display(void) -{ - D(bug("open_display()\n")); - const VideoInfo &mode = VModes[cur_mode]; - - // Get original mouse acceleration - XGetPointerControl(x_display, &orig_accel_numer, &orig_accel_denom, &orig_threshold); - - // Find best available X visual - if (!find_visual_for_depth(mode.viAppleMode)) { - ErrorAlert(GetString(STR_NO_XVISUAL_ERR)); - return false; - } - - // Build up visualFormat structure - visualFormat.fullscreen = (display_type == DIS_SCREEN); - visualFormat.depth = visualInfo.depth; - visualFormat.Rmask = visualInfo.red_mask; - visualFormat.Gmask = visualInfo.green_mask; - visualFormat.Bmask = visualInfo.blue_mask; - - // Create color maps - if (color_class == PseudoColor || color_class == DirectColor) { - cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll); - cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll); - } else { - cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocNone); - cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocNone); - } - - // Find pixel format of direct modes - if (color_class == DirectColor || color_class == TrueColor) { - rshift = gshift = bshift = 0; - rloss = gloss = bloss = 8; - uint32 mask; - for (mask=vis->red_mask; !(mask&1); mask>>=1) - ++rshift; - for (; mask&1; mask>>=1) - --rloss; - for (mask=vis->green_mask; !(mask&1); mask>>=1) - ++gshift; - for (; mask&1; mask>>=1) - --gloss; - for (mask=vis->blue_mask; !(mask&1); mask>>=1) - ++bshift; - for (; mask&1; mask>>=1) - --bloss; - } - - // Preset palette pixel values for CLUT or gamma table - if (color_class == DirectColor) { - int num = vis->map_entries; - for (int i=0; imap_entries : 256); - for (int i=0; i16/32 expand map - if (!IsDirectMode(get_current_mode()) && xdepth > 8) - for (int i=0; i<256; i++) - ExpandMap[i] = map_rgb(i, i, i); -#endif - - // Create display of requested type - display_type = mode.viType; - depth = depth_of_video_mode(mode.viAppleMode); - - bool display_open; - switch (display_type) { - case DIS_SCREEN: - display_open = open_dga(VModes[cur_mode].viXsize, VModes[cur_mode].viYsize); - break; - case DIS_WINDOW: - display_open = open_window(VModes[cur_mode].viXsize, VModes[cur_mode].viYsize); - break; - default: - display_open = false; - break; - } - -#ifdef ENABLE_VOSF - if (use_vosf) { - // Initialize the VOSF system - LOCK_VOSF; - if (!video_vosf_init()) { - ErrorAlert(GetString(STR_VOSF_INIT_ERR)); - UNLOCK_VOSF; - return false; - } - UNLOCK_VOSF; - } -#endif - - // Zero screen buffers, viRowBytes is initialized at this stage - if (display_open) { - memset(the_buffer, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - memset(the_buffer_copy, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - } - return display_open; -} - - -/* - * Close display - */ - -// Close window -static void close_window(void) -{ - if (have_shm) { - XShmDetach(x_display, &shminfo); -#ifdef ENABLE_VOSF - the_host_buffer = NULL; // don't free() in driver_base dtor -#else - the_buffer_copy = NULL; // don't free() in driver_base dtor -#endif - } - if (img) { - if (!have_shm) - img->data = NULL; - XDestroyImage(img); - } - if (have_shm) { - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); - } - if (the_gc) - XFreeGC(x_display, the_gc); - - XFlush(x_display); - XSync(x_display, false); -} - -// Close FBDev mode -static void close_fbdev_dga(void) -{ -#ifdef ENABLE_FBDEV_DGA - uint8 *fb_base; - if (!use_vosf) - fb_base = the_buffer; -#ifdef ENABLE_VOSF - else - fb_base = the_host_buffer; -#endif - munmap(fb_base, fb_finfo.smem_len); -#endif -} - -// Close XF86 DGA mode -static void close_xf86_dga(void) -{ -#ifdef ENABLE_XF86_DGA - XF86DGADirectVideo(x_display, screen, 0); -#endif -} - -// Close DGA mode -static void close_dga(void) -{ - if (is_fbdev_dga_mode) - close_fbdev_dga(); - else - close_xf86_dga(); - - XUngrabPointer(x_display, CurrentTime); - XUngrabKeyboard(x_display, CurrentTime); - -#ifdef ENABLE_XF86_VIDMODE - if (has_vidmode) - XF86VidModeSwitchToMode(x_display, screen, x_video_modes[0]); -#endif - - // Release fake image (it's not a normal XImage!) - free(img); - img = NULL; - - if (!use_vosf) { - // don't free() the screen buffer in driver_base dtor - the_buffer = NULL; - } -#ifdef ENABLE_VOSF - else { - // don't free() the screen buffer in driver_base dtor - the_host_buffer = NULL; - } -#endif -} - -static void close_display(void) -{ - if (display_type == DIS_SCREEN) - close_dga(); - else if (display_type == DIS_WINDOW) - close_window(); - - // Close window - if (the_win) { - XUnmapWindow(x_display, the_win); - wait_unmapped(the_win); - XDestroyWindow(x_display, the_win); - } - - // Free colormaps - if (cmap[0]) { - XFreeColormap(x_display, cmap[0]); - cmap[0] = 0; - } - if (cmap[1]) { - XFreeColormap(x_display, cmap[1]); - cmap[1] = 0; - } - -#ifdef ENABLE_VOSF - if (use_vosf) { - // Deinitialize VOSF - video_vosf_exit(); - } -#endif - - // Free frame buffer(s) - if (!use_vosf) { - if (the_buffer_copy) { - free(the_buffer_copy); - the_buffer_copy = NULL; - } - } -#ifdef ENABLE_VOSF - else { - // the_buffer shall always be mapped through vm_acquire() so that we can vm_protect() it at will - if (the_buffer != VM_MAP_FAILED) { - D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); - vm_release(the_buffer, the_buffer_size); - the_buffer = NULL; - } - if (the_host_buffer) { - D(bug(" freeing the_host_buffer at %p\n", the_host_buffer)); - free(the_host_buffer); - the_host_buffer = NULL; - } - if (the_buffer_copy) { - D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy)); - free(the_buffer_copy); - the_buffer_copy = NULL; - } - } -#endif - - // Restore mouse acceleration - restore_mouse_accel(); -} - - -/* - * Initialization - */ - -// Init keycode translation table -static void keycode_init(void) -{ - bool use_kc = PrefsFindBool("keycodes"); - if (use_kc) { - - // Get keycode file path from preferences - const char *kc_path = PrefsFindString("keycodefile"); - - // Open keycode table - FILE *f = fopen(kc_path ? kc_path : KEYCODE_FILE_NAME, "r"); - if (f == NULL) { - char str[256]; - sprintf(str, GetString(STR_KEYCODE_FILE_WARN), kc_path ? kc_path : KEYCODE_FILE_NAME, strerror(errno)); - WarningAlert(str); - return; - } - - // Default translation table - for (int i=0; i<256; i++) - keycode_table[i] = -1; - - // Search for server vendor string, then read keycodes - const char *vendor = ServerVendor(x_display); - // Force use of MacX mappings on MacOS X with Apple's X server - int dummy; - if (XQueryExtension(x_display, "Apple-DRI", &dummy, &dummy, &dummy)) - vendor = "MacX"; - bool vendor_found = false; - char line[256]; - while (fgets(line, 255, f)) { - // Read line - int len = strlen(line); - if (len == 0) - continue; - line[len-1] = 0; - - // Comments begin with "#" or ";" - if (line[0] == '#' || line[0] == ';' || line[0] == 0) - continue; - - if (vendor_found) { - // Read keycode - int x_code, mac_code; - if (sscanf(line, "%d %d", &x_code, &mac_code) == 2) - keycode_table[x_code & 0xff] = mac_code; - else - break; - } else { - // Search for vendor string - if (strstr(vendor, line) == vendor) - vendor_found = true; - } - } - - // Keycode file completely read - fclose(f); - use_keycodes = vendor_found; - - // Vendor not found? Then display warning - if (!vendor_found) { - char str[256]; - sprintf(str, GetString(STR_KEYCODE_VENDOR_WARN), vendor, kc_path ? kc_path : KEYCODE_FILE_NAME); - WarningAlert(str); - return; - } - } -} - -// Find Apple mode matching best specified dimensions -static int find_apple_resolution(int xsize, int ysize) -{ - int apple_id; - if (xsize < 800) - apple_id = APPLE_640x480; - else if (xsize < 1024) - apple_id = APPLE_800x600; - else if (xsize < 1152) - apple_id = APPLE_1024x768; - else if (xsize < 1280) { - if (ysize < 900) - apple_id = APPLE_1152x768; - else - apple_id = APPLE_1152x900; - } - else if (xsize < 1600) - apple_id = APPLE_1280x1024; - else - apple_id = APPLE_1600x1200; - return apple_id; -} - -// Find mode in list of supported modes -static int find_mode(int apple_mode, int apple_id, int type) -{ - for (VideoInfo *p = VModes; p->viType != DIS_INVALID; p++) { - if (p->viType == type && p->viAppleID == apple_id && p->viAppleMode == apple_mode) - return p - VModes; - } - return -1; -} - -// Add custom video mode -static void add_custom_mode(VideoInfo *&p, int type, uint32 x, uint32 y, int apple_mode, int apple_id) -{ - p->viType = type; - p->viXsize = x; - p->viYsize = y; - p->viRowBytes = TrivialBytesPerRow(p->viXsize, apple_mode); - p->viAppleMode = apple_mode; - p->viAppleID = apple_id; - p++; -} - -// Add mode to list of supported modes -static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, int apple_mode, int apple_id, int type) -{ - if (allow & test) { - uint32 x = 0, y = 0; - switch (apple_id) { - case APPLE_W_640x480: - case APPLE_640x480: - x = 640; - y = 480; - break; - case APPLE_W_800x600: - case APPLE_800x600: - x = 800; - y = 600; - break; - case APPLE_1024x768: - x = 1024; - y = 768; - break; - case APPLE_1152x768: - x = 1152; - y = 768; - break; - case APPLE_1152x900: - x = 1152; - y = 900; - break; - case APPLE_1280x1024: - x = 1280; - y = 1024; - break; - case APPLE_1600x1200: - x = 1600; - y = 1200; - break; - } - add_custom_mode(p, type, x, y, apple_mode, apple_id); - } -} - -// Add standard list of windowed modes for given color depth -static void add_window_modes(VideoInfo *&p, int window_modes, int mode) -{ - add_mode(p, window_modes, 1, mode, APPLE_W_640x480, DIS_WINDOW); - add_mode(p, window_modes, 2, mode, APPLE_W_800x600, DIS_WINDOW); -} - -static bool has_mode(int x, int y) -{ -#ifdef ENABLE_XF86_VIDMODE - if (has_vidmode) { - for (int i=0; ihdisplay == x && x_video_modes[i]->vdisplay == y) - return true; - return false; - } -#endif - return DisplayWidth(x_display, screen) >= x && DisplayHeight(x_display, screen) >= y; -} - -bool VideoInit(void) -{ -#ifdef ENABLE_VOSF - // Zero the mainBuffer structure - mainBuffer.dirtyPages = NULL; - mainBuffer.pageInfo = NULL; -#endif - - // Check if X server runs on local machine - local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0) - || (strncmp(XDisplayName(x_display_name), "/", 1) == 0) - || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0); - - // Init keycode translation - keycode_init(); - - // Read frame skip prefs - frame_skip = PrefsFindInt32("frameskip"); - if (frame_skip == 0) - frame_skip = 1; - - // Read mouse wheel prefs - mouse_wheel_mode = PrefsFindInt32("mousewheelmode"); - mouse_wheel_lines = PrefsFindInt32("mousewheellines"); - - // Init variables - private_data = NULL; - video_activated = true; - - // Find screen and root window - screen = XDefaultScreen(x_display); - rootwin = XRootWindow(x_display, screen); - - // Get sorted list of available depths - avail_depths = XListDepths(x_display, screen, &num_depths); - if (avail_depths == NULL) { - ErrorAlert(GetString(STR_UNSUPP_DEPTH_ERR)); - return false; - } - sort(avail_depths, avail_depths + num_depths); - - // Get screen depth - xdepth = DefaultDepth(x_display, screen); - -#ifdef ENABLE_XF86_DGA - // DGA available? - int event_base, error_base; - is_fbdev_dga_mode = false; - if (local_X11 && XF86DGAQueryExtension(x_display, &event_base, &error_base)) { - int dga_flags = 0; - XF86DGAQueryDirectVideo(x_display, screen, &dga_flags); - has_dga = dga_flags & XF86DGADirectPresent; -#if defined(__linux__) - // Check r/w permission on /dev/mem for DGA mode to work - if (has_dga && access("/dev/mem", R_OK | W_OK) != 0) - has_dga = false; -#endif - } else - has_dga = false; -#endif - -#ifdef ENABLE_XF86_VIDMODE - // VidMode available? - int vm_event_base, vm_error_base; - has_vidmode = XF86VidModeQueryExtension(x_display, &vm_event_base, &vm_error_base); - if (has_vidmode) { - int vm_major_version, vm_minor_version; - XF86VidModeQueryVersion(x_display, &vm_major_version, &vm_minor_version); - D(bug("VidMode extension %d.%d available\n", vm_major_version, vm_minor_version)); - XF86VidModeGetAllModeLines(x_display, screen, &num_x_video_modes, &x_video_modes); - } -#endif - -#ifdef ENABLE_FBDEV_DGA - // FBDev available? - bool has_fbdev_dga = false; - if (local_X11) { - if ((fb_dev_fd = open("/dev/fb0", O_RDWR)) > 0) { - if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo) != 0) - close(fb_dev_fd); - else { - has_fbdev_dga = true; - if (!has_dga) { - // Fallback to FBDev DGA mode if XF86 DGA is not possible - has_dga = true; - is_fbdev_dga_mode = true; - } - fb_orig_vinfo = fb_vinfo; - D(bug("Frame buffer device initial resolution: %dx%dx%d\n", fb_vinfo.xres, fb_vinfo.yres, fb_vinfo.bits_per_pixel)); - } - } - } -#endif - - // Find black and white colors - XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:00/00/00", &black); - XAllocColor(x_display, DefaultColormap(x_display, screen), &black); - XParseColor(x_display, DefaultColormap(x_display, screen), "rgb:ff/ff/ff", &white); - XAllocColor(x_display, DefaultColormap(x_display, screen), &white); - black_pixel = BlackPixel(x_display, screen); - white_pixel = WhitePixel(x_display, screen); - - // Mac screen depth follows X depth (for now) - int default_mode = APPLE_8_BIT; - switch (DefaultDepth(x_display, screen)) { - case 1: - default_mode = APPLE_1_BIT; - break; - case 8: - default_mode = APPLE_8_BIT; - break; - case 15: case 16: - default_mode = APPLE_16_BIT; - break; - case 24: case 32: - default_mode = APPLE_32_BIT; - break; - } - - // Get screen mode from preferences - const char *mode_str = PrefsFindString("screen"); - int default_width = 640, default_height = 480; - if (mode_str) { - display_type = DIS_INVALID; - if (sscanf(mode_str, "win/%d/%d", &default_width, &default_height) == 2) - display_type = DIS_WINDOW; -#ifdef ENABLE_XF86_DGA - else if (has_dga && sscanf(mode_str, "dga/%d/%d", &default_width, &default_height) == 2) - display_type = DIS_SCREEN; -#endif -#ifdef ENABLE_FBDEV_DGA - else if (has_fbdev_dga && sscanf(mode_str, "fbdev/%d/%d", &default_width, &default_height) == 2) { - is_fbdev_dga_mode = true; - display_type = DIS_SCREEN; - } -#endif - if (display_type == DIS_INVALID) { - D(bug("Invalid screen mode specified, defaulting to old modes selection\n")); - mode_str = NULL; - } - else { - if (default_width <= 0) - default_width = DisplayWidth(x_display, screen); - else if (default_width > DisplayWidth(x_display, screen)) - default_width = DisplayWidth(x_display, screen); - if (default_height <= 0) - default_height = DisplayHeight(x_display, screen); - else if (default_height > DisplayHeight(x_display, screen)) - default_height = DisplayHeight(x_display, screen); - } - } - - // Construct video mode table - uint32 window_modes = PrefsFindInt32("windowmodes"); - uint32 screen_modes = PrefsFindInt32("screenmodes"); - if (!has_dga) - screen_modes = 0; - if (mode_str) - window_modes = screen_modes = 0; - else if (window_modes == 0 && screen_modes == 0) - window_modes |= 3; // Allow at least 640x480 and 800x600 window modes - - VideoInfo *p = VModes; - if (mode_str) { - if (display_type == DIS_WINDOW) { - for (unsigned int d = APPLE_1_BIT; d <= APPLE_32_BIT; d++) { - if (find_visual_for_depth(d)) { - if (default_width > 640 && default_height > 480) - add_mode(p, 3, 1, d, APPLE_W_640x480, DIS_WINDOW); - if (default_width > 800 && default_height > 600) - add_mode(p, 3, 2, d, APPLE_W_800x600, DIS_WINDOW); - add_custom_mode(p, display_type, default_width, default_height, d, APPLE_CUSTOM); - } - } -#ifdef ENABLE_VOSF - } else if (display_type == DIS_SCREEN && is_fbdev_dga_mode) { - for (unsigned int d = APPLE_1_BIT; d <= default_mode; d++) - if (find_visual_for_depth(d)) - add_custom_mode(p, display_type, default_width, default_height, d, APPLE_CUSTOM); -#endif - } else - add_custom_mode(p, display_type, default_width, default_height, default_mode, APPLE_CUSTOM); - - // Add extra VidMode capable modes - if (display_type == DIS_SCREEN) { - struct { - int w; - int h; - int apple_id; - } - video_modes[] = { - { 640, 480, APPLE_640x480 }, - { 800, 600, APPLE_800x600 }, - { 1024, 768, APPLE_1024x768 }, - { 1152, 768, APPLE_1152x768 }, - { 1152, 900, APPLE_1152x900 }, - { 1280, 1024, APPLE_1280x1024 }, - { 1600, 1200, APPLE_1600x1200 }, - { 0, } - }; - - for (int i = 0; video_modes[i].w != 0; i++) { - const int w = video_modes[i].w; - const int h = video_modes[i].h; - if (w >= default_width || h >= default_height) - continue; - if (has_mode(w, h)) { -#ifdef ENABLE_VOSF - if (is_fbdev_dga_mode) { - for (unsigned int d = APPLE_1_BIT; d <= default_mode; d++) - if (find_visual_for_depth(d)) - add_custom_mode(p, display_type, w, h, d, video_modes[i].apple_id); - } else -#endif - add_custom_mode(p, display_type, w, h, default_mode, video_modes[i].apple_id); - } - } - } - } else if (window_modes) { - for (unsigned int d = APPLE_1_BIT; d <= APPLE_32_BIT; d++) - if (find_visual_for_depth(d)) - add_window_modes(p, window_modes, d); - } else if (has_vidmode) { - if (has_mode(640, 480)) - add_mode(p, screen_modes, 1, default_mode, APPLE_640x480, DIS_SCREEN); - if (has_mode(800, 600)) - add_mode(p, screen_modes, 2, default_mode, APPLE_800x600, DIS_SCREEN); - if (has_mode(1024, 768)) - add_mode(p, screen_modes, 4, default_mode, APPLE_1024x768, DIS_SCREEN); - if (has_mode(1152, 768)) - add_mode(p, screen_modes, 64, default_mode, APPLE_1152x768, DIS_SCREEN); - if (has_mode(1152, 900)) - add_mode(p, screen_modes, 8, default_mode, APPLE_1152x900, DIS_SCREEN); - if (has_mode(1280, 1024)) - add_mode(p, screen_modes, 16, default_mode, APPLE_1280x1024, DIS_SCREEN); - if (has_mode(1600, 1200)) - add_mode(p, screen_modes, 32, default_mode, APPLE_1600x1200, DIS_SCREEN); - } else if (screen_modes) { - int xsize = DisplayWidth(x_display, screen); - int ysize = DisplayHeight(x_display, screen); - int apple_id = find_apple_resolution(xsize, ysize); - p->viType = DIS_SCREEN; - p->viRowBytes = 0; - p->viXsize = xsize; - p->viYsize = ysize; - p->viAppleMode = default_mode; - p->viAppleID = apple_id; - p++; - } - p->viType = DIS_INVALID; // End marker - p->viRowBytes = 0; - p->viXsize = p->viYsize = 0; - p->viAppleMode = 0; - p->viAppleID = 0; - - // Find default mode (window 640x480) - cur_mode = -1; - if (has_dga && screen_modes) { - int screen_width = DisplayWidth(x_display, screen); - int screen_height = DisplayHeight(x_display, screen); - int apple_id = find_apple_resolution(screen_width, screen_height); - if (apple_id != -1) - cur_mode = find_mode(default_mode, apple_id, DIS_SCREEN); - } else if (has_dga && mode_str) - cur_mode = find_mode(default_mode, APPLE_CUSTOM, DIS_SCREEN); - - if (cur_mode == -1) { - // pick up first windowed mode available - for (VideoInfo *p = VModes; p->viType != DIS_INVALID; p++) { - if (p->viType == DIS_WINDOW && p->viAppleMode == default_mode) { - cur_mode = p - VModes; - break; - } - } - } - assert(cur_mode != -1); - -#if DEBUG - D(bug("Available video modes:\n")); - for (p = VModes; p->viType != DIS_INVALID; p++) { - int bits = depth_of_video_mode(p->viAppleMode); - D(bug(" %dx%d (ID %02x), %d colors\n", p->viXsize, p->viYsize, p->viAppleID, 1 << bits)); - } -#endif - - // Open window/screen - if (!open_display()) { - ErrorAlert(GetString(STR_OPEN_WINDOW_ERR)); - return false; - } - -#if 0 - // Ignore errors from now on - XSetErrorHandler(ignore_errors); -#endif - - // Lock down frame buffer - XSync(x_display, false); - LOCK_FRAME_BUFFER; - - // Start periodic thread - XSync(x_display, false); - if (sem_init(&thread_stop_ack, 0, 0) < 0) - return false; - if (sem_init(&thread_resume_req, 0, 0) < 0) - return false; - Set_pthread_attr(&redraw_thread_attr, 0); - redraw_thread_cancel = false; - redraw_thread_active = (pthread_create(&redraw_thread, &redraw_thread_attr, redraw_func, NULL) == 0); - D(bug("Redraw thread installed (%ld)\n", redraw_thread)); - return true; -} - - -/* - * Deinitialization - */ - -void VideoExit(void) -{ - // Stop redraw thread - if (redraw_thread_active) { - redraw_thread_cancel = true; - pthread_cancel(redraw_thread); - pthread_join(redraw_thread, NULL); - sem_destroy(&thread_stop_ack); - sem_destroy(&thread_resume_req); - redraw_thread_active = false; - } - - // Unlock frame buffer - UNLOCK_FRAME_BUFFER; - XSync(x_display, false); - D(bug(" frame buffer unlocked\n")); - -#ifdef ENABLE_VOSF - if (use_vosf) { - // Deinitialize VOSF - video_vosf_exit(); - } -#endif - - // Close window and server connection - if (x_display != NULL) { - XSync(x_display, false); - close_display(); - XFlush(x_display); - XSync(x_display, false); - } - -#ifdef ENABLE_FBDEV_DGA - // Close framebuffer device - if (fb_dev_fd >= 0) { - close(fb_dev_fd); - fb_dev_fd = -1; - } -#endif -} - - -/* - * Suspend/resume emulator - */ - -static void suspend_emul(void) -{ - if (display_type == DIS_SCREEN) { - // Release ctrl key - ADBKeyUp(0x36); - ctrl_down = false; - - // Lock frame buffer (this will stop the MacOS thread) - LOCK_FRAME_BUFFER; - - // Save frame buffer - fb_save = malloc(VModes[cur_mode].viYsize * VModes[cur_mode].viRowBytes); - if (fb_save) - Mac2Host_memcpy(fb_save, screen_base, VModes[cur_mode].viYsize * VModes[cur_mode].viRowBytes); - - // Close full screen display -#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA) -#ifdef ENABLE_XF86_DGA - if (!is_fbdev_dga_mode) - XF86DGADirectVideo(x_display, screen, 0); -#endif - XUngrabPointer(x_display, CurrentTime); - XUngrabKeyboard(x_display, CurrentTime); -#endif - restore_mouse_accel(); - XUnmapWindow(x_display, the_win); - wait_unmapped(the_win); - XSync(x_display, false); - - // Open "suspend" window - XSetWindowAttributes wattr; - wattr.event_mask = KeyPressMask; - wattr.background_pixel = (vis == DefaultVisual(x_display, screen) ? black_pixel : 0); - wattr.backing_store = Always; - wattr.colormap = (depth == 1 ? DefaultColormap(x_display, screen) : cmap[0]); - - suspend_win = XCreateWindow(x_display, rootwin, 0, 0, 512, 1, 0, xdepth, - InputOutput, vis, CWEventMask | CWBackPixel | CWBackingStore | CWColormap, &wattr); - set_window_name(suspend_win, STR_SUSPEND_WINDOW_TITLE); - set_window_focus(suspend_win); - XMapWindow(x_display, suspend_win); - emul_suspended = true; - } -} - -static void resume_emul(void) -{ - // Close "suspend" window - XDestroyWindow(x_display, suspend_win); - XSync(x_display, false); - - // Reopen full screen display - XMapRaised(x_display, the_win); - wait_mapped(the_win); - XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0); - Window w = is_fbdev_dga_mode ? the_win : rootwin; - XGrabKeyboard(x_display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(x_display, w, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, is_fbdev_dga_mode ? w : None, None, CurrentTime); - disable_mouse_accel(); -#ifdef ENABLE_XF86_DGA - if (!is_fbdev_dga_mode) { - XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse); - XF86DGASetViewPort(x_display, screen, 0, 0); - } -#endif - XSync(x_display, false); - - // the_buffer already contains the data to restore. i.e. since a temporary - // frame buffer is used when VOSF is actually used, fb_save is therefore - // not necessary. -#ifdef ENABLE_VOSF - if (use_vosf) { - LOCK_VOSF; - PFLAG_SET_ALL; - memset(the_buffer_copy, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - UNLOCK_VOSF; - } -#endif - - // Restore frame buffer - if (fb_save) { -#ifdef ENABLE_VOSF - // Don't copy fb_save to the temporary frame buffer in VOSF mode - if (!use_vosf) -#endif - Host2Mac_memcpy(screen_base, fb_save, VModes[cur_mode].viYsize * VModes[cur_mode].viRowBytes); - free(fb_save); - fb_save = NULL; - } - - // Unlock frame buffer (and continue MacOS thread) - UNLOCK_FRAME_BUFFER; - emul_suspended = false; -} - - -/* - * Close screen in full-screen mode - */ - -void VideoQuitFullScreen(void) -{ - D(bug("VideoQuitFullScreen()\n")); - if (display_type == DIS_SCREEN) { - quit_full_screen = true; - while (!quit_full_screen_ack) ; - } -} - - -/* - * X11 event handling - */ - -// Translate key event to Mac keycode -static int kc_decode(KeySym ks) -{ - switch (ks) { - case XK_A: case XK_a: return 0x00; - case XK_B: case XK_b: return 0x0b; - case XK_C: case XK_c: return 0x08; - case XK_D: case XK_d: return 0x02; - case XK_E: case XK_e: return 0x0e; - case XK_F: case XK_f: return 0x03; - case XK_G: case XK_g: return 0x05; - case XK_H: case XK_h: return 0x04; - case XK_I: case XK_i: return 0x22; - case XK_J: case XK_j: return 0x26; - case XK_K: case XK_k: return 0x28; - case XK_L: case XK_l: return 0x25; - case XK_M: case XK_m: return 0x2e; - case XK_N: case XK_n: return 0x2d; - case XK_O: case XK_o: return 0x1f; - case XK_P: case XK_p: return 0x23; - case XK_Q: case XK_q: return 0x0c; - case XK_R: case XK_r: return 0x0f; - case XK_S: case XK_s: return 0x01; - case XK_T: case XK_t: return 0x11; - case XK_U: case XK_u: return 0x20; - case XK_V: case XK_v: return 0x09; - case XK_W: case XK_w: return 0x0d; - case XK_X: case XK_x: return 0x07; - case XK_Y: case XK_y: return 0x10; - case XK_Z: case XK_z: return 0x06; - - case XK_1: case XK_exclam: return 0x12; - case XK_2: case XK_at: return 0x13; - case XK_3: case XK_numbersign: return 0x14; - case XK_4: case XK_dollar: return 0x15; - case XK_5: case XK_percent: return 0x17; - case XK_6: return 0x16; - case XK_7: return 0x1a; - case XK_8: return 0x1c; - case XK_9: return 0x19; - case XK_0: return 0x1d; - - case XK_grave: case XK_asciitilde: return 0x0a; - case XK_minus: case XK_underscore: return 0x1b; - case XK_equal: case XK_plus: return 0x18; - case XK_bracketleft: case XK_braceleft: return 0x21; - case XK_bracketright: case XK_braceright: return 0x1e; - case XK_backslash: case XK_bar: return 0x2a; - case XK_semicolon: case XK_colon: return 0x29; - case XK_apostrophe: case XK_quotedbl: return 0x27; - case XK_comma: case XK_less: return 0x2b; - case XK_period: case XK_greater: return 0x2f; - case XK_slash: case XK_question: return 0x2c; - - case XK_Tab: if (ctrl_down) {suspend_emul(); return -1;} else return 0x30; - case XK_Return: return 0x24; - case XK_space: return 0x31; - case XK_BackSpace: return 0x33; - - case XK_Delete: return 0x75; - case XK_Insert: return 0x72; - case XK_Home: case XK_Help: return 0x73; - case XK_End: return 0x77; -#ifdef __hpux - case XK_Prior: return 0x74; - case XK_Next: return 0x79; -#else - case XK_Page_Up: return 0x74; - case XK_Page_Down: return 0x79; -#endif - - case XK_Control_L: return 0x36; - case XK_Control_R: return 0x36; - case XK_Shift_L: return 0x38; - case XK_Shift_R: return 0x38; - case XK_Alt_L: return 0x37; - case XK_Alt_R: return 0x37; - case XK_Meta_L: return 0x3a; - case XK_Meta_R: return 0x3a; - case XK_Menu: return 0x32; - case XK_Caps_Lock: return 0x39; - case XK_Num_Lock: return 0x47; - - case XK_Up: return 0x3e; - case XK_Down: return 0x3d; - case XK_Left: return 0x3b; - case XK_Right: return 0x3c; - - case XK_Escape: if (ctrl_down) {quit_full_screen = true; emerg_quit = true; return -1;} else return 0x35; - - case XK_F1: if (ctrl_down) {SysMountFirstFloppy(); return -1;} else return 0x7a; - case XK_F2: return 0x78; - case XK_F3: return 0x63; - case XK_F4: return 0x76; - case XK_F5: return 0x60; - case XK_F6: return 0x61; - case XK_F7: return 0x62; - case XK_F8: return 0x64; - case XK_F9: return 0x65; - case XK_F10: return 0x6d; - case XK_F11: return 0x67; - case XK_F12: return 0x6f; - - case XK_Print: return 0x69; - case XK_Scroll_Lock: return 0x6b; - case XK_Pause: return 0x71; - -#if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End) - case XK_KP_0: case XK_KP_Insert: return 0x52; - case XK_KP_1: case XK_KP_End: return 0x53; - case XK_KP_2: case XK_KP_Down: return 0x54; - case XK_KP_3: case XK_KP_Next: return 0x55; - case XK_KP_4: case XK_KP_Left: return 0x56; - case XK_KP_5: case XK_KP_Begin: return 0x57; - case XK_KP_6: case XK_KP_Right: return 0x58; - case XK_KP_7: case XK_KP_Home: return 0x59; - case XK_KP_8: case XK_KP_Up: return 0x5b; - case XK_KP_9: case XK_KP_Prior: return 0x5c; - case XK_KP_Decimal: case XK_KP_Delete: return 0x41; -#else - case XK_KP_0: return 0x52; - case XK_KP_1: return 0x53; - case XK_KP_2: return 0x54; - case XK_KP_3: return 0x55; - case XK_KP_4: return 0x56; - case XK_KP_5: return 0x57; - case XK_KP_6: return 0x58; - case XK_KP_7: return 0x59; - case XK_KP_8: return 0x5b; - case XK_KP_9: return 0x5c; - case XK_KP_Decimal: return 0x41; -#endif - case XK_KP_Add: return 0x45; - case XK_KP_Subtract: return 0x4e; - case XK_KP_Multiply: return 0x43; - case XK_KP_Divide: return 0x4b; - case XK_KP_Enter: return 0x4c; - case XK_KP_Equal: return 0x51; - } - return -1; -} - -static int event2keycode(XKeyEvent &ev, bool key_down) -{ - KeySym ks; - int i = 0; - - do { - ks = XLookupKeysym(&ev, i++); - int as = kc_decode(ks); - if (as >= 0) - return as; - if (as == -2) - return as; - } while (ks != NoSymbol); - - return -1; -} - -static void handle_events(void) -{ - // Handle events - for (;;) { - XEvent event; - - XDisplayLock(); - if (!XCheckMaskEvent(x_display, eventmask, &event)) { - // Handle clipboard events - if (XCheckTypedEvent(x_display, SelectionRequest, &event)) - ClipboardSelectionRequest(&event.xselectionrequest); - else if (XCheckTypedEvent(x_display, SelectionClear, &event)) - ClipboardSelectionClear(&event.xselectionclear); - - // Window "close" widget clicked - else if (XCheckTypedEvent(x_display, ClientMessage, &event)) { - if (event.xclient.format == 32 && event.xclient.data.l[0] == WM_DELETE_WINDOW) { - ADBKeyDown(0x7f); // Power key - ADBKeyUp(0x7f); - } - } - - XDisplayUnlock(); - break; - } - XDisplayUnlock(); - - switch (event.type) { - // Mouse button - case ButtonPress: { - unsigned int button = ((XButtonEvent *)&event)->button; - if (button < 4) - ADBMouseDown(button - 1); - else if (button < 6) { // Wheel mouse - if (mouse_wheel_mode == 0) { - int key = (button == 5) ? 0x79 : 0x74; // Page up/down - ADBKeyDown(key); - ADBKeyUp(key); - } else { - int key = (button == 5) ? 0x3d : 0x3e; // Cursor up/down - for(int i=0; ibutton; - if (button < 4) - ADBMouseUp(button - 1); - break; - } - - // Mouse entered window - case EnterNotify: - if (event.xcrossing.mode != NotifyGrab && event.xcrossing.mode != NotifyUngrab) - ADBMouseMoved(event.xmotion.x, event.xmotion.y); - break; - - // Mouse moved - case MotionNotify: - ADBMouseMoved(event.xmotion.x, event.xmotion.y); - break; - - // Keyboard - case KeyPress: { - int code = -1; - if (use_keycodes) { - if (event2keycode(event.xkey, true) != -2) // This is called to process the hotkeys - code = keycode_table[event.xkey.keycode & 0xff]; - } else - code = event2keycode(event.xkey, true); - if (code >= 0) { - if (!emul_suspended) { - if (code == 0x39) { // Caps Lock pressed - if (caps_on) { - ADBKeyUp(code); - caps_on = false; - } else { - ADBKeyDown(code); - caps_on = true; - } - } else - ADBKeyDown(code); - if (code == 0x36) - ctrl_down = true; - } else { - if (code == 0x31) - resume_emul(); // Space wakes us up - } - } - break; - } - case KeyRelease: { - int code = -1; - if (use_keycodes) { - if (event2keycode(event.xkey, false) != -2) // This is called to process the hotkeys - code = keycode_table[event.xkey.keycode & 0xff]; - } else - code = event2keycode(event.xkey, false); - if (code >= 0 && code != 0x39) { // Don't propagate Caps Lock releases - ADBKeyUp(code); - if (code == 0x36) - ctrl_down = false; - } - break; - } - - // Hidden parts exposed, force complete refresh - case Expose: -#ifdef ENABLE_VOSF - if (use_vosf) { // VOSF refresh - LOCK_VOSF; - PFLAG_SET_ALL; - memset(the_buffer_copy, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - UNLOCK_VOSF; - } - else -#endif - memset(the_buffer_copy, 0, VModes[cur_mode].viRowBytes * VModes[cur_mode].viYsize); - break; - } - } -} - - -/* - * Execute video VBL routine - */ - -void VideoVBL(void) -{ - if (emerg_quit) - QuitEmulator(); - - // Temporarily give up frame buffer lock (this is the point where - // we are suspended when the user presses Ctrl-Tab) - UNLOCK_FRAME_BUFFER; - LOCK_FRAME_BUFFER; - - // Execute video VBL - if (private_data != NULL && private_data->interruptsEnabled) - VSLDoInterruptService(private_data->vslServiceID); -} - - -/* - * Change video mode - */ - -int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr) -{ - /* return if no mode change */ - if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) && - (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr; - - /* first find video mode in table */ - for (int i=0; VModes[i].viType != DIS_INVALID; i++) { - if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) && - (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) { - csSave->saveMode = ReadMacInt16(ParamPtr + csMode); - csSave->saveData = ReadMacInt32(ParamPtr + csData); - csSave->savePage = ReadMacInt16(ParamPtr + csPage); - - // Disable interrupts and pause redraw thread - thread_stop_req = true; - sem_wait(&thread_stop_ack); - thread_stop_req = false; - DisableInterrupt(); - - /* close old display */ - close_display(); - - /* open new display */ - cur_mode = i; - bool ok = open_display(); - - /* opening the screen failed? Then bail out */ - if (!ok) { - ErrorAlert(GetString(STR_FULL_SCREEN_ERR)); - QuitEmulator(); - } - - WriteMacInt32(ParamPtr + csBaseAddr, screen_base); - csSave->saveBaseAddr=screen_base; - csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ - csSave->saveMode=VModes[cur_mode].viAppleMode; - - // Enable interrupts and resume redraw thread - EnableInterrupt(); - sem_post(&thread_resume_req); - return noErr; - } - } - return paramErr; -} - - -/* - * Set color palette - */ - -void video_set_palette(void) -{ - LOCK_PALETTE; - - // Convert colors to XColor array - int mode = get_current_mode(); - int num_in = palette_size(mode); - int num_out = 256; - bool stretch = false; - if (IsDirectMode(mode)) { - // If X is in 565 mode we have to stretch the gamma table from 32 to 64 entries - num_out = vis->map_entries; - stretch = true; - } - XColor *p = x_palette; - for (int i=0; ired = mac_pal[c].red * 0x0101; - p->green = mac_pal[c].green * 0x0101; - p->blue = mac_pal[c].blue * 0x0101; - p++; - } - -#ifdef ENABLE_VOSF - // Recalculate pixel color expansion map - if (!IsDirectMode(mode) && xdepth > 8) { - for (int i=0; i<256; i++) { - int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier) - ExpandMap[i] = map_rgb(mac_pal[c].red, mac_pal[c].green, mac_pal[c].blue); - } - - // We have to redraw everything because the interpretation of pixel values changed - LOCK_VOSF; - PFLAG_SET_ALL; - if (display_type == DIS_SCREEN) - PFLAG_SET_VERY_DIRTY; - UNLOCK_VOSF; - } -#endif - - // Tell redraw thread to change palette - palette_changed = true; - - UNLOCK_PALETTE; -} - - -/* - * Can we set the MacOS cursor image into the window? - */ - -bool video_can_change_cursor(void) -{ - return hw_mac_cursor_accl && (display_type != DIS_SCREEN); -} - - -/* - * Set cursor image for window - */ - -void video_set_cursor(void) -{ - cursor_changed = true; -} - - -/* - * Thread for window refresh, event handling and other periodic actions - */ - -static void update_display(void) -{ - // Incremental update code - int wide = 0, high = 0, x1, x2, y1, y2, i, j; - int bytes_per_row = VModes[cur_mode].viRowBytes; - int bytes_per_pixel = VModes[cur_mode].viRowBytes / VModes[cur_mode].viXsize; - uint8 *p, *p2; - - // Check for first line from top and first line from bottom that have changed - y1 = 0; - for (j=0; j=y1; j--) { - if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) { - y2 = j; - break; - } - } - high = y2 - y1 + 1; - - // Check for first column from left and first column from right that have changed - if (high) { - if (depth == 1) { - x1 = VModes[cur_mode].viXsize; - for (j=y1; j<=y2; j++) { - p = &the_buffer[j * bytes_per_row]; - p2 = &the_buffer_copy[j * bytes_per_row]; - for (i=0; i<(x1>>3); i++) { - if (*p != *p2) { - x1 = i << 3; - break; - } - p++; - p2++; - } - } - x2 = x1; - for (j=y1; j<=y2; j++) { - p = &the_buffer[j * bytes_per_row]; - p2 = &the_buffer_copy[j * bytes_per_row]; - p += bytes_per_row; - p2 += bytes_per_row; - for (i=(VModes[cur_mode].viXsize>>3); i>(x2>>3); i--) { - p--; - p2--; - if (*p != *p2) { - x2 = i << 3; - break; - } - } - } - wide = x2 - x1; - - // Update copy of the_buffer - if (high && wide) { - for (j=y1; j<=y2; j++) { - i = j * bytes_per_row + (x1 >> 3); - memcpy(&the_buffer_copy[i], &the_buffer[i], wide >> 3); - } - } - - } else { - x1 = VModes[cur_mode].viXsize; - for (j=y1; j<=y2; j++) { - p = &the_buffer[j * bytes_per_row]; - p2 = &the_buffer_copy[j * bytes_per_row]; - for (i=0; ix2; i--) { - p -= bytes_per_pixel; - p2 -= bytes_per_pixel; - if (memcmp(p, p2, bytes_per_pixel)) { - x2 = i; - break; - } - } - } - wide = x2 - x1; - - // Update copy of the_buffer - if (high && wide) { - for (j=y1; j<=y2; j++) { - i = j * bytes_per_row + x1 * bytes_per_pixel; - memcpy(&the_buffer_copy[i], &the_buffer[i], bytes_per_pixel * wide); - } - } - } - } - - // Refresh display - if (high && wide) { - XDisplayLock(); - if (have_shm) - XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high, 0); - else - XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high); - XDisplayUnlock(); - } -} - -const int VIDEO_REFRESH_HZ = 60; -const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ; - -static void handle_palette_changes(void) -{ - LOCK_PALETTE; - - if (palette_changed && !emul_suspended) { - palette_changed = false; - - int mode = get_current_mode(); - if (color_class == PseudoColor || color_class == DirectColor) { - int num = vis->map_entries; - bool set_clut = true; - if (!IsDirectMode(mode) && color_class == DirectColor) { - if (display_type == DIS_WINDOW) - set_clut = false; // Indexed mode on true color screen, don't set CLUT - } - - if (set_clut) { - XDisplayLock(); - XStoreColors(x_display, cmap[0], x_palette, num); - XStoreColors(x_display, cmap[1], x_palette, num); - XSync(x_display, false); - XDisplayUnlock(); - } - } - -#ifdef ENABLE_XF86_DGA - if (display_type == DIS_SCREEN && !is_fbdev_dga_mode) { - current_dga_cmap ^= 1; - if (!IsDirectMode(mode) && cmap[current_dga_cmap]) - XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); - } -#endif - } - - UNLOCK_PALETTE; -} - -static void *redraw_func(void *arg) -{ - int fd = ConnectionNumber(x_display); - - uint64 start = GetTicks_usec(); - int64 ticks = 0; - uint64 next = GetTicks_usec() + VIDEO_REFRESH_DELAY; - - while (!redraw_thread_cancel) { - - // Pause if requested (during video mode switches) - if (thread_stop_req) { - sem_post(&thread_stop_ack); - sem_wait(&thread_resume_req); - } - - int64 delay = next - GetTicks_usec(); - if (delay < -VIDEO_REFRESH_DELAY) { - - // We are lagging far behind, so we reset the delay mechanism - next = GetTicks_usec(); - - } else if (delay <= 0) { - - // Delay expired, refresh display - next += VIDEO_REFRESH_DELAY; - ticks++; - - // Handle X11 events - handle_events(); - - // Quit DGA mode if requested - if (quit_full_screen) { - quit_full_screen = false; - if (display_type == DIS_SCREEN) { - XDisplayLock(); -#if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA) -#ifdef ENABLE_XF86_DGA - if (!is_fbdev_dga_mode) - XF86DGADirectVideo(x_display, screen, 0); -#endif - XUngrabPointer(x_display, CurrentTime); - XUngrabKeyboard(x_display, CurrentTime); - XUnmapWindow(x_display, the_win); - wait_unmapped(the_win); - XDestroyWindow(x_display, the_win); -#endif - XSync(x_display, false); - XDisplayUnlock(); - quit_full_screen_ack = true; - return NULL; - } - } - - // Refresh display and set cursor image in window mode - static int tick_counter = 0; - if (display_type == DIS_WINDOW) { - tick_counter++; - if (tick_counter >= frame_skip) { - tick_counter = 0; - - // Update display -#ifdef ENABLE_VOSF - if (use_vosf) { - XDisplayLock(); - if (mainBuffer.dirty) { - LOCK_VOSF; - update_display_window_vosf(); - UNLOCK_VOSF; - XSync(x_display, false); // Let the server catch up - } - XDisplayUnlock(); - } - else -#endif - update_display(); - - // Set new cursor image if it was changed - if (hw_mac_cursor_accl && cursor_changed) { - cursor_changed = false; - uint8 *x_data = (uint8 *)cursor_image->data; - uint8 *x_mask = (uint8 *)cursor_mask_image->data; - for (int i = 0; i < 32; i++) { - x_mask[i] = MacCursor[4 + i] | MacCursor[36 + i]; - x_data[i] = MacCursor[4 + i]; - } - XDisplayLock(); - XFreeCursor(x_display, mac_cursor); - XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16); - XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16); - mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, MacCursor[2], MacCursor[3]); - XDefineCursor(x_display, the_win, mac_cursor); - XDisplayUnlock(); - } - } - } -#ifdef ENABLE_VOSF - else if (use_vosf) { - // Update display (VOSF variant) - if (++tick_counter >= frame_skip) { - tick_counter = 0; - if (mainBuffer.dirty) { - LOCK_VOSF; - update_display_dga_vosf(); - UNLOCK_VOSF; - } - } - } -#endif - - // Set new palette if it was changed - handle_palette_changes(); - - } else { - - // No display refresh pending, check for X events - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = delay; - if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0) - handle_events(); - } - } - return NULL; -} - - -/* - * Record dirty area from NQD - */ - -void video_set_dirty_area(int x, int y, int w, int h) -{ - VideoInfo const & mode = VModes[cur_mode]; - const int screen_width = VIDEO_MODE_X; - const int screen_height = VIDEO_MODE_Y; - const int bytes_per_row = VIDEO_MODE_ROW_BYTES; - -#ifdef ENABLE_VOSF - if (use_vosf) { - vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row); - return; - } -#endif - - // XXX handle dirty bounding boxes for non-VOSF modes -} diff --git a/SheepShaver/src/Unix/xpram_unix.cpp b/SheepShaver/src/Unix/xpram_unix.cpp deleted file mode 120000 index 12e37c98..00000000 --- a/SheepShaver/src/Unix/xpram_unix.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Unix/xpram_unix.cpp \ No newline at end of file diff --git a/SheepShaver/src/VideoDriverStub.i b/SheepShaver/src/VideoDriverStub.i deleted file mode 100644 index ad2ed630..00000000 --- a/SheepShaver/src/VideoDriverStub.i +++ /dev/null @@ -1,24 +0,0 @@ - 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66, 0x70, 0x77, 0x70, 0x63, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0x10, - 0x00, 0x04, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, - 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x40, 0x02, 0x01, 0x04, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x80, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x68, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x54, 0x68, 0x65, 0x44, 0x72, 0x69, 0x76, 0x65, - 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x6f, 0x44, 0x72, - 0x69, 0x76, 0x65, 0x72, 0x49, 0x4f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, - 0x00, 0x14, 0xbd, 0xe0, 0x00, 0x0a, 0xd1, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x01, 0x02, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x90, 0x61, 0x00, 0x18, 0x90, 0x81, 0x00, 0x1c, 0x90, 0xa1, 0x00, 0x20, 0x90, 0xc1, 0x00, 0x24, - 0x90, 0xe1, 0x00, 0x28, 0x80, 0x40, 0x28, 0x08, 0x80, 0x00, 0x28, 0xd8, 0x7c, 0x09, 0x03, 0xa6, - 0x4e, 0x80, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x24, 0x6d, 0x74, 0x65, 0x6a, 0x04, 0x26, 0x05, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x1a, 0x21, - 0x01, 0x01, 0x21, 0x80, 0x04, 0x3b, 0x06, 0x19, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x56, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x5f, 0x53, 0x68, 0x65, 0x65, - 0x70, 0x00, 0x29, 0x2a, 0x01, 0x6e, 0x64, 0x72, 0x76, 0x76, 0x69, 0x64, 0x6f, 0x01, 0x03, diff --git a/SheepShaver/src/Windows/Makefile.in b/SheepShaver/src/Windows/Makefile.in deleted file mode 100755 index edd28f59..00000000 --- a/SheepShaver/src/Windows/Makefile.in +++ /dev/null @@ -1,221 +0,0 @@ -# Windows Makefile for SheepShaver - -## System specific configuration -@SET_MAKE@ -SHELL = /bin/sh - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -datadir = @datadir@ -mandir = @mandir@ -man1dir = $(mandir)/man1 - -DESTDIR = - -SDL_CFLAGS = @SDL_CFLAGS@ -SDL_LIBS = @SDL_LIBS@ -WANT_GTK = @WANT_GTK@ -GTK_CFLAGS = @GTK_CFLAGS@ -GTK_LIBS = @GTK_LIBS@ - -SLIRP_CFLAGS = @SLIRP_CFLAGS@ -SLIRP_SRCS = \ - ../slirp/bootp.c ../slirp/ip_output.c ../slirp/tcp_input.c \ - ../slirp/cksum.c ../slirp/mbuf.c ../slirp/tcp_output.c \ - ../slirp/debug.c ../slirp/misc.c ../slirp/tcp_subr.c \ - ../slirp/if.c ../slirp/sbuf.c ../slirp/tcp_timer.c \ - ../slirp/ip_icmp.c ../slirp/slirp.c ../slirp/tftp.c \ - ../slirp/ip_input.c ../slirp/socket.c ../slirp/udp.c -SLIRP_OBJS = $(SLIRP_SRCS:../slirp/%.c=$(OBJ_DIR)/slirp-%.o) - -LN_S = @LN_S@ -WINDRES = @WINDRES@ -CC = @CC@ -CXX = @CXX@ -CFLAGS = @CFLAGS@ $(SDL_CFLAGS) -CXXFLAGS = @CXXFLAGS@ $(SDL_CFLAGS) -CPPFLAGS = @CPPFLAGS@ -I../include -I. -I../slirp -DEFS = @DEFS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -lwsock32 -liphlpapi -CPUSRCS = @CPUSRCS@ -PERL = @PERL@ - -USE_DYNGEN = @USE_DYNGEN@ -DYNGENSRCS = @DYNGENSRCS@ -DYNGEN_CC = $(CXX) -DYNGEN_OP_FLAGS = @DYNGEN_OP_FLAGS@ - -HOST_CC = gcc -HOST_CXX = g++ -HOST_CFLAGS = -O2 -HOST_CXXFLAGS = -O2 -HOST_LDFLAGS = - -## Files -UNIXSRCS = vm_alloc.cpp vm_alloc.h sigsegv.cpp sigsegv.h video_vosf.h video_blit.cpp video_blit.h - -ROUTERSRCS = router/arp.cpp router/dump.cpp router/dynsockets.cpp router/ftp.cpp \ - router/icmp.cpp router/mib/interfaces.cpp router/iphelp.cpp router/ipsocket.cpp \ - router/mib/mibaccess.cpp router/router.cpp router/tcp.cpp router/udp.cpp b2ether/packet32.cpp - -SRCS = ../main.cpp main_windows.cpp ../prefs.cpp ../prefs_items.cpp prefs_windows.cpp \ - sys_windows.cpp cdenable/cache.cpp cdenable/eject_nt.cpp cdenable/ntcd.cpp \ - ../rom_patches.cpp ../rsrc_patches.cpp ../emul_op.cpp ../name_registry.cpp \ - ../macos_util.cpp ../timer.cpp timer_windows.cpp ../xpram.cpp xpram_windows.cpp \ - ../adb.cpp ../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../dummy/scsi_dummy.cpp \ - ../gfxaccel.cpp ../video.cpp ../SDL/video_sdl.cpp video_blit.cpp \ - ../audio.cpp ../SDL/audio_sdl.cpp ../ether.cpp ether_windows.cpp \ - ../thunks.cpp ../serial.cpp serial_windows.cpp ../extfs.cpp extfs_windows.cpp \ - about_window_windows.cpp ../user_strings.cpp user_strings_windows.cpp \ - ../dummy/prefs_editor_dummy.cpp clip_windows.cpp util_windows.cpp kernel_windows.cpp \ - vm_alloc.cpp sigsegv.cpp posix_emu.cpp SheepShaver.rc \ - $(CPUSRCS) $(ROUTERSRCS) $(SLIRP_OBJS) - -UI_SRCS = ../prefs.cpp prefs_windows.cpp prefs_editor_gtk.cpp xpram_windows.cpp \ - ../prefs_items.cpp ../user_strings.cpp user_strings_windows.cpp util_windows.cpp \ - b2ether/packet32.cpp SheepShaverGUI.rc - -UI_APP = SheepShaverGUI.exe - -APP = SheepShaver.exe - -PROGS = $(APP) - -ifeq ($(WANT_GTK),yes) -PROGS += $(UI_APP) -endif - -## Rules -.PHONY: clean distclean -.SUFFIXES: -.SUFFIXES: .c .cpp .S .o .h - -all: $(PROGS) - -$(UNIXSRCS): %: ../Unix/% - $(LN_S) $< $@ - -OBJ_DIR = obj -$(OBJ_DIR):: - @[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1 - -define SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \ - $(basename $(notdir $(file)))))) -endef -OBJS = $(SRCS_LIST_TO_OBJS) - -define UI_SRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(UI_SRCS), \ - $(basename $(notdir $(file)))))) -endef -UI_OBJS = $(UI_SRCS_LIST_TO_OBJS) - -define DYNGENSRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .ho, $(foreach file, $(DYNGENSRCS), \ - $(basename $(notdir $(file)))))) -endef -DYNGENOBJS = $(DYNGENSRCS_LIST_TO_OBJS) - -SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file)))) -VPATH := -VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS)))) - -$(APP): $(UNIXSRCS) $(OBJ_DIR) $(OBJS) - $(CXX) -o $(APP) $(LDFLAGS) $(OBJS) $(LIBS) $(SDL_LIBS) - -$(UI_APP): $(UNIXSRCS) $(OBJ_DIR) $(UI_OBJS) - $(CXX) -o $@ $(LDFLAGS) $(UI_OBJS) $(LIBS) $(GTK_LIBS) -mwindows -mno-cygwin - -mostlyclean: - rm -f $(APP) $(UI_APP) $(OBJ_DIR)/* core* *.core *~ *.bak - -clean: mostlyclean - rm -f $(UNIXSRCS) - rm -f dyngen basic-dyngen-ops.hpp ppc-dyngen-ops.hpp ppc-execute-impl.cpp - -distclean: clean - rm -rf $(OBJ_DIR) - rm -rf autom4te.cache - rm -f Makefile - rm -f config.cache config.log config.status config.h - -depend dep: - makedepend $(CPPFLAGS) -Y. $(SRCS) 2>/dev/null - -$(OBJ_DIR)/%.ho : %.c - $(HOST_CC) $(CPPFLAGS) $(DEFS) $(HOST_CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.ho : %.cpp - $(HOST_CXX) $(CPPFLAGS) $(DEFS) $(HOST_CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/slirp-%.o : ../slirp/%.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(SLIRP_CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.c - $(CC) $(CPPFLAGS) $(DEFS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.cpp - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.mm - $(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o : %.S - $(CPP) $(CPPFLAGS) -D__ASSEMBLY__ $< -o $*.out.s - $(AS) $(ASFLAGS) -o $@ $*.out.s - rm $*.out.s -$(OBJ_DIR)/prefs_editor_gtk.o: prefs_editor_gtk.cpp - $(CXX) -O2 -mno-cygwin -mms-bitfields $(CPPFLAGS) $(DEFS) $(GTK_CFLAGS) -c $< -o $@ - -# Windows resources -$(OBJ_DIR)/%.o: %.rc - $(WINDRES) --include-dir ../Windows -i $< -o $@ - -# Kheperix CPU emulator -kpxsrcdir = ../kpx_cpu/src -GENEXECPL = $(kpxsrcdir)/cpu/ppc/genexec.pl -DYNGEN = dyngen.exe - -ifeq ($(USE_DYNGEN),yes) -DYNGENDEPS = basic-dyngen-ops.hpp ppc-dyngen-ops.hpp - -$(DYNGEN): $(DYNGENOBJS) - $(HOST_CXX) -o $@ $(LDFLAGS) $(DYNGENOBJS) - -$(OBJ_DIR)/basic-dyngen.o: basic-dyngen-ops.hpp -$(OBJ_DIR)/basic-dyngen-ops.o: $(kpxsrcdir)/cpu/jit/basic-dyngen-ops.cpp - $(DYNGEN_CC) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) $(DYNGEN_OP_FLAGS) -c $< -o $@ -basic-dyngen-ops.hpp: $(OBJ_DIR)/basic-dyngen-ops.o $(DYNGEN) - ./$(DYNGEN) -o $@ $< - -$(OBJ_DIR)/ppc-dyngen.o: ppc-dyngen-ops.hpp -$(OBJ_DIR)/ppc-dyngen-ops.o: $(kpxsrcdir)/cpu/ppc/ppc-dyngen-ops.cpp basic-dyngen-ops.hpp - $(DYNGEN_CC) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) $(DYNGEN_OP_FLAGS) -c $< -o $@ -ppc-dyngen-ops.hpp: $(OBJ_DIR)/ppc-dyngen-ops.o $(DYNGEN) - ./$(DYNGEN) -o $@ $< - -$(OBJ_DIR)/sheepshaver_glue.o $(OBJ_DIR)/ppc-cpu.o $(OBJ_DIR)/ppc-decode.o $(OBJ_DIR)/ppc-translate.o $(OBJ_DIR)/ppc-jit.o: basic-dyngen-ops.hpp ppc-dyngen-ops.hpp -endif - -$(OBJ_DIR)/ppc-execute.o: ppc-execute-impl.cpp -ppc-execute-impl.cpp: $(kpxsrcdir)/cpu/ppc/ppc-decode.cpp $(GENEXECPL) $(DYNGENDEPS) - $(CPP) $(CPPFLAGS) -DGENEXEC $< | $(PERL) $(GENEXECPL) > $@ - -# PowerPC CPU tester -TESTSRCS_ = mathlib/ieeefp.cpp mathlib/mathlib.cpp cpu/ppc/ppc-cpu.cpp cpu/ppc/ppc-decode.cpp cpu/ppc/ppc-execute.cpp cpu/ppc/ppc-translate.cpp test/test-powerpc.cpp $(MONSRCS) vm_alloc.cpp utils/utils-cpuinfo.cpp -ifeq ($(USE_DYNGEN),yes) -TESTSRCS_ += cpu/jit/jit-cache.cpp cpu/jit/basic-dyngen.cpp cpu/ppc/ppc-dyngen.cpp cpu/ppc/ppc-jit.cpp -endif -TESTSRCS = $(TESTSRCS_:%.cpp=$(kpxsrcdir)/%.cpp) - -define TESTSRCS_LIST_TO_OBJS - $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(TESTSRCS), \ - $(basename $(notdir $(file)))))) -endef -TESTOBJS = $(TESTSRCS_LIST_TO_OBJS) - -$(OBJ_DIR)/test-powerpc.o: $(kpxsrcdir)/test/test-powerpc.cpp - $(HOST_CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -DEMU_KHEPERIX -c $< -o $@ - -test-powerpc.exe: $(TESTOBJS) - $(HOST_CXX) -o $@ $(LDFLAGS) $(TESTOBJS) -mconsole - -#------------------------------------------------------------------------- -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SheepShaver/src/Windows/SheepShaver.ico b/SheepShaver/src/Windows/SheepShaver.ico deleted file mode 100755 index 40c862d2ca7b612cd1215d47bbd65f17e5a4faf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2238 zcmc(fF-+@L7==%UCqC==5a-543^Qe|YkEej)CQM)iQ zBBcW(%7oPRiIEXUvfS^t<0Q08x7zw_bME>7bMLi@)ZyIO5!bG6x>77@7m#!SrvK~c ztdwrItIf?#B}qb`9qsP!YHx2(`}_MkI5^PZ;h~O>j&yu{tdo-yot~cR?CebE=jXb( zxX@%W(dFf(LI}FPzShmnjc#vmb$55C`}=!6JUr;}@lj7tPkMfS*2~L_USD7J_V%WV zY5WDh!*B32`~cs>5qt|dsCNFzeG0$APjCVMa9YFvU~_?vRRvQ`A%F)5f~pGW0X?7x zbSntx9^IpRbdT=QJ-S18=nmbXJ9I}$r6~mP-~f}AXlkWX@*#i+2MFloLjVsBXoOBa z1n}U%8dX#BA%F)5g36N*0X#Thg8a?R@&ox0z=H#tppy^wPCYo_4|MV&fCmTGtP12q z01pmi{P=}wkOv+dusO_w_hk8=dH@kcz2KJRv*!D*bY$8K2{pcJ4Id$28vp7C@l>Wm3cXUyrac9!`tmM<n42);`&KFhPU32^P3ynX`9HpnL%%@z5OD`h0>TEX&h3&?$ulr zXDU*qg+`5GZOk5(F;bXiv@n=$Wm2)MAFVrDOI<(LJY^oVFb@-0^e}CnX`U;e59dRh z>qxrdhJ)-fD>IgsmT5UGF%(#$tG=#Md%r4sy?@|; z&ZJC>WURX0md0l>z_K#rWje-S_4U#%zx>7wY5cM2fk7Il^$yF17Y0SlgZf!IwsS!J z2Q3YX1_RzenavtQ#Q2BLvHBSnmAoQ8kB`}CHkx4>r%_f_u`nz;#L-5^2Rh3!U>VoD zOG!+NGULJKVZ)7KxcUHWPdBRSlW5!+a-^?TFR*=zg(1&pjK;Hg)@}9G-CA+P{7Yk5 WMXVglC(YKTuvFI`?C0lyKK=%pC1gMV diff --git a/SheepShaver/src/Windows/SheepShaver.rc b/SheepShaver/src/Windows/SheepShaver.rc deleted file mode 100755 index b7e5281d..00000000 --- a/SheepShaver/src/Windows/SheepShaver.rc +++ /dev/null @@ -1 +0,0 @@ -SheepShaver ICON PRELOAD "SheepShaver.ico" diff --git a/SheepShaver/src/Windows/SheepShaverGUI.ico b/SheepShaver/src/Windows/SheepShaverGUI.ico deleted file mode 100755 index 67d4c55fab03db3146193a2c8fcfc69907eaabc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmchWJ#vIF422(?%(zQ90##;@kt4aI_0fEslqu7ZPqGc(#SJMUkfo~K;7@qcE31@<9aF-IC#51-QI&H>nq%`<+h!WfVQh$Ucf(}0+9O}TOLWlj#9k%d?_(vS@ zhtB_uPxal<*Ed7Oev8uSQNQgbmCE;P?Qr=cz4!c0+y9GgUz_t8Uf?$88GTHN8OOs+ zyI@7VHs?NE)M(_bp)q{oDCCYUpxD>wQo&^eIyQw6C(kdq=CwL?pBy+RocOn|vgQ2( DRT%bz diff --git a/SheepShaver/src/Windows/SheepShaverGUI.rc b/SheepShaver/src/Windows/SheepShaverGUI.rc deleted file mode 100644 index db7ed548..00000000 --- a/SheepShaver/src/Windows/SheepShaverGUI.rc +++ /dev/null @@ -1,2 +0,0 @@ -SheepShaverGUI ICON PRELOAD "SheepShaverGUI.ico" - diff --git a/SheepShaver/src/Windows/about_window_windows.cpp b/SheepShaver/src/Windows/about_window_windows.cpp deleted file mode 100755 index 4527aad5..00000000 --- a/SheepShaver/src/Windows/about_window_windows.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * about_window_windows.cpp - "About" window, Windows implementation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "about_window.h" - - -/* - * Open "About" window - */ - -void OpenAboutWindow(void) -{ -} diff --git a/SheepShaver/src/Windows/b2ether b/SheepShaver/src/Windows/b2ether deleted file mode 120000 index cf8fd89b..00000000 --- a/SheepShaver/src/Windows/b2ether +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/b2ether \ No newline at end of file diff --git a/SheepShaver/src/Windows/cd_defs.h b/SheepShaver/src/Windows/cd_defs.h deleted file mode 120000 index fdaec5bd..00000000 --- a/SheepShaver/src/Windows/cd_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/cd_defs.h \ No newline at end of file diff --git a/SheepShaver/src/Windows/cdenable b/SheepShaver/src/Windows/cdenable deleted file mode 120000 index 3b36f98c..00000000 --- a/SheepShaver/src/Windows/cdenable +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/cdenable \ No newline at end of file diff --git a/SheepShaver/src/Windows/clip_windows.cpp b/SheepShaver/src/Windows/clip_windows.cpp deleted file mode 120000 index 2669ccc9..00000000 --- a/SheepShaver/src/Windows/clip_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/clip_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/configure.ac b/SheepShaver/src/Windows/configure.ac deleted file mode 100755 index dcb4bfe0..00000000 --- a/SheepShaver/src/Windows/configure.ac +++ /dev/null @@ -1,266 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -dnl Written in 2002 by Christian Bauer - -AC_INIT([SheepShaver], 2.3, [Christian.Bauer@uni-mainz.de], SheepShaver) -AC_CONFIG_SRCDIR(main_windows.cpp) -AC_CONFIG_AUX_DIR(../Unix) -AC_PREREQ(2.52) -AC_CONFIG_HEADER(config.h) - -dnl Canonical system information. -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -dnl Options. -AC_ARG_ENABLE(jit, [ --enable-jit enable JIT compiler [default=yes]], [WANT_JIT=$enableval], [WANT_JIT=yes]) -AC_ARG_WITH(gtk, [ --with-gtk use GTK user interface [default=yes]], [WANT_GTK=$withval], [WANT_GTK=yes]) - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_MAKE_SET -AC_PROG_EGREP -AC_PROG_LN_S -AC_PATH_PROG(PERL, [perl]) -AC_CHECK_TOOL(WINDRES, windres) - -dnl We use GTK+ if possible. -if [[ "x$WANT_GTK" = "xyes" ]]; then - AM_PATH_GTK_2_0(1.3.15, [], [ - AC_MSG_WARN([Could not find GTK+ 2.0, disabling user interface.]) - WANT_GTK=no - ]) -fi -AC_SUBST(WANT_GTK) - -dnl We use 64-bit file size support if possible. -AC_SYS_LARGEFILE - -dnl Checks for header files. -AC_HEADER_STDC - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_BIGENDIAN -AC_C_CONST -AC_C_INLINE -AC_CHECK_SIZEOF(short, 2) -AC_CHECK_SIZEOF(int, 4) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_SIZEOF(long long, 8) -AC_CHECK_SIZEOF(float, 4) -AC_CHECK_SIZEOF(double, 8) -AC_CHECK_SIZEOF(void *, 4) -AC_TYPE_OFF_T -AC_CHECK_TYPES(loff_t) -AC_TYPE_SIZE_T - -dnl Checks for library functions. -AC_CHECK_FUNCS(strdup strerror) -AC_CHECK_FUNCS(exp2f log2f exp2 log2) -AC_CHECK_FUNCS(floorf roundf ceilf truncf) -AC_CHECK_FUNCS(floor round ceil trunc) - -dnl Define a macro that translates a yesno-variable into a C macro definition -dnl to be put into the config.h file -dnl $1 -- the macro to define -dnl $2 -- the value to translate -dnl $3 -- template name -AC_DEFUN([AC_TRANSLATE_DEFINE], [ - if [[ "x$2" = "xyes" -o "x$2" = "xguessing yes" ]]; then - AC_DEFINE($1, 1, $3) - fi -]) - -dnl Check that VirtualAlloc(), VirtualProtect() work -AC_CACHE_CHECK([whether VirtualProtect works], - ac_cv_VirtualProtect_works, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - ac_cv_VirtualProtect_works=yes - dnl First the tests that should segfault - for test_def in NONE_READ NONE_WRITE READ_WRITE; do - AC_TRY_RUN([ - #define HAVE_WIN32_VM 1 - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_$test_def - #include "../Unix/vm_alloc.cpp" - ], ac_cv_VirtualProtect_works=no, rm -f core, - dnl When cross-compiling, assume it works - ac_cv_VirtualProtect_works="yes" - ) - done - AC_TRY_RUN([ - #define HAVE_WIN32_VM 1 - #define CONFIGURE_TEST_VM_MAP - #define TEST_VM_PROT_RDWR_WRITE - #include "../Unix/vm_alloc.cpp" - ], , ac_cv_VirtualProtect_works=no, - dnl When cross-compiling, assume it works - ac_cv_VirtualProtect_works="yes" - ) - AC_LANG_RESTORE - ] -) -if [[ "x$ac_cv_VirtualProtect_works" = "xyes" ]]; then - AC_DEFINE(HAVE_WIN32_VM, 1, [Define if your system has a working Win32-based memory allocator.]) -else - AC_MSG_ERROR([Sorry, Windows VM functions don't work as expected on your system.]) -fi - -dnl Check if Windows exceptions are supported. -AC_CACHE_CHECK([whether your system supports Windows exceptions], - ac_cv_have_win32_exceptions, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_WIN32_EXCEPTIONS 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../Unix/vm_alloc.cpp" - #include "../Unix/sigsegv.cpp" - ], - ac_cv_have_win32_exceptions=yes, - ac_cv_have_win32_exceptions=no, - dnl When cross-compiling, assume it works - ac_cv_have_win32_exceptions="yes" - ) - AC_LANG_RESTORE - ] -) -if [[ "x$ac_cv_have_win32_exceptions" = "xyes" ]]; then - AC_DEFINE(HAVE_WIN32_EXCEPTIONS, 1, [Define if your system supports Windows exceptions.]) -else - AC_MSG_ERROR([Sorry, Windows exceptions don't work as expected on your system.]) -fi - -dnl Check if we can ignore the fault (instruction skipping in SIGSEGV handler) -AC_CACHE_CHECK([whether we can skip instruction in SIGSEGV handler], - ac_cv_have_skip_instruction, [ - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ - #define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 - #define CONFIGURE_TEST_SIGSEGV_RECOVERY - #include "../Unix/vm_alloc.cpp" - #include "../Unix/sigsegv.cpp" - ], ac_cv_have_skip_instruction=yes, ac_cv_have_skip_instruction=no, - dnl When cross-compiling, assume it works - ac_cv_have_skip_instruction="yes" - ) - AC_LANG_RESTORE - ] -) -AC_TRANSLATE_DEFINE(HAVE_SIGSEGV_SKIP_INSTRUCTION, "$ac_cv_have_skip_instruction", - [Define if we can ignore the fault (instruction skipping in SIGSEGV handler).]) - -dnl We really want VOSF (Video on SEGV Signals) screen updates acceleration -AC_DEFINE(ENABLE_VOSF, 1, [Define if using video enabled on SEGV signals.]) - -dnl Check for GCC 2.7 or higher. -HAVE_GCC27=no -AC_MSG_CHECKING(for GCC 2.7 or higher) -AC_EGREP_CPP(xyes, -[#if __GNUC__ - 1 > 1 || __GNUC_MINOR__ - 1 > 5 - xyes -#endif -], [AC_MSG_RESULT(yes); HAVE_GCC27=yes], AC_MSG_RESULT(no)) - -dnl Check for GCC 3.0 or higher. -HAVE_GCC30=no -AC_MSG_CHECKING(for GCC 3.0 or higher) -AC_EGREP_CPP(xyes, -[#if __GNUC__ >= 3 - xyes -#endif -], [AC_MSG_RESULT(yes); HAVE_GCC30=yes], AC_MSG_RESULT(no)) - -dnl Add -fno-strict-aliasing for slirp sources -if [[ "x$HAVE_GCC30" = "xyes" ]]; then - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-strict-aliasing" - AC_CACHE_CHECK([whether the compiler supports -fno-strict-aliasing], - ac_cv_gcc_no_strict_aliasing, [ - AC_TRY_COMPILE([],[], - [ac_cv_gcc_no_strict_aliasing=yes; AC_SUBST(SLIRP_CFLAGS, "-fno-strict-aliasing")], - [ac_cv_gcc_no_strict_aliasing=no]) - ]) - CFLAGS="$SAVED_CFLAGS" -fi - -dnl CPU emulator sources -CPUSRCS="\ - ../kpx_cpu/src/mathlib/ieeefp.cpp \ - ../kpx_cpu/src/mathlib/mathlib.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-cpu.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-decode.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-execute.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-translate.cpp \ - ../kpx_cpu/src/utils/utils-cpuinfo.cpp" -CPPFLAGS="$CPPFLAGS -I../kpx_cpu/include -I../kpx_cpu/src" - -dnl Enable JIT compiler, if possible -USE_DYNGEN="no" -if [[ "x$WANT_JIT" = "xyes" ]]; then - case $host_cpu in - i?86) - DYNGEN_OP_FLAGS="-fomit-frame-pointer -mpreferred-stack-boundary=2" - if [[ "x$HAVE_GCC30" = "xyes" ]]; then - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -falign-functions=0" - else - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -malign-functions=0" - fi - ;; - esac - USE_DYNGEN="yes" - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -finline-limit=10000 -g0" - if [[ "x$HAVE_GCC30" = "xyes" ]]; then - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -fno-reorder-blocks -fno-optimize-sibling-calls" - fi - AC_DEFINE(ENABLE_DYNGEN, 1, [Define to enable dyngen engine]) - DYNGENSRCS="\ - ../kpx_cpu/src/cpu/jit/dyngen.c \ - ../kpx_cpu/src/cpu/jit/cxxdemangle.cpp" - CPUSRCS="\ - ../kpx_cpu/src/cpu/jit/jit-cache.cpp \ - ../kpx_cpu/src/cpu/jit/basic-dyngen.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp \ - ../kpx_cpu/src/cpu/ppc/ppc-jit.cpp $CPUSRCS" - CPPFLAGS="$CPPFLAGS -DUSE_JIT" -fi -CPUSRCS="$CPUSRCS ../kpx_cpu/sheepshaver_glue.cpp ../kpx_cpu/ppc-dis.c" - -dnl Use the dummy prefs file. -CPUSRCS="$CPUSRCS ../dummy/prefs_dummy.cpp" - -dnl We really want SDL for now -AC_CHECK_TOOL(sdl_config, sdl-config, [AC_MSG_ERROR([Sorry, you currently need SDL for this port])]) -SDL_CFLAGS=`$sdl_config --cflags` -AC_SUBST(SDL_CFLAGS) -SDL_LIBS=`$sdl_config --libs` -AC_SUBST(SDL_LIBS) -AC_DEFINE(USE_SDL, 1, [Define to enble SDL support]) -AC_DEFINE(USE_SDL_VIDEO, 1, [Define to enable SDL video graphics support]) -AC_DEFINE(USE_SDL_AUDIO, 1, [Define to enable SDL audio support]) - -dnl Remove the "-g" option if set for GCC. -if [[ "x$HAVE_GCC27" = "xyes" ]]; then - CFLAGS=`echo $CFLAGS | sed -e 's/-g\b//g'` - CXXFLAGS=`echo $CXXFLAGS | sed -e 's/-g\b//g'` -fi - -dnl Generate Makefile. -AC_SUBST(PERL) -AC_SUBST(USE_DYNGEN) -AC_SUBST(DYNGENSRCS) -AC_SUBST(DYNGEN_OP_FLAGS) -AC_SUBST(CPUSRCS) -AC_OUTPUT([Makefile]) - -dnl Print summary. -echo -echo SheepShaver configuration summary: -echo -echo Enable JIT compiler .............. : $WANT_JIT -echo GTK user interface ............... : $WANT_GTK -echo -echo "Configuration done. Now type \"make\"." diff --git a/SheepShaver/src/Windows/ether_windows.cpp b/SheepShaver/src/Windows/ether_windows.cpp deleted file mode 120000 index 44595188..00000000 --- a/SheepShaver/src/Windows/ether_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/ether_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/ether_windows.h b/SheepShaver/src/Windows/ether_windows.h deleted file mode 120000 index 6659d3c9..00000000 --- a/SheepShaver/src/Windows/ether_windows.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/ether_windows.h \ No newline at end of file diff --git a/SheepShaver/src/Windows/extfs_windows.cpp b/SheepShaver/src/Windows/extfs_windows.cpp deleted file mode 120000 index 26d851b3..00000000 --- a/SheepShaver/src/Windows/extfs_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/extfs_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/kernel_windows.cpp b/SheepShaver/src/Windows/kernel_windows.cpp deleted file mode 120000 index d9c12cdc..00000000 --- a/SheepShaver/src/Windows/kernel_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/kernel_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/kernel_windows.h b/SheepShaver/src/Windows/kernel_windows.h deleted file mode 120000 index 10e68ceb..00000000 --- a/SheepShaver/src/Windows/kernel_windows.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/kernel_windows.h \ No newline at end of file diff --git a/SheepShaver/src/Windows/main_windows.cpp b/SheepShaver/src/Windows/main_windows.cpp deleted file mode 100755 index 2d63d76b..00000000 --- a/SheepShaver/src/Windows/main_windows.cpp +++ /dev/null @@ -1,828 +0,0 @@ -/* - * main_windows.cpp - Emulation core, Windows implementation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include - -#include "sysdeps.h" -#include "main.h" -#include "version.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "xlowmem.h" -#include "xpram.h" -#include "timer.h" -#include "adb.h" -#include "video.h" -#include "sys.h" -#include "macos_util.h" -#include "rom_patches.h" -#include "user_strings.h" -#include "vm_alloc.h" -#include "sigsegv.h" -#include "util_windows.h" -#include "kernel_windows.h" - -#define DEBUG 0 -#include "debug.h" - -#ifdef ENABLE_MON -#include "mon.h" -#endif - - -// Constants -const char ROM_FILE_NAME[] = "ROM"; -const char ROM_FILE_NAME2[] = "Mac OS ROM"; - -const uintptr ROM_BASE = 0x40800000; // Base address of ROM - -const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack - - -// Global variables (exported) -uint32 RAMBase; // Base address of Mac RAM -uint32 RAMSize; // Size of Mac RAM -uint32 ROMBase; // Base address of Mac ROM -uint32 KernelDataAddr; // Address of Kernel Data -uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM -uint32 DRCacheAddr; // Address of DR Cache -uint32 PVR; // Theoretical PVR -int64 CPUClockSpeed; // Processor clock speed (Hz) -int64 BusClockSpeed; // Bus clock speed (Hz) -int64 TimebaseSpeed; // Timebase clock speed (Hz) -uint8 *RAMBaseHost; // Base address of Mac RAM (host address space) -uint8 *ROMBaseHost; // Base address of Mac ROM (host address space) -DWORD win_os; // Windows OS id -DWORD win_os_major; // Windows OS version major - - -// Global variables -static int kernel_area = -1; // SHM ID of Kernel Data area -static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped -static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped -static bool dr_cache_area_mapped = false; // Flag: Mac DR Cache mmap()ped -static bool dr_emulator_area_mapped = false;// Flag: Mac DR Emulator mmap()ped -static KernelData *kernel_data; // Pointer to Kernel Data -static EmulatorData *emulator_data; - -static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes -static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed -static volatile bool nvram_thread_cancel; // Flag: Cancel NVRAM thread -static HANDLE nvram_thread = NULL; // NVRAM watchdog -static bool tick_thread_active = false; // Flag: MacOS thread installed -static volatile bool tick_thread_cancel; // Flag: Cancel 60Hz thread -static HANDLE tick_thread = NULL; // 60Hz thread -static HANDLE emul_thread = NULL; // MacOS thread -static uintptr sig_stack = 0; // Stack for PowerPC interrupt routine - -uint32 SheepMem::page_size; // Size of a native page -uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros -uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data -uintptr SheepMem::proc; // Bottom address of SheepShave procedures -uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) - - -// Prototypes -static bool kernel_data_init(void); -static void kernel_data_exit(void); -static void Quit(void); -static DWORD WINAPI nvram_func(void *arg); -static DWORD WINAPI tick_func(void *arg); - -static void jump_to_rom(uint32 entry); -extern void emul_ppc(uint32 start); -extern void init_emul_ppc(void); -extern void exit_emul_ppc(void); -sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip); - - -/* - * Return signal stack base - */ - -uintptr SignalStackBase(void) -{ - return sig_stack + SIG_STACK_SIZE; -} - - -/* - * Memory management helpers - */ - -static inline int vm_mac_acquire(uint32 addr, uint32 size) -{ - return vm_acquire_fixed(Mac2HostAddr(addr), size); -} - -static inline int vm_mac_release(uint32 addr, uint32 size) -{ - return vm_release(Mac2HostAddr(addr), size); -} - - -/* - * Main program - */ - -static void usage(const char *prg_name) -{ - printf("Usage: %s [OPTION...]\n", prg_name); - printf("\nUnix options:\n"); - printf(" --display STRING\n X display to use\n"); - PrefsPrintUsage(); - exit(0); -} - -int main(int argc, char **argv) -{ - char str[256]; - int16 i16; - HANDLE rom_fh; - const char *rom_path; - uint32 rom_size; - DWORD actual; - uint8 *rom_tmp; - - // Initialize variables - RAMBase = 0; - - // Print some info - printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); - printf(" %s\n", GetString(STR_ABOUT_TEXT2)); - - // Read preferences - PrefsInit(NULL, argc, argv); - - // Parse command line arguments - for (int i=1; i= 4.0 - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx(&osvi)) { - ErrorAlert("Could not determine OS type"); - QuitEmulator(); - } - win_os = osvi.dwPlatformId; - win_os_major = osvi.dwMajorVersion; - if (win_os != VER_PLATFORM_WIN32_NT || win_os_major < 4) { - ErrorAlert(GetString(STR_NO_WIN32_NT_4)); - QuitEmulator(); - } - - // Check that drivers are installed - if (!check_drivers()) - QuitEmulator(); - - // Load win32 libraries - KernelInit(); - - // FIXME: default to DIB driver - if (getenv("SDL_VIDEODRIVER") == NULL) - putenv("SDL_VIDEODRIVER=windib"); - - // Initialize SDL system - int sdl_flags = 0; -#ifdef USE_SDL_VIDEO - sdl_flags |= SDL_INIT_VIDEO; -#endif -#ifdef USE_SDL_AUDIO - sdl_flags |= SDL_INIT_AUDIO; -#endif - assert(sdl_flags != 0); - if (SDL_Init(sdl_flags) == -1) { - char str[256]; - sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError()); - ErrorAlert(str); - goto quit; - } - atexit(SDL_Quit); - -#ifdef ENABLE_MON - // Initialize mon - mon_init(); -#endif - - // Install SIGSEGV handler for CPU emulator - if (!sigsegv_install_handler(sigsegv_handler)) { - sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - - // Initialize VM system - vm_init(); - - // Get system info - PVR = 0x00040000; // Default: 604 - CPUClockSpeed = 100000000; // Default: 100MHz - BusClockSpeed = 100000000; // Default: 100MHz - TimebaseSpeed = 25000000; // Default: 25MHz - PVR = 0x000c0000; // Default: 7400 (with AltiVec) - D(bug("PVR: %08x (assumed)\n", PVR)); - - // Init system routines - SysInit(); - - // Show preferences editor - if (!PrefsFindBool("nogui")) - if (!PrefsEditor()) - goto quit; - - // Create areas for Kernel Data - if (!kernel_data_init()) - goto quit; - kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE); - emulator_data = &kernel_data->ed; - KernelDataAddr = KERNEL_DATA_BASE; - D(bug("Kernel Data at %p (%08x)\n", kernel_data, KERNEL_DATA_BASE)); - D(bug("Emulator Data at %p (%08x)\n", emulator_data, KERNEL_DATA_BASE + offsetof(KernelData, ed))); - - // Create area for DR Cache - if (vm_mac_acquire(DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) { - sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - dr_emulator_area_mapped = true; - if (vm_mac_acquire(DR_CACHE_BASE, DR_CACHE_SIZE) < 0) { - sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - dr_cache_area_mapped = true; - DRCacheAddr = (uint32)Mac2HostAddr(DR_CACHE_BASE); - D(bug("DR Cache at %p (%08x)\n", DRCacheAddr, DR_CACHE_BASE)); - - // Create area for SheepShaver data - if (!SheepMem::Init()) { - sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - - // Create area for Mac ROM - if (vm_mac_acquire(ROM_BASE, ROM_AREA_SIZE) < 0) { - sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - ROMBase = ROM_BASE; - ROMBaseHost = Mac2HostAddr(ROMBase); - rom_area_mapped = true; - D(bug("ROM area at %p (%08x)\n", ROMBaseHost, ROMBase)); - - // Create area for Mac RAM - RAMSize = PrefsFindInt32("ramsize"); - if (RAMSize < 8*1024*1024) { - WarningAlert(GetString(STR_SMALL_RAM_WARN)); - RAMSize = 8*1024*1024; - } - RAMBase = 0; - if (vm_mac_acquire(RAMBase, RAMSize) < 0) { - sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); - ErrorAlert(str); - goto quit; - } - RAMBaseHost = Mac2HostAddr(RAMBase); - ram_area_mapped = true; - D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase)); - - if (RAMBase > ROMBase) { - ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR)); - goto quit; - } - - // Load Mac ROM - rom_path = PrefsFindString("rom"); - rom_fh = CreateFile(rom_path && *rom_path ? rom_path : ROM_FILE_NAME, - GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (rom_fh == INVALID_HANDLE_VALUE) { - rom_fh = CreateFile(ROM_FILE_NAME2, - GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (rom_fh == INVALID_HANDLE_VALUE) { - ErrorAlert(GetString(STR_NO_ROM_FILE_ERR)); - goto quit; - } - } - printf(GetString(STR_READING_ROM_FILE)); - rom_size = GetFileSize(rom_fh, NULL); - rom_tmp = new uint8[ROM_SIZE]; - ReadFile(rom_fh, (void *)rom_tmp, ROM_SIZE, &actual, NULL); - CloseHandle(rom_fh); - - // Decode Mac ROM - if (!DecodeROM(rom_tmp, actual)) { - if (rom_size != 4*1024*1024) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - goto quit; - } else { - ErrorAlert(GetString(STR_ROM_FILE_READ_ERR)); - goto quit; - } - } - delete[] rom_tmp; - - // Initialize native timers - timer_init(); - - // Initialize everything - if (!InitAll(NULL)) - goto quit; - D(bug("Initialization complete\n")); - - // Write protect ROM - vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ); - - // Start 60Hz thread - tick_thread_cancel = false; - tick_thread_active = ((tick_thread = create_thread(tick_func)) != NULL); - SetThreadPriority(tick_thread, THREAD_PRIORITY_ABOVE_NORMAL); - D(bug("Tick thread installed (%ld)\n", tick_thread)); - - // Start NVRAM watchdog thread - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - nvram_thread_cancel = false; - nvram_thread_active = ((nvram_thread = create_thread(nvram_func, NULL)) != NULL); - SetThreadPriority(nvram_thread, THREAD_PRIORITY_BELOW_NORMAL); - D(bug("NVRAM thread installed (%ld)\n", nvram_thread)); - - // Get my thread ID and jump to ROM boot routine - emul_thread = GetCurrentThread(); - D(bug("Jumping to ROM\n")); - jump_to_rom(ROMBase + 0x310000); - D(bug("Returned from ROM\n")); - -quit: - Quit(); - return 0; -} - - -/* - * Cleanup and quit - */ - -static void Quit(void) -{ - // Exit PowerPC emulation - exit_emul_ppc(); - - // Stop 60Hz thread - if (tick_thread_active) { - tick_thread_cancel = true; - wait_thread(tick_thread); - } - - // Stop NVRAM watchdog thread - if (nvram_thread_active) { - nvram_thread_cancel = true; - wait_thread(nvram_thread); - } - - // Deinitialize everything - ExitAll(); - - // Delete SheepShaver globals - SheepMem::Exit(); - - // Delete RAM area - if (ram_area_mapped) - vm_mac_release(RAMBase, RAMSize); - - // Delete ROM area - if (rom_area_mapped) - vm_mac_release(ROMBase, ROM_AREA_SIZE); - - // Delete DR cache areas - if (dr_emulator_area_mapped) - vm_mac_release(DR_EMULATOR_BASE, DR_EMULATOR_SIZE); - if (dr_cache_area_mapped) - vm_mac_release(DR_CACHE_BASE, DR_CACHE_SIZE); - - // Delete Kernel Data area - kernel_data_exit(); - - // Exit system routines - SysExit(); - - // Exit preferences - PrefsExit(); - - // Release win32 libraries - KernelExit(); - -#ifdef ENABLE_MON - // Exit mon - mon_exit(); -#endif - - exit(0); -} - - -/* - * Initialize Kernel Data segments - */ - -static HANDLE kernel_handle; // Shared memory handle for Kernel Data -static DWORD allocation_granule; // Minimum size of allocateable are (64K) -static DWORD kernel_area_size; // Size of Kernel Data area - -static bool kernel_data_init(void) -{ - char str[256]; - SYSTEM_INFO si; - GetSystemInfo(&si); - allocation_granule = si.dwAllocationGranularity; - kernel_area_size = (KERNEL_AREA_SIZE + allocation_granule - 1) & -allocation_granule; - - char rcs[10]; - LPVOID kernel_addr; - kernel_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, kernel_area_size, NULL); - if (kernel_handle == NULL) { - sprintf(rcs, "%d", GetLastError()); - sprintf(str, GetString(STR_KD_SHMGET_ERR), rcs); - ErrorAlert(str); - return false; - } - kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule); - if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) { - sprintf(rcs, "%d", GetLastError()); - sprintf(str, GetString(STR_KD_SHMAT_ERR), rcs); - ErrorAlert(str); - return false; - } - kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule); - if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) { - sprintf(rcs, "%d", GetLastError()); - sprintf(str, GetString(STR_KD2_SHMAT_ERR), rcs); - ErrorAlert(str); - return false; - } - return true; -} - - -/* - * Deallocate Kernel Data segments - */ - -static void kernel_data_exit(void) -{ - if (kernel_handle) { - UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule)); - UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule)); - CloseHandle(kernel_handle); - } -} - - -/* - * Jump into Mac ROM, start 680x0 emulator - */ - -void jump_to_rom(uint32 entry) -{ - init_emul_ppc(); - emul_ppc(entry); -} - - -/* - * Quit emulator (cause return from jump_to_rom) - */ - -void QuitEmulator(void) -{ - Quit(); -} - - -/* - * Pause/resume emulator - */ - -void PauseEmulator(void) -{ - SuspendThread(emul_thread); -} - -void ResumeEmulator(void) -{ - ResumeThread(emul_thread); -} - - -/* - * Dump 68k registers - */ - -void Dump68kRegs(M68kRegisters *r) -{ - // Display 68k registers - for (int i=0; i<8; i++) { - printf("d%d: %08x", i, r->d[i]); - if (i == 3 || i == 7) - printf("\n"); - else - printf(", "); - } - for (int i=0; i<8; i++) { - printf("a%d: %08x", i, r->a[i]); - if (i == 3 || i == 7) - printf("\n"); - else - printf(", "); - } -} - - -/* - * Make code executable - */ - -void MakeExecutable(int dummy, uint32 start, uint32 length) -{ - if ((start >= ROMBase) && (start < (ROMBase + ROM_SIZE))) - return; - FlushCodeCache(start, start + length); -} - - -/* - * NVRAM watchdog thread (saves NVRAM every minute) - */ - -static void nvram_watchdog(void) -{ - if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { - memcpy(last_xpram, XPRAM, XPRAM_SIZE); - SaveXPRAM(); - } -} - -static DWORD nvram_func(void *arg) -{ - while (!nvram_thread_cancel) { - for (int i=0; i<60 && !nvram_thread_cancel; i++) - Delay_usec(999999); // Only wait 1 second so we quit promptly when nvram_thread_cancel becomes true - nvram_watchdog(); - } - return 0; -} - - -/* - * 60Hz thread (really 60.15Hz) - */ - -static DWORD tick_func(void *arg) -{ - int tick_counter = 0; - uint64 start = GetTicks_usec(); - int64 ticks = 0; - uint64 next = GetTicks_usec(); - - while (!tick_thread_cancel) { - - // Wait - next += 16625; - int64 delay = next - GetTicks_usec(); - if (delay > 0) - Delay_usec(delay); - else if (delay < -16625) - next = GetTicks_usec(); - ticks++; - - // Pseudo Mac 1Hz interrupt, update local time - if (++tick_counter > 60) { - tick_counter = 0; - WriteMacInt32(0x20c, TimerDateTime()); - } - - // Trigger 60Hz interrupt - if (ReadMacInt32(XLM_IRQ_NEST) == 0) { - SetInterruptFlag(INTFLAG_VIA); - TriggerInterrupt(); - } - } - - uint64 end = GetTicks_usec(); - D(bug("%lu ticks in %lu usec = %f ticks/sec\n", (unsigned long)ticks, (unsigned long)(end - start), ticks * 1000000.0 / (end - start))); - return 0; -} - - -/* - * Mutexes - */ - -struct B2_mutex { - mutex_t m; -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ - mutex->m.lock(); -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ - mutex->m.unlock(); -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - - -/* - * Interrupt flags (must be handled atomically!) - */ - -volatile uint32 InterruptFlags = 0; -static mutex_t intflags_mutex; - -void SetInterruptFlag(uint32 flag) -{ - intflags_mutex.lock(); - InterruptFlags |= flag; - intflags_mutex.unlock(); -} - -void ClearInterruptFlag(uint32 flag) -{ - intflags_mutex.lock(); - InterruptFlags &= ~flag; - intflags_mutex.unlock(); -} - - -/* - * Disable interrupts - */ - -void DisableInterrupt(void) -{ - WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) + 1); -} - - -/* - * Enable interrupts - */ - -void EnableInterrupt(void) -{ - WriteMacInt32(XLM_IRQ_NEST, int32(ReadMacInt32(XLM_IRQ_NEST)) - 1); -} - - -/* - * Helpers to share 32-bit addressable data with MacOS - */ - -bool SheepMem::Init(void) -{ - // Size of a native page - page_size = vm_get_page_size(); - - // Allocate SheepShaver globals - proc = base; - if (vm_mac_acquire(base, size) < 0) - return false; - - // Allocate page with all bits set to 0, right in the middle - // This is also used to catch undesired overlaps between proc and data areas - zero_page = proc + (size / 2); - Mac_memset(zero_page, 0, page_size); - if (vm_protect(Mac2HostAddr(zero_page), page_size, VM_PAGE_READ) < 0) - return false; - - // Allocate alternate stack for PowerPC interrupt routine - sig_stack = base + size; - if (vm_mac_acquire(sig_stack, SIG_STACK_SIZE) < 0) - return false; - - data = base + size; - return true; -} - -void SheepMem::Exit(void) -{ - if (data) { - // Delete SheepShaver globals - vm_mac_release(base, size); - - // Delete alternate stack for PowerPC interrupt routine - vm_mac_release(sig_stack, SIG_STACK_SIZE); - } -} - - -/* - * Get the main window handle - */ - -#ifdef USE_SDL_VIDEO -#include -HWND GetMainWindowHandle(void) -{ - SDL_SysWMinfo wmInfo; - SDL_VERSION(&wmInfo.version); - return SDL_GetWMInfo(&wmInfo) ? wmInfo.window : NULL; -} -#endif - - -/* - * Display alert - */ - -static void display_alert(int title_id, const char *text, int flags) -{ - HWND hMainWnd = GetMainWindowHandle(); - MessageBox(hMainWnd, text, GetString(title_id), MB_OK | flags); -} - - -/* - * Display error alert - */ - -void ErrorAlert(const char *text) -{ - if (PrefsFindBool("nogui")) - return; - - VideoQuitFullScreen(); - display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP); -} - - -/* - * Display warning alert - */ - -void WarningAlert(const char *text) -{ - if (PrefsFindBool("nogui")) - return; - - display_alert(STR_WARNING_ALERT_TITLE, text, MB_ICONINFORMATION); -} - - -/* - * Display choice alert - */ - -bool ChoiceAlert(const char *text, const char *pos, const char *neg) -{ - printf(GetString(STR_SHELL_WARNING_PREFIX), text); - return false; //!! -} diff --git a/SheepShaver/src/Windows/posix_emu.cpp b/SheepShaver/src/Windows/posix_emu.cpp deleted file mode 120000 index 336f134f..00000000 --- a/SheepShaver/src/Windows/posix_emu.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/posix_emu.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/posix_emu.h b/SheepShaver/src/Windows/posix_emu.h deleted file mode 120000 index 6fd82b8b..00000000 --- a/SheepShaver/src/Windows/posix_emu.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/posix_emu.h \ No newline at end of file diff --git a/SheepShaver/src/Windows/prefs_editor_gtk.cpp b/SheepShaver/src/Windows/prefs_editor_gtk.cpp deleted file mode 120000 index b94e7615..00000000 --- a/SheepShaver/src/Windows/prefs_editor_gtk.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/prefs_editor_gtk.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/prefs_windows.cpp b/SheepShaver/src/Windows/prefs_windows.cpp deleted file mode 100755 index 3f83b045..00000000 --- a/SheepShaver/src/Windows/prefs_windows.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * prefs_windows.cpp - Preferences handling, Windows specific stuff - * - * SheepShaver (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include - -#include -using std::string; - -#include "prefs.h" - - -// Platform-specific preferences items -prefs_desc platform_prefs_items[] = { - {"ether", TYPE_STRING, false, "device name of Mac ethernet adapter"}, - {"keycodes", TYPE_BOOLEAN, false, "use keycodes rather than keysyms to decode keyboard"}, - {"keycodefile", TYPE_STRING, false, "path of keycode translation file"}, - {"mousewheelmode", TYPE_INT32, false, "mouse wheel support mode (0=page up/down, 1=cursor up/down)"}, - {"mousewheellines", TYPE_INT32, false, "number of lines to scroll in mouse wheel mode 1"}, -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - {"ignoresegv", TYPE_BOOLEAN, false, "ignore illegal memory accesses"}, -#endif - {"idlewait", TYPE_BOOLEAN, false, "sleep when idle"}, - {"keycodes", TYPE_BOOLEAN, false, "use keycodes rather than keysyms to decode keyboard"}, - {"keycodefile", TYPE_STRING, false, "path of keycode translation file"}, - {"mousewheelmode", TYPE_INT32, false, "mouse wheel support mode (0=page up/down, 1=cursor up/down)"}, - {"mousewheellines", TYPE_INT32, false, "number of lines to scroll in mouse wheel mode 1"}, - {"enableextfs", TYPE_BOOLEAN, false, "enable extfs system"}, - {"debugextfs", TYPE_BOOLEAN, false, "debug extfs system"}, - {"extdrives", TYPE_STRING, false, "define allowed extfs drives"}, - {"pollmedia", TYPE_BOOLEAN, false, "poll for new media (e.g. cd, floppy)"}, - {"etherguid", TYPE_STRING, false, "GUID of the ethernet device to use"}, - {"etherpermanentaddress", TYPE_BOOLEAN, false, "use permanent NIC address to identify itself"}, - {"ethermulticastmode", TYPE_INT32, false, "how to multicast packets"}, - {"etherfakeaddress", TYPE_STRING, false, "optional fake hardware address"}, - {"routerenabled", TYPE_BOOLEAN, false, "enable NAT/Router module"}, - {"ftp_port_list", TYPE_STRING, false, "FTP ports list"}, - {"tcp_port", TYPE_STRING, false, "TCP ports list"}, - {"portfile0", TYPE_STRING, false, "output file for serial port 0"}, - {"portfile1", TYPE_STRING, false, "output file for serial port 1"}, - - {NULL, TYPE_END, false, NULL} // End of list -}; - - -// Prefs file name and path -const char PREFS_FILE_NAME[] = "SheepShaver_prefs"; -string UserPrefsPath; -static string prefs_path; - - -/* - * Load preferences from settings file - */ - -void LoadPrefs(const char *vmdir) -{ - // Construct prefs path - if (UserPrefsPath.empty()) { - int pwd_len = GetCurrentDirectory(0, NULL); - char *pwd = new char[pwd_len]; - if (GetCurrentDirectory(pwd_len, pwd) == pwd_len - 1) - prefs_path = string(pwd) + '\\'; - delete[] pwd; - prefs_path += PREFS_FILE_NAME; - } else - prefs_path = UserPrefsPath; - - // Read preferences from settings file - FILE *f = fopen(prefs_path.c_str(), "r"); - if (f != NULL) { - - // Prefs file found, load settings - LoadPrefsFromStream(f); - fclose(f); - - } else { - - // No prefs file, save defaults - SavePrefs(); - } -} - - -/* - * Save preferences to settings file - */ - -void SavePrefs(void) -{ - FILE *f; - if ((f = fopen(prefs_path.c_str(), "w")) != NULL) { - SavePrefsToStream(f); - fclose(f); - } -} - - -/* - * Add defaults of platform-specific prefs items - * You may also override the defaults set in PrefsInit() - */ - -void AddPlatformPrefsDefaults(void) -{ - PrefsAddBool("keycodes", false); - PrefsReplaceBool("pollmedia", true); - PrefsReplaceBool("enableextfs", false); - PrefsReplaceString("extfs", ""); - PrefsReplaceString("extdrives", "CDEFGHIJKLMNOPQRSTUVWXYZ"); - PrefsReplaceInt32("mousewheelmode", 1); - PrefsReplaceInt32("mousewheellines", 3); - PrefsAddInt32("windowmodes", 3); - PrefsAddInt32("screenmodes", 0x3f); -#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION - PrefsAddBool("ignoresegv", false); -#endif - PrefsAddBool("idlewait", true); - PrefsReplaceBool("etherpermanentaddress", true); - PrefsReplaceInt32("ethermulticastmode", 0); - PrefsReplaceBool("routerenabled", false); - PrefsReplaceString("ftp_port_list", "21"); - PrefsReplaceString("seriala", "COM1"); - PrefsReplaceString("serialb", "COM2"); - PrefsReplaceString("portfile0", "C:\\B2TEMP0.OUT"); - PrefsReplaceString("portfile1", "C:\\B2TEMP1.OUT"); -} diff --git a/SheepShaver/src/Windows/router b/SheepShaver/src/Windows/router deleted file mode 120000 index e8619d55..00000000 --- a/SheepShaver/src/Windows/router +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/router \ No newline at end of file diff --git a/SheepShaver/src/Windows/serial_windows.cpp b/SheepShaver/src/Windows/serial_windows.cpp deleted file mode 120000 index 88454f92..00000000 --- a/SheepShaver/src/Windows/serial_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/serial_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/sys_windows.cpp b/SheepShaver/src/Windows/sys_windows.cpp deleted file mode 120000 index 3eacbe88..00000000 --- a/SheepShaver/src/Windows/sys_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/sys_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/sysdeps.h b/SheepShaver/src/Windows/sysdeps.h deleted file mode 100755 index f5aaee12..00000000 --- a/SheepShaver/src/Windows/sysdeps.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * sysdeps.h - System dependent definitions for Windows - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -#ifndef __STDC__ -#error "Your compiler is not ANSI. Get a real one." -#endif - -#include "config.h" -#include "user_strings_windows.h" - -#ifndef STDC_HEADERS -#error "You don't have ANSI C header files." -#endif - -#include -#include -#include -#include -#include -#include -#ifdef __WIN32__ -#include -#endif -#include - - -// Define for external components -#define SHEEPSHAVER 1 -#define POWERPC_ROM 1 -#define EMULATED_PPC 1 -#define CONFIG_WIN32 1 - -// Use Direct Addressing mode -#define DIRECT_ADDRESSING 1 -#define NATMEM_OFFSET 0x11000000 - -// Always use the complete (non-stubs based) Ethernet driver -#if DIRECT_ADDRESSING -#define USE_ETHER_FULL_DRIVER 1 -#endif - -// Mac ROM is write protected when banked memory is used -#if REAL_ADDRESSING || DIRECT_ADDRESSING -# define ROM_IS_WRITE_PROTECTED 0 -# define USE_SCRATCHMEM_SUBTERFUGE 1 -#else -# define ROM_IS_WRITE_PROTECTED 1 -#endif -// Configure PowerPC emulator -#define PPC_REENTRANT_JIT 1 -#define PPC_CHECK_INTERRUPTS 1 -#define PPC_DECODE_CACHE 1 -#define PPC_FLIGHT_RECORDER 1 -#define PPC_PROFILE_COMPILE_TIME 0 -#define PPC_PROFILE_GENERIC_CALLS 0 -#define KPX_MAX_CPUS 1 -#if ENABLE_DYNGEN -#define PPC_ENABLE_JIT 1 -#endif -#if defined(__i386__) -#define DYNGEN_ASM_OPTS 1 -#endif - -// Data types -typedef unsigned char uint8; -typedef signed char int8; -#if SIZEOF_SHORT == 2 -typedef unsigned short uint16; -typedef short int16; -#elif SIZEOF_INT == 2 -typedef unsigned int uint16; -typedef int int16; -#else -#error "No 2 byte type, you lose." -#endif -#if SIZEOF_INT == 4 -typedef unsigned int uint32; -typedef int int32; -#elif SIZEOF_LONG == 4 -typedef unsigned long uint32; -typedef long int32; -#else -#error "No 4 byte type, you lose." -#endif -#if SIZEOF_LONG == 8 -typedef unsigned long uint64; -typedef long int64; -#define VAL64(a) (a ## l) -#define UVAL64(a) (a ## ul) -#elif SIZEOF_LONG_LONG == 8 -typedef unsigned long long uint64; -typedef long long int64; -#define VAL64(a) (a ## LL) -#define UVAL64(a) (a ## uLL) -#else -#error "No 8 byte type, you lose." -#endif -#if SIZEOF_VOID_P == 4 -typedef uint32 uintptr; -typedef int32 intptr; -#elif SIZEOF_VOID_P == 8 -typedef uint64 uintptr; -typedef int64 intptr; -#else -#error "Unsupported size of pointer" -#endif - -// Define if the host processor supports fast unaligned load/stores -#if defined __i386__ || defined __x86_64__ -#define UNALIGNED_PROFITABLE 1 -#endif - - -/** - * Helper functions to byteswap data - **/ - -#if defined(__GNUC__) -#if defined(__x86_64__) || defined(__i386__) -// Linux/AMD64 currently has no asm optimized bswap_32() in -#define opt_bswap_32 do_opt_bswap_32 -static inline uint32 do_opt_bswap_32(uint32 x) -{ - uint32 v; - __asm__ __volatile__ ("bswap %0" : "=r" (v) : "0" (x)); - return v; -} -#endif -#endif - -#ifdef opt_bswap_16 -#undef bswap_16 -#define bswap_16 opt_bswap_16 -#endif -#ifndef bswap_16 -#define bswap_16 generic_bswap_16 -#endif - -static inline uint16 generic_bswap_16(uint16 x) -{ - return ((x & 0xff) << 8) | ((x >> 8) & 0xff); -} - -#ifdef opt_bswap_32 -#undef bswap_32 -#define bswap_32 opt_bswap_32 -#endif -#ifndef bswap_32 -#define bswap_32 generic_bswap_32 -#endif - -static inline uint32 generic_bswap_32(uint32 x) -{ - return (((x & 0xff000000) >> 24) | - ((x & 0x00ff0000) >> 8) | - ((x & 0x0000ff00) << 8) | - ((x & 0x000000ff) << 24) ); -} - -#if defined(__i386__) -#define opt_bswap_64 do_opt_bswap_64 -static inline uint64 do_opt_bswap_64(uint64 x) -{ - return (bswap_32(x >> 32) | (((uint64)bswap_32((uint32)x)) << 32)); -} -#endif - -#ifdef opt_bswap_64 -#undef bswap_64 -#define bswap_64 opt_bswap_64 -#endif -#ifndef bswap_64 -#define bswap_64 generic_bswap_64 -#endif - -static inline uint64 generic_bswap_64(uint64 x) -{ - return (((x & UVAL64(0xff00000000000000)) >> 56) | - ((x & UVAL64(0x00ff000000000000)) >> 40) | - ((x & UVAL64(0x0000ff0000000000)) >> 24) | - ((x & UVAL64(0x000000ff00000000)) >> 8) | - ((x & UVAL64(0x00000000ff000000)) << 8) | - ((x & UVAL64(0x0000000000ff0000)) << 24) | - ((x & UVAL64(0x000000000000ff00)) << 40) | - ((x & UVAL64(0x00000000000000ff)) << 56) ); -} - -#ifdef WORDS_BIGENDIAN -static inline uint16 tswap16(uint16 x) { return x; } -static inline uint32 tswap32(uint32 x) { return x; } -static inline uint64 tswap64(uint64 x) { return x; } -#else -static inline uint16 tswap16(uint16 x) { return bswap_16(x); } -static inline uint32 tswap32(uint32 x) { return bswap_32(x); } -static inline uint64 tswap64(uint64 x) { return bswap_64(x); } -#endif - -#define do_byteswap_16_g bswap_16 -#define do_byteswap_16_c(x) \ - ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) - -#define do_byteswap_32_g bswap_32 -#define do_byteswap_32_c(x) \ - ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - -#if defined(__GNUC__) -#define do_byteswap_16(x) \ - (__extension__ \ - ({ register uint16 __v, __x = (x); \ - if (__builtin_constant_p(__x)) \ - __v = do_byteswap_16_c(__x); \ - else \ - __v = do_byteswap_16_g(__x); \ - __v; })) - -#define do_byteswap_32(x) \ - (__extension__ \ - ({ register uint32 __v, __x = (x); \ - if (__builtin_constant_p(__x)) \ - __v = do_byteswap_32_c(__x); \ - else \ - __v = do_byteswap_32_g(__x); \ - __v; })) -#else -#define do_byteswap_16(x) do_byteswap_16_g(x) -#define do_byteswap_32(x) do_byteswap_32_g(x) -#endif - -#if defined(__i386__) || defined(__x86_64__) -#define ntohl(x) do_byteswap_32(x) -#define ntohs(x) do_byteswap_16(x) -#define htonl(x) do_byteswap_32(x) -#define htons(x) do_byteswap_16(x) -#endif - - -/* - * Spin locks - */ - -#ifdef __GNUC__ - -#if defined(__powerpc__) || defined(__ppc__) -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - __asm__ __volatile__("0: lwarx %0,0,%1\n" - " xor. %0,%3,%0\n" - " bne 1f\n" - " stwcx. %2,0,%1\n" - " bne- 0b\n" - "1: " - : "=&r" (ret) - : "r" (p), "r" (1), "r" (0) - : "cr0", "memory"); - return ret; -} -#endif - -#if defined(__i386__) || defined(__x86_64__) -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - long int ret; - /* Note: the "xchg" instruction does not need a "lock" prefix */ - __asm__ __volatile__("xchgl %k0, %1" - : "=r" (ret), "=m" (*p) - : "0" (1), "m" (*p) - : "memory"); - return ret; -} -#endif - -#ifdef __alpha__ -#define HAVE_TEST_AND_SET 1 -static inline int testandset(volatile int *p) -{ - int ret; - unsigned long one; - - __asm__ __volatile__("0: mov 1,%2\n" - " ldl_l %0,%1\n" - " stl_c %2,%1\n" - " beq %2,1f\n" - ".subsection 2\n" - "1: br 0b\n" - ".previous" - : "=r" (ret), "=m" (*p), "=r" (one) - : "m" (*p)); - return ret; -} -#endif - -#endif /* __GNUC__ */ - -typedef volatile int spinlock_t; - -static const spinlock_t SPIN_LOCK_UNLOCKED = 0; - -#if HAVE_TEST_AND_SET -#define HAVE_SPINLOCKS 1 -static inline void spin_lock(spinlock_t *lock) -{ - while (testandset(lock)); -} - -static inline void spin_unlock(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return !testandset(lock); -} -#else -static inline void spin_lock(spinlock_t *lock) -{ -} - -static inline void spin_unlock(spinlock_t *lock) -{ -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return 1; -} -#endif - -// Time data type for Time Manager emulation -typedef int64 tm_time_t; - -// Timing functions -extern void timer_init(void); -extern uint64 GetTicks_usec(void); -extern void Delay_usec(uint32 usec); - -// Various definitions -typedef struct rgb_color { - uint8 red; - uint8 green; - uint8 blue; - uint8 alpha; -} rgb_color; - -// Macro for calling MacOS routines -#define CallMacOS(type, tvect) call_macos((uintptr)tvect) -#define CallMacOS1(type, tvect, arg1) call_macos1((uintptr)tvect, (uintptr)arg1) -#define CallMacOS2(type, tvect, arg1, arg2) call_macos2((uintptr)tvect, (uintptr)arg1, (uintptr)arg2) -#define CallMacOS3(type, tvect, arg1, arg2, arg3) call_macos3((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3) -#define CallMacOS4(type, tvect, arg1, arg2, arg3, arg4) call_macos4((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4) -#define CallMacOS5(type, tvect, arg1, arg2, arg3, arg4, arg5) call_macos5((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5) -#define CallMacOS6(type, tvect, arg1, arg2, arg3, arg4, arg5, arg6) call_macos6((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5, (uintptr)arg6) -#define CallMacOS7(type, tvect, arg1, arg2, arg3, arg4, arg5, arg6, arg7) call_macos7((uintptr)tvect, (uintptr)arg1, (uintptr)arg2, (uintptr)arg3, (uintptr)arg4, (uintptr)arg5, (uintptr)arg6, (uintptr)arg7) - -#ifdef __cplusplus -extern "C" { -#endif -extern uint32 call_macos(uint32 tvect); -extern uint32 call_macos1(uint32 tvect, uint32 arg1); -extern uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2); -extern uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3); -extern uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4); -extern uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5); -extern uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6); -extern uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7); -#ifdef __cplusplus -} -#endif - -// Misc platform specific definitions -#ifdef __WIN32__ -typedef int64 loff_t; -#endif -#define ATTRIBUTE_PACKED __attribute__((__packed__)) - -#endif diff --git a/SheepShaver/src/Windows/timer_windows.cpp b/SheepShaver/src/Windows/timer_windows.cpp deleted file mode 120000 index b43201a9..00000000 --- a/SheepShaver/src/Windows/timer_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/timer_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/user_strings_windows.cpp b/SheepShaver/src/Windows/user_strings_windows.cpp deleted file mode 100755 index 92555c8f..00000000 --- a/SheepShaver/src/Windows/user_strings_windows.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * user_strings_windows.cpp - Localizable strings, Windows specific strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "user_strings.h" - - -// Platform-specific string definitions -user_string_def platform_strings[] = { - // Common strings that have a platform-specific variant - {STR_EXTFS_VOLUME_NAME, "My Computer"}, - - // Purely platform-specific strings - {STR_LOW_MEM_MMAP_ERR, "Cannot map Low Memory Globals: %s."}, - {STR_KD_SHMGET_ERR, "Cannot create SHM segment for Kernel Data: %s."}, - {STR_KD_SHMAT_ERR, "Cannot map first Kernel Data area: %s."}, - {STR_KD2_SHMAT_ERR, "Cannot map second Kernel Data area: %s."}, - {STR_ROM_MMAP_ERR, "Cannot map ROM: %s."}, - {STR_RAM_MMAP_ERR, "Cannot map RAM: %s."}, - {STR_DR_CACHE_MMAP_ERR, "Cannot map DR Cache: %s."}, - {STR_DR_EMULATOR_MMAP_ERR, "Cannot map DR Emulator: %s."}, - {STR_SHEEP_MEM_MMAP_ERR, "Cannot map SheepShaver Data area: %s."}, - {STR_NO_XVISUAL_ERR, "Cannot obtain appropriate X visual."}, - {STR_SLIRP_NO_DNS_FOUND_WARN, "Cannot get DNS address. Ethernet will not be available."}, - {STR_NO_AUDIO_WARN, "No audio device found, audio output will be disabled."}, - {STR_KEYCODE_FILE_WARN, "Cannot open keycode translation file %s (%s)."}, - {STR_KEYCODE_VENDOR_WARN, "Cannot find vendor '%s' in keycode translation file %s."}, - {STR_VOSF_INIT_ERR, "Cannot initialize Video on SEGV signals."}, - - {STR_OPEN_WINDOW_ERR, "Cannot open Mac window."}, - {STR_WINDOW_TITLE_GRABBED, "SheepShaver (mouse grabbed, press Ctrl-F5 to release)"}, - {STR_NO_WIN32_NT_4, "SheepShaver does not run on Windows NT versions less than 4.0"}, - - {STR_PREFS_MENU_FILE_GTK, "/_File"}, - {STR_PREFS_ITEM_START_GTK, "/File/_Start SheepShaver"}, - {STR_PREFS_ITEM_ZAP_PRAM_GTK, "/File/_Zap PRAM File"}, - {STR_PREFS_ITEM_SEPL_GTK, "/File/sepl"}, - {STR_PREFS_ITEM_QUIT_GTK, "/File/_Quit SheepShaver"}, - {STR_HELP_MENU_GTK, "/_Help"}, - {STR_HELP_ITEM_ABOUT_GTK, "/Help/_About SheepShaver"}, - - {STR_FILE_CTRL, "File"}, - {STR_BROWSE_TITLE, "Browse file"}, - {STR_BROWSE_CTRL, "Browse..."}, - {STR_SERIAL_PANE_TITLE, "Serial"}, - {STR_NETWORK_PANE_TITLE, "Network"}, - {STR_INPUT_PANE_TITLE, "Keyboard/Mouse"}, - {STR_KEYCODES_CTRL, "Use Raw Keycodes"}, - {STR_KEYCODE_FILE_CTRL, "Keycode Translation File"}, - {STR_MOUSEWHEELMODE_CTRL, "Mouse Wheel Function"}, - {STR_MOUSEWHEELMODE_PAGE_LAB, "Page Up/Down"}, - {STR_MOUSEWHEELMODE_CURSOR_LAB, "Cursor Up/Down"}, - {STR_MOUSEWHEELLINES_CTRL, "Lines To Scroll"}, - {STR_POLLMEDIA_CTRL, "Try to automatically detect new removable media (enable polling)"}, - {STR_EXTFS_ENABLE_CTRL, "Enable \"My Computer\" icon on your Mac desktop (external file system)"}, - {STR_EXTFS_DRIVES_CTRL, "Mount drives"}, - {STR_ETHER_FTP_PORT_LIST_CTRL, "FTP ports"}, - {STR_ETHER_TCP_PORT_LIST_CTRL, "Server ports"}, - - {-1, NULL} // End marker -}; - - -/* - * Search for main volume name - */ - -static const char *get_volume_name(void) -{ - HKEY hHelpKey; - DWORD key_type, cbData; - - static char volume[256]; - memset(volume, 0, sizeof(volume)); - - // Try Windows 2000 key first - if (ERROR_SUCCESS == RegOpenKey( - HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}", - &hHelpKey)) - { - cbData = sizeof(volume); - RegQueryValueEx( hHelpKey, 0, NULL, &key_type, (unsigned char *)volume, &cbData ); - RegCloseKey(hHelpKey); - } - - if (volume[0] == 0 && - ERROR_SUCCESS == RegOpenKey( - HKEY_CURRENT_USER, - "Software\\Classes\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}", - &hHelpKey)) - { - cbData = sizeof(volume); - RegQueryValueEx( hHelpKey, 0, NULL, &key_type, (unsigned char *)volume, &cbData ); - RegCloseKey(hHelpKey); - } - - if (volume[0] == 0 && - ERROR_SUCCESS == RegOpenKey( - HKEY_CLASSES_ROOT, - "CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}", - &hHelpKey)) - { - cbData = sizeof(volume); - RegQueryValueEx( hHelpKey, 0, NULL, &key_type, (unsigned char *)volume, &cbData ); - RegCloseKey(hHelpKey); - } - - // Fix the error that some "tweak" apps do. - if (stricmp(volume, "%USERNAME% on %COMPUTER%") == 0) - volume[0] = '\0'; - - // No volume name found, default to "My Computer" - if (volume[0] == 0) - strcpy(volume, "My Computer"); - - return volume; -} - - -/* - * Fetch pointer to string, given the string number - */ - -const char *GetString(int num) -{ - // First, search for platform-specific variable string - switch (num) { - case STR_EXTFS_VOLUME_NAME: - return get_volume_name(); - } - - // Next, search for platform-specific string - int i = 0; - while (platform_strings[i].num >= 0) { - if (platform_strings[i].num == num) - return platform_strings[i].str; - i++; - } - - // Not found, search for common string - i = 0; - while (common_strings[i].num >= 0) { - if (common_strings[i].num == num) - return common_strings[i].str; - i++; - } - return NULL; -} diff --git a/SheepShaver/src/Windows/user_strings_windows.h b/SheepShaver/src/Windows/user_strings_windows.h deleted file mode 100755 index 7980c5f7..00000000 --- a/SheepShaver/src/Windows/user_strings_windows.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * user_strings_windows.h - Windows-specific localizable strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_WINDOWS_H -#define USER_STRINGS_WINDOWS_H - -enum { - STR_LOW_MEM_MMAP_ERR = 10000, - STR_KD_SHMGET_ERR, - STR_KD_SHMAT_ERR, - STR_KD2_SHMAT_ERR, - STR_ROM_MMAP_ERR, - STR_RAM_MMAP_ERR, - STR_DR_CACHE_MMAP_ERR, - STR_DR_EMULATOR_MMAP_ERR, - STR_SHEEP_MEM_MMAP_ERR, - STR_SIGSEGV_INSTALL_ERR, - STR_NO_XVISUAL_ERR, - STR_VOSF_INIT_ERR, - STR_SLIRP_NO_DNS_FOUND_WARN, - STR_NO_AUDIO_WARN, - STR_KEYCODE_FILE_WARN, - STR_KEYCODE_VENDOR_WARN, - STR_OPEN_WINDOW_ERR, - STR_WINDOW_TITLE_GRABBED, - STR_NO_WIN32_NT_4, - - STR_PREFS_MENU_FILE_GTK, - STR_PREFS_ITEM_START_GTK, - STR_PREFS_ITEM_ZAP_PRAM_GTK, - STR_PREFS_ITEM_SEPL_GTK, - STR_PREFS_ITEM_QUIT_GTK, - STR_HELP_MENU_GTK, - STR_HELP_ITEM_ABOUT_GTK, - - STR_FILE_CTRL, - STR_BROWSE_CTRL, - STR_BROWSE_TITLE, - STR_SERIAL_PANE_TITLE, - STR_NETWORK_PANE_TITLE, - STR_INPUT_PANE_TITLE, - STR_KEYCODES_CTRL, - STR_KEYCODE_FILE_CTRL, - STR_MOUSEWHEELMODE_CTRL, - STR_MOUSEWHEELMODE_PAGE_LAB, - STR_MOUSEWHEELMODE_CURSOR_LAB, - STR_MOUSEWHEELLINES_CTRL, - STR_POLLMEDIA_CTRL, - STR_EXTFS_ENABLE_CTRL, - STR_EXTFS_DRIVES_CTRL, - STR_ETHER_FTP_PORT_LIST_CTRL, - STR_ETHER_TCP_PORT_LIST_CTRL, -}; - -#endif diff --git a/SheepShaver/src/Windows/util_windows.cpp b/SheepShaver/src/Windows/util_windows.cpp deleted file mode 120000 index 74810981..00000000 --- a/SheepShaver/src/Windows/util_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/util_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/Windows/util_windows.h b/SheepShaver/src/Windows/util_windows.h deleted file mode 120000 index f875032d..00000000 --- a/SheepShaver/src/Windows/util_windows.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/util_windows.h \ No newline at end of file diff --git a/SheepShaver/src/Windows/xpram_windows.cpp b/SheepShaver/src/Windows/xpram_windows.cpp deleted file mode 120000 index 4c317a37..00000000 --- a/SheepShaver/src/Windows/xpram_windows.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/Windows/xpram_windows.cpp \ No newline at end of file diff --git a/SheepShaver/src/adb.cpp b/SheepShaver/src/adb.cpp deleted file mode 120000 index 1cc36b98..00000000 --- a/SheepShaver/src/adb.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/adb.cpp \ No newline at end of file diff --git a/SheepShaver/src/audio.cpp b/SheepShaver/src/audio.cpp deleted file mode 120000 index 3cc4fd95..00000000 --- a/SheepShaver/src/audio.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/audio.cpp \ No newline at end of file diff --git a/SheepShaver/src/cdrom.cpp b/SheepShaver/src/cdrom.cpp deleted file mode 120000 index d97cd44d..00000000 --- a/SheepShaver/src/cdrom.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/cdrom.cpp \ No newline at end of file diff --git a/SheepShaver/src/disk.cpp b/SheepShaver/src/disk.cpp deleted file mode 120000 index f994afaa..00000000 --- a/SheepShaver/src/disk.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/disk.cpp \ No newline at end of file diff --git a/SheepShaver/src/dummy/audio_dummy.cpp b/SheepShaver/src/dummy/audio_dummy.cpp deleted file mode 120000 index 6c3904ce..00000000 --- a/SheepShaver/src/dummy/audio_dummy.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/dummy/audio_dummy.cpp \ No newline at end of file diff --git a/SheepShaver/src/dummy/clip_dummy.cpp b/SheepShaver/src/dummy/clip_dummy.cpp deleted file mode 120000 index d5f48422..00000000 --- a/SheepShaver/src/dummy/clip_dummy.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/dummy/clip_dummy.cpp \ No newline at end of file diff --git a/SheepShaver/src/dummy/ether_dummy.cpp b/SheepShaver/src/dummy/ether_dummy.cpp deleted file mode 100644 index 5046b051..00000000 --- a/SheepShaver/src/dummy/ether_dummy.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ether_dummy.cpp - Ethernet device driver, dummy implementation - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "cpu_emulation.h" -#include "main.h" -#include "ether.h" -#include "ether_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -/* - * Init ethernet - */ - -void EtherInit(void) -{ -} - - -/* - * Exit ethernet - */ - -void EtherExit(void) -{ -} - - -/* - * Get ethernet hardware address - */ - -void AO_get_ethernet_address(uint32 addr) -{ -} - - -/* - * Enable multicast address - */ - -void AO_enable_multicast(uint32 addr) -{ -} - - -/* - * Disable multicast address - */ - -void AO_disable_multicast(uint32 addr) -{ -} - - -/* - * Transmit one packet - */ - -void AO_transmit_packet(uint32 mp) -{ -} - - -/* - * Ethernet interrupt - */ - -void EtherIRQ(void) -{ -} diff --git a/SheepShaver/src/dummy/prefs_dummy.cpp b/SheepShaver/src/dummy/prefs_dummy.cpp deleted file mode 100644 index d51409b5..00000000 --- a/SheepShaver/src/dummy/prefs_dummy.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * prefs_dummy.cpp - Dummy implementation of prefs_init() and prefs_exit(). - * - * Copyright (C) 2007 Alexei Svitkine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -/* - * Initialization - */ - -void prefs_init(void) -{ -} - -/* - * Exit Deinitialization - */ - -void prefs_exit(void) -{ -} - diff --git a/SheepShaver/src/dummy/prefs_editor_dummy.cpp b/SheepShaver/src/dummy/prefs_editor_dummy.cpp deleted file mode 120000 index 66b5d559..00000000 --- a/SheepShaver/src/dummy/prefs_editor_dummy.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/dummy/prefs_editor_dummy.cpp \ No newline at end of file diff --git a/SheepShaver/src/dummy/scsi_dummy.cpp b/SheepShaver/src/dummy/scsi_dummy.cpp deleted file mode 120000 index ae968210..00000000 --- a/SheepShaver/src/dummy/scsi_dummy.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/dummy/scsi_dummy.cpp \ No newline at end of file diff --git a/SheepShaver/src/dummy/serial_dummy.cpp b/SheepShaver/src/dummy/serial_dummy.cpp deleted file mode 120000 index 26af78ab..00000000 --- a/SheepShaver/src/dummy/serial_dummy.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/dummy/serial_dummy.cpp \ No newline at end of file diff --git a/SheepShaver/src/emul_op.cpp b/SheepShaver/src/emul_op.cpp deleted file mode 100644 index 9e01554d..00000000 --- a/SheepShaver/src/emul_op.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* - * emul_op.cpp - 68k opcodes for ROM patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "sysdeps.h" -#include "main.h" -#include "version.h" -#include "prefs.h" -#include "cpu_emulation.h" -#include "xlowmem.h" -#include "xpram.h" -#include "timer.h" -#include "adb.h" -#include "sony.h" -#include "disk.h" -#include "cdrom.h" -#include "scsi.h" -#include "video.h" -#include "audio.h" -#include "ether.h" -#include "serial.h" -#include "clip.h" -#include "extfs.h" -#include "macos_util.h" -#include "rom_patches.h" -#include "rsrc_patches.h" -#include "name_registry.h" -#include "user_strings.h" -#include "emul_op.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - - -// TVector of MakeExecutable -static uint32 MakeExecutableTvec; - - -/* - * Execute EMUL_OP opcode (called by 68k emulator) - */ - -void EmulOp(M68kRegisters *r, uint32 pc, int selector) -{ - D(bug("EmulOp %04x at %08x\n", selector, pc)); - switch (selector) { - case OP_BREAK: // Breakpoint - printf("*** Breakpoint\n"); - Dump68kRegs(r); - break; - - case OP_XPRAM1: { // Read/write from/to XPRam - uint32 len = r->d[3]; - uint8 *adr = Mac2HostAddr(r->a[3]); - D(bug("XPRAMReadWrite d3: %08lx, a3: %p\n", len, adr)); - int ofs = len & 0xffff; - len >>= 16; - if (len & 0x8000) { - len &= 0x7fff; - for (uint32 i=0; id[1] = XPRAM[(r->d[1] & 0xff) + 0x1300]; - break; - - case OP_XPRAM3: // Write to XPRam - XPRAM[(r->d[1] & 0xff) + 0x1300] = r->d[2]; - break; - - case OP_NVRAM1: { // Read from NVRAM - int ofs = r->d[0]; - r->d[0] = XPRAM[ofs & 0x1fff]; - bool localtalk = !(XPRAM[0x13e0] || XPRAM[0x13e1]); // LocalTalk enabled? - switch (ofs) { - case 0x13e0: // Disable LocalTalk (use EtherTalk instead) - if (localtalk) - r->d[0] = 0x00; - break; - case 0x13e1: - if (localtalk) - r->d[0] = 0x01; - break; - case 0x13e2: - if (localtalk) - r->d[0] = 0x00; - break; - case 0x13e3: - if (localtalk) - r->d[0] = 0x0a; - break; - } - break; - } - - case OP_NVRAM2: // Write to NVRAM - XPRAM[r->d[0] & 0x1fff] = r->d[1]; - break; - - case OP_NVRAM3: // Read/write from/to NVRAM - if (r->d[3]) { - r->d[0] = XPRAM[(r->d[4] + 0x1300) & 0x1fff]; - } else { - XPRAM[(r->d[4] + 0x1300) & 0x1fff] = r->d[5]; - r->d[0] = 0; - } - break; - - case OP_FIX_MEMTOP: // Fixes MemTop in BootGlobs during startup - D(bug("Fix MemTop\n")); - WriteMacInt32(BootGlobsAddr - 20, RAMBase + RAMSize); // MemTop - r->a[6] = RAMBase + RAMSize; - break; - - case OP_FIX_MEMSIZE: { // Fixes physical/logical RAM size during startup - D(bug("Fix MemSize\n")); - uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4); - WriteMacInt32(0x1ef8, RAMSize); // Physical RAM size - WriteMacInt32(0x1ef4, RAMSize - diff); // Logical RAM size - break; - } - - case OP_FIX_BOOTSTACK: // Fixes boot stack pointer in boot 3 resource - D(bug("Fix BootStack\n")); - r->a[1] = r->a[7] = RAMBase + RAMSize * 3 / 4; - break; - - case OP_SONY_OPEN: // Floppy driver functions - r->d[0] = SonyOpen(r->a[0], r->a[1]); - break; - case OP_SONY_PRIME: - r->d[0] = SonyPrime(r->a[0], r->a[1]); - break; - case OP_SONY_CONTROL: - r->d[0] = SonyControl(r->a[0], r->a[1]); - break; - case OP_SONY_STATUS: - r->d[0] = SonyStatus(r->a[0], r->a[1]); - break; - - case OP_DISK_OPEN: // Disk driver functions - r->d[0] = DiskOpen(r->a[0], r->a[1]); - break; - case OP_DISK_PRIME: - r->d[0] = DiskPrime(r->a[0], r->a[1]); - break; - case OP_DISK_CONTROL: - r->d[0] = DiskControl(r->a[0], r->a[1]); - break; - case OP_DISK_STATUS: - r->d[0] = DiskStatus(r->a[0], r->a[1]); - break; - - case OP_CDROM_OPEN: // CD-ROM driver functions - r->d[0] = CDROMOpen(r->a[0], r->a[1]); - break; - case OP_CDROM_PRIME: - r->d[0] = CDROMPrime(r->a[0], r->a[1]); - break; - case OP_CDROM_CONTROL: - r->d[0] = CDROMControl(r->a[0], r->a[1]); - break; - case OP_CDROM_STATUS: - r->d[0] = CDROMStatus(r->a[0], r->a[1]); - break; - - case OP_AUDIO_DISPATCH: // Audio component functions - r->d[0] = AudioDispatch(r->a[3], r->a[4]); - break; - - case OP_SOUNDIN_OPEN: // Sound input driver functions - r->d[0] = SoundInOpen(r->a[0], r->a[1]); - break; - case OP_SOUNDIN_PRIME: - r->d[0] = SoundInPrime(r->a[0], r->a[1]); - break; - case OP_SOUNDIN_CONTROL: - r->d[0] = SoundInControl(r->a[0], r->a[1]); - break; - case OP_SOUNDIN_STATUS: - r->d[0] = SoundInStatus(r->a[0], r->a[1]); - break; - case OP_SOUNDIN_CLOSE: - r->d[0] = SoundInClose(r->a[0], r->a[1]); - break; - - case OP_ADBOP: // ADBOp() replacement - ADBOp(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0]))); - break; - - case OP_INSTIME: // InsTime() replacement - r->d[0] = InsTime(r->a[0], r->d[1]); - break; - case OP_RMVTIME: // RmvTime() replacement - r->d[0] = RmvTime(r->a[0]); - break; - case OP_PRIMETIME: // PrimeTime() replacement - r->d[0] = PrimeTime(r->a[0], r->d[0]); - break; - - case OP_MICROSECONDS: // Microseconds() replacement - Microseconds(r->a[0], r->d[0]); - break; - - case OP_ZERO_SCRAP: // ZeroScrap() patch - ZeroScrap(); - break; - - case OP_PUT_SCRAP: // PutScrap() patch - PutScrap(ReadMacInt32(r->a[7] + 8), Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 12)); - break; - - case OP_GET_SCRAP: // GetScrap() patch - GetScrap((void **)Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 12)); - break; - - case OP_DEBUG_STR: // DebugStr() shows warning message - if (PrefsFindBool("nogui")) { - uint8 *pstr = Mac2HostAddr(ReadMacInt32(r->a[7] + 4)); - char str[256]; - int i; - for (i=0; i> 8, M68K_EMUL_OP_DEBUG_STR & 0xFF, - 0x4e, 0x74, // rtd #4 - 0x00, 0x04 - }; - BUILD_SHEEPSHAVER_PROCEDURE(proc); - WriteMacInt32(0x1dfc, proc); - break; - } - - case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc - r->d[0] = (uint32)-1; - PatchNameRegistry(); - InitCallUniversalProc(); - break; - - case OP_RESET: // Early in MacOS reset - D(bug("*** RESET ***\n")); - TimerReset(); - MacOSUtilReset(); - AudioReset(); - - // Enable DR emulator (disabled for now) - if (PrefsFindBool("jit68k") && 0) { - D(bug("DR activated\n")); - WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation - WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE); - WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE); - WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE); - WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE); - memcpy((void *)DR_EMULATOR_BASE, (void *)(ROMBase + 0x370000), DR_EMULATOR_SIZE); - MakeExecutable(0, DR_EMULATOR_BASE, DR_EMULATOR_SIZE); - } - break; - - case OP_IRQ: // Level 1 interrupt - WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt - r->d[0] = 0; - if (HasMacStarted()) { - if (InterruptFlags & INTFLAG_VIA) { - ClearInterruptFlag(INTFLAG_VIA); -#if !PRECISE_TIMING - TimerInterrupt(); -#endif - ExecuteNative(NATIVE_VIDEO_VBL); - - static int tick_counter = 0; - if (++tick_counter >= 60) { - tick_counter = 0; - SonyInterrupt(); - DiskInterrupt(); - CDROMInterrupt(); - } - - r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc. - } - if (InterruptFlags & INTFLAG_SERIAL) { - ClearInterruptFlag(INTFLAG_SERIAL); - SerialInterrupt(); - } - if (InterruptFlags & INTFLAG_ETHER) { - ClearInterruptFlag(INTFLAG_ETHER); - ExecuteNative(NATIVE_ETHER_IRQ); - } - if (InterruptFlags & INTFLAG_TIMER) { - ClearInterruptFlag(INTFLAG_TIMER); - TimerInterrupt(); - } - if (InterruptFlags & INTFLAG_AUDIO) { - ClearInterruptFlag(INTFLAG_AUDIO); - AudioInterrupt(); - } - if (InterruptFlags & INTFLAG_ADB) { - ClearInterruptFlag(INTFLAG_ADB); - ADBInterrupt(); - } - } else - r->d[0] = 1; - break; - - case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement - uint32 ret = ReadMacInt32(r->a[7]); - uint16 sel = ReadMacInt16(r->a[7] + 4); - r->a[7] += 6; -// D(bug("SCSIDispatch(%d)\n", sel)); - int stack; - switch (sel) { - case 0: // SCSIReset - WriteMacInt16(r->a[7], SCSIReset()); - stack = 0; - break; - case 1: // SCSIGet - WriteMacInt16(r->a[7], SCSIGet()); - stack = 0; - break; - case 2: // SCSISelect - case 11: // SCSISelAtn - WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1))); - stack = 2; - break; - case 3: // SCSICmd - WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2)))); - stack = 6; - break; - case 4: // SCSIComplete - WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8))); - stack = 12; - break; - case 5: // SCSIRead - case 8: // SCSIRBlind - WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7]))); - stack = 4; - break; - case 6: // SCSIWrite - case 9: // SCSIWBlind - WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7]))); - stack = 4; - break; - case 10: // SCSIStat - WriteMacInt16(r->a[7], SCSIStat()); - stack = 0; - break; - case 12: // SCSIMsgIn - WriteMacInt16(r->a[7] + 4, 0); - stack = 4; - break; - case 13: // SCSIMsgOut - WriteMacInt16(r->a[7] + 2, 0); - stack = 2; - break; - case 14: // SCSIMgrBusy - WriteMacInt16(r->a[7], SCSIMgrBusy()); - stack = 0; - break; - default: - printf("FATAL: SCSIDispatch: illegal selector\n"); - stack = 0; - //!! SysError(12) - } - r->a[0] = ret; - r->a[7] += stack; - break; - } - - case OP_SCSI_ATOMIC: // SCSIAtomic() replacement - D(bug("SCSIAtomic\n")); - r->d[0] = (uint32)-7887; - break; - - case OP_CHECK_SYSV: { // Check we are not using MacOS < 8.1 with a NewWorld ROM - r->a[1] = r->d[1]; - r->a[0] = ReadMacInt32(r->d[1]); - uint32 sysv = ReadMacInt16(r->a[0]); - D(bug("Detected MacOS version %d.%d.%d\n", (sysv >> 8) & 0xf, (sysv >> 4) & 0xf, sysv & 0xf)); - if (ROMType == ROMTYPE_NEWWORLD && sysv < 0x0801) - r->d[1] = 0; - break; - } - - case OP_NTRB_17_PATCH: - r->a[2] = ReadMacInt32(r->a[7]); - r->a[7] += 4; - if (ReadMacInt16(r->a[2] + 6) == 17) - PatchNativeResourceManager(); - break; - - case OP_NTRB_17_PATCH2: - r->a[7] += 8; - PatchNativeResourceManager(); - break; - - case OP_NTRB_17_PATCH3: - r->a[2] = ReadMacInt32(r->a[7]); - r->a[7] += 4; - D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6))); - if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17) - PatchNativeResourceManager(); - break; - - case OP_NTRB_17_PATCH4: - r->d[0] = ReadMacInt16(r->a[7]); - r->a[7] += 2; - D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6))); - if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17) - PatchNativeResourceManager(); - break; - - case OP_CHECKLOAD: { // vCheckLoad() patch - uint32 type = ReadMacInt32(r->a[7]); - r->a[7] += 4; - int16 id = ReadMacInt16(r->a[2]); - if (r->a[0] == 0) - break; - uint32 adr = ReadMacInt32(r->a[0]); - if (adr == 0) - break; - uint16 *p = (uint16 *)Mac2HostAddr(adr); - uint32 size = ReadMacInt32(adr - 8) & 0xffffff; - CheckLoad(type, id, p, size); - break; - } - - case OP_EXTFS_COMM: // External file system routines - WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4))); - break; - - case OP_EXTFS_HFS: - WriteMacInt16(r->a[7] + 20, ExtFSHFS(ReadMacInt32(r->a[7] + 16), ReadMacInt16(r->a[7] + 14), ReadMacInt32(r->a[7] + 10), ReadMacInt32(r->a[7] + 6), ReadMacInt16(r->a[7] + 4))); - break; - - case OP_IDLE_TIME: - // Sleep if no events pending - if (ReadMacInt32(0x14c) == 0) - idle_wait(); - r->a[0] = ReadMacInt32(0x2b6); - break; - - case OP_IDLE_TIME_2: - // Sleep if no events pending - if (ReadMacInt32(0x14c) == 0) - idle_wait(); - r->d[0] = (uint32)-2; - break; - - default: - printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector); - QuitEmulator(); - break; - } -} diff --git a/SheepShaver/src/emul_ppc/emul_ppc.cpp b/SheepShaver/src/emul_ppc/emul_ppc.cpp deleted file mode 100644 index 10584d72..00000000 --- a/SheepShaver/src/emul_ppc/emul_ppc.cpp +++ /dev/null @@ -1,1661 +0,0 @@ -/* - * emul_ppc.cpp - PowerPC processor emulation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* -TODO: -addme -addmeo -addze -addzeo -dcbst -dcbt -dcbtst -divwuo -fabs -fadd -fadds -fcmpo -fcmpu -fctiw -fctiwz -fdiv -fdivs -fmadd -fmadds -fmr -fmsub -fmsubs -fmul -fmuls -fnabs -fneg -fnmadd -fnmadds -fnmsub -fnmsubs -fres -frsp -frsqrte -fsel -fsqrt -fsqrts -fsub -fsubs -lfdu -lfdux -lfdx -lfs -lfsu -lfsux -lfsx -lhbrx -lwbrx -mcrfs -mcrxr -mtfsb0 -mtfsb1 -mtfsfi -mulhwu -mullwo -nego -sc -stfdu -stfdux -stfdx -stfs -stfsu -stfsux -stfsx -sthbrx -stwbrx -subfo -subfme -subfmeo -subfze -subfzeo -tw -twi - -CHECK: -crxor -creqv - */ - -#include -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "xlowmem.h" -#include "emul_op.h" - -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif - -#define DEBUG 1 -#include "debug.h" - -#define FLIGHT_RECORDER 1 - - -// PowerPC user mode registers -uint32 r[32]; -double fr[32]; -uint32 lr, ctr; -uint32 cr, xer; -uint32 fpscr; -uint32 pc; - -// Convert 8-bit field mask (e.g. mtcrf) to bit mask -static uint32 field2mask[256]; - - -/* - * Flight recorder - */ - -#if FLIGHT_RECORDER -struct rec_step { - uint32 r[32]; - double fr[32]; - uint32 lr, ctr; - uint32 cr, xer; - uint32 fpscr; - uint32 pc; - uint32 opcode; -}; - -const int LOG_SIZE = 8192; -static rec_step log[LOG_SIZE]; -static int log_ptr = 0; - -static void record_step(uint32 opcode) -{ - for (int i=0; i<32; i++) { - log[log_ptr].r[i] = r[i]; - log[log_ptr].fr[i] = fr[i]; - } - log[log_ptr].lr = lr; - log[log_ptr].ctr = ctr; - log[log_ptr].cr = cr; - log[log_ptr].xer = xer; - log[log_ptr].fpscr = fpscr; - log[log_ptr].pc = pc; - log[log_ptr].opcode = opcode; - log_ptr++; - if (log_ptr == LOG_SIZE) - log_ptr = 0; -} - -static void dump_log(void) -{ - FILE *f = fopen("log", "w"); - if (f == NULL) - return; - for (int i=0; i> 4) & 0x0f000000); -} - - -/* - * Convert mask begin/end to mask - */ - -static uint32 mbme2mask(uint32 op) -{ - uint32 mb = (op >> 6) & 0x1f; - uint32 me = (op >> 1) & 0x1f; - uint32 m = 0; - uint32 i; - - if (mb <= me) - for (i=mb; i<=me; i++) - m |= 0x80000000 >> i; - else { - for (i=0; i<=me; i++) - m |= 0x80000000 >> i; - for (i=mb; i<=31; i++) - m |= 0x80000000 >> i; - } - return m; -} - - -/* - * Emulate instruction with primary opcode = 19 - */ - -static void emul19(uint32 op) -{ - uint32 exop = (op >> 1) & 0x3ff; - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - switch (exop) { - - case 0: { // mcrf - uint32 crfd = 0x1c - (rd & 0x1c); - uint32 crfa = 0x1c - (ra & 0x1c); - uint32 crf = (cr >> crfa) & 0xf; - cr = (cr & ~(0xf << crfd)) | (crf << crfd); - break; - } - - case 16: { // bclr - uint32 oldpc = pc; - if (!(rd & 4)) { - ctr--; - if (rd & 2) { - if (ctr) - goto blr_nobranch; - } else { - if (!ctr) - goto blr_nobranch; - } - } - if (!(rd & 0x10)) { - if (rd & 8) { - if (!(cr & (0x80000000 >> ra))) - goto blr_nobranch; - } else { - if (cr & (0x80000000 >> ra)) - goto blr_nobranch; - } - } - pc = lr & 0xfffffffc; -blr_nobranch: - if (op & 1) - lr = oldpc; - break; - } - - case 33: // crnor - if ((cr & (0x80000000 >> ra)) || ((cr & (0x80000000 >> ((op >> 11) & 0x1f))))) - cr &= ~(0x80000000 >> rd); - else - cr |= 0x80000000 >> rd; - break; - - case 129: // crandc - if ((cr & (0x80000000 >> ra)) && !((cr & (0x80000000 >> ((op >> 11) & 0x1f))))) - cr |= 0x80000000 >> rd; - else - cr &= ~(0x80000000 >> rd); - break; - - case 150: // isync - break; - - case 193: { // crxor - uint32 mask = 0x80000000 >> rd; - cr = (((((cr >> (31 - ra)) ^ (cr >> (31 - ((op >> 11) & 0x1f)))) & 1) << (31 - rd)) & mask) | (cr & ~mask); - break; - } - - case 225: // crnand - if ((cr & (0x80000000 >> ra)) && ((cr & (0x80000000 >> ((op >> 11) & 0x1f))))) - cr &= ~(0x80000000 >> rd); - else - cr |= 0x80000000 >> rd; - break; - - case 257: // crand - if ((cr & (0x80000000 >> ra)) && ((cr & (0x80000000 >> ((op >> 11) & 0x1f))))) - cr |= 0x80000000 >> rd; - else - cr &= ~(0x80000000 >> rd); - break; - - case 289: { // creqv - uint32 mask = 0x80000000 >> rd; - cr = (((~((cr >> (31 - ra)) ^ (cr >> (31 - ((op >> 11) & 0x1f)))) & 1) << (31 - rd)) & mask) | (cr & ~mask); - break; - } - - case 417: // crorc - if ((cr & (0x80000000 >> ra)) || !((cr & (0x80000000 >> ((op >> 11) & 0x1f))))) - cr |= 0x80000000 >> rd; - else - cr &= ~(0x80000000 >> rd); - break; - - case 449: // cror - if ((cr & (0x80000000 >> ra)) || ((cr & (0x80000000 >> ((op >> 11) & 0x1f))))) - cr |= 0x80000000 >> rd; - else - cr &= ~(0x80000000 >> rd); - break; - - case 528: { // bcctr - if (op & 1) - lr = pc; - if (!(rd & 4)) { - ctr--; - if (rd & 2) { - if (ctr) - goto bctr_nobranch; - } else { - if (!ctr) - goto bctr_nobranch; - } - } - if (!(rd & 0x10)) { - if (rd & 8) { - if (!(cr & (0x80000000 >> ra))) - goto bctr_nobranch; - } else { - if (cr & (0x80000000 >> ra)) - goto bctr_nobranch; - } - } - pc = ctr & 0xfffffffc; -bctr_nobranch: - break; - } - - default: - printf("Illegal 19 opcode %08x (exop %d) at %08x\n", op, exop, pc-4); - dump(); - break; - } -} - - -/* - * Emulate instruction with primary opcode = 31 - */ - -static void emul31(uint32 op) -{ - uint32 exop = (op >> 1) & 0x3ff; - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 rb = (op >> 11) & 0x1f; - switch (exop) { - - case 0: { // cmpw - uint32 crfd = 0x1c - (rd & 0x1c); - uint8 crf = 0; - if (r[ra] == r[rb]) - crf |= 2; - else if ((int32)r[ra] < (int32)r[rb]) - crf |= 8; - else - crf |= 4; - if (xer & 0x80000000) - crf |= 1; - cr = (cr & ~(0xf << crfd)) | (crf << crfd); - break; - } - - case 8: { // subfc - uint64 tmp = (uint64)r[rb] - (uint64)r[ra]; - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer &= ~0x20000000; - else - xer |= 0x20000000; - if (op & 1) - record(r[rd]); - break; - } - - case 10: { // addc - uint64 tmp = (uint64)r[ra] + (uint64)r[rb]; - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer |= 0x20000000; - else - xer &= ~0x20000000; - if (op & 1) - record(r[rd]); - break; - } - - case 19: // mfcr - r[rd] = cr; - break; - - case 20: // lwarx - r[rd] = ReadMacInt32(r[rb] + (ra ? r[ra] : 0)); - //!! set reservation bit - break; - - case 23: // lwzx - r[rd] = ReadMacInt32(r[rb] + (ra ? r[ra] : 0)); - break; - - case 24: // slw - r[ra] = r[rd] << (r[rb] & 0x3f); - if (op & 1) - record(r[ra]); - break; - - case 26: { // cntlzw - uint32 mask = 0x80000000; - for (int i=0; i<32; i++, mask>>=1) { - if (r[rd] & mask) { - r[ra] = i; - goto cntlzw_done; - } - } - r[ra] = 32; -cntlzw_done:if (op & 1) - record(r[ra]); - break; - } - - case 28: // and - r[ra] = r[rd] & r[rb]; - if (op & 1) - record(r[ra]); - break; - - case 32: { // cmplw - uint32 crfd = 0x1c - (rd & 0x1c); - uint8 crf = 0; - if (r[ra] == r[rb]) - crf |= 2; - else if (r[ra] < r[rb]) - crf |= 8; - else - crf |= 4; - if (xer & 0x80000000) - crf |= 1; - cr = (cr & ~(0xf << crfd)) | (crf << crfd); - break; - } - - case 40: // subf - r[rd] = r[rb] - r[ra]; - if (op & 1) - record(r[rd]); - break; - - case 55: // lwzux - r[ra] += r[rb]; - r[rd] = ReadMacInt32(r[ra]); - break; - - case 60: // andc - r[ra] = r[rd] & ~r[rb]; - if (op & 1) - record(r[ra]); - break; - - case 75: // mulhw - r[rd] = ((int64)(int32)r[ra] * (int32)r[rb]) >> 32; - if (op & 1) - record(r[rd]); - break; - - case 86: // dcbf - break; - - case 87: // lbzx - r[rd] = ReadMacInt8(r[rb] + (ra ? r[ra] : 0)); - break; - - case 104: // neg - if (r[ra] == 0x80000000) - r[rd] = 0x80000000; - else - r[rd] = -(int32)r[ra]; - if (op & 1) - record(r[rd]); - break; - - case 119: // lbzux - r[ra] += r[rb]; - r[rd] = ReadMacInt8(r[ra]); - break; - - case 124: // nor - r[ra] = ~(r[rd] | r[rb]); - if (op & 1) - record(r[ra]); - break; - - case 136: { // subfe - uint64 tmp = (uint64)r[rb] - (uint64)r[ra]; - if (!(xer & 0x20000000)) - tmp--; - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer &= ~0x20000000; - else - xer |= 0x20000000; - if (op & 1) - record(r[rd]); - break; - } - - case 138: { // adde - uint64 tmp = (uint64)r[ra] + (uint64)r[rb]; - if (xer & 0x20000000) - tmp++; - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer |= 0x20000000; - else - xer &= ~0x20000000; - if (op & 1) - record(r[rd]); - break; - } - - case 144: { // mtcrf - uint32 mask = field2mask[(op >> 12) & 0xff]; - cr = (r[rd] & mask) | (cr & ~mask); - break; - } - - case 150: // stwcx - //!! check reserved bit - WriteMacInt32(r[rb] + (ra ? r[ra] : 0), r[rd]); - record(0); - break; - - case 151: // stwx - WriteMacInt32(r[rb] + (ra ? r[ra] : 0), r[rd]); - break; - - case 183: // stwux - r[ra] += r[rb]; - WriteMacInt32(r[ra], r[rd]); - break; - - case 215: // stbx - WriteMacInt8(r[rb] + (ra ? r[ra] : 0), r[rd]); - break; - - case 235: // mullw - r[rd] = (int32)r[ra] * (int32)r[rb]; - if (op & 1) - record(r[rd]); - break; - - case 247: // stbux - r[ra] += r[rb]; - WriteMacInt8(r[ra], r[rd]); - break; - - case 266: // add - r[rd] = r[ra] + r[rb]; - if (op & 1) - record(r[rd]); - break; - - case 279: // lhzx - r[rd] = ReadMacInt16(r[rb] + (ra ? r[ra] : 0)); - break; - - case 284: // eqv - r[ra] = ~(r[rd] ^ r[rb]); - if (op & 1) - record(r[ra]); - break; - - case 311: // lhzux - r[ra] += r[rb]; - r[rd] = ReadMacInt16(r[ra]); - break; - - case 316: // xor - r[ra] = r[rd] ^ r[rb]; - if (op & 1) - record(r[ra]); - break; - - case 339: { // mfspr - uint32 spr = ra | (rb << 5); - switch (spr) { - case 1: r[rd] = xer; break; - case 8: r[rd] = lr; break; - case 9: r[rd] = ctr; break; - default: - printf("Illegal mfspr opcode %08x at %08x\n", op, pc-4); - dump(); - } - break; - } - - case 343: // lhax - r[rd] = (int32)(int16)ReadMacInt16(r[rb] + (ra ? r[ra] : 0)); - break; - - case 371: // mftb - r[rd] = 0; //!! - break; - - case 375: // lhaux - r[ra] += r[rb]; - r[rd] = (int32)(int16)ReadMacInt16(r[ra]); - break; - - case 407: // sthx - WriteMacInt16(r[rb] + (ra ? r[ra] : 0), r[rd]); - break; - - case 412: // orc - r[ra] = r[rd] | ~r[rb]; - if (op & 1) - record(r[ra]); - break; - - case 439: // sthux - r[ra] += r[rb]; - WriteMacInt16(r[ra], r[rd]); - break; - - case 444: // or - r[ra] = r[rd] | r[rb]; - if (op & 1) - record(r[ra]); - break; - - case 459: // divwu - if (r[rb]) - r[rd] = r[ra] / r[rb]; - if (op & 1) - record(r[rd]); - break; - - case 467: { // mtspr - uint32 spr = ra | (rb << 5); - switch (spr) { - case 1: xer = r[rd] & 0xe000007f; break; - case 8: lr = r[rd]; break; - case 9: ctr = r[rd]; break; - default: - printf("Illegal mtspr opcode %08x at %08x\n", op, pc-4); - dump(); - } - break; - } - - case 476: // nand - r[ra] = ~(r[rd] & r[rb]); - if (op & 1) - record(r[ra]); - break; - - case 491: // divw - if (r[rb]) - r[rd] = (int32)r[ra] / (int32)r[rb]; - if (op & 1) - record(r[rd]); - break; - - case 520: { // subfco - uint64 tmp = (uint64)r[rb] - (uint64)r[ra]; - uint32 ov = (r[ra] ^ r[rb]) & ((uint32)tmp ^ r[rb]); - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer &= ~0x20000000; - else - xer |= 0x20000000; - if (ov & 0x80000000) - xer |= 0xc0000000; - else - xer &= ~0x40000000; - if (op & 1) - record(r[rd]); - break; - } - - case 522: { // addco - uint64 tmp = (uint64)r[ra] + (uint64)r[rb]; - uint32 ov = (r[ra] ^ (uint32)tmp) & (r[rb] ^ (uint32)tmp); - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer |= 0x20000000; - else - xer &= ~0x20000000; - if (ov & 0x80000000) - xer |= 0xc0000000; - else - xer &= ~0x40000000; - if (op & 1) - record(r[rd]); - break; - } - - case 533: { // lswx - uint32 addr = r[rb] + (ra ? r[ra] : 0); - int nb = xer & 0x7f; - int reg = rd; - for (int i=0; i> (r[rb] & 0x3f); - if (op & 1) - record(r[ra]); - break; - - case 597: { // lswi - uint32 addr = ra ? r[ra] : 0; - int nb = rb ? rb : 32; - int reg = rd; - for (int i=0; i> shift)); - shift -= 8; - if ((i & 3) == 3) { - shift = 24; - reg = (reg + 1) & 0x1f; - } - } - break; - } - - case 725: { // stswi - uint32 addr = ra ? r[ra] : 0; - int nb = rb ? rb : 32; - int reg = rd; - int shift = 24; - for (int i=0; i> shift)); - shift -= 8; - if ((i & 3) == 3) { - shift = 24; - reg = (reg + 1) & 0x1f; - } - } - break; - } - - case 778: { // addo - uint32 tmp = r[ra] + r[rb]; - uint32 ov = (r[ra] ^ tmp) & (r[rb] ^ tmp); - r[rd] = tmp; - if (ov & 0x80000000) - xer |= 0xc0000000; - else - xer &= ~0x40000000; - if (op & 1) - record(r[rd]); - break; - } - - case 792: { // sraw - uint32 sh = r[rb] & 0x3f; - uint32 mask = ~(0xffffffff << sh); - if ((r[rd] & 0x80000000) && (r[rd] & mask)) - xer |= 0x20000000; - else - xer &= ~0x20000000; - r[ra] = (int32)r[rd] >> sh; - if (op & 1) - record(r[ra]); - break; - } - - case 824: { // srawi - uint32 mask = ~(0xffffffff << rb); - if ((r[rd] & 0x80000000) && (r[rd] & mask)) - xer |= 0x20000000; - else - xer &= ~0x20000000; - r[ra] = (int32)r[rd] >> rb; - if (op & 1) - record(r[ra]); - break; - } - - case 854: // eieio - break; - - case 922: // extsh - r[ra] = (int32)(int16)r[rd]; - if (op & 1) - record(r[ra]); - break; - - case 954: // extsb - r[ra] = (int32)(int8)r[rd]; - if (op & 1) - record(r[ra]); - break; - - case 982: // icbi - break; - - case 1003: // divwo - if (r[rb] == 0 || (r[ra] == 0x80000000 && r[rb] == 0xffffffff)) - xer |= 0xc0000000; - else { - r[rd] = (int32)r[ra] / (int32)r[rb]; - xer &= ~0x40000000; - } - if (op & 1) - record(r[rd]); - break; - -#if 0 - case 1014: // dcbz - memset(r[rb] + (ra ? r[ra] : 0), 0, 32); - break; -#endif - - default: - printf("Illegal 31 opcode %08x (exop %d) at %08x\n", op, exop, pc-4); - dump(); - break; - } -} - - -/* - * Emulate instruction with primary opcode = 59 - */ - -static void emul59(uint32 op) -{ - uint32 exop = (op >> 1) & 0x3ff; - switch (exop) { - default: - printf("Illegal 59 opcode %08x (exop %d) at %08x\n", op, exop, pc-4); - dump(); - break; - } -} - - -/* - * Emulate instruction with primary opcode = 63 - */ - -static void emul63(uint32 op) -{ - uint32 exop = (op >> 1) & 0x3ff; - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 rb = (op >> 11) & 0x1f; - switch (exop) { - - case 583: // mffs - fr[rd] = (double)(uint64)fpscr; - if (op & 1) - record1(); - break; - - case 711: // mtfsf - //!! - if (op & 1) - record1(); - break; - - default: - printf("Illegal 63 opcode %08x (exop %d) at %08x\n", op, exop, pc-4); - dump(); - break; - } -} - - -/* - * Emulation loop - */ - -void emul_ppc(uint32 start) -{ - pc = start; -//uint32 old_val = 0; - for (;;) { -//uint32 val = ReadMacInt32(0x68fff778); -//if (val != old_val) { -// printf("insn at %08lx changed %08lx->%08lx\n", pc-4, old_val, val); -// old_val = val; -//} - uint32 op = ReadMacInt32(pc); -#if FLIGHT_RECORDER - record_step(op); -#endif -// printf("%08lx at %08lx\n", op, pc); - uint32 primop = op >> 26; - pc += 4; - switch (primop) { - - case 6: // SheepShaver extensions - printf("Extended opcode %08x at %08x (68k pc %08x)\n", op, pc-4, r[24]); - switch (op & 0x3f) { - case 0: // EMUL_RETURN - QuitEmulator(); - break; - - case 1: // EXEC_RETURN - //!! - dump(); - break; - - default: { // EMUL_OP - M68kRegisters r68; - WriteMacInt32(XLM_68K_R25, r[25]); - WriteMacInt32(XLM_RUN_MODE, MODE_EMUL_OP); - for (int i=0; i<8; i++) - r68.d[i] = r[8 + i]; - for (int i=0; i<7; i++) - r68.a[i] = r[16 + i]; - r68.a[7] = r[1]; - EmulOp(&r68, r[24], (op & 0x3f) - 2); - for (int i=0; i<8; i++) - r[8 + i] = r68.d[i]; - for (int i=0; i<7; i++) - r[16 + i] = r68.a[i]; - r[1] = r68.a[7]; - WriteMacInt32(XLM_RUN_MODE, MODE_68K); - break; - } - } - break; - - case 7: { // mulli - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = (int32)r[ra] * (int32)(int16)(op & 0xffff); - break; - } - - case 8: { // subfic - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint64 tmp = (uint32)(int32)(int16)(op & 0xffff) - (uint64)r[ra]; - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer &= ~0x20000000; - else - xer |= 0x20000000; - break; - } - - case 10: { // cmpli - uint32 crfd = 0x1c - ((op >> 21) & 0x1c); - uint32 ra = (op >> 16) & 0x1f; - uint32 val = (op & 0xffff); - uint8 crf = 0; - if (r[ra] == val) - crf |= 2; - else if (r[ra] < val) - crf |= 8; - else - crf |= 4; - if (xer & 0x80000000) - crf |= 1; - cr = (cr & ~(0xf << crfd)) | (crf << crfd); - break; - } - - case 11: { // cmpi - uint32 crfd = 0x1c - ((op >> 21) & 0x1c); - uint32 ra = (op >> 16) & 0x1f; - int32 val = (int32)(int16)(op & 0xffff); - uint8 crf = 0; - if ((int32)r[ra] == val) - crf |= 2; - else if ((int32)r[ra] < val) - crf |= 8; - else - crf |= 4; - if (xer & 0x80000000) - crf |= 1; - cr = (cr & ~(0xf << crfd)) | (crf << crfd); - break; - } - - case 12: { // addic - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint64 tmp = (uint64)r[ra] + (uint32)(int32)(int16)(op & 0xffff); - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer |= 0x20000000; - else - xer &= ~0x20000000; - break; - } - - case 13: { // addic. - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint64 tmp = (uint64)r[ra] + (uint32)(int32)(int16)(op & 0xffff); - r[rd] = tmp; - if (tmp & 0x100000000LL) - xer |= 0x20000000; - else - xer &= ~0x20000000; - record(r[rd]); - break; - } - - case 14: { // addi - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = (ra ? r[ra] : 0) + (int32)(int16)(op & 0xffff); - break; - } - - case 15: { // addis - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = (ra ? r[ra] : 0) + (op << 16); - break; - } - - case 16: { // bc - uint32 bo = (op >> 21) & 0x1f; - uint32 bi = (op >> 16) & 0x1f; - if (op & 1) - lr = pc; - if (!(bo & 4)) { - ctr--; - if (bo & 2) { - if (ctr) - goto bc_nobranch; - } else { - if (!ctr) - goto bc_nobranch; - } - } - if (!(bo & 0x10)) { - if (bo & 8) { - if (!(cr & (0x80000000 >> bi))) - goto bc_nobranch; - } else { - if (cr & (0x80000000 >> bi)) - goto bc_nobranch; - } - } - if (op & 2) - pc = (int32)(int16)(op & 0xfffc); - else - pc += (int32)(int16)(op & 0xfffc) - 4; -bc_nobranch: - break; - } - - case 18: { // b - int32 target = op & 0x03fffffc; - if (target & 0x02000000) - target |= 0xfc000000; - if (op & 1) - lr = pc; - if (op & 2) - pc = target; - else - pc += target - 4; - break; - } - - case 19: - emul19(op); - break; - - case 20: { // rlwimi - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 sh = (op >> 11) & 0x1f; - uint32 mask = mbme2mask(op); - r[ra] = (((r[rs] << sh) | (r[rs] >> (32-sh))) & mask) | (r[ra] & ~mask); - if (op & 1) - record(r[ra]); - break; - } - - case 21: { // rlwinm - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 sh = (op >> 11) & 0x1f; - r[ra] = ((r[rs] << sh) | (r[rs] >> (32-sh))) & mbme2mask(op); - if (op & 1) - record(r[ra]); - break; - } - - case 23: { // rlwnm - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 sh = r[(op >> 11) & 0x1f] & 0x1f; - r[ra] = ((r[rs] << sh) | (r[rs] >> (32-sh))) & mbme2mask(op); - if (op & 1) - record(r[ra]); - break; - } - - case 24: { // ori - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] = r[rs] | (op & 0xffff); - break; - } - - case 25: { // oris - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] = r[rs] | (op << 16); - break; - } - - case 26: { // xori - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] = r[rs] ^ (op & 0xffff); - break; - } - - case 27: { // xoris - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] = r[rs] ^ (op << 16); - break; - } - - case 28: { // andi. - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] = r[rs] & (op & 0xffff); - record(r[ra]); - break; - } - - case 29: { // andis. - uint32 rs = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] = r[rs] & (op << 16); - record(r[ra]); - break; - } - - case 31: - emul31(op); - break; - - case 32: { // lwz - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = ReadMacInt32(int16(op & 0xffff) + (ra ? r[ra] : 0)); - break; - } - - case 33: { // lwzu - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - r[rd] = ReadMacInt32(r[ra]); - break; - } - - case 34: { // lbz - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = ReadMacInt8(int16(op & 0xffff) + (ra ? r[ra] : 0)); - break; - } - - case 35: { // lbzu - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - r[rd] = ReadMacInt8(r[ra]); - break; - } - - case 36: { // stw - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - WriteMacInt32(int16(op & 0xffff) + (ra ? r[ra] : 0), r[rd]); - break; - } - - case 37: { // stwu - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - WriteMacInt32(r[ra], r[rd]); - break; - } - - case 38: { // stb - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - WriteMacInt8(int16(op & 0xffff) + (ra ? r[ra] : 0), r[rd]); - break; - } - - case 39: { // stbu - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - WriteMacInt8(r[ra], r[rd]); - break; - } - - case 40: { // lhz - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = ReadMacInt16(int16(op & 0xffff) + (ra ? r[ra] : 0)); - break; - } - - case 41: { // lhzu - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - r[rd] = ReadMacInt16(r[ra]); - break; - } - - case 42: { // lha - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[rd] = (int32)(int16)ReadMacInt16(int16(op & 0xffff) + (ra ? r[ra] : 0)); - break; - } - - case 43: { // lhau - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - r[rd] = (int32)(int16)ReadMacInt16(r[ra]); - break; - } - - case 44: { // sth - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - WriteMacInt16(int16(op & 0xffff) + (ra ? r[ra] : 0), r[rd]); - break; - } - - case 45: { // sthu - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - r[ra] += int16(op & 0xffff); - WriteMacInt16(r[ra], r[rd]); - break; - } - - case 46: { // lmw - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 addr = int16(op & 0xffff) + (ra ? r[ra] : 0); - while (rd <= 31) { - r[rd] = ReadMacInt32(addr); - rd++; - addr += 4; - } - break; - } - - case 47: { // stmw - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - uint32 addr = int16(op & 0xffff) + (ra ? r[ra] : 0); - while (rd <= 31) { - WriteMacInt32(addr, r[rd]); - rd++; - addr += 4; - } - break; - } - - case 50: { // lfd - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - fr[rd] = (double)ReadMacInt64(int16(op & 0xffff) + (ra ? r[ra] : 0)); - break; - } - - case 54: { // stfd - uint32 rd = (op >> 21) & 0x1f; - uint32 ra = (op >> 16) & 0x1f; - WriteMacInt64(int16(op & 0xffff) + (ra ? r[ra] : 0), (uint64)fr[rd]); - break; - } - - case 59: - emul59(op); - break; - - case 63: - emul63(op); - break; - - default: - printf("Illegal opcode %08x at %08x\n", op, pc-4); - dump(); - break; - } - } -} - - -static struct sigaction sigsegv_action; - -static void sigsegv_handler(int sig) -{ - printf("SIGSEGV\n"); - dump(); -} - -void init_emul_ppc(void) -{ - // Init field2mask - for (int i=0; i<256; i++) { - uint32 mask = 0; - if (i & 0x01) mask |= 0x0000000f; - if (i & 0x02) mask |= 0x000000f0; - if (i & 0x04) mask |= 0x00000f00; - if (i & 0x08) mask |= 0x0000f000; - if (i & 0x10) mask |= 0x000f0000; - if (i & 0x20) mask |= 0x00f00000; - if (i & 0x40) mask |= 0x0f000000; - if (i & 0x80) mask |= 0xf0000000; - field2mask[i] = mask; - } - - // Init registers - for (int i=0; i<32; i++) { - r[i] = 0; - fr[i] = 0.0; - } - lr = ctr = 0; - cr = xer = 0; - fpscr = 0; - - r[3] = ROMBase + 0x30d000; - - // Install SIGSEGV handler - sigemptyset(&sigsegv_action.sa_mask); - sigsegv_action.sa_handler = (__sighandler_t)sigsegv_handler; - sigsegv_action.sa_flags = 0; - sigsegv_action.sa_restorer = NULL; - sigaction(SIGSEGV, &sigsegv_action, NULL); - -#if FLIGHT_RECORDER && ENABLE_MON - // Install "log" command in mon - mon_add_command("log", dump_log, "log Dump PowerPC emulation log\n"); -#endif -} - - -/* - * Execute 68k subroutine (must be ended with EXEC_RETURN) - * This must only be called by the emul_thread when in EMUL_OP mode - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68k(uint32 pc, M68kRegisters *r) -{ - printf("ERROR: Execute68k() unimplemented\n"); - QuitEmulator(); -} - - -/* - * Execute 68k A-Trap from EMUL_OP routine - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68kTrap(uint16 trap, M68kRegisters *r) -{ - printf("ERROR: Execute68kTrap() unimplemented\n"); - QuitEmulator(); -} - - -/* - * Call MacOS PPC code - */ - -uint32 call_macos(uint32 tvect) -{ - printf("ERROR: call_macos() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos1(uint32 tvect, uint32 arg1) -{ - printf("ERROR: call_macos1() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2) -{ - printf("ERROR: call_macos2() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3) -{ - printf("ERROR: call_macos3() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4) -{ - printf("ERROR: call_macos4() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5) -{ - printf("ERROR: call_macos5() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6) -{ - printf("ERROR: call_macos6() unimplemented\n"); - QuitEmulator(); - return 0; -} - -uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7) -{ - printf("ERROR: call_macos7() unimplemented\n"); - QuitEmulator(); - return 0; -} - - -/* - * Atomic operations - */ - -extern int atomic_add(int *var, int v) -{ - int ret = *var; - *var += v; - return ret; -} - -extern int atomic_and(int *var, int v) -{ - int ret = *var; - *var &= v; - return ret; -} - -extern int atomic_or(int *var, int v) -{ - int ret = *var; - *var |= v; - return ret; -} - - -extern "C" void get_resource(void); -extern "C" void get_1_resource(void); -extern "C" void get_ind_resource(void); -extern "C" void get_1_ind_resource(void); -extern "C" void r_get_resource(void); - -void get_resource(void) -{ - printf("ERROR: get_resource() unimplemented\n"); - QuitEmulator(); -} - -void get_1_resource(void) -{ - printf("ERROR: get_1_resource() unimplemented\n"); - QuitEmulator(); -} - -void get_ind_resource(void) -{ - printf("ERROR: get_ind_resource() unimplemented\n"); - QuitEmulator(); -} - -void get_1_ind_resource(void) -{ - printf("ERROR: get_1_ind_resource() unimplemented\n"); - QuitEmulator(); -} - -void r_get_resource(void) -{ - printf("ERROR: r_get_resource() unimplemented\n"); - QuitEmulator(); -} diff --git a/SheepShaver/src/ether.cpp b/SheepShaver/src/ether.cpp deleted file mode 100644 index 2a1e53c7..00000000 --- a/SheepShaver/src/ether.cpp +++ /dev/null @@ -1,1738 +0,0 @@ -/* - * ether.cpp - SheepShaver Ethernet Device Driver (DLPI) - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * TODO - * - 802.2 TEST/XID - * - MIB statistics - */ - -#include - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "ether.h" -#include "ether_defs.h" -#include "macos_util.h" - -#define DEBUG 0 -#include "debug.h" - -// Packet types -enum { - kPktDIX = 0, - kPkt8022SAP = 1, - kPkt8022GroupSAP = 2, - kPkt8022SNAP = 3, - kPktIPX = 4, - kPktUnknown = 5 -}; - - -/* - * Stream private data structure - */ - -static const int kGroupSAPMapSize = 128/32; // Number of 32-bit values we need for 128 bits -static const int kGSshift = 6; -static const int kGSmask = 0x1F; - -struct multicast_node { - nw_multicast_node_p next; - uint8 addr[kEnetPhysicalAddressLength]; -}; - -struct DLPIStream { - void SetGroupSAP(uint8 sap) - { - group_sap[sap >> kGSshift] |= (1L << ((sap >> 1) & kGSmask)); - } - - void ClearGroupSAP(uint8 sap) - { - group_sap[sap >> kGSshift] &= ~(1L << ((sap >> 1) & kGSmask)); - } - - void ClearAllGroupSAPs(void) - { - for (int i=0; i> kGSshift] & (1L << ((sap >> 1) & kGSmask)); - } - - void AddMulticast(uint8 *addr) - { - multicast_node *n = (multicast_node *)Mac2HostAddr(Mac_sysalloc(sizeof(multicast_node))); - memcpy(n->addr, addr, kEnetPhysicalAddressLength); - n->next = multicast_list; - multicast_list = n; - } - - void RemoveMulticast(uint8 *addr) - { - multicast_node *p = multicast_list; - while (p) { - if (memcmp(addr, p->addr, kEnetPhysicalAddressLength) == 0) - goto found; - p = p->next; - } - return; - found: - multicast_node *q = (multicast_node *)&multicast_list; - while (q) { - if (q->next == p) { - q->next = p->next; - Mac_sysfree(Host2MacAddr((uint8 *)p)); - return; - } - q = q->next; - } - } - - uint8 *IsMulticastRegistered(uint8 *addr) - { - multicast_node *n = multicast_list; - while (n) { - if (memcmp(addr, n->addr, kEnetPhysicalAddressLength) == 0) - return n->addr; - n = n->next; - } - return NULL; - } - - nw_uint32 minor_num; // Minor device number of this stream - nw_uint32 dlpi_state; // DLPI state of this stream - nw_uint32 flags; // Flags - nw_uint16 dlsap; // SAP bound to this stream - nw_bool framing_8022; // Using 802.2 framing? This is only used to report the MAC type for DL_INFO_ACK and can be set with an ioctl() call - nw_bool raw_mode; // Using raw mode? Header is treated as data - nw_queue_p rdq; // Read queue for this stream - nw_uint32 group_sap[kGroupSAPMapSize]; // Map of bound group SAPs - uint8 snap[k8022SNAPLength]; // SNAP bound to this stream - nw_multicast_node_p multicast_list; // List of enabled multicast addresses -}; - -// Hack to make DLPIStream list initialization early to NULL (do we really need this?) -struct DLPIStreamInit { - DLPIStreamInit(nw_DLPIStream_p *dlpi_stream_p) { *dlpi_stream_p = NULL; } -}; - -// Stream flags -enum { - kSnapStream = 0x00000001, - kAcceptMulticasts = 0x00000002, - kAcceptAll8022Packets = 0x00000004, - kFastPathMode = 0x00000008 -}; - -// List of opened streams (used internally by OpenTransport) -static nw_DLPIStream_p dlpi_stream_list; -static DLPIStreamInit dlpi_stream_init(&dlpi_stream_list); - -// Are we open? -bool ether_driver_opened = false; - -// Our ethernet hardware address -static uint8 hardware_address[6] = {0, 0, 0, 0, 0, 0}; - -// Statistics -int32 num_wput = 0; -int32 num_error_acks = 0; -int32 num_tx_packets = 0; -int32 num_tx_raw_packets = 0; -int32 num_tx_normal_packets = 0; -int32 num_tx_buffer_full = 0; -int32 num_rx_packets = 0; -int32 num_ether_irq = 0; -int32 num_unitdata_ind = 0; -int32 num_rx_fastpath = 0; -int32 num_rx_no_mem = 0; -int32 num_rx_dropped = 0; -int32 num_rx_stream_not_ready = 0; -int32 num_rx_no_unitdata_mem = 0; - - -// Function pointers of imported functions -typedef mblk_t *(*allocb_ptr)(size_t size, int pri); -static uint32 allocb_tvect = 0; -mblk_t *allocb(size_t arg1, int arg2) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS2(allocb_ptr, allocb_tvect, arg1, arg2)); -} -typedef void (*freeb_ptr)(mblk_t *); -static uint32 freeb_tvect = 0; -static inline void freeb(mblk_t *arg1) -{ - CallMacOS1(freeb_ptr, freeb_tvect, arg1); -} -typedef int16 (*freemsg_ptr)(mblk_t *); -static uint32 freemsg_tvect = 0; -static inline int16 freemsg(mblk_t *arg1) -{ - return (int16)CallMacOS1(freemsg_ptr, freemsg_tvect, arg1); -} -typedef mblk_t *(*copyb_ptr)(mblk_t *); -static uint32 copyb_tvect = 0; -static inline mblk_t *copyb(mblk_t *arg1) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(copyb_ptr, copyb_tvect, arg1)); -} -typedef mblk_t *(*dupmsg_ptr)(mblk_t *); -static uint32 dupmsg_tvect = 0; -static inline mblk_t *dupmsg(mblk_t *arg1) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(dupmsg_ptr, dupmsg_tvect, arg1)); -} -typedef mblk_t *(*getq_ptr)(queue_t *); -static uint32 getq_tvect = 0; -static inline mblk_t *getq(queue_t *arg1) -{ - return (mblk_t *)Mac2HostAddr((uint32)CallMacOS1(getq_ptr, getq_tvect, arg1)); -} -typedef int (*putq_ptr)(queue_t *, mblk_t *); -static uint32 putq_tvect = 0; -static inline int putq(queue_t *arg1, mblk_t *arg2) -{ - return (int)CallMacOS2(putq_ptr, putq_tvect, arg1, arg2); -} -typedef int (*putnext_ptr)(queue_t *, mblk_t *); -static uint32 putnext_tvect = 0; -static inline int putnext(queue_t *arg1, mblk_t *arg2) -{ - return (int)CallMacOS2(putnext_ptr, putnext_tvect, arg1, arg2); -} -typedef int (*putnextctl1_ptr)(queue_t *, int type, int c); -static uint32 putnextctl1_tvect = 0; -static inline int putnextctl1(queue_t *arg1, int arg2, int arg3) -{ - return (int)CallMacOS3(putnextctl1_ptr, putnextctl1_tvect, arg1, arg2, arg3); -} -typedef int (*canputnext_ptr)(queue_t *); -static uint32 canputnext_tvect = 0; -static inline int canputnext(queue_t *arg1) -{ - return (int)CallMacOS1(canputnext_ptr, canputnext_tvect, arg1); -} -typedef int (*qreply_ptr)(queue_t *, mblk_t *); -static uint32 qreply_tvect = 0; -static inline int qreply(queue_t *arg1, mblk_t *arg2) -{ - return (int)CallMacOS2(qreply_ptr, qreply_tvect, arg1, arg2); -} -typedef void (*flushq_ptr)(queue_t *, int flag); -static uint32 flushq_tvect = 0; -static inline void flushq(queue_t *arg1, int arg2) -{ - CallMacOS2(flushq_ptr, flushq_tvect, arg1, arg2); -} -typedef int (*msgdsize_ptr)(const mblk_t *); -static uint32 msgdsize_tvect = 0; -static inline int msgdsize(const mblk_t *arg1) -{ - return (int)CallMacOS1(msgdsize_ptr, msgdsize_tvect, arg1); -} -typedef void (*otenterint_ptr)(void); -static uint32 otenterint_tvect = 0; -void OTEnterInterrupt(void) -{ - CallMacOS(otenterint_ptr, otenterint_tvect); -} -typedef void (*otleaveint_ptr)(void); -static uint32 otleaveint_tvect = 0; -void OTLeaveInterrupt(void) -{ - CallMacOS(otleaveint_ptr, otleaveint_tvect); -} -typedef int (*mi_open_comm_ptr)(DLPIStream **mi_opp_orig, size_t size, queue_t *q, void *dev, int flag, int sflag, void *credp); -static uint32 mi_open_comm_tvect = 0; -static inline int mi_open_comm(DLPIStream **arg1, size_t arg2, queue_t *arg3, void *arg4, int arg5, int arg6, void *arg7) -{ - return (int)CallMacOS7(mi_open_comm_ptr, mi_open_comm_tvect, arg1, arg2, arg3, arg4, arg5, arg6, arg7); -} -typedef int (*mi_close_comm_ptr)(DLPIStream **mi_opp_orig, queue_t *q); -static uint32 mi_close_comm_tvect = 0; -static inline int mi_close_comm(DLPIStream **arg1, queue_t *arg2) -{ - return (int)CallMacOS2(mi_close_comm_ptr, mi_close_comm_tvect, arg1, arg2); -} -typedef DLPIStream *(*mi_next_ptr_ptr)(DLPIStream *); -static uint32 mi_next_ptr_tvect = 0; -static inline DLPIStream *mi_next_ptr(DLPIStream *arg1) -{ - return (DLPIStream *)Mac2HostAddr((uint32)CallMacOS1(mi_next_ptr_ptr, mi_next_ptr_tvect, arg1)); -} -#ifdef USE_ETHER_FULL_DRIVER -typedef void (*ether_dispatch_packet_ptr)(uint32 p, uint32 size); -static uint32 ether_dispatch_packet_tvect = 0; -#endif - -// Prototypes -static void ether_ioctl(DLPIStream *the_stream, queue_t* q, mblk_t* mp); -static void ether_flush(queue_t* q, mblk_t* mp); -static mblk_t *build_tx_packet_header(DLPIStream *the_stream, mblk_t *mp, bool fast_path); -static void transmit_packet(mblk_t *mp); -static void DLPI_error_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim, uint32 err, uint32 uerr); -static void DLPI_ok_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim); -static void DLPI_info(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_phys_addr(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_subs_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_subs_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp); -static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp); - - -/* - * Initialize ethernet stream module - */ - -static uint8 InitStreamModuleImpl(void *theID) -{ - D(bug("InitStreamModule\n")); - - // Don't re-open if already open - if (ether_driver_opened) - return true; - ether_driver_opened = false; - - // Import functions from OTKernelLib - allocb_tvect = FindLibSymbol("\013OTKernelLib", "\006allocb"); - D(bug("allocb TVECT at %08lx\n", allocb_tvect)); - if (allocb_tvect == 0) - return false; - freeb_tvect = FindLibSymbol("\013OTKernelLib", "\005freeb"); - D(bug("freeb TVECT at %08lx\n", freeb_tvect)); - if (freeb_tvect == 0) - return false; - freemsg_tvect = FindLibSymbol("\013OTKernelLib", "\007freemsg"); - D(bug("freemsg TVECT at %08lx\n", freemsg_tvect)); - if (freemsg_tvect == 0) - return false; - copyb_tvect = FindLibSymbol("\013OTKernelLib", "\005copyb"); - D(bug("copyb TVECT at %08lx\n", copyb_tvect)); - if (copyb_tvect == 0) - return false; - dupmsg_tvect = FindLibSymbol("\013OTKernelLib", "\006dupmsg"); - D(bug("dupmsg TVECT at %08lx\n", dupmsg_tvect)); - if (dupmsg_tvect == 0) - return false; - getq_tvect = FindLibSymbol("\013OTKernelLib", "\004getq"); - D(bug("getq TVECT at %08lx\n", getq_tvect)); - if (getq_tvect == 0) - return false; - putq_tvect = FindLibSymbol("\013OTKernelLib", "\004putq"); - D(bug("putq TVECT at %08lx\n", putq_tvect)); - if (putq_tvect == 0) - return false; - putnext_tvect = FindLibSymbol("\013OTKernelLib", "\007putnext"); - D(bug("putnext TVECT at %08lx\n", putnext_tvect)); - if (putnext_tvect == 0) - return false; - putnextctl1_tvect = FindLibSymbol("\013OTKernelLib", "\013putnextctl1"); - D(bug("putnextctl1 TVECT at %08lx\n", putnextctl1_tvect)); - if (putnextctl1_tvect == 0) - return false; - canputnext_tvect = FindLibSymbol("\013OTKernelLib", "\012canputnext"); - D(bug("canputnext TVECT at %08lx\n", canputnext_tvect)); - if (canputnext_tvect == 0) - return false; - qreply_tvect = FindLibSymbol("\013OTKernelLib", "\006qreply"); - D(bug("qreply TVECT at %08lx\n", qreply_tvect)); - if (qreply_tvect == 0) - return false; - flushq_tvect = FindLibSymbol("\013OTKernelLib", "\006flushq"); - D(bug("flushq TVECT at %08lx\n", flushq_tvect)); - if (flushq_tvect == 0) - return false; - msgdsize_tvect = FindLibSymbol("\013OTKernelLib", "\010msgdsize"); - D(bug("msgdsize TVECT at %08lx\n", msgdsize_tvect)); - if (msgdsize_tvect == 0) - return false; - otenterint_tvect = FindLibSymbol("\017OTKernelUtilLib", "\020OTEnterInterrupt"); - D(bug("OTEnterInterrupt TVECT at %08lx\n", otenterint_tvect)); - if (otenterint_tvect == 0) - return false; - otleaveint_tvect = FindLibSymbol("\017OTKernelUtilLib", "\020OTLeaveInterrupt"); - D(bug("OTLeaveInterrupt TVECT at %08lx\n", otleaveint_tvect)); - if (otleaveint_tvect == 0) - return false; - mi_open_comm_tvect = FindLibSymbol("\013OTKernelLib", "\014mi_open_comm"); - D(bug("mi_open_comm TVECT at %08lx\n", mi_open_comm_tvect)); - if (mi_open_comm_tvect == 0) - return false; - mi_close_comm_tvect = FindLibSymbol("\013OTKernelLib", "\015mi_close_comm"); - D(bug("mi_close_comm TVECT at %08lx\n", mi_close_comm_tvect)); - if (mi_close_comm_tvect == 0) - return false; - mi_next_ptr_tvect = FindLibSymbol("\013OTKernelLib", "\013mi_next_ptr"); - D(bug("mi_next_ptr TVECT at %08lx\n", mi_next_ptr_tvect)); - if (mi_next_ptr_tvect == 0) - return false; - -#ifndef USE_ETHER_FULL_DRIVER - // Initialize stream list (which might be leftover) - dlpi_stream_list = NULL; - - // Ask add-on for ethernet hardware address - AO_get_ethernet_address(Host2MacAddr(hardware_address)); -#endif - - // Yes, we're open - ether_driver_opened = true; - return true; -} - -uint8 InitStreamModule(void *theID) -{ - // Common initialization code - bool net_open = InitStreamModuleImpl(theID); - - // Call InitStreamModule() in native side -#ifdef BUILD_ETHER_FULL_DRIVER - extern bool NativeInitStreamModule(void *); - if (!NativeInitStreamModule((void *)ether_dispatch_packet)) - net_open = false; -#endif - - // Import functions from the Ethernet driver -#ifdef USE_ETHER_FULL_DRIVER - ether_dispatch_packet_tvect = (uintptr)theID; - D(bug("ether_dispatch_packet TVECT at %08lx\n", ether_dispatch_packet_tvect)); - if (ether_dispatch_packet_tvect == 0) - net_open = false; -#endif - - return net_open; -} - - -/* - * Terminate ethernet stream module - */ - -static void TerminateStreamModuleImpl(void) -{ - D(bug("TerminateStreamModule\n")); - -#ifndef USE_ETHER_FULL_DRIVER - // This happens sometimes. I don't know why. - if (dlpi_stream_list != NULL) - printf("FATAL: TerminateStreamModule() called, but streams still open\n"); -#endif - - // Sorry, we're closed - ether_driver_opened = false; -} - -void TerminateStreamModule(void) -{ - // Common termination code - TerminateStreamModuleImpl(); - - // Call TerminateStreamModule() in native side -#ifdef BUILD_ETHER_FULL_DRIVER - extern void NativeTerminateStreamModule(void); - NativeTerminateStreamModule(); -#endif -} - - -/* - * Open new stream - */ - -int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds) -{ - D(bug("ether_open(%p,%p,%d,%d,%p)\n", rdq, dev, flag, sflag, creds)); - - // Return if driver was closed - if (!ether_driver_opened) { - printf("FATAL: ether_open(): Ethernet driver not opened\n"); - return MAC_ENXIO; - } - - // If we're being reopened, just return - if (rdq->q_ptr != NULL) - return 0; - - // Allocate DLPIStream structure - int err = mi_open_comm((DLPIStream **)&dlpi_stream_list, sizeof(DLPIStream), rdq, dev, flag, sflag, creds); - if (err) - return err; - DLPIStream *the_stream = (DLPIStream *)rdq->q_ptr; - the_stream->rdq = rdq; - the_stream->dlpi_state = DL_UNBOUND; - the_stream->flags = 0; - the_stream->dlsap = 0; - the_stream->framing_8022 = false; - the_stream->raw_mode = false; - the_stream->multicast_list = NULL; - return 0; -} - - -/* - * Close stream - */ - -int ether_close(queue_t *rdq, int flag, void *creds) -{ - D(bug("ether_close(%p,%d,%p)\n", rdq, flag, creds)); - - // Return if driver was closed - if (!ether_driver_opened) { - printf("FATAL: ether_close(): Ethernet driver not opened\n"); - return MAC_ENXIO; - } - - // Get stream - DLPIStream *the_stream = (DLPIStream *)rdq->q_ptr; - - // Don't close if never opened - if (the_stream == NULL) - return 0; - - // Disable all registered multicast addresses - while (the_stream->multicast_list) { - AO_disable_multicast(Host2MacAddr(the_stream->multicast_list->addr)); - the_stream->RemoveMulticast(the_stream->multicast_list->addr); - } - the_stream->multicast_list = NULL; - - // Delete the DLPIStream - return mi_close_comm((DLPIStream **)&dlpi_stream_list, rdq); -} - - -/* - * Put something on the write queue - */ - -int ether_wput(queue_t *q, mblk_t *mp) -{ - D(bug("ether_wput(%p,%p)\n", q, mp)); - - // Return if driver was closed - if (!ether_driver_opened) { - printf("FATAL: ether_wput(): Ethernet driver not opened\n"); - return MAC_ENXIO; - } - - // Get stream - DLPIStream *the_stream = (DLPIStream *)q->q_ptr; - if (the_stream == NULL) - return MAC_ENXIO; - - D(bug(" db_type %d\n", (int)mp->b_datap->db_type)); - switch (mp->b_datap->db_type) { - - case M_DATA: - // Transmit raw packet - D(bug(" raw packet\n")); - num_tx_raw_packets++; - transmit_packet(mp); - break; - - case M_PROTO: - case M_PCPROTO: { - union DL_primitives *dlp = (union DL_primitives *)(void *)mp->b_rptr; - uint32 prim = dlp->dl_primitive; - D(bug(" dl_primitive %d\n", prim)); - switch (prim) { - case DL_UNITDATA_REQ: - // Transmit normal packet - num_tx_normal_packets++; - DLPI_unit_data(the_stream, q, mp); - break; - - case DL_INFO_REQ: - DLPI_info(the_stream, q, mp); - break; - - case DL_PHYS_ADDR_REQ: - DLPI_phys_addr(the_stream, q, mp); - break; - - case DL_BIND_REQ: - DLPI_bind(the_stream, q, mp); - break; - - case DL_UNBIND_REQ: - DLPI_unbind(the_stream, q, mp); - break; - - case DL_SUBS_BIND_REQ: - DLPI_subs_bind(the_stream, q, mp); - break; - - case DL_SUBS_UNBIND_REQ: - DLPI_subs_unbind(the_stream, q, mp); - break; - - case DL_ENABMULTI_REQ: - DLPI_enable_multi(the_stream, q, mp); - break; - - case DL_DISABMULTI_REQ: - DLPI_disable_multi(the_stream, q, mp); - break; - - default: - D(bug("WARNING: ether_wsrv(): Unknown primitive\n")); - DLPI_error_ack(the_stream, q, mp, prim, DL_NOTSUPPORTED, 0); - break; - } - break; - } - - case M_IOCTL: - ether_ioctl(the_stream, q, mp); - break; - - case M_FLUSH: - ether_flush(q, mp); - break; - - default: - D(bug("WARNING: ether_wput(): Unknown message type\n")); - freemsg(mp); - break; - } - num_wput++; - return 0; -} - - -/* - * Dequeue and process messages from the read queue - */ - -int ether_rsrv(queue_t *q) -{ - mblk_t *mp; - while ((mp = getq(q)) != NULL) { - if (canputnext(q)) - putnext(q, mp); - else { - freemsg(mp); - flushq(q, FLUSHDATA); - break; - } - } - return 0; -} - - -/* - * Handle ioctl calls - */ - -static void ether_ioctl(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - struct iocblk *ioc = (struct iocblk *)(void *)mp->b_rptr; - D(bug(" ether_ioctl(%p,%p) cmd %d\n", q, mp, (int)ioc->ioc_cmd)); - - switch (ioc->ioc_cmd) { - - case I_OTSetFramingType: { // Toggles what the general info primitive returns for dl_mac_type in dl_info_ack_t structure - mblk_t *info_mp = mp->b_cont; - if (info_mp == NULL || ((info_mp->b_wptr - info_mp->b_rptr) != sizeof(uint32))) { - ioc->ioc_error = MAC_EINVAL; - goto ioctl_error; - } - uint32 framing_type = ntohl(*(uint32 *)(void *)info_mp->b_rptr); - D(bug(" I_OTSetFramingType type %d\n", framing_type)); - if (framing_type != kOTGetFramingValue) - the_stream->framing_8022 = (framing_type == kOTFraming8022); - mp->b_cont = NULL; - freemsg(info_mp); - if (the_stream->framing_8022) - ioc->ioc_rval = kOTFraming8022; - else - ioc->ioc_rval = kOTFramingEthernet; - goto ioctl_ok; - } - - case DL_IOC_HDR_INFO: { // Special Mentat call, for fast transmits - D(bug(" DL_IOC_HDR_INFO\n")); - mblk_t *info_mp = mp->b_cont; - - // Copy DL_UNITDATA_REQ block - mblk_t *unitdata_mp = copyb(info_mp); - if (unitdata_mp == NULL) { - ioc->ioc_error = MAC_ENOMEM; - goto ioctl_error; - } - unitdata_mp->b_datap->db_type = M_PROTO; - - // Construct header (converts DL_UNITDATA_REQ -> M_DATA) - mblk_t *header_mp = build_tx_packet_header(the_stream, unitdata_mp, true); - - if (header_mp == NULL) { - // Could not allocate a message block large enough - ioc->ioc_error = MAC_ENOMEM; - goto ioctl_error; - } - - // Attach header block at the end - mp->b_cont->b_cont = header_mp; - the_stream->flags |= kFastPathMode; - goto ioctl_ok; - } - - case I_OTSetRawMode: { - mblk_t *info_mp = mp->b_cont; - dl_recv_control_t *dlrc; - if (info_mp == NULL || ((info_mp->b_wptr - info_mp->b_rptr) != sizeof(dlrc->dl_primitive))) { - ioc->ioc_error = MAC_EINVAL; - goto ioctl_error; - } - dlrc = (dl_recv_control_t *)(void *)info_mp->b_rptr; - D(bug(" I_OTSetRawMode primitive %d\n", (int)dlrc->dl_primitive)); - the_stream->raw_mode = true; - goto ioctl_ok; - } - - default: - D(bug("WARNING: Unknown ether_ioctl() call\n")); - ioc->ioc_error = MAC_EINVAL; - goto ioctl_error; - } - -ioctl_ok: - ioc->ioc_count = 0; - for (mblk_t *mp1 = mp; (mp1 = mp1->b_cont) != NULL;) - ioc->ioc_count += mp1->b_wptr - mp1->b_rptr; - ioc->ioc_error = 0; - mp->b_datap->db_type = M_IOCACK; - qreply(q, mp); - return; - -ioctl_error: - mp->b_datap->db_type = M_IOCNAK; - qreply(q, mp); - return; -} - - -/* - * Flush call, send it up to the read side of the stream - */ - -static void ether_flush(queue_t* q, mblk_t* mp) -{ - D(bug(" ether_flush(%p,%p)\n", q, mp)); - - uint8 *rptr = mp->b_rptr; - if (*rptr & FLUSHW) - flushq(q, FLUSHALL); - if (*rptr & FLUSHR) { - flushq(RD(q), FLUSHALL); - *rptr &= ~FLUSHW; - qreply(q, mp); - } else - freemsg(mp); -} - - -/* - * Classify packet into the different types of protocols - */ - -static uint16 classify_packet_type(uint16 primarySAP, uint16 secondarySAP) -{ - if (primarySAP >= kMinDIXSAP) - return kPktDIX; - - if ((primarySAP == kIPXSAP) && (secondarySAP == kIPXSAP)) - return kPktIPX; - - if (primarySAP == kSNAPSAP) - return kPkt8022SNAP; - - if (primarySAP <= k8022GlobalSAP) - return kPkt8022SAP; - - return kPktUnknown; -} - - -/* - * Check if the address is a multicast, broadcast or standard address - */ - -static int32 get_address_type(uint8 *addr) -{ - if (addr[0] & 1) { // Multicast/broadcast flag - if (OTIs48BitBroadcastAddress(addr)) - return keaBroadcast; - else - return keaMulticast; - } else - return keaStandardAddress; -} - - -/* - * Reuse a message block, make room for more data - */ - -static mblk_t *reuse_message_block(mblk_t *mp, uint16 needed_size) -{ - mblk_t *nmp; - - if ((mp->b_datap->db_ref == 1) && ((mp->b_datap->db_lim - mp->b_datap->db_base) >= needed_size)) { - mp->b_datap->db_type = M_DATA; - mp->b_rptr = mp->b_datap->db_base; - mp->b_wptr = mp->b_datap->db_base + needed_size; - } else { - nmp = mp->b_cont; // Grab the M_DATA blocks - mp->b_cont = NULL; // Detach the M_(PC)PROTO - freemsg(mp); // Free the M_(PC)PROTO - mp = nmp; // Point to the M_DATA blocks - - // Try to get space on the first M_DATA block - if (mp && (mp->b_datap->db_ref == 1) && ((mp->b_rptr - mp->b_datap->db_base) >= needed_size)) - mp->b_rptr -= needed_size; - else { - // Try to allocate a new message - if ((nmp = allocb(needed_size, BPRI_HI)) == NULL) { - // Could not get a new message block so lets forget about the message altogether - freemsg(mp); // Free the original M_DATA portion of the message - mp = NULL; // Indicates the reuse failed - } else { - nmp->b_cont = mp; // Attach the new message block as the head - nmp->b_wptr += needed_size; - mp = nmp; - } - } - } - - return mp; -} - - -/* - * Built header for packet to be transmitted (convert DL_UNITDATA_REQ -> M_DATA) - * The passed-in message has the header info in the first message block and the data - * in the following blocks - */ - -static mblk_t *build_tx_packet_header(DLPIStream *the_stream, mblk_t *mp, bool fast_path) -{ - // Only handle unit_data requests - dl_unitdata_req_t *req = (dl_unitdata_req_t *)(void *)mp->b_rptr; - if (req->dl_primitive != DL_UNITDATA_REQ) { - freemsg(mp); - return NULL; - } - - // Extract destination address and its length - uint8 *destAddrOrig = ((uint8 *)req) + req->dl_dest_addr_offset; - uint32 destAddrLen = req->dl_dest_addr_length; - uint8 ctrl = 0x03; - - // Extract DLSAP - uint16 dlsap; - switch (destAddrLen) { - case kEnetPhysicalAddressLength: - dlsap = the_stream->dlsap; - break; - case kEnetAndSAPAddressLength: - dlsap = ntohs(*(uint16 *)(destAddrOrig + kEnetPhysicalAddressLength)); - break; - case kEnetPhysicalAddressLength + k8022DLSAPLength + k8022SNAPLength: // SNAP SAP - dlsap = ntohs(*(uint16 *)(destAddrOrig + kEnetPhysicalAddressLength)); - break; - default: - dlsap = the_stream->dlsap; - break; - } - - // Extract data size (excluding header info) and packet type - uint16 datasize = msgdsize(mp); - uint16 packetType = classify_packet_type(the_stream->dlsap, dlsap); - - // Calculate header size and protocol type/size field - uint16 hdrsize, proto; - switch (packetType) { - case kPktDIX: - hdrsize = kEnetPacketHeaderLength; - proto = dlsap; - break; - case kPkt8022SAP: - hdrsize = kEnetPacketHeaderLength + k8022BasicHeaderLength; - if (fast_path) - proto = 0; - else - proto = datasize + k8022BasicHeaderLength; - break; - case kPkt8022SNAP: - hdrsize = kEnetPacketHeaderLength + k8022SNAPHeaderLength; - if (fast_path) - proto = 0; - else - proto = datasize + k8022SNAPHeaderLength; - break; - case kPktIPX: - hdrsize = kEnetPacketHeaderLength; - if (fast_path) - proto = 0; - else - proto = datasize; - break; - default: - hdrsize = kEnetPacketHeaderLength; - proto = dlsap; - break; - } - - // We need to copy the dest address info in the message before we can reuse it - uint8 destAddrCopy[kMaxBoundAddrLength]; - memcpy(destAddrCopy, destAddrOrig, destAddrLen); - - // Resize header info in message block - if ((mp = reuse_message_block(mp, hdrsize)) == NULL) - return NULL; - struct T8022FullPacketHeader *packetHeader = (struct T8022FullPacketHeader *)(void *)mp->b_rptr; - - // Set protocol type/size field - packetHeader->fEnetPart.fProto = proto; - - // Set destination ethernet address - OTCopy48BitAddress(destAddrCopy, packetHeader->fEnetPart.fDestAddr); - - // Set other header fields - switch (packetType) { - case kPkt8022SAP: - packetHeader->f8022Part.fDSAP = (uint8)dlsap; - packetHeader->f8022Part.fSSAP = (uint8)the_stream->dlsap; - packetHeader->f8022Part.fCtrl = ctrl; - break; - case kPkt8022SNAP: { - uint8 *snapStart; - packetHeader->f8022Part.fDSAP = (uint8)dlsap; - packetHeader->f8022Part.fSSAP = (uint8)the_stream->dlsap; - packetHeader->f8022Part.fCtrl = ctrl; - if (destAddrLen >= kEnetAndSAPAddressLength + k8022SNAPLength) - snapStart = destAddrCopy + kEnetAndSAPAddressLength; - else - snapStart = the_stream->snap; - OTCopy8022SNAP(snapStart, packetHeader->f8022Part.fSNAP); - break; - } - } - - // Return updated message - return mp; -} - - -/* - * Transmit packet - */ - -static void transmit_packet(mblk_t *mp) -{ - EnetPacketHeader *enetHeader = (EnetPacketHeader *)(void *)mp->b_rptr; - - // Fill in length in 802.3 packets - if (enetHeader->fProto == 0) - enetHeader->fProto = msgdsize(mp) - sizeof(EnetPacketHeader); - - // Fill in ethernet source address - OTCopy48BitAddress(hardware_address, enetHeader->fSourceAddr); - - // Tell add-on to transmit packet - AO_transmit_packet(Host2MacAddr((uint8 *)mp)); - freemsg(mp); -} - - -/* - * Handle incoming packet (one stream), construct DL_UNITDATA_IND message - */ - -static void handle_received_packet(DLPIStream *the_stream, mblk_t *mp, uint16 packet_type, int32 dest_addr_type) -{ - // Find address and header length - uint32 addr_len; - uint32 header_len; - switch (packet_type) { - case kPkt8022SAP: - addr_len = kEnetAndSAPAddressLength; - header_len = kEnetPacketHeaderLength + k8022BasicHeaderLength; - break; - case kPkt8022SNAP: - addr_len = kEnetAndSAPAddressLength + k8022SNAPLength; - header_len = kEnetPacketHeaderLength + k8022SNAPHeaderLength; - break; - default: // DIX and IPX - addr_len = kEnetAndSAPAddressLength; - header_len = kEnetPacketHeaderLength; - break; - } - - // In Fast Path mode, don't send DL_UNITDATA_IND messages for unicast packets - if ((the_stream->flags & kFastPathMode) && dest_addr_type == keaStandardAddress) { - if (the_stream->raw_mode == false) - mp->b_rptr += header_len; - num_rx_fastpath++; - putq(the_stream->rdq, mp); - return; - } - - // Allocate the dl_unitdata_ind_t message - mblk_t *nmp; - if ((nmp = allocb(sizeof(dl_unitdata_ind_t) + 2*addr_len, BPRI_HI)) == NULL) { - freemsg(mp); - num_rx_no_unitdata_mem++; - return; - } - - // Set message type - nmp->b_datap->db_type = M_PROTO; - dl_unitdata_ind_t *ind = (dl_unitdata_ind_t*)(void *)nmp->b_rptr; - ind->dl_primitive = DL_UNITDATA_IND; - nmp->b_wptr += (sizeof(dl_unitdata_ind_t) + 2*addr_len); - - // Link M_DATA block - nmp->b_cont = mp; - - // Set address fields - ind->dl_dest_addr_length = addr_len; - ind->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t); - ind->dl_src_addr_length = addr_len; - ind->dl_src_addr_offset = sizeof(dl_unitdata_ind_t) + addr_len; - - // Set address type - ind->dl_group_address = dest_addr_type; - - // Set address fields - T8022FullPacketHeader *packetHeader = (T8022FullPacketHeader *)(void *)mp->b_rptr; - T8022AddressStruct *destAddr = ((T8022AddressStruct*)(nmp->b_rptr + ind->dl_dest_addr_offset)); - T8022AddressStruct *srcAddr = ((T8022AddressStruct*)(nmp->b_rptr + ind->dl_src_addr_offset)); - - OTCopy48BitAddress(packetHeader->fEnetPart.fDestAddr, destAddr->fHWAddr); - OTCopy48BitAddress(packetHeader->fEnetPart.fSourceAddr, srcAddr->fHWAddr); - - destAddr->fSAP = packetHeader->f8022Part.fDSAP; - srcAddr->fSAP = packetHeader->f8022Part.fSSAP; - - if (packet_type == kPkt8022SNAP) { - OTCopy8022SNAP(packetHeader->f8022Part.fSNAP, destAddr->fSNAP); - OTCopy8022SNAP(packetHeader->f8022Part.fSNAP, srcAddr->fSNAP); - } - - // "Hide" the ethernet and protocol header(s) - if (the_stream->raw_mode == false) - mp->b_rptr += header_len; - - // Pass message up the stream - num_unitdata_ind++; - putq(the_stream->rdq, nmp); - return; -} - - -/* - * Packet received, distribute it to the streams that want it - */ - -void ether_packet_received(mblk_t *mp) -{ - // Extract address and types - EnetPacketHeader *pkt = (EnetPacketHeader *)(void *)mp->b_rptr; - T8022FullPacketHeader *fullpkt = (T8022FullPacketHeader *)pkt; - uint16 sourceSAP, destSAP; - destSAP = fullpkt->fEnetPart.fProto; - if (destSAP >= kMinDIXSAP) { - // Classic ethernet - sourceSAP = destSAP; - } else { - destSAP = fullpkt->f8022Part.fDSAP; - sourceSAP = fullpkt->f8022Part.fSSAP; - } - uint16 packetType = classify_packet_type(sourceSAP, destSAP); - int32 destAddressType = get_address_type(pkt->fDestAddr); - - // Look which streams want it - DLPIStream *the_stream, *found_stream = NULL; - uint16 found_packetType = 0; - int32 found_destAddressType = 0; - for (the_stream = dlpi_stream_list; the_stream != NULL; the_stream = mi_next_ptr(the_stream)) { - - // Don't send to unbound streams - if (the_stream->dlpi_state == DL_UNBOUND) - continue; - - // Does this stream want all 802.2 packets? - if ((the_stream->flags & kAcceptAll8022Packets) && (destSAP <= 0xff)) - goto type_found; - - // No, check SAP/SNAP - if (destSAP == the_stream->dlsap) { - if (the_stream->flags & kSnapStream) { - // Check SNAPs if necessary - uint8 sum = fullpkt->f8022Part.fSNAP[0] ^ the_stream->snap[0]; - sum |= fullpkt->f8022Part.fSNAP[1] ^ the_stream->snap[1]; - sum |= fullpkt->f8022Part.fSNAP[2] ^ the_stream->snap[2]; - sum |= fullpkt->f8022Part.fSNAP[3] ^ the_stream->snap[3]; - sum |= fullpkt->f8022Part.fSNAP[4] ^ the_stream->snap[4]; - if (sum == 0) - goto type_found; - } else { - // No SNAP, found a match since saps match - goto type_found; - } - } else { - // Check for an 802.3 Group/Global (odd) - if (((packetType == kPkt8022SAP) || (packetType == kPkt8022SNAP)) && (destSAP & 1) && the_stream->TestGroupSAP(destSAP)) - goto type_found; - } - - // No stream for this SAP/SNAP found - continue; - -type_found: - // If it's a multicast packet, it must be in the stream's multicast list - if ((destAddressType == keaMulticast) && (the_stream->flags & kAcceptMulticasts) && (!the_stream->IsMulticastRegistered(pkt->fDestAddr))) - continue; - - // Send packet to stream - // found_stream keeps a pointer to the previously found stream, so that only the last - // stream gets the original message, the other ones get duplicates - if (found_stream) - handle_received_packet(found_stream, dupmsg(mp), found_packetType, found_destAddressType); - found_stream = the_stream; - found_packetType = packetType; - found_destAddressType = destAddressType; - } - - // Send original message to last found stream - if (found_stream) - handle_received_packet(found_stream, mp, found_packetType, found_destAddressType); - else { - freemsg(mp); // Nobody wants it *snief* - num_rx_dropped++; - } -} - -void ether_dispatch_packet(uint32 p, uint32 size) -{ -#ifdef USE_ETHER_FULL_DRIVER - // Call handler from the Ethernet driver - D(bug("ether_dispatch_packet\n")); - D(bug(" packet data at %p, %d bytes\n", p, size)); - CallMacOS2(ether_dispatch_packet_ptr, ether_dispatch_packet_tvect, p, size); -#else - // Wrap packet in message block - num_rx_packets++; - mblk_t *mp; - if ((mp = allocb(size, 0)) != NULL) { - D(bug(" packet data at %p\n", (void *)mp->b_rptr)); - Mac2Host_memcpy(mp->b_rptr, p, size); - mp->b_wptr += size; - ether_packet_received(mp); - } else { - D(bug("WARNING: Cannot allocate mblk for received packet\n")); - num_rx_no_mem++; - } -#endif -} - - -/* - * Build and send an error acknowledge - */ - -static void DLPI_error_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim, uint32 err, uint32 uerr) -{ - D(bug(" DLPI_error_ack(%p,%p) prim %d, err %d, uerr %d\n", the_stream, ack_mp, prim, err, uerr)); - num_error_acks++; - - if (ack_mp != NULL) - freemsg(ack_mp); - if ((ack_mp = allocb(sizeof(dl_error_ack_t), BPRI_HI)) == NULL) - return; - - ack_mp->b_datap->db_type = M_PCPROTO; - dl_error_ack_t *errp = (dl_error_ack_t *)(void *)ack_mp->b_wptr; - errp->dl_primitive = DL_ERROR_ACK; - errp->dl_error_primitive = prim; - errp->dl_errno = err; - errp->dl_unix_errno = uerr; - ack_mp->b_wptr += sizeof(dl_error_ack_t); - qreply(q, ack_mp); -} - - -/* - * Build and send an OK acknowledge - */ - -static void DLPI_ok_ack(DLPIStream *the_stream, queue_t *q, mblk_t *ack_mp, uint32 prim) -{ - if (ack_mp->b_datap->db_ref != 1) { - // Message already in use, create a new one - freemsg(ack_mp); - if ((ack_mp = allocb(sizeof(dl_error_ack_t), BPRI_HI)) == NULL) - return; - } else { - // Message free - if (ack_mp->b_cont != NULL) { - freemsg(ack_mp->b_cont); - ack_mp->b_cont = NULL; - } - } - - ack_mp->b_datap->db_type = M_PCPROTO; - dl_ok_ack_t *ackp = (dl_ok_ack_t *)(void *)ack_mp->b_rptr; - ackp->dl_primitive = DL_OK_ACK; - ackp->dl_correct_primitive = prim; - ack_mp->b_wptr = ack_mp->b_rptr + sizeof(dl_ok_ack_t); - qreply(q, ack_mp); -} - - -/* - * Handle DL_INFO_REQ (report general information) - */ - -static void DLPI_info(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_info(%p)\n", the_stream)); - uint32 saplen = 0; - uint32 addrlen = kEnetPhysicalAddressLength; - uint32 bcastlen = kEnetPhysicalAddressLength; - uint32 hdrlen = kEnetPacketHeaderLength; - - // Calculate header length - if (the_stream->dlpi_state != DL_UNBOUND) { - saplen = (the_stream->flags & kSnapStream) ? k8022DLSAPLength+k8022SNAPLength : k8022DLSAPLength; - if (the_stream->dlsap == kSNAPSAP) - hdrlen = kEnetPacketHeaderLength + k8022SNAPHeaderLength; // SNAP address - else if ((the_stream->dlsap <= kMax8022SAP) || (the_stream->dlsap == kIPXSAP)) - hdrlen = kEnetPacketHeaderLength + k8022BasicHeaderLength; // SAP or IPX - else - hdrlen = kEnetPacketHeaderLength; // Basic Ethernet - } - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_info_ack_t) + addrlen + saplen + bcastlen, BPRI_LO)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_INFO_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_info_ack_t *ackp = (dl_info_ack_t *)(void *)ack_mp->b_rptr; - ackp->dl_primitive = DL_INFO_ACK; - - // Info/version fields - ackp->dl_service_mode = DL_CLDLS; - ackp->dl_provider_style = DL_STYLE1; - ackp->dl_version = DL_VERSION_2; - ackp->dl_current_state = the_stream->dlpi_state; - ackp->dl_mac_type = the_stream->framing_8022 ? DL_CSMACD : DL_ETHER; - ackp->dl_reserved = 0; - ackp->dl_qos_length = 0; - ackp->dl_qos_offset = (uint32)DL_UNKNOWN; - ackp->dl_qos_range_length = 0; - ackp->dl_qos_range_offset = (uint32)DL_UNKNOWN; - ackp->dl_growth = 0; - ackp->dl_min_sdu = 1; - ackp->dl_max_sdu = kEnetTSDU - hdrlen; - - // Address fields - ackp->dl_sap_length = -saplen; // Negative to indicate sap follows physical address - ackp->dl_addr_length = addrlen + saplen; - ackp->dl_addr_offset = sizeof(dl_info_ack_t); - T8022AddressStruct *boundAddr = ((T8022AddressStruct *)(ack_mp->b_rptr + ackp->dl_addr_offset)); - OTCopy48BitAddress(hardware_address, boundAddr->fHWAddr); - if (saplen) { - boundAddr->fSAP = the_stream->dlsap; - if (the_stream->flags & kSnapStream) - OTCopy8022SNAP(the_stream->snap, boundAddr->fSNAP); - } - ackp->dl_brdcst_addr_length = bcastlen; - ackp->dl_brdcst_addr_offset = sizeof(dl_info_ack_t) + addrlen + saplen; - OTSet48BitBroadcastAddress(ack_mp->b_rptr + ackp->dl_brdcst_addr_offset); - - // Advance write pointer - ack_mp->b_wptr += sizeof(dl_info_ack_t) + addrlen + saplen + bcastlen; - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_PHYS_ADDR_REQ (report physical address) - */ - -static void DLPI_phys_addr(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_phys_addr(%p,%p)\n", the_stream, mp)); - dl_phys_addr_req_t *req = (dl_phys_addr_req_t *)(void *)mp->b_rptr; - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_phys_addr_ack_t) + kEnetPhysicalAddressLength, BPRI_HI)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_PHYS_ADDR_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_phys_addr_ack_t *ackp = (dl_phys_addr_ack_t *)(void *)ack_mp->b_wptr; - ackp->dl_primitive = DL_PHYS_ADDR_ACK; - - // Fill in address - ackp->dl_addr_length = kEnetPhysicalAddressLength; - ackp->dl_addr_offset = sizeof(dl_phys_addr_ack_t); - ack_mp->b_wptr += sizeof(dl_phys_addr_ack_t) + kEnetPhysicalAddressLength; - if (req->dl_addr_type == DL_CURR_PHYS_ADDR || req->dl_addr_type == DL_FACT_PHYS_ADDR) - OTCopy48BitAddress(hardware_address, ack_mp->b_rptr + ackp->dl_addr_offset); - else { - DLPI_error_ack(the_stream, q, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0); - return; - } - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_BIND_REQ (bind a stream) - */ - -static void DLPI_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_bind_req_t *req = (dl_bind_req_t *)(void *)mp->b_rptr; - uint32 sap = req->dl_sap; - D(bug(" DLPI_bind(%p,%p) SAP %04x\n", the_stream, mp, sap)); - - // Stream must be unbound - if (the_stream->dlpi_state != DL_UNBOUND) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_OUTSTATE, 0); - return; - } - - // We only support connectionless data link services - if (req->dl_service_mode != DL_CLDLS || req->dl_max_conind != 0) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0); - return; - } - - // Don't bind to 802.2 group saps, can't check 802.2 global sap (0xFF) - // because it looks like IPX - if ((sap <= kMax8022SAP) && (sap & 1)) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_BADADDR, 0); - return; - } - - if (classify_packet_type(sap, sap) == kPktUnknown) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_BADADDR, 0); - return; - } - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_bind_ack_t) + kEnetAndSAPAddressLength, BPRI_HI)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_BIND_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_bind_ack_t *ackp = (dl_bind_ack_t *)(void *)ack_mp->b_rptr; - ackp->dl_primitive = DL_BIND_ACK; - - // Fill in other fields - ackp->dl_sap = sap; - ackp->dl_addr_length = kEnetAndSAPAddressLength; - ackp->dl_addr_offset = sizeof(dl_bind_ack_t); - ackp->dl_max_conind = 0; - ackp->dl_xidtest_flg = 0; - - T8022AddressStruct *addrInfo = (T8022AddressStruct *)(ack_mp->b_rptr + sizeof(dl_bind_ack_t)); - OTCopy48BitAddress(hardware_address, addrInfo->fHWAddr); - addrInfo->fSAP = sap; - - // Must move b_wptr past the address info data - ack_mp->b_wptr = ack_mp->b_rptr + sizeof(dl_bind_ack_t) + kEnetAndSAPAddressLength; - - // Set group SAP if necessary - the_stream->ClearAllGroupSAPs(); - if (sap <= kMax8022SAP) - the_stream->SetGroupSAP(k8022GlobalSAP); - - // The stream is now bound and idle - the_stream->dlpi_state = DL_IDLE; - the_stream->dlsap = sap; - the_stream->flags &= ~kSnapStream; - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_UNBIND_REQ (unbind a stream) - */ - -static void DLPI_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_unbind(%p,%p)\n", the_stream, mp)); - - // Stream must be bound and idle - if (the_stream->dlpi_state != DL_IDLE) { - DLPI_error_ack(the_stream, q, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0); - return; - } - - // Stream is now unbound - the_stream->dlpi_state = DL_UNBOUND; - the_stream->dlsap = 0; - - // Flush all pending outbound messages - flushq(q, FLUSHDATA); - - // Flush all inbound messages pending on the stream - flushq(RD(q), FLUSHDATA); - putnextctl1(RD(q), M_FLUSH, FLUSHRW); - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_UNBIND_REQ); - return; -} - - -/* - * Handle DL_SUBS_BIND_REQ (register 802.2 SAP group addresses and SNAPs) - */ - -static void DLPI_subs_bind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_subs_bind_req_t *req = (dl_subs_bind_req_t *)(void *)mp->b_rptr; - uint8 *sap = ((uint8 *)req) + req->dl_subs_sap_offset; - int32 length = req->dl_subs_sap_length; - uint16 theSap = ntohs(*((uint16 *)sap)); - int32 error = 0; - D(bug(" DLPI_subs_bind(%p,%p) SAP %02x%02x%02x%02x%02x\n", the_stream, mp, sap[0], sap[1], sap[2], sap[3], sap[4])); - - // Stream must be idle - if (the_stream->dlpi_state != DL_IDLE) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, DL_OUTSTATE, 0); - return; - } - - // Check if address is valid - switch (req->dl_subs_bind_class) { - case DL_PEER_BIND: // Bind a group address - if (the_stream->dlsap <= kMax8022SAP) { - if ((theSap & 1) && (length == sizeof(theSap))) - the_stream->SetGroupSAP(theSap); - else - if (theSap == 0x0000) // special case to receive all 802.2 packets - the_stream->flags |= kAcceptAll8022Packets; - else - error = DL_BADADDR; - } else - error = DL_UNSUPPORTED; - break; - - case DL_HIERARCHICAL_BIND: // Bind an additional SNAP - if (the_stream->dlsap == kSNAPSAP) { - if (the_stream->flags & kSnapStream) - error = DL_TOOMANY; // only one SNAP binding allowed - else { - OTCopy8022SNAP(sap, the_stream->snap); - the_stream->flags |= kSnapStream; - } - } else - error = DL_BADADDR; - break; - - default: - error = DL_UNSUPPORTED; - break; - } - if (error) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, error, 0); - return; - } - - // Allocate message block for reply - mblk_t *ack_mp; - if ((ack_mp = allocb(sizeof(dl_subs_bind_ack_t) + length, BPRI_HI)) == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_BIND_REQ, DL_SYSERR, MAC_ENOMEM); - return; - } - - // Set up message type - ack_mp->b_datap->db_type = M_PCPROTO; - dl_subs_bind_ack_t *ackp = (dl_subs_bind_ack_t *)(void *)ack_mp->b_wptr; - memset(ackp, 0, sizeof(dl_subs_bind_ack_t) + length); - ackp->dl_primitive = DL_SUBS_BIND_ACK; - - // Fill in other fields - ackp->dl_subs_sap_length = length; - ackp->dl_subs_sap_offset = length ? sizeof(dl_subs_bind_ack_t) : 0; - ack_mp->b_wptr += sizeof(dl_subs_bind_ack_t); - if (length) - memcpy(ack_mp->b_wptr, sap, length); - ack_mp->b_wptr += length; - - // Free request - freemsg(mp); - - // Send reply - qreply(q, ack_mp); - return; -} - - -/* - * Handle DL_SUBS_UNBIND_REQ (unregister 802.2 SAP group addresses and snaps) - */ - -static void DLPI_subs_unbind(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_subs_unbind_req_t *req = (dl_subs_unbind_req_t *)(void *)mp->b_rptr; - uint8 *sap = ((uint8 *)req) + req->dl_subs_sap_offset; - int32 length = req->dl_subs_sap_length; - int32 error = 0; - D(bug(" DLPI_subs_unbind(%p,%p) SAP %02x%02x%02x%02x%02x\n", the_stream, mp, sap[0], sap[1], sap[2], sap[3], sap[4])); - - // Stream must be idle - if (the_stream->dlpi_state != DL_IDLE) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ, DL_OUTSTATE, 0); - return; - } - - // Check if we are unbinding from an address we are bound to - if (length == k8022SAPLength) { - if ((*sap & 1) && (*sap != kIPXSAP)) { - if (the_stream->dlsap <= kMax8022SAP) - the_stream->ClearGroupSAP(*sap); - else - error = DL_UNSUPPORTED; - } else - error = DL_BADADDR; - } else if (length == k8022SNAPLength) { - if (the_stream->dlsap == kSNAPSAP) { - if (the_stream->flags & kSnapStream) { - if (memcmp(the_stream->snap, sap, length) != 0) - error = DL_BADADDR; - } else - error = DL_BADADDR; - } else - error = DL_UNSUPPORTED; - } - if (error) { - DLPI_error_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ, error, 0); - return; - } - - // Stream is no longer bound to SNAP - the_stream->flags &= ~kSnapStream; - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_SUBS_UNBIND_REQ); - return; -} - - -/* - * Handles DL_ENABMULTI_REQ (enable multicast address) - */ - -static void DLPI_enable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_enabmulti_req_t* req = (dl_enabmulti_req_t*)(void *)mp->b_rptr; - uint8 *reqaddr = (uint8 *)(mp->b_rptr + req->dl_addr_offset); - D(bug(" DLPI_enable_multi(%p,%p) addr %02x%02x%02x%02x%02x%02x\n", the_stream, mp, reqaddr[0], reqaddr[1], reqaddr[2], reqaddr[3], reqaddr[4], reqaddr[5])); - - // Address must be a multicast address - if (get_address_type(reqaddr) != keaMulticast) { - DLPI_error_ack(the_stream, q, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Address already in multicast list? - if (the_stream->IsMulticastRegistered(reqaddr)) { - DLPI_error_ack(the_stream, q, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Tell add-on to enable multicast address - AO_enable_multicast(Host2MacAddr((uint8 *)reqaddr)); - - // Add new address to multicast list - uint8 *addr = Mac2HostAddr(Mac_sysalloc(kEnetPhysicalAddressLength)); - OTCopy48BitAddress(reqaddr, addr); - the_stream->AddMulticast(addr); - - // On receive now check multicast packets - the_stream->flags |= kAcceptMulticasts; - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_ENABMULTI_REQ); - return; -} - - -/* - * Handles DL_DISABMULTI_REQ (disable multicast address) - */ - -static void DLPI_disable_multi(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - dl_disabmulti_req_t *req = (dl_disabmulti_req_t*)(void *)mp->b_rptr; - uint8 *reqaddr = (uint8 *)(mp->b_rptr + req->dl_addr_offset); - D(bug(" DLPI_disable_multi(%p,%p) addr %02x%02x%02x%02x%02x%02x\n", the_stream, mp, reqaddr[0], reqaddr[1], reqaddr[2], reqaddr[3], reqaddr[4], reqaddr[5])); - - // Address must be a multicast address - if (get_address_type(reqaddr) != keaMulticast) { - DLPI_error_ack(the_stream, q, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Find address in multicast list - uint8 *addr = the_stream->IsMulticastRegistered(reqaddr); - if (addr == NULL) { - DLPI_error_ack(the_stream, q, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0); - return; - } - - // Found, then remove - the_stream->RemoveMulticast(addr); - Mac_sysfree(Host2MacAddr(addr)); - - // Tell add-on to disable multicast address - AO_disable_multicast(Host2MacAddr((uint8 *)reqaddr)); - - // No longer check multicast packets if no multicast addresses are registered - if (the_stream->multicast_list == NULL) - the_stream->flags &= ~kAcceptMulticasts; - - // Send reply - DLPI_ok_ack(the_stream, q, mp, DL_DISABMULTI_REQ); - return; -} - - -/* - * Handle DL_UNITDATA_REQ (transmit packet) - */ - -static void DLPI_unit_data(DLPIStream *the_stream, queue_t *q, mblk_t *mp) -{ - D(bug(" DLPI_unit_data(%p,%p)\n", the_stream, mp)); - dl_unitdata_req_t *req = (dl_unitdata_req_t *)(void *)mp->b_rptr; - - // Stream must be idle - if (the_stream->dlpi_state != DL_IDLE) { - - // Not idle, send error response - dl_uderror_ind_t *errp; - mblk_t *bp; - - int i = sizeof(dl_uderror_ind_t) + req->dl_dest_addr_length; - if ((bp = allocb(i, BPRI_HI)) == NULL) { - freemsg(mp); - return; - } - bp->b_datap->db_type = M_PROTO; - errp = (dl_uderror_ind_t *)(void *)bp->b_wptr; - errp->dl_primitive = DL_UDERROR_IND; - errp->dl_errno = DL_OUTSTATE; - errp->dl_unix_errno = 0; - errp->dl_dest_addr_length = req->dl_dest_addr_length; - errp->dl_dest_addr_offset = sizeof(dl_uderror_ind_t); - bp->b_wptr += sizeof(dl_uderror_ind_t); - memcpy((uint8 *)bp->b_wptr, ((uint8 *)req) + req->dl_dest_addr_offset, req->dl_dest_addr_length); - bp->b_wptr += req->dl_dest_addr_length; - qreply(q, bp); - - freemsg(mp); - return; - } - - // Build packet header and transmit packet - if ((mp = build_tx_packet_header(the_stream, mp, false)) != NULL) - transmit_packet(mp); -} - - -/* - * Ethernet packet allocator - */ - -#if SIZEOF_VOID_P != 4 || REAL_ADDRESSING == 0 -static uint32 ether_packet = 0; // Ethernet packet (cached allocation) -static uint32 n_ether_packets = 0; // Number of ethernet packets allocated so far (should be at most 1) - -EthernetPacket::EthernetPacket() -{ - ++n_ether_packets; - if (ether_packet && n_ether_packets == 1) - packet = ether_packet; - else { - packet = Mac_sysalloc(1516); - assert(packet != 0); - Mac_memset(packet, 0, 1516); - if (ether_packet == 0) - ether_packet = packet; - } -} - -EthernetPacket::~EthernetPacket() -{ - --n_ether_packets; - if (packet != ether_packet) - Mac_sysfree(packet); - if (n_ether_packets > 0) { - bug("WARNING: Nested allocation of ethernet packets!\n"); - } -} -#endif diff --git a/SheepShaver/src/extfs.cpp b/SheepShaver/src/extfs.cpp deleted file mode 120000 index 62314724..00000000 --- a/SheepShaver/src/extfs.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/extfs.cpp \ No newline at end of file diff --git a/SheepShaver/src/gfxaccel.cpp b/SheepShaver/src/gfxaccel.cpp deleted file mode 100644 index ed65e5d8..00000000 --- a/SheepShaver/src/gfxaccel.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - * gfxaccel.cpp - Generic Native QuickDraw acceleration - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "prefs.h" -#include "video.h" -#include "video_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -/* - * Utility functions - */ - -// Return bytes per pixel for requested depth -static inline int bytes_per_pixel(int depth) -{ - int bpp; - switch (depth) { - case 8: - bpp = 1; - break; - case 15: case 16: - bpp = 2; - break; - case 24: case 32: - bpp = 4; - break; - default: - abort(); - } - return bpp; -} - -// Pass-through dirty areas to redraw functions -static inline void NQD_set_dirty_area(uint32 p) -{ - if (ReadMacInt32(p + acclDestBaseAddr) == screen_base) { - int16 x = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 w = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 h = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - video_set_dirty_area(x, y, w, h); - } -} - - -/* - * Rectangle inversion - */ - -template< int bpp > -static inline void do_invrect(uint8 *dest, uint32 length) -{ -#define INVERT_1(PTR, OFS) ((uint8 *)(PTR))[OFS] = ~((uint8 *)(PTR))[OFS] -#define INVERT_2(PTR, OFS) ((uint16 *)(PTR))[OFS] = ~((uint16 *)(PTR))[OFS] -#define INVERT_4(PTR, OFS) ((uint32 *)(PTR))[OFS] = ~((uint32 *)(PTR))[OFS] -#define INVERT_8(PTR, OFS) ((uint64 *)(PTR))[OFS] = ~((uint64 *)(PTR))[OFS] - -#ifndef UNALIGNED_PROFITABLE - // Align on 16-bit boundaries - if (bpp < 16 && (((uintptr)dest) & 1)) { - INVERT_1(dest, 0); - dest += 1; length -= 1; - } - - // Align on 32-bit boundaries - if (bpp < 32 && (((uintptr)dest) & 2)) { - INVERT_2(dest, 0); - dest += 2; length -= 2; - } -#endif - - // Invert 8-byte words - if (length >= 8) { - const int r = (length / 8) % 8; - dest += r * 8; - - int n = ((length / 8) + 7) / 8; - switch (r) { - case 0: do { - dest += 64; - INVERT_8(dest, -8); - case 7: INVERT_8(dest, -7); - case 6: INVERT_8(dest, -6); - case 5: INVERT_8(dest, -5); - case 4: INVERT_8(dest, -4); - case 3: INVERT_8(dest, -3); - case 2: INVERT_8(dest, -2); - case 1: INVERT_8(dest, -1); - } while (--n > 0); - } - } - - // 32-bit cell to invert? - if (length & 4) { - INVERT_4(dest, 0); - if (bpp <= 16) - dest += 4; - } - - // 16-bit cell to invert? - if (bpp <= 16 && (length & 2)) { - INVERT_2(dest, 0); - if (bpp <= 8) - dest += 2; - } - - // 8-bit cell to invert? - if (bpp <= 8 && (length & 1)) - INVERT_1(dest, 0); - -#undef INVERT_1 -#undef INVERT_2 -#undef INVERT_4 -#undef INVERT_8 -} - -void NQD_invrect(uint32 p) -{ - D(bug("accl_invrect %08x\n", p)); - - // Get inversion parameters - int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" width %d, height %d, bytes_per_row %d\n", width, height, (int32)ReadMacInt32(p + acclDestRowBytes))); - - //!!?? pen_mode == 14 - - // And perform the inversion - const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); - const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); - width *= bpp; - switch (bpp) { - case 1: - for (int i = 0; i < height; i++) { - do_invrect<8>(dest, width); - dest += dest_row_bytes; - } - break; - case 2: - for (int i = 0; i < height; i++) { - do_invrect<16>(dest, width); - dest += dest_row_bytes; - } - break; - case 4: - for (int i = 0; i < height; i++) { - do_invrect<32>(dest, width); - dest += dest_row_bytes; - } - break; - } -} - - -/* - * Rectangle filling - */ - -template< int bpp > -static inline void do_fillrect(uint8 *dest, uint32 color, uint32 length) -{ -#define FILL_1(PTR, OFS, VAL) ((uint8 *)(PTR))[OFS] = (VAL) -#define FILL_2(PTR, OFS, VAL) ((uint16 *)(PTR))[OFS] = (VAL) -#define FILL_4(PTR, OFS, VAL) ((uint32 *)(PTR))[OFS] = (VAL) -#define FILL_8(PTR, OFS, VAL) ((uint64 *)(PTR))[OFS] = (VAL) - -#ifndef UNALIGNED_PROFITABLE - // Align on 16-bit boundaries - if (bpp < 16 && (((uintptr)dest) & 1)) { - FILL_1(dest, 0, color); - dest += 1; length -= 1; - } - - // Align on 32-bit boundaries - if (bpp < 32 && (((uintptr)dest) & 2)) { - FILL_2(dest, 0, color); - dest += 2; length -= 2; - } -#endif - - // Fill 8-byte words - if (length >= 8) { - const uint64 c = (((uint64)color) << 32) | color; - const int r = (length / 8) % 8; - dest += r * 8; - - int n = ((length / 8) + 7) / 8; - switch (r) { - case 0: do { - dest += 64; - FILL_8(dest, -8, c); - case 7: FILL_8(dest, -7, c); - case 6: FILL_8(dest, -6, c); - case 5: FILL_8(dest, -5, c); - case 4: FILL_8(dest, -4, c); - case 3: FILL_8(dest, -3, c); - case 2: FILL_8(dest, -2, c); - case 1: FILL_8(dest, -1, c); - } while (--n > 0); - } - } - - // 32-bit cell to fill? - if (length & 4) { - FILL_4(dest, 0, color); - if (bpp <= 16) - dest += 4; - } - - // 16-bit cell to fill? - if (bpp <= 16 && (length & 2)) { - FILL_2(dest, 0, color); - if (bpp <= 8) - dest += 2; - } - - // 8-bit cell to fill? - if (bpp <= 8 && (length & 1)) - FILL_1(dest, 0, color); - -#undef FILL_1 -#undef FILL_2 -#undef FILL_4 -#undef FILL_8 -} - -void NQD_fillrect(uint32 p) -{ - D(bug("accl_fillrect %08x\n", p)); - - // Get filling parameters - int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - uint32 color = htonl(ReadMacInt32(p + acclPenMode) == 8 ? ReadMacInt32(p + acclForePen) : ReadMacInt32(p + acclBackPen)); - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" width %d, height %d\n", width, height)); - D(bug(" bytes_per_row %d color %08x\n", (int32)ReadMacInt32(p + acclDestRowBytes), color)); - - // And perform the fill - const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); - const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); - width *= bpp; - switch (bpp) { - case 1: - for (int i = 0; i < height; i++) { - memset(dest, color, width); - dest += dest_row_bytes; - } - break; - case 2: - for (int i = 0; i < height; i++) { - do_fillrect<16>(dest, color, width); - dest += dest_row_bytes; - } - break; - case 4: - for (int i = 0; i < height; i++) { - do_fillrect<32>(dest, color, width); - dest += dest_row_bytes; - } - break; - } -} - -bool NQD_fillrect_hook(uint32 p) -{ - D(bug("accl_fillrect_hook %08x\n", p)); - NQD_set_dirty_area(p); - - // Check if we can accelerate this fillrect - if (ReadMacInt32(p + 0x284) != 0 && ReadMacInt32(p + acclDestPixelSize) >= 8) { - const int transfer_mode = ReadMacInt32(p + acclTransferMode); - if (transfer_mode == 8) { - // Fill - WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_NQD_FILLRECT)); - return true; - } - else if (transfer_mode == 10) { - // Invert - WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_NQD_INVRECT)); - return true; - } - } - return false; -} - - -/* - * Isomorphic rectangle blitting - */ - -void NQD_bitblt(uint32 p) -{ - D(bug("accl_bitblt %08x\n", p)); - - // Get blitting parameters - int16 src_X = (int16)ReadMacInt16(p + acclSrcRect + 2) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 2); - int16 src_Y = (int16)ReadMacInt16(p + acclSrcRect + 0) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 0); - int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - D(bug(" src addr %08x, dest addr %08x\n", ReadMacInt32(p + acclSrcBaseAddr), ReadMacInt32(p + acclDestBaseAddr))); - D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); - D(bug(" width %d, height %d\n", width, height)); - - // And perform the blit - const int bpp = bytes_per_pixel(ReadMacInt32(p + acclSrcPixelSize)); - width *= bpp; - if ((int32)ReadMacInt32(p + acclSrcRowBytes) > 0) { - const int src_row_bytes = (int32)ReadMacInt32(p + acclSrcRowBytes); - const int dst_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + (src_Y * src_row_bytes) + (src_X * bpp)); - uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dst_row_bytes) + (dest_X * bpp)); - for (int i = 0; i < height; i++) { - memmove(dst, src, width); - src += src_row_bytes; - dst += dst_row_bytes; - } - } - else { - const int src_row_bytes = -(int32)ReadMacInt32(p + acclSrcRowBytes); - const int dst_row_bytes = -(int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + ((src_Y + height - 1) * src_row_bytes) + (src_X * bpp)); - uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + ((dest_Y + height - 1) * dst_row_bytes) + (dest_X * bpp)); - for (int i = height - 1; i >= 0; i--) { - memmove(dst, src, width); - src -= src_row_bytes; - dst -= dst_row_bytes; - } - } -} - -/* - BitBlt transfer modes: - 0 : srcCopy - 1 : srcOr - 2 : srcXor - 3 : srcBic - 4 : notSrcCopy - 5 : notSrcOr - 6 : notSrcXor - 7 : notSrcBic - 32 : blend - 33 : addPin - 34 : addOver - 35 : subPin - 36 : transparent - 37 : adMax - 38 : subOver - 39 : adMin - 50 : hilite -*/ - -bool NQD_bitblt_hook(uint32 p) -{ - D(bug("accl_draw_hook %08x\n", p)); - NQD_set_dirty_area(p); - - // Check if we can accelerate this bitblt - if (ReadMacInt32(p + 0x018) + ReadMacInt32(p + 0x128) == 0 && - ReadMacInt32(p + 0x130) == 0 && - ReadMacInt32(p + acclSrcPixelSize) >= 8 && - ReadMacInt32(p + acclSrcPixelSize) == ReadMacInt32(p + acclDestPixelSize) && - (int32)(ReadMacInt32(p + acclSrcRowBytes) ^ ReadMacInt32(p + acclDestRowBytes)) >= 0 && // same sign? - ReadMacInt32(p + acclTransferMode) == 0 && // srcCopy? - (int32)ReadMacInt32(p + 0x15c) > 0) { - - // Yes, set function pointer - WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_NQD_BITBLT)); - return true; - } - return false; -} - -// Unknown hook -bool NQD_unknown_hook(uint32 arg) -{ - D(bug("accl_unknown_hook %08x\n", arg)); - NQD_set_dirty_area(arg); - - return false; -} - -// Wait for graphics operation to finish -bool NQD_sync_hook(uint32 arg) -{ - D(bug("accl_sync_hook %08x\n", arg)); - return true; -} - - -/* - * Install Native QuickDraw acceleration hooks - */ - -void VideoInstallAccel(void) -{ - // Install acceleration hooks - if (PrefsFindBool("gfxaccel")) { - D(bug("Video: Installing acceleration hooks\n")); - uint32 base; - - SheepVar bitblt_hook_info(sizeof(accl_hook_info)); - base = bitblt_hook_info.addr(); - WriteMacInt32(base + 0, NativeTVECT(NATIVE_NQD_BITBLT_HOOK)); - WriteMacInt32(base + 4, NativeTVECT(NATIVE_NQD_SYNC_HOOK)); - WriteMacInt32(base + 8, ACCL_BITBLT); - NQDMisc(6, bitblt_hook_info.addr()); - - SheepVar fillrect_hook_info(sizeof(accl_hook_info)); - base = fillrect_hook_info.addr(); - WriteMacInt32(base + 0, NativeTVECT(NATIVE_NQD_FILLRECT_HOOK)); - WriteMacInt32(base + 4, NativeTVECT(NATIVE_NQD_SYNC_HOOK)); - WriteMacInt32(base + 8, ACCL_FILLRECT); - NQDMisc(6, fillrect_hook_info.addr()); - - for (int op = 0; op < 8; op++) { - switch (op) { - case ACCL_BITBLT: - case ACCL_FILLRECT: - continue; - } - SheepVar unknown_hook_info(sizeof(accl_hook_info)); - base = unknown_hook_info.addr(); - WriteMacInt32(base + 0, NativeTVECT(NATIVE_NQD_UNKNOWN_HOOK)); - WriteMacInt32(base + 4, NativeTVECT(NATIVE_NQD_SYNC_HOOK)); - WriteMacInt32(base + 8, op); - NQDMisc(6, unknown_hook_info.addr()); - } - } -} diff --git a/SheepShaver/src/include/about_window.h b/SheepShaver/src/include/about_window.h deleted file mode 100644 index 6c2d8d82..00000000 --- a/SheepShaver/src/include/about_window.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * about_window.h - "About" window - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ABOUT_WINDOW_H -#define ABOUT_WINDOW_H - -extern void OpenAboutWindow(void); - -#endif diff --git a/SheepShaver/src/include/adb.h b/SheepShaver/src/include/adb.h deleted file mode 120000 index e65ef4a4..00000000 --- a/SheepShaver/src/include/adb.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/adb.h \ No newline at end of file diff --git a/SheepShaver/src/include/audio.h b/SheepShaver/src/include/audio.h deleted file mode 120000 index 73ebba7e..00000000 --- a/SheepShaver/src/include/audio.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/audio.h \ No newline at end of file diff --git a/SheepShaver/src/include/audio_defs.h b/SheepShaver/src/include/audio_defs.h deleted file mode 120000 index 04523f25..00000000 --- a/SheepShaver/src/include/audio_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/audio_defs.h \ No newline at end of file diff --git a/SheepShaver/src/include/cdrom.h b/SheepShaver/src/include/cdrom.h deleted file mode 120000 index d7300f7a..00000000 --- a/SheepShaver/src/include/cdrom.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/cdrom.h \ No newline at end of file diff --git a/SheepShaver/src/include/clip.h b/SheepShaver/src/include/clip.h deleted file mode 120000 index 23f10c02..00000000 --- a/SheepShaver/src/include/clip.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/clip.h \ No newline at end of file diff --git a/SheepShaver/src/include/cpu_emulation.h b/SheepShaver/src/include/cpu_emulation.h deleted file mode 100644 index aa4b7a70..00000000 --- a/SheepShaver/src/include/cpu_emulation.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * cpu_emulation.h - Definitions for CPU emulation and Mac memory access - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CPU_EMULATION_H -#define CPU_EMULATION_H - - -/* - * Memory system - */ - -// Constants -const uint32 ROM_SIZE = 0x400000; // Size of ROM file -const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area -const uintptr DR_EMULATOR_BASE = 0x68070000; // Address of DR emulator code -const uint32 DR_EMULATOR_SIZE = 0x10000; // Size of DR emulator code -const uintptr DR_CACHE_BASE = 0x69000000; // Address of DR cache -const uint32 DR_CACHE_SIZE = 0x80000; // Size of DR Cache - -const uintptr KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data -const uintptr KERNEL_DATA2_BASE = 0x5fffe000; // Alternate address of Kernel Data -const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area - -// MacOS 68k Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - -// MacOS Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - -// RAM and ROM pointers (allocated and set by main_*.cpp) -extern uint32 RAMBase; // Base address of Mac RAM -extern uint32 RAMSize; // Size address of Mac RAM -extern uint8 *RAMBaseHost; // Base address of Mac RAM (host address space) - -extern uint32 ROMBase; // Base address of Mac ROM -extern uint8 *ROMBaseHost; // Base address of Mac ROM (host address space) - -// Mac memory access functions -#if EMULATED_PPC -#include "cpu/vm.hpp" -static inline uint32 ReadMacInt8(uint32 addr) {return vm_read_memory_1(addr);} -static inline void WriteMacInt8(uint32 addr, uint32 v) {vm_write_memory_1(addr, v);} -static inline uint32 ReadMacInt16(uint32 addr) {return vm_read_memory_2(addr);} -static inline void WriteMacInt16(uint32 addr, uint32 v) {vm_write_memory_2(addr, v);} -static inline uint32 ReadMacInt32(uint32 addr) {return vm_read_memory_4(addr);} -static inline void WriteMacInt32(uint32 addr, uint32 v) {vm_write_memory_4(addr, v);} -static inline uint64 ReadMacInt64(uint32 addr) {return vm_read_memory_8(addr);} -static inline void WriteMacInt64(uint32 addr, uint64 v) {vm_write_memory_8(addr, v);} -static inline uint32 Host2MacAddr(uint8 *addr) {return vm_do_get_virtual_address(addr);} -static inline uint8 *Mac2HostAddr(uint32 addr) {return vm_do_get_real_address(addr);} -static inline void *Mac_memset(uint32 addr, int c, size_t n) {return vm_memset(addr, c, n);} -static inline void *Mac2Host_memcpy(void *dest, uint32 src, size_t n) {return vm_memcpy(dest, src, n);} -static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {return vm_memcpy(dest, src, n);} -static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return vm_memcpy(dest, src, n);} -#else -static inline uint32 ReadMacInt8(uint32 addr) {return *(uint8 *)addr;} -static inline void WriteMacInt8(uint32 addr, uint32 b) {*(uint8 *)addr = b;} -static inline uint32 ReadMacInt16(uint32 addr) {return *(uint16 *)addr;} -static inline uint32 ReadMacInt32(uint32 addr) {return *(uint32 *)addr;} -static inline uint64 ReadMacInt64(uint32 addr) {return *(uint64 *)addr;} -static inline void WriteMacInt16(uint32 addr, uint32 w) {*(uint16 *)addr = w;} -static inline void WriteMacInt32(uint32 addr, uint32 l) {*(uint32 *)addr = l;} -static inline void WriteMacInt64(uint32 addr, uint64 ll) {*(uint64 *)addr = ll;} -static inline uint32 Host2MacAddr(uint8 *addr) {return (uint32)addr;} -static inline uint8 *Mac2HostAddr(uint32 addr) {return (uint8 *)addr;} -static inline void *Mac_memset(uint32 addr, int c, size_t n) {return memset(Mac2HostAddr(addr), c, n);} -static inline void *Mac2Host_memcpy(void *dest, uint32 src, size_t n) {return memcpy(dest, Mac2HostAddr(src), n);} -static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {return memcpy(Mac2HostAddr(dest), src, n);} -static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return memcpy(Mac2HostAddr(dest), Mac2HostAddr(src), n);} -#endif - - -/* - * 680x0 and PPC emulation - */ - -// 68k procedure helper to write a big endian 16-bit word -#ifdef WORDS_BIGENDIAN -#define PW(W) W -#else -#define PW(X) ((((X) >> 8) & 0xff) | (((X) & 0xff) << 8)) -#endif - -// PowerPC procedure helper to write a big-endian 32-bit word -#ifdef WORDS_BIGENDIAN -#define PL(X) X -#else -#define PL(X) \ - ((((X) & 0xff000000) >> 24) | (((X) & 0x00ff0000) >> 8) | \ - (((X) & 0x0000ff00) << 8) | (((X) & 0x000000ff) << 24)) -#endif - -struct M68kRegisters; -extern void Execute68k(uint32, M68kRegisters *r); // Execute 68k subroutine from EMUL_OP routine, must be ended with RTS -extern void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute 68k A-Trap from EMUL_OP routine -#if EMULATED_PPC -extern void FlushCodeCache(uintptr start, uintptr end); // Invalidate emulator caches -#endif -extern void ExecuteNative(int selector); // Execute native code from EMUL_OP routine (real mode switch) - -#endif diff --git a/SheepShaver/src/include/debug.h b/SheepShaver/src/include/debug.h deleted file mode 120000 index 6a0dd40c..00000000 --- a/SheepShaver/src/include/debug.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/debug.h \ No newline at end of file diff --git a/SheepShaver/src/include/disk.h b/SheepShaver/src/include/disk.h deleted file mode 120000 index d785c55d..00000000 --- a/SheepShaver/src/include/disk.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/disk.h \ No newline at end of file diff --git a/SheepShaver/src/include/emul_op.h b/SheepShaver/src/include/emul_op.h deleted file mode 100644 index 9f9a323e..00000000 --- a/SheepShaver/src/include/emul_op.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * emul_op.h - 68k opcodes for ROM patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef EMUL_OP_H -#define EMUL_OP_H - -// PowerPC opcodes -const uint32 POWERPC_NOP = 0x60000000; -const uint32 POWERPC_ILLEGAL = 0x00000000; -const uint32 POWERPC_BLR = 0x4e800020; -const uint32 POWERPC_BCTR = 0x4e800420; -const uint32 POWERPC_EMUL_OP = 0x18000000; // Base opcode for EMUL_OP opcodes (only used with PPC emulation) - -// 68k opcodes -const uint16 M68K_ILLEGAL = 0x4afc; -const uint16 M68K_NOP = 0x4e71; -const uint16 M68K_RTS = 0x4e75; -const uint16 M68K_RTD = 0x4e74; -const uint16 M68K_JMP = 0x4ef9; -const uint16 M68K_JMP_A0 = 0x4ed0; -const uint16 M68K_JSR = 0x4eb9; -const uint16 M68K_JSR_A0 = 0x4e90; -enum { // Selectors for EMUL_OP opcodes - OP_BREAK, OP_XPRAM1, OP_XPRAM2, OP_XPRAM3, OP_NVRAM1, OP_NVRAM2, OP_NVRAM3, - OP_FIX_MEMTOP, OP_FIX_MEMSIZE, OP_FIX_BOOTSTACK, - OP_SONY_OPEN, OP_SONY_PRIME, OP_SONY_CONTROL, OP_SONY_STATUS, - OP_DISK_OPEN, OP_DISK_PRIME, OP_DISK_CONTROL, OP_DISK_STATUS, - OP_CDROM_OPEN, OP_CDROM_PRIME, OP_CDROM_CONTROL, OP_CDROM_STATUS, - OP_AUDIO_DISPATCH, OP_SOUNDIN_OPEN, OP_SOUNDIN_PRIME, OP_SOUNDIN_CONTROL, OP_SOUNDIN_STATUS, OP_SOUNDIN_CLOSE, - OP_ADBOP, OP_INSTIME, OP_RMVTIME, OP_PRIMETIME, OP_MICROSECONDS, OP_ZERO_SCRAP, OP_PUT_SCRAP, OP_GET_SCRAP, - OP_DEBUG_STR, OP_INSTALL_DRIVERS, OP_NAME_REGISTRY, OP_RESET, OP_IRQ, - OP_SCSI_DISPATCH, OP_SCSI_ATOMIC, - OP_CHECK_SYSV, OP_NTRB_17_PATCH, OP_NTRB_17_PATCH2, OP_NTRB_17_PATCH3, OP_NTRB_17_PATCH4, OP_CHECKLOAD, - OP_EXTFS_COMM, OP_EXTFS_HFS, OP_IDLE_TIME, OP_IDLE_TIME_2, - OP_MAX -}; -const uint16 M68K_EMUL_RETURN = 0xfe40; // Extended opcodes -const uint16 M68K_EXEC_RETURN = 0xfe41; -const uint16 M68K_EXEC_NATIVE = 0xfe42; -const uint16 M68K_EMUL_BREAK = 0xfe43; -const uint16 M68K_EMUL_OP_XPRAM1 = M68K_EMUL_BREAK + OP_XPRAM1; -const uint16 M68K_EMUL_OP_XPRAM2 = M68K_EMUL_BREAK + OP_XPRAM2; -const uint16 M68K_EMUL_OP_XPRAM3 = M68K_EMUL_BREAK + OP_XPRAM3; -const uint16 M68K_EMUL_OP_NVRAM1 = M68K_EMUL_BREAK + OP_NVRAM1; -const uint16 M68K_EMUL_OP_NVRAM2 = M68K_EMUL_BREAK + OP_NVRAM2; -const uint16 M68K_EMUL_OP_NVRAM3 = M68K_EMUL_BREAK + OP_NVRAM3; -const uint16 M68K_EMUL_OP_FIX_MEMTOP = M68K_EMUL_BREAK + OP_FIX_MEMTOP; -const uint16 M68K_EMUL_OP_FIX_MEMSIZE = M68K_EMUL_BREAK + OP_FIX_MEMSIZE; -const uint16 M68K_EMUL_OP_FIX_BOOTSTACK = M68K_EMUL_BREAK + OP_FIX_BOOTSTACK; -const uint16 M68K_EMUL_OP_SONY_OPEN = M68K_EMUL_BREAK + OP_SONY_OPEN; -const uint16 M68K_EMUL_OP_SONY_PRIME = M68K_EMUL_BREAK + OP_SONY_PRIME; -const uint16 M68K_EMUL_OP_SONY_CONTROL = M68K_EMUL_BREAK + OP_SONY_CONTROL; -const uint16 M68K_EMUL_OP_SONY_STATUS = M68K_EMUL_BREAK + OP_SONY_STATUS; -const uint16 M68K_EMUL_OP_DISK_OPEN = M68K_EMUL_BREAK + OP_DISK_OPEN; -const uint16 M68K_EMUL_OP_DISK_PRIME = M68K_EMUL_BREAK + OP_DISK_PRIME; -const uint16 M68K_EMUL_OP_DISK_CONTROL = M68K_EMUL_BREAK + OP_DISK_CONTROL; -const uint16 M68K_EMUL_OP_DISK_STATUS = M68K_EMUL_BREAK + OP_DISK_STATUS; -const uint16 M68K_EMUL_OP_CDROM_OPEN = M68K_EMUL_BREAK + OP_CDROM_OPEN; -const uint16 M68K_EMUL_OP_CDROM_PRIME = M68K_EMUL_BREAK + OP_CDROM_PRIME; -const uint16 M68K_EMUL_OP_CDROM_CONTROL = M68K_EMUL_BREAK + OP_CDROM_CONTROL; -const uint16 M68K_EMUL_OP_CDROM_STATUS = M68K_EMUL_BREAK + OP_CDROM_STATUS; -const uint16 M68K_EMUL_OP_AUDIO_DISPATCH = M68K_EMUL_BREAK + OP_AUDIO_DISPATCH; -const uint16 M68K_EMUL_OP_SOUNDIN_OPEN = M68K_EMUL_BREAK + OP_SOUNDIN_OPEN; -const uint16 M68K_EMUL_OP_SOUNDIN_CLOSE = M68K_EMUL_BREAK + OP_SOUNDIN_CLOSE; -const uint16 M68K_EMUL_OP_SOUNDIN_PRIME = M68K_EMUL_BREAK + OP_SOUNDIN_PRIME; -const uint16 M68K_EMUL_OP_SOUNDIN_CONTROL = M68K_EMUL_BREAK + OP_SOUNDIN_CONTROL; -const uint16 M68K_EMUL_OP_SOUNDIN_STATUS = M68K_EMUL_BREAK + OP_SOUNDIN_STATUS; -const uint16 M68K_EMUL_OP_ADBOP = M68K_EMUL_BREAK + OP_ADBOP; -const uint16 M68K_EMUL_OP_INSTIME = M68K_EMUL_BREAK + OP_INSTIME; -const uint16 M68K_EMUL_OP_RMVTIME = M68K_EMUL_BREAK + OP_RMVTIME; -const uint16 M68K_EMUL_OP_PRIMETIME = M68K_EMUL_BREAK + OP_PRIMETIME; -const uint16 M68K_EMUL_OP_MICROSECONDS = M68K_EMUL_BREAK + OP_MICROSECONDS; -const uint16 M68K_EMUL_OP_ZERO_SCRAP = M68K_EMUL_BREAK + OP_ZERO_SCRAP; -const uint16 M68K_EMUL_OP_PUT_SCRAP = M68K_EMUL_BREAK + OP_PUT_SCRAP; -const uint16 M68K_EMUL_OP_GET_SCRAP = M68K_EMUL_BREAK + OP_GET_SCRAP; -const uint16 M68K_EMUL_OP_DEBUG_STR = M68K_EMUL_BREAK + OP_DEBUG_STR; -const uint16 M68K_EMUL_OP_INSTALL_DRIVERS = M68K_EMUL_BREAK + OP_INSTALL_DRIVERS; -const uint16 M68K_EMUL_OP_NAME_REGISTRY = M68K_EMUL_BREAK + OP_NAME_REGISTRY; -const uint16 M68K_EMUL_OP_RESET = M68K_EMUL_BREAK + OP_RESET; -const uint16 M68K_EMUL_OP_IRQ = M68K_EMUL_BREAK + OP_IRQ; -const uint16 M68K_EMUL_OP_SCSI_DISPATCH = M68K_EMUL_BREAK + OP_SCSI_DISPATCH; -const uint16 M68K_EMUL_OP_SCSI_ATOMIC = M68K_EMUL_BREAK + OP_SCSI_ATOMIC; -const uint16 M68K_EMUL_OP_CHECK_SYSV = M68K_EMUL_BREAK + OP_CHECK_SYSV; -const uint16 M68K_EMUL_OP_NTRB_17_PATCH = M68K_EMUL_BREAK + OP_NTRB_17_PATCH; -const uint16 M68K_EMUL_OP_NTRB_17_PATCH2 = M68K_EMUL_BREAK + OP_NTRB_17_PATCH2; -const uint16 M68K_EMUL_OP_NTRB_17_PATCH3 = M68K_EMUL_BREAK + OP_NTRB_17_PATCH3; -const uint16 M68K_EMUL_OP_NTRB_17_PATCH4 = M68K_EMUL_BREAK + OP_NTRB_17_PATCH4; -const uint16 M68K_EMUL_OP_CHECKLOAD = M68K_EMUL_BREAK + OP_CHECKLOAD; -const uint16 M68K_EMUL_OP_EXTFS_COMM = M68K_EMUL_BREAK + OP_EXTFS_COMM; -const uint16 M68K_EMUL_OP_EXTFS_HFS = M68K_EMUL_BREAK + OP_EXTFS_HFS; -const uint16 M68K_EMUL_OP_IDLE_TIME = M68K_EMUL_BREAK + OP_IDLE_TIME; -const uint16 M68K_EMUL_OP_IDLE_TIME_2 = M68K_EMUL_BREAK + OP_IDLE_TIME_2; - -extern "C" void EmulOp(M68kRegisters *r, uint32 pc, int selector); - -#endif diff --git a/SheepShaver/src/include/ether.h b/SheepShaver/src/include/ether.h deleted file mode 100644 index b46a08e6..00000000 --- a/SheepShaver/src/include/ether.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ether.h - SheepShaver Ethernet Device Driver - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ETHER_H -#define ETHER_H - -struct queue; -struct msgb; -typedef struct queue queue_t; -typedef struct msgb mblk_t; - -extern uint8 InitStreamModule(void *theID); -extern void TerminateStreamModule(void); -extern int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds); -extern int ether_close(queue_t *rdq, int flag, void *creds); -extern int ether_wput(queue_t *q, mblk_t *mp); -extern int ether_rsrv(queue_t *q); - -// System specific and internal functions/data -extern void EtherInit(void); -extern void EtherExit(void); - -extern void EtherIRQ(void); - -extern void AO_get_ethernet_address(uint32 addr); -extern void AO_enable_multicast(uint32 addr); -extern void AO_disable_multicast(uint32 addr); -extern void AO_transmit_packet(uint32 mp); - -extern mblk_t *allocb(size_t size, int pri); -extern void OTEnterInterrupt(void); -extern void OTLeaveInterrupt(void); - -extern void ether_dispatch_packet(uint32 p, uint32 length); -extern void ether_packet_received(mblk_t *mp); - -extern bool ether_driver_opened; - -// Ethernet packet allocator (optimized for 32-bit platforms in real addressing mode) -class EthernetPacket { -#if SIZEOF_VOID_P == 4 && REAL_ADDRESSING - uint8 packet[1516]; - public: - uint32 addr(void) const { return (uint32)packet; } -#else - uint32 packet; - public: - EthernetPacket(); - ~EthernetPacket(); - uint32 addr(void) const { return packet; } -#endif -}; - -// Copy packet data from message block to linear buffer (must hold at -// least 1514 bytes), returns packet length -static inline int ether_msgb_to_buffer(uint32 mp, uint8 *p) -{ - int len = 0; - while (mp) { - uint32 size = ReadMacInt32(mp + 16) - ReadMacInt32(mp + 12); - Mac2Host_memcpy(p, ReadMacInt32(mp + 12), size); - len += size; - p += size; - mp = ReadMacInt32(mp + 8); - } - return len; -} - -extern int32 num_wput; -extern int32 num_error_acks; -extern int32 num_tx_packets; -extern int32 num_tx_raw_packets; -extern int32 num_tx_normal_packets; -extern int32 num_tx_buffer_full; -extern int32 num_rx_packets; -extern int32 num_ether_irq; -extern int32 num_unitdata_ind; -extern int32 num_rx_fastpath; -extern int32 num_rx_no_mem; -extern int32 num_rx_dropped; -extern int32 num_rx_stream_not_ready; -extern int32 num_rx_no_unitdata_mem; - -#endif diff --git a/SheepShaver/src/include/ether_defs.h b/SheepShaver/src/include/ether_defs.h deleted file mode 100644 index 390aee4c..00000000 --- a/SheepShaver/src/include/ether_defs.h +++ /dev/null @@ -1,563 +0,0 @@ -/* - * ether_defs.h - Definitions for DLPI Ethernet Driver - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ETHER_DEFS_H -#define ETHER_DEFS_H - - -#if __MWERKS__ && __POWERPC__ -#define PRAGMA_ALIGN_SUPPORTED 1 -#define PACKED__ -#elif defined __GNUC__ -#define PACKED__ __attribute__ ((packed)) -#elif defined __sgi -#define PRAGMA_PACK_SUPPORTED 1 -#define PACKED__ -#else -#error "Packed attribute or pragma shall be supported" -#endif - - -/* - * Macros - */ - -// Get pointer to the read queue, assumes 'q' is a write queue ptr -#define RD(q) (&q[-1]) - -// Get pointer to the write queue, assumes 'q' is a read queue ptr -#define WR(q) (&q[1]) - -#define OTCompare48BitAddresses(p1, p2) \ - (*(const uint32*)((const uint8*)(p1)) == *(const uint32*)((const uint8*)(p2)) && \ - *(const uint16*)(((const uint8*)(p1))+4) == *(const uint16*)(((const uint8*)(p2))+4) ) - -#define OTCopy48BitAddress(p1, p2) \ - (*(uint32*)((uint8*)(p2)) = *(const uint32*)((const uint8*)(p1)), \ - *(uint16*)(((uint8*)(p2))+4) = *(const uint16*)(((const uint8*)(p1))+4) ) - -#define OTClear48BitAddress(p1) \ - (*(uint32*)((uint8*)(p1)) = 0, \ - *(uint16*)(((uint8*)(p1))+4) = 0 ) - -#define OTCompare8022SNAP(p1, p2) \ - (*(const uint32*)((const uint8*)(p1)) == *(const uint32*)((const uint8*)(p2)) && \ - *(((const uint8*)(p1))+4) == *(((const uint8*)(p2))+4) ) - -#define OTCopy8022SNAP(p1, p2) \ - (*(uint32*)((uint8*)(p2)) = *(const uint32*)((const uint8*)(p1)), \ - *(((uint8*)(p2))+4) = *(((const uint8*)(p1))+4) ) - -#define OTIs48BitBroadcastAddress(p1) \ - (*(uint32*)((uint8*)(p1)) == 0xffffffff && \ - *(uint16*)(((uint8*)(p1))+4) == 0xffff ) - -#define OTSet48BitBroadcastAddress(p1) \ - (*(uint32*)((uint8*)(p1)) = 0xffffffff, \ - *(uint16*)(((uint8*)(p1))+4) = 0xffff ) - -#define OTIs48BitZeroAddress(p1) \ - (*(uint32*)((uint8*)(p1)) == 0 && \ - *(uint16*)(((uint8*)(p1))+4) == 0 ) - - -/* - * Constants - */ - -enum { - // Address and packet lengths - kEnetPhysicalAddressLength = 6, - k8022SAPLength = 1, - k8022DLSAPLength = 2, - k8022SNAPLength = 5, - kMaxBoundAddrLength = 6 + 2 + 5, // addr/SAP/SNAP - kEnetAndSAPAddressLength = kEnetPhysicalAddressLength + k8022DLSAPLength, - kEnetPacketHeaderLength = (2 * kEnetPhysicalAddressLength) + k8022DLSAPLength, - k8022BasicHeaderLength = 3, // SSAP/DSAP/Control - k8022SNAPHeaderLength = k8022SNAPLength + k8022BasicHeaderLength, - kMinDIXSAP = 1501, - kEnetTSDU = 1514, - - // Special addresses - kSNAPSAP = 0xaa, - kMax8022SAP = 0xfe, - k8022GlobalSAP = 0xff, - kIPXSAP = 0xff, - - // DLPI interface states - DL_UNBOUND = 0, - - // Message types - M_DATA = 0, - M_PROTO = 1, - M_IOCTL = 14, - M_IOCACK = 129, - M_IOCNAK = 130, - M_PCPROTO = 131, // priority message - M_FLUSH = 134, - FLUSHDATA = 0, - FLUSHALL = 1, - FLUSHR = 1, - FLUSHW = 2, - FLUSHRW = 3, - - // DLPI primitives - DL_INFO_REQ = 0, - DL_BIND_REQ = 1, - DL_PEER_BIND = 1, - DL_HIERARCHICAL_BIND = 2, - DL_UNBIND_REQ = 2, - DL_INFO_ACK = 3, - DL_BIND_ACK = 4, - DL_ERROR_ACK = 5, - DL_OK_ACK = 6, - DL_UNITDATA_REQ = 7, - DL_UNITDATA_IND = 8, - DL_UDERROR_IND = 9, - DL_SUBS_UNBIND_REQ = 21, - DL_SUBS_BIND_REQ = 27, - DL_SUBS_BIND_ACK = 28, - DL_ENABMULTI_REQ = 29, - DL_DISABMULTI_REQ = 30, - DL_PHYS_ADDR_REQ = 49, - DL_PHYS_ADDR_ACK = 50, - DL_FACT_PHYS_ADDR = 1, - DL_CURR_PHYS_ADDR = 2, - - // DLPI states - DL_IDLE = 3, - - // DLPI error codes - DL_BADADDR = 1, // improper address format - DL_OUTSTATE = 3, // improper state - DL_SYSERR = 4, // UNIX system error - DL_UNSUPPORTED = 7, // service unsupported - DL_BADPRIM = 9, // primitive unknown - DL_NOTSUPPORTED = 18, // primitive not implemented - DL_TOOMANY = 19, // limit exceeded - - // errnos - MAC_ENXIO = 6, - MAC_ENOMEM = 12, - MAC_EINVAL = 22, - - // Various DLPI constants - DL_CLDLS = 2, // connectionless data link service - DL_STYLE1 = 0x500, - DL_VERSION_2 = 2, - DL_CSMACD = 0, - DL_ETHER = 4, - DL_UNKNOWN = -1, - - // ioctl() codes - I_OTSetFramingType = (('O' << 8) | 2), - kOTGetFramingValue = -1, - kOTFramingEthernet = 1, - kOTFramingEthernetIPX = 2, - kOTFramingEthernet8023 = 4, - kOTFraming8022 = 8, - I_OTSetRawMode = (('O' << 8) | 3), - DL_IOC_HDR_INFO = (('l' << 8) | 10), - - // Buffer allocation priority - BPRI_LO = 1, - BPRI_HI = 3, - - // Misc constants - kEnetModuleID = 7101 -}; - -enum EAddrType { - keaStandardAddress = 0, - keaMulticast, - keaBroadcast, - keaBadAddress -}; - - -/* - * Data member wrappers - */ - -// Forward declarations -struct datab; -struct msgb; -struct queue; -struct multicast_node; -struct DLPIStream; - -// Optimize for 32-bit big endian targets -#if defined(WORDS_BIGENDIAN) && (SIZEOF_VOID_P == 4) - -// Predefined member types -typedef int8 nw_int8; -typedef int16 nw_int16; -typedef int32 nw_int32; -typedef uint8 nw_uint8; -typedef uint16 nw_uint16; -typedef uint32 nw_uint32; -typedef int nw_bool; -typedef uint8 * nw_uint8_p; -typedef void * nw_void_p; -typedef datab * nw_datab_p; -typedef msgb * nw_msgb_p; -typedef queue * nw_queue_p; -typedef multicast_node *nw_multicast_node_p; -typedef DLPIStream * nw_DLPIStream_p; - -#else - -// Big-endian memory accessor -template< int nbytes > -struct nw_memory_helper; - -template<> -struct nw_memory_helper<1> { - static inline uint8 load(void *ptr) { return *((uint8 *)ptr); } - static inline void store(void *ptr, uint8 val) { *((uint8 *)ptr) = val; } -}; - -template<> -struct nw_memory_helper<2> { - static inline uint16 load(void *ptr) { return ntohs(*((uint16 *)ptr)); } - static inline void store(void *ptr, uint16 val) { *((uint16 *)ptr) = htons(val); } -}; - -template<> -struct nw_memory_helper<4> { - static inline uint32 load(void *ptr) { return ntohl(*((uint32 *)ptr)); } - static inline void store(void *ptr, uint32 val) { *((uint32 *)ptr) = htonl(val); } -}; - -// Scalar data member wrapper (specialise for pointer member types?) -template< class type, class public_type > -class nw_scalar_member_helper { - uint8 _pad[sizeof(type)]; -public: - operator public_type () const { - return (public_type)(uintptr)nw_memory_helper::load((void *)this); - } - public_type operator -> () const { - return this->operator public_type (); - } - nw_scalar_member_helper & operator = (public_type val) { - nw_memory_helper::store((void *)this, (type)(uintptr)val); - return *this; - } - nw_scalar_member_helper & operator += (int val) { - *this = *this + val; - return *this; - } - nw_scalar_member_helper & operator -= (int val) { - *this = *this - val; - return *this; - } - nw_scalar_member_helper & operator &= (int val) { - *this = *this & val; - return *this; - } - nw_scalar_member_helper & operator |= (int val) { - *this = *this | val; - return *this; - } -}; - -// Predefined member types -typedef nw_scalar_member_helper nw_int8; -typedef nw_scalar_member_helper nw_int16; -typedef nw_scalar_member_helper nw_int32; -typedef nw_scalar_member_helper nw_uint8; -typedef nw_scalar_member_helper nw_uint16; -typedef nw_scalar_member_helper nw_uint32; -typedef nw_scalar_member_helper nw_bool; -typedef nw_scalar_member_helper nw_uint8_p; -typedef nw_scalar_member_helper nw_void_p; -typedef nw_scalar_member_helper nw_datab_p; -typedef nw_scalar_member_helper nw_msgb_p; -typedef nw_scalar_member_helper nw_queue_p; -typedef nw_scalar_member_helper nw_multicast_node_p; -typedef nw_scalar_member_helper nw_DLPIStream_p; - -#endif - - -/* - * Structures - */ - -// Data block -struct datab { - nw_datab_p db_freep; - nw_uint8_p db_base; - nw_uint8_p db_lim; - nw_uint8 db_ref; - nw_uint8 db_type; - // ... -}; - -// Message block -struct msgb { - nw_msgb_p b_next; - nw_msgb_p b_prev; - nw_msgb_p b_cont; - nw_uint8_p b_rptr; - nw_uint8_p b_wptr; - nw_datab_p b_datap; - // ... -}; - -// Queue (full structure required because of size) -struct queue { - nw_void_p q_qinfo; - nw_msgb_p q_first; - nw_msgb_p q_last; - nw_queue_p q_next; - nw_queue_p q_link; - nw_DLPIStream_p q_ptr; - nw_uint32 q_count; - nw_int32 q_minpsz; - nw_int32 q_maxpsz; - nw_uint32 q_hiwat; - nw_uint32 q_lowat; - nw_void_p q_bandp; - nw_uint16 q_flag; - nw_uint8 q_nband; - uint8 _q_pad1[1]; - nw_void_p q_osx; - nw_queue_p q_ffcp; - nw_queue_p q_bfcp; -}; -typedef struct queue queue_t; - -// M_IOCTL parameters -struct iocblk { - nw_int32 ioc_cmd; - nw_void_p ioc_cr; - nw_uint32 ioc_id; - nw_uint32 ioc_count; - nw_int32 ioc_error; - nw_int32 ioc_rval; - int32 _ioc_filler[4]; -}; - -// Priority specification -struct dl_priority_t { - nw_int32 dl_min, dl_max; -}; - -// DPLI primitives -struct dl_info_req_t { - nw_uint32 dl_primitive; // DL_INFO_REQ -}; - -struct dl_info_ack_t { - nw_uint32 dl_primitive; // DL_INFO_ACK - nw_uint32 dl_max_sdu; - nw_uint32 dl_min_sdu; - nw_uint32 dl_addr_length; - nw_uint32 dl_mac_type; - nw_uint32 dl_reserved; - nw_uint32 dl_current_state; - nw_int32 dl_sap_length; - nw_uint32 dl_service_mode; - nw_uint32 dl_qos_length; - nw_uint32 dl_qos_offset; - nw_uint32 dl_qos_range_length; - nw_uint32 dl_qos_range_offset; - nw_uint32 dl_provider_style; - nw_uint32 dl_addr_offset; - nw_uint32 dl_version; - nw_uint32 dl_brdcst_addr_length; - nw_uint32 dl_brdcst_addr_offset; - nw_uint32 dl_growth; -}; - -struct dl_bind_req_t { - nw_uint32 dl_primitive; // DL_BIND_REQ - nw_uint32 dl_sap; - nw_uint32 dl_max_conind; - nw_uint16 dl_service_mode; - nw_uint16 dl_conn_mgmt; - nw_uint32 dl_xidtest_flg; -}; - -struct dl_bind_ack_t { - nw_uint32 dl_primitive; // DL_BIND_ACK - nw_uint32 dl_sap; - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; - nw_uint32 dl_max_conind; - nw_uint32 dl_xidtest_flg; -}; - -struct dl_error_ack_t { - nw_uint32 dl_primitive; // DL_ERROR_ACK - nw_uint32 dl_error_primitive; - nw_uint32 dl_errno; - nw_uint32 dl_unix_errno; -}; - -struct dl_ok_ack_t { - nw_uint32 dl_primitive; // DL_ERROR_ACK - nw_uint32 dl_correct_primitive; -}; - -struct dl_unitdata_req_t { - nw_uint32 dl_primitive; // DL_UNITDATA_REQ - nw_uint32 dl_dest_addr_length; - nw_uint32 dl_dest_addr_offset; - dl_priority_t dl_priority; -}; - -struct dl_unitdata_ind_t { - nw_uint32 dl_primitive; // DL_UNITDATA_IND - nw_uint32 dl_dest_addr_length; - nw_uint32 dl_dest_addr_offset; - nw_uint32 dl_src_addr_length; - nw_uint32 dl_src_addr_offset; - nw_uint32 dl_group_address; -}; - -struct dl_uderror_ind_t { - nw_uint32 dl_primitive; // DL_UDERROR_IND - nw_uint32 dl_dest_addr_length; - nw_uint32 dl_dest_addr_offset; - nw_uint32 dl_unix_errno; - nw_uint32 dl_errno; -}; - -struct dl_subs_bind_req_t { - nw_uint32 dl_primitive; // DL_SUBS_BIND_REQ - nw_uint32 dl_subs_sap_offset; - nw_uint32 dl_subs_sap_length; - nw_uint32 dl_subs_bind_class; -}; - -struct dl_subs_bind_ack_t { - nw_uint32 dl_primitive; // DL_SUBS_BIND_ACK - nw_uint32 dl_subs_sap_offset; - nw_uint32 dl_subs_sap_length; -}; - -struct dl_subs_unbind_req_t { - nw_uint32 dl_primitive; // DL_SUBS_UNBIND_REQ - nw_uint32 dl_subs_sap_offset; - nw_uint32 dl_subs_sap_length; -}; - -struct dl_enabmulti_req_t { - nw_uint32 dl_primitive; // DL_ENABMULTI_REQ - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; -}; - -struct dl_disabmulti_req_t { - nw_uint32 dl_primitive; // DL_DISABMULTI_REQ - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; -}; - -struct dl_phys_addr_req_t { - nw_uint32 dl_primitive; // DL_PHYS_ADDR_REQ - nw_uint32 dl_addr_type; -}; - -struct dl_phys_addr_ack_t { - nw_uint32 dl_primitive; // DL_PHYS_ADDR_ACK - nw_uint32 dl_addr_length; - nw_uint32 dl_addr_offset; -}; - -// Parameters for I_OTSetRawMode/kOTSetRecvMode ioctl() -struct dl_recv_control_t { - nw_uint32 dl_primitive; - nw_uint32 dl_flags; - nw_uint32 dl_truncation_length; -}; - -union DL_primitives { - nw_uint32 dl_primitive; - dl_info_req_t info_req; - dl_info_ack_t info_ack; - dl_bind_req_t bind_req; - dl_bind_ack_t bind_ack; - dl_error_ack_t error_ack; - dl_ok_ack_t ok_ack; - dl_unitdata_req_t unitdata_req; - dl_unitdata_ind_t unitdata_ind; - dl_uderror_ind_t uderror_ind; - dl_subs_bind_req_t subs_bind_req; - dl_subs_bind_ack_t subs_bind_ack; - dl_subs_unbind_req_t subs_unbind_req; - dl_enabmulti_req_t enabmulti_req; - dl_disabmulti_req_t disabmulti_req; - dl_phys_addr_req_t phys_addr_req; - dl_phys_addr_ack_t phys_addr_ack; -}; - -#ifdef PRAGMA_ALIGN_SUPPORTED -#pragma options align=mac68k -#endif - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - -// Packet headers -struct EnetPacketHeader { - uint8 fDestAddr[6]; - uint8 fSourceAddr[6]; - nw_uint16 fProto; -} PACKED__; - -struct T8022Header { - uint8 fDSAP; - uint8 fSSAP; - uint8 fCtrl; -} PACKED__; - -struct T8022SNAPHeader { - uint8 fDSAP; - uint8 fSSAP; - uint8 fCtrl; - uint8 fSNAP[k8022SNAPLength]; -} PACKED__; - -struct T8022FullPacketHeader { - EnetPacketHeader fEnetPart; - T8022SNAPHeader f8022Part; -} PACKED__; - -struct T8022AddressStruct { - uint8 fHWAddr[6]; - nw_uint16 fSAP; - uint8 fSNAP[k8022SNAPLength]; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(0) -#endif - -#ifdef PRAGMA_ALIGN_SUPPORTED -#pragma options align=reset -#endif - -#endif diff --git a/SheepShaver/src/include/extfs.h b/SheepShaver/src/include/extfs.h deleted file mode 120000 index a86e2538..00000000 --- a/SheepShaver/src/include/extfs.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/extfs.h \ No newline at end of file diff --git a/SheepShaver/src/include/extfs_defs.h b/SheepShaver/src/include/extfs_defs.h deleted file mode 120000 index 0970ce1f..00000000 --- a/SheepShaver/src/include/extfs_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/extfs_defs.h \ No newline at end of file diff --git a/SheepShaver/src/include/macos_util.h b/SheepShaver/src/include/macos_util.h deleted file mode 100644 index 0b8e3eee..00000000 --- a/SheepShaver/src/include/macos_util.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * macos_util.h - MacOS definitions/utility functions - * - * SheepShaver (C) Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MACOS_UTIL_H -#define MACOS_UTIL_H - -#include "cpu_emulation.h" -#include "thunks.h" -#include - - -/* - * General definitions - */ - -struct Point { - int16 v; - int16 h; -}; - -struct Rect { - int16 top; - int16 left; - int16 bottom; - int16 right; -}; - - -/* - * Queues - */ - -enum { // Queue types - dummyType = 0, - vType = 1, - ioQType = 2, - drvQType = 3, - evType = 4, - fsQType = 5, - sIQType = 6, - dtQType = 7, - nmType = 8 -}; - -enum { // QElem struct - qLink = 0, - qType = 4, - qData = 6 -}; - -enum { // QHdr struct - qFlags = 0, - qHead = 2, - qTail = 6 -}; - - -/* - * Definitions for Deferred Task Manager - */ - -enum { // DeferredTask struct - dtFlags = 6, - dtAddr = 8, - dtParam = 12, - dtReserved = 16 -}; - - -/* - * Definitions for Device Manager - */ - -// Error codes -enum { - noErr = 0, - controlErr = -17, /* I/O System Errors */ - statusErr = -18, /* I/O System Errors */ - readErr = -19, /* I/O System Errors */ - writErr = -20, /* I/O System Errors */ - badUnitErr = -21, /* I/O System Errors */ - unitEmptyErr = -22, /* I/O System Errors */ - openErr = -23, /* I/O System Errors */ - closErr = -24, /* I/O System Errors */ - abortErr = -27, /* IO call aborted by KillIO */ - notOpenErr = -28, /* Driver not open */ - dskFulErr = -34, /* disk full */ - nsvErr = -35, /* no such volume */ - ioErr = -36, /* I/O error (bummers) */ - bdNamErr = -37, /* bad name */ - fnOpnErr = -38, /* file not open */ - eofErr = -39, /* End-of-file encountered */ - posErr = -40, /* tried to position to before start of file (r/w) */ - tmfoErr = -42, /* too many files open */ - fnfErr = -43, /* file not found */ - wPrErr = -44, /* diskette is write protected. */ - fLckdErr = -45, /* file is locked */ - fBsyErr = -47, /* file busy, dir not empty */ - dupFNErr = -48, /* duplicate filename already exists */ - paramErr = -50, /* error in user parameter list */ - rfNumErr = -51, /* bad ioRefNum */ - permErr = -54, /* permission error */ - nsDrvErr = -56, /* no such driver number */ - extFSErr = -58, /* external file system */ - noDriveErr = -64, /* drive not installed */ - offLinErr = -65, /* r/w requested for an off-line drive */ - noNybErr = -66, /* couldn't find 5 nybbles in 200 tries */ - noAdrMkErr = -67, /* couldn't find valid addr mark */ - dataVerErr = -68, /* read verify compare failed */ - badCksmErr = -69, /* addr mark checksum didn't check */ - badBtSlpErr = -70, /* bad addr mark bit slip nibbles */ - noDtaMkErr = -71, /* couldn't find a data mark header */ - badDCksum = -72, /* bad data mark checksum */ - badDBtSlp = -73, /* bad data mark bit slip nibbles */ - wrUnderrun = -74, /* write underrun occurred */ - cantStepErr = -75, /* step handshake failed */ - tk0BadErr = -76, /* track 0 detect doesn't change */ - initIWMErr = -77, /* unable to initialize IWM */ - twoSideErr = -78, /* tried to read 2nd side on a 1-sided drive */ - spdAdjErr = -79, /* unable to correctly adjust disk speed */ - seekErr = -80, /* track number wrong on address mark */ - sectNFErr = -81, /* sector number never found on a track */ - fmt1Err = -82, /* can't find sector 0 after track format */ - fmt2Err = -83, /* can't get enough sync */ - verErr = -84, /* track failed to verify */ - memFullErr = -108, - dirNFErr = -120 /* directory not found */ -}; - -// Misc constants -enum { - goodbye = -1, /* heap being reinitialized */ - - ioInProgress = 1, /* predefined value of ioResult while I/O is pending */ - aRdCmd = 2, /* low byte of ioTrap for Read calls */ - aWrCmd = 3, /* low byte of ioTrap for Write calls */ - asyncTrpBit = 10, /* trap word modifier */ - noQueueBit = 9, /* trap word modifier */ - - dReadEnable = 0, /* set if driver responds to read requests */ - dWritEnable = 1, /* set if driver responds to write requests */ - dCtlEnable = 2, /* set if driver responds to control requests */ - dStatEnable = 3, /* set if driver responds to status requests */ - dNeedGoodBye = 4, /* set if driver needs time for performing periodic tasks */ - dNeedTime = 5, /* set if driver needs time for performing periodic tasks */ - dNeedLock = 6, /* set if driver must be locked in memory as soon as it is opened */ - - dOpened = 5, /* driver is open */ - dRAMBased = 6, /* dCtlDriver is a handle (1) or pointer (0) */ - drvrActive = 7, /* driver is currently processing a request */ - - rdVerify = 64, - - fsCurPerm = 0, // Whatever is currently allowed - fsRdPerm = 1, // Exclusive read - fsWrPerm = 2, // Exclusive write - fsRdWrPerm = 3, // Exclusive read/write - fsRdWrShPerm = 4, // Shared read/write - - fsAtMark = 0, // At current mark - fsFromStart = 1, // Set mark rel to BOF - fsFromLEOF = 2, // Set mark rel to logical EOF - fsFromMark = 3, // Set mark rel to current mark - - sony = 0, - hard20 = 1 -}; - -enum { /* Large Volume Constants */ - kWidePosOffsetBit = 8, - kMaximumBlocksIn4GB = 0x007FFFFF -}; - -enum { // IOParam struct - ioTrap = 6, - ioCmdAddr = 8, - ioCompletion = 12, - ioResult = 16, - ioNamePtr = 18, - ioVRefNum = 22, - ioRefNum = 24, - ioVersNum = 26, - ioPermssn = 27, - ioMisc = 28, - ioBuffer = 32, - ioReqCount = 36, - ioActCount = 40, - ioPosMode = 44, - ioPosOffset = 46, - ioWPosOffset = 46, // Wide positioning offset when ioPosMode has kWidePosOffsetBit set - SIZEOF_IOParam = 50 -}; - -enum { // CntrlParam struct - csCode = 26, - csParam = 28 -}; - -enum { // DrvSts struct - dsTrack = 0, - dsWriteProt = 2, - dsDiskInPlace = 3, - dsInstalled = 4, - dsSides = 5, - dsQLink = 6, - dsQType = 10, - dsQDrive = 12, - dsQRefNum = 14, - dsQFSID = 16, - dsTwoSideFmt = 18, - dsNewIntf = 19, - dsDiskErrs = 20, - dsMFMDrive = 22, - dsMFMDisk = 23, - dsTwoMegFmt = 24 -}; - -enum { // DrvSts2 struct - dsDriveSize = 18, - dsDriveS1 = 20, - dsDriveType = 22, - dsDriveManf = 24, - dsDriveChar = 26, - dsDriveMisc = 28, - SIZEOF_DrvSts = 30 -}; - -enum { // DCtlEntry struct - dCtlDriver = 0, - dCtlFlags = 4, - dCtlQHdr = 6, - dCtlPosition = 16, - dCtlStorage = 20, - dCtlRefNum = 24, - dCtlCurTicks = 26, - dCtlWindow = 30, - dCtlDelay = 34, - dCtlEMask = 36, - dCtlMenu = 38, - dCtlSlot = 40, - dCtlSlotId = 41, - dCtlDevBase = 42, - dCtlOwner = 46, - dCtlExtDev = 50, - dCtlFillByte = 51, - dCtlNodeID = 52 -}; - - -/* - * Definitions for native Device Manager - */ - -// Registry EntryID -struct RegEntryID { - uint32 contents[4]; -}; - -// Command codes -enum { - kOpenCommand = 0, - kCloseCommand = 1, - kReadCommand = 2, - kWriteCommand = 3, - kControlCommand = 4, - kStatusCommand = 5, - kKillIOCommand = 6, - kInitializeCommand = 7, /* init driver and device*/ - kFinalizeCommand = 8, /* shutdown driver and device*/ - kReplaceCommand = 9, /* replace an old driver*/ - kSupersededCommand = 10, /* prepare to be replaced by a new driver*/ - kSuspendCommand = 11, /* prepare driver to go to sleep*/ - kResumeCommand = 12 /* wake up sleeping driver*/ -}; - -// Command kinds -enum { - kSynchronousIOCommandKind = 0x00000001, - kAsynchronousIOCommandKind = 0x00000002, - kImmediateIOCommandKind = 0x00000004 -}; - - -/* - * Definitions for Mixed Mode Manager - */ - -typedef uint32 ProcInfoType; -typedef int8 ISAType; -typedef uint16 RoutineFlagsType; -typedef uint32 ProcPtr; -typedef uint8 RDFlagsType; - -struct RoutineRecord { - ProcInfoType procInfo; /* calling conventions */ - int8 reserved1; /* Must be 0 */ - ISAType ISA; /* Instruction Set Architecture */ - RoutineFlagsType routineFlags; /* Flags for each routine */ - ProcPtr procDescriptor; /* Where is the thing weÕre calling? */ - uint32 reserved2; /* Must be 0 */ - uint32 selector; /* For dispatched routines, the selector */ -}; - -struct RoutineDescriptor { - uint16 goMixedModeTrap; /* Our A-Trap */ - int8 version; /* Current Routine Descriptor version */ - RDFlagsType routineDescriptorFlags; /* Routine Descriptor Flags */ - uint32 reserved1; /* Unused, must be zero */ - uint8 reserved2; /* Unused, must be zero */ - uint8 selectorInfo; /* If a dispatched routine, calling convention, else 0 */ - uint16 routineCount; /* Number of routines in this RD */ - RoutineRecord routineRecords[1]; /* The individual routines */ -}; - -struct SheepRoutineDescriptor - : public SheepVar -{ - SheepRoutineDescriptor(ProcInfoType procInfo, uint32 procedure) - : SheepVar(sizeof(RoutineDescriptor)) - { - const uintptr desc = addr(); - Mac_memset(desc, 0, sizeof(RoutineDescriptor)); - WriteMacInt16(desc + offsetof(RoutineDescriptor, goMixedModeTrap), 0xAAFE); - WriteMacInt8 (desc + offsetof(RoutineDescriptor, version), 7); - WriteMacInt32(desc + offsetof(RoutineDescriptor, routineRecords) + offsetof(RoutineRecord, procInfo), procInfo); - WriteMacInt8 (desc + offsetof(RoutineDescriptor, routineRecords) + offsetof(RoutineRecord, ISA), 1); - WriteMacInt16(desc + offsetof(RoutineDescriptor, routineRecords) + offsetof(RoutineRecord, routineFlags), 0 | 0 | 4); - WriteMacInt32(desc + offsetof(RoutineDescriptor, routineRecords) + offsetof(RoutineRecord, procDescriptor), procedure); - } -}; - - -// Functions -extern void MacOSUtilReset(void); -extern void Enqueue(uint32 elem, uint32 list); // Enqueue QElem to list -extern int FindFreeDriveNumber(int num); // Find first free drive number, starting at "num" -extern void MountVolume(void *fh); // Mount volume with given file handle (see sys.h) -extern void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size); // Calculate disk image file layout given file size and first 256 data bytes -extern uint32 FindLibSymbol(const char *lib, const char *sym); // Find symbol in shared library -extern void InitCallUniversalProc(void); // Init CallUniversalProc() -extern long CallUniversalProc(void *upp, uint32 info); // CallUniversalProc() -extern uint32 TimeToMacTime(time_t t); // Convert time_t value to MacOS time -extern uint32 Mac_sysalloc(uint32 size); // Allocate block in MacOS system heap zone -extern void Mac_sysfree(uint32 addr); // Release block occupied by the nonrelocatable block p - -// Construct four-character-code from string -#define FOURCC(a,b,c,d) (((uint32)(a) << 24) | ((uint32)(b) << 16) | ((uint32)(c) << 8) | (uint32)(d)) - -// Emulator identification codes (4 and 2 characters) -const uint32 EMULATOR_ID_4 = 0x62616168; // 'baah' -const uint16 EMULATOR_ID_2 = 0x6261; // 'ba' - -// Test if basic MacOS initializations (of the ROM) are done -static inline bool HasMacStarted(void) -{ - return ReadMacInt32(0xcfc) == FOURCC('W','L','S','C'); // Mac warm start flag -} - -#endif diff --git a/SheepShaver/src/include/main.h b/SheepShaver/src/include/main.h deleted file mode 100644 index e595c04a..00000000 --- a/SheepShaver/src/include/main.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * main.h - Emulation core - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MAIN_H -#define MAIN_H - -// Global variables -extern void *TOC; // TOC pointer -extern void *R13; // r13 register -extern uint32 KernelDataAddr; // Address of Kernel Data -extern uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM -extern uint32 PVR; // Theoretical PVR -extern int64 CPUClockSpeed; // Processor clock speed (Hz) -extern int64 BusClockSpeed; // Bus clock speed (Hz) -extern int64 TimebaseSpeed; // Timebase clock speed (Hz) - -#ifdef __BEOS__ -extern system_info SysInfo; // System information -#endif - -// 68k register structure (for Execute68k()) -struct M68kRegisters { - uint32 d[8]; - uint32 a[8]; -}; - - -// Functions -extern bool InitAll(const char *vmdir); -extern void ExitAll(void); -extern void Dump68kRegs(M68kRegisters *r); // Dump 68k registers -extern void MakeExecutable(int dummy, uint32 start, uint32 length); // Make code executable -extern void PatchAfterStartup(void); // Patches after system startup -extern void QuitEmulator(void); // Quit emulator (must only be called from main thread) -extern void ErrorAlert(const char *text); // Display error alert -extern void WarningAlert(const char *text); // Display warning alert -extern bool ChoiceAlert(const char *text, const char *pos, const char *neg); // Display choice alert - -// Mutexes (non-recursive) -struct B2_mutex; -extern B2_mutex *B2_create_mutex(void); -extern void B2_lock_mutex(B2_mutex *mutex); -extern void B2_unlock_mutex(B2_mutex *mutex); -extern void B2_delete_mutex(B2_mutex *mutex); - -// Interrupt flags -enum { - INTFLAG_VIA = 1, // 60.15Hz VBL - INTFLAG_SERIAL = 2, // Serial driver - INTFLAG_ETHER = 4, // Ethernet driver - INTFLAG_AUDIO = 16, // Audio block read - INTFLAG_TIMER = 32, // Time Manager - INTFLAG_ADB = 64 // ADB -}; - -extern volatile uint32 InterruptFlags; // Currently pending interrupts -extern void SetInterruptFlag(uint32); -extern void ClearInterruptFlag(uint32); -extern void TriggerInterrupt(void); // Trigger SIGUSR1 interrupt in emulator thread -extern void DisableInterrupt(void); // Disable SIGUSR1 interrupt (can be nested) -extern void EnableInterrupt(void); // Enable SIGUSR1 interrupt (can be nested) - -#endif diff --git a/SheepShaver/src/include/name_registry.h b/SheepShaver/src/include/name_registry.h deleted file mode 100644 index ef7cbbfe..00000000 --- a/SheepShaver/src/include/name_registry.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * name_registry.h - Name Registry handling - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef NAME_REGISTRY_H -#define NAME_REGISTRY_H - -extern void DoPatchNameRegistry(void); -extern void PatchNameRegistry(void); - -#endif diff --git a/SheepShaver/src/include/pict.h b/SheepShaver/src/include/pict.h deleted file mode 120000 index 6e5a0b71..00000000 --- a/SheepShaver/src/include/pict.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/pict.h \ No newline at end of file diff --git a/SheepShaver/src/include/prefs.h b/SheepShaver/src/include/prefs.h deleted file mode 120000 index 64a7ae51..00000000 --- a/SheepShaver/src/include/prefs.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/prefs.h \ No newline at end of file diff --git a/SheepShaver/src/include/prefs_editor.h b/SheepShaver/src/include/prefs_editor.h deleted file mode 100644 index 68b0326d..00000000 --- a/SheepShaver/src/include/prefs_editor.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * prefs_editor.h - Preferences editor - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PREFS_EDITOR_H -#define PREFS_EDITOR_H - -#ifdef __BEOS__ -extern void PrefsEditor(uint32 msg); -#else -extern bool PrefsEditor(void); -#endif - -#endif diff --git a/SheepShaver/src/include/rom_patches.h b/SheepShaver/src/include/rom_patches.h deleted file mode 100644 index c263606a..00000000 --- a/SheepShaver/src/include/rom_patches.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * rom_patches.h - ROM patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ROM_PATCHES_H -#define ROM_PATCHES_H - -// ROM types -enum { - ROMTYPE_TNT, - ROMTYPE_ALCHEMY, - ROMTYPE_ZANZIBAR, - ROMTYPE_GAZELLE, - ROMTYPE_GOSSAMER, - ROMTYPE_NEWWORLD -}; -extern int ROMType; - -extern bool DecodeROM(uint8 *data, uint32 size); -extern bool PatchROM(void); -extern void InstallDrivers(void); - -extern void AddSifter(uint32 type, int16 id); -extern bool FindSifter(uint32 type, int16 id); - -#endif diff --git a/SheepShaver/src/include/rsrc_patches.h b/SheepShaver/src/include/rsrc_patches.h deleted file mode 100644 index 2f367e12..00000000 --- a/SheepShaver/src/include/rsrc_patches.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * rsrc_patches.h - Resource patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef RSRC_PATCHES_H -#define RSRC_PATCHES_H - -extern void CheckLoad(uint32 type, int16 id, uint16 *p, uint32 size); -extern void CheckLoad(uint32 type, const char *name, uint16 *p, uint32 size); -extern void PatchNativeResourceManager(void); - -#endif diff --git a/SheepShaver/src/include/scsi.h b/SheepShaver/src/include/scsi.h deleted file mode 120000 index b5aa39cc..00000000 --- a/SheepShaver/src/include/scsi.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/scsi.h \ No newline at end of file diff --git a/SheepShaver/src/include/serial.h b/SheepShaver/src/include/serial.h deleted file mode 120000 index 42183f36..00000000 --- a/SheepShaver/src/include/serial.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/serial.h \ No newline at end of file diff --git a/SheepShaver/src/include/serial_defs.h b/SheepShaver/src/include/serial_defs.h deleted file mode 120000 index 1765fd10..00000000 --- a/SheepShaver/src/include/serial_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/serial_defs.h \ No newline at end of file diff --git a/SheepShaver/src/include/sony.h b/SheepShaver/src/include/sony.h deleted file mode 120000 index d9eb3144..00000000 --- a/SheepShaver/src/include/sony.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/sony.h \ No newline at end of file diff --git a/SheepShaver/src/include/sys.h b/SheepShaver/src/include/sys.h deleted file mode 120000 index 5581536a..00000000 --- a/SheepShaver/src/include/sys.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/sys.h \ No newline at end of file diff --git a/SheepShaver/src/include/thunks.h b/SheepShaver/src/include/thunks.h deleted file mode 100644 index e1280f39..00000000 --- a/SheepShaver/src/include/thunks.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * thunks.h - Thunks to share data and code with MacOS - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef THUNKS_H -#define THUNKS_H - -#include "cpu_emulation.h" - -/* - * Native function invocation - */ - -enum { - NATIVE_PATCH_NAME_REGISTRY, - NATIVE_VIDEO_INSTALL_ACCEL, - NATIVE_VIDEO_VBL, - NATIVE_VIDEO_DO_DRIVER_IO, - NATIVE_ETHER_AO_GET_HWADDR, - NATIVE_ETHER_AO_ADD_MULTI, - NATIVE_ETHER_AO_DEL_MULTI, - NATIVE_ETHER_AO_SEND_PACKET, - NATIVE_ETHER_IRQ, - NATIVE_ETHER_INIT, - NATIVE_ETHER_TERM, - NATIVE_ETHER_OPEN, - NATIVE_ETHER_CLOSE, - NATIVE_ETHER_WPUT, - NATIVE_ETHER_RSRV, - NATIVE_SERIAL_NOTHING, - NATIVE_SERIAL_OPEN, - NATIVE_SERIAL_PRIME_IN, - NATIVE_SERIAL_PRIME_OUT, - NATIVE_SERIAL_CONTROL, - NATIVE_SERIAL_STATUS, - NATIVE_SERIAL_CLOSE, - NATIVE_GET_RESOURCE, - NATIVE_GET_1_RESOURCE, - NATIVE_GET_IND_RESOURCE, - NATIVE_GET_1_IND_RESOURCE, - NATIVE_R_GET_RESOURCE, - NATIVE_MAKE_EXECUTABLE, - NATIVE_CHECK_LOAD_INVOC, - NATIVE_NQD_SYNC_HOOK, - NATIVE_NQD_BITBLT_HOOK, - NATIVE_NQD_FILLRECT_HOOK, - NATIVE_NQD_UNKNOWN_HOOK, - NATIVE_NQD_BITBLT, - NATIVE_NQD_INVRECT, - NATIVE_NQD_FILLRECT, - NATIVE_NAMED_CHECK_LOAD_INVOC, - NATIVE_GET_NAMED_RESOURCE, - NATIVE_GET_1_NAMED_RESOURCE, - NATIVE_OP_MAX -}; - -// Initialize the thunks system -extern bool ThunksInit(void); - -// Exit the thunks system -extern void ThunksExit(void); - -// Return the fake PowerPC opcode to handle specified native code -#if EMULATED_PPC -extern uint32 NativeOpcode(int selector); -#endif - -// Return the native function descriptor (TVECT) -extern uint32 NativeTVECT(int selector); - -// Return the native function address -extern uint32 NativeFunction(int selector); - -// Return the routine descriptor address of the native function -extern uint32 NativeRoutineDescriptor(int selector); - - -/* - * Helpers to share 32-bit addressable data with MacOS - * - * There are two distinct allocatable regions: - * - * - The Data region is used to share data between MacOS and - * SheepShaver. This is stack-like allocation since it is - * meant to only hold temporary data which dies at the end - * of the current function scope. - * - * - The Procedure region is used to hold permanent M68K or - * PowerPC code to assist native routine implementations. - * - * - The Procedure region grows up whereas the Data region - * grows down. They may intersect into the ZeroPage, which - * is a read-only page with all bits set to zero. In practise, - * the intersection is unlikely since the Procedure region is - * static and the Data region is meant to be small (< 256 KB). - */ - -class SheepMem { - static uint32 align(uint32 size); -protected: - static uint32 page_size; - static uintptr zero_page; - static uintptr base; - static uintptr data; - static uintptr proc; - static const uint32 size = 0x80000; // 512 KB -public: - static bool Init(void); - static void Exit(void); - static uint32 PageSize(); - static uint32 ZeroPage(); - static uint32 Reserve(uint32 size); - static void Release(uint32 size); - static uint32 ReserveProc(uint32 size); - friend class SheepVar; -}; - -inline uint32 SheepMem::align(uint32 size) -{ - // Align on 4 bytes boundaries - return (size + 3) & -4; -} - -inline uint32 SheepMem::PageSize() -{ - return page_size; -} - -inline uint32 SheepMem::ZeroPage() -{ - return zero_page; -} - -inline uint32 SheepMem::Reserve(uint32 size) -{ - data -= align(size); - assert(data >= proc); - return data; -} - -inline void SheepMem::Release(uint32 size) -{ - data += align(size); -} - -inline uint32 SheepMem::ReserveProc(uint32 size) -{ - uint32 mproc = proc; - proc += align(size); - assert(proc < data); - return mproc; -} - -static inline uint32 SheepProc(const uint8 *proc, uint32 proc_size) -{ - uint32 mac_proc = SheepMem::ReserveProc(proc_size); - Host2Mac_memcpy(mac_proc, proc, proc_size); - return mac_proc; -} - -#define BUILD_SHEEPSHAVER_PROCEDURE(PROC) \ - static uint32 PROC = 0; \ - if (PROC == 0) \ - PROC = SheepProc(PROC##_template, sizeof(PROC##_template)) - -class SheepVar -{ - uint32 m_base; - uint32 m_size; -public: - SheepVar(uint32 requested_size); - ~SheepVar() { SheepMem::Release(m_size); } - uint32 addr() const { return m_base; } -}; - -inline SheepVar::SheepVar(uint32 requested_size) -{ - m_size = SheepMem::align(requested_size); - m_base = SheepMem::Reserve(m_size); -} - -// TODO: optimize for 32-bit platforms - -template< int requested_size > -struct SheepArray : public SheepVar -{ - SheepArray() : SheepVar(requested_size) { } -}; - -struct SheepVar32 : public SheepVar -{ - SheepVar32() : SheepVar(4) { } - SheepVar32(uint32 value) : SheepVar(4) { set_value(value); } - uint32 value() const { return ReadMacInt32(addr()); } - void set_value(uint32 v) { WriteMacInt32(addr(), v); } -}; - -struct SheepString : public SheepVar -{ - SheepString(const char *str) : SheepVar(strlen(str) + 1) - { if (str) strcpy(value(), str); else WriteMacInt8(addr(), 0); } - char *value() const - { return (char *)Mac2HostAddr(addr()); } -}; - -#endif diff --git a/SheepShaver/src/include/timer.h b/SheepShaver/src/include/timer.h deleted file mode 120000 index a7ee23e9..00000000 --- a/SheepShaver/src/include/timer.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/timer.h \ No newline at end of file diff --git a/SheepShaver/src/include/user_strings.h b/SheepShaver/src/include/user_strings.h deleted file mode 100644 index 12ea12eb..00000000 --- a/SheepShaver/src/include/user_strings.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * user_strings.h - Localizable strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef USER_STRINGS_H -#define USER_STRINGS_H - -// Common string numbers -enum { - // General messages - STR_ABOUT_TEXT1 = 0, - STR_ABOUT_TEXT2, - STR_READING_ROM_FILE, - STR_SHELL_ERROR_PREFIX, - STR_GUI_ERROR_PREFIX, - STR_ERROR_ALERT_TITLE, - STR_SHELL_WARNING_PREFIX, - STR_GUI_WARNING_PREFIX, - STR_WARNING_ALERT_TITLE, - STR_NOTICE_ALERT_TITLE, - STR_ABOUT_TITLE, - STR_OK_BUTTON, - STR_START_BUTTON, - STR_QUIT_BUTTON, - STR_CANCEL_BUTTON, - STR_IGNORE_BUTTON, - - // Error messages - STR_NOT_ENOUGH_MEMORY_ERR = 1000, - STR_NO_KERNEL_DATA_ERR, - STR_NO_RAM_AREA_ERR, - STR_NO_ROM_FILE_ERR, - STR_RAM_HIGHER_THAN_ROM_ERR, - STR_ROM_FILE_READ_ERR, - STR_ROM_SIZE_ERR, - STR_UNSUPPORTED_ROM_TYPE_ERR, - STR_POWER_INSTRUCTION_ERR, - STR_MEM_ACCESS_ERR, - STR_MEM_ACCESS_READ, - STR_MEM_ACCESS_WRITE, - STR_UNKNOWN_SEGV_ERR, - STR_NO_NAME_REGISTRY_ERR, - STR_FULL_SCREEN_ERR, - STR_SCSI_BUFFER_ERR, - STR_SCSI_SG_FULL_ERR, - - // Warning messages - STR_SMALL_RAM_WARN = 2000, - STR_VOLUME_IS_MOUNTED_WARN, - STR_CANNOT_UNMOUNT_WARN, - STR_CREATE_VOLUME_WARN, - - // Preferences window - STR_PREFS_TITLE = 3000, - STR_PREFS_MENU = 3020, - STR_PREFS_ITEM_ABOUT, - STR_PREFS_ITEM_START, - STR_PREFS_ITEM_ZAP_PRAM, - STR_PREFS_ITEM_QUIT, - - STR_NONE_LAB = 3100, - - // Volumes pane - STR_VOLUMES_PANE_TITLE = 3200, - STR_ADD_VOLUME_BUTTON, - STR_CREATE_VOLUME_BUTTON, - STR_REMOVE_VOLUME_BUTTON, - STR_ADD_VOLUME_PANEL_BUTTON, - STR_CREATE_VOLUME_PANEL_BUTTON, - STR_CDROM_DRIVE_CTRL, - STR_BOOTDRIVER_CTRL, - STR_BOOT_ANY_LAB, - STR_BOOT_CDROM_LAB, - STR_NOCDROM_CTRL, - STR_EXTFS_CTRL, - STR_ADD_VOLUME_TITLE, - STR_CREATE_VOLUME_TITLE, - STR_HARDFILE_SIZE_CTRL, - - // Graphics pane - STR_GRAPHICS_SOUND_PANE_TITLE = 3300, - STR_FRAMESKIP_CTRL, - STR_REF_5HZ_LAB, - STR_REF_7_5HZ_LAB, - STR_REF_10HZ_LAB, - STR_REF_15HZ_LAB, - STR_REF_30HZ_LAB, - STR_REF_60HZ_LAB, - STR_REF_DYNAMIC_LAB, - STR_GFXACCEL_CTRL, - STR_8_BIT_CTRL, - STR_16_BIT_CTRL, - STR_32_BIT_CTRL, - STR_W_640x480_CTRL, - STR_W_800x600_CTRL, - STR_640x480_CTRL, - STR_800x600_CTRL, - STR_1024x768_CTRL, - STR_1152x768_CTRL, - STR_1152x900_CTRL, - STR_1280x1024_CTRL, - STR_1600x1200_CTRL, - STR_VIDEO_MODE_CTRL, - STR_FULLSCREEN_CTRL, - STR_WINDOW_CTRL, - STR_VIDEO_TYPE_CTRL, - STR_DISPLAY_X_CTRL, - STR_DISPLAY_Y_CTRL, - STR_SIZE_384_LAB, - STR_SIZE_480_LAB, - STR_SIZE_512_LAB, - STR_SIZE_600_LAB, - STR_SIZE_640_LAB, - STR_SIZE_768_LAB, - STR_SIZE_800_LAB, - STR_SIZE_1024_LAB, - STR_SIZE_MAX_LAB, - STR_NOSOUND_CTRL, - - // Serial/Network pane - STR_SERIAL_NETWORK_PANE_TITLE = 3400, - STR_SERPORTA_CTRL, - STR_SERPORTB_CTRL, - STR_NONET_CTRL, - STR_ETHERNET_IF_CTRL, - - // Memory/Misc pane - STR_MEMORY_MISC_PANE_TITLE = 3500, - STR_RAMSIZE_CTRL, - STR_RAMSIZE_4MB_LAB, - STR_RAMSIZE_8MB_LAB, - STR_RAMSIZE_16MB_LAB, - STR_RAMSIZE_32MB_LAB, - STR_RAMSIZE_64MB_LAB, - STR_RAMSIZE_128MB_LAB, - STR_RAMSIZE_256MB_LAB, - STR_RAMSIZE_512MB_LAB, - STR_RAMSIZE_1024MB_LAB, - STR_RAMSIZE_SLIDER, - STR_RAMSIZE_FMT, - STR_IGNORESEGV_CTRL, - STR_IDLEWAIT_CTRL, - STR_ROM_FILE_CTRL, - - // JIT Compiler pane - STR_JIT_PANE_TITLE = 3700, - STR_JIT_CTRL, - STR_JIT_68K_CTRL, - - // Mac window - STR_WINDOW_TITLE = 4000, - STR_WINDOW_TITLE_FROZEN, - STR_WINDOW_MENU = 4050, - STR_WINDOW_ITEM_ABOUT, - STR_WINDOW_ITEM_REFRESH, - STR_WINDOW_ITEM_MOUNT, - - // Audio - STR_SOUND_IN_NAME = 6000, - - // External file system - STR_EXTFS_NAME = 7000, - STR_EXTFS_VOLUME_NAME -}; - -// Common and platform-specific string definitions -struct user_string_def { - int num; - const char *str; -}; - -extern user_string_def common_strings[]; -extern user_string_def platform_strings[]; - -// Fetch pointer to string, given the string number -extern const char *GetString(int num); - -#endif diff --git a/SheepShaver/src/include/version.h b/SheepShaver/src/include/version.h deleted file mode 100644 index 78a3837f..00000000 --- a/SheepShaver/src/include/version.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * version.h - Version information - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef VERSION_H -#define VERSION_H - -const int VERSION_MAJOR = 2; -const int VERSION_MINOR = 4; - -#endif diff --git a/SheepShaver/src/include/video.h b/SheepShaver/src/include/video.h deleted file mode 100644 index 3b82203e..00000000 --- a/SheepShaver/src/include/video.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * video.h - Video/graphics emulation - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef VIDEO_H -#define VIDEO_H - -extern bool VideoActivated(void); -extern bool VideoSnapshot(int xsize, int ysize, uint8 *p); - -extern int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, uint32 commandCode, uint32 commandKind); - -// System specific and internal functions/data -struct VideoInfo { - int viType; // Screen/Window - uint32 viRowBytes; // width of each row in memory - uint16 viXsize,viYsize; // Window - uint32 viAppleMode; // Screen Color Depth - uint32 viAppleID; // Screen DisplayID -}; - -extern struct VideoInfo VModes[]; // List of available video modes - -enum { // viAppleMode - APPLE_1_BIT = 0x80, - APPLE_2_BIT, - APPLE_4_BIT, - APPLE_8_BIT, - APPLE_16_BIT, - APPLE_32_BIT -}; - -// 1, 2, 4 and 8 bit depths use a color palette -inline bool IsDirectMode(int mode) -{ - return mode == APPLE_16_BIT || mode == APPLE_32_BIT; -} - -// Return the depth code that corresponds to the specified bits-per-pixel value -inline int DepthModeForPixelDepth(int depth) -{ - switch (depth) { - case 1: return APPLE_1_BIT; - case 2: return APPLE_2_BIT; - case 4: return APPLE_4_BIT; - case 8: return APPLE_8_BIT; - case 15: case 16: return APPLE_16_BIT; - case 24: case 32: return APPLE_32_BIT; - default: return APPLE_1_BIT; - } -} - -// Return a bytes-per-row value (assuming no padding) for the specified depth and pixel width -inline uint32 TrivialBytesPerRow(uint32 width, int mode) -{ - switch (mode) { - case APPLE_1_BIT: return width / 8; - case APPLE_2_BIT: return width / 4; - case APPLE_4_BIT: return width / 2; - case APPLE_8_BIT: return width; - case APPLE_16_BIT: return width * 2; - case APPLE_32_BIT: return width * 4; - default: return width; - } -} - -enum { // viAppleID - APPLE_640x480 = 0x81, - APPLE_W_640x480, - APPLE_800x600, - APPLE_W_800x600, - APPLE_1024x768, - APPLE_1152x768, - APPLE_1152x900, - APPLE_1280x1024, - APPLE_1600x1200, - APPLE_CUSTOM, - APPLE_ID_MIN = APPLE_640x480, - APPLE_ID_MAX = APPLE_CUSTOM -}; - -enum { // Display type - DIS_INVALID, - DIS_SCREEN, - DIS_WINDOW -}; - -extern bool video_activated; // Flag: video display activated, mouse and keyboard data valid -extern uint32 screen_base; // Frame buffer base address -extern int cur_mode; // Number of current video mode (index in VModes array) -extern int display_type; // Current display type (see above) -extern rgb_color mac_pal[256]; -extern uint8 remap_mac_be[256]; -extern uint8 MacCursor[68]; - -struct VidLocals{ - uint16 saveMode; - uint32 saveData; - uint16 savePage; - uint32 saveBaseAddr; - uint32 gammaTable; // Mac address of gamma tble - uint32 maxGammaTableSize; // Biggest gamma table allocated - uint32 saveVidParms; - bool luminanceMapping; // Luminance mapping on/off - bool cursorHardware; // True if using hardware cursor - int32 cursorX; // Hardware cursor state - int32 cursorY; - uint32 cursorVisible; - uint32 cursorSet; - bool cursorHotFlag; - uint8 cursorHotX; - uint8 cursorHotY; - uint32 vslServiceID; // VSL interrupt service ID - bool interruptsEnabled; // VBL interrupts on/off - uint32 regEntryID; // Mac address of the service owner -}; - -extern VidLocals *private_data; // Pointer to driver local variables (there is only one display, so this is ok) - -extern bool VideoInit(void); -extern void VideoExit(void); -extern void VideoVBL(void); -extern void VideoInstallAccel(void); -extern void VideoQuitFullScreen(void); - -extern void video_set_palette(void); -extern void video_set_cursor(void); -extern bool video_can_change_cursor(void); -extern int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr); -extern void video_set_dirty_area(int x, int y, int w, int h); - -extern int16 VSLDoInterruptService(uint32 arg1); -extern void NQDMisc(uint32 arg1, uintptr arg2); - -// Native QuickDraw acceleration callbacks -extern bool NQD_sync_hook(uint32); -extern bool NQD_bitblt_hook(uint32); -extern bool NQD_fillrect_hook(uint32); -extern bool NQD_unknown_hook(uint32); -extern void NQD_bitblt(uint32); -extern void NQD_invrect(uint32); -extern void NQD_fillrect(uint32); - -extern bool keyfile_valid; - -#endif diff --git a/SheepShaver/src/include/video_defs.h b/SheepShaver/src/include/video_defs.h deleted file mode 100644 index ef9e2824..00000000 --- a/SheepShaver/src/include/video_defs.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * video_defs.h - MacOS types and structures for video - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef VIDEO_DEFS_H -#define VIDEO_DEFS_H - -#include "macos_util.h" -#include - - -/* - * Definitions for Display Manager - */ - -/* csMode values describing pixel depth in VDSwitchInfo */ -enum { - firstVidMode=128, // first depth mode, representing lowest supported - // pixel depth - secondVidMode, thirdVidMode, fourthVidMode, fifthVidMode, sixthVidMode - // following modes represent pixel depths in ascending - // order -}; - -/* csDisplayType values in VDDisplayConnectInfoRec */ -enum { - kUnknownConnect=1, // reserved - kPanelTFTConnect, // fixed-in-place LCS (TFT, aka "active matrix") panels - kFixedModeCRTConnect, // very limited displays - kMultiModeCRT1Connect, // 12" optional, 13" default, 16" required - kMultiModeCRT2Connect, // 12" optional, 13" req., 16" def., 19" req. - kMultiModeCRT3Connect, // 12" optional, 13" req., 16" req., 19" req.,21" def. - kMultiModeCRT4Connect, // expansion to large multimode (not yet implemented) - kModelessConnect, // expansion to modeless model (not yet implemented) - kFullPageConnect, // 640x818 (to get 8bpp in 512K case) and - // 640x870 (nothing else supported) - kVGAConnect, // 640x480 VGA default -- nothing else req. - kNTSCConnect, // NTSC ST(default), FF, STconv, FFconv - kPALConnect, // PAL ST(default), FF, STconv, FFconv - kHRConnect, // 640x400 (to get 8bpp in 256K case) and - // 640x480 (nothing else supported) - kPanelFSTNConnect // fixed-in-place LCD FSTN (aka "supertwist") panels -}; - -/* csConnectFlags values in VDDisplayConnectInfoRec */ -enum { - kAllModesValid=0, // all display modes not deleted by PrimaryInit code - // are optional - kAllModesSafe, // all display modes not deleted by PrimaryInit code - // are required; is you set this bit, set the - // kAllModesValid bit, too - kHasDirectConnect=3, // for future expansions, setting this bit means that - // your driver can talk directly to the display - // (e.g. there is a serial data link via sense lines) - kIsMonoDev, // this display does not support color - kUncertainConnect // there may not be a display; Monitors control panel - // makes the user confirm some operations--like moving - // the menu bar-- when this bit is set -}; - -/* csTimingFormat value in VDTimingInfoRec */ -#define kDeclROMtables FOURCC('d','e','c','l') // use information in this record instead of looking - // in the decl. ROM for timing info; used for patching - // existing card without updating declaration ROM - -/* csTimingData values in VDTimingInfoRec */ -enum { - timingUnknown = 0, // unknown timing - timingApple_512x384_60hz = 130, /* 512x384 (60 Hz) Rubik timing. */ - timingApple_560x384_60hz = 135, /* 560x384 (60 Hz) Rubik-560 timing. */ - timingApple_640x480_67hz = 140, /* 640x480 (67 Hz) HR timing. */ - timingApple_640x400_67hz = 145, /* 640x400 (67 Hz) HR-400 timing. */ - timingVESA_640x480_60hz = 150, /* 640x480 (60 Hz) VGA timing. */ - timingVESA_640x480_72hz = 152, /* 640x480 (72 Hz) VGA timing. */ - timingVESA_640x480_75hz = 154, /* 640x480 (75 Hz) VGA timing. */ - timingVESA_640x480_85hz = 158, /* 640x480 (85 Hz) VGA timing. */ - timingGTF_640x480_120hz = 159, /* 640x480 (120 Hz) VESA Generalized Timing Formula */ - timingApple_640x870_75hz = 160, /* 640x870 (75 Hz) FPD timing.*/ - timingApple_640x818_75hz = 165, /* 640x818 (75 Hz) FPD-818 timing.*/ - timingApple_832x624_75hz = 170, /* 832x624 (75 Hz) GoldFish timing.*/ - timingVESA_800x600_56hz = 180, /* 800x600 (56 Hz) SVGA timing. */ - timingVESA_800x600_60hz = 182, /* 800x600 (60 Hz) SVGA timing. */ - timingVESA_800x600_72hz = 184, /* 800x600 (72 Hz) SVGA timing. */ - timingVESA_800x600_75hz = 186, /* 800x600 (75 Hz) SVGA timing. */ - timingVESA_800x600_85hz = 188, /* 800x600 (85 Hz) SVGA timing. */ - timingVESA_1024x768_60hz = 190, /* 1024x768 (60 Hz) VESA 1K-60Hz timing. */ - timingVESA_1024x768_70hz = 200, /* 1024x768 (70 Hz) VESA 1K-70Hz timing. */ - timingVESA_1024x768_75hz = 204, /* 1024x768 (75 Hz) VESA 1K-75Hz timing (very similar to timingApple_1024x768_75hz). */ - timingVESA_1024x768_85hz = 208, /* 1024x768 (85 Hz) VESA timing. */ - timingApple_1024x768_75hz = 210, /* 1024x768 (75 Hz) Apple 19" RGB. */ - timingApple_1152x870_75hz = 220, /* 1152x870 (75 Hz) Apple 21" RGB. */ - timingVESA_1280x960_75hz = 250, /* 1280x960 (75 Hz) */ - timingVESA_1280x960_60hz = 252, /* 1280x960 (60 Hz) */ - timingVESA_1280x960_85hz = 254, /* 1280x960 (85 Hz) */ - timingVESA_1280x1024_60hz = 260, /* 1280x1024 (60 Hz) */ - timingVESA_1280x1024_75hz = 262, /* 1280x1024 (75 Hz) */ - timingVESA_1280x1024_85hz = 268, /* 1280x1024 (85 Hz) */ - timingVESA_1600x1200_60hz = 280, /* 1600x1200 (60 Hz) VESA proposed timing. */ - timingVESA_1600x1200_65hz = 282, /* 1600x1200 (65 Hz) VESA proposed timing. */ - timingVESA_1600x1200_70hz = 284, /* 1600x1200 (70 Hz) VESA proposed timing. */ - timingVESA_1600x1200_75hz = 286, /* 1600x1200 (75 Hz) VESA proposed timing. */ - timingVESA_1600x1200_80hz = 288, /* 1600x1200 (80 Hz) VESA proposed timing (pixel clock is 216 Mhz dot clock). */ - timingSMPTE240M_60hz = 400, /* 60Hz V, 33.75KHz H, interlaced timing, 16:9 aspect, typical resolution of 1920x1035. */ - timingFilmRate_48hz = 410 /* 48Hz V, 25.20KHz H, non-interlaced timing, typical resolution of 640x480. */ -}; - -/* csTimingFlags values in VDTimingInfoRec */ -enum { - kModeValid=0, // this display mode is optional - kModeSafe, // this display mode is required; if you set this - // bit, you should also set the kModeValid bit - kModeDefault, // this display mode is the default for the attached - // display; if you set this bit, you should also set - // the kModeSafe and kModeValid bits - kShowModeNow, // show this mode in Monitors control panel; useful - // for SVGA modes - kModeNotResize, - kModeRequiresPan -}; - -/* code for Display Manager control request */ -enum { - cscReset=0, - cscKillIO, - cscSetMode, - cscSetEntries, - cscSetGamma, - cscGrayPage, - cscGrayScreen=5, - cscSetGray, - cscSetInterrupt, - cscDirectSetEntries, - cscSetDefaultMode, - cscSwitchMode, // switch to another display mode - cscSetSync, - cscSavePreferredConfiguration=16, - cscSetHardwareCursor=22, - cscDrawHardwareCursor, - cscSetConvolution, - cscSetPowerState, - cscPrivateControlCall, // Takes a VDPrivateSelectorDataRec - cscSetMultiConnect, // From a GDI point of view, this call should be implemented completely in the HAL and not at all in the core. - cscSetClutBehavior, // Takes a VDClutBehavior - cscUnusedCall=127 // This call used to expend the scrn resource. Its imbedded data contains more control info -}; - -/* Constants for the GetNextResolution call */ - -enum { - kDisplayModeIDCurrent = 0x00, /* Reference the Current DisplayModeID */ - kDisplayModeIDInvalid = (long)0xFFFFFFFF, /* A bogus DisplayModeID in all cases */ - kDisplayModeIDFindFirstResolution = (long)0xFFFFFFFE, /* Used in cscGetNextResolution to reset iterator */ - kDisplayModeIDNoMoreResolutions = (long)0xFFFFFFFD /* Used in cscGetNextResolution to indicate End Of List */ -}; - -/* codes for Display Manager status requests */ -enum { - cscGetMode=2, - cscGetEntries, - cscGetPageCnt, - cscGetPages=4, // This is what C&D 2 calls it. - cscGetPageBase, - cscGetBaseAddr=5, // This is what C&D 2 calls it. - cscGetGray, - cscGetInterrupt, - cscGetGamma, - cscGetDefaultMode, - cscGetCurMode, // save the current display mode - cscGetSync, - cscGetConnection, // return information about display capabilities of - // connected display - cscGetModeTiming, // return scan timings data for a display mode - cscGetModeBaseAddress, // Return base address information about a particular mode - cscGetScanProc, // QuickTime scan chasing routine - cscGetPreferredConfiguration, - cscGetNextResolution, - cscGetVideoParameters, - cscGetGammaInfoList =20, - cscRetrieveGammaTable, - cscSupportsHardwareCursor, - cscGetHardwareCursorDrawState, - cscGetConvolution, - cscGetPowerState, - cscPrivateStatusCall, // Takes a VDPrivateSelectorDataRec - cscGetDDCBlock, // Takes a VDDDCBlockRec - cscGetMultiConnect, // From a GDI point of view, this call should be implemented completely in the HAL and not at all in the core. - cscGetClutBehavior // Takes a VDClutBehavior -}; - -enum { // VDSwitchInfo struct - csMode = 0, - csData = 2, - csPage = 6, - csBaseAddr = 8 -}; - -enum { // VDSetEntry struct - csTable = 0, // Pointer to ColorSpec[] - csStart = 4, - csCount = 6 -}; - -enum { // VDGammaRecord - csGTable = 0 -}; - -enum { // ColorSpec table entry - csValue = 0, - csRed = 2, - csGreen = 4, - csBlue = 6 -}; - -enum { // VDVideoParametersInfo struct - csDisplayModeID = 0, - csDepthMode = 4, - csVPBlockPtr = 6, - csPageCount = 10, - csDeviceType = 14 -}; - -enum { // VPBlock struct - vpBaseOffset = 0, - vpRowBytes = 4, - vpBounds = 6, - vpVersion = 14, - vpPackType = 16, - vpPackSize = 18, - vpHRes = 22, - vpVRes = 26, - vpPixelType = 30, - vpPixelSize = 32, - vpCmpCount = 34, - vpCmpSize = 36, - vpPlaneBytes = 38 -}; - -enum { // VDDisplayConnectInfo struct - csDisplayType = 0, - csConnectTaggedType = 2, - csConnectTaggedData = 3, - csConnectFlags = 4, - csDisplayComponent = 8, - csConnectReserved = 12 -}; - -enum { // VDTimingInfo struct - csTimingMode = 0, - csTimingReserved = 4, - csTimingFormat = 8, - csTimingData = 12, - csTimingFlags = 16 -}; - -enum { // VDResolutionInfo struct - csPreviousDisplayModeID = 0, - csRIDisplayModeID = 4, - csHorizontalPixels = 8, - csVerticalLines = 12, - csRefreshRate = 16, - csMaxDepthMode = 20, - csResolutionFlags = 22 -}; - -enum { // VDDrawHardwareCursor/VDHardwareCursorDrawState struct - csCursorX = 0, - csCursorY = 4, - csCursorVisible = 8, - csCursorSet = 12 -}; - -enum { // struct GammaTbl - gVersion = 0, - gType = 2, - gFormulaSize = 4, - gChanCnt = 6, - gDataCnt = 8, - gDataWidth = 10, - gFormulaData = 12, // variable size - SIZEOF_GammaTbl = 12 -}; - -enum { - kCursorImageMajorVersion = 0x0001, - kCursorImageMinorVersion = 0x0000 -}; - -enum { // CursorImage struct - ciMajorVersion = 0, - ciMinorVersion = 2, - ciCursorPixMap = 4, // Handle to PixMap - ciCursorBitMask = 8 // Handle to BitMap -}; - - -/* - * Structures for graphics acceleration - */ - -typedef uint32 CTabHandle; - -// Parameter block passed to acceleration hooks -struct accl_params { - uint32 unknown0[3]; - - uint32 transfer_mode; - uint32 pen_mode; - - uint32 unknown1[2]; - - uint32 fore_pen; - uint32 back_pen; - - uint32 unknown2[3]; - - uint32 src_base_addr; - int32 src_row_bytes; - int16 src_bounds[4]; - uint32 src_unknown1; - uint32 src_pixel_type; - uint32 src_pixel_size; - uint32 src_cmp_count; - uint32 src_cmp_size; - CTabHandle src_pm_table; - uint32 src_unknown2; - uint32 src_unknown3; - uint32 src_unknown4; - - uint32 dest_base_addr; - int32 dest_row_bytes; - int16 dest_bounds[4]; - uint32 dest_unknown1; - uint32 dest_pixel_type; - uint32 dest_pixel_size; - uint32 dest_cmp_count; - uint32 dest_cmp_size; - CTabHandle dest_pm_table; - uint32 dest_unknown2; - uint32 dest_unknown3; - uint32 dest_unknown4; - - uint32 unknown3[13]; - - int16 src_rect[4]; - int16 dest_rect[4]; - - uint32 unknown4[38]; - - uint32 draw_proc; - // Argument for accl_sync_hook at offset 0x4f8 -}; - -enum { - acclTransferMode = offsetof(accl_params, transfer_mode), - acclPenMode = offsetof(accl_params, pen_mode), - acclForePen = offsetof(accl_params, fore_pen), - acclBackPen = offsetof(accl_params, back_pen), - acclSrcBaseAddr = offsetof(accl_params, src_base_addr), - acclSrcRowBytes = offsetof(accl_params, src_row_bytes), - acclSrcBoundsRect = offsetof(accl_params, src_bounds), - acclSrcPixelType = offsetof(accl_params, src_pixel_type), - acclSrcPixelSize = offsetof(accl_params, src_pixel_size), - acclSrcCmpCount = offsetof(accl_params, src_cmp_count), - acclSrcCmpSize = offsetof(accl_params, src_cmp_size), - acclSrcPMTable = offsetof(accl_params, src_pm_table), - acclDestBaseAddr = offsetof(accl_params, dest_base_addr), - acclDestRowBytes = offsetof(accl_params, dest_row_bytes), - acclDestBoundsRect = offsetof(accl_params, dest_bounds), - acclDestPixelType = offsetof(accl_params, dest_pixel_type), - acclDestPixelSize = offsetof(accl_params, dest_pixel_size), - acclDestCmpCount = offsetof(accl_params, dest_cmp_count), - acclDestCmpSize = offsetof(accl_params, dest_cmp_size), - acclDestPMTable = offsetof(accl_params, dest_pm_table), - acclSrcRect = offsetof(accl_params, src_rect), - acclDestRect = offsetof(accl_params, dest_rect), - acclDrawProc = offsetof(accl_params, draw_proc) -}; - -// Hook info for NQDMisc -struct accl_hook_info { - uint32 draw_func; - uint32 sync_func; - uint32 code; -}; - -// Hook function index -enum { - ACCL_BITBLT, - ACCL_BLTMASK, - ACCL_FILLRECT, - ACCL_FILLMASK - // 4: bitblt - // 5: lines - // 6: fill -}; - -#endif diff --git a/SheepShaver/src/include/xlowmem.h b/SheepShaver/src/include/xlowmem.h deleted file mode 100644 index c986d73d..00000000 --- a/SheepShaver/src/include/xlowmem.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * xlowmem.h - Definitions for extra Low Memory globals (0x2800..) - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef XLOWMEM_H -#define XLOWMEM_H - -// Modes for XLM_RUN_MODE -#define MODE_68K 0 // 68k emulator active -#define MODE_NATIVE 1 // Switched to native mode -#define MODE_EMUL_OP 2 // 68k emulator active, within EMUL_OP routine - -#define XLM_SIGNATURE 0x2800 // SheepShaver signature -#define XLM_KERNEL_DATA 0x2804 // Pointer to Kernel Data -#define XLM_TOC 0x2808 // TOC pointer of emulator -#define XLM_SHEEP_OBJ 0x280c // Pointer to SheepShaver object -#define XLM_RUN_MODE 0x2810 // Current run mode, see enum above -#define XLM_68K_R25 0x2814 // Contents of the 68k emulator's r25 (which contains the interrupt level), saved upon entering EMUL_OP mode, used by Execute68k() and the USR1 signal handler -#define XLM_IRQ_NEST 0x2818 // Interrupt disable nesting counter (>0: disabled) -#define XLM_PVR 0x281c // Theoretical PVR -#define XLM_BUS_CLOCK 0x2820 // Bus clock speed in Hz (for DriverServicesLib patch) -#define XLM_EMUL_RETURN_PROC 0x2824 // Pointer to EMUL_RETURN routine -#define XLM_EXEC_RETURN_PROC 0x2828 // Pointer to EXEC_RETURN routine -#define XLM_EMUL_OP_PROC 0x282c // Pointer to EMUL_OP routine -#define XLM_EMUL_RETURN_STACK 0x2830 // Stack pointer for EMUL_RETURN -#define XLM_RES_LIB_TOC 0x2834 // TOC pointer of Resources library -#define XLM_GET_RESOURCE 0x2838 // Pointer to native GetResource() routine -#define XLM_GET_1_RESOURCE 0x283c // Pointer to native Get1Resource() routine -#define XLM_GET_IND_RESOURCE 0x2840 // Pointer to native GetIndResource() routine -#define XLM_GET_1_IND_RESOURCE 0x2844 // Pointer to native Get1IndResource() routine -#define XLM_R_GET_RESOURCE 0x2848 // Pointer to native RGetResource() routine -#define XLM_EXEC_RETURN_OPCODE 0x284c // EXEC_RETURN opcode for Execute68k() -#define XLM_ZERO_PAGE 0x2850 // Pointer to read-only page with all bits set to 0 -#define XLM_R13 0x2854 // Pointer to .sdata section (Linux) -#define XLM_GET_NAMED_RESOURCE 0x2858 // Pointer to native GetNamedResource() routine -#define XLM_GET_1_NAMED_RESOURCE 0x285c // Pointer to native Get1NamedResource() routine - -#define XLM_ETHER_AO_GET_HWADDR 0x28b0 // Pointer to ethernet A0_get_ethernet_address() function -#define XLM_ETHER_AO_ADD_MULTI 0x28b4 // Pointer to ethernet A0_enable_multicast() function -#define XLM_ETHER_AO_DEL_MULTI 0x28b8 // Pointer to ethernet A0_disable_multicast() function -#define XLM_ETHER_AO_SEND_PACKET 0x28bc // Pointer to ethernet A0_transmit_packet() function -#define XLM_ETHER_INIT 0x28c0 // Pointer to ethernet InitStreamModule() function -#define XLM_ETHER_TERM 0x28c4 // Pointer to ethernet TerminateStreamModule() function -#define XLM_ETHER_OPEN 0x28c8 // Pointer to ethernet ether_open() function -#define XLM_ETHER_CLOSE 0x28cc // Pointer to ethernet ether_close() function -#define XLM_ETHER_WPUT 0x28d0 // Pointer to ethernet ether_wput() function -#define XLM_ETHER_RSRV 0x28d4 // Pointer to ethernet ether_rsrv() function -#define XLM_VIDEO_DOIO 0x28d8 // Pointer to video DoDriverIO() function - -#endif diff --git a/SheepShaver/src/include/xpram.h b/SheepShaver/src/include/xpram.h deleted file mode 120000 index 382aa791..00000000 --- a/SheepShaver/src/include/xpram.h +++ /dev/null @@ -1 +0,0 @@ -../../../BasiliskII/src/include/xpram.h \ No newline at end of file diff --git a/SheepShaver/src/kpx_cpu/dis-asm.h b/SheepShaver/src/kpx_cpu/dis-asm.h deleted file mode 100644 index 639ace1a..00000000 --- a/SheepShaver/src/kpx_cpu/dis-asm.h +++ /dev/null @@ -1,483 +0,0 @@ -/* Interface between the opcode library and its callers. - Written by Cygnus Support, 1993. - - The opcode library (libopcodes.a) provides instruction decoders for - a large variety of instruction sets, callable with an identical - interface, for making instruction-processing programs more independent - of the instruction set being processed. */ - -#ifndef DIS_ASM_H -#define DIS_ASM_H - -#include -#include - -typedef int (*fprintf_function)(FILE *f, const char *fmt, ...); - -typedef void *PTR; -typedef uint64_t bfd_vma; -typedef int64_t bfd_signed_vma; -typedef uint8_t bfd_byte; -#define sprintf_vma(s,x) sprintf (s, "%0" PRIx64, x) -#define snprintf_vma(s,ss,x) snprintf (s, ss, "%0" PRIx64, x) - -#define BFD64 - -enum bfd_flavour { - bfd_target_unknown_flavour, - bfd_target_aout_flavour, - bfd_target_coff_flavour, - bfd_target_ecoff_flavour, - bfd_target_elf_flavour, - bfd_target_ieee_flavour, - bfd_target_nlm_flavour, - bfd_target_oasys_flavour, - bfd_target_tekhex_flavour, - bfd_target_srec_flavour, - bfd_target_ihex_flavour, - bfd_target_som_flavour, - bfd_target_os9k_flavour, - bfd_target_versados_flavour, - bfd_target_msdos_flavour, - bfd_target_evax_flavour -}; - -enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; - -enum bfd_architecture -{ - bfd_arch_unknown, /* File arch not known */ - bfd_arch_obscure, /* Arch known, not one of these */ - bfd_arch_m68k, /* Motorola 68xxx */ -#define bfd_mach_m68000 1 -#define bfd_mach_m68008 2 -#define bfd_mach_m68010 3 -#define bfd_mach_m68020 4 -#define bfd_mach_m68030 5 -#define bfd_mach_m68040 6 -#define bfd_mach_m68060 7 -#define bfd_mach_cpu32 8 -#define bfd_mach_mcf5200 9 -#define bfd_mach_mcf5206e 10 -#define bfd_mach_mcf5307 11 -#define bfd_mach_mcf5407 12 -#define bfd_mach_mcf528x 13 -#define bfd_mach_mcfv4e 14 -#define bfd_mach_mcf521x 15 -#define bfd_mach_mcf5249 16 -#define bfd_mach_mcf547x 17 -#define bfd_mach_mcf548x 18 - bfd_arch_vax, /* DEC Vax */ - bfd_arch_i960, /* Intel 960 */ - /* The order of the following is important. - lower number indicates a machine type that - only accepts a subset of the instructions - available to machines with higher numbers. - The exception is the "ca", which is - incompatible with all other machines except - "core". */ - -#define bfd_mach_i960_core 1 -#define bfd_mach_i960_ka_sa 2 -#define bfd_mach_i960_kb_sb 3 -#define bfd_mach_i960_mc 4 -#define bfd_mach_i960_xa 5 -#define bfd_mach_i960_ca 6 -#define bfd_mach_i960_jx 7 -#define bfd_mach_i960_hx 8 - - bfd_arch_a29k, /* AMD 29000 */ - bfd_arch_sparc, /* SPARC */ -#define bfd_mach_sparc 1 -/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */ -#define bfd_mach_sparc_sparclet 2 -#define bfd_mach_sparc_sparclite 3 -#define bfd_mach_sparc_v8plus 4 -#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */ -#define bfd_mach_sparc_sparclite_le 6 -#define bfd_mach_sparc_v9 7 -#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */ -#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */ -#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */ -/* Nonzero if MACH has the v9 instruction set. */ -#define bfd_mach_sparc_v9_p(mach) \ - ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \ - && (mach) != bfd_mach_sparc_sparclite_le) - bfd_arch_mips, /* MIPS Rxxxx */ -#define bfd_mach_mips3000 3000 -#define bfd_mach_mips3900 3900 -#define bfd_mach_mips4000 4000 -#define bfd_mach_mips4010 4010 -#define bfd_mach_mips4100 4100 -#define bfd_mach_mips4300 4300 -#define bfd_mach_mips4400 4400 -#define bfd_mach_mips4600 4600 -#define bfd_mach_mips4650 4650 -#define bfd_mach_mips5000 5000 -#define bfd_mach_mips6000 6000 -#define bfd_mach_mips8000 8000 -#define bfd_mach_mips10000 10000 -#define bfd_mach_mips16 16 - bfd_arch_i386, /* Intel 386 */ -#define bfd_mach_i386_i386 0 -#define bfd_mach_i386_i8086 1 -#define bfd_mach_i386_i386_intel_syntax 2 -#define bfd_mach_x86_64 3 -#define bfd_mach_x86_64_intel_syntax 4 - bfd_arch_we32k, /* AT&T WE32xxx */ - bfd_arch_tahoe, /* CCI/Harris Tahoe */ - bfd_arch_i860, /* Intel 860 */ - bfd_arch_romp, /* IBM ROMP PC/RT */ - bfd_arch_alliant, /* Alliant */ - bfd_arch_convex, /* Convex */ - bfd_arch_m88k, /* Motorola 88xxx */ - bfd_arch_pyramid, /* Pyramid Technology */ - bfd_arch_h8300, /* Hitachi H8/300 */ -#define bfd_mach_h8300 1 -#define bfd_mach_h8300h 2 -#define bfd_mach_h8300s 3 - bfd_arch_powerpc, /* PowerPC */ -#define bfd_mach_ppc 0 -#define bfd_mach_ppc64 1 -#define bfd_mach_ppc_403 403 -#define bfd_mach_ppc_403gc 4030 -#define bfd_mach_ppc_e500 500 -#define bfd_mach_ppc_505 505 -#define bfd_mach_ppc_601 601 -#define bfd_mach_ppc_602 602 -#define bfd_mach_ppc_603 603 -#define bfd_mach_ppc_ec603e 6031 -#define bfd_mach_ppc_604 604 -#define bfd_mach_ppc_620 620 -#define bfd_mach_ppc_630 630 -#define bfd_mach_ppc_750 750 -#define bfd_mach_ppc_860 860 -#define bfd_mach_ppc_a35 35 -#define bfd_mach_ppc_rs64ii 642 -#define bfd_mach_ppc_rs64iii 643 -#define bfd_mach_ppc_7400 7400 - bfd_arch_rs6000, /* IBM RS/6000 */ - bfd_arch_hppa, /* HP PA RISC */ -#define bfd_mach_hppa10 10 -#define bfd_mach_hppa11 11 -#define bfd_mach_hppa20 20 -#define bfd_mach_hppa20w 25 - bfd_arch_d10v, /* Mitsubishi D10V */ - bfd_arch_z8k, /* Zilog Z8000 */ -#define bfd_mach_z8001 1 -#define bfd_mach_z8002 2 - bfd_arch_h8500, /* Hitachi H8/500 */ - bfd_arch_sh, /* Hitachi SH */ -#define bfd_mach_sh 1 -#define bfd_mach_sh2 0x20 -#define bfd_mach_sh_dsp 0x2d -#define bfd_mach_sh2a 0x2a -#define bfd_mach_sh2a_nofpu 0x2b -#define bfd_mach_sh2e 0x2e -#define bfd_mach_sh3 0x30 -#define bfd_mach_sh3_nommu 0x31 -#define bfd_mach_sh3_dsp 0x3d -#define bfd_mach_sh3e 0x3e -#define bfd_mach_sh4 0x40 -#define bfd_mach_sh4_nofpu 0x41 -#define bfd_mach_sh4_nommu_nofpu 0x42 -#define bfd_mach_sh4a 0x4a -#define bfd_mach_sh4a_nofpu 0x4b -#define bfd_mach_sh4al_dsp 0x4d -#define bfd_mach_sh5 0x50 - bfd_arch_alpha, /* Dec Alpha */ -#define bfd_mach_alpha 1 -#define bfd_mach_alpha_ev4 0x10 -#define bfd_mach_alpha_ev5 0x20 -#define bfd_mach_alpha_ev6 0x30 - bfd_arch_arm, /* Advanced Risc Machines ARM */ -#define bfd_mach_arm_unknown 0 -#define bfd_mach_arm_2 1 -#define bfd_mach_arm_2a 2 -#define bfd_mach_arm_3 3 -#define bfd_mach_arm_3M 4 -#define bfd_mach_arm_4 5 -#define bfd_mach_arm_4T 6 -#define bfd_mach_arm_5 7 -#define bfd_mach_arm_5T 8 -#define bfd_mach_arm_5TE 9 -#define bfd_mach_arm_XScale 10 -#define bfd_mach_arm_ep9312 11 -#define bfd_mach_arm_iWMMXt 12 -#define bfd_mach_arm_iWMMXt2 13 - bfd_arch_ns32k, /* National Semiconductors ns32000 */ - bfd_arch_w65, /* WDC 65816 */ - bfd_arch_tic30, /* Texas Instruments TMS320C30 */ - bfd_arch_v850, /* NEC V850 */ -#define bfd_mach_v850 0 - bfd_arch_arc, /* Argonaut RISC Core */ -#define bfd_mach_arc_base 0 - bfd_arch_m32r, /* Mitsubishi M32R/D */ -#define bfd_mach_m32r 0 /* backwards compatibility */ - bfd_arch_mn10200, /* Matsushita MN10200 */ - bfd_arch_mn10300, /* Matsushita MN10300 */ - bfd_arch_cris, /* Axis CRIS */ -#define bfd_mach_cris_v0_v10 255 -#define bfd_mach_cris_v32 32 -#define bfd_mach_cris_v10_v32 1032 - bfd_arch_microblaze, /* Xilinx MicroBlaze. */ - bfd_arch_ia64, /* HP/Intel ia64 */ -#define bfd_mach_ia64_elf64 64 -#define bfd_mach_ia64_elf32 32 - bfd_arch_last - }; -#define bfd_mach_s390_31 31 -#define bfd_mach_s390_64 64 - -typedef struct symbol_cache_entry -{ - const char *name; - union - { - PTR p; - bfd_vma i; - } udata; -} asymbol; - -enum dis_insn_type { - dis_noninsn, /* Not a valid instruction */ - dis_nonbranch, /* Not a branch instruction */ - dis_branch, /* Unconditional branch */ - dis_condbranch, /* Conditional branch */ - dis_jsr, /* Jump to subroutine */ - dis_condjsr, /* Conditional jump to subroutine */ - dis_dref, /* Data reference instruction */ - dis_dref2 /* Two data references in instruction */ -}; - -/* This struct is passed into the instruction decoding routine, - and is passed back out into each callback. The various fields are used - for conveying information from your main routine into your callbacks, - for passing information into the instruction decoders (such as the - addresses of the callback functions), or for passing information - back from the instruction decoders to their callers. - - It must be initialized before it is first passed; this can be done - by hand, or using one of the initialization macros below. */ - -typedef struct disassemble_info { - fprintf_function fprintf_func; - FILE *stream; - PTR application_data; - - /* Target description. We could replace this with a pointer to the bfd, - but that would require one. There currently isn't any such requirement - so to avoid introducing one we record these explicitly. */ - /* The bfd_flavour. This can be bfd_target_unknown_flavour. */ - enum bfd_flavour flavour; - /* The bfd_arch value. */ - enum bfd_architecture arch; - /* The bfd_mach value. */ - unsigned long mach; - /* Endianness (for bi-endian cpus). Mono-endian cpus can ignore this. */ - enum bfd_endian endian; - - /* An array of pointers to symbols either at the location being disassembled - or at the start of the function being disassembled. The array is sorted - so that the first symbol is intended to be the one used. The others are - present for any misc. purposes. This is not set reliably, but if it is - not NULL, it is correct. */ - asymbol **symbols; - /* Number of symbols in array. */ - int num_symbols; - - /* For use by the disassembler. - The top 16 bits are reserved for public use (and are documented here). - The bottom 16 bits are for the internal use of the disassembler. */ - unsigned long flags; -#define INSN_HAS_RELOC 0x80000000 - PTR private_data; - - /* Function used to get bytes to disassemble. MEMADDR is the - address of the stuff to be disassembled, MYADDR is the address to - put the bytes in, and LENGTH is the number of bytes to read. - INFO is a pointer to this struct. - Returns an errno value or 0 for success. */ - int (*read_memory_func) - (bfd_vma memaddr, bfd_byte *myaddr, int length, - struct disassemble_info *info); - - /* Function which should be called if we get an error that we can't - recover from. STATUS is the errno value from read_memory_func and - MEMADDR is the address that we were trying to read. INFO is a - pointer to this struct. */ - void (*memory_error_func) - (int status, bfd_vma memaddr, struct disassemble_info *info); - - /* Function called to print ADDR. */ - void (*print_address_func) - (bfd_vma addr, struct disassemble_info *info); - - /* Function called to determine if there is a symbol at the given ADDR. - If there is, the function returns 1, otherwise it returns 0. - This is used by ports which support an overlay manager where - the overlay number is held in the top part of an address. In - some circumstances we want to include the overlay number in the - address, (normally because there is a symbol associated with - that address), but sometimes we want to mask out the overlay bits. */ - int (* symbol_at_address_func) - (bfd_vma addr, struct disassemble_info * info); - - /* These are for buffer_read_memory. */ - bfd_byte *buffer; - bfd_vma buffer_vma; - int buffer_length; - - /* This variable may be set by the instruction decoder. It suggests - the number of bytes objdump should display on a single line. If - the instruction decoder sets this, it should always set it to - the same value in order to get reasonable looking output. */ - int bytes_per_line; - - /* the next two variables control the way objdump displays the raw data */ - /* For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the */ - /* output will look like this: - 00: 00000000 00000000 - with the chunks displayed according to "display_endian". */ - int bytes_per_chunk; - enum bfd_endian display_endian; - - /* Results from instruction decoders. Not all decoders yet support - this information. This info is set each time an instruction is - decoded, and is only valid for the last such instruction. - - To determine whether this decoder supports this information, set - insn_info_valid to 0, decode an instruction, then check it. */ - - char insn_info_valid; /* Branch info has been set. */ - char branch_delay_insns; /* How many sequential insn's will run before - a branch takes effect. (0 = normal) */ - char data_size; /* Size of data reference in insn, in bytes */ - enum dis_insn_type insn_type; /* Type of instruction */ - bfd_vma target; /* Target address of branch or dref, if known; - zero if unknown. */ - bfd_vma target2; /* Second target address for dref2 */ - - /* Command line options specific to the target disassembler. */ - char * disassembler_options; - -} disassemble_info; - - -/* Standard disassemblers. Disassemble one instruction at the given - target address. Return number of bytes processed. */ -typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *); - -int print_insn_tci(bfd_vma, disassemble_info*); -int print_insn_big_mips (bfd_vma, disassemble_info*); -int print_insn_little_mips (bfd_vma, disassemble_info*); -int print_insn_i386 (bfd_vma, disassemble_info*); -int print_insn_m68k (bfd_vma, disassemble_info*); -int print_insn_z8001 (bfd_vma, disassemble_info*); -int print_insn_z8002 (bfd_vma, disassemble_info*); -int print_insn_h8300 (bfd_vma, disassemble_info*); -int print_insn_h8300h (bfd_vma, disassemble_info*); -int print_insn_h8300s (bfd_vma, disassemble_info*); -int print_insn_h8500 (bfd_vma, disassemble_info*); -int print_insn_alpha (bfd_vma, disassemble_info*); -disassembler_ftype arc_get_disassembler (int, int); -int print_insn_arm (bfd_vma, disassemble_info*); -int print_insn_sparc (bfd_vma, disassemble_info*); -int print_insn_big_a29k (bfd_vma, disassemble_info*); -int print_insn_little_a29k (bfd_vma, disassemble_info*); -int print_insn_i960 (bfd_vma, disassemble_info*); -int print_insn_sh (bfd_vma, disassemble_info*); -int print_insn_shl (bfd_vma, disassemble_info*); -int print_insn_hppa (bfd_vma, disassemble_info*); -int print_insn_m32r (bfd_vma, disassemble_info*); -int print_insn_m88k (bfd_vma, disassemble_info*); -int print_insn_mn10200 (bfd_vma, disassemble_info*); -int print_insn_mn10300 (bfd_vma, disassemble_info*); -int print_insn_ns32k (bfd_vma, disassemble_info*); -int print_insn_big_powerpc (bfd_vma, disassemble_info*); -int print_insn_little_powerpc (bfd_vma, disassemble_info*); -int print_insn_rs6000 (bfd_vma, disassemble_info*); -int print_insn_w65 (bfd_vma, disassemble_info*); -int print_insn_d10v (bfd_vma, disassemble_info*); -int print_insn_v850 (bfd_vma, disassemble_info*); -int print_insn_tic30 (bfd_vma, disassemble_info*); -int print_insn_ppc (bfd_vma, disassemble_info*); -int print_insn_s390 (bfd_vma, disassemble_info*); -int print_insn_crisv32 (bfd_vma, disassemble_info*); -int print_insn_crisv10 (bfd_vma, disassemble_info*); -int print_insn_microblaze (bfd_vma, disassemble_info*); -int print_insn_ia64 (bfd_vma, disassemble_info*); - -#if 0 -/* Fetch the disassembler for a given BFD, if that support is available. */ -disassembler_ftype disassembler(bfd *); -#endif - - -/* This block of definitions is for particular callers who read instructions - into a buffer before calling the instruction decoder. */ - -/* Here is a function which callers may wish to use for read_memory_func. - It gets bytes from a buffer. */ -int buffer_read_memory(bfd_vma, bfd_byte *, int, struct disassemble_info *); - -/* This function goes with buffer_read_memory. - It prints a message using info->fprintf_func and info->stream. */ -void perror_memory(int, bfd_vma, struct disassemble_info *); - - -/* Just print the address in hex. This is included for completeness even - though both GDB and objdump provide their own (to print symbolic - addresses). */ -void generic_print_address(bfd_vma, struct disassemble_info *); - -/* Always true. */ -int generic_symbol_at_address(bfd_vma, struct disassemble_info *); - -/* Macro to initialize a disassemble_info struct. This should be called - by all applications creating such a struct. */ -#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \ - (INFO).flavour = bfd_target_unknown_flavour, \ - (INFO).arch = bfd_arch_unknown, \ - (INFO).mach = 0, \ - (INFO).endian = BFD_ENDIAN_UNKNOWN, \ - INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) - -/* Call this macro to initialize only the internal variables for the - disassembler. Architecture dependent things such as byte order, or machine - variant are not touched by this macro. This makes things much easier for - GDB which must initialize these things separately. */ - -#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \ - (INFO).fprintf_func = (FPRINTF_FUNC), \ - (INFO).stream = (STREAM), \ - (INFO).symbols = NULL, \ - (INFO).num_symbols = 0, \ - (INFO).private_data = NULL, \ - (INFO).buffer = NULL, \ - (INFO).buffer_vma = 0, \ - (INFO).buffer_length = 0, \ - (INFO).read_memory_func = buffer_read_memory, \ - (INFO).memory_error_func = perror_memory, \ - (INFO).print_address_func = generic_print_address, \ - (INFO).symbol_at_address_func = generic_symbol_at_address, \ - (INFO).flags = 0, \ - (INFO).bytes_per_line = 0, \ - (INFO).bytes_per_chunk = 0, \ - (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \ - (INFO).disassembler_options = NULL, \ - (INFO).insn_info_valid = 0 - -#define _(x) x -#define ATTRIBUTE_UNUSED __attribute__((unused)) - -/* from libbfd */ - -bfd_vma bfd_getl64 (const bfd_byte *addr); -bfd_vma bfd_getl32 (const bfd_byte *addr); -bfd_vma bfd_getb32 (const bfd_byte *addr); -bfd_vma bfd_getl16 (const bfd_byte *addr); -bfd_vma bfd_getb16 (const bfd_byte *addr); -typedef int bfd_boolean; - -#endif /* ! defined (DIS_ASM_H) */ diff --git a/SheepShaver/src/kpx_cpu/include/a.out-defs.h b/SheepShaver/src/kpx_cpu/include/a.out-defs.h deleted file mode 100644 index d876677a..00000000 --- a/SheepShaver/src/kpx_cpu/include/a.out-defs.h +++ /dev/null @@ -1,443 +0,0 @@ -/* a.out.h - - Copyright 1997, 1998, 1999, 2001 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef _A_OUT_H_ -#define _A_OUT_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#define COFF_IMAGE_WITH_PE -#define COFF_LONG_SECTION_NAMES - -/*** coff information for Intel 386/486. */ - - -/********************** FILE HEADER **********************/ - -struct external_filehdr { - int16_t f_magic; /* magic number */ - int16_t f_nscns; /* number of sections */ - uint32_t f_timdat; /* time & date stamp */ - uint32_t f_symptr; /* file pointer to symtab */ - uint32_t f_nsyms; /* number of symtab entries */ - int16_t f_opthdr; /* sizeof(optional hdr) */ - int16_t f_flags; /* flags */ -}; - -/* Bits for f_flags: - * F_RELFLG relocation info stripped from file - * F_EXEC file is executable (no unresolved external references) - * F_LNNO line numbers stripped from file - * F_LSYMS local symbols stripped from file - * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax) - */ - -#define F_RELFLG (0x0001) -#define F_EXEC (0x0002) -#define F_LNNO (0x0004) -#define F_LSYMS (0x0008) - - - -#define I386MAGIC 0x14c -#define I386PTXMAGIC 0x154 -#define I386AIXMAGIC 0x175 - -/* This is Lynx's all-platform magic number for executables. */ - -#define LYNXCOFFMAGIC 0415 - -#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \ - && (x).f_magic != I386AIXMAGIC \ - && (x).f_magic != I386PTXMAGIC \ - && (x).f_magic != LYNXCOFFMAGIC) - -#define FILHDR struct external_filehdr -#define FILHSZ 20 - - -/********************** AOUT "OPTIONAL HEADER"= - **********************/ - - -typedef struct -{ - uint16_t magic; /* type of file */ - uint16_t vstamp; /* version stamp */ - uint32_t tsize; /* text size in bytes, padded to FW bdry*/ - uint32_t dsize; /* initialized data " " */ - uint32_t bsize; /* uninitialized data " " */ - uint32_t entry; /* entry pt. */ - uint32_t text_start; /* base of text used for this file */ - uint32_t data_start; /* base of data used for this file= - */ -} -AOUTHDR; - -#define AOUTSZ 28 -#define AOUTHDRSZ 28 - -#define OMAGIC 0404 /* object files, eg as output */ -#define ZMAGIC 0413 /* demand load format, eg normal ld output */ -#define STMAGIC 0401 /* target shlib */ -#define SHMAGIC 0443 /* host shlib */ - - -/* define some NT default values */ -/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */ -#define NT_SECTION_ALIGNMENT 0x1000 -#define NT_FILE_ALIGNMENT 0x200 -#define NT_DEF_RESERVE 0x100000 -#define NT_DEF_COMMIT 0x1000 - -/********************** SECTION HEADER **********************/ - - -struct external_scnhdr { - char s_name[8]; /* section name */ - uint32_t s_paddr; /* physical address, offset - of last addr in scn */ - uint32_t s_vaddr; /* virtual address */ - uint32_t s_size; /* section size */ - uint32_t s_scnptr; /* file ptr to raw data for section */ - uint32_t s_relptr; /* file ptr to relocation */ - uint32_t s_lnnoptr; /* file ptr to line numbers */ - uint16_t s_nreloc; /* number of relocation entries */ - uint16_t s_nlnno; /* number of line number entries*/ - uint32_t s_flags; /* flags */ -}; - -#define SCNHDR struct external_scnhdr -#define SCNHSZ 40 - -/* - * names of "special" sections - */ -#define _TEXT ".text" -#define _DATA ".data" -#define _BSS ".bss" -#define _COMMENT ".comment" -#define _LIB ".lib" - -/********************** LINE NUMBERS **********************/ - -/* 1 line number entry for every "breakpointable" source line in a section. - * Line numbers are grouped on a per function basis; first entry in a function - * grouping will have l_lnno = 0 and in place of physical address will be the - * symbol table index of the function name. - */ -struct external_lineno { - union { - uint32_t l_symndx; /* function name symbol index, iff l_lnno 0 */ - uint32_t l_paddr; /* (physical) address of line number */ - } l_addr; - uint16_t l_lnno; /* line number */ -}; - -#define LINENO struct external_lineno -#define LINESZ 6 - -/********************** SYMBOLS **********************/ - -#define E_SYMNMLEN 8 /* # characters in a symbol name */ -#define E_FILNMLEN 14 /* # characters in a file name */ -#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ - -struct external_syment -{ - union { - char e_name[E_SYMNMLEN]; - struct { - uint32_t e_zeroes; - uint32_t e_offset; - } e; - } e; - uint32_t e_value; - uint16_t e_scnum; - uint16_t e_type; - char e_sclass[1]; - char e_numaux[1]; -} __attribute__((packed)); - -#ifndef _WIN32 -#define N_BTMASK (0xf) -#define N_TMASK (0x30) -#define N_BTSHFT (4) -#define N_TSHIFT (2) -#endif - -union external_auxent { - struct { - uint32_t x_tagndx; /* str, un, or enum tag indx */ - union { - struct { - uint16_t x_lnno; /* declaration line number */ - uint16_t x_size; /* str/union/array size */ - } x_lnsz; - uint32_t x_fsize; /* size of function */ - } x_misc; - union { - struct { /* if ISFCN, tag, or .bb */ - uint32_t x_lnnoptr; /* ptr to fcn line # */ - uint32_t x_endndx; /* entry ndx past block end */ - } x_fcn; - struct { /* if ISARY, up to 4 dimen. */ - char x_dimen[E_DIMNUM][2]; - } x_ary; - } x_fcnary; - uint16_t x_tvndx; /* tv index */ - } x_sym; - - union { - char x_fname[E_FILNMLEN]; - struct { - uint32_t x_zeroes; - uint32_t x_offset; - } x_n; - } x_file; - - struct { - uint32_t x_scnlen; /* section length */ - uint16_t x_nreloc; /* # relocation entries */ - uint16_t x_nlinno; /* # line numbers */ - uint32_t x_checksum; /* section COMDAT checksum */ - uint16_t x_associated;/* COMDAT associated section index */ - char x_comdat[1]; /* COMDAT selection number */ - } x_scn; - - struct { - uint32_t x_tvfill; /* tv fill value */ - uint16_t x_tvlen; /* length of .tv */ - char x_tvran[2][2]; /* tv range */ - } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ - -}; - -#define SYMENT struct external_syment -#define SYMESZ 18 -#define AUXENT union external_auxent -#define AUXESZ 18 - -#define _ETEXT "etext" - -/********************** RELOCATION DIRECTIVES **********************/ - -struct external_reloc { - char r_vaddr[4]; - char r_symndx[4]; - char r_type[2]; -}; - -#define RELOC struct external_reloc -#define RELSZ 10 - -/* end of coff/i386.h */ - -/* PE COFF header information */ - -#ifndef _PE_H -#define _PE_H - -/* NT specific file attributes */ -#ifndef _WIN32 -#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 -#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 -#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 -#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 -#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 -#define IMAGE_FILE_32BIT_MACHINE 0x0100 -#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 -#define IMAGE_FILE_SYSTEM 0x1000 -#define IMAGE_FILE_DLL 0x2000 -#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 -#endif - -/* additional flags to be set for section headers to allow the NT loader to - read and write to the section data (to replace the addresses of data in - dlls for one thing); also to execute the section in .text's case= - */ -#ifndef _WIN32 -#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -#define IMAGE_SCN_MEM_EXECUTE 0x20000000 -#define IMAGE_SCN_MEM_READ 0x40000000 -#define IMAGE_SCN_MEM_WRITE 0x80000000 -#endif - -/* - * Section characteristics added for ppc-nt - */ - -#ifndef _WIN32 -#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */ - -#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */ -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */ -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */ - -#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */ -#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */ -#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */ -#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */ - -#define IMAGE_SCN_MEM_FARDATA 0x00008000 - -#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 -#define IMAGE_SCN_MEM_16BIT 0x00020000 -#define IMAGE_SCN_MEM_LOCKED 0x00040000 -#define IMAGE_SCN_MEM_PRELOAD 0x00080000 - -#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 -#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 -#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 -#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 -#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */ -#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 -#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 - - -#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */ -#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */ -#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */ -#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */ -#endif - -/* COMDAT selection codes. */ - -#ifndef _WIN32 -#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */ -#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */ -#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */ -#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */ -#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */ -#endif - -/* Magic values that are true for all dos/nt implementations */ -#define DOSMAGIC 0x5a4d -#define NT_SIGNATURE 0x00004550 - -/* NT allows long filenames, we want to accommodate this. This may break - some of the bfd functions */ -#undef FILNMLEN -#define FILNMLEN 18 /* # characters in a file name */ - - -#ifdef COFF_IMAGE_WITH_PE -/* The filehdr is only weired in images */ - -#undef FILHDR -struct external_PE_filehdr -{ - /* DOS header fields */ - uint16_t e_magic; /* Magic number, 0x5a4d */ - uint16_t e_cblp; /* Bytes on last page of file, 0x90 */ - uint16_t e_cp; /* Pages in file, 0x3 */ - uint16_t e_crlc; /* Relocations, 0x0 */ - uint16_t e_cparhdr; /* Size of header in paragraphs, 0x4 */ - uint16_t e_minalloc; /* Minimum extra paragraphs needed, 0x0 */ - uint16_t e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */ - uint16_t e_ss; /* Initial (relative) SS value, 0x0 */ - uint16_t e_sp; /* Initial SP value, 0xb8 */ - uint16_t e_csum; /* Checksum, 0x0 */ - uint16_t e_ip; /* Initial IP value, 0x0 */ - uint16_t e_cs; /* Initial (relative) CS value, 0x0 */ - uint16_t e_lfarlc; /* File address of relocation table, 0x40 */ - uint16_t e_ovno; /* Overlay number, 0x0 */ - char e_res[4][2]; /* Reserved words, all 0x0 */ - uint16_t e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */ - uint16_t e_oeminfo; /* OEM information; e_oemid specific, 0x0 */ - char e_res2[10][2]; /* Reserved words, all 0x0 */ - uint32_t e_lfanew; /* File address of new exe header, 0x80 */ - char dos_message[16][4]; /* other stuff, always follow DOS header */ - unsigned int nt_signature; /* required NT signature, 0x4550 */ - - /* From standard header */ - - uint16_t f_magic; /* magic number */ - uint16_t f_nscns; /* number of sections */ - uint32_t f_timdat; /* time & date stamp */ - uint32_t f_symptr; /* file pointer to symtab */ - uint32_t f_nsyms; /* number of symtab entries */ - uint16_t f_opthdr; /* sizeof(optional hdr) */ - uint16_t f_flags; /* flags */ -}; - - -#define FILHDR struct external_PE_filehdr -#undef FILHSZ -#define FILHSZ 152 - -#endif - -typedef struct -{ - uint16_t magic; /* type of file */ - uint16_t vstamp; /* version stamp */ - uint32_t tsize; /* text size in bytes, padded to FW bdry*/ - uint32_t dsize; /* initialized data " " */ - uint32_t bsize; /* uninitialized data " " */ - uint32_t entry; /* entry pt. */ - uint32_t text_start; /* base of text used for this file */ - uint32_t data_start; /* base of all data used for this file */ - - /* NT extra fields; see internal.h for descriptions */ - uint32_t ImageBase; - uint32_t SectionAlignment; - uint32_t FileAlignment; - uint16_t MajorOperatingSystemVersion; - uint16_t MinorOperatingSystemVersion; - uint16_t MajorImageVersion; - uint16_t MinorImageVersion; - uint16_t MajorSubsystemVersion; - uint16_t MinorSubsystemVersion; - char Reserved1[4]; - uint32_t SizeOfImage; - uint32_t SizeOfHeaders; - uint32_t CheckSum; - uint16_t Subsystem; - uint16_t DllCharacteristics; - uint32_t SizeOfStackReserve; - uint32_t SizeOfStackCommit; - uint32_t SizeOfHeapReserve; - uint32_t SizeOfHeapCommit; - uint32_t LoaderFlags; - uint32_t NumberOfRvaAndSizes; - /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */ - char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */ - -} PEAOUTHDR; - - -#undef AOUTSZ -#define AOUTSZ (AOUTHDRSZ + 196) - -#undef E_FILNMLEN -#define E_FILNMLEN 18 /* # characters in a file name */ -#endif - -/* end of coff/pe.h */ - -#define DT_NON (0) /* no derived type */ -#define DT_PTR (1) /* pointer */ -#define DT_FCN (2) /* function */ -#define DT_ARY (3) /* array */ - -#ifndef _WIN32 -#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT)) -#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT)) -#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT)) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _A_OUT_H_ */ - diff --git a/SheepShaver/src/kpx_cpu/include/basic-blockinfo.hpp b/SheepShaver/src/kpx_cpu/include/basic-blockinfo.hpp deleted file mode 100644 index e3399671..00000000 --- a/SheepShaver/src/kpx_cpu/include/basic-blockinfo.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * basic-blockinfo.hpp - PowerPC basic block information - * - * Kheperix (C) 2003 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BASIC_BLOCKINFO_H -#define BASIC_BLOCKINFO_H - -struct basic_block_info -{ - typedef basic_block_info block_info; - static const int MAX_TARGETS = 2; - - struct dependency - { - block_info * source; - block_info * target; - dependency * next; - dependency ** prev_p; - }; - - uintptr pc; - uintptr end_pc; - int32 count; - uint32 size; - uint32 c1; - uint32 c2; - - // List of blocks we depend on - dependency dep[MAX_TARGETS]; - - // List of blocks that depends on this block - dependency * deplist; - - void init(uintptr start_pc); - void remove_dep(dependency *d); - void remove_deps(); - void create_jmpdep(block_info *tbi, int i); - void maybe_create_jmpdep(block_info *tbi); - bool intersect(uintptr start, uintptr end); -}; - -inline void -basic_block_info::init(uintptr start_pc) -{ - pc = start_pc; - deplist = NULL; - for (int i = 0; i < MAX_TARGETS; i++) { - dep[i].source = NULL; - dep[i].target = NULL; - dep[i].next = NULL; - dep[i].prev_p = NULL; - } -} - -inline void -basic_block_info::remove_dep(dependency *d) -{ - if (d->prev_p) - *(d->prev_p) = d->next; - if (d->next) - d->next->prev_p = d->prev_p; - d->prev_p = NULL; - d->next = NULL; -} - -inline void -basic_block_info::remove_deps() -{ - for (int i = 0; i < MAX_TARGETS; i++) - remove_dep(&dep[i]); -} - -inline void -basic_block_info::create_jmpdep(block_info *tbi, int i) -{ - dep[i].source = this; - dep[i].target = tbi; - dep[i].next = tbi->deplist; - if (dep[i].next) - dep[i].next->prev_p = &(dep[i].next); - dep[i].prev_p = &(tbi->deplist); - tbi->deplist = &(dep[i]); -} - -inline void -basic_block_info::maybe_create_jmpdep(block_info *tbi) -{ - for (int i = 0; i < MAX_TARGETS && dep[i].target != tbi; i++) { - if (dep[i].source == NULL) { - create_jmpdep(tbi, i); - break; - } - } -} - -inline bool -basic_block_info::intersect(uintptr start, uintptr end) -{ - return (pc >= start && pc < end) || (end_pc >= start && end_pc < end); -} - -#endif /* BASIC_BLOCKINFO_H */ diff --git a/SheepShaver/src/kpx_cpu/include/basic-cpu.hpp b/SheepShaver/src/kpx_cpu/include/basic-cpu.hpp deleted file mode 100644 index 568ddb0b..00000000 --- a/SheepShaver/src/kpx_cpu/include/basic-cpu.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * basic-cpu.hpp - Basic CPU definitions - * - * Kheperix (C) 2003 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BASIC_CPU_H -#define BASIC_CPU_H - -#include "sysdeps.h" -#include -#include "task-plugin.hpp" - -/** - * Generic register value - **/ - -union any_register -{ - uint32 i; - uint64 j; - float f; - double d; - - // Explicit casts may be required to use those constructors - any_register(uint32 v = 0) : i(v) { } - any_register(uint64 v) : j(v) { } - any_register(float v) : f(v) { } - any_register(double v) : d(v) { } -}; - -/** - * Basic CPU model - **/ - -struct basic_cpu - : public task_plugin -{ - // Basic register set - struct registers - { - enum { - PC = -1, // Program Counter - SP = -2, // Stack Pointer - }; - }; - - // Constructor & destructor - basic_cpu(task_struct * parent_task); - virtual ~basic_cpu(); - - // Execute code at current address - virtual void execute() = 0; - - // Set VALUE to register ID - virtual void set_register(int id, any_register const & value) = 0; - - // Get register ID - virtual any_register get_register(int id) = 0; - - // Start emulation, returns exit status - int run(); - - // Stop emulation - void exit(int status); - -private: - jmp_buf env; - int exit_status; -}; - -// Alias basic register set -typedef basic_cpu::registers basic_registers; - -#endif /* BASIC_CPU_H */ diff --git a/SheepShaver/src/kpx_cpu/include/basic-plugin.hpp b/SheepShaver/src/kpx_cpu/include/basic-plugin.hpp deleted file mode 100644 index 77da79f2..00000000 --- a/SheepShaver/src/kpx_cpu/include/basic-plugin.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * basic-plugin.hpp - Basic plugin definition - * - * Kheperix (C) 2003 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BASIC_PLUGIN_H -#define BASIC_PLUGIN_H - -struct basic_plugin -{ - virtual ~basic_plugin() { } -}; - -#endif /* BASIC_PLUGIN_H */ diff --git a/SheepShaver/src/kpx_cpu/include/block-alloc.hpp b/SheepShaver/src/kpx_cpu/include/block-alloc.hpp deleted file mode 100644 index 70217e40..00000000 --- a/SheepShaver/src/kpx_cpu/include/block-alloc.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * block_alloc.hpp - Memory allocation in blocks - * - * Kheperix (C) 2003 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BLOCK_ALLOC_H -#define BLOCK_ALLOC_H - -/** - * Slow memory allocator - * - * Each time a DATA item is requested (resp. released), the block - * is immediately allocated (resp. free'd). - **/ - -template< class data > -struct slow_allocator -{ - data * acquire() const { return new data; } - void release(data * const x) const { delete x; } -}; - -/** - * Lazy memory allocator - * - * Allocate a big memory block, typically larger than a page, - * that contains up to POOL_COUNT data items of type DATA. - **/ - -template< class data > -class lazy_allocator -{ - static const int pool_size = 4096; - static const int pool_count = 1 + pool_size / sizeof(data); - - struct chunk - { - data value; - chunk * next; - }; - - struct pool - { - chunk chunks[pool_count]; - pool * next; - }; - - pool * pools; - chunk * chunks; - -public: - lazy_allocator() : pools(0), chunks(0) { } - ~lazy_allocator(); - data * acquire(); - void release(data * const); -}; - -template< class data > -lazy_allocator::~lazy_allocator() -{ - pool * p = pools; - while (p) { - pool * d = p; - p = p->next; - delete d; - } -} - -template< class data > -data * lazy_allocator::acquire() -{ - if (!chunks) { - // There is no chunk left, allocate a new pool and link the - // chunks into the free list - pool * p = new pool; - for (chunk * c = &p->chunks[0]; c < &p->chunks[pool_count]; c++) { - c->next = chunks; - chunks = c; - } - p->next = pools; - pools = p; - } - chunk * c = chunks; - chunks = c->next; - return &c->value; -} - -template< class data > -void lazy_allocator::release(data * const d) -{ - chunk *c = (chunk *)d; - c->next = chunks; - chunks = c; -} - -/** - * Helper memory allocator - **/ - -template< class data_type, template< class > class allocator_type = lazy_allocator > -class allocator_helper -{ - static allocator_type allocator; -public: - static inline void *allocate() - { return allocator.acquire(); } - static inline void deallocate(void * p) - { allocator.release((data_type *)p); } -}; - -#endif /* BLOCK_ALLOC_H */ diff --git a/SheepShaver/src/kpx_cpu/include/elf-defs.h b/SheepShaver/src/kpx_cpu/include/elf-defs.h deleted file mode 100644 index 8fe6b053..00000000 --- a/SheepShaver/src/kpx_cpu/include/elf-defs.h +++ /dev/null @@ -1,2360 +0,0 @@ -/* This file defines standard ELF types, structures, and macros. - Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef ELF_DEFS_H -#define ELF_DEFS_H 1 - -/* Standard ELF types. */ - -/* Type for a 16-bit quantity. */ -typedef uint16 Elf32_Half; -typedef uint16 Elf64_Half; - -/* Types for signed and unsigned 32-bit quantities. */ -typedef uint32 Elf32_Word; -typedef int32 Elf32_Sword; -typedef uint32 Elf64_Word; -typedef int32 Elf64_Sword; - -/* Types for signed and unsigned 64-bit quantities. */ -typedef uint64 Elf32_Xword; -typedef int64 Elf32_Sxword; -typedef uint64 Elf64_Xword; -typedef int64 Elf64_Sxword; - -/* Type of addresses. */ -typedef uint32 Elf32_Addr; -typedef uint64 Elf64_Addr; - -/* Type of file offsets. */ -typedef uint32 Elf32_Off; -typedef uint64 Elf64_Off; - -/* Type for section indices, which are 16-bit quantities. */ -typedef uint16 Elf32_Section; -typedef uint16 Elf64_Section; - -/* Type for version symbol information. */ -typedef Elf32_Half Elf32_Versym; -typedef Elf64_Half Elf64_Versym; - - -/* The ELF file header. This appears at the start of every ELF file. */ - -#define EI_NIDENT (16) - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf32_Half e_type; /* Object file type */ - Elf32_Half e_machine; /* Architecture */ - Elf32_Word e_version; /* Object file version */ - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; /* Processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size in bytes */ - Elf32_Half e_phentsize; /* Program header table entry size */ - Elf32_Half e_phnum; /* Program header table entry count */ - Elf32_Half e_shentsize; /* Section header table entry size */ - Elf32_Half e_shnum; /* Section header table entry count */ - Elf32_Half e_shstrndx; /* Section header string table index */ -} Elf32_Ehdr; - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ -} Elf64_Ehdr; - -/* Fields in the e_ident array. The EI_* macros are indices into the - array. The macros under each EI_* macro are the values the byte - may have. */ - -#define EI_MAG0 0 /* File identification byte 0 index */ -#define ELFMAG0 0x7f /* Magic number byte 0 */ - -#define EI_MAG1 1 /* File identification byte 1 index */ -#define ELFMAG1 'E' /* Magic number byte 1 */ - -#define EI_MAG2 2 /* File identification byte 2 index */ -#define ELFMAG2 'L' /* Magic number byte 2 */ - -#define EI_MAG3 3 /* File identification byte 3 index */ -#define ELFMAG3 'F' /* Magic number byte 3 */ - -/* Conglomeration of the identification bytes, for easy testing as a word. */ -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ -#define ELFCLASSNUM 3 - -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ELFDATA2MSB 2 /* 2's complement, big endian */ -#define ELFDATANUM 3 - -#define EI_VERSION 6 /* File version byte index */ - /* Value must be EV_CURRENT */ - -#define EI_OSABI 7 /* OS ABI identification */ -#define ELFOSABI_NONE 0 /* UNIX System V ABI */ -#define ELFOSABI_SYSV 0 /* Alias. */ -#define ELFOSABI_HPUX 1 /* HP-UX */ -#define ELFOSABI_NETBSD 2 /* NetBSD. */ -#define ELFOSABI_LINUX 3 /* Linux. */ -#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ -#define ELFOSABI_AIX 7 /* IBM AIX. */ -#define ELFOSABI_IRIX 8 /* SGI Irix. */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ -#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -#define EI_ABIVERSION 8 /* ABI version */ - -#define EI_PAD 9 /* Byte index of padding bytes */ - -/* Legal values for e_type (object file type). */ - -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_NUM 5 /* Number of defined types */ -#define ET_LOOS 0xfe00 /* OS-specific range start */ -#define ET_HIOS 0xfeff /* OS-specific range end */ -#define ET_LOPROC 0xff00 /* Processor-specific range start */ -#define ET_HIPROC 0xffff /* Processor-specific range end */ - -/* Legal values for e_machine (architecture). */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_486 6 /* Perhaps disused */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 big-endian */ -#define EM_S370 9 /* IBM System/370 */ -#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ - -#define EM_PARISC 15 /* HPPA */ -#define EM_VPP500 17 /* Fujitsu VPP500 */ -#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ -#define EM_960 19 /* Intel 80960 */ -#define EM_PPC 20 /* PowerPC */ -#define EM_PPC64 21 /* PowerPC 64-bit */ -#define EM_S390 22 /* IBM S390 */ - -#define EM_V800 36 /* NEC V800 series */ -#define EM_FR20 37 /* Fujitsu FR20 */ -#define EM_RH32 38 /* TRW RH-32 */ -#define EM_RCE 39 /* Motorola RCE */ -#define EM_ARM 40 /* ARM */ -#define EM_FAKE_ALPHA 41 /* Digital Alpha */ -#define EM_SH 42 /* Hitachi SH */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit */ -#define EM_TRICORE 44 /* Siemens Tricore */ -#define EM_ARC 45 /* Argonaut RISC Core */ -#define EM_H8_300 46 /* Hitachi H8/300 */ -#define EM_H8_300H 47 /* Hitachi H8/300H */ -#define EM_H8S 48 /* Hitachi H8S */ -#define EM_H8_500 49 /* Hitachi H8/500 */ -#define EM_IA_64 50 /* Intel Merced */ -#define EM_MIPS_X 51 /* Stanford MIPS-X */ -#define EM_COLDFIRE 52 /* Motorola Coldfire */ -#define EM_68HC12 53 /* Motorola M68HC12 */ -#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ -#define EM_PCP 55 /* Siemens PCP */ -#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ -#define EM_NDR1 57 /* Denso NDR1 microprocessor */ -#define EM_STARCORE 58 /* Motorola Start*Core processor */ -#define EM_ME16 59 /* Toyota ME16 processor */ -#define EM_ST100 60 /* STMicroelectronic ST100 processor */ -#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ -#define EM_X86_64 62 /* AMD x86-64 architecture */ -#define EM_PDSP 63 /* Sony DSP Processor */ - -#define EM_FX66 66 /* Siemens FX66 microcontroller */ -#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ -#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ -#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ -#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ -#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ -#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ -#define EM_SVX 73 /* Silicon Graphics SVx */ -#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ -#define EM_VAX 75 /* Digital VAX */ -#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ -#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ -#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ -#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ -#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ -#define EM_HUANY 81 /* Harvard University machine-independent object files */ -#define EM_PRISM 82 /* SiTera Prism */ -#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ -#define EM_FR30 84 /* Fujitsu FR30 */ -#define EM_D10V 85 /* Mitsubishi D10V */ -#define EM_D30V 86 /* Mitsubishi D30V */ -#define EM_V850 87 /* NEC v850 */ -#define EM_M32R 88 /* Mitsubishi M32R */ -#define EM_MN10300 89 /* Matsushita MN10300 */ -#define EM_MN10200 90 /* Matsushita MN10200 */ -#define EM_PJ 91 /* picoJava */ -#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ -#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ -#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ -#define EM_NUM 95 - -/* If it is necessary to assign new unofficial EM_* values, please - pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the - chances of collision with official or non-GNU unofficial values. */ - -#define EM_ALPHA 0x9026 - -/* Legal values for e_version (version). */ - -#define EV_NONE 0 /* Invalid ELF version */ -#define EV_CURRENT 1 /* Current version */ -#define EV_NUM 2 - -/* Section header. */ - -typedef struct -{ - Elf32_Word sh_name; /* Section name (string tbl index) */ - Elf32_Word sh_type; /* Section type */ - Elf32_Word sh_flags; /* Section flags */ - Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ - Elf32_Word sh_size; /* Section size in bytes */ - Elf32_Word sh_link; /* Link to another section */ - Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ - Elf32_Word sh_entsize; /* Entry size if section holds table */ -} Elf32_Shdr; - -typedef struct -{ - Elf64_Word sh_name; /* Section name (string tbl index) */ - Elf64_Word sh_type; /* Section type */ - Elf64_Xword sh_flags; /* Section flags */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Section size in bytes */ - Elf64_Word sh_link; /* Link to another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -/* Special section indices. */ - -#define SHN_UNDEF 0 /* Undefined section */ -#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ -#define SHN_LOPROC 0xff00 /* Start of processor-specific */ -#define SHN_HIPROC 0xff1f /* End of processor-specific */ -#define SHN_LOOS 0xff20 /* Start of OS-specific */ -#define SHN_HIOS 0xff3f /* End of OS-specific */ -#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ -#define SHN_COMMON 0xfff2 /* Associated symbol is common */ -#define SHN_XINDEX 0xffff /* Index is in extra table. */ -#define SHN_HIRESERVE 0xffff /* End of reserved indices */ - -/* Legal values for sh_type (section type). */ - -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_INIT_ARRAY 14 /* Array of constructors */ -#define SHT_FINI_ARRAY 15 /* Array of destructors */ -#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ -#define SHT_NUM 19 /* Number of defined types. */ -#define SHT_LOOS 0x60000000 /* Start OS-specific */ -#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ -#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ -#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_COMDAT 0x6ffffffb -#define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ -#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ -#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ -#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ -#define SHT_HIOS 0x6fffffff /* End OS-specific type */ -#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ -#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ -#define SHT_LOUSER 0x80000000 /* Start of application-specific */ -#define SHT_HIUSER 0x8fffffff /* End of application-specific */ - -/* Legal values for sh_flags (section flags). */ - -#define SHF_WRITE (1 << 0) /* Writable */ -#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ -#define SHF_EXECINSTR (1 << 2) /* Executable */ -#define SHF_MERGE (1 << 4) /* Might be merged */ -#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ -#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ -#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ -#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling - required */ -#define SHF_GROUP (1 << 9) /* Section is member of a group. */ -#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ -#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ -#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ - -/* Section group handling. */ -#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ - -/* Symbol table entry. */ - -typedef struct -{ - Elf32_Word st_name; /* Symbol name (string tbl index) */ - Elf32_Addr st_value; /* Symbol value */ - Elf32_Word st_size; /* Symbol size */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf32_Section st_shndx; /* Section index */ -} Elf32_Sym; - -typedef struct -{ - Elf64_Word st_name; /* Symbol name (string tbl index) */ - unsigned char st_info; /* Symbol type and binding */ - unsigned char st_other; /* Symbol visibility */ - Elf64_Section st_shndx; /* Section index */ - Elf64_Addr st_value; /* Symbol value */ - Elf64_Xword st_size; /* Symbol size */ -} Elf64_Sym; - -/* The syminfo section if available contains additional information about - every dynamic symbol. */ - -typedef struct -{ - Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ - Elf32_Half si_flags; /* Per symbol flags */ -} Elf32_Syminfo; - -typedef struct -{ - Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ - Elf64_Half si_flags; /* Per symbol flags */ -} Elf64_Syminfo; - -/* Possible values for si_boundto. */ -#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ -#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ -#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ - -/* Possible bitmasks for si_flags. */ -#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ -#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ -#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ -#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy - loaded */ -/* Syminfo version values. */ -#define SYMINFO_NONE 0 -#define SYMINFO_CURRENT 1 -#define SYMINFO_NUM 2 - - -/* How to extract and insert information held in the st_info field. */ - -#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) -#define ELF32_ST_TYPE(val) ((val) & 0xf) -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ -#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) -#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) -#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) - -/* Legal values for ST_BIND subfield of st_info (symbol binding). */ - -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* Weak symbol */ -#define STB_NUM 3 /* Number of defined types. */ -#define STB_LOOS 10 /* Start of OS-specific */ -#define STB_HIOS 12 /* End of OS-specific */ -#define STB_LOPROC 13 /* Start of processor-specific */ -#define STB_HIPROC 15 /* End of processor-specific */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_NOTYPE 0 /* Symbol type is unspecified */ -#define STT_OBJECT 1 /* Symbol is a data object */ -#define STT_FUNC 2 /* Symbol is a code object */ -#define STT_SECTION 3 /* Symbol associated with a section */ -#define STT_FILE 4 /* Symbol's name is file name */ -#define STT_COMMON 5 /* Symbol is a common data object */ -#define STT_TLS 6 /* Symbol is thread-local data object*/ -#define STT_NUM 7 /* Number of defined types. */ -#define STT_LOOS 10 /* Start of OS-specific */ -#define STT_HIOS 12 /* End of OS-specific */ -#define STT_LOPROC 13 /* Start of processor-specific */ -#define STT_HIPROC 15 /* End of processor-specific */ - - -/* Symbol table indices are found in the hash buckets and chain table - of a symbol hash table section. This special index value indicates - the end of a chain, meaning no further symbols are found in that bucket. */ - -#define STN_UNDEF 0 /* End of a chain. */ - - -/* How to extract and insert information held in the st_other field. */ - -#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) - -/* For ELF64 the definitions are the same. */ -#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) - -/* Symbol visibility specification encoded in the st_other field. */ -#define STV_DEFAULT 0 /* Default symbol visibility rules */ -#define STV_INTERNAL 1 /* Processor specific hidden class */ -#define STV_HIDDEN 2 /* Sym unavailable in other modules */ -#define STV_PROTECTED 3 /* Not preemptible, not exported */ - - -/* Relocation table entry without addend (in section of type SHT_REL). */ - -typedef struct -{ - Elf32_Addr r_offset; /* Address */ - Elf32_Word r_info; /* Relocation type and symbol index */ -} Elf32_Rel; - -/* I have seen two different definitions of the Elf64_Rel and - Elf64_Rela structures, so we'll leave them out until Novell (or - whoever) gets their act together. */ -/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ - -typedef struct -{ - Elf64_Addr r_offset; /* Address */ - Elf64_Xword r_info; /* Relocation type and symbol index */ -} Elf64_Rel; - -/* Relocation table entry with addend (in section of type SHT_RELA). */ - -typedef struct -{ - Elf32_Addr r_offset; /* Address */ - Elf32_Word r_info; /* Relocation type and symbol index */ - Elf32_Sword r_addend; /* Addend */ -} Elf32_Rela; - -typedef struct -{ - Elf64_Addr r_offset; /* Address */ - Elf64_Xword r_info; /* Relocation type and symbol index */ - Elf64_Sxword r_addend; /* Addend */ -} Elf64_Rela; - -/* How to extract and insert information held in the r_info field. */ - -#define ELF32_R_SYM(val) ((val) >> 8) -#define ELF32_R_TYPE(val) ((val) & 0xff) -#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i) & 0xffffffff) -#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) - -/* Program segment header. */ - -typedef struct -{ - Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ - Elf32_Addr p_vaddr; /* Segment virtual address */ - Elf32_Addr p_paddr; /* Segment physical address */ - Elf32_Word p_filesz; /* Segment size in file */ - Elf32_Word p_memsz; /* Segment size in memory */ - Elf32_Word p_flags; /* Segment flags */ - Elf32_Word p_align; /* Segment alignment */ -} Elf32_Phdr; - -typedef struct -{ - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment */ -} Elf64_Phdr; - -/* Legal values for p_type (segment type). */ - -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_TLS 7 /* Thread-local storage segment */ -#define PT_NUM 8 /* Number of defined types */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ -#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ - -/* Legal values for p_flags (segment flags). */ - -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ -#define PF_MASKOS 0x0ff00000 /* OS-specific */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific */ - -/* Legal values for note segment descriptor types for core files. */ - -#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ -#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ -#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ -#define NT_PRXREG 4 /* Contains copy of prxregset struct */ -#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ -#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ -#define NT_AUXV 6 /* Contains copy of auxv array */ -#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ -#define NT_ASRS 8 /* Contains copy of asrset struct */ -#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ -#define NT_PSINFO 13 /* Contains copy of psinfo struct */ -#define NT_PRCRED 14 /* Contains copy of prcred struct */ -#define NT_UTSNAME 15 /* Contains copy of utsname struct */ -#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ -#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ -#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ - -/* Legal values for the note segment descriptor types for object files. */ - -#define NT_VERSION 1 /* Contains a version string. */ - - -/* Dynamic section entry. */ - -typedef struct -{ - Elf32_Sword d_tag; /* Dynamic entry type */ - union - { - Elf32_Word d_val; /* Integer value */ - Elf32_Addr d_ptr; /* Address value */ - } d_un; -} Elf32_Dyn; - -typedef struct -{ - Elf64_Sxword d_tag; /* Dynamic entry type */ - union - { - Elf64_Xword d_val; /* Integer value */ - Elf64_Addr d_ptr; /* Address value */ - } d_un; -} Elf64_Dyn; - -/* Legal values for d_tag (dynamic entry type). */ - -#define DT_NULL 0 /* Marks end of dynamic section */ -#define DT_NEEDED 1 /* Name of needed library */ -#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ -#define DT_PLTGOT 3 /* Processor defined value */ -#define DT_HASH 4 /* Address of symbol hash table */ -#define DT_STRTAB 5 /* Address of string table */ -#define DT_SYMTAB 6 /* Address of symbol table */ -#define DT_RELA 7 /* Address of Rela relocs */ -#define DT_RELASZ 8 /* Total size of Rela relocs */ -#define DT_RELAENT 9 /* Size of one Rela reloc */ -#define DT_STRSZ 10 /* Size of string table */ -#define DT_SYMENT 11 /* Size of one symbol table entry */ -#define DT_INIT 12 /* Address of init function */ -#define DT_FINI 13 /* Address of termination function */ -#define DT_SONAME 14 /* Name of shared object */ -#define DT_RPATH 15 /* Library search path (deprecated) */ -#define DT_SYMBOLIC 16 /* Start symbol search here */ -#define DT_REL 17 /* Address of Rel relocs */ -#define DT_RELSZ 18 /* Total size of Rel relocs */ -#define DT_RELENT 19 /* Size of one Rel reloc */ -#define DT_PLTREL 20 /* Type of reloc in PLT */ -#define DT_DEBUG 21 /* For debugging; unspecified */ -#define DT_TEXTREL 22 /* Reloc might modify .text */ -#define DT_JMPREL 23 /* Address of PLT relocs */ -#define DT_BIND_NOW 24 /* Process relocations of object */ -#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ -#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ -#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ -#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ -#define DT_RUNPATH 29 /* Library search path */ -#define DT_FLAGS 30 /* Flags for the object being loaded */ -#define DT_ENCODING 32 /* Start of encoded range */ -#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ -#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ -#define DT_NUM 34 /* Number used */ -#define DT_LOOS 0x6000000d /* Start of OS-specific */ -#define DT_HIOS 0x6ffff000 /* End of OS-specific */ -#define DT_LOPROC 0x70000000 /* Start of processor-specific */ -#define DT_HIPROC 0x7fffffff /* End of processor-specific */ -#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ - -/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the - Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's - approach. */ -#define DT_VALRNGLO 0x6ffffd00 -#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ -#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ -#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ -#define DT_CHECKSUM 0x6ffffdf8 -#define DT_PLTPADSZ 0x6ffffdf9 -#define DT_MOVEENT 0x6ffffdfa -#define DT_MOVESZ 0x6ffffdfb -#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ -#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting - the following DT_* entry. */ -#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ -#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ -#define DT_VALRNGHI 0x6ffffdff -#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ -#define DT_VALNUM 12 - -/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the - Dyn.d_un.d_ptr field of the Elf*_Dyn structure. - - If any adjustment is made to the ELF object after it has been - built these entries will need to be adjusted. */ -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ -#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ -#define DT_CONFIG 0x6ffffefa /* Configuration information. */ -#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ -#define DT_AUDIT 0x6ffffefc /* Object auditing. */ -#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ -#define DT_MOVETAB 0x6ffffefe /* Move table. */ -#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ -#define DT_ADDRNUM 10 - -/* The versioning entry types. The next are defined as part of the - GNU extension. */ -#define DT_VERSYM 0x6ffffff0 - -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa - -/* These were chosen by Sun. */ -#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ -#define DT_VERDEF 0x6ffffffc /* Address of version definition - table */ -#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ -#define DT_VERNEED 0x6ffffffe /* Address of table with needed - versions */ -#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ -#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ -#define DT_VERSIONTAGNUM 16 - -/* Sun added these machine-independent extensions in the "processor-specific" - range. Be compatible. */ -#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ -#define DT_FILTER 0x7fffffff /* Shared object to get values from */ -#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) -#define DT_EXTRANUM 3 - -/* Values of `d_un.d_val' in the DT_FLAGS entry. */ -#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ -#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ -#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ -#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ -#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ - -/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 - entry in the dynamic section. */ -#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ -#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ -#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ -#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ -#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ -#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ -#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ -#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ -#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ -#define DF_1_TRANS 0x00000200 -#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ -#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ -#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ -#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ -#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ -#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ -#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ - -/* Flags for the feature selection in DT_FEATURE_1. */ -#define DTF_1_PARINIT 0x00000001 -#define DTF_1_CONFEXP 0x00000002 - -/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ -#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ -#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not - generally available. */ - -/* Version definition sections. */ - -typedef struct -{ - Elf32_Half vd_version; /* Version revision */ - Elf32_Half vd_flags; /* Version information */ - Elf32_Half vd_ndx; /* Version Index */ - Elf32_Half vd_cnt; /* Number of associated aux entries */ - Elf32_Word vd_hash; /* Version name hash value */ - Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ - Elf32_Word vd_next; /* Offset in bytes to next verdef - entry */ -} Elf32_Verdef; - -typedef struct -{ - Elf64_Half vd_version; /* Version revision */ - Elf64_Half vd_flags; /* Version information */ - Elf64_Half vd_ndx; /* Version Index */ - Elf64_Half vd_cnt; /* Number of associated aux entries */ - Elf64_Word vd_hash; /* Version name hash value */ - Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ - Elf64_Word vd_next; /* Offset in bytes to next verdef - entry */ -} Elf64_Verdef; - - -/* Legal values for vd_version (version revision). */ -#define VER_DEF_NONE 0 /* No version */ -#define VER_DEF_CURRENT 1 /* Current version */ -#define VER_DEF_NUM 2 /* Given version number */ - -/* Legal values for vd_flags (version information flags). */ -#define VER_FLG_BASE 0x1 /* Version definition of file itself */ -#define VER_FLG_WEAK 0x2 /* Weak version identifier */ - -/* Versym symbol index values. */ -#define VER_NDX_LOCAL 0 /* Symbol is local. */ -#define VER_NDX_GLOBAL 1 /* Symbol is global. */ -#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ -#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ - -/* Auxialiary version information. */ - -typedef struct -{ - Elf32_Word vda_name; /* Version or dependency names */ - Elf32_Word vda_next; /* Offset in bytes to next verdaux - entry */ -} Elf32_Verdaux; - -typedef struct -{ - Elf64_Word vda_name; /* Version or dependency names */ - Elf64_Word vda_next; /* Offset in bytes to next verdaux - entry */ -} Elf64_Verdaux; - - -/* Version dependency section. */ - -typedef struct -{ - Elf32_Half vn_version; /* Version of structure */ - Elf32_Half vn_cnt; /* Number of associated aux entries */ - Elf32_Word vn_file; /* Offset of filename for this - dependency */ - Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ - Elf32_Word vn_next; /* Offset in bytes to next verneed - entry */ -} Elf32_Verneed; - -typedef struct -{ - Elf64_Half vn_version; /* Version of structure */ - Elf64_Half vn_cnt; /* Number of associated aux entries */ - Elf64_Word vn_file; /* Offset of filename for this - dependency */ - Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ - Elf64_Word vn_next; /* Offset in bytes to next verneed - entry */ -} Elf64_Verneed; - - -/* Legal values for vn_version (version revision). */ -#define VER_NEED_NONE 0 /* No version */ -#define VER_NEED_CURRENT 1 /* Current version */ -#define VER_NEED_NUM 2 /* Given version number */ - -/* Auxiliary needed version information. */ - -typedef struct -{ - Elf32_Word vna_hash; /* Hash value of dependency name */ - Elf32_Half vna_flags; /* Dependency specific information */ - Elf32_Half vna_other; /* Unused */ - Elf32_Word vna_name; /* Dependency name string offset */ - Elf32_Word vna_next; /* Offset in bytes to next vernaux - entry */ -} Elf32_Vernaux; - -typedef struct -{ - Elf64_Word vna_hash; /* Hash value of dependency name */ - Elf64_Half vna_flags; /* Dependency specific information */ - Elf64_Half vna_other; /* Unused */ - Elf64_Word vna_name; /* Dependency name string offset */ - Elf64_Word vna_next; /* Offset in bytes to next vernaux - entry */ -} Elf64_Vernaux; - - -/* Legal values for vna_flags. */ -#define VER_FLG_WEAK 0x2 /* Weak version identifier */ - - -/* Auxiliary vector. */ - -/* This vector is normally only used by the program interpreter. The - usual definition in an ABI supplement uses the name auxv_t. The - vector is not usually defined in a standard file, but it - can't hurt. We rename it to avoid conflicts. The sizes of these - types are an arrangement between the exec server and the program - interpreter, so we don't fully specify them here. */ - -typedef struct -{ - int a_type; /* Entry type */ - union - { - long int a_val; /* Integer value */ - void *a_ptr; /* Pointer value */ - void (*a_fcn) (void); /* Function pointer value */ - } a_un; -} Elf32_auxv_t; - -typedef struct -{ - long int a_type; /* Entry type */ - union - { - long int a_val; /* Integer value */ - void *a_ptr; /* Pointer value */ - void (*a_fcn) (void); /* Function pointer value */ - } a_un; -} Elf64_auxv_t; - -/* Legal values for a_type (entry type). */ - -#define AT_NULL 0 /* End of vector */ -#define AT_IGNORE 1 /* Entry should be ignored */ -#define AT_EXECFD 2 /* File descriptor of program */ -#define AT_PHDR 3 /* Program headers for program */ -#define AT_PHENT 4 /* Size of program header entry */ -#define AT_PHNUM 5 /* Number of program headers */ -#define AT_PAGESZ 6 /* System page size */ -#define AT_BASE 7 /* Base address of interpreter */ -#define AT_FLAGS 8 /* Flags */ -#define AT_ENTRY 9 /* Entry point of program */ -#define AT_NOTELF 10 /* Program is not ELF */ -#define AT_UID 11 /* Real uid */ -#define AT_EUID 12 /* Effective uid */ -#define AT_GID 13 /* Real gid */ -#define AT_EGID 14 /* Effective gid */ -#define AT_CLKTCK 17 /* Frequency of times() */ - -/* Some more special a_type values describing the hardware. */ -#define AT_PLATFORM 15 /* String identifying platform. */ -#define AT_HWCAP 16 /* Machine dependent hints about - processor capabilities. */ - -/* This entry gives some information about the FPU initialization - performed by the kernel. */ -#define AT_FPUCW 18 /* Used FPU control word. */ - -/* Cache block sizes. */ -#define AT_DCACHEBSIZE 19 /* Data cache block size. */ -#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ -#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ - -/* A special ignored value for PPC, used by the kernel to control the - interpretation of the AUXV. Must be > 16. */ -#define AT_IGNOREPPC 22 /* Entry should be ignored */ - -/* Pointer to the global system page used for system calls and other - nice things. */ -#define AT_SYSINFO 32 - - -/* Note section contents. Each entry in the note section begins with - a header of a fixed form. */ - -typedef struct -{ - Elf32_Word n_namesz; /* Length of the note's name. */ - Elf32_Word n_descsz; /* Length of the note's descriptor. */ - Elf32_Word n_type; /* Type of the note. */ -} Elf32_Nhdr; - -typedef struct -{ - Elf64_Word n_namesz; /* Length of the note's name. */ - Elf64_Word n_descsz; /* Length of the note's descriptor. */ - Elf64_Word n_type; /* Type of the note. */ -} Elf64_Nhdr; - -/* Known names of notes. */ - -/* Solaris entries in the note section have this name. */ -#define ELF_NOTE_SOLARIS "SUNW Solaris" - -/* Note entries for GNU systems have this name. */ -#define ELF_NOTE_GNU "GNU" - - -/* Defined types of notes for Solaris. */ - -/* Value of descriptor (one word) is desired pagesize for the binary. */ -#define ELF_NOTE_PAGESIZE_HINT 1 - - -/* Defined note types for GNU systems. */ - -/* ABI information. The descriptor consists of words: - word 0: OS descriptor - word 1: major version of the ABI - word 2: minor version of the ABI - word 3: subminor version of the ABI -*/ -#define ELF_NOTE_ABI 1 - -/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI - note section entry. */ -#define ELF_NOTE_OS_LINUX 0 -#define ELF_NOTE_OS_GNU 1 -#define ELF_NOTE_OS_SOLARIS2 2 -#define ELF_NOTE_OS_FREEBSD 3 - - -/* Move records. */ -typedef struct -{ - Elf32_Xword m_value; /* Symbol value. */ - Elf32_Word m_info; /* Size and index. */ - Elf32_Word m_poffset; /* Symbol offset. */ - Elf32_Half m_repeat; /* Repeat count. */ - Elf32_Half m_stride; /* Stride info. */ -} Elf32_Move; - -typedef struct -{ - Elf64_Xword m_value; /* Symbol value. */ - Elf64_Xword m_info; /* Size and index. */ - Elf64_Xword m_poffset; /* Symbol offset. */ - Elf64_Half m_repeat; /* Repeat count. */ - Elf64_Half m_stride; /* Stride info. */ -} Elf64_Move; - -/* Macro to construct move records. */ -#define ELF32_M_SYM(info) ((info) >> 8) -#define ELF32_M_SIZE(info) ((unsigned char) (info)) -#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) - -#define ELF64_M_SYM(info) ELF32_M_SYM (info) -#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) -#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) - - -/* Motorola 68k specific definitions. */ - -/* Values for Elf32_Ehdr.e_flags. */ -#define EF_CPU32 0x00810000 - -/* m68k relocs. */ - -#define R_68K_NONE 0 /* No reloc */ -#define R_68K_32 1 /* Direct 32 bit */ -#define R_68K_16 2 /* Direct 16 bit */ -#define R_68K_8 3 /* Direct 8 bit */ -#define R_68K_PC32 4 /* PC relative 32 bit */ -#define R_68K_PC16 5 /* PC relative 16 bit */ -#define R_68K_PC8 6 /* PC relative 8 bit */ -#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ -#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ -#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ -#define R_68K_GOT32O 10 /* 32 bit GOT offset */ -#define R_68K_GOT16O 11 /* 16 bit GOT offset */ -#define R_68K_GOT8O 12 /* 8 bit GOT offset */ -#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ -#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ -#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ -#define R_68K_PLT32O 16 /* 32 bit PLT offset */ -#define R_68K_PLT16O 17 /* 16 bit PLT offset */ -#define R_68K_PLT8O 18 /* 8 bit PLT offset */ -#define R_68K_COPY 19 /* Copy symbol at runtime */ -#define R_68K_GLOB_DAT 20 /* Create GOT entry */ -#define R_68K_JMP_SLOT 21 /* Create PLT entry */ -#define R_68K_RELATIVE 22 /* Adjust by program base */ -/* Keep this the last entry. */ -#define R_68K_NUM 23 - -/* Intel 80386 specific definitions. */ - -/* i386 relocs. */ - -#define R_386_NONE 0 /* No reloc */ -#define R_386_32 1 /* Direct 32 bit */ -#define R_386_PC32 2 /* PC relative 32 bit */ -#define R_386_GOT32 3 /* 32 bit GOT entry */ -#define R_386_PLT32 4 /* 32 bit PLT address */ -#define R_386_COPY 5 /* Copy symbol at runtime */ -#define R_386_GLOB_DAT 6 /* Create GOT entry */ -#define R_386_JMP_SLOT 7 /* Create PLT entry */ -#define R_386_RELATIVE 8 /* Adjust by program base */ -#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ -#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ -#define R_386_32PLT 11 -#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ -#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS - block offset */ -#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block - offset */ -#define R_386_TLS_LE 17 /* Offset relative to static TLS - block */ -#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of - general dynamic thread local data */ -#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of - local dynamic thread local data - in LE code */ -#define R_386_16 20 -#define R_386_PC16 21 -#define R_386_8 22 -#define R_386_PC8 23 -#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic - thread local data */ -#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ -#define R_386_TLS_GD_CALL 26 /* Relocation for call to - __tls_get_addr() */ -#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ -#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic - thread local data in LE code */ -#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ -#define R_386_TLS_LDM_CALL 30 /* Relocation for call to - __tls_get_addr() in LDM code */ -#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ -#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ -#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS - block offset */ -#define R_386_TLS_LE_32 34 /* Negated offset relative to static - TLS block */ -#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ -#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ -#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ -/* Keep this the last entry. */ -#define R_386_NUM 38 - -/* SUN SPARC specific definitions. */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_REGISTER 13 /* Global register reserved to app. */ - -/* Values for Elf64_Ehdr.e_flags. */ - -#define EF_SPARCV9_MM 3 -#define EF_SPARCV9_TSO 0 -#define EF_SPARCV9_PSO 1 -#define EF_SPARCV9_RMO 2 -#define EF_SPARC_LEDATA 0x800000 /* little endian data */ -#define EF_SPARC_EXT_MASK 0xFFFF00 -#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ -#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ -#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ -#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ - -/* SPARC relocs. */ - -#define R_SPARC_NONE 0 /* No reloc */ -#define R_SPARC_8 1 /* Direct 8 bit */ -#define R_SPARC_16 2 /* Direct 16 bit */ -#define R_SPARC_32 3 /* Direct 32 bit */ -#define R_SPARC_DISP8 4 /* PC relative 8 bit */ -#define R_SPARC_DISP16 5 /* PC relative 16 bit */ -#define R_SPARC_DISP32 6 /* PC relative 32 bit */ -#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ -#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ -#define R_SPARC_HI22 9 /* High 22 bit */ -#define R_SPARC_22 10 /* Direct 22 bit */ -#define R_SPARC_13 11 /* Direct 13 bit */ -#define R_SPARC_LO10 12 /* Truncated 10 bit */ -#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ -#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ -#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ -#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ -#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ -#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ -#define R_SPARC_COPY 19 /* Copy symbol at runtime */ -#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ -#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ -#define R_SPARC_RELATIVE 22 /* Adjust by program base */ -#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ - -/* Additional Sparc64 relocs. */ - -#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ -#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ -#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ -#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ -#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ -#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ -#define R_SPARC_10 30 /* Direct 10 bit */ -#define R_SPARC_11 31 /* Direct 11 bit */ -#define R_SPARC_64 32 /* Direct 64 bit */ -#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ -#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ -#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ -#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ -#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ -#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ -#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ -#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ -#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ -#define R_SPARC_7 43 /* Direct 7 bit */ -#define R_SPARC_5 44 /* Direct 5 bit */ -#define R_SPARC_6 45 /* Direct 6 bit */ -#define R_SPARC_DISP64 46 /* PC relative 64 bit */ -#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ -#define R_SPARC_HIX22 48 /* High 22 bit complemented */ -#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ -#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ -#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ -#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ -#define R_SPARC_REGISTER 53 /* Global register usage */ -#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ -#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ -#define R_SPARC_TLS_GD_HI22 56 -#define R_SPARC_TLS_GD_LO10 57 -#define R_SPARC_TLS_GD_ADD 58 -#define R_SPARC_TLS_GD_CALL 59 -#define R_SPARC_TLS_LDM_HI22 60 -#define R_SPARC_TLS_LDM_LO10 61 -#define R_SPARC_TLS_LDM_ADD 62 -#define R_SPARC_TLS_LDM_CALL 63 -#define R_SPARC_TLS_LDO_HIX22 64 -#define R_SPARC_TLS_LDO_LOX10 65 -#define R_SPARC_TLS_LDO_ADD 66 -#define R_SPARC_TLS_IE_HI22 67 -#define R_SPARC_TLS_IE_LO10 68 -#define R_SPARC_TLS_IE_LD 69 -#define R_SPARC_TLS_IE_LDX 70 -#define R_SPARC_TLS_IE_ADD 71 -#define R_SPARC_TLS_LE_HIX22 72 -#define R_SPARC_TLS_LE_LOX10 73 -#define R_SPARC_TLS_DTPMOD32 74 -#define R_SPARC_TLS_DTPMOD64 75 -#define R_SPARC_TLS_DTPOFF32 76 -#define R_SPARC_TLS_DTPOFF64 77 -#define R_SPARC_TLS_TPOFF32 78 -#define R_SPARC_TLS_TPOFF64 79 -/* Keep this the last entry. */ -#define R_SPARC_NUM 80 - -/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ - -#define DT_SPARC_REGISTER 0x70000001 -#define DT_SPARC_NUM 2 - -/* Bits present in AT_HWCAP, primarily for Sparc32. */ - -#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ -#define HWCAP_SPARC_STBAR 2 -#define HWCAP_SPARC_SWAP 4 -#define HWCAP_SPARC_MULDIV 8 -#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ -#define HWCAP_SPARC_ULTRA3 32 - -/* MIPS R3000 specific definitions. */ - -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ -#define EF_MIPS_PIC 2 /* Contains PIC code */ -#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ -#define EF_MIPS_XGOT 8 -#define EF_MIPS_64BIT_WHIRL 16 -#define EF_MIPS_ABI2 32 -#define EF_MIPS_ABI_ON32 64 -#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ - -/* Legal values for MIPS architecture level. */ - -#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ -#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ -#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ -#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ -#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ -#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ -#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ - -/* The following are non-official names and should not be used. */ - -#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ -#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ -#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ -#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ -#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ -#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ -#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ - -/* Special section indices. */ - -#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ -#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ -#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ -#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ -#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ - -/* Legal values for sh_type field of Elf32_Shdr. */ - -#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ -#define SHT_MIPS_MSYM 0x70000001 -#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ -#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ -#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ -#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ -#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ -#define SHT_MIPS_PACKAGE 0x70000007 -#define SHT_MIPS_PACKSYM 0x70000008 -#define SHT_MIPS_RELD 0x70000009 -#define SHT_MIPS_IFACE 0x7000000b -#define SHT_MIPS_CONTENT 0x7000000c -#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ -#define SHT_MIPS_SHDR 0x70000010 -#define SHT_MIPS_FDESC 0x70000011 -#define SHT_MIPS_EXTSYM 0x70000012 -#define SHT_MIPS_DENSE 0x70000013 -#define SHT_MIPS_PDESC 0x70000014 -#define SHT_MIPS_LOCSYM 0x70000015 -#define SHT_MIPS_AUXSYM 0x70000016 -#define SHT_MIPS_OPTSYM 0x70000017 -#define SHT_MIPS_LOCSTR 0x70000018 -#define SHT_MIPS_LINE 0x70000019 -#define SHT_MIPS_RFDESC 0x7000001a -#define SHT_MIPS_DELTASYM 0x7000001b -#define SHT_MIPS_DELTAINST 0x7000001c -#define SHT_MIPS_DELTACLASS 0x7000001d -#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ -#define SHT_MIPS_DELTADECL 0x7000001f -#define SHT_MIPS_SYMBOL_LIB 0x70000020 -#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ -#define SHT_MIPS_TRANSLATE 0x70000022 -#define SHT_MIPS_PIXIE 0x70000023 -#define SHT_MIPS_XLATE 0x70000024 -#define SHT_MIPS_XLATE_DEBUG 0x70000025 -#define SHT_MIPS_WHIRL 0x70000026 -#define SHT_MIPS_EH_REGION 0x70000027 -#define SHT_MIPS_XLATE_OLD 0x70000028 -#define SHT_MIPS_PDR_EXCEPTION 0x70000029 - -/* Legal values for sh_flags field of Elf32_Shdr. */ - -#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ -#define SHF_MIPS_MERGE 0x20000000 -#define SHF_MIPS_ADDR 0x40000000 -#define SHF_MIPS_STRINGS 0x80000000 -#define SHF_MIPS_NOSTRIP 0x08000000 -#define SHF_MIPS_LOCAL 0x04000000 -#define SHF_MIPS_NAMES 0x02000000 -#define SHF_MIPS_NODUPE 0x01000000 - - -/* Symbol tables. */ - -/* MIPS specific values for `st_other'. */ -#define STO_MIPS_DEFAULT 0x0 -#define STO_MIPS_INTERNAL 0x1 -#define STO_MIPS_HIDDEN 0x2 -#define STO_MIPS_PROTECTED 0x3 -#define STO_MIPS_SC_ALIGN_UNUSED 0xff - -/* MIPS specific values for `st_info'. */ -#define STB_MIPS_SPLIT_COMMON 13 - -/* Entries found in sections of type SHT_MIPS_GPTAB. */ - -typedef union -{ - struct - { - Elf32_Word gt_current_g_value; /* -G value used for compilation */ - Elf32_Word gt_unused; /* Not used */ - } gt_header; /* First entry in section */ - struct - { - Elf32_Word gt_g_value; /* If this value were used for -G */ - Elf32_Word gt_bytes; /* This many bytes would be used */ - } gt_entry; /* Subsequent entries in section */ -} Elf32_gptab; - -/* Entry found in sections of type SHT_MIPS_REGINFO. */ - -typedef struct -{ - Elf32_Word ri_gprmask; /* General registers used */ - Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ - Elf32_Sword ri_gp_value; /* $gp register value */ -} Elf32_RegInfo; - -/* Entries found in sections of type SHT_MIPS_OPTIONS. */ - -typedef struct -{ - unsigned char kind; /* Determines interpretation of the - variable part of descriptor. */ - unsigned char size; /* Size of descriptor, including header. */ - Elf32_Section section; /* Section header index of section affected, - 0 for global options. */ - Elf32_Word info; /* Kind-specific information. */ -} Elf_Options; - -/* Values for `kind' field in Elf_Options. */ - -#define ODK_NULL 0 /* Undefined. */ -#define ODK_REGINFO 1 /* Register usage information. */ -#define ODK_EXCEPTIONS 2 /* Exception processing options. */ -#define ODK_PAD 3 /* Section padding options. */ -#define ODK_HWPATCH 4 /* Hardware workarounds performed */ -#define ODK_FILL 5 /* record the fill value used by the linker. */ -#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ -#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ -#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ - -/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ - -#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ -#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ -#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ -#define OEX_SMM 0x20000 /* Force sequential memory mode? */ -#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ -#define OEX_PRECISEFP OEX_FPDBUG -#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ - -#define OEX_FPU_INVAL 0x10 -#define OEX_FPU_DIV0 0x08 -#define OEX_FPU_OFLO 0x04 -#define OEX_FPU_UFLO 0x02 -#define OEX_FPU_INEX 0x01 - -/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ - -#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ -#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ -#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ -#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ - -#define OPAD_PREFIX 0x1 -#define OPAD_POSTFIX 0x2 -#define OPAD_SYMBOL 0x4 - -/* Entry found in `.options' section. */ - -typedef struct -{ - Elf32_Word hwp_flags1; /* Extra flags. */ - Elf32_Word hwp_flags2; /* Extra flags. */ -} Elf_Options_Hw; - -/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ - -#define OHWA0_R4KEOP_CHECKED 0x00000001 -#define OHWA1_R4KEOP_CLEAN 0x00000002 - -/* MIPS relocs. */ - -#define R_MIPS_NONE 0 /* No reloc */ -#define R_MIPS_16 1 /* Direct 16 bit */ -#define R_MIPS_32 2 /* Direct 32 bit */ -#define R_MIPS_REL32 3 /* PC relative 32 bit */ -#define R_MIPS_26 4 /* Direct 26 bit shifted */ -#define R_MIPS_HI16 5 /* High 16 bit */ -#define R_MIPS_LO16 6 /* Low 16 bit */ -#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ -#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ -#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ -#define R_MIPS_PC16 10 /* PC relative 16 bit */ -#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ -#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ - -#define R_MIPS_SHIFT5 16 -#define R_MIPS_SHIFT6 17 -#define R_MIPS_64 18 -#define R_MIPS_GOT_DISP 19 -#define R_MIPS_GOT_PAGE 20 -#define R_MIPS_GOT_OFST 21 -#define R_MIPS_GOT_HI16 22 -#define R_MIPS_GOT_LO16 23 -#define R_MIPS_SUB 24 -#define R_MIPS_INSERT_A 25 -#define R_MIPS_INSERT_B 26 -#define R_MIPS_DELETE 27 -#define R_MIPS_HIGHER 28 -#define R_MIPS_HIGHEST 29 -#define R_MIPS_CALL_HI16 30 -#define R_MIPS_CALL_LO16 31 -#define R_MIPS_SCN_DISP 32 -#define R_MIPS_REL16 33 -#define R_MIPS_ADD_IMMEDIATE 34 -#define R_MIPS_PJUMP 35 -#define R_MIPS_RELGOT 36 -#define R_MIPS_JALR 37 -/* Keep this the last entry. */ -#define R_MIPS_NUM 38 - -/* Legal values for p_type field of Elf32_Phdr. */ - -#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ -#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ -#define PT_MIPS_OPTIONS 0x70000002 - -/* Special program header types. */ - -#define PF_MIPS_LOCAL 0x10000000 - -/* Legal values for d_tag field of Elf32_Dyn. */ - -#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ -#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ -#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ -#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ -#define DT_MIPS_FLAGS 0x70000005 /* Flags */ -#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ -#define DT_MIPS_MSYM 0x70000007 -#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ -#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ -#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ -#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ -#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ -#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ -#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ -#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ -#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ -#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ -#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ -#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in - DT_MIPS_DELTA_CLASS. */ -#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ -#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in - DT_MIPS_DELTA_INSTANCE. */ -#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ -#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in - DT_MIPS_DELTA_RELOC. */ -#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta - relocations refer to. */ -#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in - DT_MIPS_DELTA_SYM. */ -#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the - class declaration. */ -#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in - DT_MIPS_DELTA_CLASSSYM. */ -#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ -#define DT_MIPS_PIXIE_INIT 0x70000023 -#define DT_MIPS_SYMBOL_LIB 0x70000024 -#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 -#define DT_MIPS_LOCAL_GOTIDX 0x70000026 -#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 -#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 -#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ -#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ -#define DT_MIPS_DYNSTR_ALIGN 0x7000002b -#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ -#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve - function stored in GOT. */ -#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added - by rld on dlopen() calls. */ -#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ -#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ -#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ -#define DT_MIPS_NUM 0x32 - -/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ - -#define RHF_NONE 0 /* No flags */ -#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ -#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ -#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ -#define RHF_NO_MOVE (1 << 3) -#define RHF_SGI_ONLY (1 << 4) -#define RHF_GUARANTEE_INIT (1 << 5) -#define RHF_DELTA_C_PLUS_PLUS (1 << 6) -#define RHF_GUARANTEE_START_INIT (1 << 7) -#define RHF_PIXIE (1 << 8) -#define RHF_DEFAULT_DELAY_LOAD (1 << 9) -#define RHF_REQUICKSTART (1 << 10) -#define RHF_REQUICKSTARTED (1 << 11) -#define RHF_CORD (1 << 12) -#define RHF_NO_UNRES_UNDEF (1 << 13) -#define RHF_RLD_ORDER_SAFE (1 << 14) - -/* Entries found in sections of type SHT_MIPS_LIBLIST. */ - -typedef struct -{ - Elf32_Word l_name; /* Name (string table index) */ - Elf32_Word l_time_stamp; /* Timestamp */ - Elf32_Word l_checksum; /* Checksum */ - Elf32_Word l_version; /* Interface version */ - Elf32_Word l_flags; /* Flags */ -} Elf32_Lib; - -typedef struct -{ - Elf64_Word l_name; /* Name (string table index) */ - Elf64_Word l_time_stamp; /* Timestamp */ - Elf64_Word l_checksum; /* Checksum */ - Elf64_Word l_version; /* Interface version */ - Elf64_Word l_flags; /* Flags */ -} Elf64_Lib; - - -/* Legal values for l_flags. */ - -#define LL_NONE 0 -#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ -#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ -#define LL_REQUIRE_MINOR (1 << 2) -#define LL_EXPORTS (1 << 3) -#define LL_DELAY_LOAD (1 << 4) -#define LL_DELTA (1 << 5) - -/* Entries found in sections of type SHT_MIPS_CONFLICT. */ - -typedef Elf32_Addr Elf32_Conflict; - - -/* HPPA specific definitions. */ - -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ -#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ -#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ -#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ -#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch - prediction. */ -#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ -#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ - -/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ - -#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ -#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ -#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ - -/* Additional section indeces. */ - -#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared - symbols in ANSI C. */ -#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ - -/* Legal values for sh_type field of Elf32_Shdr. */ - -#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ -#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ -#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ - -/* Legal values for sh_flags field of Elf32_Shdr. */ - -#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ -#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ -#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ - -/* Legal values for ST_TYPE subfield of st_info (symbol type). */ - -#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ - -#define STT_HP_OPAQUE (STT_LOOS + 0x1) -#define STT_HP_STUB (STT_LOOS + 0x2) - -/* HPPA relocs. */ - -#define R_PARISC_NONE 0 /* No reloc. */ -#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ -#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ -#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ -#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ -#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ -#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ -#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ -#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ -#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ -#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ -#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ -#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ -#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ -#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ -#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ -#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ -#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ -#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ -#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ -#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ -#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ -#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ -#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ -#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ -#define R_PARISC_FPTR64 64 /* 64 bits function address. */ -#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ -#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ -#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ -#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ -#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ -#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ -#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ -#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ -#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ -#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ -#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ -#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ -#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ -#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ -#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ -#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ -#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ -#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ -#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ -#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ -#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ -#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ -#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ -#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ -#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ -#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ -#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ -#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ -#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ -#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ -#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ -#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ -#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ -#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ -#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ -#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ -#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ -#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ -#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ -#define R_PARISC_LORESERVE 128 -#define R_PARISC_COPY 128 /* Copy relocation. */ -#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ -#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ -#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ -#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ -#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ -#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ -#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ -#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ -#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ -#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ -#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ -#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ -#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ -#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ -#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ -#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ -#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ -#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ -#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ -#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ -#define R_PARISC_HIRESERVE 255 - -/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ - -#define PT_HP_TLS (PT_LOOS + 0x0) -#define PT_HP_CORE_NONE (PT_LOOS + 0x1) -#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) -#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) -#define PT_HP_CORE_COMM (PT_LOOS + 0x4) -#define PT_HP_CORE_PROC (PT_LOOS + 0x5) -#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) -#define PT_HP_CORE_STACK (PT_LOOS + 0x7) -#define PT_HP_CORE_SHM (PT_LOOS + 0x8) -#define PT_HP_CORE_MMF (PT_LOOS + 0x9) -#define PT_HP_PARALLEL (PT_LOOS + 0x10) -#define PT_HP_FASTBIND (PT_LOOS + 0x11) -#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) -#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) -#define PT_HP_STACK (PT_LOOS + 0x14) - -#define PT_PARISC_ARCHEXT 0x70000000 -#define PT_PARISC_UNWIND 0x70000001 - -/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ - -#define PF_PARISC_SBP 0x08000000 - -#define PF_HP_PAGE_SIZE 0x00100000 -#define PF_HP_FAR_SHARED 0x00200000 -#define PF_HP_NEAR_SHARED 0x00400000 -#define PF_HP_CODE 0x01000000 -#define PF_HP_MODIFY 0x02000000 -#define PF_HP_LAZYSWAP 0x04000000 -#define PF_HP_SBP 0x08000000 - - -/* Alpha specific definitions. */ - -/* Legal values for e_flags field of Elf64_Ehdr. */ - -#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ -#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ - -/* Legal values for sh_type field of Elf64_Shdr. */ - -/* These two are primerily concerned with ECOFF debugging info. */ -#define SHT_ALPHA_DEBUG 0x70000001 -#define SHT_ALPHA_REGINFO 0x70000002 - -/* Legal values for sh_flags field of Elf64_Shdr. */ - -#define SHF_ALPHA_GPREL 0x10000000 - -/* Legal values for st_other field of Elf64_Sym. */ -#define STO_ALPHA_NOPV 0x80 /* No PV required. */ -#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ - -/* Alpha relocs. */ - -#define R_ALPHA_NONE 0 /* No reloc */ -#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ -#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ -#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ -#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ -#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ -#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ -#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ -#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ -#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ -#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ -#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ -#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ -#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ -#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ -#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ -#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ -#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ -#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ -#define R_ALPHA_TLS_GD_HI 28 -#define R_ALPHA_TLSGD 29 -#define R_ALPHA_TLS_LDM 30 -#define R_ALPHA_DTPMOD64 31 -#define R_ALPHA_GOTDTPREL 32 -#define R_ALPHA_DTPREL64 33 -#define R_ALPHA_DTPRELHI 34 -#define R_ALPHA_DTPRELLO 35 -#define R_ALPHA_DTPREL16 36 -#define R_ALPHA_GOTTPREL 37 -#define R_ALPHA_TPREL64 38 -#define R_ALPHA_TPRELHI 39 -#define R_ALPHA_TPRELLO 40 -#define R_ALPHA_TPREL16 41 -/* Keep this the last entry. */ -#define R_ALPHA_NUM 46 - -/* Magic values of the LITUSE relocation addend. */ -#define LITUSE_ALPHA_ADDR 0 -#define LITUSE_ALPHA_BASE 1 -#define LITUSE_ALPHA_BYTOFF 2 -#define LITUSE_ALPHA_JSR 3 -#define LITUSE_ALPHA_TLS_GD 4 -#define LITUSE_ALPHA_TLS_LDM 5 - - -/* PowerPC specific declarations */ - -/* Values for Elf32/64_Ehdr.e_flags. */ -#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ - -/* Cygnus local bits below */ -#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ -#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib - flag */ - -/* PowerPC relocations defined by the ABIs */ -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 /* 32bit absolute address */ -#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ -#define R_PPC_ADDR16 3 /* 16bit absolute address */ -#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ -#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ -#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ -#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 /* PC relative 26 bit */ -#define R_PPC_REL14 11 /* PC relative 16 bit */ -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 -/* Keep this the last entry. */ -#define R_PPC_NUM 37 - -/* PowerPC64 relocations defined by the ABIs */ -#define R_PPC64_NONE R_PPC_NONE -#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */ -#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */ -#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */ -#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */ -#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */ -#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ -#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */ -#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN -#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN -#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */ -#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */ -#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN -#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN -#define R_PPC64_GOT16 R_PPC_GOT16 -#define R_PPC64_GOT16_LO R_PPC_GOT16_LO -#define R_PPC64_GOT16_HI R_PPC_GOT16_HI -#define R_PPC64_GOT16_HA R_PPC_GOT16_HA - -#define R_PPC64_COPY R_PPC_COPY -#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT -#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT -#define R_PPC64_RELATIVE R_PPC_RELATIVE - -#define R_PPC64_UADDR32 R_PPC_UADDR32 -#define R_PPC64_UADDR16 R_PPC_UADDR16 -#define R_PPC64_REL32 R_PPC_REL32 -#define R_PPC64_PLT32 R_PPC_PLT32 -#define R_PPC64_PLTREL32 R_PPC_PLTREL32 -#define R_PPC64_PLT16_LO R_PPC_PLT16_LO -#define R_PPC64_PLT16_HI R_PPC_PLT16_HI -#define R_PPC64_PLT16_HA R_PPC_PLT16_HA - -#define R_PPC64_SECTOFF R_PPC_SECTOFF -#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO -#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI -#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA -#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */ -#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */ -#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */ -#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */ -#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */ -#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */ -#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */ -#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */ -#define R_PPC64_PLT64 45 /* doubleword64 L + A. */ -#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */ -#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */ -#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */ -#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */ -#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */ -#define R_PPC64_TOC 51 /* doubleword64 .TOC. */ -#define R_PPC64_PLTGOT16 52 /* half16* M + A. */ -#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */ -#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */ -#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */ - -#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */ -#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */ -#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */ -#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */ -#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */ -#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */ -#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */ -#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */ -#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */ -#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */ -#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */ -/* Keep this the last entry. */ -#define R_PPC64_NUM 67 - -/* The remaining relocs are from the Embedded ELF ABI, and are not - in the SVR4 ELF ABI. */ -#define R_PPC_EMB_NADDR32 101 -#define R_PPC_EMB_NADDR16 102 -#define R_PPC_EMB_NADDR16_LO 103 -#define R_PPC_EMB_NADDR16_HI 104 -#define R_PPC_EMB_NADDR16_HA 105 -#define R_PPC_EMB_SDAI16 106 -#define R_PPC_EMB_SDA2I16 107 -#define R_PPC_EMB_SDA2REL 108 -#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ -#define R_PPC_EMB_MRKREF 110 -#define R_PPC_EMB_RELSEC16 111 -#define R_PPC_EMB_RELST_LO 112 -#define R_PPC_EMB_RELST_HI 113 -#define R_PPC_EMB_RELST_HA 114 -#define R_PPC_EMB_BIT_FLD 115 -#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ - -/* Diab tool relocations. */ -#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ -#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ -#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ -#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ -#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ -#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ - -/* This is a phony reloc to handle any old fashioned TOC16 references - that may still be in object files. */ -#define R_PPC_TOC16 255 - -/* PowerPC64 specific values for the Dyn d_tag field. */ -#define DT_PPC64_GLINK (DT_LOPROC + 0) -#define DT_PPC64_NUM 1 - -/* ARM specific declarations */ - -/* Processor specific flags for the ELF header e_flags field. */ -#define EF_ARM_RELEXEC 0x01 -#define EF_ARM_HASENTRY 0x02 -#define EF_ARM_INTERWORK 0x04 -#define EF_ARM_APCS_26 0x08 -#define EF_ARM_APCS_FLOAT 0x10 -#define EF_ARM_PIC 0x20 -#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ -#define EF_ARM_NEW_ABI 0x80 -#define EF_ARM_OLD_ABI 0x100 - -/* Other constants defined in the ARM ELF spec. version B-01. */ -/* NB. These conflict with values defined above. */ -#define EF_ARM_SYMSARESORTED 0x04 -#define EF_ARM_DYNSYMSUSESEGIDX 0x08 -#define EF_ARM_MAPSYMSFIRST 0x10 -#define EF_ARM_EABIMASK 0XFF000000 - -#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) -#define EF_ARM_EABI_UNKNOWN 0x00000000 -#define EF_ARM_EABI_VER1 0x01000000 -#define EF_ARM_EABI_VER2 0x02000000 - -/* Additional symbol types for Thumb */ -#define STT_ARM_TFUNC 0xd - -/* ARM-specific values for sh_flags */ -#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ -#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined - in the input to a link step */ - -/* ARM-specific program header flags */ -#define PF_ARM_SB 0x10000000 /* Segment contains the location - addressed by the static base */ - -/* ARM relocs. */ -#define R_ARM_NONE 0 /* No reloc */ -#define R_ARM_PC24 1 /* PC relative 26 bit branch */ -#define R_ARM_ABS32 2 /* Direct 32 bit */ -#define R_ARM_REL32 3 /* PC relative 32 bit */ -#define R_ARM_PC13 4 -#define R_ARM_ABS16 5 /* Direct 16 bit */ -#define R_ARM_ABS12 6 /* Direct 12 bit */ -#define R_ARM_THM_ABS5 7 -#define R_ARM_ABS8 8 /* Direct 8 bit */ -#define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 -#define R_ARM_THM_PC8 11 -#define R_ARM_AMP_VCALL9 12 -#define R_ARM_SWI24 13 -#define R_ARM_THM_SWI8 14 -#define R_ARM_XPC25 15 -#define R_ARM_THM_XPC22 16 -#define R_ARM_COPY 20 /* Copy symbol at runtime */ -#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ -#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ -#define R_ARM_RELATIVE 23 /* Adjust by program base */ -#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ -#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ -#define R_ARM_GOT32 26 /* 32 bit GOT entry */ -#define R_ARM_PLT32 27 /* 32 bit PLT address */ -#define R_ARM_ALU_PCREL_7_0 32 -#define R_ARM_ALU_PCREL_15_8 33 -#define R_ARM_ALU_PCREL_23_15 34 -#define R_ARM_LDR_SBREL_11_0 35 -#define R_ARM_ALU_SBREL_19_12 36 -#define R_ARM_ALU_SBREL_27_20 37 -#define R_ARM_GNU_VTENTRY 100 -#define R_ARM_GNU_VTINHERIT 101 -#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ -#define R_ARM_THM_PC9 103 /* thumb conditional branch */ -#define R_ARM_RXPC25 249 -#define R_ARM_RSBREL32 250 -#define R_ARM_THM_RPC22 251 -#define R_ARM_RREL32 252 -#define R_ARM_RABS22 253 -#define R_ARM_RPC24 254 -#define R_ARM_RBASE 255 -/* Keep this the last entry. */ -#define R_ARM_NUM 256 - -/* IA-64 specific declarations. */ - -/* Processor specific flags for the Ehdr e_flags field. */ -#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ -#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ -#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ - -/* Processor specific values for the Phdr p_type field. */ -#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ -#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ - -/* Processor specific flags for the Phdr p_flags field. */ -#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ - -/* Processor specific values for the Shdr sh_type field. */ -#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ -#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ - -/* Processor specific flags for the Shdr sh_flags field. */ -#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ -#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ - -/* Processor specific values for the Dyn d_tag field. */ -#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) -#define DT_IA_64_NUM 1 - -/* IA-64 relocations. */ -#define R_IA64_NONE 0x00 /* none */ -#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ -#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ -#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ -#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ -#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ -#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ -#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ -#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ -#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ -#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ -#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ -#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ -#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ -#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ -#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ -#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ -#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ -#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ -#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ -#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ -#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ -#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ -#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ -#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ -#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ -#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ -#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ -#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ -#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ -#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ -#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ -#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ -#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ -#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ -#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ -#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ -#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ -#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ -#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ -#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ -#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ -#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ -#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ -#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ -#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ -#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ -#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ -#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ -#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ -#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ -#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ -#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ -#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ -#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ -#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ -#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ -#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ -#define R_IA64_COPY 0x84 /* copy relocation */ -#define R_IA64_SUB 0x85 /* Addend and symbol difference */ -#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ -#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ -#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ -#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ -#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ -#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ -#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ -#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ -#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ -#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ -#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ -#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ -#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ -#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ -#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ -#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ -#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ -#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ - -/* SH specific declarations */ - -/* SH relocs. */ -#define R_SH_NONE 0 -#define R_SH_DIR32 1 -#define R_SH_REL32 2 -#define R_SH_DIR8WPN 3 -#define R_SH_IND12W 4 -#define R_SH_DIR8WPL 5 -#define R_SH_DIR8WPZ 6 -#define R_SH_DIR8BP 7 -#define R_SH_DIR8W 8 -#define R_SH_DIR8L 9 -#define R_SH_SWITCH16 25 -#define R_SH_SWITCH32 26 -#define R_SH_USES 27 -#define R_SH_COUNT 28 -#define R_SH_ALIGN 29 -#define R_SH_CODE 30 -#define R_SH_DATA 31 -#define R_SH_LABEL 32 -#define R_SH_SWITCH8 33 -#define R_SH_GNU_VTINHERIT 34 -#define R_SH_GNU_VTENTRY 35 -#define R_SH_TLS_GD_32 144 -#define R_SH_TLS_LD_32 145 -#define R_SH_TLS_LDO_32 146 -#define R_SH_TLS_IE_32 147 -#define R_SH_TLS_LE_32 148 -#define R_SH_TLS_DTPMOD32 149 -#define R_SH_TLS_DTPOFF32 150 -#define R_SH_TLS_TPOFF32 151 -#define R_SH_GOT32 160 -#define R_SH_PLT32 161 -#define R_SH_COPY 162 -#define R_SH_GLOB_DAT 163 -#define R_SH_JMP_SLOT 164 -#define R_SH_RELATIVE 165 -#define R_SH_GOTOFF 166 -#define R_SH_GOTPC 167 -/* Keep this the last entry. */ -#define R_SH_NUM 256 - -/* Additional s390 relocs */ - -#define R_390_NONE 0 /* No reloc. */ -#define R_390_8 1 /* Direct 8 bit. */ -#define R_390_12 2 /* Direct 12 bit. */ -#define R_390_16 3 /* Direct 16 bit. */ -#define R_390_32 4 /* Direct 32 bit. */ -#define R_390_PC32 5 /* PC relative 32 bit. */ -#define R_390_GOT12 6 /* 12 bit GOT offset. */ -#define R_390_GOT32 7 /* 32 bit GOT offset. */ -#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ -#define R_390_COPY 9 /* Copy symbol at runtime. */ -#define R_390_GLOB_DAT 10 /* Create GOT entry. */ -#define R_390_JMP_SLOT 11 /* Create PLT entry. */ -#define R_390_RELATIVE 12 /* Adjust by program base. */ -#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ -#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ -#define R_390_GOT16 15 /* 16 bit GOT offset. */ -#define R_390_PC16 16 /* PC relative 16 bit. */ -#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ -#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ -#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ -#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ -#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ -#define R_390_64 22 /* Direct 64 bit. */ -#define R_390_PC64 23 /* PC relative 64 bit. */ -#define R_390_GOT64 24 /* 64 bit GOT offset. */ -#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ -#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ -#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ -#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ -#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ -#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ -#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ -#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ -#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ -#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ -#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ -#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ -#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ -#define R_390_TLS_GDCALL 38 /* Tag for function call in general - dynamic TLS code. */ -#define R_390_TLS_LDCALL 39 /* Tag for function call in local - dynamic TLS code. */ -#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic - thread local data. */ -#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic - thread local data. */ -#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS - block offset. */ -#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS - block offset. */ -#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS - block offset. */ -#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic - thread local data in LE code. */ -#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic - thread local data in LE code. */ -#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for - negated static TLS block offset. */ -#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for - negated static TLS block offset. */ -#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for - negated static TLS block offset. */ -#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to - static TLS block. */ -#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to - static TLS block. */ -#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS - block. */ -#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS - block. */ -#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ -#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ -#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS - block. */ - -/* Keep this the last entry. */ -#define R_390_NUM 57 - -/* CRIS relocations. */ -#define R_CRIS_NONE 0 -#define R_CRIS_8 1 -#define R_CRIS_16 2 -#define R_CRIS_32 3 -#define R_CRIS_8_PCREL 4 -#define R_CRIS_16_PCREL 5 -#define R_CRIS_32_PCREL 6 -#define R_CRIS_GNU_VTINHERIT 7 -#define R_CRIS_GNU_VTENTRY 8 -#define R_CRIS_COPY 9 -#define R_CRIS_GLOB_DAT 10 -#define R_CRIS_JUMP_SLOT 11 -#define R_CRIS_RELATIVE 12 -#define R_CRIS_16_GOT 13 -#define R_CRIS_32_GOT 14 -#define R_CRIS_16_GOTPLT 15 -#define R_CRIS_32_GOTPLT 16 -#define R_CRIS_32_GOTREL 17 -#define R_CRIS_32_PLT_GOTREL 18 -#define R_CRIS_32_PLT_PCREL 19 - -#define R_CRIS_NUM 20 - -/* AMD x86-64 relocations. */ -#define R_X86_64_NONE 0 /* No reloc */ -#define R_X86_64_64 1 /* Direct 64 bit */ -#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ -#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ -#define R_X86_64_PLT32 4 /* 32 bit PLT address */ -#define R_X86_64_COPY 5 /* Copy symbol at runtime */ -#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ -#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ -#define R_X86_64_RELATIVE 8 /* Adjust by program base */ -#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative - offset to GOT */ -#define R_X86_64_32 10 /* Direct 32 bit zero extended */ -#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ -#define R_X86_64_16 12 /* Direct 16 bit zero extended */ -#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ -#define R_X86_64_8 14 /* Direct 8 bit sign extended */ -#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ -#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ -#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ -#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ -#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset - to two GOT entries for GD symbol */ -#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset - to two GOT entries for LD symbol */ -#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ -#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset - to GOT entry for IE symbol */ -#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ - -#define R_X86_64_NUM 24 - -#endif /* elf.h */ diff --git a/SheepShaver/src/kpx_cpu/include/nvmemfun.hpp b/SheepShaver/src/kpx_cpu/include/nvmemfun.hpp deleted file mode 100644 index efad01ff..00000000 --- a/SheepShaver/src/kpx_cpu/include/nvmemfun.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * nvmemfun.hpp - Non-virtual member function wrappers - * - * Kheperix (C) 2003 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef NVMEMFUN_H -#define NVMEMFUN_H - -#include - -#if defined __GNUC__ -#define HAVE_FAST_NV_MEM_FUN 1 -#define MEM_FUN_WORDS 2 -#if defined __GXX_ABI_VERSION /* GCC >= 3.0 */ -#define MEM_FUN_OFFSET 0 -#else -#define MEM_FUN_OFFSET 1 -#endif -#endif - -#if defined __ICC -#define HAVE_FAST_NV_MEM_FUN 1 -#define MEM_FUN_WORDS 2 -#define MEM_FUN_OFFSET 0 /* GNU C++ ABI v3 */ -#endif - -#if defined __EDG__ && defined __sgi -#define HAVE_FAST_NV_MEM_FUN 1 -#define MEM_FUN_WORDS 3 -#define MEM_FUN_OFFSET 2 -#endif - -#if HAVE_FAST_NV_MEM_FUN - -template< class PMF, class PF > -inline PF nv_mem_fun_of(PMF pmf) { - if (pmf == 0) - return 0; - union { PMF pmf; uintptr p[MEM_FUN_WORDS]; } x; - x.pmf = pmf; - return (PF)x.p[MEM_FUN_OFFSET]; -} - -template< class R, class T > -class nv_mem_fun_t : public std::unary_function { - typedef R (T::*pmf_t)(); - typedef R (*pf_t)(T *); - pf_t pf; -public: - nv_mem_fun_t(pmf_t pmf) : pf(nv_mem_fun_of(pmf)) {} - R operator()(T *p) const { return (*pf)(p); } - pf_t ptr() const { return pf; } -}; - -template< class R, class T > -class const_nv_mem_fun_t : public std::unary_function { - typedef R (T::*pmf_t)(); - typedef R (*pf_t)(T *); - pf_t const pf; -public: - const_nv_mem_fun_t(pmf_t const pmf) : pf(nv_mem_fun_of(pmf)) {} - R operator()(const T *p) const { return (*pf)(p); } - pf_t ptr() const { return pf; } -}; - -template< class R, class T, class A > -class nv_mem_fun1_t : public std::binary_function { - typedef R (T::*pmf_t)(A); - typedef R (*pf_t)(T *, A x); - pf_t pf; -public: - nv_mem_fun1_t(pmf_t pmf) : pf(nv_mem_fun_of(pmf)) {} - R operator()(T *p, A x) const { return (*pf)(p, x); } - pf_t ptr() const { return pf; } -}; - -template< class R, class T, class A > -class const_nv_mem_fun1_t : public std::binary_function { - typedef R (T::*pmf_t)(A); - typedef R (*pf_t)(T *, A x); - pf_t const pf; -public: - const_nv_mem_fun1_t(pmf_t const pmf) : pf(nv_mem_fun_of(pmf)) {} - R operator()(const T *p, A x) const { return (*pf)(p, x); } - pf_t ptr() const { return pf; } -}; - -#else - -template< class R, class T > -class nv_mem_fun_t : public std::unary_function { - typedef R (T::*pmf_t)(); - pmf_t pf; -public: - nv_mem_fun_t(R (T::*pmf)()) : pf(pmf) {} - R operator()(T *p) const { return (p->*pf)(); } - pmf_t ptr() const { return pf; } -}; - -template< class R, class T > -class const_nv_mem_fun_t : public std::unary_function { - typedef R (T::*pmf_t)() const; - pmf_t pf; -public: - const_nv_mem_fun_t(R (T::*pmf)() const) : pf(pmf) {} - R operator()(const T *p) const { return (p->*pf)(); } - pmf_t ptr() const { return pf; } -}; - -template< class R, class T, class A > -class nv_mem_fun1_t : public std::binary_function { - typedef R (T::*pmf_t)(A); - pmf_t pf; -public: - nv_mem_fun1_t(R (T::*pmf)(A)) : pf(pmf) {} - R operator()(T *p, A x) const { return (p->*pf)(x); } - pmf_t ptr() const { return pf; } -}; - -template< class R, class T, class A > -class const_nv_mem_fun1_t : public std::binary_function { - typedef R (T::*pmf_t)(A) const; - pmf_t pf; -public: - const_nv_mem_fun1_t(R (T::*pmf)(A) const) : pf(pmf) {} - R operator()(const T *p, A x) const { return (p->*pf)(x); } - pmf_t ptr() const { return pf; } -}; - -#endif - -template< class R, class T > -inline nv_mem_fun_t nv_mem_fun(R (T::*pmf)()) { - return nv_mem_fun_t(pmf); -} - -template< class R, class T > -inline const_nv_mem_fun_t nv_mem_fun(R (T::*pmf)() const) { - return const_nv_mem_fun_t(pmf); -} - -template< class R, class T, class A > -inline nv_mem_fun1_t nv_mem_fun(R (T::*pmf)(A)) { - return nv_mem_fun1_t(pmf); -} - -template< class R, class T, class A > -inline const_nv_mem_fun1_t nv_mem_fun(R (T::*pmf)(A) const) { - return const_nv_mem_fun1_t(pmf); -} - -#endif /* NVMEMFUN_H */ diff --git a/SheepShaver/src/kpx_cpu/include/task-plugin.hpp b/SheepShaver/src/kpx_cpu/include/task-plugin.hpp deleted file mode 100644 index c57fcd08..00000000 --- a/SheepShaver/src/kpx_cpu/include/task-plugin.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * task-plugin.hpp - Task plugin definition - * - * Kheperix (C) 2003 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TASK_PLUGIN_H -#define TASK_PLUGIN_H - -#include "basic-plugin.hpp" - -// Forward declarations -class task_struct; -class basic_kernel; -class basic_cpu; -class program_info; - -// Base class for all task components -class task_plugin - : public basic_plugin -{ - // Parent task - task_struct * task; - -public: - - // Constructor - task_plugin(task_struct * parent_task) : task(parent_task) { } - - // Public accessors to resolve various components of a task - basic_kernel * kernel() const; - basic_cpu * cpu() const; - program_info * program() const; -}; - -// Get out of specified task -extern void task_exit(task_plugin *task, int status); - -#endif /* TASK_PLUGIN_H */ diff --git a/SheepShaver/src/kpx_cpu/ppc-dis.c b/SheepShaver/src/kpx_cpu/ppc-dis.c deleted file mode 100644 index a2478e63..00000000 --- a/SheepShaver/src/kpx_cpu/ppc-dis.c +++ /dev/null @@ -1,5489 +0,0 @@ -/* ppc-dis.c -- Disassemble PowerPC instructions - Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 - Free Software Foundation, Inc. - Written by Ian Lance Taylor, Cygnus Support - -This file is part of GDB, GAS, and the GNU binutils. - -GDB, GAS, and the GNU binutils are free software; you can redistribute -them and/or modify them under the terms of the GNU General Public -License as published by the Free Software Foundation; either version -2, or (at your option) any later version. - -GDB, GAS, and the GNU binutils are distributed in the hope that they -will be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this file; see the file COPYING. If not, -see . */ - -#include -#include - -#include "dis-asm.h" - -#define BFD_DEFAULT_TARGET_SIZE 64 - -/* ppc.h -- Header file for PowerPC opcode table - Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007 Free Software Foundation, Inc. - Written by Ian Lance Taylor, Cygnus Support - -This file is part of GDB, GAS, and the GNU binutils. - -GDB, GAS, and the GNU binutils are free software; you can redistribute -them and/or modify them under the terms of the GNU General Public -License as published by the Free Software Foundation; either version -1, or (at your option) any later version. - -GDB, GAS, and the GNU binutils are distributed in the hope that they -will be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this file; see the file COPYING. If not, -see . */ - -/* The opcode table is an array of struct powerpc_opcode. */ - -struct powerpc_opcode -{ - /* The opcode name. */ - const char *name; - - /* The opcode itself. Those bits which will be filled in with - operands are zeroes. */ - unsigned long opcode; - - /* The opcode mask. This is used by the disassembler. This is a - mask containing ones indicating those bits which must match the - opcode field, and zeroes indicating those bits which need not - match (and are presumably filled in by operands). */ - unsigned long mask; - - /* One bit flags for the opcode. These are used to indicate which - specific processors support the instructions. The defined values - are listed below. */ - unsigned long flags; - - /* An array of operand codes. Each code is an index into the - operand table. They appear in the order which the operands must - appear in assembly code, and are terminated by a zero. */ - unsigned char operands[8]; -}; - -/* The table itself is sorted by major opcode number, and is otherwise - in the order in which the disassembler should consider - instructions. */ -extern const struct powerpc_opcode powerpc_opcodes[]; -extern const int powerpc_num_opcodes; - -/* Values defined for the flags field of a struct powerpc_opcode. */ - -/* Opcode is defined for the PowerPC architecture. */ -#define PPC_OPCODE_PPC 1 - -/* Opcode is defined for the POWER (RS/6000) architecture. */ -#define PPC_OPCODE_POWER 2 - -/* Opcode is defined for the POWER2 (Rios 2) architecture. */ -#define PPC_OPCODE_POWER2 4 - -/* Opcode is only defined on 32 bit architectures. */ -#define PPC_OPCODE_32 8 - -/* Opcode is only defined on 64 bit architectures. */ -#define PPC_OPCODE_64 0x10 - -/* Opcode is supported by the Motorola PowerPC 601 processor. The 601 - is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions, - but it also supports many additional POWER instructions. */ -#define PPC_OPCODE_601 0x20 - -/* Opcode is supported in both the Power and PowerPC architectures - (ie, compiler's -mcpu=common or assembler's -mcom). */ -#define PPC_OPCODE_COMMON 0x40 - -/* Opcode is supported for any Power or PowerPC platform (this is - for the assembler's -many option, and it eliminates duplicates). */ -#define PPC_OPCODE_ANY 0x80 - -/* Opcode is supported as part of the 64-bit bridge. */ -#define PPC_OPCODE_64_BRIDGE 0x100 - -/* Opcode is supported by Altivec Vector Unit */ -#define PPC_OPCODE_ALTIVEC 0x200 - -/* Opcode is supported by PowerPC 403 processor. */ -#define PPC_OPCODE_403 0x400 - -/* Opcode is supported by PowerPC BookE processor. */ -#define PPC_OPCODE_BOOKE 0x800 - -/* Opcode is only supported by 64-bit PowerPC BookE processor. */ -#define PPC_OPCODE_BOOKE64 0x1000 - -/* Opcode is supported by PowerPC 440 processor. */ -#define PPC_OPCODE_440 0x2000 - -/* Opcode is only supported by Power4 architecture. */ -#define PPC_OPCODE_POWER4 0x4000 - -/* Opcode isn't supported by Power4 architecture. */ -#define PPC_OPCODE_NOPOWER4 0x8000 - -/* Opcode is only supported by POWERPC Classic architecture. */ -#define PPC_OPCODE_CLASSIC 0x10000 - -/* Opcode is only supported by e500x2 Core. */ -#define PPC_OPCODE_SPE 0x20000 - -/* Opcode is supported by e500x2 Integer select APU. */ -#define PPC_OPCODE_ISEL 0x40000 - -/* Opcode is an e500 SPE floating point instruction. */ -#define PPC_OPCODE_EFS 0x80000 - -/* Opcode is supported by branch locking APU. */ -#define PPC_OPCODE_BRLOCK 0x100000 - -/* Opcode is supported by performance monitor APU. */ -#define PPC_OPCODE_PMR 0x200000 - -/* Opcode is supported by cache locking APU. */ -#define PPC_OPCODE_CACHELCK 0x400000 - -/* Opcode is supported by machine check APU. */ -#define PPC_OPCODE_RFMCI 0x800000 - -/* Opcode is only supported by Power5 architecture. */ -#define PPC_OPCODE_POWER5 0x1000000 - -/* Opcode is supported by PowerPC e300 family. */ -#define PPC_OPCODE_E300 0x2000000 - -/* Opcode is only supported by Power6 architecture. */ -#define PPC_OPCODE_POWER6 0x4000000 - -/* Opcode is only supported by PowerPC Cell family. */ -#define PPC_OPCODE_CELL 0x8000000 - -/* A macro to extract the major opcode from an instruction. */ -#define PPC_OP(i) (((i) >> 26) & 0x3f) - -/* The operands table is an array of struct powerpc_operand. */ - -struct powerpc_operand -{ - /* A bitmask of bits in the operand. */ - unsigned int bitm; - - /* How far the operand is left shifted in the instruction. - -1 to indicate that BITM and SHIFT cannot be used to determine - where the operand goes in the insn. */ - int shift; - - /* Insertion function. This is used by the assembler. To insert an - operand value into an instruction, check this field. - - If it is NULL, execute - i |= (op & o->bitm) << o->shift; - (i is the instruction which we are filling in, o is a pointer to - this structure, and op is the operand value). - - If this field is not NULL, then simply call it with the - instruction and the operand value. It will return the new value - of the instruction. If the ERRMSG argument is not NULL, then if - the operand value is illegal, *ERRMSG will be set to a warning - string (the operand will be inserted in any case). If the - operand value is legal, *ERRMSG will be unchanged (most operands - can accept any value). */ - unsigned long (*insert) - (unsigned long instruction, long op, int dialect, const char **errmsg); - - /* Extraction function. This is used by the disassembler. To - extract this operand type from an instruction, check this field. - - If it is NULL, compute - op = (i >> o->shift) & o->bitm; - if ((o->flags & PPC_OPERAND_SIGNED) != 0) - sign_extend (op); - (i is the instruction, o is a pointer to this structure, and op - is the result). - - If this field is not NULL, then simply call it with the - instruction value. It will return the value of the operand. If - the INVALID argument is not NULL, *INVALID will be set to - non-zero if this operand type can not actually be extracted from - this operand (i.e., the instruction does not match). If the - operand is valid, *INVALID will not be changed. */ - long (*extract) (unsigned long instruction, int dialect, int *invalid); - - /* One bit syntax flags. */ - unsigned long flags; -}; - -/* Elements in the table are retrieved by indexing with values from - the operands field of the powerpc_opcodes table. */ - -extern const struct powerpc_operand powerpc_operands[]; -extern const unsigned int num_powerpc_operands; - -/* Values defined for the flags field of a struct powerpc_operand. */ - -/* This operand takes signed values. */ -#define PPC_OPERAND_SIGNED (0x1) - -/* This operand takes signed values, but also accepts a full positive - range of values when running in 32 bit mode. That is, if bits is - 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode, - this flag is ignored. */ -#define PPC_OPERAND_SIGNOPT (0x2) - -/* This operand does not actually exist in the assembler input. This - is used to support extended mnemonics such as mr, for which two - operands fields are identical. The assembler should call the - insert function with any op value. The disassembler should call - the extract function, ignore the return value, and check the value - placed in the valid argument. */ -#define PPC_OPERAND_FAKE (0x4) - -/* The next operand should be wrapped in parentheses rather than - separated from this one by a comma. This is used for the load and - store instructions which want their operands to look like - reg,displacement(reg) - */ -#define PPC_OPERAND_PARENS (0x8) - -/* This operand may use the symbolic names for the CR fields, which - are - lt 0 gt 1 eq 2 so 3 un 3 - cr0 0 cr1 1 cr2 2 cr3 3 - cr4 4 cr5 5 cr6 6 cr7 7 - These may be combined arithmetically, as in cr2*4+gt. These are - only supported on the PowerPC, not the POWER. */ -#define PPC_OPERAND_CR (0x10) - -/* This operand names a register. The disassembler uses this to print - register names with a leading 'r'. */ -#define PPC_OPERAND_GPR (0x20) - -/* Like PPC_OPERAND_GPR, but don't print a leading 'r' for r0. */ -#define PPC_OPERAND_GPR_0 (0x40) - -/* This operand names a floating point register. The disassembler - prints these with a leading 'f'. */ -#define PPC_OPERAND_FPR (0x80) - -/* This operand is a relative branch displacement. The disassembler - prints these symbolically if possible. */ -#define PPC_OPERAND_RELATIVE (0x100) - -/* This operand is an absolute branch address. The disassembler - prints these symbolically if possible. */ -#define PPC_OPERAND_ABSOLUTE (0x200) - -/* This operand is optional, and is zero if omitted. This is used for - example, in the optional BF field in the comparison instructions. The - assembler must count the number of operands remaining on the line, - and the number of operands remaining for the opcode, and decide - whether this operand is present or not. The disassembler should - print this operand out only if it is not zero. */ -#define PPC_OPERAND_OPTIONAL (0x400) - -/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand - is omitted, then for the next operand use this operand value plus - 1, ignoring the next operand field for the opcode. This wretched - hack is needed because the Power rotate instructions can take - either 4 or 5 operands. The disassembler should print this operand - out regardless of the PPC_OPERAND_OPTIONAL field. */ -#define PPC_OPERAND_NEXT (0x800) - -/* This operand should be regarded as a negative number for the - purposes of overflow checking (i.e., the normal most negative - number is disallowed and one more than the normal most positive - number is allowed). This flag will only be set for a signed - operand. */ -#define PPC_OPERAND_NEGATIVE (0x1000) - -/* This operand names a vector unit register. The disassembler - prints these with a leading 'v'. */ -#define PPC_OPERAND_VR (0x2000) - -/* This operand is for the DS field in a DS form instruction. */ -#define PPC_OPERAND_DS (0x4000) - -/* This operand is for the DQ field in a DQ form instruction. */ -#define PPC_OPERAND_DQ (0x8000) - -/* Valid range of operand is 0..n rather than 0..n-1. */ -#define PPC_OPERAND_PLUS1 (0x10000) - -/* The POWER and PowerPC assemblers use a few macros. We keep them - with the operands table for simplicity. The macro table is an - array of struct powerpc_macro. */ - -struct powerpc_macro -{ - /* The macro name. */ - const char *name; - - /* The number of operands the macro takes. */ - unsigned int operands; - - /* One bit flags for the opcode. These are used to indicate which - specific processors support the instructions. The values are the - same as those for the struct powerpc_opcode flags field. */ - unsigned long flags; - - /* A format string to turn the macro into a normal instruction. - Each %N in the string is replaced with operand number N (zero - based). */ - const char *format; -}; - -extern const struct powerpc_macro powerpc_macros[]; -extern const int powerpc_num_macros; - -/* ppc-opc.c -- PowerPC opcode list - Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007 Free Software Foundation, Inc. - Written by Ian Lance Taylor, Cygnus Support - - This file is part of GDB, GAS, and the GNU binutils. - - GDB, GAS, and the GNU binutils are free software; you can redistribute - them and/or modify them under the terms of the GNU General Public - License as published by the Free Software Foundation; either version - 2, or (at your option) any later version. - - GDB, GAS, and the GNU binutils are distributed in the hope that they - will be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this file; see the file COPYING. - If not, see . */ - -/* This file holds the PowerPC opcode table. The opcode table - includes almost all of the extended instruction mnemonics. This - permits the disassembler to use them, and simplifies the assembler - logic, at the cost of increasing the table size. The table is - strictly constant data, so the compiler should be able to put it in - the .text section. - - This file also holds the operand table. All knowledge about - inserting operands into instructions and vice-versa is kept in this - file. */ - -/* Local insertion and extraction functions. */ - -static unsigned long insert_bat (unsigned long, long, int, const char **); -static long extract_bat (unsigned long, int, int *); -static unsigned long insert_bba (unsigned long, long, int, const char **); -static long extract_bba (unsigned long, int, int *); -static unsigned long insert_bdm (unsigned long, long, int, const char **); -static long extract_bdm (unsigned long, int, int *); -static unsigned long insert_bdp (unsigned long, long, int, const char **); -static long extract_bdp (unsigned long, int, int *); -static unsigned long insert_bo (unsigned long, long, int, const char **); -static long extract_bo (unsigned long, int, int *); -static unsigned long insert_boe (unsigned long, long, int, const char **); -static long extract_boe (unsigned long, int, int *); -static unsigned long insert_fxm (unsigned long, long, int, const char **); -static long extract_fxm (unsigned long, int, int *); -static unsigned long insert_mbe (unsigned long, long, int, const char **); -static long extract_mbe (unsigned long, int, int *); -static unsigned long insert_mb6 (unsigned long, long, int, const char **); -static long extract_mb6 (unsigned long, int, int *); -static long extract_nb (unsigned long, int, int *); -static unsigned long insert_nsi (unsigned long, long, int, const char **); -static long extract_nsi (unsigned long, int, int *); -static unsigned long insert_ral (unsigned long, long, int, const char **); -static unsigned long insert_ram (unsigned long, long, int, const char **); -static unsigned long insert_raq (unsigned long, long, int, const char **); -static unsigned long insert_ras (unsigned long, long, int, const char **); -static unsigned long insert_rbs (unsigned long, long, int, const char **); -static long extract_rbs (unsigned long, int, int *); -static unsigned long insert_sh6 (unsigned long, long, int, const char **); -static long extract_sh6 (unsigned long, int, int *); -static unsigned long insert_spr (unsigned long, long, int, const char **); -static long extract_spr (unsigned long, int, int *); -static unsigned long insert_sprg (unsigned long, long, int, const char **); -static long extract_sprg (unsigned long, int, int *); -static unsigned long insert_tbr (unsigned long, long, int, const char **); -static long extract_tbr (unsigned long, int, int *); - -/* The operands table. - - The fields are bitm, shift, insert, extract, flags. - - We used to put parens around the various additions, like the one - for BA just below. However, that caused trouble with feeble - compilers with a limit on depth of a parenthesized expression, like - (reportedly) the compiler in Microsoft Developer Studio 5. So we - omit the parens, since the macros are never used in a context where - the addition will be ambiguous. */ - -const struct powerpc_operand powerpc_operands[] = -{ - /* The zero index is used to indicate the end of the list of - operands. */ -#define UNUSED 0 - { 0, 0, NULL, NULL, 0 }, - - /* The BA field in an XL form instruction. */ -#define BA UNUSED + 1 - /* The BI field in a B form or XL form instruction. */ -#define BI BA -#define BI_MASK (0x1f << 16) - { 0x1f, 16, NULL, NULL, PPC_OPERAND_CR }, - - /* The BA field in an XL form instruction when it must be the same - as the BT field in the same instruction. */ -#define BAT BA + 1 - { 0x1f, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE }, - - /* The BB field in an XL form instruction. */ -#define BB BAT + 1 -#define BB_MASK (0x1f << 11) - { 0x1f, 11, NULL, NULL, PPC_OPERAND_CR }, - - /* The BB field in an XL form instruction when it must be the same - as the BA field in the same instruction. */ -#define BBA BB + 1 - { 0x1f, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE }, - - /* The BD field in a B form instruction. The lower two bits are - forced to zero. */ -#define BD BBA + 1 - { 0xfffc, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, - - /* The BD field in a B form instruction when absolute addressing is - used. */ -#define BDA BD + 1 - { 0xfffc, 0, NULL, NULL, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, - - /* The BD field in a B form instruction when the - modifier is used. - This sets the y bit of the BO field appropriately. */ -#define BDM BDA + 1 - { 0xfffc, 0, insert_bdm, extract_bdm, - PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, - - /* The BD field in a B form instruction when the - modifier is used - and absolute address is used. */ -#define BDMA BDM + 1 - { 0xfffc, 0, insert_bdm, extract_bdm, - PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, - - /* The BD field in a B form instruction when the + modifier is used. - This sets the y bit of the BO field appropriately. */ -#define BDP BDMA + 1 - { 0xfffc, 0, insert_bdp, extract_bdp, - PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, - - /* The BD field in a B form instruction when the + modifier is used - and absolute addressing is used. */ -#define BDPA BDP + 1 - { 0xfffc, 0, insert_bdp, extract_bdp, - PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, - - /* The BF field in an X or XL form instruction. */ -#define BF BDPA + 1 - /* The CRFD field in an X form instruction. */ -#define CRFD BF - { 0x7, 23, NULL, NULL, PPC_OPERAND_CR }, - - /* The BF field in an X or XL form instruction. */ -#define BFF BF + 1 - { 0x7, 23, NULL, NULL, 0 }, - - /* An optional BF field. This is used for comparison instructions, - in which an omitted BF field is taken as zero. */ -#define OBF BFF + 1 - { 0x7, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, - - /* The BFA field in an X or XL form instruction. */ -#define BFA OBF + 1 - { 0x7, 18, NULL, NULL, PPC_OPERAND_CR }, - - /* The BO field in a B form instruction. Certain values are - illegal. */ -#define BO BFA + 1 -#define BO_MASK (0x1f << 21) - { 0x1f, 21, insert_bo, extract_bo, 0 }, - - /* The BO field in a B form instruction when the + or - modifier is - used. This is like the BO field, but it must be even. */ -#define BOE BO + 1 - { 0x1e, 21, insert_boe, extract_boe, 0 }, - -#define BH BOE + 1 - { 0x3, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The BT field in an X or XL form instruction. */ -#define BT BH + 1 - { 0x1f, 21, NULL, NULL, PPC_OPERAND_CR }, - - /* The condition register number portion of the BI field in a B form - or XL form instruction. This is used for the extended - conditional branch mnemonics, which set the lower two bits of the - BI field. This field is optional. */ -#define CR BT + 1 - { 0x7, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, - - /* The CRB field in an X form instruction. */ -#define CRB CR + 1 - /* The MB field in an M form instruction. */ -#define MB CRB -#define MB_MASK (0x1f << 6) - { 0x1f, 6, NULL, NULL, 0 }, - - /* The CRFS field in an X form instruction. */ -#define CRFS CRB + 1 - { 0x7, 0, NULL, NULL, PPC_OPERAND_CR }, - - /* The CT field in an X form instruction. */ -#define CT CRFS + 1 - /* The MO field in an mbar instruction. */ -#define MO CT - { 0x1f, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The D field in a D form instruction. This is a displacement off - a register, and implies that the next operand is a register in - parentheses. */ -#define D CT + 1 - { 0xffff, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, - - /* The DE field in a DE form instruction. This is like D, but is 12 - bits only. */ -#define DE D + 1 - { 0xfff, 4, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, - - /* The DES field in a DES form instruction. This is like DS, but is 14 - bits only (12 stored.) */ -#define DES DE + 1 - { 0x3ffc, 2, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, - - /* The DQ field in a DQ form instruction. This is like D, but the - lower four bits are forced to zero. */ -#define DQ DES + 1 - { 0xfff0, 0, NULL, NULL, - PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ }, - - /* The DS field in a DS form instruction. This is like D, but the - lower two bits are forced to zero. */ -#undef DS -#define DS DQ + 1 - { 0xfffc, 0, NULL, NULL, - PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS }, - - /* The E field in a wrteei instruction. */ -#define E DS + 1 - { 0x1, 15, NULL, NULL, 0 }, - - /* The FL1 field in a POWER SC form instruction. */ -#define FL1 E + 1 - /* The U field in an X form instruction. */ -#define U FL1 - { 0xf, 12, NULL, NULL, 0 }, - - /* The FL2 field in a POWER SC form instruction. */ -#define FL2 FL1 + 1 - { 0x7, 2, NULL, NULL, 0 }, - - /* The FLM field in an XFL form instruction. */ -#define FLM FL2 + 1 - { 0xff, 17, NULL, NULL, 0 }, - - /* The FRA field in an X or A form instruction. */ -#define FRA FLM + 1 -#define FRA_MASK (0x1f << 16) - { 0x1f, 16, NULL, NULL, PPC_OPERAND_FPR }, - - /* The FRB field in an X or A form instruction. */ -#define FRB FRA + 1 -#define FRB_MASK (0x1f << 11) - { 0x1f, 11, NULL, NULL, PPC_OPERAND_FPR }, - - /* The FRC field in an A form instruction. */ -#define FRC FRB + 1 -#define FRC_MASK (0x1f << 6) - { 0x1f, 6, NULL, NULL, PPC_OPERAND_FPR }, - - /* The FRS field in an X form instruction or the FRT field in a D, X - or A form instruction. */ -#define FRS FRC + 1 -#define FRT FRS - { 0x1f, 21, NULL, NULL, PPC_OPERAND_FPR }, - - /* The FXM field in an XFX instruction. */ -#define FXM FRS + 1 - { 0xff, 12, insert_fxm, extract_fxm, 0 }, - - /* Power4 version for mfcr. */ -#define FXM4 FXM + 1 - { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL }, - - /* The L field in a D or X form instruction. */ -#define L FXM4 + 1 - { 0x1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The LEV field in a POWER SVC form instruction. */ -#define SVC_LEV L + 1 - { 0x7f, 5, NULL, NULL, 0 }, - - /* The LEV field in an SC form instruction. */ -#define LEV SVC_LEV + 1 - { 0x7f, 5, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The LI field in an I form instruction. The lower two bits are - forced to zero. */ -#define LI LEV + 1 - { 0x3fffffc, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, - - /* The LI field in an I form instruction when used as an absolute - address. */ -#define LIA LI + 1 - { 0x3fffffc, 0, NULL, NULL, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, - - /* The LS field in an X (sync) form instruction. */ -#define LS LIA + 1 - { 0x3, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The ME field in an M form instruction. */ -#define ME LS + 1 -#define ME_MASK (0x1f << 1) - { 0x1f, 1, NULL, NULL, 0 }, - - /* The MB and ME fields in an M form instruction expressed a single - operand which is a bitmask indicating which bits to select. This - is a two operand form using PPC_OPERAND_NEXT. See the - description in opcode/ppc.h for what this means. */ -#define MBE ME + 1 - { 0x1f, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT }, - { -1, 0, insert_mbe, extract_mbe, 0 }, - - /* The MB or ME field in an MD or MDS form instruction. The high - bit is wrapped to the low end. */ -#define MB6 MBE + 2 -#define ME6 MB6 -#define MB6_MASK (0x3f << 5) - { 0x3f, 5, insert_mb6, extract_mb6, 0 }, - - /* The NB field in an X form instruction. The value 32 is stored as - 0. */ -#define NB MB6 + 1 - { 0x1f, 11, NULL, extract_nb, PPC_OPERAND_PLUS1 }, - - /* The NSI field in a D form instruction. This is the same as the - SI field, only negated. */ -#define NSI NB + 1 - { 0xffff, 0, insert_nsi, extract_nsi, - PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED }, - - /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction. */ -#define RA NSI + 1 -#define RA_MASK (0x1f << 16) - { 0x1f, 16, NULL, NULL, PPC_OPERAND_GPR }, - - /* As above, but 0 in the RA field means zero, not r0. */ -#define RA0 RA + 1 - { 0x1f, 16, NULL, NULL, PPC_OPERAND_GPR_0 }, - - /* The RA field in the DQ form lq instruction, which has special - value restrictions. */ -#define RAQ RA0 + 1 - { 0x1f, 16, insert_raq, NULL, PPC_OPERAND_GPR_0 }, - - /* The RA field in a D or X form instruction which is an updating - load, which means that the RA field may not be zero and may not - equal the RT field. */ -#define RAL RAQ + 1 - { 0x1f, 16, insert_ral, NULL, PPC_OPERAND_GPR_0 }, - - /* The RA field in an lmw instruction, which has special value - restrictions. */ -#define RAM RAL + 1 - { 0x1f, 16, insert_ram, NULL, PPC_OPERAND_GPR_0 }, - - /* The RA field in a D or X form instruction which is an updating - store or an updating floating point load, which means that the RA - field may not be zero. */ -#define RAS RAM + 1 - { 0x1f, 16, insert_ras, NULL, PPC_OPERAND_GPR_0 }, - - /* The RA field of the tlbwe instruction, which is optional. */ -#define RAOPT RAS + 1 - { 0x1f, 16, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }, - - /* The RB field in an X, XO, M, or MDS form instruction. */ -#define RB RAOPT + 1 -#define RB_MASK (0x1f << 11) - { 0x1f, 11, NULL, NULL, PPC_OPERAND_GPR }, - - /* The RB field in an X form instruction when it must be the same as - the RS field in the instruction. This is used for extended - mnemonics like mr. */ -#define RBS RB + 1 - { 0x1f, 11, insert_rbs, extract_rbs, PPC_OPERAND_FAKE }, - - /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form - instruction or the RT field in a D, DS, X, XFX or XO form - instruction. */ -#define RS RBS + 1 -#define RT RS -#define RT_MASK (0x1f << 21) - { 0x1f, 21, NULL, NULL, PPC_OPERAND_GPR }, - - /* The RS and RT fields of the DS form stq instruction, which have - special value restrictions. */ -#define RSQ RS + 1 -#define RTQ RSQ - { 0x1e, 21, NULL, NULL, PPC_OPERAND_GPR_0 }, - - /* The RS field of the tlbwe instruction, which is optional. */ -#define RSO RSQ + 1 -#define RTO RSO - { 0x1f, 21, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }, - - /* The SH field in an X or M form instruction. */ -#define SH RSO + 1 -#define SH_MASK (0x1f << 11) - /* The other UIMM field in a EVX form instruction. */ -#define EVUIMM SH - { 0x1f, 11, NULL, NULL, 0 }, - - /* The SH field in an MD form instruction. This is split. */ -#define SH6 SH + 1 -#define SH6_MASK ((0x1f << 11) | (1 << 1)) - { 0x3f, -1, insert_sh6, extract_sh6, 0 }, - - /* The SH field of the tlbwe instruction, which is optional. */ -#define SHO SH6 + 1 - { 0x1f, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The SI field in a D form instruction. */ -#define SI SHO + 1 - { 0xffff, 0, NULL, NULL, PPC_OPERAND_SIGNED }, - - /* The SI field in a D form instruction when we accept a wide range - of positive values. */ -#define SISIGNOPT SI + 1 - { 0xffff, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT }, - - /* The SPR field in an XFX form instruction. This is flipped--the - lower 5 bits are stored in the upper 5 and vice- versa. */ -#define SPR SISIGNOPT + 1 -#define PMR SPR -#define SPR_MASK (0x3ff << 11) - { 0x3ff, 11, insert_spr, extract_spr, 0 }, - - /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */ -#define SPRBAT SPR + 1 -#define SPRBAT_MASK (0x3 << 17) - { 0x3, 17, NULL, NULL, 0 }, - - /* The SPRG register number in an XFX form m[ft]sprg instruction. */ -#define SPRG SPRBAT + 1 - { 0x1f, 16, insert_sprg, extract_sprg, 0 }, - - /* The SR field in an X form instruction. */ -#define SR SPRG + 1 - { 0xf, 16, NULL, NULL, 0 }, - - /* The STRM field in an X AltiVec form instruction. */ -#define STRM SR + 1 - { 0x3, 21, NULL, NULL, 0 }, - - /* The SV field in a POWER SC form instruction. */ -#define SV STRM + 1 - { 0x3fff, 2, NULL, NULL, 0 }, - - /* The TBR field in an XFX form instruction. This is like the SPR - field, but it is optional. */ -#define TBR SV + 1 - { 0x3ff, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL }, - - /* The TO field in a D or X form instruction. */ -#define TO TBR + 1 -#define TO_MASK (0x1f << 21) - { 0x1f, 21, NULL, NULL, 0 }, - - /* The UI field in a D form instruction. */ -#define UI TO + 1 - { 0xffff, 0, NULL, NULL, 0 }, - - /* The VA field in a VA, VX or VXR form instruction. */ -#define VA UI + 1 - { 0x1f, 16, NULL, NULL, PPC_OPERAND_VR }, - - /* The VB field in a VA, VX or VXR form instruction. */ -#define VB VA + 1 - { 0x1f, 11, NULL, NULL, PPC_OPERAND_VR }, - - /* The VC field in a VA form instruction. */ -#define VC VB + 1 - { 0x1f, 6, NULL, NULL, PPC_OPERAND_VR }, - - /* The VD or VS field in a VA, VX, VXR or X form instruction. */ -#define VD VC + 1 -#define VS VD - { 0x1f, 21, NULL, NULL, PPC_OPERAND_VR }, - - /* The SIMM field in a VX form instruction. */ -#define SIMM VD + 1 - { 0x1f, 16, NULL, NULL, PPC_OPERAND_SIGNED}, - - /* The UIMM field in a VX form instruction, and TE in Z form. */ -#define UIMM SIMM + 1 -#define TE UIMM - { 0x1f, 16, NULL, NULL, 0 }, - - /* The SHB field in a VA form instruction. */ -#define SHB UIMM + 1 - { 0xf, 6, NULL, NULL, 0 }, - - /* The other UIMM field in a half word EVX form instruction. */ -#define EVUIMM_2 SHB + 1 - { 0x3e, 10, NULL, NULL, PPC_OPERAND_PARENS }, - - /* The other UIMM field in a word EVX form instruction. */ -#define EVUIMM_4 EVUIMM_2 + 1 - { 0x7c, 9, NULL, NULL, PPC_OPERAND_PARENS }, - - /* The other UIMM field in a double EVX form instruction. */ -#define EVUIMM_8 EVUIMM_4 + 1 - { 0xf8, 8, NULL, NULL, PPC_OPERAND_PARENS }, - - /* The WS field. */ -#define WS EVUIMM_8 + 1 - { 0x7, 11, NULL, NULL, 0 }, - - /* The L field in an mtmsrd or A form instruction or W in an X form. */ -#define A_L WS + 1 -#define W A_L - { 0x1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, - -#define RMC A_L + 1 - { 0x3, 9, NULL, NULL, 0 }, - -#define R RMC + 1 - { 0x1, 16, NULL, NULL, 0 }, - -#define SP R + 1 - { 0x3, 19, NULL, NULL, 0 }, - -#define S SP + 1 - { 0x1, 20, NULL, NULL, 0 }, - - /* SH field starting at bit position 16. */ -#define SH16 S + 1 - /* The DCM and DGM fields in a Z form instruction. */ -#define DCM SH16 -#define DGM DCM - { 0x3f, 10, NULL, NULL, 0 }, - - /* The EH field in larx instruction. */ -#define EH SH16 + 1 - { 0x1, 0, NULL, NULL, PPC_OPERAND_OPTIONAL }, - - /* The L field in an mtfsf or XFL form instruction. */ -#define XFL_L EH + 1 - { 0x1, 25, NULL, NULL, PPC_OPERAND_OPTIONAL}, -}; - -const unsigned int num_powerpc_operands = (sizeof (powerpc_operands) - / sizeof (powerpc_operands[0])); - -/* The functions used to insert and extract complicated operands. */ - -/* The BA field in an XL form instruction when it must be the same as - the BT field in the same instruction. This operand is marked FAKE. - The insertion function just copies the BT field into the BA field, - and the extraction function just checks that the fields are the - same. */ - -static unsigned long -insert_bat (unsigned long insn, - long value ATTRIBUTE_UNUSED, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | (((insn >> 21) & 0x1f) << 16); -} - -static long -extract_bat (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - if (((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) - *invalid = 1; - return 0; -} - -/* The BB field in an XL form instruction when it must be the same as - the BA field in the same instruction. This operand is marked FAKE. - The insertion function just copies the BA field into the BB field, - and the extraction function just checks that the fields are the - same. */ - -static unsigned long -insert_bba (unsigned long insn, - long value ATTRIBUTE_UNUSED, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | (((insn >> 16) & 0x1f) << 11); -} - -static long -extract_bba (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - if (((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f)) - *invalid = 1; - return 0; -} - -/* The BD field in a B form instruction when the - modifier is used. - This modifier means that the branch is not expected to be taken. - For chips built to versions of the architecture prior to version 2 - (ie. not Power4 compatible), we set the y bit of the BO field to 1 - if the offset is negative. When extracting, we require that the y - bit be 1 and that the offset be positive, since if the y bit is 0 - we just want to print the normal form of the instruction. - Power4 compatible targets use two bits, "a", and "t", instead of - the "y" bit. "at" == 00 => no hint, "at" == 01 => unpredictable, - "at" == 10 => not taken, "at" == 11 => taken. The "t" bit is 00001 - in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000 - for branch on CTR. We only handle the taken/not-taken hint here. - Note that we don't relax the conditions tested here when - disassembling with -Many because insns using extract_bdm and - extract_bdp always occur in pairs. One or the other will always - be valid. */ - -static unsigned long -insert_bdm (unsigned long insn, - long value, - int dialect, - const char **errmsg ATTRIBUTE_UNUSED) -{ - if ((dialect & PPC_OPCODE_POWER4) == 0) - { - if ((value & 0x8000) != 0) - insn |= 1 << 21; - } - else - { - if ((insn & (0x14 << 21)) == (0x04 << 21)) - insn |= 0x02 << 21; - else if ((insn & (0x14 << 21)) == (0x10 << 21)) - insn |= 0x08 << 21; - } - return insn | (value & 0xfffc); -} - -static long -extract_bdm (unsigned long insn, - int dialect, - int *invalid) -{ - if ((dialect & PPC_OPCODE_POWER4) == 0) - { - if (((insn & (1 << 21)) == 0) != ((insn & (1 << 15)) == 0)) - *invalid = 1; - } - else - { - if ((insn & (0x17 << 21)) != (0x06 << 21) - && (insn & (0x1d << 21)) != (0x18 << 21)) - *invalid = 1; - } - - return ((insn & 0xfffc) ^ 0x8000) - 0x8000; -} - -/* The BD field in a B form instruction when the + modifier is used. - This is like BDM, above, except that the branch is expected to be - taken. */ - -static unsigned long -insert_bdp (unsigned long insn, - long value, - int dialect, - const char **errmsg ATTRIBUTE_UNUSED) -{ - if ((dialect & PPC_OPCODE_POWER4) == 0) - { - if ((value & 0x8000) == 0) - insn |= 1 << 21; - } - else - { - if ((insn & (0x14 << 21)) == (0x04 << 21)) - insn |= 0x03 << 21; - else if ((insn & (0x14 << 21)) == (0x10 << 21)) - insn |= 0x09 << 21; - } - return insn | (value & 0xfffc); -} - -static long -extract_bdp (unsigned long insn, - int dialect, - int *invalid) -{ - if ((dialect & PPC_OPCODE_POWER4) == 0) - { - if (((insn & (1 << 21)) == 0) == ((insn & (1 << 15)) == 0)) - *invalid = 1; - } - else - { - if ((insn & (0x17 << 21)) != (0x07 << 21) - && (insn & (0x1d << 21)) != (0x19 << 21)) - *invalid = 1; - } - - return ((insn & 0xfffc) ^ 0x8000) - 0x8000; -} - -/* Check for legal values of a BO field. */ - -static int -valid_bo (long value, int dialect, int extract) -{ - if ((dialect & PPC_OPCODE_POWER4) == 0) - { - int valid; - /* Certain encodings have bits that are required to be zero. - These are (z must be zero, y may be anything): - 001zy - 011zy - 1z00y - 1z01y - 1z1zz - */ - switch (value & 0x14) - { - default: - case 0: - valid = 1; - break; - case 0x4: - valid = (value & 0x2) == 0; - break; - case 0x10: - valid = (value & 0x8) == 0; - break; - case 0x14: - valid = value == 0x14; - break; - } - /* When disassembling with -Many, accept power4 encodings too. */ - if (valid - || (dialect & PPC_OPCODE_ANY) == 0 - || !extract) - return valid; - } - - /* Certain encodings have bits that are required to be zero. - These are (z must be zero, a & t may be anything): - 0000z - 0001z - 0100z - 0101z - 001at - 011at - 1a00t - 1a01t - 1z1zz - */ - if ((value & 0x14) == 0) - return (value & 0x1) == 0; - else if ((value & 0x14) == 0x14) - return value == 0x14; - else - return 1; -} - -/* The BO field in a B form instruction. Warn about attempts to set - the field to an illegal value. */ - -static unsigned long -insert_bo (unsigned long insn, - long value, - int dialect, - const char **errmsg) -{ - if (!valid_bo (value, dialect, 0)) - *errmsg = _("invalid conditional option"); - return insn | ((value & 0x1f) << 21); -} - -static long -extract_bo (unsigned long insn, - int dialect, - int *invalid) -{ - long value; - - value = (insn >> 21) & 0x1f; - if (!valid_bo (value, dialect, 1)) - *invalid = 1; - return value; -} - -/* The BO field in a B form instruction when the + or - modifier is - used. This is like the BO field, but it must be even. When - extracting it, we force it to be even. */ - -static unsigned long -insert_boe (unsigned long insn, - long value, - int dialect, - const char **errmsg) -{ - if (!valid_bo (value, dialect, 0)) - *errmsg = _("invalid conditional option"); - else if ((value & 1) != 0) - *errmsg = _("attempt to set y bit when using + or - modifier"); - - return insn | ((value & 0x1f) << 21); -} - -static long -extract_boe (unsigned long insn, - int dialect, - int *invalid) -{ - long value; - - value = (insn >> 21) & 0x1f; - if (!valid_bo (value, dialect, 1)) - *invalid = 1; - return value & 0x1e; -} - -/* FXM mask in mfcr and mtcrf instructions. */ - -static unsigned long -insert_fxm (unsigned long insn, - long value, - int dialect, - const char **errmsg) -{ - /* If we're handling the mfocrf and mtocrf insns ensure that exactly - one bit of the mask field is set. */ - if ((insn & (1 << 20)) != 0) - { - if (value == 0 || (value & -value) != value) - { - *errmsg = _("invalid mask field"); - value = 0; - } - } - - /* If the optional field on mfcr is missing that means we want to use - the old form of the instruction that moves the whole cr. In that - case we'll have VALUE zero. There doesn't seem to be a way to - distinguish this from the case where someone writes mfcr %r3,0. */ - else if (value == 0) - ; - - /* If only one bit of the FXM field is set, we can use the new form - of the instruction, which is faster. Unlike the Power4 branch hint - encoding, this is not backward compatible. Do not generate the - new form unless -mpower4 has been given, or -many and the two - operand form of mfcr was used. */ - else if ((value & -value) == value - && ((dialect & PPC_OPCODE_POWER4) != 0 - || ((dialect & PPC_OPCODE_ANY) != 0 - && (insn & (0x3ff << 1)) == 19 << 1))) - insn |= 1 << 20; - - /* Any other value on mfcr is an error. */ - else if ((insn & (0x3ff << 1)) == 19 << 1) - { - *errmsg = _("ignoring invalid mfcr mask"); - value = 0; - } - - return insn | ((value & 0xff) << 12); -} - -static long -extract_fxm (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - long mask = (insn >> 12) & 0xff; - - /* Is this a Power4 insn? */ - if ((insn & (1 << 20)) != 0) - { - /* Exactly one bit of MASK should be set. */ - if (mask == 0 || (mask & -mask) != mask) - *invalid = 1; - } - - /* Check that non-power4 form of mfcr has a zero MASK. */ - else if ((insn & (0x3ff << 1)) == 19 << 1) - { - if (mask != 0) - *invalid = 1; - } - - return mask; -} - -/* The MB and ME fields in an M form instruction expressed as a single - operand which is itself a bitmask. The extraction function always - marks it as invalid, since we never want to recognize an - instruction which uses a field of this type. */ - -static unsigned long -insert_mbe (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - unsigned long uval, mask; - int mb, me, mx, count, last; - - uval = value; - - if (uval == 0) - { - *errmsg = _("illegal bitmask"); - return insn; - } - - mb = 0; - me = 32; - if ((uval & 1) != 0) - last = 1; - else - last = 0; - count = 0; - - /* mb: location of last 0->1 transition */ - /* me: location of last 1->0 transition */ - /* count: # transitions */ - - for (mx = 0, mask = 1L << 31; mx < 32; ++mx, mask >>= 1) - { - if ((uval & mask) && !last) - { - ++count; - mb = mx; - last = 1; - } - else if (!(uval & mask) && last) - { - ++count; - me = mx; - last = 0; - } - } - if (me == 0) - me = 32; - - if (count != 2 && (count != 0 || ! last)) - *errmsg = _("illegal bitmask"); - - return insn | (mb << 6) | ((me - 1) << 1); -} - -static long -extract_mbe (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - long ret; - int mb, me; - int i; - - *invalid = 1; - - mb = (insn >> 6) & 0x1f; - me = (insn >> 1) & 0x1f; - if (mb < me + 1) - { - ret = 0; - for (i = mb; i <= me; i++) - ret |= 1L << (31 - i); - } - else if (mb == me + 1) - ret = ~0; - else /* (mb > me + 1) */ - { - ret = ~0; - for (i = me + 1; i < mb; i++) - ret &= ~(1L << (31 - i)); - } - return ret; -} - -/* The MB or ME field in an MD or MDS form instruction. The high bit - is wrapped to the low end. */ - -static unsigned long -insert_mb6 (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | ((value & 0x1f) << 6) | (value & 0x20); -} - -static long -extract_mb6 (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid ATTRIBUTE_UNUSED) -{ - return ((insn >> 6) & 0x1f) | (insn & 0x20); -} - -/* The NB field in an X form instruction. The value 32 is stored as - 0. */ - -static long -extract_nb (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid ATTRIBUTE_UNUSED) -{ - long ret; - - ret = (insn >> 11) & 0x1f; - if (ret == 0) - ret = 32; - return ret; -} - -/* The NSI field in a D form instruction. This is the same as the SI - field, only negated. The extraction function always marks it as - invalid, since we never want to recognize an instruction which uses - a field of this type. */ - -static unsigned long -insert_nsi (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | (-value & 0xffff); -} - -static long -extract_nsi (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - *invalid = 1; - return -(((insn & 0xffff) ^ 0x8000) - 0x8000); -} - -/* The RA field in a D or X form instruction which is an updating - load, which means that the RA field may not be zero and may not - equal the RT field. */ - -static unsigned long -insert_ral (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - if (value == 0 - || (unsigned long) value == ((insn >> 21) & 0x1f)) - *errmsg = "invalid register operand when updating"; - return insn | ((value & 0x1f) << 16); -} - -/* The RA field in an lmw instruction, which has special value - restrictions. */ - -static unsigned long -insert_ram (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - if ((unsigned long) value >= ((insn >> 21) & 0x1f)) - *errmsg = _("index register in load range"); - return insn | ((value & 0x1f) << 16); -} - -/* The RA field in the DQ form lq instruction, which has special - value restrictions. */ - -static unsigned long -insert_raq (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - long rtvalue = (insn & RT_MASK) >> 21; - - if (value == rtvalue) - *errmsg = _("source and target register operands must be different"); - return insn | ((value & 0x1f) << 16); -} - -/* The RA field in a D or X form instruction which is an updating - store or an updating floating point load, which means that the RA - field may not be zero. */ - -static unsigned long -insert_ras (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg) -{ - if (value == 0) - *errmsg = _("invalid register operand when updating"); - return insn | ((value & 0x1f) << 16); -} - -/* The RB field in an X form instruction when it must be the same as - the RS field in the instruction. This is used for extended - mnemonics like mr. This operand is marked FAKE. The insertion - function just copies the BT field into the BA field, and the - extraction function just checks that the fields are the same. */ - -static unsigned long -insert_rbs (unsigned long insn, - long value ATTRIBUTE_UNUSED, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | (((insn >> 21) & 0x1f) << 11); -} - -static long -extract_rbs (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid) -{ - if (((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f)) - *invalid = 1; - return 0; -} - -/* The SH field in an MD form instruction. This is split. */ - -static unsigned long -insert_sh6 (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); -} - -static long -extract_sh6 (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid ATTRIBUTE_UNUSED) -{ - return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20); -} - -/* The SPR field in an XFX form instruction. This is flipped--the - lower 5 bits are stored in the upper 5 and vice- versa. */ - -static unsigned long -insert_spr (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); -} - -static long -extract_spr (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid ATTRIBUTE_UNUSED) -{ - return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); -} - -/* Some dialects have 8 SPRG registers instead of the standard 4. */ - -static unsigned long -insert_sprg (unsigned long insn, - long value, - int dialect, - const char **errmsg) -{ - /* This check uses PPC_OPCODE_403 because PPC405 is later defined - as a synonym. If ever a 405 specific dialect is added this - check should use that instead. */ - if (value > 7 - || (value > 3 - && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0)) - *errmsg = _("invalid sprg number"); - - /* If this is mfsprg4..7 then use spr 260..263 which can be read in - user mode. Anything else must use spr 272..279. */ - if (value <= 3 || (insn & 0x100) != 0) - value |= 0x10; - - return insn | ((value & 0x17) << 16); -} - -static long -extract_sprg (unsigned long insn, - int dialect, - int *invalid) -{ - unsigned long val = (insn >> 16) & 0x1f; - - /* mfsprg can use 260..263 and 272..279. mtsprg only uses spr 272..279 - If not BOOKE or 405, then both use only 272..275. */ - if (val <= 3 - || (val < 0x10 && (insn & 0x100) != 0) - || (val - 0x10 > 3 - && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0)) - *invalid = 1; - return val & 7; -} - -/* The TBR field in an XFX instruction. This is just like SPR, but it - is optional. When TBR is omitted, it must be inserted as 268 (the - magic number of the TB register). These functions treat 0 - (indicating an omitted optional operand) as 268. This means that - ``mftb 4,0'' is not handled correctly. This does not matter very - much, since the architecture manual does not define mftb as - accepting any values other than 268 or 269. */ - -#define TB (268) - -static unsigned long -insert_tbr (unsigned long insn, - long value, - int dialect ATTRIBUTE_UNUSED, - const char **errmsg ATTRIBUTE_UNUSED) -{ - if (value == 0) - value = TB; - return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); -} - -static long -extract_tbr (unsigned long insn, - int dialect ATTRIBUTE_UNUSED, - int *invalid ATTRIBUTE_UNUSED) -{ - long ret; - - ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); - if (ret == TB) - ret = 0; - return ret; -} - -/* Macros used to form opcodes. */ - -/* The main opcode. */ -#define OP(x) ((((unsigned long)(x)) & 0x3f) << 26) -#define OP_MASK OP (0x3f) - -/* The main opcode combined with a trap code in the TO field of a D - form instruction. Used for extended mnemonics for the trap - instructions. */ -#define OPTO(x,to) (OP (x) | ((((unsigned long)(to)) & 0x1f) << 21)) -#define OPTO_MASK (OP_MASK | TO_MASK) - -/* The main opcode combined with a comparison size bit in the L field - of a D form or X form instruction. Used for extended mnemonics for - the comparison instructions. */ -#define OPL(x,l) (OP (x) | ((((unsigned long)(l)) & 1) << 21)) -#define OPL_MASK OPL (0x3f,1) - -/* An A form instruction. */ -#define A(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1) | (((unsigned long)(rc)) & 1)) -#define A_MASK A (0x3f, 0x1f, 1) - -/* An A_MASK with the FRB field fixed. */ -#define AFRB_MASK (A_MASK | FRB_MASK) - -/* An A_MASK with the FRC field fixed. */ -#define AFRC_MASK (A_MASK | FRC_MASK) - -/* An A_MASK with the FRA and FRC fields fixed. */ -#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK) - -/* An AFRAFRC_MASK, but with L bit clear. */ -#define AFRALFRC_MASK (AFRAFRC_MASK & ~((unsigned long) 1 << 16)) - -/* A B form instruction. */ -#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1)) -#define B_MASK B (0x3f, 1, 1) - -/* A B form instruction setting the BO field. */ -#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21)) -#define BBO_MASK BBO (0x3f, 0x1f, 1, 1) - -/* A BBO_MASK with the y bit of the BO field removed. This permits - matching a conditional branch regardless of the setting of the y - bit. Similarly for the 'at' bits used for power4 branch hints. */ -#define Y_MASK (((unsigned long) 1) << 21) -#define AT1_MASK (((unsigned long) 3) << 21) -#define AT2_MASK (((unsigned long) 9) << 21) -#define BBOY_MASK (BBO_MASK &~ Y_MASK) -#define BBOAT_MASK (BBO_MASK &~ AT1_MASK) - -/* A B form instruction setting the BO field and the condition bits of - the BI field. */ -#define BBOCB(op, bo, cb, aa, lk) \ - (BBO ((op), (bo), (aa), (lk)) | ((((unsigned long)(cb)) & 0x3) << 16)) -#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1) - -/* A BBOCB_MASK with the y bit of the BO field removed. */ -#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK) -#define BBOATCB_MASK (BBOCB_MASK &~ AT1_MASK) -#define BBOAT2CB_MASK (BBOCB_MASK &~ AT2_MASK) - -/* A BBOYCB_MASK in which the BI field is fixed. */ -#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK) -#define BBOATBI_MASK (BBOAT2CB_MASK | BI_MASK) - -/* An Context form instruction. */ -#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7)) -#define CTX_MASK CTX(0x3f, 0x7) - -/* An User Context form instruction. */ -#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) -#define UCTX_MASK UCTX(0x3f, 0x1f) - -/* The main opcode mask with the RA field clear. */ -#define DRA_MASK (OP_MASK | RA_MASK) - -/* A DS form instruction. */ -#define DSO(op, xop) (OP (op) | ((xop) & 0x3)) -#define DS_MASK DSO (0x3f, 3) - -/* A DE form instruction. */ -#define DEO(op, xop) (OP (op) | ((xop) & 0xf)) -#define DE_MASK DEO (0x3e, 0xf) - -/* An EVSEL form instruction. */ -#define EVSEL(op, xop) (OP (op) | (((unsigned long)(xop)) & 0xff) << 3) -#define EVSEL_MASK EVSEL(0x3f, 0xff) - -/* An M form instruction. */ -#define M(op, rc) (OP (op) | ((rc) & 1)) -#define M_MASK M (0x3f, 1) - -/* An M form instruction with the ME field specified. */ -#define MME(op, me, rc) (M ((op), (rc)) | ((((unsigned long)(me)) & 0x1f) << 1)) - -/* An M_MASK with the MB and ME fields fixed. */ -#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK) - -/* An M_MASK with the SH and ME fields fixed. */ -#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK) - -/* An MD form instruction. */ -#define MD(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x7) << 2) | ((rc) & 1)) -#define MD_MASK MD (0x3f, 0x7, 1) - -/* An MD_MASK with the MB field fixed. */ -#define MDMB_MASK (MD_MASK | MB6_MASK) - -/* An MD_MASK with the SH field fixed. */ -#define MDSH_MASK (MD_MASK | SH6_MASK) - -/* An MDS form instruction. */ -#define MDS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0xf) << 1) | ((rc) & 1)) -#define MDS_MASK MDS (0x3f, 0xf, 1) - -/* An MDS_MASK with the MB field fixed. */ -#define MDSMB_MASK (MDS_MASK | MB6_MASK) - -/* An SC form instruction. */ -#define SC(op, sa, lk) (OP (op) | ((((unsigned long)(sa)) & 1) << 1) | ((lk) & 1)) -#define SC_MASK (OP_MASK | (((unsigned long)0x3ff) << 16) | (((unsigned long)1) << 1) | 1) - -/* An VX form instruction. */ -#define VX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7ff)) - -/* The mask for an VX form instruction. */ -#define VX_MASK VX(0x3f, 0x7ff) - -/* An VA form instruction. */ -#define VXA(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x03f)) - -/* The mask for an VA form instruction. */ -#define VXA_MASK VXA(0x3f, 0x3f) - -/* An VXR form instruction. */ -#define VXR(op, xop, rc) (OP (op) | (((rc) & 1) << 10) | (((unsigned long)(xop)) & 0x3ff)) - -/* The mask for a VXR form instruction. */ -#define VXR_MASK VXR(0x3f, 0x3ff, 1) - -/* An X form instruction. */ -#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) - -/* A Z form instruction. */ -#define Z(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1)) - -/* An X form instruction with the RC bit specified. */ -#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1)) - -/* A Z form instruction with the RC bit specified. */ -#define ZRC(op, xop, rc) (Z ((op), (xop)) | ((rc) & 1)) - -/* The mask for an X form instruction. */ -#define X_MASK XRC (0x3f, 0x3ff, 1) - -/* The mask for a Z form instruction. */ -#define Z_MASK ZRC (0x3f, 0x1ff, 1) -#define Z2_MASK ZRC (0x3f, 0xff, 1) - -/* An X_MASK with the RA field fixed. */ -#define XRA_MASK (X_MASK | RA_MASK) - -/* An XRA_MASK with the W field clear. */ -#define XWRA_MASK (XRA_MASK & ~((unsigned long) 1 << 16)) - -/* An X_MASK with the RB field fixed. */ -#define XRB_MASK (X_MASK | RB_MASK) - -/* An X_MASK with the RT field fixed. */ -#define XRT_MASK (X_MASK | RT_MASK) - -/* An XRT_MASK mask with the L bits clear. */ -#define XLRT_MASK (XRT_MASK & ~((unsigned long) 0x3 << 21)) - -/* An X_MASK with the RA and RB fields fixed. */ -#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK) - -/* An XRARB_MASK, but with the L bit clear. */ -#define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16)) - -/* An X_MASK with the RT and RA fields fixed. */ -#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK) - -/* An XRTRA_MASK, but with L bit clear. */ -#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21)) - -/* An X form instruction with the L bit specified. */ -#define XOPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21)) - -/* The mask for an X form comparison instruction. */ -#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22)) - -/* The mask for an X form comparison instruction with the L field - fixed. */ -#define XCMPL_MASK (XCMP_MASK | (((unsigned long)1) << 21)) - -/* An X form trap instruction with the TO field specified. */ -#define XTO(op, xop, to) (X ((op), (xop)) | ((((unsigned long)(to)) & 0x1f) << 21)) -#define XTO_MASK (X_MASK | TO_MASK) - -/* An X form tlb instruction with the SH field specified. */ -#define XTLB(op, xop, sh) (X ((op), (xop)) | ((((unsigned long)(sh)) & 0x1f) << 11)) -#define XTLB_MASK (X_MASK | SH_MASK) - -/* An X form sync instruction. */ -#define XSYNC(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 3) << 21)) - -/* An X form sync instruction with everything filled in except the LS field. */ -#define XSYNC_MASK (0xff9fffff) - -/* An X_MASK, but with the EH bit clear. */ -#define XEH_MASK (X_MASK & ~((unsigned long )1)) - -/* An X form AltiVec dss instruction. */ -#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25)) -#define XDSS_MASK XDSS(0x3f, 0x3ff, 1) - -/* An XFL form instruction. */ -#define XFL(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1) | (((unsigned long)(rc)) & 1)) -#define XFL_MASK XFL (0x3f, 0x3ff, 1) - -/* An X form isel instruction. */ -#define XISEL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1)) -#define XISEL_MASK XISEL(0x3f, 0x1f) - -/* An XL form instruction with the LK field set to 0. */ -#define XL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) - -/* An XL form instruction which uses the LK field. */ -#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1)) - -/* The mask for an XL form instruction. */ -#define XL_MASK XLLK (0x3f, 0x3ff, 1) - -/* An XL form instruction which explicitly sets the BO field. */ -#define XLO(op, bo, xop, lk) \ - (XLLK ((op), (xop), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21)) -#define XLO_MASK (XL_MASK | BO_MASK) - -/* An XL form instruction which explicitly sets the y bit of the BO - field. */ -#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | ((((unsigned long)(y)) & 1) << 21)) -#define XLYLK_MASK (XL_MASK | Y_MASK) - -/* An XL form instruction which sets the BO field and the condition - bits of the BI field. */ -#define XLOCB(op, bo, cb, xop, lk) \ - (XLO ((op), (bo), (xop), (lk)) | ((((unsigned long)(cb)) & 3) << 16)) -#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1) - -/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed. */ -#define XLBB_MASK (XL_MASK | BB_MASK) -#define XLYBB_MASK (XLYLK_MASK | BB_MASK) -#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK) - -/* A mask for branch instructions using the BH field. */ -#define XLBH_MASK (XL_MASK | (0x1c << 11)) - -/* An XL_MASK with the BO and BB fields fixed. */ -#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK) - -/* An XL_MASK with the BO, BI and BB fields fixed. */ -#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK) - -/* An XO form instruction. */ -#define XO(op, xop, oe, rc) \ - (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1) | ((((unsigned long)(oe)) & 1) << 10) | (((unsigned long)(rc)) & 1)) -#define XO_MASK XO (0x3f, 0x1ff, 1, 1) - -/* An XO_MASK with the RB field fixed. */ -#define XORB_MASK (XO_MASK | RB_MASK) - -/* An XS form instruction. */ -#define XS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 2) | (((unsigned long)(rc)) & 1)) -#define XS_MASK XS (0x3f, 0x1ff, 1) - -/* A mask for the FXM version of an XFX form instruction. */ -#define XFXFXM_MASK (X_MASK | (1 << 11) | (1 << 20)) - -/* An XFX form instruction with the FXM field filled in. */ -#define XFXM(op, xop, fxm, p4) \ - (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12) \ - | ((unsigned long)(p4) << 20)) - -/* An XFX form instruction with the SPR field filled in. */ -#define XSPR(op, xop, spr) \ - (X ((op), (xop)) | ((((unsigned long)(spr)) & 0x1f) << 16) | ((((unsigned long)(spr)) & 0x3e0) << 6)) -#define XSPR_MASK (X_MASK | SPR_MASK) - -/* An XFX form instruction with the SPR field filled in except for the - SPRBAT field. */ -#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK) - -/* An XFX form instruction with the SPR field filled in except for the - SPRG field. */ -#define XSPRG_MASK (XSPR_MASK & ~(0x1f << 16)) - -/* An X form instruction with everything filled in except the E field. */ -#define XE_MASK (0xffff7fff) - -/* An X form user context instruction. */ -#define XUC(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) -#define XUC_MASK XUC(0x3f, 0x1f) - -/* The BO encodings used in extended conditional branch mnemonics. */ -#define BODNZF (0x0) -#define BODNZFP (0x1) -#define BODZF (0x2) -#define BODZFP (0x3) -#define BODNZT (0x8) -#define BODNZTP (0x9) -#define BODZT (0xa) -#define BODZTP (0xb) - -#define BOF (0x4) -#define BOFP (0x5) -#define BOFM4 (0x6) -#define BOFP4 (0x7) -#define BOT (0xc) -#define BOTP (0xd) -#define BOTM4 (0xe) -#define BOTP4 (0xf) - -#define BODNZ (0x10) -#define BODNZP (0x11) -#define BODZ (0x12) -#define BODZP (0x13) -#define BODNZM4 (0x18) -#define BODNZP4 (0x19) -#define BODZM4 (0x1a) -#define BODZP4 (0x1b) - -#define BOU (0x14) - -/* The BI condition bit encodings used in extended conditional branch - mnemonics. */ -#define CBLT (0) -#define CBGT (1) -#define CBEQ (2) -#define CBSO (3) - -/* The TO encodings used in extended trap mnemonics. */ -#define TOLGT (0x1) -#define TOLLT (0x2) -#define TOEQ (0x4) -#define TOLGE (0x5) -#define TOLNL (0x5) -#define TOLLE (0x6) -#define TOLNG (0x6) -#define TOGT (0x8) -#define TOGE (0xc) -#define TONL (0xc) -#define TOLT (0x10) -#define TOLE (0x14) -#define TONG (0x14) -#define TONE (0x18) -#define TOU (0x1f) - -/* Smaller names for the flags so each entry in the opcodes table will - fit on a single line. */ -#undef PPC -#define PPC PPC_OPCODE_PPC -#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON -#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM -#define POWER4 PPC_OPCODE_POWER4 -#define POWER5 PPC_OPCODE_POWER5 -#define POWER6 PPC_OPCODE_POWER6 -#define CELL PPC_OPCODE_CELL -#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC -#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC -#define PPC403 PPC_OPCODE_403 -#define PPC405 PPC403 -#define PPC440 PPC_OPCODE_440 -#define PPC750 PPC -#define PPC860 PPC -#define PPCVEC PPC_OPCODE_ALTIVEC -#define POWER PPC_OPCODE_POWER -#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 -#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2 -#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_32 -#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON -#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_32 -#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601 -#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON -#define MFDEC1 PPC_OPCODE_POWER -#define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE -#define BOOKE PPC_OPCODE_BOOKE -#define BOOKE64 PPC_OPCODE_BOOKE64 -#define CLASSIC PPC_OPCODE_CLASSIC -#define PPCE300 PPC_OPCODE_E300 -#define PPCSPE PPC_OPCODE_SPE -#define PPCISEL PPC_OPCODE_ISEL -#define PPCEFS PPC_OPCODE_EFS -#define PPCBRLK PPC_OPCODE_BRLOCK -#define PPCPMR PPC_OPCODE_PMR -#define PPCCHLK PPC_OPCODE_CACHELCK -#define PPCCHLK64 PPC_OPCODE_CACHELCK | PPC_OPCODE_BOOKE64 -#define PPCRFMCI PPC_OPCODE_RFMCI - -/* The opcode table. - - The format of the opcode table is: - - NAME OPCODE MASK FLAGS { OPERANDS } - - NAME is the name of the instruction. - OPCODE is the instruction opcode. - MASK is the opcode mask; this is used to tell the disassembler - which bits in the actual opcode must match OPCODE. - FLAGS are flags indicated what processors support the instruction. - OPERANDS is the list of operands. - - The disassembler reads the table in order and prints the first - instruction which matches, so this table is sorted to put more - specific instructions before more general instructions. It is also - sorted by major opcode. */ - -const struct powerpc_opcode powerpc_opcodes[] = { -{ "attn", X(0,256), X_MASK, POWER4, { 0 } }, -{ "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdlgei", OPTO(2,TOLGE), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdlnli", OPTO(2,TOLNL), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdllei", OPTO(2,TOLLE), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdlngi", OPTO(2,TOLNG), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdgti", OPTO(2,TOGT), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdgei", OPTO(2,TOGE), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdnli", OPTO(2,TONL), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdlti", OPTO(2,TOLT), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdlei", OPTO(2,TOLE), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdngi", OPTO(2,TONG), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdnei", OPTO(2,TONE), OPTO_MASK, PPC64, { RA, SI } }, -{ "tdi", OP(2), OP_MASK, PPC64, { TO, RA, SI } }, - -{ "twlgti", OPTO(3,TOLGT), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tlgti", OPTO(3,TOLGT), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twllti", OPTO(3,TOLLT), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tllti", OPTO(3,TOLLT), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "tweqi", OPTO(3,TOEQ), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "teqi", OPTO(3,TOEQ), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twlgei", OPTO(3,TOLGE), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tlgei", OPTO(3,TOLGE), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twlnli", OPTO(3,TOLNL), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tlnli", OPTO(3,TOLNL), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twllei", OPTO(3,TOLLE), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tllei", OPTO(3,TOLLE), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twlngi", OPTO(3,TOLNG), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tlngi", OPTO(3,TOLNG), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twgti", OPTO(3,TOGT), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tgti", OPTO(3,TOGT), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twgei", OPTO(3,TOGE), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tgei", OPTO(3,TOGE), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twnli", OPTO(3,TONL), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tnli", OPTO(3,TONL), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twlti", OPTO(3,TOLT), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tlti", OPTO(3,TOLT), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twlei", OPTO(3,TOLE), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tlei", OPTO(3,TOLE), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twngi", OPTO(3,TONG), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tngi", OPTO(3,TONG), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twnei", OPTO(3,TONE), OPTO_MASK, PPCCOM, { RA, SI } }, -{ "tnei", OPTO(3,TONE), OPTO_MASK, PWRCOM, { RA, SI } }, -{ "twi", OP(3), OP_MASK, PPCCOM, { TO, RA, SI } }, -{ "ti", OP(3), OP_MASK, PWRCOM, { TO, RA, SI } }, - -{ "macchw", XO(4,172,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchw.", XO(4,172,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwo", XO(4,172,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwo.", XO(4,172,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchws", XO(4,236,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchws.", XO(4,236,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwso", XO(4,236,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwso.", XO(4,236,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwsu", XO(4,204,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwsu.", XO(4,204,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwsuo", XO(4,204,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwsuo.", XO(4,204,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwu", XO(4,140,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwu.", XO(4,140,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwuo", XO(4,140,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "macchwuo.", XO(4,140,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhw", XO(4,44,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhw.", XO(4,44,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwo", XO(4,44,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwo.", XO(4,44,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhws", XO(4,108,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhws.", XO(4,108,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwso", XO(4,108,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwso.", XO(4,108,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwsu", XO(4,76,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwsu.", XO(4,76,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwsuo", XO(4,76,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwsuo.", XO(4,76,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwu", XO(4,12,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwu.", XO(4,12,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwuo", XO(4,12,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "machhwuo.", XO(4,12,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhw", XO(4,428,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhw.", XO(4,428,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwo", XO(4,428,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwo.", XO(4,428,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhws", XO(4,492,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhws.", XO(4,492,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwso", XO(4,492,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwso.", XO(4,492,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwsu", XO(4,460,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwsu.", XO(4,460,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwsuo", XO(4,460,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwsuo.", XO(4,460,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwu", XO(4,396,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwu.", XO(4,396,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwuo", XO(4,396,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "maclhwuo.", XO(4,396,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulchw", XRC(4,168,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulchw.", XRC(4,168,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulchwu", XRC(4,136,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulchwu.", XRC(4,136,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulhhw", XRC(4,40,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulhhw.", XRC(4,40,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulhhwu", XRC(4,8,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mulhhwu.", XRC(4,8,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mullhw", XRC(4,424,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mullhw.", XRC(4,424,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mullhwu", XRC(4,392,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mullhwu.", XRC(4,392,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchw", XO(4,174,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchw.", XO(4,174,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchwo", XO(4,174,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchwo.", XO(4,174,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchws", XO(4,238,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchws.", XO(4,238,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchwso", XO(4,238,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmacchwso.", XO(4,238,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhw", XO(4,46,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhw.", XO(4,46,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhwo", XO(4,46,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhwo.", XO(4,46,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhws", XO(4,110,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhws.", XO(4,110,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhwso", XO(4,110,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmachhwso.", XO(4,110,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhw", XO(4,430,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhw.", XO(4,430,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhwo", XO(4,430,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhwo.", XO(4,430,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhws", XO(4,494,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhws.", XO(4,494,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhwso", XO(4,494,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, -{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } }, -{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } }, - - /* Double-precision opcodes. */ - /* Some of these conflict with AltiVec, so move them before, since - PPCVEC includes the PPC_OPCODE_PPC set. */ -{ "efscfd", VX(4, 719), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdabs", VX(4, 740), VX_MASK, PPCEFS, { RS, RA } }, -{ "efdnabs", VX(4, 741), VX_MASK, PPCEFS, { RS, RA } }, -{ "efdneg", VX(4, 742), VX_MASK, PPCEFS, { RS, RA } }, -{ "efdadd", VX(4, 736), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efdsub", VX(4, 737), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efdmul", VX(4, 744), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efddiv", VX(4, 745), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efdcmpgt", VX(4, 748), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efdcmplt", VX(4, 749), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efdcmpeq", VX(4, 750), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efdtstgt", VX(4, 764), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efdtstlt", VX(4, 765), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efdtsteq", VX(4, 766), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efdcfsi", VX(4, 753), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdcfsid", VX(4, 739), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdcfui", VX(4, 752), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdcfuid", VX(4, 738), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdcfsf", VX(4, 755), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdcfuf", VX(4, 754), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctsi", VX(4, 757), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctsidz",VX(4, 747), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctsiz", VX(4, 762), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctui", VX(4, 756), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctuidz",VX(4, 746), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctuiz", VX(4, 760), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctsf", VX(4, 759), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdctuf", VX(4, 758), VX_MASK, PPCEFS, { RS, RB } }, -{ "efdcfs", VX(4, 751), VX_MASK, PPCEFS, { RS, RB } }, - /* End of double-precision opcodes. */ - -{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vaddshs", VX(4, 832), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vaddsws", VX(4, 896), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vaddubm", VX(4, 0), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vaddubs", VX(4, 512), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vadduhm", VX(4, 64), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vadduhs", VX(4, 576), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vadduwm", VX(4, 128), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vadduws", VX(4, 640), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vand", VX(4, 1028), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vandc", VX(4, 1092), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vavgsb", VX(4, 1282), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vavgsh", VX(4, 1346), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vavgsw", VX(4, 1410), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vavgub", VX(4, 1026), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vavguh", VX(4, 1090), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vavguw", VX(4, 1154), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcfsx", VX(4, 842), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vcfux", VX(4, 778), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vcmpbfp", VXR(4, 966, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpbfp.", VXR(4, 966, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpeqfp", VXR(4, 198, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpeqfp.", VXR(4, 198, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpequb", VXR(4, 6, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpequb.", VXR(4, 6, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpequh", VXR(4, 70, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpequh.", VXR(4, 70, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpequw", VXR(4, 134, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpequw.", VXR(4, 134, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgefp", VXR(4, 454, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgefp.", VXR(4, 454, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtfp", VXR(4, 710, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtfp.", VXR(4, 710, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtsb", VXR(4, 774, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtsb.", VXR(4, 774, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtsh", VXR(4, 838, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtsh.", VXR(4, 838, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtsw", VXR(4, 902, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtsw.", VXR(4, 902, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtub", VXR(4, 518, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtub.", VXR(4, 518, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtuh", VXR(4, 582, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtuh.", VXR(4, 582, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtuw", VXR(4, 646, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vcmpgtuw.", VXR(4, 646, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, -{ "vctsxs", VX(4, 970), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vctuxs", VX(4, 906), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vexptefp", VX(4, 394), VX_MASK, PPCVEC, { VD, VB } }, -{ "vlogefp", VX(4, 458), VX_MASK, PPCVEC, { VD, VB } }, -{ "vmaddfp", VXA(4, 46), VXA_MASK, PPCVEC, { VD, VA, VC, VB } }, -{ "vmaxfp", VX(4, 1034), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmaxsb", VX(4, 258), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmaxsh", VX(4, 322), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmaxsw", VX(4, 386), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmaxub", VX(4, 2), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmaxuh", VX(4, 66), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmaxuw", VX(4, 130), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmhaddshs", VXA(4, 32), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmhraddshs", VXA(4, 33), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vminfp", VX(4, 1098), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vminsb", VX(4, 770), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vminsh", VX(4, 834), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vminsw", VX(4, 898), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vminub", VX(4, 514), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vminuh", VX(4, 578), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vminuw", VX(4, 642), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmladduhm", VXA(4, 34), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmrghb", VX(4, 12), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmrghh", VX(4, 76), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmrghw", VX(4, 140), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmrglb", VX(4, 268), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmrglh", VX(4, 332), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmrglw", VX(4, 396), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmsummbm", VXA(4, 37), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmsumshm", VXA(4, 40), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmsumshs", VXA(4, 41), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmsumubm", VXA(4, 36), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmsumuhm", VXA(4, 38), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmsumuhs", VXA(4, 39), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vmulesb", VX(4, 776), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmulesh", VX(4, 840), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmuleub", VX(4, 520), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmuleuh", VX(4, 584), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmulosb", VX(4, 264), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmulosh", VX(4, 328), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmuloub", VX(4, 8), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vmulouh", VX(4, 72), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vnmsubfp", VXA(4, 47), VXA_MASK, PPCVEC, { VD, VA, VC, VB } }, -{ "vnor", VX(4, 1284), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vor", VX(4, 1156), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vperm", VXA(4, 43), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vpkpx", VX(4, 782), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkshss", VX(4, 398), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkshus", VX(4, 270), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkswss", VX(4, 462), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkswus", VX(4, 334), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkuhum", VX(4, 14), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkuhus", VX(4, 142), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkuwum", VX(4, 78), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vpkuwus", VX(4, 206), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vrefp", VX(4, 266), VX_MASK, PPCVEC, { VD, VB } }, -{ "vrfim", VX(4, 714), VX_MASK, PPCVEC, { VD, VB } }, -{ "vrfin", VX(4, 522), VX_MASK, PPCVEC, { VD, VB } }, -{ "vrfip", VX(4, 650), VX_MASK, PPCVEC, { VD, VB } }, -{ "vrfiz", VX(4, 586), VX_MASK, PPCVEC, { VD, VB } }, -{ "vrlb", VX(4, 4), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vrlh", VX(4, 68), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vrlw", VX(4, 132), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vrsqrtefp", VX(4, 330), VX_MASK, PPCVEC, { VD, VB } }, -{ "vsel", VXA(4, 42), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, -{ "vsl", VX(4, 452), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vslb", VX(4, 260), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsldoi", VXA(4, 44), VXA_MASK, PPCVEC, { VD, VA, VB, SHB } }, -{ "vslh", VX(4, 324), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vslo", VX(4, 1036), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vslw", VX(4, 388), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vspltb", VX(4, 524), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vsplth", VX(4, 588), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vspltisb", VX(4, 780), VX_MASK, PPCVEC, { VD, SIMM } }, -{ "vspltish", VX(4, 844), VX_MASK, PPCVEC, { VD, SIMM } }, -{ "vspltisw", VX(4, 908), VX_MASK, PPCVEC, { VD, SIMM } }, -{ "vspltw", VX(4, 652), VX_MASK, PPCVEC, { VD, VB, UIMM } }, -{ "vsr", VX(4, 708), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsrab", VX(4, 772), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsrah", VX(4, 836), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsraw", VX(4, 900), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsrb", VX(4, 516), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsrh", VX(4, 580), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsro", VX(4, 1100), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsrw", VX(4, 644), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubcuw", VX(4, 1408), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubfp", VX(4, 74), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubsbs", VX(4, 1792), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubshs", VX(4, 1856), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubsws", VX(4, 1920), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsububm", VX(4, 1024), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsububs", VX(4, 1536), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubuhm", VX(4, 1088), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubuhs", VX(4, 1600), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubuwm", VX(4, 1152), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsubuws", VX(4, 1664), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsumsws", VX(4, 1928), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsum2sws", VX(4, 1672), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsum4sbs", VX(4, 1800), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsum4shs", VX(4, 1608), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vsum4ubs", VX(4, 1544), VX_MASK, PPCVEC, { VD, VA, VB } }, -{ "vupkhpx", VX(4, 846), VX_MASK, PPCVEC, { VD, VB } }, -{ "vupkhsb", VX(4, 526), VX_MASK, PPCVEC, { VD, VB } }, -{ "vupkhsh", VX(4, 590), VX_MASK, PPCVEC, { VD, VB } }, -{ "vupklpx", VX(4, 974), VX_MASK, PPCVEC, { VD, VB } }, -{ "vupklsb", VX(4, 654), VX_MASK, PPCVEC, { VD, VB } }, -{ "vupklsh", VX(4, 718), VX_MASK, PPCVEC, { VD, VB } }, -{ "vxor", VX(4, 1220), VX_MASK, PPCVEC, { VD, VA, VB } }, - -{ "evaddw", VX(4, 512), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evaddiw", VX(4, 514), VX_MASK, PPCSPE, { RS, RB, UIMM } }, -{ "evsubfw", VX(4, 516), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evsubw", VX(4, 516), VX_MASK, PPCSPE, { RS, RB, RA } }, -{ "evsubifw", VX(4, 518), VX_MASK, PPCSPE, { RS, UIMM, RB } }, -{ "evsubiw", VX(4, 518), VX_MASK, PPCSPE, { RS, RB, UIMM } }, -{ "evabs", VX(4, 520), VX_MASK, PPCSPE, { RS, RA } }, -{ "evneg", VX(4, 521), VX_MASK, PPCSPE, { RS, RA } }, -{ "evextsb", VX(4, 522), VX_MASK, PPCSPE, { RS, RA } }, -{ "evextsh", VX(4, 523), VX_MASK, PPCSPE, { RS, RA } }, -{ "evrndw", VX(4, 524), VX_MASK, PPCSPE, { RS, RA } }, -{ "evcntlzw", VX(4, 525), VX_MASK, PPCSPE, { RS, RA } }, -{ "evcntlsw", VX(4, 526), VX_MASK, PPCSPE, { RS, RA } }, - -{ "brinc", VX(4, 527), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evand", VX(4, 529), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evandc", VX(4, 530), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmr", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, BBA } }, -{ "evor", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evorc", VX(4, 539), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evxor", VX(4, 534), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "eveqv", VX(4, 537), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evnand", VX(4, 542), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evnot", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, BBA } }, -{ "evnor", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evrlw", VX(4, 552), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evrlwi", VX(4, 554), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, -{ "evslw", VX(4, 548), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evslwi", VX(4, 550), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, -{ "evsrws", VX(4, 545), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evsrwu", VX(4, 544), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evsrwis", VX(4, 547), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, -{ "evsrwiu", VX(4, 546), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, -{ "evsplati", VX(4, 553), VX_MASK, PPCSPE, { RS, SIMM } }, -{ "evsplatfi", VX(4, 555), VX_MASK, PPCSPE, { RS, SIMM } }, -{ "evmergehi", VX(4, 556), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmergelo", VX(4, 557), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmergehilo",VX(4,558), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmergelohi",VX(4,559), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evcmpgts", VX(4, 561), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evcmpgtu", VX(4, 560), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evcmplts", VX(4, 563), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evcmpltu", VX(4, 562), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evcmpeq", VX(4, 564), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evsel", EVSEL(4,79),EVSEL_MASK, PPCSPE, { RS, RA, RB, CRFS } }, - -{ "evldd", VX(4, 769), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, -{ "evlddx", VX(4, 768), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evldw", VX(4, 771), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, -{ "evldwx", VX(4, 770), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evldh", VX(4, 773), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, -{ "evldhx", VX(4, 772), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlwhe", VX(4, 785), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evlwhex", VX(4, 784), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlwhou", VX(4, 789), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evlwhoux", VX(4, 788), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlwhos", VX(4, 791), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evlwhosx", VX(4, 790), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlwwsplat",VX(4, 793), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evlwwsplatx",VX(4, 792), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlwhsplat",VX(4, 797), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evlwhsplatx",VX(4, 796), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlhhesplat",VX(4, 777), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } }, -{ "evlhhesplatx",VX(4, 776), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlhhousplat",VX(4, 781), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } }, -{ "evlhhousplatx",VX(4, 780), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evlhhossplat",VX(4, 783), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } }, -{ "evlhhossplatx",VX(4, 782), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evstdd", VX(4, 801), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, -{ "evstddx", VX(4, 800), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evstdw", VX(4, 803), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, -{ "evstdwx", VX(4, 802), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evstdh", VX(4, 805), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, -{ "evstdhx", VX(4, 804), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evstwwe", VX(4, 825), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evstwwex", VX(4, 824), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evstwwo", VX(4, 829), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evstwwox", VX(4, 828), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evstwhe", VX(4, 817), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evstwhex", VX(4, 816), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evstwho", VX(4, 821), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, -{ "evstwhox", VX(4, 820), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evfsabs", VX(4, 644), VX_MASK, PPCSPE, { RS, RA } }, -{ "evfsnabs", VX(4, 645), VX_MASK, PPCSPE, { RS, RA } }, -{ "evfsneg", VX(4, 646), VX_MASK, PPCSPE, { RS, RA } }, -{ "evfsadd", VX(4, 640), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evfssub", VX(4, 641), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evfsmul", VX(4, 648), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evfsdiv", VX(4, 649), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evfscmpgt", VX(4, 652), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evfscmplt", VX(4, 653), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evfscmpeq", VX(4, 654), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evfststgt", VX(4, 668), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evfststlt", VX(4, 669), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evfststeq", VX(4, 670), VX_MASK, PPCSPE, { CRFD, RA, RB } }, -{ "evfscfui", VX(4, 656), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfsctuiz", VX(4, 664), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfscfsi", VX(4, 657), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfscfuf", VX(4, 658), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfscfsf", VX(4, 659), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfsctui", VX(4, 660), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfsctsi", VX(4, 661), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfsctsiz", VX(4, 666), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfsctuf", VX(4, 662), VX_MASK, PPCSPE, { RS, RB } }, -{ "evfsctsf", VX(4, 663), VX_MASK, PPCSPE, { RS, RB } }, - -{ "efsabs", VX(4, 708), VX_MASK, PPCEFS, { RS, RA } }, -{ "efsnabs", VX(4, 709), VX_MASK, PPCEFS, { RS, RA } }, -{ "efsneg", VX(4, 710), VX_MASK, PPCEFS, { RS, RA } }, -{ "efsadd", VX(4, 704), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efssub", VX(4, 705), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efsmul", VX(4, 712), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efsdiv", VX(4, 713), VX_MASK, PPCEFS, { RS, RA, RB } }, -{ "efscmpgt", VX(4, 716), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efscmplt", VX(4, 717), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efscmpeq", VX(4, 718), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efststgt", VX(4, 732), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efststlt", VX(4, 733), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efststeq", VX(4, 734), VX_MASK, PPCEFS, { CRFD, RA, RB } }, -{ "efscfui", VX(4, 720), VX_MASK, PPCEFS, { RS, RB } }, -{ "efsctuiz", VX(4, 728), VX_MASK, PPCEFS, { RS, RB } }, -{ "efscfsi", VX(4, 721), VX_MASK, PPCEFS, { RS, RB } }, -{ "efscfuf", VX(4, 722), VX_MASK, PPCEFS, { RS, RB } }, -{ "efscfsf", VX(4, 723), VX_MASK, PPCEFS, { RS, RB } }, -{ "efsctui", VX(4, 724), VX_MASK, PPCEFS, { RS, RB } }, -{ "efsctsi", VX(4, 725), VX_MASK, PPCEFS, { RS, RB } }, -{ "efsctsiz", VX(4, 730), VX_MASK, PPCEFS, { RS, RB } }, -{ "efsctuf", VX(4, 726), VX_MASK, PPCEFS, { RS, RB } }, -{ "efsctsf", VX(4, 727), VX_MASK, PPCEFS, { RS, RB } }, - -{ "evmhossf", VX(4, 1031), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhossfa", VX(4, 1063), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmf", VX(4, 1039), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmfa", VX(4, 1071), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmi", VX(4, 1037), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmia", VX(4, 1069), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhoumi", VX(4, 1036), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhoumia", VX(4, 1068), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhessf", VX(4, 1027), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhessfa", VX(4, 1059), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmf", VX(4, 1035), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmfa", VX(4, 1067), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmi", VX(4, 1033), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmia", VX(4, 1065), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmheumi", VX(4, 1032), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmheumia", VX(4, 1064), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmhossfaaw",VX(4, 1287), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhossiaaw",VX(4, 1285), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmfaaw",VX(4, 1295), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmiaaw",VX(4, 1293), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhousiaaw",VX(4, 1284), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhoumiaaw",VX(4, 1292), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhessfaaw",VX(4, 1283), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhessiaaw",VX(4, 1281), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmfaaw",VX(4, 1291), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmiaaw",VX(4, 1289), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmheusiaaw",VX(4, 1280), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmheumiaaw",VX(4, 1288), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmhossfanw",VX(4, 1415), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhossianw",VX(4, 1413), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmfanw",VX(4, 1423), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhosmianw",VX(4, 1421), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhousianw",VX(4, 1412), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhoumianw",VX(4, 1420), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhessfanw",VX(4, 1411), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhessianw",VX(4, 1409), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmfanw",VX(4, 1419), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhesmianw",VX(4, 1417), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmheusianw",VX(4, 1408), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmheumianw",VX(4, 1416), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmhogsmfaa",VX(4, 1327), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhogsmiaa",VX(4, 1325), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhogumiaa",VX(4, 1324), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhegsmfaa",VX(4, 1323), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhegsmiaa",VX(4, 1321), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhegumiaa",VX(4, 1320), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmhogsmfan",VX(4, 1455), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhogsmian",VX(4, 1453), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhogumian",VX(4, 1452), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhegsmfan",VX(4, 1451), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhegsmian",VX(4, 1449), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmhegumian",VX(4, 1448), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwhssf", VX(4, 1095), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhssfa", VX(4, 1127), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhsmf", VX(4, 1103), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhsmfa", VX(4, 1135), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhsmi", VX(4, 1101), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhsmia", VX(4, 1133), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhumi", VX(4, 1100), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwhumia", VX(4, 1132), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwlumi", VX(4, 1096), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlumia", VX(4, 1128), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwlssiaaw",VX(4, 1345), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlsmiaaw",VX(4, 1353), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlusiaaw",VX(4, 1344), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlumiaaw",VX(4, 1352), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwlssianw",VX(4, 1473), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlsmianw",VX(4, 1481), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlusianw",VX(4, 1472), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwlumianw",VX(4, 1480), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwssf", VX(4, 1107), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwssfa", VX(4, 1139), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmf", VX(4, 1115), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmfa", VX(4, 1147), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmi", VX(4, 1113), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmia", VX(4, 1145), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwumi", VX(4, 1112), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwumia", VX(4, 1144), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwssfaa", VX(4, 1363), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmfaa", VX(4, 1371), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmiaa", VX(4, 1369), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwumiaa", VX(4, 1368), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evmwssfan", VX(4, 1491), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmfan", VX(4, 1499), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwsmian", VX(4, 1497), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evmwumian", VX(4, 1496), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "evaddssiaaw",VX(4, 1217), VX_MASK, PPCSPE, { RS, RA } }, -{ "evaddsmiaaw",VX(4, 1225), VX_MASK, PPCSPE, { RS, RA } }, -{ "evaddusiaaw",VX(4, 1216), VX_MASK, PPCSPE, { RS, RA } }, -{ "evaddumiaaw",VX(4, 1224), VX_MASK, PPCSPE, { RS, RA } }, - -{ "evsubfssiaaw",VX(4, 1219), VX_MASK, PPCSPE, { RS, RA } }, -{ "evsubfsmiaaw",VX(4, 1227), VX_MASK, PPCSPE, { RS, RA } }, -{ "evsubfusiaaw",VX(4, 1218), VX_MASK, PPCSPE, { RS, RA } }, -{ "evsubfumiaaw",VX(4, 1226), VX_MASK, PPCSPE, { RS, RA } }, - -{ "evmra", VX(4, 1220), VX_MASK, PPCSPE, { RS, RA } }, - -{ "evdivws", VX(4, 1222), VX_MASK, PPCSPE, { RS, RA, RB } }, -{ "evdivwu", VX(4, 1223), VX_MASK, PPCSPE, { RS, RA, RB } }, - -{ "mulli", OP(7), OP_MASK, PPCCOM, { RT, RA, SI } }, -{ "muli", OP(7), OP_MASK, PWRCOM, { RT, RA, SI } }, - -{ "subfic", OP(8), OP_MASK, PPCCOM, { RT, RA, SI } }, -{ "sfi", OP(8), OP_MASK, PWRCOM, { RT, RA, SI } }, - -{ "dozi", OP(9), OP_MASK, M601, { RT, RA, SI } }, - -{ "bce", B(9,0,0), B_MASK, BOOKE64, { BO, BI, BD } }, -{ "bcel", B(9,0,1), B_MASK, BOOKE64, { BO, BI, BD } }, -{ "bcea", B(9,1,0), B_MASK, BOOKE64, { BO, BI, BDA } }, -{ "bcela", B(9,1,1), B_MASK, BOOKE64, { BO, BI, BDA } }, - -{ "cmplwi", OPL(10,0), OPL_MASK, PPCCOM, { OBF, RA, UI } }, -{ "cmpldi", OPL(10,1), OPL_MASK, PPC64, { OBF, RA, UI } }, -{ "cmpli", OP(10), OP_MASK, PPC, { BF, L, RA, UI } }, -{ "cmpli", OP(10), OP_MASK, PWRCOM, { BF, RA, UI } }, - -{ "cmpwi", OPL(11,0), OPL_MASK, PPCCOM, { OBF, RA, SI } }, -{ "cmpdi", OPL(11,1), OPL_MASK, PPC64, { OBF, RA, SI } }, -{ "cmpi", OP(11), OP_MASK, PPC, { BF, L, RA, SI } }, -{ "cmpi", OP(11), OP_MASK, PWRCOM, { BF, RA, SI } }, - -{ "addic", OP(12), OP_MASK, PPCCOM, { RT, RA, SI } }, -{ "ai", OP(12), OP_MASK, PWRCOM, { RT, RA, SI } }, -{ "subic", OP(12), OP_MASK, PPCCOM, { RT, RA, NSI } }, - -{ "addic.", OP(13), OP_MASK, PPCCOM, { RT, RA, SI } }, -{ "ai.", OP(13), OP_MASK, PWRCOM, { RT, RA, SI } }, -{ "subic.", OP(13), OP_MASK, PPCCOM, { RT, RA, NSI } }, - -{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } }, -{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } }, -{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA0, SI } }, -{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA0 } }, -{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA0, NSI } }, -{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA0 } }, - -{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } }, -{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } }, -{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA0,SISIGNOPT } }, -{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA0,SISIGNOPT } }, -{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA0, NSI } }, - -{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, -{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, -{ "bdnz", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BD } }, -{ "bdn", BBO(16,BODNZ,0,0), BBOATBI_MASK, PWRCOM, { BD } }, -{ "bdnzl-", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } }, -{ "bdnzl+", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } }, -{ "bdnzl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BD } }, -{ "bdnl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PWRCOM, { BD } }, -{ "bdnza-", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } }, -{ "bdnza+", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } }, -{ "bdnza", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDA } }, -{ "bdna", BBO(16,BODNZ,1,0), BBOATBI_MASK, PWRCOM, { BDA } }, -{ "bdnzla-", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } }, -{ "bdnzla+", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } }, -{ "bdnzla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDA } }, -{ "bdnla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PWRCOM, { BDA } }, -{ "bdz-", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, -{ "bdz+", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, -{ "bdz", BBO(16,BODZ,0,0), BBOATBI_MASK, COM, { BD } }, -{ "bdzl-", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } }, -{ "bdzl+", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } }, -{ "bdzl", BBO(16,BODZ,0,1), BBOATBI_MASK, COM, { BD } }, -{ "bdza-", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } }, -{ "bdza+", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } }, -{ "bdza", BBO(16,BODZ,1,0), BBOATBI_MASK, COM, { BDA } }, -{ "bdzla-", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } }, -{ "bdzla+", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } }, -{ "bdzla", BBO(16,BODZ,1,1), BBOATBI_MASK, COM, { BDA } }, -{ "blt-", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "blt+", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "blt", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bltl-", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bltl+", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bltl", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "blta-", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "blta+", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "blta", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bltla-", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bltla+", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bltla", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bgt-", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bgt+", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bgt", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bgtl-", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bgtl+", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bgtl", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bgta-", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bgta+", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bgta", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bgtla-", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bgtla+", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bgtla", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "beq-", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "beq+", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "beq", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "beql-", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "beql+", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "beql", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "beqa-", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "beqa+", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "beqa", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "beqla-", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "beqla+", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "beqla", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bso-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bso+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bso", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bsol-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bsol+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bsol", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bsoa-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bsoa+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bsoa", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bsola-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bsola+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bsola", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bun-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bun+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bun", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } }, -{ "bunl-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bunl+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bunl", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } }, -{ "buna-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "buna+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "buna", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } }, -{ "bunla-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bunla+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bunla", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } }, -{ "bge-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bge+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bge", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bgel-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bgel+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bgel", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bgea-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bgea+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bgea", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bgela-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bgela+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bgela", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bnl-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bnl+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bnl", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnll-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bnll+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bnll", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnla-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnla+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnla", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bnlla-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnlla+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnlla", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "ble-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "ble+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "ble", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "blel-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "blel+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "blel", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "blea-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "blea+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "blea", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "blela-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "blela+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "blela", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bng-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bng+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bng", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bngl-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bngl+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bngl", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnga-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnga+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnga", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bngla-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bngla+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bngla", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bne-", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bne+", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bne", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnel-", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bnel+", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bnel", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnea-", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnea+", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnea", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bnela-", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnela+", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnela", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bns-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bns+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bns", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnsl-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bnsl+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bnsl", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } }, -{ "bnsa-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnsa+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnsa", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bnsla-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnsla+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnsla", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } }, -{ "bnu-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bnu+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bnu", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } }, -{ "bnul-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, -{ "bnul+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, -{ "bnul", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } }, -{ "bnua-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnua+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnua", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } }, -{ "bnula-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, -{ "bnula+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, -{ "bnula", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } }, -{ "bdnzt-", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdnzt+", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdnzt", BBO(16,BODNZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdnztl", BBO(16,BODNZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdnzta", BBO(16,BODNZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bdnzf-", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdnzf+", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdnzf", BBO(16,BODNZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdnzfl", BBO(16,BODNZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdnzfa", BBO(16,BODNZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bt-", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } }, -{ "bt+", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } }, -{ "bt", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BD } }, -{ "bbt", BBO(16,BOT,0,0), BBOAT_MASK, PWRCOM, { BI, BD } }, -{ "btl-", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } }, -{ "btl+", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } }, -{ "btl", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BD } }, -{ "bbtl", BBO(16,BOT,0,1), BBOAT_MASK, PWRCOM, { BI, BD } }, -{ "bta-", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } }, -{ "bta+", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } }, -{ "bta", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } }, -{ "bbta", BBO(16,BOT,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } }, -{ "btla-", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } }, -{ "btla+", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } }, -{ "btla", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } }, -{ "bbtla", BBO(16,BOT,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } }, -{ "bf-", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } }, -{ "bf+", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } }, -{ "bf", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BD } }, -{ "bbf", BBO(16,BOF,0,0), BBOAT_MASK, PWRCOM, { BI, BD } }, -{ "bfl-", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } }, -{ "bfl+", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } }, -{ "bfl", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BD } }, -{ "bbfl", BBO(16,BOF,0,1), BBOAT_MASK, PWRCOM, { BI, BD } }, -{ "bfa-", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } }, -{ "bfa+", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } }, -{ "bfa", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } }, -{ "bbfa", BBO(16,BOF,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } }, -{ "bfla-", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } }, -{ "bfla+", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } }, -{ "bfla", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } }, -{ "bbfla", BBO(16,BOF,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } }, -{ "bdzt-", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdzt+", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdzt", BBO(16,BODZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdztl-", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdztl+", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdztl", BBO(16,BODZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdzta-", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdzta+", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdzta", BBO(16,BODZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdztla", BBO(16,BODZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bdzf-", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdzf+", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdzf", BBO(16,BODZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdzfl-", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, -{ "bdzfl+", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, -{ "bdzfl", BBO(16,BODZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, -{ "bdzfa-", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdzfa+", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdzfa", BBO(16,BODZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, -{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, -{ "bdzfla", BBO(16,BODZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, -{ "bc-", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDM } }, -{ "bc+", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDP } }, -{ "bc", B(16,0,0), B_MASK, COM, { BO, BI, BD } }, -{ "bcl-", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDM } }, -{ "bcl+", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDP } }, -{ "bcl", B(16,0,1), B_MASK, COM, { BO, BI, BD } }, -{ "bca-", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDMA } }, -{ "bca+", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDPA } }, -{ "bca", B(16,1,0), B_MASK, COM, { BO, BI, BDA } }, -{ "bcla-", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDMA } }, -{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } }, -{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, - -{ "sc", SC(17,1,0), SC_MASK, PPC, { LEV } }, -{ "svc", SC(17,0,0), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, -{ "svcl", SC(17,0,1), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, -{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, -{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } }, - -{ "b", B(18,0,0), B_MASK, COM, { LI } }, -{ "bl", B(18,0,1), B_MASK, COM, { LI } }, -{ "ba", B(18,1,0), B_MASK, COM, { LIA } }, -{ "bla", B(18,1,1), B_MASK, COM, { LIA } }, - -{ "mcrf", XL(19,0), XLBB_MASK|(3 << 21)|(3 << 16), COM, { BF, BFA } }, - -{ "blr", XLO(19,BOU,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, -{ "br", XLO(19,BOU,16,0), XLBOBIBB_MASK, PWRCOM, { 0 } }, -{ "blrl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, -{ "brl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PWRCOM, { 0 } }, -{ "bdnzlr", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, -{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdnzlr-", XLO(19,BODNZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdnzlr+", XLO(19,BODNZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, -{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdnzlrl-",XLO(19,BODNZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdnzlrl+",XLO(19,BODNZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdzlr", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, -{ "bdzlr-", XLO(19,BODZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdzlr-", XLO(19,BODZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdzlr+", XLO(19,BODZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdzlr+", XLO(19,BODZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdzlrl", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, -{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdzlrl-", XLO(19,BODZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, -{ "bdzlrl+", XLO(19,BODZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, -{ "bltlr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bltlr-", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltlr-", XLOCB(19,BOTM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltlr+", XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltlr+", XLOCB(19,BOTP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bltlrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltlrl-", XLOCB(19,BOTM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltlrl+", XLOCB(19,BOTP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bgtlr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgtlr-", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtlr-", XLOCB(19,BOTM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtlr+", XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtlr+", XLOCB(19,BOTP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bgtlrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtlrl-", XLOCB(19,BOTM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtlrl+", XLOCB(19,BOTP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "beqlr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "beqlr-", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqlr-", XLOCB(19,BOTM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqlr+", XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqlr+", XLOCB(19,BOTP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "beqlrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqlrl-", XLOCB(19,BOTM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqlrl+", XLOCB(19,BOTP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bsolr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bsolr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsolr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsolr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsolr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsor", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bsolrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsolrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsolrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsorl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bunlr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bunlr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunlr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunlr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunlr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunlrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunlrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunlrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgelr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgelr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgelr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgelr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgelr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bger", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bgelrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgelrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgelrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgerl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnllr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnllr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnllr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnllr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnllr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnlr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnllrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnllrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnllrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnlrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "blelr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "blelr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blelr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blelr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blelr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bler", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "blelrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blelrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blelrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blerl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnglr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnglr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnglr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnglr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnglr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bngr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnglrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnglrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnglrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bngrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnelr", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnelr-", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnelr-", XLOCB(19,BOFM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnelr+", XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnelr+", XLOCB(19,BOFP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bner", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnelrl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnelrl-", XLOCB(19,BOFM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnelrl+", XLOCB(19,BOFP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnerl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnslr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnslr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnslr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnslr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnslr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnsr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnslrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnslrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnslrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnsrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, -{ "bnulr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnulr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnulr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnulr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnulr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnulrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnulrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnulrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "btlr", XLO(19,BOT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "btlr-", XLO(19,BOT,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btlr-", XLO(19,BOTM4,16,0), XLBOBB_MASK, POWER4, { BI } }, -{ "btlr+", XLO(19,BOTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btlr+", XLO(19,BOTP4,16,0), XLBOBB_MASK, POWER4, { BI } }, -{ "bbtr", XLO(19,BOT,16,0), XLBOBB_MASK, PWRCOM, { BI } }, -{ "btlrl", XLO(19,BOT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "btlrl-", XLO(19,BOT,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btlrl-", XLO(19,BOTM4,16,1), XLBOBB_MASK, POWER4, { BI } }, -{ "btlrl+", XLO(19,BOTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btlrl+", XLO(19,BOTP4,16,1), XLBOBB_MASK, POWER4, { BI } }, -{ "bbtrl", XLO(19,BOT,16,1), XLBOBB_MASK, PWRCOM, { BI } }, -{ "bflr", XLO(19,BOF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bflr-", XLO(19,BOF,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bflr-", XLO(19,BOFM4,16,0), XLBOBB_MASK, POWER4, { BI } }, -{ "bflr+", XLO(19,BOFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bflr+", XLO(19,BOFP4,16,0), XLBOBB_MASK, POWER4, { BI } }, -{ "bbfr", XLO(19,BOF,16,0), XLBOBB_MASK, PWRCOM, { BI } }, -{ "bflrl", XLO(19,BOF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bflrl-", XLO(19,BOF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bflrl-", XLO(19,BOFM4,16,1), XLBOBB_MASK, POWER4, { BI } }, -{ "bflrl+", XLO(19,BOFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bflrl+", XLO(19,BOFP4,16,1), XLBOBB_MASK, POWER4, { BI } }, -{ "bbfrl", XLO(19,BOF,16,1), XLBOBB_MASK, PWRCOM, { BI } }, -{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdztlr", XLO(19,BODZT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdzflr", XLO(19,BODZF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bclr", XLLK(19,16,0), XLBH_MASK, PPCCOM, { BO, BI, BH } }, -{ "bclrl", XLLK(19,16,1), XLBH_MASK, PPCCOM, { BO, BI, BH } }, -{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } }, -{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } }, -{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } }, -{ "bclrel", XLLK(19,17,1), XLBB_MASK, BOOKE64, { BO, BI } }, - -{ "rfid", XL(19,18), 0xffffffff, PPC64, { 0 } }, - -{ "crnot", XL(19,33), XL_MASK, PPCCOM, { BT, BA, BBA } }, -{ "crnor", XL(19,33), XL_MASK, COM, { BT, BA, BB } }, -{ "rfmci", X(19,38), 0xffffffff, PPCRFMCI, { 0 } }, - -{ "rfi", XL(19,50), 0xffffffff, COM, { 0 } }, -{ "rfci", XL(19,51), 0xffffffff, PPC403 | BOOKE, { 0 } }, - -{ "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } }, - -{ "crandc", XL(19,129), XL_MASK, COM, { BT, BA, BB } }, - -{ "isync", XL(19,150), 0xffffffff, PPCCOM, { 0 } }, -{ "ics", XL(19,150), 0xffffffff, PWRCOM, { 0 } }, - -{ "crclr", XL(19,193), XL_MASK, PPCCOM, { BT, BAT, BBA } }, -{ "crxor", XL(19,193), XL_MASK, COM, { BT, BA, BB } }, - -{ "crnand", XL(19,225), XL_MASK, COM, { BT, BA, BB } }, - -{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } }, - -{ "hrfid", XL(19,274), 0xffffffff, POWER5 | CELL, { 0 } }, - -{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } }, -{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } }, - -{ "doze", XL(19,402), 0xffffffff, POWER6, { 0 } }, - -{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } }, - -{ "nap", XL(19,434), 0xffffffff, POWER6, { 0 } }, - -{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } }, -{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } }, - -{ "sleep", XL(19,466), 0xffffffff, POWER6, { 0 } }, -{ "rvwinkle", XL(19,498), 0xffffffff, POWER6, { 0 } }, - -{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } }, -{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } }, -{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltctr-", XLOCB(19,BOTM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltctr+", XLOCB(19,BOTP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltctrl-",XLOCB(19,BOTM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bltctrl+",XLOCB(19,BOTP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtctr", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtctr-", XLOCB(19,BOTM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtctr+", XLOCB(19,BOTP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtctrl-",XLOCB(19,BOTM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgtctrl+",XLOCB(19,BOTP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqctr", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqctr-", XLOCB(19,BOTM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqctr+", XLOCB(19,BOTP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqctrl-",XLOCB(19,BOTM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "beqctrl+",XLOCB(19,BOTP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsoctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsoctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsoctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsoctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bsoctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bunctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgectr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgectr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgectr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgectrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bgectrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnlctr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnlctr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnlctr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnlctrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnlctrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blectr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blectr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blectr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blectrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "blectrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bngctr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bngctr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bngctr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bngctrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bngctrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnectr", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnectr-", XLOCB(19,BOFM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnectr+", XLOCB(19,BOFP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnectrl-",XLOCB(19,BOFM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnectrl+",XLOCB(19,BOFP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnsctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnsctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnsctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnsctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnsctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnuctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnuctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnuctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, -{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnuctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, -{ "bnuctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, -{ "btctr", XLO(19,BOT,528,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "btctr-", XLO(19,BOT,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btctr-", XLO(19,BOTM4,528,0), XLBOBB_MASK, POWER4, { BI } }, -{ "btctr+", XLO(19,BOTP,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btctr+", XLO(19,BOTP4,528,0), XLBOBB_MASK, POWER4, { BI } }, -{ "btctrl", XLO(19,BOT,528,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btctrl-", XLO(19,BOTM4,528,1), XLBOBB_MASK, POWER4, { BI } }, -{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "btctrl+", XLO(19,BOTP4,528,1), XLBOBB_MASK, POWER4, { BI } }, -{ "bfctr", XLO(19,BOF,528,0), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bfctr-", XLO(19,BOF,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bfctr-", XLO(19,BOFM4,528,0), XLBOBB_MASK, POWER4, { BI } }, -{ "bfctr+", XLO(19,BOFP,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bfctr+", XLO(19,BOFP4,528,0), XLBOBB_MASK, POWER4, { BI } }, -{ "bfctrl", XLO(19,BOF,528,1), XLBOBB_MASK, PPCCOM, { BI } }, -{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } }, -{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, -{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } }, -{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, -{ "bcctr", XLLK(19,528,0), XLBH_MASK, PPCCOM, { BO, BI, BH } }, -{ "bcctrl", XLLK(19,528,1), XLBH_MASK, PPCCOM, { BO, BI, BH } }, -{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } }, -{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } }, -{ "bcctre", XLLK(19,529,0), XLBB_MASK, BOOKE64, { BO, BI } }, -{ "bcctrel", XLLK(19,529,1), XLBB_MASK, BOOKE64, { BO, BI } }, - -{ "rlwimi", M(20,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, -{ "rlimi", M(20,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, - -{ "rlwimi.", M(20,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, -{ "rlimi.", M(20,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, - -{ "rotlwi", MME(21,31,0), MMBME_MASK, PPCCOM, { RA, RS, SH } }, -{ "clrlwi", MME(21,31,0), MSHME_MASK, PPCCOM, { RA, RS, MB } }, -{ "rlwinm", M(21,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, -{ "rlinm", M(21,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, -{ "rotlwi.", MME(21,31,1), MMBME_MASK, PPCCOM, { RA,RS,SH } }, -{ "clrlwi.", MME(21,31,1), MSHME_MASK, PPCCOM, { RA, RS, MB } }, -{ "rlwinm.", M(21,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, -{ "rlinm.", M(21,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, - -{ "rlmi", M(22,0), M_MASK, M601, { RA,RS,RB,MBE,ME } }, -{ "rlmi.", M(22,1), M_MASK, M601, { RA,RS,RB,MBE,ME } }, - -{ "be", B(22,0,0), B_MASK, BOOKE64, { LI } }, -{ "bel", B(22,0,1), B_MASK, BOOKE64, { LI } }, -{ "bea", B(22,1,0), B_MASK, BOOKE64, { LIA } }, -{ "bela", B(22,1,1), B_MASK, BOOKE64, { LIA } }, - -{ "rotlw", MME(23,31,0), MMBME_MASK, PPCCOM, { RA, RS, RB } }, -{ "rlwnm", M(23,0), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } }, -{ "rlnm", M(23,0), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } }, -{ "rotlw.", MME(23,31,1), MMBME_MASK, PPCCOM, { RA, RS, RB } }, -{ "rlwnm.", M(23,1), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } }, -{ "rlnm.", M(23,1), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } }, - -{ "nop", OP(24), 0xffffffff, PPCCOM, { 0 } }, -{ "ori", OP(24), OP_MASK, PPCCOM, { RA, RS, UI } }, -{ "oril", OP(24), OP_MASK, PWRCOM, { RA, RS, UI } }, - -{ "oris", OP(25), OP_MASK, PPCCOM, { RA, RS, UI } }, -{ "oriu", OP(25), OP_MASK, PWRCOM, { RA, RS, UI } }, - -{ "xori", OP(26), OP_MASK, PPCCOM, { RA, RS, UI } }, -{ "xoril", OP(26), OP_MASK, PWRCOM, { RA, RS, UI } }, - -{ "xoris", OP(27), OP_MASK, PPCCOM, { RA, RS, UI } }, -{ "xoriu", OP(27), OP_MASK, PWRCOM, { RA, RS, UI } }, - -{ "andi.", OP(28), OP_MASK, PPCCOM, { RA, RS, UI } }, -{ "andil.", OP(28), OP_MASK, PWRCOM, { RA, RS, UI } }, - -{ "andis.", OP(29), OP_MASK, PPCCOM, { RA, RS, UI } }, -{ "andiu.", OP(29), OP_MASK, PWRCOM, { RA, RS, UI } }, - -{ "rotldi", MD(30,0,0), MDMB_MASK, PPC64, { RA, RS, SH6 } }, -{ "clrldi", MD(30,0,0), MDSH_MASK, PPC64, { RA, RS, MB6 } }, -{ "rldicl", MD(30,0,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, -{ "rotldi.", MD(30,0,1), MDMB_MASK, PPC64, { RA, RS, SH6 } }, -{ "clrldi.", MD(30,0,1), MDSH_MASK, PPC64, { RA, RS, MB6 } }, -{ "rldicl.", MD(30,0,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, - -{ "rldicr", MD(30,1,0), MD_MASK, PPC64, { RA, RS, SH6, ME6 } }, -{ "rldicr.", MD(30,1,1), MD_MASK, PPC64, { RA, RS, SH6, ME6 } }, - -{ "rldic", MD(30,2,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, -{ "rldic.", MD(30,2,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, - -{ "rldimi", MD(30,3,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, -{ "rldimi.", MD(30,3,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, - -{ "rotld", MDS(30,8,0), MDSMB_MASK, PPC64, { RA, RS, RB } }, -{ "rldcl", MDS(30,8,0), MDS_MASK, PPC64, { RA, RS, RB, MB6 } }, -{ "rotld.", MDS(30,8,1), MDSMB_MASK, PPC64, { RA, RS, RB } }, -{ "rldcl.", MDS(30,8,1), MDS_MASK, PPC64, { RA, RS, RB, MB6 } }, - -{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, -{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, - -{ "cmpw", XOPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, -{ "cmpd", XOPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, -{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } }, -{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, - -{ "twlgt", XTO(31,4,TOLGT), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tlgt", XTO(31,4,TOLGT), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twllt", XTO(31,4,TOLLT), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tllt", XTO(31,4,TOLLT), XTO_MASK, PWRCOM, { RA, RB } }, -{ "tweq", XTO(31,4,TOEQ), XTO_MASK, PPCCOM, { RA, RB } }, -{ "teq", XTO(31,4,TOEQ), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twlge", XTO(31,4,TOLGE), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tlge", XTO(31,4,TOLGE), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twlnl", XTO(31,4,TOLNL), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tlnl", XTO(31,4,TOLNL), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twlle", XTO(31,4,TOLLE), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tlle", XTO(31,4,TOLLE), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twlng", XTO(31,4,TOLNG), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tlng", XTO(31,4,TOLNG), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twgt", XTO(31,4,TOGT), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tgt", XTO(31,4,TOGT), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twge", XTO(31,4,TOGE), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tge", XTO(31,4,TOGE), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twnl", XTO(31,4,TONL), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tnl", XTO(31,4,TONL), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twlt", XTO(31,4,TOLT), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tlt", XTO(31,4,TOLT), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twle", XTO(31,4,TOLE), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tle", XTO(31,4,TOLE), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twng", XTO(31,4,TONG), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tng", XTO(31,4,TONG), XTO_MASK, PWRCOM, { RA, RB } }, -{ "twne", XTO(31,4,TONE), XTO_MASK, PPCCOM, { RA, RB } }, -{ "tne", XTO(31,4,TONE), XTO_MASK, PWRCOM, { RA, RB } }, -{ "trap", XTO(31,4,TOU), 0xffffffff, PPCCOM, { 0 } }, -{ "tw", X(31,4), X_MASK, PPCCOM, { TO, RA, RB } }, -{ "t", X(31,4), X_MASK, PWRCOM, { TO, RA, RB } }, - -{ "subfc", XO(31,8,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sf", XO(31,8,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subc", XO(31,8,0,0), XO_MASK, PPC, { RT, RB, RA } }, -{ "subfc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sf.", XO(31,8,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RB, RA } }, -{ "subfco", XO(31,8,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sfo", XO(31,8,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subco", XO(31,8,1,0), XO_MASK, PPC, { RT, RB, RA } }, -{ "subfco.", XO(31,8,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sfo.", XO(31,8,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RB, RA } }, - -{ "mulhdu", XO(31,9,0,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "mulhdu.", XO(31,9,0,1), XO_MASK, PPC64, { RT, RA, RB } }, - -{ "addc", XO(31,10,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "a", XO(31,10,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addc.", XO(31,10,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "a.", XO(31,10,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addco", XO(31,10,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "ao", XO(31,10,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addco.", XO(31,10,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "ao.", XO(31,10,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, - -{ "mulhwu", XO(31,11,0,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "mulhwu.", XO(31,11,0,1), XO_MASK, PPC, { RT, RA, RB } }, - -{ "isellt", X(31,15), X_MASK, PPCISEL, { RT, RA, RB } }, -{ "iselgt", X(31,47), X_MASK, PPCISEL, { RT, RA, RB } }, -{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } }, -{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } }, - -{ "mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, { RT, FXM } }, -{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4 | COM, { RT } }, -{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } }, - -{ "lwarx", X(31,20), XEH_MASK, PPC, { RT, RA0, RB, EH } }, - -{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA0, RB } }, - -{ "icbt", X(31,22), X_MASK, BOOKE|PPCE300, { CT, RA, RB } }, -{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } }, - -{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA0, RB } }, -{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } }, - -{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } }, -{ "sl", XRC(31,24,0), X_MASK, PWRCOM, { RA, RS, RB } }, -{ "slw.", XRC(31,24,1), X_MASK, PPCCOM, { RA, RS, RB } }, -{ "sl.", XRC(31,24,1), X_MASK, PWRCOM, { RA, RS, RB } }, - -{ "cntlzw", XRC(31,26,0), XRB_MASK, PPCCOM, { RA, RS } }, -{ "cntlz", XRC(31,26,0), XRB_MASK, PWRCOM, { RA, RS } }, -{ "cntlzw.", XRC(31,26,1), XRB_MASK, PPCCOM, { RA, RS } }, -{ "cntlz.", XRC(31,26,1), XRB_MASK, PWRCOM, { RA, RS } }, - -{ "sld", XRC(31,27,0), X_MASK, PPC64, { RA, RS, RB } }, -{ "sld.", XRC(31,27,1), X_MASK, PPC64, { RA, RS, RB } }, - -{ "and", XRC(31,28,0), X_MASK, COM, { RA, RS, RB } }, -{ "and.", XRC(31,28,1), X_MASK, COM, { RA, RS, RB } }, - -{ "maskg", XRC(31,29,0), X_MASK, M601, { RA, RS, RB } }, -{ "maskg.", XRC(31,29,1), X_MASK, M601, { RA, RS, RB } }, - -{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } }, - -{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "cmplw", XOPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, -{ "cmpld", XOPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, -{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } }, -{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, - -{ "subf", XO(31,40,0,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "sub", XO(31,40,0,0), XO_MASK, PPC, { RT, RB, RA } }, -{ "subf.", XO(31,40,0,1), XO_MASK, PPC, { RT, RA, RB } }, -{ "sub.", XO(31,40,0,1), XO_MASK, PPC, { RT, RB, RA } }, -{ "subfo", XO(31,40,1,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "subo", XO(31,40,1,0), XO_MASK, PPC, { RT, RB, RA } }, -{ "subfo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RA, RB } }, -{ "subo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RB, RA } }, - -{ "ldux", X(31,53), X_MASK, PPC64, { RT, RAL, RB } }, - -{ "dcbst", X(31,54), XRT_MASK, PPC, { RA, RB } }, - -{ "lwzux", X(31,55), X_MASK, PPCCOM, { RT, RAL, RB } }, -{ "lux", X(31,55), X_MASK, PWRCOM, { RT, RA, RB } }, - -{ "dcbste", X(31,62), XRT_MASK, BOOKE64, { RA, RB } }, - -{ "lwzuxe", X(31,63), X_MASK, BOOKE64, { RT, RAL, RB } }, - -{ "cntlzd", XRC(31,58,0), XRB_MASK, PPC64, { RA, RS } }, -{ "cntlzd.", XRC(31,58,1), XRB_MASK, PPC64, { RA, RS } }, - -{ "andc", XRC(31,60,0), X_MASK, COM, { RA, RS, RB } }, -{ "andc.", XRC(31,60,1), X_MASK, COM, { RA, RS, RB } }, - -{ "tdlgt", XTO(31,68,TOLGT), XTO_MASK, PPC64, { RA, RB } }, -{ "tdllt", XTO(31,68,TOLLT), XTO_MASK, PPC64, { RA, RB } }, -{ "tdeq", XTO(31,68,TOEQ), XTO_MASK, PPC64, { RA, RB } }, -{ "tdlge", XTO(31,68,TOLGE), XTO_MASK, PPC64, { RA, RB } }, -{ "tdlnl", XTO(31,68,TOLNL), XTO_MASK, PPC64, { RA, RB } }, -{ "tdlle", XTO(31,68,TOLLE), XTO_MASK, PPC64, { RA, RB } }, -{ "tdlng", XTO(31,68,TOLNG), XTO_MASK, PPC64, { RA, RB } }, -{ "tdgt", XTO(31,68,TOGT), XTO_MASK, PPC64, { RA, RB } }, -{ "tdge", XTO(31,68,TOGE), XTO_MASK, PPC64, { RA, RB } }, -{ "tdnl", XTO(31,68,TONL), XTO_MASK, PPC64, { RA, RB } }, -{ "tdlt", XTO(31,68,TOLT), XTO_MASK, PPC64, { RA, RB } }, -{ "tdle", XTO(31,68,TOLE), XTO_MASK, PPC64, { RA, RB } }, -{ "tdng", XTO(31,68,TONG), XTO_MASK, PPC64, { RA, RB } }, -{ "tdne", XTO(31,68,TONE), XTO_MASK, PPC64, { RA, RB } }, -{ "td", X(31,68), X_MASK, PPC64, { TO, RA, RB } }, - -{ "mulhd", XO(31,73,0,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "mulhd.", XO(31,73,0,1), XO_MASK, PPC64, { RT, RA, RB } }, - -{ "mulhw", XO(31,75,0,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "mulhw.", XO(31,75,0,1), XO_MASK, PPC, { RT, RA, RB } }, - -{ "dlmzb", XRC(31,78,0), X_MASK, PPC403|PPC440, { RA, RS, RB } }, -{ "dlmzb.", XRC(31,78,1), X_MASK, PPC403|PPC440, { RA, RS, RB } }, - -{ "mtsrd", X(31,82), XRB_MASK|(1<<20), PPC64, { SR, RS } }, - -{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } }, - -{ "ldarx", X(31,84), XEH_MASK, PPC64, { RT, RA0, RB, EH } }, - -{ "dcbfl", XOPL(31,86,1), XRT_MASK, POWER5, { RA, RB } }, -{ "dcbf", X(31,86), XLRT_MASK, PPC, { RA, RB, L } }, - -{ "lbzx", X(31,87), X_MASK, COM, { RT, RA0, RB } }, - -{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } }, - -{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } }, -{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } }, -{ "nego", XO(31,104,1,0), XORB_MASK, COM, { RT, RA } }, -{ "nego.", XO(31,104,1,1), XORB_MASK, COM, { RT, RA } }, - -{ "mul", XO(31,107,0,0), XO_MASK, M601, { RT, RA, RB } }, -{ "mul.", XO(31,107,0,1), XO_MASK, M601, { RT, RA, RB } }, -{ "mulo", XO(31,107,1,0), XO_MASK, M601, { RT, RA, RB } }, -{ "mulo.", XO(31,107,1,1), XO_MASK, M601, { RT, RA, RB } }, - -{ "mtsrdin", X(31,114), XRA_MASK, PPC64, { RS, RB } }, - -{ "clf", X(31,118), XTO_MASK, POWER, { RA, RB } }, - -{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } }, - -{ "popcntb", X(31,122), XRB_MASK, POWER5, { RA, RS } }, - -{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } }, -{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } }, -{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } }, -{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } }, - -{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } }, - -{ "wrtee", X(31,131), XRARB_MASK, PPC403 | BOOKE, { RS } }, - -{ "dcbtstls",X(31,134), X_MASK, PPCCHLK, { CT, RA, RB }}, - -{ "subfe", XO(31,136,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sfe", XO(31,136,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subfe.", XO(31,136,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sfe.", XO(31,136,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subfeo", XO(31,136,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sfeo", XO(31,136,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "subfeo.", XO(31,136,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "sfeo.", XO(31,136,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, - -{ "adde", XO(31,138,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "ae", XO(31,138,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "adde.", XO(31,138,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "ae.", XO(31,138,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addeo", XO(31,138,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "aeo", XO(31,138,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addeo.", XO(31,138,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "aeo.", XO(31,138,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, - -{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }}, - -{ "mtocrf", XFXM(31,144,0,1), XFXFXM_MASK, COM, { FXM, RS } }, -{ "mtcr", XFXM(31,144,0xff,0), XRARB_MASK, COM, { RS }}, -{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } }, - -{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, - -{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA0, RB } }, - -{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA0, RB } }, - -{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA0, RB } }, -{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } }, - -{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } }, -{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } }, - -{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } }, -{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } }, - -{ "prtyw", X(31,154), XRB_MASK, POWER6, { RA, RS } }, - -{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } }, - -{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }}, -{ "dcbtlse", X(31,174), X_MASK, PPCCHLK64, { CT, RA, RB }}, - -{ "mtmsrd", X(31,178), XRLARB_MASK, PPC64, { RS, A_L } }, - -{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } }, - -{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } }, -{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA0, RB } }, - -{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } }, -{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } }, - -{ "prtyd", X(31,186), XRB_MASK, POWER6, { RA, RS } }, - -{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } }, - -{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfze", XO(31,200,0,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "subfze.", XO(31,200,0,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfze.", XO(31,200,0,1), XORB_MASK, PWRCOM, { RT, RA } }, -{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfzeo", XO(31,200,1,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfzeo.", XO(31,200,1,1), XORB_MASK, PWRCOM, { RT, RA } }, - -{ "addze", XO(31,202,0,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "aze", XO(31,202,0,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "addze.", XO(31,202,0,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "aze.", XO(31,202,0,1), XORB_MASK, PWRCOM, { RT, RA } }, -{ "addzeo", XO(31,202,1,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "azeo", XO(31,202,1,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "azeo.", XO(31,202,1,1), XORB_MASK, PWRCOM, { RT, RA } }, - -{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } }, - -{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA0, RB } }, - -{ "stbx", X(31,215), X_MASK, COM, { RS, RA0, RB } }, - -{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } }, -{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } }, - -{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } }, -{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } }, - -{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }}, - -{ "subfme", XO(31,232,0,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfme", XO(31,232,0,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "subfme.", XO(31,232,0,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfme.", XO(31,232,0,1), XORB_MASK, PWRCOM, { RT, RA } }, -{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfmeo", XO(31,232,1,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "sfmeo.", XO(31,232,1,1), XORB_MASK, PWRCOM, { RT, RA } }, - -{ "mulld", XO(31,233,0,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "mulld.", XO(31,233,0,1), XO_MASK, PPC64, { RT, RA, RB } }, -{ "mulldo", XO(31,233,1,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "mulldo.", XO(31,233,1,1), XO_MASK, PPC64, { RT, RA, RB } }, - -{ "addme", XO(31,234,0,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "ame", XO(31,234,0,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "addme.", XO(31,234,0,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "ame.", XO(31,234,0,1), XORB_MASK, PWRCOM, { RT, RA } }, -{ "addmeo", XO(31,234,1,0), XORB_MASK, PPCCOM, { RT, RA } }, -{ "ameo", XO(31,234,1,0), XORB_MASK, PWRCOM, { RT, RA } }, -{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPCCOM, { RT, RA } }, -{ "ameo.", XO(31,234,1,1), XORB_MASK, PWRCOM, { RT, RA } }, - -{ "mullw", XO(31,235,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "muls", XO(31,235,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "mullw.", XO(31,235,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "muls.", XO(31,235,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "mullwo", XO(31,235,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "mulso", XO(31,235,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "mullwo.", XO(31,235,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "mulso.", XO(31,235,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, - -{ "icblce", X(31,238), X_MASK, PPCCHLK64, { CT, RA, RB }}, -{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } }, -{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } }, - -{ "dcbtst", X(31,246), X_MASK, PPC, { CT, RA, RB } }, - -{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } }, - -{ "slliq", XRC(31,248,0), X_MASK, M601, { RA, RS, SH } }, -{ "slliq.", XRC(31,248,1), X_MASK, M601, { RA, RS, SH } }, - -{ "dcbtste", X(31,253), X_MASK, BOOKE64, { CT, RA, RB } }, - -{ "stbuxe", X(31,255), X_MASK, BOOKE64, { RS, RAS, RB } }, - -{ "mfdcrx", X(31,259), X_MASK, BOOKE, { RS, RA } }, - -{ "doz", XO(31,264,0,0), XO_MASK, M601, { RT, RA, RB } }, -{ "doz.", XO(31,264,0,1), XO_MASK, M601, { RT, RA, RB } }, -{ "dozo", XO(31,264,1,0), XO_MASK, M601, { RT, RA, RB } }, -{ "dozo.", XO(31,264,1,1), XO_MASK, M601, { RT, RA, RB } }, - -{ "add", XO(31,266,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "cax", XO(31,266,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "add.", XO(31,266,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "cax.", XO(31,266,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addo", XO(31,266,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "caxo", XO(31,266,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, -{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, -{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, - -{ "tlbiel", X(31,274), XRTLRA_MASK, POWER4, { RB, L } }, - -{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } }, - -{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, -{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, - -{ "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } }, - -{ "lhzx", X(31,279), X_MASK, COM, { RT, RA0, RB } }, - -{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } }, -{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } }, - -{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } }, - -{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } }, -{ "tlbi", X(31,306), XRT_MASK, POWER, { RA0, RB } }, - -{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } }, - -{ "lhzux", X(31,311), X_MASK, COM, { RT, RAL, RB } }, - -{ "xor", XRC(31,316,0), X_MASK, COM, { RA, RS, RB } }, -{ "xor.", XRC(31,316,1), X_MASK, COM, { RA, RS, RB } }, - -{ "lhzuxe", X(31,319), X_MASK, BOOKE64, { RT, RAL, RB } }, - -{ "mfexisr", XSPR(31,323,64), XSPR_MASK, PPC403, { RT } }, -{ "mfexier", XSPR(31,323,66), XSPR_MASK, PPC403, { RT } }, -{ "mfbr0", XSPR(31,323,128), XSPR_MASK, PPC403, { RT } }, -{ "mfbr1", XSPR(31,323,129), XSPR_MASK, PPC403, { RT } }, -{ "mfbr2", XSPR(31,323,130), XSPR_MASK, PPC403, { RT } }, -{ "mfbr3", XSPR(31,323,131), XSPR_MASK, PPC403, { RT } }, -{ "mfbr4", XSPR(31,323,132), XSPR_MASK, PPC403, { RT } }, -{ "mfbr5", XSPR(31,323,133), XSPR_MASK, PPC403, { RT } }, -{ "mfbr6", XSPR(31,323,134), XSPR_MASK, PPC403, { RT } }, -{ "mfbr7", XSPR(31,323,135), XSPR_MASK, PPC403, { RT } }, -{ "mfbear", XSPR(31,323,144), XSPR_MASK, PPC403, { RT } }, -{ "mfbesr", XSPR(31,323,145), XSPR_MASK, PPC403, { RT } }, -{ "mfiocr", XSPR(31,323,160), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacr0", XSPR(31,323,192), XSPR_MASK, PPC403, { RT } }, -{ "mfdmact0", XSPR(31,323,193), XSPR_MASK, PPC403, { RT } }, -{ "mfdmada0", XSPR(31,323,194), XSPR_MASK, PPC403, { RT } }, -{ "mfdmasa0", XSPR(31,323,195), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacc0", XSPR(31,323,196), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacr1", XSPR(31,323,200), XSPR_MASK, PPC403, { RT } }, -{ "mfdmact1", XSPR(31,323,201), XSPR_MASK, PPC403, { RT } }, -{ "mfdmada1", XSPR(31,323,202), XSPR_MASK, PPC403, { RT } }, -{ "mfdmasa1", XSPR(31,323,203), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacc1", XSPR(31,323,204), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacr2", XSPR(31,323,208), XSPR_MASK, PPC403, { RT } }, -{ "mfdmact2", XSPR(31,323,209), XSPR_MASK, PPC403, { RT } }, -{ "mfdmada2", XSPR(31,323,210), XSPR_MASK, PPC403, { RT } }, -{ "mfdmasa2", XSPR(31,323,211), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacc2", XSPR(31,323,212), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacr3", XSPR(31,323,216), XSPR_MASK, PPC403, { RT } }, -{ "mfdmact3", XSPR(31,323,217), XSPR_MASK, PPC403, { RT } }, -{ "mfdmada3", XSPR(31,323,218), XSPR_MASK, PPC403, { RT } }, -{ "mfdmasa3", XSPR(31,323,219), XSPR_MASK, PPC403, { RT } }, -{ "mfdmacc3", XSPR(31,323,220), XSPR_MASK, PPC403, { RT } }, -{ "mfdmasr", XSPR(31,323,224), XSPR_MASK, PPC403, { RT } }, -{ "mfdcr", X(31,323), X_MASK, PPC403 | BOOKE, { RT, SPR } }, - -{ "div", XO(31,331,0,0), XO_MASK, M601, { RT, RA, RB } }, -{ "div.", XO(31,331,0,1), XO_MASK, M601, { RT, RA, RB } }, -{ "divo", XO(31,331,1,0), XO_MASK, M601, { RT, RA, RB } }, -{ "divo.", XO(31,331,1,1), XO_MASK, M601, { RT, RA, RB } }, - -{ "mfpmr", X(31,334), X_MASK, PPCPMR, { RT, PMR }}, - -{ "mfmq", XSPR(31,339,0), XSPR_MASK, M601, { RT } }, -{ "mfxer", XSPR(31,339,1), XSPR_MASK, COM, { RT } }, -{ "mfrtcu", XSPR(31,339,4), XSPR_MASK, COM, { RT } }, -{ "mfrtcl", XSPR(31,339,5), XSPR_MASK, COM, { RT } }, -{ "mfdec", XSPR(31,339,6), XSPR_MASK, MFDEC1, { RT } }, -{ "mfdec", XSPR(31,339,22), XSPR_MASK, MFDEC2, { RT } }, -{ "mflr", XSPR(31,339,8), XSPR_MASK, COM, { RT } }, -{ "mfctr", XSPR(31,339,9), XSPR_MASK, COM, { RT } }, -{ "mftid", XSPR(31,339,17), XSPR_MASK, POWER, { RT } }, -{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, COM, { RT } }, -{ "mfdar", XSPR(31,339,19), XSPR_MASK, COM, { RT } }, -{ "mfsdr0", XSPR(31,339,24), XSPR_MASK, POWER, { RT } }, -{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } }, -{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } }, -{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } }, -{ "mfcfar", XSPR(31,339,28), XSPR_MASK, POWER6, { RT } }, -{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } }, -{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } }, -{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } }, -{ "mfcsrr1", XSPR(31,339,59), XSPR_MASK, BOOKE, { RT } }, -{ "mfdear", XSPR(31,339,61), XSPR_MASK, BOOKE, { RT } }, -{ "mfdear", XSPR(31,339,981), XSPR_MASK, PPC403, { RT } }, -{ "mfesr", XSPR(31,339,62), XSPR_MASK, BOOKE, { RT } }, -{ "mfesr", XSPR(31,339,980), XSPR_MASK, PPC403, { RT } }, -{ "mfivpr", XSPR(31,339,63), XSPR_MASK, BOOKE, { RT } }, -{ "mfcmpa", XSPR(31,339,144), XSPR_MASK, PPC860, { RT } }, -{ "mfcmpb", XSPR(31,339,145), XSPR_MASK, PPC860, { RT } }, -{ "mfcmpc", XSPR(31,339,146), XSPR_MASK, PPC860, { RT } }, -{ "mfcmpd", XSPR(31,339,147), XSPR_MASK, PPC860, { RT } }, -{ "mficr", XSPR(31,339,148), XSPR_MASK, PPC860, { RT } }, -{ "mfder", XSPR(31,339,149), XSPR_MASK, PPC860, { RT } }, -{ "mfcounta", XSPR(31,339,150), XSPR_MASK, PPC860, { RT } }, -{ "mfcountb", XSPR(31,339,151), XSPR_MASK, PPC860, { RT } }, -{ "mfcmpe", XSPR(31,339,152), XSPR_MASK, PPC860, { RT } }, -{ "mfcmpf", XSPR(31,339,153), XSPR_MASK, PPC860, { RT } }, -{ "mfcmpg", XSPR(31,339,154), XSPR_MASK, PPC860, { RT } }, -{ "mfcmph", XSPR(31,339,155), XSPR_MASK, PPC860, { RT } }, -{ "mflctrl1", XSPR(31,339,156), XSPR_MASK, PPC860, { RT } }, -{ "mflctrl2", XSPR(31,339,157), XSPR_MASK, PPC860, { RT } }, -{ "mfictrl", XSPR(31,339,158), XSPR_MASK, PPC860, { RT } }, -{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } }, -{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } }, -{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } }, -{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } }, -{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, -{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } }, -{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, -{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } }, -{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } }, -{ "mfsprg", XSPR(31,339,256), XSPRG_MASK, PPC, { RT, SPRG } }, -{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } }, -{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } }, -{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } }, -{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } }, -{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405 | BOOKE, { RT } }, -{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405 | BOOKE, { RT } }, -{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405 | BOOKE, { RT } }, -{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405 | BOOKE, { RT } }, -{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } }, -{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } }, -{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } }, -{ "mfpvr", XSPR(31,339,287), XSPR_MASK, PPC, { RT } }, -{ "mfdbsr", XSPR(31,339,304), XSPR_MASK, BOOKE, { RT } }, -{ "mfdbsr", XSPR(31,339,1008), XSPR_MASK, PPC403, { RT } }, -{ "mfdbcr0", XSPR(31,339,308), XSPR_MASK, BOOKE, { RT } }, -{ "mfdbcr0", XSPR(31,339,1010), XSPR_MASK, PPC405, { RT } }, -{ "mfdbcr1", XSPR(31,339,309), XSPR_MASK, BOOKE, { RT } }, -{ "mfdbcr1", XSPR(31,339,957), XSPR_MASK, PPC405, { RT } }, -{ "mfdbcr2", XSPR(31,339,310), XSPR_MASK, BOOKE, { RT } }, -{ "mfiac1", XSPR(31,339,312), XSPR_MASK, BOOKE, { RT } }, -{ "mfiac1", XSPR(31,339,1012), XSPR_MASK, PPC403, { RT } }, -{ "mfiac2", XSPR(31,339,313), XSPR_MASK, BOOKE, { RT } }, -{ "mfiac2", XSPR(31,339,1013), XSPR_MASK, PPC403, { RT } }, -{ "mfiac3", XSPR(31,339,314), XSPR_MASK, BOOKE, { RT } }, -{ "mfiac3", XSPR(31,339,948), XSPR_MASK, PPC405, { RT } }, -{ "mfiac4", XSPR(31,339,315), XSPR_MASK, BOOKE, { RT } }, -{ "mfiac4", XSPR(31,339,949), XSPR_MASK, PPC405, { RT } }, -{ "mfdac1", XSPR(31,339,316), XSPR_MASK, BOOKE, { RT } }, -{ "mfdac1", XSPR(31,339,1014), XSPR_MASK, PPC403, { RT } }, -{ "mfdac2", XSPR(31,339,317), XSPR_MASK, BOOKE, { RT } }, -{ "mfdac2", XSPR(31,339,1015), XSPR_MASK, PPC403, { RT } }, -{ "mfdvc1", XSPR(31,339,318), XSPR_MASK, BOOKE, { RT } }, -{ "mfdvc1", XSPR(31,339,950), XSPR_MASK, PPC405, { RT } }, -{ "mfdvc2", XSPR(31,339,319), XSPR_MASK, BOOKE, { RT } }, -{ "mfdvc2", XSPR(31,339,951), XSPR_MASK, PPC405, { RT } }, -{ "mftsr", XSPR(31,339,336), XSPR_MASK, BOOKE, { RT } }, -{ "mftsr", XSPR(31,339,984), XSPR_MASK, PPC403, { RT } }, -{ "mftcr", XSPR(31,339,340), XSPR_MASK, BOOKE, { RT } }, -{ "mftcr", XSPR(31,339,986), XSPR_MASK, PPC403, { RT } }, -{ "mfivor0", XSPR(31,339,400), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor1", XSPR(31,339,401), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor2", XSPR(31,339,402), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor3", XSPR(31,339,403), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor4", XSPR(31,339,404), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor5", XSPR(31,339,405), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor6", XSPR(31,339,406), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor7", XSPR(31,339,407), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor8", XSPR(31,339,408), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor9", XSPR(31,339,409), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor10", XSPR(31,339,410), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor11", XSPR(31,339,411), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor12", XSPR(31,339,412), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor13", XSPR(31,339,413), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor14", XSPR(31,339,414), XSPR_MASK, BOOKE, { RT } }, -{ "mfivor15", XSPR(31,339,415), XSPR_MASK, BOOKE, { RT } }, -{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } }, -{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } }, -{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } }, -{ "mfivor32", XSPR(31,339,528), XSPR_MASK, PPCSPE, { RT } }, -{ "mfivor33", XSPR(31,339,529), XSPR_MASK, PPCSPE, { RT } }, -{ "mfivor34", XSPR(31,339,530), XSPR_MASK, PPCSPE, { RT } }, -{ "mfivor35", XSPR(31,339,531), XSPR_MASK, PPCPMR, { RT } }, -{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, -{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, -{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, -{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, -{ "mfic_cst", XSPR(31,339,560), XSPR_MASK, PPC860, { RT } }, -{ "mfic_adr", XSPR(31,339,561), XSPR_MASK, PPC860, { RT } }, -{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } }, -{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } }, -{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } }, -{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } }, -{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } }, -{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } }, -{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } }, -{ "mfmcar", XSPR(31,339,573), XSPR_MASK, PPCRFMCI, { RT } }, -{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } }, -{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } }, -{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_ctr", XSPR(31,339,784), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_ap", XSPR(31,339,786), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_epn", XSPR(31,339,787), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_twc", XSPR(31,339,789), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_rpn", XSPR(31,339,790), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_ctr", XSPR(31,339,792), XSPR_MASK, PPC860, { RT } }, -{ "mfm_casid", XSPR(31,339,793), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_ap", XSPR(31,339,794), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_epn", XSPR(31,339,795), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_twb", XSPR(31,339,796), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_twc", XSPR(31,339,797), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_rpn", XSPR(31,339,798), XSPR_MASK, PPC860, { RT } }, -{ "mfm_tw", XSPR(31,339,799), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_dbcam", XSPR(31,339,816), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_dbram0",XSPR(31,339,817), XSPR_MASK, PPC860, { RT } }, -{ "mfmi_dbram1",XSPR(31,339,818), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_dbcam", XSPR(31,339,824), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_dbram0",XSPR(31,339,825), XSPR_MASK, PPC860, { RT } }, -{ "mfmd_dbram1",XSPR(31,339,826), XSPR_MASK, PPC860, { RT } }, -{ "mfummcr0", XSPR(31,339,936), XSPR_MASK, PPC750, { RT } }, -{ "mfupmc1", XSPR(31,339,937), XSPR_MASK, PPC750, { RT } }, -{ "mfupmc2", XSPR(31,339,938), XSPR_MASK, PPC750, { RT } }, -{ "mfusia", XSPR(31,339,939), XSPR_MASK, PPC750, { RT } }, -{ "mfummcr1", XSPR(31,339,940), XSPR_MASK, PPC750, { RT } }, -{ "mfupmc3", XSPR(31,339,941), XSPR_MASK, PPC750, { RT } }, -{ "mfupmc4", XSPR(31,339,942), XSPR_MASK, PPC750, { RT } }, -{ "mfzpr", XSPR(31,339,944), XSPR_MASK, PPC403, { RT } }, -{ "mfccr0", XSPR(31,339,947), XSPR_MASK, PPC405, { RT } }, -{ "mfmmcr0", XSPR(31,339,952), XSPR_MASK, PPC750, { RT } }, -{ "mfpmc1", XSPR(31,339,953), XSPR_MASK, PPC750, { RT } }, -{ "mfsgr", XSPR(31,339,953), XSPR_MASK, PPC403, { RT } }, -{ "mfpmc2", XSPR(31,339,954), XSPR_MASK, PPC750, { RT } }, -{ "mfdcwr", XSPR(31,339,954), XSPR_MASK, PPC403, { RT } }, -{ "mfsia", XSPR(31,339,955), XSPR_MASK, PPC750, { RT } }, -{ "mfsler", XSPR(31,339,955), XSPR_MASK, PPC405, { RT } }, -{ "mfmmcr1", XSPR(31,339,956), XSPR_MASK, PPC750, { RT } }, -{ "mfsu0r", XSPR(31,339,956), XSPR_MASK, PPC405, { RT } }, -{ "mfpmc3", XSPR(31,339,957), XSPR_MASK, PPC750, { RT } }, -{ "mfpmc4", XSPR(31,339,958), XSPR_MASK, PPC750, { RT } }, -{ "mficdbdr", XSPR(31,339,979), XSPR_MASK, PPC403, { RT } }, -{ "mfevpr", XSPR(31,339,982), XSPR_MASK, PPC403, { RT } }, -{ "mfcdbcr", XSPR(31,339,983), XSPR_MASK, PPC403, { RT } }, -{ "mfpit", XSPR(31,339,987), XSPR_MASK, PPC403, { RT } }, -{ "mftbhi", XSPR(31,339,988), XSPR_MASK, PPC403, { RT } }, -{ "mftblo", XSPR(31,339,989), XSPR_MASK, PPC403, { RT } }, -{ "mfsrr2", XSPR(31,339,990), XSPR_MASK, PPC403, { RT } }, -{ "mfsrr3", XSPR(31,339,991), XSPR_MASK, PPC403, { RT } }, -{ "mfl2cr", XSPR(31,339,1017), XSPR_MASK, PPC750, { RT } }, -{ "mfdccr", XSPR(31,339,1018), XSPR_MASK, PPC403, { RT } }, -{ "mficcr", XSPR(31,339,1019), XSPR_MASK, PPC403, { RT } }, -{ "mfictc", XSPR(31,339,1019), XSPR_MASK, PPC750, { RT } }, -{ "mfpbl1", XSPR(31,339,1020), XSPR_MASK, PPC403, { RT } }, -{ "mfthrm1", XSPR(31,339,1020), XSPR_MASK, PPC750, { RT } }, -{ "mfpbu1", XSPR(31,339,1021), XSPR_MASK, PPC403, { RT } }, -{ "mfthrm2", XSPR(31,339,1021), XSPR_MASK, PPC750, { RT } }, -{ "mfpbl2", XSPR(31,339,1022), XSPR_MASK, PPC403, { RT } }, -{ "mfthrm3", XSPR(31,339,1022), XSPR_MASK, PPC750, { RT } }, -{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } }, -{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, - -{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA0, RB } }, - -{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, -{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, - -{ "lhax", X(31,343), X_MASK, COM, { RT, RA0, RB } }, - -{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, -{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, - -{ "dccci", X(31,454), XRT_MASK, PPC403|PPC440, { RA, RB } }, - -{ "abs", XO(31,360,0,0), XORB_MASK, M601, { RT, RA } }, -{ "abs.", XO(31,360,0,1), XORB_MASK, M601, { RT, RA } }, -{ "abso", XO(31,360,1,0), XORB_MASK, M601, { RT, RA } }, -{ "abso.", XO(31,360,1,1), XORB_MASK, M601, { RT, RA } }, - -{ "divs", XO(31,363,0,0), XO_MASK, M601, { RT, RA, RB } }, -{ "divs.", XO(31,363,0,1), XO_MASK, M601, { RT, RA, RB } }, -{ "divso", XO(31,363,1,0), XO_MASK, M601, { RT, RA, RB } }, -{ "divso.", XO(31,363,1,1), XO_MASK, M601, { RT, RA, RB } }, - -{ "tlbia", X(31,370), 0xffffffff, PPC, { 0 } }, - -{ "lwaux", X(31,373), X_MASK, PPC64, { RT, RAL, RB } }, - -{ "lhaux", X(31,375), X_MASK, COM, { RT, RAL, RB } }, - -{ "lhauxe", X(31,383), X_MASK, BOOKE64, { RT, RAL, RB } }, - -{ "mtdcrx", X(31,387), X_MASK, BOOKE, { RA, RS } }, - -{ "dcblc", X(31,390), X_MASK, PPCCHLK, { CT, RA, RB }}, - -{ "subfe64", XO(31,392,0,0), XO_MASK, BOOKE64, { RT, RA, RB } }, -{ "subfe64o",XO(31,392,1,0), XO_MASK, BOOKE64, { RT, RA, RB } }, - -{ "adde64", XO(31,394,0,0), XO_MASK, BOOKE64, { RT, RA, RB } }, -{ "adde64o", XO(31,394,1,0), XO_MASK, BOOKE64, { RT, RA, RB } }, - -{ "dcblce", X(31,398), X_MASK, PPCCHLK64, { CT, RA, RB }}, - -{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } }, - -{ "sthx", X(31,407), X_MASK, COM, { RS, RA0, RB } }, - -{ "cmpb", X(31,508), X_MASK, POWER6, { RA, RS, RB } }, - -{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } }, - -{ "lfdpx", X(31,791), X_MASK, POWER6, { FRT, RA, RB } }, - -{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } }, - -{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } }, - -{ "stfdpx", X(31,919), X_MASK, POWER6, { FRS, RA, RB } }, - -{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } }, - -{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } }, -{ "orc.", XRC(31,412,1), X_MASK, COM, { RA, RS, RB } }, - -{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } }, -{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } }, - -{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } }, - -{ "ecowx", X(31,438), X_MASK, PPC, { RT, RA, RB } }, - -{ "sthux", X(31,439), X_MASK, COM, { RS, RAS, RB } }, - -{ "sthuxe", X(31,447), X_MASK, BOOKE64, { RS, RAS, RB } }, - -{ "cctpl", 0x7c210b78, 0xffffffff, CELL, { 0 }}, -{ "cctpm", 0x7c421378, 0xffffffff, CELL, { 0 }}, -{ "cctph", 0x7c631b78, 0xffffffff, CELL, { 0 }}, -{ "db8cyc", 0x7f9ce378, 0xffffffff, CELL, { 0 }}, -{ "db10cyc", 0x7fbdeb78, 0xffffffff, CELL, { 0 }}, -{ "db12cyc", 0x7fdef378, 0xffffffff, CELL, { 0 }}, -{ "db16cyc", 0x7ffffb78, 0xffffffff, CELL, { 0 }}, -{ "mr", XRC(31,444,0), X_MASK, COM, { RA, RS, RBS } }, -{ "or", XRC(31,444,0), X_MASK, COM, { RA, RS, RB } }, -{ "mr.", XRC(31,444,1), X_MASK, COM, { RA, RS, RBS } }, -{ "or.", XRC(31,444,1), X_MASK, COM, { RA, RS, RB } }, - -{ "mtexisr", XSPR(31,451,64), XSPR_MASK, PPC403, { RS } }, -{ "mtexier", XSPR(31,451,66), XSPR_MASK, PPC403, { RS } }, -{ "mtbr0", XSPR(31,451,128), XSPR_MASK, PPC403, { RS } }, -{ "mtbr1", XSPR(31,451,129), XSPR_MASK, PPC403, { RS } }, -{ "mtbr2", XSPR(31,451,130), XSPR_MASK, PPC403, { RS } }, -{ "mtbr3", XSPR(31,451,131), XSPR_MASK, PPC403, { RS } }, -{ "mtbr4", XSPR(31,451,132), XSPR_MASK, PPC403, { RS } }, -{ "mtbr5", XSPR(31,451,133), XSPR_MASK, PPC403, { RS } }, -{ "mtbr6", XSPR(31,451,134), XSPR_MASK, PPC403, { RS } }, -{ "mtbr7", XSPR(31,451,135), XSPR_MASK, PPC403, { RS } }, -{ "mtbear", XSPR(31,451,144), XSPR_MASK, PPC403, { RS } }, -{ "mtbesr", XSPR(31,451,145), XSPR_MASK, PPC403, { RS } }, -{ "mtiocr", XSPR(31,451,160), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacr0", XSPR(31,451,192), XSPR_MASK, PPC403, { RS } }, -{ "mtdmact0", XSPR(31,451,193), XSPR_MASK, PPC403, { RS } }, -{ "mtdmada0", XSPR(31,451,194), XSPR_MASK, PPC403, { RS } }, -{ "mtdmasa0", XSPR(31,451,195), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacc0", XSPR(31,451,196), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacr1", XSPR(31,451,200), XSPR_MASK, PPC403, { RS } }, -{ "mtdmact1", XSPR(31,451,201), XSPR_MASK, PPC403, { RS } }, -{ "mtdmada1", XSPR(31,451,202), XSPR_MASK, PPC403, { RS } }, -{ "mtdmasa1", XSPR(31,451,203), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacc1", XSPR(31,451,204), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacr2", XSPR(31,451,208), XSPR_MASK, PPC403, { RS } }, -{ "mtdmact2", XSPR(31,451,209), XSPR_MASK, PPC403, { RS } }, -{ "mtdmada2", XSPR(31,451,210), XSPR_MASK, PPC403, { RS } }, -{ "mtdmasa2", XSPR(31,451,211), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacc2", XSPR(31,451,212), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacr3", XSPR(31,451,216), XSPR_MASK, PPC403, { RS } }, -{ "mtdmact3", XSPR(31,451,217), XSPR_MASK, PPC403, { RS } }, -{ "mtdmada3", XSPR(31,451,218), XSPR_MASK, PPC403, { RS } }, -{ "mtdmasa3", XSPR(31,451,219), XSPR_MASK, PPC403, { RS } }, -{ "mtdmacc3", XSPR(31,451,220), XSPR_MASK, PPC403, { RS } }, -{ "mtdmasr", XSPR(31,451,224), XSPR_MASK, PPC403, { RS } }, -{ "mtdcr", X(31,451), X_MASK, PPC403 | BOOKE, { SPR, RS } }, - -{ "subfze64",XO(31,456,0,0), XORB_MASK, BOOKE64, { RT, RA } }, -{ "subfze64o",XO(31,456,1,0), XORB_MASK, BOOKE64, { RT, RA } }, - -{ "divdu", XO(31,457,0,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "divdu.", XO(31,457,0,1), XO_MASK, PPC64, { RT, RA, RB } }, -{ "divduo", XO(31,457,1,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "divduo.", XO(31,457,1,1), XO_MASK, PPC64, { RT, RA, RB } }, - -{ "addze64", XO(31,458,0,0), XORB_MASK, BOOKE64, { RT, RA } }, -{ "addze64o",XO(31,458,1,0), XORB_MASK, BOOKE64, { RT, RA } }, - -{ "divwu", XO(31,459,0,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "divwu.", XO(31,459,0,1), XO_MASK, PPC, { RT, RA, RB } }, -{ "divwuo", XO(31,459,1,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "divwuo.", XO(31,459,1,1), XO_MASK, PPC, { RT, RA, RB } }, - -{ "mtmq", XSPR(31,467,0), XSPR_MASK, M601, { RS } }, -{ "mtxer", XSPR(31,467,1), XSPR_MASK, COM, { RS } }, -{ "mtlr", XSPR(31,467,8), XSPR_MASK, COM, { RS } }, -{ "mtctr", XSPR(31,467,9), XSPR_MASK, COM, { RS } }, -{ "mttid", XSPR(31,467,17), XSPR_MASK, POWER, { RS } }, -{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, COM, { RS } }, -{ "mtdar", XSPR(31,467,19), XSPR_MASK, COM, { RS } }, -{ "mtrtcu", XSPR(31,467,20), XSPR_MASK, COM, { RS } }, -{ "mtrtcl", XSPR(31,467,21), XSPR_MASK, COM, { RS } }, -{ "mtdec", XSPR(31,467,22), XSPR_MASK, COM, { RS } }, -{ "mtsdr0", XSPR(31,467,24), XSPR_MASK, POWER, { RS } }, -{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } }, -{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } }, -{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } }, -{ "mtcfar", XSPR(31,467,28), XSPR_MASK, POWER6, { RS } }, -{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } }, -{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } }, -{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } }, -{ "mtcsrr0", XSPR(31,467,58), XSPR_MASK, BOOKE, { RS } }, -{ "mtcsrr1", XSPR(31,467,59), XSPR_MASK, BOOKE, { RS } }, -{ "mtdear", XSPR(31,467,61), XSPR_MASK, BOOKE, { RS } }, -{ "mtdear", XSPR(31,467,981), XSPR_MASK, PPC403, { RS } }, -{ "mtesr", XSPR(31,467,62), XSPR_MASK, BOOKE, { RS } }, -{ "mtesr", XSPR(31,467,980), XSPR_MASK, PPC403, { RS } }, -{ "mtivpr", XSPR(31,467,63), XSPR_MASK, BOOKE, { RS } }, -{ "mtcmpa", XSPR(31,467,144), XSPR_MASK, PPC860, { RS } }, -{ "mtcmpb", XSPR(31,467,145), XSPR_MASK, PPC860, { RS } }, -{ "mtcmpc", XSPR(31,467,146), XSPR_MASK, PPC860, { RS } }, -{ "mtcmpd", XSPR(31,467,147), XSPR_MASK, PPC860, { RS } }, -{ "mticr", XSPR(31,467,148), XSPR_MASK, PPC860, { RS } }, -{ "mtder", XSPR(31,467,149), XSPR_MASK, PPC860, { RS } }, -{ "mtcounta", XSPR(31,467,150), XSPR_MASK, PPC860, { RS } }, -{ "mtcountb", XSPR(31,467,151), XSPR_MASK, PPC860, { RS } }, -{ "mtcmpe", XSPR(31,467,152), XSPR_MASK, PPC860, { RS } }, -{ "mtcmpf", XSPR(31,467,153), XSPR_MASK, PPC860, { RS } }, -{ "mtcmpg", XSPR(31,467,154), XSPR_MASK, PPC860, { RS } }, -{ "mtcmph", XSPR(31,467,155), XSPR_MASK, PPC860, { RS } }, -{ "mtlctrl1", XSPR(31,467,156), XSPR_MASK, PPC860, { RS } }, -{ "mtlctrl2", XSPR(31,467,157), XSPR_MASK, PPC860, { RS } }, -{ "mtictrl", XSPR(31,467,158), XSPR_MASK, PPC860, { RS } }, -{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } }, -{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } }, -{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } }, -{ "mtsprg", XSPR(31,467,256), XSPRG_MASK,PPC, { SPRG, RS } }, -{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } }, -{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } }, -{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } }, -{ "mtsprg3", XSPR(31,467,275), XSPR_MASK, PPC, { RS } }, -{ "mtsprg4", XSPR(31,467,276), XSPR_MASK, PPC405 | BOOKE, { RS } }, -{ "mtsprg5", XSPR(31,467,277), XSPR_MASK, PPC405 | BOOKE, { RS } }, -{ "mtsprg6", XSPR(31,467,278), XSPR_MASK, PPC405 | BOOKE, { RS } }, -{ "mtsprg7", XSPR(31,467,279), XSPR_MASK, PPC405 | BOOKE, { RS } }, -{ "mtasr", XSPR(31,467,280), XSPR_MASK, PPC64, { RS } }, -{ "mtear", XSPR(31,467,282), XSPR_MASK, PPC, { RS } }, -{ "mttbl", XSPR(31,467,284), XSPR_MASK, PPC, { RS } }, -{ "mttbu", XSPR(31,467,285), XSPR_MASK, PPC, { RS } }, -{ "mtdbsr", XSPR(31,467,304), XSPR_MASK, BOOKE, { RS } }, -{ "mtdbsr", XSPR(31,467,1008), XSPR_MASK, PPC403, { RS } }, -{ "mtdbcr0", XSPR(31,467,308), XSPR_MASK, BOOKE, { RS } }, -{ "mtdbcr0", XSPR(31,467,1010), XSPR_MASK, PPC405, { RS } }, -{ "mtdbcr1", XSPR(31,467,309), XSPR_MASK, BOOKE, { RS } }, -{ "mtdbcr1", XSPR(31,467,957), XSPR_MASK, PPC405, { RS } }, -{ "mtdbcr2", XSPR(31,467,310), XSPR_MASK, BOOKE, { RS } }, -{ "mtiac1", XSPR(31,467,312), XSPR_MASK, BOOKE, { RS } }, -{ "mtiac1", XSPR(31,467,1012), XSPR_MASK, PPC403, { RS } }, -{ "mtiac2", XSPR(31,467,313), XSPR_MASK, BOOKE, { RS } }, -{ "mtiac2", XSPR(31,467,1013), XSPR_MASK, PPC403, { RS } }, -{ "mtiac3", XSPR(31,467,314), XSPR_MASK, BOOKE, { RS } }, -{ "mtiac3", XSPR(31,467,948), XSPR_MASK, PPC405, { RS } }, -{ "mtiac4", XSPR(31,467,315), XSPR_MASK, BOOKE, { RS } }, -{ "mtiac4", XSPR(31,467,949), XSPR_MASK, PPC405, { RS } }, -{ "mtdac1", XSPR(31,467,316), XSPR_MASK, BOOKE, { RS } }, -{ "mtdac1", XSPR(31,467,1014), XSPR_MASK, PPC403, { RS } }, -{ "mtdac2", XSPR(31,467,317), XSPR_MASK, BOOKE, { RS } }, -{ "mtdac2", XSPR(31,467,1015), XSPR_MASK, PPC403, { RS } }, -{ "mtdvc1", XSPR(31,467,318), XSPR_MASK, BOOKE, { RS } }, -{ "mtdvc1", XSPR(31,467,950), XSPR_MASK, PPC405, { RS } }, -{ "mtdvc2", XSPR(31,467,319), XSPR_MASK, BOOKE, { RS } }, -{ "mtdvc2", XSPR(31,467,951), XSPR_MASK, PPC405, { RS } }, -{ "mttsr", XSPR(31,467,336), XSPR_MASK, BOOKE, { RS } }, -{ "mttsr", XSPR(31,467,984), XSPR_MASK, PPC403, { RS } }, -{ "mttcr", XSPR(31,467,340), XSPR_MASK, BOOKE, { RS } }, -{ "mttcr", XSPR(31,467,986), XSPR_MASK, PPC403, { RS } }, -{ "mtivor0", XSPR(31,467,400), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor1", XSPR(31,467,401), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor2", XSPR(31,467,402), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor3", XSPR(31,467,403), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor4", XSPR(31,467,404), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor5", XSPR(31,467,405), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor6", XSPR(31,467,406), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor7", XSPR(31,467,407), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor8", XSPR(31,467,408), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor9", XSPR(31,467,409), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor10", XSPR(31,467,410), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor11", XSPR(31,467,411), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor12", XSPR(31,467,412), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor13", XSPR(31,467,413), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor14", XSPR(31,467,414), XSPR_MASK, BOOKE, { RS } }, -{ "mtivor15", XSPR(31,467,415), XSPR_MASK, BOOKE, { RS } }, -{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } }, -{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } }, -{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } }, -{ "mtivor32", XSPR(31,467,528), XSPR_MASK, PPCSPE, { RS } }, -{ "mtivor33", XSPR(31,467,529), XSPR_MASK, PPCSPE, { RS } }, -{ "mtivor34", XSPR(31,467,530), XSPR_MASK, PPCSPE, { RS } }, -{ "mtivor35", XSPR(31,467,531), XSPR_MASK, PPCPMR, { RS } }, -{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, -{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, -{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, -{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, -{ "mtmcsrr0", XSPR(31,467,570), XSPR_MASK, PPCRFMCI, { RS } }, -{ "mtmcsrr1", XSPR(31,467,571), XSPR_MASK, PPCRFMCI, { RS } }, -{ "mtmcsr", XSPR(31,467,572), XSPR_MASK, PPCRFMCI, { RS } }, -{ "mtummcr0", XSPR(31,467,936), XSPR_MASK, PPC750, { RS } }, -{ "mtupmc1", XSPR(31,467,937), XSPR_MASK, PPC750, { RS } }, -{ "mtupmc2", XSPR(31,467,938), XSPR_MASK, PPC750, { RS } }, -{ "mtusia", XSPR(31,467,939), XSPR_MASK, PPC750, { RS } }, -{ "mtummcr1", XSPR(31,467,940), XSPR_MASK, PPC750, { RS } }, -{ "mtupmc3", XSPR(31,467,941), XSPR_MASK, PPC750, { RS } }, -{ "mtupmc4", XSPR(31,467,942), XSPR_MASK, PPC750, { RS } }, -{ "mtzpr", XSPR(31,467,944), XSPR_MASK, PPC403, { RS } }, -{ "mtccr0", XSPR(31,467,947), XSPR_MASK, PPC405, { RS } }, -{ "mtmmcr0", XSPR(31,467,952), XSPR_MASK, PPC750, { RS } }, -{ "mtsgr", XSPR(31,467,953), XSPR_MASK, PPC403, { RS } }, -{ "mtpmc1", XSPR(31,467,953), XSPR_MASK, PPC750, { RS } }, -{ "mtdcwr", XSPR(31,467,954), XSPR_MASK, PPC403, { RS } }, -{ "mtpmc2", XSPR(31,467,954), XSPR_MASK, PPC750, { RS } }, -{ "mtsler", XSPR(31,467,955), XSPR_MASK, PPC405, { RS } }, -{ "mtsia", XSPR(31,467,955), XSPR_MASK, PPC750, { RS } }, -{ "mtsu0r", XSPR(31,467,956), XSPR_MASK, PPC405, { RS } }, -{ "mtmmcr1", XSPR(31,467,956), XSPR_MASK, PPC750, { RS } }, -{ "mtpmc3", XSPR(31,467,957), XSPR_MASK, PPC750, { RS } }, -{ "mtpmc4", XSPR(31,467,958), XSPR_MASK, PPC750, { RS } }, -{ "mticdbdr", XSPR(31,467,979), XSPR_MASK, PPC403, { RS } }, -{ "mtevpr", XSPR(31,467,982), XSPR_MASK, PPC403, { RS } }, -{ "mtcdbcr", XSPR(31,467,983), XSPR_MASK, PPC403, { RS } }, -{ "mtpit", XSPR(31,467,987), XSPR_MASK, PPC403, { RS } }, -{ "mttbhi", XSPR(31,467,988), XSPR_MASK, PPC403, { RS } }, -{ "mttblo", XSPR(31,467,989), XSPR_MASK, PPC403, { RS } }, -{ "mtsrr2", XSPR(31,467,990), XSPR_MASK, PPC403, { RS } }, -{ "mtsrr3", XSPR(31,467,991), XSPR_MASK, PPC403, { RS } }, -{ "mtl2cr", XSPR(31,467,1017), XSPR_MASK, PPC750, { RS } }, -{ "mtdccr", XSPR(31,467,1018), XSPR_MASK, PPC403, { RS } }, -{ "mticcr", XSPR(31,467,1019), XSPR_MASK, PPC403, { RS } }, -{ "mtictc", XSPR(31,467,1019), XSPR_MASK, PPC750, { RS } }, -{ "mtpbl1", XSPR(31,467,1020), XSPR_MASK, PPC403, { RS } }, -{ "mtthrm1", XSPR(31,467,1020), XSPR_MASK, PPC750, { RS } }, -{ "mtpbu1", XSPR(31,467,1021), XSPR_MASK, PPC403, { RS } }, -{ "mtthrm2", XSPR(31,467,1021), XSPR_MASK, PPC750, { RS } }, -{ "mtpbl2", XSPR(31,467,1022), XSPR_MASK, PPC403, { RS } }, -{ "mtthrm3", XSPR(31,467,1022), XSPR_MASK, PPC750, { RS } }, -{ "mtpbu2", XSPR(31,467,1023), XSPR_MASK, PPC403, { RS } }, -{ "mtspr", X(31,467), X_MASK, COM, { SPR, RS } }, - -{ "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } }, - -{ "nand", XRC(31,476,0), X_MASK, COM, { RA, RS, RB } }, -{ "nand.", XRC(31,476,1), X_MASK, COM, { RA, RS, RB } }, - -{ "dcbie", X(31,478), XRT_MASK, BOOKE64, { RA, RB } }, - -{ "dcread", X(31,486), X_MASK, PPC403|PPC440, { RT, RA, RB }}, - -{ "mtpmr", X(31,462), X_MASK, PPCPMR, { PMR, RS }}, - -{ "icbtls", X(31,486), X_MASK, PPCCHLK, { CT, RA, RB }}, - -{ "nabs", XO(31,488,0,0), XORB_MASK, M601, { RT, RA } }, -{ "subfme64",XO(31,488,0,0), XORB_MASK, BOOKE64, { RT, RA } }, -{ "nabs.", XO(31,488,0,1), XORB_MASK, M601, { RT, RA } }, -{ "nabso", XO(31,488,1,0), XORB_MASK, M601, { RT, RA } }, -{ "subfme64o",XO(31,488,1,0), XORB_MASK, BOOKE64, { RT, RA } }, -{ "nabso.", XO(31,488,1,1), XORB_MASK, M601, { RT, RA } }, - -{ "divd", XO(31,489,0,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "divd.", XO(31,489,0,1), XO_MASK, PPC64, { RT, RA, RB } }, -{ "divdo", XO(31,489,1,0), XO_MASK, PPC64, { RT, RA, RB } }, -{ "divdo.", XO(31,489,1,1), XO_MASK, PPC64, { RT, RA, RB } }, - -{ "addme64", XO(31,490,0,0), XORB_MASK, BOOKE64, { RT, RA } }, -{ "addme64o",XO(31,490,1,0), XORB_MASK, BOOKE64, { RT, RA } }, - -{ "divw", XO(31,491,0,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "divw.", XO(31,491,0,1), XO_MASK, PPC, { RT, RA, RB } }, -{ "divwo", XO(31,491,1,0), XO_MASK, PPC, { RT, RA, RB } }, -{ "divwo.", XO(31,491,1,1), XO_MASK, PPC, { RT, RA, RB } }, - -{ "icbtlse", X(31,494), X_MASK, PPCCHLK64, { CT, RA, RB }}, - -{ "slbia", X(31,498), 0xffffffff, PPC64, { 0 } }, - -{ "cli", X(31,502), XRB_MASK, POWER, { RT, RA } }, - -{ "stdcxe.", XRC(31,511,1), X_MASK, BOOKE64, { RS, RA, RB } }, - -{ "mcrxr", X(31,512), XRARB_MASK|(3<<21), COM, { BF } }, - -{ "bblels", X(31,518), X_MASK, PPCBRLK, { 0 }}, -{ "mcrxr64", X(31,544), XRARB_MASK|(3<<21), BOOKE64, { BF } }, - -{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } }, - -{ "ldbrx", X(31,532), X_MASK, CELL, { RT, RA0, RB } }, - -{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA0, RB } }, -{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } }, - -{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA0, RB } }, -{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } }, - -{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA0, RB } }, - -{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } }, -{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } }, -{ "srw.", XRC(31,536,1), X_MASK, PPCCOM, { RA, RS, RB } }, -{ "sr.", XRC(31,536,1), X_MASK, PWRCOM, { RA, RS, RB } }, - -{ "rrib", XRC(31,537,0), X_MASK, M601, { RA, RS, RB } }, -{ "rrib.", XRC(31,537,1), X_MASK, M601, { RA, RS, RB } }, - -{ "srd", XRC(31,539,0), X_MASK, PPC64, { RA, RS, RB } }, -{ "srd.", XRC(31,539,1), X_MASK, PPC64, { RA, RS, RB } }, - -{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } }, -{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } }, - -{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA0, RB } }, - -{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }}, - -{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } }, - -{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } }, - -{ "lfsuxe", X(31,575), X_MASK, BOOKE64, { FRT, RAS, RB } }, - -{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } }, - -{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA0, NB } }, -{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA0, NB } }, - -{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } }, -{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } }, -{ "msync", X(31,598), 0xffffffff, BOOKE, { 0 } }, -{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } }, -{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } }, - -{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA0, RB } }, - -{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA0, RB } }, - -{ "mffgpr", XRC(31,607,0), XRA_MASK, POWER6, { FRT, RB } }, - -{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } }, - -{ "dclst", X(31,630), XRB_MASK, PWRCOM, { RS, RA } }, - -{ "lfdux", X(31,631), X_MASK, COM, { FRT, RAS, RB } }, - -{ "lfduxe", X(31,639), X_MASK, BOOKE64, { FRT, RAS, RB } }, - -{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } }, - -{ "stdbrx", X(31,660), X_MASK, CELL, { RS, RA0, RB } }, - -{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA0, RB } }, -{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA0, RB } }, - -{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA0, RB } }, -{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA0, RB } }, - -{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA0, RB } }, - -{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } }, -{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } }, - -{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } }, -{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } }, - -{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA0, RB } }, - -{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } }, - -{ "sriq", XRC(31,696,0), X_MASK, M601, { RA, RS, SH } }, -{ "sriq.", XRC(31,696,1), X_MASK, M601, { RA, RS, SH } }, - -{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } }, - -{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA0, NB } }, -{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA0, NB } }, - -{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA0, RB } }, - -{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } }, -{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } }, - -{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } }, -{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } }, - -{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA0, RB } }, - -{ "mftgpr", XRC(31,735,0), XRA_MASK, POWER6, { RT, FRB } }, - -{ "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } }, - -{ "stfdux", X(31,759), X_MASK, COM, { FRS, RAS, RB } }, - -{ "srliq", XRC(31,760,0), X_MASK, M601, { RA, RS, SH } }, -{ "srliq.", XRC(31,760,1), X_MASK, M601, { RA, RS, SH } }, - -{ "dcbae", X(31,766), XRT_MASK, BOOKE64, { RA, RB } }, - -{ "stfduxe", X(31,767), X_MASK, BOOKE64, { FRS, RAS, RB } }, - -{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } }, -{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } }, - -{ "lwzcix", X(31,789), X_MASK, POWER6, { RT, RA0, RB } }, - -{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA0, RB } }, - -{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } }, -{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } }, -{ "sraw.", XRC(31,792,1), X_MASK, PPCCOM, { RA, RS, RB } }, -{ "sra.", XRC(31,792,1), X_MASK, PWRCOM, { RA, RS, RB } }, - -{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } }, -{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } }, - -{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA0, RB } }, -{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA0, RB } }, - -{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } }, - -{ "lhzcix", X(31,821), X_MASK, POWER6, { RT, RA0, RB } }, - -{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } }, -{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } }, - -{ "srawi", XRC(31,824,0), X_MASK, PPCCOM, { RA, RS, SH } }, -{ "srai", XRC(31,824,0), X_MASK, PWRCOM, { RA, RS, SH } }, -{ "srawi.", XRC(31,824,1), X_MASK, PPCCOM, { RA, RS, SH } }, -{ "srai.", XRC(31,824,1), X_MASK, PWRCOM, { RA, RS, SH } }, - -{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } }, - -{ "lbzcix", X(31,853), X_MASK, POWER6, { RT, RA0, RB } }, - -{ "mbar", X(31,854), X_MASK, BOOKE, { MO } }, -{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } }, - -{ "lfiwax", X(31,855), X_MASK, POWER6, { FRT, RA0, RB } }, - -{ "ldcix", X(31,885), X_MASK, POWER6, { RT, RA0, RB } }, - -{ "tlbsx", XRC(31,914,0), X_MASK, PPC403|BOOKE, { RTO, RA, RB } }, -{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403|BOOKE, { RTO, RA, RB } }, -{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RTO, RA, RB } }, -{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RTO, RA, RB } }, - -{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } }, - -{ "stwcix", X(31,917), X_MASK, POWER6, { RS, RA0, RB } }, - -{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA0, RB } }, - -{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } }, -{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } }, - -{ "srea", XRC(31,921,0), X_MASK, M601, { RA, RS, RB } }, -{ "srea.", XRC(31,921,1), X_MASK, M601, { RA, RS, RB } }, - -{ "extsh", XRC(31,922,0), XRB_MASK, PPCCOM, { RA, RS } }, -{ "exts", XRC(31,922,0), XRB_MASK, PWRCOM, { RA, RS } }, -{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } }, -{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } }, - -{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA0, RB } }, - -{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } }, -{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } }, -{ "tlbre", X(31,946), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } }, - -{ "sthcix", X(31,949), X_MASK, POWER6, { RS, RA0, RB } }, - -{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } }, -{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } }, - -{ "extsb", XRC(31,954,0), XRB_MASK, PPC, { RA, RS} }, -{ "extsb.", XRC(31,954,1), XRB_MASK, PPC, { RA, RS} }, - -{ "stduxe", X(31,959), X_MASK, BOOKE64, { RS, RAS, RB } }, - -{ "iccci", X(31,966), XRT_MASK, PPC403|PPC440, { RA, RB } }, - -{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } }, -{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } }, -{ "tlbwe", X(31,978), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } }, -{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } }, - -{ "stbcix", X(31,981), X_MASK, POWER6, { RS, RA0, RB } }, - -{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } }, - -{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA0, RB } }, - -{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } }, -{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } }, - -{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } }, - -{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } }, -{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA0, RB } }, - -{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } }, - -{ "stdcix", X(31,1013), X_MASK, POWER6, { RS, RA0, RB } }, - -{ "dcbzl", XOPL(31,1014,1), XRT_MASK,POWER4, { RA, RB } }, -{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, -{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, - -{ "dcbze", X(31,1022), XRT_MASK, BOOKE64, { RA, RB } }, - -{ "lvebx", X(31, 7), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "lvehx", X(31, 39), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "lvewx", X(31, 71), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "lvsl", X(31, 6), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "lvsr", X(31, 38), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "lvx", X(31, 103), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "lvxl", X(31, 359), X_MASK, PPCVEC, { VD, RA, RB } }, -{ "stvebx", X(31, 135), X_MASK, PPCVEC, { VS, RA, RB } }, -{ "stvehx", X(31, 167), X_MASK, PPCVEC, { VS, RA, RB } }, -{ "stvewx", X(31, 199), X_MASK, PPCVEC, { VS, RA, RB } }, -{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } }, -{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } }, - -/* New load/store left/right index vector instructions that are in the Cell only. */ -{ "lvlx", X(31, 519), X_MASK, CELL, { VD, RA0, RB } }, -{ "lvlxl", X(31, 775), X_MASK, CELL, { VD, RA0, RB } }, -{ "lvrx", X(31, 551), X_MASK, CELL, { VD, RA0, RB } }, -{ "lvrxl", X(31, 807), X_MASK, CELL, { VD, RA0, RB } }, -{ "stvlx", X(31, 647), X_MASK, CELL, { VS, RA0, RB } }, -{ "stvlxl", X(31, 903), X_MASK, CELL, { VS, RA0, RB } }, -{ "stvrx", X(31, 679), X_MASK, CELL, { VS, RA0, RB } }, -{ "stvrxl", X(31, 935), X_MASK, CELL, { VS, RA0, RB } }, - -{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA0 } }, -{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA0 } }, - -{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } }, -{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA0 } }, - -{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA0 } }, - -{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } }, - -{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA0 } }, -{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA0 } }, - -{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } }, -{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA0 } }, - -{ "stb", OP(38), OP_MASK, COM, { RS, D, RA0 } }, - -{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } }, - -{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA0 } }, - -{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } }, - -{ "lha", OP(42), OP_MASK, COM, { RT, D, RA0 } }, - -{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } }, - -{ "sth", OP(44), OP_MASK, COM, { RS, D, RA0 } }, - -{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } }, - -{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } }, -{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA0 } }, - -{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA0 } }, -{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA0 } }, - -{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA0 } }, - -{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } }, - -{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA0 } }, - -{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } }, - -{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA0 } }, - -{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } }, - -{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA0 } }, - -{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } }, - -{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } }, - -{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA0 } }, - -{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA0 } }, - -{ "lfdp", OP(57), OP_MASK, POWER6, { FRT, D, RA0 } }, - -{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA0 } }, -{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } }, -{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA0 } }, -{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } }, -{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA0 } }, -{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } }, -{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA0 } }, -{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } }, -{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA0 } }, -{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } }, -{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA0 } }, -{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } }, -{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA0 } }, -{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } }, - -{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA0 } }, - -{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } }, - -{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA0 } }, - -{ "dadd", XRC(59,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dadd.", XRC(59,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "dqua", ZRC(59,3,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "dqua.", ZRC(59,3,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, - -{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, -{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, - -{ "fsubs", A(59,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, -{ "fsubs.", A(59,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, - -{ "fadds", A(59,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, -{ "fadds.", A(59,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, - -{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, -{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, - -{ "fres", A(59,24,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, -{ "fres.", A(59,24,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, - -{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } }, -{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } }, - -{ "frsqrtes", A(59,26,0), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } }, -{ "frsqrtes.",A(59,26,1), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } }, - -{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, -{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, - -{ "fmadds", A(59,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, -{ "fmadds.", A(59,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, - -{ "fnmsubs", A(59,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, -{ "fnmsubs.",A(59,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, - -{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, -{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, - -{ "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "drrnd", ZRC(59,35,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "drrnd.", ZRC(59,35,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, - -{ "dscli", ZRC(59,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "dscli.", ZRC(59,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, - -{ "dquai", ZRC(59,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, -{ "dquai.", ZRC(59,67,1), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, - -{ "dscri", ZRC(59,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "dscri.", ZRC(59,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, - -{ "drintx", ZRC(59,99,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintx.", ZRC(59,99,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, - -{ "dcmpo", X(59,130), X_MASK, POWER6, { BF, FRA, FRB } }, - -{ "dtstex", X(59,162), X_MASK, POWER6, { BF, FRA, FRB } }, -{ "dtstdc", Z(59,194), Z_MASK, POWER6, { BF, FRA, DCM } }, -{ "dtstdg", Z(59,226), Z_MASK, POWER6, { BF, FRA, DGM } }, - -{ "drintn", ZRC(59,227,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintn.", ZRC(59,227,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, - -{ "dctdp", XRC(59,258,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dctdp.", XRC(59,258,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "dctfix", XRC(59,290,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dctfix.", XRC(59,290,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "ddedpd", XRC(59,322,0), X_MASK, POWER6, { SP, FRT, FRB } }, -{ "ddedpd.", XRC(59,322,1), X_MASK, POWER6, { SP, FRT, FRB } }, - -{ "dxex", XRC(59,354,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dxex.", XRC(59,354,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "dsub", XRC(59,514,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dsub.", XRC(59,514,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "ddiv", XRC(59,546,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "ddiv.", XRC(59,546,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "dcmpu", X(59,642), X_MASK, POWER6, { BF, FRA, FRB } }, - -{ "dtstsf", X(59,674), X_MASK, POWER6, { BF, FRA, FRB } }, - -{ "drsp", XRC(59,770,0), X_MASK, POWER6, { FRT, FRB } }, -{ "drsp.", XRC(59,770,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "dcffix", XRC(59,802,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dcffix.", XRC(59,802,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "denbcd", XRC(59,834,0), X_MASK, POWER6, { S, FRT, FRB } }, -{ "denbcd.", XRC(59,834,1), X_MASK, POWER6, { S, FRT, FRB } }, - -{ "diex", XRC(59,866,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "diex.", XRC(59,866,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } }, - -{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, - -{ "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } }, - -{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA0 } }, -{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA0 } }, -{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA0 } }, -{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } }, -{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA0 } }, -{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } }, -{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA0 } }, -{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } }, -{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA0 } }, -{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } }, -{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA0 } }, -{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } }, - -{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA0 } }, - -{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } }, - -{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA0 } }, - -{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, - -{ "daddq", XRC(63,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "daddq.", XRC(63,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "dquaq", ZRC(63,3,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "dquaq.", ZRC(63,3,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, - -{ "fcpsgn", XRC(63,8,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "fcpsgn.", XRC(63,8,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } }, -{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } }, - -{ "fctiw", XRC(63,14,0), XRA_MASK, PPCCOM, { FRT, FRB } }, -{ "fcir", XRC(63,14,0), XRA_MASK, POWER2, { FRT, FRB } }, -{ "fctiw.", XRC(63,14,1), XRA_MASK, PPCCOM, { FRT, FRB } }, -{ "fcir.", XRC(63,14,1), XRA_MASK, POWER2, { FRT, FRB } }, - -{ "fctiwz", XRC(63,15,0), XRA_MASK, PPCCOM, { FRT, FRB } }, -{ "fcirz", XRC(63,15,0), XRA_MASK, POWER2, { FRT, FRB } }, -{ "fctiwz.", XRC(63,15,1), XRA_MASK, PPCCOM, { FRT, FRB } }, -{ "fcirz.", XRC(63,15,1), XRA_MASK, POWER2, { FRT, FRB } }, - -{ "fdiv", A(63,18,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, -{ "fd", A(63,18,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, -{ "fdiv.", A(63,18,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, -{ "fd.", A(63,18,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, - -{ "fsub", A(63,20,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, -{ "fs", A(63,20,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, -{ "fsub.", A(63,20,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, -{ "fs.", A(63,20,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, - -{ "fadd", A(63,21,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, -{ "fa", A(63,21,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, -{ "fadd.", A(63,21,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, -{ "fa.", A(63,21,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, - -{ "fsqrt", A(63,22,0), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } }, -{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } }, - -{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, -{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, - -{ "fre", A(63,24,0), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } }, -{ "fre.", A(63,24,1), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } }, - -{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, -{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, -{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, -{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, - -{ "frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, -{ "frsqrte.",A(63,26,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, - -{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, -{ "fmsub.", A(63,28,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fms.", A(63,28,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, - -{ "fmadd", A(63,29,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fma", A(63,29,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, -{ "fmadd.", A(63,29,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fma.", A(63,29,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, - -{ "fnmsub", A(63,30,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fnms", A(63,30,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, -{ "fnmsub.", A(63,30,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fnms.", A(63,30,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, - -{ "fnmadd", A(63,31,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fnma", A(63,31,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, -{ "fnmadd.", A(63,31,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, -{ "fnma.", A(63,31,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, - -{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, - -{ "dmulq", XRC(63,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dmulq.", XRC(63,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "drrndq", ZRC(63,35,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, -{ "drrndq.", ZRC(63,35,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, - -{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, -{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, - -{ "fneg", XRC(63,40,0), XRA_MASK, COM, { FRT, FRB } }, -{ "fneg.", XRC(63,40,1), XRA_MASK, COM, { FRT, FRB } }, - -{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, - -{ "dscliq", ZRC(63,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, - -{ "dquaiq", ZRC(63,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, -{ "dquaiq.", ZRC(63,67,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, - -{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, -{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, - -{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } }, -{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } }, - -{ "dscriq", ZRC(63,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, -{ "dscriq.", ZRC(63,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, - -{ "drintxq", ZRC(63,99,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintxq.",ZRC(63,99,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, - -{ "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } }, - -{ "mtfsfi", XRC(63,134,0), XWRA_MASK|(3<<21)|(1<<11), COM, { BFF, U, W } }, -{ "mtfsfi.", XRC(63,134,1), XWRA_MASK|(3<<21)|(1<<11), COM, { BFF, U, W } }, - -{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, -{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, - -{ "dtstexq", X(63,162), X_MASK, POWER6, { BF, FRA, FRB } }, -{ "dtstdcq", Z(63,194), Z_MASK, POWER6, { BF, FRA, DCM } }, -{ "dtstdgq", Z(63,226), Z_MASK, POWER6, { BF, FRA, DGM } }, - -{ "drintnq", ZRC(63,227,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, -{ "drintnq.",ZRC(63,227,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, - -{ "dctqpq", XRC(63,258,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dctqpq.", XRC(63,258,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } }, -{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } }, - -{ "dctfixq", XRC(63,290,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dctfixq.",XRC(63,290,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "ddedpdq", XRC(63,322,0), X_MASK, POWER6, { SP, FRT, FRB } }, -{ "ddedpdq.",XRC(63,322,1), X_MASK, POWER6, { SP, FRT, FRB } }, - -{ "dxexq", XRC(63,354,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dxexq.", XRC(63,354,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "frin", XRC(63,392,0), XRA_MASK, POWER5, { FRT, FRB } }, -{ "frin.", XRC(63,392,1), XRA_MASK, POWER5, { FRT, FRB } }, -{ "friz", XRC(63,424,0), XRA_MASK, POWER5, { FRT, FRB } }, -{ "friz.", XRC(63,424,1), XRA_MASK, POWER5, { FRT, FRB } }, -{ "frip", XRC(63,456,0), XRA_MASK, POWER5, { FRT, FRB } }, -{ "frip.", XRC(63,456,1), XRA_MASK, POWER5, { FRT, FRB } }, -{ "frim", XRC(63,488,0), XRA_MASK, POWER5, { FRT, FRB } }, -{ "frim.", XRC(63,488,1), XRA_MASK, POWER5, { FRT, FRB } }, - -{ "dsubq", XRC(63,514,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "dsubq.", XRC(63,514,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "ddivq", XRC(63,546,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "ddivq.", XRC(63,546,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } }, -{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } }, - -{ "dcmpuq", X(63,642), X_MASK, POWER6, { BF, FRA, FRB } }, - -{ "dtstsfq", X(63,674), X_MASK, POWER6, { BF, FRA, FRB } }, - -{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB, XFL_L, W } }, -{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB, XFL_L, W } }, - -{ "drdpq", XRC(63,770,0), X_MASK, POWER6, { FRT, FRB } }, -{ "drdpq.", XRC(63,770,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "dcffixq", XRC(63,802,0), X_MASK, POWER6, { FRT, FRB } }, -{ "dcffixq.",XRC(63,802,1), X_MASK, POWER6, { FRT, FRB } }, - -{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } }, -{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } }, - -{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } }, -{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } }, - -{ "denbcdq", XRC(63,834,0), X_MASK, POWER6, { S, FRT, FRB } }, -{ "denbcdq.",XRC(63,834,1), X_MASK, POWER6, { S, FRT, FRB } }, - -{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, -{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, - -{ "diexq", XRC(63,866,0), X_MASK, POWER6, { FRT, FRA, FRB } }, -{ "diexq.", XRC(63,866,1), X_MASK, POWER6, { FRT, FRA, FRB } }, - -}; - -const int powerpc_num_opcodes = - sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]); - -/* The macro table. This is only used by the assembler. */ - -/* The expressions of the form (-x ! 31) & (x | 31) have the value 0 - when x=0; 32-x when x is between 1 and 31; are negative if x is - negative; and are 32 or more otherwise. This is what you want - when, for instance, you are emulating a right shift by a - rotate-left-and-mask, because the underlying instructions support - shifts of size 0 but not shifts of size 32. By comparison, when - extracting x bits from some word you want to use just 32-x, because - the underlying instructions don't support extracting 0 bits but do - support extracting the whole word (32 bits in this case). */ - -const struct powerpc_macro powerpc_macros[] = { -{ "extldi", 4, PPC64, "rldicr %0,%1,%3,(%2)-1" }, -{ "extldi.", 4, PPC64, "rldicr. %0,%1,%3,(%2)-1" }, -{ "extrdi", 4, PPC64, "rldicl %0,%1,(%2)+(%3),64-(%2)" }, -{ "extrdi.", 4, PPC64, "rldicl. %0,%1,(%2)+(%3),64-(%2)" }, -{ "insrdi", 4, PPC64, "rldimi %0,%1,64-((%2)+(%3)),%3" }, -{ "insrdi.", 4, PPC64, "rldimi. %0,%1,64-((%2)+(%3)),%3" }, -{ "rotrdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),0" }, -{ "rotrdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),0" }, -{ "sldi", 3, PPC64, "rldicr %0,%1,%2,63-(%2)" }, -{ "sldi.", 3, PPC64, "rldicr. %0,%1,%2,63-(%2)" }, -{ "srdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),%2" }, -{ "srdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),%2" }, -{ "clrrdi", 3, PPC64, "rldicr %0,%1,0,63-(%2)" }, -{ "clrrdi.", 3, PPC64, "rldicr. %0,%1,0,63-(%2)" }, -{ "clrlsldi",4, PPC64, "rldic %0,%1,%3,(%2)-(%3)" }, -{ "clrlsldi.",4, PPC64, "rldic. %0,%1,%3,(%2)-(%3)" }, - -{ "extlwi", 4, PPCCOM, "rlwinm %0,%1,%3,0,(%2)-1" }, -{ "extlwi.", 4, PPCCOM, "rlwinm. %0,%1,%3,0,(%2)-1" }, -{ "extrwi", 4, PPCCOM, "rlwinm %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" }, -{ "extrwi.", 4, PPCCOM, "rlwinm. %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" }, -{ "inslwi", 4, PPCCOM, "rlwimi %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1" }, -{ "inslwi.", 4, PPCCOM, "rlwimi. %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1"}, -{ "insrwi", 4, PPCCOM, "rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" }, -{ "insrwi.", 4, PPCCOM, "rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"}, -{ "rotrwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),0,31" }, -{ "rotrwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),0,31" }, -{ "slwi", 3, PPCCOM, "rlwinm %0,%1,%2,0,31-(%2)" }, -{ "sli", 3, PWRCOM, "rlinm %0,%1,%2,0,31-(%2)" }, -{ "slwi.", 3, PPCCOM, "rlwinm. %0,%1,%2,0,31-(%2)" }, -{ "sli.", 3, PWRCOM, "rlinm. %0,%1,%2,0,31-(%2)" }, -{ "srwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, -{ "sri", 3, PWRCOM, "rlinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, -{ "srwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, -{ "sri.", 3, PWRCOM, "rlinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, -{ "clrrwi", 3, PPCCOM, "rlwinm %0,%1,0,0,31-(%2)" }, -{ "clrrwi.", 3, PPCCOM, "rlwinm. %0,%1,0,0,31-(%2)" }, -{ "clrlslwi",4, PPCCOM, "rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" }, -{ "clrlslwi.",4, PPCCOM, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" }, -}; - -const int powerpc_num_macros = - sizeof (powerpc_macros) / sizeof (powerpc_macros[0]); - - -/* This file provides several disassembler functions, all of which use - the disassembler interface defined in dis-asm.h. Several functions - are provided because this file handles disassembly for the PowerPC - in both big and little endian mode and also for the POWER (RS/6000) - chip. */ - -static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int); - -/* Determine which set of machines to disassemble for. PPC403/601 or - BookE. For convenience, also disassemble instructions supported - by the AltiVec vector unit. */ - -static int -powerpc_dialect (struct disassemble_info *info) -{ - int dialect = PPC_OPCODE_PPC; - - if (BFD_DEFAULT_TARGET_SIZE == 64) - dialect |= PPC_OPCODE_64; - - if (info->disassembler_options - && strstr (info->disassembler_options, "booke") != NULL) - dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64; - else if ((info->mach == bfd_mach_ppc_e500) - || (info->disassembler_options - && strstr (info->disassembler_options, "e500") != NULL)) - dialect |= (PPC_OPCODE_BOOKE - | PPC_OPCODE_SPE | PPC_OPCODE_ISEL - | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK - | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK - | PPC_OPCODE_RFMCI); - else if (info->disassembler_options - && strstr (info->disassembler_options, "efs") != NULL) - dialect |= PPC_OPCODE_EFS; - else if (info->disassembler_options - && strstr (info->disassembler_options, "e300") != NULL) - dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON; - else if (info->disassembler_options - && strstr (info->disassembler_options, "440") != NULL) - dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32 - | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI; - else - dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC - | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC); - - if (info->disassembler_options - && strstr (info->disassembler_options, "power4") != NULL) - dialect |= PPC_OPCODE_POWER4; - - if (info->disassembler_options - && strstr (info->disassembler_options, "power5") != NULL) - dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5; - - if (info->disassembler_options - && strstr (info->disassembler_options, "cell") != NULL) - dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC; - - if (info->disassembler_options - && strstr (info->disassembler_options, "power6") != NULL) - dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC; - - if (info->disassembler_options - && strstr (info->disassembler_options, "any") != NULL) - dialect |= PPC_OPCODE_ANY; - - if (info->disassembler_options) - { - if (strstr (info->disassembler_options, "32") != NULL) - dialect &= ~PPC_OPCODE_64; - else if (strstr (info->disassembler_options, "64") != NULL) - dialect |= PPC_OPCODE_64; - } - - info->private_data = (char *) 0 + dialect; - return dialect; -} - -/* Qemu default */ -int -print_insn_ppc (bfd_vma memaddr, struct disassemble_info *info) -{ - int dialect = (char *) info->private_data - (char *) 0; - return print_insn_powerpc (memaddr, info, 1, dialect); -} - -/* Print a big endian PowerPC instruction. */ - -int -print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info) -{ - int dialect = (char *) info->private_data - (char *) 0; - return print_insn_powerpc (memaddr, info, 1, dialect); -} - -/* Print a little endian PowerPC instruction. */ - -int -print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info) -{ - int dialect = (char *) info->private_data - (char *) 0; - return print_insn_powerpc (memaddr, info, 0, dialect); -} - -/* Print a POWER (RS/6000) instruction. */ - -int -print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info) -{ - return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER); -} - -/* Extract the operand value from the PowerPC or POWER instruction. */ - -static long -operand_value_powerpc (const struct powerpc_operand *operand, - unsigned long insn, int dialect) -{ - long value; - int invalid; - /* Extract the value from the instruction. */ - if (operand->extract) - value = (*operand->extract) (insn, dialect, &invalid); - else - { - value = (insn >> operand->shift) & operand->bitm; - if ((operand->flags & PPC_OPERAND_SIGNED) != 0) - { - /* BITM is always some number of zeros followed by some - number of ones, followed by some numer of zeros. */ - unsigned long top = operand->bitm; - /* top & -top gives the rightmost 1 bit, so this - fills in any trailing zeros. */ - top |= (top & -top) - 1; - top &= ~(top >> 1); - value = (value ^ top) - top; - } - } - - return value; -} - -/* Determine whether the optional operand(s) should be printed. */ - -static int -skip_optional_operands (const unsigned char *opindex, - unsigned long insn, int dialect) -{ - const struct powerpc_operand *operand; - - for (; *opindex != 0; opindex++) - { - operand = &powerpc_operands[*opindex]; - if ((operand->flags & PPC_OPERAND_NEXT) != 0 - || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 - && operand_value_powerpc (operand, insn, dialect) != 0)) - return 0; - } - - return 1; -} - -bfd_vma bfd_getl32 (const bfd_byte *addr) -{ - unsigned long v; - - v = (unsigned long) addr[0]; - v |= (unsigned long) addr[1] << 8; - v |= (unsigned long) addr[2] << 16; - v |= (unsigned long) addr[3] << 24; - return (bfd_vma) v; -} - -bfd_vma bfd_getb32 (const bfd_byte *addr) -{ - unsigned long v; - - v = (unsigned long) addr[0] << 24; - v |= (unsigned long) addr[1] << 16; - v |= (unsigned long) addr[2] << 8; - v |= (unsigned long) addr[3]; - return (bfd_vma) v; -} - -/* Get LENGTH bytes from info's buffer, at target address memaddr. - Transfer them to myaddr. */ -int -buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, - struct disassemble_info *info) -{ - if (memaddr < info->buffer_vma - || memaddr + length > info->buffer_vma + info->buffer_length) - /* Out of bounds. Use EIO because GDB uses it. */ - return EIO; - memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length); - return 0; -} - -/* Print an error message. We can assume that this is in response to - an error return from buffer_read_memory. */ -void -perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info) -{ - if (status != EIO) - /* Can't happen. */ - (*info->fprintf_func) (info->stream, "Unknown error %d\n", status); - else - /* Actually, address between memaddr and memaddr + len was - out of bounds. */ - (*info->fprintf_func) (info->stream, - "Address 0x%" PRIx64 " is out of bounds.\n", memaddr); -} - -/* This could be in a separate file, to save miniscule amounts of space - in statically linked executables. */ - -/* Just print the address is hex. This is included for completeness even - though both GDB and objdump provide their own (to print symbolic - addresses). */ - -void -generic_print_address (bfd_vma addr, struct disassemble_info *info) -{ - (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr); -} - -/* Just return the given address. */ - -int -generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info) -{ - return 1; -} - -/* Print a PowerPC or POWER instruction. */ - -static int -print_insn_powerpc (bfd_vma memaddr, - struct disassemble_info *info, - int bigendian, - int dialect) -{ - bfd_byte buffer[4]; - int status; - unsigned long insn; - const struct powerpc_opcode *opcode; - const struct powerpc_opcode *opcode_end; - unsigned long op; - - if (dialect == 0) - dialect = powerpc_dialect (info); - - status = (*info->read_memory_func) (memaddr, buffer, 4, info); - if (status != 0) - { - (*info->memory_error_func) (status, memaddr, info); - return -1; - } - - if (bigendian) - insn = bfd_getb32 (buffer); - else - insn = bfd_getl32 (buffer); - - /* Get the major opcode of the instruction. */ - op = PPC_OP (insn); - - /* Find the first match in the opcode table. We could speed this up - a bit by doing a binary search on the major opcode. */ - opcode_end = powerpc_opcodes + powerpc_num_opcodes; - again: - for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++) - { - unsigned long table_op; - const unsigned char *opindex; - const struct powerpc_operand *operand; - int invalid; - int need_comma; - int need_paren; - int skip_optional; - - table_op = PPC_OP (opcode->opcode); - if (op < table_op) - break; - if (op > table_op) - continue; - - if ((insn & opcode->mask) != opcode->opcode - || (opcode->flags & dialect) == 0) - continue; - - /* Make two passes over the operands. First see if any of them - have extraction functions, and, if they do, make sure the - instruction is valid. */ - invalid = 0; - for (opindex = opcode->operands; *opindex != 0; opindex++) - { - operand = powerpc_operands + *opindex; - if (operand->extract) - (*operand->extract) (insn, dialect, &invalid); - } - if (invalid) - continue; - - /* The instruction is valid. */ - if (opcode->operands[0] != 0) - (*info->fprintf_func) (info->stream, "%-7s ", opcode->name); - else - (*info->fprintf_func) (info->stream, "%s", opcode->name); - - /* Now extract and print the operands. */ - need_comma = 0; - need_paren = 0; - skip_optional = -1; - for (opindex = opcode->operands; *opindex != 0; opindex++) - { - long value; - - operand = powerpc_operands + *opindex; - - /* Operands that are marked FAKE are simply ignored. We - already made sure that the extract function considered - the instruction to be valid. */ - if ((operand->flags & PPC_OPERAND_FAKE) != 0) - continue; - - /* If all of the optional operands have the value zero, - then don't print any of them. */ - if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) - { - if (skip_optional < 0) - skip_optional = skip_optional_operands (opindex, insn, - dialect); - if (skip_optional) - continue; - } - - value = operand_value_powerpc (operand, insn, dialect); - - if (need_comma) - { - (*info->fprintf_func) (info->stream, ","); - need_comma = 0; - } - - /* Print the operand as directed by the flags. */ - if ((operand->flags & PPC_OPERAND_GPR) != 0 - || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) - (*info->fprintf_func) (info->stream, "r%ld", value); - else if ((operand->flags & PPC_OPERAND_FPR) != 0) - (*info->fprintf_func) (info->stream, "f%ld", value); - else if ((operand->flags & PPC_OPERAND_VR) != 0) - (*info->fprintf_func) (info->stream, "v%ld", value); - else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) - (*info->print_address_func) (memaddr + value, info); - else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) - (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); - else if ((operand->flags & PPC_OPERAND_CR) == 0 - || (dialect & PPC_OPCODE_PPC) == 0) - (*info->fprintf_func) (info->stream, "%ld", value); - else - { - if (operand->bitm == 7) - (*info->fprintf_func) (info->stream, "cr%ld", value); - else - { - static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; - int cr; - int cc; - - cr = value >> 2; - if (cr != 0) - (*info->fprintf_func) (info->stream, "4*cr%d+", cr); - cc = value & 3; - (*info->fprintf_func) (info->stream, "%s", cbnames[cc]); - } - } - - if (need_paren) - { - (*info->fprintf_func) (info->stream, ")"); - need_paren = 0; - } - - if ((operand->flags & PPC_OPERAND_PARENS) == 0) - need_comma = 1; - else - { - (*info->fprintf_func) (info->stream, "("); - need_paren = 1; - } - } - - /* We have found and printed an instruction; return. */ - return 4; - } - - if ((dialect & PPC_OPCODE_ANY) != 0) - { - dialect = ~PPC_OPCODE_ANY; - goto again; - } - - /* We could not find a match. */ - (*info->fprintf_func) (info->stream, ".long 0x%lx", insn); - - return 4; -} diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp deleted file mode 100644 index 7d6a599c..00000000 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ /dev/null @@ -1,1235 +0,0 @@ -/* - * sheepshaver_glue.cpp - Glue Kheperix CPU to SheepShaver CPU engine interface - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "prefs.h" -#include "xlowmem.h" -#include "emul_op.h" -#include "rom_patches.h" -#include "macos_util.h" -#include "block-alloc.hpp" -#include "sigsegv.h" -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-operations.hpp" -#include "cpu/ppc/ppc-instructions.hpp" -#include "thunks.h" - -// Used for NativeOp trampolines -#include "video.h" -#include "name_registry.h" -#include "serial.h" -#include "ether.h" -#include "timer.h" - -#include -#include -#ifdef HAVE_MALLOC_H -#include -#endif - -#ifdef USE_SDL_VIDEO -#include -#endif - -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif - -#define DEBUG 0 -#include "debug.h" - -extern "C" { -#include "dis-asm.h" -} - -// Emulation time statistics -#ifndef EMUL_TIME_STATS -#define EMUL_TIME_STATS 0 -#endif - -#if EMUL_TIME_STATS -static clock_t emul_start_time; -static uint32 interrupt_count = 0, ppc_interrupt_count = 0; -static clock_t interrupt_time = 0; -static uint32 exec68k_count = 0; -static clock_t exec68k_time = 0; -static uint32 native_exec_count = 0; -static clock_t native_exec_time = 0; -static uint32 macos_exec_count = 0; -static clock_t macos_exec_time = 0; -#endif - -static void enter_mon(void) -{ - // Start up mon in real-mode -#if ENABLE_MON - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif -} - -// From main_*.cpp -extern uintptr SignalStackBase(); - -// From rsrc_patches.cpp -extern "C" void check_load_invoc(uint32 type, int16 id, uint32 h); -extern "C" void named_check_load_invoc(uint32 type, uint32 name, uint32 h); - -// PowerPC EmulOp to exit from emulation looop -const uint32 POWERPC_EXEC_RETURN = POWERPC_EMUL_OP | 1; - -// Enable Execute68k() safety checks? -#define SAFE_EXEC_68K 1 - -// Save FP state in Execute68k()? -#define SAVE_FP_EXEC_68K 1 - -// Interrupts in EMUL_OP mode? -#define INTERRUPTS_IN_EMUL_OP_MODE 1 - -// Interrupts in native mode? -#define INTERRUPTS_IN_NATIVE_MODE 1 - -// Pointer to Kernel Data -static KernelData * kernel_data; - -// SIGSEGV handler -sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); - -#if PPC_ENABLE_JIT && PPC_REENTRANT_JIT -// Special trampolines for EmulOp and NativeOp -static uint8 *emul_op_trampoline; -static uint8 *native_op_trampoline; -#endif - - -/** - * PowerPC emulator glue with special 'sheep' opcodes - **/ - -enum { - PPC_I(SHEEP) = PPC_I(MAX), - PPC_I(SHEEP_MAX) -}; - -class sheepshaver_cpu - : public powerpc_cpu -{ - void init_decoder(); - void execute_sheep(uint32 opcode); - -public: - - // Constructor - sheepshaver_cpu(); - - // CR & XER accessors - uint32 get_cr() const { return cr().get(); } - void set_cr(uint32 v) { cr().set(v); } - uint32 get_xer() const { return xer().get(); } - void set_xer(uint32 v) { xer().set(v); } - - // Execute NATIVE_OP routine - void execute_native_op(uint32 native_op); - - // Execute EMUL_OP routine - void execute_emul_op(uint32 emul_op); - - // Execute 68k routine - void execute_68k(uint32 entry, M68kRegisters *r); - - // Execute ppc routine - void execute_ppc(uint32 entry); - - // Execute MacOS/PPC code - uint32 execute_macos_code(uint32 tvect, int nargs, uint32 const *args); - -#if PPC_ENABLE_JIT - // Compile one instruction - virtual int compile1(codegen_context_t & cg_context); -#endif - // Resource manager thunk - void get_resource(uint32 old_get_resource); - - // Handle MacOS interrupt - void interrupt(uint32 entry); - - // Make sure the SIGSEGV handler can access CPU registers - friend sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip); -}; - -sheepshaver_cpu::sheepshaver_cpu() -{ - init_decoder(); - -#if PPC_ENABLE_JIT - if (PrefsFindBool("jit")) - enable_jit(); -#endif -} - -void sheepshaver_cpu::init_decoder() -{ - static const instr_info_t sheep_ii_table[] = { - { "sheep", - (execute_pmf)&sheepshaver_cpu::execute_sheep, - PPC_I(SHEEP), - D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP - } - }; - - const int ii_count = sizeof(sheep_ii_table)/sizeof(sheep_ii_table[0]); - D(bug("SheepShaver extra decode table has %d entries\n", ii_count)); - - for (int i = 0; i < ii_count; i++) { - const instr_info_t * ii = &sheep_ii_table[i]; - init_decoder_entry(ii); - } -} - -/* NativeOp instruction format: - +------------+-------------------------+--+-----------+------------+ - | 6 | |FN| OP | 2 | - +------------+-------------------------+--+-----------+------------+ - 0 5 |6 18 19 20 25 26 31 -*/ - -typedef bit_field< 19, 19 > FN_field; -typedef bit_field< 20, 25 > NATIVE_OP_field; -typedef bit_field< 26, 31 > EMUL_OP_field; - -// Execute EMUL_OP routine -void sheepshaver_cpu::execute_emul_op(uint32 emul_op) -{ - M68kRegisters r68; - WriteMacInt32(XLM_68K_R25, gpr(25)); - WriteMacInt32(XLM_RUN_MODE, MODE_EMUL_OP); - for (int i = 0; i < 8; i++) - r68.d[i] = gpr(8 + i); - for (int i = 0; i < 7; i++) - r68.a[i] = gpr(16 + i); - r68.a[7] = gpr(1); - uint32 saved_cr = get_cr() & 0xff9fffff; // mask_operand::compute(11, 8) - uint32 saved_xer = get_xer(); - EmulOp(&r68, gpr(24), emul_op); - set_cr(saved_cr); - set_xer(saved_xer); - for (int i = 0; i < 8; i++) - gpr(8 + i) = r68.d[i]; - for (int i = 0; i < 7; i++) - gpr(16 + i) = r68.a[i]; - gpr(1) = r68.a[7]; - WriteMacInt32(XLM_RUN_MODE, MODE_68K); -} - -// Execute SheepShaver instruction -void sheepshaver_cpu::execute_sheep(uint32 opcode) -{ -// D(bug("Extended opcode %08x at %08x (68k pc %08x)\n", opcode, pc(), gpr(24))); - assert((((opcode >> 26) & 0x3f) == 6) && OP_MAX <= 64 + 3); - - switch (opcode & 0x3f) { - case 0: // EMUL_RETURN - QuitEmulator(); - break; - - case 1: // EXEC_RETURN - spcflags().set(SPCFLAG_CPU_EXEC_RETURN); - break; - - case 2: // EXEC_NATIVE - execute_native_op(NATIVE_OP_field::extract(opcode)); - if (FN_field::test(opcode)) - pc() = lr(); - else - pc() += 4; - break; - - default: // EMUL_OP - execute_emul_op(EMUL_OP_field::extract(opcode) - 3); - pc() += 4; - break; - } -} - -// Compile one instruction -#if PPC_ENABLE_JIT -int sheepshaver_cpu::compile1(codegen_context_t & cg_context) -{ - const instr_info_t *ii = cg_context.instr_info; - if (ii->mnemo != PPC_I(SHEEP)) - return COMPILE_FAILURE; - - int status = COMPILE_FAILURE; - powerpc_dyngen & dg = cg_context.codegen; - uint32 opcode = cg_context.opcode; - - switch (opcode & 0x3f) { - case 0: // EMUL_RETURN - dg.gen_invoke(QuitEmulator); - status = COMPILE_CODE_OK; - break; - - case 1: // EXEC_RETURN - dg.gen_spcflags_set(SPCFLAG_CPU_EXEC_RETURN); - // Don't check for pending interrupts, we do know we have to - // get out of this block ASAP - dg.gen_exec_return(); - status = COMPILE_EPILOGUE_OK; - break; - - case 2: { // EXEC_NATIVE - uint32 selector = NATIVE_OP_field::extract(opcode); - switch (selector) { -#if !PPC_REENTRANT_JIT - // Filter out functions that may invoke Execute68k() or - // CallMacOS(), this would break reentrancy as they could - // invalidate the translation cache and even overwrite - // continuation code when we are done with them. - case NATIVE_PATCH_NAME_REGISTRY: - dg.gen_invoke(DoPatchNameRegistry); - status = COMPILE_CODE_OK; - break; - case NATIVE_VIDEO_INSTALL_ACCEL: - dg.gen_invoke(VideoInstallAccel); - status = COMPILE_CODE_OK; - break; - case NATIVE_VIDEO_VBL: - dg.gen_invoke(VideoVBL); - status = COMPILE_CODE_OK; - break; - case NATIVE_GET_RESOURCE: - case NATIVE_GET_1_RESOURCE: - case NATIVE_GET_IND_RESOURCE: - case NATIVE_GET_1_IND_RESOURCE: - case NATIVE_R_GET_RESOURCE: { - static const uint32 get_resource_ptr[] = { - XLM_GET_RESOURCE, - XLM_GET_1_RESOURCE, - XLM_GET_IND_RESOURCE, - XLM_GET_1_IND_RESOURCE, - XLM_R_GET_RESOURCE - }; - uint32 old_get_resource = ReadMacInt32(get_resource_ptr[selector - NATIVE_GET_RESOURCE]); - typedef void (*func_t)(dyngen_cpu_base, uint32); - func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::get_resource).ptr(); - dg.gen_invoke_CPU_im(func, old_get_resource); - status = COMPILE_CODE_OK; - break; - } -#endif - case NATIVE_CHECK_LOAD_INVOC: - dg.gen_load_T0_GPR(3); - dg.gen_load_T1_GPR(4); - dg.gen_se_16_32_T1(); - dg.gen_load_T2_GPR(5); - dg.gen_invoke_T0_T1_T2((void (*)(uint32, uint32, uint32))check_load_invoc); - status = COMPILE_CODE_OK; - break; - case NATIVE_NAMED_CHECK_LOAD_INVOC: - dg.gen_load_T0_GPR(3); - dg.gen_load_T1_GPR(4); - dg.gen_load_T2_GPR(5); - dg.gen_invoke_T0_T1_T2((void (*)(uint32, uint32, uint32))named_check_load_invoc); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_SYNC_HOOK: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0_ret_T0((uint32 (*)(uint32))NQD_sync_hook); - dg.gen_store_T0_GPR(3); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_BITBLT_HOOK: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0_ret_T0((uint32 (*)(uint32))NQD_bitblt_hook); - dg.gen_store_T0_GPR(3); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_FILLRECT_HOOK: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0_ret_T0((uint32 (*)(uint32))NQD_fillrect_hook); - dg.gen_store_T0_GPR(3); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_UNKNOWN_HOOK: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0_ret_T0((uint32 (*)(uint32))NQD_unknown_hook); - dg.gen_store_T0_GPR(3); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_BITBLT: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0((void (*)(uint32))NQD_bitblt); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_INVRECT: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0((void (*)(uint32))NQD_invrect); - status = COMPILE_CODE_OK; - break; - case NATIVE_NQD_FILLRECT: - dg.gen_load_T0_GPR(3); - dg.gen_invoke_T0((void (*)(uint32))NQD_fillrect); - status = COMPILE_CODE_OK; - break; - } - // Could we fully translate this NativeOp? - if (status == COMPILE_CODE_OK) { - if (!FN_field::test(opcode)) - cg_context.done_compile = false; - else { - dg.gen_load_T0_LR_aligned(); - dg.gen_set_PC_T0(); - cg_context.done_compile = true; - } - break; - } -#if PPC_REENTRANT_JIT - // Try to execute NativeOp trampoline - if (!FN_field::test(opcode)) - dg.gen_set_PC_im(cg_context.pc + 4); - else { - dg.gen_load_T0_LR_aligned(); - dg.gen_set_PC_T0(); - } - dg.gen_mov_32_T0_im(selector); - dg.gen_jmp(native_op_trampoline); - cg_context.done_compile = true; - status = COMPILE_EPILOGUE_OK; - break; -#endif - // Invoke NativeOp handler - if (!FN_field::test(opcode)) { - typedef void (*func_t)(dyngen_cpu_base, uint32); - func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_native_op).ptr(); - dg.gen_invoke_CPU_im(func, selector); - cg_context.done_compile = false; - status = COMPILE_CODE_OK; - } - // Otherwise, let it generate a call to execute_sheep() which - // will cause necessary updates to the program counter - break; - } - - default: { // EMUL_OP - uint32 emul_op = EMUL_OP_field::extract(opcode) - 3; -#if PPC_REENTRANT_JIT - // Try to execute EmulOp trampoline - dg.gen_set_PC_im(cg_context.pc + 4); - dg.gen_mov_32_T0_im(emul_op); - dg.gen_jmp(emul_op_trampoline); - cg_context.done_compile = true; - status = COMPILE_EPILOGUE_OK; - break; -#endif - // Invoke EmulOp handler - typedef void (*func_t)(dyngen_cpu_base, uint32); - func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_emul_op).ptr(); - dg.gen_invoke_CPU_im(func, emul_op); - cg_context.done_compile = false; - status = COMPILE_CODE_OK; - break; - } - } - return status; -} -#endif - -// Handle MacOS interrupt -void sheepshaver_cpu::interrupt(uint32 entry) -{ -#if EMUL_TIME_STATS - ppc_interrupt_count++; - const clock_t interrupt_start = clock(); -#endif - - // Save program counters and branch registers - uint32 saved_pc = pc(); - uint32 saved_lr = lr(); - uint32 saved_ctr= ctr(); - uint32 saved_sp = gpr(1); - - // Initialize stack pointer to SheepShaver alternate stack base - gpr(1) = SignalStackBase() - 64; - - // Build trampoline to return from interrupt - SheepVar32 trampoline = POWERPC_EXEC_RETURN; - - // Prepare registers for nanokernel interrupt routine - kernel_data->v[0x004 >> 2] = htonl(gpr(1)); - kernel_data->v[0x018 >> 2] = htonl(gpr(6)); - - gpr(6) = ntohl(kernel_data->v[0x65c >> 2]); - assert(gpr(6) != 0); - WriteMacInt32(gpr(6) + 0x13c, gpr(7)); - WriteMacInt32(gpr(6) + 0x144, gpr(8)); - WriteMacInt32(gpr(6) + 0x14c, gpr(9)); - WriteMacInt32(gpr(6) + 0x154, gpr(10)); - WriteMacInt32(gpr(6) + 0x15c, gpr(11)); - WriteMacInt32(gpr(6) + 0x164, gpr(12)); - WriteMacInt32(gpr(6) + 0x16c, gpr(13)); - - gpr(1) = KernelDataAddr; - gpr(7) = ntohl(kernel_data->v[0x660 >> 2]); - gpr(8) = 0; - gpr(10) = trampoline.addr(); - gpr(12) = trampoline.addr(); - gpr(13) = get_cr(); - - // rlwimi. r7,r7,8,0,0 - uint32 result = op_ppc_rlwimi::apply(gpr(7), 8, 0x80000000, gpr(7)); - record_cr0(result); - gpr(7) = result; - - gpr(11) = 0xf072; // MSR (SRR1) - cr().set((gpr(11) & 0x0fff0000) | (get_cr() & ~0x0fff0000)); - - // Enter nanokernel - execute(entry); - - // Restore program counters and branch registers - pc() = saved_pc; - lr() = saved_lr; - ctr()= saved_ctr; - gpr(1) = saved_sp; - -#if EMUL_TIME_STATS - interrupt_time += (clock() - interrupt_start); -#endif -} - -// Execute 68k routine -void sheepshaver_cpu::execute_68k(uint32 entry, M68kRegisters *r) -{ -#if EMUL_TIME_STATS - exec68k_count++; - const clock_t exec68k_start = clock(); -#endif - -#if SAFE_EXEC_68K - if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP) - printf("FATAL: Execute68k() not called from EMUL_OP mode\n"); -#endif - - // Save program counters and branch registers - uint32 saved_pc = pc(); - uint32 saved_lr = lr(); - uint32 saved_ctr= ctr(); - uint32 saved_cr = get_cr(); - - // Create MacOS stack frame - // FIXME: make sure MacOS doesn't expect PPC registers to live on top - uint32 sp = gpr(1); - gpr(1) -= 56; - WriteMacInt32(gpr(1), sp); - - // Save PowerPC registers - uint32 saved_GPRs[19]; - memcpy(&saved_GPRs[0], &gpr(13), sizeof(uint32)*(32-13)); -#if SAVE_FP_EXEC_68K - double saved_FPRs[18]; - memcpy(&saved_FPRs[0], &fpr(14), sizeof(double)*(32-14)); -#endif - - // Setup registers for 68k emulator - cr().set(CR_SO_field<2>::mask()); // Supervisor mode - for (int i = 0; i < 8; i++) // d[0]..d[7] - gpr(8 + i) = r->d[i]; - for (int i = 0; i < 7; i++) // a[0]..a[6] - gpr(16 + i) = r->a[i]; - gpr(23) = 0; - gpr(24) = entry; - gpr(25) = ReadMacInt32(XLM_68K_R25); // MSB of SR - gpr(26) = 0; - gpr(28) = 0; // VBR - gpr(29) = ntohl(kernel_data->ed.v[0x74 >> 2]); // Pointer to opcode table - gpr(30) = ntohl(kernel_data->ed.v[0x78 >> 2]); // Address of emulator - gpr(31) = KernelDataAddr + 0x1000; - - // Push return address (points to EXEC_RETURN opcode) on stack - gpr(1) -= 4; - WriteMacInt32(gpr(1), XLM_EXEC_RETURN_OPCODE); - - // Rentering 68k emulator - WriteMacInt32(XLM_RUN_MODE, MODE_68K); - - // Set r0 to 0 for 68k emulator - gpr(0) = 0; - - // Execute 68k opcode - uint32 opcode = ReadMacInt16(gpr(24)); - gpr(27) = (int32)(int16)ReadMacInt16(gpr(24) += 2); - gpr(29) += opcode * 8; - execute(gpr(29)); - - // Save r25 (contains current 68k interrupt level) - WriteMacInt32(XLM_68K_R25, gpr(25)); - - // Reentering EMUL_OP mode - WriteMacInt32(XLM_RUN_MODE, MODE_EMUL_OP); - - // Save 68k registers - for (int i = 0; i < 8; i++) // d[0]..d[7] - r->d[i] = gpr(8 + i); - for (int i = 0; i < 7; i++) // a[0]..a[6] - r->a[i] = gpr(16 + i); - - // Restore PowerPC registers - memcpy(&gpr(13), &saved_GPRs[0], sizeof(uint32)*(32-13)); -#if SAVE_FP_EXEC_68K - memcpy(&fpr(14), &saved_FPRs[0], sizeof(double)*(32-14)); -#endif - - // Cleanup stack - gpr(1) += 56; - - // Restore program counters and branch registers - pc() = saved_pc; - lr() = saved_lr; - ctr()= saved_ctr; - set_cr(saved_cr); - -#if EMUL_TIME_STATS - exec68k_time += (clock() - exec68k_start); -#endif -} - -// Call MacOS PPC code -uint32 sheepshaver_cpu::execute_macos_code(uint32 tvect, int nargs, uint32 const *args) -{ -#if EMUL_TIME_STATS - macos_exec_count++; - const clock_t macos_exec_start = clock(); -#endif - - // Save program counters and branch registers - uint32 saved_pc = pc(); - uint32 saved_lr = lr(); - uint32 saved_ctr= ctr(); - - // Build trampoline with EXEC_RETURN - SheepVar32 trampoline = POWERPC_EXEC_RETURN; - lr() = trampoline.addr(); - - gpr(1) -= 64; // Create stack frame - uint32 proc = ReadMacInt32(tvect); // Get routine address - uint32 toc = ReadMacInt32(tvect + 4); // Get TOC pointer - - // Save PowerPC registers - uint32 regs[8]; - regs[0] = gpr(2); - for (int i = 0; i < nargs; i++) - regs[i + 1] = gpr(i + 3); - - // Prepare and call MacOS routine - gpr(2) = toc; - for (int i = 0; i < nargs; i++) - gpr(i + 3) = args[i]; - execute(proc); - uint32 retval = gpr(3); - - // Restore PowerPC registers - for (int i = 0; i <= nargs; i++) - gpr(i + 2) = regs[i]; - - // Cleanup stack - gpr(1) += 64; - - // Restore program counters and branch registers - pc() = saved_pc; - lr() = saved_lr; - ctr()= saved_ctr; - -#if EMUL_TIME_STATS - macos_exec_time += (clock() - macos_exec_start); -#endif - - return retval; -} - -// Execute ppc routine -inline void sheepshaver_cpu::execute_ppc(uint32 entry) -{ - // Save branch registers - uint32 saved_lr = lr(); - - SheepVar32 trampoline = POWERPC_EXEC_RETURN; - WriteMacInt32(trampoline.addr(), POWERPC_EXEC_RETURN); - lr() = trampoline.addr(); - - execute(entry); - - // Restore branch registers - lr() = saved_lr; -} - -// Resource Manager thunk -inline void sheepshaver_cpu::get_resource(uint32 old_get_resource) -{ - uint32 type = gpr(3); - int16 id = gpr(4); - - // Create stack frame - gpr(1) -= 56; - - // Call old routine - execute_ppc(old_get_resource); - - // Call CheckLoad() - uint32 handle = gpr(3); - check_load_invoc(type, id, handle); - gpr(3) = handle; - - // Cleanup stack - gpr(1) += 56; -} - - -/** - * SheepShaver CPU engine interface - **/ - -// PowerPC CPU emulator -static sheepshaver_cpu *ppc_cpu = NULL; - -void FlushCodeCache(uintptr start, uintptr end) -{ - D(bug("FlushCodeCache(%08x, %08x)\n", start, end)); - ppc_cpu->invalidate_cache_range(start, end); -} - -// Dump PPC registers -static void dump_registers(void) -{ - ppc_cpu->dump_registers(); -} - -// Dump log -static void dump_log(void) -{ - ppc_cpu->dump_log(); -} - -static int read_mem(bfd_vma memaddr, bfd_byte *myaddr, int length, struct disassemble_info *info) -{ - Mac2Host_memcpy(myaddr, memaddr, length); - return 0; -} - -static void dump_disassembly(const uint32 pc, const int prefix_count, const int suffix_count) -{ - struct disassemble_info info; - INIT_DISASSEMBLE_INFO(info, stderr, fprintf); - info.read_memory_func = read_mem; - - const int count = prefix_count + suffix_count + 1; - const uint32 base_addr = pc - prefix_count * 4; - for (int i = 0; i < count; i++) { - const bfd_vma addr = base_addr + i * 4; - fprintf(stderr, "%s0x%8llx: ", addr == pc ? " >" : " ", addr); - print_insn_ppc(addr, &info); - fprintf(stderr, "\n"); - } -} - -sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip) -{ -#if ENABLE_VOSF - // Handle screen fault - extern bool Screen_fault_handler(sigsegv_info_t *sip); - if (Screen_fault_handler(sip)) - return SIGSEGV_RETURN_SUCCESS; -#endif - - const uintptr addr = (uintptr)sigsegv_get_fault_address(sip); -#if HAVE_SIGSEGV_SKIP_INSTRUCTION - // Ignore writes to ROM - if ((addr - (uintptr)ROMBaseHost) < ROM_SIZE) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // Get program counter of target CPU - sheepshaver_cpu * const cpu = ppc_cpu; - const uint32 pc = cpu->pc(); - - // Fault in Mac ROM or RAM? - bool mac_fault = (pc >= ROMBase) && (pc < (ROMBase + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize)) || (pc >= DR_CACHE_BASE && pc < (DR_CACHE_BASE + DR_CACHE_SIZE)); - if (mac_fault) { - - // "VM settings" during MacOS 8 installation - if (pc == ROMBase + 0x488160 && cpu->gpr(20) == 0xf8000000) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // MacOS 8.5 installation - else if (pc == ROMBase + 0x488140 && cpu->gpr(16) == 0xf8000000) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // MacOS 8 serial drivers on startup - else if (pc == ROMBase + 0x48e080 && (cpu->gpr(8) == 0xf3012002 || cpu->gpr(8) == 0xf3012000)) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // MacOS 8.1 serial drivers on startup - else if (pc == ROMBase + 0x48c5e0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - else if (pc == ROMBase + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // MacOS 8.6 serial drivers on startup (with DR Cache and OldWorld ROM) - else if ((pc - DR_CACHE_BASE) < DR_CACHE_SIZE && (cpu->gpr(16) == 0xf3012002 || cpu->gpr(16) == 0xf3012000)) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - else if ((pc - DR_CACHE_BASE) < DR_CACHE_SIZE && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // Ignore writes to the zero page - else if ((uint32)(addr - SheepMem::ZeroPage()) < (uint32)SheepMem::PageSize()) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - - // Ignore all other faults, if requested - if (PrefsFindBool("ignoresegv")) - return SIGSEGV_RETURN_SKIP_INSTRUCTION; - } -#else -#error "FIXME: You don't have the capability to skip instruction within signal handlers" -#endif - - fprintf(stderr, "SIGSEGV\n"); - fprintf(stderr, " pc %p\n", sigsegv_get_fault_instruction_address(sip)); - fprintf(stderr, " ea %p\n", sigsegv_get_fault_address(sip)); - dump_registers(); - ppc_cpu->dump_log(); - dump_disassembly(pc, 8, 8); - - enter_mon(); - QuitEmulator(); - - return SIGSEGV_RETURN_FAILURE; -} - -/* - * Initialize CPU emulation - */ - -void init_emul_ppc(void) -{ - // Get pointer to KernelData in host address space - kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE); - - // Initialize main CPU emulator - ppc_cpu = new sheepshaver_cpu(); - ppc_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROMBase + 0x30d000)); - ppc_cpu->set_register(powerpc_registers::GPR(4), any_register(KernelDataAddr + 0x1000)); - WriteMacInt32(XLM_RUN_MODE, MODE_68K); - -#if ENABLE_MON - // Install "regs" command in cxmon - mon_add_command("regs", dump_registers, "regs Dump PowerPC registers\n"); - mon_add_command("log", dump_log, "log Dump PowerPC emulation log\n"); -#endif - -#if EMUL_TIME_STATS - emul_start_time = clock(); -#endif -} - -/* - * Deinitialize emulation - */ - -void exit_emul_ppc(void) -{ -#if EMUL_TIME_STATS - clock_t emul_end_time = clock(); - - printf("### Statistics for SheepShaver emulation parts\n"); - const clock_t emul_time = emul_end_time - emul_start_time; - printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC)); - printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count, - (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time)); - printf("Total ppc interrupt count: %d (%2.1f %%)\n", ppc_interrupt_count, - (double(ppc_interrupt_count) * 100.0) / double(interrupt_count)); - -#define PRINT_STATS(LABEL, VAR_PREFIX) do { \ - printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count); \ - printf("Total " LABEL " time : %.1f sec (%.1f%%)\n", \ - double(VAR_PREFIX##_time) / double(CLOCKS_PER_SEC), \ - 100.0 * double(VAR_PREFIX##_time) / double(emul_time)); \ - } while (0) - - PRINT_STATS("Execute68k[Trap] execution", exec68k); - PRINT_STATS("NativeOp execution", native_exec); - PRINT_STATS("MacOS routine execution", macos_exec); - -#undef PRINT_STATS - printf("\n"); -#endif - - delete ppc_cpu; - ppc_cpu = NULL; -} - -#if PPC_ENABLE_JIT && PPC_REENTRANT_JIT -// Initialize EmulOp trampolines -void init_emul_op_trampolines(basic_dyngen & dg) -{ - typedef void (*func_t)(dyngen_cpu_base, uint32); - func_t func; - - // EmulOp - emul_op_trampoline = dg.gen_start(); - func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_emul_op).ptr(); - dg.gen_invoke_CPU_T0(func); - dg.gen_exec_return(); - dg.gen_end(); - - // NativeOp - native_op_trampoline = dg.gen_start(); - func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_native_op).ptr(); - dg.gen_invoke_CPU_T0(func); - dg.gen_exec_return(); - dg.gen_end(); - - D(bug("EmulOp trampoline: %p\n", emul_op_trampoline)); - D(bug("NativeOp trampoline: %p\n", native_op_trampoline)); -} -#endif - -/* - * Emulation loop - */ - -void emul_ppc(uint32 entry) -{ -#if 0 - ppc_cpu->start_log(); -#endif - // start emulation loop and enable code translation or caching - ppc_cpu->execute(entry); -} - -/* - * Handle PowerPC interrupt - */ - -void TriggerInterrupt(void) -{ - idle_resume(); -#if 0 - WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); -#else - // Trigger interrupt to main cpu only - if (ppc_cpu) - ppc_cpu->trigger_interrupt(); -#endif -} - -void HandleInterrupt(powerpc_registers *r) -{ -#ifdef USE_SDL_VIDEO - // We must fill in the events queue in the same thread that did call SDL_SetVideoMode() - SDL_PumpEvents(); -#endif - - // Do nothing if interrupts are disabled - if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0) - return; - - // Update interrupt count -#if EMUL_TIME_STATS - interrupt_count++; -#endif - - // Interrupt action depends on current run mode - switch (ReadMacInt32(XLM_RUN_MODE)) { - case MODE_68K: - // 68k emulator active, trigger 68k interrupt level 1 - WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); - r->cr.set(r->cr.get() | tswap32(kernel_data->v[0x674 >> 2])); - break; - -#if INTERRUPTS_IN_NATIVE_MODE - case MODE_NATIVE: - // 68k emulator inactive, in nanokernel? - if (r->gpr[1] != KernelDataAddr) { - - // Prepare for 68k interrupt level 1 - WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); - WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc, - ReadMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc) - | tswap32(kernel_data->v[0x674 >> 2])); - - // Execute nanokernel interrupt routine (this will activate the 68k emulator) - DisableInterrupt(); - if (ROMType == ROMTYPE_NEWWORLD) - ppc_cpu->interrupt(ROMBase + 0x312b1c); - else - ppc_cpu->interrupt(ROMBase + 0x312a3c); - } - break; -#endif - -#if INTERRUPTS_IN_EMUL_OP_MODE - case MODE_EMUL_OP: - // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0 - if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) { -#if EMUL_TIME_STATS - const clock_t interrupt_start = clock(); -#endif -#if 1 - // Execute full 68k interrupt routine - M68kRegisters r; - uint32 old_r25 = ReadMacInt32(XLM_68K_R25); // Save interrupt level - WriteMacInt32(XLM_68K_R25, 0x21); // Execute with interrupt level 1 - static const uint8 proc_template[] = { - 0x3f, 0x3c, 0x00, 0x00, // move.w #$0000,-(sp) (fake format word) - 0x48, 0x7a, 0x00, 0x0a, // pea @1(pc) (return address) - 0x40, 0xe7, // move sr,-(sp) (saved SR) - 0x20, 0x78, 0x00, 0x064, // move.l $64,a0 - 0x4e, 0xd0, // jmp (a0) - M68K_RTS >> 8, M68K_RTS & 0xff // @1 - }; - BUILD_SHEEPSHAVER_PROCEDURE(proc); - Execute68k(proc, &r); - WriteMacInt32(XLM_68K_R25, old_r25); // Restore interrupt level -#else - // Only update cursor - if (HasMacStarted()) { - if (InterruptFlags & INTFLAG_VIA) { - ClearInterruptFlag(INTFLAG_VIA); - ADBInterrupt(); - ExecuteNative(NATIVE_VIDEO_VBL); - } - } -#endif -#if EMUL_TIME_STATS - interrupt_time += (clock() - interrupt_start); -#endif - } - break; -#endif - } -} - -// Execute NATIVE_OP routine -void sheepshaver_cpu::execute_native_op(uint32 selector) -{ -#if EMUL_TIME_STATS - native_exec_count++; - const clock_t native_exec_start = clock(); -#endif - - switch (selector) { - case NATIVE_PATCH_NAME_REGISTRY: - DoPatchNameRegistry(); - break; - case NATIVE_VIDEO_INSTALL_ACCEL: - VideoInstallAccel(); - break; - case NATIVE_VIDEO_VBL: - VideoVBL(); - break; - case NATIVE_VIDEO_DO_DRIVER_IO: - gpr(3) = (int32)(int16)VideoDoDriverIO(gpr(3), gpr(4), gpr(5), gpr(6), gpr(7)); - break; - case NATIVE_ETHER_AO_GET_HWADDR: - AO_get_ethernet_address(gpr(3)); - break; - case NATIVE_ETHER_AO_ADD_MULTI: - AO_enable_multicast(gpr(3)); - break; - case NATIVE_ETHER_AO_DEL_MULTI: - AO_disable_multicast(gpr(3)); - break; - case NATIVE_ETHER_AO_SEND_PACKET: - AO_transmit_packet(gpr(3)); - break; - case NATIVE_ETHER_IRQ: - EtherIRQ(); - break; - case NATIVE_ETHER_INIT: - gpr(3) = InitStreamModule((void *)gpr(3)); - break; - case NATIVE_ETHER_TERM: - TerminateStreamModule(); - break; - case NATIVE_ETHER_OPEN: - gpr(3) = ether_open((queue_t *)gpr(3), (void *)gpr(4), gpr(5), gpr(6), (void*)gpr(7)); - break; - case NATIVE_ETHER_CLOSE: - gpr(3) = ether_close((queue_t *)gpr(3), gpr(4), (void *)gpr(5)); - break; - case NATIVE_ETHER_WPUT: - gpr(3) = ether_wput((queue_t *)gpr(3), (mblk_t *)gpr(4)); - break; - case NATIVE_ETHER_RSRV: - gpr(3) = ether_rsrv((queue_t *)gpr(3)); - break; - case NATIVE_NQD_SYNC_HOOK: - gpr(3) = NQD_sync_hook(gpr(3)); - break; - case NATIVE_NQD_UNKNOWN_HOOK: - gpr(3) = NQD_unknown_hook(gpr(3)); - break; - case NATIVE_NQD_BITBLT_HOOK: - gpr(3) = NQD_bitblt_hook(gpr(3)); - break; - case NATIVE_NQD_BITBLT: - NQD_bitblt(gpr(3)); - break; - case NATIVE_NQD_FILLRECT_HOOK: - gpr(3) = NQD_fillrect_hook(gpr(3)); - break; - case NATIVE_NQD_INVRECT: - NQD_invrect(gpr(3)); - break; - case NATIVE_NQD_FILLRECT: - NQD_fillrect(gpr(3)); - break; - case NATIVE_SERIAL_NOTHING: - case NATIVE_SERIAL_OPEN: - case NATIVE_SERIAL_PRIME_IN: - case NATIVE_SERIAL_PRIME_OUT: - case NATIVE_SERIAL_CONTROL: - case NATIVE_SERIAL_STATUS: - case NATIVE_SERIAL_CLOSE: { - typedef int16 (*SerialCallback)(uint32, uint32); - static const SerialCallback serial_callbacks[] = { - SerialNothing, - SerialOpen, - SerialPrimeIn, - SerialPrimeOut, - SerialControl, - SerialStatus, - SerialClose - }; - gpr(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](gpr(3), gpr(4)); - break; - } - case NATIVE_GET_RESOURCE: - get_resource(ReadMacInt32(XLM_GET_RESOURCE)); - break; - case NATIVE_GET_1_RESOURCE: - get_resource(ReadMacInt32(XLM_GET_1_RESOURCE)); - break; - case NATIVE_GET_IND_RESOURCE: - get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE)); - break; - case NATIVE_GET_1_IND_RESOURCE: - get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE)); - break; - case NATIVE_R_GET_RESOURCE: - get_resource(ReadMacInt32(XLM_R_GET_RESOURCE)); - break; - case NATIVE_MAKE_EXECUTABLE: - MakeExecutable(0, gpr(4), gpr(5)); - break; - case NATIVE_CHECK_LOAD_INVOC: - check_load_invoc(gpr(3), gpr(4), gpr(5)); - break; - case NATIVE_NAMED_CHECK_LOAD_INVOC: - named_check_load_invoc(gpr(3), gpr(4), gpr(5)); - break; - default: - printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector); - QuitEmulator(); - break; - } - -#if EMUL_TIME_STATS - native_exec_time += (clock() - native_exec_start); -#endif -} - -/* - * Execute 68k subroutine (must be ended with EXEC_RETURN) - * This must only be called by the emul_thread when in EMUL_OP mode - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68k(uint32 pc, M68kRegisters *r) -{ - ppc_cpu->execute_68k(pc, r); -} - -/* - * Execute 68k A-Trap from EMUL_OP routine - * r->a[7] is unused, the routine runs on the caller's stack - */ - -void Execute68kTrap(uint16 trap, M68kRegisters *r) -{ - SheepVar proc_var(4); - uint32 proc = proc_var.addr(); - WriteMacInt16(proc, trap); - WriteMacInt16(proc + 2, M68K_RTS); - Execute68k(proc, r); -} - -/* - * Call MacOS PPC code - */ - -uint32 call_macos(uint32 tvect) -{ - return ppc_cpu->execute_macos_code(tvect, 0, NULL); -} - -uint32 call_macos1(uint32 tvect, uint32 arg1) -{ - const uint32 args[] = { arg1 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} - -uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2) -{ - const uint32 args[] = { arg1, arg2 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} - -uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3) -{ - const uint32 args[] = { arg1, arg2, arg3 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} - -uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4) -{ - const uint32 args[] = { arg1, arg2, arg3, arg4 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} - -uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5) -{ - const uint32 args[] = { arg1, arg2, arg3, arg4, arg5 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} - -uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6) -{ - const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} - -uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7) -{ - const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }; - return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/block-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/block-cache.hpp deleted file mode 100644 index 3ba2b635..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/block-cache.hpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * block-cache.hpp - Basic block cache management - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BLOCK_CACHE_H -#define BLOCK_CACHE_H - -#include "block-alloc.hpp" - -template< class block_info, template class block_allocator = slow_allocator > -class block_cache -{ -private: - static const uint32 HASH_BITS = 15; - static const uint32 HASH_SIZE = 1 << HASH_BITS; - static const uint32 HASH_MASK = HASH_SIZE - 1; - - struct entry - : public block_info - { - entry * next_same_cl; - entry ** prev_same_cl_p; - entry * next; - entry ** prev_p; - }; - - block_allocator allocator; - entry * cache_tags[HASH_SIZE]; - entry * active; - entry * dormant; - - uint32 cacheline(uintptr addr) const { - return (addr >> 2) & HASH_MASK; - } - -public: - - block_cache(); - ~block_cache(); - - block_info *new_blockinfo(); - void delete_blockinfo(block_info *bi); - - void initialize(); - void clear(); - void clear_range(uintptr start, uintptr end); - block_info *fast_find(uintptr pc); - block_info *find(uintptr pc); - - void remove_from_cl_list(block_info *bi); - void remove_from_list(block_info *bi); - void remove_from_lists(block_info *bi); - - void add_to_cl_list(block_info *bi); - void raise_in_cl_list(block_info *bi); - - void add_to_active_list(block_info *bi); - void add_to_dormant_list(block_info *bi); -}; - -template< class block_info, template class block_allocator > -block_cache< block_info, block_allocator >::block_cache() - : active(NULL), dormant(NULL) -{ - initialize(); -} - -template< class block_info, template class block_allocator > -block_cache< block_info, block_allocator >::~block_cache() -{ - clear(); -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::initialize() -{ - for (int i = 0; i < HASH_SIZE; i++) - cache_tags[i] = NULL; -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::clear() -{ - entry *p; - - p = active; - while (p) { - entry *d = p; - p = p->next; - delete_blockinfo(d); - } - active = NULL; - - p = dormant; - while (p) { - entry *d = p; - p = p->next; - delete_blockinfo(d); - } - dormant = NULL; -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::clear_range(uintptr start, uintptr end) -{ - if (!active) - return; - - entry *p, *q; - if (cacheline(start) < cacheline(end - 1)) { - // Optimize for short ranges flush - const int end_cl = cacheline(end - 1); - for (int cl = cacheline(start); cl <= end_cl; cl++) { - p = cache_tags[cl]; - while (p) { - q = p; - p = p->next_same_cl; - if (q->intersect(start, end)) { - q->invalidate(); - remove_from_cl_list(q); - remove_from_list(q); - delete_blockinfo(q); - } - } - } - } - else { - p = active; - while (p) { - q = p; - p = p->next; - if (q->intersect(start, end)) { - q->invalidate(); - remove_from_cl_list(q); - remove_from_list(q); - delete_blockinfo(q); - } - } - } -} - -template< class block_info, template class block_allocator > -inline block_info *block_cache< block_info, block_allocator >::new_blockinfo() -{ - entry * bce = allocator.acquire(); - return bce; -} - -template< class block_info, template class block_allocator > -inline void block_cache< block_info, block_allocator >::delete_blockinfo(block_info *bi) -{ - entry * bce = (entry *)bi; - allocator.release(bce); -} - -template< class block_info, template class block_allocator > -inline block_info *block_cache< block_info, block_allocator >::fast_find(uintptr pc) -{ - // Hit: return immediately (that covers more than 95% of the cases) - entry * bce = cache_tags[cacheline(pc)]; - if (bce && bce->pc == pc) - return bce; - - return NULL; -} - -template< class block_info, template class block_allocator > -block_info *block_cache< block_info, block_allocator >::find(uintptr pc) -{ - // Hit: return immediately - entry * bce = cache_tags[cacheline(pc)]; - if (bce && bce->pc == pc) - return bce; - - // Miss: perform full list search and move block to front if found - while (bce) { - bce = bce->next_same_cl; - if (bce && bce->pc == pc) { - raise_in_cl_list(bce); - return bce; - } - } - - // Found none, will have to create a new block - return NULL; -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::remove_from_cl_list(block_info *bi) -{ - entry * bce = (entry *)bi; - if (bce->prev_same_cl_p) - *bce->prev_same_cl_p = bce->next_same_cl; - if (bce->next_same_cl) - bce->next_same_cl->prev_same_cl_p = bce->prev_same_cl_p; -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::add_to_cl_list(block_info *bi) -{ - entry * bce = (entry *)bi; - const uint32 cl = cacheline(bi->pc); - if (cache_tags[cl]) - cache_tags[cl]->prev_same_cl_p = &bce->next_same_cl; - bce->next_same_cl = cache_tags[cl]; - - cache_tags[cl] = bce; - bce->prev_same_cl_p = &cache_tags[cl]; -} - -template< class block_info, template class block_allocator > -inline void block_cache< block_info, block_allocator >::raise_in_cl_list(block_info *bi) -{ - remove_from_cl_list(bi); - add_to_cl_list(bi); -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::remove_from_list(block_info *bi) -{ - entry * bce = (entry *)bi; - if (bce->prev_p) - *bce->prev_p = bce->next; - if (bce->next) - bce->next->prev_p = bce->prev_p; -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::add_to_active_list(block_info *bi) -{ - entry * bce = (entry *)bi; - - if (active) - active->prev_p = &bce->next; - bce->next = active; - - active = bce; - bce->prev_p = &active; -} - -template< class block_info, template class block_allocator > -void block_cache< block_info, block_allocator >::add_to_dormant_list(block_info *bi) -{ - entry * bce = (entry *)bi; - - if (dormant) - dormant->prev_p = &bce->next; - bce->next = dormant; - - dormant = bce; - bce->prev_p = &dormant; -} - -template< class block_info, template class block_allocator > -inline void block_cache< block_info, block_allocator >::remove_from_lists(block_info *bi) -{ - remove_from_cl_list(bi); - remove_from_list(bi); -} - -#endif /* BLOCK_CACHE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/dyngen-target-exec.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/dyngen-target-exec.h deleted file mode 100644 index 14b070d0..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/dyngen-target-exec.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * dyngen defines for micro operation code - * - * Copyright (c) 2003-2004-2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DYNGEN_TARGET_EXEC_H -#define DYNGEN_TARGET_EXEC_H - -enum { - /* callee save registers */ -#define AREG0 "rbp" - AREG0_ID = 5, - -/* - * Use of rbx register with gcc 4.2 on Mac OS 10.6 - * does not produce usable code. Just use r12 to r15. - */ -#if (defined(__APPLE__) && defined(__MACH__)) - -#define AREG1 "r12" - AREG1_ID = 12, - -#define AREG2 "r13" - AREG2_ID = 13, - -#define AREG3 "r14" - AREG3_ID = 14, - -#define AREG4 "r15" - AREG4_ID = 15, - -#else - -#define AREG1 "rbx" - AREG1_ID = 3, - -#define AREG2 "r12" - AREG2_ID = 12, - -#define AREG3 "r13" - AREG3_ID = 13, - -#define AREG4 "r14" - AREG4_ID = 14, - -#define AREG5 "r15" - AREG5_ID = 15, - -#endif - - - // NOTE: the following XMM registers definitions require to build - // *-dyngen-ops.cpp with -ffixed-xmmN - - /* floating-point registers */ -#define FREG0 "xmm4" - FREG0_ID = 4, - -#define FREG1 "xmm5" - FREG1_ID = 5, - -#define FREG2 "xmm6" - FREG2_ID = 6, - -#define FREG3 "xmm7" - FREG3_ID = 7, - - /* vector registers -- aliased to FP registers, not intermixed */ -#define VREG0 FREG0 -#define VREG0_ID FREG0_ID -#define VREG1 FREG1 -#define VREG1_ID FREG1_ID -#define VREG2 FREG2 -#define VREG2_ID FREG2_ID -#define VREG3 FREG3 -#define VREG3_ID FREG3_ID -}; - -#endif /* DYNGEN_TARGET_EXEC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-cache.hpp deleted file mode 100644 index f411d3bb..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-cache.hpp +++ /dev/null @@ -1 +0,0 @@ -#include "cpu/jit/dummy/jit-target-cache.hpp" diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-codegen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-codegen.hpp deleted file mode 100644 index e4611d69..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/amd64/jit-target-codegen.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * jit-target-codegen.hpp - Target specific code generator - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_AMD64_CODEGEN_H -#define JIT_AMD64_CODEGEN_H - -#define X86_TARGET_64BIT 1 -#include "cpu/jit/x86/jit-target-codegen.hpp" - -class amd64_codegen - : public x86_codegen -{ -public: - -#define DEFINE_OP(NAME, OP) \ - void gen_##NAME(int s, int d) \ - { GEN_CODE(OP##rr(s, d)); } \ - void gen_##NAME(x86_memory_operand const & mem, int d) \ - { GEN_CODE(OP##mr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - - DEFINE_OP(sx_8_64, MOVSBQ); - DEFINE_OP(zx_8_64, MOVZBQ); - DEFINE_OP(sx_16_64, MOVSWQ); - DEFINE_OP(zx_16_64, MOVZWQ); - DEFINE_OP(sx_32_64, MOVSLQ); - -#undef DEFINE_OP - -public: - - void gen_push(int r) - { GEN_CODE(PUSHQr(r)); } - void gen_push(x86_memory_operand const & mem) - { GEN_CODE(PUSHQm(mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_pop(int r) - { GEN_CODE(POPQr(r)); } - void gen_pop(x86_memory_operand const & mem) - { GEN_CODE(POPQm(mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_bswap_64(int r) - { GEN_CODE(BSWAPQr(r)); } - void gen_lea_64(x86_memory_operand const & mem, int d) - { GEN_CODE(LEAQmr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - -public: - - void gen_mov_64(int s, int d) - { GEN_CODE(MOVQrr(s, d)); } - void gen_mov_64(x86_memory_operand const & mem, int d) - { GEN_CODE(MOVQmr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_mov_64(int s, x86_memory_operand const & mem) - { GEN_CODE(MOVQrm(s, mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_mov_64(x86_immediate_operand const & imm, int d) - { GEN_CODE(MOVQir(imm.value, d)); } - void gen_mov_64(x86_immediate_operand const & imm, x86_memory_operand const & mem) - { GEN_CODE(MOVQim(imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } - -private: - - void gen_rotshi_64(int op, int s, int d) - { GEN_CODE(_ROTSHIQrr(op, s, d)); } - void gen_rotshi_64(int op, int s, x86_memory_operand const & mem) - { GEN_CODE(_ROTSHIQrm(op, s, mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_rotshi_64(int op, x86_immediate_operand const & imm, int d) - { GEN_CODE(_ROTSHIQir(op, imm.value, d)); } - void gen_rotshi_64(int op, x86_immediate_operand const & imm, x86_memory_operand const & mem) - { GEN_CODE(_ROTSHIQim(op, imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } - -public: - -#define DEFINE_OP(NAME, OP) \ - void gen_##NAME##_64(int s, int d) \ - { gen_rotshi_64(X86_##OP, s, d); } \ - void gen_##NAME##_64(int s, x86_memory_operand const & mem) \ - { gen_rotshi_64(X86_##OP, s, mem); } \ - void gen_##NAME##_64(x86_immediate_operand const & imm, int d) \ - { gen_rotshi_64(X86_##OP, imm, d); } \ - void gen_##NAME##_64(x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { gen_rotshi_64(X86_##OP, imm, mem); } - - DEFINE_OP(rol, ROL); - DEFINE_OP(ror, ROR); - DEFINE_OP(rcl, RCL); - DEFINE_OP(rcr, RCR); - DEFINE_OP(shl, SHL); - DEFINE_OP(shr, SHR); - DEFINE_OP(sar, SAR); - -#undef DEFINE_OP -}; - -#endif /* JIT_AMD64_CODEGEN_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp deleted file mode 100644 index 7b9feebc..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* - * dyngen-ops.hpp - Synthetic opcodes - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "cpu/vm.hpp" -#include "cpu/jit/dyngen-exec.h" - -#include - -// We need at least 5 general purpose registers -struct basic_cpu; -register basic_cpu *CPU asm(REG_CPU); -#define DYNGEN_DEFINE_GLOBAL_REGISTER(REG) \ -register uintptr A##REG asm(REG_T##REG); \ -register uint32 T##REG asm(REG_T##REG) -DYNGEN_DEFINE_GLOBAL_REGISTER(0); -DYNGEN_DEFINE_GLOBAL_REGISTER(1); -DYNGEN_DEFINE_GLOBAL_REGISTER(2); - - -/** - * Native ALU operations optimization - **/ - -#if defined(__i386__) || defined(__x86_64__) -#define do_xchg_32(x, y) asm volatile ("xchg %0,%1" : "+r" (x), "+r" (y)) -#endif -#ifndef do_udiv_32 -#define do_udiv_32(x, y) ((uint32)x / (uint32)y) -#endif -#ifndef do_sdiv_32 -#define do_sdiv_32(x, y) ((int32)x / (int32)y) -#endif -#ifndef do_rol_32 -#define do_rol_32(x, y) ((x << y) | (x >> (32 - y))) -#endif -#ifndef do_ror_32 -#define do_ror_32(x, y) ((x >> y) | (x << (32 - y))) -#endif -#ifndef do_xchg_32 -#define do_xchg_32(x, y) do { uint32 t = x; x = y; y = t; } while (0) -#endif - - -/** - * ALU operations - **/ - -// XXX update for new 64-bit arches -#if defined __x86_64__ -#define MOV_AD_REG(PARAM, REG) asm volatile ("movabsq $__op_" #PARAM ",%0" : "=r" (REG)) -#else -#define MOV_AD_REG(PARAM, REG) REG = PARAM -#endif - -#define DEFINE_OP(REG) \ -void OPPROTO op_mov_ad_##REG##_im(void) \ -{ \ - MOV_AD_REG(PARAM1, REG); \ -} - -DEFINE_OP(A0); -DEFINE_OP(A1); -DEFINE_OP(A2); - -#undef DEFINE_OP - -#define DEFINE_OP(NAME, CODE) \ -void OPPROTO op_##NAME(void) \ -{ \ - CODE; \ -} - -// Register moves -DEFINE_OP(mov_32_T0_im, T0 = PARAM1); -DEFINE_OP(mov_32_T0_T1, T0 = T1); -DEFINE_OP(mov_32_T0_T2, T0 = T2); -DEFINE_OP(mov_32_T1_im, T1 = PARAM1); -DEFINE_OP(mov_32_T1_T0, T1 = T0); -DEFINE_OP(mov_32_T1_T2, T1 = T2); -DEFINE_OP(mov_32_T2_im, T2 = PARAM1); -DEFINE_OP(mov_32_T2_T1, T2 = T1); -DEFINE_OP(mov_32_T2_T0, T2 = T0); -DEFINE_OP(mov_32_T0_0, T0 = 0); -DEFINE_OP(mov_32_T1_0, T1 = 0); -DEFINE_OP(mov_32_T2_0, T2 = 0); - -// Arithmetic operations -DEFINE_OP(add_32_T0_T2, T0 += T2); -DEFINE_OP(add_32_T0_T1, T0 += T1); -DEFINE_OP(add_32_T0_im, T0 += PARAM1); -DEFINE_OP(add_32_T0_1, T0 += 1); -DEFINE_OP(add_32_T0_2, T0 += 2); -DEFINE_OP(add_32_T0_4, T0 += 4); -DEFINE_OP(add_32_T0_8, T0 += 8); -DEFINE_OP(sub_32_T0_T2, T0 -= T2); -DEFINE_OP(sub_32_T0_T1, T0 -= T1); -DEFINE_OP(sub_32_T0_im, T0 -= PARAM1); -DEFINE_OP(sub_32_T0_1, T0 -= 1); -DEFINE_OP(sub_32_T0_2, T0 -= 2); -DEFINE_OP(sub_32_T0_4, T0 -= 4); -DEFINE_OP(sub_32_T0_8, T0 -= 8); -DEFINE_OP(add_32_T1_T2, T1 += T2); -DEFINE_OP(add_32_T1_T0, T1 += T0); -DEFINE_OP(add_32_T1_im, T1 += PARAM1); -DEFINE_OP(add_32_T1_1, T1 += 1); -DEFINE_OP(add_32_T1_2, T1 += 2); -DEFINE_OP(add_32_T1_4, T1 += 4); -DEFINE_OP(add_32_T1_8, T1 += 8); -DEFINE_OP(sub_32_T1_T2, T1 -= T2); -DEFINE_OP(sub_32_T1_T0, T1 -= T0); -DEFINE_OP(sub_32_T1_im, T1 -= PARAM1); -DEFINE_OP(sub_32_T1_1, T1 -= 1); -DEFINE_OP(sub_32_T1_2, T1 -= 2); -DEFINE_OP(sub_32_T1_4, T1 -= 4); -DEFINE_OP(sub_32_T1_8, T1 -= 8); -DEFINE_OP(umul_32_T0_T1, T0 = (uint32)T0 * (uint32)T1); -DEFINE_OP(smul_32_T0_T1, T0 = (int32)T0 * (int32)T1); -DEFINE_OP(udiv_32_T0_T1, T0 = do_udiv_32(T0, T1)); -DEFINE_OP(sdiv_32_T0_T1, T0 = do_sdiv_32(T0, T1)); -DEFINE_OP(xchg_32_T0_T1, do_xchg_32(T0, T1)); -DEFINE_OP(bswap_16_T0, T0 = bswap_16(T0)); -DEFINE_OP(bswap_32_T0, T0 = bswap_32(T0)); - -// Logical operations -DEFINE_OP(neg_32_T0, T0 = -T0); -DEFINE_OP(not_32_T0, T0 = !T0); -DEFINE_OP(not_32_T1, T1 = !T1); -DEFINE_OP(and_32_T0_T1, T0 &= T1); -DEFINE_OP(and_32_T0_im, T0 &= PARAM1); -DEFINE_OP(or_32_T0_T1, T0 |= T1); -DEFINE_OP(or_32_T0_im, T0 |= PARAM1); -DEFINE_OP(xor_32_T0_T1, T0 ^= T1); -DEFINE_OP(xor_32_T0_im, T0 ^= PARAM1); -DEFINE_OP(orc_32_T0_T1, T0 |= ~T1); -DEFINE_OP(andc_32_T0_T1, T0 &= ~T1); -DEFINE_OP(nand_32_T0_T1, T0 = ~(T0 & T1)); -DEFINE_OP(nor_32_T0_T1, T0 = ~(T0 | T1)); -DEFINE_OP(eqv_32_T0_T1, T0 = ~(T0 ^ T1)); - -// Shift/Rotate operations -DEFINE_OP(lsl_32_T0_T1, T0 = T0 << T1); -DEFINE_OP(lsl_32_T0_im, T0 = T0 << PARAM1); -DEFINE_OP(lsr_32_T0_T1, T0 = T0 >> T1); -DEFINE_OP(lsr_32_T0_im, T0 = T0 >> PARAM1); -DEFINE_OP(asr_32_T0_T1, T0 = ((int32)T0) >> T1); -DEFINE_OP(asr_32_T0_im, T0 = ((int32)T0) >> PARAM1); -DEFINE_OP(rol_32_T0_T1, T0 = do_rol_32(T0, T1)); -DEFINE_OP(rol_32_T0_im, T0 = do_rol_32(T0, PARAM1)); -DEFINE_OP(ror_32_T0_T1, T0 = do_ror_32(T0, T1)); -DEFINE_OP(ror_32_T0_im, T0 = do_ror_32(T0, PARAM1)); - -// Sign-/Zero-extension -DEFINE_OP(se_16_32_T0, T0 = (int32)(int16)T0); -DEFINE_OP(se_16_32_T1, T1 = (int32)(int16)T1); -DEFINE_OP(ze_16_32_T0, T0 = (uint32)(uint16)T0); -DEFINE_OP(se_8_32_T0, T0 = (int32)(int8)T0); -DEFINE_OP(ze_8_32_T0, T0 = (uint32)(uint8)T0); - -#undef DEFINE_OP - - -/** - * Load/Store instructions - **/ - -#define im PARAM1 -#define DEFINE_OP(BITS,REG,SIZE,OFFSET) \ -void OPPROTO op_load_u##BITS##_##REG##_T1_##OFFSET(void) \ -{ \ - REG = (uint32)(uint##BITS)vm_read_memory_##SIZE(T1 + OFFSET); \ -} \ -void OPPROTO op_load_s##BITS##_##REG##_T1_##OFFSET(void) \ -{ \ - REG = (int32)(int##BITS)vm_read_memory_##SIZE(T1 + OFFSET); \ -} \ -void OPPROTO op_store_##BITS##_##REG##_T1_##OFFSET(void) \ -{ \ - vm_write_memory_##SIZE(T1 + OFFSET, REG); \ -} - -DEFINE_OP(32,T0,4,0); -DEFINE_OP(32,T0,4,im); -DEFINE_OP(32,T0,4,T2); -DEFINE_OP(16,T0,2,0); -DEFINE_OP(16,T0,2,im); -DEFINE_OP(16,T0,2,T2); -DEFINE_OP(8,T0,1,0); -DEFINE_OP(8,T0,1,im); -DEFINE_OP(8,T0,1,T2); - -#undef im -#undef DEFINE_OP - - -/** - * Control flow - **/ - -#ifdef __i386__ -#define FORCE_RET() asm volatile ("ret") -#endif -#ifdef __x86_64__ -#define FORCE_RET() asm volatile ("ret") -#endif -#ifdef __powerpc__ -#define FORCE_RET() asm volatile ("blr") -#endif -#ifdef __ppc__ -#define FORCE_RET() asm volatile ("blr") -#endif -#ifdef __s390__ -#define FORCE_RET() asm volatile ("br %r14") -#endif -#ifdef __alpha__ -#define FORCE_RET() asm volatile ("ret") -#endif -#ifdef __ia64__ -#define FORCE_RET() asm volatile ("br.ret.sptk.many b0;;") -#endif -#ifdef __sparc__ -#define FORCE_RET() asm volatile ("jmpl %i0 + 8, %g0\n" \ - "nop") -#endif -#ifdef __arm__ -#define FORCE_RET() asm volatile ("b exec_loop") -#endif -#ifdef __mc68000 -#define FORCE_RET() asm volatile ("rts") -#endif - -extern "C" void OPPROTO op_execute(uint8 *entry_point, basic_cpu *this_cpu); -void OPPROTO op_execute(uint8 *entry_point, basic_cpu *this_cpu) -{ - typedef void (*func_t)(void); - func_t func = (func_t)entry_point; - const int n_slots = 16 + 4; /* 16 stack slots + 4 VCPU registers */ - volatile uintptr stk[n_slots]; - stk[n_slots - 1] = (uintptr)CPU; - stk[n_slots - 2] = A0; - stk[n_slots - 3] = A1; - stk[n_slots - 4] = A2; - CPU = this_cpu; - DYNGEN_SLOW_DISPATCH(entry_point); - func(); // NOTE: never called, fake to make compiler save return point -#ifdef ASM_OP_EXEC_RETURN_INSN - asm volatile ("1: .byte " ASM_OP_EXEC_RETURN_INSN); -#else - asm volatile (ASM_DATA_SECTION); - asm volatile (ASM_GLOBAL " " ASM_NAME(op_exec_return_offset)); - asm volatile (ASM_NAME(op_exec_return_offset) ":"); - asm volatile (ASM_LONG " 1f-" ASM_NAME(op_execute)); - asm volatile (ASM_SIZE(op_exec_return_offset)); - asm volatile (ASM_PREVIOUS_SECTION); - asm volatile ("1:"); -#endif - A2 = stk[n_slots - 4]; - A1 = stk[n_slots - 3]; - A0 = stk[n_slots - 2]; - CPU = (basic_cpu *)stk[n_slots - 1]; -} - -void OPPROTO op_jmp_slow(void) -{ - DYNGEN_SLOW_DISPATCH(PARAM1); -} - -void OPPROTO op_jmp_fast(void) -{ -#ifdef DYNGEN_FAST_DISPATCH - DYNGEN_FAST_DISPATCH(__op_PARAM1); -#else - DYNGEN_SLOW_DISPATCH(PARAM1); -#endif -} - -void OPPROTO op_jmp_A0(void) -{ - DYNGEN_SLOW_DISPATCH(A0); -} - -// Register calling conventions based arches don't need a stack frame -// XXX enable on x86 too because we allocated a frame in op_execute() -#if (defined __APPLE__ && defined __MACH__) -#define DEFINE_OP(NAME, CODE) \ -static void OPPROTO impl_##NAME(void) __attribute__((used)); \ -void OPPROTO impl_##NAME(void) \ -{ \ - asm volatile (#NAME ":"); \ - CODE; \ - FORCE_RET(); \ - asm volatile ("." #NAME ":"); \ - asm volatile (ASM_SIZE(NAME)); \ -} \ -extern void OPPROTO NAME(void) __attribute__((weak_import)); \ -asm(".set helper_" #NAME "," #NAME); -#elif defined(__powerpc__) || ((defined(__x86_64__) || defined(__i386__)) && !defined(_WIN32)) -// XXX there is a problem on Windows: coff_text_shndx != text_shndx -// The latter is found by searching for ".text" in all symbols and -// assigning its e_scnum. -#define DEFINE_OP(NAME, CODE) \ -static void OPPROTO impl_##NAME(void) __attribute__((used)); \ -void OPPROTO impl_##NAME(void) \ -{ \ - asm volatile (#NAME ":"); \ - CODE; \ - FORCE_RET(); \ - asm volatile ("." #NAME ":"); \ - asm volatile (ASM_SIZE(NAME)); \ -} \ -asm(".weak " #NAME); \ -asm(".set helper_" #NAME "," #NAME); -#else -#define DEFINE_OP(NAME, CODE) \ -extern "C" void OPPROTO NAME(void); \ -void OPPROTO NAME(void) \ -{ \ - CODE; \ -} -#endif - -#if defined __mips__ -#define CALL(FUNC, ARGS) ({ \ - register uintptr func asm("t9"); \ - asm volatile ("move %0,%1" : "=r" (func) : "r" (FUNC)); \ - ((func_t)func) ARGS; \ -}) -#else -#define CALL(FUNC, ARGS) ((func_t)FUNC) ARGS -#endif - -DEFINE_OP(op_invoke, { - typedef void (*func_t)(void); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, ()); -}); - -DEFINE_OP(op_invoke_T0, { - typedef void (*func_t)(uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (T0)); -}); - -DEFINE_OP(op_invoke_T0_T1, { - typedef void (*func_t)(uint32, uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (T0, T1)); -}); - -DEFINE_OP(op_invoke_T0_T1_T2, { - typedef void (*func_t)(uint32, uint32, uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (T0, T1, T2)); -}); - -DEFINE_OP(op_invoke_T0_ret_T0, { - typedef uint32 (*func_t)(uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - T0 = CALL(func, (T0)); -}); - -DEFINE_OP(op_invoke_im, { - typedef void (*func_t)(uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (PARAM2)); -}); - -DEFINE_OP(op_invoke_CPU, { - typedef void (*func_t)(void *); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (CPU)); -}); - -DEFINE_OP(op_invoke_CPU_T0, { - typedef void (*func_t)(void *, uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (CPU, T0)); -}); - -DEFINE_OP(op_invoke_CPU_im, { - typedef void (*func_t)(void *, uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (CPU, PARAM2)); -}); - -DEFINE_OP(op_invoke_CPU_im_im, { - typedef void (*func_t)(void *, uint32, uint32); - uintptr func; - MOV_AD_REG(PARAM1, func); - CALL(func, (CPU, PARAM2, PARAM3)); -}); - -DEFINE_OP(op_invoke_CPU_A0_ret_A0, { - typedef void *(*func_t)(void *, uintptr); - uintptr func; - MOV_AD_REG(PARAM1, func); - A0 = (uintptr)CALL(func, (CPU, A0)); -}); - -DEFINE_OP(op_invoke_direct, { - typedef void (*func_t)(void); - CALL(PARAM1, ()); -}); - -DEFINE_OP(op_invoke_direct_T0, { - typedef void (*func_t)(uint32); - CALL(PARAM1, (T0)); -}); - -DEFINE_OP(op_invoke_direct_T0_T1, { - typedef void (*func_t)(uint32, uint32); - CALL(PARAM1, (T0, T1)); -}); - -DEFINE_OP(op_invoke_direct_T0_T1_T2, { - typedef void (*func_t)(uint32, uint32, uint32); - CALL(PARAM1, (T0, T1, T2)); -}); - -DEFINE_OP(op_invoke_direct_T0_ret_T0, { - typedef uint32 (*func_t)(uint32); - T0 = CALL(PARAM1, (T0)); -}); - -DEFINE_OP(op_invoke_direct_im, { - typedef void (*func_t)(uint32); - CALL(PARAM1, (PARAM2)); -}); - -DEFINE_OP(op_invoke_direct_CPU, { - typedef void (*func_t)(void *); - CALL(PARAM1, (CPU)); -}); - -DEFINE_OP(op_invoke_direct_CPU_T0, { - typedef void (*func_t)(void *, uint32); - CALL(PARAM1, (CPU, T0)); -}); - -DEFINE_OP(op_invoke_direct_CPU_im, { - typedef void (*func_t)(void *, uint32); - CALL(PARAM1, (CPU, PARAM2)); -}); - -DEFINE_OP(op_invoke_direct_CPU_im_im, { - typedef void (*func_t)(void *, uint32, uint32); - CALL(PARAM1, (CPU, PARAM2, PARAM3)); -}); - -DEFINE_OP(op_invoke_direct_CPU_A0_ret_A0, { - typedef void *(*func_t)(void *, uintptr); - A0 = (uintptr)CALL(PARAM1, (CPU, A0)); -}); - -#undef DEFINE_OP diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp deleted file mode 100644 index 4d214b73..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * dyngen-glue.hpp - Glue to QEMU dyngen infrastructure - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "basic-dyngen.hpp" - -int __op_param1, __op_param2, __op_param3; -int __op_jmp0, __op_jmp1; - -#define DYNGEN_IMPL 1 -#define DEFINE_GEN(NAME,RET,ARGS) RET basic_dyngen::NAME ARGS -#include "basic-dyngen-ops.hpp" - -basic_dyngen::basic_dyngen(dyngen_cpu_base cpu) - : parent_cpu(cpu) -{ -} - -bool -basic_dyngen::initialize(void) -{ - if (!jit_codegen::initialize()) - return false; - - execute_func = gen_start(); - gen_op_execute(); - gen_end(); - set_code_start(code_ptr()); - -#if PPC_REENTRANT_JIT -#ifdef SHEEPSHAVER - extern void init_emul_op_trampolines(basic_dyngen & dg); - init_emul_op_trampolines(*this); - set_code_start(code_ptr()); -#endif -#endif - - return true; -} - -void -basic_dyngen::gen_invoke(void (*func)()) -{ - uintptr funcptr = (uintptr)func; - if (direct_call_possible(funcptr)) - gen_op_invoke_direct(funcptr); - else - gen_op_invoke(funcptr); -} - -#define DEFINE_INVOKE(NAME, ARGS, IARGS) \ -void \ -basic_dyngen::gen_invoke_##NAME ARGS \ -{ \ - uintptr funcptr = (uintptr)func; \ - if (direct_call_possible(funcptr)) \ - gen_op_invoke_direct_##NAME IARGS; \ - else \ - gen_op_invoke_##NAME IARGS; \ -} - -DEFINE_INVOKE(T0, (void (*func)(uint32)), (funcptr)); -DEFINE_INVOKE(T0_T1, (void (*func)(uint32, uint32)), (funcptr)); -DEFINE_INVOKE(T0_T1_T2, (void (*func)(uint32, uint32, uint32)), (funcptr)); -DEFINE_INVOKE(T0_ret_T0, (uint32 (*func)(uint32)), (funcptr)); -DEFINE_INVOKE(im, (void (*func)(uint32), uint32 value), (funcptr, value)); -DEFINE_INVOKE(CPU, (void (*func)(dyngen_cpu_base)), (funcptr)); -DEFINE_INVOKE(CPU_T0, (void (*func)(dyngen_cpu_base, uint32)), (funcptr)); -DEFINE_INVOKE(CPU_im, (void (*func)(dyngen_cpu_base, uint32), uint32 value), (funcptr, value)); -DEFINE_INVOKE(CPU_im_im, (void (*func)(dyngen_cpu_base, uint32, uint32), uint32 param1, uint32 param2), (funcptr, param1, param2)); -DEFINE_INVOKE(CPU_A0_ret_A0, (void *(*func)(dyngen_cpu_base)), (funcptr)); - -#undef DEFINE_INVOKE - -uint8 * -basic_dyngen::gen_align(int align) -{ - int nbytes = align - (((uintptr)code_ptr()) % align); - if (nbytes == 0) - return code_ptr(); - -#if defined(__i386__) || defined(__x86_64__) - /* Source: GNU Binutils 2.12.90.0.15 */ - /* Various efficient no-op patterns for aligning code labels. - Note: Don't try to assemble the instructions in the comments. - 0L and 0w are not legal. */ - static const uint8 f32_1[] = - {0x90}; /* nop */ - static const uint8 f32_2[] = - {0x89,0xf6}; /* movl %esi,%esi */ - static const uint8 f32_3[] = - {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ - static const uint8 f32_4[] = - {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const uint8 f32_5[] = - {0x90, /* nop */ - 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const uint8 f32_6[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ - static const uint8 f32_7[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const uint8 f32_8[] = - {0x90, /* nop */ - 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const uint8 f32_9[] = - {0x89,0xf6, /* movl %esi,%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uint8 f32_10[] = - {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uint8 f32_11[] = - {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uint8 f32_12[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ - static const uint8 f32_13[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uint8 f32_14[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const uint8 f32_15[] = - {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const uint8 f32_16[] = - {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const uint8 *const f32_patt[] = { - f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, - f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 - }; - static const uint8 prefixes[4] = { 0x66, 0x66, 0x66, 0x66 }; - -#if defined(__x86_64__) - /* The recommended way to pad 64bit code is to use NOPs preceded by - maximally four 0x66 prefixes. Balance the size of nops. */ - int i; - int nnops = (nbytes + 3) / 4; - int len = nbytes / nnops; - int remains = nbytes - nnops * len; - - for (i = 0; i < remains; i++) { - emit_block(prefixes, len); - emit_8(0x90); // NOP - } - for (; i < nnops; i++) { - emit_block(prefixes, len - 1); - emit_8(0x90); // NOP - } -#else - int nloops = nbytes / 16; - while (nloops-- > 0) - emit_block(f32_16, sizeof(f32_16)); - - nbytes %= 16; - if (nbytes) - emit_block(f32_patt[nbytes - 1], nbytes); -#endif -#else -#warning "FIXME: tune for your target" - for (int i = 0; i < nbytes; i++) - emit_8(0); -#endif - return code_ptr(); -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp deleted file mode 100644 index f04cd5ef..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * basic-dyngen.hpp - Basic code generator - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef BASIC_DYNGEN_H -#define BASIC_DYNGEN_H - -#include "cpu/jit/jit-config.hpp" -#include "cpu/jit/jit-codegen.hpp" - -// Set jump target address -static inline void dg_set_jmp_target_noflush(uint8 *jmp_addr, uint8 *addr) -{ -#if defined(__powerpc__) || defined(__ppc__) - // patch the branch destination - uint32 *ptr = (uint32 *)jmp_addr; - uint32 val = *ptr; - val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc); - *ptr = val; -#endif -#if defined(__i386__) || defined(__x86_64__) - // patch the branch destination - *(uint32 *)jmp_addr = addr - (jmp_addr + 4); -#endif -} - -static inline void dg_set_jmp_target(uint8 *jmp_addr, uint8 *addr) -{ - dg_set_jmp_target_noflush(jmp_addr, addr); -#if defined(__powerpc__) || defined(__ppc__) - // flush icache - asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); - asm volatile ("sync" : : : "memory"); - asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory"); - asm volatile ("sync" : : : "memory"); - asm volatile ("isync" : : : "memory"); -#endif -} - -#ifdef SHEEPSHAVER -class powerpc_cpu; -typedef powerpc_cpu *dyngen_cpu_base; -#else -class basic_cpu; -typedef basic_cpu *dyngen_cpu_base; -#endif - -class basic_dyngen - : public jit_codegen -{ - uint8 *execute_func; - uint8 *gen_code_start; - dyngen_cpu_base parent_cpu; - - // Can we generate a direct call to target function? - bool direct_jump_possible(uintptr target) const; - bool direct_call_possible(uintptr target) const; - - // Generic code generators -# define DEFINE_CST(NAME,VALUE) static const unsigned long NAME = VALUE; -# define DEFINE_GEN(NAME,RET,ARGS) RET NAME ARGS; -# include "basic-dyngen-ops.hpp" - -public: - - // Constructor, parent CPU required - basic_dyngen(dyngen_cpu_base cpu); - - // Initialization - bool initialize(void); - - // Return CPU context associated to this code generator - dyngen_cpu_base cpu() const - { return parent_cpu; } - - // Align on ALIGN byte boundaries, ALIGN must be a power of 2 - uint8 *gen_align(int align = 16); - - // Start code generation of a new block - // Align on 16-byte boundaries - // Returns pointer to entry point - uint8 *gen_start(); - - // Stop code generation of the block - // Returns FALSE if translation cache is full - bool gen_end() const; - - // Execute compiled function at ENTRY_POINT - void execute(uint8 *entry_point); - - // Return from compiled code - void gen_exec_return(); - - // Function calls - void gen_jmp(const uint8 *target); - void gen_invoke(void (*func)(void)); - void gen_invoke_T0(void (*func)(uint32)); - void gen_invoke_T0_T1(void (*func)(uint32, uint32)); - void gen_invoke_T0_T1_T2(void (*func)(uint32, uint32, uint32)); - void gen_invoke_T0_ret_T0(uint32 (*func)(uint32)); - void gen_invoke_im(void (*func)(uint32), uint32 value); - void gen_invoke_CPU(void (*func)(dyngen_cpu_base)); - void gen_invoke_CPU_T0(void (*func)(dyngen_cpu_base, uint32)); - void gen_invoke_CPU_im(void (*func)(dyngen_cpu_base, uint32), uint32 value); - void gen_invoke_CPU_im_im(void (*func)(dyngen_cpu_base, uint32, uint32), uint32 param1, uint32 param2); - void gen_invoke_CPU_A0_ret_A0(void *(*func)(dyngen_cpu_base)); - - // Raw aliases -#define DEFINE_ALIAS_RAW(NAME, ARGLIST, ARGS) \ - void gen_##NAME ARGLIST { gen_op_##NAME ARGS; } - -#define DEFINE_ALIAS_0(NAME) DEFINE_ALIAS_RAW(NAME,(),()) -#define DEFINE_ALIAS_1(NAME) DEFINE_ALIAS_RAW(NAME,(long p1),(p1)) -#define DEFINE_ALIAS_2(NAME) DEFINE_ALIAS_RAW(NAME,(long p1,long p2),(p1,p2)) -#define DEFINE_ALIAS_3(NAME) DEFINE_ALIAS_RAW(NAME,(long p1,long p2,long p3),(p1,p2,p3)) -#define DEFINE_ALIAS(NAME, N) DEFINE_ALIAS_##N(NAME) - - // Register moves - void gen_mov_32_T0_im(int32 value); - DEFINE_ALIAS(mov_32_T0_T1,0); - DEFINE_ALIAS(mov_32_T0_T2,0); - void gen_mov_32_T1_im(int32 value); - DEFINE_ALIAS(mov_32_T1_T0,0); - DEFINE_ALIAS(mov_32_T1_T2,0); - void gen_mov_32_T2_im(int32 value); - DEFINE_ALIAS(mov_32_T2_T0,0); - DEFINE_ALIAS(mov_32_T2_T1,0); - DEFINE_ALIAS(mov_ad_A0_im,1); - DEFINE_ALIAS(mov_ad_A1_im,1); - DEFINE_ALIAS(mov_ad_A2_im,1); - - // Arithmetic operations - DEFINE_ALIAS(add_32_T0_T1,0); - DEFINE_ALIAS(add_32_T0_T2,0); - void gen_add_32_T0_im(int32 value); - DEFINE_ALIAS(sub_32_T0_T1,0); - DEFINE_ALIAS(sub_32_T0_T2,0); - void gen_sub_32_T0_im(int32 value); - DEFINE_ALIAS(add_32_T1_T0,0); - DEFINE_ALIAS(add_32_T1_T2,0); - void gen_add_32_T1_im(int32 value); - DEFINE_ALIAS(sub_32_T1_T0,0); - DEFINE_ALIAS(sub_32_T1_T2,0); - void gen_sub_32_T1_im(int32 value); - DEFINE_ALIAS(umul_32_T0_T1,0); - DEFINE_ALIAS(smul_32_T0_T1,0); - DEFINE_ALIAS(udiv_32_T0_T1,0); - DEFINE_ALIAS(sdiv_32_T0_T1,0); - DEFINE_ALIAS(xchg_32_T0_T1,0); - DEFINE_ALIAS(bswap_16_T0,0); - DEFINE_ALIAS(bswap_32_T0,0); - - // Logical operations - DEFINE_ALIAS(neg_32_T0,0); - DEFINE_ALIAS(not_32_T0,0); - DEFINE_ALIAS(not_32_T1,0); - DEFINE_ALIAS(and_32_T0_T1,0); - DEFINE_ALIAS(and_32_T0_im,1); - DEFINE_ALIAS(or_32_T0_T1,0); - DEFINE_ALIAS(or_32_T0_im,1); - DEFINE_ALIAS(xor_32_T0_T1,0); - DEFINE_ALIAS(xor_32_T0_im,1); - DEFINE_ALIAS(orc_32_T0_T1,0); - DEFINE_ALIAS(andc_32_T0_T1,0); - DEFINE_ALIAS(nand_32_T0_T1,0); - DEFINE_ALIAS(nor_32_T0_T1,0); - DEFINE_ALIAS(eqv_32_T0_T1,0); - - // Shift/Rotate operations - DEFINE_ALIAS(lsl_32_T0_T1,0); - DEFINE_ALIAS(lsl_32_T0_im,1); - DEFINE_ALIAS(lsr_32_T0_T1,0); - DEFINE_ALIAS(lsr_32_T0_im,1); - DEFINE_ALIAS(asr_32_T0_T1,0); - DEFINE_ALIAS(asr_32_T0_im,1); - DEFINE_ALIAS(rol_32_T0_T1,0); - DEFINE_ALIAS(rol_32_T0_im,1); - DEFINE_ALIAS(ror_32_T0_T1,0); - DEFINE_ALIAS(ror_32_T0_im,1); - - // Sign-/Zero-extension - DEFINE_ALIAS(se_16_32_T0,0); - DEFINE_ALIAS(se_16_32_T1,0); - DEFINE_ALIAS(ze_16_32_T0,0); - DEFINE_ALIAS(se_8_32_T0,0); - DEFINE_ALIAS(ze_8_32_T0,0); - - // Jump instructions - DEFINE_ALIAS(jmp_slow,1); - DEFINE_ALIAS(jmp_fast,1); - DEFINE_ALIAS(jmp_A0,0); - - // Load/Store instructions - DEFINE_ALIAS(load_u32_T0_T1_T2,0); - void gen_load_u32_T0_T1_im(int32 offset); - DEFINE_ALIAS(load_s32_T0_T1_T2,0); - void gen_load_s32_T0_T1_im(int32 offset); - DEFINE_ALIAS(load_u16_T0_T1_T2,0); - void gen_load_u16_T0_T1_im(int32 offset); - DEFINE_ALIAS(load_s16_T0_T1_T2,0); - void gen_load_s16_T0_T1_im(int32 offset); - DEFINE_ALIAS(load_u8_T0_T1_T2,0); - void gen_load_u8_T0_T1_im(int32 offset); - DEFINE_ALIAS(load_s8_T0_T1_T2,0); - void gen_load_s8_T0_T1_im(int32 offset); - DEFINE_ALIAS(store_32_T0_T1_T2,0); - void gen_store_32_T0_T1_im(int32 offset); - DEFINE_ALIAS(store_16_T0_T1_T2,0); - void gen_store_16_T0_T1_im(int32 offset); - DEFINE_ALIAS(store_8_T0_T1_T2,0); - void gen_store_8_T0_T1_im(int32 offset); - -#undef DEFINE_ALIAS -#undef DEFINE_ALIAS_0 -#undef DEFINE_ALIAS_1 -#undef DEFINE_ALIAS_2 -#undef DEFINE_ALIAS_3 -#undef DEFINE_ALIAS_RAW - - // Address of jump offset to patch for direct chaining - static const int MAX_JUMPS = 2; - uint8 *jmp_addr[MAX_JUMPS]; -}; - -inline bool -basic_dyngen::direct_jump_possible(uintptr target) const -{ -#if defined(__powerpc__) || defined(__ppc__) - const uintptr LI_OFFSET_MAX = 1 << 26; - return (((target - (uintptr)code_ptr()) < LI_OFFSET_MAX) || - (((uintptr)code_ptr() - target) < LI_OFFSET_MAX)); -#endif -#if defined(__i386__) - return true; -#endif -#if defined(__x86_64__) - const intptr offset = (intptr)target - (intptr)code_ptr() - sizeof(void *); - return offset <= 0xffffffff; -#endif - return false; -} - -inline void -basic_dyngen::gen_jmp(const uint8 *target_p) -{ - const uintptr target = (uintptr)target_p; - if (direct_jump_possible(target)) - gen_op_jmp_fast(target); - else - gen_op_jmp_slow(target); -} - -inline void -basic_dyngen::execute(uint8 *entry_point) -{ - typedef void (*func_t)(uint8 *, dyngen_cpu_base); - func_t func = (func_t)execute_func; - func(entry_point, parent_cpu); -} - -inline void -basic_dyngen::gen_exec_return() -{ - gen_jmp(execute_func + op_exec_return_offset); -} - -inline bool -basic_dyngen::direct_call_possible(uintptr target) const -{ -#if defined(__powerpc__) || defined(__ppc__) - const uintptr LI_OFFSET_MAX = 1 << 26; - return (((target - (uintptr)code_ptr()) < LI_OFFSET_MAX) || - (((uintptr)code_ptr() - target) < LI_OFFSET_MAX)); -#endif -#if defined(__i386__) - return true; -#endif -#if defined(__x86_64__) - const intptr offset = (intptr)target - (intptr)code_ptr() - sizeof(void *); - return offset <= 0xffffffff; -#endif - return false; -} - -inline uint8 * -basic_dyngen::gen_start() -{ - for (int i = 0; i < MAX_JUMPS; i++) - jmp_addr[i] = NULL; - gen_code_start = gen_align(); - return gen_code_start; -} - -inline bool -basic_dyngen::gen_end() const -{ - flush_icache_range((unsigned long)gen_code_start, (unsigned long)code_ptr()); - return !full_translation_cache(); -} - -#define DEFINE_OP(REG) \ -inline void \ -basic_dyngen::gen_mov_32_##REG##_im(int32 value) \ -{ \ - if (value == 0) \ - gen_op_mov_32_##REG##_0(); \ - else \ - gen_op_mov_32_##REG##_im(value); \ -} - -DEFINE_OP(T0); -DEFINE_OP(T1); -DEFINE_OP(T2); - -#undef DEFINE_OP - -#define DEFINE_OP(OP,REG) \ -inline void \ -basic_dyngen::gen_##OP##_32_##REG##_im(int32 value) \ -{ \ - if (value == 0) return; \ - else if (value == 1) gen_op_##OP##_32_##REG##_1(); \ - else if (value == 2) gen_op_##OP##_32_##REG##_2(); \ - else if (value == 4) gen_op_##OP##_32_##REG##_4(); \ - else if (value == 8) gen_op_##OP##_32_##REG##_8(); \ - else gen_op_##OP##_32_##REG##_im(value); \ -} - -DEFINE_OP(add,T0); -DEFINE_OP(add,T1); -DEFINE_OP(sub,T0); -DEFINE_OP(sub,T1); - -#undef DEFINE_OP - -#define DEFINE_OP(NAME,REG,SIZE) \ -inline void \ -basic_dyngen::gen_##NAME##_##SIZE##_##REG##_T1_im(int32 offset) \ -{ \ - if (offset == 0) \ - gen_op_##NAME##_##SIZE##_##REG##_T1_0(); \ - else \ - gen_op_##NAME##_##SIZE##_##REG##_T1_im(offset); \ -} - -DEFINE_OP(load,T0,u32); -DEFINE_OP(load,T0,s32); -DEFINE_OP(store,T0,32); -DEFINE_OP(load,T0,u16); -DEFINE_OP(load,T0,s16); -DEFINE_OP(store,T0,16); -DEFINE_OP(load,T0,u8); -DEFINE_OP(load,T0,s8); -DEFINE_OP(store,T0,8); - -#undef DEFINE_OP - -#endif /* BASIC_DYNGEN_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.cpp deleted file mode 100644 index e54c0f64..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.cpp +++ /dev/null @@ -1,4495 +0,0 @@ -/* - * cxxdemangle.cpp - C++ demangler - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include "cxxdemangle.h" - -#if defined(__GNUC__) && (__GXX_ABI_VERSION > 0) -#include - -char * -cxx_demangle(const char *mangled_name, char *buf, size_t *n, int *status) -{ - return abi::__cxa_demangle(mangled_name, buf, n, status); -} -#else -/* Use demangler from libiberty */ -char *cplus_demangle (const char *mangled, int options); - -/* Options passed to cplus_demangle (in 2nd parameter). */ -#define DMGL_NO_OPTS 0 /* For readability... */ -#define DMGL_PARAMS (1 << 0) /* Include function args */ -#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ -#define DMGL_AUTO (1 << 8) -#define DMGL_GNU (1 << 9) -#define DMGL_LUCID (1 << 10) -#define DMGL_ARM (1 << 11) -#define DMGL_HP (1 << 12) -#define DMGL_EDG (1 << 13) - -#ifdef __GNUC__ -#define DMGL_COMPILER DMGL_GNU -#endif - -char * -cxx_demangle(const char *mangled_name, char *buf, size_t *n, int *status) -{ - if (mangled_name == NULL || (buf != NULL && n == NULL)) { - if (status) - *status = -3; - return NULL; - } - - char *demangled = cplus_demangle(mangled_name, DMGL_COMPILER | DMGL_PARAMS | DMGL_ANSI); - if (demangled == NULL) { - if (status) - *status = -2; - return NULL; - } - else { - int len = strlen(demangled) + 1; - if (buf && n) { - if (len <= *n) - strcpy(buf, demangled); - else { - if (status) - *status = -1; - return NULL; - } - } - } - - if (status) - *status = 0; - return demangled; -} - -#include -#define xmalloc(size) malloc(size) -#define xrealloc(ptr, size) realloc(ptr, size) - -#include -#define ISDIGIT(c) isdigit(c) -#define ISLOWER(c) islower(c) - -/* ANSI and traditional C compatability macros - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 - Free Software Foundation, Inc. - This file is part of the GNU C Library. */ - -#define PARAMS(ARGS) ARGS - -/* Define macros for some gcc attributes. This permits us to use the - macros freely, and know that they will come into play for the - version of gcc in which they are supported. */ - -#ifndef ATTRIBUTE_UNUSED -#define ATTRIBUTE_UNUSED -#endif /* ATTRIBUTE_UNUSED */ - -#ifndef ATTRIBUTE_NORETURN -#define ATTRIBUTE_NORETURN -#endif /* ATTRIBUTE_NORETURN */ - -/* Demangler for GNU C++ - Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.uucp) - Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling - Modified by Satish Pai (pai@apollo.hp.com) for HP demangling - -This file is part of the libiberty library. */ - -/* This file exports two functions; cplus_mangle_opname and cplus_demangle. - - This file imports xmalloc and xrealloc, which are like malloc and - realloc except that they generate a fatal error if there is no - available memory. */ - -/* This file lives in both GCC and libiberty. When making changes, please - try not to break either. */ - -#undef CURRENT_DEMANGLING_STYLE -#define CURRENT_DEMANGLING_STYLE work->options - -#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO) -#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU) -#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID) -#define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM) -#define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP) -#define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG) -#define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) - -#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) - -/* A value at least one greater than the maximum number of characters - that will be output when using the `%d' format with `printf'. */ -#define INTBUF_SIZE 32 - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) -#endif - -extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN; - -/* In order to allow a single demangler executable to demangle strings - using various common values of CPLUS_MARKER, as well as any specific - one set at compile time, we maintain a string containing all the - commonly used ones, and check to see if the marker we are looking for - is in that string. CPLUS_MARKER is usually '$' on systems where the - assembler can deal with that. Where the assembler can't, it's usually - '.' (but on many systems '.' is used for other things). We put the - current defined CPLUS_MARKER first (which defaults to '$'), followed - by the next most common value, followed by an explicit '$' in case - the value of CPLUS_MARKER is not '$'. - - We could avoid this if we could just get g++ to tell us what the actual - cplus marker character is as part of the debug information, perhaps by - ensuring that it is the character that terminates the gcc_compiled - marker symbol (FIXME). */ - -#if !defined (CPLUS_MARKER) -#define CPLUS_MARKER '$' -#endif - -static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; - -static char char_str[2] = { '\000', '\000' }; - -typedef struct string /* Beware: these aren't required to be */ -{ /* '\0' terminated. */ - char *b; /* pointer to start of string */ - char *p; /* pointer after last character */ - char *e; /* pointer after end of allocated space */ -} string; - -/* Stuff that is shared between sub-routines. - Using a shared structure allows cplus_demangle to be reentrant. */ - -struct work_stuff -{ - int options; - char **typevec; - char **ktypevec; - char **btypevec; - int numk; - int numb; - int ksize; - int bsize; - int ntypes; - int typevec_size; - int constructor; - int destructor; - int static_type; /* A static member function */ - int temp_start; /* index in demangled to start of template args */ - int type_quals; /* The type qualifiers. */ - int dllimported; /* Symbol imported from a PE DLL */ - char **tmpl_argvec; /* Template function arguments. */ - int ntmpl_args; /* The number of template function arguments. */ - int forgetting_types; /* Nonzero if we are not remembering the types - we see. */ - string* previous_argument; /* The last function argument demangled. */ - int nrepeats; /* The number of times to repeat the previous - argument. */ -}; - -#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) -#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) - -static const struct optable -{ - const char *const in; - const char *const out; - const int flags; -} optable[] = { - {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ - {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ - {"new", " new", 0}, /* old (1.91, and 1.x) */ - {"delete", " delete", 0}, /* old (1.91, and 1.x) */ - {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ - {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ - {"as", "=", DMGL_ANSI}, /* ansi */ - {"ne", "!=", DMGL_ANSI}, /* old, ansi */ - {"eq", "==", DMGL_ANSI}, /* old, ansi */ - {"ge", ">=", DMGL_ANSI}, /* old, ansi */ - {"gt", ">", DMGL_ANSI}, /* old, ansi */ - {"le", "<=", DMGL_ANSI}, /* old, ansi */ - {"lt", "<", DMGL_ANSI}, /* old, ansi */ - {"plus", "+", 0}, /* old */ - {"pl", "+", DMGL_ANSI}, /* ansi */ - {"apl", "+=", DMGL_ANSI}, /* ansi */ - {"minus", "-", 0}, /* old */ - {"mi", "-", DMGL_ANSI}, /* ansi */ - {"ami", "-=", DMGL_ANSI}, /* ansi */ - {"mult", "*", 0}, /* old */ - {"ml", "*", DMGL_ANSI}, /* ansi */ - {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ - {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ - {"convert", "+", 0}, /* old (unary +) */ - {"negate", "-", 0}, /* old (unary -) */ - {"trunc_mod", "%", 0}, /* old */ - {"md", "%", DMGL_ANSI}, /* ansi */ - {"amd", "%=", DMGL_ANSI}, /* ansi */ - {"trunc_div", "/", 0}, /* old */ - {"dv", "/", DMGL_ANSI}, /* ansi */ - {"adv", "/=", DMGL_ANSI}, /* ansi */ - {"truth_andif", "&&", 0}, /* old */ - {"aa", "&&", DMGL_ANSI}, /* ansi */ - {"truth_orif", "||", 0}, /* old */ - {"oo", "||", DMGL_ANSI}, /* ansi */ - {"truth_not", "!", 0}, /* old */ - {"nt", "!", DMGL_ANSI}, /* ansi */ - {"postincrement","++", 0}, /* old */ - {"pp", "++", DMGL_ANSI}, /* ansi */ - {"postdecrement","--", 0}, /* old */ - {"mm", "--", DMGL_ANSI}, /* ansi */ - {"bit_ior", "|", 0}, /* old */ - {"or", "|", DMGL_ANSI}, /* ansi */ - {"aor", "|=", DMGL_ANSI}, /* ansi */ - {"bit_xor", "^", 0}, /* old */ - {"er", "^", DMGL_ANSI}, /* ansi */ - {"aer", "^=", DMGL_ANSI}, /* ansi */ - {"bit_and", "&", 0}, /* old */ - {"ad", "&", DMGL_ANSI}, /* ansi */ - {"aad", "&=", DMGL_ANSI}, /* ansi */ - {"bit_not", "~", 0}, /* old */ - {"co", "~", DMGL_ANSI}, /* ansi */ - {"call", "()", 0}, /* old */ - {"cl", "()", DMGL_ANSI}, /* ansi */ - {"alshift", "<<", 0}, /* old */ - {"ls", "<<", DMGL_ANSI}, /* ansi */ - {"als", "<<=", DMGL_ANSI}, /* ansi */ - {"arshift", ">>", 0}, /* old */ - {"rs", ">>", DMGL_ANSI}, /* ansi */ - {"ars", ">>=", DMGL_ANSI}, /* ansi */ - {"component", "->", 0}, /* old */ - {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ - {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ - {"indirect", "*", 0}, /* old */ - {"method_call", "->()", 0}, /* old */ - {"addr", "&", 0}, /* old (unary &) */ - {"array", "[]", 0}, /* old */ - {"vc", "[]", DMGL_ANSI}, /* ansi */ - {"compound", ", ", 0}, /* old */ - {"cm", ", ", DMGL_ANSI}, /* ansi */ - {"cond", "?:", 0}, /* old */ - {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ - {"max", ">?", 0}, /* old */ - {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ - {"min", "*", DMGL_ANSI}, /* ansi */ - {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ -}; - -/* These values are used to indicate the various type varieties. - They are all non-zero so that they can be used as `success' - values. */ -typedef enum type_kind_t -{ - tk_none, - tk_pointer, - tk_reference, - tk_integral, - tk_bool, - tk_char, - tk_real -} type_kind_t; - -#define STRING_EMPTY(str) ((str) -> b == (str) -> p) -#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ - string_prepend(str, " ");} -#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ - string_append(str, " ");} -#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) - -/* The scope separator appropriate for the language being demangled. */ - -#define SCOPE_STRING(work) "::" - -#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ -#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ - -/* Prototypes for local functions */ - -static void -delete_work_stuff PARAMS ((work_stuff *)); - -static void -delete_non_B_K_work_stuff PARAMS ((work_stuff *)); - -static char * -mop_up PARAMS ((work_stuff *, string *, int)); - -static void -squangle_mop_up PARAMS ((work_stuff *)); - -static void -work_stuff_copy_to_from PARAMS ((work_stuff *, work_stuff *)); - -static char * -internal_cplus_demangle PARAMS ((work_stuff *, const char *)); - -static int -demangle_template_template_parm PARAMS ((work_stuff *work, - const char **, string *)); - -static int -demangle_template PARAMS ((work_stuff *work, const char **, string *, - string *, int, int)); - -static int -arm_pt PARAMS ((work_stuff *, const char *, int, const char **, - const char **)); - -static int -demangle_class_name PARAMS ((work_stuff *, const char **, string *)); - -static int -demangle_qualified PARAMS ((work_stuff *, const char **, string *, - int, int)); - -static int -demangle_class PARAMS ((work_stuff *, const char **, string *)); - -static int -demangle_fund_type PARAMS ((work_stuff *, const char **, string *)); - -static int -demangle_signature PARAMS ((work_stuff *, const char **, string *)); - -static int -demangle_prefix PARAMS ((work_stuff *, const char **, string *)); - -static int -gnu_special PARAMS ((work_stuff *, const char **, string *)); - -static int -arm_special PARAMS ((const char **, string *)); - -static void -string_need PARAMS ((string *, int)); - -static void -string_delete PARAMS ((string *)); - -static void -string_init PARAMS ((string *)); - -static void -string_clear PARAMS ((string *)); - -static void -string_append PARAMS ((string *, const char *)); - -static void -string_appends PARAMS ((string *, string *)); - -static void -string_appendn PARAMS ((string *, const char *, int)); - -static void -string_prepend PARAMS ((string *, const char *)); - -static void -string_prependn PARAMS ((string *, const char *, int)); - -static void -string_append_template_idx PARAMS ((string *, int)); - -static int -get_count PARAMS ((const char **, int *)); - -static int -consume_count PARAMS ((const char **)); - -static int -consume_count_with_underscores PARAMS ((const char**)); - -static int -demangle_args PARAMS ((work_stuff *, const char **, string *)); - -static int -demangle_nested_args PARAMS ((work_stuff*, const char**, string*)); - -static int -do_type PARAMS ((work_stuff *, const char **, string *)); - -static int -do_arg PARAMS ((work_stuff *, const char **, string *)); - -static void -demangle_function_name PARAMS ((work_stuff *, const char **, string *, - const char *)); - -static int -iterate_demangle_function PARAMS ((work_stuff *, - const char **, string *, const char *)); - -static void -remember_type PARAMS ((work_stuff *, const char *, int)); - -static void -remember_Btype PARAMS ((work_stuff *, const char *, int, int)); - -static int -register_Btype PARAMS ((work_stuff *)); - -static void -remember_Ktype PARAMS ((work_stuff *, const char *, int)); - -static void -forget_types PARAMS ((work_stuff *)); - -static void -forget_B_and_K_types PARAMS ((work_stuff *)); - -static void -string_prepends PARAMS ((string *, string *)); - -static int -demangle_template_value_parm PARAMS ((work_stuff*, const char**, - string*, type_kind_t)); - -static int -do_hpacc_template_const_value PARAMS ((work_stuff *, const char **, string *)); - -static int -do_hpacc_template_literal PARAMS ((work_stuff *, const char **, string *)); - -static int -snarf_numeric_literal PARAMS ((const char **, string *)); - -/* There is a TYPE_QUAL value for each type qualifier. They can be - combined by bitwise-or to form the complete set of qualifiers for a - type. */ - -#define TYPE_UNQUALIFIED 0x0 -#define TYPE_QUAL_CONST 0x1 -#define TYPE_QUAL_VOLATILE 0x2 -#define TYPE_QUAL_RESTRICT 0x4 - -static int -code_for_qualifier PARAMS ((int)); - -static const char* -qualifier_string PARAMS ((int)); - -static const char* -demangle_qualifier PARAMS ((int)); - -static int -demangle_expression PARAMS ((work_stuff *, const char **, string *, - type_kind_t)); - -static int -demangle_integral_value PARAMS ((work_stuff *, const char **, - string *)); - -static int -demangle_real_value PARAMS ((work_stuff *, const char **, string *)); - -static void -demangle_arm_hp_template PARAMS ((work_stuff *, const char **, int, - string *)); - -static void -recursively_demangle PARAMS ((work_stuff *, const char **, string *, - int)); - -static void -grow_vect PARAMS ((void **, size_t *, size_t, int)); - -/* Translate count to integer, consuming tokens in the process. - Conversion terminates on the first non-digit character. - - Trying to consume something that isn't a count results in no - consumption of input and a return of -1. - - Overflow consumes the rest of the digits, and returns -1. */ - -static int -consume_count (const char **type) -{ - int count = 0; - - if (! ISDIGIT ((unsigned char)**type)) - return -1; - - while (ISDIGIT ((unsigned char)**type)) - { - count *= 10; - - /* Check for overflow. - We assume that count is represented using two's-complement; - no power of two is divisible by ten, so if an overflow occurs - when multiplying by ten, the result will not be a multiple of - ten. */ - if ((count % 10) != 0) - { - while (ISDIGIT ((unsigned char) **type)) - (*type)++; - return -1; - } - - count += **type - '0'; - (*type)++; - } - - if (count < 0) - count = -1; - - return (count); -} - - -/* Like consume_count, but for counts that are preceded and followed - by '_' if they are greater than 10. Also, -1 is returned for - failure, since 0 can be a valid value. */ - -static int -consume_count_with_underscores (const char **mangled) -{ - int idx; - - if (**mangled == '_') - { - (*mangled)++; - if (!ISDIGIT ((unsigned char)**mangled)) - return -1; - - idx = consume_count (mangled); - if (**mangled != '_') - /* The trailing underscore was missing. */ - return -1; - - (*mangled)++; - } - else - { - if (**mangled < '0' || **mangled > '9') - return -1; - - idx = **mangled - '0'; - (*mangled)++; - } - - return idx; -} - -/* C is the code for a type-qualifier. Return the TYPE_QUAL - corresponding to this qualifier. */ - -static int -code_for_qualifier (int c) -{ - switch (c) - { - case 'C': - return TYPE_QUAL_CONST; - - case 'V': - return TYPE_QUAL_VOLATILE; - - case 'u': - return TYPE_QUAL_RESTRICT; - - default: - break; - } - - /* C was an invalid qualifier. */ - abort (); -} - -/* Return the string corresponding to the qualifiers given by - TYPE_QUALS. */ - -static const char* -qualifier_string (int type_quals) -{ - switch (type_quals) - { - case TYPE_UNQUALIFIED: - return ""; - - case TYPE_QUAL_CONST: - return "const"; - - case TYPE_QUAL_VOLATILE: - return "volatile"; - - case TYPE_QUAL_RESTRICT: - return "__restrict"; - - case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: - return "const volatile"; - - case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: - return "const __restrict"; - - case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: - return "volatile __restrict"; - - case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: - return "const volatile __restrict"; - - default: - break; - } - - /* TYPE_QUALS was an invalid qualifier set. */ - abort (); -} - -/* C is the code for a type-qualifier. Return the string - corresponding to this qualifier. This function should only be - called with a valid qualifier code. */ - -static const char* -demangle_qualifier (int c) -{ - return qualifier_string (code_for_qualifier (c)); -} - - -/* char *cplus_demangle (const char *mangled, int options) - - If MANGLED is a mangled function name produced by GNU C++, then - a pointer to a @code{malloc}ed string giving a C++ representation - of the name will be returned; otherwise NULL will be returned. - It is the caller's responsibility to free the string which - is returned. - - The OPTIONS arg may contain one or more of the following bits: - - DMGL_ANSI ANSI qualifiers such as `const' and `void' are - included. - DMGL_PARAMS Function parameters are included. - - For example, - - cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" - cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" - cplus_demangle ("foo__1Ai", 0) => "A::foo" - - cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" - cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" - cplus_demangle ("foo__1Afe", 0) => "A::foo" - - Note that any leading underscores, or other such characters prepended by - the compilation system, are presumed to have already been stripped from - MANGLED. */ - -char * -cplus_demangle (const char *mangled, int options) -{ - char *ret; - work_stuff work[1]; - - memset ((char *) work, 0, sizeof (work)); - work->options = options; - ret = internal_cplus_demangle (work, mangled); - squangle_mop_up (work); - return (ret); -} - - -/* Assuming *OLD_VECT points to an array of *SIZE objects of size - ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, - updating *OLD_VECT and *SIZE as necessary. */ - -static void -grow_vect (void **old_vect, size_t *size, size_t min_size, int element_size) -{ - if (*size < min_size) - { - *size *= 2; - if (*size < min_size) - *size = min_size; - *old_vect = (char *) xrealloc (*old_vect, *size * element_size); - } -} - -/* This function performs most of what cplus_demangle use to do, but - to be able to demangle a name with a B, K or n code, we need to - have a longer term memory of what types have been seen. The original - now initializes and cleans up the squangle code info, while internal - calls go directly to this routine to avoid resetting that info. */ - -static char * -internal_cplus_demangle (work_stuff *work, const char *mangled) -{ - - string decl; - int success = 0; - char *demangled = NULL; - int s1, s2, s3, s4; - s1 = work->constructor; - s2 = work->destructor; - s3 = work->static_type; - s4 = work->type_quals; - work->constructor = work->destructor = 0; - work->type_quals = TYPE_UNQUALIFIED; - work->dllimported = 0; - - if ((mangled != NULL) && (*mangled != '\0')) - { - string_init (&decl); - - /* First check to see if gnu style demangling is active and if the - string to be demangled contains a CPLUS_MARKER. If so, attempt to - recognize one of the gnu special forms rather than looking for a - standard prefix. In particular, don't worry about whether there - is a "__" string in the mangled string. Consider "_$_5__foo" for - example. */ - - if ((AUTO_DEMANGLING || GNU_DEMANGLING)) - { - success = gnu_special (work, &mangled, &decl); - } - if (!success) - { - success = demangle_prefix (work, &mangled, &decl); - } - if (success && (*mangled != '\0')) - { - success = demangle_signature (work, &mangled, &decl); - } - if (work->constructor == 2) - { - string_prepend (&decl, "global constructors keyed to "); - work->constructor = 0; - } - else if (work->destructor == 2) - { - string_prepend (&decl, "global destructors keyed to "); - work->destructor = 0; - } - else if (work->dllimported == 1) - { - string_prepend (&decl, "import stub for "); - work->dllimported = 0; - } - demangled = mop_up (work, &decl, success); - } - work->constructor = s1; - work->destructor = s2; - work->static_type = s3; - work->type_quals = s4; - return demangled; -} - - -/* Clear out and squangling related storage */ -static void -squangle_mop_up (work_stuff *work) -{ - /* clean up the B and K type mangling types. */ - forget_B_and_K_types (work); - if (work -> btypevec != NULL) - { - free ((char *) work -> btypevec); - } - if (work -> ktypevec != NULL) - { - free ((char *) work -> ktypevec); - } -} - - -/* Copy the work state and storage. */ - -static void -work_stuff_copy_to_from (work_stuff *to, work_stuff *from) -{ - int i; - - delete_work_stuff (to); - - /* Shallow-copy scalars. */ - memcpy (to, from, sizeof (*to)); - - /* Deep-copy dynamic storage. */ - if (from->typevec_size) - to->typevec - = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0])); - - for (i = 0; i < from->ntypes; i++) - { - int len = strlen (from->typevec[i]) + 1; - - to->typevec[i] = (char *) xmalloc (len); - memcpy (to->typevec[i], from->typevec[i], len); - } - - if (from->ksize) - to->ktypevec - = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0])); - - for (i = 0; i < from->numk; i++) - { - int len = strlen (from->ktypevec[i]) + 1; - - to->ktypevec[i] = (char *) xmalloc (len); - memcpy (to->ktypevec[i], from->ktypevec[i], len); - } - - if (from->bsize) - to->btypevec - = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0])); - - for (i = 0; i < from->numb; i++) - { - int len = strlen (from->btypevec[i]) + 1; - - to->btypevec[i] = (char *) xmalloc (len); - memcpy (to->btypevec[i], from->btypevec[i], len); - } - - if (from->ntmpl_args) - to->tmpl_argvec - = (char **) xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0])); - - for (i = 0; i < from->ntmpl_args; i++) - { - int len = strlen (from->tmpl_argvec[i]) + 1; - - to->tmpl_argvec[i] = (char *) xmalloc (len); - memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); - } - - if (from->previous_argument) - { - to->previous_argument = (string*) xmalloc (sizeof (string)); - string_init (to->previous_argument); - string_appends (to->previous_argument, from->previous_argument); - } -} - - -/* Delete dynamic stuff in work_stuff that is not to be re-used. */ - -static void -delete_non_B_K_work_stuff (work_stuff *work) -{ - /* Discard the remembered types, if any. */ - - forget_types (work); - if (work -> typevec != NULL) - { - free ((char *) work -> typevec); - work -> typevec = NULL; - work -> typevec_size = 0; - } - if (work->tmpl_argvec) - { - int i; - - for (i = 0; i < work->ntmpl_args; i++) - if (work->tmpl_argvec[i]) - free ((char*) work->tmpl_argvec[i]); - - free ((char*) work->tmpl_argvec); - work->tmpl_argvec = NULL; - } - if (work->previous_argument) - { - string_delete (work->previous_argument); - free ((char*) work->previous_argument); - work->previous_argument = NULL; - } -} - - -/* Delete all dynamic storage in work_stuff. */ -static void -delete_work_stuff (work_stuff *work) -{ - delete_non_B_K_work_stuff (work); - squangle_mop_up (work); -} - - -/* Clear out any mangled storage */ - -static char * -mop_up (work_stuff *work, string *declp, int success) -{ - char *demangled = NULL; - - delete_non_B_K_work_stuff (work); - - /* If demangling was successful, ensure that the demangled string is null - terminated and return it. Otherwise, free the demangling decl. */ - - if (!success) - { - string_delete (declp); - } - else - { - string_appendn (declp, "", 1); - demangled = declp->b; - } - return (demangled); -} - -/* - -LOCAL FUNCTION - - demangle_signature -- demangle the signature part of a mangled name - -SYNOPSIS - - static int - demangle_signature (work_stuff *work, const char **mangled, - string *declp); - -DESCRIPTION - - Consume and demangle the signature portion of the mangled name. - - DECLP is the string where demangled output is being built. At - entry it contains the demangled root name from the mangled name - prefix. I.E. either a demangled operator name or the root function - name. In some special cases, it may contain nothing. - - *MANGLED points to the current unconsumed location in the mangled - name. As tokens are consumed and demangling is performed, the - pointer is updated to continuously point at the next token to - be consumed. - - Demangling GNU style mangled names is nasty because there is no - explicit token that marks the start of the outermost function - argument list. */ - -static int -demangle_signature (work_stuff *work, const char **mangled, string *declp) -{ - int success = 1; - int func_done = 0; - int expect_func = 0; - int expect_return_type = 0; - const char *oldmangled = NULL; - string trawname; - string tname; - - while (success && (**mangled != '\0')) - { - switch (**mangled) - { - case 'Q': - oldmangled = *mangled; - success = demangle_qualified (work, mangled, declp, 1, 0); - if (success) - remember_type (work, oldmangled, *mangled - oldmangled); - if (AUTO_DEMANGLING || GNU_DEMANGLING) - expect_func = 1; - oldmangled = NULL; - break; - - case 'K': - oldmangled = *mangled; - success = demangle_qualified (work, mangled, declp, 1, 0); - if (AUTO_DEMANGLING || GNU_DEMANGLING) - { - expect_func = 1; - } - oldmangled = NULL; - break; - - case 'S': - /* Static member function */ - if (oldmangled == NULL) - { - oldmangled = *mangled; - } - (*mangled)++; - work -> static_type = 1; - break; - - case 'C': - case 'V': - case 'u': - work->type_quals |= code_for_qualifier (**mangled); - - /* a qualified member function */ - if (oldmangled == NULL) - oldmangled = *mangled; - (*mangled)++; - break; - - case 'L': - /* Local class name follows after "Lnnn_" */ - if (HP_DEMANGLING) - { - while (**mangled && (**mangled != '_')) - (*mangled)++; - if (!**mangled) - success = 0; - else - (*mangled)++; - } - else - success = 0; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (oldmangled == NULL) - { - oldmangled = *mangled; - } - work->temp_start = -1; /* uppermost call to demangle_class */ - success = demangle_class (work, mangled, declp); - if (success) - { - remember_type (work, oldmangled, *mangled - oldmangled); - } - if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING) - { - /* EDG and others will have the "F", so we let the loop cycle - if we are looking at one. */ - if (**mangled != 'F') - expect_func = 1; - } - oldmangled = NULL; - break; - - case 'B': - { - string s; - success = do_type (work, mangled, &s); - if (success) - { - string_append (&s, SCOPE_STRING (work)); - string_prepends (declp, &s); - } - oldmangled = NULL; - expect_func = 1; - } - break; - - case 'F': - /* Function */ - /* ARM/HP style demangling includes a specific 'F' character after - the class name. For GNU style, it is just implied. So we can - safely just consume any 'F' at this point and be compatible - with either style. */ - - oldmangled = NULL; - func_done = 1; - (*mangled)++; - - /* For lucid/ARM/HP style we have to forget any types we might - have remembered up to this point, since they were not argument - types. GNU style considers all types seen as available for - back references. See comment in demangle_args() */ - - if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) - { - forget_types (work); - } - success = demangle_args (work, mangled, declp); - /* After picking off the function args, we expect to either - find the function return type (preceded by an '_') or the - end of the string. */ - if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_') - { - ++(*mangled); - /* At this level, we do not care about the return type. */ - success = do_type (work, mangled, &tname); - string_delete (&tname); - } - - break; - - case 't': - /* G++ Template */ - string_init(&trawname); - string_init(&tname); - if (oldmangled == NULL) - { - oldmangled = *mangled; - } - success = demangle_template (work, mangled, &tname, - &trawname, 1, 1); - if (success) - { - remember_type (work, oldmangled, *mangled - oldmangled); - } - string_append (&tname, SCOPE_STRING (work)); - - string_prepends(declp, &tname); - if (work -> destructor & 1) - { - string_prepend (&trawname, "~"); - string_appends (declp, &trawname); - work->destructor -= 1; - } - if ((work->constructor & 1) || (work->destructor & 1)) - { - string_appends (declp, &trawname); - work->constructor -= 1; - } - string_delete(&trawname); - string_delete(&tname); - oldmangled = NULL; - expect_func = 1; - break; - - case '_': - if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) - { - /* Read the return type. */ - string return_type; - string_init (&return_type); - - (*mangled)++; - success = do_type (work, mangled, &return_type); - APPEND_BLANK (&return_type); - - string_prepends (declp, &return_type); - string_delete (&return_type); - break; - } - else - /* At the outermost level, we cannot have a return type specified, - so if we run into another '_' at this point we are dealing with - a mangled name that is either bogus, or has been mangled by - some algorithm we don't know how to deal with. So just - reject the entire demangling. */ - /* However, "_nnn" is an expected suffix for alternate entry point - numbered nnn for a function, with HP aCC, so skip over that - without reporting failure. pai/1997-09-04 */ - if (HP_DEMANGLING) - { - (*mangled)++; - while (**mangled && ISDIGIT ((unsigned char)**mangled)) - (*mangled)++; - } - else - success = 0; - break; - - case 'H': - if (AUTO_DEMANGLING || GNU_DEMANGLING) - { - /* A G++ template function. Read the template arguments. */ - success = demangle_template (work, mangled, declp, 0, 0, - 0); - if (!(work->constructor & 1)) - expect_return_type = 1; - (*mangled)++; - break; - } - else - /* fall through */ - {;} - - default: - if (AUTO_DEMANGLING || GNU_DEMANGLING) - { - /* Assume we have stumbled onto the first outermost function - argument token, and start processing args. */ - func_done = 1; - success = demangle_args (work, mangled, declp); - } - else - { - /* Non-GNU demanglers use a specific token to mark the start - of the outermost function argument tokens. Typically 'F', - for ARM/HP-demangling, for example. So if we find something - we are not prepared for, it must be an error. */ - success = 0; - } - break; - } - /* - if (AUTO_DEMANGLING || GNU_DEMANGLING) - */ - { - if (success && expect_func) - { - func_done = 1; - if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) - { - forget_types (work); - } - success = demangle_args (work, mangled, declp); - /* Since template include the mangling of their return types, - we must set expect_func to 0 so that we don't try do - demangle more arguments the next time we get here. */ - expect_func = 0; - } - } - } - if (success && !func_done) - { - if (AUTO_DEMANGLING || GNU_DEMANGLING) - { - /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and - bar__3fooi is 'foo::bar(int)'. We get here when we find the - first case, and need to ensure that the '(void)' gets added to - the current declp. Note that with ARM/HP, the first case - represents the name of a static data member 'foo::bar', - which is in the current declp, so we leave it alone. */ - success = demangle_args (work, mangled, declp); - } - } - if (success && PRINT_ARG_TYPES) - { - if (work->static_type) - string_append (declp, " static"); - if (work->type_quals != TYPE_UNQUALIFIED) - { - APPEND_BLANK (declp); - string_append (declp, qualifier_string (work->type_quals)); - } - } - - return (success); -} - -static int -demangle_template_template_parm (work_stuff *work, - const char **mangled, - string *tname) -{ - int i; - int r; - int need_comma = 0; - int success = 1; - string temp; - - string_append (tname, "template <"); - /* get size of template parameter list */ - if (get_count (mangled, &r)) - { - for (i = 0; i < r; i++) - { - if (need_comma) - { - string_append (tname, ", "); - } - - /* Z for type parameters */ - if (**mangled == 'Z') - { - (*mangled)++; - string_append (tname, "class"); - } - /* z for template parameters */ - else if (**mangled == 'z') - { - (*mangled)++; - success = - demangle_template_template_parm (work, mangled, tname); - if (!success) - { - break; - } - } - else - { - /* temp is initialized in do_type */ - success = do_type (work, mangled, &temp); - if (success) - { - string_appends (tname, &temp); - } - string_delete(&temp); - if (!success) - { - break; - } - } - need_comma = 1; - } - - } - if (tname->p[-1] == '>') - string_append (tname, " "); - string_append (tname, "> class"); - return (success); -} - -static int -demangle_expression ( - work_stuff *work, - const char** mangled, - string* s, - type_kind_t tk) -{ - int need_operator = 0; - int success; - - success = 1; - string_appendn (s, "(", 1); - (*mangled)++; - while (success && **mangled != 'W' && **mangled != '\0') - { - if (need_operator) - { - size_t i; - size_t len; - - success = 0; - - len = strlen (*mangled); - - for (i = 0; i < (size_t)ARRAY_SIZE (optable); ++i) - { - size_t l = strlen (optable[i].in); - - if (l <= len - && memcmp (optable[i].in, *mangled, l) == 0) - { - string_appendn (s, " ", 1); - string_append (s, optable[i].out); - string_appendn (s, " ", 1); - success = 1; - (*mangled) += l; - break; - } - } - - if (!success) - break; - } - else - need_operator = 1; - - success = demangle_template_value_parm (work, mangled, s, tk); - } - - if (**mangled != 'W') - success = 0; - else - { - string_appendn (s, ")", 1); - (*mangled)++; - } - - return success; -} - -static int -demangle_integral_value ( - work_stuff *work, - const char** mangled, - string* s) -{ - int success; - - if (**mangled == 'E') - success = demangle_expression (work, mangled, s, tk_integral); - else if (**mangled == 'Q' || **mangled == 'K') - success = demangle_qualified (work, mangled, s, 0, 1); - else - { - int value; - - /* By default, we let the number decide whether we shall consume an - underscore. */ - int consume_following_underscore = 0; - int leave_following_underscore = 0; - - success = 0; - - /* Negative numbers are indicated with a leading `m'. */ - if (**mangled == 'm') - { - string_appendn (s, "-", 1); - (*mangled)++; - } - else if (mangled[0][0] == '_' && mangled[0][1] == 'm') - { - /* Since consume_count_with_underscores does not handle the - `m'-prefix we must do it here, using consume_count and - adjusting underscores: we have to consume the underscore - matching the prepended one. */ - consume_following_underscore = 1; - string_appendn (s, "-", 1); - (*mangled) += 2; - } - else if (**mangled == '_') - { - /* Do not consume a following underscore; - consume_following_underscore will consume what should be - consumed. */ - leave_following_underscore = 1; - } - - /* We must call consume_count if we expect to remove a trailing - underscore, since consume_count_with_underscores expects - the leading underscore (that we consumed) if it is to handle - multi-digit numbers. */ - if (consume_following_underscore) - value = consume_count (mangled); - else - value = consume_count_with_underscores (mangled); - - if (value != -1) - { - char buf[INTBUF_SIZE]; - sprintf (buf, "%d", value); - string_append (s, buf); - - /* Numbers not otherwise delimited, might have an underscore - appended as a delimeter, which we should skip. - - ??? This used to always remove a following underscore, which - is wrong. If other (arbitrary) cases are followed by an - underscore, we need to do something more radical. */ - - if ((value > 9 || consume_following_underscore) - && ! leave_following_underscore - && **mangled == '_') - (*mangled)++; - - /* All is well. */ - success = 1; - } - } - - return success; -} - -/* Demangle the real value in MANGLED. */ - -static int -demangle_real_value ( - work_stuff *work, - const char **mangled, - string* s) -{ - if (**mangled == 'E') - return demangle_expression (work, mangled, s, tk_real); - - if (**mangled == 'm') - { - string_appendn (s, "-", 1); - (*mangled)++; - } - while (ISDIGIT ((unsigned char)**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - if (**mangled == '.') /* fraction */ - { - string_appendn (s, ".", 1); - (*mangled)++; - while (ISDIGIT ((unsigned char)**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - } - if (**mangled == 'e') /* exponent */ - { - string_appendn (s, "e", 1); - (*mangled)++; - while (ISDIGIT ((unsigned char)**mangled)) - { - string_appendn (s, *mangled, 1); - (*mangled)++; - } - } - - return 1; -} - -static int -demangle_template_value_parm ( - work_stuff *work, - const char **mangled, - string* s, - type_kind_t tk) -{ - int success = 1; - - if (**mangled == 'Y') - { - /* The next argument is a template parameter. */ - int idx; - - (*mangled)++; - idx = consume_count_with_underscores (mangled); - if (idx == -1 - || (work->tmpl_argvec && idx >= work->ntmpl_args) - || consume_count_with_underscores (mangled) == -1) - return -1; - if (work->tmpl_argvec) - string_append (s, work->tmpl_argvec[idx]); - else - string_append_template_idx (s, idx); - } - else if (tk == tk_integral) - success = demangle_integral_value (work, mangled, s); - else if (tk == tk_char) - { - char tmp[2]; - int val; - if (**mangled == 'm') - { - string_appendn (s, "-", 1); - (*mangled)++; - } - string_appendn (s, "'", 1); - val = consume_count(mangled); - if (val <= 0) - success = 0; - else - { - tmp[0] = (char)val; - tmp[1] = '\0'; - string_appendn (s, &tmp[0], 1); - string_appendn (s, "'", 1); - } - } - else if (tk == tk_bool) - { - int val = consume_count (mangled); - if (val == 0) - string_appendn (s, "false", 5); - else if (val == 1) - string_appendn (s, "true", 4); - else - success = 0; - } - else if (tk == tk_real) - success = demangle_real_value (work, mangled, s); - else if (tk == tk_pointer || tk == tk_reference) - { - if (**mangled == 'Q') - success = demangle_qualified (work, mangled, s, - /*isfuncname=*/0, - /*append=*/1); - else - { - int symbol_len = consume_count (mangled); - if (symbol_len == -1) - return -1; - if (symbol_len == 0) - string_appendn (s, "0", 1); - else - { - char *p = (char *) xmalloc (symbol_len + 1), *q; - strncpy (p, *mangled, symbol_len); - p [symbol_len] = '\0'; - /* We use cplus_demangle here, rather than - internal_cplus_demangle, because the name of the entity - mangled here does not make use of any of the squangling - or type-code information we have built up thus far; it is - mangled independently. */ - q = cplus_demangle (p, work->options); - if (tk == tk_pointer) - string_appendn (s, "&", 1); - /* FIXME: Pointer-to-member constants should get a - qualifying class name here. */ - if (q) - { - string_append (s, q); - free (q); - } - else - string_append (s, p); - free (p); - } - *mangled += symbol_len; - } - } - - return success; -} - -/* Demangle the template name in MANGLED. The full name of the - template (e.g., S) is placed in TNAME. The name without the - template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is - non-NULL. If IS_TYPE is nonzero, this template is a type template, - not a function template. If both IS_TYPE and REMEMBER are nonzero, - the template is remembered in the list of back-referenceable - types. */ - -static int -demangle_template ( - work_stuff *work, - const char **mangled, - string *tname, - string *trawname, - int is_type, - int remember) -{ - int i; - int r; - int need_comma = 0; - int success = 0; - const char *start; - int is_java_array = 0; - string temp; - int bindex = 0; - - (*mangled)++; - if (is_type) - { - if (remember) - bindex = register_Btype (work); - start = *mangled; - /* get template name */ - if (**mangled == 'z') - { - int idx; - (*mangled)++; - (*mangled)++; - - idx = consume_count_with_underscores (mangled); - if (idx == -1 - || (work->tmpl_argvec && idx >= work->ntmpl_args) - || consume_count_with_underscores (mangled) == -1) - return (0); - - if (work->tmpl_argvec) - { - string_append (tname, work->tmpl_argvec[idx]); - if (trawname) - string_append (trawname, work->tmpl_argvec[idx]); - } - else - { - string_append_template_idx (tname, idx); - if (trawname) - string_append_template_idx (trawname, idx); - } - } - else - { - if ((r = consume_count (mangled)) <= 0 - || (int) strlen (*mangled) < r) - { - return (0); - } - string_appendn (tname, *mangled, r); - if (trawname) - string_appendn (trawname, *mangled, r); - *mangled += r; - } - } - if (!is_java_array) - string_append (tname, "<"); - /* get size of template parameter list */ - if (!get_count (mangled, &r)) - { - return (0); - } - if (!is_type) - { - /* Create an array for saving the template argument values. */ - work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *)); - work->ntmpl_args = r; - for (i = 0; i < r; i++) - work->tmpl_argvec[i] = 0; - } - for (i = 0; i < r; i++) - { - if (need_comma) - { - string_append (tname, ", "); - } - /* Z for type parameters */ - if (**mangled == 'Z') - { - (*mangled)++; - /* temp is initialized in do_type */ - success = do_type (work, mangled, &temp); - if (success) - { - string_appends (tname, &temp); - - if (!is_type) - { - /* Save the template argument. */ - int len = temp.p - temp.b; - work->tmpl_argvec[i] = (char *) xmalloc (len + 1); - memcpy (work->tmpl_argvec[i], temp.b, len); - work->tmpl_argvec[i][len] = '\0'; - } - } - string_delete(&temp); - if (!success) - { - break; - } - } - /* z for template parameters */ - else if (**mangled == 'z') - { - int r2; - (*mangled)++; - success = demangle_template_template_parm (work, mangled, tname); - - if (success - && (r2 = consume_count (mangled)) > 0 - && (int) strlen (*mangled) >= r2) - { - string_append (tname, " "); - string_appendn (tname, *mangled, r2); - if (!is_type) - { - /* Save the template argument. */ - int len = r2; - work->tmpl_argvec[i] = (char *) xmalloc (len + 1); - memcpy (work->tmpl_argvec[i], *mangled, len); - work->tmpl_argvec[i][len] = '\0'; - } - *mangled += r2; - } - if (!success) - { - break; - } - } - else - { - string param; - string* s; - - /* otherwise, value parameter */ - - /* temp is initialized in do_type */ - success = do_type (work, mangled, &temp); - string_delete(&temp); - if (!success) - break; - - if (!is_type) - { - s = ¶m; - string_init (s); - } - else - s = tname; - - success = demangle_template_value_parm (work, mangled, s, - (type_kind_t) success); - - if (!success) - { - if (!is_type) - string_delete (s); - success = 0; - break; - } - - if (!is_type) - { - int len = s->p - s->b; - work->tmpl_argvec[i] = (char *) xmalloc (len + 1); - memcpy (work->tmpl_argvec[i], s->b, len); - work->tmpl_argvec[i][len] = '\0'; - - string_appends (tname, s); - string_delete (s); - } - } - need_comma = 1; - } - if (is_java_array) - { - string_append (tname, "[]"); - } - else - { - if (tname->p[-1] == '>') - string_append (tname, " "); - string_append (tname, ">"); - } - - if (is_type && remember) - remember_Btype (work, tname->b, LEN_STRING (tname), bindex); - - /* - if (work -> static_type) - { - string_append (declp, *mangled + 1); - *mangled += strlen (*mangled); - success = 1; - } - else - { - success = demangle_args (work, mangled, declp); - } - } - */ - return (success); -} - -static int -arm_pt ( - work_stuff *work, - const char *mangled, - int n, - const char **anchor, - const char **args) -{ - /* Check if ARM template with "__pt__" in it ("parameterized type") */ - /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */ - if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__"))) - { - int len; - *args = *anchor + 6; - len = consume_count (args); - if (len == -1) - return 0; - if (*args + len == mangled + n && **args == '_') - { - ++*args; - return 1; - } - } - if (AUTO_DEMANGLING || EDG_DEMANGLING) - { - if ((*anchor = strstr (mangled, "__tm__")) - || (*anchor = strstr (mangled, "__ps__")) - || (*anchor = strstr (mangled, "__pt__"))) - { - int len; - *args = *anchor + 6; - len = consume_count (args); - if (len == -1) - return 0; - if (*args + len == mangled + n && **args == '_') - { - ++*args; - return 1; - } - } - else if ((*anchor = strstr (mangled, "__S"))) - { - int len; - *args = *anchor + 3; - len = consume_count (args); - if (len == -1) - return 0; - if (*args + len == mangled + n && **args == '_') - { - ++*args; - return 1; - } - } - } - - return 0; -} - -static void -demangle_arm_hp_template ( - work_stuff *work, - const char **mangled, - int n, - string *declp) -{ - const char *p; - const char *args; - const char *e = *mangled + n; - string arg; - - /* Check for HP aCC template spec: classXt1t2 where t1, t2 are - template args */ - if (HP_DEMANGLING && ((*mangled)[n] == 'X')) - { - char *start_spec_args = NULL; - - /* First check for and omit template specialization pseudo-arguments, - such as in "Spec<#1,#1.*>" */ - start_spec_args = strchr (*mangled, '<'); - if (start_spec_args && (start_spec_args - *mangled < n)) - string_appendn (declp, *mangled, start_spec_args - *mangled); - else - string_appendn (declp, *mangled, n); - (*mangled) += n + 1; - string_init (&arg); - if (work->temp_start == -1) /* non-recursive call */ - work->temp_start = declp->p - declp->b; - string_append (declp, "<"); - while (1) - { - string_clear (&arg); - switch (**mangled) - { - case 'T': - /* 'T' signals a type parameter */ - (*mangled)++; - if (!do_type (work, mangled, &arg)) - goto hpacc_template_args_done; - break; - - case 'U': - case 'S': - /* 'U' or 'S' signals an integral value */ - if (!do_hpacc_template_const_value (work, mangled, &arg)) - goto hpacc_template_args_done; - break; - - case 'A': - /* 'A' signals a named constant expression (literal) */ - if (!do_hpacc_template_literal (work, mangled, &arg)) - goto hpacc_template_args_done; - break; - - default: - /* Today, 1997-09-03, we have only the above types - of template parameters */ - /* FIXME: maybe this should fail and return null */ - goto hpacc_template_args_done; - } - string_appends (declp, &arg); - /* Check if we're at the end of template args. - 0 if at end of static member of template class, - _ if done with template args for a function */ - if ((**mangled == '\000') || (**mangled == '_')) - break; - else - string_append (declp, ","); - } - hpacc_template_args_done: - string_append (declp, ">"); - string_delete (&arg); - if (**mangled == '_') - (*mangled)++; - return; - } - /* ARM template? (Also handles HP cfront extensions) */ - else if (arm_pt (work, *mangled, n, &p, &args)) - { - string type_str; - - string_init (&arg); - string_appendn (declp, *mangled, p - *mangled); - if (work->temp_start == -1) /* non-recursive call */ - work->temp_start = declp->p - declp->b; - string_append (declp, "<"); - /* should do error checking here */ - while (args < e) { - string_clear (&arg); - - /* Check for type or literal here */ - switch (*args) - { - /* HP cfront extensions to ARM for template args */ - /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */ - /* FIXME: We handle only numeric literals for HP cfront */ - case 'X': - /* A typed constant value follows */ - args++; - if (!do_type (work, &args, &type_str)) - goto cfront_template_args_done; - string_append (&arg, "("); - string_appends (&arg, &type_str); - string_append (&arg, ")"); - if (*args != 'L') - goto cfront_template_args_done; - args++; - /* Now snarf a literal value following 'L' */ - if (!snarf_numeric_literal (&args, &arg)) - goto cfront_template_args_done; - break; - - case 'L': - /* Snarf a literal following 'L' */ - args++; - if (!snarf_numeric_literal (&args, &arg)) - goto cfront_template_args_done; - break; - default: - /* Not handling other HP cfront stuff */ - if (!do_type (work, &args, &arg)) - goto cfront_template_args_done; - } - string_appends (declp, &arg); - string_append (declp, ","); - } - cfront_template_args_done: - string_delete (&arg); - if (args >= e) - --declp->p; /* remove extra comma */ - string_append (declp, ">"); - } - else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 - && (*mangled)[9] == 'N' - && (*mangled)[8] == (*mangled)[10] - && strchr (cplus_markers, (*mangled)[8])) - { - /* A member of the anonymous namespace. */ - string_append (declp, "{anonymous}"); - } - else - { - if (work->temp_start == -1) /* non-recursive call only */ - work->temp_start = 0; /* disable in recursive calls */ - string_appendn (declp, *mangled, n); - } - *mangled += n; -} - -/* Extract a class name, possibly a template with arguments, from the - mangled string; qualifiers, local class indicators, etc. have - already been dealt with */ - -static int -demangle_class_name ( - work_stuff *work, - const char **mangled, - string *declp) -{ - int n; - int success = 0; - - n = consume_count (mangled); - if (n == -1) - return 0; - if ((int) strlen (*mangled) >= n) - { - demangle_arm_hp_template (work, mangled, n, declp); - success = 1; - } - - return (success); -} - -/* - -LOCAL FUNCTION - - demangle_class -- demangle a mangled class sequence - -SYNOPSIS - - static int - demangle_class (work_stuff *work, const char **mangled, - strint *declp) - -DESCRIPTION - - DECLP points to the buffer into which demangling is being done. - - *MANGLED points to the current token to be demangled. On input, - it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) - On exit, it points to the next token after the mangled class on - success, or the first unconsumed token on failure. - - If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then - we are demangling a constructor or destructor. In this case - we prepend "class::class" or "class::~class" to DECLP. - - Otherwise, we prepend "class::" to the current DECLP. - - Reset the constructor/destructor flags once they have been - "consumed". This allows demangle_class to be called later during - the same demangling, to do normal class demangling. - - Returns 1 if demangling is successful, 0 otherwise. - -*/ - -static int -demangle_class ( - work_stuff *work, - const char **mangled, - string *declp) -{ - int success = 0; - int btype; - string class_name; - char *save_class_name_end = 0; - - string_init (&class_name); - btype = register_Btype (work); - if (demangle_class_name (work, mangled, &class_name)) - { - save_class_name_end = class_name.p; - if ((work->constructor & 1) || (work->destructor & 1)) - { - /* adjust so we don't include template args */ - if (work->temp_start && (work->temp_start != -1)) - { - class_name.p = class_name.b + work->temp_start; - } - string_prepends (declp, &class_name); - if (work -> destructor & 1) - { - string_prepend (declp, "~"); - work -> destructor -= 1; - } - else - { - work -> constructor -= 1; - } - } - class_name.p = save_class_name_end; - remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); - remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); - string_prepend (declp, SCOPE_STRING (work)); - string_prepends (declp, &class_name); - success = 1; - } - string_delete (&class_name); - return (success); -} - - -/* Called when there's a "__" in the mangled name, with `scan' pointing to - the rightmost guess. - - Find the correct "__"-sequence where the function name ends and the - signature starts, which is ambiguous with GNU mangling. - Call demangle_signature here, so we can make sure we found the right - one; *mangled will be consumed so caller will not make further calls to - demangle_signature. */ - -static int -iterate_demangle_function ( - work_stuff *work, - const char **mangled, - string *declp, - const char *scan) -{ - const char *mangle_init = *mangled; - int success = 0; - string decl_init; - work_stuff work_init; - - if (*(scan + 2) == '\0') - return 0; - - /* Do not iterate for some demangling modes, or if there's only one - "__"-sequence. This is the normal case. */ - if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING - || strstr (scan + 2, "__") == NULL) - { - demangle_function_name (work, mangled, declp, scan); - return 1; - } - - /* Save state so we can restart if the guess at the correct "__" was - wrong. */ - string_init (&decl_init); - string_appends (&decl_init, declp); - memset (&work_init, 0, sizeof work_init); - work_stuff_copy_to_from (&work_init, work); - - /* Iterate over occurrences of __, allowing names and types to have a - "__" sequence in them. We must start with the first (not the last) - occurrence, since "__" most often occur between independent mangled - parts, hence starting at the last occurrence inside a signature - might get us a "successful" demangling of the signature. */ - - while (scan[2]) - { - demangle_function_name (work, mangled, declp, scan); - success = demangle_signature (work, mangled, declp); - if (success) - break; - - /* Reset demangle state for the next round. */ - *mangled = mangle_init; - string_clear (declp); - string_appends (declp, &decl_init); - work_stuff_copy_to_from (work, &work_init); - - /* Leave this underscore-sequence. */ - scan += 2; - - /* Scan for the next "__" sequence. */ - while (*scan && (scan[0] != '_' || scan[1] != '_')) - scan++; - - /* Move to last "__" in this sequence. */ - while (*scan && *scan == '_') - scan++; - scan -= 2; - } - - /* Delete saved state. */ - delete_work_stuff (&work_init); - string_delete (&decl_init); - - return success; -} - -/* - -LOCAL FUNCTION - - demangle_prefix -- consume the mangled name prefix and find signature - -SYNOPSIS - - static int - demangle_prefix (work_stuff *work, const char **mangled, - string *declp); - -DESCRIPTION - - Consume and demangle the prefix of the mangled name. - While processing the function name root, arrange to call - demangle_signature if the root is ambiguous. - - DECLP points to the string buffer into which demangled output is - placed. On entry, the buffer is empty. On exit it contains - the root function name, the demangled operator name, or in some - special cases either nothing or the completely demangled result. - - MANGLED points to the current pointer into the mangled name. As each - token of the mangled name is consumed, it is updated. Upon entry - the current mangled name pointer points to the first character of - the mangled name. Upon exit, it should point to the first character - of the signature if demangling was successful, or to the first - unconsumed character if demangling of the prefix was unsuccessful. - - Returns 1 on success, 0 otherwise. - */ - -static int -demangle_prefix ( - work_stuff *work, - const char **mangled, - string *declp) -{ - int success = 1; - const char *scan; - int i; - - if (strlen(*mangled) > 6 - && (strncmp(*mangled, "_imp__", 6) == 0 - || strncmp(*mangled, "__imp_", 6) == 0)) - { - /* it's a symbol imported from a PE dynamic library. Check for both - new style prefix _imp__ and legacy __imp_ used by older versions - of dlltool. */ - (*mangled) += 6; - work->dllimported = 1; - } - else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) - { - char *marker = strchr (cplus_markers, (*mangled)[8]); - if (marker != NULL && *marker == (*mangled)[10]) - { - if ((*mangled)[9] == 'D') - { - /* it's a GNU global destructor to be executed at program exit */ - (*mangled) += 11; - work->destructor = 2; - if (gnu_special (work, mangled, declp)) - return success; - } - else if ((*mangled)[9] == 'I') - { - /* it's a GNU global constructor to be executed at program init */ - (*mangled) += 11; - work->constructor = 2; - if (gnu_special (work, mangled, declp)) - return success; - } - } - } - else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0) - { - /* it's a ARM global destructor to be executed at program exit */ - (*mangled) += 7; - work->destructor = 2; - } - else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0) - { - /* it's a ARM global constructor to be executed at program initial */ - (*mangled) += 7; - work->constructor = 2; - } - - /* This block of code is a reduction in strength time optimization - of: - scan = strstr (*mangled, "__"); */ - - { - scan = *mangled; - - do { - scan = strchr (scan, '_'); - } while (scan != NULL && *++scan != '_'); - - if (scan != NULL) --scan; - } - - if (scan != NULL) - { - /* We found a sequence of two or more '_', ensure that we start at - the last pair in the sequence. */ - /* i = strspn (scan, "_"); */ - i = 0; - while (scan[i] == '_') i++; - if (i > 2) - { - scan += (i - 2); - } - } - - if (scan == NULL) - { - success = 0; - } - else if (work -> static_type) - { - if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't')) - { - success = 0; - } - } - else if ((scan == *mangled) - && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q') - || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) - { - /* The ARM says nothing about the mangling of local variables. - But cfront mangles local variables by prepending __ - to them. As an extension to ARM demangling we handle this case. */ - if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) - && ISDIGIT ((unsigned char)scan[2])) - { - *mangled = scan + 2; - consume_count (mangled); - string_append (declp, *mangled); - *mangled += strlen (*mangled); - success = 1; - } - else - { - /* A GNU style constructor starts with __[0-9Qt]. But cfront uses - names like __Q2_3foo3bar for nested type names. So don't accept - this style of constructor for cfront demangling. A GNU - style member-template constructor starts with 'H'. */ - if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)) - work -> constructor += 1; - *mangled = scan + 2; - } - } - else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') - { - /* Cfront-style parameterized type. Handled later as a signature. */ - success = 1; - - /* ARM template? */ - demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); - } - else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm') - || (scan[2] == 'p' && scan[3] == 's') - || (scan[2] == 'p' && scan[3] == 't'))) - { - /* EDG-style parameterized type. Handled later as a signature. */ - success = 1; - - /* EDG template? */ - demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); - } - else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2]) - && (scan[2] != 't')) - { - /* Mangled name starts with "__". Skip over any leading '_' characters, - then find the next "__" that separates the prefix from the signature. - */ - if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) - || (arm_special (mangled, declp) == 0)) - { - while (*scan == '_') - { - scan++; - } - if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) - { - /* No separator (I.E. "__not_mangled"), or empty signature - (I.E. "__not_mangled_either__") */ - success = 0; - } - else - return iterate_demangle_function (work, mangled, declp, scan); - } - } - else if (*(scan + 2) != '\0') - { - /* Mangled name does not start with "__" but does have one somewhere - in there with non empty stuff after it. Looks like a global - function name. Iterate over all "__":s until the right - one is found. */ - return iterate_demangle_function (work, mangled, declp, scan); - } - else - { - /* Doesn't look like a mangled name */ - success = 0; - } - - if (!success && (work->constructor == 2 || work->destructor == 2)) - { - string_append (declp, *mangled); - *mangled += strlen (*mangled); - success = 1; - } - return (success); -} - -/* - -LOCAL FUNCTION - - gnu_special -- special handling of gnu mangled strings - -SYNOPSIS - - static int - gnu_special (work_stuff *work, const char **mangled, - string *declp); - - -DESCRIPTION - - Process some special GNU style mangling forms that don't fit - the normal pattern. For example: - - _$_3foo (destructor for class foo) - _vt$foo (foo virtual table) - _vt$foo$bar (foo::bar virtual table) - __vt_foo (foo virtual table, new style with thunks) - _3foo$varname (static data member) - _Q22rs2tu$vw (static data member) - __t6vector1Zii (constructor with template) - __thunk_4__$_7ostream (virtual function thunk) - */ - -static int -gnu_special ( - work_stuff *work, - const char **mangled, - string *declp) -{ - int n; - int success = 1; - const char *p; - - if ((*mangled)[0] == '_' - && strchr (cplus_markers, (*mangled)[1]) != NULL - && (*mangled)[2] == '_') - { - /* Found a GNU style destructor, get past "__" */ - (*mangled) += 3; - work -> destructor += 1; - } - else if ((*mangled)[0] == '_' - && (((*mangled)[1] == '_' - && (*mangled)[2] == 'v' - && (*mangled)[3] == 't' - && (*mangled)[4] == '_') - || ((*mangled)[1] == 'v' - && (*mangled)[2] == 't' - && strchr (cplus_markers, (*mangled)[3]) != NULL))) - { - /* Found a GNU style virtual table, get past "_vt" - and create the decl. Note that we consume the entire mangled - input string, which means that demangle_signature has no work - to do. */ - if ((*mangled)[2] == 'v') - (*mangled) += 5; /* New style, with thunks: "__vt_" */ - else - (*mangled) += 4; /* Old style, no thunks: "_vt" */ - while (**mangled != '\0') - { - switch (**mangled) - { - case 'Q': - case 'K': - success = demangle_qualified (work, mangled, declp, 0, 1); - break; - case 't': - success = demangle_template (work, mangled, declp, 0, 1, - 1); - break; - default: - if (ISDIGIT((unsigned char)*mangled[0])) - { - n = consume_count(mangled); - /* We may be seeing a too-large size, or else a - "." indicating a static local symbol. In - any case, declare victory and move on; *don't* try - to use n to allocate. */ - if (n > (int) strlen (*mangled)) - { - success = 1; - break; - } - } - else - { - /*n = strcspn (*mangled, cplus_markers);*/ - const char *check = *mangled; - n = 0; - while (*check) - if (strchr (cplus_markers, *check++) == NULL) - n++; - else - break; - } - string_appendn (declp, *mangled, n); - (*mangled) += n; - } - - p = strpbrk (*mangled, cplus_markers); - if (success && ((p == NULL) || (p == *mangled))) - { - if (p != NULL) - { - string_append (declp, SCOPE_STRING (work)); - (*mangled)++; - } - } - else - { - success = 0; - break; - } - } - if (success) - string_append (declp, " virtual table"); - } - else if ((*mangled)[0] == '_' - && (strchr("0123456789Qt", (*mangled)[1]) != NULL) - && (p = strpbrk (*mangled, cplus_markers)) != NULL) - { - /* static data member, "_3foo$varname" for example */ - (*mangled)++; - switch (**mangled) - { - case 'Q': - case 'K': - success = demangle_qualified (work, mangled, declp, 0, 1); - break; - case 't': - success = demangle_template (work, mangled, declp, 0, 1, 1); - break; - default: - n = consume_count (mangled); - if (n < 0 || n > (long) strlen (*mangled)) - { - success = 0; - break; - } - - if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 - && (*mangled)[9] == 'N' - && (*mangled)[8] == (*mangled)[10] - && strchr (cplus_markers, (*mangled)[8])) - { - /* A member of the anonymous namespace. There's information - about what identifier or filename it was keyed to, but - it's just there to make the mangled name unique; we just - step over it. */ - string_append (declp, "{anonymous}"); - (*mangled) += n; - - /* Now p points to the marker before the N, so we need to - update it to the first marker after what we consumed. */ - p = strpbrk (*mangled, cplus_markers); - break; - } - - string_appendn (declp, *mangled, n); - (*mangled) += n; - } - if (success && (p == *mangled)) - { - /* Consumed everything up to the cplus_marker, append the - variable name. */ - (*mangled)++; - string_append (declp, SCOPE_STRING (work)); - n = strlen (*mangled); - string_appendn (declp, *mangled, n); - (*mangled) += n; - } - else - { - success = 0; - } - } - else if (strncmp (*mangled, "__thunk_", 8) == 0) - { - int delta; - - (*mangled) += 8; - delta = consume_count (mangled); - if (delta == -1) - success = 0; - else - { - char *method = internal_cplus_demangle (work, ++*mangled); - - if (method) - { - char buf[50]; - sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); - string_append (declp, buf); - string_append (declp, method); - free (method); - n = strlen (*mangled); - (*mangled) += n; - } - else - { - success = 0; - } - } - } - else if (strncmp (*mangled, "__t", 3) == 0 - && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f')) - { - p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function"; - (*mangled) += 4; - switch (**mangled) - { - case 'Q': - case 'K': - success = demangle_qualified (work, mangled, declp, 0, 1); - break; - case 't': - success = demangle_template (work, mangled, declp, 0, 1, 1); - break; - default: - success = do_type (work, mangled, declp); - break; - } - if (success && **mangled != '\0') - success = 0; - if (success) - string_append (declp, p); - } - else - { - success = 0; - } - return (success); -} - -static void -recursively_demangle ( - work_stuff *work, - const char **mangled, - string *result, - int namelength) -{ - char * recurse = (char *)NULL; - char * recurse_dem = (char *)NULL; - - recurse = (char *) xmalloc (namelength + 1); - memcpy (recurse, *mangled, namelength); - recurse[namelength] = '\000'; - - recurse_dem = cplus_demangle (recurse, work->options); - - if (recurse_dem) - { - string_append (result, recurse_dem); - free (recurse_dem); - } - else - { - string_appendn (result, *mangled, namelength); - } - free (recurse); - *mangled += namelength; -} - -/* - -LOCAL FUNCTION - - arm_special -- special handling of ARM/lucid mangled strings - -SYNOPSIS - - static int - arm_special (const char **mangled, - string *declp); - - -DESCRIPTION - - Process some special ARM style mangling forms that don't fit - the normal pattern. For example: - - __vtbl__3foo (foo virtual table) - __vtbl__3foo__3bar (bar::foo virtual table) - - */ - -static int -arm_special (const char **mangled, string *declp) -{ - int n; - int success = 1; - const char *scan; - - if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) - { - /* Found a ARM style virtual table, get past ARM_VTABLE_STRING - and create the decl. Note that we consume the entire mangled - input string, which means that demangle_signature has no work - to do. */ - scan = *mangled + ARM_VTABLE_STRLEN; - while (*scan != '\0') /* first check it can be demangled */ - { - n = consume_count (&scan); - if (n == -1) - { - return (0); /* no good */ - } - scan += n; - if (scan[0] == '_' && scan[1] == '_') - { - scan += 2; - } - } - (*mangled) += ARM_VTABLE_STRLEN; - while (**mangled != '\0') - { - n = consume_count (mangled); - if (n == -1 - || n > (long) strlen (*mangled)) - return 0; - string_prependn (declp, *mangled, n); - (*mangled) += n; - if ((*mangled)[0] == '_' && (*mangled)[1] == '_') - { - string_prepend (declp, "::"); - (*mangled) += 2; - } - } - string_append (declp, " virtual table"); - } - else - { - success = 0; - } - return (success); -} - -/* - -LOCAL FUNCTION - - demangle_qualified -- demangle 'Q' qualified name strings - -SYNOPSIS - - static int - demangle_qualified (work_stuff *, const char *mangled, - string *result, int isfuncname, int append); - -DESCRIPTION - - Demangle a qualified name, such as "Q25Outer5Inner" which is - the mangled form of "Outer::Inner". The demangled output is - prepended or appended to the result string according to the - state of the append flag. - - If isfuncname is nonzero, then the qualified name we are building - is going to be used as a member function name, so if it is a - constructor or destructor function, append an appropriate - constructor or destructor name. I.E. for the above example, - the result for use as a constructor is "Outer::Inner::Inner" - and the result for use as a destructor is "Outer::Inner::~Inner". - -BUGS - - Numeric conversion is ASCII dependent (FIXME). - - */ - -static int -demangle_qualified ( - work_stuff *work, - const char **mangled, - string *result, - int isfuncname, - int append) -{ - int qualifiers = 0; - int success = 1; - string temp; - string last_name; - int bindex = register_Btype (work); - - /* We only make use of ISFUNCNAME if the entity is a constructor or - destructor. */ - isfuncname = (isfuncname - && ((work->constructor & 1) || (work->destructor & 1))); - - string_init (&temp); - string_init (&last_name); - - if ((*mangled)[0] == 'K') - { - /* Squangling qualified name reuse */ - int idx; - (*mangled)++; - idx = consume_count_with_underscores (mangled); - if (idx == -1 || idx >= work -> numk) - success = 0; - else - string_append (&temp, work -> ktypevec[idx]); - } - else - switch ((*mangled)[1]) - { - case '_': - /* GNU mangled name with more than 9 classes. The count is preceded - by an underscore (to distinguish it from the <= 9 case) and followed - by an underscore. */ - (*mangled)++; - qualifiers = consume_count_with_underscores (mangled); - if (qualifiers == -1) - success = 0; - break; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* The count is in a single digit. */ - qualifiers = (*mangled)[1] - '0'; - - /* If there is an underscore after the digit, skip it. This is - said to be for ARM-qualified names, but the ARM makes no - mention of such an underscore. Perhaps cfront uses one. */ - if ((*mangled)[2] == '_') - { - (*mangled)++; - } - (*mangled) += 2; - break; - - case '0': - default: - success = 0; - } - - if (!success) - { - string_delete (&last_name); - string_delete (&temp); - return success; - } - - /* Pick off the names and collect them in the temp buffer in the order - in which they are found, separated by '::'. */ - - while (qualifiers-- > 0) - { - int remember_K = 1; - string_clear (&last_name); - - if (*mangled[0] == '_') - (*mangled)++; - - if (*mangled[0] == 't') - { - /* Here we always append to TEMP since we will want to use - the template name without the template parameters as a - constructor or destructor name. The appropriate - (parameter-less) value is returned by demangle_template - in LAST_NAME. We do not remember the template type here, - in order to match the G++ mangling algorithm. */ - success = demangle_template(work, mangled, &temp, - &last_name, 1, 0); - if (!success) - break; - } - else if (*mangled[0] == 'K') - { - int idx; - (*mangled)++; - idx = consume_count_with_underscores (mangled); - if (idx == -1 || idx >= work->numk) - success = 0; - else - string_append (&temp, work->ktypevec[idx]); - remember_K = 0; - - if (!success) break; - } - else - { - if (EDG_DEMANGLING) - { - int namelength; - /* Now recursively demangle the qualifier - * This is necessary to deal with templates in - * mangling styles like EDG */ - namelength = consume_count (mangled); - if (namelength == -1) - { - success = 0; - break; - } - recursively_demangle(work, mangled, &temp, namelength); - } - else - { - string temp_last_name; - string_init (&temp_last_name); - success = do_type (work, mangled, &temp_last_name); - if (!success) - { - string_delete (&temp_last_name); - break; - } - string_appends (&temp, &temp_last_name); - string_appends (&last_name, &temp_last_name); - string_delete (&temp_last_name); - } - } - - if (remember_K) - remember_Ktype (work, temp.b, LEN_STRING (&temp)); - - if (qualifiers > 0) - string_append (&temp, SCOPE_STRING (work)); - } - - remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); - - /* If we are using the result as a function name, we need to append - the appropriate '::' separated constructor or destructor name. - We do this here because this is the most convenient place, where - we already have a pointer to the name and the length of the name. */ - - if (isfuncname) - { - string_append (&temp, SCOPE_STRING (work)); - if (work -> destructor & 1) - string_append (&temp, "~"); - string_appends (&temp, &last_name); - } - - /* Now either prepend the temp buffer to the result, or append it, - depending upon the state of the append flag. */ - - if (append) - string_appends (result, &temp); - else - { - if (!STRING_EMPTY (result)) - string_append (&temp, SCOPE_STRING (work)); - string_prepends (result, &temp); - } - - string_delete (&last_name); - string_delete (&temp); - return (success); -} - -/* - -LOCAL FUNCTION - - get_count -- convert an ascii count to integer, consuming tokens - -SYNOPSIS - - static int - get_count (const char **type, int *count) - -DESCRIPTION - - Assume that *type points at a count in a mangled name; set - *count to its value, and set *type to the next character after - the count. There are some weird rules in effect here. - - If *type does not point at a string of digits, return zero. - - If *type points at a string of digits followed by an - underscore, set *count to their value as an integer, advance - *type to point *after the underscore, and return 1. - - If *type points at a string of digits not followed by an - underscore, consume only the first digit. Set *count to its - value as an integer, leave *type pointing after that digit, - and return 1. - - The excuse for this odd behavior: in the ARM and HP demangling - styles, a type can be followed by a repeat count of the form - `Nxy', where: - - `x' is a single digit specifying how many additional copies - of the type to append to the argument list, and - - `y' is one or more digits, specifying the zero-based index of - the first repeated argument in the list. Yes, as you're - unmangling the name you can figure this out yourself, but - it's there anyway. - - So, for example, in `bar__3fooFPiN51', the first argument is a - pointer to an integer (`Pi'), and then the next five arguments - are the same (`N5'), and the first repeat is the function's - second argument (`1'). -*/ - -static int -get_count (const char **type, int *count) -{ - const char *p; - int n; - - if (!ISDIGIT ((unsigned char)**type)) - return (0); - else - { - *count = **type - '0'; - (*type)++; - if (ISDIGIT ((unsigned char)**type)) - { - p = *type; - n = *count; - do - { - n *= 10; - n += *p - '0'; - p++; - } - while (ISDIGIT ((unsigned char)*p)); - if (*p == '_') - { - *type = p + 1; - *count = n; - } - } - } - return (1); -} - -/* RESULT will be initialised here; it will be freed on failure. The - value returned is really a type_kind_t. */ - -static int -do_type (work_stuff *work, const char **mangled, string *result) -{ - int n; - int done; - int success; - string decl; - const char *remembered_type; - int type_quals; - string btype; - type_kind_t tk = tk_none; - - string_init (&btype); - string_init (&decl); - string_init (result); - - done = 0; - success = 1; - while (success && !done) - { - int member; - switch (**mangled) - { - - /* A pointer type */ - case 'P': - case 'p': - (*mangled)++; - string_prepend (&decl, "*"); - if (tk == tk_none) - tk = tk_pointer; - break; - - /* A reference type */ - case 'R': - (*mangled)++; - string_prepend (&decl, "&"); - if (tk == tk_none) - tk = tk_reference; - break; - - /* An array */ - case 'A': - { - ++(*mangled); - if (!STRING_EMPTY (&decl) - && (decl.b[0] == '*' || decl.b[0] == '&')) - { - string_prepend (&decl, "("); - string_append (&decl, ")"); - } - string_append (&decl, "["); - if (**mangled != '_') - success = demangle_template_value_parm (work, mangled, &decl, - tk_integral); - if (**mangled == '_') - ++(*mangled); - string_append (&decl, "]"); - break; - } - - /* A back reference to a previously seen type */ - case 'T': - (*mangled)++; - if (!get_count (mangled, &n) || n >= work -> ntypes) - { - success = 0; - } - else - { - remembered_type = work -> typevec[n]; - mangled = &remembered_type; - } - break; - - /* A function */ - case 'F': - (*mangled)++; - if (!STRING_EMPTY (&decl) - && (decl.b[0] == '*' || decl.b[0] == '&')) - { - string_prepend (&decl, "("); - string_append (&decl, ")"); - } - /* After picking off the function args, we expect to either find the - function return type (preceded by an '_') or the end of the - string. */ - if (!demangle_nested_args (work, mangled, &decl) - || (**mangled != '_' && **mangled != '\0')) - { - success = 0; - break; - } - if (success && (**mangled == '_')) - (*mangled)++; - break; - - case 'M': - case 'O': - { - type_quals = TYPE_UNQUALIFIED; - - member = **mangled == 'M'; - (*mangled)++; - - string_append (&decl, ")"); - - /* We don't need to prepend `::' for a qualified name; - demangle_qualified will do that for us. */ - if (**mangled != 'Q') - string_prepend (&decl, SCOPE_STRING (work)); - - if (ISDIGIT ((unsigned char)**mangled)) - { - n = consume_count (mangled); - if (n == -1 - || (int) strlen (*mangled) < n) - { - success = 0; - break; - } - string_prependn (&decl, *mangled, n); - *mangled += n; - } - else if (**mangled == 'X' || **mangled == 'Y') - { - string temp; - do_type (work, mangled, &temp); - string_prepends (&decl, &temp); - } - else if (**mangled == 't') - { - string temp; - string_init (&temp); - success = demangle_template (work, mangled, &temp, - NULL, 1, 1); - if (success) - { - string_prependn (&decl, temp.b, temp.p - temp.b); - string_clear (&temp); - } - else - break; - } - else if (**mangled == 'Q') - { - success = demangle_qualified (work, mangled, &decl, - /*isfuncnam=*/0, - /*append=*/0); - if (!success) - break; - } - else - { - success = 0; - break; - } - - string_prepend (&decl, "("); - if (member) - { - switch (**mangled) - { - case 'C': - case 'V': - case 'u': - type_quals |= code_for_qualifier (**mangled); - (*mangled)++; - break; - - default: - break; - } - - if (*(*mangled)++ != 'F') - { - success = 0; - break; - } - } - if ((member && !demangle_nested_args (work, mangled, &decl)) - || **mangled != '_') - { - success = 0; - break; - } - (*mangled)++; - if (! PRINT_ANSI_QUALIFIERS) - { - break; - } - if (type_quals != TYPE_UNQUALIFIED) - { - APPEND_BLANK (&decl); - string_append (&decl, qualifier_string (type_quals)); - } - break; - } - case 'G': - (*mangled)++; - break; - - case 'C': - case 'V': - case 'u': - if (PRINT_ANSI_QUALIFIERS) - { - if (!STRING_EMPTY (&decl)) - string_prepend (&decl, " "); - - string_prepend (&decl, demangle_qualifier (**mangled)); - } - (*mangled)++; - break; - /* - } - */ - - /* fall through */ - default: - done = 1; - break; - } - } - - if (success) switch (**mangled) - { - /* A qualified name, such as "Outer::Inner". */ - case 'Q': - case 'K': - { - success = demangle_qualified (work, mangled, result, 0, 1); - break; - } - - /* A back reference to a previously seen squangled type */ - case 'B': - (*mangled)++; - if (!get_count (mangled, &n) || n >= work -> numb) - success = 0; - else - string_append (result, work->btypevec[n]); - break; - - case 'X': - case 'Y': - /* A template parm. We substitute the corresponding argument. */ - { - int idx; - - (*mangled)++; - idx = consume_count_with_underscores (mangled); - - if (idx == -1 - || (work->tmpl_argvec && idx >= work->ntmpl_args) - || consume_count_with_underscores (mangled) == -1) - { - success = 0; - break; - } - - if (work->tmpl_argvec) - string_append (result, work->tmpl_argvec[idx]); - else - string_append_template_idx (result, idx); - - success = 1; - } - break; - - default: - success = demangle_fund_type (work, mangled, result); - if (tk == tk_none) - tk = (type_kind_t) success; - break; - } - - if (success) - { - if (!STRING_EMPTY (&decl)) - { - string_append (result, " "); - string_appends (result, &decl); - } - } - else - string_delete (result); - string_delete (&decl); - - if (success) - /* Assume an integral type, if we're not sure. */ - return (int) ((tk == tk_none) ? tk_integral : tk); - else - return 0; -} - -/* Given a pointer to a type string that represents a fundamental type - argument (int, long, unsigned int, etc) in TYPE, a pointer to the - string in which the demangled output is being built in RESULT, and - the WORK structure, decode the types and add them to the result. - - For example: - - "Ci" => "const int" - "Sl" => "signed long" - "CUs" => "const unsigned short" - - The value returned is really a type_kind_t. */ - -static int -demangle_fund_type (work_stuff *work, const char **mangled, string *result) -{ - int done = 0; - int success = 1; - char buf[10]; - unsigned int dec = 0; - string btype; - type_kind_t tk = tk_integral; - - string_init (&btype); - - /* First pick off any type qualifiers. There can be more than one. */ - - while (!done) - { - switch (**mangled) - { - case 'C': - case 'V': - case 'u': - if (PRINT_ANSI_QUALIFIERS) - { - if (!STRING_EMPTY (result)) - string_prepend (result, " "); - string_prepend (result, demangle_qualifier (**mangled)); - } - (*mangled)++; - break; - case 'U': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "unsigned"); - break; - case 'S': /* signed char only */ - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "signed"); - break; - case 'J': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "__complex"); - break; - default: - done = 1; - break; - } - } - - /* Now pick off the fundamental type. There can be only one. */ - - switch (**mangled) - { - case '\0': - case '_': - break; - case 'v': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "void"); - break; - case 'x': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "long long"); - break; - case 'l': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "long"); - break; - case 'i': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "int"); - break; - case 's': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "short"); - break; - case 'b': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "bool"); - tk = tk_bool; - break; - case 'c': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "char"); - tk = tk_char; - break; - case 'w': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "wchar_t"); - tk = tk_char; - break; - case 'r': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "long double"); - tk = tk_real; - break; - case 'd': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "double"); - tk = tk_real; - break; - case 'f': - (*mangled)++; - APPEND_BLANK (result); - string_append (result, "float"); - tk = tk_real; - break; - case 'G': - (*mangled)++; - if (!ISDIGIT ((unsigned char)**mangled)) - { - success = 0; - break; - } - case 'I': - (*mangled)++; - if (**mangled == '_') - { - int i; - (*mangled)++; - for (i = 0; - i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_'; - (*mangled)++, i++) - buf[i] = **mangled; - if (**mangled != '_') - { - success = 0; - break; - } - buf[i] = '\0'; - (*mangled)++; - } - else - { - strncpy (buf, *mangled, 2); - buf[2] = '\0'; - *mangled += min (strlen (*mangled), 2); - } - /*sscanf (buf, "%x", &dec); - sprintf (buf, "int%u_t", dec);*/ - sprintf (buf, "i_xx_t"); - APPEND_BLANK (result); - string_append (result, buf); - break; - - /* fall through */ - /* An explicit type, such as "6mytype" or "7integer" */ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int bindex = register_Btype (work); - string loc_btype; - string_init (&loc_btype); - if (demangle_class_name (work, mangled, &loc_btype)) { - remember_Btype (work, loc_btype.b, LEN_STRING (&loc_btype), bindex); - APPEND_BLANK (result); - string_appends (result, &loc_btype); - } - else - success = 0; - string_delete (&loc_btype); - break; - } - case 't': - { - success = demangle_template (work, mangled, &btype, 0, 1, 1); - string_appends (result, &btype); - break; - } - default: - success = 0; - break; - } - - string_delete (&btype); - - return success ? ((int) tk) : 0; -} - - -/* Handle a template's value parameter for HP aCC (extension from ARM) - **mangled points to 'S' or 'U' */ - -static int -do_hpacc_template_const_value ( - work_stuff *work ATTRIBUTE_UNUSED, - const char **mangled, - string *result) -{ - int unsigned_const; - - if (**mangled != 'U' && **mangled != 'S') - return 0; - - unsigned_const = (**mangled == 'U'); - - (*mangled)++; - - switch (**mangled) - { - case 'N': - string_append (result, "-"); - /* fall through */ - case 'P': - (*mangled)++; - break; - case 'M': - /* special case for -2^31 */ - string_append (result, "-2147483648"); - (*mangled)++; - return 1; - default: - return 0; - } - - /* We have to be looking at an integer now */ - if (!(ISDIGIT ((unsigned char)**mangled))) - return 0; - - /* We only deal with integral values for template - parameters -- so it's OK to look only for digits */ - while (ISDIGIT ((unsigned char)**mangled)) - { - char_str[0] = **mangled; - string_append (result, char_str); - (*mangled)++; - } - - if (unsigned_const) - string_append (result, "U"); - - /* FIXME? Some day we may have 64-bit (or larger :-) ) constants - with L or LL suffixes. pai/1997-09-03 */ - - return 1; /* success */ -} - -/* Handle a template's literal parameter for HP aCC (extension from ARM) - **mangled is pointing to the 'A' */ - -static int -do_hpacc_template_literal ( - work_stuff *work, - const char **mangled, - string *result) -{ - int literal_len = 0; - char * recurse; - char * recurse_dem; - - if (**mangled != 'A') - return 0; - - (*mangled)++; - - literal_len = consume_count (mangled); - - if (literal_len <= 0) - return 0; - - /* Literal parameters are names of arrays, functions, etc. and the - canonical representation uses the address operator */ - string_append (result, "&"); - - /* Now recursively demangle the literal name */ - recurse = (char *) xmalloc (literal_len + 1); - memcpy (recurse, *mangled, literal_len); - recurse[literal_len] = '\000'; - - recurse_dem = cplus_demangle (recurse, work->options); - - if (recurse_dem) - { - string_append (result, recurse_dem); - free (recurse_dem); - } - else - { - string_appendn (result, *mangled, literal_len); - } - (*mangled) += literal_len; - free (recurse); - - return 1; -} - -static int -snarf_numeric_literal (const char **args, string *arg) -{ - if (**args == '-') - { - char_str[0] = '-'; - string_append (arg, char_str); - (*args)++; - } - else if (**args == '+') - (*args)++; - - if (!ISDIGIT ((unsigned char)**args)) - return 0; - - while (ISDIGIT ((unsigned char)**args)) - { - char_str[0] = **args; - string_append (arg, char_str); - (*args)++; - } - - return 1; -} - -/* Demangle the next argument, given by MANGLED into RESULT, which - *should be an uninitialized* string. It will be initialized here, - and free'd should anything go wrong. */ - -static int -do_arg ( - work_stuff *work, - const char **mangled, - string *result) -{ - /* Remember where we started so that we can record the type, for - non-squangling type remembering. */ - const char *start = *mangled; - string temp_result; - - string_init (result); - string_init (&temp_result); - - if (work->nrepeats > 0) - { - --work->nrepeats; - - if (work->previous_argument == 0) - return 0; - - /* We want to reissue the previous type in this argument list. */ - string_appends (result, work->previous_argument); - return 1; - } - - if (**mangled == 'n') - { - /* A squangling-style repeat. */ - (*mangled)++; - work->nrepeats = consume_count(mangled); - - if (work->nrepeats <= 0) - /* This was not a repeat count after all. */ - return 0; - - if (work->nrepeats > 9) - { - if (**mangled != '_') - /* The repeat count should be followed by an '_' in this - case. */ - return 0; - else - (*mangled)++; - } - - /* Now, the repeat is all set up. */ - return do_arg (work, mangled, result); - } - - /* Save the result in WORK->previous_argument so that we can find it - if it's repeated. Note that saving START is not good enough: we - do not want to add additional types to the back-referenceable - type vector when processing a repeated type. */ - if (work->previous_argument) - string_clear (work->previous_argument); - else - { - work->previous_argument = (string*) xmalloc (sizeof (string)); - string_init (work->previous_argument); - } - - if (!do_type (work, mangled, &temp_result)) - { - string_delete (&temp_result); - return 0; - } - string_appends (work->previous_argument, &temp_result); - string_delete (&temp_result); - - string_appends (result, work->previous_argument); - - remember_type (work, start, *mangled - start); - return 1; -} - -static void -remember_type ( - work_stuff *work, - const char *start, - int len) -{ - char *tem; - - if (work->forgetting_types) - return; - - if (work -> ntypes >= work -> typevec_size) - { - if (work -> typevec_size == 0) - { - work -> typevec_size = 3; - work -> typevec - = (char **) xmalloc (sizeof (char *) * work -> typevec_size); - } - else - { - work -> typevec_size *= 2; - work -> typevec - = (char **) xrealloc ((char *)work -> typevec, - sizeof (char *) * work -> typevec_size); - } - } - tem = (char *) xmalloc (len + 1); - memcpy (tem, start, len); - tem[len] = '\0'; - work -> typevec[work -> ntypes++] = tem; -} - - -/* Remember a K type class qualifier. */ -static void -remember_Ktype ( - work_stuff *work, - const char *start, - int len) -{ - char *tem; - - if (work -> numk >= work -> ksize) - { - if (work -> ksize == 0) - { - work -> ksize = 5; - work -> ktypevec - = (char **) xmalloc (sizeof (char *) * work -> ksize); - } - else - { - work -> ksize *= 2; - work -> ktypevec - = (char **) xrealloc ((char *)work -> ktypevec, - sizeof (char *) * work -> ksize); - } - } - tem = (char *) xmalloc (len + 1); - memcpy (tem, start, len); - tem[len] = '\0'; - work -> ktypevec[work -> numk++] = tem; -} - -/* Register a B code, and get an index for it. B codes are registered - as they are seen, rather than as they are completed, so map > - registers map > as B0, and temp as B1 */ - -static int -register_Btype (work_stuff *work) -{ - int ret; - - if (work -> numb >= work -> bsize) - { - if (work -> bsize == 0) - { - work -> bsize = 5; - work -> btypevec - = (char **) xmalloc (sizeof (char *) * work -> bsize); - } - else - { - work -> bsize *= 2; - work -> btypevec - = (char **) xrealloc ((char *)work -> btypevec, - sizeof (char *) * work -> bsize); - } - } - ret = work -> numb++; - work -> btypevec[ret] = NULL; - return(ret); -} - -/* Store a value into a previously registered B code type. */ - -static void -remember_Btype ( - work_stuff *work, - const char *start, - int len, int ind) -{ - char *tem; - - tem = (char *) xmalloc (len + 1); - memcpy (tem, start, len); - tem[len] = '\0'; - work -> btypevec[ind] = tem; -} - -/* Lose all the info related to B and K type codes. */ -static void -forget_B_and_K_types (work_stuff *work) -{ - int i; - - while (work -> numk > 0) - { - i = --(work -> numk); - if (work -> ktypevec[i] != NULL) - { - free (work -> ktypevec[i]); - work -> ktypevec[i] = NULL; - } - } - - while (work -> numb > 0) - { - i = --(work -> numb); - if (work -> btypevec[i] != NULL) - { - free (work -> btypevec[i]); - work -> btypevec[i] = NULL; - } - } -} -/* Forget the remembered types, but not the type vector itself. */ - -static void -forget_types (work_stuff *work) -{ - int i; - - while (work -> ntypes > 0) - { - i = --(work -> ntypes); - if (work -> typevec[i] != NULL) - { - free (work -> typevec[i]); - work -> typevec[i] = NULL; - } - } -} - -/* Process the argument list part of the signature, after any class spec - has been consumed, as well as the first 'F' character (if any). For - example: - - "__als__3fooRT0" => process "RT0" - "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" - - DECLP must be already initialised, usually non-empty. It won't be freed - on failure. - - Note that g++ differs significantly from ARM and lucid style mangling - with regards to references to previously seen types. For example, given - the source fragment: - - class foo { - public: - foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); - }; - - foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } - void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } - - g++ produces the names: - - __3fooiRT0iT2iT2 - foo__FiR3fooiT1iT1 - - while lcc (and presumably other ARM style compilers as well) produces: - - foo__FiR3fooT1T2T1T2 - __ct__3fooFiR3fooT1T2T1T2 - - Note that g++ bases its type numbers starting at zero and counts all - previously seen types, while lucid/ARM bases its type numbers starting - at one and only considers types after it has seen the 'F' character - indicating the start of the function args. For lucid/ARM style, we - account for this difference by discarding any previously seen types when - we see the 'F' character, and subtracting one from the type number - reference. - - */ - -static int -demangle_args ( - work_stuff *work, - const char **mangled, - string *declp) -{ - string arg; - int need_comma = 0; - int r; - int t; - const char *tem; - char temptype; - - if (PRINT_ARG_TYPES) - { - string_append (declp, "("); - if (**mangled == '\0') - { - string_append (declp, "void"); - } - } - - while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') - || work->nrepeats > 0) - { - if ((**mangled == 'N') || (**mangled == 'T')) - { - temptype = *(*mangled)++; - - if (temptype == 'N') - { - if (!get_count (mangled, &r)) - { - return (0); - } - } - else - { - r = 1; - } - if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10) - { - /* If we have 10 or more types we might have more than a 1 digit - index so we'll have to consume the whole count here. This - will lose if the next thing is a type name preceded by a - count but it's impossible to demangle that case properly - anyway. Eg if we already have 12 types is T12Pc "(..., type1, - Pc, ...)" or "(..., type12, char *, ...)" */ - if ((t = consume_count(mangled)) <= 0) - { - return (0); - } - } - else - { - if (!get_count (mangled, &t)) - { - return (0); - } - } - if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) - { - t--; - } - /* Validate the type index. Protect against illegal indices from - malformed type strings. */ - if ((t < 0) || (t >= work -> ntypes)) - { - return (0); - } - while (work->nrepeats > 0 || --r >= 0) - { - tem = work -> typevec[t]; - if (need_comma && PRINT_ARG_TYPES) - { - string_append (declp, ", "); - } - if (!do_arg (work, &tem, &arg)) - { - return (0); - } - if (PRINT_ARG_TYPES) - { - string_appends (declp, &arg); - } - string_delete (&arg); - need_comma = 1; - } - } - else - { - if (need_comma && PRINT_ARG_TYPES) - string_append (declp, ", "); - if (!do_arg (work, mangled, &arg)) - { - string_delete (&arg); - return (0); - } - if (PRINT_ARG_TYPES) - string_appends (declp, &arg); - string_delete (&arg); - need_comma = 1; - } - } - - if (**mangled == 'e') - { - (*mangled)++; - if (PRINT_ARG_TYPES) - { - if (need_comma) - { - string_append (declp, ","); - } - string_append (declp, "..."); - } - } - - if (PRINT_ARG_TYPES) - { - string_append (declp, ")"); - } - return (1); -} - -/* Like demangle_args, but for demangling the argument lists of function - and method pointers or references, not top-level declarations. */ - -static int -demangle_nested_args ( - work_stuff *work, - const char **mangled, - string *declp) -{ - string* saved_previous_argument; - int result; - int saved_nrepeats; - - /* The G++ name-mangling algorithm does not remember types on nested - argument lists, unless -fsquangling is used, and in that case the - type vector updated by remember_type is not used. So, we turn - off remembering of types here. */ - ++work->forgetting_types; - - /* For the repeat codes used with -fsquangling, we must keep track of - the last argument. */ - saved_previous_argument = work->previous_argument; - saved_nrepeats = work->nrepeats; - work->previous_argument = 0; - work->nrepeats = 0; - - /* Actually demangle the arguments. */ - result = demangle_args (work, mangled, declp); - - /* Restore the previous_argument field. */ - if (work->previous_argument) - { - string_delete (work->previous_argument); - free ((char*) work->previous_argument); - } - work->previous_argument = saved_previous_argument; - --work->forgetting_types; - work->nrepeats = saved_nrepeats; - - return result; -} - -static void -demangle_function_name ( - work_stuff *work, - const char **mangled, - string *declp, - const char *scan) -{ - size_t i; - string type; - const char *tem; - - string_appendn (declp, (*mangled), scan - (*mangled)); - string_need (declp, 1); - *(declp -> p) = '\0'; - - /* Consume the function name, including the "__" separating the name - from the signature. We are guaranteed that SCAN points to the - separator. */ - - (*mangled) = scan + 2; - /* We may be looking at an instantiation of a template function: - foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a - following _F marks the start of the function arguments. Handle - the template arguments first. */ - - if (HP_DEMANGLING && (**mangled == 'X')) - { - demangle_arm_hp_template (work, mangled, 0, declp); - /* This leaves MANGLED pointing to the 'F' marking func args */ - } - - if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) - { - - /* See if we have an ARM style constructor or destructor operator. - If so, then just record it, clear the decl, and return. - We can't build the actual constructor/destructor decl until later, - when we recover the class name from the signature. */ - - if (strcmp (declp -> b, "__ct") == 0) - { - work -> constructor += 1; - string_clear (declp); - return; - } - else if (strcmp (declp -> b, "__dt") == 0) - { - work -> destructor += 1; - string_clear (declp); - return; - } - } - - if (declp->p - declp->b >= 3 - && declp->b[0] == 'o' - && declp->b[1] == 'p' - && strchr (cplus_markers, declp->b[2]) != NULL) - { - /* see if it's an assignment expression */ - if (declp->p - declp->b >= 10 /* op$assign_ */ - && memcmp (declp->b + 3, "assign_", 7) == 0) - { - for (i = 0; i < (size_t)ARRAY_SIZE (optable); i++) - { - int len = declp->p - declp->b - 10; - if ((int) strlen (optable[i].in) == len - && memcmp (optable[i].in, declp->b + 10, len) == 0) - { - string_clear (declp); - string_append (declp, "operator"); - string_append (declp, optable[i].out); - string_append (declp, "="); - break; - } - } - } - else - { - for (i = 0; i < (size_t)ARRAY_SIZE (optable); i++) - { - int len = declp->p - declp->b - 3; - if ((int) strlen (optable[i].in) == len - && memcmp (optable[i].in, declp->b + 3, len) == 0) - { - string_clear (declp); - string_append (declp, "operator"); - string_append (declp, optable[i].out); - break; - } - } - } - } - else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 - && strchr (cplus_markers, declp->b[4]) != NULL) - { - /* type conversion operator */ - tem = declp->b + 5; - if (do_type (work, &tem, &type)) - { - string_clear (declp); - string_append (declp, "operator "); - string_appends (declp, &type); - string_delete (&type); - } - } - else if (declp->b[0] == '_' && declp->b[1] == '_' - && declp->b[2] == 'o' && declp->b[3] == 'p') - { - /* ANSI. */ - /* type conversion operator. */ - tem = declp->b + 4; - if (do_type (work, &tem, &type)) - { - string_clear (declp); - string_append (declp, "operator "); - string_appends (declp, &type); - string_delete (&type); - } - } - else if (declp->b[0] == '_' && declp->b[1] == '_' - && ISLOWER((unsigned char)declp->b[2]) - && ISLOWER((unsigned char)declp->b[3])) - { - if (declp->b[4] == '\0') - { - /* Operator. */ - for (i = 0; i < (size_t)ARRAY_SIZE (optable); i++) - { - if (strlen (optable[i].in) == 2 - && memcmp (optable[i].in, declp->b + 2, 2) == 0) - { - string_clear (declp); - string_append (declp, "operator"); - string_append (declp, optable[i].out); - break; - } - } - } - else - { - if (declp->b[2] == 'a' && declp->b[5] == '\0') - { - /* Assignment. */ - for (i = 0; i < (size_t)ARRAY_SIZE (optable); i++) - { - if (strlen (optable[i].in) == 3 - && memcmp (optable[i].in, declp->b + 2, 3) == 0) - { - string_clear (declp); - string_append (declp, "operator"); - string_append (declp, optable[i].out); - break; - } - } - } - } - } -} - -/* a mini string-handling package */ - -static void -string_need (string *s, int n) -{ - int tem; - - if (s->b == NULL) - { - if (n < 32) - { - n = 32; - } - s->p = s->b = (char *) xmalloc (n); - s->e = s->b + n; - } - else if (s->e - s->p < n) - { - tem = s->p - s->b; - n += tem; - n *= 2; - s->b = (char *) xrealloc (s->b, n); - s->p = s->b + tem; - s->e = s->b + n; - } -} - -static void -string_delete (string *s) -{ - if (s->b != NULL) - { - free (s->b); - s->b = s->e = s->p = NULL; - } -} - -static void -string_init (string *s) -{ - s->b = s->p = s->e = NULL; -} - -static void -string_clear (string *s) -{ - s->p = s->b; -} - -static void -string_append (string *p, const char *s) -{ - int n; - if (s == NULL || *s == '\0') - return; - n = strlen (s); - string_need (p, n); - memcpy (p->p, s, n); - p->p += n; -} - -static void -string_appends (string *p, string *s) -{ - int n; - - if (s->b != s->p) - { - n = s->p - s->b; - string_need (p, n); - memcpy (p->p, s->b, n); - p->p += n; - } -} - -static void -string_appendn (string *p, const char *s, int n) -{ - if (n != 0) - { - string_need (p, n); - memcpy (p->p, s, n); - p->p += n; - } -} - -static void -string_prepend (string *p, const char *s) -{ - if (s != NULL && *s != '\0') - { - string_prependn (p, s, strlen (s)); - } -} - -static void -string_prepends (string *p, string *s) -{ - if (s->b != s->p) - { - string_prependn (p, s->b, s->p - s->b); - } -} - -static void -string_prependn (string *p, const char *s, int n) -{ - char *q; - - if (n != 0) - { - string_need (p, n); - for (q = p->p - 1; q >= p->b; q--) - { - q[n] = q[0]; - } - memcpy (p->b, s, n); - p->p += n; - } -} - -static void -string_append_template_idx (string *s, int idx) -{ - char buf[INTBUF_SIZE + 1 /* 'T' */]; - sprintf(buf, "T%d", idx); - string_append (s, buf); -} -#endif - -#ifdef STANDALONE_DEMANGLER -#include -#include - -int main(int argc, char *argv[]) -{ - for (int i = 1; i < argc; i++) { - const char *mangled_name = argv[i]; - char *demangled_name = cxx_demangle(mangled_name, NULL, NULL, NULL); - if (demangled_name == NULL) - printf("Could not demangle string '%s'\n", mangled_name); - else { - printf("'%s'\n -> '%s'\n\n", mangled_name, demangled_name); - free(demangled_name); - } - } -} -#endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.h deleted file mode 100644 index 6b634f4b..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * cxxdemangle.h - C++ demangler - * - * Kheperix (C) 2003-2005-2004 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CXX_DEMANGLE_H -#define CXX_DEMANGLE_H - -/** - * cxx_demangle - * - * Following GCC 3.0 ABI: - * - * - * - MANGLED-NAME is a pointer to a null-terminated array of - * characters - * - * - BUF may be null. If it is non-null, then N must also be - * nonnull, and BUF is a pointer to an array, of at least *N - * characters, that was allocated using malloc(). - * - * - STATUS points to an int that is used as an error indicator. It - * is permitted to be null, in which case the user just doesn't - * get any detailed error information. - * - * Codes: 0: success - * -1: memory allocation failure - * -2: invalid mangled name - * -3: invalid arguments (e.g. BUG nonnull and N null) - **/ - -#ifdef __cplusplus -extern "C" -#endif -char *cxx_demangle(const char *mangled_name, - char *buf, - size_t *n, - int *status); - -#endif /* CXX_DEMANGLE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/dummy/jit-target-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/dummy/jit-target-cache.hpp deleted file mode 100644 index 8bed86af..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/dummy/jit-target-cache.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * jit-target-cache.hpp - Target specific code to invalidate cache - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_TARGET_CACHE_H -#define JIT_TARGET_CACHE_H - -static inline void flush_icache_range(unsigned long, unsigned long) -{ -} - -#endif /* JIT_TARGET_CACHE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h deleted file mode 100644 index 8c12fe6b..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * dyngen defines for micro operation code - * - * Copyright (c) 2003-2004-2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DYNGEN_EXEC_H -#define DYNGEN_EXEC_H - -#include "cpu/jit/jit-config.hpp" - -#define _JIT_HEADER dyngen-target-exec.h -#include "cpu/jit/jit-target-dispatch.h" - -/* define virtual register set */ -#define REG_CPU AREG0 -#define REG_CPU_ID AREG0_ID -#define REG_T0 AREG1 -#define REG_T0_ID AREG1_ID -#define REG_T1 AREG2 -#define REG_T1_ID AREG2_ID -#define REG_T2 AREG3 -#define REG_T2_ID AREG3_ID -#ifdef AREG4 -#define REG_T3 AREG4 -#define REG_T3_ID AREG4_ID -#endif -#ifdef FREG3 -#define REG_F0 FREG0 -#define REG_F0_ID FREG0_ID -#define REG_F1 FREG1 -#define REG_F1_ID FREG1_ID -#define REG_F2 FREG2 -#define REG_F2_ID FREG2_ID -#define REG_F3 FREG3 -#define REG_F3_ID FREG3_ID -#endif -#ifdef VREG3 -#define REG_V0 VREG0 -#define REG_V0_ID VREG0_ID -#define REG_V1 VREG1 -#define REG_V1_ID VREG1_ID -#define REG_V2 VREG2 -#define REG_V2_ID VREG2_ID -#define REG_V3 VREG3 -#define REG_V3_ID VREG3_ID -#endif - -// Force only one return point -#define dyngen_barrier() asm volatile ("") - -#ifndef OPPROTO -#define OPPROTO -#endif - -#ifdef __alpha__ -/* the symbols are considered non exported so a br immediate is generated */ -#define __hidden __attribute__((visibility("hidden"))) -#else -#define __hidden -#endif - -#ifdef __alpha__ -/* Suggested by Richard Henderson. This will result in code like - ldah $0,__op_PARAM1($29) !gprelhigh - lda $0,__op_PARAM1($0) !gprellow - We can then conveniently change $29 to $31 and adapt the offsets to - emit the appropriate constant. */ -#define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_PARAM1)); _r; }) -#define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_PARAM2)); _r; }) -#define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_PARAM3)); _r; }) -extern int __op_PARAM1 __hidden; -extern int __op_PARAM2 __hidden; -extern int __op_PARAM3 __hidden; -#elif defined __mips__ -/* On MIPS, parameters to a C expression are passed via the global pointer. - * We don't want that. */ -#define PARAMN(index) ({ register int _r; \ - asm("lui %0,%%hi(__op_PARAM" #index ")\n\t" \ - "ori %0,%0,%%lo(__op_PARAM" #index ")" \ - : "=r"(_r)); _r; }) -#define PARAM1 PARAMN(1) -#define PARAM2 PARAMN(2) -#define PARAM3 PARAMN(3) -#else -#if defined(__APPLE__) && defined(__MACH__) -static int __op_PARAM1, __op_PARAM2, __op_PARAM3; -#else -extern int __op_PARAM1, __op_PARAM2, __op_PARAM3; -#endif -#define PARAM1 ((long)(&__op_PARAM1)) -#define PARAM2 ((long)(&__op_PARAM2)) -#define PARAM3 ((long)(&__op_PARAM3)) -#endif - -// Direct block chaining support -#if defined(__powerpc__) || defined(__ppc__) -#define DYNGEN_FAST_DISPATCH(TARGET) asm volatile ("b " ASM_NAME(TARGET)) -#endif -#if defined(__i386__) || defined(__x86_64__) -#define DYNGEN_FAST_DISPATCH(TARGET) asm volatile ("jmp " ASM_NAME(TARGET)) -#endif - -#define DYNGEN_SLOW_DISPATCH(TARGET) do { \ - static const void __attribute__((unused)) *label1 = &&dummy_label1; \ - static const void __attribute__((unused)) *label2 = &&dummy_label2; \ - goto *((void *)TARGET); \ - dummy_label1: \ - dummy_label2: \ - dyngen_barrier(); \ -} while (0) - -extern int __op_jmp0, __op_jmp1; - -// Sections handling -#if defined(__CYGWIN__) || defined(_WIN32) -#define ASM_DATA_SECTION ".section .data\n" -#define ASM_PREVIOUS_SECTION ".section .text\n" -#define ASM_GLOBAL ".global" -#define ASM_NAME(NAME) "_" #NAME -#define ASM_SIZE(NAME) "" -#elif defined(__APPLE__) && defined(__MACH__) -#define ASM_DATA_SECTION ".data\n" -#define ASM_PREVIOUS_SECTION ".text\n" -#define ASM_GLOBAL ".globl" -#define ASM_NAME(NAME) "_" #NAME -#define ASM_SIZE(NAME) "" -#if defined(__ppc__) -#define ASM_OP_EXEC_RETURN_INSN "0x18,0xde,0xad,0xff" -#endif -#if defined(__i386__) -#define ASM_OP_EXEC_RETURN_INSN "0x0f,0xa6,0xf0" -#endif -#elif defined __sgi && defined __mips -#define ASM_DATA_SECTION ".data\n" -#define ASM_PREVIOUS_SECTION ".text\n" -#define ASM_GLOBAL ".globl" -#define ASM_NAME(NAME) #NAME -#define ASM_SIZE(NAME) "" -#define ASM_LONG ".word" -#else -#define ASM_DATA_SECTION ".section \".data\"\n" -#define ASM_PREVIOUS_SECTION ".previous\n" -#define ASM_GLOBAL ".global" -#define ASM_NAME(NAME) #NAME -#define ASM_SIZE(NAME) ".size " ASM_NAME(NAME) ",.-" ASM_NAME(NAME) -#endif -#ifndef ASM_LONG -#define ASM_LONG ".long" -#endif - -// Helper macros to annotate likely branch directions -#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) -#ifndef likely -#define likely(x) __builtin_expect((x),1) -#endif -#ifndef unlikely -#define unlikely(x) __builtin_expect((x),0) -#endif -#endif -#ifndef likely -#define likely(x) (x) -#endif -#ifndef unlikely -#define unlikely(x) (x) -#endif - -#endif /* DYNGEN_EXEC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c b/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c deleted file mode 100644 index b6ead792..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c +++ /dev/null @@ -1,3027 +0,0 @@ -/* - * Generic Dynamic compiler generator - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * The COFF object format support was extracted from Kazu's QEMU port - * to Win32. - * - * Mach-O Support by Matt Reda and Pierre d'Herbemont - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" -#include "cxxdemangle.h" - -/* object file format defs */ -#ifndef CONFIG_WIN32 -#if defined(__CYGWIN__) || defined(_WIN32) -#define CONFIG_WIN32 1 -#endif -#endif -#ifndef CONFIG_DARWIN -#if defined(__APPLE__) && defined(__MACH__) -#define CONFIG_DARWIN 1 -#endif -#endif - -/* host cpu defs */ -#if CONFIG_WIN32 -#define HOST_I386 1 -#elif defined(__i386__) -#define HOST_I386 1 -#elif defined(__powerpc__) || defined(__ppc__) -#define HOST_PPC 1 -#elif defined(__s390__) -#define HOST_S390 1 -#elif defined(__alpha__) -#define HOST_ALPHA 1 -#elif defined(__ia64__) -#define HOST_IA64 1 -#elif defined(__sparc__) -#define HOST_SPARC 1 -#elif defined(__x86_64__) -#define HOST_X86_64 1 -#elif defined(__m68k__) -#define HOST_M68K 1 -#elif defined(__mips__) -#define HOST_MIPS 1 -#endif - -/* Debug generated code */ -#if ENABLE_MON && (defined(HOST_I386) || defined(HOST_X86_64)) && 0 -#define DYNGEN_PRETTY_PRINT 1 - -#include "disass/dis-asm.h" - -static inline bfd_byte bfd_read_byte(bfd_vma from) -{ - bfd_byte *p = (bfd_byte *)(uintptr_t)from; - return *p; -} - -int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info) -{ - while (length--) - *to++ = bfd_read_byte(from++); - return 0; -} - -void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info) -{ - info->fprintf_func(info->stream, "Unknown error %d\n", status); -} - -static uintptr_t print_address_base; - -void generic_print_address(bfd_vma addr, struct disassemble_info *info) -{ - addr -= print_address_base; - if (addr >= UVAL64(0x100000000)) - info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr); - else - info->fprintf_func(info->stream, "$%08x", (uint32)addr); -} - -int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info) -{ - return 0; -} - -struct SFILE { - char *buffer; - char *current; -}; - -static int dyngen_sprintf(struct SFILE *f, const char *format, ...) -{ - int n; - va_list args; - va_start(args, format); - vsprintf(f->current, format, args); - f->current += n = strlen(f->current); - va_end(args); - return n; -} - -#if defined(HOST_I386) || defined(HOST_X86_64) -static int pretty_print(char *buf, uintptr_t addr, uintptr_t base) -{ - disassemble_info info; - struct SFILE sfile = {buf, buf}; - sfile.buffer = buf; - sfile.current = buf; - INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)dyngen_sprintf); -#if defined(HOST_X86_64) - info.mach = bfd_mach_x86_64; -#endif - print_address_base = base; - return print_insn_i386_att(addr, &info); -} -#endif -#endif - -/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross - compilation */ -#if defined(CONFIG_WIN32) -#define CONFIG_FORMAT_COFF -#elif defined(CONFIG_DARWIN) -#define CONFIG_FORMAT_MACH -#else -#define CONFIG_FORMAT_ELF -#endif - -#ifdef CONFIG_FORMAT_ELF - -/* elf format definitions. We use these macros to test the CPU to - allow cross compilation (this tool must be ran on the build - platform) */ -#if defined(HOST_I386) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_386 -#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) -#undef ELF_USES_RELOCA - -#elif defined(HOST_X86_64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_X86_64 -#define elf_check_arch(x) ((x) == EM_X86_64) -#define ELF_USES_RELOCA - -#elif defined(HOST_PPC) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_PPC -#define elf_check_arch(x) ((x) == EM_PPC) -#define ELF_USES_RELOCA - -#elif defined(HOST_S390) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_S390 -#define elf_check_arch(x) ((x) == EM_S390) -#define ELF_USES_RELOCA - -#elif defined(HOST_ALPHA) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_ALPHA -#define elf_check_arch(x) ((x) == EM_ALPHA) -#define ELF_USES_RELOCA - -#elif defined(HOST_IA64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_IA_64 -#define elf_check_arch(x) ((x) == EM_IA_64) -#define ELF_USES_RELOCA - -#elif defined(HOST_SPARC) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_SPARC -#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS) -#define ELF_USES_RELOCA - -#elif defined(HOST_SPARC64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_SPARCV9 -#define elf_check_arch(x) ((x) == EM_SPARCV9) -#define ELF_USES_RELOCA - -#elif defined(HOST_ARM) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_ARM -#define elf_check_arch(x) ((x) == EM_ARM) -#define ELF_USES_RELOC - -#elif defined(HOST_M68K) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_68K -#define elf_check_arch(x) ((x) == EM_68K) -#define ELF_USES_RELOCA - -#elif defined(HOST_MIPS) - -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_MIPS -#define elf_check_arch(x) ((x) == EM_MIPS) -#define ELF_USES_RELOCA -#define ELF_USES_ALSO_RELOC - -#else -#error unsupported CPU - please update the code -#endif - -#include "elf-defs.h" - -#ifndef ElfW -# if ELF_CLASS == ELFCLASS32 -# define ElfW(x) Elf32_ ## x -# define ELFW(x) ELF32_ ## x -# else -# define ElfW(x) Elf64_ ## x -# define ELFW(x) ELF64_ ## x -# endif -#endif - -#if ELF_CLASS == ELFCLASS32 -typedef uint32_t host_ulong; -#define swabls(x) swab32s(x) -#else -typedef uint64_t host_ulong; -#define swabls(x) swab64s(x) -#endif - -typedef ElfW(Ehdr) elfhdr; -typedef ElfW(Shdr) elf_shdr; -typedef ElfW(Phdr) elf_phdr; -typedef ElfW(Rel) elf_rel; -typedef ElfW(Rela) elf_rela; - -#ifdef ELF_USES_RELOCA -#define ELF_RELOC elf_rela -#define SHT_RELOC SHT_RELA -#else -#define ELF_RELOC elf_rel -#define SHT_RELOC SHT_REL -#endif - -#define EXE_RELOC ELF_RELOC -#define EXE_SYM ElfW(Sym) - -#endif /* CONFIG_FORMAT_ELF */ - -#ifdef CONFIG_FORMAT_COFF - -#include "a.out-defs.h" - -typedef uint32_t host_ulong; - -#define FILENAMELEN 256 - -typedef struct coff_sym { - struct external_syment *st_syment; - char st_name[FILENAMELEN]; - uint32_t st_value; - int st_size; - uint8_t st_type; - uint8_t st_shndx; -} coff_Sym; - -typedef struct coff_rel { - struct external_reloc *r_reloc; - int r_offset; - uint8_t r_type; -} coff_Rel; - -#define EXE_RELOC struct coff_rel -#define EXE_SYM struct coff_sym - -#endif /* CONFIG_FORMAT_COFF */ - -#ifdef CONFIG_FORMAT_MACH - -#include -#include -#include -#include - -#if defined(HOST_PPC) || defined(HOST_I386) - -# if defined(HOST_I386) - -# define mach_check_cputype(x) ((x) == CPU_TYPE_I386) -# else -# define mach_check_cputype(x) ((x) == CPU_TYPE_POWERPC) -# endif -# define check_mach_header(x) (x.magic == MH_MAGIC) -# define SEGMENT_COMMAND segment_command -# define MACH_HEADER mach_header -# define SECTION section -# define NLIST nlist -typedef uint32_t host_ulong; - -#elif defined(HOST_X86_64) - -# include -# define mach_check_cputype(x) ((x) == CPU_TYPE_X86_64) -# define check_mach_header(x) (x.magic == MH_MAGIC_64) -# define SEGMENT_COMMAND segment_command_64 -# define MACH_HEADER mach_header_64 -# define SECTION section_64 -# define NLIST nlist_64 -typedef uint64_t host_ulong; - -#else -#error unsupported CPU - please update the code -#endif - -struct nlist_extended -{ - union { -#ifdef HOST_X86_64 - unsigned int n_strx; -#else - char *n_name; - long n_strx; -#endif - } n_un; - unsigned char n_type; - unsigned char n_sect; - short st_desc; - unsigned long st_value; - unsigned long st_size; -}; - -#define EXE_RELOC struct relocation_info -#define EXE_SYM struct nlist_extended - -#endif /* CONFIG_FORMAT_MACH */ - -enum { - OUT_GEN_OP_ALL, -}; - -/* all dynamically generated functions begin with this code */ -#define OP_PREFIX "op_" - -int do_swap; - -void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "dyngen: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(1); -} - -void *load_data(int fd, long offset, unsigned int size) -{ - char *data; - - data = malloc(size); - if (!data) - return NULL; - lseek(fd, offset, SEEK_SET); - if (read(fd, data, size) != size) { - free(data); - return NULL; - } - return data; -} - -int strstart(const char *str, const char *val, const char **ptr) -{ - const char *p, *q; - p = str; - q = val; - while (*q != '\0') { - if (*p != *q) - return 0; - p++; - q++; - } - if (ptr) - *ptr = p; - return 1; -} - -void pstrcpy(char *buf, int buf_size, const char *str) -{ - int c; - char *q = buf; - - if (buf_size <= 0) - return; - - for(;;) { - c = *str++; - if (c == 0 || q >= buf + buf_size - 1) - break; - *q++ = c; - } - *q = '\0'; -} - -void swab16s(uint16_t *p) -{ - *p = bswap_16(*p); -} - -void swab32s(uint32_t *p) -{ - *p = bswap_32(*p); -} - -void swab64s(uint64_t *p) -{ - *p = bswap_64(*p); -} - -uint16_t get16(uint16_t *p) -{ - uint16_t val; - val = *p; - if (do_swap) - val = bswap_16(val); - return val; -} - -uint32_t get32(uint32_t *p) -{ - uint32_t val; - val = *p; - if (do_swap) - val = bswap_32(val); - return val; -} - -void put16(uint16_t *p, uint16_t val) -{ - if (do_swap) - val = bswap_16(val); - *p = val; -} - -void put32(uint32_t *p, uint32_t val) -{ - if (do_swap) - val = bswap_32(val); - *p = val; -} - -static int is_op_param(const char *sym_name, const char **ptr) -{ - return - strstart(sym_name, "__op_param", ptr) || strstart(sym_name, "_op_param", ptr) || - strstart(sym_name, "__op_PARAM", ptr) || strstart(sym_name, "_op_PARAM", ptr); -} - -static int is_op_jmp(const char *sym_name, const char **ptr) -{ - return strstart(sym_name, "__op_jmp", ptr) || strstart(sym_name, "_op_jmp", ptr); -} - -static int is_op_gen_label(const char *sym_name, const char **ptr) -{ - return strstart(sym_name, "__op_gen_label", ptr) || strstart(sym_name, "_op_gen_label", ptr); -} - -/* generate op code */ -void gen_code(const char *name, const char *demangled_name, - host_ulong offset, host_ulong size, - FILE *outfile, int gen_switch, const char *prefix); -void patch_relocations(FILE *outfile, const char *name, host_ulong size, host_ulong start_offset, int copy_size); - -static void do_print_code(FILE *outfile, const char *name, const uint8_t *code_p, int code_size, int is_code) -{ - int i, b; - fprintf(outfile, " static const uint8 %s[] = {", name); -#ifdef DYNGEN_PRETTY_PRINT - if (is_code) { - const int BYTES_PER_LINE = 5; - uint8_t out[1024]; - int outindex = 0; - char buf[1024]; - uintptr_t addr = (uintptr_t)code_p; - uintptr_t end_addr = addr + code_size; - int ip = 0; - fprintf(outfile, "\n"); - while (addr < end_addr) { - int num = pretty_print(buf, (uintptr_t)addr, (uintptr_t)code_p); - int max_num = num > BYTES_PER_LINE ? num : BYTES_PER_LINE; - for (i = 0; i < max_num; i++) { - if ((i % BYTES_PER_LINE) == 0) - fprintf(outfile, "/* %04x */ ", ip); - if (i < num) { - fprintf(outfile, "0x%02x", (out[outindex++] = code_p[ip++])); - if (ip != code_size) - fprintf(outfile, ", "); - else - fprintf(outfile, " "); - } - else - fprintf(outfile, " "); - if (i == BYTES_PER_LINE - 1) - fprintf(outfile, "/* %s */", buf); - if ((i + 1) % BYTES_PER_LINE == 0 || i == max_num - 1) - fprintf(outfile, "\n"); - } - addr += num; - } - fprintf(outfile, " };\n"); - - /* sanity check we have not forgotten any byte */ - assert(outindex == code_size); - assert(memcmp(code_p, out, code_size) == 0); - return; - } -#endif - for (i = 0; i < code_size; i++) { - if ((i % 12) == 0) { - if (i != 0) - fprintf(outfile, ","); - fprintf(outfile, "\n "); - } - else - fprintf(outfile, ", "); - fprintf(outfile, "0x%02x", code_p[i]); - } - fprintf(outfile, "\n };\n"); -} - -static void print_code(FILE *outfile, const char *name, const uint8_t *code_p, int code_size) -{ - char *code_name; - code_name = alloca(strlen(name) + 5); - strcpy(code_name, name); - strcat(code_name, "_code"); - do_print_code(outfile, code_name, code_p, code_size, 1); -} - -static void print_data(FILE *outfile, const char *name, const uint8_t *data, int data_size) -{ - do_print_code(outfile, name, data, data_size, 0); -} - -static char *gen_dot_prefix(const char *sym_name) -{ - static char name[256]; - assert(sym_name[0] == '.'); - snprintf(name, sizeof(name), "dot_%s", sym_name + 1); - return name; -} - - -/* executable information */ -EXE_SYM *symtab; -int nb_syms; -int text_shndx; -int data_shndx; -uint8_t *text; -uint8_t *data; -uint8_t *literal16; -EXE_RELOC *relocs; -int nb_relocs; - -#ifdef CONFIG_FORMAT_ELF - -/* ELF file info */ -elf_shdr *shdr; -uint8_t **sdata; -elfhdr ehdr; -char *strtab; - -int elf_must_swap(elfhdr *h) -{ - union { - uint32_t i; - uint8_t b[4]; - } swaptest; - - swaptest.i = 1; - return (h->e_ident[EI_DATA] == ELFDATA2MSB) != - (swaptest.b[0] == 0); -} - -void elf_swap_ehdr(elfhdr *h) -{ - swab16s(&h->e_type); /* Object file type */ - swab16s(&h-> e_machine); /* Architecture */ - swab32s(&h-> e_version); /* Object file version */ - swabls(&h-> e_entry); /* Entry point virtual address */ - swabls(&h-> e_phoff); /* Program header table file offset */ - swabls(&h-> e_shoff); /* Section header table file offset */ - swab32s(&h-> e_flags); /* Processor-specific flags */ - swab16s(&h-> e_ehsize); /* ELF header size in bytes */ - swab16s(&h-> e_phentsize); /* Program header table entry size */ - swab16s(&h-> e_phnum); /* Program header table entry count */ - swab16s(&h-> e_shentsize); /* Section header table entry size */ - swab16s(&h-> e_shnum); /* Section header table entry count */ - swab16s(&h-> e_shstrndx); /* Section header string table index */ -} - -void elf_swap_shdr(elf_shdr *h) -{ - swab32s(&h-> sh_name); /* Section name (string tbl index) */ - swab32s(&h-> sh_type); /* Section type */ - swabls(&h-> sh_flags); /* Section flags */ - swabls(&h-> sh_addr); /* Section virtual addr at execution */ - swabls(&h-> sh_offset); /* Section file offset */ - swabls(&h-> sh_size); /* Section size in bytes */ - swab32s(&h-> sh_link); /* Link to another section */ - swab32s(&h-> sh_info); /* Additional section information */ - swabls(&h-> sh_addralign); /* Section alignment */ - swabls(&h-> sh_entsize); /* Entry size if section holds table */ -} - -void elf_swap_phdr(elf_phdr *h) -{ - swab32s(&h->p_type); /* Segment type */ - swabls(&h->p_offset); /* Segment file offset */ - swabls(&h->p_vaddr); /* Segment virtual address */ - swabls(&h->p_paddr); /* Segment physical address */ - swabls(&h->p_filesz); /* Segment size in file */ - swabls(&h->p_memsz); /* Segment size in memory */ - swab32s(&h->p_flags); /* Segment flags */ - swabls(&h->p_align); /* Segment alignment */ -} - -void elf_swap_rel(ELF_RELOC *rel) -{ - swabls(&rel->r_offset); - swabls(&rel->r_info); -#ifdef ELF_USES_RELOCA - swabls(&rel->r_addend); -#endif -} - -elf_shdr *find_elf_section(elf_shdr *shdr, int shnum, const char *shstr, - const char *name) -{ - int i; - const char *shname; - elf_shdr *sec; - - for(i = 0; i < shnum; i++) { - sec = &shdr[i]; - if (!sec->sh_name) - continue; - shname = shstr + sec->sh_name; - if (!strcmp(shname, name)) - return sec; - } - return NULL; -} - -static int do_find_reloc(int sh_index, ElfW(Word) type) -{ - elf_shdr *sec; - int i; - - for(i = 0; i < ehdr.e_shnum; i++) { - sec = &shdr[i]; - if (sec->sh_type == type && sec->sh_info == sh_index) - return i; - } - return 0; -} - -static int find_reloc(int sh_index) -{ - return do_find_reloc(sh_index, SHT_RELOC); -} - -static host_ulong get_rel_offset(EXE_RELOC *rel) -{ - return rel->r_offset; -} - -static char *get_rel_sym_name(EXE_RELOC *rel) -{ - return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; -} - -static char *get_sym_name(EXE_SYM *sym) -{ - return strtab + sym->st_name; -} - -/* load an elf object file */ -int load_object(const char *filename, FILE *outfile) -{ - int fd; - elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec; - int i, j; - ElfW(Sym) *sym; - char *shstr; - ELF_RELOC *rel; - elf_shdr *data_sec; - elf_shdr *rodata_cst4_sec; - uint8_t *rodata_cst4 = NULL; - int rodata_cst4_shndx; - elf_shdr *rodata_cst8_sec; - uint8_t *rodata_cst8 = NULL; - int rodata_cst8_shndx; - elf_shdr *rodata_cst16_sec; - uint8_t *rodata_cst16 = NULL; - int rodata_cst16_shndx; - - fd = open(filename, O_RDONLY); - if (fd < 0) - error("can't open file '%s'", filename); - - /* Read ELF header. */ - if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) - error("unable to read file header"); - - /* Check ELF identification. */ - if (ehdr.e_ident[EI_MAG0] != ELFMAG0 - || ehdr.e_ident[EI_MAG1] != ELFMAG1 - || ehdr.e_ident[EI_MAG2] != ELFMAG2 - || ehdr.e_ident[EI_MAG3] != ELFMAG3 - || ehdr.e_ident[EI_VERSION] != EV_CURRENT) { - error("bad ELF header"); - } - - do_swap = elf_must_swap(&ehdr); - if (do_swap) - elf_swap_ehdr(&ehdr); - if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) - error("Unsupported ELF class"); - if (ehdr.e_type != ET_REL) - error("ELF object file expected"); - if (ehdr.e_version != EV_CURRENT) - error("Invalid ELF version"); - if (!elf_check_arch(ehdr.e_machine)) - error("Unsupported CPU (e_machine=%d)", ehdr.e_machine); - - /* read section headers */ - shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(elf_shdr)); - if (do_swap) { - for(i = 0; i < ehdr.e_shnum; i++) { - elf_swap_shdr(&shdr[i]); - } - } - - /* read all section data */ - sdata = malloc(sizeof(void *) * ehdr.e_shnum); - memset(sdata, 0, sizeof(void *) * ehdr.e_shnum); - - for(i = 0;i < ehdr.e_shnum; i++) { - sec = &shdr[i]; - if (sec->sh_type != SHT_NOBITS) - sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size); - } - - sec = &shdr[ehdr.e_shstrndx]; - shstr = sdata[ehdr.e_shstrndx]; - - /* swap relocations */ - for(i = 0; i < ehdr.e_shnum; i++) { - sec = &shdr[i]; - if (sec->sh_type == SHT_REL || sec->sh_type == SHT_RELA) { - nb_relocs = sec->sh_size / sec->sh_entsize; - if (do_swap) { - for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++) - elf_swap_rel(rel); - } - } - } - - /* data section */ - data_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".data"); - if (data_sec) { - data_shndx = data_sec - shdr; - data = sdata[data_shndx]; - } - else { - data_shndx = -1; - data = NULL; - } - - /* rodata sections */ - rodata_cst4_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".rodata.cst4"); - if (rodata_cst4_sec) { - rodata_cst4_shndx = rodata_cst4_sec - shdr; - rodata_cst4 = sdata[rodata_cst4_shndx]; - } - rodata_cst8_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".rodata.cst8"); - if (rodata_cst8_sec) { - rodata_cst8_shndx = rodata_cst8_sec - shdr; - rodata_cst8 = sdata[rodata_cst8_shndx]; - } - rodata_cst16_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".rodata.cst16"); - if (rodata_cst16_sec) { - rodata_cst16_shndx = rodata_cst16_sec - shdr; - rodata_cst16 = sdata[rodata_cst16_shndx]; - } - - /* text section */ - text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text"); - if (!text_sec) - error("could not find .text section"); - text_shndx = text_sec - shdr; - text = sdata[text_shndx]; - - /* find text relocations, if any */ - relocs = NULL; - nb_relocs = 0; - i = find_reloc(text_shndx); - if (i != 0) { - relocs = (ELF_RELOC *)sdata[i]; - nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize; - } -#ifdef ELF_USES_ALSO_RELOC - i = do_find_reloc(text_shndx, SHT_REL); - if (i != 0) { - if (relocs) { - int j, nb_rels = shdr[i].sh_size / shdr[i].sh_entsize; - ElfW(Rel) *rels = (ElfW(Rel) *)sdata[i]; - ELF_RELOC *new_relocs = (ELF_RELOC *)malloc(sizeof(ELF_RELOC) * (nb_relocs + nb_rels)); - memcpy(new_relocs, relocs, sizeof(ELF_RELOC) * nb_relocs); - for (j = 0; j < nb_rels; j++) { - new_relocs[j + nb_relocs].r_offset = rels[j].r_offset; - new_relocs[j + nb_relocs].r_info = rels[j].r_info; - new_relocs[j + nb_relocs].r_addend = 0; - } - nb_relocs += nb_rels; - relocs = new_relocs; - } - } -#endif - - symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab"); - if (!symtab_sec) - error("could not find .symtab section"); - strtab_sec = &shdr[symtab_sec->sh_link]; - - symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr]; - strtab = sdata[symtab_sec->sh_link]; - - nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym)); - if (do_swap) { - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - swab32s(&sym->st_name); - swabls(&sym->st_value); - swabls(&sym->st_size); - swab16s(&sym->st_shndx); - } - } - close(fd); - - { - int status; - size_t nf, nd = 256; - char *demangled_name, *func_name; - if ((demangled_name = malloc(nd)) == NULL) - return -1; - if ((func_name = malloc(nf = nd)) == NULL) { - free(demangled_name); - return -1; - } - - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - const char *name; - name = get_sym_name(sym); - /* emit local symbols */ - if (strstart(name, ".LC", NULL)) { - const char *dot_name = gen_dot_prefix(name); - fprintf(outfile, "DEFINE_GEN(gen_const_%s,uint8 *,(void))\n", dot_name); - fprintf(outfile, "#ifdef DYNGEN_IMPL\n"); - fprintf(outfile, "{\n"); - int dot_size = 0; - if (sym->st_shndx == (rodata_cst16_sec - shdr)) - print_data(outfile, dot_name, rodata_cst16 + sym->st_value, (dot_size = 16)); - else if (sym->st_shndx == (rodata_cst8_sec - shdr)) - print_data(outfile, dot_name, rodata_cst8 + sym->st_value, (dot_size = 8)); - else if (sym->st_shndx == (rodata_cst4_sec - shdr)) - print_data(outfile, dot_name, rodata_cst4 + sym->st_value, (dot_size = 4)); - else - error("invalid section for local data %s (%x)\n", name, sym->st_shndx); - fprintf(outfile, " static uint8 *data_p = NULL;\n"); - fprintf(outfile, " if (data_p == NULL)\n"); - fprintf(outfile, " data_p = copy_data(%s, %d);\n", dot_name, dot_size); - fprintf(outfile, " return data_p;\n"); - fprintf(outfile, "}\n"); - fprintf(outfile, "#endif\n"); - } - } - - free(func_name); - free(demangled_name); - } - return 0; -} - -#endif /* CONFIG_FORMAT_ELF */ - -#ifdef CONFIG_FORMAT_COFF - -/* COFF file info */ -struct external_scnhdr *shdr; -uint8_t **sdata; -struct external_filehdr fhdr; -struct external_syment *coff_symtab; -char *strtab; -int coff_text_shndx, coff_data_shndx; - -#define STRTAB_SIZE 4 - -#define DIR32 0x06 -#define DISP32 0x14 - -#define T_FUNCTION 0x20 -#define C_EXTERNAL 2 - -void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym) -{ - char *q; - int c, i, len; - - if (ext_sym->e.e.e_zeroes != 0) { - q = sym->st_name; - for(i = 0; i < 8; i++) { - c = ext_sym->e.e_name[i]; - if (c == '\0') - break; - *q++ = c; - } - *q = '\0'; - } else { - pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset); - } - - /* now convert the name to a C name (suppress the leading '_') */ - if (sym->st_name[0] == '_') { - len = strlen(sym->st_name); - memmove(sym->st_name, sym->st_name + 1, len - 1); - sym->st_name[len - 1] = '\0'; - } -} - -char *name_for_dotdata(struct coff_rel *rel) -{ - int i; - struct coff_sym *sym; - uint32_t text_data; - - text_data = *(uint32_t *)(text + rel->r_offset); - - for (i = 0, sym = symtab; i < nb_syms; i++, sym++) { - if (sym->st_syment->e_scnum == data_shndx && - text_data >= sym->st_value && - text_data < sym->st_value + sym->st_size) { - - return sym->st_name; - - } - } - return NULL; -} - -static char *get_sym_name(EXE_SYM *sym) -{ - return sym->st_name; -} - -static char *get_rel_sym_name(EXE_RELOC *rel) -{ - char *name; - name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx)); - if (!strcmp(name, ".data")) - name = name_for_dotdata(rel); - return name; -} - -static host_ulong get_rel_offset(EXE_RELOC *rel) -{ - return rel->r_offset; -} - -struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name) -{ - int i; - const char *shname; - struct external_scnhdr *sec; - - for(i = 0; i < shnum; i++) { - sec = &shdr[i]; - if (!sec->s_name) - continue; - shname = sec->s_name; - if (!strcmp(shname, name)) - return sec; - } - return NULL; -} - -/* load a coff object file */ -int load_object(const char *filename, FILE *outfile) -{ - int fd; - struct external_scnhdr *sec, *text_sec, *data_sec; - int i, j; - struct external_syment *ext_sym; - struct external_reloc *coff_relocs; - struct external_reloc *ext_rel; - uint32_t *n_strtab; - EXE_SYM *sym; - EXE_RELOC *rel; - - fd = open(filename, O_RDONLY -#ifdef _WIN32 - | O_BINARY -#endif - ); - if (fd < 0) - error("can't open file '%s'", filename); - - /* Read COFF header. */ - if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr)) - error("unable to read file header"); - - /* Check COFF identification. */ - if (fhdr.f_magic != I386MAGIC) { - error("bad COFF header"); - } - do_swap = 0; - - /* read section headers */ - shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr)); - - /* read all section data */ - sdata = malloc(sizeof(void *) * fhdr.f_nscns); - memset(sdata, 0, sizeof(void *) * fhdr.f_nscns); - - const char *p; - for(i = 0;i < fhdr.f_nscns; i++) { - sec = &shdr[i]; - if (!strstart(sec->s_name, ".bss", &p)) - sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size); - } - - - /* text section */ - text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text"); - if (!text_sec) - error("could not find .text section"); - coff_text_shndx = text_sec - shdr; - text = sdata[coff_text_shndx]; - - /* data section */ - data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data"); - if (!data_sec) - error("could not find .data section"); - coff_data_shndx = data_sec - shdr; - data = sdata[coff_data_shndx]; - - coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ); - for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) { - for(j=0;j<8;j++) - printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[j]); - printf("\n"); - } - - nb_syms = fhdr.f_nsyms; - n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE); - strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab); - - for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) { - if (strstart(ext_sym->e.e_name, ".text", NULL)) - text_shndx = ext_sym->e_scnum; - if (strstart(ext_sym->e.e_name, ".data", NULL)) - data_shndx = ext_sym->e_scnum; - } - - /* set coff symbol */ - symtab = malloc(sizeof(struct coff_sym) * nb_syms); - - int aux_size; - for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) { - memset(sym, 0, sizeof(*sym)); - sym->st_syment = ext_sym; - sym_ent_name(ext_sym, sym); - sym->st_value = ext_sym->e_value; - - aux_size = *(int8_t *)ext_sym->e_numaux; - if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) { - for (j = aux_size + 1; j < nb_syms - i; j++) { - if ((ext_sym + j)->e_scnum == text_shndx && - (ext_sym + j)->e_type == T_FUNCTION ){ - sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value; - break; - } else if (j == nb_syms - i - 1) { - sec = &shdr[coff_text_shndx]; - sym->st_size = sec->s_size - ext_sym->e_value; - break; - } - } - } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) { - for (j = aux_size + 1; j < nb_syms - i; j++) { - if ((ext_sym + j)->e_scnum == data_shndx) { - sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value; - break; - } else if (j == nb_syms - i - 1) { - sec = &shdr[coff_data_shndx]; - sym->st_size = sec->s_size - ext_sym->e_value; - break; - } - } - } else { - sym->st_size = 0; - } - - sym->st_type = ext_sym->e_type; - sym->st_shndx = ext_sym->e_scnum; - } - - - /* find text relocations, if any */ - sec = &shdr[coff_text_shndx]; - coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ); - nb_relocs = sec->s_nreloc; - - /* set coff relocation */ - relocs = malloc(sizeof(struct coff_rel) * nb_relocs); - for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs; - i++, ext_rel++, rel++) { - memset(rel, 0, sizeof(*rel)); - rel->r_reloc = ext_rel; - rel->r_offset = *(uint32_t *)ext_rel->r_vaddr; - rel->r_type = *(uint16_t *)ext_rel->r_type; - } - return 0; -} - -#endif /* CONFIG_FORMAT_COFF */ - -#ifdef CONFIG_FORMAT_MACH - -/* File Header */ -struct MACH_HEADER mach_hdr; - -/* commands */ -struct SEGMENT_COMMAND *segment = 0; -struct dysymtab_command *dysymtabcmd = 0; -struct symtab_command *symtabcmd = 0; - -/* section */ -struct SECTION *section_hdr; -struct SECTION *text_sec_hdr; -struct SECTION *data_sec_hdr; -struct SECTION *literal16_sec_hdr; -uint8_t **sdata; - -/* relocs */ -struct relocation_info *relocs; - -/* symbols */ -EXE_SYM *symtab; -struct NLIST *symtab_std; -char *strtab; - -/* indirect symbols */ -uint32_t *tocdylib; - -/* Utility functions */ - -static inline char *find_str_by_index(int index) -{ - return strtab+index; -} - -/* Used by dyngen common code */ -static char *get_sym_name(EXE_SYM *sym) -{ - char *name = find_str_by_index(sym->n_un.n_strx); - - if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */ - return "debug"; - - if(!name) - return name; - if(name[0]=='_') - return name + 1; - else - return name; -} - -/* find a section index given its segname, sectname */ -static int find_mach_sec_index(struct SECTION *section_hdr, int shnum, const char *segname, - const char *sectname) -{ - int i; - struct SECTION *sec = section_hdr; - - for(i = 0; i < shnum; i++, sec++) { - if (!sec->segname || !sec->sectname) - continue; - if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname)) - return i; - } - return -1; -} - -/* find a section header given its segname, sectname */ -struct SECTION *find_mach_sec_hdr(struct SECTION *section_hdr, int shnum, const char *segname, - const char *sectname) -{ - int index = find_mach_sec_index(section_hdr, shnum, segname, sectname); - if(index == -1) - return NULL; - return section_hdr+index; -} - - -static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value) -{ - struct scattered_relocation_info * scarel; - - if(R_SCATTERED & rel->r_address) { - scarel = (struct scattered_relocation_info*)rel; - if(scarel->r_type != PPC_RELOC_PAIR) - error("fetch_next_pair_value: looking for a pair which was not found (1)"); - *value = scarel->r_value; - } else { - if(rel->r_type != PPC_RELOC_PAIR) - error("fetch_next_pair_value: looking for a pair which was not found (2)"); - *value = rel->r_address; - } -} - -/* find a sym name given its value, in a section number */ -static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset ) -{ - int i, ret = -1; - - for( i = 0 ; i < nb_syms; i++ ) - { - if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) && - (symtab[i].n_sect == sectnum) && (symtab[i].st_value <= value) ) - { - if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) ) - ret = i; - } - } - if( ret < 0 ) { - *offset = 0; - return 0; - } else { - *offset = value - symtab[ret].st_value; - return get_sym_name(&symtab[ret]); - } -} - -/* - * Find symbol name given a (virtual) address, and a section which is of type - * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS - */ -static const char * find_reloc_name_in_sec_ptr(int address, struct SECTION * sec_hdr) -{ - unsigned int tocindex, symindex, size; - const char *name = 0; - - /* Sanity check */ - if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) ) - return (char*)0; - - if( sec_hdr->flags & S_SYMBOL_STUBS ){ - size = sec_hdr->reserved2; - if(size == 0) - error("size = 0"); - - } - else if( (sec_hdr->flags & S_LAZY_SYMBOL_POINTERS) || - (sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS) ) - size = sizeof(unsigned long); - else - return 0; - - /* Compute our index in toc */ - tocindex = (address - sec_hdr->addr)/size; - symindex = tocdylib[sec_hdr->reserved1 + tocindex]; - - name = get_sym_name(&symtab[symindex]); - - return name; -} - -static const char * find_reloc_name_given_its_address(int address) -{ - unsigned int i; - for(i = 0; i < segment->nsects ; i++) - { - const char * name = find_reloc_name_in_sec_ptr(address, §ion_hdr[i]); - if((long)name != -1) - return name; - } - return 0; -} - -static const char * get_reloc_name(EXE_RELOC * rel, int * sslide) -{ - char * name = 0; - struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel; - int sectnum = rel->r_symbolnum; - int sectoffset; - unsigned int other_half=0; - - /* init the slide value */ -#ifdef HOST_X86_64 /* no scattered on x86_64 */ - switch(rel->r_length) - { - case 0: *sslide = *(uint8_t *)(text + rel->r_address); break; - case 1: *sslide = *(uint16_t *)(text + rel->r_address); break; - case 2: *sslide = *(uint32_t *)(text + rel->r_address); break; - case 3: *sslide = *(uint64_t *)(text + rel->r_address); break; - } -#else - *sslide = 0; - - if (R_SCATTERED & rel->r_address) { - char *name = (char *)find_reloc_name_given_its_address(sca_rel->r_value); - - /* search it in the full symbol list, if not found */ - if (!name) { - int i; - for (i = 0; i < nb_syms; i++) { - EXE_SYM *sym = &symtab[i]; - if (sym->st_value == sca_rel->r_value) { - name = get_sym_name(sym); - switch (sca_rel->r_type) { - case GENERIC_RELOC_VANILLA: - *sslide = *(uint32_t *)(text + sca_rel->r_address) - sca_rel->r_value; - break; - } - break; - } - } - } - return name; - } -#endif - - if(rel->r_extern) - { - /* ignore debug sym */ - if ( symtab[rel->r_symbolnum].n_type & N_STAB ) - return 0; - return get_sym_name(&symtab[rel->r_symbolnum]); - } - -#ifdef HOST_X86_64 - return 0; -#else - - /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */ - sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff; - - if(sectnum==0xffffff) - return 0; - - /* Sanity Check */ - if(sectnum > segment->nsects) - error("sectnum > segment->nsects"); - - switch(rel->r_type) - { - case PPC_RELOC_PAIR: // The second relocation entry of a pair. A PPC_RELOC_PAIR entry must follow each of the other relocation entry types, except for PPC_RELOC_VANILLA, PPC_RELOC_BR14, PPC_RELOC_BR24, and PPC_RELOC_PB_LA_PTR. - break; - case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16); - break; - case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff); - break; - case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff); - break; - case PPC_RELOC_BR24: - sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc ); - if (sectoffset & 0x02000000) sectoffset |= 0xfc000000; - break; - case GENERIC_RELOC_VANILLA: - sectoffset = *(uint32_t *)(text + rel->r_address); - break; - default: - error("switch(rel->type=%d) not found", rel->r_type); - } - - if(rel->r_pcrel) { - sectoffset += rel->r_address; -#ifdef HOST_I386 - sectoffset += (1 << rel->r_length); -#endif - } - - if (rel->r_type == PPC_RELOC_BR24) - name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, §ion_hdr[sectnum-1]); - - /* search it in the full symbol list, if not found */ - if(!name) - name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide); - - return name; -#endif -} - -/* Used by dyngen common code */ -static const char * get_rel_sym_name(EXE_RELOC * rel) -{ - int sslide; - return get_reloc_name( rel, &sslide); -} - -/* Used by dyngen common code */ -static host_ulong get_rel_offset(EXE_RELOC *rel) -{ - struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel; - if(R_SCATTERED & rel->r_address) - return sca_rel->r_address; - else - return rel->r_address; -} - -/* load a mach-o object file */ -int load_object(const char *filename, FILE *outfile) -{ - int fd; - unsigned int offset_to_segment = 0; - unsigned int offset_to_dysymtab = 0; - unsigned int offset_to_symtab = 0; - struct load_command lc; - unsigned int i, j; - EXE_SYM *sym; - struct NLIST *syment; - - fd = open(filename, O_RDONLY); - if (fd < 0) - error("can't open file '%s'", filename); - - /* Read Mach header. */ - if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr)) - error("unable to read file header"); - - /* Check Mach identification. */ - if (!check_mach_header(mach_hdr)) { - error("bad Mach header"); - } - - if (!mach_check_cputype(mach_hdr.cputype)) - error("Unsupported CPU"); - - if (mach_hdr.filetype != MH_OBJECT) - error("Unsupported Mach Object"); - - /* read segment headers */ - for(i=0, j=sizeof(mach_hdr); insects * sizeof(struct SECTION)); - - /* read all section data */ - sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects); - memset(sdata, 0, sizeof(void *) * segment->nsects); - - /* Load the data in section data */ - for(i = 0; i < segment->nsects; i++) - sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size); - - /* .data section */ - data_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_DATA, SECT_DATA); - i = find_mach_sec_index(section_hdr, segment->nsects, SEG_DATA, SECT_DATA); - data = (i == -1) ? NULL : sdata[i]; - - /* const section TODO: __cstring __literal4 __literal8 */ - literal16_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, "__literal16"); - i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, "__literal16"); - literal16 = (i == -1) ? NULL : sdata[i]; - - /* .text section */ - text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); - i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); - if (i == -1 || !text_sec_hdr) - error("could not find __TEXT,__text section"); - text = sdata[i]; - - /* Make sure dysym was loaded */ - if(dysymtabcmd == NULL) - error("could not find __DYSYMTAB segment"); - - /* read the table of content of the indirect sym */ - tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) ); - - /* Make sure symtab was loaded */ - if(symtabcmd == NULL) - error("could not find __SYMTAB segment"); - nb_syms = symtabcmd->nsyms; - - symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct NLIST)); - strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize); - - symtab = malloc(sizeof(EXE_SYM) * nb_syms); - - /* Now transform the symtab, to an extended version, with the sym size, and the C name */ - for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) { - struct NLIST *sym_follow, *sym_next = 0; - unsigned int j; - memset(sym, 0, sizeof(*sym)); - - if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ - continue; - - if ( strchr((char*)(strtab + syment->n_un.n_strx), '.') ) /* no Exception handlers */ - continue; - - memcpy(sym, syment, sizeof(*syment)); - - /* Find the following symbol in order to get the current symbol size */ - for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) { - if ( sym_follow->n_sect != 1 || (sym_follow->n_type & N_STAB) || !(sym_follow->n_value > sym->st_value) ) - continue; - if(!sym_next) { - sym_next = sym_follow; - continue; - } - if(!(sym_next->n_value > sym_follow->n_value)) - continue; - sym_next = sym_follow; - } - if(sym_next) - sym->st_size = sym_next->n_value - sym->st_value; - else - sym->st_size = text_sec_hdr->size - sym->st_value; - } - - /* Find Reloc */ - relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info)); - nb_relocs = text_sec_hdr->nreloc; - - close(fd); - return 0; -} - -#endif /* CONFIG_FORMAT_MACH */ - -void get_reloc_expr(char *name, int name_size, const char *sym_name) -{ - const char *p; - char *demangled; - char demangled_buf[256]; - size_t nd = sizeof(demangled_buf); - int status; - - demangled = cxx_demangle(sym_name, demangled_buf, &nd, &status); - if (!status && demangled) - sym_name = demangled; - if (is_op_param(sym_name, &p)) { - snprintf(name, name_size, "param%s", p); - } else if (is_op_gen_label(sym_name, &p)) { - snprintf(name, name_size, "gen_labels[param%s]", p); - } else if (strstart(sym_name, ".LC", NULL)) { - snprintf(name, name_size, "(long)(gen_const_%s())", gen_dot_prefix(sym_name)); - } else { -#ifdef HOST_SPARC - if (sym_name[0] == '.') - snprintf(name, name_size, - "(long)(&__dot_%s)", - sym_name + 1); - else -#endif - snprintf(name, name_size, "(long)(&%s)", sym_name); - } -} - -#ifdef HOST_ARM - -int arm_emit_ldr_info(const char *name, unsigned long start_offset, - FILE *outfile, uint8_t *p_start, uint8_t *p_end, - ELF_RELOC *relocs, int nb_relocs) -{ - uint8_t *p; - uint32_t insn; - int offset, min_offset, pc_offset, data_size; - uint8_t data_allocated[1024]; - unsigned int data_index; - - memset(data_allocated, 0, sizeof(data_allocated)); - - p = p_start; - min_offset = p_end - p_start; - while (p < p_start + min_offset) { - insn = get32((uint32_t *)p); - if ((insn & 0x0d5f0000) == 0x051f0000) { - /* ldr reg, [pc, #im] */ - offset = insn & 0xfff; - if (!(insn & 0x00800000)) - offset = -offset; - if ((offset & 3) !=0) - error("%s:%04x: ldr pc offset must be 32 bit aligned", - name, start_offset + p - p_start); - pc_offset = p - p_start + offset + 8; - if (pc_offset <= (p - p_start) || - pc_offset >= (p_end - p_start)) - error("%s:%04x: ldr pc offset must point inside the function code", - name, start_offset + p - p_start); - if (pc_offset < min_offset) - min_offset = pc_offset; - if (outfile) { - /* ldr position */ - fprintf(outfile, " arm_ldr_ptr->ptr = ptr() + %d;\n", - p - p_start); - /* ldr data index */ - data_index = ((p_end - p_start) - pc_offset - 4) >> 2; - fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n", - data_index); - fprintf(outfile, " arm_ldr_ptr++;\n"); - if (data_index >= sizeof(data_allocated)) - error("%s: too many data", name); - if (!data_allocated[data_index]) { - ELF_RELOC *rel; - int i, addend, type; - const char *sym_name, *p; - char relname[1024]; - - data_allocated[data_index] = 1; - - /* data value */ - addend = get32((uint32_t *)(p_start + pc_offset)); - relname[0] = '\0'; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset == (pc_offset + start_offset)) { - sym_name = get_rel_sym_name(rel); - /* the compiler leave some unnecessary references to the code */ - get_reloc_expr(relname, sizeof(relname), sym_name); - type = ELF32_R_TYPE(rel->r_info); - if (type != R_ARM_ABS32) - error("%s: unsupported data relocation", name); - break; - } - } - fprintf(outfile, " arm_data_ptr[%d] = 0x%x", - data_index, addend); - if (relname[0] != '\0') - fprintf(outfile, " + %s", relname); - fprintf(outfile, ";\n"); - } - } - } - p += 4; - } - data_size = (p_end - p_start) - min_offset; - if (data_size > 0 && outfile) { - fprintf(outfile, " arm_data_ptr += %d;\n", data_size >> 2); - } - - /* the last instruction must be a mov pc, lr */ - if (p == p_start) - goto arm_ret_error; - p -= 4; - insn = get32((uint32_t *)p); - if ((insn & 0xffff0000) != 0xe91b0000) { - arm_ret_error: - if (!outfile) - printf("%s: invalid epilog\n", name); - } - return p - p_start; -} -#endif - - -#define MAX_ARGS 3 - -/* generate op code */ -void gen_code(const char *name, const char *demangled_name, - host_ulong offset, host_ulong size, - FILE *outfile, int gen_switch, const char *prefix) -{ - int copy_size = 0; - uint8_t *p_start, *p_end; - host_ulong start_offset; - int nb_args, i, n; - uint8_t args_present[MAX_ARGS]; - const char *sym_name, *p; - EXE_RELOC *rel; - int op_execute = 0; - char demangled_buf[256]; - size_t nd; - char *demangled; - int status; - - if (strncmp(name, "op_execute", 10) == 0) - op_execute = 1; - - /* Compute exact size excluding prologue and epilogue instructions. - * Increment start_offset to skip epilogue instructions, then compute - * copy_size the indicate the size of the remaining instructions (in - * bytes). - */ - p_start = text + offset; - p_end = p_start + size; - start_offset = offset; - if (op_execute) { - uint8_t *p; - copy_size = p_end - p_start; -#ifdef CONFIG_FORMAT_MACH -#if defined(HOST_PPC) - for (p = p_start; p < p_end; p += 4) { - if (get32((uint32_t *)p) == 0x18deadff) - fprintf(outfile, "DEFINE_CST(op_exec_return_offset,0x%xL)\n\n", (p + 4) - p_start); - } -#elif defined(HOST_I386) - static const uint8_t return_insn[] = {0x0f,0xa6,0xf0}; - for (p = p_start; p < p_end; p++) { - if (memcmp(p, return_insn, sizeof(return_insn)) == 0) - fprintf(outfile, "DEFINE_CST(op_exec_return_offset,0x%xL)\n\n", (p + sizeof(return_insn)) - p_start); - } -#endif -#endif - } - else -#if defined(HOST_I386) || defined(HOST_X86_64) - { - uint8_t *p; - p = p_end - 1; - if (p == p_start) - error("empty code for %s", name); - while (*p != 0xc3) { - p--; - if (p <= p_start) - error("ret or jmp expected at the end of %s", name); - } - copy_size = p - p_start; - } -#elif defined(HOST_PPC) - { - uint8_t *p; - p = (void *)(p_end - 4); - if (p == p_start) - error("empty code for %s", name); - if (get32((uint32_t *)p) != 0x4e800020) - error("blr expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_S390) - { - uint8_t *p; - p = (void *)(p_end - 2); - if (p == p_start) - error("empty code for %s", name); - if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4) - error("br %%r14 expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_ALPHA) - { - uint8_t *p; - p = p_end - 4; -#if 0 - /* XXX: check why it occurs */ - if (p == p_start) - error("empty code for %s", name); -#endif - if (get32((uint32_t *)p) != 0x6bfa8001) - error("ret expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_IA64) - { - uint8_t *p; - p = (void *)(p_end - 4); - if (p == p_start) - error("empty code for %s", name); - /* br.ret.sptk.many b0;; */ - /* 08 00 84 00 */ - if (get32((uint32_t *)p) != 0x00840008) - error("br.ret.sptk.many b0;; expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_SPARC) - { - uint32_t start_insn, end_insn1, end_insn2; - uint8_t *p; - p = (void *)(p_end - 8); - if (p <= p_start) - error("empty code for %s", name); - start_insn = get32((uint32_t *)(p_start + 0x0)); - end_insn1 = get32((uint32_t *)(p + 0x0)); - end_insn2 = get32((uint32_t *)(p + 0x4)); - if ((start_insn & ~0x1fff) == 0x9de3a000) { - p_start += 0x4; - start_offset += 0x4; - if ((int)(start_insn | ~0x1fff) < -128) - error("Found bogus save at the start of %s", name); - if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) - error("ret; restore; not found at end of %s", name); - } else { - error("No save at the beginning of %s", name); - } -#if 0 - /* Skip a preceeding nop, if present. */ - if (p > p_start) { - skip_insn = get32((uint32_t *)(p - 0x4)); - if (skip_insn == 0x01000000) - p -= 4; - } -#endif - copy_size = p - p_start; - } -#elif defined(HOST_SPARC64) - { - uint32_t start_insn, end_insn1, end_insn2, skip_insn; - uint8_t *p; - p = (void *)(p_end - 8); - if (p <= p_start) - error("empty code for %s", name); - start_insn = get32((uint32_t *)(p_start + 0x0)); - end_insn1 = get32((uint32_t *)(p + 0x0)); - end_insn2 = get32((uint32_t *)(p + 0x4)); - if ((start_insn & ~0x1fff) == 0x9de3a000) { - p_start += 0x4; - start_offset += 0x4; - if ((int)(start_insn | ~0x1fff) < -256) - error("Found bogus save at the start of %s", name); - if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) - error("ret; restore; not found at end of %s", name); - } else { - error("No save at the beginning of %s", name); - } - - /* Skip a preceeding nop, if present. */ - if (p > p_start) { - skip_insn = get32((uint32_t *)(p - 0x4)); - if (skip_insn == 0x01000000) - p -= 4; - } - - copy_size = p - p_start; - } -#elif defined(HOST_ARM) - { - if ((p_end - p_start) <= 16) - error("%s: function too small", name); - if (get32((uint32_t *)p_start) != 0xe1a0c00d || - (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 || - get32((uint32_t *)(p_start + 8)) != 0xe24cb004) - error("%s: invalid prolog", name); - p_start += 12; - start_offset += 12; - copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, - relocs, nb_relocs); - } -#elif defined(HOST_M68K) - { - uint8_t *p; - p = (void *)(p_end - 2); - if (p == p_start) - error("empty code for %s", name); - // remove NOP's, probably added for alignment - while ((get16((uint16_t *)p) == 0x4e71) && - (p>p_start)) - p -= 2; - if (get16((uint16_t *)p) != 0x4e75) - error("rts expected at the end of %s", name); - copy_size = p - p_start; - } -#elif defined(HOST_MIPS) - { - uint8_t *p; - p = (void *)(p_end - 4); - if (p == p_start) - error("empty code for %s", name); - while (p > p_start && get32((uint32_t *)p) != 0x03e00008) - p -= 4; - if (get32((uint32_t *)p) != 0x03e00008) - error("jr ra expected at the end of %s", name); - copy_size = p - p_start; - } -#else -#error unsupported CPU -#endif - - - - /* compute the number of arguments by looking at the relocations */ - for(i = 0;i < MAX_ARGS; i++) - args_present[i] = 0; - - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - host_ulong offset = get_rel_offset(rel); - if (offset >= start_offset && - offset < start_offset + (p_end - p_start)) { - sym_name = get_rel_sym_name(rel); - if(!sym_name) - continue; - nd = sizeof(demangled_buf); - demangled = cxx_demangle(sym_name, demangled_buf, &nd, &status); - if (!status && demangled) - sym_name = demangled; - if (is_op_param(sym_name, &p)) { - n = strtoul(p, NULL, 10); - if (n > MAX_ARGS) - error("too many arguments in %s", name); - args_present[n - 1] = 1; - } - } - } - - nb_args = 0; - while (nb_args < MAX_ARGS && args_present[nb_args]) - nb_args++; - for(i = nb_args; i < MAX_ARGS; i++) { - if (args_present[i]) - error("inconsistent argument numbering in %s", name); - } - - assert(gen_switch == 3); - if (gen_switch == 3) { - const char *func_name = name; - if (prefix && strstr(func_name, prefix) == func_name) - func_name += strlen(prefix); - - fprintf(outfile, "DEFINE_GEN(gen_%s,void,(", func_name); - if (nb_args == 0) { - fprintf(outfile, "void"); - } else { - for(i = 0; i < nb_args; i++) { - if (i != 0) - fprintf(outfile, ", "); - fprintf(outfile, "long param%d", i + 1); - } - } - fprintf(outfile, "))\n"); - fprintf(outfile, "#ifdef DYNGEN_IMPL\n"); - fprintf(outfile, "#define HAVE_gen_%s\n", func_name); - fprintf(outfile, "{\n"); - print_code(outfile, name, p_start + start_offset - offset, copy_size); - - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - host_ulong offset = get_rel_offset(rel); - if (offset >= start_offset && - offset < start_offset + (p_end - p_start)) { - sym_name = get_rel_sym_name(rel); - if(!sym_name) - continue; - nd = sizeof(demangled_buf); - demangled = cxx_demangle(sym_name, demangled_buf, &nd, &status); - if (!status && demangled) - sym_name = demangled; - if (*sym_name && - !is_op_param(sym_name, NULL) && - !is_op_jmp(sym_name, NULL) && - !strstart(sym_name, ".LC", NULL)) - error("unexpected external symbol %s", sym_name); - } - } - - fprintf(outfile, " copy_block(%s_code, %d);\n", name, copy_size); - - /* emit code offset information */ - { - EXE_SYM *sym; - const char *sym_name, *p; - unsigned long val; - int n; - - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - sym_name = get_sym_name(sym); - if (strstart(sym_name, "__op_label", &p)) { - uint8_t *ptr; - unsigned long offset; - - /* test if the variable refers to a label inside - the code we are generating */ -#ifdef CONFIG_FORMAT_COFF - if (sym->st_shndx == text_shndx) { - ptr = sdata[coff_text_shndx]; - } else if (sym->st_shndx == data_shndx) { - ptr = sdata[coff_data_shndx]; - } else { - ptr = NULL; - } -#elif defined(CONFIG_FORMAT_MACH) - if(!sym->n_sect) - continue; - ptr = sdata[sym->n_sect-1]; -#else - ptr = sdata[sym->st_shndx]; -#endif - if (!ptr) - error("__op_labelN in invalid section"); - offset = sym->st_value; -#ifdef CONFIG_FORMAT_MACH - offset -= section_hdr[sym->n_sect-1].addr; -#endif - val = *(unsigned long *)(ptr + offset); -#ifdef ELF_USES_RELOCA - { - int reloc_shndx, nb_relocs1, j; - - /* try to find a matching relocation */ - reloc_shndx = find_reloc(sym->st_shndx); - if (reloc_shndx) { - nb_relocs1 = shdr[reloc_shndx].sh_size / - shdr[reloc_shndx].sh_entsize; - rel = (ELF_RELOC *)sdata[reloc_shndx]; - for(j = 0; j < nb_relocs1; j++) { - if (rel->r_offset == offset) { - val = rel->r_addend; - break; - } - rel++; - } - } - } -#endif - - if (val >= start_offset && val < start_offset + copy_size) { - n = strtol(p, NULL, 10); - fprintf(outfile, " label_offsets[%d] = %d + (code_ptr() - gen_code_buf);\n", n, val - start_offset); - } - } - } - } - - /* patch relocations */ - patch_relocations(outfile, name, size, start_offset, copy_size); - fprintf(outfile, " inc_code_ptr(%d);\n", copy_size); - fprintf(outfile, "}\n"); - fprintf(outfile, "#endif\n"); - fprintf(outfile, "\n"); - } -} - -void patch_relocations(FILE *outfile, const char *name, host_ulong size, host_ulong start_offset, int copy_size) -{ - EXE_RELOC *rel; - int i; -#if defined(HOST_I386) -#ifdef CONFIG_FORMAT_MACH - struct scattered_relocation_info *scarel; - char final_sym_name[256]; - const char *sym_name; - const char *p; - int slide, sslide; - - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - unsigned int offset, length, value = 0; - unsigned int type, pcrel, isym = 0; - unsigned int usesym = 0; - - if (R_SCATTERED & rel->r_address) { - scarel = (struct scattered_relocation_info*)rel; - offset = (unsigned int)scarel->r_address; - length = scarel->r_length; - pcrel = scarel->r_pcrel; - type = scarel->r_type; - value = scarel->r_value; - } - else { - value = isym = rel->r_symbolnum; - usesym = (rel->r_extern); - offset = rel->r_address; - length = rel->r_length; - pcrel = rel->r_pcrel; - type = rel->r_type; - } - - slide = offset - start_offset; - - if (!(offset >= start_offset && offset < start_offset + size)) - continue; /* not in our range */ - - sym_name = get_reloc_name(rel, &sslide); - - if (usesym && (symtab[isym].n_type & N_STAB)) - continue; /* don't handle STAB (debug sym) */ - - if (sym_name && is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", n, slide); - continue; /* Nothing more to do */ - } - - if (!sym_name) { - fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n", - name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type); - continue; /* dunno how to handle without final_sym_name */ - } - - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - - if (length != 2) - error("unsupported %d-bit relocation", 8 * (1 << length)); - - switch (type) { - case GENERIC_RELOC_VANILLA: - if (pcrel) { - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s - (long)(code_ptr() + %d) - 4;\n", - slide, final_sym_name, slide); - } - else { - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (%s + %d);\n", - slide, final_sym_name, sslide); - } - break; - default: - error("unsupported i386 relocation (%d)", type); - } - } -#else - char final_sym_name[256]; - const char *sym_name; - const char *p; - int type; - int addend; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = get_rel_sym_name(rel); - if (is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", - n, rel->r_offset - start_offset); - continue; - } - - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - addend = get32((uint32_t *)(text + rel->r_offset)); -#ifdef CONFIG_FORMAT_ELF - type = ELF32_R_TYPE(rel->r_info); - switch(type) { - case R_386_32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - rel->r_offset - start_offset, final_sym_name, addend); - break; - case R_386_PC32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s - (long)(code_ptr() + %d) + %d;\n", - rel->r_offset - start_offset, final_sym_name, rel->r_offset - start_offset, addend); - break; - default: - error("unsupported i386 relocation (%d)", type); - } -#elif defined(CONFIG_FORMAT_COFF) - { - char *temp_name; - int j; - EXE_SYM *sym; - temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx)); - if (!strcmp(temp_name, ".data")) { - for (j = 0, sym = symtab; j < nb_syms; j++, sym++) { - if (strstart(sym->st_name, sym_name, NULL)) { - addend -= sym->st_value; - } - } - } - } - type = rel->r_type; - switch(type) { - case DIR32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - rel->r_offset - start_offset, final_sym_name, addend); - break; - case DISP32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s - (long)(code_ptr() + %d) + %d -4;\n", - rel->r_offset - start_offset, final_sym_name, rel->r_offset - start_offset, addend); - break; - default: - error("unsupported i386 relocation (%d)", type); - } -#else -#error unsupport object format for HOST_I386 -#endif - } - } -#endif -#elif defined(HOST_X86_64) -#if defined(CONFIG_FORMAT_MACH) - char final_sym_name[256]; - const char *sym_name; - const char *p; - int slide, sslide; - int bytecount, bitlength; - int local16; - - for (i = 0, rel = relocs, local16 = 0; i < nb_relocs; i++, rel++) { - unsigned int isym, usesym, offset, length, pcrel, type; - int adjustment = 0; - - isym = rel->r_symbolnum; - usesym = rel->r_extern; - offset = rel->r_address; - length = rel->r_length; - pcrel = rel->r_pcrel; - type = rel->r_type; - - if (usesym && (symtab[isym].n_type & N_STAB)) - continue; /* don't handle STAB (debug sym) */ - - if (!(offset >= start_offset && offset < start_offset + size)) - continue; /* not in our range */ - - if (length > 3) - error("unsupported %d-bit relocation", 8 * (1 << length)); - - bytecount = (1 << length); - bitlength = 8 * bytecount; - slide = offset - start_offset; - - if (!usesym) { - // local reloc - sslide = get32((uint32_t *)(text + offset)) + rel->r_address + 4; - if ( literal16_sec_hdr - && sslide >= literal16_sec_hdr->addr - && sslide + 16 <= literal16_sec_hdr->addr + literal16_sec_hdr->size ) { - sprintf(final_sym_name, "literal16_%d", ++local16); - print_data(outfile, final_sym_name, literal16 + sslide - literal16_sec_hdr->addr, 16); - fprintf(outfile, " static uint8 *data_p_%d = NULL;\n", local16); - fprintf(outfile, " if (data_p_%d == NULL)\n", local16); - fprintf(outfile, " data_p_%d = copy_data(%s, %d);\n", local16, final_sym_name, 16); - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (int32_t)((long)data_p_%d - (long)(code_ptr() + %d + %d));\n", - slide, local16, slide, bytecount); - } else { - fprintf(outfile, "/* #warning relocation not handled in %s (section %d, offset 0x%x, length 0x%x, %s, type 0x%x) */\n", - name, isym, offset, length, pcrel ? "pcrel":"", type); - } - continue; - } - - sym_name = get_reloc_name(rel, &sslide); - if (!sym_name) { - error("external symbol not found in %s (section %d, offset 0x%x, length 0x%x, %s, type 0x%x\n", - name, isym, offset, length, pcrel ? "pcrel":"", type); - } - - if (is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", n, slide); - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = 0;\n", slide); - continue; /* Nothing more to do */ - } - - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - - switch (type) { - case X86_64_RELOC_SIGNED_1: // Signed displacement with a -1 added. - adjustment = -1; - type = X86_64_RELOC_SIGNED; - break; - case X86_64_RELOC_SIGNED_2: // Signed displacement with a -2 added. - adjustment = -2; - type = X86_64_RELOC_SIGNED; - break; - case X86_64_RELOC_SIGNED_4: // Signed displacement with a -4 added. - adjustment = -4; - type = X86_64_RELOC_SIGNED; - break; - } - - if (pcrel || is_op_gen_label(sym_name, &p)) { - switch (type) { - case X86_64_RELOC_UNSIGNED: // for absolute addresses - case X86_64_RELOC_SIGNED: // for signed 32-bit displacement - case X86_64_RELOC_BRANCH: // a CALL/JMP instruction with 32-bit displacement - fprintf(outfile, " *(uint%d_t *)(code_ptr() + %d) = (int%d_t)((long)%s - (long)(code_ptr() + %d + %d)) + %d;\n", - bitlength, slide, bitlength, final_sym_name, slide, bytecount, sslide + adjustment); - break; - default: - error("unsupported x86_64 relocation (%d) in %s\n", type, sym_name); - } - } else { - switch (type) { - case X86_64_RELOC_UNSIGNED: // for absolute addresses - fprintf(outfile, " *(uint%d_t *)(code_ptr() + %d) = (uint%d_t)%s + %d;\n", - bitlength, slide, bitlength, final_sym_name, sslide); - break; - case X86_64_RELOC_SIGNED: // for signed 32-bit displacement - fprintf(outfile, " *(uint%d_t *)(code_ptr() + %d) = (int%d_t)%s + %d;\n", - bitlength, slide, bitlength, final_sym_name, sslide + adjustment); - break; - default: - error("unsupported x86_64 relocation (%d) in %s\n", type, sym_name); - } - } - } -#elif defined (CONFIG_FORMAT_ELF) - char final_sym_name[256]; - const char *sym_name; - const char *p; - int type; - int addend; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - int slide; - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - if (is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", - n, rel->r_offset - start_offset); - continue; - } - - slide = rel->r_offset - start_offset; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - switch(type) { - case R_X86_64_64: - fprintf(outfile, " *(uintptr *)(code_ptr() + %d) = (uintptr)%s + %d;\n", slide, final_sym_name, addend); - break; - case R_X86_64_32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (uint32_t)%s + %d;\n", slide, final_sym_name, addend); - break; - case R_X86_64_32S: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (int32_t)%s + %d;\n", slide, final_sym_name, addend); - break; - case R_X86_64_PC32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s - (long)(code_ptr() + %d) + %d;\n", - slide, final_sym_name, slide, addend); - break; - default: - error("unsupported AMD64 relocation (%d)", type); - } - } - } -#else -#error unsupport object format for HOST_X86_64 -#endif -#elif defined(HOST_PPC) -#ifdef CONFIG_FORMAT_ELF - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - int slide; - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - if (is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", - n, rel->r_offset - start_offset); - continue; - } - - slide = rel->r_offset - start_offset; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - switch(type) { - case R_PPC_ADDR32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - slide, final_sym_name, addend); - break; - case R_PPC_ADDR16_LO: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d) = (%s + %d);\n", - slide, final_sym_name, addend); - break; - case R_PPC_ADDR16_HI: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d) = (%s + %d) >> 16;\n", - slide, final_sym_name, addend); - break; - case R_PPC_ADDR16_HA: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d) = (%s + %d + 0x8000) >> 16;\n", - slide, final_sym_name, addend); - break; - case R_PPC_REL24: - /* warning: must be at 32 MB distancy */ - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (*(uint32_t *)(code_ptr() + %d) & ~0x03fffffc) | ((%s - (long)(code_ptr() + %d) + %d) & 0x03fffffc);\n", - slide, slide, final_sym_name, slide, addend); - break; - default: - error("unsupported powerpc relocation (%d)", type); - } - } - } -#elif defined(CONFIG_FORMAT_MACH) - struct scattered_relocation_info *scarel; - char final_sym_name[256]; - const char *sym_name; - const char *p; - int slide, sslide; - - for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - unsigned int offset, length, value = 0; - unsigned int type, pcrel, isym = 0; - unsigned int usesym = 0; - - if(R_SCATTERED & rel->r_address) { - scarel = (struct scattered_relocation_info*)rel; - offset = (unsigned int)scarel->r_address; - length = scarel->r_length; - pcrel = scarel->r_pcrel; - type = scarel->r_type; - value = scarel->r_value; - } else { - value = isym = rel->r_symbolnum; - usesym = (rel->r_extern); - offset = rel->r_address; - length = rel->r_length; - pcrel = rel->r_pcrel; - type = rel->r_type; - } - - slide = offset - start_offset; - - if (!(offset >= start_offset && offset < start_offset + size)) - continue; /* not in our range */ - - sym_name = get_reloc_name(rel, &sslide); - - if(usesym && (symtab[isym].n_type & N_STAB)) - continue; /* don't handle STAB (debug sym) */ - - if (sym_name && is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", - n, slide); - continue; /* Nothing more to do */ - } - - if(!sym_name) - { - fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n", - name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type); - continue; /* dunno how to handle without final_sym_name */ - } - - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - - switch(type) { - case PPC_RELOC_BR24: - if (!is_op_param(sym_name, &p)) { - fprintf(outfile, "{\n"); - fprintf(outfile, " uint32_t imm = *(uint32_t *)(code_ptr() + %d) & 0x3fffffc;\n", slide); - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (*(uint32_t *)(code_ptr() + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)code_ptr()) + %d) & 0x03fffffc);\n", - slide, slide, final_sym_name, sslide ); - fprintf(outfile, "}\n"); - } else { - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (*(uint32_t *)(code_ptr() + %d) & ~0x03fffffc) | (((long)%s - (long)code_ptr() - %d) & 0x03fffffc);\n", - slide, slide, final_sym_name, slide); - } - break; - case PPC_RELOC_HI16: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d + 2) = (%s + %d) >> 16;\n", - slide, final_sym_name, sslide); - break; - case PPC_RELOC_LO16: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d + 2) = (%s + %d);\n", - slide, final_sym_name, sslide); - break; - case PPC_RELOC_HA16: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d + 2) = (%s + %d + 0x8000) >> 16;\n", - slide, final_sym_name, sslide); - break; - default: - error("unsupported powerpc relocation (%d)", type); - } - } -#else -#error unsupport object format -#endif -#elif defined(HOST_S390) - char final_sym_name[256]; - const char *sym_name; - int type; - int addend; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - int slide; - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF32_R_TYPE(rel->r_info); - slide = rel->r_offset - start_offset; - addend = rel->r_addend; - switch(type) { - case R_390_32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - slide, final_sym_name, addend); - break; - case R_390_16: - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d) = %s + %d;\n", - slide, final_sym_name, addend); - break; - case R_390_8: - fprintf(outfile, " *(uint8_t *)(code_ptr() + %d) = %s + %d;\n", - slide, final_sym_name, addend); - break; - default: - error("unsupported s390 relocation (%d)", type); - } - } - } -#elif defined(HOST_ALPHA) - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { - int type; - - type = ELF64_R_TYPE(rel->r_info); - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; - switch (type) { - case R_ALPHA_GPDISP: - /* The gp is just 32 bit, and never changes, so it's easiest to emit it - as an immediate instead of constructing it from the pv or ra. */ - fprintf(outfile, " immediate_ldah(code_ptr() + %ld, gp);\n", - rel->r_offset - start_offset); - fprintf(outfile, " immediate_lda(code_ptr() + %ld, gp);\n", - rel->r_offset - start_offset + rel->r_addend); - break; - case R_ALPHA_LITUSE: - /* jsr to literal hint. Could be used to optimize to bsr. Ignore for - now, since some called functions (libc) need pv to be set up. */ - break; - case R_ALPHA_HINT: - /* Branch target prediction hint. Ignore for now. Should be already - correct for in-function jumps. */ - break; - case R_ALPHA_LITERAL: - /* Load a literal from the GOT relative to the gp. Since there's only a - single gp, nothing is to be done. */ - break; - case R_ALPHA_GPRELHIGH: - /* Handle fake relocations against __op_PARAM symbol. Need to emit the - high part of the immediate value instead. Other symbols need no - special treatment. */ - if (is_op_param(sym_name, &p)) - fprintf(outfile, " immediate_ldah(code_ptr() + %ld, param%s);\n", - rel->r_offset - start_offset, p); - break; - case R_ALPHA_GPRELLOW: - if (is_op_param(sym_name, &p)) - fprintf(outfile, " immediate_lda(code_ptr() + %ld, param%s);\n", - rel->r_offset - start_offset, p); - break; - case R_ALPHA_BRSGP: - /* PC-relative jump. Tweak offset to skip the two instructions that try to - set up the gp from the pv. */ - fprintf(outfile, " fix_bsr(code_ptr() + %ld, (uint8_t *) &%s - (code_ptr() + %ld + 4) + 8);\n", - rel->r_offset - start_offset, sym_name, rel->r_offset - start_offset); - break; - default: - error("unsupported Alpha relocation (%d)", type); - } - } - } -#elif defined(HOST_IA64) - char final_sym_name[256]; - const char *sym_name; - int type; - int addend; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF64_R_TYPE(rel->r_info); - addend = rel->r_addend; - switch(type) { - case R_IA64_LTOFF22: - error("must implement R_IA64_LTOFF22 relocation"); - case R_IA64_PCREL21B: - error("must implement R_IA64_PCREL21B relocation"); - default: - error("unsupported ia64 relocation (%d)", type); - } - } - } -#elif defined(HOST_SPARC) - char final_sym_name[256]; - const char *sym_name; - const char *p; - int type; - int addend; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; - if (is_op_param(sym_name, &p)) { - snprintf(final_sym_name, sizeof(final_sym_name), "param%s", p); - } else { - if (sym_name[0] == '.') - snprintf(final_sym_name, sizeof(final_sym_name), - "(long)(&__dot_%s)", - sym_name + 1); - else - snprintf(final_sym_name, sizeof(final_sym_name), - "(long)(&%s)", sym_name); - } - type = ELF32_R_TYPE(rel->r_info); - addend = rel->r_addend; - switch(type) { - case R_SPARC_32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - rel->r_offset - start_offset, final_sym_name, addend); - break; - case R_SPARC_HI22: - fprintf(outfile, - " *(uint32_t *)(code_ptr() + %d) = " - "((*(uint32_t *)(code_ptr() + %d)) " - " & ~0x3fffff) " - " | (((%s + %d) >> 10) & 0x3fffff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - final_sym_name, addend); - break; - case R_SPARC_LO10: - fprintf(outfile, - " *(uint32_t *)(code_ptr() + %d) = " - "((*(uint32_t *)(code_ptr() + %d)) " - " & ~0x3ff) " - " | ((%s + %d) & 0x3ff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - final_sym_name, addend); - break; - case R_SPARC_WDISP30: - fprintf(outfile, - " *(uint32_t *)(code_ptr() + %d) = " - "((*(uint32_t *)(code_ptr() + %d)) " - " & ~0x3fffffff) " - " | ((((%s + %d) - (long)(code_ptr() + %d))>>2) " - " & 0x3fffffff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - final_sym_name, addend, - rel->r_offset - start_offset); - break; - default: - error("unsupported sparc relocation (%d)", type); - } - } - } -#elif defined(HOST_SPARC64) - char final_sym_name[256]; - const char *sym_name; - int type; - int addend; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF64_R_TYPE(rel->r_info); - addend = rel->r_addend; - switch(type) { - case R_SPARC_32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - rel->r_offset - start_offset, final_sym_name, addend); - break; - case R_SPARC_HI22: - fprintf(outfile, - " *(uint32_t *)(code_ptr() + %d) = " - "((*(uint32_t *)(code_ptr() + %d)) " - " & ~0x3fffff) " - " | (((%s + %d) >> 10) & 0x3fffff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - final_sym_name, addend); - break; - case R_SPARC_LO10: - fprintf(outfile, - " *(uint32_t *)(code_ptr() + %d) = " - "((*(uint32_t *)(code_ptr() + %d)) " - " & ~0x3ff) " - " | ((%s + %d) & 0x3ff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - final_sym_name, addend); - break; - case R_SPARC_WDISP30: - fprintf(outfile, - " *(uint32_t *)(code_ptr() + %d) = " - "((*(uint32_t *)(code_ptr() + %d)) " - " & ~0x3fffffff) " - " | ((((%s + %d) - (long)(code_ptr() + %d))>>2) " - " & 0x3fffffff);\n", - rel->r_offset - start_offset, - rel->r_offset - start_offset, - final_sym_name, addend, - rel->r_offset - start_offset); - break; - default: - error("unsupported sparc64 relocation (%d)", type); - } - } - } -#elif defined(HOST_ARM) - char final_sym_name[256]; - const char *sym_name; - int type; - int addend; - - arm_emit_ldr_info(final_sym_name, start_offset, outfile, p_start, p_end, - relocs, nb_relocs); - - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - /* the compiler leave some unnecessary references to the code */ - if (sym_name[0] == '\0') - continue; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = get32((uint32_t *)(text + rel->r_offset)); - switch(type) { - case R_ARM_ABS32: - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %d;\n", - rel->r_offset - start_offset, final_sym_name, addend); - break; - case R_ARM_PC24: - fprintf(outfile, " arm_reloc_pc24((uint32_t *)(code_ptr() + %d), 0x%x, %s);\n", - rel->r_offset - start_offset, addend, final_sym_name); - break; - default: - error("unsupported arm relocation (%d)", type); - } - } - } -#elif defined(HOST_M68K) - char final_sym_name[256]; - const char *sym_name; - int type; - int addend; - Elf32_Sym *sym; - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym = &(symtab[ELFW(R_SYM)(rel->r_info)]); - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELF32_R_TYPE(rel->r_info); - addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend; - switch(type) { - case R_68K_32: - fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ; - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s + %#x;\n", - rel->r_offset - start_offset, final_sym_name, addend ); - break; - case R_68K_PC32: - fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset); - fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = %s - (long)(code_ptr() + %#x) + %#x;\n", - rel->r_offset - start_offset, final_sym_name, rel->r_offset - start_offset, /*sym->st_value+*/ addend); - break; - default: - error("unsupported m68k relocation (%d)", type); - } - } - } -#elif defined(HOST_MIPS) - char final_sym_name[256]; - const char *sym_name; - int type; - int addend; - for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && - rel->r_offset < start_offset + copy_size) { - sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; - if (is_op_jmp(sym_name, &p)) { - int n; - n = strtol(p, NULL, 10); - /* __op_jmp relocations are done at - runtime to do translated block - chaining: the offset of the instruction - needs to be stored */ - fprintf(outfile, " jmp_addr[%d] = code_ptr() + %d;\n", - n, rel->r_offset - start_offset); - continue; - } - - get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); - type = ELFW(R_TYPE)(rel->r_info); - addend = rel->r_addend; - if (addend) - error("non zero addend (%d), deal with this", addend); - switch (type) { - case R_MIPS_HI16: - fprintf(outfile, " /* R_MIPS_HI16 reloc, offset %x */\n", rel->r_offset); - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d) = (uint16_t)((uint32_t)(%s)>>16);\n", - rel->r_offset - start_offset + 2, final_sym_name); - break; - case R_MIPS_LO16: - fprintf(outfile, " /* R_MIPS_LO16 reloc, offset %x */\n", rel->r_offset); - fprintf(outfile, " *(uint16_t *)(code_ptr() + %d) = (uint16_t)((uint32_t)(%s)&0xffff);\n", - rel->r_offset - start_offset + 2, final_sym_name); - break; - default: - error("unsupported MIPS relocation (%d)", type); - } - } - } -#else -#error unsupported CPU -#endif -} - -int gen_file(FILE *outfile, int out_type) -{ - int i; - EXE_SYM *sym; - - assert(out_type == OUT_GEN_OP_ALL); - if (out_type == OUT_GEN_OP_ALL) { - int status; - size_t nf, nd = 256; - char *demangled_name, *func_name; - if ((demangled_name = malloc(nd)) == NULL) - return -1; - if ((func_name = malloc(nf = nd)) == NULL) { - free(demangled_name); - return -1; - } - - fprintf(outfile, "#ifndef DEFINE_CST\n"); - fprintf(outfile, "#define DEFINE_CST(NAME, VALUE)\n"); - fprintf(outfile, "#endif\n"); - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { - const char *name; - name = get_sym_name(sym); - if (strstart(name, OP_PREFIX "execute", NULL)) { - /* skip Exception handlers */ - if (strchr(name, '.')) - continue; - strcpy(func_name, name); -#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) - if (sym->st_shndx != text_shndx) - error("invalid section for opcode (0x%x)", sym->st_shndx); -#endif - gen_code(func_name, NULL, sym->st_value, sym->st_size, outfile, 3, NULL); - } - else if (strstart(name, OP_PREFIX "exec_return_offset", NULL)) { - host_ulong *long_p; -#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) - if (sym->st_shndx != data_shndx) - error("invalid section for data (0x%x)", sym->st_shndx); -#endif - if (data == NULL) - error("no .data section found"); -#ifdef CONFIG_FORMAT_MACH - fprintf(outfile, "DEFINE_CST(%s,0x%xL)\n\n", name, *((host_ulong *)(data + sym->st_value - data_sec_hdr->addr))); -#else - fprintf(outfile, "DEFINE_CST(%s,0x%xL)\n\n", name, *((host_ulong *)(data + sym->st_value))); -#endif - } - else if (strstart(name, OP_PREFIX "invoke", NULL)) { - const char *prefix = "helper_"; - strcpy(func_name, prefix); - strcat(func_name, name); -#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) - if (sym->st_shndx != text_shndx) - error("invalid section for opcode (0x%x)", sym->st_shndx); -#endif - gen_code(func_name, NULL, sym->st_value, sym->st_size, outfile, 3, prefix); - } - else { - /* demangle C++ symbols */ - nd = 256; - demangled_name = cxx_demangle(name, demangled_name, &nd, &status); - if (status == 0 && strstart(demangled_name, OP_PREFIX, NULL)) { - /* get real function name */ - char *p = strchr(demangled_name, '('); - if (p && !strstart(p, "()::label", NULL)) { - int func_name_length = p - demangled_name; - if (nd > nf) { - char *new_func_name; - nf = nd; - if ((new_func_name = realloc(func_name, nf)) == NULL) { - free(func_name); - return -1; - } - func_name = new_func_name; - } - strncpy(func_name, demangled_name, func_name_length); - func_name[func_name_length] = '\0'; - /* emit code generator */ -#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) - if (sym->st_shndx != text_shndx) - error("invalid section for opcode (%s:0x%x)", name, sym->st_shndx); -#endif - gen_code(func_name, demangled_name, sym->st_value, sym->st_size, outfile, 3, NULL); - } - } - } - } - fprintf(outfile, "#undef DEFINE_CST\n"); - fprintf(outfile, "#undef DEFINE_GEN\n"); - - free(func_name); - free(demangled_name); - } - - return 0; -} - -void usage(void) -{ - printf("dyngen (c) 2003-2004 Fabrice Bellard\n" - "usage: dyngen [-o outfile] objfile\n" - "Generate a dynamic code generator from an object file\n" - ); - exit(1); -} - -int main(int argc, char **argv) -{ - int c, out_type; - const char *filename, *outfilename; - FILE *outfile; - - outfilename = "out.c"; - out_type = OUT_GEN_OP_ALL; - for(;;) { - c = getopt(argc, argv, "ho:"); - if (c == -1) - break; - switch(c) { - case 'h': - usage(); - break; - case 'o': - outfilename = optarg; - break; - } - } - if (optind >= argc) - usage(); - filename = argv[optind]; - outfile = fopen(outfilename, "w"); - if (!outfile) - error("could not open '%s'", outfilename); - - load_object(filename, outfile); - gen_file(outfile, out_type); - fclose(outfile); - return 0; -} - -/* - Local variables: - tab-width: 4 - indent-tabs-mode: nil - End: - */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp deleted file mode 100644 index e99e5963..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * jit-cache.cpp - Translation cache management - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "vm_alloc.h" -#include "cpu/jit/jit-cache.hpp" - -#define DEBUG 0 -#include "debug.h" - -// Default cache size in KB -#if defined(__alpha__) -const int JIT_CACHE_SIZE = 2 * 1024; -#elif defined(__powerpc__) || defined(__ppc__) -const int JIT_CACHE_SIZE = 4 * 1024; -#else -const int JIT_CACHE_SIZE = 8 * 1024; -#endif -const int JIT_CACHE_SIZE_GUARD = 4096; - -basic_jit_cache::basic_jit_cache() - : cache_size(0), tcode_start(NULL), code_start(NULL), code_p(NULL), code_end(NULL), data(NULL) -{ -} - -basic_jit_cache::~basic_jit_cache() -{ - kill_translation_cache(); - - // Release data pool - data_chunk_t *p = data; - while (p) { - data_chunk_t *d = p; - p = p->next; - D(bug("basic_jit_cache: Release data pool %p (%d KB)\n", d, d->size / 1024)); - vm_release(d, d->size); - } -} - -bool -basic_jit_cache::init_translation_cache(uint32 size) -{ - size *= 1024; - - // Round up translation cache size to 16 KB boundaries - const uint32 roundup = 16 * 1024; - cache_size = (size + JIT_CACHE_SIZE_GUARD + roundup - 1) & -roundup; - assert(cache_size > 0); - - tcode_start = (uint8 *)vm_acquire(cache_size, VM_MAP_PRIVATE | VM_MAP_32BIT); - if (tcode_start == VM_MAP_FAILED) { - tcode_start = NULL; - return false; - } - - if (vm_protect(tcode_start, cache_size, - VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { - vm_release(tcode_start, cache_size); - tcode_start = NULL; - return false; - } - - done: - D(bug("basic_jit_cache: Translation cache: %d KB at %p\n", cache_size / 1024, tcode_start)); - code_start = tcode_start; - code_p = code_start; - code_end = code_p + size; - return true; -} - -void -basic_jit_cache::kill_translation_cache() -{ - if (tcode_start) { - D(bug("basic_jit_cache: Release translation cache\n")); - vm_release(tcode_start, cache_size); - cache_size = 0; - tcode_start = NULL; - } -} - -bool -basic_jit_cache::initialize(void) -{ - if (cache_size == 0) - set_cache_size(JIT_CACHE_SIZE); - return tcode_start && cache_size; -} - -void -basic_jit_cache::set_cache_size(uint32 size) -{ - kill_translation_cache(); - if (size) - init_translation_cache(size); -} - -uint8 * -basic_jit_cache::copy_data(const uint8 *block, uint32 size) -{ - const int ALIGN = 16; - uint8 *ptr; - - if (data && (data->offs + size) < data->size) - ptr = (uint8 *)data + data->offs; - else { - // No free space left, allocate a new chunk - uint32 to_alloc = sizeof(*data) + size + ALIGN; - uint32 page_size = vm_get_page_size(); - to_alloc = (to_alloc + page_size - 1) & -page_size; - - D(bug("basic_jit_cache: Allocate data pool (%d KB)\n", to_alloc / 1024)); - ptr = (uint8 *)vm_acquire(to_alloc, VM_MAP_PRIVATE | VM_MAP_32BIT); - if (ptr == VM_MAP_FAILED) { - fprintf(stderr, "FATAL: Could not allocate data pool!\n"); - abort(); - } - - data_chunk_t *dcp = (data_chunk_t *)ptr; - dcp->size = to_alloc; - dcp->offs = (sizeof(*data) + ALIGN - 1) & -ALIGN; - dcp->next = data; - data = dcp; - - ptr += dcp->offs; - } - - memcpy(ptr, block, size); - data->offs += (size + ALIGN - 1) & -ALIGN; - D(bug("basic_jit_cache: DATA %p, %d bytes [data=%p, offs=%u]\n", ptr, size, data, data->offs)); - return ptr; -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp deleted file mode 100644 index 201841d8..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * jit-cache.hpp - Translation cache management - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_CACHE_H -#define JIT_CACHE_H - -#define _JIT_HEADER jit-target-cache.hpp -#include "cpu/jit/jit-target-dispatch.h" - -/** - * Basic translation cache - **/ - -class basic_jit_cache -{ - // Translation cache (allocated base, current pointer, end pointer) - uint32 cache_size; - uint8 *tcode_start; - uint8 *code_start; - uint8 *code_p; - uint8 *code_end; - - // Data pool (32-bit addressable) - struct data_chunk_t { - uint32 size; - uint32 offs; - data_chunk_t *next; - }; - data_chunk_t *data; - -protected: - - // Initialize translation cache - bool init_translation_cache(uint32 size); - void kill_translation_cache(); - - // Initialize user code start - void set_code_start(uint8 *ptr); - - // Increase/set/get current position - void inc_code_ptr(int offset) { code_p += offset; } - void set_code_ptr(uint8 *ptr) { code_p = ptr; } -public: - uint8 *code_ptr() const { return code_p; } - -public: - - // Default constructor & destructor (use default JIT_CACHE_SIZE) - basic_jit_cache(); - ~basic_jit_cache(); - - bool initialize(void); - void set_cache_size(uint32 size); - - // Invalidate translation cache - void invalidate_cache(); - bool full_translation_cache() const - { return code_p >= code_end; } - - // Emit code to translation cache - template< typename T > - void emit_generic(T v); - void emit_8(uint8 v) { emit_generic(v); } - void emit_16(uint16 v) { emit_generic(v); } - void emit_32(uint32 v) { emit_generic(v); } - void emit_64(uint64 v) { emit_generic(v); } - void emit_ptr(uintptr v) { emit_generic(v); } - void copy_block(const uint8 *block, uint32 size); - void emit_block(const uint8 *block, uint32 size); - - // Emit data to constant pool - uint8 *copy_data(const uint8 *block, uint32 size); -}; - -inline void -basic_jit_cache::set_code_start(uint8 *ptr) -{ - assert(ptr >= tcode_start && ptr < code_end); - code_start = ptr; -} - -inline void -basic_jit_cache::invalidate_cache() -{ - code_p = code_start; -} - -template< class T > -inline void -basic_jit_cache::emit_generic(T v) -{ - *((T *)code_ptr()) = v; - inc_code_ptr(sizeof(T)); -} - -inline void -basic_jit_cache::copy_block(const uint8 *block, uint32 size) -{ - memcpy(code_ptr(), block, size); -} - -inline void -basic_jit_cache::emit_block(const uint8 *block, uint32 size) -{ - copy_block(block, size); - inc_code_ptr(size); -} - -#endif /* JIT_CACHE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-codegen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-codegen.hpp deleted file mode 100644 index 7d428a4c..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-codegen.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * jit-codegen.hpp - Generic code generator - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_CODEGEN_H -#define JIT_CODEGEN_H - -#include "cpu/jit/jit-cache.hpp" - -#if defined(__i386__) -#include "cpu/jit/x86/jit-target-codegen.hpp" -typedef x86_codegen jit_codegen; -#elif defined(__x86_64__) -#include "cpu/jit/amd64/jit-target-codegen.hpp" -typedef amd64_codegen jit_codegen; -#else -struct jit_codegen - : public basic_jit_cache -{ -}; -#endif - -#endif /* JIT_CODEGEN_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-config.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-config.hpp deleted file mode 100644 index 44fd2458..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-config.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * jit-config.hpp - JIT config utils - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_CONFIG_H -#define JIT_CONFIG_H - -/** - * ENABLE_DYNGEN - * - * Define to enable the portable "JIT1" engine based on code - * inlining technique as implemented in QEMU. - **/ - -#ifndef ENABLE_DYNGEN -#define ENABLE_DYNGEN 0 -#endif - -/** - * DYNGEN_ASM_OPTS - * - * Define to permit host inline asm optimizations. This is - * particularly useful to compute emulated condition code - * registers. - **/ - -#if ENABLE_DYNGEN -#ifndef DYNGEN_ASM_OPTS -#define DYNGEN_ASM_OPTS 0 -#endif -#endif - -/** - * DYNGEN_DIRECT_BLOCK_CHAINING - * - * Define to enable direct block chaining on platforms supporting - * that feature. e.g. PowerPC. - **/ - -#if ENABLE_DYNGEN -#ifndef DYNGEN_DIRECT_BLOCK_CHAINING -#define DYNGEN_DIRECT_BLOCK_CHAINING 1 -#endif -#endif - -#endif /* JIT_CONFIG_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-target-dispatch.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-target-dispatch.h deleted file mode 100644 index f1ece399..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-target-dispatch.h +++ /dev/null @@ -1,70 +0,0 @@ - -/* - * jit-target-dispatch.h - JIT headers dispatcher - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Undefine some built-ins */ -#ifdef i386 -#undef i386 -#define _jit_defined_i386 -#endif -#ifdef amd64 -#undef amd64 -#define _jit_defined_amd64 -#endif -#ifdef mips -#undef mips -#define _jit_defined_mips -#endif - -/* Dispatch arch dependent header */ -#define _JIT_CONCAT4(a,b,c,d) a##b##c##d -#if defined(__GNUC__) -#define _JIT_MAKE_HEADER(arch,header) -#else -#define _JIT_MAKE_HEADER(arch,header) _JIT_CONCAT4() -#endif -#if defined(__x86_64__) -#include _JIT_MAKE_HEADER(amd64,_JIT_HEADER) -#elif defined(__i386__) -#include _JIT_MAKE_HEADER(x86,_JIT_HEADER) -#elif defined(__powerpc__) || defined(__ppc__) -#include _JIT_MAKE_HEADER(ppc,_JIT_HEADER) -#elif defined(__mips__) || (defined __sgi && defined __mips) -#include _JIT_MAKE_HEADER(mips,_JIT_HEADER) -#else -#error "Unknown architecture, please submit bug report" -#endif -#undef _JIT_CONCAT4 -#undef _JIT_MAKE_HEADER -#undef _JIT_HEADER - -/* Redefine built-ins */ -#ifdef _jit_defined_i386 -#undef _jit_defined_i386 -#define i386 1 -#endif -#ifdef _jit_defined_amd64 -#undef _jit_defined_amd64 -#define amd64 1 -#endif -#ifdef _jit_defined_mips -#undef _jit_defined_mips -#define mips 1 -#endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/mips/dyngen-target-exec.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/mips/dyngen-target-exec.h deleted file mode 100644 index 2c2140de..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/mips/dyngen-target-exec.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * dyngen defines for micro operation code - * - * Copyright (c) 2003-2004-2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DYNGEN_TARGET_EXEC_H -#define DYNGEN_TARGET_EXEC_H - -enum { - /* callee save registers */ -#define AREG0 "s0" - AREG0_ID = 16, - -#define AREG1 "s1" - AREG1_ID = 17, - -#define AREG2 "s2" - AREG2_ID = 18, - -#define AREG3 "s3" - AREG3_ID = 19, - -#define AREG4 "s4" - AREG4_ID = 20, - -#define AREG5 "s5" - AREG5_ID = 21, -}; - -#endif /* DYNGEN_TARGET_EXEC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/mips/jit-target-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/mips/jit-target-cache.hpp deleted file mode 100644 index 8e8ca3b8..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/mips/jit-target-cache.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * jit-target-cache.hpp - Target specific code to invalidate cache - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_TARGET_CACHE_H -#define JIT_TARGET_CACHE_H - -#if defined __sgi -#include -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - cacheflush((void *)start, stop - start, BCACHE); -} -#elif defined __GNUC__ -#error "FIXME: implement assembly code for code cache invalidation" -#endif - -#endif /* JIT_TARGET_CACHE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/dyngen-target-exec.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/dyngen-target-exec.h deleted file mode 100644 index e139e4c9..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/dyngen-target-exec.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * dyngen defines for micro operation code - * - * Copyright (c) 2003-2004-2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DYNGEN_TARGET_EXEC_H -#define DYNGEN_TARGET_EXEC_H - -enum { -#define AREG0 "r27" - AREG0_ID = 27, - -#define AREG1 "r24" - AREG1_ID = 24, - -#define AREG2 "r25" - AREG2_ID = 25, - -#define AREG3 "r26" - AREG3_ID = 26, - -#define AREG4 "r16" - AREG4_ID = 16, - -#define AREG5 "r17" - AREG5_ID = 17, - -#define AREG6 "r18" - AREG6_ID = 18, - -#define AREG7 "r19" - AREG7_ID = 19, - -#define AREG8 "r20" - AREG8_ID = 20, - -#define AREG9 "r21" - AREG9_ID = 21, - -#define AREG10 "r22" - AREG10_ID = 22, - -#define AREG11 "r23" - AREG11_ID = 23, - -#define FREG0 "f1" - FREG0_ID = 1, - -#define FREG1 "f2" - FREG1_ID = 2, - -#define FREG2 "f3" - FREG2_ID = 3, -}; - -#endif /* DYNGEN_TARGET_EXEC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/jit-target-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/jit-target-cache.hpp deleted file mode 100644 index 8a83eb3d..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/ppc/jit-target-cache.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * jit-target-cache.hpp - Target specific code to invalidate cache - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_TARGET_CACHE_H -#define JIT_TARGET_CACHE_H - -static inline void flush_icache_range(unsigned long start, unsigned long stop) -{ - const int MIN_CACHE_LINE_SIZE = 8; /* conservative value */ - - unsigned long p; - - p = start & ~(MIN_CACHE_LINE_SIZE - 1); - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); - - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - asm volatile ("isync" : : : "memory"); -} - -#endif /* JIT_TARGET_CACHE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/codegen_x86.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/codegen_x86.h deleted file mode 120000 index 110f4bd0..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/codegen_x86.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../../BasiliskII/src/uae_cpu/compiler/codegen_x86.h \ No newline at end of file diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/dyngen-target-exec.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/dyngen-target-exec.h deleted file mode 100644 index 4480345e..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/dyngen-target-exec.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * dyngen defines for micro operation code - * - * Copyright (c) 2003-2004-2004 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DYNGEN_TARGET_EXEC_H -#define DYNGEN_TARGET_EXEC_H - -enum { - /* callee save registers */ -#define AREG0 "ebp" - AREG0_ID = 5, - -#define AREG1 "ebx" - AREG1_ID = 3, - -#define AREG2 "esi" - AREG2_ID = 6, - -#define AREG3 "edi" - AREG3_ID = 7, - - // NOTE: the following XMM registers definitions require to build - // *-dyngen-ops.cpp with -ffixed-xmmN - - /* vector registers */ -#define VREG0 "xmm4" - VREG0_ID = 4, - -#define VREG1 "xmm5" - VREG1_ID = 5, - -#define VREG2 "xmm6" - VREG2_ID = 6, - -#define VREG3 "xmm7" - VREG3_ID = 7, -}; - -#endif /* DYNGEN_TARGET_EXEC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-cache.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-cache.hpp deleted file mode 100644 index f411d3bb..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-cache.hpp +++ /dev/null @@ -1 +0,0 @@ -#include "cpu/jit/dummy/jit-target-cache.hpp" diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-codegen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-codegen.hpp deleted file mode 100644 index 0643de90..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/x86/jit-target-codegen.hpp +++ /dev/null @@ -1,760 +0,0 @@ -/* - * jit-target-codegen.hpp - Target specific code generator - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef JIT_X86_CODEGEN_H -#define JIT_X86_CODEGEN_H - -// XXX drop (Basilisk II, lightning) => merge into here -#define X86_FLAT_REGISTERS 0 -#define X86_OPTIMIZE_ALU 1 -#define X86_OPTIMIZE_ROTSHI 1 -#include "cpu/jit/x86/codegen_x86.h" - -#if defined(__GNUC__) -#define x86_emit_failure(MSG) gen_failure(MSG, __FILE__, __LINE__, __FUNCTION__) -#else -#define x86_emit_failure(MSG) gen_failure(MSG, __FILE__, __LINE__) -#endif -#define x86_code_pointer __my_cached_code_ptr -#define x86_get_target() x86_code_pointer -#define x86_emit_byte(v) (void)(*x86_code_pointer++ = (v)) -#define x86_emit_word(v) (*((uint16 *)x86_code_pointer) = (v), (void)(x86_code_pointer += 2)) -#define x86_emit_long(v) (*((uint32 *)x86_code_pointer) = (v), (void)(x86_code_pointer += 4)) -#define x86_emit_quad(v) (*((uint64 *)x86_code_pointer) = (v), (void)(x86_code_pointer += 8)) - -struct x86_immediate_operand { - const int32 value; - - explicit x86_immediate_operand(int32 imm) - : value(imm) - { } -}; - -struct x86_memory_operand { - const int32 MD; - const int8 MB; - const int8 MI; - const int8 MS; - - x86_memory_operand(int32 d, int b, int i = X86_NOREG, int s = 1) - : MD(d), MB(b), MI(i), MS(s) - { } -}; - -class x86_codegen - : public basic_jit_cache -{ -protected: - - void gen_failure(const char *msg, const char *file, int line, const char *fn = NULL); - -public: - - /* XXX this avoids emit_XXX() functions because GCC cannot - optimize out intermediate code_ptr() updates */ -#define GEN_CODE(CODE) do { \ - uint8 *x86_code_pointer = code_ptr(); \ - CODE; \ - set_code_ptr(x86_code_pointer); \ -} while (0) - -public: - - void gen_insn(int type, int op, int s, int d); - void gen_insn(int type, int op, x86_memory_operand const & mem, int d); - -private: - -#define DEFINE_OP(SZ, SFX) \ - void gen_arith_##SZ(int op, int s, int d) \ - { GEN_CODE(_ALU##SFX##rr(op, s, d)); } \ - void gen_arith_##SZ(int op, x86_memory_operand const & mem, int d) \ - { GEN_CODE(_ALU##SFX##mr(op, mem.MD, mem.MB, mem.MI, mem.MS, d)); } \ - void gen_arith_##SZ(int op, int s, x86_memory_operand const & mem) \ - { GEN_CODE(_ALU##SFX##rm(op, s, mem.MD, mem.MB, mem.MI, mem.MS)); } \ - void gen_arith_##SZ(int op, x86_immediate_operand const & imm, int d) \ - { GEN_CODE(_ALU##SFX##ir(op, imm.value, d)); } \ - void gen_arith_##SZ(int op, x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { GEN_CODE(_ALU##SFX##im(op, imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } - - DEFINE_OP(8, B); - DEFINE_OP(16, W); - DEFINE_OP(32, L); - -#undef DEFINE_OP - -public: - -#define DEFINE_OP_SZ(SZ, NAME, OP) \ - void gen_##NAME##_##SZ(int s, int d) \ - { gen_arith_##SZ(X86_##OP, s, d); } \ - void gen_##NAME##_##SZ(x86_memory_operand const & mem, int d) \ - { gen_arith_##SZ(X86_##OP, mem, d); } \ - void gen_##NAME##_##SZ(int s, x86_memory_operand const & mem) \ - { gen_arith_##SZ(X86_##OP, s, mem); } \ - void gen_##NAME##_##SZ(x86_immediate_operand const & imm, int d) \ - { gen_arith_##SZ(X86_##OP, imm, d); } \ - void gen_##NAME##_##SZ(x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { gen_arith_##SZ(X86_##OP, imm, mem); } - -#define DEFINE_OP(NAME, OP) \ - DEFINE_OP_SZ(8, NAME, OP) \ - DEFINE_OP_SZ(16, NAME, OP) \ - DEFINE_OP_SZ(32, NAME, OP) - - DEFINE_OP(add, ADD); - DEFINE_OP(sub, SUB); - DEFINE_OP(adc, ADC); - DEFINE_OP(sbb, SBB); - DEFINE_OP(cmp, CMP); - DEFINE_OP(or, OR); - DEFINE_OP(xor, XOR); - DEFINE_OP(and, AND); - -#undef DEFINE_OP -#undef DEFINE_OP_SZ - -private: - -#define DEFINE_OP(SZ, SFX) \ - void gen_rotshi_##SZ(int op, int s, int d) \ - { GEN_CODE(_ROTSHI##SFX##rr(op, s, d)); } \ - void gen_rotshi_##SZ(int op, int s, x86_memory_operand const & mem) \ - { GEN_CODE(_ROTSHI##SFX##rm(op, s, mem.MD, mem.MB, mem.MI, mem.MS)); } \ - void gen_rotshi_##SZ(int op, x86_immediate_operand const & imm, int d) \ - { GEN_CODE(_ROTSHI##SFX##ir(op, imm.value, d)); } \ - void gen_rotshi_##SZ(int op, x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { GEN_CODE(_ROTSHI##SFX##im(op, imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } - - DEFINE_OP(8, B); - DEFINE_OP(16, W); - DEFINE_OP(32, L); - -#undef DEFINE_OP - -public: - -#define DEFINE_OP_SZ(SZ, NAME, OP) \ - void gen_##NAME##_##SZ(int s, int d) \ - { gen_rotshi_##SZ(X86_##OP, s, d); } \ - void gen_##NAME##_##SZ(int s, x86_memory_operand const & mem) \ - { gen_rotshi_##SZ(X86_##OP, s, mem); } \ - void gen_##NAME##_##SZ(x86_immediate_operand const & imm, int d) \ - { gen_rotshi_##SZ(X86_##OP, imm, d); } \ - void gen_##NAME##_##SZ(x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { gen_rotshi_##SZ(X86_##OP, imm, mem); } - -#define DEFINE_OP(NAME, OP) \ - DEFINE_OP_SZ(8, NAME, OP) \ - DEFINE_OP_SZ(16, NAME, OP) \ - DEFINE_OP_SZ(32, NAME, OP) - - DEFINE_OP(rol, ROL); - DEFINE_OP(ror, ROR); - DEFINE_OP(rcl, RCL); - DEFINE_OP(rcr, RCR); - DEFINE_OP(shl, SHL); - DEFINE_OP(shr, SHR); - DEFINE_OP(sar, SAR); - -#undef DEFINE_OP -#undef DEFINE_OP_SZ - -private: - -#define DEFINE_OP(SZ, SFX) \ - void gen_bitop_##SZ(int op, int s, int d) \ - { GEN_CODE(_BT##SFX##rr(op, s, d)); } \ - void gen_bitop_##SZ(int op, int s, x86_memory_operand const & mem) \ - { GEN_CODE(_BT##SFX##rm(op, s, mem.MD, mem.MB, mem.MI, mem.MS)); } \ - void gen_bitop_##SZ(int op, x86_immediate_operand const & imm, int d) \ - { GEN_CODE(_BT##SFX##ir(op, imm.value, d)); } \ - void gen_bitop_##SZ(int op, x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { GEN_CODE(_BT##SFX##im(op, imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } - - DEFINE_OP(16, W); - DEFINE_OP(32, L); - -#undef DEFINE_OP - -public: - -#define DEFINE_OP_SZ(SZ, NAME, OP) \ - void gen_##NAME##_##SZ(int s, int d) \ - { gen_bitop_##SZ(X86_##OP, s, d); } \ - void gen_##NAME##_##SZ(int s, x86_memory_operand const & mem) \ - { gen_bitop_##SZ(X86_##OP, s, mem); } \ - void gen_##NAME##_##SZ(x86_immediate_operand const & imm, int d) \ - { gen_bitop_##SZ(X86_##OP, imm, d); } \ - void gen_##NAME##_##SZ(x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { gen_bitop_##SZ(X86_##OP, imm, mem); } - -#define DEFINE_OP(NAME, OP) \ - DEFINE_OP_SZ(16, NAME, OP) \ - DEFINE_OP_SZ(32, NAME, OP) - - DEFINE_OP(bt, BT); - DEFINE_OP(btc, BTC); - DEFINE_OP(bts, BTS); - DEFINE_OP(btr, BTR); - -#undef DEFINE_OP -#undef DEFINE_OP_SZ - -public: - -#define DEFINE_OP(SZ, SFX) \ - void gen_mov_##SZ(int s, int d) \ - { GEN_CODE(MOV##SFX##rr(s, d)); } \ - void gen_mov_##SZ(x86_memory_operand const & mem, int d) \ - { GEN_CODE(MOV##SFX##mr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } \ - void gen_mov_##SZ(int s, x86_memory_operand const & mem) \ - { GEN_CODE(MOV##SFX##rm(s, mem.MD, mem.MB, mem.MI, mem.MS)); } \ - void gen_mov_##SZ(x86_immediate_operand const & imm, int d) \ - { GEN_CODE(MOV##SFX##ir(imm.value, d)); } \ - void gen_mov_##SZ(x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { GEN_CODE(MOV##SFX##im(imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } \ - void gen_test_##SZ(int s, int d) \ - { GEN_CODE(TEST##SFX##rr(s, d)); } \ - void gen_test_##SZ(int s, x86_memory_operand const & mem) \ - { GEN_CODE(TEST##SFX##rm(s, mem.MD, mem.MB, mem.MI, mem.MS)); } \ - void gen_test_##SZ(x86_immediate_operand const & imm, int d) \ - { GEN_CODE(TEST##SFX##ir(imm.value, d)); } \ - void gen_test_##SZ(x86_immediate_operand const & imm, x86_memory_operand const & mem) \ - { GEN_CODE(TEST##SFX##im(imm.value, mem.MD, mem.MB, mem.MI, mem.MS)); } - - DEFINE_OP(8, B); - DEFINE_OP(16, W); - DEFINE_OP(32, L); - -#undef DEFINE_OP - -private: - - void gen_unary_8(int op, int r) - { GEN_CODE(_UNARYBr(op, r)); } - void gen_unary_8(int op, x86_memory_operand const & mem) - { GEN_CODE(_UNARYBm(op, mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_unary_16(int op, int r) - { GEN_CODE(_UNARYWr(op, r)); } - void gen_unary_16(int op, x86_memory_operand const & mem) - { GEN_CODE(_UNARYWm(op, mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_unary_32(int op, int r) - { GEN_CODE(_UNARYLr(op, r)); } - void gen_unary_32(int op, x86_memory_operand const & mem) - { GEN_CODE(_UNARYLm(op, mem.MD, mem.MB, mem.MI, mem.MS)); } - -public: - -#define DEFINE_OP_SZ(SZ, NAME, OP) \ - void gen_##NAME##_##SZ(int r) \ - { gen_unary_##SZ(X86_##OP, r); } \ - void gen_##NAME##_##SZ(x86_memory_operand const & mem) \ - { gen_unary_##SZ(X86_##OP, mem); } - -#define DEFINE_OP(NAME, OP) \ - DEFINE_OP_SZ(8, NAME, OP) \ - DEFINE_OP_SZ(16, NAME, OP) \ - DEFINE_OP_SZ(32, NAME, OP) - - DEFINE_OP(not, NOT); - DEFINE_OP(neg, NEG); - DEFINE_OP(mul, MUL); - DEFINE_OP(div, DIV); - DEFINE_OP(imul, IMUL); - DEFINE_OP(idiv, IDIV); - -#undef DEFINE_OP -#undef DEFINE_OP_SZ - - void gen_imul_16(int s, int d) - { GEN_CODE(IMULWrr(s, d)); } - void gen_imul_16(x86_memory_operand const & mem, int d) - { GEN_CODE(IMULWmr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_imul_16(int s, x86_immediate_operand const & imm, int d) - { GEN_CODE(IMULWirr(imm.value, s, d)); } - void gen_imul_16(x86_memory_operand const & mem, x86_immediate_operand const & imm, int d) - { GEN_CODE(IMULWimr(imm.value, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_imul_32(int s, int d) - { GEN_CODE(IMULLrr(s, d)); } - void gen_imul_32(x86_memory_operand const & mem, int d) - { GEN_CODE(IMULLmr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_imul_32(x86_immediate_operand const & imm, int d) - { GEN_CODE(IMULLir(imm.value, d)); } - void gen_imul_32(x86_immediate_operand const & imm, int s, int d) - { GEN_CODE(IMULLirr(imm.value, s, d)); } - void gen_imul_32(x86_memory_operand const & mem, x86_immediate_operand const & imm, int d) - { GEN_CODE(IMULLimr(imm.value, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - -public: - - void gen_call(x86_immediate_operand const & target) - { GEN_CODE(CALLm(target.value)); } - void gen_call(int r) - { GEN_CODE(CALLsr(r)); } - void gen_call(x86_memory_operand const & mem) - { GEN_CODE(CALLsm(mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_jmp(x86_immediate_operand const & target) - { GEN_CODE(JMPm(target.value)); } - void gen_jmp(int r) - { GEN_CODE(JMPsr(r)); } - void gen_jmp(x86_memory_operand const & mem) - { GEN_CODE(JMPsm(mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_jcc(int cc, x86_immediate_operand const & target) - { GEN_CODE(JCCim(cc, target.value)); } - void gen_jcc_offset(int cc, x86_immediate_operand const & offset) - { GEN_CODE(JCCii(cc, offset.value)); } - void gen_setcc(int cc, int r) - { GEN_CODE(SETCCir(cc, r)); } - void gen_setcc(int cc, x86_memory_operand const & mem) - { GEN_CODE(SETCCim(cc, mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_cmov_16(int cc, int r, int d) - { GEN_CODE(CMOVWrr(cc, r, d)); } - void gen_cmov_16(int cc, x86_memory_operand const & mem, int d) - { GEN_CODE(CMOVWmr(cc, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_cmov_32(int cc, int r, int d) - { GEN_CODE(CMOVLrr(cc, r, d)); } - void gen_cmov_32(int cc, x86_memory_operand const & mem, int d) - { GEN_CODE(CMOVLmr(cc, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - -public: - - void gen_push(int r) - { GEN_CODE(PUSHLr(r)); } - void gen_push(x86_memory_operand const & mem) - { GEN_CODE(PUSHLm(mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_pop(int r) - { GEN_CODE(POPLr(r)); } - void gen_pop(x86_memory_operand const & mem) - { GEN_CODE(POPLm(mem.MD, mem.MB, mem.MI, mem.MS)); } - void gen_pusha(void) - { GEN_CODE(PUSHA()); } - void gen_popa(void) - { GEN_CODE(POPA()); } - void gen_pushf(void) - { GEN_CODE(PUSHF()); } - void gen_popf(void) - { GEN_CODE(POPF()); } - -public: - -#define DEFINE_OP_SZ(SZ, SFX, NAME, OP) \ - void gen_##NAME##_##SZ(int s, int d) \ - { GEN_CODE(OP##SFX##rr(s, d)); } \ - void gen_##NAME##_##SZ(int s, x86_memory_operand const & mem) \ - { GEN_CODE(OP##SFX##rm(s, mem.MD, mem.MB, mem.MI, mem.MS)); } - -#define DEFINE_OP(NAME, OP) \ - DEFINE_OP_SZ(8, B, NAME, OP) \ - DEFINE_OP_SZ(16, W, NAME, OP) \ - DEFINE_OP_SZ(32, L, NAME, OP) - - DEFINE_OP(cmpxchg, CMPXCHG); - DEFINE_OP(xadd, XADD); - DEFINE_OP(xchg, XCHG); - -#undef DEFINE_OP -#undef DEFINE_OP_SZ - -public: - -#define DEFINE_OP(NAME, OP) \ - void gen_##NAME(int s, int d) \ - { GEN_CODE(OP##rr(s, d)); } \ - void gen_##NAME(x86_memory_operand const & mem, int d) \ - { GEN_CODE(OP##mr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - - DEFINE_OP(bsf_16, BSFW); - DEFINE_OP(bsr_16, BSRW); - DEFINE_OP(bsf_32, BSFL); - DEFINE_OP(bsr_32, BSRL); - DEFINE_OP(mov_sx_8_16, MOVSBW); - DEFINE_OP(mov_zx_8_16, MOVZBW); - DEFINE_OP(mov_sx_8_32, MOVSBL); - DEFINE_OP(mov_zx_8_32, MOVZBL); - DEFINE_OP(mov_sx_16_32, MOVSWL); - DEFINE_OP(mov_zx_16_32, MOVZWL); - -#undef DEFINE_OP - -public: - - void gen_bswap_32(int r) - { GEN_CODE(BSWAPLr(r)); } - void gen_lea_32(x86_memory_operand const & mem, int d) - { GEN_CODE(LEALmr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_clc(void) - { GEN_CODE(CLC()); } - void gen_stc(void) - { GEN_CODE(STC()); } - void gen_cmc(void) - { GEN_CODE(CMC()); } - void gen_lahf(void) - { GEN_CODE(LAHF()); } - void gen_sahf(void) - { GEN_CODE(SAHF()); } - -private: - - void gen_sse_arith_ss(int op, int s, int d) - { GEN_CODE(_SSESSrr(op, s, d)); } - void gen_sse_arith_ss(int op, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSESSmr(op, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_sse_arith_sd(int op, int s, int d) - { GEN_CODE(_SSESDrr(op, s, d)); } - void gen_sse_arith_sd(int op, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSESDmr(op, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_sse_arith_ps(int op, int s, int d) - { GEN_CODE(_SSEPSrr(op, s, d)); } - void gen_sse_arith_ps(int op, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSEPSmr(op, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_sse_arith_pd(int op, int s, int d) - { GEN_CODE(_SSEPDrr(op, s, d)); } - void gen_sse_arith_pd(int op, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSEPDmr(op, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - -public: - - void gen_cmpps(int cc, int s, int d) - { GEN_CODE(CMPPSrr(cc, s, d)); } - void gen_cmpps(int cc, x86_memory_operand const & mem, int d) - { GEN_CODE(CMPPSmr(cc, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_cmppd(int cc, int s, int d) - { GEN_CODE(CMPPDrr(cc, s, d)); } - void gen_cmppd(int cc, x86_memory_operand const & mem, int d) - { GEN_CODE(CMPPDmr(cc, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_cmpss(int cc, int s, int d) - { GEN_CODE(CMPSSrr(cc, s, d)); } - void gen_cmpss(int cc, x86_memory_operand const & mem, int d) - { GEN_CODE(CMPSSmr(cc, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_cmpsd(int cc, int s, int d) - { GEN_CODE(CMPSDrr(cc, s, d)); } - void gen_cmpsd(int cc, x86_memory_operand const & mem, int d) - { GEN_CODE(CMPSDmr(cc, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - -public: - -#define DEFINE_OP_SS(NAME, OP) \ - void gen_##NAME##ss(x86_memory_operand const & mem, int d) \ - { gen_sse_arith_ss(X86_SSE_##OP, mem, d); } \ - void gen_##NAME##ss(int s, int d) \ - { gen_sse_arith_ss(X86_SSE_##OP, s, d); } -#define DEFINE_OP_SD(NAME, OP) \ - void gen_##NAME##sd(x86_memory_operand const & mem, int d) \ - { gen_sse_arith_sd(X86_SSE_##OP, mem, d); } \ - void gen_##NAME##sd(int s, int d) \ - { gen_sse_arith_sd(X86_SSE_##OP, s, d); } -#define DEFINE_OP_PS(NAME, OP) \ - void gen_##NAME##ps(x86_memory_operand const & mem, int d) \ - { gen_sse_arith_ps(X86_SSE_##OP, mem, d); } \ - void gen_##NAME##ps(int s, int d) \ - { gen_sse_arith_ps(X86_SSE_##OP, s, d); } -#define DEFINE_OP_PD(NAME, OP) \ - void gen_##NAME##pd(x86_memory_operand const & mem, int d) \ - { gen_sse_arith_pd(X86_SSE_##OP, mem, d); } \ - void gen_##NAME##pd(int s, int d) \ - { gen_sse_arith_pd(X86_SSE_##OP, s, d); } - -#define DEFINE_OP_S(NAME, OP) \ - DEFINE_OP_SS(NAME, OP) \ - DEFINE_OP_SD(NAME, OP) -#define DEFINE_OP_P(NAME, OP) \ - DEFINE_OP_PS(NAME, OP) \ - DEFINE_OP_PD(NAME, OP) -#define DEFINE_OP(NAME, OP) \ - DEFINE_OP_S(NAME, OP) \ - DEFINE_OP_P(NAME, OP) - - DEFINE_OP(add, ADD); - DEFINE_OP(sub, SUB); - DEFINE_OP(mul, MUL); - DEFINE_OP(div, DIV); - DEFINE_OP(min, MIN); - DEFINE_OP(max, MAX); - DEFINE_OP_P(and, AND); - DEFINE_OP_P(andn, ANDN); - DEFINE_OP_P(or, OR); - DEFINE_OP_P(xor, XOR); - DEFINE_OP_SS(rcp, RCP); - DEFINE_OP_PS(rcp, RCP); - DEFINE_OP_SS(rsqrt, RSQRT); - DEFINE_OP_PS(rsqrt, RSQRT); - DEFINE_OP_SS(sqrt, SQRT); - DEFINE_OP_PS(sqrt, SQRT); - DEFINE_OP_SS(comi, COMI); - DEFINE_OP_SD(comi, COMI); - DEFINE_OP_SS(ucomi, UCOMI); - DEFINE_OP_SD(ucomi, UCOMI); - -#undef DEFINE_OP -#undef DEFINE_OP_S -#undef DEFINE_OP_P -#undef DEFINE_OP_SS -#undef DEFINE_OP_SD -#undef DEFINE_OP_PS -#undef DEFINE_OP_PD - -public: - -#define DEFINE_OP(NAME, OP) \ - void gen_##NAME(int s, int d) \ - { GEN_CODE(OP##rr(s, d)); } \ - void gen_##NAME(x86_memory_operand const & mem, int d) \ - { GEN_CODE(OP##mr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } \ - void gen_##NAME(int s, x86_memory_operand const & mem) \ - { GEN_CODE(OP##rm(s, mem.MD, mem.MB, mem.MI, mem.MS)); } - - DEFINE_OP(movaps, MOVAPS); - DEFINE_OP(movapd, MOVAPD); - DEFINE_OP(movdqa, MOVDQA); - DEFINE_OP(movdqu, MOVDQU); - -#undef DEFINE_OP - -public: - -#define DEFINE_OP(NAME, OP) \ - void gen_##NAME(int s, int d) \ - { GEN_CODE(OP##rr(s, d)); } \ - void gen_##NAME(x86_memory_operand const & mem, int d) \ - { GEN_CODE(OP##mr(mem.MD, mem.MB, mem.MI, mem.MS, d)); } - - DEFINE_OP(movd_lx, MOVDXD); - -#undef DEFINE_OP - -public: - -#define DEFINE_OP(NAME, OP) \ - void gen_##NAME(int s, int d) \ - { GEN_CODE(OP##rr(s, d)); } \ - void gen_##NAME(int s, x86_memory_operand const & mem) \ - { GEN_CODE(OP##rm(s, mem.MD, mem.MB, mem.MI, mem.MS)); } - - DEFINE_OP(movd_xl, MOVDXS); - -#undef DEFINE_OP - -private: - - void gen_sse_arith(int op1, int op2, int s, int d) - { GEN_CODE(_SSELrr(op1, op2, s, _rX, d, _rX)); } - void gen_sse_arith(int op1, int op2, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSELmr(op1, op2, mem.MD, mem.MB, mem.MI, mem.MS, d, _rX)); } - void gen_sse_arith(int op1, int op2, x86_immediate_operand const & imm, int s, int d) - { GEN_CODE(_SSELirr(op1, op2, imm.value, s, d)); } - void gen_sse_arith(int op1, int op2, x86_immediate_operand const & imm, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSELimr(op1, op2, imm.value, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - void gen_sse_arith(int op1, int op2, int mri, x86_immediate_operand const & imm, int d) - { GEN_CODE(_SSELir(op1, op2, mri, imm.value, d)); } - -public: - -#define DEFINE_OP(NAME, OP1, OP2) \ - void gen_##NAME(int s, int d) \ - { gen_sse_arith(OP1, OP2, s, d); } \ - void gen_##NAME(x86_memory_operand const & mem, int d) \ - { gen_sse_arith(OP1, OP2, mem, d); } - -#define DEFINE_OP_IRR(NAME, OP1, OP2) \ - void gen_##NAME(x86_immediate_operand const & imm, int s, int d) \ - { gen_sse_arith(OP1, OP2, imm, s, d); } - -#define DEFINE_OP_IXR(NAME, OP1, OP2) \ - DEFINE_OP_IRR(NAME, OP1, OP2) \ - void gen_##NAME(x86_immediate_operand const & imm, x86_memory_operand const & mem, int d) \ - { gen_sse_arith(OP1, OP2, imm, mem, d); } - -#define DEFINE_OP_IR(NAME, OP1, OP2, MRI) \ - void gen_##NAME(x86_immediate_operand const & imm, int d) \ - { gen_sse_arith(OP1, OP2, MRI, imm, d); } - - DEFINE_OP(packssdw, 0x66, 0x6b); - DEFINE_OP(packsswb, 0x66, 0x63); - DEFINE_OP(packuswb, 0x66, 0x67); - DEFINE_OP(paddb, 0x66, 0xfc); - DEFINE_OP(paddd, 0x66, 0xfe); - DEFINE_OP(paddq, 0x66, 0xd4); - DEFINE_OP(paddsb, 0x66, 0xec); - DEFINE_OP(paddsw, 0x66, 0xed); - DEFINE_OP(paddusb, 0x66, 0xdc); - DEFINE_OP(paddusw, 0x66, 0xdd); - DEFINE_OP(paddw, 0x66, 0xfd); - DEFINE_OP(pand, 0x66, 0xdb); - DEFINE_OP(pandn, 0x66, 0xdf); - DEFINE_OP(pavgb, 0x66, 0xe0); - DEFINE_OP(pavgw, 0x66, 0xe3); - DEFINE_OP(pcmpeqb, 0x66, 0x74); - DEFINE_OP(pcmpeqd, 0x66, 0x76); - DEFINE_OP(pcmpeqw, 0x66, 0x75); - DEFINE_OP(pcmpgtb, 0x66, 0x64); - DEFINE_OP(pcmpgtd, 0x66, 0x66); - DEFINE_OP(pcmpgtw, 0x66, 0x65); - DEFINE_OP_IRR(pextrw, 0x66, 0xc5); - DEFINE_OP_IRR(pinsrw, 0x66, 0xc4); - DEFINE_OP(pmaddwd, 0x66, 0xf5); - DEFINE_OP(pmaxsw, 0x66, 0xee); - DEFINE_OP(pmaxub, 0x66, 0xde); - DEFINE_OP(pminsw, 0x66, 0xea); - DEFINE_OP(pminub, 0x66, 0xda); - DEFINE_OP(pmovmskb, 0x66, 0xd7); - DEFINE_OP(pmulhuw, 0x66, 0xe4); - DEFINE_OP(pmulhw, 0x66, 0xe5); - DEFINE_OP(pmullw, 0x66, 0xd5); - DEFINE_OP(pmuludq, 0x66, 0xf4); - DEFINE_OP(por, 0x66, 0xeb); - DEFINE_OP(psadbw, 0x66, 0xf6); - DEFINE_OP_IXR(pshufd, 0x66, 0x70); - DEFINE_OP_IXR(pshufhw, 0xf3, 0x70); - DEFINE_OP_IXR(pshuflhw, 0xf2, 0x70); - DEFINE_OP(pslld, 0x66, 0xf2); - DEFINE_OP_IR(pslld, 0x66, 0x72, 6); - DEFINE_OP_IR(pslldq, 0x66, 0x73, 7); - DEFINE_OP(psllq, 0x66, 0xf3); - DEFINE_OP_IR(psllq, 0x66, 0x73, 6); - DEFINE_OP(psllw, 0x66, 0xf1); - DEFINE_OP_IR(psllw, 0x66, 0x71, 6); - DEFINE_OP(psrad, 0x66, 0xe2); - DEFINE_OP_IR(psrad, 0x66, 0x72, 4); - DEFINE_OP(psraw, 0x66, 0xe1); - DEFINE_OP_IR(psraw, 0x66, 0x71, 4); - DEFINE_OP(psrld, 0x66, 0xd2); - DEFINE_OP_IR(psrld, 0x66, 0x72, 2); - DEFINE_OP_IR(psrldq, 0x66, 0x73, 3); - DEFINE_OP(psrlq, 0x66, 0xd3); - DEFINE_OP_IR(psrlq, 0x66, 0x73, 2); - DEFINE_OP(psrlw, 0x66, 0xd1); - DEFINE_OP_IR(psrlw, 0x66, 0x71, 2); - DEFINE_OP(psubb, 0x66, 0xf8); - DEFINE_OP(psubd, 0x66, 0xfa); - DEFINE_OP(psubq, 0x66, 0xfb); - DEFINE_OP(psubsb, 0x66, 0xe8); - DEFINE_OP(psubsw, 0x66, 0xe9); - DEFINE_OP(psubusb, 0x66, 0xd8); - DEFINE_OP(psubusw, 0x66, 0xd9); - DEFINE_OP(psubw, 0x66, 0xf9); - DEFINE_OP(punpckhbw, 0x66, 0x68); - DEFINE_OP(punpckhdq, 0x66, 0x6a); - DEFINE_OP(punpckhqdq, 0x66, 0x6d); - DEFINE_OP(punpckhwd, 0x66, 0x69); - DEFINE_OP(punpcklbw, 0x66, 0x60); - DEFINE_OP(punpckldq, 0x66, 0x62); - DEFINE_OP(punpcklqdq, 0x66, 0x6c); - DEFINE_OP(punpcklwd, 0x66, 0x61); - DEFINE_OP(pxor, 0x66, 0xef); - -#undef DEFINE_OP -#undef DEFINE_OP_IR -#undef DEFINE_OP_IRR -#undef DEFINE_OP_IXR - -private: - - void gen_ssse3_arith(int op1, int op2, int s, int d) - { GEN_CODE(_SSSE3Lrr(op1, op2, s, _rX, d, _rX)); } - void gen_ssse3_arith(int op1, int op2, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSSE3Lmr(op1, op2, mem.MD, mem.MB, mem.MI, mem.MS, d, _rX)); } - void gen_ssse3_arith(int op1, int op2, x86_immediate_operand const & imm, int s, int d) - { GEN_CODE(_SSSE3Lirr(op1, op2, imm.value, s, d)); } - void gen_ssse3_arith(int op1, int op2, x86_immediate_operand const & imm, x86_memory_operand const & mem, int d) - { GEN_CODE(_SSSE3Limr(op1, op2, imm.value, mem.MD, mem.MB, mem.MI, mem.MS, d)); } - -}; - -enum { - X86_INSN_ALU_8, - X86_INSN_ALU_16, - X86_INSN_ALU_32, - X86_INSN_BIT_16, - X86_INSN_BIT_32, - X86_INSN_ROT_8, - X86_INSN_ROT_16, - X86_INSN_ROT_32, - X86_INSN_SSE_SS, - X86_INSN_SSE_SD, - X86_INSN_SSE_PS, - X86_INSN_SSE_PD, - X86_INSN_SSE_PI, - X86_INSN_SSE_3P, /* 3-byte prefix (SSSE3) */ -}; - -inline void -x86_codegen::gen_insn(int type, int op, int s, int d) -{ - switch (type) { - case X86_INSN_SSE_SS: - gen_sse_arith_ss(op, s, d); - break; - case X86_INSN_SSE_SD: - gen_sse_arith_sd(op, s, d); - break; - case X86_INSN_SSE_PS: - gen_sse_arith_ps(op, s, d); - break; - case X86_INSN_SSE_PD: - gen_sse_arith_pd(op, s, d); - break; - case X86_INSN_SSE_PI: - gen_sse_arith(0x66, op, s, d); - break; - case X86_INSN_SSE_3P: - gen_ssse3_arith(0x38, op, s, d); - break; - default: - abort(); - } -} - -inline void -x86_codegen::gen_insn(int type, int op, x86_memory_operand const & mem, int d) -{ - switch (type) { - case X86_INSN_SSE_SS: - gen_sse_arith_ss(op, mem, d); - break; - case X86_INSN_SSE_SD: - gen_sse_arith_sd(op, mem, d); - break; - case X86_INSN_SSE_PS: - gen_sse_arith_ps(op, mem, d); - break; - case X86_INSN_SSE_PD: - gen_sse_arith_pd(op, mem, d); - break; - case X86_INSN_SSE_PI: - gen_sse_arith(0x66, op, mem, d); - break; - case X86_INSN_SSE_3P: - gen_ssse3_arith(0x38, op, mem, d); - break; - default: - abort(); - } -} - -inline void -x86_codegen::gen_failure(const char *msg, const char *file, int line, const char *fn) -{ - fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n", - fn ? fn : "", file, line, msg); - abort(); -} - -#endif /* JIT_X86_CODEGEN_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/genexec.pl b/SheepShaver/src/kpx_cpu/src/cpu/ppc/genexec.pl deleted file mode 100755 index 5a6841f2..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/genexec.pl +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/perl -use strict; - -my (@handlers, @extra_handlers, %templates); - -sub split_arglist($) { - (map { $_ =~ s/\s//g; $_ } split ",", $_[0]); -} - -my @lines = map { split ";", $_ } (); - -my $is_template = 0; -my $e; -foreach (@lines) { - $_ =~ s/;/&\n/g; - if (/^DEFINE_TEMPLATE\((\w+),.+,.+\((.+)\)\)/) { - $is_template = 1; - $e = { name => $1 }; - push @{$e->{args}}, split_arglist $2; - } - elsif ($is_template && /^\}/) { - $is_template = 0; - $templates{$e->{name}} = $e; - } - elsif (/(powerpc_cpu::execute_\w+)<(.+)>/) { - my $h = { name => $1, args => $2 }; - if ($is_template) { - push @{$e->{handlers}}, $h; - } - else { - push @handlers, $h; - } - } - elsif (/template.+decode_(\w+)<(.+)>/) { - my $template = $templates{$1}; - my @template_args = @{$template->{args}}; - my @args = split_arglist $2; - my %vars; - $vars{$template_args[$_]} = $args[$_] foreach (0 .. $#template_args); - foreach my $h (@{$template->{handlers}}) { - my @new_args = map { $vars{$_} || $_ } split_arglist $h->{args}; - push @extra_handlers, { name => $h->{name}, args => join(", ", @new_args) }; - } - } -} - -my %output_handlers; -foreach (@handlers, @extra_handlers) { - my $line = "template void $_->{name}<".join(", ", $_->{args}).">(uint32);"; - print "$line\n" if (!$output_handlers{$line}); - $output_handlers{$line} = 1; -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-bitfields.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-bitfields.hpp deleted file mode 100644 index 78eba468..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-bitfields.hpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * ppc-bitfields.hpp - Instruction fields - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_BITFIELDS_H -#define PPC_BITFIELDS_H - -#include "cpu/ppc/ppc-operations.hpp" - -/// -/// Bitfield management -/// - -template< int FB, int FE > -struct static_mask { - enum { value = (0xffffffff >> FB) ^ (0xffffffff >> (FE + 1)) }; -}; - -template< int FB > -struct static_mask { - enum { value = 0xffffffff >> FB }; -}; - -template< int FB, int FE > -struct bit_field { - static inline uint32 mask() { - return static_mask::value; - } - static inline bool test(uint32 value) { - return value & mask(); - } - static inline uint32 extract(uint32 value) { - const uint32 m = mask() >> (31 - FE); - return (value >> (31 - FE)) & m; - } - static inline void insert(uint32 & data, uint32 value) { - const uint32 m = mask(); - data = (data & ~m) | ((value << (31 - FE)) & m); - } -}; - -template< class type, type value > -struct fake_bit_field { - static inline bool test(uint32) { - return value; - } - static inline type extract(uint32) { - return value; - } -}; - -/// -/// Instruction Fields -/// - -// Primary and extended opcode fields -typedef bit_field< 0, 5 > OPCD_field; -typedef bit_field< 21, 30 > XO_10_field; -typedef bit_field< 22, 30 > XO_9_field; -typedef bit_field< 26, 30 > XO_5_field; - -// General purpose registers -typedef bit_field< 11, 15 > rA_field; -typedef bit_field< 16, 20 > rB_field; -typedef bit_field< 6, 10 > rD_field; -typedef bit_field< 6, 10 > rS_field; - -// Floating-point registers -typedef bit_field< 11, 15 > frA_field; -typedef bit_field< 16, 20 > frB_field; -typedef bit_field< 21, 25 > frC_field; -typedef bit_field< 6, 10 > frD_field; -typedef bit_field< 6, 10 > frS_field; - -// Vector registers -typedef bit_field< 11, 15 > vA_field; -typedef bit_field< 16, 20 > vB_field; -typedef bit_field< 21, 25 > vC_field; -typedef bit_field< 6, 10 > vD_field; -typedef bit_field< 6, 10 > vS_field; - -typedef bit_field< 21, 21 > vRc_field; -typedef bit_field< 11, 15 > vUIMM_field; -typedef bit_field< 22, 25 > vSH_field; - -// Condition registers -typedef bit_field< 11, 15 > crbA_field; -typedef bit_field< 16, 20 > crbB_field; -typedef bit_field< 6, 10 > crbD_field; -typedef bit_field< 6, 8 > crfD_field; -typedef bit_field< 11, 13 > crfS_field; -typedef bit_field< 12, 19 > CRM_field; -typedef bit_field< 7, 14 > FM_field; - -// CR register fields -template< int CRn > struct CR_field : bit_field< 4*CRn+0, 4*CRn+3 > { }; -template< int CRn > struct CR_LT_field : bit_field< 4*CRn+0, 4*CRn+0 > { }; -template< int CRn > struct CR_GT_field : bit_field< 4*CRn+1, 4*CRn+1 > { }; -template< int CRn > struct CR_EQ_field : bit_field< 4*CRn+2, 4*CRn+2 > { }; -template< int CRn > struct CR_SO_field : bit_field< 4*CRn+3, 4*CRn+3 > { }; -template< int CRn > struct CR_UN_field : bit_field< 4*CRn+3, 4*CRn+3 > { }; - -// Aliases used for CR storage optimization -typedef CR_LT_field<7> standalone_CR_LT_field; -typedef CR_GT_field<7> standalone_CR_GT_field; -typedef CR_EQ_field<7> standalone_CR_EQ_field; -typedef CR_SO_field<7> standalone_CR_SO_field; - -// XER register fields -typedef bit_field< 0, 0 > XER_SO_field; -typedef bit_field< 1, 1 > XER_OV_field; -typedef bit_field< 2, 2 > XER_CA_field; -typedef bit_field< 25, 31 > XER_COUNT_field; - -// FPSCR register fields -typedef bit_field< 0, 0 > FPSCR_FX_field; -typedef bit_field< 1, 1 > FPSCR_FEX_field; -typedef bit_field< 2, 2 > FPSCR_VX_field; -typedef bit_field< 3, 3 > FPSCR_OX_field; -typedef bit_field< 4, 4 > FPSCR_UX_field; -typedef bit_field< 5, 5 > FPSCR_ZX_field; -typedef bit_field< 6, 6 > FPSCR_XX_field; -typedef bit_field< 7, 7 > FPSCR_VXSNAN_field; -typedef bit_field< 8, 8 > FPSCR_VXISI_field; -typedef bit_field< 9, 9 > FPSCR_VXIDI_field; -typedef bit_field< 10, 10 > FPSCR_VXZDZ_field; -typedef bit_field< 11, 11 > FPSCR_VXIMZ_field; -typedef bit_field< 12, 12 > FPSCR_VXVC_field; -typedef bit_field< 13, 13 > FPSCR_FR_field; -typedef bit_field< 14, 14 > FPSCR_FI_field; -typedef bit_field< 15, 19 > FPSCR_FPRF_field; -typedef bit_field< 21, 21 > FPSCR_VXSOFT_field; -typedef bit_field< 22, 22 > FPSCR_VXSQRT_field; -typedef bit_field< 23, 23 > FPSCR_VXCVI_field; -typedef bit_field< 24, 24 > FPSCR_VE_field; -typedef bit_field< 25, 25 > FPSCR_OE_field; -typedef bit_field< 26, 26 > FPSCR_UE_field; -typedef bit_field< 27, 27 > FPSCR_ZE_field; -typedef bit_field< 28, 28 > FPSCR_XE_field; -typedef bit_field< 29, 29 > FPSCR_NI_field; -typedef bit_field< 30, 31 > FPSCR_RN_field; -typedef bit_field< 16, 19 > FPSCR_FPCC_field; -typedef bit_field< 15, 15 > FPSCR_FPRF_C_field; // C -typedef bit_field< 16, 16 > FPSCR_FPRF_FL_field; // < -typedef bit_field< 17, 17 > FPSCR_FPRF_FG_field; // > -typedef bit_field< 18, 18 > FPSCR_FPRF_FE_field; // = -typedef bit_field< 19, 19 > FPSCR_FPRF_FU_field; // ? - -// Vector Status and Control Register -typedef bit_field< 15, 15 > VSCR_NJ_field; -typedef bit_field< 31, 31 > VSCR_SAT_field; - -// Define variations for branch instructions -typedef bit_field< 30, 30 > AA_field; -typedef bit_field< 31, 31 > LK_field; -typedef bit_field< 16, 29 > BD_field; -typedef bit_field< 11, 15 > BI_field; -typedef bit_field< 6, 10 > BO_field; - -// Helper macros to deal with BO field -#define BO_MAKE(COND, TRUE, DCTR, CTR0) (((COND) ? 0 : 16) | ((TRUE) ? 8 : 0) | ((DCTR) ? 0 : 4) | ((CTR0) ? 2 : 0)) -#define BO_DECREMENT_CTR(BO) (((BO) & 0x04) == 0) -#define BO_BRANCH_IF_CTR_ZERO(BO) (((BO) & 0x02) != 0) -#define BO_CONDITIONAL_BRANCH(BO) (((BO) & 0x10) == 0) -#define BO_BRANCH_IF_TRUE(BO) (((BO) & 0x08) != 0) - -// Define variations for ALU instructions -typedef bit_field< 31, 31 > Rc_field; -typedef bit_field< 21, 21 > OE_field; -typedef bit_field< 21, 25 > MB_field; -typedef bit_field< 26, 30 > ME_field; -typedef bit_field< 16, 20 > NB_field; -typedef bit_field< 16, 20 > SH_field; - -// Immediates -typedef bit_field< 16, 19 > IMM_field; -typedef bit_field< 16, 31 > d_field; -typedef bit_field< 6, 29 > LI_field; -typedef bit_field< 16, 31 > SIMM_field; -typedef bit_field< 16, 31 > UIMM_field; - -// Misc -typedef bit_field< 12, 15 > SR_field; -typedef bit_field< 6, 10 > TO_field; -typedef bit_field< 11, 20 > SPR_field; -typedef bit_field< 11, 20 > TBR_field; - -// Aliases to ease filling in decode table -#define DEFINE_FAKE_FIELD_ALIAS(NAME) \ -typedef fake_bit_field NAME##_0; \ -typedef fake_bit_field NAME##_1 - -#define DEFINE_FIELD_ALIAS(NAME, FIELD) \ -typedef FIELD##_field NAME##_G; \ -DEFINE_FAKE_FIELD_ALIAS(NAME) - -DEFINE_FAKE_FIELD_ALIAS(CA_BIT); -DEFINE_FIELD_ALIAS(RC_BIT, Rc); -DEFINE_FIELD_ALIAS(OE_BIT, OE); -DEFINE_FIELD_ALIAS(AA_BIT, AA); -DEFINE_FIELD_ALIAS(LK_BIT, LK); -DEFINE_FIELD_ALIAS(BO_BIT, BO); -DEFINE_FIELD_ALIAS(BI_BIT, BI); -DEFINE_FIELD_ALIAS(vRC_BIT, vRc); - -#undef DEFINE_FIELD_ALIAS -#undef DEFINE_FAKE_FIELD_ALIAS - -typedef fake_bit_field RA_FIELD_A; // GPR(RA) -typedef rA_field RA_FIELD_G; // RA ? GPR(RA) : 0 -typedef fake_bit_field RA_FIELD_0; // R0 -> 0 - -#endif /* PPC_BITFIELDS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp deleted file mode 100644 index 7cea7d27..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ppc-blockinfo.hpp - PowerPC basic block information - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_BLOCKINFO_H -#define PPC_BLOCKINFO_H - -#include "cpu/jit/jit-config.hpp" -#include "nvmemfun.hpp" -#include "basic-blockinfo.hpp" - -class powerpc_cpu; - -struct powerpc_block_info - : public basic_block_info -{ - typedef nv_mem_fun1_t< void, powerpc_cpu, uint32 > execute_fn; - - struct decode_info - { - execute_fn execute; - uint32 opcode; - }; - -#if PPC_DECODE_CACHE - decode_info * di; -#endif -#if PPC_ENABLE_JIT - uint8 * entry_point; -#if DYNGEN_DIRECT_BLOCK_CHAINING - struct link_info { - uint8 * jmp_resolve_addr; // Address of default code to resolve target addr - uint8 * jmp_addr; // Address of target native branch offset to patch - uint32 jmp_pc; // Target jump addresses in emulated address space - }; - static const uint32 INVALID_PC = 0xffffffff; // An invalid PC address to mark jmp_pc[] as stale - link_info li[MAX_TARGETS]; -#endif -#endif - uintptr min_pc, max_pc; - - void init(uintptr start_pc); - bool intersect(uintptr start, uintptr end); - void invalidate(); -}; - -inline void -powerpc_block_info::init(uintptr start_pc) -{ - basic_block_info::init(start_pc); -#if PPC_DECODE_CACHE - di = NULL; -#endif -#if PPC_ENABLE_JIT -#if DYNGEN_DIRECT_BLOCK_CHAINING - for (int i = 0; i < MAX_TARGETS; i++) - li[i].jmp_pc = INVALID_PC; -#endif -#endif -} - -inline bool -powerpc_block_info::intersect(uintptr start, uintptr end) -{ - return (min_pc >= start && min_pc < end) || (max_pc >= start && max_pc < end); -} - -#endif /* PPC_BLOCKINFO_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp deleted file mode 100644 index 7563fd02..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-config.hpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * ppc-config.hpp - PowerPC core emulator config - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_CONFIG_H -#define PPC_CONFIG_H - -/** - * PPC_CHECK_INTERRUPTS - * - * Define if interrupts need to be check after each instruction, - * in interpreted mode, or at the end of each block, in compiled - * mode. - * - * NOTE: this only checks for user defined interrupts that are - * triggered by the program. This is not about OEA interrupts. - */ - -#ifndef PPC_CHECK_INTERRUPTS -#define PPC_CHECK_INTERRUPTS 0 -#endif - - -/** - * PPC_ENABLE_FPU_EXCEPTIONS - * - * Define to enable a more precise FPU emulation with support for - * exception bits. This is slower and not fully correct yet. - **/ - -#ifndef PPC_ENABLE_FPU_EXCEPTIONS -#define PPC_ENABLE_FPU_EXCEPTIONS 0 -#endif - - -/** - * PPC_DECODE_CACHE - * - * Define to 0 to disable the decode cache. This is only useful - * for debugging purposes and side-by-side comparison with other - * PowerPC emulators. - **/ - -#ifndef PPC_DECODE_CACHE -#define PPC_DECODE_CACHE 1 -#endif - - -/** - * PPC_ENABLE_JIT - * - * Define to 1 if dynamic translation is used. This requires - * dyngen to be enabled first. - **/ - -#ifndef PPC_ENABLE_JIT -#define PPC_ENABLE_JIT ENABLE_DYNGEN -#endif - - -/** - * PPC_REENTRANT_JIT - * - * Define to 1 if we are guaranteed to be able to invoke the JIT - * compiler, and the generated code, recursively. Enable this - * only if you have necessary provisions to recover from possible - * cache invalidatation within inner calls. - **/ - -#ifndef PPC_REENTRANT_JIT -#define PPC_REENTRANT_JIT 0 -#endif - - -/** - * PPC_EXECUTE_DUMP_STATE - * - * Define to dump state after each instruction. This also - * disables the decode cache. - **/ - -#ifndef PPC_EXECUTE_DUMP_STATE -#define PPC_EXECUTE_DUMP_STATE 0 -#endif - - -/** - * PPC_FLIGHT_RECORDER - * - * Define to enable the flight recorder. If set to 2, the - * complete register state will be recorder after each - * instruction execution. - **/ - -#ifndef PPC_FLIGHT_RECORDER -#define PPC_FLIGHT_RECORDER 0 -#endif - - -/** - * PPC_PROFILE_COMPILE_TIME - * - * Define to enable some compile time statistics. This concerns - * time spent into the decoder (PPC_DECODE_CACHE case) or total - * time spent into the dynamic translator (PPC_ENABLE_JIT case). - **/ - -#ifndef PPC_PROFILE_COMPILE_TIME -#define PPC_PROFILE_COMPILE_TIME 0 -#endif - - -/** - * PPC_PROFILE_GENERIC_CALLS - * - * Define to enable some generic handler invocation statistics. - **/ - -#ifndef PPC_PROFILE_GENERIC_CALLS -#define PPC_PROFILE_GENERIC_CALLS 0 -#endif - - -/** - * PPC_PROFILE_REGS_USE - * - * Define to enable some statistics about registers use. - **/ - -#ifndef PPC_PROFILE_REGS_USE -#define PPC_PROFILE_REGS_USE 0 -#endif - -#endif /* PPC_CONFIG_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp deleted file mode 100644 index 1fb8f856..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ /dev/null @@ -1,825 +0,0 @@ -/* - * ppc-cpu.cpp - PowerPC CPU definition - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include -#include -#include "vm_alloc.h" -#include "cpu/vm.hpp" -#include "cpu/ppc/ppc-cpu.hpp" -#ifndef SHEEPSHAVER -#include "basic-kernel.hpp" -#endif - -#if PPC_ENABLE_JIT -#include "cpu/jit/dyngen-exec.h" -#endif - -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif - -#define DEBUG 0 -#include "debug.h" - -#if PPC_PROFILE_GENERIC_CALLS -uint32 powerpc_cpu::generic_calls_count[PPC_I(MAX)]; -static int generic_calls_ids[PPC_I(MAX)]; -const int generic_calls_top_ten = 20; - -int generic_calls_compare(const void *e1, const void *e2) -{ - const int id1 = *(const int *)e1; - const int id2 = *(const int *)e2; - return powerpc_cpu::generic_calls_count[id2] - powerpc_cpu::generic_calls_count[id1]; -} -#endif - -#if PPC_PROFILE_REGS_USE -int register_info_compare(const void *e1, const void *e2) -{ - const powerpc_cpu::register_info *ri1 = (powerpc_cpu::register_info *)e1; - const powerpc_cpu::register_info *ri2 = (powerpc_cpu::register_info *)e2; - return ri2->count - ri1->count; -} -#endif - -static int ppc_refcount = 0; - -void powerpc_cpu::set_register(int id, any_register const & value) -{ - if (id >= powerpc_registers::GPR(0) && id <= powerpc_registers::GPR(31)) { - gpr(id - powerpc_registers::GPR_BASE) = value.i; - return; - } - if (id >= powerpc_registers::FPR(0) && id <= powerpc_registers::FPR(31)) { - fpr(id - powerpc_registers::FPR_BASE) = value.d; - return; - } - switch (id) { - case powerpc_registers::CR: cr().set(value.i); break; - case powerpc_registers::FPSCR: fpscr() = value.i; break; - case powerpc_registers::XER: xer().set(value.i); break; - case powerpc_registers::LR: lr() = value.i; break; - case powerpc_registers::CTR: ctr() = value.i; break; - case basic_registers::PC: - case powerpc_registers::PC: pc() = value.i; break; - case basic_registers::SP: - case powerpc_registers::SP: gpr(1)= value.i; break; - default: abort(); break; - } -} - -any_register powerpc_cpu::get_register(int id) -{ - any_register value; - if (id >= powerpc_registers::GPR(0) && id <= powerpc_registers::GPR(31)) { - value.i = gpr(id - powerpc_registers::GPR_BASE); - return value; - } - if (id >= powerpc_registers::FPR(0) && id <= powerpc_registers::FPR(31)) { - value.d = fpr(id - powerpc_registers::FPR_BASE); - return value; - } - switch (id) { - case powerpc_registers::CR: value.i = cr().get(); break; - case powerpc_registers::FPSCR: value.i = fpscr(); break; - case powerpc_registers::XER: value.i = xer().get(); break; - case powerpc_registers::LR: value.i = lr(); break; - case powerpc_registers::CTR: value.i = ctr(); break; - case basic_registers::PC: - case powerpc_registers::PC: value.i = pc(); break; - case basic_registers::SP: - case powerpc_registers::SP: value.i = gpr(1); break; - default: abort(); break; - } - return value; -} - -#if KPX_MAX_CPUS != 1 -uint32 powerpc_registers::reserve_valid = 0; -uint32 powerpc_registers::reserve_addr = 0; -uint32 powerpc_registers::reserve_data = 0; -#endif - -void powerpc_cpu::init_registers() -{ - assert((((uintptr)&vr(0)) % 16) == 0); - for (int i = 0; i < 32; i++) { - gpr(i) = 0; - fpr(i) = 0; - } - cr().set(0); - fpscr() = 0; - xer().set(0); - lr() = 0; - ctr() = 0; - pc() = 0; -} - -void powerpc_cpu::init_flight_recorder() -{ -#if PPC_FLIGHT_RECORDER - log_ptr = 0; - log_ptr_wrapped = false; -#endif -} - -void powerpc_cpu::do_record_step(uint32 pc, uint32 opcode) -{ -#if PPC_FLIGHT_RECORDER - log[log_ptr].pc = pc; - log[log_ptr].opcode = opcode; -#ifdef SHEEPSHAVER - log[log_ptr].sp = gpr(1); - log[log_ptr].r24 = gpr(24); -#endif -#if PPC_FLIGHT_RECORDER >= 2 - for (int i = 0; i < 32; i++) { - log[log_ptr].r[i] = gpr(i); - log[log_ptr].fr[i] = fpr(i); - } - log[log_ptr].lr = lr(); - log[log_ptr].ctr = ctr(); - log[log_ptr].cr = cr().get(); - log[log_ptr].xer = xer().get(); - log[log_ptr].fpscr = fpscr(); -#endif - log_ptr++; - if (log_ptr == LOG_SIZE) { - log_ptr = 0; - log_ptr_wrapped = true; - } -#endif -} - -#if PPC_FLIGHT_RECORDER -void powerpc_cpu::start_log() -{ - logging = true; - invalidate_cache(); -} - -void powerpc_cpu::stop_log() -{ - logging = false; - invalidate_cache(); -} - -void powerpc_cpu::dump_log(const char *filename) -{ - if (filename == NULL) - filename = "ppc.log"; - - FILE *f = fopen(filename, "w"); - if (f == NULL) - return; - - int start_ptr = 0; - int log_size = log_ptr; - if (log_ptr_wrapped) { - start_ptr = log_ptr; - log_size = LOG_SIZE; - } - - for (int i = 0; i < log_size; i++) { - int j = (i + start_ptr) % LOG_SIZE; -#if PPC_FLIGHT_RECORDER >= 2 - fprintf(f, " pc %08x lr %08x ctr %08x cr %08x xer %08x ", log[j].pc, log[j].lr, log[j].ctr, log[j].cr, log[j].xer); - fprintf(f, " r0 %08x r1 %08x r2 %08x r3 %08x ", log[j].r[0], log[j].r[1], log[j].r[2], log[j].r[3]); - fprintf(f, " r4 %08x r5 %08x r6 %08x r7 %08x ", log[j].r[4], log[j].r[5], log[j].r[6], log[j].r[7]); - fprintf(f, " r8 %08x r9 %08x r10 %08x r11 %08x ", log[j].r[8], log[j].r[9], log[j].r[10], log[j].r[11]); - fprintf(f, "r12 %08x r13 %08x r14 %08x r15 %08x ", log[j].r[12], log[j].r[13], log[j].r[14], log[j].r[15]); - fprintf(f, "r16 %08x r17 %08x r18 %08x r19 %08x ", log[j].r[16], log[j].r[17], log[j].r[18], log[j].r[19]); - fprintf(f, "r20 %08x r21 %08x r22 %08x r23 %08x ", log[j].r[20], log[j].r[21], log[j].r[22], log[j].r[23]); - fprintf(f, "r24 %08x r25 %08x r26 %08x r27 %08x ", log[j].r[24], log[j].r[25], log[j].r[26], log[j].r[27]); - fprintf(f, "r28 %08x r29 %08x r30 %08x r31 %08x\n", log[j].r[28], log[j].r[29], log[j].r[30], log[j].r[31]); - fprintf(f, "opcode %08x\n", log[j].opcode); -#else - fprintf(f, " pc %08x opc %08x", log[j].pc, log[j].opcode); -#ifdef SHEEPSHAVER - fprintf(f, " sp %08x r24 %08x", log[j].sp, log[j].r24); -#endif - fprintf(f, "| "); -#if !ENABLE_MON - fprintf(f, "\n"); -#endif -#endif -#if ENABLE_MON - disass_ppc(f, log[j].pc, log[j].opcode); -#endif - } - fclose(f); -} -#endif - -#if ENABLE_MON -static uint32 mon_read_byte_ppc(uintptr addr) -{ - return *((uint8 *)addr); -} - -static void mon_write_byte_ppc(uintptr addr, uint32 b) -{ - uint8 *m = (uint8 *)addr; - *m = b; -} -#endif - -void powerpc_cpu::initialize() -{ -#ifdef SHEEPSHAVER - printf("PowerPC CPU emulator by Gwenole Beauchesne\n"); -#endif - -#if PPC_PROFILE_REGS_USE - reginfo = new register_info[32]; - for (int i = 0; i < 32; i++) { - reginfo[i].id = i; - reginfo[i].count = 0; - } -#endif - - init_flight_recorder(); - init_decoder(); - init_registers(); - init_decode_cache(); - execute_depth = 0; - - // Initialize block lookup table -#if PPC_DECODE_CACHE || PPC_ENABLE_JIT - my_block_cache.initialize(); -#endif - - // Init cache range invalidate recorder - cache_range.start = cache_range.end = 0; - - // Init syscalls handler - execute_do_syscall = NULL; - - // Init field2mask - for (int i = 0; i < 256; i++) { - uint32 mask = 0; - if (i & 0x01) mask |= 0x0000000f; - if (i & 0x02) mask |= 0x000000f0; - if (i & 0x04) mask |= 0x00000f00; - if (i & 0x08) mask |= 0x0000f000; - if (i & 0x10) mask |= 0x000f0000; - if (i & 0x20) mask |= 0x00f00000; - if (i & 0x40) mask |= 0x0f000000; - if (i & 0x80) mask |= 0xf0000000; - field2mask[i] = mask; - } - -#if ENABLE_MON - mon_init(); - mon_read_byte = mon_read_byte_ppc; - mon_write_byte = mon_write_byte_ppc; -#endif - -#if PPC_PROFILE_COMPILE_TIME - compile_count = 0; - compile_time = 0; - emul_start_time = clock(); -#endif -} - -#if PPC_ENABLE_JIT -void powerpc_cpu::enable_jit(uint32 cache_size) -{ - use_jit = true; - if (cache_size) - codegen.set_cache_size(cache_size); - codegen.initialize(); -} -#endif - -// Memory allocator returning powerpc_cpu objects aligned on 16-byte boundaries -// FORMAT: [ alignment ] magic identifier, offset to malloc'ed data, powerpc_cpu data -void *powerpc_cpu::operator new(size_t size) -{ - const int ALIGN = 16; - - // Allocate enough space for powerpc_cpu data + signature + align pad - uint8 *ptr = (uint8 *)malloc(size + ALIGN * 2); - if (ptr == NULL) - throw std::bad_alloc(); - - // Align memory - int ofs = 0; - while ((((uintptr)ptr) % ALIGN) != 0) - ofs++, ptr++; - - // Insert signature and offset - struct aligned_block_t { - uint32 pad[(ALIGN - 8) / 4]; - uint32 signature; - uint32 offset; - uint8 data[sizeof(powerpc_cpu)]; - }; - aligned_block_t *blk = (aligned_block_t *)ptr; - blk->signature = 0x53435055; /* 'SCPU' */ - blk->offset = ofs + (&blk->data[0] - (uint8 *)blk); - assert((((uintptr)&blk->data) % ALIGN) == 0); - return &blk->data[0]; -} - -void powerpc_cpu::operator delete(void *p) -{ - uint32 *blk = (uint32 *)p; - assert(blk[-2] == 0x53435055); /* 'SCPU' */ - void *ptr = (void *)(((uintptr)p) - blk[-1]); - free(ptr); -} - -#ifdef SHEEPSHAVER -powerpc_cpu::powerpc_cpu() -#if PPC_ENABLE_JIT - : codegen(this) -#endif -#else -powerpc_cpu::powerpc_cpu(task_struct *parent_task) - : basic_cpu(parent_task) -#if PPC_ENABLE_JIT - , codegen(this) -#endif -#endif -{ -#if PPC_ENABLE_JIT - use_jit = false; -#endif - ++ppc_refcount; - initialize(); -} - -powerpc_cpu::~powerpc_cpu() -{ - --ppc_refcount; -#if PPC_PROFILE_COMPILE_TIME - clock_t emul_end_time = clock(); - - const char *type = NULL; -#if PPC_ENABLE_JIT - if (use_jit) - type = "compile"; -#endif -#if PPC_DECODE_CACHE - if (!type) - type = "predecode"; -#endif - if (type) { - printf("### Statistics for block %s\n", type); - printf("Total block %s count : %d\n", type, compile_count); - uint32 emul_time = emul_end_time - emul_start_time; - printf("Total emulation time : %.1f sec\n", - double(emul_time) / double(CLOCKS_PER_SEC)); - printf("Total %s time : %.1f sec (%.1f%%)\n", type, - double(compile_time) / double(CLOCKS_PER_SEC), - 100.0 * double(compile_time) / double(emul_time)); - printf("\n"); - } -#endif - -#if PPC_PROFILE_GENERIC_CALLS - if (use_jit && ppc_refcount == 0) { - uint64 total_generic_calls_count = 0; - for (int i = 0; i < PPC_I(MAX); i++) { - generic_calls_ids[i] = i; - total_generic_calls_count += generic_calls_count[i]; - } - qsort(generic_calls_ids, PPC_I(MAX), sizeof(int), generic_calls_compare); - printf("Rank Count Ratio Name\n"); - for (int i = 0; i < generic_calls_top_ten; i++) { - uint32 mnemo = generic_calls_ids[i]; - uint32 count = generic_calls_count[mnemo]; - const instr_info_t *ii = powerpc_ii_table; - while (ii->mnemo != mnemo) - ii++; - printf("%03d: %10lu %2.1f%% %s\n", i, count, 100.0*double(count)/double(total_generic_calls_count), ii->name); - } - } -#endif - -#if PPC_PROFILE_REGS_USE - printf("\n### Statistics for register usage\n"); - uint64 tot_reg_count = 0; - for (int i = 0; i < 32; i++) - tot_reg_count += reginfo[i].count; - qsort(reginfo, 32, sizeof(register_info), register_info_compare); - uint64 cum_reg_count = 0; - for (int i = 0; i < 32; i++) { - cum_reg_count += reginfo[i].count; - printf("r%-2d : %16llu %2.1f%% [%3.1f%%]\n", - reginfo[i].id, reginfo[i].count, - 100.0*double(reginfo[i].count)/double(tot_reg_count), - 100.0*double(cum_reg_count)/double(tot_reg_count)); - } - delete[] reginfo; -#endif - - kill_decode_cache(); - -#if ENABLE_MON - mon_exit(); -#endif -} - -void powerpc_cpu::dump_registers() -{ - fprintf(stderr, " r0 %08x r1 %08x r2 %08x r3 %08x\n", gpr(0), gpr(1), gpr(2), gpr(3)); - fprintf(stderr, " r4 %08x r5 %08x r6 %08x r7 %08x\n", gpr(4), gpr(5), gpr(6), gpr(7)); - fprintf(stderr, " r8 %08x r9 %08x r10 %08x r11 %08x\n", gpr(8), gpr(9), gpr(10), gpr(11)); - fprintf(stderr, "r12 %08x r13 %08x r14 %08x r15 %08x\n", gpr(12), gpr(13), gpr(14), gpr(15)); - fprintf(stderr, "r16 %08x r17 %08x r18 %08x r19 %08x\n", gpr(16), gpr(17), gpr(18), gpr(19)); - fprintf(stderr, "r20 %08x r21 %08x r22 %08x r23 %08x\n", gpr(20), gpr(21), gpr(22), gpr(23)); - fprintf(stderr, "r24 %08x r25 %08x r26 %08x r27 %08x\n", gpr(24), gpr(25), gpr(26), gpr(27)); - fprintf(stderr, "r28 %08x r29 %08x r30 %08x r31 %08x\n", gpr(28), gpr(29), gpr(30), gpr(31)); - fprintf(stderr, " f0 %02.5f f1 %02.5f f2 %02.5f f3 %02.5f\n", fpr(0), fpr(1), fpr(2), fpr(3)); - fprintf(stderr, " f4 %02.5f f5 %02.5f f6 %02.5f f7 %02.5f\n", fpr(4), fpr(5), fpr(6), fpr(7)); - fprintf(stderr, " f8 %02.5f f9 %02.5f f10 %02.5f f11 %02.5f\n", fpr(8), fpr(9), fpr(10), fpr(11)); - fprintf(stderr, "f12 %02.5f f13 %02.5f f14 %02.5f f15 %02.5f\n", fpr(12), fpr(13), fpr(14), fpr(15)); - fprintf(stderr, "f16 %02.5f f17 %02.5f f18 %02.5f f19 %02.5f\n", fpr(16), fpr(17), fpr(18), fpr(19)); - fprintf(stderr, "f20 %02.5f f21 %02.5f f22 %02.5f f23 %02.5f\n", fpr(20), fpr(21), fpr(22), fpr(23)); - fprintf(stderr, "f24 %02.5f f25 %02.5f f26 %02.5f f27 %02.5f\n", fpr(24), fpr(25), fpr(26), fpr(27)); - fprintf(stderr, "f28 %02.5f f29 %02.5f f30 %02.5f f31 %02.5f\n", fpr(28), fpr(29), fpr(30), fpr(31)); - fprintf(stderr, " lr %08x ctr %08x cr %08x xer %08x\n", lr(), ctr(), cr().get(), xer().get()); - fprintf(stderr, " pc %08x fpscr %08x\n", pc(), fpscr()); - fflush(stderr); -} - -void powerpc_cpu::dump_instruction(uint32 opcode) -{ - fprintf(stderr, "[%08x]-> %08x\n", pc(), opcode); -} - -void powerpc_cpu::fake_dump_registers(uint32) -{ - dump_registers(); -} - -void powerpc_registers::interrupt_copy(powerpc_registers &oregs, powerpc_registers const &iregs) -{ - for (int i = 0; i < 32; i++) { - oregs.gpr[i] = iregs.gpr[i]; - oregs.fpr[i] = iregs.fpr[i]; - } - oregs.cr = iregs.cr; - oregs.fpscr = iregs.fpscr; - oregs.xer = iregs.xer; - oregs.lr = iregs.lr; - oregs.ctr = iregs.ctr; - oregs.pc = iregs.pc; - - uint32 vrsave = iregs.vrsave; - oregs.vrsave = vrsave; - if (vrsave) { - for (int i = 31; i >= 0; i--) { - if (vrsave & 1) - oregs.vr[i] = iregs.vr[i]; - vrsave >>= 1; - } - } -} - -bool powerpc_cpu::check_spcflags() -{ - if (spcflags().test(SPCFLAG_CPU_EXEC_RETURN)) { - spcflags().clear(SPCFLAG_CPU_EXEC_RETURN); - return false; - } -#ifdef SHEEPSHAVER - if (spcflags().test(SPCFLAG_CPU_HANDLE_INTERRUPT)) { - spcflags().clear(SPCFLAG_CPU_HANDLE_INTERRUPT); - static bool processing_interrupt = false; - if (!processing_interrupt) { - processing_interrupt = true; - powerpc_registers r; - powerpc_registers::interrupt_copy(r, regs()); - HandleInterrupt(&r); - powerpc_registers::interrupt_copy(regs(), r); - processing_interrupt = false; - } - } - if (spcflags().test(SPCFLAG_CPU_TRIGGER_INTERRUPT)) { - spcflags().clear(SPCFLAG_CPU_TRIGGER_INTERRUPT); - spcflags().set(SPCFLAG_CPU_HANDLE_INTERRUPT); - } -#endif - if (spcflags().test(SPCFLAG_CPU_ENTER_MON)) { - spcflags().clear(SPCFLAG_CPU_ENTER_MON); -#if ENABLE_MON - // Start up mon in real-mode - char *arg[] = { - "mon", -#ifdef SHEEPSHAVER - "-m", -#endif - "-r", - NULL - }; - mon(sizeof(arg)/sizeof(arg[0]) - 1, arg); -#endif - } - return true; -} - -#if DYNGEN_DIRECT_BLOCK_CHAINING -void *powerpc_cpu::compile_chain_block(block_info *sbi) -{ - // Block index is stuffed into the source basic block pointer, - // which is aligned at least on 4-byte boundaries - const int n = ((uintptr)sbi) & 3; - sbi = (block_info *)(((uintptr)sbi) & ~3L); - const uint32 bpc = sbi->pc; - - const uint32 tpc = sbi->li[n].jmp_pc; - block_info *tbi = my_block_cache.find(tpc); - if (tbi == NULL) - tbi = compile_block(tpc); - assert(tbi && tbi->pc == tpc); - - dg_set_jmp_target(sbi->li[n].jmp_addr, tbi->entry_point); - return tbi->entry_point; -} -#endif - -void powerpc_cpu::execute(uint32 entry) -{ - bool invalidated_cache = false; - pc() = entry; -#if PPC_EXECUTE_DUMP_STATE - const bool dump_state = true; -#endif - execute_depth++; -#if PPC_DECODE_CACHE || PPC_ENABLE_JIT - if (execute_depth == 1 || (PPC_ENABLE_JIT && PPC_REENTRANT_JIT)) { -#if PPC_ENABLE_JIT - if (use_jit) { - block_info *bi = my_block_cache.find(pc()); - if (bi == NULL) - bi = compile_block(pc()); - for (;;) { - // Execute all cached blocks - for (;;) { - codegen.execute(bi->entry_point); - - if (!spcflags().empty()) { - if (!check_spcflags()) - goto return_site; - - // Force redecoding if cache was invalidated - if (spcflags().test(SPCFLAG_JIT_EXEC_RETURN)) { - spcflags().clear(SPCFLAG_JIT_EXEC_RETURN); - invalidated_cache = true; - break; - } - } - - // Don't check for backward branches here as this - // is now done by generated code. Besides, we will - // get here if the fast cache lookup failed too. - if ((bi = my_block_cache.find(pc())) == NULL) - break; - } - - // Compile new block - bi = compile_block(pc()); - } - goto return_site; - } -#endif -#if PPC_DECODE_CACHE - block_info *bi = my_block_cache.find(pc()); - if (bi != NULL) - goto pdi_execute; - for (;;) { -#if PPC_PROFILE_COMPILE_TIME - compile_count++; - clock_t start_time; - start_time = clock(); -#endif - bi = my_block_cache.new_blockinfo(); - bi->init(pc()); - - // Predecode a new block - block_info::decode_info *di; - const instr_info_t *ii; - uint32 dpc; - di = bi->di = decode_cache_p; - dpc = pc() - 4; - do { - uint32 opcode = vm_read_memory_4(dpc += 4); - ii = decode(opcode); -#if PPC_EXECUTE_DUMP_STATE - if (dump_state) { - di->opcode = opcode; - di->execute = nv_mem_fun(&powerpc_cpu::dump_instruction); - di++; - } -#endif -#if PPC_FLIGHT_RECORDER - if (is_logging()) { - di->opcode = opcode; - di->execute = nv_mem_fun(&powerpc_cpu::record_step); - di++; - } -#endif - di->opcode = opcode; - di->execute = ii->execute; - di++; -#if PPC_EXECUTE_DUMP_STATE - if (dump_state) { - di->opcode = 0; - di->execute = nv_mem_fun(&powerpc_cpu::fake_dump_registers); - di++; - } -#endif - if (di >= decode_cache_end_p) { - // Invalidate cache and move current code to start - invalidate_cache(); - const int blocklen = di - bi->di; - memmove(decode_cache_p, bi->di, blocklen * sizeof(*di)); - bi->di = decode_cache_p; - di = bi->di + blocklen; - } - } while ((ii->cflow & CFLOW_END_BLOCK) == 0); - bi->end_pc = dpc; - bi->min_pc = dpc; - bi->max_pc = entry; - bi->size = di - bi->di; - my_block_cache.add_to_cl_list(bi); - my_block_cache.add_to_active_list(bi); - decode_cache_p += bi->size; -#if PPC_PROFILE_COMPILE_TIME - compile_time += (clock() - start_time); -#endif - - // Execute all cached blocks - pdi_execute: - for (;;) { - const int r = bi->size % 4; - di = bi->di + r; - int n = (bi->size + 3) / 4; - switch (r) { - case 0: do { - di += 4; - di[-4].execute(this, di[-4].opcode); - case 3: di[-3].execute(this, di[-3].opcode); - case 2: di[-2].execute(this, di[-2].opcode); - case 1: di[-1].execute(this, di[-1].opcode); - } while (--n > 0); - } - - if (!spcflags().empty()) { - if (!check_spcflags()) - goto return_site; - - // Force redecoding if cache was invalidated - if (spcflags().test(SPCFLAG_JIT_EXEC_RETURN)) { - spcflags().clear(SPCFLAG_JIT_EXEC_RETURN); - invalidated_cache = true; - break; - } - } - - if ((bi->pc != pc()) && ((bi = my_block_cache.find(pc())) == NULL)) - break; - } - } - goto return_site; -#endif - goto do_interpret; - } -#endif - do_interpret: - for (;;) { - uint32 opcode = vm_read_memory_4(pc()); - const instr_info_t *ii = decode(opcode); -#if PPC_EXECUTE_DUMP_STATE - if (dump_state) - dump_instruction(opcode); -#endif -#if PPC_FLIGHT_RECORDER - if (is_logging()) - record_step(opcode); -#endif - assert(ii->execute.ptr() != 0); - ii->execute(this, opcode); -#if PPC_EXECUTE_DUMP_STATE - if (dump_state) - dump_registers(); -#endif - if (!spcflags().empty() && !check_spcflags()) - goto return_site; - } - return_site: - // Tell upper level we invalidated cache? - if (invalidated_cache) - spcflags().set(SPCFLAG_JIT_EXEC_RETURN); - --execute_depth; -} - -void powerpc_cpu::execute() -{ - execute(pc()); -} - -void powerpc_cpu::init_decode_cache() -{ -#if PPC_DECODE_CACHE - decode_cache = (block_info::decode_info *)vm_acquire(DECODE_CACHE_SIZE); - if (decode_cache == VM_MAP_FAILED) { - fprintf(stderr, "powerpc_cpu: Could not allocate decode cache\n"); - abort(); - } - - D(bug("powerpc_cpu: Allocated decode cache: %d KB at %p\n", DECODE_CACHE_SIZE / 1024, decode_cache)); - decode_cache_p = decode_cache; - decode_cache_end_p = decode_cache + DECODE_CACHE_MAX_ENTRIES; -#if FLIGHT_RECORDER - // Leave enough room to last call to record_step() - decode_cache_end_p -= 2; -#endif -#if PPC_EXECUTE_DUMP_STATE - // Leave enough room to last calls to dump state functions - decode_cache_end_p -= 2; -#endif -#endif -} - -void powerpc_cpu::kill_decode_cache() -{ -#if PPC_DECODE_CACHE - vm_release(decode_cache, DECODE_CACHE_SIZE); -#endif -} - -void powerpc_cpu::invalidate_cache() -{ - D(bug("Invalidate all cache blocks\n")); -#if PPC_DECODE_CACHE || PPC_ENABLE_JIT - my_block_cache.clear(); - my_block_cache.initialize(); - spcflags().set(SPCFLAG_JIT_EXEC_RETURN); -#endif -#if PPC_ENABLE_JIT - codegen.invalidate_cache(); -#endif -#if PPC_DECODE_CACHE - decode_cache_p = decode_cache; -#endif -} - -void powerpc_block_info::invalidate() -{ -#if PPC_DECODE_CACHE - // Don't do anything if this is a predecoded block - if (di) - return; -#endif -#if DYNGEN_DIRECT_BLOCK_CHAINING - for (int i = 0; i < MAX_TARGETS; i++) { - link_info * const tli = &li[i]; - uint32 tpc = tli->jmp_pc; - // For any jump within page boundaries, reset the jump address - // to the target block resolver (trampoline) - if (tpc != INVALID_PC && ((tpc ^ pc) >> 12) == 0) - dg_set_jmp_target(tli->jmp_addr, tli->jmp_resolve_addr); - } -#endif -} - -void powerpc_cpu::invalidate_cache_range(uintptr start, uintptr end) -{ - D(bug("Invalidate cache block [%08x - %08x]\n", start, end)); -#if PPC_DECODE_CACHE || PPC_ENABLE_JIT -#if DYNGEN_DIRECT_BLOCK_CHAINING - if (use_jit) { - // Invalidate on page boundaries - start &= -4096; - end = (end + 4095) & -4096; - D(bug(" at page boundaries [%08x - %08x]\n", start, end)); - } -#endif - spcflags().set(SPCFLAG_JIT_EXEC_RETURN); - my_block_cache.clear_range(start, end); -#endif -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp deleted file mode 100644 index c418386e..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ /dev/null @@ -1,514 +0,0 @@ -/* - * ppc-cpu.hpp - PowerPC CPU definition - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_CPU_H -#define PPC_CPU_H - -#include "basic-cpu.hpp" -#include "nvmemfun.hpp" -#include "cpu/vm.hpp" -#include "cpu/block-cache.hpp" -#include "cpu/ppc/ppc-config.hpp" -#include "cpu/ppc/ppc-bitfields.hpp" -#include "cpu/ppc/ppc-blockinfo.hpp" -#include "cpu/ppc/ppc-registers.hpp" -#if PPC_ENABLE_JIT -#include "cpu/ppc/ppc-jit.hpp" -#endif -#include "cpu/ppc/ppc-instructions.hpp" -#include - -class powerpc_cpu -#ifndef SHEEPSHAVER - : public basic_cpu -#endif -{ - // NOTE: PowerPC registers structure shall be aligned on 16-byte - // boundaries for the AltiVec registers to be used in native code - // with aligned load/stores. - // - // We can't assume (offsetof(powerpc_cpu, regs) % 16) == 0 since - // extra data could be inserted prior regs, e.g. pointer to vtable - struct { - powerpc_registers regs; - uint8 pad[16]; - } _regs; - - // Make sure the calculation of the current offset makes use of - // 'this' as this could make it simplified at compile-time - powerpc_registers *regs_ptr() const { return (powerpc_registers *)((char *)&_regs.regs + (16 - (((char *)&_regs.regs - (char *)this) % 16))); } - powerpc_registers const & regs() const { return *regs_ptr(); } - powerpc_registers & regs() { return *regs_ptr(); } - -#if PPC_PROFILE_REGS_USE - // Registers use statistics - // NOTE: the emulator is designed to access registers only through - // the gpr() accessors. The number of calls to gpr() matches exactly - // the number of register operands for an instruction. -public: - struct register_info { - int id; - uint64 count; - }; -private: - register_info *reginfo; - void log_reg(int r) const { reginfo[r].count++; } -#else - void log_reg(int r) const { } -#endif - -protected: - - powerpc_spcflags & spcflags() { return regs().spcflags; } - powerpc_spcflags const & spcflags() const { return regs().spcflags; } - powerpc_cr_register & cr() { return regs().cr; } - powerpc_cr_register const & cr() const { return regs().cr; } - powerpc_xer_register & xer() { return regs().xer; } - powerpc_xer_register const & xer() const { return regs().xer; } - powerpc_vscr & vscr() { return regs().vscr; } - powerpc_vscr const & vscr() const { return regs().vscr; } - - uint32 vrsave() const { return regs().vrsave; } - uint32 & vrsave() { return regs().vrsave; } - - uint32 & fpscr() { return regs().fpscr; } - uint32 fpscr() const { return regs().fpscr; } - uint32 & lr() { return regs().lr; } - uint32 lr() const { return regs().lr; } - uint32 & ctr() { return regs().ctr; } - uint32 ctr() const { return regs().ctr; } - uint32 & pc() { return regs().pc; } - uint32 pc() const { return regs().pc; } - void increment_pc(int o) { pc() += o; } - - friend class pc_operand; - friend class lr_operand; - friend class ctr_operand; - friend class cr_operand; - template< class field > friend class xer_operand; - template< class field > friend class fpscr_operand; - -public: - - uint32 & gpr(int i) { log_reg(i); return regs().gpr[i]; } - uint32 gpr(int i) const { log_reg(i); return regs().gpr[i]; } - double & fpr(int i) { return regs().fpr[i].d; } - double fpr(int i) const { return regs().fpr[i].d; } - uint64 & fpr_dw(int i) { return regs().fpr[i].j; } - uint64 fpr_dw(int i) const { return regs().fpr[i].j; } - powerpc_vr & vr(int i) { return regs().vr[i]; } - powerpc_vr const & vr(int i) const { return regs().vr[i]; } - -protected: - - // Condition codes management - void record_cr(int crfd, int32 value) - { cr().compute(crfd, value); cr().set_so(crfd, xer().get_so()); } - void record_cr0(int32 value) - { record_cr(0, value); } - void record_cr1() - { cr().set((cr().get() & ~CR_field<1>::mask()) | ((fpscr() >> 4) & 0x0f000000)); } - void record_fpscr(int exceptions); - void record_cr6(powerpc_vr const & vS, bool check_one) { - if (check_one && (vS.j[0] == UVAL64(0xffffffffffffffff) && - vS.j[1] == UVAL64(0xffffffffffffffff))) - cr().set(6, 8); - else if (vS.j[0] == UVAL64(0) && vS.j[1] == UVAL64(0)) - cr().set(6, 2); - else - cr().set(6, 0); - } - - template< class FP > - void fp_classify(FP x); - -protected: - - // Flight recorder - struct rec_step { -#if PPC_FLIGHT_RECORDER >= 2 - uint32 r[32]; - double fr[32]; - uint32 lr, ctr; - uint32 cr, xer; - uint32 fpscr; -#endif - uint32 pc; - uint32 opcode; -#ifdef SHEEPSHAVER - uint32 sp; - uint32 r24; -#endif - }; - - // Instruction formats - enum instr_format_t { - INVALID_form = 0, - A_form, - B_form, - D_form, DS_form, - I_form, - M_form, - MD_form, MDS_form, - SC_form, - X_form, - XFL_form, XFX_form, XL_form, XO_form, XS_form, - VX_form, VXR_form, VA_form, - }; - - // Control flow types - enum control_flow_t { - CFLOW_NORMAL = 0, - CFLOW_BRANCH = 1, - CFLOW_JUMP = 2, - CFLOW_TRAP = 4, - CFLOW_CONST_JUMP = 8, - CFLOW_END_BLOCK = CFLOW_BRANCH | CFLOW_JUMP | CFLOW_TRAP - }; - - // Callbacks associated with each instruction - typedef void (powerpc_cpu::*execute_pmf)(uint32 opcode); - typedef nv_mem_fun1_t< void, powerpc_cpu, uint32 > execute_fn; - - // Instruction information structure - struct instr_info_t { - char name[12]; // Instruction name - execute_fn execute; // Semantic routine for this instruction - uint16 mnemo; // Mnemonic - uint16 format; // Instruction format (XO-form, D-form, etc.) - uint16 opcode; // Primary opcode - uint16 xo; // Extended opcode - uint16 cflow; // Mask of control flow information - }; - -private: - - // Compile time statistics -#if PPC_PROFILE_COMPILE_TIME - uint32 compile_count; - clock_t compile_time; - clock_t emul_start_time; -#endif - - // Compile blocks statistics -#if PPC_PROFILE_GENERIC_CALLS - friend int generic_calls_compare(const void *, const void *); - static uint32 generic_calls_count[]; -#endif - - // Flight recorder data - static const int LOG_SIZE = 32768; -#if PPC_FLIGHT_RECORDER - rec_step log[LOG_SIZE]; - bool logging; - int log_ptr; - bool log_ptr_wrapped; -#else - static const bool logging = false; -#endif - void do_record_step(uint32 pc, uint32 opcode); - void record_step(uint32 opcode) { do_record_step(pc(), opcode); } - - // Syscall callback must return TRUE if no error occurred - typedef bool (*syscall_fn)(powerpc_cpu *cpu); - syscall_fn execute_do_syscall; - - static const instr_info_t powerpc_ii_table[]; - std::vector ii_table; - typedef uint16 ii_index_t; - static const int II_INDEX_TABLE_SIZE = 0x20000; - ii_index_t ii_index_table[II_INDEX_TABLE_SIZE]; - - // Pack/unpack index into decode table - uint32 make_ii_index(uint32 opcode, uint32 xo) { return opcode | (xo << 6); } - uint32 get_ii_index(uint32 opcode) { return (opcode >> 26) | ((opcode & 0x7ff) << 6); } - - // Convert 8-bit field mask (e.g. mtcrf) to bit mask - uint32 field2mask[256]; - - // Check special CPU flags - bool check_spcflags(); - - // Current execute() nested level - int execute_depth; - -public: - - // Initialization & finalization - void initialize(); -#ifdef SHEEPSHAVER - powerpc_cpu(); -#else - powerpc_cpu(task_struct *parent_task); -#endif - ~powerpc_cpu(); - - // Specialised memory allocation (needs to be 16-byte aligned) - void *operator new(size_t size); - void operator delete(void *p); - - // Handle flight recorder -#if PPC_FLIGHT_RECORDER - bool is_logging() const { return logging; } - void start_log(); - void stop_log(); - void dump_log(const char *filename = NULL); -#else - bool is_logging() const { return false; } - void start_log() { } - void stop_log() { } - void dump_log(const char *filename = NULL) { } -#endif - - // Dump registers - void dump_registers(); - void dump_instruction(uint32 opcode); - void fake_dump_registers(uint32); - - // Start emulation loop - void execute(uint32 entry); - void execute(); - - // Interrupts handling - void trigger_interrupt(); - - // Set VALUE to register ID - void set_register(int id, any_register const & value); - - // Get register ID - any_register get_register(int id); - - // Set syscall callback - void set_syscall_callback(syscall_fn fn) { execute_do_syscall = fn; } - - // Caches invalidation - void invalidate_cache(); - void invalidate_cache_range(uintptr start, uintptr end); -private: - struct { uintptr start, end; } cache_range; - -protected: - - // Init decoder with one instruction info - void init_decoder_entry(const instr_info_t * ii); - -#if PPC_ENABLE_JIT - // Dynamic translation engine - struct codegen_context_t { - powerpc_dyngen & codegen; - uint32 entry_point; - uint32 pc; - uint32 opcode; - const instr_info_t *instr_info; - bool done_compile; - - codegen_context_t(powerpc_dyngen & codegen_init) - : codegen(codegen_init) - { } - }; - - // Compile one opcode, returns any of the following status - enum { - COMPILE_FAILURE, // no translation available, call interpreter - COMPILE_CODE_OK, // generated code, control flow fall through - COMPILE_EPILOGUE_OK // generated code, including basic block epilogue - }; - virtual int compile1(codegen_context_t & cg_context) { return COMPILE_FAILURE; } - - bool use_jit; -public: - void enable_jit(uint32 cache_size = 0); -#endif - -private: - - // Initializers & destructors - void init_flight_recorder(); - void init_registers(); - void init_decoder(); - void init_decode_cache(); - void kill_decode_cache(); - - // Get instruction info for opcode - const instr_info_t *decode(uint32 opcode) { - return &ii_table[ii_index_table[get_ii_index(opcode)]]; - } - - // Block lookup table - typedef powerpc_block_info block_info; - block_cache< block_info, lazy_allocator > my_block_cache; - -#if PPC_DECODE_CACHE - // Decode Cache - static const uint32 DECODE_CACHE_MAX_ENTRIES = 32768; - static const uint32 DECODE_CACHE_SIZE = DECODE_CACHE_MAX_ENTRIES * sizeof(block_info::decode_info); - block_info::decode_info * decode_cache; - block_info::decode_info * decode_cache_p; - block_info::decode_info * decode_cache_end_p; -#endif - -#if PPC_ENABLE_JIT - // Dynamic translation engine - friend class powerpc_dyngen_helper; - friend class powerpc_dyngen; - friend class powerpc_jit; - powerpc_jit codegen; - block_info *compile_block(uint32 entry); -#if DYNGEN_DIRECT_BLOCK_CHAINING - void *compile_chain_block(block_info *sbi); -#endif -#endif - - // Semantic action templates - template< bool SB, bool OE > - uint32 do_execute_divide(uint32, uint32); - template< bool EX, bool CA, bool OE > - uint32 do_execute_addition(uint32, uint32); - template< bool CA, bool OE > - uint32 do_execute_subtract(uint32, uint32); - template< bool OE > - uint32 do_execute_subtract_extended(uint32, uint32); - - // Instruction handlers - void execute_nop(uint32 opcode); - void execute_illegal(uint32 opcode); - template< class RA, class RB, class RC, class CA, class OE, class Rc > - void execute_addition(uint32 opcode); - template< class OP, class RD, class RA, class RB, class RC, class OE, class Rc > - void execute_generic_arith(uint32 opcode); - template< class PC, class BO, class DP, class AA, class LK > - void execute_branch(uint32 opcode); - template< class RB, typename CT > - void execute_compare(uint32 opcode); - template< class OP > - void execute_cr_op(uint32 opcode); - template< bool SB, class OE, class Rc > - void execute_divide(uint32 opcode); - template< class FP, class OP, class RD, class RA, class RB, class RC, class Rc, bool FPSCR > - void execute_fp_arith(uint32 opcode); - template< class OP, class RA, class RB, bool LD, int SZ, bool UP, bool RX > - void execute_loadstore(uint32 opcode); - template< class RA, class DP, bool LD > - void execute_loadstore_multiple(uint32 opcode); - template< class RA, bool IM, class NB > - void execute_load_string(uint32 opcode); - template< class RA, bool IM, class NB > - void execute_store_string(uint32 opcode); - template< class RA > - void execute_lwarx(uint32 opcode); - template< class RA > - void execute_stwcx(uint32 opcode); - void execute_mcrf(uint32 opcode); - void execute_mcrfs(uint32 opcode); - void execute_mcrxr(uint32 opcode); - void execute_mtcrf(uint32 opcode); - template< class FM, class RB, class Rc > - void execute_mtfsf(uint32 opcode); - template< class RB, class Rc > - void execute_mtfsfi(uint32 opcode); - template< class RB, class Rc > - void execute_mtfsb(uint32 opcode); - template< bool HI, bool SB, class OE, class Rc > - void execute_multiply(uint32 opcode); - template< class Rc > - void execute_mffs(uint32 opcode); - void execute_mfmsr(uint32 opcode); - template< class SPR > - void execute_mfspr(uint32 opcode); - template< class TBR > - void execute_mftbr(uint32 opcode); - template< class SPR > - void execute_mtspr(uint32 opcode); - template< class SH, class MA, class Rc > - void execute_rlwimi(uint32 opcode); - template< class OP, class RD, class RA, class SH, class SO, class CA, class Rc > - void execute_shift(uint32 opcode); - void execute_syscall(uint32 opcode); - template< bool OC > - void execute_fp_compare(uint32 opcode); - template< class RA, class RB, bool LD, bool DB, bool UP > - void execute_fp_loadstore(uint32 opcode); - template< class RN, class Rc > - void execute_fp_int_convert(uint32 opcode); - template< class Rc > - void execute_fp_round(uint32 opcode); - template< class RA, class RB > - void execute_icbi(uint32 opcode); - void execute_isync(uint32 opcode); - void execute_invalidate_cache_range(); - template< class RA, class RB > - void execute_dcbz(uint32 opcode); - template< bool SL > - void execute_vector_load_for_shift(uint32 opcode); - template< class VD, class RA, class RB > - void execute_vector_load(uint32 opcode); - template< class VS, class RA, class RB > - void execute_vector_store(uint32 opcode); - void execute_mfvscr(uint32 opcode); - void execute_mtvscr(uint32 opcode); - template< class OP, class VD, class VA, class VB, class VC, class Rc, int C1 > - void execute_vector_arith(uint32 opcode); - template< class OP, class VD, class VA, class VB, class VC > - void execute_vector_arith_mixed(uint32 opcode); - template< int ODD, class OP, class VD, class VA, class VB, class VC > - void execute_vector_arith_odd(uint32 opcode); - template< class VD, class VA, class VB, int LO > - void execute_vector_merge(uint32 opcode); - template< class VD, class VA, class VB > - void execute_vector_pack(uint32 opcode); - void execute_vector_pack_pixel(uint32 opcode); - template< int LO > - void execute_vector_unpack_pixel(uint32 opcode); - template< int LO, class VD, class VA > - void execute_vector_unpack(uint32 opcode); - void execute_vector_permute(uint32 opcode); - template< int SD > - void execute_vector_shift(uint32 opcode); - template< int SD, class VD, class VA, class VB, class SH > - void execute_vector_shift_octet(uint32 opcode); - template< class OP, class VD, class VB, bool IM > - void execute_vector_splat(uint32 opcode); - template< int SZ, class VD, class VA, class VB > - void execute_vector_sum(uint32 opcode); - - // Specialized instruction decoders - template< class RA, class RB, class RC, class CA > - execute_fn decode_addition(uint32 opcode); - template< class RA, class RS > - execute_fn decode_rlwinm(uint32 opcode); -}; - - -/** - * Interrupts handling - **/ - -inline void powerpc_cpu::trigger_interrupt() -{ -#if PPC_CHECK_INTERRUPTS - spcflags().set(SPCFLAG_CPU_TRIGGER_INTERRUPT); -#endif -} - -#ifdef SHEEPSHAVER -extern void HandleInterrupt(powerpc_registers *r); -#endif - -#endif /* PPC_CPU_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp deleted file mode 100644 index 972f26ec..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-decode.cpp +++ /dev/null @@ -1,1869 +0,0 @@ -/* - * ppc-decode.cpp - PowerPC instructions decoder - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-bitfields.hpp" -#include "cpu/ppc/ppc-operands.hpp" -#include "cpu/ppc/ppc-operations.hpp" -#include "cpu/ppc/ppc-instructions.hpp" - -#define DEBUG 0 -#include "debug.h" - -#define EXECUTE_0(HANDLER) \ -&powerpc_cpu::execute_##HANDLER - -#define EXECUTE_1(HANDLER, ARG1) \ -&powerpc_cpu::execute_##HANDLER - -#define EXECUTE_2(HANDLER, ARG1, ARG2) \ -&powerpc_cpu::execute_##HANDLER - -#define EXECUTE_3(HANDLER, ARG1, ARG2, ARG3) \ -&powerpc_cpu::execute_##HANDLER - -#define EXECUTE_4(HANDLER, ARG1, ARG2, ARG3, ARG4) \ -&powerpc_cpu::execute_##HANDLER - -#define EXECUTE_7(HANDLER, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ -&powerpc_cpu::execute_##HANDLER - -#define EXECUTE_ADDITION(RA, RB, RC, CA, OE, Rc) \ -&powerpc_cpu::execute_addition - -#define EXECUTE_GENERIC_ARITH(OP, RD, RA, RB, RC, OE, Rc) \ -&powerpc_cpu::execute_generic_arith - -#define EXECUTE_BRANCH(PC, BO, DP, AA, LK) \ -&powerpc_cpu::execute_branch - -#define EXECUTE_COMPARE(RB, CT) \ -&powerpc_cpu::execute_compare - -#define EXECUTE_CR_OP(OP) \ -&powerpc_cpu::execute_cr_op - -#define EXECUTE_FP_ARITH(FP, OP, RD, RA, RB, RC, Rc, FPSCR) \ -&powerpc_cpu::execute_fp_arith - -#define EXECUTE_LOADSTORE(OP, RA, RB, LD, SZ, UP, RX) \ -&powerpc_cpu::execute_loadstore - -#define EXECUTE_LOADSTORE_MULTIPLE(RA, DP, LD) \ -&powerpc_cpu::execute_loadstore_multiple - -#define EXECUTE_LOAD_STRING(RA, IM, NB) \ -&powerpc_cpu::execute_load_string - -#define EXECUTE_STORE_STRING(RA, IM, NB) \ -&powerpc_cpu::execute_store_string - -#define EXECUTE_SHIFT(OP, RD, RA, SH, SO, CA, Rc) \ -&powerpc_cpu::execute_shift - -#define EXECUTE_FP_LOADSTORE(RA, RB, LD, DB, UP) \ -&powerpc_cpu::execute_fp_loadstore - -#define EXECUTE_VECTOR_LOADSTORE(OP, VD, RA, RB) \ -&powerpc_cpu::execute_vector_##OP - -#define EXECUTE_VECTOR_ARITH(OP, VD, VA, VB, VC) \ -&powerpc_cpu::execute_vector_arith, 0 > - -#define EXECUTE_VECTOR_ARITH_MIXED(OP, VD, VA, VB, VC) \ -&powerpc_cpu::execute_vector_arith_mixed - -#define EXECUTE_VECTOR_ARITH_ODD(ODD, OP, VD, VA, VB, VC) \ -&powerpc_cpu::execute_vector_arith_odd - -#define EXECUTE_VECTOR_MERGE(VD, VA, VB, LO) \ -&powerpc_cpu::execute_vector_merge - -#define EXECUTE_VECTOR_COMPARE(OP, VD, VA, VB, C1) \ -&powerpc_cpu::execute_vector_arith - -#define EXECUTE_VECTOR_PACK(VD, VA, VB) \ -&powerpc_cpu::execute_vector_pack - -#define EXECUTE_VECTOR_UNPACK(LO, VD, VB) \ -&powerpc_cpu::execute_vector_unpack - -#define EXECUTE_VECTOR_SHIFT_OCTET(SD, VD, VA, VB, SH) \ -&powerpc_cpu::execute_vector_shift_octet - -#define EXECUTE_VECTOR_SPLAT(OP, VD, VB, IM) \ -&powerpc_cpu::execute_vector_splat - -#define EXECUTE_VECTOR_SUM(SZ, VD, VA, VB) \ -&powerpc_cpu::execute_vector_sum - -const powerpc_cpu::instr_info_t powerpc_cpu::powerpc_ii_table[] = { - { "invalid", - EXECUTE_0(illegal), - PPC_I(INVALID), - INVALID_form, 0, 0, CFLOW_TRAP - }, - { "add", - EXECUTE_ADDITION(RA, RB, NONE, CA_BIT_0, OE_BIT_G, RC_BIT_G), - PPC_I(ADD), - XO_form, 31, 266, CFLOW_NORMAL - }, - { "addc", - EXECUTE_ADDITION(RA, RB, NONE, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(ADDC), - XO_form, 31, 10, CFLOW_NORMAL - }, - { "adde", - EXECUTE_ADDITION(RA, RB, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(ADDE), - XO_form, 31, 138, CFLOW_NORMAL - }, - { "addi", - EXECUTE_ADDITION(RA_or_0, SIMM, NONE, CA_BIT_0, OE_BIT_0, RC_BIT_0), - PPC_I(ADDI), - D_form, 14, 0, CFLOW_NORMAL - }, - { "addic", - EXECUTE_ADDITION(RA, SIMM, NONE, CA_BIT_1, OE_BIT_0, RC_BIT_0), - PPC_I(ADDIC), - D_form, 12, 0, CFLOW_NORMAL - }, - { "addic.", - EXECUTE_ADDITION(RA, SIMM, NONE, CA_BIT_1, OE_BIT_0, RC_BIT_1), - PPC_I(ADDIC_), - D_form, 13, 0, CFLOW_NORMAL - }, - { "addis", - EXECUTE_ADDITION(RA_or_0, SIMM_shifted, NONE, CA_BIT_0, OE_BIT_0, RC_BIT_0), - PPC_I(ADDIS), - D_form, 15, 0, CFLOW_NORMAL - }, - { "addme", - EXECUTE_ADDITION(RA, MINUS_ONE, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(ADDME), - XO_form, 31, 234, CFLOW_NORMAL - }, - { "addze", - EXECUTE_ADDITION(RA, ZERO, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(ADDZE), - XO_form, 31, 202, CFLOW_NORMAL - }, - { "and", - EXECUTE_GENERIC_ARITH(and, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(AND), - X_form, 31, 28, CFLOW_NORMAL - }, - { "andc", - EXECUTE_GENERIC_ARITH(andc, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(ANDC), - X_form, 31, 60, CFLOW_NORMAL - }, - { "andi.", - EXECUTE_GENERIC_ARITH(and, RA, RS, UIMM, NONE, OE_BIT_0, RC_BIT_1), - PPC_I(ANDI), - D_form, 28, 0, CFLOW_NORMAL - }, - { "andis.", - EXECUTE_GENERIC_ARITH(and, RA, RS, UIMM_shifted, NONE, OE_BIT_0, RC_BIT_1), - PPC_I(ANDIS), - D_form, 29, 0, CFLOW_NORMAL - }, - { "b", - EXECUTE_BRANCH(PC, immediate_value, LI, AA_BIT_G, LK_BIT_G), - PPC_I(B), - I_form, 18, 0, CFLOW_BRANCH - }, - { "bc", - EXECUTE_BRANCH(PC, operand_BO, BD, AA_BIT_G, LK_BIT_G), - PPC_I(BC), - B_form, 16, 0, CFLOW_BRANCH - }, - { "bcctr", - EXECUTE_BRANCH(CTR, operand_BO, ZERO, AA_BIT_0, LK_BIT_G), - PPC_I(BCCTR), - XL_form, 19, 528, CFLOW_BRANCH - }, - { "bclr", - EXECUTE_BRANCH(LR, operand_BO, ZERO, AA_BIT_0, LK_BIT_G), - PPC_I(BCLR), - XL_form, 19, 16, CFLOW_BRANCH - }, - { "cmp", - EXECUTE_COMPARE(RB, int32), - PPC_I(CMP), - X_form, 31, 0, CFLOW_NORMAL - }, - { "cmpi", - EXECUTE_COMPARE(SIMM, int32), - PPC_I(CMPI), - D_form, 11, 0, CFLOW_NORMAL - }, - { "cmpl", - EXECUTE_COMPARE(RB, uint32), - PPC_I(CMPL), - X_form, 31, 32, CFLOW_NORMAL - }, - { "cmpli", - EXECUTE_COMPARE(UIMM, uint32), - PPC_I(CMPLI), - D_form, 10, 0, CFLOW_NORMAL - }, - { "cntlzw", - EXECUTE_GENERIC_ARITH(cntlzw, RA, RS, NONE, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(CNTLZW), - X_form, 31, 26, CFLOW_NORMAL - }, - { "crand", - EXECUTE_CR_OP(and), - PPC_I(CRAND), - XL_form, 19, 257, CFLOW_NORMAL - }, - { "crandc", - EXECUTE_CR_OP(andc), - PPC_I(CRANDC), - XL_form, 19, 129, CFLOW_NORMAL - }, - { "creqv", - EXECUTE_CR_OP(eqv), - PPC_I(CREQV), - XL_form, 19, 289, CFLOW_NORMAL - }, - { "crnand", - EXECUTE_CR_OP(nand), - PPC_I(CRNAND), - XL_form, 19, 225, CFLOW_NORMAL - }, - { "crnor", - EXECUTE_CR_OP(nor), - PPC_I(CRNOR), - XL_form, 19, 33, CFLOW_NORMAL - }, - { "cror", - EXECUTE_CR_OP(or), - PPC_I(CROR), - XL_form, 19, 449, CFLOW_NORMAL - }, - { "crorc", - EXECUTE_CR_OP(orc), - PPC_I(CRORC), - XL_form, 19, 417, CFLOW_NORMAL - }, - { "crxor", - EXECUTE_CR_OP(xor), - PPC_I(CRXOR), - XL_form, 19, 193, CFLOW_NORMAL - }, - { "dcba", - EXECUTE_0(nop), - PPC_I(DCBA), - X_form, 31, 758, CFLOW_NORMAL - }, - { "dcbf", - EXECUTE_0(nop), - PPC_I(DCBF), - X_form, 31, 86, CFLOW_NORMAL - }, - { "dcbi", - EXECUTE_0(nop), - PPC_I(DCBI), - X_form, 31, 470, CFLOW_NORMAL - }, - { "dcbst", - EXECUTE_0(nop), - PPC_I(DCBST), - X_form, 31, 54, CFLOW_NORMAL - }, - { "dcbt", - EXECUTE_0(nop), - PPC_I(DCBT), - X_form, 31, 278, CFLOW_NORMAL - }, - { "dcbtst", - EXECUTE_0(nop), - PPC_I(DCBTST), - X_form, 31, 246, CFLOW_NORMAL - }, - { "dcbz", - EXECUTE_2(dcbz, operand_RA_or_0, operand_RB), - PPC_I(DCBZ), - X_form, 31, 1014, CFLOW_NORMAL - }, - { "divw", - EXECUTE_3(divide, true, OE_BIT_G, RC_BIT_G), - PPC_I(DIVW), - XO_form, 31, 491, CFLOW_NORMAL - }, - { "divwu", - EXECUTE_3(divide, false, OE_BIT_G, RC_BIT_G), - PPC_I(DIVWU), - XO_form, 31, 459, CFLOW_NORMAL - }, - { "dss", - EXECUTE_0(nop), - PPC_I(DSS), - X_form, 31, 822, CFLOW_NORMAL - }, - { "dst", - EXECUTE_0(nop), - PPC_I(DST), - X_form, 31, 342, CFLOW_NORMAL - }, - { "dstst", - EXECUTE_0(nop), - PPC_I(DST), - X_form, 31, 374, CFLOW_NORMAL - }, - { "eciwx", - EXECUTE_0(nop), - PPC_I(ECIWX), - X_form, 31, 310, CFLOW_NORMAL - }, - { "ecowx", - EXECUTE_0(nop), - PPC_I(ECOWX), - X_form, 31, 438, CFLOW_NORMAL - }, - { "eieio", - EXECUTE_0(nop), - PPC_I(EIEIO), - X_form, 31, 854, CFLOW_NORMAL - }, - { "eqv", - EXECUTE_GENERIC_ARITH(eqv, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(EQV), - X_form, 31, 284, CFLOW_NORMAL - }, - { "extsb", - EXECUTE_GENERIC_ARITH(sign_extend_8_32, RA, RS, NONE, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(EXTSB), - X_form, 31, 954, CFLOW_NORMAL - }, - { "extsh", - EXECUTE_GENERIC_ARITH(sign_extend_16_32, RA, RS, NONE, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(EXTSH), - X_form, 31, 922, CFLOW_NORMAL - }, - { "fabs", - EXECUTE_FP_ARITH(double, fabs, RD, RB, NONE, NONE, RC_BIT_G, false), - PPC_I(FABS), - X_form, 63, 264, CFLOW_NORMAL - }, - { "fadd", - EXECUTE_FP_ARITH(double, fadd, RD, RA, RB, NONE, RC_BIT_G, true), - PPC_I(FADD), - A_form, 63, 21, CFLOW_NORMAL - }, - { "fadds", - EXECUTE_FP_ARITH(float, fadd, RD, RA, RB, NONE, RC_BIT_G, true), - PPC_I(FADDS), - A_form, 59, 21, CFLOW_NORMAL - }, - { "fcmpo", - EXECUTE_1(fp_compare, true), - PPC_I(FCMPO), - X_form, 63, 32, CFLOW_NORMAL - }, - { "fcmpu", - EXECUTE_1(fp_compare, false), - PPC_I(FCMPU), - X_form, 63, 0, CFLOW_NORMAL - }, - { "fctiw", - EXECUTE_2(fp_int_convert, operand_FPSCR_RN, RC_BIT_G), - PPC_I(FCTIW), - X_form, 63, 14, CFLOW_NORMAL - }, - { "fctiwz", - EXECUTE_2(fp_int_convert, operand_ONE, RC_BIT_G), - PPC_I(FCTIWZ), - X_form, 63, 15, CFLOW_NORMAL - }, - { "fdiv", - EXECUTE_FP_ARITH(double, fdiv, RD, RA, RB, NONE, RC_BIT_G, true), - PPC_I(FDIV), - A_form, 63, 18, CFLOW_NORMAL - }, - { "fdivs", - EXECUTE_FP_ARITH(float, fdiv, RD, RA, RB, NONE, RC_BIT_G, true), - PPC_I(FDIVS), - A_form, 59, 18, CFLOW_NORMAL - }, - { "fmadd", - EXECUTE_FP_ARITH(double, fmadd, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FMADD), - A_form, 63, 29, CFLOW_NORMAL - }, - { "fmadds", - EXECUTE_FP_ARITH(float, fmadd, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FMADDS), - A_form, 59, 29, CFLOW_NORMAL - }, - { "fmr", - EXECUTE_FP_ARITH(double, fnop, RD, RB, NONE, NONE, RC_BIT_G, false), - PPC_I(FMR), - X_form, 63, 72, CFLOW_NORMAL - }, - { "fmsub", - EXECUTE_FP_ARITH(double, fmsub, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FMSUB), - A_form, 63, 28, CFLOW_NORMAL - }, - { "fmsubs", - EXECUTE_FP_ARITH(float, fmsub, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FMSUBS), - A_form, 59, 28, CFLOW_NORMAL - }, - { "fmul", - EXECUTE_FP_ARITH(double, fmul, RD, RA, RC, NONE, RC_BIT_G, true), - PPC_I(FMUL), - A_form, 63, 25, CFLOW_NORMAL - }, - { "fmuls", - EXECUTE_FP_ARITH(float, fmul, RD, RA, RC, NONE, RC_BIT_G, true), - PPC_I(FMULS), - A_form, 59, 25, CFLOW_NORMAL - }, - { "fnabs", - EXECUTE_FP_ARITH(double, fnabs, RD, RB, NONE, NONE, RC_BIT_G, false), - PPC_I(FNABS), - X_form, 63, 136, CFLOW_NORMAL - }, - { "fneg", - EXECUTE_FP_ARITH(double, fneg, RD, RB, NONE, NONE, RC_BIT_G, false), - PPC_I(FNEG), - X_form, 63, 40, CFLOW_NORMAL - }, - { "fnmadd", - EXECUTE_FP_ARITH(double, fnmadd, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FNMADD), - A_form, 63, 31, CFLOW_NORMAL - }, - { "fnmadds", - EXECUTE_FP_ARITH(double, fnmadds, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FNMADDS), - A_form, 59, 31, CFLOW_NORMAL - }, - { "fnmsub", - EXECUTE_FP_ARITH(double, fnmsub, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FNMSUB), - A_form, 63, 30, CFLOW_NORMAL - }, - { "fnmsubs", - EXECUTE_FP_ARITH(double, fnmsubs, RD, RA, RC, RB, RC_BIT_G, true), - PPC_I(FNMSUBS), - A_form, 59, 30, CFLOW_NORMAL - }, - { "frsp", - EXECUTE_1(fp_round, RC_BIT_G), - PPC_I(FRSP), - X_form, 63, 12, CFLOW_NORMAL - }, - { "fsel", - EXECUTE_FP_ARITH(double, fsel, RD, RA, RC, RB, RC_BIT_G, false), - PPC_I(FSEL), - A_form, 63, 23, CFLOW_NORMAL - }, - { "fsub", - EXECUTE_FP_ARITH(double, fsub, RD, RA, RB, NONE, RC_BIT_G, true), - PPC_I(FSUB), - A_form, 63, 20, CFLOW_NORMAL - }, - { "fsubs", - EXECUTE_FP_ARITH(float, fsub, RD, RA, RB, NONE, RC_BIT_G, true), - PPC_I(FSUBS), - A_form, 59, 20, CFLOW_NORMAL - }, - { "icbi", - EXECUTE_2(icbi, operand_RA_or_0, operand_RB), - PPC_I(ICBI), - X_form, 31, 982, CFLOW_NORMAL - }, - { "isync", - EXECUTE_0(isync), - PPC_I(ISYNC), - X_form, 19, 150, CFLOW_NORMAL - }, - { "lbz", - EXECUTE_LOADSTORE(nop, RA_or_0, D, true, 1, false, false), - PPC_I(LBZ), - D_form, 34, 0, CFLOW_NORMAL - }, - { "lbzu", - EXECUTE_LOADSTORE(nop, RA, D, true, 1, true, false), - PPC_I(LBZU), - D_form, 35, 0, CFLOW_NORMAL - }, - { "lbzux", - EXECUTE_LOADSTORE(nop, RA, RB, true, 1, true, false), - PPC_I(LBZUX), - X_form, 31, 119, CFLOW_NORMAL - }, - { "lbzx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, true, 1, false, false), - PPC_I(LBZX), - X_form, 31, 87, CFLOW_NORMAL - }, - { "lfd", - EXECUTE_FP_LOADSTORE(RA_or_0, D, true, true, false), - PPC_I(LFD), - D_form, 50, 0, CFLOW_NORMAL - }, - { "lfdu", - EXECUTE_FP_LOADSTORE(RA, D, true, true, true), - PPC_I(LFDU), - D_form, 51, 0, CFLOW_NORMAL - }, - { "lfdux", - EXECUTE_FP_LOADSTORE(RA, RB, true, true, true), - PPC_I(LFDUX), - X_form, 31, 631, CFLOW_NORMAL - }, - { "lfdx", - EXECUTE_FP_LOADSTORE(RA_or_0, RB, true, true, false), - PPC_I(LFDX), - X_form, 31, 599, CFLOW_NORMAL - }, - { "lfs", - EXECUTE_FP_LOADSTORE(RA_or_0, D, true, false, false), - PPC_I(LFS), - D_form, 48, 0, CFLOW_NORMAL - }, - { "lfsu", - EXECUTE_FP_LOADSTORE(RA, D, true, false, true), - PPC_I(LFSU), - D_form, 49, 0, CFLOW_NORMAL - }, - { "lfsux", - EXECUTE_FP_LOADSTORE(RA, RB, true, false, true), - PPC_I(LFSUX), - X_form, 31, 567, CFLOW_NORMAL - }, - { "lfsx", - EXECUTE_FP_LOADSTORE(RA_or_0, RB, true, false, false), - PPC_I(LFSX), - X_form, 31, 535, CFLOW_NORMAL - }, - { "lha", - EXECUTE_LOADSTORE(sign_extend_16_32, RA_or_0, D, true, 2, false, false), - PPC_I(LHA), - D_form, 42, 0, CFLOW_NORMAL - }, - { "lhau", - EXECUTE_LOADSTORE(sign_extend_16_32, RA, D, true, 2, true, false), - PPC_I(LHAU), - D_form, 43, 0, CFLOW_NORMAL - }, - { "lhaux", - EXECUTE_LOADSTORE(sign_extend_16_32, RA, RB, true, 2, true, false), - PPC_I(LHAUX), - X_form, 31, 375, CFLOW_NORMAL - }, - { "lhax", - EXECUTE_LOADSTORE(sign_extend_16_32, RA_or_0, RB, true, 2, false, false), - PPC_I(LHAX), - X_form, 31, 343, CFLOW_NORMAL - }, - { "lhbrx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, true, 2, false, true), - PPC_I(LHBRX), - X_form, 31, 790, CFLOW_NORMAL - }, - { "lhz", - EXECUTE_LOADSTORE(nop, RA_or_0, D, true, 2, false, false), - PPC_I(LHZ), - D_form, 40, 0, CFLOW_NORMAL - }, - { "lhzu", - EXECUTE_LOADSTORE(nop, RA, D, true, 2, true, false), - PPC_I(LHZU), - D_form, 41, 0, CFLOW_NORMAL - }, - { "lhzux", - EXECUTE_LOADSTORE(nop, RA, RB, true, 2, true, false), - PPC_I(LHZUX), - X_form, 31, 311, CFLOW_NORMAL - }, - { "lhzx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, true, 2, false, false), - PPC_I(LHZX), - X_form, 31, 279, CFLOW_NORMAL - }, - { "lmw", - EXECUTE_LOADSTORE_MULTIPLE(RA_or_0, D, true), - PPC_I(LMW), - D_form, 46, 0, CFLOW_NORMAL - }, - { "lswi", - EXECUTE_LOAD_STRING(RA_or_0, true, NB), - PPC_I(LSWI), - X_form, 31, 597, CFLOW_NORMAL - }, - { "lswx", - EXECUTE_LOAD_STRING(RA_or_0, false, XER_COUNT), - PPC_I(LSWX), - X_form, 31, 533, CFLOW_NORMAL - }, - { "lvebx", - EXECUTE_VECTOR_LOADSTORE(load, V16QIm, RA_or_0, RB), - PPC_I(LVEBX), - X_form, 31, 7, CFLOW_NORMAL - }, - { "lvehx", - EXECUTE_VECTOR_LOADSTORE(load, V8HIm, RA_or_0, RB), - PPC_I(LVEHX), - X_form, 31, 39, CFLOW_NORMAL - }, - { "lvewx", - EXECUTE_VECTOR_LOADSTORE(load, V4SI, RA_or_0, RB), - PPC_I(LVEWX), - X_form, 31, 71, CFLOW_NORMAL - }, - { "lvsl", - EXECUTE_1(vector_load_for_shift, 1), - PPC_I(LVSL), - X_form, 31, 6, CFLOW_NORMAL - }, - { "lvsr", - EXECUTE_1(vector_load_for_shift, 0), - PPC_I(LVSR), - X_form, 31, 38, CFLOW_NORMAL - }, - { "lvx", - EXECUTE_VECTOR_LOADSTORE(load, V2DI, RA_or_0, RB), - PPC_I(LVX), - X_form, 31, 103, CFLOW_NORMAL - }, - { "lvxl", - EXECUTE_VECTOR_LOADSTORE(load, V2DI, RA_or_0, RB), - PPC_I(LVXL), - X_form, 31, 359, CFLOW_NORMAL - }, - { "lwarx", - EXECUTE_1(lwarx, operand_RA_or_0), - PPC_I(LWARX), - X_form, 31, 20, CFLOW_NORMAL - }, - { "lwbrx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, true, 4, false, true), - PPC_I(LWBRX), - X_form, 31, 534, CFLOW_NORMAL - }, - { "lwz", - EXECUTE_LOADSTORE(nop, RA_or_0, D, true, 4, false, false), - PPC_I(LWZ), - D_form, 32, 0, CFLOW_NORMAL - }, - { "lwzu", - EXECUTE_LOADSTORE(nop, RA, D, true, 4, true, false), - PPC_I(LWZU), - D_form, 33, 0, CFLOW_NORMAL - }, - { "lwzux", - EXECUTE_LOADSTORE(nop, RA, RB, true, 4, true, false), - PPC_I(LWZUX), - X_form, 31, 55, CFLOW_NORMAL - }, - { "lwzx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, true, 4, false, false), - PPC_I(LWZX), - X_form, 31, 23, CFLOW_NORMAL - }, - { "mcrf", - EXECUTE_0(mcrf), - PPC_I(MCRF), - XL_form, 19, 0, CFLOW_NORMAL - }, - { "mcrfs", - EXECUTE_0(mcrfs), - PPC_I(MCRFS), - X_form, 63, 64, CFLOW_NORMAL - }, - { "mcrxr", - EXECUTE_0(mcrxr), - PPC_I(MCRXR), - X_form, 31, 512, CFLOW_NORMAL - }, - { "mfcr", - EXECUTE_GENERIC_ARITH(nop, RD, CR, NONE, NONE, OE_BIT_0, RC_BIT_0), - PPC_I(MFCR), - X_form, 31, 19, CFLOW_NORMAL - }, - { "mffs", - EXECUTE_1(mffs, RC_BIT_G), - PPC_I(MFFS), - X_form, 63, 583, CFLOW_NORMAL - }, - { "mfmsr", - EXECUTE_0(mfmsr), - PPC_I(MFMSR), - X_form, 31, 83, CFLOW_NORMAL - }, - { "mfspr", - EXECUTE_1(mfspr, operand_SPR), - PPC_I(MFSPR), - XFX_form, 31, 339, CFLOW_NORMAL - }, - { "mftb", - EXECUTE_1(mftbr, operand_TBR), - PPC_I(MFTB), - XFX_form, 31, 371, CFLOW_NORMAL - }, - { "mfvscr", - EXECUTE_0(mfvscr), - PPC_I(MFVSCR), - VX_form, 4, 1540, CFLOW_NORMAL - }, - { "mtcrf", - EXECUTE_0(mtcrf), - PPC_I(MTCRF), - XFX_form, 31, 144, CFLOW_NORMAL - }, - { "mtfsb0", - EXECUTE_2(mtfsb, immediate_value<0>, RC_BIT_G), - PPC_I(MTFSB0), - X_form, 63, 70, CFLOW_NORMAL - }, - { "mtfsb1", - EXECUTE_2(mtfsb, immediate_value<1>, RC_BIT_G), - PPC_I(MTFSB1), - X_form, 63, 38, CFLOW_NORMAL - }, - { "mtfsf", - EXECUTE_3(mtfsf, operand_FM, operand_fp_dw_RB, RC_BIT_G), - PPC_I(MTFSF), - XFL_form, 63, 711, CFLOW_NORMAL - }, - { "mtfsfi", - EXECUTE_2(mtfsfi, operand_IMM, RC_BIT_G), - PPC_I(MTFSFI), - X_form, 63, 134, CFLOW_NORMAL - }, - { "mtspr", - EXECUTE_1(mtspr, operand_SPR), - PPC_I(MTSPR), - XFX_form, 31, 467, CFLOW_NORMAL - }, - { "mtvscr", - EXECUTE_0(mtvscr), - PPC_I(MTVSCR), - VX_form, 4, 1604, CFLOW_NORMAL - }, - { "mulhw", - EXECUTE_4(multiply, true, true, OE_BIT_0, RC_BIT_G), - PPC_I(MULHW), - XO_form, 31, 75, CFLOW_NORMAL - }, - { "mulhwu", - EXECUTE_4(multiply, true, false, OE_BIT_0, RC_BIT_G), - PPC_I(MULHWU), - XO_form, 31, 11, CFLOW_NORMAL - }, - { "mulli", - EXECUTE_GENERIC_ARITH(smul, RD, RA, SIMM, NONE, OE_BIT_0, RC_BIT_0), - PPC_I(MULLI), - D_form, 7, 0, CFLOW_NORMAL - }, - { "mullw", - EXECUTE_4(multiply, false, true, OE_BIT_G, RC_BIT_G), - PPC_I(MULLW), - XO_form, 31, 235, CFLOW_NORMAL - }, - { "nand", - EXECUTE_GENERIC_ARITH(nand, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(NAND), - X_form, 31, 476, CFLOW_NORMAL - }, - { "neg", - EXECUTE_GENERIC_ARITH(neg, RD, RA, NONE, NONE, OE_BIT_G, RC_BIT_G), - PPC_I(NEG), - XO_form, 31, 104, CFLOW_NORMAL - }, - { "nor", - EXECUTE_GENERIC_ARITH(nor, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(NOR), - XO_form, 31, 124, CFLOW_NORMAL - }, - { "or", - EXECUTE_GENERIC_ARITH(or, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(OR), - XO_form, 31, 444, CFLOW_NORMAL - }, - { "orc", - EXECUTE_GENERIC_ARITH(orc, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(ORC), - XO_form, 31, 412, CFLOW_NORMAL - }, - { "ori", - EXECUTE_GENERIC_ARITH(or, RA, RS, UIMM, NONE, OE_BIT_0, RC_BIT_0), - PPC_I(ORI), - D_form, 24, 0, CFLOW_NORMAL - }, - { "oris", - EXECUTE_GENERIC_ARITH(or, RA, RS, UIMM_shifted, NONE, OE_BIT_0, RC_BIT_0), - PPC_I(ORIS), - D_form, 25, 0, CFLOW_NORMAL - }, - { "rlwimi", - EXECUTE_3(rlwimi, operand_SH, operand_MASK, RC_BIT_G), - PPC_I(RLWIMI), - M_form, 20, 0, CFLOW_NORMAL - }, - { "rlwinm", - EXECUTE_GENERIC_ARITH(ppc_rlwinm, RA, RS, SH, MASK, OE_BIT_0, RC_BIT_G), - PPC_I(RLWINM), - M_form, 21, 0, CFLOW_NORMAL - }, - { "rlwnm", - EXECUTE_GENERIC_ARITH(ppc_rlwnm, RA, RS, RB, MASK, OE_BIT_0, RC_BIT_G), - PPC_I(RLWNM), - M_form, 23, 0, CFLOW_NORMAL - }, - { "sc", - EXECUTE_0(syscall), - PPC_I(SC), - SC_form, 17, 0, CFLOW_NORMAL - }, - { "slw", - EXECUTE_SHIFT(shll, RA, RS, RB, andi<0x3f>, CA_BIT_0, RC_BIT_G), - PPC_I(SLW), - X_form, 31, 24, CFLOW_NORMAL - }, - { "sraw", - EXECUTE_SHIFT(shra, RA, RS, RB, andi<0x3f>, CA_BIT_1, RC_BIT_G), - PPC_I(SRAW), - X_form, 31, 792, CFLOW_NORMAL - }, - { "srawi", - EXECUTE_SHIFT(shra, RA, RS, SH, andi<0x1f>, CA_BIT_1, RC_BIT_G), - PPC_I(SRAWI), - X_form, 31, 824, CFLOW_NORMAL - }, - { "srw", - EXECUTE_SHIFT(shrl, RA, RS, RB, andi<0x3f>, CA_BIT_0, RC_BIT_G), - PPC_I(SRW), - X_form, 31, 536, CFLOW_NORMAL - }, - { "stb", - EXECUTE_LOADSTORE(nop, RA_or_0, D, false, 1, false, false), - PPC_I(STB), - D_form, 38, 0, CFLOW_NORMAL - }, - { "stbu", - EXECUTE_LOADSTORE(nop, RA, D, false, 1, true, false), - PPC_I(STBU), - D_form, 39, 0, CFLOW_NORMAL - }, - { "stbux", - EXECUTE_LOADSTORE(nop, RA, RB, false, 1, true, false), - PPC_I(STBUX), - X_form, 31, 247, CFLOW_NORMAL - }, - { "stbx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, false, 1, false, false), - PPC_I(STBX), - X_form, 31, 215, CFLOW_NORMAL - }, - { "stfd", - EXECUTE_FP_LOADSTORE(RA_or_0, D, false, true, false), - PPC_I(STFD), - D_form, 54, 0, CFLOW_NORMAL - }, - { "stfdu", - EXECUTE_FP_LOADSTORE(RA, D, false, true, true), - PPC_I(STFDU), - D_form, 55, 0, CFLOW_NORMAL - }, - { "stfdux", - EXECUTE_FP_LOADSTORE(RA, RB, false, true, true), - PPC_I(STFDUX), - X_form, 31, 759, CFLOW_NORMAL - }, - { "stfdx", - EXECUTE_FP_LOADSTORE(RA_or_0, RB, false, true, false), - PPC_I(STFDX), - X_form, 31, 727, CFLOW_NORMAL - }, - { "stfs", - EXECUTE_FP_LOADSTORE(RA_or_0, D, false, false, false), - PPC_I(STFS), - D_form, 52, 0, CFLOW_NORMAL - }, - { "stfsu", - EXECUTE_FP_LOADSTORE(RA, D, false, false, true), - PPC_I(STFSU), - D_form, 53, 0, CFLOW_NORMAL - }, - { "stfsux", - EXECUTE_FP_LOADSTORE(RA, RB, false, false, true), - PPC_I(STFSUX), - X_form, 31, 695, CFLOW_NORMAL - }, - { "stfsx", - EXECUTE_FP_LOADSTORE(RA_or_0, RB, false, false, false), - PPC_I(STFSX), - X_form, 31, 663, CFLOW_NORMAL - }, - { "sth", - EXECUTE_LOADSTORE(nop, RA_or_0, D, false, 2, false, false), - PPC_I(STH), - D_form, 44, 0, CFLOW_NORMAL - }, - { "sthbrx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, false, 2, false, true), - PPC_I(STHBRX), - X_form, 31, 918, CFLOW_NORMAL - }, - { "sthu", - EXECUTE_LOADSTORE(nop, RA, D, false, 2, true, false), - PPC_I(STHU), - D_form, 45, 0, CFLOW_NORMAL - }, - { "sthux", - EXECUTE_LOADSTORE(nop, RA, RB, false, 2, true, false), - PPC_I(STHUX), - X_form, 31, 439, CFLOW_NORMAL - }, - { "sthx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, false, 2, false, false), - PPC_I(STHX), - X_form, 31, 407, CFLOW_NORMAL - }, - { "stmw", - EXECUTE_LOADSTORE_MULTIPLE(RA_or_0, D, false), - PPC_I(STMW), - D_form, 47, 0, CFLOW_NORMAL - }, - { "stswi", - EXECUTE_STORE_STRING(RA_or_0, true, NB), - PPC_I(STSWI), - X_form, 31, 725, CFLOW_NORMAL - }, - { "stswx", - EXECUTE_STORE_STRING(RA_or_0, false, XER_COUNT), - PPC_I(STSWX), - X_form, 31, 661, CFLOW_NORMAL - }, - { "stvebx", - EXECUTE_VECTOR_LOADSTORE(store, V16QIm, RA_or_0, RB), - PPC_I(STVEBX), - X_form, 31, 135, CFLOW_NORMAL - }, - { "stvehx", - EXECUTE_VECTOR_LOADSTORE(store, V8HIm, RA_or_0, RB), - PPC_I(STVEHX), - X_form, 31, 167, CFLOW_NORMAL - }, - { "stvewx", - EXECUTE_VECTOR_LOADSTORE(store, V4SI, RA_or_0, RB), - PPC_I(STVEWX), - X_form, 31, 199, CFLOW_NORMAL - }, - { "stvx", - EXECUTE_VECTOR_LOADSTORE(store, V2DI, RA_or_0, RB), - PPC_I(STVX), - X_form, 31, 231, CFLOW_NORMAL - }, - { "stvxl", - EXECUTE_VECTOR_LOADSTORE(store, V2DI, RA_or_0, RB), - PPC_I(STVXL), - X_form, 31, 487, CFLOW_NORMAL - }, - { "stw", - EXECUTE_LOADSTORE(nop, RA_or_0, D, false, 4, false, false), - PPC_I(STW), - D_form, 36, 0, CFLOW_NORMAL - }, - { "stwbrx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, false, 4, false, true), - PPC_I(STWBRX), - X_form, 31, 662, CFLOW_NORMAL - }, - { "stwcx.", - EXECUTE_1(stwcx, operand_RA_or_0), - PPC_I(STWCX), - X_form, 31, 150, CFLOW_NORMAL - }, - { "stwu", - EXECUTE_LOADSTORE(nop, RA, D, false, 4, true, false), - PPC_I(STWU), - D_form, 37, 0, CFLOW_NORMAL - }, - { "stwux", - EXECUTE_LOADSTORE(nop, RA, RB, false, 4, true, false), - PPC_I(STWUX), - X_form, 31, 183, CFLOW_NORMAL - }, - { "stwx", - EXECUTE_LOADSTORE(nop, RA_or_0, RB, false, 4, false, false), - PPC_I(STWX), - X_form, 31, 151, CFLOW_NORMAL - }, - { "subf", - EXECUTE_ADDITION(RA_compl, RB, ONE, CA_BIT_0, OE_BIT_G, RC_BIT_G), - PPC_I(SUBF), - XO_form, 31, 40, CFLOW_NORMAL - }, - { "subfc", - EXECUTE_ADDITION(RA_compl, RB, ONE, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(SUBFC), - XO_form, 31, 8, CFLOW_NORMAL - }, - { "subfe", - EXECUTE_ADDITION(RA_compl, RB, XER_CA, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(SUBFE), - XO_form, 31, 136, CFLOW_NORMAL - }, - { "subfic", - EXECUTE_ADDITION(RA_compl, SIMM, ONE, CA_BIT_1, OE_BIT_0, RC_BIT_0), - PPC_I(SUBFIC), - D_form, 8, 0, CFLOW_NORMAL - }, - { "subfme", - EXECUTE_ADDITION(RA_compl, XER_CA, MINUS_ONE, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(SUBFME), - XO_form, 31, 232, CFLOW_NORMAL - }, - { "subfze", - EXECUTE_ADDITION(RA_compl, XER_CA, ZERO, CA_BIT_1, OE_BIT_G, RC_BIT_G), - PPC_I(SUBFZE), - XO_form, 31, 200, CFLOW_NORMAL - }, - { "sync", - EXECUTE_0(nop), - PPC_I(SYNC), - X_form, 31, 598, CFLOW_NORMAL - }, - { "xor", - EXECUTE_GENERIC_ARITH(xor, RA, RS, RB, NONE, OE_BIT_0, RC_BIT_G), - PPC_I(XOR), - X_form, 31, 316, CFLOW_NORMAL - }, - { "xori", - EXECUTE_GENERIC_ARITH(xor, RA, RS, UIMM, NONE, OE_BIT_0, RC_BIT_0), - PPC_I(XORI), - D_form, 26, 0, CFLOW_NORMAL - }, - { "xoris", - EXECUTE_GENERIC_ARITH(xor, RA, RS, UIMM_shifted, NONE, OE_BIT_0, RC_BIT_0), - PPC_I(XORIS), - D_form, 27, 0, CFLOW_NORMAL - }, - { "vaddcuw", - EXECUTE_VECTOR_ARITH(addcuw, V4SI, V4SI, V4SI, NONE), - PPC_I(VADDCUW), - VX_form, 4, 384, CFLOW_NORMAL - }, - { "vaddfp", - EXECUTE_VECTOR_ARITH(fadds, V4SF, V4SF, V4SF, NONE), - PPC_I(VADDFP), - VX_form, 4, 10, CFLOW_NORMAL - }, - { "vaddsbs", - EXECUTE_VECTOR_ARITH(add, V16QI_SAT, V16QI_SAT, V16QI_SAT, NONE), - PPC_I(VADDSBS), - VX_form, 4, 768, CFLOW_NORMAL - }, - { "vaddshs", - EXECUTE_VECTOR_ARITH(add, V8HI_SAT, V8HI_SAT, V8HI_SAT, NONE), - PPC_I(VADDSHS), - VX_form, 4, 832, CFLOW_NORMAL - }, - { "vaddsws", - EXECUTE_VECTOR_ARITH(add_64, V4SI_SAT, V4SI_SAT, V4SI_SAT, NONE), - PPC_I(VADDSWS), - VX_form, 4, 896, CFLOW_NORMAL - }, - { "vaddubm", - EXECUTE_VECTOR_ARITH(add, V16QI, V16QI, V16QI, NONE), - PPC_I(VADDUBM), - VX_form, 4, 0, CFLOW_NORMAL - }, - { "vaddubs", - EXECUTE_VECTOR_ARITH(add, V16QI_SAT, V16QI_SAT, V16QI_SAT, NONE), - PPC_I(VADDUBS), - VX_form, 4, 512, CFLOW_NORMAL - }, - { "vadduhm", - EXECUTE_VECTOR_ARITH(add, V8HI, V8HI, V8HI, NONE), - PPC_I(VADDUHM), - VX_form, 4, 64, CFLOW_NORMAL - }, - { "vadduhs", - EXECUTE_VECTOR_ARITH(add, V8HI_SAT, V8HI_SAT, V8HI_SAT, NONE), - PPC_I(VADDUHS), - VX_form, 4, 576, CFLOW_NORMAL - }, - { "vadduwm", - EXECUTE_VECTOR_ARITH(add, V4SI, V4SI, V4SI, NONE), - PPC_I(VADDUWM), - VX_form, 4, 128, CFLOW_NORMAL - }, - { "vadduws", - EXECUTE_VECTOR_ARITH(add_64, V4SI_SAT, V4SI_SAT, V4SI_SAT, NONE), - PPC_I(VADDUWS), - VX_form, 4, 640, CFLOW_NORMAL - }, - { "vand", - EXECUTE_VECTOR_ARITH(and_64, V2DI, V2DI, V2DI, NONE), - PPC_I(VAND), - VX_form, 4, 1028, CFLOW_NORMAL - }, - { "vandc", - EXECUTE_VECTOR_ARITH(andc_64, V2DI, V2DI, V2DI, NONE), - PPC_I(VANDC), - VX_form, 4, 1092, CFLOW_NORMAL - }, - { "vavgsb", - EXECUTE_VECTOR_ARITH(avgsb, V16QI, V16QI, V16QI, NONE), - PPC_I(VAVGSB), - VX_form, 4, 1282, CFLOW_NORMAL - }, - { "vavgsh", - EXECUTE_VECTOR_ARITH(avgsh, V8HI, V8HI, V8HI, NONE), - PPC_I(VAVGSH), - VX_form, 4, 1346, CFLOW_NORMAL - }, - { "vavgsw", - EXECUTE_VECTOR_ARITH(avgsw, V4SI, V4SI, V4SI, NONE), - PPC_I(VAVGSW), - VX_form, 4, 1410, CFLOW_NORMAL - }, - { "vavgub", - EXECUTE_VECTOR_ARITH(avgub, V16QI, V16QI, V16QI, NONE), - PPC_I(VAVGUB), - VX_form, 4, 1026, CFLOW_NORMAL - }, - { "vavguh", - EXECUTE_VECTOR_ARITH(avguh, V8HI, V8HI, V8HI, NONE), - PPC_I(VAVGUH), - VX_form, 4, 1090, CFLOW_NORMAL - }, - { "vavguw", - EXECUTE_VECTOR_ARITH(avguw, V4SI, V4SI, V4SI, NONE), - PPC_I(VAVGUW), - VX_form, 4, 1154, CFLOW_NORMAL - }, - { "vcfsx", - EXECUTE_VECTOR_ARITH(cvt_si2fp, V4SF, UIMM, V4SIs, NONE), - PPC_I(VCFSX), - VX_form, 4, 842, CFLOW_NORMAL - }, - { "vcfux", - EXECUTE_VECTOR_ARITH(cvt_si2fp, V4SF, UIMM, V4SI, NONE), - PPC_I(VCFUX), - VX_form, 4, 778, CFLOW_NORMAL - }, - { "vcmpbfp", - EXECUTE_VECTOR_COMPARE(cmpbfp, V4SI, V4SF, V4SF, 0), - PPC_I(VCMPBFP), - VXR_form, 4, 966, CFLOW_NORMAL - }, - { "vcmpeqfp", - EXECUTE_VECTOR_COMPARE(cmp_eq, V4SI, V4SF, V4SF, 1), - PPC_I(VCMPEQFP), - VXR_form, 4, 198, CFLOW_NORMAL - }, - { "vcmpequb", - EXECUTE_VECTOR_COMPARE(cmp_eq, V16QI, V16QI, V16QI, 1), - PPC_I(VCMPEQUB), - VXR_form, 4, 6, CFLOW_NORMAL - }, - { "vcmpequh", - EXECUTE_VECTOR_COMPARE(cmp_eq, V8HI, V8HI, V8HI, 1), - PPC_I(VCMPEQUH), - VXR_form, 4, 70, CFLOW_NORMAL - }, - { "vcmpequw", - EXECUTE_VECTOR_COMPARE(cmp_eq, V4SI, V4SI, V4SI, 1), - PPC_I(VCMPEQUW), - VXR_form, 4, 134, CFLOW_NORMAL - }, - { "vcmpgefp", - EXECUTE_VECTOR_COMPARE(cmp_ge, V4SI, V4SF, V4SF, 1), - PPC_I(VCMPGEFP), - VXR_form, 4, 454, CFLOW_NORMAL - }, - { "vcmpgtfp", - EXECUTE_VECTOR_COMPARE(cmp_gt, V4SI, V4SF, V4SF, 1), - PPC_I(VCMPGTFP), - VXR_form, 4, 710, CFLOW_NORMAL - }, - { "vcmpgtsb", - EXECUTE_VECTOR_COMPARE(cmp_gt, V16QI, V16QIs, V16QIs, 1), - PPC_I(VCMPGTSB), - VXR_form, 4, 774, CFLOW_NORMAL - }, - { "vcmpgtsh", - EXECUTE_VECTOR_COMPARE(cmp_gt, V8HI, V8HIs, V8HIs, 1), - PPC_I(VCMPGTSH), - VXR_form, 4, 838, CFLOW_NORMAL - }, - { "vcmpgtsw", - EXECUTE_VECTOR_COMPARE(cmp_gt, V4SI, V4SIs, V4SIs, 1), - PPC_I(VCMPGTSW), - VXR_form, 4, 902, CFLOW_NORMAL - }, - { "vcmpgtub", - EXECUTE_VECTOR_COMPARE(cmp_gt, V16QI, V16QI, V16QI, 1), - PPC_I(VCMPGTUB), - VXR_form, 4, 518, CFLOW_NORMAL - }, - { "vcmpgtuh", - EXECUTE_VECTOR_COMPARE(cmp_gt, V8HI, V8HI, V8HI, 1), - PPC_I(VCMPGTUH), - VXR_form, 4, 582, CFLOW_NORMAL - }, - { "vcmpgtuw", - EXECUTE_VECTOR_COMPARE(cmp_gt, V4SI, V4SI, V4SI, 1), - PPC_I(VCMPGTUW), - VXR_form, 4, 646, CFLOW_NORMAL - }, - { "vctsxs", - EXECUTE_VECTOR_ARITH(cvt_fp2si, V4SI_SAT, UIMM, V4SF, NONE), - PPC_I(VCTSXS), - VX_form, 4, 970, CFLOW_NORMAL - }, - { "vctuxs", - EXECUTE_VECTOR_ARITH(cvt_fp2si, V4SI_SAT, UIMM, V4SF, NONE), - PPC_I(VCTUXS), - VX_form, 4, 906, CFLOW_NORMAL - }, - { "vexptefp", - EXECUTE_VECTOR_ARITH(exp2, V4SF, NONE, V4SF, NONE), - PPC_I(VEXPTEFP), - VX_form, 4, 394, CFLOW_NORMAL - }, - { "vlogefp", - EXECUTE_VECTOR_ARITH(log2, V4SF, NONE, V4SF, NONE), - PPC_I(VLOGEFP), - VX_form, 4, 458, CFLOW_NORMAL - }, - { "vmaddfp", - EXECUTE_VECTOR_ARITH(vmaddfp, V4SF, V4SF, V4SF, V4SF), - PPC_I(VMADDFP), - VA_form, 4, 46, CFLOW_NORMAL - }, - { "vmaxfp", - EXECUTE_VECTOR_ARITH(max, V4SF, V4SF, V4SF, NONE), - PPC_I(VMAXFP), - VX_form, 4, 1034, CFLOW_NORMAL - }, - { "vmaxsb", - EXECUTE_VECTOR_ARITH(max, V16QI, V16QI, V16QI, NONE), - PPC_I(VMAXSB), - VX_form, 4, 258, CFLOW_NORMAL - }, - { "vmaxsh", - EXECUTE_VECTOR_ARITH(max, V8HI, V8HI, V8HI, NONE), - PPC_I(VMAXSH), - VX_form, 4, 322, CFLOW_NORMAL - }, - { "vmaxsw", - EXECUTE_VECTOR_ARITH(max, V4SI, V4SI, V4SI, NONE), - PPC_I(VMAXSW), - VX_form, 4, 386, CFLOW_NORMAL - }, - { "vmaxub", - EXECUTE_VECTOR_ARITH(max, V16QI, V16QI, V16QI, NONE), - PPC_I(VMAXUB), - VX_form, 4, 2, CFLOW_NORMAL - }, - { "vmaxuh", - EXECUTE_VECTOR_ARITH(max, V8HI, V8HI, V8HI, NONE), - PPC_I(VMAXUH), - VX_form, 4, 66, CFLOW_NORMAL - }, - { "vmaxuw", - EXECUTE_VECTOR_ARITH(max, V4SI, V4SI, V4SI, NONE), - PPC_I(VMAXUW), - VX_form, 4, 130, CFLOW_NORMAL - }, - { "vmhaddshs", - EXECUTE_VECTOR_ARITH(mhraddsh<0>, V8HI_SAT, V8HI_SAT, V8HI_SAT, V8HI_SAT), - PPC_I(VMHADDSHS), - VA_form, 4, 32, CFLOW_NORMAL - }, - { "vmhraddshs", - EXECUTE_VECTOR_ARITH(mhraddsh<0x4000>, V8HI_SAT, V8HI_SAT, V8HI_SAT, V8HI_SAT), - PPC_I(VMHRADDSHS), - VA_form, 4, 33, CFLOW_NORMAL - }, - { "vminfp", - EXECUTE_VECTOR_ARITH(min, V4SF, V4SF, V4SF, NONE), - PPC_I(VMINFP), - VX_form, 4, 1098, CFLOW_NORMAL - }, - { "vminsb", - EXECUTE_VECTOR_ARITH(min, V16QI, V16QI, V16QI, NONE), - PPC_I(VMINSB), - VX_form, 4, 770, CFLOW_NORMAL - }, - { "vminsh", - EXECUTE_VECTOR_ARITH(min, V8HI, V8HI, V8HI, NONE), - PPC_I(VMINSH), - VX_form, 4, 834, CFLOW_NORMAL - }, - { "vminsw", - EXECUTE_VECTOR_ARITH(min, V4SI, V4SI, V4SI, NONE), - PPC_I(VMINSW), - VX_form, 4, 898, CFLOW_NORMAL - }, - { "vminub", - EXECUTE_VECTOR_ARITH(min, V16QI, V16QI, V16QI, NONE), - PPC_I(VMINUB), - VX_form, 4, 514, CFLOW_NORMAL - }, - { "vminuh", - EXECUTE_VECTOR_ARITH(min, V8HI, V8HI, V8HI, NONE), - PPC_I(VMINUH), - VX_form, 4, 578, CFLOW_NORMAL - }, - { "vminuw", - EXECUTE_VECTOR_ARITH(min, V4SI, V4SI, V4SI, NONE), - PPC_I(VMINUW), - VX_form, 4, 642, CFLOW_NORMAL - }, - { "vmladduhm", - EXECUTE_VECTOR_ARITH(mladduh, V8HI, V8HI, V8HI, V8HI), - PPC_I(VMLADDUHM), - VA_form, 4, 34, CFLOW_NORMAL - }, - { "vmrghb", - EXECUTE_VECTOR_MERGE(V16QIm, V16QIm, V16QIm, 0), - PPC_I(VMRGHB), - VX_form, 4, 12, CFLOW_NORMAL - }, - { "vmrghh", - EXECUTE_VECTOR_MERGE(V8HIm, V8HIm, V8HIm, 0), - PPC_I(VMRGHH), - VX_form, 4, 76, CFLOW_NORMAL - }, - { "vmrghw", - EXECUTE_VECTOR_MERGE(V4SI, V4SI, V4SI, 0), - PPC_I(VMRGHW), - VX_form, 4, 140, CFLOW_NORMAL - }, - { "vmrglb", - EXECUTE_VECTOR_MERGE(V16QIm, V16QIm, V16QIm, 1), - PPC_I(VMRGLB), - VX_form, 4, 268, CFLOW_NORMAL - }, - { "vmrglh", - EXECUTE_VECTOR_MERGE(V8HIm, V8HIm, V8HIm, 1), - PPC_I(VMRGLH), - VX_form, 4, 332, CFLOW_NORMAL - }, - { "vmrglw", - EXECUTE_VECTOR_MERGE(V4SI, V4SI, V4SI, 1), - PPC_I(VMRGLW), - VX_form, 4, 396, CFLOW_NORMAL - }, - { "vmsummbm", - EXECUTE_VECTOR_ARITH_MIXED(smul, V4SI, V16QI_SAT, V16QI_SAT, V4SI), - PPC_I(VMSUMMBM), - VA_form, 4, 37, CFLOW_NORMAL - }, - { "vmsumshm", - EXECUTE_VECTOR_ARITH_MIXED(smul, V4SI, V8HI_SAT, V8HI_SAT, V4SI), - PPC_I(VMSUMSHM), - VA_form, 4, 40, CFLOW_NORMAL - }, - { "vmsumshs", - EXECUTE_VECTOR_ARITH_MIXED(smul_64, V4SI_SAT, V8HI_SAT, V8HI_SAT, V4SIs), - PPC_I(VMSUMSHS), - VA_form, 4, 41, CFLOW_NORMAL - }, - { "vmsumubm", - EXECUTE_VECTOR_ARITH_MIXED(mul, V4SI, V16QI, V16QI, V4SI), - PPC_I(VMSUMUBM), - VA_form, 4, 36, CFLOW_NORMAL - }, - { "vmsumuhm", - EXECUTE_VECTOR_ARITH_MIXED(mul, V4SI, V8HI, V8HI, V4SI), - PPC_I(VMSUMUHM), - VA_form, 4, 38, CFLOW_NORMAL - }, - { "vmsumuhs", - EXECUTE_VECTOR_ARITH_MIXED(mul, V4SI_SAT, V8HI, V8HI, V4SI), - PPC_I(VMSUMUHS), - VA_form, 4, 39, CFLOW_NORMAL - }, - { "vmulesb", - EXECUTE_VECTOR_ARITH_ODD(0, smul, V8HIm, V16QIm_SAT, V16QIm_SAT, NONE), - PPC_I(VMULESB), - VX_form, 4, 776, CFLOW_NORMAL - }, - { "vmulesh", - EXECUTE_VECTOR_ARITH_ODD(0, smul, V4SI, V8HIm_SAT, V8HIm_SAT, NONE), - PPC_I(VMULESH), - VX_form, 4, 840, CFLOW_NORMAL - }, - { "vmuleub", - EXECUTE_VECTOR_ARITH_ODD(0, mul, V8HIm, V16QIm, V16QIm, NONE), - PPC_I(VMULEUB), - VX_form, 4, 520, CFLOW_NORMAL - }, - { "vmuleuh", - EXECUTE_VECTOR_ARITH_ODD(0, mul, V4SI, V8HIm, V8HIm, NONE), - PPC_I(VMULEUH), - VX_form, 4, 584, CFLOW_NORMAL - }, - { "vmulosb", - EXECUTE_VECTOR_ARITH_ODD(1, smul, V8HIm, V16QIm_SAT, V16QIm_SAT, NONE), - PPC_I(VMULOSB), - VX_form, 4, 264, CFLOW_NORMAL - }, - { "vmulosh", - EXECUTE_VECTOR_ARITH_ODD(1, smul, V4SI, V8HIm_SAT, V8HIm_SAT, NONE), - PPC_I(VMULOSH), - VX_form, 4, 328, CFLOW_NORMAL - }, - { "vmuloub", - EXECUTE_VECTOR_ARITH_ODD(1, mul, V8HIm, V16QIm, V16QIm, NONE), - PPC_I(VMULOUB), - VX_form, 4, 8, CFLOW_NORMAL - }, - { "vmulouh", - EXECUTE_VECTOR_ARITH_ODD(1, mul, V4SI, V8HIm, V8HIm, NONE), - PPC_I(VMULOUH), - VX_form, 4, 72, CFLOW_NORMAL - }, - { "vnmsubfp", - EXECUTE_VECTOR_ARITH(vnmsubfp, V4SF, V4SF, V4SF, V4SF), - PPC_I(VNMSUBFP), - VA_form, 4, 47, CFLOW_NORMAL - }, - { "vnor", - EXECUTE_VECTOR_ARITH(nor_64, V2DI, V2DI, V2DI, NONE), - PPC_I(VNOR), - VX_form, 4, 1284, CFLOW_NORMAL - }, - { "vor", - EXECUTE_VECTOR_ARITH(or_64, V2DI, V2DI, V2DI, NONE), - PPC_I(VOR), - VX_form, 4, 1156, CFLOW_NORMAL - }, - { "vperm", - EXECUTE_0(vector_permute), - PPC_I(VPERM), - VA_form, 4, 43, CFLOW_NORMAL - }, - { "vpkpx", - EXECUTE_0(vector_pack_pixel), - PPC_I(VPKPX), - VX_form, 4, 782, CFLOW_NORMAL - }, - { "vpkshss", - EXECUTE_VECTOR_PACK(V16QIm_SAT, V8HIm, V8HIm), - PPC_I(VPKSHSS), - VX_form, 4, 398, CFLOW_NORMAL - }, - { "vpkshus", - EXECUTE_VECTOR_PACK(V16QIm_SAT, V8HIm, V8HIm), - PPC_I(VPKSHUS), - VX_form, 4, 270, CFLOW_NORMAL - }, - { "vpkswss", - EXECUTE_VECTOR_PACK(V8HIm_SAT, V4SI, V4SI), - PPC_I(VPKSWSS), - VX_form, 4, 462, CFLOW_NORMAL - }, - { "vpkswus", - EXECUTE_VECTOR_PACK(V8HIm_SAT, V4SI, V4SI), - PPC_I(VPKSWUS), - VX_form, 4, 334, CFLOW_NORMAL - }, - { "vpkuhum", - EXECUTE_VECTOR_PACK(V16QIm, V8HIm, V8HIm), - PPC_I(VPKUHUM), - VX_form, 4, 14, CFLOW_NORMAL - }, - { "vpkuhus", - EXECUTE_VECTOR_PACK(V16QIm_USAT, V8HIm, V8HIm), - PPC_I(VPKUHUS), - VX_form, 4, 142, CFLOW_NORMAL - }, - { "vpkuwum", - EXECUTE_VECTOR_PACK(V8HIm, V4SI, V4SI), - PPC_I(VPKUWUM), - VX_form, 4, 78, CFLOW_NORMAL - }, - { "vpkuwus", - EXECUTE_VECTOR_PACK(V8HIm_USAT, V4SI, V4SI), - PPC_I(VPKUWUS), - VX_form, 4, 206, CFLOW_NORMAL - }, - { "vrefp", - EXECUTE_VECTOR_ARITH(fres, V4SF, NONE, V4SF, NONE), - PPC_I(VREFP), - VX_form, 4, 266, CFLOW_NORMAL - }, - { "vrfim", - EXECUTE_VECTOR_ARITH(frsim, V4SF, NONE, V4SF, NONE), - PPC_I(VRFIM), - VX_form, 4, 714, CFLOW_NORMAL - }, - { "vrfin", - EXECUTE_VECTOR_ARITH(frsin, V4SF, NONE, V4SF, NONE), - PPC_I(VRFIN), - VX_form, 4, 522, CFLOW_NORMAL - }, - { "vrfip", - EXECUTE_VECTOR_ARITH(frsip, V4SF, NONE, V4SF, NONE), - PPC_I(VRFIP), - VX_form, 4, 650, CFLOW_NORMAL - }, - { "vrfiz", - EXECUTE_VECTOR_ARITH(frsiz, V4SF, NONE, V4SF, NONE), - PPC_I(VRFIZ), - VX_form, 4, 586, CFLOW_NORMAL - }, - { "vrlb", - EXECUTE_VECTOR_ARITH(vrl, V16QI, V16QI, V16QI, NONE), - PPC_I(VRLB), - VX_form, 4, 4, CFLOW_NORMAL - }, - { "vrlh", - EXECUTE_VECTOR_ARITH(vrl, V8HI, V8HI, V8HI, NONE), - PPC_I(VRLH), - VX_form, 4, 68, CFLOW_NORMAL - }, - { "vrlw", - EXECUTE_VECTOR_ARITH(vrl, V4SI, V4SI, V4SI, NONE), - PPC_I(VRLW), - VX_form, 4, 132, CFLOW_NORMAL - }, - { "vrsqrtefp", - EXECUTE_VECTOR_ARITH(frsqrt, V4SF, NONE, V4SF, NONE), - PPC_I(VRSQRTEFP), - VX_form, 4, 330, CFLOW_NORMAL - }, - { "vsel", - EXECUTE_VECTOR_ARITH(vsel, V4SI, V4SI, V4SI, V4SI), - PPC_I(VSEL), - VA_form, 4, 42, CFLOW_NORMAL - }, - { "vsl", - EXECUTE_1(vector_shift, -1), - PPC_I(VSL), - VX_form, 4, 452, CFLOW_NORMAL - }, - { "vslb", - EXECUTE_VECTOR_ARITH(vsl, V16QI, V16QI, V16QI, NONE), - PPC_I(VSLB), - VX_form, 4, 260, CFLOW_NORMAL - }, - { "vsldoi", - EXECUTE_VECTOR_SHIFT_OCTET(-1, V16QIm, V16QIm, V16QIm, SHB), - PPC_I(VSLDOI), - VA_form, 4, 44, CFLOW_NORMAL - }, - { "vslh", - EXECUTE_VECTOR_ARITH(vsl, V8HI, V8HI, V8HI, NONE), - PPC_I(VSLH), - VX_form, 4, 324, CFLOW_NORMAL - }, - { "vslo", - EXECUTE_VECTOR_SHIFT_OCTET(-1, V16QIm, V16QIm, NONE, SHBO), - PPC_I(VSLO), - VX_form, 4, 1036, CFLOW_NORMAL - }, - { "vslw", - EXECUTE_VECTOR_ARITH(vsl, V4SI, V4SI, V4SI, NONE), - PPC_I(VSLW), - VX_form, 4, 388, CFLOW_NORMAL - }, - { "vspltb", - EXECUTE_VECTOR_SPLAT(nop, V16QI, V16QIm, false), - PPC_I(VSPLTB), - VX_form, 4, 524, CFLOW_NORMAL - }, - { "vsplth", - EXECUTE_VECTOR_SPLAT(nop, V8HI, V8HIm, false), - PPC_I(VSPLTH), - VX_form, 4, 588, CFLOW_NORMAL - }, - { "vspltisb", - EXECUTE_VECTOR_SPLAT(sign_extend_5_32, V16QI, UIMM, true), - PPC_I(VSPLTISB), - VX_form, 4, 780, CFLOW_NORMAL - }, - { "vspltish", - EXECUTE_VECTOR_SPLAT(sign_extend_5_32, V8HI, UIMM, true), - PPC_I(VSPLTISH), - VX_form, 4, 844, CFLOW_NORMAL - }, - { "vspltisw", - EXECUTE_VECTOR_SPLAT(sign_extend_5_32, V4SI, UIMM, true), - PPC_I(VSPLTISW), - VX_form, 4, 908, CFLOW_NORMAL - }, - { "vspltw", - EXECUTE_VECTOR_SPLAT(nop, V4SI, V4SI, false), - PPC_I(VSPLTW), - VX_form, 4, 652, CFLOW_NORMAL - }, - { "vsr", - EXECUTE_1(vector_shift, +1), - PPC_I(VSR), - VX_form, 4, 708, CFLOW_NORMAL - }, - { "vsrab", - EXECUTE_VECTOR_ARITH(vsr, V16QI, V16QIs, V16QI, NONE), - PPC_I(VSRAB), - VX_form, 4, 772, CFLOW_NORMAL - }, - { "vsrah", - EXECUTE_VECTOR_ARITH(vsr, V8HI, V8HIs, V8HI, NONE), - PPC_I(VSRAH), - VX_form, 4, 836, CFLOW_NORMAL - }, - { "vsraw", - EXECUTE_VECTOR_ARITH(vsr, V4SI, V4SIs, V4SIs, NONE), - PPC_I(VSRAW), - VX_form, 4, 900, CFLOW_NORMAL - }, - { "vsrb", - EXECUTE_VECTOR_ARITH(vsr, V16QI, V16QI, V16QI, NONE), - PPC_I(VSRB), - VX_form, 4, 516, CFLOW_NORMAL - }, - { "vsrh", - EXECUTE_VECTOR_ARITH(vsr, V8HI, V8HI, V8HI, NONE), - PPC_I(VSRH), - VX_form, 4, 580, CFLOW_NORMAL - }, - { "vsro", - EXECUTE_VECTOR_SHIFT_OCTET(+1, V16QIm, V16QIm, NONE, SHBO), - PPC_I(VSRO), - VX_form, 4, 1100, CFLOW_NORMAL - }, - { "vsrw", - EXECUTE_VECTOR_ARITH(vsr, V4SI, V4SI, V4SI, NONE), - PPC_I(VSRW), - VX_form, 4, 644, CFLOW_NORMAL - }, - { "vsubcuw", - EXECUTE_VECTOR_ARITH(subcuw, V4SI, V4SI, V4SI, NONE), - PPC_I(VSUBCUW), - VX_form, 4, 1408, CFLOW_NORMAL - }, - { "vsubfp", - EXECUTE_VECTOR_ARITH(fsubs, V4SF, V4SF, V4SF, NONE), - PPC_I(VSUBFP), - VX_form, 4, 74, CFLOW_NORMAL - }, - { "vsubsbs", - EXECUTE_VECTOR_ARITH(sub, V16QI_SAT, V16QI_SAT, V16QI_SAT, NONE), - PPC_I(VSUBSBS), - VX_form, 4, 1792, CFLOW_NORMAL - }, - { "vsubshs", - EXECUTE_VECTOR_ARITH(sub, V8HI_SAT, V8HI_SAT, V8HI_SAT, NONE), - PPC_I(VSUBSHS), - VX_form, 4, 1856, CFLOW_NORMAL - }, - { "vsubsws", - EXECUTE_VECTOR_ARITH(sub_64, V4SI_SAT, V4SI_SAT, V4SI_SAT, NONE), - PPC_I(VSUBSWS), - VX_form, 4, 1920, CFLOW_NORMAL - }, - { "vsububm", - EXECUTE_VECTOR_ARITH(sub, V16QI, V16QI, V16QI, NONE), - PPC_I(VSUBUBM), - VX_form, 4, 1024, CFLOW_NORMAL - }, - { "vsububs", - EXECUTE_VECTOR_ARITH(sub, V16QI_SAT, V16QI_SAT, V16QI_SAT, NONE), - PPC_I(VSUBUBS), - VX_form, 4, 1536, CFLOW_NORMAL - }, - { "vsubuhm", - EXECUTE_VECTOR_ARITH(sub, V8HI, V8HI, V8HI, NONE), - PPC_I(VSUBUHM), - VX_form, 4, 1088, CFLOW_NORMAL - }, - { "vsubuhs", - EXECUTE_VECTOR_ARITH(sub, V8HI_SAT, V8HI_SAT, V8HI_SAT, NONE), - PPC_I(VSUBUHS), - VX_form, 4, 1600, CFLOW_NORMAL - }, - { "vsubuwm", - EXECUTE_VECTOR_ARITH(sub, V4SI, V4SI, V4SI, NONE), - PPC_I(VSUBUWM), - VX_form, 4, 1152, CFLOW_NORMAL - }, - { "vsubuws", - EXECUTE_VECTOR_ARITH(sub_64, V4SI_SAT, V4SI_SAT, V4SI_SAT, NONE), - PPC_I(VSUBUWS), - VX_form, 4, 1664, CFLOW_NORMAL - }, - { "vsumsws", - EXECUTE_VECTOR_SUM(1, V4SI_SAT, V4SIs, V4SIs), - PPC_I(VSUMSWS), - VX_form, 4, 1928, CFLOW_NORMAL - }, - { "vsum2sws", - EXECUTE_VECTOR_SUM(2, V4SI_SAT, V4SIs, V4SIs), - PPC_I(VSUM2SWS), - VX_form, 4, 1672, CFLOW_NORMAL - }, - { "vsum4sbs", - EXECUTE_VECTOR_SUM(4, V4SI_SAT, V16QIs, V4SIs), - PPC_I(VSUM4SBS), - VX_form, 4, 1800, CFLOW_NORMAL - }, - { "vsum4shs", - EXECUTE_VECTOR_SUM(4, V4SI_SAT, V8HIs, V4SIs), - PPC_I(VSUM4SHS), - VX_form, 4, 1608, CFLOW_NORMAL - }, - { "vsum4ubs", - EXECUTE_VECTOR_SUM(4, V4SI_SAT, V16QI, V4SI), - PPC_I(VSUM4UBS), - VX_form, 4, 1544, CFLOW_NORMAL - }, - { "vupkhpx", - EXECUTE_1(vector_unpack_pixel, 0), - PPC_I(VUPKHPX), - VX_form, 4, 846, CFLOW_NORMAL - }, - { "vupkhsb", - EXECUTE_VECTOR_UNPACK(0, V8HIms, V16QIms), - PPC_I(VUPKHSB), - VX_form, 4, 526, CFLOW_NORMAL - }, - { "vupkhsh", - EXECUTE_VECTOR_UNPACK(0, V4SIs, V8HIms), - PPC_I(VUPKHSH), - VX_form, 4, 590, CFLOW_NORMAL - }, - { "vupklpx", - EXECUTE_1(vector_unpack_pixel, 1), - PPC_I(VUPKLPX), - VX_form, 4, 974, CFLOW_NORMAL - }, - { "vupklsb", - EXECUTE_VECTOR_UNPACK(1, V8HIms, V16QIms), - PPC_I(VUPKLSB), - VX_form, 4, 654, CFLOW_NORMAL - }, - { "vupklsh", - EXECUTE_VECTOR_UNPACK(1, V4SIs, V8HIms), - PPC_I(VUPKLSH), - VX_form, 4, 718, CFLOW_NORMAL - }, - { "vxor", - EXECUTE_VECTOR_ARITH(xor_64, V2DI, V2DI, V2DI, NONE), - PPC_I(VXOR), - VX_form, 4, 1220, CFLOW_NORMAL - } -}; - -void powerpc_cpu::init_decoder() -{ - const int ii_count = sizeof(powerpc_ii_table)/sizeof(powerpc_ii_table[0]); - D(bug("PowerPC decode table has %d entries\n", ii_count)); - assert(ii_count < (1 << (8 * sizeof(ii_index_t)))); - ii_table.reserve(ii_count); - - for (int i = 0; i < ii_count; i++) { - const instr_info_t * ii = &powerpc_ii_table[i]; - init_decoder_entry(ii); - } -} - -void powerpc_cpu::init_decoder_entry(const instr_info_t * ii) -{ - ii_table.push_back(*ii); - const ii_index_t ii_index = ii_table.size() - 1; - - assert((ii->format == INVALID_form && ii_index == 0) || - (ii->format != INVALID_form && ii_index != 0) ); - - switch (ii->format) { - case INVALID_form: - // Initialize all index table - for (int i = 0; i < II_INDEX_TABLE_SIZE; i++) - ii_index_table[i] = ii_index; - break; - - case B_form: - case D_form: - case I_form: - case M_form: - // Primary opcode only - for (int j = 0; j < 2048; j++) - ii_index_table[make_ii_index(ii->opcode, j)] = ii_index; - break; - - case SC_form: - // Primary opcode only, with reserved bits - ii_index_table[make_ii_index(ii->opcode, 2)] = ii_index; - break; - - case X_form: - case XL_form: - case XFX_form: - case XFL_form: - // Extended opcode in bits 21..30 - ii_index_table[make_ii_index(ii->opcode, (ii->xo << 1) )] = ii_index; - ii_index_table[make_ii_index(ii->opcode, (ii->xo << 1) | 1)] = ii_index; - break; - - case XO_form: - // Extended opcode in bits 22..30, with OE bit 21 - ii_index_table[make_ii_index(ii->opcode, (ii->xo << 1) )] = ii_index; - ii_index_table[make_ii_index(ii->opcode, (1 << 10) | (ii->xo << 1) )] = ii_index; - ii_index_table[make_ii_index(ii->opcode, (ii->xo << 1) | 1)] = ii_index; - ii_index_table[make_ii_index(ii->opcode, (1 << 10) | (ii->xo << 1) | 1)] = ii_index; - break; - - case A_form: - // Extended opcode in bits 26..30 - for (int j = 0; j < 32; j++) { - ii_index_table[make_ii_index(ii->opcode, (j << 6) | (ii->xo << 1) )] = ii_index; - ii_index_table[make_ii_index(ii->opcode, (j << 6) | (ii->xo << 1) | 1)] = ii_index; - } - break; - - case VX_form: - // Extended opcode in bits 21..31 - ii_index_table[make_ii_index(ii->opcode, ii->xo)] = ii_index; - break; - - case VXR_form: - // Extended opcode in bits 22..31 - ii_index_table[make_ii_index(ii->opcode, ii->xo)] = ii_index; - ii_index_table[make_ii_index(ii->opcode, (1 << 10) | ii->xo)] = ii_index; - break; - - case VA_form: - // Extended opcode in bits 26..31 - for (int j = 0; j < 32; j++) - ii_index_table[make_ii_index(ii->opcode, (j << 6) | ii->xo)] = ii_index; - break; - - default: - fprintf(stderr, "Unhandled form %d\n", ii->format); - abort(); - break; - } -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp deleted file mode 100644 index 7f9e9f0b..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen-ops.cpp +++ /dev/null @@ -1,1769 +0,0 @@ -/* - * ppc-dyngen-ops.hpp - PowerPC synthetic instructions - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "cpu/vm.hpp" -#include "cpu/jit/dyngen-exec.h" -#define NO_DEFINE_ALIAS 1 -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-bitfields.hpp" -#include "cpu/ppc/ppc-registers.hpp" -#include "cpu/ppc/ppc-operations.hpp" - -#if defined(__GNUC__) -// Force inlining under newer versions of GCC. -static inline uint64 vm_read_memory_8(vm_addr_t addr) __attribute__((always_inline)); -static inline void vm_write_memory_8(vm_addr_t addr, uint64 value) __attribute__((always_inline)); -static inline uint64 vm_do_read_memory_8(uint64 *a) __attribute__((always_inline)); -static inline void vm_do_write_memory_8(uint64 *a, uint64 v) __attribute__((always_inline)); -static inline uint64 generic_bswap_64(uint64 x) __attribute__((always_inline)); -static inline uint32 fp_store_single_convert(uint64 v) __attribute__((always_inline)); -#define INLINE inline __attribute__((always_inline)) -#else -#define INLINE inline -#endif - -// We need at least 4 general purpose registers -register struct powerpc_cpu *CPU asm(REG_CPU); -#define DYNGEN_DEFINE_GLOBAL_REGISTER(REG) \ -register uintptr A##REG asm(REG_T##REG); \ -register uint32 T##REG asm(REG_T##REG) -DYNGEN_DEFINE_GLOBAL_REGISTER(0); -DYNGEN_DEFINE_GLOBAL_REGISTER(1); -DYNGEN_DEFINE_GLOBAL_REGISTER(2); -#ifdef REG_T3 -DYNGEN_DEFINE_GLOBAL_REGISTER(3); -#else -#define A3 powerpc_dyngen_helper::reg_T3() -#define T3 powerpc_dyngen_helper::reg_T3() -#endif - -// Floating-point registers -#define FPREG(X) ((powerpc_fpr *)(X)) -#define F0 FPREG(A0)->d -#define F0_dw FPREG(A0)->j -#define F1 FPREG(A1)->d -#define F1_dw FPREG(A1)->j -#define F2 FPREG(A2)->d -#define F2_dw FPREG(A2)->j -#define FD powerpc_dyngen_helper::reg_F3().d -#define FD_dw powerpc_dyngen_helper::reg_F3().j - -// Vector registers -#define VREG(X) ((powerpc_vr *)(X))[0] -#define V0 VREG(reg_V0) -#define reg_V0 A0 -#define V1 VREG(reg_V1) -#define reg_V1 A1 -#define V2 VREG(reg_V2) -#define reg_V2 A2 -#define VD VREG(reg_VD) -#define reg_VD A3 - -/** - * Helper class to access protected CPU context - **/ - -struct powerpc_dyngen_helper { - static INLINE uint32 get_pc() { return CPU->pc(); } - static INLINE void set_pc(uint32 value) { CPU->pc() = value; } - static INLINE void inc_pc(int32 offset) { CPU->pc() += offset; } - static INLINE uint32 get_lr() { return CPU->lr(); } - static INLINE void set_lr(uint32 value) { CPU->lr() = value; } - static INLINE uint32 get_ctr() { return CPU->ctr(); } - static INLINE void set_ctr(uint32 value) { CPU->ctr() = value; } - static INLINE uint32 get_cr() { return CPU->cr().get(); } - static INLINE void set_cr(uint32 value) { CPU->cr().set(value); } - static INLINE uint32 get_fpscr() { return CPU->fpscr(); } - static INLINE void set_fpscr(uint32 value) { CPU->fpscr() = value; } - static INLINE uint32 get_xer() { return CPU->xer().get(); } - static INLINE void set_xer(uint32 value) { CPU->xer().set(value); } - static INLINE uint32 get_vrsave() { return CPU->vrsave(); } - static INLINE void set_vrsave(uint32 value) { CPU->vrsave() = value; } - static INLINE uint32 get_vscr() { return CPU->vscr().get(); } - static INLINE void set_vscr(uint32 value) { CPU->vscr().set(value); } - static INLINE void record(int crf, int32 v) { CPU->record_cr(crf, v); } - static INLINE powerpc_cr_register & cr() { return CPU->cr(); } - static INLINE powerpc_xer_register & xer() { return CPU->xer(); } - static INLINE powerpc_spcflags & spcflags() { return CPU->spcflags(); } - static INLINE void set_cr(int crfd, int v) { CPU->cr().set(crfd, v); } - static INLINE powerpc_registers *regs() { return &CPU->regs(); } - -#ifndef REG_T3 - static INLINE uintptr & reg_T3() { return CPU->codegen.reg_T3; } -#endif -//#ifndef REG_F3 - static INLINE powerpc_fpr & reg_F3() { return CPU->codegen.reg_F3; } -//#endif - - static INLINE powerpc_block_info *find_block(uint32 pc) { return CPU->my_block_cache.fast_find(pc); } -}; - -// Semantic action templates -#define DYNGEN_OPS -#include "ppc-execute.hpp" - - -/** - * Load/store general purpose registers - **/ - -#define DEFINE_OP(REG, N) \ -void OPPROTO op_load_##REG##_GPR##N(void) \ -{ \ - REG = CPU->gpr(N); \ -} \ -void OPPROTO op_store_##REG##_GPR##N(void) \ -{ \ - CPU->gpr(N) = REG; \ -} -#define DEFINE_REG(N) \ -DEFINE_OP(T0,N); \ -DEFINE_OP(T1,N); \ -DEFINE_OP(T2,N); - -DEFINE_REG(0); -DEFINE_REG(1); -DEFINE_REG(2); -DEFINE_REG(3); -DEFINE_REG(4); -DEFINE_REG(5); -DEFINE_REG(6); -DEFINE_REG(7); -DEFINE_REG(8); -DEFINE_REG(9); -DEFINE_REG(10); -DEFINE_REG(11); -DEFINE_REG(12); -DEFINE_REG(13); -DEFINE_REG(14); -DEFINE_REG(15); -DEFINE_REG(16); -DEFINE_REG(17); -DEFINE_REG(18); -DEFINE_REG(19); -DEFINE_REG(20); -DEFINE_REG(21); -DEFINE_REG(22); -DEFINE_REG(23); -DEFINE_REG(24); -DEFINE_REG(25); -DEFINE_REG(26); -DEFINE_REG(27); -DEFINE_REG(28); -DEFINE_REG(29); -DEFINE_REG(30); -DEFINE_REG(31); - -#undef DEFINE_REG -#undef DEFINE_OP - - -/** - * Load/store floating-point registers - **/ - -#define DEFINE_OP(REG, N) \ -void OPPROTO op_load_F##REG##_FPR##N(void) \ -{ \ - A##REG = (uintptr)&CPU->fpr(N); \ -} \ -void OPPROTO op_store_F##REG##_FPR##N(void) \ -{ \ - CPU->fpr_dw(N) = F##REG##_dw; \ -} -#define DEFINE_REG(N) \ -DEFINE_OP(0,N); \ -DEFINE_OP(1,N); \ -DEFINE_OP(2,N); \ -void OPPROTO op_store_FD_FPR##N(void) \ -{ \ - CPU->fpr_dw(N) = FD_dw; \ -} - -DEFINE_REG(0); -DEFINE_REG(1); -DEFINE_REG(2); -DEFINE_REG(3); -DEFINE_REG(4); -DEFINE_REG(5); -DEFINE_REG(6); -DEFINE_REG(7); -DEFINE_REG(8); -DEFINE_REG(9); -DEFINE_REG(10); -DEFINE_REG(11); -DEFINE_REG(12); -DEFINE_REG(13); -DEFINE_REG(14); -DEFINE_REG(15); -DEFINE_REG(16); -DEFINE_REG(17); -DEFINE_REG(18); -DEFINE_REG(19); -DEFINE_REG(20); -DEFINE_REG(21); -DEFINE_REG(22); -DEFINE_REG(23); -DEFINE_REG(24); -DEFINE_REG(25); -DEFINE_REG(26); -DEFINE_REG(27); -DEFINE_REG(28); -DEFINE_REG(29); -DEFINE_REG(30); -DEFINE_REG(31); - -#undef DEFINE_REG -#undef DEFINE_OP - - -/** - * Load/Store floating-point data - **/ - -#if defined(__i386__) -#define do_load_double(REG, EA) do { \ - uint32 *w = (uint32 *)® \ - w[1] = vm_read_memory_4(EA + 0); \ - w[0] = vm_read_memory_4(EA + 4); \ -} while (0) -#define do_store_double(REG, EA) do { \ - uint32 *w = (uint32 *)® \ - vm_write_memory_4(EA + 0, w[1]); \ - vm_write_memory_4(EA + 4, w[0]); \ -} while (0) -#endif - -#ifndef do_load_single -#define do_load_single(REG, EA) REG##_dw = fp_load_single_convert(vm_read_memory_4(EA)) -#endif - -#ifndef do_store_single -#define do_store_single(REG, EA) vm_write_memory_4(EA, fp_store_single_convert(REG##_dw)) -#endif - -#ifndef do_load_double -#define do_load_double(REG, EA) REG##_dw = vm_read_memory_8(EA) -#endif - -#ifndef do_store_double -#define do_store_double(REG, EA) vm_write_memory_8(EA, REG##_dw) -#endif - -#define im PARAM1 -#define DEFINE_OP(OFFSET) \ -void OPPROTO op_load_double_FD_T1_##OFFSET(void) \ -{ \ - do_load_double(FD, T1 + OFFSET); \ -} \ -void OPPROTO op_load_single_FD_T1_##OFFSET(void) \ -{ \ - do_load_single(FD, T1 + OFFSET); \ -} \ -void OPPROTO op_store_double_F0_T1_##OFFSET(void) \ -{ \ - do_store_double(F0, T1 + OFFSET); \ -} \ -void OPPROTO op_store_single_F0_T1_##OFFSET(void) \ -{ \ - do_store_single(F0, T1 + OFFSET); \ -} - -DEFINE_OP(0); -DEFINE_OP(im); -DEFINE_OP(T2); - -#undef im -#undef DEFINE_OP - -#if KPX_MAX_CPUS == 1 -void OPPROTO op_lwarx_T0_T1(void) -{ - T0 = vm_read_memory_4(T1); - powerpc_dyngen_helper::regs()->reserve_valid = 1; - powerpc_dyngen_helper::regs()->reserve_addr = T1; -} - -void OPPROTO op_stwcx_T0_T1(void) -{ - uint32 cr = powerpc_dyngen_helper::get_cr() & ~CR_field<0>::mask(); - cr |= powerpc_dyngen_helper::xer().get_so() << 28; - if (powerpc_dyngen_helper::regs()->reserve_valid) { - powerpc_dyngen_helper::regs()->reserve_valid = 0; - if (powerpc_dyngen_helper::regs()->reserve_addr == T1 /* physical_addr(EA) */) { - vm_write_memory_4(T1, T0); - cr |= CR_EQ_field<0>::mask(); - } - } - powerpc_dyngen_helper::set_cr(cr); - dyngen_barrier(); -} -#endif - - -/** - * Condition Registers - **/ - -void OPPROTO op_load_T0_CR(void) -{ - T0 = powerpc_dyngen_helper::get_cr(); -} - -void OPPROTO op_store_T0_CR(void) -{ - powerpc_dyngen_helper::set_cr(T0); -} - -#define DEFINE_OP(REG, N) \ -void OPPROTO op_load_##REG##_crb##N(void) \ -{ \ - const uint32 cr = powerpc_dyngen_helper::get_cr(); \ - REG = (cr >> (31 - N)) & 1; \ -} \ -void OPPROTO op_store_##REG##_crb##N(void) \ -{ \ - uint32 cr = powerpc_dyngen_helper::get_cr() & ~(1 << (31 - N)); \ - cr |= ((REG & 1) << (31 - N)); \ - powerpc_dyngen_helper::set_cr(cr); \ -} -#define DEFINE_REG(N) \ -DEFINE_OP(T0, N); \ -DEFINE_OP(T1, N); - -DEFINE_REG(0); -DEFINE_REG(1); -DEFINE_REG(2); -DEFINE_REG(3); -DEFINE_REG(4); -DEFINE_REG(5); -DEFINE_REG(6); -DEFINE_REG(7); -DEFINE_REG(8); -DEFINE_REG(9); -DEFINE_REG(10); -DEFINE_REG(11); -DEFINE_REG(12); -DEFINE_REG(13); -DEFINE_REG(14); -DEFINE_REG(15); -DEFINE_REG(16); -DEFINE_REG(17); -DEFINE_REG(18); -DEFINE_REG(19); -DEFINE_REG(20); -DEFINE_REG(21); -DEFINE_REG(22); -DEFINE_REG(23); -DEFINE_REG(24); -DEFINE_REG(25); -DEFINE_REG(26); -DEFINE_REG(27); -DEFINE_REG(28); -DEFINE_REG(29); -DEFINE_REG(30); -DEFINE_REG(31); - -#undef DEFINE_REG -#undef DEFINE_OP - -#define DEFINE_OP(CRF, REG) \ -void OPPROTO op_load_##REG##_cr##CRF(void) \ -{ \ - REG = powerpc_dyngen_helper::cr().get(CRF); \ -} \ -void OPPROTO op_store_##REG##_cr##CRF(void) \ -{ \ - powerpc_dyngen_helper::cr().set(CRF, REG); \ -} - -DEFINE_OP(0, T0); -DEFINE_OP(1, T0); -DEFINE_OP(2, T0); -DEFINE_OP(3, T0); -DEFINE_OP(4, T0); -DEFINE_OP(5, T0); -DEFINE_OP(6, T0); -DEFINE_OP(7, T0); - -#undef DEFINE_OP - -void OPPROTO op_mtcrf_T0_im(void) -{ - const uint32 mask = PARAM1; - const uint32 cr = powerpc_dyngen_helper::get_cr(); - powerpc_dyngen_helper::set_cr((cr & ~mask) | (T0 & mask)); -} - - -/** - * Native FP operations optimization - **/ - -#if defined(__i386__) -#define do_fabs(x) ({ double y; asm volatile ("fabs" : "=t" (y) : "0" (x)); y; }) -#define do_fneg(x) ({ double y; asm volatile ("fchs" : "=t" (y) : "0" (x)); y; }) -#endif - -#ifndef do_fabs -#define do_fabs(x) fabs(x) -#endif -#ifndef do_fadd -#define do_fadd(x, y) (x) + (y) -#endif -#ifndef do_fdiv -#define do_fdiv(x, y) (x) / (y) -#endif -#ifndef do_fmadd -#define do_fmadd(x, y, z) (((x) * (y)) + (z)) -#endif -#ifndef do_fmsub -#define do_fmsub(x, y, z) (((x) * (y)) - (z)) -#endif -#ifndef do_fmul -#define do_fmul(x, y) ((x) * (y)) -#endif -#ifndef do_fneg -#define do_fneg(x) -(x) -#endif -#ifndef do_fnabs -#define do_fnabs(x) do_fneg(do_fabs(x)) -#endif -#ifndef do_fnmadd -#define do_fnmadd(x, y, z) do_fneg(((x) * (y)) + (z)) -#endif -#ifndef do_fnmsub -#define do_fnmsub(x, y, z) do_fneg(((x) * (y)) - (z)) -#endif -#ifndef do_fsub -#define do_fsub(x, y) (x) - (y) -#endif - - -/** - * Double-precision floating point operations - **/ - -#define DEFINE_OP(NAME, CODE) \ -void OPPROTO op_##NAME(void) \ -{ \ - CODE; \ -} - -DEFINE_OP(fmov_F0_F1, F0_dw = F1_dw); -DEFINE_OP(fmov_F0_F2, F0_dw = F2_dw); -DEFINE_OP(fmov_F1_F0, F1_dw = F0_dw); -DEFINE_OP(fmov_F1_F2, F1_dw = F2_dw); -DEFINE_OP(fmov_F2_F0, F2_dw = F0_dw); -DEFINE_OP(fmov_F2_F1, F2_dw = F1_dw); -DEFINE_OP(fmov_FD_F0, FD_dw = F0_dw); -DEFINE_OP(fmov_FD_F1, FD_dw = F1_dw); -DEFINE_OP(fmov_FD_F2, FD_dw = F2_dw); - -DEFINE_OP(fabs_FD_F0, FD = do_fabs(F0)); -DEFINE_OP(fneg_FD_F0, FD = do_fneg(F0)); -DEFINE_OP(fnabs_FD_F0, FD = do_fnabs(F0)); - -DEFINE_OP(fadd_FD_F0_F1, FD = do_fadd(F0, F1)); -DEFINE_OP(fsub_FD_F0_F1, FD = do_fsub(F0, F1)); -DEFINE_OP(fmul_FD_F0_F1, FD = do_fmul(F0, F1)); -DEFINE_OP(fdiv_FD_F0_F1, FD = do_fdiv(F0, F1)); -DEFINE_OP(fmadd_FD_F0_F1_F2, FD = do_fmadd(F0, F1, F2)); -DEFINE_OP(fmsub_FD_F0_F1_F2, FD = do_fmsub(F0, F1, F2)); -DEFINE_OP(fnmadd_FD_F0_F1_F2, FD = do_fnmadd(F0, F1, F2)); -DEFINE_OP(fnmsub_FD_F0_F1_F2, FD = do_fnmsub(F0, F1, F2)); - -#undef DEFINE_OP - - -/** - * Single-Precision floating point operations - **/ - -#define DEFINE_OP(NAME, REG, OP) \ -void OPPROTO op_##NAME(void) \ -{ \ - float x = OP; \ - REG = x; \ -} - -DEFINE_OP(fadds_FD_F0_F1, FD, do_fadd(F0, F1)); -DEFINE_OP(fsubs_FD_F0_F1, FD, do_fsub(F0, F1)); -DEFINE_OP(fmuls_FD_F0_F1, FD, do_fmul(F0, F1)); -DEFINE_OP(fdivs_FD_F0_F1, FD, do_fdiv(F0, F1)); -DEFINE_OP(fmadds_FD_F0_F1_F2, FD, do_fmadd(F0, F1, F2)); -DEFINE_OP(fmsubs_FD_F0_F1_F2, FD, do_fmsub(F0, F1, F2)); -DEFINE_OP(fnmadds_FD_F0_F1_F2, FD, do_fnmadd(F0, F1, F2)); -DEFINE_OP(fnmsubs_FD_F0_F1_F2, FD, do_fnmsub(F0, F1, F2)); - -#undef DEFINE_OP - - -/** - * Special purpose registers - **/ - -void OPPROTO op_load_T0_VRSAVE(void) -{ - T0 = powerpc_dyngen_helper::get_vrsave(); -} - -void OPPROTO op_store_T0_VRSAVE(void) -{ - powerpc_dyngen_helper::set_vrsave(T0); -} - -void OPPROTO op_load_T0_XER(void) -{ - T0 = powerpc_dyngen_helper::get_xer(); -} - -void OPPROTO op_store_T0_XER(void) -{ - powerpc_dyngen_helper::set_xer(T0); -} - -void OPPROTO op_load_T0_PC(void) -{ - T0 = powerpc_dyngen_helper::get_pc(); -} - -void OPPROTO op_store_T0_PC(void) -{ - powerpc_dyngen_helper::set_pc(T0); -} - -void OPPROTO op_set_PC_im(void) -{ - powerpc_dyngen_helper::set_pc(PARAM1); -} - -void OPPROTO op_set_PC_T0(void) -{ - powerpc_dyngen_helper::set_pc(T0); -} - -void OPPROTO op_inc_PC(void) -{ - powerpc_dyngen_helper::inc_pc(PARAM1); -} - -void OPPROTO op_load_T0_LR(void) -{ - T0 = powerpc_dyngen_helper::get_lr(); -} - -void OPPROTO op_store_T0_LR(void) -{ - powerpc_dyngen_helper::set_lr(T0); -} - -void OPPROTO op_load_T0_CTR(void) -{ - T0 = powerpc_dyngen_helper::get_ctr(); -} - -void OPPROTO op_store_T0_CTR(void) -{ - powerpc_dyngen_helper::set_ctr(T0); -} - -void OPPROTO op_store_im_LR(void) -{ - powerpc_dyngen_helper::set_lr(PARAM1); -} - -void OPPROTO op_load_T0_CTR_aligned(void) -{ - T0 = powerpc_dyngen_helper::get_ctr() & -4; -} - -void OPPROTO op_load_T0_LR_aligned(void) -{ - T0 = powerpc_dyngen_helper::get_lr() & -4; -} - -void OPPROTO op_spcflags_init(void) -{ - powerpc_dyngen_helper::spcflags().set(PARAM1); -} - -void OPPROTO op_spcflags_set(void) -{ - powerpc_dyngen_helper::spcflags().set(PARAM1); -} - -void OPPROTO op_spcflags_clear(void) -{ - powerpc_dyngen_helper::spcflags().clear(PARAM1); -} - -#if defined(__x86_64__) -#define FAST_COMPARE_SPECFLAGS_DISPATCH(SPCFLAGS, TARGET) \ - asm volatile ("test %0,%0 ; jz " #TARGET : : "r" (SPCFLAGS)) -#endif -#ifndef FAST_COMPARE_SPECFLAGS_DISPATCH -#define FAST_COMPARE_SPECFLAGS_DISPATCH(SPCFLAGS, TARGET) \ - if (SPCFLAGS == 0) DYNGEN_FAST_DISPATCH(TARGET) -#endif - -void OPPROTO op_spcflags_check(void) -{ - FAST_COMPARE_SPECFLAGS_DISPATCH(powerpc_dyngen_helper::spcflags().get(), __op_jmp0); -} - - -/** - * Branch instructions - **/ - -template< int bo > -static INLINE void do_prep_branch_bo(void) -{ - bool ctr_ok = true; - bool cond_ok = true; - - if (BO_CONDITIONAL_BRANCH(bo)) { - if (BO_BRANCH_IF_TRUE(bo)) - cond_ok = T1; - else - cond_ok = !T1; - } - - if (BO_DECREMENT_CTR(bo)) { - T2 = powerpc_dyngen_helper::get_ctr() - 1; - powerpc_dyngen_helper::set_ctr(T2); - if (BO_BRANCH_IF_CTR_ZERO(bo)) - ctr_ok = !T2; - else - ctr_ok = T2; - } - - T1 = ctr_ok && cond_ok; - dyngen_barrier(); -} - -#define BO(A,B,C,D) (((A) << 4)| ((B) << 3) | ((C) << 2) | ((D) << 1)) -#define DEFINE_OP(BO_SUFFIX, BO_VALUE) \ -void OPPROTO op_prep_branch_bo_##BO_SUFFIX(void) \ -{ \ - do_prep_branch_bo(); \ -} - -DEFINE_OP(0000,(0,0,0,0)); -DEFINE_OP(0001,(0,0,0,1)); -DEFINE_OP(001x,(0,0,1,0)); -DEFINE_OP(0100,(0,1,0,0)); -DEFINE_OP(0101,(0,1,0,1)); -DEFINE_OP(011x,(0,1,1,0)); -DEFINE_OP(1x00,(1,0,0,0)); -DEFINE_OP(1x01,(1,0,0,1)); -// NOTE: the compiler is expected to optimize out the use of PARAM1 -DEFINE_OP(1x1x,(1,0,1,0)); - -#undef DEFINE_OP -#undef BO - -void OPPROTO op_branch_chain_1(void) -{ - DYNGEN_FAST_DISPATCH(__op_jmp0); -} - -void OPPROTO op_branch_chain_2(void) -{ - if (T1) - DYNGEN_FAST_DISPATCH(__op_jmp0); - else - DYNGEN_FAST_DISPATCH(__op_jmp1); - dyngen_barrier(); -} - -static INLINE void do_execute_branch_1(uint32 tpc) -{ - powerpc_dyngen_helper::set_pc(tpc); -} - -void OPPROTO op_branch_1_T0(void) -{ - do_execute_branch_1(T0); -} - -void OPPROTO op_branch_1_im(void) -{ - do_execute_branch_1(PARAM1); -} - -static INLINE void do_execute_branch_2(uint32 tpc, uint32 npc) -{ - powerpc_dyngen_helper::set_pc(T1 ? tpc : npc); - dyngen_barrier(); -} - -void OPPROTO op_branch_2_T0_im(void) -{ - do_execute_branch_2(T0, PARAM1); -} - -void OPPROTO op_branch_2_im_im(void) -{ - do_execute_branch_2(PARAM1, PARAM2); -} - - -/** - * Compare & Record instructions - **/ - -void OPPROTO op_record_cr0_T0(void) -{ - uint32 cr = powerpc_dyngen_helper::get_cr() & ~CR_field<0>::mask(); - cr |= powerpc_dyngen_helper::xer().get_so() << 28; - if ((int32)T0 < 0) - cr |= CR_LT_field<0>::mask(); - else if ((int32)T0 > 0) - cr |= CR_GT_field<0>::mask(); - else - cr |= CR_EQ_field<0>::mask(); - powerpc_dyngen_helper::set_cr(cr); - dyngen_barrier(); -} - -void OPPROTO op_record_cr1(void) -{ - powerpc_dyngen_helper::set_cr((powerpc_dyngen_helper::get_cr() & ~CR_field<1>::mask()) | - ((powerpc_dyngen_helper::get_fpscr() >> 4) & 0x0f000000)); -} - -#define im PARAM1 - -#if DYNGEN_ASM_OPTS && defined(__powerpc__) && 0 - -#define DEFINE_OP(NAME, COMP, LHS, RHST, RHS) \ -void OPPROTO op_##NAME##_##LHS##_##RHS(void) \ -{ \ - T0 = powerpc_dyngen_helper::xer().get_so(); \ - uint32 v; \ - asm volatile (COMP " 7,%1,%2 ; mfcr %0" : "=r" (v) : "r" (LHS), RHST (RHS) : "cr7"); \ - T0 |= (v & 0xe); \ -} - -DEFINE_OP(compare,"cmpw",T0,"r",T1); -DEFINE_OP(compare,"cmpw",T0,"r",im); -DEFINE_OP(compare,"cmpwi",T0,"i",0); -DEFINE_OP(compare_logical,"cmplw",T0,"r",T1); -DEFINE_OP(compare_logical,"cmplw",T0,"r",im); -DEFINE_OP(compare_logical,"cmplwi",T0,"i",0); - -#else - -#define DEFINE_OP(NAME, TYPE, LHS, RHS) \ -void OPPROTO op_##NAME##_##LHS##_##RHS(void) \ -{ \ - const uint32 SO = powerpc_dyngen_helper::xer().get_so(); \ - if ((TYPE)LHS < (TYPE)RHS) \ - T0 = SO | standalone_CR_LT_field::mask(); \ - else if ((TYPE)LHS > (TYPE)RHS) \ - T0 = SO | standalone_CR_GT_field::mask(); \ - else \ - T0 = SO | standalone_CR_EQ_field::mask(); \ - dyngen_barrier(); \ -} - -DEFINE_OP(compare,int32,T0,T1); -DEFINE_OP(compare,int32,T0,im); -DEFINE_OP(compare,int32,T0,0); -DEFINE_OP(compare_logical,uint32,T0,T1); -DEFINE_OP(compare_logical,uint32,T0,im); -DEFINE_OP(compare_logical,uint32,T0,0); - -#endif - -#undef im -#undef DEFINE_OP - - -/** - * Divide instructions - **/ - -#if DYNGEN_ASM_OPTS && defined(__powerpc__) -#define get_ov() ({ uint32 xer; asm volatile ("mfxer %0" : "=r" (xer)); XER_OV_field::extract(xer); }) -#endif - -void OPPROTO op_divw_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - asm volatile ("divw %0,%0,%1" : "=r" (T0) : "r" (T1)); - return; -#endif -#endif - T0 = do_execute_divide(T0, T1); -} - -void OPPROTO op_divwo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - asm volatile ("divwo %0,%0,%1" : "=r" (T0) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ov(get_ov()); - return; -#endif -#endif - T0 = do_execute_divide(T0, T1); -} - -void OPPROTO op_divwu_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - asm volatile ("divwu %0,%0,%1" : "=r" (T0) : "r" (T1)); - return; -#endif -#endif - T0 = do_execute_divide(T0, T1); -} - -void OPPROTO op_divwuo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - asm volatile ("divwuo %0,%0,%1" : "=r" (T0) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ov(get_ov()); - return; -#endif -#endif - T0 = do_execute_divide(T0, T1); -} - - -/** - * Multiply instructions - **/ - -void OPPROTO op_mulhw_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("imul %0" : "+d" (T0) : "a" (T1)); - return; -#endif -#endif - T0 = (((int64)(int32)T0) * ((int64)(int32)T1)) >> 32; -} - -void OPPROTO op_mulhwu_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("mul %0" : "+d" (T0) : "a" (T1)); - return; -#endif -#endif - T0 = (((uint64)T0) * ((uint64)T1)) >> 32; -} - -void OPPROTO op_mulli_T0_im(void) -{ - T0 = (int32)T0 * (int32)PARAM1; -} - -void OPPROTO op_mullwo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - asm volatile ("mullwo %0,%0,%1" : "=r" (T0) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ov(get_ov()); - return; -#endif -#endif - int64 RD = (int64)(int32)T0 * (int64)(int32)T1; - powerpc_dyngen_helper::xer().set_ov((int32)RD != RD); - T0 = RD; - dyngen_barrier(); -} - - -/** - * Shift/Rotate instructions - **/ - -void OPPROTO op_slw_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - T0 <<= T1; // the shift count is masked to 5 bits - if (T1 & 0x20) - T0 = 0; - return; -#endif -#endif - T1 &= 0x3f; - T0 = (T1 & 0x20) ? 0 : (T0 << T1); - dyngen_barrier(); -} - -void OPPROTO op_srw_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - T0 >>= T1; // the shift count is masked to 5 bits - if (T1 & 0x20) - T0 = 0; - return; -#endif -#endif - T1 &= 0x3f; - T0 = (T1 & 0x20) ? 0 : (T0 >> T1); - dyngen_barrier(); -} - -void OPPROTO op_sraw_T0_T1(void) -{ - T1 &= 0x3f; - if (T1 & 0x20) { - const uint32 SB = T0 >> 31; - powerpc_dyngen_helper::xer().set_ca(SB); - T0 = -SB; - } - else { - const uint32 RD = ((int32)T0) >> T1; - const bool CA = (int32)T0 < 0 && (T0 & ~(0xffffffff << T1)); - powerpc_dyngen_helper::xer().set_ca(CA); - T0 = RD; - } - dyngen_barrier(); -} - -void OPPROTO op_sraw_T0_im(void) -{ - const uint32 n = PARAM1; - const uint32 RD = ((int32)T0) >> n; - const bool ca = (((int32)T0) < 0) && (T0 & ~(0xffffffff << n)); - powerpc_dyngen_helper::xer().set_ca(ca); - T0 = RD; - dyngen_barrier(); -} - -void OPPROTO op_rlwimi_T0_T1(void) -{ - T0 = op_ppc_rlwimi::apply(T1, PARAM1, PARAM2, T0); -} - -void OPPROTO op_rlwinm_T0_T1(void) -{ - T0 = op_rotl::apply(T0, PARAM1) & PARAM2; -} - -void OPPROTO op_rlwnm_T0_T1(void) -{ - T0 = op_rotl::apply(T0, T1) & PARAM1; -} - -void OPPROTO op_cntlzw_32_T0(void) -{ - int n; -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - n = -1; - asm volatile ("bsr %1,%0" : "+r" (n) : "r" (T0)); - T0 = 31 - n; - return; -#endif -#endif - uint32 m = 0x80000000; - for (n = 0; n < 32; n++, m >>= 1) - if (T0 & m) - break; - T0 = n; - dyngen_barrier(); -} - - -/** - * Addition/Subtraction - **/ - -void OPPROTO op_addo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer; - asm volatile ("addo %0,%0,%2 ; mfxer %1" : "=r" (T0), "=r" (xer) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ov(XER_OV_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ov; - asm volatile ("add %2,%0; seto %b1" : "=r" (T0), "=r" (ov) : "r" (T1) : "cc"); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_addition(T0, T1); -} - -void OPPROTO op_addc_T0_im(void) -{ - T0 = do_execute_addition(T0, PARAM1); -} - -void OPPROTO op_addc_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer; - asm volatile ("addc %0,%0,%2 ; mfxer %1" : "=r" (T0), "=r" (xer) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ca; - asm volatile ("add %2,%0; setc %b1" : "=r" (T0), "=r" (ca) : "r" (T1) : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_addition(T0, T1); -} - -void OPPROTO op_addco_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer; - asm volatile ("addco %0,%0,%2 ; mfxer %1" : "=r" (T0), "=r" (xer) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - powerpc_dyngen_helper::xer().set_ov(XER_OV_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ca, ov; - asm volatile ("add %3,%0; setc %b1; seto %b2" : "=r" (T0), "=r" (ca), "=r" (ov) : "r" (T1) : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_addition(T0, T1); -} - -void OPPROTO op_adde_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("li 0,-1 ; addc 0,%0,0" : : "r" (ca) : "r0"); - asm volatile ("adde %0,%0,%2 ; mfxer %1" : "=r" (T0), "=r" (xer) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("bt $0,%1; adc %2,%0; setc %b1" : "=r" (T0), "+r" (ca) : "r" (T1) : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_addition(T0, T1); -} - -void OPPROTO op_addeo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("li 0,-1 ; addc 0,%0,0" : : "r" (ca) : "r0"); - asm volatile ("addeo %0,%0,%2 ; mfxer %1" : "=r" (T0), "=r" (xer) : "r" (T1)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - powerpc_dyngen_helper::xer().set_ov(XER_OV_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ov, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("bt $0,%1; adc %3,%0; setc %b1; seto %b2" : "=r" (T0), "+r" (ca), "=r" (ov) : "r" (T1) : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_addition(T0, T1); -} - -void OPPROTO op_addme_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("li 0,-1 ; addc 0,%0,0" : : "r" (ca) : "r0"); - asm volatile ("addme %0,%0 ; mfxer %1" : "=r" (T0), "=r" (xer)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("bt $0,%1; adc $-1,%0; setc %b1" : "=r" (T0), "+r" (ca) : : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_addition(T0, 0xffffffff); -} - -void OPPROTO op_addmeo_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("li 0,-1 ; addc 0,%0,0" : : "r" (ca) : "r0"); - asm volatile ("addmeo %0,%0 ; mfxer %1" : "=r" (T0), "=r" (xer)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - powerpc_dyngen_helper::xer().set_ov(XER_OV_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ov, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("bt $0,%1; adc $-1,%0; setc %b1; seto %b2" : "=r" (T0), "+r" (ca), "=r" (ov) : : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_addition(T0, 0xffffffff); -} - -void OPPROTO op_addze_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("li 0,-1 ; addc 0,%0,0" : : "r" (ca) : "r0"); - asm volatile ("addze %0,%0 ; mfxer %1" : "=r" (T0), "=r" (xer)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("bt $0,%1; adc $0,%0; setc %b1" : "=r" (T0), "+r" (ca) : : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_addition(T0, 0); -} - -void OPPROTO op_addzeo_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__powerpc__) - uint32 xer, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("li 0,-1 ; addc 0,%0,0" : : "r" (ca) : "r0"); - asm volatile ("addzeo %0,%0 ; mfxer %1" : "=r" (T0), "=r" (xer)); - powerpc_dyngen_helper::xer().set_ca(XER_CA_field::extract(xer)); - powerpc_dyngen_helper::xer().set_ov(XER_OV_field::extract(xer)); - return; -#endif -#if defined(__i386__) || defined(__x86_64__) - uint32 ov, ca = powerpc_dyngen_helper::xer().get_ca(); - asm volatile ("bt $0,%1; adc $0,%0; setc %b1; seto %b2" : "=r" (T0), "+r" (ca), "=r" (ov) : : "cc"); - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_addition(T0, 0); -} - -void OPPROTO op_subf_T0_T1(void) -{ - T0 = T1 - T0; -} - -void OPPROTO op_subfo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ov, TI; - TI = T1; - asm volatile ("sub %2,%0; seto %b1" : "+r" (TI), "=r" (ov) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_subtract(T0, T1); -} - -void OPPROTO op_subfc_T0_im(void) -{ - T0 = do_execute_subtract(T0, PARAM1); -} - -void OPPROTO op_subfc_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ca, TI; - TI = T1; - asm volatile ("sub %2,%0; cmc; setc %b1" : "+r" (TI), "=r" (ca) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_subtract(T0, T1); -} - -void OPPROTO op_subfco_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ca, ov, TI; - TI = T1; - asm volatile ("sub %3,%0; cmc; setc %b1; seto %b2" : "+r" (TI), "=r" (ca), "=r" (ov) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_subtract(T0, T1); -} - -void OPPROTO op_subfe_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - uint32 TI = T1; - asm volatile ("bt $0,%1; cmc; sbb %2,%0; cmc; setc %b1" : "+r" (TI), "+r" (ca) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_subtract_extended(T0, T1); -} - -void OPPROTO op_subfeo_T0_T1(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ov, ca = powerpc_dyngen_helper::xer().get_ca(); - uint32 TI = T1; - asm volatile ("bt $0,%1; cmc; sbb %3,%0; cmc; setc %b1; seto %b2" : "+r" (TI), "+r" (ca), "=r" (ov) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_subtract_extended(T0, T1); -} - -void OPPROTO op_subfme_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - uint32 TI = (uint32)-1; - asm volatile ("bt $0,%1; cmc; sbb %2,%0; cmc; setc %b1" : "+r" (TI), "+r" (ca) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_subtract_extended(T0, 0xffffffff); -} - -void OPPROTO op_subfmeo_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ov; - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - uint32 TI = (uint32)-1; - asm volatile ("bt $0,%1; cmc; sbb %3,%0; cmc; setc %b1; seto %b2" : "+r" (TI), "+r" (ca), "=r" (ov) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_subtract_extended(T0, 0xffffffff); -} - -void OPPROTO op_subfze_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - uint32 TI = 0; - asm volatile ("bt $0,%1; cmc; sbb %2,%0; cmc; setc %b1" : "+r" (TI), "+r" (ca) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - return; -#endif -#endif - T0 = do_execute_subtract_extended(T0, 0); -} - -void OPPROTO op_subfzeo_T0(void) -{ -#if DYNGEN_ASM_OPTS -#if defined(__i386__) || defined(__x86_64__) - uint32 ov; - uint32 ca = powerpc_dyngen_helper::xer().get_ca(); - uint32 TI = 0; - asm volatile ("bt $0,%1; cmc; sbb %3,%0; cmc; setc %b1; seto %b2" : "+r" (TI), "+r" (ca), "=r" (ov) : "r" (T0) : "cc"); - T0 = TI; - powerpc_dyngen_helper::xer().set_ca(ca); - powerpc_dyngen_helper::xer().set_ov(ov); - return; -#endif -#endif - T0 = do_execute_subtract_extended(T0, 0); -} - -/** - * Misc synthetic instructions - **/ - -void OPPROTO op_inc_32_mem(void) -{ - uint32 *m = (uint32 *)PARAM1; - *m += 1; -} - -void OPPROTO op_nego_T0(void) -{ - powerpc_dyngen_helper::xer().set_ov(T0 == 0x80000000); - T0 = -T0; -} - -void OPPROTO op_dcbz_T0(void) -{ - T0 &= -32; // align T0 on cache line boundaries - uint64 * block = (uint64 *) vm_do_get_real_address(T0); - block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; -} - -/** - * Generate possible call to next basic block without going - * through register state restore & full cache lookup - **/ - -void OPPROTO op_jump_next_A0(void) -{ - powerpc_block_info *bi = (powerpc_block_info *)A0; - uint32 pc = powerpc_dyngen_helper::get_pc(); - if (likely(bi->pc == pc) || likely((bi = powerpc_dyngen_helper::find_block(pc)) != NULL)) - goto *(bi->entry_point); - dyngen_barrier(); -} - -/** - * Load/store multiple - **/ - -template< int N > -static INLINE void do_lmw(void) -{ - CPU->gpr(N) = vm_read_memory_4(T0); - T0 += 4; - do_lmw(); -} - -template<> -INLINE void do_lmw<31>(void) -{ - CPU->gpr(31) = vm_read_memory_4(T0); -} - -template<> -INLINE void do_lmw<32>(void) -{ - for (uint32 r = PARAM1, ad = T0; r <= 31; r++, ad += 4) - CPU->gpr(r) = vm_read_memory_4(ad); - dyngen_barrier(); -} - -template< int N > -static INLINE void do_stmw(void) -{ - vm_write_memory_4(T0, CPU->gpr(N)); - T0 += 4; - do_stmw(); -} - -template<> -INLINE void do_stmw<31>(void) -{ - vm_write_memory_4(T0, CPU->gpr(31)); -} - -template<> -INLINE void do_stmw<32>(void) -{ - for (uint32 r = PARAM1, ad = T0; r <= 31; r++, ad += 4) - vm_write_memory_4(ad, CPU->gpr(r)); - dyngen_barrier(); -} - -#define im 32 -#define DEFINE_OP(N) \ -void op_lmw_T0_## N(void) { do_lmw (); } \ -void op_stmw_T0_##N(void) { do_stmw(); } - -DEFINE_OP(im); -DEFINE_OP(26); -DEFINE_OP(27); -DEFINE_OP(28); -DEFINE_OP(29); -DEFINE_OP(30); -DEFINE_OP(31); - -#undef im -#undef DEFINE_OP - -/** - * Load/store addresses to vector registers - **/ - -#define DEFINE_OP(REG, N) \ -void OPPROTO op_load_ad_V##REG##_VR##N(void) \ -{ \ - reg_V##REG = (uintptr)&CPU->vr(N); \ -} -#define DEFINE_REG(N) \ -DEFINE_OP(D,N); \ -DEFINE_OP(0,N); \ -DEFINE_OP(1,N); \ -DEFINE_OP(2,N) - -DEFINE_REG(0); -DEFINE_REG(1); -DEFINE_REG(2); -DEFINE_REG(3); -DEFINE_REG(4); -DEFINE_REG(5); -DEFINE_REG(6); -DEFINE_REG(7); -DEFINE_REG(8); -DEFINE_REG(9); -DEFINE_REG(10); -DEFINE_REG(11); -DEFINE_REG(12); -DEFINE_REG(13); -DEFINE_REG(14); -DEFINE_REG(15); -DEFINE_REG(16); -DEFINE_REG(17); -DEFINE_REG(18); -DEFINE_REG(19); -DEFINE_REG(20); -DEFINE_REG(21); -DEFINE_REG(22); -DEFINE_REG(23); -DEFINE_REG(24); -DEFINE_REG(25); -DEFINE_REG(26); -DEFINE_REG(27); -DEFINE_REG(28); -DEFINE_REG(29); -DEFINE_REG(30); -DEFINE_REG(31); - -#undef DEFINE_REG -#undef DEFINE_OP -#undef AD - -void op_load_word_VD_T0(void) -{ - const uint32 ea = T0; - VD.w[(ea >> 2) & 3] = vm_read_memory_4(ea & ~3); -} - -void op_store_word_VD_T0(void) -{ - const uint32 ea = T0; - vm_write_memory_4(ea & ~3, VD.w[(ea >> 2) & 3]); -} - -void op_load_vect_VD_T0(void) -{ - const uint32 ea = T0 & ~15; - VD.w[0] = vm_read_memory_4(ea + 0); - VD.w[1] = vm_read_memory_4(ea + 4); - VD.w[2] = vm_read_memory_4(ea + 8); - VD.w[3] = vm_read_memory_4(ea + 12); -} - -void op_store_vect_VD_T0(void) -{ - const uint32 ea = T0 & ~15; - vm_write_memory_4(ea + 0, VD.w[0]); - vm_write_memory_4(ea + 4, VD.w[1]); - vm_write_memory_4(ea + 8, VD.w[2]); - vm_write_memory_4(ea + 12, VD.w[3]); -} - -/** - * Vector operations helpers - **/ - -#define VNONE op_VNONE -struct op_VNONE { - typedef null_operand type; - static INLINE uint32 get(powerpc_vr const & v, int i) { return 0; } - static INLINE void set(powerpc_vr const & v, int i, uint32) { } -}; - -#define V16QI op_V16QI -struct op_V16QI { - typedef uint8 type; - static INLINE type get(powerpc_vr const & v, int i) { return v.b[i]; } - static INLINE void set(powerpc_vr & v, int i, type x) { v.b[i] = x; } -}; - -#define V8HI op_V8HI -struct op_V8HI { - typedef uint16 type; - static INLINE type get(powerpc_vr const & v, int i) { return v.h[i]; } - static INLINE void set(powerpc_vr & v, int i, type x) { v.h[i] = x; } -}; - -#define V4SI op_V4SI -struct op_V4SI { - typedef uint32 type; - static INLINE type get(powerpc_vr const & v, int i) { return v.w[i]; } - static INLINE void set(powerpc_vr & v, int i, type x) { v.w[i] = x; } -}; - -#define V2DI op_V2DI -struct op_V2DI { - typedef uint64 type; - static INLINE type get(powerpc_vr const & v, int i) { return v.j[i]; } - static INLINE void set(powerpc_vr & v, int i, type x) { v.j[i] = x; } -}; - -#define V4SF op_V4SF -struct op_V4SF { - typedef float type; - static INLINE type get(powerpc_vr const & v, int i) { return v.f[i]; } - static INLINE void set(powerpc_vr & v, int i, type x) { v.f[i] = x; } -}; - -template< class OP, class VX, class VA, class VB, class VC, int N > -struct do_vector_execute { - static INLINE void apply() { - do_vector_execute::apply(); - VX::set( - VD, N, - op_apply::apply( - VA::get(V0, N), - VB::get(V1, N), - VC::get(V2, N))); - } -}; - -template< class OP, class VX, class VA, class VB, class VC > -struct do_vector_execute { - static INLINE void apply() { - VX::set( - VD, 0, op_apply::apply( - VA::get(V0, 0), - VB::get(V1, 0), - VC::get(V2, 0))); - } -}; - -template< class OP, class VX, class VA, class VB = VNONE, class VC = VNONE > -struct vector_execute { - static INLINE void apply() { - do_vector_execute::apply(); - } -}; - - -/** - * Vector synthetic operations - **/ - -void op_vaddfp_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_vsubfp_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_vmaddfp_VD_V0_V1_V2(void) -{ - vector_execute::apply(); -} - -#if defined(__i386__) && defined(__SSE__) -// Workaround gcc 3.2.2 miscompilation that inserts SSE instructions -struct op_do_vnmsubfp { - static INLINE float apply(float x, float y, float z) { -// return 0. - ((x * z) - y); - return y - (x * z); - } -}; -#else -typedef op_vnmsubfp op_do_vnmsubfp; -#endif - -void op_vnmsubfp_VD_V0_V1_V2(void) -{ - vector_execute::apply(); -} - -void op_vand_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_vandc_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_vnor_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_vor_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_vxor_VD_V0_V1(void) -{ - vector_execute::apply(); -} - -void op_record_cr6_VD(void) -{ - unsigned int cr6 = 0; -#if SIZEOF_VOID_P == 8 - if ((~VD.j[0] | ~VD.j[1]) == 0) - cr6 = 8; - else if ((VD.j[0] | VD.j[1]) == 0) - cr6 = 2; -#else - if ((~VD.w[0] | ~VD.w[1] | ~VD.w[2] | ~VD.w[3]) == 0) - cr6 = 8; - else if ((VD.w[0] | VD.w[1] | VD.w[2] | VD.w[3]) == 0) - cr6 = 2; -#endif - powerpc_dyngen_helper::cr().set(6, cr6); - dyngen_barrier(); -} - -void op_mfvscr_VD(void) -{ - VD.w[0] = 0; - VD.w[1] = 0; - VD.w[2] = 0; - VD.w[3] = powerpc_dyngen_helper::get_vscr(); -} - -void op_mtvscr_V0(void) -{ - powerpc_dyngen_helper::set_vscr(V0.w[3]); -} - -#undef VNONE -#undef V16QI -#undef V8HI -#undef V4SI -#undef V2DI -#undef V4SF - -/** - * X86 SIMD optimizations - **/ - -#if defined(__i386__) || defined(__x86_64__) -#undef VD -#undef V0 -#undef V1 -#undef V2 - -/* We are using GCC, so we can use its extensions */ -#if defined __MMX__ || __GNUC__ < 4 -#define __mmx_clobbers(reglist...) reglist -#else -#define __mmx_clobbers(reglist...) -#endif -#if defined __SSE__ || __GNUC__ < 4 -#define __sse_clobbers(reglist...) reglist -#else -#define __sse_clobbers(reglist...) -#endif - -// MMX instructions -void op_emms(void) -{ - asm volatile ("emms"); -} - -#define DEFINE_OP(NAME, OP, VA, VB) \ -void op_mmx_##NAME(void) \ -{ \ - asm volatile ("movq (%1),%%mm0\n" \ - "movq 8(%1),%%mm1\n" \ - #OP " (%2),%%mm0\n" \ - #OP " 8(%2),%%mm1\n" \ - "movq %%mm0,(%0)\n" \ - "movq %%mm1,8(%0)\n" \ - : : "r" (reg_VD), "r" (reg_##VA), "r" (reg_##VB) \ - : __mmx_clobbers("mm0", "mm1")); \ -} - -DEFINE_OP(vcmpequb, pcmpeqb, V0, V1); -DEFINE_OP(vcmpequh, pcmpeqw, V0, V1); -DEFINE_OP(vcmpequw, pcmpeqd, V0, V1); -DEFINE_OP(vcmpgtsb, pcmpgtb, V0, V1); -DEFINE_OP(vcmpgtsh, pcmpgtw, V0, V1); -DEFINE_OP(vcmpgtsw, pcmpgtd, V0, V1); -DEFINE_OP(vaddubm, paddb, V0, V1); -DEFINE_OP(vadduhm, paddw, V0, V1); -DEFINE_OP(vadduwm, paddd, V0, V1); -DEFINE_OP(vsububm, psubb, V0, V1); -DEFINE_OP(vsubuhm, psubw, V0, V1); -DEFINE_OP(vsubuwm, psubd, V0, V1); -DEFINE_OP(vand, pand, V0, V1); -DEFINE_OP(vandc, pandn, V1, V0); -DEFINE_OP(vor, por, V0, V1); -DEFINE_OP(vxor, pxor, V0, V1); -DEFINE_OP(vmaxub, pmaxub, V0, V1); -DEFINE_OP(vminub, pminub, V0, V1); -DEFINE_OP(vmaxsh, pmaxsw, V0, V1); -DEFINE_OP(vminsh, pminsw, V0, V1); - -#undef DEFINE_OP -#endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp deleted file mode 100644 index 8d8451cb..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * ppc-dyngen.cpp - PowerPC dynamic translation (low-level) - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "utils/utils-cpuinfo.hpp" -#include "cpu/ppc/ppc-dyngen.hpp" -#include "cpu/ppc/ppc-bitfields.hpp" -#include "cpu/ppc/ppc-instructions.hpp" - -#include -#include - -#define DYNGEN_IMPL 1 -#define DEFINE_GEN(NAME,RET,ARGS) RET powerpc_dyngen::NAME ARGS -#include "ppc-dyngen-ops.hpp" - -powerpc_dyngen::powerpc_dyngen(dyngen_cpu_base cpu) - : basic_dyngen(cpu) -{ -#ifdef SHEEPSHAVER - printf("Detected CPU features:"); - if (cpuinfo_check_mmx()) - printf(" MMX"); - if (cpuinfo_check_sse()) - printf(" SSE"); - if (cpuinfo_check_sse2()) - printf(" SSE2"); - if (cpuinfo_check_sse3()) - printf(" SSE3"); - if (cpuinfo_check_ssse3()) - printf(" SSSE3"); - if (cpuinfo_check_altivec()) - printf(" VMX"); - printf("\n"); -#endif -} - -uint8 *powerpc_dyngen::gen_start(uint32 pc) -{ - // Generate exit if there are pending spcflags - uint8 *p = basic_dyngen::gen_start(); - gen_op_spcflags_check(); - gen_op_set_PC_im(pc); - gen_exec_return(); - dg_set_jmp_target_noflush(jmp_addr[0], gen_align()); - jmp_addr[0] = NULL; - return p; -} - -void powerpc_dyngen::gen_compare_T0_T1(int crf) -{ - gen_op_compare_T0_T1(); - gen_store_T0_crf(crf); -} - -void powerpc_dyngen::gen_compare_T0_im(int crf, int32 value) -{ - if (value == 0) - gen_op_compare_T0_0(); - else - gen_op_compare_T0_im(value); - gen_store_T0_crf(crf); -} - -void powerpc_dyngen::gen_compare_logical_T0_T1(int crf) -{ - gen_op_compare_logical_T0_T1(); - gen_store_T0_crf(crf); -} - -void powerpc_dyngen::gen_compare_logical_T0_im(int crf, int32 value) -{ - if (value == 0) - gen_op_compare_logical_T0_0(); - else - gen_op_compare_logical_T0_im(value); - gen_store_T0_crf(crf); -} - -void powerpc_dyngen::gen_mtcrf_T0_im(uint32 mask) -{ - gen_op_mtcrf_T0_im(mask); -} - - -/** - * Load/store multiple words - **/ - -#define DEFINE_INSN(OP) \ -void powerpc_dyngen::gen_##OP##_T0(int r) \ -{ \ - switch (r) { \ - case 26: gen_op_##OP##_T0_26(); break; \ - case 27: gen_op_##OP##_T0_27(); break; \ - case 28: gen_op_##OP##_T0_28(); break; \ - case 29: gen_op_##OP##_T0_29(); break; \ - case 30: gen_op_##OP##_T0_30(); break; \ - case 31: gen_op_##OP##_T0_31(); break; \ - default: gen_op_##OP##_T0_im(r); break; \ - } \ -} - -DEFINE_INSN(lmw); -DEFINE_INSN(stmw); - -#undef DEFINE_INSN - - -/** - * Load/store registers - **/ - -#define DEFINE_INSN(OP, REG, REGT) \ -void powerpc_dyngen::gen_##OP##_##REG##_##REGT(int i) \ -{ \ - switch (i) { \ - case 0: gen_op_##OP##_##REG##_##REGT##0(); break; \ - case 1: gen_op_##OP##_##REG##_##REGT##1(); break; \ - case 2: gen_op_##OP##_##REG##_##REGT##2(); break; \ - case 3: gen_op_##OP##_##REG##_##REGT##3(); break; \ - case 4: gen_op_##OP##_##REG##_##REGT##4(); break; \ - case 5: gen_op_##OP##_##REG##_##REGT##5(); break; \ - case 6: gen_op_##OP##_##REG##_##REGT##6(); break; \ - case 7: gen_op_##OP##_##REG##_##REGT##7(); break; \ - case 8: gen_op_##OP##_##REG##_##REGT##8(); break; \ - case 9: gen_op_##OP##_##REG##_##REGT##9(); break; \ - case 10: gen_op_##OP##_##REG##_##REGT##10(); break; \ - case 11: gen_op_##OP##_##REG##_##REGT##11(); break; \ - case 12: gen_op_##OP##_##REG##_##REGT##12(); break; \ - case 13: gen_op_##OP##_##REG##_##REGT##13(); break; \ - case 14: gen_op_##OP##_##REG##_##REGT##14(); break; \ - case 15: gen_op_##OP##_##REG##_##REGT##15(); break; \ - case 16: gen_op_##OP##_##REG##_##REGT##16(); break; \ - case 17: gen_op_##OP##_##REG##_##REGT##17(); break; \ - case 18: gen_op_##OP##_##REG##_##REGT##18(); break; \ - case 19: gen_op_##OP##_##REG##_##REGT##19(); break; \ - case 20: gen_op_##OP##_##REG##_##REGT##20(); break; \ - case 21: gen_op_##OP##_##REG##_##REGT##21(); break; \ - case 22: gen_op_##OP##_##REG##_##REGT##22(); break; \ - case 23: gen_op_##OP##_##REG##_##REGT##23(); break; \ - case 24: gen_op_##OP##_##REG##_##REGT##24(); break; \ - case 25: gen_op_##OP##_##REG##_##REGT##25(); break; \ - case 26: gen_op_##OP##_##REG##_##REGT##26(); break; \ - case 27: gen_op_##OP##_##REG##_##REGT##27(); break; \ - case 28: gen_op_##OP##_##REG##_##REGT##28(); break; \ - case 29: gen_op_##OP##_##REG##_##REGT##29(); break; \ - case 30: gen_op_##OP##_##REG##_##REGT##30(); break; \ - case 31: gen_op_##OP##_##REG##_##REGT##31(); break; \ - default: abort(); \ - } \ -} - -// General purpose registers -DEFINE_INSN(load, T0, GPR); -DEFINE_INSN(load, T1, GPR); -DEFINE_INSN(load, T2, GPR); -DEFINE_INSN(store, T0, GPR); -DEFINE_INSN(store, T1, GPR); -DEFINE_INSN(store, T2, GPR); -DEFINE_INSN(load, F0, FPR); -DEFINE_INSN(load, F1, FPR); -DEFINE_INSN(load, F2, FPR); -DEFINE_INSN(store, F0, FPR); -DEFINE_INSN(store, F1, FPR); -DEFINE_INSN(store, F2, FPR); -DEFINE_INSN(store, FD, FPR); -DEFINE_INSN(load_ad, VD, VR); -DEFINE_INSN(load_ad, V0, VR); -DEFINE_INSN(load_ad, V1, VR); -DEFINE_INSN(load_ad, V2, VR); - -// Condition register bitfield -DEFINE_INSN(load, T0, crb); -DEFINE_INSN(load, T1, crb); -DEFINE_INSN(store, T0, crb); -DEFINE_INSN(store, T1, crb); - -#undef DEFINE_INSN - -// Floating point load store -#define DEFINE_OP(NAME, REG, TYPE) \ -void powerpc_dyngen::gen_##NAME##_##TYPE##_##REG##_T1_im(int32 offset) \ -{ \ - if (offset == 0) \ - gen_op_##NAME##_##TYPE##_##REG##_T1_0(); \ - else \ - gen_op_##NAME##_##TYPE##_##REG##_T1_im(offset); \ -} - -DEFINE_OP(load, FD, double); -DEFINE_OP(load, FD, single); -DEFINE_OP(store, F0, double); -DEFINE_OP(store, F0, single); - -#undef DEFINE_OP - -#define DEFINE_INSN(OP, REG) \ -void powerpc_dyngen::gen_##OP##_##REG##_crf(int crf) \ -{ \ - switch (crf) { \ - case 0: gen_op_##OP##_##REG##_cr0(); break; \ - case 1: gen_op_##OP##_##REG##_cr1(); break; \ - case 2: gen_op_##OP##_##REG##_cr2(); break; \ - case 3: gen_op_##OP##_##REG##_cr3(); break; \ - case 4: gen_op_##OP##_##REG##_cr4(); break; \ - case 5: gen_op_##OP##_##REG##_cr5(); break; \ - case 6: gen_op_##OP##_##REG##_cr6(); break; \ - case 7: gen_op_##OP##_##REG##_cr7(); break; \ - default: abort(); \ - } \ -} - -DEFINE_INSN(load, T0); -DEFINE_INSN(store, T0); - -#undef DEFINE_INSN - -void powerpc_dyngen::gen_bc(int bo, int bi, uint32 tpc, uint32 npc, bool direct_chaining) -{ - if (BO_CONDITIONAL_BRANCH(bo)) - gen_load_T1_crb(bi); - - switch (bo >> 1) { -#define _(A,B,C,D) (((A) << 3)| ((B) << 2) | ((C) << 1) | (D)) - case _(0,0,0,0): gen_op_prep_branch_bo_0000(); break; - case _(0,0,0,1): gen_op_prep_branch_bo_0001(); break; - case _(0,0,1,0): - case _(0,0,1,1): gen_op_prep_branch_bo_001x(); break; - case _(0,1,0,0): gen_op_prep_branch_bo_0100(); break; - case _(0,1,0,1): gen_op_prep_branch_bo_0101(); break; - case _(0,1,1,0): - case _(0,1,1,1): gen_op_prep_branch_bo_011x(); break; - case _(1,0,0,0): - case _(1,1,0,0): gen_op_prep_branch_bo_1x00(); break; - case _(1,0,0,1): - case _(1,1,0,1): gen_op_prep_branch_bo_1x01(); break; - case _(1,0,1,0): - case _(1,0,1,1): - case _(1,1,1,0): - case _(1,1,1,1): gen_op_prep_branch_bo_1x1x(); break; -#undef _ - default: abort(); - } - - if (BO_CONDITIONAL_BRANCH(bo) || BO_DECREMENT_CTR(bo)) { - // two-way branches - if (direct_chaining) - gen_op_branch_chain_2(); - else { - if (tpc != 0xffffffff) - gen_op_branch_2_im_im(tpc, npc); - else - gen_op_branch_2_T0_im(npc); - } - } - else { - // one-way branches - if (direct_chaining) - gen_op_branch_chain_1(); - else { - if (tpc != 0xffffffff) - gen_op_branch_1_im(tpc); - else - gen_op_branch_1_T0(); - } - } -} - -/** - * Vector instructions - **/ - -void powerpc_dyngen::gen_load_word_VD_T0(int vD) -{ - gen_load_ad_VD_VR(vD); - gen_op_load_word_VD_T0(); -} - -void powerpc_dyngen::gen_store_word_VS_T0(int vS) -{ - gen_load_ad_VD_VR(vS); - gen_op_store_word_VD_T0(); -} - -void powerpc_dyngen::gen_load_vect_VD_T0(int vD) -{ - gen_load_ad_VD_VR(vD); - gen_op_load_vect_VD_T0(); -} - -void powerpc_dyngen::gen_store_vect_VS_T0(int vS) -{ - gen_load_ad_VD_VR(vS); - gen_op_store_vect_VD_T0(); -} diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp deleted file mode 100644 index 10af38fd..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-dyngen.hpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * ppc-dyngen.hpp - PowerPC dynamic translation (low-level) - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_DYNGEN_H -#define PPC_DYNGEN_H - -#include "sysdeps.h" -#include "nvmemfun.hpp" -#include "cpu/ppc/ppc-config.hpp" - -#if PPC_ENABLE_JIT -#include "cpu/ppc/ppc-registers.hpp" -#include "cpu/jit/jit-config.hpp" -#include "cpu/jit/basic-dyngen.hpp" - -class powerpc_dyngen - : public basic_dyngen -{ -#ifndef REG_T3 - uintptr reg_T3; -#endif - -//#ifndef REG_F3 - powerpc_fpr reg_F3; -//#endif - - // Code generators for PowerPC synthetic instructions -#ifndef NO_DEFINE_ALIAS -# define DEFINE_GEN(NAME,RET,ARGS) RET NAME ARGS; -# include "ppc-dyngen-ops.hpp" -#endif - -public: - friend class powerpc_jit; - friend class powerpc_dyngen_helper; - - // Code generators - typedef nv_mem_fun_t< void, powerpc_dyngen > gen_handler_t; - - // Default constructor - powerpc_dyngen(dyngen_cpu_base cpu); - - // Generate prologue - uint8 *gen_start(uint32 pc); - - // Load/store registers - void gen_load_T0_GPR(int i); - void gen_load_T1_GPR(int i); - void gen_load_T2_GPR(int i); - void gen_store_T0_GPR(int i); - void gen_store_T1_GPR(int i); - void gen_store_T2_GPR(int i); - void gen_load_F0_FPR(int i); - void gen_load_F1_FPR(int i); - void gen_load_F2_FPR(int i); - void gen_store_FD_FPR(int i); - void gen_store_F0_FPR(int i); - void gen_store_F1_FPR(int i); - void gen_store_F2_FPR(int i); - - // Load/store multiple words - void gen_lmw_T0(int r); - void gen_stmw_T0(int r); - - // Raw aliases -#define DEFINE_ALIAS_RAW(NAME, PRE, POST, ARGLIST, ARGS) \ - void gen_##NAME ARGLIST { PRE; gen_op_##NAME ARGS; POST; } - -#define DEFINE_ALIAS_0(NAME,PRE,POST) DEFINE_ALIAS_RAW(NAME,PRE,POST,(),()) -#define DEFINE_ALIAS_1(NAME,PRE,POST) DEFINE_ALIAS_RAW(NAME,PRE,POST,(long p1),(p1)) -#define DEFINE_ALIAS_2(NAME,PRE,POST) DEFINE_ALIAS_RAW(NAME,PRE,POST,(long p1,long p2),(p1,p2)) -#define DEFINE_ALIAS_3(NAME,PRE,POST) DEFINE_ALIAS_RAW(NAME,PRE,POST,(long p1,long p2,long p3),(p1,p2,p3)) -#ifdef NO_DEFINE_ALIAS -#define DEFINE_ALIAS(NAME,N) -#else -#define DEFINE_ALIAS(NAME,N) DEFINE_ALIAS_##N(NAME,,) -#endif - - // Misc instructions -#if KPX_MAX_CPUS == 1 - DEFINE_ALIAS(lwarx_T0_T1,0); - DEFINE_ALIAS(stwcx_T0_T1,0); -#endif - DEFINE_ALIAS(inc_32_mem,1); - DEFINE_ALIAS(nego_T0,0); - DEFINE_ALIAS(dcbz_T0,0); - - // Condition registers - DEFINE_ALIAS(load_T0_CR,0); - DEFINE_ALIAS(store_T0_CR,0); - void gen_load_T0_crf(int crf); - void gen_store_T0_crf(int crf); - void gen_load_T0_crb(int i); - void gen_load_T1_crb(int i); - void gen_store_T0_crb(int i); - void gen_store_T1_crb(int i); - void gen_mtcrf_T0_im(uint32 mask); - - // Special purpose registers - DEFINE_ALIAS(load_T0_VRSAVE,0); - DEFINE_ALIAS(store_T0_VRSAVE,0); - DEFINE_ALIAS(load_T0_XER,0); - DEFINE_ALIAS(store_T0_XER,0); - DEFINE_ALIAS(load_T0_PC,0); - DEFINE_ALIAS(store_T0_PC,0); - DEFINE_ALIAS(set_PC_im,1); - DEFINE_ALIAS(set_PC_T0,0); - DEFINE_ALIAS(inc_PC,1); - DEFINE_ALIAS(load_T0_LR,0); - DEFINE_ALIAS(store_T0_LR,0); - DEFINE_ALIAS(load_T0_CTR,0); - DEFINE_ALIAS(load_T0_CTR_aligned,0); - DEFINE_ALIAS(store_T0_CTR,0); - DEFINE_ALIAS(load_T0_LR_aligned,0); - DEFINE_ALIAS(store_im_LR,1); - - DEFINE_ALIAS(spcflags_init,1); - DEFINE_ALIAS(spcflags_set,1); - DEFINE_ALIAS(spcflags_clear,1); - - // Control Flow - DEFINE_ALIAS(jump_next_A0,0); - - // Compare & Record instructions - DEFINE_ALIAS(record_cr0_T0,0); - DEFINE_ALIAS(record_cr1,0); - void gen_compare_T0_T1(int crf); - void gen_compare_T0_im(int crf, int32 value); - void gen_compare_logical_T0_T1(int crf); - void gen_compare_logical_T0_im(int crf, int32 value); - - // Multiply/Divide instructions - DEFINE_ALIAS(mulhw_T0_T1,0); - DEFINE_ALIAS(mulhwu_T0_T1,0); - DEFINE_ALIAS(mulli_T0_im,1); - DEFINE_ALIAS(mullwo_T0_T1,0); - DEFINE_ALIAS(divw_T0_T1,0); - DEFINE_ALIAS(divwo_T0_T1,0); - DEFINE_ALIAS(divwu_T0_T1,0); - DEFINE_ALIAS(divwuo_T0_T1,0); - - // Shift/Rotate instructions - DEFINE_ALIAS(slw_T0_T1,0); - DEFINE_ALIAS(srw_T0_T1,0); - DEFINE_ALIAS(sraw_T0_T1,0); - DEFINE_ALIAS(sraw_T0_im,1); - DEFINE_ALIAS(rlwimi_T0_T1,2); - DEFINE_ALIAS(rlwinm_T0_T1,2); - DEFINE_ALIAS(rlwnm_T0_T1,1); - DEFINE_ALIAS(cntlzw_32_T0,0); - - // Add/Sub related instructions - DEFINE_ALIAS(addo_T0_T1,0); - DEFINE_ALIAS(addc_T0_im,1); - DEFINE_ALIAS(addc_T0_T1,0); - DEFINE_ALIAS(addco_T0_T1,0); - DEFINE_ALIAS(adde_T0_T1,0); - DEFINE_ALIAS(addeo_T0_T1,0); - DEFINE_ALIAS(addme_T0,0); - DEFINE_ALIAS(addmeo_T0,0); - DEFINE_ALIAS(addze_T0,0); - DEFINE_ALIAS(addzeo_T0,0); - DEFINE_ALIAS(subf_T0_T1,0); - DEFINE_ALIAS(subfo_T0_T1,0); - DEFINE_ALIAS(subfc_T0_im,1); - DEFINE_ALIAS(subfc_T0_T1,0); - DEFINE_ALIAS(subfco_T0_T1,0); - DEFINE_ALIAS(subfe_T0_T1,0); - DEFINE_ALIAS(subfeo_T0_T1,0); - DEFINE_ALIAS(subfme_T0,0); - DEFINE_ALIAS(subfmeo_T0,0); - DEFINE_ALIAS(subfze_T0,0); - DEFINE_ALIAS(subfzeo_T0,0); - - // Double-precision floating point operations - DEFINE_ALIAS(fmov_F0_F1,0); - DEFINE_ALIAS(fmov_F0_F2,0); - DEFINE_ALIAS(fmov_F1_F0,0); - DEFINE_ALIAS(fmov_F1_F2,0); - DEFINE_ALIAS(fmov_F2_F0,0); - DEFINE_ALIAS(fmov_F2_F1,0); - DEFINE_ALIAS(fmov_FD_F0,0); - DEFINE_ALIAS(fmov_FD_F1,0); - DEFINE_ALIAS(fmov_FD_F2,0); - DEFINE_ALIAS(fabs_FD_F0,0); - DEFINE_ALIAS(fneg_FD_F0,0); - DEFINE_ALIAS(fnabs_FD_F0,0); - DEFINE_ALIAS(fadd_FD_F0_F1,0); - DEFINE_ALIAS(fsub_FD_F0_F1,0); - DEFINE_ALIAS(fmul_FD_F0_F1,0); - DEFINE_ALIAS(fdiv_FD_F0_F1,0); - DEFINE_ALIAS(fmadd_FD_F0_F1_F2,0); - DEFINE_ALIAS(fmsub_FD_F0_F1_F2,0); - DEFINE_ALIAS(fnmadd_FD_F0_F1_F2,0); - DEFINE_ALIAS(fnmsub_FD_F0_F1_F2,0); - - // Single-precision floating point operations - DEFINE_ALIAS(fadds_FD_F0_F1,0); - DEFINE_ALIAS(fsubs_FD_F0_F1,0); - DEFINE_ALIAS(fmuls_FD_F0_F1,0); - DEFINE_ALIAS(fdivs_FD_F0_F1,0); - DEFINE_ALIAS(fmadds_FD_F0_F1_F2,0); - DEFINE_ALIAS(fmsubs_FD_F0_F1_F2,0); - DEFINE_ALIAS(fnmadds_FD_F0_F1_F2,0); - DEFINE_ALIAS(fnmsubs_FD_F0_F1_F2,0); - - // Load/store floating point data - DEFINE_ALIAS(load_double_FD_T1_T2,0); - void gen_load_double_FD_T1_im(int32 offset); - DEFINE_ALIAS(load_single_FD_T1_T2,0); - void gen_load_single_FD_T1_im(int32 offset); - DEFINE_ALIAS(store_double_F0_T1_T2,0); - void gen_store_double_F0_T1_im(int32 offset); - DEFINE_ALIAS(store_single_F0_T1_T2,0); - void gen_store_single_F0_T1_im(int32 offset); - - // Branch instructions - void gen_bc(int bo, int bi, uint32 tpc, uint32 npc, bool direct_chaining); - - // Vector instructions - void gen_load_ad_VD_VR(int i); - void gen_load_ad_V0_VR(int i); - void gen_load_ad_V1_VR(int i); - void gen_load_ad_V2_VR(int i); - void gen_load_word_VD_T0(int vD); - void gen_load_vect_VD_T0(int vD); - void gen_store_word_VS_T0(int vS); - void gen_store_vect_VS_T0(int vS); - DEFINE_ALIAS(record_cr6_VD,0); - DEFINE_ALIAS(mfvscr_VD,0); - DEFINE_ALIAS(mtvscr_V0,0); - -#undef DEFINE_ALIAS -#undef DEFINE_ALIAS_0 -#undef DEFINE_ALIAS_1 -#undef DEFINE_ALIAS_2 -#undef DEFINE_ALIAS_3 -#undef DEFINE_ALIAS_RAW -}; - -#endif /* PPC_ENABLE_JIT */ - -#endif /* PPC_DYNGEN_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp deleted file mode 100644 index 26e98533..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.cpp +++ /dev/null @@ -1,1787 +0,0 @@ -/* - * ppc-execute.cpp - PowerPC semantics - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include - -#include "cpu/vm.hpp" -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-bitfields.hpp" -#include "cpu/ppc/ppc-operands.hpp" -#include "cpu/ppc/ppc-operations.hpp" -#include "cpu/ppc/ppc-execute.hpp" - -#ifndef SHEEPSHAVER -#include "basic-kernel.hpp" -#endif - -#ifdef SHEEPSHAVER -#include "main.h" -#include "prefs.h" -#endif - -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif - -#define DEBUG 0 -#include "debug.h" - -/** - * Illegal & NOP instructions - **/ - -void powerpc_cpu::execute_illegal(uint32 opcode) -{ - fprintf(stderr, "Illegal instruction at %08x, opcode = %08x\n", pc(), opcode); - -#ifdef SHEEPSHAVER - if (PrefsFindBool("ignoreillegal")) { - increment_pc(4); - return; - } -#endif - -#if ENABLE_MON - disass_ppc(stdout, pc(), opcode); - - // Start up mon in real-mode - char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); -#endif - abort(); -} - -void powerpc_cpu::execute_nop(uint32 opcode) -{ - increment_pc(4); -} - -/** - * Floating-point rounding modes conversion - **/ - -static inline int ppc_to_native_rounding_mode(int round) -{ - switch (round) { - case 0: return FE_TONEAREST; - case 1: return FE_TOWARDZERO; - case 2: return FE_UPWARD; - case 3: return FE_DOWNWARD; - } -} - -static inline int native_to_ppc_rounding_mode(int round) -{ - switch (round) { - case FE_TONEAREST: return 0; - case FE_TOWARDZERO: return 1; - case FE_UPWARD: return 2; - case FE_DOWNWARD: return 3; - } -} - -/** - * Helper class to compute the overflow/carry condition - * - * OP Operation to perform - */ - -template< class OP > -struct op_carry { - static inline bool apply(uint32, uint32, uint32) { - return false; - } -}; - -template<> -struct op_carry { - static inline bool apply(uint32 a, uint32 b, uint32 c) { - // TODO: use 32-bit arithmetics - uint64 carry = (uint64)a + (uint64)b + (uint64)c; - return (carry >> 32) != 0; - } -}; - -template< class OP > -struct op_overflow { - static inline bool apply(uint32, uint32, uint32) { - return false; - } -}; - -template<> -struct op_overflow { - static inline bool apply(uint32 a, uint32, uint32) { - return a == 0x80000000; - }; -}; - -template<> -struct op_overflow { - static inline bool apply(uint32 a, uint32 b, uint32 c) { - // TODO: use 32-bit arithmetics - int64 overflow = (int64)(int32)a + (int64)(int32)b + (int64)(int32)c; - return (((uint64)overflow) >> 63) ^ (((uint32)overflow) >> 31); - } -}; - -/** - * Perform an addition/substraction - * - * RA Input operand register, possibly 0 - * RB Input operand either register or immediate - * RC Input carry - * CA Predicate to compute the carry out of the operation - * OE Predicate to compute the overflow flag - * Rc Predicate to record CR0 - **/ - -template< class RA, class RB, class RC, class CA, class OE, class Rc > -void powerpc_cpu::execute_addition(uint32 opcode) -{ - const uint32 a = RA::get(this, opcode); - const uint32 b = RB::get(this, opcode); - const uint32 c = RC::get(this, opcode); - uint32 d = a + b + c; - - // Set XER (CA) if instruction affects carry bit - if (CA::test(opcode)) - xer().set_ca(op_carry::apply(a, b, c)); - - // Set XER (OV, SO) if instruction has OE set - if (OE::test(opcode)) - xer().set_ov(op_overflow::apply(a, b, c)); - - // Set CR0 (LT, GT, EQ, SO) if instruction has Rc set - if (Rc::test(opcode)) - record_cr0((int32)d); - - // Commit result to output operand - operand_RD::set(this, opcode, d); - - increment_pc(4); -} - -/** - * Generic arithmetic instruction - * - * OP Operation to perform - * RD Output register - * RA Input operand register - * RB Input operand register or immediate (optional: operand_NONE) - * RC Input operand register or immediate (optional: operand_NONE) - * OE Predicate to compute overflow flag - * Rc Predicate to record CR0 - **/ - -template< class OP, class RD, class RA, class RB, class RC, class OE, class Rc > -void powerpc_cpu::execute_generic_arith(uint32 opcode) -{ - const uint32 a = RA::get(this, opcode); - const uint32 b = RB::get(this, opcode); - const uint32 c = RC::get(this, opcode); - - uint32 d = op_apply::apply(a, b, c); - - // Set XER (OV, SO) if instruction has OE set - if (OE::test(opcode)) - xer().set_ov(op_overflow::apply(a, b, c)); - - // Set CR0 (LT, GT, EQ, SO) if instruction has Rc set - if (Rc::test(opcode)) - record_cr0((int32)d); - - // commit result to output operand - RD::set(this, opcode, d); - - increment_pc(4); -} - -/** - * Rotate Left Word Immediate then Mask Insert - * - * SH Shift count - * MA Mask value - * Rc Predicate to record CR0 - **/ - -template< class SH, class MA, class Rc > -void powerpc_cpu::execute_rlwimi(uint32 opcode) -{ - const uint32 n = SH::get(this, opcode); - const uint32 m = MA::get(this, opcode); - const uint32 rs = operand_RS::get(this, opcode); - const uint32 ra = operand_RA::get(this, opcode); - uint32 d = op_ppc_rlwimi::apply(rs, n, m, ra); - - // Set CR0 (LT, GT, EQ, SO) if instruction has Rc set - if (Rc::test(opcode)) - record_cr0((int32)d); - - // Commit result to output operand - operand_RA::set(this, opcode, d); - - increment_pc(4); -} - -/** - * Shift instructions - * - * OP Operation to perform - * RD Output operand - * RA Source operand - * SH Shift count - * SO Shift operation - * CA Predicate to compute carry bit - * Rc Predicate to record CR0 - **/ - -template< class OP > -struct invalid_shift { - static inline uint32 value(uint32) { - return 0; - } -}; - -template<> -struct invalid_shift { - static inline uint32 value(uint32 r) { - return 0 - (r >> 31); - } -}; - -template< class OP, class RD, class RA, class SH, class SO, class CA, class Rc > -void powerpc_cpu::execute_shift(uint32 opcode) -{ - const uint32 n = SO::apply(SH::get(this, opcode)); - const uint32 r = RA::get(this, opcode); - uint32 d; - - // Shift operation is valid only if rB[26] = 0 - if (n & 0x20) { - d = invalid_shift::value(r); - if (CA::test(opcode)) - xer().set_ca(d >> 31); - } - else { - d = OP::apply(r, n); - if (CA::test(opcode)) { - const uint32 ca = (r & 0x80000000) && (r & ~(0xffffffff << n)); - xer().set_ca(ca); - } - } - - // Set CR0 (LT, GT, EQ, SO) if instruction has Rc set - if (Rc::test(opcode)) - record_cr0((int32)d); - - // Commit result to output operand - RD::set(this, opcode, d); - - increment_pc(4); -} - -/** - * Branch conditional instructions - * - * PC Input program counter (PC, LR, CTR) - * BO BO operand - * DP Displacement operand - * AA Predicate for absolute address - * LK Predicate to record NPC into link register - **/ - -template< class PC, class BO, class DP, class AA, class LK > -void powerpc_cpu::execute_branch(uint32 opcode) -{ - const int bo = BO::get(this, opcode); - bool ctr_ok = true; - bool cond_ok = true; - - if (BO_CONDITIONAL_BRANCH(bo)) { - cond_ok = cr().test(BI_field::extract(opcode)); - if (!BO_BRANCH_IF_TRUE(bo)) - cond_ok = !cond_ok; - } - - if (BO_DECREMENT_CTR(bo)) { - ctr_ok = (ctr() -= 1) == 0; - if (!BO_BRANCH_IF_CTR_ZERO(bo)) - ctr_ok = !ctr_ok; - } - - const uint32 npc = pc() + 4; - if (ctr_ok && cond_ok) - pc() = ((AA::test(opcode) ? 0 : PC::get(this, opcode)) + DP::get(this, opcode)) & -4; - else - pc() = npc; - - if (LK::test(opcode)) - lr() = npc; -} - -/** - * Compare instructions - * - * RB Second operand (GPR, SIMM, UIMM) - * CT Type of variables to be compared (uint32, int32) - **/ - -template< class RB, typename CT > -void powerpc_cpu::execute_compare(uint32 opcode) -{ - const uint32 a = operand_RA::get(this, opcode); - const uint32 b = RB::get(this, opcode); - const uint32 crfd = crfD_field::extract(opcode); - record_cr(crfd, (CT)a < (CT)b ? -1 : ((CT)a > (CT)b ? +1 : 0)); - increment_pc(4); -} - -/** - * Operations on condition register - * - * OP Operation to perform - **/ - -template< class OP > -void powerpc_cpu::execute_cr_op(uint32 opcode) -{ - const uint32 crbA = crbA_field::extract(opcode); - uint32 a = (cr().get() >> (31 - crbA)) & 1; - const uint32 crbB = crbB_field::extract(opcode); - uint32 b = (cr().get() >> (31 - crbB)) & 1; - const uint32 crbD = crbD_field::extract(opcode); - uint32 d = OP::apply(a, b) & 1; - cr().set((cr().get() & ~(1 << (31 - crbD))) | (d << (31 - crbD))); - increment_pc(4); -} - -/** - * Divide instructions - * - * SB Signed division - * OE Predicate to compute overflow - * Rc Predicate to record CR0 - **/ - -template< bool SB, class OE, class Rc > -void powerpc_cpu::execute_divide(uint32 opcode) -{ - const uint32 a = operand_RA::get(this, opcode); - const uint32 b = operand_RB::get(this, opcode); - uint32 d; - - // Specialize divide semantic action - if (OE::test(opcode)) - d = do_execute_divide(a, b); - else - d = do_execute_divide(a, b); - - // Set CR0 (LT, GT, EQ, SO) if instruction has Rc set - if (Rc::test(opcode)) - record_cr0((int32)d); - - // Commit result to output operand - operand_RD::set(this, opcode, d); - - increment_pc(4); -} - -/** - * Multiply instructions - * - * HI Predicate for multiply high word - * SB Predicate for signed operation - * OE Predicate to compute overflow - * Rc Predicate to record CR0 - **/ - -template< bool HI, bool SB, class OE, class Rc > -void powerpc_cpu::execute_multiply(uint32 opcode) -{ - const uint32 a = operand_RA::get(this, opcode); - const uint32 b = operand_RB::get(this, opcode); - uint64 d = SB ? (int64)(int32)a * (int64)(int32)b : (uint64)a * (uint64)b; - - // Overflow if the product cannot be represented in 32 bits - if (OE::test(opcode)) { - xer().set_ov((d & UVAL64(0xffffffff80000000)) != 0 && - (d & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)); - } - - // Only keep high word if multiply high instruction - if (HI) - d >>= 32; - - // Set CR0 (LT, GT, EQ, SO) if instruction has Rc set - if (Rc::test(opcode)) - record_cr0((uint32)d); - - // Commit result to output operand - operand_RD::set(this, opcode, (uint32)d); - - increment_pc(4); -} - -/** - * Record FPSCR - * - * Update FP exception bits - **/ - -void powerpc_cpu::record_fpscr(int exceptions) -{ -#if PPC_ENABLE_FPU_EXCEPTIONS - // Reset non-sticky bits - fpscr() &= ~(FPSCR_VX_field::mask() | FPSCR_FEX_field::mask()); - - // Always update FX if any exception bit was set - if (exceptions) - fpscr() |= FPSCR_FX_field::mask() | exceptions; - - // Always update VX - if (fpscr() & (FPSCR_VXSNAN_field::mask() | FPSCR_VXISI_field::mask() | - FPSCR_VXISI_field::mask() | FPSCR_VXIDI_field::mask() | - FPSCR_VXZDZ_field::mask() | FPSCR_VXIMZ_field::mask() | - FPSCR_VXVC_field::mask() | FPSCR_VXSOFT_field::mask() | - FPSCR_VXSQRT_field::mask() | FPSCR_VXCVI_field::mask())) - fpscr() |= FPSCR_VX_field::mask(); - - // Always update FEX - if (((fpscr() & FPSCR_VX_field::mask()) && (fpscr() & FPSCR_VE_field::mask())) || - ((fpscr() & FPSCR_OX_field::mask()) && (fpscr() & FPSCR_OE_field::mask())) || - ((fpscr() & FPSCR_UX_field::mask()) && (fpscr() & FPSCR_UE_field::mask())) || - ((fpscr() & FPSCR_ZX_field::mask()) && (fpscr() & FPSCR_ZE_field::mask())) || - ((fpscr() & FPSCR_XX_field::mask()) && (fpscr() & FPSCR_XE_field::mask()))) - fpscr() |= FPSCR_FEX_field::mask(); -#endif -} - -/** - * Floating-point arithmetics - * - * FP Floating Point type - * OP Operation to perform - * RD Output register - * RA Input operand - * RB Input operand (optional) - * RC Input operand (optional) - * Rc Predicate to record CR1 - * FPSCR Predicate to compute FPSCR bits - **/ - -template< class FP, class OP, class RD, class RA, class RB, class RC, class Rc, bool FPSCR > -void powerpc_cpu::execute_fp_arith(uint32 opcode) -{ - const double a = RA::get(this, opcode); - const double b = RB::get(this, opcode); - const double c = RC::get(this, opcode); - -#if PPC_ENABLE_FPU_EXCEPTIONS - int exceptions; - if (FPSCR) { - exceptions = op_apply, RA, RB, RC>::apply(a, b, c); - feclearexcept(FE_ALL_EXCEPT); - febarrier(); - } -#endif - - FP d = op_apply::apply(a, b, c); - - if (FPSCR) { - - // Update FPSCR exception bits -#if PPC_ENABLE_FPU_EXCEPTIONS - febarrier(); - int raised = fetestexcept(FE_ALL_EXCEPT); - if (raised & FE_INEXACT) - exceptions |= FPSCR_XX_field::mask(); - if (raised & FE_DIVBYZERO) - exceptions |= FPSCR_ZX_field::mask(); - if (raised & FE_UNDERFLOW) - exceptions |= FPSCR_UX_field::mask(); - if (raised & FE_OVERFLOW) - exceptions |= FPSCR_OX_field::mask(); - record_fpscr(exceptions); -#endif - - // FPSCR[FPRF] is set to the class and sign of the result - if (!FPSCR_VE_field::test(fpscr())) - fp_classify(d); - } - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - // Commit result to output operand - RD::set(this, opcode, d); - increment_pc(4); -} - -/** - * Load/store instructions - * - * OP Operation to perform on loaded value - * RA Base operand - * RB Displacement (GPR(RB), EXTS(d)) - * LD Load operation? - * SZ Size of load/store operation - * UP Update RA with EA - * RX Reverse operand - **/ - -template< int SZ, bool RX > -struct memory_helper; - -#define DEFINE_MEMORY_HELPER(SIZE) \ -template< bool RX > \ -struct memory_helper \ -{ \ - static inline uint32 load(uint32 ea) { \ - return RX ? vm_read_memory_##SIZE##_reversed(ea) : vm_read_memory_##SIZE(ea); \ - } \ - static inline void store(uint32 ea, uint32 value) { \ - RX ? vm_write_memory_##SIZE##_reversed(ea, value) : vm_write_memory_##SIZE(ea, value); \ - } \ -} - -DEFINE_MEMORY_HELPER(1); -DEFINE_MEMORY_HELPER(2); -DEFINE_MEMORY_HELPER(4); - -template< class OP, class RA, class RB, bool LD, int SZ, bool UP, bool RX > -void powerpc_cpu::execute_loadstore(uint32 opcode) -{ - const uint32 a = RA::get(this, opcode); - const uint32 b = RB::get(this, opcode); - const uint32 ea = a + b; - - if (LD) - operand_RD::set(this, opcode, OP::apply(memory_helper::load(ea))); - else - memory_helper::store(ea, operand_RS::get(this, opcode)); - - if (UP) - RA::set(this, opcode, ea); - - increment_pc(4); -} - -template< class RA, class DP, bool LD > -void powerpc_cpu::execute_loadstore_multiple(uint32 opcode) -{ - const uint32 a = RA::get(this, opcode); - const uint32 d = DP::get(this, opcode); - uint32 ea = a + d; - - // FIXME: generate exception if ea is not word-aligned - if ((ea & 3) != 0) { -#ifdef SHEEPSHAVER - D(bug("unaligned load/store multiple to %08x\n", ea)); - increment_pc(4); - return; -#else - abort(); -#endif - } - - int r = LD ? rD_field::extract(opcode) : rS_field::extract(opcode); - while (r <= 31) { - if (LD) - gpr(r) = vm_read_memory_4(ea); - else - vm_write_memory_4(ea, gpr(r)); - r++; - ea += 4; - } - - increment_pc(4); -} - -/** - * Floating-point load/store instructions - * - * RA Base operand - * RB Displacement (GPR(RB), EXTS(d)) - * LD Load operation? - * DB Predicate for double value - * UP Predicate to update RA with EA - **/ - -template< class RA, class RB, bool LD, bool DB, bool UP > -void powerpc_cpu::execute_fp_loadstore(uint32 opcode) -{ - const uint32 a = RA::get(this, opcode); - const uint32 b = RB::get(this, opcode); - const uint32 ea = a + b; - uint64 v; - - if (LD) { - if (DB) - v = vm_read_memory_8(ea); - else - v = fp_load_single_convert(vm_read_memory_4(ea)); - operand_fp_dw_RD::set(this, opcode, v); - } - else { - v = operand_fp_dw_RS::get(this, opcode); - if (DB) - vm_write_memory_8(ea, v); - else - vm_write_memory_4(ea, fp_store_single_convert(v)); - } - - if (UP) - RA::set(this, opcode, ea); - - increment_pc(4); -} - -/** - * Load/Store String Word instruction - * - * RA Input operand as base EA - * IM lswi mode? - * NB Number of bytes to transfer - **/ - -template< class RA, bool IM, class NB > -void powerpc_cpu::execute_load_string(uint32 opcode) -{ - uint32 ea = RA::get(this, opcode); - if (!IM) - ea += operand_RB::get(this, opcode); - - int nb = NB::get(this, opcode); - if (IM && nb == 0) - nb = 32; - - int rd = rD_field::extract(opcode); -#if 1 - int i; - for (i = 0; nb - i >= 4; i += 4, rd = (rd + 1) & 0x1f) - gpr(rd) = vm_read_memory_4(ea + i); - switch (nb - i) { - case 1: - gpr(rd) = vm_read_memory_1(ea + i) << 24; - break; - case 2: - gpr(rd) = vm_read_memory_2(ea + i) << 16; - break; - case 3: - gpr(rd) = (vm_read_memory_2(ea + i) << 16) + (vm_read_memory_1(ea + i + 2) << 8); - break; - } -#else - for (int i = 0; i < nb; i++) { - switch (i & 3) { - case 0: - gpr(rd) = vm_read_memory_1(ea + i) << 24; - break; - case 1: - gpr(rd) = (gpr(rd) & 0xff00ffff) | (vm_read_memory_1(ea + i) << 16); - break; - case 2: - gpr(rd) = (gpr(rd) & 0xffff00ff) | (vm_read_memory_1(ea + i) << 8); - break; - case 3: - gpr(rd) = (gpr(rd) & 0xffffff00) | vm_read_memory_1(ea + i); - rd = (rd + 1) & 0x1f; - break; - } - } -#endif - - increment_pc(4); -} - -template< class RA, bool IM, class NB > -void powerpc_cpu::execute_store_string(uint32 opcode) -{ - uint32 ea = RA::get(this, opcode); - if (!IM) - ea += operand_RB::get(this, opcode); - - int nb = NB::get(this, opcode); - if (IM && nb == 0) - nb = 32; - - int rs = rS_field::extract(opcode); - int sh = 24; - for (int i = 0; i < nb; i++) { - vm_write_memory_1(ea + i, gpr(rs) >> sh); - sh -= 8; - if (sh < 0) { - sh = 24; - rs = (rs + 1) & 0x1f; - } - } - - increment_pc(4); -} - -/** - * Load Word and Reserve Indexed / Store Word Conditional Indexed - * - * RA Input operand as base EA - **/ - -template< class RA > -void powerpc_cpu::execute_lwarx(uint32 opcode) -{ - const uint32 ea = RA::get(this, opcode) + operand_RB::get(this, opcode); - uint32 reserve_data = vm_read_memory_4(ea); - regs().reserve_valid = 1; - regs().reserve_addr = ea; -#if KPX_MAX_CPUS != 1 - regs().reserve_data = reserve_data; -#endif - operand_RD::set(this, opcode, reserve_data); - increment_pc(4); -} - -template< class RA > -void powerpc_cpu::execute_stwcx(uint32 opcode) -{ - const uint32 ea = RA::get(this, opcode) + operand_RB::get(this, opcode); - cr().clear(0); - if (regs().reserve_valid) { - if (regs().reserve_addr == ea /* physical_addr(EA) */ -#if KPX_MAX_CPUS != 1 - /* HACK: if another processor wrote to the reserved block, - nothing happens, i.e. we should operate as if reserve == 0 */ - && regs().reserve_data == vm_read_memory_4(ea) -#endif - ) { - vm_write_memory_4(ea, operand_RS::get(this, opcode)); - cr().set(0, standalone_CR_EQ_field::mask()); - } - regs().reserve_valid = 0; - } - cr().set_so(0, xer().get_so()); - increment_pc(4); -} - -/** - * Floating-point compare instruction - * - * OC Predicate for ordered compare - **/ - -template< bool OC > -void powerpc_cpu::execute_fp_compare(uint32 opcode) -{ - const double a = operand_fp_RA::get(this, opcode); - const double b = operand_fp_RB::get(this, opcode); - const int crfd = crfD_field::extract(opcode); - int c; - - if (is_NaN(a) || is_NaN(b)) - c = 1; - else if (isless(a, b)) - c = 8; - else if (isgreater(a, b)) - c = 4; - else - c = 2; - - FPSCR_FPCC_field::insert(fpscr(), c); - cr().set(crfd, c); - - // Update FPSCR exception bits -#if PPC_ENABLE_FPU_EXCEPTIONS - int exceptions = 0; - if (is_SNaN(a) || is_SNaN(b)) { - exceptions |= FPSCR_VXSNAN_field::mask(); - if (OC && !FPSCR_VE_field::test(fpscr())) - exceptions |= FPSCR_VXVC_field::mask(); - } - else if (OC && (is_QNaN(a) || is_QNaN(b))) - exceptions |= FPSCR_VXVC_field::mask(); - record_fpscr(exceptions); -#endif - - increment_pc(4); -} - -/** - * Floating Convert to Integer Word instructions - * - * RN Rounding mode - * Rc Predicate to record CR1 - **/ - -template< class RN, class Rc > -void powerpc_cpu::execute_fp_int_convert(uint32 opcode) -{ - const double b = operand_fp_RB::get(this, opcode); - const uint32 r = RN::get(this, opcode); - any_register d; - -#if PPC_ENABLE_FPU_EXCEPTIONS - int exceptions = 0; - if (is_NaN(b)) { - exceptions |= FPSCR_VXCVI_field::mask(); - if (is_SNaN(b)) - exceptions |= FPSCR_VXSNAN_field::mask(); - } - if (isinf(b)) - exceptions |= FPSCR_VXCVI_field::mask(); - - feclearexcept(FE_ALL_EXCEPT); - febarrier(); -#endif - - // Convert to integer word if operand fits bounds - if (b >= -(double)0x80000000 && b <= (double)0x7fffffff) { -#if defined mathlib_lrint - int old_round = fegetround(); - fesetround(ppc_to_native_rounding_mode(r)); - d.j = (int32)mathlib_lrint(b); - fesetround(old_round); -#else - switch (r) { - case 0: d.j = (int32)op_frin::apply(b); break; // near - case 1: d.j = (int32)op_friz::apply(b); break; // zero - case 2: d.j = (int32)op_frip::apply(b); break; // +inf - case 3: d.j = (int32)op_frim::apply(b); break; // -inf - } -#endif - } - - // NOTE: this catches infinity and NaN operands - else if (b > 0) - d.j = 0x7fffffff; - else - d.j = 0x80000000; - - // Update FPSCR exception bits -#if PPC_ENABLE_FPU_EXCEPTIONS - febarrier(); - int raised = fetestexcept(FE_ALL_EXCEPT); - if (raised & FE_UNDERFLOW) - exceptions |= FPSCR_UX_field::mask(); - if (raised & FE_INEXACT) - exceptions |= FPSCR_XX_field::mask(); - record_fpscr(exceptions); -#endif - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - // Commit result to output operand - operand_fp_RD::set(this, opcode, d.d); - increment_pc(4); -} - -/** - * Floating-point Round to Single - * - * Rc Predicate to record CR1 - **/ - -template< class FP > -void powerpc_cpu::fp_classify(FP x) -{ - uint32 c = fpscr() & ~FPSCR_FPRF_field::mask(); - uint8 fc = fpclassify(x); - switch (fc) { - case FP_NAN: - c |= FPSCR_FPRF_FU_field::mask() | FPSCR_FPRF_C_field::mask(); - break; - case FP_ZERO: - c |= FPSCR_FPRF_FE_field::mask(); - if (signbit(x)) - c |= FPSCR_FPRF_C_field::mask(); - break; - case FP_INFINITE: - c |= FPSCR_FPRF_FU_field::mask(); - goto FL_FG_field; - case FP_SUBNORMAL: - c |= FPSCR_FPRF_C_field::mask(); - // fall-through - case FP_NORMAL: - FL_FG_field: - if (x < 0) - c |= FPSCR_FPRF_FL_field::mask(); - else - c |= FPSCR_FPRF_FG_field::mask(); - break; - } - fpscr() = c; -} - -template< class Rc > -void powerpc_cpu::execute_fp_round(uint32 opcode) -{ - const double b = operand_fp_RB::get(this, opcode); - -#if PPC_ENABLE_FPU_EXCEPTIONS - int exceptions = - fp_invalid_operation_condition:: - apply(FPSCR_VXSNAN_field::mask(), b); - - feclearexcept(FE_ALL_EXCEPT); - febarrier(); -#endif - - float d = (float)b; - - // Update FPSCR exception bits -#if PPC_ENABLE_FPU_EXCEPTIONS - febarrier(); - int raised = fetestexcept(FE_ALL_EXCEPT); - if (raised & FE_UNDERFLOW) - exceptions |= FPSCR_UX_field::mask(); - if (raised & FE_OVERFLOW) - exceptions |= FPSCR_OX_field::mask(); - if (raised & FE_INEXACT) - exceptions |= FPSCR_XX_field::mask(); - record_fpscr(exceptions); -#endif - - // FPSCR[FPRF] is set to the class and sign of the result - if (!FPSCR_VE_field::test(fpscr())) - fp_classify(d); - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - // Commit result to output operand - operand_fp_RD::set(this, opcode, (double)d); - increment_pc(4); -} - -/** - * System Call instruction - **/ - -void powerpc_cpu::execute_syscall(uint32 opcode) -{ -#ifdef SHEEPSHAVER - execute_illegal(opcode); -#else - cr().set_so(0, execute_do_syscall && !execute_do_syscall(this)); -#endif - increment_pc(4); -} - -/** - * Instructions dealing with system registers - **/ - -void powerpc_cpu::execute_mcrf(uint32 opcode) -{ - const int crfS = crfS_field::extract(opcode); - const int crfD = crfD_field::extract(opcode); - cr().set(crfD, cr().get(crfS)); - increment_pc(4); -} - -void powerpc_cpu::execute_mcrfs(uint32 opcode) -{ - const int crfS = crfS_field::extract(opcode); - const int crfD = crfD_field::extract(opcode); - - // The contents of FPSCR field crfS are copied to CR field crfD - const uint32 m = 0xf << (28 - 4 * crfS); - cr().set(crfD, (fpscr() & m) >> (28 - 4 * crfS)); - - // All exception bits copied (except FEX and VX) are cleared in the FPSCR - fpscr() &= ~(m & (FPSCR_FX_field::mask() | FPSCR_OX_field::mask() | - FPSCR_UX_field::mask() | FPSCR_ZX_field::mask() | - FPSCR_XX_field::mask() | FPSCR_VXSNAN_field::mask() | - FPSCR_VXISI_field::mask() | FPSCR_VXIDI_field::mask() | - FPSCR_VXZDZ_field::mask() | FPSCR_VXIMZ_field::mask() | - FPSCR_VXVC_field::mask() | FPSCR_VXSOFT_field::mask() | - FPSCR_VXSQRT_field::mask() | FPSCR_VXCVI_field::mask())); - - increment_pc(4); -} - -void powerpc_cpu::execute_mcrxr(uint32 opcode) -{ - const int crfD = crfD_field::extract(opcode); - const uint32 x = xer().get(); - cr().set(crfD, x >> 28); - xer().set(x & 0x0fffffff); - increment_pc(4); -} - -void powerpc_cpu::execute_mtcrf(uint32 opcode) -{ - uint32 mask = field2mask[CRM_field::extract(opcode)]; - cr().set((operand_RS::get(this, opcode) & mask) | (cr().get() & ~mask)); - increment_pc(4); -} - -template< class FM, class RB, class Rc > -void powerpc_cpu::execute_mtfsf(uint32 opcode) -{ - const uint64 fsf = RB::get(this, opcode); - const uint32 f = FM::get(this, opcode); - uint32 m = field2mask[f]; - - // FPSCR[FX] is altered only if FM[0] = 1 - if ((f & 0x80) == 0) - m &= ~FPSCR_FX_field::mask(); - - // The mtfsf instruction cannot alter FPSCR[FEX] nor FPSCR[VX] explicitly - int exceptions = fsf & m; - exceptions &= ~(FPSCR_FEX_field::mask() | FPSCR_VX_field::mask()); - - // Move frB bits to FPSCR according to field mask - fpscr() = (fpscr() & ~m) | exceptions; - - // Update FPSCR exception bits (don't implicitly update FX) - record_fpscr(0); - - // Update native FP control word - if (m & FPSCR_RN_field::mask()) - fesetround(ppc_to_native_rounding_mode(FPSCR_RN_field::extract(fpscr()))); - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - increment_pc(4); -} - -template< class RB, class Rc > -void powerpc_cpu::execute_mtfsfi(uint32 opcode) -{ - const uint32 crfD = crfD_field::extract(opcode); - uint32 m = 0xf << (4 * (7 - crfD)); - - // FPSCR[FX] is altered only if crfD = 0 - if (crfD == 0) - m &= ~FPSCR_FX_field::mask(); - - // The mtfsfi instruction cannot alter FPSCR[FEX] nor FPSCR[VX] explicitly - int exceptions = RB::get(this, opcode) & m; - exceptions &= ~(FPSCR_FEX_field::mask() | FPSCR_VX_field::mask()); - - // Move immediate to FPSCR according to field crfD - fpscr() = (fpscr() & ~m) | exceptions; - - // Update native FP control word - if (m & FPSCR_RN_field::mask()) - fesetround(ppc_to_native_rounding_mode(FPSCR_RN_field::extract(fpscr()))); - - // Update FPSCR exception bits (don't implicitly update FX) - record_fpscr(0); - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - increment_pc(4); -} - -template< class RB, class Rc > -void powerpc_cpu::execute_mtfsb(uint32 opcode) -{ - const bool set_bit = RB::get(this, opcode); - - // The mtfsb0 and mtfsb1 instructions cannot alter FPSCR[FEX] nor FPSCR[VX] explicitly - uint32 m = 1 << (31 - crbD_field::extract(opcode)); - m &= ~(FPSCR_FEX_field::mask() | FPSCR_VX_field::mask()); - - // Bit crbD of the FPSCR is set or clear - fpscr() &= ~m; - - // Update FPSCR exception bits - record_fpscr(set_bit ? m : 0); - - // Update native FP control word if FPSCR[RN] changed - if (m & FPSCR_RN_field::mask()) - fesetround(ppc_to_native_rounding_mode(FPSCR_RN_field::extract(fpscr()))); - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - increment_pc(4); -} - -template< class Rc > -void powerpc_cpu::execute_mffs(uint32 opcode) -{ - // Move FPSCR to FPR(FRD) - operand_fp_dw_RD::set(this, opcode, fpscr()); - - // Set CR1 (FX, FEX, VX, VOX) if instruction has Rc set - if (Rc::test(opcode)) - record_cr1(); - - increment_pc(4); -} - -void powerpc_cpu::execute_mfmsr(uint32 opcode) -{ - operand_RD::set(this, opcode, 0xf072); - increment_pc(4); -} - -template< class SPR > -void powerpc_cpu::execute_mfspr(uint32 opcode) -{ - const uint32 spr = SPR::get(this, opcode); - uint32 d; - switch (spr) { - case powerpc_registers::SPR_XER: d = xer().get();break; - case powerpc_registers::SPR_LR: d = lr(); break; - case powerpc_registers::SPR_CTR: d = ctr(); break; - case powerpc_registers::SPR_VRSAVE: d = vrsave(); break; -#ifdef SHEEPSHAVER - case powerpc_registers::SPR_SDR1: d = 0xdead001f; break; - case powerpc_registers::SPR_PVR: { - extern uint32 PVR; - d = PVR; - break; - } - default: d = 0; -#else - default: execute_illegal(opcode); -#endif - } - operand_RD::set(this, opcode, d); - increment_pc(4); -} - -template< class SPR > -void powerpc_cpu::execute_mtspr(uint32 opcode) -{ - const uint32 spr = SPR::get(this, opcode); - const uint32 s = operand_RS::get(this, opcode); - - switch (spr) { - case powerpc_registers::SPR_XER: xer().set(s); break; - case powerpc_registers::SPR_LR: lr() = s; break; - case powerpc_registers::SPR_CTR: ctr() = s; break; - case powerpc_registers::SPR_VRSAVE: vrsave() = s; break; -#ifndef SHEEPSHAVER - default: execute_illegal(opcode); -#endif - } - - increment_pc(4); -} - -// Compute with 96 bit intermediate result: (a * b) / c -static uint64 muldiv64(uint64 a, uint32 b, uint32 c) -{ - union { - uint64 ll; - struct { -#ifdef WORDS_BIGENDIAN - uint32 high, low; -#else - uint32 low, high; -#endif - } l; - } u, res; - - u.ll = a; - uint64 rl = (uint64)u.l.low * (uint64)b; - uint64 rh = (uint64)u.l.high * (uint64)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} - -static inline uint64 get_tb_ticks(void) -{ - uint64 ticks; -#ifdef SHEEPSHAVER - const uint32 TBFreq = TimebaseSpeed; - ticks = muldiv64(GetTicks_usec(), TBFreq, 1000000); -#else - const uint32 TBFreq = 25 * 1000 * 1000; // 25 MHz - ticks = muldiv64((uint64)clock(), TBFreq, CLOCKS_PER_SEC); -#endif - return ticks; -} - -template< class TBR > -void powerpc_cpu::execute_mftbr(uint32 opcode) -{ - uint32 tbr = TBR::get(this, opcode); - uint32 d; - switch (tbr) { - case 268: d = (uint32)get_tb_ticks(); break; - case 269: d = (get_tb_ticks() >> 32); break; - default: execute_illegal(opcode); - } - operand_RD::set(this, opcode, d); - increment_pc(4); -} - -/** - * Instruction cache management - **/ - -void powerpc_cpu::execute_invalidate_cache_range() -{ - if (cache_range.start != cache_range.end) { - invalidate_cache_range(cache_range.start, cache_range.end); - cache_range.start = cache_range.end = 0; - } -} - -template< class RA, class RB > -void powerpc_cpu::execute_icbi(uint32 opcode) -{ - const uint32 ea = RA::get(this, opcode) + RB::get(this, opcode); - const uint32 block_start = ea - (ea % 32); - - if (block_start == cache_range.end) { - // Extend region to invalidate - cache_range.end += 32; - } - else { - // New region to invalidate - execute_invalidate_cache_range(); - cache_range.start = block_start; - cache_range.end = cache_range.start + 32; - } - - increment_pc(4); -} - -void powerpc_cpu::execute_isync(uint32 opcode) -{ - execute_invalidate_cache_range(); - increment_pc(4); -} - -/** - * (Fake) data cache management - **/ - -template< class RA, class RB > -void powerpc_cpu::execute_dcbz(uint32 opcode) -{ - uint32 ea = RA::get(this, opcode) + RB::get(this, opcode); - vm_memset(ea - (ea % 32), 0, 32); - increment_pc(4); -} - -/** - * Vector load/store instructions - **/ - -template< bool SL > -void powerpc_cpu::execute_vector_load_for_shift(uint32 opcode) -{ - const uint32 ra = operand_RA_or_0::get(this, opcode); - const uint32 rb = operand_RB::get(this, opcode); - const uint32 ea = ra + rb; - powerpc_vr & vD = vr(vD_field::extract(opcode)); - int j = SL ? (ea & 0xf) : (0x10 - (ea & 0xf)); - for (int i = 0; i < 16; i++) - vD.b[ev_mixed::byte_element(i)] = j++; - increment_pc(4); -} - -template< class VD, class RA, class RB > -void powerpc_cpu::execute_vector_load(uint32 opcode) -{ - uint32 ea = RA::get(this, opcode) + RB::get(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - switch (VD::element_size) { - case 1: - VD::set_element(vD, (ea & 0x0f), vm_read_memory_1(ea)); - break; - case 2: - VD::set_element(vD, ((ea >> 1) & 0x07), vm_read_memory_2(ea & ~1)); - break; - case 4: - VD::set_element(vD, ((ea >> 2) & 0x03), vm_read_memory_4(ea & ~3)); - break; - case 8: - ea &= ~15; - vD.w[0] = vm_read_memory_4(ea + 0); - vD.w[1] = vm_read_memory_4(ea + 4); - vD.w[2] = vm_read_memory_4(ea + 8); - vD.w[3] = vm_read_memory_4(ea + 12); - break; - } - increment_pc(4); -} - -template< class VS, class RA, class RB > -void powerpc_cpu::execute_vector_store(uint32 opcode) -{ - uint32 ea = RA::get(this, opcode) + RB::get(this, opcode); - typename VS::type & vS = VS::ref(this, opcode); - switch (VS::element_size) { - case 1: - vm_write_memory_1(ea, VS::get_element(vS, (ea & 0x0f))); - break; - case 2: - vm_write_memory_2(ea & ~1, VS::get_element(vS, ((ea >> 1) & 0x07))); - break; - case 4: - vm_write_memory_4(ea & ~3, VS::get_element(vS, ((ea >> 2) & 0x03))); - break; - case 8: - ea &= ~15; - vm_write_memory_4(ea + 0, vS.w[0]); - vm_write_memory_4(ea + 4, vS.w[1]); - vm_write_memory_4(ea + 8, vS.w[2]); - vm_write_memory_4(ea + 12, vS.w[3]); - break; - } - increment_pc(4); -} - -/** - * Vector arithmetic - * - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * VC Input operand vector (optional: operand_NONE) - * Rc Predicate to record CR6 - * C1 If recording CR6, do we check for '1' bits in vD? - **/ - -template< class OP, class VD, class VA, class VB, class VC, class Rc, int C1 > -void powerpc_cpu::execute_vector_arith(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VC::type const & vC = VC::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - - for (int i = 0; i < n_elements; i++) { - const typename VA::element_type a = VA::get_element(vA, i); - const typename VB::element_type b = VB::get_element(vB, i); - const typename VC::element_type c = VC::get_element(vC, i); - typename VD::element_type d = op_apply::apply(a, b, c); - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, i, d); - } - - // Propagate all conditions to CR6 - if (Rc::test(opcode)) - record_cr6(vD, C1); - - increment_pc(4); -} - -/** - * Vector mixed arithmetic - * - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * VC Input operand vector (optional: operand_NONE) - **/ - -template< class OP, class VD, class VA, class VB, class VC > -void powerpc_cpu::execute_vector_arith_mixed(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VC::type const & vC = VC::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - const int n_sub_elements = 4 / VA::element_size; - - for (int i = 0; i < n_elements; i++) { - const typename VC::element_type c = VC::get_element(vC, i); - typename VD::element_type d = c; - for (int j = 0; j < n_sub_elements; j++) { - const typename VA::element_type a = VA::get_element(vA, i * n_sub_elements + j); - const typename VB::element_type b = VB::get_element(vB, i * n_sub_elements + j); - d += op_apply::apply(a, b, c); - } - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, i, d); - } - - increment_pc(4); -} - -/** - * Vector odd/even arithmetic - * - * ODD Flag: are we computing every odd element? - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * VC Input operand vector (optional: operand_NONE) - **/ - -template< int ODD, class OP, class VD, class VA, class VB, class VC > -void powerpc_cpu::execute_vector_arith_odd(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VC::type const & vC = VC::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - - for (int i = 0; i < n_elements; i++) { - const typename VA::element_type a = VA::get_element(vA, (i * 2) + ODD); - const typename VB::element_type b = VB::get_element(vB, (i * 2) + ODD); - const typename VC::element_type c = VC::get_element(vC, (i * 2) + ODD); - typename VD::element_type d = op_apply::apply(a, b, c); - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, i, d); - } - - increment_pc(4); -} - -/** - * Vector merge instructions - * - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * VC Input operand vector (optional: operand_NONE) - * LO Flag: use lower part of element - **/ - -template< class VD, class VA, class VB, int LO > -void powerpc_cpu::execute_vector_merge(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - - for (int i = 0; i < n_elements; i += 2) { - VD::set_element(vD, i , VA::get_element(vA, (i / 2) + LO * (n_elements / 2))); - VD::set_element(vD, i + 1, VB::get_element(vB, (i / 2) + LO * (n_elements / 2))); - } - - increment_pc(4); -} - -/** - * Vector pack/unpack instructions - * - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * VC Input operand vector (optional: operand_NONE) - * LO Flag: use lower part of element - **/ - -template< class VD, class VA, class VB > -void powerpc_cpu::execute_vector_pack(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - const int n_pivot = n_elements / 2; - - for (int i = 0; i < n_elements; i++) { - typename VD::element_type d; - if (i < n_pivot) - d = VA::get_element(vA, i); - else - d = VB::get_element(vB, i - n_pivot); - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, i, d); - } - - increment_pc(4); -} - -template< int LO, class VD, class VA > -void powerpc_cpu::execute_vector_unpack(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - - for (int i = 0; i < n_elements; i++) - VD::set_element(vD, i, VA::get_element(vA, i + LO * n_elements)); - - increment_pc(4); -} - -void powerpc_cpu::execute_vector_pack_pixel(uint32 opcode) -{ - powerpc_vr const & vA = vr(vA_field::extract(opcode)); - powerpc_vr const & vB = vr(vB_field::extract(opcode)); - powerpc_vr & vD = vr(vD_field::extract(opcode)); - - for (int i = 0; i < 4; i++) { - const uint32 a = vA.w[i]; - vD.h[ev_mixed::half_element(i)] = ((a >> 9) & 0xfc00) | ((a >> 6) & 0x03e0) | ((a >> 3) & 0x001f); - const uint32 b = vB.w[i]; - vD.h[ev_mixed::half_element(i + 4)] = ((b >> 9) & 0xfc00) | ((b >> 6) & 0x03e0) | ((b >> 3) & 0x001f); - } - - increment_pc(4); -} - -template< int LO > -void powerpc_cpu::execute_vector_unpack_pixel(uint32 opcode) -{ - powerpc_vr const & vB = vr(vB_field::extract(opcode)); - powerpc_vr & vD = vr(vD_field::extract(opcode)); - - for (int i = 0; i < 4; i++) { - const uint32 h = vB.h[ev_mixed::half_element(i + LO * 4)]; - vD.w[i] = (((h & 0x8000) ? 0xff000000 : 0) | - ((h & 0x7c00) << 6) | - ((h & 0x03e0) << 3) | - (h & 0x001f)); - } - - increment_pc(4); -} - -/** - * Vector shift instructions - * - * SD Shift direction: left (-1), right (+1) - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * VC Input operand vector (optional: operand_NONE) - * SH Shift count operand - **/ - -template< int SD > -void powerpc_cpu::execute_vector_shift(uint32 opcode) -{ - powerpc_vr const & vA = vr(vA_field::extract(opcode)); - powerpc_vr const & vB = vr(vB_field::extract(opcode)); - powerpc_vr & vD = vr(vD_field::extract(opcode)); - - // The contents of the low-order three bits of all byte - // elements in vB must be identical to vB[125-127]; otherwise - // the value placed into vD is undefined. - const int sh = vB.b[ev_mixed::byte_element(15)] & 7; - if (sh == 0) { - for (int i = 0; i < 4; i++) - vD.w[i] = vA.w[i]; - } - else { - uint32 prev_bits = 0; - if (SD < 0) { - for (int i = 3; i >= 0; i--) { - uint32 next_bits = vA.w[i] >> (32 - sh); - vD.w[i] = ((vA.w[i] << sh) | prev_bits); - prev_bits = next_bits; - } - } - else if (SD > 0) { - for (int i = 0; i < 4; i++) { - uint32 next_bits = vA.w[i] << (32 - sh); - vD.w[i] = ((vA.w[i] >> sh) | prev_bits); - prev_bits = next_bits; - } - } - } - - increment_pc(4); -} - -template< int SD, class VD, class VA, class VB, class SH > -void powerpc_cpu::execute_vector_shift_octet(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - - const int sh = SH::get(this, opcode); - if (SD < 0) { - for (int i = 0; i < 16; i++) { - if (i + sh < 16) - VD::set_element(vD, i, VA::get_element(vA, i + sh)); - else - VD::set_element(vD, i, VB::get_element(vB, i - (16 - sh))); - } - } - else if (SD > 0) { - for (int i = 0; i < 16; i++) { - if (i < sh) - VD::set_element(vD, i, VB::get_element(vB, 16 - (i - sh))); - else - VD::set_element(vD, i, VA::get_element(vA, i - sh)); - } - } - - increment_pc(4); -} - -/** - * Vector splat instructions - * - * OP Operation to perform on element - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - * IM Immediate value to replicate - **/ - -template< class OP, class VD, class VB, bool IM > -void powerpc_cpu::execute_vector_splat(uint32 opcode) -{ - typename VD::type & vD = VD::ref(this, opcode); - const int n_elements = 16 / VD::element_size; - - uint32 value; - if (IM) - value = OP::apply(vUIMM_field::extract(opcode)); - else { - typename VB::type const & vB = VB::const_ref(this, opcode); - const int n = vUIMM_field::extract(opcode) & (n_elements - 1); - value = OP::apply(VB::get_element(vB, n)); - } - - for (int i = 0; i < n_elements; i++) - VD::set_element(vD, i, value); - - increment_pc(4); -} - -/** - * Vector sum instructions - * - * SZ Size of destination vector elements - * VD Output operand vector - * VA Input operand vector - * VB Input operand vector (optional: operand_NONE) - **/ - -template< int SZ, class VD, class VA, class VB > -void powerpc_cpu::execute_vector_sum(uint32 opcode) -{ - typename VA::type const & vA = VA::const_ref(this, opcode); - typename VB::type const & vB = VB::const_ref(this, opcode); - typename VD::type & vD = VD::ref(this, opcode); - typename VD::element_type d; - - switch (SZ) { - case 1: // vsum - d = VB::get_element(vB, 3); - for (int j = 0; j < 4; j++) - d += VA::get_element(vA, j); - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, 0, 0); - VD::set_element(vD, 1, 0); - VD::set_element(vD, 2, 0); - VD::set_element(vD, 3, d); - break; - - case 2: // vsum2 - for (int i = 0; i < 4; i += 2) { - d = VB::get_element(vB, i + 1); - for (int j = 0; j < 2; j++) - d += VA::get_element(vA, i + j); - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, i + 0, 0); - VD::set_element(vD, i + 1, d); - } - break; - - case 4: // vsum4 - for (int i = 0; i < 4; i += 1) { - d = VB::get_element(vB, i); - const int n_elements = 4 / VA::element_size; - for (int j = 0; j < n_elements; j++) - d += VA::get_element(vA, i * n_elements + j); - if (VD::saturate(d)) - vscr().set_sat(1); - VD::set_element(vD, i, d); - } - break; - } - - increment_pc(4); -} - -/** - * Misc vector instructions - **/ - -void powerpc_cpu::execute_vector_permute(uint32 opcode) -{ - powerpc_vr const & vA = vr(vA_field::extract(opcode)); - powerpc_vr const & vB = vr(vB_field::extract(opcode)); - powerpc_vr const & vC = vr(vC_field::extract(opcode)); - powerpc_vr & vD = vr(vD_field::extract(opcode)); - - for (int i = 0; i < 16; i++) { - const int ei = ev_mixed::byte_element(i); - const int n = vC.b[ei] & 0x1f; - const int en = ev_mixed::byte_element(n & 0xf); - vD.b[ei] = (n & 0x10) ? vB.b[en] : vA.b[en]; - } - - increment_pc(4); -} - -void powerpc_cpu::execute_mfvscr(uint32 opcode) -{ - const int vD = vD_field::extract(opcode); - vr(vD).w[0] = 0; - vr(vD).w[1] = 0; - vr(vD).w[2] = 0; - vr(vD).w[3] = vscr().get(); - increment_pc(4); -} - -void powerpc_cpu::execute_mtvscr(uint32 opcode) -{ - const int vB = vB_field::extract(opcode); - vscr().set(vr(vB).w[3]); - increment_pc(4); -} - -/** - * Explicit template instantiations - **/ - -#include "ppc-execute-impl.cpp" diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp deleted file mode 100644 index d3ce93f2..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-execute.hpp +++ /dev/null @@ -1,380 +0,0 @@ -/* - * ppc-execute.hpp - PowerPC semantic action templates - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_EXECUTE_H -#define PPC_EXECUTE_H - -// This file is designed to be included from implementation files only. -#ifdef DYNGEN_OPS -#define PPC_CPU powerpc_dyngen_helper -#define DEFINE_HELPER(NAME, ARGS) static inline uint32 NAME ARGS -#define RETURN(VAL) dyngen_barrier(); return (VAL) -#else -#define PPC_CPU powerpc_cpu -#define DEFINE_HELPER(NAME, ARGS) inline uint32 powerpc_cpu::NAME ARGS -#define RETURN(VAL) return (VAL) -#endif - - -template< bool SB > struct register_value { typedef uint32 type; }; -template< > struct register_value< true > { typedef int32 type; }; - -/** - * Helper class to apply an unary/binary/trinary operation - * - * OP Operation to perform - * RA Input operand register - * RB Input operand register or immediate (optional: operand_NONE) - * RC Input operand register or immediate (optional: operand_NONE) - **/ - -struct null_operand; -struct null_vector_operand; - -template< class RT, class OP, class RA, class RB, class RC > -struct op_apply { - template< class A, class B, class C > - static inline RT apply(A a, B b, C c) { - return OP::apply(a, b, c); - } -}; - -template< class RT, class OP, class RA, class RB > -struct op_apply { - template< class A, class B, class C > - static inline RT apply(A a, B b, C) { - return OP::apply(a, b); - } -}; - -template< class RT, class OP, class RA > -struct op_apply { - template< class A, class B, class C > - static inline RT apply(A a, B, C) { - return OP::apply(a); - } -}; - -template< class RT, class OP, class RA, class RB > -struct op_apply { - template< class A, class B, class C > - static inline RT apply(A a, B b, C) { - return (RT)OP::apply(a, b); - } -}; - -template< class RT, class OP, class RA > -struct op_apply { - template< class A, class B, class C > - static inline RT apply(A a, B, C) { - return (RT)OP::apply(a); - } -}; - -template< class RT, class OP, class RB > -struct op_apply { - template< class A, class B, class C > - static inline RT apply(A, B b, C) { - return (RT)OP::apply(b); - } -}; - -/** - * Add instruction templates - **/ - -template< bool EX, bool CA, bool OE > -DEFINE_HELPER(do_execute_addition, (uint32 RA, uint32 RB)) -{ - uint32 RD = RA + RB + (EX ? PPC_CPU::xer().get_ca() : 0); - - const bool _RA = ((int32)RA) < 0; - const bool _RB = ((int32)RB) < 0; - const bool _RD = ((int32)RD) < 0; - - if (EX) { - const bool ca = _RB ^ ((_RB ^ _RA) & (_RA ^ _RD)); - PPC_CPU::xer().set_ca(ca); - } - else if (CA) { - const bool ca = (uint32)RD < (uint32)RA; - PPC_CPU::xer().set_ca(ca); - } - - if (OE) - PPC_CPU::xer().set_ov((_RB ^ _RD) & (_RA ^ _RD)); - - RETURN(RD); -} - -/** - * Subtract instruction templates - **/ - -template< bool CA, bool OE > -DEFINE_HELPER(do_execute_subtract, (uint32 RA, uint32 RB)) -{ - uint32 RD = RB - RA; - - const bool _RA = ((int32)RA) < 0; - const bool _RB = ((int32)RB) < 0; - const bool _RD = ((int32)RD) < 0; - - if (CA) - PPC_CPU::xer().set_ca((uint32)RD <= (uint32)RB); - - if (OE) - PPC_CPU::xer().set_ov((_RA ^ _RB) & (_RD ^ _RB)); - - RETURN(RD); -} - -template< bool OE > -DEFINE_HELPER(do_execute_subtract_extended, (uint32 RA, uint32 RB)) -{ - const uint32 RD = ~RA + RB + PPC_CPU::xer().get_ca(); - - const bool _RA = ((int32)RA) < 0; - const bool _RB = ((int32)RB) < 0; - const bool _RD = ((int32)RD) < 0; - - const bool ca = !_RA ^ ((_RA ^ _RD) & (_RB ^ _RD)); - PPC_CPU::xer().set_ca(ca); - - if (OE) - PPC_CPU::xer().set_ov((_RA ^ _RB) & (_RD ^ _RB)); - - RETURN(RD); -} - -/** - * Divide instruction templates - **/ - -template< bool SB, bool OE > -DEFINE_HELPER(do_execute_divide, (uint32 RA, uint32 RB)) -{ - typename register_value::type a = RA; - typename register_value::type b = RB; - uint32 RD; - - if (b == 0 || (SB && a == 0x80000000 && b == -1)) { - // Reference manual says result is undefined but it gets all - // bits set to MSB on a real processor - RD = SB ? ((int32)RA >> 31) : 0; - if (OE) - PPC_CPU::xer().set_ov(1); - } - else { - RD = a / b; - if (OE) - PPC_CPU::xer().set_ov(0); - } - - RETURN(RD); -} - -/** - * FP load/store - **/ - -// C.6 Floating-Point Load Instructions -static inline uint64 fp_load_single_convert(uint32 v) -{ - // XXX we currently use the native floating-point capabilities - any_register x; - x.i = v; - x.d = (double)x.f; - return x.j; -} - -// C.7 Floating-Point Store Instructions -static inline uint32 fp_store_single_convert(uint64 v) -{ - int exp = (v >> 52) & 0x7ff; - if (exp < 874 || exp > 896) { - // No denormalization required (or "undefined" behaviour) - // WORD[0 - 1] = frS[0 - 1] - // WORD[2 - 31] = frS[5 - 34] - return (uint32)(((v >> 32) & 0xc0000000) | ((v >> 29) & 0x3fffffff)); - } - - // Handle denormalization (874 <= frS[1 - 11] <= 896 - // XXX we currently use the native floating-point capabilities - any_register x; - x.j = v; - x.f = (float)x.d; - return x.i; -} - -/** - * FP classification - **/ - -static inline bool is_NaN(double v) -{ - any_register x; x.d = v; - return (((x.j & UVAL64(0x7ff0000000000000)) == UVAL64(0x7ff0000000000000)) && - ((x.j & UVAL64(0x000fffffffffffff)) != 0)); -} - -static inline bool is_QNaN(double v) -{ - any_register x; x.d = v; - return is_NaN(v) && (x.j & UVAL64(0x0008000000000000)); -} - -static inline bool is_SNaN(double v) -{ - return is_NaN(v) && !is_QNaN(v); -} - -static inline bool is_NaN(float v) -{ - any_register x; x.f = v; - return (((x.i & 0x7f800000) == 0x7f800000) && - ((x.i & 0x007fffff) != 0)); -} - -static inline bool is_QNaN(float v) -{ - any_register x; x.f = v; - return is_NaN(v) && (x.i & 0x00400000); -} - -static inline bool is_SNaN(float v) -{ - return is_NaN(v) && !is_QNaN(v); -} - -/** - * Check for FP Exception Conditions - **/ - -template< class OP > -struct fp_exception_condition { - static inline uint32 apply(double) { - return 0; - } - static inline uint32 apply(double, double) { - return 0; - } - static inline uint32 apply(double, double, double) { - return 0; - } -}; - -template< class FP > -struct fp_invalid_operation_condition { - static inline uint32 apply(int flags) { - uint32 exceptions = 0; - if (FPSCR_VXSOFT_field::test(flags)) - exceptions |= FPSCR_VXSOFT_field::mask(); - return 0; - } - static inline uint32 apply(int flags, FP a) { - uint32 exceptions = 0; - if (FPSCR_VXSNAN_field::test(flags) && is_SNaN(a)) - exceptions |= FPSCR_VXSNAN_field::mask(); - if (FPSCR_VXVC_field::test(flags) && is_NaN(a)) - exceptions |= FPSCR_VXVC_field::mask(); - if (FPSCR_VXSQRT_field::test(flags) && signbit(a)) - exceptions |= FPSCR_VXSQRT_field::mask(); - return exceptions; - } - static inline uint32 apply(int flags, FP a, FP b, bool negate = false) { - uint32 exceptions = apply(flags) | apply(flags, a) | apply(flags, b); - if (FPSCR_VXISI_field::test(flags) && isinf(a) && isinf(b)) { - if (( negate && (signbit(a) == signbit(b))) || - (!negate && (signbit(a) != signbit(b)))) - exceptions |= FPSCR_VXISI_field::mask(); - } - if (FPSCR_VXIDI_field::test(flags) && isinf(a) && isinf(b)) - exceptions |= FPSCR_VXIDI_field::mask(); - if (FPSCR_VXZDZ_field::test(flags) && a == 0 && b == 0) - exceptions |= FPSCR_VXZDZ_field::mask(); - if (FPSCR_VXIMZ_field::test(flags) && ((a == 0 && isinf(b)) || (isinf(a) && b == 0))) - exceptions |= FPSCR_VXIMZ_field::mask(); - return exceptions; - } -}; - -#define DEFINE_FP_INVALID_OPERATION(OP, TYPE, EXCP, NEGATE) \ -template<> \ -struct fp_exception_condition { \ - static inline uint32 apply(TYPE a, TYPE b) { \ - return fp_invalid_operation_condition::apply(EXCP, a, b, NEGATE); \ - } \ -}; - -DEFINE_FP_INVALID_OPERATION(op_fadd, double, FPSCR_VXSNAN_field::mask() | FPSCR_VXISI_field::mask(), 0); -DEFINE_FP_INVALID_OPERATION(op_fsub, double, FPSCR_VXSNAN_field::mask() | FPSCR_VXISI_field::mask(), 1); -DEFINE_FP_INVALID_OPERATION(op_fmul, double, FPSCR_VXSNAN_field::mask() | FPSCR_VXIMZ_field::mask(), 0); - -template< class FP > -struct fp_divide_exception_condition { - static inline uint32 apply(FP a, FP b) { - int exceptions = - fp_invalid_operation_condition:: - apply(FPSCR_VXSNAN_field::mask() | FPSCR_VXIDI_field::mask() | FPSCR_VXZDZ_field::mask(), - a, b); - if (isfinite(a) && a != 0 && b == 0) - exceptions = FPSCR_ZX_field::mask(); - return exceptions; - } -}; - -template<> struct fp_exception_condition : fp_divide_exception_condition { }; - -template< class FP, bool negate > -struct fp_fma_exception_condition { - static inline uint32 apply(FP a, FP b, FP c) { - int exceptions = - fp_invalid_operation_condition:: - apply(FPSCR_VXSNAN_field::mask(), a) | - fp_invalid_operation_condition:: - apply(FPSCR_VXSNAN_field::mask(), b) | - fp_invalid_operation_condition:: - apply(FPSCR_VXSNAN_field::mask(), c) | - fp_invalid_operation_condition:: - apply(FPSCR_VXIMZ_field::mask(), a, b); - // 2.1.5 -- The XER bit definitions are based on the - // operation of an instruction considered as a whole, - // not on intermediate results - if ((isinf(a) || isinf(b)) && isinf(c)) { - FP m = a * b; - if (isinf(m)) { - // make sure the intermediate result is an infinity and not a NaN - // FIXME: it could be faster to use (exceptions & IMZ) == 0 instead of isinf() - if (( negate && (signbit(m) == signbit(c))) || - (!negate && (signbit(m) != signbit(c)))) - exceptions |= FPSCR_VXISI_field::mask(); - } - } - return exceptions; - } -}; - -template<> struct fp_exception_condition : fp_fma_exception_condition { }; -template<> struct fp_exception_condition : fp_fma_exception_condition { }; -template<> struct fp_exception_condition : fp_fma_exception_condition { }; -template<> struct fp_exception_condition : fp_fma_exception_condition { }; - -#endif /* PPC_EXECUTE_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-instructions.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-instructions.hpp deleted file mode 100644 index c42b61d1..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-instructions.hpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * ppc-instructions.hpp - PowerPC instructions IDs - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_INSTRUCTIONS_H -#define PPC_INSTRUCTIONS_H - -/** - * Define PowerPC instruction types - **/ - -#define PPC_I(X) powerpc_instruction_##X - -enum powerpc_instruction { - PPC_I(INVALID), - PPC_I(ADD), - PPC_I(ADDC), - PPC_I(ADDE), - PPC_I(ADDI), - PPC_I(ADDIC), - PPC_I(ADDIC_), - PPC_I(ADDIS), - PPC_I(ADDME), - PPC_I(ADDZE), - PPC_I(AND), - PPC_I(ANDC), - PPC_I(ANDI), - PPC_I(ANDIS), - PPC_I(B), - PPC_I(BC), - PPC_I(BCCTR), - PPC_I(BCLR), - PPC_I(CMP), - PPC_I(CMPI), - PPC_I(CMPL), - PPC_I(CMPLI), - PPC_I(CNTLZW), - PPC_I(CRAND), - PPC_I(CRANDC), - PPC_I(CREQV), - PPC_I(CRNAND), - PPC_I(CRNOR), - PPC_I(CROR), - PPC_I(CRORC), - PPC_I(CRXOR), - PPC_I(DCBA), - PPC_I(DCBF), - PPC_I(DCBI), - PPC_I(DCBST), - PPC_I(DCBT), - PPC_I(DCBTST), - PPC_I(DCBZ), - PPC_I(DIVW), - PPC_I(DIVWU), - PPC_I(DSS), - PPC_I(DST), - PPC_I(DSTST), - PPC_I(ECIWX), - PPC_I(ECOWX), - PPC_I(EIEIO), - PPC_I(EQV), - PPC_I(EXTSB), - PPC_I(EXTSH), - PPC_I(FABS), - PPC_I(FADD), - PPC_I(FADDS), - PPC_I(FCMPO), - PPC_I(FCMPU), - PPC_I(FCTIW), - PPC_I(FCTIWZ), - PPC_I(FDIV), - PPC_I(FDIVS), - PPC_I(FMADD), - PPC_I(FMADDS), - PPC_I(FMR), - PPC_I(FMSUB), - PPC_I(FMSUBS), - PPC_I(FMUL), - PPC_I(FMULS), - PPC_I(FNABS), - PPC_I(FNEG), - PPC_I(FNMADD), - PPC_I(FNMADDS), - PPC_I(FNMSUB), - PPC_I(FNMSUBS), - PPC_I(FRSP), - PPC_I(FSEL), - PPC_I(FSUB), - PPC_I(FSUBS), - PPC_I(ICBI), - PPC_I(ISYNC), - PPC_I(LBZ), - PPC_I(LBZU), - PPC_I(LBZUX), - PPC_I(LBZX), - PPC_I(LFD), - PPC_I(LFDU), - PPC_I(LFDUX), - PPC_I(LFDX), - PPC_I(LFS), - PPC_I(LFSU), - PPC_I(LFSUX), - PPC_I(LFSX), - PPC_I(LHA), - PPC_I(LHAU), - PPC_I(LHAUX), - PPC_I(LHAX), - PPC_I(LHBRX), - PPC_I(LHZ), - PPC_I(LHZU), - PPC_I(LHZUX), - PPC_I(LHZX), - PPC_I(LMW), - PPC_I(LSWI), - PPC_I(LSWX), - PPC_I(LVEBX), - PPC_I(LVEHX), - PPC_I(LVEWX), - PPC_I(LVSL), - PPC_I(LVSR), - PPC_I(LVX), - PPC_I(LVXL), - PPC_I(LWARX), - PPC_I(LWBRX), - PPC_I(LWZ), - PPC_I(LWZU), - PPC_I(LWZUX), - PPC_I(LWZX), - PPC_I(MCRF), - PPC_I(MCRFS), - PPC_I(MCRXR), - PPC_I(MFCR), - PPC_I(MFFS), - PPC_I(MFMSR), - PPC_I(MFSPR), - PPC_I(MFTB), - PPC_I(MFVSCR), - PPC_I(MTCRF), - PPC_I(MTFSB0), - PPC_I(MTFSB1), - PPC_I(MTFSF), - PPC_I(MTFSFI), - PPC_I(MTSPR), - PPC_I(MTVSCR), - PPC_I(MULHW), - PPC_I(MULHWU), - PPC_I(MULLI), - PPC_I(MULLW), - PPC_I(NAND), - PPC_I(NEG), - PPC_I(NOR), - PPC_I(OR), - PPC_I(ORC), - PPC_I(ORI), - PPC_I(ORIS), - PPC_I(RLWIMI), - PPC_I(RLWINM), - PPC_I(RLWNM), - PPC_I(SC), - PPC_I(SLW), - PPC_I(SRAW), - PPC_I(SRAWI), - PPC_I(SRW), - PPC_I(STB), - PPC_I(STBU), - PPC_I(STBUX), - PPC_I(STBX), - PPC_I(STFD), - PPC_I(STFDU), - PPC_I(STFDUX), - PPC_I(STFDX), - PPC_I(STFS), - PPC_I(STFSU), - PPC_I(STFSUX), - PPC_I(STFSX), - PPC_I(STH), - PPC_I(STHBRX), - PPC_I(STHU), - PPC_I(STHUX), - PPC_I(STHX), - PPC_I(STMW), - PPC_I(STSWI), - PPC_I(STSWX), - PPC_I(STVEBX), - PPC_I(STVEHX), - PPC_I(STVEWX), - PPC_I(STVX), - PPC_I(STVXL), - PPC_I(STW), - PPC_I(STWBRX), - PPC_I(STWCX), - PPC_I(STWU), - PPC_I(STWUX), - PPC_I(STWX), - PPC_I(SUBF), - PPC_I(SUBFC), - PPC_I(SUBFE), - PPC_I(SUBFIC), - PPC_I(SUBFME), - PPC_I(SUBFZE), - PPC_I(SYNC), - PPC_I(XOR), - PPC_I(XORI), - PPC_I(XORIS), - PPC_I(VADDCUW), - PPC_I(VADDFP), - PPC_I(VADDSBS), - PPC_I(VADDSHS), - PPC_I(VADDSWS), - PPC_I(VADDUBM), - PPC_I(VADDUBS), - PPC_I(VADDUHM), - PPC_I(VADDUHS), - PPC_I(VADDUWM), - PPC_I(VADDUWS), - PPC_I(VAND), - PPC_I(VANDC), - PPC_I(VAVGSB), - PPC_I(VAVGSH), - PPC_I(VAVGSW), - PPC_I(VAVGUB), - PPC_I(VAVGUH), - PPC_I(VAVGUW), - PPC_I(VCFSX), - PPC_I(VCFUX), - PPC_I(VCMPBFP), - PPC_I(VCMPEQFP), - PPC_I(VCMPEQUB), - PPC_I(VCMPEQUH), - PPC_I(VCMPEQUW), - PPC_I(VCMPGEFP), - PPC_I(VCMPGTFP), - PPC_I(VCMPGTSB), - PPC_I(VCMPGTSH), - PPC_I(VCMPGTSW), - PPC_I(VCMPGTUB), - PPC_I(VCMPGTUH), - PPC_I(VCMPGTUW), - PPC_I(VCTSXS), - PPC_I(VCTUXS), - PPC_I(VEXPTEFP), - PPC_I(VLOGEFP), - PPC_I(VMADDFP), - PPC_I(VMAXFP), - PPC_I(VMAXSB), - PPC_I(VMAXSH), - PPC_I(VMAXSW), - PPC_I(VMAXUB), - PPC_I(VMAXUH), - PPC_I(VMAXUW), - PPC_I(VMHADDSHS), - PPC_I(VMHRADDSHS), - PPC_I(VMINFP), - PPC_I(VMINSB), - PPC_I(VMINSH), - PPC_I(VMINSW), - PPC_I(VMINUB), - PPC_I(VMINUH), - PPC_I(VMINUW), - PPC_I(VMLADDUHM), - PPC_I(VMRGHB), - PPC_I(VMRGHH), - PPC_I(VMRGHW), - PPC_I(VMRGLB), - PPC_I(VMRGLH), - PPC_I(VMRGLW), - PPC_I(VMSUMMBM), - PPC_I(VMSUMSHM), - PPC_I(VMSUMSHS), - PPC_I(VMSUMUBM), - PPC_I(VMSUMUHM), - PPC_I(VMSUMUHS), - PPC_I(VMULESB), - PPC_I(VMULESH), - PPC_I(VMULEUB), - PPC_I(VMULEUH), - PPC_I(VMULOSB), - PPC_I(VMULOSH), - PPC_I(VMULOUB), - PPC_I(VMULOUH), - PPC_I(VNMSUBFP), - PPC_I(VNOR), - PPC_I(VOR), - PPC_I(VPERM), - PPC_I(VPKPX), - PPC_I(VPKSHSS), - PPC_I(VPKSHUS), - PPC_I(VPKSWSS), - PPC_I(VPKSWUS), - PPC_I(VPKUHUM), - PPC_I(VPKUHUS), - PPC_I(VPKUWUM), - PPC_I(VPKUWUS), - PPC_I(VREFP), - PPC_I(VRFIM), - PPC_I(VRFIN), - PPC_I(VRFIP), - PPC_I(VRFIZ), - PPC_I(VRLB), - PPC_I(VRLH), - PPC_I(VRLW), - PPC_I(VRSQRTEFP), - PPC_I(VSEL), - PPC_I(VSL), - PPC_I(VSLB), - PPC_I(VSLDOI), - PPC_I(VSLH), - PPC_I(VSLO), - PPC_I(VSLW), - PPC_I(VSPLTB), - PPC_I(VSPLTH), - PPC_I(VSPLTISB), - PPC_I(VSPLTISH), - PPC_I(VSPLTISW), - PPC_I(VSPLTW), - PPC_I(VSR), - PPC_I(VSRAB), - PPC_I(VSRAH), - PPC_I(VSRAW), - PPC_I(VSRB), - PPC_I(VSRH), - PPC_I(VSRO), - PPC_I(VSRW), - PPC_I(VSUBCUW), - PPC_I(VSUBFP), - PPC_I(VSUBSBS), - PPC_I(VSUBSHS), - PPC_I(VSUBSWS), - PPC_I(VSUBUBM), - PPC_I(VSUBUBS), - PPC_I(VSUBUHM), - PPC_I(VSUBUHS), - PPC_I(VSUBUWM), - PPC_I(VSUBUWS), - PPC_I(VSUMSWS), - PPC_I(VSUM2SWS), - PPC_I(VSUM4SBS), - PPC_I(VSUM4SHS), - PPC_I(VSUM4UBS), - PPC_I(VUPKHPX), - PPC_I(VUPKHSB), - PPC_I(VUPKHSH), - PPC_I(VUPKLPX), - PPC_I(VUPKLSB), - PPC_I(VUPKLSH), - PPC_I(VXOR), - PPC_I(MAX) // Total number of instruction types -}; - -#endif /* PPC_INSTRUCTIONS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.cpp deleted file mode 100644 index 4b294401..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.cpp +++ /dev/null @@ -1,942 +0,0 @@ -/* - * ppc-jit.cpp - PowerPC dynamic translation (mid-level) - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "cpu/jit/dyngen-exec.h" -#include "cpu/ppc/ppc-jit.hpp" -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-instructions.hpp" -#include "cpu/ppc/ppc-operands.hpp" -#include "utils/utils-cpuinfo.hpp" -#include "utils/utils-sentinel.hpp" - -// Mid-level code generator info -const powerpc_jit::jit_info_t *powerpc_jit::jit_info[PPC_I(MAX)]; - -// PowerPC JIT initializer -powerpc_jit::powerpc_jit(dyngen_cpu_base cpu) - : powerpc_dyngen(cpu) -{ -} - -bool powerpc_jit::initialize(void) -{ - if (!powerpc_dyngen::initialize()) - return false; - - static bool once = true; - - if (once) { - once = false; - - // default to no handler - static const jit_info_t jit_not_available = { - -1, - (gen_handler_t)&powerpc_jit::gen_not_available, - }; - for (int i = 0; i < PPC_I(MAX); i++) - jit_info[i] = &jit_not_available; - - // generic altivec handlers - static const jit_info_t gen_vector[] = { -#define DEFINE_OP(MNEMO, GEN_OP, DYNGEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_vector_generic_##GEN_OP, &powerpc_dyngen::gen_op_##DYNGEN_OP } - DEFINE_OP(VADDFP, 2, vaddfp_VD_V0_V1), - DEFINE_OP(VSUBFP, 2, vsubfp_VD_V0_V1), - DEFINE_OP(VMADDFP, 3, vmaddfp_VD_V0_V1_V2), - DEFINE_OP(VNMSUBFP, 3, vnmsubfp_VD_V0_V1_V2), - DEFINE_OP(VAND, 2, vand_VD_V0_V1), - DEFINE_OP(VANDC, 2, vandc_VD_V0_V1), - DEFINE_OP(VNOR, 2, vnor_VD_V0_V1), - DEFINE_OP(VOR, 2, vor_VD_V0_V1), - DEFINE_OP(VXOR, 2, vxor_VD_V0_V1), - DEFINE_OP(MFVSCR, 1, mfvscr_VD), - DEFINE_OP(MTVSCR, 1, mtvscr_V0), -#undef DEFINE_OP -#define DEFINE_OP(MNEMO, GEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_vector_generic_##GEN_OP, } - DEFINE_OP(LVX, load), - DEFINE_OP(LVXL, load), - DEFINE_OP(LVEWX, load_word), - DEFINE_OP(STVX, store), - DEFINE_OP(STVXL, store), - DEFINE_OP(STVEWX, store_word), -#undef DEFINE_OP - }; - for (int i = 0; i < sizeof(gen_vector) / sizeof(gen_vector[0]); i++) - jit_info[gen_vector[i].mnemo] = &gen_vector[i]; - -#if defined(__i386__) || defined(__x86_64__) - // x86 optimized handlers - static const jit_info_t x86_vector[] = { -#define DEFINE_OP(MNEMO, GEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_x86_##GEN_OP, } - DEFINE_OP(MTVSCR, mtvscr), - DEFINE_OP(MFVSCR, mfvscr), - DEFINE_OP(LVX, lvx), - DEFINE_OP(LVXL, lvx), - DEFINE_OP(STVX, stvx), - DEFINE_OP(STVXL, stvx) -#undef DEFINE_OP - }; - for (int i = 0; i < sizeof(x86_vector) / sizeof(x86_vector[0]); i++) - jit_info[x86_vector[i].mnemo] = &x86_vector[i]; - - // MMX optimized handlers - static const jit_info_t mmx_vector[] = { -#define DEFINE_OP(MNEMO, GEN_OP, DYNGEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_mmx_arith_##GEN_OP, &powerpc_dyngen::gen_op_mmx_##DYNGEN_OP } - DEFINE_OP(VADDUBM, 2, vaddubm), - DEFINE_OP(VADDUHM, 2, vadduhm), - DEFINE_OP(VADDUWM, 2, vadduwm), - DEFINE_OP(VAND, 2, vand), - DEFINE_OP(VANDC, 2, vandc), - DEFINE_OP(VCMPEQUB, c, vcmpequb), - DEFINE_OP(VCMPEQUH, c, vcmpequh), - DEFINE_OP(VCMPEQUW, c, vcmpequw), - DEFINE_OP(VCMPGTSB, c, vcmpgtsb), - DEFINE_OP(VCMPGTSH, c, vcmpgtsh), - DEFINE_OP(VCMPGTSW, c, vcmpgtsw), - DEFINE_OP(VOR, 2, vor), - DEFINE_OP(VSUBUBM, 2, vsububm), - DEFINE_OP(VSUBUHM, 2, vsubuhm), - DEFINE_OP(VSUBUWM, 2, vsubuwm), - DEFINE_OP(VXOR, 2, vxor) -#undef DEFINE_OP - }; - if (cpuinfo_check_mmx()) { - for (int i = 0; i < sizeof(mmx_vector) / sizeof(mmx_vector[0]); i++) - jit_info[mmx_vector[i].mnemo] = &mmx_vector[i]; - } - - // SSE optimized handlers - static const jit_info_t sse_vector[] = { - // new MMX instructions brought into SSE capable CPUs -#define DEFINE_OP(MNEMO, GEN_OP, DYNGEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_mmx_arith_##GEN_OP, &powerpc_dyngen::gen_op_mmx_##DYNGEN_OP } - DEFINE_OP(VMAXSH, 2, vmaxsh), - DEFINE_OP(VMAXUB, 2, vmaxub), - DEFINE_OP(VMINSH, 2, vminsh), - DEFINE_OP(VMINUB, 2, vminub), -#undef DEFINE_OP - // full SSE instructions -#define DEFINE_OP(MNEMO, GEN_OP, TYPE_OP, SSE_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_sse_arith_##GEN_OP, (X86_INSN_SSE_##TYPE_OP << 8) | X86_SSE_##SSE_OP } - DEFINE_OP(VADDFP, 2, PS,ADD), - DEFINE_OP(VAND, 2, PS,AND), - DEFINE_OP(VANDC, s, PS,ANDN), - DEFINE_OP(VMAXFP, 2, PS,MAX), - DEFINE_OP(VMINFP, 2, PS,MIN), - DEFINE_OP(VOR, 2, PS,OR), - DEFINE_OP(VSUBFP, 2, PS,SUB), - DEFINE_OP(VXOR, 2, PS,XOR), - DEFINE_OP(VMINUB, 2, PI,PMINUB), - DEFINE_OP(VMAXUB, 2, PI,PMAXUB), - DEFINE_OP(VMINSH, 2, PI,PMINSW), - DEFINE_OP(VMAXSH, 2, PI,PMAXSW), - DEFINE_OP(VAVGUB, 2, PI,PAVGB), - DEFINE_OP(VAVGUH, 2, PI,PAVGW), -#undef DEFINE_OP -#define DEFINE_OP(MNEMO, COND) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_sse_arith_c, X86_SSE_CC_##COND } - DEFINE_OP(VCMPEQFP, EQ), - DEFINE_OP(VCMPGEFP, GE), - DEFINE_OP(VCMPGTFP, GT), -#undef DEFINE_OP -#define DEFINE_OP(MNEMO, GEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_sse_##GEN_OP } - DEFINE_OP(VSEL, vsel), - DEFINE_OP(VMADDFP, vmaddfp), - DEFINE_OP(VNMSUBFP, vnmsubfp) -#undef DEFINE_OP - }; - - if (cpuinfo_check_sse()) { - for (int i = 0; i < sizeof(sse_vector) / sizeof(sse_vector[0]); i++) - jit_info[sse_vector[i].mnemo] = &sse_vector[i]; - } - - // SSE2 optimized handlers - static const jit_info_t sse2_vector[] = { -#define DEFINE_OP(MNEMO, GEN_OP, TYPE_OP, SSE_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_sse2_arith_##GEN_OP, (X86_INSN_SSE_##TYPE_OP << 8) | X86_SSE_##SSE_OP } - DEFINE_OP(VADDUBM, 2, PI,PADDB), - DEFINE_OP(VADDUHM, 2, PI,PADDW), - DEFINE_OP(VADDUWM, 2, PI,PADDD), - DEFINE_OP(VSUBUBM, 2, PI,PSUBB), - DEFINE_OP(VSUBUHM, 2, PI,PSUBW), - DEFINE_OP(VSUBUWM, 2, PI,PSUBD), - DEFINE_OP(VAND, 2, PI,PAND), - DEFINE_OP(VANDC, s, PI,PANDN), - DEFINE_OP(VOR, 2, PI,POR), - DEFINE_OP(VXOR, 2, PI,PXOR), - DEFINE_OP(VCMPEQUB, c, PI,PCMPEQB), - DEFINE_OP(VCMPEQUH, c, PI,PCMPEQW), - DEFINE_OP(VCMPEQUW, c, PI,PCMPEQD), - DEFINE_OP(VCMPGTSB, c, PI,PCMPGTB), - DEFINE_OP(VCMPGTSH, c, PI,PCMPGTW), - DEFINE_OP(VCMPGTSW, c, PI,PCMPGTD), - DEFINE_OP(VREFP, 2, PS,RCP), - DEFINE_OP(VRSQRTEFP,2, PS,RSQRT), -#undef DEFINE_OP -#define DEFINE_OP(MNEMO, GEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_sse2_##GEN_OP, } - DEFINE_OP(VSEL, vsel), - DEFINE_OP(VSLDOI, vsldoi), - DEFINE_OP(VSPLTB, vspltb), - DEFINE_OP(VSPLTH, vsplth), - DEFINE_OP(VSPLTW, vspltw), - DEFINE_OP(VSPLTISB, vspltisb), - DEFINE_OP(VSPLTISH, vspltish), - DEFINE_OP(VSPLTISW, vspltisw) -#undef DEFINE_OP - }; - - if (cpuinfo_check_sse2()) { - for (int i = 0; i < sizeof(sse2_vector) / sizeof(sse2_vector[0]); i++) - jit_info[sse2_vector[i].mnemo] = &sse2_vector[i]; - } - - // SSSE3 optimized handlers - static const jit_info_t ssse3_vector[] = { -#define DEFINE_OP(MNEMO, GEN_OP) \ - { PPC_I(MNEMO), (gen_handler_t)&powerpc_jit::gen_ssse3_##GEN_OP, } - DEFINE_OP(LVX, lvx), - DEFINE_OP(LVXL, lvx), - DEFINE_OP(STVX, stvx), - DEFINE_OP(STVXL, stvx), - DEFINE_OP(VPERM, vperm) -#undef DEFINE_OP - }; - - if (cpuinfo_check_ssse3()) { - for (int i = 0; i < sizeof(ssse3_vector) / sizeof(ssse3_vector[0]); i++) - jit_info[ssse3_vector[i].mnemo] = &ssse3_vector[i]; - } -#endif - } - - return true; -} - -// Dispatch mid-level code generators -bool powerpc_jit::gen_vector_1(int mnemo, int vD) -{ - return (this->*((bool (powerpc_jit::*)(int, int))jit_info[mnemo]->handler))(mnemo, vD); -} - -bool powerpc_jit::gen_vector_2(int mnemo, int vD, int vA, int vB) -{ - return (this->*((bool (powerpc_jit::*)(int, int, int, int))jit_info[mnemo]->handler))(mnemo, vD, vA, vB); -} - -bool powerpc_jit::gen_vector_3(int mnemo, int vD, int vA, int vB, int vC) -{ - return (this->*((bool (powerpc_jit::*)(int, int, int, int, int))jit_info[mnemo]->handler))(mnemo, vD, vA, vB, vC); -} - -bool powerpc_jit::gen_vector_compare(int mnemo, int vD, int vA, int vB, bool Rc) -{ - return (this->*((bool (powerpc_jit::*)(int, int, int, int, bool))jit_info[mnemo]->handler))(mnemo, vD, vA, vB, Rc); -} - - -bool powerpc_jit::gen_not_available(int mnemo) -{ - return false; -} - -bool powerpc_jit::gen_vector_generic_1(int mnemo, int vD) -{ - gen_load_ad_VD_VR(vD); - (this->*(jit_info[mnemo]->o.dyngen_handler))(); - return true; -} - -bool powerpc_jit::gen_vector_generic_2(int mnemo, int vD, int vA, int vB) -{ - gen_load_ad_VD_VR(vD); - gen_load_ad_V0_VR(vA); - gen_load_ad_V1_VR(vB); - (this->*(jit_info[mnemo]->o.dyngen_handler))(); - return true; -} - -bool powerpc_jit::gen_vector_generic_3(int mnemo, int vD, int vA, int vB, int vC) -{ - gen_load_ad_VD_VR(vD); - gen_load_ad_V0_VR(vA); - gen_load_ad_V1_VR(vB); - gen_load_ad_V2_VR(vC); - (this->*(jit_info[mnemo]->o.dyngen_handler))(); - return true; -} - -bool powerpc_jit::gen_vector_generic_c(int mnemo, int vD, int vA, int vB, bool Rc) -{ - gen_vector_generic_2(mnemo, vD, vA, vB); - if (Rc) - gen_record_cr6_VD(); - return true; -} - -bool powerpc_jit::gen_vector_generic_load(int mnemo, int vD, int rA, int rB) -{ - // NOTE: T0/VD are clobbered in the following instructions! - gen_load_T0_GPR(rB); - if (rA != 0) { - gen_load_T1_GPR(rA); - gen_add_32_T0_T1(); - } - gen_load_vect_VD_T0(vD); - return true; -} - -bool powerpc_jit::gen_vector_generic_store(int mnemo, int vS, int rA, int rB) -{ - // NOTE: T0/VS are clobbered in the following instructions! - gen_load_T0_GPR(rB); - if (rA != 0) { - gen_load_T1_GPR(rA); - gen_add_32_T0_T1(); - } - gen_store_vect_VS_T0(vS); - return true; -} - -bool powerpc_jit::gen_vector_generic_load_word(int mnemo, int vD, int rA, int rB) -{ - // NOTE: T0/VD are clobbered in the following instructions! - gen_load_T0_GPR(rB); - if (rA != 0) { - gen_load_T1_GPR(rA); - gen_add_32_T0_T1(); - } - gen_load_word_VD_T0(vD); - return true; -} - -bool powerpc_jit::gen_vector_generic_store_word(int mnemo, int vS, int rA, int rB) -{ - // NOTE: T0/VS are clobbered in the following instructions! - gen_load_T0_GPR(rB); - if (rA != 0) { - gen_load_T1_GPR(rA); - gen_add_32_T0_T1(); - } - gen_store_word_VS_T0(vS); - return true; -} - -#if PPC_PROFILE_REGS_USE -// XXX update reginfo[] counts for xPPC_GPR() accesses -static uint8 dummy_ppc_context[sizeof(powerpc_cpu)]; -#define xPPC_CONTEXT ((powerpc_cpu *)dummy_ppc_context) -#else -#define xPPC_CONTEXT ((powerpc_cpu *)0) -#endif -#define xPPC_FIELD(M) (((uintptr)&xPPC_CONTEXT->M) - (uintptr)xPPC_CONTEXT) -#define xPPC_GPR(N) xPPC_FIELD(gpr(N)) -#define xPPC_VR(N) xPPC_FIELD(vr(N)) -#define xPPC_CR xPPC_FIELD(cr()) -#define xPPC_VSCR xPPC_FIELD(vscr()) - -#if defined(__i386__) || defined(__x86_64__) -/* - * X86 optimizations - */ - -// mtvscr -bool powerpc_jit::gen_x86_mtvscr(int mnemo, int vD) -{ - gen_mov_32(x86_memory_operand(xPPC_VR(vD) + 3*4, REG_CPU_ID), REG_T0_ID); - gen_mov_32(REG_T0_ID, x86_memory_operand(xPPC_VSCR, REG_CPU_ID)); - return true; -} - -// mfvscr -bool powerpc_jit::gen_x86_mfvscr(int mnemo, int vB) -{ - gen_xor_32(REG_T0_ID, REG_T0_ID); - gen_mov_32(x86_memory_operand(xPPC_VSCR, REG_CPU_ID), REG_T1_ID); -#if SIZEOF_VOID_P == 8 - gen_mov_64(REG_T0_ID, x86_memory_operand(xPPC_VR(vB) + 0*4, REG_CPU_ID)); -#else - gen_mov_32(REG_T0_ID, x86_memory_operand(xPPC_VR(vB) + 0*4, REG_CPU_ID)); - gen_mov_32(REG_T0_ID, x86_memory_operand(xPPC_VR(vB) + 1*4, REG_CPU_ID)); -#endif - gen_mov_32(REG_T0_ID, x86_memory_operand(xPPC_VR(vB) + 2*4, REG_CPU_ID)); - gen_mov_32(REG_T1_ID, x86_memory_operand(xPPC_VR(vB) + 3*4, REG_CPU_ID)); - return true; -} - -// lvx, lvxl -bool powerpc_jit::gen_x86_lvx(int mnemo, int vD, int rA, int rB) -{ - gen_mov_32(x86_memory_operand(xPPC_GPR(rB), REG_CPU_ID), REG_T0_ID); - if (rA != 0) - gen_add_32(x86_memory_operand(xPPC_GPR(rA), REG_CPU_ID), REG_T0_ID); - gen_and_32(x86_immediate_operand(-16), REG_T0_ID); -#if SIZEOF_VOID_P == 8 - gen_mov_64(x86_memory_operand(0, REG_T0_ID), REG_T1_ID); - gen_mov_64(x86_memory_operand(8, REG_T0_ID), REG_T2_ID); - gen_bswap_64(REG_T1_ID); - gen_bswap_64(REG_T2_ID); - gen_rol_64(x86_immediate_operand(32), REG_T1_ID); - gen_rol_64(x86_immediate_operand(32), REG_T2_ID); - gen_mov_64(REG_T1_ID, x86_memory_operand(xPPC_VR(vD) + 0, REG_CPU_ID)); - gen_mov_64(REG_T2_ID, x86_memory_operand(xPPC_VR(vD) + 8, REG_CPU_ID)); -#else - gen_mov_32(x86_memory_operand(0*4, REG_T0_ID), REG_T1_ID); - gen_mov_32(x86_memory_operand(1*4, REG_T0_ID), REG_T2_ID); - gen_bswap_32(REG_T1_ID); - gen_bswap_32(REG_T2_ID); - gen_mov_32(REG_T1_ID, x86_memory_operand(xPPC_VR(vD) + 0*4, REG_CPU_ID)); - gen_mov_32(REG_T2_ID, x86_memory_operand(xPPC_VR(vD) + 1*4, REG_CPU_ID)); - gen_mov_32(x86_memory_operand(2*4, REG_T0_ID), REG_T1_ID); - gen_mov_32(x86_memory_operand(3*4, REG_T0_ID), REG_T2_ID); - gen_bswap_32(REG_T1_ID); - gen_bswap_32(REG_T2_ID); - gen_mov_32(REG_T1_ID, x86_memory_operand(xPPC_VR(vD) + 2*4, REG_CPU_ID)); - gen_mov_32(REG_T2_ID, x86_memory_operand(xPPC_VR(vD) + 3*4, REG_CPU_ID)); -#endif - return true; -} - -// stvx, stvxl -bool powerpc_jit::gen_x86_stvx(int mnemo, int vS, int rA, int rB) -{ - // NOTE: primitive scheduling - gen_mov_32(x86_memory_operand(xPPC_GPR(rB), REG_CPU_ID), REG_T0_ID); -#if SIZEOF_VOID_P == 8 - gen_mov_64(x86_memory_operand(xPPC_VR(vS) + 0, REG_CPU_ID), REG_T1_ID); - gen_mov_64(x86_memory_operand(xPPC_VR(vS) + 8, REG_CPU_ID), REG_T2_ID); - if (rA != 0) - gen_add_32(x86_memory_operand(xPPC_GPR(rA), REG_CPU_ID), REG_T0_ID); - gen_bswap_64(REG_T1_ID); - gen_bswap_64(REG_T2_ID); - gen_and_32(x86_immediate_operand(-16), REG_T0_ID); - gen_rol_64(x86_immediate_operand(32), REG_T1_ID); - gen_rol_64(x86_immediate_operand(32), REG_T2_ID); - gen_mov_64(REG_T1_ID, x86_memory_operand(0, REG_T0_ID)); - gen_mov_64(REG_T2_ID, x86_memory_operand(8, REG_T0_ID)); -#else - gen_mov_32(x86_memory_operand(xPPC_VR(vS) + 0*4, REG_CPU_ID), REG_T1_ID); - gen_mov_32(x86_memory_operand(xPPC_VR(vS) + 1*4, REG_CPU_ID), REG_T2_ID); - if (rA != 0) - gen_add_32(x86_memory_operand(xPPC_GPR(rA), REG_CPU_ID), REG_T0_ID); - gen_bswap_32(REG_T1_ID); - gen_bswap_32(REG_T2_ID); - gen_and_32(x86_immediate_operand(-16), REG_T0_ID); - gen_mov_32(REG_T1_ID, x86_memory_operand(0*4, REG_T0_ID)); - gen_mov_32(REG_T2_ID, x86_memory_operand(1*4, REG_T0_ID)); - gen_mov_32(x86_memory_operand(xPPC_VR(vS) + 2*4, REG_CPU_ID), REG_T1_ID); - gen_mov_32(x86_memory_operand(xPPC_VR(vS) + 3*4, REG_CPU_ID), REG_T2_ID); - gen_bswap_32(REG_T1_ID); - gen_bswap_32(REG_T2_ID); - gen_mov_32(REG_T1_ID, x86_memory_operand(2*4, REG_T0_ID)); - gen_mov_32(REG_T2_ID, x86_memory_operand(3*4, REG_T0_ID)); -#endif - return true; -} - -/* - * MMX optimizations - */ - -// Generic MMX arith -bool powerpc_jit::gen_mmx_arith_2(int mnemo, int vD, int vA, int vB) -{ - gen_load_ad_VD_VR(vD); - gen_load_ad_V0_VR(vA); - gen_load_ad_V1_VR(vB); - (this->*(jit_info[mnemo]->o.dyngen_handler))(); - gen_op_emms(); - return true; -} - -// MMX comparison -bool powerpc_jit::gen_mmx_arith_c(int mnemo, int vD, int vA, int vB, bool Rc) -{ - gen_mmx_arith_2(mnemo, vD, vA, vB); - if (Rc) - gen_record_cr6_VD(); - return true; -} - -/* - * SSE optimizations - */ - -// Record CR6 (vD contains the result of the CMP instruction) -void powerpc_jit::gen_sse_record_cr6(int vD) -{ - // NOTE: %ecx & %edx are caller saved registers and not static allocated at this time - assert(REG_T2_ID != (int)X86_ECX && REG_T2_ID != (int)X86_EDX); - gen_xor_32(X86_ECX, X86_ECX); // xor %t0,%t0 - gen_xor_32(X86_EDX, X86_EDX); // xor %t1,%t1 - gen_insn(X86_INSN_SSE_PS, X86_SSE_MOVMSK, vD, REG_T2_ID); // movmskps %v0,%t2 - gen_cmp_32(x86_immediate_operand(0), REG_T2_ID); // cmp $0,%t2 - gen_setcc(X86_CC_Z, X86_CL); // sete %t0 - gen_cmp_32(x86_immediate_operand(0xf), REG_T2_ID); // cmp $0xf,%t1 - gen_setcc(X86_CC_E, X86_DL); // sete %t1 - gen_lea_32(x86_memory_operand(0, X86_ECX, X86_EDX, 4), REG_T2_ID); // %t2 = %t0 + %t1*4 - gen_mov_32(x86_memory_operand(xPPC_CR, REG_CPU_ID), X86_ECX); // mov $xPPC_CR(%cpu),%t0 - gen_shl_32(x86_immediate_operand(5), REG_T2_ID); // %t2 holds new cr6 - gen_and_32(x86_immediate_operand(0xffffff0f), X86_ECX); // and $0xffffff0f,%t0 - gen_or_32(X86_ECX, REG_T2_ID); // or %t0,%t2 - gen_mov_32(REG_T2_ID, x86_memory_operand(xPPC_CR, REG_CPU_ID)); // mov %t0,$xPPC_CR(%cpu) -} - -// Generic SSE arith -bool powerpc_jit::gen_sse_arith_2(int mnemo, int vD, int vA, int vB) -{ - gen_movaps(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - const uint16 insn = jit_info[mnemo]->o.value; - gen_insn(insn >> 8, insn & 0xff, x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V0_ID); - gen_movaps(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -// Generic SSE arith with swapped operands (ANDPS) -bool powerpc_jit::gen_sse_arith_s(int mnemo, int vD, int vA, int vB) -{ - return gen_sse_arith_2(mnemo, vD, vB, vA); -} - -// SSE comparison (CMPPS) -bool powerpc_jit::gen_sse_arith_c(int mnemo, int vD, int vA, int vB, bool Rc) -{ - // NOTE: this uses swapped operands for GT, GE (no change for EQ) - gen_movaps(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V0_ID); - gen_cmpps(jit_info[mnemo]->o.value, x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - gen_movaps(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - if (Rc) - gen_sse_record_cr6(REG_V0_ID); - return true; -} - -// vmaddfp -bool powerpc_jit::gen_sse_vmaddfp(int mnemo, int vD, int vA, int vB, int vC) -{ - gen_movaps(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - gen_mulps(x86_memory_operand(xPPC_VR(vC), REG_CPU_ID), REG_V0_ID); - gen_addps(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V0_ID); - gen_movaps(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -// vnmsubfp -bool powerpc_jit::gen_sse_vnmsubfp(int mnemo, int vD, int vA, int vB, int vC) -{ - gen_movaps(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - gen_xorps(REG_V1_ID, REG_V1_ID); - gen_mulps(x86_memory_operand(xPPC_VR(vC), REG_CPU_ID), REG_V0_ID); - gen_subps(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V0_ID); - gen_subps(REG_V0_ID, REG_V1_ID); - gen_movaps(REG_V1_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -// vsel -bool powerpc_jit::gen_sse_vsel(int mnemo, int vD, int vA, int vB, int vC) -{ - // NOTE: simplified into (vB & vC) | (vA & ~vC) - gen_movaps(x86_memory_operand(xPPC_VR(vC), REG_CPU_ID), REG_V0_ID); - gen_movaps(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V1_ID); - gen_movaps(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V2_ID); - gen_andps(REG_V0_ID, REG_V1_ID); - gen_andnps(REG_V2_ID, REG_V0_ID); - gen_orps(REG_V1_ID, REG_V0_ID); - gen_movaps(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -/* - * SSE2 optimizations - */ - -// Record CR6 (vD contains the result of the CMP instruction) -void powerpc_jit::gen_sse2_record_cr6(int vD) -{ - // NOTE: %ecx & %edx are caller saved registers and not static allocated at this time - assert(REG_T2_ID != (int)X86_ECX && REG_T2_ID != (int)X86_EDX); - gen_xor_32(X86_ECX, X86_ECX); // xor %t0,%t0 - gen_xor_32(X86_EDX, X86_EDX); // xor %t1,%t1 - gen_pmovmskb(vD, REG_T2_ID); // pmovmskb %v0,%t2 - gen_cmp_32(x86_immediate_operand(0), REG_T2_ID); // cmp $0,%t2 - gen_setcc(X86_CC_Z, X86_CL); // sete %t0 - gen_cmp_32(x86_immediate_operand(0xffff), REG_T2_ID); // cmp $0xffff,%t1 - gen_setcc(X86_CC_E, X86_EDX); // sete %t1 - gen_lea_32(x86_memory_operand(0, X86_ECX, X86_EDX, 4), REG_T2_ID); // %t2 = %t0 + %t1*4 - gen_mov_32(x86_memory_operand(xPPC_CR, REG_CPU_ID), X86_ECX); // mov $xPPC_CR(%cpu),%t0 - gen_shl_32(x86_immediate_operand(5), REG_T2_ID); // %t2 holds new cr6 - gen_and_32(x86_immediate_operand(0xffffff0f), X86_ECX); // and $0xffffff0f,%t0 - gen_or_32(X86_ECX, REG_T2_ID); // or %t0,%t2 - gen_mov_32(REG_T2_ID, x86_memory_operand(xPPC_CR, REG_CPU_ID)); // mov %t0,$xPPC_CR(%cpu) -} - -// Generic SSE2 arith -bool powerpc_jit::gen_sse2_arith_2(int mnemo, int vD, int vA, int vB) -{ - gen_movdqa(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - const uint16 insn = jit_info[mnemo]->o.value; - gen_insn(insn >> 8, insn & 0xff, x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V0_ID); - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -// Generic SSE2 arith with swapped operands (PANDN) -bool powerpc_jit::gen_sse2_arith_s(int mnemo, int vD, int vA, int vB) -{ - return gen_sse2_arith_2(mnemo, vD, vB, vA); -} - -// SSE2 comparison (PCMPEQ, PCMPGT) -bool powerpc_jit::gen_sse2_arith_c(int mnemo, int vD, int vA, int vB, bool Rc) -{ - gen_sse2_arith_2(mnemo, vD, vA, vB); - if (Rc) - gen_sse2_record_cr6(REG_V0_ID); - return true; -} - -// vsldoi -bool powerpc_jit::gen_sse2_vsldoi(int mnemo, int vD, int vA, int vB, int SH) -{ - // Optimize out vsldoi vX,vX,vB,0 - if (SH == 0 && vA == vD) - return true; - - gen_movdqa(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - if (SH) { - gen_movdqa(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V1_ID); - gen_pshufd(x86_immediate_operand(0x1b), REG_V0_ID, REG_V0_ID); - gen_pshufd(x86_immediate_operand(0x1b), REG_V1_ID, REG_V1_ID); - gen_pslldq(x86_immediate_operand(SH), REG_V0_ID); - gen_psrldq(x86_immediate_operand(16 - SH), REG_V1_ID); - gen_por(REG_V1_ID, REG_V0_ID); - gen_pshufd(x86_immediate_operand(0x1b), REG_V0_ID, REG_V0_ID); - } - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -// vsel -bool powerpc_jit::gen_sse2_vsel(int mnemo, int vD, int vA, int vB, int vC) -{ - // NOTE: simplified into (vB & vC) | (vA & ~vC) - gen_movdqa(x86_memory_operand(xPPC_VR(vC), REG_CPU_ID), REG_V0_ID); - gen_movdqa(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V1_ID); - gen_movdqa(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V2_ID); - gen_pand(REG_V0_ID, REG_V1_ID); - gen_pandn(REG_V2_ID, REG_V0_ID); - gen_por(REG_V1_ID, REG_V0_ID); - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -/* - * Vector splat instructions - * - * Reference: "Optimizing subroutines in assembly language", Agner, table 13.6 - */ - -void powerpc_jit::gen_sse2_vsplat(int vD, int rValue) -{ - gen_movd_lx(rValue, REG_V0_ID); - gen_pshufd(x86_immediate_operand(0), REG_V0_ID, REG_V0_ID); - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); -} - -// vspltisb -bool powerpc_jit::gen_sse2_vspltisb(int mnemo, int vD, int SIMM) -{ - switch (SIMM) { - case 0: - gen_pxor(REG_V0_ID, REG_V0_ID); - goto commit; - case 1: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(15), REG_V0_ID); - gen_packuswb(REG_V0_ID, REG_V0_ID); - goto commit; - case 2: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(15), REG_V0_ID); - gen_psllw(x86_immediate_operand(1), REG_V0_ID); - gen_packuswb(REG_V0_ID, REG_V0_ID); - goto commit; - case 3: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(14), REG_V0_ID); - gen_packuswb(REG_V0_ID, REG_V0_ID); - goto commit; - case 4: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(15), REG_V0_ID); - gen_psllw(x86_immediate_operand(2), REG_V0_ID); - gen_packuswb(REG_V0_ID, REG_V0_ID); - goto commit; - case -1: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - goto commit; - case -2: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psllw(x86_immediate_operand(1), REG_V0_ID); - gen_packsswb(REG_V0_ID, REG_V0_ID); - goto commit; - { - commit: - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - break; - } - default: - const uint32 value = ((uint8)SIMM) * 0x01010101; - gen_mov_32(x86_immediate_operand(value), REG_T0_ID); - gen_sse2_vsplat(vD, REG_T0_ID); - break; - } - return true; -} - -// vspltish -bool powerpc_jit::gen_sse2_vspltish(int mnemo, int vD, int SIMM) -{ - switch (SIMM) { - case 0: - gen_pxor(REG_V0_ID, REG_V0_ID); - goto commit; - case 1: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(15), REG_V0_ID); - goto commit; - case 2: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(15), REG_V0_ID); - gen_psllw(x86_immediate_operand(1), REG_V0_ID); - goto commit; - case 3: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(14), REG_V0_ID); - goto commit; - case 4: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psrlw(x86_immediate_operand(15), REG_V0_ID); - gen_psllw(x86_immediate_operand(2), REG_V0_ID); - goto commit; - case -1: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - goto commit; - case -2: - gen_pcmpeqw(REG_V0_ID, REG_V0_ID); - gen_psllw(x86_immediate_operand(1), REG_V0_ID); - goto commit; - { - commit: - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - break; - } - default: - const uint32 value = ((uint16)SIMM) * 0x10001; - gen_mov_32(x86_immediate_operand(value), REG_T0_ID); - gen_sse2_vsplat(vD, REG_T0_ID); - break; - } - return true; -} - -// vspltisw -bool powerpc_jit::gen_sse2_vspltisw(int mnemo, int vD, int SIMM) -{ - switch (SIMM) { - case 0: - gen_pxor(REG_V0_ID, REG_V0_ID); - goto commit; - case 1: - gen_pcmpeqd(REG_V0_ID, REG_V0_ID); - gen_psrld(x86_immediate_operand(31), REG_V0_ID); - goto commit; - case 2: - gen_pcmpeqd(REG_V0_ID, REG_V0_ID); - gen_psrld(x86_immediate_operand(31), REG_V0_ID); - gen_pslld(x86_immediate_operand(1), REG_V0_ID); - goto commit; - case 3: - gen_pcmpeqd(REG_V0_ID, REG_V0_ID); - gen_psrld(x86_immediate_operand(30), REG_V0_ID); - goto commit; - case 4: - gen_pcmpeqd(REG_V0_ID, REG_V0_ID); - gen_psrld(x86_immediate_operand(31), REG_V0_ID); - gen_pslld(x86_immediate_operand(2), REG_V0_ID); - goto commit; - case -1: - gen_pcmpeqd(REG_V0_ID, REG_V0_ID); - goto commit; - case -2: - gen_pcmpeqd(REG_V0_ID, REG_V0_ID); - gen_pslld(x86_immediate_operand(1), REG_V0_ID); - goto commit; - { - commit: - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - break; - } - default: - const uint32 value = SIMM; - gen_mov_32(x86_immediate_operand(value), REG_T0_ID); - gen_sse2_vsplat(vD, REG_T0_ID); - } - return true; -} - -// vspltb -bool powerpc_jit::gen_sse2_vspltb(int mnemo, int vD, int UIMM, int vB) -{ - const int N = ev_mixed::byte_element(UIMM & 15); - gen_mov_zx_8_32(x86_memory_operand(xPPC_VR(vB) + N * 1, REG_CPU_ID), REG_T0_ID); - gen_imul_32(x86_immediate_operand(0x01010101), REG_T0_ID, REG_T0_ID); - gen_sse2_vsplat(vD, REG_T0_ID); - return true; -} - -// vsplth -bool powerpc_jit::gen_sse2_vsplth(int mnemo, int vD, int UIMM, int vB) -{ - const int N = ev_mixed::half_element(UIMM & 7); - gen_mov_zx_16_32(x86_memory_operand(xPPC_VR(vB) + N * 2, REG_CPU_ID), REG_T0_ID); - gen_imul_32(x86_immediate_operand(0x10001), REG_T0_ID, REG_T0_ID); - gen_sse2_vsplat(vD, REG_T0_ID); - return true; -} - -// vspltw -bool powerpc_jit::gen_sse2_vspltw(int mnemo, int vD, int UIMM, int vB) -{ - const int N = UIMM & 3; - gen_mov_32(x86_memory_operand(xPPC_VR(vB) + N * 4, REG_CPU_ID), REG_T0_ID); - gen_sse2_vsplat(vD, REG_T0_ID); - return true; -} - -/* - * SSSE3 optimizations - */ - -uintptr powerpc_jit::gen_ssse3_vswap_mask(void) -{ - // We must get the following bytes in memory - // 0x3 0x2 0x1 0x0 0x7 0x6 0x5 0x4 0xb 0xa 0x9 0x8 0xf 0xe 0xd 0xc - static uintptr control_mask = 0; - if (control_mask == 0) { - static const uint8 value[16] = { - 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, - 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c - }; - control_mask = (uintptr)copy_data(value, sizeof(value)); - assert(control_mask <= 0xffffffff); - } - return control_mask; -} - -// lvx, lvxl -bool powerpc_jit::gen_ssse3_lvx(int mnemo, int vD, int rA, int rB) -{ - gen_mov_32(x86_memory_operand(xPPC_GPR(rB), REG_CPU_ID), REG_T0_ID); - if (rA != 0) - gen_add_32(x86_memory_operand(xPPC_GPR(rA), REG_CPU_ID), REG_T0_ID); - gen_and_32(x86_immediate_operand(-16), REG_T0_ID); - - x86_memory_operand vswapmask(gen_ssse3_vswap_mask(), X86_NOREG); - gen_movdqa(x86_memory_operand(0, REG_T0_ID), REG_V0_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, vswapmask, REG_V0_ID); - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} - -// stvx, stvxl -bool powerpc_jit::gen_ssse3_stvx(int mnemo, int vS, int rA, int rB) -{ - gen_mov_32(x86_memory_operand(xPPC_GPR(rB), REG_CPU_ID), REG_T0_ID); - if (rA != 0) - gen_add_32(x86_memory_operand(xPPC_GPR(rA), REG_CPU_ID), REG_T0_ID); - gen_and_32(x86_immediate_operand(-16), REG_T0_ID); - - x86_memory_operand vswapmask(gen_ssse3_vswap_mask(), X86_NOREG); - gen_movdqa(x86_memory_operand(xPPC_VR(vS), REG_CPU_ID), REG_V0_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, vswapmask, REG_V0_ID); - gen_movdqa(REG_V0_ID, x86_memory_operand(0, REG_T0_ID)); - return true; -} - -// vperm -bool powerpc_jit::gen_ssse3_vperm(int mnemo, int vD, int vA, int vB, int vC) -{ - static uintptr zero_mask = 0; - if (zero_mask == 0) { - static const uint8 value[16] = { - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 - }; - zero_mask = (uintptr)copy_data(value, sizeof(value)); - assert(zero_mask <= 0xffffffff); - } - - static uintptr index_mask = 0; - if (index_mask == 0) { - static const uint8 value[16] = { - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f - }; - index_mask = (uintptr)copy_data(value, sizeof(value)); - assert(index_mask <= 0xffffffff); - }; - - /* - * PROP_IMSB(T) = T.index|most significant bit of T.index (T.bit0 = T.bit3) - * --> used to handle one vector at a time - * - * T.A = PSHUFB(PROP_IMSB(vC & IndexMask), vA); - * T.B = PSHUFB(PROP_IMSB(vC & IndexMaxk) ^ ZeroMask, vB); - * vD = T.A | T.B - */ - x86_memory_operand swap_mask(gen_ssse3_vswap_mask(), X86_NOREG); - gen_movdqa(x86_memory_operand(xPPC_VR(vC), REG_CPU_ID), REG_V2_ID); - gen_movdqa(swap_mask, REG_V3_ID); - gen_movdqa(x86_memory_operand(xPPC_VR(vA), REG_CPU_ID), REG_V0_ID); - gen_pand(x86_memory_operand(index_mask, X86_NOREG), REG_V2_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, REG_V3_ID, REG_V0_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, REG_V3_ID, REG_V2_ID); - gen_movdqa(REG_V2_ID, REG_V1_ID); - gen_psllq(x86_immediate_operand(3), REG_V2_ID); - gen_pand(x86_memory_operand(zero_mask, X86_NOREG), REG_V2_ID); - gen_por(REG_V2_ID, REG_V1_ID); - gen_movdqa(x86_memory_operand(xPPC_VR(vB), REG_CPU_ID), REG_V2_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, REG_V1_ID, REG_V0_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, REG_V3_ID, REG_V2_ID); - gen_pxor(x86_memory_operand(zero_mask, X86_NOREG), REG_V1_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, REG_V1_ID, REG_V2_ID); - gen_por(REG_V2_ID, REG_V0_ID); - gen_insn(X86_INSN_SSE_3P, X86_SSSE3_PSHUFB, REG_V3_ID, REG_V0_ID); - gen_movdqa(REG_V0_ID, x86_memory_operand(xPPC_VR(vD), REG_CPU_ID)); - return true; -} -#endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.hpp deleted file mode 100644 index a8e563ae..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-jit.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * ppc-jit.hpp - PowerPC dynamic translation (mid-level) - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_JIT_H -#define PPC_JIT_H - -#include "sysdeps.h" -#include "cpu/ppc/ppc-dyngen.hpp" - -struct powerpc_jit - : public powerpc_dyngen -{ - // Default constructor - powerpc_jit(dyngen_cpu_base cpu); - - // Initialization - bool initialize(void); - - bool gen_vector_1(int mnemo, int vD); - bool gen_vector_2(int mnemo, int vD, int vA, int vB); - bool gen_vector_3(int mnemo, int vD, int vA, int vB, int vC); - bool gen_vector_compare(int mnemo, int vD, int vA, int vB, bool Rc); - -private: - // Mid-level code generator info - typedef bool (powerpc_jit::*gen_handler_t)(int, bool); - typedef void (powerpc_dyngen::*dyngen_handler_t)(void); - union jit_option_t { - jit_option_t() { } - uintptr value; - jit_option_t(uintptr v) : value(v) { } - dyngen_handler_t dyngen_handler; - jit_option_t(dyngen_handler_t const & h) : dyngen_handler(h) { } - }; - struct jit_info_t { - int mnemo; - gen_handler_t handler; - jit_option_t o; - }; - static const jit_info_t *jit_info[]; - -private: - bool gen_not_available(int mnemo); - bool gen_vector_generic_1(int mnemo, int vD); - bool gen_vector_generic_2(int mnemo, int vD, int vA, int vB); - bool gen_vector_generic_3(int mnemo, int vD, int vA, int vB, int vC); - bool gen_vector_generic_c(int mnemo, int vD, int vA, int vB, bool Rc); - bool gen_vector_generic_load(int mnemo, int vD, int rA, int rB); - bool gen_vector_generic_store(int mnemo, int vS, int rA, int rB); - bool gen_vector_generic_load_word(int mnemo, int vD, int rA, int rB); - bool gen_vector_generic_store_word(int mnemo, int vS, int rA, int rB); - -#if defined(__i386__) || defined(__x86_64__) - bool gen_x86_lvx(int mnemo, int vD, int rA, int rB); - bool gen_x86_lvewx(int mnemo, int vD, int rA, int rB); - bool gen_x86_stvx(int mnemo, int vS, int rA, int rB); - bool gen_x86_stvewx(int mnemo, int vS, int rA, int rB); - bool gen_x86_mtvscr(int mnemo, int vD); - bool gen_x86_mfvscr(int mnemo, int vB); - bool gen_mmx_arith_2(int mnemo, int vD, int vA, int vB); - bool gen_mmx_arith_c(int mnemo, int vD, int vA, int vB, bool Rc); - void gen_sse_record_cr6(int vD); - bool gen_sse_arith_2(int mnemo, int vD, int vA, int vB); - bool gen_sse_arith_s(int mnemo, int vD, int vA, int vB); - bool gen_sse_arith_c(int mnemo, int vD, int vA, int vB, bool Rc); - bool gen_sse_vsel(int mnemo, int vD, int vA, int vB, int vC); - bool gen_sse_vmaddfp(int mnemo, int vD, int vA, int vB, int vC); - bool gen_sse_vnmsubfp(int mnemo, int vD, int vA, int vB, int vC); - void gen_sse2_record_cr6(int vD); - bool gen_sse2_arith_2(int mnemo, int vD, int vA, int vB); - bool gen_sse2_arith_s(int mnemo, int vD, int vA, int vB); - bool gen_sse2_arith_c(int mnemo, int vD, int vA, int vB, bool Rc); - bool gen_sse2_vsel(int mnemo, int vD, int vA, int vB, int vC); - bool gen_sse2_vsldoi(int mnemo, int vD, int vA, int vB, int SH); - void gen_sse2_vsplat(int vD, int rValue); - bool gen_sse2_vspltisb(int mnemo, int vD, int SIMM); - bool gen_sse2_vspltish(int mnemo, int vD, int SIMM); - bool gen_sse2_vspltisw(int mnemo, int vD, int SIMM); - bool gen_sse2_vspltb(int mnemo, int vD, int UIMM, int vB); - bool gen_sse2_vsplth(int mnemo, int vD, int UIMM, int vB); - bool gen_sse2_vspltw(int mnemo, int vD, int UIMM, int vB); - uintptr gen_ssse3_vswap_mask(void); - bool gen_ssse3_lvx(int mnemo, int vD, int rA, int rB); - bool gen_ssse3_stvx(int mnemo, int vS, int rA, int rB); - bool gen_ssse3_vperm(int mnemo, int vD, int vA, int vB, int vC); -#endif -}; - -#endif /* PPC_JIT_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp deleted file mode 100644 index 95716ac9..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operands.hpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - * ppc-operands.hpp - PowerPC operands definition - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_OPERANDS_H -#define PPC_OPERANDS_H - -/** - * Numerical limits of vector registers components - **/ - -template< class type > -struct vector_numeric_limits { - static type min() throw(); - static type max() throw(); -}; - -#define DEFINE_NUMERIC_LIMITS(TYPE, SMAX, USFX) \ -template<> \ -struct vector_numeric_limits { \ - static inline TYPE min() throw() { return -(SMAX) - 1; } \ - static inline TYPE max() throw() { return SMAX; } \ -}; \ -template<> \ -struct vector_numeric_limits { \ - static inline u##TYPE min() throw() { return 0##USFX; } \ - static inline u##TYPE max() throw() { return SMAX * 2##USFX + 1; } \ -} - -DEFINE_NUMERIC_LIMITS( int8, 127, U); -DEFINE_NUMERIC_LIMITS(int16, 32767, U); -DEFINE_NUMERIC_LIMITS(int32, 2147483647L, UL); -DEFINE_NUMERIC_LIMITS(int64, 9223372036854775807LL, ULL); - -#undef DEFINE_NUMERIC_LIMITS - -/** - * Compile time checks - **/ - -template< int a, int b > -struct ensure_equals; - -template< int n > -struct ensure_equals { }; - -template< class type, int size > -struct ensure_sizeof : ensure_equals { }; - -/** - * General purpose registers - **/ - -template< class field, class op > -struct input_gpr_op { - static inline uint32 get(powerpc_cpu * cpu, uint32 opcode) { - return op::apply(cpu->gpr(field::extract(opcode))); - } -}; - -template< class field > -struct input_gpr : input_gpr_op< field, op_nop > { }; - -template< class field > -struct output_gpr { - static inline void set(powerpc_cpu * cpu, uint32 opcode, uint32 value) { - cpu->gpr(field::extract(opcode)) = value; - } -}; - -template< class field > -struct gpr_operand : input_gpr< field >, output_gpr< field > { }; - -template< class field, int except_regno > -struct input_gpr_except { - static inline uint32 get(powerpc_cpu * cpu, uint32 opcode) { - const int regno = field::extract(opcode); - return regno != except_regno ? cpu->gpr(regno) : 0; - }; - static inline void set(powerpc_cpu * cpu, uint32 opcode, uint32 value) { - const int regno = field::extract(opcode); - if (regno == except_regno) abort(); - cpu->gpr(regno) = value; - } -}; - -/** - * Floating-point registers - **/ - -template< class field > -struct input_fpr { - static inline double get(powerpc_cpu * cpu, uint32 opcode) { - return cpu->fpr(field::extract(opcode)); - } -}; - -template< class field > -struct output_fpr { - static inline void set(powerpc_cpu * cpu, uint32 opcode, double value) { - cpu->fpr(field::extract(opcode)) = value; - } -}; - -template< class field > -struct fpr_operand : input_fpr< field >, output_fpr< field > { }; - -template< class field > -struct input_fpr_dw { - static inline uint64 get(powerpc_cpu * cpu, uint32 opcode) { - return cpu->fpr_dw(field::extract(opcode)); - } -}; - -template< class field > -struct output_fpr_dw { - static inline void set(powerpc_cpu * cpu, uint32 opcode, uint64 value) { - cpu->fpr_dw(field::extract(opcode)) = value; - } -}; - -template< class field > -struct fpr_dw_operand : input_fpr_dw< field >, output_fpr_dw< field > { }; - -/** - * Vector registers - **/ - -struct ev_direct { - static inline int byte_element(int i) { return i; } - static inline int half_element(int i) { return i; } - static inline int word_element(int i) { return i; } -}; - -// This supposes elements are loaded by 4-byte word parts -#ifdef WORDS_BIGENDIAN -typedef ev_direct ev_mixed; -#else -struct ev_mixed : public ev_direct { -#if 0 - static inline int byte_element(int i) { return (i & ~3) + (3 - (i & 3)); } - static inline int half_element(int i) { return (i & ~1) + (1 - (i & 1)); } -#else - static inline int byte_element(int i) { - static const int lookup[16] = { - 3, 2, 1, 0, - 7, 6, 5, 4, - 11, 10, 9, 8, - 15, 14, 13, 12 - }; - return lookup[i]; - } - static inline int half_element(int i) { - static const int lookup[8] = { - 1, 0, 3, 2, - 5, 4, 7, 6 - }; - return lookup[i]; - } -#endif -}; -#endif - -struct null_vector_operand { - typedef uint32 type; - typedef uint32 element_type; - static const uint32 element_size = sizeof(element_type); - static inline type const_ref(powerpc_cpu *, uint32) { return 0; } // fake so that compiler optimizes it out - static inline element_type get_element(type const & reg, int i) { return 0; } -}; - -template< class field > -struct vimm_operand { - typedef uint32 type; - typedef uint32 element_type; - static const uint32 element_size = sizeof(element_type); - static inline type const_ref(powerpc_cpu *, uint32 opcode) { return field::extract(opcode); } - static inline element_type get_element(type const & reg, int i) { return reg; } -}; - -template< class field > -struct input_vr { - static inline powerpc_vr const & const_ref(powerpc_cpu * cpu, uint32 opcode) { - return cpu->vr(field::extract(opcode)); - } -}; - -template< class field > -struct output_vr { - static inline powerpc_vr & ref(powerpc_cpu * cpu, uint32 opcode) { - return cpu->vr(field::extract(opcode)); - } -}; - -template< class field, class value_type > -struct vector_operand : input_vr< field >, output_vr< field > { - typedef powerpc_vr type; - typedef value_type element_type; - static const uint32 element_size = sizeof(element_type); - static inline bool saturate(element_type) { return false; } -}; - -template< class field, class value_type, class sat_type > -struct vector_saturate_operand : input_vr< field >, output_vr< field > { - typedef powerpc_vr type; - typedef sat_type element_type; - static const uint32 element_size = sizeof(value_type); - static inline bool saturate(element_type & v) { - bool sat = false; - if (v > vector_numeric_limits::max()) { - v = vector_numeric_limits::max(); - sat = true; - } - else if (v < vector_numeric_limits::min()) { - v = vector_numeric_limits::min(); - sat = true; - } - return sat; - } -}; - -template< class field, class value_type, class sat_type = int16, class ev = ev_direct > -struct v16qi_sat_operand : vector_saturate_operand< field, value_type, sat_type >, ensure_sizeof< sat_type, 2 > { - static inline sat_type get_element(powerpc_vr const & reg, int i) { - return (sat_type)(value_type)reg.b[ev::byte_element(i)]; - } - static inline void set_element(powerpc_vr & reg, int i, sat_type value) { - reg.b[ev::byte_element(i)] = value; - } -}; - -template< class field, class value_type, class sat_type = int32, class ev = ev_direct > -struct v8hi_sat_operand : vector_saturate_operand< field, value_type, sat_type >, ensure_sizeof< sat_type, 4 > { - static inline sat_type get_element(powerpc_vr const & reg, int i) { - return (sat_type)(value_type)reg.h[ev::half_element(i)]; - } - static inline void set_element(powerpc_vr & reg, int i, sat_type value) { - reg.h[ev::half_element(i)] = value; - } -}; - -template< class field, class value_type, class sat_type = int64 > -struct v4si_sat_operand : vector_saturate_operand< field, value_type, sat_type >, ensure_sizeof< sat_type, 8 > { - static inline sat_type get_element(powerpc_vr const & reg, int i) { - return (sat_type)(value_type)reg.w[i]; - } - static inline void set_element(powerpc_vr & reg, int i, sat_type value) { - reg.w[i] = value; - } -}; - -template< class field, class value_type = uint8, class ev = ev_direct > -struct v16qi_operand : vector_operand< field, value_type >, ensure_sizeof< value_type, 1 > { - static inline value_type get_element(powerpc_vr const & reg, int i) { - return reg.b[ev::byte_element(i)]; - } - static inline void set_element(powerpc_vr & reg, int i, value_type value) { - reg.b[ev::byte_element(i)] = value; - } -}; - -template< class field, class value_type = uint16, class ev = ev_direct > -struct v8hi_operand : vector_operand< field, value_type >, ensure_sizeof< value_type, 2 > { - static inline value_type get_element(powerpc_vr const & reg, int i) { - return reg.h[ev::half_element(i)]; - } - static inline void set_element(powerpc_vr & reg, int i, value_type value) { - reg.h[ev::half_element(i)] = value; - } -}; - -template< class field, class value_type = uint32 > -struct v4si_operand : vector_operand< field, value_type >, ensure_sizeof< value_type, 4 > { - static inline value_type get_element(powerpc_vr const & reg, int i) { - return reg.w[i]; - } - static inline void set_element(powerpc_vr & reg, int i, value_type value) { - reg.w[i] = value; - } -}; - -template< class field, class value_type = uint64 > -struct v2di_operand : vector_operand< field, value_type >, ensure_sizeof< value_type, 8 > { - static inline value_type get_element(powerpc_vr const & reg, int i) { - return reg.j[i]; - } - static inline void set_element(powerpc_vr & reg, int i, value_type value) { - reg.j[i] = value; - } -}; - -template< class field > -struct v4sf_operand : vector_operand< field, float > { - static inline float get_element(powerpc_vr const & reg, int i) { - return reg.f[i]; - } - static inline void set_element(powerpc_vr & reg, int i, float value) { - reg.f[i] = value; - } -}; - -template< class field > -struct vSH_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32 opcode) { - return (cpu->vr(field::extract(opcode)).b[ev_mixed::byte_element(15)] >> 3) & 15; - } -}; - - -/** - * Immediate operands - **/ - -struct null_operand { - static inline uint32 get(powerpc_cpu *, uint32) { - return 0; - } -}; -template< class field, class operation > -struct immediate_operand { - static inline uint32 get(powerpc_cpu *, uint32 opcode) { - return operation::apply(field::extract(opcode)); - } -}; - -template< int32 N > -struct immediate_value { - static inline uint32 get(powerpc_cpu *, uint32) { - return (uint32)N; - } -}; - -struct mask_operand { - static inline uint32 compute(uint32 mb, uint32 me) { - return ((mb > me) ? - ~(((uint32)-1 >> mb) ^ ((me >= 31) ? 0 : (uint32)-1 >> (me + 1))) : - (((uint32)-1 >> mb) ^ ((me >= 31) ? 0 : (uint32)-1 >> (me + 1)))); - } - static inline uint32 get(powerpc_cpu *, uint32 opcode) { - const uint32 mb = MB_field::extract(opcode); - const uint32 me = ME_field::extract(opcode); - return compute(mb, me); - } -}; - -/** - * Special purpose registers - **/ - -struct pc_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return cpu->pc(); - }; -}; - -struct lr_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return cpu->lr(); - }; -}; - -struct ctr_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return cpu->ctr(); - }; -}; - -struct cr_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return cpu->cr().get(); - } -}; - -template< class field > -struct xer_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return field::extract(cpu->xer().get()); - } -}; - -template<> -struct xer_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return cpu->xer().get_ca(); - } -}; - -template<> -struct xer_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return cpu->xer().get_count(); - } -}; - -template< class field > -struct fpscr_operand { - static inline uint32 get(powerpc_cpu * cpu, uint32) { - return field::extract(cpu->fpscr()); - } -}; - -struct spr_operand { - static inline uint32 get(powerpc_cpu *, uint32 opcode) { - uint32 spr = SPR_field::extract(opcode); - return ((spr & 0x1f) << 5) | ((spr >> 5) & 0x1f); - } -}; - -struct tbr_operand { - static inline uint32 get(powerpc_cpu *, uint32 opcode) { - uint32 tbr = TBR_field::extract(opcode); - return ((tbr & 0x1f) << 5) | ((tbr >> 5) & 0x1f); - } -}; - - -/** - * Operand aliases for decode table - **/ - -typedef null_operand operand_NONE; -typedef cr_operand operand_CR; -typedef pc_operand operand_PC; -typedef lr_operand operand_LR; -typedef ctr_operand operand_CTR; -typedef input_gpr_op operand_RA_compl; -typedef gpr_operand operand_RA; -typedef gpr_operand operand_RB; -typedef gpr_operand operand_RS; -typedef gpr_operand operand_RD; -typedef input_gpr_except operand_RA_or_0; // RA ? GPR(RA) : 0 -typedef immediate_value<0> operand_RA_is_0; // RA -> 0 -typedef immediate_value<1> operand_ONE; -typedef immediate_value<0> operand_ZERO; -typedef immediate_value<-1> operand_MINUS_ONE; -typedef null_operand operand_fp_NONE; -typedef fpr_operand operand_fp_RA; -typedef fpr_operand operand_fp_RB; -typedef fpr_operand operand_fp_RC; -typedef fpr_operand operand_fp_RD; -typedef fpr_operand operand_fp_RS; -typedef fpr_dw_operand operand_fp_dw_RA; -typedef fpr_dw_operand operand_fp_dw_RB; -typedef fpr_dw_operand operand_fp_dw_RC; -typedef fpr_dw_operand operand_fp_dw_RD; -typedef fpr_dw_operand operand_fp_dw_RS; -typedef xer_operand operand_XER_CA; -typedef xer_operand operand_XER_COUNT; -typedef fpscr_operand operand_FPSCR_RN; -typedef spr_operand operand_SPR; -typedef tbr_operand operand_TBR; -typedef mask_operand operand_MASK; -typedef null_vector_operand operand_vD_NONE; -typedef null_vector_operand operand_vA_NONE; -typedef null_vector_operand operand_vB_NONE; -typedef null_vector_operand operand_vC_NONE; -typedef v16qi_operand operand_vD_V16QI; -typedef v16qi_operand operand_vA_V16QI; -typedef v16qi_operand operand_vB_V16QI; -typedef v16qi_operand operand_vC_V16QI; -typedef v16qi_operand operand_vD_V16QIs; -typedef v16qi_operand operand_vA_V16QIs; -typedef v16qi_operand operand_vB_V16QIs; -typedef v16qi_operand operand_vC_V16QIs; -typedef v16qi_operand operand_vD_V16QIms; -typedef v16qi_operand operand_vB_V16QIms; -typedef v8hi_operand operand_vD_V8HI; -typedef v8hi_operand operand_vA_V8HI; -typedef v8hi_operand operand_vB_V8HI; -typedef v8hi_operand operand_vC_V8HI; -typedef v8hi_operand operand_vD_V8HIs; -typedef v8hi_operand operand_vA_V8HIs; -typedef v8hi_operand operand_vB_V8HIs; -typedef v8hi_operand operand_vC_V8HIs; -typedef v8hi_operand operand_vD_V8HIms; -typedef v8hi_operand operand_vB_V8HIms; -typedef v4si_operand operand_vD_V4SI; -typedef v4si_operand operand_vA_V4SI; -typedef v4si_operand operand_vB_V4SI; -typedef v4si_operand operand_vC_V4SI; -typedef v4si_operand operand_vD_V4SIs; -typedef v4si_operand operand_vA_V4SIs; -typedef v4si_operand operand_vB_V4SIs; -typedef v4si_operand operand_vC_V4SIs; -typedef v2di_operand operand_vD_V2DI; -typedef v2di_operand operand_vA_V2DI; -typedef v2di_operand operand_vB_V2DI; -typedef v2di_operand operand_vC_V2DI; -typedef v2di_operand operand_vD_V2DIs; -typedef v2di_operand operand_vA_V2DIs; -typedef v2di_operand operand_vB_V2DIs; -typedef v2di_operand operand_vC_V2DIs; -typedef v4sf_operand operand_vD_V4SF; -typedef v4sf_operand operand_vA_V4SF; -typedef v4sf_operand operand_vB_V4SF; -typedef v4sf_operand operand_vC_V4SF; -typedef v4si_operand operand_vS_V4SI; -typedef v2di_operand operand_vS_V2DI; -typedef vimm_operand operand_vA_UIMM; -typedef vimm_operand operand_vB_UIMM; -typedef vSH_operand operand_SHBO; - -// vector mixed element accessors -typedef v16qi_operand operand_vA_V16QIm; -typedef v16qi_operand operand_vB_V16QIm; -typedef v16qi_operand operand_vD_V16QIm; -typedef v8hi_operand operand_vA_V8HIm; -typedef v8hi_operand operand_vB_V8HIm; -typedef v8hi_operand operand_vD_V8HIm; - -#define DEFINE_VECTOR_SAT_OPERAND(EV, REG, OP) \ -template< class value_type > \ -struct operand_##REG##_##EV##_SAT : OP##_sat_operand { } - -DEFINE_VECTOR_SAT_OPERAND(V4SI, vD, v4si); -DEFINE_VECTOR_SAT_OPERAND(V4SI, vA, v4si); -DEFINE_VECTOR_SAT_OPERAND(V4SI, vB, v4si); -DEFINE_VECTOR_SAT_OPERAND(V4SI, vC, v4si); -DEFINE_VECTOR_SAT_OPERAND(V8HI, vD, v8hi); -DEFINE_VECTOR_SAT_OPERAND(V8HI, vA, v8hi); -DEFINE_VECTOR_SAT_OPERAND(V8HI, vB, v8hi); -DEFINE_VECTOR_SAT_OPERAND(V8HI, vC, v8hi); -DEFINE_VECTOR_SAT_OPERAND(V16QI, vD, v16qi); -DEFINE_VECTOR_SAT_OPERAND(V16QI, vA, v16qi); -DEFINE_VECTOR_SAT_OPERAND(V16QI, vB, v16qi); -DEFINE_VECTOR_SAT_OPERAND(V16QI, vC, v16qi); - -#undef DEFINE_VECTOR_SAT_OPERAND - -#define DEFINE_VECTOR_MIXED_SAT_OPERAND(EV, SAT, REG, OP, TYPE) \ -template< class value_type > \ -struct operand_##REG##_##EV##m_##SAT : OP##_sat_operand { } - -DEFINE_VECTOR_MIXED_SAT_OPERAND(V16QI, SAT, vA, v16qi, int16); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V16QI, SAT, vB, v16qi, int16); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V16QI, SAT, vD, v16qi, int16); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V16QI, USAT, vD, v16qi, uint16); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V8HI, SAT, vA, v8hi, int32); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V8HI, SAT, vB, v8hi, int32); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V8HI, SAT, vD, v8hi, int32); -DEFINE_VECTOR_MIXED_SAT_OPERAND(V8HI, USAT, vD, v8hi, uint32); - -#undef DEFINE_VECTOR_MIXED_SAT_OPERAND - -#define DEFINE_VECTOR_USAT_OPERAND(EV, REG, OP, TYPE) \ -template< class value_type > \ -struct operand_##REG##_##EV##_USAT : OP##_sat_operand { } - -// FIXME: temporary for vector pack unsigned saturate variants -DEFINE_VECTOR_USAT_OPERAND(V4SI, vD, v4si, uint64); -DEFINE_VECTOR_USAT_OPERAND(V8HI, vD, v8hi, uint32); -DEFINE_VECTOR_USAT_OPERAND(V16QI, vD, v16qi, uint16); - -#undef DEFINE_VECTOR_USAT_OPERAND - -#define DEFINE_IMMEDIATE_OPERAND(NAME, FIELD, OP) \ -typedef immediate_operand operand_##NAME - -DEFINE_IMMEDIATE_OPERAND(LI, LI, sign_extend_LI_32); -DEFINE_IMMEDIATE_OPERAND(BO, BO, nop); -DEFINE_IMMEDIATE_OPERAND(BD, BD, sign_extend_BD_32); -DEFINE_IMMEDIATE_OPERAND(IMM, IMM, nop); -DEFINE_IMMEDIATE_OPERAND(UIMM, UIMM, zero_extend_16_32); -DEFINE_IMMEDIATE_OPERAND(UIMM_shifted, UIMM, zero_extend_16_32_shifted); -DEFINE_IMMEDIATE_OPERAND(SIMM, SIMM, sign_extend_16_32); -DEFINE_IMMEDIATE_OPERAND(SIMM_shifted, SIMM, sign_extend_16_32_shifted); -DEFINE_IMMEDIATE_OPERAND(D, d, sign_extend_16_32); -DEFINE_IMMEDIATE_OPERAND(NB, NB, nop); -DEFINE_IMMEDIATE_OPERAND(SH, SH, nop); -DEFINE_IMMEDIATE_OPERAND(FM, FM, nop); -DEFINE_IMMEDIATE_OPERAND(SHB, vSH, nop); - -#undef DEFINE_IMMEDIATE_OPERAND - -#endif /* PPC_OPERANDS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operations.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operations.hpp deleted file mode 100644 index 47b56493..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-operations.hpp +++ /dev/null @@ -1,405 +0,0 @@ -/* - * ppc-operations.cpp - PowerPC specific operations - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_OPERATIONS_H -#define PPC_OPERATIONS_H - -#include -#include "mathlib/mathlib.hpp" - -/** - * Define an unary/binary/trinary operation - * - * NAME Name of the operation - * TYPE Type of operands and result - * EXPR C++ expression defining the operation, parameters are x/y/z/t - **/ - -#define DEFINE_ALIAS_OP(NAME, T_NAME, TYPE) \ -typedef op_template_##T_NAME op_##NAME - -#define DEFINE_OP1(NAME, TYPE, EXPR) \ -struct op_##NAME { \ - static inline TYPE apply(TYPE x) { \ - return EXPR; \ - } \ -} - -#define DEFINE_TEMPLATE_OP1(NAME, EXPR) \ -template< class TYPE > \ -DEFINE_OP1(template_##NAME, TYPE, EXPR) - -#define DEFINE_OP2(NAME, TYPE, EXPR) \ -struct op_##NAME { \ - static inline TYPE apply(TYPE x, TYPE y) { \ - return EXPR; \ - } \ -} - -#define DEFINE_TEMPLATE_OP2(NAME, EXPR) \ -template< class TYPE > \ -DEFINE_OP2(template_##NAME, TYPE, EXPR) - -#define DEFINE_OP3(NAME, TYPE, EXPR) \ -struct op_##NAME { \ - static inline TYPE apply(TYPE x, TYPE y, TYPE z) { \ - return EXPR; \ - } \ -} - -#define DEFINE_OP4(NAME, TYPE, EXPR) \ -struct op_##NAME { \ - static inline TYPE apply(TYPE x, TYPE y, TYPE z, TYPE t) { \ - return EXPR; \ - } \ -} - -// Basic operations - -DEFINE_TEMPLATE_OP1(nop, x); -DEFINE_TEMPLATE_OP2(add, x + y); -DEFINE_TEMPLATE_OP2(sub, x - y); -DEFINE_TEMPLATE_OP2(mul, x * y); -DEFINE_TEMPLATE_OP2(div, x / y); -DEFINE_TEMPLATE_OP2(and, x & y); -DEFINE_TEMPLATE_OP2(or, x | y); -DEFINE_TEMPLATE_OP2(xor, x ^ y); -DEFINE_TEMPLATE_OP2(orc, x | ~y); -DEFINE_TEMPLATE_OP2(andc,x & ~y); -DEFINE_TEMPLATE_OP2(nand,~(x & y)); -DEFINE_TEMPLATE_OP2(nor, ~(x | y)); -DEFINE_TEMPLATE_OP2(eqv, ~(x ^ y)); - -// Integer basic operations - -DEFINE_ALIAS_OP(nop, nop, uint32); -DEFINE_ALIAS_OP(add, add, uint32); -DEFINE_ALIAS_OP(sub, sub, uint32); -DEFINE_ALIAS_OP(mul, mul, uint32); -DEFINE_ALIAS_OP(smul,mul, int32); -DEFINE_ALIAS_OP(div, div, uint32); -DEFINE_ALIAS_OP(sdiv,div, int32); -DEFINE_OP1(neg, uint32, -x); -DEFINE_OP1(compl, uint32, ~x); -DEFINE_OP2(mod, uint32, x % y); -DEFINE_ALIAS_OP(and, and, uint32); -DEFINE_ALIAS_OP(or, or, uint32); -DEFINE_ALIAS_OP(xor, xor, uint32); -DEFINE_ALIAS_OP(orc, orc, uint32); -DEFINE_ALIAS_OP(andc,andc,uint32); -DEFINE_ALIAS_OP(nand,nand,uint32); -DEFINE_ALIAS_OP(nor, nor, uint32); -DEFINE_ALIAS_OP(eqv, eqv, uint32); -DEFINE_OP2(shll, uint32, x << y); -DEFINE_OP2(shrl, uint32, x >> y); -DEFINE_OP2(shra, uint32, (int32)x >> y); -DEFINE_OP2(rotl, uint32, ((x << y) | (x >> (32 - y)))); -DEFINE_OP2(rotr, uint32, ((x >> y) | (x << (32 - y)))); - -DEFINE_OP4(ppc_rlwimi, uint32, (op_rotl::apply(x, y) & z) | (t & ~z)); -DEFINE_OP3(ppc_rlwinm, uint32, (op_rotl::apply(x, y) & z)); -DEFINE_OP3(ppc_rlwnm, uint32, (op_rotl::apply(x, (y & 0x1f)) & z)); - -DEFINE_ALIAS_OP(add_64, add, uint64); -DEFINE_ALIAS_OP(sub_64, sub, uint64); -DEFINE_ALIAS_OP(smul_64,mul, int64); -DEFINE_ALIAS_OP(and_64, and, uint64); -DEFINE_ALIAS_OP(andc_64,andc,uint64); -DEFINE_ALIAS_OP(or_64, or, uint64); -DEFINE_ALIAS_OP(nor_64, nor, uint64); -DEFINE_ALIAS_OP(xor_64, xor, uint64); - -// Floating-point basic operations - -DEFINE_OP1(fnop, double, x); -DEFINE_OP1(fabs, double, fabs(x)); -DEFINE_OP2(fadd, double, x + y); -DEFINE_OP2(fdiv, double, x / y); -DEFINE_OP3(fmadd, double, mathlib_fmadd(x, y, z)); -DEFINE_OP3(fmsub, double, mathlib_fmsub(x, y, z)); -DEFINE_OP2(fmul, double, x * y); -DEFINE_OP1(fnabs, double, -fabs(x)); -DEFINE_OP1(fneg, double, -x); -DEFINE_OP3(fnmadd, double, -mathlib_fmadd(x, y, z)); -DEFINE_OP3(fnmsub, double, -mathlib_fmsub(x, y, z)); -DEFINE_OP3(fnmadds, double, -(float)mathlib_fmadd(x, y, z)); -DEFINE_OP3(fnmsubs, double, -(float)mathlib_fmsub(x, y, z)); -DEFINE_OP2(fsub, double, x - y); -DEFINE_OP3(fsel, double, (x >= 0.0) ? y : z); -DEFINE_OP1(frim, double, floor(x)); -DEFINE_OP1(frin, double, round(x)); -DEFINE_OP1(frip, double, ceil(x)); -DEFINE_OP1(friz, double, trunc(x)); - -DEFINE_OP2(fadds, float, x + y); -DEFINE_OP2(fsubs, float, x - y); -DEFINE_OP1(exp2, float, exp2f(x)); -DEFINE_OP1(log2, float, log2f(x)); -DEFINE_OP1(fres, float, 1 / x); -DEFINE_OP1(frsqrt, float, 1 / sqrt(x)); -DEFINE_OP1(frsim, float, floorf(x)); -DEFINE_OP1(frsin, float, roundf(x)); -DEFINE_OP1(frsip, float, ceilf(x)); -DEFINE_OP1(frsiz, float, truncf(x)); - -// Misc operations used in AltiVec instructions - -template< class TYPE > -struct op_vrl { - static inline TYPE apply(TYPE v, TYPE n) { - const int sh = n & ((8 * sizeof(TYPE)) - 1); - return ((v << sh) | (v >> ((8 * sizeof(TYPE)) - sh))); - } -}; - -template< class TYPE > -struct op_vsl { - static inline TYPE apply(TYPE v, TYPE n) { - const int sh = n & ((8 * sizeof(TYPE)) - 1); - return v << sh; - } -}; - -template< class TYPE > -struct op_vsr { - static inline TYPE apply(TYPE v, TYPE n) { - const int sh = n & ((8 * sizeof(TYPE)) - 1); - return v >> sh; - } -}; - -template< uint16 round = 0 > -struct op_mhraddsh { - static inline int32 apply(int32 a, int32 b, int32 c) { - return (((a * b) + round) >> 15) + c; - } -}; - -struct op_cvt_fp2si { - static inline int64 apply(uint32 a, float b) { - // Delegate saturation to upper level - if (mathlib_isinf(b)) - return ((int64)(b < 0 ? 0x80000000 : 0x7fffffff)) << 32; - if (mathlib_isnan(b)) - return 0; - return (int64)(b * (1U << a)); - } -}; - -template< class TYPE > -struct op_cvt_si2fp { - static inline float apply(uint32 a, TYPE b) { - return ((float)b) / ((float)(1U << a)); - } -}; - -template< class TYPE > -struct op_max { - static inline TYPE apply(TYPE a, TYPE b) { - return (a > b) ? a : b; - } -}; - -template<> -struct op_max { - static inline float apply(float a, float b) { - // XXX The maximum of any value and a NaN is a QNaN - if (mathlib_isnan(a)) - return a; - if (mathlib_isnan(b)) - return b; - return a > b ? a : b; - } -}; - -template< class TYPE > -struct op_min { - static inline TYPE apply(TYPE a, TYPE b) { - return (a < b) ? a : b; - } -}; - -template<> -struct op_min { - static inline float apply(float a, float b) { - // XXX The minimum of any value and a NaN is a QNaN - if (mathlib_isnan(a)) - return a; - if (mathlib_isnan(b)) - return b; - return a < b ? a : b; - } -}; - -template< int nbytes > -struct op_all_ones { - static const uint32 value = (1U << (8 * nbytes)) - 1; -}; - -template<> -struct op_all_ones<4> { - static const uint32 value = 0xffffffff; -}; - -template< class VX > -struct op_cmp { - static const uint32 result = op_all_ones::value; -}; - -template< class VX > -struct op_cmp_eq { - static inline uint32 apply(VX a, VX b) { - return a == b ? op_cmp::result : 0; - } -}; - -template< class VX > -struct op_cmp_ge { - static inline uint32 apply(VX a, VX b) { - return a >= b ? op_cmp::result : 0; - } -}; - -template< class VX > -struct op_cmp_gt { - static inline uint32 apply(VX a, VX b) { - return a > b ? op_cmp::result : 0; - } -}; - -struct op_cmpbfp { - static inline uint32 apply(float a, float b) { - const bool le = a <= b; - const bool ge = a >= -b; - return (le ? 0 : (1 << 31)) | (ge ? 0 : (1 << 30)); - } -}; - -DEFINE_OP3(vsel, uint32, ((y & z) | (x & ~z))); -DEFINE_OP3(vmaddfp, float, ((x * z) + y)); -DEFINE_OP3(vnmsubfp, float, -((x * z) - y)); -DEFINE_OP3(mladduh, uint32, ((x * y) + z) & 0xffff); -DEFINE_OP2(addcuw, uint32, ((uint64)x + (uint64)y) >> 32); -DEFINE_OP2(subcuw, uint32, (~((int64)x - (int64)y) >> 32) & 1); -DEFINE_OP2(avgsb, int8, (((int16)x + (int16)y + 1) >> 1)); -DEFINE_OP2(avgsh, int16, (((int32)x + (int32)y + 1) >> 1)); -DEFINE_OP2(avgsw, int32, (((int64)x + (int64)y + 1) >> 1)); -DEFINE_OP2(avgub, uint8, ((uint16)x + (uint16)y + 1) >> 1); -DEFINE_OP2(avguh, uint16, ((uint32)x + (uint32)y + 1) >> 1); -DEFINE_OP2(avguw, uint32, ((uint64)x + (uint64)y + 1) >> 1); - - -#undef DEFINE_OP1 -#undef DEFINE_OP2 -#undef DEFINE_OP3 -#undef DEFINE_OP4 - -#undef DEFINE_TEMPLATE_OP1 -#undef DEFINE_TEMPLATE_OP2 -#undef DEFINE_TEMPLATE_OP3 - -#undef DEFINE_ALIAS_OP - - -// Sign/Zero-extend operation - -struct op_sign_extend_5_32 { - static inline uint32 apply(uint32 value) { - if (value & 0x10) - value -= 0x20; - return value; - } -}; - -struct op_sign_extend_16_32 { - static inline uint32 apply(uint32 value) { - return (uint32)(int32)(int16)value; - } -}; - -struct op_sign_extend_8_32 { - static inline uint32 apply(uint32 value) { - return (uint32)(int32)(int8)value; - } -}; - -struct op_zero_extend_16_32 { - static inline uint32 apply(uint32 value) { - return (uint32)(uint16)value; - } -}; - -struct op_zero_extend_8_32 { - static inline uint32 apply(uint32 value) { - return (uint32)(uint8)value; - } -}; - -struct op_sign_extend_16_32_shifted { - static inline uint32 apply(uint32 value) { - return op_sign_extend_16_32::apply(value) << 16; - } -}; - -struct op_zero_extend_16_32_shifted { - static inline uint32 apply(uint32 value) { - return op_zero_extend_16_32::apply(value) << 16; - } -}; - -struct op_sign_extend_BD_32 { - static inline uint32 apply(uint32 value) { - return op_sign_extend_16_32::apply(value << 2); - } -}; - -struct op_sign_extend_LI_32 { - static inline uint32 apply(uint32 value) { - if (value & 0x800000) - value |= 0xff000000; - return value << 2; - } -}; - - -// And Word with Immediate value - -template< uint32 value > -struct op_andi { - static inline uint32 apply(uint32 x) { - return x & value; - } -}; - - -// Count Leading Zero Word - -struct op_cntlzw { - static inline uint32 apply(uint32 x) { - uint32 n; - uint32 m = 0x80000000; - for (n = 0; n < 32; n++, m >>= 1) - if (x & m) - break; - return n; - } -}; - -#endif /* PPC_OPERATIONS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp deleted file mode 100644 index a44a32df..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-registers.hpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * ppc-registers.hpp - PowerPC registers definition - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef PPC_REGISTERS_H -#define PPC_REGISTERS_H - -#include "cpu/ppc/ppc-bitfields.hpp" - -/** - * Condition Register - **/ - -class powerpc_cr_register -{ - uint32 cr; -public: - bool test(int condition) const; - void set(uint32 v); - uint32 get() const; - void clear(int crfd); - void set(int crfd, uint32 v); - uint32 get(int crfd) const; - void set_so(int crfd, bool v); - void compute(int crfd, int32 v); -}; - -inline void -powerpc_cr_register::clear(int crfd) -{ - cr &= ~(0xf << (28 - 4 * crfd)); -} - -inline void -powerpc_cr_register::set(int crfd, uint32 v) -{ - clear(crfd); - cr |= v << (28 - 4 * crfd); -} - -inline uint32 -powerpc_cr_register::get(int crfd) const -{ - return (cr >> (28 - 4 * crfd)) & 0xf; -} - -inline void -powerpc_cr_register::set_so(int crfd, bool v) -{ - const uint32 m = standalone_CR_SO_field::mask() << (28 - 4 * crfd); - cr = (cr & ~m) | (v ? m : 0); -} - -inline void -powerpc_cr_register::compute(int crfd, int32 v) -{ - const uint32 m = (standalone_CR_LT_field::mask() | - standalone_CR_GT_field::mask() | - standalone_CR_EQ_field::mask() ) << (28 - 4 * crfd); - cr = (cr & ~m); - if (v < 0) - cr |= standalone_CR_LT_field::mask() << (28 - 4 * crfd); - else if (v > 0) - cr |= standalone_CR_GT_field::mask() << (28 - 4 * crfd); - else - cr |= standalone_CR_EQ_field::mask() << (28 - 4 * crfd); -} - -inline void -powerpc_cr_register::set(uint32 v) -{ - cr = v; -} - -inline uint32 -powerpc_cr_register::get() const -{ - return cr; -} - -inline bool -powerpc_cr_register::test(int condition) const -{ - return (cr << condition) & 0x80000000; -} - - -/** - * XER register (SPR1) - **/ - -class powerpc_xer_register -{ - uint8 so; - uint8 ov; - uint8 ca; - uint8 byte_count; -public: - powerpc_xer_register(); - void set(uint32 xer); - uint32 get() const; - void set_so(int v) { so = v; } - int get_so() const { return so; } - void set_ov(int v) { ov = v; so |= v; } - int get_ov() const { return ov; } - void set_ca(int v) { ca = v; } - int get_ca() const { return ca; } - void set_count(int v) { byte_count = v; } - int get_count() const { return byte_count; } -}; - -inline -powerpc_xer_register::powerpc_xer_register() - : so(0), ov(0), ca(0), byte_count(0) -{ } - -inline uint32 -powerpc_xer_register::get() const -{ - return (so << 31) | (ov << 30) | (ca << 29) | byte_count; -} - -inline void -powerpc_xer_register::set(uint32 xer) -{ - so = XER_SO_field::extract(xer); - ov = XER_OV_field::extract(xer); - ca = XER_CA_field::extract(xer); - byte_count = XER_COUNT_field::extract(xer); -} - - -/** - * Special CPU flags - **/ - -#include "cpu/spcflags.hpp" -typedef basic_spcflags powerpc_spcflags; - - -/** - * Floating point register - **/ - -union powerpc_fpr { - uint64 j; - double d; -}; - - -/** - * Vector Status and Control Register - **/ - -class powerpc_vscr -{ - uint32 vscr; -public: - powerpc_vscr() : vscr(0) { } - void set(uint32 v) { vscr = v; } - uint32 get() const { return vscr; } - uint32 get_nj() const { return vscr & VSCR_NJ_field::mask(); } - void set_nj(bool v) { VSCR_NJ_field::insert(vscr, v); } - uint32 get_sat() const { return vscr & VSCR_SAT_field::mask(); } - void set_sat(bool v) { VSCR_SAT_field::insert(vscr, v); } -}; - - -/** - * Vector register - **/ - -union powerpc_vr -{ - uint8 b[16]; - uint16 h[8]; - uint32 w[4]; - uint64 j[2]; - float f[4]; -}; - - -/** - * User Environment Architecture (UEA) Register Set - **/ - -struct powerpc_registers -{ - enum { - GPR_BASE = 0, - FPR_BASE = 32, - CR = 64, - FPSCR, - XER, - LR, CTR, - PC, - SP = GPR_BASE + 1 - }; - - enum { - SPR_XER = 1, - SPR_LR = 8, - SPR_CTR = 9, - SPR_SDR1 = 25, - SPR_PVR = 287, - SPR_VRSAVE = 256, - }; - - static inline int GPR(int r) { return GPR_BASE + r; } - static inline int FPR(int r) { return FPR_BASE + r; } - static void interrupt_copy(powerpc_registers &oregs, powerpc_registers const &iregs); - - uint32 gpr[32]; // General-Purpose Registers - powerpc_fpr fpr[32]; // Floating-Point Registers - powerpc_vr vr[32]; // Vector Registers - powerpc_cr_register cr; // Condition Register - powerpc_xer_register xer; // XER Register (SPR 1) - powerpc_vscr vscr; // Vector Status and Control Register - uint32 vrsave; // AltiVec Save Register - uint32 fpscr; // Floating-Point Status and Control Register - uint32 lr; // Link Register (SPR 8) - uint32 ctr; // Count Register (SPR 9) - uint32 pc; // Program Counter - powerpc_spcflags spcflags; // Special CPU flags -#if KPX_MAX_CPUS == 1 - uint32 reserve_valid; - uint32 reserve_addr; -#else - static uint32 reserve_valid; - static uint32 reserve_addr; - static uint32 reserve_data; -#endif -}; - -#endif /* PPC_REGISTERS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp deleted file mode 100644 index 6db1fa29..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-translate.cpp +++ /dev/null @@ -1,1589 +0,0 @@ -/* - * ppc-translate.cpp - PowerPC dynamic translation - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-instructions.hpp" -#include "cpu/ppc/ppc-operands.hpp" - -#if PPC_ENABLE_JIT -#include "cpu/jit/dyngen-exec.h" -#endif - -#ifdef SHEEPSHAVER -#include "cpu_emulation.h" -#endif - -#include - -#define DEBUG 1 -#include "debug.h" - -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif - -// Define to enable const branches optimization -#define FOLLOW_CONST_JUMPS 1 - -// FIXME: define ROM areas -static inline bool is_read_only_memory(uintptr addr) -{ -#ifdef SHEEPSHAVER - if ((addr - ROMBase) < ROM_AREA_SIZE) - return true; -#endif - return false; -} - -// Returns TRUE if we can directly generate a jump to the target block -// XXX mixing front-end and back-end conditions is not a very good idea... -static inline bool direct_chaining_possible(uint32 bpc, uint32 tpc) -{ -#ifndef DYNGEN_FAST_DISPATCH - return false; -#endif - return ((bpc ^ tpc) >> 12) == 0 || is_read_only_memory(tpc); -} - - -/** - * Basic block disassemblers - **/ - -#define TARGET_M68K 0 -#define TARGET_POWERPC 1 -#define TARGET_X86 2 -#define TARGET_AMD64 3 -#if defined(i386) || defined(__i386__) -#define TARGET_NATIVE TARGET_X86 -#endif -#if defined(x86_64) || defined(__x86_64__) -#define TARGET_NATIVE TARGET_AMD64 -#endif -#if defined(powerpc) || defined(__powerpc__) || defined(__ppc__) -#define TARGET_NATIVE TARGET_POWERPC -#endif - -#if PPC_ENABLE_JIT -static void disasm_block(int target, uint8 *start, uint32 length) -{ -#if ENABLE_MON - char disasm_str[200]; - sprintf(disasm_str, "%s $%x $%x", - target == TARGET_M68K ? "d68" : - target == TARGET_X86 ? "d86" : - target == TARGET_AMD64 ? "d8664" : - target == TARGET_POWERPC ? "d" : "x", - start, start + length - 1); - - char *arg[] = {"mon", -#ifdef SHEEPSHAVER - "-m", -#endif - "-r", disasm_str, NULL}; - mon(sizeof(arg)/sizeof(arg[0]) - 1, arg); -#endif -} - -static void disasm_translation(uint32 src_addr, uint32 src_len, - uint8* dst_addr, uint32 dst_len) -{ - printf("### Block at %08x translated to %p (%d bytes)\n", src_addr, dst_addr, dst_len); - printf("IN:\n"); - disasm_block(TARGET_POWERPC, vm_do_get_real_address(src_addr), src_len); - printf("OUT:\n"); -#ifdef TARGET_NATIVE - disasm_block(TARGET_NATIVE, dst_addr, dst_len); -#else - printf("unsupported disassembler for this archicture\n"); -#endif -} -#endif - - -/** - * DynGen dynamic code translation - **/ - -#if PPC_ENABLE_JIT -powerpc_cpu::block_info * -powerpc_cpu::compile_block(uint32 entry_point) -{ -#if DEBUG - bool disasm = false; -#else - const bool disasm = false; -#endif - -#if PPC_PROFILE_COMPILE_TIME - compile_count++; - clock_t start_time = clock(); -#endif - - powerpc_jit & dg = codegen; - codegen_context_t cg_context(dg); - cg_context.entry_point = entry_point; - again: - block_info *bi = my_block_cache.new_blockinfo(); - bi->init(entry_point); - bi->entry_point = dg.gen_start(entry_point); - - // Direct block chaining support variables - bool use_direct_block_chaining = false; - - int compile_status; - uint32 dpc = entry_point - 4; - uint32 min_pc, max_pc; - min_pc = max_pc = entry_point; - uint32 sync_pc = dpc; - uint32 sync_pc_offset = 0; - bool done_compile = false; - while (!done_compile) { - uint32 opcode = vm_read_memory_4(dpc += 4); - const instr_info_t *ii = decode(opcode); - if (ii->cflow & CFLOW_END_BLOCK) - done_compile = true; - - // Assume we can compile this opcode - compile_status = COMPILE_CODE_OK; - -#if PPC_FLIGHT_RECORDER - if (is_logging()) { - typedef void (*func_t)(dyngen_cpu_base, uint32, uint32); - func_t func = (func_t)nv_mem_fun((execute_pmf)&powerpc_cpu::do_record_step).ptr(); - dg.gen_invoke_CPU_im_im(func, dpc, opcode); - } -#endif - - union operands_t { - struct { - int size, sign; - int do_update; - int do_indexed; - } mem; - struct { - uint32 target; - } jmp; - }; - operands_t op; - - switch (ii->mnemo) { - case PPC_I(LBZ): // Load Byte and Zero - op.mem.size = 1; - op.mem.sign = 0; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LBZU): // Load Byte and Zero with Update - op.mem.size = 1; - op.mem.sign = 0; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LBZUX): // Load Byte and Zero with Update Indexed - op.mem.size = 1; - op.mem.sign = 0; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LBZX): // Load Byte and Zero Indexed - op.mem.size = 1; - op.mem.sign = 0; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LHA): // Load Half Word Algebraic - op.mem.size = 2; - op.mem.sign = 1; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LHAU): // Load Half Word Algebraic with Update - op.mem.size = 2; - op.mem.sign = 1; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LHAUX): // Load Half Word Algebraic with Update Indexed - op.mem.size = 2; - op.mem.sign = 1; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LHAX): // Load Half Word Algebraic Indexed - op.mem.size = 2; - op.mem.sign = 1; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LHZ): // Load Half Word and Zero - op.mem.size = 2; - op.mem.sign = 0; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LHZU): // Load Half Word and Zero with Update - op.mem.size = 2; - op.mem.sign = 0; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LHZUX): // Load Half Word and Zero with Update Indexed - op.mem.size = 2; - op.mem.sign = 0; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LHZX): // Load Half Word and Zero Indexed - op.mem.size = 2; - op.mem.sign = 0; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LWZ): // Load Word and Zero - op.mem.size = 4; - op.mem.sign = 0; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LWZU): // Load Word and Zero with Update - op.mem.size = 4; - op.mem.sign = 0; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_load; - case PPC_I(LWZUX): // Load Word and Zero with Update Indexed - op.mem.size = 4; - op.mem.sign = 0; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_load; - case PPC_I(LWZX): // Load Word and Zero Indexed - op.mem.size = 4; - op.mem.sign = 0; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_load; - { - do_load: - // Extract RZ operand - const int rA = rA_field::extract(opcode); - if (rA == 0 && !op.mem.do_update) - dg.gen_mov_32_T1_im(0); - else - dg.gen_load_T1_GPR(rA); - - // Extract index operand - if (op.mem.do_indexed) - dg.gen_load_T2_GPR(rB_field::extract(opcode)); - - switch (op.mem.size) { - case 1: - if (op.mem.do_indexed) - dg.gen_load_u8_T0_T1_T2(); - else - dg.gen_load_u8_T0_T1_im(operand_D::get(this, opcode)); - break; - case 2: - if (op.mem.do_indexed) { - if (op.mem.sign) - dg.gen_load_s16_T0_T1_T2(); - else - dg.gen_load_u16_T0_T1_T2(); - } - else { - const int32 offset = operand_D::get(this, opcode); - if (op.mem.sign) - dg.gen_load_s16_T0_T1_im(offset); - else - dg.gen_load_u16_T0_T1_im(offset); - } - break; - case 4: - if (op.mem.do_indexed) { - dg.gen_load_u32_T0_T1_T2(); - } - else { - const int32 offset = operand_D::get(this, opcode); - dg.gen_load_u32_T0_T1_im(offset); - } - break; - } - - // Commit result - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - - // Update RA - if (op.mem.do_update) { - if (op.mem.do_indexed) - dg.gen_add_32_T1_T2(); - else - dg.gen_add_32_T1_im(operand_D::get(this, opcode)); - dg.gen_store_T1_GPR(rA); - } - break; - } - case PPC_I(STB): // Store Byte - op.mem.size = 1; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_store; - case PPC_I(STBU): // Store Byte with Update - op.mem.size = 1; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_store; - case PPC_I(STBUX): // Store Byte with Update Indexed - op.mem.size = 1; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_store; - case PPC_I(STBX): // Store Byte Indexed - op.mem.size = 1; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_store; - case PPC_I(STH): // Store Half Word - op.mem.size = 2; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_store; - case PPC_I(STHU): // Store Half Word with Update - op.mem.size = 2; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_store; - case PPC_I(STHUX): // Store Half Word with Update Indexed - op.mem.size = 2; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_store; - case PPC_I(STHX): // Store Half Word Indexed - op.mem.size = 2; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_store; - case PPC_I(STW): // Store Word - op.mem.size = 4; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_store; - case PPC_I(STWU): // Store Word with Update - op.mem.size = 4; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_store; - case PPC_I(STWUX): // Store Word with Update Indexed - op.mem.size = 4; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_store; - case PPC_I(STWX): // Store Word Indexed - op.mem.size = 4; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_store; - { - do_store: - // Extract RZ operand - const int rA = rA_field::extract(opcode); - if (rA == 0 && !op.mem.do_update) - dg.gen_mov_32_T1_im(0); - else - dg.gen_load_T1_GPR(rA); - - // Extract index operand - if (op.mem.do_indexed) - dg.gen_load_T2_GPR(rB_field::extract(opcode)); - - // Load register to commit to memory - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - - switch (op.mem.size) { - case 1: - if (op.mem.do_indexed) - dg.gen_store_8_T0_T1_T2(); - else - dg.gen_store_8_T0_T1_im(operand_D::get(this, opcode)); - break; - case 2: - if (op.mem.do_indexed) - dg.gen_store_16_T0_T1_T2(); - else - dg.gen_store_16_T0_T1_im(operand_D::get(this, opcode)); - break; - case 4: - if (op.mem.do_indexed) - dg.gen_store_32_T0_T1_T2(); - else - dg.gen_store_32_T0_T1_im(operand_D::get(this, opcode)); - break; - } - - // Update RA - if (op.mem.do_update) { - if (op.mem.do_indexed) - dg.gen_add_32_T1_T2(); - else - dg.gen_add_32_T1_im(operand_D::get(this, opcode)); - dg.gen_store_T1_GPR(rA); - } - break; - } - case PPC_I(LMW): // Load Multiple Word - case PPC_I(STMW): // Store Multiple Word - { - const int rA = rA_field::extract(opcode); - if (rA == 0) - dg.gen_mov_32_T0_im(operand_D::get(this, opcode)); - else { - dg.gen_load_T0_GPR(rA); - dg.gen_add_32_T0_im(operand_D::get(this, opcode)); - } - switch (ii->mnemo) { - case PPC_I(LMW): dg.gen_lmw_T0(rD_field::extract(opcode)); break; - case PPC_I(STMW): dg.gen_stmw_T0(rS_field::extract(opcode)); break; - } - break; - } -#if KPX_MAX_CPUS == 1 - case PPC_I(STWCX): // Store Word Conditional Indexed - case PPC_I(LWARX): // Load Word and Reserve Indexed - { - const int rA = rA_field::extract(opcode); - const int rB = rB_field::extract(opcode); - if (rA == 0) - dg.gen_load_T1_GPR(rB); - else { - dg.gen_load_T1_GPR(rA); - dg.gen_load_T2_GPR(rB); - dg.gen_add_32_T1_T2(); - } - switch (ii->mnemo) { - case PPC_I(LWARX): - dg.gen_lwarx_T0_T1(); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - case PPC_I(STWCX): - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_stwcx_T0_T1(); - break; - } - break; - } -#endif - case PPC_I(BC): // Branch Conditional - { - const int bo = BO_field::extract(opcode); -#if FOLLOW_CONST_JUMPS - if (!BO_CONDITIONAL_BRANCH(bo) && !BO_DECREMENT_CTR(bo)) { - if (LK_field::test(opcode)) { - const uint32 npc = dpc + 4; - dg.gen_store_im_LR(npc); - } - if (AA_field::test(opcode)) - dpc = 0; - op.jmp.target = ((dpc + operand_BD::get(this, opcode)) & -4); - goto do_const_jump; - } -#endif - const uint32 tpc = ((AA_field::test(opcode) ? 0 : dpc) + operand_BD::get(this, opcode)) & -4; - const uint32 npc = dpc + 4; -#if DYNGEN_DIRECT_BLOCK_CHAINING - // Use direct block chaining for in-page jumps or jumps to ROM area - if (direct_chaining_possible(bi->pc, tpc)) { - use_direct_block_chaining = true; - bi->li[0].jmp_pc = tpc; - // Make sure it's a conditional branch - if (BO_CONDITIONAL_BRANCH(bo) || BO_DECREMENT_CTR(bo)) - bi->li[1].jmp_pc = npc; - } -#endif - - if (LK_field::test(opcode)) - dg.gen_store_im_LR(npc); - - dg.gen_bc(bo, BI_field::extract(opcode), tpc, npc, use_direct_block_chaining); - break; - } - case PPC_I(BCCTR): // Branch Conditional to Count Register - dg.gen_load_T0_CTR_aligned(); - goto do_branch; - case PPC_I(BCLR): // Branch Conditional to Link Register - dg.gen_load_T0_LR_aligned(); - goto do_branch; - { - do_branch: - const int bo = BO_field::extract(opcode); - const int bi = BI_field::extract(opcode); - - const uint32 npc = dpc + 4; - if (LK_field::test(opcode)) - dg.gen_store_im_LR(npc); - - dg.gen_bc(bo, bi, (uint32)-1, npc, use_direct_block_chaining); - break; - } - case PPC_I(B): // Branch - goto do_call; - { -#if FOLLOW_CONST_JUMPS - do_const_jump: - sync_pc = dpc = op.jmp.target - 4; - sync_pc_offset = 0; - if (dpc < min_pc) - min_pc = dpc; - else if (dpc > max_pc) - max_pc = dpc; - done_compile = false; - break; -#endif - do_call: - uint32 tpc = AA_field::test(opcode) ? 0 : dpc; - tpc = (tpc + operand_LI::get(this, opcode)) & -4; - - const uint32 npc = dpc + 4; - if (LK_field::test(opcode)) - dg.gen_store_im_LR(npc); -#if FOLLOW_CONST_JUMPS - else { - op.jmp.target = tpc; - goto do_const_jump; - } -#endif - -#if DYNGEN_DIRECT_BLOCK_CHAINING - // Use direct block chaining, addresses will be resolved at execution - if (direct_chaining_possible(bi->pc, tpc)) { - use_direct_block_chaining = true; - bi->li[0].jmp_pc = tpc; - } -#endif - - // BO field is built so that we always branch to pc - dg.gen_bc(BO_MAKE(0,0,0,0), 0, tpc, 0, use_direct_block_chaining); - break; - } - case PPC_I(CMP): // Compare - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - dg.gen_compare_T0_T1(crfD_field::extract(opcode)); - break; - } - case PPC_I(CMPI): // Compare Immediate - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_compare_T0_im(crfD_field::extract(opcode), operand_SIMM::get(this, opcode)); - break; - } - case PPC_I(CMPL): // Compare Logical - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - dg.gen_compare_logical_T0_T1(crfD_field::extract(opcode)); - break; - } - case PPC_I(CMPLI): // Compare Logical Immediate - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_compare_logical_T0_im(crfD_field::extract(opcode), operand_UIMM::get(this, opcode)); - break; - } - case PPC_I(CRAND): // Condition Register AND - case PPC_I(CRANDC): // Condition Register AND with Complement - case PPC_I(CREQV): // Condition Register Equivalent - case PPC_I(CRNAND): // Condition Register NAND - case PPC_I(CRNOR): // Condition Register NOR - case PPC_I(CROR): // Condition Register OR - case PPC_I(CRORC): // Condition Register OR with Complement - case PPC_I(CRXOR): // Condition Register XOR - { - dg.gen_load_T0_crb(crbA_field::extract(opcode)); - dg.gen_load_T1_crb(crbB_field::extract(opcode)); - switch (ii->mnemo) { - case PPC_I(CRAND): dg.gen_and_32_T0_T1(); break; - case PPC_I(CRANDC): dg.gen_andc_32_T0_T1(); break; - case PPC_I(CREQV): dg.gen_eqv_32_T0_T1(); break; - case PPC_I(CRNAND): dg.gen_nand_32_T0_T1(); break; - case PPC_I(CRNOR): dg.gen_nor_32_T0_T1(); break; - case PPC_I(CROR): dg.gen_or_32_T0_T1(); break; - case PPC_I(CRORC): dg.gen_orc_32_T0_T1(); break; - case PPC_I(CRXOR): dg.gen_xor_32_T0_T1(); break; - default: abort(); - } - dg.gen_store_T0_crb(crbD_field::extract(opcode)); - break; - } - case PPC_I(AND): // AND - case PPC_I(ANDC): // AND with Complement - case PPC_I(EQV): // Equivalent - case PPC_I(NAND): // NAND - case PPC_I(NOR): // NOR - case PPC_I(ORC): // ORC - case PPC_I(XOR): // XOR - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - switch (ii->mnemo) { - case PPC_I(AND): dg.gen_and_32_T0_T1(); break; - case PPC_I(ANDC): dg.gen_andc_32_T0_T1(); break; - case PPC_I(EQV): dg.gen_eqv_32_T0_T1(); break; - case PPC_I(NAND): dg.gen_nand_32_T0_T1(); break; - case PPC_I(NOR): dg.gen_nor_32_T0_T1(); break; - case PPC_I(ORC): dg.gen_orc_32_T0_T1(); break; - case PPC_I(XOR): dg.gen_xor_32_T0_T1(); break; - default: abort(); - } - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(OR): // OR - { - const int rS = rS_field::extract(opcode); - const int rB = rB_field::extract(opcode); - const int rA = rA_field::extract(opcode); - dg.gen_load_T0_GPR(rS); - if (rS != rB) { // Not MR case - dg.gen_load_T1_GPR(rB); - dg.gen_or_32_T0_T1(); - } - dg.gen_store_T0_GPR(rA); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(ORI): // OR Immediate - { - const int rA = rA_field::extract(opcode); - const int rS = rS_field::extract(opcode); - const uint32 val = operand_UIMM::get(this, opcode); - if (val == 0) { - if (rA != rS) { // Skip NOP, handle register move - dg.gen_load_T0_GPR(rS); - dg.gen_store_T0_GPR(rA); - } - } - else { - dg.gen_load_T0_GPR(rS); - dg.gen_or_32_T0_im(val); - dg.gen_store_T0_GPR(rA); - } - break; - } - case PPC_I(XORI): // XOR Immediate - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_xor_32_T0_im(operand_UIMM::get(this, opcode)); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - break; - } - case PPC_I(ORIS): // OR Immediate Shifted - case PPC_I(XORIS): // XOR Immediate Shifted - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - uint32 val = operand_UIMM_shifted::get(this, opcode); - switch (ii->mnemo) { - case PPC_I(ORIS): dg.gen_or_32_T0_im(val); break; - case PPC_I(XORIS): dg.gen_xor_32_T0_im(val); break; - default: abort(); - } - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - break; - } - case PPC_I(ANDI): // AND Immediate - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_and_32_T0_im(operand_UIMM::get(this, opcode)); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(ANDIS): // AND Immediate Shifted - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_and_32_T0_im(operand_UIMM_shifted::get(this, opcode)); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(EXTSB): // Extend Sign Byte - case PPC_I(EXTSH): // Extend Sign Half Word - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - switch (ii->mnemo) { - case PPC_I(EXTSB): dg.gen_se_8_32_T0(); break; - case PPC_I(EXTSH): dg.gen_se_16_32_T0(); break; - default: abort(); - } - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(NEG): // Negate - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - if (OE_field::test(opcode)) - dg.gen_nego_T0(); - else - dg.gen_neg_32_T0(); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(MFCR): // Move from Condition Register - { - dg.gen_load_T0_CR(); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(MFSPR): // Move from Special-Purpose Register - { - const int spr = operand_SPR::get(this, opcode); - switch (spr) { - case powerpc_registers::SPR_XER: - dg.gen_load_T0_XER(); - break; - case powerpc_registers::SPR_LR: - dg.gen_load_T0_LR(); - break; - case powerpc_registers::SPR_CTR: - dg.gen_load_T0_CTR(); - break; - case powerpc_registers::SPR_VRSAVE: - dg.gen_load_T0_VRSAVE(); - break; -#ifdef SHEEPSHAVER - case powerpc_registers::SPR_SDR1: - dg.gen_mov_32_T0_im(0xdead001f); - break; - case powerpc_registers::SPR_PVR: { - extern uint32 PVR; - dg.gen_mov_32_T0_im(PVR); - break; - } - default: - dg.gen_mov_32_T0_im(0); - break; -#else - default: goto do_generic; -#endif - } - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(MTSPR): // Move to Special-Purpose Register - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - const int spr = operand_SPR::get(this, opcode); - switch (spr) { - case powerpc_registers::SPR_XER: - dg.gen_store_T0_XER(); - break; - case powerpc_registers::SPR_LR: - dg.gen_store_T0_LR(); - break; - case powerpc_registers::SPR_CTR: - dg.gen_store_T0_CTR(); - break; - case powerpc_registers::SPR_VRSAVE: - dg.gen_store_T0_VRSAVE(); - break; -#ifndef SHEEPSHAVER - default: goto do_generic; -#endif - } - break; - } - case PPC_I(ADD): // Add - case PPC_I(ADDC): // Add Carrying - case PPC_I(ADDE): // Add Extended - case PPC_I(SUBF): // Subtract From - case PPC_I(SUBFC): // Subtract from Carrying - case PPC_I(SUBFE): // Subtract from Extended - case PPC_I(MULLW): // Multiply Low Word - case PPC_I(DIVW): // Divide Word - case PPC_I(DIVWU): // Divide Word Unsigned - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - if (OE_field::test(opcode)) { - switch (ii->mnemo) { - case PPC_I(ADD): dg.gen_addo_T0_T1(); break; - case PPC_I(ADDC): dg.gen_addco_T0_T1(); break; - case PPC_I(ADDE): dg.gen_addeo_T0_T1(); break; - case PPC_I(SUBF): dg.gen_subfo_T0_T1(); break; - case PPC_I(SUBFC): dg.gen_subfco_T0_T1(); break; - case PPC_I(SUBFE): dg.gen_subfeo_T0_T1(); break; - case PPC_I(MULLW): dg.gen_mullwo_T0_T1(); break; - case PPC_I(DIVW): dg.gen_divwo_T0_T1(); break; - case PPC_I(DIVWU): dg.gen_divwuo_T0_T1(); break; - default: abort(); - } - } - else { - switch (ii->mnemo) { - case PPC_I(ADD): dg.gen_add_32_T0_T1(); break; - case PPC_I(ADDC): dg.gen_addc_T0_T1(); break; - case PPC_I(ADDE): dg.gen_adde_T0_T1(); break; - case PPC_I(SUBF): dg.gen_subf_T0_T1(); break; - case PPC_I(SUBFC): dg.gen_subfc_T0_T1(); break; - case PPC_I(SUBFE): dg.gen_subfe_T0_T1(); break; - case PPC_I(MULLW): dg.gen_umul_32_T0_T1(); break; - case PPC_I(DIVW): dg.gen_divw_T0_T1(); break; - case PPC_I(DIVWU): dg.gen_divwu_T0_T1(); break; - default: abort(); - } - } - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(ADDIC): // Add Immediate Carrying - case PPC_I(ADDIC_): // Add Immediate Carrying and Record - case PPC_I(SUBFIC): // Subtract from Immediate Carrying - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - const uint32 val = operand_SIMM::get(this, opcode); - switch (ii->mnemo) { - case PPC_I(ADDIC): - dg.gen_addc_T0_im(val); - break; - case PPC_I(ADDIC_): - dg.gen_addc_T0_im(val); - dg.gen_record_cr0_T0(); - break; - case PPC_I(SUBFIC): - dg.gen_subfc_T0_im(val); - break; - defautl: - abort(); - } - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(ADDME): // Add to Minus One Extended - case PPC_I(ADDZE): // Add to Zero Extended - case PPC_I(SUBFME): // Subtract from Minus One Extended - case PPC_I(SUBFZE): // Subtract from Zero Extended - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - if (OE_field::test(opcode)) { - switch (ii->mnemo) { - case PPC_I(ADDME): dg.gen_addmeo_T0(); break; - case PPC_I(ADDZE): dg.gen_addzeo_T0(); break; - case PPC_I(SUBFME): dg.gen_subfmeo_T0(); break; - case PPC_I(SUBFZE): dg.gen_subfzeo_T0(); break; - default: abort(); - } - } - else { - switch (ii->mnemo) { - case PPC_I(ADDME): dg.gen_addme_T0(); break; - case PPC_I(ADDZE): dg.gen_addze_T0(); break; - case PPC_I(SUBFME): dg.gen_subfme_T0(); break; - case PPC_I(SUBFZE): dg.gen_subfze_T0(); break; - default: abort(); - } - } - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(ADDI): // Add Immediate - { - const int rA = rA_field::extract(opcode); - const int rD = rD_field::extract(opcode); - if (rA == 0) // li rD,value - dg.gen_mov_32_T0_im(operand_SIMM::get(this, opcode)); - else { - dg.gen_load_T0_GPR(rA); - dg.gen_add_32_T0_im(operand_SIMM::get(this, opcode)); - } - dg.gen_store_T0_GPR(rD); - break; - } - case PPC_I(ADDIS): // Add Immediate Shifted - { - const int rA = rA_field::extract(opcode); - const int rD = rD_field::extract(opcode); - if (rA == 0) // lis rD,value - dg.gen_mov_32_T0_im(operand_SIMM_shifted::get(this, opcode)); - else { - dg.gen_load_T0_GPR(rA); - dg.gen_add_32_T0_im(operand_SIMM_shifted::get(this, opcode)); - } - dg.gen_store_T0_GPR(rD); - break; - } - case PPC_I(RLWIMI): // Rotate Left Word Immediate then Mask Insert - { - const int rA = rA_field::extract(opcode); - const int rS = rS_field::extract(opcode); - const int SH = SH_field::extract(opcode); - const int MB = MB_field::extract(opcode); - const int ME = ME_field::extract(opcode); - dg.gen_load_T0_GPR(rA); - dg.gen_load_T1_GPR(rS); - const uint32 m = mask_operand::compute(MB, ME); - dg.gen_rlwimi_T0_T1(SH, m); - dg.gen_store_T0_GPR(rA); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(RLWINM): // Rotate Left Word Immediate then AND with Mask - { - const int rS = rS_field::extract(opcode); - const int rA = rA_field::extract(opcode); - const int SH = SH_field::extract(opcode); - const int MB = MB_field::extract(opcode); - const int ME = ME_field::extract(opcode); - const uint32 m = mask_operand::compute(MB, ME); - dg.gen_load_T0_GPR(rS); - if (MB == 0) { - if (ME == 31) { - // rotlwi rA,rS,SH - if (SH > 0) - dg.gen_rol_32_T0_im(SH); - } - else if (ME == (31 - SH)) { - // slwi rA,rS,SH - dg.gen_lsl_32_T0_im(SH); - } - else if (SH == 0) { - // andi rA,rS,MASK(0,ME) - dg.gen_and_32_T0_im(m); - } - else goto do_generic_rlwinm; - } - else if (ME == 31) { - if (SH == (32 - MB)) { - // srwi rA,rS,SH - dg.gen_lsr_32_T0_im(MB); - } - else if (SH == 0) { - // andi rA,rS,MASK(MB,31) - dg.gen_and_32_T0_im(m); - } - else goto do_generic_rlwinm; - } - else { - // rlwinm rA,rS,SH,MB,ME - do_generic_rlwinm: - dg.gen_rlwinm_T0_T1(SH, m); - } - dg.gen_store_T0_GPR(rA); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(RLWNM): // Rotate Left Word then AND with Mask - { - const int rS = rS_field::extract(opcode); - const int rB = rB_field::extract(opcode); - const int rA = rA_field::extract(opcode); - const int MB = MB_field::extract(opcode); - const int ME = ME_field::extract(opcode); - const uint32 m = mask_operand::compute(MB, ME); - dg.gen_load_T0_GPR(rS); - dg.gen_load_T1_GPR(rB); - if (MB == 0 && ME == 31) - dg.gen_rol_32_T0_T1(); - else - dg.gen_rlwnm_T0_T1(m); - dg.gen_store_T0_GPR(rA); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(CNTLZW): // Count Leading Zeros Word - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_cntlzw_32_T0(); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(SLW): // Shift Left Word - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - dg.gen_slw_T0_T1(); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(SRW): // Shift Right Word - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - dg.gen_srw_T0_T1(); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(SRAW): // Shift Right Algebraic Word - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - dg.gen_sraw_T0_T1(); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(SRAWI): // Shift Right Algebraic Word Immediate - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_sraw_T0_im(SH_field::extract(opcode)); - dg.gen_store_T0_GPR(rA_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(MULHW): // Multiply High Word - case PPC_I(MULHWU): // Multiply High Word Unsigned - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_load_T1_GPR(rB_field::extract(opcode)); - if (ii->mnemo == PPC_I(MULHW)) - dg.gen_mulhw_T0_T1(); - else - dg.gen_mulhwu_T0_T1(); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr0_T0(); - break; - } - case PPC_I(MULLI): // Multiply Low Immediate - { - dg.gen_load_T0_GPR(rA_field::extract(opcode)); - dg.gen_mulli_T0_im(operand_SIMM::get(this, opcode)); - dg.gen_store_T0_GPR(rD_field::extract(opcode)); - break; - } - case PPC_I(DCBZ): // Data Cache Block Clear to Zero - { - const int rA = rA_field::extract(opcode); - const int rB = rB_field::extract(opcode); - if (rA == 0) - dg.gen_load_T0_GPR(rB); - else { - dg.gen_load_T0_GPR(rA); - dg.gen_load_T1_GPR(rB); - dg.gen_add_32_T0_T1(); - } - dg.gen_dcbz_T0(); - break; - } - case PPC_I(DCBA): // Data Cache Block Allocate - case PPC_I(DCBF): // Data Cache Block Flush - case PPC_I(DCBI): // Data Cache Block Invalidate - case PPC_I(DCBST): // Data Cache Block Store - case PPC_I(DCBT): // Data Cache Block Touch - case PPC_I(DCBTST): // Data Cache Block Touch for Store - case PPC_I(ECIWX): // External Control In Word Indexed - case PPC_I(ECOWX): // External Control Out Word Indexed - case PPC_I(EIEIO): // Enforce In-Order Execution of I/O - case PPC_I(SYNC): // Synchronize - { - break; - } - case PPC_I(ISYNC): // Instruction synchronize - { - typedef void (*func_t)(dyngen_cpu_base); - func_t func = (func_t)nv_mem_fun(&powerpc_cpu::execute_invalidate_cache_range).ptr(); - dg.gen_invoke_CPU(func); - break; - } - case PPC_I(MTCRF): // Move to Condition Register Fields - { - dg.gen_load_T0_GPR(rS_field::extract(opcode)); - dg.gen_mtcrf_T0_im(field2mask[CRM_field::extract(opcode)]); - break; - } - case PPC_I(MCRF): // Move Condition Register Field - { - dg.gen_load_T0_crf(crfS_field::extract(opcode)); - dg.gen_store_T0_crf(crfD_field::extract(opcode)); - break; - } - case PPC_I(LFD): // Load Floating-Point Double - op.mem.size = 8; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_fp_load;; - case PPC_I(LFDU): // Load Floating-Point Double with Update - op.mem.size = 8; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_fp_load; - case PPC_I(LFDUX): // Load Floating-Point Double with Update Indexed - op.mem.size = 8; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_fp_load; - case PPC_I(LFDX): // Load Floating-Point Double Indexed - op.mem.size = 8; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_fp_load; - case PPC_I(LFS): // Load Floating-Point Single - op.mem.size = 4; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_fp_load; - case PPC_I(LFSU): // Load Floating-Point Single with Update - op.mem.size = 4; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_fp_load; - case PPC_I(LFSUX): // Load Floating-Point Single with Update Indexed - op.mem.size = 4; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_fp_load; - case PPC_I(LFSX): // Load Floating-Point Single Indexed - op.mem.size = 4; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_fp_load; - { - do_fp_load: - // Extract RZ operand - const int rA = rA_field::extract(opcode); - if (rA == 0 && !op.mem.do_update) - dg.gen_mov_32_T1_im(0); - else - dg.gen_load_T1_GPR(rA); - - // Extract index operand - if (op.mem.do_indexed) - dg.gen_load_T2_GPR(rB_field::extract(opcode)); - - // Load floating point data - if (op.mem.size == 8) { - if (op.mem.do_indexed) - dg.gen_load_double_FD_T1_T2(); - else - dg.gen_load_double_FD_T1_im(operand_D::get(this, opcode)); - } - else { - if (op.mem.do_indexed) - dg.gen_load_single_FD_T1_T2(); - else - dg.gen_load_single_FD_T1_im(operand_D::get(this, opcode)); - } - - // Commit result - dg.gen_store_FD_FPR(frD_field::extract(opcode)); - - // Update RA - if (op.mem.do_update) { - if (op.mem.do_indexed) - dg.gen_add_32_T1_T2(); - else - dg.gen_add_32_T1_im(operand_D::get(this, opcode)); - dg.gen_store_T1_GPR(rA); - } - break; - } - case PPC_I(STFD): // Store Floating-Point Double - op.mem.size = 8; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_fp_store; - case PPC_I(STFDU): // Store Floating-Point Double with Update - op.mem.size = 8; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_fp_store; - case PPC_I(STFDUX): // Store Floating-Point Double with Update Indexed - op.mem.size = 8; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_fp_store; - case PPC_I(STFDX): // Store Floating-Point Double Indexed - op.mem.size = 8; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_fp_store; - case PPC_I(STFS): // Store Floating-Point Single - op.mem.size = 4; - op.mem.do_update = 0; - op.mem.do_indexed = 0; - goto do_fp_store; - case PPC_I(STFSU): // Store Floating-Point Single with Update - op.mem.size = 4; - op.mem.do_update = 1; - op.mem.do_indexed = 0; - goto do_fp_store; - case PPC_I(STFSUX): // Store Floating-Point Single with Update Indexed - op.mem.size = 4; - op.mem.do_update = 1; - op.mem.do_indexed = 1; - goto do_fp_store; - case PPC_I(STFSX): // Store Floating-Point Single Indexed - op.mem.size = 4; - op.mem.do_update = 0; - op.mem.do_indexed = 1; - goto do_fp_store; - { - do_fp_store: - // Extract RZ operand - const int rA = rA_field::extract(opcode); - if (rA == 0 && !op.mem.do_update) - dg.gen_mov_32_T1_im(0); - else - dg.gen_load_T1_GPR(rA); - - // Extract index operand - if (op.mem.do_indexed) - dg.gen_load_T2_GPR(rB_field::extract(opcode)); - - // Load register to commit to memory - dg.gen_load_F0_FPR(frS_field::extract(opcode)); - - // Store floating point data - if (op.mem.size == 8) { - if (op.mem.do_indexed) - dg.gen_store_double_F0_T1_T2(); - else - dg.gen_store_double_F0_T1_im(operand_D::get(this, opcode)); - } - else { - if (op.mem.do_indexed) - dg.gen_store_single_F0_T1_T2(); - else - dg.gen_store_single_F0_T1_im(operand_D::get(this, opcode)); - } - - // Update RA - if (op.mem.do_update) { - if (op.mem.do_indexed) - dg.gen_add_32_T1_T2(); - else - dg.gen_add_32_T1_im(operand_D::get(this, opcode)); - dg.gen_store_T1_GPR(rA); - } - break; - } -#if PPC_ENABLE_FPU_EXCEPTIONS == 0 - case PPC_I(FABS): // Floating Absolute Value - case PPC_I(FNABS): // Floating Negative Absolute Value - case PPC_I(FNEG): // Floating Negate - case PPC_I(FMR): // Floating Move Register - { - dg.gen_load_F0_FPR(frB_field::extract(opcode)); - switch (ii->mnemo) { - case PPC_I(FABS): dg.gen_fabs_FD_F0(); break; - case PPC_I(FNABS): dg.gen_fnabs_FD_F0(); break; - case PPC_I(FNEG): dg.gen_fneg_FD_F0(); break; - case PPC_I(FMR): dg.gen_fmov_FD_F0(); break; - } - dg.gen_store_FD_FPR(frD_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr1(); - break; - } - case PPC_I(FADD): // Floating Add (Double-Precision) - case PPC_I(FSUB): // Floating Subtract (Double-Precision) - case PPC_I(FMUL): // Floating Multiply (Double-Precision) - case PPC_I(FDIV): // Floating Divide (Double-Precision) - case PPC_I(FADDS): // Floating Add (Single-Precision) - case PPC_I(FSUBS): // Floating Subtract (Single-Precision) - case PPC_I(FMULS): // Floating Multiply (Single-Precision) - case PPC_I(FDIVS): // Floating Divide (Single-Precision) - { - dg.gen_load_F0_FPR(frA_field::extract(opcode)); - if (ii->mnemo == PPC_I(FMUL) || ii->mnemo == PPC_I(FMULS)) - dg.gen_load_F1_FPR(frC_field::extract(opcode)); - else - dg.gen_load_F1_FPR(frB_field::extract(opcode)); - switch (ii->mnemo) { - case PPC_I(FADD): dg.gen_fadd_FD_F0_F1(); break; - case PPC_I(FSUB): dg.gen_fsub_FD_F0_F1(); break; - case PPC_I(FMUL): dg.gen_fmul_FD_F0_F1(); break; - case PPC_I(FDIV): dg.gen_fdiv_FD_F0_F1(); break; - case PPC_I(FADDS): dg.gen_fadds_FD_F0_F1(); break; - case PPC_I(FSUBS): dg.gen_fsubs_FD_F0_F1(); break; - case PPC_I(FMULS): dg.gen_fmuls_FD_F0_F1(); break; - case PPC_I(FDIVS): dg.gen_fdivs_FD_F0_F1(); break; - } - dg.gen_store_FD_FPR(frD_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr1(); - break; - } - case PPC_I(FMADD): // Floating Multiply-Add (Double-Precision) - case PPC_I(FMSUB): // Floating Multiply-Subtract (Double-Precision) - case PPC_I(FNMADD): // Floating Negative Multiply-Add (Double-Precision) - case PPC_I(FNMSUB): // Floating Negative Multiply-Subract (Double-Precision) - case PPC_I(FMADDS): // Floating Multiply-Add (Single-Precision) - case PPC_I(FMSUBS): // Floating Multiply-Subtract (Single-Precision) - case PPC_I(FNMADDS): // Floating Negative Multiply-Add (Single-Precision) - case PPC_I(FNMSUBS): // Floating Negative Multiply-Subract (Single-Precision) - { - dg.gen_load_F0_FPR(frA_field::extract(opcode)); - dg.gen_load_F1_FPR(frC_field::extract(opcode)); - dg.gen_load_F2_FPR(frB_field::extract(opcode)); - switch (ii->mnemo) { - case PPC_I(FMADD): dg.gen_fmadd_FD_F0_F1_F2(); break; - case PPC_I(FMSUB): dg.gen_fmsub_FD_F0_F1_F2(); break; - case PPC_I(FNMADD): dg.gen_fnmadd_FD_F0_F1_F2(); break; - case PPC_I(FNMSUB): dg.gen_fnmsub_FD_F0_F1_F2(); break; - case PPC_I(FMADDS): dg.gen_fmadds_FD_F0_F1_F2(); break; - case PPC_I(FMSUBS): dg.gen_fmsubs_FD_F0_F1_F2(); break; - case PPC_I(FNMADDS): dg.gen_fnmadds_FD_F0_F1_F2(); break; - case PPC_I(FNMSUBS): dg.gen_fnmsubs_FD_F0_F1_F2(); break; - } - dg.gen_store_FD_FPR(frD_field::extract(opcode)); - if (Rc_field::test(opcode)) - dg.gen_record_cr1(); - break; - } -#endif - case PPC_I(LVEWX): - case PPC_I(LVX): - case PPC_I(LVXL): - case PPC_I(STVEWX): - case PPC_I(STVX): - case PPC_I(STVXL): - assert(vD_field::mask() == vS_field::mask()); - assert(vA_field::mask() == rA_field::mask()); - assert(vB_field::mask() == rB_field::mask()); - // fall-through - case PPC_I(VCMPEQFP): - case PPC_I(VCMPEQUB): - case PPC_I(VCMPEQUH): - case PPC_I(VCMPEQUW): - case PPC_I(VCMPGEFP): - case PPC_I(VCMPGTFP): - case PPC_I(VCMPGTSB): - case PPC_I(VCMPGTSH): - case PPC_I(VCMPGTSW): - { - const int vD = vD_field::extract(opcode); - const int vA = vA_field::extract(opcode); - const int vB = vB_field::extract(opcode); - if (!dg.gen_vector_compare(ii->mnemo, vD, vA, vB, vRc_field::test(opcode))) - goto do_generic; - break; - } - case PPC_I(VADDFP): - case PPC_I(VADDUBM): - case PPC_I(VADDUHM): - case PPC_I(VADDUWM): - case PPC_I(VAND): - case PPC_I(VANDC): - case PPC_I(VAVGUB): - case PPC_I(VAVGUH): - case PPC_I(VMAXSH): - case PPC_I(VMAXUB): - case PPC_I(VMINSH): - case PPC_I(VMINUB): - case PPC_I(VNOR): - case PPC_I(VOR): - case PPC_I(VSUBFP): - case PPC_I(VSUBUBM): - case PPC_I(VSUBUHM): - case PPC_I(VSUBUWM): - case PPC_I(VXOR): - case PPC_I(VREFP): - case PPC_I(VRSQRTEFP): - { - const int vD = vD_field::extract(opcode); - const int vA = vA_field::extract(opcode); - const int vB = vB_field::extract(opcode); - if (!dg.gen_vector_2(ii->mnemo, vD, vA, vB)) - goto do_generic; - break; - } - case PPC_I(VSEL): - case PPC_I(VPERM): - case PPC_I(VMADDFP): - case PPC_I(VNMSUBFP): - { - const int vD = vD_field::extract(opcode); - const int vA = vA_field::extract(opcode); - const int vB = vB_field::extract(opcode); - const int vC = vC_field::extract(opcode); - if (!dg.gen_vector_3(ii->mnemo, vD, vA, vB, vC)) - goto do_generic; - break; - } - case PPC_I(VSLDOI): - { - const int vD = vD_field::extract(opcode); - const int vA = vA_field::extract(opcode); - const int vB = vB_field::extract(opcode); - const int SH = vSH_field::extract(opcode); - if (!dg.gen_vector_3(ii->mnemo, vD, vA, vB, SH)) - goto do_generic; - break; - } - case PPC_I(MFVSCR): - { - if (!dg.gen_vector_1(ii->mnemo, vD_field::extract(opcode))) - goto do_generic; - break; - } - case PPC_I(MTVSCR): - { - if (!dg.gen_vector_1(ii->mnemo, vB_field::extract(opcode))) - goto do_generic; - break; - } - case PPC_I(VSPLTISB): - case PPC_I(VSPLTISH): - case PPC_I(VSPLTISW): - { - const int vD = vD_field::extract(opcode); - const int SIMM = op_sign_extend_5_32::apply(vUIMM_field::extract(opcode)); - if (!dg.gen_vector_2(ii->mnemo, vD, SIMM, 0)) - goto do_generic; - break; - } - case PPC_I(VSPLTB): - case PPC_I(VSPLTH): - case PPC_I(VSPLTW): - { - const int vD = vD_field::extract(opcode); - const int UIMM = vUIMM_field::extract(opcode); - const int vB = vB_field::extract(opcode); - if (!dg.gen_vector_2(ii->mnemo, vD, UIMM, vB)) - goto do_generic; - break; - } - default: // Direct call to instruction handler - { - typedef void (*func_t)(dyngen_cpu_base, uint32); - func_t func; - do_generic: - func = (func_t)ii->execute.ptr(); - goto do_invoke; - do_illegal: - func = (func_t)nv_mem_fun(&powerpc_cpu::execute_illegal).ptr(); - goto do_invoke; - do_invoke: -#if PPC_PROFILE_GENERIC_CALLS - if (ii->mnemo <= PPC_I(MAX)) { - uintptr mem = (uintptr)&generic_calls_count[ii->mnemo]; - if (mem <= 0xffffffff) - dg.gen_inc_32_mem(mem); - } -#endif - cg_context.pc = dpc; - cg_context.opcode = opcode; - cg_context.instr_info = ii; - cg_context.done_compile = done_compile; - compile_status = compile1(cg_context); - switch (compile_status) { - case COMPILE_FAILURE: - case COMPILE_EPILOGUE_OK: - if ((dpc - sync_pc) > sync_pc_offset) { - sync_pc = dpc; - sync_pc_offset = 0; - if (compile_status == COMPILE_EPILOGUE_OK) - break; - dg.gen_set_PC_im(dpc); - } - sync_pc_offset += 4; - dg.gen_invoke_CPU_im(func, opcode); - compile_status = COMPILE_CODE_OK; // could generate code, though a call to handler - break; - } - done_compile = cg_context.done_compile; - } - } - if (dg.full_translation_cache()) { - // Invalidate cache and start again - invalidate_cache(); - goto again; - } - } - // Do nothing if block has special epilogue code generated already - assert(compile_status != COMPILE_FAILURE); - if (compile_status != COMPILE_EPILOGUE_OK) { - // In direct block chaining mode, this code is reached only if - // there are pending spcflags, i.e. get out of this block - if (!use_direct_block_chaining) { - // TODO: optimize this to a direct jump to pregenerated code? - dg.gen_mov_ad_A0_im((uintptr)bi); - dg.gen_jump_next_A0(); - } - dg.gen_exec_return(); - } - bi->end_pc = dpc; - if (dpc < min_pc) - min_pc = dpc; - else if (dpc > max_pc) - max_pc = dpc; - bi->min_pc = min_pc; - bi->max_pc = max_pc; - -#if DYNGEN_DIRECT_BLOCK_CHAINING - // Generate backpatch trampolines - if (use_direct_block_chaining) { - typedef void *(*func_t)(dyngen_cpu_base); - func_t func = (func_t)nv_mem_fun(&powerpc_cpu::compile_chain_block).ptr(); - for (int i = 0; i < block_info::MAX_TARGETS; i++) { - if (bi->li[i].jmp_pc != block_info::INVALID_PC) { - uint8 *p = dg.gen_align(16); - dg.gen_mov_ad_A0_im(((uintptr)bi) | i); - dg.gen_invoke_CPU_A0_ret_A0(func); - dg.gen_jmp_A0(); - assert(dg.jmp_addr[i] != NULL); - bi->li[i].jmp_addr = dg.jmp_addr[i]; - bi->li[i].jmp_resolve_addr = p; - dg_set_jmp_target_noflush(bi->li[i].jmp_addr, bi->li[i].jmp_resolve_addr); - } - } - } -#endif - - bi->size = dg.code_ptr() - bi->entry_point; - if (disasm) - disasm_translation(entry_point, dpc - entry_point + 4, bi->entry_point, bi->size); - - dg.gen_end(); - my_block_cache.add_to_cl_list(bi); - if (is_read_only_memory(bi->pc)) - my_block_cache.add_to_dormant_list(bi); - else - my_block_cache.add_to_active_list(bi); -#if PPC_PROFILE_COMPILE_TIME - compile_time += (clock() - start_time); -#endif - return bi; -} -#endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/spcflags.hpp b/SheepShaver/src/kpx_cpu/src/cpu/spcflags.hpp deleted file mode 100644 index 0b521d53..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/spcflags.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * spcflags.hpp - CPU special flags - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SPCFLAGS_H -#define SPCFLAGS_H - -/** - * Basic special flags - **/ - -enum { - SPCFLAG_CPU_EXEC_RETURN = 1 << 0, // Return from emulation loop - SPCFLAG_CPU_TRIGGER_INTERRUPT = 1 << 1, // Trigger user interrupt - SPCFLAG_CPU_HANDLE_INTERRUPT = 1 << 2, // Call user interrupt handler - SPCFLAG_CPU_ENTER_MON = 1 << 3, // Enter cxmon - SPCFLAG_JIT_EXEC_RETURN = 1 << 4, // Return from compiled code -}; - -class basic_spcflags -{ - uint32 mask; - spinlock_t lock; - -public: - - basic_spcflags() - : mask(0), lock(SPIN_LOCK_UNLOCKED) - { } - - bool empty() const - { return (mask == 0); } - - bool test(uint32 v) const - { return (mask & v); } - - void init(uint32 v) - { spin_lock(&lock); mask = v; spin_unlock(&lock); } - - uint32 get() const - { return mask; } - - void set(uint32 v) - { spin_lock(&lock); mask |= v; spin_unlock(&lock); } - - void clear(uint32 v) - { spin_lock(&lock); mask &= ~v; spin_unlock(&lock); } -}; - -#endif /* SPCFLAGS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp b/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp deleted file mode 100644 index 55f30ec3..00000000 --- a/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * vm.hpp - Virtual memory management - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef VM_H -#define VM_H - -/// -/// Optimized memory accessors -/// - -#if defined(__i386__) || defined(__powerpc__) || defined(__ppc__) || defined(__m68k__) || defined(__x86_64__) -# define VM_CAN_ACCESS_UNALIGNED -#endif - -#ifdef WORDS_BIGENDIAN - -#ifdef VM_CAN_ACCESS_UNALIGNED - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_2 -#define VM_OPTIMIZED_MEMORY_ACCESS_2 -static inline uint32 vm_do_read_memory_2(uint16 *a) { return *a; } -static inline void vm_do_write_memory_2(uint16 *a, uint32 v) { *a = v; } -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_4 -#define VM_OPTIMIZED_MEMORY_ACCESS_4 -static inline uint32 vm_do_read_memory_4(uint32 *a) { return *a; } -static inline void vm_do_write_memory_4(uint32 *a, uint32 v) { *a = v; } -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_8 -#define VM_OPTIMIZED_MEMORY_ACCESS_8 -static inline uint64 vm_do_read_memory_8(uint64 *a) { return *a; } -static inline void vm_do_write_memory_8(uint64 *a, uint64 v) { *a = v; } -#endif - -#endif /* VM_CAN_ACCESS_UNALIGNED */ - -#else - -#ifdef VM_CAN_ACCESS_UNALIGNED - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_2 -#define VM_OPTIMIZED_MEMORY_ACCESS_2 -static inline uint32 vm_do_read_memory_2(uint16 *a) { return bswap_16(*a); } -static inline void vm_do_write_memory_2(uint16 *a, uint32 v) { *a = bswap_16(v); } -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_4 -#define VM_OPTIMIZED_MEMORY_ACCESS_4 -static inline uint32 vm_do_read_memory_4(uint32 *a) { return bswap_32(*a); } -static inline void vm_do_write_memory_4(uint32 *a, uint32 v) { *a = bswap_32(v); } -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_8 -#define VM_OPTIMIZED_MEMORY_ACCESS_8 -static inline uint64 vm_do_read_memory_8(uint64 *a) { return bswap_64(*a); } -static inline void vm_do_write_memory_8(uint64 *a, uint64 v) { *a = bswap_64(v); } -#endif - -#endif /* VM_CAN_ACCESS_UNALIGNED */ - -#endif /* WORDS_BIGENDIAN */ - -/// -/// Generic core memory accessors -/// - -static inline uint32 vm_do_read_memory_1(uint8 *a) -{ - return *a; -} -static inline void vm_do_write_memory_1(uint8 *a, uint32 v) -{ - *a = v; -} - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_2 -static inline uint32 vm_do_read_memory_2(uint16 *a) -{ - uint8 * b = (uint8 *)a; - return (b[0] << 8) | b[1]; -} -static inline void vm_do_write_memory_2(uint16 *a, uint32 v) -{ - uint8 * b = (uint8 *)a; - b[0] = v >> 8; - b[1] = v; -} -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_4 -static inline uint32 vm_do_read_memory_4(uint32 *a) -{ - uint8 * b = (uint8 *)a; - return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; -} -static inline void vm_do_write_memory_4(uint32 *a, uint32 v) -{ - uint8 * b = (uint8 *)a; - b[0] = v >> 24; - b[1] = v >> 16; - b[2] = v >> 8; - b[3] = v; -} -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_8 -static inline uint64 vm_do_read_memory_8(uint64 *a) -{ - uint8 * b = (uint8 *)a; - return - ((uint64)b[0] << 56) | - ((uint64)b[1] << 48) | - ((uint64)b[2] << 40) | - ((uint64)b[3] << 32) | - ((uint64)b[4] << 24) | - ((uint64)b[5] << 16) | - ((uint64)b[6] << 8) | - ((uint64)b[7]); -} - -static inline void vm_do_write_memory_8(uint64 *a, uint64 v) -{ - uint8 * b = (uint8 *)a; - b[0] = v >> 56; - b[1] = v >> 48; - b[2] = v >> 40; - b[3] = v >> 32; - b[4] = v >> 24; - b[5] = v >> 16; - b[6] = v >> 8; - b[7] = v; -} -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_2_REVERSED -static inline uint32 vm_do_read_memory_2_reversed(uint16 *a) -{ - uint8 * b = (uint8 *)a; - return b[0] | (b[1] << 8); -} -static inline void vm_do_write_memory_2_reversed(uint16 *a, uint32 v) -{ - uint8 * b = (uint8 *)a; - b[0] = v; - b[1] = v >> 8; -} -#endif - -#ifndef VM_OPTIMIZED_MEMORY_ACCESS_4_REVERSED -static inline uint32 vm_do_read_memory_4_reversed(uint32 *a) -{ - uint8 * b = (uint8 *)a; - return b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); -} -static inline void vm_do_write_memory_4_reversed(uint32 *a, uint32 v) -{ - uint8 * b = (uint8 *)a; - b[0] = v; - b[1] = v >> 8; - b[2] = v >> 16; - b[3] = v >> 24; -} -#endif - -/// -/// Actual memory accessors visible to CPU through virtual addresses -/// - -typedef uintptr vm_addr_t; - -#if REAL_ADDRESSING -const uintptr VMBaseDiff = 0; -#elif DIRECT_ADDRESSING -#ifdef NATMEM_OFFSET -const uintptr VMBaseDiff = NATMEM_OFFSET; -#endif -// Wrap address to 32-bit if we are not using 33-bit addressing space -#if defined(SHEEPSHAVER) && SIZEOF_VOID_P == 8 -#define vm_wrap_address(ADDR) (uintptr)(uint32)(ADDR) -#endif -#endif -#ifndef vm_wrap_address -#define vm_wrap_address(ADDR) (ADDR) -#endif - -#if REAL_ADDRESSING || DIRECT_ADDRESSING -static inline uint8 * vm_do_get_real_address(vm_addr_t addr) -{ - return (uint8 *)vm_wrap_address(VMBaseDiff + addr); -} -static inline vm_addr_t vm_do_get_virtual_address(uint8 *addr) -{ - return vm_wrap_address((uintptr)addr - VMBaseDiff); -} -static inline uint32 vm_read_memory_1(vm_addr_t addr) -{ - uint8 * const m = vm_do_get_real_address(addr); - return vm_do_read_memory_1(m); -} -static inline uint32 vm_read_memory_2(vm_addr_t addr) -{ - uint16 * const m = (uint16 *)vm_do_get_real_address(addr); - return vm_do_read_memory_2(m); -} -static inline uint32 vm_read_memory_4(vm_addr_t addr) -{ - uint32 * const m = (uint32 *)vm_do_get_real_address(addr); - return vm_do_read_memory_4(m); -} -static inline uint64 vm_read_memory_8(vm_addr_t addr) -{ - uint64 * const m = (uint64 *)vm_do_get_real_address(addr); - return vm_do_read_memory_8(m); -} -#define vm_read_memory_1_reversed vm_read_memory_1 -static inline uint32 vm_read_memory_2_reversed(vm_addr_t addr) -{ - uint16 * const m = (uint16 *)vm_do_get_real_address(addr); - return vm_do_read_memory_2_reversed(m); -} -static inline uint32 vm_read_memory_4_reversed(vm_addr_t addr) -{ - uint32 * const m = (uint32 *)vm_do_get_real_address(addr); - return vm_do_read_memory_4_reversed(m); -} -static inline void vm_write_memory_1(vm_addr_t addr, uint32 value) -{ - uint8 * const m = vm_do_get_real_address(addr); - vm_do_write_memory_1(m, value); -} -static inline void vm_write_memory_2(vm_addr_t addr, uint32 value) -{ - uint16 * const m = (uint16 *)vm_do_get_real_address(addr); - vm_do_write_memory_2(m, value); -} -static inline void vm_write_memory_4(vm_addr_t addr, uint32 value) -{ - uint32 * const m = (uint32 *)vm_do_get_real_address(addr); - vm_do_write_memory_4(m, value); -} -static inline void vm_write_memory_8(vm_addr_t addr, uint64 value) -{ - uint64 * const m = (uint64 *)vm_do_get_real_address(addr); - vm_do_write_memory_8(m, value); -} -#define vm_write_memory_1_reversed vm_write_memory_1 -static inline void vm_write_memory_2_reversed(vm_addr_t addr, uint32 value) -{ - uint16 * const m = (uint16 *)vm_do_get_real_address(addr); - vm_do_write_memory_2_reversed(m, value); -} -static inline void vm_write_memory_4_reversed(vm_addr_t addr, uint32 value) -{ - uint32 * const m = (uint32 *)vm_do_get_real_address(addr); - vm_do_write_memory_4_reversed(m, value); -} -static inline void *vm_memset(vm_addr_t addr, int c, size_t n) -{ - uint8 * const m = (uint8 *)vm_do_get_real_address(addr); - return memset(m, c, n); -} -#ifdef __cplusplus -static inline void *vm_memcpy(void *dest, vm_addr_t src, size_t n) -{ - return memcpy(dest, vm_do_get_real_address(src), n); -} -static inline void *vm_memcpy(vm_addr_t dest, const void *src, size_t n) -{ - return memcpy(vm_do_get_real_address(dest), src, n); -} -#endif -static inline void *vm_memcpy(vm_addr_t dest, vm_addr_t src, size_t n) -{ - return memcpy(vm_do_get_real_address(dest), vm_do_get_real_address(src), n); -} -#endif - -#endif /* VM_H */ - diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp deleted file mode 100755 index 3b471cda..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * ieeefp-i386.cpp - Access to FPU environment, x86 specific code - * Code largely derived from GNU libc - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * CPU features - */ - -/* XXX: duplicate from cpu/ppc/ppc-dyngen.cpp! */ -static uint32 cpu_features = 0; - -enum { - HWCAP_I386_CMOV = 1 << 15, - HWCAP_I386_MMX = 1 << 23, - HWCAP_I386_SSE = 1 << 25, - HWCAP_I386_SSE2 = 1 << 26, -}; - -static unsigned int x86_cpuid(void) -{ - int fl1, fl2; - - /* See if we can use cpuid. On AMD64 we always can. */ - __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" - "pushl %0; popfl; pushfl; popl %0; popfl" - : "=&r" (fl1), "=&r" (fl2) - : "i" (0x00200000)); - if (((fl1 ^ fl2) & 0x00200000) == 0) - return (0); - - /* Host supports cpuid. See if cpuid gives capabilities, try - CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we - don't need their CPUID values here, and %ebx may be the PIC - register. */ - __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx" - : "=a" (fl1) : "0" (0) : "edx", "cc"); - if (fl1 == 0) - return (0); - - /* Invoke CPUID(1), return %edx; caller can examine bits to - determine what's supported. */ - __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx" : "=d" (fl2) : "a" (1) : "cc"); - - return fl2; -} - -static inline int has_cpu_features(int test_cpu_features) -{ - static bool initted = false; - if (!initted) { - cpu_features = x86_cpuid(); - initted = true; - } - return cpu_features & test_cpu_features; -} - - -/* - * Rounding control - */ - -// Get current rounding direction -int fegetround(void) -{ - unsigned short cw; - - __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)); - - return cw & 0xc00; -} - -// Set the rounding direction represented by ROUND -int fesetround(int round) -{ - unsigned short cw; - - if ((round & ~0xc00) != 0) - return 1; - - __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)); - cw &= ~0xc00; - cw |= round; - __asm__ __volatile__("fldcw %0" : : "m" (*&cw)); - - if (has_cpu_features(HWCAP_I386_SSE) != 0) { - uint32 xcw; - __asm__ __volatile__("stmxcsr %0" : "=m" (*&xcw)); - xcw &= ~0x6000; - xcw |= round << 3; - __asm__ __volatile__("ldmxcsr %0" : : "m" (*&xcw)); - } - - return 0; -} diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp deleted file mode 100755 index 17e27d14..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-i386.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ieeefp-i386.hpp - IEEE754 Floating-Point Math library, x86 specific code - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * Code derived from the GNU C Library - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IEEEFP_I386_H -#define IEEEFP_I386_H - -// 7.6 Floating-point environment -#ifndef HAVE_FENV_H - -// Exceptions -enum { - FE_INVALID = 0x01, -#define FE_INVALID FE_INVALID - FE_DIVBYZERO = 0x04, -#define FE_DIVBYZERO FE_DIVBYZERO - FE_OVERFLOW = 0x08, -#define FE_OVERFLOW FE_OVERFLOW - FE_UNDERFLOW = 0x10, -#define FE_UNDERFLOW FE_UNDERFLOW - FE_INEXACT = 0x20 -#define FE_INEXACT FE_INEXACT -}; - -#define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) - -// Rounding modes -enum { - FE_TONEAREST = 0, -#define FE_TONEAREST FE_TONEAREST - FE_DOWNWARD = 0x400, -#define FE_DOWNWARD FE_DOWNWARD - FE_UPWARD = 0x800, -#define FE_UPWARD FE_UPWARD - FE_TOWARDZERO = 0xc00 -#define FE_TOWARDZERO FE_TOWARDZERO -}; - -#endif - -#endif /* IEEEFP_I386_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-mips.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-mips.hpp deleted file mode 100644 index 593331eb..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp-mips.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ieee-mips.hpp - IEE754 Floating-Point Math library, mips specific code - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * Code derived from the GNU C Library - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IEEEFP_MIPS_H -#define IEEEFP_MIPS_H - -// 7.6 Floating-point environment -#ifndef USE_FENV_H - -// Exceptions -enum { - FE_INEXACT = 0x04, -#define FE_INEXACT FE_INEXACT - FE_UNDERFLOW = 0x08, -#define FE_UNDERFLOW FE_UNDERFLOW - FE_OVERFLOW = 0x10, -#define FE_OVERFLOW FE_OVERFLOW - FE_DIVBYZERO = 0x20, -#define FE_DIVBYZERO FE_DIVBYZERO - FE_INVALID = 0x40, -#define FE_INVALID FE_INVALID -}; - -#define FE_ALL_EXCEPT (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) - -// Rounding modes -enum { - FE_TONEAREST = 0x0, -#define FE_TONEAREST FE_TONEAREST - FE_TOWARDZERO = 0x1, -#define FE_TOWARDZERO FE_TOWARDZERO - FE_UPWARD = 0x2, -#define FE_UPWARD FE_UPWARD - FE_DOWNWARD = 0x3 -#define FE_DOWNWARD FE_DOWNWARD -}; - -#endif - -#endif /* IEEEFP_MIPS_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp deleted file mode 100755 index 8158acee..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * ieeefp.cpp - Access to FPU environment - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#ifndef HAVE_FENV_H -#include "mathlib/ieeefp.hpp" -#if defined(__i386__) -#include "mathlib/ieeefp-i386.cpp" -#endif -#endif - diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp deleted file mode 100755 index 7fe544e5..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/ieeefp.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * ieeefp.hpp - IEEE754 Floating-Point Math library - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IEEEFP_H -#define IEEEFP_H - -// Can we use C99 extensions in C++ mode? -#ifdef HAVE_FENV_H -#if defined __GNUC__ -#define USE_FENV_H 1 -#endif -#endif - -// Arch-dependent definitions -#if defined(__i386__) -#include "mathlib/ieeefp-i386.hpp" -#endif -#if defined(__mips__) || (defined(sgi) && defined(mips)) -#include "mathlib/ieeefp-mips.hpp" -#endif - -#ifdef USE_FENV_H -#include -#else - -// Rounding control -extern "C" int fegetround(void); -extern "C" int fesetround(int); - -#endif /* FENV_H */ - -// Make sure previous instructions are executed first -// XXX this is most really a hint to the compiler so that is doesn't -// reorder calls to fe*() functions before the actual compuation... -#if defined __GNUC__ -#define febarrier() __asm__ __volatile__ ("") -#endif -#ifndef febarrier -#define febarrier() -#endif - -// HOST_FLOAT_WORDS_BIG_ENDIAN is a tristate: -// yes (1) / no (0) / default (undefined) -#if HOST_FLOAT_WORDS_BIG_ENDIAN -#define FLOAT_WORD_ORDER_BIG_ENDIAN -#elif defined(WORDS_BIGENDIAN) -#define FLOAT_WORD_ORDER_BIG_ENDIAN -#endif - -// Representation of an IEEE 754 float -union mathlib_ieee_float_shape_type { - float value; - uint32 word; -}; - -#define MATHLIB_GET_FLOAT_WORD(i,d) \ -do { \ - mathlib_ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ -} while (0) - -#define MATHLIB_SET_FLOAT_WORD(d,i) \ -do { \ - mathlib_ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ -} while (0) - -// Representation of an IEEE 754 double -union mathlib_ieee_double_shape_type { - double value; - struct { -#ifdef FLOAT_WORD_ORDER_BIG_ENDIAN - uint32 msw; - uint32 lsw; -#else - uint32 lsw; - uint32 msw; -#endif - } parts; -}; - -#define MATHLIB_EXTRACT_WORDS(ix0,ix1,d) \ -do { \ - mathlib_ieee_double_shape_type ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ -} while (0) - -#define MATHLIB_GET_HIGH_WORD(i,d) \ -do { \ - mathlib_ieee_double_shape_type gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ -} while (0) - -#define MATHLIB_GET_LOW_WORD(i,d) \ -do { \ - mathlib_ieee_double_shape_type gl_u; \ - gl_u.value = (d); \ - (i) = gl_u.parts.lsw; \ -} while (0) - -#endif /* IEEEFP_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.cpp b/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.cpp deleted file mode 100644 index cc82bbea..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * mathlib-i386.cpp - Math library wrapper, x86 specific code - * Code largely derived from GNU libc - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// 7.12.9.8 The trunc functions -#ifndef HAVE_TRUNC -#define HAVE_TRUNC -double trunc(double x) -{ - volatile unsigned short int cw; - volatile unsigned short int cwtmp; - double value; - - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); - cwtmp = (cw & 0xf3ff) | 0x0c00; /* toward zero */ - __asm__ __volatile__("fldcw %0" : : "m" (cwtmp)); - __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); - __asm__ __volatile__("fldcw %0" : : "m" (cw)); - return value; -} -#endif diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.hpp deleted file mode 100644 index 3c23b81c..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-i386.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * mathlib-i386.hpp - Math library wrapper, x86 specific code - * Code largely derived from GNU libc - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MATHLIB_I386_H -#define MATHLIB_I386_H - -// 7.12.9.5 The lrint and llrint functions -#if defined(__GNUC__) -#define mathlib_lrint(x) \ -({ long int __result; \ - __asm__ __volatile__ ("fistpl %0" : "=m" (__result) : "t" (x) : "st"); \ - __result; }) -#endif - -// 7.12.14 Comparison macros -#if defined(__GNUC__) -#ifndef isless -#define isless(x, y) \ -({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ - : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ - __result; }) -#endif - -#ifndef isgreater -#define isgreater(x, y) \ -({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ - __result; }) -#endif -#endif - -#endif /* MATHLIB_I386_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-ppc.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-ppc.hpp deleted file mode 100644 index 79cccb22..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-ppc.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * mathlib-ppc.hpp - Math library wrapper, ppc specific code - * Code largely derived from GNU libc - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MATHLIB_PPC_H -#define MATHLIB_PPC_H - -// Floating-Point Multiply Add -#if defined __GNUC__ -static inline double mathlib_fmadd(double x, double y, double z) -{ - double r; - __asm__ __volatile__ ("fmadd %0,%1,%2,%3" : "=f" (r) : "f" (x), "f" (y) , "f" (z)); - return r; -} - -static inline float mathlib_fmadd(float x, float y, float z) -{ - float r; - __asm__ __volatile__ ("fmadds %0,%1,%2,%3" : "=f" (r) : "f" (x), "f" (y) , "f" (z)); - return r; -} - -#define mathlib_fmadd(x, y, z) (mathlib_fmadd)(x, y, z) -#endif - -// Floating-Point Multiply Subtract -#if defined __GNUC__ -static inline double mathlib_fmsub(double x, double y, double z) -{ - double r; - __asm__ __volatile__ ("fmsub %0,%1,%2,%3" : "=f" (r) : "f" (x), "f" (y) , "f" (z)); - return r; -} - -static inline float mathlib_fmsub(float x, float y, float z) -{ - float r; - __asm__ __volatile__ ("fmsubs %0,%1,%2,%3" : "=f" (r) : "f" (x), "f" (y) , "f" (z)); - return r; -} - -#define mathlib_fmsub(x, y, z) (mathlib_fmsub)(x, y, z) -#endif - -#endif /* MATHLIB_PPC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-x86_64.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-x86_64.hpp deleted file mode 100644 index 4af8a426..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib-x86_64.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * mathlib-x86_64.hpp - Math library wrapper, x86-64 specific code - * Code largely derived from GNU libc - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MATHLIB_X86_64_H -#define MATHLIB_X86_64_H - -// 7.12.9.5 The lrint and llrint functions -#if defined(__GNUC__) -#define mathlib_lrint(x) \ -({ long int __result; \ - __asm__ __volatile__ ("cvtsd2si %1, %0" : "=r" (__result) : "x" (x)); \ - __result; }) -#endif - -#endif /* MATHLIB_X86_64_H */ diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib.cpp b/SheepShaver/src/kpx_cpu/src/mathlib/mathlib.cpp deleted file mode 100644 index d51a8db2..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * mathlib.cpp - Math library wrapper - * Code largely derived from GNU libc - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "mathlib/mathlib.hpp" - -#include -#include - - -/** - * Arch-dependent optimizations - **/ - -#if defined(__i386__) -#include "mathlib/mathlib-i386.cpp" -#endif - - -/** - * Helper functions - **/ - -static void unimplemented(const char *function) -{ - fprintf(stderr, "MATHLIB: unimplemented function '%s', aborting execution\n", function); - abort(); -} - - -/** - * 7.12.3.1 The fpclassify macro - **/ - -int mathlib_fpclassifyf (float x) -{ - uint32 wx; - int retval = FP_NORMAL; - - MATHLIB_GET_FLOAT_WORD (wx, x); - wx &= 0x7fffffff; - if (wx == 0) - retval = FP_ZERO; - else if (wx < 0x800000) - retval = FP_SUBNORMAL; - else if (wx >= 0x7f800000) - retval = wx > 0x7f800000 ? FP_NAN : FP_INFINITE; - - return retval; -} - -int mathlib_fpclassify (double x) -{ - uint32 hx, lx; - int retval = FP_NORMAL; - - MATHLIB_EXTRACT_WORDS (hx, lx, x); - lx |= hx & 0xfffff; - hx &= 0x7ff00000; - if ((hx | lx) == 0) - retval = FP_ZERO; - else if (hx == 0) - retval = FP_SUBNORMAL; - else if (hx == 0x7ff00000) - retval = lx != 0 ? FP_NAN : FP_INFINITE; - - return retval; -} - -int mathlib_fpclassifyl(long double x) -{ - unimplemented("fpclassifyl"); -} - - -/** - * 7.12.3.6 The signbit macro - **/ - -int mathlib_signbitf (float x) -{ - int32 hx; - - MATHLIB_GET_FLOAT_WORD (hx, x); - return hx & 0x80000000; -} - -int mathlib_signbit (double x) -{ - int32 hx; - - MATHLIB_GET_HIGH_WORD (hx, x); - return hx & 0x80000000; -} - -int mathlib_signbitl(long double x) -{ - unimplemented("signbitl"); -} - - -/** - * 7.12.9.5 The lrint and llrint functions - **/ - -#ifndef mathlib_lrint -long mathlib_lrint(double x) -{ - int32 j0; - uint32 i0, i1; - volatile double w; - double t; - long int result; - int sx; - - static const double two52[2] = { - 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ - }; - - MATHLIB_EXTRACT_WORDS (i0, i1, x); - j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; - sx = i0 >> 31; - i0 &= 0xfffff; - i0 |= 0x100000; - - if (j0 < 20) { - if (j0 < -1) - return 0; - else { - w = two52[sx] + x; - t = w - two52[sx]; - MATHLIB_EXTRACT_WORDS (i0, i1, t); - j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; - i0 &= 0xfffff; - i0 |= 0x100000; - - result = i0 >> (20 - j0); - } - } - else if (j0 < (int32) (8 * sizeof (long int)) - 1) { - if (j0 >= 52) - result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); - else { - w = two52[sx] + x; - t = w - two52[sx]; - MATHLIB_EXTRACT_WORDS (i0, i1, t); - j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; - i0 &= 0xfffff; - i0 |= 0x100000; - - if (j0 == 20) - result = (long int) i0; - else - result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); - } - } - else { - /* The number is too large. It is left implementation defined - what happens. */ - return (long int) x; - } - - return sx ? -result : result; -} -#endif - - -/** - * 7.12.9.6 The round functions - **/ - -float mathlib_roundf(float x) -{ - int32 i0, j0; - static const float huge = 1.0e30; - - MATHLIB_GET_FLOAT_WORD (i0, x); - j0 = ((i0 >> 23) & 0xff) - 0x7f; - if (j0 < 23) { - if (j0 < 0) { - if (huge + x > 0.0F) { - i0 &= 0x80000000; - if (j0 == -1) - i0 |= 0x3f800000; - } - } - else { - uint32 i = 0x007fffff >> j0; - if ((i0 & i) == 0) - /* X is integral. */ - return x; - if (huge + x > 0.0F) { - /* Raise inexact if x != 0. */ - i0 += 0x00400000 >> j0; - i0 &= ~i; - } - } - } - else { - if (j0 == 0x80) - /* Inf or NaN. */ - return x + x; - else - return x; - } - - MATHLIB_SET_FLOAT_WORD (x, i0); - return x; -} diff --git a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib.hpp b/SheepShaver/src/kpx_cpu/src/mathlib/mathlib.hpp deleted file mode 100644 index d0ef5dcf..00000000 --- a/SheepShaver/src/kpx_cpu/src/mathlib/mathlib.hpp +++ /dev/null @@ -1,339 +0,0 @@ - -/* - * mathlib.hpp - Math library wrapper - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MATHLIB_H -#define MATHLIB_H - -#include -#include "mathlib/ieeefp.hpp" - -// Broken MacOS X headers -#if defined(__APPLE__) && defined(__MACH__) -// ... the following exist but are not macro-defined ... -#ifndef FP_NAN -#define FP_NAN FP_NAN -#define FP_INFINITE FP_INFINITE -#define FP_ZERO FP_ZERO -#define FP_NORMAL FP_NORMAL -#define FP_SUBNORMAL FP_SUBNORMAL -#endif -#endif - -// GCC fixes for IRIX/mips -#if defined __GNUC__ && defined __sgi__ && defined __mips__ -#define mathlib_generic_1(func, x) \ - (sizeof(x) == sizeof(float) ? _##func##f(x) : _##func(x)) - -#define fpclassify(x) mathlib_generic_1(fpclassify, x) -#define isnormal(x) mathlib_generic_1(isnormal, x) -#define isfinite(x) mathlib_generic_1(isfinite, x) -#define isnan(x) mathlib_generic_1(isnan, x) -#define isinf(x) mathlib_generic_1(isinf, x) -#define signbit(x) mathlib_generic_1(signbit, x) - -#define mathlib_generic_2(func, x, y) \ - ((sizeof(x) == sizeof(float) && sizeof(x) == sizeof(y)) ? _##func##f(x, y) : _##func(x, y)) - -#define isless(x,y) mathlib_generic_2(isless, x, y) -#define isgreater(x,y) mathlib_generic_2(isgreater, x, y) -#endif - -// C++ exception specifications -#if defined __GLIBC__ && defined __THROW -#define MATHLIB_THROW __THROW -#else -#define MATHLIB_THROW -#endif - -// 7.12 Mathematics [#6] -#ifndef FP_NAN -enum { - FP_NAN, -# define FP_NAN FP_NAN - FP_INFINITE, -# define FP_INFINITE FP_INFINITE - FP_ZERO, -# define FP_ZERO FP_ZERO - FP_SUBNORMAL, -# define FP_SUBNORMAL FP_SUBNORMAL - FP_NORMAL -# define FP_NORMAL FP_NORMAL -}; -#endif - -// Arch-dependent definitions -#if defined(__i386__) -#include "mathlib/mathlib-i386.hpp" -#endif -#if defined(__x86_64__) -#include "mathlib/mathlib-x86_64.hpp" -#endif -#if defined(__powerpc__) || defined(__ppc__) -#include "mathlib/mathlib-ppc.hpp" -#endif - -// Floating-Point Multiply Add/Subtract functions -#if (SIZEOF_LONG_DOUBLE > SIZEOF_DOUBLE) && (SIZEOF_DOUBLE > SIZEOF_FLOAT) -// FIXME: this is wrong for underflow conditions -#ifndef mathlib_fmadd -static inline double mathlib_fmadd(double x, double y, double z) -{ - return ((long double)x * (long double)y) + z; -} -static inline float mathlib_fmadd(float x, float y, float z) -{ - return ((double)x * (double)y) + z; -} -#define mathlib_fmadd(x, y, z) (mathlib_fmadd)(x, y, z) -#endif -#ifndef mathlib_fmsub -static inline double mathlib_fmsub(double x, double y, double z) -{ - return ((long double)x * (long double)y) - z; -} -static inline float mathlib_fmsub(float x, float y, float z) -{ - return ((double)x * (double)y) - z; -} -#define mathlib_fmsub(x, y, z) (mathlib_fmsub)(x, y, z) -#endif -#endif -#ifndef mathlib_fmadd -#define mathlib_fmadd(x, y, z) (((x) * (y)) + (z)) -#endif -#ifndef mathlib_fmsub -#define mathlib_fmsub(x, y, z) (((x) * (y)) - (z)) -#endif - -// 7.12.6.2 The exp2 functions -#ifdef HAVE_EXP2F -extern "C" float exp2f(float x) MATHLIB_THROW; -#else -#ifdef HAVE_EXP2 -extern "C" double exp2(double x) MATHLIB_THROW; -#define exp2f(x) (float)exp2(x) -#else -#ifndef exp2f -#define exp2f(x) powf(2.0, (x)) -#endif -#endif -#endif - -// 7.12.6.10 The log2 functions -#ifdef HAVE_LOG2F -extern "C" float log2f(float x) MATHLIB_THROW; -#else -#ifdef HAVE_LOG2 -extern "C" double log2(double x) MATHLIB_THROW; -#define log2f(x) (float)log2(x) -#else -#ifndef M_LN2 -#define M_LN2 logf(2.0) -#endif -#ifndef log2f -#define log2f(x) logf(x) / M_LN2 -#endif -#endif -#endif - -// 7.12.9.1 The ceil functions -#ifdef HAVE_CEILF -extern "C" float ceilf(float x) MATHLIB_THROW; -#else -#ifdef HAVE_CEIL -extern "C" double ceil(double x) MATHLIB_THROW; -#define ceilf(x) (float)ceil(x) -#endif -#endif - -// 7.12.9.2 The floor functions -#ifdef HAVE_FLOORF -extern "C" float floorf(float x) MATHLIB_THROW; -#else -#ifdef HAVE_FLOOR -extern "C" double floor(double x) MATHLIB_THROW; -#define floorf(x) (float)floor(x) -#endif -#endif - -// 7.12.9.5 The lrint and llrint functions -#ifdef HAVE_LRINT -extern "C" long lrint(double x) MATHLIB_THROW; -#else -#ifndef mathlib_lrint -extern long mathlib_lrint(double); -#endif -#define lrint(x) mathlib_lrint(x) -#endif - -// 7.12.9.6 The round functions -#ifdef HAVE_ROUNDF -extern "C" float roundf(float x) MATHLIB_THROW; -#else -#ifdef HAVE_ROUND -extern "C" double round(double x) MATHLIB_THROW; -#define roundf(x) (float)round(x) -#else -extern float mathlib_roundf(float); -#define roundf(x) mathlib_roundf(x) -#endif -#endif - -// 7.12.9.8 The trunc functions -#ifdef HAVE_TRUNCF -extern "C" float truncf(float x) MATHLIB_THROW; -#else -#ifdef HAVE_TRUNC -extern "C" double trunc(double x) MATHLIB_THROW; -#define truncf(x) (float)trunc(x) -#endif -#endif - -// 7.12.3.1 The fpclassify macro -#ifndef fpclassify -#ifndef mathlib_fpclassifyf -extern int mathlib_fpclassifyf(float x); -#endif -#ifndef mathlib_fpclassify -extern int mathlib_fpclassify(double x); -#endif -#ifndef mathlib_fpclassifyl -extern int mathlib_fpclassifyl(long double x); -#endif -#define fpclassify(x) \ - (sizeof (x) == sizeof (float) \ - ? mathlib_fpclassifyf (x) \ - : sizeof (x) == sizeof (double) \ - ? mathlib_fpclassify (x) : mathlib_fpclassifyl (x)) -#endif - -// 7.12.3.2 The isfinite macro -static inline int mathlib_isfinite(float x) -{ - int32 ix; - - MATHLIB_GET_FLOAT_WORD(ix, x); - return (int)((uint32)((ix & 0x7fffffff) - 0x7f800000) >> 31); -} - -static inline int mathlib_isfinite(double x) -{ - int32 hx; - - MATHLIB_GET_HIGH_WORD(hx, x); - return (int)((uint32)((hx & 0x7fffffff) - 0x7ff00000) >> 31); -} - -#ifndef isfinite -#define isfinite(x) mathlib_isfinite(x) -#endif - -// 7.12.3.3 The isinf macro -static inline int mathlib_isinf(float x) -{ - int32 ix, t; - - MATHLIB_GET_FLOAT_WORD(ix, x); - t = ix & 0x7fffffff; - t ^= 0x7f800000; - t |= -t; - return ~(t >> 31) & (ix >> 30); -} - -static inline int mathlib_isinf(double x) -{ - int32 hx, lx; - - MATHLIB_EXTRACT_WORDS(hx, lx, x); - lx |= (hx & 0x7fffffff) ^ 0x7ff00000; - lx |= -lx; - return ~(lx >> 31) & (hx >> 30); -} - -#ifndef isinf -#if defined __sgi && defined __mips -// specialized implementation for IRIX mips compilers -extern "C" int _isinf(double); -extern "C" int _isinff(float); -static inline int isinf(double x) { return _isinf(x); } -static inline int isinf(float x) { return _isinff(x); } -#else -#define isinf(x) mathlib_isinf(x) -#endif -#endif - -// 7.12.3.4 The isnan macro -static inline int mathlib_isnan(float x) -{ - int32 ix; - - MATHLIB_GET_FLOAT_WORD(ix, x); - ix &= 0x7fffffff; - ix = 0x7f800000 - ix; - return (int)(((uint32)ix) >> 31); -} - -static inline int mathlib_isnan(double x) -{ - int32 hx, lx; - - MATHLIB_EXTRACT_WORDS(hx, lx, x); - hx &= 0x7fffffff; - hx |= (uint32)(lx|(-lx)) >> 31; - hx = 0x7ff00000 - hx; - return (int)(((uint32)hx) >> 31); -} - -#ifndef isnan -#define isnan(x) mathlib_isnan(x) -#endif - -// 7.12.3.6 The signbit macro -#ifndef signbit -#ifndef mathlib_signbitf -extern int mathlib_signbitf(float x); -#endif -#ifndef mathlib_signbit -extern int mathlib_signbit(double x); -#endif -#ifndef mathlib_signbitl -extern int mathlib_signbitl(long double x); -#endif -#define signbit(x) \ - (sizeof (x) == sizeof (float) \ - ? mathlib_signbitf (x) \ - : sizeof (x) == sizeof (double) \ - ? mathlib_signbit (x) : mathlib_signbitl (x)) -#endif - -// 7.12.14.1 The isgreater macro -// FIXME: this is wrong for unordered values -#ifndef isgreater -#define isgreater(x, y) ((x) > (y)) -#endif - -// 7.12.14.3 The isless macro -// FIXME: this is wrong for unordered values -#ifndef isless -#define isless(x, y) ((x) < (y)) -#endif - -#endif /* MATHLIB_H */ diff --git a/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp b/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp deleted file mode 100644 index 2e5b99d3..00000000 --- a/SheepShaver/src/kpx_cpu/src/test/test-powerpc.cpp +++ /dev/null @@ -1,2242 +0,0 @@ -/* - * test-powerpc.cpp - PowerPC regression testing - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// NOTE: Results file md5sum: 3e29432abb6e21e625a2eef8cf2f0840 ($Revision$) - -#include -#include -#include -#include -#include -#include // ntohl(), htonl() -#include -#include -#include -#include - -#if defined(__powerpc__) || defined(__ppc__) -#define NATIVE_POWERPC -#endif - -#if EMU_KHEPERIX -#include "sysdeps.h" -#include "vm_alloc.h" -#include "cpu/ppc/ppc-cpu.hpp" -#include "cpu/ppc/ppc-instructions.hpp" -#endif - -#if EMU_MICROLIB -#include -typedef unsigned int uint32; -typedef unsigned long uintptr; -#undef RD -#undef RA -#undef RB -#undef FB -#undef FE -#endif - -#if EMU_MODEL3PPC -extern "C" { -#include "ppc.h" -} -typedef unsigned int uint32; -typedef unsigned long uintptr; -typedef uint32_t UINT32; -typedef char CHAR; -typedef int BOOL; -#endif - -#if EMU_QEMU -extern "C" { -#include "target-ppc/cpu.h" -extern void tb_flush(); -} -typedef uint32_t uint32; -typedef uintptr_t uintptr; -#endif - -// Disassemblers needed for debugging purposes -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif - -// Define units to test (in-order: ALU, FPU, VMX) -#define TEST_ALU_OPS 1 -#if EMU_KHEPERIX -#define TEST_FPU_OPS 1 -#define TEST_VMX_OPS 1 -#endif - -// Define units to skip during testing -#define SKIP_ALU_OPS 0 -#define SKIP_FPU_OPS 0 -#define SKIP_VMX_OPS 0 - -// Define instructions to test -#define TEST_ADD 1 -#define TEST_SUB 1 -#define TEST_MUL 1 -#define TEST_DIV 1 -#define TEST_SHIFT 1 -#define TEST_ROTATE 1 -#define TEST_MISC 1 -#define TEST_LOGICAL 1 -#define TEST_COMPARE 1 -#define TEST_CR_LOGICAL 1 -#define TEST_VMX_LOADSH 1 -#define TEST_VMX_LOAD 1 -#define TEST_VMX_ARITH 1 - - -// Partial PowerPC runtime assembler from GNU lightning -#undef _I -#define _I(X) ((uint32)(X)) -#undef _UL -#define _UL(X) ((uint32)(X)) -#undef _MASK -#define _MASK(N) ((uint32)((1<<(N)))-1) -#undef _ck_s -#define _ck_s(W,I) (_UL(I) & _MASK(W)) -#undef _ck_u -#define _ck_u(W,I) (_UL(I) & _MASK(W)) -#undef _ck_su -#define _ck_su(W,I) (_UL(I) & _MASK(W)) -#undef _u1 -#define _u1(I) _ck_u( 1,I) -#undef _u5 -#define _u5(I) _ck_u( 5,I) -#undef _u6 -#define _u6(I) _ck_u( 6,I) -#undef _u9 -#define _u9(I) _ck_u( 9,I) -#undef _u10 -#define _u10(I) _ck_u(10,I) -#undef _u11 -#define _u11(I) _ck_u(11,I) -#undef _s16 -#define _s16(I) _ck_s(16,I) - -#undef _D -#define _D( OP,RD,RA, DD ) _I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)| _s16(DD) ) -#undef _X -#define _X( OP,RD,RA,RB, XO,RC ) _I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)| (_u10(XO)<<1)|_u1(RC)) -#undef _XO -#define _XO( OP,RD,RA,RB,OE,XO,RC ) _I((_u6(OP)<<26)|(_u5(RD)<<21)|(_u5(RA)<<16)|( _u5(RB)<<11)|(_u1(OE)<<10)|( _u9(XO)<<1)|_u1(RC)) -#undef _M -#define _M( OP,RS,RA,SH,MB,ME,RC ) _I((_u6(OP)<<26)|(_u5(RS)<<21)|(_u5(RA)<<16)|( _u5(SH)<<11)|(_u5(MB)<< 6)|( _u5(ME)<<1)|_u1(RC)) -#undef _VX -#define _VX( OP,VD,VA,VB, XO ) _I((_u6(OP)<<26)|(_u5(VD)<<21)|(_u5(VA)<<16)|( _u5(VB)<<11)| _u11(XO) ) -#undef _VXR -#define _VXR( OP,VD,VA,VB, XO,RC ) _I((_u6(OP)<<26)|(_u5(VD)<<21)|(_u5(VA)<<16)|( _u5(VB)<<11)| (_u1(RC)<<10)|_u10(XO)) -#undef _VA -#define _VA( OP,VD,VA,VB,VC,XO ) _I((_u6(OP)<<26)|(_u5(VD)<<21)|(_u5(VA)<<16)|( _u5(VB)<<11)|(_u5(VC)<< 6)| _u6(XO) ) - -// PowerPC opcodes -static inline uint32 POWERPC_LI(int RD, uint32 v) { return _D(14,RD,00,(v&0xffff)); } -static inline uint32 POWERPC_MR(int RD, int RA) { return _X(31,RA,RD,RA,444,0); } -static inline uint32 POWERPC_MFCR(int RD) { return _X(31,RD,00,00,19,0); } -static inline uint32 POWERPC_LVX(int vD, int rA, int rB) { return _X(31,vD,rA,rB,103,0); } -static inline uint32 POWERPC_STVX(int vS, int rA, int rB) { return _X(31,vS,rA,rB,231,0); } -static inline uint32 POWERPC_MFSPR(int rD, int SPR) { return _X(31,rD,(SPR&0x1f),((SPR>>5)&0x1f),339,0); } -static inline uint32 POWERPC_MTSPR(int rS, int SPR) { return _X(31,rS,(SPR&0x1f),((SPR>>5)&0x1f),467,0); } -const uint32 POWERPC_NOP = 0x60000000; -const uint32 POWERPC_BLR = 0x4e800020; -const uint32 POWERPC_BLRL = 0x4e800021; -const uint32 POWERPC_ILLEGAL = 0x00000000; -const uint32 POWERPC_EMUL_OP = 0x18000000; - -// Invalidate test cache -#ifdef NATIVE_POWERPC -static void inline ppc_flush_icache_range(uint32 *start_p, uint32 length) -{ - const int MIN_CACHE_LINE_SIZE = 8; /* conservative value */ - - unsigned long start = (unsigned long)start_p; - unsigned long stop = start + length; - unsigned long p; - - p = start & ~(MIN_CACHE_LINE_SIZE - 1); - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); - - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); - } - asm volatile ("sync" : : : "memory"); - asm volatile ("isync" : : : "memory"); -} -#else -static void inline ppc_flush_icache_range(uint32 *start_p, uint32 length) -{ -} -#endif - -#if EMU_KHEPERIX -// Wrappers when building from SheepShaver tree -#ifdef SHEEPSHAVER -uint32 ROMBase = 0x40800000; -int64 TimebaseSpeed = 25000000; // Default: 25 MHz -uint32 PVR = 0x000c0000; // Default: 7400 (with AltiVec) - -bool PrefsFindBool(const char *name) -{ - return false; -} - -uint64 GetTicks_usec(void) -{ - return clock(); -} - -void HandleInterrupt(powerpc_registers *) -{ -} - -#if PPC_ENABLE_JIT && PPC_REENTRANT_JIT -void init_emul_op_trampolines(basic_dyngen & dg) -{ -} -#endif -#endif - -struct powerpc_cpu_base - : public powerpc_cpu -{ - powerpc_cpu_base(); - void init_decoder(); - void execute_return(uint32 opcode); - void invalidate_cache_range(uint32 *start, uint32 size) - { powerpc_cpu::invalidate_cache_range((uintptr)start, ((uintptr)start) + size); } - - uint32 emul_get_xer() const { return xer().get(); } - void emul_set_xer(uint32 value) { xer().set(value); } - uint32 emul_get_cr() const { return cr().get(); } - void emul_set_cr(uint32 value) { cr().set(value); } - uint32 get_lr() const { return lr(); } - void set_lr(uint32 value) { lr() = value; } - uint32 get_gpr(int i) const { return gpr(i); } - void set_gpr(int i, uint32 value) { gpr(i) = value; } -}; - -powerpc_cpu_base::powerpc_cpu_base() -#ifndef SHEEPSHAVER - : powerpc_cpu(NULL) -#endif -{ - init_decoder(); -} - -void powerpc_cpu_base::execute_return(uint32 opcode) -{ - spcflags().set(SPCFLAG_CPU_EXEC_RETURN); -} - -void powerpc_cpu_base::init_decoder() -{ - static const instr_info_t return_ii_table[] = { - { "return", - (execute_pmf)&powerpc_cpu_base::execute_return, - PPC_I(MAX), - D_form, 6, 0, CFLOW_JUMP - } - }; - - const int ii_count = sizeof(return_ii_table)/sizeof(return_ii_table[0]); - - for (int i = 0; i < ii_count; i++) { - const instr_info_t * ii = &return_ii_table[i]; - init_decoder_entry(ii); - } -} -#endif - -#if EMU_MICROLIB -static volatile bool ppc_running = false; - -struct powerpc_cpu_base -{ - powerpc_cpu_base(); - void execute(uintptr); - void enable_jit() { } - void invalidate_cache() { } - void invalidate_cache_range(uint32 *start, uint32 size) { } - - uint32 emul_get_xer() const { return XER; } - void emul_set_xer(uint32 value) { XER = value; } - uint32 emul_get_cr() const { return CR; } - void emul_set_cr(uint32 value) { CR = value; } - uint32 get_lr() const { return LR; } - void set_lr(uint32 value) { LR = value; } - uint32 get_gpr(int i) const { return GPR(i); } - void set_gpr(int i, uint32 value) { GPR(i) = value; } -}; - -void sheep_impl(ppc_inst_t inst) -{ - ppc_running = false; -} - -extern "C" void init_table(int opcd, void (*impl)(ppc_inst_t), char *(*bin2c)(ppc_inst_t, addr_t, char *), char *(*disasm)(ppc_inst_t, addr_t, char *), void (*translate)(ppc_inst_t, struct DecodedInstruction *), void (*xmlize)(ppc_inst_t, addr_t, char *), char *mnemonic); - -powerpc_cpu_base::powerpc_cpu_base() -{ - ppc_init(); - init_table(6, sheep_impl, NULL, NULL, NULL, NULL, "sheep"); -} - -#define ppc_code_fetch(A) ntohl(*((uint32 *)(A))) - -void powerpc_cpu_base::execute(uintptr entry_point) -{ - PC = entry_point; - - ppc_running = true; - while (ppc_running) { - ppc_inst_t inst = ppc_code_fetch(PC); - ppc_execute(inst); - } -} -#endif - -#if EMU_MODEL3PPC -extern "C" BOOL DisassemblePowerPC(UINT32, UINT32, CHAR *, CHAR *, BOOL); -BOOL DisassemblePowerPC(UINT32, UINT32, CHAR *, CHAR *, BOOL) { } - -static volatile bool ppc_running = false; - -struct powerpc_cpu_base -{ - powerpc_cpu_base(); - void execute(uintptr); - void enable_jit() { } - void invalidate_cache() { } - void invalidate_cache_range(uint32 *start, uint32 size) { } - - uint32 emul_get_xer() const { return ppc_get_reg(PPC_REG_XER); } - void emul_set_xer(uint32 value) { ppc_set_reg(PPC_REG_XER, value); } - uint32 emul_get_cr() const { return ppc_get_reg(PPC_REG_CR); } - void emul_set_cr(uint32 value) { ppc_set_reg(PPC_REG_CR, value); } - uint32 get_lr() const { return ppc_get_reg(PPC_REG_LR); } - void set_lr(uint32 value) { ppc_set_reg(PPC_REG_LR, value); } - uint32 get_gpr(int i) const { return ppc_get_r(i); } - void set_gpr(int i, uint32 value) { ppc_set_r(i, value); } -}; - -static uint32 read_32(uint32 a) -{ - return ntohl(*((uint32 *)a)); -} - -static uint32 read_op(uint32 a) -{ - uint32 opcode = read_32(a); - if (opcode == POWERPC_EMUL_OP) { - ppc_running = false; - return POWERPC_NOP; - } - return opcode; -} - -powerpc_cpu_base::powerpc_cpu_base() -{ - ppc_init(NULL); - ppc_set_read_32_handler((void *)&read_32); - ppc_set_read_op_handler((void *)&read_op); -} - -void powerpc_cpu_base::execute(uintptr entry_point) -{ - ppc_set_reg(PPC_REG_PC, entry_point); - - ppc_running = true; - while (ppc_running) - ppc_run(1); -} -#endif - -#if EMU_QEMU -class powerpc_cpu_base -{ - CPUPPCState *ppc; -public: - powerpc_cpu_base(); - ~powerpc_cpu_base(); - void execute(uintptr); - void enable_jit() { } - void invalidate_cache() { tb_flush(); } - void invalidate_cache_range(uint32 *start, uint32 size) { invalidate_cache(); } - - uint32 emul_get_xer() const; - void emul_set_xer(uint32 value); - uint32 emul_get_cr() const; - void emul_set_cr(uint32 value); - uint32 get_lr() const { return ppc->LR; } - void set_lr(uint32 value) { ppc->LR = value; } - uint32 get_gpr(int i) const { return ppc->gpr[i]; } - void set_gpr(int i, uint32 value) { ppc->gpr[i] = value; } -}; - -uint32 powerpc_cpu_base::emul_get_xer() const -{ - uint32 xer = 0; - for (int i = 0; i < 32; i++) - xer |= ppc->xer[i] << i; - return xer; -} - -void powerpc_cpu_base::emul_set_xer(uint32 value) -{ - for (int i = 0; i < 32; i++) - ppc->xer[i] = (value >> i) & 1; -} - -uint32 powerpc_cpu_base::emul_get_cr() const -{ - uint32 cr = 0; - for (int i = 0; i < 8; i++) - cr |= (ppc->crf[i] & 15) << (28 - 4 * i); - return cr; -} - -void powerpc_cpu_base::emul_set_cr(uint32 value) -{ - for (int i = 0; i < 8; i++) - ppc->crf[i] = (value >> (28 - 4 * i)) & 15; -} - -powerpc_cpu_base::powerpc_cpu_base() -{ - ppc = cpu_ppc_init(); -} - -powerpc_cpu_base::~powerpc_cpu_base() -{ - cpu_ppc_close(ppc); -} - -void powerpc_cpu_base::execute(uintptr entry_point) -{ - ppc->nip = entry_point; - cpu_exec(ppc); -} -#endif - -// Define bit-fields -#if !EMU_KHEPERIX -template< int FB, int FE > -struct static_mask { - enum { value = (0xffffffff >> FB) ^ (0xffffffff >> (FE + 1)) }; -}; - -template< int FB > -struct static_mask { - enum { value = 0xffffffff >> FB }; -}; - -template< int FB, int FE > -struct bit_field { - static inline uint32 mask() { - return static_mask::value; - } - static inline bool test(uint32 value) { - return value & mask(); - } - static inline uint32 extract(uint32 value) { - const uint32 m = mask() >> (31 - FE); - return (value >> (31 - FE)) & m; - } - static inline void insert(uint32 & data, uint32 value) { - const uint32 m = mask(); - data = (data & ~m) | ((value << (31 - FE)) & m); - } -}; - -// General purpose registers -typedef bit_field< 11, 15 > rA_field; -typedef bit_field< 16, 20 > rB_field; -typedef bit_field< 6, 10 > rD_field; -typedef bit_field< 6, 10 > rS_field; - -// Vector registers -typedef bit_field< 11, 15 > vA_field; -typedef bit_field< 16, 20 > vB_field; -typedef bit_field< 21, 25 > vC_field; -typedef bit_field< 6, 10 > vD_field; -typedef bit_field< 6, 10 > vS_field; -typedef bit_field< 22, 25 > vSH_field; - -// Condition registers -typedef bit_field< 11, 15 > crbA_field; -typedef bit_field< 16, 20 > crbB_field; -typedef bit_field< 6, 10 > crbD_field; -typedef bit_field< 6, 8 > crfD_field; -typedef bit_field< 11, 13 > crfS_field; - -// CR register fields -template< int CRn > struct CR_field : bit_field< 4*CRn+0, 4*CRn+3 > { }; -template< int CRn > struct CR_LT_field : bit_field< 4*CRn+0, 4*CRn+0 > { }; -template< int CRn > struct CR_GT_field : bit_field< 4*CRn+1, 4*CRn+1 > { }; -template< int CRn > struct CR_EQ_field : bit_field< 4*CRn+2, 4*CRn+2 > { }; -template< int CRn > struct CR_SO_field : bit_field< 4*CRn+3, 4*CRn+3 > { }; -template< int CRn > struct CR_UN_field : bit_field< 4*CRn+3, 4*CRn+3 > { }; - -// Immediates -typedef bit_field< 16, 31 > UIMM_field; -typedef bit_field< 21, 25 > MB_field; -typedef bit_field< 26, 30 > ME_field; -typedef bit_field< 16, 20 > SH_field; - -// XER register fields -typedef bit_field< 0, 0 > XER_SO_field; -typedef bit_field< 1, 1 > XER_OV_field; -typedef bit_field< 2, 2 > XER_CA_field; -#endif -#undef CA -#define CA XER_CA_field::mask() -#undef OV -#define OV XER_OV_field::mask() -#undef SO -#define SO XER_SO_field::mask() - -// Flag: does the host support AltiVec instructions? -static bool has_altivec = true; - -// A 128-bit AltiVec register -typedef uint8 vector_t[16]; - -class aligned_vector_t { - struct { - vector_t v; - uint8 pad[16]; - } vs; -public: - aligned_vector_t() - { clear(); } - void clear() - { memset(addr(), 0, sizeof(vector_t)); } - void copy(vector_t const & vi, int n = sizeof(vector_t)) - { clear(); memcpy(addr(), &vi, n); } - vector_t *addr() const - { return (vector_t *)(((char *)&vs.v) + (16 - (((uintptr)&vs.v) % 16))); } - vector_t const & value() const - { return *addr(); } - vector_t & value() - { return *addr(); } -}; - -union vector_helper_t { - vector_t v; - uint8 b[16]; - uint16 h[8]; - uint32 w[4]; - float f[4]; -}; - -static void print_vector(vector_t const & v, char type = 'b') -{ - vector_helper_t x; - memcpy(&x.b, &v, sizeof(vector_t)); - - printf("{"); - switch (type) { - case 'b': - default: - for (int i = 0; i < 16; i++) { - if (i != 0) - printf(","); - printf(" %02x", x.b[i]); - } - break; - case 'h': - for (int i = 0; i < 8; i++) { - if (i != 0) - printf(","); - printf(" %04x", x.h[i]); - } - break; - case 'w': - for (int i = 0; i < 4; i++) { - if (i != 0) - printf(","); - printf(" %08x", x.w[i]); - } - break; - case 'f': - case 'e': // estimate result - case 'l': // estimate log2 result - for (int i = 0; i < 4; i++) { - x.w[i] = ntohl(x.w[i]); - if (i != 0) - printf(","); - printf(" %g", x.f[i]); - } - break; - } - printf(" }"); -} - -static inline bool do_float_equals(float a, float b, float tolerance) -{ - if (a == b) - return true; - - if (isnan(a) && isnan(b)) - return true; - - if (isinf(a) && isinf(b) && signbit(a) == signbit(b)) - return true; - - if ((b < (a + tolerance)) && (b > (a - tolerance))) - return true; - - return false; -} - -static inline bool float_equals(float a, float b) -{ - return do_float_equals(a, b, 3 * std::numeric_limits::epsilon()); -} - -static bool vector_equals(char type, vector_t const & a, vector_t const & b) -{ - // the vector is in ppc big endian format - float tolerance; - switch (type) { - case 'f': - tolerance = 3 * std::numeric_limits::epsilon(); - goto do_compare; - case 'l': // FIXME: this does not handle |x-1|<=1/8 case - tolerance = 1. / 32.; - goto do_compare; - case 'e': - tolerance = 1. / 4096.; - do_compare: - for (int i = 0; i < 4; i++) { - union { float f; uint32 i; } u, v; - u.i = ntohl(((uint32 *)&a)[i]); - v.i = ntohl(((uint32 *)&b)[i]); - if (!do_float_equals(u.f, v.f, tolerance)) - return false; - } - return true; - } - - return memcmp(&a, &b, sizeof(vector_t)) == 0; -} - -static bool vector_all_eq(char type, vector_t const & b) -{ - uint32 v; - vector_helper_t x; - memcpy(&x.v, &b, sizeof(vector_t)); - - bool all_eq = true; - switch (type) { - case 'b': - default: - v = x.b[0]; - for (int i = 1; all_eq && i < 16; i++) - if (x.b[i] != v) - all_eq = false; - break; - case 'h': - v = x.h[0]; - for (int i = 1; all_eq && i < 8; i++) - if (x.h[i] != v) - all_eq = false; - break; - case 'w': - case 'f': - v = x.w[0]; - for (int i = 1; all_eq && i < 4; i++) - if (x.w[i] != v) - all_eq = false; - break; - } - return all_eq; -} - -// Define PowerPC tester -class powerpc_test_cpu - : public powerpc_cpu_base -{ -#ifdef NATIVE_POWERPC - uint32 native_get_xer() const - { uint32 xer; asm volatile ("mfxer %0" : "=r" (xer)); return xer; } - - void native_set_xer(uint32 xer) const - { asm volatile ("mtxer %0" : : "r" (xer)); } - - uint32 native_get_cr() const - { uint32 cr; asm volatile ("mfcr %0" : "=r" (cr)); return cr; } - - void native_set_cr(uint32 cr) const - { asm volatile ("mtcr %0" : : "r" (cr)); } -#endif - - void flush_icache_range(uint32 *start, uint32 size) - { invalidate_cache_range(start, size); ppc_flush_icache_range(start, size); } - - void print_xer_flags(uint32 xer) const; - void print_flags(uint32 cr, uint32 xer, int crf = 0) const; - void execute(uint32 *code); - -public: - - powerpc_test_cpu(); - ~powerpc_test_cpu(); - - bool test(void); - - void set_results_file(FILE *fp) - { results_file = fp; } - -private: - - static const bool verbose = false; - uint32 tests, errors; - - // Results file for reference - FILE *results_file; - uint32 get32(); - void put32(uint32 v); - void get_vector(vector_t & v); - void put_vector(vector_t const & v); - - // Initial CR0, XER states - uint32 init_cr; - uint32 init_xer; - - // XER preset values to test with - std::vector xer_values; - void gen_xer_values(uint32 use_mask, uint32 set_mask); - - // Emulated registers IDs - enum { - RD = 3, - RA = 4, - RB = 5, - RC = 6, - VSCR = 7, - }; - - // Operands - enum { - __, - vD, vS, vA, vB, vC, vI, vN, - rD, rS, rA, rB, rC, - }; - - struct vector_test_t { - uint8 name[14]; - char type; - char op_type; - uint32 opcode; - uint8 operands[4]; - }; - - struct vector_value_t { - char type; - vector_t v; - }; - - static const uint32 reg_values[]; - static const uint32 imm_values[]; - static const uint32 msk_values[]; - static const vector_value_t vector_values[]; - static const vector_value_t vector_fp_values[]; - - void test_one_1(uint32 *code, const char *insn, uint32 a1, uint32 a2, uint32 a3, uint32 a0 = 0); - void test_one(uint32 *code, const char *insn, uint32 a1, uint32 a2, uint32 a3, uint32 a0 = 0); - void test_instruction_CNTLZ(const char *insn, uint32 opcode); - void test_instruction_RR___(const char *insn, uint32 opcode); - void test_instruction_RRI__(const char *insn, uint32 opcode); -#define test_instruction_RRK__ test_instruction_RRI__ - void test_instruction_RRS__(const char *insn, uint32 opcode); - void test_instruction_RRR__(const char *insn, uint32 opcode); - void test_instruction_RRRSH(const char *insn, uint32 opcode); - void test_instruction_RRIII(const char *insn, uint32 opcode); - void test_instruction_RRRII(const char *insn, uint32 opcode); - void test_instruction_CRR__(const char *insn, uint32 opcode); - void test_instruction_CRI__(const char *insn, uint32 opcode); -#define test_instruction_CRK__ test_instruction_CRI__ - void test_instruction_CCC__(const char *insn, uint32 opcode); - - void test_add(void); - void test_sub(void); - void test_mul(void); - void test_div(void); - void test_shift(void); - void test_rotate(void); - void test_logical(void); - void test_compare(void); - void test_cr_logical(void); - - void test_one_vector(uint32 *code, vector_test_t const & vt, uint8 *rA, uint8 *rB = 0, uint8 *rC = 0); - void test_one_vector(uint32 *code, vector_test_t const & vt, vector_t const *vA = 0, vector_t const *vB = 0, vector_t const *vC = 0) - { test_one_vector(code, vt, (uint8 *)vA, (uint8 *)vB, (uint8 *)vC); } - void test_vector_load(void); - void test_vector_load_for_shift(void); - void test_vector_arith(void); -}; - -powerpc_test_cpu::powerpc_test_cpu() - : powerpc_cpu_base(), results_file(NULL) -{ -#if ENABLE_MON - mon_init(); -#endif -} - -powerpc_test_cpu::~powerpc_test_cpu() -{ -#if ENABLE_MON - mon_exit(); -#endif -} - -uint32 powerpc_test_cpu::get32() -{ - uint32 v; - if (fread(&v, sizeof(v), 1, results_file) != 1) { - fprintf(stderr, "ERROR: unexpected end of results file\n"); - exit(EXIT_FAILURE); - } - return ntohl(v); -} - -void powerpc_test_cpu::put32(uint32 v) -{ - uint32 out = htonl(v); - if (fwrite(&out, sizeof(out), 1, results_file) != 1) { - fprintf(stderr, "could not write item to results file\n"); - exit(EXIT_FAILURE); - } -} - -void powerpc_test_cpu::get_vector(vector_t & v) -{ - if (fread(&v, sizeof(v), 1, results_file) != 1) { - fprintf(stderr, "ERROR: unexpected end of results file\n"); - exit(EXIT_FAILURE); - } -} - -void powerpc_test_cpu::put_vector(vector_t const & v) -{ - if (fwrite(&v, sizeof(v), 1, results_file) != 1) { - fprintf(stderr, "could not write vector to results file\n"); - exit(EXIT_FAILURE); - } -} - -void powerpc_test_cpu::execute(uint32 *code_p) -{ - static uint32 code[2]; - code[0] = htonl(POWERPC_BLRL); - code[1] = htonl(POWERPC_EMUL_OP); - -#ifndef NATIVE_POWERPC - const int n_func_words = 1024; - static uint32 func[n_func_words]; - static int old_i; - again: - int i = old_i; - for (int j = 0; ; j++, i++) { - if (i >= n_func_words) { - old_i = 0; - invalidate_cache(); - goto again; - } - uint32 opcode = code_p[j]; - func[i] = htonl(opcode); - if (opcode == POWERPC_BLR) - break; - } - code_p = &func[old_i]; - old_i = i; -#endif - - assert((uintptr)code_p <= UINT_MAX); - set_lr((uintptr)code_p); - - assert((uintptr)code <= UINT_MAX); - powerpc_cpu_base::execute((uintptr)code); -} - -void powerpc_test_cpu::gen_xer_values(uint32 use_mask, uint32 set_mask) -{ - const uint32 mask = use_mask | set_mask; - - // Always test with XER=0 - xer_values.clear(); - xer_values.push_back(0); - - // Iterate over XER fields, only handle CA, OV, SO - for (uint32 m = 0x80000000; m != 0; m >>= 1) { - if (m & (CA | OV | SO) & mask) { - const int n_xer_values = xer_values.size(); - for (int i = 0; i < n_xer_values; i++) - xer_values.push_back(xer_values[i] | m); - } - } - -#if 0 - printf("%d XER values\n", xer_values.size()); - for (int i = 0; i < xer_values.size(); i++) { - print_xer_flags(xer_values[i]); - printf("\n"); - } -#endif -} - -void powerpc_test_cpu::print_xer_flags(uint32 xer) const -{ - printf("%s,%s,%s", - (xer & XER_CA_field::mask() ? "CA" : "__"), - (xer & XER_OV_field::mask() ? "OV" : "__"), - (xer & XER_SO_field::mask() ? "SO" : "__")); -} - -void powerpc_test_cpu::print_flags(uint32 cr, uint32 xer, int crf) const -{ - cr = cr << (4 * crf); - printf("%s,%s,%s,%s,%s,%s", - (cr & CR_LT_field<0>::mask() ? "LT" : "__"), - (cr & CR_GT_field<0>::mask() ? "GT" : "__"), - (cr & CR_EQ_field<0>::mask() ? "EQ" : "__"), - (cr & CR_SO_field<0>::mask() ? "SO" : "__"), - (xer & XER_OV_field::mask() ? "OV" : "__"), - (xer & XER_CA_field::mask() ? "CA" : "__")); -} - -#define TEST_INSTRUCTION(FORMAT, NATIVE_OP, EMUL_OP) do { \ - printf("Testing " NATIVE_OP "\n"); \ - test_instruction_##FORMAT(NATIVE_OP, EMUL_OP); \ -} while (0) - -void powerpc_test_cpu::test_one(uint32 *code, const char *insn, uint32 a1, uint32 a2, uint32 a3, uint32 a0) -{ - // Iterate over test XER values as input - const int n_xer_values = xer_values.size(); - for (int i = 0; i < n_xer_values; i++) { - init_xer = xer_values[i]; - test_one_1(code, insn, a1, a2, a3, a0); - } - init_xer = 0; -} - -void powerpc_test_cpu::test_one_1(uint32 *code, const char *insn, uint32 a1, uint32 a2, uint32 a3, uint32 a0) -{ -#ifdef NATIVE_POWERPC - // Invoke native code - const uint32 save_xer = native_get_xer(); - const uint32 save_cr = native_get_cr(); - native_set_xer(init_xer); - native_set_cr(init_cr); - typedef uint32 (*func_t)(uint32, uint32, uint32); - func_t func = (func_t)code; - const uint32 native_rd = func(a0, a1, a2); - const uint32 native_xer = native_get_xer(); - const uint32 native_cr = native_get_cr(); - native_set_xer(save_xer); - native_set_cr(save_cr); - if (results_file) { - put32(native_rd); - put32(native_xer); - put32(native_cr); - } -#else - const uint32 native_rd = get32(); - const uint32 native_xer = get32(); - const uint32 native_cr = get32(); -#endif - - if (SKIP_ALU_OPS) - return; - - // Invoke emulated code - emul_set_xer(init_xer); - emul_set_cr(init_cr); - set_gpr(RD, a0); - set_gpr(RA, a1); - set_gpr(RB, a2); - execute(code); - const uint32 emul_rd = get_gpr(RD); - const uint32 emul_xer = emul_get_xer(); - const uint32 emul_cr = emul_get_cr(); - - ++tests; - - bool ok = native_rd == emul_rd - && native_xer == emul_xer - && native_cr == emul_cr; - - if (code[0] == POWERPC_MR(0, RA)) - code++; - - if (!ok) { - printf("FAIL: %s [%08x]\n", insn, code[0]); - errors++; - } - else if (verbose) { - printf("PASS: %s [%08x]\n", insn, code[0]); - } - - if (!ok || verbose) { -#if ENABLE_MON - disass_ppc(stdout, (uintptr)code, code[0]); -#endif -#define PRINT_OPERANDS(PREFIX) do { \ - printf(" %08x, %08x, %08x, %08x => %08x [", \ - a0, a1, a2, a3, PREFIX##_rd); \ - print_flags(PREFIX##_cr, PREFIX##_xer); \ - printf("]\n"); \ - } while (0) - PRINT_OPERANDS(native); - PRINT_OPERANDS(emul); -#undef PRINT_OPERANDS - } -} - -const uint32 powerpc_test_cpu::reg_values[] = { - 0x00000000, 0x10000000, 0x20000000, - 0x30000000, 0x40000000, 0x50000000, - 0x60000000, 0x70000000, 0x80000000, - 0x90000000, 0xa0000000, 0xb0000000, - 0xc0000000, 0xd0000000, 0xe0000000, - 0xf0000000, 0xfffffffd, 0xfffffffe, - 0xffffffff, 0x00000001, 0x00000002, - 0x00000003, 0x11111111, 0x22222222, - 0x33333333, 0x44444444, 0x55555555, - 0x66666666, 0x77777777, 0x88888888, - 0x99999999, 0xaaaaaaaa, 0xbbbbbbbb, - 0xcccccccc, 0xdddddddd, 0xeeeeeeee -}; - -const uint32 powerpc_test_cpu::imm_values[] = { - 0x0000, 0x1000, 0x2000, - 0x3000, 0x4000, 0x5000, - 0x6000, 0x7000, 0x8000, - 0x9000, 0xa000, 0xb000, - 0xc000, 0xd000, 0xe000, - 0xf000, 0xfffd, 0xfffe, - 0xffff, 0x0001, 0x0002, - 0x0003, 0x1111, 0x2222, - 0x3333, 0x4444, 0x5555, - 0x6666, 0x7777, 0x8888, - 0x9999, 0xaaaa, 0xbbbb, - 0xcccc, 0xdddd, 0xeeee -}; - -const uint32 powerpc_test_cpu::msk_values[] = { - 0, 1, -// 15, 16, 17, - 30, 31 -}; - -void powerpc_test_cpu::test_instruction_CNTLZ(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_values = sizeof(reg_values)/sizeof(reg_values[0]); - - code[0] = code[3] = opcode; // RD,RA,RB - rA_field::insert(code[3], 0); // RD,R0,RB - flush_icache_range(code, sizeof(code)); - - for (uint32 mask = 0x80000000; mask != 0; mask >>= 1) { - uint32 ra = mask; - test_one(&code[0], insn, ra, 0, 0); - test_one(&code[2], insn, ra, 0, 0); - } - // random values (including zero) - for (int i = 0; i < n_values; i++) { - uint32 ra = reg_values[i]; - test_one(&code[0], insn, ra, 0, 0); - test_one(&code[2], insn, ra, 0, 0); - } -} - -void powerpc_test_cpu::test_instruction_RR___(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_values = sizeof(reg_values)/sizeof(reg_values[0]); - - code[0] = code[3] = opcode; // RD,RA,RB - rA_field::insert(code[3], 0); // RD,R0,RB - flush_icache_range(code, sizeof(code)); - - for (int i = 0; i < n_values; i++) { - uint32 ra = reg_values[i]; - test_one(&code[0], insn, ra, 0, 0); - test_one(&code[2], insn, ra, 0, 0); - } -} - -void powerpc_test_cpu::test_instruction_RRI__(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_reg_values = sizeof(reg_values)/sizeof(reg_values[0]); - const int n_imm_values = sizeof(imm_values)/sizeof(imm_values[0]); - - for (int j = 0; j < n_imm_values; j++) { - const uint32 im = imm_values[j]; - uint32 op = opcode; - UIMM_field::insert(op, im); - code[0] = code[3] = op; // RD,RA,IM - rA_field::insert(code[3], 0); // RD,R0,IM - flush_icache_range(code, sizeof(code)); - for (int i = 0; i < n_reg_values; i++) { - const uint32 ra = reg_values[i]; - test_one(&code[0], insn, ra, im, 0); - test_one(&code[2], insn, ra, im, 0); - } - } -} - -void powerpc_test_cpu::test_instruction_RRS__(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_values = sizeof(reg_values)/sizeof(reg_values[0]); - - for (int j = 0; j < 32; j++) { - const uint32 sh = j; - SH_field::insert(opcode, sh); - code[0] = code[3] = opcode; - rA_field::insert(code[3], 0); - flush_icache_range(code, sizeof(code)); - for (int i = 0; i < n_values; i++) { - const uint32 ra = reg_values[i]; - test_one(&code[0], insn, ra, sh, 0); - } - } -} - -void powerpc_test_cpu::test_instruction_RRR__(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_values = sizeof(reg_values)/sizeof(reg_values[0]); - - code[0] = code[3] = opcode; // RD,RA,RB - rA_field::insert(code[3], 0); // RD,R0,RB - flush_icache_range(code, sizeof(code)); - - for (int i = 0; i < n_values; i++) { - const uint32 ra = reg_values[i]; - for (int j = 0; j < n_values; j++) { - const uint32 rb = reg_values[j]; - test_one(&code[0], insn, ra, rb, 0); - test_one(&code[2], insn, ra, rb, 0); - } - } -} - -void powerpc_test_cpu::test_instruction_RRRSH(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_values = sizeof(reg_values)/sizeof(reg_values[0]); - - code[0] = code[3] = opcode; // RD,RA,RB - rA_field::insert(code[3], 0); // RD,R0,RB - flush_icache_range(code, sizeof(code)); - - for (int i = 0; i < n_values; i++) { - const uint32 ra = reg_values[i]; - for (int j = 0; j <= 64; j++) { - const uint32 rb = j; - test_one(&code[0], insn, ra, rb, 0); - test_one(&code[2], insn, ra, rb, 0); - } - } -} - -void powerpc_test_cpu::test_instruction_RRIII(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_reg_values = sizeof(reg_values)/sizeof(reg_values[0]); - const int n_msk_values = sizeof(msk_values)/sizeof(msk_values[0]); - - for (int sh = 0; sh < 32; sh++) { - for (int i_mb = 0; i_mb < n_msk_values; i_mb++) { - const uint32 mb = msk_values[i_mb]; - for (int i_me = 0; i_me < n_msk_values; i_me++) { - const uint32 me = msk_values[i_me]; - SH_field::insert(opcode, sh); - MB_field::insert(opcode, mb); - ME_field::insert(opcode, me); - code[0] = opcode; - code[3] = opcode; - rA_field::insert(code[3], 0); - flush_icache_range(code, sizeof(code)); - for (int i = 0; i < n_reg_values; i++) { - const uint32 ra = reg_values[i]; - test_one(&code[0], insn, ra, sh, 0, 0); - test_one(&code[2], insn, ra, sh, 0, 0); - } - } - } - } -} - -void powerpc_test_cpu::test_instruction_RRRII(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_reg_values = sizeof(reg_values)/sizeof(reg_values[0]); - const int n_msk_values = sizeof(msk_values)/sizeof(msk_values[0]); - - for (int i_mb = 0; i_mb < n_msk_values; i_mb++) { - const uint32 mb = msk_values[i_mb]; - for (int i_me = 0; i_me < n_msk_values; i_me++) { - const uint32 me = msk_values[i_me]; - MB_field::insert(opcode, mb); - ME_field::insert(opcode, me); - code[0] = opcode; - code[3] = opcode; - rA_field::insert(code[3], 0); - flush_icache_range(code, sizeof(code)); - for (int i = 0; i < n_reg_values; i++) { - const uint32 ra = reg_values[i]; - for (int j = -1; j <= 33; j++) { - const uint32 rb = j; - test_one(&code[0], insn, ra, rb, 0, 0); - test_one(&code[2], insn, ra, rb, 0, 0); - } - } - } - } -} - -void powerpc_test_cpu::test_instruction_CRR__(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_values = sizeof(reg_values)/sizeof(reg_values[0]); - - for (int k = 0; k < 8; k++) { - crfD_field::insert(opcode, k); - code[0] = code[3] = opcode; // crfD,RA,RB - rA_field::insert(code[3], 0); // crfD,R0,RB - flush_icache_range(code, sizeof(code)); - for (int i = 0; i < n_values; i++) { - const uint32 ra = reg_values[i]; - for (int j = 0; j < n_values; j++) { - const uint32 rb = reg_values[j]; - test_one(&code[0], insn, ra, rb, 0); - test_one(&code[2], insn, ra, rb, 0); - } - } - } -} - -void powerpc_test_cpu::test_instruction_CRI__(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_BLR, - POWERPC_MR(0, RA), POWERPC_ILLEGAL, POWERPC_BLR - }; - - // Input values - const int n_reg_values = sizeof(reg_values)/sizeof(reg_values[0]); - const int n_imm_values = sizeof(imm_values)/sizeof(imm_values[0]); - - for (int k = 0; k < 8; k++) { - crfD_field::insert(opcode, k); - for (int j = 0; j < n_imm_values; j++) { - const uint32 im = imm_values[j]; - UIMM_field::insert(opcode, im); - code[0] = code[3] = opcode; // crfD,RA,SIMM - rA_field::insert(code[3], 0); // crfD,R0,SIMM - flush_icache_range(code, sizeof(code)); - for (int i = 0; i < n_reg_values; i++) { - const uint32 ra = reg_values[i]; - test_one(&code[0], insn, ra, im, 0); - test_one(&code[2], insn, ra, im, 0); - } - } - } -} - -void powerpc_test_cpu::test_instruction_CCC__(const char *insn, uint32 opcode) -{ - // Test code - static uint32 code[] = { - POWERPC_ILLEGAL, POWERPC_MFCR(RD), POWERPC_BLR, - }; - - const uint32 saved_cr = init_cr; - crbD_field::insert(opcode, 0); - - // Loop over crbA=[4-7] (crf1), crbB=[28-31] (crf7) - for (int crbA = 4; crbA <= 7; crbA++) { - crbA_field::insert(opcode, crbA); - for (int crbB = 28; crbB <= 31; crbB++) { - crbB_field::insert(opcode, crbB); - code[0] = opcode; - flush_icache_range(code, sizeof(code)); - // Generate CR values for (crf1, crf7) - uint32 cr = 0; - for (int i = 0; i < 16; i++) { - CR_field<1>::insert(cr, i); - for (int j = 0; j < 16; j++) { - CR_field<7>::insert(cr, j); - init_cr = cr; - test_one(&code[0], insn, init_cr, 0, 0); - } - } - } - } - init_cr = saved_cr; -} - -void powerpc_test_cpu::test_add(void) -{ -#if TEST_ADD - gen_xer_values(0, 0); - TEST_INSTRUCTION(RRI__,"addi", _D (14,RD,RA,00)); - TEST_INSTRUCTION(RRI__,"addis", _D (15,RD,RA,00)); - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRR__,"add", _XO(31,RD,RA,RB,0,266,0)); - TEST_INSTRUCTION(RRR__,"add.", _XO(31,RD,RA,RB,0,266,1)); - gen_xer_values(0, SO|OV); - TEST_INSTRUCTION(RRR__,"addo", _XO(31,RD,RA,RB,1,266,0)); - TEST_INSTRUCTION(RRR__,"addo." , _XO(31,RD,RA,RB,1,266,1)); - gen_xer_values(0, SO|CA); - TEST_INSTRUCTION(RRR__,"addc", _XO(31,RD,RA,RB,0, 10,0)); - TEST_INSTRUCTION(RRR__,"addc.", _XO(31,RD,RA,RB,0, 10,1)); - TEST_INSTRUCTION(RRI__,"addic", _D (12,RD,RA,00)); - TEST_INSTRUCTION(RRI__,"addic.", _D (13,RD,RA,00)); - gen_xer_values(0, SO|CA|OV); - TEST_INSTRUCTION(RRR__,"addco", _XO(31,RD,RA,RB,1, 10,0)); - TEST_INSTRUCTION(RRR__,"addco.", _XO(31,RD,RA,RB,1, 10,1)); - gen_xer_values(CA, SO|CA); - TEST_INSTRUCTION(RRR__,"adde", _XO(31,RD,RA,RB,0,138,0)); - TEST_INSTRUCTION(RRR__,"adde.", _XO(31,RD,RA,RB,0,138,1)); - TEST_INSTRUCTION(RR___,"addme", _XO(31,RD,RA,00,0,234,0)); - TEST_INSTRUCTION(RR___,"addme.", _XO(31,RD,RA,00,0,234,1)); - TEST_INSTRUCTION(RR___,"addze", _XO(31,RD,RA,00,0,202,0)); - TEST_INSTRUCTION(RR___,"addze.", _XO(31,RD,RA,00,0,202,1)); - gen_xer_values(CA, SO|CA|OV); - TEST_INSTRUCTION(RRR__,"addeo", _XO(31,RD,RA,RB,1,138,0)); - TEST_INSTRUCTION(RRR__,"addeo.", _XO(31,RD,RA,RB,1,138,1)); - TEST_INSTRUCTION(RR___,"addmeo", _XO(31,RD,RA,00,1,234,0)); - TEST_INSTRUCTION(RR___,"addmeo.", _XO(31,RD,RA,00,1,234,1)); - TEST_INSTRUCTION(RR___,"addzeo", _XO(31,RD,RA,00,1,202,0)); - TEST_INSTRUCTION(RR___,"addzeo.", _XO(31,RD,RA,00,1,202,1)); -#endif -} - -void powerpc_test_cpu::test_sub(void) -{ -#if TEST_SUB - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRR__,"subf", _XO(31,RD,RA,RB,0, 40,0)); - TEST_INSTRUCTION(RRR__,"subf.", _XO(31,RD,RA,RB,0, 40,1)); - gen_xer_values(0, SO|OV); - TEST_INSTRUCTION(RRR__,"subfo", _XO(31,RD,RA,RB,1, 40,0)); - TEST_INSTRUCTION(RRR__,"subfo.", _XO(31,RD,RA,RB,1, 40,1)); - gen_xer_values(0, SO|CA); - TEST_INSTRUCTION(RRR__,"subfc", _XO(31,RD,RA,RB,0, 8,0)); - TEST_INSTRUCTION(RRR__,"subfc.", _XO(31,RD,RA,RB,0, 8,1)); - gen_xer_values(0, SO|CA|OV); - TEST_INSTRUCTION(RRR__,"subfco", _XO(31,RD,RA,RB,1, 8,0)); - TEST_INSTRUCTION(RRR__,"subfco.", _XO(31,RD,RA,RB,1, 8,1)); - gen_xer_values(0, CA); - TEST_INSTRUCTION(RRI__,"subfic", _D ( 8,RD,RA,00)); - gen_xer_values(CA, SO|CA); - TEST_INSTRUCTION(RRR__,"subfe", _XO(31,RD,RA,RB,0,136,0)); - TEST_INSTRUCTION(RRR__,"subfe.", _XO(31,RD,RA,RB,0,136,1)); - TEST_INSTRUCTION(RR___,"subfme", _XO(31,RD,RA,00,0,232,0)); - TEST_INSTRUCTION(RR___,"subfme.", _XO(31,RD,RA,00,0,232,1)); - TEST_INSTRUCTION(RR___,"subfze", _XO(31,RD,RA,00,0,200,0)); - TEST_INSTRUCTION(RR___,"subfze.", _XO(31,RD,RA,00,0,200,1)); - gen_xer_values(CA, SO|CA|OV); - TEST_INSTRUCTION(RRR__,"subfeo", _XO(31,RD,RA,RB,1,136,0)); - TEST_INSTRUCTION(RRR__,"subfeo.", _XO(31,RD,RA,RB,1,136,1)); - TEST_INSTRUCTION(RR___,"subfmeo", _XO(31,RD,RA,00,1,232,0)); - TEST_INSTRUCTION(RR___,"subfmeo.", _XO(31,RD,RA,00,1,232,1)); - TEST_INSTRUCTION(RR___,"subfzeo", _XO(31,RD,RA,00,1,200,0)); - TEST_INSTRUCTION(RR___,"subfzeo.", _XO(31,RD,RA,00,1,200,1)); -#endif -} - -void powerpc_test_cpu::test_mul(void) -{ -#if TEST_MUL - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRR__,"mulhw", _XO(31,RD,RA,RB,0, 75,0)); - TEST_INSTRUCTION(RRR__,"mulhw.", _XO(31,RD,RA,RB,0, 75,1)); - TEST_INSTRUCTION(RRR__,"mulhwu", _XO(31,RD,RA,RB,0, 11,0)); - TEST_INSTRUCTION(RRR__,"mulhwu.", _XO(31,RD,RA,RB,0, 11,1)); - TEST_INSTRUCTION(RRI__,"mulli", _D ( 7,RD,RA,00)); - TEST_INSTRUCTION(RRR__,"mullw", _XO(31,RD,RA,RB,0,235,0)); - TEST_INSTRUCTION(RRR__,"mullw.", _XO(31,RD,RA,RB,0,235,1)); - gen_xer_values(0, SO|OV); - TEST_INSTRUCTION(RRR__,"mullwo", _XO(31,RD,RA,RB,1,235,0)); - TEST_INSTRUCTION(RRR__,"mullwo.", _XO(31,RD,RA,RB,1,235,1)); -#endif -} - -void powerpc_test_cpu::test_div(void) -{ -#if TEST_DIV - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRR__,"divw", _XO(31,RD,RA,RB,0,491,0)); - TEST_INSTRUCTION(RRR__,"divw.", _XO(31,RD,RA,RB,0,491,1)); - TEST_INSTRUCTION(RRR__,"divwu", _XO(31,RD,RA,RB,0,459,0)); - TEST_INSTRUCTION(RRR__,"divwu.", _XO(31,RD,RA,RB,0,459,1)); - gen_xer_values(0, SO|OV); - TEST_INSTRUCTION(RRR__,"divwo", _XO(31,RD,RA,RB,1,491,0)); - TEST_INSTRUCTION(RRR__,"divwo.", _XO(31,RD,RA,RB,1,491,1)); - TEST_INSTRUCTION(RRR__,"divwuo", _XO(31,RD,RA,RB,1,459,0)); - TEST_INSTRUCTION(RRR__,"divwuo.", _XO(31,RD,RA,RB,1,459,1)); -#endif -} - -void powerpc_test_cpu::test_logical(void) -{ -#if TEST_LOGICAL - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRR__,"and", _X (31,RA,RD,RB,28,0)); - TEST_INSTRUCTION(RRR__,"and.", _X (31,RA,RD,RB,28,1)); - TEST_INSTRUCTION(RRR__,"andc", _X (31,RA,RD,RB,60,0)); - TEST_INSTRUCTION(RRR__,"andc.", _X (31,RA,RD,RB,60,1)); - TEST_INSTRUCTION(RRK__,"andi.", _D (28,RA,RD,00)); - TEST_INSTRUCTION(RRK__,"andis.", _D (29,RA,RD,00)); - TEST_INSTRUCTION(CNTLZ,"cntlzw", _X (31,RA,RD,00,26,0)); - TEST_INSTRUCTION(CNTLZ,"cntlzw.", _X (31,RA,RD,00,26,1)); - TEST_INSTRUCTION(RRR__,"eqv", _X (31,RA,RD,RB,284,0)); - TEST_INSTRUCTION(RRR__,"eqv.", _X (31,RA,RD,RB,284,1)); - TEST_INSTRUCTION(RR___,"extsb", _X (31,RA,RD,00,954,0)); - TEST_INSTRUCTION(RR___,"extsb.", _X (31,RA,RD,00,954,1)); - TEST_INSTRUCTION(RR___,"extsh", _X (31,RA,RD,00,922,0)); - TEST_INSTRUCTION(RR___,"extsh.", _X (31,RA,RD,00,922,1)); - TEST_INSTRUCTION(RRR__,"nand", _X (31,RA,RD,RB,476,0)); - TEST_INSTRUCTION(RRR__,"nand.", _X (31,RA,RD,RB,476,1)); - TEST_INSTRUCTION(RR___,"neg", _XO(31,RD,RA,RB,0,104,0)); - TEST_INSTRUCTION(RR___,"neg.", _XO(31,RD,RA,RB,0,104,1)); - TEST_INSTRUCTION(RRR__,"nor", _X (31,RA,RD,RB,124,0)); - TEST_INSTRUCTION(RRR__,"nor.", _X (31,RA,RD,RB,124,1)); - TEST_INSTRUCTION(RRR__,"or", _X (31,RA,RD,RB,444,0)); - TEST_INSTRUCTION(RRR__,"or.", _X (31,RA,RD,RB,444,1)); - TEST_INSTRUCTION(RRR__,"orc", _X (31,RA,RD,RB,412,0)); - TEST_INSTRUCTION(RRR__,"orc.", _X (31,RA,RD,RB,412,1)); - TEST_INSTRUCTION(RRK__,"ori", _D (24,RA,RD,00)); - TEST_INSTRUCTION(RRK__,"oris", _D (25,RA,RD,00)); - TEST_INSTRUCTION(RRR__,"xor", _X (31,RA,RD,RB,316,0)); - TEST_INSTRUCTION(RRR__,"xor.", _X (31,RA,RD,RB,316,1)); - TEST_INSTRUCTION(RRK__,"xori", _D (26,RA,RD,00)); - TEST_INSTRUCTION(RRK__,"xoris", _D (27,RA,RD,00)); - gen_xer_values(0, SO|OV); - TEST_INSTRUCTION(RR___,"nego", _XO(31,RD,RA,RB,1,104,0)); - TEST_INSTRUCTION(RR___,"nego.", _XO(31,RD,RA,RB,1,104,1)); -#endif -} - -void powerpc_test_cpu::test_shift(void) -{ -#if TEST_SHIFT - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRRSH,"slw", _X (31,RA,RD,RB, 24,0)); - TEST_INSTRUCTION(RRRSH,"slw.", _X (31,RA,RD,RB, 24,1)); - TEST_INSTRUCTION(RRRSH,"sraw", _X (31,RA,RD,RB,792,0)); - TEST_INSTRUCTION(RRRSH,"sraw.", _X (31,RA,RD,RB,792,1)); - TEST_INSTRUCTION(RRS__,"srawi", _X (31,RA,RD,00,824,0)); - TEST_INSTRUCTION(RRS__,"srawi.", _X (31,RA,RD,00,824,1)); - TEST_INSTRUCTION(RRRSH,"srw", _X (31,RA,RD,RB,536,0)); - TEST_INSTRUCTION(RRRSH,"srw.", _X (31,RA,RD,RB,536,1)); -#endif -} - -void powerpc_test_cpu::test_rotate(void) -{ -#if TEST_ROTATE - gen_xer_values(0, SO); - TEST_INSTRUCTION(RRIII,"rlwimi", _M (20,RA,RD,00,00,00,0)); - TEST_INSTRUCTION(RRIII,"rlwimi.", _M (20,RA,RD,00,00,00,1)); - TEST_INSTRUCTION(RRIII,"rlwinm", _M (21,RA,RD,00,00,00,0)); - TEST_INSTRUCTION(RRIII,"rlwinm.", _M (21,RA,RD,00,00,00,1)); - TEST_INSTRUCTION(RRRII,"rlwnm", _M (23,RA,RD,RB,00,00,0)); - TEST_INSTRUCTION(RRRII,"rlwnm.", _M (23,RA,RD,RB,00,00,1)); -#endif -} - -void powerpc_test_cpu::test_compare(void) -{ -#if TEST_COMPARE - gen_xer_values(0, SO); - TEST_INSTRUCTION(CRR__,"cmp", _X (31,00,RA,RB,000,0)); - TEST_INSTRUCTION(CRI__,"cmpi", _D (11,00,RA,00)); - TEST_INSTRUCTION(CRR__,"cmpl", _X (31,00,RA,RB, 32,0)); - TEST_INSTRUCTION(CRK__,"cmpli", _D (10,00,RA,00)); -#endif -} - -void powerpc_test_cpu::test_cr_logical(void) -{ -#if TEST_CR_LOGICAL - gen_xer_values(0, SO); - TEST_INSTRUCTION(CCC__,"crand", _X (19,00,00,00,257,0)); - TEST_INSTRUCTION(CCC__,"crandc", _X (19,00,00,00,129,0)); - TEST_INSTRUCTION(CCC__,"creqv", _X (19,00,00,00,289,0)); - TEST_INSTRUCTION(CCC__,"crnand", _X (19,00,00,00,225,0)); - TEST_INSTRUCTION(CCC__,"crnor", _X (19,00,00,00, 33,0)); - TEST_INSTRUCTION(CCC__,"cror", _X (19,00,00,00,449,0)); - TEST_INSTRUCTION(CCC__,"crorc", _X (19,00,00,00,417,0)); - TEST_INSTRUCTION(CCC__,"crxor", _X (19,00,00,00,193,0)); -#endif -} - -// Template-generated vector values -const powerpc_test_cpu::vector_value_t powerpc_test_cpu::vector_values[] = { - {'w',{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - {'w',{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}}, - {'w',{0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02}}, - {'w',{0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03}}, - {'w',{0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}}, - {'w',{0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05}}, - {'w',{0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06}}, - {'w',{0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07}}, - {'w',{0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08}}, - {'w',{0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}}, - {'w',{0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, - {'w',{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}}, - {'w',{0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28}}, - {'w',{0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30}}, - {'w',{0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38}}, - {'w',{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40}}, - {'w',{0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48}}, - {'w',{0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50}}, - {'w',{0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58}}, - {'w',{0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60}}, - {'w',{0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68}}, - {'w',{0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70}}, - {'w',{0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78}}, - {'w',{0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00}}, - {'w',{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}}, - {'w',{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}}, - {'w',{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {'w',{0x11,0x11,0x11,0x11,0x22,0x22,0x22,0x22,0x33,0x33,0x33,0x33,0x44,0x44,0x44,0x44}}, - {'w',{0x88,0x88,0x88,0x88,0x77,0x77,0x77,0x77,0x66,0x66,0x66,0x66,0x55,0x55,0x55,0x55}}, - {'w',{0x99,0x99,0x99,0x99,0xaa,0xaa,0xaa,0xaa,0xbb,0xbb,0xbb,0xbb,0xcc,0xcc,0xcc,0xcc}}, - {'w',{0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xee,0xee,0xee,0xee,0xdd,0xdd,0xdd,0xdd}}, - {'w',{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}}, - {'h',{0x00,0x00,0x11,0x11,0x22,0x22,0x33,0x33,0x44,0x44,0x55,0x55,0x66,0x66,0x77,0x77}}, - {'h',{0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08}}, - {'h',{0x00,0x16,0x00,0x15,0x00,0x14,0x00,0x13,0x00,0x12,0x00,0x10,0x00,0x10,0x00,0x09}}, - {'b',{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}}, - {'b',{0xff,0xee,0xdd,0xcc,0xbb,0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00}}, - {'b',{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}}, - {'b',{0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}}, - {'b',{0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20}} -}; - -const powerpc_test_cpu::vector_value_t powerpc_test_cpu::vector_fp_values[] = { - {'f',{0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00}}, // -0, -0, -0, -0 - {'f',{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, // 0, 0, 0, 0 - {'f',{0xbf,0x80,0x00,0x00,0xbf,0x80,0x00,0x00,0xbf,0x80,0x00,0x00,0xbf,0x80,0x00,0x00}}, // -1, -1, -1, -1 - {'f',{0x3f,0x80,0x00,0x00,0x3f,0x80,0x00,0x00,0x3f,0x80,0x00,0x00,0x3f,0x80,0x00,0x00}}, // 1, 1, 1, 1 - {'f',{0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00}}, // -2, -2, -2, -2 - {'f',{0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00}}, // 2, 2, 2, 2 - {'f',{0xc0,0x00,0x00,0x00,0xbf,0x80,0x00,0x00,0x3f,0x80,0x00,0x00,0x40,0x00,0x00,0x00}}, // -2, -1, 1, 2 - {'f',{0xc0,0x40,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00}}, // -3, -0, 0, 3 - {'f',{0x40,0x00,0x00,0x00,0x3f,0x80,0x00,0x00,0xbf,0x80,0x00,0x00,0xc0,0x00,0x00,0x00}} // 2, 1, -1, -2 -}; - -void powerpc_test_cpu::test_one_vector(uint32 *code, vector_test_t const & vt, uint8 *rAp, uint8 *rBp, uint8 *rCp) -{ -#if TEST_VMX_OPS - static vector_t native_vD; - memset(&native_vD, 0, sizeof(native_vD)); - static vector_helper_t native_vSCR; - memset(&native_vSCR, 0, sizeof(native_vSCR)); - static aligned_vector_t dummy_vector; - dummy_vector.clear(); - if (!rAp) rAp = (uint8 *)dummy_vector.addr(); - if (!rBp) rBp = (uint8 *)dummy_vector.addr(); - if (!rCp) rCp = (uint8 *)dummy_vector.addr(); -#ifdef NATIVE_POWERPC - // Invoke native code - const uint32 save_cr = native_get_cr(); - native_set_cr(init_cr); - native_vSCR.w[3] = 0; - typedef void (*func_t)(uint8 *, uint8 *, uint8 *, uint8 *, uint8 *); - func_t func = (func_t)code; - func((uint8 *)&native_vD, rAp, rBp, rCp, native_vSCR.b); - const uint32 native_cr = native_get_cr(); - const uint32 native_vscr = native_vSCR.w[3]; - native_set_cr(save_cr); - if (results_file) { - put_vector(native_vD); - put32(native_cr); - put32(native_vscr); - } -#else - get_vector(native_vD); - const uint32 native_cr = get32(); - const uint32 native_vscr = get32(); -#endif - - if (SKIP_VMX_OPS) - return; - - // Invoke emulated code - static aligned_vector_t emul_vD; - emul_vD.clear(); - static aligned_vector_t emul_vSCR; - emul_vSCR.clear(); - emul_set_cr(init_cr); - set_gpr(RD, (uintptr)emul_vD.addr()); - set_gpr(RA, (uintptr)rAp); - set_gpr(RB, (uintptr)rBp); - set_gpr(RC, (uintptr)rCp); - set_gpr(VSCR, (uintptr)emul_vSCR.addr()); - execute(code); - vector_helper_t emul_vSCR_helper; - memcpy(&emul_vSCR_helper, emul_vSCR.addr(), sizeof(vector_t)); - const uint32 emul_cr = emul_get_cr(); - const uint32 emul_vscr = ntohl(emul_vSCR_helper.w[3]); - - ++tests; - - bool ok = vector_equals(vt.type, native_vD, emul_vD.value()) - && native_cr == emul_cr - && native_vscr == emul_vscr; - - if (!ok) { - printf("FAIL: %s [%08x]\n", vt.name, vt.opcode); - errors++; - } - else if (verbose) { - printf("PASS: %s [%08x]\n", vt.name, vt.opcode); - } - - if (!ok || verbose) { -#if ENABLE_MON - disass_ppc(stdout, (uintptr)code, vt.opcode); -#endif - char op_type = tolower(vt.op_type); - if (!op_type) - op_type = vt.type; -#define PRINT_OPERAND(N, vX, rX) \ - switch (vt.operands[N]) { \ - case vX: \ - printf(#vX " = "); \ - print_vector(*((vector_t *)rX##p)); \ - printf("\n"); \ - break; \ - case vI: \ - case vN: \ - printf(#vX " = %d\n", vX##_field::extract(vt.opcode)); \ - break; \ - case rX: \ - printf(#rX " = %08x", rX##p); \ - if (rX##p) switch (op_type) { \ - case 'b': printf(" [%02x]", *rX##p); break; \ - case 'h': printf(" [%04x]", *((uint16 *)rX##p)); break; \ - case 'w': printf(" [%08x]", *((uint32 *)rX##p)); break; \ - } \ - printf("\n"); \ - break; \ - } - PRINT_OPERAND(1, vA, rA); - PRINT_OPERAND(2, vB, rB); - PRINT_OPERAND(3, vC, rC); -#undef PRINT_OPERAND - printf("vD.N = "); - print_vector(native_vD, vt.type); - printf("\n"); - printf("vD.E = "); - print_vector(emul_vD.value(), vt.type); - printf("\n"); - printf("CR.N = %08x ; VSCR.N = %08x\n", native_cr, native_vscr); - printf("CR.E = %08x ; VSCR.E = %08x\n", emul_cr, emul_vscr); - } -#endif -} - -void powerpc_test_cpu::test_vector_load_for_shift(void) -{ -#if TEST_VMX_LOADSH - // Tested instructions - static const vector_test_t tests[] = { - { "lvsl", 'b', 0, _X (31,00,00,00, 6,0), { vD, rA, rB } }, - { "lvsr", 'b', 0, _X (31,00,00,00, 38,0), { vD, rA, rB } }, - }; - - // Code template - static uint32 code[] = { - POWERPC_MFSPR(12, 256), // mfvrsave r12 - _D(15,0,0,0x1000), // lis r0,0x1000 ([v3]) - POWERPC_MTSPR(0, 256), // mtvrsave r0 - POWERPC_LI(RA, 0), // li rB, - 0, // - POWERPC_STVX(RD, 0, RD), // stvx v3,r3(0) - POWERPC_MTSPR(12, 256), // mtvrsave r12 - POWERPC_BLR // blr - }; - - int i_opcode = -1; - const int n_instructions = sizeof(code) / sizeof(code[0]); - for (int i = 0; i < n_instructions; i++) { - if (code[i] == 0) { - i_opcode = i; - break; - } - } - assert(i_opcode != -1); - - const int n_elements = sizeof(tests) / sizeof(tests[0]); - for (int i = 0; i < n_elements; i++) { - vector_test_t const & vt = tests[i]; - code[i_opcode] = vt.opcode; - vD_field::insert(code[i_opcode], RD); - rA_field::insert(code[i_opcode], 00); - rB_field::insert(code[i_opcode], RA); - - printf("Testing %s\n", vt.name); - for (int j = 0; j < 32; j++) { - UIMM_field::insert(code[i_opcode - 1], j); - flush_icache_range(code, sizeof(code)); - test_one_vector(code, vt, (uint8 *)NULL); - } - } -#endif -} - -void powerpc_test_cpu::test_vector_load(void) -{ -#if TEST_VMX_LOAD - // Tested instructions - static const vector_test_t tests[] = { - { "lvebx", 'b', 0, _X (31,00,00,00, 7,0), { vD, rA, rB } }, - { "lvehx", 'h', 0, _X (31,00,00,00, 39,0), { vD, rA, rB } }, - { "lvewx", 'w', 0, _X (31,00,00,00, 71,0), { vD, rA, rB } } - }; - - // Code template - static uint32 code[] = { - POWERPC_MFSPR(12, 256), // mfvrsave r12 - _D(15,0,0,0x1000), // lis r0,0x1000 ([v3]) - POWERPC_MTSPR(0, 256), // mtvrsave r0 - POWERPC_LVX(RD, 0, RD), // lvx v3,r3(0) - 0, // - POWERPC_STVX(RD, 0, RD), // stvx v3,r3(0) - POWERPC_MTSPR(12, 256), // mtvrsave r12 - POWERPC_BLR // blr - }; - - int i_opcode = -1; - const int n_instructions = sizeof(code) / sizeof(code[0]); - for (int i = 0; i < n_instructions; i++) { - if (code[i] == 0) { - i_opcode = i; - break; - } - } - assert(i_opcode != -1); - - const int n_elements = sizeof(tests) / sizeof(tests[0]); - for (int i = 0; i < n_elements; i++) { - vector_test_t const & vt = tests[i]; - code[i_opcode] = vt.opcode; - vD_field::insert(code[i_opcode], RD); - rA_field::insert(code[i_opcode], 00); - rB_field::insert(code[i_opcode], RA); - flush_icache_range(code, sizeof(code)); - - printf("Testing %s\n", vt.name); - const int n_vector_values = sizeof(vector_values)/sizeof(vector_values[0]); - for (int j = 0; j < n_vector_values; j++) { - static aligned_vector_t av; - switch (vt.type) { - case 'b': - for (int k = 0; k < 16; k++) { - av.copy(*(vector_t *)((uint8 *)(&vector_values[j].v) + 1 * k), 16 - 1 * k); - test_one_vector(code, vt, av.addr()); - } - break; - case 'h': - for (int k = 0; k < 8; k++) { - av.copy(*(vector_t *)((uint8 *)(&vector_values[j].v) + 2 * k), 16 - 2 * k); - test_one_vector(code, vt, av.addr()); - } - break; - case 'w': - for (int k = 0; k < 4; k++) { - av.copy(*(vector_t *)((uint8 *)(&vector_values[j].v) + 4 * k), 16 - 4 * k); - test_one_vector(code, vt, av.addr()); - } - break; - } - } - } -#endif -} - -void powerpc_test_cpu::test_vector_arith(void) -{ -#if TEST_VMX_ARITH - // Tested instructions - static const vector_test_t tests[] = { - { "vaddcuw", 'w', 0 , _VX(04,RD,RA,RB, 384), { vD, vA, vB } }, - { "vaddfp", 'f', 0 , _VX(04,RD,RA,RB, 10), { vD, vA, vB } }, - { "vaddsbs", 'b', 0 , _VX(04,RD,RA,RB, 768), { vD, vA, vB } }, - { "vaddshs", 'h', 0 , _VX(04,RD,RA,RB, 832), { vD, vA, vB } }, - { "vaddsws", 'w', 0 , _VX(04,RD,RA,RB, 896), { vD, vA, vB } }, - { "vaddubm", 'b', 0 , _VX(04,RD,RA,RB, 0), { vD, vA, vB } }, - { "vaddubs", 'b', 0 , _VX(04,RD,RA,RB, 512), { vD, vA, vB } }, - { "vadduhm", 'h', 0 , _VX(04,RD,RA,RB, 64), { vD, vA, vB } }, - { "vadduhs", 'h', 0 , _VX(04,RD,RA,RB, 576), { vD, vA, vB } }, - { "vadduwm", 'w', 0 , _VX(04,RD,RA,RB, 128), { vD, vA, vB } }, - { "vadduws", 'w', 0 , _VX(04,RD,RA,RB, 640), { vD, vA, vB } }, - { "vand", 'w', 0 , _VX(04,RD,RA,RB,1028), { vD, vA, vB } }, - { "vandc", 'w', 0 , _VX(04,RD,RA,RB,1092), { vD, vA, vB } }, - { "vavgsb", 'b', 0 , _VX(04,RD,RA,RB,1282), { vD, vA, vB } }, - { "vavgsh", 'h', 0 , _VX(04,RD,RA,RB,1346), { vD, vA, vB } }, - { "vavgsw", 'w', 0 , _VX(04,RD,RA,RB,1410), { vD, vA, vB } }, - { "vavgub", 'b', 0 , _VX(04,RD,RA,RB,1026), { vD, vA, vB } }, - { "vavguh", 'h', 0 , _VX(04,RD,RA,RB,1090), { vD, vA, vB } }, - { "vavguw", 'w', 0 , _VX(04,RD,RA,RB,1154), { vD, vA, vB } }, - { "vcfsx", 'f', 'w', _VX(04,RD,00,RB, 842), { vD, vI, vB } }, - { "vcfux", 'f', 'w', _VX(04,RD,00,RB, 778), { vD, vI, vB } }, - { "vcmpbfp", 'w', 'f', _VXR(04,RD,RA,RB,966,0), { vD, vA, vB } }, - { "vcmpbfp.", 'w', 'f', _VXR(04,RD,RA,RB,966,1), { vD, vA, vB } }, - { "vcmpeqfp", 'w', 'f', _VXR(04,RD,RA,RB,198,0), { vD, vA, vB } }, - { "vcmpeqfp.", 'w', 'f', _VXR(04,RD,RA,RB,198,1), { vD, vA, vB } }, - { "vcmpequb", 'b', 0 , _VXR(04,RD,RA,RB, 6,0), { vD, vA, vB } }, - { "vcmpequb.", 'b', 0 , _VXR(04,RD,RA,RB, 6,1), { vD, vA, vB } }, - { "vcmpequh", 'h', 0 , _VXR(04,RD,RA,RB, 70,0), { vD, vA, vB } }, - { "vcmpequh.", 'h', 0 , _VXR(04,RD,RA,RB, 70,1), { vD, vA, vB } }, - { "vcmpequw", 'w', 0 , _VXR(04,RD,RA,RB,134,0), { vD, vA, vB } }, - { "vcmpequw.", 'w', 0 , _VXR(04,RD,RA,RB,134,1), { vD, vA, vB } }, - { "vcmpgefp", 'w', 'f', _VXR(04,RD,RA,RB,454,0), { vD, vA, vB } }, - { "vcmpgefp.", 'w', 'f', _VXR(04,RD,RA,RB,454,1), { vD, vA, vB } }, - { "vcmpgtfp", 'w', 'f', _VXR(04,RD,RA,RB,710,0), { vD, vA, vB } }, - { "vcmpgtfp.", 'w', 'f', _VXR(04,RD,RA,RB,710,1), { vD, vA, vB } }, - { "vcmpgtsb", 'b', 0 , _VXR(04,RD,RA,RB,774,0), { vD, vA, vB } }, - { "vcmpgtsb.", 'b', 0 , _VXR(04,RD,RA,RB,774,1), { vD, vA, vB } }, - { "vcmpgtsh", 'h', 0 , _VXR(04,RD,RA,RB,838,0), { vD, vA, vB } }, - { "vcmpgtsh.", 'h', 0 , _VXR(04,RD,RA,RB,838,1), { vD, vA, vB } }, - { "vcmpgtsw", 'w', 0 , _VXR(04,RD,RA,RB,902,0), { vD, vA, vB } }, - { "vcmpgtsw.", 'w', 0 , _VXR(04,RD,RA,RB,902,1), { vD, vA, vB } }, - { "vcmpgtub", 'b', 0 , _VXR(04,RD,RA,RB,518,0), { vD, vA, vB } }, - { "vcmpgtub.", 'b', 0 , _VXR(04,RD,RA,RB,518,1), { vD, vA, vB } }, - { "vcmpgtuh", 'h', 0 , _VXR(04,RD,RA,RB,582,0), { vD, vA, vB } }, - { "vcmpgtuh.", 'h', 0 , _VXR(04,RD,RA,RB,582,1), { vD, vA, vB } }, - { "vcmpgtuw", 'w', 0 , _VXR(04,RD,RA,RB,646,0), { vD, vA, vB } }, - { "vcmpgtuw.", 'w', 0 , _VXR(04,RD,RA,RB,646,1), { vD, vA, vB } }, - { "vctsxs", 'w', 'f', _VX(04,RD,00,RB, 970), { vD, vI, vB } }, - { "vctuxs", 'w', 'f', _VX(04,RD,00,RB, 906), { vD, vI, vB } }, - { "vexptefp", 'f', 0 , _VX(04,RD,00,RB, 394), { vD, __, vB } }, - { "vlogefp", 'l', 'f', _VX(04,RD,00,RB, 458), { vD, __, vB } }, - { "vmaddfp", 'f', 0 , _VA(04,RD,RA,RB,RC,46),{ vD, vA, vB, vC } }, - { "vmaxfp", 'f', 0 , _VX(04,RD,RA,RB,1034), { vD, vA, vB } }, - { "vmaxsb", 'b', 0 , _VX(04,RD,RA,RB, 258), { vD, vA, vB } }, - { "vmaxsh", 'h', 0 , _VX(04,RD,RA,RB, 322), { vD, vA, vB } }, - { "vmaxsw", 'w', 0 , _VX(04,RD,RA,RB, 386), { vD, vA, vB } }, - { "vmaxub", 'b', 0 , _VX(04,RD,RA,RB, 2), { vD, vA, vB } }, - { "vmaxuh", 'h', 0 , _VX(04,RD,RA,RB, 66), { vD, vA, vB } }, - { "vmaxuw", 'w', 0 , _VX(04,RD,RA,RB, 130), { vD, vA, vB } }, - { "vmhaddshs", 'h', 0 , _VA(04,RD,RA,RB,RC,32),{ vD, vA, vB, vC } }, - { "vmhraddshs", 'h', 0 , _VA(04,RD,RA,RB,RC,33),{ vD, vA, vB, vC } }, - { "vminfp", 'f', 0 , _VX(04,RD,RA,RB,1098), { vD, vA, vB } }, - { "vminsb", 'b', 0 , _VX(04,RD,RA,RB, 770), { vD, vA, vB } }, - { "vminsh", 'h', 0 , _VX(04,RD,RA,RB, 834), { vD, vA, vB } }, - { "vminsw", 'w', 0 , _VX(04,RD,RA,RB, 898), { vD, vA, vB } }, - { "vminub", 'b', 0 , _VX(04,RD,RA,RB, 514), { vD, vA, vB } }, - { "vminuh", 'h', 0 , _VX(04,RD,RA,RB, 578), { vD, vA, vB } }, - { "vminuw", 'w', 0 , _VX(04,RD,RA,RB, 642), { vD, vA, vB } }, - { "vmladduhm", 'h', 0 , _VA(04,RD,RA,RB,RC,34),{ vD, vA, vB, vC } }, - { "vmrghb", 'b', 0 , _VX(04,RD,RA,RB, 12), { vD, vA, vB } }, - { "vmrghh", 'h', 0 , _VX(04,RD,RA,RB, 76), { vD, vA, vB } }, - { "vmrghw", 'w', 0 , _VX(04,RD,RA,RB, 140), { vD, vA, vB } }, - { "vmrglb", 'b', 0 , _VX(04,RD,RA,RB, 268), { vD, vA, vB } }, - { "vmrglh", 'h', 0 , _VX(04,RD,RA,RB, 332), { vD, vA, vB } }, - { "vmrglw", 'w', 0 , _VX(04,RD,RA,RB, 396), { vD, vA, vB } }, - { "vmsummbm", 'b', 0 , _VA(04,RD,RA,RB,RC,37),{ vD, vA, vB, vC } }, - { "vmsumshm", 'h', 0 , _VA(04,RD,RA,RB,RC,40),{ vD, vA, vB, vC } }, - { "vmsumshs", 'h', 0 , _VA(04,RD,RA,RB,RC,41),{ vD, vA, vB, vC } }, - { "vmsumubm", 'b', 0 , _VA(04,RD,RA,RB,RC,36),{ vD, vA, vB, vC } }, - { "vmsumuhm", 'h', 0 , _VA(04,RD,RA,RB,RC,38),{ vD, vA, vB, vC } }, - { "vmsumuhs", 'h', 0 , _VA(04,RD,RA,RB,RC,39),{ vD, vA, vB, vC } }, - { "vmulesb", 'b', 0 , _VX(04,RD,RA,RB, 776), { vD, vA, vB } }, - { "vmulesh", 'h', 0 , _VX(04,RD,RA,RB, 840), { vD, vA, vB } }, - { "vmuleub", 'b', 0 , _VX(04,RD,RA,RB, 520), { vD, vA, vB } }, - { "vmuleuh", 'h', 0 , _VX(04,RD,RA,RB, 584), { vD, vA, vB } }, - { "vmulosb", 'b', 0 , _VX(04,RD,RA,RB, 264), { vD, vA, vB } }, - { "vmulosh", 'h', 0 , _VX(04,RD,RA,RB, 328), { vD, vA, vB } }, - { "vmuloub", 'b', 0 , _VX(04,RD,RA,RB, 8), { vD, vA, vB } }, - { "vmulouh", 'h', 0 , _VX(04,RD,RA,RB, 72), { vD, vA, vB } }, - { "vnmsubfp", 'f', 0 , _VA(04,RD,RA,RB,RC,47),{ vD, vA, vB, vC } }, - { "vnor", 'w', 0 , _VX(04,RD,RA,RB,1284), { vD, vA, vB } }, - { "vor", 'w', 0 , _VX(04,RD,RA,RB,1156), { vD, vA, vB } }, - { "vperm", 'b', 0 , _VA(04,RD,RA,RB,RC,43),{ vD, vA, vB, vC } }, - { "vpkpx", 'h', 0 , _VX(04,RD,RA,RB, 782), { vD, vA, vB } }, - { "vpkshss", 'b', 0 , _VX(04,RD,RA,RB, 398), { vD, vA, vB } }, - { "vpkshus", 'b', 0 , _VX(04,RD,RA,RB, 270), { vD, vA, vB } }, - { "vpkswss", 'h', 0 , _VX(04,RD,RA,RB, 462), { vD, vA, vB } }, - { "vpkswus", 'h', 0 , _VX(04,RD,RA,RB, 334), { vD, vA, vB } }, - { "vpkuhum", 'b', 0 , _VX(04,RD,RA,RB, 14), { vD, vA, vB } }, - { "vpkuhus", 'b', 0 , _VX(04,RD,RA,RB, 142), { vD, vA, vB } }, - { "vpkuwum", 'h', 0 , _VX(04,RD,RA,RB, 78), { vD, vA, vB } }, - { "vpkuwus", 'h', 0 , _VX(04,RD,RA,RB, 206), { vD, vA, vB } }, - { "vrefp", 'e', 'f', _VX(04,RD,00,RB, 266), { vD, __, vB } }, - { "vrfim", 'f', 0 , _VX(04,RD,00,RB, 714), { vD, __, vB } }, - { "vrfin", 'f', 0 , _VX(04,RD,00,RB, 522), { vD, __, vB } }, - { "vrfip", 'f', 0 , _VX(04,RD,00,RB, 650), { vD, __, vB } }, - { "vrfiz", 'f', 0 , _VX(04,RD,00,RB, 586), { vD, __, vB } }, - { "vrlb", 'b', 0 , _VX(04,RD,RA,RB, 4), { vD, vA, vB } }, - { "vrlh", 'h', 0 , _VX(04,RD,RA,RB, 68), { vD, vA, vB } }, - { "vrlw", 'w', 0 , _VX(04,RD,RA,RB, 132), { vD, vA, vB } }, - { "vrsqrtefp", 'e', 'f', _VX(04,RD,00,RB, 330), { vD, __, vB } }, - { "vsel", 'b', 0 , _VA(04,RD,RA,RB,RC,42),{ vD, vA, vB, vC } }, - { "vsl", 'b', 'B', _VX(04,RD,RA,RB, 452), { vD, vA, vB } }, - { "vslb", 'b', 0 , _VX(04,RD,RA,RB, 260), { vD, vA, vB } }, - { "vsldoi", 'b', 0 , _VA(04,RD,RA,RB,00,44),{ vD, vA, vB, vN } }, - { "vslh", 'h', 0 , _VX(04,RD,RA,RB, 324), { vD, vA, vB } }, - { "vslo", 'b', 0 , _VX(04,RD,RA,RB,1036), { vD, vA, vB } }, - { "vslw", 'w', 0 , _VX(04,RD,RA,RB, 388), { vD, vA, vB } }, - { "vspltb", 'b', 0 , _VX(04,RD,00,RB, 524), { vD, vI, vB } }, - { "vsplth", 'h', 0 , _VX(04,RD,00,RB, 588), { vD, vI, vB } }, - { "vspltisb", 'b', 0 , _VX(04,RD,00,00, 780), { vD, vI } }, - { "vspltish", 'h', 0 , _VX(04,RD,00,00, 844), { vD, vI } }, - { "vspltisw", 'w', 0 , _VX(04,RD,00,00, 908), { vD, vI } }, - { "vspltw", 'w', 0 , _VX(04,RD,00,RB, 652), { vD, vI, vB } }, - { "vsr", 'b', 'B', _VX(04,RD,RA,RB, 708), { vD, vA, vB } }, - { "vsrab", 'b', 0 , _VX(04,RD,RA,RB, 772), { vD, vA, vB } }, - { "vsrah", 'h', 0 , _VX(04,RD,RA,RB, 836), { vD, vA, vB } }, - { "vsraw", 'w', 0 , _VX(04,RD,RA,RB, 900), { vD, vA, vB } }, - { "vsrb", 'b', 0 , _VX(04,RD,RA,RB, 516), { vD, vA, vB } }, - { "vsrh", 'h', 0 , _VX(04,RD,RA,RB, 580), { vD, vA, vB } }, - { "vsro", 'b', 0 , _VX(04,RD,RA,RB,1100), { vD, vA, vB } }, - { "vsrw", 'w', 0 , _VX(04,RD,RA,RB, 644), { vD, vA, vB } }, - { "vsubcuw", 'w', 0 , _VX(04,RD,RA,RB,1408), { vD, vA, vB } }, - { "vsubfp", 'f', 0 , _VX(04,RD,RA,RB, 74), { vD, vA, vB } }, - { "vsubsbs", 'b', 0 , _VX(04,RD,RA,RB,1792), { vD, vA, vB } }, - { "vsubshs", 'h', 0 , _VX(04,RD,RA,RB,1856), { vD, vA, vB } }, - { "vsubsws", 'w', 0 , _VX(04,RD,RA,RB,1920), { vD, vA, vB } }, - { "vsububm", 'b', 0 , _VX(04,RD,RA,RB,1024), { vD, vA, vB } }, - { "vsububs", 'b', 0 , _VX(04,RD,RA,RB,1536), { vD, vA, vB } }, - { "vsubuhm", 'h', 0 , _VX(04,RD,RA,RB,1088), { vD, vA, vB } }, - { "vsubuhs", 'h', 0 , _VX(04,RD,RA,RB,1600), { vD, vA, vB } }, - { "vsubuwm", 'w', 0 , _VX(04,RD,RA,RB,1152), { vD, vA, vB } }, - { "vsubuws", 'w', 0 , _VX(04,RD,RA,RB,1664), { vD, vA, vB } }, - { "vsum2sws", 'w', 0 , _VX(04,RD,RA,RB,1672), { vD, vA, vB } }, - { "vsum4sbs", 'w', 0 , _VX(04,RD,RA,RB,1800), { vD, vA, vB } }, - { "vsum4shs", 'w', 0 , _VX(04,RD,RA,RB,1608), { vD, vA, vB } }, - { "vsum4ubs", 'w', 0 , _VX(04,RD,RA,RB,1544), { vD, vA, vB } }, - { "vsumsws", 'w', 0 , _VX(04,RD,RA,RB,1928), { vD, vA, vB } }, - { "vupkhpx", 'w', 0 , _VX(04,RD,00,RB, 846), { vD, __, vB } }, - { "vupkhsb", 'h', 0 , _VX(04,RD,00,RB, 526), { vD, __, vB } }, - { "vupkhsh", 'w', 0 , _VX(04,RD,00,RB, 590), { vD, __, vB } }, - { "vupklpx", 'w', 0 , _VX(04,RD,00,RB, 974), { vD, __, vB } }, - { "vupklsb", 'h', 0 , _VX(04,RD,00,RB, 654), { vD, __, vB } }, - { "vupklsh", 'w', 0 , _VX(04,RD,00,RB, 718), { vD, __, vB } }, - { "vxor", 'w', 0 , _VX(04,RD,RA,RB,1220), { vD, vA, vB } }, - }; - - // Code template - static uint32 code[] = { - POWERPC_MFSPR(12, 256), // mfvrsave r12 - _D(15,0,0,0x9e00), // lis r0,0x9e00 ([v0;v3-v6]) - POWERPC_MTSPR(0, 256), // mtvrsave r0 - POWERPC_LVX(RA, 0, RA), // lvx v4,r4(0) - POWERPC_LVX(RB, 0, RB), // lvx v5,r5(0) - POWERPC_LVX(RC, 0, RC), // lvx v6,r6(0) - POWERPC_LVX(0, 0, VSCR), // lvx v0,r7(0) - _VX(04,00,00,00,1604), // mtvscr v0 - 0, // v3,v4,v5 - _VX(04,00,00,00,1540), // mfvscr v0 - POWERPC_STVX(0, 0, VSCR), // stvx v0,r7(0) - POWERPC_STVX(RD, 0, RD), // stvx v3,r3(0) - POWERPC_MTSPR(12, 256), // mtvrsave r12 - POWERPC_BLR // blr - }; - - int i_opcode = -1; - const int n_instructions = sizeof(code) / sizeof(code[0]); - for (int i = 0; i < n_instructions; i++) { - if (code[i] == 0) { - i_opcode = i; - break; - } - } - assert(i_opcode != -1); - - const int n_elements = sizeof(tests) / sizeof(tests[0]); - for (int n = 0; n < n_elements; n++) { - vector_test_t vt = tests[n]; - code[i_opcode] = vt.opcode; - flush_icache_range(code, sizeof(code)); - - // Operand type - char op_type = vt.op_type; - if (!op_type) - op_type = vt.type; - - // Operand values - int n_vector_values; - const vector_value_t *vvp; - if (op_type == 'f') { - n_vector_values = sizeof(vector_fp_values)/sizeof(vector_fp_values[0]); - vvp = vector_fp_values; - } - else { - n_vector_values = sizeof(vector_values)/sizeof(vector_values[0]); - vvp = vector_values; - } - - printf("Testing %s\n", vt.name); - static aligned_vector_t avi, avj, avk; - if (vt.operands[1] == vA && vt.operands[2] == vB && vt.operands[3] == vC) { - for (int i = 0; i < n_vector_values; i++) { - avi.copy(vvp[i].v); - for (int j = 0; j < n_vector_values; j++) { - avj.copy(vvp[j].v); - for (int k = 0; k < n_vector_values; k++) { - avk.copy(vvp[k].v); - test_one_vector(code, vt, avi.addr(), avj.addr(), avk.addr()); - } - } - } - } - else if (vt.operands[1] == vA && vt.operands[2] == vB && vt.operands[3] == vN) { - for (int i = 0; i < 16; i++) { - vSH_field::insert(vt.opcode, i); - code[i_opcode] = vt.opcode; - flush_icache_range(code, sizeof(code)); - avi.copy(vvp[i].v); - for (int j = 0; j < n_vector_values; j++) { - avj.copy(vvp[j].v); - for (int k = 0; k < n_vector_values; k++) - test_one_vector(code, vt, avi.addr(), avj.addr()); - } - } - } - else if (vt.operands[1] == vA && vt.operands[2] == vB) { - for (int i = 0; i < n_vector_values; i++) { - avi.copy(vvp[i].v); - for (int j = 0; j < n_vector_values; j++) { - if (op_type == 'B') { - if (!vector_all_eq('b', vvp[j].v)) - continue; - } - avj.copy(vvp[j].v); - test_one_vector(code, vt, avi.addr(), avj.addr()); - } - } - } - else if (vt.operands[1] == vI && vt.operands[2] == vB) { - for (int i = 0; i < 32; i++) { - rA_field::insert(vt.opcode, i); - code[i_opcode] = vt.opcode; - flush_icache_range(code, sizeof(code)); - for (int j = 0; j < n_vector_values; j++) { - avj.copy(vvp[j].v); - test_one_vector(code, vt, NULL, avj.addr()); - } - } - } - else if (vt.operands[1] == vI) { - for (int i = 0; i < 32; i++) { - rA_field::insert(vt.opcode, i); - code[i_opcode] = vt.opcode; - flush_icache_range(code, sizeof(code)); - test_one_vector(code, vt); - } - } - else if (vt.operands[1] == __ && vt.operands[2] == vB) { - for (int i = 0; i < n_vector_values; i++) { - avi.copy(vvp[i].v); - test_one_vector(code, vt, NULL, avi.addr()); - } - } - else { - printf("ERROR: unhandled test case\n"); - abort(); - } - } -#endif -} - -// Illegal handler to catch out AltiVec instruction -#ifdef NATIVE_POWERPC -static sigjmp_buf env; - -static void sigill_handler(int sig) -{ - has_altivec = false; - siglongjmp(env, 1); -} -#endif - -bool powerpc_test_cpu::test(void) -{ - // Tests initialization - tests = errors = 0; - init_cr = init_xer = 0; - - // Execution ALU tests -#if TEST_ALU_OPS - test_add(); - test_sub(); - test_mul(); - test_div(); - test_shift(); - test_rotate(); - test_logical(); - test_compare(); - test_cr_logical(); -#endif - - // Execute VMX tests -#if TEST_VMX_OPS - if (has_altivec) { - test_vector_load_for_shift(); - test_vector_load(); - test_vector_arith(); - } -#endif - - printf("%u errors out of %u tests\n", errors, tests); - return errors == 0; -} - -int main(int argc, char *argv[]) -{ -#ifdef EMU_KHEPERIX - // Initialize VM system (predecode cache uses vm_acquire()) - vm_init(); -#endif - - FILE *fp = NULL; - powerpc_test_cpu *ppc = new powerpc_test_cpu; - - if (argc > 1) { - const char *arg = argv[1]; - if (strcmp(arg, "--jit") == 0) { - --argc; - argv[1] = argv[0]; - ++argv; - ppc->enable_jit(); - } - } - - if (argc > 1) { - const char *file = argv[1]; -#ifdef NATIVE_POWERPC - if ((fp = fopen(file, "wb")) == NULL) { - fprintf(stderr, "ERROR: can't open %s for writing\n", file); - return EXIT_FAILURE; - } -#else - if ((fp = fopen(file, "rb")) == NULL) { - fprintf(stderr, "ERROR: can't open %s for reading\n", file); - return EXIT_FAILURE; - } -#endif - ppc->set_results_file(fp); - - // Use a large enough buffer - static char buffer[4096]; - setvbuf(fp, buffer, _IOFBF, sizeof(buffer)); - } - - // We need a results file on non PowerPC platforms -#ifndef NATIVE_POWERPC - if (fp == NULL) { - fprintf(stderr, "ERROR: a results file for reference is required\n"); - return EXIT_FAILURE; - } -#endif - - // Check if host CPU supports AltiVec instructions - has_altivec = true; -#ifdef NATIVE_POWERPC - signal(SIGILL, sigill_handler); - if (!sigsetjmp(env, 1)) - asm volatile(".long 0x10000484"); // vor v0,v0,v0 - signal(SIGILL, SIG_DFL); -#endif - - bool ok = ppc->test(); - if (fp) fclose(fp); - delete ppc; - return !ok; -} diff --git a/SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.cpp b/SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.cpp deleted file mode 100644 index d7e2d012..00000000 --- a/SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * utils-cpuinfo.cpp - Processor capability information - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "utils/utils-cpuinfo.hpp" -#include "utils/utils-sentinel.hpp" - -// x86 CPU features -static uint32 x86_cpu_features = 0; - -enum { - HWCAP_I386_CMOV = 1 << 15, - HWCAP_I386_MMX = 1 << 23, - HWCAP_I386_SSE = 1 << 25, - HWCAP_I386_SSE2 = 1 << 26, - HWCAP_I386_EDX_FLAGS = (HWCAP_I386_CMOV|HWCAP_I386_MMX|HWCAP_I386_SSE|HWCAP_I386_SSE2), - HWCAP_I386_SSE3 = 1 << 0, - HWCAP_I386_SSSE3 = 1 << 9, - HWCAP_I386_SSE4_1 = 1 << 19, - HWCAP_I386_SSE4_2 = 1 << 20, - HWCAP_I386_ECX_FLAGS = (HWCAP_I386_SSE3|HWCAP_I386_SSSE3|HWCAP_I386_SSE4_1|HWCAP_I386_SSE4_2) -}; - -// Determine x86 CPU features -DEFINE_INIT_SENTINEL(init_x86_cpu_features); - -static void init_x86_cpu_features(void) -{ -#if defined(__i386__) || defined(__x86_64__) - unsigned int fl1, fl2; - -#ifndef __x86_64__ - /* See if we can use cpuid. On AMD64 we always can. */ - __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" - "pushl %0; popfl; pushfl; popl %0; popfl" - : "=&r" (fl1), "=&r" (fl2) - : "i" (0x00200000)); - if (((fl1 ^ fl2) & 0x00200000) == 0) - return; -#endif - - /* Host supports cpuid. See if cpuid gives capabilities, try - CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we - don't need their CPUID values here, and %ebx may be the PIC - register. */ -#ifdef __x86_64__ - __asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx" - : "=a" (fl1) : "0" (0) : "rdx", "cc"); -#else - __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx" - : "=a" (fl1) : "0" (0) : "edx", "cc"); -#endif - if (fl1 == 0) - return; - - /* Invoke CPUID(1), return %edx; caller can examine bits to - determine what's supported. */ -#ifdef __x86_64__ - __asm__ ("push %%rbx ; cpuid ; pop %%rbx" : "=c" (fl1), "=d" (fl2) : "a" (1) : "cc"); -#else - __asm__ ("push %%ebx ; cpuid ; pop %%ebx" : "=c" (fl1), "=d" (fl2) : "a" (1) : "cc"); -#endif - - x86_cpu_features = (fl1 & HWCAP_I386_ECX_FLAGS) | (fl2 & HWCAP_I386_EDX_FLAGS); -#endif -} - -// Check for x86 feature CMOV -bool cpuinfo_check_cmov(void) -{ - return x86_cpu_features & HWCAP_I386_CMOV; -} - -// Check for x86 feature MMX -bool cpuinfo_check_mmx(void) -{ - return x86_cpu_features & HWCAP_I386_MMX; -} - -// Check for x86 feature SSE -bool cpuinfo_check_sse(void) -{ - return x86_cpu_features & HWCAP_I386_SSE; -} - -// Check for x86 feature SSE2 -bool cpuinfo_check_sse2(void) -{ - return x86_cpu_features & HWCAP_I386_SSE2; -} - -// Check for x86 feature SSE3 -bool cpuinfo_check_sse3(void) -{ - return x86_cpu_features & HWCAP_I386_SSE3; -} - -// Check for x86 feature SSSE3 -bool cpuinfo_check_ssse3(void) -{ - return x86_cpu_features & HWCAP_I386_SSSE3; -} - -// Check for x86 feature SSE4.1 -bool cpuinfo_check_sse4_1(void) -{ - return x86_cpu_features & HWCAP_I386_SSE4_1; -} - -// Check for x86 feature SSE4_2 -bool cpuinfo_check_sse4_2(void) -{ - return x86_cpu_features & HWCAP_I386_SSE4_2; -} - -// PowerPC CPU features -static uint32 ppc_cpu_features = 0; - -enum { - HWCAP_PPC_ALTIVEC = 1 << 0 -}; - -// Determine PowerPC CPU features -DEFINE_INIT_SENTINEL(init_ppc_cpu_features); - -static void init_ppc_cpu_features(void) -{ -} - -// Check for ppc feature VMX (Altivec) -bool cpuinfo_check_altivec(void) -{ - return ppc_cpu_features & HWCAP_PPC_ALTIVEC; -} diff --git a/SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.hpp b/SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.hpp deleted file mode 100644 index 22bd621f..00000000 --- a/SheepShaver/src/kpx_cpu/src/utils/utils-cpuinfo.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * utils-cpuinfo.hpp - Processor capability information - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef UTILS_CPUINFO_H -#define UTILS_CPUINFO_H - -// Check for x86 feature CMOV -extern bool cpuinfo_check_cmov(void); - -// Check for x86 feature MMX -extern bool cpuinfo_check_mmx(void); - -// Check for x86 feature SSE -extern bool cpuinfo_check_sse(void); - -// Check for x86 feature SSE2 -extern bool cpuinfo_check_sse2(void); - -// Check for x86 feature SSE3 -extern bool cpuinfo_check_sse3(void); - -// Check for x86 feature SSSE3 -extern bool cpuinfo_check_ssse3(void); - -// Check for x86 feature SSE4.1 -extern bool cpuinfo_check_sse4_1(void); - -// Check for x86 feature SSE4_2 -extern bool cpuinfo_check_sse4_2(void); - -// Check for ppc feature VMX (Altivec) -extern bool cpuinfo_check_altivec(void); - -#endif /* UTILS_CPUINFO_H */ diff --git a/SheepShaver/src/kpx_cpu/src/utils/utils-sentinel.hpp b/SheepShaver/src/kpx_cpu/src/utils/utils-sentinel.hpp deleted file mode 100644 index b696f419..00000000 --- a/SheepShaver/src/kpx_cpu/src/utils/utils-sentinel.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * utils-sentinel.hpp - Helper functions for program initialization and termination - * - * Kheperix (C) 2003-2005 Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef UTILS_SENTINEL_H -#define UTILS_SENTINEL_H - -class program_sentinel { - void (*fini)(void); -public: - program_sentinel(void (*init_func)(void) = 0, void (*exit_func)(void) = 0) - : fini(exit_func) - { if (init_func) init_func(); } - ~program_sentinel() - { if (fini) fini(); } -}; - -#define DEFINE_INIT_SENTINEL(FUNCTION) \ -static void FUNCTION(void); \ -static program_sentinel g_program_init_sentinel__##FUNCTION(FUNCTION) - -#define DEFINE_EXIT_SENTINEL(FUNCTION) \ -static void FUNCTION(void); \ -static program_sentinel g_program_exit_sentinel__##FUNCTION(0, FUNCTION) - -#define DEFINE_PROG_SENTINEL(FUNCTION) \ -static void init_##FUNCTION(void); \ -static void exit_##FUNCTION(void); \ -static program_sentinel g_program_sentinel_##FUNCTION(init_##FUNCTION, exit_##FUNCTION) - -#endif /* UTILS_SENTINEL_H */ diff --git a/SheepShaver/src/macos_util.cpp b/SheepShaver/src/macos_util.cpp deleted file mode 100644 index 13b21397..00000000 --- a/SheepShaver/src/macos_util.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * macos_util.cpp - MacOS definitions/utility functions - * - * SheepShaver (C) Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "sony.h" -#include "disk.h" -#include "cdrom.h" -#include "xlowmem.h" -#include "emul_op.h" -#include "macos_util.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - - -// Function pointers -typedef long (*cu_ptr)(void *, uint32); -static uint32 cu_tvect = 0; -static inline long CallUniversal(void *arg1, uint32 arg2) -{ - return (long)CallMacOS2(cu_ptr, cu_tvect, arg1, arg2); -} -typedef int16 (*gsl_ptr)(char *, uint32, uint32, uint32 *, void **, char *); -static uint32 gsl_tvect = 0; -static inline int16 GetSharedLibrary(uintptr arg1, uint32 arg2, uint32 arg3, uintptr arg4, uintptr arg5, uintptr arg6) -{ - return (int16)CallMacOS6(gsl_ptr, gsl_tvect, (char *)arg1, arg2, arg3, (uint32 *)arg4, (void **)arg5, (char *)arg6); -} -typedef int16 (*fs_ptr)(uint32, char *, void **, uint32 *); -static uint32 fs_tvect = 0; -static inline int16 FindSymbol(uint32 arg1, uintptr arg2, uintptr arg3, uintptr arg4) -{ - return (int16)CallMacOS4(fs_ptr, fs_tvect, arg1, (char *)arg2, (void **)arg3, (uint32 **)arg4); -} -typedef int16 (*cc_ptr)(uint32 *); -static uint32 cc_tvect = 0; -static inline int16 CloseConnection(uint32 *arg1) -{ - return (int16)CallMacOS1(cc_ptr, cc_tvect, arg1); -} -typedef uint32 (*nps_ptr)(uint32); -static uint32 nps_tvect = 0; -static inline uint32 NewPtrSys(uint32 arg1) -{ - return CallMacOS1(nps_ptr, nps_tvect, arg1); -} -typedef void (*d_ptr)(uint32); -static uint32 d_tvect = 0; -static inline void DisposePtr(uint32 arg1) -{ - CallMacOS1(d_ptr, d_tvect, arg1); -} - - -/* - * Reset MacOS utilities - */ - -void MacOSUtilReset(void) -{ - cu_tvect = 0; - gsl_tvect = 0; - fs_tvect = 0; - cc_tvect = 0; -} - - -/* - * Enqueue QElem to list - */ - -void Enqueue(uint32 elem, uint32 list) -{ - WriteMacInt32(elem + qLink, 0); - if (!ReadMacInt32(list + qTail)) { - WriteMacInt32(list + qHead, elem); - WriteMacInt32(list + qTail, elem); - } else { - WriteMacInt32(ReadMacInt32(list + qTail) + qLink, elem); - WriteMacInt32(list + qTail, elem); - } -} - - -/* - * Find first free drive number, starting at num - */ - -static bool is_drive_number_free(int num) -{ - uint32 e = ReadMacInt32(0x308 + qHead); - while (e) { - uint32 d = e - dsQLink; - if ((int)ReadMacInt16(d + dsQDrive) == num) - return false; - e = ReadMacInt32(e + qLink); - } - return true; -} - -int FindFreeDriveNumber(int num) -{ - while (!is_drive_number_free(num)) - num++; - return num; -} - - -/* - * Mount volume with given file handle (call this function when you are unable to - * do automatic media change detection and the user has to press a special key - * or something to mount a volume; this function will check if there's really a - * volume in the drive with SysIsDiskInserted(); volumes which are present on startup - * are automatically mounted) - */ - -void MountVolume(void *fh) -{ - SonyMountVolume(fh) || DiskMountVolume(fh) || CDROMMountVolume(fh); -} - - -/* - * Calculate disk image file layout given file size and first 256 data bytes - */ - -void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) -{ - if (size == 419284 || size == 838484) { - // 400K/800K DiskCopy image, 84 byte header - start_byte = 84; - real_size = (size - 84) & ~0x1ff; - } else { - // 0..511 byte header - start_byte = size & 0x1ff; - real_size = size - start_byte; - } -} - - -/* - * Find symbol in shared library (using CFM) - * lib and sym must be Pascal strings! - */ - -uint32 FindLibSymbol(const char *lib_str, const char *sym_str) -{ - SheepVar32 conn_id = 0; - SheepVar32 main_addr = 0; - SheepArray<256> err; - WriteMacInt8(err.addr(), 0); - SheepVar32 sym_addr = 0; - SheepVar32 sym_class = 0; - - SheepString lib(lib_str); - SheepString sym(sym_str); - - D(bug("FindLibSymbol %s in %s...\n", sym.value()+1, lib.value()+1)); - - if (ReadMacInt32(XLM_RUN_MODE) == MODE_EMUL_OP) { - M68kRegisters r; - - // Find shared library - static const uint8 proc1_template[] = { - 0x55, 0x8f, // subq.l #2,a7 - 0x2f, 0x08, // move.l a0,-(a7) - 0x2f, 0x3c, 0x70, 0x77, 0x70, 0x63, // move.l #'pwpc',-(a7) - 0x2f, 0x3c, 0x00, 0x00, 0x00, 0x01, // move.l #kReferenceCFrag,-(a7) - 0x2f, 0x09, // move.l a1,-(a7) - 0x2f, 0x0a, // move.l a2,-(a7) - 0x2f, 0x0b, // move.l a3,-(a7) - 0x3f, 0x3c, 0x00, 0x01, // (GetSharedLibrary) - 0xaa, 0x5a, // CFMDispatch - 0x30, 0x1f, // move.w (a7)+,d0 - M68K_RTS >> 8, M68K_RTS & 0xff - }; - BUILD_SHEEPSHAVER_PROCEDURE(proc1); - r.a[0] = lib.addr(); - r.a[1] = conn_id.addr(); - r.a[2] = main_addr.addr(); - r.a[3] = err.addr(); - Execute68k(proc1, &r); - D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", (int16)r.d[0], conn_id.value(), main_addr.value())); - if (r.d[0]) - return 0; - - // Find symbol - static const uint8 proc2_template[] = { - 0x55, 0x8f, // subq.l #2,a7 - 0x2f, 0x00, // move.l d0,-(a7) - 0x2f, 0x08, // move.l a0,-(a7) - 0x2f, 0x09, // move.l a1,-(a7) - 0x2f, 0x0a, // move.l a2,-(a7) - 0x3f, 0x3c, 0x00, 0x05, // (FindSymbol) - 0xaa, 0x5a, // CFMDispatch - 0x30, 0x1f, // move.w (a7)+,d0 - M68K_RTS >> 8, M68K_RTS & 0xff - }; - BUILD_SHEEPSHAVER_PROCEDURE(proc2); - r.d[0] = conn_id.value(); - r.a[0] = sym.addr(); - r.a[1] = sym_addr.addr(); - r.a[2] = sym_class.addr(); - Execute68k(proc2, &r); - D(bug(" FindSymbol1: ret %d, sym_addr %p, sym_class %ld\n", (int16)r.d[0], sym_addr.value(), sym_class.value())); -//!! CloseConnection()? - if (r.d[0]) - return 0; - else - return sym_addr.value(); - - } else { - - if (GetSharedLibrary == NULL || FindSymbol == NULL) { - printf("FATAL: FindLibSymbol() called too early\n"); - return 0; - } - int16 res; - res = GetSharedLibrary(lib.addr(), FOURCC('p','w','p','c'), 1, conn_id.addr(), main_addr.addr(), err.addr()); - D(bug(" GetSharedLibrary: ret %d, connection ID %ld, main %p\n", res, conn_id.value(), main_addr.value())); - if (res) - return 0; - res = FindSymbol(conn_id.value(), sym.addr(), sym_addr.addr(), sym_class.addr()); - D(bug(" FindSymbol: ret %d, sym_addr %p, sym_class %ld\n", res, sym_addr.value(), sym_class.value())); -//!!?? CloseConnection(&conn_id); - if (res) - return 0; - else - return sym_addr.value(); - } -} - - -/* - * Find CallUniversalProc() TVector - */ - -void InitCallUniversalProc() -{ - cu_tvect = FindLibSymbol("\014InterfaceLib", "\021CallUniversalProc"); - D(bug("CallUniversalProc TVECT at %08lx\n", cu_tvect)); - if (cu_tvect == 0) { - printf("FATAL: Can't find CallUniversalProc()\n"); - QuitEmulator(); - } - - gsl_tvect = FindLibSymbol("\014InterfaceLib", "\020GetSharedLibrary"); - D(bug("GetSharedLibrary TVECT at %08lx\n", gsl_tvect)); - if (gsl_tvect == 0) { - printf("FATAL: Can't find GetSharedLibrary()\n"); - QuitEmulator(); - } - - fs_tvect = FindLibSymbol("\014InterfaceLib", "\012FindSymbol"); - D(bug("FindSymbol TVECT at %08lx\n", fs_tvect)); - if (fs_tvect == 0) { - printf("FATAL: Can't find FindSymbol()\n"); - QuitEmulator(); - } - - cc_tvect = FindLibSymbol("\014InterfaceLib", "\017CloseConnection"); - D(bug("CloseConnection TVECT at %08lx\n", cc_tvect)); - if (cc_tvect == 0) { - printf("FATAL: Can't find CloseConnection()\n"); - QuitEmulator(); - } - - nps_tvect = FindLibSymbol("\014InterfaceLib", "\011NewPtrSys"); - D(bug("NewPtrSys TVECT at %08lx\n", nps_tvect)); - if (nps_tvect == 0) { - printf("FATAL: Can't find NewPtrSys()\n"); - QuitEmulator(); - } - - d_tvect = FindLibSymbol("\014InterfaceLib", "\012DisposePtr"); - D(bug("DisposePtr TVECT at %08lx\n", d_tvect)); - if (d_tvect == 0) { - printf("FATAL: Can't find DisposePtr()\n"); - QuitEmulator(); - } -} - - -/* - * CallUniversalProc - */ - -long CallUniversalProc(void *upp, uint32 info) -{ - if (cu_tvect == 0) { - printf("FATAL: CallUniversalProc() called too early\n"); - return 0; - } - return CallUniversal(upp, info); -} - - -/* - * Convert time_t value to MacOS time (seconds since 1.1.1904) - */ - -uint32 TimeToMacTime(time_t t) -{ - // This code is taken from glibc 2.2 - - // Convert to number of seconds elapsed since 1-Jan-1904 - struct tm *local = localtime(&t); - const int TM_EPOCH_YEAR = 1900; - const int MAC_EPOCH_YEAR = 1904; - int a4 = ((local->tm_year + TM_EPOCH_YEAR) >> 2) - !(local->tm_year & 3); - int b4 = (MAC_EPOCH_YEAR >> 2) - !(MAC_EPOCH_YEAR & 3); - int a100 = a4 / 25 - (a4 % 25 < 0); - int b100 = b4 / 25 - (b4 % 25 < 0); - int a400 = a100 >> 2; - int b400 = b100 >> 2; - int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); - uint32 days = local->tm_yday + 365 * (local->tm_year - 4) + intervening_leap_days; - return local->tm_sec + 60 * (local->tm_min + 60 * (local->tm_hour + 24 * days)); -} - - -/* - * Memory allocators in MacOS system heap zone - */ - -uint32 Mac_sysalloc(uint32 size) -{ - return NewPtrSys(size); -} - -void Mac_sysfree(uint32 addr) -{ - DisposePtr(addr); -} diff --git a/SheepShaver/src/main.cpp b/SheepShaver/src/main.cpp deleted file mode 100644 index 1224fbe1..00000000 --- a/SheepShaver/src/main.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* - * main.cpp - ROM patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "main.h" -#include "version.h" -#include "prefs.h" -#include "prefs_editor.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "xlowmem.h" -#include "xpram.h" -#include "timer.h" -#include "adb.h" -#include "sony.h" -#include "disk.h" -#include "cdrom.h" -#include "scsi.h" -#include "video.h" -#include "audio.h" -#include "ether.h" -#include "serial.h" -#include "clip.h" -#include "extfs.h" -#include "sys.h" -#include "macos_util.h" -#include "rom_patches.h" -#include "user_strings.h" -#include "vm_alloc.h" -#include "sigsegv.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - -#ifdef ENABLE_MON -#include "mon.h" - -static uint32 sheepshaver_read_byte(uintptr adr) -{ - return ReadMacInt8(adr); -} - -static void sheepshaver_write_byte(uintptr adr, uint32 b) -{ - WriteMacInt8(adr, b); -} -#endif - - -/* - * Initialize everything, returns false on error - */ - -bool InitAll(const char *vmdir) -{ - // Load NVRAM - XPRAMInit(vmdir); - - // Load XPRAM default values if signature not found - if (XPRAM[0x130c] != 0x4e || XPRAM[0x130d] != 0x75 - || XPRAM[0x130e] != 0x4d || XPRAM[0x130f] != 0x63) { - D(bug("Loading XPRAM default values\n")); - memset(XPRAM + 0x1300, 0, 0x100); - XPRAM[0x130c] = 0x4e; // "NuMc" signature - XPRAM[0x130d] = 0x75; - XPRAM[0x130e] = 0x4d; - XPRAM[0x130f] = 0x63; - XPRAM[0x1301] = 0x80; // InternalWaitFlags = DynWait (don't wait for SCSI devices upon bootup) - XPRAM[0x1310] = 0xa8; // Standard PRAM values - XPRAM[0x1311] = 0x00; - XPRAM[0x1312] = 0x00; - XPRAM[0x1313] = 0x22; - XPRAM[0x1314] = 0xcc; - XPRAM[0x1315] = 0x0a; - XPRAM[0x1316] = 0xcc; - XPRAM[0x1317] = 0x0a; - XPRAM[0x131c] = 0x00; - XPRAM[0x131d] = 0x02; - XPRAM[0x131e] = 0x63; - XPRAM[0x131f] = 0x00; - XPRAM[0x1308] = 0x13; - XPRAM[0x1309] = 0x88; - XPRAM[0x130a] = 0x00; - XPRAM[0x130b] = 0xcc; - XPRAM[0x1376] = 0x00; // OSDefault = MacOS - XPRAM[0x1377] = 0x01; - XPRAM[0x138a] = 0x25; // Use PPC memory manager ("Modern Memory Manager") - } - - // Set boot volume - int16 i16 = PrefsFindInt32("bootdrive"); - XPRAM[0x1378] = i16 >> 8; - XPRAM[0x1379] = i16 & 0xff; - i16 = PrefsFindInt32("bootdriver"); - XPRAM[0x137a] = i16 >> 8; - XPRAM[0x137b] = i16 & 0xff; - - // Create BootGlobs at top of Mac memory - memset(RAMBaseHost + RAMSize - 4096, 0, 4096); - BootGlobsAddr = RAMBase + RAMSize - 0x1c; - WriteMacInt32(BootGlobsAddr - 5 * 4, RAMBase + RAMSize); // MemTop - WriteMacInt32(BootGlobsAddr + 0 * 4, RAMBase); // First RAM bank - WriteMacInt32(BootGlobsAddr + 1 * 4, RAMSize); - WriteMacInt32(BootGlobsAddr + 2 * 4, (uint32)-1); // End of bank table - - // Init thunks - if (!ThunksInit()) - return false; - - // Init drivers - SonyInit(); - DiskInit(); - CDROMInit(); - SCSIInit(); - - // Init external file system - ExtFSInit(); - - // Init ADB - ADBInit(); - - // Init audio - AudioInit(); - - // Init network - EtherInit(); - - // Init serial ports - SerialInit(); - - // Init Time Manager - TimerInit(); - - // Init clipboard - ClipInit(); - - // Init video - if (!VideoInit()) - return false; - - // Install ROM patches - if (!PatchROM()) { - ErrorAlert(GetString(STR_UNSUPPORTED_ROM_TYPE_ERR)); - return false; - } - - // Initialize Kernel Data - KernelData *kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE); - memset(kernel_data, 0, sizeof(KernelData)); - if (ROMType == ROMTYPE_NEWWORLD) { - uint32 of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32)); - Mac_memset(of_dev_tree, 0, 4 * sizeof(uint32)); - uint32 vector_lookup_tbl = SheepMem::Reserve(128); - uint32 vector_mask_tbl = SheepMem::Reserve(64); - memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80); - Mac_memset(vector_lookup_tbl, 0, 128); - Mac_memset(vector_mask_tbl, 0, 64); - kernel_data->v[0xb80 >> 2] = htonl(ROMBase); - kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree); // OF device tree base - kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl); - kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl); - kernel_data->v[0xb98 >> 2] = htonl(ROMBase); // OpenPIC base - kernel_data->v[0xbb0 >> 2] = htonl(0); // ADB base - kernel_data->v[0xc20 >> 2] = htonl(RAMSize); - kernel_data->v[0xc24 >> 2] = htonl(RAMSize); - kernel_data->v[0xc30 >> 2] = htonl(RAMSize); - kernel_data->v[0xc34 >> 2] = htonl(RAMSize); - kernel_data->v[0xc38 >> 2] = htonl(0x00010020); - kernel_data->v[0xc3c >> 2] = htonl(0x00200001); - kernel_data->v[0xc40 >> 2] = htonl(0x00010000); - kernel_data->v[0xc50 >> 2] = htonl(RAMBase); - kernel_data->v[0xc54 >> 2] = htonl(RAMSize); - kernel_data->v[0xf60 >> 2] = htonl(PVR); - kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed); // clock-frequency - kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed); // bus-frequency - kernel_data->v[0xf6c >> 2] = htonl(TimebaseSpeed); // timebase-frequency - } else if (ROMType == ROMTYPE_GOSSAMER) { - kernel_data->v[0xc80 >> 2] = htonl(RAMSize); - kernel_data->v[0xc84 >> 2] = htonl(RAMSize); - kernel_data->v[0xc90 >> 2] = htonl(RAMSize); - kernel_data->v[0xc94 >> 2] = htonl(RAMSize); - kernel_data->v[0xc98 >> 2] = htonl(0x00010020); - kernel_data->v[0xc9c >> 2] = htonl(0x00200001); - kernel_data->v[0xca0 >> 2] = htonl(0x00010000); - kernel_data->v[0xcb0 >> 2] = htonl(RAMBase); - kernel_data->v[0xcb4 >> 2] = htonl(RAMSize); - kernel_data->v[0xf60 >> 2] = htonl(PVR); - kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed); // clock-frequency - kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed); // bus-frequency - kernel_data->v[0xf6c >> 2] = htonl(TimebaseSpeed); // timebase-frequency - } else { - kernel_data->v[0xc80 >> 2] = htonl(RAMSize); - kernel_data->v[0xc84 >> 2] = htonl(RAMSize); - kernel_data->v[0xc90 >> 2] = htonl(RAMSize); - kernel_data->v[0xc94 >> 2] = htonl(RAMSize); - kernel_data->v[0xc98 >> 2] = htonl(0x00010020); - kernel_data->v[0xc9c >> 2] = htonl(0x00200001); - kernel_data->v[0xca0 >> 2] = htonl(0x00010000); - kernel_data->v[0xcb0 >> 2] = htonl(RAMBase); - kernel_data->v[0xcb4 >> 2] = htonl(RAMSize); - kernel_data->v[0xf80 >> 2] = htonl(PVR); - kernel_data->v[0xf84 >> 2] = htonl(CPUClockSpeed); // clock-frequency - kernel_data->v[0xf88 >> 2] = htonl(BusClockSpeed); // bus-frequency - kernel_data->v[0xf8c >> 2] = htonl(TimebaseSpeed); // timebase-frequency - } - - // Initialize extra low memory - D(bug("Initializing Low Memory...\n")); - Mac_memset(0, 0, 0x3000); - WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h')); // Signature to detect SheepShaver - WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr); // For trap replacement routines - WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR - WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch - WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode) - WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0 -#if !EMULATED_PPC -#ifdef SYSTEM_CLOBBERS_R2 - WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator -#endif -#ifdef SYSTEM_CLOBBERS_R13 - WriteMacInt32(XLM_R13, (uint32)R13); // TLS register -#endif -#endif - - WriteMacInt32(XLM_ETHER_AO_GET_HWADDR, NativeFunction(NATIVE_ETHER_AO_GET_HWADDR)); // Low level ethernet driver functions - WriteMacInt32(XLM_ETHER_AO_ADD_MULTI, NativeFunction(NATIVE_ETHER_AO_ADD_MULTI)); - WriteMacInt32(XLM_ETHER_AO_DEL_MULTI, NativeFunction(NATIVE_ETHER_AO_DEL_MULTI)); - WriteMacInt32(XLM_ETHER_AO_SEND_PACKET, NativeFunction(NATIVE_ETHER_AO_SEND_PACKET)); - - WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT)); // DLPI ethernet driver functions - WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM)); - WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN)); - WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE)); - WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT)); - WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV)); - WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO)); - D(bug("Low Memory initialized\n")); - -#if ENABLE_MON - // Initialize mon - mon_init(); - mon_read_byte = sheepshaver_read_byte; - mon_write_byte = sheepshaver_write_byte; -#endif - - return true; -} - - -/* - * Deinitialize everything - */ - -void ExitAll(void) -{ -#if ENABLE_MON - // Deinitialize mon - mon_exit(); -#endif - - // Save NVRAM - XPRAMExit(); - - // Exit clipboard - ClipExit(); - - // Exit Time Manager - TimerExit(); - - // Exit serial - SerialExit(); - - // Exit network - EtherExit(); - - // Exit audio - AudioExit(); - - // Exit ADB - ADBExit(); - - // Exit video - VideoExit(); - - // Exit external file system - ExtFSExit(); - - // Exit drivers - SCSIExit(); - CDROMExit(); - DiskExit(); - SonyExit(); - - // Delete thunks - ThunksExit(); -} - - -/* - * Patch things after system startup (gets called by disk driver accRun routine) - */ - -void PatchAfterStartup(void) -{ - ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL); - InstallExtFS(); -} diff --git a/SheepShaver/src/name_registry.cpp b/SheepShaver/src/name_registry.cpp deleted file mode 100644 index 89819d6d..00000000 --- a/SheepShaver/src/name_registry.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * name_registry.cpp - Name Registry handling - * - * SheepShaver (C) Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "sysdeps.h" -#include "name_registry.h" -#include "main.h" -#include "macos_util.h" -#include "user_strings.h" -#include "emul_op.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - - -// Function pointers -typedef int16 (*rcec_ptr)(const RegEntryID *, const char *, RegEntryID *); -static uint32 rcec_tvect = 0; -static inline int16 RegistryCStrEntryCreate(uintptr arg1, const char *arg2, uint32 arg3) -{ - SheepString arg2str(arg2); - return (int16)CallMacOS3(rcec_ptr, rcec_tvect, (const RegEntryID *)arg1, arg2str.addr(), arg3); -} -typedef int16 (*rpc_ptr)(const RegEntryID *, const char *, const void *, uint32); -static uint32 rpc_tvect = 0; -static inline int16 RegistryPropertyCreate(uintptr arg1, const char *arg2, uintptr arg3, uint32 arg4) -{ - SheepString arg2str(arg2); - return (int16)CallMacOS4(rpc_ptr, rpc_tvect, (const RegEntryID *)arg1, arg2str.addr(), (const void *)arg3, arg4); -} -static inline int16 RegistryPropertyCreateStr(uintptr arg1, const char *arg2, const char *arg3) -{ - SheepString arg3str(arg3); - return RegistryPropertyCreate(arg1, arg2, arg3str.addr(), strlen(arg3) + 1); -} - -// Video driver stub -static const uint8 video_driver[] = { -#include "VideoDriverStub.i" -}; - -// Ethernet driver stub -static const uint8 ethernet_driver[] = { -#ifdef USE_ETHER_FULL_DRIVER -#include "EthernetDriverFull.i" -#else -#include "EthernetDriverStub.i" -#endif -}; - -// Helper for RegEntryID -typedef SheepArray SheepRegEntryID; - -// Helper for a pair -struct SheepPair : public SheepArray<8> { - SheepPair(uint32 base, uint32 size) : SheepArray<8>() - { WriteMacInt32(addr(), base); WriteMacInt32(addr() + 4, size); } -}; - - -/* - * Patch Name Registry during startup - */ - -void DoPatchNameRegistry(void) -{ - SheepVar32 u32; - D(bug("Patching Name Registry...")); - - // Create "device-tree" - SheepRegEntryID device_tree; - if (!RegistryCStrEntryCreate(0, "Devices:device-tree", device_tree.addr())) { - u32.set_value(BusClockSpeed); - RegistryPropertyCreate(device_tree.addr(), "clock-frequency", u32.addr(), 4); - RegistryPropertyCreateStr(device_tree.addr(), "model", "Power Macintosh"); - - // Create "AAPL,ROM" - SheepRegEntryID aapl_rom; - if (!RegistryCStrEntryCreate(device_tree.addr(), "AAPL,ROM", aapl_rom.addr())) { - RegistryPropertyCreateStr(aapl_rom.addr(), "device_type", "rom"); - SheepPair reg(ROMBase, ROM_SIZE); - RegistryPropertyCreate(aapl_rom.addr(), "reg", reg.addr(), 8); - } - - // Create "PowerPC,60x" - SheepRegEntryID power_pc; - const char *str; - switch (PVR >> 16) { - case 1: // 601 - str = "PowerPC,601"; - break; - case 3: // 603 - str = "PowerPC,603"; - break; - case 4: // 604 - str = "PowerPC,604"; - break; - case 6: // 603e - str = "PowerPC,603e"; - break; - case 7: // 603ev - str = "PowerPC,603ev"; - break; - case 8: // 750 - str = "PowerPC,750"; - break; - case 9: // 604e - str = "PowerPC,604e"; - break; - case 10: // 604ev5 - str = "PowerPC,604ev"; - break; - case 50: // 821 - str = "PowerPC,821"; - break; - case 80: // 860 - str = "PowerPC,860"; - break; - case 12: // 7400, 7410, 7450, 7455, 7457 - case 0x800c: - case 0x8000: - case 0x8001: - case 0x8002: - str = "PowerPC,G4"; - break; - default: - str = "PowerPC,???"; - break; - } - if (!RegistryCStrEntryCreate(device_tree.addr(), str, power_pc.addr())) { - u32.set_value(CPUClockSpeed); - RegistryPropertyCreate(power_pc.addr(), "clock-frequency", u32.addr(), 4); - u32.set_value(BusClockSpeed); - RegistryPropertyCreate(power_pc.addr(), "bus-frequency", u32.addr(), 4); - u32.set_value(TimebaseSpeed); - RegistryPropertyCreate(power_pc.addr(), "timebase-frequency", u32.addr(), 4); - u32.set_value(PVR); - RegistryPropertyCreate(power_pc.addr(), "cpu-version", u32.addr(), 4); - RegistryPropertyCreateStr(power_pc.addr(), "device_type", "cpu"); - switch (PVR >> 16) { - case 1: // 601 - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(256); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 3: // 603 - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x2000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x2000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 4: // 604 - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x4000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x4000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 6: // 603e - case 7: // 603ev - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x4000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x4000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 8: // 750, 750FX - case 0x7000: - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(256); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(256); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 9: // 604e - case 10: // 604ev5 - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(256); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(256); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 12: // 7400, 7410, 7450, 7455, 7457 - case 0x800c: - case 0x8000: - case 0x8001: - case 0x8002: - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(64); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - case 0x39: // 970 - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "d-cache-block-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "d-cache-sets", u32.addr(), 4); - u32.set_value(0x8000); - RegistryPropertyCreate(power_pc.addr(), "d-cache-size", u32.addr(), 4); - u32.set_value(128); - RegistryPropertyCreate(power_pc.addr(), "i-cache-block-size", u32.addr(), 4); - u32.set_value(512); - RegistryPropertyCreate(power_pc.addr(), "i-cache-sets", u32.addr(), 4); - u32.set_value(0x10000); - RegistryPropertyCreate(power_pc.addr(), "i-cache-size", u32.addr(), 4); - u32.set_value(256); - RegistryPropertyCreate(power_pc.addr(), "tlb-sets", u32.addr(), 4); - u32.set_value(0x1000); - RegistryPropertyCreate(power_pc.addr(), "tlb-size", u32.addr(), 4); - break; - default: - break; - } - u32.set_value(32); - RegistryPropertyCreate(power_pc.addr(), "reservation-granularity", u32.addr(), 4); - SheepPair reg(0, 0); - RegistryPropertyCreate(power_pc.addr(), "reg", reg.addr(), 8); - } - - // Create "memory" - SheepRegEntryID memory; - if (!RegistryCStrEntryCreate(device_tree.addr(), "memory", memory.addr())) { - SheepPair reg(RAMBase, RAMSize); - RegistryPropertyCreateStr(memory.addr(), "device_type", "memory"); - RegistryPropertyCreate(memory.addr(), "reg", reg.addr(), 8); - } - - // Create "video" - SheepRegEntryID video; - if (!RegistryCStrEntryCreate(device_tree.addr(), "video", video.addr())) { - RegistryPropertyCreateStr(video.addr(), "AAPL,connector", "monitor"); - RegistryPropertyCreateStr(video.addr(), "device_type", "display"); - SheepArray the_video_driver; - Host2Mac_memcpy(the_video_driver.addr(), video_driver, sizeof(video_driver)); - RegistryPropertyCreate(video.addr(), "driver,AAPL,MacOS,PowerPC", the_video_driver.addr(), sizeof(video_driver)); - RegistryPropertyCreateStr(video.addr(), "model", "SheepShaver Video"); - } - - // Create "ethernet" - SheepRegEntryID ethernet; - if (!RegistryCStrEntryCreate(device_tree.addr(), "ethernet", ethernet.addr())) { - RegistryPropertyCreateStr(ethernet.addr(), "AAPL,connector", "ethernet"); - RegistryPropertyCreateStr(ethernet.addr(), "device_type", "network"); - SheepArray the_ethernet_driver; - Host2Mac_memcpy(the_ethernet_driver.addr(), ethernet_driver, sizeof(ethernet_driver)); - RegistryPropertyCreate(ethernet.addr(), "driver,AAPL,MacOS,PowerPC", the_ethernet_driver.addr(), sizeof(ethernet_driver)); - // local-mac-address - // max-frame-size 2048 - } - } - D(bug("done.\n")); -} - -void PatchNameRegistry(void) -{ - // Find RegistryCStrEntryCreate() and RegistryPropertyCreate() TVECTs - rcec_tvect = FindLibSymbol("\017NameRegistryLib", "\027RegistryCStrEntryCreate"); - D(bug("RegistryCStrEntryCreate TVECT at %08x\n", rcec_tvect)); - rpc_tvect = FindLibSymbol("\017NameRegistryLib", "\026RegistryPropertyCreate"); - D(bug("RegistryPropertyCreate TVECT at %08x\n", rpc_tvect)); - if (rcec_tvect == 0 || rpc_tvect == 0) { - ErrorAlert(GetString(STR_NO_NAME_REGISTRY_ERR)); - QuitEmulator(); - } - - // Main routine must be executed in PPC mode - ExecuteNative(NATIVE_PATCH_NAME_REGISTRY); -} diff --git a/SheepShaver/src/pict.c b/SheepShaver/src/pict.c deleted file mode 120000 index bcbd7ff4..00000000 --- a/SheepShaver/src/pict.c +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/pict.c \ No newline at end of file diff --git a/SheepShaver/src/prefs.cpp b/SheepShaver/src/prefs.cpp deleted file mode 120000 index 6559f3b1..00000000 --- a/SheepShaver/src/prefs.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/prefs.cpp \ No newline at end of file diff --git a/SheepShaver/src/prefs_items.cpp b/SheepShaver/src/prefs_items.cpp deleted file mode 100644 index 1d4758dc..00000000 --- a/SheepShaver/src/prefs_items.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * prefs_items.cpp - Common preferences items - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "sys.h" -#include "prefs.h" - - -// Common preferences items (those which exist on all platforms) -prefs_desc common_prefs_items[] = { - {"disk", TYPE_STRING, true, "device/file name of Mac volume"}, - {"floppy", TYPE_STRING, true, "device/file name of Mac floppy drive"}, - {"cdrom", TYPE_STRING, true, "device/file names of Mac CD-ROM drive"}, - {"extfs", TYPE_STRING, false, "root path of ExtFS"}, - {"scsi0", TYPE_STRING, false, "SCSI target for Mac SCSI ID 0"}, - {"scsi1", TYPE_STRING, false, "SCSI target for Mac SCSI ID 1"}, - {"scsi2", TYPE_STRING, false, "SCSI target for Mac SCSI ID 2"}, - {"scsi3", TYPE_STRING, false, "SCSI target for Mac SCSI ID 3"}, - {"scsi4", TYPE_STRING, false, "SCSI target for Mac SCSI ID 4"}, - {"scsi5", TYPE_STRING, false, "SCSI target for Mac SCSI ID 5"}, - {"scsi6", TYPE_STRING, false, "SCSI target for Mac SCSI ID 6"}, - {"screen", TYPE_STRING, false, "video mode"}, - {"windowmodes", TYPE_INT32, false, "bitmap of allowed window video modes"}, - {"screenmodes", TYPE_INT32, false, "bitmap of allowed fullscreen video modes"}, - {"seriala", TYPE_STRING, false, "device name of Mac serial port A"}, - {"serialb", TYPE_STRING, false, "device name of Mac serial port B"}, - {"rom", TYPE_STRING, false, "path of ROM file"}, - {"bootdrive", TYPE_INT32, false, "boot drive number"}, - {"bootdriver", TYPE_INT32, false, "boot driver number"}, - {"ramsize", TYPE_INT32, false, "size of Mac RAM in bytes"}, - {"frameskip", TYPE_INT32, false, "number of frames to skip in refreshed video modes"}, - {"gfxaccel", TYPE_BOOLEAN, false, "turn on QuickDraw acceleration"}, - {"nocdrom", TYPE_BOOLEAN, false, "don't install CD-ROM driver"}, - {"nonet", TYPE_BOOLEAN, false, "don't use Ethernet"}, - {"nosound", TYPE_BOOLEAN, false, "don't enable sound output"}, - {"nogui", TYPE_BOOLEAN, false, "disable GUI"}, - {"noclipconversion", TYPE_BOOLEAN, false, "don't convert clipboard contents"}, - {"ignoresegv", TYPE_BOOLEAN, false, "ignore illegal memory accesses"}, - {"ignoreillegal", TYPE_BOOLEAN, false, "ignore illegal instructions"}, - {"jit", TYPE_BOOLEAN, false, "enable JIT compiler"}, - {"jit68k", TYPE_BOOLEAN, false, "enable 68k DR emulator"}, - {"keyboardtype", TYPE_INT32, false, "hardware keyboard type"}, - {NULL, TYPE_END, false, NULL} // End of list -}; - -/* - * Set default values for preferences items - */ - -void AddPrefsDefaults(void) -{ -#ifndef PREFS_EDITOR - SysAddSerialPrefs(); -#endif - PrefsAddInt32("bootdriver", 0); - PrefsAddInt32("bootdrive", 0); - PrefsAddInt32("ramsize", 16 * 1024 * 1024); - PrefsAddInt32("frameskip", 8); - PrefsAddBool("gfxaccel", true); - PrefsAddBool("nocdrom", false); - PrefsAddBool("nonet", false); - PrefsAddBool("nosound", false); - PrefsAddBool("nogui", false); - PrefsAddBool("noclipconversion", false); - PrefsAddBool("ignoresegv", false); - PrefsAddBool("ignoreillegal", false); - -#if USE_JIT - // JIT compiler specific options - PrefsAddBool("jit", true); -#else - PrefsAddBool("jit", false); -#endif - PrefsAddBool("jit68k", false); - - PrefsAddInt32("keyboardtype", 5); -} diff --git a/SheepShaver/src/rom_patches.cpp b/SheepShaver/src/rom_patches.cpp deleted file mode 100644 index 9dcd826a..00000000 --- a/SheepShaver/src/rom_patches.cpp +++ /dev/null @@ -1,2499 +0,0 @@ -/* - * rom_patches.cpp - ROM patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * TODO: - * IRQ_NEST must be handled atomically - * Don't use r1 in extra routines - */ - -#include - -#include "sysdeps.h" -#include "rom_patches.h" -#include "main.h" -#include "prefs.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "xlowmem.h" -#include "sony.h" -#include "disk.h" -#include "cdrom.h" -#include "audio.h" -#include "audio_defs.h" -#include "serial.h" -#include "macos_util.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - - -// 68k breakpoint address -//#define M68K_BREAK_POINT 0x29e0 // BootMe -//#define M68K_BREAK_POINT 0x2a1e // Boot block code returned -//#define M68K_BREAK_POINT 0x3150 // CritError -//#define M68K_BREAK_POINT 0x187ce // Unimplemented trap - -// PowerPC breakpoint address -//#define POWERPC_BREAK_POINT 0x36e6c0 // 68k emulator start - -#define DISABLE_SCSI 1 - - -// Other ROM addresses -const uint32 CHECK_LOAD_PATCH_SPACE = 0x2fcf00; -const uint32 ZERO_SCRAP_PATCH_SPACE = 0x2fcf80; -const uint32 PUT_SCRAP_PATCH_SPACE = 0x2fcfc0; -const uint32 GET_SCRAP_PATCH_SPACE = 0x2fd100; -const uint32 ADDR_MAP_PATCH_SPACE = 0x2fd140; - -// Global variables -int ROMType; // ROM type -static uint32 sony_offset; // Offset of .Sony driver resource - -// Prototypes -static bool patch_nanokernel_boot(void); -static bool patch_68k_emul(void); -static bool patch_nanokernel(void); -static bool patch_68k(void); - - -// Decode LZSS data -static void decode_lzss(const uint8 *src, uint8 *dest, int size) -{ - char dict[0x1000]; - int run_mask = 0, dict_idx = 0xfee; - for (;;) { - if (run_mask < 0x100) { - // Start new run - if (--size < 0) - break; - run_mask = *src++ | 0xff00; - } - bool bit = run_mask & 1; - run_mask >>= 1; - if (bit) { - // Verbatim copy - if (--size < 0) - break; - int c = *src++; - dict[dict_idx++] = c; - *dest++ = c; - dict_idx &= 0xfff; - } else { - // Copy from dictionary - if (--size < 0) - break; - int idx = *src++; - if (--size < 0) - break; - int cnt = *src++; - idx |= (cnt << 4) & 0xf00; - cnt = (cnt & 0x0f) + 3; - while (cnt--) { - char c = dict[idx++]; - dict[dict_idx++] = c; - *dest++ = c; - idx &= 0xfff; - dict_idx &= 0xfff; - } - } - } -} - -// Decode parcels of ROM image (MacOS 9.X and even earlier) -void decode_parcels(const uint8 *src, uint8 *dest, int size) -{ - uint32 parcel_offset = 0x14; - D(bug("Offset Type Name\n")); - while (parcel_offset != 0) { - const uint32 *parcel_data = (uint32 *)(src + parcel_offset); - uint32 next_offset = ntohl(parcel_data[0]); - uint32 parcel_type = ntohl(parcel_data[1]); - D(bug("%08x %c%c%c%c %s\n", parcel_offset, - (parcel_type >> 24) & 0xff, (parcel_type >> 16) & 0xff, - (parcel_type >> 8) & 0xff, parcel_type & 0xff, &parcel_data[6])); - if (parcel_type == FOURCC('r','o','m',' ')) { - uint32 lzss_offset = ntohl(parcel_data[2]); - uint32 lzss_size = ((uintptr)src + next_offset) - ((uintptr)parcel_data + lzss_offset); - decode_lzss((uint8 *)parcel_data + lzss_offset, dest, lzss_size); - } - parcel_offset = next_offset; - } -} - - -/* - * Decode ROM image, 4 MB plain images or NewWorld images - */ - -bool DecodeROM(uint8 *data, uint32 size) -{ - if (size == ROM_SIZE) { - // Plain ROM image - memcpy(ROMBaseHost, data, ROM_SIZE); - return true; - } - else if (strncmp((char *)data, "", 11) == 0) { - // CHRP compressed ROM image - uint32 image_offset, image_size; - bool decode_info_ok = false; - - char *s = strstr((char *)data, "constant lzss-offset"); - if (s != NULL) { - // Probably a plain LZSS compressed ROM image - if (sscanf(s - 7, "%06x", &image_offset) == 1) { - s = strstr((char *)data, "constant lzss-size"); - if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1)) - decode_info_ok = true; - } - } - else { - // Probably a MacOS 9.2.x ROM image - s = strstr((char *)data, "constant parcels-offset"); - if (s != NULL) { - if (sscanf(s - 7, "%06x", &image_offset) == 1) { - s = strstr((char *)data, "constant parcels-size"); - if (s != NULL && (sscanf(s - 7, "%06x", &image_size) == 1)) - decode_info_ok = true; - } - } - } - - // No valid information to decode the ROM found? - if (!decode_info_ok) - return false; - - // Check signature, this could be a parcels-based ROM image - uint32 rom_signature = ntohl(*(uint32 *)(data + image_offset)); - if (rom_signature == FOURCC('p','r','c','l')) { - D(bug("Offset of parcels data: %08x\n", image_offset)); - D(bug("Size of parcels data: %08x\n", image_size)); - decode_parcels(data + image_offset, ROMBaseHost, image_size); - } - else { - D(bug("Offset of compressed data: %08x\n", image_offset)); - D(bug("Size of compressed data: %08x\n", image_size)); - decode_lzss(data + image_offset, ROMBaseHost, image_size); - } - return true; - } - return false; -} - - -/* - * Search ROM for byte string, return ROM offset (or 0) - */ - -static uint32 find_rom_data(uint32 start, uint32 end, const uint8 *data, uint32 data_len) -{ - uint32 ofs = start; - while (ofs < end) { - if (!memcmp(ROMBaseHost + ofs, data, data_len)) - return ofs; - ofs++; - } - return 0; -} - - -/* - * Search ROM resource by type/ID, return ROM offset of resource data - */ - -static uint32 rsrc_ptr = 0; - -// id = 4711 means "find any ID" -static uint32 find_rom_resource(uint32 s_type, int16 s_id = 4711, bool cont = false) -{ - uint32 lp = ROMBase + 0x1a; - uint32 x = ReadMacInt32(lp); - uint32 header_size = ReadMacInt8(ROMBase + x + 5); - - if (!cont) - rsrc_ptr = x; - else if (rsrc_ptr == 0) - return 0; - - for (;;) { - lp = ROMBase + rsrc_ptr; - rsrc_ptr = ReadMacInt32(lp); - if (rsrc_ptr == 0) - break; - - rsrc_ptr += header_size; - - lp = ROMBase + rsrc_ptr + 4; - uint32 data = ReadMacInt32(lp); - uint32 type = ReadMacInt32(lp + 4); - int16 id = ReadMacInt16(lp + 8); - if (type == s_type && (id == s_id || s_id == 4711)) - return data; - } - return 0; -} - - -/* - * Search offset of A-Trap routine in ROM - */ - -static uint32 find_rom_trap(uint16 trap) -{ - uint32 lp = ROMBase + ReadMacInt32(ROMBase + 0x22); - - if (trap > 0xa800) - return ReadMacInt32(lp + 4 * (trap & 0x3ff)); - else - return ReadMacInt32(lp + 4 * ((trap & 0xff) + 0x400)); -} - - -/* - * Return target of branch instruction specified at ADDR, or 0 if - * there is no such instruction - */ - -static uint32 rom_powerpc_branch_target(uint32 addr) -{ - uint32 opcode = ntohl(*(uint32 *)(ROMBaseHost + addr)); - uint32 primop = opcode >> 26; - uint32 target = 0; - - if (primop == 18) { // Branch - target = opcode & 0x3fffffc; - if (target & 0x2000000) - target |= 0xfc000000; - if ((opcode & 2) == 0) - target += addr; - } - else if (primop == 16) { // Branch Conditional - target = (int32)(int16)(opcode & 0xfffc); - if ((opcode & 2) == 0) - target += addr; - } - return target; -} - - -/* - * Search ROM for instruction branching to target address, return 0 if none found - */ - -static uint32 find_rom_powerpc_branch(uint32 start, uint32 end, uint32 target) -{ - for (uint32 addr = start; addr < end; addr += 4) { - if (rom_powerpc_branch_target(addr) == target) - return addr; - } - return 0; -} - - -/* - * Check that requested ROM patch space is really available - */ - -static bool check_rom_patch_space(uint32 base, uint32 size) -{ - size = (size + 3) & -4; - for (int i = 0; i < size; i += 4) { - uint32 x = ntohl(*(uint32 *)(ROMBaseHost + base + i)); - if (x != 0x6b636b63 && x != 0) - return false; - } - return true; -} - - -/* - * List of audio sifters installed in ROM and System file - */ - -struct sift_entry { - uint32 type; - int16 id; -}; -static sift_entry sifter_list[32]; -static int num_sifters; - -void AddSifter(uint32 type, int16 id) -{ - if (FindSifter(type, id)) - return; - D(bug(" adding sifter type %c%c%c%c (%08x), id %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, id)); - sifter_list[num_sifters].type = type; - sifter_list[num_sifters].id = id; - num_sifters++; -} - -bool FindSifter(uint32 type, int16 id) -{ - for (int i=0; i> 8, SonyDriverFlags & 0xff, 0, 0, 0, 0, 0, 0, - 0x00, 0x18, // Open() offset - 0x00, 0x1c, // Prime() offset - 0x00, 0x20, // Control() offset - 0x00, 0x2c, // Status() offset - 0x00, 0x52, // Close() offset - 0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79, // ".Sony" - - // Open() - M68K_EMUL_OP_SONY_OPEN >> 8, M68K_EMUL_OP_SONY_OPEN & 0xff, - 0x4e, 0x75, // rts - - // Prime() - M68K_EMUL_OP_SONY_PRIME >> 8, M68K_EMUL_OP_SONY_PRIME & 0xff, - 0x60, 0x0e, // bra IOReturn - - // Control() - M68K_EMUL_OP_SONY_CONTROL >> 8, M68K_EMUL_OP_SONY_CONTROL & 0xff, - 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0) - 0x66, 0x04, // bne IOReturn - 0x4e, 0x75, // rts - - // Status() - M68K_EMUL_OP_SONY_STATUS >> 8, M68K_EMUL_OP_SONY_STATUS & 0xff, - - // IOReturn - 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1 - 0x08, 0x01, 0x00, 0x09, // btst #9,d1 - 0x67, 0x0c, // beq 1 - 0x4a, 0x40, // tst.w d0 - 0x6f, 0x02, // ble 2 - 0x42, 0x40, // clr.w d0 - 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0) - 0x4e, 0x75, // rts - 0x4a, 0x40, //1 tst.w d0 - 0x6f, 0x04, // ble 3 - 0x42, 0x40, // clr.w d0 - 0x4e, 0x75, // rts - 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp) - 0x4e, 0x75, // rts - - // Close() - 0x70, 0xe8, // moveq #-24,d0 - 0x4e, 0x75 // rts -}; - -static const uint8 disk_driver[] = { // Generic disk driver - // Driver header - DiskDriverFlags >> 8, DiskDriverFlags & 0xff, 0, 0, 0, 0, 0, 0, - 0x00, 0x18, // Open() offset - 0x00, 0x1c, // Prime() offset - 0x00, 0x20, // Control() offset - 0x00, 0x2c, // Status() offset - 0x00, 0x52, // Close() offset - 0x05, 0x2e, 0x44, 0x69, 0x73, 0x6b, // ".Disk" - - // Open() - M68K_EMUL_OP_DISK_OPEN >> 8, M68K_EMUL_OP_DISK_OPEN & 0xff, - 0x4e, 0x75, // rts - - // Prime() - M68K_EMUL_OP_DISK_PRIME >> 8, M68K_EMUL_OP_DISK_PRIME & 0xff, - 0x60, 0x0e, // bra IOReturn - - // Control() - M68K_EMUL_OP_DISK_CONTROL >> 8, M68K_EMUL_OP_DISK_CONTROL & 0xff, - 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0) - 0x66, 0x04, // bne IOReturn - 0x4e, 0x75, // rts - - // Status() - M68K_EMUL_OP_DISK_STATUS >> 8, M68K_EMUL_OP_DISK_STATUS & 0xff, - - // IOReturn - 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1 - 0x08, 0x01, 0x00, 0x09, // btst #9,d1 - 0x67, 0x0c, // beq 1 - 0x4a, 0x40, // tst.w d0 - 0x6f, 0x02, // ble 2 - 0x42, 0x40, // clr.w d0 - 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0) - 0x4e, 0x75, // rts - 0x4a, 0x40, //1 tst.w d0 - 0x6f, 0x04, // ble 3 - 0x42, 0x40, // clr.w d0 - 0x4e, 0x75, // rts - 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp) - 0x4e, 0x75, // rts - - // Close() - 0x70, 0xe8, // moveq #-24,d0 - 0x4e, 0x75 // rts -}; - -static const uint8 cdrom_driver[] = { // CD-ROM driver - // Driver header - CDROMDriverFlags >> 8, CDROMDriverFlags & 0xff, 0, 0, 0, 0, 0, 0, - 0x00, 0x1c, // Open() offset - 0x00, 0x20, // Prime() offset - 0x00, 0x24, // Control() offset - 0x00, 0x30, // Status() offset - 0x00, 0x56, // Close() offset - 0x08, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x43, 0x44, 0x00, // ".AppleCD" - - // Open() - M68K_EMUL_OP_CDROM_OPEN >> 8, M68K_EMUL_OP_CDROM_OPEN & 0xff, - 0x4e, 0x75, // rts - - // Prime() - M68K_EMUL_OP_CDROM_PRIME >> 8, M68K_EMUL_OP_CDROM_PRIME & 0xff, - 0x60, 0x0e, // bra IOReturn - - // Control() - M68K_EMUL_OP_CDROM_CONTROL >> 8, M68K_EMUL_OP_CDROM_CONTROL & 0xff, - 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0) - 0x66, 0x04, // bne IOReturn - 0x4e, 0x75, // rts - - // Status() - M68K_EMUL_OP_CDROM_STATUS >> 8, M68K_EMUL_OP_CDROM_STATUS & 0xff, - - // IOReturn - 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1 - 0x08, 0x01, 0x00, 0x09, // btst #9,d1 - 0x67, 0x0c, // beq 1 - 0x4a, 0x40, // tst.w d0 - 0x6f, 0x02, // ble 2 - 0x42, 0x40, // clr.w d0 - 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0) - 0x4e, 0x75, // rts - 0x4a, 0x40, //1 tst.w d0 - 0x6f, 0x04, // ble 3 - 0x42, 0x40, // clr.w d0 - 0x4e, 0x75, // rts - 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp) - 0x4e, 0x75, // rts - - // Close() - 0x70, 0xe8, // moveq #-24,d0 - 0x4e, 0x75 // rts -}; - -static uint32 long_ptr; - -static void SetLongBase(uint32 addr) -{ - long_ptr = addr; -} - -static void Long(uint32 value) -{ - WriteMacInt32(long_ptr, value); - long_ptr += 4; -} - -static void gen_ain_driver(uintptr addr) -{ - SetLongBase(addr); - - // .AIn driver header - Long(0x4d000000); Long(0x00000000); - Long(0x00200040); Long(0x00600080); - Long(0x00a0042e); Long(0x41496e00); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_IN)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); - Long(0x00000000); Long(0x00000000); -}; - -static void gen_aout_driver(uintptr addr) -{ - SetLongBase(addr); - - // .AOut driver header - Long(0x4d000000); Long(0x00000000); - Long(0x00200040); Long(0x00600080); - Long(0x00a0052e); Long(0x414f7574); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_OPEN)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_OUT)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CLOSE)); - Long(0x00000000); Long(0x00000000); -}; - -static void gen_bin_driver(uintptr addr) -{ - SetLongBase(addr); - - // .BIn driver header - Long(0x4d000000); Long(0x00000000); - Long(0x00200040); Long(0x00600080); - Long(0x00a0042e); Long(0x42496e00); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_IN)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_NOTHING)); - Long(0x00000000); Long(0x00000000); -}; - -static void gen_bout_driver(uintptr addr) -{ - SetLongBase(addr); - - // .BOut driver header - Long(0x4d000000); Long(0x00000000); - Long(0x00200040); Long(0x00600080); - Long(0x00a0052e); Long(0x424f7574); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_OPEN)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_PRIME_OUT)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CONTROL)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_STATUS)); - Long(0x00000000); Long(0x00000000); - Long(0xaafe0700); Long(0x00000000); - Long(0x00000000); Long(0x00179822); - Long(0x00010004); Long(NativeTVECT(NATIVE_SERIAL_CLOSE)); - Long(0x00000000); Long(0x00000000); -}; - -static const uint8 adbop_patch[] = { // Call ADBOp() completion procedure - // The completion procedure may call ADBOp() again! - 0x40, 0xe7, // move sr,-(sp) - 0x00, 0x7c, 0x07, 0x00, // ori #$0700,sr - M68K_EMUL_OP_ADBOP >> 8, M68K_EMUL_OP_ADBOP & 0xff, - 0x48, 0xe7, 0x70, 0xf0, // movem.l d1-d3/a0-a3,-(sp) - 0x26, 0x48, // move.l a0,a3 - 0x4a, 0xab, 0x00, 0x04, // tst.l 4(a3) - 0x67, 0x00, 0x00, 0x18, // beq 1 - 0x20, 0x53, // move.l (a3),a0 - 0x22, 0x6b, 0x00, 0x04, // move.l 4(a3),a1 - 0x24, 0x6b, 0x00, 0x08, // move.l 8(a3),a2 - 0x26, 0x78, 0x0c, 0xf8, // move.l $cf8,a3 - 0x4e, 0x91, // jsr (a1) - 0x70, 0x00, // moveq #0,d0 - 0x60, 0x00, 0x00, 0x04, // bra 2 - 0x70, 0xff, //1 moveq #-1,d0 - 0x4c, 0xdf, 0x0f, 0x0e, //2 movem.l (sp)+,d1-d3/a0-a3 - 0x46, 0xdf, // move (sp)+,sr - 0x4e, 0x75 // rts -}; - - -/* - * Copy PowerPC code to ROM image and reverse bytes if necessary - */ - -static inline void memcpy_powerpc_code(void *dst, const void *src, size_t len) -{ -#ifdef WORDS_BIGENDIAN - (void)memcpy(dst, src, len); -#else - uint32 *d = (uint32 *)dst; - uint32 *s = (uint32 *)src; - for (int i = 0; i < len/4; i++) - d[i] = htonl(s[i]); -#endif -} - - -/* - * Install ROM patches (RAMBase and KernelDataAddr must be set) - */ - -bool PatchROM(void) -{ - // Print ROM info - D(bug("Checksum: %08lx\n", ntohl(*(uint32 *)ROMBaseHost))); - D(bug("Version: %04x\n", ntohs(*(uint16 *)(ROMBaseHost + 8)))); - D(bug("Sub Version: %04x\n", ntohs(*(uint16 *)(ROMBaseHost + 18)))); - D(bug("Nanokernel ID: %s\n", (char *)ROMBaseHost + 0x30d064)); - D(bug("Resource Map at %08lx\n", ntohl(*(uint32 *)(ROMBaseHost + 26)))); - D(bug("Trap Tables at %08lx\n\n", ntohl(*(uint32 *)(ROMBaseHost + 34)))); - - // Detect ROM type - if (!memcmp(ROMBaseHost + 0x30d064, "Boot TNT", 8)) - ROMType = ROMTYPE_TNT; - else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Alchemy", 12)) - ROMType = ROMTYPE_ALCHEMY; - else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Zanzibar", 13)) - ROMType = ROMTYPE_ZANZIBAR; - else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Gazelle", 12)) - ROMType = ROMTYPE_GAZELLE; - else if (!memcmp(ROMBaseHost + 0x30d064, "Boot Gossamer", 13)) - ROMType = ROMTYPE_GOSSAMER; - else if (!memcmp(ROMBaseHost + 0x30d064, "NewWorld", 8)) - ROMType = ROMTYPE_NEWWORLD; - else - return false; - - // Check that other ROM addresses point to really free regions - if (!check_rom_patch_space(CHECK_LOAD_PATCH_SPACE, 0x40)) - return false; - if (!check_rom_patch_space(ZERO_SCRAP_PATCH_SPACE, 0x40)) - return false; - if (!check_rom_patch_space(PUT_SCRAP_PATCH_SPACE, 0x40)) - return false; - if (!check_rom_patch_space(GET_SCRAP_PATCH_SPACE, 0x40)) - return false; - if (!check_rom_patch_space(ADDR_MAP_PATCH_SPACE - 10 * 4, 0x100)) - return false; - - // Apply patches - if (!patch_nanokernel_boot()) return false; - if (!patch_68k_emul()) return false; - if (!patch_nanokernel()) return false; - if (!patch_68k()) return false; - -#ifdef M68K_BREAK_POINT - // Install 68k breakpoint - uint16 *wp = (uint16 *)(ROMBaseHost + M68K_BREAK_POINT); - *wp++ = htons(M68K_EMUL_BREAK); - *wp = htons(M68K_EMUL_RETURN); -#endif - -#ifdef POWERPC_BREAK_POINT - // Install PowerPC breakpoint - uint32 *lp = (uint32 *)(ROMBaseHost + POWERPC_BREAK_POINT); - *lp = htonl(0); -#endif - - // Copy 68k emulator to 2MB boundary - memcpy(ROMBaseHost + ROM_SIZE, ROMBaseHost + (ROM_SIZE - 0x100000), 0x100000); - return true; -} - - -/* - * Nanokernel boot routine patches - */ - -static bool patch_nanokernel_boot(void) -{ - uint32 *lp; - uint32 base, loc; - - // ROM boot structure patches - lp = (uint32 *)(ROMBaseHost + 0x30d000); - lp[0x9c >> 2] = htonl(KernelDataAddr); // LA_InfoRecord - lp[0xa0 >> 2] = htonl(KernelDataAddr); // LA_KernelData - lp[0xa4 >> 2] = htonl(KernelDataAddr + 0x1000); // LA_EmulatorData - lp[0xa8 >> 2] = htonl(ROMBase + 0x480000); // LA_DispatchTable - lp[0xac >> 2] = htonl(ROMBase + 0x460000); // LA_EmulatorCode - lp[0x360 >> 2] = htonl(0); // Physical RAM base (? on NewWorld ROM, this contains -1) - lp[0xfd8 >> 2] = htonl(ROMBase + 0x2a); // 68k reset vector - - // Skip SR/BAT/SDR init - loc = 0x310000; - if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_GOSSAMER || ROMType == ROMTYPE_NEWWORLD) { - lp = (uint32 *)(ROMBaseHost + loc); - *lp++ = htonl(POWERPC_NOP); - *lp = htonl(0x38000000); - } - static const uint8 sr_init_dat[] = {0x35, 0x4a, 0xff, 0xfc, 0x7d, 0x86, 0x50, 0x2e}; - if ((base = find_rom_data(0x3101b0, 0x3105b0, sr_init_dat, sizeof(sr_init_dat))) == 0) return false; - D(bug("sr_init %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + loc + 8); - *lp = htonl(0x48000000 | ((base - loc - 8) & 0x3fffffc)); // b ROMBase+0x3101b0 - lp = (uint32 *)(ROMBaseHost + base); - *lp++ = htonl(0x80200000 + XLM_KERNEL_DATA); // lwz r1,(pointer to Kernel Data) - *lp++ = htonl(0x3da0dead); // lis r13,0xdead (start of kernel memory) - *lp++ = htonl(0x3dc00010); // lis r14,0x0010 (size of page table) - *lp = htonl(0x3de00010); // lis r15,0x0010 (size of kernel memory) - - // Don't read PVR - static const uint8 pvr_read_dat[] = {0x7d, 0x9f, 0x42, 0xa6}; - if ((base = find_rom_data(0x3103b0, 0x3108b0, pvr_read_dat, sizeof(pvr_read_dat))) == 0) return false; - D(bug("pvr_read %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x81800000 + XLM_PVR); // lwz r12,(theoretical PVR) - - // Set CPU specific data (even if ROM doesn't have support for that CPU) - if (ntohl(lp[6]) != 0x2c0c0001) - return false; - uint32 ofs = ntohl(lp[7]) & 0xffff; - D(bug("ofs %08lx\n", ofs)); - lp[8] = htonl((ntohl(lp[8]) & 0xffff) | 0x48000000); // beq -> b - loc = (ntohl(lp[8]) & 0xffff) + (uintptr)(lp+8) - (uintptr)ROMBaseHost; - D(bug("loc %08lx\n", loc)); - lp = (uint32 *)(ROMBaseHost + ofs + 0x310000); - switch (PVR >> 16) { - case 1: // 601 - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x8000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00010040); // Unified caches/Inst cache line size - lp[5] = htonl(0x00400020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x01000002); // TLB total size/TLB assoc - break; - case 3: // 603 - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x2000); // Data cache size - lp[2] = htonl(0x2000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00020002); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00400002); // TLB total size/TLB assoc - break; - case 4: // 604 - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x4000); // Data cache size - lp[2] = htonl(0x4000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00800002); // TLB total size/TLB assoc - break; -// case 5: // 740? - case 6: // 603e - case 7: // 603ev - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x4000); // Data cache size - lp[2] = htonl(0x4000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00400002); // TLB total size/TLB assoc - break; - case 8: // 750, 750FX - case 0x7000: - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x8000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00800002); // TLB total size/TLB assoc - break; - case 9: // 604e - case 10: // 604ev5 - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x8000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00040004); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00800002); // TLB total size/TLB assoc - break; -// case 11: // X704? - case 12: // 7400, 7410, 7450, 7455, 7457 - case 0x800c: - case 0x8000: - case 0x8001: - case 0x8002: - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x8000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00800002); // TLB total size/TLB assoc - break; - case 13: // ??? - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x8000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00000020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x01000004); // TLB total size/TLB assoc - break; -// case 50: // 821 -// case 80: // 860 - case 96: // ??? - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x8000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00010020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00200020); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00080008); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x00800004); // TLB total size/TLB assoc - break; - case 0x39: // 970 - lp[0] = htonl(0x1000); // Page size - lp[1] = htonl(0x8000); // Data cache size - lp[2] = htonl(0x10000); // Inst cache size - lp[3] = htonl(0x00200020); // Coherency block size/Reservation granule size - lp[4] = htonl(0x00010020); // Unified caches/Inst cache line size - lp[5] = htonl(0x00200020); // Data cache line size/Data cache block size touch - lp[6] = htonl(0x00800080); // Inst cache block size/Data cache block size - lp[7] = htonl(0x00020002); // Inst cache assoc/Data cache assoc - lp[8] = htonl(0x02000004); // TLB total size/TLB assoc - break; - default: - printf("WARNING: Unknown CPU type\n"); - break; - } - - // Don't set SPRG3, don't test MQ - static const uint8 sprg3_mq_dat[] = {0x7d, 0x13, 0x43, 0xa6, 0x3d, 0x00, 0x00, 0x04, 0x7d, 0x00, 0x03, 0xa6, 0x39, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x02, 0xa6}; - if ((base = find_rom_data(loc + 0x20, loc + 0x60, sprg3_mq_dat, sizeof(sprg3_mq_dat))) == 0) return false; - D(bug("sprg3/mq %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - lp[0] = htonl(POWERPC_NOP); - lp[2] = htonl(POWERPC_NOP); - lp[4] = htonl(POWERPC_NOP); - - // Don't read MSR - static const uint8 msr_dat[] = {0x7d, 0xc0, 0x00, 0xa6}; - if ((base = find_rom_data(loc + 0x40, loc + 0x80, msr_dat, sizeof(msr_dat))) == 0) return false; - D(bug("msr %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x39c00000); // li r14,0 - - // Don't write to DEC - lp = (uint32 *)(ROMBaseHost + loc + 0x70); - *lp++ = htonl(POWERPC_NOP); - loc = (ntohl(lp[0]) & 0xffff) + (uintptr)lp - (uintptr)ROMBaseHost; - D(bug("loc %08lx\n", loc)); - - // Don't set SPRG3 - static const uint8 sprg3_dat[] = {0x39, 0x21, 0x03, 0x60, 0x7d, 0x33, 0x43, 0xa6, 0x39, 0x01, 0x04, 0x20}; - if ((base = find_rom_data(0x310000, 0x314000, sprg3_dat, sizeof(sprg3_dat))) == 0) return false; - D(bug("sprg3 %08lx\n", base + 4)); - lp = (uint32 *)(ROMBaseHost + base + 4); - *lp = htonl(POWERPC_NOP); - - // Don't read PVR - static const uint8 pvr_read2_dat[] = {0x7e, 0xff, 0x42, 0xa6, 0x56, 0xf7, 0x84, 0x3e}; - if ((base = find_rom_data(0x310000, 0x320000, pvr_read2_dat, sizeof(pvr_read2_dat))) == 0) return false; - D(bug("pvr_read2 %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR) - if ((base = find_rom_data(base + 4, 0x320000, pvr_read2_dat, sizeof(pvr_read2_dat))) != 0) { - D(bug("pvr_read2 %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x82e00000 + XLM_PVR); // lwz r23,(theoretical PVR) - } - static const uint8 pvr_read3_dat[] = {0x7e, 0x5f, 0x42, 0xa6, 0x56, 0x52, 0x84, 0x3e}; - if ((base = find_rom_data(0x310000, 0x320000, pvr_read3_dat, sizeof(pvr_read3_dat))) != 0) { - D(bug("pvr_read3 %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x82400000 + XLM_PVR); // lwz r18,(theoretical PVR) - } - static const uint8 pvr_read4_dat[] = {0x7d, 0x3f, 0x42, 0xa6, 0x55, 0x29, 0x84, 0x3e}; - if ((base = find_rom_data(0x310000, 0x320000, pvr_read4_dat, sizeof(pvr_read4_dat))) != 0) { - D(bug("pvr_read4 %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x81200000 + XLM_PVR); // lzw r9,(theoritical PVR) - } - - // Don't read SDR1 - static const uint8 sdr1_read_dat[] = {0x7d, 0x19, 0x02, 0xa6, 0x55, 0x16, 0x81, 0xde}; - if ((base = find_rom_data(0x310000, 0x320000, sdr1_read_dat, sizeof(sdr1_read_dat))) == 0) return false; - D(bug("sdr1_read %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp++ = htonl(0x3d00dead); // lis r8,0xdead (pointer to page table) - *lp++ = htonl(0x3ec0001f); // lis r22,0x001f (size of page table) - *lp = htonl(POWERPC_NOP); - - // Don't clear page table, don't invalidate TLB - static const uint8 pgtb_clear_dat[] = {0x36, 0xd6, 0xff, 0xfc, 0x7e, 0xe8, 0xb1, 0x2e, 0x41, 0x81, 0xff, 0xf8}; - if ((base = find_rom_data(0x310000, 0x320000, pgtb_clear_dat, sizeof(pgtb_clear_dat))) == 0) return false; - D(bug("pgtb_clear %08lx\n", base + 4)); - lp = (uint32 *)(ROMBaseHost + base + 4); - *lp = htonl(POWERPC_NOP); - D(bug("tblie %08lx\n", base + 12)); - lp = (uint32 *)(ROMBaseHost + base + 12); - *lp = htonl(POWERPC_NOP); - - // Don't create RAM descriptor table - static const uint8 desc_create_dat[] = {0x97, 0xfd, 0x00, 0x04, 0x3b, 0xff, 0x10, 0x00, 0x4b, 0xff, 0xff, 0xdc}; - if ((base = find_rom_data(0x310000, 0x320000, desc_create_dat, sizeof(desc_create_dat))) == 0) return false; - D(bug("desc_create %08lx\n", base)) - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(POWERPC_NOP); - - // Don't load SRs and BATs - static const uint8 sr_load[] = {0x7c, 0x00, 0x04, 0xac, 0x83, 0x9d, 0x00, 0x00, 0x93, 0x81, 0x05, 0xe8}; - if ((loc = find_rom_data(0x310000, 0x320000, sr_load, sizeof(sr_load))) == 0) return false; - static const uint8 sr_load_caller[] = {0x3e, 0xd6, 0xff, 0xff, 0x41, 0x81, 0xff, 0xdc, 0xb2, 0xc8, 0x00, 0x02}; - if ((base = find_rom_data(0x310000, 0x320000, sr_load_caller, sizeof(sr_load_caller))) == 0) return false; - if ((base = find_rom_powerpc_branch(base + 12, 0x320000, loc)) == 0) return false; - D(bug("sr_load %08lx, called from %08lx\n", loc, base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(POWERPC_NOP); - - // Don't mess with SRs - static const uint8 sr_load2_dat[] = {0x83, 0xa1, 0x05, 0xe8, 0x57, 0x7c, 0x3e, 0x78, 0x7f, 0xbd, 0xe0, 0x2e}; - if ((base = find_rom_data(0x310000, 0x320000, sr_load2_dat, sizeof(sr_load2_dat))) == 0) return false; - D(bug("sr_load2 %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(POWERPC_BLR); - - // Don't check performance monitor - static const uint8 pm_check_dat[] = {0x7e, 0x58, 0xeb, 0xa6, 0x7e, 0x53, 0x90, 0xf8, 0x7e, 0x78, 0xea, 0xa6}; - if ((base = find_rom_data(0x310000, 0x320000, pm_check_dat, sizeof(pm_check_dat))) == 0) return false; - D(bug("pm_check %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - - static const int spr_check_list[] = { - 952 /* mmcr0 */, 953 /* pmc1 */, 954 /* pmc2 */, 955 /* sia */, - 956 /* mmcr1 */, 957 /* pmc3 */, 958 /* pmc4 */, 959 /* sda */ - }; - - for (int i = 0; i < sizeof(spr_check_list)/sizeof(spr_check_list[0]); i++) { - int spr = spr_check_list[i]; - uint32 mtspr = 0x7e4003a6 | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6); - uint32 mfspr = 0x7e6002a6 | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6); - for (int ofs = 0; ofs < 64; ofs++) { - if (ntohl(lp[ofs]) == mtspr) { - if (ntohl(lp[ofs + 2]) != mfspr) - return false; - D(bug(" SPR%d %08lx\n", spr, base + 4*ofs)); - lp[ofs] = htonl(POWERPC_NOP); - lp[ofs + 2] = htonl(POWERPC_NOP); - } - } - } - - // Jump to 68k emulator - static const uint8 jump68k_dat[] = {0x7d, 0x92, 0x43, 0xa6, 0x7d, 0x5a, 0x03, 0xa6, 0x7d, 0x7b, 0x03, 0xa6}; - if ((loc = find_rom_data(0x310000, 0x320000, jump68k_dat, sizeof(jump68k_dat))) == 0) return false; - static const uint8 jump68k_caller_dat[] = {0x85, 0x13, 0x00, 0x08, 0x56, 0xbf, 0x50, 0x3e, 0x63, 0xff, 0x0c, 0x00}; - if ((base = find_rom_data(0x310000, 0x320000, jump68k_caller_dat, sizeof(jump68k_caller_dat))) == 0) return false; - if ((base = find_rom_powerpc_branch(base + 12, 0x320000, loc)) == 0) return false; - D(bug("jump68k %08lx, called from %08lx\n", loc, base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp++ = htonl(0x80610634); // lwz r3,0x0634(r1) (pointer to Emulator Data) - *lp++ = htonl(0x8081119c); // lwz r4,0x119c(r1) (pointer to opcode table) - *lp++ = htonl(0x80011184); // lwz r0,0x1184(r1) (pointer to emulator init routine) - *lp++ = htonl(0x7c0903a6); // mtctr r0 - *lp = htonl(POWERPC_BCTR); - return true; -} - - -/* - * 68k emulator patches - */ - -static bool patch_68k_emul(void) -{ - uint32 *lp; - uint32 base, loc; - - // Overwrite twi instructions - static const uint8 twi_dat[] = {0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x01, 0x0f, 0xff, 0x00, 0x02}; - if ((base = find_rom_data(0x36e600, 0x36ea00, twi_dat, sizeof(twi_dat))) == 0) return false; - D(bug("twi %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp++ = htonl(0x48000000 + 0x36f900 - base); // b 0x36f900 (Emulator start) - *lp++ = htonl(0x48000000 + 0x36fa00 - base - 4); // b 0x36fa00 (Mixed mode) - *lp++ = htonl(0x48000000 + 0x36fb00 - base - 8); // b 0x36fb00 (Reset/FC1E opcode) - *lp++ = htonl(0x48000000 + 0x36fc00 - base - 12); // FE0A opcode - *lp++ = htonl(POWERPC_ILLEGAL); // Interrupt - *lp++ = htonl(0x48000000 + 0x36fd00 - base - 20); // FE0F opcode - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp++ = htonl(POWERPC_ILLEGAL); - *lp = htonl(POWERPC_ILLEGAL); - -#if EMULATED_PPC - // Install EMUL_RETURN, EXEC_RETURN, EXEC_NATIVE and EMUL_OP opcodes - lp = (uint32 *)(ROMBaseHost + 0x380000 + (M68K_EMUL_RETURN << 3)); - *lp++ = htonl(POWERPC_EMUL_OP); - *lp++ = htonl(0x4bf66e80); // b 0x366084 - *lp++ = htonl(POWERPC_EMUL_OP | 1); - *lp++ = htonl(0x4bf66e78); // b 0x366084 - *lp++ = htonl(POWERPC_EMUL_OP | 2); - *lp++ = htonl(0x4bf66e70); // b 0x366084 - for (int i=0; i> 16)); // lis r0,xxx - *lp++ = htonl(0x60000000 + ((ROMBase + base) & 0xffff)); // ori r0,r0,xxx - *lp++ = htonl(0x7c0803a6); // mtlr r0 - *lp = htonl(POWERPC_BLR); // blr - } - return true; -} - - -/* - * Nanokernel patches - */ - -static bool patch_nanokernel(void) -{ - uint32 *lp; - uint32 base, loc; - - // Patch Mixed Mode trap - static const uint8 virt2phys_dat[] = {0x7d, 0x1b, 0x43, 0x78, 0x3b, 0xa1, 0x03, 0x20}; - if ((base = find_rom_data(0x313000, 0x314000, virt2phys_dat, sizeof(virt2phys_dat))) == 0) return false; - D(bug("virt2phys %08lx\n", base + 8)); - lp = (uint32 *)(ROMBaseHost + base + 8); // Don't translate virtual->physical - lp[0] = htonl(0x7f7fdb78); // mr r31,r27 - lp[2] = htonl(POWERPC_NOP); - - static const uint8 ppc_excp_tbl_dat[] = {0x39, 0x01, 0x04, 0x20, 0x7d, 0x13, 0x43, 0xa6}; - if ((base = find_rom_data(0x313000, 0x314000, ppc_excp_tbl_dat, sizeof(ppc_excp_tbl_dat))) == 0) return false; - D(bug("ppc_excp_tbl %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); // Don't activate PPC exception table - *lp++ = htonl(0x39000000 + MODE_NATIVE); // li r8,MODE_NATIVE - *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE - - static const uint8 save_fpu_dat[] = {0x7d, 0x00, 0x00, 0xa6, 0x61, 0x08, 0x20, 0x00, 0x7d, 0x00, 0x01, 0x24}; - if ((base = find_rom_data(0x310000, 0x314000, save_fpu_dat, sizeof(save_fpu_dat))) == 0) return false; - D(bug("save_fpu %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); // Don't modify MSR to turn on FPU - if (ntohl(lp[4]) != 0x556b04e2) return false; - loc = base; -#if 1 - // FIXME: is that really intended? - *lp++ = htonl(POWERPC_NOP); - lp++; - *lp++ = htonl(POWERPC_NOP); - lp++; - *lp = htonl(POWERPC_NOP); -#else - lp[0] = htonl(POWERPC_NOP); - lp[1] = htonl(POWERPC_NOP); - lp[2] = htonl(POWERPC_NOP); - lp[3] = htonl(POWERPC_NOP); -#endif - - static const uint8 save_fpu_caller_dat[] = {0x93, 0xa6, 0x01, 0xec, 0x93, 0xc6, 0x01, 0xf4, 0x93, 0xe6, 0x01, 0xfc, 0x40}; - if ((base = find_rom_data(0x310000, 0x314000, save_fpu_caller_dat, sizeof(save_fpu_caller_dat))) == 0) return false; - D(bug("save_fpu_caller %08lx\n", base + 12)); - if (rom_powerpc_branch_target(base + 12) != loc) return false; - lp = (uint32 *)(ROMBaseHost + base + 12); // Always save FPU state - *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312e88 - - static const uint8 mdec_dat[] = {0x7f, 0xf6, 0x02, 0xa6, 0x2c, 0x08, 0x00, 0x00, 0x93, 0xe1, 0x06, 0x68, 0x7d, 0x16, 0x03, 0xa6}; - if ((base = find_rom_data(0x310000, 0x314000, mdec_dat, sizeof(mdec_dat))) == 0) return false; - D(bug("mdec %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); // Don't modify DEC - lp[0] = htonl(0x3be00000); // li r31,0 -#if 1 - lp[3] = htonl(POWERPC_NOP); - lp[4] = htonl(POWERPC_NOP); -#else - lp[3] = htonl(0x39000040); // li r8,0x40 - lp[4] = htonl(0x990600e4); // stb r8,0xe4(r6) -#endif - - static const uint8 restore_fpu_caller_dat[] = {0x81, 0x06, 0x00, 0xf4, 0x81, 0x46, 0x00, 0xfc, 0x7d, 0x09, 0x03, 0xa6, 0x40}; - if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_caller_dat, sizeof(restore_fpu_caller_dat))) == 0) return false; - D(bug("restore_fpu_caller %08lx\n", base + 12)); - lp = (uint32 *)(ROMBaseHost + base + 12); // Always restore FPU state - *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312ddc - - static const uint8 m68k_excp_tbl_dat[] = {0x81, 0x21, 0x06, 0x58, 0x39, 0x01, 0x03, 0x60, 0x7d, 0x13, 0x43, 0xa6}; - if ((base = find_rom_data(0x310000, 0x314000, m68k_excp_tbl_dat, sizeof(m68k_excp_tbl_dat))) == 0) return false; - D(bug("m68k_excp %08lx\n", base + 4)); - lp = (uint32 *)(ROMBaseHost + base + 4); // Don't activate 68k exception table - *lp++ = htonl(0x39000000 + MODE_68K); // li r8,MODE_68K - *lp = htonl(0x91000000 + XLM_RUN_MODE); // stw r8,XLM_RUN_MODE - - // Patch 68k emulator trap routine - static const uint8 restore_fpu_caller2_dat[] = {0x81, 0x86, 0x00, 0x8c, 0x80, 0x66, 0x00, 0x94, 0x80, 0x86, 0x00, 0x9c, 0x40}; - if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_caller2_dat, sizeof(restore_fpu_caller2_dat))) == 0) return false; - D(bug("restore_fpu_caller2 %08lx\n", base + 12)); - loc = rom_powerpc_branch_target(base + 12); - lp = (uint32 *)(ROMBaseHost + base + 12); // Always restore FPU state - *lp = htonl(0x48000000 | (ntohl(*lp) & 0xffff)); // bl 0x00312dd4 - - static const uint8 restore_fpu_dat[] = {0x55, 0x68, 0x04, 0xa5, 0x4c, 0x82, 0x00, 0x20, 0x81, 0x06, 0x00, 0xe4}; - if ((base = find_rom_data(0x310000, 0x314000, restore_fpu_dat, sizeof(restore_fpu_dat))) == 0) return false; - D(bug("restore_fpu %08lx\n", base)); - if (base != loc) return false; - lp = (uint32 *)(ROMBaseHost + base + 4); // Don't modify MSR to turn on FPU - *lp++ = htonl(POWERPC_NOP); - lp += 2; - *lp++ = htonl(POWERPC_NOP); - lp++; - *lp++ = htonl(POWERPC_NOP); - *lp++ = htonl(POWERPC_NOP); - *lp = htonl(POWERPC_NOP); - - // Disable suspend (FE0F opcode) - // TODO: really suspend SheepShaver? - static const uint8 suspend_dat[] = {0x7c, 0x88, 0x68, 0x39, 0x41, 0x9d}; - if ((base = find_rom_data(0x315000, 0x316000, suspend_dat, sizeof(suspend_dat))) == 0) return false; - D(bug("suspend %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base + 4); - *lp = htonl((ntohl(*lp) & 0xffff) | 0x48000000); // bgt -> b - - // Patch trap return routine - static const uint8 trap_return_dat[] = {0x80, 0xc1, 0x00, 0x18, 0x80, 0x21, 0x00, 0x04, 0x4c, 0x00, 0x00, 0x64}; - if ((base = find_rom_data(0x312000, 0x320000, trap_return_dat, sizeof(trap_return_dat))) == 0) return false; - D(bug("trap_return %08lx\n", base + 8)); - lp = (uint32 *)(ROMBaseHost + base + 8); // Replace rfi - *lp = htonl(POWERPC_BCTR); - - while (ntohl(*lp) != 0x7d5a03a6) lp--; - *lp++ = htonl(0x7d4903a6); // mtctr r10 - *lp++ = htonl(0x7daff120); // mtcr r13 - *lp = htonl(0x48000000 + ((0x318000 - ((uintptr)lp - (uintptr)ROMBaseHost)) & 0x03fffffc)); // b ROMBase+0x318000 - uint32 npc = (uintptr)(lp + 1) - (uintptr)ROMBaseHost; - - lp = (uint32 *)(ROMBaseHost + 0x318000); - *lp++ = htonl(0x81400000 + XLM_IRQ_NEST); // lwz r10,XLM_IRQ_NEST - *lp++ = htonl(0x394affff); // subi r10,r10,1 - *lp++ = htonl(0x91400000 + XLM_IRQ_NEST); // stw r10,XLM_IRQ_NEST - *lp = htonl(0x48000000 + ((npc - 0x31800c) & 0x03fffffc)); // b ROMBase+0x312c2c - - // Patch FEOA opcode, selector 0x0A (virtual->physical page index) - static const uint8 fe0a_0a_dat[] = {0x55, 0x23, 0xa3, 0x3e, 0x4b}; - if ((base = find_rom_data(0x314000, 0x318000, fe0a_0a_dat, sizeof(fe0a_0a_dat))) == 0) return false; - loc = rom_powerpc_branch_target(base - 8); - static const uint8 fe0a_dat[] = {0x7e, 0x04, 0x48, 0x40, 0x81, 0xe1, 0x06, 0xb0, 0x54, 0x88, 0x10, 0x3a, 0x40, 0x90}; - if (find_rom_data(loc, 0x318000, fe0a_dat, sizeof(fe0a_dat)) != loc) return false; - D(bug("fe0a_0a %08lx\n", base - 8)); - lp = (uint32 *)(ROMBaseHost + base - 8); - *lp++ = htonl(0x7c832378); // mr r3,r4 - *lp++ = htonl(POWERPC_NOP); - *lp = htonl(POWERPC_NOP); - - // Disable FE0A opcode, selector 0x11 (init page tables?) - static const uint8 fe0a_11_dat[] = {0x56, 0x07, 0x06, 0x74, 0x2c, 0x07, 0x00, 0x60, 0x40}; - if ((base = find_rom_data(0x314000, 0x318000, fe0a_11_dat, sizeof(fe0a_11_dat))) == 0) return false; - loc = rom_powerpc_branch_target(base - 4); - if (find_rom_data(0x314000, 0x318000, fe0a_dat, sizeof(fe0a_dat)) != loc) return false; - D(bug("fe0a_11 %08lx\n", base - 4)); - lp = (uint32 *)(ROMBaseHost + base - 4); - *lp++ = htonl(POWERPC_NOP); - *lp++ = htonl(POWERPC_NOP); - *lp++ = htonl(POWERPC_NOP); - *lp = htonl(ntohl(*lp) | 0x02800000); // bf => ba - - // Patch FE0A opcode to fake a page table entry so that V=P for RAM and ROM - static const uint8 pg_lookup_dat[] = {0x7e, 0x0f, 0x40, 0x6e, 0x81, 0xc1, 0x06, 0xa4, 0x7e, 0x00, 0x71, 0x20}; - if ((base = find_rom_data(0x310000, 0x320000, pg_lookup_dat, sizeof(pg_lookup_dat))) == 0) return false; - D(bug("fe0a_pgtb_lookup %08lx\n", base - 12)); - lp = (uint32 *)(ROMBaseHost + base - 12); - if (ntohl(lp[0]) != 0x81e106b0) // lwz r15,$06b0(r1) - return false; - lp[0] = htonl(0x54906026); // slwi r16,r4,12 - lp[3] = htonl(0x62100121); // ori r16,r16,0x121 - - // Patch FE0A opcode to not write to kernel memory - static const uint8 krnl_write_dat[] = {0x38, 0xe0, 0x00, 0x01, 0x7e, 0x10, 0x38, 0x78, 0x92, 0x0f, 0x00, 0x00}; - if ((base = find_rom_data(0x310000, 0x320000, krnl_write_dat, sizeof(krnl_write_dat))) == 0) return false; - D(bug("fe0a_krnl_write %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - lp[2] = htonl(POWERPC_NOP); - -/* - // Disable FE0A/FE06 opcodes - lp = (uint32 *)(ROMBase + 0x3144ac); - *lp++ = htonl(POWERPC_NOP); - *lp += 8; -*/ - return true; -} - - -/* - * 68k boot routine patches - */ - -static bool patch_68k(void) -{ - uint32 *lp; - uint16 *wp; - uint8 *bp; - uint32 base, loc; - - // Remove 68k RESET instruction - static const uint8 reset_dat[] = {0x4e, 0x70}; - if ((base = find_rom_data(0xc8, 0x120, reset_dat, sizeof(reset_dat))) == 0) return false; - D(bug("reset %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp = htons(M68K_NOP); - - // Fake reading PowerMac ID (via Universal) - static const uint8 powermac_id_dat[] = {0x45, 0xf9, 0x5f, 0xff, 0xff, 0xfc, 0x20, 0x12, 0x72, 0x00}; - if ((base = find_rom_data(0xe000, 0x15000, powermac_id_dat, sizeof(powermac_id_dat))) == 0) return false; - D(bug("powermac_id %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x203c); // move.l #id,d0 - *wp++ = htons(0); -// if (ROMType == ROMTYPE_NEWWORLD) -// *wp++ = htons(0x3035); // (PowerMac 9500 ID) -// else - *wp++ = htons(0x3020); // (PowerMac 9500 ID) - *wp++ = htons(0xb040); // cmp.w d0,d0 - *wp = htons(0x4ed6); // jmp (a6) - - // Patch UniversalInfo - if (ROMType == ROMTYPE_NEWWORLD) { - static const uint8 univ_info_dat[] = {0x3f, 0xff, 0x04, 0x00}; - if ((base = find_rom_data(0x14000, 0x18000, univ_info_dat, sizeof(univ_info_dat))) == 0) return false; - D(bug("universal_info %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base - 0x14); - lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); - lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo - lp[0x14 >> 2] = htonl(0x3fff0401); - lp[0x18 >> 2] = htonl(0x0300001c); - lp[0x1c >> 2] = htonl(0x000108c4); - lp[0x24 >> 2] = htonl(0xc301bf26); - lp[0x28 >> 2] = htonl(0x00000861); - lp[0x58 >> 2] = htonl(0x30200000); - lp[0x60 >> 2] = htonl(0x0000003d); - } else if (ROMType == ROMTYPE_ZANZIBAR) { - base = 0x12b70; - lp = (uint32 *)(ROMBaseHost + base - 0x14); - lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); - lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo - lp[0x14 >> 2] = htonl(0x3fff0401); - lp[0x18 >> 2] = htonl(0x0300001c); - lp[0x1c >> 2] = htonl(0x000108c4); - lp[0x24 >> 2] = htonl(0xc301bf26); - lp[0x28 >> 2] = htonl(0x00000861); - lp[0x58 >> 2] = htonl(0x30200000); - lp[0x60 >> 2] = htonl(0x0000003d); - } else if (ROMType == ROMTYPE_GOSSAMER) { - base = 0x12d20; - lp = (uint32 *)(ROMBaseHost + base - 0x14); - lp[0x00 >> 2] = htonl(ADDR_MAP_PATCH_SPACE - (base - 0x14)); - lp[0x10 >> 2] = htonl(0xcc003d11); // Make it like the PowerMac 9500 UniversalInfo - lp[0x14 >> 2] = htonl(0x3fff0401); - lp[0x18 >> 2] = htonl(0x0300001c); - lp[0x1c >> 2] = htonl(0x000108c4); - lp[0x24 >> 2] = htonl(0xc301bf26); - lp[0x28 >> 2] = htonl(0x00000861); - lp[0x58 >> 2] = htonl(0x30410000); - lp[0x60 >> 2] = htonl(0x0000003d); - } - - // Construct AddrMap for NewWorld ROM - if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) { - lp = (uint32 *)(ROMBaseHost + ADDR_MAP_PATCH_SPACE); - memset(lp - 10, 0, 0x128); - lp[-10] = htonl(0x0300001c); - lp[-9] = htonl(0x000108c4); - lp[-4] = htonl(0x00300000); - lp[-2] = htonl(0x11010000); - lp[-1] = htonl(0xf8000000); - lp[0] = htonl(0xffc00000); - lp[2] = htonl(0xf3016000); - lp[3] = htonl(0xf3012000); - lp[4] = htonl(0xf3012000); - lp[24] = htonl(0xf3018000); - lp[25] = htonl(0xf3010000); - lp[34] = htonl(0xf3011000); - lp[38] = htonl(0xf3015000); - lp[39] = htonl(0xf3014000); - lp[43] = htonl(0xf3000000); - lp[48] = htonl(0xf8000000); - } - - // Don't initialize VIA (via Universal) - static const uint8 via_init_dat[] = {0x08, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x2c, 0x24, 0x68, 0x00, 0x08}; - if ((base = find_rom_data(0xe000, 0x15000, via_init_dat, sizeof(via_init_dat))) == 0) return false; - D(bug("via_init %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 4); - *wp = htons(0x6000); // bra - - static const uint8 via_init2_dat[] = {0x24, 0x68, 0x00, 0x08, 0x00, 0x12, 0x00, 0x30, 0x4e, 0x71}; - if ((base = find_rom_data(0xa000, 0x10000, via_init2_dat, sizeof(via_init2_dat))) == 0) return false; - D(bug("via_init2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp = htons(0x4ed6); // jmp (a6) - - static const uint8 via_init3_dat[] = {0x22, 0x68, 0x00, 0x08, 0x28, 0x3c, 0x20, 0x00, 0x01, 0x00}; - if ((base = find_rom_data(0xa000, 0x10000, via_init3_dat, sizeof(via_init3_dat))) == 0) return false; - D(bug("via_init3 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp = htons(0x4ed6); // jmp (a6) - - // Don't RunDiags, get BootGlobs pointer directly - if (ROMType == ROMTYPE_NEWWORLD) { - static const uint8 run_diags_dat[] = {0x60, 0xff, 0x00, 0x0c}; - if ((base = find_rom_data(0x110, 0x128, run_diags_dat, sizeof(run_diags_dat))) == 0) return false; - D(bug("run_diags %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x4df9); // lea xxx,a6 - *wp++ = htons((RAMBase + RAMSize - 0x1c) >> 16); - *wp = htons((RAMBase + RAMSize - 0x1c) & 0xffff); - } else { - static const uint8 run_diags_dat[] = {0x74, 0x00, 0x2f, 0x0e}; - if ((base = find_rom_data(0xd0, 0xf0, run_diags_dat, sizeof(run_diags_dat))) == 0) return false; - D(bug("run_diags %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base - 6); - *wp++ = htons(0x4df9); // lea xxx,a6 - *wp++ = htons((RAMBase + RAMSize - 0x1c) >> 16); - *wp = htons((RAMBase + RAMSize - 0x1c) & 0xffff); - } - - // Replace NVRAM routines - static const uint8 nvram1_dat[] = {0x48, 0xe7, 0x01, 0x0e, 0x24, 0x68, 0x00, 0x08, 0x08, 0x83, 0x00, 0x1f}; - if ((base = find_rom_data(0x7000, 0xc000, nvram1_dat, sizeof(nvram1_dat))) == 0) return false; - D(bug("nvram1 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_EMUL_OP_XPRAM1); - *wp = htons(M68K_RTS); - - if (ROMType == ROMTYPE_NEWWORLD) { - static const uint8 nvram2_dat[] = {0x48, 0xe7, 0x1c, 0xe0, 0x4f, 0xef, 0xff, 0xb4}; - if ((base = find_rom_data(0xa000, 0xd000, nvram2_dat, sizeof(nvram2_dat))) == 0) return false; - D(bug("nvram2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_EMUL_OP_XPRAM2); - *wp = htons(0x4ed3); // jmp (a3) - - static const uint8 nvram3_dat[] = {0x48, 0xe7, 0xdc, 0xe0, 0x4f, 0xef, 0xff, 0xb4}; - if ((base = find_rom_data(0xa000, 0xd000, nvram3_dat, sizeof(nvram3_dat))) == 0) return false; - D(bug("nvram3 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_EMUL_OP_XPRAM3); - *wp = htons(0x4ed3); // jmp (a3) - - static const uint8 nvram4_dat[] = {0x4e, 0x56, 0xff, 0xa8, 0x48, 0xe7, 0x1f, 0x38, 0x16, 0x2e, 0x00, 0x13}; - if ((base = find_rom_data(0xa000, 0xd000, nvram4_dat, sizeof(nvram4_dat))) == 0) return false; - D(bug("nvram4 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 16); - *wp++ = htons(0x1a2e); // move.b ($000f,a6),d5 - *wp++ = htons(0x000f); - *wp++ = htons(M68K_EMUL_OP_NVRAM3); - *wp++ = htons(0x4cee); // movem.l ($ff88,a6),d3-d7/a2-a4 - *wp++ = htons(0x1cf8); - *wp++ = htons(0xff88); - *wp++ = htons(0x4e5e); // unlk a6 - *wp = htons(M68K_RTS); - - static const uint8 nvram5_dat[] = {0x0c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x66, 0x0a, 0x70, 0x00, 0x21, 0xf8, 0x02, 0x0c, 0x01, 0xe4}; - if ((base = find_rom_data(0xa000, 0xd000, nvram5_dat, sizeof(nvram5_dat))) == 0) return false; - D(bug("nvram5 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 6); - *wp = htons(M68K_NOP); - - static const uint8 nvram6_dat[] = {0x2f, 0x0a, 0x24, 0x48, 0x4f, 0xef, 0xff, 0xa0, 0x20, 0x0f}; - if ((base = find_rom_data(0x9000, 0xb000, nvram6_dat, sizeof(nvram6_dat))) == 0) return false; - D(bug("nvram6 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x7000); // moveq #0,d0 - *wp++ = htons(0x2080); // move.l d0,(a0) - *wp++ = htons(0x4228); // clr.b 4(a0) - *wp++ = htons(0x0004); - *wp = htons(M68K_RTS); - - static const uint8 nvram7_dat[] = {0x42, 0x2a, 0x00, 0x04, 0x4f, 0xef, 0x00, 0x60, 0x24, 0x5f, 0x4e, 0x75, 0x4f, 0xef, 0xff, 0xa0, 0x20, 0x0f}; - base = find_rom_data(0x9000, 0xb000, nvram7_dat, sizeof(nvram7_dat)); - if (base) { - D(bug("nvram7 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 12); - *wp = htons(M68K_RTS); - } - } else { - static const uint8 nvram2_dat[] = {0x4e, 0xd6, 0x06, 0x41, 0x13, 0x00}; - if ((base = find_rom_data(0x7000, 0xb000, nvram2_dat, sizeof(nvram2_dat))) == 0) return false; - D(bug("nvram2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 2); - *wp++ = htons(M68K_EMUL_OP_XPRAM2); - *wp = htons(0x4ed3); // jmp (a3) - - static const uint8 nvram3_dat[] = {0x4e, 0xd3, 0x06, 0x41, 0x13, 0x00}; - if ((base = find_rom_data(0x7000, 0xb000, nvram3_dat, sizeof(nvram3_dat))) == 0) return false; - D(bug("nvram3 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 2); - *wp++ = htons(M68K_EMUL_OP_XPRAM3); - *wp = htons(0x4ed3); // jmp (a3) - - static const uint32 nvram4_loc[] = {0x582f0, 0xa0a0, 0x7e50, 0xa1d0, 0x538d0, 0}; - wp = (uint16 *)(ROMBaseHost + nvram4_loc[ROMType]); - *wp++ = htons(0x202f); // move.l 4(sp),d0 - *wp++ = htons(0x0004); - *wp++ = htons(M68K_EMUL_OP_NVRAM1); - if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE) - *wp = htons(M68K_RTS); - else { - *wp++ = htons(0x1f40); // move.b d0,8(sp) - *wp++ = htons(0x0008); - *wp++ = htons(0x4e74); // rtd #4 - *wp = htons(0x0004); - } - - static const uint32 nvram5_loc[] = {0x58460, 0xa0f0, 0x7f40, 0xa220, 0x53a20, 0}; - wp = (uint16 *)(ROMBaseHost + nvram5_loc[ROMType]); - if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GAZELLE) { - *wp++ = htons(0x202f); // move.l 4(sp),d0 - *wp++ = htons(0x0004); - *wp++ = htons(0x122f); // move.b 11(sp),d1 - *wp++ = htons(0x000b); - *wp++ = htons(M68K_EMUL_OP_NVRAM2); - *wp = htons(M68K_RTS); - } else { - *wp++ = htons(0x202f); // move.l 6(sp),d0 - *wp++ = htons(0x0006); - *wp++ = htons(0x122f); // move.b 4(sp),d1 - *wp++ = htons(0x0004); - *wp++ = htons(M68K_EMUL_OP_NVRAM2); - *wp++ = htons(0x4e74); // rtd #6 - *wp = htons(0x0006); - } - } - - // Fix MemTop/BootGlobs during system startup - static const uint8 mem_top_dat[] = {0x2c, 0x6c, 0xff, 0xec, 0x2a, 0x4c, 0xdb, 0xec, 0xff, 0xf4}; - if ((base = find_rom_data(0x120, 0x180, mem_top_dat, sizeof(mem_top_dat))) == 0) return false; - D(bug("mem_top %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_EMUL_OP_FIX_MEMTOP); - *wp = htons(M68K_NOP); - - // Don't initialize SCC (via 0x1ac) - static const uint8 scc_init_caller_dat[] = {0x21, 0xce, 0x01, 0x08, 0x22, 0x78, 0x0d, 0xd8}; - if ((base = find_rom_data(0x180, 0x1f0, scc_init_caller_dat, sizeof(scc_init_caller_dat))) == 0) return false; - D(bug("scc_init_caller %08lx\n", base + 12)); - wp = (uint16 *)(ROMBaseHost + base + 12); - loc = ntohs(wp[1]) + ((uintptr)wp - (uintptr)ROMBaseHost) + 2; - static const uint8 scc_init_dat[] = {0x20, 0x78, 0x01, 0xdc, 0x22, 0x78, 0x01, 0xd8}; - if ((base = find_rom_data(loc, loc + 0x80, scc_init_dat, sizeof(scc_init_dat))) == 0) return false; - D(bug("scc_init %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_EMUL_OP_RESET); - *wp = htons(M68K_RTS); - - // Don't EnableExtCache (via 0x1f6) and don't DisableIntSources(via 0x1fc) - static const uint8 ext_cache_dat[] = {0x4e, 0x7b, 0x00, 0x02}; - if ((base = find_rom_data(0x1d0, 0x230, ext_cache_dat, sizeof(ext_cache_dat))) == 0) return false; - D(bug("ext_cache %08lx\n", base)); - loc = ReadMacInt32(ROMBase + base + 6); - wp = (uint16 *)(ROMBaseHost + loc + base + 6); - *wp = htons(M68K_RTS); - loc = ReadMacInt32(ROMBase + base + 12); - wp = (uint16 *)(ROMBaseHost + loc + base + 12); - *wp = htons(M68K_RTS); - - // Fake CPU speed test (SetupTimeK) - static const uint8 timek_dat[] = {0x0c, 0x38, 0x00, 0x04, 0x01, 0x2f, 0x6d, 0x3c}; - if ((base = find_rom_data(0x400, 0x500, timek_dat, sizeof(timek_dat))) == 0) return false; - D(bug("timek %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x31fc); // move.w #xxx,TimeDBRA - *wp++ = htons(100); - *wp++ = htons(0x0d00); - *wp++ = htons(0x31fc); // move.w #xxx,TimeSCCDBRA - *wp++ = htons(100); - *wp++ = htons(0x0d02); - *wp++ = htons(0x31fc); // move.w #xxx,TimeSCSIDBRA - *wp++ = htons(100); - *wp++ = htons(0x0b24); - *wp++ = htons(0x31fc); // move.w #xxx,TimeRAMDBRA - *wp++ = htons(100); - *wp++ = htons(0x0cea); - *wp = htons(M68K_RTS); - - // Relocate jump tables ($2000..) - static const uint8 jump_tab_dat[] = {0x41, 0xfa, 0x00, 0x0e, 0x21, 0xc8, 0x20, 0x10, 0x4e, 0x75}; - if ((base = find_rom_data(0x3000, 0x6000, jump_tab_dat, sizeof(jump_tab_dat))) == 0) return false; - D(bug("jump_tab %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base + 16); - for (;;) { - D(bug(" %08lx\n", (uintptr)lp - (uintptr)ROMBaseHost)); - while ((ntohl(*lp) & 0xff000000) == 0xff000000) { - *lp = htonl((ntohl(*lp) & (ROM_SIZE-1)) + ROMBase); - lp++; - } - while (!ntohl(*lp)) lp++; - if (ntohl(*lp) != 0x41fa000e) - break; - lp += 4; - } - - // Create SysZone at start of Mac RAM (SetSysAppZone, via 0x22a) - static const uint8 sys_zone_dat[] = {0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x00}; - if ((base = find_rom_data(0x600, 0x900, sys_zone_dat, sizeof(sys_zone_dat))) == 0) return false; - D(bug("sys_zone %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp++ = htonl(RAMBase ? RAMBase : 0x3000); - *lp = htonl(RAMBase ? RAMBase + 0x1800 : 0x4800); - - // Set boot stack at RAMBase+4MB and fix logical/physical RAM size (CompBootStack) - // The RAM size fix must be done after InitMemMgr! - static const uint8 boot_stack_dat[] = {0x08, 0x38, 0x00, 0x06, 0x24, 0x0b}; - if ((base = find_rom_data(0x580, 0x800, boot_stack_dat, sizeof(boot_stack_dat))) == 0) return false; - D(bug("boot_stack %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x207c); // move.l #RAMBase+0x3ffffe,a0 - *wp++ = htons((RAMBase + 0x3ffffe) >> 16); - *wp++ = htons((RAMBase + 0x3ffffe) & 0xffff); - *wp++ = htons(M68K_EMUL_OP_FIX_MEMSIZE); - *wp = htons(M68K_RTS); - - // Get PowerPC page size (InitVMemMgr, via 0x240) - static const uint8 page_size_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x10}; - if ((base = find_rom_data(0xb000, 0x12000, page_size_dat, sizeof(page_size_dat))) == 0) return false; - D(bug("page_size %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x203c); // move.l #$1000,d0 - *wp++ = htons(0); - *wp++ = htons(0x1000); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - - // Gestalt PowerPC page size, CPU type, RAM size (InitGestalt, via 0x25c) - static const uint8 page_size2_dat[] = {0x26, 0x79, 0x5f, 0xff, 0xef, 0xd8, 0x25, 0x6b, 0x00, 0x10, 0x00, 0x1e}; - if ((base = find_rom_data(0x50000, 0x70000, page_size2_dat, sizeof(page_size2_dat))) == 0) return false; - D(bug("page_size2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x257c); // move.l #$1000,$1e(a2) - *wp++ = htons(0); - *wp++ = htons(0x1000); - *wp++ = htons(0x001e); - *wp++ = htons(0x157c); // move.b #PVR,$1d(a2) - uint32 cput = (PVR >> 16); - if (cput == 0x7000) - cput |= 0x20; - else if (cput >= 0x8000 && cput <= 0x8002) - cput |= 0x10; - cput &= 0xff; - *wp++ = htons(cput); - *wp++ = htons(0x001d); - *wp++ = htons(0x263c); // move.l #RAMSize,d3 - *wp++ = htons(RAMSize >> 16); - *wp++ = htons(RAMSize & 0xffff); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - if (ROMType == ROMTYPE_NEWWORLD) - wp = (uint16 *)(ROMBaseHost + base + 0x4a); - else - wp = (uint16 *)(ROMBaseHost + base + 0x28); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - - // Gestalt CPU/bus clock speed (InitGestalt, via 0x25c) - if (ROMType == ROMTYPE_ZANZIBAR) { - wp = (uint16 *)(ROMBaseHost + 0x5d87a); - *wp++ = htons(0x203c); // move.l #Hz,d0 - *wp++ = htons(BusClockSpeed >> 16); - *wp++ = htons(BusClockSpeed & 0xffff); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - wp = (uint16 *)(ROMBaseHost + 0x5d888); - *wp++ = htons(0x203c); // move.l #Hz,d0 - *wp++ = htons(CPUClockSpeed >> 16); - *wp++ = htons(CPUClockSpeed & 0xffff); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - } - - // Don't write to GC interrupt mask register (via 0x262) - if (ROMType != ROMTYPE_NEWWORLD) { - static const uint8 gc_mask_dat[] = {0x83, 0xa8, 0x00, 0x24, 0x4e, 0x71}; - if ((base = find_rom_data(0x13000, 0x20000, gc_mask_dat, sizeof(gc_mask_dat))) == 0) return false; - D(bug("gc_mask %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - wp = (uint16 *)(ROMBaseHost + base + 0x40); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - wp = (uint16 *)(ROMBaseHost + base + 0x78); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - wp = (uint16 *)(ROMBaseHost + base + 0x96); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - - static const uint8 gc_mask2_dat[] = {0x02, 0xa8, 0x00, 0x00, 0x00, 0x80, 0x00, 0x24}; - if ((base = find_rom_data(0x13000, 0x20000, gc_mask2_dat, sizeof(gc_mask2_dat))) == 0) return false; - D(bug("gc_mask2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - if (ROMType == ROMTYPE_GOSSAMER) { - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - } - for (int i=0; i<5; i++) { - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - wp += 2; - } - if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_GOSSAMER) { - for (int i=0; i<6; i++) { - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - wp += 2; - } - } - } - - // Don't initialize Cuda (via 0x274) - static const uint8 cuda_init_dat[] = {0x08, 0xa9, 0x00, 0x04, 0x16, 0x00, 0x4e, 0x71, 0x13, 0x7c, 0x00, 0x84, 0x1c, 0x00, 0x4e, 0x71}; - if ((base = find_rom_data(0xa000, 0x12000, cuda_init_dat, sizeof(cuda_init_dat))) == 0) return false; - D(bug("cuda_init %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - - // Patch GetCPUSpeed (via 0x27a) (some ROMs have two of them) - static const uint8 cpu_speed_dat[] = {0x20, 0x30, 0x81, 0xf2, 0x5f, 0xff, 0xef, 0xd8, 0x00, 0x04, 0x4c, 0x7c}; - if ((base = find_rom_data(0x6000, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) == 0) return false; - D(bug("cpu_speed %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 - *wp++ = htons(CPUClockSpeed / 1000000); - *wp++ = htons(CPUClockSpeed / 1000000); - *wp = htons(M68K_RTS); - if ((base = find_rom_data(base, 0xa000, cpu_speed_dat, sizeof(cpu_speed_dat))) != 0) { - D(bug("cpu_speed2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x203c); // move.l #(MHz<<16)|MHz,d0 - *wp++ = htons(CPUClockSpeed / 1000000); - *wp++ = htons(CPUClockSpeed / 1000000); - *wp = htons(M68K_RTS); - } - - // Don't poke VIA in InitTimeMgr (via 0x298) - static const uint8 time_via_dat[] = {0x40, 0xe7, 0x00, 0x7c, 0x07, 0x00, 0x28, 0x78, 0x01, 0xd4, 0x43, 0xec, 0x10, 0x00}; - if ((base = find_rom_data(0x30000, 0x40000, time_via_dat, sizeof(time_via_dat))) == 0) return false; - D(bug("time_via %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4 - *wp++ = htons(0x1f3f); - *wp = htons(M68K_RTS); - - // Don't read from 0xff800000 (Name Registry, Open Firmware?) (via 0x2a2) - // Remove this if FE03 works!! - static const uint8 open_firmware_dat[] = {0x2f, 0x79, 0xff, 0x80, 0x00, 0x00, 0x00, 0xfc}; - if ((base = find_rom_data(0x48000, 0x58000, open_firmware_dat, sizeof(open_firmware_dat))) == 0) return false; - D(bug("open_firmware %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x2f7c); // move.l #deadbeef,0xfc(a7) - *wp++ = htons(0xdead); - *wp++ = htons(0xbeef); - *wp = htons(0x00fc); - wp = (uint16 *)(ROMBaseHost + base + 0x1a); - *wp++ = htons(M68K_NOP); // (FE03 opcode, tries to jump to 0xdeadbeef) - *wp = htons(M68K_NOP); - - // Don't EnableExtCache (via 0x2b2) - static const uint8 ext_cache2_dat[] = {0x4f, 0xef, 0xff, 0xec, 0x20, 0x4f, 0x10, 0xbc, 0x00, 0x01, 0x11, 0x7c, 0x00, 0x1b}; - if ((base = find_rom_data(0x13000, 0x20000, ext_cache2_dat, sizeof(ext_cache2_dat))) == 0) return false; - D(bug("ext_cache2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp = htons(M68K_RTS); - - // Don't install Time Manager task for 60Hz interrupt (Enable60HzInts, via 0x2b8) - if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) { - static const uint8 tm_task_dat[] = {0x30, 0x3c, 0x4e, 0x2b, 0xa9, 0xc9}; - if ((base = find_rom_data(0x2a0, 0x320, tm_task_dat, sizeof(tm_task_dat))) == 0) return false; - D(bug("tm_task %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 28); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - } else { - static const uint8 tm_task_dat[] = {0x20, 0x3c, 0x73, 0x79, 0x73, 0x61}; - if ((base = find_rom_data(0x280, 0x300, tm_task_dat, sizeof(tm_task_dat))) == 0) return false; - D(bug("tm_task %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base - 6); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - } - - // Don't read PVR from 0x5fffef80 in DriverServicesLib (via 0x316) - if (ROMType != ROMTYPE_NEWWORLD && ROMType != ROMTYPE_GOSSAMER) { - uint32 dsl_offset = find_rom_resource(FOURCC('n','l','i','b'), -16401); - if (ROMType == ROMTYPE_ZANZIBAR) { - static const uint8 dsl_pvr_dat[] = {0x40, 0x82, 0x00, 0x40, 0x38, 0x60, 0xef, 0x80, 0x3c, 0x63, 0x60, 0x00, 0x80, 0x83, 0x00, 0x00, 0x54, 0x84, 0x84, 0x3e}; - if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_pvr_dat, sizeof(dsl_pvr_dat))) == 0) return false; - } else { - static const uint8 dsl_pvr_dat[] = {0x3b, 0xc3, 0x00, 0x00, 0x30, 0x84, 0xff, 0xa0, 0x40, 0x82, 0x00, 0x44, 0x80, 0x84, 0xef, 0xe0, 0x54, 0x84, 0x84, 0x3e}; - if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_pvr_dat, sizeof(dsl_pvr_dat))) == 0) return false; - } - D(bug("dsl_pvr %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base + 12); - *lp = htonl(0x3c800000 | (PVR >> 16)); // lis r4,PVR - - // Don't read bus clock from 0x5fffef88 in DriverServicesLib (via 0x316) - if (ROMType == ROMTYPE_ZANZIBAR) { - static const uint8 dsl_bus_dat[] = {0x81, 0x07, 0x00, 0x00, 0x39, 0x20, 0x42, 0x40, 0x81, 0x62, 0xff, 0x20}; - if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_bus_dat, sizeof(dsl_bus_dat))) == 0) return false; - D(bug("dsl_bus %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x81000000 + XLM_BUS_CLOCK); // lwz r8,(bus clock speed) - } else { - static const uint8 dsl_bus_dat[] = {0x80, 0x83, 0xef, 0xe8, 0x80, 0x62, 0x00, 0x10, 0x7c, 0x04, 0x03, 0x96}; - if ((base = find_rom_data(dsl_offset, dsl_offset + 0x6000, dsl_bus_dat, sizeof(dsl_bus_dat))) == 0) return false; - D(bug("dsl_bus %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x80800000 + XLM_BUS_CLOCK); // lwz r4,(bus clock speed) - } - } - - // Don't open InterruptTreeTNT in MotherBoardHAL init in DriverServicesLib init - if (ROMType == ROMTYPE_ZANZIBAR) { - lp = (uint32 *)(ROMBaseHost + find_rom_resource(FOURCC('n','l','i','b'), -16408) + 0x16c); - *lp = htonl(0x38600000); // li r3,0 - } - - // Don't read from MacPgm in WipeOutMACPGMINFOProcPtrs (StdCLib) - if (1) { - uint32 hpchk_offset = find_rom_resource(FOURCC('n','l','i','b'), 10); - static const uint8 hpchk_dat[] = {0x80, 0x80, 0x03, 0x16, 0x94, 0x21, 0xff, 0xb0, 0x83, 0xc4, 0x00, 0x04}; - if ((base = find_rom_data(hpchk_offset, hpchk_offset + 0x3000, hpchk_dat, sizeof(hpchk_dat))) == 0) return false; - D(bug("macpgm %08lx\n", base)); - lp = (uint32 *)(ROMBaseHost + base); - *lp = htonl(0x80800000 + XLM_ZERO_PAGE); // lwz r4,(zero page) - } - - // Patch Name Registry - static const uint8 name_reg_dat[] = {0x70, 0xff, 0xab, 0xeb}; - if ((base = find_rom_data(0x300, 0x380, name_reg_dat, sizeof(name_reg_dat))) == 0) return false; - D(bug("name_reg %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp = htons(M68K_EMUL_OP_NAME_REGISTRY); - -#if DISABLE_SCSI - // Fake SCSI Manager - // Remove this if SCSI Manager works!! - static const uint8 scsi_mgr_a_dat[] = {0x4e, 0x56, 0x00, 0x00, 0x20, 0x3c, 0x00, 0x00, 0x04, 0x0c, 0xa7, 0x1e}; - static const uint8 scsi_mgr_b_dat[] = {0x4e, 0x56, 0x00, 0x00, 0x2f, 0x0c, 0x20, 0x3c, 0x00, 0x00, 0x04, 0x0c, 0xa7, 0x1e}; - if ((base = find_rom_data(0x1c000, 0x28000, scsi_mgr_a_dat, sizeof(scsi_mgr_a_dat))) == 0) { - if ((base = find_rom_data(0x1c000, 0x28000, scsi_mgr_b_dat, sizeof(scsi_mgr_b_dat))) == 0) return false; - } - D(bug("scsi_mgr %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x21fc); // move.l #xxx,0x624 (SCSIAtomic) - *wp++ = htons((ROMBase + base + 18) >> 16); - *wp++ = htons((ROMBase + base + 18) & 0xffff); - *wp++ = htons(0x0624); - *wp++ = htons(0x21fc); // move.l #xxx,0xe54 (SCSIDispatch) - *wp++ = htons((ROMBase + base + 22) >> 16); - *wp++ = htons((ROMBase + base + 22) & 0xffff); - *wp++ = htons(0x0e54); - *wp++ = htons(M68K_RTS); - *wp++ = htons(M68K_EMUL_OP_SCSI_ATOMIC); - *wp++ = htons(M68K_RTS); - *wp++ = htons(M68K_EMUL_OP_SCSI_DISPATCH); - *wp = htons(0x4ed0); // jmp (a0) - wp = (uint16 *)(ROMBaseHost + base + 0x20); - *wp++ = htons(0x7000); // moveq #0,d0 - *wp = htons(M68K_RTS); -#endif - -#if DISABLE_SCSI - // Don't access SCSI variables - // Remove this if SCSI Manager works!! - if (ROMType == ROMTYPE_NEWWORLD) { - static const uint8 scsi_var_dat[] = {0x70, 0x01, 0xa0, 0x89, 0x4a, 0x6e, 0xfe, 0xac, 0x4f, 0xef, 0x00, 0x10, 0x66, 0x00}; - if ((base = find_rom_data(0x1f500, 0x1f600, scsi_var_dat, sizeof(scsi_var_dat))) != 0) { - D(bug("scsi_var %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 12); - *wp = htons(0x6000); // bra - } - - static const uint8 scsi_var2_dat[] = {0x4e, 0x56, 0xfc, 0x58, 0x48, 0xe7, 0x1f, 0x38}; - if ((base = find_rom_data(0x1f700, 0x1f800, scsi_var2_dat, sizeof(scsi_var2_dat))) != 0) { - D(bug("scsi_var2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x7000); // moveq #0,d0 - *wp = htons(M68K_RTS); - } - } - else if (ROMType == ROMTYPE_GOSSAMER) { - static const uint8 scsi_var_dat[] = {0x70, 0x01, 0xa0, 0x89, 0x4a, 0x6e, 0xfe, 0xac, 0x4f, 0xef, 0x00, 0x10, 0x66, 0x00}; - if ((base = find_rom_data(0x1d700, 0x1d800, scsi_var_dat, sizeof(scsi_var_dat))) != 0) { - D(bug("scsi_var %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 12); - *wp = htons(0x6000); // bra - } - - static const uint8 scsi_var2_dat[] = {0x4e, 0x56, 0xfc, 0x5a, 0x48, 0xe7, 0x1f, 0x38}; - if ((base = find_rom_data(0x1d900, 0x1da00, scsi_var2_dat, sizeof(scsi_var2_dat))) != 0) { - D(bug("scsi_var2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x7000); // moveq #0,d0 - *wp = htons(M68K_RTS); - } - } -#endif - - // Don't wait in ADBInit (via 0x36c) - static const uint8 adb_init_dat[] = {0x08, 0x2b, 0x00, 0x05, 0x01, 0x5d, 0x66, 0xf8}; - if ((base = find_rom_data(0x31000, 0x3d000, adb_init_dat, sizeof(adb_init_dat))) == 0) return false; - D(bug("adb_init %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 6); - *wp = htons(M68K_NOP); - - // Modify check in InitResources() so that addresses >0x80000000 work - static const uint8 init_res_dat[] = {0x4a, 0xb8, 0x0a, 0x50, 0x6e, 0x20}; - if ((base = find_rom_data(0x78000, 0x8c000, init_res_dat, sizeof(init_res_dat))) == 0) return false; - D(bug("init_res %08lx\n", base)); - bp = (uint8 *)(ROMBaseHost + base + 4); - *bp = 0x66; - - // Modify vCheckLoad() so that we can patch resources (68k Resource Manager) - static const uint8 check_load_dat[] = {0x20, 0x78, 0x07, 0xf0, 0x4e, 0xd0}; - if ((base = find_rom_data(0x78000, 0x8c000, check_load_dat, sizeof(check_load_dat))) == 0) return false; - D(bug("check_load %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(M68K_JMP); - *wp++ = htons((ROMBase + CHECK_LOAD_PATCH_SPACE) >> 16); - *wp = htons((ROMBase + CHECK_LOAD_PATCH_SPACE) & 0xffff); - wp = (uint16 *)(ROMBaseHost + CHECK_LOAD_PATCH_SPACE); - *wp++ = htons(0x2f03); // move.l d3,-(a7) - *wp++ = htons(0x2078); // move.l $07f0,a0 - *wp++ = htons(0x07f0); - *wp++ = htons(M68K_JSR_A0); - *wp++ = htons(M68K_EMUL_OP_CHECKLOAD); - *wp = htons(M68K_RTS); - - // Replace .Sony driver - sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4); - if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD) - sony_offset = find_rom_resource(FOURCC('D','R','V','R'), 4, true); // First DRVR 4 is .MFMFloppy - if (sony_offset == 0) { - sony_offset = find_rom_resource(FOURCC('n','d','r','v'), -20196); // NewWorld 1.6 has "PCFloppy" ndrv - if (sony_offset == 0) - return false; - lp = (uint32 *)(ROMBaseHost + rsrc_ptr + 8); - *lp = htonl(FOURCC('D','R','V','R')); - wp = (uint16 *)(ROMBaseHost + rsrc_ptr + 12); - *wp = htons(4); - } - D(bug("sony_offset %08lx\n", sony_offset)); - memcpy((void *)(ROMBaseHost + sony_offset), sony_driver, sizeof(sony_driver)); - - // Install .Disk and .AppleCD drivers - memcpy((void *)(ROMBaseHost + sony_offset + 0x100), disk_driver, sizeof(disk_driver)); - memcpy((void *)(ROMBaseHost + sony_offset + 0x200), cdrom_driver, sizeof(cdrom_driver)); - - // Install serial drivers - gen_ain_driver( ROMBase + sony_offset + 0x300); - gen_aout_driver(ROMBase + sony_offset + 0x400); - gen_bin_driver( ROMBase + sony_offset + 0x500); - gen_bout_driver(ROMBase + sony_offset + 0x600); - - // Copy icons to ROM - SonyDiskIconAddr = ROMBase + sony_offset + 0x800; - memcpy(ROMBaseHost + sony_offset + 0x800, SonyDiskIcon, sizeof(SonyDiskIcon)); - SonyDriveIconAddr = ROMBase + sony_offset + 0xa00; - memcpy(ROMBaseHost + sony_offset + 0xa00, SonyDriveIcon, sizeof(SonyDriveIcon)); - DiskIconAddr = ROMBase + sony_offset + 0xc00; - memcpy(ROMBaseHost + sony_offset + 0xc00, DiskIcon, sizeof(DiskIcon)); - CDROMIconAddr = ROMBase + sony_offset + 0xe00; - memcpy(ROMBaseHost + sony_offset + 0xe00, CDROMIcon, sizeof(CDROMIcon)); - - // Patch driver install routine - static const uint8 drvr_install_dat[] = {0xa7, 0x1e, 0x21, 0xc8, 0x01, 0x1c, 0x4e, 0x75}; - if ((base = find_rom_data(0xb00, 0xd00, drvr_install_dat, sizeof(drvr_install_dat))) == 0) return false; - D(bug("drvr_install %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base + 8); - *wp++ = htons(M68K_EMUL_OP_INSTALL_DRIVERS); - *wp = htons(M68K_RTS); - - // Don't install serial drivers from ROM - if (ROMType == ROMTYPE_ZANZIBAR || ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) { - wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('S','E','R','D'), 0)); - *wp = htons(M68K_RTS); - } else { - wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0xc4); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp = htons(0x7000); // moveq #0,d0 - wp = (uint16 *)(ROMBaseHost + find_rom_resource(FOURCC('s','l','0','5'), 2) + 0x8ee); - *wp = htons(M68K_NOP); - } - uint32 nsrd_offset = find_rom_resource(FOURCC('n','s','r','d'), 1); - if (nsrd_offset) { - lp = (uint32 *)(ROMBaseHost + rsrc_ptr + 8); - *lp = htonl(FOURCC('x','s','r','d')); - } - - // Replace ADBOp() - memcpy(ROMBaseHost + find_rom_trap(0xa07c), adbop_patch, sizeof(adbop_patch)); - - // Replace Time Manager - wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa058)); - *wp++ = htons(M68K_EMUL_OP_INSTIME); - *wp = htons(M68K_RTS); - wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa059)); - *wp++ = htons(0x40e7); // move sr,-(sp) - *wp++ = htons(0x007c); // ori #$0700,sr - *wp++ = htons(0x0700); - *wp++ = htons(M68K_EMUL_OP_RMVTIME); - *wp++ = htons(0x46df); // move (sp)+,sr - *wp = htons(M68K_RTS); - wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa05a)); - *wp++ = htons(0x40e7); // move sr,-(sp) - *wp++ = htons(0x007c); // ori #$0700,sr - *wp++ = htons(0x0700); - *wp++ = htons(M68K_EMUL_OP_PRIMETIME); - *wp++ = htons(0x46df); // move (sp)+,sr - *wp = htons(M68K_RTS); - wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa093)); - *wp++ = htons(M68K_EMUL_OP_MICROSECONDS); - *wp = htons(M68K_RTS); - - // Disable Egret Manager - static const uint8 egret_dat[] = {0x2f, 0x30, 0x81, 0xe2, 0x20, 0x10, 0x00, 0x18}; - if ((base = find_rom_data(0xa000, 0x10000, egret_dat, sizeof(egret_dat))) == 0) return false; - D(bug("egret %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - *wp++ = htons(0x7000); - *wp = htons(M68K_RTS); - - // Don't call FE0A opcode in Shutdown Manager - static const uint8 shutdown_dat[] = {0x40, 0xe7, 0x00, 0x7c, 0x07, 0x00, 0x48, 0xe7, 0x3f, 0x00, 0x2c, 0x00, 0x2e, 0x01}; - if ((base = find_rom_data(0x30000, 0x40000, shutdown_dat, sizeof(shutdown_dat))) == 0) return false; - D(bug("shutdown %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); - if (ROMType == ROMTYPE_ZANZIBAR) - *wp = htons(M68K_RTS); - else if (ntohs(wp[-4]) == 0x61ff) - *wp = htons(M68K_RTS); - else if (ntohs(wp[-2]) == 0x6700) - wp[-2] = htons(0x6000); // bra - - // Patch PowerOff() - wp = (uint16 *)(ROMBaseHost + find_rom_trap(0xa05b)); // PowerOff() - *wp = htons(M68K_EMUL_RETURN); - - // Patch VIA interrupt handler - static const uint8 via_int_dat[] = {0x70, 0x7f, 0xc0, 0x29, 0x1a, 0x00, 0xc0, 0x29, 0x1c, 0x00}; - if ((base = find_rom_data(0x13000, 0x1c000, via_int_dat, sizeof(via_int_dat))) == 0) return false; - D(bug("via_int %08lx\n", base)); - uint32 level1_int = ROMBase + base; - wp = (uint16 *)(ROMBaseHost + base); // Level 1 handler - *wp++ = htons(0x7002); // moveq #2,d0 (60Hz interrupt) - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp++ = htons(M68K_NOP); - *wp = htons(M68K_NOP); - - static const uint8 via_int2_dat[] = {0x13, 0x7c, 0x00, 0x02, 0x1a, 0x00, 0x4e, 0x71, 0x52, 0xb8, 0x01, 0x6a}; - if ((base = find_rom_data(0x10000, 0x18000, via_int2_dat, sizeof(via_int2_dat))) == 0) return false; - D(bug("via_int2 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); // 60Hz handler - *wp++ = htons(M68K_EMUL_OP_IRQ); - *wp++ = htons(0x4a80); // tst.l d0 - *wp++ = htons(0x6700); // beq xxx - *wp = htons(0xffe8); - - if (ROMType == ROMTYPE_NEWWORLD) { - static const uint8 via_int3_dat[] = {0x48, 0xe7, 0xf0, 0xf0, 0x76, 0x01, 0x60, 0x26}; - if ((base = find_rom_data(0x15000, 0x19000, via_int3_dat, sizeof(via_int3_dat))) == 0) return false; - D(bug("via_int3 %08lx\n", base)); - wp = (uint16 *)(ROMBaseHost + base); // CHRP level 1 handler - *wp++ = htons(M68K_JMP); - *wp++ = htons((level1_int - 12) >> 16); - *wp = htons((level1_int - 12) & 0xffff); - } - - // Patch ZeroScrap() for clipboard exchange with host OS - uint32 zero_scrap = find_rom_trap(0xa9fc); // ZeroScrap() - wp = (uint16 *)(ROMBaseHost + ZERO_SCRAP_PATCH_SPACE); - *wp++ = htons(M68K_EMUL_OP_ZERO_SCRAP); - *wp++ = htons(M68K_JMP); - *wp++ = htons((ROMBase + zero_scrap) >> 16); - *wp++ = htons((ROMBase + zero_scrap) & 0xffff); - base = ROMBase + ReadMacInt32(ROMBase + 0x22); - WriteMacInt32(base + 4 * (0xa9fc & 0x3ff), ZERO_SCRAP_PATCH_SPACE); - - // Patch PutScrap() for clipboard exchange with host OS - uint32 put_scrap = find_rom_trap(0xa9fe); // PutScrap() - wp = (uint16 *)(ROMBaseHost + PUT_SCRAP_PATCH_SPACE); - *wp++ = htons(M68K_EMUL_OP_PUT_SCRAP); - *wp++ = htons(M68K_JMP); - *wp++ = htons((ROMBase + put_scrap) >> 16); - *wp++ = htons((ROMBase + put_scrap) & 0xffff); - base = ROMBase + ReadMacInt32(ROMBase + 0x22); - WriteMacInt32(base + 4 * (0xa9fe & 0x3ff), PUT_SCRAP_PATCH_SPACE); - - // Patch GetScrap() for clipboard exchange with host OS - uint32 get_scrap = find_rom_trap(0xa9fd); // GetScrap() - wp = (uint16 *)(ROMBaseHost + GET_SCRAP_PATCH_SPACE); - *wp++ = htons(M68K_EMUL_OP_GET_SCRAP); - *wp++ = htons(M68K_JMP); - *wp++ = htons((ROMBase + get_scrap) >> 16); - *wp++ = htons((ROMBase + get_scrap) & 0xffff); - base = ROMBase + ReadMacInt32(ROMBase + 0x22); - WriteMacInt32(base + 4 * (0xa9fd & 0x3ff), GET_SCRAP_PATCH_SPACE); - - // Patch SynchIdleTime() - if (PrefsFindBool("idlewait")) { - base = find_rom_trap(0xabf7) + 4; // SynchIdleTime() - wp = (uint16 *)(ROMBaseHost + base); - D(bug("SynchIdleTime at %08lx\n", base)); - if (ntohs(*wp) == 0x2078) { // movea.l ExpandMem,a0 - *wp++ = htons(M68K_EMUL_OP_IDLE_TIME); - *wp = htons(M68K_NOP); - } - else if (ntohs(*wp) == 0x70fe) // moveq #-2,d0 - *wp++ = htons(M68K_EMUL_OP_IDLE_TIME_2); - else { - D(bug("SynchIdleTime patch not installed\n")); - } - } - - // Construct list of all sifters used by sound components in ROM - D(bug("Searching for sound components with type sdev in ROM\n")); - uint32 thing = find_rom_resource(FOURCC('t','h','n','g')); - while (thing) { - thing += ROMBase; - D(bug(" found %c%c%c%c %c%c%c%c\n", ReadMacInt8(thing), ReadMacInt8(thing + 1), ReadMacInt8(thing + 2), ReadMacInt8(thing + 3), ReadMacInt8(thing + 4), ReadMacInt8(thing + 5), ReadMacInt8(thing + 6), ReadMacInt8(thing + 7))); - if (ReadMacInt32(thing) == FOURCC('s','d','e','v') && ReadMacInt32(thing + 4) == FOURCC('s','i','n','g')) { - WriteMacInt32(thing + 4, FOURCC('a','w','g','c')); - D(bug(" found sdev component at offset %08x in ROM\n", thing)); - AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID)); - if (ReadMacInt32(thing + componentPFCount)) - AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID)); - } - thing = find_rom_resource(FOURCC('t','h','n','g'), 4711, true); - } - - // Patch component code - D(bug("Patching sifters in ROM\n")); - for (int i=0; i pb_var; - const uintptr pb = pb_var.addr(); - -#if DISABLE_SCSI - // Setup fake SCSI Globals - r.d[0] = 0x1000; - Execute68kTrap(0xa71e, &r); // NewPtrSysClear() - uint32 scsi_globals = r.a[0]; - D(bug("Fake SCSI globals at %08lx\n", scsi_globals)); - WriteMacInt32(0xc0c, scsi_globals); // Set SCSIGlobals -#endif - - // Install floppy driver - if (ROMType == ROMTYPE_NEWWORLD || ROMType == ROMTYPE_GOSSAMER) { - - // Force installation of floppy driver with NewWorld and Gossamer ROMs - r.a[0] = ROMBase + sony_offset; - r.d[0] = (uint32)SonyRefNum; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~SonyRefNum * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - uint32 dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset); - WriteMacInt16(dce + dCtlFlags, SonyDriverFlags); - } - - // Open .Sony driver - SheepString sony_str("\005.Sony"); - WriteMacInt8(pb + ioPermssn, 0); - WriteMacInt32(pb + ioNamePtr, sony_str.addr()); - r.a[0] = pb; - Execute68kTrap(0xa000, &r); // Open() - - // Install disk driver - r.a[0] = ROMBase + sony_offset + 0x100; - r.d[0] = (uint32)DiskRefNum; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~DiskRefNum * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - uint32 dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x100); - WriteMacInt16(dce + dCtlFlags, DiskDriverFlags); - - // Open disk driver - SheepString disk_str("\005.Disk"); - WriteMacInt32(pb + ioNamePtr, disk_str.addr()); - r.a[0] = pb; - Execute68kTrap(0xa000, &r); // Open() - - // Install CD-ROM driver unless nocdrom option given - if (!PrefsFindBool("nocdrom")) { - - // Install CD-ROM driver - r.a[0] = ROMBase + sony_offset + 0x200; - r.d[0] = (uint32)CDROMRefNum; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~CDROMRefNum * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x200); - WriteMacInt16(dce + dCtlFlags, CDROMDriverFlags); - - // Open CD-ROM driver - SheepString apple_cd("\010.AppleCD"); - WriteMacInt32(pb + ioNamePtr, apple_cd.addr()); - r.a[0] = pb; - Execute68kTrap(0xa000, &r); // Open() - } - - // Install serial drivers - r.a[0] = ROMBase + sony_offset + 0x300; - r.d[0] = (uint32)-6; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-6) * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x300); - WriteMacInt16(dce + dCtlFlags, 0x4d00); - - r.a[0] = ROMBase + sony_offset + 0x400; - r.d[0] = (uint32)-7; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-7) * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x400); - WriteMacInt16(dce + dCtlFlags, 0x4e00); - - r.a[0] = ROMBase + sony_offset + 0x500; - r.d[0] = (uint32)-8; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-8) * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x500); - WriteMacInt16(dce + dCtlFlags, 0x4d00); - - r.a[0] = ROMBase + sony_offset + 0x600; - r.d[0] = (uint32)-9; - Execute68kTrap(0xa43d, &r); // DrvrInstallRsrvMem() - r.a[0] = ReadMacInt32(ReadMacInt32(0x11c) + ~(-9) * 4); // Get driver handle from Unit Table - Execute68kTrap(0xa029, &r); // HLock() - dce = ReadMacInt32(r.a[0]); - WriteMacInt32(dce + dCtlDriver, ROMBase + sony_offset + 0x600); - WriteMacInt16(dce + dCtlFlags, 0x4e00); -} diff --git a/SheepShaver/src/rsrc_patches.cpp b/SheepShaver/src/rsrc_patches.cpp deleted file mode 100644 index 8bf0ac4f..00000000 --- a/SheepShaver/src/rsrc_patches.cpp +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * rsrc_patches.cpp - Resource patches - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include "sysdeps.h" -#include "rsrc_patches.h" -#include "cpu_emulation.h" -#include "emul_op.h" -#include "xlowmem.h" -#include "macos_util.h" -#include "rom_patches.h" -#include "main.h" -#include "audio.h" -#include "audio_defs.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - - -// Sound input driver -static const uint8 sound_input_driver[] = { // .AppleSoundInput driver header - // Driver header - 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x24, // Open() offset - 0x00, 0x28, // Prime() offset - 0x00, 0x2c, // Control() offset - 0x00, 0x38, // Status() offset - 0x00, 0x5e, // Close() offset - 0x10, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x00, // ".AppleSoundInput" - - // Open() - M68K_EMUL_OP_SOUNDIN_OPEN >> 8, M68K_EMUL_OP_SOUNDIN_OPEN & 0xff, - 0x4e, 0x75, // rts - - // Prime() - M68K_EMUL_OP_SOUNDIN_PRIME >> 8, M68K_EMUL_OP_SOUNDIN_PRIME & 0xff, - 0x60, 0x0e, // bra IOReturn - - // Control() - M68K_EMUL_OP_SOUNDIN_CONTROL >> 8, M68K_EMUL_OP_SOUNDIN_CONTROL & 0xff, - 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, // cmp.w #1,$1a(a0) - 0x66, 0x04, // bne IOReturn - 0x4e, 0x75, // rts - - // Status() - M68K_EMUL_OP_SOUNDIN_STATUS >> 8, M68K_EMUL_OP_SOUNDIN_STATUS & 0xff, - - // IOReturn - 0x32, 0x28, 0x00, 0x06, // move.w 6(a0),d1 - 0x08, 0x01, 0x00, 0x09, // btst #9,d1 - 0x67, 0x0c, // beq 1 - 0x4a, 0x40, // tst.w d0 - 0x6f, 0x02, // ble 2 - 0x42, 0x40, // clr.w d0 - 0x31, 0x40, 0x00, 0x10, //2 move.w d0,$10(a0) - 0x4e, 0x75, // rts - 0x4a, 0x40, //1 tst.w d0 - 0x6f, 0x04, // ble 3 - 0x42, 0x40, // clr.w d0 - 0x4e, 0x75, // rts - 0x2f, 0x38, 0x08, 0xfc, //3 move.l $8fc,-(sp) - 0x4e, 0x75, // rts - - // Close() - M68K_EMUL_OP_SOUNDIN_CLOSE >> 8, M68K_EMUL_OP_SOUNDIN_CLOSE & 0xff, - 0x4e, 0x75, // rts -}; - - -/* - * Search resource for byte string, return offset (or 0) - */ - -static uint32 find_rsrc_data(const uint8 *rsrc, uint32 max, const uint8 *search, uint32 search_len, uint32 ofs = 0) -{ - while (ofs < max - search_len) { - if (!memcmp(rsrc + ofs, search, search_len)) - return ofs; - ofs++; - } - return 0; -} - - -/* - * Resource patches via vCheckLoad - */ - -// 680x0 code pattern matching helper -#define PM(N, V) (p[N] == htons(V)) - -void CheckLoad(uint32 type, int16 id, uint16 *p, uint32 size) -{ - uint16 *p16; - uint32 base; - D(bug("vCheckLoad %c%c%c%c (%08x) ID %d, data %p, size %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, id, p, size)); - - // Don't modify resources in ROM - if ((uintptr)p >= (uintptr)ROMBaseHost && (uintptr)p <= (uintptr)(ROMBaseHost + ROM_SIZE)) - return; - - if (type == FOURCC('b','o','o','t') && id == 3) { - D(bug("boot 3 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x51c9) && PM(2,0x2e49)) { - // Set boot stack pointer (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6, 9.0) - p[2] = htons(M68K_EMUL_OP_FIX_BOOTSTACK); - D(bug(" patch 1 applied\n")); - } else if (PM(0,0x4267) && PM(1,0x3f01) && PM(2,0x3f2a) && PM(3,0x0006) && PM(4,0x6100)) { - // Check when ntrb 17 is installed (for native Resource Manager patch) (7.5.3, 7.5.5) - p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH3); - D(bug(" patch 2 applied\n")); - } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x6100)) { - // Check when ntrb 17 is installed (for native Resource Manager patch) (7.6, 7.6.1, 8.0, 8.1) - p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH); - D(bug(" patch 3 applied\n")); - } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x61ff) && PM(8,0x245f)) { - // Check when ntrb 17 is installed (for native Resource Manager patch) (8.5, 8.6) - p[8] = htons(M68K_EMUL_OP_NTRB_17_PATCH); - D(bug(" patch 4 applied\n")); - } else if (PM(0,0x3f2a) && PM(1,0x0006) && PM(2,0x3f2a) && PM(3,0x0002) && PM(4,0x61ff) && PM(7,0x301f)) { - // Check when ntrb 17 is installed (for native Resource Manager patch) (9.0) - p[7] = htons(M68K_EMUL_OP_NTRB_17_PATCH4); - p[8] = htons(ntohs(p[8]) & 0xf0ff); // bra - D(bug(" patch 5 applied\n")); - } else if (PM(0,0x0c39) && PM(1,0x0001) && PM(2,0xf800) && PM(3,0x0008) && PM(4,0x6f00)) { - // Don't read from 0xf8000008 (8.5 with Zanzibar ROM, 8.6, 9.0) - p[0] = htons(M68K_NOP); - p[1] = htons(M68K_NOP); - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(0x6000); // bra - D(bug(" patch 6 applied\n")); - } else if (PM(0,0x2f3c) && PM(1,0x6b72) && PM(2,0x6e6c) && PM(3,0x4267) && PM(4,0xa9a0) && PM(5,0x265f) && PM(6,0x200b) && PM(7,0x6700)) { - // Don't replace nanokernel ("krnl" resource) (8.6, 9.0) - p[0] = htons(M68K_NOP); - p[1] = htons(M68K_NOP); - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(M68K_NOP); - p[7] = htons(0x6000); // bra - D(bug(" patch 7 applied\n")); - } else if (PM(0,0xa8fe) && PM(1,0x3038) && PM(2,0x017a) && PM(3,0x0c40) && PM(4,0x8805) && PM(5,0x6710)) { - // No SCSI (calls via 0x205c jump vector which is not initialized in NewWorld ROM 1.6) (8.6) - if (ROMType == ROMTYPE_NEWWORLD) { - p[5] = htons(0x6010); // bra - D(bug(" patch 8 applied\n")); - } - } else if (PM(0,0x2f3c) && PM(1,0x7665) && PM(2,0x7273) && PM(3,0x3f3c) && PM(4,0x0001) && PM(10,0x2041) && PM(11,0x2248) && PM(12,0x2050) && PM(20,0x7066) && PM(21,0xa9c9)) { - // Check when vers 1 is installed (for safe abort if MacOS < 8.1 is used with a NewWorld ROM) - p[10] = htons(M68K_EMUL_OP_CHECK_SYSV); - p[11] = htons(0x4a81); // tst.l d1 - p[12] = htons(0x670e); // beq.s - D(bug(" patch 9 applied\n")); - } - p++; - } - - } else if (type == FOURCC('g','n','l','d') && id == 0) { - D(bug("gnld 0 found\n")); - - // Patch native Resource Manager after ntrbs are installed (7.5.2) - static const uint8 dat[] = {0x4e, 0xba, 0x00, 0x9e, 0x3e, 0x00, 0x50, 0x4f, 0x67, 0x04}; - base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat)); - if (base) { - p16 = (uint16 *)((uintptr)p + base + 6); - *p16 = htons(M68K_EMUL_OP_NTRB_17_PATCH2); - D(bug(" patch 1 applied\n")); - } - - } else if (type == FOURCC('p','t','c','h') && id == 156) { - D(bug("ptch 156 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x4e56) && PM(1,0xfffa) && PM(2,0x48e7) && PM(3,0x1f18) && PM(4,0x7800) && PM(5,0x267c) && PM(6,0x6900) && PM(7,0x0000)) { - // Don't call FE0A opcode (9.0) - p[0] = htons(0x7000); // moveq #0,d0 - p[1] = htons(M68K_RTS); - D(bug(" patch 1 applied\n")); - break; - } - p++; - } - - } else if (type == FOURCC('p','t','c','h') && id == 420) { - D(bug("ptch 420 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x303c) && PM(3,0x0100) && PM(4,0xc06e) && PM(5,0xfef6)) { - // Disable VM (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1) - p[1] = htons(M68K_NOP); - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(M68K_NOP); - p[5] = htons(M68K_NOP); - p[6] = htons(M68K_NOP); - p[7] = htons(M68K_NOP); - p[8] = htons(M68K_NOP); - p[9] = htons(M68K_NOP); - p[10] = htons(M68K_NOP); - p[11] = htons(M68K_NOP); - D(bug(" patch 1 applied\n")); - break; - } else if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x7000) && PM(3,0x302e) && PM(4,0xfef6) && PM(5,0x323c) && PM(6,0x0100)) { - // Disable VM (8.0, 8.1) - p[8] = htons(M68K_NOP); - p[15] = htons(M68K_NOP); - D(bug(" patch 2 applied\n")); - break; - } else if (PM(0,0xa030) && PM(1,0x5240) && PM(2,0x7000) && PM(3,0x302e) && PM(4,0xfecc) && PM(5,0x323c) && PM(6,0x0100)) { - // Disable VM (8.5, 8.6, 9.0) - p[8] = htons(M68K_NOP); - p[15] = htons(M68K_NOP); - D(bug(" patch 3 applied\n")); - break; - } - p++; - } - - } else if (type == FOURCC('g','p','c','h') && id == 16) { - D(bug("gpch 16 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x6700) && PM(13,0x7013) && PM(14,0xfe0a)) { - // Don't call FE0A in Shutdown Manager (7.6.1, 8.0, 8.1, 8.5) - p[0] = htons(0x6000); - D(bug(" patch 1 applied\n")); - break; - } - p++; - } - - } else if (type == FOURCC('g','p','c','h') && id == 650) { - D(bug("gpch 650 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x6600) && PM(1,0x001a) && PM(2,0x2278) && PM(3,0x0134)) { - // We don't have SonyVars (7.5.2) - p[0] = htons(0x6000); - D(bug(" patch 1 applied\n")); - } else if (PM(0,0x6618) && PM(1,0x2278) && PM(2,0x0134)) { - // We don't have SonyVars (7.5.3) - p[-6] = htons(M68K_NOP); - p[-3] = htons(M68K_NOP); - p[0] = htons(0x6018); - D(bug(" patch 2 applied\n")); - } else if (PM(0,0x6660) && PM(1,0x2278) && PM(2,0x0134)) { - // We don't have SonyVars (7.5.3 Revision 2.2) - p[-6] = htons(M68K_NOP); - p[-3] = htons(M68K_NOP); - p[0] = htons(0x6060); - D(bug(" patch 3 applied\n")); - } else if (PM(0,0x666e) && PM(1,0x2278) && PM(2,0x0134)) { - // We don't have SonyVars (7.5.5) - p[-6] = htons(M68K_NOP); - p[-3] = htons(M68K_NOP); - p[0] = htons(0x606e); - D(bug(" patch 4 applied\n")); - } else if (PM(0,0x6400) && PM(1,0x011c) && PM(2,0x2278) && PM(3,0x0134)) { - // We don't have SonyVars (7.6.1, 8.0, 8.1, 8.5, 8.6, 9.0) - p[0] = htons(0x6000); - D(bug(" patch 5 applied\n")); - } else if (PM(0,0x6400) && PM(1,0x00e6) && PM(2,0x2278) && PM(3,0x0134)) { - // We don't have SonyVars (7.6) - p[0] = htons(0x6000); - D(bug(" patch 6 applied\n")); - } - p++; - } - - } else if (type == FOURCC('g','p','c','h') && id == 655) { - D(bug("gpch 655 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x83a8) && PM(1,0x0024) && PM(2,0x4e71)) { - // Don't write to GC interrupt mask (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(M68K_NOP); - p[1] = htons(M68K_NOP); - D(bug(" patch 1 applied\n")); - } else if (PM(0,0x207c) && PM(1,0xf300) && PM(2,0x0034)) { - // Don't read PowerMac ID (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(0x303c); // move.w #id,d0 - p[1] = htons(0x3020); - p[2] = htons(M68K_RTS); - D(bug(" patch 2 applied\n")); - } else if (PM(0,0x13fc) && PM(1,0x0081) && PM(2,0xf130) && PM(3,0xa030)) { - // Don't write to hardware (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(M68K_NOP); - p[1] = htons(M68K_NOP); - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - D(bug(" patch 3 applied\n")); - } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf800) && PM(4,0x0000)) { - // OpenFirmare? (7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(M68K_RTS); - D(bug(" patch 4 applied\n")); - } else if (PM(0,0x4e56) && PM(1,0xfffc) && PM(2,0x48e7) && PM(3,0x0300) && PM(4,0x598f) && PM(5,0x2eb8) && PM(6,0x01dc)) { - // Don't write to SCC (7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(M68K_RTS); - D(bug(" patch 5 applied\n")); - } else if (PM(0,0x4e56) && PM(1,0x0000) && PM(2,0x227c) && PM(3,0xf300) && PM(4,0x0034)) { - // Don't write to GC (7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(M68K_RTS); - D(bug(" patch 6 applied\n")); - } else if (PM(0,0x40e7) && PM(1,0x007c) && PM(2,0x0700) && PM(3,0x48e7) && PM(4,0x00c0) && PM(5,0x2078) && PM(6,0x0dd8) && PM(7,0xd1e8) && PM(8,0x0044) && PM(9,0x8005) && PM(11,0x93c8) && PM(12,0x2149) && PM(13,0x0024)) { - // Don't replace NVRAM routines (7.6, 7.6.1, 8.0, 8.1 with Zanzibar ROM) - p[0] = htons(M68K_RTS); - D(bug(" patch 7 applied\n")); - } else if (PM(0,0x207c) && PM(1,0x50f1) && PM(2,0xa101) && (PM(3,0x08d0) || PM(3,0x0890))) { - // Don't write to 0x50f1a101 (8.1 with Zanzibar ROM) - p[3] = htons(M68K_NOP); - p[4] = htons(M68K_NOP); - D(bug(" patch 8 applied\n")); - } - p++; - } - - } else if (type == FOURCC('g','p','c','h') && id == 750) { - D(bug("gpch 750 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) { - // Don't read from 0xf3019100 (MACE ENET) (7.6, 7.6.1, 8.0, 8.1) - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(0x6026); - D(bug(" patch 1 applied\n")); - } else if (PM(0,0x41e8) && PM(1,0x0374) && PM(2,0xfc1e)) { - // Don't call FC1E opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6) - p[2] = htons(M68K_NOP); - D(bug(" patch 2 applied\n")); - } else if (PM(0,0x700a) && PM(1,0xfe0a)) { - // Don't call FE0A opcode (7.6, 7.6.1, 8.0, 8.1, 8.5, 8.6, 9.0) - p[1] = htons(0x2008); // move.l a0,d0 - D(bug(" patch 3 applied\n")); - } else if (PM(0,0x6c00) && PM(1,0x016a) && PM(2,0x2278) && PM(3,0x0134)) { - // We don't have SonyVars (8.6) - p[-4] = htons(0x21fc); // move.l $40810000,($0000) - p[-3] = htons(0x4081); - p[-2] = htons(0x0000); - p[-1] = htons(0x0000); - p[0] = htons(0x6000); - D(bug(" patch 4 applied\n")); - } - p++; - } - - } else if (type == FOURCC('g','p','c','h') && id == 999) { - D(bug("gpch 999 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) { - // Don't read from 0xf3019100 (MACE ENET) (8.5, 8.6) - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(0x6026); - D(bug(" patch 1 applied\n")); - } - p++; - } - - } else if (type == FOURCC('g','p','c','h') && id == 3000) { - D(bug("gpch 3000 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0xf301) && PM(1,0x9100) && PM(2,0x0c11) && PM(3,0x0044)) { - // Don't read from 0xf3019100 (MACE ENET) (8.1 with NewWorld ROM) - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(0x6026); - D(bug(" patch 1 applied\n")); - } - p++; - } - - } else if (type == FOURCC('l','t','l','k') && id == 0) { - D(bug("ltlk 0 found\n")); -#if 1 - size >>= 1; - while (size--) { - if (PM(0,0xc2fc) && PM(1,0x0fa0) && PM(2,0x82c5)) { - // Prevent division by 0 in speed test (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1) - p[2] = htons(0x7200); - WriteMacInt32(0x1d8, 0x2c00); - WriteMacInt32(0x1dc, 0x2c00); - D(bug(" patch 1 applied\n")); - } else if (PM(0,0x1418) && PM(1,0x84c1)) { - // Prevent division by 0 (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1) - p[1] = htons(0x7400); - D(bug(" patch 2 applied\n")); - } else if (PM(0,0x2678) && PM(1,0x01dc) && PM(2,0x3018) && PM(3,0x6708) && PM(4,0x1680) && PM(5,0xe058) && PM(6,0x1680)) { - // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1) - p[4] = htons(M68K_NOP); - p[6] = htons(M68K_NOP); - D(bug(" patch 3 applied\n")); - } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0006) && PM(4,0x4e71) && PM(5,0x1292)) { - // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1) - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[5] = htons(M68K_NOP); - D(bug(" patch 4 applied\n")); - } else if (PM(0,0x2278) && PM(1,0x01dc) && PM(2,0x12bc) && PM(3,0x0003) && PM(4,0x4e71) && PM(5,0x1281)) { - // Don't write to SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1) - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[5] = htons(M68K_NOP); - D(bug(" patch 5 applied\n")); - } else if (PM(0,0x0811) && PM(1,0x0000) && PM(2,0x51c8) && PM(3,0xfffa)) { - // Don't test SCC (7.5.2, 7.5.3, 7.5.5, 7.6, 7.6.1, 8.0, 8.1) - p[0] = htons(M68K_NOP); - p[1] = htons(M68K_NOP); - D(bug(" patch 6 applied\n")); - } else if (PM(0,0x4a2a) && PM(1,0x063e) && PM(2,0x66fa)) { - // Don't wait for SCC (7.5.2, 7.5.3, 7.5.5) - p[2] = htons(M68K_NOP); - D(bug(" patch 7 applied\n")); - } else if (PM(0,0x4a2a) && PM(1,0x03a6) && PM(2,0x66fa)) { - // Don't wait for SCC (7.6, 7.6.1, 8.0, 8.1) - p[2] = htons(M68K_NOP); - D(bug(" patch 8 applied\n")); - } - p++; - } -#else - // Disable LocalTalk - p[0] = htons(M68K_JMP_A0); - p[1] = htons(0x7000); // moveq #0,d0 - p[2] = htons(M68K_RTS); - D(bug(" patch 1 applied\n")); -#endif - - } else if (type == FOURCC('n','s','r','d') && id == 1) { - D(bug("nsrd 1 found\n")); - if (p[(0x378 + 0x460) >> 1] == htons(0x7c08) && p[(0x37a + 0x460) >> 1] == htons(0x02a6)) { - // Don't overwrite our serial drivers (7.5.3 Revision 2.2) - p[(0x378 + 0x460) >> 1] = htons(0x4e80); // blr - p[(0x37a + 0x460) >> 1] = htons(0x0020); - D(bug(" patch 1 applied\n")); - } else if (p[(0x378 + 0x570) >> 1] == htons(0x7c08) && p[(0x37a + 0x570) >> 1] == htons(0x02a6)) { - // Don't overwrite our serial drivers (8.0, 8.1) - p[(0x378 + 0x570) >> 1] = htons(0x4e80); // blr - p[(0x37a + 0x570) >> 1] = htons(0x0020); - D(bug(" patch 2 applied\n")); - } else if (p[(0x378 + 0x6c0) >> 1] == htons(0x7c08) && p[(0x37a + 0x6c0) >> 1] == htons(0x02a6)) { - // Don't overwrite our serial drivers (8.5, 8.6) - p[(0x378 + 0x6c0) >> 1] = htons(0x4e80); // blr - p[(0x37a + 0x6c0) >> 1] = htons(0x0020); - D(bug(" patch 3 applied\n")); - } else if (p[(0x374 + 0x510) >> 1] == htons(0x7c08) && p[(0x376 + 0x510) >> 1] == htons(0x02a6)) { - // Don't overwrite our serial drivers (9.0) - p[(0x374 + 0x510) >> 1] = htons(0x4e80); // blr - p[(0x376 + 0x510) >> 1] = htons(0x0020); - D(bug(" patch 4 applied\n")); - } - - } else if (type == FOURCC('c','i','t','t') && id == 45) { - D(bug("citt 45 found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x203c) && PM(1,0x0100) && PM(2,0x0000) && PM(3,0xc0ae) && PM(4,0xfffc)) { - // Don't replace SCSI Manager (8.1, 8.5, 8.6, 9.0) - p[5] = htons((ntohs(p[5]) & 0xff) | 0x6000); // beq - D(bug(" patch 1 applied\n")); - break; - } - p++; - } - - } else if (type == FOURCC('t','h','n','g')) { - // Collect info about used audio sifters - uint32 thing = Host2MacAddr((uint8 *)p); - uint32 c_type = ReadMacInt32(thing); - uint32 sub_type = ReadMacInt32(thing + 4); - if (c_type == FOURCC('s','d','e','v') && sub_type == FOURCC('s','i','n','g')) { - WriteMacInt32(thing + 4, FOURCC('a','w','g','c')); - D(bug("thng %d, type %c%c%c%c (%08x), sub type %c%c%c%c (%08x), data %p\n", id, c_type >> 24, (c_type >> 16) & 0xff, (c_type >> 8) & 0xff, c_type & 0xff, c_type, sub_type >> 24, (sub_type >> 16) & 0xff, (sub_type >> 8) & 0xff, sub_type & 0xff, sub_type, p)); - AddSifter(ReadMacInt32(thing + componentResType), ReadMacInt16(thing + componentResID)); - if (ReadMacInt32(thing + componentPFCount)) - AddSifter(ReadMacInt32(thing + componentPFResType), ReadMacInt16(thing + componentPFResID)); - } - - } else if (type == FOURCC('s','i','f','t') || type == FOURCC('n','i','f','t')) { - // Patch audio sifters - if (FindSifter(type, id)) { - D(bug("sifter found\n")); - p[0] = htons(0x4e56); p[1] = htons(0x0000); // link a6,#0 - p[2] = htons(0x48e7); p[3] = htons(0x8018); // movem.l d0/a3-a4,-(a7) - p[4] = htons(0x266e); p[5] = htons(0x000c); // movea.l $c(a6),a3 - p[6] = htons(0x286e); p[7] = htons(0x0008); // movea.l $8(a6),a4 - p[8] = htons(M68K_EMUL_OP_AUDIO_DISPATCH); - p[9] = htons(0x2d40); p[10] = htons(0x0010); // move.l d0,$10(a6) - p[11] = htons(0x4cdf); p[12] = htons(0x1801); // movem.l (a7)+,d0/a3-a4 - p[13] = htons(0x4e5e); // unlk a6 - p[14] = htons(0x4e74); p[15] = htons(0x0008); // rtd #8 - D(bug(" patch applied\n")); - } - - } else if (type == FOURCC('D','R','V','R') && (id == -16501 || id == -16500)) { - D(bug("DRVR -16501/-16500 found\n")); - // Install sound input driver - memcpy(p, sound_input_driver, sizeof(sound_input_driver)); - D(bug(" patch 1 applied\n")); - - } else if (type == FOURCC('I','N','I','T') && id == 1 && size == (2416 >> 1)) { - D(bug("INIT 1 (size 2416) found\n")); - size >>= 1; - while (size--) { - if (PM(0,0x247c) && PM(1,0xf301) && PM(2,0x9000)) { - // Prevent "MacOS Licensing Extension" from accessing hardware (7.6) - p[22] = htons(0x6028); - D(bug(" patch 1 applied\n")); - break; - } - p++; - } - - } else if (type == FOURCC('s','c','o','d') && id == -16465) { - D(bug("scod -16465 found\n")); - - // Don't crash in Process Manager on reset/shutdown (8.6, 9.0) - static const uint8 dat[] = {0x4e, 0x56, 0x00, 0x00, 0x48, 0xe7, 0x03, 0x18, 0x2c, 0x2e, 0x00, 0x10}; - base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat)); - if (base) { - p16 = (uint16 *)((uintptr)p + base); - p16[0] = htons(0x7000); // moveq #0,d0 - p16[1] = htons(M68K_RTS); - D(bug(" patch 1 applied\n")); - } - - } else if (type == FOURCC('N','O','b','j') && id == 100) { - D(bug("NObj 100 found\n")); - - // Don't access VIA registers in MacBench 5.0 - static const uint8 dat1[] = {0x7c, 0x08, 0x02, 0xa6, 0xbf, 0x01, 0xff, 0xe0, 0x90, 0x01, 0x00, 0x08}; - base = find_rsrc_data((uint8 *)p, size, dat1, sizeof(dat1)); - if (base) { - p[(base + 0x00) >> 1] = htons(0x3860); // li r3,0 - p[(base + 0x02) >> 1] = htons(0x0000); - p[(base + 0x04) >> 1] = htons(0x4e80); // blr - p[(base + 0x06) >> 1] = htons(0x0020); - D(bug(" patch 1 applied\n")); - } - static const uint8 dat2[] = {0x7c, 0x6c, 0x1b, 0x78, 0x7c, 0x8b, 0x23, 0x78, 0x38, 0xc0, 0x3f, 0xfd}; - base = find_rsrc_data((uint8 *)p, size, dat2, sizeof(dat2)); - if (base) { - p[(base + 0x00) >> 1] = htons(0x3860); // li r3,0 - p[(base + 0x02) >> 1] = htons(0x0000); - p[(base + 0x04) >> 1] = htons(0x4e80); // blr - p[(base + 0x06) >> 1] = htons(0x0020); - D(bug(" patch 2 applied\n")); - } - - } else if (type == FOURCC('C','O','D','E') && id == 27 && size == 25024) { - D(bug("CODE 27 found [Apple Personal Diagnostics]\n")); - - // Don't access FCBs directly in Apple Personal Diagnostics (MacOS 9) - // FIXME: this should not be called in the first place, use UTResolveFCB? - static const uint8 dat[] = {0x2d, 0x78, 0x03, 0x4e, 0xff, 0xf8, 0x20, 0x6e, 0xff, 0xf8}; - base = find_rsrc_data((uint8 *)p, size, dat, sizeof(dat)); - if (base - && ReadMacInt16(0x3f6) == 4 /* FSFCBLen */ - && p[(base + 0x1a) >> 1] == htons(0x605e) - && p[(base + 0x80) >> 1] == htons(0x7000)) - { - p[(base + 0x1a) >> 1] = htons(0x6064); - D(bug(" patch1 applied\n")); - } - - } else if (type == FOURCC('i','n','f','n') && (id == 129 || id == 200)) { - D(bug("infn %d found\n", id)); - size >>= 1; - while (size--) { - if (PM(0,0x203c) && PM(1,0xf800) && PM(2,0x0000) && PM(4,0x2040) && PM(5,0x1028) && PM(6,0x0090)) { - // Don't read from 0xf8000090 during MacOS (8.5, 9.0) installation - p[0] = htons(M68K_NOP); - p[1] = htons(M68K_NOP); - p[2] = htons(M68K_NOP); - p[3] = htons(M68K_NOP); - p[4] = htons(M68K_NOP); - p[5] = htons(M68K_NOP); - p[6] = htons(0x7000); // moveq #0,d0 - D(bug(" patch 1 applied\n")); - break; - } - p++; - } - - } -} - - -/* - * Resource patches via GetNamedResource() and Get1NamedResource() - */ - -void CheckLoad(uint32 type, const char *name, uint8 *p, uint32 size) -{ - uint16 *p16; - uint32 base; - D(bug("vCheckLoad %c%c%c%c (%08x) name \"%*s\", data %p, size %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, name[0], &name[1], p, size)); - - // Don't modify resources in ROM - if ((uintptr)p >= (uintptr)ROMBaseHost && (uintptr)p <= (uintptr)(ROMBaseHost + ROM_SIZE)) - return; - - if (type == FOURCC('D','R','V','R') && strncmp(&name[1], ".AFPTranslator", name[0]) == 0) { - D(bug(" DRVR .AFPTranslator found\n")); - - // Don't access ROM85 as it it was a pointer to a ROM version number (8.0, 8.1) - static const uint8 dat[] = {0x3a, 0x2e, 0x00, 0x0a, 0x55, 0x4f, 0x3e, 0xb8, 0x02, 0x8e, 0x30, 0x1f, 0x48, 0xc0, 0x24, 0x40, 0x20, 0x40}; - base = find_rsrc_data(p, size, dat, sizeof(dat)); - if (base) { - p16 = (uint16 *)(p + base + 4); - *p16++ = htons(0x303c); // move.l #ROM85,%d0 - *p16++ = htons(0x028e); - *p16++ = htons(M68K_NOP); - *p16++ = htons(M68K_NOP); - D(bug(" patch 1 applied\n")); - } - } -} - - -/* - * Native Resource Manager patches - */ - -#ifdef __BEOS__ -static -#else -extern "C" -#endif -void check_load_invoc(uint32 type, int16 id, uint32 h) -{ - if (h == 0) - return; - uint32 p = ReadMacInt32(h); - if (p == 0) - return; - uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff; - - CheckLoad(type, id, (uint16 *)Mac2HostAddr(p), size); -} - -#ifdef __BEOS__ -static -#else -extern "C" -#endif -void named_check_load_invoc(uint32 type, uint32 name, uint32 h) -{ - if (h == 0) - return; - uint32 p = ReadMacInt32(h); - if (p == 0) - return; - uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff; - - CheckLoad(type, (char *)Mac2HostAddr(name), Mac2HostAddr(p), size); -} - -#ifdef __BEOS__ -static asm void **get_resource(register uint32 type, register int16 id) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_GET_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} - -static asm void **get_1_resource(register uint32 type, register int16 id) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_GET_1_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} - -static asm void **get_ind_resource(register uint32 type, register int16 index) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/index - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_GET_IND_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} - -static asm void **get_1_ind_resource(register uint32 type, register int16 index) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/index - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_GET_1_IND_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} - -static asm void **r_get_resource(register uint32 type, register int16 id) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_R_GET_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} - -static asm void **get_named_resource(register uint32 type, register uint32 name) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_GET_NAMED_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl named_check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} - -static asm void **get_1_named_resource(register uint32 type, register uint32 name) -{ - // Create stack frame - mflr r0 - stw r0,8(r1) - stwu r1,-(56+12)(r1) - - // Save type/ID - stw r3,56(r1) - stw r4,56+4(r1) - - // Call old routine - lwz r0,XLM_GET_1_NAMED_RESOURCE - lwz r2,XLM_RES_LIB_TOC - mtctr r0 - bctrl - lwz r2,XLM_TOC // Get TOC - stw r3,56+8(r1) // Save handle - - // Call CheckLoad - lwz r3,56(r1) - lwz r4,56+4(r1) - lwz r5,56+8(r1) - bl named_check_load_invoc - lwz r3,56+8(r1) // Restore handle - - // Return to caller - lwz r0,56+12+8(r1) - mtlr r0 - addi r1,r1,56+12 - blr -} -#else -// Routines in asm_linux.S -extern "C" void get_resource(void); -extern "C" void get_1_resource(void); -extern "C" void get_ind_resource(void); -extern "C" void get_1_ind_resource(void); -extern "C" void r_get_resource(void); -extern "C" void get_named_resource(void); -extern "C" void get_1_named_resource(void); -#endif - -void PatchNativeResourceManager(void) -{ - D(bug("PatchNativeResourceManager\n")); - - // Patch native GetResource() - uint32 upp = ReadMacInt32(0x1480); - if ((upp & 0xffc00000) == ROMBase) - return; - uint32 tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" GetResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_RES_LIB_TOC, ReadMacInt32(tvec + 4)); - WriteMacInt32(XLM_GET_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_GET_RESOURCE)); -#else -#ifdef __BEOS__ - uint32 *tvec2 = (uint32 *)get_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)get_resource); -#endif -#endif - - // Patch native Get1Resource() - upp = ReadMacInt32(0x0e7c); - tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" Get1Resource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_GET_1_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_RESOURCE)); -#else -#ifdef __BEOS__ - tvec2 = (uint32 *)get_1_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)get_1_resource); -#endif -#endif - - // Patch native GetIndResource() - upp = ReadMacInt32(0x1474); - tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" GetIndResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_GET_IND_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_GET_IND_RESOURCE)); -#else -#ifdef __BEOS__ - tvec2 = (uint32 *)get_ind_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)get_ind_resource); -#endif -#endif - - // Patch native Get1IndResource() - upp = ReadMacInt32(0x0e38); - tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" Get1IndResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_GET_1_IND_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_IND_RESOURCE)); -#else -#ifdef __BEOS__ - tvec2 = (uint32 *)get_1_ind_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)get_1_ind_resource); -#endif -#endif - - // Patch native RGetResource() - upp = ReadMacInt32(0x0e30); - tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" RGetResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_R_GET_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_R_GET_RESOURCE)); -#else -#ifdef __BEOS__ - tvec2 = (uint32 *)r_get_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)r_get_resource); -#endif -#endif - - // Patch native GetNamedResource() - upp = ReadMacInt32(0x1484); - tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" GetNamedResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_GET_NAMED_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_GET_NAMED_RESOURCE)); -#else -#ifdef __BEOS__ - tvec2 = (uint32 *)get_named_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)get_named_resource); -#endif -#endif - - // Patch native Get1NamedResource() - upp = ReadMacInt32(0x0e80); - tvec = ReadMacInt32(upp + 5 * 4); - D(bug(" Get1NamedResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); - WriteMacInt32(XLM_GET_1_NAMED_RESOURCE, ReadMacInt32(tvec)); -#if EMULATED_PPC - WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_NAMED_RESOURCE)); -#else -#ifdef __BEOS__ - tvec2 = (uint32 *)get_1_named_resource; - WriteMacInt32(tvec, tvec2[0]); - WriteMacInt32(tvec + 4, tvec2[1]); -#else - WriteMacInt32(tvec, (uint32)get_1_named_resource); -#endif -#endif -} diff --git a/SheepShaver/src/scsi.cpp b/SheepShaver/src/scsi.cpp deleted file mode 120000 index 1e1a7e34..00000000 --- a/SheepShaver/src/scsi.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/scsi.cpp \ No newline at end of file diff --git a/SheepShaver/src/serial.cpp b/SheepShaver/src/serial.cpp deleted file mode 100644 index 723fc8dc..00000000 --- a/SheepShaver/src/serial.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* - * serial.cpp - Serial device driver - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "main.h" -#include "macos_util.h" -#include "serial.h" -#include "serial_defs.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -SERDPort *the_serd_port[2]; - -// Function pointers from imported functions -typedef int16 (*iocic_ptr)(uint32, int16); -static uint32 iocic_tvect = 0; -static inline int16 IOCommandIsComplete(uint32 arg1, int16 arg2) -{ - return (int16)CallMacOS2(iocic_ptr, iocic_tvect, arg1, arg2); -} - - -/* - * Empty function (AIn/BIn Open/Close) - */ - -int16 SerialNothing(uint32 pb, uint32 dce) -{ - return noErr; -} - - -/* - * Driver Open() routine (output side only) - */ - -int16 SerialOpen(uint32 pb, uint32 dce) -{ - D(bug("SerialOpen pb %08lx, dce %08lx\n", pb, dce)); - - // Get IOCommandIsComplete function - iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete"); - D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect)); - if (iocic_tvect == 0) { - printf("FATAL: SerialOpen(): Can't find IOCommandIsComplete()\n"); - return openErr; - } - - // Do nothing if port is already open - SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1]; - if (the_port->is_open) - return noErr; - - // Init variables - the_port->read_pending = the_port->write_pending = false; - the_port->read_done = the_port->write_done = false; - the_port->cum_errors = 0; - - // Open port - int16 res = the_port->open(ReadMacInt16(0x1fc + ((-(int16)ReadMacInt16(dce + dCtlRefNum)-6) & 2))); - if (res) - return res; - - // Allocate Deferred Task structures - if ((the_port->dt_store = Mac_sysalloc(SIZEOF_serdt * 2)) == 0) - return openErr; - uint32 input_dt = the_port->input_dt = the_port->dt_store; - uint32 output_dt = the_port->output_dt = the_port->dt_store + SIZEOF_serdt; - D(bug(" input_dt %08lx, output_dt %08lx\n", input_dt, output_dt)); - - WriteMacInt16(input_dt + qType, dtQType); - WriteMacInt32(input_dt + dtAddr, input_dt + serdtCode); - WriteMacInt32(input_dt + dtParam, input_dt + serdtResult); - // Deferred function for signalling that Prime is complete (pointer to mydtResult in a1) - WriteMacInt16(input_dt + serdtCode, 0x2019); // move.l (a1)+,d0 (result) - WriteMacInt16(input_dt + serdtCode + 2, 0x2251); // move.l (a1),a1 (dce) - WriteMacInt32(input_dt + serdtCode + 4, 0x207808fc); // move.l JIODone,a0 - WriteMacInt16(input_dt + serdtCode + 8, 0x4ed0); // jmp (a0) - - WriteMacInt16(output_dt + qType, dtQType); - WriteMacInt32(output_dt + dtAddr, output_dt + serdtCode); - WriteMacInt32(output_dt + dtParam, output_dt + serdtResult); - // Deferred function for signalling that Prime is complete (pointer to mydtResult in a1) - WriteMacInt16(output_dt + serdtCode, 0x2019); // move.l (a1)+,d0 (result) - WriteMacInt16(output_dt + serdtCode + 2, 0x2251); // move.l (a1),a1 (dce) - WriteMacInt32(output_dt + serdtCode + 4, 0x207808fc); // move.l JIODone,a0 - WriteMacInt16(output_dt + serdtCode + 8, 0x4ed0); // jmp (a0) - - the_port->is_open = true; - return noErr; -} - - -/* - * Driver Prime() routines - */ - -int16 SerialPrimeIn(uint32 pb, uint32 dce) -{ - D(bug("SerialPrimeIn pb %08lx, dce %08lx\n", pb, dce)); - int16 res; - - SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1]; - if (!the_port->is_open) - res = notOpenErr; - else { - if (the_port->read_pending) { - printf("FATAL: SerialPrimeIn() called while request is pending\n"); - res = readErr; - } else - res = the_port->prime_in(pb, dce); - } - - if (ReadMacInt16(pb + ioTrap) & 0x0200) - if (res > 0) { - WriteMacInt16(pb + ioResult, 0); - return 0; // Command in progress - } else { - WriteMacInt16(pb + ioResult, res); - return res; - } - else - if (res > 0) - return 0; // Command in progress - else { - IOCommandIsComplete(pb, res); - return res; - } -} - -int16 SerialPrimeOut(uint32 pb, uint32 dce) -{ - D(bug("SerialPrimeOut pb %08lx, dce %08lx\n", pb, dce)); - int16 res; - - SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1]; - if (!the_port->is_open) - res = notOpenErr; - else { - if (the_port->write_pending) { - printf("FATAL: SerialPrimeOut() called while request is pending\n"); - res = writErr; - } else - res = the_port->prime_out(pb, dce); - } - - if (ReadMacInt16(pb + ioTrap) & 0x0200) - if (res > 0) { - WriteMacInt16(pb + ioResult, 0); - return 0; // Command in progress - } else { - WriteMacInt16(pb + ioResult, res); - return res; - } - else - if (res > 0) - return 0; // Command in progress - else { - IOCommandIsComplete(pb, res); - return res; - } -} - - -/* - * Driver Control() routine - */ - -int16 SerialControl(uint32 pb, uint32 dce) -{ - uint16 code = ReadMacInt16(pb + csCode); - D(bug("SerialControl %d, pb %08lx, dce %08lx\n", code, pb, dce)); - int16 res; - - SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1]; - if (!the_port->is_open) - res = notOpenErr; - else { - switch (code) { - case kSERDSetPollWrite: - res = noErr; - break; - default: - res = the_port->control(pb, dce, code); - break; - } - } - - if (code == 1) - return res; - else if (ReadMacInt16(pb + ioTrap) & 0x0200) { - WriteMacInt16(pb + ioResult, res); - return res; - } else { - IOCommandIsComplete(pb, res); - return res; - } -} - - -/* - * Driver Status() routine - */ - -int16 SerialStatus(uint32 pb, uint32 dce) -{ - uint16 code = ReadMacInt16(pb + csCode); - D(bug("SerialStatus %d, pb %08lx, dce %08lx\n", code, pb, dce)); - int16 res; - - SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1]; - if (!the_port->is_open) - res = notOpenErr; - else { - switch (code) { - case kSERDVersion: - WriteMacInt8(pb + csParam, 9); // Second-generation SerialDMA driver - res = noErr; - break; - - case 0x8000: - WriteMacInt8(pb + csParam, 9); // Second-generation SerialDMA driver - WriteMacInt16(pb + csParam + 4, 0x1997); // Date of serial driver - WriteMacInt16(pb + csParam + 6, 0x0616); - res = noErr; - break; - - default: - res = the_port->status(pb, dce, code); - break; - } - } - - if (ReadMacInt16(pb + ioTrap) & 0x0200) { - WriteMacInt16(pb + ioResult, res); - return res; - } else { - IOCommandIsComplete(pb, res); - return res; - } -} - - -/* - * Driver Close() routine - */ - -int16 SerialClose(uint32 pb, uint32 dce) -{ - D(bug("SerialClose pb %08lx, dce %08lx\n", pb, dce)); - - // Close port if open - SERDPort *the_port = the_serd_port[(-(int16)ReadMacInt16(dce + dCtlRefNum)-6) >> 1]; - if (the_port->is_open) { - Mac_sysfree(the_port->dt_store); - int16 res = the_port->close(); - the_port->is_open = false; - return res; - } else - return noErr; -} - - -/* - * Serial interrupt - Prime command completed, activate deferred tasks to call IODone - */ - -void SerialInterrupt(void) -{ - D(bug("SerialIRQ\n")); - - // Port 0 - if (the_serd_port[0]->is_open) { - if (the_serd_port[0]->read_pending && the_serd_port[0]->read_done) { - Enqueue(the_serd_port[0]->input_dt, 0xd92); - the_serd_port[0]->read_pending = the_serd_port[0]->read_done = false; - } - if (the_serd_port[0]->write_pending && the_serd_port[0]->write_done) { - Enqueue(the_serd_port[0]->output_dt, 0xd92); - the_serd_port[0]->write_pending = the_serd_port[0]->write_done = false; - } - } - - // Port 1 - if (the_serd_port[1]->is_open) { - if (the_serd_port[1]->read_pending && the_serd_port[1]->read_done) { - Enqueue(the_serd_port[1]->input_dt, 0xd92); - the_serd_port[1]->read_pending = the_serd_port[1]->read_done = false; - } - if (the_serd_port[1]->write_pending && the_serd_port[1]->write_done) { - Enqueue(the_serd_port[1]->output_dt, 0xd92); - the_serd_port[1]->write_pending = the_serd_port[1]->write_done = false; - } - } -} diff --git a/SheepShaver/src/slirp b/SheepShaver/src/slirp deleted file mode 120000 index 4e6fe8f5..00000000 --- a/SheepShaver/src/slirp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/slirp \ No newline at end of file diff --git a/SheepShaver/src/sony.cpp b/SheepShaver/src/sony.cpp deleted file mode 120000 index 42aaabb7..00000000 --- a/SheepShaver/src/sony.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/sony.cpp \ No newline at end of file diff --git a/SheepShaver/src/thunks.cpp b/SheepShaver/src/thunks.cpp deleted file mode 100644 index f8a1b64a..00000000 --- a/SheepShaver/src/thunks.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * thunks.cpp - Thunks to share data and code with MacOS - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "thunks.h" -#include "emul_op.h" -#include "cpu_emulation.h" -#include "xlowmem.h" - -// Native function declarations -#include "main.h" -#include "video.h" -#include "name_registry.h" -#include "serial.h" -#include "ether.h" -#include "macos_util.h" - -// Generate PowerPC thunks for GetResource() replacements? -#define POWERPC_GET_RESOURCE_THUNKS 1 - - -/* NativeOp instruction format: - +------------+-------------------------+--+-----------+------------+ - | 6 | |FN| OP | 2 | - +------------+-------------------------+--+-----------+------------+ - 0 5 |6 18 19 20 25 26 31 -*/ - -#define POWERPC_NATIVE_OP(FN, OP) \ - (POWERPC_EMUL_OP | ((FN) << 12) | (((uint32)OP) << 6) | 2) - -/* - * Return the fake PowerPC opcode to handle specified native code - */ - -#if EMULATED_PPC -uint32 NativeOpcode(int selector) -{ - uint32 opcode; - switch (selector) { - case NATIVE_CHECK_LOAD_INVOC: - case NATIVE_NAMED_CHECK_LOAD_INVOC: - case NATIVE_NQD_SYNC_HOOK: - case NATIVE_NQD_BITBLT_HOOK: - case NATIVE_NQD_FILLRECT_HOOK: - case NATIVE_NQD_UNKNOWN_HOOK: - case NATIVE_NQD_BITBLT: - case NATIVE_NQD_INVRECT: - case NATIVE_NQD_FILLRECT: - opcode = POWERPC_NATIVE_OP(0, selector); - break; - case NATIVE_PATCH_NAME_REGISTRY: - case NATIVE_VIDEO_INSTALL_ACCEL: - case NATIVE_VIDEO_VBL: - case NATIVE_VIDEO_DO_DRIVER_IO: - case NATIVE_ETHER_AO_GET_HWADDR: - case NATIVE_ETHER_AO_ADD_MULTI: - case NATIVE_ETHER_AO_DEL_MULTI: - case NATIVE_ETHER_AO_SEND_PACKET: - case NATIVE_ETHER_IRQ: - case NATIVE_ETHER_INIT: - case NATIVE_ETHER_TERM: - case NATIVE_ETHER_OPEN: - case NATIVE_ETHER_CLOSE: - case NATIVE_ETHER_WPUT: - case NATIVE_ETHER_RSRV: - case NATIVE_SERIAL_NOTHING: - case NATIVE_SERIAL_OPEN: - case NATIVE_SERIAL_PRIME_IN: - case NATIVE_SERIAL_PRIME_OUT: - case NATIVE_SERIAL_CONTROL: - case NATIVE_SERIAL_STATUS: - case NATIVE_SERIAL_CLOSE: - case NATIVE_GET_RESOURCE: - case NATIVE_GET_1_RESOURCE: - case NATIVE_GET_IND_RESOURCE: - case NATIVE_GET_1_IND_RESOURCE: - case NATIVE_R_GET_RESOURCE: - case NATIVE_GET_NAMED_RESOURCE: - case NATIVE_GET_1_NAMED_RESOURCE: - case NATIVE_MAKE_EXECUTABLE: - opcode = POWERPC_NATIVE_OP(1, selector); - break; - default: - abort(); - } - return opcode; -} -#endif - - -/* - * Generate PowerPC thunks for GetResource() replacements - */ - -#if EMULATED_PPC -static uint32 get_resource_func; -static uint32 get_1_resource_func; -static uint32 get_ind_resource_func; -static uint32 get_1_ind_resource_func; -static uint32 r_get_resource_func; -static uint32 get_named_resource_func; -static uint32 get_1_named_resource_func; - -static void generate_powerpc_thunks(void) -{ - // check_load_invoc() thunk - uint32 check_load_invoc_opcode = NativeOpcode(NATIVE_CHECK_LOAD_INVOC); - uint32 base; - - static uint32 get_resource_template[] = { - PL(0x7c0802a6), // mflr r0 - PL(0x90010008), // stw r0,8(r1) - PL(0x9421ffbc), // stwu r1,-68(r1) - PL(0x90610038), // stw r3,56(r1) - PL(0x9081003c), // stw r4,60(r1) - PL(0x00000000), // lwz r0,XLM_GET_RESOURCE(r0) - PL(0x80402834), // lwz r2,XLM_RES_LIB_TOC(r0) - PL(0x7c0903a6), // mtctr r0 - PL(0x4e800421), // bctrl - PL(0x90610040), // stw r3,64(r1) - PL(0x80610038), // lwz r3,56(r1) - PL(0xa881003e), // lha r4,62(r1) - PL(0x80a10040), // lwz r5,64(r1) - PL(0x00000001), // - PL(0x80610040), // lwz r3,64(r1) - PL(0x8001004c), // lwz r0,76(r1) - PL(0x7c0803a6), // mtlr r0 - PL(0x38210044), // addi r1,r1,68 - PL(0x4e800020) // blr - }; - const uint32 get_resource_template_size = sizeof(get_resource_template); - - int xlm_index = -1, check_load_invoc_index = -1; - for (int i = 0; i < get_resource_template_size/4; i++) { - uint32 opcode = ntohl(get_resource_template[i]); - switch (opcode) { - case 0x00000000: - xlm_index = i; - break; - case 0x00000001: - check_load_invoc_index = i; - break; - } - } - assert(xlm_index != -1 && check_load_invoc_index != -1); - - // GetResource() - get_resource_func = base = SheepMem::Reserve(get_resource_template_size); - Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); - - // Get1Resource() - get_1_resource_func = base = SheepMem::Reserve(get_resource_template_size); - Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); - - // GetIndResource() - get_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size); - Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_IND_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); - - // Get1IndResource() - get_1_ind_resource_func = base = SheepMem::Reserve(get_resource_template_size); - Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_IND_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); - - // RGetResource() - r_get_resource_func = base = SheepMem::Reserve(get_resource_template_size); - Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_R_GET_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); - - // named_check_load_invoc() thunk - check_load_invoc_opcode = NativeOpcode(NATIVE_NAMED_CHECK_LOAD_INVOC); - - static uint32 get_named_resource_template[] = { - PL(0x7c0802a6), // mflr r0 - PL(0x90010008), // stw r0,8(r1) - PL(0x9421ffbc), // stwu r1,-68(r1) - PL(0x90610038), // stw r3,56(r1) - PL(0x9081003c), // stw r4,60(r1) - PL(0x00000000), // lwz r0,XLM_GET_NAMED_RESOURCE(r0) - PL(0x80402834), // lwz r2,XLM_RES_LIB_TOC(r0) - PL(0x7c0903a6), // mtctr r0 - PL(0x4e800421), // bctrl - PL(0x90610040), // stw r3,64(r1) - PL(0x80610038), // lwz r3,56(r1) - PL(0x8081003c), // lwz r4,60(r1) - PL(0x80a10040), // lwz r5,64(r1) - PL(0x00000001), // - PL(0x80610040), // lwz r3,64(r1) - PL(0x8001004c), // lwz r0,76(r1) - PL(0x7c0803a6), // mtlr r0 - PL(0x38210044), // addi r1,r1,68 - PL(0x4e800020) // blr - }; - const uint32 get_named_resource_template_size = sizeof(get_named_resource_template); - - xlm_index = -1, check_load_invoc_index = -1; - for (int i = 0; i < get_resource_template_size/4; i++) { - uint32 opcode = ntohl(get_resource_template[i]); - switch (opcode) { - case 0x00000000: - xlm_index = i; - break; - case 0x00000001: - check_load_invoc_index = i; - break; - } - } - assert(xlm_index != -1 && check_load_invoc_index != -1); - - // GetNamedResource() - get_named_resource_func = base = SheepMem::Reserve(get_named_resource_template_size); - Host2Mac_memcpy(base, get_named_resource_template, get_named_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_NAMED_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); - - // Get1NamedResource() - get_1_named_resource_func = base = SheepMem::Reserve(get_named_resource_template_size); - Host2Mac_memcpy(base, get_named_resource_template, get_named_resource_template_size); - WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_NAMED_RESOURCE); - WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); -} -#endif - - -/* - * Initialize the thunks system - */ - -struct native_op_t { - uint32 tvect; - uint32 func; - SheepRoutineDescriptor *desc; -}; -static native_op_t native_op[NATIVE_OP_MAX]; - -bool ThunksInit(void) -{ -#if EMULATED_PPC - for (int i = 0; i < NATIVE_OP_MAX; i++) { - uintptr base = SheepMem::Reserve(16); - WriteMacInt32(base + 0, base + 8); - WriteMacInt32(base + 4, 0); // Fake TVECT - WriteMacInt32(base + 8, NativeOpcode(i)); - WriteMacInt32(base + 12, POWERPC_BLR); - native_op[i].tvect = base; - native_op[i].func = base + 8; - } -#if POWERPC_GET_RESOURCE_THUNKS - generate_powerpc_thunks(); - native_op[NATIVE_GET_RESOURCE].func = get_resource_func; - native_op[NATIVE_GET_1_RESOURCE].func = get_1_resource_func; - native_op[NATIVE_GET_IND_RESOURCE].func = get_ind_resource_func; - native_op[NATIVE_GET_1_IND_RESOURCE].func = get_1_ind_resource_func; - native_op[NATIVE_R_GET_RESOURCE].func = r_get_resource_func; - native_op[NATIVE_GET_NAMED_RESOURCE].func = get_named_resource_func; - native_op[NATIVE_GET_1_NAMED_RESOURCE].func = get_1_named_resource_func; -#endif -#else -#if defined(__linux__) || defined(__NetBSD__) || (defined(__APPLE__) && defined(__MACH__)) -#define DEFINE_NATIVE_OP(ID, FUNC) do { \ - uintptr base = SheepMem::Reserve(8); \ - WriteMacInt32(base + 0, (uint32)FUNC); \ - WriteMacInt32(base + 4, (uint32)TOC); \ - native_op[ID].tvect = base; \ - native_op[ID].func = (uint32)FUNC; \ - } while (0) -#elif defined(__BEOS__) -#define DEFINE_NATIVE_OP(ID, FUNC) do { \ - native_op[ID].tvect = FUNC; \ - native_op[ID].func = ((uint32 *)FUNC)[0]; \ - } while (0) -#else -#error "FIXME: define NativeOp for your platform" -#endif - // FIXME: add GetResource() and friends for completeness - DEFINE_NATIVE_OP(NATIVE_PATCH_NAME_REGISTRY, DoPatchNameRegistry); - DEFINE_NATIVE_OP(NATIVE_VIDEO_INSTALL_ACCEL, VideoInstallAccel); - DEFINE_NATIVE_OP(NATIVE_VIDEO_VBL, VideoVBL); - DEFINE_NATIVE_OP(NATIVE_VIDEO_DO_DRIVER_IO, VideoDoDriverIO); - DEFINE_NATIVE_OP(NATIVE_ETHER_AO_GET_HWADDR, AO_get_ethernet_address); - DEFINE_NATIVE_OP(NATIVE_ETHER_AO_ADD_MULTI, AO_enable_multicast); - DEFINE_NATIVE_OP(NATIVE_ETHER_AO_DEL_MULTI, AO_disable_multicast); - DEFINE_NATIVE_OP(NATIVE_ETHER_AO_SEND_PACKET, AO_transmit_packet); - DEFINE_NATIVE_OP(NATIVE_ETHER_IRQ, EtherIRQ); - DEFINE_NATIVE_OP(NATIVE_ETHER_INIT, InitStreamModule); - DEFINE_NATIVE_OP(NATIVE_ETHER_TERM, TerminateStreamModule); - DEFINE_NATIVE_OP(NATIVE_ETHER_OPEN, ether_open); - DEFINE_NATIVE_OP(NATIVE_ETHER_CLOSE, ether_close); - DEFINE_NATIVE_OP(NATIVE_ETHER_WPUT, ether_wput); - DEFINE_NATIVE_OP(NATIVE_ETHER_RSRV, ether_rsrv); - DEFINE_NATIVE_OP(NATIVE_SERIAL_NOTHING, SerialNothing); - DEFINE_NATIVE_OP(NATIVE_SERIAL_OPEN, SerialOpen); - DEFINE_NATIVE_OP(NATIVE_SERIAL_PRIME_IN, SerialPrimeIn); - DEFINE_NATIVE_OP(NATIVE_SERIAL_PRIME_OUT, SerialPrimeOut); - DEFINE_NATIVE_OP(NATIVE_SERIAL_CONTROL, SerialControl); - DEFINE_NATIVE_OP(NATIVE_SERIAL_STATUS, SerialStatus); - DEFINE_NATIVE_OP(NATIVE_SERIAL_CLOSE, SerialClose); - DEFINE_NATIVE_OP(NATIVE_MAKE_EXECUTABLE, MakeExecutable); - DEFINE_NATIVE_OP(NATIVE_NQD_SYNC_HOOK, NQD_sync_hook); - DEFINE_NATIVE_OP(NATIVE_NQD_BITBLT_HOOK, NQD_bitblt_hook); - DEFINE_NATIVE_OP(NATIVE_NQD_FILLRECT_HOOK, NQD_fillrect_hook); - DEFINE_NATIVE_OP(NATIVE_NQD_UNKNOWN_HOOK, NQD_unknown_hook); - DEFINE_NATIVE_OP(NATIVE_NQD_BITBLT, NQD_bitblt); - DEFINE_NATIVE_OP(NATIVE_NQD_INVRECT, NQD_invrect); - DEFINE_NATIVE_OP(NATIVE_NQD_FILLRECT, NQD_fillrect); -#undef DEFINE_NATIVE_OP -#endif - - // Initialize routine descriptors (if TVECT exists) - for (int i = 0; i < NATIVE_OP_MAX; i++) { - uint32 tvect = native_op[i].tvect; - if (tvect) - native_op[i].desc = new SheepRoutineDescriptor(0, tvect); - } - - return true; -} - - -/* - * Delete generated thunks - */ - -void ThunksExit(void) -{ - for (int i = 0; i < NATIVE_OP_MAX; i++) { - SheepRoutineDescriptor *desc = native_op[i].desc; - if (desc) - delete desc; - } -} - - -/* - * Return the native function descriptor (TVECT) - */ - -uint32 NativeTVECT(int selector) -{ - assert(selector < NATIVE_OP_MAX); - const uint32 tvect = native_op[selector].tvect; - assert(tvect != 0); - return tvect; -} - - -/* - * Return the native function address - */ - -uint32 NativeFunction(int selector) -{ - assert(selector < NATIVE_OP_MAX); - const uint32 func = native_op[selector].func; - assert(func != 0); - return func; -} - - -/* - * Return the routine descriptor address of the native function - */ - -uint32 NativeRoutineDescriptor(int selector) -{ - assert(selector < NATIVE_OP_MAX); - SheepRoutineDescriptor * const desc = native_op[selector].desc; - assert(desc != 0); - return desc->addr(); -} - - -/* - * Execute native code from EMUL_OP routine (real mode switch) - */ - -void ExecuteNative(int selector) -{ - M68kRegisters r; - Execute68k(NativeRoutineDescriptor(selector), &r); -} diff --git a/SheepShaver/src/timer.cpp b/SheepShaver/src/timer.cpp deleted file mode 100644 index 3edd6ca0..00000000 --- a/SheepShaver/src/timer.cpp +++ /dev/null @@ -1,677 +0,0 @@ -/* - * timer.cpp - Time Manager emulation - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include "timer.h" -#include "macos_util.h" -#include "main.h" -#include "cpu_emulation.h" - -#ifdef PRECISE_TIMING_POSIX -#include -#include -#endif - -#ifdef PRECISE_TIMING_MACH -#include -#endif - -#define DEBUG 0 -#include "debug.h" - - -#define TM_QUEUE 0 // Enable TMQueue management (doesn't work) - - -// Definitions for Time Manager -enum { // TMTask struct - tmAddr = 6, - tmCount = 10, - tmWakeUp = 14, - tmReserved = 18 -}; - - -// Array of additional info for each installed TMTask -struct TMDesc { - uint32 task; // Mac address of associated TMTask - tm_time_t wakeup; // Time this task is scheduled for execution - TMDesc *next; -}; - -static TMDesc *tmDescList; - -#if PRECISE_TIMING -#ifdef PRECISE_TIMING_BEOS -static thread_id timer_thread = -1; -static bool thread_active = true; -static const tm_time_t wakeup_time_max = 0x7fffffffffffffff; -static volatile tm_time_t wakeup_time = wakeup_time_max; -static sem_id wakeup_time_sem = -1; -static int32 timer_func(void *arg); -#endif -#ifdef PRECISE_TIMING_POSIX -static pthread_t timer_thread; -static bool timer_thread_active = false; -static volatile bool timer_thread_cancel = false; -static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 }; -static tm_time_t wakeup_time = wakeup_time_max; -static pthread_mutex_t wakeup_time_lock = PTHREAD_MUTEX_INITIALIZER; -static void *timer_func(void *arg); -#endif -#ifdef PRECISE_TIMING_MACH -static clock_serv_t system_clock; -static thread_act_t timer_thread; -static bool timer_thread_active = false; -static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 }; -static tm_time_t wakeup_time = wakeup_time_max; -static semaphore_t wakeup_time_sem; -static void *timer_func(void *arg); -#endif -#endif - - -inline static void free_desc(TMDesc *desc) -{ - if (desc == tmDescList) { - tmDescList = desc->next; - } else { - for (TMDesc *d = tmDescList; d; d = d->next) { - if (d->next == desc) { - d->next = desc->next; - break; - } - } - } - delete desc; -} - -/* - * Find descriptor associated with given TMTask - */ - -inline static TMDesc *find_desc(uint32 tm) -{ - TMDesc *desc = tmDescList; - while (desc) { - if (desc->task == tm) { - return desc; - } - desc = desc->next; - } - return NULL; -} - - -/* - * Enqueue task in Time Manager queue - */ - -static void enqueue_tm(uint32 tm) -{ -#if TM_QUEUE - uint32 tm_var = ReadMacInt32(0xb30); - WriteMacInt32(tm + qLink, ReadMacInt32(tm_var)); - WriteMacInt32(tm_var, tm); -#endif -} - - -/* - * Remove task from Time Manager queue - */ - -static void dequeue_tm(uint32 tm) -{ -#if TM_QUEUE - uint32 p = ReadMacInt32(0xb30); - while (p) { - uint32 next = ReadMacInt32(p + qLink); - if (next == tm) { - WriteMacInt32(p + qLink, ReadMacInt32(next + qLink)); - return; - } - } -#endif -} - - -/* - * Timer thread operations - */ - -#ifdef PRECISE_TIMING_POSIX -const int SIGSUSPEND = SIGRTMIN + 6; -const int SIGRESUME = SIGRTMIN + 7; -static struct sigaction sigsuspend_action; -static struct sigaction sigresume_action; - -static int suspend_count = 0; -static pthread_mutex_t suspend_count_lock = PTHREAD_MUTEX_INITIALIZER; -static sem_t suspend_ack_sem; -static sigset_t suspend_handler_mask; - -// Signal handler for suspended thread -static void sigsuspend_handler(int sig) -{ - sem_post(&suspend_ack_sem); - sigsuspend(&suspend_handler_mask); -} - -// Signal handler for resumed thread -static void sigresume_handler(int sig) -{ - /* simply trigger a signal to stop clock_nanosleep() */ -} - -// Initialize timer thread -static bool timer_thread_init(void) -{ - // Install suspend signal handler - sigemptyset(&sigsuspend_action.sa_mask); - sigaddset(&sigsuspend_action.sa_mask, SIGRESUME); - sigsuspend_action.sa_handler = sigsuspend_handler; - sigsuspend_action.sa_flags = SA_RESTART; -#ifdef HAVE_SIGNAL_SA_RESTORER - sigsuspend_action.sa_restorer = NULL; -#endif - if (sigaction(SIGSUSPEND, &sigsuspend_action, NULL) < 0) - return false; - - // Install resume signal handler - sigemptyset(&sigresume_action.sa_mask); - sigresume_action.sa_handler = sigresume_handler; - sigresume_action.sa_flags = SA_RESTART; -#ifdef HAVE_SIGNAL_SA_RESTORER - sigresume_action.sa_restorer = NULL; -#endif - if (sigaction(SIGRESUME, &sigresume_action, NULL) < 0) - return false; - - // Initialize semaphore - if (sem_init(&suspend_ack_sem, 0, 0) < 0) - return false; - - // Initialize suspend_handler_mask, it excludes SIGRESUME - if (sigfillset(&suspend_handler_mask) != 0) - return false; - if (sigdelset(&suspend_handler_mask, SIGRESUME) != 0) - return false; - - // Create thread in running state - suspend_count = 0; - return (pthread_create(&timer_thread, NULL, timer_func, NULL) == 0); -} - -// Kill timer thread -static void timer_thread_kill(void) -{ - timer_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(timer_thread); -#endif - pthread_join(timer_thread, NULL); -} - -// Suspend timer thread -static void timer_thread_suspend(void) -{ - pthread_mutex_lock(&suspend_count_lock); - if (suspend_count == 0) { - suspend_count ++; - if (pthread_kill(timer_thread, SIGSUSPEND) == 0) - sem_wait(&suspend_ack_sem); - } - pthread_mutex_unlock(&suspend_count_lock); -} - -// Resume timer thread -static void timer_thread_resume(void) -{ - pthread_mutex_lock(&suspend_count_lock); - assert(suspend_count > 0); - if (suspend_count == 1) { - suspend_count = 0; - pthread_kill(timer_thread, SIGRESUME); - } - pthread_mutex_unlock(&suspend_count_lock); -} -#endif - - -/* - * Initialize Time Manager - */ - -void TimerInit(void) -{ - TimerReset(); - -#if PRECISE_TIMING - // Start timer thread -#ifdef PRECISE_TIMING_BEOS - wakeup_time_sem = create_sem(1, "Wakeup Time"); - timer_thread = spawn_thread(timer_func, "Time Manager", B_REAL_TIME_PRIORITY, NULL); - resume_thread(timer_thread); -#elif PRECISE_TIMING_MACH - pthread_t pthread; - - host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &system_clock); - semaphore_create(mach_task_self(), &wakeup_time_sem, SYNC_POLICY_FIFO, 1); - - pthread_create(&pthread, NULL, &timer_func, NULL); -#endif -#ifdef PRECISE_TIMING_POSIX - timer_thread_active = timer_thread_init(); -#endif -#endif -} - - -/* - * Exit Time Manager - */ - -void TimerExit(void) -{ -#if PRECISE_TIMING - // Quit timer thread - if (timer_thread > 0) { -#ifdef PRECISE_TIMING_BEOS - status_t l; - thread_active = false; - suspend_thread(timer_thread); - resume_thread(timer_thread); - wait_for_thread(timer_thread, &l); - delete_sem(wakeup_time_sem); -#endif -#ifdef PRECISE_TIMING_MACH - timer_thread_active = false; - semaphore_destroy(mach_task_self(), wakeup_time_sem); -#endif -#ifdef PRECISE_TIMING_POSIX - timer_thread_kill(); -#endif - } -#endif -} - - -/* - * Emulator reset, remove all timer tasks - */ - -void TimerReset(void) -{ - TMDesc *desc = tmDescList; - while (desc) { - TMDesc *next = desc->next; - delete desc; - desc = next; - } - tmDescList = NULL; -} - - -/* - * Insert timer task - */ - -int16 InsTime(uint32 tm, uint16 trap) -{ - D(bug("InsTime %08lx, trap %04x\n", tm, trap)); - WriteMacInt16((uint32)tm + qType, ReadMacInt16((uint32)tm + qType) & 0x1fff | (trap << 4) & 0x6000); - if (find_desc(tm)) - printf("WARNING: InsTime(%08x): Task re-inserted\n", tm); - else { - TMDesc *desc = new TMDesc; - desc->task = tm; - desc->next = tmDescList; - tmDescList = desc; - } - return 0; -} - - -/* - * Remove timer task - */ - -int16 RmvTime(uint32 tm) -{ - D(bug("RmvTime %08lx\n", tm)); - - // Find descriptor - TMDesc *desc = find_desc(tm); - if (!desc) { - printf("WARNING: RmvTime(%08x): Descriptor not found\n", tm); - return 0; - } - - // Task active? -#if PRECISE_TIMING_BEOS - while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; - suspend_thread(timer_thread); -#endif -#ifdef PRECISE_TIMING_MACH - semaphore_wait(wakeup_time_sem); - thread_suspend(timer_thread); -#endif -#if PRECISE_TIMING_POSIX - timer_thread_suspend(); - pthread_mutex_lock(&wakeup_time_lock); -#endif - if (ReadMacInt16(tm + qType) & 0x8000) { - - // Yes, make task inactive and remove it from the Time Manager queue - WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); - dequeue_tm(tm); -#if PRECISE_TIMING - // Look for next task to be called and set wakeup_time - wakeup_time = wakeup_time_max; - for (TMDesc *d = tmDescList; d; d = d->next) - if ((ReadMacInt16(d->task + qType) & 0x8000)) - if (timer_cmp_time(d->wakeup, wakeup_time) < 0) - wakeup_time = d->wakeup; -#endif - - // Compute remaining time - tm_time_t remaining, current; - timer_current_time(current); - timer_sub_time(remaining, desc->wakeup, current); - WriteMacInt32(tm + tmCount, timer_host2mac_time(remaining)); - } else - WriteMacInt32(tm + tmCount, 0); - D(bug(" tmCount %ld\n", ReadMacInt32(tm + tmCount))); -#if PRECISE_TIMING_BEOS - release_sem(wakeup_time_sem); - thread_info info; - do { - resume_thread(timer_thread); // This will unblock the thread - get_thread_info(timer_thread, &info); - } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) -#endif -#ifdef PRECISE_TIMING_MACH - semaphore_signal(wakeup_time_sem); - thread_abort(timer_thread); - thread_resume(timer_thread); -#endif -#if PRECISE_TIMING_POSIX - pthread_mutex_unlock(&wakeup_time_lock); - timer_thread_resume(); - assert(suspend_count == 0); -#endif - - // Free descriptor - free_desc(desc); - return 0; -} - - -/* - * Start timer task - */ - -int16 PrimeTime(uint32 tm, int32 time) -{ - D(bug("PrimeTime %08lx, time %ld\n", tm, time)); - - // Find descriptor - TMDesc *desc = find_desc(tm); - if (!desc) { - printf("FATAL: PrimeTime(%08x): Descriptor not found\n", tm); - return 0; - } - - // Convert delay time - tm_time_t delay; - timer_mac2host_time(delay, time); - - // Extended task? - if (ReadMacInt16(tm + qType) & 0x4000) { - - // Yes, tmWakeUp set? - if (ReadMacInt32(tm + tmWakeUp)) { - - // PrimeTime(0) can either mean (a) "the task runs as soon as interrupts are enabled" - // or (b) "continue previous delay" if an expired task was stopped via RmvTime() and - // then re-installed using InsXTime(). Since tmWakeUp was set, this is case (b). - // The remaining time was saved in tmCount by RmvTime(). - if (time == 0) { - timer_mac2host_time(delay, ReadMacInt16(tm + tmCount)); - } - - // Yes, calculate wakeup time relative to last scheduled time - tm_time_t wakeup; - timer_add_time(wakeup, desc->wakeup, delay); - desc->wakeup = wakeup; - - } else { - - // No, calculate wakeup time relative to current time - tm_time_t now; - timer_current_time(now); - timer_add_time(desc->wakeup, now, delay); - } - - // Set tmWakeUp to indicate that task was scheduled - WriteMacInt32(tm + tmWakeUp, 0x12345678); - - } else { - - // Not extended task, calculate wakeup time relative to current time - tm_time_t now; - timer_current_time(now); - timer_add_time(desc->wakeup, now, delay); - } - - // Make task active and enqueue it in the Time Manager queue -#if PRECISE_TIMING_BEOS - while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; - suspend_thread(timer_thread); -#endif -#ifdef PRECISE_TIMING_MACH - semaphore_wait(wakeup_time_sem); - thread_suspend(timer_thread); -#endif -#if PRECISE_TIMING_POSIX - timer_thread_suspend(); - pthread_mutex_lock(&wakeup_time_lock); -#endif - WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000); - enqueue_tm(tm); -#if PRECISE_TIMING - // Look for next task to be called and set wakeup_time - wakeup_time = wakeup_time_max; - for (TMDesc *d = tmDescList; d; d = d->next) - if ((ReadMacInt16(d->task + qType) & 0x8000)) - if (timer_cmp_time(d->wakeup, wakeup_time) < 0) - wakeup_time = d->wakeup; -#ifdef PRECISE_TIMING_BEOS - release_sem(wakeup_time_sem); - thread_info info; - do { - resume_thread(timer_thread); // This will unblock the thread - get_thread_info(timer_thread, &info); - } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) -#endif -#ifdef PRECISE_TIMING_MACH - semaphore_signal(wakeup_time_sem); - thread_abort(timer_thread); - thread_resume(timer_thread); -#endif -#ifdef PRECISE_TIMING_POSIX - pthread_mutex_unlock(&wakeup_time_lock); - timer_thread_resume(); - assert(suspend_count == 0); -#endif -#endif - return 0; -} - - -/* - * Time Manager thread - */ - -#ifdef PRECISE_TIMING_BEOS -static int32 timer_func(void *arg) -{ - while (thread_active) { - - // Wait until time specified by wakeup_time - snooze_until(wakeup_time, B_SYSTEM_TIMEBASE); - - while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; - if (wakeup_time < system_time()) { - - // Timer expired, trigger interrupt - wakeup_time = 0x7fffffffffffffff; - SetInterruptFlag(INTFLAG_TIMER); - TriggerInterrupt(); - } - release_sem(wakeup_time_sem); - } - return 0; -} -#endif - -#ifdef PRECISE_TIMING_MACH -static void *timer_func(void *arg) -{ - timer_thread = mach_thread_self(); - timer_thread_active = true; - - while (timer_thread_active) { - clock_sleep(system_clock, TIME_ABSOLUTE, wakeup_time, NULL); - semaphore_wait(wakeup_time_sem); - - tm_time_t system_time; - - timer_current_time(system_time); - if (timer_cmp_time(wakeup_time, system_time) < 0) { - wakeup_time = wakeup_time_max; - SetInterruptFlag(INTFLAG_TIMER); - TriggerInterrupt(); - } - semaphore_signal(wakeup_time_sem); - } - return NULL; -} -#endif - -#ifdef PRECISE_TIMING_POSIX -static void *timer_func(void *arg) -{ - while (!timer_thread_cancel) { - // Wait until time specified by wakeup_time - clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wakeup_time, NULL); - - tm_time_t system_time; - timer_current_time(system_time); - if (timer_cmp_time(wakeup_time, system_time) < 0) { - - // Timer expired, trigger interrupt - pthread_mutex_lock(&wakeup_time_lock); - wakeup_time = wakeup_time_max; - pthread_mutex_unlock(&wakeup_time_lock); - SetInterruptFlag(INTFLAG_TIMER); - TriggerInterrupt(); - } - } - return NULL; -} -#endif - - -/* - * Timer interrupt function (executed as part of 60Hz interrupt) - */ - -void TimerInterrupt(void) -{ -// D(bug("TimerIRQ\n")); - - // Look for active TMTasks that have expired - tm_time_t now; - timer_current_time(now); - TMDesc *desc = tmDescList; - while (desc) { - TMDesc *next = desc->next; - uint32 tm = desc->task; - if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc->wakeup, now) <= 0) { - - // Found one, mark as inactive and remove it from the Time Manager queue - WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); - dequeue_tm(tm); - - // Call timer function - uint32 addr = ReadMacInt32(tm + tmAddr); - if (addr) { - D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr)); - M68kRegisters r; - r.a[0] = addr; - r.a[1] = tm; - Execute68k(r.a[0], &r); - D(bug(" returned from TimeTask\n")); - } - } - desc = next; - } - -#if PRECISE_TIMING - // Look for next task to be called and set wakeup_time -#if PRECISE_TIMING_BEOS - while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; - suspend_thread(timer_thread); -#endif -#if PRECISE_TIMING_MACH - semaphore_wait(wakeup_time_sem); - thread_suspend(timer_thread); -#endif -#if PRECISE_TIMING_POSIX - timer_thread_suspend(); - pthread_mutex_lock(&wakeup_time_lock); -#endif - wakeup_time = wakeup_time_max; - for (TMDesc *d = tmDescList; d; d = d->next) - if ((ReadMacInt16(d->task + qType) & 0x8000)) - if (timer_cmp_time(d->wakeup, wakeup_time) < 0) - wakeup_time = d->wakeup; -#if PRECISE_TIMING_BEOS - release_sem(wakeup_time_sem); - thread_info info; - do { - resume_thread(timer_thread); // This will unblock the thread - get_thread_info(timer_thread, &info); - } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) -#endif -#if PRECISE_TIMING_MACH - semaphore_signal(wakeup_time_sem); - thread_abort(timer_thread); - thread_resume(timer_thread); -#endif -#if PRECISE_TIMING_POSIX - pthread_mutex_unlock(&wakeup_time_lock); - timer_thread_resume(); - assert(suspend_count == 0); -#endif -#endif -} diff --git a/SheepShaver/src/user_strings.cpp b/SheepShaver/src/user_strings.cpp deleted file mode 100644 index 4041d451..00000000 --- a/SheepShaver/src/user_strings.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * user_strings.cpp - Localizable strings - * - * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - * This should only be used for user-interface related messages that must be - * translated or transcibed for localized versions of SheepShaver. - * It should NOT be used for: - * - file names - * - names of threads, areas, ports, semaphores, drivers, views and other "invisible" names - * - debugging messages - * - error messages that only go to the shell ("FATAL"/"WARNING", those are really debugging messages) - */ - -#include "sysdeps.h" -#include "user_strings.h" - -#ifdef __BEOS__ -#define ELLIPSIS "\xE2\x80\xA6" -#else -#define ELLIPSIS "..." -#endif - - -// Common string definitions -user_string_def common_strings[] = { - {STR_ABOUT_TEXT1, "SheepShaver V%d.%d"}, - {STR_ABOUT_TEXT2, "by Christian Bauer and Mar\"c\" Hellwig"}, - {STR_READING_ROM_FILE, "Reading ROM file...\n"}, - {STR_SHELL_ERROR_PREFIX, "ERROR: %s\n"}, - {STR_GUI_ERROR_PREFIX, "SheepShaver error:\n%s"}, - {STR_ERROR_ALERT_TITLE, "SheepShaver Error"}, - {STR_SHELL_WARNING_PREFIX, "WARNING: %s\n"}, - {STR_GUI_WARNING_PREFIX, "SheepShaver warning:\n%s"}, - {STR_WARNING_ALERT_TITLE, "SheepShaver Warning"}, - {STR_NOTICE_ALERT_TITLE, "SheepShaver Notice"}, - {STR_ABOUT_TITLE, "About SheepShaver"}, - {STR_OK_BUTTON, "OK"}, - {STR_START_BUTTON, "Start"}, - {STR_QUIT_BUTTON, "Quit"}, - {STR_CANCEL_BUTTON, "Cancel"}, - {STR_IGNORE_BUTTON, "Ignore"}, - - {STR_NOT_ENOUGH_MEMORY_ERR, "Your computer does not have enough memory to run SheepShaver."}, - {STR_NO_KERNEL_DATA_ERR, "Cannot create Kernel Data area: %s (%08x)."}, - {STR_NO_ROM_FILE_ERR, "Cannot open ROM file."}, - {STR_RAM_HIGHER_THAN_ROM_ERR, "RAM area higher than ROM area. Try to decrease the MacOS RAM size."}, - {STR_ROM_FILE_READ_ERR, "Cannot read ROM file."}, - {STR_ROM_SIZE_ERR, "Invalid ROM file size. SheepShaver requires a 4MB PCI PowerMac ROM."}, - {STR_UNSUPPORTED_ROM_TYPE_ERR, "Unsupported ROM type."}, - {STR_POWER_INSTRUCTION_ERR, "Your Mac program is using POWER instructions which are not supported by SheepShaver.\n(pc %p, sp %p, opcode %08lx)"}, - {STR_MEM_ACCESS_ERR, "Your Mac program made an illegal %s %s access to address %p.\n(pc %p, 68k pc %p, sp %p)"}, - {STR_MEM_ACCESS_READ, "read"}, - {STR_MEM_ACCESS_WRITE, "write"}, - {STR_UNKNOWN_SEGV_ERR, "Your Mac program did something terribly stupid.\n(pc %p, 68k pc %p, sp %p, opcode %08lx)"}, - {STR_NO_NAME_REGISTRY_ERR, "Cannot find Name Registry. Giving up."}, - {STR_FULL_SCREEN_ERR, "Cannot open full screen display: %s (%08x)."}, - {STR_SCSI_BUFFER_ERR, "Cannot allocate SCSI buffer (requested %d bytes). Giving up."}, - {STR_SCSI_SG_FULL_ERR, "SCSI scatter/gather table full. Giving up."}, - - {STR_SMALL_RAM_WARN, "Selected less than 8MB Mac RAM, using 8MB."}, - {STR_CANNOT_UNMOUNT_WARN, "The volume '%s' could not be unmounted. SheepShaver will not use it."}, - {STR_CREATE_VOLUME_WARN, "Cannot create hardfile (%s)."}, - - {STR_PREFS_TITLE, "SheepShaver Settings"}, - {STR_PREFS_MENU, "Settings"}, - {STR_PREFS_ITEM_ABOUT, "About SheepShaver" ELLIPSIS}, - {STR_PREFS_ITEM_START, "Start SheepShaver"}, - {STR_PREFS_ITEM_ZAP_PRAM, "Zap PRAM File"}, - {STR_PREFS_ITEM_QUIT, "Quit SheepShaver"}, - - {STR_NONE_LAB, ""}, - - {STR_VOLUMES_PANE_TITLE, "Volumes"}, - {STR_ADD_VOLUME_BUTTON, "Add" ELLIPSIS}, - {STR_CREATE_VOLUME_BUTTON, "Create" ELLIPSIS}, - {STR_REMOVE_VOLUME_BUTTON, "Remove"}, - {STR_ADD_VOLUME_PANEL_BUTTON, "Add"}, - {STR_CREATE_VOLUME_PANEL_BUTTON, "Create"}, - {STR_CDROM_DRIVE_CTRL, "CD-ROM Drive"}, - {STR_BOOTDRIVER_CTRL, "Boot From"}, - {STR_BOOT_ANY_LAB, "Any"}, - {STR_BOOT_CDROM_LAB, "CD-ROM"}, - {STR_NOCDROM_CTRL, "Disable CD-ROM Driver"}, - {STR_ADD_VOLUME_TITLE, "Add Volume"}, - {STR_CREATE_VOLUME_TITLE, "Create Hardfile"}, - {STR_HARDFILE_SIZE_CTRL, "Size (MB)"}, - - {STR_GRAPHICS_SOUND_PANE_TITLE, "Graphics/Sound"}, - {STR_FRAMESKIP_CTRL, "Window Refresh Rate"}, - {STR_REF_5HZ_LAB, "5 Hz"}, - {STR_REF_7_5HZ_LAB, "7.5 Hz"}, - {STR_REF_10HZ_LAB, "10 Hz"}, - {STR_REF_15HZ_LAB, "15 Hz"}, - {STR_REF_30HZ_LAB, "30 Hz"}, - {STR_REF_60HZ_LAB, "60 Hz"}, - {STR_REF_DYNAMIC_LAB, "Dynamic"}, - {STR_GFXACCEL_CTRL, "QuickDraw Acceleration"}, - {STR_8_BIT_CTRL, "8 Bit"}, - {STR_16_BIT_CTRL, "15 Bit"}, - {STR_32_BIT_CTRL, "32 Bit"}, - {STR_W_640x480_CTRL, "Window 640x480"}, - {STR_W_800x600_CTRL, "Window 800x600"}, - {STR_640x480_CTRL, "Fullscreen 640x480"}, - {STR_800x600_CTRL, "Fullscreen 800x600"}, - {STR_1024x768_CTRL, "Fullscreen 1024x768"}, - {STR_1152x768_CTRL, "Fullscreen 1152x768"}, - {STR_1152x900_CTRL, "Fullscreen 1152x900"}, - {STR_1280x1024_CTRL, "Fullscreen 1280x1024"}, - {STR_1600x1200_CTRL, "Fullscreen 1600x1200"}, - {STR_VIDEO_MODE_CTRL, "Enabled Video Modes"}, - {STR_FULLSCREEN_CTRL, "Fullscreen"}, - {STR_WINDOW_CTRL, "Window"}, - {STR_VIDEO_TYPE_CTRL, "Video Type"}, - {STR_DISPLAY_X_CTRL, "Width"}, - {STR_DISPLAY_Y_CTRL, "Height"}, - {STR_SIZE_384_LAB, "384"}, - {STR_SIZE_480_LAB, "480"}, - {STR_SIZE_512_LAB, "512"}, - {STR_SIZE_600_LAB, "600"}, - {STR_SIZE_640_LAB, "640"}, - {STR_SIZE_768_LAB, "768"}, - {STR_SIZE_800_LAB, "800"}, - {STR_SIZE_1024_LAB, "1024"}, - {STR_SIZE_MAX_LAB, "Maximum"}, - {STR_NOSOUND_CTRL, "Disable Sound Output"}, - - {STR_SERIAL_NETWORK_PANE_TITLE, "Serial/Network"}, - {STR_SERPORTA_CTRL, "Modem Port"}, - {STR_SERPORTB_CTRL, "Printer Port"}, - {STR_NONET_CTRL, "Disable Ethernet"}, - {STR_ETHERNET_IF_CTRL, "Ethernet Interface"}, - - {STR_MEMORY_MISC_PANE_TITLE, "Memory/Misc"}, - {STR_RAMSIZE_CTRL, "MacOS RAM Size (MB)"}, - {STR_RAMSIZE_4MB_LAB, "4"}, - {STR_RAMSIZE_8MB_LAB, "8"}, - {STR_RAMSIZE_16MB_LAB, "16"}, - {STR_RAMSIZE_32MB_LAB, "32"}, - {STR_RAMSIZE_64MB_LAB, "64"}, - {STR_RAMSIZE_128MB_LAB, "128"}, - {STR_RAMSIZE_256MB_LAB, "256"}, - {STR_RAMSIZE_512MB_LAB, "512"}, - {STR_RAMSIZE_1024MB_LAB, "1024"}, - {STR_RAMSIZE_SLIDER, "MacOS RAM Size:"}, - {STR_RAMSIZE_FMT, "%d MB"}, - {STR_IGNORESEGV_CTRL, "Ignore Illegal Memory Accesses"}, - {STR_IDLEWAIT_CTRL, "Don't Use CPU When Idle"}, - {STR_ROM_FILE_CTRL, "ROM File"}, - - {STR_JIT_PANE_TITLE, "JIT Compiler"}, - {STR_JIT_CTRL, "Enable JIT Compiler"}, - {STR_JIT_68K_CTRL, "Enable built-in 68k DR Emulator (EXPERIMENTAL)"}, - - {STR_WINDOW_TITLE, "SheepShaver"}, - {STR_WINDOW_TITLE_FROZEN, "SheepShaver *** FROZEN ***"}, - {STR_WINDOW_MENU, "SheepShaver"}, - {STR_WINDOW_ITEM_ABOUT, "About SheepShaver" ELLIPSIS}, - {STR_WINDOW_ITEM_REFRESH, "Refresh Rate"}, - {STR_WINDOW_ITEM_MOUNT, "Mount"}, - - {STR_SOUND_IN_NAME, "\010Built-In"}, - - {STR_EXTFS_NAME, "Host Directory Tree"}, - {STR_EXTFS_VOLUME_NAME, "Host"}, - - {-1, NULL} // End marker -}; diff --git a/SheepShaver/src/video.cpp b/SheepShaver/src/video.cpp deleted file mode 100644 index d0eda93d..00000000 --- a/SheepShaver/src/video.cpp +++ /dev/null @@ -1,1097 +0,0 @@ -/* - * video.cpp - Video/graphics emulation - * - * SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * TODO - * - check for supported modes ??? - */ - -#include -#include - -#include "sysdeps.h" -#include "video.h" -#include "video_defs.h" -#include "main.h" -#include "adb.h" -#include "macos_util.h" -#include "user_strings.h" -#include "version.h" -#include "thunks.h" - -#define DEBUG 0 -#include "debug.h" - - -// Global variables -bool video_activated = false; // Flag: video display activated, mouse and keyboard data valid -uint32 screen_base = 0; // Frame buffer base address -int cur_mode; // Number of current video mode (index in VModes array) -int display_type = DIS_INVALID; // Current display type -rgb_color mac_pal[256]; -uint8 remap_mac_be[256]; -uint8 MacCursor[68] = {16, 1}; // Mac cursor image - - -bool keyfile_valid; // Flag: Keyfile is valid, enable full-screen modes - - -/* - * Video mode information (constructed by VideoInit()) - */ - -struct VideoInfo VModes[64]; - - -/* - * Driver local variables - */ - -VidLocals *private_data = NULL; // Pointer to driver local variables (there is only one display, so this is ok) - -static long save_conf_id = APPLE_W_640x480; -static long save_conf_mode = APPLE_8_BIT; - - -// Function pointers of imported functions -typedef int16 (*iocic_ptr)(void *, int16); -static uint32 iocic_tvect = 0; -static inline int16 IOCommandIsComplete(uintptr arg1, int16 arg2) -{ - return (int16)CallMacOS2(iocic_ptr, iocic_tvect, (void *)arg1, arg2); -} -typedef int16 (*vslnewis_ptr)(void *, uint32, uint32 *); -static uint32 vslnewis_tvect = 0; -static inline int16 VSLNewInterruptService(uintptr arg1, uint32 arg2, uintptr arg3) -{ - return (int16)CallMacOS3(vslnewis_ptr, vslnewis_tvect, (void *)arg1, arg2, (uint32 *)arg3); -} -typedef int16 (*vsldisposeis_ptr)(uint32); -static uint32 vsldisposeis_tvect = 0; -static inline int16 VSLDisposeInterruptService(uint32 arg1) -{ - return (int16)CallMacOS1(vsldisposeis_ptr, vsldisposeis_tvect, arg1); -} -typedef int16 (*vsldois_ptr)(uint32); -static uint32 vsldois_tvect = 0; -int16 VSLDoInterruptService(uint32 arg1) -{ - return (int16)CallMacOS1(vsldois_ptr, vsldois_tvect, arg1); -} -typedef void (*nqdmisc_ptr)(uint32, void *); -static uint32 nqdmisc_tvect = 0; -void NQDMisc(uint32 arg1, uintptr arg2) -{ - CallMacOS2(nqdmisc_ptr, nqdmisc_tvect, arg1, (void *)arg2); -} - - -// Prototypes -static int16 set_gamma(VidLocals *csSave, uint32 gamma); - - -/* - * Tell whether window/screen is activated or not (for mouse/keyboard polling) - */ - -bool VideoActivated(void) -{ - return video_activated; -} - - -/* - * Create RGB snapshot of current screen - */ - -bool VideoSnapshot(int xsize, int ysize, uint8 *p) -{ - if (display_type == DIS_WINDOW) { - uint8 *screen = (uint8 *)private_data->saveBaseAddr; - uint32 row_bytes = VModes[cur_mode].viRowBytes; - uint32 y2size = VModes[cur_mode].viYsize; - uint32 x2size = VModes[cur_mode].viXsize; - for (int j=0;jsaveBaseAddr = screen_base; - csSave->saveData = VModes[cur_mode].viAppleID;// First mode ... - csSave->saveMode = VModes[cur_mode].viAppleMode; - csSave->savePage = 0; - csSave->saveVidParms = 0; // Add the right table - csSave->luminanceMapping = false; - csSave->cursorHardware = UseHardwareCursor(); - csSave->cursorX = 0; - csSave->cursorY = 0; - csSave->cursorVisible = 0; - csSave->cursorSet = 0; - csSave->cursorHotFlag = false; - csSave->cursorHotX = 0; - csSave->cursorHotY = 0; - - // Find and set default gamma table - csSave->gammaTable = 0; - csSave->maxGammaTableSize = 0; - set_gamma(csSave, 0); - - // Install and activate interrupt service - SheepVar32 theServiceID = 0; - VSLNewInterruptService(csSave->regEntryID, FOURCC('v','b','l',' '), theServiceID.addr()); - csSave->vslServiceID = theServiceID.value(); - D(bug(" Interrupt ServiceID %08lx\n", csSave->vslServiceID)); - csSave->interruptsEnabled = true; - - return noErr; -} - - -/* - * Video driver control routine - */ - -static bool allocate_gamma_table(VidLocals *csSave, uint32 size) -{ - if (size > csSave->maxGammaTableSize) { - if (csSave->gammaTable) { - Mac_sysfree(csSave->gammaTable); - csSave->gammaTable = 0; - csSave->maxGammaTableSize = 0; - } - if ((csSave->gammaTable = Mac_sysalloc(size)) == 0) - return false; - csSave->maxGammaTableSize = size; - } - return true; -} - -static int16 set_gamma(VidLocals *csSave, uint32 gamma) -{ - if (gamma == 0) { // Build linear ramp, 256 entries - - // Allocate new table, if necessary - if (!allocate_gamma_table(csSave, SIZEOF_GammaTbl + 256)) - return memFullErr; - - // Initialize header - WriteMacInt16(csSave->gammaTable + gVersion, 0); // A version 0 style of the GammaTbl structure - WriteMacInt16(csSave->gammaTable + gType, 0); // Frame buffer hardware invariant - WriteMacInt16(csSave->gammaTable + gFormulaSize, 0); // No formula data, just correction data - WriteMacInt16(csSave->gammaTable + gChanCnt, 1); // Apply same correction to Red, Green, & Blue - WriteMacInt16(csSave->gammaTable + gDataCnt, 256); // gDataCnt == 2^^gDataWidth - WriteMacInt16(csSave->gammaTable + gDataWidth, 8); // 8 bits of significant data per entry - - // Build the linear ramp - uint32 p = csSave->gammaTable + gFormulaData; - for (int i=0; i<256; i++) - WriteMacInt8(p + i, i); - - } else { // User-supplied gamma table - - // Validate header - if (ReadMacInt16(gamma + gVersion) != 0) - return paramErr; - if (ReadMacInt16(gamma + gType) != 0) - return paramErr; - int chan_cnt = ReadMacInt16(gamma + gChanCnt); - if (chan_cnt != 1 && chan_cnt != 3) - return paramErr; - int data_width = ReadMacInt16(gamma + gDataWidth); - if (data_width > 8) - return paramErr; - int data_cnt = ReadMacInt16(gamma + gDataCnt); - if (data_cnt != (1 << data_width)) - return paramErr; - - // Allocate new table, if necessary - int size = SIZEOF_GammaTbl + ReadMacInt16(gamma + gFormulaSize) + chan_cnt * data_cnt; - if (!allocate_gamma_table(csSave, size)) - return memFullErr; - - // Copy table - Mac2Mac_memcpy(csSave->gammaTable, gamma, size); - } - return noErr; -} - -static int16 VideoControl(uint32 pb, VidLocals *csSave) -{ - int16 code = ReadMacInt16(pb + csCode); - D(bug("VideoControl %d: ", code)); - uint32 param = ReadMacInt32(pb + csParam); - switch (code) { - - case cscReset: // VidReset - D(bug("VidReset\n")); - return controlErr; - - case cscKillIO: // VidKillIO - D(bug("VidKillIO\n")); - return controlErr; - - case cscSetMode: // SetVidMode - D(bug("SetVidMode\n")); - D(bug("mode:%04x page:%04x \n", ReadMacInt16(param + csMode), - ReadMacInt16(param + csPage))); - WriteMacInt32(param + csData, csSave->saveData); - return video_mode_change(csSave, param); - - case cscSetEntries: { // SetEntries - D(bug("SetEntries\n")); - if (VModes[cur_mode].viAppleMode > APPLE_8_BIT) return controlErr; - uint32 s_pal = ReadMacInt32(param + csTable); - uint16 start = ReadMacInt16(param + csStart); - uint16 count = ReadMacInt16(param + csCount); - if (s_pal == 0 || count > 256) return controlErr; - - // Preparations for gamma correction - bool do_gamma = false; - uint8 *red_gamma = NULL; - uint8 *green_gamma = NULL; - uint8 *blue_gamma = NULL; - int gamma_data_width = 0; - if (csSave->gammaTable) { -#ifdef __BEOS__ - // Windows are gamma-corrected by BeOS - const bool can_do_gamma = (display_type == DIS_SCREEN); -#else - const bool can_do_gamma = true; -#endif - if (can_do_gamma) { - uint32 gamma_table = csSave->gammaTable; - red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize)); - int chan_cnt = ReadMacInt16(gamma_table + gChanCnt); - if (chan_cnt == 1) - green_gamma = blue_gamma = red_gamma; - else { - int ofs = ReadMacInt16(gamma_table + gDataCnt); - green_gamma = red_gamma + ofs; - blue_gamma = green_gamma + ofs; - } - gamma_data_width = ReadMacInt16(gamma_table + gDataWidth); - do_gamma = true; - } - } - - // Set palette - rgb_color *d_pal; - if (start == 0xffff) { // Indexed - for (int i=0; i<=count; i++) { - d_pal = mac_pal + (ReadMacInt16(s_pal + csValue) & 0xff); - uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8; - uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8; - uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8; - if (csSave->luminanceMapping) - red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; - if (do_gamma) { - red = red_gamma[red >> (8 - gamma_data_width)]; - green = green_gamma[green >> (8 - gamma_data_width)]; - blue = blue_gamma[blue >> (8 - gamma_data_width)]; - } - (*d_pal).red = red; - (*d_pal).green = green; - (*d_pal).blue = blue; - s_pal += 8; - } - } else { // Sequential - d_pal = mac_pal + start; - for (int i=0; i<=count; i++) { - uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8; - uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8; - uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8; - if (csSave->luminanceMapping) - red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; - if (do_gamma) { - red = red_gamma[red >> (8 - gamma_data_width)]; - green = green_gamma[green >> (8 - gamma_data_width)]; - blue = blue_gamma[blue >> (8 - gamma_data_width)]; - } - (*d_pal).red = red; - (*d_pal).green = green; - (*d_pal).blue = blue; - d_pal++; - s_pal += 8; - } - } - video_set_palette(); - return noErr; - } - - case cscSetGamma: { // SetGamma - uint32 user_table = ReadMacInt32(param + csGTable); - D(bug("SetGamma %08x\n", user_table)); - return set_gamma(csSave, user_table); - } - - case cscGrayPage: { // GrayPage - D(bug("GrayPage %d\n", ReadMacInt16(param + csPage))); - if (ReadMacInt16(param + csPage)) - return paramErr; - - uint32 pattern[6] = { - 0xaaaaaaaa, // 1 bpp - 0xcccccccc, // 2 bpp - 0xf0f0f0f0, // 4 bpp - 0xff00ff00, // 8 bpp - 0xffff0000, // 16 bpp - 0xffffffff // 32 bpp - }; - uint32 p = csSave->saveBaseAddr; - uint32 pat = pattern[VModes[cur_mode].viAppleMode - APPLE_1_BIT]; - bool invert = (VModes[cur_mode].viAppleMode == APPLE_32_BIT); - for (uint32 y=0; yluminanceMapping = ReadMacInt8(param); - return noErr; - - case cscSetInterrupt: // SetInterrupt - D(bug("SetInterrupt\n")); - csSave->interruptsEnabled = !ReadMacInt8(param); - return noErr; - - case cscDirectSetEntries: // DirectSetEntries - D(bug("DirectSetEntries\n")); - return controlErr; - - case cscSetDefaultMode: // SetDefaultMode - D(bug("SetDefaultMode\n")); - return controlErr; - - case cscSwitchMode: - D(bug("cscSwitchMode (Display Manager support) \nMode:%02x ID:%04x Page:%d\n", - ReadMacInt16(param + csMode), ReadMacInt32(param + csData), ReadMacInt16(param + csPage))); - return video_mode_change(csSave, param); - - case cscSavePreferredConfiguration: - D(bug("SavePreferredConfiguration\n")); - save_conf_id = ReadMacInt32(param + csData); - save_conf_mode = ReadMacInt16(param + csMode); - return noErr; - - case cscSetHardwareCursor: { -// D(bug("SetHardwareCursor\n")); - - if (!csSave->cursorHardware) - return controlErr; - - csSave->cursorSet = false; - bool changed = false; - - // Image - uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage - uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap); - if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0) - return controlErr; - uint32 pixmap = ReadMacInt32(pmhandle); - - // XXX: only certain image formats are handled properly at the moment - uint16 rowBytes = ReadMacInt16(pixmap + 4) & 0x7FFF; - if (rowBytes != 2) - return controlErr; - - // Mask - uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask); - if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0) - return controlErr; - uint32 bitmap = ReadMacInt32(bmhandle); - - // Get cursor data even on a screen, to set the right cursor image when switching back to a window. - // Hotspot is stale, but will be fixed by the next call to DrawHardwareCursor, which is likely to - // occur immediately hereafter. - - if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) { - memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32); - changed = true; - } - if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) { - memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32); - changed = true; - } - - // Set new cursor image - if (!video_can_change_cursor()) - return controlErr; - if (changed) - video_set_cursor(); - - csSave->cursorSet = true; - csSave->cursorHotFlag = true; - return noErr; - } - - case cscDrawHardwareCursor: { -// D(bug("DrawHardwareCursor\n")); - - if (!csSave->cursorHardware) - return controlErr; - - int32 oldX = csSave->cursorX; - int32 oldY = csSave->cursorY; - uint32 oldVisible = csSave->cursorVisible; - - csSave->cursorX = ReadMacInt32(param + csCursorX); - csSave->cursorY = ReadMacInt32(param + csCursorY); - csSave->cursorVisible = ReadMacInt32(param + csCursorVisible); - bool changed = (csSave->cursorVisible != oldVisible); - - // If this is the first DrawHardwareCursor call since the cursor was last set (via SetHardwareCursor), - // attempt to set an appropriate cursor hotspot. SetHardwareCursor itself does not know what the - // hotspot should be; it knows only the cursor image and mask. The hotspot is known only to the caller, - // and we have to try to infer it here. The usual sequence of calls when changing the cursor is: - // - // DrawHardwareCursor with (oldX, oldY, invisible) - // SetHardwareCursor with (cursor) - // DrawHardwareCursor with (newX, newY, visible) - // - // The key thing to note is that the sequence is intended not to change the current screen pixel location - // indicated by the hotspot. Thus, the difference between (newX, newY) and (oldX, oldY) reflects precisely - // the difference between the old cursor hotspot and the new one. For example, if you change from a - // cursor whose hotspot is (1, 1) to one whose hotspot is (7, 4), then you must adjust the cursor position - // by (-6, -3) in order for the same screen pixel to remain under the new hotspot. - // - // Alas, on rare occasions this heuristic can fail, and if you did nothing else you could even get stuck - // with the wrong hotspot from then on. To address that possibility, we force the hotspot to (1, 1) - // whenever the cursor being drawn is the standard arrow. Thus, while it is very unlikely that you will - // ever have the wrong hotspot, if you do, it is easy to recover. - - if (csSave->cursorHotFlag) { - csSave->cursorHotFlag = false; - D(bug("old hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY)); - - static uint8 arrow[] = { - 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, - 0x7F, 0x80, 0x7C, 0x00, 0x6C, 0x00, 0x46, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - }; - if (memcmp(MacCursor + 4, arrow, 32) == 0) { - csSave->cursorHotX = 1; - csSave->cursorHotY = 1; - } else if (csSave->cursorX != oldX || csSave->cursorY != oldY) { - int32 hotX = csSave->cursorHotX + (oldX - csSave->cursorX); - int32 hotY = csSave->cursorHotY + (oldY - csSave->cursorY); - - if (0 <= hotX && hotX <= 15 && 0 <= hotY && hotY <= 15) { - csSave->cursorHotX = hotX; - csSave->cursorHotY = hotY; - } - } - if (MacCursor[2] != csSave->cursorHotX || MacCursor[3] != csSave->cursorHotY) { - MacCursor[2] = csSave->cursorHotX; - MacCursor[3] = csSave->cursorHotY; - changed = true; - } - D(bug("new hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY)); - } - - if (changed && video_can_change_cursor()) - video_set_cursor(); - - return noErr; - } - - case 43: { // Driver Gestalt - uint32 sel = ReadMacInt32(pb + csParam); - D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel)); - switch (sel) { - case FOURCC('v','e','r','s'): - WriteMacInt32(pb + csParam + 4, 0x01008000); - break; - case FOURCC('i','n','t','f'): - WriteMacInt32(pb + csParam + 4, FOURCC('c','a','r','d')); - break; - case FOURCC('s','y','n','c'): - WriteMacInt32(pb + csParam + 4, 0x01000000); - break; - default: - return statusErr; - }; - return noErr; - } - - default: - D(bug(" unknown control code %d\n", code)); - return controlErr; - } -} - - -/* - * Video driver status routine - */ - -// Search for given AppleID in mode table -static bool has_mode(uint32 id) -{ - VideoInfo *p = VModes; - while (p->viType != DIS_INVALID) { - if (p->viAppleID == id) - return true; - p++; - } - return false; -} - -// Find maximum depth for given AppleID -static uint32 max_depth(uint32 id) -{ - uint32 max = APPLE_1_BIT; - VideoInfo *p = VModes; - while (p->viType != DIS_INVALID) { - if (p->viAppleID == id && p->viAppleMode > max) - max = p->viAppleMode; - p++; - } - return max; -} - -// Get X/Y size of specified resolution -static void get_size_of_resolution(int id, uint32 &x, uint32 &y) -{ - VideoInfo *p = VModes; - while (p->viType != DIS_INVALID) { - if (p->viAppleID == id) { - x = p->viXsize; - y = p->viYsize; - return; - } - p++; - } - x = y = 0; -} - -static int16 VideoStatus(uint32 pb, VidLocals *csSave) -{ - int16 code = ReadMacInt16(pb + csCode); - D(bug("VideoStatus %d: ", code)); - uint32 param = ReadMacInt32(pb + csParam); - switch (code) { - - case cscGetMode: // GetMode - D(bug("GetMode\n")); - WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr); - WriteMacInt16(param + csMode, csSave->saveMode); - WriteMacInt16(param + csPage, csSave->savePage); - D(bug("return: mode:%04x page:%04x ", ReadMacInt16(param + csMode), - ReadMacInt16(param + csPage))); - D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr))); - return noErr; - - case cscGetEntries: { // GetEntries - D(bug("GetEntries\n")); - uint32 d_pal = ReadMacInt32(param + csTable); - uint16 start = ReadMacInt16(param + csStart); - uint16 count = ReadMacInt16(param + csCount); - rgb_color *s_pal; - if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)|| - (VModes[cur_mode].viAppleMode == APPLE_16_BIT)) { - D(bug("ERROR: GetEntries in direct mode \n")); - return statusErr; - } - - if (start == 0xffff) { // Indexed - for (uint16 i=0;i 255) - return paramErr; - s_pal = mac_pal + start; - for (uint16 i=0;isaveBaseAddr); - return noErr; - - case cscGetGray: // GetGray - D(bug("GetGray\n")); - WriteMacInt8(param, csSave->luminanceMapping ? 1 : 0); - return noErr; - - case cscGetInterrupt: // GetInterrupt - D(bug("GetInterrupt\n")); - WriteMacInt8(param, csSave->interruptsEnabled ? 0 : 1); - return noErr; - - case cscGetGamma: // GetGamma - D(bug("GetGamma\n")); - WriteMacInt32(param, (uint32)csSave->gammaTable); - return noErr; - - case cscGetDefaultMode: // GetDefaultMode - D(bug("GetDefaultMode\n")); - return statusErr; - - case cscGetCurMode: // GetCurMode - D(bug("GetCurMode\n")); - WriteMacInt16(param + csMode, csSave->saveMode); - WriteMacInt32(param + csData, csSave->saveData); - WriteMacInt16(param + csPage, csSave->savePage); - WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr); - - D(bug("return: mode:%04x ID:%08lx page:%04x ", ReadMacInt16(param + csMode), - ReadMacInt32(param + csData), ReadMacInt16(param + csPage))); - D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr))); - return noErr; - - case cscGetConnection: // GetConnection - D(bug("GetConnection\n")); - WriteMacInt16(param + csDisplayType, kMultiModeCRT3Connect); - WriteMacInt8(param + csConnectTaggedType, 6); - WriteMacInt8(param + csConnectTaggedData, 0x23); - WriteMacInt32(param + csConnectFlags, (1<saveData; - break; - case kDisplayModeIDFindFirstResolution: - work_id = APPLE_ID_MIN; - while (!has_mode(work_id)) - work_id ++; - break; - default: - if (!has_mode(work_id)) - return paramErr; - work_id++; - while (!has_mode(work_id)) { - work_id++; - if (work_id > APPLE_ID_MAX) { - WriteMacInt32(param + csRIDisplayModeID, kDisplayModeIDNoMoreResolutions); - return noErr; - } - } - break; - } - WriteMacInt32(param + csRIDisplayModeID, work_id); - WriteMacInt16(param + csMaxDepthMode, max_depth(work_id)); - switch (work_id) { - case APPLE_640x480: - WriteMacInt32(param + csHorizontalPixels, 640); - WriteMacInt32(param + csVerticalLines, 480); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_W_640x480: - WriteMacInt32(param + csHorizontalPixels, 640); - WriteMacInt32(param + csVerticalLines, 480); - WriteMacInt32(param + csRefreshRate, 60<<16); - break; - case APPLE_800x600: - WriteMacInt32(param + csHorizontalPixels, 800); - WriteMacInt32(param + csVerticalLines, 600); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_W_800x600: - WriteMacInt32(param + csHorizontalPixels, 800); - WriteMacInt32(param + csVerticalLines, 600); - WriteMacInt32(param + csRefreshRate, 60<<16); - break; - case APPLE_1024x768: - WriteMacInt32(param + csHorizontalPixels, 1024); - WriteMacInt32(param + csVerticalLines, 768); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_1152x768: - WriteMacInt32(param + csHorizontalPixels, 1152); - WriteMacInt32(param + csVerticalLines, 768); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_1152x900: - WriteMacInt32(param + csHorizontalPixels, 1152); - WriteMacInt32(param + csVerticalLines, 900); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_1280x1024: - WriteMacInt32(param + csHorizontalPixels, 1280); - WriteMacInt32(param + csVerticalLines, 1024); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_1600x1200: - WriteMacInt32(param + csHorizontalPixels, 1600); - WriteMacInt32(param + csVerticalLines, 1200); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - case APPLE_CUSTOM: { - uint32 x, y; - get_size_of_resolution(work_id, x, y); - WriteMacInt32(param + csHorizontalPixels, x); - WriteMacInt32(param + csVerticalLines, y); - WriteMacInt32(param + csRefreshRate, 75<<16); - break; - } - } - return noErr; - } - - case cscGetVideoParameters: // GetVideoParameters - D(bug("GetVideoParameters ID:%08lx Depth:%04x\n", - ReadMacInt32(param + csDisplayModeID), - ReadMacInt16(param + csDepthMode))); - - // find right video mode - for (int i=0; VModes[i].viType!=DIS_INVALID; i++) { - if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) && - (ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) { - uint32 vpb = ReadMacInt32(param + csVPBlockPtr); - WriteMacInt32(vpb + vpBaseOffset, 0); - WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes); - WriteMacInt16(vpb + vpBounds, 0); - WriteMacInt16(vpb + vpBounds + 2, 0); - WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize); - WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize); - WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number - WriteMacInt16(vpb + vpPackType, 0); - WriteMacInt32(vpb + vpPackSize, 0); - WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi) - WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi) - switch (VModes[i].viAppleMode) { - case APPLE_1_BIT: - WriteMacInt16(vpb + vpPixelType, 0); - WriteMacInt16(vpb + vpPixelSize, 1); - WriteMacInt16(vpb + vpCmpCount, 1); - WriteMacInt16(vpb + vpCmpSize, 1); - WriteMacInt32(param + csDeviceType, 0); // CLUT - break; - case APPLE_2_BIT: - WriteMacInt16(vpb + vpPixelType, 0); - WriteMacInt16(vpb + vpPixelSize, 2); - WriteMacInt16(vpb + vpCmpCount, 1); - WriteMacInt16(vpb + vpCmpSize, 2); - WriteMacInt32(param + csDeviceType, 0); // CLUT - break; - case APPLE_4_BIT: - WriteMacInt16(vpb + vpPixelType, 0); - WriteMacInt16(vpb + vpPixelSize, 4); - WriteMacInt16(vpb + vpCmpCount, 1); - WriteMacInt16(vpb + vpCmpSize, 4); - WriteMacInt32(param + csDeviceType, 0); // CLUT - break; - case APPLE_8_BIT: - WriteMacInt16(vpb + vpPixelType, 0); - WriteMacInt16(vpb + vpPixelSize, 8); - WriteMacInt16(vpb + vpCmpCount, 1); - WriteMacInt16(vpb + vpCmpSize, 8); - WriteMacInt32(param + csDeviceType, 0); // CLUT - break; - case APPLE_16_BIT: - WriteMacInt16(vpb + vpPixelType, 0x10); - WriteMacInt16(vpb + vpPixelSize, 16); - WriteMacInt16(vpb + vpCmpCount, 3); - WriteMacInt16(vpb + vpCmpSize, 5); - WriteMacInt32(param + csDeviceType, 2); // DIRECT - break; - case APPLE_32_BIT: - WriteMacInt16(vpb + vpPixelType, 0x10); - WriteMacInt16(vpb + vpPixelSize, 32); - WriteMacInt16(vpb + vpCmpCount, 3); - WriteMacInt16(vpb + vpCmpSize, 8); - WriteMacInt32(param + csDeviceType, 2); // DIRECT - break; - } - WriteMacInt32(param + csPageCount, 1); - return noErr; - } - } - return paramErr; - - case cscGetModeTiming: - D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode))); - WriteMacInt32(param + csTimingFormat, kDeclROMtables); - WriteMacInt32(param + csTimingFlags, (1<cursorHardware); - return noErr; - - case cscGetHardwareCursorDrawState: - D(bug("GetHardwareCursorDrawState\n")); - - if (!csSave->cursorHardware) - return statusErr; - - WriteMacInt32(param + csCursorX, csSave->cursorX); - WriteMacInt32(param + csCursorY, csSave->cursorY); - WriteMacInt32(param + csCursorVisible, csSave->cursorVisible); - WriteMacInt32(param + csCursorSet, csSave->cursorSet); - return noErr; - - default: - D(bug(" unknown status code %d\n", code)); - return statusErr; - } -} - - -/* - * Video driver close routine - */ - -static int16 VideoClose(uint32 pb, VidLocals *csSave) -{ - D(bug("VideoClose\n")); - - // Delete interrupt service - csSave->interruptsEnabled = false; - VSLDisposeInterruptService(csSave->vslServiceID); - - return noErr; -} - - -/* - * Native (PCI) driver entry - */ - -int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, uint32 commandCode, uint32 commandKind) -{ -// D(bug("VideoDoDriverIO space %08x, command %08x, contents %08x, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind)); - int16 err = noErr; - - switch (commandCode) { - case kInitializeCommand: - case kReplaceCommand: - if (private_data != NULL) { // Might be left over from a reboot - if (private_data->gammaTable) - Mac_sysfree(private_data->gammaTable); - if (private_data->regEntryID) - Mac_sysfree(private_data->regEntryID); - } - delete private_data; - - iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete"); - D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect)); - if (iocic_tvect == 0) { - printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n"); - err = -1; - break; - } - vslnewis_tvect = FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService"); - D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect)); - if (vslnewis_tvect == 0) { - printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n"); - err = -1; - break; - } - vsldisposeis_tvect = FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService"); - D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect)); - if (vsldisposeis_tvect == 0) { - printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n"); - err = -1; - break; - } - vsldois_tvect = FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService"); - D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect)); - if (vsldois_tvect == 0) { - printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n"); - err = -1; - break; - } - nqdmisc_tvect = FindLibSymbol("\014InterfaceLib", "\007NQDMisc"); - D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect)); - if (nqdmisc_tvect == 0) { - printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n"); - err = -1; - break; - } - - private_data = new VidLocals; - private_data->gammaTable = 0; - private_data->regEntryID = Mac_sysalloc(sizeof(RegEntryID)); - if (private_data->regEntryID == 0) { - printf("FATAL: VideoDoDriverIO(): Can't allocate service owner\n"); - err = -1; - break; - } - Mac2Mac_memcpy(private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry - private_data->interruptsEnabled = false; // Disable interrupts - break; - - case kFinalizeCommand: - case kSupersededCommand: - if (private_data != NULL) { - if (private_data->gammaTable) - Mac_sysfree(private_data->gammaTable); - if (private_data->regEntryID) - Mac_sysfree(private_data->regEntryID); - } - delete private_data; - private_data = NULL; - break; - - case kOpenCommand: - err = VideoOpen(commandContents, private_data); - break; - - case kCloseCommand: - err = VideoClose(commandContents, private_data); - break; - - case kControlCommand: - err = VideoControl(commandContents, private_data); - break; - - case kStatusCommand: - err = VideoStatus(commandContents, private_data); - break; - - case kReadCommand: - case kWriteCommand: - break; - - case kKillIOCommand: - err = abortErr; - break; - - default: - err = paramErr; - break; - } - - if (commandKind == kImmediateIOCommandKind) - return err; - else - return IOCommandIsComplete(commandID, err); -} diff --git a/SheepShaver/src/xpram.cpp b/SheepShaver/src/xpram.cpp deleted file mode 120000 index 17fe090f..00000000 --- a/SheepShaver/src/xpram.cpp +++ /dev/null @@ -1 +0,0 @@ -../../BasiliskII/src/xpram.cpp \ No newline at end of file diff --git a/cxmon/.gitignore b/cxmon/.gitignore deleted file mode 100644 index ab09b307..00000000 --- a/cxmon/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# Object files -*.o - -# Executables and libraries -src/cxmon -src/disass/libdisass.a - -# Autoconf generated files -.deps -Makefile -Makefile.in -aclocal.m4 -autom4te.cache -compile -config.guess -config.h -config.h.in -config.log -config.status -config.sub -configure -cxmon.spec -depcomp -install-sh -missing -stamp-h1 diff --git a/cxmon/AUTHORS b/cxmon/AUTHORS deleted file mode 100644 index ffbd0fa0..00000000 --- a/cxmon/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -'mon' was written by - Christian Bauer - Marc Hellwig - -with contributions from - Gwenolé Beauchesne (64-bit support and PPC extensions) - -The 680x0 and 80x86 disassemblers are taken from GNU binutils. diff --git a/cxmon/COPYING b/cxmon/COPYING deleted file mode 100644 index 60549be5..00000000 --- a/cxmon/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. 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. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/cxmon/ChangeLog b/cxmon/ChangeLog deleted file mode 100644 index df26a0ef..00000000 --- a/cxmon/ChangeLog +++ /dev/null @@ -1,20 +0,0 @@ -V3.2 - 64-bit fixes to 680x0 disassembler, added AltiVec instructions to PPC - disassembler, fixes to Z80 disassembler (hl->ix/iy and relative jumps) -V3.1 - Make LowMem globals as predefined variables, fix 64-bit support, enable - x86-64 disassembler with "d8664" command, removed input line length - restrictions -V3.0 - Replaced 680x0 and 80x86 disassemblers with the ones from GNU binutils, - added symbolic display of MacOS low memory globals to PPC disassembler, - MacOS features in PPC disassembler are controlled by "-m" argument, - real memory mode is entered by "-r" argument, extended 8080 disassembler - to Z80, name changed from "mon" to "cxmon" -V2.2 - Switched to autoconf/automake, fixed some minor bugs in the PPC - disassembler, commands made modular, added binary dump (b) command -V2.1 - Compiled for BeOS R4, opens Terminal window when started from Tracker, - implemented 8080 disassembler, included Unix makefile -V2.0 - Unified PPC and x86 release -V1.5 - Non-interactive mode, real mode -V1.4 - Implemented 6502 and 680x0 disassemblers -V1.3 - Now uses libreadline - Disassembler: prints SPR names instead of numbers, fixed bugs -V1.0 - Initial release diff --git a/cxmon/INSTALL b/cxmon/INSTALL deleted file mode 100644 index b42a17ac..00000000 --- a/cxmon/INSTALL +++ /dev/null @@ -1,182 +0,0 @@ -Basic Installation -================== - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. - - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. You can give `configure' -initial values for variables by setting them in the environment. Using -a Bourne-compatible shell, you can do that on the command line like -this: - CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure - -Or on systems that have the `env' program, you can do it like this: - env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: - CPU-COMPANY-SYSTEM - -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. - - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Operation Controls -================== - - `configure' recognizes the following options to control how it -operates. - -`--cache-file=FILE' - Use and save the results of the tests in FILE instead of - `./config.cache'. Set FILE to `/dev/null' to disable caching, for - debugging `configure'. - -`--help' - Print a summary of the options to `configure', and exit. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--version' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`configure' also accepts some other, not widely useful, options. diff --git a/cxmon/Makefile.am b/cxmon/Makefile.am deleted file mode 100644 index 4e8b8b26..00000000 --- a/cxmon/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -## Process this file with automake to produce Makefile.in -SUBDIRS = src - -# Manpages -man_MANS = cxmon.1 - -EXTRA_DIST = cxmon.1 bootstrap - -dist-hook: cxmon.spec - cp cxmon.spec $(distdir) - -# Rule to build tar-gzipped distribution package -$(PACKAGE)-$(VERSION).tar.gz: dist - -# Rule to build RPM distribution package -rpm: $(PACKAGE)-$(VERSION).tar.gz - rpm -ta --clean $(PACKAGE)-$(VERSION).tar.gz diff --git a/cxmon/README b/cxmon/README deleted file mode 100644 index 44ab37f6..00000000 --- a/cxmon/README +++ /dev/null @@ -1,437 +0,0 @@ - - cxmon, Version 3.2 - A command-line file manipulation tool and disassembler - - Copyright (C) 1997-2007 Christian Bauer, Marc Hellwig - GNU binutils disassemblers Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. - - -License -------- - -cxmon is available under the terms of the GNU General Public License. See the -file "COPYING" that is included in the distribution for details. - - -Overview --------- - -cxmon is an interactive command-driven file manipulation tool that is -inspired by the "Amiga Monitor" by Timo Rossi. It has commands and features -similar to a machine code monitor/debugger, but it lacks any functions for -running/tracing code. There are, however, built-in PowerPC, 680x0, 80x86, -x86-64, 6502 and Z80 disassemblers and special support for disassembling -MacOS code. By default, cxmon operates on a fixed-size (but adjustable) -memory buffer with adresses starting at 0. - - -Installation ------------- - -Please consult the file "INSTALL" for installation instructions. - - -Usage ------ - -cxmon can be started from the Shell or from the Tracker (BeOS), but command -line history doesn't work when started from the Tracker. - -Options: - -m enables symbolic MacOS A-Trap and low memory globals display in the - 680x0 disassembler - -r makes cxmon operate in real (virtual) memory space instead of an - allocated buffer - -If no additional command line arguments are given, cxmon enters interactive -mode. Otherwise, all remaining arguments are interpreted and executed as cxmon -commands. - -The default buffer size is 1MB. - -The cxmon command prompt looks like this: - - [00000000]-> - -The number in brackets is the value of "." (the "current address", see the -section on expressions). You can get a short command overview by entering -"h". - -Commands that create a longer output can be interrupted with Ctrl-C. - -To quit cxmon, enter the command "x". - - -Constants, variables and expressions ------------------------------------- - -The default number base is hexadecimal. Decimal numbers must be prefixed with -"_". Hexadecimal numbers may also be prefixed with "$" for clarity. Numbers -can also be entered as ASCII characters enclosed in single quotes (e.g. 'BAPP' -is the same as $42415050). All numbers are 32-bit values (one word). - -With the "set" command, variables can be defined that hold 32-bit integer -values. A variable is referred to by its name. Variable names may be arbitrary -combinations of digits and letters (they may also start with a digit) that -are not also valid hexadecimal numbers. Names are case-sensitive. - -cxmon accepts expressions in all places where you have to specify a number. -The following operators are available and have the same meaning and -precedence as in the C programming language: - - ~ complement - + unary plus - - unary minus - * multiplication - / integer division - % modulo - + addition - - subtraction - << shift left - >> shift right - & bitwise AND - ^ bitwise exclusive OR - | bitwise inclusive OR - -Parentheses may be used to change the evaluation order of sub-expressions. - -There are two special symbols that can be used in expressions: - - . represents the "current address" (the value of "." is also displayed in - the command prompt). What exactly the current address is, depends on the - command last executed. The display commands set "." to the address after - the last address displayed, the "hunt" commands sets "." to the address - of the first found occurence of the search string, etc. - : is used by the "apply" ("y") command and holds the value of the byte/ - half-word/word at the current address. - -The "modify" (":"), "fill" ("f") and "hunt" ("h") commands require you to -specify a byte string. Byte strings consist of an arbitrary number of byte -values and ASCII strings separated by commas. Examples: - - "string" - 12,34,56,78,9a,bc,de,f0 - "this",0a,"is a string",0a,"with","newlines",_10 - - -The buffer ----------- - -Those cxmon commands that operate on "memory" operate on a buffer allocated -by cxmon whose size is adjustable with the "@" command. The default buffer -size is 1MB. The buffer is an array of bytes where each byte has a 32-bit -integer address. Addresses start at 0 and are taken modulo the buffer size -(i.e. for the default 1MB buffer, addresses 0 and 100000 refer to the same -byte). - -The buffer is the working area of cxmon where you load files into, manipulate -them, and write files back from. Arbitraty portions of the buffer may be used -as scratch space. - - -Commands --------- - -The following commands are available in cxmon ('[]' marks a parameter than -can be left out): - - - x Quit cxmon - -quits cxmon and returns to the shell. - - - h Show help text - -displays a short overview of commands. - - - ?? Show list of commands - -displays a short list of available commands. - - - ver Show version - -shows the version number of cxmon. - - - ? expression Calculate expression - -displays the value of the given expression in hex, decimal, and ASCII -characters. If the value is negative, it is displayed as a signed and unsigned -number. - - - @ [size] Reallocate buffer - -changes the size of the buffer to the given number of bytes while preserving -the contents of the buffer. If the "size" argument is omitted, the current -buffer size is displayed. - - - i [start [end]] ASCII memory dump - -displays the buffer contents from address "start" to address "end" as ASCII -characters. Entering "i" without arguments is equivalent to "i .". The value -of "." is set to the address after the last address displayed. - - - b [start [end]] Binary memory dump - -displays the buffer contents from address "start" to address "end" in a binary -format. Entering "b" without arguments is equivalent to "b .". The value of -"." is set to the address after the last address displayed. - - - m [start [end]] Hex/ASCII memory dump - -displays the buffer contents from address "start" to address "end" as hex -words and ASCII characters. Entering "m" without arguments is equivalent to -"m .". The value of "." is set to the address after the last address displayed. - - - d [start [end]] Disassemble PowerPC code - -disassembles the buffer contents from address "start" to address "end". -Entering "d" without arguments is equivalent to "d .". The value of "." is -set to the address after the last address displayed. - - - d65 [start [end]] Disassemble 6502 code - -disassembles the buffer contents from address "start" to address "end". -Entering "d65" without arguments is equivalent to "d65 .". The value of -"." is set to the address after the last address displayed. - - - d68 [start [end]] Disassemble 680x0 code - -disassembles the buffer contents from address "start" to address "end". -Entering "d68" without arguments is equivalent to "d68 .". The value of -"." is set to the address after the last address displayed. - - - d80 [start [end]] Disassemble Z80 code - -disassembles the buffer contents from address "start" to address "end". -Entering "d80" without arguments is equivalent to "d80 .". The value of -"." is set to the address after the last address displayed. - - - d86 [start [end]] Disassemble 80x86 (32-bit) code - -disassembles the buffer contents from address "start" to address "end". -Entering "d86" without arguments is equivalent to "d86 .". The value of -"." is set to the address after the last address displayed. - - - d8086 [start [end]] Disassemble 80x86 (16-bit) code - -disassembles the buffer contents from address "start" to address "end". -Entering "d8086" without arguments is equivalent to "d8086 .". The value -of "." is set to the address after the last address displayed. - - - d8664 [start [end]] Disassemble x86-64 code - -disassembles the buffer contents from address "start" to address "end". -Entering "d8086" without arguments is equivalent to "d8086 .". The value -of "." is set to the address after the last address displayed. - - - : start string Modify memory - -puts the specified byte string at the address "start" into the buffer. The -value of "." is set to the address after the last address modified. - - - f start end string Fill memory - -fill the buffer in the range from "start" to (and including) "end" with the -given byte string. - - - y[b|h|w] start end expr Apply expression to memory - -works like the "fill" ("f") command, but it doesn't fill with a byte string -but with the value of an expression that is re-evaluated for each buffer -location to be filled. The command comes in three flavors: "y"/"yb" works on -bytes (8-bit), "yh" on half-words (16-bit) and "yw" on words (32-bit). The -value of "." is the current address to be modified, the value of ":" holds -the contents of this address before modification. - -Examples: - yw 0 fff :<<8 shifts all words in the address range 0..fff to the left - by 8 bits (you can use this to convert bitmap data from - ARGB to RGBA format, for example) - y 0 1234 ~: inverts all bytes in the address range 0..1234 - yh 2 ff 20000/. creates a table of the fractional parts of the reciprocals - of 1..7f - - - t start end dest Transfer memory - -transfers the buffer contents from "start" to (and including) "end" to "dest". -Source and destination may overlap. - - - c start end dest Compare memory - -compares the buffer contents in the range from "start" to (and including) -"end" with the contents at "dest". The addresses of all different bytes and -the total number of differences (decimal) are printed. - - - h start end string Search for byte string - -searches for the given byte string in the buffer starting at "start" up to -(and including) "end". The addresses and the total number of occurrences are -displayed. The value of "." is set to the address of the first occurrence. - - - \ "command" Execute shell command - -executes the given shell command which must be enclosed in quotes. - - - ls [args] List directory contents - -works as the shell command "ls". - - - rm [args] Remove file(s) - -works as the shell command "rm". - - - cp [args] Copy file(s) - -works as the shell command "cp". - - - mv [args] Move file(s) - -works as the shell command "mv". - - - cd directory Change current directory - -works as the shell command "cd". The name of the directory doesn't have to be -enclosed in quotes. - - - o ["file"] Redirect output - -When a file name is specified, all following output is redirected to this -file. The file name must be enclosed in quotation marks even if it contains -no spaces. Entering "o" without parameters closes the file and directs the -output into the terminal window again. - - - [ start "file" Load data from file - -loads the contents of the specified file into the buffer starting from address -"start". The file name must be enclosed in quotation marks even if it contains -no spaces. The value of "." is set to the address after the last address -affected by the load. - - - ] start size "file" Save data to file - -writes "size" number of bytes of the buffer from "start" to the specified file. -The file name must be enclosed in quotation marks even if it contains no spaces. - - - set [var[=value]] Set/clear/show variables - -If no arguments are given, all currently defined variables are displayed. -Otherwise, the value of "var" is set to the specified value. If "=value" -is omitted, the variable "var" is cleared. - - - cv Clear all variables - -clears all currently defined variables. - - -Examples --------- - -Here are some simple examples for what is possible with cxmon. - -Join "file1" and "file2" to "file3": - - [ 0 "file1" - [ . "file2" - ] 0 . "file3" - -Remove the first 24 bytes (e.g. an unneeded header) of a file: - - [ 0 "file" - ] 18 .-18 "file" - -Load the cxmon executable and search for PowerPC "nop" commands: - - [ 0 "cxmon" - h 0 . 60,00,00,00 - -Create a modified version of cxmon so that the prompt has " $" instead of -"->": - - [ 0 "cxmon" - set size=. - h 0 . "->" - : . " $" - ] 0 size "cxmon1" - -Convert a binary file which contains 16-bit numbers in little-endian format -to big-endian format (or vice-versa): - - [ 0 "file" - yh 0 .-1 :>>8|:<<8 - ] 0 . "file" - -Load a BeBox boot ROM image and start disassembling the system reset handler: - - [ 0 "bootnub.image" - d 100 - - -Using cxmon in your own programs --------------------------------- - -cxmon provides a simple interface for integration in other programs. It can, -for example, be used as a monitor/debugger for an emulator (it is used in -Basilisk II in this way). - -Here's how to do it (all functions are defined in the mon.h header file): - - 1. Link all the cxmon object files, except main.o, to your program. - 2. In your program, call mon_init() before using any other cxmon functions. - 3. After calling mon_init(), set the mon_read_byte and mon_write_byte - function pointers to the routines used for accessing memory. - 4. You can use mon_add_command() to add new commands to cxmon by specifying - the command name, function and help text. From within your command - function, you can use mon_get_token() and mon_expression() to parse the - arguments and the mon_read/write_*() functions to access memory. - 5. To enter cxmon, call the mon() function like this: - - char *args[3] = {"mon", "-r", NULL}; - mon(2, args); - - 6. If you're done with cxmon, call mon_exit(). - - -History -------- - -Please consult the file "ChangeLog" for the release history. - - -Christian Bauer -www.cebix.net - -Marc Hellwig - diff --git a/cxmon/bootstrap b/cxmon/bootstrap deleted file mode 100755 index 0fb6c4f8..00000000 --- a/cxmon/bootstrap +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -autoreconf --install diff --git a/cxmon/configure.ac b/cxmon/configure.ac deleted file mode 100644 index f93e6c85..00000000 --- a/cxmon/configure.ac +++ /dev/null @@ -1,47 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -dnl Written by Christian Bauer - -AC_PREREQ(2.69) -AC_INIT([cxmon], [3.2], [cb@cebix.net], [cxmon]) -AC_CONFIG_SRCDIR([src/mon.cpp]) -AM_INIT_AUTOMAKE([1.12 foreign]) - -AM_CONFIG_HEADER(config.h) - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_CXXCPP -AC_PROG_INSTALL -AC_PROG_RANLIB - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(unistd.h readline.h history.h readline/readline.h readline/history.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_CHECK_SIZEOF(short, 2) -AC_CHECK_SIZEOF(int, 4) -AC_CHECK_SIZEOF(long, 4) -AC_CHECK_SIZEOF(long long, 8) -AC_CHECK_SIZEOF(void *, 4) - -dnl Checks for libraries. -AC_SEARCH_LIBS([tgetent], [ncurses termcap termlib terminfo Hcurses curses], [], [ - AC_MSG_ERROR([unable to find the tgetent() function]) -]) -AC_SEARCH_LIBS([readline], [readline], [], [ - AC_MSG_ERROR([unable to find the readline() function]) -]) - -dnl Generate Makefile. -AC_OUTPUT([ -Makefile -cxmon.spec -src/Makefile -src/disass/Makefile -]) - -dnl Print summary. -echo "Configuration done. Now type \"make\"." diff --git a/cxmon/cxmon.1 b/cxmon/cxmon.1 deleted file mode 100644 index 7e0ef360..00000000 --- a/cxmon/cxmon.1 +++ /dev/null @@ -1,56 +0,0 @@ -.TH cxmon 1 "January, 2007" -.SH NAME -cxmon \- a command-line file manipulation tool and disassembler -.SH SYNOPSIS -.B cxmon -[\-m] [\-r] -.RI [ commands\&... ] -.SH DESCRIPTION -.B cxmon -is an interactive command-driven file manipulation tool that is inspired by -the "Amiga Monitor" by Timo Rossi. It has commands and features similar to a -machine code monitor/debugger, but it lacks any functions for running/tracing -code. There are, however, built-in PowerPC, 680x0, 80x86, 6502 and Z80 -disassemblers and special support for disassembling MacOS code. By default, -cxmon operates on a fixed-size (but adjustable) memory buffer with adresses -starting at 0. -.PP -Type "h" to get a list of supported commands. -.PP -For more information, see the included "README" file. -.SH OPTIONS -.TP -.B \-m -enables symbolic MacOS A-Trap and low memory globals display in the 680x0 -disassembler -.TP -.B \-r -makes cxmon operate in real (virtual) memory space instead of an allocated -buffer -.PP -If no additional command line arguments are given, cxmon enters interactive -mode. Otherwise, all remaining arguments are interpreted and executed as cxmon -commands. -.SH AUTHORS -Christian Bauer -.br -Marc Hellwig -.SH COPYRIGHT -Copyright \(co 1997-2007 Christian Bauer, Marc Hellwig -.br -GNU binutils disassemblers Copyright \(co 1988, 89, 91, 93, 94, 95, 96, 97, 1998 -Free Software Foundation, Inc. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. diff --git a/cxmon/cxmon.spec.in b/cxmon/cxmon.spec.in deleted file mode 100644 index 6b1cfd33..00000000 --- a/cxmon/cxmon.spec.in +++ /dev/null @@ -1,42 +0,0 @@ -%define name @PACKAGE@ -%define version @VERSION@ -%define release 1 - -Summary: Command-line file manipulation tool and disassembler -Name: %{name} -Version: %{version} -Release: %{release} -License: GPL -Group: Utilities/File -Source0: %{name}-%{version}.tar.gz -URL: http://cxmon.cebix.net/ -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -Prefix: %{_prefix} - -%description -cxmon is an interactive command-driven file manipulation tool that is -inspired by the "Amiga Monitor" by Timo Rossi. It has commands and features -similar to a machine code monitor/debugger, but it lacks any functions for -running/tracing code. There are, however, built-in PowerPC, 680x0, 80x86, -x86-64, 6502 and Z80 disassemblers and special support for disassembling -MacOS code. - -%prep -%setup -q - -%build -%configure -make - -%install -rm -rf ${RPM_BUILD_ROOT} -%makeinstall - -%clean -rm -rf ${RPM_BUILD_ROOT} - -%files -%defattr(-,root,root) -%doc AUTHORS ChangeLog COPYING README -%{_bindir}/* -%{_mandir}/man1/* diff --git a/cxmon/src/Makefile.am b/cxmon/src/Makefile.am deleted file mode 100644 index 0b865b2d..00000000 --- a/cxmon/src/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -## Process this file with automake to produce Makefile.in - -SUBDIRS = disass - -bin_PROGRAMS = cxmon -cxmon_SOURCES = main.cpp mon.cpp mon.h mon_6502.cpp mon_z80.cpp mon_atraps.h \ - mon_cmd.cpp mon_cmd.h mon_disass.cpp mon_disass.h mon_lowmem.cpp mon_lowmem.h \ - mon_ppc.cpp sysdeps.h - -cxmon_LDADD = disass/libdisass.a diff --git a/cxmon/src/disass/Makefile.am b/cxmon/src/disass/Makefile.am deleted file mode 100644 index 80a908fb..00000000 --- a/cxmon/src/disass/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -## Process this file with automake to produce Makefile.in - -noinst_LIBRARIES = libdisass.a -libdisass_a_SOURCES = ansidecl.h bfd.h dis-asm.h floatformat.c floatformat.h \ - i386-dis.c m68k-dis.c m68k-opc.c m68k.h opintl.h - -# Extra includes, for -CPPFLAGS = -I$(srcdir)/.. diff --git a/cxmon/src/disass/ansidecl.h b/cxmon/src/disass/ansidecl.h deleted file mode 100644 index 9a7c5777..00000000 --- a/cxmon/src/disass/ansidecl.h +++ /dev/null @@ -1,295 +0,0 @@ -/* ANSI and traditional C compatability macros - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* ANSI and traditional C compatibility macros - - ANSI C is assumed if __STDC__ is #defined. - - Macro ANSI C definition Traditional C definition - ----- ---- - ---------- ----------- - ---------- - ANSI_PROTOTYPES 1 not defined - PTR `void *' `char *' - PTRCONST `void *const' `char *' - LONG_DOUBLE `long double' `double' - const not defined `' - volatile not defined `' - signed not defined `' - VA_START(ap, var) va_start(ap, var) va_start(ap) - - Note that it is safe to write "void foo();" indicating a function - with no return value, in all K+R compilers we have been able to test. - - For declaring functions with prototypes, we also provide these: - - PARAMS ((prototype)) - -- for functions which take a fixed number of arguments. Use this - when declaring the function. When defining the function, write a - K+R style argument list. For example: - - char *strcpy PARAMS ((char *dest, char *source)); - ... - char * - strcpy (dest, source) - char *dest; - char *source; - { ... } - - - VPARAMS ((prototype, ...)) - -- for functions which take a variable number of arguments. Use - PARAMS to declare the function, VPARAMS to define it. For example: - - int printf PARAMS ((const char *format, ...)); - ... - int - printf VPARAMS ((const char *format, ...)) - { - ... - } - - For writing functions which take variable numbers of arguments, we - also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros. These - hide the differences between K+R and C89 more - thoroughly than the simple VA_START() macro mentioned above. - - VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end. - Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls - corresponding to the list of fixed arguments. Then use va_arg - normally to get the variable arguments, or pass your va_list object - around. You do not declare the va_list yourself; VA_OPEN does it - for you. - - Here is a complete example: - - int - printf VPARAMS ((const char *format, ...)) - { - int result; - - VA_OPEN (ap, format); - VA_FIXEDARG (ap, const char *, format); - - result = vfprintf (stdout, format, ap); - VA_CLOSE (ap); - - return result; - } - - - You can declare variables either before or after the VA_OPEN, - VA_FIXEDARG sequence. Also, VA_OPEN and VA_CLOSE are the beginning - and end of a block. They must appear at the same nesting level, - and any variables declared after VA_OPEN go out of scope at - VA_CLOSE. Unfortunately, with a K+R compiler, that includes the - argument list. You can have multiple instances of VA_OPEN/VA_CLOSE - pairs in a single function in case you need to traverse the - argument list more than once. - - For ease of writing code which uses GCC extensions but needs to be - portable to other compilers, we provide the GCC_VERSION macro that - simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various - wrappers around __attribute__. Also, __extension__ will be #defined - to nothing if it doesn't work. See below. - - This header also defines a lot of obsolete macros: - CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID, - AND, DOTS, NOARGS. Don't use them. */ - -#ifndef _ANSIDECL_H -#define _ANSIDECL_H 1 - -/* Every source file includes this file, - so they will all get the switch for lint. */ -/* LINTLIBRARY */ - -/* Using MACRO(x,y) in cpp #if conditionals does not work with some - older preprocessors. Thus we can't define something like this: - -#define HAVE_GCC_VERSION(MAJOR, MINOR) \ - (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR))) - -and then test "#if HAVE_GCC_VERSION(2,7)". - -So instead we use the macro below and test it against specific values. */ - -/* This macro simplifies testing whether we are using gcc, and if it - is of a particular minimum version. (Both major & minor numbers are - significant.) This macro will evaluate to 0 if we are not using - gcc at all. */ -#ifndef GCC_VERSION -#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) -#endif /* GCC_VERSION */ - -#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) -/* All known AIX compilers implement these things (but don't always - define __STDC__). The RISC/OS MIPS compiler defines these things - in SVR4 mode, but does not define __STDC__. */ - -#define ANSI_PROTOTYPES 1 -#define PTR void * -#define PTRCONST void *const -#define LONG_DOUBLE long double - -#define PARAMS(ARGS) ARGS -#define VPARAMS(ARGS) ARGS -#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR) - -/* variadic function helper macros */ -/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's - use without inhibiting further decls and without declaring an - actual variable. */ -#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP, VAR); { struct Qdmy -#define VA_CLOSE(AP) } va_end(AP); } -#define VA_FIXEDARG(AP, T, N) struct Qdmy - -#undef const -#undef volatile -#undef signed - -/* inline requires special treatment; it's in C99, and GCC >=2.7 supports - it too, but it's not in C89. */ -#undef inline -#if __STDC_VERSION__ > 199901L -/* it's a keyword */ -#else -# if GCC_VERSION >= 2007 -# define inline __inline__ /* __inline__ prevents -pedantic warnings */ -# else -# define inline /* nothing */ -# endif -#endif - -/* These are obsolete. Do not use. */ -#ifndef IN_GCC -#define CONST const -#define VOLATILE volatile -#define SIGNED signed - -#define PROTO(type, name, arglist) type name arglist -#define EXFUN(name, proto) name proto -#define DEFUN(name, arglist, args) name(args) -#define DEFUN_VOID(name) name(void) -#define AND , -#define DOTS , ... -#define NOARGS void -#endif /* ! IN_GCC */ - -#else /* Not ANSI C. */ - -#undef ANSI_PROTOTYPES -#define PTR char * -#define PTRCONST PTR -#define LONG_DOUBLE double - -#define PARAMS(args) () -#define VPARAMS(args) (va_alist) va_dcl -#define VA_START(va_list, var) va_start(va_list) - -#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP); { struct Qdmy -#define VA_CLOSE(AP) } va_end(AP); } -#define VA_FIXEDARG(AP, TYPE, NAME) TYPE NAME = va_arg(AP, TYPE) - -/* some systems define these in header files for non-ansi mode */ -#undef const -#undef volatile -#undef signed -#undef inline -#define const -#define volatile -#define signed -#define inline - -#ifndef IN_GCC -#define CONST -#define VOLATILE -#define SIGNED - -#define PROTO(type, name, arglist) type name () -#define EXFUN(name, proto) name() -#define DEFUN(name, arglist, args) name arglist args; -#define DEFUN_VOID(name) name() -#define AND ; -#define DOTS -#define NOARGS -#endif /* ! IN_GCC */ - -#endif /* ANSI C. */ - -/* Define macros for some gcc attributes. This permits us to use the - macros freely, and know that they will come into play for the - version of gcc in which they are supported. */ - -#if (GCC_VERSION < 2007) -# define __attribute__(x) -#endif - -/* Attribute __malloc__ on functions was valid as of gcc 2.96. */ -#ifndef ATTRIBUTE_MALLOC -# if (GCC_VERSION >= 2096) -# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) -# else -# define ATTRIBUTE_MALLOC -# endif /* GNUC >= 2.96 */ -#endif /* ATTRIBUTE_MALLOC */ - -/* Attributes on labels were valid as of gcc 2.93. */ -#ifndef ATTRIBUTE_UNUSED_LABEL -# if (GCC_VERSION >= 2093) -# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED -# else -# define ATTRIBUTE_UNUSED_LABEL -# endif /* GNUC >= 2.93 */ -#endif /* ATTRIBUTE_UNUSED_LABEL */ - -#ifndef ATTRIBUTE_UNUSED -#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#endif /* ATTRIBUTE_UNUSED */ - -#ifndef ATTRIBUTE_NORETURN -#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -#endif /* ATTRIBUTE_NORETURN */ - -#ifndef ATTRIBUTE_PRINTF -#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) -#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2) -#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3) -#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4) -#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5) -#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6) -#endif /* ATTRIBUTE_PRINTF */ - -/* We use __extension__ in some places to suppress -pedantic warnings - about GCC extensions. This feature didn't work properly before - gcc 2.8. */ -#if GCC_VERSION < 2008 -#define __extension__ -#endif - -/* Bootstrap support: Adjust certain macros defined by Autoconf, - which are only valid for the stage1 compiler. If we detect - a modern version of GCC, we are probably in stage2 or beyond, - so unconditionally reset the values. Note that const, inline, - etc. have been dealt with above. */ -#if (GCC_VERSION >= 2007) -# ifndef HAVE_LONG_DOUBLE -# define HAVE_LONG_DOUBLE 1 -# endif -#endif /* GCC >= 2.7 */ - -#endif /* ansidecl.h */ diff --git a/cxmon/src/disass/bfd.h b/cxmon/src/disass/bfd.h deleted file mode 100644 index dbb9a882..00000000 --- a/cxmon/src/disass/bfd.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * bfd.h - Dummy bfd library header file - */ - -#include "sysdeps.h" -#include "ansidecl.h" - -enum bfd_flavour { - bfd_target_unknown_flavour -}; - -enum bfd_endian { - BFD_ENDIAN_BIG, - BFD_ENDIAN_LITTLE, - BFD_ENDIAN_UNKNOWN -}; - -enum bfd_architecture { - bfd_arch_unknown, - bfd_arch_m68k, -#define bfd_mach_m68000 1 -#define bfd_mach_m68008 2 -#define bfd_mach_m68010 3 -#define bfd_mach_m68020 4 -#define bfd_mach_m68030 5 -#define bfd_mach_m68040 6 -#define bfd_mach_m68060 7 - bfd_arch_i386 -#define bfd_mach_i386_i386 0 -#define bfd_mach_i386_i8086 1 -#define bfd_mach_i386_i386_intel_syntax 2 -#define bfd_mach_x86_64 3 -#define bfd_mach_x86_64_intel_syntax 4 -}; - -typedef struct symbol_cache_entry { - CONST char *name; -} asymbol; - -typedef uint64 bfd_vma; -typedef int64 bfd_signed_vma; -typedef unsigned char bfd_byte; - -typedef struct _bfd bfd; -struct _bfd; - -#if SIZEOF_LONG == 8 -#define BFD_HOST_64BIT_LONG 1 -#endif - -// 64-bit vma -#define BFD64 - -#ifndef fprintf_vma -#if BFD_HOST_64BIT_LONG -#define sprintf_vma(s,x) sprintf (s, "%016lx", x) -#define fprintf_vma(f,x) fprintf (f, "%016lx", x) -#else -#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff))) -#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff)) -#define fprintf_vma(s,x) \ - fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) -#define sprintf_vma(s,x) \ - sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) -#endif -#endif diff --git a/cxmon/src/disass/dis-asm.h b/cxmon/src/disass/dis-asm.h deleted file mode 100644 index 3d2461c0..00000000 --- a/cxmon/src/disass/dis-asm.h +++ /dev/null @@ -1,315 +0,0 @@ -/* Interface between the opcode library and its callers. - - Copyright 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Written by Cygnus Support, 1993. - - The opcode library (libopcodes.a) provides instruction decoders for - a large variety of instruction sets, callable with an identical - interface, for making instruction-processing programs more independent - of the instruction set being processed. */ - -#ifndef DIS_ASM_H -#define DIS_ASM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "bfd.h" - -typedef int (*fprintf_ftype) PARAMS((PTR, const char*, ...)); - -enum dis_insn_type { - dis_noninsn, /* Not a valid instruction */ - dis_nonbranch, /* Not a branch instruction */ - dis_branch, /* Unconditional branch */ - dis_condbranch, /* Conditional branch */ - dis_jsr, /* Jump to subroutine */ - dis_condjsr, /* Conditional jump to subroutine */ - dis_dref, /* Data reference instruction */ - dis_dref2 /* Two data references in instruction */ -}; - -/* This struct is passed into the instruction decoding routine, - and is passed back out into each callback. The various fields are used - for conveying information from your main routine into your callbacks, - for passing information into the instruction decoders (such as the - addresses of the callback functions), or for passing information - back from the instruction decoders to their callers. - - It must be initialized before it is first passed; this can be done - by hand, or using one of the initialization macros below. */ - -typedef struct disassemble_info { - fprintf_ftype fprintf_func; - PTR stream; - PTR application_data; - - /* Target description. We could replace this with a pointer to the bfd, - but that would require one. There currently isn't any such requirement - so to avoid introducing one we record these explicitly. */ - /* The bfd_flavour. This can be bfd_target_unknown_flavour. */ - enum bfd_flavour flavour; - /* The bfd_arch value. */ - enum bfd_architecture arch; - /* The bfd_mach value. */ - unsigned long mach; - /* Endianness (for bi-endian cpus). Mono-endian cpus can ignore this. */ - enum bfd_endian endian; - /* An arch/mach-specific bitmask of selected instruction subsets, mainly - for processors with run-time-switchable instruction sets. The default, - zero, means that there is no constraint. CGEN-based opcodes ports - may use ISA_foo masks. */ - unsigned long insn_sets; - - /* An array of pointers to symbols either at the location being disassembled - or at the start of the function being disassembled. The array is sorted - so that the first symbol is intended to be the one used. The others are - present for any misc. purposes. This is not set reliably, but if it is - not NULL, it is correct. */ - asymbol **symbols; - /* Number of symbols in array. */ - int num_symbols; - - /* For use by the disassembler. - The top 16 bits are reserved for public use (and are documented here). - The bottom 16 bits are for the internal use of the disassembler. */ - unsigned long flags; -#define INSN_HAS_RELOC 0x80000000 - PTR private_data; - - /* Function used to get bytes to disassemble. MEMADDR is the - address of the stuff to be disassembled, MYADDR is the address to - put the bytes in, and LENGTH is the number of bytes to read. - INFO is a pointer to this struct. - Returns an errno value or 0 for success. */ - int (*read_memory_func) - PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, - struct disassemble_info *info)); - - /* Function which should be called if we get an error that we can't - recover from. STATUS is the errno value from read_memory_func and - MEMADDR is the address that we were trying to read. INFO is a - pointer to this struct. */ - void (*memory_error_func) - PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info)); - - /* Function called to print ADDR. */ - void (*print_address_func) - PARAMS ((bfd_vma addr, struct disassemble_info *info)); - - /* Function called to determine if there is a symbol at the given ADDR. - If there is, the function returns 1, otherwise it returns 0. - This is used by ports which support an overlay manager where - the overlay number is held in the top part of an address. In - some circumstances we want to include the overlay number in the - address, (normally because there is a symbol associated with - that address), but sometimes we want to mask out the overlay bits. */ - int (* symbol_at_address_func) - PARAMS ((bfd_vma addr, struct disassemble_info * info)); - - /* These are for buffer_read_memory. */ - bfd_byte *buffer; - bfd_vma buffer_vma; - unsigned int buffer_length; - - /* This variable may be set by the instruction decoder. It suggests - the number of bytes objdump should display on a single line. If - the instruction decoder sets this, it should always set it to - the same value in order to get reasonable looking output. */ - int bytes_per_line; - - /* the next two variables control the way objdump displays the raw data */ - /* For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the */ - /* output will look like this: - 00: 00000000 00000000 - with the chunks displayed according to "display_endian". */ - int bytes_per_chunk; - enum bfd_endian display_endian; - - /* Number of octets per incremented target address - Normally one, but some DSPs have byte sizes of 16 or 32 bits. */ - unsigned int octets_per_byte; - - /* Results from instruction decoders. Not all decoders yet support - this information. This info is set each time an instruction is - decoded, and is only valid for the last such instruction. - - To determine whether this decoder supports this information, set - insn_info_valid to 0, decode an instruction, then check it. */ - - char insn_info_valid; /* Branch info has been set. */ - char branch_delay_insns; /* How many sequential insn's will run before - a branch takes effect. (0 = normal) */ - char data_size; /* Size of data reference in insn, in bytes */ - enum dis_insn_type insn_type; /* Type of instruction */ - bfd_vma target; /* Target address of branch or dref, if known; - zero if unknown. */ - bfd_vma target2; /* Second target address for dref2 */ - - /* Command line options specific to the target disassembler. */ - char * disassembler_options; - -} disassemble_info; - - -/* Standard disassemblers. Disassemble one instruction at the given - target address. Return number of octets processed. */ -typedef int (*disassembler_ftype) - PARAMS((bfd_vma, disassemble_info *)); - -extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_little_mips PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info *)); -extern int print_insn_i386_att PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_i386_intel PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_ia64 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_i370 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_m68hc11 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_m68hc12 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_m68k PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_z8001 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_z8002 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_h8300 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_h8300h PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_h8300s PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_big_arm PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_little_arm PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_avr PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_d10v PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_d30v PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_dlx PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_fr30 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_hppa PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_i860 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_i960 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_m32r PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_m88k PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_mcore PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_mmix PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_mn10200 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_mn10300 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_ns32k PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_openrisc PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_big_or32 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_little_or32 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_pdp11 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_pj PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_big_powerpc PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_little_powerpc PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_rs6000 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_s390 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_sh PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_tic54x PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_tic80 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_v850 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_vax PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_w65 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_xstormy16 PARAMS ((bfd_vma, disassemble_info*)); -extern int print_insn_sh64 PARAMS ((bfd_vma, disassemble_info *)); -extern int print_insn_sh64x_media PARAMS ((bfd_vma, disassemble_info *)); -extern int print_insn_frv PARAMS ((bfd_vma, disassemble_info *)); - -extern disassembler_ftype arc_get_disassembler PARAMS ((void *)); -extern disassembler_ftype cris_get_disassembler PARAMS ((bfd *)); - -extern void print_arm_disassembler_options PARAMS ((FILE *)); -extern void parse_arm_disassembler_option PARAMS ((char *)); -extern int get_arm_regname_num_options PARAMS ((void)); -extern int set_arm_regname_option PARAMS ((int)); -extern int get_arm_regnames PARAMS ((int, const char **, const char **, const char ***)); - -/* Fetch the disassembler for a given BFD, if that support is available. */ -extern disassembler_ftype disassembler PARAMS ((bfd *)); - -/* Document any target specific options available from the disassembler. */ -extern void disassembler_usage PARAMS ((FILE *)); - - -/* This block of definitions is for particular callers who read instructions - into a buffer before calling the instruction decoder. */ - -/* Here is a function which callers may wish to use for read_memory_func. - It gets bytes from a buffer. */ -extern int buffer_read_memory - PARAMS ((bfd_vma, bfd_byte *, unsigned int, struct disassemble_info *)); - -/* This function goes with buffer_read_memory. - It prints a message using info->fprintf_func and info->stream. */ -extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *)); - - -/* Just print the address in hex. This is included for completeness even - though both GDB and objdump provide their own (to print symbolic - addresses). */ -extern void generic_print_address - PARAMS ((bfd_vma, struct disassemble_info *)); - -/* Always true. */ -extern int generic_symbol_at_address - PARAMS ((bfd_vma, struct disassemble_info *)); - -/* Macro to initialize a disassemble_info struct. This should be called - by all applications creating such a struct. */ -#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \ - (INFO).flavour = bfd_target_unknown_flavour, \ - (INFO).arch = bfd_arch_unknown, \ - (INFO).mach = 0, \ - (INFO).insn_sets = 0, \ - (INFO).endian = BFD_ENDIAN_UNKNOWN, \ - (INFO).octets_per_byte = 1, \ - INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) - -/* Call this macro to initialize only the internal variables for the - disassembler. Architecture dependent things such as byte order, or machine - variant are not touched by this macro. This makes things much easier for - GDB which must initialize these things separately. */ - -#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \ - (INFO).fprintf_func = (fprintf_ftype)(FPRINTF_FUNC), \ - (INFO).stream = (PTR)(STREAM), \ - (INFO).symbols = NULL, \ - (INFO).num_symbols = 0, \ - (INFO).private_data = NULL, \ - (INFO).buffer = NULL, \ - (INFO).buffer_vma = 0, \ - (INFO).buffer_length = 0, \ - (INFO).read_memory_func = buffer_read_memory, \ - (INFO).memory_error_func = perror_memory, \ - (INFO).print_address_func = generic_print_address, \ - (INFO).symbol_at_address_func = generic_symbol_at_address, \ - (INFO).flags = 0, \ - (INFO).bytes_per_line = 0, \ - (INFO).bytes_per_chunk = 0, \ - (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \ - (INFO).disassembler_options = NULL, \ - (INFO).insn_info_valid = 0 - -#ifdef __cplusplus -}; -#endif - -#endif /* ! defined (DIS_ASM_H) */ diff --git a/cxmon/src/disass/floatformat.c b/cxmon/src/disass/floatformat.c deleted file mode 100644 index 7f6086f4..00000000 --- a/cxmon/src/disass/floatformat.c +++ /dev/null @@ -1,401 +0,0 @@ -/* IEEE floating point support routines, for GDB, the GNU Debugger. - Copyright (C) 1991, 1994 Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "floatformat.h" -#include /* ldexp */ -#ifdef __STDC__ -#include -extern void *memcpy (void *s1, const void *s2, size_t n); -extern void *memset (void *s, int c, size_t n); -#else -extern char *memcpy (); -extern char *memset (); -#endif - -/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not - going to bother with trying to muck around with whether it is defined in - a system header, what we do if not, etc. */ -#define FLOATFORMAT_CHAR_BIT 8 - -/* floatformats for IEEE single and double, big and little endian. */ -const struct floatformat floatformat_ieee_single_big = -{ - floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23, floatformat_intbit_no -}; -const struct floatformat floatformat_ieee_single_little = -{ - floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23, floatformat_intbit_no -}; -const struct floatformat floatformat_ieee_double_big = -{ - floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52, floatformat_intbit_no -}; -const struct floatformat floatformat_ieee_double_little = -{ - floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52, floatformat_intbit_no -}; - -/* floatformat for IEEE double, little endian byte order, with big endian word - ordering, as on the ARM. */ - -const struct floatformat floatformat_ieee_double_littlebyte_bigword = -{ - floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52, floatformat_intbit_no -}; - -const struct floatformat floatformat_i387_ext = -{ - floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, - floatformat_intbit_yes -}; -const struct floatformat floatformat_m68881_ext = -{ - /* Note that the bits from 16 to 31 are unused. */ - floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64, floatformat_intbit_yes -}; -const struct floatformat floatformat_i960_ext = -{ - /* Note that the bits from 0 to 15 are unused. */ - floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64, - floatformat_intbit_yes -}; -const struct floatformat floatformat_m88110_ext = -{ -#ifdef HARRIS_FLOAT_FORMAT - /* Harris uses raw format 128 bytes long, but the number is just an ieee - double, and the last 64 bits are wasted. */ - floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52, - floatformat_intbit_no -#else - floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, - floatformat_intbit_yes -#endif /* HARRIS_FLOAT_FORMAT */ -}; -const struct floatformat floatformat_arm_ext = -{ - /* Bits 1 to 16 are unused. */ - floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, - floatformat_intbit_yes -}; - -static unsigned long get_field PARAMS ((unsigned char *, - enum floatformat_byteorders, - unsigned int, - unsigned int, - unsigned int)); - -/* Extract a field which starts at START and is LEN bytes long. DATA and - TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ -static unsigned long -get_field (data, order, total_len, start, len) - unsigned char *data; - enum floatformat_byteorders order; - unsigned int total_len; - unsigned int start; - unsigned int len; -{ - unsigned long result; - unsigned int cur_byte; - int cur_bitshift; - - /* Start at the least significant part of the field. */ - cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little) - cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1; - cur_bitshift = - ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; - result = *(data + cur_byte) >> (-cur_bitshift); - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little) - ++cur_byte; - else - --cur_byte; - - /* Move towards the most significant part of the field. */ - while (cur_bitshift < len) - { - if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT) - /* This is the last byte; zero out the bits which are not part of - this field. */ - result |= - (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1)) - << cur_bitshift; - else - result |= *(data + cur_byte) << cur_bitshift; - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little) - ++cur_byte; - else - --cur_byte; - } - return result; -} - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -/* Convert from FMT to a double. - FROM is the address of the extended float. - Store the double in *TO. */ - -void -floatformat_to_double (fmt, from, to) - const struct floatformat *fmt; - char *from; - double *to; -{ - unsigned char *ufrom = (unsigned char *)from; - double dto; - long exponent; - unsigned long mant; - unsigned int mant_bits, mant_off; - int mant_bits_left; - int special_exponent; /* It's a NaN, denorm or zero */ - - exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, - fmt->exp_start, fmt->exp_len); - /* Note that if exponent indicates a NaN, we can't really do anything useful - (not knowing if the host has NaN's, or how to build one). So it will - end up as an infinity or something close; that is OK. */ - - mant_bits_left = fmt->man_len; - mant_off = fmt->man_start; - dto = 0.0; - - special_exponent = exponent == 0 || exponent == fmt->exp_nan; - - /* Don't bias zero's, denorms or NaNs. */ - if (!special_exponent) - exponent -= fmt->exp_bias; - - /* Build the result algebraically. Might go infinite, underflow, etc; - who cares. */ - - /* If this format uses a hidden bit, explicitly add it in now. Otherwise, - increment the exponent by one to account for the integer bit. */ - - if (!special_exponent) - if (fmt->intbit == floatformat_intbit_no) - dto = ldexp (1.0, exponent); - else - exponent++; - - while (mant_bits_left > 0) - { - mant_bits = min (mant_bits_left, 32); - - mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, - mant_off, mant_bits); - - dto += ldexp ((double)mant, exponent - mant_bits); - exponent -= mant_bits; - mant_off += mant_bits; - mant_bits_left -= mant_bits; - } - - /* Negate it if negative. */ - if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) - dto = -dto; - *to = dto; -} - -static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders, - unsigned int, - unsigned int, - unsigned int, - unsigned long)); - -/* Set a field which starts at START and is LEN bytes long. DATA and - TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ -static void -put_field (data, order, total_len, start, len, stuff_to_put) - unsigned char *data; - enum floatformat_byteorders order; - unsigned int total_len; - unsigned int start; - unsigned int len; - unsigned long stuff_to_put; -{ - unsigned int cur_byte; - int cur_bitshift; - - /* Start at the least significant part of the field. */ - cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little) - cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1; - cur_bitshift = - ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT; - *(data + cur_byte) &= - ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift)); - *(data + cur_byte) |= - (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little) - ++cur_byte; - else - --cur_byte; - - /* Move towards the most significant part of the field. */ - while (cur_bitshift < len) - { - if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT) - { - /* This is the last byte. */ - *(data + cur_byte) &= - ~((1 << (len - cur_bitshift)) - 1); - *(data + cur_byte) |= (stuff_to_put >> cur_bitshift); - } - else - *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) - & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); - cur_bitshift += FLOATFORMAT_CHAR_BIT; - if (order == floatformat_little) - ++cur_byte; - else - --cur_byte; - } -} - -/* The converse: convert the double *FROM to an extended float - and store where TO points. Neither FROM nor TO have any alignment - restrictions. */ - -void -floatformat_from_double (fmt, from, to) - CONST struct floatformat *fmt; - double *from; - char *to; -{ - double dfrom; - int exponent; - double mant; - unsigned int mant_bits, mant_off; - int mant_bits_left; - unsigned char *uto = (unsigned char *)to; - - memcpy (&dfrom, from, sizeof (dfrom)); - memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT); - if (dfrom == 0) - return; /* Result is zero */ - if (dfrom != dfrom) - { - /* From is NaN */ - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, - fmt->exp_len, fmt->exp_nan); - /* Be sure it's not infinity, but NaN value is irrel */ - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, - 32, 1); - return; - } - - /* If negative, set the sign bit. */ - if (dfrom < 0) - { - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); - dfrom = -dfrom; - } - - /* How to tell an infinity from an ordinary number? FIXME-someday */ - - mant = frexp (dfrom, &exponent); - put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, - exponent + fmt->exp_bias - 1); - - mant_bits_left = fmt->man_len; - mant_off = fmt->man_start; - while (mant_bits_left > 0) - { - unsigned long mant_long; - mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; - - mant *= 4294967296.0; - mant_long = (unsigned long)mant; - mant -= mant_long; - - /* If the integer bit is implicit, then we need to discard it. - If we are discarding a zero, we should be (but are not) creating - a denormalized number which means adjusting the exponent - (I think). */ - if (mant_bits_left == fmt->man_len - && fmt->intbit == floatformat_intbit_no) - { - mant_long &= 0x7fffffff; - mant_bits -= 1; - } - else if (mant_bits < 32) - { - /* The bits we want are in the most significant MANT_BITS bits of - mant_long. Move them to the least significant. */ - mant_long >>= 32 - mant_bits; - } - - put_field (uto, fmt->byteorder, fmt->totalsize, - mant_off, mant_bits, mant_long); - mant_off += mant_bits; - mant_bits_left -= mant_bits; - } -} - - -#ifdef IEEE_DEBUG - -/* This is to be run on a host which uses IEEE floating point. */ - -void -ieee_test (n) - double n; -{ - double result; - char exten[16]; - - floatformat_to_double (&floatformat_ieee_double_big, &n, &result); - if (n != result) - printf ("Differ(to): %.20g -> %.20g\n", n, result); - floatformat_from_double (&floatformat_ieee_double_big, &n, &result); - if (n != result) - printf ("Differ(from): %.20g -> %.20g\n", n, result); - - floatformat_from_double (&floatformat_m68881_ext, &n, exten); - floatformat_to_double (&floatformat_m68881_ext, exten, &result); - if (n != result) - printf ("Differ(to+from): %.20g -> %.20g\n", n, result); - -#if IEEE_DEBUG > 1 - /* This is to be run on a host which uses 68881 format. */ - { - long double ex = *(long double *)exten; - if (ex != n) - printf ("Differ(from vs. extended): %.20g\n", n); - } -#endif -} - -int -main () -{ - ieee_test (0.5); - ieee_test (256.0); - ieee_test (0.12345); - ieee_test (234235.78907234); - ieee_test (-512.0); - ieee_test (-0.004321); - return 0; -} -#endif diff --git a/cxmon/src/disass/floatformat.h b/cxmon/src/disass/floatformat.h deleted file mode 100644 index 90daca21..00000000 --- a/cxmon/src/disass/floatformat.h +++ /dev/null @@ -1,111 +0,0 @@ -/* IEEE floating point support declarations, for GDB, the GNU Debugger. - Copyright (C) 1991 Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#if !defined (FLOATFORMAT_H) -#define FLOATFORMAT_H 1 - -#include "ansidecl.h" - -/* A floatformat consists of a sign bit, an exponent and a mantissa. Once the - bytes are concatenated according to the byteorder flag, then each of those - fields is contiguous. We number the bits with 0 being the most significant - (i.e. BITS_BIG_ENDIAN type numbering), and specify which bits each field - contains with the *_start and *_len fields. */ - -/* What is the order of the bytes. */ - -enum floatformat_byteorders { - - /* Standard little endian byte order. - EX: 1.2345678e10 => 00 00 80 c5 e0 fe 06 42 */ - - floatformat_little, - - /* Standard big endian byte order. - EX: 1.2345678e10 => 42 06 fe e0 c5 80 00 00 */ - - floatformat_big, - - /* Little endian byte order but big endian word order. - EX: 1.2345678e10 => e0 fe 06 42 00 00 80 c5 */ - - floatformat_littlebyte_bigword - -}; - -enum floatformat_intbit { floatformat_intbit_yes, floatformat_intbit_no }; - -struct floatformat -{ - enum floatformat_byteorders byteorder; - unsigned int totalsize; /* Total size of number in bits */ - - /* Sign bit is always one bit long. 1 means negative, 0 means positive. */ - unsigned int sign_start; - - unsigned int exp_start; - unsigned int exp_len; - /* Amount added to "true" exponent. 0x3fff for many IEEE extendeds. */ - unsigned int exp_bias; - /* Exponent value which indicates NaN. This is the actual value stored in - the float, not adjusted by the exp_bias. This usually consists of all - one bits. */ - unsigned int exp_nan; - - unsigned int man_start; - unsigned int man_len; - - /* Is the integer bit explicit or implicit? */ - enum floatformat_intbit intbit; -}; - -/* floatformats for IEEE single and double, big and little endian. */ - -extern const struct floatformat floatformat_ieee_single_big; -extern const struct floatformat floatformat_ieee_single_little; -extern const struct floatformat floatformat_ieee_double_big; -extern const struct floatformat floatformat_ieee_double_little; - -/* floatformat for ARM IEEE double, little endian bytes and big endian words */ - -extern const struct floatformat floatformat_ieee_double_littlebyte_bigword; - -/* floatformats for various extendeds. */ - -extern const struct floatformat floatformat_i387_ext; -extern const struct floatformat floatformat_m68881_ext; -extern const struct floatformat floatformat_i960_ext; -extern const struct floatformat floatformat_m88110_ext; -extern const struct floatformat floatformat_arm_ext; - -/* Convert from FMT to a double. - FROM is the address of the extended float. - Store the double in *TO. */ - -extern void -floatformat_to_double PARAMS ((const struct floatformat *, char *, double *)); - -/* The converse: convert the double *FROM to FMT - and store where TO points. */ - -extern void -floatformat_from_double PARAMS ((const struct floatformat *, - double *, char *)); - -#endif /* defined (FLOATFORMAT_H) */ diff --git a/cxmon/src/disass/i386-dis.c b/cxmon/src/disass/i386-dis.c deleted file mode 100644 index e417212e..00000000 --- a/cxmon/src/disass/i386-dis.c +++ /dev/null @@ -1,4146 +0,0 @@ -/* Print i386 instructions for GDB, the GNU debugger. - Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2001 - Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* - * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) - * July 1988 - * modified by John Hassey (hassey@dg-rtp.dg.com) - * x86-64 support added by Jan Hubicka (jh@suse.cz) - */ - -/* - * The main tables describing the instructions is essentially a copy - * of the "Opcode Map" chapter (Appendix A) of the Intel 80386 - * Programmers Manual. Usually, there is a capital letter, followed - * by a small letter. The capital letter tell the addressing mode, - * and the small letter tells about the operand size. Refer to - * the Intel manual for details. - */ - -#include "dis-asm.h" -#include "opintl.h" - -#define MAXLEN 20 - -#include - -#ifndef UNIXWARE_COMPAT -/* Set non-zero for broken, compatible instructions. Set to zero for - non-broken opcodes. */ -#define UNIXWARE_COMPAT 1 -#endif - -static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *)); -static void ckprefix PARAMS ((void)); -static const char *prefix_name PARAMS ((int, int)); -static int print_insn PARAMS ((bfd_vma, disassemble_info *)); -static void dofloat PARAMS ((int)); -static void OP_ST PARAMS ((int, int)); -static void OP_STi PARAMS ((int, int)); -static int putop PARAMS ((const char *, int)); -static void oappend PARAMS ((const char *)); -static void append_seg PARAMS ((void)); -static void OP_indirE PARAMS ((int, int)); -static void print_operand_value PARAMS ((char *, int, bfd_vma)); -static void OP_E PARAMS ((int, int)); -static void OP_G PARAMS ((int, int)); -static bfd_vma get64 PARAMS ((void)); -static bfd_signed_vma get32 PARAMS ((void)); -static bfd_signed_vma get32s PARAMS ((void)); -static int get16 PARAMS ((void)); -static void set_op PARAMS ((bfd_vma, int)); -static void OP_REG PARAMS ((int, int)); -static void OP_IMREG PARAMS ((int, int)); -static void OP_I PARAMS ((int, int)); -static void OP_I64 PARAMS ((int, int)); -static void OP_sI PARAMS ((int, int)); -static void OP_J PARAMS ((int, int)); -static void OP_SEG PARAMS ((int, int)); -static void OP_DIR PARAMS ((int, int)); -static void OP_OFF PARAMS ((int, int)); -static void OP_OFF64 PARAMS ((int, int)); -static void ptr_reg PARAMS ((int, int)); -static void OP_ESreg PARAMS ((int, int)); -static void OP_DSreg PARAMS ((int, int)); -static void OP_C PARAMS ((int, int)); -static void OP_D PARAMS ((int, int)); -static void OP_T PARAMS ((int, int)); -static void OP_Rd PARAMS ((int, int)); -static void OP_MMX PARAMS ((int, int)); -static void OP_XMM PARAMS ((int, int)); -static void OP_EM PARAMS ((int, int)); -static void OP_EX PARAMS ((int, int)); -static void OP_MS PARAMS ((int, int)); -static void OP_XS PARAMS ((int, int)); -static void OP_3DNowSuffix PARAMS ((int, int)); -static void OP_SIMD_Suffix PARAMS ((int, int)); -static void SIMD_Fixup PARAMS ((int, int)); -static void BadOp PARAMS ((void)); - -struct dis_private { - /* Points to first byte not fetched. */ - bfd_byte *max_fetched; - bfd_byte the_buffer[MAXLEN]; - bfd_vma insn_start; - int orig_sizeflag; - jmp_buf bailout; -}; - -/* The opcode for the fwait instruction, which we treat as a prefix - when we can. */ -#define FWAIT_OPCODE (0x9b) - -/* Set to 1 for 64bit mode disassembly. */ -static int mode_64bit; - -/* Flags for the prefixes for the current instruction. See below. */ -static int prefixes; - -/* REX prefix the current instruction. See below. */ -static int rex; -/* Bits of REX we've already used. */ -static int rex_used; -#define REX_MODE64 8 -#define REX_EXTX 4 -#define REX_EXTY 2 -#define REX_EXTZ 1 -/* Mark parts used in the REX prefix. When we are testing for - empty prefix (for 8bit register REX extension), just mask it - out. Otherwise test for REX bit is excuse for existence of REX - only in case value is nonzero. */ -#define USED_REX(value) \ - { \ - if (value) \ - rex_used |= (rex & value) ? (value) | 0x40 : 0; \ - else \ - rex_used |= 0x40; \ - } - -/* Flags for prefixes which we somehow handled when printing the - current instruction. */ -static int used_prefixes; - -/* Flags stored in PREFIXES. */ -#define PREFIX_REPZ 1 -#define PREFIX_REPNZ 2 -#define PREFIX_LOCK 4 -#define PREFIX_CS 8 -#define PREFIX_SS 0x10 -#define PREFIX_DS 0x20 -#define PREFIX_ES 0x40 -#define PREFIX_FS 0x80 -#define PREFIX_GS 0x100 -#define PREFIX_DATA 0x200 -#define PREFIX_ADDR 0x400 -#define PREFIX_FWAIT 0x800 - -/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) - to ADDR (exclusive) are valid. Returns 1 for success, longjmps - on error. */ -#define FETCH_DATA(info, addr) \ - ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \ - ? 1 : fetch_data ((info), (addr))) - -static int -fetch_data (info, addr) - struct disassemble_info *info; - bfd_byte *addr; -{ - int status; - struct dis_private *priv = (struct dis_private *) info->private_data; - bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); - - status = (*info->read_memory_func) (start, - priv->max_fetched, - addr - priv->max_fetched, - info); - if (status != 0) - { - /* If we did manage to read at least one byte, then - print_insn_i386 will do something sensible. Otherwise, print - an error. We do that here because this is where we know - STATUS. */ - if (priv->max_fetched == priv->the_buffer) - (*info->memory_error_func) (status, start, info); - longjmp (priv->bailout, 1); - } - else - priv->max_fetched = addr; - return 1; -} - -#define XX NULL, 0 - -#define Eb OP_E, b_mode -#define Ev OP_E, v_mode -#define Ed OP_E, d_mode -#define Edq OP_E, dq_mode -#define indirEb OP_indirE, b_mode -#define indirEv OP_indirE, v_mode -#define Ew OP_E, w_mode -#define Ma OP_E, v_mode -#define M OP_E, 0 /* lea, lgdt, etc. */ -#define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */ -#define Gb OP_G, b_mode -#define Gv OP_G, v_mode -#define Gd OP_G, d_mode -#define Gw OP_G, w_mode -#define Rd OP_Rd, d_mode -#define Rm OP_Rd, m_mode -#define Ib OP_I, b_mode -#define sIb OP_sI, b_mode /* sign extened byte */ -#define Iv OP_I, v_mode -#define Iq OP_I, q_mode -#define Iv64 OP_I64, v_mode -#define Iw OP_I, w_mode -#define Jb OP_J, b_mode -#define Jv OP_J, v_mode -#define Cm OP_C, m_mode -#define Dm OP_D, m_mode -#define Td OP_T, d_mode - -#define RMeAX OP_REG, eAX_reg -#define RMeBX OP_REG, eBX_reg -#define RMeCX OP_REG, eCX_reg -#define RMeDX OP_REG, eDX_reg -#define RMeSP OP_REG, eSP_reg -#define RMeBP OP_REG, eBP_reg -#define RMeSI OP_REG, eSI_reg -#define RMeDI OP_REG, eDI_reg -#define RMrAX OP_REG, rAX_reg -#define RMrBX OP_REG, rBX_reg -#define RMrCX OP_REG, rCX_reg -#define RMrDX OP_REG, rDX_reg -#define RMrSP OP_REG, rSP_reg -#define RMrBP OP_REG, rBP_reg -#define RMrSI OP_REG, rSI_reg -#define RMrDI OP_REG, rDI_reg -#define RMAL OP_REG, al_reg -#define RMAL OP_REG, al_reg -#define RMCL OP_REG, cl_reg -#define RMDL OP_REG, dl_reg -#define RMBL OP_REG, bl_reg -#define RMAH OP_REG, ah_reg -#define RMCH OP_REG, ch_reg -#define RMDH OP_REG, dh_reg -#define RMBH OP_REG, bh_reg -#define RMAX OP_REG, ax_reg -#define RMDX OP_REG, dx_reg - -#define eAX OP_IMREG, eAX_reg -#define eBX OP_IMREG, eBX_reg -#define eCX OP_IMREG, eCX_reg -#define eDX OP_IMREG, eDX_reg -#define eSP OP_IMREG, eSP_reg -#define eBP OP_IMREG, eBP_reg -#define eSI OP_IMREG, eSI_reg -#define eDI OP_IMREG, eDI_reg -#define AL OP_IMREG, al_reg -#define AL OP_IMREG, al_reg -#define CL OP_IMREG, cl_reg -#define DL OP_IMREG, dl_reg -#define BL OP_IMREG, bl_reg -#define AH OP_IMREG, ah_reg -#define CH OP_IMREG, ch_reg -#define DH OP_IMREG, dh_reg -#define BH OP_IMREG, bh_reg -#define AX OP_IMREG, ax_reg -#define DX OP_IMREG, dx_reg -#define indirDX OP_IMREG, indir_dx_reg - -#define Sw OP_SEG, w_mode -#define Ap OP_DIR, 0 -#define Ob OP_OFF, b_mode -#define Ob64 OP_OFF64, b_mode -#define Ov OP_OFF, v_mode -#define Ov64 OP_OFF64, v_mode -#define Xb OP_DSreg, eSI_reg -#define Xv OP_DSreg, eSI_reg -#define Yb OP_ESreg, eDI_reg -#define Yv OP_ESreg, eDI_reg -#define DSBX OP_DSreg, eBX_reg - -#define es OP_REG, es_reg -#define ss OP_REG, ss_reg -#define cs OP_REG, cs_reg -#define ds OP_REG, ds_reg -#define fs OP_REG, fs_reg -#define gs OP_REG, gs_reg - -#define MX OP_MMX, 0 -#define XM OP_XMM, 0 -#define EM OP_EM, v_mode -#define EX OP_EX, v_mode -#define MS OP_MS, v_mode -#define XS OP_XS, v_mode -#define None OP_E, 0 -#define OPSUF OP_3DNowSuffix, 0 -#define OPSIMD OP_SIMD_Suffix, 0 - -#define cond_jump_flag NULL, cond_jump_mode -#define loop_jcxz_flag NULL, loop_jcxz_mode - -/* bits in sizeflag */ -#define SUFFIX_ALWAYS 4 -#define AFLAG 2 -#define DFLAG 1 - -#define b_mode 1 /* byte operand */ -#define v_mode 2 /* operand size depends on prefixes */ -#define w_mode 3 /* word operand */ -#define d_mode 4 /* double word operand */ -#define q_mode 5 /* quad word operand */ -#define x_mode 6 -#define m_mode 7 /* d_mode in 32bit, q_mode in 64bit mode. */ -#define cond_jump_mode 8 -#define loop_jcxz_mode 9 -#define dq_mode 10 /* operand size depends on REX prefixes. */ - -#define es_reg 100 -#define cs_reg 101 -#define ss_reg 102 -#define ds_reg 103 -#define fs_reg 104 -#define gs_reg 105 - -#define eAX_reg 108 -#define eCX_reg 109 -#define eDX_reg 110 -#define eBX_reg 111 -#define eSP_reg 112 -#define eBP_reg 113 -#define eSI_reg 114 -#define eDI_reg 115 - -#define al_reg 116 -#define cl_reg 117 -#define dl_reg 118 -#define bl_reg 119 -#define ah_reg 120 -#define ch_reg 121 -#define dh_reg 122 -#define bh_reg 123 - -#define ax_reg 124 -#define cx_reg 125 -#define dx_reg 126 -#define bx_reg 127 -#define sp_reg 128 -#define bp_reg 129 -#define si_reg 130 -#define di_reg 131 - -#define rAX_reg 132 -#define rCX_reg 133 -#define rDX_reg 134 -#define rBX_reg 135 -#define rSP_reg 136 -#define rBP_reg 137 -#define rSI_reg 138 -#define rDI_reg 139 - -#define indir_dx_reg 150 - -#define FLOATCODE 1 -#define USE_GROUPS 2 -#define USE_PREFIX_USER_TABLE 3 -#define X86_64_SPECIAL 4 - -#define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0 - -#define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0 -#define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0 -#define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0 -#define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0 -#define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0 -#define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0 -#define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0 -#define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0 -#define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0 -#define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0 -#define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0 -#define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0 -#define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0 -#define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0 -#define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0 -#define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0 -#define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0 -#define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0 -#define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0 -#define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0 -#define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0 -#define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0 -#define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0 - -#define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0 -#define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0 -#define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0 -#define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0 -#define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0 -#define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0 -#define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0 -#define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0 -#define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0 -#define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0 -#define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0 -#define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0 -#define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0 -#define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0 -#define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0 -#define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0 -#define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0 -#define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0 -#define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0 -#define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0 -#define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0 -#define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0 -#define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0 -#define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0 -#define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0 -#define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0 -#define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0 - -#define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0 - -typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag)); - -struct dis386 { - const char *name; - op_rtn op1; - int bytemode1; - op_rtn op2; - int bytemode2; - op_rtn op3; - int bytemode3; -}; - -/* Upper case letters in the instruction names here are macros. - 'A' => print 'b' if no register operands or suffix_always is true - 'B' => print 'b' if suffix_always is true - 'E' => print 'e' if 32-bit form of jcxz - 'F' => print 'w' or 'l' depending on address size prefix (loop insns) - 'H' => print ",pt" or ",pn" branch hint - 'L' => print 'l' if suffix_always is true - 'N' => print 'n' if instruction has no wait "prefix" - 'O' => print 'd', or 'o' - 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix, - . or suffix_always is true. print 'q' if rex prefix is present. - 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always - . is true - 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode) - 'S' => print 'w', 'l' or 'q' if suffix_always is true - 'T' => print 'q' in 64bit mode and behave as 'P' otherwise - 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise - 'X' => print 's', 'd' depending on data16 prefix (for XMM) - 'W' => print 'b' or 'w' ("w" or "de" in intel mode) - 'Y' => 'q' if instruction has an REX 64bit overwrite prefix - - Many of the above letters print nothing in Intel mode. See "putop" - for the details. - - Braces '{' and '}', and vertical bars '|', indicate alternative - mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel - modes. In cases where there are only two alternatives, the X86_64 - instruction is reserved, and "(bad)" is printed. -*/ - -static const struct dis386 dis386[] = { - /* 00 */ - { "addB", Eb, Gb, XX }, - { "addS", Ev, Gv, XX }, - { "addB", Gb, Eb, XX }, - { "addS", Gv, Ev, XX }, - { "addB", AL, Ib, XX }, - { "addS", eAX, Iv, XX }, - { "push{T|}", es, XX, XX }, - { "pop{T|}", es, XX, XX }, - /* 08 */ - { "orB", Eb, Gb, XX }, - { "orS", Ev, Gv, XX }, - { "orB", Gb, Eb, XX }, - { "orS", Gv, Ev, XX }, - { "orB", AL, Ib, XX }, - { "orS", eAX, Iv, XX }, - { "push{T|}", cs, XX, XX }, - { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */ - /* 10 */ - { "adcB", Eb, Gb, XX }, - { "adcS", Ev, Gv, XX }, - { "adcB", Gb, Eb, XX }, - { "adcS", Gv, Ev, XX }, - { "adcB", AL, Ib, XX }, - { "adcS", eAX, Iv, XX }, - { "push{T|}", ss, XX, XX }, - { "popT|}", ss, XX, XX }, - /* 18 */ - { "sbbB", Eb, Gb, XX }, - { "sbbS", Ev, Gv, XX }, - { "sbbB", Gb, Eb, XX }, - { "sbbS", Gv, Ev, XX }, - { "sbbB", AL, Ib, XX }, - { "sbbS", eAX, Iv, XX }, - { "push{T|}", ds, XX, XX }, - { "pop{T|}", ds, XX, XX }, - /* 20 */ - { "andB", Eb, Gb, XX }, - { "andS", Ev, Gv, XX }, - { "andB", Gb, Eb, XX }, - { "andS", Gv, Ev, XX }, - { "andB", AL, Ib, XX }, - { "andS", eAX, Iv, XX }, - { "(bad)", XX, XX, XX }, /* SEG ES prefix */ - { "daa{|}", XX, XX, XX }, - /* 28 */ - { "subB", Eb, Gb, XX }, - { "subS", Ev, Gv, XX }, - { "subB", Gb, Eb, XX }, - { "subS", Gv, Ev, XX }, - { "subB", AL, Ib, XX }, - { "subS", eAX, Iv, XX }, - { "(bad)", XX, XX, XX }, /* SEG CS prefix */ - { "das{|}", XX, XX, XX }, - /* 30 */ - { "xorB", Eb, Gb, XX }, - { "xorS", Ev, Gv, XX }, - { "xorB", Gb, Eb, XX }, - { "xorS", Gv, Ev, XX }, - { "xorB", AL, Ib, XX }, - { "xorS", eAX, Iv, XX }, - { "(bad)", XX, XX, XX }, /* SEG SS prefix */ - { "aaa{|}", XX, XX, XX }, - /* 38 */ - { "cmpB", Eb, Gb, XX }, - { "cmpS", Ev, Gv, XX }, - { "cmpB", Gb, Eb, XX }, - { "cmpS", Gv, Ev, XX }, - { "cmpB", AL, Ib, XX }, - { "cmpS", eAX, Iv, XX }, - { "(bad)", XX, XX, XX }, /* SEG DS prefix */ - { "aas{|}", XX, XX, XX }, - /* 40 */ - { "inc{S|}", RMeAX, XX, XX }, - { "inc{S|}", RMeCX, XX, XX }, - { "inc{S|}", RMeDX, XX, XX }, - { "inc{S|}", RMeBX, XX, XX }, - { "inc{S|}", RMeSP, XX, XX }, - { "inc{S|}", RMeBP, XX, XX }, - { "inc{S|}", RMeSI, XX, XX }, - { "inc{S|}", RMeDI, XX, XX }, - /* 48 */ - { "dec{S|}", RMeAX, XX, XX }, - { "dec{S|}", RMeCX, XX, XX }, - { "dec{S|}", RMeDX, XX, XX }, - { "dec{S|}", RMeBX, XX, XX }, - { "dec{S|}", RMeSP, XX, XX }, - { "dec{S|}", RMeBP, XX, XX }, - { "dec{S|}", RMeSI, XX, XX }, - { "dec{S|}", RMeDI, XX, XX }, - /* 50 */ - { "pushS", RMrAX, XX, XX }, - { "pushS", RMrCX, XX, XX }, - { "pushS", RMrDX, XX, XX }, - { "pushS", RMrBX, XX, XX }, - { "pushS", RMrSP, XX, XX }, - { "pushS", RMrBP, XX, XX }, - { "pushS", RMrSI, XX, XX }, - { "pushS", RMrDI, XX, XX }, - /* 58 */ - { "popS", RMrAX, XX, XX }, - { "popS", RMrCX, XX, XX }, - { "popS", RMrDX, XX, XX }, - { "popS", RMrBX, XX, XX }, - { "popS", RMrSP, XX, XX }, - { "popS", RMrBP, XX, XX }, - { "popS", RMrSI, XX, XX }, - { "popS", RMrDI, XX, XX }, - /* 60 */ - { "pusha{P|}", XX, XX, XX }, - { "popa{P|}", XX, XX, XX }, - { "bound{S|}", Gv, Ma, XX }, - { X86_64_0 }, - { "(bad)", XX, XX, XX }, /* seg fs */ - { "(bad)", XX, XX, XX }, /* seg gs */ - { "(bad)", XX, XX, XX }, /* op size prefix */ - { "(bad)", XX, XX, XX }, /* adr size prefix */ - /* 68 */ - { "pushT", Iq, XX, XX }, - { "imulS", Gv, Ev, Iv }, - { "pushT", sIb, XX, XX }, - { "imulS", Gv, Ev, sIb }, - { "ins{b||b|}", Yb, indirDX, XX }, - { "ins{R||R|}", Yv, indirDX, XX }, - { "outs{b||b|}", indirDX, Xb, XX }, - { "outs{R||R|}", indirDX, Xv, XX }, - /* 70 */ - { "joH", Jb, XX, cond_jump_flag }, - { "jnoH", Jb, XX, cond_jump_flag }, - { "jbH", Jb, XX, cond_jump_flag }, - { "jaeH", Jb, XX, cond_jump_flag }, - { "jeH", Jb, XX, cond_jump_flag }, - { "jneH", Jb, XX, cond_jump_flag }, - { "jbeH", Jb, XX, cond_jump_flag }, - { "jaH", Jb, XX, cond_jump_flag }, - /* 78 */ - { "jsH", Jb, XX, cond_jump_flag }, - { "jnsH", Jb, XX, cond_jump_flag }, - { "jpH", Jb, XX, cond_jump_flag }, - { "jnpH", Jb, XX, cond_jump_flag }, - { "jlH", Jb, XX, cond_jump_flag }, - { "jgeH", Jb, XX, cond_jump_flag }, - { "jleH", Jb, XX, cond_jump_flag }, - { "jgH", Jb, XX, cond_jump_flag }, - /* 80 */ - { GRP1b }, - { GRP1S }, - { "(bad)", XX, XX, XX }, - { GRP1Ss }, - { "testB", Eb, Gb, XX }, - { "testS", Ev, Gv, XX }, - { "xchgB", Eb, Gb, XX }, - { "xchgS", Ev, Gv, XX }, - /* 88 */ - { "movB", Eb, Gb, XX }, - { "movS", Ev, Gv, XX }, - { "movB", Gb, Eb, XX }, - { "movS", Gv, Ev, XX }, - { "movQ", Ev, Sw, XX }, - { "leaS", Gv, M, XX }, - { "movQ", Sw, Ev, XX }, - { "popU", Ev, XX, XX }, - /* 90 */ - { "nop", XX, XX, XX }, - /* FIXME: NOP with REPz prefix is called PAUSE. */ - { "xchgS", RMeCX, eAX, XX }, - { "xchgS", RMeDX, eAX, XX }, - { "xchgS", RMeBX, eAX, XX }, - { "xchgS", RMeSP, eAX, XX }, - { "xchgS", RMeBP, eAX, XX }, - { "xchgS", RMeSI, eAX, XX }, - { "xchgS", RMeDI, eAX, XX }, - /* 98 */ - { "cW{tR||tR|}", XX, XX, XX }, - { "cR{tO||tO|}", XX, XX, XX }, - { "lcall{T|}", Ap, XX, XX }, - { "(bad)", XX, XX, XX }, /* fwait */ - { "pushfT", XX, XX, XX }, - { "popfT", XX, XX, XX }, - { "sahf{|}", XX, XX, XX }, - { "lahf{|}", XX, XX, XX }, - /* a0 */ - { "movB", AL, Ob64, XX }, - { "movS", eAX, Ov64, XX }, - { "movB", Ob64, AL, XX }, - { "movS", Ov64, eAX, XX }, - { "movs{b||b|}", Yb, Xb, XX }, - { "movs{R||R|}", Yv, Xv, XX }, - { "cmps{b||b|}", Xb, Yb, XX }, - { "cmps{R||R|}", Xv, Yv, XX }, - /* a8 */ - { "testB", AL, Ib, XX }, - { "testS", eAX, Iv, XX }, - { "stosB", Yb, AL, XX }, - { "stosS", Yv, eAX, XX }, - { "lodsB", AL, Xb, XX }, - { "lodsS", eAX, Xv, XX }, - { "scasB", AL, Yb, XX }, - { "scasS", eAX, Yv, XX }, - /* b0 */ - { "movB", RMAL, Ib, XX }, - { "movB", RMCL, Ib, XX }, - { "movB", RMDL, Ib, XX }, - { "movB", RMBL, Ib, XX }, - { "movB", RMAH, Ib, XX }, - { "movB", RMCH, Ib, XX }, - { "movB", RMDH, Ib, XX }, - { "movB", RMBH, Ib, XX }, - /* b8 */ - { "movS", RMeAX, Iv64, XX }, - { "movS", RMeCX, Iv64, XX }, - { "movS", RMeDX, Iv64, XX }, - { "movS", RMeBX, Iv64, XX }, - { "movS", RMeSP, Iv64, XX }, - { "movS", RMeBP, Iv64, XX }, - { "movS", RMeSI, Iv64, XX }, - { "movS", RMeDI, Iv64, XX }, - /* c0 */ - { GRP2b }, - { GRP2S }, - { "retT", Iw, XX, XX }, - { "retT", XX, XX, XX }, - { "les{S|}", Gv, Mp, XX }, - { "ldsS", Gv, Mp, XX }, - { "movA", Eb, Ib, XX }, - { "movQ", Ev, Iv, XX }, - /* c8 */ - { "enterT", Iw, Ib, XX }, - { "leaveT", XX, XX, XX }, - { "lretP", Iw, XX, XX }, - { "lretP", XX, XX, XX }, - { "int3", XX, XX, XX }, - { "int", Ib, XX, XX }, - { "into{|}", XX, XX, XX }, - { "iretP", XX, XX, XX }, - /* d0 */ - { GRP2b_one }, - { GRP2S_one }, - { GRP2b_cl }, - { GRP2S_cl }, - { "aam{|}", sIb, XX, XX }, - { "aad{|}", sIb, XX, XX }, - { "(bad)", XX, XX, XX }, - { "xlat", DSBX, XX, XX }, - /* d8 */ - { FLOAT }, - { FLOAT }, - { FLOAT }, - { FLOAT }, - { FLOAT }, - { FLOAT }, - { FLOAT }, - { FLOAT }, - /* e0 */ - { "loopneFH", Jb, XX, loop_jcxz_flag }, - { "loopeFH", Jb, XX, loop_jcxz_flag }, - { "loopFH", Jb, XX, loop_jcxz_flag }, - { "jEcxzH", Jb, XX, loop_jcxz_flag }, - { "inB", AL, Ib, XX }, - { "inS", eAX, Ib, XX }, - { "outB", Ib, AL, XX }, - { "outS", Ib, eAX, XX }, - /* e8 */ - { "callT", Jv, XX, XX }, - { "jmpT", Jv, XX, XX }, - { "ljmp{T|}", Ap, XX, XX }, - { "jmp", Jb, XX, XX }, - { "inB", AL, indirDX, XX }, - { "inS", eAX, indirDX, XX }, - { "outB", indirDX, AL, XX }, - { "outS", indirDX, eAX, XX }, - /* f0 */ - { "(bad)", XX, XX, XX }, /* lock prefix */ - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, /* repne */ - { "(bad)", XX, XX, XX }, /* repz */ - { "hlt", XX, XX, XX }, - { "cmc", XX, XX, XX }, - { GRP3b }, - { GRP3S }, - /* f8 */ - { "clc", XX, XX, XX }, - { "stc", XX, XX, XX }, - { "cli", XX, XX, XX }, - { "sti", XX, XX, XX }, - { "cld", XX, XX, XX }, - { "std", XX, XX, XX }, - { GRP4 }, - { GRP5 }, -}; - -static const struct dis386 dis386_twobyte[] = { - /* 00 */ - { GRP6 }, - { GRP7 }, - { "larS", Gv, Ew, XX }, - { "lslS", Gv, Ew, XX }, - { "(bad)", XX, XX, XX }, - { "syscall", XX, XX, XX }, - { "clts", XX, XX, XX }, - { "sysretP", XX, XX, XX }, - /* 08 */ - { "invd", XX, XX, XX }, - { "wbinvd", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "ud2a", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { GRPAMD }, - { "femms", XX, XX, XX }, - { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix. */ - /* 10 */ - { PREGRP8 }, - { PREGRP9 }, - { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */ - { "movlpX", EX, XM, SIMD_Fixup, 'h' }, - { "unpcklpX", XM, EX, XX }, - { "unpckhpX", XM, EX, XX }, - { "movhpX", XM, EX, SIMD_Fixup, 'l' }, - { "movhpX", EX, XM, SIMD_Fixup, 'l' }, - /* 18 */ - { GRP14 }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - /* 20 */ - { "movL", Rm, Cm, XX }, - { "movL", Rm, Dm, XX }, - { "movL", Cm, Rm, XX }, - { "movL", Dm, Rm, XX }, - { "movL", Rd, Td, XX }, - { "(bad)", XX, XX, XX }, - { "movL", Td, Rd, XX }, - { "(bad)", XX, XX, XX }, - /* 28 */ - { "movapX", XM, EX, XX }, - { "movapX", EX, XM, XX }, - { PREGRP2 }, - { "movntpX", Ev, XM, XX }, - { PREGRP4 }, - { PREGRP3 }, - { "ucomisX", XM,EX, XX }, - { "comisX", XM,EX, XX }, - /* 30 */ - { "wrmsr", XX, XX, XX }, - { "rdtsc", XX, XX, XX }, - { "rdmsr", XX, XX, XX }, - { "rdpmc", XX, XX, XX }, - { "sysenter", XX, XX, XX }, - { "sysexit", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - /* 38 */ - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - /* 40 */ - { "cmovo", Gv, Ev, XX }, - { "cmovno", Gv, Ev, XX }, - { "cmovb", Gv, Ev, XX }, - { "cmovae", Gv, Ev, XX }, - { "cmove", Gv, Ev, XX }, - { "cmovne", Gv, Ev, XX }, - { "cmovbe", Gv, Ev, XX }, - { "cmova", Gv, Ev, XX }, - /* 48 */ - { "cmovs", Gv, Ev, XX }, - { "cmovns", Gv, Ev, XX }, - { "cmovp", Gv, Ev, XX }, - { "cmovnp", Gv, Ev, XX }, - { "cmovl", Gv, Ev, XX }, - { "cmovge", Gv, Ev, XX }, - { "cmovle", Gv, Ev, XX }, - { "cmovg", Gv, Ev, XX }, - /* 50 */ - { "movmskpX", Gd, XS, XX }, - { PREGRP13 }, - { PREGRP12 }, - { PREGRP11 }, - { "andpX", XM, EX, XX }, - { "andnpX", XM, EX, XX }, - { "orpX", XM, EX, XX }, - { "xorpX", XM, EX, XX }, - /* 58 */ - { PREGRP0 }, - { PREGRP10 }, - { PREGRP17 }, - { PREGRP16 }, - { PREGRP14 }, - { PREGRP7 }, - { PREGRP5 }, - { PREGRP6 }, - /* 60 */ - { "punpcklbw", MX, EM, XX }, - { "punpcklwd", MX, EM, XX }, - { "punpckldq", MX, EM, XX }, - { "packsswb", MX, EM, XX }, - { "pcmpgtb", MX, EM, XX }, - { "pcmpgtw", MX, EM, XX }, - { "pcmpgtd", MX, EM, XX }, - { "packuswb", MX, EM, XX }, - /* 68 */ - { "punpckhbw", MX, EM, XX }, - { "punpckhwd", MX, EM, XX }, - { "punpckhdq", MX, EM, XX }, - { "packssdw", MX, EM, XX }, - { PREGRP26 }, - { PREGRP24 }, - { "movd", MX, Edq, XX }, - { PREGRP19 }, - /* 70 */ - { PREGRP22 }, - { GRP10 }, - { GRP11 }, - { GRP12 }, - { "pcmpeqb", MX, EM, XX }, - { "pcmpeqw", MX, EM, XX }, - { "pcmpeqd", MX, EM, XX }, - { "emms", XX, XX, XX }, - /* 78 */ - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { PREGRP23 }, - { PREGRP20 }, - /* 80 */ - { "joH", Jv, XX, cond_jump_flag }, - { "jnoH", Jv, XX, cond_jump_flag }, - { "jbH", Jv, XX, cond_jump_flag }, - { "jaeH", Jv, XX, cond_jump_flag }, - { "jeH", Jv, XX, cond_jump_flag }, - { "jneH", Jv, XX, cond_jump_flag }, - { "jbeH", Jv, XX, cond_jump_flag }, - { "jaH", Jv, XX, cond_jump_flag }, - /* 88 */ - { "jsH", Jv, XX, cond_jump_flag }, - { "jnsH", Jv, XX, cond_jump_flag }, - { "jpH", Jv, XX, cond_jump_flag }, - { "jnpH", Jv, XX, cond_jump_flag }, - { "jlH", Jv, XX, cond_jump_flag }, - { "jgeH", Jv, XX, cond_jump_flag }, - { "jleH", Jv, XX, cond_jump_flag }, - { "jgH", Jv, XX, cond_jump_flag }, - /* 90 */ - { "seto", Eb, XX, XX }, - { "setno", Eb, XX, XX }, - { "setb", Eb, XX, XX }, - { "setae", Eb, XX, XX }, - { "sete", Eb, XX, XX }, - { "setne", Eb, XX, XX }, - { "setbe", Eb, XX, XX }, - { "seta", Eb, XX, XX }, - /* 98 */ - { "sets", Eb, XX, XX }, - { "setns", Eb, XX, XX }, - { "setp", Eb, XX, XX }, - { "setnp", Eb, XX, XX }, - { "setl", Eb, XX, XX }, - { "setge", Eb, XX, XX }, - { "setle", Eb, XX, XX }, - { "setg", Eb, XX, XX }, - /* a0 */ - { "pushT", fs, XX, XX }, - { "popT", fs, XX, XX }, - { "cpuid", XX, XX, XX }, - { "btS", Ev, Gv, XX }, - { "shldS", Ev, Gv, Ib }, - { "shldS", Ev, Gv, CL }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - /* a8 */ - { "pushT", gs, XX, XX }, - { "popT", gs, XX, XX }, - { "rsm", XX, XX, XX }, - { "btsS", Ev, Gv, XX }, - { "shrdS", Ev, Gv, Ib }, - { "shrdS", Ev, Gv, CL }, - { GRP13 }, - { "imulS", Gv, Ev, XX }, - /* b0 */ - { "cmpxchgB", Eb, Gb, XX }, - { "cmpxchgS", Ev, Gv, XX }, - { "lssS", Gv, Mp, XX }, - { "btrS", Ev, Gv, XX }, - { "lfsS", Gv, Mp, XX }, - { "lgsS", Gv, Mp, XX }, - { "movz{bR|x|bR|x}", Gv, Eb, XX }, - { "movz{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movzww ! */ - /* b8 */ - { "(bad)", XX, XX, XX }, - { "ud2b", XX, XX, XX }, - { GRP8 }, - { "btcS", Ev, Gv, XX }, - { "bsfS", Gv, Ev, XX }, - { "bsrS", Gv, Ev, XX }, - { "movs{bR|x|bR|x}", Gv, Eb, XX }, - { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */ - /* c0 */ - { "xaddB", Eb, Gb, XX }, - { "xaddS", Ev, Gv, XX }, - { PREGRP1 }, - { "movntiS", Ev, Gv, XX }, - { "pinsrw", MX, Ed, Ib }, - { "pextrw", Gd, MS, Ib }, - { "shufpX", XM, EX, Ib }, - { GRP9 }, - /* c8 */ - { "bswap", RMeAX, XX, XX }, - { "bswap", RMeCX, XX, XX }, - { "bswap", RMeDX, XX, XX }, - { "bswap", RMeBX, XX, XX }, - { "bswap", RMeSP, XX, XX }, - { "bswap", RMeBP, XX, XX }, - { "bswap", RMeSI, XX, XX }, - { "bswap", RMeDI, XX, XX }, - /* d0 */ - { "(bad)", XX, XX, XX }, - { "psrlw", MX, EM, XX }, - { "psrld", MX, EM, XX }, - { "psrlq", MX, EM, XX }, - { "paddq", MX, EM, XX }, - { "pmullw", MX, EM, XX }, - { PREGRP21 }, - { "pmovmskb", Gd, MS, XX }, - /* d8 */ - { "psubusb", MX, EM, XX }, - { "psubusw", MX, EM, XX }, - { "pminub", MX, EM, XX }, - { "pand", MX, EM, XX }, - { "paddusb", MX, EM, XX }, - { "paddusw", MX, EM, XX }, - { "pmaxub", MX, EM, XX }, - { "pandn", MX, EM, XX }, - /* e0 */ - { "pavgb", MX, EM, XX }, - { "psraw", MX, EM, XX }, - { "psrad", MX, EM, XX }, - { "pavgw", MX, EM, XX }, - { "pmulhuw", MX, EM, XX }, - { "pmulhw", MX, EM, XX }, - { PREGRP15 }, - { PREGRP25 }, - /* e8 */ - { "psubsb", MX, EM, XX }, - { "psubsw", MX, EM, XX }, - { "pminsw", MX, EM, XX }, - { "por", MX, EM, XX }, - { "paddsb", MX, EM, XX }, - { "paddsw", MX, EM, XX }, - { "pmaxsw", MX, EM, XX }, - { "pxor", MX, EM, XX }, - /* f0 */ - { "(bad)", XX, XX, XX }, - { "psllw", MX, EM, XX }, - { "pslld", MX, EM, XX }, - { "psllq", MX, EM, XX }, - { "pmuludq", MX, EM, XX }, - { "pmaddwd", MX, EM, XX }, - { "psadbw", MX, EM, XX }, - { PREGRP18 }, - /* f8 */ - { "psubb", MX, EM, XX }, - { "psubw", MX, EM, XX }, - { "psubd", MX, EM, XX }, - { "psubq", MX, EM, XX }, - { "paddb", MX, EM, XX }, - { "paddw", MX, EM, XX }, - { "paddd", MX, EM, XX }, - { "(bad)", XX, XX, XX } -}; - -static const unsigned char onebyte_has_modrm[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */ - /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */ - /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */ - /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ - /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ - /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */ - /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */ - /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */ - /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -static const unsigned char twobyte_has_modrm[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */ - /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */ - /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */ - /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */ - /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */ - /* a0 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* af */ - /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */ - /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */ - /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */ - /* f0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -static const unsigned char twobyte_uses_SSE_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */ - /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -static char obuf[100]; -static char *obufp; -static char scratchbuf[100]; -static unsigned char *start_codep; -static unsigned char *insn_codep; -static unsigned char *codep; -static disassemble_info *the_info; -static int mod; -static int rm; -static int reg; -static unsigned char need_modrm; - -/* If we are accessing mod/rm/reg without need_modrm set, then the - values are stale. Hitting this abort likely indicates that you - need to update onebyte_has_modrm or twobyte_has_modrm. */ -#define MODRM_CHECK if (!need_modrm) abort () - -static const char **names64; -static const char **names32; -static const char **names16; -static const char **names8; -static const char **names8rex; -static const char **names_seg; -static const char **index16; - -static const char *intel_names64[] = { - "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" -}; -static const char *intel_names32[] = { - "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", - "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" -}; -static const char *intel_names16[] = { - "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", - "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" -}; -static const char *intel_names8[] = { - "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", -}; -static const char *intel_names8rex[] = { - "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", - "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" -}; -static const char *intel_names_seg[] = { - "es", "cs", "ss", "ds", "fs", "gs", "?", "?", -}; -static const char *intel_index16[] = { - "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" -}; - -static const char *att_names64[] = { - "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" -}; -static const char *att_names32[] = { - "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", - "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" -}; -static const char *att_names16[] = { - "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", - "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" -}; -static const char *att_names8[] = { - "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", -}; -static const char *att_names8rex[] = { - "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", - "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" -}; -static const char *att_names_seg[] = { - "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?", -}; -static const char *att_index16[] = { - "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx" -}; - -static const struct dis386 grps[][8] = { - /* GRP1b */ - { - { "addA", Eb, Ib, XX }, - { "orA", Eb, Ib, XX }, - { "adcA", Eb, Ib, XX }, - { "sbbA", Eb, Ib, XX }, - { "andA", Eb, Ib, XX }, - { "subA", Eb, Ib, XX }, - { "xorA", Eb, Ib, XX }, - { "cmpA", Eb, Ib, XX } - }, - /* GRP1S */ - { - { "addQ", Ev, Iv, XX }, - { "orQ", Ev, Iv, XX }, - { "adcQ", Ev, Iv, XX }, - { "sbbQ", Ev, Iv, XX }, - { "andQ", Ev, Iv, XX }, - { "subQ", Ev, Iv, XX }, - { "xorQ", Ev, Iv, XX }, - { "cmpQ", Ev, Iv, XX } - }, - /* GRP1Ss */ - { - { "addQ", Ev, sIb, XX }, - { "orQ", Ev, sIb, XX }, - { "adcQ", Ev, sIb, XX }, - { "sbbQ", Ev, sIb, XX }, - { "andQ", Ev, sIb, XX }, - { "subQ", Ev, sIb, XX }, - { "xorQ", Ev, sIb, XX }, - { "cmpQ", Ev, sIb, XX } - }, - /* GRP2b */ - { - { "rolA", Eb, Ib, XX }, - { "rorA", Eb, Ib, XX }, - { "rclA", Eb, Ib, XX }, - { "rcrA", Eb, Ib, XX }, - { "shlA", Eb, Ib, XX }, - { "shrA", Eb, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "sarA", Eb, Ib, XX }, - }, - /* GRP2S */ - { - { "rolQ", Ev, Ib, XX }, - { "rorQ", Ev, Ib, XX }, - { "rclQ", Ev, Ib, XX }, - { "rcrQ", Ev, Ib, XX }, - { "shlQ", Ev, Ib, XX }, - { "shrQ", Ev, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "sarQ", Ev, Ib, XX }, - }, - /* GRP2b_one */ - { - { "rolA", Eb, XX, XX }, - { "rorA", Eb, XX, XX }, - { "rclA", Eb, XX, XX }, - { "rcrA", Eb, XX, XX }, - { "shlA", Eb, XX, XX }, - { "shrA", Eb, XX, XX }, - { "(bad)", XX, XX, XX }, - { "sarA", Eb, XX, XX }, - }, - /* GRP2S_one */ - { - { "rolQ", Ev, XX, XX }, - { "rorQ", Ev, XX, XX }, - { "rclQ", Ev, XX, XX }, - { "rcrQ", Ev, XX, XX }, - { "shlQ", Ev, XX, XX }, - { "shrQ", Ev, XX, XX }, - { "(bad)", XX, XX, XX}, - { "sarQ", Ev, XX, XX }, - }, - /* GRP2b_cl */ - { - { "rolA", Eb, CL, XX }, - { "rorA", Eb, CL, XX }, - { "rclA", Eb, CL, XX }, - { "rcrA", Eb, CL, XX }, - { "shlA", Eb, CL, XX }, - { "shrA", Eb, CL, XX }, - { "(bad)", XX, XX, XX }, - { "sarA", Eb, CL, XX }, - }, - /* GRP2S_cl */ - { - { "rolQ", Ev, CL, XX }, - { "rorQ", Ev, CL, XX }, - { "rclQ", Ev, CL, XX }, - { "rcrQ", Ev, CL, XX }, - { "shlQ", Ev, CL, XX }, - { "shrQ", Ev, CL, XX }, - { "(bad)", XX, XX, XX }, - { "sarQ", Ev, CL, XX } - }, - /* GRP3b */ - { - { "testA", Eb, Ib, XX }, - { "(bad)", Eb, XX, XX }, - { "notA", Eb, XX, XX }, - { "negA", Eb, XX, XX }, - { "mulA", Eb, XX, XX }, /* Don't print the implicit %al register, */ - { "imulA", Eb, XX, XX }, /* to distinguish these opcodes from other */ - { "divA", Eb, XX, XX }, /* mul/imul opcodes. Do the same for div */ - { "idivA", Eb, XX, XX } /* and idiv for consistency. */ - }, - /* GRP3S */ - { - { "testQ", Ev, Iv, XX }, - { "(bad)", XX, XX, XX }, - { "notQ", Ev, XX, XX }, - { "negQ", Ev, XX, XX }, - { "mulQ", Ev, XX, XX }, /* Don't print the implicit register. */ - { "imulQ", Ev, XX, XX }, - { "divQ", Ev, XX, XX }, - { "idivQ", Ev, XX, XX }, - }, - /* GRP4 */ - { - { "incA", Eb, XX, XX }, - { "decA", Eb, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - }, - /* GRP5 */ - { - { "incQ", Ev, XX, XX }, - { "decQ", Ev, XX, XX }, - { "callT", indirEv, XX, XX }, - { "lcallT", indirEv, XX, XX }, - { "jmpT", indirEv, XX, XX }, - { "ljmpT", indirEv, XX, XX }, - { "pushU", Ev, XX, XX }, - { "(bad)", XX, XX, XX }, - }, - /* GRP6 */ - { - { "sldtQ", Ev, XX, XX }, - { "strQ", Ev, XX, XX }, - { "lldt", Ew, XX, XX }, - { "ltr", Ew, XX, XX }, - { "verr", Ew, XX, XX }, - { "verw", Ew, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX } - }, - /* GRP7 */ - { - { "sgdtQ", M, XX, XX }, - { "sidtQ", M, XX, XX }, - { "lgdtQ", M, XX, XX }, - { "lidtQ", M, XX, XX }, - { "smswQ", Ev, XX, XX }, - { "(bad)", XX, XX, XX }, - { "lmsw", Ew, XX, XX }, - { "invlpg", Ew, XX, XX }, - }, - /* GRP8 */ - { - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "btQ", Ev, Ib, XX }, - { "btsQ", Ev, Ib, XX }, - { "btrQ", Ev, Ib, XX }, - { "btcQ", Ev, Ib, XX }, - }, - /* GRP9 */ - { - { "(bad)", XX, XX, XX }, - { "cmpxchg8b", Ev, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - }, - /* GRP10 */ - { - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "psrlw", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "psraw", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "psllw", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - }, - /* GRP11 */ - { - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "psrld", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "psrad", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "pslld", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - }, - /* GRP12 */ - { - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "psrlq", MS, Ib, XX }, - { "psrldq", MS, Ib, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "psllq", MS, Ib, XX }, - { "pslldq", MS, Ib, XX }, - }, - /* GRP13 */ - { - { "fxsave", Ev, XX, XX }, - { "fxrstor", Ev, XX, XX }, - { "ldmxcsr", Ev, XX, XX }, - { "stmxcsr", Ev, XX, XX }, - { "(bad)", XX, XX, XX }, - { "lfence", None, XX, XX }, - { "mfence", None, XX, XX }, - { "sfence", None, XX, XX }, - /* FIXME: the sfence with memory operand is clflush! */ - }, - /* GRP14 */ - { - { "prefetchnta", Ev, XX, XX }, - { "prefetcht0", Ev, XX, XX }, - { "prefetcht1", Ev, XX, XX }, - { "prefetcht2", Ev, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - }, - /* GRPAMD */ - { - { "prefetch", Eb, XX, XX }, - { "prefetchw", Eb, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - } -}; - -static const struct dis386 prefix_user_table[][4] = { - /* PREGRP0 */ - { - { "addps", XM, EX, XX }, - { "addss", XM, EX, XX }, - { "addpd", XM, EX, XX }, - { "addsd", XM, EX, XX }, - }, - /* PREGRP1 */ - { - { "", XM, EX, OPSIMD }, /* See OP_SIMD_SUFFIX. */ - { "", XM, EX, OPSIMD }, - { "", XM, EX, OPSIMD }, - { "", XM, EX, OPSIMD }, - }, - /* PREGRP2 */ - { - { "cvtpi2ps", XM, EM, XX }, - { "cvtsi2ssY", XM, Ev, XX }, - { "cvtpi2pd", XM, EM, XX }, - { "cvtsi2sdY", XM, Ev, XX }, - }, - /* PREGRP3 */ - { - { "cvtps2pi", MX, EX, XX }, - { "cvtss2siY", Gv, EX, XX }, - { "cvtpd2pi", MX, EX, XX }, - { "cvtsd2siY", Gv, EX, XX }, - }, - /* PREGRP4 */ - { - { "cvttps2pi", MX, EX, XX }, - { "cvttss2siY", Gv, EX, XX }, - { "cvttpd2pi", MX, EX, XX }, - { "cvttsd2siY", Gv, EX, XX }, - }, - /* PREGRP5 */ - { - { "divps", XM, EX, XX }, - { "divss", XM, EX, XX }, - { "divpd", XM, EX, XX }, - { "divsd", XM, EX, XX }, - }, - /* PREGRP6 */ - { - { "maxps", XM, EX, XX }, - { "maxss", XM, EX, XX }, - { "maxpd", XM, EX, XX }, - { "maxsd", XM, EX, XX }, - }, - /* PREGRP7 */ - { - { "minps", XM, EX, XX }, - { "minss", XM, EX, XX }, - { "minpd", XM, EX, XX }, - { "minsd", XM, EX, XX }, - }, - /* PREGRP8 */ - { - { "movups", XM, EX, XX }, - { "movss", XM, EX, XX }, - { "movupd", XM, EX, XX }, - { "movsd", XM, EX, XX }, - }, - /* PREGRP9 */ - { - { "movups", EX, XM, XX }, - { "movss", EX, XM, XX }, - { "movupd", EX, XM, XX }, - { "movsd", EX, XM, XX }, - }, - /* PREGRP10 */ - { - { "mulps", XM, EX, XX }, - { "mulss", XM, EX, XX }, - { "mulpd", XM, EX, XX }, - { "mulsd", XM, EX, XX }, - }, - /* PREGRP11 */ - { - { "rcpps", XM, EX, XX }, - { "rcpss", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, - /* PREGRP12 */ - { - { "rsqrtps", XM, EX, XX }, - { "rsqrtss", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, - /* PREGRP13 */ - { - { "sqrtps", XM, EX, XX }, - { "sqrtss", XM, EX, XX }, - { "sqrtpd", XM, EX, XX }, - { "sqrtsd", XM, EX, XX }, - }, - /* PREGRP14 */ - { - { "subps", XM, EX, XX }, - { "subss", XM, EX, XX }, - { "subpd", XM, EX, XX }, - { "subsd", XM, EX, XX }, - }, - /* PREGRP15 */ - { - { "(bad)", XM, EX, XX }, - { "cvtdq2pd", XM, EX, XX }, - { "cvttpd2dq", XM, EX, XX }, - { "cvtpd2dq", XM, EX, XX }, - }, - /* PREGRP16 */ - { - { "cvtdq2ps", XM, EX, XX }, - { "cvttps2dq",XM, EX, XX }, - { "cvtps2dq",XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, - /* PREGRP17 */ - { - { "cvtps2pd", XM, EX, XX }, - { "cvtss2sd", XM, EX, XX }, - { "cvtpd2ps", XM, EX, XX }, - { "cvtsd2ss", XM, EX, XX }, - }, - /* PREGRP18 */ - { - { "maskmovq", MX, MS, XX }, - { "(bad)", XM, EX, XX }, - { "maskmovdqu", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, - /* PREGRP19 */ - { - { "movq", MX, EM, XX }, - { "movdqu", XM, EX, XX }, - { "movdqa", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, - /* PREGRP20 */ - { - { "movq", EM, MX, XX }, - { "movdqu", EX, XM, XX }, - { "movdqa", EX, XM, XX }, - { "(bad)", EX, XM, XX }, - }, - /* PREGRP21 */ - { - { "(bad)", EX, XM, XX }, - { "movq2dq", XM, MS, XX }, - { "movq", EX, XM, XX }, - { "movdq2q", MX, XS, XX }, - }, - /* PREGRP22 */ - { - { "pshufw", MX, EM, Ib }, - { "pshufhw", XM, EX, Ib }, - { "pshufd", XM, EX, Ib }, - { "pshuflw", XM, EX, Ib }, - }, - /* PREGRP23 */ - { - { "movd", Edq, MX, XX }, - { "movq", XM, EX, XX }, - { "movd", Edq, XM, XX }, - { "(bad)", Ed, XM, XX }, - }, - /* PREGRP24 */ - { - { "(bad)", MX, EX, XX }, - { "(bad)", XM, EX, XX }, - { "punpckhqdq", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, - /* PREGRP25 */ - { - { "movntq", Ev, MX, XX }, - { "(bad)", Ev, XM, XX }, - { "movntdq", Ev, XM, XX }, - { "(bad)", Ev, XM, XX }, - }, - /* PREGRP26 */ - { - { "(bad)", MX, EX, XX }, - { "(bad)", XM, EX, XX }, - { "punpcklqdq", XM, EX, XX }, - { "(bad)", XM, EX, XX }, - }, -}; - -static const struct dis386 x86_64_table[][2] = { - { - { "arpl", Ew, Gw, XX }, - { "movs{||lq|xd}", Gv, Ed, XX }, - }, -}; - -#define INTERNAL_DISASSEMBLER_ERROR _("") - -static void -ckprefix () -{ - int newrex; - rex = 0; - prefixes = 0; - used_prefixes = 0; - rex_used = 0; - while (1) - { - FETCH_DATA (the_info, codep + 1); - newrex = 0; - switch (*codep) - { - /* REX prefixes family. */ - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: - if (mode_64bit) - newrex = *codep; - else - return; - break; - case 0xf3: - prefixes |= PREFIX_REPZ; - break; - case 0xf2: - prefixes |= PREFIX_REPNZ; - break; - case 0xf0: - prefixes |= PREFIX_LOCK; - break; - case 0x2e: - prefixes |= PREFIX_CS; - break; - case 0x36: - prefixes |= PREFIX_SS; - break; - case 0x3e: - prefixes |= PREFIX_DS; - break; - case 0x26: - prefixes |= PREFIX_ES; - break; - case 0x64: - prefixes |= PREFIX_FS; - break; - case 0x65: - prefixes |= PREFIX_GS; - break; - case 0x66: - prefixes |= PREFIX_DATA; - break; - case 0x67: - prefixes |= PREFIX_ADDR; - break; - case FWAIT_OPCODE: - /* fwait is really an instruction. If there are prefixes - before the fwait, they belong to the fwait, *not* to the - following instruction. */ - if (prefixes) - { - prefixes |= PREFIX_FWAIT; - codep++; - return; - } - prefixes = PREFIX_FWAIT; - break; - default: - return; - } - /* Rex is ignored when followed by another prefix. */ - if (rex) - { - oappend (prefix_name (rex, 0)); - oappend (" "); - } - rex = newrex; - codep++; - } -} - -/* Return the name of the prefix byte PREF, or NULL if PREF is not a - prefix byte. */ - -static const char * -prefix_name (pref, sizeflag) - int pref; - int sizeflag; -{ - switch (pref) - { - /* REX prefixes family. */ - case 0x40: - return "rex"; - case 0x41: - return "rexZ"; - case 0x42: - return "rexY"; - case 0x43: - return "rexYZ"; - case 0x44: - return "rexX"; - case 0x45: - return "rexXZ"; - case 0x46: - return "rexXY"; - case 0x47: - return "rexXYZ"; - case 0x48: - return "rex64"; - case 0x49: - return "rex64Z"; - case 0x4a: - return "rex64Y"; - case 0x4b: - return "rex64YZ"; - case 0x4c: - return "rex64X"; - case 0x4d: - return "rex64XZ"; - case 0x4e: - return "rex64XY"; - case 0x4f: - return "rex64XYZ"; - case 0xf3: - return "repz"; - case 0xf2: - return "repnz"; - case 0xf0: - return "lock"; - case 0x2e: - return "cs"; - case 0x36: - return "ss"; - case 0x3e: - return "ds"; - case 0x26: - return "es"; - case 0x64: - return "fs"; - case 0x65: - return "gs"; - case 0x66: - return (sizeflag & DFLAG) ? "data16" : "data32"; - case 0x67: - if (mode_64bit) - return (sizeflag & AFLAG) ? "addr32" : "addr64"; - else - return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32"; - case FWAIT_OPCODE: - return "fwait"; - default: - return NULL; - } -} - -static char op1out[100], op2out[100], op3out[100]; -static int op_ad, op_index[3]; -static bfd_vma op_address[3]; -static bfd_vma op_riprel[3]; -static bfd_vma start_pc; - -/* - * On the 386's of 1988, the maximum length of an instruction is 15 bytes. - * (see topic "Redundant prefixes" in the "Differences from 8086" - * section of the "Virtual 8086 Mode" chapter.) - * 'pc' should be the address of this instruction, it will - * be used to print the target address if this is a relative jump or call - * The function returns the length of this instruction in bytes. - */ - -static char intel_syntax; -static char open_char; -static char close_char; -static char separator_char; -static char scale_char; - -/* Here for backwards compatibility. When gdb stops using - print_insn_i386_att and print_insn_i386_intel these functions can - disappear, and print_insn_i386 be merged into print_insn. */ -int -print_insn_i386_att (pc, info) - bfd_vma pc; - disassemble_info *info; -{ - intel_syntax = 0; - - return print_insn (pc, info); -} - -int -print_insn_i386_intel (pc, info) - bfd_vma pc; - disassemble_info *info; -{ - intel_syntax = 1; - - return print_insn (pc, info); -} - -int -print_insn_i386 (pc, info) - bfd_vma pc; - disassemble_info *info; -{ - intel_syntax = -1; - - return print_insn (pc, info); -} - -static int -print_insn (pc, info) - bfd_vma pc; - disassemble_info *info; -{ - const struct dis386 *dp; - int i; - int two_source_ops; - char *first, *second, *third; - int needcomma; - unsigned char uses_SSE_prefix; - int sizeflag; - const char *p; - struct dis_private priv; - - mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax - || info->mach == bfd_mach_x86_64); - - if (intel_syntax == -1) - intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax - || info->mach == bfd_mach_x86_64_intel_syntax); - - if (info->mach == bfd_mach_i386_i386 - || info->mach == bfd_mach_x86_64 - || info->mach == bfd_mach_i386_i386_intel_syntax - || info->mach == bfd_mach_x86_64_intel_syntax) - priv.orig_sizeflag = AFLAG | DFLAG; - else if (info->mach == bfd_mach_i386_i8086) - priv.orig_sizeflag = 0; - else - abort (); - - for (p = info->disassembler_options; p != NULL; ) - { - if (strncmp (p, "x86-64", 6) == 0) - { - mode_64bit = 1; - priv.orig_sizeflag = AFLAG | DFLAG; - } - else if (strncmp (p, "i386", 4) == 0) - { - mode_64bit = 0; - priv.orig_sizeflag = AFLAG | DFLAG; - } - else if (strncmp (p, "i8086", 5) == 0) - { - mode_64bit = 0; - priv.orig_sizeflag = 0; - } - else if (strncmp (p, "intel", 5) == 0) - { - intel_syntax = 1; - } - else if (strncmp (p, "att", 3) == 0) - { - intel_syntax = 0; - } - else if (strncmp (p, "addr", 4) == 0) - { - if (p[4] == '1' && p[5] == '6') - priv.orig_sizeflag &= ~AFLAG; - else if (p[4] == '3' && p[5] == '2') - priv.orig_sizeflag |= AFLAG; - } - else if (strncmp (p, "data", 4) == 0) - { - if (p[4] == '1' && p[5] == '6') - priv.orig_sizeflag &= ~DFLAG; - else if (p[4] == '3' && p[5] == '2') - priv.orig_sizeflag |= DFLAG; - } - else if (strncmp (p, "suffix", 6) == 0) - priv.orig_sizeflag |= SUFFIX_ALWAYS; - - p = strchr (p, ','); - if (p != NULL) - p++; - } - - if (intel_syntax) - { - names64 = intel_names64; - names32 = intel_names32; - names16 = intel_names16; - names8 = intel_names8; - names8rex = intel_names8rex; - names_seg = intel_names_seg; - index16 = intel_index16; - open_char = '['; - close_char = ']'; - separator_char = '+'; - scale_char = '*'; - } - else - { - names64 = att_names64; - names32 = att_names32; - names16 = att_names16; - names8 = att_names8; - names8rex = att_names8rex; - names_seg = att_names_seg; - index16 = att_index16; - open_char = '('; - close_char = ')'; - separator_char = ','; - scale_char = ','; - } - - /* The output looks better if we put 7 bytes on a line, since that - puts most long word instructions on a single line. */ - info->bytes_per_line = 7; - - info->private_data = (PTR) &priv; - priv.max_fetched = priv.the_buffer; - priv.insn_start = pc; - - obuf[0] = 0; - op1out[0] = 0; - op2out[0] = 0; - op3out[0] = 0; - - op_index[0] = op_index[1] = op_index[2] = -1; - - the_info = info; - start_pc = pc; - start_codep = priv.the_buffer; - codep = priv.the_buffer; - - if (setjmp (priv.bailout) != 0) - { - const char *name; - - /* Getting here means we tried for data but didn't get it. That - means we have an incomplete instruction of some sort. Just - print the first byte as a prefix or a .byte pseudo-op. */ - if (codep > priv.the_buffer) - { - name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); - if (name != NULL) - (*info->fprintf_func) (info->stream, "%s", name); - else - { - /* Just print the first byte as a .byte instruction. */ - (*info->fprintf_func) (info->stream, ".byte 0x%x", - (unsigned int) priv.the_buffer[0]); - } - - return 1; - } - - return -1; - } - - obufp = obuf; - ckprefix (); - - insn_codep = codep; - sizeflag = priv.orig_sizeflag; - - FETCH_DATA (info, codep + 1); - two_source_ops = (*codep == 0x62) || (*codep == 0xc8); - - if ((prefixes & PREFIX_FWAIT) - && ((*codep < 0xd8) || (*codep > 0xdf))) - { - const char *name; - - /* fwait not followed by floating point instruction. Print the - first prefix, which is probably fwait itself. */ - name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); - if (name == NULL) - name = INTERNAL_DISASSEMBLER_ERROR; - (*info->fprintf_func) (info->stream, "%s", name); - return 1; - } - - if (*codep == 0x0f) - { - FETCH_DATA (info, codep + 2); - dp = &dis386_twobyte[*++codep]; - need_modrm = twobyte_has_modrm[*codep]; - uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep]; - } - else - { - dp = &dis386[*codep]; - need_modrm = onebyte_has_modrm[*codep]; - uses_SSE_prefix = 0; - } - codep++; - - if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ)) - { - oappend ("repz "); - used_prefixes |= PREFIX_REPZ; - } - if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ)) - { - oappend ("repnz "); - used_prefixes |= PREFIX_REPNZ; - } - if (prefixes & PREFIX_LOCK) - { - oappend ("lock "); - used_prefixes |= PREFIX_LOCK; - } - - if (prefixes & PREFIX_ADDR) - { - sizeflag ^= AFLAG; - if (dp->bytemode3 != loop_jcxz_mode || intel_syntax) - { - if ((sizeflag & AFLAG) || mode_64bit) - oappend ("addr32 "); - else - oappend ("addr16 "); - used_prefixes |= PREFIX_ADDR; - } - } - - if (!uses_SSE_prefix && (prefixes & PREFIX_DATA)) - { - sizeflag ^= DFLAG; - if (dp->bytemode3 == cond_jump_mode - && dp->bytemode1 == v_mode - && !intel_syntax) - { - if (sizeflag & DFLAG) - oappend ("data32 "); - else - oappend ("data16 "); - used_prefixes |= PREFIX_DATA; - } - } - - if (need_modrm) - { - FETCH_DATA (info, codep + 1); - mod = (*codep >> 6) & 3; - reg = (*codep >> 3) & 7; - rm = *codep & 7; - } - - if (dp->name == NULL && dp->bytemode1 == FLOATCODE) - { - dofloat (sizeflag); - } - else - { - int index; - if (dp->name == NULL) - { - switch (dp->bytemode1) - { - case USE_GROUPS: - dp = &grps[dp->bytemode2][reg]; - break; - - case USE_PREFIX_USER_TABLE: - index = 0; - used_prefixes |= (prefixes & PREFIX_REPZ); - if (prefixes & PREFIX_REPZ) - index = 1; - else - { - used_prefixes |= (prefixes & PREFIX_DATA); - if (prefixes & PREFIX_DATA) - index = 2; - else - { - used_prefixes |= (prefixes & PREFIX_REPNZ); - if (prefixes & PREFIX_REPNZ) - index = 3; - } - } - dp = &prefix_user_table[dp->bytemode2][index]; - break; - - case X86_64_SPECIAL: - dp = &x86_64_table[dp->bytemode2][mode_64bit]; - break; - - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - break; - } - } - - if (putop (dp->name, sizeflag) == 0) - { - obufp = op1out; - op_ad = 2; - if (dp->op1) - (*dp->op1) (dp->bytemode1, sizeflag); - - obufp = op2out; - op_ad = 1; - if (dp->op2) - (*dp->op2) (dp->bytemode2, sizeflag); - - obufp = op3out; - op_ad = 0; - if (dp->op3) - (*dp->op3) (dp->bytemode3, sizeflag); - } - } - - /* See if any prefixes were not used. If so, print the first one - separately. If we don't do this, we'll wind up printing an - instruction stream which does not precisely correspond to the - bytes we are disassembling. */ - if ((prefixes & ~used_prefixes) != 0) - { - const char *name; - - name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); - if (name == NULL) - name = INTERNAL_DISASSEMBLER_ERROR; - (*info->fprintf_func) (info->stream, "%s", name); - return 1; - } - if (rex & ~rex_used) - { - const char *name; - name = prefix_name (rex | 0x40, priv.orig_sizeflag); - if (name == NULL) - name = INTERNAL_DISASSEMBLER_ERROR; - (*info->fprintf_func) (info->stream, "%s ", name); - } - - obufp = obuf + strlen (obuf); - for (i = strlen (obuf); i < 6; i++) - oappend (" "); - oappend (" "); - (*info->fprintf_func) (info->stream, "%s", obuf); - - /* The enter and bound instructions are printed with operands in the same - order as the intel book; everything else is printed in reverse order. */ - if (intel_syntax || two_source_ops) - { - first = op1out; - second = op2out; - third = op3out; - op_ad = op_index[0]; - op_index[0] = op_index[2]; - op_index[2] = op_ad; - } - else - { - first = op3out; - second = op2out; - third = op1out; - } - needcomma = 0; - if (*first) - { - if (op_index[0] != -1 && !op_riprel[0]) - (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info); - else - (*info->fprintf_func) (info->stream, "%s", first); - needcomma = 1; - } - if (*second) - { - if (needcomma) - (*info->fprintf_func) (info->stream, ","); - if (op_index[1] != -1 && !op_riprel[1]) - (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info); - else - (*info->fprintf_func) (info->stream, "%s", second); - needcomma = 1; - } - if (*third) - { - if (needcomma) - (*info->fprintf_func) (info->stream, ","); - if (op_index[2] != -1 && !op_riprel[2]) - (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info); - else - (*info->fprintf_func) (info->stream, "%s", third); - } - for (i = 0; i < 3; i++) - if (op_index[i] != -1 && op_riprel[i]) - { - (*info->fprintf_func) (info->stream, " # "); - (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep - + op_address[op_index[i]]), info); - } - return codep - priv.the_buffer; -} - -static const char *float_mem[] = { - /* d8 */ - "fadd{s||s|}", - "fmul{s||s|}", - "fcom{s||s|}", - "fcomp{s||s|}", - "fsub{s||s|}", - "fsubr{s||s|}", - "fdiv{s||s|}", - "fdivr{s||s|}", - /* d9 */ - "fld{s||s|}", - "(bad)", - "fst{s||s|}", - "fstp{s||s|}", - "fldenv", - "fldcw", - "fNstenv", - "fNstcw", - /* da */ - "fiadd{l||l|}", - "fimul{l||l|}", - "ficom{l||l|}", - "ficomp{l||l|}", - "fisub{l||l|}", - "fisubr{l||l|}", - "fidiv{l||l|}", - "fidivr{l||l|}", - /* db */ - "fild{l||l|}", - "(bad)", - "fist{l||l|}", - "fistp{l||l|}", - "(bad)", - "fld{t||t|}", - "(bad)", - "fstp{t||t|}", - /* dc */ - "fadd{l||l|}", - "fmul{l||l|}", - "fcom{l||l|}", - "fcomp{l||l|}", - "fsub{l||l|}", - "fsubr{l||l|}", - "fdiv{l||l|}", - "fdivr{l||l|}", - /* dd */ - "fld{l||l|}", - "(bad)", - "fst{l||l|}", - "fstp{l||l|}", - "frstor", - "(bad)", - "fNsave", - "fNstsw", - /* de */ - "fiadd", - "fimul", - "ficom", - "ficomp", - "fisub", - "fisubr", - "fidiv", - "fidivr", - /* df */ - "fild", - "(bad)", - "fist", - "fistp", - "fbld", - "fild{ll||ll|}", - "fbstp", - "fistpll", -}; - -#define ST OP_ST, 0 -#define STi OP_STi, 0 - -#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0 -#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0 -#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0 -#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0 -#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0 -#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0 -#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0 -#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0 -#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0 - -static const struct dis386 float_reg[][8] = { - /* d8 */ - { - { "fadd", ST, STi, XX }, - { "fmul", ST, STi, XX }, - { "fcom", STi, XX, XX }, - { "fcomp", STi, XX, XX }, - { "fsub", ST, STi, XX }, - { "fsubr", ST, STi, XX }, - { "fdiv", ST, STi, XX }, - { "fdivr", ST, STi, XX }, - }, - /* d9 */ - { - { "fld", STi, XX, XX }, - { "fxch", STi, XX, XX }, - { FGRPd9_2 }, - { "(bad)", XX, XX, XX }, - { FGRPd9_4 }, - { FGRPd9_5 }, - { FGRPd9_6 }, - { FGRPd9_7 }, - }, - /* da */ - { - { "fcmovb", ST, STi, XX }, - { "fcmove", ST, STi, XX }, - { "fcmovbe",ST, STi, XX }, - { "fcmovu", ST, STi, XX }, - { "(bad)", XX, XX, XX }, - { FGRPda_5 }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - }, - /* db */ - { - { "fcmovnb",ST, STi, XX }, - { "fcmovne",ST, STi, XX }, - { "fcmovnbe",ST, STi, XX }, - { "fcmovnu",ST, STi, XX }, - { FGRPdb_4 }, - { "fucomi", ST, STi, XX }, - { "fcomi", ST, STi, XX }, - { "(bad)", XX, XX, XX }, - }, - /* dc */ - { - { "fadd", STi, ST, XX }, - { "fmul", STi, ST, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, -#if UNIXWARE_COMPAT - { "fsub", STi, ST, XX }, - { "fsubr", STi, ST, XX }, - { "fdiv", STi, ST, XX }, - { "fdivr", STi, ST, XX }, -#else - { "fsubr", STi, ST, XX }, - { "fsub", STi, ST, XX }, - { "fdivr", STi, ST, XX }, - { "fdiv", STi, ST, XX }, -#endif - }, - /* dd */ - { - { "ffree", STi, XX, XX }, - { "(bad)", XX, XX, XX }, - { "fst", STi, XX, XX }, - { "fstp", STi, XX, XX }, - { "fucom", STi, XX, XX }, - { "fucomp", STi, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - }, - /* de */ - { - { "faddp", STi, ST, XX }, - { "fmulp", STi, ST, XX }, - { "(bad)", XX, XX, XX }, - { FGRPde_3 }, -#if UNIXWARE_COMPAT - { "fsubp", STi, ST, XX }, - { "fsubrp", STi, ST, XX }, - { "fdivp", STi, ST, XX }, - { "fdivrp", STi, ST, XX }, -#else - { "fsubrp", STi, ST, XX }, - { "fsubp", STi, ST, XX }, - { "fdivrp", STi, ST, XX }, - { "fdivp", STi, ST, XX }, -#endif - }, - /* df */ - { - { "ffreep", STi, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { "(bad)", XX, XX, XX }, - { FGRPdf_4 }, - { "fucomip",ST, STi, XX }, - { "fcomip", ST, STi, XX }, - { "(bad)", XX, XX, XX }, - }, -}; - -static char *fgrps[][8] = { - /* d9_2 0 */ - { - "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", - }, - - /* d9_4 1 */ - { - "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)", - }, - - /* d9_5 2 */ - { - "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)", - }, - - /* d9_6 3 */ - { - "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp", - }, - - /* d9_7 4 */ - { - "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos", - }, - - /* da_5 5 */ - { - "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", - }, - - /* db_4 6 */ - { - "feni(287 only)","fdisi(287 only)","fNclex","fNinit", - "fNsetpm(287 only)","(bad)","(bad)","(bad)", - }, - - /* de_3 7 */ - { - "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", - }, - - /* df_4 8 */ - { - "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", - }, -}; - -static void -dofloat (sizeflag) - int sizeflag; -{ - const struct dis386 *dp; - unsigned char floatop; - - floatop = codep[-1]; - - if (mod != 3) - { - putop (float_mem[(floatop - 0xd8) * 8 + reg], sizeflag); - obufp = op1out; - if (floatop == 0xdb) - OP_E (x_mode, sizeflag); - else if (floatop == 0xdd) - OP_E (d_mode, sizeflag); - else - OP_E (v_mode, sizeflag); - return; - } - /* Skip mod/rm byte. */ - MODRM_CHECK; - codep++; - - dp = &float_reg[floatop - 0xd8][reg]; - if (dp->name == NULL) - { - putop (fgrps[dp->bytemode1][rm], sizeflag); - - /* Instruction fnstsw is only one with strange arg. */ - if (floatop == 0xdf && codep[-1] == 0xe0) - strcpy (op1out, names16[0]); - } - else - { - putop (dp->name, sizeflag); - - obufp = op1out; - if (dp->op1) - (*dp->op1) (dp->bytemode1, sizeflag); - obufp = op2out; - if (dp->op2) - (*dp->op2) (dp->bytemode2, sizeflag); - } -} - -static void -OP_ST (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - oappend ("%st"); -} - -static void -OP_STi (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - sprintf (scratchbuf, "%%st(%d)", rm); - oappend (scratchbuf + intel_syntax); -} - -/* Capital letters in template are macros. */ -static int -putop (template, sizeflag) - const char *template; - int sizeflag; -{ - const char *p; - int alt; - - for (p = template; *p; p++) - { - switch (*p) - { - default: - *obufp++ = *p; - break; - case '{': - alt = 0; - if (intel_syntax) - alt += 1; - if (mode_64bit) - alt += 2; - while (alt != 0) - { - while (*++p != '|') - { - if (*p == '}') - { - /* Alternative not valid. */ - strcpy (obuf, "(bad)"); - obufp = obuf + 5; - return 1; - } - else if (*p == '\0') - abort (); - } - alt--; - } - break; - case '|': - while (*++p != '}') - { - if (*p == '\0') - abort (); - } - break; - case '}': - break; - case 'A': - if (intel_syntax) - break; - if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) - *obufp++ = 'b'; - break; - case 'B': - if (intel_syntax) - break; - if (sizeflag & SUFFIX_ALWAYS) - *obufp++ = 'b'; - break; - case 'E': /* For jcxz/jecxz */ - if (mode_64bit) - { - if (sizeflag & AFLAG) - *obufp++ = 'r'; - else - *obufp++ = 'e'; - } - else - if (sizeflag & AFLAG) - *obufp++ = 'e'; - used_prefixes |= (prefixes & PREFIX_ADDR); - break; - case 'F': - if (intel_syntax) - break; - if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS)) - { - if (sizeflag & AFLAG) - *obufp++ = mode_64bit ? 'q' : 'l'; - else - *obufp++ = mode_64bit ? 'l' : 'w'; - used_prefixes |= (prefixes & PREFIX_ADDR); - } - break; - case 'H': - if (intel_syntax) - break; - if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS - || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS) - { - used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS); - *obufp++ = ','; - *obufp++ = 'p'; - if (prefixes & PREFIX_DS) - *obufp++ = 't'; - else - *obufp++ = 'n'; - } - break; - case 'L': - if (intel_syntax) - break; - if (sizeflag & SUFFIX_ALWAYS) - *obufp++ = 'l'; - break; - case 'N': - if ((prefixes & PREFIX_FWAIT) == 0) - *obufp++ = 'n'; - else - used_prefixes |= PREFIX_FWAIT; - break; - case 'O': - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - *obufp++ = 'o'; - else - *obufp++ = 'd'; - break; - case 'T': - if (intel_syntax) - break; - if (mode_64bit) - { - *obufp++ = 'q'; - break; - } - /* Fall through. */ - case 'P': - if (intel_syntax) - break; - if ((prefixes & PREFIX_DATA) - || (rex & REX_MODE64) - || (sizeflag & SUFFIX_ALWAYS)) - { - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - *obufp++ = 'q'; - else - { - if (sizeflag & DFLAG) - *obufp++ = 'l'; - else - *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); - } - } - break; - case 'U': - if (intel_syntax) - break; - if (mode_64bit) - { - *obufp++ = 'q'; - break; - } - /* Fall through. */ - case 'Q': - if (intel_syntax) - break; - USED_REX (REX_MODE64); - if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) - { - if (rex & REX_MODE64) - *obufp++ = 'q'; - else - { - if (sizeflag & DFLAG) - *obufp++ = 'l'; - else - *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); - } - } - break; - case 'R': - USED_REX (REX_MODE64); - if (intel_syntax) - { - if (rex & REX_MODE64) - { - *obufp++ = 'q'; - *obufp++ = 't'; - } - else if (sizeflag & DFLAG) - { - *obufp++ = 'd'; - *obufp++ = 'q'; - } - else - { - *obufp++ = 'w'; - *obufp++ = 'd'; - } - } - else - { - if (rex & REX_MODE64) - *obufp++ = 'q'; - else if (sizeflag & DFLAG) - *obufp++ = 'l'; - else - *obufp++ = 'w'; - } - if (!(rex & REX_MODE64)) - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case 'S': - if (intel_syntax) - break; - if (sizeflag & SUFFIX_ALWAYS) - { - if (rex & REX_MODE64) - *obufp++ = 'q'; - else - { - if (sizeflag & DFLAG) - *obufp++ = 'l'; - else - *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); - } - } - break; - case 'X': - if (prefixes & PREFIX_DATA) - *obufp++ = 'd'; - else - *obufp++ = 's'; - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case 'Y': - if (intel_syntax) - break; - if (rex & REX_MODE64) - { - USED_REX (REX_MODE64); - *obufp++ = 'q'; - } - break; - /* implicit operand size 'l' for i386 or 'q' for x86-64 */ - case 'W': - /* operand size flag for cwtl, cbtw */ - USED_REX (0); - if (rex) - *obufp++ = 'l'; - else if (sizeflag & DFLAG) - *obufp++ = 'w'; - else - *obufp++ = 'b'; - if (intel_syntax) - { - if (rex) - { - *obufp++ = 'q'; - *obufp++ = 'e'; - } - if (sizeflag & DFLAG) - { - *obufp++ = 'd'; - *obufp++ = 'e'; - } - else - { - *obufp++ = 'w'; - } - } - if (!rex) - used_prefixes |= (prefixes & PREFIX_DATA); - break; - } - } - *obufp = 0; - return 0; -} - -static void -oappend (s) - const char *s; -{ - strcpy (obufp, s); - obufp += strlen (s); -} - -static void -append_seg () -{ - if (prefixes & PREFIX_CS) - { - used_prefixes |= PREFIX_CS; - oappend ("%cs:" + intel_syntax); - } - if (prefixes & PREFIX_DS) - { - used_prefixes |= PREFIX_DS; - oappend ("%ds:" + intel_syntax); - } - if (prefixes & PREFIX_SS) - { - used_prefixes |= PREFIX_SS; - oappend ("%ss:" + intel_syntax); - } - if (prefixes & PREFIX_ES) - { - used_prefixes |= PREFIX_ES; - oappend ("%es:" + intel_syntax); - } - if (prefixes & PREFIX_FS) - { - used_prefixes |= PREFIX_FS; - oappend ("%fs:" + intel_syntax); - } - if (prefixes & PREFIX_GS) - { - used_prefixes |= PREFIX_GS; - oappend ("%gs:" + intel_syntax); - } -} - -static void -OP_indirE (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - if (!intel_syntax) - oappend ("*"); - OP_E (bytemode, sizeflag); -} - -static void -print_operand_value (buf, hex, disp) - char *buf; - int hex; - bfd_vma disp; -{ - if (mode_64bit) - { - if (hex) - { - char tmp[30]; - int i; - buf[0] = '0'; - buf[1] = 'x'; - sprintf_vma (tmp, disp); - for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++); - strcpy (buf + 2, tmp + i); - } - else - { - bfd_signed_vma v = disp; - char tmp[30]; - int i; - if (v < 0) - { - *(buf++) = '-'; - v = -disp; - /* Check for possible overflow on 0x8000000000000000. */ - if (v < 0) - { - strcpy (buf, "9223372036854775808"); - return; - } - } - if (!v) - { - strcpy (buf, "0"); - return; - } - - i = 0; - tmp[29] = 0; - while (v) - { - tmp[28 - i] = (v % 10) + '0'; - v /= 10; - i++; - } - strcpy (buf, tmp + 29 - i); - } - } - else - { - if (hex) - sprintf (buf, "0x%x", (unsigned int) disp); - else - sprintf (buf, "%d", (int) disp); - } -} - -static void -OP_E (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - bfd_vma disp; - int add = 0; - int riprel = 0; - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) - add += 8; - - /* Skip mod/rm byte. */ - MODRM_CHECK; - codep++; - - if (mod == 3) - { - switch (bytemode) - { - case b_mode: - USED_REX (0); - if (rex) - oappend (names8rex[rm + add]); - else - oappend (names8[rm + add]); - break; - case w_mode: - oappend (names16[rm + add]); - break; - case d_mode: - oappend (names32[rm + add]); - break; - case q_mode: - oappend (names64[rm + add]); - break; - case m_mode: - if (mode_64bit) - oappend (names64[rm + add]); - else - oappend (names32[rm + add]); - break; - case v_mode: - case dq_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - oappend (names64[rm + add]); - else if ((sizeflag & DFLAG) || bytemode == dq_mode) - oappend (names32[rm + add]); - else - oappend (names16[rm + add]); - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case 0: - if (!(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */) - && !(codep[-2] == 0xAE && codep[-1] == 0xF0 /* mfence */) - && !(codep[-2] == 0xAE && codep[-1] == 0xe8 /* lfence */)) - BadOp (); /* bad sfence,lea,lds,les,lfs,lgs,lss modrm */ - break; - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - break; - } - return; - } - - disp = 0; - append_seg (); - - if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */ - { - int havesib; - int havebase; - int base; - int index = 0; - int scale = 0; - - havesib = 0; - havebase = 1; - base = rm; - - if (base == 4) - { - havesib = 1; - FETCH_DATA (the_info, codep + 1); - scale = (*codep >> 6) & 3; - index = (*codep >> 3) & 7; - base = *codep & 7; - USED_REX (REX_EXTY); - USED_REX (REX_EXTZ); - if (rex & REX_EXTY) - index += 8; - if (rex & REX_EXTZ) - base += 8; - codep++; - } - - switch (mod) - { - case 0: - if ((base & 7) == 5) - { - havebase = 0; - if (mode_64bit && !havesib && (sizeflag & AFLAG)) - riprel = 1; - disp = get32s (); - } - break; - case 1: - FETCH_DATA (the_info, codep + 1); - disp = *codep++; - if ((disp & 0x80) != 0) - disp -= 0x100; - break; - case 2: - disp = get32s (); - break; - } - - if (!intel_syntax) - if (mod != 0 || (base & 7) == 5) - { - print_operand_value (scratchbuf, !riprel, disp); - oappend (scratchbuf); - if (riprel) - { - set_op (disp, 1); - oappend ("(%rip)"); - } - } - - if (havebase || (havesib && (index != 4 || scale != 0))) - { - if (intel_syntax) - { - switch (bytemode) - { - case b_mode: - oappend ("BYTE PTR "); - break; - case w_mode: - oappend ("WORD PTR "); - break; - case v_mode: - oappend ("DWORD PTR "); - break; - case d_mode: - oappend ("QWORD PTR "); - break; - case m_mode: - if (mode_64bit) - oappend ("DWORD PTR "); - else - oappend ("QWORD PTR "); - break; - case x_mode: - oappend ("XWORD PTR "); - break; - default: - break; - } - } - *obufp++ = open_char; - if (intel_syntax && riprel) - oappend ("rip + "); - *obufp = '\0'; - USED_REX (REX_EXTZ); - if (!havesib && (rex & REX_EXTZ)) - base += 8; - if (havebase) - oappend (mode_64bit && (sizeflag & AFLAG) - ? names64[base] : names32[base]); - if (havesib) - { - if (index != 4) - { - if (intel_syntax) - { - if (havebase) - { - *obufp++ = separator_char; - *obufp = '\0'; - } - sprintf (scratchbuf, "%s", - mode_64bit && (sizeflag & AFLAG) - ? names64[index] : names32[index]); - } - else - sprintf (scratchbuf, ",%s", - mode_64bit && (sizeflag & AFLAG) - ? names64[index] : names32[index]); - oappend (scratchbuf); - } - if (!intel_syntax - || (intel_syntax - && bytemode != b_mode - && bytemode != w_mode - && bytemode != v_mode)) - { - *obufp++ = scale_char; - *obufp = '\0'; - sprintf (scratchbuf, "%d", 1 << scale); - oappend (scratchbuf); - } - } - if (intel_syntax) - if (mod != 0 || (base & 7) == 5) - { - /* Don't print zero displacements. */ - if (disp != 0) - { - if ((bfd_signed_vma) disp > 0) - { - *obufp++ = '+'; - *obufp = '\0'; - } - - print_operand_value (scratchbuf, 0, disp); - oappend (scratchbuf); - } - } - - *obufp++ = close_char; - *obufp = '\0'; - } - else if (intel_syntax) - { - if (mod != 0 || (base & 7) == 5) - { - if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS - | PREFIX_ES | PREFIX_FS | PREFIX_GS)) - ; - else - { - oappend (names_seg[ds_reg - es_reg]); - oappend (":"); - } - print_operand_value (scratchbuf, 1, disp); - oappend (scratchbuf); - } - } - } - else - { /* 16 bit address mode */ - switch (mod) - { - case 0: - if ((rm & 7) == 6) - { - disp = get16 (); - if ((disp & 0x8000) != 0) - disp -= 0x10000; - } - break; - case 1: - FETCH_DATA (the_info, codep + 1); - disp = *codep++; - if ((disp & 0x80) != 0) - disp -= 0x100; - break; - case 2: - disp = get16 (); - if ((disp & 0x8000) != 0) - disp -= 0x10000; - break; - } - - if (!intel_syntax) - if (mod != 0 || (rm & 7) == 6) - { - print_operand_value (scratchbuf, 0, disp); - oappend (scratchbuf); - } - - if (mod != 0 || (rm & 7) != 6) - { - *obufp++ = open_char; - *obufp = '\0'; - oappend (index16[rm + add]); - *obufp++ = close_char; - *obufp = '\0'; - } - } -} - -static void -OP_G (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) - add += 8; - switch (bytemode) - { - case b_mode: - USED_REX (0); - if (rex) - oappend (names8rex[reg + add]); - else - oappend (names8[reg + add]); - break; - case w_mode: - oappend (names16[reg + add]); - break; - case d_mode: - oappend (names32[reg + add]); - break; - case q_mode: - oappend (names64[reg + add]); - break; - case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - oappend (names64[reg + add]); - else if (sizeflag & DFLAG) - oappend (names32[reg + add]); - else - oappend (names16[reg + add]); - used_prefixes |= (prefixes & PREFIX_DATA); - break; - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - break; - } -} - -static bfd_vma -get64 () -{ - bfd_vma x; -#ifdef BFD64 - unsigned int a; - unsigned int b; - - FETCH_DATA (the_info, codep + 8); - a = *codep++ & 0xff; - a |= (*codep++ & 0xff) << 8; - a |= (*codep++ & 0xff) << 16; - a |= (*codep++ & 0xff) << 24; - b = *codep++ & 0xff; - b |= (*codep++ & 0xff) << 8; - b |= (*codep++ & 0xff) << 16; - b |= (*codep++ & 0xff) << 24; - x = a + ((bfd_vma) b << 32); -#else - abort (); - x = 0; -#endif - return x; -} - -static bfd_signed_vma -get32 () -{ - bfd_signed_vma x = 0; - - FETCH_DATA (the_info, codep + 4); - x = *codep++ & (bfd_signed_vma) 0xff; - x |= (*codep++ & (bfd_signed_vma) 0xff) << 8; - x |= (*codep++ & (bfd_signed_vma) 0xff) << 16; - x |= (*codep++ & (bfd_signed_vma) 0xff) << 24; - return x; -} - -static bfd_signed_vma -get32s () -{ - bfd_signed_vma x = 0; - - FETCH_DATA (the_info, codep + 4); - x = *codep++ & (bfd_signed_vma) 0xff; - x |= (*codep++ & (bfd_signed_vma) 0xff) << 8; - x |= (*codep++ & (bfd_signed_vma) 0xff) << 16; - x |= (*codep++ & (bfd_signed_vma) 0xff) << 24; - - x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31); - - return x; -} - -static int -get16 () -{ - int x = 0; - - FETCH_DATA (the_info, codep + 2); - x = *codep++ & 0xff; - x |= (*codep++ & 0xff) << 8; - return x; -} - -static void -set_op (op, riprel) - bfd_vma op; - int riprel; -{ - op_index[op_ad] = op_ad; - if (mode_64bit) - { - op_address[op_ad] = op; - op_riprel[op_ad] = riprel; - } - else - { - /* Mask to get a 32-bit address. */ - op_address[op_ad] = op & 0xffffffff; - op_riprel[op_ad] = riprel & 0xffffffff; - } -} - -static void -OP_REG (code, sizeflag) - int code; - int sizeflag; -{ - const char *s; - int add = 0; - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) - add = 8; - - switch (code) - { - case indir_dx_reg: - if (intel_syntax) - s = "[dx]"; - else - s = "(%dx)"; - break; - case ax_reg: case cx_reg: case dx_reg: case bx_reg: - case sp_reg: case bp_reg: case si_reg: case di_reg: - s = names16[code - ax_reg + add]; - break; - case es_reg: case ss_reg: case cs_reg: - case ds_reg: case fs_reg: case gs_reg: - s = names_seg[code - es_reg + add]; - break; - case al_reg: case ah_reg: case cl_reg: case ch_reg: - case dl_reg: case dh_reg: case bl_reg: case bh_reg: - USED_REX (0); - if (rex) - s = names8rex[code - al_reg + add]; - else - s = names8[code - al_reg]; - break; - case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg: - case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg: - if (mode_64bit) - { - s = names64[code - rAX_reg + add]; - break; - } - code += eAX_reg - rAX_reg; - /* Fall through. */ - case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: - case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - s = names64[code - eAX_reg + add]; - else if (sizeflag & DFLAG) - s = names32[code - eAX_reg + add]; - else - s = names16[code - eAX_reg + add]; - used_prefixes |= (prefixes & PREFIX_DATA); - break; - default: - s = INTERNAL_DISASSEMBLER_ERROR; - break; - } - oappend (s); -} - -static void -OP_IMREG (code, sizeflag) - int code; - int sizeflag; -{ - const char *s; - - switch (code) - { - case indir_dx_reg: - if (intel_syntax) - s = "[dx]"; - else - s = "(%dx)"; - break; - case ax_reg: case cx_reg: case dx_reg: case bx_reg: - case sp_reg: case bp_reg: case si_reg: case di_reg: - s = names16[code - ax_reg]; - break; - case es_reg: case ss_reg: case cs_reg: - case ds_reg: case fs_reg: case gs_reg: - s = names_seg[code - es_reg]; - break; - case al_reg: case ah_reg: case cl_reg: case ch_reg: - case dl_reg: case dh_reg: case bl_reg: case bh_reg: - USED_REX (0); - if (rex) - s = names8rex[code - al_reg]; - else - s = names8[code - al_reg]; - break; - case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: - case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - s = names64[code - eAX_reg]; - else if (sizeflag & DFLAG) - s = names32[code - eAX_reg]; - else - s = names16[code - eAX_reg]; - used_prefixes |= (prefixes & PREFIX_DATA); - break; - default: - s = INTERNAL_DISASSEMBLER_ERROR; - break; - } - oappend (s); -} - -static void -OP_I (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - bfd_signed_vma op; - bfd_signed_vma mask = -1; - - switch (bytemode) - { - case b_mode: - FETCH_DATA (the_info, codep + 1); - op = *codep++; - mask = 0xff; - break; - case q_mode: - if (mode_64bit) - { - op = get32s (); - break; - } - /* Fall through. */ - case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - op = get32s (); - else if (sizeflag & DFLAG) - { - op = get32 (); - mask = 0xffffffff; - } - else - { - op = get16 (); - mask = 0xfffff; - } - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case w_mode: - mask = 0xfffff; - op = get16 (); - break; - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - return; - } - - op &= mask; - scratchbuf[0] = '$'; - print_operand_value (scratchbuf + 1, 1, op); - oappend (scratchbuf + intel_syntax); - scratchbuf[0] = '\0'; -} - -static void -OP_I64 (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - bfd_signed_vma op; - bfd_signed_vma mask = -1; - - if (!mode_64bit) - { - OP_I (bytemode, sizeflag); - return; - } - - switch (bytemode) - { - case b_mode: - FETCH_DATA (the_info, codep + 1); - op = *codep++; - mask = 0xff; - break; - case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - op = get64 (); - else if (sizeflag & DFLAG) - { - op = get32 (); - mask = 0xffffffff; - } - else - { - op = get16 (); - mask = 0xfffff; - } - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case w_mode: - mask = 0xfffff; - op = get16 (); - break; - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - return; - } - - op &= mask; - scratchbuf[0] = '$'; - print_operand_value (scratchbuf + 1, 1, op); - oappend (scratchbuf + intel_syntax); - scratchbuf[0] = '\0'; -} - -static void -OP_sI (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - bfd_signed_vma op; - bfd_signed_vma mask = -1; - - switch (bytemode) - { - case b_mode: - FETCH_DATA (the_info, codep + 1); - op = *codep++; - if ((op & 0x80) != 0) - op -= 0x100; - mask = 0xffffffff; - break; - case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - op = get32s (); - else if (sizeflag & DFLAG) - { - op = get32s (); - mask = 0xffffffff; - } - else - { - mask = 0xffffffff; - op = get16 (); - if ((op & 0x8000) != 0) - op -= 0x10000; - } - used_prefixes |= (prefixes & PREFIX_DATA); - break; - case w_mode: - op = get16 (); - mask = 0xffffffff; - if ((op & 0x8000) != 0) - op -= 0x10000; - break; - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - return; - } - - scratchbuf[0] = '$'; - print_operand_value (scratchbuf + 1, 1, op); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_J (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - bfd_vma disp; - bfd_vma mask = -1; - - switch (bytemode) - { - case b_mode: - FETCH_DATA (the_info, codep + 1); - disp = *codep++; - if ((disp & 0x80) != 0) - disp -= 0x100; - break; - case v_mode: - if (sizeflag & DFLAG) - disp = get32s (); - else - { - disp = get16 (); - /* For some reason, a data16 prefix on a jump instruction - means that the pc is masked to 16 bits after the - displacement is added! */ - mask = 0xffff; - } - break; - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - return; - } - disp = (start_pc + codep - start_codep + disp) & mask; - set_op (disp, 0); - print_operand_value (scratchbuf, 1, disp); - oappend (scratchbuf); -} - -static void -OP_SEG (dummy, sizeflag) - int dummy ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - oappend (names_seg[reg]); -} - -static void -OP_DIR (dummy, sizeflag) - int dummy ATTRIBUTE_UNUSED; - int sizeflag; -{ - int seg, offset; - - if (sizeflag & DFLAG) - { - offset = get32 (); - seg = get16 (); - } - else - { - offset = get16 (); - seg = get16 (); - } - used_prefixes |= (prefixes & PREFIX_DATA); - if (intel_syntax) - sprintf (scratchbuf, "0x%x,0x%x", seg, offset); - else - sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset); - oappend (scratchbuf); -} - -static void -OP_OFF (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag; -{ - bfd_vma off; - - append_seg (); - - if ((sizeflag & AFLAG) || mode_64bit) - off = get32 (); - else - off = get16 (); - - if (intel_syntax) - { - if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS - | PREFIX_ES | PREFIX_FS | PREFIX_GS))) - { - oappend (names_seg[ds_reg - es_reg]); - oappend (":"); - } - } - print_operand_value (scratchbuf, 1, off); - oappend (scratchbuf); -} - -static void -OP_OFF64 (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - bfd_vma off; - - if (!mode_64bit) - { - OP_OFF (bytemode, sizeflag); - return; - } - - append_seg (); - - off = get64 (); - - if (intel_syntax) - { - if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS - | PREFIX_ES | PREFIX_FS | PREFIX_GS))) - { - oappend (names_seg[ds_reg - es_reg]); - oappend (":"); - } - } - print_operand_value (scratchbuf, 1, off); - oappend (scratchbuf); -} - -static void -ptr_reg (code, sizeflag) - int code; - int sizeflag; -{ - const char *s; - if (intel_syntax) - oappend ("["); - else - oappend ("("); - - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - { - if (!(sizeflag & AFLAG)) - s = names32[code - eAX_reg]; - else - s = names64[code - eAX_reg]; - } - else if (sizeflag & AFLAG) - s = names32[code - eAX_reg]; - else - s = names16[code - eAX_reg]; - oappend (s); - if (intel_syntax) - oappend ("]"); - else - oappend (")"); -} - -static void -OP_ESreg (code, sizeflag) - int code; - int sizeflag; -{ - oappend ("%es:" + intel_syntax); - ptr_reg (code, sizeflag); -} - -static void -OP_DSreg (code, sizeflag) - int code; - int sizeflag; -{ - if ((prefixes - & (PREFIX_CS - | PREFIX_DS - | PREFIX_SS - | PREFIX_ES - | PREFIX_FS - | PREFIX_GS)) == 0) - prefixes |= PREFIX_DS; - append_seg (); - ptr_reg (code, sizeflag); -} - -static void -OP_C (dummy, sizeflag) - int dummy ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) - add = 8; - sprintf (scratchbuf, "%%cr%d", reg + add); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_D (dummy, sizeflag) - int dummy ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) - add = 8; - if (intel_syntax) - sprintf (scratchbuf, "db%d", reg + add); - else - sprintf (scratchbuf, "%%db%d", reg + add); - oappend (scratchbuf); -} - -static void -OP_T (dummy, sizeflag) - int dummy ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - sprintf (scratchbuf, "%%tr%d", reg); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_Rd (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - if (mod == 3) - OP_E (bytemode, sizeflag); - else - BadOp (); -} - -static void -OP_MMX (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) - add = 8; - used_prefixes |= (prefixes & PREFIX_DATA); - if (prefixes & PREFIX_DATA) - sprintf (scratchbuf, "%%xmm%d", reg + add); - else - sprintf (scratchbuf, "%%mm%d", reg + add); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_XMM (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) - add = 8; - sprintf (scratchbuf, "%%xmm%d", reg + add); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_EM (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - int add = 0; - if (mod != 3) - { - OP_E (bytemode, sizeflag); - return; - } - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) - add = 8; - - /* Skip mod/rm byte. */ - MODRM_CHECK; - codep++; - used_prefixes |= (prefixes & PREFIX_DATA); - if (prefixes & PREFIX_DATA) - sprintf (scratchbuf, "%%xmm%d", rm + add); - else - sprintf (scratchbuf, "%%mm%d", rm + add); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_EX (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - int add = 0; - if (mod != 3) - { - OP_E (bytemode, sizeflag); - return; - } - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) - add = 8; - - /* Skip mod/rm byte. */ - MODRM_CHECK; - codep++; - sprintf (scratchbuf, "%%xmm%d", rm + add); - oappend (scratchbuf + intel_syntax); -} - -static void -OP_MS (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - if (mod == 3) - OP_EM (bytemode, sizeflag); - else - BadOp (); -} - -static void -OP_XS (bytemode, sizeflag) - int bytemode; - int sizeflag; -{ - if (mod == 3) - OP_EX (bytemode, sizeflag); - else - BadOp (); -} - -static const char *Suffix3DNow[] = { -/* 00 */ NULL, NULL, NULL, NULL, -/* 04 */ NULL, NULL, NULL, NULL, -/* 08 */ NULL, NULL, NULL, NULL, -/* 0C */ "pi2fw", "pi2fd", NULL, NULL, -/* 10 */ NULL, NULL, NULL, NULL, -/* 14 */ NULL, NULL, NULL, NULL, -/* 18 */ NULL, NULL, NULL, NULL, -/* 1C */ "pf2iw", "pf2id", NULL, NULL, -/* 20 */ NULL, NULL, NULL, NULL, -/* 24 */ NULL, NULL, NULL, NULL, -/* 28 */ NULL, NULL, NULL, NULL, -/* 2C */ NULL, NULL, NULL, NULL, -/* 30 */ NULL, NULL, NULL, NULL, -/* 34 */ NULL, NULL, NULL, NULL, -/* 38 */ NULL, NULL, NULL, NULL, -/* 3C */ NULL, NULL, NULL, NULL, -/* 40 */ NULL, NULL, NULL, NULL, -/* 44 */ NULL, NULL, NULL, NULL, -/* 48 */ NULL, NULL, NULL, NULL, -/* 4C */ NULL, NULL, NULL, NULL, -/* 50 */ NULL, NULL, NULL, NULL, -/* 54 */ NULL, NULL, NULL, NULL, -/* 58 */ NULL, NULL, NULL, NULL, -/* 5C */ NULL, NULL, NULL, NULL, -/* 60 */ NULL, NULL, NULL, NULL, -/* 64 */ NULL, NULL, NULL, NULL, -/* 68 */ NULL, NULL, NULL, NULL, -/* 6C */ NULL, NULL, NULL, NULL, -/* 70 */ NULL, NULL, NULL, NULL, -/* 74 */ NULL, NULL, NULL, NULL, -/* 78 */ NULL, NULL, NULL, NULL, -/* 7C */ NULL, NULL, NULL, NULL, -/* 80 */ NULL, NULL, NULL, NULL, -/* 84 */ NULL, NULL, NULL, NULL, -/* 88 */ NULL, NULL, "pfnacc", NULL, -/* 8C */ NULL, NULL, "pfpnacc", NULL, -/* 90 */ "pfcmpge", NULL, NULL, NULL, -/* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt", -/* 98 */ NULL, NULL, "pfsub", NULL, -/* 9C */ NULL, NULL, "pfadd", NULL, -/* A0 */ "pfcmpgt", NULL, NULL, NULL, -/* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1", -/* A8 */ NULL, NULL, "pfsubr", NULL, -/* AC */ NULL, NULL, "pfacc", NULL, -/* B0 */ "pfcmpeq", NULL, NULL, NULL, -/* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw", -/* B8 */ NULL, NULL, NULL, "pswapd", -/* BC */ NULL, NULL, NULL, "pavgusb", -/* C0 */ NULL, NULL, NULL, NULL, -/* C4 */ NULL, NULL, NULL, NULL, -/* C8 */ NULL, NULL, NULL, NULL, -/* CC */ NULL, NULL, NULL, NULL, -/* D0 */ NULL, NULL, NULL, NULL, -/* D4 */ NULL, NULL, NULL, NULL, -/* D8 */ NULL, NULL, NULL, NULL, -/* DC */ NULL, NULL, NULL, NULL, -/* E0 */ NULL, NULL, NULL, NULL, -/* E4 */ NULL, NULL, NULL, NULL, -/* E8 */ NULL, NULL, NULL, NULL, -/* EC */ NULL, NULL, NULL, NULL, -/* F0 */ NULL, NULL, NULL, NULL, -/* F4 */ NULL, NULL, NULL, NULL, -/* F8 */ NULL, NULL, NULL, NULL, -/* FC */ NULL, NULL, NULL, NULL, -}; - -static void -OP_3DNowSuffix (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - const char *mnemonic; - - FETCH_DATA (the_info, codep + 1); - /* AMD 3DNow! instructions are specified by an opcode suffix in the - place where an 8-bit immediate would normally go. ie. the last - byte of the instruction. */ - obufp = obuf + strlen (obuf); - mnemonic = Suffix3DNow[*codep++ & 0xff]; - if (mnemonic) - oappend (mnemonic); - else - { - /* Since a variable sized modrm/sib chunk is between the start - of the opcode (0x0f0f) and the opcode suffix, we need to do - all the modrm processing first, and don't know until now that - we have a bad opcode. This necessitates some cleaning up. */ - op1out[0] = '\0'; - op2out[0] = '\0'; - BadOp (); - } -} - -static const char *simd_cmp_op[] = { - "eq", - "lt", - "le", - "unord", - "neq", - "nlt", - "nle", - "ord" -}; - -static void -OP_SIMD_Suffix (bytemode, sizeflag) - int bytemode ATTRIBUTE_UNUSED; - int sizeflag ATTRIBUTE_UNUSED; -{ - unsigned int cmp_type; - - FETCH_DATA (the_info, codep + 1); - obufp = obuf + strlen (obuf); - cmp_type = *codep++ & 0xff; - if (cmp_type < 8) - { - char suffix1 = 'p', suffix2 = 's'; - used_prefixes |= (prefixes & PREFIX_REPZ); - if (prefixes & PREFIX_REPZ) - suffix1 = 's'; - else - { - used_prefixes |= (prefixes & PREFIX_DATA); - if (prefixes & PREFIX_DATA) - suffix2 = 'd'; - else - { - used_prefixes |= (prefixes & PREFIX_REPNZ); - if (prefixes & PREFIX_REPNZ) - suffix1 = 's', suffix2 = 'd'; - } - } - sprintf (scratchbuf, "cmp%s%c%c", - simd_cmp_op[cmp_type], suffix1, suffix2); - used_prefixes |= (prefixes & PREFIX_REPZ); - oappend (scratchbuf); - } - else - { - /* We have a bad extension byte. Clean up. */ - op1out[0] = '\0'; - op2out[0] = '\0'; - BadOp (); - } -} - -static void -SIMD_Fixup (extrachar, sizeflag) - int extrachar; - int sizeflag ATTRIBUTE_UNUSED; -{ - /* Change movlps/movhps to movhlps/movlhps for 2 register operand - forms of these instructions. */ - if (mod == 3) - { - char *p = obuf + strlen (obuf); - *(p + 1) = '\0'; - *p = *(p - 1); - *(p - 1) = *(p - 2); - *(p - 2) = *(p - 3); - *(p - 3) = extrachar; - } -} - -static void -BadOp (void) -{ - /* Throw away prefixes and 1st. opcode byte. */ - codep = insn_codep + 1; - oappend ("(bad)"); -} diff --git a/cxmon/src/disass/m68k-dis.c b/cxmon/src/disass/m68k-dis.c deleted file mode 100644 index 3e10c8c2..00000000 --- a/cxmon/src/disass/m68k-dis.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* Print Motorola 68k instructions. - Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. - -This file is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include -#include "dis-asm.h" -#include "floatformat.h" -#include "opintl.h" - -#include "m68k.h" - -/* Local function prototypes */ - -static int -fetch_data PARAMS ((struct disassemble_info *, bfd_byte *)); - -static void -dummy_print_address PARAMS ((bfd_vma, struct disassemble_info *)); - -static int -fetch_arg PARAMS ((unsigned char *, int, int, disassemble_info *)); - -static void -print_base PARAMS ((int, bfd_vma, disassemble_info*)); - -static unsigned char * -print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *)); - -static int -print_insn_arg PARAMS ((const char *, unsigned char *, unsigned char *, - bfd_vma, disassemble_info *)); - -CONST char * CONST fpcr_names[] = { - "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr", - "fpiar/fpcr", "fpsr/fpcr", "fpiar/fpsr/fpcr"}; - -static char *const reg_names[] = { - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", - "sr", "pc"}; - -/* Sign-extend an (unsigned char). */ -#if __STDC__ == 1 -#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch)) -#else -#define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128) -#endif - -/* Get a 1 byte signed integer. */ -#define NEXTBYTE(p) (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1])) - -/* Get a 2 byte signed integer. */ -#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000)) -#define NEXTWORD(p) \ - (p += 2, FETCH_DATA (info, p), \ - COERCE16 ((p[-2] << 8) + p[-1])) - -/* Get a 4 byte signed integer. */ -#define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000) -#define NEXTLONG(p) \ - (p += 4, FETCH_DATA (info, p), \ - (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))) - -/* Get a 4 byte unsigned integer. */ -#define NEXTULONG(p) \ - (p += 4, FETCH_DATA (info, p), \ - (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])) - -/* Get a single precision float. */ -#define NEXTSINGLE(val, p) \ - (p += 4, FETCH_DATA (info, p), \ - floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val)) - -/* Get a double precision float. */ -#define NEXTDOUBLE(val, p) \ - (p += 8, FETCH_DATA (info, p), \ - floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val)) - -/* Get an extended precision float. */ -#define NEXTEXTEND(val, p) \ - (p += 12, FETCH_DATA (info, p), \ - floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val)) - -/* Need a function to convert from packed to double - precision. Actually, it's easier to print a - packed number than a double anyway, so maybe - there should be a special case to handle this... */ -#define NEXTPACKED(p) \ - (p += 12, FETCH_DATA (info, p), 0.0) - - -/* Maximum length of an instruction. */ -#define MAXLEN 22 - -#include - -struct private -{ - /* Points to first byte not fetched. */ - bfd_byte *max_fetched; - bfd_byte the_buffer[MAXLEN]; - bfd_vma insn_start; - jmp_buf bailout; -}; - -/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) - to ADDR (exclusive) are valid. Returns 1 for success, longjmps - on error. */ -#define FETCH_DATA(info, addr) \ - ((addr) <= ((struct private *)(info->private_data))->max_fetched \ - ? 1 : fetch_data ((info), (addr))) - -static int -fetch_data (info, addr) - struct disassemble_info *info; - bfd_byte *addr; -{ - int status; - struct private *priv = (struct private *)info->private_data; - bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); - - status = (*info->read_memory_func) (start, - priv->max_fetched, - addr - priv->max_fetched, - info); - if (status != 0) - { - (*info->memory_error_func) (status, start, info); - longjmp (priv->bailout, 1); - } - else - priv->max_fetched = addr; - return 1; -} - -/* This function is used to print to the bit-bucket. */ -static int -#ifdef __STDC__ -dummy_printer (FILE * file, const char * format, ...) -#else -dummy_printer (file) FILE *file; -#endif - { return 0; } - -static void -dummy_print_address (vma, info) - bfd_vma vma; - struct disassemble_info *info; -{ -} - -/* Print the m68k instruction at address MEMADDR in debugged memory, - on INFO->STREAM. Returns length of the instruction, in bytes. */ - -int -print_insn_m68k (memaddr, info) - bfd_vma memaddr; - disassemble_info *info; -{ - register int i; - register unsigned char *p; - unsigned char *save_p; - register const char *d; - register unsigned long bestmask; - const struct m68k_opcode *best = 0; - unsigned int arch_mask; - struct private priv; - bfd_byte *buffer = priv.the_buffer; - fprintf_ftype save_printer = info->fprintf_func; - void (*save_print_address) PARAMS((bfd_vma, struct disassemble_info*)) - = info->print_address_func; - int major_opcode; - static int numopcodes[16]; - static const struct m68k_opcode **opcodes[16]; - - if (!opcodes[0]) - { - /* Speed up the matching by sorting the opcode table on the upper - four bits of the opcode. */ - const struct m68k_opcode **opc_pointer[16]; - - /* First count how many opcodes are in each of the sixteen buckets. */ - for (i = 0; i < m68k_numopcodes; i++) - numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++; - - /* Then create a sorted table of pointers that point into the - unsorted table. */ - opc_pointer[0] = ((const struct m68k_opcode **) - malloc (sizeof (struct m68k_opcode *) - * m68k_numopcodes)); - opcodes[0] = opc_pointer[0]; - for (i = 1; i < 16; i++) - { - opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1]; - opcodes[i] = opc_pointer[i]; - } - - for (i = 0; i < m68k_numopcodes; i++) - *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i]; - - } - - info->private_data = (PTR) &priv; - /* Tell objdump to use two bytes per chunk and six bytes per line for - displaying raw data. */ - info->bytes_per_chunk = 2; - info->bytes_per_line = 6; - info->display_endian = BFD_ENDIAN_BIG; - priv.max_fetched = priv.the_buffer; - priv.insn_start = memaddr; - if (setjmp (priv.bailout) != 0) - /* Error return. */ - return -1; - - switch (info->mach) - { - default: - case 0: - arch_mask = (unsigned int) -1; - break; - case bfd_mach_m68000: - arch_mask = m68000; - break; - case bfd_mach_m68008: - arch_mask = m68008; - break; - case bfd_mach_m68010: - arch_mask = m68010; - break; - case bfd_mach_m68020: - arch_mask = m68020; - break; - case bfd_mach_m68030: - arch_mask = m68030; - break; - case bfd_mach_m68040: - arch_mask = m68040; - break; - case bfd_mach_m68060: - arch_mask = m68060; - break; - } - - arch_mask |= m68881 | m68851; - - bestmask = 0; - FETCH_DATA (info, buffer + 2); - major_opcode = (buffer[0] >> 4) & 15; - for (i = 0; i < numopcodes[major_opcode]; i++) - { - const struct m68k_opcode *opc = opcodes[major_opcode][i]; - unsigned long opcode = opc->opcode; - unsigned long match = opc->match; - - if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24))) - && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16))) - /* Only fetch the next two bytes if we need to. */ - && (((0xffff & match) == 0) - || - (FETCH_DATA (info, buffer + 4) - && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8))) - && ((0xff & buffer[3] & match) == (0xff & opcode))) - ) - && (opc->arch & arch_mask) != 0) - { - /* Don't use for printout the variants of divul and divsl - that have the same register number in two places. - The more general variants will match instead. */ - for (d = opc->args; *d; d += 2) - if (d[1] == 'D') - break; - - /* Don't use for printout the variants of most floating - point coprocessor instructions which use the same - register number in two places, as above. */ - if (*d == '\0') - for (d = opc->args; *d; d += 2) - if (d[1] == 't') - break; - - /* Don't match fmovel with more than one register; wait for - fmoveml. */ - if (*d == '\0') - { - for (d = opc->args; *d; d += 2) - { - if (d[0] == 's' && d[1] == '8') - { - int val; - - val = fetch_arg (buffer, d[1], 3, info); - if ((val & (val - 1)) != 0) - break; - } - } - } - - if (*d == '\0' && match > bestmask) - { - best = opc; - bestmask = match; - } - } - } - - if (best == 0) - goto invalid; - - /* Point at first word of argument data, - and at descriptor for first argument. */ - p = buffer + 2; - - /* Figure out how long the fixed-size portion of the instruction is. - The only place this is stored in the opcode table is - in the arguments--look for arguments which specify fields in the 2nd - or 3rd words of the instruction. */ - for (d = best->args; *d; d += 2) - { - /* I don't think it is necessary to be checking d[0] here; I suspect - all this could be moved to the case statement below. */ - if (d[0] == '#') - { - if (d[1] == 'l' && p - buffer < 6) - p = buffer + 6; - else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' ) - p = buffer + 4; - } - if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4) - p = buffer + 4; - switch (d[1]) - { - case '1': - case '2': - case '3': - case '7': - case '8': - case '9': - case 'i': - if (p - buffer < 4) - p = buffer + 4; - break; - case '4': - case '5': - case '6': - if (p - buffer < 6) - p = buffer + 6; - break; - default: - break; - } - } - - /* pflusha is an exceptions. It takes no arguments but is two words - long. Recognize it by looking at the lower 16 bits of the mask. */ - if (p - buffer < 4 && (best->match & 0xFFFF) != 0) - p = buffer + 4; - - /* lpstop is another exception. It takes a one word argument but is - three words long. */ - if (p - buffer < 6 - && (best->match & 0xffff) == 0xffff - && best->args[0] == '#' - && best->args[1] == 'w') - { - /* Copy the one word argument into the usual location for a one - word argument, to simplify printing it. We can get away with - this because we know exactly what the second word is, and we - aren't going to print anything based on it. */ - p = buffer + 6; - FETCH_DATA (info, p); - buffer[2] = buffer[4]; - buffer[3] = buffer[5]; - } - - FETCH_DATA (info, p); - - d = best->args; - - /* We can the operands twice. The first time we don't print anything, - but look for errors. */ - - save_p = p; - info->print_address_func = dummy_print_address; - info->fprintf_func = (fprintf_ftype)dummy_printer; - for ( ; *d; d += 2) - { - int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info); - if (eaten >= 0) - p += eaten; - else if (eaten == -1) - goto invalid; - else - { - (*info->fprintf_func)(info->stream, - /* xgettext:c-format */ - _("\n"), - best->name, - best->args); - goto invalid; - } - - } - p = save_p; - info->fprintf_func = save_printer; - info->print_address_func = save_print_address; - - d = best->args; - - (*info->fprintf_func) (info->stream, "%s", best->name); - - if (*d) - (*info->fprintf_func) (info->stream, "\t"); - - while (*d) - { - p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info); - d += 2; - if (*d && *(d - 2) != 'I' && *d != 'k') - (*info->fprintf_func) (info->stream, ","); - } - return p - buffer; - -invalid: { - extern void print_68k_invalid_opcode(unsigned long, struct disassemble_info *); - - /* Handle undefined instructions. */ - info->fprintf_func = save_printer; - info->print_address_func = save_print_address; - print_68k_invalid_opcode((buffer[0] << 8) | buffer[1], info); - return 2; - } -} - -/* Returns number of bytes "eaten" by the operand, or - return -1 if an invalid operand was found, or -2 if - an opcode tabe error was found. */ - -static int -print_insn_arg (d, buffer, p0, addr, info) - const char *d; - unsigned char *buffer; - unsigned char *p0; - bfd_vma addr; /* PC for this arg to be relative to */ - disassemble_info *info; -{ - register int val = 0; - register int place = d[1]; - register unsigned char *p = p0; - int regno; - register CONST char *regname; - register unsigned char *p1; - double flval; - int flt_p; - bfd_signed_vma disp; - unsigned int uval; - - switch (*d) - { - case 'c': /* cache identifier */ - { - static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" }; - val = fetch_arg (buffer, place, 2, info); - (*info->fprintf_func) (info->stream, cacheFieldName[val]); - break; - } - - case 'a': /* address register indirect only. Cf. case '+'. */ - { - (*info->fprintf_func) - (info->stream, - "(%s)", - reg_names [fetch_arg (buffer, place, 3, info) + 8]); - break; - } - - case '_': /* 32-bit absolute address for move16. */ - { - uval = NEXTULONG (p); - (*info->print_address_func) (uval, info); - break; - } - - case 'C': - (*info->fprintf_func) (info->stream, "ccr"); - break; - - case 'S': - (*info->fprintf_func) (info->stream, "sr"); - break; - - case 'U': - (*info->fprintf_func) (info->stream, "usp"); - break; - - case 'J': - { - static const struct { char *name; int value; } names[] - = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002}, - {"tc", 0x003}, {"itt0",0x004}, {"itt1", 0x005}, - {"dtt0",0x006}, {"dtt1",0x007}, {"buscr",0x008}, - {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802}, - {"msp", 0x803}, {"isp", 0x804}, - - /* Should we be calling this psr like we do in case 'Y'? */ - {"mmusr",0x805}, - - {"urp", 0x806}, {"srp", 0x807}, {"pcr", 0x808}}; - - val = fetch_arg (buffer, place, 12, info); - for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--) - if (names[regno].value == val) - { - (*info->fprintf_func) (info->stream, "%s", names[regno].name); - break; - } - if (regno < 0) - (*info->fprintf_func) (info->stream, "$%04x", val); - } - break; - - case 'Q': - val = fetch_arg (buffer, place, 3, info); - /* 0 means 8, except for the bkpt instruction... */ - if (val == 0 && d[1] != 's') - val = 8; - (*info->fprintf_func) (info->stream, "#%d", val); - break; - - case 'M': - val = fetch_arg (buffer, place, 8, info); - if (val & 0x80) - val = val - 0x100; - (*info->fprintf_func) (info->stream, "#$%02x", val); - break; - - case 'T': - val = fetch_arg (buffer, place, 4, info); - (*info->fprintf_func) (info->stream, "#$%08x", val); - break; - - case 'D': - (*info->fprintf_func) (info->stream, "%s", - reg_names[fetch_arg (buffer, place, 3, info)]); - break; - - case 'A': - (*info->fprintf_func) - (info->stream, "%s", - reg_names[fetch_arg (buffer, place, 3, info) + 010]); - break; - - case 'R': - (*info->fprintf_func) - (info->stream, "%s", - reg_names[fetch_arg (buffer, place, 4, info)]); - break; - - case 'r': - regno = fetch_arg (buffer, place, 4, info); - (*info->fprintf_func) (info->stream, "(%s)", reg_names[regno]); - break; - - case 'F': - (*info->fprintf_func) - (info->stream, "fp%d", - fetch_arg (buffer, place, 3, info)); - break; - - case 'O': - val = fetch_arg (buffer, place, 6, info); - if (val & 0x20) - (*info->fprintf_func) (info->stream, "%s", reg_names [val & 7]); - else - (*info->fprintf_func) (info->stream, "%d", val); - break; - - case '+': - (*info->fprintf_func) - (info->stream, "(%s)+", - reg_names[fetch_arg (buffer, place, 3, info) + 8]); - break; - - case '-': - (*info->fprintf_func) - (info->stream, "-(%s)", - reg_names[fetch_arg (buffer, place, 3, info) + 8]); - break; - - case 'k': - if (place == 'k') - (*info->fprintf_func) - (info->stream, "{%s}", - reg_names[fetch_arg (buffer, place, 3, info)]); - else if (place == 'C') - { - val = fetch_arg (buffer, place, 7, info); - if ( val > 63 ) /* This is a signed constant. */ - val -= 128; - (*info->fprintf_func) (info->stream, "{#%d}", val); - } - else - return -2; - break; - - case '#': - case '^': - p1 = buffer + (*d == '#' ? 2 : 4); - if (place == 's') - val = fetch_arg (buffer, place, 4, info); - else if (place == 'C') - val = fetch_arg (buffer, place, 7, info); - else if (place == '8') - val = fetch_arg (buffer, place, 3, info); - else if (place == '3') - val = fetch_arg (buffer, place, 8, info); - else if (place == 'b') { - val = NEXTBYTE (p1); - (*info->fprintf_func) (info->stream, "#$%02x", val & 0xff); - break; - } - else if (place == 'w' || place == 'W') { - val = NEXTWORD (p1); - (*info->fprintf_func) (info->stream, "#$%04x", val & 0xffff); - break; - } - else if (place == 'l') { - val = NEXTLONG (p1); - (*info->fprintf_func) (info->stream, "#$%08x", val); - break; - } - else - return -2; - (*info->fprintf_func) (info->stream, "#%d", val); - break; - - case 'B': - if (place == 'b') - disp = NEXTBYTE (p); - else if (place == 'B') - disp = COERCE_SIGNED_CHAR(buffer[1]); - else if (place == 'w' || place == 'W') - disp = NEXTWORD (p); - else if (place == 'l' || place == 'L' || place == 'C') - disp = NEXTLONG (p); - else if (place == 'g') - { - disp = NEXTBYTE (buffer); - if (disp == 0) - disp = NEXTWORD (p); - else if (disp == -1) - disp = NEXTLONG (p); - } - else if (place == 'c') - { - if (buffer[1] & 0x40) /* If bit six is one, long offset */ - disp = NEXTLONG (p); - else - disp = NEXTWORD (p); - } - else - return -2; - - (*info->print_address_func) (addr + disp, info); - break; - - case 'd': - val = NEXTWORD (p); - (*info->fprintf_func) - (info->stream, "($%04x,%s)", - val, reg_names[fetch_arg (buffer, place, 3, info) + 8]); - break; - - case 's': - (*info->fprintf_func) (info->stream, "%s", - fpcr_names[fetch_arg (buffer, place, 3, info)]); - break; - - case 'I': - /* Get coprocessor ID... */ - val = fetch_arg (buffer, 'd', 3, info); - - if (val != 1) /* Unusual coprocessor ID? */ - (*info->fprintf_func) (info->stream, "(cpid=%d) ", val); - break; - - case '*': - case '~': - case '%': - case ';': - case '@': - case '!': - case '$': - case '?': - case '/': - case '&': - case '|': - case '<': - case '>': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'v': - - if (place == 'd') - { - val = fetch_arg (buffer, 'x', 6, info); - val = ((val & 7) << 3) + ((val >> 3) & 7); - } - else - val = fetch_arg (buffer, 's', 6, info); - - /* Get register number assuming address register. */ - regno = (val & 7) + 8; - regname = reg_names[regno]; - switch (val >> 3) - { - case 0: - (*info->fprintf_func) (info->stream, "%s", reg_names[val]); - break; - - case 1: - (*info->fprintf_func) (info->stream, "%s", regname); - break; - - case 2: - (*info->fprintf_func) (info->stream, "(%s)", regname); - break; - - case 3: - (*info->fprintf_func) (info->stream, "(%s)+", regname); - break; - - case 4: - (*info->fprintf_func) (info->stream, "-(%s)", regname); - break; - - case 5: - val = NEXTWORD (p); - (*info->fprintf_func) (info->stream, "($%04x,%s)", val, regname); - break; - - case 6: - p = print_indexed (regno, p, addr, info); - break; - - case 7: - switch (val & 7) - { - case 0: - val = NEXTWORD (p); - (*info->print_address_func) (val, info); - break; - - case 1: - uval = NEXTULONG (p); - (*info->print_address_func) (uval, info); - break; - - case 2: - val = NEXTWORD (p); - (*info->fprintf_func) (info->stream, "("); - (*info->print_address_func) (addr + val, info); - (*info->fprintf_func) (info->stream, ",pc)"); - break; - - case 3: - p = print_indexed (-1, p, addr, info); - break; - - case 4: - switch( place ) - { - case 'b': - val = NEXTBYTE (p); - (*info->fprintf_func) (info->stream, "#$%02x", val & 0xff); - goto imm_printed; - - case 'w': - val = NEXTWORD (p); - (*info->fprintf_func) (info->stream, "#$%04x", val & 0xffff); - goto imm_printed; - - case 'l': - val = NEXTLONG (p); - (*info->fprintf_func) (info->stream, "#$%08x", val); - goto imm_printed; - - case 'f': - NEXTSINGLE(flval, p); - break; - - case 'F': - NEXTDOUBLE(flval, p); - break; - - case 'x': - NEXTEXTEND(flval, p); - break; - - case 'p': - flval = NEXTPACKED(p); - break; - - default: - return -1; - } - (*info->fprintf_func) (info->stream, "#%g", flval); -imm_printed: - break; - - default: - return -1; - } - } - break; - - case 'L': - case 'l': - if (place == 'w') - { - char doneany; - p1 = buffer + 2; - val = NEXTWORD (p1); - /* Move the pointer ahead if this point is farther ahead - than the last. */ - p = p1 > p ? p1 : p; - if (val == 0) - { - (*info->fprintf_func) (info->stream, "#0"); - break; - } - if (*d == 'l') - { - register int newval = 0; - for (regno = 0; regno < 16; ++regno) - if (val & (0x8000 >> regno)) - newval |= 1 << regno; - val = newval; - } - val &= 0xffff; - doneany = 0; - for (regno = 0; regno < 16; ++regno) - if (val & (1 << regno)) - { - int first_regno; - if (doneany) - (*info->fprintf_func) (info->stream, "/"); - doneany = 1; - (*info->fprintf_func) (info->stream, "%s", reg_names[regno]); - first_regno = regno; - while (val & (1 << (regno + 1))) - ++regno; - if (regno > first_regno) - (*info->fprintf_func) (info->stream, "-%s", - reg_names[regno]); - } - } - else if (place == '3') - { - /* `fmovem' insn. */ - char doneany; - val = fetch_arg (buffer, place, 8, info); - if (val == 0) - { - (*info->fprintf_func) (info->stream, "#0"); - break; - } - if (*d == 'l') - { - register int newval = 0; - for (regno = 0; regno < 8; ++regno) - if (val & (0x80 >> regno)) - newval |= 1 << regno; - val = newval; - } - val &= 0xff; - doneany = 0; - for (regno = 0; regno < 8; ++regno) - if (val & (1 << regno)) - { - int first_regno; - if (doneany) - (*info->fprintf_func) (info->stream, "/"); - doneany = 1; - (*info->fprintf_func) (info->stream, "fp%d", regno); - first_regno = regno; - while (val & (1 << (regno + 1))) - ++regno; - if (regno > first_regno) - (*info->fprintf_func) (info->stream, "-fp%d", regno); - } - } - else if (place == '8') - { - /* fmoveml for FP status registers */ - (*info->fprintf_func) (info->stream, "%s", - fpcr_names[fetch_arg (buffer, place, 3, - info)]); - } - else - return -2; - break; - - case 'X': - place = '8'; - case 'Y': - case 'Z': - case 'W': - case '0': - case '1': - case '2': - case '3': - { - int val = fetch_arg (buffer, place, 5, info); - char *name = 0; - switch (val) - { - case 2: name = "tt0"; break; - case 3: name = "tt1"; break; - case 0x10: name = "tc"; break; - case 0x11: name = "drp"; break; - case 0x12: name = "srp"; break; - case 0x13: name = "crp"; break; - case 0x14: name = "cal"; break; - case 0x15: name = "val"; break; - case 0x16: name = "scc"; break; - case 0x17: name = "ac"; break; - case 0x18: name = "psr"; break; - case 0x19: name = "pcsr"; break; - case 0x1c: - case 0x1d: - { - int break_reg = ((buffer[3] >> 2) & 7); - (*info->fprintf_func) - (info->stream, val == 0x1c ? "bad%d" : "bac%d", - break_reg); - } - break; - default: - (*info->fprintf_func) (info->stream, "", val); - } - if (name) - (*info->fprintf_func) (info->stream, "%s", name); - } - break; - - case 'f': - { - int fc = fetch_arg (buffer, place, 5, info); - if (fc == 1) - (*info->fprintf_func) (info->stream, "dfc"); - else if (fc == 0) - (*info->fprintf_func) (info->stream, "sfc"); - else - /* xgettext:c-format */ - (*info->fprintf_func) (info->stream, _(""), fc); - } - break; - - case 'V': - (*info->fprintf_func) (info->stream, "val"); - break; - - case 't': - { - int level = fetch_arg (buffer, place, 3, info); - (*info->fprintf_func) (info->stream, "%d", level); - } - break; - - default: - return -2; - } - - return p - p0; -} - -/* Fetch BITS bits from a position in the instruction specified by CODE. - CODE is a "place to put an argument", or 'x' for a destination - that is a general address (mode and register). - BUFFER contains the instruction. */ - -static int -fetch_arg (buffer, code, bits, info) - unsigned char *buffer; - int code; - int bits; - disassemble_info *info; -{ - register int val = 0; - switch (code) - { - case 's': - val = buffer[1]; - break; - - case 'd': /* Destination, for register or quick. */ - val = (buffer[0] << 8) + buffer[1]; - val >>= 9; - break; - - case 'x': /* Destination, for general arg */ - val = (buffer[0] << 8) + buffer[1]; - val >>= 6; - break; - - case 'k': - FETCH_DATA (info, buffer + 3); - val = (buffer[3] >> 4); - break; - - case 'C': - FETCH_DATA (info, buffer + 3); - val = buffer[3]; - break; - - case '1': - FETCH_DATA (info, buffer + 3); - val = (buffer[2] << 8) + buffer[3]; - val >>= 12; - break; - - case '2': - FETCH_DATA (info, buffer + 3); - val = (buffer[2] << 8) + buffer[3]; - val >>= 6; - break; - - case '3': - case 'j': - FETCH_DATA (info, buffer + 3); - val = (buffer[2] << 8) + buffer[3]; - break; - - case '4': - FETCH_DATA (info, buffer + 5); - val = (buffer[4] << 8) + buffer[5]; - val >>= 12; - break; - - case '5': - FETCH_DATA (info, buffer + 5); - val = (buffer[4] << 8) + buffer[5]; - val >>= 6; - break; - - case '6': - FETCH_DATA (info, buffer + 5); - val = (buffer[4] << 8) + buffer[5]; - break; - - case '7': - FETCH_DATA (info, buffer + 3); - val = (buffer[2] << 8) + buffer[3]; - val >>= 7; - break; - - case '8': - FETCH_DATA (info, buffer + 3); - val = (buffer[2] << 8) + buffer[3]; - val >>= 10; - break; - - case '9': - FETCH_DATA (info, buffer + 3); - val = (buffer[2] << 8) + buffer[3]; - val >>= 5; - break; - - case 'e': - val = (buffer[1] >> 6); - break; - - default: - abort (); - } - - switch (bits) - { - case 2: - return val & 3; - case 3: - return val & 7; - case 4: - return val & 017; - case 5: - return val & 037; - case 6: - return val & 077; - case 7: - return val & 0177; - case 8: - return val & 0377; - case 12: - return val & 07777; - default: - abort (); - } -} - -/* Print an indexed argument. The base register is BASEREG (-1 for pc). - P points to extension word, in buffer. - ADDR is the nominal core address of that extension word. */ - -static unsigned char * -print_indexed (basereg, p, addr, info) - int basereg; - unsigned char *p; - bfd_vma addr; - disassemble_info *info; -{ - register int word; - static char *const scales[] = {"", "*2", "*4", "*8"}; - bfd_vma base_disp; - bfd_vma outer_disp; - char buf[40]; - char vmabuf[50]; - - word = NEXTWORD (p); - - /* Generate the text for the index register. - Where this will be output is not yet determined. */ - sprintf (buf, "%s.%c%s", - reg_names[(word >> 12) & 0xf], - (word & 0x800) ? 'l' : 'w', - scales[(word >> 9) & 3]); - - /* Handle the 68000 style of indexing. */ - - if ((word & 0x100) == 0) - { - base_disp = word & 0xff; - if ((base_disp & 0x80) != 0) - base_disp -= 0x100; - if (basereg == -1) - base_disp += addr; - (*info->fprintf_func) (info->stream, "(", buf); - print_base (basereg, base_disp, info); - (*info->fprintf_func) (info->stream, ",%s)", buf); - return p; - } - - /* Handle the generalized kind. */ - /* First, compute the displacement to add to the base register. */ - - if (word & 0200) - { - if (basereg == -1) - basereg = -3; - else - basereg = -2; - } - if (word & 0100) - buf[0] = '\0'; - base_disp = 0; - switch ((word >> 4) & 3) - { - case 2: - base_disp = NEXTWORD (p); - break; - case 3: - base_disp = NEXTLONG (p); - } - if (basereg == -1) - base_disp += addr; - - /* Handle single-level case (not indirect) */ - - if ((word & 7) == 0) - { - (*info->fprintf_func) (info->stream, "("); - print_base (basereg, base_disp, info); - if (buf[0] != '\0') - (*info->fprintf_func) (info->stream, ",%s", buf); - (*info->fprintf_func) (info->stream, ")"); - return p; - } - - /* Two level. Compute displacement to add after indirection. */ - - outer_disp = 0; - switch (word & 3) - { - case 2: - outer_disp = NEXTWORD (p); - break; - case 3: - outer_disp = NEXTLONG (p); - } - - (*info->fprintf_func) (info->stream, "(["); - print_base (basereg, base_disp, info); - if ((word & 4) == 0 && buf[0] != '\0') - { - (*info->fprintf_func) (info->stream, ",%s", buf); - buf[0] = '\0'; - } - if (outer_disp) - (*info->fprintf_func) (info->stream, "],$%08x", (uint32)outer_disp); - else - (*info->fprintf_func) (info->stream, "]"); - if (buf[0] != '\0') - (*info->fprintf_func) (info->stream, ",%s", buf); - (*info->fprintf_func) (info->stream, ")"); - - return p; -} - -/* Print a base register REGNO and displacement DISP, on INFO->STREAM. - REGNO = -1 for pc, -2 for none (suppressed). */ - -static void -print_base (regno, disp, info) - int regno; - bfd_vma disp; - disassemble_info *info; -{ - if (regno == -1) { - (*info->print_address_func) (disp, info); - (*info->fprintf_func) (info->stream, ",pc"); - } - else { - if (regno == -3) { - (*info->print_address_func) (disp, info); - (*info->fprintf_func) (info->stream, ",zpc"); - } - else if (regno == -2) - (*info->print_address_func) (disp, info); - else - (*info->fprintf_func) (info->stream, "$%08x,%s", (uint32)disp, reg_names[regno]); - } -} diff --git a/cxmon/src/disass/m68k-opc.c b/cxmon/src/disass/m68k-opc.c deleted file mode 100644 index 751eae60..00000000 --- a/cxmon/src/disass/m68k-opc.c +++ /dev/null @@ -1,2066 +0,0 @@ -/* Opcode table for m680[012346]0/m6888[12]/m68851/mcf5200. - Copyright 1989, 91, 92, 93, 94, 95, 96, 97, 98, 1999 - Free Software Foundation. - -This file is part of GDB, GAS, and the GNU binutils. - -GDB, GAS, and the GNU binutils are free software; you can redistribute -them and/or modify them under the terms of the GNU General Public -License as published by the Free Software Foundation; either version -1, or (at your option) any later version. - -GDB, GAS, and the GNU binutils are distributed in the hope that they -will be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this file; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -#include "ansidecl.h" -#include "m68k.h" - -#define one(x) ((unsigned int) (x) << 16) -#define two(x, y) (((unsigned int) (x) << 16) + (y)) - -/* The assembler requires that all instances of the same mnemonic must - be consecutive. If they aren't, the assembler will bomb at - runtime. */ - -const struct m68k_opcode m68k_opcodes[] = -{ -{"abcd", one(0140400), one(0170770), "DsDd", m68000up }, -{"abcd", one(0140410), one(0170770), "-s-d", m68000up }, - -{"adda.w", one(0150300), one(0170700), "*wAd", m68000up }, -{"adda.l", one(0150700), one(0170700), "*lAd", m68000up | mcf5200 }, - -{"addi.b", one(0003000), one(0177700), "#b$s", m68000up }, -{"addi.w", one(0003100), one(0177700), "#w$s", m68000up }, -{"addi.l", one(0003200), one(0177700), "#l$s", m68000up }, -{"addi.l", one(0003200), one(0177700), "#lDs", mcf5200 }, - -{"addq.b", one(0050000), one(0170700), "Qd$b", m68000up }, -{"addq.w", one(0050100), one(0170700), "Qd%w", m68000up }, -{"addq.l", one(0050200), one(0170700), "Qd%l", m68000up | mcf5200 }, - -/* The add opcode can generate the adda, addi, and addq instructions. */ -{"add.b", one(0050000), one(0170700), "Qd$b", m68000up }, -{"add.b", one(0003000), one(0177700), "#b$s", m68000up }, -{"add.b", one(0150000), one(0170700), ";bDd", m68000up }, -{"add.b", one(0150400), one(0170700), "Dd~b", m68000up }, -{"add.w", one(0050100), one(0170700), "Qd%w", m68000up }, -{"add.w", one(0150300), one(0170700), "*wAd", m68000up }, -{"add.w", one(0003100), one(0177700), "#w$s", m68000up }, -{"add.w", one(0150100), one(0170700), "*wDd", m68000up }, -{"add.w", one(0150500), one(0170700), "Dd~w", m68000up }, -{"add.l", one(0050200), one(0170700), "Qd%l", m68000up | mcf5200 }, -{"add.l", one(0003200), one(0177700), "#l$s", m68000up }, -{"add.l", one(0003200), one(0177700), "#lDs", mcf5200 }, -{"add.l", one(0150700), one(0170700), "*lAd", m68000up | mcf5200 }, -{"add.l", one(0150200), one(0170700), "*lDd", m68000up | mcf5200 }, -{"add.l", one(0150600), one(0170700), "Dd~l", m68000up | mcf5200 }, - -{"addx.b", one(0150400), one(0170770), "DsDd", m68000up }, -{"addx.b", one(0150410), one(0170770), "-s-d", m68000up }, -{"addx.w", one(0150500), one(0170770), "DsDd", m68000up }, -{"addx.w", one(0150510), one(0170770), "-s-d", m68000up }, -{"addx.l", one(0150600), one(0170770), "DsDd", m68000up | mcf5200 }, -{"addx.l", one(0150610), one(0170770), "-s-d", m68000up }, - -{"andi.b", one(0001000), one(0177700), "#b$s", m68000up }, -{"andi.w", one(0001100), one(0177700), "#w$s", m68000up }, -{"andi.l", one(0001200), one(0177700), "#l$s", m68000up }, -{"andi.l", one(0001200), one(0177700), "#lDs", mcf5200 }, -{"andi", one(0001100), one(0177700), "#w$s", m68000up }, -{"andi", one(0001074), one(0177777), "#bCs", m68000up }, -{"andi", one(0001174), one(0177777), "#wSs", m68000up }, - -/* The and opcode can generate the andi instruction. */ -{"and.b", one(0001000), one(0177700), "#b$s", m68000up }, -{"and.b", one(0140000), one(0170700), ";bDd", m68000up }, -{"and.b", one(0140400), one(0170700), "Dd~b", m68000up }, -{"and.w", one(0001100), one(0177700), "#w$s", m68000up }, -{"and.w", one(0140100), one(0170700), ";wDd", m68000up }, -{"and.w", one(0140500), one(0170700), "Dd~w", m68000up }, -{"and.l", one(0001200), one(0177700), "#l$s", m68000up }, -{"and.l", one(0001200), one(0177700), "#lDs", mcf5200 }, -{"and.l", one(0140200), one(0170700), ";lDd", m68000up | mcf5200 }, -{"and.l", one(0140600), one(0170700), "Dd~l", m68000up | mcf5200 }, -{"and", one(0001100), one(0177700), "#w$w", m68000up }, -{"and", one(0001074), one(0177777), "#bCs", m68000up }, -{"and", one(0001174), one(0177777), "#wSs", m68000up }, -{"and", one(0140100), one(0170700), ";wDd", m68000up }, -{"and", one(0140500), one(0170700), "Dd~w", m68000up }, - -{"asl.b", one(0160400), one(0170770), "QdDs", m68000up }, -{"asl.b", one(0160440), one(0170770), "DdDs", m68000up }, -{"asl.w", one(0160500), one(0170770), "QdDs", m68000up }, -{"asl.w", one(0160540), one(0170770), "DdDs", m68000up }, -{"asl.w", one(0160700), one(0177700), "~s", m68000up }, -{"asl.l", one(0160600), one(0170770), "QdDs", m68000up | mcf5200 }, -{"asl.l", one(0160640), one(0170770), "DdDs", m68000up | mcf5200 }, - -{"asr.b", one(0160000), one(0170770), "QdDs", m68000up }, -{"asr.b", one(0160040), one(0170770), "DdDs", m68000up }, -{"asr.w", one(0160100), one(0170770), "QdDs", m68000up }, -{"asr.w", one(0160140), one(0170770), "DdDs", m68000up }, -{"asr.w", one(0160300), one(0177700), "~s", m68000up }, -{"asr.l", one(0160200), one(0170770), "QdDs", m68000up | mcf5200 }, -{"asr.l", one(0160240), one(0170770), "DdDs", m68000up | mcf5200 }, - -{"bhi", one(0061000), one(0177777), "BW", m68000up | mcf5200 }, -{"bls", one(0061400), one(0177777), "BW", m68000up | mcf5200 }, -{"bcc", one(0062000), one(0177777), "BW", m68000up | mcf5200 }, -{"bcs", one(0062400), one(0177777), "BW", m68000up | mcf5200 }, -{"bne", one(0063000), one(0177777), "BW", m68000up | mcf5200 }, -{"beq", one(0063400), one(0177777), "BW", m68000up | mcf5200 }, -{"bvc", one(0064000), one(0177777), "BW", m68000up | mcf5200 }, -{"bvs", one(0064400), one(0177777), "BW", m68000up | mcf5200 }, -{"bpl", one(0065000), one(0177777), "BW", m68000up | mcf5200 }, -{"bmi", one(0065400), one(0177777), "BW", m68000up | mcf5200 }, -{"bge", one(0066000), one(0177777), "BW", m68000up | mcf5200 }, -{"blt", one(0066400), one(0177777), "BW", m68000up | mcf5200 }, -{"bgt", one(0067000), one(0177777), "BW", m68000up | mcf5200 }, -{"ble", one(0067400), one(0177777), "BW", m68000up | mcf5200 }, - -{"bhi.l", one(0061377), one(0177777), "BL", m68020up | cpu32 }, -{"bls.l", one(0061777), one(0177777), "BL", m68020up | cpu32 }, -{"bcc.l", one(0062377), one(0177777), "BL", m68020up | cpu32 }, -{"bcs.l", one(0062777), one(0177777), "BL", m68020up | cpu32 }, -{"bne.l", one(0063377), one(0177777), "BL", m68020up | cpu32 }, -{"beq.l", one(0063777), one(0177777), "BL", m68020up | cpu32 }, -{"bvc.l", one(0064377), one(0177777), "BL", m68020up | cpu32 }, -{"bvs.l", one(0064777), one(0177777), "BL", m68020up | cpu32 }, -{"bpl.l", one(0065377), one(0177777), "BL", m68020up | cpu32 }, -{"bmi.l", one(0065777), one(0177777), "BL", m68020up | cpu32 }, -{"bge.l", one(0066377), one(0177777), "BL", m68020up | cpu32 }, -{"blt.l", one(0066777), one(0177777), "BL", m68020up | cpu32 }, -{"bgt.l", one(0067377), one(0177777), "BL", m68020up | cpu32 }, -{"ble.l", one(0067777), one(0177777), "BL", m68020up | cpu32 }, - -{"bhi.s", one(0061000), one(0177400), "BB", m68000up | mcf5200 }, -{"bls.s", one(0061400), one(0177400), "BB", m68000up | mcf5200 }, -{"bcc.s", one(0062000), one(0177400), "BB", m68000up | mcf5200 }, -{"bcs.s", one(0062400), one(0177400), "BB", m68000up | mcf5200 }, -{"bne.s", one(0063000), one(0177400), "BB", m68000up | mcf5200 }, -{"beq.s", one(0063400), one(0177400), "BB", m68000up | mcf5200 }, -{"bvc.s", one(0064000), one(0177400), "BB", m68000up | mcf5200 }, -{"bvs.s", one(0064400), one(0177400), "BB", m68000up | mcf5200 }, -{"bpl.s", one(0065000), one(0177400), "BB", m68000up | mcf5200 }, -{"bmi.s", one(0065400), one(0177400), "BB", m68000up | mcf5200 }, -{"bge.s", one(0066000), one(0177400), "BB", m68000up | mcf5200 }, -{"blt.s", one(0066400), one(0177400), "BB", m68000up | mcf5200 }, -{"bgt.s", one(0067000), one(0177400), "BB", m68000up | mcf5200 }, -{"ble.s", one(0067400), one(0177400), "BB", m68000up | mcf5200 }, - -{"jhi", one(0061000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jls", one(0061400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jcc", one(0062000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jcs", one(0062400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jne", one(0063000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jeq", one(0063400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jvc", one(0064000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jvs", one(0064400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jpl", one(0065000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jmi", one(0065400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jge", one(0066000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jlt", one(0066400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jgt", one(0067000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jle", one(0067400), one(0177400), "Bg", m68000up | mcf5200 }, - -{"bchg", one(0000500), one(0170700), "Dd$s", m68000up | mcf5200 }, -{"bchg", one(0004100), one(0177700), "#b$s", m68000up }, -{"bchg", one(0004100), one(0177700), "#bqs", mcf5200 }, - -{"bclr", one(0000600), one(0170700), "Dd$s", m68000up }, -{"bclr", one(0000600), one(0170700), "Ddvs", mcf5200 }, -{"bclr", one(0004200), one(0177700), "#b$s", m68000up }, -{"bclr", one(0004200), one(0177700), "#bqs", mcf5200 }, - -{"bfchg", two(0165300, 0), two(0177700, 0170000), "?sO2O3", m68020up }, -{"bfclr", two(0166300, 0), two(0177700, 0170000), "?sO2O3", m68020up }, -{"bfexts", two(0165700, 0), two(0177700, 0100000), "/sO2O3D1", m68020up }, -{"bfextu", two(0164700, 0), two(0177700, 0100000), "/sO2O3D1", m68020up }, -{"bfffo", two(0166700, 0), two(0177700, 0100000), "/sO2O3D1", m68020up }, -{"bfins", two(0167700, 0), two(0177700, 0100000), "D1?sO2O3", m68020up }, -{"bfset", two(0167300, 0), two(0177700, 0170000), "?sO2O3", m68020up }, -{"bftst", two(0164300, 0), two(0177700, 0170000), "/sO2O3", m68020up }, - -{"bgnd", one(0045372), one(0177777), "", cpu32 }, - -{"bkpt", one(0044110), one(0177770), "ts", m68010up }, - -{"bra", one(0060000), one(0177777), "BW", m68000up | mcf5200 }, -{"bra.l", one(0060377), one(0177777), "BL", m68020up | cpu32 }, -{"bra.s", one(0060000), one(0177400), "BB", m68000up | mcf5200 }, - -{"bset", one(0000700), one(0170700), "Dd$s", m68000up }, -{"bset", one(0000700), one(0170700), "Ddvs", mcf5200 }, -{"bset", one(0004300), one(0177700), "#b$s", m68000up }, -{"bset", one(0004300), one(0177700), "#bqs", mcf5200 }, - -{"bsr", one(0060400), one(0177777), "BW", m68000up | mcf5200 }, -{"bsr.l", one(0060777), one(0177777), "BL", m68020up | cpu32 }, -{"bsr.s", one(0060400), one(0177400), "BB", m68000up | mcf5200 }, - -{"btst", one(0000400), one(0170700), "Dd;b", m68000up | mcf5200 }, -{"btst", one(0004000), one(0177700), "#b@s", m68000up }, -{"btst", one(0004000), one(0177700), "#bqs", mcf5200 }, - -{"callm", one(0003300), one(0177700), "#b!s", m68020 }, - -{"cas2.w", two(0006374,0), two(0177777,0007070), "D3D6D2D5r1r4", m68020up }, -{"cas2.w", two(0006374,0), two(0177777,0007070), "D3D6D2D5R1R4", m68020up }, -{"cas2.l", two(0007374,0), two(0177777,0007070), "D3D6D2D5r1r4", m68020up }, -{"cas2.l", two(0007374,0), two(0177777,0007070), "D3D6D2D5R1R4", m68020up }, - -{"cas.b", two(0005300, 0), two(0177700, 0177070), "D3D2~s", m68020up }, -{"cas.w", two(0006300, 0), two(0177700, 0177070), "D3D2~s", m68020up }, -{"cas.l", two(0007300, 0), two(0177700, 0177070), "D3D2~s", m68020up }, - -{"chk2.b", two(0000300,0004000), two(0177700,07777), "!sR1", m68020up | cpu32 }, -{"chk2.w", two(0001300,0004000), two(0177700,07777), "!sR1", m68020up | cpu32 }, -{"chk2.l", two(0002300,0004000), two(0177700,07777), "!sR1", m68020up | cpu32 }, - -{"chk.l", one(0040400), one(0170700), ";lDd", m68000up }, -{"chk.w", one(0040600), one(0170700), ";wDd", m68000up }, - -#define SCOPE_LINE (0x1 << 3) -#define SCOPE_PAGE (0x2 << 3) -#define SCOPE_ALL (0x3 << 3) - -{"cinva", one(0xf400|SCOPE_ALL), one(0xff38), "ce", m68040up }, -{"cinvl", one(0xf400|SCOPE_LINE), one(0xff38), "ceas", m68040up }, -{"cinvp", one(0xf400|SCOPE_PAGE), one(0xff38), "ceas", m68040up }, - -{"cpusha", one(0xf420|SCOPE_ALL), one(0xff38), "ce", m68040up }, -{"cpushl", one(0xf420|SCOPE_LINE), one(0xff38), "ceas", m68040up }, -{"cpushl", one(0x04e8), one(0xfff8), "as", mcf5200 }, -{"cpushp", one(0xf420|SCOPE_PAGE), one(0xff38), "ceas", m68040up }, - -#undef SCOPE_LINE -#undef SCOPE_PAGE -#undef SCOPE_ALL - -{"clr.b", one(0041000), one(0177700), "$s", m68000up | mcf5200 }, -{"clr.w", one(0041100), one(0177700), "$s", m68000up | mcf5200 }, -{"clr.l", one(0041200), one(0177700), "$s", m68000up | mcf5200 }, - -{"cmp2.b", two(0000300,0), two(0177700,07777), "!sR1", m68020up | cpu32 }, -{"cmp2.w", two(0001300,0), two(0177700,07777), "!sR1", m68020up | cpu32 }, -{"cmp2.l", two(0002300,0), two(0177700,07777), "!sR1", m68020up | cpu32 }, - -{"cmpa.w", one(0130300), one(0170700), "*wAd", m68000up }, -{"cmpa.l", one(0130700), one(0170700), "*lAd", m68000up | mcf5200 }, - -{"cmpi.b", one(0006000), one(0177700), "#b;s", m68000up }, -{"cmpi.w", one(0006100), one(0177700), "#w;s", m68000up }, -{"cmpi.l", one(0006200), one(0177700), "#l;s", m68000up }, -{"cmpi.l", one(0006200), one(0177700), "#lDs", mcf5200 }, - -{"cmpm.b", one(0130410), one(0170770), "+s+d", m68000up }, -{"cmpm.w", one(0130510), one(0170770), "+s+d", m68000up }, -{"cmpm.l", one(0130610), one(0170770), "+s+d", m68000up }, - -/* The cmp opcode can generate the cmpa, cmpm, and cmpi instructions. */ -{"cmp.b", one(0006000), one(0177700), "#b;s", m68000up }, -{"cmp.b", one(0130410), one(0170770), "+s+d", m68000up }, -{"cmp.b", one(0130000), one(0170700), ";bDd", m68000up }, -{"cmp.w", one(0130300), one(0170700), "*wAd", m68000up }, -{"cmp.w", one(0006100), one(0177700), "#w;s", m68000up }, -{"cmp.w", one(0130510), one(0170770), "+s+d", m68000up }, -{"cmp.w", one(0130100), one(0170700), "*wDd", m68000up }, -{"cmp.l", one(0130700), one(0170700), "*lAd", m68000up | mcf5200 }, -{"cmp.l", one(0006200), one(0177700), "#l;s", m68000up }, -{"cmp.l", one(0006200), one(0177700), "#lDs", mcf5200 }, -{"cmp.l", one(0130610), one(0170770), "+s+d", m68000up }, -{"cmp.l", one(0130200), one(0170700), "*lDd", m68000up | mcf5200 }, - -{"dbcc", one(0052310), one(0177770), "DsBw", m68000up }, -{"dbcs", one(0052710), one(0177770), "DsBw", m68000up }, -{"dbeq", one(0053710), one(0177770), "DsBw", m68000up }, -{"dbf", one(0050710), one(0177770), "DsBw", m68000up }, -{"dbge", one(0056310), one(0177770), "DsBw", m68000up }, -{"dbgt", one(0057310), one(0177770), "DsBw", m68000up }, -{"dbhi", one(0051310), one(0177770), "DsBw", m68000up }, -{"dble", one(0057710), one(0177770), "DsBw", m68000up }, -{"dbls", one(0051710), one(0177770), "DsBw", m68000up }, -{"dblt", one(0056710), one(0177770), "DsBw", m68000up }, -{"dbmi", one(0055710), one(0177770), "DsBw", m68000up }, -{"dbne", one(0053310), one(0177770), "DsBw", m68000up }, -{"dbpl", one(0055310), one(0177770), "DsBw", m68000up }, -{"dbt", one(0050310), one(0177770), "DsBw", m68000up }, -{"dbvc", one(0054310), one(0177770), "DsBw", m68000up }, -{"dbvs", one(0054710), one(0177770), "DsBw", m68000up }, - -{"divs.w", one(0100700), one(0170700), ";wDd", m68000up }, - -{"divs.l", two(0046100,0006000),two(0177700,0107770),";lD3D1", m68020up|cpu32 }, -{"divs.l", two(0046100,0004000),two(0177700,0107770),";lDD", m68020up|cpu32 }, - -{"divsl.l", two(0046100,0004000),two(0177700,0107770),";lD3D1",m68020up|cpu32 }, -{"divsl.l", two(0046100,0004000),two(0177700,0107770),";lDD", m68020up|cpu32 }, - -{"divu.w", one(0100300), one(0170700), ";wDd", m68000up }, - -{"divu.l", two(0046100,0002000),two(0177700,0107770),";lD3D1", m68020up|cpu32 }, -{"divu.l", two(0046100,0000000),two(0177700,0107770),";lDD", m68020up|cpu32 }, - -{"divul.l", two(0046100,0000000),two(0177700,0107770),";lD3D1",m68020up|cpu32 }, -{"divul.l", two(0046100,0000000),two(0177700,0107770),";lDD", m68020up|cpu32 }, - -{"eori.b", one(0005000), one(0177700), "#b$s", m68000up }, -{"eori.w", one(0005100), one(0177700), "#w$s", m68000up }, -{"eori.l", one(0005200), one(0177700), "#l$s", m68000up }, -{"eori.l", one(0005200), one(0177700), "#lDs", mcf5200 }, -{"eori", one(0005074), one(0177777), "#bCs", m68000up }, -{"eori", one(0005174), one(0177777), "#wSs", m68000up }, -{"eori", one(0005100), one(0177700), "#w$s", m68000up }, - -/* The eor opcode can generate the eori instruction. */ -{"eor.b", one(0005000), one(0177700), "#b$s", m68000up }, -{"eor.b", one(0130400), one(0170700), "Dd$s", m68000up }, -{"eor.w", one(0005100), one(0177700), "#w$s", m68000up }, -{"eor.w", one(0130500), one(0170700), "Dd$s", m68000up }, -{"eor.l", one(0005200), one(0177700), "#l$s", m68000up }, -{"eor.l", one(0005200), one(0177700), "#lDs", mcf5200 }, -{"eor.l", one(0130600), one(0170700), "Dd$s", m68000up | mcf5200 }, -{"eor", one(0005074), one(0177777), "#bCs", m68000up }, -{"eor", one(0005174), one(0177777), "#wSs", m68000up }, -{"eor", one(0005100), one(0177700), "#w$s", m68000up }, -{"eor", one(0130500), one(0170700), "Dd$s", m68000up }, - -{"exg", one(0140500), one(0170770), "DdDs", m68000up }, -{"exg", one(0140510), one(0170770), "AdAs", m68000up }, -{"exg", one(0140610), one(0170770), "DdAs", m68000up }, -{"exg", one(0140610), one(0170770), "AsDd", m68000up }, - -{"ext.w", one(0044200), one(0177770), "Ds", m68000up|mcf5200 }, -{"ext.l", one(0044300), one(0177770), "Ds", m68000up|mcf5200 }, -{"extb.l", one(0044700), one(0177770), "Ds", m68020up|cpu32|mcf5200 }, - -/* float stuff starts here */ - -{"fabs.b", two(0xF000, 0x5818), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fabs.d", two(0xF000, 0x5418), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fabs.l", two(0xF000, 0x4018), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fabs.p", two(0xF000, 0x4C18), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fabs.s", two(0xF000, 0x4418), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fabs.w", two(0xF000, 0x5018), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fabs.x", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fabs.x", two(0xF000, 0x4818), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fabs.x", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fsabs.b", two(0xF000, 0x5858), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fsabs.d", two(0xF000, 0x5458), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fsabs.l", two(0xF000, 0x4058), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fsabs.p", two(0xF000, 0x4C58), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fsabs.s", two(0xF000, 0x4458), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fsabs.w", two(0xF000, 0x5058), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fsabs.x", two(0xF000, 0x0058), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fsabs.x", two(0xF000, 0x4858), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fsabs.x", two(0xF000, 0x0058), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"fdabs.b", two(0xF000, 0x585c), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up}, -{"fdabs.d", two(0xF000, 0x545c), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up}, -{"fdabs.l", two(0xF000, 0x405c), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up}, -{"fdabs.p", two(0xF000, 0x4C5c), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up}, -{"fdabs.s", two(0xF000, 0x445c), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up}, -{"fdabs.w", two(0xF000, 0x505c), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up}, -{"fdabs.x", two(0xF000, 0x005c), two(0xF1C0, 0xE07F), "IiF8F7", m68040up}, -{"fdabs.x", two(0xF000, 0x485c), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up}, -{"fdabs.x", two(0xF000, 0x005c), two(0xF1C0, 0xE07F), "IiFt", m68040up}, - -{"facos.b", two(0xF000, 0x581C), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"facos.d", two(0xF000, 0x541C), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"facos.l", two(0xF000, 0x401C), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"facos.p", two(0xF000, 0x4C1C), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"facos.s", two(0xF000, 0x441C), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"facos.w", two(0xF000, 0x501C), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"facos.x", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"facos.x", two(0xF000, 0x481C), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"facos.x", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fadd.b", two(0xF000, 0x5822), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fadd.d", two(0xF000, 0x5422), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fadd.l", two(0xF000, 0x4022), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fadd.p", two(0xF000, 0x4C22), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fadd.s", two(0xF000, 0x4422), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fadd.w", two(0xF000, 0x5022), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fadd.x", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fadd.x", two(0xF000, 0x4822), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -{"fsadd.b", two(0xF000, 0x5862), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fsadd.d", two(0xF000, 0x5462), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fsadd.l", two(0xF000, 0x4062), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fsadd.p", two(0xF000, 0x4C62), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fsadd.s", two(0xF000, 0x4462), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fsadd.w", two(0xF000, 0x5062), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fsadd.x", two(0xF000, 0x0062), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fsadd.x", two(0xF000, 0x4862), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, - -{"fdadd.b", two(0xF000, 0x5866), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fdadd.d", two(0xF000, 0x5466), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fdadd.l", two(0xF000, 0x4066), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fdadd.p", two(0xF000, 0x4C66), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fdadd.s", two(0xF000, 0x4466), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fdadd.w", two(0xF000, 0x5066), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fdadd.x", two(0xF000, 0x0066), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fdadd.x", two(0xF000, 0x4866), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, - -{"fasin.b", two(0xF000, 0x580C), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fasin.d", two(0xF000, 0x540C), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fasin.l", two(0xF000, 0x400C), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fasin.p", two(0xF000, 0x4C0C), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fasin.s", two(0xF000, 0x440C), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fasin.w", two(0xF000, 0x500C), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fasin.x", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fasin.x", two(0xF000, 0x480C), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fasin.x", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fatan.b", two(0xF000, 0x580A), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fatan.d", two(0xF000, 0x540A), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fatan.l", two(0xF000, 0x400A), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fatan.p", two(0xF000, 0x4C0A), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fatan.s", two(0xF000, 0x440A), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fatan.w", two(0xF000, 0x500A), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fatan.x", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fatan.x", two(0xF000, 0x480A), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fatan.x", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fatanh.b", two(0xF000, 0x580D), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fatanh.d", two(0xF000, 0x540D), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fatanh.l", two(0xF000, 0x400D), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fatanh.p", two(0xF000, 0x4C0D), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fatanh.s", two(0xF000, 0x440D), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fatanh.w", two(0xF000, 0x500D), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fatanh.x", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fatanh.x", two(0xF000, 0x480D), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fatanh.x", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fbeq", one(0xF081), one(0xF1FF), "IdBW", mfloat }, -{"fbf", one(0xF080), one(0xF1FF), "IdBW", mfloat }, -{"fbge", one(0xF093), one(0xF1FF), "IdBW", mfloat }, -{"fbgl", one(0xF096), one(0xF1FF), "IdBW", mfloat }, -{"fbgle", one(0xF097), one(0xF1FF), "IdBW", mfloat }, -{"fbgt", one(0xF092), one(0xF1FF), "IdBW", mfloat }, -{"fble", one(0xF095), one(0xF1FF), "IdBW", mfloat }, -{"fblt", one(0xF094), one(0xF1FF), "IdBW", mfloat }, -{"fbne", one(0xF08E), one(0xF1FF), "IdBW", mfloat }, -{"fbnge", one(0xF09C), one(0xF1FF), "IdBW", mfloat }, -{"fbngl", one(0xF099), one(0xF1FF), "IdBW", mfloat }, -{"fbngle", one(0xF098), one(0xF1FF), "IdBW", mfloat }, -{"fbngt", one(0xF09D), one(0xF1FF), "IdBW", mfloat }, -{"fbnle", one(0xF09A), one(0xF1FF), "IdBW", mfloat }, -{"fbnlt", one(0xF09B), one(0xF1FF), "IdBW", mfloat }, -{"fboge", one(0xF083), one(0xF1FF), "IdBW", mfloat }, -{"fbogl", one(0xF086), one(0xF1FF), "IdBW", mfloat }, -{"fbogt", one(0xF082), one(0xF1FF), "IdBW", mfloat }, -{"fbole", one(0xF085), one(0xF1FF), "IdBW", mfloat }, -{"fbolt", one(0xF084), one(0xF1FF), "IdBW", mfloat }, -{"fbor", one(0xF087), one(0xF1FF), "IdBW", mfloat }, -{"fbseq", one(0xF091), one(0xF1FF), "IdBW", mfloat }, -{"fbsf", one(0xF090), one(0xF1FF), "IdBW", mfloat }, -{"fbsne", one(0xF09E), one(0xF1FF), "IdBW", mfloat }, -{"fbst", one(0xF09F), one(0xF1FF), "IdBW", mfloat }, -{"fbt", one(0xF08F), one(0xF1FF), "IdBW", mfloat }, -{"fbueq", one(0xF089), one(0xF1FF), "IdBW", mfloat }, -{"fbuge", one(0xF08B), one(0xF1FF), "IdBW", mfloat }, -{"fbugt", one(0xF08A), one(0xF1FF), "IdBW", mfloat }, -{"fbule", one(0xF08D), one(0xF1FF), "IdBW", mfloat }, -{"fbult", one(0xF08C), one(0xF1FF), "IdBW", mfloat }, -{"fbun", one(0xF088), one(0xF1FF), "IdBW", mfloat }, - -{"fbeq.l", one(0xF0C1), one(0xF1FF), "IdBC", mfloat }, -{"fbf.l", one(0xF0C0), one(0xF1FF), "IdBC", mfloat }, -{"fbge.l", one(0xF0D3), one(0xF1FF), "IdBC", mfloat }, -{"fbgl.l", one(0xF0D6), one(0xF1FF), "IdBC", mfloat }, -{"fbgle.l", one(0xF0D7), one(0xF1FF), "IdBC", mfloat }, -{"fbgt.l", one(0xF0D2), one(0xF1FF), "IdBC", mfloat }, -{"fble.l", one(0xF0D5), one(0xF1FF), "IdBC", mfloat }, -{"fblt.l", one(0xF0D4), one(0xF1FF), "IdBC", mfloat }, -{"fbne.l", one(0xF0CE), one(0xF1FF), "IdBC", mfloat }, -{"fbnge.l", one(0xF0DC), one(0xF1FF), "IdBC", mfloat }, -{"fbngl.l", one(0xF0D9), one(0xF1FF), "IdBC", mfloat }, -{"fbngle.l", one(0xF0D8), one(0xF1FF), "IdBC", mfloat }, -{"fbngt.l", one(0xF0DD), one(0xF1FF), "IdBC", mfloat }, -{"fbnle.l", one(0xF0DA), one(0xF1FF), "IdBC", mfloat }, -{"fbnlt.l", one(0xF0DB), one(0xF1FF), "IdBC", mfloat }, -{"fboge.l", one(0xF0C3), one(0xF1FF), "IdBC", mfloat }, -{"fbogl.l", one(0xF0C6), one(0xF1FF), "IdBC", mfloat }, -{"fbogt.l", one(0xF0C2), one(0xF1FF), "IdBC", mfloat }, -{"fbole.l", one(0xF0C5), one(0xF1FF), "IdBC", mfloat }, -{"fbolt.l", one(0xF0C4), one(0xF1FF), "IdBC", mfloat }, -{"fbor.l", one(0xF0C7), one(0xF1FF), "IdBC", mfloat }, -{"fbseq.l", one(0xF0D1), one(0xF1FF), "IdBC", mfloat }, -{"fbsf.l", one(0xF0D0), one(0xF1FF), "IdBC", mfloat }, -{"fbsne.l", one(0xF0DE), one(0xF1FF), "IdBC", mfloat }, -{"fbst.l", one(0xF0DF), one(0xF1FF), "IdBC", mfloat }, -{"fbt.l", one(0xF0CF), one(0xF1FF), "IdBC", mfloat }, -{"fbueq.l", one(0xF0C9), one(0xF1FF), "IdBC", mfloat }, -{"fbuge.l", one(0xF0CB), one(0xF1FF), "IdBC", mfloat }, -{"fbugt.l", one(0xF0CA), one(0xF1FF), "IdBC", mfloat }, -{"fbule.l", one(0xF0CD), one(0xF1FF), "IdBC", mfloat }, -{"fbult.l", one(0xF0CC), one(0xF1FF), "IdBC", mfloat }, -{"fbun.l", one(0xF0C8), one(0xF1FF), "IdBC", mfloat }, - -{"fjeq", one(0xF081), one(0xF1BF), "IdBc", mfloat }, -{"fjf", one(0xF080), one(0xF1BF), "IdBc", mfloat }, -{"fjge", one(0xF093), one(0xF1BF), "IdBc", mfloat }, -{"fjgl", one(0xF096), one(0xF1BF), "IdBc", mfloat }, -{"fjgle", one(0xF097), one(0xF1BF), "IdBc", mfloat }, -{"fjgt", one(0xF092), one(0xF1BF), "IdBc", mfloat }, -{"fjle", one(0xF095), one(0xF1BF), "IdBc", mfloat }, -{"fjlt", one(0xF094), one(0xF1BF), "IdBc", mfloat }, -{"fjne", one(0xF08E), one(0xF1BF), "IdBc", mfloat }, -{"fjnge", one(0xF09C), one(0xF1BF), "IdBc", mfloat }, -{"fjngl", one(0xF099), one(0xF1BF), "IdBc", mfloat }, -{"fjngle", one(0xF098), one(0xF1BF), "IdBc", mfloat }, -{"fjngt", one(0xF09D), one(0xF1BF), "IdBc", mfloat }, -{"fjnle", one(0xF09A), one(0xF1BF), "IdBc", mfloat }, -{"fjnlt", one(0xF09B), one(0xF1BF), "IdBc", mfloat }, -{"fjoge", one(0xF083), one(0xF1BF), "IdBc", mfloat }, -{"fjogl", one(0xF086), one(0xF1BF), "IdBc", mfloat }, -{"fjogt", one(0xF082), one(0xF1BF), "IdBc", mfloat }, -{"fjole", one(0xF085), one(0xF1BF), "IdBc", mfloat }, -{"fjolt", one(0xF084), one(0xF1BF), "IdBc", mfloat }, -{"fjor", one(0xF087), one(0xF1BF), "IdBc", mfloat }, -{"fjseq", one(0xF091), one(0xF1BF), "IdBc", mfloat }, -{"fjsf", one(0xF090), one(0xF1BF), "IdBc", mfloat }, -{"fjsne", one(0xF09E), one(0xF1BF), "IdBc", mfloat }, -{"fjst", one(0xF09F), one(0xF1BF), "IdBc", mfloat }, -{"fjt", one(0xF08F), one(0xF1BF), "IdBc", mfloat }, -{"fjueq", one(0xF089), one(0xF1BF), "IdBc", mfloat }, -{"fjuge", one(0xF08B), one(0xF1BF), "IdBc", mfloat }, -{"fjugt", one(0xF08A), one(0xF1BF), "IdBc", mfloat }, -{"fjule", one(0xF08D), one(0xF1BF), "IdBc", mfloat }, -{"fjult", one(0xF08C), one(0xF1BF), "IdBc", mfloat }, -{"fjun", one(0xF088), one(0xF1BF), "IdBc", mfloat }, - -{"fcmp.b", two(0xF000, 0x5838), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fcmp.d", two(0xF000, 0x5438), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fcmp.l", two(0xF000, 0x4038), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fcmp.p", two(0xF000, 0x4C38), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fcmp.s", two(0xF000, 0x4438), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fcmp.w", two(0xF000, 0x5038), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fcmp.x", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fcmp.x", two(0xF000, 0x4838), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -{"fcos.b", two(0xF000, 0x581D), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fcos.d", two(0xF000, 0x541D), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fcos.l", two(0xF000, 0x401D), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fcos.p", two(0xF000, 0x4C1D), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fcos.s", two(0xF000, 0x441D), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fcos.w", two(0xF000, 0x501D), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fcos.x", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fcos.x", two(0xF000, 0x481D), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fcos.x", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fcosh.b", two(0xF000, 0x5819), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fcosh.d", two(0xF000, 0x5419), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fcosh.l", two(0xF000, 0x4019), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fcosh.p", two(0xF000, 0x4C19), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fcosh.s", two(0xF000, 0x4419), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fcosh.w", two(0xF000, 0x5019), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fcosh.x", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fcosh.x", two(0xF000, 0x4819), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fcosh.x", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fdbeq", two(0xF048, 0x0001), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbf", two(0xF048, 0x0000), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbge", two(0xF048, 0x0013), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbgl", two(0xF048, 0x0016), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbgle", two(0xF048, 0x0017), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbgt", two(0xF048, 0x0012), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdble", two(0xF048, 0x0015), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdblt", two(0xF048, 0x0014), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbne", two(0xF048, 0x000E), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbnge", two(0xF048, 0x001C), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbngl", two(0xF048, 0x0019), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbngle", two(0xF048, 0x0018), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbngt", two(0xF048, 0x001D), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbnle", two(0xF048, 0x001A), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbnlt", two(0xF048, 0x001B), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdboge", two(0xF048, 0x0003), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbogl", two(0xF048, 0x0006), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbogt", two(0xF048, 0x0002), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbole", two(0xF048, 0x0005), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbolt", two(0xF048, 0x0004), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbor", two(0xF048, 0x0007), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbseq", two(0xF048, 0x0011), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbsf", two(0xF048, 0x0010), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbsne", two(0xF048, 0x001E), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbst", two(0xF048, 0x001F), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbt", two(0xF048, 0x000F), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbueq", two(0xF048, 0x0009), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbuge", two(0xF048, 0x000B), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbugt", two(0xF048, 0x000A), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbule", two(0xF048, 0x000D), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbult", two(0xF048, 0x000C), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, -{"fdbun", two(0xF048, 0x0008), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat }, - -{"fdiv.b", two(0xF000, 0x5820), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fdiv.d", two(0xF000, 0x5420), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fdiv.l", two(0xF000, 0x4020), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fdiv.p", two(0xF000, 0x4C20), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fdiv.s", two(0xF000, 0x4420), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fdiv.w", two(0xF000, 0x5020), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fdiv.x", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fdiv.x", two(0xF000, 0x4820), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -{"fsdiv.b", two(0xF000, 0x5860), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fsdiv.d", two(0xF000, 0x5460), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fsdiv.l", two(0xF000, 0x4060), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fsdiv.p", two(0xF000, 0x4C60), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fsdiv.s", two(0xF000, 0x4460), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fsdiv.w", two(0xF000, 0x5060), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fsdiv.x", two(0xF000, 0x0060), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fsdiv.x", two(0xF000, 0x4860), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, - -{"fddiv.b", two(0xF000, 0x5864), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fddiv.d", two(0xF000, 0x5464), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fddiv.l", two(0xF000, 0x4064), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fddiv.p", two(0xF000, 0x4C64), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fddiv.s", two(0xF000, 0x4464), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fddiv.w", two(0xF000, 0x5064), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fddiv.x", two(0xF000, 0x0064), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fddiv.x", two(0xF000, 0x4864), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, - -{"fetox.b", two(0xF000, 0x5810), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fetox.d", two(0xF000, 0x5410), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fetox.l", two(0xF000, 0x4010), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fetox.p", two(0xF000, 0x4C10), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fetox.s", two(0xF000, 0x4410), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fetox.w", two(0xF000, 0x5010), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fetox.x", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fetox.x", two(0xF000, 0x4810), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fetox.x", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fetoxm1.b", two(0xF000, 0x5808), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fetoxm1.d", two(0xF000, 0x5408), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fetoxm1.l", two(0xF000, 0x4008), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fetoxm1.p", two(0xF000, 0x4C08), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fetoxm1.s", two(0xF000, 0x4408), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fetoxm1.w", two(0xF000, 0x5008), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fetoxm1.x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fetoxm1.x", two(0xF000, 0x4808), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fetoxm1.x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fgetexp.b", two(0xF000, 0x581E), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fgetexp.d", two(0xF000, 0x541E), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fgetexp.l", two(0xF000, 0x401E), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fgetexp.p", two(0xF000, 0x4C1E), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fgetexp.s", two(0xF000, 0x441E), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fgetexp.w", two(0xF000, 0x501E), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fgetexp.x", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fgetexp.x", two(0xF000, 0x481E), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fgetexp.x", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fgetman.b", two(0xF000, 0x581F), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fgetman.d", two(0xF000, 0x541F), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fgetman.l", two(0xF000, 0x401F), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fgetman.p", two(0xF000, 0x4C1F), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fgetman.s", two(0xF000, 0x441F), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fgetman.w", two(0xF000, 0x501F), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fgetman.x", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fgetman.x", two(0xF000, 0x481F), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fgetman.x", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fint.b", two(0xF000, 0x5801), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fint.d", two(0xF000, 0x5401), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fint.l", two(0xF000, 0x4001), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fint.p", two(0xF000, 0x4C01), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fint.s", two(0xF000, 0x4401), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fint.w", two(0xF000, 0x5001), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fint.x", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fint.x", two(0xF000, 0x4801), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fint.x", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fintrz.b", two(0xF000, 0x5803), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fintrz.d", two(0xF000, 0x5403), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fintrz.l", two(0xF000, 0x4003), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fintrz.p", two(0xF000, 0x4C03), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fintrz.s", two(0xF000, 0x4403), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fintrz.w", two(0xF000, 0x5003), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fintrz.x", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fintrz.x", two(0xF000, 0x4803), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fintrz.x", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"flog10.b", two(0xF000, 0x5815), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"flog10.d", two(0xF000, 0x5415), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"flog10.l", two(0xF000, 0x4015), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"flog10.p", two(0xF000, 0x4C15), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"flog10.s", two(0xF000, 0x4415), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"flog10.w", two(0xF000, 0x5015), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"flog10.x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"flog10.x", two(0xF000, 0x4815), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"flog10.x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"flog2.b", two(0xF000, 0x5816), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"flog2.d", two(0xF000, 0x5416), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"flog2.l", two(0xF000, 0x4016), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"flog2.p", two(0xF000, 0x4C16), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"flog2.s", two(0xF000, 0x4416), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"flog2.w", two(0xF000, 0x5016), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"flog2.x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"flog2.x", two(0xF000, 0x4816), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"flog2.x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"flogn.b", two(0xF000, 0x5814), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"flogn.d", two(0xF000, 0x5414), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"flogn.l", two(0xF000, 0x4014), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"flogn.p", two(0xF000, 0x4C14), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"flogn.s", two(0xF000, 0x4414), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"flogn.w", two(0xF000, 0x5014), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"flogn.x", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"flogn.x", two(0xF000, 0x4814), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"flogn.x", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"flognp1.b", two(0xF000, 0x5806), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"flognp1.d", two(0xF000, 0x5406), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"flognp1.l", two(0xF000, 0x4006), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"flognp1.p", two(0xF000, 0x4C06), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"flognp1.s", two(0xF000, 0x4406), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"flognp1.w", two(0xF000, 0x5006), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"flognp1.x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"flognp1.x", two(0xF000, 0x4806), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"flognp1.x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fmod.b", two(0xF000, 0x5821), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fmod.d", two(0xF000, 0x5421), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fmod.l", two(0xF000, 0x4021), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fmod.p", two(0xF000, 0x4C21), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fmod.s", two(0xF000, 0x4421), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fmod.w", two(0xF000, 0x5021), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fmod.x", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fmod.x", two(0xF000, 0x4821), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -{"fmove.b", two(0xF000, 0x5800), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fmove.b", two(0xF000, 0x7800), two(0xF1C0, 0xFC7F), "IiF7$b", mfloat }, -{"fmove.d", two(0xF000, 0x5400), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fmove.d", two(0xF000, 0x7400), two(0xF1C0, 0xFC7F), "IiF7~F", mfloat }, -{"fmove.l", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fmove.l", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7$l", mfloat }, -/* FIXME: the next two variants should not permit moving an address - register to anything but the floating point instruction register. */ -{"fmove.l", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8%s", mfloat }, -{"fmove.l", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8", mfloat }, -{"fmove.p", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fmove.p", two(0xF000, 0x6C00), two(0xF1C0, 0xFC00), "IiF7~pkC", mfloat }, -{"fmove.p", two(0xF000, 0x7C00), two(0xF1C0, 0xFC0F), "IiF7~pDk", mfloat }, -{"fmove.s", two(0xF000, 0x4400), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fmove.s", two(0xF000, 0x6400), two(0xF1C0, 0xFC7F), "IiF7$f", mfloat }, -{"fmove.w", two(0xF000, 0x5000), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fmove.w", two(0xF000, 0x7000), two(0xF1C0, 0xFC7F), "IiF7$w", mfloat }, -{"fmove.x", two(0xF000, 0x0000), two(0xF1FF, 0xE07F), "IiF8F7", mfloat }, -{"fmove.x", two(0xF000, 0x4800), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fmove.x", two(0xF000, 0x6800), two(0xF1C0, 0xFC7F), "IiF7~x", mfloat }, - -{"fsmove.b", two(0xF000, 0x5840), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fsmove.d", two(0xF000, 0x5440), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fsmove.l", two(0xF000, 0x4040), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fsmove.s", two(0xF000, 0x4440), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fsmove.w", two(0xF000, 0x5040), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fsmove.x", two(0xF000, 0x0040), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fsmove.x", two(0xF000, 0x4840), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fsmove.p", two(0xF000, 0x4C40), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, - -{"fdmove.b", two(0xF000, 0x5844), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fdmove.d", two(0xF000, 0x5444), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fdmove.l", two(0xF000, 0x4044), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fdmove.s", two(0xF000, 0x4444), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fdmove.w", two(0xF000, 0x5044), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fdmove.x", two(0xF000, 0x0044), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fdmove.x", two(0xF000, 0x4844), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fdmove.p", two(0xF000, 0x4C44), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, - -{"fmovecr.x", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7", mfloat }, - -{"fmovem.x", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s", mfloat }, -{"fmovem.x", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s", mfloat }, -{"fmovem.x", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk", mfloat }, -{"fmovem.x", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk", mfloat }, -{"fmovem.x", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s", mfloat }, -{"fmovem.x", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s", mfloat }, -{"fmovem.x", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3", mfloat }, -{"fmovem.x", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3", mfloat }, -{"fmovem.x", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s", mfloat }, -{"fmovem.x", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s", mfloat }, -{"fmovem.x", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3", mfloat }, -{"fmovem.x", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3", mfloat }, - -{"fmovem.l", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8%s", mfloat }, -{"fmovem.l", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8~s", mfloat }, -/* FIXME: In the next instruction, we should only permit %dn if the - target is a single register. We should only permit %an if the - target is a single %fpiar. */ -{"fmovem.l", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*lL8", mfloat }, - -{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s", mfloat }, -{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s", mfloat }, -{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3", mfloat }, -{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3", mfloat }, -{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s", mfloat }, -{"fmovem", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s", mfloat }, -{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s", mfloat }, -{"fmovem", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s", mfloat }, -{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3", mfloat }, -{"fmovem", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk", mfloat }, -{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3", mfloat }, -{"fmovem", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk", mfloat }, -{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8%s", mfloat }, -{"fmovem", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8", mfloat }, -{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8~s", mfloat }, -{"fmovem", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8", mfloat }, - -{"fmul.b", two(0xF000, 0x5823), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fmul.d", two(0xF000, 0x5423), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fmul.l", two(0xF000, 0x4023), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fmul.p", two(0xF000, 0x4C23), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fmul.s", two(0xF000, 0x4423), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fmul.w", two(0xF000, 0x5023), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fmul.x", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fmul.x", two(0xF000, 0x4823), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -{"fsmul.b", two(0xF000, 0x5863), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fsmul.d", two(0xF000, 0x5463), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fsmul.l", two(0xF000, 0x4063), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fsmul.p", two(0xF000, 0x4C63), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fsmul.s", two(0xF000, 0x4463), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fsmul.w", two(0xF000, 0x5063), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fsmul.x", two(0xF000, 0x0063), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fsmul.x", two(0xF000, 0x4863), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, - -{"fdmul.b", two(0xF000, 0x5867), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fdmul.d", two(0xF000, 0x5467), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fdmul.l", two(0xF000, 0x4067), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fdmul.p", two(0xF000, 0x4C67), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fdmul.s", two(0xF000, 0x4467), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fdmul.w", two(0xF000, 0x5067), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fdmul.x", two(0xF000, 0x0067), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fdmul.x", two(0xF000, 0x4867), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, - -{"fneg.b", two(0xF000, 0x581A), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fneg.d", two(0xF000, 0x541A), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fneg.l", two(0xF000, 0x401A), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fneg.p", two(0xF000, 0x4C1A), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fneg.s", two(0xF000, 0x441A), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fneg.w", two(0xF000, 0x501A), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fneg.x", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fneg.x", two(0xF000, 0x481A), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fneg.x", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fsneg.b", two(0xF000, 0x585A), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fsneg.d", two(0xF000, 0x545A), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fsneg.l", two(0xF000, 0x405A), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fsneg.p", two(0xF000, 0x4C5A), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fsneg.s", two(0xF000, 0x445A), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fsneg.w", two(0xF000, 0x505A), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fsneg.x", two(0xF000, 0x005A), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fsneg.x", two(0xF000, 0x485A), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fsneg.x", two(0xF000, 0x005A), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"fdneg.b", two(0xF000, 0x585E), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fdneg.d", two(0xF000, 0x545E), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fdneg.l", two(0xF000, 0x405E), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fdneg.p", two(0xF000, 0x4C5E), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fdneg.s", two(0xF000, 0x445E), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fdneg.w", two(0xF000, 0x505E), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fdneg.x", two(0xF000, 0x005E), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fdneg.x", two(0xF000, 0x485E), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fdneg.x", two(0xF000, 0x005E), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"fnop", two(0xF280, 0x0000), two(0xFFFF, 0xFFFF), "Ii", mfloat }, - -{"frem.b", two(0xF000, 0x5825), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"frem.d", two(0xF000, 0x5425), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"frem.l", two(0xF000, 0x4025), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"frem.p", two(0xF000, 0x4C25), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"frem.s", two(0xF000, 0x4425), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"frem.w", two(0xF000, 0x5025), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"frem.x", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"frem.x", two(0xF000, 0x4825), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -{"frestore", one(0xF140), one(0xF1C0), "Ids", mfloat }, - -{"fscale.b", two(0xF000, 0x5826), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fscale.d", two(0xF000, 0x5426), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fscale.l", two(0xF000, 0x4026), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fscale.p", two(0xF000, 0x4C26), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fscale.s", two(0xF000, 0x4426), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fscale.w", two(0xF000, 0x5026), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fscale.x", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fscale.x", two(0xF000, 0x4826), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, - -/* $ is necessary to prevent the assembler from using PC-relative. - If @ were used, "label: fseq label" could produce "ftrapeq", - because "label" became "pc@label". */ -{"fseq", two(0xF040, 0x0001), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsf", two(0xF040, 0x0000), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsge", two(0xF040, 0x0013), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsgl", two(0xF040, 0x0016), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsgle", two(0xF040, 0x0017), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsgt", two(0xF040, 0x0012), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsle", two(0xF040, 0x0015), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fslt", two(0xF040, 0x0014), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsne", two(0xF040, 0x000E), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsnge", two(0xF040, 0x001C), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsngl", two(0xF040, 0x0019), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsngle", two(0xF040, 0x0018), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsngt", two(0xF040, 0x001D), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsnle", two(0xF040, 0x001A), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsnlt", two(0xF040, 0x001B), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsoge", two(0xF040, 0x0003), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsogl", two(0xF040, 0x0006), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsogt", two(0xF040, 0x0002), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsole", two(0xF040, 0x0005), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsolt", two(0xF040, 0x0004), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsor", two(0xF040, 0x0007), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsseq", two(0xF040, 0x0011), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fssf", two(0xF040, 0x0010), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fssne", two(0xF040, 0x001E), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsst", two(0xF040, 0x001F), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fst", two(0xF040, 0x000F), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsueq", two(0xF040, 0x0009), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsuge", two(0xF040, 0x000B), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsugt", two(0xF040, 0x000A), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsule", two(0xF040, 0x000D), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsult", two(0xF040, 0x000C), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, -{"fsun", two(0xF040, 0x0008), two(0xF1C0, 0xFFFF), "Ii$s", mfloat }, - -{"fsgldiv.b", two(0xF000, 0x5824), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fsgldiv.d", two(0xF000, 0x5424), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fsgldiv.l", two(0xF000, 0x4024), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fsgldiv.p", two(0xF000, 0x4C24), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fsgldiv.s", two(0xF000, 0x4424), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fsgldiv.w", two(0xF000, 0x5024), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fsgldiv.x", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fsgldiv.x", two(0xF000, 0x4824), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fsgldiv.x", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fsglmul.b", two(0xF000, 0x5827), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fsglmul.d", two(0xF000, 0x5427), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fsglmul.l", two(0xF000, 0x4027), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fsglmul.p", two(0xF000, 0x4C27), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fsglmul.s", two(0xF000, 0x4427), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fsglmul.w", two(0xF000, 0x5027), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fsglmul.x", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fsglmul.x", two(0xF000, 0x4827), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fsglmul.x", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fsin.b", two(0xF000, 0x580E), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fsin.d", two(0xF000, 0x540E), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fsin.l", two(0xF000, 0x400E), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fsin.p", two(0xF000, 0x4C0E), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fsin.s", two(0xF000, 0x440E), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fsin.w", two(0xF000, 0x500E), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fsin.x", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fsin.x", two(0xF000, 0x480E), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fsin.x", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fsincos.b", two(0xF000, 0x5830), two(0xF1C0, 0xFC78), "Ii;bF3F7", mfloat }, -{"fsincos.d", two(0xF000, 0x5430), two(0xF1C0, 0xFC78), "Ii;FF3F7", mfloat }, -{"fsincos.l", two(0xF000, 0x4030), two(0xF1C0, 0xFC78), "Ii;lF3F7", mfloat }, -{"fsincos.p", two(0xF000, 0x4C30), two(0xF1C0, 0xFC78), "Ii;pF3F7", mfloat }, -{"fsincos.s", two(0xF000, 0x4430), two(0xF1C0, 0xFC78), "Ii;fF3F7", mfloat }, -{"fsincos.w", two(0xF000, 0x5030), two(0xF1C0, 0xFC78), "Ii;wF3F7", mfloat }, -{"fsincos.x", two(0xF000, 0x0030), two(0xF1C0, 0xE078), "IiF8F3F7", mfloat }, -{"fsincos.x", two(0xF000, 0x4830), two(0xF1C0, 0xFC78), "Ii;xF3F7", mfloat }, - -{"fsinh.b", two(0xF000, 0x5802), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fsinh.d", two(0xF000, 0x5402), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fsinh.l", two(0xF000, 0x4002), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fsinh.p", two(0xF000, 0x4C02), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fsinh.s", two(0xF000, 0x4402), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fsinh.w", two(0xF000, 0x5002), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fsinh.x", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fsinh.x", two(0xF000, 0x4802), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fsinh.x", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fsqrt.b", two(0xF000, 0x5804), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fsqrt.d", two(0xF000, 0x5404), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fsqrt.l", two(0xF000, 0x4004), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fsqrt.p", two(0xF000, 0x4C04), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fsqrt.s", two(0xF000, 0x4404), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fsqrt.w", two(0xF000, 0x5004), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fsqrt.x", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fsqrt.x", two(0xF000, 0x4804), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fsqrt.x", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fssqrt.b", two(0xF000, 0x5841), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fssqrt.d", two(0xF000, 0x5441), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fssqrt.l", two(0xF000, 0x4041), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fssqrt.p", two(0xF000, 0x4C41), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fssqrt.s", two(0xF000, 0x4441), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fssqrt.w", two(0xF000, 0x5041), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fssqrt.x", two(0xF000, 0x0041), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fssqrt.x", two(0xF000, 0x4841), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fssqrt.x", two(0xF000, 0x0041), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"fdsqrt.b", two(0xF000, 0x5845), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fdsqrt.d", two(0xF000, 0x5445), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fdsqrt.l", two(0xF000, 0x4045), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fdsqrt.p", two(0xF000, 0x4C45), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fdsqrt.s", two(0xF000, 0x4445), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fdsqrt.w", two(0xF000, 0x5045), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fdsqrt.x", two(0xF000, 0x0045), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fdsqrt.x", two(0xF000, 0x4845), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fdsqrt.x", two(0xF000, 0x0045), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"fsub.b", two(0xF000, 0x5828), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"fsub.d", two(0xF000, 0x5428), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"fsub.l", two(0xF000, 0x4028), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"fsub.p", two(0xF000, 0x4C28), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"fsub.s", two(0xF000, 0x4428), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"fsub.w", two(0xF000, 0x5028), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"fsub.x", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"fsub.x", two(0xF000, 0x4828), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"fsub.x", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"fssub.b", two(0xF000, 0x5868), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fssub.d", two(0xF000, 0x5468), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fssub.l", two(0xF000, 0x4068), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fssub.p", two(0xF000, 0x4C68), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fssub.s", two(0xF000, 0x4468), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fssub.w", two(0xF000, 0x5068), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fssub.x", two(0xF000, 0x0068), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fssub.x", two(0xF000, 0x4868), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fssub.x", two(0xF000, 0x0068), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"fdsub.b", two(0xF000, 0x586c), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040up }, -{"fdsub.d", two(0xF000, 0x546c), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040up }, -{"fdsub.l", two(0xF000, 0x406c), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040up }, -{"fdsub.p", two(0xF000, 0x4C6c), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040up }, -{"fdsub.s", two(0xF000, 0x446c), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040up }, -{"fdsub.w", two(0xF000, 0x506c), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040up }, -{"fdsub.x", two(0xF000, 0x006c), two(0xF1C0, 0xE07F), "IiF8F7", m68040up }, -{"fdsub.x", two(0xF000, 0x486c), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040up }, -{"fdsub.x", two(0xF000, 0x006c), two(0xF1C0, 0xE07F), "IiFt", m68040up }, - -{"ftan.b", two(0xF000, 0x580F), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"ftan.d", two(0xF000, 0x540F), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"ftan.l", two(0xF000, 0x400F), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"ftan.p", two(0xF000, 0x4C0F), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"ftan.s", two(0xF000, 0x440F), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"ftan.w", two(0xF000, 0x500F), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"ftan.x", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"ftan.x", two(0xF000, 0x480F), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"ftan.x", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"ftanh.b", two(0xF000, 0x5809), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"ftanh.d", two(0xF000, 0x5409), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"ftanh.l", two(0xF000, 0x4009), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"ftanh.p", two(0xF000, 0x4C09), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"ftanh.s", two(0xF000, 0x4409), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"ftanh.w", two(0xF000, 0x5009), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"ftanh.x", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"ftanh.x", two(0xF000, 0x4809), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"ftanh.x", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"ftentox.b", two(0xF000, 0x5812), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"ftentox.d", two(0xF000, 0x5412), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"ftentox.l", two(0xF000, 0x4012), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"ftentox.p", two(0xF000, 0x4C12), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"ftentox.s", two(0xF000, 0x4412), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"ftentox.w", two(0xF000, 0x5012), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"ftentox.x", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"ftentox.x", two(0xF000, 0x4812), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"ftentox.x", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"ftrapeq", two(0xF07C, 0x0001), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapf", two(0xF07C, 0x0000), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapge", two(0xF07C, 0x0013), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapgl", two(0xF07C, 0x0016), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapgle", two(0xF07C, 0x0017), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapgt", two(0xF07C, 0x0012), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftraple", two(0xF07C, 0x0015), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftraplt", two(0xF07C, 0x0014), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapne", two(0xF07C, 0x000E), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapnge", two(0xF07C, 0x001C), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapngl", two(0xF07C, 0x0019), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapngle", two(0xF07C, 0x0018), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapngt", two(0xF07C, 0x001D), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapnle", two(0xF07C, 0x001A), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapnlt", two(0xF07C, 0x001B), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapoge", two(0xF07C, 0x0003), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapogl", two(0xF07C, 0x0006), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapogt", two(0xF07C, 0x0002), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapole", two(0xF07C, 0x0005), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapolt", two(0xF07C, 0x0004), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapor", two(0xF07C, 0x0007), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapseq", two(0xF07C, 0x0011), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapsf", two(0xF07C, 0x0010), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapsne", two(0xF07C, 0x001E), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapst", two(0xF07C, 0x001F), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapt", two(0xF07C, 0x000F), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapueq", two(0xF07C, 0x0009), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapuge", two(0xF07C, 0x000B), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapugt", two(0xF07C, 0x000A), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapule", two(0xF07C, 0x000D), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapult", two(0xF07C, 0x000C), two(0xF1FF, 0xFFFF), "Ii", mfloat }, -{"ftrapun", two(0xF07C, 0x0008), two(0xF1FF, 0xFFFF), "Ii", mfloat }, - -{"ftrapeq.w", two(0xF07A, 0x0001), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapf.w", two(0xF07A, 0x0000), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapge.w", two(0xF07A, 0x0013), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapgl.w", two(0xF07A, 0x0016), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapgle.w", two(0xF07A, 0x0017), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapgt.w", two(0xF07A, 0x0012), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftraple.w", two(0xF07A, 0x0015), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftraplt.w", two(0xF07A, 0x0014), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapne.w", two(0xF07A, 0x000E), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapnge.w", two(0xF07A, 0x001C), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapngl.w", two(0xF07A, 0x0019), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapngle.w", two(0xF07A, 0x0018), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapngt.w", two(0xF07A, 0x001D), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapnle.w", two(0xF07A, 0x001A), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapnlt.w", two(0xF07A, 0x001B), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapoge.w", two(0xF07A, 0x0003), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapogl.w", two(0xF07A, 0x0006), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapogt.w", two(0xF07A, 0x0002), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapole.w", two(0xF07A, 0x0005), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapolt.w", two(0xF07A, 0x0004), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapor.w", two(0xF07A, 0x0007), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapseq.w", two(0xF07A, 0x0011), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapsf.w", two(0xF07A, 0x0010), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapsne.w", two(0xF07A, 0x001E), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapst.w", two(0xF07A, 0x001F), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapt.w", two(0xF07A, 0x000F), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapueq.w", two(0xF07A, 0x0009), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapuge.w", two(0xF07A, 0x000B), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapugt.w", two(0xF07A, 0x000A), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapule.w", two(0xF07A, 0x000D), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapult.w", two(0xF07A, 0x000C), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, -{"ftrapun.w", two(0xF07A, 0x0008), two(0xF1FF, 0xFFFF), "Ii^w", mfloat }, - -{"ftrapeq.l", two(0xF07B, 0x0001), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapf.l", two(0xF07B, 0x0000), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapge.l", two(0xF07B, 0x0013), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapgl.l", two(0xF07B, 0x0016), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapgle.l", two(0xF07B, 0x0017), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapgt.l", two(0xF07B, 0x0012), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftraple.l", two(0xF07B, 0x0015), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftraplt.l", two(0xF07B, 0x0014), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapne.l", two(0xF07B, 0x000E), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapnge.l", two(0xF07B, 0x001C), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapngl.l", two(0xF07B, 0x0019), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapngle.l", two(0xF07B, 0x0018), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapngt.l", two(0xF07B, 0x001D), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapnle.l", two(0xF07B, 0x001A), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapnlt.l", two(0xF07B, 0x001B), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapoge.l", two(0xF07B, 0x0003), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapogl.l", two(0xF07B, 0x0006), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapogt.l", two(0xF07B, 0x0002), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapole.l", two(0xF07B, 0x0005), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapolt.l", two(0xF07B, 0x0004), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapor.l", two(0xF07B, 0x0007), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapseq.l", two(0xF07B, 0x0011), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapsf.l", two(0xF07B, 0x0010), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapsne.l", two(0xF07B, 0x001E), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapst.l", two(0xF07B, 0x001F), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapt.l", two(0xF07B, 0x000F), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapueq.l", two(0xF07B, 0x0009), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapuge.l", two(0xF07B, 0x000B), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapugt.l", two(0xF07B, 0x000A), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapule.l", two(0xF07B, 0x000D), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapult.l", two(0xF07B, 0x000C), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, -{"ftrapun.l", two(0xF07B, 0x0008), two(0xF1FF, 0xFFFF), "Ii^l", mfloat }, - -{"ftst.b", two(0xF000, 0x583A), two(0xF1C0, 0xFC7F), "Ii;b", mfloat }, -{"ftst.d", two(0xF000, 0x543A), two(0xF1C0, 0xFC7F), "Ii;F", mfloat }, -{"ftst.l", two(0xF000, 0x403A), two(0xF1C0, 0xFC7F), "Ii;l", mfloat }, -{"ftst.p", two(0xF000, 0x4C3A), two(0xF1C0, 0xFC7F), "Ii;p", mfloat }, -{"ftst.s", two(0xF000, 0x443A), two(0xF1C0, 0xFC7F), "Ii;f", mfloat }, -{"ftst.w", two(0xF000, 0x503A), two(0xF1C0, 0xFC7F), "Ii;w", mfloat }, -{"ftst.x", two(0xF000, 0x003A), two(0xF1C0, 0xE07F), "IiF8", mfloat }, -{"ftst.x", two(0xF000, 0x483A), two(0xF1C0, 0xFC7F), "Ii;x", mfloat }, - -{"ftwotox.b", two(0xF000, 0x5811), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, -{"ftwotox.d", two(0xF000, 0x5411), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, -{"ftwotox.l", two(0xF000, 0x4011), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, -{"ftwotox.p", two(0xF000, 0x4C11), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, -{"ftwotox.s", two(0xF000, 0x4411), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, -{"ftwotox.w", two(0xF000, 0x5011), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, -{"ftwotox.x", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, -{"ftwotox.x", two(0xF000, 0x4811), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, -{"ftwotox.x", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiFt", mfloat }, - -{"halt", one(0045310), one(0177777), "", m68060 | mcf5200 }, - -{"illegal", one(0045374), one(0177777), "", m68000up }, - -{"jmp", one(0047300), one(0177700), "!s", m68000up | mcf5200 }, - -{"jra", one(0060000), one(0177400), "Bg", m68000up | mcf5200 }, -{"jra", one(0047300), one(0177700), "!s", m68000up | mcf5200 }, - -{"jsr", one(0047200), one(0177700), "!s", m68000up | mcf5200 }, - -{"jbsr", one(0060400), one(0177400), "Bg", m68000up | mcf5200 }, -{"jbsr", one(0047200), one(0177700), "!s", m68000up | mcf5200 }, - -{"lea", one(0040700), one(0170700), "!sAd", m68000up | mcf5200 }, - -{"lpstop", two(0174000,0000700),two(0177777,0177777),"#w", cpu32|m68060 }, - -{"link.w", one(0047120), one(0177770), "As#w", m68000up | mcf5200 }, -{"link.l", one(0044010), one(0177770), "As#l", m68020up | cpu32 }, -{"link", one(0047120), one(0177770), "As#W", m68000up | mcf5200 }, -{"link", one(0044010), one(0177770), "As#l", m68020up | cpu32 }, - -{"lsl.b", one(0160410), one(0170770), "QdDs", m68000up }, -{"lsl.b", one(0160450), one(0170770), "DdDs", m68000up }, -{"lsl.w", one(0160510), one(0170770), "QdDs", m68000up }, -{"lsl.w", one(0160550), one(0170770), "DdDs", m68000up }, -{"lsl.w", one(0161700), one(0177700), "~s", m68000up }, -{"lsl.l", one(0160610), one(0170770), "QdDs", m68000up | mcf5200 }, -{"lsl.l", one(0160650), one(0170770), "DdDs", m68000up | mcf5200 }, - -{"lsr.b", one(0160010), one(0170770), "QdDs", m68000up }, -{"lsr.b", one(0160050), one(0170770), "DdDs", m68000up }, -{"lsr.w", one(0160110), one(0170770), "QdDs", m68000up }, -{"lsr.w", one(0160150), one(0170770), "DdDs", m68000up }, -{"lsr.w", one(0161300), one(0177700), "~s", m68000up }, -{"lsr.l", one(0160210), one(0170770), "QdDs", m68000up | mcf5200 }, -{"lsr.l", one(0160250), one(0170770), "DdDs", m68000up | mcf5200 }, - -/* NOTE: The mcf5200 family programmer's reference manual does not - indicate the byte form of the movea instruction is invalid (as it - is on 68000 family cpus). However, experiments on the 5202 yeild - unexpected results. The value is copied, but it is not sign extended - (as is done with movea.w) and the top three bytes in the address - register are not disturbed. I don't know if this is the intended - behavior --- it could be a hole in instruction decoding (Motorola - decided not to trap all invalid instructions for performance reasons) - --- but I suspect that it is not. - - I reported this to Motorola ISD Technical Communications Support, - which replied that other coldfire assemblers reject movea.b. For - this reason I've decided to not allow moveab. - - jtc@cygnus.com - 97/01/24 - */ - -{"movea.l", one(0020100), one(0170700), "*lAd", m68000up | mcf5200 }, -{"movea.w", one(0030100), one(0170700), "*wAd", m68000up | mcf5200 }, - -{"movec", one(0047173), one(0177777), "R1Jj", m68010up | mcf5200 }, -{"movec", one(0047173), one(0177777), "R1#j", m68010up | mcf5200 }, -{"movec", one(0047172), one(0177777), "JjR1", m68010up }, -{"movec", one(0047172), one(0177777), "#jR1", m68010up }, - -{"movem.w", one(0044200), one(0177700), "Lw&s", m68000up }, -{"movem.w", one(0044240), one(0177770), "lw-s", m68000up }, -{"movem.w", one(0044200), one(0177700), "#w>s", m68000up }, -{"movem.w", one(0046200), one(0177700), "s", m68000up }, -{"movem.l", one(0046300), one(0177700), "s", m68851 }, - -{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "$s", m68851 }, -{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "$s", m68851 }, -{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "$s", m68851 }, -{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "$s", m68851 }, -{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "$s", m68851 }, -{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "$s", m68851 }, -{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "$s", m68851 }, -{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "$s", m68851 }, -{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "$s", m68851 }, -{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "$s", m68851 }, -{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "$s", m68851 }, -{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "$s", m68851 }, -{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "$s", m68851 }, -{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "$s", m68851 }, -{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "$s", m68851 }, -{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "$s", m68851 }, - -{"ptestr", two(0xf000,0x8210), two(0xffc0, 0xe3f0), "T3&st8", m68030|m68851 }, -{"ptestr", two(0xf000,0x8310), two(0xffc0,0xe310), "T3&st8A9", m68030|m68851 }, -{"ptestr", two(0xf000,0x8208), two(0xffc0,0xe3f8), "D3&st8", m68030|m68851 }, -{"ptestr", two(0xf000,0x8308), two(0xffc0,0xe318), "D3&st8A9", m68030|m68851 }, -{"ptestr", two(0xf000,0x8200), two(0xffc0,0xe3fe), "f3&st8", m68030|m68851 }, -{"ptestr", two(0xf000,0x8300), two(0xffc0,0xe31e), "f3&st8A9", m68030|m68851 }, -{"ptestr", one(0xf568), one(0xfff8), "as", m68040 }, - -{"ptestw", two(0xf000,0x8010), two(0xffc0,0xe3f0), "T3&st8", m68030|m68851 }, -{"ptestw", two(0xf000,0x8110), two(0xffc0,0xe310), "T3&st8A9", m68030|m68851 }, -{"ptestw", two(0xf000,0x8008), two(0xffc0,0xe3f8), "D3&st8", m68030|m68851 }, -{"ptestw", two(0xf000,0x8108), two(0xffc0,0xe318), "D3&st8A9", m68030|m68851 }, -{"ptestw", two(0xf000,0x8000), two(0xffc0,0xe3fe), "f3&st8", m68030|m68851 }, -{"ptestw", two(0xf000,0x8100), two(0xffc0,0xe31e), "f3&st8A9", m68030|m68851 }, -{"ptestw", one(0xf548), one(0xfff8), "as", m68040 }, - -{"ptrapac.w", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapac.l", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapas.w", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapas.l", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapbc.w", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapbc.l", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapbs.w", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapbs.l", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapcc.w", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapcc.l", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapcs.w", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapcs.l", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapgc.w", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapgc.l", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapgs.w", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapgs.l", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapic.w", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapic.l", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapis.w", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapis.l", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), "", m68851 }, - -{"ptraplc.w", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w", m68851 }, -{"ptraplc.l", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l", m68851 }, -{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapls.w", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapls.l", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapsc.w", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapsc.l", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapss.w", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapss.l", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapwc.w", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapwc.l", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), "", m68851 }, - -{"ptrapws.w", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w", m68851 }, -{"ptrapws.l", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l", m68851 }, -{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), "", m68851 }, - -{"pulse", one(0045314), one(0177777), "", m68060 | mcf5200 }, - -{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s", m68851 }, -{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s", m68851 }, - - -{"reset", one(0047160), one(0177777), "", m68000up }, - -{"rol.b", one(0160430), one(0170770), "QdDs", m68000up }, -{"rol.b", one(0160470), one(0170770), "DdDs", m68000up }, -{"rol.w", one(0160530), one(0170770), "QdDs", m68000up }, -{"rol.w", one(0160570), one(0170770), "DdDs", m68000up }, -{"rol.w", one(0163700), one(0177700), "~s", m68000up }, -{"rol.l", one(0160630), one(0170770), "QdDs", m68000up }, -{"rol.l", one(0160670), one(0170770), "DdDs", m68000up }, - -{"ror.b", one(0160030), one(0170770), "QdDs", m68000up }, -{"ror.b", one(0160070), one(0170770), "DdDs", m68000up }, -{"ror.w", one(0160130), one(0170770), "QdDs", m68000up }, -{"ror.w", one(0160170), one(0170770), "DdDs", m68000up }, -{"ror.w", one(0163300), one(0177700), "~s", m68000up }, -{"ror.l", one(0160230), one(0170770), "QdDs", m68000up }, -{"ror.l", one(0160270), one(0170770), "DdDs", m68000up }, - -{"roxl.b", one(0160420), one(0170770), "QdDs", m68000up }, -{"roxl.b", one(0160460), one(0170770), "DdDs", m68000up }, -{"roxl.w", one(0160520), one(0170770), "QdDs", m68000up }, -{"roxl.w", one(0160560), one(0170770), "DdDs", m68000up }, -{"roxl.w", one(0162700), one(0177700), "~s", m68000up }, -{"roxl.l", one(0160620), one(0170770), "QdDs", m68000up }, -{"roxl.l", one(0160660), one(0170770), "DdDs", m68000up }, - -{"roxr.b", one(0160020), one(0170770), "QdDs", m68000up }, -{"roxr.b", one(0160060), one(0170770), "DdDs", m68000up }, -{"roxr.w", one(0160120), one(0170770), "QdDs", m68000up }, -{"roxr.w", one(0160160), one(0170770), "DdDs", m68000up }, -{"roxr.w", one(0162300), one(0177700), "~s", m68000up }, -{"roxr.l", one(0160220), one(0170770), "QdDs", m68000up }, -{"roxr.l", one(0160260), one(0170770), "DdDs", m68000up }, - -{"rtd", one(0047164), one(0177777), "#w", m68010up }, - -{"rte", one(0047163), one(0177777), "", m68000up|mcf5200 }, - -{"rtm", one(0003300), one(0177760), "Rs", m68020 }, - -{"rtr", one(0047167), one(0177777), "", m68000up }, - -{"rts", one(0047165), one(0177777), "", m68000up|mcf5200 }, - -{"sbcd", one(0100400), one(0170770), "DsDd", m68000up }, -{"sbcd", one(0100410), one(0170770), "-s-d", m68000up }, - - -{"scc", one(0052300), one(0177700), "$s", m68000up }, -{"scc", one(0052300), one(0177700), "Ds", mcf5200 }, -{"scs", one(0052700), one(0177700), "$s", m68000up }, -{"scs", one(0052700), one(0177700), "Ds", mcf5200 }, -{"seq", one(0053700), one(0177700), "$s", m68000up }, -{"seq", one(0053700), one(0177700), "Ds", mcf5200 }, -{"sf", one(0050700), one(0177700), "$s", m68000up }, -{"sf", one(0050700), one(0177700), "Ds", mcf5200 }, -{"sge", one(0056300), one(0177700), "$s", m68000up }, -{"sge", one(0056300), one(0177700), "Ds", mcf5200 }, -{"sgt", one(0057300), one(0177700), "$s", m68000up }, -{"sgt", one(0057300), one(0177700), "Ds", mcf5200 }, -{"shi", one(0051300), one(0177700), "$s", m68000up }, -{"shi", one(0051300), one(0177700), "Ds", mcf5200 }, -{"sle", one(0057700), one(0177700), "$s", m68000up }, -{"sle", one(0057700), one(0177700), "Ds", mcf5200 }, -{"sls", one(0051700), one(0177700), "$s", m68000up }, -{"sls", one(0051700), one(0177700), "Ds", mcf5200 }, -{"slt", one(0056700), one(0177700), "$s", m68000up }, -{"slt", one(0056700), one(0177700), "Ds", mcf5200 }, -{"smi", one(0055700), one(0177700), "$s", m68000up }, -{"smi", one(0055700), one(0177700), "Ds", mcf5200 }, -{"sne", one(0053300), one(0177700), "$s", m68000up }, -{"sne", one(0053300), one(0177700), "Ds", mcf5200 }, -{"spl", one(0055300), one(0177700), "$s", m68000up }, -{"spl", one(0055300), one(0177700), "Ds", mcf5200 }, -{"st", one(0050300), one(0177700), "$s", m68000up }, -{"st", one(0050300), one(0177700), "Ds", mcf5200 }, -{"svc", one(0054300), one(0177700), "$s", m68000up }, -{"svc", one(0054300), one(0177700), "Ds", mcf5200 }, -{"svs", one(0054700), one(0177700), "$s", m68000up }, -{"svs", one(0054700), one(0177700), "Ds", mcf5200 }, - -{"stop", one(0047162), one(0177777), "#w", m68000up | mcf5200 }, - -{"suba.l", one(0110700), one(0170700), "*lAd", m68000up | mcf5200 }, -{"suba.w", one(0110300), one(0170700), "*wAd", m68000up }, - -{"subi.b", one(0002000), one(0177700), "#b$s", m68000up }, -{"subi.w", one(0002100), one(0177700), "#w$s", m68000up }, -{"subi.l", one(0002200), one(0177700), "#l$s", m68000up }, -{"subi.l", one(0002200), one(0177700), "#lDs", mcf5200 }, - -{"subq.b", one(0050400), one(0170700), "Qd%s", m68000up }, -{"subq.w", one(0050500), one(0170700), "Qd%s", m68000up }, -{"subq.l", one(0050600), one(0170700), "Qd%s", m68000up | mcf5200 }, - -/* The sub opcode can generate the suba, subi, and subq instructions. */ -{"sub.b", one(0050400), one(0170700), "Qd%s", m68000up }, -{"sub.b", one(0002000), one(0177700), "#b$s", m68000up }, -{"sub.b", one(0110000), one(0170700), ";bDd", m68000up }, -{"sub.b", one(0110400), one(0170700), "Dd~s", m68000up }, -{"sub.w", one(0050500), one(0170700), "Qd%s", m68000up }, -{"sub.w", one(0002100), one(0177700), "#w$s", m68000up }, -{"sub.w", one(0110300), one(0170700), "*wAd", m68000up }, -{"sub.w", one(0110100), one(0170700), "*wDd", m68000up }, -{"sub.w", one(0110500), one(0170700), "Dd~s", m68000up }, -{"sub.l", one(0050600), one(0170700), "Qd%s", m68000up | mcf5200 }, -{"sub.l", one(0002200), one(0177700), "#l$s", m68000up }, -{"sub.l", one(0002200), one(0177700), "#lDs", mcf5200 }, -{"sub.l", one(0110700), one(0170700), "*lAd", m68000up | mcf5200 }, -{"sub.l", one(0110200), one(0170700), "*lDd", m68000up | mcf5200 }, -{"sub.l", one(0110600), one(0170700), "Dd~s", m68000up | mcf5200 }, - -{"subx.b", one(0110400), one(0170770), "DsDd", m68000up }, -{"subx.b", one(0110410), one(0170770), "-s-d", m68000up }, -{"subx.w", one(0110500), one(0170770), "DsDd", m68000up }, -{"subx.w", one(0110510), one(0170770), "-s-d", m68000up }, -{"subx.l", one(0110600), one(0170770), "DsDd", m68000up | mcf5200 }, -{"subx.l", one(0110610), one(0170770), "-s-d", m68000up }, - -{"swap", one(0044100), one(0177770), "Ds", m68000up | mcf5200 }, - -/* swbeg and swbegl are magic constants used on sysV68. The compiler - generates them before a switch table. They tell the debugger and - disassembler that a switch table follows. The parameter is the - number of elements in the table. swbeg means that the entries in - the table are word (2 byte) sized, and swbegl means that the - entries in the table are longword (4 byte) sized. */ -{"swbeg", one(0045374), one(0177777), "#w", m68000up | mcf5200 }, -{"swbeg.l", one(0045375), one(0177777), "#l", m68000up | mcf5200 }, - -{"tas", one(0045300), one(0177700), "$s", m68000up }, - -#define TBL1(name,signed,round,size) \ - {name, two(0174000, (signed<<11)|(!round<<10)|(size<<6)|0000400), \ - two(0177700,0107777), "!sD1", cpu32 }, \ - {name, two(0174000, (signed<<11)|(!round<<10)|(size<<6)), \ - two(0177770,0107770), "DsD3D1", cpu32 } -#define TBL(name1, name2, name3, s, r) \ - TBL1(name1, s, r, 0), TBL1(name2, s, r, 1), TBL1(name3, s, r, 2) -TBL("tbls.b", "tbls.w", "tbls.l", 1, 1), -TBL("tblsn.b", "tblsn.w", "tblsn.l", 1, 0), -TBL("tblu.b", "tblu.w", "tblu.l", 0, 1), -TBL("tblun.b", "tblun.w", "tblun.l", 0, 0), - -{"trap", one(0047100), one(0177760), "Ts", m68000up | mcf5200 }, - -{"trapcc", one(0052374), one(0177777), "", m68020up | cpu32 }, -{"trapcs", one(0052774), one(0177777), "", m68020up | cpu32 }, -{"trapeq", one(0053774), one(0177777), "", m68020up | cpu32 }, -{"trapf", one(0050774), one(0177777), "", m68020up | cpu32 | mcf5200 }, -{"trapge", one(0056374), one(0177777), "", m68020up | cpu32 }, -{"trapgt", one(0057374), one(0177777), "", m68020up | cpu32 }, -{"traphi", one(0051374), one(0177777), "", m68020up | cpu32 }, -{"traple", one(0057774), one(0177777), "", m68020up | cpu32 }, -{"trapls", one(0051774), one(0177777), "", m68020up | cpu32 }, -{"traplt", one(0056774), one(0177777), "", m68020up | cpu32 }, -{"trapmi", one(0055774), one(0177777), "", m68020up | cpu32 }, -{"trapne", one(0053374), one(0177777), "", m68020up | cpu32 }, -{"trappl", one(0055374), one(0177777), "", m68020up | cpu32 }, -{"trapt", one(0050374), one(0177777), "", m68020up | cpu32 }, -{"trapvc", one(0054374), one(0177777), "", m68020up | cpu32 }, -{"trapvs", one(0054774), one(0177777), "", m68020up | cpu32 }, - -{"trapcc.w", one(0052372), one(0177777), "#w", m68020up|cpu32 }, -{"trapcs.w", one(0052772), one(0177777), "#w", m68020up|cpu32 }, -{"trapeq.w", one(0053772), one(0177777), "#w", m68020up|cpu32 }, -{"trapf.w", one(0050772), one(0177777), "#w", m68020up|cpu32|mcf5200}, -{"trapge.w", one(0056372), one(0177777), "#w", m68020up|cpu32 }, -{"trapgt.w", one(0057372), one(0177777), "#w", m68020up|cpu32 }, -{"traphi.w", one(0051372), one(0177777), "#w", m68020up|cpu32 }, -{"traple.w", one(0057772), one(0177777), "#w", m68020up|cpu32 }, -{"trapls.w", one(0051772), one(0177777), "#w", m68020up|cpu32 }, -{"traplt.w", one(0056772), one(0177777), "#w", m68020up|cpu32 }, -{"trapmi.w", one(0055772), one(0177777), "#w", m68020up|cpu32 }, -{"trapne.w", one(0053372), one(0177777), "#w", m68020up|cpu32 }, -{"trappl.w", one(0055372), one(0177777), "#w", m68020up|cpu32 }, -{"trapt.w", one(0050372), one(0177777), "#w", m68020up|cpu32 }, -{"trapvc.w", one(0054372), one(0177777), "#w", m68020up|cpu32 }, -{"trapvs.w", one(0054772), one(0177777), "#w", m68020up|cpu32 }, - -{"trapcc.l", one(0052373), one(0177777), "#l", m68020up|cpu32 }, -{"trapcs.l", one(0052773), one(0177777), "#l", m68020up|cpu32 }, -{"trapeq.l", one(0053773), one(0177777), "#l", m68020up|cpu32 }, -{"trapf.l", one(0050773), one(0177777), "#l", m68020up|cpu32|mcf5200}, -{"trapge.l", one(0056373), one(0177777), "#l", m68020up|cpu32 }, -{"trapgt.l", one(0057373), one(0177777), "#l", m68020up|cpu32 }, -{"traphi.l", one(0051373), one(0177777), "#l", m68020up|cpu32 }, -{"traple.l", one(0057773), one(0177777), "#l", m68020up|cpu32 }, -{"trapls.l", one(0051773), one(0177777), "#l", m68020up|cpu32 }, -{"traplt.l", one(0056773), one(0177777), "#l", m68020up|cpu32 }, -{"trapmi.l", one(0055773), one(0177777), "#l", m68020up|cpu32 }, -{"trapne.l", one(0053373), one(0177777), "#l", m68020up|cpu32 }, -{"trappl.l", one(0055373), one(0177777), "#l", m68020up|cpu32 }, -{"trapt.l", one(0050373), one(0177777), "#l", m68020up|cpu32 }, -{"trapvc.l", one(0054373), one(0177777), "#l", m68020up|cpu32 }, -{"trapvs.l", one(0054773), one(0177777), "#l", m68020up|cpu32 }, - -{"trapv", one(0047166), one(0177777), "", m68000up }, - -{"tst.b", one(0045000), one(0177700), ";b", m68020up|cpu32|mcf5200 }, -{"tst.b", one(0045000), one(0177700), "$b", m68000up }, -{"tst.w", one(0045100), one(0177700), "*w", m68020up|cpu32|mcf5200 }, -{"tst.w", one(0045100), one(0177700), "$w", m68000up }, -{"tst.l", one(0045200), one(0177700), "*l", m68020up|cpu32|mcf5200 }, -{"tst.l", one(0045200), one(0177700), "$l", m68000up }, - -{"unlk", one(0047130), one(0177770), "As", m68000up | mcf5200 }, - -{"unpk", one(0100600), one(0170770), "DsDd#w", m68020up }, -{"unpk", one(0100610), one(0170770), "-s-d#w", m68020up }, - -{"wddata.b", one(0172000), one(0177700), "~s", mcf5200 }, -{"wddata.w", one(0172100), one(0177700), "~s", mcf5200 }, -{"wddata.l", one(0172200), one(0177700), "~s", mcf5200 }, - -}; - -const int m68k_numopcodes = sizeof m68k_opcodes / sizeof m68k_opcodes[0]; - -/* These aliases used to be in the above table, each one duplicating - all of the entries for its primary exactly. This table was - constructed by mechanical processing of the opcode table, with a - small number of tweaks done by hand. There are probably a lot more - aliases above that could be moved down here, except for very minor - differences. */ - -const struct m68k_opcode_alias m68k_opcode_aliases[] = -{ - { "add", "add.w", }, - { "adda", "adda.w", }, - { "addi", "addi.w", }, - { "addq", "addq.w", }, - { "addx", "addx.w", }, - { "asl", "asl.w", }, - { "asr", "asr.w", }, - { "bhi", "bhi.w", }, - { "bls", "bls.w", }, - { "bcc", "bcc.w", }, - { "bcs", "bcs.w", }, - { "bne", "bne.w", }, - { "beq", "beq.w", }, - { "bvc", "bvc.w", }, - { "bvs", "bvs.w", }, - { "bpl", "bpl.w", }, - { "bmi", "bmi.w", }, - { "bge", "bge.w", }, - { "blt", "blt.w", }, - { "bgt", "bgt.w", }, - { "ble", "ble.w", }, - { "bra", "bra.w", }, - { "bsr", "bsr.w", }, - { "bhi.b", "bhi.s", }, - { "bls.b", "bls.s", }, - { "bcc.b", "bcc.s", }, - { "bcs.b", "bcs.s", }, - { "bne.b", "bne.s", }, - { "beq.b", "beq.s", }, - { "bvc.b", "bvc.s", }, - { "bvs.b", "bvs.s", }, - { "bpl.b", "bpl.s", }, - { "bmi.b", "bmi.s", }, - { "bge.b", "bge.s", }, - { "blt.b", "blt.s", }, - { "bgt.b", "bgt.s", }, - { "ble.b", "ble.s", }, - { "bra.b", "bra.s", }, - { "bsr.b", "bsr.s", }, - { "bhs", "bcc.w" }, - { "bhs.s", "bcc.s" }, - { "bhs.b", "bcc.s" }, - { "bhs.w", "bcc.w" }, - { "bhs.l", "bcc.l" }, - { "blo", "bcs.w" }, - { "blo.s", "bcs.s" }, - { "blo.b", "bcs.s" }, - { "blo.w", "bcs.w" }, - { "blo.l", "bcs.l" }, - { "br", "bra.w", }, - { "br.s", "bra.s", }, - { "br.b", "bra.s", }, - { "br.w", "bra.w", }, - { "br.l", "bra.l", }, - { "jfnlt", "bcc", }, /* apparently a sun alias */ - { "jfngt", "ble", }, /* apparently a sun alias */ - { "jfeq", "beq.s", }, /* apparently a sun alias */ - { "bchg.b", "bchg", }, - { "bchg.l", "bchg", }, - { "bclr.b", "bclr", }, - { "bclr.l", "bclr", }, - { "bset.b", "bset", }, - { "bset.l", "bset", }, - { "btst.b", "btst", }, - { "btst.l", "btst", }, - { "cas2", "cas2.w", }, - { "cas", "cas.w", }, - { "chk2", "chk2.w", }, - { "chk", "chk.w", }, - { "clr", "clr.w", }, - { "cmp2", "cmp2.w", }, - { "cmpa", "cmpa.w", }, - { "cmpi", "cmpi.w", }, - { "cmpm", "cmpm.w", }, - { "cmp", "cmp.w", }, - { "dbcc.w", "dbcc", }, - { "dbcs.w", "dbcs", }, - { "dbeq.w", "dbeq", }, - { "dbf.w", "dbf", }, - { "dbge.w", "dbge", }, - { "dbgt.w", "dbgt", }, - { "dbhi.w", "dbhi", }, - { "dble.w", "dble", }, - { "dbls.w", "dbls", }, - { "dblt.w", "dblt", }, - { "dbmi.w", "dbmi", }, - { "dbne.w", "dbne", }, - { "dbpl.w", "dbpl", }, - { "dbt.w", "dbt", }, - { "dbvc.w", "dbvc", }, - { "dbvs.w", "dbvs", }, - { "dbhs", "dbcc", }, - { "dbhs.w", "dbcc", }, - { "dbra", "dbf", }, - { "dbra.w", "dbf", }, - { "tdivs.l", "divs.l", }, - { "divs", "divs.w", }, - { "divu", "divu.w", }, - { "ext", "ext.w", }, - { "extb.w", "ext.w", }, - { "extw.l", "ext.l", }, - { "fbneq", "fbne", }, - { "fbsneq", "fbsne", }, - { "fdbneq", "fdbne", }, - { "fdbsneq", "fdbsne", }, - { "fmovecr", "fmovecrx", }, - { "fmovm", "fmovem", }, - { "fsneq", "fsne", }, - { "fssneq", "fssne", }, - { "ftrapneq", "ftrapne", }, - { "ftrapsneq", "ftrapsne", }, - { "fjneq", "fjne", }, - { "fjsneq", "fjsne", }, - { "jmp.l", "jmp", }, - { "jmp.s", "jmp", }, - { "jsr.l", "jsr", }, - { "jsr.s", "jsr", }, - { "lea.l", "lea", }, - { "lsl", "lsl.w", }, - { "lsr", "lsr.w", }, - { "movea", "movea.w", }, - { "movem", "movem.w", }, - { "movm.l", "movem.l", }, - { "movm.w", "movem.w", }, - { "movm", "movem.w", }, - { "movep", "movep.w", }, - { "movp.w", "movep.w", }, - { "moves", "moves.w" }, - { "muls", "muls.w", }, - { "mulu", "mulu.w", }, - { "nbcd.b", "nbcd" }, - { "neg", "neg.w", }, - { "negx", "negx.w", }, - { "not", "not.w", }, - { "pea.l", "pea", }, - { "rol", "rol.w", }, - { "ror", "ror.w", }, - { "roxl", "roxl.w", }, - { "roxr", "roxr.w", }, - { "sbcd.b", "sbcd", }, - { "scc.b", "scc", }, - { "scs.b", "scs", }, - { "seq.b", "seq", }, - { "sf.b", "sf", }, - { "sge.b", "sge", }, - { "sgt.b", "sgt", }, - { "shi.b", "shi", }, - { "sle.b", "sle", }, - { "sls.b", "sls", }, - { "slt.b", "slt", }, - { "smi.b", "smi", }, - { "sne.b", "sne", }, - { "spl.b", "spl", }, - { "st.b", "st", }, - { "svc.b", "svc", }, - { "svs.b", "svs", }, - { "sfge", "sge", }, - { "sfgt", "sgt", }, - { "sfle", "sle", }, - { "sflt", "slt", }, - { "sfneq", "sne", }, - { "suba", "suba.w", }, - { "subi", "subi.w", }, - { "subq", "subq.w", }, - { "sub", "sub.w", }, - { "subx", "subx.w", }, - { "swap.w", "swap", }, - { "tas.b", "tas", }, - { "tpcc", "trapcc", }, - { "tcc", "trapcc", }, - { "tst", "tst.w", }, - { "jbra", "jra", }, - { "jbhi", "jhi", }, - { "jbls", "jls", }, - { "jbcc", "jcc", }, - { "jbcs", "jcs", }, - { "jbne", "jne", }, - { "jbeq", "jeq", }, - { "jbvc", "jvc", }, - { "jbvs", "jvs", }, - { "jbpl", "jpl", }, - { "jbmi", "jmi", }, - { "jbge", "jge", }, - { "jblt", "jlt", }, - { "jbgt", "jgt", }, - { "jble", "jle", }, - { "movq.l", "moveq", }, - { "moveq.l", "moveq", }, - { "mov.l", "move.l", }, - { "movq", "moveq", }, - { "mova.l", "movea.l", }, - { "mova.w", "movea.w", }, - { "mov.b", "move.b", }, - { "movc", "movec", }, - { "movec.l", "movec", }, - { "movp.l", "movep.l", }, - { "mov.w", "move.w", }, - { "movs.b", "moves.b", }, - { "movs.l", "moves.l", }, - { "movs.w", "moves.w", }, - - { "tdivu.l", "divu.l", }, /* for m68k-svr4 */ - { "fmov.b", "fmove.b", }, - { "fsmov.b", "fsmove.b", }, - { "fdmov.b", "fdmove.b", }, - { "fmov.d", "fmove.d", }, - { "fsmov.d", "fsmove.d", }, - { "fmov.l", "fmove.l", }, - { "fsmov.l", "fsmove.l", }, - { "fdmov.l", "fdmove.l", }, - { "fmov.p", "fmove.p", }, - { "fsmov.p", "fsmove.p", }, - { "fdmov.p", "fdmove.p", }, - { "fmov.s", "fmove.s", }, - { "fsmov.s", "fsmove.s", }, - { "fdmov.s", "fdmove.s", }, - { "fmov.w", "fmove.w", }, - { "fsmov.w", "fsmove.w", }, - { "fdmov.w", "fdmove.w", }, - { "fmov.x", "fmove.x", }, - { "fsmov.x", "fsmove.x", }, - { "fdmov.x", "fdmove.x", }, - { "fmovcr", "fmovecr", }, - { "fmovcr.x", "fmovecr.x", }, - { "ftest.b", "ftst.b", }, - { "ftest.d", "ftst.d", }, - { "ftest.l", "ftst.l", }, - { "ftest.p", "ftst.p", }, - { "ftest.s", "ftst.s", }, - { "ftest.w", "ftst.w", }, - { "ftest.x", "ftst.x", }, -}; - -const int m68k_numaliases = - sizeof m68k_opcode_aliases / sizeof m68k_opcode_aliases[0]; diff --git a/cxmon/src/disass/m68k.h b/cxmon/src/disass/m68k.h deleted file mode 100644 index 4d27d7f7..00000000 --- a/cxmon/src/disass/m68k.h +++ /dev/null @@ -1,315 +0,0 @@ -/* Opcode table header for m680[01234]0/m6888[12]/m68851. - Copyright 1989, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation. - -This file is part of GDB, GAS, and the GNU binutils. - -GDB, GAS, and the GNU binutils are free software; you can redistribute -them and/or modify them under the terms of the GNU General Public -License as published by the Free Software Foundation; either version -1, or (at your option) any later version. - -GDB, GAS, and the GNU binutils are distributed in the hope that they -will be useful, but WITHOUT ANY WARRANTY; without even the implied -warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this file; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -/* These are used as bit flags for the arch field in the m68k_opcode - structure. */ -#define _m68k_undef 0 -#define m68000 0x001 -#define m68008 m68000 /* synonym for -m68000. otherwise unused. */ -#define m68010 0x002 -#define m68020 0x004 -#define m68030 0x008 -#define m68ec030 m68030 /* similar enough to -m68030 to ignore differences; - gas will deal with the few differences. */ -#define m68040 0x010 -/* there is no 68050 */ -#define m68060 0x020 -#define m68881 0x040 -#define m68882 m68881 /* synonym for -m68881. otherwise unused. */ -#define m68851 0x080 -#define cpu32 0x100 /* e.g., 68332 */ -#define mcf5200 0x200 - - /* handy aliases */ -#define m68040up (m68040 | m68060) -#define m68030up (m68030 | m68040up) -#define m68020up (m68020 | m68030up) -#define m68010up (m68010 | cpu32 | m68020up) -#define m68000up (m68000 | m68010up) - -#define mfloat (m68881 | m68882 | m68040 | m68060) -#define mmmu (m68851 | m68030 | m68040 | m68060) - -/* The structure used to hold information for an opcode. */ - -struct m68k_opcode -{ - /* The opcode name. */ - const char *name; - /* The opcode itself. */ - unsigned long opcode; - /* The mask used by the disassembler. */ - unsigned long match; - /* The arguments. */ - const char *args; - /* The architectures which support this opcode. */ - unsigned int arch; -}; - -/* The structure used to hold information for an opcode alias. */ - -struct m68k_opcode_alias -{ - /* The alias name. */ - const char *alias; - /* The instruction for which this is an alias. */ - const char *primary; -}; - -/* We store four bytes of opcode for all opcodes because that is the - most any of them need. The actual length of an instruction is - always at least 2 bytes, and is as much longer as necessary to hold - the operands it has. - - The match field is a mask saying which bits must match particular - opcode in order for an instruction to be an instance of that - opcode. - - The args field is a string containing two characters for each - operand of the instruction. The first specifies the kind of - operand; the second, the place it is stored. */ - -/* Kinds of operands: - Characters used: AaBCcDdFfIJkLlMmnOopQqRrSsTtUVvWXYZ0123|*~%;@!&$?/<>#^+- - - D data register only. Stored as 3 bits. - A address register only. Stored as 3 bits. - a address register indirect only. Stored as 3 bits. - R either kind of register. Stored as 4 bits. - r either kind of register indirect only. Stored as 4 bits. - At the moment, used only for cas2 instruction. - F floating point coprocessor register only. Stored as 3 bits. - O an offset (or width): immediate data 0-31 or data register. - Stored as 6 bits in special format for BF... insns. - + autoincrement only. Stored as 3 bits (number of the address register). - - autodecrement only. Stored as 3 bits (number of the address register). - Q quick immediate data. Stored as 3 bits. - This matches an immediate operand only when value is in range 1 .. 8. - M moveq immediate data. Stored as 8 bits. - This matches an immediate operand only when value is in range -128..127 - T trap vector immediate data. Stored as 4 bits. - - k K-factor for fmove.p instruction. Stored as a 7-bit constant or - a three bit register offset, depending on the field type. - - # immediate data. Stored in special places (b, w or l) - which say how many bits to store. - ^ immediate data for floating point instructions. Special places - are offset by 2 bytes from '#'... - B pc-relative address, converted to an offset - that is treated as immediate data. - d displacement and register. Stores the register as 3 bits - and stores the displacement in the entire second word. - - C the CCR. No need to store it; this is just for filtering validity. - S the SR. No need to store, just as with CCR. - U the USP. No need to store, just as with CCR. - - I Coprocessor ID. Not printed if 1. The Coprocessor ID is always - extracted from the 'd' field of word one, which means that an extended - coprocessor opcode can be skipped using the 'i' place, if needed. - - s System Control register for the floating point coprocessor. - - J Misc register for movec instruction, stored in 'j' format. - Possible values: - 0x000 SFC Source Function Code reg [60, 40, 30, 20, 10] - 0x001 DFC Data Function Code reg [60, 40, 30, 20, 10] - 0x002 CACR Cache Control Register [60, 40, 30, 20] - 0x003 TC MMU Translation Control [60, 40] - 0x004 ITT0 Instruction Transparent - Translation reg 0 [60, 40] - 0x005 ITT1 Instruction Transparent - Translation reg 1 [60, 40] - 0x006 DTT0 Data Transparent - Translation reg 0 [60, 40] - 0x007 DTT1 Data Transparent - Translation reg 1 [60, 40] - 0x008 BUSCR Bus Control Register [60] - 0x800 USP User Stack Pointer [60, 40, 30, 20, 10] - 0x801 VBR Vector Base reg [60, 40, 30, 20, 10] - 0x802 CAAR Cache Address Register [ 30, 20] - 0x803 MSP Master Stack Pointer [ 40, 30, 20] - 0x804 ISP Interrupt Stack Pointer [ 40, 30, 20] - 0x805 MMUSR MMU Status reg [ 40] - 0x806 URP User Root Pointer [60, 40] - 0x807 SRP Supervisor Root Pointer [60, 40] - 0x808 PCR Processor Configuration reg [60] - 0xC00 ROMBAR ROM Base Address Register [520X] - 0xC04 RAMBAR0 RAM Base Address Register 0 [520X] - 0xC05 RAMBAR1 RAM Base Address Register 0 [520X] - 0xC0F MBAR0 RAM Base Address Register 0 [520X] - - L Register list of the type d0-d7/a0-a7 etc. - (New! Improved! Can also hold fp0-fp7, as well!) - The assembler tries to see if the registers match the insn by - looking at where the insn wants them stored. - - l Register list like L, but with all the bits reversed. - Used for going the other way. . . - - c cache identifier which may be "nc" for no cache, "ic" - for instruction cache, "dc" for data cache, or "bc" - for both caches. Used in cinv and cpush. Always - stored in position "d". - - The remainder are all stored as 6 bits using an address mode and a - register number; they differ in which addressing modes they match. - - * all (modes 0-6,7.0-4) - ~ alterable memory (modes 2-6,7.0,7.1) - (not 0,1,7.2-4) - % alterable (modes 0-6,7.0,7.1) - (not 7.2-4) - ; data (modes 0,2-6,7.0-4) - (not 1) - @ data, but not immediate (modes 0,2-6,7.0-3) - (not 1,7.4) - ! control (modes 2,5,6,7.0-3) - (not 0,1,3,4,7.4) - & alterable control (modes 2,5,6,7.0,7.1) - (not 0,1,7.2-4) - $ alterable data (modes 0,2-6,7.0,7.1) - (not 1,7.2-4) - ? alterable control, or data register (modes 0,2,5,6,7.0,7.1) - (not 1,3,4,7.2-4) - / control, or data register (modes 0,2,5,6,7.0-3) - (not 1,3,4,7.4) - > *save operands (modes 2,4,5,6,7.0,7.1) - (not 0,1,3,7.2-4) - < *restore operands (modes 2,3,5,6,7.0-3) - (not 0,1,4,7.4) - - coldfire move operands: - m (modes 0-4) - n (modes 5,7.2) - o (modes 6,7.0,7.1,7.3,7.4) - p (modes 0-5) - - coldfire bset/bclr/btst operands: - q (modes 0,2-5) - v (modes 0,2-5,7.0,7.1) -*/ - -/* For the 68851: */ -/* - I didn't use much imagination in choosing the - following codes, so many of them aren't very - mnemonic. -rab - - 0 32 bit pmmu register - Possible values: - 000 TC Translation Control Register (68030, 68851) - - 1 16 bit pmmu register - 111 AC Access Control (68851) - - 2 8 bit pmmu register - 100 CAL Current Access Level (68851) - 101 VAL Validate Access Level (68851) - 110 SCC Stack Change Control (68851) - - 3 68030-only pmmu registers (32 bit) - 010 TT0 Transparent Translation reg 0 - (aka Access Control reg 0 -- AC0 -- on 68ec030) - 011 TT1 Transparent Translation reg 1 - (aka Access Control reg 1 -- AC1 -- on 68ec030) - - W wide pmmu registers - Possible values: - 001 DRP Dma Root Pointer (68851) - 010 SRP Supervisor Root Pointer (68030, 68851) - 011 CRP Cpu Root Pointer (68030, 68851) - - f function code register (68030, 68851) - 0 SFC - 1 DFC - - V VAL register only (68851) - - X BADx, BACx (16 bit) - 100 BAD Breakpoint Acknowledge Data (68851) - 101 BAC Breakpoint Acknowledge Control (68851) - - Y PSR (68851) (MMUSR on 68030) (ACUSR on 68ec030) - Z PCSR (68851) - - | memory (modes 2-6, 7.*) - - t address test level (68030 only) - Stored as 3 bits, range 0-7. - Also used for breakpoint instruction now. - -*/ - -/* Places to put an operand, for non-general operands: - s source, low bits of first word. - d dest, shifted 9 in first word - 1 second word, shifted 12 - 2 second word, shifted 6 - 3 second word, shifted 0 - 4 third word, shifted 12 - 5 third word, shifted 6 - 6 third word, shifted 0 - 7 second word, shifted 7 - 8 second word, shifted 10 - 9 second word, shifted 5 - D store in both place 1 and place 3; for divul and divsl. - B first word, low byte, for branch displacements - W second word (entire), for branch displacements - L second and third words (entire), for branch displacements - (also overloaded for move16) - b second word, low byte - w second word (entire) [variable word/long branch offset for dbra] - W second word (entire) (must be signed 16 bit value) - l second and third word (entire) - g variable branch offset for bra and similar instructions. - The place to store depends on the magnitude of offset. - t store in both place 7 and place 8; for floating point operations - c branch offset for cpBcc operations. - The place to store is word two if bit six of word one is zero, - and words two and three if bit six of word one is one. - i Increment by two, to skip over coprocessor extended operands. Only - works with the 'I' format. - k Dynamic K-factor field. Bits 6-4 of word 2, used as a register number. - Also used for dynamic fmovem instruction. - C floating point coprocessor constant - 7 bits. Also used for static - K-factors... - j Movec register #, stored in 12 low bits of second word. - - Places to put operand, for general operands: - d destination, shifted 6 bits in first word - b source, at low bit of first word, and immediate uses one byte - w source, at low bit of first word, and immediate uses two bytes - l source, at low bit of first word, and immediate uses four bytes - s source, at low bit of first word. - Used sometimes in contexts where immediate is not allowed anyway. - f single precision float, low bit of 1st word, immediate uses 4 bytes - F double precision float, low bit of 1st word, immediate uses 8 bytes - x extended precision float, low bit of 1st word, immediate uses 12 bytes - p packed float, low bit of 1st word, immediate uses 12 bytes -*/ - -extern const struct m68k_opcode m68k_opcodes[]; -extern const struct m68k_opcode_alias m68k_opcode_aliases[]; - -extern const int m68k_numopcodes, m68k_numaliases; - -/* end of m68k-opcode.h */ diff --git a/cxmon/src/disass/opintl.h b/cxmon/src/disass/opintl.h deleted file mode 100644 index 1e3c318e..00000000 --- a/cxmon/src/disass/opintl.h +++ /dev/null @@ -1,34 +0,0 @@ -/* opintl.h - opcodes specific header for gettext code. - Copyright (C) 1998 Free Software Foundation, Inc. - - Written by Tom Tromey - - This file is part of the opcodes library used by GAS and the GNU binutils. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#ifdef ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -# ifdef gettext_noop -# define N_(String) gettext_noop (String) -# else -# define N_(String) (String) -# endif -#else -/* Stubs that do something close enough. */ -# define textdomain(String) (String) -# define gettext(String) (String) -# define dgettext(Domain,Message) (Message) -# define dcgettext(Domain,Message,Type) (Message) -# define bindtextdomain(Domain,Directory) (Domain) -# define _(String) (String) -# define N_(String) (String) -/* In this case we don't care about the value. */ -# ifndef LC_MESSAGES -# define LC_MESSAGES 0 -# endif -#endif diff --git a/cxmon/src/main.cpp b/cxmon/src/main.cpp deleted file mode 100644 index 3f40d8a6..00000000 --- a/cxmon/src/main.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * main.cpp - Wrapper program for standalone cxmon - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "mon.h" - - -#ifdef __BEOS__ -#include -#include -#include -#include - -// Detect if program was launched from Shell or Tracker -static bool launched_from_tracker(void) -{ - char *cmd = getenv("_"); - if (cmd == NULL || strlen(cmd) < 7) - return false; - return !strcmp(cmd + strlen(cmd) - 7 , "Tracker"); -} - -// Open Terminal window with given title for stdio, returns false on error -static bool open_stdio(const char *title) -{ - // Create key - char key_name[64]; - bigtime_t t = system_time(); - sprintf(key_name, "%Ld", t); - - // Make pipe names - char out_pipe_name[64], in_pipe_name[64]; - sprintf(out_pipe_name, "/pipe/debug_out_%s", key_name); - sprintf(in_pipe_name, "/pipe/debug_in_%s", key_name); - - // Create semaphore - char sem_name[B_OS_NAME_LENGTH], sem_id_str[B_OS_NAME_LENGTH]; - sprintf(sem_name, "debug_glue_%s", key_name); - sem_id glue_sem = create_sem(0, sem_name); - sprintf(sem_id_str, "%d", glue_sem); - - // Make path for "Terminal" app - char term_path[B_PATH_NAME_LENGTH]; - find_directory(B_BEOS_APPS_DIRECTORY, -1, false, term_path, 1024); - strcat(term_path, "/Terminal"); - - // Load "Terminal" - const char *t_argv[6]; - t_argv[0] = term_path; - t_argv[1] = "-t"; - t_argv[2] = (char *)title; - t_argv[3] = "/bin/debug_glue"; - t_argv[4] = key_name; - t_argv[5] = sem_id_str; - thread_id th = load_image(6, t_argv, (const char **)environ); - if (th < 0) { - delete_sem(glue_sem); - return false; - } - - // Start "Terminal" - resume_thread(th); - status_t err = acquire_sem_etc(glue_sem, 1, B_TIMEOUT, 5000000); - delete_sem(glue_sem); - if (err) - return false; - - // Open input/output pipes - FILE *in = freopen(in_pipe_name, "rb", stdin); - if (in == NULL) - return false; - FILE *out = freopen(out_pipe_name, "wb", stdout); - if (out == NULL) { - fclose(in); - return false; - } - - // Set buffer modes - setvbuf(stdout, NULL, _IOLBF, 0); - return true; -} -#endif - -// Main program -int main(int argc, char **argv) -{ -#ifdef __BEOS__ - // Launched from Tracker? Then open terminal window - if (launched_from_tracker()) { - if (!open_stdio("mon")) - return 1; - } -#endif - - // Execute mon - mon_init(); - mon(argc, argv); - mon_exit(); - return 0; -} diff --git a/cxmon/src/mon.cpp b/cxmon/src/mon.cpp deleted file mode 100644 index f3c6c4e7..00000000 --- a/cxmon/src/mon.cpp +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * mon.cpp - cxmon main program - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include - -#if defined(HAVE_READLINE_H) -extern "C" { -#include -} -#elif defined(HAVE_READLINE_READLINE_H) -extern "C" { -#include -} -#endif - -#if defined(HAVE_HISTORY_H) -extern "C" { -#include -} -#elif defined(HAVE_READLINE_HISTORY_H) -extern "C" { -#include -} -#endif - -#include "mon.h" -#include "mon_cmd.h" -#include "mon_lowmem.h" - -#ifndef VERSION -#define VERSION "3" -#endif - - -// Buffer we're operating on -bool mon_use_real_mem = false; -uint32 mon_mem_size; -static uint8 *mem; - - -// Streams for input, output and error messages -FILE *monin, *monout, *monerr; - -// Input line -static char *input; -static char *in_ptr; -char *mon_args_ptr; - -// Current address, value of '.' in expressions -uintptr mon_dot_address; - -// Current value of ':' in expression -static uint32 colon_value; - - -// Scanner variables -enum Token mon_token; // Last token read -uintptr mon_number; // Contains the number if mon_token==T_NUMBER -char *mon_string; // Contains the string if mon_token==T_STRING -char *mon_name; // Contains the variable name if mon_token==T_NAME - - -// List of installed commands -struct CmdSpec { - const char *name; // Name of command - void (*func)(); // Function that executes this command -}; - -static CmdSpec *cmds; // Array of CmdSpecs -static int num_cmds; // Number of installed commands -static char *cmd_help; // Help text for commands - - -// List of variables -typedef std::map var_map; -static var_map vars; - - -// Prototypes -static void init_abort(); -static void exit_abort(); - -static void read_line(char *prompt); // Scanner -static char get_char(); -static void put_back(char c); -static enum Token get_hex_number(uintptr &i); -static enum Token get_dec_number(uintptr &i); -static enum Token get_char_number(uintptr &i); -static enum Token get_string(char *&str); -static enum Token get_hex_or_name(uintptr &i, char *&name); - -static bool eor_expr(uintptr *number); // Parser -static bool and_expr(uintptr *number); -static bool shift_expr(uintptr *number); -static bool add_expr(uintptr *number); -static bool mul_expr(uintptr *number); -static bool factor(uintptr *number); - - -/* - * Add command to mon - */ - -void mon_add_command(const char *name, void (*func)(), const char *help_text) -{ - num_cmds++; - if (cmds) - cmds = (CmdSpec *)realloc(cmds, num_cmds * sizeof(CmdSpec)); - else - cmds = (CmdSpec *)malloc(sizeof(CmdSpec)); - cmds[num_cmds - 1].name = name; - cmds[num_cmds - 1].func = func; - if (help_text) { - if (cmd_help) { - cmd_help = (char *)realloc(cmd_help, strlen(cmd_help) + strlen(help_text) + 1); - strcat(cmd_help, help_text); - } else - cmd_help = strdup(help_text); - } -} - - -/* - * Print error message - */ - -void mon_error(const char *s) -{ - fprintf(monerr, "*** %s\n", s); -} - - -/* - * CTRL-C pressed? - */ - -static bool was_aborted; -static struct sigaction my_sa; - -#ifdef __BEOS__ -static void handle_abort(int sig, void *arg, vregs *r) -#else -static void handle_abort(int sig) -#endif -{ - was_aborted = true; -} - -static void init_abort() -{ - was_aborted = false; - sigemptyset(&my_sa.sa_mask); -#ifdef __BEOS__ - my_sa.sa_handler = (__signal_func_ptr)handle_abort; - my_sa.sa_userdata = 0; -#else - my_sa.sa_handler = handle_abort; -#endif - my_sa.sa_flags = 0; - sigaction(SIGINT, &my_sa, NULL); -} - -static void exit_abort() -{ - my_sa.sa_handler = SIG_DFL; - sigaction(SIGINT, &my_sa, NULL); -} - -bool mon_aborted() -{ - bool ret = was_aborted; - was_aborted = false; - return ret; -} - - -/* - * Access to buffer - */ - -uint32 (*mon_read_byte)(uintptr adr); - -uint32 mon_read_byte_buffer(uintptr adr) -{ - return mem[adr % mon_mem_size]; -} - -uint32 mon_read_byte_real(uintptr adr) -{ - return *(uint8 *)adr; -} - -void (*mon_write_byte)(uintptr adr, uint32 b); - -void mon_write_byte_buffer(uintptr adr, uint32 b) -{ - mem[adr % mon_mem_size] = b; -} - -void mon_write_byte_real(uintptr adr, uint32 b) -{ - *(uint8 *)adr = b; -} - -uint32 mon_read_half(uintptr adr) -{ - return (mon_read_byte(adr) << 8) | mon_read_byte(adr+1); -} - -void mon_write_half(uintptr adr, uint32 w) -{ - mon_write_byte(adr, w >> 8); - mon_write_byte(adr+1, w); -} - -uint32 mon_read_word(uintptr adr) -{ - return (mon_read_byte(adr) << 24) | (mon_read_byte(adr+1) << 16) | (mon_read_byte(adr+2) << 8) | mon_read_byte(adr+3); -} - -void mon_write_word(uintptr adr, uint32 l) -{ - mon_write_byte(adr, l >> 24); - mon_write_byte(adr+1, l >> 16); - mon_write_byte(adr+2, l >> 8); - mon_write_byte(adr+3, l); -} - - -/* - * Read a line from the keyboard - */ - -static void read_line(char *prompt) -{ -#ifdef HAVE_LIBREADLINE - if (input) - free(input); - input = readline(prompt); - - if (input) { - if (*input) - add_history(input); - } else { - // EOF, quit cxmon - input = (char *)malloc(2); - input[0] = 'x'; - input[1] = 0; - fprintf(monout, "x\n"); - } - - in_ptr = input; -#else - static const unsigned INPUT_LENGTH = 256; - if (!input) - input = (char *)malloc(INPUT_LENGTH); - fprintf(monout, prompt); - fflush(monout); - fgets(in_ptr = input, INPUT_LENGTH, monin); - char *s = strchr(input, '\n'); - if (s != NULL) - *s = 0; -#endif -} - - -/* - * Read a character from the input line - */ - -static char get_char() -{ - return *in_ptr++; -} - - -/* - * Stuff back a character into the input line - */ - -static void put_back(char c) -{ - *(--in_ptr) = c; -} - - -/* - * Scanner: Get a token from the input line - */ - -enum Token mon_get_token() -{ - char c = get_char(); - - // Skip spaces - while (isspace(c)) - c = get_char(); - - switch (c) { - case 0: - return mon_token = T_END; - case '(': - return mon_token = T_LPAREN; - case ')': - return mon_token = T_RPAREN; - case '.': - return mon_token = T_DOT; - case ':': - return mon_token = T_COLON; - case ',': - return mon_token = T_COMMA; - case '+': - return mon_token = T_PLUS; - case '-': - return mon_token = T_MINUS; - case '*': - return mon_token = T_MUL; - case '/': - return mon_token = T_DIV; - case '%': - return mon_token = T_MOD; - case '&': - return mon_token = T_AND; - case '|': - return mon_token = T_OR; - case '^': - return mon_token = T_EOR; - case '<': - if (get_char() == '<') - return mon_token = T_SHIFTL; - else { - mon_error("Unrecognized token"); - return mon_token = T_NULL; - } - case '>': - if (get_char() == '>') - return mon_token = T_SHIFTR; - else { - mon_error("Unrecognized token"); - return mon_token = T_NULL; - } - case '~': - return mon_token = T_NOT; - case '=': - return mon_token = T_ASSIGN; - - case '$': - if ((mon_token = get_hex_number(mon_number)) == T_NULL) - mon_error("'$' must be followed by hexadecimal number"); - return mon_token; - case '_': - if ((mon_token = get_dec_number(mon_number)) == T_NULL) - mon_error("'_' must be followed by decimal number"); - return mon_token; - case '\'': - return mon_token = get_char_number(mon_number); - case '"': - return mon_token = get_string(mon_string); - - default: - if (isalnum(c)) { - put_back(c); - return mon_token = get_hex_or_name(mon_number, mon_name); - } - mon_error("Unrecognized token"); - return mon_token = T_NULL; - } -} - -static enum Token get_hex_number(uintptr &i) -{ - char c = get_char(); - - i = 0; - if (!isxdigit(c)) - return T_NULL; - - do { - c = tolower(c); - if (c < 'a') - i = (i << 4) + (c - '0'); - else - i = (i << 4) + (c - 'a' + 10); - c = get_char(); - } while (isxdigit(c)); - - if (isalnum(c)) - return T_NULL; - else { - put_back(c); - return T_NUMBER; - } -} - -static enum Token get_dec_number(uintptr &i) -{ - char c = get_char(); - - i = 0; - if (!isdigit(c)) - return T_NULL; - - do { - i = (i * 10) + (c - '0'); - c = get_char(); - } while (isdigit(c)); - - if (isalnum(c)) - return T_NULL; - else { - put_back(c); - return T_NUMBER; - } -} - -static enum Token get_char_number(uintptr &i) -{ - char c; - - i = 0; - while ((c = get_char()) != 0) { - if (c == '\'') - return T_NUMBER; - i = (i << 8) + (uint8)c; - } - - mon_error("Unterminated character constant"); - return T_NULL; -} - -static enum Token get_string(char *&str) -{ - // Remember start of string - char *old_in_ptr = in_ptr; - - // Determine string length - char c; - unsigned n = 0; - while ((c = get_char()) != 0) { - n++; - if (c == '"') - break; - } - if (c == 0) { - mon_error("Unterminated string"); - return T_NULL; - } - - // Allocate new buffer (n: size needed including terminating 0) - str = (char *)realloc(str, n); - - // Copy string to buffer - char *p = str; - in_ptr = old_in_ptr; - while (--n) - *p++ = get_char(); - *p++ = 0; - get_char(); // skip closing '"' - return T_STRING; -} - -static enum Token get_hex_or_name(uintptr &i, char *&name) -{ - // Remember start of token - char *old_in_ptr = in_ptr; - - // Try hex number first - if (get_hex_number(i) == T_NUMBER) - return T_NUMBER; - - // Not a hex number, must be a variable name; determine its length - in_ptr = old_in_ptr; - char c = get_char(); - unsigned n = 1; - do { - n++; - c = get_char(); - } while (isalnum(c)); - - // Allocate new buffer (n: size needed including terminating 0) - name = (char *)realloc(name, n); - - // Copy name to buffer - in_ptr = old_in_ptr; - char *p = name; - while (--n) - *p++ = get_char(); - *p = 0; - return T_NAME; -} - - -/* - * expression = eor_expr {OR eor_expr} - * true: OK, false: Error - */ - -bool mon_expression(uintptr *number) -{ - uintptr accu, expr; - - if (!eor_expr(&accu)) - return false; - - for (;;) - switch (mon_token) { - case T_OR: - mon_get_token(); - if (!eor_expr(&expr)) - return false; - accu |= expr; - break; - - default: - *number = accu; - return true; - } -} - - -/* - * eor_expr = and_expr {EOR and_expr} - * true: OK, false: Error - */ - -static bool eor_expr(uintptr *number) -{ - uintptr accu, expr; - - if (!and_expr(&accu)) - return false; - - for (;;) - switch (mon_token) { - case T_EOR: - mon_get_token(); - if (!and_expr(&expr)) - return false; - accu ^= expr; - break; - - default: - *number = accu; - return true; - } -} - - -/* - * and_expr = shift_expr {AND shift_expr} - * true: OK, false: Error - */ - -static bool and_expr(uintptr *number) -{ - uintptr accu, expr; - - if (!shift_expr(&accu)) - return false; - - for (;;) - switch (mon_token) { - case T_AND: - mon_get_token(); - if (!shift_expr(&expr)) - return false; - accu &= expr; - break; - - default: - *number = accu; - return true; - } -} - - -/* - * shift_expr = add_expr {(SHIFTL | SHIFTR) add_expr} - * true: OK, false: Error - */ - -static bool shift_expr(uintptr *number) -{ - uintptr accu, expr; - - if (!add_expr(&accu)) - return false; - - for (;;) - switch (mon_token) { - case T_SHIFTL: - mon_get_token(); - if (!add_expr(&expr)) - return false; - accu <<= expr; - break; - - case T_SHIFTR: - mon_get_token(); - if (!add_expr(&expr)) - return false; - accu >>= expr; - break; - - default: - *number = accu; - return true; - } -} - - -/* - * add_expr = mul_expr {(PLUS | MINUS) mul_expr} - * true: OK, false: Error - */ - -static bool add_expr(uintptr *number) -{ - uintptr accu, expr; - - if (!mul_expr(&accu)) - return false; - - for (;;) - switch (mon_token) { - case T_PLUS: - mon_get_token(); - if (!mul_expr(&expr)) - return false; - accu += expr; - break; - - case T_MINUS: - mon_get_token(); - if (!mul_expr(&expr)) - return false; - accu -= expr; - break; - - default: - *number = accu; - return true; - } -} - - -/* - * mul_expr = factor {(MUL | DIV | MOD) factor} - * true: OK, false: Error - */ - -static bool mul_expr(uintptr *number) -{ - uintptr accu, fact; - - if (!factor(&accu)) - return false; - - for (;;) - switch (mon_token) { - case T_MUL: - mon_get_token(); - if (!factor(&fact)) - return false; - accu *= fact; - break; - - case T_DIV: - mon_get_token(); - if (!factor(&fact)) - return false; - if (fact == 0) { - mon_error("Division by 0"); - return false; - } - accu /= fact; - break; - - case T_MOD: - mon_get_token(); - if (!factor(&fact)) - return false; - if (fact == 0) { - mon_error("Division by 0"); - return false; - } - accu %= fact; - break; - - default: - *number = accu; - return true; - } -} - - -/* - * factor = NUMBER | NAME | DOT | COLON | (PLUS | MINUS | NOT) factor | LPAREN expression RPAREN - * true: OK, false: Error - */ - -static bool factor(uintptr *number) -{ - switch (mon_token) { - case T_NUMBER: - *number = mon_number; - mon_get_token(); - return true; - - case T_NAME:{ - var_map::const_iterator v = vars.find(mon_name); - if (v == vars.end()) - return false; - else { - *number = v->second; - mon_get_token(); - return true; - } - } - - case T_DOT: - *number = mon_dot_address; - mon_get_token(); - return true; - - case T_COLON: - *number = colon_value; - mon_get_token(); - return true; - - case T_PLUS: - mon_get_token(); - return factor(number); - - case T_MINUS: - mon_get_token(); - if (factor(number)) { - *number = -*number; - return true; - } else - return false; - - case T_NOT: - mon_get_token(); - if (factor(number)) { - *number = ~*number; - return true; - } else - return false; - - case T_LPAREN: - mon_get_token(); - if (mon_expression(number)) - if (mon_token == T_RPAREN) { - mon_get_token(); - return true; - } else { - mon_error("Missing ')'"); - return false; - } - else { - mon_error("Error in expression"); - return false; - } - - case T_END: - mon_error("Required argument missing"); - return false; - - default: - mon_error("'(' or number expected"); - return false; - } -} - - -/* - * Set/clear/show variables - * set [var[=value]] - */ - -static void set_var() -{ - if (mon_token == T_END) { - - // Show all variables - if (vars.empty()) - fprintf(monout, "No variables defined\n"); - else { - var_map::const_iterator v = vars.begin(), end = vars.end(); - for (v=vars.begin(); v!=end; ++v) - fprintf(monout, "%s = %08lx\n", v->first.c_str(), v->second); - } - - } else if (mon_token == T_NAME) { - std::string var_name = mon_name; - mon_get_token(); - if (mon_token == T_ASSIGN) { - - // Set variable - uintptr value; - mon_get_token(); - if (!mon_expression(&value)) - return; - if (mon_token != T_END) { - mon_error("Too many arguments"); - return; - } - vars[var_name] = value; - - } else if (mon_token == T_END) { - - // Clear variable - vars.erase(var_name); - - } else - mon_error("'=' expected"); - } else - mon_error("Variable name expected"); -} - - -/* - * Clear all variables - * cv - */ - -static void clear_vars() -{ - vars.clear(); -} - - -/* - * Display help - * h - */ - -static void help_or_hunt() -{ - if (mon_token != T_END) { - hunt(); - return; - } - fprintf(monout, "x Quit mon\n" - "h This help text\n"); - fprintf(monout, cmd_help); -} - - -/* - * Display command list - * ?? - */ - -static void mon_cmd_list() -{ - for (int i=0; i 0) { - if (strcmp(argv[0], "-h") == 0 || strcmp(argv[0], "--help") == 0) { - printf("Usage: %s [-m] [-r] [command...]\n", prg_name); - exit(0); - } else if (strcmp(argv[0], "-m") == 0) - mon_macos_mode = true; - else if (strcmp(argv[0], "-r") == 0) - mon_use_real_mem = true; - else - break; - argc--; argv++; - } - interactive = (argc == 0); - - // Set up memory access functions if not supplied by the user - if (mon_read_byte == NULL) { - if (mon_use_real_mem) - mon_read_byte = mon_read_byte_real; - else - mon_read_byte = mon_read_byte_buffer; - } - if (mon_write_byte == NULL) { - if (mon_use_real_mem) - mon_write_byte = mon_write_byte_real; - else - mon_write_byte = mon_write_byte_buffer; - } - - // Allocate buffer - if (!mon_use_real_mem) { - mon_mem_size = 0x100000; - mem = (uint8 *)malloc(mon_mem_size); - - // Print banner - if (interactive) - fprintf(monerr, "\n *** cxmon V" VERSION " by Christian Bauer and Marc Hellwig ***\n" - " *** Press 'h' for help ***\n\n"); - } - - // Clear variables - vars.clear(); - - // In MacOS mode, pull in the lowmem globals as variables - if (mon_macos_mode) { - const lowmem_info *l = lowmem; - while (l->name) { - vars[l->name] = l->addr; - l++; - } - } - - init_abort(); - - // Read and parse command line - char *cmd = NULL; - while (!done) { - if (interactive) { - char prompt[16]; - sprintf(prompt, "[%0*lx]-> ", int(2 * sizeof(mon_dot_address)), mon_dot_address); - read_line(prompt); - if (!input) { - done = true; - continue; - } - } else { - if (argc == 0) { - done = true; - break; - } else { - unsigned n = strlen(argv[0]) + 1; - input = (char *)realloc(input, n); - strcpy(in_ptr = input, argv[0]); - argc--; - argv++; - } - } - - // Skip leading spaces - char c = get_char(); - while (isspace(c)) - c = get_char(); - put_back(c); - if (!c) - continue; // blank line - - // Read command word - char *p = in_ptr; - while (isgraph(c)) - c = get_char(); - put_back(c); - unsigned n = in_ptr - p; - cmd = (char *)realloc(cmd, n + 1); - memcpy(cmd, p, n); - cmd[n] = 0; - - // Execute command - if (strcmp(cmd, "x") == 0) { // Exit - done = true; - continue; - } - for (int i=0; i - - -/* - * Initialization, deinitialization and invocation - */ - -void mon_init(); -void mon_exit(); -void mon(int argc, char **argv); - - -/* - * Definitions for adding commands to mon - */ - -// Input tokens -enum Token { - T_NULL, // Invalid token - T_END, // End of line - T_NUMBER, // Hexadecimal/decimal number (uint32) - T_STRING, // String enclosed in "" - T_NAME, // Variable name - T_DOT, // '.' - T_COLON, // ':' - T_COMMA, // ',' - T_LPAREN, // '(' - T_RPAREN, // ')' - T_PLUS, // '+' - T_MINUS, // '-' - T_MUL, // '*' - T_DIV, // '/' - T_MOD, // '%' - T_AND, // '&' - T_OR, // '|' - T_EOR, // '^' - T_SHIFTL, // '<<' - T_SHIFTR, // '>>' - T_NOT, // '~' - T_ASSIGN // '=' -}; - -// Scanner variables -extern enum Token mon_token; // Last token read -extern uintptr mon_number; // Contains the number if mon_token==T_NUMBER -extern char *mon_string; // Contains the string if mon_token==T_STRING -extern char *mon_name; // Contains the variable name if mon_token==T_NAME - -// Streams for input, output and error messages -extern FILE *monin, *monout, *monerr; - -// Current address, value of '.' in expressions -extern uintptr mon_dot_address; - -extern bool mon_use_real_mem; // Flag: mon is using real memory -extern uint32 mon_mem_size; // Size of mon buffer (if mon_use_real_mem = false) - -extern bool mon_macos_mode; // Flag: enable features in the disassembler for working with MacOS code - -// Add command to mon -extern void mon_add_command(const char *name, void (*func)(), const char *help_text); - -// Functions for commands -extern void mon_error(const char *s); // Print error message -extern enum Token mon_get_token(); // Get next token -extern bool mon_expression(uintptr *number); // Parse expression -extern bool mon_aborted(); // Check if Ctrl-C was pressed - -// Memory access -extern uint32 (*mon_read_byte)(uintptr adr); -extern void (*mon_write_byte)(uintptr adr, uint32 b); -extern uint32 mon_read_half(uintptr adr); -extern void mon_write_half(uintptr adr, uint32 w); -extern uint32 mon_read_word(uintptr adr); -extern void mon_write_word(uintptr adr, uint32 l); - -#endif diff --git a/cxmon/src/mon_6502.cpp b/cxmon/src/mon_6502.cpp deleted file mode 100644 index 1a2b6a31..00000000 --- a/cxmon/src/mon_6502.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * mon_6502.cpp - 6502 disassembler - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "mon.h" -#include "mon_disass.h" - - -// Addressing modes -enum AddrMode { - A_IMPL, - A_ACCU, // A - A_IMM, // #zz - A_REL, // Branches - A_ZERO, // zz - A_ZEROX, // zz,x - A_ZEROY, // zz,y - A_ABS, // zzzz - A_ABSX, // zzzz,x - A_ABSY, // zzzz,y - A_IND, // (zzzz) - A_INDX, // (zz,x) - A_INDY // (zz),y -}; - -// Mnemonics -enum Mnemonic { - M_ADC, M_AND, M_ASL, M_BCC, M_BCS, M_BEQ, M_BIT, M_BMI, M_BNE, M_BPL, - M_BRK, M_BVC, M_BVS, M_CLC, M_CLD, M_CLI, M_CLV, M_CMP, M_CPX, M_CPY, - M_DEC, M_DEX, M_DEY, M_EOR, M_INC, M_INX, M_INY, M_JMP, M_JSR, M_LDA, - M_LDX, M_LDY, M_LSR, M_NOP, M_ORA, M_PHA, M_PHP, M_PLA, M_PLP, M_ROL, - M_ROR, M_RTI, M_RTS, M_SBC, M_SEC, M_SED, M_SEI, M_STA, M_STX, M_STY, - M_TAX, M_TAY, M_TSX, M_TXA, M_TXS, M_TYA, - - M_ILLEGAL, // Undocumented opcodes start here - - M_IANC, M_IANE, M_IARR, M_IASR, M_IDCP, M_IISB, M_IJAM, M_INOP, M_ILAS, - M_ILAX, M_ILXA, M_IRLA, M_IRRA, M_ISAX, M_ISBC, M_ISBX, M_ISHA, M_ISHS, - M_ISHX, M_ISHY, M_ISLO, M_ISRE, - - M_MAXIMUM // Highest element -}; - -// Mnemonic for each opcode -static const Mnemonic mnemonic[256] = { - M_BRK , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, // 00 - M_PHP , M_ORA , M_ASL , M_IANC, M_INOP, M_ORA, M_ASL , M_ISLO, - M_BPL , M_ORA , M_IJAM, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, // 10 - M_CLC , M_ORA , M_INOP, M_ISLO, M_INOP, M_ORA, M_ASL , M_ISLO, - M_JSR , M_AND , M_IJAM, M_IRLA, M_BIT , M_AND, M_ROL , M_IRLA, // 20 - M_PLP , M_AND , M_ROL , M_IANC, M_BIT , M_AND, M_ROL , M_IRLA, - M_BMI , M_AND , M_IJAM, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA, // 30 - M_SEC , M_AND , M_INOP, M_IRLA, M_INOP, M_AND, M_ROL , M_IRLA, - M_RTI , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, // 40 - M_PHA , M_EOR , M_LSR , M_IASR, M_JMP , M_EOR, M_LSR , M_ISRE, - M_BVC , M_EOR , M_IJAM, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, // 50 - M_CLI , M_EOR , M_INOP, M_ISRE, M_INOP, M_EOR, M_LSR , M_ISRE, - M_RTS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, // 60 - M_PLA , M_ADC , M_ROR , M_IARR, M_JMP , M_ADC, M_ROR , M_IRRA, - M_BVS , M_ADC , M_IJAM, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, // 70 - M_SEI , M_ADC , M_INOP, M_IRRA, M_INOP, M_ADC, M_ROR , M_IRRA, - M_INOP, M_STA , M_INOP, M_ISAX, M_STY , M_STA, M_STX , M_ISAX, // 80 - M_DEY , M_INOP, M_TXA , M_IANE, M_STY , M_STA, M_STX , M_ISAX, - M_BCC , M_STA , M_IJAM, M_ISHA, M_STY , M_STA, M_STX , M_ISAX, // 90 - M_TYA , M_STA , M_TXS , M_ISHS, M_ISHY, M_STA, M_ISHX, M_ISHA, - M_LDY , M_LDA , M_LDX , M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX, // a0 - M_TAY , M_LDA , M_TAX , M_ILXA, M_LDY , M_LDA, M_LDX , M_ILAX, - M_BCS , M_LDA , M_IJAM, M_ILAX, M_LDY , M_LDA, M_LDX , M_ILAX, // b0 - M_CLV , M_LDA , M_TSX , M_ILAS, M_LDY , M_LDA, M_LDX , M_ILAX, - M_CPY , M_CMP , M_INOP, M_IDCP, M_CPY , M_CMP, M_DEC , M_IDCP, // c0 - M_INY , M_CMP , M_DEX , M_ISBX, M_CPY , M_CMP, M_DEC , M_IDCP, - M_BNE , M_CMP , M_IJAM, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP, // d0 - M_CLD , M_CMP , M_INOP, M_IDCP, M_INOP, M_CMP, M_DEC , M_IDCP, - M_CPX , M_SBC , M_INOP, M_IISB, M_CPX , M_SBC, M_INC , M_IISB, // e0 - M_INX , M_SBC , M_NOP , M_ISBC, M_CPX , M_SBC, M_INC , M_IISB, - M_BEQ , M_SBC , M_IJAM, M_IISB, M_INOP, M_SBC, M_INC , M_IISB, // f0 - M_SED , M_SBC , M_INOP, M_IISB, M_INOP, M_SBC, M_INC , M_IISB -}; - -// Addressing mode for each opcode -static const AddrMode adr_mode[256] = { - A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 00 - A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 10 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, - A_ABS , A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 20 - A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 30 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, - A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 40 - A_IMPL, A_IMM , A_ACCU, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 50 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, - A_IMPL, A_INDX, A_IMPL, A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 60 - A_IMPL, A_IMM , A_ACCU, A_IMM , A_IND , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // 70 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, - A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // 80 - A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY, // 90 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY, - A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // a0 - A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROY, A_ZEROY, // b0 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSY , A_ABSY, - A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // c0 - A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // d0 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX, - A_IMM , A_INDX, A_IMM , A_INDX, A_ZERO , A_ZERO , A_ZERO , A_ZERO, // e0 - A_IMPL, A_IMM , A_IMPL, A_IMM , A_ABS , A_ABS , A_ABS , A_ABS, - A_REL , A_INDY, A_IMPL, A_INDY, A_ZEROX, A_ZEROX, A_ZEROX, A_ZEROX, // f0 - A_IMPL, A_ABSY, A_IMPL, A_ABSY, A_ABSX , A_ABSX , A_ABSX , A_ABSX -}; - -// Chars for each mnemonic -static const char mnem_1[] = "aaabbbbbbbbbbcccccccdddeiiijjllllnopppprrrrssssssstttttt?aaaadijnlllrrsssssssss"; -static const char mnem_2[] = "dnscceimnprvvllllmppeeeonnnmsdddsorhhlloottbeeetttaasxxy?nnrscsaoaaxlrabbhhhhlr"; -static const char mnem_3[] = "cdlcsqtielkcscdivpxycxyrcxypraxyrpaapaplrisccdiaxyxyxasa?cerrpbmpsxaaaxcxasxyoe"; - -// Instruction length for each addressing mode -static const int adr_length[] = {1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2}; - - -/* - * Disassemble one instruction, return number of bytes - */ - -int disass_6502(FILE *f, uint32 adr, uint8 op, uint8 lo, uint8 hi) -{ - AddrMode mode = adr_mode[op]; - Mnemonic mnem = mnemonic[op]; - - // Display instruction bytes in hex - switch (adr_length[mode]) { - case 1: - fprintf(f, "%02x\t\t", op); - break; - - case 2: - fprintf(f, "%02x %02x\t\t", op, lo); - break; - - case 3: - fprintf(f, "%02x %02x %02x\t", op, lo, hi); - break; - } - - // Tag undocumented opcodes with an asterisk - if (mnem > M_ILLEGAL) - fputc('*', f); - else - fputc(' ', f); - - // Print mnemonic - fprintf(f, "%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem]); - - // Print argument - switch (mode) { - case A_IMPL: - break; - - case A_ACCU: - fprintf(f, "a"); - break; - - case A_IMM: - fprintf(f, "#$%02x", lo); - break; - - case A_REL: - fprintf(f, "$%04x", (adr + 2) + (int8)lo); - break; - - case A_ZERO: - fprintf(f, "$%02x", lo); - break; - - case A_ZEROX: - fprintf(f, "$%02x,x", lo); - break; - - case A_ZEROY: - fprintf(f, "$%02x,y", lo); - break; - - case A_ABS: - fprintf(f, "$%04x", (hi << 8) | lo); - break; - - case A_ABSX: - fprintf(f, "$%04x,x", (hi << 8) | lo); - break; - - case A_ABSY: - fprintf(f, "$%04x,y", (hi << 8) | lo); - break; - - case A_IND: - fprintf(f, "($%04x)", (hi << 8) | lo); - break; - - case A_INDX: - fprintf(f, "($%02x,x)", lo); - break; - - case A_INDY: - fprintf(f, "($%02x),y", lo); - break; - } - - fputc('\n', f); - return adr_length[mode]; -} diff --git a/cxmon/src/mon_atraps.h b/cxmon/src/mon_atraps.h deleted file mode 100644 index f18c41ce..00000000 --- a/cxmon/src/mon_atraps.h +++ /dev/null @@ -1,1212 +0,0 @@ -/* - * mon_atraps.h - MacOS A-Line trap definitions - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MON_ATRAPS_H -#define MON_ATRAPS_H - -struct atrap_info { - const char *name; - uint16 word; -}; - -// A-Traps in ascending order -static const atrap_info atraps[] = { - {"Open" , 0xA000}, - {"Close" , 0xA001}, - {"Read" , 0xA002}, - {"Write" , 0xA003}, - {"Control" , 0xA004}, - {"Status" , 0xA005}, - {"KillIO" , 0xA006}, - {"GetVolInfo" , 0xA007}, - {"Create" , 0xA008}, - {"Delete" , 0xA009}, - {"OpenRF" , 0xA00A}, - {"Rename" , 0xA00B}, - {"GetFileInfo" , 0xA00C}, - {"SetFileInfo" , 0xA00D}, - {"UnmountVol" , 0xA00E}, - {"MountVol" , 0xA00F}, - {"Allocate" , 0xA010}, - {"GetEOF" , 0xA011}, - {"SetEOF" , 0xA012}, - {"FlushVol" , 0xA013}, - {"GetVol" , 0xA014}, - {"SetVol" , 0xA015}, - {"FInitQueue" , 0xA016}, - {"Eject" , 0xA017}, - {"GetFPos" , 0xA018}, - {"InitZone" , 0xA019}, - {"SetZone" , 0xA01B}, - {"FreeMem" , 0xA01C}, - {"DisposePtr" , 0xA01F}, - {"SetPtrSize" , 0xA020}, - {"GetPtrSize" , 0xA021}, - {"DisposeHandle" , 0xA023}, - {"SetHandleSize" , 0xA024}, - {"GetHandleSize" , 0xA025}, - {"ReallocHandle" , 0xA027}, - {"HLock" , 0xA029}, - {"HUnlock" , 0xA02A}, - {"EmptyHandle" , 0xA02B}, - {"InitApplZone" , 0xA02C}, - {"SetApplLimit" , 0xA02D}, - {"BlockMove" , 0xA02E}, - {"PostEvent" , 0xA02F}, - {"OSEventAvail" , 0xA030}, - {"GetOSEvent" , 0xA031}, - {"FlushEvents" , 0xA032}, - {"VInstall" , 0xA033}, - {"VRemove" , 0xA034}, - {"OffLine" , 0xA035}, - {"MoreMasters" , 0xA036}, - {"ReadParam" , 0xA037}, - {"WriteParam" , 0xA038}, - {"ReadDateTime" , 0xA039}, - {"SetDateTime" , 0xA03A}, - {"Delay" , 0xA03B}, - {"CmpString" , 0xA03C}, - {"DrvrInstall" , 0xA03D}, - {"DrvrRemove" , 0xA03E}, - {"InitUtil" , 0xA03F}, - {"ResrvMem" , 0xA040}, - {"SetFilLock" , 0xA041}, - {"RstFilLock" , 0xA042}, - {"SetFilType" , 0xA043}, - {"SetFPos" , 0xA044}, - {"FlushFile" , 0xA045}, - {"SetTrapAddress" , 0xA047}, - {"HPurge" , 0xA049}, - {"HNoPurge" , 0xA04A}, - {"SetGrowZone" , 0xA04B}, - {"CompactMem" , 0xA04C}, - {"PurgeMem" , 0xA04D}, - {"AddDrive" , 0xA04E}, - {"RDrvrInstall" , 0xA04F}, - {"CompareString" , 0xA050}, - {"ReadXPRam" , 0xA051}, - {"WriteXPRam" , 0xA052}, - {"UprString" , 0xA054}, - {"StripAddress" , 0xA055}, - {"LowerText" , 0xA056}, - {"SetApplBase" , 0xA057}, - {"InsTime" , 0xA058}, - {"RmvTime" , 0xA059}, - {"PrimeTime" , 0xA05A}, - {"PowerOff" , 0xA05B}, - {"MemoryDispatch" , 0xA05C}, - {"SwapMMUMode" , 0xA05D}, - {"NMInstall" , 0xA05E}, - {"NMRemove" , 0xA05F}, - {"FSDispatch" , 0xA060}, - {"MaxBlock" , 0xA061}, - {"MaxApplZone" , 0xA063}, - {"MoveHHi" , 0xA064}, - {"StackSpace" , 0xA065}, - {"HSetRBit" , 0xA067}, - {"HClrRBit" , 0xA068}, - {"HGetState" , 0xA069}, - {"HSetState" , 0xA06A}, - {"TestManager" , 0xA06B}, - {"InitFS" , 0xA06C}, - {"InitEvents" , 0xA06D}, - {"SlotManager" , 0xA06E}, - {"SlotVInstall" , 0xA06F}, - {"SlotVRemove" , 0xA070}, - {"AttachVBL" , 0xA071}, - {"DoVBLTask" , 0xA072}, - {"OSReserved" , 0xA073}, - {"CacheMgr" , 0xA074}, - {"SIntInstall" , 0xA075}, - {"SIntRemove" , 0xA076}, - {"CountADBs" , 0xA077}, - {"GetIndADB" , 0xA078}, - {"GetADBInfo" , 0xA079}, - {"SetADBInfo" , 0xA07A}, - {"ADBReInit" , 0xA07B}, - {"ADBOp" , 0xA07C}, - {"GetDefaultStartup" , 0xA07D}, - {"SetDefaultStartup" , 0xA07E}, - {"InternalWait" , 0xA07F}, - {"GetVideoDefault" , 0xA080}, - {"SetVideoDefault" , 0xA081}, - {"DTInstall" , 0xA082}, - {"SetOSDefault" , 0xA083}, - {"GetOSDefault" , 0xA084}, - {"PMgrOp" , 0xA085}, - {"IOPInfoAccess" , 0xA086}, - {"IOPMsgRequest" , 0xA087}, - {"IOPMoveData" , 0xA088}, - {"SCSIAtomic" , 0xA089}, - {"Sleep" , 0xA08A}, - {"CommToolboxDispatch" , 0xA08B}, - {"Wakeup" , 0xA08C}, - {"DebugUtil" , 0xA08D}, - {"BTreeDispatch" , 0xA08E}, - {"DeferUserFn" , 0xA08F}, - {"SysEnvirons" , 0xA090}, - {"Translate24To32" , 0xA091}, - {"EgretDispatch" , 0xA092}, - {"Microseconds" , 0xA093}, - {"ServerDispatch" , 0xA094}, - {"POGOMPW" , 0xA095}, - {"SharedLibsMPW" , 0xA096}, - {"FPPriv" , 0xA097}, - {"XToolTable" , 0xA099}, - {"vProcHelper" , 0xA09A}, - {"Messager" , 0xA09B}, - {"NewPtrStartup" , 0xA09C}, - {"MoveHLow" , 0xA09D}, - {"PowerMgrDispatch" , 0xA09E}, - {"PowerDispatch" , 0xA09F}, - {"vMRdAddr" , 0xA0A0}, - {"vMRdData" , 0xA0A1}, - {"vMWrData" , 0xA0A2}, - {"HeapDispatch" , 0xA0A4}, - {"VisRegionChanged" , 0xA0A5}, - {"vStdEntry" , 0xA0A6}, - {"vStdExit" , 0xA0A7}, - {"FSM" , 0xA0AC}, - {"vADBProc" , 0xA0AE}, - {"vMtCheck" , 0xA0AF}, - {"vCheckReMount" , 0xA0B0}, - {"vDtrmV2" , 0xA0B1}, - {"vFindDrive" , 0xA0B2}, - {"vFClose" , 0xA0B3}, - {"vFlushMDB" , 0xA0B4}, - {"vGoDriver" , 0xA0B5}, - {"vWaitUntil" , 0xA0B6}, - {"vSyncWait" , 0xA0B7}, - {"vSoundDead" , 0xA0B8}, - {"vDisptch" , 0xA0B9}, - {"vIAZInit" , 0xA0BA}, - {"vIAZPostInit" , 0xA0BB}, - {"vLaunchInit" , 0xA0BC}, - {"vCacheFlush" , 0xA0BD}, - {"vSysUtil" , 0xA0BE}, - {"vLg2Phys" , 0xA0BF}, - {"vFlushCache" , 0xA0C0}, - {"vGetBlock" , 0xA0C1}, - {"vMarkBlock" , 0xA0C2}, - {"vRelBlock" , 0xA0C3}, - {"vTrashBlocks" , 0xA0C4}, - {"vTrashVBlks" , 0xA0C5}, - {"vCacheWrIP" , 0xA0C6}, - {"vCacheRdIP" , 0xA0C7}, - {"vBasicIO" , 0xA0C8}, - {"vRdBlocks" , 0xA0C9}, - {"vWrBlocks" , 0xA0CA}, - {"vSetUpTags" , 0xA0CB}, - {"vBTClose" , 0xA0CC}, - {"vBTDelete" , 0xA0CD}, - {"vBTFlush" , 0xA0CE}, - {"vBTGetRecord" , 0xA0CF}, - {"vBTInsert" , 0xA0D0}, - {"vBTOpen" , 0xA0D1}, - {"vBTSearch" , 0xA0D2}, - {"vBTUpdate" , 0xA0D3}, - {"vGetNode" , 0xA0D4}, - {"vRelNode" , 0xA0D5}, - {"vAllocNode" , 0xA0D6}, - {"vFreeNode" , 0xA0D7}, - {"vExtBTFile" , 0xA0D8}, - {"vDeallocFile" , 0xA0D9}, - {"vExtendFile" , 0xA0DA}, - {"vTruncateFile" , 0xA0DB}, - {"vCMSetup" , 0xA0DC}, - {"PPC" , 0xA0DD}, - {"vDtrmV1" , 0xA0DE}, - {"vBlkAlloc" , 0xA0DF}, - {"vBlkDeAlloc" , 0xA0E0}, - {"vFileOpen" , 0xA0E1}, - {"vPermssnChk" , 0xA0E2}, - {"vFndFilName" , 0xA0E3}, - {"vRfNCall" , 0xA0E4}, - {"vAdjEOF" , 0xA0E5}, - {"vPixel2Char" , 0xA0E6}, - {"vChar2Pixel" , 0xA0E7}, - {"vHiliteText" , 0xA0E8}, - {"vFileClose" , 0xA0E9}, - {"vFileRead" , 0xA0EA}, - {"vFileWrite" , 0xA0EB}, - {"DispatchHelper" , 0xA0EC}, - {"vUpdAltMDB" , 0xA0ED}, - {"vCkExtFS" , 0xA0EE}, - {"vDtrmV3" , 0xA0EF}, - {"vBMChk" , 0xA0F0}, - {"vTstMod" , 0xA0F1}, - {"vLocCRec" , 0xA0F2}, - {"vTreeSearch" , 0xA0F3}, - {"vMapFBlock" , 0xA0F4}, - {"vXFSearch" , 0xA0F5}, - {"vReadBM" , 0xA0F6}, - {"vDoEject" , 0xA0F7}, - {"vSegStack" , 0xA0F8}, - {"vSuperLoad" , 0xA0F9}, - {"vCmpFrm" , 0xA0FA}, - {"vNewMap" , 0xA0FB}, - {"vCheckLoad" , 0xA0FC}, - {"XTrimMeasure" , 0xA0FD}, - {"XFindWord" , 0xA0FE}, - {"XFindLine" , 0xA0FF}, - {"GetZone" , 0xA11A}, - {"MaxMem" , 0xA11D}, - {"NewPtr" , 0xA11E}, - {"NewHandle" , 0xA122}, - {"HandleZone" , 0xA126}, - {"RecoverHandle" , 0xA128}, - {"PPostEvent" , 0xA12F}, - {"DrvrInstall" , 0xA13D}, - {"GetTrapAddress" , 0xA146}, - {"PtrZone" , 0xA148}, - {"MemoryDispatch" , 0xA15C}, - {"PurgeSpace" , 0xA162}, - {"NewEmptyHandle" , 0xA166}, - {"Microseconds" , 0xA193}, - {"HWPriv" , 0xA198}, - {"Gestalt" , 0xA1AD}, - {"HOpen" , 0xA200}, - {"HGetVInfo" , 0xA207}, - {"HCreate" , 0xA208}, - {"HDelete" , 0xA209}, - {"HOpenRF" , 0xA20A}, - {"HRename" , 0xA20B}, - {"HGetFileInfo" , 0xA20C}, - {"HSetFileInfo" , 0xA20D}, - {"HUnmountVol" , 0xA20E}, - {"AllocContig" , 0xA210}, - {"HGetVol" , 0xA214}, - {"HSetVol" , 0xA215}, - {"BlockMoveData" , 0xA22E}, - {"HSetFLock" , 0xA241}, - {"HRstFLock" , 0xA242}, - {"SetOSTrapAddress" , 0xA247}, - {"StripText" , 0xA256}, - {"HFSDispatch" , 0xA260}, - {"IdleUpdate" , 0xA285}, - {"SleepQInstall" , 0xA28A}, - {"NewPtrClear" , 0xA31E}, - {"NewHandleClear" , 0xA322}, - {"GetOSTrapAddress" , 0xA346}, - {"NewGestalt" , 0xA3AD}, - {"DrvrInstallRsrvMem" , 0xA43D}, - {"UpperText" , 0xA456}, - {"InsXTime" , 0xA458}, - {"IdleState" , 0xA485}, - {"SleepQRemove" , 0xA48A}, - {"NewPtrSys" , 0xA51E}, - {"NewHandleSys" , 0xA522}, - {"DrvrInstallRsrvMem" , 0xA53D}, - {"PurgeSpaceSys" , 0xA562}, - {"ReplaceGestalt" , 0xA5AD}, - {"SetToolBoxTrapAddress" , 0xA647}, - {"StripUpperText" , 0xA656}, - {"SerialPower" , 0xA685}, - {"NewPtrSysClear" , 0xA71E}, - {"NewHandleSysClear" , 0xA722}, - {"GetToolBoxTrapAddress" , 0xA746}, - {"GetToolTrapAddress" , 0xA746}, - {"GetGestaltProcPtr" , 0xA7AD}, - {"SoundDispatch" , 0xA800}, - {"SndDisposeChannel" , 0xA801}, - {"SndAddModifier" , 0xA802}, - {"SndDoCommand" , 0xA803}, - {"SndDoImmediate" , 0xA804}, - {"SndPlay" , 0xA805}, - {"SndControl" , 0xA806}, - {"SndNewChannel" , 0xA807}, - {"InitProcMenu" , 0xA808}, - {"GetControlVariant" , 0xA809}, - {"GetWVariant" , 0xA80A}, - {"PopUpMenuSelect" , 0xA80B}, - {"RGetResource" , 0xA80C}, - {"Count1Resources" , 0xA80D}, - {"Get1IxResource" , 0xA80E}, - {"Get1IxType" , 0xA80F}, - {"Unique1ID" , 0xA810}, - {"TESelView" , 0xA811}, - {"TEPinScroll" , 0xA812}, - {"TEAutoView" , 0xA813}, - {"SetFractEnable" , 0xA814}, - {"SCSIDispatch" , 0xA815}, - {"Pack8" , 0xA816}, - {"CopyMask" , 0xA817}, - {"FixATan2" , 0xA818}, - {"XMunger" , 0xA819}, - {"HOpenResFile" , 0xA81A}, - {"HCreateResFile" , 0xA81B}, - {"Count1Types" , 0xA81C}, - {"InvalMenuBar" , 0xA81D}, - {"SaveRestoreBits" , 0xA81E}, - {"Get1Resource" , 0xA81F}, - {"Get1NamedResource" , 0xA820}, - {"MaxSizeRsrc" , 0xA821}, - {"ResourceDispatch" , 0xA822}, - {"AliasDispatch" , 0xA823}, - {"FSMgr" , 0xA824}, - {"MenuDispatch" , 0xA825}, - {"InsertMenuItem" , 0xA826}, - {"HideDialogItem" , 0xA827}, - {"ShowDialogItem" , 0xA828}, - {"LayerDispatch" , 0xA829}, - {"ComponentDispatch" , 0xA82A}, - {"Pack9" , 0xA82B}, - {"Pack10" , 0xA82C}, - {"Pack11" , 0xA82D}, - {"Pack12" , 0xA82E}, - {"Pack13" , 0xA82F}, - {"Pack14" , 0xA830}, - {"Pack15" , 0xA831}, - {"QuickDrawGX" , 0xA832}, - {"ScrnBitMap" , 0xA833}, - {"SetFScaleDisable" , 0xA834}, - {"FontMetrics" , 0xA835}, - {"GetMaskTable" , 0xA836}, - {"MeasureText" , 0xA837}, - {"CalcMask" , 0xA838}, - {"SeedFill" , 0xA839}, - {"ZoomWindow" , 0xA83A}, - {"TrackBox" , 0xA83B}, - {"TEGetOffset" , 0xA83C}, - {"TEDispatch" , 0xA83D}, - {"TEStyleNew" , 0xA83E}, - {"Long2Fix" , 0xA83F}, - {"Fix2Long" , 0xA840}, - {"Fix2Frac" , 0xA841}, - {"Frac2Fix" , 0xA842}, - {"Fix2X" , 0xA843}, - {"X2Fix" , 0xA844}, - {"Frac2X" , 0xA845}, - {"X2Frac" , 0xA846}, - {"FracCos" , 0xA847}, - {"FracSin" , 0xA848}, - {"FracSqrt" , 0xA849}, - {"FracMul" , 0xA84A}, - {"FracDiv" , 0xA84B}, - {"UserDelay" , 0xA84C}, - {"FixDiv" , 0xA84D}, - {"GetItemCmd" , 0xA84E}, - {"SetItemCmd" , 0xA84F}, - {"InitCursor" , 0xA850}, - {"SetCursor" , 0xA851}, - {"HideCursor" , 0xA852}, - {"ShowCursor" , 0xA853}, - {"FontDispatch" , 0xA854}, - {"ShieldCursor" , 0xA855}, - {"ObscureCursor" , 0xA856}, - {"SetEntry" , 0xA857}, - {"BitAnd" , 0xA858}, - {"BitXOr" , 0xA859}, - {"BitNot" , 0xA85A}, - {"BitOr" , 0xA85B}, - {"BitShift" , 0xA85C}, - {"BitTst" , 0xA85D}, - {"BitSet" , 0xA85E}, - {"BitClr" , 0xA85F}, - {"WaitNextEvent" , 0xA860}, - {"Random" , 0xA861}, - {"ForeColor" , 0xA862}, - {"BackColor" , 0xA863}, - {"ColorBit" , 0xA864}, - {"GetPixel" , 0xA865}, - {"StuffHex" , 0xA866}, - {"LongMul" , 0xA867}, - {"FixMul" , 0xA868}, - {"FixRatio" , 0xA869}, - {"HiWord" , 0xA86A}, - {"LoWord" , 0xA86B}, - {"FixRound" , 0xA86C}, - {"InitPort" , 0xA86D}, - {"InitGraf" , 0xA86E}, - {"OpenPort" , 0xA86F}, - {"LocalToGlobal" , 0xA870}, - {"GlobalToLocal" , 0xA871}, - {"GrafDevice" , 0xA872}, - {"SetPort" , 0xA873}, - {"GetPort" , 0xA874}, - {"SetPBits" , 0xA875}, - {"PortSize" , 0xA876}, - {"MovePortTo" , 0xA877}, - {"SetOrigin" , 0xA878}, - {"SetClip" , 0xA879}, - {"GetClip" , 0xA87A}, - {"ClipRect" , 0xA87B}, - {"BackPat" , 0xA87C}, - {"ClosePort" , 0xA87D}, - {"AddPt" , 0xA87E}, - {"SubPt" , 0xA87F}, - {"SetPt" , 0xA880}, - {"EqualPt" , 0xA881}, - {"StdText" , 0xA882}, - {"DrawChar" , 0xA883}, - {"DrawString" , 0xA884}, - {"DrawText" , 0xA885}, - {"TextWidth" , 0xA886}, - {"TextFont" , 0xA887}, - {"TextFace" , 0xA888}, - {"TextMode" , 0xA889}, - {"TextSize" , 0xA88A}, - {"GetFontInfo" , 0xA88B}, - {"StringWidth" , 0xA88C}, - {"CharWidth" , 0xA88D}, - {"SpaceExtra" , 0xA88E}, - {"OSDispatch" , 0xA88F}, - {"StdLine" , 0xA890}, - {"LineTo" , 0xA891}, - {"Line" , 0xA892}, - {"MoveTo" , 0xA893}, - {"Move" , 0xA894}, - {"ShutDown" , 0xA895}, - {"HidePen" , 0xA896}, - {"ShowPen" , 0xA897}, - {"GetPenState" , 0xA898}, - {"SetPenState" , 0xA899}, - {"GetPen" , 0xA89A}, - {"PenSize" , 0xA89B}, - {"PenMode" , 0xA89C}, - {"PenPat" , 0xA89D}, - {"PenNormal" , 0xA89E}, - {"Unimplemented" , 0xA89F}, - {"StdRect" , 0xA8A0}, - {"FrameRect" , 0xA8A1}, - {"PaintRect" , 0xA8A2}, - {"EraseRect" , 0xA8A3}, - {"InverRect" , 0xA8A4}, - {"FillRect" , 0xA8A5}, - {"EqualRect" , 0xA8A6}, - {"SetRect" , 0xA8A7}, - {"OffsetRect" , 0xA8A8}, - {"InsetRect" , 0xA8A9}, - {"SectRect" , 0xA8AA}, - {"UnionRect" , 0xA8AB}, - {"Pt2Rect" , 0xA8AC}, - {"PtInRect" , 0xA8AD}, - {"EmptyRect" , 0xA8AE}, - {"StdRRect" , 0xA8AF}, - {"FrameRoundRect" , 0xA8B0}, - {"PaintRoundRect" , 0xA8B1}, - {"EraseRoundRect" , 0xA8B2}, - {"InverRoundRect" , 0xA8B3}, - {"FillRoundRect" , 0xA8B4}, - {"ScriptUtil" , 0xA8B5}, - {"StdOval" , 0xA8B6}, - {"FrameOval" , 0xA8B7}, - {"PaintOval" , 0xA8B8}, - {"EraseOval" , 0xA8B9}, - {"InvertOval" , 0xA8BA}, - {"FillOval" , 0xA8BB}, - {"SlopeFromAngle" , 0xA8BC}, - {"StdArc" , 0xA8BD}, - {"FrameArc" , 0xA8BE}, - {"PaintArc" , 0xA8BF}, - {"EraseArc" , 0xA8C0}, - {"InvertArc" , 0xA8C1}, - {"FillArc" , 0xA8C2}, - {"PtToAngle" , 0xA8C3}, - {"AngleFromSlope" , 0xA8C4}, - {"StdPoly" , 0xA8C5}, - {"FramePoly" , 0xA8C6}, - {"PaintPoly" , 0xA8C7}, - {"ErasePoly" , 0xA8C8}, - {"InvertPoly" , 0xA8C9}, - {"FillPoly" , 0xA8CA}, - {"OpenPoly" , 0xA8CB}, - {"ClosePoly" , 0xA8CC}, - {"KillPoly" , 0xA8CD}, - {"OffsetPoly" , 0xA8CE}, - {"PackBits" , 0xA8CF}, - {"UnpackBits" , 0xA8D0}, - {"StdRgn" , 0xA8D1}, - {"FrameRgn" , 0xA8D2}, - {"PaintRgn" , 0xA8D3}, - {"EraseRgn" , 0xA8D4}, - {"InverRgn" , 0xA8D5}, - {"FillRgn" , 0xA8D6}, - {"BitMapToRegion" , 0xA8D7}, - {"NewRgn" , 0xA8D8}, - {"DisposeRgn" , 0xA8D9}, - {"OpenRgn" , 0xA8DA}, - {"CloseRgn" , 0xA8DB}, - {"CopyRgn" , 0xA8DC}, - {"SetEmptyRgn" , 0xA8DD}, - {"SetRecRgn" , 0xA8DE}, - {"RectRgn" , 0xA8DF}, - {"OffsetRgn" , 0xA8E0}, - {"InsetRgn" , 0xA8E1}, - {"EmptyRgn" , 0xA8E2}, - {"EqualRgn" , 0xA8E3}, - {"SectRgn" , 0xA8E4}, - {"UnionRgn" , 0xA8E5}, - {"DiffRgn" , 0xA8E6}, - {"XOrRgn" , 0xA8E7}, - {"PtInRgn" , 0xA8E8}, - {"RectInRgn" , 0xA8E9}, - {"SetStdProcs" , 0xA8EA}, - {"StdBits" , 0xA8EB}, - {"CopyBits" , 0xA8EC}, - {"StdTxMeas" , 0xA8ED}, - {"StdGetPic" , 0xA8EE}, - {"ScrollRect" , 0xA8EF}, - {"StdPutPic" , 0xA8F0}, - {"StdComment" , 0xA8F1}, - {"PicComment" , 0xA8F2}, - {"OpenPicture" , 0xA8F3}, - {"ClosePicture" , 0xA8F4}, - {"KillPicture" , 0xA8F5}, - {"DrawPicture" , 0xA8F6}, - {"Layout" , 0xA8F7}, - {"ScalePt" , 0xA8F8}, - {"MapPt" , 0xA8F9}, - {"MapRect" , 0xA8FA}, - {"MapRgn" , 0xA8FB}, - {"MapPoly" , 0xA8FC}, - {"PrGlue" , 0xA8FD}, - {"InitFonts" , 0xA8FE}, - {"GetFName" , 0xA8FF}, - {"GetFNum" , 0xA900}, - {"FMSwapFont" , 0xA901}, - {"RealFont" , 0xA902}, - {"SetFontLock" , 0xA903}, - {"DrawGrowIcon" , 0xA904}, - {"DragGrayRgn" , 0xA905}, - {"NewString" , 0xA906}, - {"SetString" , 0xA907}, - {"ShowHide" , 0xA908}, - {"CalcVis" , 0xA909}, - {"CalcVBehind" , 0xA90A}, - {"ClipAbove" , 0xA90B}, - {"PaintOne" , 0xA90C}, - {"PaintBehind" , 0xA90D}, - {"SaveOld" , 0xA90E}, - {"DrawNew" , 0xA90F}, - {"GetWMgrPort" , 0xA910}, - {"CheckUpDate" , 0xA911}, - {"InitWindows" , 0xA912}, - {"NewWindow" , 0xA913}, - {"DisposeWindow" , 0xA914}, - {"ShowWindow" , 0xA915}, - {"HideWindow" , 0xA916}, - {"GetWRefCon" , 0xA917}, - {"SetWRefCon" , 0xA918}, - {"GetWTitle" , 0xA919}, - {"SetWTitle" , 0xA91A}, - {"MoveWindow" , 0xA91B}, - {"HiliteWindow" , 0xA91C}, - {"SizeWindow" , 0xA91D}, - {"TrackGoAway" , 0xA91E}, - {"SelectWindow" , 0xA91F}, - {"BringToFront" , 0xA920}, - {"SendBehind" , 0xA921}, - {"BeginUpDate" , 0xA922}, - {"EndUpDate" , 0xA923}, - {"FrontWindow" , 0xA924}, - {"DragWindow" , 0xA925}, - {"DragTheRgn" , 0xA926}, - {"InvalRgn" , 0xA927}, - {"InvalRect" , 0xA928}, - {"ValidRgn" , 0xA929}, - {"ValidRect" , 0xA92A}, - {"GrowWindow" , 0xA92B}, - {"FindWindow" , 0xA92C}, - {"CloseWindow" , 0xA92D}, - {"SetWindowPic" , 0xA92E}, - {"GetWindowPic" , 0xA92F}, - {"InitMenus" , 0xA930}, - {"NewMenu" , 0xA931}, - {"DisposeMenu" , 0xA932}, - {"AppendMenu" , 0xA933}, - {"ClearMenuBar" , 0xA934}, - {"InsertMenu" , 0xA935}, - {"DeleteMenu" , 0xA936}, - {"DrawMenuBar" , 0xA937}, - {"HiliteMenu" , 0xA938}, - {"EnableItem" , 0xA939}, - {"DisableItem" , 0xA93A}, - {"GetMenuBar" , 0xA93B}, - {"SetMenuBar" , 0xA93C}, - {"MenuSelect" , 0xA93D}, - {"MenuKey" , 0xA93E}, - {"GetItmIcon" , 0xA93F}, - {"SetItmIcon" , 0xA940}, - {"GetItmStyle" , 0xA941}, - {"SetItmStyle" , 0xA942}, - {"GetItmMark" , 0xA943}, - {"SetItmMark" , 0xA944}, - {"CheckItem" , 0xA945}, - {"GetMenuItemText" , 0xA946}, - {"SetMenuItemText" , 0xA947}, - {"CalcMenuSize" , 0xA948}, - {"GetMenuHandle" , 0xA949}, - {"SetMFlash" , 0xA94A}, - {"PlotIcon" , 0xA94B}, - {"FlashMenuBar" , 0xA94C}, - {"AppendResMenu" , 0xA94D}, - {"PinRect" , 0xA94E}, - {"DeltaPoint" , 0xA94F}, - {"CountMItems" , 0xA950}, - {"InsertResMenu" , 0xA951}, - {"DeleteMenuItem" , 0xA952}, - {"UpdtControl" , 0xA953}, - {"NewControl" , 0xA954}, - {"DisposeControl" , 0xA955}, - {"KillControls" , 0xA956}, - {"ShowControl" , 0xA957}, - {"HideControl" , 0xA958}, - {"MoveControl" , 0xA959}, - {"GetControlReference" , 0xA95A}, - {"SetControlReference" , 0xA95B}, - {"SizeControl" , 0xA95C}, - {"HiliteControl" , 0xA95D}, - {"GetControlTitle" , 0xA95E}, - {"SetControlTitle" , 0xA95F}, - {"GetControlValue" , 0xA960}, - {"GetControlMinimum" , 0xA961}, - {"GetControlMaximum" , 0xA962}, - {"SetControlValue" , 0xA963}, - {"SetControlMinimum" , 0xA964}, - {"SetControlMaximum" , 0xA965}, - {"TestControl" , 0xA966}, - {"DragControl" , 0xA967}, - {"TrackControl" , 0xA968}, - {"DrawControls" , 0xA969}, - {"GetControlAction" , 0xA96A}, - {"SetControlAction" , 0xA96B}, - {"FindControl" , 0xA96C}, - {"Draw1Control" , 0xA96D}, - {"Dequeue" , 0xA96E}, - {"Enqueue" , 0xA96F}, - {"GetNextEvent" , 0xA970}, - {"EventAvail" , 0xA971}, - {"GetMouse" , 0xA972}, - {"StillDown" , 0xA973}, - {"Button" , 0xA974}, - {"TickCount" , 0xA975}, - {"GetKeys" , 0xA976}, - {"WaitMouseUp" , 0xA977}, - {"UpdtDialog" , 0xA978}, - {"CouldDialog" , 0xA979}, - {"FreeDialog" , 0xA97A}, - {"InitDialogs" , 0xA97B}, - {"GetNewDialog" , 0xA97C}, - {"NewDialog" , 0xA97D}, - {"SelectDialogItemText" , 0xA97E}, - {"IsDialogEvent" , 0xA97F}, - {"DialogSelect" , 0xA980}, - {"DrawDialog" , 0xA981}, - {"CloseDialog" , 0xA982}, - {"DisposeDialog" , 0xA983}, - {"FindDialogItem" , 0xA984}, - {"Alert" , 0xA985}, - {"StopAlert" , 0xA986}, - {"NoteAlert" , 0xA987}, - {"CautionAlert" , 0xA988}, - {"CouldAlert" , 0xA989}, - {"FreeAlert" , 0xA98A}, - {"ParamText" , 0xA98B}, - {"ErrorSound" , 0xA98C}, - {"GetDialogItem" , 0xA98D}, - {"SetDialogItem" , 0xA98E}, - {"SetDialogItemText" , 0xA98F}, - {"GetDialogItemText" , 0xA990}, - {"ModalDialog" , 0xA991}, - {"DetachResource" , 0xA992}, - {"SetResPurge" , 0xA993}, - {"CurResFile" , 0xA994}, - {"InitResources" , 0xA995}, - {"RsrcZoneInit" , 0xA996}, - {"OpenResFile" , 0xA997}, - {"UseResFile" , 0xA998}, - {"UpdateResFile" , 0xA999}, - {"CloseResFile" , 0xA99A}, - {"SetResLoad" , 0xA99B}, - {"CountResources" , 0xA99C}, - {"GetIndResource" , 0xA99D}, - {"CountTypes" , 0xA99E}, - {"GetIndType" , 0xA99F}, - {"GetResource" , 0xA9A0}, - {"GetNamedResource" , 0xA9A1}, - {"LoadResource" , 0xA9A2}, - {"ReleaseResource" , 0xA9A3}, - {"HomeResFile" , 0xA9A4}, - {"SizeRsrc" , 0xA9A5}, - {"GetResAttrs" , 0xA9A6}, - {"SetResAttrs" , 0xA9A7}, - {"GetResInfo" , 0xA9A8}, - {"SetResInfo" , 0xA9A9}, - {"ChangedResource" , 0xA9AA}, - {"AddResource" , 0xA9AB}, - {"AddReference" , 0xA9AC}, - {"RmveResource" , 0xA9AD}, - {"RmveReference" , 0xA9AE}, - {"ResError" , 0xA9AF}, - {"WriteResource" , 0xA9B0}, - {"CreateResFile" , 0xA9B1}, - {"SystemEvent" , 0xA9B2}, - {"SystemClick" , 0xA9B3}, - {"SystemTask" , 0xA9B4}, - {"SystemMenu" , 0xA9B5}, - {"OpenDeskAcc" , 0xA9B6}, - {"CloseDeskAcc" , 0xA9B7}, - {"GetPattern" , 0xA9B8}, - {"GetCursor" , 0xA9B9}, - {"GetString" , 0xA9BA}, - {"GetIcon" , 0xA9BB}, - {"GetPicture" , 0xA9BC}, - {"GetNewWindow" , 0xA9BD}, - {"GetNewControl" , 0xA9BE}, - {"GetRMenu" , 0xA9BF}, - {"GetNewMBar" , 0xA9C0}, - {"UniqueID" , 0xA9C1}, - {"SysEdit" , 0xA9C2}, - {"KeyTranslate" , 0xA9C3}, - {"OpenRFPerm" , 0xA9C4}, - {"RsrcMapEntry" , 0xA9C5}, - {"SecondsToDate" , 0xA9C6}, - {"DateToSeconds" , 0xA9C7}, - {"SysBeep" , 0xA9C8}, - {"SysError" , 0xA9C9}, - {"PutIcon" , 0xA9CA}, - {"TEGetText" , 0xA9CB}, - {"TEInit" , 0xA9CC}, - {"TEDispose" , 0xA9CD}, - {"TETextBox" , 0xA9CE}, - {"TESetText" , 0xA9CF}, - {"TECalText" , 0xA9D0}, - {"TESetSelect" , 0xA9D1}, - {"TENew" , 0xA9D2}, - {"TEUpdate" , 0xA9D3}, - {"TEClick" , 0xA9D4}, - {"TECopy" , 0xA9D5}, - {"TECut" , 0xA9D6}, - {"TEDelete" , 0xA9D7}, - {"TEActivate" , 0xA9D8}, - {"TEDeactivate" , 0xA9D9}, - {"TEIdle" , 0xA9DA}, - {"TEPaste" , 0xA9DB}, - {"TEKey" , 0xA9DC}, - {"TEScroll" , 0xA9DD}, - {"TEInsert" , 0xA9DE}, - {"TESetAlignment" , 0xA9DF}, - {"Munger" , 0xA9E0}, - {"HandToHand" , 0xA9E1}, - {"PtrToXHand" , 0xA9E2}, - {"PtrToHand" , 0xA9E3}, - {"HandAndHand" , 0xA9E4}, - {"InitPack" , 0xA9E5}, - {"InitAllPacks" , 0xA9E6}, - {"Pack0" , 0xA9E7}, - {"Pack1" , 0xA9E8}, - {"Pack2" , 0xA9E9}, - {"Pack3" , 0xA9EA}, - {"FP68K" , 0xA9EB}, - {"Elems68K" , 0xA9EC}, - {"Pack6" , 0xA9ED}, - {"DECSTR68K" , 0xA9EE}, - {"PtrAndHand" , 0xA9EF}, - {"LoadSeg" , 0xA9F0}, - {"UnLoadSeg" , 0xA9F1}, - {"Launch" , 0xA9F2}, - {"Chain" , 0xA9F3}, - {"ExitToShell" , 0xA9F4}, - {"GetAppParms" , 0xA9F5}, - {"GetResFileAttrs" , 0xA9F6}, - {"SetResFileAttrs" , 0xA9F7}, - {"MethodDispatch" , 0xA9F8}, - {"InfoScrap" , 0xA9F9}, - {"UnloadScrap" , 0xA9FA}, - {"LoadScrap" , 0xA9FB}, - {"ZeroScrap" , 0xA9FC}, - {"GetScrap" , 0xA9FD}, - {"PutScrap" , 0xA9FE}, - {"Debugger" , 0xA9FF}, - {"OpenCPort" , 0xAA00}, - {"InitCPort" , 0xAA01}, - {"CloseCPort" , 0xAA02}, - {"NewPixMap" , 0xAA03}, - {"DisposePixMap" , 0xAA04}, - {"CopyPixMap" , 0xAA05}, - {"SetPortPix" , 0xAA06}, - {"NewPixPat" , 0xAA07}, - {"DisposePixPat" , 0xAA08}, - {"CopyPixPat" , 0xAA09}, - {"PenPixPat" , 0xAA0A}, - {"BackPixPat" , 0xAA0B}, - {"GetPixPat" , 0xAA0C}, - {"MakeRGBPat" , 0xAA0D}, - {"FillCRect" , 0xAA0E}, - {"FillCOval" , 0xAA0F}, - {"FillCRoundRect" , 0xAA10}, - {"FillCArc" , 0xAA11}, - {"FillCRgn" , 0xAA12}, - {"FillCPoly" , 0xAA13}, - {"RGBForeColor" , 0xAA14}, - {"RGBBackColor" , 0xAA15}, - {"SetCPixel" , 0xAA16}, - {"GetCPixel" , 0xAA17}, - {"GetCTable" , 0xAA18}, - {"GetForeColor" , 0xAA19}, - {"GetBackColor" , 0xAA1A}, - {"GetCCursor" , 0xAA1B}, - {"SetCCursor" , 0xAA1C}, - {"AllocCursor" , 0xAA1D}, - {"GetCIcon" , 0xAA1E}, - {"PlotCIcon" , 0xAA1F}, - {"OpenCPicture" , 0xAA20}, - {"OpColor" , 0xAA21}, - {"HiliteColor" , 0xAA22}, - {"CharExtra" , 0xAA23}, - {"DisposeCTable" , 0xAA24}, - {"DisposeCIcon" , 0xAA25}, - {"DisposeCCursor" , 0xAA26}, - {"GetMaxDevice" , 0xAA27}, - {"GetCTSeed" , 0xAA28}, - {"GetDeviceList" , 0xAA29}, - {"GetMainDevice" , 0xAA2A}, - {"GetNextDevice" , 0xAA2B}, - {"TestDeviceAttribute" , 0xAA2C}, - {"SetDeviceAttribute" , 0xAA2D}, - {"InitGDevice" , 0xAA2E}, - {"NewGDevice" , 0xAA2F}, - {"DisposeGDevice" , 0xAA30}, - {"SetGDevice" , 0xAA31}, - {"GetGDevice" , 0xAA32}, - {"Color2Index" , 0xAA33}, - {"Index2Color" , 0xAA34}, - {"InvertColor" , 0xAA35}, - {"RealColor" , 0xAA36}, - {"GetSubTable" , 0xAA37}, - {"UpdatePixMap" , 0xAA38}, - {"MakeITable" , 0xAA39}, - {"AddSearch" , 0xAA3A}, - {"AddComp" , 0xAA3B}, - {"SetClientID" , 0xAA3C}, - {"ProtectEntry" , 0xAA3D}, - {"ReserveEntry" , 0xAA3E}, - {"SetEntries" , 0xAA3F}, - {"QDError" , 0xAA40}, - {"SetWinColor" , 0xAA41}, - {"GetAuxWin" , 0xAA42}, - {"SetControlColor" , 0xAA43}, - {"GetAuxiliaryControlRecord", 0xAA44}, - {"NewCWindow" , 0xAA45}, - {"GetNewCWindow" , 0xAA46}, - {"SetDeskCPat" , 0xAA47}, - {"GetCWMgrPort" , 0xAA48}, - {"SaveEntries" , 0xAA49}, - {"RestoreEntries" , 0xAA4A}, - {"NewColorDialog" , 0xAA4B}, - {"DelSearch" , 0xAA4C}, - {"DelComp" , 0xAA4D}, - {"SetStdCProcs" , 0xAA4E}, - {"CalcCMask" , 0xAA4F}, - {"SeedCFill" , 0xAA50}, - {"CopyDeepMask" , 0xAA51}, - {"HighLevelFSDispatch" , 0xAA52}, - {"DictionaryDispatch" , 0xAA53}, - {"TextServicesDispatch" , 0xAA54}, - {"KobeMgr" , 0xAA55}, - {"SpeechRecognitionDispatch", 0xAA56}, - {"DockingDispatch" , 0xAA57}, - {"NewKernelDispatch" , 0xAA58}, - {"MixedModeDispatch" , 0xAA59}, - {"CodeFragmentDispatch" , 0xAA5A}, - {"PBRemoteAccess" , 0xAA5B}, - {"OCEUtils" , 0xAA5C}, - {"DigitalSignature" , 0xAA5D}, - {"OCETBDispatch" , 0xAA5E}, - {"OCEAuthentication" , 0xAA5F}, - {"DeleteMCEntries" , 0xAA60}, - {"GetMCInfo" , 0xAA61}, - {"SetMCInfo" , 0xAA62}, - {"DisposeMCInfo" , 0xAA63}, - {"GetMCEntry" , 0xAA64}, - {"SetMCEntries" , 0xAA65}, - {"MenuChoice" , 0xAA66}, - {"ModalDialogMenuSetup" , 0xAA67}, - {"DialogDispatch" , 0xAA68}, - {"UserNameNotification" , 0xAA69}, - {"DeviceMgr" , 0xAA6A}, - {"PowerPCFuture" , 0xAA6B}, - {"PenMacMgr" , 0xAA6C}, - {"LanguageMgr" , 0xAA6D}, - {"AppleGuideDispatch" , 0xAA6E}, - {"InitPalettes" , 0xAA90}, - {"NewPalette" , 0xAA91}, - {"GetNewPalette" , 0xAA92}, - {"DisposePalette" , 0xAA93}, - {"ActivatePalette" , 0xAA94}, - {"SetPalette" , 0xAA95}, - {"GetPalette" , 0xAA96}, - {"PmForeColor" , 0xAA97}, - {"PmBackColor" , 0xAA98}, - {"AnimateEntry" , 0xAA99}, - {"AnimatePalette" , 0xAA9A}, - {"GetEntryColor" , 0xAA9B}, - {"SetEntryColor" , 0xAA9C}, - {"GetEntryUsage" , 0xAA9D}, - {"SetEntryUsage" , 0xAA9E}, - {"CTab2Palette" , 0xAA9F}, - {"Palette2CTab" , 0xAAA0}, - {"CopyPalette" , 0xAAA1}, - {"PaletteDispatch" , 0xAAA2}, - {"CodecDispatch" , 0xAAA3}, - {"ALMDispatch" , 0xAAA4}, - {"QuickTimeDispatch" , 0xAAAA}, - {"CursorDeviceDispatch" , 0xAADB}, - {"HumanInterfaceUtilsDispatch", 0xAADD}, - {"AppleScript" , 0xAAEE}, - {"PCCardDispatch" , 0xAAF0}, - {"ATAMgr" , 0xAAF1}, - {"ControlStripDispatch" , 0xAAF2}, - {"ExpansionBusDispatch" , 0xAAF3}, - {"InterruptMgr" , 0xAAF4}, - {"InitApplication" , 0xAAFA}, - {"CleanupApplication" , 0xAAFB}, - {"MixedModeMagic" , 0xAAFE}, - {"BitBlt" , 0xAB00}, - {"BitsToMap" , 0xAB01}, - {"BitsToPix" , 0xAB02}, - {"Jackson" , 0xAB03}, - {"ColorMap" , 0xAB04}, - {"CopyHandle" , 0xAB05}, - {"CullPoints" , 0xAB06}, - {"PutPicByte" , 0xAB07}, - {"PutPicOp" , 0xAB08}, - {"DrawArc" , 0xAB09}, - {"DrawLine" , 0xAB0A}, - {"DrawSlab" , 0xAB0B}, - {"FastSlabMode" , 0xAB0C}, - {"GetSeek" , 0xAB0D}, - {"MakeScaleTbl" , 0xAB0E}, - {"CheckPic" , 0xAB0F}, - {"DoLine" , 0xAB10}, - {"OldPatToNew" , 0xAB11}, - {"PackRgn" , 0xAB12}, - {"PatConvert" , 0xAB13}, - {"PatDither" , 0xAB14}, - {"PatExpand" , 0xAB15}, - {"PInit" , 0xAB16}, - {"PortToMap" , 0xAB17}, - {"PushVerb" , 0xAB18}, - {"PutLine" , 0xAB19}, - {"PutOval" , 0xAB1A}, - {"PutRgn" , 0xAB1B}, - {"NewTempBuffer" , 0xAB1C}, - {"QDExtensions" , 0xAB1D}, - {"DisposeTempBuffer" , 0xAB1E}, - {"RgnBlit" , 0xAB1F}, - {"RgnOp" , 0xAB20}, - {"RSect" , 0xAB21}, - {"SeekRgn" , 0xAB22}, - {"SetFillPat" , 0xAB23}, - {"SetUpStretch" , 0xAB24}, - {"SlabMode" , 0xAB25}, - {"SortPoints" , 0xAB26}, - {"StretchBits" , 0xAB27}, - {"StdDevLoop" , 0xAB28}, - {"TrimRect" , 0xAB29}, - {"XorSlab" , 0xAB2A}, - {"ExTblPtr" , 0xAB2B}, - {"NewTempHandle" , 0xAB2D}, - {"PatExTbl" , 0xAB2E}, - {"bMAIN0" , 0xAB30}, - {"bMAIN1" , 0xAB31}, - {"bMAIN2" , 0xAB32}, - {"bMAIN3" , 0xAB33}, - {"bSETUP8" , 0xAB34}, - {"bMAIN9" , 0xAB35}, - {"bSETUP10" , 0xAB36}, - {"bMAIN11" , 0xAB37}, - {"bXMAIN8" , 0xAB38}, - {"bXMAIN9" , 0xAB39}, - {"bXMAIN10" , 0xAB3A}, - {"bXMAIN11" , 0xAB3B}, - {"bcMain0" , 0xAB3C}, - {"bcMain1" , 0xAB3D}, - {"bHilite" , 0xAB3E}, - {"bcMain3" , 0xAB3F}, - {"bEND0" , 0xAB40}, - {"bEND1" , 0xAB41}, - {"bEND2" , 0xAB42}, - {"bEND3" , 0xAB43}, - {"bLONG8" , 0xAB44}, - {"bEND9" , 0xAB45}, - {"bEND10" , 0xAB46}, - {"bEND11" , 0xAB47}, - {"bXLONG8" , 0xAB48}, - {"bXEND9" , 0xAB49}, - {"bXEND10" , 0xAB4A}, - {"bXEND11" , 0xAB4B}, - {"bcEnd0" , 0xAB4C}, - {"bcEnd1" , 0xAB4D}, - {"bSlowHilite" , 0xAB4E}, - {"bcEnd" , 0xAB4F}, - {"bAvg" , 0xAB50}, - {"bAddPin" , 0xAB51}, - {"bAddOver" , 0xAB52}, - {"bSubPin" , 0xAB53}, - {"bTransparent" , 0xAB54}, - {"bMax" , 0xAB55}, - {"bSubOver" , 0xAB56}, - {"bMin" , 0xAB57}, - {"bSetup0" , 0xAB58}, - {"bLeft0" , 0xAB59}, - {"rMASK0" , 0xAB5A}, - {"rMASK1" , 0xAB5B}, - {"rMASK2" , 0xAB5C}, - {"rMASK3" , 0xAB5D}, - {"rMASK8" , 0xAB5E}, - {"rMASK9" , 0xAB5F}, - {"rMASK10" , 0xAB60}, - {"rMASK11" , 0xAB61}, - {"rXMASK8" , 0xAB62}, - {"rXMASK9" , 0xAB63}, - {"rXMASK10" , 0xAB64}, - {"rXMASK11" , 0xAB65}, - {"rAvg" , 0xAB66}, - {"rAddPin" , 0xAB67}, - {"rAddOver" , 0xAB68}, - {"rSubPin" , 0xAB69}, - {"rTransparent" , 0xAB6A}, - {"rMax" , 0xAB6B}, - {"rSubOver" , 0xAB6C}, - {"rMin" , 0xAB6D}, - {"rcMask0" , 0xAB6E}, - {"rcMask1" , 0xAB6F}, - {"rSlowHilite" , 0xAB70}, - {"rcMask3" , 0xAB71}, - {"rHilite" , 0xAB72}, - {"stMASK0" , 0xAB73}, - {"stMASK1" , 0xAB74}, - {"stMASK2" , 0xAB75}, - {"stMASK3" , 0xAB76}, - {"stAvg" , 0xAB77}, - {"stAddPin" , 0xAB78}, - {"stAddOver" , 0xAB79}, - {"stSubPin" , 0xAB7A}, - {"stTransparent" , 0xAB7B}, - {"stMax" , 0xAB7C}, - {"stSubOver" , 0xAB7D}, - {"stMin" , 0xAB7E}, - {"stHilite" , 0xAB7F}, - {"slMASK8" , 0xAB80}, - {"slMASK9" , 0xAB81}, - {"slMASK10" , 0xAB82}, - {"slMASK11" , 0xAB83}, - {"slXMASK8" , 0xAB84}, - {"slXMASK9" , 0xAB85}, - {"slXMASK10" , 0xAB86}, - {"slXMASK11" , 0xAB87}, - {"slAvg" , 0xAB88}, - {"slAddPin" , 0xAB89}, - {"slAddOver" , 0xAB8A}, - {"slSubPin" , 0xAB8B}, - {"slTransparent" , 0xAB8C}, - {"slMax" , 0xAB8D}, - {"slSubOver" , 0xAB8E}, - {"slMin" , 0xAB8F}, - {"slHilite" , 0xAB90}, - {"ITabMatch" , 0xAB91}, - {"ColorThing" , 0xAB92}, - {"Pollack" , 0xAB93}, - {"AllocRunBuf" , 0xAB94}, - {"InitRgn" , 0xAB95}, - {"ScaleBlt" , 0xAB96}, - {"stNoStack" , 0xAB97}, - {"BlitCase" , 0xAB98}, - {"stScanLoop" , 0xAB99}, - {"PicItem1" , 0xAB9A}, - {"MakeGrayITab" , 0xAB9B}, - {"FastLine" , 0xAB9C}, - {"FastSlant" , 0xAB9D}, - {"BitsDevLoop" , 0xAB9E}, - {"rArith16Tab" , 0xABA0}, - {"rArith32Tab" , 0xABA1}, - {"rHiliteTab" , 0xABA2}, - {"gsRunTbl" , 0xABA3}, - {"gsExpTbl" , 0xABA4}, - {"gsSeekTbl" , 0xABA5}, - {"stArith16Tab" , 0xABA6}, - {"stArith32Tab" , 0xABA7}, - {"stColorTab" , 0xABA8}, - {"stGrayTab" , 0xABA9}, - {"stSearchTab" , 0xABAA}, - {"ScaleIndToInd" , 0xABAB}, - {"scIndTab1" , 0xABAC}, - {"scIndTab2" , 0xABAD}, - {"scIndTab4" , 0xABAE}, - {"scIndTab8" , 0xABAF}, - {"scIndTab16" , 0xABB0}, - {"scIndTab32" , 0xABB1}, - {"scDirTab1" , 0xABB2}, - {"scDirTab2" , 0xABB3}, - {"scDirTab4" , 0xABB4}, - {"scDirTab8" , 0xABB5}, - {"scDirTab16" , 0xABB6}, - {"scDirTab32" , 0xABB7}, - {"bArith16Tab" , 0xABB8}, - {"bArith32Tab" , 0xABB9}, - {"bHiliteTab" , 0xABBA}, - {"bArith16Setup" , 0xABBB}, - {"bArith32Setup" , 0xABBC}, - {"slArith16Tab" , 0xABBD}, - {"slArith32Tab" , 0xABBE}, - {"32QD" , 0xABBF}, - {"QDAlphaDispatch" , 0xABC0}, - {"QDStreamToMask" , 0xABC1}, - {"QTMatrixMathDispatch" , 0xABC2}, - {"NQDMisc" , 0xABC3}, - {"GetPMData" , 0xABC4}, - {"32QD" , 0xABC5}, - {"32QD" , 0xABC6}, - {"32QD" , 0xABC7}, - {"StdOpcodeProc" , 0xABC8}, - {"IconDispatch" , 0xABC9}, - {"DeviceLoop" , 0xABCA}, - {"PBBlockMove" , 0xABCC}, - {"SnappingTurk" , 0xABCD}, - {"UnicodeMgr" , 0xABCE}, - {"ProcessMgr" , 0xABCF}, - {"ModemMgr" , 0xABEA}, - {"DisplayDispatch" , 0xABEB}, - {"ButtonMgr" , 0xABEC}, - {"DragDispatch" , 0xABED}, - {"ColorSync" , 0xABEE}, - {"TTSMgr" , 0xABEF}, - {"AROSE" , 0xABF0}, - {"GestaltValueDispatch" , 0xABF1}, - {"ThreadDispatch" , 0xABF2}, - {"EddyTrap" , 0xABF3}, - {"XTNDMgr" , 0xABF4}, - {"DSPManager" , 0xABF5}, - {"CollectionMgr" , 0xABF6}, - {"SynchIdleTime" , 0xABF7}, - {"StdOpcodeProc" , 0xABF8}, - {"AUXDispatch" , 0xABF9}, - {"AUXSysCall" , 0xABFA}, - {"MessageMgr" , 0xABFB}, - {"TranslationDispatch" , 0xABFC}, - {"TouchStone" , 0xABFD}, - {"GXPrinting" , 0xABFE}, - {"DebugStr" , 0xABFF}, - {"" , 0} -}; - -#endif diff --git a/cxmon/src/mon_cmd.cpp b/cxmon/src/mon_cmd.cpp deleted file mode 100644 index 4cb6a92b..00000000 --- a/cxmon/src/mon_cmd.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* - * mon_cmd.cpp - cxmon standard commands - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include -#include - -#include "mon.h" -#include "mon_cmd.h" -#include "mon_disass.h" - -#ifndef VERSION -#define VERSION "3" -#endif - - -/* - * range_args = [expression] [[COMMA] expression] END - * - * Read start address to "adr", end address to "end_adr". - * "adr" defaults to '.', "end_adr" defaults to '.'+def_range - * - * true: OK, false: Error - */ - -static bool range_args(uintptr *adr, uintptr *end_adr, uint32 def_range) -{ - *adr = mon_dot_address; - *end_adr = mon_dot_address + def_range; - - if (mon_token == T_END) - return true; - else { - if (!mon_expression(adr)) - return false; - *end_adr = *adr + def_range; - if (mon_token == T_END) - return true; - else { - if (mon_token == T_COMMA) mon_get_token(); - if (!mon_expression(end_adr)) - return false; - return mon_token == T_END; - } - } -} - - -/* - * byte_string = (expression | STRING) {COMMA (expression | STRING)} END - */ - -static bool byte_string(uint8 *&str, uintptr &len) -{ - uintptr value; - - static const int GRANULARITY = 16; // must be a power of 2 - str = NULL; - len = 0; - goto start; - - for (;;) { - if (mon_token == T_COMMA) { - mon_get_token(); - -start: - if (mon_token == T_STRING) { - unsigned n = strlen(mon_string); - str = (uint8 *)realloc(str, (len + n - 1 + GRANULARITY) & ~(GRANULARITY - 1)); - assert(str != NULL); - memcpy(str + len, mon_string, n); - len += n; - mon_get_token(); - } else if (mon_expression(&value)) { - str = (uint8 *)realloc(str, (len + GRANULARITY) & ~(GRANULARITY - 1)); - assert(str != NULL); - str[len] = value; - len++; - } else { - if (str) - free(str); - return false; - } - - } else if (mon_token == T_END) { - return true; - } else { - mon_error("',' expected"); - if (str) - free(str); - return false; - } - } -} - - -/* - * Convert character to printable character - */ - -static inline uint8 char2print(uint8 c) -{ - return (c >= 0x20 && c <= 0x7e) ? c : '.'; -} - - -/* - * Show version - * ver - */ - -void version(void) -{ - fprintf(monout, "cxmon V" VERSION "\n"); -} - - -/* - * Redirect output - * o [file] - */ - -void redir_output(void) -{ - // Close old file - if (monout != monerr) { - fclose(monout); - monout = monerr; - return; - } - - // No argument given? - if (mon_token == T_END) - return; - - // Otherwise open file - if (mon_token == T_STRING) { - mon_get_token(); - if (mon_token != T_END) { - mon_error("Too many arguments"); - return; - } - if (!(monout = fopen(mon_string, "w"))) - mon_error("Unable to open file"); - } else - mon_error("'\"' around file name expected"); -} - - -/* - * Compute and display expression - * ? expression - */ - -void print_expr(void) -{ - uintptr val; - - if (!mon_expression(&val)) - return; - if (mon_token != T_END) { - mon_error("Too many arguments"); - return; - } - - if (val > 0x7fffffff) { - fprintf(monout, "Hex unsigned: $%08x\n" - "Hex signed : -$%08x\n" - "Dec unsigned: %u\n" - "Dec signed : %d\n", val, -val, val, val); - fprintf(monout, "Char : '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val)); - } else { - fprintf(monout, "Hex : $%08x\n" - "Dec : %d\n", val, val); - fprintf(monout, "Char: '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val)); - } -} - - -/* - * Execute shell command - * \ "command" - */ - -void shell_command(void) -{ - if (mon_token != T_STRING) { - mon_error("'\"' around command expected"); - return; - } - mon_get_token(); - if (mon_token != T_END) { - mon_error("Too many arguments"); - return; - } - system(mon_string); -} - - -/* - * Memory dump - * m [start [end]] - */ - -#define MEMDUMP_BPL 16 // Bytes per line - -void memory_dump(void) -{ - uintptr adr, end_adr; - uint8 mem[MEMDUMP_BPL + 1]; - - mem[MEMDUMP_BPL] = 0; - - if (!range_args(&adr, &end_adr, 16 * MEMDUMP_BPL - 1)) // 16 lines unless end address specified - return; - - while (adr <= end_adr && !mon_aborted()) { - fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr: adr % mon_mem_size); - for (int i=0; i>=1, i++) - str[i] = (b & m) ? '*' : '.'; - fprintf(monout, " '%s'\n", str); - adr++; - } - - mon_dot_address = adr; -} - - -/* - * Disassemble - * d [start [end]] - * d65 [start [end]] - * d68 [start [end]] - * d80 [start [end]] - * d86 [start [end]] - * d8086 [start [end]] - */ - -enum CPUType { - CPU_PPC, - CPU_6502, - CPU_680x0, - CPU_Z80, - CPU_80x86_32, - CPU_80x86_16, - CPU_x86_64 -}; - -static void disassemble(CPUType type) -{ - uintptr adr, end_adr; - - if (!range_args(&adr, &end_adr, 16 * 4 - 1)) // 16 lines unless end address specified - return; - - switch (type) { - case CPU_PPC: - while (adr <= end_adr && !mon_aborted()) { - uint32 w = mon_read_word(adr); - fprintf(monout, "%0*lx: %08x\t", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size, w); - disass_ppc(monout, mon_use_real_mem ? adr : adr % mon_mem_size, w); - adr += 4; - } - break; - - case CPU_6502: - while (adr <= end_adr && !mon_aborted()) { - uint8 op = mon_read_byte(adr); - uint8 lo = mon_read_byte(adr + 1); - uint8 hi = mon_read_byte(adr + 2); - fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size); - adr += disass_6502(monout, mon_use_real_mem ? adr : adr % mon_mem_size, op, lo, hi); - } - break; - - case CPU_680x0: - while (adr <= end_adr && !mon_aborted()) { - fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size); - adr += disass_68k(monout, mon_use_real_mem ? adr : adr % mon_mem_size); - } - break; - - case CPU_Z80: - while (adr <= end_adr && !mon_aborted()) { - fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size); - adr += disass_z80(monout, mon_use_real_mem ? adr : adr % mon_mem_size); - } - break; - - case CPU_x86_64: - while (adr <= end_adr && !mon_aborted()) { - fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size); - adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 64); - } - break; - - case CPU_80x86_32: - while (adr <= end_adr && !mon_aborted()) { - fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size); - adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 32); - } - break; - - case CPU_80x86_16: - while (adr <= end_adr && !mon_aborted()) { - fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size); - adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 16); - } - } - - mon_dot_address = adr; -} - -void disassemble_ppc(void) -{ - disassemble(CPU_PPC); -} - -void disassemble_6502(void) -{ - disassemble(CPU_6502); -} - -void disassemble_680x0(void) -{ - disassemble(CPU_680x0); -} - -void disassemble_z80(void) -{ - disassemble(CPU_Z80); -} - -void disassemble_80x86_32(void) -{ - disassemble(CPU_80x86_32); -} - -void disassemble_80x86_16(void) -{ - disassemble(CPU_80x86_16); -} - -void disassemble_x86_64(void) -{ - disassemble(CPU_x86_64); -} - - -/* - * Modify memory - * : addr bytestring - */ - -void modify(void) -{ - uintptr adr, len, src_adr = 0; - uint8 *str; - - if (!mon_expression(&adr)) - return; - if (!byte_string(str, len)) - return; - - while (src_adr < len) - mon_write_byte(adr++, str[src_adr++]); - mon_dot_address = adr; - - free(str); -} - - -/* - * Fill - * f start end bytestring - */ - -void fill(void) -{ - uintptr adr, end_adr, len, src_adr = 0; - uint8 *str; - - if (!mon_expression(&adr)) - return; - if (!mon_expression(&end_adr)) - return; - if (!byte_string(str, len)) - return; - - while (adr <= end_adr) - mon_write_byte(adr++, str[src_adr++ % len]); - - free(str); -} - - -/* - * Transfer memory - * t start end dest - */ - -void transfer(void) -{ - uintptr adr, end_adr, dest; - int num; - - if (!mon_expression(&adr)) - return; - if (!mon_expression(&end_adr)) - return; - if (!mon_expression(&dest)) - return; - if (mon_token != T_END) { - mon_error("Too many arguments"); - return; - } - - num = end_adr - adr + 1; - - if (dest < adr) - for (int i=0; i - -#include "mon.h" -#include "mon_disass.h" - -#include "mon_atraps.h" -#include "mon_lowmem.h" - - -// Flag: enable MacOS A-Trap and LM globals lookup in 68k disassembler -bool mon_macos_mode = false; - - -/* - * GNU disassembler callbacks - */ - -extern "C" { -#include "disass/dis-asm.h" - -int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info) -{ - while (length--) - *to++ = mon_read_byte(from++); - return 0; -} - -void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info) -{ - info->fprintf_func(info->stream, "Unknown error %d\n", status); -} - -bool lookup_lowmem; - -void generic_print_address(bfd_vma addr, struct disassemble_info *info) -{ - if (lookup_lowmem && addr >= 0x100 && addr < 0x3000) { - if (((addr >= 0x400 && addr < 0x800) || (addr >= 0xe00 && addr < 0x1e00)) && ((addr & 3) == 0)) { - // Look for address in A-Trap table - uint16 opcode = (addr < 0xe00 ? 0xa000 + (addr - 0x400) / 4 : 0xa800 + (addr - 0xe00) / 4); - uint16 mask = (addr < 0xe00 ? 0xf8ff : 0xffff); - const atrap_info *p = atraps; - while (p->word) { - if ((p->word & mask) == opcode) { - info->fprintf_func(info->stream, p->name); - return; - } - p++; - } - } else { - // Look for address in low memory globals table - const lowmem_info *p = lowmem; - while (p->name) { - if (addr >= p[0].addr && addr < p[1].addr) { - if (addr == p[0].addr) - info->fprintf_func(info->stream, "%s", p->name); - else - info->fprintf_func(info->stream, "%s+%d", p->name, addr - p->addr); - return; - } - p++; - } - } - } - if (addr >= UVAL64(0x100000000)) - info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr); - else - info->fprintf_func(info->stream, "$%08x", (uint32)addr); -} - -int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info) -{ - return 0; -} - -void print_68k_invalid_opcode(unsigned long opcode, struct disassemble_info *info) -{ - if (mon_macos_mode) { - // Look for MacOS A-Trap - const atrap_info *p = atraps; - while (p->word) { - if (p->word == opcode) { - info->fprintf_func(info->stream, p->name); - return; - } - p++; - } - } - info->fprintf_func(info->stream, "?"); -} - -}; - - -/* - * sprintf into a "stream" - */ - -struct SFILE { - char *buffer; - char *current; -}; - -static int mon_sprintf(SFILE *f, const char *format, ...) -{ - int n; - va_list args; - va_start(args, format); - vsprintf(f->current, format, args); - f->current += n = strlen(f->current); - va_end(args); - return n; -} - - -/* - * Disassemble one instruction, return number of bytes - */ - -int disass_68k(FILE *f, uint32 adr) -{ - // Initialize info for GDB disassembler - disassemble_info info; - char buf[1024]; - SFILE sfile = {buf, buf}; - sfile.buffer = buf; - sfile.current = buf; - INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf); - - // Disassemble instruction - lookup_lowmem = mon_macos_mode; - int num = print_insn_m68k(adr, &info); - - for (int i=0; i<6; i+=2) { - if (num > i) - fprintf(f, "%04x ", mon_read_half(adr + i)); - else - fprintf(f, " "); - } - if (num == 8) - fprintf(f, "%04x\t%s\n", mon_read_half(adr + 6), buf); - else if (num > 8) - fprintf(f, "...\t%s\n", buf); - else - fprintf(f, " \t%s\n", buf); - - return num; -} - -int disass_x86(FILE *f, uint32 adr, uint32 bits) -{ - // Initialize info for GDB disassembler - disassemble_info info; - char buf[1024]; - SFILE sfile = {buf, buf}; - sfile.buffer = buf; - sfile.current = buf; - INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf); - if (bits == 16) - info.mach = bfd_mach_i386_i8086; - else if (bits == 64) - info.mach = bfd_mach_x86_64; - - // Disassemble instruction - lookup_lowmem = false; - int num = print_insn_i386_att(adr, &info); - - for (int i=0; i<6; i++) { - if (num > i) - fprintf(f, "%02x ", mon_read_byte(adr + i)); - else - fprintf(f, " "); - } - if (num == 7) - fprintf(f, "%02x\t%s\n", mon_read_byte(adr + 7), buf); - else if (num > 7) - fprintf(f, "..\t%s\n", buf); - else - fprintf(f, " \t%s\n", buf); - - return num; -} diff --git a/cxmon/src/mon_disass.h b/cxmon/src/mon_disass.h deleted file mode 100644 index 487a2965..00000000 --- a/cxmon/src/mon_disass.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * mon_disass.h - Disassemblers - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MON_DISASS_H -#define MON_DISASS_H - -extern void disass_ppc(FILE *f, unsigned int adr, unsigned int w); -extern int disass_68k(FILE *f, uint32 adr); -extern int disass_x86(FILE *f, uint32 adr, uint32 bits = 32); -extern int disass_6502(FILE *f, uint32 adr, uint8 op, uint8 lo, uint8 hi); -extern int disass_z80(FILE *f, uint32 adr); - -#endif diff --git a/cxmon/src/mon_lowmem.cpp b/cxmon/src/mon_lowmem.cpp deleted file mode 100644 index e902352b..00000000 --- a/cxmon/src/mon_lowmem.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* - * mon_lowmem.cpp - MacOS low memory globals definitions - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "mon_lowmem.h" - -// Array of low memory globals in ascending order -const lowmem_info lowmem[] = { - {"MonkeyLives" , 0x100}, - {"ScrVRes" , 0x102}, - {"ScrHRes" , 0x104}, - {"ScreenRow" , 0x106}, - {"MemTop" , 0x108}, - {"BufPtr" , 0x10C}, - {"StkLowPt" , 0x110}, - {"HeapEnd" , 0x114}, - {"TheZone" , 0x118}, - {"UTableBase" , 0x11C}, - {"MacJump" , 0x120}, - {"DskRtnAdr" , 0x124}, - {"PollRtnAdr" , 0x128}, - {"DskVerify" , 0x12C}, - {"LoadTrap" , 0x12D}, - {"MmInOK" , 0x12E}, - {"CPUFlag" , 0x12F}, - {"ApplLimit" , 0x130}, - {"SonyVars" , 0x134}, - {"PWMValue" , 0x138}, - {"PollStack" , 0x13A}, - {"PollProc" , 0x13E}, - {"DskErr" , 0x142}, - {"SysEvtMask" , 0x144}, - {"SysEvtBuf" , 0x146}, - {"EventQueue" , 0x14A}, - {"EvtBufCnt" , 0x154}, - {"RndSeed" , 0x156}, - {"SysVersion" , 0x15A}, - {"SEvtEnb" , 0x15C}, - {"DSWndUpdate" , 0x15D}, - {"FontFlag" , 0x15E}, - {"IntFlag" , 0x15F}, - {"VBLQueue" , 0x160}, - {"Ticks" , 0x16A}, - {"MBTicks" , 0x16E}, - {"MBState" , 0x172}, - {"Tocks" , 0x173}, - {"KeyMap" , 0x174}, - {"KeypadMap" , 0x17C}, - {"KeyLast" , 0x184}, - {"KeyTime" , 0x186}, - {"KeyRepTime" , 0x18A}, - {"KeyThresh" , 0x18E}, - {"KeyRepThresh" , 0x190}, - {"Lvl1DT" , 0x192}, - {"Lvl2DT" , 0x1B2}, - {"UnitNtryCnt" , 0x1D2}, - {"VIA" , 0x1D4}, - {"SCCRd" , 0x1D8}, - {"SCCWr" , 0x1DC}, - {"IWM" , 0x1E0}, - {"GetParam" , 0x1E4}, - {"SysParam" , 0x1F8}, - {"SPValid" , 0x1F8}, - {"SPATalkA" , 0x1F9}, - {"SPATalkB" , 0x1FA}, - {"SPConfig" , 0x1FB}, - {"SPPortA" , 0x1FC}, - {"SPPortB" , 0x1FE}, - {"SPAlarm" , 0x200}, - {"SPFont" , 0x204}, - {"SPKbd" , 0x206}, - {"SPPrint" , 0x207}, - {"SPVolCtl" , 0x208}, - {"SPClikCaret" , 0x209}, - {"SPMisc1" , 0x20A}, - {"SPMisc2" , 0x20B}, - {"Time" , 0x20C}, - {"BootDrive" , 0x210}, - {"JShell" , 0x212}, - {"SFSaveDisk" , 0x214}, - {"KbdVars" , 0x216}, - {"KbdLast" , 0x218}, - {"JKybdTask" , 0x21A}, - {"KbdType" , 0x21E}, - {"AlarmState" , 0x21F}, - {"MemErr" , 0x220}, - {"JFigTrkSpd" , 0x222}, - {"JDiskPrime" , 0x226}, - {"JRdAddr" , 0x22A}, - {"JRdData" , 0x22E}, - {"JWrData" , 0x232}, - {"JSeek" , 0x236}, - {"JSetupPoll" , 0x23A}, - {"JRecal" , 0x23E}, - {"JControl" , 0x242}, - {"JWakeUp" , 0x246}, - {"JReSeek" , 0x24A}, - {"JMakeSpdTbl" , 0x24E}, - {"JAdrDisk" , 0x252}, - {"JSetSpeed" , 0x256}, - {"NiblTbl" , 0x25A}, - {"FlEvtMask" , 0x25E}, - {"SdVolume" , 0x260}, - {"SdEnable/Finder" , 0x261}, - {"SoundVars" , 0x262}, - {"SoundBase" , 0x266}, - {"SoundVBL" , 0x26A}, - {"SoundDCE" , 0x27A}, - {"SoundActive" , 0x27E}, - {"SoundLevel" , 0x27F}, - {"CurPitch" , 0x280}, - {"Switcher" , 0x282}, - {"SwitcherTPtr" , 0x286}, - {"RSDHndl" , 0x28A}, - {"ROM85" , 0x28E}, - {"PortAUse" , 0x290}, - {"PortBUse" , 0x291}, - {"ScreenVars" , 0x292}, - {"JGNEFilter" , 0x29A}, - {"Key1Trans" , 0x29E}, - {"Key2Trans" , 0x2A2}, - {"SysZone" , 0x2A6}, - {"ApplZone" , 0x2AA}, - {"ROMBase" , 0x2AE}, - {"RAMBase" , 0x2B2}, - {"ExpandMem" , 0x2B6}, - {"DSAlertTab" , 0x2BA}, - {"ExtStsDT" , 0x2BE}, - {"SCCASts" , 0x2CE}, - {"SCCBSts" , 0x2CF}, - {"SerialVars" , 0x2D0}, - {"ABusVars" , 0x2D8}, - {"ABusDCE" , 0x2DC}, - {"FinderName" , 0x2E0}, - {"DoubleTime" , 0x2F0}, - {"CaretTime" , 0x2F4}, - {"ScrDmpEnb" , 0x2F8}, - {"ScrDmpType" , 0x2F9}, - {"TagData" , 0x2FA}, - {"BufTgFNum" , 0x2FC}, - {"BufTgFFlg" , 0x300}, - {"BufTgFBkNum" , 0x302}, - {"BufTgDate" , 0x304}, - {"DrvQHdr" , 0x308}, - {"PWMBuf2" , 0x312}, - {"HpChk/MacPgm" , 0x316}, - {"Lo3Bytes" , 0x31A}, - {"MinStack" , 0x31E}, - {"DefltStack" , 0x322}, - {"MMDefFlags" , 0x326}, - {"GZRootHnd" , 0x328}, - {"GZRootPtr" , 0x32C}, - {"GZMoveHnd" , 0x330}, - {"DSDrawProc" , 0x334}, - {"EjectNotify" , 0x338}, - {"IAZNotify" , 0x33C}, - {"CurDB" , 0x340}, - {"NxtDB" , 0x342}, - {"MaxDB" , 0x344}, - {"FlushOnly" , 0x346}, - {"RegRsrc" , 0x347}, - {"FLckUnlck" , 0x348}, - {"FrcSync" , 0x349}, - {"NewMount" , 0x34A}, - {"NoEject" , 0x34B}, - {"DrMstrBlk" , 0x34C}, - {"FCBSPtr" , 0x34E}, - {"DefVCBPtr" , 0x352}, - {"VCBQHdr" , 0x356}, - {"FSQHdr" , 0x360}, - {"FSQHead" , 0x362}, - {"FSQTail" , 0x366}, - {"HFSStkTop" , 0x36A}, - {"HFSStkPtr" , 0x36E}, - {"WDCBsPtr" , 0x372}, - {"HFSFlags" , 0x376}, - {"CacheFlag" , 0x377}, - {"SysBMCPtr" , 0x378}, - {"SysVolCPtr" , 0x37C}, - {"SysCtlCPtr" , 0x380}, - {"DefVRefNum" , 0x384}, - {"PMSPPtr" , 0x386}, - {"HFSTagData" , 0x38A}, - {"HFSDSErr" , 0x392}, - {"CacheVars" , 0x394}, - {"CurDirStore" , 0x398}, - {"CacheCom" , 0x39C}, - {"FmtDefaults" , 0x39E}, - {"ErCode" , 0x3A2}, - {"Params" , 0x3A4}, - {"FSTemp8" , 0x3D6}, - {"FSIOErr" , 0x3DE}, - {"FSQueueHook" , 0x3E2}, - {"ExtFSHook" , 0x3E6}, - {"DskSwtchHook" , 0x3EA}, - {"ReqstVol" , 0x3EE}, - {"ToExtFS" , 0x3F2}, - {"FSFCBLen" , 0x3F6}, - {"DSAlertRect" , 0x3F8}, - {"JHideCrsr" , 0x800}, - {"JShowCrsr" , 0x804}, - {"JShieldCrsr" , 0x808}, - {"JScrnAddr" , 0x80C}, - {"JScrnSize" , 0x810}, - {"JInitCrsr" , 0x814}, - {"JSetCrsr" , 0x818}, - {"JCrsrObscure" , 0x81C}, - {"JUpdateProc" , 0x820}, - {"ScrnBase" , 0x824}, - {"MTemp" , 0x828}, - {"RawMouse" , 0x82C}, - {"Mouse" , 0x830}, - {"CrsrPin" , 0x834}, - {"CrsrRect" , 0x83C}, - {"TheCrsr" , 0x844}, - {"CrsrAddr" , 0x888}, - {"JAllocCrsr" , 0x88C}, - {"JSetCCrsr" , 0x890}, - {"JOpcodeProc" , 0x894}, - {"CrsrBase" , 0x898}, - {"CrsrDevice" , 0x89C}, - {"SrcDevice" , 0x8A0}, - {"MainDevice" , 0x8A4}, - {"DeviceList" , 0x8A8}, - {"CrsrRow" , 0x8AC}, - {"QDColors" , 0x8B0}, - {"CrsrVis" , 0x8CC}, - {"CrsrBusy" , 0x8CD}, - {"CrsrNew" , 0x8CE}, - {"CrsrCouple" , 0x8CF}, - {"CrsrState" , 0x8D0}, - {"CrsrObscure" , 0x8D2}, - {"CrsrScale" , 0x8D3}, - {"MouseMask" , 0x8D6}, - {"MouseOffset" , 0x8DA}, - {"JournalFlag" , 0x8DE}, - {"JSwapFont" , 0x8E0}, - {"JFontInfo" , 0x8E4}, - {"JournalRef" , 0x8E8}, - {"CrsrThresh" , 0x8EC}, - {"JCrsrTask" , 0x8EE}, - {"WWExist" , 0x8F2}, - {"QDExist" , 0x8F3}, - {"JFetch" , 0x8F4}, - {"JStash" , 0x8F8}, - {"JIODone" , 0x8FC}, - {"CurApRefNum" , 0x900}, - {"LaunchFlag" , 0x902}, - {"FondState" , 0x903}, - {"CurrentA5" , 0x904}, - {"CurStackBase" , 0x908}, - {"LoadFiller" , 0x90C}, - {"CurApName" , 0x910}, - {"SaveSegHandle" , 0x930}, - {"CurJTOffset" , 0x934}, - {"CurPageOption" , 0x936}, - {"HiliteMode" , 0x938}, - {"LoaderPBlock" , 0x93A}, - {"PrintErr" , 0x944}, - {"ChooserBits" , 0x946}, - {"PrFlags" , 0x946}, - {"PrType" , 0x947}, - {"PrRefNum" , 0x952}, - {"LastPGlobal" , 0x954}, - {"ScrapSize" , 0x960}, - {"ScrapHandle" , 0x964}, - {"ScrapCount" , 0x968}, - {"ScrapState" , 0x96A}, - {"ScrapName" , 0x96C}, - {"ScrapTag" , 0x970}, - {"RomFont0" , 0x980}, - {"AppFontID" , 0x984}, - {"SaveFondFlags" , 0x986}, - {"FMDefaultSize" , 0x987}, - {"CurFMFamily" , 0x988}, - {"CurFMSize" , 0x98A}, - {"CurFMFace" , 0x98C}, - {"CurFMNeedBits" , 0x98D}, - {"CurFMDevice" , 0x98E}, - {"CurFMNumer" , 0x990}, - {"CurFMDenom" , 0x994}, - {"FOutError" , 0x998}, - {"FOutFontHandle" , 0x99A}, - {"FOutBold" , 0x99E}, - {"FOutItalic" , 0x99F}, - {"FOutULOffset" , 0x9A0}, - {"FOutULShadow" , 0x9A1}, - {"FOutULThick" , 0x9A2}, - {"FOutShadow" , 0x9A3}, - {"FOutExtra" , 0x9A4}, - {"FOutAscent" , 0x9A5}, - {"FOutDescent" , 0x9A6}, - {"FOutWidMax" , 0x9A7}, - {"FOutLeading" , 0x9A8}, - {"FOutUnused" , 0x9A9}, - {"FOutNumer" , 0x9AA}, - {"FOutDenom" , 0x9AE}, - {"FMDotsPerInch" , 0x9B2}, - {"FMStyleTab" , 0x9B6}, - {"ToolScratch" , 0x9CE}, - {"WindowList" , 0x9D6}, - {"SaveUpdate" , 0x9DA}, - {"PaintWhite" , 0x9DC}, - {"WMgrPort" , 0x9DE}, - {"DeskPort" , 0x9E2}, - {"OldStructure" , 0x9E6}, - {"OldContent" , 0x9EA}, - {"GrayRgn" , 0x9EE}, - {"SaveVisRgn" , 0x9F2}, - {"DragHook" , 0x9F6}, - {"TempRect" , 0x9FA}, - {"OneOne" , 0xA02}, - {"MinusOne" , 0xA06}, - {"TopMenuItem" , 0xA0A}, - {"AtMenuBottom" , 0xA0C}, - {"IconBitmap" , 0xA0E}, - {"MenuList" , 0xA1C}, - {"MBarEnable" , 0xA20}, - {"CurDeKind" , 0xA22}, - {"MenuFlash" , 0xA24}, - {"TheMenu" , 0xA26}, - {"SavedHandle" , 0xA28}, - {"MBarHook" , 0xA2C}, - {"MenuHook" , 0xA30}, - {"DragPattern" , 0xA34}, - {"DeskPattern" , 0xA3C}, - {"DragFlag" , 0xA44}, - {"CurDragAction" , 0xA46}, - {"FPState" , 0xA4A}, - {"TopMapHndl" , 0xA50}, - {"SysMapHndl" , 0xA54}, - {"SysMap" , 0xA58}, - {"CurMap" , 0xA5A}, - {"ResReadOnly" , 0xA5C}, - {"ResLoad" , 0xA5E}, - {"ResErr" , 0xA60}, - {"TaskLock" , 0xA62}, - {"FScaleDisable" , 0xA63}, - {"CurActivate" , 0xA64}, - {"CurDeactive" , 0xA68}, - {"DeskHook" , 0xA6C}, - {"TEDoText" , 0xA70}, - {"TERecal" , 0xA74}, - {"ApplScratch" , 0xA78}, - {"GhostWindow" , 0xA84}, - {"CloseOrnHook" , 0xA88}, - {"ResumeProc" , 0xA8C}, - {"RestProc" , 0xA8C}, - {"SaveProc" , 0xA90}, - {"SaveSP" , 0xA94}, - {"ANumber" , 0xA98}, - {"ACount" , 0xA9A}, - {"DABeeper" , 0xA9C}, - {"DAStrings" , 0xAA0}, - {"TEScrpLength" , 0xAB0}, - {"TEScrpHandle" , 0xAB4}, - {"AppPacks" , 0xAB8}, - {"SysResName" , 0xAD8}, - {"SoundGlue" , 0xAE8}, - {"AppParmHandle" , 0xAEC}, - {"DSErrCode" , 0xAF0}, - {"ResErrProc" , 0xAF2}, - {"TEWdBreak" , 0xAF6}, - {"DlgFont" , 0xAFA}, - {"LastTGlobal" , 0xAFC}, - {"TrapAgain" , 0xB00}, - {"KeyMVars" , 0xB04}, - {"ROMMapHndl" , 0xB06}, - {"PWMBuf1" , 0xB0A}, - {"BootMask" , 0xB0E}, - {"WidthPtr" , 0xB10}, - {"ATalkHk1" , 0xB14}, - {"LAPMgrPtr" , 0xB18}, - {"FourDHack" , 0xB1C}, - {"UnSwitchedFlags" , 0xB20}, - {"SwitchedFlags" , 0xB21}, - {"HWCfgFlags" , 0xB22}, - {"TimeSCSIDB" , 0xB24}, - {"Top2MenuItem" , 0xB26}, - {"At2MenuBottom" , 0xB28}, - {"WidthTabHandle" , 0xB2A}, - {"SCSIDrvrs" , 0xB2E}, - {"TimeVars" , 0xB30}, - {"BtDskRfn" , 0xB34}, - {"BootTmp8" , 0xB36}, - {"NTSC" , 0xB3E}, - {"T1Arbitrate" , 0xB3F}, - {"JDiskSel" , 0xB40}, - {"JSendCmd" , 0xB44}, - {"JDCDReset" , 0xB48}, - {"LastSPExtra" , 0xB4C}, - {"FileShareVars" , 0xB50}, - {"MenuDisable" , 0xB54}, - {"MBDFHndl" , 0xB58}, - {"MBSaveLoc" , 0xB5C}, - {"BNMQHdr" , 0xB60}, - {"BackgrounderVars" , 0xB64}, - {"MenuLayer" , 0xB68}, - {"OmegaSANE" , 0xB6C}, - {"CarlByte" , 0xB72}, - {"SystemInfo" , 0xB73}, - {"VMGlobals" , 0xB78}, - {"Twitcher2" , 0xB7C}, - {"RMgrHiVars" , 0xB80}, - {"HSCHndl" , 0xB84}, - {"PadRsrc" , 0xB88}, - {"ResOneDeep" , 0xB9A}, - {"PadRsrc2" , 0xB9C}, - {"RomMapInsert" , 0xB9E}, - {"TmpResLoad" , 0xB9F}, - {"IntlSpec" , 0xBA0}, - {"RMgrPerm" , 0xBA4}, - {"WordRedraw" , 0xBA5}, - {"SysFontFam" , 0xBA6}, - {"DefFontSize" , 0xBA8}, - {"MBarHeight" , 0xBAA}, - {"TESysJust" , 0xBAC}, - {"HiHeapMark" , 0xBAE}, - {"SegHiEnable" , 0xBB2}, - {"FDevDisable" , 0xBB3}, - {"CommToolboxGlob" , 0xBB4}, - {"CMVector" , 0xBB4}, - {"ShutDwnQHdr" , 0xBBC}, - {"NewUnused" , 0xBC0}, - {"LastFOND" , 0xBC2}, - {"FONDID" , 0xBC6}, - {"App2Packs" , 0xBC8}, - {"MAErrProc" , 0xBE8}, - {"MASuperTab" , 0xBEC}, - {"MimeGlobs" , 0xBF0}, - {"FractEnable" , 0xBF4}, - {"UsedFWidth" , 0xBF5}, - {"FScaleHFact" , 0xBF6}, - {"FScaleVFact" , 0xBFA}, - {"SCCIOPFlag" , 0xBFE}, - {"MacJmpFlag" , 0xBFF}, - {"SCSIBase" , 0xC00}, - {"SCSIDMA" , 0xC04}, - {"SCSIHsk" , 0xC08}, - {"SCSIGlobals" , 0xC0C}, - {"RGBBlack" , 0xC10}, - {"RGBWhite" , 0xC16}, - {"FMSynth" , 0xC1C}, - {"RowBits" , 0xC20}, - {"ColLines" , 0xC22}, - {"ScreenBytes" , 0xC24}, - {"IOPMgrVars" , 0xC28}, - {"NMIFlag" , 0xC2C}, - {"VidType" , 0xC2D}, - {"VidMode" , 0xC2E}, - {"SCSIPoll" , 0xC2F}, - {"SEVarBase" , 0xC30}, - {"MacsBugSP" , 0xC6C}, - {"MacsBugPC" , 0xC70}, - {"MacsBugSR" , 0xC74}, - {"MMUFlags" , 0xCB0}, - {"MMUType" , 0xCB1}, - {"MMU32bit" , 0xCB2}, - {"MachineType" , 0xCB3}, - {"MMUTbl24" , 0xCB4}, - {"MMUTbl32" , 0xCB8}, - {"SInfoPtr" , 0xCBC}, - {"ASCBase" , 0xCC0}, - {"SMGlobals" , 0xCC4}, - {"TheGDevice" , 0xCC8}, - {"CQDGlobals" , 0xCCC}, - {"AuxWinHead" , 0xCD0}, - {"AuxCtlHead" , 0xCD4}, - {"DeskCPat" , 0xCD8}, - {"SetOSDefKey" , 0xCDC}, - {"LastBinPat" , 0xCE0}, - {"DeskPatEnable" , 0xCE8}, - {"TimeVIADB" , 0xCEA}, - {"VIA2Base" , 0xCEC}, - {"VMVectors" , 0xCF0}, - {"ADBBase" , 0xCF8}, - {"WarmStart" , 0xCFC}, - {"TimeDBRA" , 0xD00}, - {"TimeSCCDB" , 0xD02}, - {"SlotQDT" , 0xD04}, - {"SlotPrTbl" , 0xD08}, - {"SlotVBLQ" , 0xD0C}, - {"ScrnVBLPtr" , 0xD10}, - {"SlotTICKS" , 0xD14}, - {"PowerMgrVars" , 0xD18}, - {"AGBHandle" , 0xD1C}, - {"TableSeed" , 0xD20}, - {"SRsrcTblPtr" , 0xD24}, - {"JVBLTask" , 0xD28}, - {"WMgrCPort" , 0xD2C}, - {"VertRRate" , 0xD30}, - {"SynListHandle" , 0xD32}, - {"LastFore" , 0xD36}, - {"LastBG" , 0xD3A}, - {"LastMode" , 0xD3E}, - {"LastDepth" , 0xD40}, - {"FMExist" , 0xD42}, - {"SavedHilite" , 0xD43}, - {"ShieldDepth" , 0xD4C}, - {"MenuCInfo" , 0xD50}, - {"MBProcHndl" , 0xD54}, - {"MBFlash" , 0xD5C}, - {"ChunkyDepth" , 0xD60}, - {"CrsrPtr" , 0xD62}, - {"PortList" , 0xD66}, - {"MickeyBytes" , 0xD6A}, - {"QDErr" , 0xD6E}, - {"VIA2DT" , 0xD70}, - {"SInitFlags" , 0xD90}, - {"DTQueue" , 0xD92}, - {"DTQFlags" , 0xD92}, - {"DTskQHdr" , 0xD94}, - {"DTskQTail" , 0xD98}, - {"JDTInstall" , 0xD9C}, - {"HiliteRGB" , 0xDA0}, - {"OldTimeSCSIDB" , 0xDA6}, - {"DSCtrAdj" , 0xDA8}, - {"IconTLAddr" , 0xDAC}, - {"VideoInfoOK" , 0xDB0}, - {"EndSRTPtr" , 0xDB4}, - {"SDMJmpTblPtr" , 0xDB8}, - {"JSwapMMU" , 0xDBC}, - {"SdmBusErr" , 0xDC0}, - {"LastTxGDevice" , 0xDC4}, - {"PMgrHandle" , 0xDC8}, - {"LayerPalette" , 0xDCC}, - {"AddrMapFlags" , 0xDD0}, - {"UnivROMFlags" , 0xDD4}, - {"UniversalInfoPtr" , 0xDD8}, - {"BootGlobPtr" , 0xDDC}, - {"EgretGlobals" , 0xDE0}, - {"SaneTrapAddr" , 0xDE4}, - {"Warhol" , 0xDE8}, - {"MemVectors24" , 0x1E00}, - {"Mem2Vectors24" , 0x1EE0}, - {"Phys2Log" , 0x1EF0}, - {"RealMemTop" , 0x1EF4}, - {"PhysMemTop" , 0x1EF8}, - {"MMFlags" , 0x1EFC}, - {"MemVectors32" , 0x1F00}, - {"DrawCrsrVector" , 0x1FB8}, - {"EraseCrsrVector" , 0x1FBC}, - {"PSCIntTbl" , 0x1FC0}, - {"DSPGlobals" , 0x1FC4}, - {"FP040Vects" , 0x1FC8}, - {"FPBSUNVec" , 0x1FCC}, - {"FPUNFLVec" , 0x1FD0}, - {"FPOPERRVec" , 0x1FD4}, - {"FPOVFLVec" , 0x1FD8}, - {"FPSNANVec" , 0x1FDC}, - {"Mem2Vectors32" , 0x1FE0}, - {"SCSI2Base" , 0x1FF0}, - {"LockMemCt" , 0x1FF4}, - {"DockingGlobals" , 0x1FF8}, - {"VectorPtr" , 0x2000}, - {"BasesValid1" , 0x2400}, - {"BasesValid2" , 0x2404}, - {"ExtValid1" , 0x2408}, - {"ExtValid2" , 0x240C}, - {NULL , 0xFFFF} -}; diff --git a/cxmon/src/mon_lowmem.h b/cxmon/src/mon_lowmem.h deleted file mode 100644 index 55e058e8..00000000 --- a/cxmon/src/mon_lowmem.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * mon_lowmem.h - MacOS low memory globals definitions - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef MON_LOWMEM_H -#define MON_LOWMEM_H - -struct lowmem_info { - const char *name; - uint16 addr; -}; - -// Array of low memory globals in ascending order -extern const lowmem_info lowmem[]; - -#endif diff --git a/cxmon/src/mon_ppc.cpp b/cxmon/src/mon_ppc.cpp deleted file mode 100644 index 56683654..00000000 --- a/cxmon/src/mon_ppc.cpp +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * mon_ppc.cpp - PowerPC disassembler - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "mon.h" -#include "mon_disass.h" - - -// Instruction fields -static int primop, exop, vxop, ra, rb, rc, rd; -static unsigned short imm; - - -// Codes for trap instructions -static char *to_code[32] = { - NULL, "lgt", "llt", NULL, "eq", "lge", "lle", NULL, - "gt", NULL, NULL, NULL, "ge", NULL, NULL, NULL, - "lt", NULL, NULL, NULL, "le", NULL, NULL, NULL, - "ne", NULL, NULL, NULL, NULL, NULL, NULL, "" -}; - - -// Macros for instruction forms -#define iform(s, t) fprintf(f, "%s\t$%08x\n", s, t) - -#define bform(s, t) \ - if (rd == 0) \ - fprintf(f, "bdnzf%s\t%d,$%08x\n", s, ra, t); \ - else if (rd == 2) \ - fprintf(f, "bdzf%s\t%d,$%08x\n", s, ra, t); \ - else if (rd == 4) { \ - if (ra == 0) \ - fprintf(f, "bge%s\t$%08x\n", s, t); \ - else if (ra == 1) \ - fprintf(f, "ble%s\t$%08x\n", s, t); \ - else if (ra == 2) \ - fprintf(f, "bne%s\t$%08x\n", s, t); \ - else \ - fprintf(f, "bf%s\t%d,$%08x\n", s, ra, t); \ - } else if (rd == 8) \ - fprintf(f, "bdnzt%s\t%d,$%08x\n", s, ra, t); \ - else if (rd == 10) \ - fprintf(f, "bdzt%s\t%d,$%08x\n", s, ra, t); \ - else if (rd == 12) { \ - if (ra == 0) \ - fprintf(f, "blt%s\t$%08x\n", s, t); \ - else if (ra == 1) \ - fprintf(f, "bgt%s\t$%08x\n", s, t); \ - else if (ra == 2) \ - fprintf(f, "beq%s\t$%08x\n", s, t); \ - else \ - fprintf(f, "bt%s\t%d,$%08x\n", s, ra, t); \ - } else if (rd == 16) \ - fprintf(f, "bdnz%s\t$%08x\n", s, t); \ - else if (rd == 18) \ - fprintf(f, "bdz%s\t$%08x\n", s, t); \ - else \ - fprintf(f, "bc%s\t%d,%d,$%08x\n", s, rd, ra, t) - -#define scform(s) fprintf(f, s "\n") - -#define dform_ls(s) \ - if (ra == 0) \ - fprintf(f, "%s\tr%d,$%08x\n", s, rd, short(imm)); \ - else \ - fprintf(f, "%s\tr%d,$%04x(r%d)\n", s, rd, short(imm), ra) -#define dform_fls(s) \ - if (ra == 0) \ - fprintf(f, "%s\tfr%d,$%08x\n", s, rd, short(imm)); \ - else \ - fprintf(f, "%s\tfr%d,$%04x(r%d)\n", s, rd, short(imm), ra) -#define dform_simm(s) fprintf(f, "%s\tr%d,r%d,$%04x\n", s, rd, ra, short(imm)) -#define dform_simmn(s) fprintf(f, "%s\tr%d,r%d,$%04x\n", s, rd, ra, (-imm) & 0xffff) -#define dform_uimm(s) fprintf(f, "%s\tr%d,r%d,$%04x\n", s, ra, rd, imm) -#define dform_crs(s) fprintf(f, "%s\tcrf%d,r%d,$%04x\n", s, rd >> 2, ra, short(imm)) -#define dform_cru(s) fprintf(f, "%s\tcrf%d,r%d,$%04x\n", s, rd >> 2, ra, imm) -#define dform_to(s) fprintf(f, "%s\t%d,r%d,$%04x\n", s, rd, ra, short(imm)) - -#define dsform(s) fprintf(f, "%s\tr%d,$%04x(r%d)\n", s, rd, short(imm & 0xfffc), ra) - -#define xform_vls(s) \ - if (ra == 0) \ - fprintf(f, "%s\tv%d,r%d\n", s, rd, rb); \ - else \ - fprintf(f, "%s\tv%d,r%d,r%d\n", s, rd, ra, rb) -#define xform_ls(s) \ - if (ra == 0) \ - fprintf(f, "%s\tr%d,r%d\n", s, rd, rb); \ - else \ - fprintf(f, "%s\tr%d,r%d,r%d\n", s, rd, ra, rb) -#define xform_fls(s) \ - if (ra == 0) \ - fprintf(f, "%s\tfr%d,r%d\n", s, rd, rb); \ - else \ - fprintf(f, "%s\tfr%d,r%d,r%d\n", s, rd, ra, rb) -#define xform_lsswi(s) \ - if (ra == 0) \ - fprintf(f, "%s\tr%d,%d\n", s, rd, rb ? rb : 32); \ - else \ - fprintf(f, "%s\tr%d,r%d,%d\n", s, rd, ra, rb ? rb : 32) -#define xform_db(s) fprintf(f, "%s\tr%d,r%d\n", s, rd, rb) -#define xform_d(s) fprintf(f, "%s\tr%d\n", s, rd) -#define xform_fsr(s) fprintf(f, s "\tr%d,%d\n", rd, ra & 0xf) -#define xform_sabc(s) fprintf(f, "%s%s\tr%d,r%d,r%d\n", s, w & 1 ? "." : "", ra, rd, rb) -#define xform_sac(s) fprintf(f, "%s%s\tr%d,r%d\n", s, w & 1 ? "." : "", ra, rd) -#define xform_tsr(s) fprintf(f, s "\t%d,r%d\n", ra & 0xf, rd) -#define xform_sash(s) fprintf(f, s "%s\tr%d,r%d,%d\n", w & 1 ? "." : "", ra, rd, rb) -#define xform_crlab(s) fprintf(f, "%s\tcrf%d,r%d,r%d\n", s, rd >> 2, ra, rb) -#define xform_fcrab(s) fprintf(f, "%s\tcrf%d,fr%d,fr%d\n", s, rd >> 2, ra, rb) -#define xform_crcr(s) fprintf(f, "%s\tcrf%d,crf%d\n", s, rd >> 2, ra >> 2) -#define xform_cr(s) fprintf(f, "%s\tcrf%d\n", s, rd >> 2) -#define xform_cri(s) fprintf(f, s "%s\tcrf%d,%d\n", w & 1 ? "." : "", rd >> 2, rb >> 1) -#define xform_to(s) fprintf(f, "%s\t%d,r%d,r%d\n", s, rd, ra, rb) -#define xform_fdb(s) fprintf(f, "%s%s\tfr%d,fr%d\n", s, w & 1 ? "." : "", rd, rb) -#define xform_fd(s) fprintf(f, "%s%s\tfr%d\n", s, w & 1 ? "." : "", rd) -#define xform_crb(s) fprintf(f, "%s%s\tcrb%d\n", s, w & 1 ? "." : "", rd) -#define xform_ab(s) fprintf(f, "%s\tr%d,r%d\n", s, ra, rb) -#define xform_b(s) fprintf(f, "%s\tr%d\n", s, rb) -#define xform(s) fprintf(f, s "\n") - -#define xlform_b(s) fprintf(f, "%s\t%d,%d\n", s, rd, ra) -#define xlform_cr(s) fprintf(f, "%s\tcrb%d,crb%d,crb%d\n", s, rd, ra, rb) -#define xlform_crcr(s) fprintf(f, "%s\tcrf%d,crf%d\n", s, rd >> 2, ra >> 2) -#define xlform(s) fprintf(f, s "\n") - -#define xfxform_fspr(s) fprintf(f, "%s\tr%d,SPR%d\n", s, rd, ra | (rb << 5)) -#define xfxform_crm(s) fprintf(f, s "\t$%02x,r%d\n", w >> 12 & 0xff, rd) -#define xfxform_tspr(s) fprintf(f, "%s\tSPR%d,r%d\n", s, ra | (rb << 5), rd) -#define xfxform_tb(s) fprintf(f, "%s\tr%d\n", s, rd) - -#define xflform(s) fprintf(f, s "%s\t$%02x,fr%d\n", w & 1 ? "." : "", w >> 17 & 0xff, rb) - -#define xsform(s) fprintf(f, s "%s\tr%d,r%d,%d\n", w & 1 ? "." : "", ra, rd, rb | (w & 2 ? 32 : 0)) - -#define xoform_dab(s) fprintf(f, "%s%s\tr%d,r%d,r%d\n", s, w & 1 ? "." : "", rd, ra, rb) -#define xoform_da(s) fprintf(f, "%s%s\tr%d,r%d\n", s, w & 1 ? "." : "", rd, ra) - -#define aform_dab(s) fprintf(f, "%s%s\tfr%d,fr%d,fr%d\n", s, w & 1 ? "." : "", rd, ra, rb) -#define aform_db(s) fprintf(f, "%s%s\tfr%d,fr%d\n", s, w & 1 ? "." : "", rd, rb) -#define aform_dac(s) fprintf(f, "%s%s\tfr%d,fr%d,fr%d\n", s, w & 1 ? "." : "", rd, ra, rc) -#define aform_dacb(s) fprintf(f, "%s%s\tfr%d,fr%d,fr%d,fr%d\n", s, w & 1 ? "." : "", rd, ra, rc, rb) - -#define mform(s) fprintf(f, "%s%s\tr%d,r%d,r%d,$%08x\n", s, w & 1 ? "." : "", ra, rd, rb, mbme2mask(w >> 6 & 31, w >>1 & 31)) -#define mform_i(s) fprintf(f, "%s%s\tr%d,r%d,%d,$%08x\n", s, w & 1 ? "." : "", ra, rd, rb, mbme2mask(w >> 6 & 31, w >>1 & 31)) - -#define mdform(s) fprintf(f, "%s%s\tr%d,r%d,%d,%d\n", s, w & 1 ? "." : "", ra, rd, rb | (w & 2 ? 32 : 0), rc | (w & 32 ? 32 : 0)) - -#define mdsform(s) fprintf(f, "%s%s\tr%d,r%d,r%d,%d\n", s, w & 1 ? "." : "", ra, rd, rb, rc | (w & 32 ? 32 : 0)) - -#define va_form(s) fprintf(f, "%s\tv%d,v%d,v%d,v%d\n", s, rd, ra, rb, rc) -#define vx_form(s) fprintf(f, "%s\tv%d,v%d,v%d\n", s, rd, ra, rb) -#define vxr_form(s) fprintf(f, "%s%s\tv%d,v%d,v%d\n", s, w & (1 << 10) ? "." : "", rd, ra, rb) -#define vxi_ra_form(s) fprintf(f, "%s\tv%d,v%d,%d\n", s, rd, rb, ra) -#define vx_raz_form(s) \ - if (ra == 0) \ - fprintf(f, "%s\tv%d,v%d\n", s, rd, rb); \ - else \ - fprintf(f, "?\n") -#define vxi_ras_rbz_form(s) \ - if (rb == 0) \ - fprintf(f, "%s\tv%d,%d\n", s, rd, ra - (ra & 0x10 ? 0x20 : 0)); \ - else \ - fprintf(f, "?\n") - -// Prototypes -static void disass4(FILE *f, unsigned int adr, unsigned int w); -static void disass19(FILE *f, unsigned int adr, unsigned int w); -static void disass31(FILE *f, unsigned int adr, unsigned int w); -static void disass59(FILE *f, unsigned int adr, unsigned int w); -static void disass63(FILE *f, unsigned int adr, unsigned int w); -static unsigned int mbme2mask(int mb, int me); -static char *get_spr(int reg); - - -/* - * Disassemble one instruction - */ - -void disass_ppc(FILE *f, unsigned int adr, unsigned int w) -{ - // Divide instruction into fields - primop = w >> 26; - rd = w >> 21 & 0x1f; - ra = w >> 16 & 0x1f; - rb = w >> 11 & 0x1f; - rc = w >> 6 & 0x1f; - exop = w >> 1 & 0x3ff; - vxop = w & 0x7ff; - imm = w & 0xffff; - - // Decode primary opcode - switch (primop) { - case 2: // 64 bit - if (to_code[rd] != NULL) - fprintf(f, "td%si\tr%d,$%04x\n", to_code[rd], ra, short(imm)); - else - dform_to("tdi"); - break; - - case 3: - if (to_code[rd] != NULL) - fprintf(f, "tw%si\tr%d,$%04x\n", to_code[rd], ra, short(imm)); - else - dform_to("twi"); - break; - - case 4: // AltiVec - disass4(f, adr, w); - break; - - case 7: dform_simm("mulli"); break; - case 8: dform_simm("subfic"); break; - - case 10: - if (rd & 1) - dform_cru("cmpldi"); // 64 bit - else - dform_cru("cmplwi"); - break; - - case 11: - if (rd & 1) - dform_crs("cmpdi"); // 64 bit - else - dform_crs("cmpwi"); - break; - - case 12: - if (imm < 0x8000) - dform_simm("addic"); - else - dform_simmn("subic"); - break; - - case 13: - if (imm < 0x8000) - dform_simm("addic."); - else - dform_simmn("subic."); - break; - - case 14: - if (ra == 0) - fprintf(f, "li\tr%d,$%04x\n", rd, short(imm)); - else - if (imm < 0x8000) - dform_simm("addi"); - else - dform_simmn("subi"); - break; - - case 15: - if (ra == 0) - fprintf(f, "lis\tr%d,$%04x\n", rd, imm); - else - if (imm < 0x8000) - dform_simm("addis"); - else - dform_simmn("subis"); - break; - - case 16: { - int target = short(imm & 0xfffc); - char *form; - if (w & 1) - if (w & 2) - form = "la"; - else { - form = "l"; - target += adr; - } - else - if (w & 2) - form = "a"; - else { - form = ""; - target += adr; - } - bform(form, target); - break; - } - - case 17: - if (w & 2) - scform("sc"); - else - fprintf(f, "?\n"); - break; - - case 18: { - int target = w & 0x03fffffc; - if (target & 0x02000000) - target |= 0xfc000000; - if (w & 1) - if (w & 2) - iform("bla", target); - else - iform("bl", adr + target); - else - if (w & 2) - iform("ba", target); - else - iform("b", adr + target); - break; - } - - case 19: disass19(f, adr, w); break; - case 20: mform_i("rlwimi"); break; - case 21: mform_i("rlwinm"); break; - case 23: mform("rlwnm"); break; - - case 24: - if (rd == 0 && ra == 0 && imm == 0) - fprintf(f, "nop\n"); - else - dform_uimm("ori"); - break; - - case 25: dform_uimm("oris"); break; - case 26: dform_uimm("xori"); break; - case 27: dform_uimm("xoris"); break; - case 28: dform_uimm("andi."); break; - case 29: dform_uimm("andis."); break; - - case 30: // 64 bit - switch (w >> 1 & 0xf) { - case 0: case 1: mdform("rldicl"); break; - case 2: case 3: mdform("rldicr"); break; - case 4: case 5: mdform("rldic"); break; - case 6: case 7: mdform("rldimi"); break; - case 8: mdsform("rldcl"); break; - case 9: mdsform("rldcr"); break; - default: - fprintf(f, "?\n"); - break; - }; - break; - - case 31: disass31(f, adr, w); break; - case 32: dform_ls("lwz"); break; - case 33: dform_ls("lwzu"); break; - case 34: dform_ls("lbz"); break; - case 35: dform_ls("lbzu"); break; - case 36: dform_ls("stw"); break; - case 37: dform_ls("stwu"); break; - case 38: dform_ls("stb"); break; - case 39: dform_ls("stbu"); break; - case 40: dform_ls("lhz"); break; - case 41: dform_ls("lhzu"); break; - case 42: dform_ls("lha"); break; - case 43: dform_ls("lhau"); break; - case 44: dform_ls("sth"); break; - case 45: dform_ls("sthu"); break; - case 46: dform_ls("lmw"); break; - case 47: dform_ls("stmw"); break; - case 48: dform_fls("lfs"); break; - case 49: dform_fls("lfsu"); break; - case 50: dform_fls("lfd"); break; - case 51: dform_fls("lfdu"); break; - case 52: dform_fls("stfs"); break; - case 53: dform_fls("stfsu"); break; - case 54: dform_fls("stfd"); break; - case 55: dform_fls("stfdu"); break; - - case 58: // 64 bit - switch (w & 3) { - case 0: dsform("ld"); break; - case 1: dsform("ldu"); break; - case 2: dsform("lwa"); break; - default: - fprintf(f, "?\n"); - break; - } - break; - - case 59: disass59(f, adr, w); break; - - case 62: // 64 bit - switch (w & 3) { - case 0: dsform("std"); break; - case 1: dsform("stdu"); break; - default: - fprintf(f, "?\n"); - break; - } - break; - - case 63: disass63(f, adr, w); break; - - default: - if (!w) - fprintf(f, "illegal\n"); - else - fprintf(f, "?\n"); - break; - } -} - - -/* - * Disassemble instruction with primary opcode = 4 (VX-Form) - */ - -static void disass4(FILE *f, unsigned int adr, unsigned int w) -{ - switch (vxop) { - case 1540: - if (ra == 0 && rb == 0) - fprintf(f, "mfvscr\tv%d\n", rd); - else - fprintf(f, "?\n"); - break; - case 1604: - if (rd == 0 && ra == 0) - fprintf(f, "mtvscr\tv%d\n", rb); - else - fprintf(f, "?\n"); - break; - case 384: vx_form("vaddcuw"); break; - case 10: vx_form("vaddfp"); break; - case 768: vx_form("vaddsbs"); break; - case 832: vx_form("vaddshs"); break; - case 896: vx_form("vaddsws"); break; - case 0: vx_form("vaddubm"); break; - case 512: vx_form("vaddubs"); break; - case 64: vx_form("vadduhm"); break; - case 576: vx_form("vadduhs"); break; - case 128: vx_form("vadduwm"); break; - case 640: vx_form("vadduws"); break; - case 1028: vx_form("vand"); break; - case 1092: vx_form("vandc"); break; - case 1282: vx_form("vavgsb"); break; - case 1346: vx_form("vavgsh"); break; - case 1410: vx_form("vavgsw"); break; - case 1026: vx_form("vavgub"); break; - case 1090: vx_form("vavguh"); break; - case 1154: vx_form("vavguw"); break; - case 842: vxi_ra_form("vcfsx"); break; - case 778: vxi_ra_form("vcfux"); break; - case 966: case 966+1024: vxr_form("vcmpbfp"); break; - case 198: case 198+1024: vxr_form("vcmpeqfp"); break; - case 6: case 6+1024: vxr_form("vcmpequb"); break; - case 70: case 70+1024: vxr_form("vcmpequh"); break; - case 134: case 134+1024: vxr_form("vcmpequw"); break; - case 454: case 454+1024: vxr_form("vcmpgefp"); break; - case 710: case 710+1024: vxr_form("vcmpgtfp"); break; - case 774: case 774+1024: vxr_form("vcmpgtsb"); break; - case 838: case 838+1024: vxr_form("vcmpgtsh"); break; - case 902: case 902+1024: vxr_form("vcmpgtsw"); break; - case 518: case 518+1024: vxr_form("vcmpgtub"); break; - case 582: case 582+1024: vxr_form("vcmpgtuh"); break; - case 646: case 646+1024: vxr_form("vcmpgtuw"); break; - case 970: vxi_ra_form("vctsxs"); break; - case 906: vxi_ra_form("vctuxs"); break; - case 394: vx_raz_form("vexptefp"); break; - case 458: vx_raz_form("vlogefp"); break; - case 1034: vx_form("vmaxfp"); break; - case 258: vx_form("vmaxsb"); break; - case 322: vx_form("vmaxsh"); break; - case 386: vx_form("vmaxsw"); break; - case 2: vx_form("vmaxub"); break; - case 66: vx_form("vmaxuh"); break; - case 130: vx_form("vmaxuw"); break; - case 1098: vx_form("vminfp"); break; - case 770: vx_form("vminsb"); break; - case 834: vx_form("vminsh"); break; - case 898: vx_form("vminsw"); break; - case 514: vx_form("vminub"); break; - case 578: vx_form("vminuh"); break; - case 642: vx_form("vminuw"); break; - case 12: vx_form("vmrghb"); break; - case 76: vx_form("vmrghh"); break; - case 140: vx_form("vmrghw"); break; - case 268: vx_form("vmrglb"); break; - case 332: vx_form("vmrglh"); break; - case 396: vx_form("vmrglw"); break; - case 776: vx_form("vmulesb"); break; - case 840: vx_form("vmulesh"); break; - case 520: vx_form("vmuleub"); break; - case 584: vx_form("vmuleuh"); break; - case 264: vx_form("vmulosb"); break; - case 328: vx_form("vmulosh"); break; - case 8: vx_form("vmuloub"); break; - case 72: vx_form("vmulouh"); break; - case 1284: vx_form("vnor"); break; - case 1156: vx_form("vor"); break; - case 782: vx_form("vpkpx"); break; - case 398: vx_form("vpkshss"); break; - case 270: vx_form("vpkshus"); break; - case 462: vx_form("vpkswss"); break; - case 334: vx_form("vpkswus"); break; - case 14: vx_form("vpkuhum"); break; - case 142: vx_form("vpkuhus"); break; - case 78: vx_form("vpkuwum"); break; - case 206: vx_form("vpkuwus"); break; - case 266: vx_raz_form("vrefp"); break; - case 714: vx_raz_form("vrfim"); break; - case 522: vx_raz_form("vrfin"); break; - case 650: vx_raz_form("vrfip"); break; - case 586: vx_raz_form("vrfiz"); break; - case 4: vx_form("vrlb"); break; - case 68: vx_form("vrlh"); break; - case 132: vx_form("vrlw"); break; - case 330: vx_raz_form("vrsqrtefp"); break; - case 452: vx_form("vsl"); break; - case 260: vx_form("vslb"); break; - case 324: vx_form("vslh"); break; - case 1036: vx_form("vslo"); break; - case 388: vx_form("vslw"); break; - case 524: vxi_ra_form("vspltb"); break; - case 588: vxi_ra_form("vsplth"); break; - case 780: vxi_ras_rbz_form("vspltisb"); break; - case 844: vxi_ras_rbz_form("vspltish"); break; - case 908: vxi_ras_rbz_form("vspltisw"); break; - case 652: vxi_ra_form("vspltw"); break; - case 708: vx_form("vsr"); break; - case 772: vx_form("vsrab"); break; - case 836: vx_form("vsrah"); break; - case 900: vx_form("vsraw"); break; - case 516: vx_form("vsrb"); break; - case 580: vx_form("vsrh"); break; - case 1100: vx_form("vsro"); break; - case 644: vx_form("vsrw"); break; - case 1408: vx_form("vsubcuw"); break; - case 74: vx_form("vsubfp"); break; - case 1792: vx_form("vsubsbs"); break; - case 1856: vx_form("vsubshs"); break; - case 1920: vx_form("vsubsws"); break; - case 1024: vx_form("vsububm"); break; - case 1536: vx_form("vsububs"); break; - case 1088: vx_form("vsubuhm"); break; - case 1600: vx_form("vsubuhs"); break; - case 1152: vx_form("vsubuwm"); break; - case 1664: vx_form("vsubuws"); break; - case 1928: vx_form("vsumsws"); break; - case 1672: vx_form("vsum2sws"); break; - case 1800: vx_form("vsum4sbs"); break; - case 1608: vx_form("vsum4shs"); break; - case 1544: vx_form("vsum4ubs"); break; - case 846: vx_raz_form("vupkhpx"); break; - case 526: vx_raz_form("vupkhsb"); break; - case 590: vx_raz_form("vupkhsh"); break; - case 974: vx_raz_form("vupklpx"); break; - case 654: vx_raz_form("vupklsb"); break; - case 718: vx_raz_form("vupklsh"); break; - case 1220: vx_form("vxor"); break; - default: - if ((vxop & 0x43f) == 44) { // vsldoi vD,vA,vB,SHB - fprintf(f, "vsldoi\tv%d,v%d,v%d,%d\n", rd, ra, rb, rc & 15); - break; - } - switch (vxop & 0x3f) { // VA-form, must come last - case 46: va_form("vmaddfp"); break; - case 32: va_form("vmhaddshs"); break; - case 33: va_form("vmhraddshs"); break; - case 34: va_form("vmladduhm"); break; - case 37: va_form("vmsummbm"); break; - case 40: va_form("vmsumshm"); break; - case 41: va_form("vmsumshs"); break; - case 36: va_form("vmsumubm"); break; - case 38: va_form("vmsumuhm"); break; - case 39: va_form("vmsumuhs"); break; - case 47: va_form("vnmsubfp"); break; - case 43: va_form("vperm"); break; - case 42: va_form("vsel"); break; - default: fprintf(f, "?\n"); break; - } - break; - } -} - - -/* - * Disassemble instruction with primary opcode = 19 (XL-Form) - */ - -static void disass19(FILE *f, unsigned int adr, unsigned int w) -{ - switch (exop) { - case 0: xlform_crcr("mcrf"); break; - - case 16: - if (w & 1) - if (rd == 20) - fprintf(f, "blrl\n"); - else - xlform_b("bclrl"); - else - if (rd == 20) - fprintf(f, "blr\n"); - else - xlform_b("bclr"); - break; - - case 33: - if (ra == rb) - fprintf(f, "crnot\tcrb%d,crb%d\n", rd, ra); - else - xlform_cr("crnor"); - break; - - case 50: xlform("rfi"); break; - case 129: xlform_cr("crandc"); break; - case 150: xlform("isync"); break; - - case 193: - if (ra == rd && rb == rd) - fprintf(f, "crclr\tcrb%d\n", rd); - else - xlform_cr("crxor"); - break; - - case 225: xlform_cr("crnand"); break; - case 257: xlform_cr("crand"); break; - - case 289: - if (ra == rd && rb == rd) - fprintf(f, "crset\tcrb%d\n", rd); - else - xlform_cr("creqv"); - break; - - case 417: xlform_cr("crorc"); break; - - case 449: - if (ra == rb) - fprintf(f, "crmove\tcrb%d,crb%d\n", rd, ra); - else - xlform_cr("cror"); - break; - - case 528: - if (w & 1) - if (rd == 20) - fprintf(f, "bctrl\n"); - else - xlform_b("bcctrl"); - else - if (rd == 20) - fprintf(f, "bctr\n"); - else - xlform_b("bcctr"); - break; - - default: - fprintf(f, "?\n"); - break; - } -} - - -/* - * Disassemble instruction with primary opcode = 31 (X-Form/XO-Form/XFX-Form/XS-Form) - */ - -static void disass31(FILE *f, unsigned int adr, unsigned int w) -{ - switch (exop) { - case 0: - if (rd & 1) - xform_crlab("cmpd"); // 64 bit - else - xform_crlab("cmpw"); - break; - - case 4: - if (rd == 31 && ra == 0 && rb == 0) - xform("trap"); - else if (to_code[rd] != NULL) - fprintf(f, "tw%s\tr%d,r%d\n", to_code[rd], ra, rb); - else - xform_to("tw"); - break; - - case 6: xform_vls("lvsl"); break; - case 7: xform_vls("lvebx"); break; - case 8: xoform_dab("subfc"); break; - case 8+512: xoform_dab("subfco"); break; - case 9: case 9+512: xoform_dab("mulhdu"); break; // 64 bit - case 10: xoform_dab("addc"); break; - case 10+512: xoform_dab("addco"); break; - case 11: case 11+512: xoform_dab("mulhwu"); break; - case 19: xform_d("mfcr"); break; - case 20: xform_ls("lwarx"); break; - case 21: xform_ls("ldx"); break; // 64 bit - case 23: xform_ls("lwzx"); break; - case 24: xform_sabc("slw"); break; - case 26: xform_sac("cntlzw"); break; - case 27: xform_sabc("sld"); break; // 64 bit - case 28: xform_sabc("and"); break; - - case 32: - if (rd & 1) - xform_crlab("cmpld"); // 64 bit - else - xform_crlab("cmplw"); - break; - - case 38: xform_vls("lvsr"); break; - case 39: xform_vls("lvehx"); break; - case 40: xoform_dab("subf"); break; - case 40+512: xoform_dab("subfo"); break; - case 53: xform_ls("ldux"); break; // 64 bit - case 54: xform_ab("dcbst"); break; - case 55: xform_ls("lwzux"); break; - case 58: xform_sac("cntlzd"); break; // 64 bit - case 60: xform_sabc("andc"); break; - - case 68: // 64 bit - if (to_code[rd] != NULL) - fprintf(f, "td%s\tr%d,r%d\n", to_code[rd], ra, rb); - else - xform_to("td"); - break; - - case 71: xform_vls("lvewx"); break; - case 73: case 73+512: xoform_dab("mulhd"); break; // 64 bit - case 75: case 75+512: xoform_dab("mulhw"); break; - case 83: xform_d("mfmsr"); break; - case 84: xform_ls("ldarx"); break; // 64 bit - case 86: xform_ab("dcbf"); break; - case 87: xform_ls("lbzx"); break; - case 103: xform_vls("lvx"); break; - case 104: xoform_da("neg"); break; - case 104+512: xoform_da("nego"); break; - case 119: xform_ls("lbzux"); break; - - case 124: - if (rd == rb) - fprintf(f, "not%s\tr%d,r%d\n", w & 1 ? "." : "", ra, rd); - else - xform_sabc("nor"); - break; - - case 135: xform_vls("stvebx"); break; - case 136: xoform_dab("subfe"); break; - case 136+512: xoform_dab("subfeo"); break; - case 138: xoform_dab("adde"); break; - case 138+512: xoform_dab("addeo"); break; - case 144: xfxform_crm("mtcrf"); break; - case 146: xform_d("mtmsr"); break; - case 149: xform_ls("stdx"); break; // 64 bit - - case 150: - if (w & 1) - xform_ls("stwcx."); - else - fprintf(f, "?\n"); - break; - - case 151: xform_ls("stwx"); break; - case 167: xform_vls("stvehx"); break; - case 181: xform_ls("stdux"); break; // 64 bit - case 183: xform_ls("stwux"); break; - case 199: xform_vls("stvewx"); break; - case 200: xoform_da("subfze"); break; - case 200+512: xoform_da("subfzeo"); break; - case 202: xoform_da("addze"); break; - case 202+512: xoform_da("addzeo"); break; - case 210: xform_tsr("mtsr"); break; - - case 214: // 64 bit - if (w & 1) - xform_ls("stdcx"); - else - fprintf(f, "?\n"); - break; - - case 215: xform_ls("stbx"); break; - case 231: xform_vls("stvx"); break; - case 232: xoform_da("subfme"); break; - case 232+512: xoform_da("subfmeo"); break; - case 233: xoform_dab("mulld"); break; // 64 bit - case 233+512: xoform_dab("mulldo"); break; // 64 bit - case 234: xoform_da("addme"); break; - case 234+512: xoform_da("addmeo"); break; - case 235: xoform_dab("mullw"); break; - case 235+512: xoform_dab("mullwo"); break; - case 242: xform_db("mtsrin"); break; - case 246: xform_ab("dcbtst"); break; - case 247: xform_ls("stbux"); break; - case 266: xoform_dab("add"); break; - case 266+512: xoform_dab("addo"); break; - case 278: xform_ab("dcbt"); break; - case 279: xform_ls("lhzx"); break; - case 284: xform_sabc("eqv"); break; - case 306: xform_b("tlbie"); break; - case 310: xform_ls("eciwx"); break; - case 311: xform_ls("lhzux"); break; - case 316: xform_sabc("xor"); break; - - case 339: - if ((ra | (rb << 5)) == 1) - fprintf(f, "mfxer\tr%d\n", rd); - else if ((ra | (rb << 5)) == 8) - fprintf(f, "mflr\tr%d\n", rd); - else if ((ra | (rb << 5)) == 9) - fprintf(f, "mfctr\tr%d\n", rd); - else if ((ra | (rb << 5)) == 256) - fprintf(f, "mfvrsave\tr%d\n", rd); - else { - char *spr = get_spr(ra | (rb << 5)); - if (spr) - fprintf(f, "mfspr\tr%d,%s\n", rd, spr); - else - xfxform_fspr("mfspr"); - } - break; - - case 341: xform_ls("lwax"); break; // 64 bit - case 343: xform_ls("lhax"); break; - case 359: xform_vls("lvxl"); break; - case 370: xform("tlbia"); break; - - case 822: // AltiVec - if ((rd & 0xc) == 0 && ra == 0 && rb == 0 && (w & 1) == 0) { - if (rd & 0x10) - fprintf(f, "dssall\n"); - else - fprintf(f, "dss\t%d\n", rd & 3); - } - else - fprintf(f, "?\n"); - break; - - case 342: // AltiVec - if ((rd & 0xc) == 0 && (w & 1) == 0) - fprintf(f, "dst%s\tr%d,r%d,%d\n", rd & 0x10 ? "t" : "", ra, rb, rd & 3); - else - fprintf(f, "?\n"); - break; - - case 374: // AltiVec - if ((rd & 0xc) == 0 && (w & 1) == 0) - fprintf(f, "dstst%s\tr%d,r%d,%d\n", rd & 0x10 ? "t" : "", ra, rb, rd & 3); - else - fprintf(f, "?\n"); - break; - - case 371: - if ((ra | (rb << 5)) == 268) - xfxform_tb("mftb"); - else if ((ra | (rb << 5)) == 269) - xfxform_tb("mftbu"); - else - fprintf(f, "?\n"); - break; - - case 373: xform_ls("lwaux"); break; // 64 bit - case 375: xform_ls("lhaux"); break; - case 407: xform_ls("sthx"); break; - case 412: xform_sabc("orc"); break; - case 434: xform_b("slbie"); break; // 64 bit - case 438: xform_ls("ecowx"); break; - case 439: xform_ls("sthux"); break; - - case 444: - if (rd == rb) - fprintf(f, "mr%s\tr%d,r%d\n", w & 1 ? "." : "", ra, rd); - else - xform_sabc("or"); - break; - - case 457: xoform_dab("divdu"); break; // 64 bit - case 457+512: xoform_dab("divduo"); break; // 64 bit - case 459: xoform_dab("divwu"); break; - case 459+512: xoform_dab("divwuo"); break; - - case 467: - if ((ra | (rb << 5)) == 1) - fprintf(f, "mtxer\tr%d\n", rd); - else if ((ra | (rb << 5)) == 8) - fprintf(f, "mtlr\tr%d\n", rd); - else if ((ra | (rb << 5)) == 9) - fprintf(f, "mtctr\tr%d\n", rd); - else if ((ra | (rb << 5)) == 256) - fprintf(f, "mtvrsave\tr%d\n", rd); - else { - char *spr = get_spr(ra | (rb << 5)); - if (spr) - fprintf(f, "mtspr\t%s,r%d\n", spr, rd); - else - xfxform_tspr("mtspr"); - } - break; - - case 470: xform_ab("dcbi"); break; - case 476: xform_sabc("nand"); break; - case 487: xform_vls("stvxl"); break; - case 489: xoform_dab("divd"); break; // 64 bit - case 489+512: xoform_dab("divdo"); break; // 64 bit - case 491: xoform_dab("divw"); break; - case 491+512: xoform_dab("divwo"); break; - case 498: xform("slbia"); break; // 64 bit - case 512: xform_cr("mcrxr"); break; - case 533: xform_ls("lswx"); break; - case 534: xform_ls("lwbrx"); break; - case 535: xform_fls("lfsx"); break; - case 536: xform_sabc("srw"); break; - case 539: xform_sabc("srd"); break; // 64 bit - case 566: xform("tlbsync"); break; - case 567: xform_fls("lfsux"); break; - case 595: xform_fsr("mfsr"); break; - case 597: xform_lsswi("lswi"); break; - case 598: xform("sync"); break; - case 599: xform_fls("lfdx"); break; - case 631: xform_fls("lfdux"); break; - case 659: xform_db("mfsrin"); break; - case 661: xform_ls("stswx"); break; - case 662: xform_ls("stwbrx"); break; - case 663: xform_fls("stfsx"); break; - case 695: xform_fls("stfsux"); break; - case 725: xform_lsswi("stswi"); break; - case 727: xform_fls("stfdx"); break; - case 758: xform_ab("dcba"); break; - case 759: xform_fls("stfdux"); break; - case 790: xform_ls("lhbrx"); break; - case 792: xform_sabc("sraw"); break; - case 794: xform_sabc("srad"); break; // 64 bit - case 824: xform_sash("srawi"); break; - case 826: case 827: xsform("sradi"); break; // 64 bit - case 854: xform("eieio"); break; - case 918: xform_ls("sthbrx"); break; - case 922: xform_sac("extsh"); break; - case 954: xform_sac("extsb"); break; - case 978: fprintf(f, "tlbld\tr%d\n", rb); break; // 603 - case 982: xform_ab("icbi"); break; - case 983: xform_fls("stfiwx"); break; - case 986: xform_sac("extsw"); break; // 64 bit - case 1010: fprintf(f, "tlbli\tr%d\n", rb); break; // 603 - case 1014: xform_ab("dcbz"); break; - - default: - fprintf(f, "?\n"); - break; - } -} - - -/* - * Disassemble instruction with primary opcode = 59 (A-Form) - */ - -static void disass59(FILE *f, unsigned int adr, unsigned int w) -{ - switch (exop & 0x1f) { - case 18: aform_dab("fdivs"); break; - case 20: aform_dab("fsubs"); break; - case 21: aform_dab("fadds"); break; - case 22: aform_db("fsqrts"); break; - case 24: aform_db("fres"); break; - case 25: aform_dac("fmuls"); break; - case 28: aform_dacb("fmsubs"); break; - case 29: aform_dacb("fmadds"); break; - case 30: aform_dacb("fnmsubs"); break; - case 31: aform_dacb("fnmadds"); break; - - default: - fprintf(f, "?\n"); - break; - } -} - - -/* - * Disassemble instruction with primary opcode = 63 (A-Form/X-Form/XFL-Form) - */ - -static void disass63(FILE *f, unsigned int adr, unsigned int w) -{ - if (exop & 0x10) - switch (exop & 0x1f) { - case 18: aform_dab("fdiv"); break; - case 20: aform_dab("fsub"); break; - case 21: aform_dab("fadd"); break; - case 22: aform_db("fsqrt"); break; - case 23: aform_dacb("fsel"); break; - case 25: aform_dac("fmul"); break; - case 26: aform_db("frsqrte"); break; - case 28: aform_dacb("fmsub"); break; - case 29: aform_dacb("fmadd"); break; - case 30: aform_dacb("fnmsub"); break; - case 31: aform_dacb("fnmadd"); break; - - default: - fprintf(f, "?\n"); - break; - } - else - switch (exop) { - case 0: xform_fcrab("fcmpu"); break; - case 12: xform_fdb("frsp"); break; - case 14: xform_fdb("fctiw"); break; - case 15: xform_fdb("fctiwz"); break; - case 32: xform_fcrab("fcmpo"); break; - case 38: xform_crb("mtfsb1"); break; - case 40: xform_fdb("fneg"); break; - case 64: xform_crcr("mcrfs"); break; - case 70: xform_crb("mtfsb0"); break; - case 72: xform_fdb("fmr"); break; - case 134: xform_cri("mtfsfi"); break; - case 136: xform_fdb("fnabs"); break; - case 264: xform_fdb("fabs"); break; - case 583: xform_fd("mffs"); break; - case 711: xflform("mtfsf"); break; - case 814: xform_fdb("fctid"); break; // 64 bit - case 815: xform_fdb("fctidz"); break; // 64 bit - case 846: xform_fdb("fcfid"); break; // 64 bit - - default: - fprintf(f, "?\n"); - break; - } -} - - -/* - * Convert mask begin/end to mask - */ - -static unsigned int mbme2mask(int mb, int me) -{ - unsigned int m = 0; - int i; - - if (mb <= me) - for (i=mb; i<=me; i++) - m |= 1 << (31-i); - else { - for (i=0; i<=me; i++) - m |= 1 << (31-i); - for (i=mb; i<=31; i++) - m |= 1 << (31-i); - } - return m; -} - - -/* - * Convert SPR number to register name - */ - -char *get_spr(int reg) -{ - switch (reg) { - case 1: return "xer"; - case 8: return "lr"; - case 9: return "ctr"; - case 18: return "dsisr"; - case 19: return "dar"; - case 22: return "dec"; - case 25: return "sdr1"; - case 26: return "srr0"; - case 27: return "srr1"; - case 272: return "sprg0"; - case 273: return "sprg1"; - case 274: return "sprg2"; - case 275: return "sprg3"; - case 280: return "asr"; // 64 bit - case 282: return "ear"; - case 284: return "tbl"; - case 285: return "tbu"; - case 287: return "pvr"; - case 528: return "ibat0u"; - case 529: return "ibat0l"; - case 530: return "ibat1u"; - case 531: return "ibat1l"; - case 532: return "ibat2u"; - case 533: return "ibat2l"; - case 534: return "ibat3u"; - case 535: return "ibat3l"; - case 536: return "dbat0u"; - case 537: return "dbat0l"; - case 538: return "dbat1u"; - case 539: return "dbat1l"; - case 540: return "dbat2u"; - case 541: return "dbat2l"; - case 542: return "dbat3u"; - case 543: return "dbat3l"; - case 1013: return "dabr"; - - case 0: return "mq"; // 601 - case 4: return "rtcu"; // 601 - case 5: return "rtcl"; // 601 - case 20: return "rtcu"; // 601 - case 21: return "rtcl"; // 601 - case 952: return "mmcr0"; // 604 - case 953: return "pmc1"; // 604 - case 954: return "pmc2"; // 604 - case 955: return "sia"; // 604 - case 956: return "mmcr1"; // 604e - case 957: return "pmc3"; // 604e - case 958: return "pmc4"; // 604e - case 959: return "sda"; // 604 - case 976: return "dmiss"; // 603 - case 977: return "dcmp"; // 603 - case 978: return "hash1"; // 603 - case 979: return "hash2"; // 603 - case 980: return "imiss"; // 603 - case 981: return "icmp"; // 603 - case 982: return "rpa"; // 603 - case 1008: return "hid0"; // 601/603/604 - case 1009: return "hid1"; // 601/603/604e - case 1010: return "iabr"; // 601/603 - case 1023: return "pir"; // 601/604 - - case 256: return "vrsave"; // AltiVec - - default: return NULL; - } -} diff --git a/cxmon/src/mon_z80.cpp b/cxmon/src/mon_z80.cpp deleted file mode 100644 index b103f5f0..00000000 --- a/cxmon/src/mon_z80.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* - * mon_z80.cpp - Z80 disassembler - * - * cxmon (C) 1997-2007 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include - -#include "mon.h" -#include "mon_disass.h" - - -// Addressing modes -enum AddrMode { - A_IMPL, - A_IMM8, // xx - A_IMM16, // xxxx - A_ABS8, // (xx) - A_ABS16, // (xxxx) - A_REL, // relative - A_A, // a - A_HL, // hl or ix or iy - A_SP, // sp - A_REG1, // 8-bit register (bits 0..2 of opcode) or (hl)/(ix+d)/(iy+d) - A_REG1X, // 8-bit register (bits 0..2 of opcode) or (hl)/(ix+d)/(iy+d), don't substitute h or l on prefixes - A_REG2, // 8-bit register (bits 3..5 of opcode) or (hl)/(ix+d)/(iy+d) - A_REG2X, // 8-bit register (bits 3..5 of opcode) or (hl)/(ix+d)/(iy+d), don't substitute h or l on prefixes - A_REG3, // 16-bit register (bits 4..5 of opcode) bc/de/hl/sp - A_REG4, // 16-bit register (bits 4..5 of opcode) bc/de/hl/af - A_COND, // condition code (bits 3..5 of opcode) - A_COND2, // condition code (bits 3..4 of opcode) - A_BIT, // bit number (bits 3..5 of opcode) - A_BIT_REG1, // bit number (bits 3..5 of opcode) followed by 8-bit register (bits 0..2 of opcode) - A_RST, // restart - A_BC_IND, // (bc) - A_DE_IND, // (de) - A_HL_IND, // (hl) or (ix) or (iy) - A_XY_IND, // (ix+d) or (iy+d) - A_SP_IND, // (sp) - A_DE_HL, // de,hl - A_AF_AF, // af,af' -}; - -// Mnemonics -enum Mnemonic { - M_ADC, M_ADD, M_AND, M_BIT, M_CALL, M_CCF, M_CP, M_CPD, M_CPDR, M_CPI, - M_CPIR, M_CPL, M_DAA, M_DEC, M_DI, M_DJNZ, M_EI, M_EX, M_EXX, M_HALT, - M_IM0, M_IM1, M_IM2, M_IN, M_INC, M_IND, M_INDR, M_INI, M_INIR, M_JP, - M_JR, M_LD, M_LDD, M_LDDR, M_LDI, M_LDIR, M_NEG, M_NOP, M_OR, M_OTDR, - M_OTIR, M_OUT, M_OUTD, M_OUTI, M_POP, M_PUSH, M_RES, M_RET, M_RETI, - M_RETN, M_RL, M_RLA, M_RLC, M_RLCA, M_RLD, M_RR, M_RRA, M_RRC, M_RRCA, - M_RRD, M_RST, M_SBC, M_SCF, M_SET, M_SL1, M_SLA, M_SRA, M_SRL, M_SUB, - M_XOR, - M_ILLEGAL, - - M_MAXIMUM -}; - -// Chars for each mnemonic -static const char mnem_1[] = "aaabccccccccddddeeehiiiiiiiiijjlllllnnoooooopprrrrrrrrrrrrrrrssssssssx?"; -static const char mnem_2[] = "ddniacppppppaeijixxammmnnnnnnprdddddeorttuuuoueeeelllllrrrrrsbcellrruo "; -static const char mnem_3[] = "cddtlf ddiilac n xl cddii ddiigp ditttpssttt accd accdtcft1aalbr "; -static const char mnem_4[] = " l r r z t012 r r r r rr di h in a a "; - -// Mnemonic for each opcode -static const Mnemonic mnemonic[256] = { - M_NOP , M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_RLCA, // 00 - M_EX , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_RRCA, - M_DJNZ, M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_RLA , // 10 - M_JR , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_RRA , - M_JR , M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_DAA , // 20 - M_JR , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_CPL , - M_JR , M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_SCF , // 30 - M_JR , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_CCF , - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , // 40 - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , // 50 - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , // 60 - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_HALT, M_LD , // 70 - M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , - M_ADD , M_ADD, M_ADD, M_ADD , M_ADD , M_ADD , M_ADD , M_ADD , // 80 - M_ADC , M_ADC, M_ADC, M_ADC , M_ADC , M_ADC , M_ADC , M_ADC , - M_SUB , M_SUB, M_SUB, M_SUB , M_SUB , M_SUB , M_SUB , M_SUB , // 90 - M_SBC , M_SBC, M_SBC, M_SBC , M_SBC , M_SBC , M_SBC , M_SBC , - M_AND , M_AND, M_AND, M_AND , M_AND , M_AND , M_AND , M_AND , // a0 - M_XOR , M_XOR, M_XOR, M_XOR , M_XOR , M_XOR , M_XOR , M_XOR , - M_OR , M_OR , M_OR , M_OR , M_OR , M_OR , M_OR , M_OR , // b0 - M_CP , M_CP , M_CP , M_CP , M_CP , M_CP , M_CP , M_CP , - M_RET , M_POP, M_JP , M_JP , M_CALL, M_PUSH , M_ADD , M_RST , // c0 - M_RET , M_RET, M_JP , M_ILLEGAL, M_CALL, M_CALL , M_ADC , M_RST , - M_RET , M_POP, M_JP , M_OUT , M_CALL, M_PUSH , M_SUB , M_RST , // d0 - M_RET , M_EXX, M_JP , M_IN , M_CALL, M_ILLEGAL, M_SBC , M_RST , - M_RET , M_POP, M_JP , M_EX , M_CALL, M_PUSH , M_AND , M_RST , // e0 - M_RET , M_JP , M_JP , M_EX , M_CALL, M_ILLEGAL, M_XOR , M_RST , - M_RET , M_POP, M_JP , M_DI , M_CALL, M_PUSH , M_OR , M_RST , // f0 - M_RET , M_LD , M_JP , M_EI , M_CALL, M_ILLEGAL, M_CP , M_RST -}; - -// Source/destination addressing modes for each opcode -#define A(d,s) (((A_ ## d) << 8) | (A_ ## s)) - -static const int adr_mode[256] = { - A(IMPL,IMPL) , A(REG3,IMM16) , A(BC_IND,A) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 00 - A(AF_AF,IMPL) , A(HL,REG3) , A(A,BC_IND) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , - A(REL,IMPL) , A(REG3,IMM16) , A(DE_IND,A) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 10 - A(REL,IMPL) , A(HL,REG3) , A(A,DE_IND) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , - A(COND2,REL) , A(REG3,IMM16) , A(ABS16,HL) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 20 - A(COND2,REL) , A(HL,REG3) , A(HL,ABS16) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , - A(COND2,REL) , A(REG3,IMM16) , A(ABS16,A) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 30 - A(COND2,REL) , A(HL,REG3) , A(A,ABS16) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , // 40 - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , // 50 - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , // 60 - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , - A(REG2,REG1X) , A(REG2,REG1X) , A(REG2,REG1X), A(REG2,REG1X), A(REG2,REG1X), A(REG2,REG1X), A(IMPL,IMPL) , A(REG2,REG1X), // 70 - A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , - A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , // 80 - A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , - A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , // 90 - A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , - A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , // a0 - A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , - A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , // b0 - A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , - A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(IMM16,IMPL), A(COND,IMM16), A(REG4,IMPL) , A(A,IMM8) , A(RST,IMPL) , // c0 - A(COND,IMPL) , A(IMPL,IMPL) , A(COND,IMM16), A(IMPL,IMPL) , A(COND,IMM16), A(IMM16,IMPL), A(A,IMM8) , A(RST,IMPL) , - A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(ABS8,A) , A(COND,IMM16), A(REG4,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , // d0 - A(COND,IMPL) , A(IMPL,IMPL) , A(COND,IMM16), A(A,ABS8) , A(COND,IMM16), A(IMPL,IMPL) , A(A,IMM8) , A(RST,IMPL) , - A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(SP_IND,HL) , A(COND,IMM16), A(REG4,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , // e0 - A(COND,IMPL) , A(HL_IND,IMPL), A(COND,IMM16), A(DE_HL,IMPL), A(COND,IMM16), A(IMPL,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , - A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(IMPL,IMPL) , A(COND,IMM16), A(REG4,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , // f0 - A(COND,IMPL) , A(SP,HL) , A(COND,IMM16), A(IMPL,IMPL) , A(COND,IMM16), A(IMPL,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) -}; - - -/* - * sprintf into a "stream" - */ - -struct SFILE { - char *buffer; - char *current; -}; - -static int mon_sprintf(SFILE *f, const char *format, ...) -{ - int n; - va_list args; - va_start(args, format); - vsprintf(f->current, format, args); - f->current += n = strlen(f->current); - va_end(args); - return n; -} - - -/* - * Disassemble one instruction, return number of bytes - */ - -static const char *reg_name[] = {"b", "c", "d", "e", "h", "l", "*", "a"}; -static const char *reg_name_ix[] = {"b", "c", "d", "e", "hx", "lx", "*", "a"}; // undoc -static const char *reg_name_iy[] = {"b", "c", "d", "e", "hy", "ly", "*", "a"}; // undoc -static const char *reg_name_16[] = {"bc", "de", "hl", "sp"}; -static const char *reg_name_16_2[] = {"bc", "de", "hl", "af"}; -static const char *cond_name[] = {"nz", "z", "nc", "c", "po", "pe", "p", "m"}; - -static void operand(SFILE *f, char mode, uint32 &adr, uint8 op, bool ix, bool iy) -{ - switch (mode) { - case A_IMPL: - break; - - case A_IMM8: - mon_sprintf(f, "$%02x", mon_read_byte(adr)); adr++; - break; - - case A_IMM16: - mon_sprintf(f, "$%04x", (mon_read_byte(adr + 1) << 8) | mon_read_byte(adr)); adr += 2; - break; - - case A_ABS8: - mon_sprintf(f, "($%02x)", mon_read_byte(adr)); adr++; - break; - - case A_ABS16: - mon_sprintf(f, "($%04x)", (mon_read_byte(adr + 1) << 8) | mon_read_byte(adr)); adr += 2; - break; - - case A_REL: - mon_sprintf(f, "$%04x", (adr + 1 + (int8)mon_read_byte(adr)) & 0xffff); adr++; - break; - - case A_A: - mon_sprintf(f, "a"); - break; - - case A_HL: - mon_sprintf(f, ix ? "ix" : (iy ? "iy" : "hl")); - break; - - case A_SP: - mon_sprintf(f, "sp"); - break; - - case A_REG1: - case A_REG1X: { - int reg = op & 7; - if (reg == 6) { - if (ix || iy) { - mon_sprintf(f, "(%s+$%02x)", ix ? "ix" : "iy", mon_read_byte(adr)); adr++; - } else { - mon_sprintf(f, "(hl)"); - } - } else if (mode == A_REG1) { - mon_sprintf(f, "%s", ix ? reg_name_ix[reg] : (iy ? reg_name_iy[reg] : reg_name[reg])); - } else { - mon_sprintf(f, "%s", reg_name[reg]); - } - break; - } - - case A_REG2: - case A_REG2X: { - int reg = (op >> 3) & 7; - if (reg == 6) { - if (ix || iy) { - mon_sprintf(f, "(%s+$%02x)", ix ? "ix" : "iy", mon_read_byte(adr)); adr++; - } else { - mon_sprintf(f, "(hl)"); - } - } else if (mode == A_REG2) { - mon_sprintf(f, "%s", ix ? reg_name_ix[reg] : (iy ? reg_name_iy[reg] : reg_name[reg])); - } else { - mon_sprintf(f, "%s", reg_name[reg]); - } - break; - } - - case A_REG3: { - int reg = (op >> 4) & 3; - if (reg == 2 && (ix || iy)) { - mon_sprintf(f, ix ? "ix" : "iy"); - } else { - mon_sprintf(f, reg_name_16[reg]); - } - break; - } - - case A_REG4: { - int reg = (op >> 4) & 3; - if (reg == 2 && (ix || iy)) { - mon_sprintf(f, ix ? "ix" : "iy"); - } else { - mon_sprintf(f, reg_name_16_2[reg]); - } - break; - } - - case A_COND: - mon_sprintf(f, cond_name[(op >> 3) & 7]); - break; - - case A_COND2: - mon_sprintf(f, cond_name[(op >> 3) & 3]); - break; - - case A_BIT: - mon_sprintf(f, "%d", (op >> 3) & 7); - break; - - case A_BIT_REG1: { // undoc - int reg = op & 7; - if (reg == 6) { - mon_sprintf(f, "%d", (op >> 3) & 7); - } else { - mon_sprintf(f, "%d,%s", (op >> 3) & 7, reg_name[reg]); - } - break; - } - - case A_RST: - mon_sprintf(f, "$%02x", op & 0x38); - break; - - case A_BC_IND: - mon_sprintf(f, "(bc)"); - break; - - case A_DE_IND: - mon_sprintf(f, "(de)"); - break; - - case A_HL_IND: - mon_sprintf(f, ix ? "(ix)" : (iy ? "(iy)" : "(hl)")); - break; - - case A_XY_IND: // undoc - mon_sprintf(f, "(%s+$%02x)", ix ? "ix" : "iy", mon_read_byte(adr)); adr++; - break; - - case A_SP_IND: - mon_sprintf(f, "(sp)"); - break; - - case A_DE_HL: - mon_sprintf(f, "de,hl"); - break; - - case A_AF_AF: - mon_sprintf(f, "af,af'"); - break; - } -} - -static int print_instr(SFILE *f, Mnemonic mnem, AddrMode dst_mode, AddrMode src_mode, uint32 adr, uint8 op, bool ix, bool iy) -{ - uint32 orig_adr = adr; - - // Print mnemonic - mon_sprintf(f, "%c%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem], mnem_4[mnem]); - - // Print destination operand - operand(f, dst_mode, adr, op, ix, iy); - - // Print source operand - if (src_mode != A_IMPL) - mon_sprintf(f, ","); - operand(f, src_mode, adr, op, ix, iy); - - return adr - orig_adr; -} - -static int disass_cb(SFILE *f, uint32 adr, bool ix, bool iy) -{ - int num; - - // Fetch opcode - uint8 op; - if (ix || iy) { - op = mon_read_byte(adr + 1); - num = 2; - } else { - op = mon_read_byte(adr); - num = 1; - } - - // Decode mnemonic and addressing modes - Mnemonic mnem = M_ILLEGAL; - AddrMode dst_mode = A_IMPL, src_mode = A_IMPL; - - switch (op & 0xc0) { - case 0x00: - dst_mode = A_REG1X; - if ((ix || iy) && ((op & 7) != 6)) - src_mode = A_XY_IND; - switch ((op >> 3) & 7) { - case 0: mnem = M_RLC; break; - case 1: mnem = M_RRC; break; - case 2: mnem = M_RL; break; - case 3: mnem = M_RR; break; - case 4: mnem = M_SLA; break; - case 5: mnem = M_SRA; break; - case 6: mnem = M_SL1; break; // undoc - case 7: mnem = M_SRL; break; - } - break; - case 0x40: - mnem = M_BIT; dst_mode = A_BIT; - if (ix || iy) - src_mode = A_XY_IND; - else - src_mode = A_REG1; - break; - case 0x80: - mnem = M_RES; - if (ix || iy) { - dst_mode = A_BIT_REG1; - src_mode = A_XY_IND; - } else { - dst_mode = A_BIT; - src_mode = A_REG1; - } - break; - case 0xc0: - mnem = M_SET; - if (ix || iy) { - dst_mode = A_BIT_REG1; - src_mode = A_XY_IND; - } else { - dst_mode = A_BIT; - src_mode = A_REG1; - } - break; - } - - // Print instruction - print_instr(f, mnem, dst_mode, src_mode, adr, op, ix, iy); - return num; -} - -static int disass_ed(SFILE *f, uint32 adr) -{ - // Fetch opcode - uint8 op = mon_read_byte(adr); - - // Decode mnemonic and addressing modes - Mnemonic mnem; - AddrMode dst_mode = A_IMPL, src_mode = A_IMPL; - - switch (op) { - case 0x40: - case 0x48: - case 0x50: - case 0x58: - case 0x60: - case 0x68: - case 0x78: - mon_sprintf(f, "in %s,(c)", reg_name[(op >> 3) & 7]); - return 1; - case 0x70: - mon_sprintf(f, "in (c)"); - return 1; - - case 0x41: - case 0x49: - case 0x51: - case 0x59: - case 0x61: - case 0x69: - case 0x79: - mon_sprintf(f, "out (c),%s", reg_name[(op >> 3) & 7]); - return 1; - case 0x71: // undoc - mon_sprintf(f, "out (c),0"); - return 1; - - case 0x42: - case 0x52: - case 0x62: - case 0x72: - mnem = M_SBC; dst_mode = A_HL; src_mode = A_REG3; - break; - - case 0x43: - case 0x53: - case 0x63: - case 0x73: - mnem = M_LD; dst_mode = A_ABS16; src_mode = A_REG3; - break; - - case 0x4a: - case 0x5a: - case 0x6a: - case 0x7a: - mnem = M_ADC; dst_mode = A_HL; src_mode = A_REG3; - break; - - case 0x4b: - case 0x5b: - case 0x6b: - case 0x7b: - mnem = M_LD; dst_mode = A_REG3; src_mode = A_ABS16; - break; - - case 0x44: - case 0x4c: // undoc - case 0x54: // undoc - case 0x5c: // undoc - case 0x64: // undoc - case 0x6c: // undoc - case 0x74: // undoc - case 0x7c: // undoc - mnem = M_NEG; - break; - - case 0x45: - case 0x55: // undoc - case 0x5d: // undoc - case 0x65: // undoc - case 0x6d: // undoc - case 0x75: // undoc - case 0x7d: // undoc - mnem = M_RETN; - break; - case 0x4d: mnem = M_RETI; break; - - case 0x46: - case 0x4e: // undoc - case 0x66: // undoc - case 0x6e: // undoc - mnem = M_IM0; - break; - case 0x56: - case 0x76: // undoc - mnem = M_IM1; - break; - case 0x5e: - case 0x7e: // undoc - mnem = M_IM2; - break; - - case 0x47: - mon_sprintf(f, "ld i,a"); - return 1; - case 0x4f: - mon_sprintf(f, "ld r,a"); - return 1; - case 0x57: - mon_sprintf(f, "ld a,i"); - return 1; - case 0x5f: - mon_sprintf(f, "ld a,r"); - return 1; - - case 0x67: mnem = M_RRD; break; - case 0x6f: mnem = M_RLD; break; - - case 0xa0: mnem = M_LDI; break; - case 0xa1: mnem = M_CPI; break; - case 0xa2: mnem = M_INI; break; - case 0xa3: mnem = M_OUTI; break; - case 0xa8: mnem = M_LDD; break; - case 0xa9: mnem = M_CPD; break; - case 0xaa: mnem = M_IND; break; - case 0xab: mnem = M_OUTD; break; - case 0xb0: mnem = M_LDIR; break; - case 0xb1: mnem = M_CPIR; break; - case 0xb2: mnem = M_INIR; break; - case 0xb3: mnem = M_OTIR; break; - case 0xb8: mnem = M_LDDR; break; - case 0xb9: mnem = M_CPDR; break; - case 0xba: mnem = M_INDR; break; - case 0xbb: mnem = M_OTDR; break; - - default: - mnem = M_NOP; - break; - } - - // Print instruction - return print_instr(f, mnem, dst_mode, src_mode, adr + 1, op, false, false) + 1; -} - -static int disass(SFILE *f, uint32 adr, bool ix, bool iy) -{ - uint8 op = mon_read_byte(adr); - if (op == 0xcb) - return disass_cb(f, adr + 1, ix, iy) + 1; - else - return print_instr(f, mnemonic[op], AddrMode(adr_mode[op] >> 8), AddrMode(adr_mode[op] & 0xff), adr + 1, op, ix, iy) + 1; -} - -int disass_z80(FILE *f, uint32 adr) -{ - int num; - char buf[64]; - SFILE sfile = {buf, buf}; - - switch (mon_read_byte(adr)) { - case 0xdd: // ix prefix - num = disass(&sfile, adr + 1, true, false) + 1; - break; - case 0xed: - num = disass_ed(&sfile, adr + 1) + 1; - break; - case 0xfd: // iy prefix - num = disass(&sfile, adr + 1, false, true) + 1; - break; - default: - num = disass(&sfile, adr, false, false); - break; - } - - for (int i=0; i<4; i++) { - if (num > i) - fprintf(f, "%02x ", mon_read_byte(adr + i)); - else - fprintf(f, " "); - } - - fprintf(f, "\t%s\n", buf); - return num; -} diff --git a/cxmon/src/sysdeps.h b/cxmon/src/sysdeps.h deleted file mode 100644 index 2b40d17c..00000000 --- a/cxmon/src/sysdeps.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * sysdeps.h - System dependent definitions - * - * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SYSDEPS_H -#define SYSDEPS_H - -#ifndef __STDC__ -#error "Your compiler is not ANSI. Get a real one." -#endif - -#include "config.h" - -#ifndef STDC_HEADERS -#error "You don't have ANSI C header files." -#endif - -#ifdef HAVE_UNISTD_H -# include -# include -#endif - -#include -#include -#include - -/* Data types */ - -#ifdef __BEOS__ - -#include - -#else - -typedef unsigned char uint8; -typedef signed char int8; -#if SIZEOF_SHORT == 2 -typedef unsigned short uint16; -typedef short int16; -#elif SIZEOF_INT == 2 -typedef unsigned int uint16; -typedef int int16; -#else -#error "No 2 byte type, you lose." -#endif -#if SIZEOF_INT == 4 -typedef unsigned int uint32; -typedef int int32; -#elif SIZEOF_LONG == 4 -typedef unsigned long uint32; -typedef long int32; -#else -#error "No 4 byte type, you lose." -#endif -#if SIZEOF_LONG == 8 -typedef unsigned long uint64; -typedef long int64; -#define VAL64(a) (a ## l) -#define UVAL64(a) (a ## ul) -#elif SIZEOF_LONG_LONG == 8 -typedef unsigned long long uint64; -typedef long long int64; -#define VAL64(a) (a ## LL) -#define UVAL64(a) (a ## uLL) -#else -#error "No 8 byte type, you lose." -#endif -#if SIZEOF_VOID_P == 4 -typedef uint32 uintptr; -typedef int32 intptr; -#elif SIZEOF_VOID_P == 8 -typedef uint64 uintptr; -typedef int64 intptr; -#else -#error "Unsupported size of pointer" -#endif - -#endif // def __BEOS__ - -#endif From 1bf6e934614af4dedbbc7a2f9af7f92898134c9d Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 15 Apr 2018 17:33:50 -0500 Subject: [PATCH 04/20] Downgraded emulated UAE cpu --- BasiliskII/src/Unix/CMakeLists.txt | 4 +- BasiliskII/src/uae_cpu/basilisk_glue.cpp | 42 +- BasiliskII/src/uae_cpu/build68k.c | 51 +- BasiliskII/src/uae_cpu/cpu_emulation.h | 15 +- BasiliskII/src/uae_cpu/cpuopti.c | 20 +- BasiliskII/src/uae_cpu/fpu/core.h | 259 --- BasiliskII/src/uae_cpu/fpu/exceptions.cpp | 188 -- BasiliskII/src/uae_cpu/fpu/exceptions.h | 149 -- BasiliskII/src/uae_cpu/fpu/flags.cpp | 169 -- BasiliskII/src/uae_cpu/fpu/flags.h | 217 -- BasiliskII/src/uae_cpu/fpu/fpu.h | 49 - BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp | 2369 --------------------- BasiliskII/src/uae_cpu/fpu/fpu_uae.h | 212 -- BasiliskII/src/uae_cpu/fpu/impl.h | 147 -- BasiliskII/src/uae_cpu/fpu/mathlib.cpp | 100 - BasiliskII/src/uae_cpu/fpu/mathlib.h | 1129 ---------- BasiliskII/src/uae_cpu/fpu/rounding.cpp | 64 - BasiliskII/src/uae_cpu/fpu/rounding.h | 154 -- BasiliskII/src/uae_cpu/fpu/types.h | 135 -- BasiliskII/src/uae_cpu/gencpu.c | 681 +++--- BasiliskII/src/uae_cpu/m68k.h | 392 +--- BasiliskII/src/uae_cpu/newcpu.cpp | 391 ++-- BasiliskII/src/uae_cpu/newcpu.h | 246 +-- BasiliskII/src/uae_cpu/noflags.h | 142 -- BasiliskII/src/uae_cpu/readcpu.cpp | 228 +- BasiliskII/src/uae_cpu/readcpu.h | 36 +- BasiliskII/src/uae_cpu/spcflags.h | 103 - BasiliskII/src/uae_cpu/table68k | 372 ++-- 28 files changed, 977 insertions(+), 7087 deletions(-) delete mode 100644 BasiliskII/src/uae_cpu/fpu/core.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/exceptions.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/exceptions.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/flags.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/flags.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_uae.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/impl.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/mathlib.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/mathlib.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/rounding.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/rounding.h delete mode 100644 BasiliskII/src/uae_cpu/fpu/types.h delete mode 100644 BasiliskII/src/uae_cpu/noflags.h delete mode 100644 BasiliskII/src/uae_cpu/spcflags.h diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index 0d3f9b9d..fca7bca0 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -76,7 +76,7 @@ set(BasiliskII_SRCS ../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp - ../uae_cpu/fpu/fpu_uae.cpp + # ../uae_cpu/fpp.cpp cpustbl.cpp cpudefs.cpp cpuemu.cpp @@ -87,7 +87,7 @@ set(BasiliskII_SRCS add_executable(BasiliskII ${BasiliskII_SRCS}) set_source_files_properties(${BasiliskII_SRCS} - PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"") + PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DDATADIR=\\\".\\\"") target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY}) diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index 8dd7d173..9d344816 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -1,7 +1,7 @@ /* * basilisk_glue.cpp - Glue UAE CPU to Basilisk II CPU engine interface * - * Basilisk II (C) 1997-2008 Christian Bauer + * Basilisk II (C) 1997-1999 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +19,8 @@ */ #include "sysdeps.h" - #include "cpu_emulation.h" #include "main.h" -#include "prefs.h" #include "emul_op.h" #include "rom_patches.h" #include "timer.h" @@ -31,26 +29,27 @@ #include "readcpu.h" #include "newcpu.h" - // RAM and ROM pointers -uint32 RAMBaseMac = 0; // RAM base (Mac address space) gb-- initializer is important +uint32 RAMBaseMac; // RAM base (Mac address space) uint8 *RAMBaseHost; // RAM base (host address space) uint32 RAMSize; // Size of RAM uint32 ROMBaseMac; // ROM base (Mac address space) uint8 *ROMBaseHost; // ROM base (host address space) uint32 ROMSize; // Size of ROM +#if !REAL_ADDRESSING // Mac frame buffer uint8 *MacFrameBaseHost; // Frame buffer base (host address space) uint32 MacFrameSize; // Size of frame buffer int MacFrameLayout; // Frame buffer layout +#endif #if DIRECT_ADDRESSING uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equivalent #endif // From newcpu.cpp -extern bool quit_program; +extern int quit_program; /* @@ -59,7 +58,7 @@ extern bool quit_program; bool Init680x0(void) { -#if DIRECT_ADDRESSING +#if REAL_ADDRESSING // Mac address space = host address space minus constant offset (MEMBaseDiff) // NOTE: MEMBaseDiff is set up in main_unix.cpp/main() RAMBaseMac = 0; @@ -67,7 +66,6 @@ bool Init680x0(void) #endif init_m68k(); - return true; } @@ -78,20 +76,9 @@ bool Init680x0(void) void Exit680x0(void) { - - exit_m68k(); } -/* - * Initialize memory mapping of frame buffer (called upon video mode change) - */ - -void InitFrameBufferMapping(void) -{ - -} - /* * Reset and start 680x0 emulation (doesn't return) */ @@ -99,8 +86,7 @@ void InitFrameBufferMapping(void) void Start680x0(void) { m68k_reset(); - - m68k_execute(); + m68k_go(true); } @@ -111,7 +97,7 @@ void Start680x0(void) void TriggerInterrupt(void) { idle_resume(); - SPCFLAGS_SET( SPCFLAG_INT ); + regs.spcflags |= SPCFLAG_INT; } void TriggerNMI(void) @@ -157,8 +143,8 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) // Execute trap m68k_setpc(m68k_areg(regs, 7)); fill_prefetch_0(); - quit_program = false; - m68k_execute(); + quit_program = 0; + m68k_go(true); // Clean up stack m68k_areg(regs, 7) += 4; @@ -172,7 +158,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) r->d[i] = m68k_dreg(regs, i); for (i=0; i<7; i++) r->a[i] = m68k_areg(regs, i); - quit_program = false; + quit_program = 0; } @@ -204,8 +190,8 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) // Execute routine m68k_setpc(addr); fill_prefetch_0(); - quit_program = false; - m68k_execute(); + quit_program = 0; + m68k_go(true); // Clean up stack m68k_areg(regs, 7) += 2; @@ -219,5 +205,5 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) r->d[i] = m68k_dreg(regs, i); for (i=0; i<7; i++) r->a[i] = m68k_areg(regs, i); - quit_program = false; + quit_program = 0; } diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index af5cac92..42a7de8b 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -4,20 +4,6 @@ * Read 68000 CPU specs from file "table68k" and build table68k.c * * Copyright 1995,1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -72,7 +58,15 @@ int main(int argc, char **argv) printf ("#include \"sysdeps.h\"\n"); printf ("#include \"readcpu.h\"\n"); printf ("struct instr_def defs68k[] = {\n"); +#if 0 + tablef = fopen("table68k","r"); + if (tablef == NULL) { + fprintf(stderr, "table68k not found\n"); + exit(1); + } +#else tablef = stdin; +#endif getnextch(); while (nextch != EOF) { int cpulevel, plevel, sduse; @@ -82,7 +76,6 @@ int main(int argc, char **argv) char opcstr[256]; int bitpos[16]; int flagset[5], flaguse[5]; - char cflow; unsigned int bitmask,bitpattern; int n_variable; @@ -114,8 +107,6 @@ int main(int argc, char **argv) case 'r': currbit = bitr; break; case 'R': currbit = bitR; break; case 'z': currbit = bitz; break; - case 'E': currbit = bitE; break; - case 'p': currbit = bitp; break; default: abort(); } if (!(bitmask & 1)) { @@ -164,6 +155,7 @@ int main(int argc, char **argv) getnextch(); switch(nextch){ case '-': flagset[i] = fa_unset; break; + case '/': flagset[i] = fa_isjmp; break; case '0': flagset[i] = fa_zero; break; case '1': flagset[i] = fa_one; break; case 'x': flagset[i] = fa_dontcare; break; @@ -183,31 +175,13 @@ int main(int argc, char **argv) getnextch(); switch(nextch){ case '-': flaguse[i] = fu_unused; break; + case '/': flaguse[i] = fu_isjmp; break; + case '+': flaguse[i] = fu_maybecc; break; case '?': flaguse[i] = fu_unknown; break; default: flaguse[i] = fu_used; break; } } - getnextch(); - while (isspace(nextch)) - getnextch(); - - if (nextch != ':') /* Get control flow information */ - abort(); - - cflow = 0; - for(i = 0; i < 2; i++) { - getnextch(); - switch(nextch){ - case '-': break; - case 'R': cflow |= fl_return; break; - case 'B': cflow |= fl_branch; break; - case 'J': cflow |= fl_jump; break; - case 'T': cflow |= fl_trap; break; - default: abort(); - } - } - getnextch(); while (isspace(nextch)) getnextch(); @@ -259,10 +233,9 @@ int main(int argc, char **argv) for(i = 0; i < 5; i++) { printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ','); } - printf("}, %d, %d, \"%s\"}", cflow, sduse, opstrp); + printf("}, %d, \"%s\"}", sduse, opstrp); } } printf("};\nint n_defs68k = %d;\n", no_insns); - fflush(stdout); return 0; } diff --git a/BasiliskII/src/uae_cpu/cpu_emulation.h b/BasiliskII/src/uae_cpu/cpu_emulation.h index 809959c9..cc1d6e05 100644 --- a/BasiliskII/src/uae_cpu/cpu_emulation.h +++ b/BasiliskII/src/uae_cpu/cpu_emulation.h @@ -1,7 +1,7 @@ /* - * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version) + * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.8 version) * - * Basilisk II (C) 1997-2008 Christian Bauer + * Basilisk II (C) 1997-1999 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,6 @@ #ifndef CPU_EMULATION_H #define CPU_EMULATION_H -#include - /* * Memory system @@ -37,7 +35,15 @@ extern uint32 ROMBaseMac; // ROM base (Mac address space) extern uint8 *ROMBaseHost; // ROM base (host address space) extern uint32 ROMSize; // Size of ROM +#if !REAL_ADDRESSING +// If we are not using real addressing, the Mac frame buffer gets mapped to this location +// The memory must be allocated by VideoInit(). If multiple monitors are used, they must +// share the frame buffer +const uint32 MacFrameBaseMac = 0xa0000000; +extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space) +extern uint32 MacFrameSize; // Size of frame buffer extern int MacFrameLayout; // Frame buffer layout (see defines below) +#endif // Possible frame buffer layouts enum { @@ -72,7 +78,6 @@ static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return me // Initialization extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation extern void Exit680x0(void); -extern void InitFrameBufferMapping(void); // 680x0 emulation functions struct M68kRegisters; diff --git a/BasiliskII/src/uae_cpu/cpuopti.c b/BasiliskII/src/uae_cpu/cpuopti.c index 28ba7c22..2dc10507 100644 --- a/BasiliskII/src/uae_cpu/cpuopti.c +++ b/BasiliskII/src/uae_cpu/cpuopti.c @@ -5,20 +5,6 @@ * Based on work by Tauno Taipaleenmaki * * Copyright 1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -41,7 +27,7 @@ struct func { static void oops(void) { fprintf(stderr, "Don't know how to optimize this file.\n"); - exit(1); + abort(); } static char * match(struct line *l, const char *m) @@ -60,7 +46,7 @@ static int insn_references_reg (struct line *l, char *reg) { if (reg[0] != 'e') { fprintf(stderr, "Unknown register?!?\n"); - exit(1); + abort(); } if (strstr (l->data, reg) != 0) return 1; @@ -135,7 +121,7 @@ static void do_function(struct func *f) l3 = l3->prev; } if (l3 == l2) - exit(1); + abort(); for (l4 = l2; l4 != l3; l4 = l4->prev) { /* The register may not be referenced by any of the insns that we * move the popl past */ diff --git a/BasiliskII/src/uae_cpu/fpu/core.h b/BasiliskII/src/uae_cpu/fpu/core.h deleted file mode 100644 index 66358a2d..00000000 --- a/BasiliskII/src/uae_cpu/fpu/core.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * fpu/core.h - base fpu context definition - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_CORE_H -#define FPU_CORE_H - -#include "sysdeps.h" -#include "fpu/types.h" - -/* Always use x87 FPU stack on IA-32. */ -#if defined(X86_ASSEMBLY) -#define USE_X87_ASSEMBLY 1 -#endif - -/* Only use x87 FPU on x86-64 if long double precision is requested. */ -#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE -#define USE_X87_ASSEMBLY 1 -#endif - -/* ========================================================================== */ -/* ========================= FPU CONTEXT DEFINITION ========================= */ -/* ========================================================================== */ - -/* We don't use all features of the C++ language so that we may still - * easily backport that code to C. - */ - -struct fpu_t { - - /* ---------------------------------------------------------------------- */ - /* --- Floating-Point Data Registers --- */ - /* ---------------------------------------------------------------------- */ - - /* The eight %fp0 .. %fp7 registers */ - fpu_register registers[8]; - - /* Used for lazy evalualation of FPU flags */ - fpu_register result; - - /* ---------------------------------------------------------------------- */ - /* --- Floating-Point Control Register --- */ - /* ---------------------------------------------------------------------- */ - - struct { - - /* Exception Enable Byte */ - uae_u32 exception_enable; - #define FPCR_EXCEPTION_ENABLE 0x0000ff00 - #define FPCR_EXCEPTION_BSUN 0x00008000 - #define FPCR_EXCEPTION_SNAN 0x00004000 - #define FPCR_EXCEPTION_OPERR 0x00002000 - #define FPCR_EXCEPTION_OVFL 0x00001000 - #define FPCR_EXCEPTION_UNFL 0x00000800 - #define FPCR_EXCEPTION_DZ 0x00000400 - #define FPCR_EXCEPTION_INEX2 0x00000200 - #define FPCR_EXCEPTION_INEX1 0x00000100 - - /* Mode Control Byte Mask */ - #define FPCR_MODE_CONTROL 0x000000ff - - /* Rounding precision */ - uae_u32 rounding_precision; - #define FPCR_ROUNDING_PRECISION 0x000000c0 - #define FPCR_PRECISION_SINGLE 0x00000040 - #define FPCR_PRECISION_DOUBLE 0x00000080 - #define FPCR_PRECISION_EXTENDED 0x00000000 - - /* Rounding mode */ - uae_u32 rounding_mode; - #define FPCR_ROUNDING_MODE 0x00000030 - #define FPCR_ROUND_NEAR 0x00000000 - #define FPCR_ROUND_ZERO 0x00000010 - #define FPCR_ROUND_MINF 0x00000020 - #define FPCR_ROUND_PINF 0x00000030 - - } fpcr; - - /* ---------------------------------------------------------------------- */ - /* --- Floating-Point Status Register --- */ - /* ---------------------------------------------------------------------- */ - - struct { - - /* Floating-Point Condition Code Byte */ - uae_u32 condition_codes; - #define FPSR_CCB 0xff000000 - #define FPSR_CCB_NEGATIVE 0x08000000 - #define FPSR_CCB_ZERO 0x04000000 - #define FPSR_CCB_INFINITY 0x02000000 - #define FPSR_CCB_NAN 0x01000000 - - /* Quotient Byte */ - uae_u32 quotient; - #define FPSR_QUOTIENT 0x00ff0000 - #define FPSR_QUOTIENT_SIGN 0x00800000 - #define FPSR_QUOTIENT_VALUE 0x007f0000 - - /* Exception Status Byte */ - uae_u32 exception_status; - #define FPSR_EXCEPTION_STATUS FPCR_EXCEPTION_ENABLE - #define FPSR_EXCEPTION_BSUN FPCR_EXCEPTION_BSUN - #define FPSR_EXCEPTION_SNAN FPCR_EXCEPTION_SNAN - #define FPSR_EXCEPTION_OPERR FPCR_EXCEPTION_OPERR - #define FPSR_EXCEPTION_OVFL FPCR_EXCEPTION_OVFL - #define FPSR_EXCEPTION_UNFL FPCR_EXCEPTION_UNFL - #define FPSR_EXCEPTION_DZ FPCR_EXCEPTION_DZ - #define FPSR_EXCEPTION_INEX2 FPCR_EXCEPTION_INEX2 - #define FPSR_EXCEPTION_INEX1 FPCR_EXCEPTION_INEX1 - - /* Accrued Exception Byte */ - uae_u32 accrued_exception; - #define FPSR_ACCRUED_EXCEPTION 0x000000ff - #define FPSR_ACCR_IOP 0x00000080 - #define FPSR_ACCR_OVFL 0x00000040 - #define FPSR_ACCR_UNFL 0x00000020 - #define FPSR_ACCR_DZ 0x00000010 - #define FPSR_ACCR_INEX 0x00000008 - - } fpsr; - - /* ---------------------------------------------------------------------- */ - /* --- Floating-Point Instruction Address Register --- */ - /* ---------------------------------------------------------------------- */ - - uae_u32 instruction_address; - - /* ---------------------------------------------------------------------- */ - /* --- Initialization / Finalization --- */ - /* ---------------------------------------------------------------------- */ - - /* Flag set if we emulate an integral 68040 FPU */ - bool is_integral; - - /* ---------------------------------------------------------------------- */ - /* --- Extra FPE-dependant defines --- */ - /* ---------------------------------------------------------------------- */ - - #if defined(FPU_X86) \ - || (defined(FPU_UAE) && defined(USE_X87_ASSEMBLY)) \ - || (defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)) - - #define CW_RESET 0x0040 // initial CW value after RESET - #define CW_FINIT 0x037F // initial CW value after FINIT - #define SW_RESET 0x0000 // initial SW value after RESET - #define SW_FINIT 0x0000 // initial SW value after FINIT - #define TW_RESET 0x5555 // initial TW value after RESET - #define TW_FINIT 0x0FFF // initial TW value after FINIT - - #define CW_X 0x1000 // infinity control - #define CW_RC_ZERO 0x0C00 // rounding control toward zero - #define CW_RC_UP 0x0800 // rounding control toward + - #define CW_RC_DOWN 0x0400 // rounding control toward - - #define CW_RC_NEAR 0x0000 // rounding control toward even - #define CW_PC_EXTENDED 0x0300 // precision control 64bit - #define CW_PC_DOUBLE 0x0200 // precision control 53bit - #define CW_PC_RESERVED 0x0100 // precision control reserved - #define CW_PC_SINGLE 0x0000 // precision control 24bit - #define CW_PM 0x0020 // precision exception mask - #define CW_UM 0x0010 // underflow exception mask - #define CW_OM 0x0008 // overflow exception mask - #define CW_ZM 0x0004 // zero divide exception mask - #define CW_DM 0x0002 // denormalized operand exception mask - #define CW_IM 0x0001 // invalid operation exception mask - - #define SW_B 0x8000 // busy flag - #define SW_C3 0x4000 // condition code flag 3 - #define SW_TOP_7 0x3800 // top of stack = ST(7) - #define SW_TOP_6 0x3000 // top of stack = ST(6) - #define SW_TOP_5 0x2800 // top of stack = ST(5) - #define SW_TOP_4 0x2000 // top of stack = ST(4) - #define SW_TOP_3 0x1800 // top of stack = ST(3) - #define SW_TOP_2 0x1000 // top of stack = ST(2) - #define SW_TOP_1 0x0800 // top of stack = ST(1) - #define SW_TOP_0 0x0000 // top of stack = ST(0) - #define SW_C2 0x0400 // condition code flag 2 - #define SW_C1 0x0200 // condition code flag 1 - #define SW_C0 0x0100 // condition code flag 0 - #define SW_ES 0x0080 // error summary status flag - #define SW_SF 0x0040 // stack fault flag - #define SW_PE 0x0020 // precision exception flag - #define SW_UE 0x0010 // underflow exception flag - #define SW_OE 0x0008 // overflow exception flag - #define SW_ZE 0x0004 // zero divide exception flag - #define SW_DE 0x0002 // denormalized operand exception flag - #define SW_IE 0x0001 // invalid operation exception flag - - #define X86_ROUNDING_MODE 0x0C00 - #define X86_ROUNDING_PRECISION 0x0300 - - #endif /* FPU_X86 */ - -}; - -/* We handle only one global fpu */ -extern fpu_t fpu; - -/* Return the address of a particular register */ -inline fpu_register * const fpu_register_address(int i) - { return &fpu.registers[i]; } - -/* Dump functions for m68k_dumpstate */ -extern void fpu_dump_registers(void); -extern void fpu_dump_flags(void); - -/* Accessors to FPU Control Register */ -static inline uae_u32 get_fpcr(void); -static inline void set_fpcr(uae_u32 new_fpcr); - -/* Accessors to FPU Status Register */ -static inline uae_u32 get_fpsr(void); -static inline void set_fpsr(uae_u32 new_fpsr); - -/* Accessors to FPU Instruction Address Register */ -static inline uae_u32 get_fpiar(); -static inline void set_fpiar(uae_u32 new_fpiar); - -/* Initialization / Finalization */ -extern void fpu_init(bool integral_68040); -extern void fpu_exit(void); -extern void fpu_reset(void); - -/* Floating-point arithmetic instructions */ -void fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) REGPARAM; - -/* Floating-point program control operations */ -void fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) REGPARAM; -void fpuop_dbcc(uae_u32 opcode, uae_u32 extra) REGPARAM; -void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM; - -/* Floating-point system control operations */ -void fpuop_save(uae_u32 opcode) REGPARAM; -void fpuop_restore(uae_u32 opcode) REGPARAM; -void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM; - -#endif /* FPU_CORE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp deleted file mode 100644 index 6aa6431a..00000000 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * fpu/exceptions.cpp - system-dependant FPU exceptions management - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#undef PRIVATE -#define PRIVATE /**/ - -#undef PUBLIC -#define PUBLIC /**/ - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* -------------------------------------------------------------------------- */ -/* --- Native X86 exceptions --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_X86_EXCEPTIONS -void FFPU fpu_init_native_exceptions(void) -{ - // Mapping for "sw" -> fpsr exception byte - for (uae_u32 i = 0; i < 0x80; i++) { - exception_host2mac[i] = 0; - - if(i & SW_FAKE_BSUN) { - exception_host2mac[i] |= FPSR_EXCEPTION_BSUN; - } - // precision exception - if(i & SW_PE) { - exception_host2mac[i] |= FPSR_EXCEPTION_INEX2; - } - // underflow exception - if(i & SW_UE) { - exception_host2mac[i] |= FPSR_EXCEPTION_UNFL; - } - // overflow exception - if(i & SW_OE) { - exception_host2mac[i] |= FPSR_EXCEPTION_OVFL; - } - // zero divide exception - if(i & SW_ZE) { - exception_host2mac[i] |= FPSR_EXCEPTION_DZ; - } - // denormalized operand exception. - // wrong, but should not get here, normalization is done in elsewhere - if(i & SW_DE) { - exception_host2mac[i] |= FPSR_EXCEPTION_SNAN; - } - // invalid operation exception - if(i & SW_IE) { - exception_host2mac[i] |= FPSR_EXCEPTION_OPERR; - } - } - - // Mapping for fpsr exception byte -> "sw" - for (uae_u32 i = 0; i < 0x100; i++) { - uae_u32 fpsr = (i << 8); - exception_mac2host[i] = 0; - - // BSUN; make sure that you don't generate FPU stack faults. - if(fpsr & FPSR_EXCEPTION_BSUN) { - exception_mac2host[i] |= SW_FAKE_BSUN; - } - // precision exception - if(fpsr & FPSR_EXCEPTION_INEX2) { - exception_mac2host[i] |= SW_PE; - } - // underflow exception - if(fpsr & FPSR_EXCEPTION_UNFL) { - exception_mac2host[i] |= SW_UE; - } - // overflow exception - if(fpsr & FPSR_EXCEPTION_OVFL) { - exception_mac2host[i] |= SW_OE; - } - // zero divide exception - if(fpsr & FPSR_EXCEPTION_DZ) { - exception_mac2host[i] |= SW_ZE; - } - // denormalized operand exception - if(fpsr & FPSR_EXCEPTION_SNAN) { - exception_mac2host[i] |= SW_DE; //Wrong - } - // invalid operation exception - if(fpsr & FPSR_EXCEPTION_OPERR) { - exception_mac2host[i] |= SW_IE; - } - } -} -#endif - -#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS -void FFPU fpu_init_native_accrued_exceptions(void) -{ - /* - 68881/68040 accrued exceptions accumulate as follows: - Accrued.IOP |= (Exception.SNAN | Exception.OPERR) - Accrued.OVFL |= (Exception.OVFL) - Accrued.UNFL |= (Exception.UNFL | Exception.INEX2) - Accrued.DZ |= (Exception.DZ) - Accrued.INEX |= (Exception.INEX1 | Exception.INEX2 | Exception.OVFL) - */ - - // Mapping for "fpsr.accrued_exception" -> fpsr accrued exception byte - for (uae_u32 i = 0; i < 0x40; i++ ) { - accrued_exception_host2mac[i] = 0; - - // precision exception - if(i & SW_PE) { - accrued_exception_host2mac[i] |= FPSR_ACCR_INEX; - } - // underflow exception - if(i & SW_UE) { - accrued_exception_host2mac[i] |= FPSR_ACCR_UNFL; - } - // overflow exception - if(i & SW_OE) { - accrued_exception_host2mac[i] |= FPSR_ACCR_OVFL; - } - // zero divide exception - if(i & SW_ZE) { - accrued_exception_host2mac[i] |= FPSR_ACCR_DZ; - } - // denormalized operand exception - if(i & SW_DE) { - accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; //?????? - } - // invalid operation exception - if(i & SW_IE) { - accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; - } - } - - // Mapping for fpsr accrued exception byte -> "fpsr.accrued_exception" - for (uae_u32 i = 0; i < 0x20; i++) { - int fpsr = (i << 3); - accrued_exception_mac2host[i] = 0; - - // precision exception - if(fpsr & FPSR_ACCR_INEX) { - accrued_exception_mac2host[i] |= SW_PE; - } - // underflow exception - if(fpsr & FPSR_ACCR_UNFL) { - accrued_exception_mac2host[i] |= SW_UE; - } - // overflow exception - if(fpsr & FPSR_ACCR_OVFL) { - accrued_exception_mac2host[i] |= SW_OE; - } - // zero divide exception - if(fpsr & FPSR_ACCR_DZ) { - accrued_exception_mac2host[i] |= SW_ZE; - } - // What about SW_DE; //?????? - // invalid operation exception - if(fpsr & FPSR_ACCR_IOP) { - accrued_exception_mac2host[i] |= SW_IE; - } - } -} -#endif diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.h b/BasiliskII/src/uae_cpu/fpu/exceptions.h deleted file mode 100644 index 8c69a69d..00000000 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * fpu/exceptions.h - system-dependant FPU exceptions management - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_EXCEPTIONS_H -#define FPU_EXCEPTIONS_H - -/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* Defaults to generic exceptions */ -#define FPU_USE_GENERIC_EXCEPTIONS -#define FPU_USE_GENERIC_ACCRUED_EXCEPTIONS - -/* -------------------------------------------------------------------------- */ -/* --- Selection of floating-point exceptions handling mode --- */ -/* -------------------------------------------------------------------------- */ - -/* Optimized i386 fpu core must use native exceptions */ -#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_EXCEPTIONS -# define FPU_USE_X86_EXCEPTIONS -#endif - -/* Optimized i386 fpu core must use native accrued exceptions */ -#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS -# define FPU_USE_X86_ACCRUED_EXCEPTIONS -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Native X86 Exceptions --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_X86_EXCEPTIONS - -/* Extend the SW_* codes */ -#define SW_FAKE_BSUN SW_SF - -/* Shorthand */ -#define SW_EXCEPTION_MASK (SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) -// #define SW_EXCEPTION_MASK (SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) - -/* Lookup tables */ -PRIVATE uae_u32 exception_host2mac[ 0x80 ]; -PRIVATE uae_u32 exception_mac2host[ 0x100 ]; - -/* Initialize native exception management */ -PUBLIC void FFPU fpu_init_native_exceptions(void); - -/* Return m68k floating-point exception status */ -PRIVATE inline uae_u32 FFPU get_exception_status(void) - { return exception_host2mac[FPU fpsr.exception_status & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; } - -/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */ -PRIVATE inline void FFPU set_exception_status(uae_u32 new_status) - { FPU fpsr.exception_status = exception_mac2host[new_status >> 8]; } - -#endif /* FPU_USE_X86_EXCEPTIONS */ - -#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS - -/* Lookup tables */ -PRIVATE uae_u32 accrued_exception_host2mac[ 0x40 ]; -PRIVATE uae_u32 accrued_exception_mac2host[ 0x20 ]; - -/* Initialize native accrued exception management */ -PUBLIC void FFPU fpu_init_native_accrued_exceptions(void); - -/* Return m68k accrued exception byte */ -PRIVATE inline uae_u32 FFPU get_accrued_exception(void) - { return accrued_exception_host2mac[FPU fpsr.accrued_exception & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; } - -/* Set new accrued exception byte */ -PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status) - { FPU fpsr.accrued_exception = accrued_exception_mac2host[(new_status & 0xF8) >> 3]; } - -#endif /* FPU_USE_X86_ACCRUED_EXCEPTIONS */ - -/* -------------------------------------------------------------------------- */ -/* --- Default Exceptions Handling --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_GENERIC_EXCEPTIONS - -/* Initialize native exception management */ -static inline void FFPU fpu_init_native_exceptions(void) - { } - -/* Return m68k floating-point exception status */ -PRIVATE inline uae_u32 FFPU get_exception_status(void) - { return FPU fpsr.exception_status; } - -/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */ -PRIVATE inline void FFPU set_exception_status(uae_u32 new_status) - { FPU fpsr.exception_status = new_status; } - -#endif /* FPU_USE_GENERIC_EXCEPTIONS */ - -#ifdef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS - -/* Initialize native accrued exception management */ -PRIVATE inline void FFPU fpu_init_native_accrued_exceptions(void) - { } - -/* Return m68k accrued exception byte */ -PRIVATE inline uae_u32 FFPU get_accrued_exception(void) - { return FPU fpsr.accrued_exception; } - -/* Set new accrued exception byte */ -PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status) - { FPU fpsr.accrued_exception = new_status; } - -#endif /* FPU_USE_GENERIC_ACCRUED_EXCEPTIONS */ - -#endif /* FPU_EXCEPTIONS_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/flags.cpp b/BasiliskII/src/uae_cpu/fpu/flags.cpp deleted file mode 100644 index 2eabef85..00000000 --- a/BasiliskII/src/uae_cpu/fpu/flags.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * fpu/flags.cpp - Floating-point flags - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ -#undef PRIVATE -#define PRIVATE /**/ - -#undef PUBLIC -#define PUBLIC /**/ - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* -------------------------------------------------------------------------- */ -/* --- Native X86 floating-point flags --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_X86_FLAGS - -/* Initialization */ -void FFPU fpu_init_native_fflags(void) -{ - // Adapted from fpu_x86.cpp - #define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3) - #define SW_Z (SW_C3) - #define SW_I (SW_C0|SW_C2) - #define SW_NAN (SW_C0) - #define SW_FINITE (SW_C2) - #define SW_EMPTY_REGISTER (SW_C0|SW_C3) - #define SW_DENORMAL (SW_C2|SW_C3) - #define SW_UNSUPPORTED (0) - #define SW_N (SW_C1) - - // Sanity checks - #if (SW_Z != NATIVE_FFLAG_ZERO) - #error "Incorrect X86 Z fflag" - #endif - #if (SW_I != NATIVE_FFLAG_INFINITY) - #error "Incorrect X86 I fflag" - #endif - #if (SW_N != NATIVE_FFLAG_NEGATIVE) - #error "Incorrect X86 N fflag" - #endif - #if (SW_NAN != NATIVE_FFLAG_NAN) - #error "Incorrect X86 NAN fflag" - #endif - - // Native status word to m68k mappings - for (uae_u32 i = 0; i < 0x48; i++) { - to_m68k_fpcond[i] = 0; - const uae_u32 native_fpcond = i << 8; - switch (native_fpcond & SW_Z_I_NAN_MASK) { -#ifndef FPU_UAE -// gb-- enabling it would lead to incorrect drawing of digits -// in Speedometer Performance Test - case SW_UNSUPPORTED: -#endif - case SW_NAN: - case SW_EMPTY_REGISTER: - to_m68k_fpcond[i] |= FPSR_CCB_NAN; - break; - case SW_FINITE: - case SW_DENORMAL: - break; - case SW_I: - to_m68k_fpcond[i] |= FPSR_CCB_INFINITY; - break; - case SW_Z: - to_m68k_fpcond[i] |= FPSR_CCB_ZERO; - break; - } - if (native_fpcond & SW_N) - to_m68k_fpcond[i] |= FPSR_CCB_NEGATIVE; - } - - // m68k to native status word mappings - for (uae_u32 i = 0; i < 0x10; i++) { - const uae_u32 m68k_fpcond = i << 24; - if (m68k_fpcond & FPSR_CCB_NAN) - to_host_fpcond[i] = SW_NAN; - else if (m68k_fpcond & FPSR_CCB_ZERO) - to_host_fpcond[i] = SW_Z; - else if (m68k_fpcond & FPSR_CCB_INFINITY) - to_host_fpcond[i] = SW_I; - else - to_host_fpcond[i] = SW_FINITE; - if (m68k_fpcond & FPSR_CCB_NEGATIVE) - to_host_fpcond[i] |= SW_N; - } - - // truth-table for FPU conditions - for (uae_u32 host_fpcond = 0; host_fpcond < 0x08; host_fpcond++) { - // host_fpcond: C3 on bit 2, C1 and C0 are respectively on bits 1 and 0 - const uae_u32 real_host_fpcond = ((host_fpcond & 4) << 12) | ((host_fpcond & 3) << 8); - const bool N = ((real_host_fpcond & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE); - const bool Z = ((real_host_fpcond & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO); - const bool NaN = ((real_host_fpcond & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN); - - int value; - for (uae_u32 m68k_fpcond = 0; m68k_fpcond < 0x20; m68k_fpcond++) { - switch (m68k_fpcond) { - case 0x00: value = 0; break; // False - case 0x01: value = Z; break; // Equal - case 0x02: value = !(NaN || Z || N); break; // Ordered Greater Than - case 0x03: value = Z || !(NaN || N); break; // Ordered Greater Than or Equal - case 0x04: value = N && !(NaN || Z); break; // Ordered Less Than - case 0x05: value = Z || (N && !NaN); break; // Ordered Less Than or Equal - case 0x06: value = !(NaN || Z); break; // Ordered Greater or Less Than - case 0x07: value = !NaN; break; // Ordered - case 0x08: value = NaN; break; // Unordered - case 0x09: value = NaN || Z; break; // Unordered or Equal - case 0x0a: value = NaN || !(N || Z); break; // Unordered or Greater Than - case 0x0b: value = NaN || Z || !N; break; // Unordered or Greater or Equal - case 0x0c: value = NaN || (N && !Z); break; // Unordered or Less Than - case 0x0d: value = NaN || Z || N; break; // Unordered or Less or Equal - case 0x0e: value = !Z; break; // Not Equal - case 0x0f: value = 1; break; // True - case 0x10: value = 0; break; // Signaling False - case 0x11: value = Z; break; // Signaling Equal - case 0x12: value = !(NaN || Z || N); break; // Greater Than - case 0x13: value = Z || !(NaN || N); break; // Greater Than or Equal - case 0x14: value = N && !(NaN || Z); break; // Less Than - case 0x15: value = Z || (N && !NaN); break; // Less Than or Equal - case 0x16: value = !(NaN || Z); break; // Greater or Less Than - case 0x17: value = !NaN; break; // Greater, Less or Equal - case 0x18: value = NaN; break; // Not Greater, Less or Equal - case 0x19: value = NaN || Z; break; // Not Greater or Less Than - case 0x1a: value = NaN || !(N || Z); break; // Not Less Than or Equal - case 0x1b: value = NaN || Z || !N; break; // Not Less Than - case 0x1c: value = NaN || (N && !Z); break; // Not Greater Than or Equal -// case 0x1c: value = !Z && (NaN || N); break; // Not Greater Than or Equal - case 0x1d: value = NaN || Z || N; break; // Not Greater Than - case 0x1e: value = !Z; break; // Signaling Not Equal - case 0x1f: value = 1; break; // Signaling True - default: value = -1; - } - fpcond_truth_table[m68k_fpcond][host_fpcond] = value; - } - } -} - -#endif diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h deleted file mode 100644 index 5983e15e..00000000 --- a/BasiliskII/src/uae_cpu/fpu/flags.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * fpu/flags.h - Floating-point flags - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_FLAGS_H -#define FPU_FLAGS_H - -/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* Defaults to generic flags */ -#define FPU_USE_GENERIC_FLAGS - -/* -------------------------------------------------------------------------- */ -/* --- Selection of floating-point flags handling mode --- */ -/* -------------------------------------------------------------------------- */ - -/* Optimized i386 fpu core must use native flags */ -#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_FLAGS -# define FPU_USE_X86_FLAGS -#endif - -/* Old UAE FPU core can use native flags */ -#if defined(FPU_UAE) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_FLAGS -# define FPU_USE_X86_FLAGS -#endif - -/* IEEE-based implementation must use lazy flag evaluation */ -#if defined(FPU_IEEE) -# undef FPU_USE_GENERIC_FLAGS -# define FPU_USE_LAZY_FLAGS -#endif - -#ifdef FPU_IMPLEMENTATION - -/* -------------------------------------------------------------------------- */ -/* --- Native X86 Floating-Point Flags --- */ -/* -------------------------------------------------------------------------- */ - -/* FPU_X86 has its own set of lookup functions */ - -#ifdef FPU_USE_X86_FLAGS - -#define FPU_USE_NATIVE_FLAGS - -#define NATIVE_FFLAG_NEGATIVE 0x0200 -#define NATIVE_FFLAG_ZERO 0x4000 -#define NATIVE_FFLAG_INFINITY 0x0500 -#define NATIVE_FFLAG_NAN 0x0100 - -/* Translation tables between native and m68k floating-point flags */ -PRIVATE uae_u32 to_m68k_fpcond[0x48]; -PRIVATE uae_u32 to_host_fpcond[0x10]; - -/* Truth table for floating-point condition codes */ -PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes - -/* Initialization */ -PUBLIC void FFPU fpu_init_native_fflags(void); - -#ifdef FPU_UAE - -/* Native to m68k floating-point condition codes */ -PRIVATE inline uae_u32 FFPU get_fpccr(void) - { return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; } - -/* M68k to native floating-point condition codes */ -PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) - /* Precondition: new_fpcond is only valid for floating-point condition codes */ - { FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; } - -/* Make FPSR according to the value passed in argument */ -PRIVATE inline void FFPU make_fpsr(fpu_register const & r) - { uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } - -/* Return the corresponding ID of the current floating-point condition codes */ -/* NOTE: only valid for evaluation of a condition */ -PRIVATE inline int FFPU host_fpcond_id(void) - { return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); } - -/* Return true if the floating-point condition is satisfied */ -PRIVATE inline bool FFPU fpcctrue(int condition) - { return fpcond_truth_table[condition][host_fpcond_id()]; } - -#endif /* FPU_UAE */ - -/* Return the address of the floating-point condition codes truth table */ -static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void) - { return ((uae_u8*)&fpcond_truth_table[0][0]); } - -#endif /* FPU_X86_USE_NATIVE_FLAGS */ - -/* -------------------------------------------------------------------------- */ -/* --- Use Original M68K FPU Mappings --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_GENERIC_FLAGS - -#undef FPU_USE_NATIVE_FLAGS - -#define NATIVE_FFLAG_NEGATIVE 0x08000000 -#define NATIVE_FFLAG_ZERO 0x04000000 -#define NATIVE_FFLAG_INFINITY 0x02000000 -#define NATIVE_FFLAG_NAN 0x01000000 - -/* Initialization - NONE */ -PRIVATE inline void FFPU fpu_init_native_fflags(void) - { } - -/* Native to m68k floating-point condition codes - SELF */ -PRIVATE inline uae_u32 FFPU get_fpccr(void) - { return FPU fpsr.condition_codes; } - -/* M68k to native floating-point condition codes - SELF */ -PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) - { FPU fpsr.condition_codes = new_fpcond; } - -#endif /* FPU_USE_GENERIC_FLAGS */ - -/* -------------------------------------------------------------------------- */ -/* --- Use Lazy Flags Evaluation --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_LAZY_FLAGS - -#undef FPU_USE_NATIVE_FLAGS - -#define NATIVE_FFLAG_NEGATIVE 0x08000000 -#define NATIVE_FFLAG_ZERO 0x04000000 -#define NATIVE_FFLAG_INFINITY 0x02000000 -#define NATIVE_FFLAG_NAN 0x01000000 - -/* Initialization - NONE */ -PRIVATE inline void FFPU fpu_init_native_fflags(void) - { } - -/* Native to m68k floating-point condition codes - SELF */ -PRIVATE inline uae_u32 FFPU get_fpccr(void) -{ - uae_u32 fpccr = 0; - if (isnan(FPU result)) - fpccr |= FPSR_CCB_NAN; - else if (FPU result == 0.0) - fpccr |= FPSR_CCB_ZERO; - else if (FPU result < 0.0) - fpccr |= FPSR_CCB_NEGATIVE; - if (isinf(FPU result)) - fpccr |= FPSR_CCB_INFINITY; - return fpccr; -} - -/* M68k to native floating-point condition codes - SELF */ -PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) -{ - if (new_fpcond & FPSR_CCB_NAN) - make_nan(FPU result); - else if (new_fpcond & FPSR_CCB_ZERO) - FPU result = 0.0; - else if (new_fpcond & FPSR_CCB_NEGATIVE) - FPU result = -1.0; - else - FPU result = +1.0; - /* gb-- where is Infinity ? */ -} - -/* Make FPSR according to the value passed in argument */ -PRIVATE inline void FFPU make_fpsr(fpu_register const & r) - { FPU result = r; } - -#endif /* FPU_USE_LAZY_FLAGS */ - -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Common methods --- */ -/* -------------------------------------------------------------------------- */ - -/* Return the address of the floating-point condition codes register */ -static inline uae_u32 * const FFPU address_of_fpccr(void) - { return ((uae_u32 *)& FPU fpsr.condition_codes); } - -#endif /* FPU_FLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu.h b/BasiliskII/src/uae_cpu/fpu/fpu.h deleted file mode 100644 index 3940a75b..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * fpu/fpu.h - public header - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_PUBLIC_HEADER_H -#define FPU_PUBLIC_HEADER_H - -#ifndef FPU_DEBUG -#define FPU_DEBUG 0 -#endif - -#if FPU_DEBUG -#define fpu_debug(args) printf args; -#define FPU_DUMP_REGISTERS 0 -#define FPU_DUMP_FIRST_BYTES 0 -#else -#define fpu_debug(args) ; -#undef FPU_DUMP_REGISTERS -#undef FPU_DUMP_FIRST_BYTES -#endif - -#include "sysdeps.h" -#include "fpu/types.h" -#include "fpu/core.h" - -#endif /* FPU_PUBLIC_HEADER_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp deleted file mode 100644 index ffc784a5..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp +++ /dev/null @@ -1,2369 +0,0 @@ -/* - * fpu/fpu_uae.cpp - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Following fixes by Lauri Pesonen, July 1999: - * - * FMOVEM list handling: - * The lookup tables did not work correctly, rewritten. - * FINT: - * (int) cast does not work, fixed. - * Further, now honors the FPU fpcr rounding modes. - * FINTRZ: - * (int) cast cannot be used, fixed. - * FGETEXP: - * Input argument value 0 returned erroneous value. - * FMOD: - * (int) cast cannot be used. Replaced by proper rounding. - * Quotient byte handling was missing. - * FREM: - * (int) cast cannot be used. Replaced by proper rounding. - * Quotient byte handling was missing. - * FSCALE: - * Input argument value 0 was not handled correctly. - * FMOVEM Control Registers to/from address FPU registers An: - * A bug caused the code never been called. - * FMOVEM Control Registers pre-decrement: - * Moving of control regs from memory to FPP was not handled properly, - * if not all of the three FPU registers were moved. - * Condition code "Not Greater Than or Equal": - * Returned erroneous value. - * FSINCOS: - * Cosine must be loaded first if same register. - * FMOVECR: - * Status register was not updated (yes, this affects it). - * FMOVE -> reg: - * Status register was not updated (yes, this affects it). - * FMOVE reg -> reg: - * Status register was not updated. - * FDBcc: - * The loop termination condition was wrong. - * Possible leak from int16 to int32 fixed. - * get_fp_value: - * Immediate addressing mode && Operation Length == Byte -> - * Use the low-order byte of the extension word. - * Now FPU fpcr high 16 bits are always read as zeroes, no matter what was - * written to them. - * - * Other: - * - Optimized single/double/extended to/from conversion functions. - * Huge speed boost, but not (necessarily) portable to other systems. - * Enabled/disabled by #define FPU_HAVE_IEEE_DOUBLE 1 - * - Optimized versions of FSCALE, FGETEXP, FGETMAN - * - Conversion routines now handle NaN and infinity better. - * - Some constants precalculated. Not all compilers can optimize the - * expressions previously used. - * - * TODO: - * - Floating point exceptions. - * - More Infinity/NaN/overflow/underflow checking. - * - FPU instruction_address (only needed when exceptions are implemented) - * - Should be written in assembly to support long doubles. - * - Precision rounding single/double - */ - -#include "sysdeps.h" -#include -#include -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#include "main.h" -#define FPU_IMPLEMENTATION -#include "fpu/fpu.h" -#include "fpu/fpu_uae.h" - -/* Global FPU context */ -fpu_t fpu; - -/* -------------------------------------------------------------------------- */ -/* --- Native Support --- */ -/* -------------------------------------------------------------------------- */ - -#include "fpu/flags.h" -#include "fpu/exceptions.h" -#include "fpu/rounding.h" -#include "fpu/impl.h" - -#include "fpu/flags.cpp" -#include "fpu/exceptions.cpp" - -/* -------------------------------------------------------------------------- */ -/* --- Scopes Definition --- */ -/* -------------------------------------------------------------------------- */ - -#undef PUBLIC -#define PUBLIC /**/ - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* -------------------------------------------------------------------------- */ -/* --- Debugging --- */ -/* -------------------------------------------------------------------------- */ - -PUBLIC void FFPU fpu_dump_registers(void) -{ - for (int i = 0; i < 8; i++){ - printf ("FP%d: %g ", i, fpu_get_register(i)); - if ((i & 3) == 3) - printf ("\n"); - } -} - -PUBLIC void FFPU fpu_dump_flags(void) -{ - printf ("N=%d Z=%d I=%d NAN=%d\n", - (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, - (get_fpsr() & FPSR_CCB_ZERO)!= 0, - (get_fpsr() & FPSR_CCB_INFINITY) != 0, - (get_fpsr() & FPSR_CCB_NAN) != 0); -} - -/* single : S 8*E 23*F */ -/* double : S 11*E 52*F */ -/* extended : S 15*E 64*F */ -/* E = 0 & F = 0 -> 0 */ -/* E = MAX & F = 0 -> Infin */ -/* E = MAX & F # 0 -> NotANumber */ -/* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */ - -#if FPU_DEBUG - -PUBLIC void FFPU dump_registers(const char * str) -{ - char temp_str[512]; - - sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", - str, - get_register(0), get_register(1), get_register(2), get_register(3), - get_register(4), get_register(5), get_register(6), get_register(7) ); - - fpu_debug((temp_str)); -} - -PUBLIC void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) -{ - char temp_buf1[256], temp_buf2[10]; - int bytes = sizeof(temp_buf1)/3-1-3; - if (actual < bytes) - bytes = actual; - - temp_buf1[0] = 0; - for (int i = 0; i < bytes; i++) { - sprintf(temp_buf2, "%02x ", (uae_u32)buffer[i]); - strcat(temp_buf1, temp_buf2); - } - - strcat(temp_buf1, "\n"); - fpu_debug((temp_buf1)); -} - -#else - -PUBLIC void FFPU dump_registers(const char *) -{ -} - -PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32) -{ -} - -#endif - -PRIVATE inline fpu_register FFPU round_to_zero(fpu_register const & x) -{ - return (x < 0.0 ? ceil(x) : floor(x)); -} - -PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x) -{ - return floor(x + 0.5); -} - -#if FPU_HAVE_IEEE_DOUBLE - -#ifndef HAVE_ISNAN -#define isnan(x) do_isnan((x)) -#endif - -PRIVATE inline bool FFPU do_isnan(fpu_register const & r) -{ - uae_u32 * p = (uae_u32 *)&r; - if ((p[FHI] & 0x7FF00000) == 0x7FF00000) { - // logical or is faster here. - if ((p[FHI] & 0x000FFFFF) || p[FLO]) { - return true; - } - } - return false; -} - -#ifndef HAVE_ISINF -#define isinf(x) do_isinf((x)) -#endif - -PRIVATE inline bool FFPU do_isinf(fpu_register const & r) -{ - uae_u32 * p = (uae_u32 *)&r; - if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) { - return true; - } - return false; -} - -#ifndef HAVE_ISNEG -#define isneg(x) do_isneg((x)) -#endif - -PRIVATE inline bool FFPU do_isneg(fpu_register const & r) -{ - uae_u32 * p = (uae_u32 *)&r; - return ((p[FHI] & 0x80000000) != 0); -} - -#ifndef HAVE_ISZERO -#define iszero(x) do_iszero((x)) -#endif - -PRIVATE inline bool FFPU do_iszero(fpu_register const & r) -{ - uae_u32 * p = (uae_u32 *)&r; - return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0); -} - -// May be optimized for particular processors -#ifndef FPU_USE_NATIVE_FLAGS -PRIVATE inline void FFPU make_fpsr(fpu_register const & r) -{ - FPU fpsr.condition_codes - = (iszero(r) ? NATIVE_FFLAG_ZERO : 0) - | (isneg(r) ? NATIVE_FFLAG_NEGATIVE : 0) - | (isnan(r) ? NATIVE_FFLAG_NAN : 0) - | (isinf(r) ? NATIVE_FFLAG_INFINITY : 0) - ; -} -#endif - -PRIVATE inline void FFPU get_dest_flags(fpu_register const & r) -{ - fl_dest.negative = isneg(r); - fl_dest.zero = iszero(r); - fl_dest.infinity = isinf(r); - fl_dest.nan = isnan(r); - fl_dest.in_range = !fl_dest.zero && !fl_dest.infinity && !fl_dest.nan; -} - -PRIVATE inline void FFPU get_source_flags(fpu_register const & r) -{ - fl_source.negative = isneg(r); - fl_source.zero = iszero(r); - fl_source.infinity = isinf(r); - fl_source.nan = isnan(r); - fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan; -} - -PRIVATE inline void FFPU make_nan(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0xffffffff; - p[FHI] = 0x7fffffff; -} - -PRIVATE inline void FFPU make_zero_positive(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = p[FHI] = 0; -} - -PRIVATE inline void FFPU make_zero_negative(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0; - p[FHI] = 0x80000000; -} - -PRIVATE inline void FFPU make_inf_positive(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0; - p[FHI] = 0x7FF00000; -} - -PRIVATE inline void FFPU make_inf_negative(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0; - p[FHI] = 0xFFF00000; -} - -PRIVATE inline void FFPU fast_scale(fpu_register & r, int add) -{ - uae_u32 * const p = (uae_u32 *)&r; - int exp = (p[FHI] & 0x7FF00000) >> 20; - // TODO: overflow flags - exp += add; - if(exp >= 2047) { - make_inf_positive(r); - } else if(exp < 0) { - // keep sign (+/- 0) - p[FHI] &= 0x80000000; - } else { - p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); - } -} - -PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - int exp = (p[FHI] & 0x7FF00000) >> 20; - return( exp - 1023 ); -} - -// Normalize to range 1..2 -PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000; -} - -// The sign of the quotient is the exclusive-OR of the sign bits -// of the source and destination operands. -PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) -{ - uae_u32 * const a = (uae_u32 *)&ra; - uae_u32 * const b = (uae_u32 *)&rb; - return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); -} - -// Quotient Byte is loaded with the sign and least significant -// seven bits of the quotient. -PRIVATE inline void FFPU make_quotient(fpu_register const & quotient, uae_u32 sign) -{ - uae_u32 lsb = (uae_u32)fabs(quotient) & 0x7f; - FPU fpsr.quotient = sign | (lsb << 16); -} - -// to_single -PRIVATE inline fpu_register FFPU make_single(uae_u32 value) -{ - if ((value & 0x7fffffff) == 0) - return (0.0); - - fpu_register result; - uae_u32 * p = (uae_u32 *)&result; - - uae_u32 sign = (value & 0x80000000); - uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - - p[FLO] = value << 29; - p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); - - fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); - - return(result); -} - -// from_single -PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) -{ - if (src == 0.0) - return 0; - - uae_u32 result; - uae_u32 *p = (uae_u32 *)&src; - - uae_u32 sign = (p[FHI] & 0x80000000); - uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; - - if(exp + 127 < 1023) { - exp = 0; - } else if(exp > 1023 + 127) { - exp = 255; - } else { - exp = exp + 127 - 1023; - } - - result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); - - fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); - - return (result); -} - -// to_exten -PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return 0.0; - - fpu_register result; - uae_u32 *p = (uae_u32 *)&result; - - uae_u32 sign = wrd1 & 0x80000000; - uae_u32 exp = (wrd1 >> 16) & 0x7fff; - - // The explicit integer bit is not set, must normalize. - if((wrd2 & 0x80000000) == 0) { - fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3)); - if( wrd2 | wrd3 ) { - // mantissa, not fraction. - uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; - while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) { - man <<= 1; - exp--; - } - wrd2 = (uae_u32)( man >> 32 ); - wrd3 = (uae_u32)( man & 0xFFFFFFFF ); - } else { - if(exp == 0x7FFF) { - // Infinity. - } else { - // Zero - exp = 16383 - 1023; - } - } - } - - if(exp < 16383 - 1023) { - // should set underflow. - exp = 0; - } else if(exp > 16383 + 1023) { - // should set overflow. - exp = 2047; - } else { - exp = exp + 1023 - 16383; - } - - // drop the explicit integer bit. - p[FLO] = (wrd2 << 21) | (wrd3 >> 11); - p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); - - return(result); -} - -/* - Would be so much easier with full size floats :( - ... this is so vague. -*/ -// make_extended_no_normalize -PRIVATE inline void FFPU make_extended_no_normalize( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result -) -{ - // Is it zero? - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - make_zero_positive(result); - return; - } - - // Is it NaN? - if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) { - if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) { - make_nan(result); - return; - } - } - - uae_u32 sign = wrd1 & 0x80000000; - uae_u32 exp = (wrd1 >> 16) & 0x7fff; - - if(exp < 16383 - 1023) { - // should set underflow. - exp = 0; - } else if(exp > 16383 + 1023) { - // should set overflow. - exp = 2047; - } else { - exp = exp + 1023 - 16383; - } - - // drop the explicit integer bit. - uae_u32 *p = (uae_u32 *)&result; - p[FLO] = (wrd2 << 21) | (wrd3 >> 11); - p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); -} - -// from_exten -PRIVATE inline void FFPU extract_extended(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -) -{ - if (src == 0.0) { - *wrd1 = *wrd2 = *wrd3 = 0; - return; - } - - uae_u32 *p = (uae_u32 *)&src; - - fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI])); - - uae_u32 sign = p[FHI] & 0x80000000; - - uae_u32 exp = ((p[FHI] >> 20) & 0x7ff); - // Check for maximum - if(exp == 0x7FF) { - exp = 0x7FFF; - } else { - exp += 16383 - 1023; - } - - *wrd1 = sign | (exp << 16); - // always set the explicit integer bit. - *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); - *wrd3 = p[FLO] << 11; - - fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); -} - -// to_double -PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) -{ - if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) - return 0.0; - - fpu_register result; - uae_u32 *p = (uae_u32 *)&result; - p[FLO] = wrd2; - p[FHI] = wrd1; - - fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); - - return(result); -} - -// from_double -PRIVATE inline void FFPU extract_double(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2 -) -{ -/* - if (src == 0.0) { - *wrd1 = *wrd2 = 0; - return; - } -*/ - uae_u32 *p = (uae_u32 *)&src; - *wrd2 = p[FLO]; - *wrd1 = p[FHI]; - - fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); -} - -#else // !FPU_HAVE_IEEE_DOUBLE - -#ifndef FPU_USE_NATIVE_FLAGS -PRIVATE inline void FFPU make_fpsr(fpu_register const & r) -{ - FPU fpsr.condition_codes - = ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0) - | ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0) - ; -} -#endif - -// make_single -PRIVATE inline fpu_register FFPU make_single(uae_u32 value) -{ - if ((value & 0x7fffffff) == 0) - return (0.0); - - fpu_register frac = (fpu_register) ((value & 0x7fffff) | 0x800000) / 8388608.0; - if (value & 0x80000000) - frac = -frac; - - fpu_register result = ldexp (frac, (int)((value >> 23) & 0xff) - 127); - fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); - - return (result); -} - -// extract_single -PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) -{ - int expon; - uae_u32 tmp, result; - fpu_register frac; -#if FPU_DEBUG - fpu_register src0 = src; -#endif - - if (src == 0.0) - return 0; - if (src < 0) { - tmp = 0x80000000; - src = -src; - } else { - tmp = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 16777216.0; - if (frac >= 1.0) { - frac /= 2.0; - expon++; - } - result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff); - - // fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result)); - - return (result); -} - -// to exten -PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - fpu_register frac, result; - - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return 0.0; - frac = (fpu_register) wrd2 / 2147483648.0 + - (fpu_register) wrd3 / 9223372036854775808.0; - if (wrd1 & 0x80000000) - frac = -frac; - result = ldexp (frac, (int)((wrd1 >> 16) & 0x7fff) - 16383); - - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); - - return result; -} - -// extract_extended -PRIVATE inline void FFPU extract_extended(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) -{ - int expon; - fpu_register frac; -#if FPU_DEBUG - fpu_register src0 = src; -#endif - - if (src == 0.0) { - *wrd1 = 0; - *wrd2 = 0; - *wrd3 = 0; - return; - } - if (src < 0) { - *wrd1 = 0x80000000; - src = -src; - } else { - *wrd1 = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 18446744073709551616.0; - if (frac >= 1.0) { - frac /= 2.0; - expon++; - } - *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); - *wrd2 = (uae_u32) (frac * 4294967296.0); - *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0); - - // fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(float)src0,*wrd1,*wrd2,*wrd3)); -} - -// make_double -PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) -{ - if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) - return 0.0; - - fpu_register frac = - (fpu_register) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 + - (fpu_register) wrd2 / 4503599627370496.0; - - if (wrd1 & 0x80000000) - frac = -frac; - - fpu_register result = ldexp (frac, (int)((wrd1 >> 20) & 0x7ff) - 1023); - fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); - - return result; -} - -// extract_double -PRIVATE inline void FFPU extract_double(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2) -{ - int expon; - int tmp; - fpu_register frac frac; -#if FPU_DEBUG - fpu_register src0 = src; -#endif - - if (src == 0.0) { - *wrd1 = 0; - *wrd2 = 0; - return; - } - if (src < 0) { - *wrd1 = 0x80000000; - src = -src; - } else { - *wrd1 = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 9007199254740992.0; - if (frac >= 1.0) { - frac /= 2.0; - expon++; - } - tmp = (uae_u32) (frac * 2097152.0); - *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff); - *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0); - - // fpu_debug(("extract_double (%.04f) = %X,%X\n",(float)src0,*wrd1,*wrd2)); -} - -#endif - -// to_pack -PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) -{ - fpu_double d; - char *cp; - char str[100]; - - cp = str; - if (wrd1 & 0x80000000) - *cp++ = '-'; - *cp++ = (char)((wrd1 & 0xf) + '0'); - *cp++ = '.'; - *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); - *cp++ = 'E'; - if (wrd1 & 0x40000000) - *cp++ = '-'; - *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); - *cp = 0; - sscanf(str, "%le", &d); - - fpu_debug(("make_packed str = %s\n",str)); - - fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); - return d; -} - -// from_pack -PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) -{ - int i; - int t; - char *cp; - char str[100]; - - sprintf(str, "%.16e", src); - - fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); - - cp = str; - *wrd1 = *wrd2 = *wrd3 = 0; - if (*cp == '-') { - cp++; - *wrd1 = 0x80000000; - } - if (*cp == '+') - cp++; - *wrd1 |= (*cp++ - '0'); - if (*cp == '.') - cp++; - for (i = 0; i < 8; i++) { - *wrd2 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd2 |= *cp++ - '0'; - } - for (i = 0; i < 8; i++) { - *wrd3 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd3 |= *cp++ - '0'; - } - if (*cp == 'e' || *cp == 'E') { - cp++; - if (*cp == '-') { - cp++; - *wrd1 |= 0x40000000; - } - if (*cp == '+') - cp++; - t = 0; - for (i = 0; i < 3; i++) { - if (*cp >= '0' && *cp <= '9') - t = (t << 4) | (*cp++ - '0'); - } - *wrd1 |= t << 16; - } - - fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); -} - -PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register & src) -{ - uaecptr tmppc; - uae_u16 tmp; - int size; - int mode; - int reg; - uae_u32 ad = 0; - static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - // fpu_debug(("get_fp_value(%X,%X)\n",(int)opcode,(int)extra)); - // dump_first_bytes( regs.pc_p-4, 16 ); - - if ((extra & 0x4000) == 0) { - src = FPU registers[(extra >> 10) & 7]; - return 1; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - - fpu_debug(("get_fp_value mode=%d, reg=%d, size=%d\n",(int)mode,(int)reg,(int)size)); - - switch (mode) { - case 0: - switch (size) { - case 6: - src = (fpu_register) (uae_s8) m68k_dreg (regs, reg); - break; - case 4: - src = (fpu_register) (uae_s16) m68k_dreg (regs, reg); - break; - case 0: - src = (fpu_register) (uae_s32) m68k_dreg (regs, reg); - break; - case 1: - src = make_single(m68k_dreg (regs, reg)); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - fpu_debug(("get_fp_value next_iword()=%X\n",ad-m68k_getpc()-2)); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - // Immediate addressing mode && Operation Length == Byte -> - // Use the low-order byte of the extension word. - if(size == 6) ad++; - break; - default: - return 0; - } - } - - fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); - fpu_debug(("get_fp_value ad=%X\n",ad)); - fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); - dump_first_bytes( get_real_address(ad)-64, 64 ); - dump_first_bytes( get_real_address(ad), 64 ); - - switch (size) { - case 0: - src = (fpu_register) (uae_s32) get_long (ad); - break; - case 1: - src = make_single(get_long (ad)); - break; - case 2: { - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - src = make_extended(wrd1, wrd2, wrd3); - break; - } - case 3: { - uae_u32 wrd1, wrd2, wrd3; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - src = make_packed(wrd1, wrd2, wrd3); - break; - } - case 4: - src = (fpu_register) (uae_s16) get_word(ad); - break; - case 5: { - uae_u32 wrd1, wrd2; - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - src = make_double(wrd1, wrd2); - break; - } - case 6: - src = (fpu_register) (uae_s8) get_byte(ad); - break; - default: - return 0; - } - - // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); - return 1; -} - -PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) -{ - uae_u16 tmp; - uaecptr tmppc; - int size; - int mode; - int reg; - uae_u32 ad; - static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - // fpu_debug(("put_fp_value(%.04f,%X,%X)\n",(float)value,(int)opcode,(int)extra)); - - if ((extra & 0x4000) == 0) { - int dest_reg = (extra >> 10) & 7; - FPU registers[dest_reg] = value; - make_fpsr(FPU registers[dest_reg]); - return 1; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - ad = 0xffffffff; - switch (mode) { - case 0: - switch (size) { - case 6: - m68k_dreg (regs, reg) - = (((uae_s32) value & 0xff) - | (m68k_dreg (regs, reg) & ~0xff)); - break; - case 4: - m68k_dreg (regs, reg) - = (((uae_s32) value & 0xffff) - | (m68k_dreg (regs, reg) & ~0xffff)); - break; - case 0: - m68k_dreg (regs, reg) = (uae_s32) value; - break; - case 1: - m68k_dreg (regs, reg) = extract_single(value); - break; - default: - return 0; - } - return 1; - case 1: - return 0; - case 2: - ad = m68k_areg (regs, reg); - break; - case 3: - ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); - break; - case 5: - ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - ad = next_ilong(); - break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - ad = m68k_getpc (); - m68k_setpc (ad + sz2[size]); - break; - default: - return 0; - } - } - switch (size) { - case 0: - put_long (ad, (uae_s32) value); - break; - case 1: - put_long (ad, extract_single(value)); - break; - case 2: { - uae_u32 wrd1, wrd2, wrd3; - extract_extended(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - break; - } - case 3: { - uae_u32 wrd1, wrd2, wrd3; - extract_packed(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - break; - } - case 4: - put_word(ad, (uae_s16) value); - break; - case 5: { - uae_u32 wrd1, wrd2; - extract_double(value, &wrd1, &wrd2); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - break; - } - case 6: - put_byte(ad, (uae_s8) value); - break; - default: - return 0; - } - return 1; -} - -PRIVATE inline int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) -{ - uae_u16 tmp; - uaecptr tmppc; - int mode; - int reg; - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) { - case 0: - case 1: - return 0; - case 2: - *ad = m68k_areg (regs, reg); - break; - case 3: - *ad = m68k_areg (regs, reg); - break; - case 4: - *ad = m68k_areg (regs, reg); - break; - case 5: - *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); - break; - case 6: - *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) { - case 0: - *ad = (uae_s32) (uae_s16) next_iword(); - break; - case 1: - *ad = next_ilong(); - break; - case 2: - *ad = m68k_getpc (); - *ad += (uae_s32) (uae_s16) next_iword(); - break; - case 3: - tmppc = m68k_getpc (); - tmp = (uae_u16)next_iword(); - *ad = get_disp_ea_020 (tmppc, tmp); - break; - default: - return 0; - } - } - return 1; -} - -#if FPU_DEBUG -# define CONDRET(s,x) fpu_debug(("fpp_cond %s = %d\n",s,(uint32)(x))); return (x) -#else -# define CONDRET(s,x) return (x) -#endif - -PRIVATE inline int FFPU fpp_cond(int condition) -{ -#if 1 -# define N ((FPU fpsr.condition_codes & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE) -# define Z ((FPU fpsr.condition_codes & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO) -# define I ((FPU fpsr.condition_codes & NATIVE_FFLAG_INFINITY) == NATIVE_FFLAG_INFINITY) -# define NaN ((FPU fpsr.condition_codes & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN) -#else -# define N ((FPU fpsr.condition_codes & NATIVE_FFLAG_NEGATIVE) != 0) -# define Z ((FPU fpsr.condition_codes & NATIVE_FFLAG_ZERO) != 0) -# define I ((FPU fpsr.condition_codes & NATIVE_FFLAG_INFINITY) != 0) -# define NaN ((FPU fpsr.condition_codes & NATIVE_FFLAG_NAN) != 0) -#endif - -#if 0 - return fpcctrue(condition); -#else - switch (condition) { - case 0x00: CONDRET("False",0); - case 0x01: CONDRET("Equal",Z); - case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); - case 0x03: CONDRET("Ordered Greater Than or Equal",Z || !(NaN || N)); - case 0x04: CONDRET("Ordered Less Than",N && !(NaN || Z)); - case 0x05: CONDRET("Ordered Less Than or Equal",Z || (N && !NaN)); - case 0x06: CONDRET("Ordered Greater or Less Than",!(NaN || Z)); - case 0x07: CONDRET("Ordered",!NaN); - case 0x08: CONDRET("Unordered",NaN); - case 0x09: CONDRET("Unordered or Equal",NaN || Z); - case 0x0a: CONDRET("Unordered or Greater Than",NaN || !(N || Z)); - case 0x0b: CONDRET("Unordered or Greater or Equal",NaN || Z || !N); - case 0x0c: CONDRET("Unordered or Less Than",NaN || (N && !Z)); - case 0x0d: CONDRET("Unordered or Less or Equal",NaN || Z || N); - case 0x0e: CONDRET("Not Equal",!Z); - case 0x0f: CONDRET("True",1); - case 0x10: CONDRET("Signaling False",0); - case 0x11: CONDRET("Signaling Equal",Z); - case 0x12: CONDRET("Greater Than",!(NaN || Z || N)); - case 0x13: CONDRET("Greater Than or Equal",Z || !(NaN || N)); - case 0x14: CONDRET("Less Than",N && !(NaN || Z)); - case 0x15: CONDRET("Less Than or Equal",Z || (N && !NaN)); - case 0x16: CONDRET("Greater or Less Than",!(NaN || Z)); - case 0x17: CONDRET("Greater, Less or Equal",!NaN); - case 0x18: CONDRET("Not Greater, Less or Equal",NaN); - case 0x19: CONDRET("Not Greater or Less Than",NaN || Z); - case 0x1a: CONDRET("Not Less Than or Equal",NaN || !(N || Z)); - case 0x1b: CONDRET("Not Less Than",NaN || Z || !N); - case 0x1c: CONDRET("Not Greater Than or Equal", NaN || (N && !Z)); -// case 0x1c: CONDRET("Not Greater Than or Equal",!Z && (NaN || N)); - case 0x1d: CONDRET("Not Greater Than",NaN || Z || N); - case 0x1e: CONDRET("Signaling Not Equal",!Z); - case 0x1f: CONDRET("Signaling True",1); - default: CONDRET("",-1); - } -#endif - -# undef N -# undef Z -# undef I -# undef NaN -} - -void FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) -{ - fpu_debug(("fdbcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - uaecptr pc = (uae_u32) m68k_getpc (); - uae_s32 disp = (uae_s32) (uae_s16) next_iword(); - int cc = fpp_cond(extra & 0x3f); - if (cc == -1) { - m68k_setpc (pc - 4); - op_illg (opcode); - } else if (!cc) { - int reg = opcode & 0x7; - - // this may have leaked. - /* - m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) - | ((m68k_dreg (regs, reg) - 1) & 0xffff)); - */ - m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000) - | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff)); - - - // condition reversed. - // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) - if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) - m68k_setpc (pc + disp); - } -} - -void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) -{ - fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - - uae_u32 ad; - int cc = fpp_cond(extra & 0x3f); - if (cc == -1) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - else if ((opcode & 0x38) == 0) { - m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | - (cc ? 0xff : 0x00); - } - else if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - else - put_byte(ad, cc ? 0xff : 0x00); -} - -void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) -{ - fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); - - int cc = fpp_cond(opcode & 0x3f); - if (cc == -1) { - m68k_setpc (oldpc); - op_illg (opcode); - } - if (cc) - Exception(7, oldpc - 2); -} - -// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) -void FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) -{ - fpu_debug(("fbcc_opp %X, %X at %08lx, jumpto=%X\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); - - int cc = fpp_cond(opcode & 0x3f); - if (cc == -1) { - m68k_setpc (pc); - op_illg (opcode); - } - else if (cc) { - if ((opcode & 0x40) == 0) - extra = (uae_s32) (uae_s16) extra; - m68k_setpc (pc + extra); - } -} - -// FSAVE has no post-increment -// 0x1f180000 == IDLE state frame, coprocessor version number 1F -void FFPU fpuop_save(uae_u32 opcode) -{ - fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); - - uae_u32 ad; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - int i; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - if (CPUType == 4) { - // Put 4 byte 68040 IDLE frame. - if (incr < 0) { - ad -= 4; - put_long (ad, 0x41000000); - } - else { - put_long (ad, 0x41000000); - ad += 4; - } - } else { - // Put 28 byte 68881 IDLE frame. - if (incr < 0) { - fpu_debug(("fsave_opp pre-decrement\n")); - ad -= 4; - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); - } - ad -= 4; - put_long (ad, 0x1f180000); // IDLE, vers 1f - } - else { - put_long (ad, 0x1f180000); // IDLE, vers 1f - ad += 4; - for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); - ad += 4; - } - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - ad += 4; - } - } - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - fpu_debug(("PROBLEM: fsave_opp post-increment\n")); - } - if ((opcode & 0x38) == 0x20) { - m68k_areg (regs, opcode & 7) = ad; - fpu_debug(("fsave_opp pre-decrement %X -> A%d\n",ad,opcode & 7)); - } -} - -// FRESTORE has no pre-decrement -void FFPU fpuop_restore(uae_u32 opcode) -{ - fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); - - uae_u32 ad; - uae_u32 d; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - if (CPUType == 4) { - // 68040 - if (incr < 0) { - fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0) { // IDLE - fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); - } - else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); - ad -= 44; - } - else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); - ad -= 92; - } - } - } - else { - d = get_long (ad); - fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); - ad += 4; - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0) { // IDLE - fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); - } - else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP - fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); - ad += 44; - } - else if ((d & 0x00ff0000) == 0x00600000) { // BUSY - fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); - ad += 92; - } - } - } - } - else { - // 68881 - if (incr < 0) { - fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad -= 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad -= 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad -= 45 * 4; - } - } - else { - d = get_long (ad); - fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); - ad += 4; - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0x00180000) { // IDLE - fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); - ad += 6 * 4; - } - else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? - ad += 14 * 4; - fpu_debug(("PROBLEM: frestore_opp found UNIMP? frame at %X\n",ad-4)); - } - else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY - fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); - ad += 45 * 4; - } - } - } - } - if ((opcode & 0x38) == 0x18) { - m68k_areg (regs, opcode & 7) = ad; - fpu_debug(("frestore_opp post-increment %X -> A%d\n",ad,opcode & 7)); - } - if ((opcode & 0x38) == 0x20) { - m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 - fpu_debug(("PROBLEM: frestore_opp pre-decrement\n")); - } -} - -void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) -{ - int reg; - fpu_register src; - - fpu_debug(("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, - m68k_getpc () - 4)); - - dump_registers( "START"); - - switch ((extra >> 13) & 0x7) { - case 3: - fpu_debug(("FMOVE -> \n")); - if (put_fp_value (opcode, extra, FPU registers[(extra >> 7) & 7]) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - dump_registers( "END "); - return; - case 4: - case 5: - if ((opcode & 0x38) == 0) { - if (extra & 0x2000) { // dr bit - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; - fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); - } - if (extra & 0x0800) { - m68k_dreg (regs, opcode & 7) = get_fpsr(); - fpu_debug(("FMOVEM FPU fpsr (%X) -> D%d\n", get_fpsr(), opcode & 7)); - } - if (extra & 0x0400) { - m68k_dreg (regs, opcode & 7) = FPU instruction_address; - fpu_debug(("FMOVEM FPU instruction_address (%X) -> D%d\n", FPU instruction_address, opcode & 7)); - } - } - else { - if (extra & 0x1000) { - set_fpcr( m68k_dreg (regs, opcode & 7) ); - fpu_debug(("FMOVEM D%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); - } - if (extra & 0x0800) { - set_fpsr( m68k_dreg (regs, opcode & 7) ); - fpu_debug(("FMOVEM D%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); - } - if (extra & 0x0400) { - FPU instruction_address = m68k_dreg (regs, opcode & 7); - fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); - } - } -// } else if ((opcode & 0x38) == 1) { - } - else if ((opcode & 0x38) == 8) { - if (extra & 0x2000) { // dr bit - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; - fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); - } - if (extra & 0x0800) { - m68k_areg (regs, opcode & 7) = get_fpsr(); - fpu_debug(("FMOVEM FPU fpsr (%X) -> A%d\n", get_fpsr(), opcode & 7)); - } - if (extra & 0x0400) { - m68k_areg (regs, opcode & 7) = FPU instruction_address; - fpu_debug(("FMOVEM FPU instruction_address (%X) -> A%d\n", FPU instruction_address, opcode & 7)); - } - } else { - if (extra & 0x1000) { - set_fpcr( m68k_areg (regs, opcode & 7) ); - fpu_debug(("FMOVEM A%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); - } - if (extra & 0x0800) { - set_fpsr( m68k_areg (regs, opcode & 7) ); - fpu_debug(("FMOVEM A%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); - } - if (extra & 0x0400) { - FPU instruction_address = m68k_areg (regs, opcode & 7); - fpu_debug(("FMOVEM A%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); - } - } - } - else if ((opcode & 0x3f) == 0x3c) { - if ((extra & 0x2000) == 0) { - if (extra & 0x1000) { - set_fpcr( next_ilong() ); - fpu_debug(("FMOVEM #<%X> -> FPU fpcr\n", get_fpcr())); - } - if (extra & 0x0800) { - set_fpsr( next_ilong() ); - fpu_debug(("FMOVEM #<%X> -> FPU fpsr\n", get_fpsr())); - } - if (extra & 0x0400) { - FPU instruction_address = next_ilong(); - fpu_debug(("FMOVEM #<%X> -> FPU instruction_address\n", FPU instruction_address)); - } - } - } - else if (extra & 0x2000) { - /* FMOVEM FPP->memory */ - uae_u32 ad; - int incr = 0; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - if ((opcode & 0x38) == 0x20) { - if (extra & 0x1000) - incr += 4; - if (extra & 0x0800) - incr += 4; - if (extra & 0x0400) - incr += 4; - } - ad -= incr; - if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - put_long (ad, get_fpcr() & 0xFFFF); - fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); - ad += 4; - } - if (extra & 0x0800) { - put_long (ad, get_fpsr()); - fpu_debug(("FMOVEM FPU fpsr (%X) -> mem %X\n", get_fpsr(), ad )); - ad += 4; - } - if (extra & 0x0400) { - put_long (ad, FPU instruction_address); - fpu_debug(("FMOVEM FPU instruction_address (%X) -> mem %X\n", FPU instruction_address, ad )); - ad += 4; - } - ad -= incr; - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - else { - /* FMOVEM memory->FPP */ - uae_u32 ad; - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - - // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; - int incr = 0; - if((opcode & 0x38) == 0x20) { - if (extra & 0x1000) - incr += 4; - if (extra & 0x0800) - incr += 4; - if (extra & 0x0400) - incr += 4; - ad = ad - incr; - } - - if (extra & 0x1000) { - set_fpcr( get_long (ad) ); - fpu_debug(("FMOVEM mem %X (%X) -> FPU fpcr\n", ad, get_fpcr() )); - ad += 4; - } - if (extra & 0x0800) { - set_fpsr( get_long (ad) ); - fpu_debug(("FMOVEM mem %X (%X) -> FPU fpsr\n", ad, get_fpsr() )); - ad += 4; - } - if (extra & 0x0400) { - FPU instruction_address = get_long (ad); - fpu_debug(("FMOVEM mem %X (%X) -> FPU instruction_address\n", ad, FPU instruction_address )); - ad += 4; - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? -// m68k_areg (regs, opcode & 7) = ad - 12; - m68k_areg (regs, opcode & 7) = ad - incr; - } - dump_registers( "END "); - return; - case 6: - case 7: { - uae_u32 ad, list = 0; - int incr = 0; - if (extra & 0x2000) { - /* FMOVEM FPP->memory */ - fpu_debug(("FMOVEM FPP->memory\n")); - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 1: /* dynamic pred */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 3: /* dynamic postinc */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = 1; - break; - } - - if (incr < 0) { - for(reg=7; reg>=0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); - ad -= 4; - put_long (ad, wrd3); - ad -= 4; - put_long (ad, wrd2); - ad -= 4; - put_long (ad, wrd1); - } - list <<= 1; - } - } - else { - for(reg=0; reg<8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); - ad += 4; - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - else { - /* FMOVEM memory->FPP */ - fpu_debug(("FMOVEM memory->FPP\n")); - - if (get_fp_ad(opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); - list = extra & 0xff; - incr = -1; - break; - case 1: /* dynamic pred */ - fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 3: /* dynamic postinc */ - list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; - incr = 1; - break; - } - - /**/ - if (incr < 0) { - // not reached - for(reg=7; reg>=0; reg--) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - ad -= 4; - wrd3 = get_long (ad); - ad -= 4; - wrd2 = get_long (ad); - ad -= 4; - wrd1 = get_long (ad); - // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); - make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); - } - list <<= 1; - } - } - else { - for(reg=0; reg<8; reg++) { - uae_u32 wrd1, wrd2, wrd3; - if( list & 0x80 ) { - wrd1 = get_long (ad); - ad += 4; - wrd2 = get_long (ad); - ad += 4; - wrd3 = get_long (ad); - ad += 4; - // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); - make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) // post-increment? - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) // pre-decrement? - m68k_areg (regs, opcode & 7) = ad; - } - dump_registers( "END "); - return; - } - case 0: - case 2: - reg = (extra >> 7) & 7; - if ((extra & 0xfc00) == 0x5c00) { - fpu_debug(("FMOVECR memory->FPP\n")); - switch (extra & 0x7f) { - case 0x00: - // FPU registers[reg] = 4.0 * atan(1.0); - FPU registers[reg] = 3.1415926535897932384626433832795; - fpu_debug(("FP const: Pi\n")); - break; - case 0x0b: - // FPU registers[reg] = log10 (2.0); - FPU registers[reg] = 0.30102999566398119521373889472449; - fpu_debug(("FP const: Log 10 (2)\n")); - break; - case 0x0c: - // FPU registers[reg] = exp (1.0); - FPU registers[reg] = 2.7182818284590452353602874713527; - fpu_debug(("FP const: e\n")); - break; - case 0x0d: - // FPU registers[reg] = log (exp (1.0)) / log (2.0); - FPU registers[reg] = 1.4426950408889634073599246810019; - fpu_debug(("FP const: Log 2 (e)\n")); - break; - case 0x0e: - // FPU registers[reg] = log (exp (1.0)) / log (10.0); - FPU registers[reg] = 0.43429448190325182765112891891661; - fpu_debug(("FP const: Log 10 (e)\n")); - break; - case 0x0f: - FPU registers[reg] = 0.0; - fpu_debug(("FP const: zero\n")); - break; - case 0x30: - // FPU registers[reg] = log (2.0); - FPU registers[reg] = 0.69314718055994530941723212145818; - fpu_debug(("FP const: ln(2)\n")); - break; - case 0x31: - // FPU registers[reg] = log (10.0); - FPU registers[reg] = 2.3025850929940456840179914546844; - fpu_debug(("FP const: ln(10)\n")); - break; - case 0x32: - // ?? - FPU registers[reg] = 1.0e0; - fpu_debug(("FP const: 1.0e0\n")); - break; - case 0x33: - FPU registers[reg] = 1.0e1; - fpu_debug(("FP const: 1.0e1\n")); - break; - case 0x34: - FPU registers[reg] = 1.0e2; - fpu_debug(("FP const: 1.0e2\n")); - break; - case 0x35: - FPU registers[reg] = 1.0e4; - fpu_debug(("FP const: 1.0e4\n")); - break; - case 0x36: - FPU registers[reg] = 1.0e8; - fpu_debug(("FP const: 1.0e8\n")); - break; - case 0x37: - FPU registers[reg] = 1.0e16; - fpu_debug(("FP const: 1.0e16\n")); - break; - case 0x38: - FPU registers[reg] = 1.0e32; - fpu_debug(("FP const: 1.0e32\n")); - break; - case 0x39: - FPU registers[reg] = 1.0e64; - fpu_debug(("FP const: 1.0e64\n")); - break; - case 0x3a: - FPU registers[reg] = 1.0e128; - fpu_debug(("FP const: 1.0e128\n")); - break; - case 0x3b: - FPU registers[reg] = 1.0e256; - fpu_debug(("FP const: 1.0e256\n")); - break; -#if 0 - case 0x3c: - FPU registers[reg] = 1.0e512; - fpu_debug(("FP const: 1.0e512\n")); - break; - case 0x3d: - FPU registers[reg] = 1.0e1024; - fpu_debug(("FP const: 1.0e1024\n")); - break; - case 0x3e: - FPU registers[reg] = 1.0e2048; - fpu_debug(("FP const: 1.0e2048\n")); - break; - case 0x3f: - FPU registers[reg] = 1.0e4096; - fpu_debug(("FP const: 1.0e4096\n")); - break; -#endif - default: - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - break; - } - // these *do* affect the status reg - make_fpsr(FPU registers[reg]); - dump_registers( "END "); - return; - } - - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); - - switch (extra & 0x7f) { - case 0x00: /* FMOVE */ - fpu_debug(("FMOVE %.04f\n",(double)src)); - FPU registers[reg] = src; - // -> reg DOES affect the status reg - make_fpsr(FPU registers[reg]); - break; - case 0x01: /* FINT */ - fpu_debug(("FINT %.04f\n",(double)src)); - // FPU registers[reg] = (int) (src + 0.5); - // FIXME: use native rounding mode flags - switch (get_fpcr() & 0x30) { - case FPCR_ROUND_ZERO: - FPU registers[reg] = round_to_zero(src); - break; - case FPCR_ROUND_MINF: - FPU registers[reg] = floor(src); - break; - case FPCR_ROUND_NEAR: - FPU registers[reg] = round_to_nearest(src); - break; - case FPCR_ROUND_PINF: - FPU registers[reg] = ceil(src); - break; - } - make_fpsr(FPU registers[reg]); - break; - case 0x02: /* FSINH */ - fpu_debug(("FSINH %.04f\n",(double)src)); - FPU registers[reg] = sinh (src); - make_fpsr(FPU registers[reg]); - break; - case 0x03: /* FINTRZ */ - fpu_debug(("FINTRZ %.04f\n",(double)src)); - // FPU registers[reg] = (int) src; - FPU registers[reg] = round_to_zero(src); - make_fpsr(FPU registers[reg]); - break; - case 0x04: /* FSQRT */ - fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = sqrt (src); - make_fpsr(FPU registers[reg]); - break; - case 0x06: /* FLOGNP1 */ - fpu_debug(("FLOGNP1 %.04f\n",(double)src)); - FPU registers[reg] = log (src + 1.0); - make_fpsr(FPU registers[reg]); - break; - case 0x08: /* FETOXM1 */ - fpu_debug(("FETOXM1 %.04f\n",(double)src)); - FPU registers[reg] = exp (src) - 1.0; - make_fpsr(FPU registers[reg]); - break; - case 0x09: /* FTANH */ - fpu_debug(("FTANH %.04f\n",(double)src)); - FPU registers[reg] = tanh (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0a: /* FATAN */ - fpu_debug(("FATAN %.04f\n",(double)src)); - FPU registers[reg] = atan (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0c: /* FASIN */ - fpu_debug(("FASIN %.04f\n",(double)src)); - FPU registers[reg] = asin (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0d: /* FATANH */ - fpu_debug(("FATANH %.04f\n",(double)src)); -#if HAVE_ATANH - FPU registers[reg] = atanh (src); -#else - /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */ - FPU registers[reg] = log ((1 + src) / (1 - src)) / 2; -#endif - make_fpsr(FPU registers[reg]); - break; - case 0x0e: /* FSIN */ - fpu_debug(("FSIN %.04f\n",(double)src)); - FPU registers[reg] = sin (src); - make_fpsr(FPU registers[reg]); - break; - case 0x0f: /* FTAN */ - fpu_debug(("FTAN %.04f\n",(double)src)); - FPU registers[reg] = tan (src); - make_fpsr(FPU registers[reg]); - break; - case 0x10: /* FETOX */ - fpu_debug(("FETOX %.04f\n",(double)src)); - FPU registers[reg] = exp (src); - make_fpsr(FPU registers[reg]); - break; - case 0x11: /* FTWOTOX */ - fpu_debug(("FTWOTOX %.04f\n",(double)src)); - FPU registers[reg] = pow(2.0, src); - make_fpsr(FPU registers[reg]); - break; - case 0x12: /* FTENTOX */ - fpu_debug(("FTENTOX %.04f\n",(double)src)); - FPU registers[reg] = pow(10.0, src); - make_fpsr(FPU registers[reg]); - break; - case 0x14: /* FLOGN */ - fpu_debug(("FLOGN %.04f\n",(double)src)); - FPU registers[reg] = log (src); - make_fpsr(FPU registers[reg]); - break; - case 0x15: /* FLOG10 */ - fpu_debug(("FLOG10 %.04f\n",(double)src)); - FPU registers[reg] = log10 (src); - make_fpsr(FPU registers[reg]); - break; - case 0x16: /* FLOG2 */ - fpu_debug(("FLOG2 %.04f\n",(double)src)); - FPU registers[reg] = log (src) / log (2.0); - make_fpsr(FPU registers[reg]); - break; - case 0x18: /* FABS */ - case 0x58: /* single precision rounding */ - case 0x5C: /* double precision rounding */ - fpu_debug(("FABS %.04f\n",(double)src)); - FPU registers[reg] = src < 0 ? -src : src; - make_fpsr(FPU registers[reg]); - break; - case 0x19: /* FCOSH */ - fpu_debug(("FCOSH %.04f\n",(double)src)); - FPU registers[reg] = cosh(src); - make_fpsr(FPU registers[reg]); - break; - case 0x1a: /* FNEG */ - fpu_debug(("FNEG %.04f\n",(double)src)); - FPU registers[reg] = -src; - make_fpsr(FPU registers[reg]); - break; - case 0x1c: /* FACOS */ - fpu_debug(("FACOS %.04f\n",(double)src)); - FPU registers[reg] = acos(src); - make_fpsr(FPU registers[reg]); - break; - case 0x1d: /* FCOS */ - fpu_debug(("FCOS %.04f\n",(double)src)); - FPU registers[reg] = cos(src); - make_fpsr(FPU registers[reg]); - break; - case 0x1e: /* FGETEXP */ - fpu_debug(("FGETEXP %.04f\n",(double)src)); -#if FPU_HAVE_IEEE_DOUBLE - if( isinf(src) ) { - make_nan( FPU registers[reg] ); - } - else { - FPU registers[reg] = fast_fgetexp( src ); - } -#else - if(src == 0) { - FPU registers[reg] = (fpu_register)0; - } - else { - int expon; - frexp (src, &expon); - FPU registers[reg] = (fpu_register) (expon - 1); - } -#endif - make_fpsr(FPU registers[reg]); - break; - case 0x1f: /* FGETMAN */ - fpu_debug(("FGETMAN %.04f\n",(double)src)); -#if FPU_HAVE_IEEE_DOUBLE - if( src == 0 ) { - FPU registers[reg] = 0; - } - else if( isinf(src) ) { - make_nan( FPU registers[reg] ); - } - else { - FPU registers[reg] = src; - fast_remove_exponent( FPU registers[reg] ); - } -#else - { - int expon; - FPU registers[reg] = frexp (src, &expon) * 2.0; - } -#endif - make_fpsr(FPU registers[reg]); - break; - case 0x20: /* FDIV */ - fpu_debug(("FDIV %.04f\n",(double)src)); - FPU registers[reg] /= src; - make_fpsr(FPU registers[reg]); - break; - case 0x21: /* FMOD */ - fpu_debug(("FMOD %.04f\n",(double)src)); - // FPU registers[reg] = FPU registers[reg] - (fpu_register) ((int) (FPU registers[reg] / src)) * src; - { - fpu_register quot = round_to_zero(FPU registers[reg] / src); -#if FPU_HAVE_IEEE_DOUBLE - uae_u32 sign = get_quotient_sign(FPU registers[reg],src); -#endif - FPU registers[reg] = FPU registers[reg] - quot * src; - make_fpsr(FPU registers[reg]); -#if FPU_HAVE_IEEE_DOUBLE - make_quotient(quot, sign); -#endif - } - break; - case 0x22: /* FADD */ - case 0x62: /* single */ - case 0x66: /* double */ - fpu_debug(("FADD %.04f\n",(double)src)); - FPU registers[reg] += src; - make_fpsr(FPU registers[reg]); - break; - case 0x23: /* FMUL */ - fpu_debug(("FMUL %.04f\n",(double)src)); -#if FPU_HAVE_IEEE_DOUBLE - get_dest_flags(FPU registers[reg]); - get_source_flags(src); - if(fl_dest.in_range && fl_source.in_range) { - FPU registers[reg] *= src; - } - else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); - } - else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } - } - else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } - } -#else - fpu_debug(("FMUL %.04f\n",(double)src)); - FPU registers[reg] *= src; -#endif - make_fpsr(FPU registers[reg]); - break; - case 0x24: /* FSGLDIV */ - fpu_debug(("FSGLDIV %.04f\n",(double)src)); - // TODO: round to float. - FPU registers[reg] /= src; - make_fpsr(FPU registers[reg]); - break; - case 0x25: /* FREM */ - fpu_debug(("FREM %.04f\n",(double)src)); - // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; - { - fpu_register quot = round_to_nearest(FPU registers[reg] / src); -#if FPU_HAVE_IEEE_DOUBLE - uae_u32 sign = get_quotient_sign(FPU registers[reg],src); -#endif - FPU registers[reg] = FPU registers[reg] - quot * src; - make_fpsr(FPU registers[reg]); -#if FPU_HAVE_IEEE_DOUBLE - make_quotient(quot,sign); -#endif - } - break; - - case 0x26: /* FSCALE */ - fpu_debug(("FSCALE %.04f\n",(double)src)); - - // TODO: - // Overflow, underflow - -#if FPU_HAVE_IEEE_DOUBLE - if( isinf(FPU registers[reg]) ) { - make_nan( FPU registers[reg] ); - } - else { - // When the absolute value of the source operand is >= 2^14, - // an overflow or underflow always results. - // Here (int) cast is okay. - fast_scale( FPU registers[reg], (int)round_to_zero(src) ); - } -#else - if (src != 0) { // Manual says: src==0 -> FPn - FPU registers[reg] *= exp (log (2.0) * src); - } -#endif - make_fpsr(FPU registers[reg]); - break; - case 0x27: /* FSGLMUL */ - fpu_debug(("FSGLMUL %.04f\n",(double)src)); - FPU registers[reg] *= src; - make_fpsr(FPU registers[reg]); - break; - case 0x28: /* FSUB */ - fpu_debug(("FSUB %.04f\n",(double)src)); - FPU registers[reg] -= src; - make_fpsr(FPU registers[reg]); - break; - case 0x30: /* FSINCOS */ - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - fpu_debug(("FSINCOS %.04f\n",(double)src)); - // Cosine must be calculated first if same register - FPU registers[extra & 7] = cos(src); - FPU registers[reg] = sin (src); - // Set FPU fpsr according to the sine result - make_fpsr(FPU registers[reg]); - break; - case 0x38: /* FCMP */ - fpu_debug(("FCMP %.04f\n",(double)src)); - - // The infinity bit is always cleared by the FCMP - // instruction since it is not used by any of the - // conditional predicate equations. - -#if FPU_HAVE_IEEE_DOUBLE - if( isinf(src) ) { - if( isneg(src) ) { - // negative infinity - if( isinf(FPU registers[reg]) && isneg(FPU registers[reg]) ) { - // Zero, Negative - FPU fpsr.condition_codes = NATIVE_FFLAG_ZERO | NATIVE_FFLAG_NEGATIVE; - fpu_debug(("-INF cmp -INF -> NZ\n")); - } - else { - // None - FPU fpsr.condition_codes = 0; - fpu_debug(("x cmp -INF -> None\n")); - } - } - else { - // positive infinity - if( isinf(FPU registers[reg]) && !isneg(FPU registers[reg]) ) { - // Zero - FPU fpsr.condition_codes = NATIVE_FFLAG_ZERO; - fpu_debug(("+INF cmp +INF -> Z\n")); - } - else { - // Negative - FPU fpsr.condition_codes = NATIVE_FFLAG_NEGATIVE; - fpu_debug(("X cmp +INF -> N\n")); - } - } - } - else { - fpu_register tmp = FPU registers[reg] - src; - FPU fpsr.condition_codes - = (iszero(tmp) ? NATIVE_FFLAG_ZERO : 0) - | (isneg(tmp) ? NATIVE_FFLAG_NEGATIVE : 0) - ; - } -#else - { - fpu_register tmp = FPU registers[reg] - src; - make_fpsr(tmp); - } -#endif - break; - case 0x3a: /* FTST */ - fpu_debug(("FTST %.04f\n",(double)src)); - // make_fpsr(FPU registers[reg]); - make_fpsr(src); - break; - default: - fpu_debug(("ILLEGAL F OP %X\n",opcode)); - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - break; - } - fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); - dump_registers( "END "); - return; - } - - fpu_debug(("ILLEGAL F OP 2 %X\n",opcode)); - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); -} - -/* -------------------------- Initialization -------------------------- */ - -void FFPU fpu_init (bool integral_68040) -{ - fpu_debug(("fpu_init\n")); - - static bool initialized_lookup_tables = false; - if (!initialized_lookup_tables) { - fpu_init_native_fflags(); - fpu_init_native_exceptions(); - fpu_init_native_accrued_exceptions(); - initialized_lookup_tables = true; - } - - FPU is_integral = integral_68040; - set_fpcr(0); - set_fpsr(0); - FPU instruction_address = 0; -} - -void FFPU fpu_exit (void) -{ - fpu_debug(("fpu_exit\n")); -} - -void FFPU fpu_reset (void) -{ - fpu_debug(("fpu_reset\n")); - fpu_exit(); - fpu_init(FPU is_integral); -} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h deleted file mode 100644 index 7fc4ebbd..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_UAE_H -#define FPU_UAE_H - -// Only define if you have IEEE 64 bit doubles. -#define FPU_HAVE_IEEE_DOUBLE 1 - -/* NOTE: this file shall be included from fpu/fpu_uae.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -enum { -#ifdef WORDS_BIGENDIAN - FHI = 0, - FLO = 1 -#else - FHI = 1, - FLO = 0 -#endif -}; - -// Floating-point rounding support -PRIVATE inline fpu_register round_to_zero(fpu_register const & x); -PRIVATE inline fpu_register round_to_nearest(fpu_register const & x); - -#if FPU_HAVE_IEEE_DOUBLE - -// Lauri-- full words to avoid partial register stalls. -struct double_flags { - uae_u32 in_range; - uae_u32 zero; - uae_u32 infinity; - uae_u32 nan; - uae_u32 negative; -}; -PRIVATE double_flags fl_source; -PRIVATE double_flags fl_dest; -PRIVATE inline void FFPU get_dest_flags(fpu_register const & r); -PRIVATE inline void FFPU get_source_flags(fpu_register const & r); - -PRIVATE inline bool FFPU do_isnan(fpu_register const & r); -PRIVATE inline bool FFPU do_isinf(fpu_register const & r); -PRIVATE inline bool FFPU do_isneg(fpu_register const & r); -PRIVATE inline bool FFPU do_iszero(fpu_register const & r); - -PRIVATE inline void FFPU make_nan(fpu_register & r); -PRIVATE inline void FFPU make_zero_positive(fpu_register & r); -PRIVATE inline void FFPU make_zero_negative(fpu_register & r); -PRIVATE inline void FFPU make_inf_positive(fpu_register & r); -PRIVATE inline void FFPU make_inf_negative(fpu_register & r); - -PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); -PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); - -// May be optimized for particular processors -#ifndef FPU_USE_NATIVE_FLAGS -PRIVATE inline void FFPU make_fpsr(fpu_register const & r); -#endif - -// Normalize to range 1..2 -PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r); - -// The sign of the quotient is the exclusive-OR of the sign bits -// of the source and destination operands. -PRIVATE inline uae_u32 FFPU get_quotient_sign( - fpu_register const & ra, fpu_register const & rb -); - -// Quotient Byte is loaded with the sign and least significant -// seven bits of the quotient. -PRIVATE inline void FFPU make_quotient( - fpu_register const & quotient, uae_u32 sign -); - -// to_single -PRIVATE inline fpu_register FFPU make_single( - uae_u32 value -); - -// from_single -PRIVATE inline uae_u32 FFPU extract_single( - fpu_register const & src -); - -// to_exten -PRIVATE inline fpu_register FFPU make_extended( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 -); - -/* - Would be so much easier with full size floats :( - ... this is so vague. -*/ -// to_exten_no_normalize -PRIVATE inline void FFPU make_extended_no_normalize( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result -); - -// from_exten -PRIVATE inline void FFPU extract_extended(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -); - -// to_double -PRIVATE inline fpu_register FFPU make_double( - uae_u32 wrd1, uae_u32 wrd2 -); - -// from_double -PRIVATE inline void FFPU extract_double(fpu_register const & src, - uae_u32 * wrd1, uae_u32 * wrd2 -); - -#else /* !FPU_HAVE_IEEE_DOUBLE */ - -// FIXME: may be optimized for particular processors -#ifndef FPU_USE_NATIVE_FLAGS -PRIVATE inline void FFPU make_fpsr(fpu_register const & r); -#endif - -// to_single -PRIVATE inline fpu_register make_single( - uae_u32 value -); - -// from_single -PRIVATE inline uae_u32 FFPU extract_single( - fpu_register const & src -); - -// to exten -PRIVATE inline fpu_register FFPU make_extended( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 -); - -// from_exten -PRIVATE inline void FFPU extract_extended( - fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -); - -// to_double -PRIVATE inline fpu_register FFPU make_double( - uae_u32 wrd1, uae_u32 wrd2 -); - -// from_double -PRIVATE inline void FFPU extract_double( - fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2 -); - -#endif /* FPU_HAVE_IEEE_DOUBLE */ - -PRIVATE inline fpu_register FFPU make_packed( - uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 -); - -PRIVATE inline void FFPU extract_packed( - fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 -); - -PRIVATE inline int FFPU get_fp_value( - uae_u32 opcode, uae_u16 extra, fpu_register & src -); - -PRIVATE inline int FFPU put_fp_value( - uae_u32 opcode, uae_u16 extra, fpu_register const & value -); - -PRIVATE inline int FFPU get_fp_ad( - uae_u32 opcode, uae_u32 * ad -); - -PRIVATE inline int FFPU fpp_cond( - int condition -); - -#endif /* FPU_UAE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/impl.h b/BasiliskII/src/uae_cpu/fpu/impl.h deleted file mode 100644 index c79d1f3f..00000000 --- a/BasiliskII/src/uae_cpu/fpu/impl.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * fpu/impl.h - extra functions and inline implementations - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_IMPL_H -#define FPU_IMPL_H - -/* NOTE: this file shall be included from fpu/core.h */ -#undef PUBLIC -#define PUBLIC /**/ - -#undef PRIVATE -#define PRIVATE /**/ - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* -------------------------------------------------------------------------- */ -/* --- X86 assembly fpu specific methods --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_X86 - -/* Return the floating-point status register in m68k format */ -static inline uae_u32 FFPU get_fpsr(void) -{ - return to_m68k_fpcond[(x86_status_word & 0x4700) >> 8] - | FPU fpsr.quotient - | exception_host2mac[x86_status_word & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)] - | accrued_exception_host2mac[x86_status_word_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)] - ; -} - -/* Set the floating-point status register from an m68k format */ -static inline void FFPU set_fpsr(uae_u32 new_fpsr) -{ - x86_status_word = to_host_fpcond[(new_fpsr & FPSR_CCB) >> 24 ] - | exception_mac2host[(new_fpsr & FPSR_EXCEPTION_STATUS) >> 8]; - x86_status_word_accrued = accrued_exception_mac2host[(new_fpsr & FPSR_ACCRUED_EXCEPTION) >> 3]; -} - -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Original UAE and IEEE FPU core methods --- */ -/* -------------------------------------------------------------------------- */ - -#ifndef FPU_X86 - -/* Return the floating-point status register in m68k format */ -static inline uae_u32 FFPU get_fpsr(void) -{ - uae_u32 condition_codes = get_fpccr(); - uae_u32 exception_status = get_exception_status(); - uae_u32 accrued_exception = get_accrued_exception(); - uae_u32 quotient = FPU fpsr.quotient; - return (condition_codes | quotient | exception_status | accrued_exception); -} - -/* Set the floating-point status register from an m68k format */ -static inline void FFPU set_fpsr(uae_u32 new_fpsr) -{ - set_fpccr ( new_fpsr & FPSR_CCB ); - set_exception_status ( new_fpsr & FPSR_EXCEPTION_STATUS ); - set_accrued_exception ( new_fpsr & FPSR_ACCRUED_EXCEPTION ); - FPU fpsr.quotient = new_fpsr & FPSR_QUOTIENT; -} - -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Common routines for control word --- */ -/* -------------------------------------------------------------------------- */ - -/* Return the floating-point control register in m68k format */ -static inline uae_u32 FFPU get_fpcr(void) -{ - uae_u32 rounding_precision = get_rounding_precision(); - uae_u32 rounding_mode = get_rounding_mode(); - return (rounding_precision | rounding_mode); -} - -/* Set the floating-point control register from an m68k format */ -static inline void FFPU set_fpcr(uae_u32 new_fpcr) -{ - set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION); - set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE ); - set_host_control_word(); -} - -/* -------------------------------------------------------------------------- */ -/* --- Specific part to X86 assembly FPU --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_X86 - -/* Retrieve a floating-point register value and convert it to double precision */ -static inline double FFPU fpu_get_register(int r) -{ - double f; - __asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r])); - return f; -} - -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Specific to original UAE or new IEEE-based FPU core --- */ -/* -------------------------------------------------------------------------- */ - -#if defined(FPU_UAE) || defined(FPU_IEEE) - -/* Retrieve a floating-point register value and convert it to double precision */ -static inline double FFPU fpu_get_register(int r) -{ - return FPU registers[r]; -} - -#endif - -#endif /* FPU_IMPL_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp deleted file mode 100644 index eabb376e..00000000 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * fpu/mathlib.cpp - Floating-point math support library - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ -#undef PRIVATE -#define PRIVATE static - -#undef PUBLIC -#define PUBLIC /**/ - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) - -PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y) -{ - fpu_extended value, exponent; - uae_s64 p = (uae_s64)y; - - if (x == 0.0) { - if (y > 0.0) - return (y == (double) p && (p & 1) != 0 ? x : 0.0); - else if (y < 0.0) - return (y == (double) p && (-p & 1) != 0 ? 1.0 / x : 1.0 / fp_fabs (x)); - } - - if (y == (double) p) { - fpu_extended r = 1.0; - if (p == 0) - return 1.0; - if (p < 0) { - p = -p; - x = 1.0 / x; - } - while (1) { - if (p & 1) - r *= x; - p >>= 1; - if (p == 0) - return r; - x *= x; - } - } - - __asm__ __volatile__("fyl2x" : "=t" (value) : "0" (x), "u" (1.0) : "st(1)"); - __asm__ __volatile__("fmul %%st(1) # y * log2(x)\n\t" - "fst %%st(1)\n\t" - "frndint # int(y * log2(x))\n\t" - "fxch\n\t" - "fsub %%st(1) # fract(y * log2(x))\n\t" - "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" - : "=t" (value), "=u" (exponent) : "0" (y), "1" (value)); - value += 1.0; - __asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent)); - return value; -} - -PRIVATE fpu_extended fp_do_log1p(fpu_extended x) -{ - // TODO: handle NaN and +inf/-inf - fpu_extended value; - // The fyl2xp1 can only be used for values in - // -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 - // 0.29 is a safe value. - if (fp_fabs(x) <= 0.29) - __asm__ __volatile__("fldln2; fxch; fyl2xp1" : "=t" (value) : "0" (x)); - else - __asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0)); - return value; -} - -#endif diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h deleted file mode 100644 index 755c43d9..00000000 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.h +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * fpu/mathlib.h - Floating-point math support library - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_MATHLIB_H -#define FPU_MATHLIB_H - -/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -// Define the following macro if branches are expensive. If so, -// integer-based isnan() and isinf() functions are implemented. -// TODO: move to Makefile.in -#define BRANCHES_ARE_EXPENSIVE 1 - -// Use ISO C99 extended-precision math functions (glibc 2.1+) -#define FPU_USE_ISO_C99 1 - -// Use faster implementation of math functions, but this could cause -// some incorrect results (?) -#ifdef _MSC_VER -// MSVC uses intrinsics for all of the math functions, so it should still be fast -#define FPU_FAST_MATH 0 -#else -#define FPU_FAST_MATH 1 -#endif - -#if FPU_USE_ISO_C99 -// NOTE: no prior shall be included at this point -#define __USE_ISOC99 1 // for glibc 2.2.X and newer -#define __USE_ISOC9X 1 // for glibc 2.1.X -#include -#else -#include -using namespace std; -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Floating-point register types --- */ -/* -------------------------------------------------------------------------- */ - -// Single : S 8*E 23*F -#define FP_SINGLE_EXP_MAX 0xff -#define FP_SINGLE_EXP_BIAS 0x7f - -// Double : S 11*E 52*F -#define FP_DOUBLE_EXP_MAX 0x7ff -#define FP_DOUBLE_EXP_BIAS 0x3ff - -// Extended : S 15*E 64*F -#define FP_EXTENDED_EXP_MAX 0x7fff -#define FP_EXTENDED_EXP_BIAS 0x3fff - -// Zeroes : E = 0 & F = 0 -// Infinities : E = MAX & F = 0 -// Not-A-Number : E = MAX & F # 0 - -/* -------------------------------------------------------------------------- */ -/* --- Floating-point type shapes (IEEE-compliant) --- */ -/* -------------------------------------------------------------------------- */ - -// Taken from glibc 2.2.x: ieee754.h - -// IEEE-754 float format -union fpu_single_shape { - - fpu_single value; - - /* This is the IEEE 754 single-precision format. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int mantissa:23; -#else - unsigned int mantissa:23; - unsigned int exponent:8; - unsigned int negative:1; -#endif - } ieee; - - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int quiet_nan:1; - unsigned int mantissa:22; -#else - unsigned int mantissa:22; - unsigned int quiet_nan:1; - unsigned int exponent:8; - unsigned int negative:1; -#endif - } ieee_nan; -}; - -// IEEE-754 double format -union fpu_double_shape { - fpu_double value; - - /* This is the IEEE 754 double-precision format. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:11; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:20; - unsigned int mantissa1:32; -#else -# if HOST_FLOAT_WORDS_BIG_ENDIAN - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; -# else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; -# endif -#endif - } ieee; - - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:11; - unsigned int quiet_nan:1; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:19; - unsigned int mantissa1:32; -#else -# if HOST_FLOAT_WORDS_BIG_ENDIAN - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; -# else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; -# endif -#endif - } ieee_nan; - - /* This format is used to extract the sign_exponent and mantissa parts only */ - struct { -#if HOST_FLOAT_WORDS_BIG_ENDIAN - unsigned int msw:32; - unsigned int lsw:32; -#else - unsigned int lsw:32; - unsigned int msw:32; -#endif - } parts; -}; - -#ifdef USE_LONG_DOUBLE -// IEEE-854 long double format -union fpu_extended_shape { - fpu_extended value; - - /* This is the IEEE 854 double-extended-precision format. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; -#else -# if HOST_FLOAT_WORDS_BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; -# else - unsigned int mantissa1:32; - unsigned int mantissa0:32; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; -# endif -#endif - } ieee; - - /* This is for NaNs in the IEEE 854 double-extended-precision format. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int one:1; - unsigned int quiet_nan:1; - unsigned int mantissa0:30; - unsigned int mantissa1:32; -#else -# if HOST_FLOAT_WORDS_BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int mantissa1:32; -# else - unsigned int mantissa1:32; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; -# endif -#endif - } ieee_nan; - - /* This format is used to extract the sign_exponent and mantissa parts only */ - struct { -#if HOST_FLOAT_WORDS_BIG_ENDIAN - unsigned int sign_exponent:16; - unsigned int empty:16; - unsigned int msw:32; - unsigned int lsw:32; -#else - unsigned int lsw:32; - unsigned int msw:32; - unsigned int sign_exponent:16; - unsigned int empty:16; -#endif - } parts; -}; -#endif - -#ifdef USE_QUAD_DOUBLE -// IEEE-854 quad double format -union fpu_extended_shape { - fpu_extended value; - - /* This is the IEEE 854 quad-precision format. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int mantissa0:16; - unsigned int mantissa1:32; - unsigned int mantissa2:32; - unsigned int mantissa3:32; -#else - unsigned int mantissa3:32; - unsigned int mantissa2:32; - unsigned int mantissa1:32; - unsigned int mantissa0:16; - unsigned int exponent:15; - unsigned int negative:1; -#endif - } ieee; - - /* This is for NaNs in the IEEE 854 quad-precision format. */ - struct { -#ifdef WORDS_BIGENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int quiet_nan:1; - unsigned int mantissa0:15; - unsigned int mantissa1:30; - unsigned int mantissa2:32; - unsigned int mantissa3:32; -#else - unsigned int mantissa3:32; - unsigned int mantissa2:32; - unsigned int mantissa1:32; - unsigned int mantissa0:15; - unsigned int quiet_nan:1; - unsigned int exponent:15; - unsigned int negative:1; -#endif - } ieee_nan; - - /* This format is used to extract the sign_exponent and mantissa parts only */ -#if HOST_FLOAT_WORDS_BIG_ENDIAN - struct { - uae_u64 msw; - uae_u64 lsw; - } parts64; - struct { - uae_u32 w0; - uae_u32 w1; - uae_u32 w2; - uae_u32 w3; - } parts32; -#else - struct { - uae_u64 lsw; - uae_u64 msw; - } parts64; - struct { - uae_u32 w3; - uae_u32 w2; - uae_u32 w1; - uae_u32 w0; - } parts32; -#endif -}; -#endif - -// Declare and initialize a pointer to a shape of the requested FP type -#define fp_declare_init_shape(psvar, rfvar, ftype) \ - fpu_ ## ftype ## _shape * psvar = (fpu_ ## ftype ## _shape *)( &rfvar ) - -/* -------------------------------------------------------------------------- */ -/* --- Extra Math Functions --- */ -/* --- (most of them had to be defined before including ) --- */ -/* -------------------------------------------------------------------------- */ - -#undef isnan -#if 0 && defined(HAVE_ISNANL) -# define isnan(x) isnanl((x)) -#else -# define isnan(x) fp_do_isnan((x)) -#endif - -PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r) -{ -#ifdef BRANCHES_ARE_EXPENSIVE -#ifndef USE_LONG_DOUBLE - fp_declare_init_shape(sxp, r, double); - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; - hx &= 0x7fffffff; - hx |= (uae_u32)(lx | (-lx)) >> 31; - hx = 0x7ff00000 - hx; - return (((uae_u32)hx) >> 31) != 0; -#elif USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - uae_s64 hx = sxp->parts64.msw; - uae_s64 lx = sxp->parts64.lsw; - hx &= 0x7fffffffffffffffLL; - hx |= (uae_u64)(lx | (-lx)) >> 63; - hx = 0x7fff000000000000LL - hx; - return ((uae_u64)hx >> 63) != 0; -#else - fp_declare_init_shape(sxp, r, extended); - uae_s32 se = sxp->parts.sign_exponent; - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; - se = (se & 0x7fff) << 1; - lx |= hx & 0x7fffffff; - se |= (uae_u32)(lx | (-lx)) >> 31; - se = 0xfffe - se; - // TODO: check whether rshift count is 16 or 31 - return (((uae_u32)(se)) >> 16) != 0; -#endif -#else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX) -#else - fp_declare_init_shape(sxp, r, double); - return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX) -#endif - && (sxp->ieee_nan.mantissa0 != 0) - && (sxp->ieee_nan.mantissa1 != 0) -#ifdef USE_QUAD_DOUBLE - && (sxp->ieee_nan.mantissa2 != 0) - && (sxp->ieee_nan.mantissa3 != 0) -#endif - ; -#endif -} - -#undef isinf -#if 0 && defined(HAVE_ISINFL) -# define isinf(x) isinfl((x)) -#else -# define isinf(x) fp_do_isinf((x)) -#endif - -PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r) -{ -#ifdef BRANCHES_ARE_EXPENSIVE -#ifndef USE_LONG_DOUBLE - fp_declare_init_shape(sxp, r, double); - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; - lx |= (hx & 0x7fffffff) ^ 0x7ff00000; - lx |= -lx; - return (~(lx >> 31) & (hx >> 30)) != 0; -#elif USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - uae_s64 hx = sxp->parts64.msw; - uae_s64 lx = sxp->parts64.lsw; - lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL; - lx |= -lx; - return (~(lx >> 63) & (hx >> 62)) != 0; -#else - fp_declare_init_shape(sxp, r, extended); - uae_s32 se = sxp->parts.sign_exponent; - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; - /* This additional ^ 0x80000000 is necessary because in Intel's - internal representation of the implicit one is explicit. - NOTE: anyway, this is equivalent to & 0x7fffffff in that case. */ -#ifdef __i386__ - lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff); -#else - lx |= (hx & 0x7fffffff) | ((se & 0x7fff) ^ 0x7fff); -#endif - lx |= -lx; - se &= 0x8000; - return (~(lx >> 31) & (1 - (se >> 14))) != 0; -#endif -#else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX) -#else - fp_declare_init_shape(sxp, r, double); - return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX) -#endif - && (sxp->ieee_nan.mantissa0 == 0) - && (sxp->ieee_nan.mantissa1 == 0) -#ifdef USE_QUAD_DOUBLE - && (sxp->ieee_nan.mantissa2 == 0) - && (sxp->ieee_nan.mantissa3 == 0) -#endif - ; -#endif -} - -#undef isneg -#define isneg(x) fp_do_isneg((x)) - -PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); -#else - fp_declare_init_shape(sxp, r, double); -#endif - return sxp->ieee.negative; -} - -#undef iszero -#define iszero(x) fp_do_iszero((x)) - -PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r) -{ - // TODO: BRANCHES_ARE_EXPENSIVE -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); -#else - fp_declare_init_shape(sxp, r, double); -#endif - return (sxp->ieee.exponent == 0) - && (sxp->ieee.mantissa0 == 0) - && (sxp->ieee.mantissa1 == 0) -#ifdef USE_QUAD_DOUBLE - && (sxp->ieee.mantissa2 == 0) - && (sxp->ieee.mantissa3 == 0) -#endif - ; -} - -PRIVATE inline void FFPU get_dest_flags(fpu_register const & r) -{ - fl_dest.negative = isneg(r); - fl_dest.zero = iszero(r); - fl_dest.infinity = isinf(r); - fl_dest.nan = isnan(r); - fl_dest.in_range = !fl_dest.zero && !fl_dest.infinity && !fl_dest.nan; -} - -PRIVATE inline void FFPU get_source_flags(fpu_register const & r) -{ - fl_source.negative = isneg(r); - fl_source.zero = iszero(r); - fl_source.infinity = isinf(r); - fl_source.nan = isnan(r); - fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan; -} - -PRIVATE inline void FFPU make_nan(fpu_register & r) -{ - // FIXME: is that correct ? -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee.exponent = FP_EXTENDED_EXP_MAX; - sxp->ieee.mantissa0 = 0xffffffff; -#else - fp_declare_init_shape(sxp, r, double); - sxp->ieee.exponent = FP_DOUBLE_EXP_MAX; - sxp->ieee.mantissa0 = 0xfffff; -#endif - sxp->ieee.mantissa1 = 0xffffffff; -#ifdef USE_QUAD_DOUBLE - sxp->ieee.mantissa2 = 0xffffffff; - sxp->ieee.mantissa3 = 0xffffffff; -#endif -} - -PRIVATE inline void FFPU make_zero_positive(fpu_register & r) -{ -#if 1 - r = +0.0; -#else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); -#else - fp_declare_init_shape(sxp, r, double); -#endif - sxp->ieee.negative = 0; - sxp->ieee.exponent = 0; - sxp->ieee.mantissa0 = 0; - sxp->ieee.mantissa1 = 0; -#ifdef USE_QUAD_DOUBLE - sxp->ieee.mantissa2 = 0; - sxp->ieee.mantissa3 = 0; -#endif -#endif -} - -PRIVATE inline void FFPU make_zero_negative(fpu_register & r) -{ -#if 1 - r = -0.0; -#else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); -#else - fp_declare_init_shape(sxp, r, double); -#endif - sxp->ieee.negative = 1; - sxp->ieee.exponent = 0; - sxp->ieee.mantissa0 = 0; - sxp->ieee.mantissa1 = 0; -#ifdef USE_QUAD_DOUBLE - sxp->ieee.mantissa2 = 0; - sxp->ieee.mantissa3 = 0; -#endif -#endif -} - -PRIVATE inline void FFPU make_inf_positive(fpu_register & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; -#else - fp_declare_init_shape(sxp, r, double); - sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; -#endif - sxp->ieee_nan.negative = 0; - sxp->ieee_nan.mantissa0 = 0; - sxp->ieee_nan.mantissa1 = 0; -#ifdef USE_QUAD_DOUBLE - sxp->ieee_nan.mantissa2 = 0; - sxp->ieee_nan.mantissa3 = 0; -#endif -} - -PRIVATE inline void FFPU make_inf_negative(fpu_register & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; -#else - fp_declare_init_shape(sxp, r, double); - sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; -#endif - sxp->ieee_nan.negative = 1; - sxp->ieee_nan.mantissa0 = 0; - sxp->ieee_nan.mantissa1 = 0; -#ifdef USE_QUAD_DOUBLE - sxp->ieee_nan.mantissa2 = 0; - sxp->ieee_nan.mantissa3 = 0; -#endif -} - -PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - return (sxp->ieee.exponent - FP_EXTENDED_EXP_BIAS); -#else - fp_declare_init_shape(sxp, r, double); - return (sxp->ieee.exponent - FP_DOUBLE_EXP_BIAS); -#endif -} - -// Normalize to range 1..2 -PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee.exponent = FP_EXTENDED_EXP_BIAS; -#else - fp_declare_init_shape(sxp, r, double); - sxp->ieee.exponent = FP_DOUBLE_EXP_BIAS; -#endif -} - -// The sign of the quotient is the exclusive-OR of the sign bits -// of the source and destination operands. -PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sap, ra, extended); - fp_declare_init_shape(sbp, rb, extended); -#else - fp_declare_init_shape(sap, ra, double); - fp_declare_init_shape(sbp, rb, double); -#endif - return ((sap->ieee.negative ^ sbp->ieee.negative) ? FPSR_QUOTIENT_SIGN : 0); -} - -/* -------------------------------------------------------------------------- */ -/* --- Math functions --- */ -/* -------------------------------------------------------------------------- */ - -#if FPU_USE_ISO_C99 -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE -# ifdef HAVE_LOGL -# define fp_log logl -# endif -# ifdef HAVE_LOG10L -# define fp_log10 log10l -# endif -# ifdef HAVE_EXPL -# define fp_exp expl -# endif -# ifdef HAVE_POWL -# define fp_pow powl -# endif -# ifdef HAVE_FABSL -# define fp_fabs fabsl -# endif -# ifdef HAVE_SQRTL -# define fp_sqrt sqrtl -# endif -# ifdef HAVE_SINL -# define fp_sin sinl -# endif -# ifdef HAVE_COSL -# define fp_cos cosl -# endif -# ifdef HAVE_TANL -# define fp_tan tanl -# endif -# ifdef HAVE_SINHL -# define fp_sinh sinhl -# endif -# ifdef HAVE_COSHL -# define fp_cosh coshl -# endif -# ifdef HAVE_TANHL -# define fp_tanh tanhl -# endif -# ifdef HAVE_ASINL -# define fp_asin asinl -# endif -# ifdef HAVE_ACOSL -# define fp_acos acosl -# endif -# ifdef HAVE_ATANL -# define fp_atan atanl -# endif -# ifdef HAVE_ASINHL -# define fp_asinh asinhl -# endif -# ifdef HAVE_ACOSHL -# define fp_acosh acoshl -# endif -# ifdef HAVE_ATANHL -# define fp_atanh atanhl -# endif -# ifdef HAVE_FLOORL -# define fp_floor floorl -# endif -# ifdef HAVE_CEILL -# define fp_ceil ceill -# endif -#endif - -#ifndef fp_log -# define fp_log log -#endif -#ifndef fp_log10 -# define fp_log10 log10 -#endif -#ifndef fp_exp -# define fp_exp exp -#endif -#ifndef fp_pow -# define fp_pow pow -#endif -#ifndef fp_fabs -# define fp_fabs fabs -#endif -#ifndef fp_sqrt -# define fp_sqrt sqrt -#endif -#ifndef fp_sin -# define fp_sin sin -#endif -#ifndef fp_cos -# define fp_cos cos -#endif -#ifndef fp_tan -# define fp_tan tan -#endif -#ifndef fp_sinh -# define fp_sinh sinh -#endif -#ifndef fp_cosh -# define fp_cosh cosh -#endif -#ifndef fp_tanh -# define fp_tanh tanh -#endif -#ifndef fp_asin -# define fp_asin asin -#endif -#ifndef fp_acos -# define fp_acos acos -#endif -#ifndef fp_atan -# define fp_atan atan -#endif -#ifndef fp_asinh -# define fp_asinh asinh -#endif -#ifndef fp_acosh -# define fp_acosh acosh -#endif -#ifndef fp_atanh -# define fp_atanh atanh -#endif -#ifndef fp_floor -# define fp_floor floor -#endif -#ifndef fp_ceil -# define fp_ceil ceil -#endif - -#elif defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) -// Assembly optimized support functions. Taken from glibc 2.2.2 - -#undef fp_log -#define fp_log fp_do_log - -#if !FPU_FAST_MATH -PRIVATE fpu_extended fp_do_log(fpu_extended x); -#else -PRIVATE inline fpu_extended fp_do_log(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)"); - return value; -} -#endif - -#undef fp_log10 -#define fp_log10 fp_do_log10 - -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_log10(fpu_extended x); -#else -PRIVATE inline fpu_extended fp_do_log10(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fldlg2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)"); - return value; -} -#endif - -#undef fp_exp -#define fp_exp fp_do_exp - -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_exp(fpu_extended x); -#else -PRIVATE inline fpu_extended fp_do_exp(fpu_extended x) -{ - fpu_extended value, exponent; - __asm__ __volatile__("fldl2e # e^x = 2^(x * log2(e))\n\t" - "fmul %%st(1) # x * log2(e)\n\t" - "fst %%st(1)\n\t" - "frndint # int(x * log2(e))\n\t" - "fxch\n\t" - "fsub %%st(1) # fract(x * log2(e))\n\t" - "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" - : "=t" (value), "=u" (exponent) : "0" (x)); - value += 1.0; - __asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent)); - return value; -} -#endif - -#undef fp_pow -#define fp_pow fp_do_pow - -PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y); - -#undef fp_fabs -#define fp_fabs fp_do_fabs - -PRIVATE inline fpu_extended fp_do_fabs(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fabs" : "=t" (value) : "0" (x)); - return value; -} - -#undef fp_sqrt -#define fp_sqrt fp_do_sqrt - -PRIVATE inline fpu_extended fp_do_sqrt(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fsqrt" : "=t" (value) : "0" (x)); - return value; -} - -#undef fp_sin -#define fp_sin fp_do_sin - -PRIVATE inline fpu_extended fp_do_sin(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fsin" : "=t" (value) : "0" (x)); - return value; -} - -#undef fp_cos -#define fp_cos fp_do_cos - -PRIVATE inline fpu_extended fp_do_cos(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fcos" : "=t" (value) : "0" (x)); - return value; -} - -#undef fp_tan -#define fp_tan fp_do_tan - -PRIVATE inline fpu_extended fp_do_tan(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fptan" : "=t" (value) : "0" (x)); - return value; -} - -#undef fp_expm1 -#define fp_expm1 fp_do_expm1 - -// Returns: exp(X) - 1.0 -PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) -{ - fpu_extended value, exponent, temp; - __asm__ __volatile__("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" - "fmul %%st(1) # x * log2(e)\n\t" - "fst %%st(1)\n\t" - "frndint # int(x * log2(e))\n\t" - "fxch\n\t" - "fsub %%st(1) # fract(x * log2(e))\n\t" - "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" - "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" - : "=t" (value), "=u" (exponent) : "0" (x)); - __asm__ __volatile__("fscale" : "=t" (temp) : "0" (1.0), "u" (exponent)); - temp -= 1.0; - return temp + value ? temp + value : x; -} - -#undef fp_sgn1 -#define fp_sgn1 fp_do_sgn1 - -PRIVATE inline fpu_extended fp_do_sgn1(fpu_extended x) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, x, extended); - sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; - sxp->ieee_nan.one = 1; -#else - fp_declare_init_shape(sxp, x, double); - sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; -#endif - sxp->ieee_nan.quiet_nan = 0; - sxp->ieee_nan.mantissa0 = 0; - sxp->ieee_nan.mantissa1 = 0; - return x; -} - -#undef fp_sinh -#define fp_sinh fp_do_sinh - -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_sinh(fpu_extended x); -#else -PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x) -{ - fpu_extended exm1 = fp_expm1(fp_fabs(x)); - return 0.5 * (exm1 / (exm1 + 1.0) + exm1) * fp_sgn1(x); -} -#endif - -#undef fp_cosh -#define fp_cosh fp_do_cosh - -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_cosh(fpu_extended x); -#else -PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x) -{ - fpu_extended ex = fp_exp(x); - return 0.5 * (ex + 1.0 / ex); -} -#endif - -#undef fp_tanh -#define fp_tanh fp_do_tanh - -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_tanh(fpu_extended x); -#else -PRIVATE inline fpu_extended fp_do_tanh(fpu_extended x) -{ - fpu_extended exm1 = fp_expm1(-fp_fabs(x + x)); - return exm1 / (exm1 + 2.0) * fp_sgn1(-x); -} -#endif - -#undef fp_atan2 -#define fp_atan2 fp_do_atan2 - -PRIVATE inline fpu_extended fp_do_atan2(fpu_extended y, fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fpatan" : "=t" (value) : "0" (x), "u" (y) : "st(1)"); - return value; -} - -#undef fp_asin -#define fp_asin fp_do_asin - -PRIVATE inline fpu_extended fp_do_asin(fpu_extended x) -{ - return fp_atan2(x, fp_sqrt(1.0 - x * x)); -} - -#undef fp_acos -#define fp_acos fp_do_acos - -PRIVATE inline fpu_extended fp_do_acos(fpu_extended x) -{ - return fp_atan2(fp_sqrt(1.0 - x * x), x); -} - -#undef fp_atan -#define fp_atan fp_do_atan - -PRIVATE inline fpu_extended fp_do_atan(fpu_extended x) -{ - fpu_extended value; - __asm__ __volatile__("fld1; fpatan" : "=t" (value) : "0" (x) : "st(1)"); - return value; -} - -#undef fp_log1p -#define fp_log1p fp_do_log1p - -// Returns: ln(1.0 + X) -PRIVATE fpu_extended fp_do_log1p(fpu_extended x); - -#undef fp_asinh -#define fp_asinh fp_do_asinh - -PRIVATE inline fpu_extended fp_do_asinh(fpu_extended x) -{ - fpu_extended y = fp_fabs(x); - return (fp_log1p(y * y / (fp_sqrt(y * y + 1.0) + 1.0) + y) * fp_sgn1(x)); -} - -#undef fp_acosh -#define fp_acosh fp_do_acosh - -PRIVATE inline fpu_extended fp_do_acosh(fpu_extended x) -{ - return fp_log(x + fp_sqrt(x - 1.0) * fp_sqrt(x + 1.0)); -} - -#undef fp_atanh -#define fp_atanh fp_do_atanh - -PRIVATE inline fpu_extended fp_do_atanh(fpu_extended x) -{ - fpu_extended y = fp_fabs(x); - return -0.5 * fp_log1p(-(y + y) / (1.0 + y)) * fp_sgn1(x); -} - -#undef fp_floor -#define fp_floor fp_do_floor - -PRIVATE inline fpu_extended fp_do_floor(fpu_extended x) -{ - volatile unsigned int cw; - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); - volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0400; // rounding down - __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); - fpu_extended value; - __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); - __asm__ __volatile__("fldcw %0" : : "m" (cw)); - return value; -} - -#undef fp_ceil -#define fp_ceil fp_do_ceil - -PRIVATE inline fpu_extended fp_do_ceil(fpu_extended x) -{ - volatile unsigned int cw; - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); - volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0800; // rounding up - __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); - fpu_extended value; - __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); - __asm__ __volatile__("fldcw %0" : : "m" (cw)); - return value; -} - -#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ -PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended x) \ -{ \ - volatile unsigned int cw; \ - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); \ - volatile unsigned int cw_temp = (cw & 0xf3ff) | (rounding_mode); \ - __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); \ - fpu_extended value; \ - __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); \ - __asm__ __volatile__("fldcw %0" : : "m" (cw)); \ - return value; \ -} - -#undef fp_round_to_minus_infinity -#define fp_round_to_minus_infinity fp_do_round_to_minus_infinity - -DEFINE_ROUND_FUNC(minus_infinity, 0x400) - -#undef fp_round_to_plus_infinity -#define fp_round_to_plus_infinity fp_do_round_to_plus_infinity - -DEFINE_ROUND_FUNC(plus_infinity, 0x800) - -#undef fp_round_to_zero -#define fp_round_to_zero fp_do_round_to_zero - -DEFINE_ROUND_FUNC(zero, 0xc00) - -#undef fp_round_to_nearest -#define fp_round_to_nearest fp_do_round_to_nearest - -DEFINE_ROUND_FUNC(nearest, 0x000) - -#endif /* USE_X87_ASSEMBLY */ - -#ifndef fp_round_to_minus_infinity -#define fp_round_to_minus_infinity(x) fp_floor(x) -#endif - -#ifndef fp_round_to_plus_infinity -#define fp_round_to_plus_infinity(x) fp_ceil(x) -#endif - -#ifndef fp_round_to_zero -#define fp_round_to_zero(x) ((int)(x)) -#endif - -#ifndef fp_round_to_nearest -#define fp_round_to_nearest(x) ((int)((x) + 0.5)) -#endif - -#endif /* FPU_MATHLIB_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.cpp b/BasiliskII/src/uae_cpu/fpu/rounding.cpp deleted file mode 100644 index 1f8b3618..00000000 --- a/BasiliskII/src/uae_cpu/fpu/rounding.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * fpu/rounding.cpp - system-dependant FPU rounding mode and precision - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#undef PRIVATE -#define PRIVATE /**/ - -#undef PUBLIC -#define PUBLIC /**/ - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* -------------------------------------------------------------------------- */ -/* --- Native X86 Rounding Mode --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_X86_ROUNDING_MODE -const uae_u32 FFPU x86_control_word_rm_mac2host[] = { - CW_RC_NEAR, - CW_RC_ZERO, - CW_RC_DOWN, - CW_RC_UP -}; -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Native X86 Rounding Precision --- */ -/* -------------------------------------------------------------------------- */ - -#ifdef FPU_USE_X86_ROUNDING_PRECISION -const uae_u32 FFPU x86_control_word_rp_mac2host[] = { - CW_PC_EXTENDED, - CW_PC_SINGLE, - CW_PC_DOUBLE, - CW_PC_RESERVED -}; -#endif diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.h b/BasiliskII/src/uae_cpu/fpu/rounding.h deleted file mode 100644 index 67db5519..00000000 --- a/BasiliskII/src/uae_cpu/fpu/rounding.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * fpu/rounding.h - system-dependant FPU rounding mode and precision - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_ROUNDING_H -#define FPU_ROUNDING_H - -/* NOTE: this file shall be included from fpu/fpu_*.cpp */ -#undef PUBLIC -#define PUBLIC extern - -#undef PRIVATE -#define PRIVATE static - -#undef FFPU -#define FFPU /**/ - -#undef FPU -#define FPU fpu. - -/* Defaults to generic rounding mode and precision handling */ -#define FPU_USE_GENERIC_ROUNDING_MODE -#define FPU_USE_GENERIC_ROUNDING_PRECISION - -/* -------------------------------------------------------------------------- */ -/* --- Selection of floating-point rounding mode and precision --- */ -/* -------------------------------------------------------------------------- */ - -/* Optimized i386 fpu core must use native rounding mode */ -#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_ROUNDING_MODE -# define FPU_USE_X86_ROUNDING_MODE -#endif - -/* Optimized i386 fpu core must use native rounding precision */ -#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_ROUNDING_PRECISION -# define FPU_USE_X86_ROUNDING_PRECISION -#endif - -#if 0 // gb-- FIXME: that doesn't work -/* IEEE-based fpu core can have native rounding mode on i386 */ -#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_ROUNDING_MODE -# define FPU_USE_X86_ROUNDING_MODE -#endif - -/* IEEE-based fpu core can have native rounding precision on i386 */ -#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) -# undef FPU_USE_GENERIC_ROUNDING_PRECISION -# define FPU_USE_X86_ROUNDING_PRECISION -#endif -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Sanity checks --- */ -/* -------------------------------------------------------------------------- */ - -/* X86 rounding mode and precision work together */ -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) -# define FPU_USE_X86_ROUNDING -# define CW_INITIAL (CW_RESET|CW_X|CW_PC_EXTENDED|CW_RC_NEAR|CW_PM|CW_UM|CW_OM|CW_ZM|CW_DM|CW_IM) - PRIVATE uae_u32 x86_control_word; -#endif - -/* Control word -- rounding mode */ -#ifdef FPU_USE_X86_ROUNDING_MODE -PUBLIC const uae_u32 x86_control_word_rm_mac2host[]; -#endif - -/* Control word -- rounding precision */ -#ifdef FPU_USE_X86_ROUNDING_PRECISION -PUBLIC const uae_u32 x86_control_word_rp_mac2host[]; -#endif - -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) -/* Set host control word for rounding mode and rounding precision */ -PRIVATE inline void set_host_control_word(void) -{ - /* - Exception enable byte is ignored, but the same value is returned - that was previously set. - */ - x86_control_word - = (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION)) - | x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4] - | x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6] - ; - __asm__ __volatile__("fldcw %0" : : "m" (x86_control_word)); -} -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Generic rounding mode and precision --- */ -/* -------------------------------------------------------------------------- */ - -#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION) -/* Set host control word for rounding mode and rounding precision */ -PRIVATE inline void set_host_control_word(void) - { } -#endif - -/* -------------------------------------------------------------------------- */ -/* --- Common rounding mode and precision --- */ -/* -------------------------------------------------------------------------- */ - -#if defined(FPU_USE_GENERIC_ROUNDING_MODE) || defined(FPU_USE_X86_ROUNDING_MODE) - -/* Return the current rounding mode in m68k format */ -static inline uae_u32 FFPU get_rounding_mode(void) - { return FPU fpcr.rounding_mode; } - -/* Convert and set to native rounding mode */ -static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode) - { FPU fpcr.rounding_mode = new_rounding_mode; } - -#endif - -#if defined(FPU_USE_GENERIC_ROUNDING_PRECISION) || defined(FPU_USE_X86_ROUNDING_PRECISION) - -/* Return the current rounding precision in m68k format */ -static inline uae_u32 FFPU get_rounding_precision(void) - { return FPU fpcr.rounding_precision; } - -/* Convert and set to native rounding precision */ -static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision) - { FPU fpcr.rounding_precision = new_rounding_precision; } - -#endif - -#endif /* FPU_ROUNDING_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h deleted file mode 100644 index 5f708048..00000000 --- a/BasiliskII/src/uae_cpu/fpu/types.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * types.h - basic types for fpu registers - * - * Basilisk II (C) 1997-2008 Christian Bauer - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef FPU_TYPES_H -#define FPU_TYPES_H - -#include "sysdeps.h" - -/* Default behavior is *not* to use long doubles */ -#undef USE_LONG_DOUBLE -#undef USE_QUAD_DOUBLE - -/* -------------------------------------------------------------------------- */ -/* --- Original UAE fpu core --- */ -/* -------------------------------------------------------------------------- */ - -#if defined(FPU_UAE) - -/* 4-byte floats */ -typedef float uae_f32; - -/* 8-byte floats */ -typedef double uae_f64; - -/* Original UAE FPU registers are only 8 bytes long */ -typedef uae_f64 fpu_register; -typedef fpu_register fpu_extended; -typedef uae_f64 fpu_double; -typedef uae_f32 fpu_single; - -/* -------------------------------------------------------------------------- */ -/* --- Optimized core for x86 --- */ -/* -------------------------------------------------------------------------- */ - -#elif defined(FPU_X86) - -/* 4-byte floats */ -typedef float uae_f32; - -/* 8-byte floats */ -typedef double uae_f64; - -/* At least 10-byte floats are required */ -#if SIZEOF_LONG_DOUBLE >= 10 -typedef long double fpu_register; -#else -#error "No float type at least 10 bytes long, you lose." -#endif - -/* X86 FPU has a custom register type that maps to a native X86 register */ -typedef fpu_register fpu_extended; -typedef uae_f64 fpu_double; -typedef uae_f32 fpu_single; - -/* -------------------------------------------------------------------------- */ -/* --- C99 implementation --- */ -/* -------------------------------------------------------------------------- */ - -#elif defined(FPU_IEEE) - -#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT -#error "No IEEE float format, you lose." -#endif - -/* 4-byte floats */ -#if SIZEOF_FLOAT == 4 -typedef float uae_f32; -#elif SIZEOF_DOUBLE == 4 -typedef double uae_f32; -#else -#error "No 4 byte float type, you lose." -#endif - -/* 8-byte floats */ -#if SIZEOF_DOUBLE == 8 -typedef double uae_f64; -#elif SIZEOF_LONG_DOUBLE == 8 -typedef long double uae_f64; -#else -#error "No 8 byte float type, you lose." -#endif - -/* 12-byte or 16-byte floats */ -#if SIZEOF_LONG_DOUBLE == 12 -typedef long double uae_f96; -typedef uae_f96 fpu_register; -#define USE_LONG_DOUBLE 1 -#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__)) -/* Long doubles on x86-64 are really held in old x87 FPU stack. */ -typedef long double uae_f128; -typedef uae_f128 fpu_register; -#define USE_LONG_DOUBLE 1 -#elif 0 -/* Disable for now and probably for good as (i) the emulator - implementation is not correct, (ii) I don't know of any CPU which - handles this kind of format *natively* with conformance to IEEE. */ -typedef long double uae_f128; -typedef uae_f128 fpu_register; -#define USE_QUAD_DOUBLE 1 -#else -typedef uae_f64 fpu_register; -#endif - -/* We need all those floating-point types */ -typedef fpu_register fpu_extended; -typedef uae_f64 fpu_double; -typedef uae_f32 fpu_single; - -#endif - -#endif /* FPU_TYPES_H */ diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 3030258f..8e2502a3 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -14,21 +14,6 @@ * take care of this. * * Copyright 1995, 1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include @@ -45,9 +30,6 @@ #define BOOL_TYPE "int" -/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ -#define xBCD_KEEPS_NV_FLAGS 4 - static FILE *headerfile; static FILE *stblfile; @@ -239,8 +221,7 @@ static void sync_m68k_pc (void) } /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, - * the calling routine handles Apdi and Aipi modes. - * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ + * the calling routine handles Apdi and Aipi modes. */ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) { start_brace (); @@ -586,7 +567,7 @@ static void duplicate_carry (void) } typedef enum { - flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_z, flag_zn, + flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn, flag_av, flag_sv } flagtypes; @@ -640,7 +621,6 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * switch (type) { case flag_logical_noclobber: case flag_logical: - case flag_z: case flag_zn: case flag_av: case flag_sv: @@ -662,7 +642,6 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * switch (type) { case flag_logical_noclobber: case flag_logical: - case flag_z: case flag_zn: break; @@ -696,9 +675,6 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * case flag_sv: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n"); break; - case flag_z: - printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr); - break; case flag_zn: printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr); printf ("\tSET_NFLG (%s < 0);\n", vstr); @@ -738,16 +714,163 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * static void genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst) { - /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have - them in the appropriate m68k.h files and use just one copy of this - code here. The API can be changed if necessary. */ -#ifdef OPTIMIZED_FLAGS +#ifdef SPARC_V8_ASSEMBLY + switch(type) + { + case flag_add: + start_brace(); + printf("\tuae_u32 %s;\n", value); + switch(size) + { + case sz_byte: + printf("\t%s = sparc_v8_flag_add_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_word: + printf("\t%s = sparc_v8_flag_add_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_long: + printf("\t%s = sparc_v8_flag_add_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + } + return; + + case flag_sub: + start_brace(); + printf("\tuae_u32 %s;\n", value); + switch(size) + { + case sz_byte: + printf("\t%s = sparc_v8_flag_sub_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_word: + printf("\t%s = sparc_v8_flag_sub_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_long: + printf("\t%s = sparc_v8_flag_sub_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + } + return; + + case flag_cmp: + switch(size) + { + case sz_byte: +// printf("\tsparc_v8_flag_cmp_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); + break; + case sz_word: +// printf("\tsparc_v8_flag_cmp_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); + break; + case sz_long: +#if 1 + printf("\tsparc_v8_flag_cmp_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); + return; +#endif + break; + } +// return; + break; + } +#elif defined(SPARC_V9_ASSEMBLY) + switch(type) + { + case flag_add: + start_brace(); + printf("\tuae_u32 %s;\n", value); + switch(size) + { + case sz_byte: + printf("\t%s = sparc_v9_flag_add_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_word: + printf("\t%s = sparc_v9_flag_add_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_long: + printf("\t%s = sparc_v9_flag_add_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + } + return; + + case flag_sub: + start_brace(); + printf("\tuae_u32 %s;\n", value); + switch(size) + { + case sz_byte: + printf("\t%s = sparc_v9_flag_sub_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_word: + printf("\t%s = sparc_v9_flag_sub_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + case sz_long: + printf("\t%s = sparc_v9_flag_sub_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); + break; + } + return; + + case flag_cmp: + switch(size) + { + case sz_byte: + printf("\tsparc_v9_flag_cmp_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); + break; + case sz_word: + printf("\tsparc_v9_flag_cmp_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); + break; + case sz_long: + printf("\tsparc_v9_flag_cmp_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); + break; + } + return; + + case flag_logical: + if (strcmp(value, "0") == 0) { + printf("\tregflags.nzvc = 0x04;\n"); + } else { + switch(size) { + case sz_byte: + printf("\tsparc_v9_flag_test_8(®flags, (uae_u32)(%s));\n", value); + break; + case sz_word: + printf("\tsparc_v9_flag_test_16(®flags, (uae_u32)(%s));\n", value); + break; + case sz_long: + printf("\tsparc_v9_flag_test_32(®flags, (uae_u32)(%s));\n", value); + break; + } + } + return; + +#if 0 + case flag_logical_noclobber: + printf("\t{uae_u32 old_flags = regflags.nzvc & ~0x0C;\n"); + if (strcmp(value, "0") == 0) { + printf("\tregflags.nzvc = old_flags | 0x04;\n"); + } else { + switch(size) { + case sz_byte: + printf("\tsparc_v9_flag_test_8(®flags, (uae_u32)(%s));\n", value); + break; + case sz_word: + printf("\tsparc_v9_flag_test_16(®flags, (uae_u32)(%s));\n", value); + break; + case sz_long: + printf("\tsparc_v9_flag_test_32(®flags, (uae_u32)(%s));\n", value); + break; + } + printf("\tregflags.nzvc |= old_flags;\n"); + } + printf("\t}\n"); + return; +#endif + } +#elif defined(X86_ASSEMBLY) switch (type) { case flag_add: case flag_sub: start_brace (); printf ("\tuae_u32 %s;\n", value); break; + default: break; } @@ -755,59 +878,231 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch /* At least some of those casts are fairly important! */ switch (type) { case flag_logical_noclobber: - printf ("\t{uae_u32 oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n"); + printf ("\t{uae_u32 oldcznv = regflags.cznv & ~0xC0;\n"); if (strcmp (value, "0") == 0) { - printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n"); + printf ("\tregflags.cznv = olcznv | 64;\n"); } else { switch (size) { - case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break; - case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break; - case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; + case sz_byte: printf ("\tx86_flag_testb ((uae_s8)(%s));\n", value); break; + case sz_word: printf ("\tx86_flag_testw ((uae_s16)(%s));\n", value); break; + case sz_long: printf ("\tx86_flag_testl ((uae_s32)(%s));\n", value); break; } - printf ("\tIOR_CZNV (oldcznv);\n"); + printf ("\tregflags.cznv |= oldcznv;\n"); } printf ("\t}\n"); return; - case flag_logical: if (strcmp (value, "0") == 0) { - printf ("\tSET_CZNV (FLAGVAL_Z);\n"); + printf ("\tregflags.cznv = 64;\n"); } else { switch (size) { - case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break; - case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break; - case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; + case sz_byte: printf ("\tx86_flag_testb ((uae_s8)(%s));\n", value); break; + case sz_word: printf ("\tx86_flag_testw ((uae_s16)(%s));\n", value); break; + case sz_long: printf ("\tx86_flag_testl ((uae_s32)(%s));\n", value); break; } } return; case flag_add: switch (size) { - case sz_byte: printf ("\toptflag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; - case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; - case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; + case sz_byte: printf ("\tx86_flag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; + case sz_word: printf ("\tx86_flag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; + case sz_long: printf ("\tx86_flag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } return; case flag_sub: switch (size) { - case sz_byte: printf ("\toptflag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; - case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; - case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; + case sz_byte: printf ("\tx86_flag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; + case sz_word: printf ("\tx86_flag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; + case sz_long: printf ("\tx86_flag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } return; case flag_cmp: switch (size) { - case sz_byte: printf ("\toptflag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break; - case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; - case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; + case sz_byte: printf ("\tx86_flag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break; + case sz_word: printf ("\tx86_flag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; + case sz_long: printf ("\tx86_flag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; } return; default: break; } +#elif defined(M68K_FLAG_OPT) + /* sam: here I'm cloning what X86_ASSEMBLY does */ +#define EXT(size) (size==sz_byte?"b":(size==sz_word?"w":"l")) +#define CAST(size) (size==sz_byte?"uae_s8":(size==sz_word?"uae_s16":"uae_s32")) + switch (type) { + case flag_add: + case flag_sub: + start_brace (); + printf ("\tuae_u32 %s;\n", value); + break; + + default: + break; + } + + switch (type) { + case flag_logical: + if (strcmp (value, "0") == 0) { + printf ("\t*(uae_u16 *)®flags = 4;\n"); /* Z = 1 */ + } else { + printf ("\tm68k_flag_tst (%s, (%s)(%s));\n", + EXT (size), CAST (size), value); + } + return; + + case flag_add: + printf ("\t{uae_u16 ccr;\n"); + printf ("\tm68k_flag_add (%s, (%s)%s, (%s)(%s), (%s)(%s));\n", + EXT (size), CAST (size), value, CAST (size), src, CAST (size), dst); + printf ("\t((uae_u16*)®flags)[1]=((uae_u16*)®flags)[0]=ccr;}\n"); + return; + + case flag_sub: + printf ("\t{uae_u16 ccr;\n"); + printf ("\tm68k_flag_sub (%s, (%s)%s, (%s)(%s), (%s)(%s));\n", + EXT (size), CAST (size), value, CAST (size), src, CAST (size), dst); + printf ("\t((uae_u16*)®flags)[1]=((uae_u16*)®flags)[0]=ccr;}\n"); + return; + + case flag_cmp: + printf ("\tm68k_flag_cmp (%s, (%s)(%s), (%s)(%s));\n", + EXT (size), CAST (size), src, CAST (size), dst); + return; + + default: + break; + } +#elif defined(ACORN_FLAG_OPT) && defined(__GNUC_MINOR__) +/* + * This is new. Might be quite buggy. + */ + switch (type) { + case flag_av: + case flag_sv: + case flag_zn: + case flag_addx: + case flag_subx: + break; + + case flag_logical: + if (strcmp (value, "0") == 0) { + /* v=c=n=0 z=1 */ + printf ("\t*(ULONG*)®flags = 0x40000000;\n"); + return; + } else { + start_brace (); + switch (size) { + case sz_byte: + printf ("\tUBYTE ccr;\n"); + printf ("\tULONG shift;\n"); + printf ("\t__asm__(\"mov %%2,%%1,lsl#24\n\ttst %%2,%%2\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n" + "\t: \"=r\" (ccr) : \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value); + printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); + return; + case sz_word: + printf ("\tUBYTE ccr;\n"); + printf ("\tULONG shift;\n"); + printf ("\t__asm__(\"mov %%2,%%1,lsl#16\n\ttst %%2,%%2\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n" + "\t: \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value); + printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); + return; + case sz_long: + printf ("\tUBYTE ccr;\n"); + printf ("\t__asm__(\"tst %%1,%%1\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n" + "\t: \"=r\" (ccr) : \"r\" ((LONG)%s) : \"cc\" );\n", value); + printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); + return; + } + } + break; + case flag_add: + if (strcmp (dst, "0") == 0) { + printf ("/* Error! Hier muss Peter noch was machen !!! (ADD-Flags) */"); + } else { + start_brace (); + switch (size) { + case sz_byte: + printf ("\tULONG ccr, shift, %s;\n", value); + printf ("\t__asm__(\"mov %%4,%%3,lsl#24\n\tadds %%0,%%4,%%2,lsl#24\n\tmov %%0,%%0,asr#24\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n" + "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); + printf ("\t*(ULONG*)®flags = ccr;\n"); + return; + case sz_word: + printf ("\tULONG ccr, shift, %s;\n", value); + printf ("\t__asm__(\"mov %%4,%%3,lsl#16\n\tadds %%0,%%4,%%2,lsl#16\n\tmov %%0,%%0,asr#16\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n" + "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); + printf ("\t*(ULONG*)®flags = ccr;\n"); + return; + case sz_long: + printf ("\tULONG ccr, %s;\n", value); + printf ("\t__asm__(\"adds %%0,%%3,%%2\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n" + "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", value, src, dst); + printf ("\t*(ULONG*)®flags = ccr;\n"); + return; + } + } + break; + case flag_sub: + if (strcmp (dst, "0") == 0) { + printf ("/* Error! Hier muss Peter noch was machen !!! (SUB-Flags) */"); + } else { + start_brace (); + switch (size) { + case sz_byte: + printf ("\tULONG ccr, shift, %s;\n", value); + printf ("\t__asm__(\"mov %%4,%%3,lsl#24\n\tsubs %%0,%%4,%%2,lsl#24\n\tmov %%0,%%0,asr#24\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n" + "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); + printf ("\t*(ULONG*)®flags = ccr;\n"); + return; + case sz_word: + printf ("\tULONG ccr, shift, %s;\n", value); + printf ("\t__asm__(\"mov %%4,%%3,lsl#16\n\tsubs %%0,%%4,%%2,lsl#16\n\tmov %%0,%%0,asr#16\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n" + "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); + printf ("\t*(ULONG*)®flags = ccr;\n"); + return; + case sz_long: + printf ("\tULONG ccr, %s;\n", value); + printf ("\t__asm__(\"subs %%0,%%3,%%2\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n" + "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", value, src, dst); + printf ("\t*(ULONG*)®flags = ccr;\n"); + return; + } + } + break; + case flag_cmp: + if (strcmp (dst, "0") == 0) { + printf ("/*Error! Hier muss Peter noch was machen !!! (CMP-Flags)*/"); + } else { + start_brace (); + switch (size) { + case sz_byte: + printf ("\tULONG shift, ccr;\n"); + printf ("\t__asm__(\"mov %%3,%%2,lsl#24\n\tcmp %%3,%%1,lsl#24\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n" + "\t: \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", src, dst); + printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); + return; + case sz_word: + printf ("\tULONG shift, ccr;\n"); + printf ("\t__asm__(\"mov %%3,%%2,lsl#16\n\tcmp %%3,%%1,lsl#16\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n" + "\t: \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", src, dst); + printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); + return; + case sz_long: + printf ("\tULONG ccr;\n"); + printf ("\t__asm__(\"cmp %%2,%%1\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n" + "\t: \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", src, dst); + printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); + /*printf ("\tprintf (\"%%08x %%08x %%08x\\n\", %s, %s, *((ULONG*)®flags));\n", src, dst); */ + return; + } + } + break; + } #endif genflags_normal (type, size, value, src, dst); } @@ -932,28 +1227,21 @@ static void gen_opcode (unsigned long int opcode) genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_SBCD: + /* Let's hope this works... */ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n"); - printf ("\tuae_u16 newv, tmp_newv;\n"); - printf ("\tint bcd = 0;\n"); - printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); - printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n"); - printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); - printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n"); + printf ("\tuae_u16 newv;\n"); + printf ("\tint cflg;\n"); + printf ("\tif (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }\n"); + printf ("\tnewv = newv_hi + (newv_lo & 0xF);"); + printf ("\tSET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68040 don't change them */ - if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { - if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) - next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } - else { - genflags (flag_zn, curi->size, "newv", "", ""); - printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); - } + printf ("\tif (cflg) newv -= 0x60;\n"); + genflags (flag_zn, curi->size, "newv", "", ""); + genflags (flag_sv, curi->size, "newv", "src", "dst"); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ADD: @@ -985,24 +1273,15 @@ static void gen_opcode (unsigned long int opcode) start_brace (); printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); - printf ("\tuae_u16 newv, tmp_newv;\n"); + printf ("\tuae_u16 newv;\n"); printf ("\tint cflg;\n"); - printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); - printf ("\tif (newv_lo > 9) { newv += 6; }\n"); - printf ("\tcflg = (newv & 0x3F0) > 0x90;\n"); - printf ("\tif (cflg) newv += 0x60;\n"); - printf ("\tSET_CFLG (cflg);\n"); + printf ("\tif (newv_lo > 9) { newv_lo +=6; }\n"); + printf ("\tnewv = newv_hi + newv_lo;"); + printf ("\tSET_CFLG (cflg = (newv & 0x1F0) > 0x90);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68040 don't change them */ - if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { - if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) - next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } - else { - genflags (flag_zn, curi->size, "newv", "", ""); - printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); - } + printf ("\tif (cflg) newv += 0x60;\n"); + genflags (flag_zn, curi->size, "newv", "", ""); + genflags (flag_sv, curi->size, "newv", "src", "dst"); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_NEG: @@ -1026,21 +1305,12 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n"); printf ("\tuae_u16 newv;\n"); printf ("\tint cflg;\n"); - printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n"); - printf ("\tnewv = newv_hi + newv_lo;\n"); - printf ("\tcflg = (newv & 0x1F0) > 0x90;\n"); - printf ("\tif (cflg) newv -= 0x60;\n"); - printf ("\tSET_CFLG (cflg);\n"); + printf ("\tif (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }\n"); + printf ("\tnewv = newv_hi + (newv_lo & 0xF);"); + printf ("\tSET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);\n"); duplicate_carry(); - /* Manual says bits NV are undefined though a real 68040 don't change them */ - if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { - if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) - next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } - else { - genflags (flag_zn, curi->size, "newv", "", ""); - } + printf ("\tif (cflg) newv -= 0x60;\n"); + genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->smode, "srcreg", curi->size, "src"); break; case i_CLR: @@ -1076,7 +1346,7 @@ static void gen_opcode (unsigned long int opcode) else printf ("\tsrc &= 31;\n"); printf ("\tdst ^= (1 << src);\n"); - printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n"); + printf ("\tSET_ZFLG ((dst & (1 << src)) >> src);\n"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_BCLR: @@ -1199,10 +1469,10 @@ static void gen_opcode (unsigned long int opcode) curi->size == sz_word ? sz_word : sz_long, "src"); break; case i_MVMEL: - genmovemel ((uae_u16)opcode); + genmovemel (opcode); break; case i_MVMLE: - genmovemle ((uae_u16)opcode); + genmovemle (opcode); break; case i_TRAP: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1247,7 +1517,6 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); - /* gb-- the next two lines are deleted in Bernie's gencpu.c */ printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); @@ -1336,18 +1605,6 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_Bcc: - if (0 && !using_prefetch && !using_exception_3 && (cpu_level >= 2)) { - /* gb-- variant probably more favorable to compiler optimizations - also assumes no prefetch buffer is used - Hmm, that would make sense with processors capable of conditional moves */ - if (curi->size == sz_long && next_cpu_level < 1) - next_cpu_level = 1; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - printf ("\tm68k_incpc (cctrue(%d) ? ((uae_s32)src + 2) : %d);\n", curi->cc, m68k_pc_offset); - m68k_pc_offset = 0; - } - else { - /* original code for branch instructions */ if (curi->size == sz_long) { if (cpu_level < 2) { printf ("\tm68k_incpc(2);\n"); @@ -1373,10 +1630,9 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); fill_prefetch_0 (); - printf ("return;\n"); + printf ("\tgoto %s;\n", endlabelstr); printf ("didnt_jump:;\n"); need_endlabel = 1; - } break; case i_LEA: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); @@ -1406,7 +1662,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n"); fill_prefetch_0 (); - printf ("return;\n"); + printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t\t}\n"); printf ("\t}\n"); need_endlabel = 1; @@ -1421,10 +1677,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuaecptr oldpc = m68k_getpc();\n"); genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - sync_m68k_pc (); - /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends - * on this (actually, it's doing a DIVS). */ - printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc); goto %s; } else {\n", endlabelstr); + printf ("\tif(src == 0) { Exception(5,oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n"); printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n"); /* The N flag appears to be set each time there is an overflow. @@ -1442,8 +1695,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuaecptr oldpc = m68k_getpc();\n"); genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - sync_m68k_pc (); - printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr); + printf ("\tif(src == 0) { Exception(5,oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n"); printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); @@ -1504,7 +1756,7 @@ static void gen_opcode (unsigned long int opcode) abort (); } printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); - printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); + printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; @@ -1523,7 +1775,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); - printf ("\t\tval = %s & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size)); + printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size)); printf ("\t\tSET_CFLG (sign);\n"); duplicate_carry (); if (source_is_imm1_8 (curi)) @@ -1534,7 +1786,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tSET_CFLG (val & 1);\n"); duplicate_carry (); printf ("\t\tval >>= 1;\n"); - printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-(uae_s32)sign;\n", + printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n", bit_mask (curi->size), bit_size (curi->size)); printf ("\t\tval &= %s;\n", bit_mask (curi->size)); @@ -1703,12 +1955,12 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); + if (! source_is_imm1_8 (curi)) + force_range_for_rox ("cnt", curi->size); if (source_is_imm1_8 (curi)) printf ("{"); - else { - force_range_for_rox ("cnt", curi->size); + else printf ("\tif (cnt > 0) {\n"); - } printf ("\tcnt--;\n"); printf ("\t{\n\tuae_u32 carry;\n"); printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1); @@ -1733,12 +1985,12 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); + if (! source_is_imm1_8 (curi)) + force_range_for_rox ("cnt", curi->size); if (source_is_imm1_8 (curi)) printf ("{"); - else { - force_range_for_rox ("cnt", curi->size); + else printf ("\tif (cnt > 0) {\n"); - } printf ("\tcnt--;\n"); printf ("\t{\n\tuae_u32 carry;\n"); printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n"); @@ -1894,14 +2146,14 @@ static void gen_opcode (unsigned long int opcode) start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tm68k_movec2(src & 0xFFF, regp);\n"); break; case i_MOVE2C: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tm68k_move2c(src & 0xFFF, regp);\n"); break; case i_CAS: { @@ -2041,7 +2293,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n"); } printf ("\ttmp >>= (32 - width);\n"); - printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width-1)) ? 1 : 0);\n"); + printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n"); switch (curi->mnemo) { case i_BFTST: @@ -2069,8 +2321,6 @@ static void gen_opcode (unsigned long int opcode) break; case i_BFINS: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n"); - printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width - 1)) ? 1 : 0);\n"); - printf ("\tSET_ZFLG (tmp == 0);\n"); break; default: break; @@ -2141,19 +2391,19 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_arithmetic(opcode, extra);\n"); + printf ("\tfpp_opp(opcode,extra);\n"); break; case i_FDBcc: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_dbcc(opcode, extra);\n"); + printf ("\tfdbcc_opp(opcode,extra);\n"); break; case i_FScc: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_scc(opcode,extra);\n"); + printf ("\tfscc_opp(opcode,extra);\n"); break; case i_FTRAPcc: sync_m68k_pc (); @@ -2163,7 +2413,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_trapcc(opcode,oldpc);\n"); + printf ("\tftrapcc_opp(opcode,oldpc);\n"); break; case i_FBcc: sync_m68k_pc (); @@ -2172,59 +2422,35 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_bcc(opcode,pc,extra);\n"); + printf ("\tfbcc_opp(opcode,pc,extra);\n"); break; case i_FSAVE: sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_save(opcode);\n"); + printf ("\tfsave_opp(opcode);\n"); break; case i_FRESTORE: sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_restore(opcode);\n"); + printf ("\tfrestore_opp(opcode);\n"); break; case i_CINVL: case i_CINVP: case i_CINVA: - /* gb-- srcreg now contains the cache field */ - - break; case i_CPUSHL: case i_CPUSHP: case i_CPUSHA: - /* gb-- srcreg now contains the cache field */ - break; case i_MOVE16: - if ((opcode & 0xfff8) == 0xf620) { - /* MOVE16 (Ax)+,(Ay)+ */ - printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); - printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); - printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); - printf ("\tput_long(memd, get_long(mems));\n"); - printf ("\tput_long(memd+4, get_long(mems+4));\n"); - printf ("\tput_long(memd+8, get_long(mems+8));\n"); - printf ("\tput_long(memd+12, get_long(mems+12));\n"); - printf ("\tif (srcreg != dstreg)\n"); - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } - else { - /* Other variants */ - genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2); - genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2); - printf ("\tmemsa &= ~15;\n"); - printf ("\tmemda &= ~15;\n"); - printf ("\tput_long(memda, get_long(memsa));\n"); - printf ("\tput_long(memda+4, get_long(memsa+4));\n"); - printf ("\tput_long(memda+8, get_long(memsa+8));\n"); - printf ("\tput_long(memda+12, get_long(memsa+12));\n"); - if ((opcode & 0xfff8) == 0xf600) - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - else if ((opcode & 0xfff8) == 0xf608) - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } + printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); + printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); + printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); + printf ("\tput_long(memd, get_long(mems));\n"); + printf ("\tput_long(memd+4, get_long(mems+4));\n"); + printf ("\tput_long(memd+8, get_long(mems+8));\n"); + printf ("\tput_long(memd+12, get_long(mems+12));\n"); + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); break; case i_MMUOP: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); @@ -2232,18 +2458,6 @@ static void gen_opcode (unsigned long int opcode) swap_opcode (); printf ("\tmmu_op(opcode,extra);\n"); break; - - case i_EMULOP_RETURN: - printf ("\tm68k_emulop_return();\n"); - m68k_pc_offset = 0; - break; - - case i_EMULOP: - printf ("\n"); - swap_opcode (); - printf ("\tm68k_emulop(opcode);\n"); - break; - default: abort (); break; @@ -2255,71 +2469,41 @@ static void gen_opcode (unsigned long int opcode) static void generate_includes (FILE * f) { fprintf (f, "#include \"sysdeps.h\"\n"); - fprintf (f, "#include \"m68k.h\"\n"); fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); - fprintf (f, "#include \"fpu/fpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); - - fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); - fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); - fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); - fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); - fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); - - fprintf (f, "#ifdef NOFLAGS\n"); - fprintf (f, "# include \"noflags.h\"\n"); - fprintf (f, "#endif\n"); } static int postfix; static void generate_one_opcode (int rp) { + int i; uae_u16 smsk, dmsk; long int opcode = opcode_map[rp]; - const char *opcode_str; if (table68k[opcode].mnemo == i_ILLG - || table68k[opcode].clev > (unsigned)cpu_level) + || table68k[opcode].clev > cpu_level) return; + for (i = 0; lookuptab[i].name[0]; i++) { + if (table68k[opcode].mnemo == lookuptab[i].mnemo) + break; + } + if (table68k[opcode].handler != -1) return; - opcode_str = get_instruction_string (opcode); - if (opcode_next_clev[rp] != cpu_level) { - if (table68k[opcode].flagdead == 0) - /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ - fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], - opcode, opcode_str); - else - fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], - opcode, opcode_str); + fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], + opcode, lookuptab[i].name); return; } - - if (table68k[opcode].flagdead == 0) - /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ - fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); - else - fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); - - fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix); - fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix); - - /* gb-- The "nf" variant for an instruction that doesn't set the condition - codes at all is the same as the "ff" variant, so we don't need the "nf" - variant to be compiled since it is mapped to the "ff" variant in the - smalltbl. */ - if (table68k[opcode].flagdead == 0) - printf ("#ifndef NOFLAGS\n"); - - printf ("void REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, opcode_str); - printf ("\tcpuop_begin();\n"); + fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name); + fprintf (headerfile, "extern cpuop_func op_%lx_%d;\n", opcode, postfix); + printf ("void REGPARAM2 op_%lx_%d(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); switch (table68k[opcode].stype) { case 0: smsk = 7; break; @@ -2328,8 +2512,6 @@ static void generate_one_opcode (int rp) case 3: smsk = 7; break; case 4: smsk = 7; break; case 5: smsk = 63; break; - case 6: smsk = 255; break; - case 7: smsk = 3; break; default: abort (); } dmsk = 7; @@ -2339,12 +2521,7 @@ static void generate_one_opcode (int rp) && table68k[opcode].smode != imm && table68k[opcode].smode != imm0 && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2 && table68k[opcode].smode != absw && table68k[opcode].smode != absl - && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16 - /* gb-- We don't want to fetch the EmulOp code since the EmulOp() - routine uses the whole opcode value. Maybe all the EmulOps - could be expanded out but I don't think it is an improvement */ - && table68k[opcode].stype != 6 - ) + && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16) { if (table68k[opcode].spos == -1) { if (((int) table68k[opcode].sreg) >= 128) @@ -2440,10 +2617,7 @@ static void generate_one_opcode (int rp) gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); - printf ("\tcpuop_end();\n"); printf ("}\n"); - if (table68k[opcode].flagdead == 0) - printf ("\n#endif\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; } @@ -2454,13 +2628,7 @@ static void generate_func (void) using_prefetch = 0; using_exception_3 = 0; -#if !USE_PREFETCH_BUFFER - /* gb-- No need for a prefetch buffer, nor exception 3 handling */ - /* Anyway, Basilisk2 does not use the op_smalltbl_5 table... */ - for (i = 0; i <= 4; i++) { -#else for (i = 0; i < 6; i++) { -#endif cpu_level = 4 - i; if (i == 5) { cpu_level = 0; @@ -2470,18 +2638,12 @@ static void generate_func (void) opcode_next_clev[rp] = 0; } postfix = i; - fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); - - /* Disable spurious warnings. */ - printf ("\n" - "#ifdef _MSC_VER\n" - "#pragma warning(disable:4102) /* unreferenced label */\n" - "#endif\n"); + fprintf (stblfile, "struct cputbl op_smalltbl_%d[] = {\n", postfix); /* sam: this is for people with low memory (eg. me :)) */ printf ("\n" "#if !defined(PART_1) && !defined(PART_2) && " - "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_3) && !defined(PART_4) && " "!defined(PART_5) && !defined(PART_6) && " "!defined(PART_7) && !defined(PART_8)" "\n" @@ -2510,7 +2672,6 @@ static void generate_func (void) int main (int argc, char **argv) { - FILE *out; read_table68k (); do_merges (); @@ -2524,9 +2685,9 @@ int main (int argc, char **argv) * cputbl.h that way), but cpuopti can't cope. That could be fixed, but * I don't dare to touch the 68k version. */ - headerfile = fopen ("cputbl.h", "w"); - stblfile = fopen ("cpustbl.cpp", "w"); - out = freopen ("cpuemu.cpp", "w", stdout); + headerfile = fopen ("cputbl.h", "wb"); + stblfile = fopen ("cpustbl.cpp", "wb"); + freopen ("cpuemu.cpp", "wb", stdout); generate_includes (stdout); generate_includes (stblfile); @@ -2534,9 +2695,5 @@ int main (int argc, char **argv) generate_func (); free (table68k); - fclose (headerfile); - fclose (stblfile); - fflush (out); - return 0; } diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index f329cb3e..f1ff6977 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -1,65 +1,34 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - machine dependent bits - * - * Copyright 1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation - machine dependent bits + * + * Copyright 1996 Bernd Schmidt + */ -#ifndef M68K_FLAGS_H -#define M68K_FLAGS_H +#if defined(__i386__) && defined(X86_ASSEMBLY) -#ifdef OPTIMIZED_FLAGS - -#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) || defined(MSVC_INTRINSICS) - -#ifndef SAHF_SETO_PROFITABLE - -/* PUSH/POP instructions are naturally 64-bit sized on x86-64, thus - unsigned long hereunder is either 64-bit or 32-bit wide depending - on the target. */ struct flag_struct { - unsigned long cznv; - unsigned long x; + unsigned int cznv; + unsigned int x; }; -#define FLAGVAL_Z 0x40 -#define FLAGVAL_N 0x80 +#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6)) +#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1)) +#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11)) +#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7)) +#define SET_XFLG(y) (regflags.x = (y)) -#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x40) | (((y) & 1) << 6)) -#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x800) | (((y) & 1) << 11)) -#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x80) | (((y) & 1) << 7)) -#define SET_XFLG(y) (regflags.x = (y)) +#define GET_ZFLG ((regflags.cznv >> 6) & 1) +#define GET_CFLG (regflags.cznv & 1) +#define GET_VFLG ((regflags.cznv >> 11) & 1) +#define GET_NFLG ((regflags.cznv >> 7) & 1) +#define GET_XFLG (regflags.x & 1) -#define GET_ZFLG ((regflags.cznv >> 6) & 1) -#define GET_CFLG (regflags.cznv & 1) -#define GET_VFLG ((regflags.cznv >> 11) & 1) -#define GET_NFLG ((regflags.cznv >> 7) & 1) -#define GET_XFLG (regflags.x & 1) +#define CLEAR_CZNV (regflags.cznv = 0) +#define COPY_CARRY (regflags.x = regflags.cznv) -#define CLEAR_CZNV (regflags.cznv = 0) -#define GET_CZNV (regflags.cznv) -#define IOR_CZNV(X) (regflags.cznv |= (X)) -#define SET_CZNV(X) (regflags.cznv = (X)) - -#define COPY_CARRY (regflags.x = regflags.cznv) - -extern struct flag_struct regflags ASM_SYM ("regflags"); +extern struct flag_struct regflags __asm__ ("regflags"); static __inline__ int cctrue(int cc) { @@ -89,270 +58,91 @@ static __inline__ int cctrue(int cc) return 0; } -#define optflag_testl(v) \ - __asm__ __volatile__ ("andl %1,%1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ +#define x86_flag_testl(v) \ + __asm__ __volatile__ ("testl %1,%1\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv) : "r" (v) : "cc") -#define optflag_testw(v) \ - __asm__ __volatile__ ("andw %w1,%w1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ +#define x86_flag_testw(v) \ + __asm__ __volatile__ ("testw %w1,%w1\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv) : "r" (v) : "cc") -#define optflag_testb(v) \ - __asm__ __volatile__ ("andb %b1,%b1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ +#define x86_flag_testb(v) \ + __asm__ __volatile__ ("testb %b1,%b1\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv) : "q" (v) : "cc") -#define optflag_addl(v, s, d) do { \ +#define x86_flag_addl(v, s, d) do { \ __asm__ __volatile__ ("addl %k2,%k1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define optflag_addw(v, s, d) do { \ +#define x86_flag_addw(v, s, d) do { \ __asm__ __volatile__ ("addw %w2,%w1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define optflag_addb(v, s, d) do { \ +#define x86_flag_addb(v, s, d) do { \ __asm__ __volatile__ ("addb %b2,%b1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define optflag_subl(v, s, d) do { \ +#define x86_flag_subl(v, s, d) do { \ __asm__ __volatile__ ("subl %k2,%k1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define optflag_subw(v, s, d) do { \ +#define x86_flag_subw(v, s, d) do { \ __asm__ __volatile__ ("subw %w2,%w1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define optflag_subb(v, s, d) do { \ +#define x86_flag_subb(v, s, d) do { \ __asm__ __volatile__ ("subb %b2,%b1\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define optflag_cmpl(s, d) \ +#define x86_flag_cmpl(s, d) \ __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") -#define optflag_cmpw(s, d) \ +#define x86_flag_cmpw(s, d) \ __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") -#define optflag_cmpb(s, d) \ +#define x86_flag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \ - "pushf\n\t" \ - "pop %0\n\t" \ + "pushfl\n\t" \ + "popl %0\n\t" \ : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc") -#else - -struct flag_struct { - uae_u32 cznv; - uae_u32 x; -}; - -#define FLAGVAL_Z 0x4000 -#define FLAGVAL_N 0x8000 - -#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14)) -#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8)) -#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1))) -#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15)) -#define SET_XFLG(y) (regflags.x = (y)) - -#define GET_ZFLG ((regflags.cznv >> 14) & 1) -#define GET_CFLG ((regflags.cznv >> 8) & 1) -#define GET_VFLG ((regflags.cznv >> 0) & 1) -#define GET_NFLG ((regflags.cznv >> 15) & 1) -#define GET_XFLG (regflags.x & 1) - -#define CLEAR_CZNV (regflags.cznv = 0) -#define GET_CZNV (regflags.cznv) -#define IOR_CZNV(X) (regflags.cznv |= (X)) -#define SET_CZNV(X) (regflags.cznv = (X)) - -#define COPY_CARRY (regflags.x = (regflags.cznv)>>8) - -extern struct flag_struct regflags ASM_SYM("regflags"); - -static __inline__ int cctrue(int cc) -{ - uae_u32 cznv = regflags.cznv; - switch(cc){ - case 0: return 1; /* T */ - case 1: return 0; /* F */ - case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ - case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */ - case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */ - case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */ - case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */ - case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */ - case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */ - case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */ - case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */ - case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */ - case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */ - case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */ - case 14: - cznv &= 0xc001; - return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ - case 15: - cznv &= 0xc001; - return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ - } - abort(); - return 0; -} - -/* Manually emit LAHF instruction so that 64-bit assemblers can grok it */ -#if defined __x86_64__ && defined __GNUC__ -#define ASM_LAHF ".byte 0x9f" -#else -#define ASM_LAHF "lahf" -#endif - -/* Is there any way to do this without declaring *all* memory clobbered? - I.e. any way to tell gcc that some byte-sized value is in %al? */ -#define optflag_testl(v) \ - __asm__ __volatile__ ("andl %0,%0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : : "r" (v) : "%eax","cc","memory") - -#define optflag_testw(v) \ - __asm__ __volatile__ ("andw %w0,%w0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : : "r" (v) : "%eax","cc","memory") - -#define optflag_testb(v) \ - __asm__ __volatile__ ("andb %b0,%b0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : : "q" (v) : "%eax","cc","memory") - -#define optflag_addl(v, s, d) do { \ - __asm__ __volatile__ ("addl %k1,%k0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ - } while (0) - -#define optflag_addw(v, s, d) do { \ - __asm__ __volatile__ ("addw %w1,%w0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ - } while (0) - -#define optflag_addb(v, s, d) do { \ - __asm__ __volatile__ ("addb %b1,%b0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ - } while (0) - -#define optflag_subl(v, s, d) do { \ - __asm__ __volatile__ ("subl %k1,%k0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ - } while (0) - -#define optflag_subw(v, s, d) do { \ - __asm__ __volatile__ ("subw %w1,%w0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ - } while (0) - -#define optflag_subb(v, s, d) do { \ - __asm__ __volatile__ ("subb %b1,%b0\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ - } while (0) - -#define optflag_cmpl(s, d) \ - __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : : "rmi" (s), "r" (d) : "%eax","cc","memory") - -#define optflag_cmpw(s, d) \ - __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : : "rmi" (s), "r" (d) : "%eax","cc","memory"); - -#define optflag_cmpb(s, d) \ - __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ - ASM_LAHF "\n\t" \ - "seto %%al\n\t" \ - "movb %%al,regflags\n\t" \ - "movb %%ah,regflags+1\n\t" \ - : : "qmi" (s), "q" (d) : "%eax","cc","memory") - -#endif - -#elif defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) +#elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)) struct flag_struct { unsigned char nzvc; @@ -361,26 +151,19 @@ struct flag_struct { extern struct flag_struct regflags; -#define FLAGVAL_Z 0x04 -#define FLAGVAL_N 0x08 +#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) +#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) +#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) +#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) +#define SET_XFLG(y) (regflags.x = (y)) -#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) -#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) -#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) -#define SET_XFLG(y) (regflags.x = (y)) - -#define GET_ZFLG ((regflags.nzvc >> 2) & 1) -#define GET_CFLG (regflags.nzvc & 1) -#define GET_VFLG ((regflags.nzvc >> 1) & 1) -#define GET_NFLG ((regflags.nzvc >> 3) & 1) -#define GET_XFLG (regflags.x & 1) - -#define CLEAR_CZNV (regflags.nzvc = 0) -#define GET_CZNV (reflags.nzvc) -#define IOR_CZNV(X) (refglags.nzvc |= (X)) -#define SET_CZNV(X) (regflags.nzvc = (X)) +#define GET_ZFLG ((regflags.nzvc >> 2) & 1) +#define GET_CFLG (regflags.nzvc & 1) +#define GET_VFLG ((regflags.nzvc >> 1) & 1) +#define GET_NFLG ((regflags.nzvc >> 3) & 1) +#define GET_XFLG (regflags.x & 1) +#define CLEAR_CZNV (regflags.nzvc = 0) #define COPY_CARRY (regflags.x = regflags.nzvc) static __inline__ int cctrue(int cc) @@ -1004,8 +787,6 @@ static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae #endif /* SPARC_V9_ASSEMBLY */ -#endif - #else struct flag_struct { @@ -1024,27 +805,6 @@ extern struct flag_struct regflags; #define VFLG (regflags.v) #define XFLG (regflags.x) -#define SET_CFLG(x) (CFLG = (x)) -#define SET_NFLG(x) (NFLG = (x)) -#define SET_VFLG(x) (VFLG = (x)) -#define SET_ZFLG(x) (ZFLG = (x)) -#define SET_XFLG(x) (XFLG = (x)) - -#define GET_CFLG CFLG -#define GET_NFLG NFLG -#define GET_VFLG VFLG -#define GET_ZFLG ZFLG -#define GET_XFLG XFLG - -#define CLEAR_CZNV do { \ - SET_CFLG (0); \ - SET_ZFLG (0); \ - SET_NFLG (0); \ - SET_VFLG (0); \ -} while (0) - -#define COPY_CARRY (SET_XFLG (GET_CFLG)) - static __inline__ int cctrue(const int cc) { switch(cc){ @@ -1068,6 +828,4 @@ static __inline__ int cctrue(const int cc) return 0; } -#endif /* OPTIMIZED_FLAGS */ - -#endif /* M68K_FLAGS_H */ +#endif diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index a88ebf5e..4adf0cc8 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -1,24 +1,10 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * (c) 1995 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * (c) 1995 Bernd Schmidt + */ #include #include @@ -36,14 +22,9 @@ extern int intlev(void); // From baisilisk_glue.cpp #include "memory.h" #include "readcpu.h" #include "newcpu.h" -#include "fpu/fpu.h" -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) -B2_mutex *spcflags_lock = NULL; -#endif - - -bool quit_program = false; +int quit_program = 0; +int debugging = 0; struct flag_struct regflags; /* Opcode of faulting instruction */ @@ -60,70 +41,12 @@ int movem_index1[256]; int movem_index2[256]; int movem_next[256]; +int fpp_movem_index1[256]; +int fpp_movem_index2[256]; +int fpp_movem_next[256]; + cpuop_func *cpufunctbl[65536]; -#if FLIGHT_RECORDER -struct rec_step { - uae_u32 pc; -#if FLIGHT_RECORDER >= 2 - uae_u32 d[8]; - uae_u32 a[8]; -#endif -}; - -const int LOG_SIZE = 32768; -static rec_step log[LOG_SIZE]; -static int log_ptr = -1; // First time initialization - -static const char *log_filename(void) -{ - const char *name = getenv("M68K_LOG_FILE"); - return name ? name : "log.68k"; -} - -void m68k_record_step(uaecptr pc) -{ -#if FLIGHT_RECORDER >= 2 - /* XXX: if LSB is set, we are recording from generated code and we - don't support registers recording yet. */ - if ((pc & 1) == 0) { - for (int i = 0; i < 8; i++) { - log[log_ptr].d[i] = m68k_dreg(regs, i); - log[log_ptr].a[i] = m68k_areg(regs, i); - } - } -#endif - log[log_ptr].pc = pc; - log_ptr = (log_ptr + 1) % LOG_SIZE; -} - -static void dump_log(void) -{ - FILE *f = fopen(log_filename(), "w"); - if (f == NULL) - return; - for (int i = 0; i < LOG_SIZE; i++) { - int j = (i + log_ptr) % LOG_SIZE; - uae_u32 pc = log[j].pc & ~1; - fprintf(f, "pc %08x", pc); -#if FLIGHT_RECORDER >= 2 - fprintf(f, "\n"); - if ((log[j].pc & 1) == 0) { - fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]); - fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]); - fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]); - fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]); - } -#else - fprintf(f, " | "); -#endif - - } - fclose(f); -} -#endif - - #define COUNT_INSTRS 0 #if COUNT_INSTRS @@ -187,9 +110,9 @@ static __inline__ unsigned int cft_map (unsigned int f) #endif } -void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; +static void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; -void REGPARAM2 op_illg_1 (uae_u32 opcode) +static void REGPARAM2 op_illg_1 (uae_u32 opcode) { op_illg (cft_map (opcode)); } @@ -198,7 +121,7 @@ static void build_cpufunctbl (void) { int i; unsigned long opcode; - unsigned int cpu_level = 0; // 68000 (default) + int cpu_level = 0; // 68000 (default) if (CPUType == 4) cpu_level = 4; // 68040 with FPU else { @@ -210,11 +133,11 @@ static void build_cpufunctbl (void) cpu_level = 1; } struct cputbl *tbl = ( - cpu_level == 4 ? op_smalltbl_0_ff - : cpu_level == 3 ? op_smalltbl_1_ff - : cpu_level == 2 ? op_smalltbl_2_ff - : cpu_level == 1 ? op_smalltbl_3_ff - : op_smalltbl_4_ff); + cpu_level == 4 ? op_smalltbl_0 + : cpu_level == 3 ? op_smalltbl_1 + : cpu_level == 2 ? op_smalltbl_2 + : cpu_level == 1 ? op_smalltbl_3 + : op_smalltbl_4); for (opcode = 0; opcode < 65536; opcode++) cpufunctbl[cft_map (opcode)] = op_illg_1; @@ -254,6 +177,15 @@ void init_m68k (void) movem_index2[i] = 7-j; movem_next[i] = i & (~(1 << j)); } + for (i = 0 ; i < 256 ; i++) { + int j; + for (j = 7 ; j >= 0 ; j--) { + if (i & (1 << j)) break; + } + fpp_movem_index1[i] = 7-j; + fpp_movem_index2[i] = j; + fpp_movem_next[i] = i & (~(1 << j)); + } #if COUNT_INSTRS { FILE *f = fopen (icountfilename (), "r"); @@ -274,19 +206,6 @@ void init_m68k (void) do_merges (); build_cpufunctbl (); - -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) - spcflags_lock = B2_create_mutex(); -#endif - fpu_init(CPUType == 4); -} - -void exit_m68k (void) -{ - fpu_exit (); -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) - B2_delete_mutex(spcflags_lock); -#endif } struct regstruct regs, lastint_regs; @@ -295,15 +214,9 @@ static int backup_pointer = 0; static long int m68kpc_offset; int lastint_no; -#if DIRECT_ADDRESSING -#define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1) -#define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o)) -#define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o)) -#else #define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) #define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) #define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) -#endif uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf) { @@ -722,18 +635,15 @@ void MakeFromSR (void) } } - SPCFLAGS_SET( SPCFLAG_INT ); + regs.spcflags |= SPCFLAG_INT; if (regs.t1 || regs.t0) - SPCFLAGS_SET( SPCFLAG_TRACE ); + regs.spcflags |= SPCFLAG_TRACE; else - /* Keep SPCFLAG_DOTRACE, we still want a trace exception for - SR-modifying instructions (including STOP). */ - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); } void Exception(int nr, uaecptr oldpc) { - uae_u32 currpc = m68k_getpc (); MakeSR(); if (!regs.s) { regs.usp = m68k_areg(regs, 7); @@ -762,7 +672,7 @@ void Exception(int nr, uaecptr oldpc) m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), nr * 4); m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), currpc); + put_long (m68k_areg(regs, 7), m68k_getpc ()); m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), regs.sr); regs.sr |= (1 << 13); @@ -788,15 +698,14 @@ void Exception(int nr, uaecptr oldpc) } } m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), currpc); + put_long (m68k_areg(regs, 7), m68k_getpc ()); kludge_me_do: m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), regs.sr); m68k_setpc (get_long (regs.vbr + 4*nr)); - SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); fill_prefetch_0 (); regs.t1 = regs.t0 = regs.m = 0; - SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE ); + regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); } static void Interrupt(int nr) @@ -807,48 +716,20 @@ static void Interrupt(int nr) Exception(nr+24, 0); regs.intmask = nr; - SPCFLAGS_SET( SPCFLAG_INT ); + regs.spcflags |= SPCFLAG_INT; } -static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp; +static int caar, cacr, tc, itt0, itt1, dtt0, dtt1; -static int movec_illg (int regno) +void m68k_move2c (int regno, uae_u32 *regp) { - switch (CPUType) { - case 1: - if ((regno & 0x7ff) <= 1) - return 0; - break; - case 2: - case 3: - if ((regno & 0x7ff) <= 2) - return 0; - if (regno == 3 || regno == 4) - return 0; - break; - case 4: - if ((regno & 0x7ff) <= 7) { - if (regno != 0x802) - return 0; - } - break; - } - return 1; -} - -int m68k_move2c (int regno, uae_u32 *regp) -{ - if (movec_illg (regno)) { + if (CPUType == 1 && (regno & 0x7FF) > 1) op_illg (0x4E7B); - return 0; - } else { + else switch (regno) { case 0: regs.sfc = *regp & 7; break; case 1: regs.dfc = *regp & 7; break; - case 2: - cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); - - break; + case 2: cacr = *regp & 0x3; break; /* ignore C and CE */ case 3: tc = *regp & 0xc000; break; case 4: itt0 = *regp & 0xffffe364; break; case 5: itt1 = *regp & 0xffffe364; break; @@ -859,24 +740,17 @@ int m68k_move2c (int regno, uae_u32 *regp) case 0x802: caar = *regp &0xfc; break; case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; - case 0x805: mmusr = *regp; break; - case 0x806: urp = *regp; break; - case 0x807: srp = *regp; break; default: op_illg (0x4E7B); - return 0; + break; } - } - return 1; } -int m68k_movec2 (int regno, uae_u32 *regp) +void m68k_movec2 (int regno, uae_u32 *regp) { - if (movec_illg (regno)) - { + if (CPUType == 1 && (regno & 0x7FF) > 1) op_illg (0x4E7A); - return 0; - } else { + else switch (regno) { case 0: *regp = regs.sfc; break; case 1: *regp = regs.dfc; break; @@ -891,15 +765,10 @@ int m68k_movec2 (int regno, uae_u32 *regp) case 0x802: *regp = caar; break; case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; - case 0x805: *regp = mmusr; break; - case 0x806: *regp = urp; break; - case 0x807: *regp = srp; break; default: op_illg (0x4E7A); - return 0; + break; } - } - return 1; } static __inline__ int @@ -957,8 +826,8 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) SET_CFLG (0); SET_ZFLG (((uae_s32)quot) == 0); SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = (uae_u32)rem; - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; } } else { /* unsigned */ @@ -980,8 +849,8 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) SET_CFLG (0); SET_ZFLG (((uae_s32)quot) == 0); SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = (uae_u32)rem; - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; } } #else @@ -1157,16 +1026,12 @@ static char* ccnames[] = { "T ","F ","HI","LS","CC","CS","NE","EQ", "VC","VS","PL","MI","GE","LT","GT","LE" }; -// If value is greater than zero, this means we are still processing an EmulOp -// because the counter is incremented only in m68k_execute(), i.e. interpretive -// execution only -static int m68k_execute_depth = 0; - void m68k_reset (void) { m68k_areg (regs, 7) = 0x2000; m68k_setpc (ROMBaseMac + 0x2a); fill_prefetch_0 (); + regs.kick_mask = 0xF80000; regs.s = 1; regs.m = 0; regs.stopped = 0; @@ -1177,29 +1042,29 @@ void m68k_reset (void) SET_CFLG (0); SET_VFLG (0); SET_NFLG (0); - SPCFLAGS_INIT( 0 ); + regs.spcflags = 0; regs.intmask = 7; regs.vbr = regs.sfc = regs.dfc = 0; - fpu_reset(); - -#if FLIGHT_RECORDER - log_ptr = 0; - memset(log, 0, sizeof(log)); -#endif - + regs.fpcr = regs.fpsr = regs.fpiar = 0; } -void m68k_emulop_return(void) +void REGPARAM2 op_illg (uae_u32 opcode) { - SPCFLAGS_SET( SPCFLAG_BRK ); - quit_program = true; -} + uaecptr pc = m68k_getpc (); -void m68k_emulop(uae_u32 opcode) -{ + + if ((opcode & 0xFF00) == 0x7100) { struct M68kRegisters r; int i; + // Return from Execute68k()? + if (opcode == M68K_EXEC_RETURN) { + regs.spcflags |= SPCFLAG_BRK; + quit_program = 1; + return; + } + + // Call EMUL_OP opcode for (i=0; i<8; i++) { r.d[i] = m68k_dreg(regs, i); r.a[i] = m68k_areg(regs, i); @@ -1213,17 +1078,18 @@ void m68k_emulop(uae_u32 opcode) } regs.sr = r.sr; MakeFromSR(); -} - -void REGPARAM2 op_illg (uae_u32 opcode) -{ - uaecptr pc = m68k_getpc (); + m68k_incpc(2); + fill_prefetch_0 (); + return; + } if ((opcode & 0xF000) == 0xA000) { Exception(0xA,0); return; } +// write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); + if ((opcode & 0xF000) == 0xF000) { Exception(0xB,0); return; @@ -1232,18 +1098,16 @@ void REGPARAM2 op_illg (uae_u32 opcode) write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); Exception (4,0); - return; } void mmu_op(uae_u32 opcode, uae_u16 extra) { - if ((opcode & 0xFE0) == 0x0500) { - /* PFLUSH */ - mmusr = 0; - } else if ((opcode & 0x0FD8) == 0x548) { - /* PTEST */ + if ((extra & 0xB000) == 0) { /* PMOVE instruction */ + + } else if ((extra & 0xF000) == 0x2000) { /* PLOAD instruction */ + } else if ((extra & 0xF000) == 0x8000) { /* PTEST instruction */ } else - op_illg (opcode); + op_illg (opcode); } static int n_insns = 0, n_spcinsns = 0; @@ -1252,14 +1116,14 @@ static uaecptr last_trace_ad = 0; static void do_trace (void) { - if (regs.t0 && CPUType >= 2) { + if (regs.t0) { uae_u16 opcode; /* should also include TRAP, CHK, SR modification FPcc */ /* probably never used so why bother */ /* We can afford this to be inefficient... */ m68k_setpc (m68k_getpc ()); fill_prefetch_0 (); - opcode = get_word(m68k_getpc()); + opcode = get_word (regs.pc); if (opcode == 0x4e72 /* RTE */ || opcode == 0x4e74 /* RTD */ || opcode == 0x4e75 /* RTS */ @@ -1275,80 +1139,97 @@ static void do_trace (void) && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) { last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); + regs.spcflags &= ~SPCFLAG_TRACE; + regs.spcflags |= SPCFLAG_DOTRACE; } } else if (regs.t1) { last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); + regs.spcflags &= ~SPCFLAG_TRACE; + regs.spcflags |= SPCFLAG_DOTRACE; } } -int m68k_do_specialties (void) -{ - if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { +static int do_specialties (void) +{ + /*n_spcinsns++;*/ + if (regs.spcflags & SPCFLAG_DOTRACE) { Exception (9,last_trace_ad); } - while (SPCFLAGS_TEST( SPCFLAG_STOP )) { - if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ - SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); + while (regs.spcflags & SPCFLAG_STOP) { + if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ int intr = intlev (); + regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); if (intr != -1 && intr > regs.intmask) { Interrupt (intr); regs.stopped = 0; - SPCFLAGS_CLEAR( SPCFLAG_STOP ); + regs.spcflags &= ~SPCFLAG_STOP; } } } - if (SPCFLAGS_TEST( SPCFLAG_TRACE )) + if (regs.spcflags & SPCFLAG_TRACE) do_trace (); - if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { - SPCFLAGS_CLEAR( SPCFLAG_DOINT ); + if (regs.spcflags & SPCFLAG_DOINT) { int intr = intlev (); + regs.spcflags &= ~SPCFLAG_DOINT; if (intr != -1 && intr > regs.intmask) { Interrupt (intr); regs.stopped = 0; } } - if (SPCFLAGS_TEST( SPCFLAG_INT )) { - SPCFLAGS_CLEAR( SPCFLAG_INT ); - SPCFLAGS_SET( SPCFLAG_DOINT ); + if (regs.spcflags & SPCFLAG_INT) { + regs.spcflags &= ~SPCFLAG_INT; + regs.spcflags |= SPCFLAG_DOINT; } - if (SPCFLAGS_TEST( SPCFLAG_BRK )) { - SPCFLAGS_CLEAR( SPCFLAG_BRK ); + if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { + regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); return 1; } return 0; } -void m68k_do_execute (void) +static void m68k_run_1 (void) { for (;;) { uae_u32 opcode = GET_OPCODE; -#if FLIGHT_RECORDER - m68k_record_step(m68k_getpc()); -#endif (*cpufunctbl[opcode])(opcode); - cpu_check_ticks(); - if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { - if (m68k_do_specialties()) + if (regs.spcflags) { + if (do_specialties()) return; } } } -void m68k_execute (void) +#define m68k_run1 m68k_run_1 + +int in_m68k_go = 0; + +void m68k_go (int may_quit) { - - for (;;) { - if (quit_program) - break; - m68k_do_execute(); +// m68k_go() must be reentrant for Execute68k() and Execute68kTrap() to work +/* + if (in_m68k_go || !may_quit) { + write_log("Bug! m68k_go is not reentrant.\n"); + abort(); } - +*/ + in_m68k_go++; + for (;;) { + if (quit_program > 0) { + if (quit_program == 1) + break; + quit_program = 0; + m68k_reset (); + } + m68k_run1(); + } + if (debugging) { + uaecptr nextpc; + m68k_dumpstate(&nextpc); + exit(1); + } + in_m68k_go--; } static void m68k_verify (uaecptr addr, uaecptr *nextpc) @@ -1457,10 +1338,16 @@ void m68k_dumpstate (uaecptr *nextpc) printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n", regs.t1, regs.t0, regs.s, regs.m, GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); - - fpu_dump_registers(); - fpu_dump_flags(); - + for (i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, regs.fp[i]); + if ((i & 3) == 3) printf ("\n"); + } + printf ("N=%d Z=%d I=%d NAN=%d\n", + (regs.fpsr & 0x8000000) != 0, + (regs.fpsr & 0x4000000) != 0, + (regs.fpsr & 0x2000000) != 0, + (regs.fpsr & 0x1000000) != 0); + m68k_disasm(m68k_getpc (), nextpc, 1); if (nextpc) printf ("next PC: %08lx\n", *nextpc); diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index a15d79d8..dc174a78 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -1,36 +1,47 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * Copyright 1995 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * Copyright 1995 Bernd Schmidt + */ -#ifndef NEWCPU_H -#define NEWCPU_H +#define SPCFLAG_STOP 2 +#define SPCFLAG_DISK 4 +#define SPCFLAG_INT 8 +#define SPCFLAG_BRK 16 +#define SPCFLAG_EXTRA_CYCLES 32 +#define SPCFLAG_TRACE 64 +#define SPCFLAG_DOTRACE 128 +#define SPCFLAG_DOINT 256 +#define SPCFLAG_BLTNASTY 512 +#define SPCFLAG_EXEC 1024 +#define SPCFLAG_MODE_CHANGE 8192 -#ifndef FLIGHT_RECORDER -#define FLIGHT_RECORDER 0 +#ifndef SET_CFLG + +#define SET_CFLG(x) (CFLG = (x)) +#define SET_NFLG(x) (NFLG = (x)) +#define SET_VFLG(x) (VFLG = (x)) +#define SET_ZFLG(x) (ZFLG = (x)) +#define SET_XFLG(x) (XFLG = (x)) + +#define GET_CFLG CFLG +#define GET_NFLG NFLG +#define GET_VFLG VFLG +#define GET_ZFLG ZFLG +#define GET_XFLG XFLG + +#define CLEAR_CZNV do { \ + SET_CFLG (0); \ + SET_ZFLG (0); \ + SET_NFLG (0); \ + SET_VFLG (0); \ +} while (0) + +#define COPY_CARRY (SET_XFLG (GET_CFLG)) #endif -#include "m68k.h" -#include "readcpu.h" -#include "spcflags.h" - extern int areg_byteinc[]; extern int imm8_table[]; @@ -38,66 +49,56 @@ extern int movem_index1[256]; extern int movem_index2[256]; extern int movem_next[256]; +extern int fpp_movem_index1[256]; +extern int fpp_movem_index2[256]; +extern int fpp_movem_next[256]; + extern int broken_in; -#ifdef X86_ASSEMBLY -/* This hack seems to force all register saves (pushl %reg) to be moved to the - begining of the function, thus making it possible to cpuopti to remove them - since m68k_run_1 will save those registers before calling the instruction - handler */ -# define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag ) -#else -# define cpuop_tag(tag) ; -#endif - -#define cpuop_begin() do { cpuop_tag("begin"); } while (0) -#define cpuop_end() do { cpuop_tag("end"); } while (0) - typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM; - + struct cputbl { cpuop_func *handler; - uae_u16 specific; + int specific; uae_u16 opcode; }; -extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl"); - extern void REGPARAM2 op_illg (uae_u32) REGPARAM; typedef char flagtype; -struct regstruct { - uae_u32 regs[16]; +extern struct regstruct +{ + uae_u32 regs[16]; + uaecptr usp,isp,msp; + uae_u16 sr; + flagtype t1; + flagtype t0; + flagtype s; + flagtype m; + flagtype x; + flagtype stopped; + int intmask; - uae_u32 pc; - uae_u8 * pc_p; - uae_u8 * pc_oldp; + uae_u32 pc; + uae_u8 *pc_p; + uae_u8 *pc_oldp; - spcflags_t spcflags; - int intmask; + uae_u32 vbr,sfc,dfc; - uae_u32 vbr, sfc, dfc; - uaecptr usp, isp, msp; - uae_u16 sr; - flagtype t1; - flagtype t0; - flagtype s; - flagtype m; - flagtype x; - flagtype stopped; + double fp[8]; + uae_u32 fpcr,fpsr,fpiar; + + uae_u32 spcflags; + uae_u32 kick_mask; -#if USE_PREFETCH_BUFFER /* Fellow sources say this is 4 longwords. That's impossible. It needs * to be at least a longword. The HRM has some cryptic comment about two * instructions being on the same longword boundary. * The way this is implemented now seems like a good compromise. */ uae_u32 prefetch; -#endif -}; - -extern regstruct regs, lastint_regs; +} regs, lastint_regs; #define m68k_dreg(r,num) ((r).regs[(num)]) #define m68k_areg(r,num) (((r).regs + 8)[(num)]) @@ -112,7 +113,6 @@ extern regstruct regs, lastint_regs; #define GET_OPCODE (get_iword (0)) #endif -#if USE_PREFETCH_BUFFER static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o) { if (o > 3 || o < 0) @@ -135,13 +135,11 @@ static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o) return do_get_mem_long(®s.prefetch); return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4)); } -#endif #define m68k_incpc(o) (regs.pc_p += (o)) static __inline__ void fill_prefetch_0 (void) { -#if USE_PREFETCH_BUFFER uae_u32 r; #ifdef UNALIGNED_PROFITABLE r = *(uae_u32 *)regs.pc_p; @@ -150,7 +148,6 @@ static __inline__ void fill_prefetch_0 (void) r = do_get_mem_long ((uae_u32 *)regs.pc_p); do_put_mem_long (®s.prefetch, r); #endif -#endif } #if 0 @@ -190,54 +187,49 @@ static __inline__ uae_u32 next_ilong (void) static __inline__ void m68k_setpc (uaecptr newpc) { -#if DIRECT_ADDRESSING - regs.pc_p = get_real_address(newpc); -#else regs.pc_p = regs.pc_oldp = get_real_address(newpc); regs.pc = newpc; -#endif } static __inline__ uaecptr m68k_getpc (void) { -#if DIRECT_ADDRESSING - return get_virtual_address(regs.pc_p); -#else return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); -#endif +} + +static __inline__ uaecptr m68k_getpc_p (uae_u8 *p) +{ + return regs.pc + ((char *)p - (char *)regs.pc_oldp); +} + +static __inline__ void m68k_do_rts(void) +{ + m68k_setpc(get_long(m68k_areg(regs, 7))); + m68k_areg(regs, 7) += 4; +} + +static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) +{ + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), oldpc); + m68k_incpc(offset); +} + +static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest) +{ + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), oldpc); + m68k_setpc(dest); } #define m68k_setpc_fast m68k_setpc #define m68k_setpc_bcc m68k_setpc #define m68k_setpc_rte m68k_setpc -static __inline__ void m68k_do_rts(void) -{ - m68k_setpc(get_long(m68k_areg(regs, 7))); - m68k_areg(regs, 7) += 4; -} - -static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) -{ - m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); - m68k_incpc(offset); -} - -static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest) -{ - m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); - m68k_setpc(dest); -} - static __inline__ void m68k_setstopped (int stop) { regs.stopped = stop; - /* A traced STOP instruction drops through immediately without - actually stopping. */ - if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0) - SPCFLAGS_SET( SPCFLAG_STOP ); + if (stop) + regs.spcflags |= SPCFLAG_STOP; } extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); @@ -249,22 +241,27 @@ extern void MakeSR (void); extern void MakeFromSR (void); extern void Exception (int, uaecptr); extern void dump_counts (void); -extern int m68k_move2c (int, uae_u32 *); -extern int m68k_movec2 (int, uae_u32 *); +extern void m68k_move2c (int, uae_u32 *); +extern void m68k_movec2 (int, uae_u32 *); extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); extern void m68k_mull (uae_u32, uae_u32, uae_u16); -extern void m68k_emulop (uae_u32); -extern void m68k_emulop_return (void); extern void init_m68k (void); -extern void exit_m68k (void); +extern void m68k_go (int); extern void m68k_dumpstate (uaecptr *); extern void m68k_disasm (uaecptr, uaecptr *, int); extern void m68k_reset (void); extern void m68k_enter_debugger(void); -extern int m68k_do_specialties(void); extern void mmu_op (uae_u32, uae_u16); +extern void fpp_opp (uae_u32, uae_u16); +extern void fdbcc_opp (uae_u32, uae_u16); +extern void fscc_opp (uae_u32, uae_u16); +extern void ftrapcc_opp (uae_u32,uaecptr); +extern void fbcc_opp (uae_u32, uaecptr, uae_u32); +extern void fsave_opp (uae_u32); +extern void frestore_opp (uae_u32); + /* Opcode of faulting instruction */ extern uae_u16 last_op_for_exception_3; /* PC at fault time */ @@ -275,34 +272,15 @@ extern uaecptr last_fault_for_exception_3; #define CPU_OP_NAME(a) op ## a /* 68020 + 68881 */ -extern struct cputbl op_smalltbl_0_ff[]; +extern struct cputbl op_smalltbl_0[]; /* 68020 */ -extern struct cputbl op_smalltbl_1_ff[]; +extern struct cputbl op_smalltbl_1[]; /* 68010 */ -extern struct cputbl op_smalltbl_2_ff[]; +extern struct cputbl op_smalltbl_2[]; /* 68000 */ -extern struct cputbl op_smalltbl_3_ff[]; +extern struct cputbl op_smalltbl_3[]; /* 68000 slow but compatible. */ -extern struct cputbl op_smalltbl_4_ff[]; +extern struct cputbl op_smalltbl_4[]; -#if FLIGHT_RECORDER -extern void m68k_record_step(uaecptr) REGPARAM; -#endif -extern void m68k_do_execute(void); -extern void m68k_execute(void); +extern cpuop_func *cpufunctbl[65536]; -#ifdef USE_CPU_EMUL_SERVICES -extern int32 emulated_ticks; -extern void cpu_do_check_ticks(void); - -static inline void cpu_check_ticks(void) -{ - if (--emulated_ticks <= 0) - cpu_do_check_ticks(); -} -#else -#define cpu_check_ticks() -#define cpu_do_check_ticks() -#endif - -#endif /* NEWCPU_H */ diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h deleted file mode 100644 index eacbc214..00000000 --- a/BasiliskII/src/uae_cpu/noflags.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef NOFLAGS_H -#define NOFLAGS_H - -/* Undefine everything that will *set* flags. Note: Leave *reading* - flags alone ;-). We assume that nobody does something like - SET_ZFLG(a=b+c), i.e. expect side effects of the macros. That would - be a stupid thing to do when using macros. -*/ - -/* Gwenole Beauchesne pointed out that CAS and CAS2 use flag_cmp to set - flags that are then used internally, and that thus the noflags versions - of those instructions were broken. Oops! - Easy fix: Leave flag_cmp alone. It is only used by CMP* and CAS* - instructions. For CAS*, noflags is a bad idea. For CMP*, which has - setting flags as its only function, the noflags version is kinda pointless, - anyway. - Note that this will only work while using the optflag_* routines --- - as we do on all (one ;-) platforms that will ever use the noflags - versions, anyway. - However, if you try to compile without optimized flags, the "SET_ZFLAG" - macro will be left unchanged, to make CAS and CAS2 work right. Of course, - this is contrary to the whole idea of noflags, but better be right than - be fast. - - Another problem exists with one of the bitfield operations. Once again, - one of the operations sets a flag, and looks at it later. And the CHK2 - instruction does so as well. For those, a different solution is possible. - the *_ALWAYS versions of the SET_?FLG macros shall remain untouched by - the redefinitions in this file. - Unfortunately, they are defined in terms of the macros we *do* redefine. - So here comes a bit of trickery.... -*/ -#define NOFLAGS_CMP 0 - -#undef SET_NFLG_ALWAYS -static __inline__ void SET_NFLG_ALWAYS(uae_u32 x) -{ - SET_NFLG(x); /* This has not yet been redefined */ -} - -#undef SET_CFLG_ALWAYS -static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) -{ - SET_CFLG(x); /* This has not yet been redefined */ -} - -#undef CPUFUNC -#define CPUFUNC(x) x##_nf - -#ifndef OPTIMIZED_FLAGS -#undef SET_ZFLG -#define SET_ZFLG(y) do {uae_u32 dummy=(y); } while (0) -#endif - -#undef SET_CFLG -#define SET_CFLG(y) do {uae_u32 dummy=(y); } while (0) -#undef SET_VFLG -#define SET_VFLG(y) do {uae_u32 dummy=(y); } while (0) -#undef SET_NFLG -#define SET_NFLG(y) do {uae_u32 dummy=(y); } while (0) -#undef SET_XFLG -#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0) - -#undef CLEAR_CZNV -#define CLEAR_CZNV -#undef IOR_CZNV -#define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0) -#undef SET_CZNV -#define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0) -#undef COPY_CARRY -#define COPY_CARRY - -#ifdef optflag_testl -#undef optflag_testl -#endif - -#ifdef optflag_testw -#undef optflag_testw -#endif - -#ifdef optflag_testb -#undef optflag_testb -#endif - -#ifdef optflag_addl -#undef optflag_addl -#endif - -#ifdef optflag_addw -#undef optflag_addw -#endif - -#ifdef optflag_addb -#undef optflag_addb -#endif - -#ifdef optflag_subl -#undef optflag_subl -#endif - -#ifdef optflag_subw -#undef optflag_subw -#endif - -#ifdef optflag_subb -#undef optflag_subb -#endif - -#if NOFLAGS_CMP -#ifdef optflag_cmpl -#undef optflag_cmpl -#endif - -#ifdef optflag_cmpw -#undef optflag_cmpw -#endif - -#ifdef optflag_cmpb -#undef optflag_cmpb -#endif -#endif - -#define optflag_testl(v) do { } while (0) -#define optflag_testw(v) do { } while (0) -#define optflag_testb(v) do { } while (0) - -#define optflag_addl(v, s, d) (v = (uae_s32)(d) + (uae_s32)(s)) -#define optflag_addw(v, s, d) (v = (uae_s16)(d) + (uae_s16)(s)) -#define optflag_addb(v, s, d) (v = (uae_s8)(d) + (uae_s8)(s)) - -#define optflag_subl(v, s, d) (v = (uae_s32)(d) - (uae_s32)(s)) -#define optflag_subw(v, s, d) (v = (uae_s16)(d) - (uae_s16)(s)) -#define optflag_subb(v, s, d) (v = (uae_s8)(d) - (uae_s8)(s)) - -#if NOFLAGS_CMP -/* These are just for completeness sake */ -#define optflag_cmpl(s, d) do { } while (0) -#define optflag_cmpw(s, d) do { } while (0) -#define optflag_cmpb(s, d) do { } while (0) -#endif - -#endif diff --git a/BasiliskII/src/uae_cpu/readcpu.cpp b/BasiliskII/src/uae_cpu/readcpu.cpp index 3fccdfb7..abb3faae 100644 --- a/BasiliskII/src/uae_cpu/readcpu.cpp +++ b/BasiliskII/src/uae_cpu/readcpu.cpp @@ -4,20 +4,6 @@ * Read 68000 CPU specs from file "table68k" * * Copyright 1995,1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -153,9 +139,6 @@ struct mnemolookup lookuptab[] = { { i_CPUSHA, "CPUSHA" }, { i_MOVE16, "MOVE16" }, - { i_EMULOP_RETURN, "EMULOP_RETURN" }, - { i_EMULOP, "EMULOP" }, - { i_MMUOP, "MMUOP" }, { i_ILLG, "" }, }; @@ -212,34 +195,16 @@ static void build_insn (int insn) int variants; struct instr_def id; const char *opcstr; - int i, n; + int i; int flaglive = 0, flagdead = 0; - int cflow = 0; id = defs68k[insn]; - // Control flow information - cflow = id.cflow; - - // Mask of flags set/used - unsigned char flags_set(0), flags_used(0); - - for (i = 0, n = 4; i < 5; i++, n--) { - switch (id.flaginfo[i].flagset) { - case fa_unset: case fa_isjmp: break; - default: flags_set |= (1 << n); - } - - switch (id.flaginfo[i].flaguse) { - case fu_unused: case fu_isjmp: break; - default: flags_used |= (1 << n); - } - } - for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flagset){ case fa_unset: break; + case fa_isjmp: break; case fa_zero: flagdead |= 1 << i; break; case fa_one: flagdead |= 1 << i; break; case fa_dontcare: flagdead |= 1 << i; break; @@ -252,6 +217,8 @@ static void build_insn (int insn) for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flaguse) { case fu_unused: break; + case fu_isjmp: flaglive |= 1 << i; break; + case fu_maybecc: flaglive |= 1 << i; break; case fu_unknown: flaglive = -1; goto out2; case fu_used: flaglive |= 1 << i; break; } @@ -269,7 +236,7 @@ static void build_insn (int insn) int pos = 0; int mnp = 0; int bitno = 0; - char mnemonic[64]; + char mnemonic[10]; wordsizes sz = sz_long; int srcgather = 0, dstgather = 0; @@ -306,8 +273,6 @@ static void build_insn (int insn) continue; if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) continue; - if (bitcnt[bitE] && (bitval[bitE] == 0x00)) - continue; /* bitI and bitC get copied to biti and bitc */ if (bitcnt[bitI]) { @@ -346,11 +311,6 @@ static void build_insn (int insn) } } mnp++; - if ((unsigned)mnp >= sizeof(mnemonic) - 1) { - mnemonic[sizeof(mnemonic) - 1] = 0; - fprintf(stderr, "Instruction %s overflow\n", mnemonic); - abort(); - } } pos++; } @@ -388,9 +348,6 @@ static void build_insn (int insn) case 'P': srcmode = Aipi; pos++; break; } break; - case 'L': - srcmode = absl; - break; case '#': switch (opcstr[pos++]) { case 'z': srcmode = imm; break; @@ -436,22 +393,6 @@ static void build_insn (int insn) srcpos = bitpos[bitK]; } break; - case 'E': srcmode = immi; srcreg = bitval[bitE]; - if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? - /* 1..255 */ - srcgather = 1; - srctype = 6; - srcpos = bitpos[bitE]; - } - break; - case 'p': srcmode = immi; srcreg = bitval[bitp]; - if (CPU_EMU_SIZE < 5) { - /* 0..3 */ - srcgather = 1; - srctype = 7; - srcpos = bitpos[bitp]; - } - break; default: abort(); } break; @@ -576,27 +517,19 @@ static void build_insn (int insn) case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; default: abort(); } - if (dstpos < 0 || dstpos >= 32) - abort(); break; case 'A': destmode = Areg; switch (opcstr[pos++]) { case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; - case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; default: abort(); } - if (dstpos < 0 || dstpos >= 32) - abort(); switch (opcstr[pos]) { case 'p': destmode = Apdi; pos++; break; case 'P': destmode = Aipi; pos++; break; } break; - case 'L': - destmode = absl; - break; case '#': switch (opcstr[pos++]) { case 'z': destmode = imm; break; @@ -767,44 +700,8 @@ static void build_insn (int insn) table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; } #endif - - // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions - if ( table68k[opc].mnemo == i_Scc - || table68k[opc].mnemo == i_Bcc - || table68k[opc].mnemo == i_DBcc - || table68k[opc].mnemo == i_TRAPcc - ) { - switch (table68k[opc].cc) { - // CC mask: XNZVC - // 8421 - case 0: flags_used = 0x00; break; /* T */ - case 1: flags_used = 0x00; break; /* F */ - case 2: flags_used = 0x05; break; /* HI */ - case 3: flags_used = 0x05; break; /* LS */ - case 4: flags_used = 0x01; break; /* CC */ - case 5: flags_used = 0x01; break; /* CS */ - case 6: flags_used = 0x04; break; /* NE */ - case 7: flags_used = 0x04; break; /* EQ */ - case 8: flags_used = 0x02; break; /* VC */ - case 9: flags_used = 0x02; break; /* VS */ - case 10:flags_used = 0x08; break; /* PL */ - case 11:flags_used = 0x08; break; /* MI */ - case 12:flags_used = 0x0A; break; /* GE */ - case 13:flags_used = 0x0A; break; /* LT */ - case 14:flags_used = 0x0E; break; /* GT */ - case 15:flags_used = 0x0E; break; /* LE */ - } - } - -#if 1 - /* gb-- flagdead and flaglive would not have correct information */ - table68k[opc].flagdead = flags_set; - table68k[opc].flaglive = flags_used; -#else table68k[opc].flagdead = flagdead; table68k[opc].flaglive = flaglive; -#endif - table68k[opc].cflow = cflow; nomatch: /* FOO! */; } @@ -850,10 +747,6 @@ static void handle_merges (long int opcode) smsk = 7; sbitdst = 8; break; case 5: smsk = 63; sbitdst = 64; break; - case 6: - smsk = 255; sbitdst = 256; break; - case 7: - smsk = 3; sbitdst = 4; break; default: smsk = 0; sbitdst = 0; abort(); @@ -869,7 +762,7 @@ static void handle_merges (long int opcode) } for (srcreg=0; srcreg < sbitdst; srcreg++) { for (dstreg=0; dstreg < dstend; dstreg++) { - uae_u16 code = uae_u16(opcode); + uae_u16 code = opcode; code = (code & ~smsk) | (srcreg << table68k[opcode].spos); code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos); @@ -922,112 +815,3 @@ int get_no_mismatches (void) { return mismatch; } - -const char *get_instruction_name (unsigned int opcode) -{ - struct instr *ins = &table68k[opcode]; - for (int i = 0; lookuptab[i].name[0]; i++) { - if (ins->mnemo == lookuptab[i].mnemo) - return lookuptab[i].name; - } - abort(); - return NULL; -} - -static char *get_ea_string (amodes mode, wordsizes size) -{ - static char buffer[80]; - - buffer[0] = 0; - switch (mode){ - case Dreg: - strcpy (buffer,"Dn"); - break; - case Areg: - strcpy (buffer,"An"); - break; - case Aind: - strcpy (buffer,"(An)"); - break; - case Aipi: - strcpy (buffer,"(An)+"); - break; - case Apdi: - strcpy (buffer,"-(An)"); - break; - case Ad16: - strcpy (buffer,"(d16,An)"); - break; - case Ad8r: - strcpy (buffer,"(d8,An,Xn)"); - break; - case PC16: - strcpy (buffer,"(d16,PC)"); - break; - case PC8r: - strcpy (buffer,"(d8,PC,Xn)"); - break; - case absw: - strcpy (buffer,"(xxx).W"); - break; - case absl: - strcpy (buffer,"(xxx).L"); - break; - case imm: - switch (size){ - case sz_byte: - strcpy (buffer,"#.B"); - break; - case sz_word: - strcpy (buffer,"#.W"); - break; - case sz_long: - strcpy (buffer,"#.L"); - break; - default: - break; - } - break; - case imm0: - strcpy (buffer,"#.B"); - break; - case imm1: - strcpy (buffer,"#.W"); - break; - case imm2: - strcpy (buffer,"#.L"); - break; - case immi: - strcpy (buffer,"#"); - break; - - default: - break; - } - return buffer; -} - -const char *get_instruction_string (unsigned int opcode) -{ - static char out[100]; - struct instr *ins; - - strcpy (out, get_instruction_name (opcode)); - - ins = &table68k[opcode]; - if (ins->size == sz_byte) - strcat (out,".B"); - if (ins->size == sz_word) - strcat (out,".W"); - if (ins->size == sz_long) - strcat (out,".L"); - strcat (out," "); - if (ins->suse) - strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size))); - if (ins->duse) { - if (ins->suse) - strcat (out,","); - strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size))); - } - return out; -} diff --git a/BasiliskII/src/uae_cpu/readcpu.h b/BasiliskII/src/uae_cpu/readcpu.h index 6fba3c39..4f225f13 100644 --- a/BasiliskII/src/uae_cpu/readcpu.h +++ b/BasiliskII/src/uae_cpu/readcpu.h @@ -1,6 +1,3 @@ -#ifndef READCPU_H -#define READCPU_H - #ifdef __cplusplus extern "C" { #endif @@ -35,8 +32,7 @@ ENUMDECL { i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES, i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE, i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16, - i_MMUOP, - i_EMULOP_RETURN, i_EMULOP + i_MMUOP } ENUMNAME (instrmnem); extern struct mnemolookup { @@ -56,21 +52,9 @@ ENUMDECL { fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp } ENUMNAME (flaguse); -ENUMDECL { - fl_normal = 0, - fl_branch = 1, - fl_jump = 2, - fl_return = 3, - fl_trap = 4, - fl_const_jump = 8, - - /* Instructions that can trap don't mark the end of a block */ - fl_end_block = 3 -} ENUMNAME (cflow_t); - ENUMDECL { bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK, - bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit + bits, bitS, bitd, bitD, bitr, bitR, bitz, lastbit } ENUMNAME (bitvals); struct instr_def { @@ -84,7 +68,6 @@ struct instr_def { unsigned int flaguse:3; unsigned int flagset:3; } flaginfo[5]; - unsigned char cflow; unsigned char sduse; const char *opcstr; }; @@ -103,16 +86,22 @@ extern struct instr { unsigned int mnemo:8; unsigned int cc:4; unsigned int plev:2; +#ifdef sgi + wordsizes size:2; + amodes smode:5; + unsigned int stype:3; + amodes dmode:5; +#else unsigned int size:2; unsigned int smode:5; unsigned int stype:3; unsigned int dmode:5; +#endif unsigned int suse:1; unsigned int duse:1; unsigned int unused1:1; unsigned int clev:3; - unsigned int cflow:3; - unsigned int unused2:2; + unsigned int unused2:5; } *table68k; extern void read_table68k (void); @@ -120,11 +109,6 @@ extern void do_merges (void); extern int get_no_mismatches (void); extern int nr_cpuop_funcs; -extern const char *get_instruction_name (unsigned int opcode); -extern const char *get_instruction_string (unsigned int opcode); - #ifdef __cplusplus } #endif - -#endif /* READCPU_H */ diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h deleted file mode 100644 index 494f4fcc..00000000 --- a/BasiliskII/src/uae_cpu/spcflags.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * Copyright 1995 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SPCFLAGS_H -#define SPCFLAGS_H - -typedef uae_u32 spcflags_t; - -enum { - SPCFLAG_STOP = 0x01, - SPCFLAG_INT = 0x02, - SPCFLAG_BRK = 0x04, - SPCFLAG_TRACE = 0x08, - SPCFLAG_DOTRACE = 0x10, - SPCFLAG_DOINT = 0x20, - - SPCFLAG_JIT_END_COMPILE = 0, - SPCFLAG_JIT_EXEC_RETURN = 0, - - SPCFLAG_ALL = SPCFLAG_STOP - | SPCFLAG_INT - | SPCFLAG_BRK - | SPCFLAG_TRACE - | SPCFLAG_DOTRACE - | SPCFLAG_DOINT - | SPCFLAG_JIT_END_COMPILE - | SPCFLAG_JIT_EXEC_RETURN - , - - SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN -}; - -#define SPCFLAGS_TEST(m) \ - ((regs.spcflags & (m)) != 0) - -/* Macro only used in m68k_reset() */ -#define SPCFLAGS_INIT(m) do { \ - regs.spcflags = (m); \ -} while (0) - -#if !(ENABLE_EXCLUSIVE_SPCFLAGS) - -#define SPCFLAGS_SET(m) do { \ - regs.spcflags |= (m); \ -} while (0) - -#define SPCFLAGS_CLEAR(m) do { \ - regs.spcflags &= ~(m); \ -} while (0) - -#elif defined(X86_ASSEMBLY) - -#define HAVE_HARDWARE_LOCKS - -#define SPCFLAGS_SET(m) do { \ - __asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \ -} while (0) - -#define SPCFLAGS_CLEAR(m) do { \ - __asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \ -} while (0) - -#else - -#undef HAVE_HARDWARE_LOCKS - -#include "main.h" -extern B2_mutex *spcflags_lock; - -#define SPCFLAGS_SET(m) do { \ - B2_lock_mutex(spcflags_lock); \ - regs.spcflags |= (m); \ - B2_unlock_mutex(spcflags_lock); \ -} while (0) - -#define SPCFLAGS_CLEAR(m) do { \ - B2_lock_mutex(spcflags_lock); \ - regs.spcflags &= ~(m); \ - B2_unlock_mutex(spcflags_lock); \ -} while (0) - -#endif - -#endif /* SPCFLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/table68k b/BasiliskII/src/uae_cpu/table68k index ab9eabe1..54f7c5f3 100644 --- a/BasiliskII/src/uae_cpu/table68k +++ b/BasiliskII/src/uae_cpu/table68k @@ -4,13 +4,11 @@ % C: condition codes, except F % f: direction % i: immediate -% E: immediate, except 00 (for EmulOp instructions) % I: immediate, except 00 and ff % j: immediate 1..8 % J: immediate 0..15 % k: immediate 0..7 % K: immediate 0..63 -% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field) % s: source mode % S: source reg % d: dest mode @@ -26,7 +24,6 @@ % % Arp: --> -(Ar) % ArP: --> (Ar)+ -% L: --> (xxx.L) % % Fields on a line: % 16 chars bitpattern : @@ -46,17 +43,10 @@ % 0 means flag reset % 1 means flag set % ? means programmer was too lazy to check or instruction may trap +% + means instruction is conditional branch % everything else means flag set/used +% / means instruction is unconditional branch/call % x means flag is unknown and well-behaved programs shouldn't check it -% -% Control flow -% two letters, combination of -% - nothing -% T the instruction may trap or cause an exception -% B branch instruction -% J jump instruction -% R return instruction -% % srcaddr status destaddr status : % bitmasks of % 1 means fetched @@ -66,209 +56,197 @@ % instruction % -0000 0000 0011 1100:00:XNZVC:XNZVC:--:10: ORSR.B #1 -0000 0000 0111 1100:02:XNZVC:XNZVC:T-:10: ORSR.W #1 -0000 0zz0 11ss sSSS:20:-?Z?C:-----:T-:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd] -0000 0000 zzdd dDDD:00:-NZ00:-----:--:13: OR.z #z,d[!Areg] -0000 0010 0011 1100:00:XNZVC:XNZVC:--:10: ANDSR.B #1 -0000 0010 0111 1100:02:XNZVC:XNZVC:T-:10: ANDSR.W #1 -0000 0010 zzdd dDDD:00:-NZ00:-----:--:13: AND.z #z,d[!Areg] -0000 0100 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #z,d[!Areg] -0000 0110 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #z,d[!Areg] -0000 0110 11ss sSSS:20:-----:XNZVC:--:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd] -0000 0110 11ss sSSS:20:XNZVC:-----:-R:10: RTM s[Dreg,Areg] -0000 1000 00ss sSSS:00:--Z--:-----:--:11: BTST #1,s[!Areg] -0000 1000 01ss sSSS:00:--Z--:-----:--:13: BCHG #1,s[!Areg,Immd] -0000 1000 10ss sSSS:00:--Z--:-----:--:13: BCLR #1,s[!Areg,Immd] -0000 1000 11ss sSSS:00:--Z--:-----:--:13: BSET #1,s[!Areg,Immd] -0000 1010 0011 1100:00:XNZVC:XNZVC:--:10: EORSR.B #1 -0000 1010 0111 1100:02:XNZVC:XNZVC:T-:10: EORSR.W #1 -0000 1010 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z #z,d[!Areg] -0000 1100 zzss sSSS:00:-NZVC:-----:--:11: CMP.z #z,s[!Areg,Immd] +0000 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1 +0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1 +0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd] +0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg] +0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1 +0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1 +0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg] +0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg] +0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg] +0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd] +0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg] +0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg] +0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd] +0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd] +0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd] +0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1 +0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1 +0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg] +0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd] -0000 1010 11ss sSSS:20:-NZVC:-----:--:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1100 11ss sSSS:20:-NZVC:-----:--:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1100 1111 1100:20:-NZVC:-----:--:10: CAS2.W #2 -0000 1110 zzss sSSS:22:-----:-----:T-:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1110 11ss sSSS:20:-NZVC:-----:--:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1110 1111 1100:20:-NZVC:-----:--:10: CAS2.L #2 +0000 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2 +0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2 -0000 rrr1 00dd dDDD:00:-----:-----:--:12: MVPMR.W d[Areg-Ad16],Dr -0000 rrr1 01dd dDDD:00:-----:-----:--:12: MVPMR.L d[Areg-Ad16],Dr -0000 rrr1 10dd dDDD:00:-----:-----:--:12: MVPRM.W Dr,d[Areg-Ad16] -0000 rrr1 11dd dDDD:00:-----:-----:--:12: MVPRM.L Dr,d[Areg-Ad16] -0000 rrr1 00ss sSSS:00:--Z--:-----:--:11: BTST Dr,s[!Areg] -0000 rrr1 01ss sSSS:00:--Z--:-----:--:13: BCHG Dr,s[!Areg,Immd] -0000 rrr1 10ss sSSS:00:--Z--:-----:--:13: BCLR Dr,s[!Areg,Immd] -0000 rrr1 11ss sSSS:00:--Z--:-----:--:13: BSET Dr,s[!Areg,Immd] +0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr +0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr +0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16] +0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16] +0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg] +0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd] +0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd] +0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd] -0001 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.B s,d[!Areg] -0010 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.L s,d[Areg] -0010 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.L s,d[!Areg] -0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg] -0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg] +0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg] +0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg] +0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg] +0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg] +0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg] -0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg] -0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg] -0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg] -0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg] -0100 0100 zzdd dDDD:00:XNZVC:-----:--:30: NEG.z d[!Areg] -0100 0100 11ss sSSS:00:XNZVC:-----:--:10: MV2SR.B s[!Areg] -0100 0110 zzdd dDDD:00:-NZ00:-----:--:30: NOT.z d[!Areg] -0100 0110 11ss sSSS:02:XNZVC:XNZVC:T-:10: MV2SR.W s[!Areg] -0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2 -0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg] -0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k -0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] -0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] -0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] -0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] -0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] -0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] -0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s -0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg] -0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL -0100 1100 00ss sSSS:20:-NZVC:-----:--:13: MULL.L #1,s[!Areg] -0100 1100 01ss sSSS:20:-NZV0:-----:T-:13: DIVL.L #1,s[!Areg] -0100 1100 10ss sSSS:00:-----:-----:--:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd] -0100 1100 11ss sSSS:00:-----:-----:--:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd] -0100 1110 0100 JJJJ:00:-----:XNZVC:--:10: TRAP #J -0100 1110 0101 0rrr:00:-----:-----:--:31: LINK.W Ar,#1 -0100 1110 0101 1rrr:00:-----:-----:--:30: UNLK.L Ar -0100 1110 0110 0rrr:02:-----:-----:T-:10: MVR2USP.L Ar -0100 1110 0110 1rrr:02:-----:-----:T-:20: MVUSP2R.L Ar -0100 1110 0111 0000:02:-----:-----:T-:00: RESET -0100 1110 0111 0001:00:-----:-----:--:00: NOP -0100 1110 0111 0010:02:XNZVC:-----:T-:10: STOP #1 -0100 1110 0111 0011:02:XNZVC:-----:TR:00: RTE -0100 1110 0111 0100:00:-----:-----:-R:10: RTD #1 -0100 1110 0111 0101:00:-----:-----:-R:00: RTS -0100 1110 0111 0110:00:-----:XNZVC:T-:00: TRAPV -0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR -0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1 -0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1 -0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr -0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr -0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar +0100 0000 zzdd dDDD:00:XxZxC:-----:30: NEGX.z d[!Areg] +0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg] +0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg] +0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg] +0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg] +0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg] +0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg] +0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg] +0100 1000 0000 1rrr:20:-----:-----:31: LINK.L Ar,#2 +0100 1000 00dd dDDD:00:X?Z?C:X-Z--:30: NBCD.B d[!Areg] +0100 1000 0100 1kkk:20:?????:?????:10: BKPT #k +0100 1000 01ss sSSS:00:-NZ00:-----:30: SWAP.W s[Dreg] +0100 1000 01ss sSSS:00:-----:-----:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1000 10dd dDDD:00:-NZ00:-----:30: EXT.W d[Dreg] +0100 1000 10dd dDDD:00:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] +0100 1000 11dd dDDD:00:-NZ00:-----:30: EXT.L d[Dreg] +0100 1000 11dd dDDD:00:-----:-----:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] +0100 1001 11dd dDDD:00:-NZ00:-----:30: EXT.B d[Dreg] +0100 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s +0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg] +0100 1010 1111 1100:00:?????:?????:00: ILLEGAL +0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg] +0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg] +0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd] +0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd] +0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J +0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1 +0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar +0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar +0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar +0100 1110 0111 0000:02:-----:-----:00: RESET +0100 1110 0111 0001:00:-----:-----:00: NOP +0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1 +0100 1110 0111 0011:02:XNZVC:-----:00: RTE +0100 1110 0111 0100:00:?????:?????:10: RTD #1 +0100 1110 0111 0101:00:-----:-----:00: RTS +0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV +0100 1110 0111 0111:00:XNZVC:-----:00: RTR +0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1 +0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1 +0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 rrr1 00ss sSSS:00:?????:?????:11: CHK.L s[!Areg],Dr +0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr +0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar -0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] -0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] -0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg] -0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] -0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] -0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg] - -0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1 -0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg] -0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1 -0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2 -0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc +0101 jjj0 zzdd dDDD:00:-----:-----:13: ADDA.z #j,d[Areg] +0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg] +0101 jjj1 zzdd dDDD:00:-----:-----:13: SUBA.z #j,d[Areg] +0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg] +0101 cccc 1100 1rrr:00:-----:+++++:31: DBcc.W Dr,#1 +0101 cccc 11dd dDDD:00:-----:+++++:20: Scc.B d[!Areg] +0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1 +0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2 +0101 cccc 1111 1100:20:?????:?????:00: TRAPcc % Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal % instruction exceptions when compiling a 68000 only emulation, which isn't % what we want either. -0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1 -0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i -0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2 -0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1 -0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i -0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2 +0110 0001 0000 0000:00://///://///:40: BSR.W #1 +0110 0001 IIII IIII:00://///://///:40: BSR.B #i +0110 0001 1111 1111:00://///://///:40: BSR.L #2 +0110 CCCC 0000 0000:00:-----:+++++:40: Bcc.W #1 +0110 CCCC IIII IIII:00:-----:+++++:40: Bcc.B #i +0110 CCCC 1111 1111:00:-----:+++++:40: Bcc.L #2 -0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr +0111 rrr0 iiii iiii:00:-NZ00:-----:12: MOVE.L #i,Dr -1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr -1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp -1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg] -1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr -1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp -1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr -1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp -1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr +1000 rrr0 zzss sSSS:00:-NZ00:-----:13: OR.z s[!Areg],Dr +1000 rrr0 11ss sSSS:00:?????:?????:13: DIVU.W s[!Areg],Dr +1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Dreg],Dr +1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Areg-Apdi],Arp +1000 rrr1 zzdd dDDD:00:-NZ00:-----:13: OR.z Dr,d[!Areg,Dreg] +1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Dreg],Dr +1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Areg-Apdi],Arp +1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Dreg],Dr +1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Areg-Apdi],Arp +1000 rrr1 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],Dr -1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr -1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp -1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg] -1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar +1001 rrr0 zzss sSSS:00:XNZVC:-----:13: SUB.z s,Dr +1001 rrr0 11ss sSSS:00:-----:-----:13: SUBA.W s,Ar +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Dreg],Dr +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Areg-Apdi],Arp +1001 rrr1 zzdd dDDD:00:XNZVC:-----:13: SUB.z Dr,d[!Areg,Dreg] +1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar -1011 rrr0 zzss sSSS:00:-NZVC:-----:--:11: CMP.z s,Dr -1011 rrr0 11ss sSSS:00:-NZVC:-----:--:11: CMPA.W s,Ar -1011 rrr1 11ss sSSS:00:-NZVC:-----:--:11: CMPA.L s,Ar -1011 rrr1 zzdd dDDD:00:-NZVC:-----:--:11: CMPM.z d[Areg-Aipi],ArP -1011 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z Dr,d[!Areg] +1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr +1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar +1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar +1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP +1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg] -1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr -1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp -1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] -1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] -1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr +1100 rrr0 zzss sSSS:00:-NZ00:-----:13: AND.z s[!Areg],Dr +1100 rrr0 11ss sSSS:00:-NZ00:-----:13: MULU.W s[!Areg],Dr +1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Dreg],Dr +1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Areg-Apdi],Arp +1100 rrr1 zzdd dDDD:00:-NZ00:-----:13: AND.z Dr,d[!Areg,Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Dr,d[Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Ar,d[Areg] +1100 rrr1 10dd dDDD:00:-----:-----:33: EXG.L Dr,d[Areg] +1100 rrr1 11ss sSSS:00:-NZ00:-----:13: MULS.W s[!Areg],Dr -1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr -1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp -1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg] -1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar +1101 rrr0 zzss sSSS:00:XNZVC:-----:13: ADD.z s,Dr +1101 rrr0 11ss sSSS:00:-----:-----:13: ADDA.W s,Ar +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Dreg],Dr +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Areg-Apdi],Arp +1101 rrr1 zzdd dDDD:00:XNZVC:-----:13: ADD.z Dr,d[!Areg,Dreg] +1101 rrr1 11ss sSSS:00:-----:-----:13: ADDA.L s,Ar -1110 jjjf zz00 0RRR:00:XNZVC:-----:--:13: ASf.z #j,DR -1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR -1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR -1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR -1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR -1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR -1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR -1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR -1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg] -1110 001f 11dd dDDD:00:XNZ0C:-----:--:13: LSfW.W d[!Dreg,Areg] -1110 010f 11dd dDDD:00:XNZ0C:X----:--:13: ROXfW.W d[!Dreg,Areg] -1110 011f 11dd dDDD:00:-NZ0C:-----:--:13: ROfW.W d[!Dreg,Areg] +1110 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR +1110 jjjf zz00 1RRR:00:XNZ0C:-----:13: LSf.z #j,DR +1110 jjjf zz01 0RRR:00:XNZ0C:X----:13: ROXf.z #j,DR +1110 jjjf zz01 1RRR:00:-NZ0C:-----:13: ROf.z #j,DR +1110 rrrf zz10 0RRR:00:XNZVC:X----:13: ASf.z Dr,DR +1110 rrrf zz10 1RRR:00:XNZ0C:X----:13: LSf.z Dr,DR +1110 rrrf zz11 0RRR:00:XNZ0C:X----:13: ROXf.z Dr,DR +1110 rrrf zz11 1RRR:00:-NZ0C:-----:13: ROf.z Dr,DR +1110 000f 11dd dDDD:00:XNZVC:-----:13: ASfW.W d[!Dreg,Areg] +1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg] +1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg] +1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg] -1110 1000 11ss sSSS:20:-NZ00:-----:--:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd] -1110 1001 11ss sSSS:20:-NZ00:-----:--:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd] -1110 1010 11ss sSSS:20:-NZ00:-----:--:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1011 11ss sSSS:20:-NZ00:-----:--:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd] -1110 1100 11ss sSSS:20:-NZ00:-----:--:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1101 11ss sSSS:20:-NZ00:-----:--:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd] -1110 1110 11ss sSSS:20:-NZ00:-----:--:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1111 11ss sSSS:20:-NZ00:-----:--:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd] +1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd] +1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd] +1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd] +1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] % floating point co processor -1111 0010 00ss sSSS:30:-----:-----:--:11: FPP #1,s -1111 0010 01ss sSSS:30:-----:-----:-B:11: FDBcc #1,s[Areg-Dreg] -1111 0010 01ss sSSS:30:-----:-----:--:11: FScc #1,s[!Areg,Immd,PC8r,PC16] -1111 0010 0111 1010:30:-----:-----:T-:10: FTRAPcc #1 -1111 0010 0111 1011:30:-----:-----:T-:10: FTRAPcc #2 -1111 0010 0111 1100:30:-----:-----:T-:00: FTRAPcc -1111 0010 10KK KKKK:30:-----:-----:-B:11: FBcc #K,#1 -1111 0010 11KK KKKK:30:-----:-----:-B:11: FBcc #K,#2 -1111 0011 00ss sSSS:32:-----:-----:--:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16] -1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] +% TODO: FPU is currently commented out +% 1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s +% 1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg] +% 1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16] +% 1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1 +% 1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2 +% 1111 0010 0111 1100:30:?????:?????:00: FTRAPcc +% 1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1 +% 1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2 +% 1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16] +% 1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] % 68040 instructions -1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s -1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar -1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar -1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p -1111 0100 pp10 1rrr:42:-----:-----:T-:02: CPUSHL #p,Ar -1111 0100 pp11 0rrr:42:-----:-----:T-:02: CPUSHP #p,Ar -1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p -% destination register number is encoded in the following word -1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP -1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L -1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi] -1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L -1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind] - -% EmulOp instructions -0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN -0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E +1111 0100 ii00 1rrr:42:-----:-----:02: CINVL #i,Ar +1111 0100 ii01 0rrr:42:-----:-----:02: CINVP #i,Ar +1111 0100 ii01 1rrr:42:-----:-----:00: CINVA #i +1111 0100 ii10 1rrr:42:-----:-----:02: CPUSHL #i,Ar +1111 0100 ii11 0rrr:42:-----:-----:02: CPUSHP #i,Ar +1111 0100 ii11 1rrr:42:-----:-----:00: CPUSHA #i +1111 0110 0010 0rrr:40:-----:-----:12: MOVE16 ArP,ARP From 1758ef58b5b677daf9d0ae9df3751177ce7e718d Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 15 Apr 2018 20:23:12 -0500 Subject: [PATCH 05/20] Port of CPU code from ARAnyM (currently hangs) --- BasiliskII/src/Unix/CMakeLists.txt | 9 +- BasiliskII/src/Unix/main_unix.cpp | 5 +- BasiliskII/src/Unix/sysdeps.h | 11 + BasiliskII/src/include/main.h | 7 - BasiliskII/src/uae_cpu/Makefile.am | 80 + BasiliskII/src/uae_cpu/aranym_glue.cpp | 327 + BasiliskII/src/uae_cpu/basilisk_glue.cpp | 81 +- BasiliskII/src/uae_cpu/build68k.c | 71 +- .../src/uae_cpu/compiler/codegen_arm.cpp | 2872 +++++++ BasiliskII/src/uae_cpu/compiler/codegen_arm.h | 1292 ++++ .../src/uae_cpu/compiler/codegen_x86.cpp | 5372 +++++++++++++ BasiliskII/src/uae_cpu/compiler/codegen_x86.h | 1996 +++++ BasiliskII/src/uae_cpu/compiler/compemu.h | 543 ++ BasiliskII/src/uae_cpu/compiler/compemu1.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu2.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu3.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu4.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu5.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu6.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu7.cpp | 2 + BasiliskII/src/uae_cpu/compiler/compemu8.cpp | 2 + .../src/uae_cpu/compiler/compemu_fpp.cpp | 1638 ++++ .../uae_cpu/compiler/compemu_midfunc_arm.cpp | 2106 +++++ .../uae_cpu/compiler/compemu_midfunc_arm.h | 184 + .../uae_cpu/compiler/compemu_midfunc_arm2.cpp | 5428 +++++++++++++ .../uae_cpu/compiler/compemu_midfunc_arm2.h | 348 + .../uae_cpu/compiler/compemu_midfunc_x86.cpp | 2982 ++++++++ .../uae_cpu/compiler/compemu_midfunc_x86.h | 252 + .../src/uae_cpu/compiler/compemu_support.cpp | 5111 +++++++++++++ BasiliskII/src/uae_cpu/compiler/compstbla.cpp | 5 + BasiliskII/src/uae_cpu/compiler/flags_arm.h | 52 + BasiliskII/src/uae_cpu/compiler/flags_x86.h | 52 + BasiliskII/src/uae_cpu/compiler/gencomp.c | 3619 +++++++++ BasiliskII/src/uae_cpu/compiler/gencomp_arm.c | 4981 ++++++++++++ .../src/uae_cpu/compiler/test_codegen_arm.c | 264 + .../src/uae_cpu/compiler/test_codegen_x86.cpp | 1008 +++ BasiliskII/src/uae_cpu/cpu_emulation.h | 16 +- BasiliskII/src/uae_cpu/cpudefsa.cpp | 5 + BasiliskII/src/uae_cpu/cpuemu1.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu1_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu2.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu2_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu3.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu3_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu4.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu4_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu5.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu5_nf.cpp | 4 + BasiliskII/src/uae_cpu/cpuemu6.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu6_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu7.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu7_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu8.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu8_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpufunctbla.cpp | 5 + BasiliskII/src/uae_cpu/cpummu.cpp | 1096 +++ BasiliskII/src/uae_cpu/cpummu.h | 267 + BasiliskII/src/uae_cpu/cpuopti.c | 298 - BasiliskII/src/uae_cpu/cpustbl_nf.cpp | 2 + BasiliskII/src/uae_cpu/cpustbla.cpp | 5 + BasiliskII/src/uae_cpu/debug.cpp | 82 + BasiliskII/src/uae_cpu/fpu/core.h | 268 + BasiliskII/src/uae_cpu/fpu/exceptions.cpp | 193 + BasiliskII/src/uae_cpu/fpu/exceptions.h | 154 + BasiliskII/src/uae_cpu/fpu/flags.cpp | 174 + BasiliskII/src/uae_cpu/fpu/flags.h | 228 + BasiliskII/src/uae_cpu/fpu/fpu.h | 59 + BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp | 2330 ++++++ BasiliskII/src/uae_cpu/fpu/fpu_ieee.h | 154 + BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp | 2110 +++++ BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp | 2553 +++++++ BasiliskII/src/uae_cpu/fpu/fpu_uae.h | 217 + BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp | 6791 +++++++++++++++++ BasiliskII/src/uae_cpu/fpu/fpu_x86.h | 384 + BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h | 104 + BasiliskII/src/uae_cpu/fpu/impl.h | 159 + BasiliskII/src/uae_cpu/fpu/mathlib.cpp | 105 + BasiliskII/src/uae_cpu/fpu/mathlib.h | 1185 +++ BasiliskII/src/uae_cpu/fpu/rounding.cpp | 69 + BasiliskII/src/uae_cpu/fpu/rounding.h | 159 + BasiliskII/src/uae_cpu/fpu/types.h | 181 + BasiliskII/src/uae_cpu/gencpu.c | 1766 +++-- BasiliskII/src/uae_cpu/m68k.h | 705 +- BasiliskII/src/uae_cpu/memory-uae.h | 606 ++ BasiliskII/src/uae_cpu/memory.cpp | 59 + BasiliskII/src/uae_cpu/memory.h | 45 + BasiliskII/src/uae_cpu/newcpu.cpp | 1741 +++-- BasiliskII/src/uae_cpu/newcpu.h | 366 +- BasiliskII/src/uae_cpu/noflags.h | 142 + BasiliskII/src/uae_cpu/readcpu.cpp | 143 +- BasiliskII/src/uae_cpu/readcpu.h | 59 +- BasiliskII/src/uae_cpu/readcpua.cpp | 5 + BasiliskII/src/uae_cpu/registers.h | 116 + BasiliskII/src/uae_cpu/spcflags.h | 104 + BasiliskII/src/uae_cpu/table68k | 392 +- 95 files changed, 63979 insertions(+), 2376 deletions(-) create mode 100644 BasiliskII/src/uae_cpu/Makefile.am create mode 100644 BasiliskII/src/uae_cpu/aranym_glue.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/codegen_arm.h create mode 100644 BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/codegen_x86.h create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu.h create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu1.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu2.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu3.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu4.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu5.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu6.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu7.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu8.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.h create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h create mode 100644 BasiliskII/src/uae_cpu/compiler/compemu_support.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/compstbla.cpp create mode 100644 BasiliskII/src/uae_cpu/compiler/flags_arm.h create mode 100644 BasiliskII/src/uae_cpu/compiler/flags_x86.h create mode 100644 BasiliskII/src/uae_cpu/compiler/gencomp.c create mode 100644 BasiliskII/src/uae_cpu/compiler/gencomp_arm.c create mode 100644 BasiliskII/src/uae_cpu/compiler/test_codegen_arm.c create mode 100644 BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp create mode 100644 BasiliskII/src/uae_cpu/cpudefsa.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu1.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu1_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu2.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu2_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu3.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu3_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu4.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu4_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu5.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu5_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu6.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu6_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu7.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu7_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu8.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu8_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpufunctbla.cpp create mode 100644 BasiliskII/src/uae_cpu/cpummu.cpp create mode 100644 BasiliskII/src/uae_cpu/cpummu.h delete mode 100644 BasiliskII/src/uae_cpu/cpuopti.c create mode 100644 BasiliskII/src/uae_cpu/cpustbl_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpustbla.cpp create mode 100644 BasiliskII/src/uae_cpu/debug.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/core.h create mode 100644 BasiliskII/src/uae_cpu/fpu/exceptions.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/exceptions.h create mode 100644 BasiliskII/src/uae_cpu/fpu/flags.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/flags.h create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu.h create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_ieee.h create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_uae.h create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_x86.h create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h create mode 100644 BasiliskII/src/uae_cpu/fpu/impl.h create mode 100644 BasiliskII/src/uae_cpu/fpu/mathlib.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/mathlib.h create mode 100644 BasiliskII/src/uae_cpu/fpu/rounding.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/rounding.h create mode 100644 BasiliskII/src/uae_cpu/fpu/types.h create mode 100644 BasiliskII/src/uae_cpu/memory-uae.h create mode 100644 BasiliskII/src/uae_cpu/memory.cpp create mode 100644 BasiliskII/src/uae_cpu/noflags.h create mode 100644 BasiliskII/src/uae_cpu/readcpua.cpp create mode 100644 BasiliskII/src/uae_cpu/registers.h create mode 100644 BasiliskII/src/uae_cpu/spcflags.h diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index fca7bca0..65a607f8 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -15,7 +15,7 @@ add_custom_command(OUTPUT cpudefs.cpp add_executable(gencpu ../uae_cpu/gencpu.c ../uae_cpu/readcpu.cpp cpudefs.cpp) -add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp COMMAND gencpu DEPENDS gencpu) +add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu) set(BasiliskII_SRCS ../main.cpp @@ -76,10 +76,11 @@ set(BasiliskII_SRCS ../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp - # ../uae_cpu/fpp.cpp + ../uae_cpu/fpu/fpu_uae.cpp cpustbl.cpp cpudefs.cpp cpuemu.cpp + cpufunctbl.cpp #addressing mode =direct -DDIRECT_ADDRESSING #includes ) @@ -87,8 +88,10 @@ set(BasiliskII_SRCS add_executable(BasiliskII ${BasiliskII_SRCS}) set_source_files_properties(${BasiliskII_SRCS} - PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DDATADIR=\\\".\\\"") + PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"") target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY}) + + #keycodes -> ../SDL/keycodes diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 644c215b..3affe236 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -199,9 +199,8 @@ static void sigsegv_dump_state(sigsegv_info_t *sip) fprintf(stderr, " [IP=%p]", fault_instruction); fprintf(stderr, "\n"); #if EMULATED_68K - uaecptr nextpc; - extern void m68k_dumpstate(uaecptr *nextpc); - m68k_dumpstate(&nextpc); + extern void m68k_dumpstate (FILE *, uaecptr *); + m68k_dumpstate(stderr, 0); #endif VideoQuitFullScreen(); diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index 8dd77b1d..56b7a71d 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -712,6 +712,17 @@ static inline uae_u32 do_byteswap_16(uae_u32 v) #endif #define REGPARAM2 + +#if __GNUC__ < 3 +# define __builtin_expect(foo,bar) (foo) +#endif +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#define ALWAYS_INLINE inline __attribute__((always_inline)) + +#define memptr uint32 + + #endif /* NEED_CONFIG_H_ONLY */ #endif diff --git a/BasiliskII/src/include/main.h b/BasiliskII/src/include/main.h index 1ba7b6ac..b55ddc6d 100644 --- a/BasiliskII/src/include/main.h +++ b/BasiliskII/src/include/main.h @@ -31,13 +31,6 @@ extern int FPUType; // Flag: 24-bit-addressing? extern bool TwentyFourBitAddressing; -// 68k register structure (for Execute68k()) -struct M68kRegisters { - uint32 d[8]; - uint32 a[8]; - uint16 sr; -}; - // General functions extern bool InitAll(const char *vmdir); extern void ExitAll(void); diff --git a/BasiliskII/src/uae_cpu/Makefile.am b/BasiliskII/src/uae_cpu/Makefile.am new file mode 100644 index 00000000..0f27219d --- /dev/null +++ b/BasiliskII/src/uae_cpu/Makefile.am @@ -0,0 +1,80 @@ +# +# Note: this Makefile only contains rules for the source +# generator tools. +# + +# +# suppress warnings about overriding LDFLAGS and CPPFLAGS +# +AUTOMAKE_OPTIONS = -Wno-gnu + +AM_CPPFLAGS = $(DEFINES) \ + "-I$(srcdir)/../include" \ + "-I$(srcdir)/../Unix" \ + "-I$(builddir)/.." \ + "-I$(builddir)" \ + "-I$(srcdir)" + +CC = $(CC_FOR_BUILD) +CXX = $(CXX_FOR_BUILD) + +LDFLAGS = $(LDFLAGS_FOR_BUILD) +CPPFLAGS = $(CPPFLAGS_FOR_BUILD) +CFLAGS = $(CFLAGS_FOR_BUILD) +CXXFLAGS = $(CXXFLAGS_FOR_BUILD) +LIBS=-lm + +CFLAGS_NOWARN = $(DBGSP) +AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS) +AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS) + +noinst_PROGRAMS = build68k gencpu +if USE_JIT +noinst_PROGRAMS += gencomp +endif + +BUILT_SOURCES = \ + cpudefs.cpp \ + cpuemu.cpp \ + cpustbl.cpp \ + cpufunctbl.cpp \ + cputbl.h \ + $(empty) + +build68k_SOURCES = build68k.c +gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp +gencomp_SOURCES = +if GENCOMP_ARCH_X86 +gencomp_SOURCES += compiler/gencomp.c +endif +if GENCOMP_ARCH_ARM +gencomp_SOURCES += compiler/gencomp_arm.c +endif +gencomp_SOURCES += readcpu.cpp cpudefs.cpp + +if USE_JIT +BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h +endif + + +cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k + ./build68k <$(srcdir)/table68k > $@ +cpuemu.cpp: gencpu$(EXEEXT) + ./gencpu$(EXEEXT) +cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp +compemu.cpp: gencomp$(EXEEXT) + ./gencomp$(EXEEXT) +compstbl.cpp comptbl.h: compemu.cpp + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = \ + table68k \ + compiler/codegen_arm.cpp compiler/codegen_arm.h \ + compiler/compemu_midfunc_arm.cpp compiler/compemu_midfunc_arm.h \ + compiler/compemu_midfunc_arm2.cpp compiler/compemu_midfunc_arm2.h \ + compiler/test_codegen_arm.c \ + compiler/codegen_x86.cpp compiler/codegen_x86.h \ + compiler/compemu_midfunc_x86.cpp compiler/compemu_midfunc_x86.h \ + compiler/test_codegen_x86.cpp \ + $(empty) diff --git a/BasiliskII/src/uae_cpu/aranym_glue.cpp b/BasiliskII/src/uae_cpu/aranym_glue.cpp new file mode 100644 index 00000000..7148d446 --- /dev/null +++ b/BasiliskII/src/uae_cpu/aranym_glue.cpp @@ -0,0 +1,327 @@ +/* + * aranym_glue.cpp - CPU interface + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "cpu_emulation.h" +#include "newcpu.h" +#include "hardware.h" +#include "input.h" +#ifdef USE_JIT +# include "compiler/compemu.h" +#endif +#include "nf_objs.h" + +#include "debug.h" + +// RAM and ROM pointers +memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important +uint8 *RAMBaseHost; // RAM base (host address space) +uint32 RAMSize = 0x00e00000; // Size of RAM + +memptr ROMBase = 0x00e00000; // ROM base (Atari address space) +uint8 *ROMBaseHost; // ROM base (host address space) +uint32 ROMSize = 0x00100000; // Size of ROM + +uint32 RealROMSize; // Real size of ROM + +memptr HWBase = 0x00f00000; // HW base (Atari address space) +uint8 *HWBaseHost; // HW base (host address space) +uint32 HWSize = 0x00100000; // Size of HW space + +memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space) +uint8 *FastRAMBaseHost; // Fast-RAM base (host address space) + +#ifdef HW_SIGSEGV +uint8 *FakeIOBaseHost; +#endif + +#ifdef FIXED_VIDEORAM +memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space) +#else +memptr VideoRAMBase; // VideoRAM base (Atari address space) +#endif +uint8 *VideoRAMBaseHost;// VideoRAM base (host address space) +//uint32 VideoRAMSize; // Size of VideoRAM + +#ifndef NOT_MALLOC +uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent +uintptr ROMBaseDiff; +uintptr FastRAMBaseDiff; +#endif + +uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap + +// From newcpu.cpp +extern int quit_program; + +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) +SDL_mutex *spcflags_lock; +#endif +#if defined(ENABLE_REALSTOP) +SDL_cond *stop_condition; +#endif + + +/* + * Initialize 680x0 emulation + */ + +bool InitMEM() { + InitMEMBaseDiff(RAMBaseHost, RAMBase); + InitROMBaseDiff(ROMBaseHost, ROMBase); + InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase); + InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase); + return true; +} + +bool Init680x0(void) +{ + init_m68k(); + +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) + if ((spcflags_lock = SDL_CreateMutex()) == NULL) { + panicbug("Error by SDL_CreateMutex()"); + exit(EXIT_FAILURE); + } +#endif + +#if ENABLE_REALSTOP + if ((stop_condition = SDL_CreateCond()) == NULL) { + panicbug("Error by SDL_CreateCond()"); + exit(EXIT_FAILURE); + } +#endif + +#ifdef USE_JIT + if (bx_options.jit.jit) compiler_init(); +#endif + return true; +} + +/* + * Instr. RESET + */ + +void AtariReset(void) +{ + // reset Atari hardware here + HWReset(); + // reset NatFeats here + NFReset(); + // reset the input devices (input.cpp) + InputReset(); + +} + +/* + * Reset CPU + */ + +void Reset680x0(void) +{ + m68k_reset(); +} + +/* + * Deinitialize 680x0 emulation + */ + +void Exit680x0(void) +{ +#ifdef USE_JIT + if (bx_options.jit.jit) compiler_exit(); +#endif + exit_m68k(); +} + + +/* + * Reset and start 680x0 emulation + */ + +void Start680x0(void) +{ + m68k_reset(); +#ifdef USE_JIT + if (bx_options.jit.jit) { + m68k_compile_execute(); + } + else +#endif + m68k_execute(); +} + +/* + * Restart running 680x0 emulation safely from different thread + */ +void Restart680x0(void) +{ + quit_program = 2; + TriggerNMI(); +} + +/* + * Quit 680x0 emulation safely from different thread + */ +void Quit680x0(void) +{ + quit_program = 1; + TriggerNMI(); +} + + +int MFPdoInterrupt(void) +{ + return getMFP()->doInterrupt(); +} + +int SCCdoInterrupt(void) +{ + return getSCC()->doInterrupt(); +} + +/* + * Trigger interrupts + */ +void TriggerInternalIRQ(void) +{ + SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ ); +} + +void TriggerInt3(void) +{ + SPCFLAGS_SET( SPCFLAG_INT3 ); +} + +void TriggerVBL(void) +{ + SPCFLAGS_SET( SPCFLAG_VBL ); +} + +void TriggerInt5(void) +{ + SPCFLAGS_SET( SPCFLAG_INT5 ); +} + +void TriggerSCC(bool enable) +{ + if (enable) + SPCFLAGS_SET( SPCFLAG_SCC ); + else + SPCFLAGS_CLEAR( SPCFLAG_SCC ); +} + +void TriggerMFP(bool enable) +{ + if (enable) + SPCFLAGS_SET( SPCFLAG_MFP ); + else + SPCFLAGS_CLEAR( SPCFLAG_MFP ); +} + +void TriggerNMI(void) +{ + SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI +} + +#ifndef REBOOT_OR_HALT +#define REBOOT_OR_HALT 0 // halt by default +#endif + +#if REBOOT_OR_HALT == 1 +# define CPU_MSG "CPU: Rebooting" +# define CPU_ACTION Restart680x0() +#else +# define CPU_MSG "CPU: Halting" +# define CPU_ACTION Quit680x0() +#endif + +#ifdef ENABLE_EPSLIMITER + +#ifndef EPS_LIMIT +# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */ +#endif + +void check_eps_limit(uaecptr pc) +{ + static long last_exception_time=-1; + static long exception_per_sec=0; + static long exception_per_sec_pc=0; + static uaecptr prevpc = 0; + + if (bx_options.cpu.eps_enabled) { + if (last_exception_time == -1) { + last_exception_time = SDL_GetTicks(); + } + + exception_per_sec++; + + if (pc == prevpc) { + /* BUS ERRORs occur at the same PC - watch out! */ + exception_per_sec_pc++; + } + else { + exception_per_sec_pc = 0; + prevpc = pc; + } + + if (SDL_GetTicks() - last_exception_time > 1000) { + last_exception_time = SDL_GetTicks(); + if (exception_per_sec_pc > bx_options.cpu.eps_max || + exception_per_sec > EPS_LIMIT /* make it configurable */) { + panicbug("CPU: Exception per second limit reached: %ld/%ld", + exception_per_sec_pc, exception_per_sec); + /* would be cool to open SDL dialog here: */ + /* [Exception per seconds limit reached. XXXXX exception + occured in the last second. The limit is set to YYYYY + in your config file. Do you want to continue emulation, + reset ARAnyM or quit ?][Continue] [Reset] [Quit] + */ + panicbug(CPU_MSG); + CPU_ACTION; + } + exception_per_sec = 0; + exception_per_sec_pc = 0; + } + } +} +#endif + +void report_double_bus_error() +{ + panicbug("CPU: Double bus fault detected !"); + /* would be cool to open SDL dialog here: */ + /* [Double bus fault detected. The emulated system crashed badly. + Do you want to reset ARAnyM or quit ?] [Reset] [Quit]" + */ + panicbug(CPU_MSG); + CPU_ACTION; +} + +#ifdef FLIGHT_RECORDER +extern bool cpu_flight_recorder_active; +void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; } +#endif diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index 9d344816..1b03160a 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -1,7 +1,7 @@ /* * basilisk_glue.cpp - Glue UAE CPU to Basilisk II CPU engine interface * - * Basilisk II (C) 1997-1999 Christian Bauer + * Basilisk II (C) 1997-2008 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,8 +19,10 @@ */ #include "sysdeps.h" + #include "cpu_emulation.h" #include "main.h" +#include "prefs.h" #include "emul_op.h" #include "rom_patches.h" #include "timer.h" @@ -28,9 +30,11 @@ #include "memory.h" #include "readcpu.h" #include "newcpu.h" +#include "compiler/compemu.h" + // RAM and ROM pointers -uint32 RAMBaseMac; // RAM base (Mac address space) +uint32 RAMBaseMac = 0; // RAM base (Mac address space) gb-- initializer is important uint8 *RAMBaseHost; // RAM base (host address space) uint32 RAMSize; // Size of RAM uint32 ROMBaseMac; // ROM base (Mac address space) @@ -48,8 +52,12 @@ int MacFrameLayout; // Frame buffer layout uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equivalent #endif +#if USE_JIT +bool UseJIT = false; +#endif + // From newcpu.cpp -extern int quit_program; +extern bool quit_program; /* @@ -59,13 +67,41 @@ extern int quit_program; bool Init680x0(void) { #if REAL_ADDRESSING + // Mac address space = host address space + RAMBaseMac = (uintptr)RAMBaseHost; + ROMBaseMac = (uintptr)ROMBaseHost; +#elif DIRECT_ADDRESSING // Mac address space = host address space minus constant offset (MEMBaseDiff) // NOTE: MEMBaseDiff is set up in main_unix.cpp/main() RAMBaseMac = 0; ROMBaseMac = Host2MacAddr(ROMBaseHost); +#else + // Initialize UAE memory banks + RAMBaseMac = 0; + switch (ROMVersion) { + case ROM_VERSION_64K: + case ROM_VERSION_PLUS: + case ROM_VERSION_CLASSIC: + ROMBaseMac = 0x00400000; + break; + case ROM_VERSION_II: + ROMBaseMac = 0x00a00000; + break; + case ROM_VERSION_32: + ROMBaseMac = 0x40800000; + break; + default: + return false; + } + memory_init(); #endif init_m68k(); +#if USE_JIT + UseJIT = compiler_use_jit(); + if (UseJIT) + compiler_init(); +#endif return true; } @@ -76,9 +112,25 @@ bool Init680x0(void) void Exit680x0(void) { +#if USE_JIT + if (UseJIT) + compiler_exit(); +#endif + exit_m68k(); } +/* + * Initialize memory mapping of frame buffer (called upon video mode change) + */ + +void InitFrameBufferMapping(void) +{ +#if !REAL_ADDRESSING && !DIRECT_ADDRESSING + memory_init(); +#endif +} + /* * Reset and start 680x0 emulation (doesn't return) */ @@ -86,7 +138,12 @@ void Exit680x0(void) void Start680x0(void) { m68k_reset(); - m68k_go(true); +#if USE_JIT + if (UseJIT) + m68k_compile_execute(); + else +#endif + m68k_execute(); } @@ -97,7 +154,7 @@ void Start680x0(void) void TriggerInterrupt(void) { idle_resume(); - regs.spcflags |= SPCFLAG_INT; + SPCFLAGS_SET( SPCFLAG_INT ); } void TriggerNMI(void) @@ -143,8 +200,8 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) // Execute trap m68k_setpc(m68k_areg(regs, 7)); fill_prefetch_0(); - quit_program = 0; - m68k_go(true); + quit_program = false; + m68k_execute(); // Clean up stack m68k_areg(regs, 7) += 4; @@ -158,7 +215,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) r->d[i] = m68k_dreg(regs, i); for (i=0; i<7; i++) r->a[i] = m68k_areg(regs, i); - quit_program = 0; + quit_program = false; } @@ -190,8 +247,8 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) // Execute routine m68k_setpc(addr); fill_prefetch_0(); - quit_program = 0; - m68k_go(true); + quit_program = false; + m68k_execute(); // Clean up stack m68k_areg(regs, 7) += 2; @@ -205,5 +262,7 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) r->d[i] = m68k_dreg(regs, i); for (i=0; i<7; i++) r->a[i] = m68k_areg(regs, i); - quit_program = 0; + quit_program = false; } + +void report_double_bus_error() {} diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index 42a7de8b..e996758d 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -1,3 +1,27 @@ +/* + * build68k.c - m68k CPU builder + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * @@ -6,13 +30,15 @@ * Copyright 1995,1996 Bernd Schmidt */ -#include -#include -#include - -#include "sysdeps.h" #include "readcpu.h" +#include +#include +#include +#include +#include +#undef abort + static FILE *tablef; static int nextch = 0; @@ -51,7 +77,7 @@ static int nextchtohex(void) } } -int main(int argc, char **argv) +int main() { int no_insns = 0; @@ -76,6 +102,7 @@ int main(int argc, char **argv) char opcstr[256]; int bitpos[16]; int flagset[5], flaguse[5]; + char cflow; unsigned int bitmask,bitpattern; int n_variable; @@ -107,6 +134,8 @@ int main(int argc, char **argv) case 'r': currbit = bitr; break; case 'R': currbit = bitR; break; case 'z': currbit = bitz; break; + case 'E': currbit = bitE; break; + case 'p': currbit = bitp; break; default: abort(); } if (!(bitmask & 1)) { @@ -121,6 +150,7 @@ int main(int argc, char **argv) patbits[i] = nextch; getnextch(); } + (void) patbits; while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */ getnextch(); @@ -156,6 +186,7 @@ int main(int argc, char **argv) switch(nextch){ case '-': flagset[i] = fa_unset; break; case '/': flagset[i] = fa_isjmp; break; + case '+': flagset[i] = fa_isbranch; break; case '0': flagset[i] = fa_zero; break; case '1': flagset[i] = fa_one; break; case 'x': flagset[i] = fa_dontcare; break; @@ -182,6 +213,26 @@ int main(int argc, char **argv) } } + getnextch(); + while (isspace(nextch)) + getnextch(); + + if (nextch != ':') /* Get control flow information */ + abort(); + + cflow = 0; + for(i = 0; i < 2; i++) { + getnextch(); + switch(nextch){ + case '-': break; + case 'R': cflow |= fl_return; break; + case 'B': cflow |= fl_branch; break; + case 'J': cflow |= fl_jump; break; + case 'T': cflow |= fl_trap; break; + default: abort(); + } + } + getnextch(); while (isspace(nextch)) getnextch(); @@ -201,7 +252,7 @@ int main(int argc, char **argv) if (nextch != ':') abort(); - fgets(opcstr, 250, tablef); + assert(fgets(opcstr, 250, tablef) != NULL); getnextch(); { int j; @@ -209,12 +260,12 @@ int main(int argc, char **argv) char *opstrp = opcstr, *osendp; int slen = 0; - while (isspace(*opstrp)) + while (isspace((int)*opstrp)) opstrp++; osendp = opstrp; while (*osendp) { - if (!isspace (*osendp)) + if (!isspace ((int)*osendp)) slen = osendp - opstrp + 1; osendp++; } @@ -233,7 +284,7 @@ int main(int argc, char **argv) for(i = 0; i < 5; i++) { printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ','); } - printf("}, %d, \"%s\"}", sduse, opstrp); + printf("}, %d, %d, \"%s\"}", cflow, sduse, opstrp); } } printf("};\nint n_defs68k = %d;\n", no_insns); diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp new file mode 100644 index 00000000..fb7e69c7 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp @@ -0,0 +1,2872 @@ +/* + * compiler/codegen_arm.cpp - ARM code generator + * + * Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> ARM + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Current state: + * - Experimental + * - Still optimizable + * - Not clock cycle optimized + * - as a first step this compiler emulates x86 instruction to be compatible + * with gencomp. Better would be a specialized version of gencomp compiling + * 68k instructions to ARM compatible instructions. This is a step for the + * future + * + */ + +#include "flags_arm.h" + +// Declare the built-in __clear_cache function. +extern void __clear_cache (char*, char*); + +/************************************************************************* + * Some basic information about the the target CPU * + *************************************************************************/ + +#define R0_INDEX 0 +#define R1_INDEX 1 +#define R2_INDEX 2 +#define R3_INDEX 3 +#define R4_INDEX 4 +#define R5_INDEX 5 +#define R6_INDEX 6 +#define R7_INDEX 7 +#define R8_INDEX 8 +#define R9_INDEX 9 +#define R10_INDEX 10 +#define R11_INDEX 11 +#define R12_INDEX 12 +#define R13_INDEX 13 +#define R14_INDEX 14 +#define R15_INDEX 15 + +#define RSP_INDEX 13 +#define RLR_INDEX 14 +#define RPC_INDEX 15 + +/* The register in which subroutines return an integer return value */ +#define REG_RESULT R0_INDEX + +/* The registers subroutines take their first and second argument in */ +#define REG_PAR1 R0_INDEX +#define REG_PAR2 R1_INDEX + +#define REG_WORK1 R2_INDEX +#define REG_WORK2 R3_INDEX + +//#define REG_DATAPTR R10_INDEX + +#define REG_PC_PRE R0_INDEX /* The register we use for preloading regs.pc_p */ +#define REG_PC_TMP R1_INDEX /* Another register that is not the above */ + +#define SHIFTCOUNT_NREG R1_INDEX /* Register that can be used for shiftcount. + -1 if any reg will do. Normally this can be set to -1 but compemu_support is tied to 1 */ +#define MUL_NREG1 R0_INDEX /* %r4 will hold the low 32 bits after a 32x32 mul */ +#define MUL_NREG2 R1_INDEX /* %r5 will hold the high 32 bits */ + +#define STACK_ALIGN 4 +#define STACK_OFFSET sizeof(void *) +#define STACK_SHADOW_SPACE 0 + +uae_s8 always_used[]={2,3,-1}; +uae_s8 can_byte[]={0,1,4,5,6,7,8,9,10,11,12,-1}; +uae_s8 can_word[]={0,1,4,5,6,7,8,9,10,11,12,-1}; + +uae_u8 call_saved[]={0,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1}; + +/* This *should* be the same as call_saved. But: + - We might not really know which registers are saved, and which aren't, + so we need to preserve some, but don't want to rely on everyone else + also saving those registers + - Special registers (such like the stack pointer) should not be "preserved" + by pushing, even though they are "saved" across function calls +*/ +static const uae_u8 need_to_preserve[]={0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0}; +static const uae_u32 PRESERVE_MASK = ((1<=-128 && x<=127); +} + +static inline int is8bit(uae_s32 x) +{ + return (x>=-255 && x<=255); +} + +static inline int isword(uae_s32 x) +{ + return (x>=-32768 && x<=32767); +} + +#define jit_unimplemented(fmt, ...) do{ panicbug("**** Unimplemented ****"); panicbug(fmt, ## __VA_ARGS__); abort(); }while (0) + +#if 0 /* currently unused */ +static void jit_fail(const char *msg, const char *file, int line, const char *function) +{ + panicbug("JIT failure in function %s from file %s at line %d: %s", + function, file, line, msg); + abort(); +} +#endif + +LOWFUNC(NONE,WRITE,1,raw_push_l_r,(RR4 r)) +{ + PUSH(r); +} +LENDFUNC(NONE,WRITE,1,raw_push_l_r,(RR4 r)) + +LOWFUNC(NONE,READ,1,raw_pop_l_r,(RR4 r)) +{ + POP(r); +} +LENDFUNC(NONE,READ,1,raw_pop_l_r,(RR4 r)) + +LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, RR1 s)) +{ + MVN_ri(REG_WORK1, 0); // mvn r2,#0 + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + ORR_rrrLSRi(REG_WORK2, REG_WORK2, REG_WORK1, 8); // orr r3, r3, r2, lsr #8 + LSL_rri(REG_WORK1, s, 24); // lsl r2, %[s], #24 + + ADCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adcs r3, r3, r2 + + BIC_rri(d, d, 0xFF); // bic %[d],%[d],#0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], R3 LSR #24 +} +LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, RR1 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, RR2 s)) +{ + MVN_ri(REG_WORK1, 0); // mvn r2,#0 + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #16 + ORR_rrrLSRi(REG_WORK2, REG_WORK2, REG_WORK1, 16); // orr r3, r3, r2, lsr #16 + LSL_rri(REG_WORK1, s, 16); // lsl r2, %[s], #16 + + ADCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 +#ifdef ARMV6_ASSEMBLY + PKHTB_rrrASRi(d,d,REG_WORK2,16); +#else + BIC_rri(d, d, 0xff); // bic %[d],%[d],#0xff + BIC_rri(d, d, 0xff00); // bic %[d],%[d],#0xff00 + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr %[d], %[d], r3, lsr #16 +#endif +} +LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, RR2 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, RR4 s)) +{ + ADCS_rrr(d, d, s); // adcs %[d],%[d],%[s] +} +LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, RR1 s)) +{ + LSL_rri(REG_WORK1, s, 24); // lsl r2, %[s], #24 + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + + ADDS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + + BIC_rri(d, d, 0xFF); // bic %[d],%[d],#0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], r3 LSR #24 +} +LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, RR2 s)) +{ + LSL_rri(REG_WORK1, s, 16); // lsl r2, %[s], #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #16 + + ADDS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + +#ifdef ARMV6_ASSEMBLY + PKHTB_rrrASRi(d,d,REG_WORK2,16); +#else + BIC_rri(d, d, 0xff); // bic %[d],%[d],#0xff + BIC_rri(d, d, 0xff00); // bic %[d],%[d],#0xff00 + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3, LSR #16 +#endif +} +LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, RR4 s)) +{ + ADDS_rrr(d, d, s); // adds %[d], %[d], %[s] +} +LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldrh r2, [pc, #offs] +#else +# ifdef ARMV6_ASSEMBLY + LDRH_rRI(REG_WORK1, RPC_INDEX, 24); // ldrh r2, [pc, #24] ; +# else + LDRH_rRI(REG_WORK1, RPC_INDEX, 16); // ldrh r2, [pc, #16] ; +# endif +#endif + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #16 + LSL_rri(REG_WORK1, REG_WORK1, 16); // lsl r2, r2, #16 + + ADDS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + +#ifdef ARMV6_ASSEMBLY + PKHTB_rrrASRi(d,d,REG_WORK2,16); +#else + BIC_rri(d, d, 0xff); // bic %[d],%[d],#0xff + BIC_rri(d, d, 0xff00); // bic %[d],%[d],#0xff00 + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr %[d],%[d], r3, LSR #16 +#endif + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_word(i); + skip_word(0); + //: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) +{ + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + + ADDS_rri(REG_WORK2, REG_WORK2, i << 24); // adds r3, r3, #0x12000000 + + BIC_rri(d, d, 0xFF); // bic %[d],%[d], #0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], r3, lsr #24 +} +LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + ADDS_rrr(d, d, REG_WORK1); // adds %[d], %[d], r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADDS_rrr(d, d, REG_WORK1); // adds %[d], %[d], r2 + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, RR1 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 24); // mvn r2, %[s], lsl #24 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 24); // mvn r2, %[s], lsr #24 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 + + LSLS_rri(REG_WORK1, d, 24); // lsls r2, %[d], #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, RR2 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 16); // mvn r2, %[s], lsl #16 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 16); // mvn r2, %[s], lsr #16 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 + + LSLS_rri(REG_WORK1, d, 16); // lsls r2, %[d], #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, RR4 s)) +{ + ANDS_rrr(d, d, s); // ands r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +#endif + ANDS_rrr(d, d, REG_WORK1); // ands %[d], %[d], r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, RR4 s)) +{ + MOV_rr(REG_WORK1, s); // mov r2,%[s] + RSB_rri(REG_WORK2, REG_WORK1, 0); // rsb r3,r2,#0 + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // and r2,r2,r3 + CLZ_rr(REG_WORK2, REG_WORK1); // clz r3,r2 + MOV_ri(d, 32); // mov %[d],#32 + SUB_rrr(d, d, REG_WORK2); // sub %[d],%[d],r3 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TEQ_ri(d, 0); // teq %[d],#0 + CC_SUBS_rri(NATIVE_CC_NE, d,d,1); // sub %[d],%[d],#1 + CC_BIC_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_Z_FLAG); // bic r3,r3,#0x40000000 + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_Z_FLAG); // orr r3,r3,#0x40000000 + MSR_CPSR_r(REG_WORK2); // msr cpsr,r3 +} +LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) +{ +#if defined(ARMV6_ASSEMBLY) + REVSH_rr(REG_WORK1,r); // revsh r2,%[r] + UXTH_rr(REG_WORK1, REG_WORK1); // utxh r2,r2 + LSR_rri(r, r, 16); + ORR_rrrLSLi(r, REG_WORK1, r, 16); // orr %[r], %[r], r2 +#else + MOV_rr(REG_WORK1, r); // mov r2, r6 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2, r2, #0xff0000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // bic r2, r2, #0xff000000 + + EOR_rrr(r, r, REG_WORK1); // eor r6, r6, r2 + + ORR_rrrLSRi(r, r, REG_WORK1, 8); // orr r6, r6, r2, lsr #8 + BIC_rri(REG_WORK1, REG_WORK1, 0xff00); // bic r2, r2, #0xff00 + ORR_rrrLSLi(r,r,REG_WORK1, 8); // orr r6, r6, r2, lsl #8 +#endif +} +LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) + +LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) +{ +#if defined(ARMV6_ASSEMBLY) + REV_rr(r,r); // rev %[r],%[r] +#else + EOR_rrrRORi(REG_WORK1, r, r, 16); // eor r2, r6, r6, ror #16 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2, r2, #0xff0000 + ROR_rri(r, r, 8); // ror r6, r6, #8 + EOR_rrrLSRi(r, r, REG_WORK1, 8); // eor r6, r6, r2, lsr #8 +#endif +} +LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) + +LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(RR4 r, IMM i)) +{ + int imm = (1 << (i & 0x1f)); + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_ri(r, imm); // tst r6, #0x1000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} +LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(RR4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(RR4 r, RR4 b)) +{ + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSR_rrr(REG_WORK1, r, REG_WORK2); // lsr r2, r6, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_ri(REG_WORK1, 1); // tst r2, #1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} +LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(RR4 r, RR4 b)) + +LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, RR4 b)) +{ + MOV_ri(REG_WORK1, 1); // mov r2, #1 + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSL_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // lsl r2, r2, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_rr(r, REG_WORK1); // tst r6, r2 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + EOR_rrr(r, r, REG_WORK1); // eor r6, r6, r2 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} +LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, RR4 b)) + +LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, RR4 b)) +{ + MOV_ri(REG_WORK1, 1); // mov r2, #1 + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSL_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // lsl r2, r2, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_rr(r, REG_WORK1); // tst r6, r2 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + BIC_rrr(r, r, REG_WORK1); // bic r6, r6, r2 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} +LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, RR4 b)) + +LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, RR4 b)) +{ + MOV_ri(REG_WORK1, 1); // mov r2, #1 + AND_rri(REG_WORK2, b, 0x1f); // and r3, r7, #0x1f + LSL_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // lsl r2, r2, r3 + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_rr(r, REG_WORK1); // tst r6, r2 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + ORR_rrr(r, r, REG_WORK1); // orr r6, r6, r2 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} +LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, RR4 b)) + +LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, RR4 s, IMM cc)) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq Z != 0 + BCC_i(0); // bcc C == 0 + + //: + MOV_rr(d, s); // mov r7,r6 + break; + + case 8: // HI + BEQ_i(1); // beq Z != 0 + BCS_i(0); // bcs C != 0 + MOV_rr(d, s); // mov r7,#0 + break; + + default: + CC_MOV_rr(cc, d, s); // MOVcc R7,#1 + break; + } + //: +} +LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, RR4 s, IMM cc)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_b,(RR1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(REG_WORK1, d); // sxtb r2,%[d] + SXTB_rr(REG_WORK2, s); // sxtb r3,%[s] +#else + LSL_rri(REG_WORK1, d, 24); // lsl r2,r6,#24 + LSL_rri(REG_WORK2, s, 24); // lsl r3,r7,#24 +#endif + CMP_rr(REG_WORK1, REG_WORK2); // cmp r2, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_cmp_b,(RR1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_w,(RR2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTH_rr(REG_WORK1, d); // sxtb r2,%[d] + SXTH_rr(REG_WORK2, s); // sxtb r3,%[s] +#else + LSL_rri(REG_WORK1, d, 16); // lsl r6, r1, #16 + LSL_rri(REG_WORK2, s, 16); // lsl r7, r2, #16 +#endif + + CMP_rr(REG_WORK1, REG_WORK2); // cmp r7, r6, asr #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_cmp_w,(RR2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_l,(RR4 d, RR4 s)) +{ + CMP_rr(d, s); // cmp r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_cmp_l,(RR4 d, RR4 s)) + +LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, RR4 s)) +{ + SMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // smull r2,r3,r7,r6 + MOV_rr(d, REG_WORK1); // mov r7,r2 +} +LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, RR4 s)) + +LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) +{ + SMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // smull r2,r3,r7,r6 + MOV_rr(MUL_NREG1, REG_WORK1); // mov r7,r2 + MOV_rr(MUL_NREG2, REG_WORK2); +} +LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) + +LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} +LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // LDR R2,[PC, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // LDR R2,[PC, #8] +#endif + ADD_rrr(REG_WORK1, s, REG_WORK1); // ADD R7,R6,R2 + ADD_rrrLSLi(d, REG_WORK1, index, shft); // ADD R7,R7,R5,LSL #2 +#if !defined(USE_DATA_BUFFER) + B_i(0); // B jp + + emit_long(offset); + //; +#endif +} +LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) + +LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + ADD_rrrLSLi(d, s, index, shft); // ADD R7,R6,R5,LSL #2 +} +LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) + +LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + LDRB_rRR(REG_WORK1, REG_WORK1, s); // ldrb r2, [r2, r6] + + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} +LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(RR4 d, RR1 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2,[pc, #offs] + STRB_rRR(s, d, REG_WORK1); // strb r6,[r7, r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2,[pc,#4] + STRB_rRR(s, d, REG_WORK1); // strb r6,[r7, r2] + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(RR4 d, RR1 s, IMM offset)) + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; +#endif + MOV_ri(REG_WORK2, s & 0xFF); // mov r3, #0x34 + STRB_rR(REG_WORK2, REG_WORK1); // strb r3, [r2] +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //d: + emit_long(d); + + //: +#endif +} +LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, RR1 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + STRB_rR(s, REG_WORK1); // strb r6, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRB_rR(s, REG_WORK1); // strb r6, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, RR1 s)) + +LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) +{ + BIC_rri(d, d, 0xff); // bic %[d], %[d], #0xff + ORR_rri(d, d, (s & 0xff)); // orr %[d], %[d], #%[s] +} +LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) + +LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + LDRB_rR(REG_WORK2, REG_WORK1); // ldrb r2, [r2] + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + ORR_rrr(d, REG_WORK2, d); // orr r7, r2, r7 +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(s); + //: +#endif +} +LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) +{ + AND_rri(REG_WORK1, s, 0xff); // and r2,r2, #0xff + BIC_rri(d, d, 0x0ff); // bic %[d], %[d], #0xff + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 +} +LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) + +LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + LDR_rRR(d, REG_WORK1, s); // ldr r7, [r2, r6] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rRR(d, REG_WORK1, s); // ldr r7, [r2, r6] + + B_i(0); // b + + emit_long(offset); //: + //: +#endif +} +LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(RR4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2,[pc, #offs] + STR_rRR(s, d, REG_WORK1); // str R6,[R7, r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2,[pc,#4] ; + STR_rRR(s, d, REG_WORK1); // str R6,[R7, r2] + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(RR4 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) +{ + // TODO: optimize imm + +#if defined(USE_DATA_BUFFER) + data_check_end(8, 12); + long offs = data_long_offs(d); + + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + + offs = data_long_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; s + + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #8] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + B_i(1); // b + + emit_long(d); //: + emit_long(s); //: + + //: +#endif +} +LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else +# ifdef ARMV6_ASSEMBLY + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #16] ; +# else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +# endif +#endif + LDRH_rRR(REG_WORK1, REG_WORK1, s); // ldrh r2, [r2, r6] + +#ifdef ARMV6_ASSEMBLY + PKHBT_rrr(d,REG_WORK1,d); +#else + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + BIC_rri(d, d, 0xff00); // bic r7, r7, #0xff00 + ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 +#endif + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + emit_long(offset); //: + //: +#endif +} +LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(RR4 d, RR2 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2,[pc, #offs] + STRH_rRR(s, d, REG_WORK1); // strh r6,[r7, r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2,[pc,#4] + STRH_rRR(s, d, REG_WORK1); // strh r6,[r7, r2] + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(RR4 d, RR2 s, IMM offset)) + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, RR2 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc,#offs] + STRH_rR(s, REG_WORK1); // strh r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRH_rR(s, REG_WORK1); // strh r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, RR2 s)) + +LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldrh r3, [pc, #offs] +#else +# ifdef ARMV6_ASSEMBLY + LDRH_rRI(REG_WORK2, RPC_INDEX, 12); // ldrh r3, [pc, #12] ; +# else + LDRH_rRI(REG_WORK2, RPC_INDEX, 4); // ldrh r3, [pc, #12] ; +# endif +#endif + +#ifdef ARMV6_ASSEMBLY + PKHBT_rrr(d,REG_WORK2,d); +#else + BIC_rri(REG_WORK1, d, 0xff); // bic r2, r7, #0xff + BIC_rri(REG_WORK1, REG_WORK1, 0xff00); // bic r2, r2, #0xff00 + ORR_rrr(d, REG_WORK2, REG_WORK1); // orr r7, r3, r2 +#endif + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_word(s); + skip_word(0); + //: +#endif +} +LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) +{ + // TODO: optimize imm + +#if defined(USE_DATA_BUFFER) + data_check_end(8, 12); + long offs = data_long_offs(d); + + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; + + offs = data_word_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + + STRH_rR(REG_WORK1, REG_WORK2); // strh r2, [r3] +#else + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #8] ; + LDRH_rRI(REG_WORK1, RPC_INDEX, 8); // ldrh r2, [pc, #8] ; + STRH_rR(REG_WORK1, REG_WORK2); // strh r2, [r3] + B_i(1); // b + + //mem: + emit_long(d); + //imm: + emit_word(s); + skip_word(0); // Alignment + + //: +#endif +} +LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + STR_rR(s, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STR_rR(s, REG_WORK1); // str r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(RR4 d, IMM i, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDRH_rRI(REG_WORK1, RPC_INDEX, 4); // ldrh r2, [pc, #4] ; +#endif + if (offset >= 0) + STRH_rRI(REG_WORK1, d, offset); // strh r2, [r7, #0x54] + else + STRH_rRi(REG_WORK1, d, -offset);// strh r2, [r7, #-0x54] +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_word(i); + skip_word(0); + //: +#endif +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(RR4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + LDRH_rR(REG_WORK1, REG_WORK1); // ldrh r2, [r2] + LSR_rri(d, d, 16); // lsr r7, r7, #16 + ORR_rrrLSLi(d, REG_WORK1, d, 16); // orr r7, r2, r7, lsl #16 +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(s); + //: +#endif +} +LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, RR2 s)) +{ + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + ORR_rrrLSRi(d, REG_WORK1, d, 16); // orr r7, r2, r7, lsr #16 + ROR_rri(d, d, 16); // ror r7, r7, #16 +} +LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, RR2 s)) + +LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, RR4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) + LDRH_rRI(REG_WORK1, s, offset); // ldrh r2, [r6, #12] + else + LDRH_rRi(REG_WORK1, s, -offset); // ldrh r2, [r6, #-12] + +#ifdef ARMV6_ASSEMBLY + PKHBT_rrr(d,REG_WORK1,d); +#else + BIC_rri(d, d, 0xff); // bic r7, r7, #0xff + BIC_rri(d, d, 0xff00); // bic r7, r7, #0xff00 + ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 +#endif +} +LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(RR4 d, RR2 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) + STRH_rRI(s, d, offset); // strh r6, [r7, #0x7f] + else + STRH_rRi(s, d, -offset);// strh r6, [r7, #-0x7f] +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(RR4 d, RR2 s, IMM offset)) + +LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [r10, #offs] + LDR_rR(d, REG_WORK1); // ldr r7, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rR(d, REG_WORK1); // ldr r7, [r2] + B_i(0); // b + + emit_long(s); //: + + //: +#endif +} +LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) + +LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(base); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] + LDR_rRR_LSLi(d, REG_WORK1, index, shft); // ldr %[d], [r2, %[index], lsl #[shift]] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rRR_LSLi(d, REG_WORK1, index, shft); // ldr %[d], [r2, %[index], lsl #[shift]] + + B_i(0); // b + emit_long(base); //: + //: +#endif +} +LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(RR4 d, IMM i, IMM offset8)) +{ + Dif(!isbyte(offset8)) abort(); + +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; +#endif + if (offset8 >= 0) + STR_rRI(REG_WORK1, d, offset8); // str r2, [r7, #0x54] + else + STR_rRi(REG_WORK1, d, -offset8); // str r2, [r7, #-0x54] +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(RR4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, RR4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) { + LDR_rRI(d, s, offset); // ldr r2, [r1, #-12] + } else + LDR_rRi(d, s, -offset); // ldr r2, [r1, #12] +} +LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, RR4 s)) +{ + MOV_rr(d, s); // mov %[d], %[s] +} +LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, RR4 s)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(RR4 d, RR4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + + if (offset >= 0) + STR_rRI(s, d, offset); // str r6, [r7, #12] + else + STR_rRi(s, d, -offset); // str r6, [r7, #-12] +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(RR4 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) +{ + UMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // umull r2,r3,r7,r6 + MOV_rr(MUL_NREG1, REG_WORK1); // mov r7,r2 + MOV_rr(MUL_NREG2, REG_WORK2); +} +LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, RR1 s)) +{ + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 24); // lsls r2, %[d], #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + BIC_rri(REG_WORK1, s, 0xff000000); // bic r2, %[s], #0xff000000 + BIC_rri(REG_WORK1, REG_WORK1, 0x00ff0000); // bic r2, r2, #0x00ff0000 +#endif + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 16); // lsls r2, %[d], #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, RR4 s)) +{ + ORRS_rrr(d, d, s); // orrs r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // LDR r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // LDR r2, [pc,#16] ; +#endif + ORRS_rrr(d, d, REG_WORK1); // ORRS r7,r7,r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + // value: + emit_long(i); + //jp: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + int imm = 32 - (i & 0x1f); + + MOV_rrLSLi(REG_WORK1, r, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rri(REG_WORK1, REG_WORK1, imm); // rors r2,r2,#(32 - (i & 0x1f)) + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(r, r, 0xff); // bic r7,r7,#0xff + ORR_rrr(r, r, REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, RR1 r)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + + MOV_ri(REG_WORK2, 32); // mov r3,#32 + AND_rri(REG_WORK1, r, 0x1f); // and r2,r6,#0x1f + SUB_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // sub r3,r3,r2 + + MOV_rrLSLi(REG_WORK1, d, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // rors r2,r2,r3 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(d, d, 0xff); // bic r7,r7,#0xff + + ORR_rrr(d, d, REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + int imm = 32 - (i & 0x1f); + + MOV_rrLSLi(REG_WORK1, r, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rri(REG_WORK1, REG_WORK1, imm); // rors r2,r2,#(32 - (i & 0x1f)) + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + BIC_rri(r, r, 0xff00); // bic r2,r2,#0xff00 + BIC_rri(r, r, 0xff); // bic r2,r2,#0xff + + ORR_rrrLSRi(r, r, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 +} +LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, RR1 r)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + + MOV_ri(REG_WORK2, 32); // mov r3,#32 + AND_rri(REG_WORK1, r, 0x1f); // and r2,r6,#0x1f + SUB_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // sub r3,r3,r2 + + MOV_rrLSLi(REG_WORK1, d, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // rors r2,r2,r3 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(REG_WORK1, 1); // tst r2,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); + + BIC_rri(d, d, 0xff00); // bic r2,r2,#0xff00 + BIC_rri(d, d, 0xff); // bic r2,r2,#0xff + + ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr r2,r2,r7,lsr #16 +} +LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + int imm = 32 - (i & 0x1f); + + RORS_rri(r, r, imm); // rors r7,r7,#(32 - (i & 0x1f)) + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(r, 1); // tst r7,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); +} +LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) +{ + RORS_rri(r, r, i & 0x1F); // RORS r7,r7,#12 +} +LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, RR1 r)) +{ + // TODO: Check if the Bittest is necessary. compemu.c seems to do it itself, but meanwhile make sure, that carry is set correctly + + MOV_ri(REG_WORK1, 32); // mov r2,#32 + AND_rri(REG_WORK2, r, 0x1f); // and r3,r6,#0x1f + SUB_rrr(REG_WORK1, REG_WORK1, REG_WORK2); // sub r2,r2,r3 + + RORS_rrr(d, d, REG_WORK1); // rors r7,r7,r2 + + MRS_CPSR(REG_WORK2); // mrs r3,cpsr + TST_ri(d, 1); // tst r7,#1 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3,r3,#0x20000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 + MSR_CPSR_r(REG_WORK2); +} +LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, RR1 r)) +{ + RORS_rrr(d, d, r); // RORS r7,r7,r6 +} +LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) +{ + MOV_rrLSLi(REG_WORK1, r, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // rors r2,r2,#12 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(r, r, 0xff); // bic r7,r7,#0xff + ORR_rrr(r, r, REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, RR1 r)) +{ + MOV_rrLSLi(REG_WORK1, d, 24); // mov r2,r7,lsl #24 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 8); // orr r2,r2,r2,lsr #8 + + RORS_rrr(REG_WORK1, REG_WORK1, r); // rors r2,r2,r6 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(d, d, 0xff); // bic r7,r7,#0xff + ORR_rrr(d, d, REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) +{ + MOV_rrLSLi(REG_WORK1, r, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // RORS r2,r2,#12 + + BIC_rri(r, r, 0xff00); // bic r7,r7,#0xff00 + BIC_rri(r, r, 0xff); // bic r7,r7,#0xff + + ORR_rrrLSRi(r, r, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 +} +LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, RR1 r)) +{ + MOV_rrLSLi(REG_WORK1, d, 16); // mov r2,r7,lsl #16 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, REG_WORK1, 16); // orr r2,r2,r2,lsr #16 + + RORS_rrr(REG_WORK1, REG_WORK1, r); // RORS r2,r2,r6 + + BIC_rri(d, d, 0xff00); // bic r7,r7,#0xff00 + BIC_rri(d, d, 0xff); // bic r7,r7,#0xff + + ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 +} +LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, RR1 r)) + +LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, RR1 s)) +{ + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + + LSL_rri(REG_WORK2, d, 24); // lsl r3, %[d], #24 + LSL_rri(REG_WORK1, s, 24); // lsl r2, r6, #24 + + SBCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xFF); + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, RR1 s)) + +LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, RR4 s)) +{ + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + + SBCS_rrr(d, d, s); // sbcs r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, RR4 s)) + +LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, RR2 s)) +{ + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + + LSL_rri(REG_WORK2, d, 16); // lsl r3, %[d], #24 + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + + SBCS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d,d, 0xff); + BIC_rri(d,d, 0xff00); + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, RR2 s)) + +LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq + BCC_i(1); // bcs + + MOV_ri(d, 1); // mov r7,#0 + B_i(0); // b + + //: + MOV_ri(d, 0); // mov r7,#1 + break; + + case 8: // HI + BEQ_i(2); // beq Z != 0 + BCS_i(1); // bcc C = 0 + + //: + MOV_ri(d, 1); // mov r7,#0 + B_i(0); // b + + //: + MOV_ri(d, 0); // mov r7,#1 + break; + + default: + CC_MOV_ri(cc, d, 1); // MOVcc R7,#1 + CC_MOV_ri(cc^1, d, 0); // MOVcc^1 R7,#0 + break; + } + //: +} +LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) + +LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq + BCC_i(1); // bcs + + MOV_ri(REG_WORK1, 1); // mov r2,#0 + B_i(0); // b + + //: + MOV_ri(REG_WORK1, 0); // mov r2,#1 + break; + + case 8: // HI + BEQ_i(2); // beq Z != 0 + BCS_i(1); // bcc C = 0 + + MOV_ri(REG_WORK1, 1); // mov r2,#0 + B_i(0); // b + + //: + MOV_ri(REG_WORK1, 0); // mov r2,#1 + break; + + default: + CC_MOV_ri(cc, REG_WORK1, 1); // MOVcc R2,#1 + CC_MOV_ri(cc^1, REG_WORK1, 0); // MOVcc^1 R2,#0 + break; + } + //: +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // LDR R3,[PC, #offs] +#else + LDR_rRI(REG_WORK2, RPC_INDEX, 4); // LDR R3,[PC, #4] +#endif + STRB_rR(REG_WORK1, REG_WORK2); // STRB R2,[R3] +#if !defined(USE_DATA_BUFFER) + B_i(0); // B + + emit_long(d); + //: +#endif +} +LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) + +LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 24); // LSL r2,r7,#24 + + LSLS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // LSLS r2,r2,#12 + + BIC_rri(r, r, 0xff); // BIC r7,r7,0xff + ORR_rrrLSRi(r, r, REG_WORK1, 24); // ORR r7,r7,r2,lsr #24 +} +LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 24); // LSL r2,r7,#24 + LSLS_rrr(REG_WORK1, REG_WORK1, r); // LSLS r2,r2,r6 + BIC_rri(d, d, 0xff); // BIC r7,r7,#0xff + ORR_rrrLSRi(d, d, REG_WORK1, 24); // ORR r7,r7,r2,lsr #24 +} +LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) +{ + LSLS_rri(r,r, i & 0x1f); // lsls r7,r7,#12 +} +LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, RR1 r)) +{ + LSLS_rrr(d, d, r); +} +LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 16); // LSL r2,r7,#16 + LSLS_rri(REG_WORK1, REG_WORK1, i&0x1f); // LSLS r2,r2,#12 + + ORR_rrrLSRi(REG_WORK1, REG_WORK1, r, 16); // ORR r2,r2,r7,lsr #16 + + ROR_rri(r, REG_WORK1, 16); // ROR r7,r2,#16 +} +LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 16); // LSL r2,r7,#16 + LSLS_rrr(REG_WORK1, REG_WORK1, r); // LSLS r2,r2,r6 + ORR_rrrLSRi(REG_WORK1, REG_WORK1, d, 16); // ORR r2,r2,r7,lsr #16 + ROR_rri(d, REG_WORK1, 16); // ROR r7,r2,#16 +} +LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 24); // lsl r2,r7,#24 + ASR_rri(REG_WORK1, REG_WORK1, 24); // asr r2,r2,#24 + + ASRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // asrs r2,r2,#12 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(r,r, 0xff); // bic r7,r7,#0xff + ORR_rrr(r,r,REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 24); // lsl r2,r7,#24 + ASR_rri(REG_WORK1, REG_WORK1, 24); // asr r2,r2,#24 + + ASRS_rrr(REG_WORK1, REG_WORK1, r); // asrs r2,r2,r6 + + AND_rri(REG_WORK1, REG_WORK1, 0xff); // and r2,r2,#0xff + BIC_rri(d,d, 0xff); // bic r7,r7,#0xff + + ORR_rrr(d,d,REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) +{ + LSL_rri(REG_WORK1, r, 16); // lsl r2,r7,#16 + ASR_rri(REG_WORK1, REG_WORK1, 16); // asr r2,r2,#16 + + ASRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // asrs r2,r2,#12 + +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, REG_WORK1); +#else + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); +#endif + + BIC_rri(r,r,0xff00); // bic r7,r7,#0xff00 + BIC_rri(r,r,0xff); // bic r7,r7,#0xff + + ORR_rrr(r,r,REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, RR1 r)) +{ + LSL_rri(REG_WORK1, d, 16); // lsl r2,r7,#16 + ASR_rri(REG_WORK1, REG_WORK1, 16); // asr r2,r2,#16 + + ASRS_rrr(REG_WORK1, REG_WORK1, r); // asrs r2,r2,r6 + +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, REG_WORK1); +#else + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // bic r2,r2,#0xff000000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2,r2,#0xff0000 +#endif + + BIC_rri(d,d, 0xff00); // bic r7,r7,#0xff00 + BIC_rri(d,d, 0xff); // bic r7,r7,#0xff + + ORR_rrr(d,d,REG_WORK1); // orr r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) +{ + ASRS_rri(r, r, i & 0x1f); // ASRS r7,r7,#12 +} +LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, RR1 r)) +{ + ASRS_rrr(d, d, r); // ASRS r7,r7,r6 +} +LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) +{ + AND_rri(REG_WORK1, r, 0xff); // AND r2,r7,#0xFF + + LSRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // LSRS r2,r2,r6 + + BIC_rri(r, r, 0xFF); // BIC r7,r7,#0xff + ORR_rrr(r, r, REG_WORK1); // ORR r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, RR1 r)) +{ + AND_rri(REG_WORK1, d, 0xff); // AND r2,r7,#0xFF + + LSRS_rrr(REG_WORK1, REG_WORK1, r); // LSRS r2,r2,r6 + + BIC_rri(d, d, 0xFF); // BIC r7,r7,#0xff + ORR_rrr(d, d, REG_WORK1); // ORR r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) +{ + LSRS_rri(r, r, i & 0x1f); // LSRS r7,r7,#12 +} +LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, r); +#else + BIC_rri(REG_WORK1, r, 0xff0000); // BIC r2,r7,#0xff0000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // BIC r2,r2,#0xff000000 +#endif + + LSRS_rri(REG_WORK1, REG_WORK1, i & 0x1f); // LSRS r2,r2,#12 + + BIC_rri(r, r, 0xFF); // BIC r7,r7,#0xff + BIC_rri(r, r, 0xFF00); // BIC r7,r7,#0xff00 + ORR_rrr(r, r, REG_WORK1); // ORR r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, RR1 r)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, d); +#else + BIC_rri(REG_WORK1, d, 0xff0000); // BIC r2,r7,#0xff0000 + BIC_rri(REG_WORK1, REG_WORK1, 0xff000000); // BIC r2,r2,#0xff000000 +#endif + + LSRS_rrr(REG_WORK1, REG_WORK1, r); // LSRS r2,r2,r6 + + BIC_rri(d, d, 0xFF); // BIC r7,r7,#0xff + BIC_rri(d, d, 0xFF00); // BIC r7,r7,#0xff00 + ORR_rrr(d, d, REG_WORK1); // ORR r7,r7,r2 +} +LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, RR1 r)) +{ + LSRS_rrr(d, d, r); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, RR1 r)) + +LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, RR1 s)) +{ + LSL_rri(REG_WORK1, s, 24); // lsl r2, r6, #24 + LSL_rri(REG_WORK2, d, 24); // lsl r3, r7, #24 + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xFF); + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) +{ + LSL_rri(REG_WORK2, d, 24); // lsl r3, r7, #24 + + SUBS_rri(REG_WORK2, REG_WORK2, i << 24); // subs r3, r3, #0x12000000 + BIC_rri(d, d, 0xFF); // bic r7, r7, #0xFF + ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr r7, r7, r3, lsr #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, RR4 s)) +{ + SUBS_rrr(d, d, s); // subs r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +#endif + SUBS_rrr(d, d, REG_WORK1); // subs r7, r7, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, RR2 s)) +{ + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, r7, #16 + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xff); + BIC_rri(d, d, 0xff00); + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) +{ + // TODO: optimize_imm + +#if defined(USE_DATA_BUFFER) + long offs = data_word_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDRH_rRI(REG_WORK1, RPC_INDEX, 36); // ldrh r2, [pc, #36] ; +#endif + LSL_rri(REG_WORK1, REG_WORK1, 16); // lsl r2, r2, #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, r6, #16 + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + BIC_rri(d, d, 0xff); + BIC_rri(d, d, 0xff00); + ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r6, r3, r6, lsr #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + emit_word(i); + skip_word(0); //: + + //: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(RR1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(REG_WORK1, s); + SXTB_rr(REG_WORK2, d); +#else + LSL_rri(REG_WORK1, s, 24); // lsl r2, r6, #24 + LSL_rri(REG_WORK2, d, 24); // lsl r3, r7, #24 +#endif + + TST_rr(REG_WORK2, REG_WORK1); // tst r3, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(RR1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(RR4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; +#endif + TST_rr(d, REG_WORK1); // tst r7, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(i); + //: +#endif +} +LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(RR4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(RR4 d, RR4 s)) +{ + TST_rr(d, s); // tst r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(RR4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(RR2 d, RR2 s)) +{ +#ifdef ARMV6_ASSEMBLY + SXTH_rr(REG_WORK1, s); + SXTH_rr(REG_WORK2, d); +#else + LSL_rri(REG_WORK1, s, 16); // lsl r2, r6, #16 + LSL_rri(REG_WORK2, d, 16); // lsl r3, r7, #16 +#endif + + TST_rr(REG_WORK2, REG_WORK1); // tst r3, r2 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(RR2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, RR1 s)) +{ + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 24); // lsls r2, %[d], #24 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + BIC_rri(REG_WORK1, s, 0xff000000); // bic r2, %[s], #0xff000000 + BIC_rri(REG_WORK1, REG_WORK1, 0x00ff0000); // bic r2, r2, #0x00ff0000 +#endif + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 + LSLS_rri(REG_WORK1, d, 16); // lsls r2, %[d], #16 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, RR4 s)) +{ + EORS_rrr(d, d, s); // eors r7, r7, r6 + + MRS_CPSR(REG_WORK1); // mrs r2, CPSR + BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 + MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 +} +LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, RR4 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTH_rr(d, s); // sxth %[d],%[s] +#else + LSL_rri(d, s, 16); // lsl r6, r7, #16 + ASR_rri(d, d, 16); // asr r6, r6, #16 +#endif +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, RR2 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(d, s); // SXTB %[d],%[s] +#else + ROR_rri(d, s, 8); // ror r6, r7, #8 + ASR_rri(d, d, 24); // asr r6, r6, #24 +#endif +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, RR1 s)) + +LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(d, s); // UXTB %[d], %[s] +#else + ROR_rri(d, s, 8); // ror r2, r1, #8 + LSR_rri(d, d, 24); // lsr r2, r2, #24 +#endif +} +LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, RR1 s)) + +LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(d, s); // UXTH %[d], %[s] +#else + BIC_rri(d, s, 0xff000000); // bic %[d], %[s], #0xff000000 + BIC_rri(d, d, 0x00ff0000); // bic %[d], %[d], #0x00ff0000 +#endif +} +LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, RR2 s)) + +static inline void raw_dec_sp(int off) +{ + if (off) { + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + SUB_rrr(RSP_INDEX, RSP_INDEX, REG_WORK1); // sub r7, r7, r2 + B_i(0); // b + //: + emit_long(off); + } +} + +static inline void raw_inc_sp(int off) +{ + if (off) { + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADD_rrr(RSP_INDEX, RSP_INDEX, REG_WORK1); // sub r7, r7, r2 + B_i(0); // b + //: + emit_long(off); + } +} + +static inline void raw_push_regs_to_preserve(void) { + PUSH_REGS(PRESERVE_MASK); +} + +static inline void raw_pop_preserved_regs(void) { + POP_REGS(PRESERVE_MASK); +} + +// Verify!!! +/* FLAGX is byte sized, and we *do* write it at that size */ +static inline void raw_load_flagx(uae_u32 t, uae_u32 r) +{ + raw_mov_l_rm(t,(uintptr)live.state[r].mem); +} + +static inline void raw_flags_evicted(int r) +{ + //live.state[FLAGTMP].status=CLEAN; + live.state[FLAGTMP].status=INMEM; + live.state[FLAGTMP].realreg=-1; + /* We just "evicted" FLAGTMP. */ + if (live.nat[r].nholds!=1) { + /* Huh? */ + abort(); + } + live.nat[r].nholds=0; +} + +static inline void raw_flags_init(void) { +} + +static __inline__ void raw_flags_set_zero(int s, int tmp) +{ + raw_mov_l_rr(tmp,s); + MRS_CPSR(s); + BIC_rri(s,s,ARM_Z_FLAG); + AND_rri(tmp,tmp,ARM_Z_FLAG); + EOR_rri(tmp,tmp,ARM_Z_FLAG); + ORR_rrr(s,s,tmp); + MSR_CPSR_r(s); +} + +static inline void raw_flags_to_reg(int r) +{ + MRS_CPSR(r); + raw_mov_l_mr((uintptr)live.state[FLAGTMP].mem,r); + raw_flags_evicted(r); +} + +static inline void raw_reg_to_flags(int r) +{ + MSR_CPSR_r(r); // msr CPSR_fc, %r +} + +/* Apparently, there are enough instructions between flag store and + flag reload to avoid the partial memory stall */ +static inline void raw_load_flagreg(uae_u32 t, uae_u32 r) +{ + raw_mov_l_rm(t,(uintptr)live.state[r].mem); +} + +/* %eax register is clobbered if target processor doesn't support fucomi */ +#define FFLAG_NREG_CLOBBER_CONDITION !have_cmov +#define FFLAG_NREG R0_INDEX +#define FLAG_NREG2 -1 +#define FLAG_NREG1 -1 +#define FLAG_NREG3 -1 + +static inline void raw_fflags_into_flags(int r) +{ + jit_unimplemented("raw_fflags_into_flags %x", r); +} + +static inline void raw_fp_init(void) +{ + int i; + + for (i=0;i=1) { +// emit_byte(0xde); +// emit_byte(0xd9); + live.tos-=2; + } + while (live.tos>=0) { +// emit_byte(0xdd); +// emit_byte(0xd8); + live.tos--; + } + raw_fp_init(); +} + +LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) +{ + jit_unimplemented("raw_fmov_mr_drop %x %x", m, r); +} +LENDFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) + +LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) +{ + jit_unimplemented("raw_fmov_mr %x %x", m, r); +} +LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) + +LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) +{ + jit_unimplemented("raw_fmov_rm %x %x", r, m); +} +LENDFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) + +LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) +{ + jit_unimplemented("raw_fmov_rr %x %x", d, s); +} +LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) + +static inline void raw_emit_nop_filler(int nbytes) +{ + nbytes >>= 2; + while(nbytes--) { NOP(); } +} + +static inline void raw_emit_nop(void) +{ + NOP(); +} + +#ifdef UAE +static +#endif +void compiler_status() { + jit_log("compiled code starts at %p, current at %p (size 0x%x)", compiled_code, current_compile_p, (unsigned int)(current_compile_p - compiled_code)); +} + +// +// ARM doesn't have bsf, but clz is a good alternative instruction for it +// +static bool target_check_bsf(void) +{ + return false; +} + +static void raw_init_cpu(void) +{ + /* Have CMOV support, because ARM support conditions for all instructions */ + have_cmov = true; + + align_loops = 0; + align_jumps = 0; + + raw_flags_init(); +} + +// +// Arm instructions +// +LOWFUNC(WRITE,NONE,2,raw_ADD_l_rr,(RW4 d, RR4 s)) +{ + ADD_rrr(d, d, s); +} +LENDFUNC(WRITE,NONE,2,raw_ADD_l_rr,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_ADD_l_rri,(RW4 d, RR4 s, IMM i)) +{ + ADD_rri(d, s, i); +} +LENDFUNC(WRITE,NONE,2,raw_ADD_l_rri,(RW4 d, RR4 s, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_SUB_l_rri,(RW4 d, RR4 s, IMM i)) +{ + SUB_rri(d, s, i); +} +LENDFUNC(WRITE,NONE,2,raw_SUB_l_rri,(RW4 d, RR4 s, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_AND_b_rr,(RW1 d, RR1 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 24); // mvn r2, %[s], lsl #24 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 24); // mvn r2, %[s], lsr #24 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 +} +LENDFUNC(WRITE,NONE,2,raw_AND_b_rr,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_AND_l_rr,(RW4 d, RR4 s)) +{ + AND_rrr(d, d, s); +} +LENDFUNC(WRITE,NONE,2,raw_AND_l_rr,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_AND_l_ri,(RW4 d, IMM i)) +{ + AND_rri(d, d, i); +} +LENDFUNC(WRITE,NONE,2,raw_AND_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_AND_w_rr,(RW2 d, RR2 s)) +{ + MVN_rrLSLi(REG_WORK1, s, 16); // mvn r2, %[s], lsl #16 + MVN_rrLSRi(REG_WORK1, REG_WORK1, 16); // mvn r2, %[s], lsr #16 + AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 +} +LENDFUNC(WRITE,NONE,2,raw_AND_w_rr,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_EOR_b_rr,(RW1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF +#endif + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 +} +LENDFUNC(WRITE,NONE,2,raw_EOR_b_rr,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_EOR_l_rr,(RW4 d, RR4 s)) +{ + EOR_rrr(d, d, s); // eors r7, r7, r6 +} +LENDFUNC(WRITE,NONE,2,raw_EOR_l_rr,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_EOR_w_rr,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] + EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 +#else + LSL_rri(REG_WORK1, s, 16); // bic r2, %[s], #0xff000000 + EOR_rrrLSRi(d, d, REG_WORK1, 16); // orr %[d], %[d], r2 +#endif +} +LENDFUNC(WRITE,NONE,2,raw_EOR_w_rr,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_LDR_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(d, RPC_INDEX, offs); // ldr r2, [pc, #offs] +#else + LDR_rR(d, RPC_INDEX); + B_i(0); + emit_long(i); +#endif +} +LENDFUNC(WRITE,NONE,2,raw_LDR_l_rr,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_MOV_l_ri8,(RW4 d, IMM i)) +{ + MOV_ri(d, i); +} +LENDFUNC(WRITE,NONE,2,raw_MOV_l_ri8,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ORR_b_rr,(RW1 d, RR1 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK1, s); // UXTH r2, %[s] +#else + AND_rri(REG_WORK1, s, 0xFF); // and r2, %[s], 0xFF +#endif + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 +} +LENDFUNC(WRITE,NONE,2,raw_ORR_b_rr,(RW1 d, RR1 s)) + +LOWFUNC(WRITE,NONE,2,raw_ORR_l_rr,(RW4 d, RR4 s)) +{ + ORR_rrr(d, d, s); +} +LENDFUNC(WRITE,NONE,2,raw_ORR_l_rr,(RW4 d, RR4 s)) + +LOWFUNC(WRITE,NONE,2,raw_ORR_w_rr,(RW2 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK1, s); // UXTH r2, %[s] + ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 +#else + LSL_rri(REG_WORK1, s, 16); // bic r2, %[s], #0xff000000 + ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr %[d], %[d], r2 +#endif +} +LENDFUNC(WRITE,NONE,2,raw_ORR_w_rr,(RW2 d, RR2 s)) + +LOWFUNC(WRITE,NONE,2,raw_ROR_l_ri,(RW4 r, IMM i)) +{ + ROR_rri(r, r, i); +} +LENDFUNC(WRITE,NONE,2,raw_ROR_l_ri,(RW4 r, IMM i)) + +// +// compuemu_support used raw calls +// +LOWFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + data_check_end(8, 24); + long target = data_long(d, 24); + long offs = get_data_offset(target); + + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; s + + ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + + offs = get_data_offset(target); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 20); // ldr r2, [pc, #20] ; + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #16] ; + + ADD_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // adds r3, r3, r2 + + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + + B_i(1); // b + + //: + emit_long(d); + //: + emit_long(s); + //: +#endif +} +LENDFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,NONE,2,compemu_raw_and_l_ri,(RW4 d, IMM i)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(i); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + AND_rrr(d, d, REG_WORK1); // ands %[d], %[d], r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #16] ; + AND_rrr(d, d, REG_WORK1); // ands %[d], %[d], r2 + B_i(0); + emit_long(i); +#endif +} +LENDFUNC(WRITE,NONE,2,compemu_raw_and_l_ri,(RW4 d, IMM i)) + +LOWFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) +{ +#if defined(ARMV6_ASSEMBLY) + REV_rr(r,r); // rev %[r],%[r] +#else + EOR_rrrRORi(REG_WORK1, r, r, 16); // eor r2, r6, r6, ror #16 + BIC_rri(REG_WORK1, REG_WORK1, 0xff0000); // bic r2, r2, #0xff0000 + ROR_rri(r, r, 8); // ror r6, r6, #8 + EOR_rrrLSRi(r, r, REG_WORK1, 8); // eor r6, r6, r2, lsr #8 +#endif +} +LENDFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) + +LOWFUNC(WRITE,NONE,2,compemu_raw_bt_l_ri,(RR4 r, IMM i)) +{ + int imm = (1 << (i & 0x1f)); + + MRS_CPSR(REG_WORK2); // mrs r3, CPSR + TST_ri(r, imm); // tst r6, #0x1000000 + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 + MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 +} +LENDFUNC(WRITE,NONE,2,compemu_raw_bt_l_ri,(RR4 r, IMM i)) + +LOWFUNC(NONE,READ,5,compemu_raw_cmov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor, IMM cond)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + switch (cond) { + case 9: // LS + jit_unimplemented("cmov LS not implemented"); + abort(); + case 8: // HI + jit_unimplemented("cmov HI not implemented"); + abort(); + default: +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(base); + CC_LDR_rRI(cond, REG_WORK1, RPC_INDEX, offs); // ldrcc r2, [pc, #offs] ; + CC_LDR_rRR_LSLi(cond, d, REG_WORK1, index, shft); // ldrcc %[d], [r2, %[index], lsl #[shift]] +#else + CC_LDR_rRI(cond, REG_WORK1, RPC_INDEX, 4); // ldrcc r2, [pc, #4] ; + CC_LDR_rRR_LSLi(cond, d, REG_WORK1, index, shft); // ldrcc %[d], [r2, %[index], lsl #[shift]] + B_i(0); // b +#endif + break; + } +#if !defined(USE_DATA_BUFFER) + emit_long(base); // : + //: +#endif +} +LENDFUNC(NONE,READ,5,compemu_raw_cmov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor, IMM cond)) + +LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + data_check_end(8, 16); + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + LDR_rR(REG_WORK1, REG_WORK1); // ldr r2, [r2] + + offs = data_long_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; s + + CMP_rr(REG_WORK1, REG_WORK2); // cmp r2, r3 + +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #24] ; + LDR_rR(REG_WORK1, REG_WORK1); // ldr r2, [r2] + + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #20] ; + + CMP_rr(REG_WORK1, REG_WORK2); // cmp r2, r3 + + B_i(1); // b + + //: + emit_long(d); + //: + emit_long(s); + //: +#endif +} +LENDFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) + +LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi8,(MEMR d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; +#endif + LDR_rR(REG_WORK1, REG_WORK1); // ldr r2, [r2] + + CMP_ri(REG_WORK1, s); // cmp r2, r3 + +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi8,(MEMR d, IMM s)) + +LOWFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(offset); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + ADD_rrr(d, s, REG_WORK1); // add r7, r6, r2 + B_i(0); // b + + //: + emit_long(offset); + //: +#endif +} +LENDFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) + +LOWFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) +{ + int shft; + switch(factor) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + ADD_rrrLSLi(d, s, index, shft); // ADD R7,R6,R5,LSL #2 +} +LENDFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + STRB_rR(s, REG_WORK1); // strb r6, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRB_rR(s, REG_WORK1); // strb r6, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) +{ + // TODO: optimize imm + +#if defined(USE_DATA_BUFFER) + data_check_end(8, 12); + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + offs = data_long_offs(s); + LDR_rRI(REG_WORK2, RPC_INDEX, offs); // ldr r3, [pc, #offs] ; s + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 8); // ldr r2, [pc, #8] ; + LDR_rRI(REG_WORK2, RPC_INDEX, 8); // ldr r3, [pc, #8] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + B_i(1); // b + + emit_long(d); //: + emit_long(s); //: + + //: +#endif +} +LENDFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + STR_rR(s, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STR_rR(s, REG_WORK1); // str r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) + +LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(d, RPC_INDEX, offs); // ldr %[d], [pc, #offs] ; +#else + LDR_rR(d, RPC_INDEX); // ldr %[d], [pc] ; + B_i(0); // b + + //: + emit_long(s); + //: +#endif +} +LENDFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) + +LOWFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + LDR_rR(d, REG_WORK1); // ldr r7, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + LDR_rR(d, REG_WORK1); // ldr r7, [r2] + B_i(0); // b + + emit_long(s); //: + //: +#endif +} +LENDFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) + +LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_rr,(W4 d, RR4 s)) +{ + MOV_rr(d, s); // mov %[d], %[s] +} +LENDFUNC(NONE,NONE,2,compemu_raw_mov_l_rr,(W4 d, RR4 s)) + +LOWFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(d); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; + STRH_rR(s, REG_WORK1); // strh r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #4] ; + STRH_rR(s, REG_WORK1); // strh r3, [r2] + B_i(0); // b + + //: + emit_long(d); + //: +#endif +} +LENDFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) + +LOWFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) +{ +#if defined(USE_DATA_BUFFER) + data_check_end(8, 24); + long target = data_long(d, 24); + long offs = get_data_offset(target); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + offs = data_long_offs(s); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; s + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + + offs = get_data_offset(target); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; d + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 20); // ldr r2, [pc, #32] ; + LDR_rR(REG_WORK2, REG_WORK1); // ldr r3, [r2] + + LDR_rRI(REG_WORK1, RPC_INDEX, 16); // ldr r2, [pc, #28] ; + + SUBS_rrr(REG_WORK2, REG_WORK2, REG_WORK1); // subs r3, r3, r2 + + LDR_rRI(REG_WORK1, RPC_INDEX, 4); // ldr r2, [pc, #16] ; + STR_rR(REG_WORK2, REG_WORK1); // str r3, [r2] + + B_i(1); // b + + //: + emit_long(d); + //: + emit_long(s); + //: +#endif +} +LENDFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) + +LOWFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) +{ + TST_rr(d, s); // tst r7, r6 +} +LENDFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) + +LOWFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) +{ +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(d, s); // UXTH %[d], %[s] +#else + BIC_rri(d, s, 0xff000000); // bic %[d], %[s], #0xff000000 + BIC_rri(d, d, 0x00ff0000); // bic %[d], %[d], #0x00ff0000 +#endif +} +LENDFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) + +static inline void compemu_raw_call(uae_u32 t) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(t); + LDR_rRI(REG_WORK1, RPC_INDEX, offs); // ldr r2, [pc, #offs] ; +#else + LDR_rRI(REG_WORK1, RPC_INDEX, 12); // ldr r2, [pc, #12] ; +#endif + PUSH(RLR_INDEX); // push {lr} + BLX_r(REG_WORK1); // blx r2 + POP(RLR_INDEX); // pop {lr} +#if !defined(USE_DATA_BUFFER) + B_i(0); // b + + //: + emit_long(t); + //: +#endif +} + +static inline void compemu_raw_call_r(RR4 r) +{ + PUSH(RLR_INDEX); // push {lr} + BLX_r(r); // blx r0 + POP(RLR_INDEX); // pop {lr} +} + +static inline void compemu_raw_jcc_l_oponly(int cc) +{ + switch (cc) { + case 9: // LS + BEQ_i(0); // beq + BCC_i(2); // bcc + + //: + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; + BX_r(REG_WORK1); // bx r2 + break; + + case 8: // HI + BEQ_i(3); // beq + BCS_i(2); // bcs + + //: + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; + BX_r(REG_WORK1); // bx r2 + break; + + default: + CC_LDR_rRI(cc, REG_WORK1, RPC_INDEX, 4); // ldrlt r2, [pc, #4] ; + CC_BX_r(cc, REG_WORK1); // bxlt r2 + B_i(0); // b + break; + } + // emit of target will be done by caller +} + +static inline void compemu_raw_jl(uae_u32 t) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(t); + CC_LDR_rRI(NATIVE_CC_LT, RPC_INDEX, RPC_INDEX, offs); // ldrlt pc, [pc, offs] +#else + CC_LDR_rR(NATIVE_CC_LT, RPC_INDEX, RPC_INDEX); // ldrlt pc, [pc] + B_i(0); // b + + //: + emit_long(t); + //: +#endif +} + +static inline void compemu_raw_jmp(uae_u32 t) +{ + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] + BX_r(REG_WORK1); // bx r2 + emit_long(t); +} + +static inline void compemu_raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) +{ + int shft; + switch(m) { + case 1: shft=0; break; + case 2: shft=1; break; + case 4: shft=2; break; + case 8: shft=3; break; + default: abort(); + } + + LDR_rR(REG_WORK1, RPC_INDEX); // ldr r2, [pc] ; + LDR_rRR_LSLi(RPC_INDEX, REG_WORK1, r, shft); // ldr pc, [r2, r6, lsl #3] + emit_long(base); +} + +static inline void compemu_raw_jmp_r(RR4 r) +{ + BX_r(r); +} + +static inline void compemu_raw_jnz(uae_u32 t) +{ +#if defined(USE_DATA_BUFFER) + long offs = data_long_offs(t); + CC_LDR_rRI(NATIVE_CC_NE, RPC_INDEX, RPC_INDEX, offs); // ldrne pc, [pc, offs] +#else + CC_LDR_rR(NATIVE_CC_NE, RPC_INDEX, RPC_INDEX); // ldrne pc, [pc] + B_i(0); // b + + emit_long(t); + //: +#endif +} + +static inline void compemu_raw_jz_b_oponly(void) +{ + BNE_i(2); // bne jp + LDRSB_rRI(REG_WORK1, RPC_INDEX, 3); // ldrsb r2,[pc,#3] + ADD_rrr(RPC_INDEX, RPC_INDEX, REG_WORK1); // add pc,pc,r2 + + skip_n_bytes(3); + + // +} + +static inline void compemu_raw_branch(IMM d) +{ + B_i((d >> 2) - 1); +} diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_arm.h b/BasiliskII/src/uae_cpu/compiler/codegen_arm.h new file mode 100644 index 00000000..f92bb1da --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/codegen_arm.h @@ -0,0 +1,1292 @@ +/* + * compiler/codegen_arm.h - IA-32 and AMD64 code generator + * + * Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> ARM + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * This file is derived from CCG, copyright 1999-2003 Ian Piumarta + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ARM_RTASM_H +#define ARM_RTASM_H + +/* NOTES + * + */ + +/* --- Configuration ------------------------------------------------------- */ + +/* CPSR flags */ + +#define ARM_N_FLAG 0x80000000 +#define ARM_Z_FLAG 0x40000000 +#define ARM_C_FLAG 0x20000000 +#define ARM_V_FLAG 0x10000000 +#define ARM_Q_FLAG 0x08000000 +#define ARM_CV_FLAGS (ARM_C_FLAG|ARM_V_FLAG) + +#define ARM_GE3 0x00080000 +#define ARM_GE2 0x00040000 +#define ARM_GE1 0x00020000 +#define ARM_GE0 0x00010000 + +/* --- Macros -------------------------------------------------------------- */ + +/* ========================================================================= */ +/* --- UTILITY ------------------------------------------------------------- */ +/* ========================================================================= */ + +#define _W(c) emit_long(c) +#define _LS2_ADDR(a) (((a) & 0x01f0000f) | (((a) & 0xf0) << 4)) + +/* ========================================================================= */ +/* --- ENCODINGS ----------------------------------------------------------- */ +/* ========================================================================= */ + +#define IMM32(c) ((c & 0xffffff00) == 0 ? c : \ + (c & 0x3fffffc0) == 0 ? (0x100 | ((c >> 30) & 0x3) | ((c << 2) & 0xfc)) : \ + (c & 0x0ffffff0) == 0 ? (0x200 | ((c >> 28) & 0xf) | ((c << 4) & 0xf0)) : \ + (c & 0x03fffffc) == 0 ? (0x300 | ((c >> 26) & 0x3f) | ((c << 6) & 0xc0) ) : \ + (c & 0x00ffffff) == 0 ? (0x400 | ((c >> 24) & 0xff)) : \ + (c & 0xc03fffff) == 0 ? (0x500 | (c >> 22)) : \ + (c & 0xf00fffff) == 0 ? (0x600 | (c >> 20)) : \ + (c & 0xfc03ffff) == 0 ? (0x700 | (c >> 18)) : \ + (c & 0xff00ffff) == 0 ? (0x800 | (c >> 16)) : \ + (c & 0xffc03fff) == 0 ? (0x900 | (c >> 14)) : \ + (c & 0xfff00fff) == 0 ? (0xa00 | (c >> 12)) : \ + (c & 0xfffc03ff) == 0 ? (0xb00 | (c >> 10)) : \ + (c & 0xffff00ff) == 0 ? (0xc00 | (c >> 8)) : \ + (c & 0xffffc03f) == 0 ? (0xd00 | (c >> 6)) : \ + (c & 0xfffff00f) == 0 ? (0xe00 | (c >> 4)) : \ + (c & 0xfffffc03) == 0 ? (0xf00 | (c >> 2)) : \ + 0\ + ) + +#define SHIFT_IMM(c) (0x02000000 | (IMM32((c)))) + +#define UNSHIFTED_IMM8(c) (0x02000000 | (c)) +#define SHIFT_IMM8_ROR(c,r) (0x02000000 | (c) | ((r >> 1) << 8)) + +#define SHIFT_REG(Rm) (Rm) +#define SHIFT_LSL_i(Rm,s) ((Rm) | ((s) << 7)) +#define SHIFT_LSL_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x10) +#define SHIFT_LSR_i(Rm,s) ((Rm) | ((s) << 7) | 0x20) +#define SHIFT_LSR_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x30) +#define SHIFT_ASR_i(Rm,s) ((Rm) | ((s) << 7) | 0x40) +#define SHIFT_ASR_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x50) +#define SHIFT_ROR_i(Rm,s) ((Rm) | ((s) << 7) | 0x60) +#define SHIFT_ROR_r(Rm,Rs) ((Rm) | ((Rs) << 8) | 0x70) +#define SHIFT_RRX(Rm) ((Rm) | 0x60) +#define SHIFT_PK(Rm,s) ((Rm) | ((s) << 7)) + +// Load/Store addressings +#define ADR_ADD(v) ((1 << 23) | (v)) +#define ADR_SUB(v) (v) + +#define ADR_IMM(v) ((v) | (1 << 24)) +#define ADR_IMMPOST(v) (v) +#define ADR_REG(Rm) ((1 << 25) | (1 << 24) | (Rm)) +#define ADR_REGPOST(Rm) ((1 << 25) | (Rm)) + +#define ADD_IMM(i) ADR_ADD(ADR_IMM(i)) +#define SUB_IMM(i) ADR_SUB(ADR_IMM(i)) + +#define ADD_REG(Rm) ADR_ADD(ADR_REG(Rm)) +#define SUB_REG(Rm) ADR_SUB(ADR_REG(Rm)) + +#define ADD_LSL(Rm,i) ADR_ADD(ADR_REG(Rm) | ((i) << 7)) +#define SUB_LSL(Rm,i) ADR_SUB(ADR_REG(Rm) | ((i) << 7)) + +#define ADD_LSR(Rm,i) ADR_ADD(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (1 << 5)) +#define SUB_LSR(Rm,i) ADR_SUB(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (1 << 5)) + +#define ADD_ASR(Rm,i) ADR_ADD(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (2 << 5)) +#define SUB_ASR(Rm,i) ADR_SUB(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (2 << 5)) + +#define ADD_ROR(Rm,i) ADR_ADD(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (3 << 5)) +#define SUB_ROR(Rm,i) ADR_SUB(ADR_REG(Rm) | (((i) & 0x1f) << 7) | (3 << 5)) + +#define ADD_RRX(Rm) ADR_ADD(ADR_REG(Rm) | (3 << 5)) +#define SUB_RRX(Rm) ADR_SUB(ADR_REG(Rm) | (3 << 5)) + +#define ADD2_IMM(i) ADR_ADD(i | (1 << 22)) +#define SUB2_IMM(i) ADR_SUB(i | (1 << 22)) + +#define ADD2_REG(Rm) ADR_ADD(Rm) +#define SUB2_REG(Rm) ADR_SUB(Rm) + +// MOV, MVN +#define _OP1(cc,op,s,Rd,shift) _W(((cc) << 28) | ((op) << 21) | ((s) << 20) | ((Rd) << 12) | (shift)) + +// CMP, CMN, TST, TEQ +#define _OP2(cc,op,Rn,shift) _W(((cc) << 28) | ((op) << 21) | (1 << 20) | ((Rn) << 16) | (shift)) + +// ADD, SUB, RSB, ADC, SBC, RSC, AND, BIC, EOR, ORR +#define _OP3(cc,op,s,Rd,Rn,shift) _W(((cc) << 28) | ((op) << 21) | ((s) << 20) | ((Rn) << 16) | ((Rd) << 12) | (shift)) + +// LDR, STR +#define _LS1(cc,l,b,Rd,Rn,a) _W(((cc) << 28) | (0x01 << 26) | ((l) << 20) | ((b) << 22) | ((Rn) << 16) | ((Rd) << 12) | (a)) +#define _LS2(cc,p,l,s,h,Rd,Rn,a) _W(((cc) << 28) | ((p) << 24) | ((l) << 20) | ((Rn) << 16) | ((Rd) << 12) | ((s) << 6) | ((h) << 5) | 0x90 | _LS2_ADDR((a))) + +/* ========================================================================= */ +/* --- OPCODES ------------------------------------------------------------- */ +/* ========================================================================= */ + +/* Branch instructions */ +#ifndef __ANDROID__ +enum { + _B, _BL, _BLX, _BX, _BXJ +}; +#endif + +/* Data processing instructions */ +enum { + _AND = 0, + _EOR, + _SUB, + _RSB, + _ADD, + _ADC, + _SBC, + _RSC, + _TST, + _TEQ, + _CMP, + _CMN, + _ORR, + _MOV, + _BIC, + _MVN +}; + +/* Single instruction Multiple Data (SIMD) instructions */ + +/* Multiply instructions */ + +/* Parallel instructions */ + +/* Extend instructions */ + +/* Miscellaneous arithmetic instrations */ + +/* Status register transfer instructions */ + +/* Load and Store instructions */ + +/* Coprocessor instructions */ + +/* Exception generation instructions */ + +/* ========================================================================= */ +/* --- ASSEMBLER ----------------------------------------------------------- */ +/* ========================================================================= */ + +#define NOP() _W(0xe1a00000) +#define SETEND_BE() _W(0xf1010200) +#define SETEND_LE() _W(0xf1010000) + +/* Data processing instructions */ + +/* Opcodes Type 1 */ +// MOVcc rd,#i +#define CC_MOV_ri8(cc,Rd,i) _OP1(cc,_MOV,0,Rd,UNSHIFTED_IMM8(i)) +// MOVcc Rd,#i ROR #s +#define CC_MOV_ri8RORi(cc,Rd,i,s) _OP1(cc,_MOV,0,Rd,SHIFT_IMM8_ROR(i,s)) +#define CC_MOV_ri(cc,Rd,i) _OP1(cc,_MOV,0,Rd,SHIFT_IMM(i)) +#define CC_MOV_rr(cc,Rd,Rm) _OP1(cc,_MOV,0,Rd,SHIFT_REG(Rm)) +#define CC_MOV_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MOV_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MOV_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MOV_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MOV_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MOV_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MOV_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MOV,0,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MOV_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MOV_rrRRX(cc,Rd,Rm) _OP1(cc,_MOV,0,Rd,SHIFT_RRX(Rm)) + +// MOV rd,#i +#define MOV_ri8(Rd,i) CC_MOV_ri8(NATIVE_CC_AL,Rd,i) +// MOV Rd,#i ROR #s +#define MOV_ri8RORi(Rd,i,s) CC_MOV_ri8RORi(NATIVE_CC_AL,Rd,i,s) +#define MOV_ri(Rd,i) CC_MOV_ri(NATIVE_CC_AL,Rd,i) +#define MOV_rr(Rd,Rm) CC_MOV_rr(NATIVE_CC_AL,Rd,Rm) +#define MOV_rrLSLi(Rd,Rm,i) CC_MOV_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrLSLr(Rd,Rm,Rs) CC_MOV_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrLSRi(Rd,Rm,i) CC_MOV_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrLSRr(Rd,Rm,Rs) CC_MOV_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrASRi(Rd,Rm,i) CC_MOV_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrASRr(Rd,Rm,Rs) CC_MOV_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrRORi(Rd,Rm,i) CC_MOV_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MOV_rrRORr(Rd,Rm,Rs) CC_MOV_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOV_rrRRX(Rd,Rm) CC_MOV_rrRRX(NATIVE_CC_AL,Rd,Rm) + +#define CC_MOVS_ri(cc,Rd,i) _OP1(cc,_MOV,1,Rd,SHIFT_IMM(i)) +#define CC_MOVS_rr(cc,Rd,Rm) _OP1(cc,_MOV,1,Rd,SHIFT_REG(Rm)) +#define CC_MOVS_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MOVS_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MOVS_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MOVS_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MOVS_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MOVS_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MOVS_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MOV,1,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MOVS_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,1,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MOVS_rrRRX(cc,Rd,Rm) _OP1(cc,_MOV,1,Rd,SHIFT_RRX(Rm)) + +#define MOVS_ri(Rd,i) CC_MOVS_ri(NATIVE_CC_AL,Rd,i) +#define MOVS_rr(Rd,Rm) CC_MOVS_rr(NATIVE_CC_AL,Rd,Rm) +#define MOVS_rrLSLi(Rd,Rm,i) CC_MOVS_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrLSLr(Rd,Rm,Rs) CC_MOVS_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrLSRi(Rd,Rm,i) CC_MOVS_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrLSRr(Rd,Rm,Rs) CC_MOVS_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrASRi(Rd,Rm,i) CC_MOVS_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrASRr(Rd,Rm,Rs) CC_MOVS_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrRORi(Rd,Rm,i) CC_MOVS_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MOVS_rrRORr(Rd,Rm,Rs) CC_MOVS_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MOVS_rrRRX(Rd,Rm) CC_MOVS_rrRRX(NATIVE_CC_AL,Rd,Rm) + +// MVNcc rd,#i +#define CC_MVN_ri8(cc,Rd,i) _OP1(cc,_MVN,0,Rd,UNSHIFTED_IMM8(i)) +// MVNcc Rd,#i ROR #s +#define CC_MVN_ri8RORi(cc,Rd,i,s) _OP1(cc,_MVN,0,Rd,SHIFT_IMM8_ROR(i,s)) +#define CC_MVN_ri(cc,Rd,i) _OP1(cc,_MVN,0,Rd,SHIFT_IMM(i)) +#define CC_MVN_rr(cc,Rd,Rm) _OP1(cc,_MVN,0,Rd,SHIFT_REG(Rm)) +#define CC_MVN_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MVN_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MVN_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MVN_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MVN_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MVN_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MVN_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MVN,0,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MVN_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MVN_rrRRX(cc,Rd,Rm) _OP1(cc,_MVN,0,Rd,SHIFT_RRX(Rm)) + +// MVN rd,#i +#define MVN_ri8(Rd,i) CC_MVN_ri8(NATIVE_CC_AL,Rd,i) +// MVN Rd,#i ROR #s +#define MVN_ri8RORi(Rd,i,s) CC_MVN_ri8RORi(NATIVE_CC_AL,Rd,i,s) +#define MVN_ri(Rd,i) CC_MVN_ri(NATIVE_CC_AL,Rd,i) +#define MVN_rr(Rd,Rm) CC_MVN_rr(NATIVE_CC_AL,Rd,Rm) +#define MVN_rrLSLi(Rd,Rm,i) CC_MVN_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrLSLr(Rd,Rm,Rs) CC_MVN_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrLSRi(Rd,Rm,i) CC_MVN_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrLSRr(Rd,Rm,Rs) CC_MVN_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrASRi(Rd,Rm,i) CC_MVN_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrASRr(Rd,Rm,Rs) CC_MVN_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrRORi(Rd,Rm,i) CC_MVN_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MVN_rrRORr(Rd,Rm,Rs) CC_MVN_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVN_rrRRX(Rd,Rm) CC_MVN_rrRRX(NATIVE_CC_AL,Rd,Rm) + +#define CC_MVNS_ri(cc,Rd,i) _OP1(cc,_MVN,1,Rd,SHIFT_IMM(i)) +#define CC_MVNS_rr(cc,Rd,Rm) _OP1(cc,_MVN,1,Rd,SHIFT_REG(Rm)) +#define CC_MVNS_rrLSLi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_LSL_i(Rm,i)) +#define CC_MVNS_rrLSLr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_LSL_r(Rm,Rs)) +#define CC_MVNS_rrLSRi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_LSR_i(Rm,i)) +#define CC_MVNS_rrLSRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_LSR_r(Rm,Rs)) +#define CC_MVNS_rrASRi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_ASR_i(Rm,i)) +#define CC_MVNS_rrASRr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_ASR_r(Rm,Rs)) +#define CC_MVNS_rrRORi(cc,Rd,Rm,i) _OP1(cc,_MVN,1,Rd,SHIFT_ROR_i(Rm,i)) +#define CC_MVNS_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,1,Rd,SHIFT_ROR_r(Rm,Rs)) +#define CC_MVNS_rrRRX(cc,Rd,Rm) _OP1(cc,_MVN,1,Rd,SHIFT_RRX(Rm)) + +#define MVNS_ri(Rd,i) CC_MVNS_ri(NATIVE_CC_AL,Rd,i) +#define MVNS_rr(Rd,Rm) CC_MVNS_rr(NATIVE_CC_AL,Rd,Rm) +#define MVNS_rrLSLi(Rd,Rm,i) CC_MVNS_rrLSLi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrLSLr(Rd,Rm,Rs) CC_MVNS_rrLSLr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrLSRi(Rd,Rm,i) CC_MVNS_rrLSRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrLSRr(Rd,Rm,Rs) CC_MVNS_rrLSRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrASRi(Rd,Rm,i) CC_MVNS_rrASRi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrASRr(Rd,Rm,Rs) CC_MVNS_rrASRr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrRORi(Rd,Rm,i) CC_MVNS_rrRORi(NATIVE_CC_AL,Rd,Rm,i) +#define MVNS_rrRORr(Rd,Rm,Rs) CC_MVNS_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) +#define MVNS_rrRRX(Rd,Rm) CC_MVNS_rrRRX(NATIVE_CC_AL,Rd,Rm) + +/* Opcodes Type 2 */ +#define CC_CMP_ri(cc,Rn,i) _OP2(cc,_CMP,Rn,SHIFT_IMM(i)) +#define CC_CMP_rr(cc,Rn,Rm) _OP2(cc,_CMP,Rn,SHIFT_REG(Rm)) +#define CC_CMP_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_CMP_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_CMP_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_CMP_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_CMP_rrASRi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_CMP_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_CMP_rrRORi(cc,Rn,Rm,i) _OP2(cc,_CMP,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_CMP_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_CMP,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_CMP_rrRRX(cc,Rn,Rm) _OP2(cc,_CMP,Rn,SHIFT_RRX(Rm)) + +#define CMP_ri(Rn,i) CC_CMP_ri(NATIVE_CC_AL,Rn,i) +#define CMP_rr(Rn,Rm) CC_CMP_rr(NATIVE_CC_AL,Rn,Rm) +#define CMP_rrLSLi(Rn,Rm,i) CC_CMP_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrLSLr(Rn,Rm,Rs) CC_CMP_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrLSRi(Rn,Rm,i) CC_CMP_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrLSRr(Rn,Rm,Rs) CC_CMP_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrASRi(Rn,Rm,i) CC_CMP_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrASRr(Rn,Rm,Rs) CC_CMP_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrRORi(Rn,Rm,i) CC_CMP_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define CMP_rrRORr(Rn,Rm,Rs) CC_CMP_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMP_rrRRX(Rn,Rm) CC_CMP_rrRRX(NATIVE_CC_AL,Rn,Rm) + +#define CC_CMN_ri(cc,Rn,i) _OP2(cc,_CMN,Rn,SHIFT_IMM(i)) +#define CC_CMN_rr(cc,Rn,r) _OP2(cc,_CMN,Rn,SHIFT_REG(r)) +#define CC_CMN_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_CMN_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_CMN_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_CMN_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_CMN_rrASRi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_CMN_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_CMN_rrRORi(cc,Rn,Rm,i) _OP2(cc,_CMN,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_CMN_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_CMN,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_CMN_rrRRX(cc,Rn,Rm) _OP2(cc,_CMN,Rn,SHIFT_RRX(Rm)) + +#define CMN_ri(Rn,i) CC_CMN_ri(NATIVE_CC_AL,Rn,i) +#define CMN_rr(Rn,r) CC_CMN_rr(NATIVE_CC_AL,Rn,r) +#define CMN_rrLSLi(Rn,Rm,i) CC_CMN_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrLSLr(Rn,Rm,Rs) CC_CMN_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrLSRi(Rn,Rm,i) CC_CMN_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrLSRr(Rn,Rm,Rs) CC_CMN_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrASRi(Rn,Rm,i) CC_CMN_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrASRr(Rn,Rm,Rs) CC_CMN_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrRORi(Rn,Rm,i) CC_CMN_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define CMN_rrRORr(Rn,Rm,Rs) CC_CMN_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define CMN_rrRRX(Rn,Rm) CC_CMN_rrRRX(NATIVE_CC_AL,Rn,Rm) + +#define CC_TST_ri(cc,Rn,i) _OP2(cc,_TST,Rn,SHIFT_IMM(i)) +#define CC_TST_rr(cc,Rn,r) _OP2(cc,_TST,Rn,SHIFT_REG(r)) +#define CC_TST_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_TST_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_TST_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_TST_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_TST_rrASRi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_TST_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_TST_rrRORi(cc,Rn,Rm,i) _OP2(cc,_TST,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_TST_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_TST,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_TST_rrRRX(cc,Rn,Rm) _OP2(cc,_TST,Rn,SHIFT_RRX(Rm)) + +#define TST_ri(Rn,i) CC_TST_ri(NATIVE_CC_AL,Rn,i) +#define TST_rr(Rn,r) CC_TST_rr(NATIVE_CC_AL,Rn,r) +#define TST_rrLSLi(Rn,Rm,i) CC_TST_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrLSLr(Rn,Rm,Rs) CC_TST_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrLSRi(Rn,Rm,i) CC_TST_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrLSRr(Rn,Rm,Rs) CC_TST_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrASRi(Rn,Rm,i) CC_TST_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrASRr(Rn,Rm,Rs) CC_TST_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrRORi(Rn,Rm,i) CC_TST_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define TST_rrRORr(Rn,Rm,Rs) CC_TST_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TST_rrRRX(Rn,Rm) CC_TST_rrRRX(NATIVE_CC_AL,Rn,Rm) + +#define CC_TEQ_ri(cc,Rn,i) _OP2(cc,_TEQ,Rn,SHIFT_IMM(i)) +#define CC_TEQ_rr(cc,Rn,r) _OP2(cc,_TEQ,Rn,SHIFT_REG(r)) +#define CC_TEQ_rrLSLi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_TEQ_rrLSLr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_TEQ_rrLSRi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_TEQ_rrLSRr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_TEQ_rrASRi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_TEQ_rrASRr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_TEQ_rrRORi(cc,Rn,Rm,i) _OP2(cc,_TEQ,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_TEQ_rrRORr(cc,Rn,Rm,Rs) _OP2(cc,_TEQ,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_TEQ_rrRRX(cc,Rn,Rm) _OP2(cc,_TEQ,Rn,SHIFT_RRX(Rm)) + +#define TEQ_ri(Rn,i) CC_TEQ_ri(NATIVE_CC_AL,Rn,i) +#define TEQ_rr(Rn,r) CC_TEQ_rr(NATIVE_CC_AL,Rn,r) +#define TEQ_rrLSLi(Rn,Rm,i) CC_TEQ_rrLSLi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrLSLr(Rn,Rm,Rs) CC_TEQ_rrLSLr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrLSRi(Rn,Rm,i) CC_TEQ_rrLSRi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrLSRr(Rn,Rm,Rs) CC_TEQ_rrLSRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrASRi(Rn,Rm,i) CC_TEQ_rrASRi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrASRr(Rn,Rm,Rs) CC_TEQ_rrASRr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrRORi(Rn,Rm,i) CC_TEQ_rrRORi(NATIVE_CC_AL,Rn,Rm,i) +#define TEQ_rrRORr(Rn,Rm,Rs) CC_TEQ_rrRORr(NATIVE_CC_AL,Rn,Rm,Rs) +#define TEQ_rrRRX(Rn,Rm) CC_TEQ_rrRRX(NATIVE_CC_AL,Rn,Rm) + +/* Opcodes Type 3 */ +#define CC_AND_rri(cc,Rd,Rn,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_AND_rrr(cc,Rd,Rn,Rm) _OP3(cc,_AND,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_AND_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_AND_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_AND_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_AND_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_AND_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_AND_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_AND_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_AND_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_AND_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_AND,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define AND_rri(Rd,Rn,i) CC_AND_rri(NATIVE_CC_AL,Rd,Rn,i) +#define AND_rrr(Rd,Rn,Rm) CC_AND_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define AND_rrrLSLi(Rd,Rn,Rm,i) CC_AND_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrLSLr(Rd,Rn,Rm,Rs) CC_AND_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrLSRi(Rd,Rn,Rm,i) CC_AND_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrLSRr(Rd,Rn,Rm,Rs) CC_AND_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrASRi(Rd,Rn,Rm,i) CC_AND_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrASRr(Rd,Rn,Rm,Rs) CC_AND_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrRORi(Rd,Rn,Rm,i) CC_AND_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define AND_rrrRORr(Rd,Rn,Rm,Rs) CC_AND_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define AND_rrrRRX(Rd,Rn,Rm) CC_AND_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ANDS_rri(cc,Rd,Rn,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ANDS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_AND,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ANDS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ANDS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ANDS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ANDS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ANDS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ANDS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ANDS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ANDS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_AND,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ANDS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_AND,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ANDS_rri(Rd,Rn,i) CC_ANDS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ANDS_rrr(Rd,Rn,Rm) CC_ANDS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ANDS_rrrLSLi(Rd,Rn,Rm,i) CC_ANDS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ANDS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrLSRi(Rd,Rn,Rm,i) CC_ANDS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ANDS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrASRi(Rd,Rn,Rm,i) CC_ANDS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrASRr(Rd,Rn,Rm,Rs) CC_ANDS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrRORi(Rd,Rn,Rm,i) CC_ANDS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ANDS_rrrRORr(Rd,Rn,Rm,Rs) CC_ANDS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ANDS_rrrRRX(Rd,Rn,Rm) CC_ANDS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_EOR_rri(cc,Rd,Rn,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_EOR_rrr(cc,Rd,Rn,Rm) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_EOR_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_EOR_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_EOR_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_EOR_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_EOR_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_EOR_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_EOR_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_EOR_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_EOR_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_EOR,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define EOR_rri(Rd,Rn,i) CC_EOR_rri(NATIVE_CC_AL,Rd,Rn,i) +#define EOR_rrr(Rd,Rn,Rm) CC_EOR_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define EOR_rrrLSLi(Rd,Rn,Rm,i) CC_EOR_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrLSLr(Rd,Rn,Rm,Rs) CC_EOR_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrLSRi(Rd,Rn,Rm,i) CC_EOR_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrLSRr(Rd,Rn,Rm,Rs) CC_EOR_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrASRi(Rd,Rn,Rm,i) CC_EOR_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrASRr(Rd,Rn,Rm,Rs) CC_EOR_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrRORi(Rd,Rn,Rm,i) CC_EOR_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EOR_rrrRORr(Rd,Rn,Rm,Rs) CC_EOR_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EOR_rrrRRX(Rd,Rn,Rm) CC_EOR_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_EORS_rri(cc,Rd,Rn,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_EORS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_EORS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_EORS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_EORS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_EORS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_EORS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_EORS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_EORS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_EORS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_EORS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_EOR,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define EORS_rri(Rd,Rn,i) CC_EORS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define EORS_rrr(Rd,Rn,Rm) CC_EORS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define EORS_rrrLSLi(Rd,Rn,Rm,i) CC_EORS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrLSLr(Rd,Rn,Rm,Rs) CC_EORS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrLSRi(Rd,Rn,Rm,i) CC_EORS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrLSRr(Rd,Rn,Rm,Rs) CC_EORS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrASRi(Rd,Rn,Rm,i) CC_EORS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrASRr(Rd,Rn,Rm,Rs) CC_EORS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrRORi(Rd,Rn,Rm,i) CC_EORS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define EORS_rrrRORr(Rd,Rn,Rm,Rs) CC_EORS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define EORS_rrrRRX(Rd,Rn,Rm) CC_EORS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SUB_rri(cc,Rd,Rn,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_SUB_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SUB_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SUB_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SUB_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SUB_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SUB_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SUB_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SUB_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SUB_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SUB_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SUB,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define SUB_rri(Rd,Rn,i) CC_SUB_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SUB_rrr(Rd,Rn,Rm) CC_SUB_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SUB_rrrLSLi(Rd,Rn,Rm,i) CC_SUB_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrLSLr(Rd,Rn,Rm,Rs) CC_SUB_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrLSRi(Rd,Rn,Rm,i) CC_SUB_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrLSRr(Rd,Rn,Rm,Rs) CC_SUB_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrASRi(Rd,Rn,Rm,i) CC_SUB_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrASRr(Rd,Rn,Rm,Rs) CC_SUB_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrRORi(Rd,Rn,Rm,i) CC_SUB_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUB_rrrRORr(Rd,Rn,Rm,Rs) CC_SUB_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUB_rrrRRX(Rd,Rn,Rm) CC_SUB_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SUBS_rri(cc,Rd,Rn,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_SUBS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SUBS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SUBS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SUBS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SUBS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SUBS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SUBS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SUBS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SUBS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SUBS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SUB,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define SUBS_rri(Rd,Rn,i) CC_SUBS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SUBS_rrr(Rd,Rn,Rm) CC_SUBS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SUBS_rrrLSLi(Rd,Rn,Rm,i) CC_SUBS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrLSLr(Rd,Rn,Rm,Rs) CC_SUBS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrLSRi(Rd,Rn,Rm,i) CC_SUBS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrLSRr(Rd,Rn,Rm,Rs) CC_SUBS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrASRi(Rd,Rn,Rm,i) CC_SUBS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrASRr(Rd,Rn,Rm,Rs) CC_SUBS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrRORi(Rd,Rn,Rm,i) CC_SUBS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SUBS_rrrRORr(Rd,Rn,Rm,Rs) CC_SUBS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SUBS_rrrRRX(Rd,Rn,Rm) CC_SUBS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSB_rri(cc,Rd,Rn,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSB_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSB_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSB_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSB_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSB_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSB_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSB_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSB_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSB_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSB_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSB,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSB_rri(Rd,Rn,i) CC_RSB_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSB_rrr(Rd,Rn,Rm) CC_RSB_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSB_rrrLSLi(Rd,Rn,Rm,i) CC_RSB_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSB_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrLSRi(Rd,Rn,Rm,i) CC_RSB_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSB_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrASRi(Rd,Rn,Rm,i) CC_RSB_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrASRr(Rd,Rn,Rm,Rs) CC_RSB_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrRORi(Rd,Rn,Rm,i) CC_RSB_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSB_rrrRORr(Rd,Rn,Rm,Rs) CC_RSB_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSB_rrrRRX(Rd,Rn,Rm) CC_RSB_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSBS_rri(cc,Rd,Rn,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSBS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSBS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSBS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSBS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSBS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSBS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSBS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSBS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSBS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSBS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSB,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSBS_rri(Rd,Rn,i) CC_RSBS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSBS_rrr(Rd,Rn,Rm) CC_RSBS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSBS_rrrLSLi(Rd,Rn,Rm,i) CC_RSBS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSBS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrLSRi(Rd,Rn,Rm,i) CC_RSBS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSBS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrASRi(Rd,Rn,Rm,i) CC_RSBS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrASRr(Rd,Rn,Rm,Rs) CC_RSBS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrRORi(Rd,Rn,Rm,i) CC_RSBS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSBS_rrrRORr(Rd,Rn,Rm,Rs) CC_RSBS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSBS_rrrRRX(Rd,Rn,Rm) CC_RSBS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADD_rri8(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,UNSHIFT_IMM8(i)) +#define CC_ADD_rri8RORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_IMM8_ROR(Rm,i)) + +#define CC_ADD_rri(cc,Rd,Rn,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADD_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADD_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADD_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADD_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADD_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADD_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADD_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADD_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADD_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADD_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADD,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADD_rri8(cc,Rd,Rn,i) CC_ADD_rri8(NATIVE_CC_AL,Rd,Rn,i) +#define ADD_rri8RORi(cc,Rd,Rn,Rm,i) CC_ADD_rri8RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) + +#define ADD_rri(Rd,Rn,i) CC_ADD_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADD_rrr(Rd,Rn,Rm) CC_ADD_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADD_rrrLSLi(Rd,Rn,Rm,i) CC_ADD_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADD_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrLSRi(Rd,Rn,Rm,i) CC_ADD_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADD_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrASRi(Rd,Rn,Rm,i) CC_ADD_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrASRr(Rd,Rn,Rm,Rs) CC_ADD_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrRORi(Rd,Rn,Rm,i) CC_ADD_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADD_rrrRORr(Rd,Rn,Rm,Rs) CC_ADD_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADD_rrrRRX(Rd,Rn,Rm) CC_ADD_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADDS_rri(cc,Rd,Rn,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADDS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADDS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADDS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADDS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADDS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADDS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADDS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADDS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADDS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADDS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADD,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADDS_rri(Rd,Rn,i) CC_ADDS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADDS_rrr(Rd,Rn,Rm) CC_ADDS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADDS_rrrLSLi(Rd,Rn,Rm,i) CC_ADDS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADDS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrLSRi(Rd,Rn,Rm,i) CC_ADDS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADDS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrASRi(Rd,Rn,Rm,i) CC_ADDS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrASRr(Rd,Rn,Rm,Rs) CC_ADDS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrRORi(Rd,Rn,Rm,i) CC_ADDS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADDS_rrrRORr(Rd,Rn,Rm,Rs) CC_ADDS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADDS_rrrRRX(Rd,Rn,Rm) CC_ADDS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADC_rri(cc,Rd,Rn,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADC_rri(Rd,Rn,i) CC_ADC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADC_rrr(Rd,Rn,Rm) CC_ADC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADC_rrrLSLi(Rd,Rn,Rm,i) CC_ADC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrLSRi(Rd,Rn,Rm,i) CC_ADC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrASRi(Rd,Rn,Rm,i) CC_ADC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrASRr(Rd,Rn,Rm,Rs) CC_ADC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrRORi(Rd,Rn,Rm,i) CC_ADC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADC_rrrRORr(Rd,Rn,Rm,Rs) CC_ADC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADC_rrrRRX(Rd,Rn,Rm) CC_ADC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ADCS_rri(cc,Rd,Rn,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ADCS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ADCS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ADCS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ADCS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ADCS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ADCS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ADCS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ADCS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ADCS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ADCS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ADC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ADCS_rri(Rd,Rn,i) CC_ADCS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ADCS_rrr(Rd,Rn,Rm) CC_ADCS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ADCS_rrrLSLi(Rd,Rn,Rm,i) CC_ADCS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ADCS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrLSRi(Rd,Rn,Rm,i) CC_ADCS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ADCS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrASRi(Rd,Rn,Rm,i) CC_ADCS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrASRr(Rd,Rn,Rm,Rs) CC_ADCS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrRORi(Rd,Rn,Rm,i) CC_ADCS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ADCS_rrrRORr(Rd,Rn,Rm,Rs) CC_ADCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ADCS_rrrRRX(Rd,Rn,Rm) CC_ADCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SBC_rri(cc,Rd,Rn,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_SBC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SBC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SBC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SBC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SBC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SBC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SBC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SBC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SBC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SBC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SBC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define SBC_rri(Rd,Rn,i) CC_SBC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SBC_rrr(Rd,Rn,Rm) CC_SBC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SBC_rrrLSLi(Rd,Rn,Rm,i) CC_SBC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrLSLr(Rd,Rn,Rm,Rs) CC_SBC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrLSRi(Rd,Rn,Rm,i) CC_SBC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrLSRr(Rd,Rn,Rm,Rs) CC_SBC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrASRi(Rd,Rn,Rm,i) CC_SBC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrASRr(Rd,Rn,Rm,Rs) CC_SBC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrRORi(Rd,Rn,Rm,i) CC_SBC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBC_rrrRORr(Rd,Rn,Rm,Rs) CC_SBC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBC_rrrRRX(Rd,Rn,Rm) CC_SBC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_SBCS_rri(cc,Rd,Rn,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_SBCS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_SBCS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_SBCS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_SBCS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_SBCS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_SBCS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_SBCS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_SBCS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_SBCS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_SBCS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_SBC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define SBCS_rri(Rd,Rn,i) CC_SBCS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define SBCS_rrr(Rd,Rn,Rm) CC_SBCS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define SBCS_rrrLSLi(Rd,Rn,Rm,i) CC_SBCS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrLSLr(Rd,Rn,Rm,Rs) CC_SBCS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrLSRi(Rd,Rn,Rm,i) CC_SBCS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrLSRr(Rd,Rn,Rm,Rs) CC_SBCS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrASRi(Rd,Rn,Rm,i) CC_SBCS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrASRr(Rd,Rn,Rm,Rs) CC_SBCS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrRORi(Rd,Rn,Rm,i) CC_SBCS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define SBCS_rrrRORr(Rd,Rn,Rm,Rs) CC_SBCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define SBCS_rrrRRX(Rd,Rn,Rm) CC_SBCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSC_rri(cc,Rd,Rn,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSC_rri(Rd,Rn,i) CC_RSC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSC_rrr(Rd,Rn,Rm) CC_RSC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSC_rrrLSLi(Rd,Rn,Rm,i) CC_RSC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrLSRi(Rd,Rn,Rm,i) CC_RSC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrASRi(Rd,Rn,Rm,i) CC_RSC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrASRr(Rd,Rn,Rm,Rs) CC_RSC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrRORi(Rd,Rn,Rm,i) CC_RSC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSC_rrrRORr(Rd,Rn,Rm,Rs) CC_RSC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSC_rrrRRX(Rd,Rn,Rm) CC_RSC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_RSCS_rri(cc,Rd,Rn,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_RSCS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_RSCS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_RSCS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_RSCS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_RSCS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_RSCS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_RSCS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_RSCS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_RSCS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_RSCS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_RSC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define RSCS_rri(Rd,Rn,i) CC_RSCS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define RSCS_rrr(Rd,Rn,Rm) CC_RSCS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define RSCS_rrrLSLi(Rd,Rn,Rm,i) CC_RSCS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrLSLr(Rd,Rn,Rm,Rs) CC_RSCS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrLSRi(Rd,Rn,Rm,i) CC_RSCS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrLSRr(Rd,Rn,Rm,Rs) CC_RSCS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrASRi(Rd,Rn,Rm,i) CC_RSCS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrASRr(Rd,Rn,Rm,Rs) CC_RSCS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrRORi(Rd,Rn,Rm,i) CC_RSCS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define RSCS_rrrRORr(Rd,Rn,Rm,Rs) CC_RSCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define RSCS_rrrRRX(Rd,Rn,Rm) CC_RSCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +// ORRcc Rd,Rn,#i +#define CC_ORR_rri8(cc,Rd,Rn,i) _OP3(cc,_ORR,0,Rd,Rn,UNSHIFTED_IMM8(i)) +// ORRcc Rd,Rn,#i ROR #s +#define CC_ORR_rri8RORi(cc,Rd,Rn,i,s) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_IMM8_ROR(i,s)) + +#define CC_ORR_rri(cc,Rd,Rn,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_ORR_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ORR_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ORR_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ORR_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ORR_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ORR_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ORR_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ORR_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ORR_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ORR_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_RRX(Rm)) + +// ORR Rd,Rn,#i +#define ORR_rri8(Rd,Rn,i) CC_ORR_rri8(NATIVE_CC_AL,Rd,Rn,i) +// ORR Rd,Rn,#i ROR #s +#define ORR_rri8RORi(Rd,Rn,i,s) CC_ORR_rri8RORi(NATIVE_CC_AL,Rd,Rn,i,s) + +#define ORR_rri(Rd,Rn,i) CC_ORR_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ORR_rrr(Rd,Rn,Rm) CC_ORR_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ORR_rrrLSLi(Rd,Rn,Rm,i) CC_ORR_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrLSLr(Rd,Rn,Rm,Rs) CC_ORR_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrLSRi(Rd,Rn,Rm,i) CC_ORR_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrLSRr(Rd,Rn,Rm,Rs) CC_ORR_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrASRi(Rd,Rn,Rm,i) CC_ORR_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrASRr(Rd,Rn,Rm,Rs) CC_ORR_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrRORi(Rd,Rn,Rm,i) CC_ORR_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORR_rrrRORr(Rd,Rn,Rm,Rs) CC_ORR_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORR_rrrRRX(Rd,Rn,Rm) CC_ORR_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_ORRS_rri(cc,Rd,Rn,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_ORRS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_ORRS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_ORRS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_ORRS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_ORRS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_ORRS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_ORRS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_ORRS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_ORRS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_ORRS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ORR,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define ORRS_rri(Rd,Rn,i) CC_ORRS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define ORRS_rrr(Rd,Rn,Rm) CC_ORRS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define ORRS_rrrLSLi(Rd,Rn,Rm,i) CC_ORRS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrLSLr(Rd,Rn,Rm,Rs) CC_ORRS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrLSRi(Rd,Rn,Rm,i) CC_ORRS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrLSRr(Rd,Rn,Rm,Rs) CC_ORRS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrASRi(Rd,Rn,Rm,i) CC_ORRS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrASRr(Rd,Rn,Rm,Rs) CC_ORRS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrRORi(Rd,Rn,Rm,i) CC_ORRS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define ORRS_rrrRORr(Rd,Rn,Rm,Rs) CC_ORRS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define ORRS_rrrRRX(Rd,Rn,Rm) CC_ORRS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_BIC_rri(cc,Rd,Rn,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_IMM(i)) +#define CC_BIC_rrr(cc,Rd,Rn,Rm) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_REG(Rm)) +#define CC_BIC_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_BIC_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_BIC_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_BIC_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_BIC_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_BIC_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_BIC_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_BIC_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_BIC_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_BIC,0,Rd,Rn,SHIFT_RRX(Rm)) + +#define BIC_rri(Rd,Rn,i) CC_BIC_rri(NATIVE_CC_AL,Rd,Rn,i) +#define BIC_rrr(Rd,Rn,Rm) CC_BIC_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define BIC_rrrLSLi(Rd,Rn,Rm,i) CC_BIC_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrLSLr(Rd,Rn,Rm,Rs) CC_BIC_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrLSRi(Rd,Rn,Rm,i) CC_BIC_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrLSRr(Rd,Rn,Rm,Rs) CC_BIC_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrASRi(Rd,Rn,Rm,i) CC_BIC_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrASRr(Rd,Rn,Rm,Rs) CC_BIC_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrRORi(Rd,Rn,Rm,i) CC_BIC_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BIC_rrrRORr(Rd,Rn,Rm,Rs) CC_BIC_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BIC_rrrRRX(Rd,Rn,Rm) CC_BIC_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_BICS_rri(cc,Rd,Rn,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_IMM(i)) +#define CC_BICS_rrr(cc,Rd,Rn,Rm) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_REG(Rm)) +#define CC_BICS_rrrLSLi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSL_i(Rm,i)) +#define CC_BICS_rrrLSLr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSL_r(Rm,Rs)) +#define CC_BICS_rrrLSRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSR_i(Rm,i)) +#define CC_BICS_rrrLSRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_LSR_r(Rm,Rs)) +#define CC_BICS_rrrASRi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ASR_i(Rm,i)) +#define CC_BICS_rrrASRr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ASR_r(Rm,Rs)) +#define CC_BICS_rrrRORi(cc,Rd,Rn,Rm,i) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ROR_i(Rm,i)) +#define CC_BICS_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) +#define CC_BICS_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_BIC,1,Rd,Rn,SHIFT_RRX(Rm)) + +#define BICS_rri(Rd,Rn,i) CC_BICS_rri(NATIVE_CC_AL,Rd,Rn,i) +#define BICS_rrr(Rd,Rn,Rm) CC_BICS_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define BICS_rrrLSLi(Rd,Rn,Rm,i) CC_BICS_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrLSLr(Rd,Rn,Rm,Rs) CC_BICS_rrrLSLr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrLSRi(Rd,Rn,Rm,i) CC_BICS_rrrLSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrLSRr(Rd,Rn,Rm,Rs) CC_BICS_rrrLSRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrASRi(Rd,Rn,Rm,i) CC_BICS_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrASRr(Rd,Rn,Rm,Rs) CC_BICS_rrrASRr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrRORi(Rd,Rn,Rm,i) CC_BICS_rrrRORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define BICS_rrrRORr(Rd,Rn,Rm,Rs) CC_BICS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) +#define BICS_rrrRRX(Rd,Rn,Rm) CC_BICS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) + +/* Branch instructions */ +#define CC_B_i(cc,i) _W(((cc) << 28) | (10 << 24) | (i)) +#define CC_BL_i(cc,i) _W(((cc) << 28) | (11 << 24) | (i)) +#define CC_BLX_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (3 << 4) | (0xfff << 8) | (r)) +#define CC_BX_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (1 << 4) | (0xfff << 8) | (r)) +#define CC_BXJ_r(cc,r) _W(((cc) << 28) | (0x12 << 20) | (2 << 4) | (0xfff << 8) | (r)) + +#define BEQ_i(i) CC_B_i(NATIVE_CC_EQ,i) +#define BNE_i(i) CC_B_i(NATIVE_CC_NE,i) +#define BCS_i(i) CC_B_i(NATIVE_CC_CS,i) +#define BCC_i(i) CC_B_i(NATIVE_CC_CC,i) +#define BMI_i(i) CC_B_i(NATIVE_CC_MI,i) +#define BPL_i(i) CC_B_i(NATIVE_CC_PL,i) +#define BVS_i(i) CC_B_i(NATIVE_CC_VS,i) +#define BVC_i(i) CC_B_i(NATIVE_CC_VC,i) +#define BHI_i(i) CC_B_i(NATIVE_CC_HI,i) +#define BLS_i(i) CC_B_i(NATIVE_CC_LS,i) +#define BGE_i(i) CC_B_i(NATIVE_CC_GE,i) +#define BLT_i(i) CC_B_i(NATIVE_CC_LT,i) +#define BGT_i(i) CC_B_i(NATIVE_CC_GT,i) +#define BLE_i(i) CC_B_i(NATIVE_CC_LE,i) +#define B_i(i) CC_B_i(NATIVE_CC_AL,i) + +#define BL_i(i) CC_BL_i(NATIVE_CC_AL,i) +#define BLX_i(i) _W((NATIVE_CC_AL << 28) | (10 << 24) | (i)) +#define BLX_r(r) CC_BLX_r(NATIVE_CC_AL,r) +#define BX_r(r) CC_BX_r(NATIVE_CC_AL,r) +#define BXJ_r(r) CC_BXJ_r(NATIVE_CC_AL,r) + +/* Status register instructions */ +#define CC_MRS_CPSR(cc,Rd) _W(((cc) << 28) | (0x10 << 20) | ((Rd) << 12) | (0xf << 16)) +#define MRS_CPSR(Rd) CC_MRS_CPSR(NATIVE_CC_AL,Rd) +#define CC_MRS_SPSR(cc,Rd) _W(((cc) << 28) | (0x14 << 20) | ((Rd) << 12) | (0xf << 16)) +#define MRS_SPSR(Rd) CC_MRS_SPSR(NATIVE_CC_AL,Rd) + +#define CC_MSR_CPSR_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x9 << 16) | (0xf << 12) | SHIFT_IMM(i)) +#define CC_MSR_CPSR_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x9 << 16) | (0xf << 12) | (Rm)) + +#define MSR_CPSR_i(i) CC_MSR_CPSR_i(NATIVE_CC_AL,(i)) +#define MSR_CPSR_r(Rm) CC_MSR_CPSR_r(NATIVE_CC_AL,(Rm)) + +#define CC_MSR_CPSRf_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x8 << 16) | (0xf << 12) | SHIFT_IMM(i)) +#define CC_MSR_CPSRf_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x8 << 16) | (0xf << 12) | (Rm)) + +#define MSR_CPSRf_i(i) CC_MSR_CPSRf_i(NATIVE_CC_AL,(i)) +#define MSR_CPSRf_r(Rm) CC_MSR_CPSRf_r(NATIVE_CC_AL,(Rm)) + +#define CC_MSR_CPSRc_i(cc,i) _W(((cc) << 28) | (0x32 << 20) | (0x1 << 16) | (0xf << 12) | SHIFT_IMM(i)) +#define CC_MSR_CPSRc_r(cc,Rm) _W(((cc) << 28) | (0x12 << 20) | (0x1 << 16) | (0xf << 12) | (Rm)) + +#define MSR_CPSRc_i(i) CC_MSR_CPSRc_i(NATIVE_CC_AL,(i)) +#define MSR_CPSRc_r(Rm) CC_MSR_CPSRc_r(NATIVE_CC_AL,(Rm)) + +/* Load Store instructions */ + +#define CC_PUSH(cc,r) _W(((cc) << 28) | (0x92d << 16) | (1 << (r))) +#define PUSH(r) CC_PUSH(NATIVE_CC_AL, r) + +#define CC_PUSH_REGS(cc,r) _W(((cc) << 28) | (0x92d << 16) | (r)) +#define PUSH_REGS(r) CC_PUSH_REGS(NATIVE_CC_AL, r) + +#define CC_POP(cc,r) _W(((cc) << 28) | (0x8bd << 16) | (1 << (r))) +#define POP(r) CC_POP(NATIVE_CC_AL, r) + +#define CC_POP_REGS(cc,r) _W(((cc) << 28) | (0x8bd << 16) | (r)) +#define POP_REGS(r) CC_POP_REGS(NATIVE_CC_AL, r) + +#define CC_LDR_rR(cc,Rd,Rn) _LS1(cc,1,0,Rd,Rn,ADD_IMM(0)) +#define CC_LDR_rRI(cc,Rd,Rn,i) _LS1(cc,1,0,Rd,Rn,(i) >= 0 ? ADD_IMM(i) : SUB_IMM(-(i))) +#define CC_LDR_rRi(cc,Rd,Rn,i) _LS1(cc,1,0,Rd,Rn,SUB_IMM(i)) +#define CC_LDR_rRR(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,ADD_REG(Rm)) +#define CC_LDR_rRr(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,SUB_REG(Rm)) +#define CC_LDR_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_LDR_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_LDR_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_LDR_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_LDR_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_LDR_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_LDR_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_LDR_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,0,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_LDR_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,ADD_RRX(Rm)) +#define CC_LDR_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,0,Rd,Rn,SUB_RRX(Rm)) + +#define LDR_rR(Rd,Rn) CC_LDR_rR(NATIVE_CC_AL,Rd,Rn) +#define LDR_rRI(Rd,Rn,i) CC_LDR_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDR_rRi(Rd,Rn,i) CC_LDR_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDR_rRR(Rd,Rn,Rm) CC_LDR_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDR_rRr(Rd,Rn,Rm) CC_LDR_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDR_rRR_LSLi(Rd,Rn,Rm,i) CC_LDR_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_LSLi(Rd,Rn,Rm,i) CC_LDR_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_LSRi(Rd,Rn,Rm,i) CC_LDR_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_LSRi(Rd,Rn,Rm,i) CC_LDR_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_ASRi(Rd,Rn,Rm,i) CC_LDR_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_ASRi(Rd,Rn,Rm,i) CC_LDR_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_RORi(Rd,Rn,Rm,i) CC_LDR_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRr_RORi(Rd,Rn,Rm,i) CC_LDR_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDR_rRR_RRX(Rd,Rn,Rm) CC_LDR_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDR_rRr_RRX(Rd,Rn,Rm) CC_LDR_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STR_rR(cc,Rd,Rn) _LS1(cc,0,0,Rd,Rn,ADD_IMM(0)) +#define CC_STR_rRI(cc,Rd,Rn,i) _LS1(cc,0,0,Rd,Rn,ADD_IMM(i)) +#define CC_STR_rRi(cc,Rd,Rn,i) _LS1(cc,0,0,Rd,Rn,SUB_IMM(i)) +#define CC_STR_rRR(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,ADD_REG(Rm)) +#define CC_STR_rRr(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,SUB_REG(Rm)) +#define CC_STR_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_STR_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_STR_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_STR_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_STR_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_STR_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_STR_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_STR_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,0,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_STR_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,ADD_RRX(Rm)) +#define CC_STR_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,0,Rd,Rn,SUB_RRX(Rm)) + +#define STR_rR(Rd,Rn) CC_STR_rR(NATIVE_CC_AL,Rd,Rn) +#define STR_rRI(Rd,Rn,i) CC_STR_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STR_rRi(Rd,Rn,i) CC_STR_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STR_rRR(Rd,Rn,Rm) CC_STR_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STR_rRr(Rd,Rn,Rm) CC_STR_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define STR_rRR_LSLi(Rd,Rn,Rm,i) CC_STR_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_LSLi(Rd,Rn,Rm,i) CC_STR_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_LSRi(Rd,Rn,Rm,i) CC_STR_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_LSRi(Rd,Rn,Rm,i) CC_STR_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_ASRi(Rd,Rn,Rm,i) CC_STR_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_ASRi(Rd,Rn,Rm,i) CC_STR_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_RORi(Rd,Rn,Rm,i) CC_STR_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRr_RORi(Rd,Rn,Rm,i) CC_STR_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STR_rRR_RRX(Rd,Rn,Rm) CC_STR_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define STR_rRr_RRX(Rd,Rn,Rm) CC_STR_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRB_rR(cc,Rd,Rn) _LS1(cc,1,1,Rd,Rn,ADD_IMM(0)) +#define CC_LDRB_rRI(cc,Rd,Rn,i) _LS1(cc,1,1,Rd,Rn,ADD_IMM(i)) +#define CC_LDRB_rRi(cc,Rd,Rn,i) _LS1(cc,1,1,Rd,Rn,SUB_IMM(i)) +#define CC_LDRB_rRR(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,ADD_REG(Rm)) +#define CC_LDRB_rRr(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,SUB_REG(Rm)) +#define CC_LDRB_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_LDRB_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_LDRB_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_LDRB_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_LDRB_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_LDRB_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_LDRB_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_LDRB_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,1,1,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_LDRB_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,ADD_RRX(Rm)) +#define CC_LDRB_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,1,1,Rd,Rn,SUB_RRX(Rm)) + +#define LDRB_rR(Rd,Rn) CC_LDRB_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRB_rRI(Rd,Rn,i) CC_LDRB_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRB_rRi(Rd,Rn,i) CC_LDRB_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRB_rRR(Rd,Rn,Rm) CC_LDRB_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRB_rRr(Rd,Rn,Rm) CC_LDRB_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRB_rRR_LSLi(Rd,Rn,Rm,i) CC_LDRB_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_LSLi(Rd,Rn,Rm,i) CC_LDRB_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_LSRi(Rd,Rn,Rm,i) CC_LDRB_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_LSRi(Rd,Rn,Rm,i) CC_LDRB_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_ASRi(Rd,Rn,Rm,i) CC_LDRB_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_ASRi(Rd,Rn,Rm,i) CC_LDRB_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_RORi(Rd,Rn,Rm,i) CC_LDRB_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRr_RORi(Rd,Rn,Rm,i) CC_LDRB_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define LDRB_rRR_RRX(Rd,Rn,Rm) CC_LDRB_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRB_rRr_RRX(Rd,Rn,Rm) CC_LDRB_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STRB_rR(cc,Rd,Rn) _LS1(cc,0,1,Rd,Rn,ADD_IMM(0)) +#define CC_STRB_rRI(cc,Rd,Rn,i) _LS1(cc,0,1,Rd,Rn,ADD_IMM(i)) +#define CC_STRB_rRi(cc,Rd,Rn,i) _LS1(cc,0,1,Rd,Rn,SUB_IMM(i)) +#define CC_STRB_rRR(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,ADD_REG(Rm)) +#define CC_STRB_rRr(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,SUB_REG(Rm)) +#define CC_STRB_rRR_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_LSL(Rm,i)) +#define CC_STRB_rRr_LSLi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_LSL(Rm,i)) +#define CC_STRB_rRR_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_LSR(Rm,i)) +#define CC_STRB_rRr_LSRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_LSR(Rm,i)) +#define CC_STRB_rRR_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_ASR(Rm,i)) +#define CC_STRB_rRr_ASRi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_ASR(Rm,i)) +#define CC_STRB_rRR_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,ADD_ROR(Rm,i)) +#define CC_STRB_rRr_RORi(cc,Rd,Rn,Rm,i) _LS1(cc,0,1,Rd,Rn,SUB_ROR(Rm,i)) +#define CC_STRB_rRR_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,ADD_RRX(Rm)) +#define CC_STRB_rRr_RRX(cc,Rd,Rn,Rm) _LS1(cc,0,1,Rd,Rn,SUB_RRX(Rm)) + +#define STRB_rR(Rd,Rn) CC_STRB_rR(NATIVE_CC_AL,Rd,Rn) +#define STRB_rRI(Rd,Rn,i) CC_STRB_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STRB_rRi(Rd,Rn,i) CC_STRB_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STRB_rRR(Rd,Rn,Rm) CC_STRB_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRB_rRr(Rd,Rn,Rm) CC_STRB_rRr(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRB_rRR_LSLi(Rd,Rn,Rm,i) CC_STRB_rRR_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_LSLi(Rd,Rn,Rm,i) CC_STRB_rRr_LSLi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_LSRi(Rd,Rn,Rm,i) CC_STRB_rRR_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_LSRi(Rd,Rn,Rm,i) CC_STRB_rRr_LSRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_ASRi(Rd,Rn,Rm,i) CC_STRB_rRR_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_ASRi(Rd,Rn,Rm,i) CC_STRB_rRr_ASRi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_RORi(Rd,Rn,Rm,i) CC_STRB_rRR_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRr_RORi(Rd,Rn,Rm,i) CC_STRB_rRr_RORi(NATIVE_CC_AL,Rd,Rn,Rm,i) +#define STRB_rRR_RRX(Rd,Rn,Rm) CC_STRB_rRR_RRX(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRB_rRr_RRX(Rd,Rn,Rm) CC_STRB_rRr_RRX(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRSH_rR(cc,Rd,Rn) _LS2(cc,1,1,1,1,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRSH_rRI(cc,Rd,Rn,i) _LS2(cc,1,1,1,1,Rd,Rn,ADD2_IMM(i)) +#define CC_LDRSH_rRi(cc,Rd,Rn,i) _LS2(cc,1,1,1,1,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRSH_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRSH_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,1,Rd,Rn,SUB2_REG(Rm)) + +#define LDRSH_rR(Rd,Rn) CC_LDRSH_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRSH_rRI(Rd,Rn,i) CC_LDRSH_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSH_rRi(Rd,Rn,i) CC_LDRSH_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSH_rRR(Rd,Rn,Rm) CC_LDRSH_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRSH_rRr(Rd,Rn,Rm) CC_LDRSH_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRH_rR(cc,Rd,Rn) _LS2(cc,1,1,0,1,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRH_rRI(cc,Rd,Rn,i) _LS2(cc,1,1,0,1,Rd,Rn,(i) >= 0 ? ADD2_IMM(i) : SUB2_IMM(-(i))) +#define CC_LDRH_rRi(cc,Rd,Rn,i) _LS2(cc,1,1,0,1,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRH_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,1,0,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRH_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,1,0,1,Rd,Rn,SUB2_REG(Rm)) + +#define LDRH_rR(Rd,Rn) CC_LDRH_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRH_rRI(Rd,Rn,i) CC_LDRH_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRH_rRi(Rd,Rn,i) CC_LDRH_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRH_rRR(Rd,Rn,Rm) CC_LDRH_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRH_rRr(Rd,Rn,Rm) CC_LDRH_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STRD_rR(cc,Rd,Rn) _LS2(cc,1,0,1,1,Rd,Rn,ADD2_IMM(0)) +#define CC_STRD_rRI(cc,Rd,Rn,i) _LS2(cc,1,0,1,1,Rd,Rn,ADD2_IMM(i)) +#define CC_STRD_rRi(cc,Rd,Rn,i) _LS2(cc,1,0,1,1,Rd,Rn,SUB2_IMM(i)) +#define CC_STRD_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_STRD_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,1,Rd,Rn,SUB2_REG(Rm)) + +#define STRD_rR(Rd,Rn) CC_STRD_rR(NATIVE_CC_AL,Rd,Rn) +#define STRD_rRI(Rd,Rn,i) CC_STRD_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STRD_rRi(Rd,Rn,i) CC_STRD_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STRD_rRR(Rd,Rn,Rm) CC_STRD_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRD_rRr(Rd,Rn,Rm) CC_STRD_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_STRH_rR(cc,Rd,Rn) _LS2(cc,1,0,0,1,Rd,Rn,ADD2_IMM(0)) +#define CC_STRH_rRI(cc,Rd,Rn,i) _LS2(cc,1,0,0,1,Rd,Rn,ADD2_IMM(i)) +#define CC_STRH_rRi(cc,Rd,Rn,i) _LS2(cc,1,0,0,1,Rd,Rn,SUB2_IMM(i)) +#define CC_STRH_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,0,0,1,Rd,Rn,ADD2_REG(Rm)) +#define CC_STRH_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,0,0,1,Rd,Rn,SUB2_REG(Rm)) + +#define STRH_rR(Rd,Rn) CC_STRH_rR(NATIVE_CC_AL,Rd,Rn) +#define STRH_rRI(Rd,Rn,i) CC_STRH_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define STRH_rRi(Rd,Rn,i) CC_STRH_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define STRH_rRR(Rd,Rn,Rm) CC_STRH_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define STRH_rRr(Rd,Rn,Rm) CC_STRH_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRSB_rR(cc,Rd,Rn) _LS2(cc,1,1,1,0,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRSB_rRI(cc,Rd,Rn,i) _LS2(cc,1,1,1,0,Rd,Rn,ADD2_IMM(i)) +#define CC_LDRSB_rRi(cc,Rd,Rn,i) _LS2(cc,1,1,1,0,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRSB_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,0,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRSB_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,1,1,0,Rd,Rn,SUB2_REG(Rm)) + +#define LDRSB_rR(Rd,Rn) CC_LDRSB_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRSB_rRI(Rd,Rn,i) CC_LDRSB_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSB_rRi(Rd,Rn,i) CC_LDRSB_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRSB_rRR(Rd,Rn,Rm) CC_LDRSB_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRSB_rRr(Rd,Rn,Rm) CC_LDRSB_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +#define CC_LDRD_rR(cc,Rd,Rn) _LS2(cc,1,0,1,0,Rd,Rn,ADD2_IMM(0)) +#define CC_LDRD_rRI(cc,Rd,Rn,i) _LS2(cc,1,0,1,0,Rd,Rn,ADD2_IMM(i)) +#define CC_LDRD_rRi(cc,Rd,Rn,i) _LS2(cc,1,0,1,0,Rd,Rn,SUB2_IMM(i)) +#define CC_LDRD_rRR(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,0,Rd,Rn,ADD2_REG(Rm)) +#define CC_LDRD_rRr(cc,Rd,Rn,Rm) _LS2(cc,1,0,1,0,Rd,Rn,SUB2_REG(Rm)) + +#define LDRD_rR(Rd,Rn) CC_LDRD_rR(NATIVE_CC_AL,Rd,Rn) +#define LDRD_rRI(Rd,Rn,i) CC_LDRD_rRI(NATIVE_CC_AL,Rd,Rn,i) +#define LDRD_rRi(Rd,Rn,i) CC_LDRD_rRi(NATIVE_CC_AL,Rd,Rn,i) +#define LDRD_rRR(Rd,Rn,Rm) CC_LDRD_rRR(NATIVE_CC_AL,Rd,Rn,Rm) +#define LDRD_rRr(Rd,Rn,Rm) CC_LDRD_rRr(NATIVE_CC_AL,Rd,Rn,Rm) + +/* Multiply */ +#define CC_SMULL_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x0C << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define SMULL_rrrr(RdLo,RdHi,Rm,Rs) CC_SMULL_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) +#define CC_SMULLS_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x0D << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define SMULLS_rrrr(RdLo,RdHi,Rm,Rs) CC_SMULLS_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) +#define CC_MUL_rrr(cc, Rd, Rm, Rs) _W(((cc) << 28) | (0x00 << 20) | ((Rd) << 16) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define MUL_rrr(Rd, Rm, Rs) CC_MUL_rrr(NATIVE_CC_AL, Rd, Rm, Rs) +#define CC_MULS_rrr(cc, Rd, Rm, Rs) _W(((cc) << 28) | (0x01 << 20) | ((Rd) << 16) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define MULS_rrr(Rd, Rm, Rs) CC_MULS_rrr(NATIVE_CC_AL, Rd, Rm, Rs) + +#define CC_UMULL_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x08 << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define UMULL_rrrr(RdLo,RdHi,Rm,Rs) CC_UMULL_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) +#define CC_UMULLS_rrrr(cc, RdLo, RdHi, Rm, Rs) _W(((cc) << 28) | (0x09 << 20) | ((RdHi) << 16) | ((RdLo) << 12) | ((Rs) << 8) | (0x9 << 4) | (Rm)) +#define UMULLS_rrrr(RdLo,RdHi,Rm,Rs) CC_UMULLS_rrrr(NATIVE_CC_AL,RdLo,RdHi,Rm,Rs) + +/* Others */ +#define CC_CLZ_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x16 << 20) | (0xf << 16) | ((Rd) << 12) | (0xf << 8) | (0x1 << 4) | SHIFT_REG(Rm)) +#define CLZ_rr(Rd,Rm) CC_CLZ_rr(NATIVE_CC_AL,Rd,Rm) + +/* Alias */ +#define LSL_rri(Rd,Rm,i) MOV_rrLSLi(Rd,Rm,i) +#define LSL_rrr(Rd,Rm,Rs) MOV_rrLSLr(Rd,Rm,Rs) +#define LSR_rri(Rd,Rm,i) MOV_rrLSRi(Rd,Rm,i) +#define LSR_rrr(Rd,Rm,Rs) MOV_rrLSRr(Rd,Rm,Rs) +#define ASR_rri(Rd,Rm,i) MOV_rrASRi(Rd,Rm,i) +#define ASR_rrr(Rd,Rm,Rs) MOV_rrASRr(Rd,Rm,Rs) +#define ROR_rri(Rd,Rm,i) MOV_rrRORi(Rd,Rm,i) +#define ROR_rrr(Rd,Rm,Rs) MOV_rrRORr(Rd,Rm,Rs) +#define RRX_rr(Rd,Rm) MOV_rrRRX(Rd,Rm) +#define LSLS_rri(Rd,Rm,i) MOVS_rrLSLi(Rd,Rm,i) +#define LSLS_rrr(Rd,Rm,Rs) MOVS_rrLSLr(Rd,Rm,Rs) +#define LSRS_rri(Rd,Rm,i) MOVS_rrLSRi(Rd,Rm,i) +#define LSRS_rrr(Rd,Rm,Rs) MOVS_rrLSRr(Rd,Rm,Rs) +#define ASRS_rri(Rd,Rm,i) MOVS_rrASRi(Rd,Rm,i) +#define ASRS_rrr(Rd,Rm,Rs) MOVS_rrASRr(Rd,Rm,Rs) +#define RORS_rri(Rd,Rm,i) MOVS_rrRORi(Rd,Rm,i) +#define RORS_rrr(Rd,Rm,Rs) MOVS_rrRORr(Rd,Rm,Rs) +#define RRXS_rr(Rd,Rm) MOVS_rrRRX(Rd,Rm) + +/* ARMV6 ops */ +#define CC_SXTB_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr(Rd,Rm) CC_SXTB_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTB_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr_ROR8(Rd,Rm) CC_SXTB_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTB_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr_ROR16(Rd,Rm) CC_SXTB_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTB_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6a << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTB_rr_ROR24(Rd,Rm) CC_SXTB_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr(Rd,Rm) CC_SXTH_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr_ROR8(Rd,Rm) CC_SXTH_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr_ROR16(Rd,Rm) CC_SXTH_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_SXTH_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define SXTH_rr_ROR24(Rd,Rm) CC_SXTH_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr(Rd,Rm) CC_UXTB_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr_ROR8(Rd,Rm) CC_UXTB_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr_ROR16(Rd,Rm) CC_UXTB_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTB_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6e << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTB_rr_ROR24(Rd,Rm) CC_UXTB_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr(Rd,Rm) CC_UXTH_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr_ROR8(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (1 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr_ROR8(Rd,Rm) CC_UXTH_rr_ROR8(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr_ROR16(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (2 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr_ROR16(Rd,Rm) CC_UXTH_rr_ROR16(NATIVE_CC_AL,Rd,Rm) + +#define CC_UXTH_rr_ROR24(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | ((Rd) << 12) | (3 << 10) | (0x7 << 4) | SHIFT_REG(Rm)) +#define UXTH_rr_ROR24(Rd,Rm) CC_UXTH_rr_ROR24(NATIVE_CC_AL,Rd,Rm) + +#define CC_REV_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | (0xf << 8) | ((Rd) << 12) | (0x3 << 4) | SHIFT_REG(Rm)) +#define REV_rr(Rd,Rm) CC_REV_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_REV16_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6b << 20) | (0xf << 16) | (0xf << 8) | ((Rd) << 12) | (0xB << 4) | SHIFT_REG(Rm)) +#define REV16_rr(Rd,Rm) CC_REV16_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_REVSH_rr(cc,Rd,Rm) _W(((cc) << 28) | (0x6f << 20) | (0xf << 16) | (0xf << 8) | ((Rd) << 12) | (0xB << 4) | SHIFT_REG(Rm)) +#define REVSH_rr(Rd,Rm) CC_REVSH_rr(NATIVE_CC_AL,Rd,Rm) + +#define CC_PKHBT_rrr(cc,Rd,Rn,Rm) _W(((cc) << 28) | (0x68 << 20) | (Rn << 16) | (Rd << 12) | (0x1 << 4) | (Rm)) +#define CC_PKHBT_rrrLSLi(cc,Rd,Rn,Rm,s) _W(((cc) << 28) | (0x68 << 20) | (Rn << 16) | (Rd << 12) | (0x1 << 4) | SHIFT_PK(Rm, s)) +#define PKHBT_rrr(Rd,Rn,Rm) CC_PKHBT_rrr(NATIVE_CC_AL,Rd,Rn,Rm) +#define PKHBT_rrrLSLi(Rd,Rn,Rm,s) CC_PKHBT_rrrLSLi(NATIVE_CC_AL,Rd,Rn,Rm,s) + +#define CC_PKHTB_rrrASRi(cc,Rd,Rn,Rm,s) _W(((cc) << 28) | (0x68 << 20) | (Rn << 16) | (Rd << 12) | (0x5 << 4) | SHIFT_PK(Rm, s)) +#define PKHTB_rrrASRi(Rd,Rn,Rm,s) CC_PKHTB_rrrASRi(NATIVE_CC_AL,Rd,Rn,Rm,s) + +#endif /* ARM_RTASM_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp new file mode 100644 index 00000000..32e6982a --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp @@ -0,0 +1,5372 @@ +/* + * compiler/codegen_x86.cpp - IA-32 and AMD64 code generator + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> IA-32 and AMD64 + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This should eventually end up in machdep/, but for now, x86 is the + only target, and it's easier this way... */ + +#include "flags_x86.h" + +/************************************************************************* + * Some basic information about the the target CPU * + *************************************************************************/ + +#define R1 RR1 +#define R2 RR2 +#define R4 RR4 + +#define EAX_INDEX 0 +#define ECX_INDEX 1 +#define EDX_INDEX 2 +#define EBX_INDEX 3 +#define ESP_INDEX 4 +#define EBP_INDEX 5 +#define ESI_INDEX 6 +#define EDI_INDEX 7 +#if defined(CPU_x86_64) +#define R8_INDEX 8 +#define R9_INDEX 9 +#define R10_INDEX 10 +#define R11_INDEX 11 +#define R12_INDEX 12 +#define R13_INDEX 13 +#define R14_INDEX 14 +#define R15_INDEX 15 +#endif +/* XXX this has to match X86_Reg8H_Base + 4 */ +#define AH_INDEX (0x10+4+EAX_INDEX) +#define CH_INDEX (0x10+4+ECX_INDEX) +#define DH_INDEX (0x10+4+EDX_INDEX) +#define BH_INDEX (0x10+4+EBX_INDEX) + +/* The register in which subroutines return an integer return value */ +#define REG_RESULT EAX_INDEX + +/* The registers subroutines take their first and second argument in */ +#ifdef _WIN32 +/* Handle the _fastcall parameters of ECX and EDX */ +#define REG_PAR1 ECX_INDEX +#define REG_PAR2 EDX_INDEX +#elif defined(CPU_x86_64) +#define REG_PAR1 EDI_INDEX +#define REG_PAR2 ESI_INDEX +#else +#define REG_PAR1 EAX_INDEX +#define REG_PAR2 EDX_INDEX +#endif + +#define REG_PC_PRE EAX_INDEX /* The register we use for preloading regs.pc_p */ +#ifdef _WIN32 +#define REG_PC_TMP ECX_INDEX +#else +#define REG_PC_TMP ECX_INDEX /* Another register that is not the above */ +#endif + +#define SHIFTCOUNT_NREG ECX_INDEX /* Register that can be used for shiftcount. + -1 if any reg will do */ +#define MUL_NREG1 EAX_INDEX /* %eax will hold the low 32 bits after a 32x32 mul */ +#define MUL_NREG2 EDX_INDEX /* %edx will hold the high 32 bits */ + +#define STACK_ALIGN 16 +#define STACK_OFFSET sizeof(void *) +#ifdef _WIN64 +/* In the Microsoft x64 calling convention, it's the caller's responsibility + * to allocate 32 bytes of "shadow space" on the stack right before calling + * the function (regardless of the actual number of parameters used). */ +#define STACK_SHADOW_SPACE 32 +#else +#define STACK_SHADOW_SPACE 0 +#endif + +#if defined(CPU_x86_64) +#ifdef UAE +uae_s8 always_used[] = { ESP_INDEX, R12_INDEX, -1 }; +#else +uae_s8 always_used[] = { ESP_INDEX, -1 }; +#endif +uae_s8 can_byte[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; +uae_s8 can_word[]={0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,-1}; +#else +uae_s8 always_used[] = { ESP_INDEX, -1 }; +uae_s8 can_byte[]={0,1,2,3,-1}; +uae_s8 can_word[]={0,1,2,3,5,6,7,-1}; +#endif +static bool have_lahf_lm = true; // target has LAHF supported in long mode ? + +#if USE_OPTIMIZED_CALLS +/* Make sure interpretive core does not use cpuopti */ +uae_u8 call_saved[]={0,0,0,1,1,1,1,1}; +#error FIXME: code not ready +#else +/* cpuopti mutate instruction handlers to assume registers are saved + by the caller */ +uae_u8 call_saved[]={0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}; +#endif + +/* This *should* be the same as call_saved. But: + - We might not really know which registers are saved, and which aren't, + so we need to preserve some, but don't want to rely on everyone else + also saving those registers + - Special registers (such like the stack pointer) should not be "preserved" + by pushing, even though they are "saved" across function calls +*/ +#if defined(CPU_x86_64) +#ifdef _WIN64 +/* https://msdn.microsoft.com/en-us/library/6t169e9c.aspx: + * "The registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are + * considered nonvolatile and must be saved and restored by a function that + * uses them". Also saving r11 for now (see comment below). */ +static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1,0,0,0,1,1,1,1,1}; +#else +/* callee-saved registers as defined by Linux AMD64 ABI: rbx, rbp, rsp, r12 - r15 */ +/* preserve r11 because it's generally used to hold pointers to functions */ +/* FIXME: not really sure what the point of saving r11 is (??). If functions + * cannot assume calle preserves it, it will not be used across calls anyway? */ +static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,0,0,0,0,0,1,1,1,1,1}; +#endif +#else +/* callee-saved registers as defined by System V IA-32 ABI: edi, esi, ebx, ebp */ +static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1}; +#endif + +/* Whether classes of instructions do or don't clobber the native flags */ +#define CLOBBER_MOV +#define CLOBBER_LEA +#define CLOBBER_CMOV +#define CLOBBER_POP +#define CLOBBER_PUSH +#define CLOBBER_SUB clobber_flags() +#define CLOBBER_SBB clobber_flags() +#define CLOBBER_CMP clobber_flags() +#define CLOBBER_ADD clobber_flags() +#define CLOBBER_ADC clobber_flags() +#define CLOBBER_AND clobber_flags() +#define CLOBBER_OR clobber_flags() +#define CLOBBER_XOR clobber_flags() + +#define CLOBBER_ROL clobber_flags() +#define CLOBBER_ROR clobber_flags() +#define CLOBBER_SHLL clobber_flags() +#define CLOBBER_SHRL clobber_flags() +#define CLOBBER_SHRA clobber_flags() +#define CLOBBER_TEST clobber_flags() +#define CLOBBER_CL16 +#define CLOBBER_CL8 +#define CLOBBER_SE32 +#define CLOBBER_SE16 +#define CLOBBER_SE8 +#define CLOBBER_ZE32 +#define CLOBBER_ZE16 +#define CLOBBER_ZE8 +#define CLOBBER_SW16 clobber_flags() +#define CLOBBER_SW32 +#define CLOBBER_SETCC +#define CLOBBER_MUL clobber_flags() +#define CLOBBER_BT clobber_flags() +#define CLOBBER_BSF clobber_flags() + +/* The older code generator is now deprecated. */ +#define USE_NEW_RTASM 1 + +#if USE_NEW_RTASM + +#if defined(CPU_x86_64) +#define X86_TARGET_64BIT 1 +/* The address override prefix causes a 5 cycles penalty on Intel Core + processors. Another solution would be to decompose the load in an LEA, + MOV (to zero-extend), MOV (from memory): is it better? */ +#define ADDR32 x86_emit_byte(0x67), +#else +#define ADDR32 +#endif +#define X86_FLAT_REGISTERS 0 +#define X86_OPTIMIZE_ALU 1 +#define X86_OPTIMIZE_ROTSHI 1 +#include "codegen_x86.h" + +#define x86_emit_byte(B) emit_byte(B) +#define x86_emit_word(W) emit_word(W) +#define x86_emit_long(L) emit_long(L) +#define x86_emit_quad(Q) emit_quad(Q) +#define x86_get_target() get_target() +#define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__) + +static inline void x86_64_addr32(void) +{ +#ifdef CPU_x86_64 + emit_byte(0x67); +#endif +} + +static inline void x86_64_rex(bool /* w */, uae_u32 * /* r */, uae_u32 * /* x */, uae_u32 *b) +{ +#ifdef CPU_x86_64 + int rex_byte = 0x40; + if (*b >= R8_INDEX) { + *b -= R8_INDEX; + rex_byte |= 1; + } + if (rex_byte != 0x40) { + emit_byte(rex_byte); + } +#else + UNUSED(b); +#endif +} + +static inline void x86_64_prefix( + bool addr32, bool w, uae_u32 *r, uae_u32 *x, uae_u32 *b) +{ + if (addr32) { + x86_64_addr32(); + } + x86_64_rex(w, r, x, b); +} + +// Some mappings to mark compemu_support calls as only used by compemu +// These are still mainly x86 minded. Should be more CPU independent in the future +#define compemu_raw_add_l_mi(a,b) raw_add_l_mi(a,b) +#define compemu_raw_and_l_ri(a,b) raw_and_l_ri(a,b) +#define compemu_raw_bswap_32(a) raw_bswap_32(a) +#define compemu_raw_bt_l_ri(a,b) raw_bt_l_ri(a,b) +#define compemu_raw_call(a) raw_call(a) +#define compemu_raw_cmov_l_rm_indexed(a,b,c,d,e) raw_cmov_l_rm_indexed(a,b,c,d,e) +#define compemu_raw_cmp_l_mi(a,b) raw_cmp_l_mi(a,b) +#define compemu_raw_cmp_l_mi8(a,b) raw_cmp_l_mi(a,b) +#define compemu_raw_jcc_b_oponly(a) raw_jcc_b_oponly(a) +#define compemu_raw_jcc_l_oponly(a) raw_jcc_l_oponly(a) +#define compemu_raw_jl(a) raw_jl(a) +#define compemu_raw_jmp(a) raw_jmp(a) +#define compemu_raw_jmp_m_indexed(a,b,c) raw_jmp_m_indexed(a,b,c) +#define compemu_raw_jmp_r(a) raw_jmp_r(a) +#define compemu_raw_jnz(a) raw_jnz(a) +#define compemu_raw_jz_b_oponly() raw_jz_b_oponly() +#define compemu_raw_lea_l_brr(a,b,c) raw_lea_l_brr(a,b,c) +#define compemu_raw_lea_l_brr_indexed(a,b,c,d,e) raw_lea_l_brr_indexed(a,b,c,d,e) +#define compemu_raw_mov_b_mr(a,b) raw_mov_b_mr(a,b) +#define compemu_raw_mov_l_mi(a,b) raw_mov_l_mi(a,b) +#define compemu_raw_mov_l_mr(a,b) raw_mov_l_mr(a,b) +#define compemu_raw_mov_l_ri(a,b) raw_mov_l_ri(a,b) +#define compemu_raw_mov_l_rm(a,b) raw_mov_l_rm(a,b) +#define compemu_raw_mov_l_rr(a,b) raw_mov_l_rr(a,b) +#define compemu_raw_mov_w_mr(a,b) raw_mov_w_mr(a,b) +#define compemu_raw_sub_l_mi(a,b) raw_sub_l_mi(a,b) +#define compemu_raw_test_l_rr(a,b) raw_test_l_rr(a,b) +#define compemu_raw_zero_extend_16_rr(a,b) raw_zero_extend_16_rr(a,b) +#define compemu_raw_lea_l_rr_indexed(a,b,c,d) raw_lea_l_rr_indexed(a,b,c,d) + +static void jit_fail(const char *msg, const char *file, int line, const char *function) +{ + jit_abort("failure in function %s from file %s at line %d: %s", + function, file, line, msg); +} + +LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) +{ +#if defined(CPU_x86_64) + PUSHQr(r); +#else + PUSHLr(r); +#endif +} +LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) + +LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) +{ +#if defined(CPU_x86_64) + POPQr(r); +#else + POPLr(r); +#endif +} +LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) + +LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) +{ +#if defined(CPU_x86_64) + POPQm(d, X86_NOREG, X86_NOREG, 1); +#else + POPLm(d, X86_NOREG, X86_NOREG, 1); +#endif +} +LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) + +LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) +{ + BTLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) +{ + BTLrr(b, r); +} +LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) +{ + BTCLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) +{ + BTCLrr(b, r); +} +LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) +{ + BTRLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) +{ + BTRLrr(b, r); +} +LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) +{ + BTSLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) +{ + BTSLrr(b, r); +} +LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) +{ + SUBWir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) + +LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) +{ + ADDR32 MOVLmr(s, X86_NOREG, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) +{ + ADDR32 MOVLim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) +{ + ADDR32 MOVWim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) +{ + ADDR32 MOVBim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) +{ + ADDR32 ROLBim(i, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) +{ + ROLBir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) +{ + ROLWir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) +{ + ROLLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) +{ + ROLLrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) +{ + ROLWrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) +{ + ROLBrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) +{ + SHLLrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) +{ + SHLWrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) +{ + SHLBrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) +{ + RORBir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) +{ + RORWir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) +{ + ADDR32 ORLmr(s, X86_NOREG, X86_NOREG, 1, d); +} +LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) + +LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) +{ + RORLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) +{ + RORLrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) +{ + RORWrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) +{ + RORBrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) +{ + SHRLrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) +{ + SHRWrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) +{ + SHRBrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) +{ + SARLrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) +{ + SARWrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) +{ + SARBrr(r, d); +} +LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) +{ + SHLLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) +{ + SHLWir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) +{ + SHLBir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) +{ + SHRLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) +{ + SHRWir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) +{ + SHRBir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) +{ + SARLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) +{ + SARWir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) +{ + SARBir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,1,raw_sahf,(R2)) +{ + SAHF(); +} +LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) + +LOWFUNC(NONE,NONE,1,raw_cpuid,(R4)) +{ + CPUID(); +} +LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) + +LOWFUNC(READ,NONE,1,raw_lahf,(W2)) +{ + LAHF(); +} +LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) + +LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) +{ + SETCCir(cc, d); +} +LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) + +LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) +{ + ADDR32 SETCCim(cc, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) + +LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) +{ + if (have_cmov) + CMOVLrr(cc, s, d); + else { /* replacement using branch and mov */ + uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1; + JCCSii(cc^1, 0); + MOVLrr(s, d); + *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); + } +} +LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) + +LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) +{ + BSFLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) +{ + MOVSLQrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) +{ + MOVSWLrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) +{ + MOVSBLrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) + +LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) +{ + MOVZWLrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) + +LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) +{ + MOVZBLrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) + +LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) +{ + IMULLrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) +{ + if (d!=MUL_NREG1 || s!=MUL_NREG2) { + jit_abort("Bad register in IMUL: d=%d, s=%d",d,s); + } + IMULLr(s); +} +LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) + +LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) +{ + if (d!=MUL_NREG1 || s!=MUL_NREG2) { + jit_abort("Bad register in MUL: d=%d, s=%d",d,s); + } + MULLr(s); +} +LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) + +LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4, R4)) +{ + abort(); /* %^$&%^$%#^ x86! */ +} +LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) +{ + MOVBrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) + +LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) +{ + MOVWrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) + +LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) +{ + ADDR32 MOVLmr(0, baser, index, factor, d); +} +LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) +{ + ADDR32 MOVWmr(0, baser, index, factor, d); +} +LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) +{ + ADDR32 MOVBmr(0, baser, index, factor, d); +} +LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) +{ + ADDR32 MOVLrm(s, 0, baser, index, factor); +} +LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) + +LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) +{ + ADDR32 MOVWrm(s, 0, baser, index, factor); +} +LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) + +LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) +{ + ADDR32 MOVBrm(s, 0, baser, index, factor); +} +LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) + +LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) +{ + ADDR32 MOVLrm(s, base, baser, index, factor); +} +LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) + +LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) +{ + ADDR32 MOVWrm(s, base, baser, index, factor); +} +LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) + +LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) +{ + ADDR32 MOVBrm(s, base, baser, index, factor); +} +LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) + +LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) +{ + ADDR32 MOVLmr(base, baser, index, factor, d); +} +LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) +{ + ADDR32 MOVWmr(base, baser, index, factor, d); +} +LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) +{ + ADDR32 MOVBmr(base, baser, index, factor, d); +} +LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) +{ + ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); +} +LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) +{ + if (have_cmov) + ADDR32 CMOVLmr(cond, base, X86_NOREG, index, factor, d); + else { /* replacement using branch and mov */ + uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1; + JCCSii(cond^1, 0); + ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); + *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); + } +} +LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) + +LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) +{ + if (have_cmov) + CMOVLmr(cond, mem, X86_NOREG, X86_NOREG, 1, d); + else { /* replacement using branch and mov */ + uae_s8 *target_p = (uae_s8 *)x86_get_target() + 1; + JCCSii(cond^1, 0); + ADDR32 MOVLmr(mem, X86_NOREG, X86_NOREG, 1, d); + *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); + } +} +LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) + +LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) +{ + ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) +{ + ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) +{ + ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) +{ + ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) +{ + ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) +{ + ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) +{ + ADDR32 MOVLim(i, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) +{ + ADDR32 MOVWim(i, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) +{ + ADDR32 MOVBim(i, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) +{ + ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) +{ + ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) +{ + ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) + +LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) +{ + ADDR32 LEALmr(offset, s, X86_NOREG, 1, d); +} +LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) +{ + ADDR32 LEALmr(offset, s, index, factor, d); +} +LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) + +LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) +{ + ADDR32 LEALmr(0, s, index, factor, d); +} +LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) + +LOWFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) +{ + ADDR32 LEALmr(0, X86_NOREG, index, factor, d); +} +LENDFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) +{ + ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) +{ + ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) +{ + ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) + +LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) +{ + BSWAPLr(r); +} +LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) + +LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) +{ + ROLWir(8, r); +} +LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) + +LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) +{ + MOVLrr(s, d); +} +LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) +{ + ADDR32 MOVLrm(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) +{ + ADDR32 MOVWrm(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) + +LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) +{ + ADDR32 MOVWmr(s, X86_NOREG, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) +{ + ADDR32 MOVBrm(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) + +LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) +{ + ADDR32 MOVBmr(s, X86_NOREG, X86_NOREG, 1, d); +} +LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) +{ + MOVLir(s, d); +} +LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) +{ + MOVWir(s, d); +} +LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) +{ + MOVBir(s, d); +} +LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) + +LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) +{ + ADDR32 ADCLim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) +{ + ADDR32 ADDLim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) +{ + ADDR32 ADDWim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) +{ + ADDR32 ADDBim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) +{ + TESTLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) +{ + TESTLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) +{ + TESTWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) +{ + TESTBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) +{ + XORLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) +{ + ANDLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) +{ + ANDWir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) +{ + ANDLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) +{ + ANDWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) +{ + ANDBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) +{ + ORLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) +{ + ORLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) +{ + ORWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) +{ + ORBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) +{ + ADCLrr(s, d); +} +LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) +{ + ADCWrr(s, d); +} +LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) +{ + ADCBrr(s, d); +} +LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) +{ + ADDLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) +{ + ADDWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) +{ + ADDBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) +{ + SUBLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) +{ + SUBBir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) +{ + ADDLir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) +{ + ADDWir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) +{ + ADDBir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) + +LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) +{ + SBBLrr(s, d); +} +LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) + +LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) +{ + SBBWrr(s, d); +} +LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) + +LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) +{ + SBBBrr(s, d); +} +LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) +{ + SUBLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) +{ + SUBWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) +{ + SUBBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) +{ + CMPLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) +{ + CMPLir(i, r); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) +{ + CMPWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) + +LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) +{ + ADDR32 CMPBim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) +{ + CMPBir(i, d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) +{ + CMPBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) + +LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) +{ + ADDR32 CMPLmr(offset, X86_NOREG, index, factor, d); +} +LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) + +LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) +{ + XORLrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) +{ + XORWrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) +{ + XORBrr(s, d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) +{ + ADDR32 SUBLim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) + +LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) +{ + ADDR32 CMPLim(s, d, X86_NOREG, X86_NOREG, 1); +} +LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) +{ + XCHGLrr(r2, r1); +} +LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) + +LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) +{ + XCHGBrr(r2, r1); +} +LENDFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) + +LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) +{ + PUSHF(); +} +LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) + +LOWFUNC(WRITE,READ,0,raw_popfl,(void)) +{ + POPF(); +} +LENDFUNC(WRITE,READ,0,raw_popfl,(void)) + +/* Generate floating-point instructions */ +static inline void x86_fadd_m(MEMR s) +{ + ADDR32 FADDLm(s,X86_NOREG,X86_NOREG,1); +} + +#else + +const bool optimize_accum = true; +const bool optimize_imm8 = true; +const bool optimize_shift_once = true; + +/************************************************************************* + * Actual encoding of the instructions on the target CPU * + *************************************************************************/ + +static inline int isaccum(int r) +{ + return (r == EAX_INDEX); +} + +static inline int isbyte(uae_s32 x) +{ + return (x>=-128 && x<=127); +} + +static inline int isword(uae_s32 x) +{ + return (x>=-32768 && x<=32767); +} + +LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) +{ + emit_byte(0x50+r); +} +LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) + +LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) +{ + emit_byte(0x58+r); +} +LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) + +LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) +{ + emit_byte(0x8f); + emit_byte(0x05); + emit_long(d); +} +LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) + +LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) +{ + emit_byte(0x0f); + emit_byte(0xba); + emit_byte(0xe0+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) +{ + emit_byte(0x0f); + emit_byte(0xa3); + emit_byte(0xc0+8*b+r); +} +LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) +{ + emit_byte(0x0f); + emit_byte(0xba); + emit_byte(0xf8+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) +{ + emit_byte(0x0f); + emit_byte(0xbb); + emit_byte(0xc0+8*b+r); +} +LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) + + +LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) +{ + emit_byte(0x0f); + emit_byte(0xba); + emit_byte(0xf0+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) +{ + emit_byte(0x0f); + emit_byte(0xb3); + emit_byte(0xc0+8*b+r); +} +LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) +{ + emit_byte(0x0f); + emit_byte(0xba); + emit_byte(0xe8+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) +{ + emit_byte(0x0f); + emit_byte(0xab); + emit_byte(0xc0+8*b+r); +} +LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) + +LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) +{ + emit_byte(0x66); + if (isbyte(i)) { + emit_byte(0x83); + emit_byte(0xe8+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x2d); + else { + emit_byte(0x81); + emit_byte(0xe8+d); + } + emit_word(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) + + +LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) +{ + emit_byte(0x8b); + emit_byte(0x05+8*d); + emit_long(s); +} +LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) +{ + emit_byte(0xc7); + emit_byte(0x05); + emit_long(d); + emit_long(s); +} +LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) +{ + emit_byte(0x66); + emit_byte(0xc7); + emit_byte(0x05); + emit_long(d); + emit_word(s); +} +LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) +{ + emit_byte(0xc6); + emit_byte(0x05); + emit_long(d); + emit_byte(s); +} +LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd0); + emit_byte(0x05); + emit_long(d); + } + else { + emit_byte(0xc0); + emit_byte(0x05); + emit_long(d); + emit_byte(i); + } +} +LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd0); + emit_byte(0xc0+r); + } + else { + emit_byte(0xc0); + emit_byte(0xc0+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) +{ + emit_byte(0x66); + emit_byte(0xc1); + emit_byte(0xc0+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd1); + emit_byte(0xc0+r); + } + else { + emit_byte(0xc1); + emit_byte(0xc0+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) +{ + emit_byte(0xd3); + emit_byte(0xc0+d); +} +LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) +{ + emit_byte(0x66); + emit_byte(0xd3); + emit_byte(0xc0+d); +} +LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) +{ + emit_byte(0xd2); + emit_byte(0xc0+d); +} +LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) +{ + emit_byte(0xd3); + emit_byte(0xe0+d); +} +LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) +{ + emit_byte(0x66); + emit_byte(0xd3); + emit_byte(0xe0+d); +} +LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) +{ + emit_byte(0xd2); + emit_byte(0xe0+d); +} +LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd0); + emit_byte(0xc8+r); + } + else { + emit_byte(0xc0); + emit_byte(0xc8+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) +{ + emit_byte(0x66); + emit_byte(0xc1); + emit_byte(0xc8+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) + +// gb-- used for making an fpcr value in compemu_fpp.cpp +LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) +{ + emit_byte(0x0b); + emit_byte(0x05+8*d); + emit_long(s); +} +LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) + +LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd1); + emit_byte(0xc8+r); + } + else { + emit_byte(0xc1); + emit_byte(0xc8+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) +{ + emit_byte(0xd3); + emit_byte(0xc8+d); +} +LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) +{ + emit_byte(0x66); + emit_byte(0xd3); + emit_byte(0xc8+d); +} +LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) +{ + emit_byte(0xd2); + emit_byte(0xc8+d); +} +LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) +{ + emit_byte(0xd3); + emit_byte(0xe8+d); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) +{ + emit_byte(0x66); + emit_byte(0xd3); + emit_byte(0xe8+d); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) +{ + emit_byte(0xd2); + emit_byte(0xe8+d); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) +{ + emit_byte(0xd3); + emit_byte(0xf8+d); +} +LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) +{ + emit_byte(0x66); + emit_byte(0xd3); + emit_byte(0xf8+d); +} +LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) +{ + emit_byte(0xd2); + emit_byte(0xf8+d); +} +LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) + +LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd1); + emit_byte(0xe0+r); + } + else { + emit_byte(0xc1); + emit_byte(0xe0+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) +{ + emit_byte(0x66); + emit_byte(0xc1); + emit_byte(0xe0+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd0); + emit_byte(0xe0+r); + } + else { + emit_byte(0xc0); + emit_byte(0xe0+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd1); + emit_byte(0xe8+r); + } + else { + emit_byte(0xc1); + emit_byte(0xe8+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) +{ + emit_byte(0x66); + emit_byte(0xc1); + emit_byte(0xe8+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd0); + emit_byte(0xe8+r); + } + else { + emit_byte(0xc0); + emit_byte(0xe8+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd1); + emit_byte(0xf8+r); + } + else { + emit_byte(0xc1); + emit_byte(0xf8+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) +{ + emit_byte(0x66); + emit_byte(0xc1); + emit_byte(0xf8+r); + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) +{ + if (optimize_shift_once && (i == 1)) { + emit_byte(0xd0); + emit_byte(0xf8+r); + } + else { + emit_byte(0xc0); + emit_byte(0xf8+r); + emit_byte(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) + +LOWFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) +{ + emit_byte(0x9e); +} +LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) + +LOWFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) +{ + emit_byte(0x0f); + emit_byte(0xa2); +} +LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) + +LOWFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) +{ + emit_byte(0x9f); +} +LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) + +LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) +{ + emit_byte(0x0f); + emit_byte(0x90+cc); + emit_byte(0xc0+d); +} +LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) + +LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) +{ + emit_byte(0x0f); + emit_byte(0x90+cc); + emit_byte(0x05); + emit_long(d); +} +LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) + +LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) +{ + if (have_cmov) { + emit_byte(0x0f); + emit_byte(0x40+cc); + emit_byte(0xc0+8*d+s); + } + else { /* replacement using branch and mov */ + int uncc=(cc^1); + emit_byte(0x70+uncc); + emit_byte(2); /* skip next 2 bytes if not cc=true */ + emit_byte(0x89); + emit_byte(0xc0+8*s+d); + } +} +LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) + +LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) +{ + emit_byte(0x0f); + emit_byte(0xbc); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) +{ + emit_byte(0x0f); + emit_byte(0xbf); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) + +LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) +{ + emit_byte(0x0f); + emit_byte(0xbe); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) + +LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) +{ + emit_byte(0x0f); + emit_byte(0xb7); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) + +LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) +{ + emit_byte(0x0f); + emit_byte(0xb6); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) + +LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) +{ + emit_byte(0x0f); + emit_byte(0xaf); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) +{ + if (d!=MUL_NREG1 || s!=MUL_NREG2) { + jit_abort("Bad register in IMUL: d=%d, s=%d\n",d,s); + } + emit_byte(0xf7); + emit_byte(0xea); +} +LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) + +LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) +{ + if (d!=MUL_NREG1 || s!=MUL_NREG2) { + jit_abort("Bad register in MUL: d=%d, s=%d",d,s); + } + emit_byte(0xf7); + emit_byte(0xe2); +} +LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) + +LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) +{ + jit_abort("unsupported MUL"); /* %^$&%^$%#^ x86! */ + emit_byte(0x0f); + emit_byte(0xaf); + emit_byte(0xc0+8*d+s); +} +LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) + +LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) +{ + emit_byte(0x88); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) + +LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x89); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) + +LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) +{ + int isebp=(baser==5)?0x40:0; + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + + emit_byte(0x8b); + emit_byte(0x04+8*d+isebp); + emit_byte(baser+8*index+0x40*fi); + if (isebp) + emit_byte(0x00); +} +LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) +{ + int fi; + int isebp; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + isebp=(baser==5)?0x40:0; + + emit_byte(0x66); + emit_byte(0x8b); + emit_byte(0x04+8*d+isebp); + emit_byte(baser+8*index+0x40*fi); + if (isebp) + emit_byte(0x00); +} +LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) +{ + int fi; + int isebp; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + isebp=(baser==5)?0x40:0; + + emit_byte(0x8a); + emit_byte(0x04+8*d+isebp); + emit_byte(baser+8*index+0x40*fi); + if (isebp) + emit_byte(0x00); +} +LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) +{ + int fi; + int isebp; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + + isebp=(baser==5)?0x40:0; + + emit_byte(0x89); + emit_byte(0x04+8*s+isebp); + emit_byte(baser+8*index+0x40*fi); + if (isebp) + emit_byte(0x00); +} +LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) + +LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) +{ + int fi; + int isebp; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + isebp=(baser==5)?0x40:0; + + emit_byte(0x66); + emit_byte(0x89); + emit_byte(0x04+8*s+isebp); + emit_byte(baser+8*index+0x40*fi); + if (isebp) + emit_byte(0x00); +} +LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) + +LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) +{ + int fi; + int isebp; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + isebp=(baser==5)?0x40:0; + + emit_byte(0x88); + emit_byte(0x04+8*s+isebp); + emit_byte(baser+8*index+0x40*fi); + if (isebp) + emit_byte(0x00); +} +LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) + +LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x89); + emit_byte(0x84+8*s); + emit_byte(baser+8*index+0x40*fi); + emit_long(base); +} +LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) + +LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x66); + emit_byte(0x89); + emit_byte(0x84+8*s); + emit_byte(baser+8*index+0x40*fi); + emit_long(base); +} +LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) + +LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x88); + emit_byte(0x84+8*s); + emit_byte(baser+8*index+0x40*fi); + emit_long(base); +} +LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) + +LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x8b); + emit_byte(0x84+8*d); + emit_byte(baser+8*index+0x40*fi); + emit_long(base); +} +LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x66); + emit_byte(0x8b); + emit_byte(0x84+8*d); + emit_byte(baser+8*index+0x40*fi); + emit_long(base); +} +LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x8a); + emit_byte(0x84+8*d); + emit_byte(baser+8*index+0x40*fi); + emit_long(base); +} +LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) +{ + int fi; + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: + jit_abort("Bad factor %d in mov_l_rm_indexed!",factor); + } + emit_byte(0x8b); + emit_byte(0x04+8*d); + emit_byte(0x05+8*index+64*fi); + emit_long(base); +} +LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) + +LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) +{ + int fi; + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: + jit_abort("Bad factor %d in mov_l_rm_indexed!",factor); + } + if (have_cmov) { + emit_byte(0x0f); + emit_byte(0x40+cond); + emit_byte(0x04+8*d); + emit_byte(0x05+8*index+64*fi); + emit_long(base); + } + else { /* replacement using branch and mov */ + int uncc=(cond^1); + emit_byte(0x70+uncc); + emit_byte(7); /* skip next 7 bytes if not cc=true */ + emit_byte(0x8b); + emit_byte(0x04+8*d); + emit_byte(0x05+8*index+64*fi); + emit_long(base); + } +} +LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) + +LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) +{ + if (have_cmov) { + emit_byte(0x0f); + emit_byte(0x40+cond); + emit_byte(0x05+8*d); + emit_long(mem); + } + else { /* replacement using branch and mov */ + int uncc=(cond^1); + emit_byte(0x70+uncc); + emit_byte(6); /* skip next 6 bytes if not cc=true */ + emit_byte(0x8b); + emit_byte(0x05+8*d); + emit_long(mem); + } +} +LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) + +LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x8b); + emit_byte(0x40+8*d+s); + emit_byte(offset); +} +LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x66); + emit_byte(0x8b); + emit_byte(0x40+8*d+s); + emit_byte(offset); +} +LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x8a); + emit_byte(0x40+8*d+s); + emit_byte(offset); +} +LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) +{ + emit_byte(0x8b); + emit_byte(0x80+8*d+s); + emit_long(offset); +} +LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) +{ + emit_byte(0x66); + emit_byte(0x8b); + emit_byte(0x80+8*d+s); + emit_long(offset); +} +LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) + +LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) +{ + emit_byte(0x8a); + emit_byte(0x80+8*d+s); + emit_long(offset); +} +LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0xc7); + emit_byte(0x40+d); + emit_byte(offset); + emit_long(i); +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x66); + emit_byte(0xc7); + emit_byte(0x40+d); + emit_byte(offset); + emit_word(i); +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0xc6); + emit_byte(0x40+d); + emit_byte(offset); + emit_byte(i); +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x89); + emit_byte(0x40+8*s+d); + emit_byte(offset); +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x66); + emit_byte(0x89); + emit_byte(0x40+8*s+d); + emit_byte(offset); +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) +{ + Dif(!isbyte(offset)) abort(); + emit_byte(0x88); + emit_byte(0x40+8*s+d); + emit_byte(offset); +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) + +LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) +{ + if (optimize_imm8 && isbyte(offset)) { + emit_byte(0x8d); + emit_byte(0x40+8*d+s); + emit_byte(offset); + } + else { + emit_byte(0x8d); + emit_byte(0x80+8*d+s); + emit_long(offset); + } +} +LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + if (optimize_imm8 && isbyte(offset)) { + emit_byte(0x8d); + emit_byte(0x44+8*d); + emit_byte(0x40*fi+8*index+s); + emit_byte(offset); + } + else { + emit_byte(0x8d); + emit_byte(0x84+8*d); + emit_byte(0x40*fi+8*index+s); + emit_long(offset); + } +} +LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) + +LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) +{ + int isebp=(s==5)?0x40:0; + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + + emit_byte(0x8d); + emit_byte(0x04+8*d+isebp); + emit_byte(0x40*fi+8*index+s); + if (isebp) + emit_byte(0); +} +LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) + +LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) +{ + if (optimize_imm8 && isbyte(offset)) { + emit_byte(0x89); + emit_byte(0x40+8*s+d); + emit_byte(offset); + } + else { + emit_byte(0x89); + emit_byte(0x80+8*s+d); + emit_long(offset); + } +} +LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) +{ + emit_byte(0x66); + emit_byte(0x89); + emit_byte(0x80+8*s+d); + emit_long(offset); +} +LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) + +LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) +{ + if (optimize_imm8 && isbyte(offset)) { + emit_byte(0x88); + emit_byte(0x40+8*s+d); + emit_byte(offset); + } + else { + emit_byte(0x88); + emit_byte(0x80+8*s+d); + emit_long(offset); + } +} +LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) + +LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) +{ + emit_byte(0x0f); + emit_byte(0xc8+r); +} +LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) + +LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) +{ + emit_byte(0x66); + emit_byte(0xc1); + emit_byte(0xc0+r); + emit_byte(0x08); +} +LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) + +LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) +{ + emit_byte(0x89); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) +{ + emit_byte(0x89); + emit_byte(0x05+8*s); + emit_long(d); +} +LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x89); + emit_byte(0x05+8*s); + emit_long(d); +} +LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) + +LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) +{ + emit_byte(0x66); + emit_byte(0x8b); + emit_byte(0x05+8*d); + emit_long(s); +} +LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) + +LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) +{ + emit_byte(0x88); + emit_byte(0x05+8*(s&0xf)); /* XXX this handles %ah case (defined as 0x10+4) and others */ + emit_long(d); +} +LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) + +LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) +{ + emit_byte(0x8a); + emit_byte(0x05+8*d); + emit_long(s); +} +LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) +{ + emit_byte(0xb8+d); + emit_long(s); +} +LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) +{ + emit_byte(0x66); + emit_byte(0xb8+d); + emit_word(s); +} +LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) +{ + emit_byte(0xb0+d); + emit_byte(s); +} +LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) + +LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) +{ + emit_byte(0x81); + emit_byte(0x15); + emit_long(d); + emit_long(s); +} +LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) +{ + if (optimize_imm8 && isbyte(s)) { + emit_byte(0x83); + emit_byte(0x05); + emit_long(d); + emit_byte(s); + } + else { + emit_byte(0x81); + emit_byte(0x05); + emit_long(d); + emit_long(s); + } +} +LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) +{ + emit_byte(0x66); + emit_byte(0x81); + emit_byte(0x05); + emit_long(d); + emit_word(s); +} +LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) +{ + emit_byte(0x80); + emit_byte(0x05); + emit_long(d); + emit_byte(s); +} +LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) + +LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) +{ + if (optimize_accum && isaccum(d)) + emit_byte(0xa9); + else { + emit_byte(0xf7); + emit_byte(0xc0+d); + } + emit_long(i); +} +LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) +{ + emit_byte(0x85); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x85); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) +{ + emit_byte(0x84); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) +{ + emit_byte(0x81); + emit_byte(0xf0+d); + emit_long(i); +} +LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) +{ + if (optimize_imm8 && isbyte(i)) { + emit_byte(0x83); + emit_byte(0xe0+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x25); + else { + emit_byte(0x81); + emit_byte(0xe0+d); + } + emit_long(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) +{ + emit_byte(0x66); + if (optimize_imm8 && isbyte(i)) { + emit_byte(0x83); + emit_byte(0xe0+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x25); + else { + emit_byte(0x81); + emit_byte(0xe0+d); + } + emit_word(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) +{ + emit_byte(0x21); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x21); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) +{ + emit_byte(0x20); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) +{ + if (optimize_imm8 && isbyte(i)) { + emit_byte(0x83); + emit_byte(0xc8+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x0d); + else { + emit_byte(0x81); + emit_byte(0xc8+d); + } + emit_long(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) +{ + emit_byte(0x09); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x09); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) +{ + emit_byte(0x08); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) +{ + emit_byte(0x11); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x11); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) + +LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) +{ + emit_byte(0x10); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) +{ + emit_byte(0x01); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x01); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) +{ + emit_byte(0x00); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) +{ + if (isbyte(i)) { + emit_byte(0x83); + emit_byte(0xe8+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x2d); + else { + emit_byte(0x81); + emit_byte(0xe8+d); + } + emit_long(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) +{ + if (optimize_accum && isaccum(d)) + emit_byte(0x2c); + else { + emit_byte(0x80); + emit_byte(0xe8+d); + } + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) +{ + if (isbyte(i)) { + emit_byte(0x83); + emit_byte(0xc0+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x05); + else { + emit_byte(0x81); + emit_byte(0xc0+d); + } + emit_long(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) +{ + emit_byte(0x66); + if (isbyte(i)) { + emit_byte(0x83); + emit_byte(0xc0+d); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(d)) + emit_byte(0x05); + else { + emit_byte(0x81); + emit_byte(0xc0+d); + } + emit_word(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) +{ + if (optimize_accum && isaccum(d)) + emit_byte(0x04); + else { + emit_byte(0x80); + emit_byte(0xc0+d); + } + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) + +LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) +{ + emit_byte(0x19); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) + +LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x19); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) + +LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) +{ + emit_byte(0x18); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) +{ + emit_byte(0x29); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x29); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) +{ + emit_byte(0x28); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) +{ + emit_byte(0x39); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) +{ + if (optimize_imm8 && isbyte(i)) { + emit_byte(0x83); + emit_byte(0xf8+r); + emit_byte(i); + } + else { + if (optimize_accum && isaccum(r)) + emit_byte(0x3d); + else { + emit_byte(0x81); + emit_byte(0xf8+r); + } + emit_long(i); + } +} +LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x39); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) + +LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) +{ + emit_byte(0x80); + emit_byte(0x3d); + emit_long(d); + emit_byte(s); +} +LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) +{ + if (optimize_accum && isaccum(d)) + emit_byte(0x3c); + else { + emit_byte(0x80); + emit_byte(0xf8+d); + } + emit_byte(i); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) + +LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) +{ + emit_byte(0x38); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) + +LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) +{ + int fi; + + switch(factor) { + case 1: fi=0; break; + case 2: fi=1; break; + case 4: fi=2; break; + case 8: fi=3; break; + default: abort(); + } + emit_byte(0x39); + emit_byte(0x04+8*d); + emit_byte(5+8*index+0x40*fi); + emit_long(offset); +} +LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) + +LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) +{ + emit_byte(0x31); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) +{ + emit_byte(0x66); + emit_byte(0x31); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) + +LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) +{ + emit_byte(0x30); + emit_byte(0xc0+8*s+d); +} +LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) + +LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) +{ + if (optimize_imm8 && isbyte(s)) { + emit_byte(0x83); + emit_byte(0x2d); + emit_long(d); + emit_byte(s); + } + else { + emit_byte(0x81); + emit_byte(0x2d); + emit_long(d); + emit_long(s); + } +} +LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) + +LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) +{ + if (optimize_imm8 && isbyte(s)) { + emit_byte(0x83); + emit_byte(0x3d); + emit_long(d); + emit_byte(s); + } + else { + emit_byte(0x81); + emit_byte(0x3d); + emit_long(d); + emit_long(s); + } +} +LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) + +LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) +{ + emit_byte(0x87); + emit_byte(0xc0+8*r1+r2); +} +LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) + +LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) +{ + emit_byte(0x86); + emit_byte(0xc0+8*(r1&0xf)+(r2&0xf)); /* XXX this handles upper-halves registers (e.g. %ah defined as 0x10+4) */ +} +LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) + +/************************************************************************* + * FIXME: mem access modes probably wrong * + *************************************************************************/ + +LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) +{ + emit_byte(0x9c); +} +LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) + +LOWFUNC(WRITE,READ,0,raw_popfl,(void)) +{ + emit_byte(0x9d); +} +LENDFUNC(WRITE,READ,0,raw_popfl,(void)) + +/* Generate floating-point instructions */ +static inline void x86_fadd_m(MEMR s) +{ + emit_byte(0xdc); + emit_byte(0x05); + emit_long(s); +} + +#endif + +/************************************************************************* + * Unoptimizable stuff --- jump * + *************************************************************************/ + +static inline void raw_call_r(R4 r) +{ +#if USE_NEW_RTASM + CALLsr(r); +#else + emit_byte(0xff); + emit_byte(0xd0+r); +#endif +} + +static inline void raw_call_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) +{ +#if USE_NEW_RTASM + ADDR32 CALLsm(base, X86_NOREG, r, m); +#else + int mu; + switch(m) { + case 1: mu=0; break; + case 2: mu=1; break; + case 4: mu=2; break; + case 8: mu=3; break; + default: abort(); + } + emit_byte(0xff); + emit_byte(0x14); + emit_byte(0x05+8*r+0x40*mu); + emit_long(base); +#endif +} + +static inline void raw_jmp_r(R4 r) +{ +#if USE_NEW_RTASM + JMPsr(r); +#else + emit_byte(0xff); + emit_byte(0xe0+r); +#endif +} + +static inline void raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) +{ +#if USE_NEW_RTASM + ADDR32 JMPsm(base, X86_NOREG, r, m); +#else + int mu; + switch (m) { + case 1: mu=0; break; + case 2: mu=1; break; + case 4: mu=2; break; + case 8: mu=3; break; + default: abort(); + } + emit_byte(0xff); + emit_byte(0x24); + emit_byte(0x05+8*r+0x40*mu); + emit_long(base); +#endif +} + +static inline void raw_jmp_m(uae_u32 base) +{ + emit_byte(0xff); + emit_byte(0x25); + emit_long(base); +} + + +static inline void raw_call(uae_u32 t) +{ +#if USE_NEW_RTASM + ADDR32 CALLm(t); +#else + emit_byte(0xe8); + emit_long(t-(uintptr)target-4); +#endif +} + +static inline void raw_jmp(uae_u32 t) +{ +#if USE_NEW_RTASM + ADDR32 JMPm(t); +#else + emit_byte(0xe9); + emit_long(t-(uintptr)target-4); +#endif +} + +static inline void raw_jl(uae_u32 t) +{ + emit_byte(0x0f); + emit_byte(0x8c); + emit_long(t-(uintptr)target-4); +} + +static inline void raw_jz(uae_u32 t) +{ + emit_byte(0x0f); + emit_byte(0x84); + emit_long(t-(uintptr)target-4); +} + +static inline void raw_jnz(uae_u32 t) +{ + emit_byte(0x0f); + emit_byte(0x85); + emit_long(t-(uintptr)target-4); +} + +static inline void raw_jnz_l_oponly(void) +{ + emit_byte(0x0f); + emit_byte(0x85); +} + +static inline void raw_jcc_l_oponly(int cc) +{ + emit_byte(0x0f); + emit_byte(0x80+cc); +} + +static inline void raw_jnz_b_oponly(void) +{ + emit_byte(0x75); +} + +static inline void raw_jz_b_oponly(void) +{ + emit_byte(0x74); +} + +static inline void raw_jcc_b_oponly(int cc) +{ + emit_byte(0x70+cc); +} + +static inline void raw_jmp_l_oponly(void) +{ + emit_byte(0xe9); +} + +static inline void raw_jmp_b_oponly(void) +{ + emit_byte(0xeb); +} + +static inline void raw_ret(void) +{ + emit_byte(0xc3); +} + +static inline void raw_emit_nop(void) +{ + emit_byte(0x90); +} + +static inline void raw_emit_nop_filler(int nbytes) +{ + +#if defined(CPU_x86_64) + /* The recommended way to pad 64bit code is to use NOPs preceded by + maximally four 0x66 prefixes. Balance the size of nops. */ + static const uae_u8 prefixes[4] = { 0x66, 0x66, 0x66, 0x66 }; + if (nbytes == 0) + return; + + int i; + int nnops = (nbytes + 3) / 4; + int len = nbytes / nnops; + int remains = nbytes - nnops * len; + + for (i = 0; i < remains; i++) { + emit_block(prefixes, len); + raw_emit_nop(); + } + for (; i < nnops; i++) { + emit_block(prefixes, len - 1); + raw_emit_nop(); + } +#else + /* Source: GNU Binutils 2.12.90.0.15 */ + /* Various efficient no-op patterns for aligning code labels. + Note: Don't try to assemble the instructions in the comments. + 0L and 0w are not legal. */ + static const uae_u8 f32_1[] = + {0x90}; /* nop */ + static const uae_u8 f32_2[] = + {0x89,0xf6}; /* movl %esi,%esi */ + static const uae_u8 f32_3[] = + {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ + static const uae_u8 f32_4[] = + {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ + static const uae_u8 f32_5[] = + {0x90, /* nop */ + 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ + static const uae_u8 f32_6[] = + {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ + static const uae_u8 f32_7[] = + {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ + static const uae_u8 f32_8[] = + {0x90, /* nop */ + 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ + static const uae_u8 f32_9[] = + {0x89,0xf6, /* movl %esi,%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ + static const uae_u8 f32_10[] = + {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ + static const uae_u8 f32_11[] = + {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ + static const uae_u8 f32_12[] = + {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ + 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ + static const uae_u8 f32_13[] = + {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ + static const uae_u8 f32_14[] = + {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ + 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ + static const uae_u8 f32_15[] = + {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; + static const uae_u8 f32_16[] = + {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; + static const uae_u8 *const f32_patt[] = { + f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, + f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 + }; + + int nloops = nbytes / 16; + while (nloops-- > 0) + emit_block(f32_16, sizeof(f32_16)); + + nbytes %= 16; + if (nbytes) + emit_block(f32_patt[nbytes - 1], nbytes); +#endif +} + + +/************************************************************************* + * Flag handling, to and fro UAE flag register * + *************************************************************************/ + +static inline void raw_flags_evicted(int r) +{ + //live.state[FLAGTMP].status=CLEAN; + live.state[FLAGTMP].status=INMEM; + live.state[FLAGTMP].realreg=-1; + /* We just "evicted" FLAGTMP. */ + if (live.nat[r].nholds!=1) { + /* Huh? */ + abort(); + } + live.nat[r].nholds=0; +} + +#define FLAG_NREG1_FLAGREG 0 /* Set to -1 if any register will do */ +static inline void raw_flags_to_reg_FLAGREG(int r) +{ + raw_lahf(0); /* Most flags in AH */ + //raw_setcc(r,0); /* V flag in AL */ + raw_setcc_m((uintptr)live.state[FLAGTMP].mem,0); + +#if 1 /* Let's avoid those nasty partial register stalls */ + //raw_mov_b_mr((uintptr)live.state[FLAGTMP].mem,r); + raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,AH_INDEX); + raw_flags_evicted(r); +#endif +} + +#define FLAG_NREG2_FLAGREG 0 /* Set to -1 if any register will do */ +static inline void raw_reg_to_flags_FLAGREG(int r) +{ + raw_cmp_b_ri(r,-127); /* set V */ + raw_sahf(0); +} + +#define FLAG_NREG3_FLAGREG 0 /* Set to -1 if any register will do */ +static __inline__ void raw_flags_set_zero_FLAGREG(int s, int tmp) +{ + raw_mov_l_rr(tmp,s); + raw_lahf(s); /* flags into ah */ + raw_and_l_ri(s,0xffffbfff); + raw_and_l_ri(tmp,0x00004000); + raw_xor_l_ri(tmp,0x00004000); + raw_or_l(s,tmp); + raw_sahf(s); +} + +static inline void raw_flags_init_FLAGREG(void) { } + +#define FLAG_NREG1_FLAGSTK -1 /* Set to -1 if any register will do */ +static inline void raw_flags_to_reg_FLAGSTK(int r) +{ + raw_pushfl(); + raw_pop_l_r(r); + raw_mov_l_mr((uintptr)live.state[FLAGTMP].mem,r); + raw_flags_evicted(r); +} + +#define FLAG_NREG2_FLAGSTK -1 /* Set to -1 if any register will do */ +static inline void raw_reg_to_flags_FLAGSTK(int r) +{ + raw_push_l_r(r); + raw_popfl(); +} + +#define FLAG_NREG3_FLAGSTK -1 /* Set to -1 if any register will do */ +static inline void raw_flags_set_zero_FLAGSTK(int s, int tmp) +{ + raw_mov_l_rr(tmp,s); + raw_pushfl(); + raw_pop_l_r(s); + raw_and_l_ri(s,0xffffffbf); + raw_and_l_ri(tmp,0x00000040); + raw_xor_l_ri(tmp,0x00000040); + raw_or_l(s,tmp); + raw_push_l_r(s); + raw_popfl(); +} + +static inline void raw_flags_init_FLAGSTK(void) { } + +#if defined(CPU_x86_64) +/* Try to use the LAHF/SETO method on x86_64 since it is faster. + This can't be the default because some older CPUs don't support + LAHF/SAHF in long mode. */ +static int FLAG_NREG1_FLAGGEN = 0; +static inline void raw_flags_to_reg_FLAGGEN(int r) +{ + if (have_lahf_lm) { + // NOTE: the interpreter uses the normal EFLAGS layout + // pushf/popf CF(0) ZF( 6) SF( 7) OF(11) + // sahf/lahf CF(8) ZF(14) SF(15) OF( 0) + assert(r == 0); + raw_setcc(r,0); /* V flag in AL */ + raw_lea_l_r_scaled(0,0,8); /* move it to its EFLAGS location */ + raw_mov_b_mr(((uintptr)live.state[FLAGTMP].mem)+1,0); + raw_lahf(0); /* most flags in AH */ + raw_mov_b_mr((uintptr)live.state[FLAGTMP].mem,AH_INDEX); + raw_flags_evicted(r); + } + else + raw_flags_to_reg_FLAGSTK(r); +} + +static int FLAG_NREG2_FLAGGEN = 0; +static inline void raw_reg_to_flags_FLAGGEN(int r) +{ + if (have_lahf_lm) { + raw_xchg_b_rr(0,AH_INDEX); + raw_cmp_b_ri(r,-120); /* set V */ + raw_sahf(0); + } + else + raw_reg_to_flags_FLAGSTK(r); +} + +static int FLAG_NREG3_FLAGGEN = 0; +static inline void raw_flags_set_zero_FLAGGEN(int s, int tmp) +{ + if (have_lahf_lm) + raw_flags_set_zero_FLAGREG(s, tmp); + else + raw_flags_set_zero_FLAGSTK(s, tmp); +} + +static inline void raw_flags_init_FLAGGEN(void) +{ + if (have_lahf_lm) { + FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGREG; + FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGREG; + FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGREG; + } + else { + FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGSTK; + FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGSTK; + FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGSTK; + } +} +#endif + +#ifdef SAHF_SETO_PROFITABLE +#define FLAG_SUFFIX FLAGREG +#elif defined CPU_x86_64 +#define FLAG_SUFFIX FLAGGEN +#else +#define FLAG_SUFFIX FLAGSTK +#endif + +#define FLAG_GLUE_2(x, y) x ## _ ## y +#define FLAG_GLUE_1(x, y) FLAG_GLUE_2(x, y) +#define FLAG_GLUE(x) FLAG_GLUE_1(x, FLAG_SUFFIX) + +#define raw_flags_init FLAG_GLUE(raw_flags_init) +#define FLAG_NREG1 FLAG_GLUE(FLAG_NREG1) +#define raw_flags_to_reg FLAG_GLUE(raw_flags_to_reg) +#define FLAG_NREG2 FLAG_GLUE(FLAG_NREG2) +#define raw_reg_to_flags FLAG_GLUE(raw_reg_to_flags) +#define FLAG_NREG3 FLAG_GLUE(FLAG_NREG3) +#define raw_flags_set_zero FLAG_GLUE(raw_flags_set_zero) + +/* Apparently, there are enough instructions between flag store and + flag reload to avoid the partial memory stall */ +static inline void raw_load_flagreg(uae_u32 target, uae_u32 r) +{ +#if 1 + raw_mov_l_rm(target,(uintptr)live.state[r].mem); +#else + raw_mov_b_rm(target,(uintptr)live.state[r].mem); + raw_mov_b_rm(target+4,((uintptr)live.state[r].mem)+1); +#endif +} + +#ifdef UAE +/* FLAGX is word-sized */ +#else +/* FLAGX is byte sized, and we *do* write it at that size */ +#endif +static inline void raw_load_flagx(uae_u32 target, uae_u32 r) +{ +#ifdef UAE + if (live.nat[target].canword) +#else + if (live.nat[target].canbyte) + raw_mov_b_rm(target,(uintptr)live.state[r].mem); + else if (live.nat[target].canword) +#endif + raw_mov_w_rm(target,(uintptr)live.state[r].mem); + else + raw_mov_l_rm(target,(uintptr)live.state[r].mem); +} + +static inline void raw_dec_sp(int off) +{ + if (off) { +#ifdef CPU_x86_64 + emit_byte(0x48); /* REX prefix */ +#endif + raw_sub_l_ri(ESP_INDEX,off); + } +} + +static inline void raw_inc_sp(int off) +{ + if (off) { +#ifdef CPU_x86_64 + emit_byte(0x48); /* REX prefix */ +#endif + raw_add_l_ri(ESP_INDEX,off); + } +} + +static inline void raw_push_regs_to_preserve(void) { + for (int i=N_REGS;i--;) { + if (need_to_preserve[i]) + raw_push_l_r(i); + } +} + +static inline void raw_pop_preserved_regs(void) { + for (int i=0;ix86_vendor_id; + + if (!strcmp(v, "GenuineIntel")) + c->x86_vendor = X86_VENDOR_INTEL; + else if (!strcmp(v, "AuthenticAMD")) + c->x86_vendor = X86_VENDOR_AMD; + else if (!strcmp(v, "CyrixInstead")) + c->x86_vendor = X86_VENDOR_CYRIX; + else if (!strcmp(v, "Geode by NSC")) + c->x86_vendor = X86_VENDOR_NSC; + else if (!strcmp(v, "UMC UMC UMC ")) + c->x86_vendor = X86_VENDOR_UMC; + else if (!strcmp(v, "CentaurHauls")) + c->x86_vendor = X86_VENDOR_CENTAUR; + else if (!strcmp(v, "NexGenDriven")) + c->x86_vendor = X86_VENDOR_NEXGEN; + else if (!strcmp(v, "RiseRiseRise")) + c->x86_vendor = X86_VENDOR_RISE; + else if (!strcmp(v, "GenuineTMx86") || !strcmp(v, "TransmetaCPU")) + c->x86_vendor = X86_VENDOR_TRANSMETA; + else + c->x86_vendor = X86_VENDOR_UNKNOWN; +} + +/* + * Generic CPUID function + * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx + * resulting in stale register contents being returned. + */ +/* Some CPUID calls want 'count' to be placed in ecx */ +#ifdef __GNUC__ +static void cpuid_count(uae_u32 op, uae_u32 count, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) +{ + uae_u32 _eax, _ebx, _ecx, _edx; + _eax = op; + _ecx = count; + __asm__ __volatile__( + " movl %0,%%eax \n" + " movl %2,%%ecx \n" + " cpuid \n" + " movl %%eax,%0 \n" + " movl %%ebx,%1 \n" + " movl %%ecx,%2 \n" + " movl %%edx,%3 \n" + : "+m" (_eax), + "=m" (_ebx), + "+m" (_ecx), + "=m" (_edx) + : + : "eax", "ebx", "ecx", "edx"); + *eax = _eax; + *ebx = _ebx; + *ecx = _ecx; + *edx = _edx; +} +#endif + +#ifdef _MSC_VER +#include +static void cpuid_count(uae_u32 op, uae_u32 count, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) +{ + int cpuinfo[4]; + cpuinfo[0] = op; + cpuinfo[1] = 0; + cpuinfo[2] = count; + cpuinfo[3] = 0; + __cpuidex(cpuinfo, op, count); + *eax = cpuinfo[0]; + *ebx = cpuinfo[1]; + *ecx = cpuinfo[2]; + *edx = cpuinfo[3]; +} +#endif + +static void +cpuid(uae_u32 op, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) +{ + cpuid_count(op, 0, eax, ebx, ecx, edx); +} + +static void +raw_init_cpu(void) +{ + struct cpuinfo_x86 *c = &cpuinfo; + uae_u32 dummy; + + /* Defaults */ + c->x86_processor = X86_PROCESSOR_max; + c->x86_vendor = X86_VENDOR_UNKNOWN; + c->cpuid_level = -1; /* CPUID not detected */ + c->x86_model = c->x86_mask = 0; /* So far unknown... */ + c->x86_vendor_id[0] = '\0'; /* Unset */ + c->x86_hwcap = 0; +#ifdef CPU_x86_64 + c->x86_clflush_size = 64; +#else + c->x86_clflush_size = 32; +#endif + + /* Get vendor name */ + c->x86_vendor_id[12] = '\0'; + cpuid(0x00000000, + (uae_u32 *)&c->cpuid_level, + (uae_u32 *)&c->x86_vendor_id[0], + (uae_u32 *)&c->x86_vendor_id[8], + (uae_u32 *)&c->x86_vendor_id[4]); + x86_get_cpu_vendor(c); + + /* Intel-defined flags: level 0x00000001 */ + c->x86_brand_id = 0; + if ( c->cpuid_level >= 0x00000001 ) { + uae_u32 tfms, brand_id; + cpuid(0x00000001, &tfms, &brand_id, &dummy, &c->x86_hwcap); + c->x86 = (tfms >> 8) & 15; + if (c->x86 == 0xf) + c->x86 += (tfms >> 20) & 0xff; /* extended family */ + c->x86_model = (tfms >> 4) & 15; + if (c->x86_model == 0xf) + c->x86_model |= (tfms >> 12) & 0xf0; /* extended model */ + c->x86_brand_id = brand_id & 0xff; + c->x86_mask = tfms & 15; + if (c->x86_hwcap & (1 << 19)) + { + c->x86_clflush_size = ((brand_id >> 8) & 0xff) * 8; + } + } else { + /* Have CPUID level 0 only - unheard of */ + c->x86 = 4; + } + + /* AMD-defined flags: level 0x80000001 */ + uae_u32 xlvl; + cpuid(0x80000000, &xlvl, &dummy, &dummy, &dummy); + if ( (xlvl & 0xffff0000) == 0x80000000 ) { + if ( xlvl >= 0x80000001 ) { + uae_u32 features, extra_features; + cpuid(0x80000001, &dummy, &dummy, &extra_features, &features); + if (features & (1 << 29)) { + /* Assume x86-64 if long mode is supported */ + c->x86_processor = X86_PROCESSOR_X86_64; + } + if (extra_features & (1 << 0)) + have_lahf_lm = true; + } + } + + /* Canonicalize processor ID */ + switch (c->x86) { + case 3: + c->x86_processor = X86_PROCESSOR_I386; + break; + case 4: + c->x86_processor = X86_PROCESSOR_I486; + break; + case 5: + if (c->x86_vendor == X86_VENDOR_AMD) + c->x86_processor = X86_PROCESSOR_K6; + else + c->x86_processor = X86_PROCESSOR_PENTIUM; + break; + case 6: + if (c->x86_vendor == X86_VENDOR_AMD) + c->x86_processor = X86_PROCESSOR_ATHLON; + else + c->x86_processor = X86_PROCESSOR_PENTIUMPRO; + break; + case 15: + if (c->x86_processor == X86_PROCESSOR_max) { + switch (c->x86_vendor) { + case X86_VENDOR_INTEL: + c->x86_processor = X86_PROCESSOR_PENTIUM4; + break; + case X86_VENDOR_AMD: + /* Assume a 32-bit Athlon processor if not in long mode */ + c->x86_processor = X86_PROCESSOR_ATHLON; + break; + } + } + break; + } + if (c->x86_processor == X86_PROCESSOR_max) { + c->x86_processor = X86_PROCESSOR_I386; + jit_log("Error: unknown processor type"); + jit_log(" Family : %d", c->x86); + jit_log(" Model : %d", c->x86_model); + jit_log(" Mask : %d", c->x86_mask); + jit_log(" Vendor : %s [%d]", c->x86_vendor_id, c->x86_vendor); + if (c->x86_brand_id) + { + jit_log(" BrandID : %02x", c->x86_brand_id); + } + } + + /* Have CMOV support? */ + have_cmov = (c->x86_hwcap & (1 << 15)) != 0; +#if defined(CPU_x86_64) + if (!have_cmov) { + jit_abort("x86-64 implementations are bound to have CMOV!"); + } +#endif + + c->x86_has_xmm2 = (c->x86_hwcap & (1 << 26)) != 0; + + /* Can the host CPU suffer from partial register stalls? */ + // non-RAT_STALL mode is currently broken + have_rat_stall = true; //(c->x86_vendor == X86_VENDOR_INTEL); +#if 0 + /* It appears that partial register writes are a bad idea even on + AMD K7 cores, even though they are not supposed to have the + dreaded rat stall. Why? Anyway, that's why we lie about it ;-) */ + if (c->x86_processor == X86_PROCESSOR_ATHLON) + have_rat_stall = true; +#endif + + /* Alignments */ + if (tune_alignment) { + align_loops = x86_alignments[c->x86_processor].align_loop; + align_jumps = x86_alignments[c->x86_processor].align_jump; + } + + jit_log(" : Max CPUID level=%d Processor is %s [%s]", + c->cpuid_level, c->x86_vendor_id, + x86_processor_string_table[c->x86_processor]); + + raw_flags_init(); +} + +#ifndef UAE +static void __attribute_noinline__ prevent_redzone_use(void) {} + +static bool target_check_bsf(void) +{ + bool mismatch = false; + for (int g_ZF = 0; g_ZF <= 1; g_ZF++) { + for (int g_CF = 0; g_CF <= 1; g_CF++) { + for (int g_OF = 0; g_OF <= 1; g_OF++) { + for (int g_SF = 0; g_SF <= 1; g_SF++) { + for (int value = -1; value <= 1; value++) { + uintptr flags = (g_SF << 7) | (g_OF << 11) | (g_ZF << 6) | g_CF; + intptr tmp = value; + prevent_redzone_use(); + __asm__ __volatile__ ("push %0; popf; bsf %1,%1; pushf; pop %0" + : "+r" (flags), "+r" (tmp) : : "cc"); + int OF = (flags >> 11) & 1; + int SF = (flags >> 7) & 1; + int ZF = (flags >> 6) & 1; + int CF = flags & 1; + tmp = (value == 0); + if (ZF != tmp || SF != g_SF || OF != g_OF || CF != g_CF) + mismatch = true; + } + } + } + } + } + if (mismatch) + { + jit_log(" : Target CPU defines all flags on BSF instruction"); + } + return !mismatch; +} +#endif + +/************************************************************************* + * FPU stuff * + *************************************************************************/ + + +static inline void raw_fp_init(void) +{ + int i; + + for (i=0;i1) { + emit_byte(0x9b); + emit_byte(0xdb); + emit_byte(0xe3); + live.tos=-1; + } +#endif + while (live.tos>=1) { + emit_byte(0xde); + emit_byte(0xd9); + live.tos-=2; + } + while (live.tos>=0) { + emit_byte(0xdd); + emit_byte(0xd8); + live.tos--; + } + raw_fp_init(); +} + +static inline void make_tos(int r) +{ + int p,q; + + if (live.spos[r]<0) { /* Register not yet on stack */ + emit_byte(0xd9); + emit_byte(0xe8); /* Push '1' on the stack, just to grow it */ + live.tos++; + live.spos[r]=live.tos; + live.onstack[live.tos]=r; + return; + } + /* Register is on stack */ + if (live.tos==live.spos[r]) + return; + p=live.spos[r]; + q=live.onstack[live.tos]; + + emit_byte(0xd9); + emit_byte(0xc8+live.tos-live.spos[r]); /* exchange it with top of stack */ + live.onstack[live.tos]=r; + live.spos[r]=live.tos; + live.onstack[p]=q; + live.spos[q]=p; +} + +static inline void make_tos2(int r, int r2) +{ + int q; + + make_tos(r2); /* Put the reg that's supposed to end up in position2 on top */ + + if (live.spos[r]<0) { /* Register not yet on stack */ + make_tos(r); /* This will extend the stack */ + return; + } + /* Register is on stack */ + emit_byte(0xd9); + emit_byte(0xc9); /* Move r2 into position 2 */ + + q=live.onstack[live.tos-1]; + live.onstack[live.tos]=q; + live.spos[q]=live.tos; + live.onstack[live.tos-1]=r2; + live.spos[r2]=live.tos-1; + + make_tos(r); /* And r into 1 */ +} + +static inline int stackpos(int r) +{ + if (live.spos[r]<0) + abort(); + if (live.tos=0) { + /* source is on top of stack, and we already have the dest */ + int dd=stackpos(d); + emit_byte(0xdd); + emit_byte(0xd0+dd); + } + else { + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source on tos */ + tos_make(d); /* store to destination, pop if necessary */ + } +} +LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) + +LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) +{ + x86_64_prefix(true, false, NULL, NULL, &index); + emit_byte(0xd9); + emit_byte(0xa8 + index); + emit_long(base); +} +LENDFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) + +LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xfa); /* take square root */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xfa); /* take square root */ + } +} +LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xe1); /* take fabs */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xe1); /* take fabs */ + } +} +LENDFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xfc); /* take frndint */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xfc); /* take frndint */ + } +} +LENDFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xff); /* take cos */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xff); /* take cos */ + } +} +LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xfe); /* fsin sin(x) */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xfe); /* fsin y=sin(x) */ + } +} +LENDFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) + +static const double one = 1; + +LOWFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) +{ + int ds; + + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xc0); /* duplicate top of stack. Now up to 8 high */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(x) */ + emit_byte(0xd9); + emit_byte(0xc9); /* swap top two elements */ + emit_byte(0xd8); + emit_byte(0xe1); /* subtract rounded from original */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 */ + x86_fadd_m((uintptr)&one); /* Add '1' without using extra stack space */ + emit_byte(0xd9); + emit_byte(0xfd); /* and scale it */ + emit_byte(0xdd); + emit_byte(0xd9); /* take he rounded value off */ + tos_make(d); /* store to destination */ +} +LENDFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) +{ + int ds; + + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xea); /* fldl2e log2(e) */ + emit_byte(0xde); + emit_byte(0xc9); /* fmulp --- multiply source by log2(e) */ + + emit_byte(0xd9); + emit_byte(0xc0); /* duplicate top of stack. Now up to 8 high */ + emit_byte(0xd9); + emit_byte(0xfc); /* rndint */ + emit_byte(0xd9); + emit_byte(0xc9); /* swap top two elements */ + emit_byte(0xd8); + emit_byte(0xe1); /* subtract rounded from original */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 */ + x86_fadd_m((uintptr)&one); /* Add '1' without using extra stack space */ + emit_byte(0xd9); + emit_byte(0xfd); /* and scale it */ + emit_byte(0xdd); + emit_byte(0xd9); /* take he rounded value off */ + tos_make(d); /* store to destination */ +} +LENDFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) +{ + int ds; + + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xe8); /* push '1' */ + emit_byte(0xd9); + emit_byte(0xc9); /* swap top two */ + emit_byte(0xd9); + emit_byte(0xf1); /* take 1*log2(x) */ + tos_make(d); /* store to destination */ +} +LENDFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) + + +LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + usereg(s); + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* duplicate source */ + emit_byte(0xd9); + emit_byte(0xe0); /* take fchs */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xe0); /* take fchs */ + } +} +LENDFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + if (live.spos[s]==live.tos) { + /* Source is on top of stack */ + ds=stackpos(d); + emit_byte(0xdc); + emit_byte(0xc0+ds); /* add source to dest*/ + } + else { + make_tos(d); + ds=stackpos(s); + + emit_byte(0xd8); + emit_byte(0xc0+ds); /* add source to dest*/ + } +} +LENDFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + if (live.spos[s]==live.tos) { + /* Source is on top of stack */ + ds=stackpos(d); + emit_byte(0xdc); + emit_byte(0xe8+ds); /* sub source from dest*/ + } + else { + make_tos(d); + ds=stackpos(s); + + emit_byte(0xd8); + emit_byte(0xe0+ds); /* sub src from dest */ + } +} +LENDFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + make_tos(d); + ds=stackpos(s); + + emit_byte(0xdd); + emit_byte(0xe0+ds); /* cmp dest with source*/ +} +LENDFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + if (live.spos[s]==live.tos) { + /* Source is on top of stack */ + ds=stackpos(d); + emit_byte(0xdc); + emit_byte(0xc8+ds); /* mul dest by source*/ + } + else { + make_tos(d); + ds=stackpos(s); + + emit_byte(0xd8); + emit_byte(0xc8+ds); /* mul dest by source*/ + } +} +LENDFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + if (live.spos[s]==live.tos) { + /* Source is on top of stack */ + ds=stackpos(d); + emit_byte(0xdc); + emit_byte(0xf8+ds); /* div dest by source */ + } + else { + make_tos(d); + ds=stackpos(s); + + emit_byte(0xd8); + emit_byte(0xf0+ds); /* div dest by source*/ + } +} +LENDFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + make_tos2(d,s); + ds=stackpos(s); + + if (ds!=1) { + jit_abort("Failed horribly in raw_frem_rr! ds is %d",ds); + } + emit_byte(0xd9); + emit_byte(0xf8); /* take rem from dest by source */ +} +LENDFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) +{ + int ds; + + usereg(s); + usereg(d); + + make_tos2(d,s); + ds=stackpos(s); + + if (ds!=1) { + jit_abort("Failed horribly in raw_frem1_rr! ds is %d",ds); + } + emit_byte(0xd9); + emit_byte(0xf5); /* take rem1 from dest by source */ +} +LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) + + +LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) +{ + make_tos(r); + emit_byte(0xd9); /* ftst */ + emit_byte(0xe4); +} +LENDFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) + +LOWFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) +{ + int ds; + + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xea); /* fldl2e log2(e) */ + emit_byte(0xd8); + emit_byte(0xc9); /* fmul x*log2(e) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy up */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap top two elements */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + emit_byte(0xd9); + emit_byte(0xfd); /* fscale ((2^frac(x))-1)*2^int(x*log2(e)) */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy & pop */ + if (s!=d) + tos_make(d); /* store y=(e^x)-1 */ +} +LENDFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) +{ + int ds; + + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xe9); /* fldl2t log2(10) */ + emit_byte(0xd8); + emit_byte(0xc9); /* fmul x*log2(10) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy up */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(x*log2(10)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap top two elements */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub x*log2(10) - int(x*log2(10)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(10)) */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy & pop */ + if (s!=d) + tos_make(d); /* store y=10^x */ +} +LENDFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) +{ + int ds; + + if (s==d) { + //write_log (_T("FSINCOS src = dest\n")); + make_tos(s); + emit_byte(0xd9); + emit_byte(0xfb); /* fsincos sin(x) push cos(x) */ + tos_make(c); /* store cos(x) to c */ + return; + } + + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xfb); /* fsincos sin(x) push cos(x) */ + if (live.spos[c]<0) { + if (live.spos[d]<0) { /* occupy both regs directly */ + live.tos++; + live.spos[d]=live.tos; + live.onstack[live.tos]=d; /* sin(x) comes first */ + live.tos++; + live.spos[c]=live.tos; + live.onstack[live.tos]=c; + } + else { + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap cos(x) with sin(x) */ + emit_byte(0xdd); /* store sin(x) to d & pop */ + emit_byte(0xd8+(live.tos+2)-live.spos[d]); + live.tos++; /* occupy a reg for cos(x) here */ + live.spos[c]=live.tos; + live.onstack[live.tos]=c; + } + } + else { + emit_byte(0xdd); /* store cos(x) to c & pop */ + emit_byte(0xd8+(live.tos+2)-live.spos[c]); + tos_make(d); /* store sin(x) to destination */ + } +} +LENDFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) +{ + int ds; + + if (live.spos[d]==live.tos && live.spos[s]==live.tos-1) { + //write_log (_T("fscale found x in TOS-1 and y in TOS\n")); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale y*(2^x) */ + } + else { + make_tos(s); /* tos=x */ + ds=stackpos(d); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld y */ + emit_byte(0xd9); + emit_byte(0xfd); /* fscale y*(2^x) */ + tos_make(d); /* store y=y*(2^x) */ + } +} +LENDFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xf2); /* fptan tan(x)=y/1.0 */ + emit_byte(0xdd); + emit_byte(0xd8); /* fstp pop 1.0 */ + tos_make(d); /* store to destination */ + } + else { + make_tos(d); + emit_byte(0xd9); + emit_byte(0xf2); /* fptan tan(x)=y/1.0 */ + emit_byte(0xdd); + emit_byte(0xd8); /* fstp pop 1.0 */ + } +} +LENDFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) + +#ifdef CPU_x86_64 +#define REX64() emit_byte(0x48) +#else +#define REX64() +#endif + +LOWFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) +{ + make_tos(r); /* TOS = r */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0xfc); /* add -4 to esp */ + emit_byte(0xd9); + emit_byte(0x1c); + emit_byte(0x24); /* fstp store r as SINGLE to [esp] and pop */ + emit_byte(0xd9); + emit_byte(0x04); + emit_byte(0x24); /* fld load r as SINGLE from [esp] */ + emit_byte(0x9b); /* let the CPU wait on FPU exceptions */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0x04); /* add +4 to esp */ +} +LENDFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) + +LOWFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) +{ + make_tos(r); /* TOS = r */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0xf8); /* add -8 to esp */ + emit_byte(0xdd); + emit_byte(0x1c); + emit_byte(0x24); /* fstp store r as DOUBLE to [esp] and pop */ + emit_byte(0xdd); + emit_byte(0x04); + emit_byte(0x24); /* fld load r as DOUBLE from [esp] */ + emit_byte(0x9b); /* let the CPU wait on FPU exceptions */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0x08); /* add +8 to esp */ +} +LENDFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) + +LOWFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xf4); /* fxtract exp push man */ + emit_byte(0xdd); + emit_byte(0xd8); /* fstp just pop man */ + tos_make(d); /* store exp to destination */ + } + else { + make_tos(d); /* tos=x=y */ + emit_byte(0xd9); + emit_byte(0xf4); /* fxtract exp push man */ + emit_byte(0xdd); + emit_byte(0xd8); /* fstp just pop man */ + } +} +LENDFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) +{ + int ds; + + if (d!=s) { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xf4); /* fxtract exp push man */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy man up & pop */ + tos_make(d); /* store man to destination */ + } + else { + make_tos(d); /* tos=x=y */ + emit_byte(0xd9); + emit_byte(0xf4); /* fxtract exp push man */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy man up & pop */ + } +} +LENDFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) +{ + int ds; + + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xed); /* fldln2 logN(2) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap logN(2) with x */ + emit_byte(0xd9); + emit_byte(0xf1); /* fyl2x logN(2)*log2(x) */ + if (s!=d) + tos_make(d); /* store y=logN(x) */ +} +LENDFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) +{ + int ds; + + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xed); /* fldln2 logN(2) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap logN(2) with x */ + emit_byte(0xd9); + emit_byte(0xf9); /* fyl2xp1 logN(2)*log2(x+1) */ + if (s!=d) + tos_make(d); /* store y=logN(x+1) */ +} +LENDFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) +{ + int ds; + + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xec); /* fldlg2 log10(2) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap log10(2) with x */ + emit_byte(0xd9); + emit_byte(0xf1); /* fyl2x log10(2)*log2(x) */ + if (s!=d) + tos_make(d); /* store y=log10(x) */ +} +LENDFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) +{ + int ds; + + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd8); + emit_byte(0xc8); /* fmul x*x */ + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xde); + emit_byte(0xe1); /* fsubrp 1 - (x^2) */ + emit_byte(0xd9); + emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */ + emit_byte(0xd9); + emit_byte(0xc1+ds); /* fld x again */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */ + emit_byte(0xd9); + emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ + tos_make(d); /* store y=asin(x) */ +} +LENDFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) + +static uae_u32 pihalf[] = {0x2168c234, 0xc90fdaa2, 0x3fff}; // LSB=0 to get acos(1)=0 + +LOWFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) +{ + int ds; + + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd8); + emit_byte(0xc8); /* fmul x*x */ + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xde); + emit_byte(0xe1); /* fsubrp 1 - (x^2) */ + emit_byte(0xd9); + emit_byte(0xfa); /* fsqrt sqrt(1-(x^2)) */ + emit_byte(0xd9); + emit_byte(0xc1+ds); /* fld x again */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap x with sqrt(1-(x^2)) */ + emit_byte(0xd9); + emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ + raw_fldt((uintptr) &pihalf); /* fld load pi/2 from pihalf */ + emit_byte(0xde); + emit_byte(0xe1); /* fsubrp pi/2 - asin(x) & pop */ + tos_make(d); /* store y=acos(x) */ +} +LENDFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) +{ + int ds; + + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xd9); + emit_byte(0xf3); /* fpatan atan(x)/1 & pop*/ + if (s!=d) + tos_make(d); /* store y=atan(x) */ +} +LENDFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) +{ + int ds; + + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xdc); + emit_byte(0xc1); /* fadd 1 + x */ + emit_byte(0xd8); + emit_byte(0xe2+ds); /* fsub 1 - x */ + emit_byte(0xde); + emit_byte(0xf9); /* fdivp (1+x)/(1-x) */ + emit_byte(0xd9); + emit_byte(0xed); /* fldl2e logN(2) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap logN(2) with (1+x)/(1-x) */ + emit_byte(0xd9); + emit_byte(0xf1); /* fyl2x logN(2)*log2((1+x)/(1-x)) pop */ + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xd9); + emit_byte(0xe0); /* fchs -1.0 */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd9); + emit_byte(0xfd); /* fscale logN((1+x)/(1-x)) * 2^(-1) */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy & pop */ + tos_make(d); /* store y=atanh(x) */ +} +LENDFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) +{ + int ds,tr; + + tr=live.onstack[live.tos+3]; + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xea); /* fldl2e log2(e) */ + emit_byte(0xd8); + emit_byte(0xc9); /* fmul x*log2(e) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy x*log2(e) */ + if (tr>=0) { + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap with temp-reg */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0xf4); /* add -12 to esp */ + emit_byte(0xdb); + emit_byte(0x3c); + emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ + } + emit_byte(0xd9); + emit_byte(0xe0); /* fchs -x*log2(e) */ + emit_byte(0xd9); + emit_byte(0xc0); /* fld -x*log2(e) again */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(-x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy x*log2(e) */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy e^x & pop */ + if (tr>=0) { + emit_byte(0xdb); + emit_byte(0x2c); + emit_byte(0x24); /* fld load temp-reg from [esp] */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ + emit_byte(0xde); + emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0x0c); /* delayed add +12 to esp */ + } + else { + emit_byte(0xde); + emit_byte(0xe1); /* fsubrp (e^x)-(e^-x) */ + } + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xd9); + emit_byte(0xe0); /* fchs -1.0 */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd9); + emit_byte(0xfd); /* fscale ((e^x)-(e^-x))/2 */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy & pop */ + if (s!=d) + tos_make(d); /* store y=sinh(x) */ +} +LENDFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) +{ + int ds,tr; + + tr=live.onstack[live.tos+3]; + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xea); /* fldl2e log2(e) */ + emit_byte(0xd8); + emit_byte(0xc9); /* fmul x*log2(e) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy x*log2(e) */ + if (tr>=0) { + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap with temp-reg */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0xf4); /* add -12 to esp */ + emit_byte(0xdb); + emit_byte(0x3c); + emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ + } + emit_byte(0xd9); + emit_byte(0xe0); /* fchs -x*log2(e) */ + emit_byte(0xd9); + emit_byte(0xc0); /* fld -x*log2(e) again */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(-x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap e^-x with x*log2(e) in tr */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy x*log2(e) */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy e^x & pop */ + if (tr>=0) { + emit_byte(0xdb); + emit_byte(0x2c); + emit_byte(0x24); /* fld load temp-reg from [esp] */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0x0c); /* delayed add +12 to esp */ + } + emit_byte(0xde); + emit_byte(0xc1); /* faddp (e^x)+(e^-x) */ + emit_byte(0xd9); + emit_byte(0xe8); /* fld 1.0 */ + emit_byte(0xd9); + emit_byte(0xe0); /* fchs -1.0 */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd9); + emit_byte(0xfd); /* fscale ((e^x)+(e^-x))/2 */ + emit_byte(0xdd); + emit_byte(0xd9); /* fstp copy & pop */ + if (s!=d) + tos_make(d); /* store y=cosh(x) */ +} +LENDFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) + +LOWFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) +{ + int ds,tr; + + tr=live.onstack[live.tos+3]; + if (s==d) + make_tos(s); + else { + ds=stackpos(s); + emit_byte(0xd9); + emit_byte(0xc0+ds); /* fld x */ + } + emit_byte(0xd9); + emit_byte(0xea); /* fldl2e log2(e) */ + emit_byte(0xd8); + emit_byte(0xc9); /* fmul x*log2(e) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy x*log2(e) */ + if (tr>=0) { + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap with temp-reg */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0xf4); /* add -12 to esp */ + emit_byte(0xdb); + emit_byte(0x3c); + emit_byte(0x24); /* fstp store temp-reg to [esp] & pop */ + } + emit_byte(0xd9); + emit_byte(0xe0); /* fchs -x*log2(e) */ + emit_byte(0xd9); + emit_byte(0xc0); /* fld -x*log2(e) again */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(-x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub -x*log2(e) - int(-x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap e^-x with x*log2(e) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy x*log2(e) */ + emit_byte(0xd9); + emit_byte(0xfc); /* frndint int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xc9); /* fxch swap */ + emit_byte(0xd8); + emit_byte(0xe1); /* fsub x*log2(e) - int(x*log2(e)) */ + emit_byte(0xd9); + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); + emit_byte(0xd9); + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x*log2(e)) */ + emit_byte(0xdd); + emit_byte(0xd1); /* fst copy e^x */ + emit_byte(0xd8); + emit_byte(0xc2); /* fadd (e^x)+(e^-x) */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap with e^-x */ + emit_byte(0xde); + emit_byte(0xe9); /* fsubp (e^x)-(e^-x) */ + if (tr>=0) { + emit_byte(0xdb); + emit_byte(0x2c); + emit_byte(0x24); /* fld load temp-reg from [esp] */ + emit_byte(0xd9); + emit_byte(0xca); /* fxch swap temp-reg with e^-x in tr */ + emit_byte(0xde); + emit_byte(0xf9); /* fdivp ((e^x)-(e^-x))/((e^x)+(e^-x)) */ + REX64(); + emit_byte(0x83); + emit_byte(0xc4); + emit_byte(0x0c); /* delayed add +12 to esp */ + } + else { + emit_byte(0xde); + emit_byte(0xf1); /* fdivrp ((e^x)-(e^-x))/((e^x)+(e^-x)) */ + } + if (s!=d) + tos_make(d); /* store y=tanh(x) */ +} +LENDFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) + +/* %eax register is clobbered if target processor doesn't support fucomi */ +#define FFLAG_NREG_CLOBBER_CONDITION !have_cmov +#define FFLAG_NREG EAX_INDEX + +static inline void raw_fflags_into_flags(int r) +{ + int p; + + usereg(r); + p=stackpos(r); + + emit_byte(0xd9); + emit_byte(0xee); /* Push 0 */ + emit_byte(0xd9); + emit_byte(0xc9+p); /* swap top two around */ + if (have_cmov) { + // gb-- fucomi is for P6 cores only, not K6-2 then... + emit_byte(0xdb); + emit_byte(0xe9+p); /* fucomi them */ + } + else { + emit_byte(0xdd); + emit_byte(0xe1+p); /* fucom them */ + emit_byte(0x9b); + emit_byte(0xdf); + emit_byte(0xe0); /* fstsw ax */ + raw_sahf(0); /* sahf */ + } + emit_byte(0xdd); + emit_byte(0xd9+p); /* store value back, and get rid of 0 */ +} diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.h b/BasiliskII/src/uae_cpu/compiler/codegen_x86.h new file mode 100644 index 00000000..6743392d --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.h @@ -0,0 +1,1996 @@ +/* + * compiler/codegen_x86.h - IA-32 and AMD64 code generator + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> IA-32 and AMD64 + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * This file is derived from CCG, copyright 1999-2003 Ian Piumarta + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef X86_RTASM_H +#define X86_RTASM_H + +/* NOTES + * + * o Best viewed on a 1024x768 screen with fixed-6x10 font ;-) + * + * TODO + * + * o Fix FIXMEs + * o i387 FPU instructions + * o SSE instructions + * o Optimize for cases where register numbers are not integral constants + */ + +/* --- Configuration ------------------------------------------------------- */ + +/* Define to settle a "flat" register set, i.e. different regno for + each size variant. */ +#ifndef X86_FLAT_REGISTERS +#define X86_FLAT_REGISTERS 1 +#endif + +/* Define to generate x86-64 code. */ +#ifndef X86_TARGET_64BIT +#define X86_TARGET_64BIT 0 +#endif + +/* Define to optimize ALU instructions. */ +#ifndef X86_OPTIMIZE_ALU +#define X86_OPTIMIZE_ALU 1 +#endif + +/* Define to optimize rotate/shift instructions. */ +#ifndef X86_OPTIMIZE_ROTSHI +#define X86_OPTIMIZE_ROTSHI 1 +#endif + +/* Define to optimize absolute addresses for RIP relative addressing. */ +#ifndef X86_RIP_RELATIVE_ADDR +#define X86_RIP_RELATIVE_ADDR 1 +#endif + + +/* --- Macros -------------------------------------------------------------- */ + +/* Functions used to emit code. + * + * x86_emit_byte(B) + * x86_emit_word(W) + * x86_emit_long(L) + */ + +/* Get pointer to current code + * + * x86_get_target() + */ + +/* Abort assembler, fatal failure. + * + * x86_emit_failure(MSG) + */ + +#define x86_emit_failure0(MSG) (x86_emit_failure(MSG),0) + + +/* --- Register set -------------------------------------------------------- */ + +enum { + X86_RIP = -2, +#if X86_FLAT_REGISTERS + X86_NOREG = 0, + X86_Reg8L_Base = 0x10, + X86_Reg8H_Base = 0x20, + X86_Reg16_Base = 0x30, + X86_Reg32_Base = 0x40, + X86_Reg64_Base = 0x50, + X86_RegMMX_Base = 0x60, + X86_RegXMM_Base = 0x70, +#else + X86_NOREG = -1, + X86_Reg8L_Base = 0, + X86_Reg8H_Base = 16, + X86_Reg16_Base = 0, + X86_Reg32_Base = 0, + X86_Reg64_Base = 0, + X86_RegMMX_Base = 0, + X86_RegXMM_Base = 0, +#endif +}; + +enum { + X86_AL = X86_Reg8L_Base, + X86_CL, X86_DL, X86_BL, + X86_SPL, X86_BPL, X86_SIL, X86_DIL, + X86_R8B, X86_R9B, X86_R10B, X86_R11B, + X86_R12B, X86_R13B, X86_R14B, X86_R15B, + X86_AH = X86_Reg8H_Base + 4, + X86_CH, X86_DH, X86_BH +}; + +enum { + X86_AX = X86_Reg16_Base, + X86_CX, X86_DX, X86_BX, + X86_SP, X86_BP, X86_SI, X86_DI, + X86_R8W, X86_R9W, X86_R10W, X86_R11W, + X86_R12W, X86_R13W, X86_R14W, X86_R15W +}; + +enum { + X86_EAX = X86_Reg32_Base, + X86_ECX, X86_EDX, X86_EBX, + X86_ESP, X86_EBP, X86_ESI, X86_EDI, + X86_R8D, X86_R9D, X86_R10D, X86_R11D, + X86_R12D, X86_R13D, X86_R14D, X86_R15D +}; + +enum { + X86_RAX = X86_Reg64_Base, + X86_RCX, X86_RDX, X86_RBX, + X86_RSP, X86_RBP, X86_RSI, X86_RDI, + X86_R8, X86_R9, X86_R10, X86_R11, + X86_R12, X86_R13, X86_R14, X86_R15 +}; + +enum { + X86_MM0 = X86_RegMMX_Base, + X86_MM1, X86_MM2, X86_MM3, + X86_MM4, X86_MM5, X86_MM6, X86_MM7, +}; + +enum { + X86_XMM0 = X86_RegXMM_Base, + X86_XMM1, X86_XMM2, X86_XMM3, + X86_XMM4, X86_XMM5, X86_XMM6, X86_XMM7, + X86_XMM8, X86_XMM9, X86_XMM10, X86_XMM11, + X86_XMM12, X86_XMM13, X86_XMM14, X86_XMM15 +}; + +/* Register control and access + * + * _r0P(R) Null register? + * _rIP(R) RIP register? + * _rXP(R) Extended register? + * + * _rC(R) Class of register (only valid if X86_FLAT_REGISTERS) + * _rR(R) Full register number + * _rN(R) Short register number for encoding + * + * _r1(R) 8-bit register ID + * _r2(R) 16-bit register ID + * _r4(R) 32-bit register ID + * _r8(R) 64-bit register ID + * _rM(R) MMX register ID + * _rX(R) XMM register ID + * _rA(R) Address register ID used for EA calculation + */ + +#define _r0P(R) ((int)(R) == (int)X86_NOREG) +#define _rIP(R) ((int)(R) == (int)X86_RIP) + +#if X86_FLAT_REGISTERS +#define _rC(R) ((R) & 0xf0) +#define _rR(R) ((R) & 0x0f) +#define _rN(R) ((R) & 0x07) +#define _rXP(R) ((R) > 0 && _rR(R) > 7) +#else +#define _rN(R) ((R) & 0x07) +#define _rR(R) (int(R)) +#define _rXP(R) (_rR(R) > 7 && _rR(R) < 16) +#endif + +#if !defined(_ASM_SAFETY) || ! X86_FLAT_REGISTERS +#define _r1(R) _rN(R) +#define _r2(R) _rN(R) +#define _r4(R) _rN(R) +#define _r8(R) _rN(R) +#define _rA(R) _rN(R) +#define _rM(R) _rN(R) +#define _rX(R) _rN(R) +#else +#define _r1(R) ( ((_rC(R) & (X86_Reg8L_Base | X86_Reg8H_Base)) != 0) ? _rN(R) : x86_emit_failure0( "8-bit register required")) +#define _r2(R) ( (_rC(R) == X86_Reg16_Base) ? _rN(R) : x86_emit_failure0("16-bit register required")) +#define _r4(R) ( (_rC(R) == X86_Reg32_Base) ? _rN(R) : x86_emit_failure0("32-bit register required")) +#define _r8(R) ( (_rC(R) == X86_Reg64_Base) ? _rN(R) : x86_emit_failure0("64-bit register required")) +#define _rA(R) ( X86_TARGET_64BIT ? \ + ( (_rC(R) == X86_Reg64_Base) ? _rN(R) : x86_emit_failure0("not a valid 64-bit base/index expression")) : \ + ( (_rC(R) == X86_Reg32_Base) ? _rN(R) : x86_emit_failure0("not a valid 32-bit base/index expression")) ) +#define _rM(R) ( (_rC(R) == X86_RegMMX_Base) ? _rN(R) : x86_emit_failure0("MMX register required")) +#define _rX(R) ( (_rC(R) == X86_RegXMM_Base) ? _rN(R) : x86_emit_failure0("SSE register required")) +#endif + +#define _rSP() (X86_TARGET_64BIT ? (int)X86_RSP : (int)X86_ESP) +#define _r1e8lP(R) (int(R) >= X86_SPL && int(R) <= X86_DIL) +#define _rbpP(R) (_rR(R) == _rR(X86_RBP)) +#define _rspP(R) (_rR(R) == _rR(X86_RSP)) +#define _rbp13P(R) (_rN(R) == _rN(X86_RBP)) +#define _rsp12P(R) (_rN(R) == _rN(X86_RSP)) + + +/* ========================================================================= */ +/* --- UTILITY ------------------------------------------------------------- */ +/* ========================================================================= */ + +typedef signed char _sc; +typedef unsigned char _uc; +typedef signed short _ss; +typedef unsigned short _us; +typedef signed int _sl; +typedef unsigned int _ul; + +#define _UC(X) ((_uc )(uintptr_t)(X)) +#define _US(X) ((_us )(uintptr_t)(X)) +#define _SL(X) ((_sl )(uintptr_t)(X)) +#define _UL(X) ((_ul )(uintptr_t)(X)) + +#define _PUC(X) ((_uc *)(X)) +#define _PUS(X) ((_us *)(X)) +#define _PSL(X) ((_sl *)(X)) +#define _PUL(X) ((_ul *)(X)) + +#undef _B +#undef _W +#undef _L +#undef _Q + +#define _B(B) x86_emit_byte((B)) +#define _W(W) x86_emit_word((W)) +#define _L(L) x86_emit_long((L)) +#define _Q(Q) x86_emit_quad((Q)) + +#define _MASK(N) ((unsigned)((1<<(N)))-1) +#define _siP(N,I) (!((((unsigned)(I))^(((unsigned)(I))<<1))&~_MASK(N))) +#define _uiP(N,I) (!(((unsigned)(I))&~_MASK(N))) +#define _suiP(N,I) (_siP(N,I) | _uiP(N,I)) + +#ifndef _ASM_SAFETY +#define _ck_s(W,I) (_UL(I) & _MASK(W)) +#define _ck_u(W,I) (_UL(I) & _MASK(W)) +#define _ck_su(W,I) (_UL(I) & _MASK(W)) +#define _ck_d(W,I) (_UL(I) & _MASK(W)) +#else +#define _ck_s(W,I) (_siP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0( "signed integer `"#I"' too large for "#W"-bit field")) +#define _ck_u(W,I) (_uiP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0("unsigned integer `"#I"' too large for "#W"-bit field")) +#define _ck_su(W,I) (_suiP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0( "integer `"#I"' too large for "#W"-bit field")) +#define _ck_d(W,I) (_siP(W,I) ? (_UL(I) & _MASK(W)) : x86_emit_failure0( "displacement `"#I"' too large for "#W"-bit field")) +#endif + +#define _s0P(I) ((I)==0) +#define _s8P(I) _siP(8,I) +#define _s16P(I) _siP(16,I) +#define _u8P(I) _uiP(8,I) +#define _u16P(I) _uiP(16,I) + +#define _su8(I) _ck_su(8,I) +#define _su16(I) _ck_su(16,I) + +#define _s1(I) _ck_s( 1,I) +#define _s2(I) _ck_s( 2,I) +#define _s3(I) _ck_s( 3,I) +#define _s4(I) _ck_s( 4,I) +#define _s5(I) _ck_s( 5,I) +#define _s6(I) _ck_s( 6,I) +#define _s7(I) _ck_s( 7,I) +#define _s8(I) _ck_s( 8,I) +#define _s9(I) _ck_s( 9,I) +#define _s10(I) _ck_s(10,I) +#define _s11(I) _ck_s(11,I) +#define _s12(I) _ck_s(12,I) +#define _s13(I) _ck_s(13,I) +#define _s14(I) _ck_s(14,I) +#define _s15(I) _ck_s(15,I) +#define _s16(I) _ck_s(16,I) +#define _s17(I) _ck_s(17,I) +#define _s18(I) _ck_s(18,I) +#define _s19(I) _ck_s(19,I) +#define _s20(I) _ck_s(20,I) +#define _s21(I) _ck_s(21,I) +#define _s22(I) _ck_s(22,I) +#define _s23(I) _ck_s(23,I) +#define _s24(I) _ck_s(24,I) +#define _s25(I) _ck_s(25,I) +#define _s26(I) _ck_s(26,I) +#define _s27(I) _ck_s(27,I) +#define _s28(I) _ck_s(28,I) +#define _s29(I) _ck_s(29,I) +#define _s30(I) _ck_s(30,I) +#define _s31(I) _ck_s(31,I) +#define _u1(I) _ck_u( 1,I) +#define _u2(I) _ck_u( 2,I) +#define _u3(I) _ck_u( 3,I) +#define _u4(I) _ck_u( 4,I) +#define _u5(I) _ck_u( 5,I) +#define _u6(I) _ck_u( 6,I) +#define _u7(I) _ck_u( 7,I) +#define _u8(I) _ck_u( 8,I) +#define _u9(I) _ck_u( 9,I) +#define _u10(I) _ck_u(10,I) +#define _u11(I) _ck_u(11,I) +#define _u12(I) _ck_u(12,I) +#define _u13(I) _ck_u(13,I) +#define _u14(I) _ck_u(14,I) +#define _u15(I) _ck_u(15,I) +#define _u16(I) _ck_u(16,I) +#define _u17(I) _ck_u(17,I) +#define _u18(I) _ck_u(18,I) +#define _u19(I) _ck_u(19,I) +#define _u20(I) _ck_u(20,I) +#define _u21(I) _ck_u(21,I) +#define _u22(I) _ck_u(22,I) +#define _u23(I) _ck_u(23,I) +#define _u24(I) _ck_u(24,I) +#define _u25(I) _ck_u(25,I) +#define _u26(I) _ck_u(26,I) +#define _u27(I) _ck_u(27,I) +#define _u28(I) _ck_u(28,I) +#define _u29(I) _ck_u(29,I) +#define _u30(I) _ck_u(30,I) +#define _u31(I) _ck_u(31,I) + +/* ========================================================================= */ +/* --- ASSEMBLER ----------------------------------------------------------- */ +/* ========================================================================= */ + +#define _b00 0 +#define _b01 1 +#define _b10 2 +#define _b11 3 + +#define _b000 0 +#define _b001 1 +#define _b010 2 +#define _b011 3 +#define _b100 4 +#define _b101 5 +#define _b110 6 +#define _b111 7 + +#define _OFF4(D) (_UL(D) - _UL(x86_get_target())) +#define _CKD8(D) _ck_d(8, ((_uc) _OFF4(D)) ) + +#define _D8(D) (_B(0), ((*(_PUC(x86_get_target())-1))= _CKD8(D))) +#define _D32(D) (_L(0), ((*(_PUL(x86_get_target())-1))= _OFF4(D))) + +#ifndef _ASM_SAFETY +# define _M(M) (M) +# define _r(R) (R) +# define _m(M) (M) +# define _s(S) (S) +# define _i(I) (I) +# define _b(B) (B) +#else +# define _M(M) (((M)>3) ? x86_emit_failure0("internal error: mod = " #M) : (M)) +# define _r(R) (((R)>7) ? x86_emit_failure0("internal error: reg = " #R) : (R)) +# define _m(M) (((M)>7) ? x86_emit_failure0("internal error: r/m = " #M) : (M)) +# define _s(S) (((S)>3) ? x86_emit_failure0("internal error: memory scale = " #S) : (S)) +# define _i(I) (((I)>7) ? x86_emit_failure0("internal error: memory index = " #I) : (I)) +# define _b(B) (((B)>7) ? x86_emit_failure0("internal error: memory base = " #B) : (B)) +#endif + +#define _Mrm(Md,R,M) _B((_M(Md)<<6)|(_r(R)<<3)|_m(M)) +#define _SIB(Sc,I, B) _B((_s(Sc)<<6)|(_i(I)<<3)|_b(B)) + +#define _SCL(S) ((((S)==1) ? _b00 : \ + (((S)==2) ? _b01 : \ + (((S)==4) ? _b10 : \ + (((S)==8) ? _b11 : x86_emit_failure0("illegal scale: " #S)))))) + + +/* --- Memory subformats - urgh! ------------------------------------------- */ + +/* _r_D() is RIP addressing mode if X86_TARGET_64BIT, use _r_DSIB() instead */ +#define _r_D( R, D ) (_Mrm(_b00,_rN(R),_b101 ) ,_L((long)(D))) +#define _r_DSIB(R, D ) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(1),_b100 ,_b101 ),_L((long)(D))) +#define _r_0B( R, B ) (_Mrm(_b00,_rN(R),_rA(B)) ) +#define _r_0BIS(R, B,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)) ) +#define _r_1B( R, D,B ) (_Mrm(_b01,_rN(R),_rA(B)) ,_B((long)(D))) +#define _r_1BIS(R, D,B,I,S) (_Mrm(_b01,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_B((long)(D))) +#define _r_4B( R, D,B ) (_Mrm(_b10,_rN(R),_rA(B)) ,_L((long)(D))) +#define _r_4IS( R, D,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_b101 ),_L((long)(D))) +#define _r_4BIS(R, D,B,I,S) (_Mrm(_b10,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_L((long)(D))) + +#define _r_DB( R, D,B ) ((_s0P(D) && (!_rbp13P(B)) ? _r_0B (R, B ) : (_s8P(D) ? _r_1B( R,D,B ) : _r_4B( R,D,B )))) +#define _r_DBIS(R, D,B,I,S) ((_s0P(D) && (!_rbp13P(B)) ? _r_0BIS(R, B,I,S) : (_s8P(D) ? _r_1BIS(R,D,B,I,S) : _r_4BIS(R,D,B,I,S)))) + +/* Use RIP-addressing in 64-bit mode, if possible */ +#define _x86_RIP_addressing_possible(D,O) (X86_RIP_RELATIVE_ADDR && \ + ((uintptr)x86_get_target() + 4 + (O) - (D) <= 0xffffffff)) + +#define _r_X( R, D,B,I,S,O) (_r0P(I) ? (_r0P(B) ? (!X86_TARGET_64BIT ? _r_D(R,D) : \ + (_x86_RIP_addressing_possible(D, O) ? \ + _r_D(R, (D) - ((uintptr)x86_get_target() + 4 + (O))) : \ + _r_DSIB(R,D))) : \ + (_rIP(B) ? _r_D (R,D ) : \ + (_rsp12P(B) ? _r_DBIS(R,D,_rSP(),_rSP(),1) : \ + _r_DB (R,D, B )))) : \ + (_r0P(B) ? _r_4IS (R,D, I,S) : \ + (!_rspP(I) ? _r_DBIS(R,D, B, I,S) : \ + x86_emit_failure("illegal index register: %esp")))) + + +/* --- Instruction formats ------------------------------------------------- */ + +#define _m32only(X) (! X86_TARGET_64BIT ? X : x86_emit_failure("invalid instruction in 64-bit mode")) +#define _m64only(X) ( X86_TARGET_64BIT ? X : x86_emit_failure("invalid instruction in 32-bit mode")) +#define _m64(X) ( X86_TARGET_64BIT ? X : ((void)0) ) + +/* _format Opcd ModR/M dN(rB,rI,Sc) imm... */ + +#define _d16() ( _B(0x66 ) ) +#define _O( OP ) ( _B( OP ) ) +#define _Or( OP,R ) ( _B( (OP)|_r(R)) ) +#define _OO( OP ) ( _B((OP)>>8), _B( (uae_u8)(OP) ) ) +#define _OOr( OP,R ) ( _B((OP)>>8), _B( (OP)|_r(R)) ) +#define _Os( OP,B ) ( _s8P(B) ? _B(((OP)|_b10)) : _B(OP) ) +#define _sW( W ) ( _s8P(W) ? _B(W):_W(W) ) +#define _sL( L ) ( _s8P(L) ? _B(L):_L(L) ) +#define _sWO( W ) ( _s8P(W) ? 1 : 2 ) +#define _sLO( L ) ( _s8P(L) ? 1 : 4 ) +#define _O_B( OP ,B ) ( _O ( OP ) ,_B(B) ) +#define _O_W( OP ,W ) ( _O ( OP ) ,_W(W) ) +#define _O_L( OP ,L ) ( _O ( OP ) ,_L(L) ) +#define _O_D8( OP ,D ) ( _O ( OP ) ,_D8(D) ) +#define _O_D32( OP ,D ) ( _O ( OP ) ,_D32(D) ) +#define _OO_D32( OP ,D ) ( _OO ( OP ) ,_D32(D) ) +#define _Os_sW( OP ,W ) ( _Os ( OP,W) ,_sW(W) ) +#define _Os_sL( OP ,L ) ( _Os ( OP,L) ,_sL(L) ) +#define _O_W_B( OP ,W,B) ( _O ( OP ) ,_W(W),_B(B)) +#define _Or_B( OP,R ,B ) ( _Or ( OP,R) ,_B(B) ) +#define _Or_W( OP,R ,W ) ( _Or ( OP,R) ,_W(W) ) +#define _Or_L( OP,R ,L ) ( _Or ( OP,R) ,_L(L) ) +#define _Or_Q( OP,R ,Q ) ( _Or ( OP,R) ,_Q(Q) ) +#define _O_Mrm( OP ,MO,R,M ) ( _O ( OP ),_Mrm(MO,R,M ) ) +#define _OO_Mrm( OP ,MO,R,M ) ( _OO ( OP ),_Mrm(MO,R,M ) ) +#define _O_Mrm_B( OP ,MO,R,M ,B ) ( _O ( OP ),_Mrm(MO,R,M ) ,_B(B) ) +#define _O_Mrm_W( OP ,MO,R,M ,W ) ( _O ( OP ),_Mrm(MO,R,M ) ,_W(W) ) +#define _O_Mrm_L( OP ,MO,R,M ,L ) ( _O ( OP ),_Mrm(MO,R,M ) ,_L(L) ) +#define _OO_Mrm_B( OP ,MO,R,M ,B ) ( _OO ( OP ),_Mrm(MO,R,M ) ,_B(B) ) +#define _Os_Mrm_sW(OP ,MO,R,M ,W ) ( _Os ( OP,W),_Mrm(MO,R,M ),_sW(W) ) +#define _Os_Mrm_sL(OP ,MO,R,M ,L ) ( _Os ( OP,L),_Mrm(MO,R,M ),_sL(L) ) +#define _O_r_X( OP ,R ,MD,MB,MI,MS ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,0) ) +#define _OO_r_X( OP ,R ,MD,MB,MI,MS ) ( _OO ( OP ),_r_X( R ,MD,MB,MI,MS,0) ) +#define _O_r_X_B( OP ,R ,MD,MB,MI,MS,B ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,1) ,_B(B) ) +#define _O_r_X_W( OP ,R ,MD,MB,MI,MS,W ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,2) ,_W(W) ) +#define _O_r_X_L( OP ,R ,MD,MB,MI,MS,L ) ( _O ( OP ),_r_X( R ,MD,MB,MI,MS,4) ,_L(L) ) +#define _OO_r_X_B( OP ,R ,MD,MB,MI,MS,B ) ( _OO ( OP ),_r_X( R ,MD,MB,MI,MS,1) ,_B(B) ) +#define _Os_r_X_sW(OP ,R ,MD,MB,MI,MS,W ) ( _Os ( OP,W),_r_X( R ,MD,MB,MI,MS,_sWO(W)),_sW(W)) +#define _Os_r_X_sL(OP ,R ,MD,MB,MI,MS,L ) ( _Os ( OP,L),_r_X( R ,MD,MB,MI,MS,_sLO(L)),_sL(L)) +#define _O_X_B( OP ,MD,MB,MI,MS,B ) ( _O_r_X_B( OP ,0 ,MD,MB,MI,MS ,B) ) +#define _O_X_W( OP ,MD,MB,MI,MS,W ) ( _O_r_X_W( OP ,0 ,MD,MB,MI,MS ,W) ) +#define _O_X_L( OP ,MD,MB,MI,MS,L ) ( _O_r_X_L( OP ,0 ,MD,MB,MI,MS ,L) ) + + +/* --- REX prefixes -------------------------------------------------------- */ + +#undef _VOID + +#define _VOID() ((void)0) +#define _BIT(X) (!!(X)) +#define _d64(W,R,X,B) (_B(0x40|(W)<<3|(R)<<2|(X)<<1|(B))) + +#define __REXwrxb(L,W,R,X,B) ((W|R|X|B) || (L) ? _d64(W,R,X,B) : _VOID()) +#define __REXwrx_(L,W,R,X,MR) (__REXwrxb(L,W,R,X,_BIT(_rIP(MR)?0:_rXP(MR)))) +#define __REXw_x_(L,W,R,X,MR) (__REXwrx_(L,W,_BIT(_rXP(R)),X,MR)) +#define __REX_reg(RR) (__REXwrxb(0,0,0,00,_BIT(_rXP(RR)))) +#define __REX_mem(MB,MI) (__REXwrxb(0,0,0,_BIT(_rXP(MI)),_BIT(_rXP(MB)))) + +// FIXME: can't mix new (SPL,BPL,SIL,DIL) with (AH,BH,CH,DH) +#define _REXBrr(RR,MR) _m64(__REXw_x_(_r1e8lP(RR)||_r1e8lP(MR),0,RR,0,MR)) +#define _REXBmr(MB,MI,RD) _m64(__REXw_x_(_r1e8lP(RD)||_r1e8lP(MB),0,RD,_BIT(_rXP(MI)),MB)) +#define _REXBrm(RS,MB,MI) _REXBmr(MB,MI,RS) + +#define _REXBLrr(RR,MR) _m64(__REXw_x_(_r1e8lP(MR),0,RR,0,MR)) +#define _REXLrr(RR,MR) _m64(__REXw_x_(0,0,RR,0,MR)) +#define _REXLmr(MB,MI,RD) _m64(__REXw_x_(0,0,RD,_BIT(_rXP(MI)),MB)) +#define _REXLrm(RS,MB,MI) _REXLmr(MB,MI,RS) +#define _REXLr(RR) _m64(__REX_reg(RR)) +#define _REXLm(MB,MI) _m64(__REX_mem(MB,MI)) + +#define _REXQrr(RR,MR) _m64only(__REXw_x_(0,1,RR,0,MR)) +#define _REXQmr(MB,MI,RD) _m64only(__REXw_x_(0,1,RD,_BIT(_rXP(MI)),MB)) +#define _REXQrm(RS,MB,MI) _REXQmr(MB,MI,RS) +#define _REXQr(RR) _m64only(__REX_reg(RR)) +#define _REXQm(MB,MI) _m64only(__REX_mem(MB,MI)) + + +/* ========================================================================= */ +/* --- Fully-qualified intrinsic instructions ------------------------------ */ +/* ========================================================================= */ + +/* OPCODE + i = immediate operand + * + r = register operand + * + m = memory operand (disp,base,index,scale) + * + sr/sm = a star preceding a register or memory + * + 0 = top of stack register (for FPU instructions) + * + * NOTE in x86-64 mode: a memory operand with only a valid + * displacement value will lead to the expect absolute mode. If + * RIP addressing is necessary, X86_RIP shall be used as the base + * register argument. + */ + +/* --- ALU instructions ---------------------------------------------------- */ + +enum { + X86_ADD = 0, + X86_OR = 1, + X86_ADC = 2, + X86_SBB = 3, + X86_AND = 4, + X86_SUB = 5, + X86_XOR = 6, + X86_CMP = 7, +}; + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define _ALUBrr(OP,RS, RD) (_REXBrr(RS, RD), _O_Mrm (((OP) << 3) ,_b11,_r1(RS),_r1(RD) )) +#define _ALUBmr(OP, MD, MB, MI, MS, RD) (_REXBmr(MB, MI, RD), _O_r_X (((OP) << 3) + 2,_r1(RD) ,MD,MB,MI,MS )) +#define _ALUBrm(OP, RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (((OP) << 3) , ,_r1(RS) ,MD,MB,MI,MS )) +#define _ALUBir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AL) ? \ + (_REXBrr(0, RD), _O_B (((OP) << 3) + 4 ,_su8(IM))) : \ + (_REXBrr(0, RD), _O_Mrm_B (0x80 ,_b11,OP ,_r1(RD) ,_su8(IM))) ) +#define _ALUBim(OP, IM, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X_B (0x80 ,OP ,MD,MB,MI,MS ,_su8(IM))) + +#define _ALUWrr(OP, RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (((OP) << 3) + 1,_b11,_r2(RS),_r2(RD) )) +#define _ALUWmr(OP, MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _O_r_X (((OP) << 3) + 3 ,_r2(RD) ,MD,MB,MI,MS )) +#define _ALUWrm(OP, RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (((OP) << 3) + 1 ,_r2(RS) ,MD,MB,MI,MS )) +#define _ALUWir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AX) ? \ + (_d16(), _REXLrr(0, RD), _O_W (((OP) << 3) + 5 ,_su16(IM))) : \ + (_d16(), _REXLrr(0, RD), _Os_Mrm_sW (0x81 ,_b11,OP ,_r2(RD) ,_su16(IM))) ) +#define _ALUWim(OP, IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _Os_r_X_sW (0x81 ,OP ,MD,MB,MI,MS ,_su16(IM))) + +#define _ALULrr(OP, RS, RD) (_REXLrr(RS, RD), _O_Mrm (((OP) << 3) + 1,_b11,_r4(RS),_r4(RD) )) +#define _ALULmr(OP, MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (((OP) << 3) + 3 ,_r4(RD) ,MD,MB,MI,MS )) +#define _ALULrm(OP, RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (((OP) << 3) + 1 ,_r4(RS) ,MD,MB,MI,MS )) +#define _ALULir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_EAX) ? \ + (_REXLrr(0, RD), _O_L (((OP) << 3) + 5 ,IM )) : \ + (_REXLrr(0, RD), _Os_Mrm_sL (0x81 ,_b11,OP ,_r4(RD) ,IM )) ) +#define _ALULim(OP, IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _Os_r_X_sL (0x81 ,OP ,MD,MB,MI,MS ,IM )) + +#define _ALUQrr(OP, RS, RD) (_REXQrr(RS, RD), _O_Mrm (((OP) << 3) + 1,_b11,_r8(RS),_r8(RD) )) +#define _ALUQmr(OP, MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (((OP) << 3) + 3 ,_r8(RD) ,MD,MB,MI,MS )) +#define _ALUQrm(OP, RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (((OP) << 3) + 1 ,_r8(RS) ,MD,MB,MI,MS )) +#define _ALUQir(OP, IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_RAX) ? \ + (_REXQrr(0, RD), _O_L (((OP) << 3) + 5 ,IM )) : \ + (_REXQrr(0, RD), _Os_Mrm_sL (0x81 ,_b11,OP ,_r8(RD) ,IM )) ) +#define _ALUQim(OP, IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _Os_r_X_sL (0x81 ,OP ,MD,MB,MI,MS ,IM )) + +#define ADCBrr(RS, RD) _ALUBrr(X86_ADC, RS, RD) +#define ADCBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_ADC, MD, MB, MI, MS, RD) +#define ADCBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_ADC, RS, MD, MB, MI, MS) +#define ADCBir(IM, RD) _ALUBir(X86_ADC, IM, RD) +#define ADCBim(IM, MD, MB, MI, MS) _ALUBim(X86_ADC, IM, MD, MB, MI, MS) + +#define ADCWrr(RS, RD) _ALUWrr(X86_ADC, RS, RD) +#define ADCWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_ADC, MD, MB, MI, MS, RD) +#define ADCWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_ADC, RS, MD, MB, MI, MS) +#define ADCWir(IM, RD) _ALUWir(X86_ADC, IM, RD) +#define ADCWim(IM, MD, MB, MI, MS) _ALUWim(X86_ADC, IM, MD, MB, MI, MS) + +#define ADCLrr(RS, RD) _ALULrr(X86_ADC, RS, RD) +#define ADCLmr(MD, MB, MI, MS, RD) _ALULmr(X86_ADC, MD, MB, MI, MS, RD) +#define ADCLrm(RS, MD, MB, MI, MS) _ALULrm(X86_ADC, RS, MD, MB, MI, MS) +#define ADCLir(IM, RD) _ALULir(X86_ADC, IM, RD) +#define ADCLim(IM, MD, MB, MI, MS) _ALULim(X86_ADC, IM, MD, MB, MI, MS) + +#define ADCQrr(RS, RD) _ALUQrr(X86_ADC, RS, RD) +#define ADCQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_ADC, MD, MB, MI, MS, RD) +#define ADCQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_ADC, RS, MD, MB, MI, MS) +#define ADCQir(IM, RD) _ALUQir(X86_ADC, IM, RD) +#define ADCQim(IM, MD, MB, MI, MS) _ALUQim(X86_ADC, IM, MD, MB, MI, MS) + +#define ADDBrr(RS, RD) _ALUBrr(X86_ADD, RS, RD) +#define ADDBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_ADD, MD, MB, MI, MS, RD) +#define ADDBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_ADD, RS, MD, MB, MI, MS) +#define ADDBir(IM, RD) _ALUBir(X86_ADD, IM, RD) +#define ADDBim(IM, MD, MB, MI, MS) _ALUBim(X86_ADD, IM, MD, MB, MI, MS) + +#define ADDWrr(RS, RD) _ALUWrr(X86_ADD, RS, RD) +#define ADDWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_ADD, MD, MB, MI, MS, RD) +#define ADDWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_ADD, RS, MD, MB, MI, MS) +#define ADDWir(IM, RD) _ALUWir(X86_ADD, IM, RD) +#define ADDWim(IM, MD, MB, MI, MS) _ALUWim(X86_ADD, IM, MD, MB, MI, MS) + +#define ADDLrr(RS, RD) _ALULrr(X86_ADD, RS, RD) +#define ADDLmr(MD, MB, MI, MS, RD) _ALULmr(X86_ADD, MD, MB, MI, MS, RD) +#define ADDLrm(RS, MD, MB, MI, MS) _ALULrm(X86_ADD, RS, MD, MB, MI, MS) +#define ADDLir(IM, RD) _ALULir(X86_ADD, IM, RD) +#define ADDLim(IM, MD, MB, MI, MS) _ALULim(X86_ADD, IM, MD, MB, MI, MS) + +#define ADDQrr(RS, RD) _ALUQrr(X86_ADD, RS, RD) +#define ADDQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_ADD, MD, MB, MI, MS, RD) +#define ADDQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_ADD, RS, MD, MB, MI, MS) +#define ADDQir(IM, RD) _ALUQir(X86_ADD, IM, RD) +#define ADDQim(IM, MD, MB, MI, MS) _ALUQim(X86_ADD, IM, MD, MB, MI, MS) + +#define ANDBrr(RS, RD) _ALUBrr(X86_AND, RS, RD) +#define ANDBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_AND, MD, MB, MI, MS, RD) +#define ANDBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_AND, RS, MD, MB, MI, MS) +#define ANDBir(IM, RD) _ALUBir(X86_AND, IM, RD) +#define ANDBim(IM, MD, MB, MI, MS) _ALUBim(X86_AND, IM, MD, MB, MI, MS) + +#define ANDWrr(RS, RD) _ALUWrr(X86_AND, RS, RD) +#define ANDWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_AND, MD, MB, MI, MS, RD) +#define ANDWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_AND, RS, MD, MB, MI, MS) +#define ANDWir(IM, RD) _ALUWir(X86_AND, IM, RD) +#define ANDWim(IM, MD, MB, MI, MS) _ALUWim(X86_AND, IM, MD, MB, MI, MS) + +#define ANDLrr(RS, RD) _ALULrr(X86_AND, RS, RD) +#define ANDLmr(MD, MB, MI, MS, RD) _ALULmr(X86_AND, MD, MB, MI, MS, RD) +#define ANDLrm(RS, MD, MB, MI, MS) _ALULrm(X86_AND, RS, MD, MB, MI, MS) +#define ANDLir(IM, RD) _ALULir(X86_AND, IM, RD) +#define ANDLim(IM, MD, MB, MI, MS) _ALULim(X86_AND, IM, MD, MB, MI, MS) + +#define ANDQrr(RS, RD) _ALUQrr(X86_AND, RS, RD) +#define ANDQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_AND, MD, MB, MI, MS, RD) +#define ANDQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_AND, RS, MD, MB, MI, MS) +#define ANDQir(IM, RD) _ALUQir(X86_AND, IM, RD) +#define ANDQim(IM, MD, MB, MI, MS) _ALUQim(X86_AND, IM, MD, MB, MI, MS) + +#define CMPBrr(RS, RD) _ALUBrr(X86_CMP, RS, RD) +#define CMPBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_CMP, MD, MB, MI, MS, RD) +#define CMPBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_CMP, RS, MD, MB, MI, MS) +#define CMPBir(IM, RD) _ALUBir(X86_CMP, IM, RD) +#define CMPBim(IM, MD, MB, MI, MS) _ALUBim(X86_CMP, IM, MD, MB, MI, MS) + +#define CMPWrr(RS, RD) _ALUWrr(X86_CMP, RS, RD) +#define CMPWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_CMP, MD, MB, MI, MS, RD) +#define CMPWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_CMP, RS, MD, MB, MI, MS) +#define CMPWir(IM, RD) _ALUWir(X86_CMP, IM, RD) +#define CMPWim(IM, MD, MB, MI, MS) _ALUWim(X86_CMP, IM, MD, MB, MI, MS) + +#define CMPLrr(RS, RD) _ALULrr(X86_CMP, RS, RD) +#define CMPLmr(MD, MB, MI, MS, RD) _ALULmr(X86_CMP, MD, MB, MI, MS, RD) +#define CMPLrm(RS, MD, MB, MI, MS) _ALULrm(X86_CMP, RS, MD, MB, MI, MS) +#define CMPLir(IM, RD) _ALULir(X86_CMP, IM, RD) +#define CMPLim(IM, MD, MB, MI, MS) _ALULim(X86_CMP, IM, MD, MB, MI, MS) + +#define CMPQrr(RS, RD) _ALUQrr(X86_CMP, RS, RD) +#define CMPQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_CMP, MD, MB, MI, MS, RD) +#define CMPQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_CMP, RS, MD, MB, MI, MS) +#define CMPQir(IM, RD) _ALUQir(X86_CMP, IM, RD) +#define CMPQim(IM, MD, MB, MI, MS) _ALUQim(X86_CMP, IM, MD, MB, MI, MS) + +#define ORBrr(RS, RD) _ALUBrr(X86_OR, RS, RD) +#define ORBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_OR, MD, MB, MI, MS, RD) +#define ORBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_OR, RS, MD, MB, MI, MS) +#define ORBir(IM, RD) _ALUBir(X86_OR, IM, RD) +#define ORBim(IM, MD, MB, MI, MS) _ALUBim(X86_OR, IM, MD, MB, MI, MS) + +#define ORWrr(RS, RD) _ALUWrr(X86_OR, RS, RD) +#define ORWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_OR, MD, MB, MI, MS, RD) +#define ORWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_OR, RS, MD, MB, MI, MS) +#define ORWir(IM, RD) _ALUWir(X86_OR, IM, RD) +#define ORWim(IM, MD, MB, MI, MS) _ALUWim(X86_OR, IM, MD, MB, MI, MS) + +#define ORLrr(RS, RD) _ALULrr(X86_OR, RS, RD) +#define ORLmr(MD, MB, MI, MS, RD) _ALULmr(X86_OR, MD, MB, MI, MS, RD) +#define ORLrm(RS, MD, MB, MI, MS) _ALULrm(X86_OR, RS, MD, MB, MI, MS) +#define ORLir(IM, RD) _ALULir(X86_OR, IM, RD) +#define ORLim(IM, MD, MB, MI, MS) _ALULim(X86_OR, IM, MD, MB, MI, MS) + +#define ORQrr(RS, RD) _ALUQrr(X86_OR, RS, RD) +#define ORQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_OR, MD, MB, MI, MS, RD) +#define ORQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_OR, RS, MD, MB, MI, MS) +#define ORQir(IM, RD) _ALUQir(X86_OR, IM, RD) +#define ORQim(IM, MD, MB, MI, MS) _ALUQim(X86_OR, IM, MD, MB, MI, MS) + +#define SBBBrr(RS, RD) _ALUBrr(X86_SBB, RS, RD) +#define SBBBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_SBB, MD, MB, MI, MS, RD) +#define SBBBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_SBB, RS, MD, MB, MI, MS) +#define SBBBir(IM, RD) _ALUBir(X86_SBB, IM, RD) +#define SBBBim(IM, MD, MB, MI, MS) _ALUBim(X86_SBB, IM, MD, MB, MI, MS) + +#define SBBWrr(RS, RD) _ALUWrr(X86_SBB, RS, RD) +#define SBBWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_SBB, MD, MB, MI, MS, RD) +#define SBBWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_SBB, RS, MD, MB, MI, MS) +#define SBBWir(IM, RD) _ALUWir(X86_SBB, IM, RD) +#define SBBWim(IM, MD, MB, MI, MS) _ALUWim(X86_SBB, IM, MD, MB, MI, MS) + +#define SBBLrr(RS, RD) _ALULrr(X86_SBB, RS, RD) +#define SBBLmr(MD, MB, MI, MS, RD) _ALULmr(X86_SBB, MD, MB, MI, MS, RD) +#define SBBLrm(RS, MD, MB, MI, MS) _ALULrm(X86_SBB, RS, MD, MB, MI, MS) +#define SBBLir(IM, RD) _ALULir(X86_SBB, IM, RD) +#define SBBLim(IM, MD, MB, MI, MS) _ALULim(X86_SBB, IM, MD, MB, MI, MS) + +#define SBBQrr(RS, RD) _ALUQrr(X86_SBB, RS, RD) +#define SBBQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_SBB, MD, MB, MI, MS, RD) +#define SBBQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_SBB, RS, MD, MB, MI, MS) +#define SBBQir(IM, RD) _ALUQir(X86_SBB, IM, RD) +#define SBBQim(IM, MD, MB, MI, MS) _ALUQim(X86_SBB, IM, MD, MB, MI, MS) + +#define SUBBrr(RS, RD) _ALUBrr(X86_SUB, RS, RD) +#define SUBBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_SUB, MD, MB, MI, MS, RD) +#define SUBBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_SUB, RS, MD, MB, MI, MS) +#define SUBBir(IM, RD) _ALUBir(X86_SUB, IM, RD) +#define SUBBim(IM, MD, MB, MI, MS) _ALUBim(X86_SUB, IM, MD, MB, MI, MS) + +#define SUBWrr(RS, RD) _ALUWrr(X86_SUB, RS, RD) +#define SUBWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_SUB, MD, MB, MI, MS, RD) +#define SUBWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_SUB, RS, MD, MB, MI, MS) +#define SUBWir(IM, RD) _ALUWir(X86_SUB, IM, RD) +#define SUBWim(IM, MD, MB, MI, MS) _ALUWim(X86_SUB, IM, MD, MB, MI, MS) + +#define SUBLrr(RS, RD) _ALULrr(X86_SUB, RS, RD) +#define SUBLmr(MD, MB, MI, MS, RD) _ALULmr(X86_SUB, MD, MB, MI, MS, RD) +#define SUBLrm(RS, MD, MB, MI, MS) _ALULrm(X86_SUB, RS, MD, MB, MI, MS) +#define SUBLir(IM, RD) _ALULir(X86_SUB, IM, RD) +#define SUBLim(IM, MD, MB, MI, MS) _ALULim(X86_SUB, IM, MD, MB, MI, MS) + +#define SUBQrr(RS, RD) _ALUQrr(X86_SUB, RS, RD) +#define SUBQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_SUB, MD, MB, MI, MS, RD) +#define SUBQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_SUB, RS, MD, MB, MI, MS) +#define SUBQir(IM, RD) _ALUQir(X86_SUB, IM, RD) +#define SUBQim(IM, MD, MB, MI, MS) _ALUQim(X86_SUB, IM, MD, MB, MI, MS) + +#define XORBrr(RS, RD) _ALUBrr(X86_XOR, RS, RD) +#define XORBmr(MD, MB, MI, MS, RD) _ALUBmr(X86_XOR, MD, MB, MI, MS, RD) +#define XORBrm(RS, MD, MB, MI, MS) _ALUBrm(X86_XOR, RS, MD, MB, MI, MS) +#define XORBir(IM, RD) _ALUBir(X86_XOR, IM, RD) +#define XORBim(IM, MD, MB, MI, MS) _ALUBim(X86_XOR, IM, MD, MB, MI, MS) + +#define XORWrr(RS, RD) _ALUWrr(X86_XOR, RS, RD) +#define XORWmr(MD, MB, MI, MS, RD) _ALUWmr(X86_XOR, MD, MB, MI, MS, RD) +#define XORWrm(RS, MD, MB, MI, MS) _ALUWrm(X86_XOR, RS, MD, MB, MI, MS) +#define XORWir(IM, RD) _ALUWir(X86_XOR, IM, RD) +#define XORWim(IM, MD, MB, MI, MS) _ALUWim(X86_XOR, IM, MD, MB, MI, MS) + +#define XORLrr(RS, RD) _ALULrr(X86_XOR, RS, RD) +#define XORLmr(MD, MB, MI, MS, RD) _ALULmr(X86_XOR, MD, MB, MI, MS, RD) +#define XORLrm(RS, MD, MB, MI, MS) _ALULrm(X86_XOR, RS, MD, MB, MI, MS) +#define XORLir(IM, RD) _ALULir(X86_XOR, IM, RD) +#define XORLim(IM, MD, MB, MI, MS) _ALULim(X86_XOR, IM, MD, MB, MI, MS) + +#define XORQrr(RS, RD) _ALUQrr(X86_XOR, RS, RD) +#define XORQmr(MD, MB, MI, MS, RD) _ALUQmr(X86_XOR, MD, MB, MI, MS, RD) +#define XORQrm(RS, MD, MB, MI, MS) _ALUQrm(X86_XOR, RS, MD, MB, MI, MS) +#define XORQir(IM, RD) _ALUQir(X86_XOR, IM, RD) +#define XORQim(IM, MD, MB, MI, MS) _ALUQim(X86_XOR, IM, MD, MB, MI, MS) + + +/* --- Shift/Rotate instructions ------------------------------------------- */ + +enum { + X86_ROL = 0, + X86_ROR = 1, + X86_RCL = 2, + X86_RCR = 3, + X86_SHL = 4, + X86_SHR = 5, + X86_SAR = 7, +}; + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define _ROTSHIBir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_REXBrr(0, RD), _O_Mrm (0xd0 ,_b11,OP,_r1(RD) )) : \ + (_REXBrr(0, RD), _O_Mrm_B (0xc0 ,_b11,OP,_r1(RD) ,_u8(IM))) ) +#define _ROTSHIBim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_REXBrm(0, MB, MI), _O_r_X (0xd0 ,OP ,MD,MB,MI,MS )) : \ + (_REXBrm(0, MB, MI), _O_r_X_B (0xc0 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) +#define _ROTSHIBrr(OP,RS,RD) (((RS) == X86_CL) ? \ + (_REXBrr(RS, RD), _O_Mrm (0xd2 ,_b11,OP,_r1(RD) )) : \ + x86_emit_failure("source register must be CL" ) ) +#define _ROTSHIBrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ + (_REXBrm(RS, MB, MI), _O_r_X (0xd2 ,OP ,MD,MB,MI,MS )) : \ + x86_emit_failure("source register must be CL" ) ) + +#define _ROTSHIWir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_d16(), _REXLrr(0, RD), _O_Mrm (0xd1 ,_b11,OP,_r2(RD) )) : \ + (_d16(), _REXLrr(0, RD), _O_Mrm_B (0xc1 ,_b11,OP,_r2(RD) ,_u8(IM))) ) +#define _ROTSHIWim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_d16(), _REXLrm(0, MB, MI), _O_r_X (0xd1 ,OP ,MD,MB,MI,MS )) : \ + (_d16(), _REXLrm(0, MB, MI), _O_r_X_B (0xc1 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) +#define _ROTSHIWrr(OP,RS,RD) (((RS) == X86_CL) ? \ + (_d16(), _REXLrr(RS, RD), _O_Mrm (0xd3 ,_b11,OP,_r2(RD) )) : \ + x86_emit_failure("source register must be CL" ) ) +#define _ROTSHIWrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ + (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0xd3 ,OP ,MD,MB,MI,MS )) : \ + x86_emit_failure("source register must be CL" ) ) + +#define _ROTSHILir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_REXLrr(0, RD), _O_Mrm (0xd1 ,_b11,OP,_r4(RD) )) : \ + (_REXLrr(0, RD), _O_Mrm_B (0xc1 ,_b11,OP,_r4(RD) ,_u8(IM))) ) +#define _ROTSHILim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_REXLrm(0, MB, MI), _O_r_X (0xd1 ,OP ,MD,MB,MI,MS )) : \ + (_REXLrm(0, MB, MI), _O_r_X_B (0xc1 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) +#define _ROTSHILrr(OP,RS,RD) (((RS) == X86_CL) ? \ + (_REXLrr(RS, RD), _O_Mrm (0xd3 ,_b11,OP,_r4(RD) )) : \ + x86_emit_failure("source register must be CL" ) ) +#define _ROTSHILrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ + (_REXLrm(RS, MB, MI), _O_r_X (0xd3 ,OP ,MD,MB,MI,MS )) : \ + x86_emit_failure("source register must be CL" ) ) + +#define _ROTSHIQir(OP,IM,RD) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_REXQrr(0, RD), _O_Mrm (0xd1 ,_b11,OP,_r8(RD) )) : \ + (_REXQrr(0, RD), _O_Mrm_B (0xc1 ,_b11,OP,_r8(RD) ,_u8(IM))) ) +#define _ROTSHIQim(OP,IM,MD,MB,MI,MS) (X86_OPTIMIZE_ROTSHI && ((IM) == 1) ? \ + (_REXQrm(0, MB, MI), _O_r_X (0xd1 ,OP ,MD,MB,MI,MS )) : \ + (_REXQrm(0, MB, MI), _O_r_X_B (0xc1 ,OP ,MD,MB,MI,MS ,_u8(IM))) ) +#define _ROTSHIQrr(OP,RS,RD) (((RS) == X86_CL) ? \ + (_REXQrr(RS, RD), _O_Mrm (0xd3 ,_b11,OP,_r8(RD) )) : \ + x86_emit_failure("source register must be CL" ) ) +#define _ROTSHIQrm(OP,RS,MD,MB,MI,MS) (((RS) == X86_CL) ? \ + (_REXQrm(RS, MB, MI), _O_r_X (0xd3 ,OP ,MD,MB,MI,MS )) : \ + x86_emit_failure("source register must be CL" ) ) + +#define ROLBir(IM, RD) _ROTSHIBir(X86_ROL, IM, RD) +#define ROLBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_ROL, IM, MD, MB, MI, MS) +#define ROLBrr(RS, RD) _ROTSHIBrr(X86_ROL, RS, RD) +#define ROLBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_ROL, RS, MD, MB, MI, MS) + +#define ROLWir(IM, RD) _ROTSHIWir(X86_ROL, IM, RD) +#define ROLWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_ROL, IM, MD, MB, MI, MS) +#define ROLWrr(RS, RD) _ROTSHIWrr(X86_ROL, RS, RD) +#define ROLWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_ROL, RS, MD, MB, MI, MS) + +#define ROLLir(IM, RD) _ROTSHILir(X86_ROL, IM, RD) +#define ROLLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_ROL, IM, MD, MB, MI, MS) +#define ROLLrr(RS, RD) _ROTSHILrr(X86_ROL, RS, RD) +#define ROLLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_ROL, RS, MD, MB, MI, MS) + +#define ROLQir(IM, RD) _ROTSHIQir(X86_ROL, IM, RD) +#define ROLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_ROL, IM, MD, MB, MI, MS) +#define ROLQrr(RS, RD) _ROTSHIQrr(X86_ROL, RS, RD) +#define ROLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_ROL, RS, MD, MB, MI, MS) + +#define RORBir(IM, RD) _ROTSHIBir(X86_ROR, IM, RD) +#define RORBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_ROR, IM, MD, MB, MI, MS) +#define RORBrr(RS, RD) _ROTSHIBrr(X86_ROR, RS, RD) +#define RORBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_ROR, RS, MD, MB, MI, MS) + +#define RORWir(IM, RD) _ROTSHIWir(X86_ROR, IM, RD) +#define RORWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_ROR, IM, MD, MB, MI, MS) +#define RORWrr(RS, RD) _ROTSHIWrr(X86_ROR, RS, RD) +#define RORWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_ROR, RS, MD, MB, MI, MS) + +#define RORLir(IM, RD) _ROTSHILir(X86_ROR, IM, RD) +#define RORLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_ROR, IM, MD, MB, MI, MS) +#define RORLrr(RS, RD) _ROTSHILrr(X86_ROR, RS, RD) +#define RORLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_ROR, RS, MD, MB, MI, MS) + +#define RORQir(IM, RD) _ROTSHIQir(X86_ROR, IM, RD) +#define RORQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_ROR, IM, MD, MB, MI, MS) +#define RORQrr(RS, RD) _ROTSHIQrr(X86_ROR, RS, RD) +#define RORQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_ROR, RS, MD, MB, MI, MS) + +#define RCLBir(IM, RD) _ROTSHIBir(X86_RCL, IM, RD) +#define RCLBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_RCL, IM, MD, MB, MI, MS) +#define RCLBrr(RS, RD) _ROTSHIBrr(X86_RCL, RS, RD) +#define RCLBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_RCL, RS, MD, MB, MI, MS) + +#define RCLWir(IM, RD) _ROTSHIWir(X86_RCL, IM, RD) +#define RCLWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_RCL, IM, MD, MB, MI, MS) +#define RCLWrr(RS, RD) _ROTSHIWrr(X86_RCL, RS, RD) +#define RCLWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_RCL, RS, MD, MB, MI, MS) + +#define RCLLir(IM, RD) _ROTSHILir(X86_RCL, IM, RD) +#define RCLLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_RCL, IM, MD, MB, MI, MS) +#define RCLLrr(RS, RD) _ROTSHILrr(X86_RCL, RS, RD) +#define RCLLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_RCL, RS, MD, MB, MI, MS) + +#define RCLQir(IM, RD) _ROTSHIQir(X86_RCL, IM, RD) +#define RCLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_RCL, IM, MD, MB, MI, MS) +#define RCLQrr(RS, RD) _ROTSHIQrr(X86_RCL, RS, RD) +#define RCLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_RCL, RS, MD, MB, MI, MS) + +#define RCRBir(IM, RD) _ROTSHIBir(X86_RCR, IM, RD) +#define RCRBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_RCR, IM, MD, MB, MI, MS) +#define RCRBrr(RS, RD) _ROTSHIBrr(X86_RCR, RS, RD) +#define RCRBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_RCR, RS, MD, MB, MI, MS) + +#define RCRWir(IM, RD) _ROTSHIWir(X86_RCR, IM, RD) +#define RCRWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_RCR, IM, MD, MB, MI, MS) +#define RCRWrr(RS, RD) _ROTSHIWrr(X86_RCR, RS, RD) +#define RCRWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_RCR, RS, MD, MB, MI, MS) + +#define RCRLir(IM, RD) _ROTSHILir(X86_RCR, IM, RD) +#define RCRLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_RCR, IM, MD, MB, MI, MS) +#define RCRLrr(RS, RD) _ROTSHILrr(X86_RCR, RS, RD) +#define RCRLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_RCR, RS, MD, MB, MI, MS) + +#define RCRQir(IM, RD) _ROTSHIQir(X86_RCR, IM, RD) +#define RCRQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_RCR, IM, MD, MB, MI, MS) +#define RCRQrr(RS, RD) _ROTSHIQrr(X86_RCR, RS, RD) +#define RCRQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_RCR, RS, MD, MB, MI, MS) + +#define SHLBir(IM, RD) _ROTSHIBir(X86_SHL, IM, RD) +#define SHLBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_SHL, IM, MD, MB, MI, MS) +#define SHLBrr(RS, RD) _ROTSHIBrr(X86_SHL, RS, RD) +#define SHLBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_SHL, RS, MD, MB, MI, MS) + +#define SHLWir(IM, RD) _ROTSHIWir(X86_SHL, IM, RD) +#define SHLWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_SHL, IM, MD, MB, MI, MS) +#define SHLWrr(RS, RD) _ROTSHIWrr(X86_SHL, RS, RD) +#define SHLWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_SHL, RS, MD, MB, MI, MS) + +#define SHLLir(IM, RD) _ROTSHILir(X86_SHL, IM, RD) +#define SHLLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_SHL, IM, MD, MB, MI, MS) +#define SHLLrr(RS, RD) _ROTSHILrr(X86_SHL, RS, RD) +#define SHLLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_SHL, RS, MD, MB, MI, MS) + +#define SHLQir(IM, RD) _ROTSHIQir(X86_SHL, IM, RD) +#define SHLQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SHL, IM, MD, MB, MI, MS) +#define SHLQrr(RS, RD) _ROTSHIQrr(X86_SHL, RS, RD) +#define SHLQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SHL, RS, MD, MB, MI, MS) + +#define SHRBir(IM, RD) _ROTSHIBir(X86_SHR, IM, RD) +#define SHRBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_SHR, IM, MD, MB, MI, MS) +#define SHRBrr(RS, RD) _ROTSHIBrr(X86_SHR, RS, RD) +#define SHRBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_SHR, RS, MD, MB, MI, MS) + +#define SHRWir(IM, RD) _ROTSHIWir(X86_SHR, IM, RD) +#define SHRWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_SHR, IM, MD, MB, MI, MS) +#define SHRWrr(RS, RD) _ROTSHIWrr(X86_SHR, RS, RD) +#define SHRWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_SHR, RS, MD, MB, MI, MS) + +#define SHRLir(IM, RD) _ROTSHILir(X86_SHR, IM, RD) +#define SHRLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_SHR, IM, MD, MB, MI, MS) +#define SHRLrr(RS, RD) _ROTSHILrr(X86_SHR, RS, RD) +#define SHRLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_SHR, RS, MD, MB, MI, MS) + +#define SHRQir(IM, RD) _ROTSHIQir(X86_SHR, IM, RD) +#define SHRQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SHR, IM, MD, MB, MI, MS) +#define SHRQrr(RS, RD) _ROTSHIQrr(X86_SHR, RS, RD) +#define SHRQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SHR, RS, MD, MB, MI, MS) + +#define SALBir SHLBir +#define SALBim SHLBim +#define SALBrr SHLBrr +#define SALBrm SHLBrm + +#define SALWir SHLWir +#define SALWim SHLWim +#define SALWrr SHLWrr +#define SALWrm SHLWrm + +#define SALLir SHLLir +#define SALLim SHLLim +#define SALLrr SHLLrr +#define SALLrm SHLLrm + +#define SALQir SHLQir +#define SALQim SHLQim +#define SALQrr SHLQrr +#define SALQrm SHLQrm + +#define SARBir(IM, RD) _ROTSHIBir(X86_SAR, IM, RD) +#define SARBim(IM, MD, MB, MI, MS) _ROTSHIBim(X86_SAR, IM, MD, MB, MI, MS) +#define SARBrr(RS, RD) _ROTSHIBrr(X86_SAR, RS, RD) +#define SARBrm(RS, MD, MB, MI, MS) _ROTSHIBrm(X86_SAR, RS, MD, MB, MI, MS) + +#define SARWir(IM, RD) _ROTSHIWir(X86_SAR, IM, RD) +#define SARWim(IM, MD, MB, MI, MS) _ROTSHIWim(X86_SAR, IM, MD, MB, MI, MS) +#define SARWrr(RS, RD) _ROTSHIWrr(X86_SAR, RS, RD) +#define SARWrm(RS, MD, MB, MI, MS) _ROTSHIWrm(X86_SAR, RS, MD, MB, MI, MS) + +#define SARLir(IM, RD) _ROTSHILir(X86_SAR, IM, RD) +#define SARLim(IM, MD, MB, MI, MS) _ROTSHILim(X86_SAR, IM, MD, MB, MI, MS) +#define SARLrr(RS, RD) _ROTSHILrr(X86_SAR, RS, RD) +#define SARLrm(RS, MD, MB, MI, MS) _ROTSHILrm(X86_SAR, RS, MD, MB, MI, MS) + +#define SARQir(IM, RD) _ROTSHIQir(X86_SAR, IM, RD) +#define SARQim(IM, MD, MB, MI, MS) _ROTSHIQim(X86_SAR, IM, MD, MB, MI, MS) +#define SARQrr(RS, RD) _ROTSHIQrr(X86_SAR, RS, RD) +#define SARQrm(RS, MD, MB, MI, MS) _ROTSHIQrm(X86_SAR, RS, MD, MB, MI, MS) + + +/* --- Bit test instructions ----------------------------------------------- */ + +enum { + X86_BT = 4, + X86_BTS = 5, + X86_BTR = 6, + X86_BTC = 7, +}; + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define _BTWir(OP, IM, RD) (_d16(), _REXLrr(0, RD), _OO_Mrm_B (0x0fba ,_b11,OP ,_r2(RD) ,_u8(IM))) +#define _BTWim(OP, IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _OO_r_X_B (0x0fba ,OP ,MD,MB,MI,MS ,_u8(IM))) +#define _BTWrr(OP, RS, RD) (_d16(), _REXLrr(RS, RD), _OO_Mrm (0x0f83|((OP)<<3),_b11,_r2(RS),_r2(RD) )) +#define _BTWrm(OP, RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _OO_r_X (0x0f83|((OP)<<3) ,_r2(RS) ,MD,MB,MI,MS )) + +#define _BTLir(OP, IM, RD) (_REXLrr(0, RD), _OO_Mrm_B (0x0fba ,_b11,OP ,_r4(RD) ,_u8(IM))) +#define _BTLim(OP, IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _OO_r_X_B (0x0fba ,OP ,MD,MB,MI,MS ,_u8(IM))) +#define _BTLrr(OP, RS, RD) (_REXLrr(RS, RD), _OO_Mrm (0x0f83|((OP)<<3),_b11,_r4(RS),_r4(RD) )) +#define _BTLrm(OP, RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0f83|((OP)<<3) ,_r4(RS) ,MD,MB,MI,MS )) + +#define _BTQir(OP, IM, RD) (_REXQrr(0, RD), _OO_Mrm_B (0x0fba ,_b11,OP ,_r8(RD) ,_u8(IM))) +#define _BTQim(OP, IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _OO_r_X_B (0x0fba ,OP ,MD,MB,MI,MS ,_u8(IM))) +#define _BTQrr(OP, RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0f83|((OP)<<3),_b11,_r8(RS),_r8(RD) )) +#define _BTQrm(OP, RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f83|((OP)<<3) ,_r8(RS) ,MD,MB,MI,MS )) + +#define BTWir(IM, RD) _BTWir(X86_BT, IM, RD) +#define BTWim(IM, MD, MB, MI, MS) _BTWim(X86_BT, IM, MD, MI, MS) +#define BTWrr(RS, RD) _BTWrr(X86_BT, RS, RD) +#define BTWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BT, RS, MD, MB, MI, MS) + +#define BTLir(IM, RD) _BTLir(X86_BT, IM, RD) +#define BTLim(IM, MD, MB, MI, MS) _BTLim(X86_BT, IM, MD, MB, MI, MS) +#define BTLrr(RS, RD) _BTLrr(X86_BT, RS, RD) +#define BTLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BT, RS, MD, MB, MI, MS) + +#define BTQir(IM, RD) _BTQir(X86_BT, IM, RD) +#define BTQim(IM, MD, MB, MI, MS) _BTQim(X86_BT, IM, MD, MB, MI, MS) +#define BTQrr(RS, RD) _BTQrr(X86_BT, RS, RD) +#define BTQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BT, RS, MD, MB, MI, MS) + +#define BTCWir(IM, RD) _BTWir(X86_BTC, IM, RD) +#define BTCWim(IM, MD, MB, MI, MS) _BTWim(X86_BTC, IM, MD, MI, MS) +#define BTCWrr(RS, RD) _BTWrr(X86_BTC, RS, RD) +#define BTCWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BTC, RS, MD, MB, MI, MS) + +#define BTCLir(IM, RD) _BTLir(X86_BTC, IM, RD) +#define BTCLim(IM, MD, MB, MI, MS) _BTLim(X86_BTC, IM, MD, MB, MI, MS) +#define BTCLrr(RS, RD) _BTLrr(X86_BTC, RS, RD) +#define BTCLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BTC, RS, MD, MB, MI, MS) + +#define BTCQir(IM, RD) _BTQir(X86_BTC, IM, RD) +#define BTCQim(IM, MD, MB, MI, MS) _BTQim(X86_BTC, IM, MD, MB, MI, MS) +#define BTCQrr(RS, RD) _BTQrr(X86_BTC, RS, RD) +#define BTCQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTC, RS, MD, MB, MI, MS) + +#define BTRWir(IM, RD) _BTWir(X86_BTR, IM, RD) +#define BTRWim(IM, MD, MB, MI, MS) _BTWim(X86_BTR, IM, MD, MI, MS) +#define BTRWrr(RS, RD) _BTWrr(X86_BTR, RS, RD) +#define BTRWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BTR, RS, MD, MB, MI, MS) + +#define BTRLir(IM, RD) _BTLir(X86_BTR, IM, RD) +#define BTRLim(IM, MD, MB, MI, MS) _BTLim(X86_BTR, IM, MD, MB, MI, MS) +#define BTRLrr(RS, RD) _BTLrr(X86_BTR, RS, RD) +#define BTRLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BTR, RS, MD, MB, MI, MS) + +#define BTRQir(IM, RD) _BTQir(X86_BTR, IM, RD) +#define BTRQim(IM, MD, MB, MI, MS) _BTQim(X86_BTR, IM, MD, MB, MI, MS) +#define BTRQrr(RS, RD) _BTQrr(X86_BTR, RS, RD) +#define BTRQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTR, RS, MD, MB, MI, MS) + +#define BTSWir(IM, RD) _BTWir(X86_BTS, IM, RD) +#define BTSWim(IM, MD, MB, MI, MS) _BTWim(X86_BTS, IM, MD, MI, MS) +#define BTSWrr(RS, RD) _BTWrr(X86_BTS, RS, RD) +#define BTSWrm(RS, MD, MB, MI, MS) _BTWrm(X86_BTS, RS, MD, MB, MI, MS) + +#define BTSLir(IM, RD) _BTLir(X86_BTS, IM, RD) +#define BTSLim(IM, MD, MB, MI, MS) _BTLim(X86_BTS, IM, MD, MB, MI, MS) +#define BTSLrr(RS, RD) _BTLrr(X86_BTS, RS, RD) +#define BTSLrm(RS, MD, MB, MI, MS) _BTLrm(X86_BTS, RS, MD, MB, MI, MS) + +#define BTSQir(IM, RD) _BTQir(X86_BTS, IM, RD) +#define BTSQim(IM, MD, MB, MI, MS) _BTQim(X86_BTS, IM, MD, MB, MI, MS) +#define BTSQrr(RS, RD) _BTQrr(X86_BTS, RS, RD) +#define BTSQrm(RS, MD, MB, MI, MS) _BTQrm(X86_BTS, RS, MD, MB, MI, MS) + + +/* --- Move instructions --------------------------------------------------- */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define MOVBrr(RS, RD) (_REXBrr(RS, RD), _O_Mrm (0x88 ,_b11,_r1(RS),_r1(RD) )) +#define MOVBmr(MD, MB, MI, MS, RD) (_REXBmr(MB, MI, RD), _O_r_X (0x8a ,_r1(RD) ,MD,MB,MI,MS )) +#define MOVBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (0x88 ,_r1(RS) ,MD,MB,MI,MS )) +#define MOVBir(IM, R) (_REXBrr(0, R), _Or_B (0xb0,_r1(R) ,_su8(IM))) +#define MOVBim(IM, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_X_B (0xc6 ,MD,MB,MI,MS ,_su8(IM))) + +#define MOVWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (0x89 ,_b11,_r2(RS),_r2(RD) )) +#define MOVWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _O_r_X (0x8b ,_r2(RD) ,MD,MB,MI,MS )) +#define MOVWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0x89 ,_r2(RS) ,MD,MB,MI,MS )) +#define MOVWir(IM, R) (_d16(), _REXLrr(0, R), _Or_W (0xb8,_r2(R) ,_su16(IM))) +#define MOVWim(IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_X_W (0xc7 ,MD,MB,MI,MS ,_su16(IM))) + +#define MOVLrr(RS, RD) (_REXLrr(RS, RD), _O_Mrm (0x89 ,_b11,_r4(RS),_r4(RD) )) +#define MOVLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (0x8b ,_r4(RD) ,MD,MB,MI,MS )) +#define MOVLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (0x89 ,_r4(RS) ,MD,MB,MI,MS )) +#define MOVLir(IM, R) (_REXLrr(0, R), _Or_L (0xb8,_r4(R) ,IM )) +#define MOVLim(IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_X_L (0xc7 ,MD,MB,MI,MS ,IM )) + +#define MOVQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x89 ,_b11,_r8(RS),_r8(RD) )) +#define MOVQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _O_r_X (0x8b ,_r8(RD) ,MD,MB,MI,MS )) +#define MOVQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x89 ,_r8(RS) ,MD,MB,MI,MS )) +#define MOVQir(IM, R) (_REXQrr(0, R), _Or_Q (0xb8,_r8(R) ,IM )) +#define MOVQim(IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_X_L (0xc7 ,MD,MB,MI,MS ,IM )) + + +/* --- Unary and Multiply/Divide instructions ------------------------------ */ + +enum { + X86_NOT = 2, + X86_NEG = 3, + X86_MUL = 4, + X86_IMUL = 5, + X86_DIV = 6, + X86_IDIV = 7, +}; + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define _UNARYBr(OP, RS) (_REXBrr(0, RS), _O_Mrm (0xf6 ,_b11,OP ,_r1(RS) )) +#define _UNARYBm(OP, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X (0xf6 ,OP ,MD,MB,MI,MS )) +#define _UNARYWr(OP, RS) (_d16(), _REXLrr(0, RS), _O_Mrm (0xf7 ,_b11,OP ,_r2(RS) )) +#define _UNARYWm(OP, MD, MB, MI, MS) (_d16(), _REXLmr(MB, MI, 0), _O_r_X (0xf7 ,OP ,MD,MB,MI,MS )) +#define _UNARYLr(OP, RS) (_REXLrr(0, RS), _O_Mrm (0xf7 ,_b11,OP ,_r4(RS) )) +#define _UNARYLm(OP, MD, MB, MI, MS) (_REXLmr(MB, MI, 0), _O_r_X (0xf7 ,OP ,MD,MB,MI,MS )) +#define _UNARYQr(OP, RS) (_REXQrr(0, RS), _O_Mrm (0xf7 ,_b11,OP ,_r8(RS) )) +#define _UNARYQm(OP, MD, MB, MI, MS) (_REXQmr(MB, MI, 0), _O_r_X (0xf7 ,OP ,MD,MB,MI,MS )) + +#define NOTBr(RS) _UNARYBr(X86_NOT, RS) +#define NOTBm(MD, MB, MI, MS) _UNARYBm(X86_NOT, MD, MB, MI, MS) +#define NOTWr(RS) _UNARYWr(X86_NOT, RS) +#define NOTWm(MD, MB, MI, MS) _UNARYWm(X86_NOT, MD, MB, MI, MS) +#define NOTLr(RS) _UNARYLr(X86_NOT, RS) +#define NOTLm(MD, MB, MI, MS) _UNARYLm(X86_NOT, MD, MB, MI, MS) +#define NOTQr(RS) _UNARYQr(X86_NOT, RS) +#define NOTQm(MD, MB, MI, MS) _UNARYQm(X86_NOT, MD, MB, MI, MS) + +#define NEGBr(RS) _UNARYBr(X86_NEG, RS) +#define NEGBm(MD, MB, MI, MS) _UNARYBm(X86_NEG, MD, MB, MI, MS) +#define NEGWr(RS) _UNARYWr(X86_NEG, RS) +#define NEGWm(MD, MB, MI, MS) _UNARYWm(X86_NEG, MD, MB, MI, MS) +#define NEGLr(RS) _UNARYLr(X86_NEG, RS) +#define NEGLm(MD, MB, MI, MS) _UNARYLm(X86_NEG, MD, MB, MI, MS) +#define NEGQr(RS) _UNARYQr(X86_NEG, RS) +#define NEGQm(MD, MB, MI, MS) _UNARYQm(X86_NEG, MD, MB, MI, MS) + +#define MULBr(RS) _UNARYBr(X86_MUL, RS) +#define MULBm(MD, MB, MI, MS) _UNARYBm(X86_MUL, MD, MB, MI, MS) +#define MULWr(RS) _UNARYWr(X86_MUL, RS) +#define MULWm(MD, MB, MI, MS) _UNARYWm(X86_MUL, MD, MB, MI, MS) +#define MULLr(RS) _UNARYLr(X86_MUL, RS) +#define MULLm(MD, MB, MI, MS) _UNARYLm(X86_MUL, MD, MB, MI, MS) +#define MULQr(RS) _UNARYQr(X86_MUL, RS) +#define MULQm(MD, MB, MI, MS) _UNARYQm(X86_MUL, MD, MB, MI, MS) + +#define IMULBr(RS) _UNARYBr(X86_IMUL, RS) +#define IMULBm(MD, MB, MI, MS) _UNARYBm(X86_IMUL, MD, MB, MI, MS) +#define IMULWr(RS) _UNARYWr(X86_IMUL, RS) +#define IMULWm(MD, MB, MI, MS) _UNARYWm(X86_IMUL, MD, MB, MI, MS) +#define IMULLr(RS) _UNARYLr(X86_IMUL, RS) +#define IMULLm(MD, MB, MI, MS) _UNARYLm(X86_IMUL, MD, MB, MI, MS) +#define IMULQr(RS) _UNARYQr(X86_IMUL, RS) +#define IMULQm(MD, MB, MI, MS) _UNARYQm(X86_IMUL, MD, MB, MI, MS) + +#define DIVBr(RS) _UNARYBr(X86_DIV, RS) +#define DIVBm(MD, MB, MI, MS) _UNARYBm(X86_DIV, MD, MB, MI, MS) +#define DIVWr(RS) _UNARYWr(X86_DIV, RS) +#define DIVWm(MD, MB, MI, MS) _UNARYWm(X86_DIV, MD, MB, MI, MS) +#define DIVLr(RS) _UNARYLr(X86_DIV, RS) +#define DIVLm(MD, MB, MI, MS) _UNARYLm(X86_DIV, MD, MB, MI, MS) +#define DIVQr(RS) _UNARYQr(X86_DIV, RS) +#define DIVQm(MD, MB, MI, MS) _UNARYQm(X86_DIV, MD, MB, MI, MS) + +#define IDIVBr(RS) _UNARYBr(X86_IDIV, RS) +#define IDIVBm(MD, MB, MI, MS) _UNARYBm(X86_IDIV, MD, MB, MI, MS) +#define IDIVWr(RS) _UNARYWr(X86_IDIV, RS) +#define IDIVWm(MD, MB, MI, MS) _UNARYWm(X86_IDIV, MD, MB, MI, MS) +#define IDIVLr(RS) _UNARYLr(X86_IDIV, RS) +#define IDIVLm(MD, MB, MI, MS) _UNARYLm(X86_IDIV, MD, MB, MI, MS) +#define IDIVQr(RS) _UNARYQr(X86_IDIV, RS) +#define IDIVQm(MD, MB, MI, MS) _UNARYQm(X86_IDIV, MD, MB, MI, MS) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define IMULWrr(RS, RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r2(RD),_r2(RS) )) +#define IMULWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0faf ,_r2(RD) ,MD,MB,MI,MS )) + +#define IMULWirr(IM,RS,RD) (_d16(), _REXLrr(RS, RD), _Os_Mrm_sW (0x69 ,_b11,_r2(RS),_r2(RD) ,_su16(IM) )) +#define IMULWimr(IM,MD,MB,MI,MS,RD) (_d16(), _REXLmr(MB, MI, RD), _Os_r_X_sW (0x69 ,_r2(RD) ,MD,MB,MI,MS ,_su16(IM) )) + +#define IMULLir(IM, RD) (_REXLrr(0, RD), _Os_Mrm_sL (0x69 ,_b11,_r4(RD),_r4(RD) ,IM )) +#define IMULLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r4(RD),_r4(RS) )) +#define IMULLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0faf ,_r4(RD) ,MD,MB,MI,MS )) + +#define IMULQir(IM, RD) (_REXQrr(0, RD), _Os_Mrm_sL (0x69 ,_b11,_r8(RD),_r8(RD) ,IM )) +#define IMULQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0faf ,_b11,_r8(RD),_r8(RS) )) +#define IMULQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0faf ,_r8(RD) ,MD,MB,MI,MS )) + +#define IMULLirr(IM,RS,RD) (_REXLrr(RS, RD), _Os_Mrm_sL (0x69 ,_b11,_r4(RS),_r4(RD) ,IM )) +#define IMULLimr(IM,MD,MB,MI,MS,RD) (_REXLmr(MB, MI, RD), _Os_r_X_sL (0x69 ,_r4(RD) ,MD,MB,MI,MS ,IM )) + +#define IMULQirr(IM,RS,RD) (_REXQrr(RS, RD), _Os_Mrm_sL (0x69 ,_b11,_r8(RS),_r8(RD) ,IM )) +#define IMULQimr(IM,MD,MB,MI,MS,RD) (_REXQmr(MB, MI, RD), _Os_r_X_sL (0x69 ,_r8(RD) ,MD,MB,MI,MS ,IM )) + + +/* --- Control Flow related instructions ----------------------------------- */ + +enum { + X86_CC_O = 0x0, + X86_CC_NO = 0x1, + X86_CC_NAE = 0x2, + X86_CC_B = 0x2, + X86_CC_C = 0x2, + X86_CC_AE = 0x3, + X86_CC_NB = 0x3, + X86_CC_NC = 0x3, + X86_CC_E = 0x4, + X86_CC_Z = 0x4, + X86_CC_NE = 0x5, + X86_CC_NZ = 0x5, + X86_CC_BE = 0x6, + X86_CC_NA = 0x6, + X86_CC_A = 0x7, + X86_CC_NBE = 0x7, + X86_CC_S = 0x8, + X86_CC_NS = 0x9, + X86_CC_P = 0xa, + X86_CC_PE = 0xa, + X86_CC_NP = 0xb, + X86_CC_PO = 0xb, + X86_CC_L = 0xc, + X86_CC_NGE = 0xc, + X86_CC_GE = 0xd, + X86_CC_NL = 0xd, + X86_CC_LE = 0xe, + X86_CC_NG = 0xe, + X86_CC_G = 0xf, + X86_CC_NLE = 0xf, +}; + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +// FIXME: no prefix is availble to encode a 32-bit operand size in 64-bit mode +#define CALLm(M) _O_D32 (0xe8 ,(int)(M) ) +#define _CALLLsr(R) (_REXLrr(0, R), _O_Mrm (0xff ,_b11,_b010,_r4(R) )) +#define _CALLQsr(R) (_REXQrr(0, R), _O_Mrm (0xff ,_b11,_b010,_r8(R) )) +#define CALLsr(R) ( X86_TARGET_64BIT ? _CALLQsr(R) : _CALLLsr(R)) +#define CALLsm(D,B,I,S) (_REXLrm(0, B, I), _O_r_X (0xff ,_b010 ,(int)(D),B,I,S )) + +// FIXME: no prefix is availble to encode a 32-bit operand size in 64-bit mode +#define JMPSm(M) _O_D8 (0xeb ,(int)(M) ) +#define JMPm(M) _O_D32 (0xe9 ,(int)(M) ) +#define _JMPLsr(R) (_REXLrr(0, R), _O_Mrm (0xff ,_b11,_b100,_r4(R) )) +#define _JMPQsr(R) (_REXQrr(0, R), _O_Mrm (0xff ,_b11,_b100,_r8(R) )) +#define JMPsr(R) ( X86_TARGET_64BIT ? _JMPQsr(R) : _JMPLsr(R)) +#define JMPsm(D,B,I,S) (_REXLrm(0, B, I), _O_r_X (0xff ,_b100 ,(int)(D),B,I,S )) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ +#define JCCSii(CC, D) _O_B (0x70|(CC) ,(_sc)(int)(D) ) +#define JCCSim(CC, D) _O_D8 (0x70|(CC) ,(int)(D) ) +#define JOSm(D) JCCSim(0x0, D) +#define JNOSm(D) JCCSim(0x1, D) +#define JBSm(D) JCCSim(0x2, D) +#define JNAESm(D) JCCSim(0x2, D) +#define JNBSm(D) JCCSim(0x3, D) +#define JAESm(D) JCCSim(0x3, D) +#define JESm(D) JCCSim(0x4, D) +#define JZSm(D) JCCSim(0x4, D) +#define JNESm(D) JCCSim(0x5, D) +#define JNZSm(D) JCCSim(0x5, D) +#define JBESm(D) JCCSim(0x6, D) +#define JNASm(D) JCCSim(0x6, D) +#define JNBESm(D) JCCSim(0x7, D) +#define JASm(D) JCCSim(0x7, D) +#define JSSm(D) JCCSim(0x8, D) +#define JNSSm(D) JCCSim(0x9, D) +#define JPSm(D) JCCSim(0xa, D) +#define JPESm(D) JCCSim(0xa, D) +#define JNPSm(D) JCCSim(0xb, D) +#define JPOSm(D) JCCSim(0xb, D) +#define JLSm(D) JCCSim(0xc, D) +#define JNGESm(D) JCCSim(0xc, D) +#define JNLSm(D) JCCSim(0xd, D) +#define JGESm(D) JCCSim(0xd, D) +#define JLESm(D) JCCSim(0xe, D) +#define JNGSm(D) JCCSim(0xe, D) +#define JNLESm(D) JCCSim(0xf, D) +#define JGSm(D) JCCSim(0xf, D) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ +#define JCCii(CC, D) _OO_L (0x0f80|(CC) ,(int)(D) ) +#define JCCim(CC, D) _OO_D32 (0x0f80|(CC) ,(int)(D) ) +#define JOm(D) JCCim(0x0, D) +#define JNOm(D) JCCim(0x1, D) +#define JBm(D) JCCim(0x2, D) +#define JNAEm(D) JCCim(0x2, D) +#define JNBm(D) JCCim(0x3, D) +#define JAEm(D) JCCim(0x3, D) +#define JEm(D) JCCim(0x4, D) +#define JZm(D) JCCim(0x4, D) +#define JNEm(D) JCCim(0x5, D) +#define JNZm(D) JCCim(0x5, D) +#define JBEm(D) JCCim(0x6, D) +#define JNAm(D) JCCim(0x6, D) +#define JNBEm(D) JCCim(0x7, D) +#define JAm(D) JCCim(0x7, D) +#define JSm(D) JCCim(0x8, D) +#define JNSm(D) JCCim(0x9, D) +#define JPm(D) JCCim(0xa, D) +#define JPEm(D) JCCim(0xa, D) +#define JNPm(D) JCCim(0xb, D) +#define JPOm(D) JCCim(0xb, D) +#define JLm(D) JCCim(0xc, D) +#define JNGEm(D) JCCim(0xc, D) +#define JNLm(D) JCCim(0xd, D) +#define JGEm(D) JCCim(0xd, D) +#define JLEm(D) JCCim(0xe, D) +#define JNGm(D) JCCim(0xe, D) +#define JNLEm(D) JCCim(0xf, D) +#define JGm(D) JCCim(0xf, D) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ +#define SETCCir(CC, RD) (_REXBrr(0, RD), _OO_Mrm (0x0f90|(CC) ,_b11,_b000,_r1(RD) )) +#define SETOr(RD) SETCCir(0x0,RD) +#define SETNOr(RD) SETCCir(0x1,RD) +#define SETBr(RD) SETCCir(0x2,RD) +#define SETNAEr(RD) SETCCir(0x2,RD) +#define SETNBr(RD) SETCCir(0x3,RD) +#define SETAEr(RD) SETCCir(0x3,RD) +#define SETEr(RD) SETCCir(0x4,RD) +#define SETZr(RD) SETCCir(0x4,RD) +#define SETNEr(RD) SETCCir(0x5,RD) +#define SETNZr(RD) SETCCir(0x5,RD) +#define SETBEr(RD) SETCCir(0x6,RD) +#define SETNAr(RD) SETCCir(0x6,RD) +#define SETNBEr(RD) SETCCir(0x7,RD) +#define SETAr(RD) SETCCir(0x7,RD) +#define SETSr(RD) SETCCir(0x8,RD) +#define SETNSr(RD) SETCCir(0x9,RD) +#define SETPr(RD) SETCCir(0xa,RD) +#define SETPEr(RD) SETCCir(0xa,RD) +#define SETNPr(RD) SETCCir(0xb,RD) +#define SETPOr(RD) SETCCir(0xb,RD) +#define SETLr(RD) SETCCir(0xc,RD) +#define SETNGEr(RD) SETCCir(0xc,RD) +#define SETNLr(RD) SETCCir(0xd,RD) +#define SETGEr(RD) SETCCir(0xd,RD) +#define SETLEr(RD) SETCCir(0xe,RD) +#define SETNGr(RD) SETCCir(0xe,RD) +#define SETNLEr(RD) SETCCir(0xf,RD) +#define SETGr(RD) SETCCir(0xf,RD) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ +#define SETCCim(CC,MD,MB,MI,MS) (_REXBrm(0, MB, MI), _OO_r_X (0x0f90|(CC) ,_b000 ,MD,MB,MI,MS )) +#define SETOm(D, B, I, S) SETCCim(0x0, D, B, I, S) +#define SETNOm(D, B, I, S) SETCCim(0x1, D, B, I, S) +#define SETBm(D, B, I, S) SETCCim(0x2, D, B, I, S) +#define SETNAEm(D, B, I, S) SETCCim(0x2, D, B, I, S) +#define SETNBm(D, B, I, S) SETCCim(0x3, D, B, I, S) +#define SETAEm(D, B, I, S) SETCCim(0x3, D, B, I, S) +#define SETEm(D, B, I, S) SETCCim(0x4, D, B, I, S) +#define SETZm(D, B, I, S) SETCCim(0x4, D, B, I, S) +#define SETNEm(D, B, I, S) SETCCim(0x5, D, B, I, S) +#define SETNZm(D, B, I, S) SETCCim(0x5, D, B, I, S) +#define SETBEm(D, B, I, S) SETCCim(0x6, D, B, I, S) +#define SETNAm(D, B, I, S) SETCCim(0x6, D, B, I, S) +#define SETNBEm(D, B, I, S) SETCCim(0x7, D, B, I, S) +#define SETAm(D, B, I, S) SETCCim(0x7, D, B, I, S) +#define SETSm(D, B, I, S) SETCCim(0x8, D, B, I, S) +#define SETNSm(D, B, I, S) SETCCim(0x9, D, B, I, S) +#define SETPm(D, B, I, S) SETCCim(0xa, D, B, I, S) +#define SETPEm(D, B, I, S) SETCCim(0xa, D, B, I, S) +#define SETNPm(D, B, I, S) SETCCim(0xb, D, B, I, S) +#define SETPOm(D, B, I, S) SETCCim(0xb, D, B, I, S) +#define SETLm(D, B, I, S) SETCCim(0xc, D, B, I, S) +#define SETNGEm(D, B, I, S) SETCCim(0xc, D, B, I, S) +#define SETNLm(D, B, I, S) SETCCim(0xd, D, B, I, S) +#define SETGEm(D, B, I, S) SETCCim(0xd, D, B, I, S) +#define SETLEm(D, B, I, S) SETCCim(0xe, D, B, I, S) +#define SETNGm(D, B, I, S) SETCCim(0xe, D, B, I, S) +#define SETNLEm(D, B, I, S) SETCCim(0xf, D, B, I, S) +#define SETGm(D, B, I, S) SETCCim(0xf, D, B, I, S) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ +#define CMOVWrr(CC,RS,RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r2(RD),_r2(RS) )) +#define CMOVWmr(CC,MD,MB,MI,MS,RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r2(RD) ,MD,MB,MI,MS )) +#define CMOVLrr(CC,RS,RD) (_REXLrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r4(RD),_r4(RS) )) +#define CMOVLmr(CC,MD,MB,MI,MS,RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r4(RD) ,MD,MB,MI,MS )) +#define CMOVQrr(CC,RS,RD) (_REXQrr(RD, RS), _OO_Mrm (0x0f40|(CC) ,_b11,_r8(RD),_r8(RS) )) +#define CMOVQmr(CC,MD,MB,MI,MS,RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f40|(CC) ,_r8(RD) ,MD,MB,MI,MS )) + + +/* --- Push/Pop instructions ----------------------------------------------- */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define POPWr(RD) _m32only((_d16(), _Or (0x58,_r2(RD) ))) +#define POPWm(MD, MB, MI, MS) _m32only((_d16(), _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS ))) + +#define POPLr(RD) _m32only( _Or (0x58,_r4(RD) )) +#define POPLm(MD, MB, MI, MS) _m32only( _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS )) + +#define POPQr(RD) _m64only((_REXQr(RD), _Or (0x58,_r8(RD) ))) +#define POPQm(MD, MB, MI, MS) _m64only((_REXQm(MB, MI), _O_r_X (0x8f ,_b000 ,MD,MB,MI,MS ))) + +#define PUSHWr(RS) _m32only((_d16(), _Or (0x50,_r2(RS) ))) +#define PUSHWm(MD, MB, MI, MS) _m32only((_d16(), _O_r_X (0xff, ,_b110 ,MD,MB,MI,MS ))) +#define PUSHWi(IM) _m32only((_d16(), _Os_sW (0x68 ,IM ))) + +#define PUSHLr(RS) _m32only( _Or (0x50,_r4(RS) )) +#define PUSHLm(MD, MB, MI, MS) _m32only( _O_r_X (0xff ,_b110 ,MD,MB,MI,MS )) +#define PUSHLi(IM) _m32only( _Os_sL (0x68 ,IM )) + +#define PUSHQr(RS) _m64only((_REXQr(RS), _Or (0x50,_r8(RS) ))) +#define PUSHQm(MD, MB, MI, MS) _m64only((_REXQm(MB, MI), _O_r_X (0xff ,_b110 ,MD,MB,MI,MS ))) +#define PUSHQi(IM) _m64only( _Os_sL (0x68 ,IM )) + +#define POPA() (_d16(), _O (0x61 )) +#define POPAD() _O (0x61 ) + +#define PUSHA() (_d16(), _O (0x60 )) +#define PUSHAD() _O (0x60 ) + +#define POPF() _O (0x9d ) +#define PUSHF() _O (0x9c ) + + +/* --- Test instructions --------------------------------------------------- */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define TESTBrr(RS, RD) (_REXBrr(RS, RD), _O_Mrm (0x84 ,_b11,_r1(RS),_r1(RD) )) +#define TESTBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (0x84 ,_r1(RS) ,MD,MB,MI,MS )) +#define TESTBir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AL) ? \ + (_REXBrr(0, RD), _O_B (0xa8 ,_u8(IM))) : \ + (_REXBrr(0, RD), _O_Mrm_B (0xf6 ,_b11,_b000 ,_r1(RD) ,_u8(IM))) ) +#define TESTBim(IM, MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X_B (0xf6 ,_b000 ,MD,MB,MI,MS ,_u8(IM))) + +#define TESTWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (0x85 ,_b11,_r2(RS),_r2(RD) )) +#define TESTWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0x85 ,_r2(RS) ,MD,MB,MI,MS )) +#define TESTWir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_AX) ? \ + (_d16(), _REXLrr(0, RD), _O_W (0xa9 ,_u16(IM))) : \ + (_d16(), _REXLrr(0, RD), _O_Mrm_W (0xf7 ,_b11,_b000 ,_r2(RD) ,_u16(IM))) ) +#define TESTWim(IM, MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_r_X_W (0xf7 ,_b000 ,MD,MB,MI,MS ,_u16(IM))) + +#define TESTLrr(RS, RD) (_REXLrr(RS, RD), _O_Mrm (0x85 ,_b11,_r4(RS),_r4(RD) )) +#define TESTLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (0x85 ,_r4(RS) ,MD,MB,MI,MS )) +#define TESTLir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_EAX) ? \ + (_REXLrr(0, RD), _O_L (0xa9 ,IM )) : \ + (_REXLrr(0, RD), _O_Mrm_L (0xf7 ,_b11,_b000 ,_r4(RD) ,IM )) ) +#define TESTLim(IM, MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X_L (0xf7 ,_b000 ,MD,MB,MI,MS ,IM )) + +#define TESTQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x85 ,_b11,_r8(RS),_r8(RD) )) +#define TESTQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x85 ,_r8(RS) ,MD,MB,MI,MS )) +#define TESTQir(IM, RD) (X86_OPTIMIZE_ALU && ((RD) == X86_RAX) ? \ + (_REXQrr(0, RD), _O_L (0xa9 ,IM )) : \ + (_REXQrr(0, RD), _O_Mrm_L (0xf7 ,_b11,_b000 ,_r8(RD) ,IM )) ) +#define TESTQim(IM, MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X_L (0xf7 ,_b000 ,MD,MB,MI,MS ,IM )) + + +/* --- Exchange instructions ----------------------------------------------- */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define CMPXCHGBrr(RS, RD) (_REXBrr(RS, RD), _OO_Mrm (0x0fb0 ,_b11,_r1(RS),_r1(RD) )) +#define CMPXCHGBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _OO_r_X (0x0fb0 ,_r1(RS) ,MD,MB,MI,MS )) + +#define CMPXCHGWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r2(RS),_r2(RD) )) +#define CMPXCHGWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r2(RS) ,MD,MB,MI,MS )) + +#define CMPXCHGLrr(RS, RD) (_REXLrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r4(RS),_r4(RD) )) +#define CMPXCHGLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r4(RS) ,MD,MB,MI,MS )) + +#define CMPXCHGQrr(RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0fb1 ,_b11,_r8(RS),_r8(RD) )) +#define CMPXCHGQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0fb1 ,_r8(RS) ,MD,MB,MI,MS )) + +#define XADDBrr(RS, RD) (_REXBrr(RS, RD), _OO_Mrm (0x0fc0 ,_b11,_r1(RS),_r1(RD) )) +#define XADDBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _OO_r_X (0x0fc0 ,_r1(RS) ,MD,MB,MI,MS )) + +#define XADDWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r2(RS),_r2(RD) )) +#define XADDWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r2(RS) ,MD,MB,MI,MS )) + +#define XADDLrr(RS, RD) (_REXLrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r4(RS),_r4(RD) )) +#define XADDLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r4(RS) ,MD,MB,MI,MS )) + +#define XADDQrr(RS, RD) (_REXQrr(RS, RD), _OO_Mrm (0x0fc1 ,_b11,_r8(RS),_r8(RD) )) +#define XADDQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0fc1 ,_r8(RS) ,MD,MB,MI,MS )) + +#define XCHGBrr(RS, RD) (_REXBrr(RS, RD), _O_Mrm (0x86 ,_b11,_r1(RS),_r1(RD) )) +#define XCHGBrm(RS, MD, MB, MI, MS) (_REXBrm(RS, MB, MI), _O_r_X (0x86 ,_r1(RS) ,MD,MB,MI,MS )) + +#define XCHGWrr(RS, RD) (_d16(), _REXLrr(RS, RD), _O_Mrm (0x87 ,_b11,_r2(RS),_r2(RD) )) +#define XCHGWrm(RS, MD, MB, MI, MS) (_d16(), _REXLrm(RS, MB, MI), _O_r_X (0x87 ,_r2(RS) ,MD,MB,MI,MS )) + +#define XCHGLrr(RS, RD) (_REXLrr(RS, RD), _O_Mrm (0x87 ,_b11,_r4(RS),_r4(RD) )) +#define XCHGLrm(RS, MD, MB, MI, MS) (_REXLrm(RS, MB, MI), _O_r_X (0x87 ,_r4(RS) ,MD,MB,MI,MS )) + +#define XCHGQrr(RS, RD) (_REXQrr(RS, RD), _O_Mrm (0x87 ,_b11,_r8(RS),_r8(RD) )) +#define XCHGQrm(RS, MD, MB, MI, MS) (_REXQrm(RS, MB, MI), _O_r_X (0x87 ,_r8(RS) ,MD,MB,MI,MS )) + + +/* --- Increment/Decrement instructions ------------------------------------ */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define DECBm(MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X (0xfe ,_b001 ,MD,MB,MI,MS )) +#define DECBr(RD) (_REXBrr(0, RD), _O_Mrm (0xfe ,_b11,_b001 ,_r1(RD) )) + +#define DECWm(MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS )) +#define DECWr(RD) (! X86_TARGET_64BIT ? (_d16(), _Or (0x48,_r2(RD) )) : \ + (_d16(), _REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r2(RD) ))) + +#define DECLm(MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS )) +#define DECLr(RD) (! X86_TARGET_64BIT ? _Or (0x48,_r4(RD) ) : \ + (_REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r4(RD) ))) + +#define DECQm(MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X (0xff ,_b001 ,MD,MB,MI,MS )) +#define DECQr(RD) (_REXQrr(0, RD), _O_Mrm (0xff ,_b11,_b001 ,_r8(RD) )) + +#define INCBm(MD, MB, MI, MS) (_REXBrm(0, MB, MI), _O_r_X (0xfe ,_b000 ,MD,MB,MI,MS )) +#define INCBr(RD) (_REXBrr(0, RD), _O_Mrm (0xfe ,_b11,_b000 ,_r1(RD) )) + +#define INCWm(MD, MB, MI, MS) (_d16(), _REXLrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS )) +#define INCWr(RD) (! X86_TARGET_64BIT ? (_d16(), _Or (0x40,_r2(RD) )) : \ + (_d16(), _REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r2(RD) )) ) + +#define INCLm(MD, MB, MI, MS) (_REXLrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS )) +#define INCLr(RD) (! X86_TARGET_64BIT ? _Or (0x40,_r4(RD) ) : \ + (_REXLrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r4(RD) ))) + +#define INCQm(MD, MB, MI, MS) (_REXQrm(0, MB, MI), _O_r_X (0xff ,_b000 ,MD,MB,MI,MS )) +#define INCQr(RD) (_REXQrr(0, RD), _O_Mrm (0xff ,_b11,_b000 ,_r8(RD) )) + + +/* --- Misc instructions --------------------------------------------------- */ + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define BSFWrr(RS, RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r2(RD),_r2(RS) )) +#define BSFWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r2(RD) ,MD,MB,MI,MS )) +#define BSRWrr(RS, RD) (_d16(), _REXLrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r2(RD),_r2(RS) )) +#define BSRWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r2(RD) ,MD,MB,MI,MS )) + +#define BSFLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r4(RD),_r4(RS) )) +#define BSFLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r4(RD) ,MD,MB,MI,MS )) +#define BSRLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r4(RD),_r4(RS) )) +#define BSRLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r4(RD) ,MD,MB,MI,MS )) + +#define BSFQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbc ,_b11,_r8(RD),_r8(RS) )) +#define BSFQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbc ,_r8(RD) ,MD,MB,MI,MS )) +#define BSRQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbd ,_b11,_r8(RD),_r8(RS) )) +#define BSRQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbd ,_r8(RD) ,MD,MB,MI,MS )) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define MOVSBWrr(RS, RD) (_d16(), _REXBLrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r2(RD),_r1(RS) )) +#define MOVSBWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r2(RD) ,MD,MB,MI,MS )) +#define MOVZBWrr(RS, RD) (_d16(), _REXBLrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r2(RD),_r1(RS) )) +#define MOVZBWmr(MD, MB, MI, MS, RD) (_d16(), _REXLmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r2(RD) ,MD,MB,MI,MS )) + +#define MOVSBLrr(RS, RD) (_REXBLrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r4(RD),_r1(RS) )) +#define MOVSBLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r4(RD) ,MD,MB,MI,MS )) +#define MOVZBLrr(RS, RD) (_REXBLrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r4(RD),_r1(RS) )) +#define MOVZBLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r4(RD) ,MD,MB,MI,MS )) + +#define MOVSBQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbe ,_b11,_r8(RD),_r1(RS) )) +#define MOVSBQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbe ,_r8(RD) ,MD,MB,MI,MS )) +#define MOVZBQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fb6 ,_b11,_r8(RD),_r1(RS) )) +#define MOVZBQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fb6 ,_r8(RD) ,MD,MB,MI,MS )) + +#define MOVSWLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fbf ,_b11,_r4(RD),_r2(RS) )) +#define MOVSWLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fbf ,_r4(RD) ,MD,MB,MI,MS )) +#define MOVZWLrr(RS, RD) (_REXLrr(RD, RS), _OO_Mrm (0x0fb7 ,_b11,_r4(RD),_r2(RS) )) +#define MOVZWLmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _OO_r_X (0x0fb7 ,_r4(RD) ,MD,MB,MI,MS )) + +#define MOVSWQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fbf ,_b11,_r8(RD),_r2(RS) )) +#define MOVSWQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fbf ,_r8(RD) ,MD,MB,MI,MS )) +#define MOVZWQrr(RS, RD) (_REXQrr(RD, RS), _OO_Mrm (0x0fb7 ,_b11,_r8(RD),_r2(RS) )) +#define MOVZWQmr(MD, MB, MI, MS, RD) (_REXQmr(MB, MI, RD), _OO_r_X (0x0fb7 ,_r8(RD) ,MD,MB,MI,MS )) + +#define MOVSLQrr(RS, RD) _m64only((_REXQrr(RD, RS), _O_Mrm (0x63 ,_b11,_r8(RD),_r4(RS) ))) +#define MOVSLQmr(MD, MB, MI, MS, RD) _m64only((_REXQmr(MB, MI, RD), _O_r_X (0x63 ,_r8(RD) ,MD,MB,MI,MS ))) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define LEALmr(MD, MB, MI, MS, RD) (_REXLmr(MB, MI, RD), _O_r_X (0x8d ,_r4(RD) ,MD,MB,MI,MS )) + +#define BSWAPLr(R) (_REXLrr(0, R), _OOr (0x0fc8,_r4(R) )) +#define BSWAPQr(R) (_REXQrr(0, R), _OOr (0x0fc8,_r8(R) )) + +#define CLC() _O (0xf8 ) +#define STC() _O (0xf9 ) + +#define CMC() _O (0xf5 ) +#define CLD() _O (0xfc ) +#define STD() _O (0xfd ) + +#define CBTW() (_d16(), _O (0x98 )) +#define CWTL() _O (0x98 ) +#define CLTQ() _m64only(_REXQrr(0, 0), _O (0x98 )) + +#define CBW CBTW +#define CWDE CWTL +#define CDQE CLTQ + +#define CWTD() (_d16(), _O (0x99 )) +#define CLTD() _O (0x99 ) +#define CQTO() _m64only(_REXQrr(0, 0), _O (0x99 )) + +#define CWD CWTD +#define CDQ CLTD +#define CQO CQTO + +#define LAHF() _O (0x9f ) +#define SAHF() _O (0x9e ) + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define CPUID() _OO (0x0fa2 ) +#define RDTSC() _OO (0xff31 ) + +#define ENTERii(W, B) _O_W_B (0xc8 ,_su16(W),_su8(B)) + +#define LEAVE() _O (0xc9 ) +#define RET() _O (0xc3 ) +#define RETi(IM) _O_W (0xc2 ,_su16(IM)) + +#define NOP() _O (0x90 ) + + +/* --- Media 128-bit instructions ------------------------------------------ */ + +enum { + X86_SSE_CVTIS = 0x2a, + X86_SSE_CVTSI = 0x2d, + X86_SSE_UCOMI = 0x2e, + X86_SSE_COMI = 0x2f, + X86_SSE_SQRT = 0x51, + X86_SSE_RSQRT = 0x52, + X86_SSE_RCP = 0x53, + X86_SSE_AND = 0x54, + X86_SSE_ANDN = 0x55, + X86_SSE_OR = 0x56, + X86_SSE_XOR = 0x57, + X86_SSE_ADD = 0x58, + X86_SSE_MUL = 0x59, + X86_SSE_CVTSD = 0x5a, + X86_SSE_CVTDT = 0x5b, + X86_SSE_SUB = 0x5c, + X86_SSE_MIN = 0x5d, + X86_SSE_DIV = 0x5e, + X86_SSE_MAX = 0x5f, +}; + +/* _format Opcd ,Mod ,r ,m ,mem=dsp+sib ,imm... */ + +#define __SSELrr(OP,RS,RSA,RD,RDA) (_REXLrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) )) +#define __SSELmr(OP,MD,MB,MI,MS,RD,RDA) (_REXLmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS )) +#define __SSELrm(OP,RS,RSA,MD,MB,MI,MS) (_REXLrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS )) + +#define __SSEQrr(OP,RS,RSA,RD,RDA) (_REXQrr(RD, RS), _OO_Mrm (0x0f00|(OP) ,_b11,RDA(RD),RSA(RS) )) +#define __SSEQmr(OP,MD,MB,MI,MS,RD,RDA) (_REXQmr(MB, MI, RD), _OO_r_X (0x0f00|(OP) ,RDA(RD) ,MD,MB,MI,MS )) +#define __SSEQrm(OP,RS,RSA,MD,MB,MI,MS) (_REXQrm(RS, MB, MI), _OO_r_X (0x0f00|(OP) ,RSA(RS) ,MD,MB,MI,MS )) + +#define _SSELrr(PX,OP,RS,RSA,RD,RDA) (_B(PX), __SSELrr(OP, RS, RSA, RD, RDA)) +#define _SSELmr(PX,OP,MD,MB,MI,MS,RD,RDA) (_B(PX), __SSELmr(OP, MD, MB, MI, MS, RD, RDA)) +#define _SSELrm(PX,OP,RS,RSA,MD,MB,MI,MS) (_B(PX), __SSELrm(OP, RS, RSA, MD, MB, MI, MS)) + +#define _SSEQrr(PX,OP,RS,RSA,RD,RDA) (_B(PX), __SSEQrr(OP, RS, RSA, RD, RDA)) +#define _SSEQmr(PX,OP,MD,MB,MI,MS,RD,RDA) (_B(PX), __SSEQmr(OP, MD, MB, MI, MS, RD, RDA)) +#define _SSEQrm(PX,OP,RS,RSA,MD,MB,MI,MS) (_B(PX), __SSEQrm(OP, RS, RSA, MD, MB, MI, MS)) + +#define _SSEPSrr(OP,RS,RD) __SSELrr( OP, RS,_rX, RD,_rX) +#define _SSEPSmr(OP,MD,MB,MI,MS,RD) __SSELmr( OP, MD, MB, MI, MS, RD,_rX) +#define _SSEPSrm(OP,RS,MD,MB,MI,MS) __SSELrm( OP, RS,_rX, MD, MB, MI, MS) + +#define _SSEPDrr(OP,RS,RD) _SSELrr(0x66, OP, RS,_rX, RD,_rX) +#define _SSEPDmr(OP,MD,MB,MI,MS,RD) _SSELmr(0x66, OP, MD, MB, MI, MS, RD,_rX) +#define _SSEPDrm(OP,RS,MD,MB,MI,MS) _SSELrm(0x66, OP, RS,_rX, MD, MB, MI, MS) + +#define _SSESSrr(OP,RS,RD) _SSELrr(0xf3, OP, RS,_rX, RD,_rX) +#define _SSESSmr(OP,MD,MB,MI,MS,RD) _SSELmr(0xf3, OP, MD, MB, MI, MS, RD,_rX) +#define _SSESSrm(OP,RS,MD,MB,MI,MS) _SSELrm(0xf3, OP, RS,_rX, MD, MB, MI, MS) + +#define _SSESDrr(OP,RS,RD) _SSELrr(0xf2, OP, RS,_rX, RD,_rX) +#define _SSESDmr(OP,MD,MB,MI,MS,RD) _SSELmr(0xf2, OP, MD, MB, MI, MS, RD,_rX) +#define _SSESDrm(OP,RS,MD,MB,MI,MS) _SSELrm(0xf2, OP, RS,_rX, MD, MB, MI, MS) + +#define ADDPSrr(RS, RD) _SSEPSrr(X86_SSE_ADD, RS, RD) +#define ADDPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_ADD, MD, MB, MI, MS, RD) +#define ADDPDrr(RS, RD) _SSEPDrr(X86_SSE_ADD, RS, RD) +#define ADDPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_ADD, MD, MB, MI, MS, RD) + +#define ADDSSrr(RS, RD) _SSESSrr(X86_SSE_ADD, RS, RD) +#define ADDSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_ADD, MD, MB, MI, MS, RD) +#define ADDSDrr(RS, RD) _SSESDrr(X86_SSE_ADD, RS, RD) +#define ADDSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_ADD, MD, MB, MI, MS, RD) + +#define ANDNPSrr(RS, RD) _SSEPSrr(X86_SSE_ANDN, RS, RD) +#define ANDNPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_ANDN, MD, MB, MI, MS, RD) +#define ANDNPDrr(RS, RD) _SSEPDrr(X86_SSE_ANDN, RS, RD) +#define ANDNPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_ANDN, MD, MB, MI, MS, RD) + +#define ANDPSrr(RS, RD) _SSEPSrr(X86_SSE_AND, RS, RD) +#define ANDPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_AND, MD, MB, MI, MS, RD) +#define ANDPDrr(RS, RD) _SSEPDrr(X86_SSE_AND, RS, RD) +#define ANDPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_AND, MD, MB, MI, MS, RD) + +#define DIVPSrr(RS, RD) _SSEPSrr(X86_SSE_DIV, RS, RD) +#define DIVPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_DIV, MD, MB, MI, MS, RD) +#define DIVPDrr(RS, RD) _SSEPDrr(X86_SSE_DIV, RS, RD) +#define DIVPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_DIV, MD, MB, MI, MS, RD) + +#define DIVSSrr(RS, RD) _SSESSrr(X86_SSE_DIV, RS, RD) +#define DIVSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_DIV, MD, MB, MI, MS, RD) +#define DIVSDrr(RS, RD) _SSESDrr(X86_SSE_DIV, RS, RD) +#define DIVSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_DIV, MD, MB, MI, MS, RD) + +#define MAXPSrr(RS, RD) _SSEPSrr(X86_SSE_MAX, RS, RD) +#define MAXPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_MAX, MD, MB, MI, MS, RD) +#define MAXPDrr(RS, RD) _SSEPDrr(X86_SSE_MAX, RS, RD) +#define MAXPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_MAX, MD, MB, MI, MS, RD) + +#define MAXSSrr(RS, RD) _SSESSrr(X86_SSE_MAX, RS, RD) +#define MAXSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_MAX, MD, MB, MI, MS, RD) +#define MAXSDrr(RS, RD) _SSESDrr(X86_SSE_MAX, RS, RD) +#define MAXSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_MAX, MD, MB, MI, MS, RD) + +#define MINPSrr(RS, RD) _SSEPSrr(X86_SSE_MIN, RS, RD) +#define MINPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_MIN, MD, MB, MI, MS, RD) +#define MINPDrr(RS, RD) _SSEPDrr(X86_SSE_MIN, RS, RD) +#define MINPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_MIN, MD, MB, MI, MS, RD) + +#define MINSSrr(RS, RD) _SSESSrr(X86_SSE_MIN, RS, RD) +#define MINSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_MIN, MD, MB, MI, MS, RD) +#define MINSDrr(RS, RD) _SSESDrr(X86_SSE_MIN, RS, RD) +#define MINSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_MIN, MD, MB, MI, MS, RD) + +#define MULPSrr(RS, RD) _SSEPSrr(X86_SSE_MUL, RS, RD) +#define MULPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_MUL, MD, MB, MI, MS, RD) +#define MULPDrr(RS, RD) _SSEPDrr(X86_SSE_MUL, RS, RD) +#define MULPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_MUL, MD, MB, MI, MS, RD) + +#define MULSSrr(RS, RD) _SSESSrr(X86_SSE_MUL, RS, RD) +#define MULSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_MUL, MD, MB, MI, MS, RD) +#define MULSDrr(RS, RD) _SSESDrr(X86_SSE_MUL, RS, RD) +#define MULSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_MUL, MD, MB, MI, MS, RD) + +#define ORPSrr(RS, RD) _SSEPSrr(X86_SSE_OR, RS, RD) +#define ORPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_OR, MD, MB, MI, MS, RD) +#define ORPDrr(RS, RD) _SSEPDrr(X86_SSE_OR, RS, RD) +#define ORPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_OR, MD, MB, MI, MS, RD) + +#define RCPPSrr(RS, RD) _SSEPSrr(X86_SSE_RCP, RS, RD) +#define RCPPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_RCP, MD, MB, MI, MS, RD) +#define RCPSSrr(RS, RD) _SSESSrr(X86_SSE_RCP, RS, RD) +#define RCPSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_RCP, MD, MB, MI, MS, RD) + +#define RSQRTPSrr(RS, RD) _SSEPSrr(X86_SSE_RSQRT, RS, RD) +#define RSQRTPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_RSQRT, MD, MB, MI, MS, RD) +#define RSQRTSSrr(RS, RD) _SSESSrr(X86_SSE_RSQRT, RS, RD) +#define RSQRTSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_RSQRT, MD, MB, MI, MS, RD) + +#define SQRTPSrr(RS, RD) _SSEPSrr(X86_SSE_SQRT, RS, RD) +#define SQRTPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) +#define SQRTPDrr(RS, RD) _SSEPDrr(X86_SSE_SQRT, RS, RD) +#define SQRTPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) + +#define SQRTSSrr(RS, RD) _SSESSrr(X86_SSE_SQRT, RS, RD) +#define SQRTSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) +#define SQRTSDrr(RS, RD) _SSESDrr(X86_SSE_SQRT, RS, RD) +#define SQRTSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_SQRT, MD, MB, MI, MS, RD) + +#define SUBPSrr(RS, RD) _SSEPSrr(X86_SSE_SUB, RS, RD) +#define SUBPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_SUB, MD, MB, MI, MS, RD) +#define SUBPDrr(RS, RD) _SSEPDrr(X86_SSE_SUB, RS, RD) +#define SUBPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_SUB, MD, MB, MI, MS, RD) + +#define SUBSSrr(RS, RD) _SSESSrr(X86_SSE_SUB, RS, RD) +#define SUBSSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_SUB, MD, MB, MI, MS, RD) +#define SUBSDrr(RS, RD) _SSESDrr(X86_SSE_SUB, RS, RD) +#define SUBSDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_SUB, MD, MB, MI, MS, RD) + +#define XORPSrr(RS, RD) _SSEPSrr(X86_SSE_XOR, RS, RD) +#define XORPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_XOR, MD, MB, MI, MS, RD) +#define XORPDrr(RS, RD) _SSEPDrr(X86_SSE_XOR, RS, RD) +#define XORPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_XOR, MD, MB, MI, MS, RD) + +#define COMISSrr(RS, RD) _SSESSrr(X86_SSE_COMI, RS, RD) +#define COMISSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_COMI, MD, MB, MI, MS, RD) +#define COMISDrr(RS, RD) _SSESDrr(X86_SSE_COMI, RS, RD) +#define COMISDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_COMI, MD, MB, MI, MS, RD) + +#define UCOMISSrr(RS, RD) _SSESSrr(X86_SSE_UCOMI, RS, RD) +#define UCOMISSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD) +#define UCOMISDrr(RS, RD) _SSESDrr(X86_SSE_UCOMI, RS, RD) +#define UCOMISDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD) + +#define MOVAPSrr(RS, RD) _SSEPSrr(0x28, RS, RD) +#define MOVAPSmr(MD, MB, MI, MS, RD) _SSEPSmr(0x28, MD, MB, MI, MS, RD) +#define MOVAPSrm(RS, MD, MB, MI, MS) _SSEPSrm(0x29, RS, MD, MB, MI, MS) + +#define MOVAPDrr(RS, RD) _SSEPDrr(0x28, RS, RD) +#define MOVAPDmr(MD, MB, MI, MS, RD) _SSEPDmr(0x28, MD, MB, MI, MS, RD) +#define MOVAPDrm(RS, MD, MB, MI, MS) _SSEPDrm(0x29, RS, MD, MB, MI, MS) + +#define CVTPS2PIrr(RS, RD) __SSELrr( X86_SSE_CVTSI, RS,_rX, RD,_rM) +#define CVTPS2PImr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTSI, MD, MB, MI, MS, RD,_rM) +#define CVTPD2PIrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTSI, RS,_rX, RD,_rM) +#define CVTPD2PImr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_rM) + +#define CVTPI2PSrr(RS, RD) __SSELrr( X86_SSE_CVTIS, RS,_rM, RD,_rX) +#define CVTPI2PSmr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX) +#define CVTPI2PDrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTIS, RS,_rM, RD,_rX) +#define CVTPI2PDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX) + +#define CVTPS2PDrr(RS, RD) __SSELrr( X86_SSE_CVTSD, RS,_rX, RD,_rX) +#define CVTPS2PDmr(MD, MB, MI, MS, RD) __SSELmr( X86_SSE_CVTSD, MD, MB, MI, MS, RD,_rX) +#define CVTPD2PSrr(RS, RD) _SSELrr(0x66, X86_SSE_CVTSD, RS,_rX, RD,_rX) +#define CVTPD2PSmr(MD, MB, MI, MS, RD) _SSELmr(0x66, X86_SSE_CVTSD, MD, MB, MI, MS, RD,_rX) + +#define CVTSS2SDrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTSD, RS,_rX, RD,_rX) +#define CVTSS2SDmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTSD, MD, MB, MI, MS, RD,_rX) +#define CVTSD2SSrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTSD, RS,_rX, RD,_rX) +#define CVTSD2SSmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTSD, MD, MB, MI, MS, RD,_rX) + +#define CVTSS2SILrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTSI, RS,_rX, RD,_r4) +#define CVTSS2SILmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_r4) +#define CVTSD2SILrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTSI, RS,_rX, RD,_r4) +#define CVTSD2SILmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_r4) + +#define CVTSI2SSLrr(RS, RD) _SSELrr(0xf3, X86_SSE_CVTIS, RS,_r4, RD,_rX) +#define CVTSI2SSLmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX) +#define CVTSI2SDLrr(RS, RD) _SSELrr(0xf2, X86_SSE_CVTIS, RS,_r4, RD,_rX) +#define CVTSI2SDLmr(MD, MB, MI, MS, RD) _SSELmr(0xf2, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX) + +#define CVTSS2SIQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTSI, RS,_rX, RD,_r8) +#define CVTSS2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_r8) +#define CVTSD2SIQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTSI, RS,_rX, RD,_r8) +#define CVTSD2SIQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTSI, MD, MB, MI, MS, RD,_r8) + +#define CVTSI2SSQrr(RS, RD) _SSEQrr(0xf3, X86_SSE_CVTIS, RS,_r8, RD,_rX) +#define CVTSI2SSQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf3, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX) +#define CVTSI2SDQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTIS, RS,_r8, RD,_rX) +#define CVTSI2SDQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX) + +#define MOVDLXrr(RS, RD) _SSELrr(0x66, 0x6e, RS,_r4, RD,_rX) +#define MOVDLXmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX) +#define MOVDQXrr(RS, RD) _SSEQrr(0x66, 0x6e, RS,_r8, RD,_rX) +#define MOVDQXmr(MD, MB, MI, MS, RD) _SSEQmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX) + +#define MOVDXLrr(RS, RD) _SSELrr(0x66, 0x7e, RS,_rX, RD,_r4) +#define MOVDXLrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS) +#define MOVDXQrr(RS, RD) _SSEQrr(0x66, 0x7e, RS,_rX, RD,_r8) +#define MOVDXQrm(RS, MD, MB, MI, MS) _SSEQrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS) + +#define MOVDLMrr(RS, RD) __SSELrr( 0x6e, RS,_r4, RD,_rM) +#define MOVDLMmr(MD, MB, MI, MS, RD) __SSELmr( 0x6e, MD, MB, MI, MS, RD,_rM) +#define MOVDQMrr(RS, RD) __SSEQrr( 0x6e, RS,_r8, RD,_rM) +#define MOVDQMmr(MD, MB, MI, MS, RD) __SSEQmr( 0x6e, MD, MB, MI, MS, RD,_rM) + +#define MOVDMLrr(RS, RD) __SSELrr( 0x7e, RS,_rM, RD,_r4) +#define MOVDMLrm(RS, MD, MB, MI, MS) __SSELrm( 0x7e, RS,_rM, MD, MB, MI, MS) +#define MOVDMQrr(RS, RD) __SSEQrr( 0x7e, RS,_rM, RD,_r8) +#define MOVDMQrm(RS, MD, MB, MI, MS) __SSEQrm( 0x7e, RS,_rM, MD, MB, MI, MS) + +#define MOVDQ2Qrr(RS, RD) _SSELrr(0xf2, 0xd6, RS,_rX, RD,_rM) +#define MOVHLPSrr(RS, RD) __SSELrr( 0x12, RS,_rX, RD,_rX) +#define MOVLHPSrr(RS, RD) __SSELrr( 0x16, RS,_rX, RD,_rX) + +#define MOVDQArr(RS, RD) _SSELrr(0x66, 0x6f, RS,_rX, RD,_rX) +#define MOVDQAmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x6f, MD, MB, MI, MS, RD,_rX) +#define MOVDQArm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x7f, RS,_rX, MD, MB, MI, MS) + +#define MOVDQUrr(RS, RD) _SSELrr(0xf3, 0x6f, RS,_rX, RD,_rX) +#define MOVDQUmr(MD, MB, MI, MS, RD) _SSELmr(0xf3, 0x6f, MD, MB, MI, MS, RD,_rX) +#define MOVDQUrm(RS, MD, MB, MI, MS) _SSELrm(0xf3, 0x7f, RS,_rX, MD, MB, MI, MS) + +#define MOVHPDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x16, MD, MB, MI, MS, RD,_rX) +#define MOVHPDrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x17, RS,_rX, MD, MB, MI, MS) +#define MOVHPSmr(MD, MB, MI, MS, RD) __SSELmr( 0x16, MD, MB, MI, MS, RD,_rX) +#define MOVHPSrm(RS, MD, MB, MI, MS) __SSELrm( 0x17, RS,_rX, MD, MB, MI, MS) + +#define MOVLPDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x12, MD, MB, MI, MS, RD,_rX) +#define MOVLPDrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x13, RS,_rX, MD, MB, MI, MS) +#define MOVLPSmr(MD, MB, MI, MS, RD) __SSELmr( 0x12, MD, MB, MI, MS, RD,_rX) +#define MOVLPSrm(RS, MD, MB, MI, MS) __SSELrm( 0x13, RS,_rX, MD, MB, MI, MS) + + +/* --- FLoating-Point instructions ----------------------------------------- */ + +#define _ESCmi(D,B,I,S,OP) (_REXLrm(0,B,I), _O_r_X(0xd8|(OP & 7), (OP >> 3), D,B,I,S)) + +#define FLDr(R) _OOr(0xd9c0,_rN(R)) +#define FLDLm(D,B,I,S) _ESCmi(D,B,I,S,005) +#define FLDSm(D,B,I,S) _ESCmi(D,B,I,S,001) +#define FLDTm(D,B,I,S) _ESCmi(D,B,I,S,053) + +#define FSTr(R) _OOr(0xddd0,_rN(R)) +#define FSTSm(D,B,I,S) _ESCmi(D,B,I,S,021) +#define FSTLm(D,B,I,S) _ESCmi(D,B,I,S,025) + +#define FSTPr(R) _OOr(0xddd8,_rN(R)) +#define FSTPSm(D,B,I,S) _ESCmi(D,B,I,S,031) +#define FSTPLm(D,B,I,S) _ESCmi(D,B,I,S,035) +#define FSTPTm(D,B,I,S) _ESCmi(D,B,I,S,073) + +#define FADDr0(R) _OOr(0xd8c0,_rN(R)) +#define FADD0r(R) _OOr(0xdcc0,_rN(R)) +#define FADDP0r(R) _OOr(0xdec0,_rN(R)) +#define FADDSm(D,B,I,S) _ESCmi(D,B,I,S,000) +#define FADDLm(D,B,I,S) _ESCmi(D,B,I,S,004) + +#define FSUBSm(D,B,I,S) _ESCmi(D,B,I,S,040) +#define FSUBLm(D,B,I,S) _ESCmi(D,B,I,S,044) +#define FSUBr0(R) _OOr(0xd8e0,_rN(R)) +#define FSUB0r(R) _OOr(0xdce8,_rN(R)) +#define FSUBP0r(R) _OOr(0xdee8,_rN(R)) + +#define FSUBRr0(R) _OOr(0xd8e8,_rN(R)) +#define FSUBR0r(R) _OOr(0xdce0,_rN(R)) +#define FSUBRP0r(R) _OOr(0xdee0,_rN(R)) +#define FSUBRSm(D,B,I,S) _ESCmi(D,B,I,S,050) +#define FSUBRLm(D,B,I,S) _ESCmi(D,B,I,S,054) + +#define FMULr0(R) _OOr(0xd8c8,_rN(R)) +#define FMUL0r(R) _OOr(0xdcc8,_rN(R)) +#define FMULP0r(R) _OOr(0xdec8,_rN(R)) +#define FMULSm(D,B,I,S) _ESCmi(D,B,I,S,010) +#define FMULLm(D,B,I,S) _ESCmi(D,B,I,S,014) + +#define FDIVr0(R) _OOr(0xd8f0,_rN(R)) +#define FDIV0r(R) _OOr(0xdcf8,_rN(R)) +#define FDIVP0r(R) _OOr(0xdef8,_rN(R)) +#define FDIVSm(D,B,I,S) _ESCmi(D,B,I,S,060) +#define FDIVLm(D,B,I,S) _ESCmi(D,B,I,S,064) + +#define FDIVRr0(R) _OOr(0xd8f8,_rN(R)) +#define FDIVR0r(R) _OOr(0xdcf0,_rN(R)) +#define FDIVRP0r(R) _OOr(0xdef0,_rN(R)) +#define FDIVRSm(D,B,I,S) _ESCmi(D,B,I,S,070) +#define FDIVRLm(D,B,I,S) _ESCmi(D,B,I,S,074) + +#define FCMOVBr0(R) _OOr(0xdac0,_rN(R)) +#define FCMOVBEr0(R) _OOr(0xdad0,_rN(R)) +#define FCMOVEr0(R) _OOr(0xdac8,_rN(R)) +#define FCMOVNBr0(R) _OOr(0xdbc0,_rN(R)) +#define FCMOVNBEr0(R) _OOr(0xdbd0,_rN(R)) +#define FCMOVNEr0(R) _OOr(0xdbc8,_rN(R)) +#define FCMOVNUr0(R) _OOr(0xdbd8,_rN(R)) +#define FCMOVUr0(R) _OOr(0xdad8,_rN(R)) +#define FCOMIr0(R) _OOr(0xdbf0,_rN(R)) +#define FCOMIPr0(R) _OOr(0xdff0,_rN(R)) + +#define FCOMr(R) _OOr(0xd8d0,_rN(R)) +#define FCOMSm(D,B,I,S) _ESCmi(D,B,I,S,020) +#define FCOMLm(D,B,I,S) _ESCmi(D,B,I,S,024) + +#define FCOMPr(R) _OOr(0xd8d8,_rN(R)) +#define FCOMPSm(D,B,I,S) _ESCmi(D,B,I,S,030) +#define FCOMPLm(D,B,I,S) _ESCmi(D,B,I,S,034) + +#define FUCOMIr0(R) _OOr(0xdbe8,_rN(R)) +#define FUCOMIPr0(R) _OOr(0xdfe8,_rN(R)) +#define FUCOMPr(R) _OOr(0xdde8,_rN(R)) +#define FUCOMr(R) _OOr(0xdde0,_rN(R)) + +#define FIADDLm(D,B,I,S) _ESCmi(D,B,I,S,002) +#define FICOMLm(D,B,I,S) _ESCmi(D,B,I,S,022) +#define FICOMPLm(D,B,I,S) _ESCmi(D,B,I,S,032) +#define FIDIVLm(D,B,I,S) _ESCmi(D,B,I,S,062) +#define FIDIVRLm(D,B,I,S) _ESCmi(D,B,I,S,072) +#define FILDLm(D,B,I,S) _ESCmi(D,B,I,S,003) +#define FILDQm(D,B,I,S) _ESCmi(D,B,I,S,057) +#define FIMULLm(D,B,I,S) _ESCmi(D,B,I,S,012) +#define FISTLm(D,B,I,S) _ESCmi(D,B,I,S,023) +#define FISTPLm(D,B,I,S) _ESCmi(D,B,I,S,033) +#define FISTPQm(D,B,I,S) _ESCmi(D,B,I,S,077) +#define FISUBLm(D,B,I,S) _ESCmi(D,B,I,S,042) +#define FISUBRLm(D,B,I,S) _ESCmi(D,B,I,S,052) + +#define FREEr(R) _OOr(0xddc0,_rN(R)) +#define FXCHr(R) _OOr(0xd9c8,_rN(R)) + +#endif /* X86_RTASM_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h new file mode 100644 index 00000000..6e3abb1e --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -0,0 +1,543 @@ +/* + * compiler/compemu.h - Public interface and definitions + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> IA-32 and AMD64 + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef COMPEMU_H +#define COMPEMU_H + +// #include "sysconfig.h" +#include "newcpu.h" + +#ifdef UAE +#ifdef CPU_64_BIT +typedef uae_u64 uintptr; +#else +typedef uae_u32 uintptr; +#endif +/* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */ +// #define USE_JIT +#endif + +#ifdef USE_JIT + +#ifdef JIT_DEBUG +/* dump some information (m68k block, x86 block addresses) about the compiler state */ +extern void compiler_dumpstate(void); +#endif + +/* Now that we do block chaining, and also have linked lists on each tag, + TAGMASK can be much smaller and still do its job. Saves several megs + of memory! */ +#define TAGMASK 0x0000ffff +#define TAGSIZE (TAGMASK+1) +#define MAXRUN 1024 +#define cacheline(x) (((uintptr)x)&TAGMASK) + +extern uae_u8* start_pc_p; +extern uae_u32 start_pc; + +struct blockinfo_t; + +struct cpu_history { + uae_u16* location; +#ifdef UAE + uae_u8 specmem; +#endif +}; + +union cacheline { + cpuop_func* handler; + blockinfo_t * bi; +}; + +/* Use new spill/reload strategy when calling external functions */ +#define USE_OPTIMIZED_CALLS 0 +#if USE_OPTIMIZED_CALLS +#error implementation in progress +#endif + +/* (gb) When on, this option can save save up to 30% compilation time + * when many lazy flushes occur (e.g. apps in MacOS 8.x). + */ +#define USE_SEPARATE_BIA 1 + +/* Use chain of checksum_info_t to compute the block checksum */ +#define USE_CHECKSUM_INFO 1 + +/* Use code inlining, aka follow-up of constant jumps */ +#define USE_INLINING 1 + +/* Inlining requires the chained checksuming information */ +#if USE_INLINING +#undef USE_CHECKSUM_INFO +#define USE_CHECKSUM_INFO 1 +#endif + +/* Does flush_icache_range() only check for blocks falling in the requested range? */ +#define LAZY_FLUSH_ICACHE_RANGE 0 + +#define USE_F_ALIAS 1 +#define USE_OFFSET 1 +#define COMP_DEBUG 1 + +#if COMP_DEBUG +#define Dif(x) if (x) +#else +#define Dif(x) if (0) +#endif + +#define SCALE 2 + +#define BYTES_PER_INST 10240 /* paranoid ;-) */ +#if defined(CPU_arm) +#define LONGEST_68K_INST 256 /* The number of bytes the longest possible + 68k instruction takes */ +#else +#define LONGEST_68K_INST 16 /* The number of bytes the longest possible + 68k instruction takes */ +#endif +#define MAX_CHECKSUM_LEN 2048 /* The maximum size we calculate checksums + for. Anything larger will be flushed + unconditionally even with SOFT_FLUSH */ +#define MAX_HOLD_BI 3 /* One for the current block, and up to two + for jump targets */ + +#define INDIVIDUAL_INST 0 +#define FLAG_X 0x0010 +#define FLAG_N 0x0008 +#define FLAG_Z 0x0004 +#define FLAG_V 0x0002 +#define FLAG_C 0x0001 +#define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V) +#define FLAG_ALL (FLAG_C | FLAG_Z | FLAG_N | FLAG_V | FLAG_X) +#define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V) + +#define KILLTHERAT 1 /* Set to 1 to avoid some partial_rat_stalls */ + +#if defined(CPU_arm) +#define USE_DATA_BUFFER +#define N_REGS 13 /* really 16, but 13 to 15 are SP, LR, PC */ +#else +#if defined(CPU_x86_64) +#define N_REGS 16 /* really only 15, but they are numbered 0-3,5-15 */ +#else +#define N_REGS 8 /* really only 7, but they are numbered 0,1,2,3,5,6,7 */ +#endif +#endif +#define N_FREGS 6 /* That leaves us two positions on the stack to play with */ + +/* Functions exposed to newcpu, or to what was moved from newcpu.c to + * compemu_support.c */ +#ifdef WINUAE_ARANYM +extern void compiler_init(void); +extern void compiler_exit(void); +extern bool compiler_use_jit(void); +#endif +extern void init_comp(void); +extern void flush(int save_regs); +extern void small_flush(int save_regs); +extern void set_target(uae_u8* t); +extern uae_u8* get_target(void); +extern void freescratch(void); +extern void build_comp(void); +extern void set_cache_state(int enabled); +extern int get_cache_state(void); +extern uae_u32 get_jitted_size(void); +#ifdef JIT +#ifdef WINUAE_ARANYM +extern void (*flush_icache)(int n); +#else +extern void flush_icache(int n); +#endif +#endif +extern void alloc_cache(void); +extern int check_for_cache_miss(void); + +/* JIT FPU compilation */ +extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra); +extern void comp_fbcc_opp (uae_u32 opcode); +extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra); +void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra); +void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc); +void comp_fsave_opp (uae_u32 opcode); +void comp_frestore_opp (uae_u32 opcode); + +extern uae_u32 needed_flags; +extern uae_u8* comp_pc_p; +extern void* pushall_call_handler; + +#define VREGS 32 +#define VFREGS 16 + +#define INMEM 1 +#define CLEAN 2 +#define DIRTY 3 +#define UNDEF 4 +#define ISCONST 5 + +typedef struct { + uae_u32* mem; + uae_u32 val; + uae_u8 is_swapped; + uae_u8 status; + uae_s8 realreg; /* gb-- realreg can hold -1 */ + uae_u8 realind; /* The index in the holds[] array */ + uae_u8 needflush; + uae_u8 validsize; + uae_u8 dirtysize; + uae_u8 dummy; +} reg_status; + +typedef struct { + uae_u32* mem; + double val; + uae_u8 status; + uae_s8 realreg; /* gb-- realreg can hold -1 */ + uae_u8 realind; + uae_u8 needflush; +} freg_status; + +#define PC_P 16 +#define FLAGX 17 +#define FLAGTMP 18 +#define NEXT_HANDLER 19 +#define S1 20 +#define S2 21 +#define S3 22 +#define S4 23 +#define S5 24 +#define S6 25 +#define S7 26 +#define S8 27 +#define S9 28 +#define S10 29 +#define S11 30 +#define S12 31 + +#define FP_RESULT 8 +#define FS1 9 +#define FS2 10 +#define FS3 11 + +typedef struct { + uae_u32 touched; + uae_s8 holds[VREGS]; + uae_u8 nholds; + uae_u8 canbyte; + uae_u8 canword; + uae_u8 locked; +} n_status; + +typedef struct { + uae_u32 touched; + uae_s8 holds[VFREGS]; + uae_u8 nholds; + uae_u8 locked; +} fn_status; + +/* For flag handling */ +#define NADA 1 +#define TRASH 2 +#define VALID 3 + +/* needflush values */ +#define NF_SCRATCH 0 +#define NF_TOMEM 1 +#define NF_HANDLER 2 + +typedef struct { + /* Integer part */ + reg_status state[VREGS]; + n_status nat[N_REGS]; + uae_u32 flags_on_stack; + uae_u32 flags_in_flags; + uae_u32 flags_are_important; + /* FPU part */ + freg_status fate[VFREGS]; + fn_status fat[N_FREGS]; + + /* x86 FPU part */ + uae_s8 spos[N_FREGS]; + uae_s8 onstack[6]; + uae_s8 tos; +} bigstate; + +typedef struct { + /* Integer part */ + uae_s8 virt[VREGS]; + uae_s8 nat[N_REGS]; +} smallstate; + +extern int touchcnt; + +#define IMM uae_s32 +#define RR1 uae_u32 +#define RR2 uae_u32 +#define RR4 uae_u32 +/* + R1, R2, R4 collides with ARM registers defined in ucontext +#define R1 uae_u32 +#define R2 uae_u32 +#define R4 uae_u32 +*/ +#define W1 uae_u32 +#define W2 uae_u32 +#define W4 uae_u32 +#define RW1 uae_u32 +#define RW2 uae_u32 +#define RW4 uae_u32 +#define MEMR uae_u32 +#define MEMW uae_u32 +#define MEMRW uae_u32 + +#define FW uae_u32 +#define FR uae_u32 +#define FRW uae_u32 + +#define MIDFUNC(nargs,func,args) void func args +#define MENDFUNC(nargs,func,args) +#define COMPCALL(func) func + +#define LOWFUNC(flags,mem,nargs,func,args) static inline void func args +#define LENDFUNC(flags,mem,nargs,func,args) + +/* What we expose to the outside */ +#define DECLARE_MIDFUNC(func) extern void func + +#if defined(CPU_arm) + +#include "compemu_midfunc_arm.h" + +#if defined(USE_JIT2) +#include "compemu_midfunc_arm2.h" +#endif +#endif + +#if defined(CPU_i386) || defined(CPU_x86_64) +#include "compemu_midfunc_x86.h" +#endif + +#undef DECLARE_MIDFUNC + +extern int failure; +#define FAIL(x) do { failure|=x; } while (0) + +/* Convenience functions exposed to gencomp */ +extern uae_u32 m68k_pc_offset; +extern void readbyte(int address, int dest, int tmp); +extern void readword(int address, int dest, int tmp); +extern void readlong(int address, int dest, int tmp); +extern void writebyte(int address, int source, int tmp); +extern void writeword(int address, int source, int tmp); +extern void writelong(int address, int source, int tmp); +extern void writeword_clobber(int address, int source, int tmp); +extern void writelong_clobber(int address, int source, int tmp); +extern void get_n_addr(int address, int dest, int tmp); +extern void get_n_addr_jmp(int address, int dest, int tmp); +extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp); +/* Set native Z flag only if register is zero */ +extern void set_zero(int r, int tmp); +extern int kill_rodent(int r); +#define SYNC_PC_OFFSET 100 +extern void sync_m68k_pc(void); +extern uae_u32 get_const(int r); +extern int is_const(int r); +extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond); + +#define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1)) +#define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o))) +#define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o))) + +struct blockinfo_t; + +typedef struct dep_t { + uae_u32* jmp_off; + struct blockinfo_t* target; + struct blockinfo_t* source; + struct dep_t** prev_p; + struct dep_t* next; +} dependency; + +typedef struct checksum_info_t { + uae_u8 *start_p; + uae_u32 length; + struct checksum_info_t *next; +} checksum_info; + +typedef struct blockinfo_t { + uae_s32 count; + cpuop_func* direct_handler_to_use; + cpuop_func* handler_to_use; + /* The direct handler does not check for the correct address */ + + cpuop_func* handler; + cpuop_func* direct_handler; + + cpuop_func* direct_pen; + cpuop_func* direct_pcc; + +#ifdef UAE + uae_u8* nexthandler; +#endif + uae_u8* pc_p; + + uae_u32 c1; + uae_u32 c2; +#if USE_CHECKSUM_INFO + checksum_info *csi; +#else + uae_u32 len; + uae_u32 min_pcp; +#endif + + struct blockinfo_t* next_same_cl; + struct blockinfo_t** prev_same_cl_p; + struct blockinfo_t* next; + struct blockinfo_t** prev_p; + + uae_u8 optlevel; + uae_u8 needed_flags; + uae_u8 status; + uae_u8 havestate; + + dependency dep[2]; /* Holds things we depend on */ + dependency* deplist; /* List of things that depend on this */ + smallstate env; + +#ifdef JIT_DEBUG + /* (gb) size of the compiled block (direct handler) */ + uae_u32 direct_handler_size; +#endif +} blockinfo; + +#define BI_INVALID 0 +#define BI_ACTIVE 1 +#define BI_NEED_RECOMP 2 +#define BI_NEED_CHECK 3 +#define BI_CHECKING 4 +#define BI_COMPILING 5 +#define BI_FINALIZING 6 + +void execute_normal(void); +void exec_nostats(void); +void do_nothing(void); + +#else + +static inline void flush_icache(int) { } +static inline void build_comp() { } + +#endif /* !USE_JIT */ + +#ifdef UAE + +typedef struct { + uae_u8 type; + uae_u8 reg; + uae_u32 next; +} regacc; + +#define JIT_EXCEPTION_HANDLER +// #define JIT_ALWAYS_DISTRUST + +/* ARAnyM uses fpu_register name, used in scratch_t */ +/* FIXME: check that no ARAnyM code assumes different floating point type */ +typedef fptype fpu_register; + +extern void compile_block(cpu_history* pc_hist, int blocklen, int totcyles); + +#define MAXCYCLES (1000 * CYCLE_UNIT) +#define scaled_cycles(x) (currprefs.m68k_speed<0?(((x)/SCALE)?(((x)/SCALE (uintptr_t) 0xffffffff) { + jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)", + (unsigned long long)address, file, line); + } + return (uae_u32) address; +} +#define uae_p32(x) (check_uae_p32((uintptr)(x), __FILE__, __LINE__)) +#else +#define uae_p32(x) ((uae_u32)(x)) +#endif + +#endif /* COMPEMU_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/compemu1.cpp b/BasiliskII/src/uae_cpu/compiler/compemu1.cpp new file mode 100644 index 00000000..297c6250 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu1.cpp @@ -0,0 +1,2 @@ +#define PART_1 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu2.cpp b/BasiliskII/src/uae_cpu/compiler/compemu2.cpp new file mode 100644 index 00000000..8c0ddeac --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu2.cpp @@ -0,0 +1,2 @@ +#define PART_2 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu3.cpp b/BasiliskII/src/uae_cpu/compiler/compemu3.cpp new file mode 100644 index 00000000..975e0669 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu3.cpp @@ -0,0 +1,2 @@ +#define PART_3 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu4.cpp b/BasiliskII/src/uae_cpu/compiler/compemu4.cpp new file mode 100644 index 00000000..a49b5444 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu4.cpp @@ -0,0 +1,2 @@ +#define PART_4 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu5.cpp b/BasiliskII/src/uae_cpu/compiler/compemu5.cpp new file mode 100644 index 00000000..41e872f6 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu5.cpp @@ -0,0 +1,2 @@ +#define PART_5 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu6.cpp b/BasiliskII/src/uae_cpu/compiler/compemu6.cpp new file mode 100644 index 00000000..9156e597 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu6.cpp @@ -0,0 +1,2 @@ +#define PART_6 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu7.cpp b/BasiliskII/src/uae_cpu/compiler/compemu7.cpp new file mode 100644 index 00000000..63108e04 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu7.cpp @@ -0,0 +1,2 @@ +#define PART_7 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu8.cpp b/BasiliskII/src/uae_cpu/compiler/compemu8.cpp new file mode 100644 index 00000000..543f9dfd --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu8.cpp @@ -0,0 +1,2 @@ +#define PART_8 +#include "compemu.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp new file mode 100644 index 00000000..cef6d43e --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp @@ -0,0 +1,1638 @@ +/* + * compiler/compemu_fpp.cpp - Dynamic translation of FPU instructions + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> IA-32 and AMD64 + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * UAE - The Un*x Amiga Emulator + * + * MC68881 emulation + * + * Copyright 1996 Herman ten Brugge + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + */ + +#include "sysdeps.h" + +# include +# include +# include + +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#include "main.h" +#include "compiler/compemu.h" +#include "fpu/fpu.h" +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" + +#define DEBUG 0 +#include "debug.h" + +// gb-- WARNING: get_fpcr() and set_fpcr() support is experimental +#define HANDLE_FPCR 0 + +// - IEEE-based fpu core must be used +#if defined(FPU_IEEE) +# define CAN_HANDLE_FPCR +#endif + +// - Generic rounding mode and precision modes are supported if set together +#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION) +# define CAN_HANDLE_FPCR +#endif + +// - X86 rounding mode and precision modes are *not* supported but might work (?!) +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) +# define CAN_HANDLE_FPCR +#endif + +#if HANDLE_FPCR && !defined(CAN_HANDLE_FPCR) +# warning "Can't handle FPCR, will FAIL(1) at runtime" +# undef HANDLE_FPCR +# define HANDLE_FPCR 0 +#endif + +#define STATIC_INLINE static inline +#define MAKE_FPSR(r) do { fmov_rr(FP_RESULT,r); } while (0) + +#define delay nop() ;nop() +#define delay2 nop() ;nop() + +#define UNKNOWN_EXTRA 0xFFFFFFFF +static void fpuop_illg(uae_u32 opcode, uae_u32 /* extra */) +{ +/* + if (extra == UNKNOWN_EXTRA) + printf("FPU opcode %x, extra UNKNOWN_EXTRA\n",opcode & 0xFFFF); + else + printf("FPU opcode %x, extra %x\n",opcode & 0xFFFF,extra & 0xFFFF); +*/ + op_illg(opcode); +} + +uae_s32 temp_fp[4]; /* To convert between FP/integer */ + +/* return register number, or -1 for failure */ +STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra) +{ + uaecptr tmppc; + uae_u16 tmp; + int size; + int mode; + int reg; + uae_u32 ad = 0; + static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; + static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; + + if ((extra & 0x4000) == 0) { + return ((extra >> 10) & 7); + } + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + switch (mode) { + case 0: + switch (size) { + case 6: + sign_extend_8_rr(S1,reg); + mov_l_mr((uintptr)temp_fp,S1); + delay2; + fmovi_rm(FS1,(uintptr)temp_fp); + return FS1; + case 4: + sign_extend_16_rr(S1,reg); + mov_l_mr((uintptr)temp_fp,S1); + delay2; + fmovi_rm(FS1,(uintptr)temp_fp); + return FS1; + case 0: + mov_l_mr((uintptr)temp_fp,reg); + delay2; + fmovi_rm(FS1,(uintptr)temp_fp); + return FS1; + case 1: + mov_l_mr((uintptr)temp_fp,reg); + delay2; + fmovs_rm(FS1,(uintptr)temp_fp); + return FS1; + default: + return -1; + } + return -1; /* Should be unreachable */ + case 1: + return -1; /* Genuine invalid instruction */ + default: + break; + } + /* OK, we *will* have to load something from an address. Let's make + sure we know how to handle that, or quit early --- i.e. *before* + we do any postincrement/predecrement that we may regret */ + + switch (size) { + case 3: + return -1; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + break; + default: + return -1; + } + + switch (mode) { + case 2: + ad=S1; /* We will change it, anyway ;-) */ + mov_l_rr(ad,reg+8); + break; + case 3: + ad=S1; + mov_l_rr(ad,reg+8); + lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size])); + break; + case 4: + ad=S1; + + lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size])); + mov_l_rr(ad,reg+8); + break; + case 5: + { + uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + mov_l_rr(ad,reg+8); + lea_l_brr(ad,ad,off); + break; + } + case 6: + { + uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + calc_disp_ea_020(reg+8,dp,ad,S2); + break; + } + case 7: + switch (reg) { + case 0: + { + uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + mov_l_ri(ad,off); + break; + } + case 1: + { + uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4); + ad=S1; + mov_l_ri(ad,off); + break; + } + case 2: + { + uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ + m68k_pc_offset; + uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + mov_l_ri(ad,address+PC16off); + break; + } + case 3: + return -1; + tmppc = m68k_getpc (); + tmp = next_iword (); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + { + uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ m68k_pc_offset; + ad=S1; + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + if (size == 6) address++; + mov_l_ri(ad,address); + m68k_pc_offset+=sz2[size]; + break; + } + default: + return -1; + } + } + + switch (size) { + case 0: + readlong(ad,S2,S3); + mov_l_mr((uintptr)temp_fp,S2); + delay2; + fmovi_rm(FS1,(uintptr)temp_fp); + break; + case 1: + readlong(ad,S2,S3); + mov_l_mr((uintptr)temp_fp,S2); + delay2; + fmovs_rm(FS1,(uintptr)temp_fp); + break; + case 2: + readword(ad,S2,S3); + mov_w_mr(((uintptr)temp_fp)+8,S2); + add_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp)+4,S2); + add_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp),S2); + delay2; + fmov_ext_rm(FS1,(uintptr)(temp_fp)); + break; + case 3: + return -1; /* Some silly "packed" stuff */ + case 4: + readword(ad,S2,S3); + sign_extend_16_rr(S2,S2); + mov_l_mr((uintptr)temp_fp,S2); + delay2; + fmovi_rm(FS1,(uintptr)temp_fp); + break; + case 5: + readlong(ad,S2,S3); + mov_l_mr(((uintptr)temp_fp)+4,S2); + add_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp),S2); + delay2; + fmov_rm(FS1,(uintptr)(temp_fp)); + break; + case 6: + readbyte(ad,S2,S3); + sign_extend_8_rr(S2,S2); + mov_l_mr((uintptr)temp_fp,S2); + delay2; + fmovi_rm(FS1,(uintptr)temp_fp); + break; + default: + return -1; + } + return FS1; +} + +/* return of -1 means failure, >=0 means OK */ +STATIC_INLINE int put_fp_value (int val, uae_u32 opcode, uae_u16 extra) +{ + uae_u16 tmp; + uaecptr tmppc; + int size; + int mode; + int reg; + uae_u32 ad; + static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; + static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; + + if ((extra & 0x4000) == 0) { + const int dest_reg = (extra >> 10) & 7; + fmov_rr(dest_reg, val); + // gb-- status register is affected + MAKE_FPSR(dest_reg); + return 0; + } + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + ad = (uae_u32)-1; + switch (mode) { + case 0: + switch (size) { + case 6: + fmovi_mr((uintptr)temp_fp,val); + delay; + mov_b_rm(reg,(uintptr)temp_fp); + return 0; + case 4: + fmovi_mr((uintptr)temp_fp,val); + delay; + mov_w_rm(reg,(uintptr)temp_fp); + return 0; + case 0: + fmovi_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(reg,(uintptr)temp_fp); + return 0; + case 1: + fmovs_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(reg,(uintptr)temp_fp); + return 0; + default: + return -1; + } + case 1: + return -1; /* genuine invalid instruction */ + default: break; + } + + /* Let's make sure we get out *before* doing something silly if + we can't handle the size */ + switch (size) { + case 0: + case 4: + case 5: + case 6: + case 2: + case 1: + break; + case 3: + default: + return -1; + } + + switch (mode) { + case 2: + ad=S1; + mov_l_rr(ad,reg+8); + break; + case 3: + ad=S1; + mov_l_rr(ad,reg+8); + lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size])); + break; + case 4: + ad=S1; + lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size])); + mov_l_rr(ad,reg+8); + break; + case 5: + { + uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + mov_l_rr(ad,reg+8); + add_l_ri(ad,off); + break; + } + case 6: + { + uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + calc_disp_ea_020(reg+8,dp,ad,S2); + break; + } + case 7: + switch (reg) { + case 0: + { + uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + mov_l_ri(ad,off); + break; + } + case 1: + { + uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4); + ad=S1; + mov_l_ri(ad,off); + break; + } + case 2: + { + uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ + m68k_pc_offset; + uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + ad=S1; + mov_l_ri(ad,address+PC16off); + break; + } + case 3: + return -1; + tmppc = m68k_getpc (); + tmp = next_iword (); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + { + uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ + m68k_pc_offset; + ad=S1; + mov_l_ri(ad,address); + m68k_pc_offset+=sz2[size]; + break; + } + default: + return -1; + } + } + switch (size) { + case 0: + fmovi_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(S2,(uintptr)temp_fp); + writelong_clobber(ad,S2,S3); + break; + case 1: + fmovs_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(S2,(uintptr)temp_fp); + writelong_clobber(ad,S2,S3); + break; + case 2: + fmov_ext_mr((uintptr)temp_fp,val); + delay; + mov_w_rm(S2,(uintptr)temp_fp+8); + writeword_clobber(ad,S2,S3); + add_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp+4); + writelong_clobber(ad,S2,S3); + add_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp); + writelong_clobber(ad,S2,S3); + break; + case 3: return -1; /* Packed */ + + case 4: + fmovi_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(S2,(uintptr)temp_fp); + writeword_clobber(ad,S2,S3); + break; + case 5: + fmov_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(S2,(uintptr)temp_fp+4); + writelong_clobber(ad,S2,S3); + add_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp); + writelong_clobber(ad,S2,S3); + break; + case 6: + fmovi_mr((uintptr)temp_fp,val); + delay; + mov_l_rm(S2,(uintptr)temp_fp); + writebyte(ad,S2,S3); + break; + default: + return -1; + } + return 0; +} + +/* return -1 for failure, or register number for success */ +STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad) +{ + uae_u16 tmp; + uaecptr tmppc; + int mode; + int reg; + uae_s32 off; + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) { + case 0: + case 1: + return -1; + case 2: + case 3: + case 4: + mov_l_rr(S1,8+reg); + return S1; + *ad = m68k_areg (regs, reg); + break; + case 5: + off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + + mov_l_rr(S1,8+reg); + add_l_ri(S1,off); + return S1; + case 6: + return -1; + break; + case 7: + switch (reg) { + case 0: + off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + mov_l_ri(S1,off); + return S1; + case 1: + off=comp_get_ilong((m68k_pc_offset+=4)-4); + mov_l_ri(S1,off); + return S1; + case 2: + return -1; +// *ad = m68k_getpc (); +// *ad += (uae_s32) (uae_s16) next_iword (); + off=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset; + off+=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + mov_l_ri(S1,off); + return S1; + case 3: + return -1; + tmppc = m68k_getpc (); + tmp = next_iword (); + *ad = get_disp_ea_020 (tmppc, tmp); + break; + default: + return -1; + } + } + abort(); +} + +void comp_fdbcc_opp (uae_u32 /* opcode */, uae_u16 /* extra */) +{ + FAIL(1); + return; +} + +void comp_fscc_opp (uae_u32 opcode, uae_u16 extra) +{ + uae_u32 ad; + int cc; + int reg; + +#ifdef DEBUG_FPP + printf ("fscc_opp at %08lx\n", m68k_getpc ()); + fflush (stdout); +#endif + + + if (extra&0x20) { /* only cc from 00 to 1f are defined */ + FAIL(1); + return; + } + if ((opcode & 0x38) != 0) { /* We can only do to integer register */ + FAIL(1); + return; + } + + fflags_into_flags(S2); + reg=(opcode&7); + + mov_l_ri(S1,255); + mov_l_ri(S4,0); + switch(extra&0x0f) { /* according to fpp.c, the 0x10 bit is ignored + */ + case 0: break; /* set never */ + case 1: mov_l_rr(S2,S4); + cmov_l_rr(S4,S1,4); + cmov_l_rr(S4,S2,10); break; + case 2: cmov_l_rr(S4,S1,7); break; + case 3: cmov_l_rr(S4,S1,3); break; + case 4: mov_l_rr(S2,S4); + cmov_l_rr(S4,S1,2); + cmov_l_rr(S4,S2,10); break; + case 5: mov_l_rr(S2,S4); + cmov_l_rr(S4,S1,6); + cmov_l_rr(S4,S2,10); break; + case 6: cmov_l_rr(S4,S1,5); break; + case 7: cmov_l_rr(S4,S1,11); break; + case 8: cmov_l_rr(S4,S1,10); break; + case 9: cmov_l_rr(S4,S1,4); break; + case 10: cmov_l_rr(S4,S1,10); cmov_l_rr(S4,S1,7); break; + case 11: cmov_l_rr(S4,S1,4); cmov_l_rr(S4,S1,3); break; + case 12: cmov_l_rr(S4,S1,2); break; + case 13: cmov_l_rr(S4,S1,6); break; + case 14: cmov_l_rr(S4,S1,5); cmov_l_rr(S4,S1,10); break; + case 15: mov_l_rr(S4,S1); break; + } + + if ((opcode & 0x38) == 0) { + mov_b_rr(reg,S4); + } else { + abort(); + if (get_fp_ad (opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + fpuop_illg (opcode,extra); + } else + put_byte (ad, cc ? 0xff : 0x00); + } +} + +void comp_ftrapcc_opp (uae_u32 /* opcode */, uaecptr /* oldpc */) +{ + FAIL(1); + return; +} + +void comp_fbcc_opp (uae_u32 opcode) +{ + uae_u32 start_68k_offset=m68k_pc_offset; + uae_u32 off; + uae_u32 v1; + uae_u32 v2; + int cc; + + // comp_pc_p is expected to be bound to 32-bit addresses + assert((uintptr)comp_pc_p <= 0xffffffffUL); + + if (opcode&0x20) { /* only cc from 00 to 1f are defined */ + FAIL(1); + return; + } + if ((opcode&0x40)==0) { + off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + } + else { + off=comp_get_ilong((m68k_pc_offset+=4)-4); + } + mov_l_ri(S1,(uintptr) + (comp_pc_p+off-(m68k_pc_offset-start_68k_offset))); + mov_l_ri(PC_P,(uintptr)comp_pc_p); + + /* Now they are both constant. Might as well fold in m68k_pc_offset */ + add_l_ri(S1,m68k_pc_offset); + add_l_ri(PC_P,m68k_pc_offset); + m68k_pc_offset=0; + + /* according to fpp.c, the 0x10 bit is ignored + (it handles exception handling, which we don't + do, anyway ;-) */ + cc=opcode&0x0f; + v1=get_const(PC_P); + v2=get_const(S1); + fflags_into_flags(S2); + + switch(cc) { + case 0: break; /* jump never */ + case 1: + mov_l_rr(S2,PC_P); + cmov_l_rr(PC_P,S1,4); + cmov_l_rr(PC_P,S2,10); break; + case 2: register_branch(v1,v2,7); break; + case 3: register_branch(v1,v2,3); break; + case 4: + mov_l_rr(S2,PC_P); + cmov_l_rr(PC_P,S1,2); + cmov_l_rr(PC_P,S2,10); break; + case 5: + mov_l_rr(S2,PC_P); + cmov_l_rr(PC_P,S1,6); + cmov_l_rr(PC_P,S2,10); break; + case 6: register_branch(v1,v2,5); break; + case 7: register_branch(v1,v2,11); break; + case 8: register_branch(v1,v2,10); break; + case 9: register_branch(v1,v2,4); break; + case 10: + cmov_l_rr(PC_P,S1,10); + cmov_l_rr(PC_P,S1,7); break; + case 11: + cmov_l_rr(PC_P,S1,4); + cmov_l_rr(PC_P,S1,3); break; + case 12: register_branch(v1,v2,2); break; + case 13: register_branch(v1,v2,6); break; + case 14: + cmov_l_rr(PC_P,S1,5); + cmov_l_rr(PC_P,S1,10); break; + case 15: mov_l_rr(PC_P,S1); break; + } +} + + /* Floating point conditions + The "NotANumber" part could be problematic; Howver, when NaN is + encountered, the ftst instruction sets bot N and Z to 1 on the x87, + so quite often things just fall into place. This is probably not + accurate wrt the 68k FPU, but it is *as* accurate as this was before. + However, some more thought should go into fixing this stuff up so + it accurately emulates the 68k FPU. +>==> 13) & 0x7) { + case 3: /* 2nd most common */ + if (put_fp_value ((extra >> 7)&7 , opcode, extra) < 0) { + FAIL(1); + return; + + } + return; + case 6: + case 7: + { + uae_u32 ad, list = 0; + int incr = 0; + if (extra & 0x2000) { + + /* FMOVEM FPP->memory */ + switch ((extra >> 11) & 3) { /* Get out early if failure */ + case 0: + case 2: + break; + case 1: + case 3: + default: + FAIL(1); return; + } + ad=get_fp_ad (opcode, &ad); + if ((uae_s32)ad<0) { + m68k_setpc (m68k_getpc () - 4); + fpuop_illg (opcode,extra); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 1: /* dynamic pred */ + case 3: /* dynamic postinc */ + abort(); + } + if (incr < 0) { /* Predecrement */ + for (reg = 7; reg >= 0; reg--) { + if (list & 0x80) { + fmov_ext_mr((uintptr)temp_fp,reg); + delay; + sub_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp); + writelong_clobber(ad,S2,S3); + sub_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp+4); + writelong_clobber(ad,S2,S3); + sub_l_ri(ad,4); + mov_w_rm(S2,(uintptr)temp_fp+8); + writeword_clobber(ad,S2,S3); + } + list <<= 1; + } + } + else { /* Postincrement */ + for (reg = 0; reg < 8; reg++) { + if (list & 0x80) { + fmov_ext_mr((uintptr)temp_fp,reg); + delay; + mov_w_rm(S2,(uintptr)temp_fp+8); + writeword_clobber(ad,S2,S3); + add_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp+4); + writelong_clobber(ad,S2,S3); + add_l_ri(ad,4); + mov_l_rm(S2,(uintptr)temp_fp); + writelong_clobber(ad,S2,S3); + add_l_ri(ad,4); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) + mov_l_rr((opcode & 7)+8,ad); + if ((opcode & 0x38) == 0x20) + mov_l_rr((opcode & 7)+8,ad); + } else { + /* FMOVEM memory->FPP */ + + uae_u32 ad; + switch ((extra >> 11) & 3) { /* Get out early if failure */ + case 0: + case 2: + break; + case 1: + case 3: + default: + FAIL(1); return; + } + ad=get_fp_ad (opcode, &ad); + if ((uae_s32)ad<0) { + m68k_setpc (m68k_getpc () - 4); + D(bug("no ad\n")); + fpuop_illg (opcode,extra); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 1: /* dynamic pred */ + case 3: /* dynamic postinc */ + abort(); + } + + if (incr < 0) { + // not reached + for (reg = 7; reg >= 0; reg--) { + if (list & 0x80) { + sub_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp),S2); + sub_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp)+4,S2); + sub_l_ri(ad,4); + readword(ad,S2,S3); + mov_w_mr(((uintptr)temp_fp)+8,S2); + delay2; + fmov_ext_rm(reg,(uintptr)(temp_fp)); + } + list <<= 1; + } + } + else { + for (reg = 0; reg < 8; reg++) { + if (list & 0x80) { + readword(ad,S2,S3); + mov_w_mr(((uintptr)temp_fp)+8,S2); + add_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp)+4,S2); + add_l_ri(ad,4); + readlong(ad,S2,S3); + mov_l_mr((uintptr)(temp_fp),S2); + add_l_ri(ad,4); + delay2; + fmov_ext_rm(reg,(uintptr)(temp_fp)); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) + mov_l_rr((opcode & 7)+8,ad); + if ((opcode & 0x38) == 0x20) + mov_l_rr((opcode & 7)+8,ad); + } + } + return; + + case 4: + case 5: /* rare */ + if ((opcode & 0x30) == 0) { + if (extra & 0x2000) { + if (extra & 0x1000) { +#if HANDLE_FPCR + mov_l_rm(opcode & 15, (uintptr)&fpu.fpcr.rounding_mode); + or_l_rm(opcode & 15, (uintptr)&fpu.fpcr.rounding_precision); +#else + FAIL(1); + return; +#endif + } + if (extra & 0x0800) { + FAIL(1); + return; + } + if (extra & 0x0400) { + mov_l_rm(opcode & 15,(uintptr)&fpu.instruction_address); + return; + } + } else { + // gb-- moved here so that we may FAIL() without generating any code + if (extra & 0x0800) { + // set_fpsr(m68k_dreg (regs, opcode & 15)); + FAIL(1); + return; + } + if (extra & 0x1000) { +#if HANDLE_FPCR +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) + FAIL(1); + return; +#endif + mov_l_rr(S1,opcode & 15); + mov_l_rr(S2,opcode & 15); + and_l_ri(S1,FPCR_ROUNDING_PRECISION); + and_l_ri(S2,FPCR_ROUNDING_MODE); + mov_l_mr((uintptr)&fpu.fpcr.rounding_precision,S1); + mov_l_mr((uintptr)&fpu.fpcr.rounding_mode,S2); +#else + FAIL(1); + return; +#endif +// return; gb-- FMOVEM could also operate on fpiar + } + if (extra & 0x0400) { + mov_l_mr((uintptr)&fpu.instruction_address,opcode & 15); +// return; gb-- we have to process all FMOVEM bits before returning + } + return; + } + } else if ((opcode & 0x3f) == 0x3c) { + if ((extra & 0x2000) == 0) { + // gb-- moved here so that we may FAIL() without generating any code + if (extra & 0x0800) { + FAIL(1); + return; + } + if (extra & 0x1000) { + comp_get_ilong((m68k_pc_offset+=4)-4); +#if HANDLE_FPCR +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) + FAIL(1); + return; +#endif +// mov_l_mi((uintptr)®s.fpcr,val); + mov_l_ri(S1,val); + mov_l_ri(S2,val); + and_l_ri(S1,FPCR_ROUNDING_PRECISION); + and_l_ri(S2,FPCR_ROUNDING_MODE); + mov_l_mr((uintptr)&fpu.fpcr.rounding_precision,S1); + mov_l_mr((uintptr)&fpu.fpcr.rounding_mode,S2); +#else + FAIL(1); + return; +#endif +// return; gb-- FMOVEM could also operate on fpiar + } + if (extra & 0x0400) { + uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4); + mov_l_mi((uintptr)&fpu.instruction_address,val); +// return; gb-- we have to process all FMOVEM bits before returning + } + return; + } + FAIL(1); + return; + } else if (extra & 0x2000) { + FAIL(1); + return; + } else { + FAIL(1); + return; + } + FAIL(1); + return; + + case 0: + case 2: /* Extremely common */ + reg = (extra >> 7) & 7; + if ((extra & 0xfc00) == 0x5c00) { + switch (extra & 0x7f) { + case 0x00: + fmov_pi(reg); + break; + case 0x0b: + fmov_log10_2(reg); + break; + case 0x0c: +#if USE_LONG_DOUBLE + fmov_ext_rm(reg,(uintptr)&const_e); +#else + fmov_rm(reg,(uintptr)&const_e); +#endif + break; + case 0x0d: + fmov_log2_e(reg); + break; + case 0x0e: +#if USE_LONG_DOUBLE + fmov_ext_rm(reg,(uintptr)&const_log10_e); +#else + fmov_rm(reg,(uintptr)&const_log10_e); +#endif + break; + case 0x0f: + fmov_0(reg); + break; + case 0x30: + fmov_loge_2(reg); + break; + case 0x31: +#if USE_LONG_DOUBLE + fmov_ext_rm(reg,(uintptr)&const_loge_10); +#else + fmov_rm(reg,(uintptr)&const_loge_10); +#endif + break; + case 0x32: + fmov_1(reg); + break; + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: +#if USE_LONG_DOUBLE + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + fmov_ext_rm(reg,(uintptr)(power10+(extra & 0x7f)-0x32)); +#else + fmov_rm(reg,(uintptr)(power10+(extra & 0x7f)-0x32)); +#endif + break; + default: + /* This is not valid, so we fail */ + FAIL(1); + return; + } + return; + } + + switch (extra & 0x7f) { + case 0x00: /* FMOVE */ + case 0x40: /* Explicit rounding. This is just a quick fix. Same + * for all other cases that have three choices */ + case 0x44: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fmov_rr(reg,src); + MAKE_FPSR (src); + break; + case 0x01: /* FINT */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x02: /* FSINH */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x03: /* FINTRZ */ +#ifdef USE_X86_FPUCW + /* If we have control over the CW, we can do this */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + mov_l_ri(S1,16); /* Switch to "round to zero" mode */ + fldcw_m_indexed(S1,(uae_u32)x86_fpucw); + + frndint_rr(reg,src); + + /* restore control word */ + mov_l_rm(S1,(uintptr)®s.fpcr); + and_l_ri(S1,0x000000f0); + fldcw_m_indexed(S1,(uintptr)x86_fpucw); + + MAKE_FPSR (reg); + break; +#endif + FAIL(1); + return; + break; + case 0x04: /* FSQRT */ + case 0x41: + case 0x45: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fsqrt_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x06: /* FLOGNP1 */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x08: /* FETOXM1 */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x09: /* FTANH */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x0a: /* FATAN */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x0c: /* FASIN */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x0d: /* FATANH */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x0e: /* FSIN */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fsin_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x0f: /* FTAN */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x10: /* FETOX */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fetox_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x11: /* FTWOTOX */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + ftwotox_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x12: /* FTENTOX */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x14: /* FLOGN */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x15: /* FLOG10 */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x16: /* FLOG2 */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + flog2_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x18: /* FABS */ + case 0x58: + case 0x5c: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fabs_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x19: /* FCOSH */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x1a: /* FNEG */ + case 0x5a: + case 0x5e: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fneg_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x1c: /* FACOS */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x1d: /* FCOS */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fcos_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x1e: /* FGETEXP */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x1f: /* FGETMAN */ + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x20: /* FDIV */ + case 0x60: + case 0x64: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fdiv_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x21: /* FMOD */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + frem_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x22: /* FADD */ + case 0x62: + case 0x66: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fadd_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x23: /* FMUL */ + case 0x63: + case 0x67: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fmul_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x24: /* FSGLDIV */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fdiv_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x25: /* FREM */ + // gb-- disabled because the quotient byte must be computed + // otherwise, free rotation in ClarisWorks doesn't work. + FAIL(1); + return; + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + frem1_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x26: /* FSCALE */ + dont_care_fflags(); + FAIL(1); + return; + break; + case 0x27: /* FSGLMUL */ + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fmul_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x28: /* FSUB */ + case 0x68: + case 0x6c: + dont_care_fflags(); + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fsub_rr(reg,src); + MAKE_FPSR (reg); + break; + case 0x30: /* FSINCOS */ + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x38: /* FCMP */ + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fmov_rr(FP_RESULT,reg); + fsub_rr(FP_RESULT,src); /* Right way? */ + break; + case 0x3a: /* FTST */ + src=get_fp_value (opcode, extra); + if (src < 0) { + FAIL(1); /* Illegal instruction */ + return; + } + fmov_rr(FP_RESULT,src); + break; + default: + FAIL(1); + return; + break; + } + return; + } + m68k_setpc (m68k_getpc () - 4); + fpuop_illg (opcode,extra); +} diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp new file mode 100644 index 00000000..6c1ede09 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp @@ -0,0 +1,2106 @@ +/* + * compiler/compemu_midfunc_arm.cpp - Native MIDFUNCS for ARM + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu_support.cpp + * + */ + +/******************************************************************** + * CPU functions exposed to gencomp. Both CREATE and EMIT time * + ********************************************************************/ + +/* + * RULES FOR HANDLING REGISTERS: + * + * * In the function headers, order the parameters + * - 1st registers written to + * - 2nd read/modify/write registers + * - 3rd registers read from + * * Before calling raw_*, you must call readreg, writereg or rmw for + * each register + * * The order for this is + * - 1st call remove_offset for all registers written to with size<4 + * - 2nd call readreg for all registers read without offset + * - 3rd call rmw for all rmw registers + * - 4th call readreg_offset for all registers that can handle offsets + * - 5th call get_offset for all the registers from the previous step + * - 6th call writereg for all written-to registers + * - 7th call raw_* + * - 8th unlock2 all registers that were locked + */ + +MIDFUNC(0,live_flags,(void)) +{ + live.flags_on_stack=TRASH; + live.flags_in_flags=VALID; + live.flags_are_important=1; +} +MENDFUNC(0,live_flags,(void)) + +MIDFUNC(0,dont_care_flags,(void)) +{ + live.flags_are_important=0; +} +MENDFUNC(0,dont_care_flags,(void)) + +MIDFUNC(0,duplicate_carry,(void)) +{ + evict(FLAGX); + make_flags_live_internal(); + COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem,NATIVE_CC_CS); + log_vwrite(FLAGX); +} +MENDFUNC(0,duplicate_carry,(void)) + +MIDFUNC(0,restore_carry,(void)) +{ +#if defined(USE_JIT2) + RR4 r=readreg(FLAGX,4); + MRS_CPSR(REG_WORK1); + TEQ_ri(r,1); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_C_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + unlock2(r); +#else + if (!have_rat_stall) { /* Not a P6 core, i.e. no partial stalls */ + bt_l_ri_noclobber(FLAGX,0); + } + else { /* Avoid the stall the above creates. + This is slow on non-P6, though. + */ + COMPCALL(rol_b_ri(FLAGX,8)); + isclean(FLAGX); + } +#endif +} +MENDFUNC(0,restore_carry,(void)) + +MIDFUNC(0,start_needflags,(void)) +{ + needflags=1; +} +MENDFUNC(0,start_needflags,(void)) + +MIDFUNC(0,end_needflags,(void)) +{ + needflags=0; +} +MENDFUNC(0,end_needflags,(void)) + +MIDFUNC(0,make_flags_live,(void)) +{ + make_flags_live_internal(); +} +MENDFUNC(0,make_flags_live,(void)) + +MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ +{ + int size=4; + if (i<16) + size=2; + CLOBBER_BT; + r=readreg(r,size); + raw_bt_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ + +MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ +{ + CLOBBER_BT; + r=readreg(r,4); + b=readreg(b,4); + raw_bt_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ + +MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_btc_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) + +MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_btr_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) + +MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_bts_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) + +MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,4); + raw_mov_l_rm(d,s); + unlock2(d); +} +MENDFUNC(2,mov_l_rm,(W4 d, IMM s)) + +MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) +{ + CLOBBER_MOV; + index=readreg(index,4); + d=writereg(d,4); + raw_mov_l_rm_indexed(d,base,index,factor); + unlock2(index); + unlock2(d); +} +MENDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) + +MIDFUNC(2,mov_l_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_l_mi(d,s); +} +MENDFUNC(2,mov_l_mi,(IMM d, IMM s)) + +MIDFUNC(2,mov_w_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_w_mi(d,s); +} +MENDFUNC(2,mov_w_mi,(IMM d, IMM s)) + +MIDFUNC(2,mov_b_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_b_mi(d,s); +} +MENDFUNC(2,mov_b_mi,(IMM d, IMM s)) + +MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,1,1); + raw_rol_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,rol_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,2,2); + raw_rol_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,rol_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,4,4); + raw_rol_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,rol_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(rol_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg(r,1); + d=rmw(d,4,4); + raw_rol_l_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(rol_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg(r,1); + d=rmw(d,2,2); + raw_rol_w_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(rol_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg(r,1); + d=rmw(d,1,1); + raw_rol_b_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) + +MIDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shll_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg(r,1); + d=rmw(d,4,4); + raw_shll_l_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shll_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg(r,1); + d=rmw(d,2,2); + raw_shll_w_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shll_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg(r,1); + d=rmw(d,1,1); + raw_shll_b_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) + +MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,1,1); + raw_ror_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,ror_b_ri,(RR1 r, IMM i)) + +MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,2,2); + raw_ror_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,ror_w_ri,(RR2 r, IMM i)) + +MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,4,4); + raw_ror_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,ror_l_ri,(RR4 r, IMM i)) + +MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROR; + r=readreg(r,1); + d=rmw(d,4,4); + raw_ror_l_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) + +MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROR; + r=readreg(r,1); + d=rmw(d,2,2); + raw_ror_w_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) + +MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_ROR; + r=readreg(r,1); + d=rmw(d,1,1); + raw_ror_b_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) + +MIDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shrl_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRL; + r=readreg(r,1); + d=rmw(d,4,4); + raw_shrl_l_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shrl_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRL; + r=readreg(r,1); + d=rmw(d,2,2); + raw_shrl_w_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shrl_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHRL; + r=readreg(r,1); + d=rmw(d,1,1); + raw_shrl_b_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) + +MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(r) && !needflags) { + live.state[r].val<<=i; + return; + } + CLOBBER_SHLL; + r=rmw(r,4,4); + raw_shll_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shll_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHLL; + r=rmw(r,2,2); + raw_shll_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shll_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHLL; + r=rmw(r,1,1); + raw_shll_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shll_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(r) && !needflags) { + live.state[r].val>>=i; + return; + } + CLOBBER_SHRL; + r=rmw(r,4,4); + raw_shrl_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRL; + r=rmw(r,2,2); + raw_shrl_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRL; + r=rmw(r,1,1); + raw_shrl_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,4,4); + raw_shra_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shra_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,2,2); + raw_shra_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shra_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,1,1); + raw_shra_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shra_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shra_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRA; + r=readreg(r,1); + d=rmw(d,4,4); + raw_shra_l_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shra_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRA; + r=readreg(r,1); + d=rmw(d,2,2); + raw_shra_w_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shra_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHRA; + r=readreg(r,1); + d=rmw(d,1,1); + raw_shra_b_rr(d,r); + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) + +MIDFUNC(2,setcc,(W1 d, IMM cc)) +{ + CLOBBER_SETCC; + d=writereg(d,1); + raw_setcc(d,cc); + unlock2(d); +} +MENDFUNC(2,setcc,(W1 d, IMM cc)) + +MIDFUNC(2,setcc_m,(IMM d, IMM cc)) +{ + CLOBBER_SETCC; + raw_setcc_m(d,cc); +} +MENDFUNC(2,setcc_m,(IMM d, IMM cc)) + +MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) +{ + if (d==s) + return; + CLOBBER_CMOV; + s=readreg(s,4); + d=rmw(d,4,4); + raw_cmov_l_rr(d,s,cc); + unlock2(s); + unlock2(d); +} +MENDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) + +MIDFUNC(2,bsf_l_rr,(W4 d, W4 s)) +{ + CLOBBER_BSF; + s = readreg(s, 4); + d = writereg(d, 4); + raw_bsf_l_rr(d, s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,bsf_l_rr,(W4 d, W4 s)) + +/* Set the Z flag depending on the value in s. Note that the + value has to be 0 or -1 (or, more precisely, for non-zero + values, bit 14 must be set)! */ +MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) +{ + CLOBBER_BSF; + s=rmw_specific(s,4,4,FLAG_NREG3); + tmp=writereg(tmp,4); + raw_flags_set_zero(s, tmp); + unlock2(tmp); + unlock2(s); +} +MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) + +MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) +{ + CLOBBER_MUL; + s=readreg(s,4); + d=rmw(d,4,4); + raw_imul_32_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,imul_32_32,(RW4 d, RR4 s)) + +MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) +{ + CLOBBER_MUL; + s=rmw_specific(s,4,4,MUL_NREG2); + d=rmw_specific(d,4,4,MUL_NREG1); + raw_imul_64_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,imul_64_32,(RW4 d, RW4 s)) + +MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) +{ + CLOBBER_MUL; + s=rmw_specific(s,4,4,MUL_NREG2); + d=rmw_specific(d,4,4,MUL_NREG1); + raw_mul_64_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,mul_64_32,(RW4 d, RW4 s)) + +MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s16)live.state[s].val); + return; + } + + CLOBBER_SE16; + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,2); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,2); + } + raw_sign_extend_16_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) + +MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_SE8; + if (!isrmw) { + s=readreg(s,1); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,1); + } + + raw_sign_extend_8_rr(d,s); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) + +MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_u32)(uae_u16)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_ZE16; + if (!isrmw) { + s=readreg(s,2); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,2); + } + raw_zero_extend_16_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) + +MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) +{ + int isrmw; + if (isconst(s)) { + set_const(d,(uae_u32)(uae_u8)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_ZE8; + if (!isrmw) { + s=readreg(s,1); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,1); + } + + raw_zero_extend_8_rr(d,s); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) + +MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) +{ + if (d==s) + return; + if (isconst(s)) { + COMPCALL(mov_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=writereg(d,1); + raw_mov_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,mov_b_rr,(W1 d, RR1 s)) + +MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) +{ + if (d==s) + return; + if (isconst(s)) { + COMPCALL(mov_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=writereg(d,2); + raw_mov_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,mov_w_rr,(W2 d, RR2 s)) + +/* read the long at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_l_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,4); + + raw_mov_l_rR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_w_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,2); + + raw_mov_w_rR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) + +/* read the long at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_l_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,4); + + raw_mov_l_brR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_w_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + remove_offset(d,-1); + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,2); + + raw_mov_w_brR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_b_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + remove_offset(d,-1); + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,1); + + raw_mov_b_brR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) + +MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_l_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_l_Ri(d,i,offset); + unlock2(d); +} +MENDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) + +MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_w_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_w_Ri(d,i,offset); + unlock2(d); +} +MENDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) + +/* Warning! OFFSET is byte sized only! */ +MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_l_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_l_Ri)(d,live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,4); + d=readreg(d,4); + + raw_mov_l_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) + +MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_w_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_w_Ri)(d,(uae_u16)live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=readreg(d,4); + raw_mov_w_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) + +MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_l_ri)(d,live.state[s].val+offset); + return; + } +#if USE_OFFSET + if (d==s) { + add_offset(d,offset); + return; + } +#endif + CLOBBER_LEA; + s=readreg(s,4); + d=writereg(d,4); + raw_lea_l_brr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) + +MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) +{ + if (!offset) { + COMPCALL(lea_l_rr_indexed)(d,s,index,factor); + return; + } + CLOBBER_LEA; + s=readreg(s,4); + index=readreg(index,4); + d=writereg(d,4); + + raw_lea_l_brr_indexed(d,s,index,factor,offset); + unlock2(d); + unlock2(index); + unlock2(s); +} +MENDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) + +MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) +{ + CLOBBER_LEA; + s=readreg(s,4); + index=readreg(index,4); + d=writereg(d,4); + + raw_lea_l_rr_indexed(d,s,index,factor); + unlock2(d); + unlock2(index); + unlock2(s); +} +MENDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) + +/* write d to the long at the address contained in s+offset */ +MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_l_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,4); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + + raw_mov_l_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) + +/* write the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) +{ + int dreg=d; + + if (isconst(d)) { + COMPCALL(mov_w_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_w_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) + +MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_b_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_b_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) + +MIDFUNC(1,mid_bswap_32,(RW4 r)) +{ + + if (isconst(r)) { + uae_u32 oldv=live.state[r].val; + live.state[r].val=reverse32(oldv); + return; + } + + CLOBBER_SW32; + r=rmw(r,4,4); + raw_bswap_32(r); + unlock2(r); +} +MENDFUNC(1,mid_bswap_32,(RW4 r)) + +MIDFUNC(1,mid_bswap_16,(RW2 r)) +{ + if (isconst(r)) { + uae_u32 oldv=live.state[r].val; + live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) | + (oldv&0xffff0000); + return; + } + + CLOBBER_SW16; + r=rmw(r,2,2); + + raw_bswap_16(r); + unlock2(r); +} +MENDFUNC(1,mid_bswap_16,(RW2 r)) + +MIDFUNC(2,mov_l_rr,(W4 d, RR4 s)) +{ + int olds; + + if (d==s) { /* How pointless! */ + return; + } + if (isconst(s)) { + COMPCALL(mov_l_ri)(d,live.state[s].val); + return; + } + olds=s; + disassociate(d); + s=readreg_offset(s,4); + live.state[d].realreg=s; + live.state[d].realind=live.nat[s].nholds; + live.state[d].val=live.state[olds].val; + live.state[d].validsize=4; + live.state[d].dirtysize=4; + set_status(d,DIRTY); + + live.nat[s].holds[live.nat[s].nholds]=d; + live.nat[s].nholds++; + log_clobberreg(d); + D2(panicbug("Added %d to nreg %d(%d), now holds %d regs", d,s,live.state[d].realind,live.nat[s].nholds)); + unlock2(s); +} +MENDFUNC(2,mov_l_rr,(W4 d, RR4 s)) + +MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(mov_l_mi)(d,live.state[s].val); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + + raw_mov_l_mr(d,s); + unlock2(s); +} +MENDFUNC(2,mov_l_mr,(IMM d, RR4 s)) + +MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(mov_w_mi)(d,(uae_u16)live.state[s].val); + return; + } + CLOBBER_MOV; + s=readreg(s,2); + + raw_mov_w_mr(d,s); + unlock2(s); +} +MENDFUNC(2,mov_w_mr,(IMM d, RR2 s)) + +MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,2); + + raw_mov_w_rm(d,s); + unlock2(d); +} +MENDFUNC(2,mov_w_rm,(W2 d, IMM s)) + +MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(mov_b_mi)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + + raw_mov_b_mr(d,s); + unlock2(s); +} +MENDFUNC(2,mov_b_mr,(IMM d, RR1 s)) + +MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,1); + + raw_mov_b_rm(d,s); + unlock2(d); +} +MENDFUNC(2,mov_b_rm,(W1 d, IMM s)) + +MIDFUNC(2,mov_l_ri,(W4 d, IMM s)) +{ + set_const(d,s); + return; +} +MENDFUNC(2,mov_l_ri,(W4 d, IMM s)) + +MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,2); + + raw_mov_w_ri(d,s); + unlock2(d); +} +MENDFUNC(2,mov_w_ri,(W2 d, IMM s)) + +MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,1); + + raw_mov_b_ri(d,s); + unlock2(d); +} +MENDFUNC(2,mov_b_ri,(W1 d, IMM s)) + +MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) +{ + CLOBBER_TEST; + d=readreg(d,4); + + raw_test_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,test_l_ri,(RR4 d, IMM i)) + +MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) +{ + CLOBBER_TEST; + d=readreg(d,4); + s=readreg(s,4); + + raw_test_l_rr(d,s);; + unlock2(d); + unlock2(s); +} +MENDFUNC(2,test_l_rr,(RR4 d, RR4 s)) + +MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) +{ + CLOBBER_TEST; + d=readreg(d,2); + s=readreg(s,2); + + raw_test_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,test_w_rr,(RR2 d, RR2 s)) + +MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) +{ + CLOBBER_TEST; + d=readreg(d,1); + s=readreg(s,1); + + raw_test_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,test_b_rr,(RR1 d, RR1 s)) + +MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) +{ + if (isconst(d) && !needflags) { + live.state[d].val &= i; + return; + } + + CLOBBER_AND; + d=rmw(d,4,4); + + raw_and_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,and_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,and_l,(RW4 d, RR4 s)) +{ + CLOBBER_AND; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_and_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,and_l,(RW4 d, RR4 s)) + +MIDFUNC(2,and_w,(RW2 d, RR2 s)) +{ + CLOBBER_AND; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_and_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,and_w,(RW2 d, RR2 s)) + +MIDFUNC(2,and_b,(RW1 d, RR1 s)) +{ + CLOBBER_AND; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_and_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,and_b,(RW1 d, RR1 s)) + +MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) +{ + if (isconst(d) && !needflags) { + live.state[d].val|=i; + return; + } + CLOBBER_OR; + d=rmw(d,4,4); + + raw_or_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,or_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,or_l,(RW4 d, RR4 s)) +{ + if (isconst(d) && isconst(s) && !needflags) { + live.state[d].val|=live.state[s].val; + return; + } + CLOBBER_OR; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_or_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,or_l,(RW4 d, RR4 s)) + +MIDFUNC(2,or_w,(RW2 d, RR2 s)) +{ + CLOBBER_OR; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_or_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,or_w,(RW2 d, RR2 s)) + +MIDFUNC(2,or_b,(RW1 d, RR1 s)) +{ + CLOBBER_OR; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_or_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,or_b,(RW1 d, RR1 s)) + +MIDFUNC(2,adc_l,(RW4 d, RR4 s)) +{ + CLOBBER_ADC; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_adc_l(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,adc_l,(RW4 d, RR4 s)) + +MIDFUNC(2,adc_w,(RW2 d, RR2 s)) +{ + CLOBBER_ADC; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_adc_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,adc_w,(RW2 d, RR2 s)) + +MIDFUNC(2,adc_b,(RW1 d, RR1 s)) +{ + CLOBBER_ADC; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_adc_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,adc_b,(RW1 d, RR1 s)) + +MIDFUNC(2,add_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(add_l_ri)(d,live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_add_l(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,add_l,(RW4 d, RR4 s)) + +MIDFUNC(2,add_w,(RW2 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(add_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_add_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,add_w,(RW2 d, RR2 s)) + +MIDFUNC(2,add_b,(RW1 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(add_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_add_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,add_b,(RW1 d, RR1 s)) + +MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(d) && !needflags) { + live.state[d].val-=i; + return; + } +#if USE_OFFSET + if (!needflags) { + add_offset(d,-i); + return; + } +#endif + + CLOBBER_SUB; + d=rmw(d,4,4); + + raw_sub_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,sub_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_SUB; + d=rmw(d,2,2); + + raw_sub_w_ri(d,i); + unlock2(d); +} +MENDFUNC(2,sub_w_ri,(RW2 d, IMM i)) + +MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_SUB; + d=rmw(d,1,1); + + raw_sub_b_ri(d,i); + + unlock2(d); +} +MENDFUNC(2,sub_b_ri,(RW1 d, IMM i)) + +MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(d) && !needflags) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + if (!needflags) { + add_offset(d,i); + return; + } +#endif + CLOBBER_ADD; + d=rmw(d,4,4); + raw_add_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,add_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_ADD; + d=rmw(d,2,2); + + raw_add_w_ri(d,i); + unlock2(d); +} +MENDFUNC(2,add_w_ri,(RW2 d, IMM i)) + +MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_ADD; + d=rmw(d,1,1); + + raw_add_b_ri(d,i); + + unlock2(d); +} +MENDFUNC(2,add_b_ri,(RW1 d, IMM i)) + +MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) +{ + CLOBBER_SBB; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_sbb_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sbb_l,(RW4 d, RR4 s)) + +MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) +{ + CLOBBER_SBB; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_sbb_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sbb_w,(RW2 d, RR2 s)) + +MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) +{ + CLOBBER_SBB; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_sbb_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sbb_b,(RW1 d, RR1 s)) + +MIDFUNC(2,sub_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(sub_l_ri)(d,live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_sub_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sub_l,(RW4 d, RR4 s)) + +MIDFUNC(2,sub_w,(RW2 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(sub_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_sub_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sub_w,(RW2 d, RR2 s)) + +MIDFUNC(2,sub_b,(RW1 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(sub_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_sub_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sub_b,(RW1 d, RR1 s)) + +MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) +{ + CLOBBER_CMP; + s=readreg(s,4); + d=readreg(d,4); + + raw_cmp_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,cmp_l,(RR4 d, RR4 s)) + +MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) +{ + CLOBBER_CMP; + s=readreg(s,2); + d=readreg(d,2); + + raw_cmp_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,cmp_w,(RR2 d, RR2 s)) + +MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) +{ + CLOBBER_CMP; + s=readreg(s,1); + d=readreg(d,1); + + raw_cmp_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,cmp_b,(RR1 d, RR1 s)) + +MIDFUNC(2,xor_l,(RW4 d, RR4 s)) +{ + CLOBBER_XOR; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_xor_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,xor_l,(RW4 d, RR4 s)) + +MIDFUNC(2,xor_w,(RW2 d, RR2 s)) +{ + CLOBBER_XOR; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_xor_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,xor_w,(RW2 d, RR2 s)) + +MIDFUNC(2,xor_b,(RW1 d, RR1 s)) +{ + CLOBBER_XOR; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_xor_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,xor_b,(RW1 d, RR1 s)) + +MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) +{ + clobber_flags(); + in1=readreg_specific(in1,isize1,REG_PAR1); + in2=readreg_specific(in2,isize2,REG_PAR2); + r=readreg(r,4); + prepare_for_call_1(); + unlock2(r); + unlock2(in1); + unlock2(in2); + prepare_for_call_2(); + compemu_raw_call_r(r); +} +MENDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) + +MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) +{ + clobber_flags(); + + if (osize==4) { + if (out1!=in1 && out1!=r) { + COMPCALL(forget_about)(out1); + } + } + else { + tomem_c(out1); + } + + in1=readreg_specific(in1,isize,REG_PAR1); + r=readreg(r,4); + + prepare_for_call_1(); + unlock2(in1); + unlock2(r); + + prepare_for_call_2(); + + compemu_raw_call_r(r); + + live.nat[REG_RESULT].holds[0]=out1; + live.nat[REG_RESULT].nholds=1; + live.nat[REG_RESULT].touched=touchcnt++; + + live.state[out1].realreg=REG_RESULT; + live.state[out1].realind=0; + live.state[out1].val=0; + live.state[out1].validsize=osize; + live.state[out1].dirtysize=osize; + set_status(out1,DIRTY); +} +MENDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) + +MIDFUNC(0,nop,(void)) +{ + raw_emit_nop(); +} +MENDFUNC(0,nop,(void)) + +/* forget_about() takes a mid-layer register */ +MIDFUNC(1,forget_about,(W4 r)) +{ + if (isinreg(r)) + disassociate(r); + live.state[r].val=0; + set_status(r,UNDEF); +} +MENDFUNC(1,forget_about,(W4 r)) + +MIDFUNC(1,f_forget_about,(FW r)) +{ + if (f_isinreg(r)) + f_disassociate(r); + live.fate[r].status=UNDEF; +} +MENDFUNC(1,f_forget_about,(FW r)) + +// ARM optimized functions + +MIDFUNC(2,arm_ADD_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(arm_ADD_l_ri)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + raw_ADD_l_rr(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_ADD_l,(RW4 d, RR4 s)) + +MIDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) +{ + if (!i) return; + if (isconst(d)) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + add_offset(d,i); + return; +#endif + d=rmw(d,4,4); + + raw_LDR_l_ri(REG_WORK1, i); + raw_ADD_l_rr(d,REG_WORK1); + unlock2(d); +} +MENDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) +{ + if (!i) return; + if (isconst(d)) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + add_offset(d,i); + return; +#endif + d=rmw(d,4,4); + + raw_ADD_l_rri(d,d,i); + unlock2(d); +} +MENDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) + +MIDFUNC(2,arm_SUB_l_ri8,(RW4 d, IMM i)) +{ + if (!i) return; + if (isconst(d)) { + live.state[d].val-=i; + return; + } +#if USE_OFFSET + add_offset(d,-i); + return; +#endif + d=rmw(d,4,4); + + raw_SUB_l_rri(d,d,i); + unlock2(d); +} +MENDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) + +MIDFUNC(2,arm_AND_l,(RW4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + raw_AND_l_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_AND_l,(RW4 d, RR4 s)) + +MIDFUNC(2,arm_AND_w,(RW2 d, RR2 s)) +{ + s=readreg(s,2); + d=rmw(d,2,2); + + raw_AND_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_AND_w,(RW2 d, RR2 s)) + +MIDFUNC(2,arm_AND_b,(RW1 d, RR1 s)) +{ + s=readreg(s,1); + d=rmw(d,1,1); + + raw_AND_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_AND_b,(RW1 d, RR1 s)) + +MIDFUNC(2,arm_AND_l_ri8,(RW4 d, IMM i)) +{ + if (isconst(d)) { + live.state[d].val &= i; + return; + } + + d=rmw(d,4,4); + + raw_AND_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,arm_AND_l_ri8,(RW4 d, IMM i)) + +MIDFUNC(2,arm_EOR_b,(RW1 d, RR1 s)) +{ + s=readreg(s,1); + d=rmw(d,1,1); + + raw_EOR_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_EOR_b,(RW1 d, RR1 s)) + +MIDFUNC(2,arm_EOR_l,(RW4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + raw_EOR_l_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_EOR_l,(RW4 d, RR4 s)) + +MIDFUNC(2,arm_EOR_w,(RW2 d, RR2 s)) +{ + s=readreg(s,2); + d=rmw(d,2,2); + + raw_EOR_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_EOR_w,(RW2 d, RR2 s)) + +MIDFUNC(2,arm_ORR_b,(RW1 d, RR1 s)) +{ + s=readreg(s,1); + d=rmw(d,1,1); + + raw_ORR_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_ORR_b,(RW1 d, RR1 s)) + +MIDFUNC(2,arm_ORR_l,(RW4 d, RR4 s)) +{ + if (isconst(d) && isconst(s)) { + live.state[d].val|=live.state[s].val; + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + raw_ORR_l_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_ORR_l,(RW4 d, RR4 s)) + +MIDFUNC(2,arm_ORR_w,(RW2 d, RR2 s)) +{ + s=readreg(s,2); + d=rmw(d,2,2); + + raw_ORR_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,arm_ORR_w,(RW2 d, RR2 s)) + +MIDFUNC(2,arm_ROR_l_ri8,(RW4 r, IMM i)) +{ + if (!i) + return; + + r=rmw(r,4,4); + raw_ROR_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,arm_ROR_l_ri8,(RW4 r, IMM i)) + +// Other +static inline void flush_cpu_icache(void *start, void *stop) +{ + + register void *_beg __asm ("a1") = start; + register void *_end __asm ("a2") = stop; + register void *_flg __asm ("a3") = 0; +#ifdef __ARM_EABI__ + register unsigned long _scno __asm ("r7") = 0xf0002; + __asm __volatile ("swi 0x0 @ sys_cacheflush" + : "=r" (_beg) + : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); +#else + __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" + : "=r" (_beg) + : "0" (_beg), "r" (_end), "r" (_flg)); +#endif +} + +static inline void write_jmp_target(uae_u32* jmpaddr, cpuop_func* a) { + *(jmpaddr) = (uae_u32) a; + flush_cpu_icache((void *) jmpaddr, (void *) &jmpaddr[1]); +} + +static inline void emit_jmp_target(uae_u32 a) { + emit_long((uae_u32) a); +} diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h new file mode 100644 index 00000000..52541326 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h @@ -0,0 +1,184 @@ +/* + * compiler/compemu_midfunc_arm.h - Native MIDFUNCS for ARM + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu.h + * + */ + +// Arm optimized midfunc +DECLARE_MIDFUNC(arm_ADD_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_ADD_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_ADD_l_ri8(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_SUB_l_ri8(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_AND_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(arm_AND_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(arm_AND_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_AND_l_ri8(RW4 d, IMM i)); +DECLARE_MIDFUNC(arm_EOR_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(arm_EOR_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_EOR_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(arm_ORR_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(arm_ORR_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(arm_ORR_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(arm_ROR_l_ri8(RW4 r, IMM i)); + +// Emulated midfunc +DECLARE_MIDFUNC(bt_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(bt_l_rr(RR4 r, RR4 b)); +DECLARE_MIDFUNC(btc_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(bts_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(btr_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s)); +DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(rol_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(rol_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(rol_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shll_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shll_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shll_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(ror_b_ri(RR1 r, IMM i)); +DECLARE_MIDFUNC(ror_w_ri(RR2 r, IMM i)); +DECLARE_MIDFUNC(ror_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(ror_l_rr(RR4 d, RR1 r)); +DECLARE_MIDFUNC(ror_w_rr(RR2 d, RR1 r)); +DECLARE_MIDFUNC(ror_b_rr(RR1 d, RR1 r)); +DECLARE_MIDFUNC(shrl_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shrl_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shrl_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shra_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shra_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shra_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(setcc(W1 d, IMM cc)); +DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc)); +DECLARE_MIDFUNC(cmov_l_rr(RW4 d, RR4 s, IMM cc)); +DECLARE_MIDFUNC(bsf_l_rr(W4 d, RR4 s)); +DECLARE_MIDFUNC(pop_l(W4 d)); +DECLARE_MIDFUNC(push_l(RR4 s)); +DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s)); +DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s)); +DECLARE_MIDFUNC(imul_32_32(RW4 d, RR4 s)); +DECLARE_MIDFUNC(mov_b_rr(W1 d, RR1 s)); +DECLARE_MIDFUNC(mov_w_rr(W2 d, RR2 s)); +DECLARE_MIDFUNC(mov_l_rR(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_rR(W2 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_l_brR(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_brR(W2 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_brR(W1 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_l_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_w_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_l_Rr(RR4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_Rr(RR4 d, RR2 s, IMM offset)); +DECLARE_MIDFUNC(lea_l_brr(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)); +DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, RR4 s, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_bRr(RR4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_bRr(RR4 d, RR2 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_bRr(RR4 d, RR1 s, IMM offset)); +DECLARE_MIDFUNC(mid_bswap_32(RW4 r)); +DECLARE_MIDFUNC(mid_bswap_16(RW2 r)); +DECLARE_MIDFUNC(mov_l_rr(W4 d, RR4 s)); +DECLARE_MIDFUNC(mov_l_mr(IMM d, RR4 s)); +DECLARE_MIDFUNC(mov_w_mr(IMM d, RR2 s)); +DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s)); +DECLARE_MIDFUNC(mov_b_mr(IMM d, RR1 s)); +DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s)); +DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s)); +DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s)); +DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s)); +DECLARE_MIDFUNC(test_l_ri(RR4 d, IMM i)); +DECLARE_MIDFUNC(test_l_rr(RR4 d, RR4 s)); +DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s)); +DECLARE_MIDFUNC(test_b_rr(RR1 d, RR1 s)); +DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(and_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(and_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(and_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(or_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(or_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(or_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(adc_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(adc_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(adc_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(add_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(add_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(add_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i)); +DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i)); +DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i)); +DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i)); +DECLARE_MIDFUNC(sbb_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(sbb_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(sbb_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(sub_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(sub_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(sub_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(cmp_l(RR4 d, RR4 s)); +DECLARE_MIDFUNC(cmp_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(cmp_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(xor_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(xor_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(xor_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(call_r_02(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)); +DECLARE_MIDFUNC(call_r_11(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)); +DECLARE_MIDFUNC(live_flags(void)); +DECLARE_MIDFUNC(dont_care_flags(void)); +DECLARE_MIDFUNC(duplicate_carry(void)); +DECLARE_MIDFUNC(restore_carry(void)); +DECLARE_MIDFUNC(start_needflags(void)); +DECLARE_MIDFUNC(end_needflags(void)); +DECLARE_MIDFUNC(make_flags_live(void)); +DECLARE_MIDFUNC(forget_about(W4 r)); +DECLARE_MIDFUNC(nop(void)); + +DECLARE_MIDFUNC(f_forget_about(FW r)); + + + + diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp new file mode 100644 index 00000000..9da2c058 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp @@ -0,0 +1,5428 @@ +/* + * compiler/compemu_midfunc_arm.cpp - Native MIDFUNCS for ARM (JIT v2) + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu_support.cpp + * + */ + +const uae_u32 ARM_CCR_MAP[] = { 0, ARM_C_FLAG, // 1 C + ARM_V_FLAG, // 2 V + ARM_C_FLAG | ARM_V_FLAG, // 3 VC + ARM_Z_FLAG, // 4 Z + ARM_Z_FLAG | ARM_C_FLAG, // 5 ZC + ARM_Z_FLAG | ARM_V_FLAG, // 6 ZV + ARM_Z_FLAG | ARM_C_FLAG | ARM_V_FLAG, // 7 ZVC + ARM_N_FLAG, // 8 N + ARM_N_FLAG | ARM_C_FLAG, // 9 NC + ARM_N_FLAG | ARM_V_FLAG, // 10 NV + ARM_N_FLAG | ARM_C_FLAG | ARM_V_FLAG, // 11 NVC + ARM_N_FLAG | ARM_Z_FLAG, // 12 NZ + ARM_N_FLAG | ARM_Z_FLAG | ARM_C_FLAG, // 13 NZC + ARM_N_FLAG | ARM_Z_FLAG | ARM_V_FLAG, // 14 NZV + ARM_N_FLAG | ARM_Z_FLAG | ARM_C_FLAG | ARM_V_FLAG, // 15 NZVC + }; + +// First we start with some helper functions (may be moved to codegen_arm) +static inline void UNSIGNED8_IMM_2_REG(W4 r, IMM v) { + MOV_ri8(r, (uint8) v); +} + +static inline void SIGNED8_IMM_2_REG(W4 r, IMM v) { + if (v & 0x80) { + MVN_ri8(r, (uint8) ~v); + } else { + MOV_ri8(r, (uint8) v); + } +} + +static inline void UNSIGNED16_IMM_2_REG(W4 r, IMM v) { + MOV_ri8(r, (uint8) v); + ORR_rri8RORi(r, r, (uint8)(v >> 8), 24); +} + +static inline void SIGNED16_IMM_2_REG(W4 r, IMM v) { +#if defined(ARMV6_ASSEMBLY) + MOV_ri8(r, (uint8) v); + ORR_rri8RORi(r, r, (uint8)(v >> 8), 24); + SXTH_rr(r, r); +#else + MOV_ri8(r, (uint8)(v << 16)); + ORR_rri8RORi(r, r, (uint8)(v >> 8), 8); + ASR_rri(r, r, 16); +#endif +} + +static inline void UNSIGNED8_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(d, s); +#else + ROR_rri(d, s, 8); + LSR_rri(d, d, 24); +#endif +} + +static inline void SIGNED8_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + SXTB_rr(d, s); +#else + ROR_rri(d, s, 8); + ASR_rri(d, d, 24); +#endif +} + +static inline void UNSIGNED16_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(d, s); +#else + LSL_rri(d, s, 16); + LSR_rri(d, d, 16); +#endif +} + +static inline void SIGNED16_REG_2_REG(W4 d, RR4 s) { +#if defined(ARMV6_ASSEMBLY) + SXTH_rr(d, s); +#else + LSL_rri(d, s, 16); + ASR_rri(d, d, 16); +#endif +} + +#define ZERO_EXTEND_8_REG_2_REG(d,s) UNSIGNED8_REG_2_REG(d,s) +#define ZERO_EXTEND_16_REG_2_REG(d,s) UNSIGNED16_REG_2_REG(d,s) +#define SIGN_EXTEND_8_REG_2_REG(d,s) SIGNED8_REG_2_REG(d,s) +#define SIGN_EXTEND_16_REG_2_REG(d,s) SIGNED16_REG_2_REG(d,s) + +MIDFUNC(0,restore_inverted_carry,(void)) +{ + RR4 r=readreg(FLAGX,4); + MRS_CPSR(REG_WORK1); + TEQ_ri(r,1); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_C_FLAG); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSRf_r(REG_WORK1); + unlock2(r); +} +MENDFUNC(0,restore_inverted_carry,(void)) + +/* + * ADD + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + */ +MIDFUNC(3,jnf_ADD_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val+v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK1, v); + ADD_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ADD_imm,(W4 d, RR4 s, IMM v)) + +MIDFUNC(3,jnf_ADD,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_ADD_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + ADD_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jnf_ADD,(W4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_ADD_b_imm,(W4 d, RR1 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_IMM_2_REG(REG_WORK2, (uint8)v); + SIGNED8_REG_2_REG(REG_WORK1, s); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ADD_b_imm,(W4 d, RR1 s, IMM v)) + +MIDFUNC(3,jff_ADD_b,(W4 d, RR1 s, RR1 v)) +{ + if (isconst(v)) { + COMPCALL(jff_ADD_b_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_ADD_b,(W4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_IMM_2_REG(REG_WORK2, (uint16)v); + SIGNED16_REG_2_REG(REG_WORK1, s); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) + +MIDFUNC(3,jff_ADD_w,(W4 d, RR2 s, RR2 v)) +{ + if (isconst(v)) { + COMPCALL(jff_ADD_w_imm)(d,s,live.state[v].val); + return; + } + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + ADDS_rrr(d,REG_WORK1,REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_ADD_w,(W4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK2, v); + ADDS_rrr(d,s,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) + +MIDFUNC(3,jff_ADD_l,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jff_ADD_l_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + ADDS_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_ADD_l,(W4 d, RR4 s, RR4 v)) + +/* + * ADDA + * Operand Syntax: , An + * + * Operand Size: 16,32 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_ADDA_b,(W4 d, RR1 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED8_REG_2_REG(REG_WORK1,s); + ADD_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ADDA_b,(W4 d, RR1 s)) + +MIDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED16_REG_2_REG(REG_WORK1,s); + ADD_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) + +MIDFUNC(2,jnf_ADDA_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + ADD_rrr(d,d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ADDA_l,(W4 d, RR4 s)) + +/* + * ADDX + * Operand Syntax: Dy, Dx + * -(Ay), -(Ax) + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Cleared if the result is nonzero; unchanged otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + * Attention: Z is cleared only if the result is nonzero. Unchanged otherwise + * + */ +MIDFUNC(3,jnf_ADDX,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + ADC_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jnf_ADDX,(W4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + PUSH(REG_WORK2); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + ADCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + PUSH(REG_WORK2); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + ADCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + PUSH(REG_WORK2); + + ADCS_rrr(d,s,v); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) + +/* + * ANDI + * Operand Syntax: #, CCR + * + * Operand Size: 8 + * + * X Cleared if bit 4 of immediate operand is zero. Unchanged otherwise. + * N Cleared if bit 3 of immediate operand is zero. Unchanged otherwise. + * Z Cleared if bit 2 of immediate operand is zero. Unchanged otherwise. + * V Cleared if bit 1 of immediate operand is zero. Unchanged otherwise. + * C Cleared if bit 0 of immediate operand is zero. Unchanged otherwise. + * + */ +MIDFUNC(1,jff_ANDSR,(IMM s, IMM x)) +{ + MRS_CPSR(REG_WORK1); + AND_rri(REG_WORK1, REG_WORK1, s); + MSR_CPSRf_r(REG_WORK1); + + if (!x) { + compemu_raw_mov_l_ri(REG_WORK1, (uintptr)live.state[FLAGX].mem); + MOV_ri(REG_WORK2, 0); + STRB_rR(REG_WORK2, REG_WORK1); + } +} +MENDFUNC(1,jff_ANDSR,(IMM s)) + +/* + * AND + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. + * Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(3,jnf_AND,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(s) && isconst(v)) { + set_const(d, + live.state[s].val&live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + AND_rrr(d, s, v); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_AND,(RW4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_AND_b,(W4 d, RR1 s, RR1 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ANDS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_AND_b,(RW4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_AND_w,(W4 d, RR2 s, RR2 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ANDS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_AND_w,(RW4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_AND_l,(W4 d, RR4 s, RR4 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + ANDS_rrr(d, s,v); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_AND_l,(RW4 d, RR4 s, RR4 v)) + +/* + * ASL + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * + */ +MIDFUNC(3,jff_ASL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d, s, 24); + if (i) { + MRS_CPSR(REG_WORK1); // store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except N & Z + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rri(REG_WORK2, REG_WORK2, (i+1)); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// restore flags + + LSLS_rri(d,d,i); + } else { + MSR_CPSRf_i(0); + TST_rr(d,d); + } + REV_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ASL_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ASL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d, s, 16); + if (i) { + MRS_CPSR(REG_WORK1); // store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except N & Z + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rri(REG_WORK2, REG_WORK2, (i+1)); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + LSLS_rri(d,d,i); + } else { + MSR_CPSRf_i(0); + TST_rr(d,d); + } + ASR_rri(d,d, 16); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ASL_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ASL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i) { + MRS_CPSR(REG_WORK1); // store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except C + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rri(REG_WORK2, REG_WORK2, (i+1)); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, s, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + LSLS_rri(d,s,i); + } else { + MSR_CPSRf_i(0); + MOVS_rr(d, s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ASL_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ASL_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + // Calculate V Flag + MRS_CPSR(REG_WORK1);// store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except C + PUSH(REG_WORK1); + + LSL_rri(d, s, 24); + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rrr(REG_WORK2, REG_WORK2, i); + LSR_rri(REG_WORK2, REG_WORK2, 1); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + AND_rri(REG_WORK2, i, 63); + LSLS_rrr(d,d,REG_WORK2); + ASR_rri(d,d, 24); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ASL_b_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ASL_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + // Calculate V Flag + MRS_CPSR(REG_WORK1);// store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except c + PUSH(REG_WORK1); + + LSL_rri(d, s, 16); + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rrr(REG_WORK2, REG_WORK2, i); + LSR_rri(REG_WORK2, REG_WORK2, 1); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, d, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + AND_rri(REG_WORK2, i, 63); + LSLS_rrr(d,d,REG_WORK2); + ASR_rri(d,d, 16); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ASL_w_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ASL_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + // Calculate V Flag + MRS_CPSR(REG_WORK1);// store flags + BIC_rri(REG_WORK1, REG_WORK1, ARM_N_FLAG|ARM_Z_FLAG|ARM_V_FLAG);// Clear everything except C + PUSH(REG_WORK1); + + // Calculate V Flag + MVN_ri(REG_WORK2, 0); + LSR_rrr(REG_WORK2, REG_WORK2, i); + LSR_rri(REG_WORK2, REG_WORK2, 1); + MVN_rr(REG_WORK2, REG_WORK2); + AND_rrr(REG_WORK1, s, REG_WORK2); + TST_rr(REG_WORK1, REG_WORK1); + CC_TEQ_rr(NATIVE_CC_NE, REG_WORK1, REG_WORK2); + POP(REG_WORK1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + + MSR_CPSRf_r(REG_WORK1);// retore flags + + AND_rri(REG_WORK2, i, 63); + LSLS_rrr(d,s,REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ASL_l_reg,(W4 d, RR4 s, RR4 i)) + +/* + * ASLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. + * + */ +MIDFUNC(2,jnf_ASLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ASLW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_ASLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + LSLS_rri(d,s,17); + + MRS_CPSR(REG_WORK1); + CC_ORR_rri(NATIVE_CC_MI, REG_WORK1, REG_WORK1, ARM_V_FLAG); + CC_EOR_rri(NATIVE_CC_CS, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_ASLW,(W4 d, RR4 s)) + +/* + * ASR + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * + */ +MIDFUNC(3,jnf_ASR_b_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + ASR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ASR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ASR_w_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + ASR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ASR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ASR_l_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + ASR_rri(d,s,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ASR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ASR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + if (i) { + MSR_CPSRf_i(0); + ASRS_rri(d,d,i); + } else { + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ASR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ASR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + if (i) { + MSR_CPSRf_i(0); + ASRS_rri(d,d,i); + } else { + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ASR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ASR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i) { + MSR_CPSRf_i(0); + ASRS_rri(d,s,i); + } else { + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + TST_rr(s,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ASR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ASR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + ASR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ASR_b_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ASR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + ASR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ASR_w_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ASR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 63); + ASR_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ASR_l_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ASR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + ASRS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ASR_b_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ASR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + ASRS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ASR_w_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ASR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + ASRS_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ASR_l_reg,(W4 d, RR4 s, RR4 i)) + +/* + * ASRW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if the most significant bit is changed at any time during the shift operation. Cleared otherwise. + * C Set according to the last bit shifted out of the operand. + * + */ +MIDFUNC(2,jnf_ASRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + ASR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ASRW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_ASRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + ASR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_ASRW,(W4 d, RR4 s)) + +/* + * BCHG + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected. + * N Not affected. + * Z Set if the bit tested is zero. Cleared otherwise. + * V Not affected. + * C Not affected. + * + */ +MIDFUNC(2,jnf_BCHG_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + EOR_rri(d,d,(1 << s)); + unlock2(d); +} +MENDFUNC(2,jnf_BCHG_b_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jnf_BCHG_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + EOR_rri(d,d,(1 << s)); + unlock2(d); +} +MENDFUNC(2,jnf_BCHG_l_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jnf_BCHG_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCHG_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_BCHG_b,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_BCHG_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCHG_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_BCHG_l,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rri(d,d,v); + + unlock2(d); +} +MENDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rri(d,d,v); + + unlock2(d); +} +MENDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCHG_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCHG_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + EOR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) + +/* + * BCLR + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected. + * N Not affected. + * Z Set if the bit tested is zero. Cleared otherwise. + * V Not affected. + * C Not affected. + * + */ +MIDFUNC(2,jnf_BCLR_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + BIC_rri(d,d,(1 << s)); + unlock2(d); +} +MENDFUNC(2,jnf_BCLR_b_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jnf_BCLR_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + BIC_rri(d,d,(1 << s)); + unlock2(d); +} +MENDFUNC(2,jnf_BCLR_l_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jnf_BCLR_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCLR_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_BCLR_b,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_BCLR_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BCLR_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_BCLR_l,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rri(d,d,v); + + unlock2(d); +} +MENDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rri(d,d,v); + + unlock2(d); +} +MENDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCLR_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BCLR_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + BIC_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) + +/* + * BSET + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected. + * N Not affected. + * Z Set if the bit tested is zero. Cleared otherwise. + * V Not affected. + * C Not affected. + * + */ +MIDFUNC(2,jnf_BSET_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + ORR_rri(d,d,(1 << s)); + unlock2(d); +} +MENDFUNC(2,jnf_BSET_b_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jnf_BSET_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + ORR_rri(d,d,(1 << s)); + unlock2(d); +} +MENDFUNC(2,jnf_BSET_l_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jnf_BSET_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BSET_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_BSET_b,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_BSET_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jnf_BSET_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_BSET_l,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rri(d,d,v); + + unlock2(d); +} +MENDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) +{ + d=rmw(d,4,4); + + uae_u32 v = (1 << s); + MRS_CPSR(REG_WORK1); + TST_ri(d,v); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rri(d,d,v); + + unlock2(d); +} +MENDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) + +MIDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BSET_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BSET_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=rmw(d,4,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + ORR_rrr(d,d,REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) + +/* + * BTST + * Operand Syntax: Dn, + * #, + * + * Operand Size: 8,32 + * + * X Not affected + * N Not affected + * Z Set if the bit tested is zero. Cleared otherwise + * V Not affected + * C Not affected + * + */ +MIDFUNC(2,jff_BTST_b_imm,(RR4 d, IMM s)) +{ + d=readreg(d,4); + + MRS_CPSR(REG_WORK1); + TST_ri(d,(1 << s)); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); +} +MENDFUNC(2,jff_BTST_b_imm,(RR4 d, IMM s)) + +MIDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) +{ + d=readreg(d,4); + + MRS_CPSR(REG_WORK1); + TST_ri(d,(1 << s)); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); +} +MENDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) + +MIDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BTST_b_imm)(d,live.state[s].val&7); + return; + } + s=readreg(s,4); + d=readreg(d,4); + + AND_rri(REG_WORK1, s, 7); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) + +MIDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_BTST_l_imm)(d,live.state[s].val&31); + return; + } + + s=readreg(s,4); + d=readreg(d,4); + + AND_rri(REG_WORK1, s, 31); + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + MRS_CPSR(REG_WORK1); + TST_rr(d,REG_WORK2); + CC_BIC_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + CC_ORR_rri(NATIVE_CC_EQ, REG_WORK1, REG_WORK1, ARM_Z_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) + +/* + * CLR + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Always cleared. + * Z Always set. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(1,jnf_CLR,(W4 d)) +{ + d=writereg(d,4); + MOV_ri(d,0); + unlock2(d); +} +MENDFUNC(1,jnf_CLR,(W4 d)) + +MIDFUNC(1,jff_CLR,(W4 d)) +{ + d=writereg(d,4); + MOV_ri(d,0); + MSR_CPSR_i(ARM_Z_FLAG); + unlock2(d); +} +MENDFUNC(1,jff_CLR,(W4 d)) + +/* + * CMP + * Operand Syntax: , Dn + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Set if a borrow occurs. Cleared otherwise. + * + */ +MIDFUNC(2,jff_CMP_b,(RR1 d, RR1 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED8_REG_2_REG(REG_WORK1, d); + SIGNED8_REG_2_REG(REG_WORK2, s); + CMP_rr(REG_WORK1,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // inverted_carry = true; + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_CMP_b,(RR1 d, RR1 s)) + +MIDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED16_REG_2_REG(REG_WORK1, d); + SIGNED16_REG_2_REG(REG_WORK2, s); + CMP_rr(REG_WORK1,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // inverted_carry = true; + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) + +MIDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + CMP_rr(d,s); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // inverted_carry = true; + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) + +/* + * CMPA + * Operand Syntax: , An + * + * Operand Size: 16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Set if a borrow occurs. Cleared otherwise. + * + */ +MIDFUNC(2,jff_CMPA_b,(RR1 d, RR1 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED8_REG_2_REG(REG_WORK2, s); + CMP_rr(d,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // invertedcarry = true; + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_CMPA_b,(RR1 d, RR1 s)) + +MIDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + SIGNED16_REG_2_REG(REG_WORK2, s); + CMP_rr(d,REG_WORK2); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // invertedcarry = true; + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) + +MIDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) +{ + d=readreg(d,4); + s=readreg(s,4); + + CMP_rr(d,s); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + // invertedcarry = true; + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) + +/* + * EOR + * Operand Syntax: Dn, + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. + * Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(3,jnf_EOR,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(s) && isconst(v)) { + set_const(d, + live.state[s].val^live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + EOR_rrr(d, s, v); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_EOR,(RW4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_EOR_b,(W4 d, RR1 s, RR1 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + EORS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_EOR_b,(RW4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_EOR_w,(W4 d, RR2 s, RR2 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + EORS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_EOR_w,(RW4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_EOR_l,(W4 d, RR4 s, RR4 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + EORS_rrr(d, s,v); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_EOR_l,(RW4 d, RR4 s, RR4 v)) + +/* + * EORI + * Operand Syntax: #, CCR + * + * Operand Size: 8 + * + * X — Changed if bit 4 of immediate operand is one; unchanged otherwise. + * N — Changed if bit 3 of immediate operand is one; unchanged otherwise. + * Z — Changed if bit 2 of immediate operand is one; unchanged otherwise. + * V — Changed if bit 1 of immediate operand is one; unchanged otherwise. + * C — Changed if bit 0 of immediate operand is one; unchanged otherwise. + * + */ +MIDFUNC(1,jff_EORSR,(IMM s, IMM x)) +{ + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, s); + MSR_CPSRf_r(REG_WORK1); + + if (x) { + compemu_raw_mov_l_ri(REG_WORK1, (uintptr)live.state[FLAGX].mem); + LDRB_rR(REG_WORK2, REG_WORK1); + EOR_rri(REG_WORK2, REG_WORK2, 1); + STRB_rR(REG_WORK2, REG_WORK1); + } +} +MENDFUNC(1,jff_EORSR,(IMM s)) + +/* + * EXT + * Operand Syntax: + * + * Operand Size: 16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(2,jnf_EXT_b,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_EXT_b,(W4 d, RR4 s)) + +MIDFUNC(2,jnf_EXT_w,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_EXT_w,(W4 d, RR4 s)) + +MIDFUNC(2,jnf_EXT_l,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s16)live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_EXT_l,(W4 d, RR4 s)) + +MIDFUNC(2,jff_EXT_b,(W4 d, RR4 s)) +{ + if (isconst(s)) { + d=writereg(d,4); + SIGNED8_IMM_2_REG(d, (uint8)live.state[s].val); + } else { + s=readreg(s,4); + d=writereg(d,4); + SIGNED8_REG_2_REG(d, s); + unlock2(s); + } + + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(2,jff_EXT_b,(W4 d, RR4 s)) + +MIDFUNC(2,jff_EXT_w,(W4 d, RR4 s)) +{ + if (isconst(s)) { + d=writereg(d,4); + SIGNED8_IMM_2_REG(d, (uint8)live.state[s].val); + } else { + s=readreg(s,4); + d=writereg(d,4); + SIGNED8_REG_2_REG(d, s); + unlock2(s); + } + + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(2,jff_EXT_w,(W4 d, RR4 s)) + +MIDFUNC(2,jff_EXT_l,(W4 d, RR4 s)) +{ + if (isconst(s)) { + d=writereg(d,4); + SIGNED16_IMM_2_REG(d, (uint16)live.state[s].val); + } else { + s=readreg(s,4); + d=writereg(d,4); + SIGNED16_REG_2_REG(d, s); + unlock2(s); + } + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(2,jff_EXT_l,(W4 d, RR4 s)) + +/* + * LSL + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. Cleared for a shift count of zero. + * + */ +MIDFUNC(3,jnf_LSL_imm,(W4 d, RR4 s, IMM i)) +{ + if (!i) return; + + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_LSL_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_LSL_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 63); + LSL_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_LSL_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_LSL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d, s); + MSR_CPSRf_i(0); + + REV_rr(d,d); + if (i) { + LSLS_rri(d,d,i); + } else { + TST_rr(d,d); + } + REV_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_LSL_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_LSL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + + LSL_rri(d,s,16); + if (i) { + LSLS_rri(d,d,i); + } else { + TST_rr(d,d); + } + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_LSL_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_LSL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + if (i) { + LSLS_rri(d,s,i); + } else { + MOV_rr(d,s); + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_LSL_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_LSL_b_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + REV_rr(d,d); + AND_rri(REG_WORK1, i, 63); + LSLS_rrr(d,d,REG_WORK1); + REV_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_LSL_b_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_LSL_w_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + LSL_rri(d, s, 16); + AND_rri(REG_WORK1, i, 63); + LSLS_rrr(d,d,REG_WORK1); + LSR_rri(d, d, 16); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_LSL_w_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_LSL_l_reg,(W4 d, RR4 s, RR4 i)) +{ + i=readreg(i,4); + s=readreg(s,4); + d=writereg(d,4); + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSLS_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_LSL_l_reg,(W4 d, RR4 s, RR4 i)) + +/* + * LSLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. Cleared for a shift count of zero. + * + */ +MIDFUNC(2,jnf_LSLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_LSLW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_LSLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + LSLS_rri(d,s,17); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_LSLW,(W4 d, RR4 s)) + +/* + * LSR + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit shifted out of the operand. + * Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. + * Cleared for a shift count of zero. + * + */ +MIDFUNC(3,jnf_LSR_b_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + if (!i) + return; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + LSR_rri(d,d,i); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(3,jnf_LSR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_LSR_w_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + if (!i) + return; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + LSR_rri(d,d,i); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(3,jnf_LSR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_LSR_l_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + if (!i) + return; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + LSR_rri(d,s,i); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(3,jnf_LSR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_LSR_b_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + MSR_CPSRf_i(0); + if (i) { + LSRS_rri(d,d,i); + } else { + TST_rr(d,d); + } + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(3,jff_LSR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_LSR_w_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + if (i) { + LSRS_rri(d,d,i); + } else { + TST_rr(d,d); + } + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(3,jff_LSR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_LSR_l_imm,(W4 d, RR4 s, IMM i)) +{ + int isrmw; + + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + MSR_CPSRf_i(0); + if (i) { + LSRS_rri(d,s,i); + } else { + TST_rr(s,s); + } + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(3,jff_LSR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_LSR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + LSR_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} +MENDFUNC(3,jnf_LSR_b_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_LSR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + AND_rri(REG_WORK1, i, 63); + LSR_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} +MENDFUNC(3,jnf_LSR_w_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_LSR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + AND_rri(REG_WORK1, i, 63); + LSR_rrr(d,s,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} +MENDFUNC(3,jnf_LSR_l_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_LSR_b_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED8_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSRS_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} +MENDFUNC(3,jff_LSR_b_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_LSR_w_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + UNSIGNED16_REG_2_REG(d, s); + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSRS_rrr(d,d,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} +MENDFUNC(3,jff_LSR_w_reg,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_LSR_l_reg,(W4 d, RR4 s, RR4 i)) +{ + int isrmw; + + i=readreg(i,4); + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { + s=d=rmw(s,4,4); + } + + CC_MSR_CPSRf_r(NATIVE_CC_CC, 0); // Clear everything except C + CC_MSR_CPSRf_r(NATIVE_CC_CS, ARM_C_FLAG);// Clear everything except C + AND_rri(REG_WORK1, i, 63); + LSRS_rrr(d,s,REG_WORK1); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } + unlock2(i); +} +MENDFUNC(3,jff_LSR_l_reg,(W4 d, RR4 s, RR4 i)) + +/* + * LSRW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Set according to the last bit shifted out of the operand. Unaffected for a shift count of zero. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit shifted out of the operand. Cleared for a shift count of zero. + * + */ +MIDFUNC(2,jnf_LSRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d, s); + LSR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_LSRW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_LSRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + LSR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_LSRW,(W4 d, RR4 s)) + +/* + * MOVE + * Operand Syntax: , + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(2,jnf_MOVE,(W4 d, RR4 s)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val); + return; + } + s=readreg(s,4); + d=writereg(d,4); + + MOV_rr(d, s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_MOVE,(W4 d, RR4 s)) + +MIDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) +{ + d=writereg(d,4); + + SIGNED8_IMM_2_REG(d, (uint8)s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) + +MIDFUNC(2,jff_MOVE_w_imm,(W4 d, IMM s)) +{ + d=writereg(d,4); + + SIGNED16_IMM_2_REG(d, (uint16)s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(2,jff_MOVE_w_imm,(W4 d, IMM s)) + +MIDFUNC(2,jff_MOVE_l_imm,(W4 d, IMM s)) +{ + d=writereg(d,4); + + compemu_raw_mov_l_ri(d, s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(2,jff_MOVE_l_imm,(W4 d, IMM s)) + +MIDFUNC(2,jff_MOVE_b,(W4 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(jff_MOVE_b_imm)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(d, s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_MOVE_b,(W4 d, RR1 s)) + +MIDFUNC(2,jff_MOVE_w,(W4 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(jff_MOVE_w_imm)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d, s); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_MOVE_w,(W4 d, RR2 s)) + +MIDFUNC(2,jff_MOVE_l,(W4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(jff_MOVE_l_imm)(d,live.state[s].val); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + MOVS_rr(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_MOVE_l,(W4 d, RR4 s)) + +/* + * MOVE16 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_MOVE16,(RR4 d, RR4 s)) +{ + s=readreg(s,4); + d=readreg(d,4); + + BIC_rri(s, s, 0x000000FF); + BIC_rri(d, d, 0x000000FF); + + compemu_raw_mov_l_ri(REG_WORK1, (IMM)MEMBaseDiff); + ADD_rrr(s, s, REG_WORK1); + ADD_rrr(d, d, REG_WORK1); + + LDR_rRI(REG_WORK1, s, 8); + LDR_rRI(REG_WORK2, s, 12); + + PUSH_REGS((1<, An + * + * Operand Size: 16,32 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_MOVEA_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_MOVEA_w,(W4 d, RR2 s)) + +MIDFUNC(2,jnf_MOVEA_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MOV_rr(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_MOVEA_l,(W4 d, RR4 s)) + +/* + * MULS + * Operand Syntax: , Dn + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if overflow. Cleared otherwise. (32 Bit multiply only) + * C Always cleared. + * + */ +MIDFUNC(2,jnf_MULS,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + SIGN_EXTEND_16_REG_2_REG(d,d); + SIGN_EXTEND_16_REG_2_REG(REG_WORK1,s); + MUL_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_MULS,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_MULS,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + SIGN_EXTEND_16_REG_2_REG(d,d); + SIGN_EXTEND_16_REG_2_REG(REG_WORK1,s); + + MSR_CPSRf_i(0); + MULS_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_MULS,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_MULS32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + MUL_rrr(d, d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_MULS32,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_MULS32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + MSR_CPSRf_i(0); + // L, H, + SMULLS_rrrr(d, REG_WORK2, d, s); + MRS_CPSR(REG_WORK1); + TEQ_rrASRi(REG_WORK2,d,31); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_MULS32,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_MULS64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + // L, H, + SMULL_rrrr(d, s, d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_MULS64,(RW4 d, RW4 s)) + +MIDFUNC(2,jff_MULS64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + MSR_CPSRf_i(0); + // L, H, + SMULLS_rrrr(d, s, d, s); + MRS_CPSR(REG_WORK1); + TEQ_rrASRi(s,d,31); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_MULS64,(RW4 d, RW4 s)) + +/* + * MULU + * Operand Syntax: , Dn + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if overflow. Cleared otherwise. (32 Bit multiply only) + * C Always cleared. + * + */ +MIDFUNC(2,jnf_MULU,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + ZERO_EXTEND_16_REG_2_REG(d,d); + ZERO_EXTEND_16_REG_2_REG(REG_WORK1,s); + + MUL_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_MULU,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_MULU,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + ZERO_EXTEND_16_REG_2_REG(d,d); + ZERO_EXTEND_16_REG_2_REG(REG_WORK1, s); + + MSR_CPSRf_i(0); + MULS_rrr(d, d, REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_MULU,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_MULU32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + MUL_rrr(d, d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_MULU32,(RW4 d, RR4 s)) + +MIDFUNC(2,jff_MULU32,(RW4 d, RR4 s)) +{ + s = readreg(s, 4); + d = rmw(d, 4, 4); + + // L, H, + MSR_CPSRf_i(0); + UMULLS_rrrr(d, REG_WORK2, d, s); + MRS_CPSR(REG_WORK1); + TST_rr(REG_WORK2,REG_WORK2); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_MULU32,(RW4 d, RR4 s)) + +MIDFUNC(2,jnf_MULU64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + // L, H, + UMULL_rrrr(d, s, d, s); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jnf_MULU64,(RW4 d, RW4 s)) + +MIDFUNC(2,jff_MULU64,(RW4 d, RW4 s)) +{ + s = rmw(s, 4, 4); + d = rmw(d, 4, 4); + + // L, H, + MSR_CPSRf_i(0); + UMULLS_rrrr(d, s, d, s); + MRS_CPSR(REG_WORK1); + TST_rr(s,s); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK1, REG_WORK1, ARM_V_FLAG); + MSR_CPSRf_r(REG_WORK1); + + unlock2(s); + unlock2(d); +} +MENDFUNC(2,jff_MULU64,(RW4 d, RW4 s)) + +/* + * NEG + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Cleared if the result is zero. Set otherwise. + * + */ +MIDFUNC(2,jnf_NEG,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + RSB_rri(d,s,0); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_NEG,(W4 d, RR4 s)) + +MIDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + RSBS_rri(d,REG_WORK1,0); + + // inverted_carry = true; + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) + +MIDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + RSBS_rri(d,REG_WORK1,0); + + // inverted_carry = true; + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) + +MIDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + RSBS_rri(d,s,0); + + // inverted_carry = true; + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) + +/* + * NEGX + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Cleared if the result is nonzero; unchanged otherwise. + * V Set if an overflow occurs. Cleared otherwise. + * C Cleared if the result is zero. Set otherwise. + * + * Attention: Z is cleared only if the result is nonzero. Unchanged otherwise + * + */ +MIDFUNC(2,jnf_NEGX,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + RSC_rri(d,s,0); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_NEGX,(W4 d, RR4 s)) + +MIDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + SIGNED8_REG_2_REG(REG_WORK1, s); + RSCS_rri(d,REG_WORK1,0); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) + +MIDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + SIGNED16_REG_2_REG(REG_WORK1, s); + RSCS_rri(d,REG_WORK1,0); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) + +MIDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) +{ + d=writereg(d,4); + s=readreg(s,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + RSCS_rri(d,s,0); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) + +/* + * NOT + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(2,jnf_NOT,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MVN_rr(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_NOT,(W4 d, RR4 s)) + +MIDFUNC(2,jff_NOT_b,(W4 d, RR1 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + MSR_CPSRf_i(0); // Clear flags + MVNS_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NOT_b,(W4 d, RR1 s)) + +MIDFUNC(2,jff_NOT_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MSR_CPSRf_i(0); // Clear flags + MVNS_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NOT_w,(W4 d, RR2 s)) + +MIDFUNC(2,jff_NOT_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); // Clear flags + MVNS_rr(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_NOT_l,(W4 d, RR4 s)) + +/* + * OR + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(3,jnf_OR,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(s) && isconst(v)) { + set_const(d, + live.state[s].val|live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + ORR_rrr(d, s, v); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_OR,(RW4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_OR_b,(W4 d, RR1 s, RR1 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ORRS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_OR_b,(RW4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_OR_w,(W4 d, RR2 s, RR2 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + MSR_CPSRf_i(0); + ORRS_rrr(d, REG_WORK1, REG_WORK2); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_OR_w,(RW4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_OR_l,(W4 d, RR4 s, RR4 v)) +{ + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + ORRS_rrr(d, s,v); + + unlock2(v); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_OR_l,(RW4 d, RR4 s, RR4 v)) + +/* + * ORI + * Operand Syntax: #, CCR + * + * Operand Size: 8 + * + * X — Set if bit 4 of immediate operand is one; unchanged otherwise. + * N — Set if bit 3 of immediate operand is one; unchanged otherwise. + * Z — Set if bit 2 of immediate operand is one; unchanged otherwise. + * V — Set if bit 1 of immediate operand is one; unchanged otherwise. + * C — Set if bit 0 of immediate operand is one; unchanged otherwise. + * + */ +MIDFUNC(1,jff_ORSR,(IMM s, IMM x)) +{ + MRS_CPSR(REG_WORK1); + ORR_rri(REG_WORK1, REG_WORK1, s); + MSR_CPSRf_r(REG_WORK1); + + if (x) { + compemu_raw_mov_l_ri(REG_WORK1, (uintptr)live.state[FLAGX].mem); + MOV_ri(REG_WORK2, 1); + STRB_rR(REG_WORK2, REG_WORK1); + } +} +MENDFUNC(1,jff_ORSR,(IMM s)) + +/* + * ROL + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,(32-(i&0x1f))); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROL_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,(32-(i&0x1f))); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + ROR_rri(d,s,(32-(i&0x1f))); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROL_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + if (i) { + RORS_rri(d,d,(32-(i&0x1f))); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + } else { + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + if (i) { + RORS_rri(d,d,(32-(i&0x1f))); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + } else { + TST_rr(d,d); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + if (i) { + RORS_rri(d,s,(32-(i&0x1f))); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + } else { + MOVS_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROL_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + ROR_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROL_l,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rrr(d,d,REG_WORK1); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rrr(d,d,REG_WORK1); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + AND_rri(REG_WORK1, i, 0x1f); + RSB_rri(REG_WORK1, REG_WORK1, 32); + + MSR_CPSRf_i(0); + RORS_rrr(d,s,REG_WORK1); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) + +/* + * ROLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(2,jnf_ROLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,(32-1)); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ROLW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_ROLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rri(d,d,(32-1)); + + MRS_CPSR(REG_WORK2); + TST_ri(d, 1); + CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); + CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); + MSR_CPSR_r(REG_WORK2); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_ROLW,(W4 d, RR4 s)) + +/* + * RORW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. + * + */ +MIDFUNC(2,jnf_RORW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_RORW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_RORW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rri(d,d,1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_RORW,(W4 d, RR4 s)) + +/* + * ROXL + * Operand Syntax: Dx, Dy + * #, Dy + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROXL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED8_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,9); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROXL_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROXL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED16_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,17); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROXL_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROXL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSL_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,s,(32-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROXL_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROXL_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED8_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,9); + TST_ri(s, (1<<(8-i))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED8_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROXL_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROXL_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED16_REG_2_REG(d,s); + LSL_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,d,17); + TST_ri(s, (1<<(16-i))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROXL_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROXL_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSL_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (1 << (i - 1))); + if (i > 1) ORR_rrrLSRi(d,d,s,(32-i)); + TST_ri(s, (1<<(32-i))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROXL_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROXL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(8-1); +#else + BLE_i(9-1); +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 8); +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK2, s); +#else + ROR_rri(REG_WORK2, s, 8); + LSR_rri(REG_WORK2, REG_WORK2, 24); +#endif + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROXL_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROXL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(8-1); +#else + BLE_i(9-1); +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 16); +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK2, s); +#else + LSL_rri(REG_WORK2, s, 16); + LSR_rri(REG_WORK2, REG_WORK2, 16); +#endif + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROXL_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROXL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSRr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROXL_l,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROXL_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXL_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(16-1); // label +#else + BLE_i(17-1); // label +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 0x80); + LSR_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + PUSH(REG_WORK2); + + RSB_rri(REG_WORK1, REG_WORK1, 8); +#if defined(ARMV6_ASSEMBLY) + UXTB_rr(REG_WORK2, s); +#else + ROR_rri(REG_WORK2, s, 8); + LSR_rri(REG_WORK2, REG_WORK2, 24); +#endif + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + POP(REG_WORK2); + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0); // label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + raw_sign_extend_8_rr(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROXL_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROXL_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXL_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); +#if defined(ARMV6_ASSEMBLY) + BLE_i(16-1); // label +#else + BLE_i(17-1); // label +#endif + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 0x8000); + LSR_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + PUSH(REG_WORK2); + +#if defined(ARMV6_ASSEMBLY) + UXTH_rr(REG_WORK2, s); +#else + LSL_rri(REG_WORK2, s, 16); + LSR_rri(REG_WORK2, REG_WORK2, 16); +#endif + + RSB_rri(REG_WORK1, REG_WORK1, 16); + ORR_rrrLSRr(d,d,REG_WORK2,REG_WORK1); + + POP(REG_WORK2); + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0); // label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROXL_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROXL_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXL_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSL_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,1); + LSL_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 0x80000000); + LSR_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSRr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROXL_l,(W4 d, RR4 s, RR4 i)) + +/* + * ROXLW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. + * + */ +MIDFUNC(2,jnf_ROXLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + ADC_rri(d,d,0); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ROXLW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,1); + ADC_rri(d,d,0); + MSR_CPSRf_i(0); + LSLS_rri(d,d,15); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) + +/* + * ROR + * Operand Syntax: Dx, Dy + * #, Dy + * + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rri(d,d,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + ROR_rri(d,s,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rri(d,d,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + RORS_rrr(d,d,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + RORS_rrr(d,s,i); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,i); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROR_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + ROR_rrr(d,d,i); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + ROR_rrr(d,s,i); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROR_l,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,24); + ORR_rrrLSRi(d,d,d,8); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + AND_rri(REG_WORK1, i, 63); + RORS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROR_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + ORR_rrrLSRi(d,d,d,16); + MSR_CPSRf_i(0); + AND_rri(REG_WORK1, i, 63); + RORS_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MSR_CPSRf_i(0); + AND_rri(REG_WORK1, i, 63); + RORS_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROR_l,(W4 d, RR4 s, RR4 i)) + +/* + * ROXR + * Operand Syntax: Dx, Dy + * #, Dy + * + * Operand Size: 8,16,32 + * + * X Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. Cleared when the rotate count is zero. + * + */ +MIDFUNC(3,jnf_ROXR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(9-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROXR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROXR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x8000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(17-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROXR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROXR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80000000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(33-i)); + } else { + MOV_rr(d,s); + } + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_ROXR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROXR_b_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED8_REG_2_REG(d,s); + LSR_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(9-i)); + TST_ri(s, (1<<(i-1))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED8_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROXR_b_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROXR_w_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + UNSIGNED16_REG_2_REG(d,s); + LSR_rri(d,d,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x8000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(17-i)); + TST_ri(s, (1<<(i-1))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROXR_w_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jff_ROXR_l_imm,(W4 d, RR4 s, IMM i)) +{ + s=readreg(s,4); + d=writereg(d,4); + + if (i > 0) { + LSR_rri(d,s,i); + CC_ORR_rri(NATIVE_CC_CS, d,d, (0x80000000 >> (i - 1))); + if (i > 1) ORR_rrrLSLi(d,d,s,(33-i)); + TST_ri(s, (1<<(i-1))); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + } else { + MOV_rr(d,s); + MSR_CPSRf_i(0); + } + + TST_rr(d,d); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_ROXR_l_imm,(W4 d, RR4 s, IMM i)) + +MIDFUNC(3,jnf_ROXR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80); + LSR_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 8); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROXR_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROXR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x8000); + LSR_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 16); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROXR_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jnf_ROXR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jnf_ROXR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(7-1); + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80000000); + LSR_rrr(d, d, REG_WORK1); + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jnf_ROXR_l,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROXR_b,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXR_b_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED8_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 36); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 36); + CMP_ri(REG_WORK1, 18); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 18); + CMP_ri(REG_WORK1, 9); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 9); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80); + LSR_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 8); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + SIGNED8_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROXR_b,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROXR_w,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXR_w_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + UNSIGNED16_REG_2_REG(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 34); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 34); + CMP_ri(REG_WORK1, 17); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 17); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x8000); + LSR_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 16); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + SIGNED16_REG_2_REG(d,d); + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROXR_w,(W4 d, RR4 s, RR4 i)) + +MIDFUNC(3,jff_ROXR_l,(W4 d, RR4 s, RR4 i)) +{ + if (isconst(i)) { + COMPCALL(jff_ROXR_l_imm)(d,s,(uae_u8)live.state[i].val); + return; + } + + s=readreg(s,4); + i=readreg(i,4); + d=writereg(d,4); + + MOV_rr(d,s); + MRS_CPSR(REG_WORK2); + + AND_rri(REG_WORK1, i, 0x3f); + CMP_ri(REG_WORK1, 33); + CC_SUB_rri(NATIVE_CC_GE, REG_WORK1, REG_WORK1, 33); + CMP_ri(REG_WORK1, 0); + BLE_i(13-1); // label + + SUB_rri(REG_WORK1, REG_WORK1, 1); + LSR_rri(d, d, 1); + MSR_CPSRf_r(REG_WORK2); + CC_ORR_rri(NATIVE_CC_CS, d,d,0x80000000); + LSR_rrr(d, d, REG_WORK1); + + MOV_ri(REG_WORK2, 1); + LSL_rrr(REG_WORK2, REG_WORK2, REG_WORK1); + + RSB_rri(REG_WORK1, REG_WORK1, 32); + ORR_rrrLSLr(d,d,s,REG_WORK1); + + TST_rr(s, REG_WORK2); + CC_MSR_CPSRf_i(NATIVE_CC_NE, ARM_C_FLAG); + CC_MSR_CPSRf_i(NATIVE_CC_EQ, 0); + B_i(0);// label2 + +// label: + MSR_CPSRf_i(0); + +// label2: + TST_rr(d,d); + + unlock2(d); + unlock2(s); + unlock2(i); +} +MENDFUNC(3,jff_ROXR_l,(W4 d, RR4 s, RR4 i)) + +/* + * ROXRW + * Operand Syntax: + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the result is set. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Always cleared. + * C Set according to the last bit rotated out of the operand. + * + */ +MIDFUNC(2,jnf_ROXRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + RRX_rr(d,d); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_ROXRW,(W4 d, RR4 s)) + +MIDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=writereg(d,4); + + LSL_rri(d,s,16); + MSR_CPSRf_i(0); + RRXS_rr(d,d); + LSR_rri(d,d,16); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) + +/* + * SUB + * Operand Syntax: , Dn + * Dn, + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Set if the result is zero. Cleared otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + */ +MIDFUNC(3,jnf_SUB_b_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val-v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED8_IMM_2_REG(REG_WORK1, (uint8)v); + SUB_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_SUB_b_imm,(W4 d, RR4 s, IMM v)) + +MIDFUNC(3,jnf_SUB_b,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_SUB_b_imm)(d,s,live.state[v].val); + return; + } + + // d has to be different to s and v + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUB_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jnf_SUB_b,(W4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jnf_SUB_w_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val-v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + UNSIGNED16_IMM_2_REG(REG_WORK1, (uint16)v); + SUB_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_SUB_w_imm,(W4 d, RR4 s, IMM v)) + +MIDFUNC(3,jnf_SUB_w,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_SUB_w_imm)(d,s,live.state[v].val); + return; + } + + // d has to be different to s and v + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUB_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jnf_SUB_w,(W4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jnf_SUB_l_imm,(W4 d, RR4 s, IMM v)) +{ + if (isconst(s)) { + set_const(d,live.state[s].val-v); + return; + } + + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK1, v); + SUB_rrr(d,s,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jnf_SUB_l_imm,(W4 d, RR4 s, IMM v)) + +MIDFUNC(3,jnf_SUB_l,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jnf_SUB_l_imm)(d,s,live.state[v].val); + return; + } + + // d has to be different to s and v + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUB_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jnf_SUB_l,(W4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_IMM_2_REG(REG_WORK2, (uint8)v); + SIGNED8_REG_2_REG(REG_WORK1, s); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) + +MIDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) +{ + if (isconst(v)) { + COMPCALL(jff_SUB_b_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_SUB_w_imm,(W4 d, RR2 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_IMM_2_REG(REG_WORK2, (uint16)v); + SIGNED16_REG_2_REG(REG_WORK1, s); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jitc_SUB_ff_w2l_rri,(W4 d, RR2 s, IMM v)) + +MIDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) +{ + if (isconst(v)) { + COMPCALL(jff_SUB_w_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + SUBS_rrr(d,REG_WORK1,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) +{ + s=readreg(s,4); + d=writereg(d,4); + + compemu_raw_mov_l_ri(REG_WORK2, v); + SUBS_rrr(d,s,REG_WORK2); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); +} +MENDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) + +MIDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) +{ + if (isconst(v)) { + COMPCALL(jff_SUB_l_imm)(d,s,live.state[v].val); + return; + } + + v=readreg(v,4); + s=readreg(s,4); + d=writereg(d,4); + + SUBS_rrr(d,s,v); + + // Todo: Handle this with inverted carry + MRS_CPSR(REG_WORK1);// mrs r2, CPSR + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG);// eor r2, r2, #0x20000000 + MSR_CPSR_r(REG_WORK1);// msr CPSR_fc, r2 + // inverted_carry = true; + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) + +/* + * SUBA + * + * Operand Syntax: , Dn + * + * Operand Size: 16,32 + * + * Flags: Not affected. + * + */ +MIDFUNC(2,jnf_SUBA_b,(W4 d, RR1 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED8_REG_2_REG(REG_WORK1,s); + SUB_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_SUBA_b,(W4 d, RR1 s)) + +MIDFUNC(2,jnf_SUBA_w,(W4 d, RR2 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SIGNED16_REG_2_REG(REG_WORK1,s); + SUB_rrr(d,d,REG_WORK1); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_SUBA_w,(W4 d, RR2 s)) + +MIDFUNC(2,jnf_SUBA_l,(W4 d, RR4 s)) +{ + s=readreg(s,4); + d=rmw(d,4,4); + + SUB_rrr(d,d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,jnf_SUBA_l,(W4 d, RR4 s)) + +/* + * SUBX + * Operand Syntax: Dy, Dx + * -(Ay), -(Ax) + * + * Operand Size: 8,16,32 + * + * X Set the same as the carry bit. + * N Set if the result is negative. Cleared otherwise. + * Z Cleared if the result is nonzero. Unchanged otherwise. + * V Set if an overflow is generated. Cleared otherwise. + * C Set if a carry is generated. Cleared otherwise. + * + * Attention: Z is cleared only if the result is nonzero. Unchanged otherwise + * + */ +MIDFUNC(3,jnf_SUBX,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + SBC_rrr(d,s,v); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jnf_SUBX,(W4 d, RR4 s, RR4 v)) + +MIDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + MRS_CPSR(REG_WORK1); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK1, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK1, ARM_Z_FLAG); + PUSH(REG_WORK1); + + SIGNED8_REG_2_REG(REG_WORK1, s); + SIGNED8_REG_2_REG(REG_WORK2, v); + SBCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) + +MIDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + MRS_CPSR(REG_WORK1); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK1, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK1, ARM_Z_FLAG); + PUSH(REG_WORK1); + + SIGNED16_REG_2_REG(REG_WORK1, s); + SIGNED16_REG_2_REG(REG_WORK2, v); + SBCS_rrr(d,REG_WORK1,REG_WORK2); + + POP(REG_WORK2); + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) + +MIDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) +{ + s=readreg(s,4); + v=readreg(v,4); + d=writereg(d,4); + + MRS_CPSR(REG_WORK2); + CC_MVN_ri(NATIVE_CC_EQ, REG_WORK2, 0); + CC_MVN_ri(NATIVE_CC_NE, REG_WORK2, ARM_Z_FLAG); + + SBCS_rrr(d,s,v); + + MRS_CPSR(REG_WORK1); + EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); + AND_rrr(REG_WORK1, REG_WORK1, REG_WORK2); + MSR_CPSR_r(REG_WORK1); + + unlock2(d); + unlock2(s); + unlock2(v); +} +MENDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) + +/* + * SWAP + * Operand Syntax: Dn + * + * Operand Size: 16 + * + * X Not affected. + * N Set if the most significant bit of the 32-bit result is set. Cleared otherwise. + * Z Set if the 32-bit result is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(1,jnf_SWAP,(RW4 d)) +{ + d=rmw(d,4,4); + + ROR_rri(d,d,16); + + unlock2(d); +} +MENDFUNC(1,jnf_SWAP,(RW4 d)) + +MIDFUNC(1,jff_SWAP,(RW4 d)) +{ + d=rmw(d,4,4); + + ROR_rri(d,d,16); + MSR_CPSRf_i(0); + TST_rr(d,d); + + unlock2(d); +} +MENDFUNC(1,jff_SWAP,(RW4 d)) + +/* + * TST + * Operand Syntax: + * + * Operand Size: 8,16,32 + * + * X Not affected. + * N Set if the operand is negative. Cleared otherwise. + * Z Set if the operand is zero. Cleared otherwise. + * V Always cleared. + * C Always cleared. + * + */ +MIDFUNC(1,jff_TST_b,(RR1 s)) +{ + if (isconst(s)) { + SIGNED8_IMM_2_REG(REG_WORK1, (uint8)live.state[s].val); + } else { + s=readreg(s,4); + SIGNED8_REG_2_REG(REG_WORK1, s); + unlock2(s); + } + MSR_CPSRf_i(0); + TST_rr(REG_WORK1,REG_WORK1); +} +MENDFUNC(1,jff_TST_b,(RR1 s)) + +MIDFUNC(1,jff_TST_w,(RR2 s)) +{ + if (isconst(s)) { + SIGNED16_IMM_2_REG(REG_WORK1, (uint16)live.state[s].val); + } else { + s=readreg(s,4); + SIGNED16_REG_2_REG(REG_WORK1, s); + unlock2(s); + } + MSR_CPSRf_i(0); + TST_rr(REG_WORK1,REG_WORK1); +} +MENDFUNC(1,jff_TST_w,(RR2 s)) + +MIDFUNC(1,jff_TST_l,(RR4 s)) +{ + MSR_CPSRf_i(0); + + if (isconst(s)) { + compemu_raw_mov_l_ri(REG_WORK1, live.state[s].val); + TST_rr(REG_WORK1,REG_WORK1); + } + else { + s=readreg(s,4); + TST_rr(s,s); + unlock2(s); + } +} +MENDFUNC(1,jff_TST_l,(RR4 s)) diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.h b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.h new file mode 100644 index 00000000..ecbc2fdf --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.h @@ -0,0 +1,348 @@ +/* + * compiler/compemu_midfunc_arm2.h - Native MIDFUNCS for ARM (JIT v2) + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu.h + * + */ + +// Arm optimized midfunc +extern const uae_u32 ARM_CCR_MAP[]; + +DECLARE_MIDFUNC(restore_inverted_carry(void)); + +// ADD +DECLARE_MIDFUNC(jnf_ADD(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jnf_ADD_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jff_ADD_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_ADD_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_ADD_l(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADD_b_imm(W4 d, RR1 s, IMM v)); +DECLARE_MIDFUNC(jff_ADD_w_imm(W4 d, RR2 s, IMM v)); +DECLARE_MIDFUNC(jff_ADD_l_imm(W4 d, RR4 s, IMM v)); + +// ADDA +DECLARE_MIDFUNC(jnf_ADDA_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jnf_ADDA_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jnf_ADDA_l(W4 d, RR4 s)); + +// ADDX +DECLARE_MIDFUNC(jnf_ADDX(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADDX_b(W4 d, RR1 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADDX_w(W4 d, RR2 s, RR4 v)); +DECLARE_MIDFUNC(jff_ADDX_l(W4 d, RR4 s, RR4 v)); + +// AND +DECLARE_MIDFUNC(jnf_AND(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_AND_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_AND_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_AND_l(W4 d, RR4 s, RR4 v)); + +// ANDSR +DECLARE_MIDFUNC(jff_ANDSR(IMM s, IMM x)); + +// ASL +DECLARE_MIDFUNC(jff_ASL_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASL_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASL_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASL_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASL_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASL_l_reg(W4 d, RR4 s, RR4 i)); + +// ASLW +DECLARE_MIDFUNC(jff_ASLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ASLW(W4 d, RR4 s)); + +// ASR +DECLARE_MIDFUNC(jnf_ASR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_ASR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_ASR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_ASR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_ASR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ASR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ASR_l_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ASR_l_reg(W4 d, RR4 s, RR4 i)); + +// ASRW +DECLARE_MIDFUNC(jff_ASRW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ASRW(W4 d, RR4 s)); + +// BCHG +DECLARE_MIDFUNC(jnf_BCHG_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jnf_BCHG_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BCHG_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jff_BCHG_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jnf_BCHG_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_BCHG_l(RW4 d, RR4 s)); + +DECLARE_MIDFUNC(jff_BCHG_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BCHG_l(RW4 d, RR4 s)); + +// BCLR +DECLARE_MIDFUNC(jnf_BCLR_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jnf_BCLR_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jnf_BCLR_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_BCLR_l(RW4 d, RR4 s)); + +DECLARE_MIDFUNC(jff_BCLR_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jff_BCLR_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BCLR_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BCLR_l(RW4 d, RR4 s)); + +// BSET +DECLARE_MIDFUNC(jnf_BSET_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jnf_BSET_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jnf_BSET_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_BSET_l(RW4 d, RR4 s)); + +DECLARE_MIDFUNC(jff_BSET_b_imm(RW4 d, IMM s)); +DECLARE_MIDFUNC(jff_BSET_l_imm(RW4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BSET_b(RW4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BSET_l(RW4 d, RR4 s)); + +// BTST +DECLARE_MIDFUNC(jff_BTST_b_imm(RR4 d, IMM s)); +DECLARE_MIDFUNC(jff_BTST_l_imm(RR4 d, IMM s)); + +DECLARE_MIDFUNC(jff_BTST_b(RR4 d, RR4 s)); +DECLARE_MIDFUNC(jff_BTST_l(RR4 d, RR4 s)); + +// CLR +DECLARE_MIDFUNC (jnf_CLR(W4 d)); +DECLARE_MIDFUNC (jff_CLR(W4 d)); + +// CMP +DECLARE_MIDFUNC(jff_CMP_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(jff_CMP_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(jff_CMP_l(RR4 d, RR4 s)); + +// CMPA +DECLARE_MIDFUNC(jff_CMPA_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(jff_CMPA_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(jff_CMPA_l(RR4 d, RR4 s)); + +// EOR +DECLARE_MIDFUNC(jnf_EOR(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_EOR_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_EOR_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_EOR_l(W4 d, RR4 s, RR4 v)); + +// EORSR +DECLARE_MIDFUNC(jff_EORSR(IMM s, IMM x)); + +// EXT +DECLARE_MIDFUNC(jnf_EXT_b(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_EXT_w(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_EXT_l(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_EXT_b(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_EXT_w(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_EXT_l(W4 d, RR4 s)); + +// LSL +DECLARE_MIDFUNC(jnf_LSL_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSL_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSL_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSL_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSL_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSL_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSL_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSL_l_reg(W4 d, RR4 s, RR4 i)); + +// LSLW +DECLARE_MIDFUNC(jff_LSLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_LSLW(W4 d, RR4 s)); + +// LSR +DECLARE_MIDFUNC(jnf_LSR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSR_b_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSR_w_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jff_LSR_l_imm(W4 d, RR4 s, IMM i)); +DECLARE_MIDFUNC(jnf_LSR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_LSR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_LSR_l_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSR_b_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSR_w_reg(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_LSR_l_reg(W4 d, RR4 s, RR4 i)); + +// LSRW +DECLARE_MIDFUNC(jff_LSRW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_LSRW(W4 d, RR4 s)); + +// MOVE +DECLARE_MIDFUNC(jnf_MOVE(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_MOVE_b_imm(W4 d, IMM i)); +DECLARE_MIDFUNC(jff_MOVE_w_imm(W4 d, IMM i)); +DECLARE_MIDFUNC(jff_MOVE_l_imm(W4 d, IMM i)); +DECLARE_MIDFUNC(jff_MOVE_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_MOVE_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_MOVE_l(W4 d, RR4 s)); + +// MOVE16 +DECLARE_MIDFUNC(jnf_MOVE16(RR4 d, RR4 s)); + +// MOVEA +DECLARE_MIDFUNC(jnf_MOVEA_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jnf_MOVEA_l(W4 d, RR4 s)); + +// MULS +DECLARE_MIDFUNC (jnf_MULS(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULS(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULS32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULS32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULS64(RW4 d, RW4 s)); +DECLARE_MIDFUNC (jff_MULS64(RW4 d, RW4 s)); + +// MULU +DECLARE_MIDFUNC (jnf_MULU(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULU(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULU32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jff_MULU32(RW4 d, RR4 s)); +DECLARE_MIDFUNC (jnf_MULU64(RW4 d, RW4 s)); +DECLARE_MIDFUNC (jff_MULU64(RW4 d, RW4 s)); + +// NEG +DECLARE_MIDFUNC(jnf_NEG(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_NEG_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_NEG_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_NEG_l(W4 d, RR4 s)); + +// NEGX +DECLARE_MIDFUNC(jnf_NEGX(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_NEGX_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_NEGX_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_NEGX_l(W4 d, RR4 s)); + +// NOT +DECLARE_MIDFUNC(jnf_NOT(W4 d, RR4 s)); +DECLARE_MIDFUNC(jff_NOT_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jff_NOT_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jff_NOT_l(W4 d, RR4 s)); + +// OR +DECLARE_MIDFUNC(jnf_OR(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_OR_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_OR_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_OR_l(W4 d, RR4 s, RR4 v)); + +// ORSR +DECLARE_MIDFUNC(jff_ORSR(IMM s, IMM x)); + +// ROL +DECLARE_MIDFUNC(jnf_ROL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROL_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROL_l(W4 d, RR4 s, RR4 i)); + +// ROLW +DECLARE_MIDFUNC(jff_ROLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ROLW(W4 d, RR4 s)); + +// RORW +DECLARE_MIDFUNC(jff_RORW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_RORW(W4 d, RR4 s)); + +// ROXL +DECLARE_MIDFUNC(jnf_ROXL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXL_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXL_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXL_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXL_l(W4 d, RR4 s, RR4 i)); + +// ROXLW +DECLARE_MIDFUNC(jff_ROXLW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ROXLW(W4 d, RR4 s)); + +// ROR +DECLARE_MIDFUNC(jnf_ROR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROR_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROR_l(W4 d, RR4 s, RR4 i)); + +// ROXR +DECLARE_MIDFUNC(jnf_ROXR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jnf_ROXR_l(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXR_b(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXR_w(W4 d, RR4 s, RR4 i)); +DECLARE_MIDFUNC(jff_ROXR_l(W4 d, RR4 s, RR4 i)); + +// ROXRW +DECLARE_MIDFUNC(jff_ROXRW(W4 d, RR4 s)); +DECLARE_MIDFUNC(jnf_ROXRW(W4 d, RR4 s)); + +// SUB +DECLARE_MIDFUNC(jnf_SUB_b_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jnf_SUB_b(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jnf_SUB_w_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jnf_SUB_w(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jnf_SUB_l_imm(W4 d, RR4 s, IMM v)); +DECLARE_MIDFUNC(jnf_SUB_l(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUB_b(W4 d, RR1 s, RR1 v)); +DECLARE_MIDFUNC(jff_SUB_w(W4 d, RR2 s, RR2 v)); +DECLARE_MIDFUNC(jff_SUB_l(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUB_b_imm(W4 d, RR1 s, IMM v)); +DECLARE_MIDFUNC(jff_SUB_w_imm(W4 d, RR2 s, IMM v)); +DECLARE_MIDFUNC(jff_SUB_l_imm(W4 d, RR4 s, IMM v)); + +// SUBA +DECLARE_MIDFUNC(jnf_SUBA_b(W4 d, RR1 s)); +DECLARE_MIDFUNC(jnf_SUBA_w(W4 d, RR2 s)); +DECLARE_MIDFUNC(jnf_SUBA_l(W4 d, RR4 s)); + +// SUBX +DECLARE_MIDFUNC(jnf_SUBX(W4 d, RR4 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUBX_b(W4 d, RR1 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUBX_w(W4 d, RR2 s, RR4 v)); +DECLARE_MIDFUNC(jff_SUBX_l(W4 d, RR4 s, RR4 v)); + +// SWAP +DECLARE_MIDFUNC (jnf_SWAP(RW4 d)); +DECLARE_MIDFUNC (jff_SWAP(RW4 d)); + +// TST +DECLARE_MIDFUNC (jff_TST_b(RR1 s)); +DECLARE_MIDFUNC (jff_TST_w(RR2 s)); +DECLARE_MIDFUNC (jff_TST_l(RR4 s)); + diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp new file mode 100644 index 00000000..d5e2e053 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp @@ -0,0 +1,2982 @@ +/* + * compiler/compemu_midfunc_arm.cpp - Native MIDFUNCS for IA-32 and AMD64 + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu_support.cpp + * + */ + +static int f_rmw(int r) +{ + int n; + + f_make_exclusive(r,0); + if (f_isinreg(r)) { + n=live.fate[r].realreg; + } + else + n=f_alloc_reg(r,0); + live.fate[r].status=DIRTY; + live.fat[n].locked++; + live.fat[n].touched=touchcnt++; + return n; +} + +static void fflags_into_flags_internal(uae_u32 tmp) +{ + int r; + + clobber_flags(); + r=f_readreg(FP_RESULT); + if (FFLAG_NREG_CLOBBER_CONDITION) { + int tmp2=tmp; + tmp=writereg_specific(tmp,4,FFLAG_NREG); + raw_fflags_into_flags(r); + unlock2(tmp); + forget_about(tmp2); + } + else + raw_fflags_into_flags(r); + f_unlock(r); + live_flags(); +} + + +/******************************************************************** + * CPU functions exposed to gencomp. Both CREATE and EMIT time * + ********************************************************************/ + + +/* + * RULES FOR HANDLING REGISTERS: + * + * * In the function headers, order the parameters + * - 1st registers written to + * - 2nd read/modify/write registers + * - 3rd registers read from + * * Before calling raw_*, you must call readreg, writereg or rmw for + * each register + * * The order for this is + * - 1st call remove_offset for all registers written to with size<4 + * - 2nd call readreg for all registers read without offset + * - 3rd call rmw for all rmw registers + * - 4th call readreg_offset for all registers that can handle offsets + * - 5th call get_offset for all the registers from the previous step + * - 6th call writereg for all written-to registers + * - 7th call raw_* + * - 8th unlock2 all registers that were locked + */ + +MIDFUNC(0,live_flags,(void)) +{ + live.flags_on_stack=TRASH; + live.flags_in_flags=VALID; + live.flags_are_important=1; +} +MENDFUNC(0,live_flags,(void)) + +MIDFUNC(0,dont_care_flags,(void)) +{ + live.flags_are_important=0; +} +MENDFUNC(0,dont_care_flags,(void)) + +MIDFUNC(0,duplicate_carry,(void)) +{ + evict(FLAGX); + make_flags_live_internal(); +#ifdef UAE + COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem + 1, NATIVE_CC_CS); +#else + COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem, NATIVE_CC_CS); +#endif + log_vwrite(FLAGX); +} +MENDFUNC(0,duplicate_carry,(void)) + +MIDFUNC(0,restore_carry,(void)) +{ + if (!have_rat_stall) { /* Not a P6 core, i.e. no partial stalls */ +#ifdef UAE + bt_l_ri_noclobber(FLAGX, 8); +#else + bt_l_ri_noclobber(FLAGX, 0); +#endif + } + else { /* Avoid the stall the above creates. + This is slow on non-P6, though. + */ +#ifdef UAE + COMPCALL(rol_w_ri(FLAGX, 8)); +#else + COMPCALL(rol_b_ri(FLAGX, 8)); +#endif + isclean(FLAGX); + } +} +MENDFUNC(0,restore_carry,(void)) + +MIDFUNC(0,start_needflags,(void)) +{ + needflags=1; +} +MENDFUNC(0,start_needflags,(void)) + +MIDFUNC(0,end_needflags,(void)) +{ + needflags=0; +} +MENDFUNC(0,end_needflags,(void)) + +MIDFUNC(0,make_flags_live,(void)) +{ + make_flags_live_internal(); +} +MENDFUNC(0,make_flags_live,(void)) + +MIDFUNC(1,fflags_into_flags,(W2 tmp)) +{ + clobber_flags(); + fflags_into_flags_internal(tmp); +} +MENDFUNC(1,fflags_into_flags,(W2 tmp)) + +MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ +{ + int size=4; + if (i<16) + size=2; + CLOBBER_BT; + r=readreg(r,size); + raw_bt_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ + +MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ +{ + CLOBBER_BT; + r=readreg(r,4); + b=readreg(b,4); + raw_bt_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ + +MIDFUNC(2,btc_l_ri,(RW4 r, IMM i)) +{ + int size=4; + if (i<16) + size=2; + CLOBBER_BT; + r=rmw(r,size,size); + raw_btc_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,btc_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_btc_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) + +MIDFUNC(2,btr_l_ri,(RW4 r, IMM i)) +{ + int size=4; + if (i<16) + size=2; + CLOBBER_BT; + r=rmw(r,size,size); + raw_btr_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,btr_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_btr_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) + +MIDFUNC(2,bts_l_ri,(RW4 r, IMM i)) +{ + int size=4; + if (i<16) + size=2; + CLOBBER_BT; + r=rmw(r,size,size); + raw_bts_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,bts_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) +{ + CLOBBER_BT; + b=readreg(b,4); + r=rmw(r,4,4); + raw_bts_l_rr(r,b); + unlock2(r); + unlock2(b); +} +MENDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) + +MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,4); + raw_mov_l_rm(d,s); + unlock2(d); +} +MENDFUNC(2,mov_l_rm,(W4 d, IMM s)) + +MIDFUNC(1,call_r,(RR4 r)) /* Clobbering is implicit */ +{ + r=readreg(r,4); + raw_dec_sp(STACK_SHADOW_SPACE); + raw_call_r(r); + raw_inc_sp(STACK_SHADOW_SPACE); + unlock2(r); +} +MENDFUNC(1,call_r,(RR4 r)) /* Clobbering is implicit */ + +MIDFUNC(2,sub_l_mi,(IMM d, IMM s)) +{ + CLOBBER_SUB; + raw_sub_l_mi(d,s) ; +} +MENDFUNC(2,sub_l_mi,(IMM d, IMM s)) + +MIDFUNC(2,mov_l_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_l_mi(d,s) ; +} +MENDFUNC(2,mov_l_mi,(IMM d, IMM s)) + +MIDFUNC(2,mov_w_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_w_mi(d,s) ; +} +MENDFUNC(2,mov_w_mi,(IMM d, IMM s)) + +MIDFUNC(2,mov_b_mi,(IMM d, IMM s)) +{ + CLOBBER_MOV; + raw_mov_b_mi(d,s) ; +} +MENDFUNC(2,mov_b_mi,(IMM d, IMM s)) + +MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,1,1); + raw_rol_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,rol_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,2,2); + raw_rol_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,rol_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROL; + r=rmw(r,4,4); + raw_rol_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,rol_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(rol_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,4,4); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_rol_b",r); + } + raw_rol_l_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(rol_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,2,2); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_rol_b",r); + } + raw_rol_w_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(rol_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_ROL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,1,1); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_rol_b",r); + } + raw_rol_b_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) + + +MIDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shll_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,4,4); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_rol_b",r); + } + raw_shll_l_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shll_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHLL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,2,2); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_shll_b",r); + } + raw_shll_w_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shll_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHLL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,1,1); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_shll_b",r); + } + raw_shll_b_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) + + +MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,1,1); + raw_ror_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,ror_b_ri,(RR1 r, IMM i)) + +MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,2,2); + raw_ror_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,ror_w_ri,(RR2 r, IMM i)) + +MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_ROR; + r=rmw(r,4,4); + raw_ror_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,ror_l_ri,(RR4 r, IMM i)) + +MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROR; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,4,4); + raw_ror_l_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) + +MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_ROR; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,2,2); + raw_ror_w_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) + +MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(ror_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_ROR; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,1,1); + raw_ror_b_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) + +MIDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shrl_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,4,4); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_rol_b",r); + } + raw_shrl_l_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shrl_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,2,2); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_shrl_b",r); + } + raw_shrl_w_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shrl_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHRL; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,1,1); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_shrl_b",r); + } + raw_shrl_b_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) + + + +MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(r) && !needflags) { + live.state[r].val<<=i; + return; + } + CLOBBER_SHLL; + r=rmw(r,4,4); + raw_shll_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shll_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHLL; + r=rmw(r,2,2); + raw_shll_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shll_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHLL; + r=rmw(r,1,1); + raw_shll_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shll_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(r) && !needflags) { + live.state[r].val>>=i; + return; + } + CLOBBER_SHRL; + r=rmw(r,4,4); + raw_shrl_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRL; + r=rmw(r,2,2); + raw_shrl_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRL; + r=rmw(r,1,1); + raw_shrl_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,4,4); + raw_shra_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shra_l_ri,(RW4 r, IMM i)) + +MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,2,2); + raw_shra_w_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shra_w_ri,(RW2 r, IMM i)) + +MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) +{ + if (!i && !needflags) + return; + CLOBBER_SHRA; + r=rmw(r,1,1); + raw_shra_b_ri(r,i); + unlock2(r); +} +MENDFUNC(2,shra_b_ri,(RW1 r, IMM i)) + +MIDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) +{ + if (isconst(r)) { + COMPCALL(shra_l_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRA; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,4,4); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_rol_b",r); + } + raw_shra_l_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) + +MIDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shra_w_ri)(d,(uae_u8)live.state[r].val); + return; + } + CLOBBER_SHRA; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,2,2); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_shra_b",r); + } + raw_shra_w_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) + +MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) +{ /* Can only do this with r==1, i.e. cl */ + + if (isconst(r)) { + COMPCALL(shra_b_ri)(d,(uae_u8)live.state[r].val); + return; + } + + CLOBBER_SHRA; + r=readreg_specific(r,1,SHIFTCOUNT_NREG); + d=rmw(d,1,1); + Dif (r!=1) { + jit_abort("Illegal register %d in raw_shra_b",r); + } + raw_shra_b_rr(d,r) ; + unlock2(r); + unlock2(d); +} +MENDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) + + +MIDFUNC(2,setcc,(W1 d, IMM cc)) +{ + CLOBBER_SETCC; + d=writereg(d,1); + raw_setcc(d,cc); + unlock2(d); +} +MENDFUNC(2,setcc,(W1 d, IMM cc)) + +MIDFUNC(2,setcc_m,(IMM d, IMM cc)) +{ + CLOBBER_SETCC; + raw_setcc_m(d,cc); +} +MENDFUNC(2,setcc_m,(IMM d, IMM cc)) + +MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) +{ + if (d==s) + return; + CLOBBER_CMOV; + s=readreg(s,4); + d=rmw(d,4,4); + raw_cmov_l_rr(d,s,cc); + unlock2(s); + unlock2(d); +} +MENDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) + +MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) +{ + CLOBBER_CMOV; + d=rmw(d,4,4); + raw_cmov_l_rm(d,s,cc); + unlock2(d); +} +MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) + +MIDFUNC(2,bsf_l_rr,(W4 d, RR4 s)) +{ + CLOBBER_BSF; + s = readreg(s, 4); + d = writereg(d, 4); + raw_bsf_l_rr(d, s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,bsf_l_rr,(W4 d, RR4 s)) + +/* Set the Z flag depending on the value in s. Note that the + value has to be 0 or -1 (or, more precisely, for non-zero + values, bit 14 must be set)! */ +MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) +{ + CLOBBER_BSF; + s=rmw_specific(s,4,4,FLAG_NREG3); + tmp=writereg(tmp,4); + raw_flags_set_zero(s, tmp); + unlock2(tmp); + unlock2(s); +} +MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) + +MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) +{ + CLOBBER_MUL; + s=readreg(s,4); + d=rmw(d,4,4); + raw_imul_32_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,imul_32_32,(RW4 d, RR4 s)) + +MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) +{ + CLOBBER_MUL; + s=rmw_specific(s,4,4,MUL_NREG2); + d=rmw_specific(d,4,4,MUL_NREG1); + raw_imul_64_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,imul_64_32,(RW4 d, RW4 s)) + +MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) +{ + CLOBBER_MUL; + s=rmw_specific(s,4,4,MUL_NREG2); + d=rmw_specific(d,4,4,MUL_NREG1); + raw_mul_64_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,mul_64_32,(RW4 d, RW4 s)) + +MIDFUNC(2,mul_32_32,(RW4 d, RR4 s)) +{ + CLOBBER_MUL; + s=readreg(s,4); + d=rmw(d,4,4); + raw_mul_32_32(d,s); + unlock2(s); + unlock2(d); +} +MENDFUNC(2,mul_32_32,(RW4 d, RR4 s)) + +#if SIZEOF_VOID_P == 8 +MIDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)live.state[s].val); + return; + } + + CLOBBER_SE32; + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,4); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,4); + } + raw_sign_extend_32_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s)) +#endif + +MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s16)live.state[s].val); + return; + } + + CLOBBER_SE16; + isrmw=(s==d); + if (!isrmw) { + s=readreg(s,2); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,2); + } + raw_sign_extend_16_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) + +MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_s32)(uae_s8)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_SE8; + if (!isrmw) { + s=readreg(s,1); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,1); + } + + raw_sign_extend_8_rr(d,s); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) + + +MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) +{ + int isrmw; + + if (isconst(s)) { + set_const(d,(uae_u32)(uae_u16)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_ZE16; + if (!isrmw) { + s=readreg(s,2); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,2); + } + raw_zero_extend_16_rr(d,s); + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) + +MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) +{ + int isrmw; + if (isconst(s)) { + set_const(d,(uae_u32)(uae_u8)live.state[s].val); + return; + } + + isrmw=(s==d); + CLOBBER_ZE8; + if (!isrmw) { + s=readreg(s,1); + d=writereg(d,4); + } + else { /* If we try to lock this twice, with different sizes, we + are int trouble! */ + s=d=rmw(s,4,1); + } + + raw_zero_extend_8_rr(d,s); + + if (!isrmw) { + unlock2(d); + unlock2(s); + } + else { + unlock2(s); + } +} +MENDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) + +MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) +{ + if (d==s) + return; + if (isconst(s)) { + COMPCALL(mov_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=writereg(d,1); + raw_mov_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,mov_b_rr,(W1 d, RR1 s)) + +MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) +{ + if (d==s) + return; + if (isconst(s)) { + COMPCALL(mov_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=writereg(d,2); + raw_mov_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,mov_w_rr,(W2 d, RR2 s)) + +MIDFUNC(4,mov_l_rrm_indexed,(W4 d,RR4 baser, RR4 index, IMM factor)) +{ + CLOBBER_MOV; + baser=readreg(baser,4); + index=readreg(index,4); + d=writereg(d,4); + + raw_mov_l_rrm_indexed(d,baser,index,factor); + unlock2(d); + unlock2(baser); + unlock2(index); +} +MENDFUNC(4,mov_l_rrm_indexed,(W4 d,RR4 baser, RR4 index, IMM factor)) + +MIDFUNC(4,mov_w_rrm_indexed,(W2 d, RR4 baser, RR4 index, IMM factor)) +{ + CLOBBER_MOV; + baser=readreg(baser,4); + index=readreg(index,4); + d=writereg(d,2); + + raw_mov_w_rrm_indexed(d,baser,index,factor); + unlock2(d); + unlock2(baser); + unlock2(index); +} +MENDFUNC(4,mov_w_rrm_indexed,(W2 d, RR4 baser, RR4 index, IMM factor)) + +MIDFUNC(4,mov_b_rrm_indexed,(W1 d, RR4 baser, RR4 index, IMM factor)) +{ + CLOBBER_MOV; + baser=readreg(baser,4); + index=readreg(index,4); + d=writereg(d,1); + + raw_mov_b_rrm_indexed(d,baser,index,factor); + + unlock2(d); + unlock2(baser); + unlock2(index); +} +MENDFUNC(4,mov_b_rrm_indexed,(W1 d, RR4 baser, RR4 index, IMM factor)) + + +MIDFUNC(4,mov_l_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR4 s)) +{ + CLOBBER_MOV; + baser=readreg(baser,4); + index=readreg(index,4); + s=readreg(s,4); + + Dif (baser==s || index==s) + jit_abort("mov_l_mrr_indexed"); + + + raw_mov_l_mrr_indexed(baser,index,factor,s); + unlock2(s); + unlock2(baser); + unlock2(index); +} +MENDFUNC(4,mov_l_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR4 s)) + +MIDFUNC(4,mov_w_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR2 s)) +{ + CLOBBER_MOV; + baser=readreg(baser,4); + index=readreg(index,4); + s=readreg(s,2); + + raw_mov_w_mrr_indexed(baser,index,factor,s); + unlock2(s); + unlock2(baser); + unlock2(index); +} +MENDFUNC(4,mov_w_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR2 s)) + +MIDFUNC(4,mov_b_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR1 s)) +{ + CLOBBER_MOV; + s=readreg(s,1); + baser=readreg(baser,4); + index=readreg(index,4); + + raw_mov_b_mrr_indexed(baser,index,factor,s); + unlock2(s); + unlock2(baser); + unlock2(index); +} +MENDFUNC(4,mov_b_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR1 s)) + + +MIDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s)) +{ + int basereg=baser; + int indexreg=index; + + CLOBBER_MOV; + s=readreg(s,4); + baser=readreg_offset(baser,4); + index=readreg_offset(index,4); + + base+=get_offset(basereg); + base+=factor*get_offset(indexreg); + + raw_mov_l_bmrr_indexed(base,baser,index,factor,s); + unlock2(s); + unlock2(baser); + unlock2(index); +} +MENDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s)) + +MIDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s)) +{ + int basereg=baser; + int indexreg=index; + + CLOBBER_MOV; + s=readreg(s,2); + baser=readreg_offset(baser,4); + index=readreg_offset(index,4); + + base+=get_offset(basereg); + base+=factor*get_offset(indexreg); + + raw_mov_w_bmrr_indexed(base,baser,index,factor,s); + unlock2(s); + unlock2(baser); + unlock2(index); +} +MENDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s)) + +MIDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s)) +{ + int basereg=baser; + int indexreg=index; + + CLOBBER_MOV; + s=readreg(s,1); + baser=readreg_offset(baser,4); + index=readreg_offset(index,4); + + base+=get_offset(basereg); + base+=factor*get_offset(indexreg); + + raw_mov_b_bmrr_indexed(base,baser,index,factor,s); + unlock2(s); + unlock2(baser); + unlock2(index); +} +MENDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s)) + + + +/* Read a long from base+baser+factor*index */ +MIDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, RR4 baser, RR4 index, IMM factor)) +{ + int basereg=baser; + int indexreg=index; + + CLOBBER_MOV; + baser=readreg_offset(baser,4); + index=readreg_offset(index,4); + base+=get_offset(basereg); + base+=factor*get_offset(indexreg); + d=writereg(d,4); + raw_mov_l_brrm_indexed(d,base,baser,index,factor); + unlock2(d); + unlock2(baser); + unlock2(index); +} +MENDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, RR4 baser, RR4 index, IMM factor)) + + +MIDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor)) +{ + int basereg=baser; + int indexreg=index; + + CLOBBER_MOV; + remove_offset(d,-1); + baser=readreg_offset(baser,4); + index=readreg_offset(index,4); + base+=get_offset(basereg); + base+=factor*get_offset(indexreg); + d=writereg(d,2); + raw_mov_w_brrm_indexed(d,base,baser,index,factor); + unlock2(d); + unlock2(baser); + unlock2(index); +} +MENDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor)) + + +MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor)) +{ + int basereg=baser; + int indexreg=index; + + CLOBBER_MOV; + remove_offset(d,-1); + baser=readreg_offset(baser,4); + index=readreg_offset(index,4); + base+=get_offset(basereg); + base+=factor*get_offset(indexreg); + d=writereg(d,1); + raw_mov_b_brrm_indexed(d,base,baser,index,factor); + unlock2(d); + unlock2(baser); + unlock2(index); +} +MENDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor)) + +/* Read a long from base+factor*index */ +MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) +{ + int indexreg=index; + + if (isconst(index)) { + COMPCALL(mov_l_rm)(d,base+factor*live.state[index].val); + return; + } + + CLOBBER_MOV; + index=readreg_offset(index,4); + base+=get_offset(indexreg)*factor; + d=writereg(d,4); + + raw_mov_l_rm_indexed(d,base,index,factor); + unlock2(index); + unlock2(d); +} +MENDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) + +/* read the long at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_l_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,4); + + raw_mov_l_rR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_w_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,2); + + raw_mov_w_rR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_b_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + d=writereg(d,1); + + raw_mov_b_rR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset)) + +/* read the long at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_l_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,4); + + raw_mov_l_brR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_w_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + remove_offset(d,-1); + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,2); + + raw_mov_w_brR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) + +/* read the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) +{ + int sreg=s; + if (isconst(s)) { + COMPCALL(mov_b_rm)(d,live.state[s].val+offset); + return; + } + CLOBBER_MOV; + remove_offset(d,-1); + s=readreg_offset(s,4); + offset+=get_offset(sreg); + d=writereg(d,1); + + raw_mov_b_brR(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) + +MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_l_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_l_Ri(d,i,offset); + unlock2(d); +} +MENDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) + +MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_w_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_w_Ri(d,i,offset); + unlock2(d); +} +MENDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) + +MIDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_b_mi)(live.state[d].val+offset,i); + return; + } + + CLOBBER_MOV; + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_b_Ri(d,i,offset); + unlock2(d); +} +MENDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset)) + +/* Warning! OFFSET is byte sized only! */ +MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_l_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_l_Ri)(d,live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,4); + d=readreg(d,4); + + raw_mov_l_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) + +MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_w_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_w_Ri)(d,(uae_u16)live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=readreg(d,4); + raw_mov_w_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) + +MIDFUNC(3,mov_b_Rr,(RR4 d, RR1 s, IMM offset)) +{ + if (isconst(d)) { + COMPCALL(mov_b_mr)(live.state[d].val+offset,s); + return; + } + if (isconst(s)) { + COMPCALL(mov_b_Ri)(d,(uae_u8)live.state[s].val,offset); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=readreg(d,4); + raw_mov_b_Rr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_b_Rr,(RR4 d, RR1 s, IMM offset)) + +MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) +{ + if (isconst(s)) { + COMPCALL(mov_l_ri)(d,live.state[s].val+offset); + return; + } +#if USE_OFFSET + if (d==s) { + add_offset(d,offset); + return; + } +#endif + CLOBBER_LEA; + s=readreg(s,4); + d=writereg(d,4); + raw_lea_l_brr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) + +MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) +{ + if (!offset) { + COMPCALL(lea_l_rr_indexed)(d,s,index,factor); + return; + } + CLOBBER_LEA; + s=readreg(s,4); + index=readreg(index,4); + d=writereg(d,4); + + raw_lea_l_brr_indexed(d,s,index,factor,offset); + unlock2(d); + unlock2(index); + unlock2(s); +} +MENDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) + +MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) +{ + CLOBBER_LEA; + s=readreg(s,4); + index=readreg(index,4); + d=writereg(d,4); + + raw_lea_l_rr_indexed(d,s,index,factor); + unlock2(d); + unlock2(index); + unlock2(s); +} +MENDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) + +/* write d to the long at the address contained in s+offset */ +MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_l_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,4); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + + raw_mov_l_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) + +/* write the word at the address contained in s+offset and store in d */ +MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) +{ + int dreg=d; + + if (isconst(d)) { + COMPCALL(mov_w_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,2); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_w_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) + +MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) +{ + int dreg=d; + if (isconst(d)) { + COMPCALL(mov_b_mr)(live.state[d].val+offset,s); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + d=readreg_offset(d,4); + offset+=get_offset(dreg); + raw_mov_b_bRr(d,s,offset); + unlock2(d); + unlock2(s); +} +MENDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) + +MIDFUNC(1,mid_bswap_32,(RW4 r)) +{ + + if (isconst(r)) { + uae_u32 oldv=live.state[r].val; + live.state[r].val=reverse32(oldv); + return; + } + + CLOBBER_SW32; + r=rmw(r,4,4); + raw_bswap_32(r); + unlock2(r); +} +MENDFUNC(1,mid_bswap_32,(RW4 r)) + +MIDFUNC(1,mid_bswap_16,(RW2 r)) +{ + if (isconst(r)) { + uae_u32 oldv=live.state[r].val; + live.state[r].val=((oldv>>8)&0xff) | ((oldv<<8)&0xff00) | (oldv&0xffff0000); + return; + } + + CLOBBER_SW16; + r=rmw(r,2,2); + + raw_bswap_16(r); + unlock2(r); +} +MENDFUNC(1,mid_bswap_16,(RW2 r)) + + + +MIDFUNC(2,mov_l_rr,(W4 d, RR4 s)) +{ + int olds; + + if (d==s) { /* How pointless! */ + return; + } + if (isconst(s)) { + COMPCALL(mov_l_ri)(d,live.state[s].val); + return; + } + olds=s; + disassociate(d); + s=readreg_offset(s,4); + live.state[d].realreg=s; + live.state[d].realind=live.nat[s].nholds; + live.state[d].val=live.state[olds].val; + live.state[d].validsize=4; + live.state[d].dirtysize=4; + set_status(d,DIRTY); + + live.nat[s].holds[live.nat[s].nholds]=d; + live.nat[s].nholds++; + log_clobberreg(d); + jit_log2("Added %d to nreg %d(%d), now holds %d regs", d,s,live.state[d].realind,live.nat[s].nholds); + unlock2(s); +} +MENDFUNC(2,mov_l_rr,(W4 d, RR4 s)) + +MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(mov_l_mi)(d,live.state[s].val); + return; + } + CLOBBER_MOV; + s=readreg(s,4); + + raw_mov_l_mr(d,s); + unlock2(s); +} +MENDFUNC(2,mov_l_mr,(IMM d, RR4 s)) + + +MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(mov_w_mi)(d,(uae_u16)live.state[s].val); + return; + } + CLOBBER_MOV; + s=readreg(s,2); + + raw_mov_w_mr(d,s); + unlock2(s); +} +MENDFUNC(2,mov_w_mr,(IMM d, RR2 s)) + +MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,2); + + raw_mov_w_rm(d,s); + unlock2(d); +} +MENDFUNC(2,mov_w_rm,(W2 d, IMM s)) + +MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(mov_b_mi)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_MOV; + s=readreg(s,1); + + raw_mov_b_mr(d,s); + unlock2(s); +} +MENDFUNC(2,mov_b_mr,(IMM d, RR1 s)) + +MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,1); + + raw_mov_b_rm(d,s); + unlock2(d); +} +MENDFUNC(2,mov_b_rm,(W1 d, IMM s)) + +MIDFUNC(2,mov_l_ri,(W4 d, IMM s)) +{ + set_const(d,s); + return; +} +MENDFUNC(2,mov_l_ri,(W4 d, IMM s)) + +MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,2); + + raw_mov_w_ri(d,s); + unlock2(d); +} +MENDFUNC(2,mov_w_ri,(W2 d, IMM s)) + +MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) +{ + CLOBBER_MOV; + d=writereg(d,1); + + raw_mov_b_ri(d,s); + unlock2(d); +} +MENDFUNC(2,mov_b_ri,(W1 d, IMM s)) + +MIDFUNC(2,add_l_mi,(IMM d, IMM s)) +{ + CLOBBER_ADD; + raw_add_l_mi(d,s) ; +} +MENDFUNC(2,add_l_mi,(IMM d, IMM s)) + +MIDFUNC(2,add_w_mi,(IMM d, IMM s)) +{ + CLOBBER_ADD; + raw_add_w_mi(d,s) ; +} +MENDFUNC(2,add_w_mi,(IMM d, IMM s)) + +MIDFUNC(2,add_b_mi,(IMM d, IMM s)) +{ + CLOBBER_ADD; + raw_add_b_mi(d,s) ; +} +MENDFUNC(2,add_b_mi,(IMM d, IMM s)) + +MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) +{ + CLOBBER_TEST; + d=readreg(d,4); + + raw_test_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,test_l_ri,(RR4 d, IMM i)) + +MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) +{ + CLOBBER_TEST; + d=readreg(d,4); + s=readreg(s,4); + + raw_test_l_rr(d,s);; + unlock2(d); + unlock2(s); +} +MENDFUNC(2,test_l_rr,(RR4 d, RR4 s)) + +MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) +{ + CLOBBER_TEST; + d=readreg(d,2); + s=readreg(s,2); + + raw_test_w_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,test_w_rr,(RR2 d, RR2 s)) + +MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) +{ + CLOBBER_TEST; + d=readreg(d,1); + s=readreg(s,1); + + raw_test_b_rr(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,test_b_rr,(RR1 d, RR1 s)) + + +MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) +{ + if (isconst(d) && !needflags) { + live.state[d].val &= i; + return; + } + + CLOBBER_AND; + d=rmw(d,4,4); + + raw_and_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,and_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,and_l,(RW4 d, RR4 s)) +{ + CLOBBER_AND; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_and_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,and_l,(RW4 d, RR4 s)) + +MIDFUNC(2,and_w,(RW2 d, RR2 s)) +{ + CLOBBER_AND; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_and_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,and_w,(RW2 d, RR2 s)) + +MIDFUNC(2,and_b,(RW1 d, RR1 s)) +{ + CLOBBER_AND; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_and_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,and_b,(RW1 d, RR1 s)) + +// gb-- used for making an fpcr value in compemu_fpp.cpp +MIDFUNC(2,or_l_rm,(RW4 d, IMM s)) +{ + CLOBBER_OR; + d=rmw(d,4,4); + + raw_or_l_rm(d,s); + unlock2(d); +} +MENDFUNC(2,or_l_rm,(RW4 d, IMM s)) + +MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) +{ + if (isconst(d) && !needflags) { + live.state[d].val|=i; + return; + } + CLOBBER_OR; + d=rmw(d,4,4); + + raw_or_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,or_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,or_l,(RW4 d, RR4 s)) +{ + if (isconst(d) && isconst(s) && !needflags) { + live.state[d].val|=live.state[s].val; + return; + } + CLOBBER_OR; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_or_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,or_l,(RW4 d, RR4 s)) + +MIDFUNC(2,or_w,(RW2 d, RR2 s)) +{ + CLOBBER_OR; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_or_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,or_w,(RW2 d, RR2 s)) + +MIDFUNC(2,or_b,(RW1 d, RR1 s)) +{ + CLOBBER_OR; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_or_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,or_b,(RW1 d, RR1 s)) + +MIDFUNC(2,adc_l,(RW4 d, RR4 s)) +{ + CLOBBER_ADC; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_adc_l(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,adc_l,(RW4 d, RR4 s)) + +MIDFUNC(2,adc_w,(RW2 d, RR2 s)) +{ + CLOBBER_ADC; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_adc_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,adc_w,(RW2 d, RR2 s)) + +MIDFUNC(2,adc_b,(RW1 d, RR1 s)) +{ + CLOBBER_ADC; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_adc_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,adc_b,(RW1 d, RR1 s)) + +MIDFUNC(2,add_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(add_l_ri)(d,live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_add_l(d,s); + + unlock2(d); + unlock2(s); +} +MENDFUNC(2,add_l,(RW4 d, RR4 s)) + +MIDFUNC(2,add_w,(RW2 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(add_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_add_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,add_w,(RW2 d, RR2 s)) + +MIDFUNC(2,add_b,(RW1 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(add_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_ADD; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_add_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,add_b,(RW1 d, RR1 s)) + +MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(d) && !needflags) { + live.state[d].val-=i; + return; + } +#if USE_OFFSET + if (!needflags) { + add_offset(d,-i); + return; + } +#endif + + CLOBBER_SUB; + d=rmw(d,4,4); + + raw_sub_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,sub_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_SUB; + d=rmw(d,2,2); + + raw_sub_w_ri(d,i); + unlock2(d); +} +MENDFUNC(2,sub_w_ri,(RW2 d, IMM i)) + +MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_SUB; + d=rmw(d,1,1); + + raw_sub_b_ri(d,i); + + unlock2(d); +} +MENDFUNC(2,sub_b_ri,(RW1 d, IMM i)) + +MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) +{ + if (!i && !needflags) + return; + if (isconst(d) && !needflags) { + live.state[d].val+=i; + return; + } +#if USE_OFFSET + if (!needflags) { + add_offset(d,i); + return; + } +#endif + CLOBBER_ADD; + d=rmw(d,4,4); + raw_add_l_ri(d,i); + unlock2(d); +} +MENDFUNC(2,add_l_ri,(RW4 d, IMM i)) + +MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_ADD; + d=rmw(d,2,2); + + raw_add_w_ri(d,i); + unlock2(d); +} +MENDFUNC(2,add_w_ri,(RW2 d, IMM i)) + +MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) +{ + if (!i && !needflags) + return; + + CLOBBER_ADD; + d=rmw(d,1,1); + + raw_add_b_ri(d,i); + + unlock2(d); +} +MENDFUNC(2,add_b_ri,(RW1 d, IMM i)) + +MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) +{ + CLOBBER_SBB; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_sbb_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sbb_l,(RW4 d, RR4 s)) + +MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) +{ + CLOBBER_SBB; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_sbb_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sbb_w,(RW2 d, RR2 s)) + +MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) +{ + CLOBBER_SBB; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_sbb_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sbb_b,(RW1 d, RR1 s)) + +MIDFUNC(2,sub_l,(RW4 d, RR4 s)) +{ + if (isconst(s)) { + COMPCALL(sub_l_ri)(d,live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_sub_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sub_l,(RW4 d, RR4 s)) + +MIDFUNC(2,sub_w,(RW2 d, RR2 s)) +{ + if (isconst(s)) { + COMPCALL(sub_w_ri)(d,(uae_u16)live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_sub_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sub_w,(RW2 d, RR2 s)) + +MIDFUNC(2,sub_b,(RW1 d, RR1 s)) +{ + if (isconst(s)) { + COMPCALL(sub_b_ri)(d,(uae_u8)live.state[s].val); + return; + } + + CLOBBER_SUB; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_sub_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,sub_b,(RW1 d, RR1 s)) + +MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) +{ + CLOBBER_CMP; + s=readreg(s,4); + d=readreg(d,4); + + raw_cmp_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,cmp_l,(RR4 d, RR4 s)) + +MIDFUNC(2,cmp_l_ri,(RR4 r, IMM i)) +{ + CLOBBER_CMP; + r=readreg(r,4); + + raw_cmp_l_ri(r,i); + unlock2(r); +} +MENDFUNC(2,cmp_l_ri,(RR4 r, IMM i)) + +MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) +{ + CLOBBER_CMP; + s=readreg(s,2); + d=readreg(d,2); + + raw_cmp_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,cmp_w,(RR2 d, RR2 s)) + +MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) +{ + CLOBBER_CMP; + s=readreg(s,1); + d=readreg(d,1); + + raw_cmp_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,cmp_b,(RR1 d, RR1 s)) + + +MIDFUNC(2,xor_l,(RW4 d, RR4 s)) +{ + CLOBBER_XOR; + s=readreg(s,4); + d=rmw(d,4,4); + + raw_xor_l(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,xor_l,(RW4 d, RR4 s)) + +MIDFUNC(2,xor_w,(RW2 d, RR2 s)) +{ + CLOBBER_XOR; + s=readreg(s,2); + d=rmw(d,2,2); + + raw_xor_w(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,xor_w,(RW2 d, RR2 s)) + +MIDFUNC(2,xor_b,(RW1 d, RR1 s)) +{ + CLOBBER_XOR; + s=readreg(s,1); + d=rmw(d,1,1); + + raw_xor_b(d,s); + unlock2(d); + unlock2(s); +} +MENDFUNC(2,xor_b,(RW1 d, RR1 s)) + +MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) +{ + clobber_flags(); + remove_all_offsets(); + if (osize==4) { + if (out1!=in1 && out1!=r) { + COMPCALL(forget_about)(out1); + } + } + else { + tomem_c(out1); + } + + in1=readreg_specific(in1,isize,REG_PAR1); + r=readreg(r,4); + prepare_for_call_1(); /* This should ensure that there won't be + any need for swapping nregs in prepare_for_call_2 + */ +#if USE_NORMAL_CALLING_CONVENTION + raw_push_l_r(in1); +#endif + unlock2(in1); + unlock2(r); + + prepare_for_call_2(); + raw_dec_sp(STACK_SHADOW_SPACE); + raw_call_r(r); + raw_inc_sp(STACK_SHADOW_SPACE); + +#if USE_NORMAL_CALLING_CONVENTION + raw_inc_sp(4); +#endif + + + live.nat[REG_RESULT].holds[0]=out1; + live.nat[REG_RESULT].nholds=1; + live.nat[REG_RESULT].touched=touchcnt++; + + live.state[out1].realreg=REG_RESULT; + live.state[out1].realind=0; + live.state[out1].val=0; + live.state[out1].validsize=osize; + live.state[out1].dirtysize=osize; + set_status(out1,DIRTY); +} +MENDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) + +MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) +{ + clobber_flags(); + remove_all_offsets(); + in1=readreg_specific(in1,isize1,REG_PAR1); + in2=readreg_specific(in2,isize2,REG_PAR2); + r=readreg(r,4); + prepare_for_call_1(); /* This should ensure that there won't be + any need for swapping nregs in prepare_for_call_2 + */ +#if USE_NORMAL_CALLING_CONVENTION + raw_push_l_r(in2); + raw_push_l_r(in1); +#endif + unlock2(r); + unlock2(in1); + unlock2(in2); + prepare_for_call_2(); + raw_dec_sp(STACK_SHADOW_SPACE); + raw_call_r(r); + raw_inc_sp(STACK_SHADOW_SPACE); +#if USE_NORMAL_CALLING_CONVENTION + raw_inc_sp(8); +#endif +} +MENDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) + +/* forget_about() takes a mid-layer register */ +MIDFUNC(1,forget_about,(W4 r)) +{ + if (isinreg(r)) + disassociate(r); + live.state[r].val=0; + set_status(r,UNDEF); +} +MENDFUNC(1,forget_about,(W4 r)) + +MIDFUNC(0,nop,(void)) +{ + raw_emit_nop(); +} +MENDFUNC(0,nop,(void)) + +MIDFUNC(1,f_forget_about,(FW r)) +{ + if (f_isinreg(r)) + f_disassociate(r); + live.fate[r].status=UNDEF; +} +MENDFUNC(1,f_forget_about,(FW r)) + +MIDFUNC(1,fmov_pi,(FW r)) +{ + r=f_writereg(r); + raw_fmov_pi(r); + f_unlock(r); +} +MENDFUNC(1,fmov_pi,(FW r)) + +MIDFUNC(1,fmov_log10_2,(FW r)) +{ + r=f_writereg(r); + raw_fmov_log10_2(r); + f_unlock(r); +} +MENDFUNC(1,fmov_log10_2,(FW r)) + +MIDFUNC(1,fmov_log2_e,(FW r)) +{ + r=f_writereg(r); + raw_fmov_log2_e(r); + f_unlock(r); +} +MENDFUNC(1,fmov_log2_e,(FW r)) + +MIDFUNC(1,fmov_loge_2,(FW r)) +{ + r=f_writereg(r); + raw_fmov_loge_2(r); + f_unlock(r); +} +MENDFUNC(1,fmov_loge_2,(FW r)) + +MIDFUNC(1,fmov_1,(FW r)) +{ + r=f_writereg(r); + raw_fmov_1(r); + f_unlock(r); +} +MENDFUNC(1,fmov_1,(FW r)) + +MIDFUNC(1,fmov_0,(FW r)) +{ + r=f_writereg(r); + raw_fmov_0(r); + f_unlock(r); +} +MENDFUNC(1,fmov_0,(FW r)) + +MIDFUNC(2,fmov_rm,(FW r, MEMR m)) +{ + r=f_writereg(r); + raw_fmov_rm(r,m); + f_unlock(r); +} +MENDFUNC(2,fmov_rm,(FW r, MEMR m)) + +MIDFUNC(2,fmovi_rm,(FW r, MEMR m)) +{ + r=f_writereg(r); + raw_fmovi_rm(r,m); + f_unlock(r); +} +MENDFUNC(2,fmovi_rm,(FW r, MEMR m)) + +MIDFUNC(2,fmovi_mr,(MEMW m, FR r)) +{ + r=f_readreg(r); + raw_fmovi_mr(m,r); + f_unlock(r); +} +MENDFUNC(2,fmovi_mr,(MEMW m, FR r)) + +MIDFUNC(3,fmovi_mrb,(MEMW m, FR r, double *bounds)) +{ + r=f_readreg(r); + raw_fmovi_mrb(m,r,bounds); + f_unlock(r); +} +MENDFUNC(3,fmovi_mrb,(MEMW m, FR r, double *bounds)) + +MIDFUNC(2,fmovs_rm,(FW r, MEMR m)) +{ + r=f_writereg(r); + raw_fmovs_rm(r,m); + f_unlock(r); +} +MENDFUNC(2,fmovs_rm,(FW r, MEMR m)) + +MIDFUNC(2,fmovs_mr,(MEMW m, FR r)) +{ + r=f_readreg(r); + raw_fmovs_mr(m,r); + f_unlock(r); +} +MENDFUNC(2,fmovs_mr,(MEMW m, FR r)) + +MIDFUNC(1,fcuts_r,(FRW r)) +{ + r=f_rmw(r); + raw_fcuts_r(r); + f_unlock(r); +} +MENDFUNC(1,fcuts_r,(FRW r)) + +MIDFUNC(1,fcut_r,(FRW r)) +{ + r=f_rmw(r); + raw_fcut_r(r); + f_unlock(r); +} +MENDFUNC(1,fcut_r,(FRW r)) + +MIDFUNC(2,fmov_ext_mr,(MEMW m, FR r)) +{ + r=f_readreg(r); + raw_fmov_ext_mr(m,r); + f_unlock(r); +} +MENDFUNC(2,fmov_ext_mr,(MEMW m, FR r)) + +MIDFUNC(2,fmov_mr,(MEMW m, FR r)) +{ + r=f_readreg(r); + raw_fmov_mr(m,r); + f_unlock(r); +} +MENDFUNC(2,fmov_mr,(MEMW m, FR r)) + +MIDFUNC(2,fmov_ext_rm,(FW r, MEMR m)) +{ + r=f_writereg(r); + raw_fmov_ext_rm(r,m); + f_unlock(r); +} +MENDFUNC(2,fmov_ext_rm,(FW r, MEMR m)) + +MIDFUNC(2,fmov_rr,(FW d, FR s)) +{ + if (d==s) { /* How pointless! */ + return; + } +#if USE_F_ALIAS + f_disassociate(d); + s=f_readreg(s); + live.fate[d].realreg=s; + live.fate[d].realind=live.fat[s].nholds; + live.fate[d].status=DIRTY; + live.fat[s].holds[live.fat[s].nholds]=d; + live.fat[s].nholds++; + f_unlock(s); +#else + s=f_readreg(s); + d=f_writereg(d); + raw_fmov_rr(d,s); + f_unlock(s); + f_unlock(d); +#endif +} +MENDFUNC(2,fmov_rr,(FW d, FR s)) + +MIDFUNC(2,fldcw_m_indexed,(RR4 index, IMM base)) +{ + index=readreg(index,4); + + raw_fldcw_m_indexed(index,base); + unlock2(index); +} +MENDFUNC(2,fldcw_m_indexed,(RR4 index, IMM base)) + +MIDFUNC(1,ftst_r,(FR r)) +{ + r=f_readreg(r); + raw_ftst_r(r); + f_unlock(r); +} +MENDFUNC(1,ftst_r,(FR r)) + +MIDFUNC(0,dont_care_fflags,(void)) +{ + f_disassociate(FP_RESULT); +} +MENDFUNC(0,dont_care_fflags,(void)) + +MIDFUNC(2,fsqrt_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fsqrt_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fsqrt_rr,(FW d, FR s)) + +MIDFUNC(2,fabs_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fabs_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fabs_rr,(FW d, FR s)) + +MIDFUNC(2,fgetexp_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fgetexp_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fgetexp_rr,(FW d, FR s)) + +MIDFUNC(2,fgetman_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fgetman_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fgetman_rr,(FW d, FR s)) + +MIDFUNC(2,fsin_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fsin_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fsin_rr,(FW d, FR s)) + +MIDFUNC(2,fcos_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fcos_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fcos_rr,(FW d, FR s)) + +MIDFUNC(2,ftan_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_ftan_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,ftan_rr,(FW d, FR s)) + +MIDFUNC(3,fsincos_rr,(FW d, FW c, FR s)) +{ + s=f_readreg(s); /* s for source */ + d=f_writereg(d); /* d for sine */ + c=f_writereg(c); /* c for cosine */ + raw_fsincos_rr(d,c,s); + f_unlock(s); + f_unlock(d); + f_unlock(c); +} +MENDFUNC(3,fsincos_rr,(FW d, FW c, FR s)) + +MIDFUNC(2,fscale_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_fscale_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fscale_rr,(FRW d, FR s)) + +MIDFUNC(2,ftwotox_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_ftwotox_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,ftwotox_rr,(FW d, FR s)) + +MIDFUNC(2,fetox_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fetox_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fetox_rr,(FW d, FR s)) + +MIDFUNC(2,frndint_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_frndint_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,frndint_rr,(FW d, FR s)) + +MIDFUNC(2,fetoxM1_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fetoxM1_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fetoxM1_rr,(FW d, FR s)) + +MIDFUNC(2,ftentox_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_ftentox_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,ftentox_rr,(FW d, FR s)) + +MIDFUNC(2,flog2_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_flog2_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,flog2_rr,(FW d, FR s)) + +MIDFUNC(2,flogN_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_flogN_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,flogN_rr,(FW d, FR s)) + +MIDFUNC(2,flogNP1_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_flogNP1_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,flogNP1_rr,(FW d, FR s)) + +MIDFUNC(2,flog10_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_flog10_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,flog10_rr,(FW d, FR s)) + +MIDFUNC(2,fasin_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fasin_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fasin_rr,(FW d, FR s)) + +MIDFUNC(2,facos_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_facos_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,facos_rr,(FW d, FR s)) + +MIDFUNC(2,fatan_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fatan_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fatan_rr,(FW d, FR s)) + +MIDFUNC(2,fatanh_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fatanh_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fatanh_rr,(FW d, FR s)) + +MIDFUNC(2,fsinh_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fsinh_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fsinh_rr,(FW d, FR s)) + +MIDFUNC(2,fcosh_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fcosh_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fcosh_rr,(FW d, FR s)) + +MIDFUNC(2,ftanh_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_ftanh_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,ftanh_rr,(FW d, FR s)) + +MIDFUNC(2,fneg_rr,(FW d, FR s)) +{ + s=f_readreg(s); + d=f_writereg(d); + raw_fneg_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fneg_rr,(FW d, FR s)) + +MIDFUNC(2,fadd_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_fadd_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fadd_rr,(FRW d, FR s)) + +MIDFUNC(2,fsub_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_fsub_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fsub_rr,(FRW d, FR s)) + +MIDFUNC(2,fcmp_rr,(FR d, FR s)) +{ + d=f_readreg(d); + s=f_readreg(s); + raw_fcmp_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fcmp_rr,(FR d, FR s)) + +MIDFUNC(2,fdiv_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_fdiv_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fdiv_rr,(FRW d, FR s)) + +MIDFUNC(2,frem_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_frem_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,frem_rr,(FRW d, FR s)) + +MIDFUNC(2,frem1_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_frem1_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,frem1_rr,(FRW d, FR s)) + +MIDFUNC(2,fmul_rr,(FRW d, FR s)) +{ + s=f_readreg(s); + d=f_rmw(d); + raw_fmul_rr(d,s); + f_unlock(s); + f_unlock(d); +} +MENDFUNC(2,fmul_rr,(FRW d, FR s)) + +#ifdef __GNUC__ + +static inline void mfence(void) +{ +#ifdef CPU_i386 + if (!cpuinfo.x86_has_xmm2) + __asm__ __volatile__("lock; addl $0,0(%%esp)":::"memory"); + else +#endif + __asm__ __volatile__("mfence":::"memory"); +} + +static inline void clflush(volatile void *__p) +{ + __asm__ __volatile__("clflush %0" : "+m" (*(volatile char *)__p)); +} + +static inline void flush_cpu_icache(void *start, void *stop) +{ + mfence(); + if (cpuinfo.x86_clflush_size != 0) + { + volatile char *vaddr = (volatile char *)(((uintptr)start / cpuinfo.x86_clflush_size) * cpuinfo.x86_clflush_size); + volatile char *vend = (volatile char *)((((uintptr)stop + cpuinfo.x86_clflush_size - 1) / cpuinfo.x86_clflush_size) * cpuinfo.x86_clflush_size); + while (vaddr < vend) + { + clflush(vaddr); + vaddr += cpuinfo.x86_clflush_size; + } + } + mfence(); +} + +#else + +static inline void flush_cpu_icache(void *start, void *stop) +{ + UNUSED(start); + UNUSED(stop); +} + +#endif + +static inline void write_jmp_target(uae_u32 *jmpaddr, cpuop_func* a) { + uintptr rel = (uintptr) a - ((uintptr) jmpaddr + 4); + *(jmpaddr) = (uae_u32) rel; + flush_cpu_icache((void *) jmpaddr, (void *) &jmpaddr[1]); +} + +static inline void emit_jmp_target(uae_u32 a) { + emit_long(a-((uintptr)target+4)); +} diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h new file mode 100644 index 00000000..a0f5cf92 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h @@ -0,0 +1,252 @@ +/* + * compiler/compemu_midfunc_x86.h - Native MIDFUNCS for IA-32 and AMD64 + * + * Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: + * File is included by compemu.h + * + */ + +DECLARE_MIDFUNC(bt_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(bt_l_rr(RR4 r, RR4 b)); +DECLARE_MIDFUNC(btc_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(btc_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(bts_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(bts_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(btr_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(btr_l_rr(RW4 r, RR4 b)); +DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s)); +DECLARE_MIDFUNC(call_r(RR4 r)); +DECLARE_MIDFUNC(sub_l_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(rol_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(rol_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(rol_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shll_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shll_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shll_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(ror_b_ri(RR1 r, IMM i)); +DECLARE_MIDFUNC(ror_w_ri(RR2 r, IMM i)); +DECLARE_MIDFUNC(ror_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(ror_l_rr(RR4 d, RR1 r)); +DECLARE_MIDFUNC(ror_w_rr(RR2 d, RR1 r)); +DECLARE_MIDFUNC(ror_b_rr(RR1 d, RR1 r)); +DECLARE_MIDFUNC(shrl_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shrl_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shrl_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shra_l_rr(RW4 d, RR1 r)); +DECLARE_MIDFUNC(shra_w_rr(RW2 d, RR1 r)); +DECLARE_MIDFUNC(shra_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i)); +DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i)); +DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i)); +DECLARE_MIDFUNC(setcc(W1 d, IMM cc)); +DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc)); +DECLARE_MIDFUNC(cmov_l_rr(RW4 d, RR4 s, IMM cc)); +DECLARE_MIDFUNC(cmov_l_rm(RW4 d, IMM s, IMM cc)); +DECLARE_MIDFUNC(bsf_l_rr(W4 d, RR4 s)); +DECLARE_MIDFUNC(pop_m(IMM d)); +DECLARE_MIDFUNC(push_m(IMM d)); +DECLARE_MIDFUNC(pop_l(W4 d)); +DECLARE_MIDFUNC(push_l_i(IMM i)); +DECLARE_MIDFUNC(push_l(RR4 s)); +DECLARE_MIDFUNC(clear_16(RW4 r)); +DECLARE_MIDFUNC(clear_8(RW4 r)); +DECLARE_MIDFUNC(sign_extend_32_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, RR2 s)); +DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s)); +DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s)); +DECLARE_MIDFUNC(simulate_bsf(W4 tmp, RW4 s)); +DECLARE_MIDFUNC(imul_32_32(RW4 d, RR4 s)); +DECLARE_MIDFUNC(mul_32_32(RW4 d, RR4 s)); +DECLARE_MIDFUNC(mov_b_rr(W1 d, RR1 s)); +DECLARE_MIDFUNC(mov_w_rr(W2 d, RR2 s)); +DECLARE_MIDFUNC(mov_l_rrm_indexed(W4 d,RR4 baser, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_w_rrm_indexed(W2 d, RR4 baser, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_b_rrm_indexed(W1 d, RR4 baser, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_mrr_indexed(RR4 baser, RR4 index, IMM factor, RR4 s)); +DECLARE_MIDFUNC(mov_w_mrr_indexed(RR4 baser, RR4 index, IMM factor, RR2 s)); +DECLARE_MIDFUNC(mov_b_mrr_indexed(RR4 baser, RR4 index, IMM factor, RR1 s)); +DECLARE_MIDFUNC(mov_l_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s)); +DECLARE_MIDFUNC(mov_w_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s)); +DECLARE_MIDFUNC(mov_b_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s)); +DECLARE_MIDFUNC(mov_l_brrm_indexed(W4 d, IMM base, RR4 baser, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_w_brrm_indexed(W2 d, IMM base, RR4 baser, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_b_brrm_indexed(W1 d, IMM base, RR4 baser, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_rR(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_rR(W2 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_rR(W1 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_l_brR(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_brR(W2 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_brR(W1 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_l_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_w_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_b_Ri(RR4 d, IMM i, IMM offset)); +DECLARE_MIDFUNC(mov_l_Rr(RR4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_Rr(RR4 d, RR2 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_Rr(RR4 d, RR1 s, IMM offset)); +DECLARE_MIDFUNC(lea_l_brr(W4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)); +DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, RR4 s, RR4 index, IMM factor)); +DECLARE_MIDFUNC(mov_l_bRr(RR4 d, RR4 s, IMM offset)); +DECLARE_MIDFUNC(mov_w_bRr(RR4 d, RR2 s, IMM offset)); +DECLARE_MIDFUNC(mov_b_bRr(RR4 d, RR1 s, IMM offset)); +DECLARE_MIDFUNC(mid_bswap_32(RW4 r)); +DECLARE_MIDFUNC(mid_bswap_16(RW2 r)); +DECLARE_MIDFUNC(mov_l_rr(W4 d, RR4 s)); +DECLARE_MIDFUNC(mov_l_mr(IMM d, RR4 s)); +DECLARE_MIDFUNC(mov_w_mr(IMM d, RR2 s)); +DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s)); +DECLARE_MIDFUNC(mov_b_mr(IMM d, RR1 s)); +DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s)); +DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s)); +DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s)); +DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s)); +DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s) ); +DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s) ); +DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s) ); +DECLARE_MIDFUNC(test_l_ri(RR4 d, IMM i)); +DECLARE_MIDFUNC(test_l_rr(RR4 d, RR4 s)); +DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s)); +DECLARE_MIDFUNC(test_b_rr(RR1 d, RR1 s)); +DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(and_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(and_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(and_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(or_l_rm(RW4 d, IMM s)); +DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(or_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(or_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(or_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(adc_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(adc_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(adc_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(add_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(add_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(add_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i)); +DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i)); +DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i)); +DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i)); +DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i)); +DECLARE_MIDFUNC(sbb_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(sbb_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(sbb_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(sub_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(sub_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(sub_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(cmp_l(RR4 d, RR4 s)); +DECLARE_MIDFUNC(cmp_l_ri(RR4 r, IMM i)); +DECLARE_MIDFUNC(cmp_w(RR2 d, RR2 s)); +DECLARE_MIDFUNC(cmp_b(RR1 d, RR1 s)); +DECLARE_MIDFUNC(xor_l(RW4 d, RR4 s)); +DECLARE_MIDFUNC(xor_w(RW2 d, RR2 s)); +DECLARE_MIDFUNC(xor_b(RW1 d, RR1 s)); +DECLARE_MIDFUNC(live_flags(void)); +DECLARE_MIDFUNC(dont_care_flags(void)); +DECLARE_MIDFUNC(duplicate_carry(void)); +DECLARE_MIDFUNC(restore_carry(void)); +DECLARE_MIDFUNC(start_needflags(void)); +DECLARE_MIDFUNC(end_needflags(void)); +DECLARE_MIDFUNC(make_flags_live(void)); +DECLARE_MIDFUNC(call_r_11(RR4 r, W4 out1, RR4 in1, IMM osize, IMM isize)); +DECLARE_MIDFUNC(call_r_02(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)); +DECLARE_MIDFUNC(forget_about(W4 r)); +DECLARE_MIDFUNC(nop(void)); + +DECLARE_MIDFUNC(f_forget_about(FW r)); +DECLARE_MIDFUNC(fmov_pi(FW r)); +DECLARE_MIDFUNC(fmov_log10_2(FW r)); +DECLARE_MIDFUNC(fmov_log2_e(FW r)); +DECLARE_MIDFUNC(fmov_loge_2(FW r)); +DECLARE_MIDFUNC(fmov_1(FW r)); +DECLARE_MIDFUNC(fmov_0(FW r)); +DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m)); +DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r)); +DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m)); +DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r)); +DECLARE_MIDFUNC(fmovi_mrb(MEMW m, FR r, double *bounds)); +DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m)); +DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r)); +DECLARE_MIDFUNC(fcuts_r(FRW r)); +DECLARE_MIDFUNC(fcut_r(FRW r)); +DECLARE_MIDFUNC(fmov_ext_mr(MEMW m, FR r)); +DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMR m)); +DECLARE_MIDFUNC(fmov_rr(FW d, FR s)); +DECLARE_MIDFUNC(fldcw_m_indexed(RR4 index, IMM base)); +DECLARE_MIDFUNC(ftst_r(FR r)); +DECLARE_MIDFUNC(dont_care_fflags(void)); +DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s)); +DECLARE_MIDFUNC(fabs_rr(FW d, FR s)); +DECLARE_MIDFUNC(frndint_rr(FW d, FR s)); +DECLARE_MIDFUNC(fgetexp_rr(FW d, FR s)); +DECLARE_MIDFUNC(fgetman_rr(FW d, FR s)); +DECLARE_MIDFUNC(fsin_rr(FW d, FR s)); +DECLARE_MIDFUNC(fcos_rr(FW d, FR s)); +DECLARE_MIDFUNC(ftan_rr(FW d, FR s)); +DECLARE_MIDFUNC(fsincos_rr(FW d, FW c, FR s)); +DECLARE_MIDFUNC(fscale_rr(FRW d, FR s)); +DECLARE_MIDFUNC(ftwotox_rr(FW d, FR s)); +DECLARE_MIDFUNC(fetox_rr(FW d, FR s)); +DECLARE_MIDFUNC(fetoxM1_rr(FW d, FR s)); +DECLARE_MIDFUNC(ftentox_rr(FW d, FR s)); +DECLARE_MIDFUNC(flog2_rr(FW d, FR s)); +DECLARE_MIDFUNC(flogN_rr(FW d, FR s)); +DECLARE_MIDFUNC(flogNP1_rr(FW d, FR s)); +DECLARE_MIDFUNC(flog10_rr(FW d, FR s)); +DECLARE_MIDFUNC(fasin_rr(FW d, FR s)); +DECLARE_MIDFUNC(facos_rr(FW d, FR s)); +DECLARE_MIDFUNC(fatan_rr(FW d, FR s)); +DECLARE_MIDFUNC(fatanh_rr(FW d, FR s)); +DECLARE_MIDFUNC(fsinh_rr(FW d, FR s)); +DECLARE_MIDFUNC(fcosh_rr(FW d, FR s)); +DECLARE_MIDFUNC(ftanh_rr(FW d, FR s)); +DECLARE_MIDFUNC(fneg_rr(FW d, FR s)); +DECLARE_MIDFUNC(fadd_rr(FRW d, FR s)); +DECLARE_MIDFUNC(fsub_rr(FRW d, FR s)); +DECLARE_MIDFUNC(fmul_rr(FRW d, FR s)); +DECLARE_MIDFUNC(frem_rr(FRW d, FR s)); +DECLARE_MIDFUNC(frem1_rr(FRW d, FR s)); +DECLARE_MIDFUNC(fdiv_rr(FRW d, FR s)); +DECLARE_MIDFUNC(fcmp_rr(FR d, FR s)); +DECLARE_MIDFUNC(fflags_into_flags(W2 tmp)); diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp new file mode 100644 index 00000000..c7b94244 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -0,0 +1,5111 @@ +/* + * compiler/compemu_support.cpp - Core dynamic translation engine + * + * Copyright (c) 2001-2009 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * JIT compiler m68k -> IA-32 and AMD64 / ARM + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne + * Portions related to CPU detection come from linux/arch/i386/kernel/setup.c + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef UAE + +#define writemem_special writemem +#define readmem_special readmem + +#else +#if !FIXED_ADDRESSING +#error "Only Fixed Addressing is supported with the JIT Compiler" +#endif + +#if defined(X86_ASSEMBLY) && !SAHF_SETO_PROFITABLE +#error "Only [LS]AHF scheme to [gs]et flags is supported with the JIT Compiler" +#endif + +/* NOTE: support for AMD64 assumes translation cache and other code + * buffers are allocated into a 32-bit address space because (i) B2/JIT + * code is not 64-bit clean and (ii) it's faster to resolve branches + * that way. + */ +#if !defined(CPU_i386) && !defined(CPU_x86_64) && !defined(CPU_arm) +#error "Only IA-32, X86-64 and ARM v6 targets are supported with the JIT Compiler" +#endif +#endif + +#define USE_MATCH 0 + +/* kludge for Brian, so he can compile under MSVC++ */ +#define USE_NORMAL_CALLING_CONVENTION 0 + +#include "sysconfig.h" +#include "sysdeps.h" + +#ifdef JIT + +#ifdef UAE +#include "options.h" +#include "events.h" +#include "memory.h" +#include "custom.h" +#else +#include "cpu_emulation.h" +#include "main.h" +#include "vm_alloc.h" + +#include "m68k.h" +#include "memory.h" +#include "readcpu.h" +#endif +#include "newcpu.h" +#include "comptbl.h" +#ifdef UAE +#include "compemu.h" +#else +#include "compiler/compemu.h" +#include "fpu/fpu.h" +#include "fpu/flags.h" +#include "parameters.h" +#endif +#include "verify.h" + +#ifdef UAE +#include "uae/log.h" + +#include "uae/vm.h" +#define VM_PAGE_READ UAE_VM_READ +#define VM_PAGE_WRITE UAE_VM_WRITE +#define VM_PAGE_EXECUTE UAE_VM_EXECUTE +#define VM_MAP_FAILED UAE_VM_ALLOC_FAILED +#define VM_MAP_DEFAULT 1 +#define VM_MAP_32BIT 1 +#define vm_protect(address, size, protect) uae_vm_protect(address, size, protect) +#define vm_release(address, size) uae_vm_free(address, size) + +static inline void *vm_acquire(size_t size, int options = VM_MAP_DEFAULT) +{ + assert(options == (VM_MAP_DEFAULT | VM_MAP_32BIT)); + return uae_vm_alloc(size, UAE_VM_32BIT, UAE_VM_READ_WRITE); +} + +#define UNUSED(x) +#include "uae.h" +#include "uae/log.h" +#define jit_log(format, ...) \ + uae_log("JIT: " format "\n", ##__VA_ARGS__); +#define jit_log2(format, ...) + +#define MEMBaseDiff uae_p32(NATMEM_OFFSET) + +#ifdef NATMEM_OFFSET +#define FIXED_ADDRESSING 1 +#endif + +#define SAHF_SETO_PROFITABLE + +// %%% BRIAN KING WAS HERE %%% +extern bool canbang; + +#include "compemu_prefs.cpp" + +#define uint32 uae_u32 +#define uint8 uae_u8 + +static inline int distrust_check(int value) +{ +#ifdef JIT_ALWAYS_DISTRUST + return 1; +#else + int distrust = value; + return distrust; +#endif +} + +static inline int distrust_byte(void) +{ + return distrust_check(currprefs.comptrustbyte); +} + +static inline int distrust_word(void) +{ + return distrust_check(currprefs.comptrustword); +} + +static inline int distrust_long(void) +{ + return distrust_check(currprefs.comptrustlong); +} + +static inline int distrust_addr(void) +{ + return distrust_check(currprefs.comptrustnaddr); +} + +#else +#define DEBUG 0 +#include "debug.h" + +#define NATMEM_OFFSET MEMBaseDiff +#define canbang 1 +#define op_illg op_illg_1 + +#ifdef WINUAE_ARANYM +void jit_abort(const char *format, ...) +{ + va_list args; + va_start(args, format); + ndebug::pdbvprintf(format, args); + va_end(args); + abort(); +} +#endif + +#if DEBUG +#define PROFILE_COMPILE_TIME 1 +#define PROFILE_UNTRANSLATED_INSNS 1 +#endif +#endif + +# include +# include +# include +# include + +#if defined(CPU_x86_64) && 0 +#define RECORD_REGISTER_USAGE 1 +#endif + +#ifdef JIT_DEBUG +#undef abort +#define abort() do { \ + fprintf(stderr, "Abort in file %s at line %d\n", __FILE__, __LINE__); \ + compiler_dumpstate(); \ + exit(EXIT_FAILURE); \ +} while (0) +#endif + +#ifdef RECORD_REGISTER_USAGE +static uint64 reg_count[16]; +static int reg_count_local[16]; + +static int reg_count_compare(const void *ap, const void *bp) +{ + const int a = *((int *)ap); + const int b = *((int *)bp); + return reg_count[b] - reg_count[a]; +} +#endif + +#ifdef PROFILE_COMPILE_TIME +#include +static uae_u32 compile_count = 0; +static clock_t compile_time = 0; +static clock_t emul_start_time = 0; +static clock_t emul_end_time = 0; +#endif + +#ifdef PROFILE_UNTRANSLATED_INSNS +static const int untranslated_top_ten = 20; +static uae_u32 raw_cputbl_count[65536] = { 0, }; +static uae_u16 opcode_nums[65536]; + + +static int untranslated_compfn(const void *e1, const void *e2) +{ + return raw_cputbl_count[*(const uae_u16 *)e1] < raw_cputbl_count[*(const uae_u16 *)e2]; +} +#endif + +static compop_func *compfunctbl[65536]; +static compop_func *nfcompfunctbl[65536]; +#ifdef NOFLAGS_SUPPORT +static cpuop_func *nfcpufunctbl[65536]; +#endif +uae_u8* comp_pc_p; + +#ifdef UAE +/* defined in uae.h */ +#else +// External variables +// newcpu.cpp +extern int quit_program; +#endif + +// gb-- Extra data for Basilisk II/JIT +#ifdef JIT_DEBUG +static bool JITDebug = false; // Enable runtime disassemblers through mon? +#endif +#if USE_INLINING +#ifdef UAE +#define follow_const_jumps (currprefs.comp_constjump != 0) +#else +static bool follow_const_jumps = true; // Flag: translation through constant jumps +#endif +#else +const bool follow_const_jumps = false; +#endif + +const uae_u32 MIN_CACHE_SIZE = 1024; // Minimal translation cache size (1 MB) +static uae_u32 cache_size = 0; // Size of total cache allocated for compiled blocks +static uae_u32 current_cache_size = 0; // Cache grows upwards: how much has been consumed already +static bool lazy_flush = true; // Flag: lazy translation cache invalidation +#ifdef UAE +#ifdef USE_JIT_FPU +#define avoid_fpu (!currprefs.compfpu) +#else +#define avoid_fpu (true) +#endif +#else +static bool avoid_fpu = true; // Flag: compile FPU instructions ? +#endif +static bool have_cmov = false; // target has CMOV instructions ? +static bool have_rat_stall = true; // target has partial register stalls ? +const bool tune_alignment = true; // Tune code alignments for running CPU ? +const bool tune_nop_fillers = true; // Tune no-op fillers for architecture +static bool setzflg_uses_bsf = false; // setzflg virtual instruction can use native BSF instruction correctly? +static int align_loops = 32; // Align the start of loops +static int align_jumps = 32; // Align the start of jumps +static int optcount[10] = { +#ifdef UAE + 4, // How often a block has to be executed before it is translated +#else + 10, // How often a block has to be executed before it is translated +#endif + 0, // How often to use naive translation + 0, 0, 0, 0, + -1, -1, -1, -1 +}; + +#ifdef UAE +/* FIXME: op_properties is currently in compemu.h */ + +op_properties prop[65536]; + +static inline bool is_const_jump(uae_u32 opcode) +{ + return prop[opcode].is_const_jump != 0; +} +#else +struct op_properties { + uae_u8 use_flags; + uae_u8 set_flags; + uae_u8 is_addx; + uae_u8 cflow; +}; +static op_properties prop[65536]; + +static inline int end_block(uae_u32 opcode) +{ + return (prop[opcode].cflow & fl_end_block); +} + +static inline bool is_const_jump(uae_u32 opcode) +{ + return (prop[opcode].cflow == fl_const_jump); +} + +#if 0 +static inline bool may_trap(uae_u32 opcode) +{ + return (prop[opcode].cflow & fl_trap); +} +#endif + +#endif + +static inline unsigned int cft_map (unsigned int f) +{ +#ifdef UAE + return f; +#else +#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU) + return f; +#else + return ((f >> 8) & 255) | ((f & 255) << 8); +#endif +#endif +} + +uae_u8* start_pc_p; +uae_u32 start_pc; +uae_u32 current_block_pc_p; +static uintptr current_block_start_target; +uae_u32 needed_flags; +static uintptr next_pc_p; +static uintptr taken_pc_p; +static int branch_cc; +static int redo_current_block; + +int segvcount=0; +int soft_flush_count=0; +int hard_flush_count=0; +int checksum_count=0; +static uae_u8* current_compile_p=NULL; +static uae_u8* max_compile_start; +static uae_u8* compiled_code=NULL; +static uae_s32 reg_alloc_run; +const int POPALLSPACE_SIZE = 2048; /* That should be enough space */ +static uae_u8 *popallspace=NULL; + +void* pushall_call_handler=NULL; +static void* popall_do_nothing=NULL; +static void* popall_exec_nostats=NULL; +static void* popall_execute_normal=NULL; +static void* popall_cache_miss=NULL; +static void* popall_recompile_block=NULL; +static void* popall_check_checksum=NULL; + +/* The 68k only ever executes from even addresses. So right now, we + * waste half the entries in this array + * UPDATE: We now use those entries to store the start of the linked + * lists that we maintain for each hash result. + */ +static cacheline cache_tags[TAGSIZE]; +int letit=0; +static blockinfo* hold_bi[MAX_HOLD_BI]; +static blockinfo* active; +static blockinfo* dormant; + +#ifdef NOFLAGS_SUPPORT +/* 68040 */ +extern const struct cputbl op_smalltbl_0_nf[]; +#endif +extern const struct comptbl op_smalltbl_0_comp_nf[]; +extern const struct comptbl op_smalltbl_0_comp_ff[]; + +#ifdef NOFLAGS_SUPPORT +/* 68020 + 68881 */ +extern const struct cputbl op_smalltbl_1_nf[]; +/* 68020 */ +extern const struct cputbl op_smalltbl_2_nf[]; +/* 68010 */ +extern const struct cputbl op_smalltbl_3_nf[]; +/* 68000 */ +extern const struct cputbl op_smalltbl_4_nf[]; +/* 68000 slow but compatible. */ +extern const struct cputbl op_smalltbl_5_nf[]; +#endif + +#ifdef WINUAE_ARANYM +static void flush_icache_hard(int n); +static void flush_icache_lazy(int n); +static void flush_icache_none(int n); +void (*flush_icache)(int n) = flush_icache_none; +#endif + +static bigstate live; +static smallstate empty_ss; +static smallstate default_ss; +static int optlev; + +static int writereg(int r, int size); +static void unlock2(int r); +static void setlock(int r); +static int readreg_specific(int r, int size, int spec); +static int writereg_specific(int r, int size, int spec); +static void prepare_for_call_1(void); +static void prepare_for_call_2(void); +static void align_target(uae_u32 a); + +static void inline flush_cpu_icache(void *from, void *to); +static void inline write_jmp_target(uae_u32 *jmpaddr, cpuop_func* a); +static void inline emit_jmp_target(uae_u32 a); + +uae_u32 m68k_pc_offset; + +/* Some arithmetic operations can be optimized away if the operands + * are known to be constant. But that's only a good idea when the + * side effects they would have on the flags are not important. This + * variable indicates whether we need the side effects or not + */ +uae_u32 needflags=0; + +/* Flag handling is complicated. + * + * x86 instructions create flags, which quite often are exactly what we + * want. So at times, the "68k" flags are actually in the x86 flags. + * + * Then again, sometimes we do x86 instructions that clobber the x86 + * flags, but don't represent a corresponding m68k instruction. In that + * case, we have to save them. + * + * We used to save them to the stack, but now store them back directly + * into the regflags.cznv of the traditional emulation. Thus some odd + * names. + * + * So flags can be in either of two places (used to be three; boy were + * things complicated back then!); And either place can contain either + * valid flags or invalid trash (and on the stack, there was also the + * option of "nothing at all", now gone). A couple of variables keep + * track of the respective states. + * + * To make things worse, we might or might not be interested in the flags. + * by default, we are, but a call to dont_care_flags can change that + * until the next call to live_flags. If we are not, pretty much whatever + * is in the register and/or the native flags is seen as valid. + */ + +static inline blockinfo* get_blockinfo(uae_u32 cl) +{ + return cache_tags[cl+1].bi; +} + +static inline blockinfo* get_blockinfo_addr(void* addr) +{ + blockinfo* bi=get_blockinfo(cacheline(addr)); + + while (bi) { + if (bi->pc_p==addr) + return bi; + bi=bi->next_same_cl; + } + return NULL; +} + +#ifdef WINUAE_ARANYM +/******************************************************************* + * Disassembler support * + *******************************************************************/ + +#define TARGET_M68K 0 +#define TARGET_POWERPC 1 +#define TARGET_X86 2 +#define TARGET_X86_64 3 +#define TARGET_ARM 4 +#if defined(CPU_i386) +#define TARGET_NATIVE TARGET_X86 +#endif +#if defined(CPU_powerpc) +#define TARGET_NATIVE TARGET_POWERPC +#endif +#if defined(CPU_x86_64) +#define TARGET_NATIVE TARGET_X86_64 +#endif +#if defined(CPU_arm) +#define TARGET_NATIVE TARGET_ARM +#endif +#include "disasm-glue.h" + +#ifdef JIT_DEBUG +static void disasm_block(int disasm_target, const uint8 *start, size_t length) +{ + UNUSED(start); + UNUSED(length); + switch (disasm_target) + { + case TARGET_M68K: +#if defined(HAVE_DISASM_M68K) + { + char buf[256]; + + disasm_info.memory_vma = ((memptr)((uintptr_t)(start) - MEMBaseDiff)); + while (length > 0) + { + int isize = m68k_disasm_to_buf(&disasm_info, buf); + bug("%s", buf); + if (isize < 0) + break; + if ((uintptr)isize > length) + break; + length -= isize; + } + } +#endif + break; + case TARGET_X86: + case TARGET_X86_64: +#if defined(HAVE_DISASM_X86) + { + const uint8 *end = start + length; + char buf[256]; + + while (start < end) + { + start = x86_disasm(start, buf); + bug("%s", buf); + } + } +#endif + break; + case TARGET_ARM: +#if defined(HAVE_DISASM_ARM) + { + const uint8 *end = start + length; + char buf[256]; + + while (start < end) + { + start = arm_disasm(start, buf); + bug("%s", buf); + } + } +#endif + break; + } +} + +static inline void disasm_native_block(const uint8 *start, size_t length) +{ + disasm_block(TARGET_NATIVE, start, length); +} + +static inline void disasm_m68k_block(const uint8 *start, size_t length) +{ + disasm_block(TARGET_M68K, start, length); +} +#endif +#endif + + +/******************************************************************* + * All sorts of list related functions for all of the lists * + *******************************************************************/ + +static inline void remove_from_cl_list(blockinfo* bi) +{ + uae_u32 cl=cacheline(bi->pc_p); + + if (bi->prev_same_cl_p) + *(bi->prev_same_cl_p)=bi->next_same_cl; + if (bi->next_same_cl) + bi->next_same_cl->prev_same_cl_p=bi->prev_same_cl_p; + if (cache_tags[cl+1].bi) + cache_tags[cl].handler=cache_tags[cl+1].bi->handler_to_use; + else + cache_tags[cl].handler=(cpuop_func*)popall_execute_normal; +} + +static inline void remove_from_list(blockinfo* bi) +{ + if (bi->prev_p) + *(bi->prev_p)=bi->next; + if (bi->next) + bi->next->prev_p=bi->prev_p; +} + +#if 0 +static inline void remove_from_lists(blockinfo* bi) +{ + remove_from_list(bi); + remove_from_cl_list(bi); +} +#endif + +static inline void add_to_cl_list(blockinfo* bi) +{ + uae_u32 cl=cacheline(bi->pc_p); + + if (cache_tags[cl+1].bi) + cache_tags[cl+1].bi->prev_same_cl_p=&(bi->next_same_cl); + bi->next_same_cl=cache_tags[cl+1].bi; + + cache_tags[cl+1].bi=bi; + bi->prev_same_cl_p=&(cache_tags[cl+1].bi); + + cache_tags[cl].handler=bi->handler_to_use; +} + +static inline void raise_in_cl_list(blockinfo* bi) +{ + remove_from_cl_list(bi); + add_to_cl_list(bi); +} + +static inline void add_to_active(blockinfo* bi) +{ + if (active) + active->prev_p=&(bi->next); + bi->next=active; + + active=bi; + bi->prev_p=&active; +} + +static inline void add_to_dormant(blockinfo* bi) +{ + if (dormant) + dormant->prev_p=&(bi->next); + bi->next=dormant; + + dormant=bi; + bi->prev_p=&dormant; +} + +static inline void remove_dep(dependency* d) +{ + if (d->prev_p) + *(d->prev_p)=d->next; + if (d->next) + d->next->prev_p=d->prev_p; + d->prev_p=NULL; + d->next=NULL; +} + +/* This block's code is about to be thrown away, so it no longer + depends on anything else */ +static inline void remove_deps(blockinfo* bi) +{ + remove_dep(&(bi->dep[0])); + remove_dep(&(bi->dep[1])); +} + +static inline void adjust_jmpdep(dependency* d, cpuop_func* a) +{ + write_jmp_target(d->jmp_off, a); +} + +/******************************************************************** + * Soft flush handling support functions * + ********************************************************************/ + +static inline void set_dhtu(blockinfo* bi, cpuop_func *dh) +{ + jit_log2("bi is %p",bi); + if (dh!=bi->direct_handler_to_use) { + dependency* x=bi->deplist; + jit_log2("bi->deplist=%p",bi->deplist); + while (x) { + jit_log2("x is %p",x); + jit_log2("x->next is %p",x->next); + jit_log2("x->prev_p is %p",x->prev_p); + + if (x->jmp_off) { + adjust_jmpdep(x,dh); + } + x=x->next; + } + bi->direct_handler_to_use=dh; + } +} + +static inline void invalidate_block(blockinfo* bi) +{ + int i; + + bi->optlevel=0; + bi->count=optcount[0]-1; + bi->handler=NULL; + bi->handler_to_use=(cpuop_func*)popall_execute_normal; + bi->direct_handler=NULL; + set_dhtu(bi,bi->direct_pen); + bi->needed_flags=0xff; + bi->status=BI_INVALID; + for (i=0;i<2;i++) { + bi->dep[i].jmp_off=NULL; + bi->dep[i].target=NULL; + } + remove_deps(bi); +} + +static inline void create_jmpdep(blockinfo* bi, int i, uae_u32* jmpaddr, uae_u32 target) +{ + blockinfo* tbi=get_blockinfo_addr((void*)(uintptr)target); + + Dif(!tbi) { + jit_abort("Could not create jmpdep!"); + } + bi->dep[i].jmp_off=jmpaddr; + bi->dep[i].source=bi; + bi->dep[i].target=tbi; + bi->dep[i].next=tbi->deplist; + if (bi->dep[i].next) + bi->dep[i].next->prev_p=&(bi->dep[i].next); + bi->dep[i].prev_p=&(tbi->deplist); + tbi->deplist=&(bi->dep[i]); +} + +static inline void block_need_recompile(blockinfo * bi) +{ + uae_u32 cl = cacheline(bi->pc_p); + + set_dhtu(bi, bi->direct_pen); + bi->direct_handler = bi->direct_pen; + + bi->handler_to_use = (cpuop_func *)popall_execute_normal; + bi->handler = (cpuop_func *)popall_execute_normal; + if (bi == cache_tags[cl + 1].bi) + cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; + bi->status = BI_NEED_RECOMP; +} + +#if USE_MATCH +static inline void mark_callers_recompile(blockinfo * bi) +{ + dependency *x = bi->deplist; + + while (x) { + dependency *next = x->next; /* This disappears when we mark for + * recompilation and thus remove the + * blocks from the lists */ + if (x->jmp_off) { + blockinfo *cbi = x->source; + + Dif(cbi->status == BI_INVALID) { + jit_log("invalid block in dependency list"); // FIXME? + // abort(); + } + if (cbi->status == BI_ACTIVE || cbi->status == BI_NEED_CHECK) { + block_need_recompile(cbi); + mark_callers_recompile(cbi); + } + else if (cbi->status == BI_COMPILING) { + redo_current_block = 1; + } + else if (cbi->status == BI_NEED_RECOMP) { + /* nothing */ + } + else { + jit_log2("Status %d in mark_callers",cbi->status); // FIXME? + } + } + x = next; + } +} +#endif + +static inline blockinfo* get_blockinfo_addr_new(void* addr, int /* setstate */) +{ + blockinfo* bi=get_blockinfo_addr(addr); + int i; + + if (!bi) { + for (i=0;ipc_p=(uae_u8*)addr; + invalidate_block(bi); + add_to_active(bi); + add_to_cl_list(bi); + + } + } + } + if (!bi) { + jit_abort("Looking for blockinfo, can't find free one"); + } + return bi; +} + +static void prepare_block(blockinfo* bi); + +/* Managment of blockinfos. + + A blockinfo struct is allocated whenever a new block has to be + compiled. If the list of free blockinfos is empty, we allocate a new + pool of blockinfos and link the newly created blockinfos altogether + into the list of free blockinfos. Otherwise, we simply pop a structure + of the free list. + + Blockinfo are lazily deallocated, i.e. chained altogether in the + list of free blockinfos whenvever a translation cache flush (hard or + soft) request occurs. +*/ + +template< class T > +class LazyBlockAllocator +{ + enum { + kPoolSize = 1 + (16384 - sizeof(T) - sizeof(void *)) / sizeof(T) + }; + struct Pool { + T chunk[kPoolSize]; + Pool * next; + }; + Pool * mPools; + T * mChunks; +public: + LazyBlockAllocator() : mPools(0), mChunks(0) { } +#ifdef UAE +#else + ~LazyBlockAllocator(); +#endif + T * acquire(); + void release(T * const); +}; + +#ifdef UAE +/* uae_vm_release may do logging, which isn't safe to do when the application + * is shutting down. Better to release memory manually with a function call + * to a release_all method on shutdown, or even simpler, just let the OS + * handle it (we're shutting down anyway). */ +#else +template< class T > +LazyBlockAllocator::~LazyBlockAllocator() +{ + Pool * currentPool = mPools; + while (currentPool) { + Pool * deadPool = currentPool; + currentPool = currentPool->next; + vm_release(deadPool, sizeof(Pool)); + } +} +#endif + +template< class T > +T * LazyBlockAllocator::acquire() +{ + if (!mChunks) { + // There is no chunk left, allocate a new pool and link the + // chunks into the free list + Pool * newPool = (Pool *)vm_acquire(sizeof(Pool), VM_MAP_DEFAULT | VM_MAP_32BIT); + if (newPool == VM_MAP_FAILED) { + jit_abort("Could not allocate block pool!"); + } + for (T * chunk = &newPool->chunk[0]; chunk < &newPool->chunk[kPoolSize]; chunk++) { + chunk->next = mChunks; + mChunks = chunk; + } + newPool->next = mPools; + mPools = newPool; + } + T * chunk = mChunks; + mChunks = chunk->next; + return chunk; +} + +template< class T > +void LazyBlockAllocator::release(T * const chunk) +{ + chunk->next = mChunks; + mChunks = chunk; +} + +template< class T > +class HardBlockAllocator +{ +public: + T * acquire() { + T * data = (T *)current_compile_p; + current_compile_p += sizeof(T); + return data; + } + + void release(T * const ) { + // Deallocated on invalidation + } +}; + +#if USE_SEPARATE_BIA +static LazyBlockAllocator BlockInfoAllocator; +static LazyBlockAllocator ChecksumInfoAllocator; +#else +static HardBlockAllocator BlockInfoAllocator; +static HardBlockAllocator ChecksumInfoAllocator; +#endif + +static inline checksum_info *alloc_checksum_info(void) +{ + checksum_info *csi = ChecksumInfoAllocator.acquire(); + csi->next = NULL; + return csi; +} + +static inline void free_checksum_info(checksum_info *csi) +{ + csi->next = NULL; + ChecksumInfoAllocator.release(csi); +} + +static inline void free_checksum_info_chain(checksum_info *csi) +{ + while (csi != NULL) { + checksum_info *csi2 = csi->next; + free_checksum_info(csi); + csi = csi2; + } +} + +static inline blockinfo *alloc_blockinfo(void) +{ + blockinfo *bi = BlockInfoAllocator.acquire(); +#if USE_CHECKSUM_INFO + bi->csi = NULL; +#endif + return bi; +} + +static inline void free_blockinfo(blockinfo *bi) +{ +#if USE_CHECKSUM_INFO + free_checksum_info_chain(bi->csi); + bi->csi = NULL; +#endif + BlockInfoAllocator.release(bi); +} + +static inline void alloc_blockinfos(void) +{ + int i; + blockinfo* bi; + + for (i=0;i>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v<<24)&0xff000000); +#endif +} + +void set_target(uae_u8* t) +{ + target=t; +} + +static inline uae_u8* get_target_noopt(void) +{ + return target; +} + +inline uae_u8* get_target(void) +{ + return get_target_noopt(); +} + +/******************************************************************** + * New version of data buffer: interleave data and code * + ********************************************************************/ +#if defined(USE_DATA_BUFFER) + +#define DATA_BUFFER_SIZE 1024 // Enlarge POPALLSPACE_SIZE if this value is greater than 768 +#define DATA_BUFFER_MAXOFFSET 4096 - 32 // max range between emit of data and use of data +static uae_u8* data_writepos = 0; +static uae_u8* data_endpos = 0; +#if DEBUG +static long data_wasted = 0; +#endif + +static inline void compemu_raw_branch(IMM d); + +static inline void data_check_end(long n, long codesize) +{ + if(data_writepos + n > data_endpos || get_target_noopt() + codesize - data_writepos > DATA_BUFFER_MAXOFFSET) + { + // Start new buffer +#if DEBUG + if(data_writepos < data_endpos) + data_wasted += data_endpos - data_writepos; +#endif + compemu_raw_branch(DATA_BUFFER_SIZE); + data_writepos = get_target_noopt(); + data_endpos = data_writepos + DATA_BUFFER_SIZE; + set_target(get_target_noopt() + DATA_BUFFER_SIZE); + } +} + +static inline long data_word_offs(uae_u16 x) +{ + data_check_end(4, 4); +#ifdef WORDS_BIGENDIAN + *((uae_u16*)data_writepos)=x; + data_writepos += 2; + *((uae_u16*)data_writepos)=0; + data_writepos += 2; +#else + *((uae_u32*)data_writepos)=x; + data_writepos += 4; +#endif + return (long)data_writepos - (long)get_target_noopt() - 12; +} + +static inline long data_long(uae_u32 x, long codesize) +{ + data_check_end(4, codesize); + *((uae_u32*)data_writepos)=x; + data_writepos += 4; + return (long)data_writepos - 4; +} + +static inline long data_long_offs(uae_u32 x) +{ + data_check_end(4, 4); + *((uae_u32*)data_writepos)=x; + data_writepos += 4; + return (long)data_writepos - (long)get_target_noopt() - 12; +} + +static inline long get_data_offset(long t) +{ + return t - (long)get_target_noopt() - 8; +} + +static inline void reset_data_buffer(void) +{ + data_writepos = 0; + data_endpos = 0; +} + +#endif +/******************************************************************** + * Getting the information about the target CPU * + ********************************************************************/ + +#if defined(CPU_arm) +#include "codegen_arm.cpp" +#endif +#if defined(CPU_i386) || defined(CPU_x86_64) +#include "codegen_x86.cpp" +#endif + + +/******************************************************************** + * Flags status handling. EMIT TIME! * + ********************************************************************/ + +static void bt_l_ri_noclobber(RR4 r, IMM i); + +static void make_flags_live_internal(void) +{ + if (live.flags_in_flags==VALID) + return; + Dif (live.flags_on_stack==TRASH) { + jit_abort("Want flags, got something on stack, but it is TRASH"); + } + if (live.flags_on_stack==VALID) { + int tmp; + tmp=readreg_specific(FLAGTMP,4,FLAG_NREG2); + raw_reg_to_flags(tmp); + unlock2(tmp); + + live.flags_in_flags=VALID; + return; + } + jit_abort("Huh? live.flags_in_flags=%d, live.flags_on_stack=%d, but need to make live", + live.flags_in_flags,live.flags_on_stack); +} + +static void flags_to_stack(void) +{ + if (live.flags_on_stack==VALID) + return; + if (!live.flags_are_important) { + live.flags_on_stack=VALID; + return; + } + Dif (live.flags_in_flags!=VALID) + jit_abort("flags_to_stack != VALID"); + else { + int tmp; + tmp=writereg_specific(FLAGTMP,4,FLAG_NREG1); + raw_flags_to_reg(tmp); + unlock2(tmp); + } + live.flags_on_stack=VALID; +} + +static inline void clobber_flags(void) +{ + if (live.flags_in_flags==VALID && live.flags_on_stack!=VALID) + flags_to_stack(); + live.flags_in_flags=TRASH; +} + +/* Prepare for leaving the compiled stuff */ +static inline void flush_flags(void) +{ + flags_to_stack(); + return; +} + +int touchcnt; + +/******************************************************************** + * Partial register flushing for optimized calls * + ********************************************************************/ + +struct regusage { + uae_u16 rmask; + uae_u16 wmask; +}; + +#if 0 +static inline void ru_set(uae_u16 *mask, int reg) +{ +#if USE_OPTIMIZED_CALLS + *mask |= 1 << reg; +#else + UNUSED(mask); + UNUSED(reg); +#endif +} + +static inline bool ru_get(const uae_u16 *mask, int reg) +{ +#if USE_OPTIMIZED_CALLS + return (*mask & (1 << reg)); +#else + UNUSED(mask); + UNUSED(reg); + /* Default: instruction reads & write to register */ + return true; +#endif +} + +static inline void ru_set_read(regusage *ru, int reg) +{ + ru_set(&ru->rmask, reg); +} + +static inline void ru_set_write(regusage *ru, int reg) +{ + ru_set(&ru->wmask, reg); +} + +static inline bool ru_read_p(const regusage *ru, int reg) +{ + return ru_get(&ru->rmask, reg); +} + +static inline bool ru_write_p(const regusage *ru, int reg) +{ + return ru_get(&ru->wmask, reg); +} + +static void ru_fill_ea(regusage *ru, int reg, amodes mode, + wordsizes size, int write_mode) +{ + switch (mode) { + case Areg: + reg += 8; + /* fall through */ + case Dreg: + ru_set(write_mode ? &ru->wmask : &ru->rmask, reg); + break; + case Ad16: + /* skip displacment */ + m68k_pc_offset += 2; + case Aind: + case Aipi: + case Apdi: + ru_set_read(ru, reg+8); + break; + case Ad8r: + ru_set_read(ru, reg+8); + /* fall through */ + case PC8r: { + uae_u16 dp = comp_get_iword((m68k_pc_offset+=2)-2); + reg = (dp >> 12) & 15; + ru_set_read(ru, reg); + if (dp & 0x100) + m68k_pc_offset += (((dp & 0x30) >> 3) & 7) + ((dp & 3) * 2); + break; + } + case PC16: + case absw: + case imm0: + case imm1: + m68k_pc_offset += 2; + break; + case absl: + case imm2: + m68k_pc_offset += 4; + break; + case immi: + m68k_pc_offset += (size == sz_long) ? 4 : 2; + break; + } +} + +/* TODO: split into a static initialization part and a dynamic one + (instructions depending on extension words) */ + +static void ru_fill(regusage *ru, uae_u32 opcode) +{ + m68k_pc_offset += 2; + + /* Default: no register is used or written to */ + ru->rmask = 0; + ru->wmask = 0; + + uae_u32 real_opcode = cft_map(opcode); + struct instr *dp = &table68k[real_opcode]; + + bool rw_dest = true; + bool handled = false; + + /* Handle some instructions specifically */ + uae_u16 ext; + switch (dp->mnemo) { + case i_BFCHG: + case i_BFCLR: + case i_BFEXTS: + case i_BFEXTU: + case i_BFFFO: + case i_BFINS: + case i_BFSET: + case i_BFTST: + ext = comp_get_iword((m68k_pc_offset+=2)-2); + if (ext & 0x800) ru_set_read(ru, (ext >> 6) & 7); + if (ext & 0x020) ru_set_read(ru, ext & 7); + ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1); + if (dp->dmode == Dreg) + ru_set_read(ru, dp->dreg); + switch (dp->mnemo) { + case i_BFEXTS: + case i_BFEXTU: + case i_BFFFO: + ru_set_write(ru, (ext >> 12) & 7); + break; + case i_BFINS: + ru_set_read(ru, (ext >> 12) & 7); + /* fall through */ + case i_BFCHG: + case i_BFCLR: + case i_BSET: + if (dp->dmode == Dreg) + ru_set_write(ru, dp->dreg); + break; + } + handled = true; + rw_dest = false; + break; + + case i_BTST: + rw_dest = false; + break; + + case i_CAS: + { + ext = comp_get_iword((m68k_pc_offset+=2)-2); + int Du = ext & 7; + ru_set_read(ru, Du); + int Dc = (ext >> 6) & 7; + ru_set_read(ru, Dc); + ru_set_write(ru, Dc); + break; + } + case i_CAS2: + { + int Dc1, Dc2, Du1, Du2, Rn1, Rn2; + ext = comp_get_iword((m68k_pc_offset+=2)-2); + Rn1 = (ext >> 12) & 15; + Du1 = (ext >> 6) & 7; + Dc1 = ext & 7; + ru_set_read(ru, Rn1); + ru_set_read(ru, Du1); + ru_set_read(ru, Dc1); + ru_set_write(ru, Dc1); + ext = comp_get_iword((m68k_pc_offset+=2)-2); + Rn2 = (ext >> 12) & 15; + Du2 = (ext >> 6) & 7; + Dc2 = ext & 7; + ru_set_read(ru, Rn2); + ru_set_read(ru, Du2); + ru_set_write(ru, Dc2); + break; + } + case i_DIVL: case i_MULL: + m68k_pc_offset += 2; + break; + case i_LEA: + case i_MOVE: case i_MOVEA: case i_MOVE16: + rw_dest = false; + break; + case i_PACK: case i_UNPK: + rw_dest = false; + m68k_pc_offset += 2; + break; + case i_TRAPcc: + m68k_pc_offset += (dp->size == sz_long) ? 4 : 2; + break; + case i_RTR: + /* do nothing, just for coverage debugging */ + break; + /* TODO: handle EXG instruction */ + } + + /* Handle A-Traps better */ + if ((real_opcode & 0xf000) == 0xa000) { + handled = true; + } + + /* Handle EmulOps better */ + if ((real_opcode & 0xff00) == 0x7100) { + handled = true; + ru->rmask = 0xffff; + ru->wmask = 0; + } + + if (dp->suse && !handled) + ru_fill_ea(ru, dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); + + if (dp->duse && !handled) + ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1); + + if (rw_dest) + ru->rmask |= ru->wmask; + + handled = handled || dp->suse || dp->duse; + + /* Mark all registers as used/written if the instruction may trap */ + if (may_trap(opcode)) { + handled = true; + ru->rmask = 0xffff; + ru->wmask = 0xffff; + } + + if (!handled) { + jit_abort("ru_fill: %04x = { %04x, %04x }", + real_opcode, ru->rmask, ru->wmask); + } +} +#endif + +/******************************************************************** + * register allocation per block logging * + ********************************************************************/ + +static uae_s8 vstate[VREGS]; +static uae_s8 vwritten[VREGS]; +static uae_s8 nstate[N_REGS]; + +#define L_UNKNOWN -127 +#define L_UNAVAIL -1 +#define L_NEEDED -2 +#define L_UNNEEDED -3 + +#if USE_MATCH +static inline void big_to_small_state(bigstate * /* b */, smallstate * s) +{ + int i; + + for (i = 0; i < VREGS; i++) + s->virt[i] = vstate[i]; + for (i = 0; i < N_REGS; i++) + s->nat[i] = nstate[i]; +} + +static inline int callers_need_recompile(bigstate * /* b */, smallstate * s) +{ + int i; + int reverse = 0; + + for (i = 0; i < VREGS; i++) { + if (vstate[i] != L_UNNEEDED && s->virt[i] == L_UNNEEDED) + return 1; + if (vstate[i] == L_UNNEEDED && s->virt[i] != L_UNNEEDED) + reverse++; + } + for (i = 0; i < N_REGS; i++) { + if (nstate[i] >= 0 && nstate[i] != s->nat[i]) + return 1; + if (nstate[i] < 0 && s->nat[i] >= 0) + reverse++; + } + if (reverse >= 2 && USE_MATCH) + return 1; /* In this case, it might be worth recompiling the + * callers */ + return 0; +} +#endif + +static inline void log_startblock(void) +{ + int i; + + for (i = 0; i < VREGS; i++) { + vstate[i] = L_UNKNOWN; + vwritten[i] = 0; + } + for (i = 0; i < N_REGS; i++) + nstate[i] = L_UNKNOWN; +} + +/* Using an n-reg for a temp variable */ +static inline void log_isused(int n) +{ + if (nstate[n] == L_UNKNOWN) + nstate[n] = L_UNAVAIL; +} + +static inline void log_visused(int r) +{ + if (vstate[r] == L_UNKNOWN) + vstate[r] = L_NEEDED; +} + +static inline void do_load_reg(int n, int r) +{ + if (r == FLAGTMP) + raw_load_flagreg(n, r); + else if (r == FLAGX) + raw_load_flagx(n, r); + else + compemu_raw_mov_l_rm(n, (uintptr) live.state[r].mem); +} + +#if 0 +static inline void check_load_reg(int n, int r) +{ + compemu_raw_mov_l_rm(n, (uintptr) live.state[r].mem); +} +#endif + +static inline void log_vwrite(int r) +{ + vwritten[r] = 1; +} + +/* Using an n-reg to hold a v-reg */ +static inline void log_isreg(int n, int r) +{ + if (nstate[n] == L_UNKNOWN && r < 16 && !vwritten[r] && USE_MATCH) + nstate[n] = r; + else { + do_load_reg(n, r); + if (nstate[n] == L_UNKNOWN) + nstate[n] = L_UNAVAIL; + } + if (vstate[r] == L_UNKNOWN) + vstate[r] = L_NEEDED; +} + +static inline void log_clobberreg(int r) +{ + if (vstate[r] == L_UNKNOWN) + vstate[r] = L_UNNEEDED; +} + +/* This ends all possibility of clever register allocation */ + +static inline void log_flush(void) +{ + int i; + + for (i = 0; i < VREGS; i++) + if (vstate[i] == L_UNKNOWN) + vstate[i] = L_NEEDED; + for (i = 0; i < N_REGS; i++) + if (nstate[i] == L_UNKNOWN) + nstate[i] = L_UNAVAIL; +} + +static inline void log_dump(void) +{ + int i; + + return; + + jit_log("----------------------"); + for (i = 0; i < N_REGS; i++) { + switch (nstate[i]) { + case L_UNKNOWN: + jit_log("Nat %d : UNKNOWN", i); + break; + case L_UNAVAIL: + jit_log("Nat %d : UNAVAIL", i); + break; + default: + jit_log("Nat %d : %d", i, nstate[i]); + break; + } + } + for (i = 0; i < VREGS; i++) { + if (vstate[i] == L_UNNEEDED) { + jit_log("Virt %d: UNNEEDED", i); + } + } +} + +/******************************************************************** + * register status handling. EMIT TIME! * + ********************************************************************/ + +static inline void set_status(int r, int status) +{ + if (status == ISCONST) + log_clobberreg(r); + live.state[r].status=status; +} + +static inline int isinreg(int r) +{ + return live.state[r].status==CLEAN || live.state[r].status==DIRTY; +} + +static inline void adjust_nreg(int r, uae_u32 val) +{ + if (!val) + return; + compemu_raw_lea_l_brr(r,r,val); +} + +static void tomem(int r) +{ + int rr=live.state[r].realreg; + + if (isinreg(r)) { + if (live.state[r].val && live.nat[rr].nholds==1 + && !live.nat[rr].locked) { + jit_log2("RemovingA offset %x from reg %d (%d) at %p", live.state[r].val,r,rr,target); + adjust_nreg(rr,live.state[r].val); + live.state[r].val=0; + live.state[r].dirtysize=4; + set_status(r,DIRTY); + } + } + + if (live.state[r].status==DIRTY) { + switch (live.state[r].dirtysize) { + case 1: compemu_raw_mov_b_mr((uintptr)live.state[r].mem,rr); break; + case 2: compemu_raw_mov_w_mr((uintptr)live.state[r].mem,rr); break; + case 4: compemu_raw_mov_l_mr((uintptr)live.state[r].mem,rr); break; + default: abort(); + } + log_vwrite(r); + set_status(r,CLEAN); + live.state[r].dirtysize=0; + } +} + +static inline int isconst(int r) +{ + return live.state[r].status==ISCONST; +} + +int is_const(int r) +{ + return isconst(r); +} + +static inline void writeback_const(int r) +{ + if (!isconst(r)) + return; + Dif (live.state[r].needflush==NF_HANDLER) { + jit_abort("Trying to write back constant NF_HANDLER!"); + } + + compemu_raw_mov_l_mi((uintptr)live.state[r].mem,live.state[r].val); + log_vwrite(r); + live.state[r].val=0; + set_status(r,INMEM); +} + +static inline void tomem_c(int r) +{ + if (isconst(r)) { + writeback_const(r); + } + else + tomem(r); +} + +static void evict(int r) +{ + int rr; + + if (!isinreg(r)) + return; + tomem(r); + rr=live.state[r].realreg; + + Dif (live.nat[rr].locked && + live.nat[rr].nholds==1) { + jit_abort("register %d in nreg %d is locked!",r,live.state[r].realreg); + } + + live.nat[rr].nholds--; + if (live.nat[rr].nholds!=live.state[r].realind) { /* Was not last */ + int topreg=live.nat[rr].holds[live.nat[rr].nholds]; + int thisind=live.state[r].realind; + + live.nat[rr].holds[thisind]=topreg; + live.state[topreg].realind=thisind; + } + live.state[r].realreg=-1; + set_status(r,INMEM); +} + +static inline void free_nreg(int r) +{ + int i=live.nat[r].nholds; + + while (i) { + int vr; + + --i; + vr=live.nat[r].holds[i]; + evict(vr); + } + Dif (live.nat[r].nholds!=0) { + jit_abort("Failed to free nreg %d, nholds is %d",r,live.nat[r].nholds); + } +} + +/* Use with care! */ +static inline void isclean(int r) +{ + if (!isinreg(r)) + return; + live.state[r].validsize=4; + live.state[r].dirtysize=0; + live.state[r].val=0; + set_status(r,CLEAN); +} + +static inline void disassociate(int r) +{ + isclean(r); + evict(r); +} + +static inline void set_const(int r, uae_u32 val) +{ + disassociate(r); + live.state[r].val=val; + set_status(r,ISCONST); +} + +static inline uae_u32 get_offset(int r) +{ + return live.state[r].val; +} + +static int alloc_reg_hinted(int r, int size, int willclobber, int hint) +{ + int bestreg; + uae_s32 when; + int i; + uae_s32 badness=0; /* to shut up gcc */ + bestreg=-1; + when=2000000000; + + /* XXX use a regalloc_order table? */ + for (i=0;i0) { + free_nreg(bestreg); + } + if (isinreg(r)) { + int rr=live.state[r].realreg; + /* This will happen if we read a partially dirty register at a + bigger size */ + Dif (willclobber || live.state[r].validsize>=size) + jit_abort("willclobber || live.state[r].validsize>=size"); + Dif (live.nat[rr].nholds!=1) + jit_abort("live.nat[rr].nholds!=1"); + if (size==4 && live.state[r].validsize==2) { + log_isused(bestreg); + log_visused(r); + compemu_raw_mov_l_rm(bestreg,(uintptr)live.state[r].mem); + compemu_raw_bswap_32(bestreg); + compemu_raw_zero_extend_16_rr(rr,rr); + compemu_raw_zero_extend_16_rr(bestreg,bestreg); + compemu_raw_bswap_32(bestreg); + compemu_raw_lea_l_rr_indexed(rr, rr, bestreg, 1); + live.state[r].validsize=4; + live.nat[rr].touched=touchcnt++; + return rr; + } + if (live.state[r].validsize==1) { + /* Nothing yet */ + } + evict(r); + } + + if (!willclobber) { + if (live.state[r].status!=UNDEF) { + if (isconst(r)) { + compemu_raw_mov_l_ri(bestreg,live.state[r].val); + live.state[r].val=0; + live.state[r].dirtysize=4; + set_status(r,DIRTY); + log_isused(bestreg); + } + else { + log_isreg(bestreg, r); /* This will also load it! */ + live.state[r].dirtysize=0; + set_status(r,CLEAN); + } + } + else { + live.state[r].val=0; + live.state[r].dirtysize=0; + set_status(r,CLEAN); + log_isused(bestreg); + } + live.state[r].validsize=4; + } + else { /* this is the easiest way, but not optimal. FIXME! */ + /* Now it's trickier, but hopefully still OK */ + if (!isconst(r) || size==4) { + live.state[r].validsize=size; + live.state[r].dirtysize=size; + live.state[r].val=0; + set_status(r,DIRTY); + if (size == 4) { + log_clobberreg(r); + log_isused(bestreg); + } + else { + log_visused(r); + log_isused(bestreg); + } + } + else { + if (live.state[r].status!=UNDEF) + compemu_raw_mov_l_ri(bestreg,live.state[r].val); + live.state[r].val=0; + live.state[r].validsize=4; + live.state[r].dirtysize=4; + set_status(r,DIRTY); + log_isused(bestreg); + } + } + live.state[r].realreg=bestreg; + live.state[r].realind=live.nat[bestreg].nholds; + live.nat[bestreg].touched=touchcnt++; + live.nat[bestreg].holds[live.nat[bestreg].nholds]=r; + live.nat[bestreg].nholds++; + + return bestreg; +} + +/* +static int alloc_reg(int r, int size, int willclobber) +{ + return alloc_reg_hinted(r,size,willclobber,-1); +} +*/ + +static void unlock2(int r) +{ + Dif (!live.nat[r].locked) + jit_abort("unlock2 %d not locked", r); + live.nat[r].locked--; +} + +static void setlock(int r) +{ + live.nat[r].locked++; +} + + +static void mov_nregs(int d, int s) +{ + int nd=live.nat[d].nholds; + int i; + + if (s==d) + return; + + if (nd>0) + free_nreg(d); + + log_isused(d); + compemu_raw_mov_l_rr(d,s); + + for (i=0;i=size) { + n=live.state[r].realreg; + switch(size) { + case 1: + if (live.nat[n].canbyte || spec>=0) { + answer=n; + } + break; + case 2: + if (live.nat[n].canword || spec>=0) { + answer=n; + } + break; + case 4: + answer=n; + break; + default: abort(); + } + if (answer<0) + evict(r); + } + /* either the value was in memory to start with, or it was evicted and + is in memory now */ + if (answer<0) { + answer=alloc_reg_hinted(r,spec>=0?4:size,0,spec); + } + + if (spec>=0 && spec!=answer) { + /* Too bad */ + mov_nregs(spec,answer); + answer=spec; + } + live.nat[answer].locked++; + live.nat[answer].touched=touchcnt++; + return answer; +} + + + +static int readreg(int r, int size) +{ + return readreg_general(r,size,-1,0); +} + +static int readreg_specific(int r, int size, int spec) +{ + return readreg_general(r,size,spec,0); +} + +static int readreg_offset(int r, int size) +{ + return readreg_general(r,size,-1,1); +} + +/* writereg_general(r, size, spec) + * + * INPUT + * - r : mid-layer register + * - size : requested size (1/2/4) + * - spec : -1 if find or make a register free, otherwise specifies + * the physical register to use in any case + * + * OUTPUT + * - hard (physical, x86 here) register allocated to virtual register r + */ +static inline int writereg_general(int r, int size, int spec) +{ + int n; + int answer=-1; + + record_register(r); + if (size<4) { + remove_offset(r,spec); + } + + make_exclusive(r,size,spec); + if (isinreg(r)) { + int nvsize=size>live.state[r].validsize?size:live.state[r].validsize; + int ndsize=size>live.state[r].dirtysize?size:live.state[r].dirtysize; + n=live.state[r].realreg; + + Dif (live.nat[n].nholds!=1) + jit_abort("live.nat[%d].nholds!=1", n); + switch(size) { + case 1: + if (live.nat[n].canbyte || spec>=0) { + live.state[r].dirtysize=ndsize; + live.state[r].validsize=nvsize; + answer=n; + } + break; + case 2: + if (live.nat[n].canword || spec>=0) { + live.state[r].dirtysize=ndsize; + live.state[r].validsize=nvsize; + answer=n; + } + break; + case 4: + live.state[r].dirtysize=ndsize; + live.state[r].validsize=nvsize; + answer=n; + break; + default: abort(); + } + if (answer<0) + evict(r); + } + /* either the value was in memory to start with, or it was evicted and + is in memory now */ + if (answer<0) { + answer=alloc_reg_hinted(r,size,1,spec); + } + if (spec>=0 && spec!=answer) { + mov_nregs(spec,answer); + answer=spec; + } + if (live.state[r].status==UNDEF) + live.state[r].validsize=4; + live.state[r].dirtysize=size>live.state[r].dirtysize?size:live.state[r].dirtysize; + live.state[r].validsize=size>live.state[r].validsize?size:live.state[r].validsize; + + live.nat[answer].locked++; + live.nat[answer].touched=touchcnt++; + if (size==4) { + live.state[r].val=0; + } + else { + Dif (live.state[r].val) { + jit_abort("Problem with val"); + } + } + set_status(r,DIRTY); + return answer; +} + +static int writereg(int r, int size) +{ + return writereg_general(r,size,-1); +} + +static int writereg_specific(int r, int size, int spec) +{ + return writereg_general(r,size,spec); +} + +static inline int rmw_general(int r, int wsize, int rsize, int spec) +{ + int n; + int answer=-1; + + record_register(r); + if (live.state[r].status==UNDEF) { + jit_log("WARNING: Unexpected read of undefined register %d",r); + } + remove_offset(r,spec); + make_exclusive(r,0,spec); + + Dif (wsize=rsize) { + n=live.state[r].realreg; + Dif (live.nat[n].nholds!=1) + jit_abort("live.nat[%d].nholds!=1", n); + + switch(rsize) { + case 1: + if (live.nat[n].canbyte || spec>=0) { + answer=n; + } + break; + case 2: + if (live.nat[n].canword || spec>=0) { + answer=n; + } + break; + case 4: + answer=n; + break; + default: abort(); + } + if (answer<0) + evict(r); + } + /* either the value was in memory to start with, or it was evicted and + is in memory now */ + if (answer<0) { + answer=alloc_reg_hinted(r,spec>=0?4:rsize,0,spec); + } + + if (spec>=0 && spec!=answer) { + /* Too bad */ + mov_nregs(spec,answer); + answer=spec; + } + if (wsize>live.state[r].dirtysize) + live.state[r].dirtysize=wsize; + if (wsize>live.state[r].validsize) + live.state[r].validsize=wsize; + set_status(r,DIRTY); + + live.nat[answer].locked++; + live.nat[answer].touched=touchcnt++; + + Dif (live.state[r].val) { + jit_abort("Problem with val(rmw)"); + } + return answer; +} + +static int rmw(int r, int wsize, int rsize) +{ + return rmw_general(r,wsize,rsize,-1); +} + +static int rmw_specific(int r, int wsize, int rsize, int spec) +{ + return rmw_general(r,wsize,rsize,spec); +} + + +/* needed for restoring the carry flag on non-P6 cores */ +static void bt_l_ri_noclobber(RR4 r, IMM i) +{ + int size=4; + if (i<16) + size=2; + r=readreg(r,size); + compemu_raw_bt_l_ri(r,i); + unlock2(r); +} + +/******************************************************************** + * FPU register status handling. EMIT TIME! * + ********************************************************************/ + +static void f_tomem(int r) +{ + if (live.fate[r].status==DIRTY) { +#if defined(USE_LONG_DOUBLE) + raw_fmov_ext_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); +#else + raw_fmov_mr((uintptr)live.fate[r].mem,live.fate[r].realreg); +#endif + live.fate[r].status=CLEAN; + } +} + +static void f_tomem_drop(int r) +{ + if (live.fate[r].status==DIRTY) { +#if defined(USE_LONG_DOUBLE) + raw_fmov_ext_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); +#else + raw_fmov_mr_drop((uintptr)live.fate[r].mem,live.fate[r].realreg); +#endif + live.fate[r].status=INMEM; + } +} + + +static inline int f_isinreg(int r) +{ + return live.fate[r].status==CLEAN || live.fate[r].status==DIRTY; +} + +static void f_evict(int r) +{ + int rr; + + if (!f_isinreg(r)) + return; + rr=live.fate[r].realreg; + if (live.fat[rr].nholds==1) + f_tomem_drop(r); + else + f_tomem(r); + + Dif (live.fat[rr].locked && + live.fat[rr].nholds==1) { + jit_abort("FPU register %d in nreg %d is locked!",r,live.fate[r].realreg); + } + + live.fat[rr].nholds--; + if (live.fat[rr].nholds!=live.fate[r].realind) { /* Was not last */ + int topreg=live.fat[rr].holds[live.fat[rr].nholds]; + int thisind=live.fate[r].realind; + live.fat[rr].holds[thisind]=topreg; + live.fate[topreg].realind=thisind; + } + live.fate[r].status=INMEM; + live.fate[r].realreg=-1; +} + +static inline void f_free_nreg(int r) +{ + int i=live.fat[r].nholds; + + while (i) { + int vr; + + --i; + vr=live.fat[r].holds[i]; + f_evict(vr); + } + Dif (live.fat[r].nholds!=0) { + jit_abort("Failed to free nreg %d, nholds is %d",r,live.fat[r].nholds); + } +} + + +/* Use with care! */ +static inline void f_isclean(int r) +{ + if (!f_isinreg(r)) + return; + live.fate[r].status=CLEAN; +} + +static inline void f_disassociate(int r) +{ + f_isclean(r); + f_evict(r); +} + + + +static int f_alloc_reg(int r, int willclobber) +{ + int bestreg; + uae_s32 when; + int i; + uae_s32 badness; + bestreg=-1; + when=2000000000; + for (i=N_FREGS;i--;) { + badness=live.fat[i].touched; + if (live.fat[i].nholds==0) + badness=0; + + if (!live.fat[i].locked && badness0) { + f_free_nreg(bestreg); + } + if (f_isinreg(r)) { + f_evict(r); + } + + if (!willclobber) { + if (live.fate[r].status!=UNDEF) { +#if defined(USE_LONG_DOUBLE) + raw_fmov_ext_rm(bestreg,(uintptr)live.fate[r].mem); +#else + raw_fmov_rm(bestreg,(uintptr)live.fate[r].mem); +#endif + } + live.fate[r].status=CLEAN; + } + else { + live.fate[r].status=DIRTY; + } + live.fate[r].realreg=bestreg; + live.fate[r].realind=live.fat[bestreg].nholds; + live.fat[bestreg].touched=touchcnt++; + live.fat[bestreg].holds[live.fat[bestreg].nholds]=r; + live.fat[bestreg].nholds++; + + return bestreg; +} + +static void f_unlock(int r) +{ + Dif (!live.fat[r].locked) + jit_abort ("unlock %d", r); + live.fat[r].locked--; +} + +static void f_setlock(int r) +{ + live.fat[r].locked++; +} + +static inline int f_readreg(int r) +{ + int n; + int answer=-1; + + if (f_isinreg(r)) { + n=live.fate[r].realreg; + answer=n; + } + /* either the value was in memory to start with, or it was evicted and + is in memory now */ + if (answer<0) + answer=f_alloc_reg(r,0); + + live.fat[answer].locked++; + live.fat[answer].touched=touchcnt++; + return answer; +} + +static inline void f_make_exclusive(int r, int clobber) +{ + freg_status oldstate; + int rr=live.fate[r].realreg; + int nr; + int nind; + int ndirt=0; + int i; + + if (!f_isinreg(r)) + return; + if (live.fat[rr].nholds==1) + return; + for (i=0;i : enable runtime disassemblers : %s", JITDebug ? "yes" : "no"); + +#ifdef USE_JIT_FPU + // Use JIT compiler for FPU instructions ? + avoid_fpu = !bx_options.jit.jitfpu; +#else + // JIT FPU is always disabled + avoid_fpu = true; +#endif + jit_log(" : compile FPU instructions : %s", !avoid_fpu ? "yes" : "no"); + + // Get size of the translation cache (in KB) + cache_size = bx_options.jit.jitcachesize; + jit_log(" : requested translation cache size : %d KB", cache_size); + + // Initialize target CPU (check for features, e.g. CMOV, rat stalls) + raw_init_cpu(); + setzflg_uses_bsf = target_check_bsf(); + jit_log(" : target processor has CMOV instructions : %s", have_cmov ? "yes" : "no"); + jit_log(" : target processor can suffer from partial register stalls : %s", have_rat_stall ? "yes" : "no"); + jit_log(" : alignment for loops, jumps are %d, %d", align_loops, align_jumps); +#if defined(CPU_i386) || defined(CPU_x86_64) + jit_log(" : target processor has SSE2 instructions : %s", cpuinfo.x86_has_xmm2 ? "yes" : "no"); + jit_log(" : cache linesize is %lu", (unsigned long)cpuinfo.x86_clflush_size); +#endif + + // Translation cache flush mechanism + lazy_flush = (bx_options.jit.jitlazyflush == 0) ? false : true; + jit_log(" : lazy translation cache invalidation : %s", str_on_off(lazy_flush)); + flush_icache = lazy_flush ? flush_icache_lazy : flush_icache_hard; + + // Compiler features + jit_log(" : register aliasing : %s", str_on_off(1)); + jit_log(" : FP register aliasing : %s", str_on_off(USE_F_ALIAS)); + jit_log(" : lazy constant offsetting : %s", str_on_off(USE_OFFSET)); +#if USE_INLINING + follow_const_jumps = bx_options.jit.jitinline; +#endif + jit_log(" : block inlining : %s", str_on_off(follow_const_jumps)); + jit_log(" : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA)); + + // Build compiler tables + build_comp(); +#endif + + initialized = true; + +#ifdef PROFILE_UNTRANSLATED_INSNS + jit_log(" : gather statistics on untranslated insns count"); +#endif + +#ifdef PROFILE_COMPILE_TIME + jit_log(" : gather statistics on translation time"); + emul_start_time = clock(); +#endif +} + +#ifdef UAE +static +#endif +void compiler_exit(void) +{ +#ifdef PROFILE_COMPILE_TIME + emul_end_time = clock(); +#endif + +#ifdef UAE +#else +#if DEBUG +#if defined(USE_DATA_BUFFER) + jit_log("data_wasted = %d bytes", data_wasted); +#endif +#endif + + // Deallocate translation cache + if (compiled_code) { + vm_release(compiled_code, cache_size * 1024); + compiled_code = 0; + } + + // Deallocate popallspace + if (popallspace) { + vm_release(popallspace, POPALLSPACE_SIZE); + popallspace = 0; + } +#endif + +#ifdef PROFILE_COMPILE_TIME + jit_log("### Compile Block statistics"); + jit_log("Number of calls to compile_block : %d", compile_count); + uae_u32 emul_time = emul_end_time - emul_start_time; + jit_log("Total emulation time : %.1f sec", double(emul_time)/double(CLOCKS_PER_SEC)); + jit_log("Total compilation time : %.1f sec (%.1f%%)", double(compile_time)/double(CLOCKS_PER_SEC), 100.0*double(compile_time)/double(emul_time)); +#endif + +#ifdef PROFILE_UNTRANSLATED_INSNS + uae_u64 untranslated_count = 0; + for (int i = 0; i < 65536; i++) { + opcode_nums[i] = i; + untranslated_count += raw_cputbl_count[i]; + } + jit_log("Sorting out untranslated instructions count..."); + qsort(opcode_nums, 65536, sizeof(uae_u16), untranslated_compfn); + jit_log("Rank Opc Count Name"); + for (int i = 0; i < untranslated_top_ten; i++) { + uae_u32 count = raw_cputbl_count[opcode_nums[i]]; + struct instr *dp; + struct mnemolookup *lookup; + if (!count) + break; + dp = table68k + opcode_nums[i]; + for (lookup = lookuptab; lookup->mnemo != (instrmnem)dp->mnemo; lookup++) + ; + jit_log("%03d: %04x %10u %s", i, opcode_nums[i], count, lookup->name); + } +#endif + +#ifdef RECORD_REGISTER_USAGE + int reg_count_ids[16]; + uint64 tot_reg_count = 0; + for (int i = 0; i < 16; i++) { + reg_count_ids[i] = i; + tot_reg_count += reg_count[i]; + } + qsort(reg_count_ids, 16, sizeof(int), reg_count_compare); + uint64 cum_reg_count = 0; + for (int i = 0; i < 16; i++) { + int r = reg_count_ids[i]; + cum_reg_count += reg_count[r]; + jit_log("%c%d : %16ld %2.1f%% [%2.1f]", r < 8 ? 'D' : 'A', r % 8, + reg_count[r], + 100.0*double(reg_count[r])/double(tot_reg_count), + 100.0*double(cum_reg_count)/double(tot_reg_count)); + } +#endif +} + +#ifdef UAE +#else +bool compiler_use_jit(void) +{ + // Check for the "jit" prefs item + if (!bx_options.jit.jit) + return false; + + // Don't use JIT if translation cache size is less then MIN_CACHE_SIZE KB + if (bx_options.jit.jitcachesize < MIN_CACHE_SIZE) { + panicbug(" : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE); + return false; + } + + return true; +} +#endif + +void init_comp(void) +{ + int i; + uae_s8* cb=can_byte; + uae_s8* cw=can_word; + uae_s8* au=always_used; + +#ifdef RECORD_REGISTER_USAGE + for (i=0;i<16;i++) + reg_count_local[i] = 0; +#endif + + for (i=0;i= uae_p32(kickmem_bank.baseaddr) && + addr < uae_p32(kickmem_bank.baseaddr + 8 * 65536)); +#else + return ((addr >= (uintptr)ROMBaseHost) && (addr < (uintptr)ROMBaseHost + ROMSize)); +#endif +} + +static void flush_all(void) +{ + int i; + + log_flush(); + for (i=0;i0) + free_nreg(i); + + for (i=0;i0) + f_free_nreg(i); + + live.flags_in_flags=TRASH; /* Note: We assume we already rescued the + flags at the very start of the call_r + functions! */ +} + +/******************************************************************** + * Memory access and related functions, CREATE time * + ********************************************************************/ + +void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond) +{ + next_pc_p=not_taken; + taken_pc_p=taken; + branch_cc=cond; +} + +/* Note: get_handler may fail in 64 Bit environments, if direct_handler_to_use is + * outside 32 bit + */ +static uintptr get_handler(uintptr addr) +{ + blockinfo* bi=get_blockinfo_addr_new((void*)(uintptr)addr,0); + return (uintptr)bi->direct_handler_to_use; +} + +/* This version assumes that it is writing *real* memory, and *will* fail + * if that assumption is wrong! No branches, no second chances, just + * straight go-for-it attitude */ + +static void writemem_real(int address, int source, int size, int tmp, int clobber) +{ + int f=tmp; + +#ifdef NATMEM_OFFSET + if (canbang) { /* Woohoo! go directly at the memory! */ + if (clobber) + f=source; + + switch(size) { + case 1: mov_b_bRr(address,source,MEMBaseDiff); break; + case 2: mov_w_rr(f,source); mid_bswap_16(f); mov_w_bRr(address,f,MEMBaseDiff); break; + case 4: mov_l_rr(f,source); mid_bswap_32(f); mov_l_bRr(address,f,MEMBaseDiff); break; + } + forget_about(tmp); + forget_about(f); + return; + } +#endif + +#ifdef UAE + mov_l_rr(f,address); + shrl_l_ri(f,16); /* The index into the baseaddr table */ + mov_l_rm_indexed(f,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */ + + if (address==source) { /* IBrowse does this! */ + if (size > 1) { + add_l(f,address); /* f now holds the final address */ + switch (size) { + case 2: mid_bswap_16(source); mov_w_Rr(f,source,0); + mid_bswap_16(source); return; + case 4: mid_bswap_32(source); mov_l_Rr(f,source,0); + mid_bswap_32(source); return; + } + } + } + switch (size) { /* f now holds the offset */ + case 1: mov_b_mrr_indexed(address,f,1,source); break; + case 2: mid_bswap_16(source); mov_w_mrr_indexed(address,f,1,source); + mid_bswap_16(source); break; /* base, index, source */ + case 4: mid_bswap_32(source); mov_l_mrr_indexed(address,f,1,source); + mid_bswap_32(source); break; + } +#endif +} + +#ifdef UAE +static inline void writemem(int address, int source, int offset, int size, int tmp) +{ + int f=tmp; + + mov_l_rr(f,address); + shrl_l_ri(f,16); /* The index into the mem bank table */ + mov_l_rm_indexed(f,uae_p32(mem_banks),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */ + /* Now f holds a pointer to the actual membank */ + mov_l_rR(f,f,offset); + /* Now f holds the address of the b/w/lput function */ + call_r_02(f,address,source,4,size); + forget_about(tmp); +} +#endif + +void writebyte(int address, int source, int tmp) +{ +#ifdef UAE + if ((special_mem & S_WRITE) || distrust_byte()) + writemem_special(address, source, 5 * SIZEOF_VOID_P, 1, tmp); + else +#endif + writemem_real(address,source,1,tmp,0); +} + +static inline void writeword_general(int address, int source, int tmp, + int clobber) +{ +#ifdef UAE + if ((special_mem & S_WRITE) || distrust_word()) + writemem_special(address, source, 4 * SIZEOF_VOID_P, 2, tmp); + else +#endif + writemem_real(address,source,2,tmp,clobber); +} + +void writeword_clobber(int address, int source, int tmp) +{ + writeword_general(address,source,tmp,1); +} + +void writeword(int address, int source, int tmp) +{ + writeword_general(address,source,tmp,0); +} + +static inline void writelong_general(int address, int source, int tmp, + int clobber) +{ +#ifdef UAE + if ((special_mem & S_WRITE) || distrust_long()) + writemem_special(address, source, 3 * SIZEOF_VOID_P, 4, tmp); + else +#endif + writemem_real(address,source,4,tmp,clobber); +} + +void writelong_clobber(int address, int source, int tmp) +{ + writelong_general(address,source,tmp,1); +} + +void writelong(int address, int source, int tmp) +{ + writelong_general(address,source,tmp,0); +} + + + +/* This version assumes that it is reading *real* memory, and *will* fail + * if that assumption is wrong! No branches, no second chances, just + * straight go-for-it attitude */ + +static void readmem_real(int address, int dest, int size, int tmp) +{ + int f=tmp; + + if (size==4 && address!=dest) + f=dest; + +#ifdef NATMEM_OFFSET + if (canbang) { /* Woohoo! go directly at the memory! */ + switch(size) { + case 1: mov_b_brR(dest,address,MEMBaseDiff); break; + case 2: mov_w_brR(dest,address,MEMBaseDiff); mid_bswap_16(dest); break; + case 4: mov_l_brR(dest,address,MEMBaseDiff); mid_bswap_32(dest); break; + } + forget_about(tmp); + (void) f; + return; + } +#endif + +#ifdef UAE + mov_l_rr(f,address); + shrl_l_ri(f,16); /* The index into the baseaddr table */ + mov_l_rm_indexed(f,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */ + /* f now holds the offset */ + + switch(size) { + case 1: mov_b_rrm_indexed(dest,address,f,1); break; + case 2: mov_w_rrm_indexed(dest,address,f,1); mid_bswap_16(dest); break; + case 4: mov_l_rrm_indexed(dest,address,f,1); mid_bswap_32(dest); break; + } + forget_about(tmp); +#endif +} + + + +#ifdef UAE +static inline void readmem(int address, int dest, int offset, int size, int tmp) +{ + int f=tmp; + + mov_l_rr(f,address); + shrl_l_ri(f,16); /* The index into the mem bank table */ + mov_l_rm_indexed(f,uae_p32(mem_banks),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */ + /* Now f holds a pointer to the actual membank */ + mov_l_rR(f,f,offset); + /* Now f holds the address of the b/w/lget function */ + call_r_11(dest,f,address,size,4); + forget_about(tmp); +} +#endif + +void readbyte(int address, int dest, int tmp) +{ +#ifdef UAE + if ((special_mem & S_READ) || distrust_byte()) + readmem_special(address, dest, 2 * SIZEOF_VOID_P, 1, tmp); + else +#endif + readmem_real(address,dest,1,tmp); +} + +void readword(int address, int dest, int tmp) +{ +#ifdef UAE + if ((special_mem & S_READ) || distrust_word()) + readmem_special(address, dest, 1 * SIZEOF_VOID_P, 2, tmp); + else +#endif + readmem_real(address,dest,2,tmp); +} + +void readlong(int address, int dest, int tmp) +{ +#ifdef UAE + if ((special_mem & S_READ) || distrust_long()) + readmem_special(address, dest, 0 * SIZEOF_VOID_P, 4, tmp); + else +#endif + readmem_real(address,dest,4,tmp); +} + +void get_n_addr(int address, int dest, int tmp) +{ +#ifdef UAE + if (special_mem || distrust_addr()) { + /* This one might appear a bit odd... */ + readmem(address, dest, 6 * SIZEOF_VOID_P, 4, tmp); + return; + } +#endif + + // a is the register containing the virtual address + // after the offset had been fetched + int a=tmp; + + // f is the register that will contain the offset + int f=tmp; + + // a == f == tmp if (address == dest) + if (address!=dest) { + a=address; + f=dest; + } + +#ifdef NATMEM_OFFSET + if (canbang) { +#if FIXED_ADDRESSING + lea_l_brr(dest,address,MEMBaseDiff); +#else +# error "Only fixed adressing mode supported" +#endif + forget_about(tmp); + (void) f; + (void) a; + return; + } +#endif + +#ifdef UAE + mov_l_rr(f,address); + mov_l_rr(dest,address); // gb-- nop if dest==address + shrl_l_ri(f,16); + mov_l_rm_indexed(f,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */ + add_l(dest,f); + forget_about(tmp); +#endif +} + +void get_n_addr_jmp(int address, int dest, int tmp) +{ +#ifdef WINUAE_ARANYM + /* For this, we need to get the same address as the rest of UAE + would --- otherwise we end up translating everything twice */ + get_n_addr(address,dest,tmp); +#else + int f=tmp; + if (address!=dest) + f=dest; + mov_l_rr(f,address); + shrl_l_ri(f,16); /* The index into the baseaddr bank table */ + mov_l_rm_indexed(dest,uae_p32(baseaddr),f,SIZEOF_VOID_P); /* FIXME: is SIZEOF_VOID_P correct? */ + add_l(dest,address); + and_l_ri (dest, ~1); + forget_about(tmp); +#endif +} + + +/* base is a register, but dp is an actual value. + target is a register, as is tmp */ +void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp) +{ + int reg = (dp >> 12) & 15; + int regd_shift=(dp >> 9) & 3; + + if (dp & 0x100) { + int ignorebase=(dp&0x80); + int ignorereg=(dp&0x40); + int addbase=0; + int outer=0; + + if ((dp & 0x30) == 0x20) addbase = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + if ((dp & 0x30) == 0x30) addbase = comp_get_ilong((m68k_pc_offset+=4)-4); + + if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); + if ((dp & 0x3) == 0x3) outer = comp_get_ilong((m68k_pc_offset+=4)-4); + + if ((dp & 0x4) == 0) { /* add regd *before* the get_long */ + if (!ignorereg) { + if ((dp & 0x800) == 0) + sign_extend_16_rr(target,reg); + else + mov_l_rr(target,reg); + shll_l_ri(target,regd_shift); + } + else + mov_l_ri(target,0); + + /* target is now regd */ + if (!ignorebase) + add_l(target,base); + add_l_ri(target,addbase); + if (dp&0x03) readlong(target,target,tmp); + } else { /* do the getlong first, then add regd */ + if (!ignorebase) { + mov_l_rr(target,base); + add_l_ri(target,addbase); + } + else + mov_l_ri(target,addbase); + if (dp&0x03) readlong(target,target,tmp); + + if (!ignorereg) { + if ((dp & 0x800) == 0) + sign_extend_16_rr(tmp,reg); + else + mov_l_rr(tmp,reg); + shll_l_ri(tmp,regd_shift); + /* tmp is now regd */ + add_l(target,tmp); + } + } + add_l_ri(target,outer); + } + else { /* 68000 version */ + if ((dp & 0x800) == 0) { /* Sign extend */ + sign_extend_16_rr(target,reg); + lea_l_brr_indexed(target,base,target,1<= CODE_ALLOC_MAX_ATTEMPTS) + return NULL; + + return do_alloc_code(size, depth + 1); +#else + UNUSED(depth); + uint8 *code = (uint8 *)vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); + return code == VM_MAP_FAILED ? NULL : code; +#endif +} + +static inline uint8 *alloc_code(uint32 size) +{ + uint8 *ptr = do_alloc_code(size, 0); + /* allocated code must fit in 32-bit boundaries */ + assert((uintptr)ptr <= 0xffffffff); + return ptr; +} + +void alloc_cache(void) +{ + if (compiled_code) { + flush_icache_hard(6); + vm_release(compiled_code, cache_size * 1024); + compiled_code = 0; + } + +#ifdef UAE + cache_size = currprefs.cachesize; +#endif + if (cache_size == 0) + return; + + while (!compiled_code && cache_size) { + if ((compiled_code = alloc_code(cache_size * 1024)) == NULL) { + compiled_code = 0; + cache_size /= 2; + } + } + vm_protect(compiled_code, cache_size * 1024, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE); + + if (compiled_code) { + jit_log(" : actual translation cache size : %d KB at %p-%p", cache_size, compiled_code, compiled_code + cache_size*1024); +#ifdef USE_DATA_BUFFER + max_compile_start = compiled_code + cache_size*1024 - BYTES_PER_INST - DATA_BUFFER_SIZE; +#else + max_compile_start = compiled_code + cache_size*1024 - BYTES_PER_INST; +#endif + current_compile_p = compiled_code; + current_cache_size = 0; +#if defined(USE_DATA_BUFFER) + reset_data_buffer(); +#endif + } +} + +static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2) +{ + uae_u32 k1 = 0; + uae_u32 k2 = 0; + +#if USE_CHECKSUM_INFO + checksum_info *csi = bi->csi; + Dif(!csi) abort(); + while (csi) { + uae_s32 len = csi->length; + uintptr tmp = (uintptr)csi->start_p; +#else + uae_s32 len = bi->len; + uintptr tmp = (uintptr)bi->min_pcp; +#endif + uae_u32* pos; + + len += (tmp & 3); + tmp &= ~((uintptr)3); + pos = (uae_u32 *)tmp; + + if (len >= 0 && len <= MAX_CHECKSUM_LEN) { + while (len > 0) { + k1 += *pos; + k2 ^= *pos; + pos++; + len -= 4; + } + } + +#if USE_CHECKSUM_INFO + csi = csi->next; + } +#endif + + *c1 = k1; + *c2 = k2; +} + +#if 0 +static void show_checksum(CSI_TYPE* csi) +{ + uae_u32 k1=0; + uae_u32 k2=0; + uae_s32 len=CSI_LENGTH(csi); + uae_u32 tmp=(uintptr)CSI_START_P(csi); + uae_u32* pos; + + len+=(tmp&3); + tmp&=(~3); + pos=(uae_u32*)tmp; + + if (len<0 || len>MAX_CHECKSUM_LEN) { + return; + } + else { + while (len>0) { + jit_log("%08x ",*pos); + pos++; + len-=4; + } + jit_log(" bla"); + } +} +#endif + + +int check_for_cache_miss(void) +{ + blockinfo* bi=get_blockinfo_addr(regs.pc_p); + + if (bi) { + int cl=cacheline(regs.pc_p); + if (bi!=cache_tags[cl+1].bi) { + raise_in_cl_list(bi); + return 1; + } + } + return 0; +} + + +static void recompile_block(void) +{ + /* An existing block's countdown code has expired. We need to make + sure that execute_normal doesn't refuse to recompile due to a + perceived cache miss... */ + blockinfo* bi=get_blockinfo_addr(regs.pc_p); + + Dif (!bi) + jit_abort("recompile_block"); + raise_in_cl_list(bi); + execute_normal(); + return; +} +static void cache_miss(void) +{ + blockinfo* bi=get_blockinfo_addr(regs.pc_p); +#if COMP_DEBUG + uae_u32 cl=cacheline(regs.pc_p); + blockinfo* bi2=get_blockinfo(cl); +#endif + + if (!bi) { + execute_normal(); /* Compile this block now */ + return; + } + Dif (!bi2 || bi==bi2) { + jit_abort("Unexplained cache miss %p %p",bi,bi2); + } + raise_in_cl_list(bi); + return; +} + +static int called_check_checksum(blockinfo* bi); + +static inline int block_check_checksum(blockinfo* bi) +{ + uae_u32 c1,c2; + bool isgood; + + if (bi->status!=BI_NEED_CHECK) + return 1; /* This block is in a checked state */ + + checksum_count++; + + if (bi->c1 || bi->c2) + calc_checksum(bi,&c1,&c2); + else { + c1=c2=1; /* Make sure it doesn't match */ + } + + isgood=(c1==bi->c1 && c2==bi->c2); + + if (isgood) { + /* This block is still OK. So we reactivate. Of course, that + means we have to move it into the needs-to-be-flushed list */ + bi->handler_to_use=bi->handler; + set_dhtu(bi,bi->direct_handler); + bi->status=BI_CHECKING; + isgood=called_check_checksum(bi) != 0; + } + if (isgood) { + jit_log2("reactivate %p/%p (%x %x/%x %x)",bi,bi->pc_p, c1,c2,bi->c1,bi->c2); + remove_from_list(bi); + add_to_active(bi); + raise_in_cl_list(bi); + bi->status=BI_ACTIVE; + } + else { + /* This block actually changed. We need to invalidate it, + and set it up to be recompiled */ + jit_log2("discard %p/%p (%x %x/%x %x)",bi,bi->pc_p, c1,c2,bi->c1,bi->c2); + invalidate_block(bi); + raise_in_cl_list(bi); + } + return isgood; +} + +static int called_check_checksum(blockinfo* bi) +{ + int isgood=1; + int i; + + for (i=0;i<2 && isgood;i++) { + if (bi->dep[i].jmp_off) { + isgood=block_check_checksum(bi->dep[i].target); + } + } + return isgood; +} + +static void check_checksum(void) +{ + blockinfo* bi=get_blockinfo_addr(regs.pc_p); + uae_u32 cl=cacheline(regs.pc_p); + blockinfo* bi2=get_blockinfo(cl); + + /* These are not the droids you are looking for... */ + if (!bi) { + /* Whoever is the primary target is in a dormant state, but + calling it was accidental, and we should just compile this + new block */ + execute_normal(); + return; + } + if (bi!=bi2) { + /* The block was hit accidentally, but it does exist. Cache miss */ + cache_miss(); + return; + } + + if (!block_check_checksum(bi)) + execute_normal(); +} + +static inline void match_states(blockinfo* bi) +{ + int i; + smallstate* s=&(bi->env); + + if (bi->status==BI_NEED_CHECK) { + block_check_checksum(bi); + } + if (bi->status==BI_ACTIVE || + bi->status==BI_FINALIZING) { /* Deal with the *promises* the + block makes (about not using + certain vregs) */ + for (i=0;i<16;i++) { + if (s->virt[i]==L_UNNEEDED) { + jit_log2("unneeded reg %d at %p",i,target); + COMPCALL(forget_about)(i); // FIXME + } + } + } + flush(1); + + /* And now deal with the *demands* the block makes */ + for (i=0;inat[i]; + if (v>=0) { + // printf("Loading reg %d into %d at %p\n",v,i,target); + readreg_specific(v,4,i); + // do_load_reg(i,v); + // setlock(i); + } + } + for (i=0;inat[i]; + if (v>=0) { + unlock2(i); + } + } +} + +static inline void create_popalls(void) +{ + int i,r; + + if (popallspace == NULL) { + if ((popallspace = alloc_code(POPALLSPACE_SIZE)) == NULL) { + jit_log("WARNING: Could not allocate popallspace!"); +#ifdef UAE + if (currprefs.cachesize > 0) +#endif + { + jit_abort("Could not allocate popallspace!"); + } +#ifdef UAE + /* This is not fatal if JIT is not used. If JIT is + * turned on, it will crash, but it would have crashed + * anyway. */ + return; +#endif + } + } + vm_protect(popallspace, POPALLSPACE_SIZE, VM_PAGE_READ | VM_PAGE_WRITE); + + int stack_space = STACK_OFFSET; + for (i=0;idirect_pen=(cpuop_func*)get_target(); + compemu_raw_mov_l_rm(0,(uintptr)&(bi->pc_p)); + compemu_raw_mov_l_mr((uintptr)®s.pc_p,0); + compemu_raw_jmp((uintptr)popall_execute_normal); + + align_target(align_jumps); + bi->direct_pcc=(cpuop_func*)get_target(); + compemu_raw_mov_l_rm(0,(uintptr)&(bi->pc_p)); + compemu_raw_mov_l_mr((uintptr)®s.pc_p,0); + compemu_raw_jmp((uintptr)popall_check_checksum); + flush_cpu_icache((void *)current_compile_p, (void *)target); + current_compile_p=get_target(); + + bi->deplist=NULL; + for (i=0;i<2;i++) { + bi->dep[i].prev_p=NULL; + bi->dep[i].next=NULL; + } + bi->env=default_ss; + bi->status=BI_INVALID; + bi->havestate=0; + //bi->env=empty_ss; +} + +#ifdef UAE +void compemu_reset(void) +{ + set_cache_state(0); +} +#endif + +#ifdef UAE +#else +// OPCODE is in big endian format, use cft_map() beforehand, if needed. +#endif +static inline void reset_compop(int opcode) +{ + compfunctbl[opcode] = NULL; + nfcompfunctbl[opcode] = NULL; +} + +static int read_opcode(const char *p) +{ + int opcode = 0; + for (int i = 0; i < 4; i++) { + int op = p[i]; + switch (op) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + opcode = (opcode << 4) | (op - '0'); + break; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + opcode = (opcode << 4) | ((op - 'a') + 10); + break; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + opcode = (opcode << 4) | ((op - 'A') + 10); + break; + default: + return -1; + } + } + return opcode; +} + +static bool merge_blacklist() +{ +#ifdef UAE + const char *blacklist = ""; +#else + const char *blacklist = bx_options.jit.jitblacklist; +#endif + if (blacklist[0] != '\0') { + const char *p = blacklist; + for (;;) { + if (*p == 0) + return true; + + int opcode1 = read_opcode(p); + if (opcode1 < 0) + return false; + p += 4; + + int opcode2 = opcode1; + if (*p == '-') { + p++; + opcode2 = read_opcode(p); + if (opcode2 < 0) + return false; + p += 4; + } + + if (*p == 0 || *p == ',') { + jit_log(" : blacklist opcodes : %04x-%04x", opcode1, opcode2); + for (int opcode = opcode1; opcode <= opcode2; opcode++) + reset_compop(cft_map(opcode)); + + if (*(p++) == ',') + continue; + + return true; + } + + return false; + } + } + return true; +} + +void build_comp(void) +{ + int i; + unsigned long opcode; + const struct comptbl* tbl=op_smalltbl_0_comp_ff; + const struct comptbl* nftbl=op_smalltbl_0_comp_nf; + int count; +#ifdef WINUAE_ARANYM + unsigned int cpu_level = 4; // 68040 + const struct cputbl *nfctbl = op_smalltbl_0_nf; +#else +#ifdef NOFLAGS_SUPPORT + struct comptbl *nfctbl = (currprefs.cpu_level >= 5 ? op_smalltbl_0_nf + : currprefs.cpu_level == 4 ? op_smalltbl_1_nf + : (currprefs.cpu_level == 2 || currprefs.cpu_level == 3) ? op_smalltbl_2_nf + : currprefs.cpu_level == 1 ? op_smalltbl_3_nf + : ! currprefs.cpu_compatible ? op_smalltbl_4_nf + : op_smalltbl_5_nf); +#endif +#endif + +#ifdef NATMEM_OFFSET +#ifdef UAE +#ifdef JIT_EXCEPTION_HANDLER + install_exception_handler(); +#endif +#endif +#endif + + jit_log(" : building compiler function tables"); + + for (opcode = 0; opcode < 65536; opcode++) { + reset_compop(opcode); +#ifdef NOFLAGS_SUPPORT + nfcpufunctbl[opcode] = op_illg; +#endif + prop[opcode].use_flags = FLAG_ALL; + prop[opcode].set_flags = FLAG_ALL; +#ifdef UAE + prop[opcode].is_jump=1; +#else + prop[opcode].cflow = fl_trap; // ILLEGAL instructions do trap +#endif + } + + for (i = 0; tbl[i].opcode < 65536; i++) { +#ifdef UAE + int isjmp = (tbl[i].specific & COMP_OPCODE_ISJUMP); + int isaddx = (tbl[i].specific & COMP_OPCODE_ISADDX); + int iscjmp = (tbl[i].specific & COMP_OPCODE_ISCJUMP); + + prop[cft_map(tbl[i].opcode)].is_jump = isjmp; + prop[cft_map(tbl[i].opcode)].is_const_jump = iscjmp; + prop[cft_map(tbl[i].opcode)].is_addx = isaddx; +#else + int cflow = table68k[tbl[i].opcode].cflow; + if (follow_const_jumps && (tbl[i].specific & COMP_OPCODE_ISCJUMP)) + cflow = fl_const_jump; + else + cflow &= ~fl_const_jump; + prop[cft_map(tbl[i].opcode)].cflow = cflow; +#endif + + bool uses_fpu = (tbl[i].specific & COMP_OPCODE_USES_FPU) != 0; + if (uses_fpu && avoid_fpu) + compfunctbl[cft_map(tbl[i].opcode)] = NULL; + else + compfunctbl[cft_map(tbl[i].opcode)] = tbl[i].handler; + } + + for (i = 0; nftbl[i].opcode < 65536; i++) { + bool uses_fpu = (tbl[i].specific & COMP_OPCODE_USES_FPU) != 0; + if (uses_fpu && avoid_fpu) + nfcompfunctbl[cft_map(nftbl[i].opcode)] = NULL; + else + nfcompfunctbl[cft_map(nftbl[i].opcode)] = nftbl[i].handler; +#ifdef NOFLAGS_SUPPORT + nfcpufunctbl[cft_map(nftbl[i].opcode)] = nfctbl[i].handler; +#endif + } + +#ifdef NOFLAGS_SUPPORT + for (i = 0; nfctbl[i].handler; i++) { + nfcpufunctbl[cft_map(nfctbl[i].opcode)] = nfctbl[i].handler; + } +#endif + + for (opcode = 0; opcode < 65536; opcode++) { + compop_func *f; + compop_func *nff; +#ifdef NOFLAGS_SUPPORT + cpuop_func *nfcf; +#endif + int isaddx; +#ifdef UAE + int isjmp,iscjmp; +#else + int cflow; +#endif + +#ifdef UAE + int cpu_level = (currprefs.cpu_model - 68000) / 10; + if (cpu_level > 4) + cpu_level--; +#endif + if ((instrmnem)table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) + continue; + + if (table68k[opcode].handler != -1) { + f = compfunctbl[cft_map(table68k[opcode].handler)]; + nff = nfcompfunctbl[cft_map(table68k[opcode].handler)]; +#ifdef NOFLAGS_SUPPORT + nfcf = nfcpufunctbl[cft_map(table68k[opcode].handler)]; +#endif + isaddx = prop[cft_map(table68k[opcode].handler)].is_addx; + prop[cft_map(opcode)].is_addx = isaddx; +#ifdef UAE + isjmp = prop[cft_map(table68k[opcode].handler)].is_jump; + iscjmp = prop[cft_map(table68k[opcode].handler)].is_const_jump; + prop[cft_map(opcode)].is_jump = isjmp; + prop[cft_map(opcode)].is_const_jump = iscjmp; +#else + cflow = prop[cft_map(table68k[opcode].handler)].cflow; + prop[cft_map(opcode)].cflow = cflow; +#endif + compfunctbl[cft_map(opcode)] = f; + nfcompfunctbl[cft_map(opcode)] = nff; +#ifdef NOFLAGS_SUPPORT + Dif (nfcf == op_illg) + abort(); + nfcpufunctbl[cft_map(opcode)] = nfcf; +#endif + } + prop[cft_map(opcode)].set_flags = table68k[opcode].flagdead; + prop[cft_map(opcode)].use_flags = table68k[opcode].flaglive; + /* Unconditional jumps don't evaluate condition codes, so they + * don't actually use any flags themselves */ +#ifdef UAE + if (prop[cft_map(opcode)].is_const_jump) +#else + if (prop[cft_map(opcode)].cflow & fl_const_jump) +#endif + prop[cft_map(opcode)].use_flags = 0; + } +#ifdef NOFLAGS_SUPPORT + for (i = 0; nfctbl[i].handler != NULL; i++) { + if (nfctbl[i].specific) + nfcpufunctbl[cft_map(tbl[i].opcode)] = nfctbl[i].handler; + } +#endif + + /* Merge in blacklist */ + if (!merge_blacklist()) + { + jit_log(" : blacklist merge failure!"); + } + + count=0; + for (opcode = 0; opcode < 65536; opcode++) { + if (compfunctbl[cft_map(opcode)]) + count++; + } + jit_log(" : supposedly %d compileable opcodes!",count); + + /* Initialise state */ + create_popalls(); + alloc_cache(); + reset_lists(); + + for (i=0;ipc_p)].handler=(cpuop_func*)popall_execute_normal; + cache_tags[cacheline(bi->pc_p)+1].bi=NULL; + dbi=bi; bi=bi->next; + free_blockinfo(dbi); + } + bi=dormant; + while(bi) { + cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func*)popall_execute_normal; + cache_tags[cacheline(bi->pc_p)+1].bi=NULL; + dbi=bi; bi=bi->next; + free_blockinfo(dbi); + } + + reset_lists(); + if (!compiled_code) + return; + +#if defined(USE_DATA_BUFFER) + reset_data_buffer(); +#endif + + current_compile_p=compiled_code; +#ifdef UAE + set_special(0); /* To get out of compiled code */ +#else + SPCFLAGS_SET( SPCFLAG_JIT_EXEC_RETURN ); /* To get out of compiled code */ +#endif +} + + +/* "Soft flushing" --- instead of actually throwing everything away, + we simply mark everything as "needs to be checked". +*/ + +#ifdef WINUAE_ARANYM +static inline void flush_icache_lazy(int) +#else +void flush_icache(int n) +#endif +{ + blockinfo* bi; + blockinfo* bi2; + +#ifdef UAE + if (currprefs.comp_hardflush) { + flush_icache_hard(n); + return; + } +#endif + soft_flush_count++; + if (!active) + return; + + bi=active; + while (bi) { + uae_u32 cl=cacheline(bi->pc_p); + if (bi->status==BI_INVALID || + bi->status==BI_NEED_RECOMP) { + if (bi==cache_tags[cl+1].bi) + cache_tags[cl].handler=(cpuop_func*)popall_execute_normal; + bi->handler_to_use=(cpuop_func*)popall_execute_normal; + set_dhtu(bi,bi->direct_pen); + bi->status=BI_INVALID; + } + else { + if (bi==cache_tags[cl+1].bi) + cache_tags[cl].handler=(cpuop_func*)popall_check_checksum; + bi->handler_to_use=(cpuop_func*)popall_check_checksum; + set_dhtu(bi,bi->direct_pcc); + bi->status=BI_NEED_CHECK; + } + bi2=bi; + bi=bi->next; + } + /* bi2 is now the last entry in the active list */ + bi2->next=dormant; + if (dormant) + dormant->prev_p=&(bi2->next); + + dormant=active; + active->prev_p=&dormant; + active=NULL; +} + +#ifdef UAE +static +#endif +void flush_icache_range(uae_u32 start, uae_u32 length) +{ + if (!active) + return; + +#if LAZY_FLUSH_ICACHE_RANGE + uae_u8 *start_p = get_real_address(start); + blockinfo *bi = active; + while (bi) { +#if USE_CHECKSUM_INFO + bool invalidate = false; + for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) + invalidate = (((start_p - csi->start_p) < csi->length) || + ((csi->start_p - start_p) < length)); +#else + // Assume system is consistent and would invalidate the right range + const bool invalidate = (bi->pc_p - start_p) < length; +#endif + if (invalidate) { + uae_u32 cl = cacheline(bi->pc_p); + if (bi == cache_tags[cl + 1].bi) + cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; + bi->handler_to_use = (cpuop_func *)popall_execute_normal; + set_dhtu(bi, bi->direct_pen); + bi->status = BI_NEED_RECOMP; + } + bi = bi->next; + } + return; +#else + UNUSED(start); + UNUSED(length); +#endif + flush_icache(-1); +} + +/* +static void catastrophe(void) +{ + jit_abort("catastprophe"); +} +*/ + +int failure; + +#ifdef UAE +static inline unsigned int get_opcode_cft_map(unsigned int f) +{ + return ((f >> 8) & 255) | ((f & 255) << 8); +} +#define DO_GET_OPCODE(a) (get_opcode_cft_map((uae_u16)*(a))) +#else +#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU) +# define DO_GET_OPCODE(a) (do_get_mem_word_unswapped((uae_u16 *)(a))) +#else +# define DO_GET_OPCODE(a) (do_get_mem_word((uae_u16 *)(a))) +#endif +#endif + +#ifdef JIT_DEBUG +static uae_u8 *last_regs_pc_p = 0; +static uae_u8 *last_compiled_block_addr = 0; + +void compiler_dumpstate(void) +{ + if (!JITDebug) + return; + + bug("### Host addresses"); + bug("MEM_BASE : %lx", (unsigned long)MEMBaseDiff); + bug("PC_P : %p", ®s.pc_p); + bug("SPCFLAGS : %p", ®s.spcflags); + bug("D0-D7 : %p-%p", ®s.regs[0], ®s.regs[7]); + bug("A0-A7 : %p-%p", ®s.regs[8], ®s.regs[15]); + bug(" "); + + bug("### M68k processor state"); + m68k_dumpstate(stderr, 0); + bug(" "); + + bug("### Block in Atari address space"); + bug("M68K block : %p", + (void *)(uintptr)last_regs_pc_p); + if (last_regs_pc_p != 0) { + bug("Native block : %p (%d bytes)", + (void *)last_compiled_block_addr, + get_blockinfo_addr(last_regs_pc_p)->direct_handler_size); + } + bug(" "); +} +#endif + +#ifdef UAE +void compile_block(cpu_history *pc_hist, int blocklen, int totcycles) +{ + if (letit && compiled_code && currprefs.cpu_model >= 68020) { +#else +static void compile_block(cpu_history* pc_hist, int blocklen) +{ + if (letit && compiled_code) { +#endif +#ifdef PROFILE_COMPILE_TIME + compile_count++; + clock_t start_time = clock(); +#endif +#ifdef JIT_DEBUG + bool disasm_block = true; +#endif + + /* OK, here we need to 'compile' a block */ + int i; + int r; + int was_comp=0; + uae_u8 liveflags[MAXRUN+1]; +#if USE_CHECKSUM_INFO + bool trace_in_rom = isinrom((uintptr)pc_hist[0].location) != 0; + uintptr max_pcp=(uintptr)pc_hist[blocklen - 1].location; + uintptr min_pcp=max_pcp; +#else + uintptr max_pcp=(uintptr)pc_hist[0].location; + uintptr min_pcp=max_pcp; +#endif + uae_u32 cl=cacheline(pc_hist[0].location); + void* specflags=(void*)®s.spcflags; + blockinfo* bi=NULL; + blockinfo* bi2; + int extra_len=0; + + redo_current_block=0; + if (current_compile_p >= MAX_COMPILE_PTR) + flush_icache_hard(7); + + alloc_blockinfos(); + + bi=get_blockinfo_addr_new(pc_hist[0].location,0); + bi2=get_blockinfo(cl); + + optlev=bi->optlevel; + if (bi->status!=BI_INVALID) { + Dif (bi!=bi2) { + /* I don't think it can happen anymore. Shouldn't, in + any case. So let's make sure... */ + jit_abort("WOOOWOO count=%d, ol=%d %p %p", bi->count,bi->optlevel,bi->handler_to_use, cache_tags[cl].handler); + } + + Dif (bi->count!=-1 && bi->status!=BI_NEED_RECOMP) { + jit_abort("bi->count=%d, bi->status=%d,bi->optlevel=%d",bi->count,bi->status,bi->optlevel); + /* What the heck? We are not supposed to be here! */ + } + } + if (bi->count==-1) { + optlev++; + while (!optcount[optlev]) + optlev++; + bi->count=optcount[optlev]-1; + } + current_block_pc_p=(uintptr)pc_hist[0].location; + + remove_deps(bi); /* We are about to create new code */ + bi->optlevel=optlev; + bi->pc_p=(uae_u8*)pc_hist[0].location; +#if USE_CHECKSUM_INFO + free_checksum_info_chain(bi->csi); + bi->csi = NULL; +#endif + + liveflags[blocklen]=FLAG_ALL; /* All flags needed afterwards */ + i=blocklen; + while (i--) { + uae_u16* currpcp=pc_hist[i].location; + uae_u32 op=DO_GET_OPCODE(currpcp); + +#if USE_CHECKSUM_INFO + trace_in_rom = trace_in_rom && isinrom((uintptr)currpcp); + if (follow_const_jumps && is_const_jump(op)) { + checksum_info *csi = alloc_checksum_info(); + csi->start_p = (uae_u8 *)min_pcp; + csi->length = max_pcp - min_pcp + LONGEST_68K_INST; + csi->next = bi->csi; + bi->csi = csi; + max_pcp = (uintptr)currpcp; + } + min_pcp = (uintptr)currpcp; +#else + if ((uintptr)currpcpmax_pcp) + max_pcp=(uintptr)currpcp; +#endif + +#ifdef UAE + if (!currprefs.compnf) { + liveflags[i]=FLAG_ALL; + } + else +#endif + { + liveflags[i] = ((liveflags[i+1] & (~prop[op].set_flags))|prop[op].use_flags); + if (prop[op].is_addx && (liveflags[i+1]&FLAG_Z)==0) + liveflags[i]&= ~FLAG_Z; + } + } + +#if USE_CHECKSUM_INFO + checksum_info *csi = alloc_checksum_info(); + csi->start_p = (uae_u8 *)min_pcp; + csi->length = max_pcp - min_pcp + LONGEST_68K_INST; + csi->next = bi->csi; + bi->csi = csi; +#endif + + bi->needed_flags=liveflags[0]; + + align_target(align_loops); + was_comp=0; + + bi->direct_handler=(cpuop_func*)get_target(); + set_dhtu(bi,bi->direct_handler); + bi->status=BI_COMPILING; + current_block_start_target=(uintptr)get_target(); + + log_startblock(); + + if (bi->count>=0) { /* Need to generate countdown code */ + compemu_raw_mov_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); + compemu_raw_sub_l_mi((uintptr)&(bi->count),1); + compemu_raw_jl((uintptr)popall_recompile_block); + } + if (optlev==0) { /* No need to actually translate */ + /* Execute normally without keeping stats */ + compemu_raw_mov_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); + compemu_raw_jmp((uintptr)popall_exec_nostats); + } + else { + reg_alloc_run=0; + next_pc_p=0; + taken_pc_p=0; + branch_cc=0; // Only to be initialized. Will be set together with next_pc_p + + comp_pc_p=(uae_u8*)pc_hist[0].location; + init_comp(); + was_comp=1; + +#ifdef USE_CPU_EMUL_SERVICES + compemu_raw_sub_l_mi((uintptr)&emulated_ticks,blocklen); + compemu_raw_jcc_b_oponly(NATIVE_CC_GT); + uae_s8 *branchadd=(uae_s8*)get_target(); + skip_byte(); + raw_dec_sp(STACK_SHADOW_SPACE); + compemu_raw_call((uintptr)cpu_do_check_ticks); + raw_inc_sp(STACK_SHADOW_SPACE); + *branchadd=(uintptr)get_target()-((uintptr)branchadd+1); +#endif + +#ifdef JIT_DEBUG + if (JITDebug) { + compemu_raw_mov_l_mi((uintptr)&last_regs_pc_p,(uintptr)pc_hist[0].location); + compemu_raw_mov_l_mi((uintptr)&last_compiled_block_addr,current_block_start_target); + } +#endif + + for (i=0;i1) { + failure=0; + if (!was_comp) { + comp_pc_p=(uae_u8*)pc_hist[i].location; + init_comp(); + } + was_comp=1; + + bool isnop = do_get_mem_word(pc_hist[i].location) == 0x4e71 || + ((i + 1) < blocklen && do_get_mem_word(pc_hist[i+1].location) == 0x4e71); + + if (isnop) + compemu_raw_mov_l_mi((uintptr)®s.fault_pc, ((uintptr)(pc_hist[i].location)) - MEMBaseDiff); + + comptbl[opcode](opcode); + freescratch(); + if (!(liveflags[i+1] & FLAG_CZNV)) { + /* We can forget about flags */ + dont_care_flags(); + } +#if INDIVIDUAL_INST + flush(1); + nop(); + flush(1); + was_comp=0; +#endif + /* + * workaround for buserror handling: on a "nop", write registers back + */ + if (isnop) + { + flush(1); + nop(); + was_comp=0; + } + } + + if (failure) { + if (was_comp) { + flush(1); + was_comp=0; + } + compemu_raw_mov_l_ri(REG_PAR1,(uae_u32)opcode); +#if USE_NORMAL_CALLING_CONVENTION + raw_push_l_r(REG_PAR1); +#endif + compemu_raw_mov_l_mi((uintptr)®s.pc_p, + (uintptr)pc_hist[i].location); + raw_dec_sp(STACK_SHADOW_SPACE); + compemu_raw_call((uintptr)cputbl[opcode]); + raw_inc_sp(STACK_SHADOW_SPACE); +#ifdef PROFILE_UNTRANSLATED_INSNS + // raw_cputbl_count[] is indexed with plain opcode (in m68k order) + compemu_raw_add_l_mi((uintptr)&raw_cputbl_count[cft_map(opcode)],1); +#endif +#if USE_NORMAL_CALLING_CONVENTION + raw_inc_sp(4); +#endif + + if (i < blocklen - 1) { + uae_s8* branchadd; + + /* if (SPCFLAGS_TEST(SPCFLAG_STOP)) popall_do_nothing() */ + compemu_raw_mov_l_rm(0,(uintptr)specflags); + compemu_raw_test_l_rr(0,0); +#if defined(USE_DATA_BUFFER) + data_check_end(8, 64); // just a pessimistic guess... +#endif + compemu_raw_jz_b_oponly(); + branchadd=(uae_s8*)get_target(); + skip_byte(); +#ifdef UAE + raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles)); +#endif + compemu_raw_jmp((uintptr)popall_do_nothing); + *branchadd=(uintptr)get_target()-(uintptr)branchadd-1; + } + } + } +#if 1 /* This isn't completely kosher yet; It really needs to be + be integrated into a general inter-block-dependency scheme */ + if (next_pc_p && taken_pc_p && + was_comp && taken_pc_p==current_block_pc_p) + { + blockinfo* bi1=get_blockinfo_addr_new((void*)next_pc_p,0); + blockinfo* bi2=get_blockinfo_addr_new((void*)taken_pc_p,0); + uae_u8 x=bi1->needed_flags; + + if (x==0xff || 1) { /* To be on the safe side */ + uae_u16* next=(uae_u16*)next_pc_p; + uae_u32 op=DO_GET_OPCODE(next); + + x=FLAG_ALL; + x&=(~prop[op].set_flags); + x|=prop[op].use_flags; + } + + x|=bi2->needed_flags; + if (!(x & FLAG_CZNV)) { + /* We can forget about flags */ + dont_care_flags(); + extra_len+=2; /* The next instruction now is part of this block */ + } + } +#endif + log_flush(); + + if (next_pc_p) { /* A branch was registered */ + uintptr t1=next_pc_p; + uintptr t2=taken_pc_p; + int cc=branch_cc; + + uae_u32* branchadd; + uae_u32* tba; + bigstate tmp; + blockinfo* tbi; + + if (taken_pc_penv))) { + mark_callers_recompile(bi); + } + + big_to_small_state(&live,&(bi->env)); +#endif + +#if USE_CHECKSUM_INFO + remove_from_list(bi); + if (trace_in_rom) { + // No need to checksum that block trace on cache invalidation + free_checksum_info_chain(bi->csi); + bi->csi = NULL; + add_to_dormant(bi); + } + else { + calc_checksum(bi,&(bi->c1),&(bi->c2)); + add_to_active(bi); + } +#else + if (next_pc_p+extra_len>=max_pcp && + next_pc_p+extra_lenlen=max_pcp-min_pcp; + bi->min_pcp=min_pcp; + + remove_from_list(bi); + if (isinrom(min_pcp) && isinrom(max_pcp)) { + add_to_dormant(bi); /* No need to checksum it on cache flush. + Please don't start changing ROMs in + flight! */ + } + else { + calc_checksum(bi,&(bi->c1),&(bi->c2)); + add_to_active(bi); + } +#endif + + current_cache_size += get_target() - (uae_u8 *)current_compile_p; + +#ifdef JIT_DEBUG + bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target; + + if (JITDebug && disasm_block) { + uaecptr block_addr = start_pc + ((char *)pc_hist[0].location - (char *)start_pc_p); + jit_log("M68K block @ 0x%08x (%d insns)", block_addr, blocklen); + uae_u32 block_size = ((uae_u8 *)pc_hist[blocklen - 1].location - (uae_u8 *)pc_hist[0].location) + 1; + disasm_m68k_block((const uae_u8 *)pc_hist[0].location, block_size); + jit_log("Compiled block @ %p", pc_hist[0].location); + disasm_native_block((const uae_u8 *)current_block_start_target, bi->direct_handler_size); + UNUSED(block_addr); + } +#endif + + log_dump(); + align_target(align_jumps); + +#ifdef UAE +#ifdef USE_UDIS86 + UDISFN(current_block_start_target, target) +#endif +#endif + + /* This is the non-direct handler */ + bi->handler= + bi->handler_to_use=(cpuop_func *)get_target(); + compemu_raw_cmp_l_mi((uintptr)®s.pc_p,(uintptr)pc_hist[0].location); + compemu_raw_jnz((uintptr)popall_cache_miss); + comp_pc_p=(uae_u8*)pc_hist[0].location; + + bi->status=BI_FINALIZING; + init_comp(); + match_states(bi); + flush(1); + + compemu_raw_jmp((uintptr)bi->direct_handler); + + flush_cpu_icache((void *)current_block_start_target, (void *)target); + current_compile_p=get_target(); + raise_in_cl_list(bi); +#ifdef UAE + bi->nexthandler=current_compile_p; +#endif + + /* We will flush soon, anyway, so let's do it now */ + if (current_compile_p >= MAX_COMPILE_PTR) + flush_icache_hard(7); + + bi->status=BI_ACTIVE; + if (redo_current_block) + block_need_recompile(bi); + +#ifdef PROFILE_COMPILE_TIME + compile_time += (clock() - start_time); +#endif +#ifdef UAE + /* Account for compilation time */ + do_extra_cycles(totcycles); +#endif + } + +#ifndef UAE + /* Account for compilation time */ + cpu_do_check_ticks(); +#endif +} + +#ifdef UAE + /* Slightly different function defined in newcpu.cpp */ +#else +void do_nothing(void) +{ + /* What did you expect this to do? */ +} +#endif + +#ifdef UAE + /* Different implementation in newcpu.cpp */ +#else +void exec_nostats(void) +{ + for (;;) { + uae_u32 opcode = GET_OPCODE; +#ifdef FLIGHT_RECORDER + m68k_record_step(m68k_getpc(), opcode); +#endif + (*cpufunctbl[opcode])(opcode); + cpu_check_ticks(); + if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL)) { + return; /* We will deal with the spcflags in the caller */ + } + } +} +#endif + +#ifdef UAE +/* FIXME: check differences against UAE execute_normal (newcpu.cpp) */ +#else +void execute_normal(void) +{ + if (!check_for_cache_miss()) { + cpu_history pc_hist[MAXRUN]; + int blocklen = 0; +#if 0 && FIXED_ADDRESSING + start_pc_p = regs.pc_p; + start_pc = get_virtual_address(regs.pc_p); +#else + start_pc_p = regs.pc_oldp; + start_pc = regs.pc; +#endif + for (;;) { /* Take note: This is the do-it-normal loop */ + pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p; + uae_u32 opcode = GET_OPCODE; +#ifdef FLIGHT_RECORDER + m68k_record_step(m68k_getpc(), opcode); +#endif + (*cpufunctbl[opcode])(opcode); + cpu_check_ticks(); + if (end_block(opcode) || SPCFLAGS_TEST(SPCFLAG_ALL) || blocklen>=MAXRUN) { + compile_block(pc_hist, blocklen); + return; /* We will deal with the spcflags in the caller */ + } + /* No need to check regs.spcflags, because if they were set, + we'd have ended up inside that "if" */ + } + } +} +#endif + +typedef void (*compiled_handler)(void); + +#ifdef UAE +/* FIXME: check differences against UAE m68k_do_compile_execute */ +#else +void m68k_do_compile_execute(void) +{ + for (;;) { + ((compiled_handler)(pushall_call_handler))(); + /* Whenever we return from that, we should check spcflags */ + if (SPCFLAGS_TEST(SPCFLAG_ALL)) { + if (m68k_do_specialties ()) + return; + } + } +} +#endif + +#ifdef UAE +/* FIXME: check differences against UAE m68k_compile_execute */ +#else +void m68k_compile_execute (void) +{ +setjmpagain: + TRY(prb) { + for (;;) { + if (quit_program > 0) { + if (quit_program == 1) { +#ifdef FLIGHT_RECORDER + dump_flight_recorder(); +#endif + break; + } + quit_program = 0; + m68k_reset (); + } + m68k_do_compile_execute(); + } + } + CATCH(prb) { + jit_log("m68k_compile_execute: exception %d pc=%08x (%08x+%p-%p) fault_pc=%08x addr=%08x -> %08x sp=%08x", + int(prb), + m68k_getpc(), + regs.pc, regs.pc_p, regs.pc_oldp, + regs.fault_pc, + regs.mmu_fault_addr, get_long (regs.vbr + 4*prb), + regs.regs[15]); + flush_icache(0); + Exception(prb, 0); + goto setjmpagain; + } +} +#endif + +#endif /* JIT */ diff --git a/BasiliskII/src/uae_cpu/compiler/compstbla.cpp b/BasiliskII/src/uae_cpu/compiler/compstbla.cpp new file mode 100644 index 00000000..e2f36d1e --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/compstbla.cpp @@ -0,0 +1,5 @@ +/* + * compstbl.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "compstbl.cpp" diff --git a/BasiliskII/src/uae_cpu/compiler/flags_arm.h b/BasiliskII/src/uae_cpu/compiler/flags_arm.h new file mode 100644 index 00000000..c9a60490 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/flags_arm.h @@ -0,0 +1,52 @@ +/* + * compiler/flags_arm.h - Native flags definitions for ARM + * + * Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef NATIVE_FLAGS_ARM_H +#define NATIVE_FLAGS_ARM_H + +/* Native integer code conditions */ +enum { + NATIVE_CC_EQ = 0, + NATIVE_CC_NE = 1, + NATIVE_CC_CS = 2, + NATIVE_CC_CC = 3, + NATIVE_CC_MI = 4, + NATIVE_CC_PL = 5, + NATIVE_CC_VS = 6, + NATIVE_CC_VC = 7, + NATIVE_CC_HI = 8, + NATIVE_CC_LS = 9, + NATIVE_CC_GE = 10, + NATIVE_CC_LT = 11, + NATIVE_CC_GT = 12, + NATIVE_CC_LE = 13, + NATIVE_CC_AL = 14 +}; + +#endif /* NATIVE_FLAGS_ARM_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/flags_x86.h b/BasiliskII/src/uae_cpu/compiler/flags_x86.h new file mode 100644 index 00000000..310dbcc3 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/flags_x86.h @@ -0,0 +1,52 @@ +/* + * compiler/flags_x86.h - Native flags definitions for IA-32 + * + * Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer + * + * Adaptation for Basilisk II and improvements, copyright 2000-2002 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2002 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef NATIVE_FLAGS_X86_H +#define NATIVE_FLAGS_X86_H + +/* Native integer code conditions */ +enum { + NATIVE_CC_HI = 7, + NATIVE_CC_LS = 6, + NATIVE_CC_CC = 3, + NATIVE_CC_CS = 2, + NATIVE_CC_NE = 5, + NATIVE_CC_EQ = 4, + NATIVE_CC_VC = 1, + NATIVE_CC_VS = 0, + NATIVE_CC_PL = 9, + NATIVE_CC_MI = 8, + NATIVE_CC_GE = 13, + NATIVE_CC_LT = 12, + NATIVE_CC_GT = 15, + NATIVE_CC_LE = 14 +}; + +/* FIXME: include/flags_x86.h in UAE had the following values: + NATIVE_CC_VC = 11, + NATIVE_CC_VS = 10, +*/ + +#endif /* NATIVE_FLAGS_X86_H */ diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c new file mode 100644 index 00000000..a7c4ee2b --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -0,0 +1,3619 @@ +/* + * compiler/gencomp.c - MC680x0 compilation generator + * + * Based on work Copyright 1995, 1996 Bernd Schmidt + * Changes for UAE-JIT Copyright 2000 Bernd Meyer + * + * Adaptation for ARAnyM/ARM, copyright 2001-2014 + * Milan Jurik, Jens Heitmann + * + * Adaptation for Basilisk II and improvements, copyright 2000-2005 + * Gwenole Beauchesne + * + * Basilisk II (C) 1997-2005 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CC_FOR_BUILD 1 +#include "sysconfig.h" + +#include "sysdeps.h" +#include "readcpu.h" + +#undef NDEBUG +#include +#include +#include +#include +#include +#include +#undef abort + +#ifdef UAE +/* +#define DISABLE_I_OR_AND_EOR +#define DISABLE_I_SUB +#define DISABLE_I_SUBA +#define DISABLE_I_SUBX +#define DISABLE_I_ADD +#define DISABLE_I_ADDA +#define DISABLE_I_ADDX +#define DISABLE_I_NEG +#define DISABLE_I_NEGX +#define DISABLE_I_CLR +#define DISABLE_I_NOT +#define DISABLE_I_TST +#define DISABLE_I_BCHG_BCLR_BSET_BTST +#define DISABLE_I_CMPM_CMP +#define DISABLE_I_CMPA +#define DISABLE_I_MOVE +#define DISABLE_I_MOVEA +#define DISABLE_I_SWAP +#define DISABLE_I_EXG +#define DISABLE_I_EXT +#define DISABLE_I_MVEL +#define DISABLE_I_MVMLE +#define DISABLE_I_RTD +#define DISABLE_I_LINK +#define DISABLE_I_UNLK +#define DISABLE_I_RTS +#define DISABLE_I_JSR +#define DISABLE_I_JMP +#define DISABLE_I_BSR +#define DISABLE_I_BCC +#define DISABLE_I_LEA +#define DISABLE_I_PEA +#define DISABLE_I_DBCC +#define DISABLE_I_SCC +#define DISABLE_I_MULU +#define DISABLE_I_MULS +#define DISABLE_I_ASR +#define DISABLE_I_ASL +#define DISABLE_I_LSR +#define DISABLE_I_LSL +#define DISABLE_I_ROL +#define DISABLE_I_ROR +#define DISABLE_I_MULL +#define DISABLE_I_FPP +#define DISABLE_I_FBCC +#define DISABLE_I_FSCC +#define DISABLE_I_MOVE16 +*/ +#endif /* UAE */ + +#ifdef UAE +#define JIT_PATH "jit/" +#define GEN_PATH "jit/" +#define RETURN "return 0;" +#define RETTYPE "uae_u32" +#define NEXT_CPU_LEVEL 5 +#else +#define JIT_PATH "compiler/" +#define GEN_PATH "" +#define RETURN "return;" +#define RETTYPE "void" +#define NEXT_CPU_LEVEL 4 +#define ua(s) s +#endif + +#define BOOL_TYPE "int" +#define failure global_failure=1 +#define FAILURE global_failure=1 +#define isjump global_isjump=1 +#define is_const_jump global_iscjump=1 +#define isaddx global_isaddx=1 +#define uses_cmov global_cmov=1 +#define mayfail global_mayfail=1 +#define uses_fpu global_fpu=1 + +int hack_opcode; + +static int global_failure; +static int global_isjump; +static int global_iscjump; +static int global_isaddx; +static int global_cmov; +static int long_opcode; +static int global_mayfail; +static int global_fpu; + +static char endstr[1000]; +static char lines[100000]; +static int comp_index=0; + +#include "flags_x86.h" + +#ifndef __attribute__ +# ifndef __GNUC__ +# define __attribute__(x) +# endif +#endif + + +static int cond_codes[]={-1,-1, + NATIVE_CC_HI,NATIVE_CC_LS, + NATIVE_CC_CC,NATIVE_CC_CS, + NATIVE_CC_NE,NATIVE_CC_EQ, + -1,-1, + NATIVE_CC_PL,NATIVE_CC_MI, + NATIVE_CC_GE,NATIVE_CC_LT, + NATIVE_CC_GT,NATIVE_CC_LE + }; + +__attribute__((format(printf, 1, 2))) +static void comprintf(const char *format, ...) +{ + va_list args; + + va_start(args, format); + comp_index += vsprintf(lines + comp_index, format, args); + va_end(args); +} + +static void com_discard(void) +{ + comp_index = 0; +} + +static void com_flush(void) +{ + int i; + for (i = 0; i < comp_index; i++) + putchar(lines[i]); + com_discard(); +} + + +static FILE *headerfile; +static FILE *stblfile; + +static int using_prefetch; +static int using_exception_3; +static int cpu_level; +static int noflags; + +/* For the current opcode, the next lower level that will have different code. + * Initialized to -1 for each opcode. If it remains unchanged, indicates we + * are done with that opcode. */ +static int next_cpu_level; + +static int *opcode_map; +static int *opcode_next_clev; +static int *opcode_last_postfix; +static unsigned long *counts; + +static void read_counts(void) +{ + FILE *file; + unsigned long opcode, count, total; + char name[20]; + int nr = 0; + memset (counts, 0, 65536 * sizeof *counts); + + file = fopen ("frequent.68k", "r"); + if (file) + { + if (fscanf (file, "Total: %lu\n", &total) != 1) { + assert(0); + } + while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) + { + opcode_next_clev[nr] = NEXT_CPU_LEVEL; + opcode_last_postfix[nr] = -1; + opcode_map[nr++] = opcode; + counts[opcode] = count; + } + fclose (file); + } + if (nr == nr_cpuop_funcs) + return; + for (opcode = 0; opcode < 0x10000; opcode++) + { + if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG + && counts[opcode] == 0) + { + opcode_next_clev[nr] = NEXT_CPU_LEVEL; + opcode_last_postfix[nr] = -1; + opcode_map[nr++] = opcode; + counts[opcode] = count; + } + } + assert (nr == nr_cpuop_funcs); +} + +static int n_braces = 0; +static int insn_n_cycles; + +static void +start_brace (void) +{ + n_braces++; + comprintf ("{"); +} + +static void +close_brace (void) +{ + assert (n_braces > 0); + n_braces--; + comprintf ("}"); +} + +static void +finish_braces (void) +{ + while (n_braces > 0) + close_brace (); +} + +static inline void gen_update_next_handler(void) +{ + return; /* Can anything clever be done here? */ +} + +static void gen_writebyte(const char *address, const char *source) +{ + comprintf("\twritebyte(%s, %s, scratchie);\n", address, source); +} + +static void gen_writeword(const char *address, const char *source) +{ + comprintf("\twriteword(%s, %s, scratchie);\n", address, source); +} + +static void gen_writelong(const char *address, const char *source) +{ + comprintf("\twritelong(%s, %s, scratchie);\n", address, source); +} + +static void gen_readbyte(const char *address, const char* dest) +{ + comprintf("\treadbyte(%s, %s, scratchie);\n", address, dest); +} + +static void gen_readword(const char *address, const char *dest) +{ + comprintf("\treadword(%s,%s,scratchie);\n", address, dest); +} + +static void gen_readlong(const char *address, const char *dest) +{ + comprintf("\treadlong(%s, %s, scratchie);\n", address, dest); +} + + + +static const char * +gen_nextilong (void) +{ + static char buffer[80]; + + sprintf (buffer, "comp_get_ilong((m68k_pc_offset+=4)-4)"); + insn_n_cycles += 4; + + long_opcode=1; + return buffer; +} + +static const char * +gen_nextiword (void) +{ + static char buffer[80]; + + sprintf (buffer, "comp_get_iword((m68k_pc_offset+=2)-2)"); + insn_n_cycles+=2; + + long_opcode=1; + return buffer; +} + +static const char * +gen_nextibyte (void) +{ + static char buffer[80]; + + sprintf (buffer, "comp_get_ibyte((m68k_pc_offset+=2)-2)"); + insn_n_cycles += 2; + + long_opcode=1; + return buffer; +} + + +static void +swap_opcode (void) +{ +#ifdef UAE + /* no-op */ +#else + comprintf("#ifdef USE_JIT_FPU\n"); + comprintf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + comprintf("\topcode = do_byteswap_16(opcode);\n"); + comprintf("#endif\n"); + comprintf("#endif\n"); +#endif +} + +static void +sync_m68k_pc (void) +{ + comprintf("\t if (m68k_pc_offset > SYNC_PC_OFFSET) sync_m68k_pc();\n"); +} + + +/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, + * the calling routine handles Apdi and Aipi modes. + * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ +static void genamode(amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem) +{ + start_brace(); + switch (mode) + { + case Dreg: /* Do we need to check dodgy here? */ + assert (!movem); + if (getv == 1 || getv == 2) + { + /* We generate the variable even for getv==2, so we can use + it as a destination for MOVE */ + comprintf("\tint %s = %s;\n", name, reg); + } + return; + + case Areg: + assert (!movem); + if (getv == 1 || getv == 2) + { + /* see above */ + comprintf("\tint %s = dodgy ? scratchie++ : %s + 8;\n", name, reg); + if (getv == 1) + { + comprintf("\tif (dodgy) \n"); + comprintf("\t\tmov_l_rr(%s, %s + 8);\n", name, reg); + } + } + return; + + case Aind: + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, %s + 8);\n", name, reg); + break; + case Aipi: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_rr(%sa, %s + 8);\n", name, reg); + break; + case Apdi: + switch (size) + { + case sz_byte: + if (movem) + { + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, (uae_s32)-areg_byteinc[%s]);\n", reg, reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + case sz_word: + if (movem) + { + comprintf("\tint %sa=dodgy?scratchie++:%s+8;\n", name, reg); + comprintf("\tif (dodgy) \n"); + comprintf("\tmov_l_rr(%sa,8+%s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, -2);\n", reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + case sz_long: + if (movem) + { + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, -4);\n", reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + default: + assert(0); + break; + } + break; + case Ad16: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + comprintf("\tlea_l_brr(%sa, %sa, (uae_s32)(uae_s16)%s);\n", name, name, gen_nextiword()); + break; + case Ad8r: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tcalc_disp_ea_020(%s + 8, %s, %sa, scratchie);\n", reg, gen_nextiword(), name); + break; + + case PC16: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n"); + comprintf("\tuae_s32 PC16off = (uae_s32)(uae_s16)%s;\n", gen_nextiword()); + comprintf("\tmov_l_ri(%sa, address + PC16off);\n", name); + break; + + case PC8r: + comprintf("\tint pctmp = scratchie++;\n"); + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n"); + start_brace(); + comprintf("\tmov_l_ri(pctmp,address);\n"); + + comprintf("\tcalc_disp_ea_020(pctmp, %s, %sa, scratchie);\n", gen_nextiword(), name); + break; + case absw: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_ri(%sa, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + break; + case absl: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_ri(%sa, %s); /* absl */\n", name, gen_nextilong()); + break; + case imm: + assert (getv == 1); + switch (size) + { + case sz_byte: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte()); + break; + case sz_word: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + break; + case sz_long: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); + break; + default: + assert(0); + break; + } + return; + case imm0: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte()); + return; + case imm1: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + return; + case imm2: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); + return; + case immi: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, reg); + return; + default: + assert(0); + break; + } + + /* We get here for all non-reg non-immediate addressing modes to + * actually fetch the value. */ + if (getv == 1) + { + char astring[80]; + sprintf(astring, "%sa", name); + switch (size) + { + case sz_byte: + insn_n_cycles += 2; + break; + case sz_word: + insn_n_cycles += 2; + break; + case sz_long: + insn_n_cycles += 4; + break; + default: + assert(0); + break; + } + start_brace(); + comprintf("\tint %s = scratchie++;\n", name); + switch (size) + { + case sz_byte: + gen_readbyte(astring, name); + break; + case sz_word: + gen_readword(astring, name); + break; + case sz_long: + gen_readlong(astring, name); + break; + default: + assert(0); + break; + } + } + + /* We now might have to fix up the register for pre-dec or post-inc + * addressing modes. */ + if (!movem) + { + switch (mode) + { + case Aipi: + switch (size) + { + case sz_byte: + comprintf("\tlea_l_brr(%s + 8,%s + 8, areg_byteinc[%s]);\n", reg, reg, reg); + break; + case sz_word: + comprintf("\tlea_l_brr(%s + 8, %s + 8, 2);\n", reg, reg); + break; + case sz_long: + comprintf("\tlea_l_brr(%s + 8, %s + 8, 4);\n", reg, reg); + break; + default: + assert(0); + break; + } + break; + case Apdi: + break; + default: + break; + } + } +} + +static void genastore(const char *from, amodes mode, const char *reg, wordsizes size, const char *to) +{ + switch (mode) + { + case Dreg: + switch (size) + { + case sz_byte: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_b_rr(%s, %s);\n", reg, from); + break; + case sz_word: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_w_rr(%s, %s);\n", reg, from); + break; + case sz_long: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_l_rr(%s, %s);\n", reg, from); + break; + default: + assert(0); + break; + } + break; + case Areg: + switch (size) + { + case sz_word: + comprintf("\tif(%s + 8 != %s)\n", reg, from); + comprintf("\t\tmov_w_rr(%s + 8, %s);\n", reg, from); + break; + case sz_long: + comprintf("\tif(%s + 8 != %s)\n", reg, from); + comprintf("\t\tmov_l_rr(%s + 8, %s);\n", reg, from); + break; + default: + assert(0); + break; + } + break; + + case Apdi: + case absw: + case PC16: + case PC8r: + case Ad16: + case Ad8r: + case Aipi: + case Aind: + case absl: + { + char astring[80]; + sprintf(astring, "%sa", to); + + switch (size) + { + case sz_byte: + insn_n_cycles += 2; + gen_writebyte(astring, from); + break; + case sz_word: + insn_n_cycles += 2; + gen_writeword(astring, from); + break; + case sz_long: + insn_n_cycles += 4; + gen_writelong(astring, from); + break; + default: + assert(0); + break; + } + } + break; + case imm: + case imm0: + case imm1: + case imm2: + case immi: + assert(0); + break; + default: + assert(0); + break; + } +} + +static void genmov16(uae_u32 opcode, struct instr *curi) +{ + comprintf("\tint src=scratchie++;\n"); + comprintf("\tint dst=scratchie++;\n"); + + if ((opcode & 0xfff8) == 0xf620) { + /* MOVE16 (Ax)+,(Ay)+ */ + comprintf("\tuae_u16 dstreg=((%s)>>12)&0x07;\n", gen_nextiword()); + comprintf("\tmov_l_rr(src,8+srcreg);\n"); + comprintf("\tmov_l_rr(dst,8+dstreg);\n"); + } + else { + /* Other variants */ + genamode (curi->smode, "srcreg", curi->size, "src", 0, 2); + genamode (curi->dmode, "dstreg", curi->size, "dst", 0, 2); + comprintf("\tmov_l_rr(src,srca);\n"); + comprintf("\tmov_l_rr(dst,dsta);\n"); + } + + /* Align on 16-byte boundaries */ + comprintf("\tand_l_ri(src,~15);\n"); + comprintf("\tand_l_ri(dst,~15);\n"); + + if ((opcode & 0xfff8) == 0xf620) { + comprintf("\tif (srcreg != dstreg)\n"); + comprintf("\tadd_l_ri(srcreg+8,16);\n"); + comprintf("\tadd_l_ri(dstreg+8,16);\n"); + } + else if ((opcode & 0xfff8) == 0xf600) + comprintf("\tadd_l_ri(srcreg+8,16);\n"); + else if ((opcode & 0xfff8) == 0xf608) + comprintf("\tadd_l_ri(dstreg+8,16);\n"); + +#ifdef UAE + comprintf("\tif (special_mem) {\n"); + comprintf("\t\tint tmp=scratchie;\n"); + comprintf("\tscratchie+=4;\n" + "\treadlong(src,tmp,scratchie);\n" + "\twritelong_clobber(dst,tmp,scratchie);\n" + "\tadd_l_ri(src,4);\n" + "\tadd_l_ri(dst,4);\n" + "\treadlong(src,tmp,scratchie);\n" + "\twritelong_clobber(dst,tmp,scratchie);\n" + "\tadd_l_ri(src,4);\n" + "\tadd_l_ri(dst,4);\n" + "\treadlong(src,tmp,scratchie);\n" + "\twritelong_clobber(dst,tmp,scratchie);\n" + "\tadd_l_ri(src,4);\n" + "\tadd_l_ri(dst,4);\n" + "\treadlong(src,tmp,scratchie);\n" + "\twritelong_clobber(dst,tmp,scratchie);\n"); + comprintf("\t} else {\n"); +#endif + comprintf("\tint tmp=scratchie;\n"); + comprintf("\tscratchie+=4;\n" + "\tget_n_addr(src,src,scratchie);\n" + "\tget_n_addr(dst,dst,scratchie);\n" + "\tmov_l_rR(tmp+0,src,0);\n" + "\tmov_l_rR(tmp+1,src,4);\n" + "\tmov_l_rR(tmp+2,src,8);\n" + "\tmov_l_rR(tmp+3,src,12);\n" + "\tmov_l_Rr(dst,tmp+0,0);\n" + "\tforget_about(tmp+0);\n" + "\tmov_l_Rr(dst,tmp+1,4);\n" + "\tforget_about(tmp+1);\n" + "\tmov_l_Rr(dst,tmp+2,8);\n" + "\tforget_about(tmp+2);\n" + "\tmov_l_Rr(dst,tmp+3,12);\n"); +#ifdef UAE + comprintf("\t}\n"); +#endif +} + +static void +genmovemel (uae_u16 opcode) +{ + comprintf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); + comprintf ("\tint native=scratchie++;\n"); + comprintf ("\tint i;\n"); + comprintf ("\tsigned char offset=0;\n"); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); +#ifdef UAE + if (table68k[opcode].size == sz_long) + comprintf("\tif (1 && !special_mem) {\n"); + else + comprintf("\tif (1 && !special_mem) {\n"); +#endif + + /* Fast but unsafe... */ + comprintf("\tget_n_addr(srca,native,scratchie);\n"); + + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch(table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tmov_l_rR(i,native,offset);\n" + "\t\t\tmid_bswap_32(i);\n" + "\t\t\toffset+=4;\n"); + break; + case sz_word: + comprintf("\t\t\tmov_w_rR(i,native,offset);\n" + "\t\t\tmid_bswap_16(i);\n" + "\t\t\tsign_extend_16_rr(i,i);\n" + "\t\t\toffset+=2;\n"); + break; + default: assert(0); + } + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Aipi) { + comprintf("\t\t\tlea_l_brr(8+dstreg,srca,offset);\n"); + } + /* End fast but unsafe. */ + +#ifdef UAE + comprintf("\t} else {\n"); + + comprintf ("\t\tint tmp=scratchie++;\n"); + + comprintf("\t\tmov_l_rr(tmp,srca);\n"); + comprintf("\t\tfor (i=0;i<16;i++) {\n" + "\t\t\tif ((mask>>i)&1) {\n"); + switch(table68k[opcode].size) { + case sz_long: + comprintf("\t\t\t\treadlong(tmp,i,scratchie);\n" + "\t\t\t\tadd_l_ri(tmp,4);\n"); + break; + case sz_word: + comprintf("\t\t\t\treadword(tmp,i,scratchie);\n" + "\t\t\t\tadd_l_ri(tmp,2);\n"); + break; + default: assert(0); + } + + comprintf("\t\t\t}\n" + "\t\t}\n"); + if (table68k[opcode].dmode == Aipi) { + comprintf("\t\tmov_l_rr(8+dstreg,tmp);\n"); + } + comprintf("\t}\n"); +#endif + +} + + +static void +genmovemle (uae_u16 opcode) +{ + comprintf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); + comprintf ("\tint native=scratchie++;\n"); + comprintf ("\tint i;\n"); + comprintf ("\tint tmp=scratchie++;\n"); + comprintf ("\tsigned char offset=0;\n"); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + +#ifdef UAE + /* *Sigh* Some clever geek realized that the fastest way to copy a + buffer from main memory to the gfx card is by using movmle. Good + on her, but unfortunately, gfx mem isn't "real" mem, and thus that + act of cleverness means that movmle must pay attention to special_mem, + or Genetic Species is a rather boring-looking game ;-) */ + if (table68k[opcode].size == sz_long) + comprintf("\tif (1 && !special_mem) {\n"); + else + comprintf("\tif (1 && !special_mem) {\n"); +#endif + comprintf("\tget_n_addr(srca,native,scratchie);\n"); + + if (table68k[opcode].dmode!=Apdi) { + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch(table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tmov_l_rr(tmp,i);\n" + "\t\t\tmid_bswap_32(tmp);\n" + "\t\t\tmov_l_Rr(native,tmp,offset);\n" + "\t\t\toffset+=4;\n"); + break; + case sz_word: + comprintf("\t\t\tmov_l_rr(tmp,i);\n" + "\t\t\tmid_bswap_16(tmp);\n" + "\t\t\tmov_w_Rr(native,tmp,offset);\n" + "\t\t\toffset+=2;\n"); + break; + default: assert(0); + } + } + else { /* Pre-decrement */ + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch(table68k[opcode].size) { + case sz_long: + comprintf("\t\t\toffset-=4;\n" + "\t\t\tmov_l_rr(tmp,15-i);\n" + "\t\t\tmid_bswap_32(tmp);\n" + "\t\t\tmov_l_Rr(native,tmp,offset);\n" + ); + break; + case sz_word: + comprintf("\t\t\toffset-=2;\n" + "\t\t\tmov_l_rr(tmp,15-i);\n" + "\t\t\tmid_bswap_16(tmp);\n" + "\t\t\tmov_w_Rr(native,tmp,offset);\n" + ); + break; + default: assert(0); + } + } + + + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Apdi) { + comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n"); + } +#ifdef UAE + comprintf("\t} else {\n"); + + if (table68k[opcode].dmode!=Apdi) { + comprintf("\tmov_l_rr(tmp,srca);\n"); + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch(table68k[opcode].size) { + case sz_long: + comprintf("\t\t\twritelong(tmp,i,scratchie);\n" + "\t\t\tadd_l_ri(tmp,4);\n"); + break; + case sz_word: + comprintf("\t\t\twriteword(tmp,i,scratchie);\n" + "\t\t\tadd_l_ri(tmp,2);\n"); + break; + default: assert(0); + } + } + else { /* Pre-decrement */ + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch(table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tsub_l_ri(srca,4);\n" + "\t\t\twritelong(srca,15-i,scratchie);\n"); + break; + case sz_word: + comprintf("\t\t\tsub_l_ri(srca,2);\n" + "\t\t\twriteword(srca,15-i,scratchie);\n"); + break; + default: assert(0); + } + } + + + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Apdi) { + comprintf("\t\t\tmov_l_rr(8+dstreg,srca);\n"); + } + comprintf("\t}\n"); +#endif +} + + +static void +duplicate_carry (void) +{ + comprintf ("\tif (needed_flags&FLAG_X) duplicate_carry();\n"); +} + +typedef enum +{ + flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, + flag_addx, flag_subx, flag_zn, flag_av, flag_sv, flag_and, flag_or, + flag_eor, flag_mov +} +flagtypes; + + +static void +genflags (flagtypes type, wordsizes size, const char *value, const char *src, const char *dst) +{ + if (noflags) { + switch(type) { + case flag_cmp: + comprintf("\tdont_care_flags();\n"); + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + return; + case flag_add: + case flag_sub: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch(type) { + case flag_add: op="add"; break; + case flag_sub: op="sub"; break; + default: assert(0); + } + switch (size) + { + case sz_byte: + comprintf("\t%s_b(%s,%s);\n",op,dst,src); + break; + case sz_word: + comprintf("\t%s_w(%s,%s);\n",op,dst,src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n",op,dst,src); + break; + } + return; + } + break; + + case flag_and: + comprintf("\tdont_care_flags();\n"); + switch (size) + { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src); + comprintf("\tor_l_ri(scratchie,0xffffff00);\n"); + comprintf("\tand_l(%s,scratchie);\n",dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tand_b(%s,%s);\n",dst,src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src); + comprintf("\tor_l_ri(scratchie,0xffff0000);\n"); + comprintf("\tand_l(%s,scratchie);\n",dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tand_w(%s,%s);\n",dst,src); + break; + case sz_long: + comprintf("\tand_l(%s,%s);\n",dst,src); + break; + } + return; + + case flag_mov: + comprintf("\tdont_care_flags();\n"); + switch (size) + { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src); + comprintf("\tand_l_ri(%s,0xffffff00);\n",dst); + comprintf("\tor_l(%s,scratchie);\n",dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tmov_b_rr(%s,%s);\n",dst,src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src); + comprintf("\tand_l_ri(%s,0xffff0000);\n",dst); + comprintf("\tor_l(%s,scratchie);\n",dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tmov_w_rr(%s,%s);\n",dst,src); + break; + case sz_long: + comprintf("\tmov_l_rr(%s,%s);\n",dst,src); + break; + } + return; + + case flag_or: + case flag_eor: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + const char* op; + switch(type) { + case flag_or: op="or"; break; + case flag_eor: op="xor"; break; + default: assert(0); + } + switch (size) + { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src); + comprintf("\t%s_l(%s,scratchie);\n",op,dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\t%s_b(%s,%s);\n",op,dst,src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src); + comprintf("\t%s_l(%s,scratchie);\n",op,dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\t%s_w(%s,%s);\n",op,dst,src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n",op,dst,src); + break; + } + close_brace(); + return; + } + + + case flag_addx: + case flag_subx: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch(type) { + case flag_addx: op="adc"; break; + case flag_subx: op="sbb"; break; + default: assert(0); + } + comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ + switch (size) + { + case sz_byte: + comprintf("\t%s_b(%s,%s);\n",op,dst,src); + break; + case sz_word: + comprintf("\t%s_w(%s,%s);\n",op,dst,src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n",op,dst,src); + break; + } + return; + } + break; + default: return; + } + } + + /* Need the flags, but possibly not all of them */ + switch (type) + { + case flag_logical_noclobber: + failure; + /* fall through */ + + case flag_and: + case flag_or: + case flag_eor: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + const char* op; + switch(type) { + case flag_and: op="and"; break; + case flag_or: op="or"; break; + case flag_eor: op="xor"; break; + default: assert(0); + } + switch (size) + { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n",op,dst,src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n",op,dst,src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n",op,dst,src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + } + + case flag_mov: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + switch (size) + { + case sz_byte: + comprintf("\tif (%s!=%s) {\n",src,dst); + comprintf("\tmov_b_ri(%s,0);\n" + "\tstart_needflags();\n",dst); + comprintf("\tor_b(%s,%s);\n",dst,src); + comprintf("\t} else {\n"); + comprintf("\tmov_b_rr(%s,%s);\n",dst,src); + comprintf("\ttest_b_rr(%s,%s);\n",dst,dst); + comprintf("\t}\n"); + break; + case sz_word: + comprintf("\tif (%s!=%s) {\n",src,dst); + comprintf("\tmov_w_ri(%s,0);\n" + "\tstart_needflags();\n",dst); + comprintf("\tor_w(%s,%s);\n",dst,src); + comprintf("\t} else {\n"); + comprintf("\tmov_w_rr(%s,%s);\n",dst,src); + comprintf("\ttest_w_rr(%s,%s);\n",dst,dst); + comprintf("\t}\n"); + break; + case sz_long: + comprintf("\tif (%s!=%s) {\n",src,dst); + comprintf("\tmov_l_ri(%s,0);\n" + "\tstart_needflags();\n",dst); + comprintf("\tor_l(%s,%s);\n",dst,src); + comprintf("\t} else {\n"); + comprintf("\tmov_l_rr(%s,%s);\n",dst,src); + comprintf("\ttest_l_rr(%s,%s);\n",dst,dst); + comprintf("\t}\n"); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + } + + case flag_logical: + comprintf("\tdont_care_flags();\n"); + start_brace(); + switch (size) + { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\ttest_b_rr(%s,%s);\n",value,value); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\ttest_w_rr(%s,%s);\n",value,value); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\ttest_l_rr(%s,%s);\n",value,value); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + + + case flag_add: + case flag_sub: + case flag_cmp: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch(type) { + case flag_add: op="add"; break; + case flag_sub: op="sub"; break; + case flag_cmp: op="cmp"; break; + default: assert(0); + } + switch (size) + { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n",op,dst,src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n",op,dst,src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n",op,dst,src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (type!=flag_cmp) { + duplicate_carry(); + } + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + + return; + } + + case flag_addx: + case flag_subx: + uses_cmov; + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch(type) { + case flag_addx: op="adc"; break; + case flag_subx: op="sbb"; break; + default: assert(0); + } + start_brace(); + comprintf("\tint zero=scratchie++;\n" + "\tint one=scratchie++;\n" + "\tif (needed_flags&FLAG_Z) {\n" + "\tmov_l_ri(zero,0);\n" + "\tmov_l_ri(one,-1);\n" + "\tmake_flags_live();\n" + "\tcmov_l_rr(zero,one,%d);\n" + "\t}\n",NATIVE_CC_NE); + comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ + switch (size) + { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n",op,dst,src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n",op,dst,src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n",op,dst,src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tif (needed_flags&FLAG_Z) {\n" + "\tcmov_l_rr(zero,one,%d);\n" + "\tset_zero(zero, one);\n" /* No longer need one */ + "\tlive_flags();\n" + "\t}\n",NATIVE_CC_NE); + comprintf("\tend_needflags();\n"); + duplicate_carry(); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + return; + } + default: + failure; + break; + } +} + +static int /* returns zero for success, non-zero for failure */ +gen_opcode (unsigned int opcode) +{ + struct instr *curi = table68k + opcode; + const char* ssize=NULL; + + insn_n_cycles = 2; + global_failure=0; + long_opcode=0; + global_isjump=0; + global_iscjump=0; + global_isaddx=0; + global_cmov=0; + global_fpu=0; + global_mayfail=0; + hack_opcode=opcode; + endstr[0]=0; + + start_brace (); + comprintf("\tuae_u8 scratchie=S1;\n"); + switch (curi->plev) + { + case 0: /* not privileged */ + break; + case 1: /* unprivileged only on 68000 */ + if (cpu_level == 0) + break; + if (next_cpu_level < 0) + next_cpu_level = 0; + + /* fall through */ + case 2: /* priviledged */ + failure; /* Easy ones first */ + break; + case 3: /* privileged if size == word */ + if (curi->size == sz_byte) + break; + failure; + break; + } + switch (curi->size) { + case sz_byte: ssize="b"; break; + case sz_word: ssize="w"; break; + case sz_long: ssize="l"; break; + default: assert(0); + } + (void)ssize; + + switch (curi->mnemo) + { + case i_OR: + case i_AND: + case i_EOR: +#ifdef DISABLE_I_OR_AND_EOR + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + switch(curi->mnemo) { + case i_OR: genflags (flag_or, curi->size, "", "src", "dst"); break; + case i_AND: genflags (flag_and, curi->size, "", "src", "dst"); break; + case i_EOR: genflags (flag_eor, curi->size, "", "src", "dst"); break; + } + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_ORSR: + case i_EORSR: + failure; + isjump; + break; + + case i_ANDSR: + failure; + isjump; + break; + + case i_SUB: +#ifdef DISABLE_I_SUB + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags (flag_sub, curi->size, "", "src", "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_SUBA: +#ifdef DISABLE_I_SUBA + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break; + case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break; + case sz_long: comprintf("\ttmp=src;\n"); break; + default: assert(0); + } + comprintf("\tsub_l(dst,tmp);\n"); + genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); + break; + + case i_SUBX: +#ifdef DISABLE_I_SUBX + failure; +#endif + isaddx; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags (flag_subx, curi->size, "", "src", "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_SBCD: + failure; + /* I don't think so! */ + break; + + case i_ADD: +#ifdef DISABLE_I_ADD + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags (flag_add, curi->size, "", "src", "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_ADDA: +#ifdef DISABLE_I_ADDA + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break; + case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break; + case sz_long: comprintf("\ttmp=src;\n"); break; + default: assert(0); + } + comprintf("\tadd_l(dst,tmp);\n"); + genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); + break; + + case i_ADDX: +#ifdef DISABLE_I_ADDX + failure; +#endif + isaddx; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + genflags (flag_addx, curi->size, "", "src", "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_ABCD: + failure; + /* No BCD maths for me.... */ + break; + + case i_NEG: +#ifdef DISABLE_I_NEG + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace (); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags (flag_sub, curi->size, "", "src", "dst"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_NEGX: +#ifdef DISABLE_I_NEGX + failure; +#endif + isaddx; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace (); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags (flag_subx, curi->size, "", "src", "dst"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_NBCD: + failure; + /* Nope! */ + break; + + case i_CLR: +#ifdef DISABLE_I_CLR + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags (flag_logical, curi->size, "dst", "", ""); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_NOT: +#ifdef DISABLE_I_NOT + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace (); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0xffffffff);\n"); + genflags (flag_eor, curi->size, "", "src", "dst"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_TST: +#ifdef DISABLE_I_TST + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genflags (flag_logical, curi->size, "src", "", ""); + break; + case i_BCHG: + case i_BCLR: + case i_BSET: + case i_BTST: +#ifdef DISABLE_I_BCHG_BCLR_BSET_BTST + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + { + const char* op; + int need_write=1; + + switch(curi->mnemo) { + case i_BCHG: op="btc"; break; + case i_BCLR: op="btr"; break; + case i_BSET: op="bts"; break; + case i_BTST: op="bt"; need_write=0; break; + default: op=""; assert(0); + } + comprintf("\t%s_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n",op); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + if (need_write) + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + } + break; + + case i_CMPM: + case i_CMP: +#ifdef DISABLE_I_CMPM_CMP + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace (); + genflags (flag_cmp, curi->size, "", "src", "dst"); + break; + + case i_CMPA: +#ifdef DISABLE_I_CMPA + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmps=scratchie++;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tsign_extend_8_rr(tmps,src);\n"); break; + case sz_word: comprintf("\tsign_extend_16_rr(tmps,src);\n"); break; + case sz_long: comprintf("tmps=src;\n"); break; + default: assert(0); + } + genflags (flag_cmp, sz_long, "", "tmps", "dst"); + break; + /* The next two are coded a little unconventional, but they are doing + * weird things... */ + + case i_MVPRM: + isjump; + failure; + break; + + case i_MVPMR: + isjump; + failure; + break; + + case i_MOVE: +#ifdef DISABLE_I_MOVE + failure; +#endif + switch(curi->dmode) { + case Dreg: + case Areg: + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genflags (flag_mov, curi->size, "", "src", "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + default: /* It goes to memory, not a register */ + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genflags (flag_logical, curi->size, "src", "", ""); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + break; + } + break; + + case i_MOVEA: +#ifdef DISABLE_I_MOVEA + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + + start_brace(); + comprintf("\tint tmps=scratchie++;\n"); + switch(curi->size) { + case sz_word: comprintf("\tsign_extend_16_rr(dst,src);\n"); break; + case sz_long: comprintf("\tmov_l_rr(dst,src);\n"); break; + default: assert(0); + } + genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); + break; + + case i_MVSR2: + isjump; + failure; + break; + + case i_MV2SR: + isjump; + failure; + break; + + case i_SWAP: +#ifdef DISABLE_I_SWAP + failure; +#endif + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\tdont_care_flags();\n"); + comprintf("\trol_l_ri(src,16);\n"); + genflags (flag_logical, sz_long, "src", "", ""); + genastore ("src", curi->smode, "srcreg", sz_long, "src"); + break; + + case i_EXG: +#ifdef DISABLE_I_EXG + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tmov_l_rr(tmp,src);\n"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("tmp", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_EXT: +#ifdef DISABLE_I_EXT + failure; +#endif + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\tdont_care_flags();\n"); + start_brace (); + switch (curi->size) + { + case sz_byte: + comprintf ("\tint dst = src;\n" + "\tsign_extend_8_rr(src,src);\n"); + break; + case sz_word: + comprintf ("\tint dst = scratchie++;\n" + "\tsign_extend_8_rr(dst,src);\n"); + break; + case sz_long: + comprintf ("\tint dst = src;\n" + "\tsign_extend_16_rr(src,src);\n"); + break; + default: + assert(0); + } + genflags (flag_logical, + curi->size == sz_word ? sz_word : sz_long, "dst", "", ""); + genastore ("dst", curi->smode, "srcreg", + curi->size == sz_word ? sz_word : sz_long, "src"); + break; + + case i_MVMEL: +#ifdef DISABLE_I_MVEL + failure; +#endif + genmovemel (opcode); + break; + + case i_MVMLE: +#ifdef DISABLE_I_MVMLE + failure; +#endif + genmovemle (opcode); + break; + + case i_TRAP: + isjump; + failure; + break; + + case i_MVR2USP: + isjump; + failure; + break; + + case i_MVUSP2R: + isjump; + failure; + break; + + case i_RESET: + isjump; + failure; + break; + + case i_NOP: + break; + + case i_STOP: + isjump; + failure; + break; + + case i_RTE: + isjump; + failure; + break; + + case i_RTD: +#ifdef DISABLE_I_RTD + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); + /* offs is constant */ + comprintf("\tadd_l_ri(offs,4);\n"); + start_brace(); + comprintf("\tint newad=scratchie++;\n" + "\treadlong(15,newad,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc,newad);\n" + "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n" + "\tadd_l(15,offs);\n"); + gen_update_next_handler(); + isjump; + break; + + case i_LINK: +#ifdef DISABLE_I_LINK + failure; +#endif + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + comprintf("\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,src,scratchie);\n" + "\tmov_l_rr(src,15);\n"); + if (curi->size==sz_word) + comprintf("\tsign_extend_16_rr(offs,offs);\n"); + comprintf("\tadd_l(15,offs);\n"); + genastore ("src", curi->smode, "srcreg", sz_long, "src"); + break; + + case i_UNLK: +#ifdef DISABLE_I_UNLK + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\tmov_l_rr(15,src);\n" + "\treadlong(15,src,scratchie);\n" + "\tadd_l_ri(15,4);\n"); + genastore ("src", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_RTS: +#ifdef DISABLE_I_RTS + failure; +#endif + comprintf("\tint newad=scratchie++;\n" + "\treadlong(15,newad,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc,newad);\n" + "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n" + "\tlea_l_brr(15,15,4);\n"); + gen_update_next_handler(); + isjump; + break; + + case i_TRAPV: + isjump; + failure; + break; + + case i_RTR: + isjump; + failure; + break; + + case i_JSR: +#ifdef DISABLE_I_JSR + failure; +#endif + isjump; + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + start_brace(); + comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,ret,scratchie);\n"); + comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" + "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n"); + gen_update_next_handler(); + break; + + case i_JMP: +#ifdef DISABLE_I_JMP + failure; +#endif + isjump; + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" + "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n"); + gen_update_next_handler(); + break; + + case i_BSR: +#ifdef DISABLE_I_BSR + failure; +#endif + is_const_jump; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,ret,scratchie);\n"); + comprintf("\tadd_l_ri(src,m68k_pc_offset_thisinst+2);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + comprintf("\tadd_l(PC_P,src);\n"); + + comprintf("\tcomp_pc_p=(uae_u8*)(uintptr)get_const(PC_P);\n"); + break; + + case i_Bcc: +#ifdef DISABLE_I_BCC + failure; +#endif + comprintf("\tuae_u32 v,v1,v2;\n"); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + /* That source is an immediate, so we can clobber it with abandon */ + switch(curi->size) { + case sz_byte: comprintf("\tsign_extend_8_rr(src,src);\n"); break; + case sz_word: comprintf("\tsign_extend_16_rr(src,src);\n"); break; + case sz_long: break; + } + comprintf("\tsub_l_ri(src,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); + /* Leave the following as "add" --- it will allow it to be optimized + away due to src being a constant ;-) */ + comprintf("\tadd_l_ri(src,(uintptr)comp_pc_p);\n"); + comprintf("\tmov_l_ri(PC_P,(uintptr)comp_pc_p);\n"); + /* Now they are both constant. Might as well fold in m68k_pc_offset */ + comprintf("\tadd_l_ri(src,m68k_pc_offset);\n"); + comprintf("\tadd_l_ri(PC_P,m68k_pc_offset);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + + if (curi->cc>=2) { + comprintf("\tv1=get_const(PC_P);\n" + "\tv2=get_const(src);\n" + "\tregister_branch(v1,v2,%d);\n", + cond_codes[curi->cc]); + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + isjump; + } + else { + is_const_jump; + } + + switch(curi->cc) { + case 0: /* Unconditional jump */ + comprintf("\tmov_l_rr(PC_P,src);\n"); + comprintf("\tcomp_pc_p=(uae_u8*)(uintptr)get_const(PC_P);\n"); + break; + case 1: break; /* This is silly! */ + case 8: failure; break; /* Work out details! FIXME */ + case 9: failure; break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + break; + default: assert(0); + } + break; + + case i_LEA: +#ifdef DISABLE_I_LEA + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_PEA: +#ifdef DISABLE_I_PEA + failure; +#endif + if (table68k[opcode].smode==Areg || + table68k[opcode].smode==Aind || + table68k[opcode].smode==Aipi || + table68k[opcode].smode==Apdi || + table68k[opcode].smode==Ad16 || + table68k[opcode].smode==Ad8r) + comprintf("if (srcreg==7) dodgy=1;\n"); + + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (Apdi, "7", sz_long, "dst", 2, 0); + genastore ("srca", Apdi, "7", sz_long, "dst"); + break; + + case i_DBcc: +#ifdef DISABLE_I_DBCC + failure; +#endif + isjump; + uses_cmov; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + + /* That offs is an immediate, so we can clobber it with abandon */ + switch(curi->size) { + case sz_word: comprintf("\tsign_extend_16_rr(offs,offs);\n"); break; + default: assert(0); /* Seems this only comes in word flavour */ + } + comprintf("\tsub_l_ri(offs,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); + comprintf("\tadd_l_ri(offs,(uintptr)comp_pc_p);\n"); /* New PC, + once the + offset_68k is + * also added */ + /* Let's fold in the m68k_pc_offset at this point */ + comprintf("\tadd_l_ri(offs,m68k_pc_offset);\n"); + comprintf("\tadd_l_ri(PC_P,m68k_pc_offset);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + + start_brace(); + comprintf("\tint nsrc=scratchie++;\n"); + + if (curi->cc>=2) { + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + } + + assert (curi->size==sz_word); + + switch(curi->cc) { + case 0: /* This is an elaborate nop? */ + break; + case 1: + comprintf("\tstart_needflags();\n"); + comprintf("\tsub_w_ri(src,1);\n"); + comprintf("\t end_needflags();\n"); + start_brace(); + comprintf("\tuae_u32 v2,v;\n" + "\tuae_u32 v1=get_const(PC_P);\n"); + comprintf("\tv2=get_const(offs);\n" + "\tregister_branch(v1,v2,%d);\n", NATIVE_CC_CC); + break; + + case 8: failure; break; /* Work out details! FIXME */ + case 9: failure; break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\tmov_l_rr(nsrc,src);\n"); + comprintf("\tlea_l_brr(scratchie,src,(uae_s32)-1);\n" + "\tmov_w_rr(src,scratchie);\n"); + comprintf("\tcmov_l_rr(offs,PC_P,%d);\n", + cond_codes[curi->cc]); + comprintf("\tcmov_l_rr(src,nsrc,%d);\n", + cond_codes[curi->cc]); + /* OK, now for cc=true, we have src==nsrc and offs==PC_P, + so whether we move them around doesn't matter. However, + if cc=false, we have offs==jump_pc, and src==nsrc-1 */ + + comprintf("\t start_needflags();\n"); + comprintf("\ttest_w_rr(nsrc,nsrc);\n"); + comprintf("\t end_needflags();\n"); + comprintf("\tcmov_l_rr(PC_P,offs,%d);\n", NATIVE_CC_NE); + break; + default: assert(0); + } + genastore ("src", curi->smode, "srcreg", curi->size, "src"); + gen_update_next_handler(); + break; + + case i_Scc: +#ifdef DISABLE_I_SCC + failure; +#endif + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace (); + comprintf ("\tint val = scratchie++;\n"); + + /* We set val to 0 if we really should use 255, and to 1 for real 0 */ + switch(curi->cc) { + case 0: /* Unconditional set */ + comprintf("\tmov_l_ri(val,0);\n"); + break; + case 1: + /* Unconditional not-set */ + comprintf("\tmov_l_ri(val,1);\n"); + break; + case 8: failure; break; /* Work out details! FIXME */ + case 9: failure; break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + /* All condition codes can be inverted by changing the LSB */ + comprintf("\tsetcc(val,%d);\n", + cond_codes[curi->cc]^1); break; + default: assert(0); + } + comprintf("\tsub_b_ri(val,1);\n"); + genastore ("val", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_DIVU: + isjump; + failure; + break; + + case i_DIVS: + isjump; + failure; + break; + + case i_MULU: +#ifdef DISABLE_I_MULU + failure; +#endif + comprintf("\tdont_care_flags();\n"); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + /* To do 16x16 unsigned multiplication, we actually use + 32x32 signed, and zero-extend the registers first. + That solves the problem of MUL needing dedicated registers + on the x86 */ + comprintf("\tzero_extend_16_rr(scratchie,src);\n" + "\tzero_extend_16_rr(dst,dst);\n" + "\timul_32_32(dst,scratchie);\n"); + genflags (flag_logical, sz_long, "dst", "", ""); + genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); + break; + + case i_MULS: +#ifdef DISABLE_I_MULS + failure; +#endif + comprintf("\tdont_care_flags();\n"); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + comprintf("\tsign_extend_16_rr(scratchie,src);\n" + "\tsign_extend_16_rr(dst,dst);\n" + "\timul_32_32(dst,scratchie);\n"); + genflags (flag_logical, sz_long, "dst", "", ""); + genastore ("dst", curi->dmode, "dstreg", sz_long, "dst"); + break; + + case i_CHK: + isjump; + failure; + break; + + case i_CHK2: + isjump; + failure; + break; + + case i_ASR: +#ifdef DISABLE_I_ASR + failure; +#endif + mayfail; + if (curi->smode==Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode!=immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint width;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n" + "\tint highshift=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(data,cnt);\n" + "\thighmask=0x38;\n" + "\twidth=8;\n"); + break; + case sz_word: comprintf("\tshra_w_rr(data,cnt);\n" + "\thighmask=0x30;\n" + "\twidth=16;\n"); + break; + case sz_long: comprintf("\tshra_l_rr(data,cnt);\n" + "\thighmask=0x20;\n" + "\twidth=32;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(highshift,0);\n" + "mov_l_ri(scratchie,width/2);\n" + "cmov_l_rr(highshift,scratchie,%d);\n", NATIVE_CC_NE); + /* The x86 masks out bits, so we now make sure that things + really get shifted as much as planned */ + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; + case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; + case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; + default: assert(0); + } + /* And again */ + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; + case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; + case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; + default: assert(0); + } + + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(cdata,tmpcnt);\n");break; + case sz_word: comprintf("\tshra_w_rr(cdata,tmpcnt);\n");break; + case sz_long: comprintf("\tshra_l_rr(cdata,tmpcnt);\n");break; + default: assert(0); + } + /* If the shift count was higher than the width, we need + to pick up the sign from data */ + comprintf("test_l_ri(tmpcnt,highmask);\n" + "cmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint width;\n" + "\tint highshift=scratchie++;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(data,cnt);\n" + "\thighmask=0x38;\n" + "\twidth=8;\n"); + break; + case sz_word: comprintf("\tshra_w_rr(data,cnt);\n" + "\thighmask=0x30;\n" + "\twidth=16;\n"); + break; + case sz_long: comprintf("\tshra_l_rr(data,cnt);\n" + "\thighmask=0x20;\n" + "\twidth=32;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(highshift,0);\n" + "mov_l_ri(scratchie,width/2);\n" + "cmov_l_rr(highshift,scratchie,%d);\n",NATIVE_CC_NE); + /* The x86 masks out bits, so we now make sure that things + really get shifted as much as planned */ + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; + case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; + case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; + default: assert(0); + } + /* And again */ + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; + case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; + case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; + default: assert(0); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + } + else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshra_b_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); break; + case sz_word: comprintf("\tshra_w_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); break; + case sz_long: comprintf("\tshra_l_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); break; + default: assert(0); + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + break; + + case i_ASL: +#ifdef DISABLE_I_ASL + failure; +#endif + mayfail; + if (curi->smode==Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + /* Except for the handling of the V flag, this is identical to + LSL. The handling of V is, uhm, unpleasant, so if it's needed, + let the normal emulation handle it. Shoulders of giants kinda + thing ;-) */ + comprintf("if (needed_flags & FLAG_V) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode!=immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n",NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); + switch(curi->size) { + case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; + case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; + case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; + default: assert(0); + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break; + case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break; + case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break; + default: assert(0); + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n",NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,7);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,15);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,31);\n"); break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); + switch(curi->size) { + case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; + case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; + case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; + default: assert(0); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + } + else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n" + "\tbp=8-srcreg;\n"); break; + case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n" + "\tbp=16-srcreg;\n"); break; + case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n" + "\tbp=32-srcreg;\n"); break; + default: assert(0); + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + break; + + case i_LSR: +#ifdef DISABLE_I_LSR + failure; +#endif + mayfail; + if (curi->smode==Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode!=immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n",NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch(curi->size) { + case sz_byte: comprintf("\tshrl_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: comprintf("\tshrl_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); + switch(curi->size) { + case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; + case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; + case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; + default: assert(0); + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshrl_b_rr(cdata,tmpcnt);\n");break; + case sz_word: comprintf("\tshrl_w_rr(cdata,tmpcnt);\n");break; + case sz_long: comprintf("\tshrl_l_rr(cdata,tmpcnt);\n");break; + default: assert(0); + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n",NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshrl_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: comprintf("\tshrl_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); + switch(curi->size) { + case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; + case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; + case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; + default: assert(0); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + } + else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshrl_b_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); break; + case sz_word: comprintf("\tshrl_w_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); break; + case sz_long: comprintf("\tshrl_l_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); break; + default: assert(0); + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + break; + + case i_LSL: +#ifdef DISABLE_I_LSL + failure; +#endif + mayfail; + if (curi->smode==Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode!=immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n",NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); + switch(curi->size) { + case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; + case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; + case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; + default: assert(0); + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break; + case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break; + case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break; + default: assert(0); + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n",NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,7);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,15);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,31);\n"); break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: assert(0); + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); + switch(curi->size) { + case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; + case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; + case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; + default: assert(0); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + } + else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch(curi->size) { + case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n" + "\tbp=8-srcreg;\n"); break; + case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n" + "\tbp=16-srcreg;\n"); break; + case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n" + "\tbp=32-srcreg;\n"); break; + default: assert(0); + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + } + break; + + case i_ROL: +#ifdef DISABLE_I_ROL + failure; +#endif + mayfail; + if (curi->smode==Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace (); + + switch(curi->size) { + case sz_long: comprintf("\t rol_l_rr(data,cnt);\n"); break; + case sz_word: comprintf("\t rol_w_rr(data,cnt);\n"); break; + case sz_byte: comprintf("\t rol_b_rr(data,cnt);\n"); break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + comprintf("\t bt_l_ri(data,0x00);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + break; + + case i_ROR: +#ifdef DISABLE_I_ROR + failure; +#endif + mayfail; + if (curi->smode==Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace (); + + switch(curi->size) { + case sz_long: comprintf("\t ror_l_rr(data,cnt);\n"); break; + case sz_word: comprintf("\t ror_w_rr(data,cnt);\n"); break; + case sz_byte: comprintf("\t ror_b_rr(data,cnt);\n"); break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch(curi->size) { + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + } + switch(curi->size) { + case sz_byte: comprintf("\t bt_l_ri(data,0x07);\n"); break; + case sz_word: comprintf("\t bt_l_ri(data,0x0f);\n"); break; + case sz_long: comprintf("\t bt_l_ri(data,0x1f);\n"); break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); + break; + + case i_ROXL: + failure; + break; + + case i_ROXR: + failure; + break; + + case i_ASRW: + failure; + break; + + case i_ASLW: + failure; + break; + + case i_LSRW: + failure; + break; + + case i_LSLW: + failure; + break; + + case i_ROLW: + failure; + break; + + case i_RORW: + failure; + break; + + case i_ROXLW: + failure; + break; + + case i_ROXRW: + failure; + break; + + case i_MOVEC2: + isjump; + failure; + break; + + case i_MOVE2C: + isjump; + failure; + break; + + case i_CAS: + failure; + break; + + case i_CAS2: + failure; + break; + + case i_MOVES: /* ignore DFC and SFC because we have no MMU */ + isjump; + failure; + break; + + case i_BKPT: /* only needed for hardware emulators */ + isjump; + failure; + break; + + case i_CALLM: /* not present in 68030 */ + isjump; + failure; + break; + + case i_RTM: /* not present in 68030 */ + isjump; + failure; + break; + + case i_TRAPcc: + isjump; + failure; + break; + + case i_DIVL: + isjump; + failure; + break; + + case i_MULL: +#ifdef DISABLE_I_MULL + failure; +#endif + if (!noflags) { + failure; + break; + } + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + comprintf("\tint r2=(extra>>12)&7;\n" + "\tint tmp=scratchie++;\n"); + + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + /* The two operands are in dst and r2 */ + comprintf("\tif (extra&0x0400) {\n" /* Need full 64 bit result */ + "\tint r3=(extra&7);\n" + "\tmov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\tif (extra&0x0800) { \n" /* signed */ + "\t\timul_64_32(r2,r3);\n" + "\t} else { \n" + "\t\tmul_64_32(r2,r3);\n" + "\t} \n"); + /* The result is in r2/tmp, with r2 holding the lower 32 bits */ + comprintf("\t} else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result foes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\timul_32_32(r2,dst);\n" + "\t}\n"); + break; + + case i_BFTST: + case i_BFEXTU: + case i_BFCHG: + case i_BFEXTS: + case i_BFCLR: + case i_BFFFO: + case i_BFSET: + case i_BFINS: + failure; + break; + + case i_PACK: + failure; + break; + + case i_UNPK: + failure; + break; + + case i_TAS: + failure; + break; + + case i_FPP: +#ifdef DISABLE_I_FPP + failure; +#endif + uses_fpu; + mayfail; + comprintf("#ifdef USE_JIT_FPU\n"); + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + swap_opcode(); + comprintf("\tcomp_fpp_opp(opcode,extra);\n"); + comprintf("#else\n"); + comprintf("\tfailure = 1;\n"); + comprintf("#endif\n"); + break; + + case i_FBcc: +#ifdef DISABLE_I_FBCC + failure; +#endif + uses_fpu; + isjump; + uses_cmov; + mayfail; + comprintf("#ifdef USE_JIT_FPU\n"); + swap_opcode(); + comprintf("\tcomp_fbcc_opp(opcode);\n"); + comprintf("#else\n"); + comprintf("\tfailure = 1;\n"); + comprintf("#endif\n"); + break; + + case i_FDBcc: + uses_fpu; + isjump; + failure; + break; + + case i_FScc: +#ifdef DISABLE_I_FSCC + failure; +#endif + uses_fpu; + mayfail; + uses_cmov; + comprintf("#ifdef USE_JIT_FPU\n"); + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + swap_opcode(); + comprintf("\tcomp_fscc_opp(opcode,extra);\n"); + comprintf("#else\n"); + comprintf("\tfailure = 1;\n"); + comprintf("#endif\n"); + break; + + case i_FTRAPcc: + uses_fpu; + isjump; + failure; + break; + + case i_FSAVE: + uses_fpu; + failure; + break; + + case i_FRESTORE: + uses_fpu; + failure; + break; + + case i_CINVL: + case i_CINVP: + case i_CINVA: + isjump; /* Not really, but it's probably a good idea to stop + translating at this point */ + failure; + comprintf ("\tflush_icache();\n"); /* Differentiate a bit more? */ + break; + + case i_CPUSHL: + case i_CPUSHP: + case i_CPUSHA: + isjump; /* Not really, but it's probably a good idea to stop + translating at this point */ + failure; + break; + + case i_MOVE16: +#ifdef DISABLE_I_MOVE16 + failure; +#endif + genmov16(opcode,curi); + break; + +#ifdef UAE + case i_MMUOP030: + case i_PFLUSHN: + case i_PFLUSH: + case i_PFLUSHAN: + case i_PFLUSHA: + case i_PLPAR: + case i_PLPAW: + case i_PTESTR: + case i_PTESTW: + case i_LPSTOP: + isjump; + failure; + break; +#endif + +#ifdef WINUAE_ARANYM + case i_EMULOP_RETURN: + isjump; + failure; + break; + + case i_EMULOP: + failure; + break; + + case i_NATFEAT_ID: + case i_NATFEAT_CALL: + failure; + break; + + case i_MMUOP: + isjump; + failure; + break; +#endif + + default: + assert(0); + break; + } + comprintf("%s",endstr); + finish_braces (); + sync_m68k_pc (); + if (global_mayfail) + comprintf("\tif (failure) m68k_pc_offset=m68k_pc_offset_thisinst;\n"); + return global_failure; +} + +static void +generate_includes (FILE * f) +{ + fprintf (f, "#include \"sysconfig.h\"\n"); + fprintf (f, "#if defined(JIT)\n"); + fprintf (f, "#include \"sysdeps.h\"\n"); +#ifdef UAE + fprintf (f, "#include \"options.h\"\n"); + fprintf (f, "#include \"memory.h\"\n"); +#else + fprintf (f, "#include \"m68k.h\"\n"); + fprintf (f, "#include \"memory.h\"\n"); +#endif + fprintf (f, "#include \"readcpu.h\"\n"); + fprintf (f, "#include \"newcpu.h\"\n"); + fprintf (f, "#include \"comptbl.h\"\n"); + fprintf (f, "#include \"debug.h\"\n"); +} + +static int postfix; + + +#ifdef UAE +static char *decodeEA (amodes mode, wordsizes size) +{ + static char buffer[80]; + + buffer[0] = 0; + switch (mode){ + case Dreg: + strcpy (buffer,"Dn"); + break; + case Areg: + strcpy (buffer,"An"); + break; + case Aind: + strcpy (buffer,"(An)"); + break; + case Aipi: + strcpy (buffer,"(An)+"); + break; + case Apdi: + strcpy (buffer,"-(An)"); + break; + case Ad16: + strcpy (buffer,"(d16,An)"); + break; + case Ad8r: + strcpy (buffer,"(d8,An,Xn)"); + break; + case PC16: + strcpy (buffer,"(d16,PC)"); + break; + case PC8r: + strcpy (buffer,"(d8,PC,Xn)"); + break; + case absw: + strcpy (buffer,"(xxx).W"); + break; + case absl: + strcpy (buffer,"(xxx).L"); + break; + case imm: + switch (size){ + case sz_byte: + strcpy (buffer,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + break; + + default: + break; + } + return buffer; +} + +static char *outopcode (int opcode) +{ + static char out[100]; + struct instr *ins; + int i; + + ins = &table68k[opcode]; + for (i = 0; lookuptab[i].name[0]; i++) { + if (ins->mnemo == lookuptab[i].mnemo) + break; + } + { + char *s = ua (lookuptab[i].name); + strcpy (out, s); + xfree (s); + } + if (ins->smode == immi) + strcat (out, "Q"); + if (ins->size == sz_byte) + strcat (out,".B"); + if (ins->size == sz_word) + strcat (out,".W"); + if (ins->size == sz_long) + strcat (out,".L"); + strcat (out," "); + if (ins->suse) + strcat (out, decodeEA (ins->smode, ins->size)); + if (ins->duse) { + if (ins->suse) strcat (out,","); + strcat (out, decodeEA (ins->dmode, ins->size)); + } + return out; +} +#endif + + +static void +generate_one_opcode (int rp, int noflags) +{ + int i; + uae_u16 smsk, dmsk; + unsigned int opcode = opcode_map[rp]; + int aborted=0; + int have_srcreg=0; + int have_dstreg=0; +#ifdef UAE + char *name; +#else + const char *name; +#endif + + if (table68k[opcode].mnemo == i_ILLG + || table68k[opcode].clev > cpu_level) + return; + + for (i = 0; lookuptab[i].name[0]; i++) + { + if (table68k[opcode].mnemo == lookuptab[i].mnemo) + break; + } + + if (table68k[opcode].handler != -1) + return; + + switch (table68k[opcode].stype) + { + case 0: + smsk = 7; + break; + case 1: + smsk = 255; + break; + case 2: + smsk = 15; + break; + case 3: + smsk = 7; + break; + case 4: + smsk = 7; + break; + case 5: + smsk = 63; + break; +#ifndef UAE + case 6: + smsk = 255; + break; +#endif + case 7: + smsk = 3; + break; + default: + smsk = 0; + assert(0); + } + dmsk = 7; + + next_cpu_level = -1; + if (table68k[opcode].suse + && table68k[opcode].smode != imm && table68k[opcode].smode != imm0 + && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2 + && table68k[opcode].smode != absw && table68k[opcode].smode != absl + && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16) + { + have_srcreg=1; + if (table68k[opcode].spos == -1) + { + if (((int) table68k[opcode].sreg) >= 128) + comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg); + else + comprintf ("\tuae_s32 srcreg = %d;\n", (int) table68k[opcode].sreg); + } + else + { + char source[100]; + int pos = table68k[opcode].spos; + +#ifndef UAE + comprintf ("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + + if (pos < 8 && (smsk >> (8 - pos)) != 0) + sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk); + else + sprintf (source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + comprintf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + comprintf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + comprintf ("\tuae_u32 srcreg = %s;\n", source); + + comprintf ("#else\n"); +#endif + + if (pos) + sprintf (source, "((opcode >> %d) & %d)", pos, smsk); + else + sprintf (source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + comprintf ("\tuae_s32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + comprintf ("\tuae_s32 srcreg = %s;\n", source); + +#ifndef UAE + comprintf ("#endif\n"); +#endif + } + } + if (table68k[opcode].duse + /* Yes, the dmode can be imm, in case of LINK or DBcc */ + && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0 + && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2 + && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl) + { + have_dstreg=1; + if (table68k[opcode].dpos == -1) + { + if (((int) table68k[opcode].dreg) >= 128) + comprintf ("\tuae_s32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg); + else + comprintf ("\tuae_s32 dstreg = %d;\n", (int) table68k[opcode].dreg); + } + else + { + int pos = table68k[opcode].dpos; + +#ifndef UAE + comprintf ("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + + if (pos < 8 && (dmsk >> (8 - pos)) != 0) + comprintf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", + pos ^ 8, dmsk); + else + comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + comprintf ("#else\n"); +#endif + + if (pos) + comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", + pos, dmsk); + else + comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + +#ifndef UAE + comprintf ("#endif\n"); +#endif + } + } + + if (have_srcreg && have_dstreg && + (table68k[opcode].dmode==Areg || + table68k[opcode].dmode==Aind || + table68k[opcode].dmode==Aipi || + table68k[opcode].dmode==Apdi || + table68k[opcode].dmode==Ad16 || + table68k[opcode].dmode==Ad8r) && + (table68k[opcode].smode==Areg || + table68k[opcode].smode==Aind || + table68k[opcode].smode==Aipi || + table68k[opcode].smode==Apdi || + table68k[opcode].smode==Ad16 || + table68k[opcode].smode==Ad8r) + ) { + comprintf("\tuae_u32 dodgy=(srcreg==(uae_s32)dstreg);\n"); + } + else { + comprintf("\tuae_u32 dodgy=0;\n"); + } + comprintf("\tuae_u32 m68k_pc_offset_thisinst=m68k_pc_offset;\n"); + comprintf("\tm68k_pc_offset+=2;\n"); + + aborted=gen_opcode (opcode); + { + char flags[64 * 6]; + *flags = '\0'; + if (global_isjump) strcat(flags, "COMP_OPCODE_ISJUMP|"); + if (long_opcode) strcat(flags, "COMP_OPCODE_LONG_OPCODE|"); + if (global_cmov) strcat(flags, "COMP_OPCODE_CMOV|"); + if (global_isaddx) strcat(flags, "COMP_OPCODE_ISADDX|"); + if (global_iscjump) strcat(flags, "COMP_OPCODE_ISCJUMP|"); + if (global_fpu) strcat(flags, "COMP_OPCODE_USES_FPU|"); + if (*flags) + flags[strlen(flags) - 1] = '\0'; + else + strcpy(flags, "0"); + +#ifdef UAE + comprintf ("return 0;\n"); +#endif + comprintf ("}\n"); + +#ifdef UAE + name = ua (lookuptab[i].name); +#else + name = lookuptab[i].name; +#endif + if (aborted) { + fprintf (stblfile, "{ NULL, %u, %s }, /* %s */\n", opcode, flags, name); + com_discard(); + } else { + const char *tbl = noflags ? "nf" : "ff"; +#ifdef UAE + printf ("/* %s */\n", outopcode (opcode)); +#else + printf ("/* %s */\n", name); +#endif + fprintf (stblfile, "{ op_%x_%d_comp_%s, %u, %s }, /* %s */\n", opcode, postfix, tbl, opcode, flags, name); + fprintf (headerfile, "extern compop_func op_%x_%d_comp_%s;\n", opcode, postfix, tbl); + printf (RETTYPE " REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode)\n{\n", opcode, postfix, tbl); + com_flush(); + } +#ifdef UAE + xfree (name); +#endif + } + opcode_next_clev[rp] = next_cpu_level; + opcode_last_postfix[rp] = postfix; +} + +static void +generate_func (int noflags) +{ + int i, j, rp; + const char *tbl = noflags ? "nf" : "ff"; + + using_prefetch = 0; + using_exception_3 = 0; + for (i = 0; i < 1; i++) /* We only do one level! */ + { + cpu_level = NEXT_CPU_LEVEL - i; + postfix = i; + + fprintf (stblfile, "const struct comptbl op_smalltbl_%d_comp_%s[] = {\n", postfix, tbl); + + /* sam: this is for people with low memory (eg. me :)) */ + printf ("\n" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" + "\n" + "#define PART_1 1\n" + "#define PART_2 1\n" + "#define PART_3 1\n" + "#define PART_4 1\n" + "#define PART_5 1\n" + "#define PART_6 1\n" + "#define PART_7 1\n" + "#define PART_8 1\n" + "#endif\n\n"); +#ifdef UAE + printf ("extern void comp_fpp_opp();\n" + "extern void comp_fscc_opp();\n" + "extern void comp_fbcc_opp();\n\n"); +#endif + + rp = 0; + for (j = 1; j <= 8; ++j) + { + int k = (j * nr_cpuop_funcs) / 8; + printf ("#ifdef PART_%d\n", j); + for (; rp < k; rp++) + generate_one_opcode (rp,noflags); + printf ("#endif\n\n"); + } + + fprintf (stblfile, "{ 0, 65536, 0 }};\n"); + } + +} + +#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) +void cygwin_mingw_abort() +{ +#undef abort + abort(); +} +#endif + +int main(void) +{ + read_table68k (); + do_merges (); + + opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs); + opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs); + opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs); + counts = (unsigned long *) malloc (65536 * sizeof (unsigned long)); + read_counts (); + + /* It would be a lot nicer to put all in one file (we'd also get rid of + * cputbl.h that way), but cpuopti can't cope. That could be fixed, but + * I don't dare to touch the 68k version. */ + + headerfile = fopen (GEN_PATH "comptbl.h", "wb"); + fprintf (headerfile, "" + "extern const struct comptbl op_smalltbl_0_comp_nf[];\n" + "extern const struct comptbl op_smalltbl_0_comp_ff[];\n" + ""); + + stblfile = fopen (GEN_PATH "compstbl.cpp", "wb"); + if (freopen (GEN_PATH "compemu.cpp", "wb", stdout) == NULL) { + abort(); + } + + generate_includes (stdout); + generate_includes (stblfile); + + printf("#include \"" JIT_PATH "compemu.h\"\n"); + + noflags=0; + generate_func (noflags); + + free(opcode_map); + free(opcode_last_postfix); + free(opcode_next_clev); + free(counts); + + opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs); + opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs); + opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs); + counts = (unsigned long *) malloc (65536 * sizeof (unsigned long)); + read_counts (); + noflags=1; + generate_func (noflags); + + printf ("#endif\n"); + fprintf (stblfile, "#endif\n"); + + free(opcode_map); + free(opcode_last_postfix); + free(opcode_next_clev); + free(counts); + + free (table68k); + fclose (stblfile); + fclose (headerfile); + return 0; +} + +#ifdef UAE +void write_log (const TCHAR *format,...) +{ +} +#endif diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c new file mode 100644 index 00000000..13e2776e --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c @@ -0,0 +1,4981 @@ +/* + * compiler/gencomp_arm2.c - MC680x0 compilation generator (ARM Adaption JIT v1 & JIT v2) + * + * Based on work Copyright 1995, 1996 Bernd Schmidt + * Changes for UAE-JIT Copyright 2000 Bernd Meyer + * + * Adaptation for ARAnyM/ARM, copyright 2001-2015 + * Milan Jurik, Jens Heitmann + * + * Basilisk II (C) 1997-2005 Christian Bauer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Notes + * ===== + * + * Advantages of JIT v2 + * - Processor independent style + * - Reduced overhead + * - Easier to understand / read + * - Easier to optimize + * - More precise flag handling + * - Better optimization for different CPU version ARM, ARMv6 etc.. + * + * Disadvantages of JIT v2 + * - Less generated + * - Requires more code implementation by hand (MidFunc) + * - MIDFUNCS are more CPU minded (closer to raw) + * - Separate code for each instruction (but this could be also an advantage, because you can concentrate on it) + * + * Additional note: + * - current using jnf_xxx calls for non-flag operations and + * jff_xxx for flag operations + * + * Still todo: + * - Optimize genamode, genastore, gen_writeXXX, gen_readXXX, genmovemXXX + * + */ + +#define CC_FOR_BUILD 1 +#include "sysconfig.h" + +#include "sysdeps.h" +#include "readcpu.h" + +#include +#include +#include +#include +#include +#include +#undef abort + +#define BOOL_TYPE "int" +#define failure global_failure=1 +#define FAILURE global_failure=1 +#define isjump global_isjump=1 +#define is_const_jump global_iscjump=1 +#define isaddx global_isaddx=1 +#define uses_cmov global_cmov=1 +#define mayfail global_mayfail=1 +#define uses_fpu global_fpu=1 + +int hack_opcode; + +static int global_failure; +static int global_isjump; +static int global_iscjump; +static int global_isaddx; +static int global_cmov; +static int long_opcode; +static int global_mayfail; +static int global_fpu; + +static char endstr[1000]; +static char lines[100000]; +static int comp_index = 0; + +#include "flags_arm.h" + +#ifndef __attribute__ +# ifndef __GNUC__ +# define __attribute__(x) +# endif +#endif + + +static int cond_codes[] = { // + NATIVE_CC_AL, -1, // + NATIVE_CC_HI, NATIVE_CC_LS, // + NATIVE_CC_CC, NATIVE_CC_CS, // + NATIVE_CC_NE, NATIVE_CC_EQ, // + NATIVE_CC_VC, NATIVE_CC_VS, // + NATIVE_CC_PL, NATIVE_CC_MI, // + NATIVE_CC_GE, NATIVE_CC_LT, // + NATIVE_CC_GT, NATIVE_CC_LE // + }; + +__attribute__((format(printf, 1, 2))) +static void comprintf(const char *format, ...) +{ + va_list args; + + va_start(args, format); + comp_index += vsprintf(lines + comp_index, format, args); + va_end(args); +} + +static void com_discard(void) +{ + comp_index = 0; +} + +static void com_flush(void) +{ + int i; + for (i = 0; i < comp_index; i++) + putchar(lines[i]); + com_discard(); +} + + +static FILE *headerfile; +static FILE *stblfile; + +static int using_prefetch; +static int using_exception_3; +static int cpu_level; +static int noflags; + +/* For the current opcode, the next lower level that will have different code. + * Initialized to -1 for each opcode. If it remains unchanged, indicates we + * are done with that opcode. */ +static int next_cpu_level; + +static int *opcode_map; +static int *opcode_next_clev; +static int *opcode_last_postfix; +static unsigned long *counts; + +static void read_counts(void) +{ + FILE *file; + unsigned long opcode, count, total; + char name[20]; + int nr = 0; + memset(counts, 0, 65536 * sizeof *counts); + + file = fopen("frequent.68k", "r"); + if (file) { + if (fscanf(file, "Total: %lu\n", &total) != 1) + { + assert(0); + } + while (fscanf(file, "%lx: %lu %s\n", &opcode, &count, name) == 3) { + opcode_next_clev[nr] = 4; + opcode_last_postfix[nr] = -1; + opcode_map[nr++] = opcode; + counts[opcode] = count; + } + fclose(file); + } + if (nr == nr_cpuop_funcs) + return; + for (opcode = 0; opcode < 0x10000; opcode++) { + if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG + && counts[opcode] == 0) { + opcode_next_clev[nr] = 4; + opcode_last_postfix[nr] = -1; + opcode_map[nr++] = opcode; + counts[opcode] = count; + } + } + assert (nr == nr_cpuop_funcs); +} + +static int n_braces = 0; +static int insn_n_cycles; + +static void start_brace(void) { + n_braces++; + comprintf("{"); +} + +static void close_brace(void) { + assert(n_braces > 0); + n_braces--; + comprintf("}"); +} + +static void finish_braces(void) { + while (n_braces > 0) + close_brace(); +} + +static inline void gen_update_next_handler(void) { + return; /* Can anything clever be done here? */ +} + +static void gen_writebyte(const char *address, const char *source) +{ + comprintf("\twritebyte(%s, %s, scratchie);\n", address, source); +} + +static void gen_writeword(const char *address, const char *source) +{ + comprintf("\twriteword(%s, %s, scratchie);\n", address, source); +} + +static void gen_writelong(const char *address, const char *source) +{ + comprintf("\twritelong(%s, %s, scratchie);\n", address, source); +} + +static void gen_readbyte(const char *address, const char* dest) +{ + comprintf("\treadbyte(%s, %s, scratchie);\n", address, dest); +} + +static void gen_readword(const char *address, const char *dest) +{ + comprintf("\treadword(%s,%s,scratchie);\n", address, dest); +} + +static void gen_readlong(const char *address, const char *dest) +{ + comprintf("\treadlong(%s, %s, scratchie);\n", address, dest); +} + +static const char * +gen_nextilong(void) { + static char buffer[80]; + + sprintf(buffer, "comp_get_ilong((m68k_pc_offset+=4)-4)"); + insn_n_cycles += 4; + + long_opcode = 1; + return buffer; +} + +static const char * +gen_nextiword(void) { + static char buffer[80]; + + sprintf(buffer, "comp_get_iword((m68k_pc_offset+=2)-2)"); + insn_n_cycles += 2; + + long_opcode = 1; + return buffer; +} + +static const char * +gen_nextibyte(void) { + static char buffer[80]; + + sprintf(buffer, "comp_get_ibyte((m68k_pc_offset+=2)-2)"); + insn_n_cycles += 2; + + long_opcode = 1; + return buffer; +} + +#if defined(USE_JIT_FPU) +// Only used by FPU (future), get rid of unused warning +static void +swap_opcode (void) +{ + comprintf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + comprintf("\topcode = do_byteswap_16(opcode);\n"); + comprintf("#endif\n"); +} +#endif + +static void sync_m68k_pc(void) { + comprintf("\t if (m68k_pc_offset>SYNC_PC_OFFSET) sync_m68k_pc();\n"); +} + +/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, + * the calling routine handles Apdi and Aipi modes. + * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ +static void genamode(amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem) +{ + start_brace(); + switch (mode) + { + case Dreg: /* Do we need to check dodgy here? */ + assert (!movem); + if (getv == 1 || getv == 2) + { + /* We generate the variable even for getv==2, so we can use + it as a destination for MOVE */ + comprintf("\tint %s = %s;\n", name, reg); + } + return; + + case Areg: + assert (!movem); + if (getv == 1 || getv == 2) + { + /* see above */ + comprintf("\tint %s = dodgy ? scratchie++ : %s + 8;\n", name, reg); + if (getv == 1) + { + comprintf("\tif (dodgy) \n"); + comprintf("\t\tmov_l_rr(%s, %s + 8);\n", name, reg); + } + } + return; + + case Aind: + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, %s + 8);\n", name, reg); + break; + case Aipi: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_rr(%sa, %s + 8);\n", name, reg); + break; + case Apdi: + switch (size) + { + case sz_byte: + if (movem) + { + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, (uae_s32)-areg_byteinc[%s]);\n", reg, reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + case sz_word: + if (movem) + { + comprintf("\tint %sa=dodgy?scratchie++:%s+8;\n", name, reg); + comprintf("\tif (dodgy) \n"); + comprintf("\tmov_l_rr(%sa,8+%s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, -2);\n", reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + case sz_long: + if (movem) + { + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } else + { + start_brace(); + comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); + comprintf("\tlea_l_brr(%s + 8, %s + 8, -4);\n", reg, reg); + comprintf("\tif (dodgy)\n"); + comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + } + break; + default: + assert(0); + break; + } + break; + case Ad16: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_rr(%sa, 8 + %s);\n", name, reg); + comprintf("\tlea_l_brr(%sa, %sa, (uae_s32)(uae_s16)%s);\n", name, name, gen_nextiword()); + break; + case Ad8r: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tcalc_disp_ea_020(%s + 8, %s, %sa, scratchie);\n", reg, gen_nextiword(), name); + break; + + case PC16: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n"); + comprintf("\tuae_s32 PC16off = (uae_s32)(uae_s16)%s;\n", gen_nextiword()); + comprintf("\tmov_l_ri(%sa, address + PC16off);\n", name); + break; + + case PC8r: + comprintf("\tint pctmp = scratchie++;\n"); + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n"); + start_brace(); + comprintf("\tmov_l_ri(pctmp,address);\n"); + + comprintf("\tcalc_disp_ea_020(pctmp, %s, %sa, scratchie);\n", gen_nextiword(), name); + break; + case absw: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_ri(%sa, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + break; + case absl: + comprintf("\tint %sa = scratchie++;\n", name); + comprintf("\tmov_l_ri(%sa, %s); /* absl */\n", name, gen_nextilong()); + break; + case imm: + assert (getv == 1); + switch (size) + { + case sz_byte: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte()); + break; + case sz_word: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + break; + case sz_long: + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); + break; + default: + assert(0); + break; + } + return; + case imm0: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte()); + return; + case imm1: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); + return; + case imm2: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); + return; + case immi: + assert (getv == 1); + comprintf("\tint %s = scratchie++;\n", name); + comprintf("\tmov_l_ri(%s, %s);\n", name, reg); + return; + default: + assert(0); + break; + } + + /* We get here for all non-reg non-immediate addressing modes to + * actually fetch the value. */ + if (getv == 1) + { + char astring[80]; + sprintf(astring, "%sa", name); + switch (size) + { + case sz_byte: + insn_n_cycles += 2; + break; + case sz_word: + insn_n_cycles += 2; + break; + case sz_long: + insn_n_cycles += 4; + break; + default: + assert(0); + break; + } + start_brace(); + comprintf("\tint %s = scratchie++;\n", name); + switch (size) + { + case sz_byte: + gen_readbyte(astring, name); + break; + case sz_word: + gen_readword(astring, name); + break; + case sz_long: + gen_readlong(astring, name); + break; + default: + assert(0); + break; + } + } + + /* We now might have to fix up the register for pre-dec or post-inc + * addressing modes. */ + if (!movem) + { + switch (mode) + { + case Aipi: + switch (size) + { + case sz_byte: + comprintf("\tlea_l_brr(%s + 8,%s + 8, areg_byteinc[%s]);\n", reg, reg, reg); + break; + case sz_word: + comprintf("\tlea_l_brr(%s + 8, %s + 8, 2);\n", reg, reg); + break; + case sz_long: + comprintf("\tlea_l_brr(%s + 8, %s + 8, 4);\n", reg, reg); + break; + default: + assert(0); + break; + } + break; + case Apdi: + break; + default: + break; + } + } +} + +static void genastore(const char *from, amodes mode, const char *reg, wordsizes size, const char *to) +{ + switch (mode) + { + case Dreg: + switch (size) + { + case sz_byte: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_b_rr(%s, %s);\n", reg, from); + break; + case sz_word: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_w_rr(%s, %s);\n", reg, from); + break; + case sz_long: + comprintf("\tif(%s != %s)\n", reg, from); + comprintf("\t\tmov_l_rr(%s, %s);\n", reg, from); + break; + default: + assert(0); + break; + } + break; + case Areg: + switch (size) + { + case sz_word: + comprintf("\tif(%s + 8 != %s)\n", reg, from); + comprintf("\t\tmov_w_rr(%s + 8, %s);\n", reg, from); + break; + case sz_long: + comprintf("\tif(%s + 8 != %s)\n", reg, from); + comprintf("\t\tmov_l_rr(%s + 8, %s);\n", reg, from); + break; + default: + assert(0); + break; + } + break; + + case Apdi: + case absw: + case PC16: + case PC8r: + case Ad16: + case Ad8r: + case Aipi: + case Aind: + case absl: + { + char astring[80]; + sprintf(astring, "%sa", to); + + switch (size) + { + case sz_byte: + insn_n_cycles += 2; + gen_writebyte(astring, from); + break; + case sz_word: + insn_n_cycles += 2; + gen_writeword(astring, from); + break; + case sz_long: + insn_n_cycles += 4; + gen_writelong(astring, from); + break; + default: + assert(0); + break; + } + } + break; + case imm: + case imm0: + case imm1: + case imm2: + case immi: + assert(0); + break; + default: + assert(0); + break; + } +} + +static void gen_move16(uae_u32 opcode, struct instr *curi) { +#if defined(USE_JIT2) + comprintf("\tint src=scratchie++;\n"); + comprintf("\tint dst=scratchie++;\n"); + + uae_u32 masked_op = (opcode & 0xfff8); + if (masked_op == 0xf620) { + // POSTINCREMENT SOURCE AND DESTINATION version + comprintf("\t uae_u16 dstreg = ((%s)>>12) & 0x07;\n", gen_nextiword()); + comprintf("\t jnf_MOVE(src, srcreg + 8);"); + comprintf("\t jnf_MOVE(dst, dstreg + 8);"); + comprintf("\t if (srcreg != dstreg)\n"); + comprintf("\t jnf_ADD_imm(srcreg + 8, srcreg + 8, 16);"); + comprintf("\t jnf_ADD_imm(dstreg + 8, dstreg + 8, 16);"); + } else { + /* Other variants */ + genamode(curi->smode, "srcreg", curi->size, "src", 0, 2); + genamode(curi->dmode, "dstreg", curi->size, "dst", 0, 2); + switch (masked_op) { + case 0xf600: + comprintf("\t jnf_ADD_imm(srcreg + 8, srcreg + 8, 16);"); + break; + case 0xf608: + comprintf("\t jnf_ADD_imm(dstreg + 8, dstreg + 8, 16);"); + break; + } + } + comprintf("\t jnf_MOVE16(dst, src);"); +#else + comprintf("\tint src=scratchie++;\n"); + comprintf("\tint dst=scratchie++;\n"); + + if ((opcode & 0xfff8) == 0xf620) { + /* MOVE16 (Ax)+,(Ay)+ */ + comprintf("\tuae_u16 dstreg=((%s)>>12)&0x07;\n", gen_nextiword()); + comprintf("\tmov_l_rr(src,8+srcreg);\n"); + comprintf("\tmov_l_rr(dst,8+dstreg);\n"); + } else { + /* Other variants */ + genamode(curi->smode, "srcreg", curi->size, "src", 0, 2); + genamode(curi->dmode, "dstreg", curi->size, "dst", 0, 2); + comprintf("\tmov_l_rr(src,srca);\n"); + comprintf("\tmov_l_rr(dst,dsta);\n"); + } + + /* Align on 16-byte boundaries */ + comprintf("\tand_l_ri(src,~15);\n"); + comprintf("\tand_l_ri(dst,~15);\n"); + + if ((opcode & 0xfff8) == 0xf620) { + comprintf("\tif (srcreg != dstreg)\n"); + comprintf("\tarm_ADD_l_ri8(srcreg+8,16);\n"); + comprintf("\tarm_ADD_l_ri8(dstreg+8,16);\n"); + } else if ((opcode & 0xfff8) == 0xf600) + comprintf("\tarm_ADD_l_ri8(srcreg+8,16);\n"); + else if ((opcode & 0xfff8) == 0xf608) + comprintf("\tarm_ADD_l_ri8(dstreg+8,16);\n"); + + comprintf("\tint tmp=scratchie;\n"); + comprintf("\tscratchie+=4;\n"); + + comprintf("\tget_n_addr(src,src,scratchie);\n" + "\tget_n_addr(dst,dst,scratchie);\n" + "\tmov_l_rR(tmp+0,src,0);\n" + "\tmov_l_rR(tmp+1,src,4);\n" + "\tmov_l_rR(tmp+2,src,8);\n" + "\tmov_l_rR(tmp+3,src,12);\n" + "\tmov_l_Rr(dst,tmp+0,0);\n" + "\tforget_about(tmp+0);\n" + "\tmov_l_Rr(dst,tmp+1,4);\n" + "\tforget_about(tmp+1);\n" + "\tmov_l_Rr(dst,tmp+2,8);\n" + "\tforget_about(tmp+2);\n" + "\tmov_l_Rr(dst,tmp+3,12);\n"); +#endif +} + +static void genmovemel(uae_u16 opcode) { + comprintf("\tuae_u16 mask = %s;\n", gen_nextiword()); + comprintf("\tint native=scratchie++;\n"); + comprintf("\tint i;\n"); + comprintf("\tsigned char offset=0;\n"); + genamode(table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, + 1); + comprintf("\tget_n_addr(srca,native,scratchie);\n"); + + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch (table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tmov_l_rR(i,native,offset);\n" + "\t\t\tmid_bswap_32(i);\n" + "\t\t\toffset+=4;\n"); + break; + case sz_word: + comprintf("\t\t\tmov_w_rR(i,native,offset);\n" + "\t\t\tmid_bswap_16(i);\n" + "\t\t\tsign_extend_16_rr(i,i);\n" + "\t\t\toffset+=2;\n"); + break; + default: + assert(0); + break; + } + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Aipi) { + comprintf("\t\t\tlea_l_brr(8+dstreg,srca,offset);\n"); + } +} + +static void genmovemle(uae_u16 opcode) { + comprintf("\tuae_u16 mask = %s;\n", gen_nextiword()); + comprintf("\tint native=scratchie++;\n"); + comprintf("\tint i;\n"); + comprintf("\tint tmp=scratchie++;\n"); + comprintf("\tsigned char offset=0;\n"); + genamode(table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, + 1); + + comprintf("\tget_n_addr(srca,native,scratchie);\n"); + + if (table68k[opcode].dmode != Apdi) { + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch (table68k[opcode].size) { + case sz_long: + comprintf("\t\t\tmov_l_rr(tmp,i);\n" + "\t\t\tmid_bswap_32(tmp);\n" + "\t\t\tmov_l_Rr(native,tmp,offset);\n" + "\t\t\toffset+=4;\n"); + break; + case sz_word: + comprintf("\t\t\tmov_l_rr(tmp,i);\n" + "\t\t\tmid_bswap_16(tmp);\n" + "\t\t\tmov_w_Rr(native,tmp,offset);\n" + "\t\t\toffset+=2;\n"); + break; + default: + assert(0); + break; + } + } else { /* Pre-decrement */ + comprintf("\tfor (i=0;i<16;i++) {\n" + "\t\tif ((mask>>i)&1) {\n"); + switch (table68k[opcode].size) { + case sz_long: + comprintf("\t\t\toffset-=4;\n" + "\t\t\tmov_l_rr(tmp,15-i);\n" + "\t\t\tmid_bswap_32(tmp);\n" + "\t\t\tmov_l_Rr(native,tmp,offset);\n"); + break; + case sz_word: + comprintf("\t\t\toffset-=2;\n" + "\t\t\tmov_l_rr(tmp,15-i);\n" + "\t\t\tmid_bswap_16(tmp);\n" + "\t\t\tmov_w_Rr(native,tmp,offset);\n"); + break; + default: + assert(0); + break; + } + } + + comprintf("\t\t}\n" + "\t}"); + if (table68k[opcode].dmode == Apdi) { + comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n"); + } +} + +static void duplicate_carry(void) { + comprintf("\tif (needed_flags&FLAG_X) duplicate_carry();\n"); +} + +typedef enum { + flag_logical_noclobber, + flag_logical, + flag_add, + flag_sub, + flag_cmp, + flag_addx, + flag_subx, + flag_zn, + flag_av, + flag_sv, + flag_and, + flag_or, + flag_eor, + flag_mov +} flagtypes; + +#if !defined(USE_JIT2) +static void genflags(flagtypes type, wordsizes size, const char *value, const char *src, const char *dst) +{ + if (noflags) { + switch (type) { + case flag_cmp: + comprintf("\tdont_care_flags();\n"); + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + return; + case flag_add: + case flag_sub: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_add: + op = "add"; + break; // nf + case flag_sub: + op = "sub"; + break; // nf + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n", op, dst, src); + break; + } + return; + } + break; + + case flag_and: + comprintf("\tdont_care_flags();\n"); + switch (size) { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n", src); + comprintf("\tor_l_ri(scratchie,0xffffff00);\n"); // nf + comprintf("\tarm_AND_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_AND_b(%s,%s);\n", dst, src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n", src); + comprintf("\tor_l_ri(scratchie,0xffff0000);\n"); // nf + comprintf("\tarm_AND_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_AND_w(%s,%s);\n", dst, src); + break; + case sz_long: + comprintf("\tarm_AND_l(%s,%s);\n", dst, src); + break; + } + return; + + case flag_mov: + comprintf("\tdont_care_flags();\n"); + switch (size) { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n", src); + comprintf("\tand_l_ri(%s,0xffffff00);\n", dst); // nf + comprintf("\tarm_ORR_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tmov_b_rr(%s,%s);\n", dst, src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n", src); + comprintf("\tand_l_ri(%s,0xffff0000);\n", dst); // nf + comprintf("\tarm_ORR_l(%s,scratchie);\n", dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tmov_w_rr(%s,%s);\n", dst, src); + break; + case sz_long: + comprintf("\tmov_l_rr(%s,%s);\n", dst, src); + break; + } + return; + + case flag_or: + case flag_eor: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + const char* op; + switch (type) { + case flag_or: + op = "ORR"; + break; // nf + case flag_eor: + op = "EOR"; + break; // nf + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_8_rr(scratchie,%s);\n", src); + comprintf("\tarm_%s_l(%s,scratchie);\n", op, dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("if (kill_rodent(dst)) {\n"); + comprintf("\tzero_extend_16_rr(scratchie,%s);\n", src); + comprintf("\tarm_%s_l(%s,scratchie);\n", op, dst); + comprintf("\tforget_about(scratchie);\n"); + comprintf("\t} else \n" + "\tarm_%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tarm_%s_l(%s,%s);\n", op, dst, src); + break; + } + close_brace(); + return; + } + + case flag_addx: + case flag_subx: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_addx: + op = "adc"; + break; + case flag_subx: + op = "sbb"; + break; + default: + assert(0); + break; + } + comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ + switch (size) { + case sz_byte: + comprintf("\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\t%s_l(%s,%s);\n", op, dst, src); + break; + } + return; + } + break; + default: + return; + } + } + + /* Need the flags, but possibly not all of them */ + switch (type) { + case flag_logical_noclobber: + failure; + /* fall through */ + + case flag_and: + case flag_or: + case flag_eor: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + const char* op; + switch (type) { + case flag_and: + op = "and"; + break; + case flag_or: + op = "or"; + break; + case flag_eor: + op = "xor"; + break; + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n", op, dst, src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + } + + case flag_mov: + comprintf("\tdont_care_flags();\n"); + start_brace(); + { + switch (size) { + case sz_byte: + comprintf("\tif (%s!=%s) {\n", src, dst); + comprintf("\tmov_b_ri(%s,0);\n" + "\tstart_needflags();\n", dst); + comprintf("\tor_b(%s,%s);\n", dst, src); + comprintf("\t} else {\n"); + comprintf("\tmov_b_rr(%s,%s);\n", dst, src); + comprintf("\ttest_b_rr(%s,%s);\n", dst, dst); + comprintf("\t}\n"); + break; + case sz_word: + comprintf("\tif (%s!=%s) {\n", src, dst); + comprintf("\tmov_w_ri(%s,0);\n" + "\tstart_needflags();\n", dst); + comprintf("\tor_w(%s,%s);\n", dst, src); + comprintf("\t} else {\n"); + comprintf("\tmov_w_rr(%s,%s);\n", dst, src); + comprintf("\ttest_w_rr(%s,%s);\n", dst, dst); + comprintf("\t}\n"); + break; + case sz_long: + comprintf("\tif (%s!=%s) {\n", src, dst); + comprintf("\tmov_l_ri(%s,0);\n" + "\tstart_needflags();\n", dst); + comprintf("\tor_l(%s,%s);\n", dst, src); + comprintf("\t} else {\n"); + comprintf("\tmov_l_rr(%s,%s);\n", dst, src); + comprintf("\ttest_l_rr(%s,%s);\n", dst, dst); + comprintf("\t}\n"); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + } + + case flag_logical: + comprintf("\tdont_care_flags();\n"); + start_brace(); + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\ttest_b_rr(%s,%s);\n", value, value); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\ttest_w_rr(%s,%s);\n", value, value); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\ttest_l_rr(%s,%s);\n", value, value); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + close_brace(); + return; + + case flag_add: + case flag_sub: + case flag_cmp: + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_add: + op = "add"; + break; + case flag_sub: + op = "sub"; + break; + case flag_cmp: + op = "cmp"; + break; + default: + assert(0); + break; + } + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n", op, dst, src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (type != flag_cmp) { + duplicate_carry(); + } + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + + return; + } + + case flag_addx: + case flag_subx: + uses_cmov; + comprintf("\tdont_care_flags();\n"); + { + const char* op; + switch (type) { + case flag_addx: + op = "adc"; + break; + case flag_subx: + op = "sbb"; + break; + default: + assert(0); + break; + } + start_brace(); + comprintf("\tint zero=scratchie++;\n" + "\tint one=scratchie++;\n" + "\tif (needed_flags&FLAG_Z) {\n" + "\tmov_l_ri(zero,0);\n" + "\tmov_l_ri(one,-1);\n" + "\tmake_flags_live();\n" + "\tcmov_l_rr(zero,one,%d);\n" + "\t}\n", NATIVE_CC_NE); + comprintf("\trestore_carry();\n"); /* Reload the X flag into C */ + switch (size) { + case sz_byte: + comprintf("\tstart_needflags();\n" + "\t%s_b(%s,%s);\n", op, dst, src); + break; + case sz_word: + comprintf("\tstart_needflags();\n" + "\t%s_w(%s,%s);\n", op, dst, src); + break; + case sz_long: + comprintf("\tstart_needflags();\n" + "\t%s_l(%s,%s);\n", op, dst, src); + break; + } + comprintf("\tlive_flags();\n"); + comprintf("\tif (needed_flags&FLAG_Z) {\n" + "\tcmov_l_rr(zero,one,%d);\n" + "\tset_zero(zero, one);\n" /* No longer need one */ + "\tlive_flags();\n" + "\t}\n", NATIVE_CC_NE); + comprintf("\tend_needflags();\n"); + duplicate_carry(); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + return; + } + default: + failure; + break; + } +} +#endif + +static void gen_abcd(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) curi; + (void) ssize; + failure; + /* No BCD maths for me.... */ +#endif +} + +static void gen_add(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + // Use tmp register to avoid destroying upper part in .B., .W cases + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ADD_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_ADD(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_add, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_adda(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\t jnf_ADDA_%s(dst, src);\n", ssize); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tsign_extend_8_rr(tmp,src);\n"); + break; + case sz_word: + comprintf("\tsign_extend_16_rr(tmp,src);\n"); + break; + case sz_long: + comprintf("\ttmp=src;\n"); + break; + default: + assert(0); + break; + } + comprintf("\tarm_ADD_l(dst,tmp);\n"); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_addx(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + // Use tmp register to avoid destroying upper part in .B., .W cases + comprintf("\t dont_care_flags();\n"); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ADDX_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ADDX(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + genflags(flag_addx, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_and(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + comprintf("\t int tmp=scratchie++;\n"); + start_brace(); + if (!noflags) { + comprintf("\t jff_AND_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_AND(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_and, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_andsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ANDSR(ARM_CCR_MAP[src & 0xF], (src & 0x10));\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + (void) curi; + failure; + isjump; +#endif +} + +static void gen_asl(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + comprintf("\t int tmp=scratchie++;\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + + if (curi->smode != immi) { + if (!noflags) { + start_brace(); + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASL_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + start_brace(); + comprintf("\t jnf_LSL_reg(tmp,data,cnt);\n"); + } + } else { + start_brace(); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASL_%s_imm(tmp,data,srcreg);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_LSL_imm(tmp,data,srcreg);\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + /* Except for the handling of the V flag, this is identical to + LSL. The handling of V is, uhm, unpleasant, so if it's needed, + let the normal emulation handle it. Shoulders of giants kinda + thing ;-) */ + comprintf("if (needed_flags & FLAG_V) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + case sz_byte: + comprintf("\tmov_b_rr(data,scratchie);\n"); + break; + case sz_word: + comprintf("\tmov_w_rr(data,scratchie);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(data,scratchie);\n"); + break; + default: + assert(0); + break; + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(cdata,tmpcnt);\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(cdata,tmpcnt);\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(cdata,tmpcnt);\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,7);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,15);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,31);\n"); + break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + case sz_byte: + comprintf("\tmov_b_rr(data,scratchie);\n"); + break; + case sz_word: + comprintf("\tmov_w_rr(data,scratchie);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(data,scratchie);\n"); + break; + default: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_ri(data,srcreg);\n" + "\tbp=8-srcreg;\n"); + break; + case sz_word: + comprintf("\tshll_w_ri(data,srcreg);\n" + "\tbp=16-srcreg;\n"); + break; + case sz_long: + comprintf("\tshll_l_ri(data,srcreg);\n" + "\tbp=32-srcreg;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_aslw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ASLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_asr(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if defined(USE_JIT2) + (void)opcode; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (curi->smode != immi) { + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASR_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_ASR_%s_reg(tmp,data,cnt);\n", ssize); + } + } else { + char *op; + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + op = "ff"; + } else + op = "nf"; + + comprintf("\t j%s_ASR_%s_imm(tmp,data,srcreg);\n", op, ssize); + if (!noflags) { + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) opcode; + (void) ssize; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint width;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n" + "\tint highshift=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,cnt);\n" + "\thighmask=0x38;\n" + "\twidth=8;\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,cnt);\n" + "\thighmask=0x30;\n" + "\twidth=16;\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,cnt);\n" + "\thighmask=0x20;\n" + "\twidth=32;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(highshift,0);\n" + "mov_l_ri(scratchie,width/2);\n" + "cmov_l_rr(highshift,scratchie,%d);\n", NATIVE_CC_NE); + /* The x86 masks out bits, so we now make sure that things + really get shifted as much as planned */ + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,highshift);\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,highshift);\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,highshift);\n"); + break; + default: + assert(0); + break; + } + /* And again */ + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,highshift);\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,highshift);\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,highshift);\n"); + break; + default: + assert(0); + break; + } + + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(cdata,tmpcnt);\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(cdata,tmpcnt);\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(cdata,tmpcnt);\n"); + break; + default: + assert(0); + break; + } + /* If the shift count was higher than the width, we need + to pick up the sign from data */ + comprintf("test_l_ri(tmpcnt,highmask);\n" + "cmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint width;\n" + "\tint highshift=scratchie++;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,cnt);\n" + "\thighmask=0x38;\n" + "\twidth=8;\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,cnt);\n" + "\thighmask=0x30;\n" + "\twidth=16;\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,cnt);\n" + "\thighmask=0x20;\n" + "\twidth=32;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(highshift,0);\n" + "mov_l_ri(scratchie,width/2);\n" + "cmov_l_rr(highshift,scratchie,%d);\n", NATIVE_CC_NE); + /* The x86 masks out bits, so we now make sure that things + really get shifted as much as planned */ + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,highshift);\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,highshift);\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,highshift);\n"); + break; + default: + assert(0); + break; + } + /* And again */ + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_rr(data,highshift);\n"); + break; + case sz_word: + comprintf("\tshra_w_rr(data,highshift);\n"); + break; + case sz_long: + comprintf("\tshra_l_rr(data,highshift);\n"); + break; + default: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshra_b_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_word: + comprintf("\tshra_w_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_long: + comprintf("\tshra_l_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_asrw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ASRW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ASRW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_bchg(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BCHG_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_BCHG_%s(dst,src);\n", ssize); + comprintf("\t dont_care_flags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbtc_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_bclr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BCLR_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_BCLR_%s(dst,src);\n", ssize); + comprintf("\t dont_care_flags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbtr_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_bset(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BSET_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_BSET_%s(dst,src);\n", ssize); + comprintf("\t dont_care_flags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbts_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_btst(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + + // If we are not interested in flags it is not necessary to do + // anything with the data + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_BTST_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t dont_care_flags();\n"); + } +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint s=scratchie++;\n" + "\tint tmp=scratchie++;\n" + "\tmov_l_rr(s,src);\n"); + if (curi->size == sz_byte) + comprintf("\tand_l_ri(s,7);\n"); + else + comprintf("\tand_l_ri(s,31);\n"); + + comprintf("\tbt_l_rr(dst,s);\n" /* Answer now in C */ + "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */ + "\tmake_flags_live();\n" /* Get the flags back */ + "\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\tstart_needflags();\n" + "\tset_zero(s,tmp);\n" + "\tlive_flags();\n" + "\tend_needflags();\n"); + } +#endif +} + +static void gen_clr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_CLR(tmp);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_CLR(tmp);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags(flag_logical, curi->size, "dst", "", ""); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_cmp(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\t dont_care_flags();\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_CMP_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + } +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + genflags(flag_cmp, curi->size, "", "src", "dst"); +#endif +} + +static void gen_cmpa(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + if (!noflags) { + comprintf("\t dont_care_flags();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_CMPA_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\tdont_care_flags();\n"); + comprintf("/* Weird --- CMP with noflags ;-) */\n"); + } +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmps=scratchie++;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tsign_extend_8_rr(tmps,src);\n"); + break; + case sz_word: + comprintf("\tsign_extend_16_rr(tmps,src);\n"); + break; + case sz_long: + comprintf("tmps=src;\n"); + break; + default: + assert(0); + break; + } + genflags(flag_cmp, sz_long, "", "tmps", "dst"); +#endif +} + +static void gen_dbcc(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if 0 + isjump; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "offs", 1, 0); + + comprintf("uae_u32 voffs;\n"); + comprintf("voffs = get_const(offs);\n"); + /* That offs is an immediate, so we can clobber it with abandon */ + switch (curi->size) { + case sz_word: + comprintf("\t voffs = (uae_s32)((uae_s16)voffs);\n"); + break; + default: + assert(0); /* Seems this only comes in word flavour */ + break; + } + comprintf("\t voffs -= m68k_pc_offset - m68k_pc_offset_thisinst - 2;\n"); + comprintf("\t voffs += (uintptr)comp_pc_p + m68k_pc_offset;\n"); + + comprintf("\t add_const_v(PC_P, m68k_pc_offset);\n"); + comprintf("\t m68k_pc_offset = 0;\n"); + + start_brace(); + + if (curi->cc >= 2) { + comprintf("\t make_flags_live();\n"); /* Load the flags */ + } + + assert(curi->size == sz_word); + + switch (curi->cc) { + case 0: /* This is an elaborate nop? */ + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\t start_needflags();\n"); + comprintf("\t jnf_DBcc(src,voffs,%d);\n", curi->cc); + comprintf("\t end_needflags();\n"); + break; + default: + assert(0); + break; + } + genastore("src", curi->smode, "srcreg", curi->size, "src"); + gen_update_next_handler(); +#else + isjump; + uses_cmov; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "offs", 1, 0); + + /* That offs is an immediate, so we can clobber it with abandon */ + switch (curi->size) { + case sz_word: + comprintf("\tsign_extend_16_rr(offs,offs);\n"); + break; + default: + assert(0); /* Seems this only comes in word flavour */ + break; + } + comprintf("\tsub_l_ri(offs,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); + comprintf("\tarm_ADD_l_ri(offs,(uintptr)comp_pc_p);\n"); + /* New PC, + once the + offset_68k is + * also added */ + /* Let's fold in the m68k_pc_offset at this point */ + comprintf("\tarm_ADD_l_ri(offs,m68k_pc_offset);\n"); + comprintf("\tarm_ADD_l_ri(PC_P,m68k_pc_offset);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + + start_brace(); + comprintf("\tint nsrc=scratchie++;\n"); + + if (curi->cc >= 2) { + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + } + + assert (curi->size == sz_word); + + switch (curi->cc) { + case 0: /* This is an elaborate nop? */ + break; + case 1: + comprintf("\tstart_needflags();\n"); + comprintf("\tsub_w_ri(src,1);\n"); + comprintf("\t end_needflags();\n"); + start_brace(); + comprintf("\tuae_u32 v2,v;\n" + "\tuae_u32 v1=get_const(PC_P);\n"); + comprintf("\tv2=get_const(offs);\n" + "\tregister_branch(v1,v2,%d);\n", NATIVE_CC_CC); + break; + + case 8: + failure; + break; /* Work out details! FIXME */ + case 9: + failure; + break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\tmov_l_rr(nsrc,src);\n"); + comprintf("\tlea_l_brr(scratchie,src,(uae_s32)-1);\n" + "\tmov_w_rr(src,scratchie);\n"); + comprintf("\tcmov_l_rr(offs,PC_P,%d);\n", cond_codes[curi->cc]); + comprintf("\tcmov_l_rr(src,nsrc,%d);\n", cond_codes[curi->cc]); + /* OK, now for cc=true, we have src==nsrc and offs==PC_P, + so whether we move them around doesn't matter. However, + if cc=false, we have offs==jump_pc, and src==nsrc-1 */ + + comprintf("\t start_needflags();\n"); + comprintf("\ttest_w_rr(nsrc,nsrc);\n"); + comprintf("\t end_needflags();\n"); + comprintf("\tcmov_l_rr(PC_P,offs,%d);\n", NATIVE_CC_NE); + break; + default: + assert(0); + break; + } + genastore("src", curi->smode, "srcreg", curi->size, "src"); + gen_update_next_handler(); +#endif +} + +static void gen_eor(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t jff_EOR_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_EOR(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_eor, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_eorsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_EORSR(ARM_CCR_MAP[src & 0xF], ((src & 0x10) >> 4));\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + (void) curi; + failure; + isjump; +#endif +} + +static void gen_exg(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tmov_l_rr(tmp,src);\n"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_ext(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_EXT_%s(tmp,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_EXT_%s(tmp,src);\n", ssize); + } + genastore("tmp", curi->smode, "srcreg", + curi->size == sz_word ? sz_word : sz_long, "src"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\tdont_care_flags();\n"); + start_brace(); + switch (curi->size) { + case sz_byte: + comprintf("\tint dst = src;\n" + "\tsign_extend_8_rr(src,src);\n"); + break; + case sz_word: + comprintf("\tint dst = scratchie++;\n" + "\tsign_extend_8_rr(dst,src);\n"); + break; + case sz_long: + comprintf("\tint dst = src;\n" + "\tsign_extend_16_rr(src,src);\n"); + break; + default: + assert(0); + break; + } + genflags(flag_logical, curi->size == sz_word ? sz_word : sz_long, "dst", "", + ""); + genastore("dst", curi->smode, "srcreg", + curi->size == sz_word ? sz_word : sz_long, "src"); +#endif +} + +static void gen_lsl(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + comprintf("\t int tmp=scratchie++;\n"); + if (curi->smode != immi) { + if (!noflags) { + start_brace(); + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSL_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + start_brace(); + comprintf("\t jnf_LSL_reg(tmp,data,cnt);\n"); + } + } else { + start_brace(); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSL_%s_imm(tmp,data,srcreg);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_LSL_imm(tmp,data,srcreg);\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + case sz_byte: + comprintf("\tmov_b_rr(data,scratchie);\n"); + break; + case sz_word: + comprintf("\tmov_w_rr(data,scratchie);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(data,scratchie);\n"); + break; + default: + assert(0); + break; + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(cdata,tmpcnt);\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(cdata,tmpcnt);\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(cdata,tmpcnt);\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,7);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,15);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + comprintf("\t bt_l_ri(cdata,31);\n"); + break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshll_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshll_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + case sz_byte: + comprintf("\tmov_b_rr(data,scratchie);\n"); + break; + case sz_word: + comprintf("\tmov_w_rr(data,scratchie);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(data,scratchie);\n"); + break; + default: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshll_b_ri(data,srcreg);\n" + "\tbp=8-srcreg;\n"); + break; + case sz_word: + comprintf("\tshll_w_ri(data,srcreg);\n" + "\tbp=16-srcreg;\n"); + break; + case sz_long: + comprintf("\tshll_l_ri(data,srcreg);\n" + "\tbp=32-srcreg;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_lslw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_LSLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_lsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + comprintf("\t int tmp=scratchie++;\n"); + if (curi->smode != immi) { + if (!noflags) { + start_brace(); + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSR_%s_reg(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + start_brace(); + comprintf("\t jnf_LSR_%s_reg(tmp,data,cnt);\n", ssize); + } + } else { + start_brace(); + char *op; + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + op = "ff"; + } else + op = "nf"; + + comprintf("\t j%s_LSR_%s_imm(tmp,data,srcreg);\n", op, ssize); + + if (!noflags) { + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + if (curi->smode != immi) { + if (!noflags) { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n" + "\tint cdata=scratchie++;\n" + "\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n" + "\tand_l_ri(tmpcnt,63);\n" + "\tmov_l_ri(cdata,0);\n" + "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); + /* cdata is now either data (for shift count!=0) or + 0 (for shift count==0) */ + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshrl_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshrl_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + case sz_byte: + comprintf("\tmov_b_rr(data,scratchie);\n"); + break; + case sz_word: + comprintf("\tmov_w_rr(data,scratchie);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(data,scratchie);\n"); + break; + default: + assert(0); + break; + } + /* Result of shift is now in data. Now we need to determine + the carry by shifting cdata one less */ + comprintf("\tsub_l_ri(tmpcnt,1);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_rr(cdata,tmpcnt);\n"); + break; + case sz_word: + comprintf("\tshrl_w_rr(cdata,tmpcnt);\n"); + break; + case sz_long: + comprintf("\tshrl_l_rr(cdata,tmpcnt);\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(tmpcnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(cdata,scratchie,%d);\n", NATIVE_CC_NE); + /* And create the flags */ + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } else { + uses_cmov; + start_brace(); + comprintf("\tint highmask;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_rr(data,cnt);\n" + "\thighmask=0x38;\n"); + break; + case sz_word: + comprintf("\tshrl_w_rr(data,cnt);\n" + "\thighmask=0x30;\n"); + break; + case sz_long: + comprintf("\tshrl_l_rr(data,cnt);\n" + "\thighmask=0x20;\n"); + break; + default: + assert(0); + break; + } + comprintf("test_l_ri(cnt,highmask);\n" + "mov_l_ri(scratchie,0);\n" + "cmov_l_rr(scratchie,data,%d);\n", NATIVE_CC_EQ); + switch (curi->size) { + case sz_byte: + comprintf("\tmov_b_rr(data,scratchie);\n"); + break; + case sz_word: + comprintf("\tmov_w_rr(data,scratchie);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(data,scratchie);\n"); + break; + default: + assert(0); + break; + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } + } else { + start_brace(); + comprintf("\tint tmp=scratchie++;\n" + "\tint bp;\n" + "\tmov_l_rr(tmp,data);\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tshrl_b_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_word: + comprintf("\tshrl_w_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + case sz_long: + comprintf("\tshrl_l_ri(data,srcreg);\n" + "\tbp=srcreg-1;\n"); + break; + default: + assert(0); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("\t duplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); + } +#endif +} + +static void gen_lsrw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_LSRW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_LSRW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_move(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + switch (curi->dmode) { + case Dreg: + case Areg: + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags && curi->dmode == Dreg) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_MOVE_%s(tmp, src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t tmp = src;\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); + break; + + default: /* It goes to memory, not a register */ + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_TST_%s(src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore("src", curi->dmode, "dstreg", curi->size, "dst"); + break; + } +#else + (void) ssize; + + switch (curi->dmode) { + case Dreg: + case Areg: + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genflags(flag_mov, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); + break; + default: /* It goes to memory, not a register */ + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genflags(flag_logical, curi->size, "src", "", ""); + genastore("src", curi->dmode, "dstreg", curi->size, "dst"); + break; + } +#endif +} + +static void gen_movea(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + + start_brace(); + comprintf("\t jnf_MOVEA_%s(dst, src);\n", ssize); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + (void) ssize; + + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + + start_brace(); + comprintf("\tint tmps=scratchie++;\n"); + switch (curi->size) { + case sz_word: + comprintf("\tsign_extend_16_rr(dst,src);\n"); + break; + case sz_long: + comprintf("\tmov_l_rr(dst,src);\n"); + break; + default: + assert(0); + break; + } + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_mull(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t uae_u16 extra=%s;\n", gen_nextiword()); + comprintf("\t int r2=(extra>>12)&7;\n" + "\t int tmp=scratchie++;\n"); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + /* The two operands are in dst and r2 */ + if (!noflags) { + comprintf("\t if (extra & 0x0400) {\n"); /* Need full 64 bit result */ + comprintf("\t int r3=(extra & 7);\n"); + comprintf("\t mov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t\t jff_MULS64(r2,r3);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jff_MULU64(r2,r3);\n"); + comprintf("\t } \n"); /* The result is in r2/r3, with r2 holding the lower 32 bits */ + comprintf("\t } else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result goes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t jff_MULS32(r2,dst);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jff_MULU32(r2,dst);\n"); + comprintf("\t } \n"); /* The result is in r2, with r2 holding the lower 32 bits */ + comprintf("\t }\n"); + } else { + comprintf("\t if (extra & 0x0400) {\n"); /* Need full 64 bit result */ + comprintf("\t int r3=(extra & 7);\n"); + comprintf("\t mov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t\t jnf_MULS64(r2,r3);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jnf_MULU64(r2,r3);\n"); + comprintf("\t } \n"); /* The result is in r2/r3, with r2 holding the lower 32 bits */ + comprintf("\t } else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result foes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\t if (extra & 0x0800) { \n"); /* signed */ + comprintf("\t jnf_MULS32(r2,dst);\n"); + comprintf("\t } else { \n"); + comprintf("\t\t jnf_MULU32(r2,dst);\n"); + comprintf("\t } \n"); /* The result is in r2, with r2 holding the lower 32 bits */ + comprintf("\t }\n"); + } +#else + if (!noflags) { + failure; + return; + } + comprintf("\tuae_u16 extra=%s;\n", gen_nextiword()); + comprintf("\tint r2=(extra>>12)&7;\n" + "\tint tmp=scratchie++;\n"); + + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + /* The two operands are in dst and r2 */ + comprintf("\tif (extra&0x0400) {\n" /* Need full 64 bit result */ + "\tint r3=(extra&7);\n" + "\tmov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */ + comprintf("\tif (extra&0x0800) { \n" /* signed */ + "\t\timul_64_32(r2,r3);\n" + "\t} else { \n" + "\t\tmul_64_32(r2,r3);\n" + "\t} \n"); + /* The result is in r2/tmp, with r2 holding the lower 32 bits */ + comprintf("\t} else {\n"); /* Only want 32 bit result */ + /* operands in dst and r2, result foes into r2 */ + /* shouldn't matter whether it's signed or unsigned?!? */ + comprintf("\timul_32_32(r2,dst);\n" + "\t}\n"); +#endif +} + +static void gen_muls(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + start_brace(); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_MULS(dst,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_MULS(dst,src);\n"); + } + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + comprintf("\tsign_extend_16_rr(scratchie,src);\n" + "\tsign_extend_16_rr(dst,dst);\n" + "\timul_32_32(dst,scratchie);\n"); + genflags(flag_logical, sz_long, "dst", "", ""); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_mulu(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + start_brace(); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_MULU(dst,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_MULU(dst,src);\n"); + } + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0); + /* To do 16x16 unsigned multiplication, we actually use + 32x32 signed, and zero-extend the registers first. + That solves the problem of MUL needing dedicated registers + on the x86 */ + comprintf("\tzero_extend_16_rr(scratchie,src);\n" + "\tzero_extend_16_rr(dst,dst);\n" + "\timul_32_32(dst,scratchie);\n"); + genflags(flag_logical, sz_long, "dst", "", ""); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); + +#endif +} + +static void gen_nbcd(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) curi; + (void) ssize; + failure; + /* Nope! */ +#endif +} + +static void gen_neg(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_NEG_%s(tmp,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_NEG(tmp,src);\n"); + } + + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags(flag_sub, curi->size, "", "src", "dst"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_negx(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int dst=scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_NEGX_%s(dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_NEGX(dst,src);\n"); + } + + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#else + (void) ssize; + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0);\n"); + genflags(flag_subx, curi->size, "", "src", "dst"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_not(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_NOT_%s(tmp,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_NOT(tmp,src);\n", ssize); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\tint dst=scratchie++;\n"); + comprintf("\tmov_l_ri(dst,0xffffffff);\n"); + genflags(flag_eor, curi->size, "", "src", "dst"); + genastore("dst", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_or(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t jff_OR_%s(tmp, dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_OR(tmp, dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_or, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_orsr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ORSR(ARM_CCR_MAP[src & 0xF], ((src & 0x10) >> 4));\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + (void) curi; + failure; + isjump; +#endif +} + +static void gen_rol(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROL_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ROL_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + + switch (curi->size) { + case sz_long: + comprintf("\t rol_l_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\t rol_w_rr(data,cnt);\n"); + break; + case sz_byte: + comprintf("\t rol_b_rr(data,cnt);\n"); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + comprintf("\t bt_l_ri(data,0x00);\n"); /* Set C */ + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); +#endif +} + +static void gen_rolw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ROLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_ror(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROR_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_ROR_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) ssize; + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + comprintf("\tdont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + + switch (curi->size) { + case sz_long: + comprintf("\t ror_l_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\t ror_w_rr(data,cnt);\n"); + break; + case sz_byte: + comprintf("\t ror_b_rr(data,cnt);\n"); + break; + } + + if (!noflags) { + comprintf("\tstart_needflags();\n"); + comprintf("\tif (needed_flags & FLAG_ZNV)\n"); + switch (curi->size) { + case sz_byte: + comprintf("\t test_b_rr(data,data);\n"); + break; + case sz_word: + comprintf("\t test_w_rr(data,data);\n"); + break; + case sz_long: + comprintf("\t test_l_rr(data,data);\n"); + break; + } + switch (curi->size) { + case sz_byte: + comprintf("\t bt_l_ri(data,0x07);\n"); + break; + case sz_word: + comprintf("\t bt_l_ri(data,0x0f);\n"); + break; + case sz_long: + comprintf("\t bt_l_ri(data,0x1f);\n"); + break; + } + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } + genastore("data", curi->dmode, "dstreg", curi->size, "data"); +#endif +} + +static void gen_rorw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_RORW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } else { + comprintf("\t jnf_RORW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_roxl(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXL_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXL_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) curi; + (void) ssize; + failure; +#endif +} + +static void gen_roxlw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXLW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXLW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_roxr(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + mayfail; + if (curi->smode == Dreg) { + comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " return;\n" + "} \n"); + start_brace(); + } + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "data", 1, 0); + start_brace(); + comprintf("\t int tmp=scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXR_%s(tmp,data,cnt);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXR_%s(tmp,data,cnt);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "data"); +#else + (void) curi; + failure; +#endif +} + +static void gen_roxrw(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + isaddx; + comprintf("\t dont_care_flags();\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf("\t int tmp = scratchie++;\n"); + + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_ROXRW(tmp,src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + } else { + comprintf("\t restore_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_ROXRW(tmp,src);\n"); + } + genastore("tmp", curi->smode, "srcreg", curi->size, "src"); +#else + (void) curi; + failure; +#endif +} + +static void gen_sbcd(uae_u32 opcode, struct instr *curi, const char* ssize) { +#if 0 +#else + (void) opcode; + (void) curi; + (void) ssize; + failure; + /* I don't think so! */ +#endif +} + +static void gen_scc(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if 0 + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\t int val = scratchie++;\n"); + switch (curi->cc) { + case 0: /* Unconditional set */ + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\t make_flags_live();\n"); /* Load the flags */ + comprintf("\t jnf_Scc_ri(val,%d);\n", curi->cc); + break; + default: + assert(0); + break; + } + genastore("val", curi->smode, "srcreg", curi->size, "src"); +#else + genamode(curi->smode, "srcreg", curi->size, "src", 2, 0); + start_brace(); + comprintf("\tint val = scratchie++;\n"); + + /* We set val to 0 if we really should use 255, and to 1 for real 0 */ + switch (curi->cc) { + case 0: /* Unconditional set */ + comprintf("\tmov_l_ri(val,0);\n"); + break; + case 1: + /* Unconditional not-set */ + comprintf("\tmov_l_ri(val,1);\n"); + break; + case 8: + failure; + break; /* Work out details! FIXME */ + case 9: + failure; + break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + /* All condition codes can be inverted by changing the LSB */ + comprintf("\tsetcc(val,%d);\n", cond_codes[curi->cc] ^ 1); + break; + default: + assert(0); + break; + } + comprintf("\tsub_b_ri(val,1);\n"); + genastore("val", curi->smode, "srcreg", curi->size, "src"); +#endif +} + +static void gen_sub(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + + comprintf("\t dont_care_flags();\n"); + start_brace(); + // Use tmp register to avoid destroying upper part in .B., .W cases + comprintf("\t int tmp=scratchie++;\n"); + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_SUB_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf( + "\t if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_SUB_%s(tmp,dst,src);\n", ssize); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_sub, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_suba(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\t jnf_SUBA_%s(dst, src);\n", ssize); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#else + (void) ssize; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", sz_long, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + switch (curi->size) { + case sz_byte: + comprintf("\tsign_extend_8_rr(tmp,src);\n"); + break; + case sz_word: + comprintf("\tsign_extend_16_rr(tmp,src);\n"); + break; + case sz_long: + comprintf("\ttmp=src;\n"); + break; + default: + assert(0); + break; + } + comprintf("\tsub_l(dst,tmp);\n"); + genastore("dst", curi->dmode, "dstreg", sz_long, "dst"); +#endif +} + +static void gen_subx(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; +#if defined(USE_JIT2) + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + start_brace(); + comprintf("\tint tmp=scratchie++;\n"); + comprintf("\tdont_care_flags();\n"); + if (!noflags) { + comprintf("\t make_flags_live();\n"); + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t start_needflags();\n"); + comprintf("\t jff_SUBX_%s(tmp,dst,src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + duplicate_carry(); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t restore_inverted_carry();\n"); /* Reload the X flag into C */ + comprintf("\t jnf_SUBX(tmp,dst,src);\n"); + } + genastore("tmp", curi->dmode, "dstreg", curi->size, "dst"); +#else + (void) ssize; + isaddx; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genflags(flag_subx, curi->size, "", "src", "dst"); + genastore("dst", curi->dmode, "dstreg", curi->size, "dst"); +#endif +} + +static void gen_swap(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + start_brace(); + + if (!noflags) { + comprintf("\t start_needflags();\n"); + comprintf("\t jff_SWAP(src);\n"); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } else { + comprintf("\t jnf_SWAP(src);\n"); + } + genastore("src", curi->smode, "srcreg", sz_long, "src"); +#else + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + comprintf("\tdont_care_flags();\n"); + comprintf("\tarm_ROR_l_ri8(src,16);\n"); + genflags(flag_logical, sz_long, "src", "", ""); + genastore("src", curi->smode, "srcreg", sz_long, "src"); +#endif +} + +static void gen_tst(uae_u32 opcode, struct instr *curi, const char* ssize) { + (void) opcode; + (void) ssize; +#if defined(USE_JIT2) + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\t dont_care_flags();\n"); + if (!noflags) { + start_brace(); + comprintf("\t start_needflags();\n"); + comprintf("\t jff_TST_%s(src);\n", ssize); + comprintf("\t live_flags();\n"); + comprintf("\t end_needflags();\n"); + } +#else + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + genflags(flag_logical, curi->size, "src", "", ""); +#endif +} + +static int /* returns zero for success, non-zero for failure */ +gen_opcode(unsigned long int opcode) { + struct instr *curi = table68k + opcode; + const char* ssize = NULL; + + insn_n_cycles = 2; + global_failure = 0; + long_opcode = 0; + global_isjump = 0; + global_iscjump = 0; + global_isaddx = 0; + global_cmov = 0; + global_fpu = 0; + global_mayfail = 0; + hack_opcode = opcode; + endstr[0] = 0; + + start_brace(); + comprintf("\tuae_u8 scratchie=S1;\n"); + switch (curi->plev) { + case 0: /* not privileged */ + break; + case 1: /* unprivileged only on 68000 */ + if (cpu_level == 0) + break; + if (next_cpu_level < 0) + next_cpu_level = 0; + + /* fall through */ + case 2: /* priviledged */ + failure; /* Easy ones first */ + break; + case 3: /* privileged if size == word */ + if (curi->size == sz_byte) + break; + failure; + break; + } + switch (curi->size) { + case sz_byte: + ssize = "b"; + break; + case sz_word: + ssize = "w"; + break; + case sz_long: + ssize = "l"; + break; + default: + assert(0); + break; + } + (void) ssize; + + switch (curi->mnemo) { + case i_AND: + gen_and(opcode, curi, ssize); + break; + + case i_OR: + gen_or(opcode, curi, ssize); + break; + + case i_EOR: + gen_eor(opcode, curi, ssize); + break; + + case i_ORSR: + gen_orsr(opcode, curi, ssize); + break; + + case i_EORSR: + gen_eorsr(opcode, curi, ssize); + break; + + case i_ANDSR: + gen_andsr(opcode, curi, ssize); + break; + + case i_SUB: + gen_sub(opcode, curi, ssize); + break; + + case i_SUBA: + gen_suba(opcode, curi, ssize); + break; + + case i_SUBX: + gen_subx(opcode, curi, ssize); + break; + + case i_SBCD: + gen_sbcd(opcode, curi, ssize); + break; + + case i_ADD: + gen_add(opcode, curi, ssize); + break; + + case i_ADDA: + gen_adda(opcode, curi, ssize); + break; + + case i_ADDX: + gen_addx(opcode, curi, ssize); + break; + + case i_ABCD: + gen_abcd(opcode, curi, ssize); + break; + + case i_NEG: + gen_neg(opcode, curi, ssize); + break; + + case i_NEGX: + gen_negx(opcode, curi, ssize); + break; + + case i_NBCD: + gen_nbcd(opcode, curi, ssize); + break; + + case i_CLR: + gen_clr(opcode, curi, ssize); + break; + + case i_NOT: + gen_not(opcode, curi, ssize); + break; + + case i_TST: + gen_tst(opcode, curi, ssize); + break; + + case i_BCHG: + gen_bchg(opcode, curi, ssize); + break; + + case i_BCLR: + gen_bclr(opcode, curi, ssize); + break; + + case i_BSET: + gen_bset(opcode, curi, ssize); + break; + + case i_BTST: + gen_btst(opcode, curi, ssize); + break; + + case i_CMPM: + case i_CMP: + gen_cmp(opcode, curi, ssize); + break; + + case i_CMPA: + gen_cmpa(opcode, curi, ssize); + break; + + /* The next two are coded a little unconventional, but they are doing + * weird things... */ + case i_MVPRM: + isjump; + failure; + break; + + case i_MVPMR: + isjump; + failure; + break; + + case i_MOVE: + gen_move(opcode, curi, ssize); + break; + + case i_MOVEA: + gen_movea(opcode, curi, ssize); + break; + + case i_MVSR2: + isjump; + failure; + break; + + case i_MV2SR: + isjump; + failure; + break; + + case i_SWAP: + gen_swap(opcode, curi, ssize); + break; + + case i_EXG: + gen_exg(opcode, curi, ssize); + break; + + case i_EXT: + gen_ext(opcode, curi, ssize); + break; + + case i_MVMEL: + genmovemel(opcode); + break; + + case i_MVMLE: + genmovemle(opcode); + break; + + case i_TRAP: + isjump; + failure; + break; + + case i_MVR2USP: + isjump; + failure; + break; + + case i_MVUSP2R: + isjump; + failure; + break; + + case i_RESET: + isjump; + failure; + break; + + case i_NOP: + break; + + case i_STOP: + isjump; + failure; + break; + + case i_RTE: + isjump; + failure; + break; + + case i_RTD: + genamode(curi->smode, "srcreg", curi->size, "offs", 1, 0); + /* offs is constant */ + comprintf("\tarm_ADD_l_ri8(offs,4);\n"); + start_brace(); + comprintf("\tint newad=scratchie++;\n" + "\treadlong(15,newad,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc,newad);\n" + "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n" + "\tarm_ADD_l(15,offs);\n"); + gen_update_next_handler(); + isjump; + break; + + case i_LINK: + genamode(curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode(curi->dmode, "dstreg", curi->size, "offs", 1, 0); + comprintf("\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,src,scratchie);\n" + "\tmov_l_rr(src,15);\n"); + if (curi->size == sz_word) + comprintf("\tsign_extend_16_rr(offs,offs);\n"); + comprintf("\tarm_ADD_l(15,offs);\n"); + genastore("src", curi->smode, "srcreg", sz_long, "src"); + break; + + case i_UNLK: + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + comprintf("\tmov_l_rr(15,src);\n" + "\treadlong(15,src,scratchie);\n" + "\tarm_ADD_l_ri8(15,4);\n"); + genastore("src", curi->smode, "srcreg", curi->size, "src"); + break; + + case i_RTS: + comprintf("\tint newad=scratchie++;\n" + "\treadlong(15,newad,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc,newad);\n" + "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n" + "\tlea_l_brr(15,15,4);\n"); + gen_update_next_handler(); + isjump; + break; + + case i_TRAPV: + isjump; + failure; + break; + + case i_RTR: + isjump; + failure; + break; + + case i_JSR: + isjump; + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + start_brace(); + comprintf( + "\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,ret,scratchie);\n"); + comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" + "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n"); + gen_update_next_handler(); + break; + + case i_JMP: + isjump; + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" + "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" + "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" + "\tm68k_pc_offset=0;\n"); + gen_update_next_handler(); + break; + + case i_BSR: + is_const_jump; + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + start_brace(); + comprintf( + "\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tsub_l_ri(15,4);\n" + "\twritelong_clobber(15,ret,scratchie);\n"); + comprintf("\tarm_ADD_l_ri(src,m68k_pc_offset_thisinst+2);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + comprintf("\tarm_ADD_l(PC_P,src);\n"); + comprintf("\tcomp_pc_p=(uae_u8*)get_const(PC_P);\n"); + break; + + case i_Bcc: + comprintf("\tuae_u32 v,v1,v2;\n"); + genamode(curi->smode, "srcreg", curi->size, "src", 1, 0); + /* That source is an immediate, so we can clobber it with abandon */ + switch (curi->size) { + case sz_byte: + comprintf("\tsign_extend_8_rr(src,src);\n"); + break; + case sz_word: + comprintf("\tsign_extend_16_rr(src,src);\n"); + break; + case sz_long: + break; + } + comprintf( + "\tsub_l_ri(src,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n"); + /* Leave the following as "add" --- it will allow it to be optimized + away due to src being a constant ;-) */ + comprintf("\tarm_ADD_l_ri(src,(uintptr)comp_pc_p);\n"); + comprintf("\tmov_l_ri(PC_P,(uintptr)comp_pc_p);\n"); + /* Now they are both constant. Might as well fold in m68k_pc_offset */ + comprintf("\tarm_ADD_l_ri(src,m68k_pc_offset);\n"); + comprintf("\tarm_ADD_l_ri(PC_P,m68k_pc_offset);\n"); + comprintf("\tm68k_pc_offset=0;\n"); + + if (curi->cc >= 2) { + comprintf("\tv1=get_const(PC_P);\n" + "\tv2=get_const(src);\n" + "\tregister_branch(v1,v2,%d);\n", cond_codes[curi->cc]); + comprintf("\tmake_flags_live();\n"); /* Load the flags */ + isjump; + } else { + is_const_jump; + } + + switch (curi->cc) { + case 0: /* Unconditional jump */ + comprintf("\tmov_l_rr(PC_P,src);\n"); + comprintf("\tcomp_pc_p=(uae_u8*)get_const(PC_P);\n"); + break; + case 1: + break; /* This is silly! */ + case 8: + failure; + break; /* Work out details! FIXME */ + case 9: + failure; + break; /* Not critical, though! */ + + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + break; + default: + assert(0); + break; + } + break; + + case i_LEA: + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode(curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore("srca", curi->dmode, "dstreg", curi->size, "dst"); + break; + + case i_PEA: + if (table68k[opcode].smode == Areg || table68k[opcode].smode == Aind + || table68k[opcode].smode == Aipi + || table68k[opcode].smode == Apdi + || table68k[opcode].smode == Ad16 + || table68k[opcode].smode == Ad8r) + comprintf("if (srcreg==7) dodgy=1;\n"); + + genamode(curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode(Apdi, "7", sz_long, "dst", 2, 0); + genastore("srca", Apdi, "7", sz_long, "dst"); + break; + + case i_DBcc: + gen_dbcc(opcode, curi, ssize); + break; + + case i_Scc: + gen_scc(opcode, curi, ssize); + break; + + case i_DIVU: + isjump; + failure; + break; + + case i_DIVS: + isjump; + failure; + break; + + case i_MULU: + gen_mulu(opcode, curi, ssize); + break; + + case i_MULS: + gen_muls(opcode, curi, ssize); + break; + + case i_CHK: + isjump; + failure; + break; + + case i_CHK2: + isjump; + failure; + break; + + case i_ASR: + gen_asr(opcode, curi, ssize); + break; + + case i_ASL: + gen_asl(opcode, curi, ssize); + break; + + case i_LSR: + gen_lsr(opcode, curi, ssize); + break; + + case i_LSL: + gen_lsl(opcode, curi, ssize); + break; + + case i_ROL: + gen_rol(opcode, curi, ssize); + break; + + case i_ROR: + gen_ror(opcode, curi, ssize); + break; + + case i_ROXL: + gen_roxl(opcode, curi, ssize); + break; + + case i_ROXR: + gen_roxr(opcode, curi, ssize); + break; + + case i_ASRW: + gen_asrw(opcode, curi, ssize); + break; + + case i_ASLW: + gen_aslw(opcode, curi, ssize); + break; + + case i_LSRW: + gen_lsrw(opcode, curi, ssize); + break; + + case i_LSLW: + gen_lslw(opcode, curi, ssize); + break; + + case i_ROLW: + gen_rolw(opcode, curi, ssize); + break; + + case i_RORW: + gen_rorw(opcode, curi, ssize); + break; + + case i_ROXLW: + gen_roxlw(opcode, curi, ssize); + break; + + case i_ROXRW: + gen_roxrw(opcode, curi, ssize); + break; + + case i_MOVEC2: + isjump; + failure; + break; + + case i_MOVE2C: + isjump; + failure; + break; + + case i_CAS: + failure; + break; + + case i_CAS2: + failure; + break; + + case i_MOVES: + /* ignore DFC and SFC because we have no MMU */ + isjump; + failure; + break; + + case i_BKPT: + /* only needed for hardware emulators */ + isjump; + failure; + break; + + case i_CALLM: + /* not present in 68030 */ + isjump; + failure; + break; + + case i_RTM: + /* not present in 68030 */ + isjump; + failure; + break; + + case i_TRAPcc: + isjump; + failure; + break; + + case i_DIVL: + isjump; + failure; + break; + + case i_MULL: + gen_mull(opcode, curi, ssize); + break; + + case i_BFTST: + case i_BFEXTU: + case i_BFCHG: + case i_BFEXTS: + case i_BFCLR: + case i_BFFFO: + case i_BFSET: + case i_BFINS: + failure; + break; + case i_PACK: + failure; + break; + case i_UNPK: + failure; + break; + case i_TAS: + failure; + break; + case i_FPP: + uses_fpu; +#ifdef USE_JIT_FPU + mayfail; + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + swap_opcode(); + comprintf("\tcomp_fpp_opp(opcode,extra);\n"); +#else + failure; +#endif + break; + case i_FBcc: + uses_fpu; +#ifdef USE_JIT_FPU + isjump; + uses_cmov; + mayfail; + swap_opcode(); + comprintf("\tcomp_fbcc_opp(opcode);\n"); +#else + isjump; + failure; +#endif + break; + case i_FDBcc: + uses_fpu; + isjump; + failure; + break; + case i_FScc: + uses_fpu; +#ifdef USE_JIT_FPU + mayfail; + uses_cmov; + comprintf("\tuae_u16 extra=%s;\n",gen_nextiword()); + swap_opcode(); + comprintf("\tcomp_fscc_opp(opcode,extra);\n"); +#else + failure; +#endif + break; + case i_FTRAPcc: + uses_fpu; + isjump; + failure; + break; + case i_FSAVE: + uses_fpu; + failure; + break; + case i_FRESTORE: + uses_fpu; + failure; + break; + + case i_CINVL: + case i_CINVP: + case i_CINVA: + isjump; /* Not really, but it's probably a good idea to stop + translating at this point */ + failure; + comprintf("\tflush_icache();\n"); /* Differentiate a bit more? */ + break; + case i_CPUSHL: + case i_CPUSHP: + case i_CPUSHA: + isjump; /* Not really, but it's probably a good idea to stop + translating at this point */ + failure; + break; + + case i_MOVE16: + gen_move16(opcode, curi); + break; + + case i_EMULOP_RETURN: + isjump; + failure; + break; + + case i_EMULOP: + failure; + break; + + case i_NATFEAT_ID: + case i_NATFEAT_CALL: + failure; + break; + + case i_MMUOP: + isjump; + failure; + break; + default: + assert(0); + break; + } + comprintf("%s", endstr); + finish_braces(); + sync_m68k_pc(); + if (global_mayfail) + comprintf("\tif (failure) m68k_pc_offset=m68k_pc_offset_thisinst;\n"); + return global_failure; +} + +static void generate_includes(FILE * f) { + fprintf(f, "#include \"sysdeps.h\"\n"); + fprintf(f, "#include \"m68k.h\"\n"); + fprintf(f, "#include \"memory.h\"\n"); + fprintf(f, "#include \"readcpu.h\"\n"); + fprintf(f, "#include \"newcpu.h\"\n"); + fprintf(f, "#include \"comptbl.h\"\n"); + fprintf(f, "#include \"debug.h\"\n"); +} + +static int postfix; + +static void generate_one_opcode(int rp, int noflags) { + int i; + uae_u16 smsk, dmsk; + int opcode = opcode_map[rp]; + int aborted = 0; + int have_srcreg = 0; + int have_dstreg = 0; + const char *name; + + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) + return; + + for (i = 0; lookuptab[i].name[0]; i++) { + if (table68k[opcode].mnemo == lookuptab[i].mnemo) + break; + } + + if (table68k[opcode].handler != -1) + return; + + switch (table68k[opcode].stype) { + case 0: + smsk = 7; + break; + case 1: + smsk = 255; + break; + case 2: + smsk = 15; + break; + case 3: + smsk = 7; + break; + case 4: + smsk = 7; + break; + case 5: + smsk = 63; + break; + case 6: + smsk = 255; + break; + case 7: + smsk = 3; + break; + default: + assert(0); + break; + } + dmsk = 7; + + next_cpu_level = -1; + if (table68k[opcode].suse && table68k[opcode].smode != imm + && table68k[opcode].smode != imm0 && table68k[opcode].smode != imm1 + && table68k[opcode].smode != imm2 && table68k[opcode].smode != absw + && table68k[opcode].smode != absl && table68k[opcode].smode != PC8r + && table68k[opcode].smode != PC16) { + have_srcreg = 1; + if (table68k[opcode].spos == -1) { + if (((int) table68k[opcode].sreg) >= 128) + comprintf("\tuae_s32 srcreg = (uae_s32)(uae_s8)%d;\n", + (int) table68k[opcode].sreg); + else + comprintf("\tuae_s32 srcreg = %d;\n", + (int) table68k[opcode].sreg); + } else { + char source[100]; + int pos = table68k[opcode].spos; + + comprintf( + "#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + + if (pos < 8 && (smsk >> (8 - pos)) != 0) + sprintf(source, "(((opcode >> %d) | (opcode << %d)) & %d)", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + sprintf(source, "((opcode >> %d) & %d)", pos ^ 8, smsk); + else + sprintf(source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + comprintf("\tuae_u32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + comprintf("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + comprintf("\tuae_u32 srcreg = %s;\n", source); + + comprintf("#else\n"); + + if (pos) + sprintf(source, "((opcode >> %d) & %d)", pos, smsk); + else + sprintf(source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + comprintf("\tuae_s32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + comprintf("\tuae_s32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + comprintf("\tuae_s32 srcreg = %s;\n", source); + + comprintf("#endif\n"); + } + } + if (table68k[opcode].duse + /* Yes, the dmode can be imm, in case of LINK or DBcc */ + && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0 + && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2 + && table68k[opcode].dmode != absw + && table68k[opcode].dmode != absl) { + have_dstreg = 1; + if (table68k[opcode].dpos == -1) { + if (((int) table68k[opcode].dreg) >= 128) + comprintf("\tuae_s32 dstreg = (uae_s32)(uae_s8)%d;\n", + (int) table68k[opcode].dreg); + else + comprintf("\tuae_s32 dstreg = %d;\n", + (int) table68k[opcode].dreg); + } else { + int pos = table68k[opcode].dpos; + + comprintf( + "#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + + if (pos < 8 && (dmsk >> (8 - pos)) != 0) + comprintf( + "\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + comprintf("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", pos ^ 8, + dmsk); + else + comprintf("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + comprintf("#else\n"); + + if (pos) + comprintf("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", pos, + dmsk); + else + comprintf("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + comprintf("#endif\n"); + } + } + + if (have_srcreg && have_dstreg + && (table68k[opcode].dmode == Areg || table68k[opcode].dmode == Aind + || table68k[opcode].dmode == Aipi + || table68k[opcode].dmode == Apdi + || table68k[opcode].dmode == Ad16 + || table68k[opcode].dmode == Ad8r) + && (table68k[opcode].smode == Areg || table68k[opcode].smode == Aind + || table68k[opcode].smode == Aipi + || table68k[opcode].smode == Apdi + || table68k[opcode].smode == Ad16 + || table68k[opcode].smode == Ad8r)) { + comprintf("\tuae_u32 dodgy=(srcreg==(uae_s32)dstreg);\n"); + } else { + comprintf("\tuae_u32 dodgy=0;\n"); + } + comprintf("\tuae_u32 m68k_pc_offset_thisinst=m68k_pc_offset;\n"); + comprintf("\tm68k_pc_offset+=2;\n"); + + aborted = gen_opcode(opcode); + { + int flags = 0; + if (global_isjump) + flags |= 1; + if (long_opcode) + flags |= 2; + if (global_cmov) + flags |= 4; + if (global_isaddx) + flags |= 8; + if (global_iscjump) + flags |= 16; + if (global_fpu) + flags |= 32; + + comprintf("}\n"); + + name = lookuptab[i].name; + if (aborted) { + fprintf(stblfile, "{ NULL, 0x%08x, %d }, /* %s */\n", opcode, flags, name); + com_discard(); + } else { + const char *tbl = noflags ? "nf" : "ff"; + fprintf(stblfile, + "{ op_%x_%d_comp_%s, %d, 0x%08x }, /* %s */\n", + opcode, postfix, tbl, opcode, flags, name); + fprintf(headerfile, "extern compop_func op_%x_%d_comp_%s;\n", + opcode, postfix, tbl); + printf( + "void REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode) /* %s */\n{\n", + opcode, postfix, tbl, name); + com_flush(); + } + } + opcode_next_clev[rp] = next_cpu_level; + opcode_last_postfix[rp] = postfix; +} + +static void generate_func(int noflags) { + int i, j, rp; + const char *tbl = noflags ? "nf" : "ff"; + + using_prefetch = 0; + using_exception_3 = 0; + for (i = 0; i < 1; i++) /* We only do one level! */ + { + cpu_level = 4 - i; + postfix = i; + + fprintf(stblfile, "const struct comptbl op_smalltbl_%d_comp_%s[] = {\n", + postfix, tbl); + + /* sam: this is for people with low memory (eg. me :)) */ + printf("\n" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" + "\n" + "#define PART_1 1\n" + "#define PART_2 1\n" + "#define PART_3 1\n" + "#define PART_4 1\n" + "#define PART_5 1\n" + "#define PART_6 1\n" + "#define PART_7 1\n" + "#define PART_8 1\n" + "#endif\n\n"); + + rp = 0; + for (j = 1; j <= 8; ++j) { + int k = (j * nr_cpuop_funcs) / 8; + printf("#ifdef PART_%d\n", j); + for (; rp < k; rp++) + generate_one_opcode(rp, noflags); + printf("#endif\n\n"); + } + + fprintf(stblfile, "{ 0, 65536, 0 }};\n"); + } + +} + +#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) +void cygwin_mingw_abort() +{ +#undef abort + abort(); +} +#endif + +int main(void) +{ + read_table68k(); + do_merges(); + + opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_last_postfix = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_next_clev = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + counts = (unsigned long *) malloc(65536 * sizeof(unsigned long)); + read_counts(); + + /* It would be a lot nicer to put all in one file (we'd also get rid of + * cputbl.h that way), but cpuopti can't cope. That could be fixed, but + * I don't dare to touch the 68k version. */ + + headerfile = fopen("comptbl.h", "wb"); + fprintf (headerfile, "" + "extern const struct comptbl op_smalltbl_0_comp_nf[];\n" + "extern const struct comptbl op_smalltbl_0_comp_ff[];\n" + ""); + + stblfile = fopen("compstbl.cpp", "wb"); + if (freopen("compemu.cpp", "wb", stdout) == NULL) + { + assert(0); + } + + generate_includes(stdout); + generate_includes(stblfile); + + printf("#include \"compiler/compemu.h\"\n"); + + noflags = 0; + generate_func(noflags); + + free(opcode_map); + free(opcode_last_postfix); + free(opcode_next_clev); + free(counts); + + opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_last_postfix = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + opcode_next_clev = (int *) malloc(sizeof(int) * nr_cpuop_funcs); + counts = (unsigned long *) malloc(65536 * sizeof(unsigned long)); + read_counts(); + noflags = 1; + generate_func(noflags); + + free(opcode_map); + free(opcode_last_postfix); + free(opcode_next_clev); + free(counts); + + free(table68k); + fclose(stblfile); + fclose(headerfile); + return 0; +} diff --git a/BasiliskII/src/uae_cpu/compiler/test_codegen_arm.c b/BasiliskII/src/uae_cpu/compiler/test_codegen_arm.c new file mode 100644 index 00000000..227a99d3 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/test_codegen_arm.c @@ -0,0 +1,264 @@ +/* Example of using sigaction() to setup a signal handler with 3 arguments + * including siginfo_t. + */ +#include +#include +#include +#include + +#include "flags_arm.h" +#include "codegen_arm.h" + +#define TEST(c,ex,s) { c; if (opcode != ex) printf("(%s) Invalid opcode %x expected %x\n", s, opcode, ex); } + +int opcode; + +void emit_long(v) { + opcode = v; +} + +int main (int argc, char *argv[]) +{ +TEST(MOV_ri(8, 15), 0xe3a0800f, "mov r8,#15"); +TEST(MOV_rr(8,9), 0xe1a08009, "mov r8, r9"); +TEST(MOV_rrLSLi(8,9,5), 0xe1a08289, "lsl r8, r9, #5"); +TEST(MOV_rrLSLr(8,9,7), 0xe1a08719, "lsl r8, r9, r7"); +TEST(MOV_rrLSRi(8,9,5), 0xe1a082a9, "lsr r8, r9, #5"); +TEST(MOV_rrLSRr(8,9,7), 0xe1a08739, "lsr r8, r9, r7"); +TEST(MOV_rrASRi(8,9,5), 0xe1a082c9, "asr r8, r9, #5"); +TEST(MOV_rrASRr(8,9,7), 0xe1a08759, "asr r8, r9, r7"); +TEST(MOV_rrRORi(8,9,5), 0xe1a082e9, "ror r8, r9, #5"); +TEST(MOV_rrRORr(8,9,7), 0xe1a08779, "ror r8, r9, r7"); +TEST(MOV_rrRRX(8,9), 0xe1a08069, "rrx r8, r9"); + +TEST(MOVS_ri(8, 15), 0xe3b0800f, "movs r8,#15"); +TEST(MOVS_rr(8,9), 0xe1b08009, "movs r8, r9"); +TEST(MOVS_rrLSLi(8,9,5), 0xe1b08289, "lsls r8, r9, #5"); +TEST(MOVS_rrLSLr(8,9,7), 0xe1b08719, "lsls r8, r9, r7"); +TEST(MOVS_rrLSRi(8,9,5), 0xe1b082a9, "lsrs r8, r9, #5"); +TEST(MOVS_rrLSRr(8,9,7), 0xe1b08739, "lsrs r8, r9, r7"); +TEST(MOVS_rrASRi(8,9,5), 0xe1b082c9, "asrs r8, r9, #5"); +TEST(MOVS_rrASRr(8,9,7), 0xe1b08759, "asrs r8, r9, r7"); +TEST(MOVS_rrRORi(8,9,5), 0xe1b082e9, "rors r8, r9, #5"); +TEST(MOVS_rrRORr(8,9,7), 0xe1b08779, "rors r8, r9, r7"); +TEST(MOVS_rrRRX(8,9), 0xe1b08069, "rrxs r8, r9"); + +TEST(MVN_ri(8, 15), 0xe3e0800f, "mvn r8,#15"); +TEST(MVN_rr(8,9), 0xe1e08009, "mvn r8, r9"); +TEST(MVN_rrLSLi(8,9,5), 0xe1e08289, "mvn r8, r9, lsl #5"); +TEST(MVN_rrLSLr(8,9,7), 0xe1e08719, "mvn r8, r9, lsl r7"); +TEST(MVN_rrLSRi(8,9,5), 0xe1e082a9, "mvn r8, r9, lsr #5"); +TEST(MVN_rrLSRr(8,9,7), 0xe1e08739, "mvn r8, r9, lsr r7"); +TEST(MVN_rrASRi(8,9,5), 0xe1e082c9, "mvn r8, r9, asr #5"); +TEST(MVN_rrASRr(8,9,7), 0xe1e08759, "mvn r8, r9, asr r7"); +TEST(MVN_rrRORi(8,9,5), 0xe1e082e9, "mvn r8, r9, ror #5"); +TEST(MVN_rrRORr(8,9,7), 0xe1e08779, "mvn r8, r9, ror r7"); +TEST(MVN_rrRRX(8,9), 0xe1e08069, "mvn r8, r9, rrx"); + +TEST(CMP_ri(8, 15), 0xe358000f, "cmp r8,#15"); +TEST(CMP_rr(8,9), 0xe1580009, "cmp r8, r9"); +TEST(CMP_rrLSLi(8,9,5), 0xe1580289, "cmp r8, r9, #5"); +TEST(CMP_rrLSLr(8,9,7), 0xe1580719, "cmp r8, r9, r7"); +TEST(CMP_rrLSRi(8,9,5), 0xe15802a9, "cmp r8, r9, #5"); +TEST(CMP_rrLSRr(8,9,7), 0xe1580739, "cmp r8, r9, r7"); +TEST(CMP_rrASRi(8,9,5), 0xe15802c9, "cmp r8, r9, #5"); +TEST(CMP_rrASRr(8,9,7), 0xe1580759, "cmp r8, r9, r7"); +TEST(CMP_rrRORi(8,9,5), 0xe15802e9, "cmp r8, r9, #5"); +TEST(CMP_rrRORr(8,9,7), 0xe1580779, "cmp r8, r9, r7"); +TEST(CMP_rrRRX(8,9), 0xe1580069, "cmp r8, r9"); + +TEST(CMP_ri(8, 0x81), 0xe3580081, "cmp r8,#0x81"); +TEST(CMP_ri(8, 0x204), 0xe3580f81, "cmp r8,#0x204"); +TEST(CMP_ri(8, 0x810), 0xe3580e81, "cmp r8,#0x8100"); +TEST(CMP_ri(8, 0x2040), 0xe3580d81, "cmp r8,#0x2040"); +TEST(CMP_ri(8, 0x8100), 0xe3580c81, "cmp r8,#0x8100"); +TEST(CMP_ri(8, 0x20400), 0xe3580b81, "cmp r8,#0x20400"); +TEST(CMP_ri(8, 0x81000), 0xe3580a81, "cmp r8,#0x81000"); +TEST(CMP_ri(8, 0x204000), 0xe3580981, "cmp r8,#0x204000"); +TEST(CMP_ri(8, 0x810000), 0xe3580881, "cmp r8,#0x810000"); +TEST(CMP_ri(8, 0x2040000), 0xe3580781, "cmp r8,#0x2040000"); +TEST(CMP_ri(8, 0x8100000), 0xe3580681, "cmp r8,#0x8100000"); +TEST(CMP_ri(8, 0x20400000), 0xe3580581, "cmp r8,#0x20400000"); +TEST(CMP_ri(8, 0x81000000), 0xe3580481, "cmp r8,#0x81000000"); +TEST(CMP_ri(8, 0x04000002), 0xe3580381, "cmp r8,#0x04000002"); +TEST(CMP_ri(8, 0x10000008), 0xe3580281, "cmp r8,#0x10000008"); +TEST(CMP_ri(8, 0x40000020), 0xe3580181, "cmp r8,#0x40000020"); + +TEST(CMP_ri(8, 0x1200), 0xe3580c12, "cmp r8,#0x1200"); +TEST(CMP_ri(8, 0x120000), 0xe3580812, "cmp r8,#0x120000"); +TEST(CMP_ri(8, 0x12000000), 0xe3580412, "cmp r8,#0x12000000"); + +TEST(BEQ_i(5), 0x0a000005, "beq #5"); +TEST(BNE_i(5), 0x1a000005, "bne #5"); +TEST(BCS_i(5), 0x2a000005, "bcs #5"); +TEST(BCC_i(5), 0x3a000005, "bcc #5"); +TEST(BMI_i(5), 0x4a000005, "bmi #5"); +TEST(BPL_i(5), 0x5a000005, "bpl #5"); +TEST(BVS_i(5), 0x6a000005, "bvs #5"); +TEST(BVC_i(5), 0x7a000005, "bvc #5"); +TEST(BHI_i(5), 0x8a000005, "bhi #5"); +TEST(BLS_i(5), 0x9a000005, "bls #5"); +TEST(BGE_i(5), 0xaa000005, "bge #5"); +TEST(BLT_i(5), 0xba000005, "blt #5"); +TEST(BGT_i(5), 0xca000005, "bgt #5"); +TEST(BLE_i(5), 0xda000005, "ble #5"); +TEST(B_i(5), 0xea000005, "b #5"); + +TEST(BL_i(5), 0xeb000005, "bl #5"); +TEST(BLX_r(8), 0xe12fff38, "blx r8"); +TEST(BX_r(8), 0xe12fff18, "bx r8"); + +TEST(EOR_rri(6, 8, 15), 0xe228600f, "eor r6, r8,#15"); +TEST(EOR_rrr(6, 8,9), 0xe0286009, "eor r6, r8, r9"); +TEST(EOR_rrrLSLi(6,8,9,5), 0xe0286289, "eor r6, r8, r9, lsl #5"); +TEST(EOR_rrrLSLr(6,8,9,7), 0xe0286719, "eor r6, r8, r9, lsl r7"); +TEST(EOR_rrrLSRi(6,8,9,5), 0xe02862a9, "eor r6, r8, r9, lsr #5"); +TEST(EOR_rrrLSRr(6,8,9,7), 0xe0286739, "eor r6, r8, r9, lsr r7"); +TEST(EOR_rrrASRi(6,8,9,5), 0xe02862c9, "eor r6, r8, r9, asr #5"); +TEST(EOR_rrrASRr(6,8,9,7), 0xe0286759, "eor r6, r8, r9, asr r7"); +TEST(EOR_rrrRORi(6,8,9,5), 0xe02862e9, "eor r6, r8, r9, ror #5"); +TEST(EOR_rrrRORr(6,8,9,7), 0xe0286779, "eor r6, r8, r9, ror r7"); +TEST(EOR_rrrRRX(6,8,9), 0xe0286069, "eor r6, r8, r9, rrx"); + +TEST(EORS_rri(6, 8, 15), 0xe238600f, "eors r6, r8,#15"); +TEST(EORS_rrr(6, 8,9), 0xe0386009, "eors r6, r8, r9"); +TEST(EORS_rrrLSLi(6,8,9,5), 0xe0386289, "eors r6, r8, r9, lsl #5"); +TEST(EORS_rrrLSLr(6,8,9,7), 0xe0386719, "eors r6, r8, r9, lsr r7"); +TEST(EORS_rrrLSRi(6,8,9,5), 0xe03862a9, "eors r6, r8, r9, lsr #5"); +TEST(EORS_rrrLSRr(6,8,9,7), 0xe0386739, "eors r6, r8, r9, lsr r7"); +TEST(EORS_rrrASRi(6,8,9,5), 0xe03862c9, "eors r6, r8, r9, asr #5"); +TEST(EORS_rrrASRr(6,8,9,7), 0xe0386759, "eors r6, r8, r9, asr r7"); +TEST(EORS_rrrRORi(6,8,9,5), 0xe03862e9, "eors r6, r8, r9, ror #5"); +TEST(EORS_rrrRORr(6,8,9,7), 0xe0386779, "eors r6, r8, r9, ror r7"); +TEST(EORS_rrrRRX(6,8,9), 0xe0386069, "eors r6, r8, r9, rrx"); + +TEST(MRS_CPSR(6), 0xe10f6000, "mrs r6, CPSR"); +TEST(MRS_SPSR(6), 0xe14f6000, "mrs r6, SPSR"); + +TEST(MSR_CPSR_i(5), 0xe329f005, "msr CPSR_fc, #5"); +TEST(MSR_CPSR_r(5), 0xe129f005, "msr CPSR_fc, r5"); + +TEST(MSR_CPSRf_i(5), 0xe328f005, "msr CPSR_f, #5"); +TEST(MSR_CPSRf_r(5), 0xe128f005, "msr CPSR_f, r5"); + +TEST(MSR_CPSRc_i(5), 0xe321f005, "msr CPSR_c, #5"); +TEST(MSR_CPSRc_r(5), 0xe121f005, "msr CPSR_c, r5"); + +TEST(PUSH(6), 0xe92d0040, "push {r6}"); +TEST(POP(6), 0xe8bd0040, "pop {r6}"); + +TEST(BIC_rri(0, 0, 0x9f000000), 0xe3c0049f, "bic r0, r0, #0x9f000000"); +TEST(BIC_rri(2, 3, 0xff00), 0xe3c32cff, "bic r2, r3, #0xff00"); +TEST(BIC_rri(3, 4, 0xff), 0xe3c430ff, "bic r3, r4, #0xff"); + +TEST(ORR_rrrLSRi(0, 1, 2, 16), 0xe1810822, "orr r0, r1, r2, lsr #16"); +TEST(ORR_rrrLSRi(0, 1, 2, 24), 0xe1810c22, "orr r0, r1, r2, lsr #24"); + +TEST(LDR_rR(8, 9), 0xe5998000, "ldr r8, [r9]"); +TEST(LDR_rRI(8, 9, 4), 0xe5998004, "ldr r8, [r9, #4]"); +TEST(LDR_rRi(8, 9, 4), 0xe5198004, "ldr r8, [r9, #-4]"); +TEST(LDR_rRR(8, 9, 7), 0xe7998007, "ldr r8, [r9, r7]"); +TEST(LDR_rRr(8, 9, 7), 0xe7198007, "ldr r8, [r9, -r7]"); +TEST(LDR_rRR_LSLi(8, 9, 7, 5), 0xe7998287, "ldr r8, [r9, r7, lsl #5]"); +TEST(LDR_rRr_LSLi(8, 9, 7, 5), 0xe7198287, "ldr r8, [r9, -r7, lsl #5]"); +TEST(LDR_rRR_LSRi(8, 9, 7, 5), 0xe79982a7, "ldr r8, [r9, r7, lsr #5]"); +TEST(LDR_rRr_LSRi(8, 9, 7, 5), 0xe71982a7, "ldr r8, [r9, -r7, lsr #5]"); +TEST(LDR_rRR_ASRi(8, 9, 7, 5), 0xe79982c7, "ldr r8, [r9, r7, asr #5]"); +TEST(LDR_rRr_ASRi(8, 9, 7, 5), 0xe71982c7, "ldr r8, [r9, -r7, asr #5]"); +TEST(LDR_rRR_RORi(8, 9, 7, 5), 0xe79982e7, "ldr r8, [r9, r7, ror #5]"); +TEST(LDR_rRr_RORi(8, 9, 7, 5), 0xe71982e7, "ldr r8, [r9, -r7, ror #5]"); +TEST(LDR_rRR_RRX(8, 9, 7), 0xe7998067, "ldr r8, [r9, r7, rrx]"); +TEST(LDR_rRr_RRX(8, 9, 7), 0xe7198067, "ldr r8, [r9, -r7, rrx]"); + +TEST(LDRB_rR(8, 9), 0xe5d98000, "ldrb r8, [r9]"); +TEST(LDRB_rRI(8, 9, 4), 0xe5d98004, "ldrb r8, [r9, #4]"); +TEST(LDRB_rRi(8, 9, 4), 0xe5598004, "ldrb r8, [r9, #-4]"); +TEST(LDRB_rRR(8, 9, 7), 0xe7d98007, "ldrb r8, [r9, r7]"); +TEST(LDRB_rRr(8, 9, 7), 0xe7598007, "ldrb r8, [r9, -r7]"); +TEST(LDRB_rRR_LSLi(8, 9, 7, 5), 0xe7d98287, "ldrb r8, [r9, r7, lsl #5]"); +TEST(LDRB_rRr_LSLi(8, 9, 7, 5), 0xe7598287, "ldrb r8, [r9, -r7, lsl #5]"); +TEST(LDRB_rRR_LSRi(8, 9, 7, 5), 0xe7d982a7, "ldrb r8, [r9, r7, lsr #5]"); +TEST(LDRB_rRr_LSRi(8, 9, 7, 5), 0xe75982a7, "ldrb r8, [r9, -r7, lsr #5]"); +TEST(LDRB_rRR_ASRi(8, 9, 7, 5), 0xe7d982c7, "ldrb r8, [r9, r7, asr #5]"); +TEST(LDRB_rRr_ASRi(8, 9, 7, 5), 0xe75982c7, "ldrb r8, [r9, -r7, asr #5]"); +TEST(LDRB_rRR_RORi(8, 9, 7, 5), 0xe7d982e7, "ldrb r8, [r9, r7, ror #5]"); +TEST(LDRB_rRr_RORi(8, 9, 7, 5), 0xe75982e7, "ldrb r8, [r9, -r7, ror #5]"); +TEST(LDRB_rRR_RRX(8, 9, 7), 0xe7d98067, "ldrb r8, [r9, r7, rrx]"); +TEST(LDRB_rRr_RRX(8, 9, 7), 0xe7598067, "ldrb r8, [r9, -r7, rrx]"); + +TEST(LDRSB_rR(8, 9), 0xe1d980d0, "ldrsb r8, [r9]"); +TEST(LDRSB_rRI(8, 9, 4), 0xe1d980d4, "ldrsb r8, [r9, #4]"); +TEST(LDRSB_rRi(8, 9, 4), 0xe15980d4, "ldrsb r8, [r9, #-4]"); +TEST(LDRSB_rRR(8, 9, 7), 0xe19980d7, "ldrsb r8, [r9, r7]"); +TEST(LDRSB_rRr(8, 9, 7), 0xe11980d7, "ldrsb r8, [r9, -r7]"); + +TEST(LDRSH_rR(8, 9), 0xe1d980f0, "ldrsh r8, [r9]"); +TEST(LDRSH_rRI(8, 9, 4), 0xe1d980f4, "ldrsh r8, [r9, #4]"); +TEST(LDRSH_rRi(8, 9, 4), 0xe15980f4, "ldrsh r8, [r9, #-4]"); +TEST(LDRSH_rRR(8, 9, 7), 0xe19980f7, "ldrsh r8, [r9, r7]"); +TEST(LDRSH_rRr(8, 9, 7), 0xe11980f7, "ldrsh r8, [r9, -r7]"); + +TEST(LDRH_rR(8, 9), 0xe1d980b0, "ldrh r8, [r9]"); +TEST(LDRH_rRI(8, 9, 4), 0xe1d980b4, "ldrh r8, [r9, #4]"); +TEST(LDRH_rRi(8, 9, 4), 0xe15980b4, "ldrh r8, [r9, #-4]"); +TEST(LDRH_rRR(8, 9, 7), 0xe19980b7, "ldrh r8, [r9, r7]"); +TEST(LDRH_rRr(8, 9, 7), 0xe11980b7, "ldrh r8, [r9, -r7]"); + +TEST(STR_rRR(8,9,7), 0xe7898007, "str r8, [r9, r7]"); +TEST(STR_rRr(8,9,7), 0xe7098007, "str r8, [r9, -r7]"); + +TEST(STRB_rR(5, 6), 0xe5c65000, "strb r5,[r6]"); + +TEST(STRH_rR(8, 9), 0xe1c980b0, "strh r8, [r9]"); +TEST(STRH_rRI(8, 9, 4), 0xe1c980b4, "strh r8, [r9, #4]"); +TEST(STRH_rRi(8, 9, 4), 0xe14980b4, "strh r8, [r9, #-4]"); +TEST(STRH_rRR(8, 9, 7), 0xe18980b7, "strh r8, [r9, r7]"); +TEST(STRH_rRr(8, 9, 7), 0xe10980b7, "strh r8, [r9, -r7]"); + +TEST(CLZ_rr(2, 3), 0xe16f2f13, "clz r2,r3"); +TEST(REV_rr(2, 3), 0xe6bf2f33, "rev r2, r3"); +TEST(REV16_rr(2, 3), 0xe6bf2fb3, "rev16 r2, r3"); +TEST(REVSH_rr(2, 3), 0xe6ff2fb3, "revsh r2, r3"); + +TEST(SXTB_rr(2,3), 0xe6af2073, "sxtb r2,r3"); +TEST(SXTB_rr(3,4), 0xe6af3074, "sxtb r3,r4"); + +TEST(SXTB_rr_ROR8(2,3), 0xe6af2473, "sxtb r2, r3, ror #8"); +TEST(SXTB_rr_ROR16(2,3), 0xe6af2873, "sxtb r2, r3, ror #16"); +TEST(SXTB_rr_ROR24(2,3), 0xe6af2c73, "sxtb r2, r3, ror #24"); +TEST(SXTH_rr(2,3), 0xe6bf2073, "sxth r2, r3"); +TEST(SXTH_rr_ROR8(2,3), 0xe6bf2473, "sxth r2, r3, ror #8"); +TEST(SXTH_rr_ROR16(2,3), 0xe6bf2873, "sxth r2, r3, ror #16"); +TEST(SXTH_rr_ROR24(2,3), 0xe6bf2c73, "sxth r2, r3, ror #24"); +TEST(UXTB_rr(2,3), 0xe6ef2073, "uxtb r2, r3"); +TEST(UXTB_rr_ROR8(2,3), 0xe6ef2473, "uxtb r2, r3, ror #8"); +TEST(UXTB_rr_ROR16(2,3), 0xe6ef2873, "uxtb r2, r3, ror #16"); +TEST(UXTB_rr_ROR24(2,3), 0xe6ef2c73, "uxtb r2, r3, ror #24"); +TEST(UXTH_rr(2,3), 0xe6ff2073, "uxth r2, r3"); +TEST(UXTH_rr_ROR8(2,3), 0xe6ff2473, "uxth r2, r3, ror #8"); +TEST(UXTH_rr_ROR16(2,3), 0xe6ff2873, "uxth r2, r3, ror #16"); +TEST(UXTH_rr_ROR24(2,3), 0xe6ff2c73, "uxth r2, r3, ror #24"); + +TEST(REV_rr(2,3), 0xe6bf2f33, "rev r2, r3"); +TEST(REV16_rr(2,3), 0xe6bf2fb3, "rev16 r2, r3"); +TEST(REVSH_rr(2,3), 0xe6ff2fb3, "revsh r2, r3"); + +TEST(CC_MOV_ri(NATIVE_CC_CS, 4,1), 0x23a04001, "movcs r4, #1"); +TEST(CC_MOV_ri(NATIVE_CC_CC, 4,1), 0x33a04001, "movcc r4, #1"); + +int imm = 0x9f; +TEST(ADDS_rri(0, 0, imm << 24), 0xe290049f, "adds r0, r0, 0x9f000000"); + +TEST(PKHBT_rrr(1, 2, 3), 0xe6821013, "pkhbt r1,r2,r3"); +TEST(MVN_ri8(1,2), 0xe3e01002, "mvn r1,#2"); + +TEST(ORR_rri8RORi(1,2,0x12,24), 0xe3821c12, "orr r1, r2, #0x1200"); +TEST(PKHTB_rrrASRi(1, 2, 3, 4), 0xe6821253, "pkhtb r1,r2,r3,ASR #4"); +TEST(PKHBT_rrrLSLi(1, 2, 3, 4), 0xe6821213, "pkhbt r1,r2,r3,LSL #4"); + +TEST(MUL_rrr(1,2,3), 0xe0010392, "mul r1, r2, r3"); +TEST(MULS_rrr(1,2,3), 0xe0110392, "muls r1, r2, r3"); + + +} + diff --git a/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp new file mode 100644 index 00000000..216effe5 --- /dev/null +++ b/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp @@ -0,0 +1,1008 @@ +/******************** -*- mode: C; tab-width: 8 -*- ******************** + * + * Dumb and Brute Force Run-time assembler verifier for IA-32 and AMD64 + * + ***********************************************************************/ + + +/*********************************************************************** + * + * Copyright 2004 Gwenole Beauchesne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + ***********************************************************************/ + +/* + * STATUS: 5.5M variations covering unary register based operations, + * reg/reg operations, imm/reg operations. + * + * TODO: + * - Rewrite to use internal BFD/opcodes format instead of string compares + * - Add reg/mem, imm/mem variations + */ + +#define _BSD_SOURCE 1 +#include +#include +#include +#include +#include +#include + +#include "sysdeps.h" + +#undef abort +#define abort() do { \ + fprintf(stderr, "ABORT: %s, line %d\n", __FILE__, __LINE__); \ + (abort)(); \ +} while (0) + +#define X86_TARGET_64BIT 1 +#define X86_FLAT_REGISTERS 0 +#define X86_OPTIMIZE_ALU 1 +#define X86_OPTIMIZE_ROTSHI 1 +#include "compiler/codegen_x86.h" + +#define x86_emit_byte(B) emit_byte(B) +#define x86_emit_word(W) emit_word(W) +#define x86_emit_long(L) emit_long(L) +#define x86_emit_quad(Q) emit_quad(Q) +#define x86_get_target() get_target() +#define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__) + +static void jit_fail(const char *msg, const char *file, int line, const char *function) +{ + fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n", + function, file, line, msg); + abort(); +} + +static uint8 *target; + +static inline void emit_byte(uint8 x) +{ + *target++ = x; +} + +static inline void emit_word(uint16 x) +{ + *((uint16 *)target) = x; + target += 2; +} + +static inline void emit_long(uint32 x) +{ + *((uint32 *)target) = x; + target += 4; +} + +static inline void emit_quad(uint64 x) +{ + *((uint64 *)target) = x; + target += 8; +} + +static inline void set_target(uint8 *t) +{ + target = t; +} + +static inline uint8 *get_target(void) +{ + return target; +} + +static uint32 mon_read_byte(uintptr addr) +{ + uint8 *m = (uint8 *)addr; + return (uint32)(*m); +} + +extern "C" { +#include "disass/dis-asm.h" + +int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info) +{ + while (length--) + *to++ = mon_read_byte(from++); + return 0; +} + +void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info) +{ + info->fprintf_func(info->stream, "Unknown error %d\n", status); +} + +void generic_print_address(bfd_vma addr, struct disassemble_info *info) +{ + if (addr >= UVAL64(0x100000000)) + info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr); + else + info->fprintf_func(info->stream, "$%08x", (uint32)addr); +} + +int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info) +{ + return 0; +} +} + +struct SFILE { + char *buffer; + char *current; +}; + +static int mon_sprintf(SFILE *f, const char *format, ...) +{ + int n; + va_list args; + va_start(args, format); + vsprintf(f->current, format, args); + f->current += n = strlen(f->current); + va_end(args); + return n; +} + +static int disass_x86(char *buf, uintptr adr) +{ + disassemble_info info; + SFILE sfile; + sfile.buffer = buf; + sfile.current = buf; + INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf); + info.mach = bfd_mach_x86_64; + info.disassembler_options = "suffix"; + return print_insn_i386(adr, &info); +} + +enum { + op_disp, + op_reg, + op_base, + op_index, + op_scale, + op_imm, +}; +struct operand_t { + int32 disp; + int8 reg; + int8 base; + int8 index; + int8 scale; + int64 imm; + + void clear() { + disp = imm = 0; + reg = base = index = -1; + scale = 1; + } + + void fill(int optype, int value) { + switch (optype) { + case op_disp: disp = value; break; + case op_reg: reg = value; break; + case op_base: base = value; break; + case op_index: index = value; break; + case op_scale: scale = value; break; + case op_imm: imm = value; break; + default: abort(); + } + } +}; + +struct insn_t { + char name[16]; + int n_operands; +#define MAX_OPERANDS 3 + operand_t operands[MAX_OPERANDS]; + + void clear() { + memset(name, 0, sizeof(name)); + n_operands = 0; + for (int i = 0; i < MAX_OPERANDS; i++) + operands[i].clear(); + } + + void pretty_print() { + printf("%s, %d operands\n", name, n_operands); + for (int i = 0; i < n_operands; i++) { + operand_t *op = &operands[i]; + if (op->reg != -1) + printf(" reg r%d\n", op->reg); + else { + printf(" mem 0x%08x(", op->disp); + if (op->base != -1) + printf("r%d", op->base); + printf(","); + if (op->index != -1) + printf("r%d", op->index); + printf(","); + if (op->base != -1 || op->index != -1) + printf("%d", op->scale); + printf(")\n"); + } + } + } +}; + +static const struct { + const char *name; + int reg; +} +regnames[] = { +#define _(REG) { #REG, X86_##REG } + + _(AL), _(CL), _(DL), _(BL), + _(AH), _(CH), _(DH), _(BH), + _(SPL), _(BPL), _(SIL), _(DIL), + _(R8B), _(R9B), _(R10B), _(R11B), _(R12B), _(R13B), _(R14B), _(R15B), + + _(AX), _(CX), _(DX), _(BX), _(SP), _(BP), _(SI), _(DI), + _(R8W), _(R9W), _(R10W), _(R11W), _(R12W), _(R13W), _(R14W), _(R15W), + + _(EAX), _(ECX), _(EDX), _(EBX), _(ESP), _(EBP), _(ESI), _(EDI), + _(R8D), _(R9D), _(R10D), _(R11D), _(R12D), _(R13D), _(R14D), _(R15D), + + _(RAX), _(RCX), _(RDX), _(RBX), _(RSP), _(RBP), _(RSI), _(RDI), + _(R8), _(R9), _(R10), _(R11), _(R12), _(R13), _(R14), _(R15), + + { NULL, -1 } +#undef _ +}; + +static int parse_reg(operand_t *op, int optype, char *buf) +{ + for (int i = 0; regnames[i].name; i++) { + int len = strlen(regnames[i].name); + if (strncasecmp(regnames[i].name, buf, len) == 0) { + op->fill(optype, regnames[i].reg); + return len; + } + } + return 0; +} + +static int parse_mem(operand_t *op, char *buf) +{ + char *p = buf; + + if (strncmp(buf, "0x", 2) == 0) { + unsigned long val = strtoul(buf, &p, 16); + if (val == 0 && errno == EINVAL) + abort(); + op->disp = val; + } + + if (*p == '(') { + p++; + + if (*p == '%') { + p++; + + int n = parse_reg(op, op_base, p); + if (n <= 0) + return -3; + p += n; + } + + if (*p == ',') { + p++; + + if (*p == '%') { + int n = parse_reg(op, op_index, ++p); + if (n <= 0) + return -4; + p += n; + + if (*p != ',') + return -5; + p++; + + goto do_parse_scale; + } + else if (isdigit(*p)) { + do_parse_scale: + long val = strtol(p, &p, 10); + if (val == 0 && errno == EINVAL) + abort(); + op->scale = val; + } + } + + if (*p != ')') + return -6; + p++; + } + + return p - buf; +} + +static void parse_insn(insn_t *ii, char *buf) +{ + char *p = buf; + ii->clear(); + + for (int i = 0; !isspace(*p); i++) + ii->name[i] = *p++; + + while (*p && isspace(*p)) + p++; + if (*p == '\0') + return; + + int n_operands = 0; + int optype = op_reg; + bool done = false; + while (!done) { + int n; + switch (*p) { + case '%': + n = parse_reg(&ii->operands[n_operands], optype, ++p); + if (n <= 0) { + fprintf(stderr, "parse_reg(%s) error %d\n", p, n); + abort(); + } + p += n; + break; + case '0': case '(': + n = parse_mem(&ii->operands[n_operands], p); + if (n <= 0) { + fprintf(stderr, "parse_mem(%s) error %d\n", p, n); + abort(); + } + p += n; + break; + case '$': { + unsigned long val = strtoul(++p, &p, 16); + if (val == 0 && errno == EINVAL) + abort(); + ii->operands[n_operands].imm = val; + break; + } + case '*': + p++; + break; + case ',': + n_operands++; + p++; + break; + case ' ': case '\t': + p++; + break; + case '\0': + done = true; + break; + default: + fprintf(stderr, "parse error> %s\n", p); + abort(); + } + } + ii->n_operands = n_operands + 1; +} + +static long n_tests, n_failures; +static long n_all_tests, n_all_failures; + +static bool check_reg(insn_t *ii, const char *name, int r) +{ + if (strcasecmp(ii->name, name) != 0) { + fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); + return false; + } + + if (ii->n_operands != 1) { + fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands); + return false; + } + + int reg = ii->operands[0].reg; + + if (reg != r) { + fprintf(stderr, "ERROR: instruction expected r%d as source, got ", r); + if (reg == -1) + fprintf(stderr, "nothing\n"); + else + fprintf(stderr, "%d\n", reg); + return false; + } + + return true; +} + +static bool check_reg_reg(insn_t *ii, const char *name, int s, int d) +{ + if (strcasecmp(ii->name, name) != 0) { + fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); + return false; + } + + if (ii->n_operands != 2) { + fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands); + return false; + } + + int srcreg = ii->operands[0].reg; + int dstreg = ii->operands[1].reg; + + if (srcreg != s) { + fprintf(stderr, "ERROR: instruction expected r%d as source, got ", s); + if (srcreg == -1) + fprintf(stderr, "nothing\n"); + else + fprintf(stderr, "%d\n", srcreg); + return false; + } + + if (dstreg != d) { + fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d); + if (dstreg == -1) + fprintf(stderr, "nothing\n"); + else + fprintf(stderr, "%d\n", dstreg); + return false; + } + + return true; +} + +static bool check_imm_reg(insn_t *ii, const char *name, uint32 v, int d, int mode = -1) +{ + if (strcasecmp(ii->name, name) != 0) { + fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); + return false; + } + + if (ii->n_operands != 2) { + fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands); + return false; + } + + uint32 imm = ii->operands[0].imm; + int dstreg = ii->operands[1].reg; + + if (mode == -1) { + char suffix = name[strlen(name) - 1]; + switch (suffix) { + case 'b': mode = 1; break; + case 'w': mode = 2; break; + case 'l': mode = 4; break; + case 'q': mode = 8; break; + } + } + switch (mode) { + case 1: v &= 0xff; break; + case 2: v &= 0xffff; break; + } + + if (imm != v) { + fprintf(stderr, "ERROR: instruction expected 0x%08x as immediate, got ", v); + if (imm == -1) + fprintf(stderr, "nothing\n"); + else + fprintf(stderr, "0x%08x\n", imm); + return false; + } + + if (dstreg != d) { + fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d); + if (dstreg == -1) + fprintf(stderr, "nothing\n"); + else + fprintf(stderr, "%d\n", dstreg); + return false; + } + + return true; +} + +static bool check_mem_reg(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R) +{ + if (strcasecmp(ii->name, name) != 0) { + fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name); + return false; + } + + if (ii->n_operands != 2) { + fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands); + return false; + } + + operand_t *mem = &ii->operands[0]; + operand_t *reg = &ii->operands[1]; + + uint32 d = mem->disp; + int b = mem->base; + int i = mem->index; + int s = mem->scale; + int r = reg->reg; + + if (d != D) { + fprintf(stderr, "ERROR: instruction expected 0x%08x as displacement, got 0x%08x\n", D, d); + return false; + } + + if (b != B) { + fprintf(stderr, "ERROR: instruction expected r%d as base, got r%d\n", B, b); + return false; + } + + if (i != I) { + fprintf(stderr, "ERROR: instruction expected r%d as index, got r%d\n", I, i); + return false; + } + + if (s != S) { + fprintf(stderr, "ERROR: instruction expected %d as scale factor, got %d\n", S, s); + return false; + } + + if (r != R) { + fprintf(stderr, "ERROR: instruction expected r%d as reg operand, got r%d\n", R, r); + return false; + } + + return true; +} + +static int verbose = 2; + +int main(void) +{ + static char buffer[1024]; +#define MAX_INSN_LENGTH 16 +#define MAX_INSNS 1024 + static uint8 block[MAX_INSNS * MAX_INSN_LENGTH]; + static char *insns[MAX_INSNS]; + static int modes[MAX_INSNS]; + n_all_tests = n_all_failures = 0; + + printf("Testing reg forms\n"); + n_tests = n_failures = 0; + for (int r = 0; r < 16; r++) { + set_target(block); + uint8 *b = get_target(); + int i = 0; +#define GEN(INSN, GENOP) do { \ + insns[i++] = INSN; \ + GENOP##r(r); \ +} while (0) +#define GENA(INSN, GENOP) do { \ + GEN(INSN "b", GENOP##B); \ + GEN(INSN "w", GENOP##W); \ + GEN(INSN "l", GENOP##L); \ + GEN(INSN "q", GENOP##Q); \ +} while (0) + GENA("not", NOT); + GENA("neg", NEG); + GENA("mul", MUL); + GENA("imul", IMUL); + GENA("div", DIV); + GENA("idiv", IDIV); + GENA("dec", DEC); + GENA("inc", INC); + GEN("callq", CALLs); + GEN("jmpq", JMPs); + GEN("pushl", PUSHQ); // FIXME: disass bug? wrong suffix + GEN("popl", POPQ); // FIXME: disass bug? wrong suffix + GEN("bswap", BSWAPL); // FIXME: disass bug? no suffix + GEN("bswap", BSWAPQ); // FIXME: disass bug? no suffix + GEN("seto", SETO); + GEN("setno", SETNO); + GEN("setb", SETB); + GEN("setae", SETAE); + GEN("sete", SETE); + GEN("setne", SETNE); + GEN("setbe", SETBE); + GEN("seta", SETA); + GEN("sets", SETS); + GEN("setns", SETNS); + GEN("setp", SETP); + GEN("setnp", SETNP); + GEN("setl", SETL); + GEN("setge", SETGE); + GEN("setle", SETLE); + GEN("setg", SETG); +#undef GENA +#undef GEN + int last_insn = i; + uint8 *e = get_target(); + + uint8 *p = b; + i = 0; + while (p < e) { + int n = disass_x86(buffer, (uintptr)p); + insn_t ii; + parse_insn(&ii, buffer); + + if (!check_reg(&ii, insns[i], r)) { + if (verbose > 1) + fprintf(stderr, "%s\n", buffer); + n_failures++; + } + + p += n; + i += 1; + n_tests++; + } + if (i != last_insn) + abort(); + } + printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); + n_all_tests += n_tests; + n_all_failures += n_failures; + + printf("Testing reg,reg forms\n"); + n_tests = n_failures = 0; + for (int s = 0; s < 16; s++) { + for (int d = 0; d < 16; d++) { + set_target(block); + uint8 *b = get_target(); + int i = 0; +#define GEN(INSN, GENOP) do { \ + insns[i++] = INSN; \ + GENOP##rr(s, d); \ +} while (0) +#define GEN1(INSN, GENOP, OP) do { \ + insns[i++] = INSN; \ + GENOP##rr(OP, s, d); \ +} while (0) +#define GENA(INSN, GENOP) do { \ + GEN(INSN "b", GENOP##B); \ + GEN(INSN "w", GENOP##W); \ + GEN(INSN "l", GENOP##L); \ + GEN(INSN "q", GENOP##Q); \ +} while (0) + GENA("adc", ADC); + GENA("add", ADD); + GENA("and", AND); + GENA("cmp", CMP); + GENA("or", OR); + GENA("sbb", SBB); + GENA("sub", SUB); + GENA("xor", XOR); + GENA("mov", MOV); + GEN("btw", BTW); + GEN("btl", BTL); + GEN("btq", BTQ); + GEN("btcw", BTCW); + GEN("btcl", BTCL); + GEN("btcq", BTCQ); + GEN("btrw", BTRW); + GEN("btrl", BTRL); + GEN("btrq", BTRQ); + GEN("btsw", BTSW); + GEN("btsl", BTSL); + GEN("btsq", BTSQ); + GEN("imulw", IMULW); + GEN("imull", IMULL); + GEN("imulq", IMULQ); + GEN1("cmove", CMOVW, X86_CC_Z); + GEN1("cmove", CMOVL, X86_CC_Z); + GEN1("cmove", CMOVQ, X86_CC_Z); + GENA("test", TEST); + GENA("cmpxchg", CMPXCHG); + GENA("xadd", XADD); + GENA("xchg", XCHG); + GEN("bsfw", BSFW); + GEN("bsfl", BSFL); + GEN("bsfq", BSFQ); + GEN("bsrw", BSRW); + GEN("bsrl", BSRL); + GEN("bsrq", BSRQ); + GEN("movsbw", MOVSBW); + GEN("movsbl", MOVSBL); + GEN("movsbq", MOVSBQ); + GEN("movzbw", MOVZBW); + GEN("movzbl", MOVZBL); + GEN("movzbq", MOVZBQ); + GEN("movswl", MOVSWL); + GEN("movswq", MOVSWQ); + GEN("movzwl", MOVZWL); + GEN("movzwq", MOVZWQ); + GEN("movslq", MOVSLQ); +#undef GENA +#undef GEN1 +#undef GEN + int last_insn = i; + uint8 *e = get_target(); + + uint8 *p = b; + i = 0; + while (p < e) { + int n = disass_x86(buffer, (uintptr)p); + insn_t ii; + parse_insn(&ii, buffer); + + if (!check_reg_reg(&ii, insns[i], s, d)) { + if (verbose > 1) + fprintf(stderr, "%s\n", buffer); + n_failures++; + } + + p += n; + i += 1; + n_tests++; + } + if (i != last_insn) + abort(); + } + } + printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); + n_all_tests += n_tests; + n_all_failures += n_failures; + + printf("Testing cl,reg forms\n"); + n_tests = n_failures = 0; + for (int d = 0; d < 16; d++) { + set_target(block); + uint8 *b = get_target(); + int i = 0; +#define GEN(INSN, GENOP) do { \ + insns[i++] = INSN; \ + GENOP##rr(X86_CL, d); \ +} while (0) +#define GENA(INSN, GENOP) do { \ + GEN(INSN "b", GENOP##B); \ + GEN(INSN "w", GENOP##W); \ + GEN(INSN "l", GENOP##L); \ + GEN(INSN "q", GENOP##Q); \ +} while (0) + GENA("rol", ROL); + GENA("ror", ROR); + GENA("rcl", RCL); + GENA("rcr", RCR); + GENA("shl", SHL); + GENA("shr", SHR); + GENA("sar", SAR); +#undef GENA +#undef GEN + int last_insn = i; + uint8 *e = get_target(); + + uint8 *p = b; + i = 0; + while (p < e) { + int n = disass_x86(buffer, (uintptr)p); + insn_t ii; + parse_insn(&ii, buffer); + + if (!check_reg_reg(&ii, insns[i], X86_CL, d)) { + if (verbose > 1) + fprintf(stderr, "%s\n", buffer); + n_failures++; + } + + p += n; + i += 1; + n_tests++; + } + if (i != last_insn) + abort(); + } + printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); + n_all_tests += n_tests; + n_all_failures += n_failures; + + printf("Testing imm,reg forms\n"); + static const uint32 imm_table[] = { + 0x00000000, 0x00000001, 0x00000002, 0x00000004, + 0x00000008, 0x00000010, 0x00000020, 0x00000040, + 0x00000080, 0x000000fe, 0x000000ff, 0x00000100, + 0x00000101, 0x00000102, 0xfffffffe, 0xffffffff, + 0x00000000, 0x10000000, 0x20000000, 0x30000000, + 0x40000000, 0x50000000, 0x60000000, 0x70000000, + 0x80000000, 0x90000000, 0xa0000000, 0xb0000000, + 0xc0000000, 0xd0000000, 0xe0000000, 0xf0000000, + 0xfffffffd, 0xfffffffe, 0xffffffff, 0x00000001, + 0x00000002, 0x00000003, 0x11111111, 0x22222222, + 0x33333333, 0x44444444, 0x55555555, 0x66666666, + 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa, + 0xbbbbbbbb, 0xcccccccc, 0xdddddddd, 0xeeeeeeee, + }; + const int n_imm_tab_count = sizeof(imm_table)/sizeof(imm_table[0]); + n_tests = n_failures = 0; + for (int j = 0; j < n_imm_tab_count; j++) { + const uint32 value = imm_table[j]; + for (int d = 0; d < 16; d++) { + set_target(block); + uint8 *b = get_target(); + int i = 0; +#define GEN(INSN, GENOP) do { \ + insns[i] = INSN; \ + modes[i] = -1; \ + i++; GENOP##ir(value, d); \ + } while (0) +#define GENM(INSN, GENOP, MODE) do { \ + insns[i] = INSN; \ + modes[i] = MODE; \ + i++; GENOP##ir(value, d); \ + } while (0) +#define GENA(INSN, GENOP) do { \ + GEN(INSN "b", GENOP##B); \ + GEN(INSN "w", GENOP##W); \ + GEN(INSN "l", GENOP##L); \ + GEN(INSN "q", GENOP##Q); \ + } while (0) +#define GENAM(INSN, GENOP, MODE) do { \ + GENM(INSN "b", GENOP##B, MODE); \ + GENM(INSN "w", GENOP##W, MODE); \ + GENM(INSN "l", GENOP##L, MODE); \ + GENM(INSN "q", GENOP##Q, MODE); \ + } while (0) + GENA("adc", ADC); + GENA("add", ADD); + GENA("and", AND); + GENA("cmp", CMP); + GENA("or", OR); + GENA("sbb", SBB); + GENA("sub", SUB); + GENA("xor", XOR); + GENA("mov", MOV); + GENM("btw", BTW, 1); + GENM("btl", BTL, 1); + GENM("btq", BTQ, 1); + GENM("btcw", BTCW, 1); + GENM("btcl", BTCL, 1); + GENM("btcq", BTCQ, 1); + GENM("btrw", BTRW, 1); + GENM("btrl", BTRL, 1); + GENM("btrq", BTRQ, 1); + GENM("btsw", BTSW, 1); + GENM("btsl", BTSL, 1); + GENM("btsq", BTSQ, 1); + if (value != 1) { + GENAM("rol", ROL, 1); + GENAM("ror", ROR, 1); + GENAM("rcl", RCL, 1); + GENAM("rcr", RCR, 1); + GENAM("shl", SHL, 1); + GENAM("shr", SHR, 1); + GENAM("sar", SAR, 1); + } + GENA("test", TEST); +#undef GENAM +#undef GENA +#undef GENM +#undef GEN + int last_insn = i; + uint8 *e = get_target(); + + uint8 *p = b; + i = 0; + while (p < e) { + int n = disass_x86(buffer, (uintptr)p); + insn_t ii; + parse_insn(&ii, buffer); + + if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) { + if (verbose > 1) + fprintf(stderr, "%s\n", buffer); + n_failures++; + } + + p += n; + i += 1; + n_tests++; + } + if (i != last_insn) + abort(); + } + } + printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); + n_all_tests += n_tests; + n_all_failures += n_failures; + + printf("Testing mem,reg forms\n"); + n_tests = n_failures = 0; + static const uint32 off_table[] = { + 0x00000000, + 0x00000001, + 0x00000040, + 0x00000080, + 0x000000ff, + 0x00000100, + 0xfffffffe, + 0xffffffff, + }; + const int off_table_count = sizeof(off_table) / sizeof(off_table[0]); + for (int d = 0; d < off_table_count; d++) { + const uint32 D = off_table[d]; + for (int B = -1; B < 16; B++) { + for (int I = -1; I < 16; I++) { + if (I == X86_RSP) + continue; + for (int S = 1; S < 8; S *= 2) { + if (I == -1) + continue; + for (int r = 0; r < 16; r++) { + set_target(block); + uint8 *b = get_target(); + int i = 0; +#define GEN(INSN, GENOP) do { \ + insns[i++] = INSN; \ + GENOP##mr(D, B, I, S, r); \ + } while (0) +#define GENA(INSN, GENOP) do { \ + GEN(INSN "b", GENOP##B); \ + GEN(INSN "w", GENOP##W); \ + GEN(INSN "l", GENOP##L); \ + GEN(INSN "q", GENOP##Q); \ + } while (0) + GENA("adc", ADC); + GENA("add", ADD); + GENA("and", AND); + GENA("cmp", CMP); + GENA("or", OR); + GENA("sbb", SBB); + GENA("sub", SUB); + GENA("xor", XOR); + GENA("mov", MOV); + GEN("imulw", IMULW); + GEN("imull", IMULL); + GEN("imulq", IMULQ); + GEN("bsfw", BSFW); + GEN("bsfl", BSFL); + GEN("bsfq", BSFQ); + GEN("bsrw", BSRW); + GEN("bsrl", BSRL); + GEN("bsrq", BSRQ); + GEN("movsbw", MOVSBW); + GEN("movsbl", MOVSBL); + GEN("movsbq", MOVSBQ); + GEN("movzbw", MOVZBW); + GEN("movzbl", MOVZBL); + GEN("movzbq", MOVZBQ); + GEN("movswl", MOVSWL); + GEN("movswq", MOVSWQ); + GEN("movzwl", MOVZWL); + GEN("movzwq", MOVZWQ); + GEN("movslq", MOVSLQ); +#undef GENA +#undef GEN + int last_insn = i; + uint8 *e = get_target(); + + uint8 *p = b; + i = 0; + while (p < e) { + int n = disass_x86(buffer, (uintptr)p); + insn_t ii; + parse_insn(&ii, buffer); + + if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) { + if (verbose > 1) + fprintf(stderr, "%s\n", buffer); + n_failures++; + } + + p += n; + i += 1; + n_tests++; + } + if (i != last_insn) + abort(); + } + } + } + } + } + printf(" done %ld/%ld\n", n_tests - n_failures, n_tests); + n_all_tests += n_tests; + n_all_failures += n_failures; + + printf("\n"); + printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures); +} diff --git a/BasiliskII/src/uae_cpu/cpu_emulation.h b/BasiliskII/src/uae_cpu/cpu_emulation.h index cc1d6e05..2e926874 100644 --- a/BasiliskII/src/uae_cpu/cpu_emulation.h +++ b/BasiliskII/src/uae_cpu/cpu_emulation.h @@ -80,7 +80,13 @@ extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType extern void Exit680x0(void); // 680x0 emulation functions -struct M68kRegisters; +struct M68kRegisters { + uint32 d[8]; + memptr a[8]; + uint16 sr; + memptr usp, isp, msp; + memptr pc; +}; extern void Start680x0(void); // Reset and start 680x0 extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine @@ -89,4 +95,12 @@ extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first) extern void TriggerNMI(void); // Trigger interrupt level 7 +// CPU looping handlers +void check_eps_limit(uaecptr); +void report_double_bus_error(void); + +extern int intlev(void); + +static inline void AtariReset(void) {} + #endif diff --git a/BasiliskII/src/uae_cpu/cpudefsa.cpp b/BasiliskII/src/uae_cpu/cpudefsa.cpp new file mode 100644 index 00000000..ad7d6979 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpudefsa.cpp @@ -0,0 +1,5 @@ +/* + * cpudefs.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "cpudefs.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1.cpp b/BasiliskII/src/uae_cpu/cpuemu1.cpp new file mode 100644 index 00000000..089eefd4 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu1.cpp @@ -0,0 +1,2 @@ +#define PART_1 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp new file mode 100644 index 00000000..58acf444 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_1 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2.cpp b/BasiliskII/src/uae_cpu/cpuemu2.cpp new file mode 100644 index 00000000..1e18b587 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu2.cpp @@ -0,0 +1,2 @@ +#define PART_2 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp new file mode 100644 index 00000000..8e5136c4 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_2 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3.cpp b/BasiliskII/src/uae_cpu/cpuemu3.cpp new file mode 100644 index 00000000..0385e2f0 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu3.cpp @@ -0,0 +1,2 @@ +#define PART_3 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp new file mode 100644 index 00000000..6565dc8c --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_3 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4.cpp b/BasiliskII/src/uae_cpu/cpuemu4.cpp new file mode 100644 index 00000000..13d27e7a --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu4.cpp @@ -0,0 +1,2 @@ +#define PART_4 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp new file mode 100644 index 00000000..a16c36cb --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_4 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5.cpp b/BasiliskII/src/uae_cpu/cpuemu5.cpp new file mode 100644 index 00000000..9b33a654 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu5.cpp @@ -0,0 +1,2 @@ +#define PART_5 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp new file mode 100644 index 00000000..5bf24360 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp @@ -0,0 +1,4 @@ +#define NOFLAGS 1 +#define PART_5 +#include "cpuemu.cpp" + diff --git a/BasiliskII/src/uae_cpu/cpuemu6.cpp b/BasiliskII/src/uae_cpu/cpuemu6.cpp new file mode 100644 index 00000000..e4b1efb0 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu6.cpp @@ -0,0 +1,2 @@ +#define PART_6 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp new file mode 100644 index 00000000..7afe15d4 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_6 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7.cpp b/BasiliskII/src/uae_cpu/cpuemu7.cpp new file mode 100644 index 00000000..faec7ef8 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu7.cpp @@ -0,0 +1,2 @@ +#define PART_7 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp new file mode 100644 index 00000000..1e404dea --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_7 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8.cpp b/BasiliskII/src/uae_cpu/cpuemu8.cpp new file mode 100644 index 00000000..c4efcfa3 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu8.cpp @@ -0,0 +1,2 @@ +#define PART_8 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp new file mode 100644 index 00000000..7c7f8f6e --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_8 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpufunctbla.cpp b/BasiliskII/src/uae_cpu/cpufunctbla.cpp new file mode 100644 index 00000000..17dd0d3f --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpufunctbla.cpp @@ -0,0 +1,5 @@ +/* + * cpufunctbl.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "cpufunctbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpummu.cpp b/BasiliskII/src/uae_cpu/cpummu.cpp new file mode 100644 index 00000000..1630bc78 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpummu.cpp @@ -0,0 +1,1096 @@ +/* + * cpummu.cpp - MMU emulation + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by UAE MMU patch + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DEBUG 0 +#include "sysdeps.h" + +#include "cpummu.h" +#include "memory.h" +#include "newcpu.h" +#include "debug.h" +#ifdef USE_JIT +# include "compiler/compemu.h" +#endif + +#define DBG_MMU_VERBOSE 1 +#define DBG_MMU_SANITY 1 + +#ifdef FULLMMU + +mmu_atc_l1_array atc_l1[2]; +mmu_atc_l1_array *current_atc; +struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; + +# ifdef ATC_STATS +static unsigned int mmu_atc_hits[ATC_L2_SIZE]; +# endif + + +static void mmu_dump_ttr(const char * label, uae_u32 ttr) +{ + DUNUSED(label); +#if DEBUG + uae_u32 from_addr, to_addr; + + from_addr = ttr & MMU_TTR_LOGICAL_BASE; + to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8; + + D(bug("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d", + label, ttr, + from_addr, to_addr, + ttr & MMU_TTR_BIT_ENABLED ? 1 : 0, + (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT, + ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0, + (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT + )); +#else + DUNUSED(ttr); +#endif +} + +void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode) +{ + uae_u32 * ttr; + uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0; + uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1; + + if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0) + ttr = ttr1; + else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0) + ttr = ttr0; + else + return; + + *ttr = baseaddr & MMU_TTR_LOGICAL_BASE; + *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8; + *ttr |= MMU_TTR_BIT_ENABLED; + + D(bug("MMU: map transparent mapping of %08x", *ttr)); +} + +/* check if an address matches a ttr */ +static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, int super) +{ + if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ + uae_u8 msb, mask; + + msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; + mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; + + if (!(msb & ~mask)) { + + if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { + if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { + return TTR_NO_MATCH; + } + } + + return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; + } + } + return TTR_NO_MATCH; +} + +static inline int mmu_match_ttr(uaecptr addr, int super, int data) +{ + int res; + + if (data) { + res = mmu_do_match_ttr(regs.dtt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.dtt1, addr, super); + } else { + res = mmu_do_match_ttr(regs.itt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.itt1, addr, super); + } + return res; +} + +#if DEBUG +/* {{{ mmu_dump_table */ +static void mmu_dump_table(const char * label, uaecptr root_ptr) +{ + DUNUSED(label); + const int ROOT_TABLE_SIZE = 128, + PTR_TABLE_SIZE = 128, + PAGE_TABLE_SIZE = regs.mmu_pagesize_8k ? 32 : 64, + ROOT_INDEX_SHIFT = 25, + PTR_INDEX_SHIFT = 18; + const uae_u32 ptr_addr_mask = (regs.mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4); + const uae_u32 page_addr_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4); + const uae_u32 page_ur_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4); + const uae_u32 page_size = (regs.mmu_pagesize_8k ? (1 << 13) : (1 << 12)); + int root_idx, ptr_idx, page_idx; + uae_u32 root_des, ptr_des, page_des; + uaecptr ptr_des_addr, page_addr, + root_log, ptr_log, page_log; + + D(bug("%s: root=%x", label, root_ptr)); + + for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) { + root_des = phys_get_long(root_ptr + (root_idx << 2)); + + if ((root_des & 2) == 0) + continue; /* invalid */ + + D(bug("ROOT: %03d U=%d W=%d UDT=%02d", root_idx, + root_des & 8 ? 1 : 0, + root_des & 4 ? 1 : 0, + root_des & 3 + )); + + root_log = root_idx << ROOT_INDEX_SHIFT; + + ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK; + + for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) { + struct { + uaecptr log, phys; + int start_idx, n_pages; /* number of pages covered by this entry */ + uae_u32 match; + } page_info[PAGE_TABLE_SIZE]; + int n_pages_used; + + ptr_des = phys_get_long(ptr_des_addr + (ptr_idx << 2)); + ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT); + + if ((ptr_des & 2) == 0) + continue; /* invalid */ + + page_addr = ptr_des & ptr_addr_mask; + + n_pages_used = -1; + for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) { + + page_des = phys_get_long(page_addr + (page_idx << 2)); + page_log = ptr_log | (page_idx * page_size); + + switch (page_des & 3) { + case 0: /* invalid */ + continue; + case 1: case 3: /* resident */ + case 2: /* indirect */ + if (n_pages_used == -1 || + (page_info[n_pages_used].match & ~page_addr_mask) != (page_des & ~page_addr_mask) || + page_info[n_pages_used].phys + (page_info[n_pages_used].n_pages * page_size) != (page_des & page_addr_mask)) + { + /* use the next entry */ + n_pages_used++; + + page_info[n_pages_used].match = page_des; + page_info[n_pages_used].n_pages = 1; + page_info[n_pages_used].start_idx = page_idx; + page_info[n_pages_used].log = page_log; + page_info[n_pages_used].phys = page_des & page_addr_mask; + } else { + page_info[n_pages_used].n_pages++; + } + break; + } + } + + if (n_pages_used == -1) + continue; + + D(bug(" PTR: %03d U=%d W=%d UDT=%02d", ptr_idx, + ptr_des & 8 ? 1 : 0, + ptr_des & 4 ? 1 : 0, + ptr_des & 3 + )); + + + for (page_idx = 0; page_idx <= n_pages_used; page_idx++) { + page_des = page_info[page_idx].match; + + if ((page_des & MMU_PDT_MASK) == 2) { + D(bug(" PAGE: %03d-%03d log=%08x INDIRECT --> addr=%08x", + page_info[page_idx].start_idx, + page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, + page_info[page_idx].log, + page_des & MMU_PAGE_INDIRECT_MASK + )); + + } else { + D(bug(" PAGE: %03d-%03d log=%08x addr=%08x UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d", + page_info[page_idx].start_idx, + page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, + page_info[page_idx].log, + page_info[page_idx].phys, + (page_des & page_ur_mask) >> MMU_PAGE_UR_SHIFT, + page_des & MMU_DES_GLOBAL ? 1 : 0, + (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT, + page_des & MMU_DES_SUPER ? 1 : 0, + (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT, + page_des & MMU_DES_MODIFIED ? 1 : 0, + page_des & MMU_DES_USED ? 1 : 0, + page_des & MMU_DES_WP ? 1 : 0 + )); + } + } + } + + } +} +/* }}} */ +#endif + +/* {{{ mmu_dump_atc */ +void mmu_dump_atc(void) +{ + int i, j; + for (i = 0; i < 2; i++) { + for (j = 0; j < ATC_L2_SIZE; j++) { + if (atc_l2[i][j].tag == 0x8000) + continue; + D(bug("ATC[%02d] G=%d TT=%d M=%d WP=%d VD=%d VI=%d tag=%08x --> phys=%08x", + j, atc_l2[i][j].global, atc_l2[i][j].tt, atc_l2[i][j].modified, + atc_l2[i][j].write_protect, atc_l2[i][j].valid_data, atc_l2[i][j].valid_inst, + atc_l2[i][j].tag, atc_l2[i][j].phys)); + } + } +} +/* }}} */ + +/* {{{ mmu_dump_tables */ +void mmu_dump_tables(void) +{ + D(bug("URP: %08x SRP: %08x MMUSR: %x TC: %x", regs.urp, regs.srp, regs.mmusr, regs.tc)); + mmu_dump_ttr("DTT0", regs.dtt0); + mmu_dump_ttr("DTT1", regs.dtt1); + mmu_dump_ttr("ITT0", regs.itt0); + mmu_dump_ttr("ITT1", regs.itt1); + mmu_dump_atc(); + //mmu_dump_table("SRP", regs.srp); +} +/* }}} */ + +static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write); + +static ALWAYS_INLINE int mmu_get_fc(bool super, bool data) +{ + return (super ? 4 : 0) | (data ? 1 : 2); +} + +static void mmu_bus_error(uaecptr addr, int fc, int write, int size) +{ + uae_u16 ssw = 0; + + ssw |= fc & MMU_SSW_TM; /* Copy TM */ + switch (size) { + case sz_byte: + ssw |= MMU_SSW_SIZE_B; + break; + case sz_word: + ssw |= MMU_SSW_SIZE_W; + break; + case sz_long: + ssw |= MMU_SSW_SIZE_L; + break; + } + + regs.wb3_status = write ? 0x80 | ssw : 0; + if (!write) + ssw |= MMU_SSW_RW; + + regs.mmu_fault_addr = addr; + regs.mmu_ssw = ssw | MMU_SSW_ATC; + + D(bug("BUS ERROR: fc=%d w=%d log=%08x ssw=%04x", fc, write, addr, ssw)); + + breakpt(); + THROW(2); +} + +/* + * Update the atc line for a given address by doing a mmu lookup. + */ +static uaecptr mmu_fill_atc_l2(uaecptr addr, int super, int data, int write, + struct mmu_atc_line *l) +{ + int res; + uae_u32 desc; + + l->tag = ATC_TAG(addr); + l->hw = l->bus_fault = 0; + + /* check ttr0 */ + res = mmu_match_ttr(addr, super, data); + if (res != TTR_NO_MATCH) { + l->tt = 1; + if (data) { + l->valid_data = 1; + l->valid_inst = mmu_match_ttr(addr, super, 0) == res; + } else { + l->valid_inst = 1; + l->valid_data = mmu_match_ttr(addr, super, 1) == res; + } + l->global = 1; + l->modified = 1; + l->write_protect = (res == TTR_NO_WRITE); + l->phys = 0; + + return 0; + } + + l->tt = 0; + if (!regs.mmu_enabled) { + l->valid_data = l->valid_inst = 1; + l->global = 1; + l->modified = 1; + l->write_protect = 0; + l->phys = 0; + return 0; + } + + SAVE_EXCEPTION; + TRY(prb) { + desc = mmu_lookup_pagetable(addr, super, write); + D(bug("translate: %x,%u,%u,%u -> %x", addr, super, write, data, desc)); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + /* bus error during table search */ + desc = 0; + goto fail; + } + + if ((desc & 1) == 0 || (!super && desc & MMU_MMUSR_S)) { + fail: + l->valid_data = l->valid_inst = 0; + l->global = 0; + } else { + l->valid_data = l->valid_inst = 1; + if (regs.mmu_pagesize_8k) + l->phys = (desc & ~0x1fff) - (addr & ~0x1fff); + else + l->phys = (desc & ~0xfff) - (addr & ~0xfff); + l->global = (desc & MMU_MMUSR_G) != 0; + l->modified = (desc & MMU_MMUSR_M) != 0; + l->write_protect = (desc & MMU_MMUSR_W) != 0; + } + + return desc; +} + +static ALWAYS_INLINE bool +mmu_fill_atc_l1(uaecptr addr, int super, int data, int write, + struct mmu_atc_line *l1) +{ + int idx = ATC_L2_INDEX(addr); + int tag = ATC_TAG(addr); + struct mmu_atc_line *l = &atc_l2[super][idx]; + uaecptr phys_addr; + + if (l->tag != tag) { + restart: + mmu_fill_atc_l2(addr, super, data, write, l); + } + if (!(data ? l->valid_data : l->valid_inst)) { + D(bug("MMU: non-resident page (%x,%x,%x)!", addr, regs.pc, regs.fault_pc)); + goto fail; + } + if (write) { + if (l->write_protect) { + D(bug("MMU: write protected (via %s) %x", l->tt ? "ttr" : "atc", addr)); + goto fail; + } + if (!l->modified) + goto restart; + } + *l1 = *l; + + phys_addr = addr + l1->phys; + if ((phys_addr & 0xfff00000) == 0x00f00000) { + l1->hw = 1; + goto fail; + } + if ((phys_addr & 0xfff00000) == 0xfff00000) { + l1->hw = 1; + l1->phys -= 0xff000000; + goto fail; + } + + if (!test_ram_boundary(phys_addr, 1, super, write)) { + l1->bus_fault = 1; + goto fail; + } + + return true; + +fail: + l1->tag = ~l1->tag; + return false; +} + +uaecptr mmu_translate(uaecptr addr, int super, int data, int write) +{ + struct mmu_atc_line *l; + + l = &atc_l2[super][ATC_L2_INDEX(addr)]; + mmu_fill_atc_l2(addr, super, data, write, l); + if (!(data ? l->valid_data : l->valid_inst)) + { + breakpt(); + THROW(2); + } + + return addr + l->phys; +} + +/* + * Lookup the address by walking the page table and updating + * the page descriptors accordingly. Returns the found descriptor + * or produces a bus error. + */ +static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write) +{ + uae_u32 desc, desc_addr, wp; + int i; + + wp = 0; + desc = super ? regs.srp : regs.urp; + + /* fetch root table descriptor */ + i = (addr >> 23) & 0x1fc; + desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; + desc = phys_get_long(desc_addr); + if ((desc & 2) == 0) { + D(bug("MMU: invalid root descriptor for %x", addr)); + return 0; + } + + wp |= desc; + if ((desc & MMU_DES_USED) == 0) + phys_put_long(desc_addr, desc | MMU_DES_USED); + + /* fetch pointer table descriptor */ + i = (addr >> 16) & 0x1fc; + desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; + desc = phys_get_long(desc_addr); + if ((desc & 2) == 0) { + D(bug("MMU: invalid ptr descriptor for %x", addr)); + return 0; + } + wp |= desc; + if ((desc & MMU_DES_USED) == 0) + phys_put_long(desc_addr, desc | MMU_DES_USED); + + /* fetch page table descriptor */ + if (regs.mmu_pagesize_8k) { + i = (addr >> 11) & 0x7c; + desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) | i; + } else { + i = (addr >> 10) & 0xfc; + desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) | i; + } + + desc = phys_get_long(desc_addr); + if ((desc & 3) == 2) { + /* indirect */ + desc_addr = desc & MMU_PAGE_INDIRECT_MASK; + desc = phys_get_long(desc_addr); + } + if ((desc & 1) == 0) { + D(bug("MMU: invalid page descriptor log=%08x desc=%08x @%08x", addr, desc, desc_addr)); + return desc; + } + + desc |= wp & MMU_DES_WP; + if (write) { + if (desc & MMU_DES_WP) { + if ((desc & MMU_DES_USED) == 0) { + desc |= MMU_DES_USED; + phys_put_long(desc_addr, desc); + } + } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) != + (MMU_DES_USED|MMU_DES_MODIFIED)) { + desc |= MMU_DES_USED|MMU_DES_MODIFIED; + phys_put_long(desc_addr, desc); + } + } else { + if ((desc & MMU_DES_USED) == 0) { + desc |= MMU_DES_USED; + phys_put_long(desc_addr, desc); + } + } + return desc; +} + +uae_u16 mmu_get_word_unaligned(uaecptr addr, int data) +{ + uae_u16 res; + + res = (uae_u16)mmu_get_byte(addr, data, sz_word) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_byte(addr + 1, data, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + return res; +} + +uae_u32 mmu_get_long_unaligned(uaecptr addr, int data) +{ + uae_u32 res; + + if (likely(!(addr & 1))) { + res = (uae_u32)mmu_get_word(addr, data, sz_long) << 16; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_word(addr + 2, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } else { + res = (uae_u32)mmu_get_byte(addr, data, sz_long) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res = (res | mmu_get_byte(addr + 1, data, sz_long)) << 8; + res = (res | mmu_get_byte(addr + 2, data, sz_long)) << 8; + res |= mmu_get_byte(addr + 3, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } + return res; +} + +uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) + return HWget_b(cl->phys + addr); + mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); + return 0; + } + + if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) + goto redo; + + return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); +} + +uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) + return HWget_w(cl->phys + addr); + mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); + return 0; + } + + if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) + goto redo; + + return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); +} + +uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) + return HWget_l(cl->phys + addr); + mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); + return 0; + } + + if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) + goto redo; + + return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); +} + + +uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, + struct mmu_atc_line *cl) +{ + uae_u64 h = mmu_get_long_slow(addr, super, data, sz_long, cl); + uae_u64 l = mmu_get_long_slow(addr + 4, super, data, sz_long, cl); + return (h << 32) | l; +} + +REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data) +{ + SAVE_EXCEPTION; + TRY(prb) { + if (likely(!(addr & 1))) { + mmu_put_word(addr, val >> 16, data, sz_long); + mmu_put_word(addr + 2, val, data, sz_long); + } else { + mmu_put_byte(addr, val >> 24, data, sz_long); + mmu_put_byte(addr + 1, val >> 16, data, sz_long); + mmu_put_byte(addr + 2, val >> 8, data, sz_long); + mmu_put_byte(addr + 3, val, data, sz_long); + } + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data) +{ + SAVE_EXCEPTION; + TRY(prb) { + mmu_put_byte(addr, val >> 8, data, sz_word); + mmu_put_byte(addr + 1, val, data, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) { + HWput_b(cl->phys + addr, val); + return; + } + regs.wb3_data = val; + mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); + return; + } + + if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) + goto redo; + + do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); +} + +REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) { + HWput_w(cl->phys + addr, val); + return; + } + regs.wb3_data = val; + mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); + return; + } + + if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) + goto redo; + + do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); +} + +REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) { + HWput_l(cl->phys + addr, val); + return; + } + regs.wb3_data = val; + mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); + return; + } + + if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) + goto redo; + + do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); +} + +REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, + struct mmu_atc_line *cl) +{ + mmu_put_long_slow(addr, (uae_u32)(val >> 32), super, data, sz_long, cl); + mmu_put_long_slow(addr + 4, (uae_u32)(val), super, data, sz_long, cl); +} + +uae_u32 sfc_get_long(uaecptr addr) +{ + int super = (regs.sfc & 4) != 0; + int data = (regs.sfc & 3) != 2; + uae_u32 res; + + if (likely(!is_unaligned(addr, 4))) + return mmu_get_user_long(addr, super, data, sz_long); + + if (likely(!(addr & 1))) { + res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_user_word(addr + 2, super, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } else { + res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8; + res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8; + res |= mmu_get_user_byte(addr + 3, super, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } + return res; +} + +uae_u16 sfc_get_word(uaecptr addr) +{ + int super = (regs.sfc & 4) != 0; + int data = (regs.sfc & 3) != 2; + uae_u16 res; + + if (likely(!is_unaligned(addr, 2))) + return mmu_get_user_word(addr, super, data, sz_word); + + res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_user_byte(addr + 1, super, data, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + return res; +} + +uae_u8 sfc_get_byte(uaecptr addr) +{ + int super = (regs.sfc & 4) != 0; + int data = (regs.sfc & 3) != 2; + + return mmu_get_user_byte(addr, super, data, sz_byte); +} + +void dfc_put_long(uaecptr addr, uae_u32 val) +{ + int super = (regs.dfc & 4) != 0; + int data = (regs.dfc & 3) != 2; + + SAVE_EXCEPTION; + TRY(prb) { + if (likely(!is_unaligned(addr, 4))) + mmu_put_user_long(addr, val, super, data, sz_long); + else if (likely(!(addr & 1))) { + mmu_put_user_word(addr, val >> 16, super, data, sz_long); + mmu_put_user_word(addr + 2, val, super, data, sz_long); + } else { + mmu_put_user_byte(addr, val >> 24, super, data, sz_long); + mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long); + mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long); + mmu_put_user_byte(addr + 3, val, super, data, sz_long); + } + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +void dfc_put_word(uaecptr addr, uae_u16 val) +{ + int super = (regs.dfc & 4) != 0; + int data = (regs.dfc & 3) != 2; + + SAVE_EXCEPTION; + TRY(prb) { + if (likely(!is_unaligned(addr, 2))) + mmu_put_user_word(addr, val, super, data, sz_word); + else { + mmu_put_user_byte(addr, val >> 8, super, data, sz_word); + mmu_put_user_byte(addr + 1, val, super, data, sz_word); + } + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +void dfc_put_byte(uaecptr addr, uae_u8 val) +{ + int super = (regs.dfc & 4) != 0; + int data = (regs.dfc & 3) != 2; + + SAVE_EXCEPTION; + TRY(prb) { + mmu_put_user_byte(addr, val, super, data, sz_byte); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + breakpt(); + THROW_AGAIN(prb); + } +} + +void mmu_op(uae_u32 opcode, uae_u16 extra) +{ + int super = (regs.dfc & 4) != 0; + DUNUSED(extra); + if ((opcode & 0xFE0) == 0x0500) { + int regno, glob; + //D(didflush = 0); + uae_u32 addr; + /* PFLUSH */ + regno = opcode & 7; + glob = (opcode & 8) != 0; + + if (opcode & 16) { + D(bug("pflusha(%u,%u)", glob, regs.dfc)); + mmu_flush_atc_all(glob); + } else { + addr = m68k_areg(regs, regno); + D(bug("pflush(%u,%u,%x)", glob, regs.dfc, addr)); + mmu_flush_atc(addr, super, glob); + } + flush_internals(); +#ifdef USE_JIT + flush_icache(0); +#endif + } else if ((opcode & 0x0FD8) == 0x548) { + int write, regno; + uae_u32 addr; + + regno = opcode & 7; + write = (opcode & 32) == 0; + addr = m68k_areg(regs, regno); + //bug("ptest(%u,%u,%x)", write, regs.dfc, addr); + D(bug("PTEST%c (A%d) %08x DFC=%d", write ? 'W' : 'R', regno, addr, regs.dfc)); + mmu_flush_atc(addr, super, true); + SAVE_EXCEPTION; + TRY(prb) { + struct mmu_atc_line *l; + uae_u32 desc; + bool data = (regs.dfc & 3) != 2; + + l = &atc_l2[super][ATC_L2_INDEX(addr)]; + desc = mmu_fill_atc_l2(addr, super, data, write, l); + if (!(data ? l->valid_data : l->valid_inst)) + regs.mmusr = MMU_MMUSR_B; + else if (l->tt) + regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R; + else { + regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S| + MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W); + regs.mmusr |= MMU_MMUSR_R; + } + } + CATCH(prb) { + regs.mmusr = MMU_MMUSR_B; + } + RESTORE_EXCEPTION; + D(bug("PTEST result: mmusr %08x", regs.mmusr)); + } else + op_illg (opcode); +} + +void mmu_flush_atc(uaecptr addr, bool super, bool global) +{ + struct mmu_atc_line *l; + int i, j; + + l = atc_l1[super][0][0]; + i = ATC_L1_INDEX(addr); + for (j = 0; j < 4; j++) { + if (global || !l[i].global) + l[i].tag = 0x8000; + l += ATC_L1_SIZE; + } + if (regs.mmu_pagesize_8k) { + i = ATC_L1_INDEX(addr) ^ 1; + for (j = 0; j < 4; j++) { + if (global || !l[i].global) + l[i].tag = 0x8000; + l += ATC_L1_SIZE; + } + } + l = atc_l2[super]; + i = ATC_L2_INDEX(addr); + if (global || !l[i].global) + l[i].tag = 0x8000; + if (regs.mmu_pagesize_8k) { + i ^= 1; + if (global || !l[i].global) + l[i].tag = 0x8000; + } +} + +void mmu_flush_atc_all(bool global) +{ + struct mmu_atc_line *l; + unsigned int i; + + l = atc_l1[0][0][0]; + for (i = 0; i < sizeof(atc_l1) / sizeof(*l); l++, i++) { + if (global || !l->global) + l->tag = 0x8000; + } + + l = atc_l2[0]; + for (i = 0; i < sizeof(atc_l2) / sizeof(*l); l++, i++) { + if (global || !l->global) + l->tag = 0x8000; + } +} + +void mmu_reset(void) +{ + mmu_flush_atc_all(true); + + regs.urp = regs.srp = 0; + regs.itt0 = regs.itt1 = 0; + regs.dtt0 = regs.dtt1 = 0; + regs.mmusr = 0; +} + + +void mmu_set_tc(uae_u16 tc) +{ + if (regs.tc == tc) + return; + + regs.tc = tc; + regs.mmu_enabled = tc & 0x8000 ? 1 : 0; + regs.mmu_pagesize_8k = tc & 0x4000 ? 1 : 0; + mmu_flush_atc_all(true); + + D(bug("MMU: enabled=%d page8k=%d\n", regs.mmu_enabled, regs.mmu_pagesize_8k)); +} + +void mmu_set_super(bool super) +{ + current_atc = &atc_l1[super]; +} + +#else + +void mmu_op(uae_u32 opcode, uae_u16 /*extra*/) +{ + if ((opcode & 0xFE0) == 0x0500) { + /* PFLUSH instruction */ + flush_internals(); + } else if ((opcode & 0x0FD8) == 0x548) { + /* PTEST instruction */ + } else + op_illg(opcode); +} + +#endif + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/cpummu.h b/BasiliskII/src/uae_cpu/cpummu.h new file mode 100644 index 00000000..01359f6f --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpummu.h @@ -0,0 +1,267 @@ +/* + * cpummu.h - MMU emulation + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by UAE MMU patch + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CPUMMU_H +#define CPUMMU_H + +#include "registers.h" + +# include + +#define MMU_TEST_PTEST 1 +#define MMU_TEST_VERBOSE 2 +#define MMU_TEST_FORCE_TABLE_SEARCH 4 +#define MMU_TEST_NO_BUSERR 8 + +extern void mmu_dump_tables(void); + +#define MMU_TTR_LOGICAL_BASE 0xff000000 +#define MMU_TTR_LOGICAL_MASK 0x00ff0000 +#define MMU_TTR_BIT_ENABLED (1 << 15) +#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) +#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) +#define MMU_TTR_SFIELD_SHIFT 13 +#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) +#define MMU_TTR_UX_SHIFT 8 +#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) +#define MMU_TTR_CACHE_SHIFT 5 +#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) + +#define MMU_UDT_MASK 3 +#define MMU_PDT_MASK 3 + +#define MMU_DES_WP 4 +#define MMU_DES_USED 8 + +/* page descriptors only */ +#define MMU_DES_MODIFIED 16 +#define MMU_DES_SUPER (1 << 7) +#define MMU_DES_GLOBAL (1 << 10) + +#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 +#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 +#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 + +#define MMU_PAGE_INDIRECT_MASK 0xfffffffc +#define MMU_PAGE_ADDR_MASK_8 0xffffe000 +#define MMU_PAGE_ADDR_MASK_4 0xfffff000 +#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) +#define MMU_PAGE_UR_MASK_4 (1 << 11) +#define MMU_PAGE_UR_SHIFT 11 + +#define MMU_MMUSR_ADDR_MASK 0xfffff000 +#define MMU_MMUSR_B (1 << 11) +#define MMU_MMUSR_G (1 << 10) +#define MMU_MMUSR_U1 (1 << 9) +#define MMU_MMUSR_U0 (1 << 8) +#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) +#define MMU_MMUSR_S (1 << 7) +#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) +#define MMU_MMUSR_M (1 << 4) +#define MMU_MMUSR_W (1 << 2) +#define MMU_MMUSR_T (1 << 1) +#define MMU_MMUSR_R (1 << 0) + +/* special status word (access error stack frame) */ +#define MMU_SSW_TM 0x0007 +#define MMU_SSW_TT 0x0018 +#define MMU_SSW_SIZE 0x0060 +#define MMU_SSW_SIZE_B 0x0020 +#define MMU_SSW_SIZE_W 0x0040 +#define MMU_SSW_SIZE_L 0x0000 +#define MMU_SSW_RW 0x0100 +#define MMU_SSW_LK 0x0200 +#define MMU_SSW_ATC 0x0400 +#define MMU_SSW_MA 0x0800 + +#define TTR_I0 4 +#define TTR_I1 5 +#define TTR_D0 6 +#define TTR_D1 7 + +#define TTR_NO_MATCH 0 +#define TTR_NO_WRITE 1 +#define TTR_OK_MATCH 2 + +struct mmu_atc_line { + uae_u16 tag; + unsigned tt : 1; + unsigned valid_data : 1; + unsigned valid_inst : 1; + unsigned global : 1; + unsigned modified : 1; + unsigned write_protect : 1; + unsigned hw : 1; + unsigned bus_fault : 1; + uaecptr phys; +}; + +/* + * We don't need to store the whole logical address in the atc cache, as part of + * it is encoded as index into the cache. 14 bits of the address are stored in + * the tag, this means at least 6 bits must go into the index. The upper two + * bits of the tag define the type of data in the atc line: + * - 00: a normal memory address + * - 11: invalid memory address or hardware access + * (generated via ~ATC_TAG(addr) in the slow path) + * - 10: empty atc line + */ + +#define ATC_TAG_SHIFT 18 +#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT) + + +#define ATC_L1_SIZE_LOG 8 +#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG) + +#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE) + +/* + * first level atc cache + * indexed by [super][data][rw][idx] + */ + +typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE]; +extern mmu_atc_l1_array atc_l1[2]; +extern mmu_atc_l1_array *current_atc; + +#define ATC_L2_SIZE_LOG 12 +#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG) + +#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE) + +extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; + +/* + * lookup address in the level 1 atc cache, + * the data and write arguments are constant in the common, + * thus allows gcc to generate a constant offset. + */ +static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write, + struct mmu_atc_line **cl) +{ + addr >>= 12; + *cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE]; + return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); +} + +/* + * similiar to mmu_user_lookup, but for the use of the moves instruction + */ +static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data, + bool write, struct mmu_atc_line **cl) +{ + addr >>= 12; + *cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE]; + return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); +} + +extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data); +extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data); + +extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, + struct mmu_atc_line *cl); + +extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data); +extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data); + +extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, + struct mmu_atc_line *cl); + +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); + +static inline void mmu_set_ttr(int regno, uae_u32 val) +{ + uae_u32 * ttr; + switch(regno) { + case TTR_I0: ttr = ®s.itt0; break; + case TTR_I1: ttr = ®s.itt1; break; + case TTR_D0: ttr = ®s.dtt0; break; + case TTR_D1: ttr = ®s.dtt1; break; + default: abort(); + } + *ttr = val; +} + +static inline void mmu_set_mmusr(uae_u32 val) +{ + regs.mmusr = val; +} + +#define FC_DATA (regs.s ? 5 : 1) +#define FC_INST (regs.s ? 6 : 2) + +extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write); + +extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr); +extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr); +extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr); +extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val); +extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val); +extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val); + + +extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global); +extern void REGPARAM2 mmu_flush_atc_all(bool global); +extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra); + +#ifdef FULLMMU + +extern void REGPARAM2 mmu_reset(void); +extern void REGPARAM2 mmu_set_tc(uae_u16 tc); +extern void REGPARAM2 mmu_set_super(bool super); + +#else + +static inline void mmu_reset(void) +{ +} + +static inline void mmu_set_tc(uae_u16 /*tc*/) +{ +} + +static inline void mmu_set_super(bool /*super*/) +{ +} + +#endif + +#endif /* CPUMMU_H */ +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/cpuopti.c b/BasiliskII/src/uae_cpu/cpuopti.c deleted file mode 100644 index 2dc10507..00000000 --- a/BasiliskII/src/uae_cpu/cpuopti.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * cpuopti.c - Small optimizer for cpu*.s files - * Based on work by Tauno Taipaleenmaki - * - * Copyright 1996 Bernd Schmidt - */ - -#include -#include -#include - -#include "sysdeps.h" - -struct line { - struct line *next, *prev; - int delet; - char *data; -}; - -struct func { - struct line *first_line, *last_line; - int initial_offset; -}; - -static void oops(void) -{ - fprintf(stderr, "Don't know how to optimize this file.\n"); - abort(); -} - -static char * match(struct line *l, const char *m) -{ - char *str = l->data; - int len = strlen(m); - while (isspace(*str)) - str++; - - if (strncmp(str, m, len) != 0) - return NULL; - return str + len; -} - -static int insn_references_reg (struct line *l, char *reg) -{ - if (reg[0] != 'e') { - fprintf(stderr, "Unknown register?!?\n"); - abort(); - } - if (strstr (l->data, reg) != 0) - return 1; - if (strstr (l->data, reg+1) != 0) - return 1; - if (strcmp (reg, "eax") == 0 - && (strstr (l->data, "%al") != 0 || strstr (l->data, "%ah") != 0)) - return 1; - if (strcmp (reg, "ebx") == 0 - && (strstr (l->data, "%bl") != 0 || strstr (l->data, "%bh") != 0)) - return 1; - if (strcmp (reg, "ecx") == 0 - && (strstr (l->data, "%cl") != 0 || strstr (l->data, "%ch") != 0)) - return 1; - if (strcmp (reg, "edx") == 0 - && (strstr (l->data, "%dl") != 0 || strstr (l->data, "%dh") != 0)) - return 1; - return 0; -} - -static void do_function(struct func *f) -{ - int v; - int pops_at_end = 0; - struct line *l, *l1, *fl, *l2; - char *s, *s2; - int in_pop_area = 1; - - f->initial_offset = 0; - - l = f->last_line; - fl = f->first_line; - - if (match(l,".LFE")) - l = l->prev; - if (!match(l,"ret")) - oops(); - - while (!match(fl, "op_")) - fl = fl->next; - fl = fl->next; - - /* Try reordering the insns at the end of the function so that the - * pops are all at the end. */ - l2 = l->prev; - /* Tolerate one stack adjustment */ - if (match (l2, "addl $") && strstr(l2->data, "esp") != 0) - l2 = l2->prev; - for (;;) { - char *forbidden_reg; - struct line *l3, *l4; - - while (match (l2, "popl %")) - l2 = l2->prev; - - l3 = l2; - for (;;) { - forbidden_reg = match (l3, "popl %"); - if (forbidden_reg) - break; - if (l3 == fl) - goto reordered; - /* Jumps and labels put an end to our attempts... */ - if (strstr (l3->data, ".L") != 0) - goto reordered; - /* Likewise accesses to the stack pointer... */ - if (strstr (l3->data, "esp") != 0) - goto reordered; - /* Function calls... */ - if (strstr (l3->data, "call") != 0) - goto reordered; - l3 = l3->prev; - } - if (l3 == l2) - abort(); - for (l4 = l2; l4 != l3; l4 = l4->prev) { - /* The register may not be referenced by any of the insns that we - * move the popl past */ - if (insn_references_reg (l4, forbidden_reg)) - goto reordered; - } - l3->prev->next = l3->next; - l3->next->prev = l3->prev; - l2->next->prev = l3; - l3->next = l2->next; - l2->next = l3; - l3->prev = l2; - } -reordered: - - l = l->prev; - - s = match (l, "addl $"); - s2 = match (fl, "subl $"); - - l1 = l; - if (s == 0) { - char *t = match (l, "popl %"); - if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) { - s = "4,%esp"; - l = l->prev; - t = match (l, "popl %"); - if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) { - s = "8,%esp"; - l = l->prev; - } - } - } else { - l = l->prev; - } - - if (s && s2) { - int v = 0; - if (strcmp (s, s2) != 0) { - fprintf (stderr, "Stack adjustment not matching.\n"); - return; - } - - while (isdigit(*s)) { - v = v * 10 + (*s) - '0'; - s++; - } - - if (strcmp (s, ",%esp") != 0) { - fprintf (stderr, "Not adjusting the stack pointer.\n"); - return; - } - f->initial_offset = v; - fl->delet = 3; - fl = fl->next; - l1->delet = 2; - l1 = l1->prev; - while (l1 != l) { - l1->delet = 1; - l1 = l1->prev; - } - } - - while (in_pop_area) { - char *popm, *pushm; - popm = match (l, "popl %"); - pushm = match (fl, "pushl %"); - if (popm && pushm && strcmp(pushm, popm) == 0) { - pops_at_end++; - fl->delet = l->delet = 1; - } else - in_pop_area = 0; - l = l->prev; - fl = fl->next; - } - if (f->initial_offset) - f->initial_offset += 4 * pops_at_end; -} - -static void output_function(struct func *f) -{ - struct line *l = f->first_line; - - while (l) { - switch (l->delet) { - case 1: - break; - case 0: - printf("%s\n", l->data); - break; - case 2: - if (f->initial_offset) - printf("\taddl $%d,%%esp\n", f->initial_offset); - break; - case 3: - if (f->initial_offset) - printf("\tsubl $%d,%%esp\n", f->initial_offset); - break; - } - l = l->next; - } -} - -int main(int argc, char **argv) -{ - FILE *infile = stdin; - char tmp[4096]; - -#ifdef __mc68000__ - if(system("perl machdep/cpuopti")==-1) { - perror("perl machdep/cpuopti"); - return 10; - } else return 0; -#endif - - /* For debugging... */ - if (argc == 2) - infile = fopen (argv[1], "r"); - - for(;;) { - char *s; - - if ((fgets(tmp, 4095, infile)) == NULL) - break; - - s = strchr (tmp, '\n'); - if (s != NULL) - *s = 0; - - if (strncmp(tmp, ".globl op_", 10) == 0) { - struct line *first_line = NULL, *prev = NULL; - struct line **nextp = &first_line; - struct func f; - int nr_rets = 0; - int can_opt = 1; - - do { - struct line *current; - - if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) { - current = *nextp = (struct line *)malloc(sizeof (struct line)); - nextp = ¤t->next; - current->prev = prev; prev = current; - current->next = NULL; - current->delet = 0; - current->data = strdup (tmp); - if (match (current, "movl %esp,%ebp") || match (current, "enter")) { - fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data); - can_opt = 0; - } - - if (match (current, "ret")) - nr_rets++; - } - if ((fgets(tmp, 4095, infile)) == NULL) - oops(); - s = strchr (tmp, '\n'); - if (s != NULL) - *s = 0; - } while (strncmp (tmp,".Lfe", 4) != 0); - - f.first_line = first_line; - f.last_line = prev; - - if (nr_rets == 1 && can_opt) - do_function(&f); - /*else - fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/ - output_function(&f); - } - printf("%s\n", tmp); - } - return 0; -} diff --git a/BasiliskII/src/uae_cpu/cpustbl_nf.cpp b/BasiliskII/src/uae_cpu/cpustbl_nf.cpp new file mode 100644 index 00000000..0ea66010 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpustbl_nf.cpp @@ -0,0 +1,2 @@ +#define NOFLAGS 1 +#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpustbla.cpp b/BasiliskII/src/uae_cpu/cpustbla.cpp new file mode 100644 index 00000000..f3f8e320 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpustbla.cpp @@ -0,0 +1,5 @@ +/* + * cpustbl.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/debug.cpp b/BasiliskII/src/uae_cpu/debug.cpp new file mode 100644 index 00000000..8b2f14e0 --- /dev/null +++ b/BasiliskII/src/uae_cpu/debug.cpp @@ -0,0 +1,82 @@ +/* + * debug.cpp - CPU debugger + * + * Copyright (c) 2001-2010 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Bernd Schmidt's UAE + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * UAE - The Un*x Amiga Emulator + * + * Debugger + * + * (c) 1995 Bernd Schmidt + * + */ + +#include "sysdeps.h" + +#include "memory.h" +#include "newcpu.h" +#include "debug.h" + +#include "input.h" +#include "cpu_emulation.h" + +#include "main.h" + +static int debugger_active = 0; +int debugging = 0; +int irqindebug = 0; + +int ignore_irq = 0; + + +void activate_debugger (void) +{ +#ifdef DEBUGGER + ndebug::do_skip = false; +#endif + debugger_active = 1; + SPCFLAGS_SET( SPCFLAG_BRK ); + debugging = 1; + /* use_debugger = 1; */ +} + +void deactivate_debugger(void) +{ + debugging = 0; + debugger_active = 0; +} + +void debug (void) +{ + if (ignore_irq && regs.s && !regs.m ) { + SPCFLAGS_SET( SPCFLAG_BRK ); + return; + } +#ifdef DEBUGGER + ndebug::run(); +#endif +} + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/fpu/core.h b/BasiliskII/src/uae_cpu/fpu/core.h new file mode 100644 index 00000000..1801ff7c --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/core.h @@ -0,0 +1,268 @@ +/* + * fpu/core.h - base fpu context definition + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_CORE_H +#define FPU_CORE_H + +#include "sysdeps.h" +#include "fpu/types.h" + +/* Always use x87 FPU stack on IA-32. */ +#if defined(X86_ASSEMBLY) +#define USE_X87_ASSEMBLY 1 +#ifndef USE_JIT_FPU +#define ACCURATE_SIN_COS_TAN 1 +#endif +#endif + +/* Only use x87 FPU on x86-64 if long double precision is requested. */ +#if defined(X86_64_ASSEMBLY) && defined(USE_LONG_DOUBLE) +#define USE_X87_ASSEMBLY 1 +#define ACCURATE_SIN_COS_TAN 1 +#endif + +/* ========================================================================== */ +/* ========================= FPU CONTEXT DEFINITION ========================= */ +/* ========================================================================== */ + +/* We don't use all features of the C++ language so that we may still + * easily backport that code to C. + */ + +struct fpu_t { + + /* ---------------------------------------------------------------------- */ + /* --- Floating-Point Data Registers --- */ + /* ---------------------------------------------------------------------- */ + + /* The eight %fp0 .. %fp7 registers */ + fpu_register registers[8]; + + /* Used for lazy evalualation of FPU flags */ + fpu_register result; + + /* ---------------------------------------------------------------------- */ + /* --- Floating-Point Control Register --- */ + /* ---------------------------------------------------------------------- */ + + struct { + + /* Exception Enable Byte */ + uae_u32 exception_enable; + #define FPCR_EXCEPTION_ENABLE 0x0000ff00 + #define FPCR_EXCEPTION_BSUN 0x00008000 + #define FPCR_EXCEPTION_SNAN 0x00004000 + #define FPCR_EXCEPTION_OPERR 0x00002000 + #define FPCR_EXCEPTION_OVFL 0x00001000 + #define FPCR_EXCEPTION_UNFL 0x00000800 + #define FPCR_EXCEPTION_DZ 0x00000400 + #define FPCR_EXCEPTION_INEX2 0x00000200 + #define FPCR_EXCEPTION_INEX1 0x00000100 + + /* Mode Control Byte Mask */ + #define FPCR_MODE_CONTROL 0x000000ff + + /* Rounding precision */ + uae_u32 rounding_precision; + #define FPCR_ROUNDING_PRECISION 0x000000c0 + #define FPCR_PRECISION_SINGLE 0x00000040 + #define FPCR_PRECISION_DOUBLE 0x00000080 + #define FPCR_PRECISION_EXTENDED 0x00000000 + + /* Rounding mode */ + uae_u32 rounding_mode; + #define FPCR_ROUNDING_MODE 0x00000030 + #define FPCR_ROUND_NEAR 0x00000000 + #define FPCR_ROUND_ZERO 0x00000010 + #define FPCR_ROUND_MINF 0x00000020 + #define FPCR_ROUND_PINF 0x00000030 + + } fpcr; + + /* ---------------------------------------------------------------------- */ + /* --- Floating-Point Status Register --- */ + /* ---------------------------------------------------------------------- */ + + struct { + + /* Floating-Point Condition Code Byte */ + uae_u32 condition_codes; + #define FPSR_CCB 0x0f000000 + #define FPSR_CCB_NEGATIVE 0x08000000 + #define FPSR_CCB_ZERO 0x04000000 + #define FPSR_CCB_INFINITY 0x02000000 + #define FPSR_CCB_NAN 0x01000000 + + /* Quotient Byte */ + uae_u32 quotient; + #define FPSR_QUOTIENT 0x00ff0000 + #define FPSR_QUOTIENT_SIGN 0x00800000 + #define FPSR_QUOTIENT_VALUE 0x007f0000 + + /* Exception Status Byte */ + uae_u32 exception_status; + #define FPSR_EXCEPTION_STATUS FPCR_EXCEPTION_ENABLE + #define FPSR_EXCEPTION_BSUN FPCR_EXCEPTION_BSUN + #define FPSR_EXCEPTION_SNAN FPCR_EXCEPTION_SNAN + #define FPSR_EXCEPTION_OPERR FPCR_EXCEPTION_OPERR + #define FPSR_EXCEPTION_OVFL FPCR_EXCEPTION_OVFL + #define FPSR_EXCEPTION_UNFL FPCR_EXCEPTION_UNFL + #define FPSR_EXCEPTION_DZ FPCR_EXCEPTION_DZ + #define FPSR_EXCEPTION_INEX2 FPCR_EXCEPTION_INEX2 + #define FPSR_EXCEPTION_INEX1 FPCR_EXCEPTION_INEX1 + + /* Accrued Exception Byte */ + uae_u32 accrued_exception; + #define FPSR_ACCRUED_EXCEPTION 0x000000ff + #define FPSR_ACCR_IOP 0x00000080 + #define FPSR_ACCR_OVFL 0x00000040 + #define FPSR_ACCR_UNFL 0x00000020 + #define FPSR_ACCR_DZ 0x00000010 + #define FPSR_ACCR_INEX 0x00000008 + + } fpsr; + + /* ---------------------------------------------------------------------- */ + /* --- Floating-Point Instruction Address Register --- */ + /* ---------------------------------------------------------------------- */ + + uae_u32 instruction_address; + + /* ---------------------------------------------------------------------- */ + /* --- Initialization / Finalization --- */ + /* ---------------------------------------------------------------------- */ + + /* Flag set if we emulate an integral 68040 FPU */ + bool is_integral; + + /* ---------------------------------------------------------------------- */ + /* --- Extra FPE-dependant defines --- */ + /* ---------------------------------------------------------------------- */ + + #if defined(FPU_X86) \ + || (defined(FPU_UAE) && defined(USE_X87_ASSEMBLY)) \ + || (defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)) + + #define CW_RESET 0x0040 // initial CW value after RESET + #define CW_FINIT 0x037F // initial CW value after FINIT + #define SW_RESET 0x0000 // initial SW value after RESET + #define SW_FINIT 0x0000 // initial SW value after FINIT + #define TW_RESET 0x5555 // initial TW value after RESET + #define TW_FINIT 0x0FFF // initial TW value after FINIT + + #define CW_X 0x1000 // infinity control + #define CW_RC_ZERO 0x0C00 // rounding control toward zero + #define CW_RC_UP 0x0800 // rounding control toward + + #define CW_RC_DOWN 0x0400 // rounding control toward - + #define CW_RC_NEAR 0x0000 // rounding control toward even + #define CW_PC_EXTENDED 0x0300 // precision control 64bit + #define CW_PC_DOUBLE 0x0200 // precision control 53bit + #define CW_PC_RESERVED 0x0100 // precision control reserved + #define CW_PC_SINGLE 0x0000 // precision control 24bit + #define CW_PM 0x0020 // precision exception mask + #define CW_UM 0x0010 // underflow exception mask + #define CW_OM 0x0008 // overflow exception mask + #define CW_ZM 0x0004 // zero divide exception mask + #define CW_DM 0x0002 // denormalized operand exception mask + #define CW_IM 0x0001 // invalid operation exception mask + + #define SW_B 0x8000 // busy flag + #define SW_C3 0x4000 // condition code flag 3 + #define SW_TOP_7 0x3800 // top of stack = ST(7) + #define SW_TOP_6 0x3000 // top of stack = ST(6) + #define SW_TOP_5 0x2800 // top of stack = ST(5) + #define SW_TOP_4 0x2000 // top of stack = ST(4) + #define SW_TOP_3 0x1800 // top of stack = ST(3) + #define SW_TOP_2 0x1000 // top of stack = ST(2) + #define SW_TOP_1 0x0800 // top of stack = ST(1) + #define SW_TOP_0 0x0000 // top of stack = ST(0) + #define SW_C2 0x0400 // condition code flag 2 + #define SW_C1 0x0200 // condition code flag 1 + #define SW_C0 0x0100 // condition code flag 0 + #define SW_ES 0x0080 // error summary status flag + #define SW_SF 0x0040 // stack fault flag + #define SW_PE 0x0020 // precision exception flag + #define SW_UE 0x0010 // underflow exception flag + #define SW_OE 0x0008 // overflow exception flag + #define SW_ZE 0x0004 // zero divide exception flag + #define SW_DE 0x0002 // denormalized operand exception flag + #define SW_IE 0x0001 // invalid operation exception flag + + #define X86_ROUNDING_MODE 0x0C00 + #define X86_ROUNDING_PRECISION 0x0300 + + #endif /* FPU_X86 */ + +}; + +/* We handle only one global fpu */ +extern fpu_t fpu; + +/* Return the address of a particular register */ +inline fpu_register * fpu_register_address(int i) + { return &fpu.registers[i]; } + +/* Dump functions for m68k_dumpstate */ +extern void fpu_dump_registers(void); +extern void fpu_dump_flags(void); + +/* Accessors to FPU Control Register */ +//static inline uae_u32 get_fpcr(void); +//static inline void set_fpcr(uae_u32 new_fpcr); + +/* Accessors to FPU Status Register */ +//static inline uae_u32 get_fpsr(void); +//static inline void set_fpsr(uae_u32 new_fpsr); + +/* Accessors to FPU Instruction Address Register */ +//static inline uae_u32 get_fpiar(); +//static inline void set_fpiar(uae_u32 new_fpiar); + +/* Initialization / Finalization */ +extern void fpu_init(bool integral_68040); +extern void fpu_exit(void); +extern void fpu_reset(void); + +/* Floating-point arithmetic instructions */ +void fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) REGPARAM; + +/* Floating-point program control operations */ +void fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) REGPARAM; +void fpuop_dbcc(uae_u32 opcode, uae_u32 extra) REGPARAM; +void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM; + +/* Floating-point system control operations */ +void fpuop_save(uae_u32 opcode) REGPARAM; +void fpuop_restore(uae_u32 opcode) REGPARAM; +void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) REGPARAM; + +#endif /* FPU_CORE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp new file mode 100644 index 00000000..2a597997 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp @@ -0,0 +1,193 @@ +/* + * fpu/exceptions.cpp - system-dependant FPU exceptions management + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#undef PRIVATE +#define PRIVATE /**/ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Native X86 exceptions --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_X86_EXCEPTIONS +void FFPU fpu_init_native_exceptions(void) +{ + // Mapping for "sw" -> fpsr exception byte + for (uae_u32 i = 0; i < 0x80; i++) { + exception_host2mac[i] = 0; + + if(i & SW_FAKE_BSUN) { + exception_host2mac[i] |= FPSR_EXCEPTION_BSUN; + } + // precision exception + if(i & SW_PE) { + exception_host2mac[i] |= FPSR_EXCEPTION_INEX2; + } + // underflow exception + if(i & SW_UE) { + exception_host2mac[i] |= FPSR_EXCEPTION_UNFL; + } + // overflow exception + if(i & SW_OE) { + exception_host2mac[i] |= FPSR_EXCEPTION_OVFL; + } + // zero divide exception + if(i & SW_ZE) { + exception_host2mac[i] |= FPSR_EXCEPTION_DZ; + } + // denormalized operand exception. + // wrong, but should not get here, normalization is done in elsewhere + if(i & SW_DE) { + exception_host2mac[i] |= FPSR_EXCEPTION_SNAN; + } + // invalid operation exception + if(i & SW_IE) { + exception_host2mac[i] |= FPSR_EXCEPTION_OPERR; + } + } + + // Mapping for fpsr exception byte -> "sw" + for (uae_u32 i = 0; i < 0x100; i++) { + uae_u32 fpsr = (i << 8); + exception_mac2host[i] = 0; + + // BSUN; make sure that you don't generate FPU stack faults. + if(fpsr & FPSR_EXCEPTION_BSUN) { + exception_mac2host[i] |= SW_FAKE_BSUN; + } + // precision exception + if(fpsr & FPSR_EXCEPTION_INEX2) { + exception_mac2host[i] |= SW_PE; + } + // underflow exception + if(fpsr & FPSR_EXCEPTION_UNFL) { + exception_mac2host[i] |= SW_UE; + } + // overflow exception + if(fpsr & FPSR_EXCEPTION_OVFL) { + exception_mac2host[i] |= SW_OE; + } + // zero divide exception + if(fpsr & FPSR_EXCEPTION_DZ) { + exception_mac2host[i] |= SW_ZE; + } + // denormalized operand exception + if(fpsr & FPSR_EXCEPTION_SNAN) { + exception_mac2host[i] |= SW_DE; //Wrong + } + // invalid operation exception + if(fpsr & FPSR_EXCEPTION_OPERR) { + exception_mac2host[i] |= SW_IE; + } + } +} +#endif + +#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS +void FFPU fpu_init_native_accrued_exceptions(void) +{ + /* + 68881/68040 accrued exceptions accumulate as follows: + Accrued.IOP |= (Exception.SNAN | Exception.OPERR) + Accrued.OVFL |= (Exception.OVFL) + Accrued.UNFL |= (Exception.UNFL | Exception.INEX2) + Accrued.DZ |= (Exception.DZ) + Accrued.INEX |= (Exception.INEX1 | Exception.INEX2 | Exception.OVFL) + */ + + // Mapping for "fpsr.accrued_exception" -> fpsr accrued exception byte + for (uae_u32 i = 0; i < 0x40; i++ ) { + accrued_exception_host2mac[i] = 0; + + // precision exception + if(i & SW_PE) { + accrued_exception_host2mac[i] |= FPSR_ACCR_INEX; + } + // underflow exception + if(i & SW_UE) { + accrued_exception_host2mac[i] |= FPSR_ACCR_UNFL; + } + // overflow exception + if(i & SW_OE) { + accrued_exception_host2mac[i] |= FPSR_ACCR_OVFL; + } + // zero divide exception + if(i & SW_ZE) { + accrued_exception_host2mac[i] |= FPSR_ACCR_DZ; + } + // denormalized operand exception + if(i & SW_DE) { + accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; //?????? + } + // invalid operation exception + if(i & SW_IE) { + accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; + } + } + + // Mapping for fpsr accrued exception byte -> "fpsr.accrued_exception" + for (uae_u32 i = 0; i < 0x20; i++) { + int fpsr = (i << 3); + accrued_exception_mac2host[i] = 0; + + // precision exception + if(fpsr & FPSR_ACCR_INEX) { + accrued_exception_mac2host[i] |= SW_PE; + } + // underflow exception + if(fpsr & FPSR_ACCR_UNFL) { + accrued_exception_mac2host[i] |= SW_UE; + } + // overflow exception + if(fpsr & FPSR_ACCR_OVFL) { + accrued_exception_mac2host[i] |= SW_OE; + } + // zero divide exception + if(fpsr & FPSR_ACCR_DZ) { + accrued_exception_mac2host[i] |= SW_ZE; + } + // What about SW_DE; //?????? + // invalid operation exception + if(fpsr & FPSR_ACCR_IOP) { + accrued_exception_mac2host[i] |= SW_IE; + } + } +} +#endif diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.h b/BasiliskII/src/uae_cpu/fpu/exceptions.h new file mode 100644 index 00000000..f943da04 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.h @@ -0,0 +1,154 @@ +/* + * fpu/exceptions.h - system-dependant FPU exceptions management + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_EXCEPTIONS_H +#define FPU_EXCEPTIONS_H + +/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* Defaults to generic exceptions */ +#define FPU_USE_GENERIC_EXCEPTIONS +#define FPU_USE_GENERIC_ACCRUED_EXCEPTIONS + +/* -------------------------------------------------------------------------- */ +/* --- Selection of floating-point exceptions handling mode --- */ +/* -------------------------------------------------------------------------- */ + +/* Optimized i386 fpu core must use native exceptions */ +#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_EXCEPTIONS +# define FPU_USE_X86_EXCEPTIONS +#endif + +/* Optimized i386 fpu core must use native accrued exceptions */ +#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS +# define FPU_USE_X86_ACCRUED_EXCEPTIONS +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Native X86 Exceptions --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_X86_EXCEPTIONS + +/* Extend the SW_* codes */ +#define SW_FAKE_BSUN SW_SF + +/* Shorthand */ +#define SW_EXCEPTION_MASK (SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) +// #define SW_EXCEPTION_MASK (SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) + +/* Lookup tables */ +PRIVATE uae_u32 exception_host2mac[ 0x80 ]; +PRIVATE uae_u32 exception_mac2host[ 0x100 ]; + +/* Initialize native exception management */ +PUBLIC void FFPU fpu_init_native_exceptions(void); + +/* Return m68k floating-point exception status */ +PRIVATE inline uae_u32 FFPU get_exception_status(void) + { return exception_host2mac[FPU fpsr.exception_status & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; } + +/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */ +PRIVATE inline void FFPU set_exception_status(uae_u32 new_status) + { FPU fpsr.exception_status = exception_mac2host[new_status >> 8]; } + +#endif /* FPU_USE_X86_EXCEPTIONS */ + +#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS + +/* Lookup tables */ +PRIVATE uae_u32 accrued_exception_host2mac[ 0x40 ]; +PRIVATE uae_u32 accrued_exception_mac2host[ 0x20 ]; + +/* Initialize native accrued exception management */ +PUBLIC void FFPU fpu_init_native_accrued_exceptions(void); + +/* Return m68k accrued exception byte */ +PRIVATE inline uae_u32 FFPU get_accrued_exception(void) + { return accrued_exception_host2mac[FPU fpsr.accrued_exception & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; } + +/* Set new accrued exception byte */ +PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status) + { FPU fpsr.accrued_exception = accrued_exception_mac2host[(new_status & 0xF8) >> 3]; } + +#endif /* FPU_USE_X86_ACCRUED_EXCEPTIONS */ + +/* -------------------------------------------------------------------------- */ +/* --- Default Exceptions Handling --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_GENERIC_EXCEPTIONS + +/* Initialize native exception management */ +static inline void FFPU fpu_init_native_exceptions(void) + { } + +/* Return m68k floating-point exception status */ +PRIVATE inline uae_u32 FFPU get_exception_status(void) + { return FPU fpsr.exception_status; } + +/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */ +PRIVATE inline void FFPU set_exception_status(uae_u32 new_status) + { FPU fpsr.exception_status = new_status; } + +#endif /* FPU_USE_GENERIC_EXCEPTIONS */ + +#ifdef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS + +/* Initialize native accrued exception management */ +PRIVATE inline void FFPU fpu_init_native_accrued_exceptions(void) + { } + +/* Return m68k accrued exception byte */ +PRIVATE inline uae_u32 FFPU get_accrued_exception(void) + { return FPU fpsr.accrued_exception; } + +/* Set new accrued exception byte */ +PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status) + { FPU fpsr.accrued_exception = new_status; } + +#endif /* FPU_USE_GENERIC_ACCRUED_EXCEPTIONS */ + +#endif /* FPU_EXCEPTIONS_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/flags.cpp b/BasiliskII/src/uae_cpu/fpu/flags.cpp new file mode 100644 index 00000000..4b0972df --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/flags.cpp @@ -0,0 +1,174 @@ +/* + * fpu/flags.cpp - Floating-point flags + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ +#undef PRIVATE +#define PRIVATE /**/ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Native X86 floating-point flags --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_X86_FLAGS + +/* Initialization */ +void FFPU fpu_init_native_fflags(void) +{ + // Adapted from fpu_x86.cpp + #define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3) + #define SW_Z (SW_C3) + #define SW_I (SW_C0|SW_C2) + #define SW_NAN (SW_C0) + #define SW_FINITE (SW_C2) + #define SW_EMPTY_REGISTER (SW_C0|SW_C3) + #define SW_DENORMAL (SW_C2|SW_C3) + #define SW_UNSUPPORTED (0) + #define SW_N (SW_C1) + + // Sanity checks + #if (SW_Z != NATIVE_FFLAG_ZERO) + #error "Incorrect X86 Z fflag" + #endif + #if (SW_I != NATIVE_FFLAG_INFINITY) + #error "Incorrect X86 I fflag" + #endif + #if (SW_N != NATIVE_FFLAG_NEGATIVE) + #error "Incorrect X86 N fflag" + #endif + #if (SW_NAN != NATIVE_FFLAG_NAN) + #error "Incorrect X86 NAN fflag" + #endif + + // Native status word to m68k mappings + for (uae_u32 i = 0; i < 0x48; i++) { + to_m68k_fpcond[i] = 0; + const uae_u32 native_fpcond = i << 8; + switch (native_fpcond & SW_Z_I_NAN_MASK) { +#ifndef FPU_UAE +// gb-- enabling it would lead to incorrect drawing of digits +// in Speedometer Performance Test + case SW_UNSUPPORTED: +#endif + case SW_NAN: + case SW_EMPTY_REGISTER: + to_m68k_fpcond[i] |= FPSR_CCB_NAN; + break; + case SW_FINITE: + case SW_DENORMAL: + break; + case SW_I: + to_m68k_fpcond[i] |= FPSR_CCB_INFINITY; + break; + case SW_Z: + to_m68k_fpcond[i] |= FPSR_CCB_ZERO; + break; + } + if (native_fpcond & SW_N) + to_m68k_fpcond[i] |= FPSR_CCB_NEGATIVE; + } + + // m68k to native status word mappings + for (uae_u32 i = 0; i < 0x10; i++) { + const uae_u32 m68k_fpcond = i << 24; + if (m68k_fpcond & FPSR_CCB_NAN) + to_host_fpcond[i] = SW_NAN; + else if (m68k_fpcond & FPSR_CCB_ZERO) + to_host_fpcond[i] = SW_Z; + else if (m68k_fpcond & FPSR_CCB_INFINITY) + to_host_fpcond[i] = SW_I; + else + to_host_fpcond[i] = SW_FINITE; + if (m68k_fpcond & FPSR_CCB_NEGATIVE) + to_host_fpcond[i] |= SW_N; + } + + // truth-table for FPU conditions + for (uae_u32 host_fpcond = 0; host_fpcond < 0x08; host_fpcond++) { + // host_fpcond: C3 on bit 2, C1 and C0 are respectively on bits 1 and 0 + const uae_u32 real_host_fpcond = ((host_fpcond & 4) << 12) | ((host_fpcond & 3) << 8); + const bool N = ((real_host_fpcond & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE); + const bool Z = ((real_host_fpcond & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO); + const bool NaN = ((real_host_fpcond & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN); + + int value; + for (uae_u32 m68k_fpcond = 0; m68k_fpcond < 0x20; m68k_fpcond++) { + switch (m68k_fpcond) { + case 0x00: value = 0; break; // False + case 0x01: value = Z; break; // Equal + case 0x02: value = !(NaN || Z || N); break; // Ordered Greater Than + case 0x03: value = Z || !(NaN || N); break; // Ordered Greater Than or Equal + case 0x04: value = N && !(NaN || Z); break; // Ordered Less Than + case 0x05: value = Z || (N && !NaN); break; // Ordered Less Than or Equal + case 0x06: value = !(NaN || Z); break; // Ordered Greater or Less Than + case 0x07: value = !NaN; break; // Ordered + case 0x08: value = NaN; break; // Unordered + case 0x09: value = NaN || Z; break; // Unordered or Equal + case 0x0a: value = NaN || !(N || Z); break; // Unordered or Greater Than + case 0x0b: value = NaN || Z || !N; break; // Unordered or Greater or Equal + case 0x0c: value = NaN || (N && !Z); break; // Unordered or Less Than + case 0x0d: value = NaN || Z || N; break; // Unordered or Less or Equal + case 0x0e: value = !Z; break; // Not Equal + case 0x0f: value = 1; break; // True + case 0x10: value = 0; break; // Signaling False + case 0x11: value = Z; break; // Signaling Equal + case 0x12: value = !(NaN || Z || N); break; // Greater Than + case 0x13: value = Z || !(NaN || N); break; // Greater Than or Equal + case 0x14: value = N && !(NaN || Z); break; // Less Than + case 0x15: value = Z || (N && !NaN); break; // Less Than or Equal + case 0x16: value = !(NaN || Z); break; // Greater or Less Than + case 0x17: value = !NaN; break; // Greater, Less or Equal + case 0x18: value = NaN; break; // Not Greater, Less or Equal + case 0x19: value = NaN || Z; break; // Not Greater or Less Than + case 0x1a: value = NaN || !(N || Z); break; // Not Less Than or Equal + case 0x1b: value = NaN || Z || !N; break; // Not Less Than + case 0x1c: value = NaN || (N && !Z); break; // Not Greater Than or Equal +// case 0x1c: value = !Z && (NaN || N); break; // Not Greater Than or Equal + case 0x1d: value = NaN || Z || N; break; // Not Greater Than + case 0x1e: value = !Z; break; // Signaling Not Equal + case 0x1f: value = 1; break; // Signaling True + default: value = -1; + } + fpcond_truth_table[m68k_fpcond][host_fpcond] = value; + } + } +} + +#endif diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h new file mode 100644 index 00000000..3d144ac2 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/flags.h @@ -0,0 +1,228 @@ +/* + * fpu/flags.h - Floating-point flags + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_FLAGS_H +#define FPU_FLAGS_H + +/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* Defaults to generic flags */ +#define FPU_USE_GENERIC_FLAGS + +/* -------------------------------------------------------------------------- */ +/* --- Selection of floating-point flags handling mode --- */ +/* -------------------------------------------------------------------------- */ + +/* Optimized i386 fpu core must use native flags */ +#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_FLAGS +# define FPU_USE_X86_FLAGS +#endif + +/* Old UAE FPU core can use native flags */ +#if defined(FPU_UAE) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_FLAGS +# define FPU_USE_X86_FLAGS +#endif + +/* IEEE-based implementation must use lazy flag evaluation */ +#if defined(FPU_IEEE) +# undef FPU_USE_GENERIC_FLAGS +# define FPU_USE_LAZY_FLAGS +#endif + +/* JIT Compilation for FPU only works with lazy evaluation of FPU flags */ +#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) && defined(USE_JIT_FPU) +# undef FPU_USE_GENERIC_FLAGS +# define FPU_USE_LAZY_FLAGS +#endif + +#ifdef FPU_IMPLEMENTATION + +/* -------------------------------------------------------------------------- */ +/* --- Native X86 Floating-Point Flags --- */ +/* -------------------------------------------------------------------------- */ + +/* FPU_X86 has its own set of lookup functions */ + +#ifdef FPU_USE_X86_FLAGS + +#define FPU_USE_NATIVE_FLAGS + +#define NATIVE_FFLAG_NEGATIVE 0x0200 +#define NATIVE_FFLAG_ZERO 0x4000 +#define NATIVE_FFLAG_INFINITY 0x0500 +#define NATIVE_FFLAG_NAN 0x0100 + +/* Translation tables between native and m68k floating-point flags */ +PRIVATE uae_u32 to_m68k_fpcond[0x48]; +PRIVATE uae_u32 to_host_fpcond[0x10]; + +/* Truth table for floating-point condition codes */ +PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes + +/* Initialization */ +PUBLIC void FFPU fpu_init_native_fflags(void); + +#ifdef FPU_UAE + +/* Native to m68k floating-point condition codes */ +PRIVATE inline uae_u32 FFPU get_fpccr(void) + { return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; } + +/* M68k to native floating-point condition codes */ +PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) + /* Precondition: new_fpcond is only valid for floating-point condition codes */ + { FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; } + +/* Make FPSR according to the value passed in argument */ +PRIVATE inline void FFPU make_fpsr(fpu_register const & r) + { uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=a" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } + +/* Return the corresponding ID of the current floating-point condition codes */ +/* NOTE: only valid for evaluation of a condition */ +PRIVATE inline int FFPU host_fpcond_id(void) + { return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); } + +/* Return true if the floating-point condition is satisfied */ +PRIVATE inline bool FFPU fpcctrue(int condition) + { return fpcond_truth_table[condition][host_fpcond_id()]; } + +#endif /* FPU_UAE */ + +/* Return the address of the floating-point condition codes truth table */ +static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void) + { return ((uae_u8*)&fpcond_truth_table[0][0]); } + +#endif /* FPU_X86_USE_NATIVE_FLAGS */ + +/* -------------------------------------------------------------------------- */ +/* --- Use Original M68K FPU Mappings --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_GENERIC_FLAGS + +#undef FPU_USE_NATIVE_FLAGS + +#define NATIVE_FFLAG_NEGATIVE 0x08000000 +#define NATIVE_FFLAG_ZERO 0x04000000 +#define NATIVE_FFLAG_INFINITY 0x02000000 +#define NATIVE_FFLAG_NAN 0x01000000 + +/* Initialization - NONE */ +PRIVATE inline void FFPU fpu_init_native_fflags(void) + { } + +/* Native to m68k floating-point condition codes - SELF */ +PRIVATE inline uae_u32 FFPU get_fpccr(void) + { return FPU fpsr.condition_codes; } + +/* M68k to native floating-point condition codes - SELF */ +PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) + { FPU fpsr.condition_codes = new_fpcond; } + +#endif /* FPU_USE_GENERIC_FLAGS */ + +/* -------------------------------------------------------------------------- */ +/* --- Use Lazy Flags Evaluation --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_LAZY_FLAGS + +#undef FPU_USE_NATIVE_FLAGS + +#define NATIVE_FFLAG_NEGATIVE 0x08000000 +#define NATIVE_FFLAG_ZERO 0x04000000 +#define NATIVE_FFLAG_INFINITY 0x02000000 +#define NATIVE_FFLAG_NAN 0x01000000 + +/* Initialization - NONE */ +PRIVATE inline void FFPU fpu_init_native_fflags(void) + { } + +/* Native to m68k floating-point condition codes - SELF */ +PRIVATE inline uae_u32 FFPU get_fpccr(void) +{ + uae_u32 fpccr = 0; + if (isnan(FPU result)) + fpccr |= FPSR_CCB_NAN; + else if (FPU result == 0.0) + fpccr |= FPSR_CCB_ZERO; + else if (FPU result < 0.0) + fpccr |= FPSR_CCB_NEGATIVE; + if (isinf(FPU result)) + fpccr |= FPSR_CCB_INFINITY; + return fpccr; +} + +/* M68k to native floating-point condition codes - SELF */ +PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) +{ + if (new_fpcond & FPSR_CCB_NAN) + make_nan(FPU result); + else if (new_fpcond & FPSR_CCB_ZERO) + FPU result = 0.0; + else if (new_fpcond & FPSR_CCB_NEGATIVE) + FPU result = -1.0; + else + FPU result = +1.0; + /* gb-- where is Infinity ? */ +} + +/* Make FPSR according to the value passed in argument */ +PRIVATE inline void FFPU make_fpsr(fpu_register const & r) + { FPU result = r; } + +#endif /* FPU_USE_LAZY_FLAGS */ + +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Common methods --- */ +/* -------------------------------------------------------------------------- */ + +/* Return the address of the floating-point condition codes register */ +static inline uae_u32 * FFPU address_of_fpccr(void) + { return ((uae_u32 *)& FPU fpsr.condition_codes); } + +#endif /* FPU_FLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu.h b/BasiliskII/src/uae_cpu/fpu/fpu.h new file mode 100644 index 00000000..d1fe6dd2 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu.h @@ -0,0 +1,59 @@ +/* + * fpu/fpu.h - public header + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_PUBLIC_HEADER_H +#define FPU_PUBLIC_HEADER_H + +#ifndef FPU_DEBUG +#define FPU_DEBUG 0 +#endif + +#if FPU_DEBUG +#define fpu_debug(args) printf args; +#define FPU_DUMP_REGISTERS 0 +#define FPU_DUMP_FIRST_BYTES 0 +#else +#define fpu_debug(args) ; +#undef FPU_DUMP_REGISTERS +#undef FPU_DUMP_FIRST_BYTES +#endif + +#include "sysdeps.h" +#include "fpu/types.h" +#include "fpu/core.h" + +void fpu_set_fpsr(uae_u32 new_fpsr); +uae_u32 fpu_get_fpsr(void); +void fpu_set_fpcr(uae_u32 new_fpcr); +uae_u32 fpu_get_fpcr(void); + +#endif /* FPU_PUBLIC_HEADER_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp new file mode 100644 index 00000000..5fa1ad0b --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp @@ -0,0 +1,2330 @@ +/* + * fpu_ieee.cpp - the IEEE FPU + * + * Copyright (c) 2001-2008 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * UAE - The Un*x Amiga Emulator + * + * MC68881/MC68040 emulation + * + * Copyright 1996 Herman ten Brugge + * + * + * Following fixes by Lauri Pesonen, July 1999: + * + * FMOVEM list handling: + * The lookup tables did not work correctly, rewritten. + * FINT: + * (int) cast does not work, fixed. + * Further, now honors the FPU fpcr rounding modes. + * FINTRZ: + * (int) cast cannot be used, fixed. + * FGETEXP: + * Input argument value 0 returned erroneous value. + * FMOD: + * (int) cast cannot be used. Replaced by proper rounding. + * Quotient byte handling was missing. + * FREM: + * (int) cast cannot be used. Replaced by proper rounding. + * Quotient byte handling was missing. + * FSCALE: + * Input argument value 0 was not handled correctly. + * FMOVEM Control Registers to/from address FPU registers An: + * A bug caused the code never been called. + * FMOVEM Control Registers pre-decrement: + * Moving of control regs from memory to FPP was not handled properly, + * if not all of the three FPU registers were moved. + * Condition code "Not Greater Than or Equal": + * Returned erroneous value. + * FSINCOS: + * Cosine must be loaded first if same register. + * FMOVECR: + * Status register was not updated (yes, this affects it). + * FMOVE -> reg: + * Status register was not updated (yes, this affects it). + * FMOVE reg -> reg: + * Status register was not updated. + * FDBcc: + * The loop termination condition was wrong. + * Possible leak from int16 to int32 fixed. + * get_fp_value: + * Immediate addressing mode && Operation Length == Byte -> + * Use the low-order byte of the extension word. + * Now FPU fpcr high 16 bits are always read as zeroes, no matter what was + * written to them. + * + * Other: + * - Optimized single/double/extended to/from conversion functions. + * Huge speed boost, but not (necessarily) portable to other systems. + * Enabled/disabled by #define FPU_HAVE_IEEE_DOUBLE 1 + * - Optimized versions of FSCALE, FGETEXP, FGETMAN + * - Conversion routines now handle NaN and infinity better. + * - Some constants precalculated. Not all compilers can optimize the + * expressions previously used. + * + * TODO: + * - Floating point exceptions. + * - More Infinity/NaN/overflow/underflow checking. + * - FPU instruction_address (only needed when exceptions are implemented) + * - Should be written in assembly to support long doubles. + * - Precision rounding single/double + */ + +#include "sysdeps.h" +#include +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#include "main.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" +#include "fpu/fpu_ieee.h" + +/* Global FPU context */ +fpu_t fpu; + +/* -------------------------------------------------------------------------- */ +/* --- Scopes Definition --- */ +/* -------------------------------------------------------------------------- */ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Native Support --- */ +/* -------------------------------------------------------------------------- */ + +#include "fpu/mathlib.h" +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#include "fpu/mathlib.cpp" +#include "fpu/flags.cpp" +#include "fpu/exceptions.cpp" +#include "fpu/rounding.cpp" + +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +#define LD(x) x ## L +#ifdef HAVE_POWL +#define POWL(x, y) powl(x, y) +#else +#define POWL(x, y) pow(x, y) +#endif +#ifdef HAVE_LOG10L +#define LOG10L(x) log10l(x) +#else +#define LOG10L(x) log10(x) +#endif +#else +#define LD(x) x +#define POWL(x, y) pow(x, y) +#define LOG10L(x) log10(x) +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Debugging --- */ +/* -------------------------------------------------------------------------- */ + +PUBLIC void FFPU fpu_dump_registers(void) +{ + for (int i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, fpu_get_register(i)); + if ((i & 3) == 3) + printf ("\n"); + } +} + +PUBLIC void FFPU fpu_dump_flags(void) +{ + printf ("N=%d Z=%d I=%d NAN=%d\n", + (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, + (get_fpsr() & FPSR_CCB_ZERO)!= 0, + (get_fpsr() & FPSR_CCB_INFINITY) != 0, + (get_fpsr() & FPSR_CCB_NAN) != 0); +} + +#if FPU_DEBUG && FPU_DUMP_REGISTERS +PRIVATE void FFPU dump_registers(const char * str) +{ + char temp_str[512]; + + sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", + str, + fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), + fpu_get_register(3), fpu_get_register(4), fpu_get_register(5), + fpu_get_register(6), fpu_get_register(7) ); + + fpu_debug((temp_str)); +#else +PRIVATE void FFPU dump_registers(const char *) +{ +#endif +} + +#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES +PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) +{ + char temp_buf1[256], temp_buf2[10]; + int bytes = sizeof(temp_buf1)/3-1-3; + if (actual < bytes) + bytes = actual; + + temp_buf1[0] = 0; + for (int i = 0; i < bytes; i++) { + sprintf(temp_buf2, "%02x ", (uae_u32)buffer[i]); + strcat(temp_buf1, temp_buf2); + } + + strcat(temp_buf1, "\n"); + fpu_debug((temp_buf1)); +#else + PRIVATE void FFPU dump_first_bytes(uae_u8 *, uae_s32) +{ +#endif +} + +// Quotient Byte is loaded with the sign and least significant +// seven bits of the quotient. +PRIVATE inline void FFPU make_quotient(fpu_register const & quotient, uae_u32 sign) +{ + uae_u32 lsb = (uae_u32)fp_fabs(quotient) & 0x7f; + FPU fpsr.quotient = sign | (lsb << 16); +} + +// to_single +PRIVATE inline fpu_register FFPU make_single(uae_u32 value) +{ +#if 1 + // Use a single, otherwise some checks for NaN, Inf, Zero would have to + // be performed + fpu_single result = 0; + fp_declare_init_shape(srp, single); + srp.ieee.negative = (value >> 31) & 1; + srp.ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; + srp.ieee.mantissa = value & 0x007fffff; + result = srp.value; + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + return result; +#elif 0 /* Original code */ + if ((value & 0x7fffffff) == 0) + return (0.0); + + fpu_register result; + fpu_register_parts *p = (fpu_register_parts *)&result; + + uae_u32 sign = (value & 0x80000000); + uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; + + p->parts[FLO] = value << 29; + p->parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + + return(result); +#endif +} + +// from_single +PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) +{ +#if 1 + fpu_single input = (fpu_single) src; + fp_declare_init_shape(sip, single); + sip.value = input; + uae_u32 result = (sip.ieee.negative << 31) + | (sip.ieee.exponent << 23) + | sip.ieee.mantissa; + fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); + return result; +#elif 0 /* Original code */ + if (src == 0.0) + return 0; + + uae_u32 result; + fpu_register_parts const *p = (fpu_register_parts const *)&src; + + uae_u32 sign = (p->parts[FHI] & 0x80000000); + uae_u32 exp = (p->parts[FHI] & 0x7FF00000) >> 20; + + if(exp + 127 < 1023) { + exp = 0; + } else if(exp > 1023 + 127) { + exp = 255; + } else { + exp = exp + 127 - 1023; + } + + result = sign | (exp << 23) | ((p->parts[FHI] & 0x000FFFFF) << 3) | (p->parts[FLO] >> 29); + + fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); + + return (result); +#endif +} + +// to_exten +PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + // is it zero? + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) + return (wrd1 & 0x80000000) ? -0.0 : 0.0; + + fpu_register result; +#if defined(USE_QUAD_DOUBLE) + // is it NaN? + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + make_nan(result); + return result; + } + // is it inf? + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + if ((wrd1 & 0x80000000) == 0) + make_inf_positive(result); + else + make_inf_negative(result); + return result; + } + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp.ieee.mantissa3 = 0; +#elif defined(USE_LONG_DOUBLE) + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = wrd2; + srp.ieee.mantissa1 = wrd3; + +#else + uae_u32 sgn = (wrd1 >> 31) & 1; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + + // the explicit integer bit is not set, must normalize + if ((wrd2 & 0x80000000) == 0) { + fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3)); + if (wrd2 | wrd3) { + // mantissa, not fraction. + uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; + while (exp > 0 && (man & UVAL64(0x8000000000000000)) == 0) { + man <<= 1; + exp--; + } + wrd2 = (uae_u32)(man >> 32); + wrd3 = (uae_u32)(man & 0xFFFFFFFF); + } + else if (exp != 0x7fff) // zero + exp = FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; + } + + if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) + exp = 0; + else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) + exp = FP_DOUBLE_EXP_MAX; + else + exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; + + fp_declare_init_shape(srp, double); + srp.ieee.negative = sgn; + srp.ieee.exponent = exp; + // drop the explicit integer bit + srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); +#endif + result = srp.value; + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); + return result; +} + +/* + Would be so much easier with full size floats :( + ... this is so vague. +*/ +// make_extended_no_normalize +PRIVATE inline void FFPU make_extended_no_normalize( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result +) +{ + // is it zero? + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + if (wrd1 & 0x80000000) + make_zero_negative(result); + else + make_zero_positive(result); + return; + } + // is it NaN? + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + make_nan(result); + return; + } +#if defined(USE_QUAD_DOUBLE) + // is it inf? + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + if ((wrd1 & 0x80000000) == 0) + make_inf_positive(result); + else + make_inf_negative(result); + return; + } + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp.ieee.mantissa3 = 0; +#elif defined(USE_LONG_DOUBLE) + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = wrd2; + srp.ieee.mantissa1 = wrd3; +#else + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) + exp = 0; + else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) + exp = FP_DOUBLE_EXP_MAX; + else + exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; + + fp_declare_init_shape(srp, double); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = exp; + // drop the explicit integer bit + srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); +#endif + result = srp.value; + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); +} + +// from_exten +PRIVATE inline void FFPU extract_extended(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +) +{ + if (src == 0.0) { + *wrd1 = *wrd2 = *wrd3 = 0; + return; + } +#if defined(USE_QUAD_DOUBLE) + // FIXME: deal with denormals? + fp_declare_init_shape(srp, extended); + srp.value = src; + *wrd1 = (srp.ieee.negative << 31) | (srp.ieee.exponent << 16); + // always set the explicit integer bit. + *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 15) | ((srp.ieee.mantissa1 & 0xfffe0000) >> 17); + *wrd3 = (srp.ieee.mantissa1 << 15) | ((srp.ieee.mantissa2 & 0xfffe0000) >> 17); +#elif defined(USE_LONG_DOUBLE) + fpu_register_parts p = { src }; +#ifdef WORDS_BIGENDIAN + *wrd1 = p.parts[0]; + *wrd2 = p.parts[1]; + *wrd3 = p.parts[2]; +#else + *wrd3 = p.parts[0]; + *wrd2 = p.parts[1]; + *wrd1 = (p.parts[2] & 0xffff) << 16; +#endif +#else + fp_declare_init_shape(srp, double); + srp.value = src; + fpu_debug(("extract_extended (%d,%d,%X,%X)\n", + srp.ieee.negative , srp.ieee.exponent, + srp.ieee.mantissa0, srp.ieee.mantissa1)); + + uae_u32 exp = srp.ieee.exponent; + + if (exp == FP_DOUBLE_EXP_MAX) + exp = FP_EXTENDED_EXP_MAX; + else + exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; + + *wrd1 = (srp.ieee.negative << 31) | (exp << 16); + // always set the explicit integer bit. + *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 11) | ((srp.ieee.mantissa1 & 0xffe00000) >> 21); + *wrd3 = srp.ieee.mantissa1 << 11; +#endif + fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +} + +// to_double +PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) +{ + union { + fpu_double value; + uae_u32 parts[2]; + } dest; +#ifdef WORDS_BIGENDIAN + dest.parts[0] = wrd1; + dest.parts[1] = wrd2; +#else + dest.parts[0] = wrd2; + dest.parts[1] = wrd1; +#endif + fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,dest.value)); + return (fpu_register)(dest.value); +} + +// from_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2 +) +{ + union { + fpu_double value; + uae_u32 parts[2]; + } dest; + dest.value = (fpu_double)src; +#ifdef WORDS_BIGENDIAN + *wrd1 = dest.parts[0]; + *wrd2 = dest.parts[1]; +#else + *wrd2 = dest.parts[0]; + *wrd1 = dest.parts[1]; +#endif + fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); +} + +// to_pack +PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + fpu_register d; + bool sm = (wrd1 & 0x80000000) != 0; + bool se = (wrd1 & 0x40000000) != 0; + int exp = (wrd1 & 0x7fff0000) >> 16; + unsigned int dig; + fpu_register pwr; + + if (exp == 0x7fff) + { + if (wrd2 == 0 && wrd3 == 0) + { + sm ? make_inf_negative(d) : make_inf_positive(d); + } else + { + make_nan(d); + } + return d; + } + dig = wrd1 & 0x0000000f; + if (dig == 0 && wrd2 == 0 && wrd3 == 0) + { + sm ? make_zero_negative(d) : make_zero_positive(d); + return d; + } + + /* + * Convert the bcd exponent to binary by successive adds and + * muls. Set the sign according to SE. Subtract 16 to compensate + * for the mantissa which is to be interpreted as 17 integer + * digits, rather than 1 integer and 16 fraction digits. + * Note: this operation can never overflow. + */ + exp = ((wrd1 >> 24) & 0xf); + exp = exp * 10 + ((wrd1 >> 20) & 0xf); + exp = exp * 10 + ((wrd1 >> 16) & 0xf); + if (se) + exp = -exp; + /* sub to compensate for shift of mant */ + exp = exp - 16; + + /* + * Convert the bcd mantissa to binary by successive + * adds and muls. Set the sign according to SM. + * The mantissa digits will be converted with the decimal point + * assumed following the least-significant digit. + * Note: this operation can never overflow. + */ + d = wrd1 & 0xf; + d = (d * LD(10.0)) + ((wrd2 >> 28) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 24) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 20) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 16) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 12) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 8) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 4) & 0xf); + d = (d * LD(10.0)) + ((wrd2 ) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 28) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 24) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 20) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 16) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 12) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 8) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 4) & 0xf); + d = (d * LD(10.0)) + ((wrd3 ) & 0xf); + + /* Check the sign of the mant and make the value in fp0 the same sign. */ + if (sm) + d = -d; + + /* + * Calculate power-of-ten factor from exponent. + */ + if (exp < 0) + { + exp = -exp; + pwr = POWL(LD(10.0), exp); + d = d / pwr; + } else + { + pwr = POWL(LD(10.0), exp); + d = d * pwr; + } + + fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); + return d; +} + +// from_pack +PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +{ + fpu_register pwr; + int exp; + fpu_register d; + bool sm, se; + int dig; + + *wrd1 = *wrd2 = *wrd3 = 0; + + d = src; + sm = false; + if (isneg(src)) + { + d = -d; + sm = true; + } + + if (isnan(src)) + { + *wrd1 = sm ? 0xffff0000 : 0x7fff0000; + *wrd2 = 0xffffffff; + *wrd3 = 0xffffffff; + return; + } + if (isinf(src)) + { + *wrd1 = sm ? 0xffff0000 : 0x7fff0000; + *wrd2 = *wrd3 = 0; + return; + } + if (iszero(src)) + { + *wrd1 = sm ? 0x80000000 : 0x00000000; + *wrd2 = *wrd3 = 0; + return; + } + sm = false; + if (isneg(src)) + { + d = -d; + sm = true; + } + exp = (int)floor(LOG10L(d)); + se = false; + if (exp < 0) + { + exp = -exp; + se = true; + pwr = POWL(LD(10.0), exp); + d = d * pwr; + } else + { + pwr = POWL(LD(10.0), exp); + d = d / pwr; + } + dig = (int)d; d = LD(10) * (d - dig); *wrd1 |= dig; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 28; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 24; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 20; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 16; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 12; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 8; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 4; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 28; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 24; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 20; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 16; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 12; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 8; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 4; + dig = (int)d; *wrd3 |= dig; + + dig = (exp / 100) % 10; + *wrd1 |= dig << 24; + dig = (exp / 10) % 10; + *wrd1 |= dig << 20; + dig = (exp) % 10; + *wrd1 |= dig << 16; + if (sm) + *wrd1 |= 0x80000000; + if (se) + *wrd1 |= 0x40000000; + fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +} + +PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register & src) +{ + uaecptr tmppc; + uae_u16 tmp; + int size; + int mode; + int reg; + uae_u32 ad = 0; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // fpu_debug(("get_fp_value(%X,%X)\n",(int)opcode,(int)extra)); + // dump_first_bytes( regs.pc_p-4, 16 ); + + if ((extra & 0x4000) == 0) { + src = FPU registers[(extra >> 10) & 7]; + return 1; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + + fpu_debug(("get_fp_value mode=%d, reg=%d, size=%d\n",(int)mode,(int)reg,(int)size)); + + switch (mode) { + case 0: + switch (size) { + case 6: + src = (fpu_register) (uae_s8) m68k_dreg (regs, reg); + break; + case 4: + src = (fpu_register) (uae_s16) m68k_dreg (regs, reg); + break; + case 0: + src = (fpu_register) (uae_s32) m68k_dreg (regs, reg); + break; + case 1: + src = make_single(m68k_dreg (regs, reg)); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + break; + case 4: + ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + fpu_debug(("get_fp_value next_iword()=%X\n",ad-m68k_getpc()-2)); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + if(size == 6) ad++; + break; + default: + return 0; + } + } + + fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + fpu_debug(("get_fp_value ad=%X\n",ad)); + fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); + //dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 ); + //dump_first_bytes( get_real_address(ad, 0, 0), 64 ); + + switch (size) { + case 0: + src = (fpu_register) (uae_s32) get_long (ad); + break; + case 1: + src = make_single(get_long (ad)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_extended(wrd1, wrd2, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_packed(wrd1, wrd2, wrd3); + break; + } + case 4: + src = (fpu_register) (uae_s16) get_word(ad); + break; + case 5: { + uae_u32 wrd1, wrd2; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + src = make_double(wrd1, wrd2); + break; + } + case 6: + src = (fpu_register) (uae_s8) get_byte(ad); + break; + default: + return 0; + } + + switch (mode) { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); + return 1; +} + +/* Convert the FP value to integer according to the current m68k rounding mode */ +PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) +{ + fpu_register result; + switch (get_fpcr() & FPCR_ROUNDING_MODE) { + case FPCR_ROUND_ZERO: + result = fp_round_to_zero(src); + break; + case FPCR_ROUND_MINF: + result = fp_round_to_minus_infinity(src); + break; + case FPCR_ROUND_NEAR: + result = fp_round_to_nearest(src); + break; + case FPCR_ROUND_PINF: + result = fp_round_to_plus_infinity(src); + break; + default: + result = src; /* should never be reached */ + break; + } + return (uae_s32)result; +} + +PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) +{ + uae_u16 tmp; + uaecptr tmppc; + int size; + int mode; + int reg; + uae_u32 ad; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // fpu_debug(("put_fp_value(%.04f,%X,%X)\n",(float)value,(int)opcode,(int)extra)); + + if ((extra & 0x4000) == 0) { + int dest_reg = (extra >> 10) & 7; + FPU registers[dest_reg] = value; + make_fpsr(FPU registers[dest_reg]); + return 1; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + ad = 0xffffffff; + switch (mode) { + case 0: + switch (size) { + case 6: + m68k_dreg (regs, reg) = ((toint(value) & 0xff) + | (m68k_dreg (regs, reg) & ~0xff)); + break; + case 4: + m68k_dreg (regs, reg) = ((toint(value) & 0xffff) + | (m68k_dreg (regs, reg) & ~0xffff)); + break; + case 0: + m68k_dreg (regs, reg) = toint(value); + break; + case 1: + m68k_dreg (regs, reg) = extract_single(value); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + break; + default: + return 0; + } + } + switch (size) { + case 0: + put_long (ad, toint(value)); + break; + case 1: + put_long (ad, extract_single(value)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + extract_extended(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + extract_packed(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 4: + put_word(ad, (uae_s16) toint(value)); + break; + case 5: { + uae_u32 wrd1, wrd2; + extract_double(value, &wrd1, &wrd2); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + break; + } + case 6: + put_byte(ad, (uae_s8) toint(value)); + break; + default: + return 0; + } + return 1; +} + +PRIVATE inline int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) +{ + uae_u16 tmp; + uaecptr tmppc; + int mode; + int reg; + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) { + case 0: + case 1: + return 0; + case 2: + *ad = m68k_areg (regs, reg); + break; + case 3: + *ad = m68k_areg (regs, reg); + break; + case 4: + *ad = m68k_areg (regs, reg); + break; + case 5: + *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + *ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + *ad = next_ilong(); + break; + case 2: + *ad = m68k_getpc (); + *ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + *ad = get_disp_ea_020 (tmppc, tmp); + break; + default: + return 0; + } + } + return 1; +} + +#if FPU_DEBUG +# define CONDRET(s,x) fpu_debug(("fpp_cond %s = %d\n",s,(uint32)(x))); return (x) +#else +# define CONDRET(s,x) return (x) +#endif + +PRIVATE inline int FFPU fpp_cond(int condition) +{ + int N = (FPU result < 0.0); + int Z = (FPU result == 0.0); + int NaN = isnan(FPU result); + + if (NaN) + N = Z = 0; + + switch (condition & 0x1f) { + case 0x00: CONDRET("False",0); + case 0x01: CONDRET("Equal",Z); + case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); + case 0x03: CONDRET("Ordered Greater Than or Equal",Z || !(NaN || N)); + case 0x04: CONDRET("Ordered Less Than",N && !(NaN || Z)); + case 0x05: CONDRET("Ordered Less Than or Equal",Z || (N && !NaN)); + case 0x06: CONDRET("Ordered Greater or Less Than",!(NaN || Z)); + case 0x07: CONDRET("Ordered",!NaN); + case 0x08: CONDRET("Unordered",NaN); + case 0x09: CONDRET("Unordered or Equal",NaN || Z); + case 0x0a: CONDRET("Unordered or Greater Than",NaN || !(N || Z)); + case 0x0b: CONDRET("Unordered or Greater or Equal",NaN || Z || !N); + case 0x0c: CONDRET("Unordered or Less Than",NaN || (N && !Z)); + case 0x0d: CONDRET("Unordered or Less or Equal",NaN || Z || N); + case 0x0e: CONDRET("Not Equal",!Z); + case 0x0f: CONDRET("True",1); + case 0x10: CONDRET("Signaling False",0); + case 0x11: CONDRET("Signaling Equal",Z); + case 0x12: CONDRET("Greater Than",!(NaN || Z || N)); + case 0x13: CONDRET("Greater Than or Equal",Z || !(NaN || N)); + case 0x14: CONDRET("Less Than",N && !(NaN || Z)); + case 0x15: CONDRET("Less Than or Equal",Z || (N && !NaN)); + case 0x16: CONDRET("Greater or Less Than",!(NaN || Z)); + case 0x17: CONDRET("Greater, Less or Equal",!NaN); + case 0x18: CONDRET("Not Greater, Less or Equal",NaN); + case 0x19: CONDRET("Not Greater or Less Than",NaN || Z); + case 0x1a: CONDRET("Not Less Than or Equal",NaN || !(N || Z)); + case 0x1b: CONDRET("Not Less Than",NaN || Z || !N); + case 0x1c: CONDRET("Not Greater Than or Equal", NaN || (N && !Z)); + case 0x1d: CONDRET("Not Greater Than",NaN || Z || N); + case 0x1e: CONDRET("Signaling Not Equal",!Z); + case 0x1f: CONDRET("Signaling True",1); + default: CONDRET("",-1); + } +} + +void FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fdbcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uaecptr pc = (uae_u32) m68k_getpc (); + uae_s32 disp = (uae_s32) (uae_s16) next_iword(); + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (pc - 4); + op_illg (opcode); + } else if (!cc) { + int reg = opcode & 0x7; + + // this may have leaked. + /* + m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) + | ((m68k_dreg (regs, reg) - 1) & 0xffff)); + */ + m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000) + | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff)); + + + // condition reversed. + // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) + if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) + m68k_setpc (pc + disp); + } +} + +void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uae_u32 ad = 0; + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else if ((opcode & 0x38) == 0) { + m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | + (cc ? 0xff : 0x00); + } + else if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else + put_byte(ad, cc ? 0xff : 0x00); +} + +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +{ + fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (oldpc); + op_illg (opcode); + } + if (cc) + Exception(7, oldpc - 2); +} + +// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) +void FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) +{ + fpu_debug(("fbcc_opp %X, %X at %08lx, jumpto=%X\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); + + int cc = fpp_cond(opcode & 0x3f); + if (cc == -1) { + m68k_setpc (pc); + op_illg (opcode); + } + else if (cc) { + if ((opcode & 0x40) == 0) + extra = (uae_s32) (uae_s16) extra; + m68k_setpc (pc + extra); + } +} + +// FSAVE has no post-increment +// 0x1f180000 == IDLE state frame, coprocessor version number 1F +void FFPU fpuop_save(uae_u32 opcode) +{ + fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); + + uae_u32 ad = 0; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int i; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (CPUType == 4) { + // Put 4 byte 68040 IDLE frame. + if (incr < 0) { + ad -= 4; + put_long (ad, 0x41000000); + } + else { + put_long (ad, 0x41000000); + ad += 4; + } + } else { + // Put 28 byte 68881 IDLE frame. + if (incr < 0) { + fpu_debug(("fsave_opp pre-decrement\n")); + ad -= 4; + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + for (i = 0; i < 5; i++) { + ad -= 4; + put_long (ad, 0x00000000); + } + ad -= 4; + put_long (ad, 0x1f180000); // IDLE, vers 1f + } + else { + put_long (ad, 0x1f180000); // IDLE, vers 1f + ad += 4; + for (i = 0; i < 5; i++) { + put_long (ad, 0x00000000); + ad += 4; + } + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + ad += 4; + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + fpu_debug(("PROBLEM: fsave_opp post-increment\n")); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("fsave_opp pre-decrement %X -> A%d\n",ad,opcode & 7)); + } +} + +// FRESTORE has no pre-decrement +void FFPU fpuop_restore(uae_u32 opcode) +{ + fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); + + uae_u32 ad = 0; + uae_u32 d; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (CPUType == 4) { + // 68040 + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); + ad -= 44; + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad -= 92; + } + } + } + else { + d = get_long (ad); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); + ad += 44; + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad += 92; + } + } + } + } + else { + // 68881 + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { + if ((d & 0x00ff0000) == 0x00180000) + ad -= 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad -= 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad -= 45 * 4; + } + } + else { + d = get_long (ad); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0x00180000) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + ad += 6 * 4; + } + else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? + ad += 14 * 4; + fpu_debug(("PROBLEM: frestore_opp found UNIMP? frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad += 45 * 4; + } + } + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("frestore_opp post-increment %X -> A%d\n",ad,opcode & 7)); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + fpu_debug(("PROBLEM: frestore_opp pre-decrement\n")); + } +} + +void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) +{ + int reg; + fpu_register src; + + fpu_debug(("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, + m68k_getpc () - 4)); + + dump_registers( "START"); + + switch ((extra >> 13) & 0x7) { + case 3: + fpu_debug(("FMOVE -> \n")); + if (put_fp_value (opcode, extra, FPU registers[(extra >> 7) & 7]) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + dump_registers( "END "); + return; + case 4: + case 5: + if ((opcode & 0x38) == 0) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_dreg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> D%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> D%d\n", FPU instruction_address, opcode & 7)); + } + } + else { + if (extra & 0x1000) { + set_fpcr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_dreg (regs, opcode & 7); + fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } +// } else if ((opcode & 0x38) == 1) { + } + else if ((opcode & 0x38) == 8) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_areg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> A%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_areg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> A%d\n", FPU instruction_address, opcode & 7)); + } + } else { + if (extra & 0x1000) { + set_fpcr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_areg (regs, opcode & 7); + fpu_debug(("FMOVEM A%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } + } + else if ((opcode & 0x3f) == 0x3c) { + if ((extra & 0x2000) == 0) { + if (extra & 0x1000) { + set_fpcr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpcr\n", get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpsr\n", get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = next_ilong(); + fpu_debug(("FMOVEM #<%X> -> FPU instruction_address\n", FPU instruction_address)); + } + } + } + else if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + uae_u32 ad = 0; + int incr = 0; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + if ((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + } + ad -= incr; + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + put_long (ad, get_fpcr() & 0xFFFF); + fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); + ad += 4; + } + if (extra & 0x0800) { + put_long (ad, get_fpsr()); + fpu_debug(("FMOVEM FPU fpsr (%X) -> mem %X\n", get_fpsr(), ad )); + ad += 4; + } + if (extra & 0x0400) { + put_long (ad, FPU instruction_address); + fpu_debug(("FMOVEM FPU instruction_address (%X) -> mem %X\n", FPU instruction_address, ad )); + ad += 4; + } + ad -= incr; + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + uae_u32 ad = 0; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + + // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; + int incr = 0; + if((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + ad = ad - incr; + } + + if (extra & 0x1000) { + set_fpcr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpcr\n", ad, get_fpcr() )); + ad += 4; + } + if (extra & 0x0800) { + set_fpsr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpsr\n", ad, get_fpsr() )); + ad += 4; + } + if (extra & 0x0400) { + FPU instruction_address = get_long (ad); + fpu_debug(("FMOVEM mem %X (%X) -> FPU instruction_address\n", ad, FPU instruction_address )); + ad += 4; + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? +// m68k_areg (regs, opcode & 7) = ad - 12; + m68k_areg (regs, opcode & 7) = ad - incr; + } + dump_registers( "END "); + return; + case 6: + case 7: { + uae_u32 ad = 0, list = 0; + int incr = 0; + if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + fpu_debug(("FMOVEM FPP->memory\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + if (incr < 0) { + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + fpu_debug(("FMOVEM memory->FPP\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + /**/ + if (incr < 0) { + // not reached + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + dump_registers( "END "); + return; + } + case 0: + case 2: + reg = (extra >> 7) & 7; + if ((extra & 0xfc00) == 0x5c00) { + fpu_debug(("FMOVECR memory->FPP\n")); + switch (extra & 0x7f) { + case 0x00: + // FPU registers[reg] = 4.0 * atan(1.0); + FPU registers[reg] = LD(3.1415926535897932384626433832795029); + fpu_debug(("FP const: Pi\n")); + break; + case 0x0b: + // FPU registers[reg] = log10 (2.0); + FPU registers[reg] = LD(0.30102999566398119521); // 0.3010299956639811952137388947244930L + fpu_debug(("FP const: Log 10 (2)\n")); + break; + case 0x0c: + // FPU registers[reg] = exp (1.0); + FPU registers[reg] = LD(2.7182818284590452353); // 2.7182818284590452353602874713526625L + fpu_debug(("FP const: e\n")); + break; + case 0x0d: + // FPU registers[reg] = log (exp (1.0)) / log (2.0); + FPU registers[reg] = LD(1.4426950408889634073599246810019); + fpu_debug(("FP const: Log 2 (e)\n")); + break; + case 0x0e: + // FPU registers[reg] = log (exp (1.0)) / log (10.0); + FPU registers[reg] = LD(0.4342944819032518276511289189166051); + fpu_debug(("FP const: Log 10 (e)\n")); + break; + case 0x0f: + FPU registers[reg] = 0.0; + fpu_debug(("FP const: zero\n")); + break; + case 0x30: + // FPU registers[reg] = log (2.0); + FPU registers[reg] = LD(0.6931471805599453094172321214581766); + fpu_debug(("FP const: ln(2)\n")); + break; + case 0x31: + // FPU registers[reg] = log (10.0); + FPU registers[reg] = LD(2.3025850929940456840179914546843642); + fpu_debug(("FP const: ln(10)\n")); + break; + case 0x32: + // ?? + FPU registers[reg] = LD(1.0e0); + fpu_debug(("FP const: 1.0e0\n")); + break; + case 0x33: + FPU registers[reg] = LD(1.0e1); + fpu_debug(("FP const: 1.0e1\n")); + break; + case 0x34: + FPU registers[reg] = LD(1.0e2); + fpu_debug(("FP const: 1.0e2\n")); + break; + case 0x35: + FPU registers[reg] = LD(1.0e4); + fpu_debug(("FP const: 1.0e4\n")); + break; + case 0x36: + FPU registers[reg] = LD(1.0e8); + fpu_debug(("FP const: 1.0e8\n")); + break; + case 0x37: + FPU registers[reg] = LD(1.0e16); + fpu_debug(("FP const: 1.0e16\n")); + break; + case 0x38: + FPU registers[reg] = LD(1.0e32); + fpu_debug(("FP const: 1.0e32\n")); + break; + case 0x39: + FPU registers[reg] = LD(1.0e64); + fpu_debug(("FP const: 1.0e64\n")); + break; + case 0x3a: + FPU registers[reg] = LD(1.0e128); + fpu_debug(("FP const: 1.0e128\n")); + break; + case 0x3b: + FPU registers[reg] = LD(1.0e256); + fpu_debug(("FP const: 1.0e256\n")); + break; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + case 0x3c: + FPU registers[reg] = LD(1.0e512); + fpu_debug(("FP const: 1.0e512\n")); + break; + case 0x3d: + FPU registers[reg] = LD(1.0e1024); + fpu_debug(("FP const: 1.0e1024\n")); + break; + case 0x3e: + FPU registers[reg] = LD(1.0e2048); + fpu_debug(("FP const: 1.0e2048\n")); + break; + case 0x3f: + FPU registers[reg] = LD(1.0e4096); + fpu_debug(("FP const: 1.0e4096\n")); +#endif + break; + default: + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + // these *do* affect the status reg + make_fpsr(FPU registers[reg]); + dump_registers( "END "); + return; + } + + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + + if (FPU is_integral) { + // 68040-specific operations + switch (extra & 0x7f) { + case 0x40: /* FSMOVE */ + fpu_debug(("FSMOVE %.04f\n",(double)src)); + FPU registers[reg] = (float)src; + make_fpsr(FPU registers[reg]); + break; + case 0x44: /* FDMOVE */ + fpu_debug(("FDMOVE %.04f\n",(double)src)); + FPU registers[reg] = (double)src; + make_fpsr(FPU registers[reg]); + break; + case 0x41: /* FSSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (float)fp_sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x45: /* FDSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (double)fp_sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x58: /* FSABS */ + fpu_debug(("FSABS %.04f\n",(double)src)); + FPU registers[reg] = (float)fp_fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5c: /* FDABS */ + fpu_debug(("FDABS %.04f\n",(double)src)); + FPU registers[reg] = (double)fp_fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5a: /* FSNEG */ + fpu_debug(("FSNEG %.04f\n",(double)src)); + FPU registers[reg] = (float)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x5e: /* FDNEG */ + fpu_debug(("FDNEG %.04f\n",(double)src)); + FPU registers[reg] = (double)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x60: /* FSDIV */ + fpu_debug(("FSDIV %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x64: /* FDDIV */ + fpu_debug(("FDDIV %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x62: /* FSADD */ + fpu_debug(("FSADD %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x66: /* FDADD */ + fpu_debug(("FDADD %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x68: /* FSSUB */ + fpu_debug(("FSSUB %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x6c: /* FDSUB */ + fpu_debug(("FDSUB %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x63: /* FSMUL */ + case 0x67: /* FDMUL */ + fpu_debug(("FMUL %.04f\n",(double)src)); + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if (fl_dest.in_range && fl_source.in_range) { + if ((extra & 0x7f) == 0x63) + FPU registers[reg] = (float)(FPU registers[reg] * src); + else + FPU registers[reg] = (double)(FPU registers[reg] * src); + } + else if (fl_dest.nan || fl_source.nan || + (fl_dest.zero && fl_source.infinity) || + (fl_dest.infinity && fl_source.zero) ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if ( (fl_dest.negative && !fl_source.negative) || + (!fl_dest.negative && fl_source.negative) ) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if ( (fl_dest.negative && !fl_source.negative) || + (!fl_dest.negative && fl_source.negative) ) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } + make_fpsr(FPU registers[reg]); + break; + default: + // Continue decode-execute 6888x instructions below + goto process_6888x_instructions; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + process_6888x_instructions: + switch (extra & 0x7f) { + case 0x00: /* FMOVE */ + fpu_debug(("FMOVE %.04f\n",(double)src)); + FPU registers[reg] = src; + make_fpsr(FPU registers[reg]); + break; + case 0x01: /* FINT */ + fpu_debug(("FINT %.04f\n",(double)src)); + FPU registers[reg] = toint(src); + make_fpsr(FPU registers[reg]); + break; + case 0x02: /* FSINH */ + fpu_debug(("FSINH %.04f\n",(double)src)); + FPU registers[reg] = fp_sinh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x03: /* FINTRZ */ + fpu_debug(("FINTRZ %.04f\n",(double)src)); + FPU registers[reg] = fp_round_to_zero(src); + make_fpsr(FPU registers[reg]); + break; + case 0x04: /* FSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = fp_sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x06: /* FLOGNP1 */ + fpu_debug(("FLOGNP1 %.04f\n",(double)src)); + FPU registers[reg] = fp_log (src + 1.0); + make_fpsr(FPU registers[reg]); + break; + case 0x08: /* FETOXM1 */ + fpu_debug(("FETOXM1 %.04f\n",(double)src)); + FPU registers[reg] = fp_exp (src) - 1.0; + make_fpsr(FPU registers[reg]); + break; + case 0x09: /* FTANH */ + fpu_debug(("FTANH %.04f\n",(double)src)); + FPU registers[reg] = fp_tanh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0a: /* FATAN */ + fpu_debug(("FATAN %.04f\n",(double)src)); + FPU registers[reg] = fp_atan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0c: /* FASIN */ + fpu_debug(("FASIN %.04f\n",(double)src)); + FPU registers[reg] = fp_asin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0d: /* FATANH */ + fpu_debug(("FATANH %.04f\n",(double)src)); + FPU registers[reg] = fp_atanh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0e: /* FSIN */ + fpu_debug(("FSIN %.04f\n",(double)src)); + FPU registers[reg] = fp_sin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0f: /* FTAN */ + fpu_debug(("FTAN %.04f\n",(double)src)); + FPU registers[reg] = fp_tan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x10: /* FETOX */ + fpu_debug(("FETOX %.04f\n",(double)src)); + FPU registers[reg] = fp_exp (src); + make_fpsr(FPU registers[reg]); + break; + case 0x11: /* FTWOTOX */ + fpu_debug(("FTWOTOX %.04f\n",(double)src)); + FPU registers[reg] = fp_pow(2.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x12: /* FTENTOX */ + fpu_debug(("FTENTOX %.04f\n",(double)src)); + FPU registers[reg] = fp_pow(10.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x14: /* FLOGN */ + fpu_debug(("FLOGN %.04f\n",(double)src)); + FPU registers[reg] = fp_log (src); + make_fpsr(FPU registers[reg]); + break; + case 0x15: /* FLOG10 */ + fpu_debug(("FLOG10 %.04f\n",(double)src)); + FPU registers[reg] = fp_log10 (src); + make_fpsr(FPU registers[reg]); + break; + case 0x16: /* FLOG2 */ + fpu_debug(("FLOG2 %.04f\n",(double)src)); + FPU registers[reg] = fp_log (src) / fp_log (2.0); + make_fpsr(FPU registers[reg]); + break; + case 0x18: /* FABS */ + fpu_debug(("FABS %.04f\n",(double)src)); + FPU registers[reg] = fp_fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x19: /* FCOSH */ + fpu_debug(("FCOSH %.04f\n",(double)src)); + FPU registers[reg] = fp_cosh(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1a: /* FNEG */ + fpu_debug(("FNEG %.04f\n",(double)src)); + FPU registers[reg] = -src; + make_fpsr(FPU registers[reg]); + break; + case 0x1c: /* FACOS */ + fpu_debug(("FACOS %.04f\n",(double)src)); + FPU registers[reg] = fp_acos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1d: /* FCOS */ + fpu_debug(("FCOS %.04f\n",(double)src)); + FPU registers[reg] = fp_cos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1e: /* FGETEXP */ + fpu_debug(("FGETEXP %.04f\n",(double)src)); + if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = fast_fgetexp( src ); + } + make_fpsr(FPU registers[reg]); + break; + case 0x1f: /* FGETMAN */ + fpu_debug(("FGETMAN %.04f\n",(double)src)); + if( src == 0 ) { + FPU registers[reg] = 0; + } + else if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = src; + fast_remove_exponent( FPU registers[reg] ); + } + make_fpsr(FPU registers[reg]); + break; + case 0x20: /* FDIV */ + fpu_debug(("FDIV %.04f\n",(double)src)); + FPU registers[reg] /= src; + make_fpsr(FPU registers[reg]); + break; + case 0x21: /* FMOD */ + fpu_debug(("FMOD %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (fpu_register) ((int) (FPU registers[reg] / src)) * src; + { + fpu_register quot = fp_round_to_zero(FPU registers[reg] / src); + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); + make_quotient(quot, sign); + } + break; + case 0x23: /* FMUL */ + fpu_debug(("FMUL %.04f\n",(double)src)); + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if (fl_dest.in_range && fl_source.in_range) { + FPU registers[reg] *= src; + if (unlikely(isinf(FPU registers[reg]))) + { + isneg(FPU registers[reg]) ? make_inf_negative(FPU registers[reg]) : make_inf_positive(FPU registers[reg]); + } + } + else if (fl_dest.nan || fl_source.nan || + (fl_dest.zero && fl_source.infinity) || + (fl_dest.infinity && fl_source.zero) ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if ( (fl_dest.negative && !fl_source.negative) || + (!fl_dest.negative && fl_source.negative) ) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if ( (fl_dest.negative && !fl_source.negative) || + (!fl_dest.negative && fl_source.negative) ) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } + make_fpsr(FPU registers[reg]); + break; + case 0x24: /* FSGLDIV */ + fpu_debug(("FSGLDIV %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x25: /* FREM */ + fpu_debug(("FREM %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; + { + fpu_register quot = fp_round_to_nearest(FPU registers[reg] / src); + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); + make_quotient(quot,sign); + } + break; + + case 0x26: /* FSCALE */ + fpu_debug(("FSCALE %.04f\n",(double)src)); + // TODO: overflow flags + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if (fl_source.in_range && fl_dest.in_range) { + // When the absolute value of the source operand is >= 2^14, + // an overflow or underflow always results. + // Here (int) cast is okay. + int scale_factor = (int)fp_round_to_zero(src); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = FPU registers[reg]; + sxp.ieee.exponent += scale_factor; + FPU registers[reg] = sxp.value; +#else + fp_declare_init_shape(sxp, double); + sxp.value = FPU registers[reg]; + uae_u32 exp = sxp.ieee.exponent + scale_factor; + if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) + exp = 0; + else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) + exp = FP_DOUBLE_EXP_MAX; + else + exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; + sxp.ieee.exponent = exp; + FPU registers[reg] = sxp.value; +#endif + } + else if (fl_source.infinity) { + // Returns NaN for any Infinity source + make_nan( FPU registers[reg] ); + } + make_fpsr(FPU registers[reg]); + break; + case 0x27: /* FSGLMUL */ + fpu_debug(("FSGLMUL %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] * src); + make_fpsr(FPU registers[reg]); + break; + case 0x28: /* FSUB */ + fpu_debug(("FSUB %.04f\n",(double)src)); + FPU registers[reg] -= src; + make_fpsr(FPU registers[reg]); + break; + case 0x22: /* FADD */ + fpu_debug(("FADD %.04f\n",(double)src)); + FPU registers[reg] += src; + if (unlikely(isinf(FPU registers[reg]))) + { + isneg(FPU registers[reg]) ? make_inf_negative(FPU registers[reg]) : make_inf_positive(FPU registers[reg]); + } + make_fpsr(FPU registers[reg]); + break; + case 0x30: /* FSINCOS */ + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + fpu_debug(("FSINCOS %.04f\n",(double)src)); + // Cosine must be calculated first if same register + FPU registers[extra & 7] = fp_cos(src); + FPU registers[reg] = fp_sin (src); + // Set FPU fpsr according to the sine result + make_fpsr(FPU registers[reg]); + break; + case 0x38: /* FCMP */ + fpu_debug(("FCMP %.04f\n",(double)src)); + set_fpsr(0); + if (isinf(FPU registers[reg])) + { + if (isinf(src) && isneg(FPU registers[reg]) == isneg (src)) + make_fpsr(0); + else + make_fpsr(FPU registers[reg]); + } + else if (isinf(src)) + make_fpsr(-src); + else + make_fpsr(FPU registers[reg] - src); + break; + case 0x3a: /* FTST */ + fpu_debug(("FTST %.04f\n",(double)src)); + set_fpsr(0); + make_fpsr(src); + break; + default: + fpu_debug(("ILLEGAL F OP %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + fpu_debug(("ILLEGAL F OP 2 %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); +} + + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} + +/* -------------------------- Initialization -------------------------- */ + +PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 + +PUBLIC void FFPU fpu_init (bool integral_68040) +{ + fpu_debug(("fpu_init\n")); + + static bool initialized_lookup_tables = false; + if (!initialized_lookup_tables) { + fpu_init_native_fflags(); + fpu_init_native_exceptions(); + fpu_init_native_accrued_exceptions(); + initialized_lookup_tables = true; + } + + FPU is_integral = integral_68040; + FPU instruction_address = 0; + FPU fpsr.quotient = 0; + set_fpcr(0); + set_fpsr(0); + +#if defined(FPU_USE_X86_ROUNDING) + // Initial state after boot, reset and frestore(null frame) + x86_control_word = CW_INITIAL; +#elif defined(USE_X87_ASSEMBLY) + volatile unsigned short int cw; + __asm__ __volatile__("fnstcw %0" : "=m" (cw)); + cw &= ~0x0300; cw |= 0x0300; // CW_PC_EXTENDED + cw &= ~0x0C00; cw |= 0x0000; // CW_RC_NEAR + __asm__ __volatile__("fldcw %0" : : "m" (cw)); +#endif + + FPU result = 1; + + for (int i = 0; i < 8; i++) + make_nan(FPU registers[i]); +} + +PUBLIC void FFPU fpu_exit (void) +{ + fpu_debug(("fpu_exit\n")); +} + +PUBLIC void FFPU fpu_reset (void) +{ + fpu_debug(("fpu_reset\n")); + fpu_exit(); + fpu_init(FPU is_integral); +} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h new file mode 100644 index 00000000..3321891a --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h @@ -0,0 +1,154 @@ +/* + * fpu/fpu_ieee.h - Extra Definitions for the IEEE FPU core + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_IEEE_H +#define FPU_IEEE_H + +/* NOTE: this file shall be included from fpu/fpu_uae.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +// Lauri-- full words to avoid partial register stalls. +struct double_flags { + uae_u32 in_range; + uae_u32 zero; + uae_u32 infinity; + uae_u32 nan; + uae_u32 negative; +}; +PRIVATE double_flags fl_source; +PRIVATE double_flags fl_dest; +PRIVATE inline void FFPU get_dest_flags(fpu_register const & r); +PRIVATE inline void FFPU get_source_flags(fpu_register const & r); + +PRIVATE inline void FFPU make_nan(fpu_register & r); +PRIVATE inline void FFPU make_zero_positive(fpu_register & r); +PRIVATE inline void FFPU make_zero_negative(fpu_register & r); +PRIVATE inline void FFPU make_inf_positive(fpu_register & r); +PRIVATE inline void FFPU make_inf_negative(fpu_register & r); + +// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); +PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); + +// May be optimized for particular processors +#ifndef FPU_USE_NATIVE_FLAGS +PRIVATE inline void FFPU make_fpsr(fpu_register const & r); +#endif + +// Normalize to range 1..2 +PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r); + +// The sign of the quotient is the exclusive-OR of the sign bits +// of the source and destination operands. +PRIVATE inline uae_u32 FFPU get_quotient_sign( + fpu_register const & ra, fpu_register const & rb +); + +// Quotient Byte is loaded with the sign and least significant +// seven bits of the quotient. +PRIVATE inline void FFPU make_quotient( + fpu_register const & quotient, uae_u32 sign +); + +// to_single +PRIVATE inline fpu_register FFPU make_single( + uae_u32 value +); + +// from_single +PRIVATE inline uae_u32 FFPU extract_single( + fpu_register const & src +); + +// to_exten +PRIVATE inline fpu_register FFPU make_extended( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 +); + +/* + Would be so much easier with full size floats :( + ... this is so vague. +*/ +// to_exten_no_normalize +PRIVATE inline void FFPU make_extended_no_normalize( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result +); + +// from_exten +PRIVATE inline void FFPU extract_extended(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +); + +// to_double +PRIVATE inline fpu_register FFPU make_double( + uae_u32 wrd1, uae_u32 wrd2 +); + +// from_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2 +); + +PRIVATE inline fpu_register FFPU make_packed( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 +); + +PRIVATE inline void FFPU extract_packed( + fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +); + +PRIVATE inline int FFPU get_fp_value( + uae_u32 opcode, uae_u16 extra, fpu_register & src +); + +PRIVATE inline int FFPU put_fp_value( + uae_u32 opcode, uae_u16 extra, fpu_register const & value +); + +PRIVATE inline int FFPU get_fp_ad( + uae_u32 opcode, uae_u32 * ad +); + +PRIVATE inline int FFPU fpp_cond( + int condition +); + +#endif /* FPU_IEEE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp new file mode 100644 index 00000000..1975aba8 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp @@ -0,0 +1,2110 @@ +/* + * fpu_mpfr.cpp - emulate 68881/68040 fpu with mpfr + * + * Copyright (c) 2012, 2013 Andreas Schwab + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" +#include +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#include "main.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" + +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#define SINGLE_PREC 24 +#define SINGLE_MIN_EXP -126 +#define SINGLE_MAX_EXP 127 +#define SINGLE_BIAS 127 +#define DOUBLE_PREC 53 +#define DOUBLE_MIN_EXP -1022 +#define DOUBLE_MAX_EXP 1023 +#define DOUBLE_BIAS 1023 +#define EXTENDED_PREC 64 +#define EXTENDED_MIN_EXP -16383 +#define EXTENDED_MAX_EXP 16383 +#define EXTENDED_BIAS 16383 + +fpu_t fpu; +// The constant ROM +// Constants 48 to 63 are mapped to index 16 to 31 +const int num_fpu_constants = 32; +static mpfr_t fpu_constant_rom[num_fpu_constants]; +#define FPU_CONSTANT_ONE fpu_constant_rom[18] +// Exceptions generated during execution in addition to the ones +// maintained by mpfr +static uae_u32 cur_exceptions; +static uaecptr cur_instruction_address; + +static void +set_format (int prec) +{ + // MPFR represents numbers as 0.m*2^e + switch (prec) + { + case SINGLE_PREC: + mpfr_set_emin (SINGLE_MIN_EXP + 1 - (SINGLE_PREC - 1)); + mpfr_set_emax (SINGLE_MAX_EXP + 1); + break; + case DOUBLE_PREC: + mpfr_set_emin (DOUBLE_MIN_EXP + 1 - (DOUBLE_PREC - 1)); + mpfr_set_emax (DOUBLE_MAX_EXP + 1); + break; + case EXTENDED_PREC: + mpfr_set_emin (EXTENDED_MIN_EXP + 1 - (EXTENDED_PREC - 1)); + mpfr_set_emax (EXTENDED_MAX_EXP + 1); + break; + } +} + +static mpfr_rnd_t +get_cur_rnd () +{ + switch (get_rounding_mode ()) + { + default: + case FPCR_ROUND_NEAR: + return MPFR_RNDN; + case FPCR_ROUND_ZERO: + return MPFR_RNDZ; + case FPCR_ROUND_MINF: + return MPFR_RNDD; + case FPCR_ROUND_PINF: + return MPFR_RNDU; + } +} + +static mpfr_prec_t +get_cur_prec () +{ + switch (get_rounding_precision ()) + { + default: + case FPCR_PRECISION_EXTENDED: + return EXTENDED_PREC; + case FPCR_PRECISION_SINGLE: + return SINGLE_PREC; + case FPCR_PRECISION_DOUBLE: + return DOUBLE_PREC; + } +} + +#define DEFAULT_NAN_BITS 0xffffffffffffffffULL + +static void +set_nan (fpu_register ®, uae_u64 nan_bits, int nan_sign) +{ + mpfr_set_nan (reg.f); + reg.nan_bits = nan_bits; + reg.nan_sign = nan_sign; +} + +static void +set_nan (fpu_register ®) +{ + set_nan (reg, DEFAULT_NAN_BITS, 0); +} + +static bool fpu_inited; + +void +fpu_init (bool integral_68040) +{ + fpu.is_integral = integral_68040; + + mpfr_set_default_prec (EXTENDED_PREC); + mpfr_set_default_rounding_mode (MPFR_RNDN); + set_format (EXTENDED_PREC); + + for (int i = 0; i < 8; i++) + mpfr_init (fpu.registers[i].f); + mpfr_init (fpu.result.f); + + // Initialize constant ROM + for (int i = 0; i < num_fpu_constants; i++) + mpfr_init (fpu_constant_rom[i]); + + // 0: pi + mpfr_const_pi (fpu_constant_rom[0], MPFR_RNDN); + // 11: log10 (2) + mpfr_set_ui (fpu_constant_rom[11], 2, MPFR_RNDN); + mpfr_log10 (fpu_constant_rom[11], fpu_constant_rom[11], MPFR_RNDZ); + // 12: e + mpfr_set_ui (fpu_constant_rom[12], 1, MPFR_RNDN); + mpfr_exp (fpu_constant_rom[12], fpu_constant_rom[12], MPFR_RNDZ); + // 13: log2 (e) + mpfr_log2 (fpu_constant_rom[13], fpu_constant_rom[12], MPFR_RNDU); + // 14: log10 (e) + mpfr_log10 (fpu_constant_rom[14], fpu_constant_rom[12], MPFR_RNDU); + // 15: 0 + mpfr_set_zero (fpu_constant_rom[15], 0); + // 48: ln (2) + mpfr_const_log2 (fpu_constant_rom[16], MPFR_RNDN); + // 49: ln (10) + mpfr_set_ui (fpu_constant_rom[17], 10, MPFR_RNDN); + mpfr_log (fpu_constant_rom[17], fpu_constant_rom[17], MPFR_RNDN); + // 50 to 63: powers of 10 + mpfr_set_ui (fpu_constant_rom[18], 1, MPFR_RNDN); + for (int i = 19; i < 32; i++) + { + mpfr_set_ui (fpu_constant_rom[i], 1L << (i - 19) , MPFR_RNDN); + mpfr_exp10 (fpu_constant_rom[i], fpu_constant_rom[i], MPFR_RNDN); + } + + fpu_inited = true; + + fpu_reset (); +} + +void +fpu_exit () +{ + if (!fpu_inited) return; + + for (int i = 0; i < 8; i++) + mpfr_clear (fpu.registers[i].f); + mpfr_clear (fpu.result.f); + for (int i = 0; i < num_fpu_constants; i++) + mpfr_clear (fpu_constant_rom[i]); +} + +void +fpu_reset () +{ + set_fpcr (0); + set_fpsr (0); + fpu.instruction_address = 0; + + for (int i = 0; i < 8; i++) + set_nan (fpu.registers[i]); +} + +fpu_register::operator long double () +{ + return mpfr_get_ld (f, MPFR_RNDN); +} + +fpu_register & +fpu_register::operator= (long double x) +{ + mpfr_set_ld (f, x, MPFR_RNDN); + nan_bits = DEFAULT_NAN_BITS; + nan_sign = 0; + return *this; +} + +static bool +get_fp_addr (uae_u32 opcode, uae_u32 *addr, bool write) +{ + uaecptr pc; + int mode; + int reg; + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) + { + case 0: + case 1: + return false; + case 2: + *addr = m68k_areg (regs, reg); + break; + case 3: + *addr = m68k_areg (regs, reg); + break; + case 4: + *addr = m68k_areg (regs, reg); + break; + case 5: + *addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); + break; + case 6: + *addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) + { + case 0: + *addr = (uae_s16) next_iword(); + break; + case 1: + *addr = next_ilong(); + break; + case 2: + if (write) + return false; + pc = m68k_getpc (); + *addr = pc + (uae_s16) next_iword(); + break; + case 3: + if (write) + return false; + pc = m68k_getpc (); + *addr = get_disp_ea_020 (pc, next_iword()); + break; + default: + return false; + } + } + return true; +} + +static void +set_from_single (fpu_register &value, uae_u32 data) +{ + int s = data >> 31; + int e = (data >> 23) & 0xff; + uae_u32 m = data & 0x7fffff; + + if (e == 0xff) + { + if (m != 0) + { + if (!(m & 0x400000)) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + set_nan (value, (uae_u64) (m | 0xc00000) << (32 + 8), s); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + if (e != 0) + // Add integer bit + m |= 0x800000; + else + e++; + // Remove bias + e -= SINGLE_BIAS; + mpfr_set_ui_2exp (value.f, m, e - (SINGLE_PREC - 1), MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, s, MPFR_RNDN); +} + +static void +set_from_double (fpu_register &value, uae_u32 words[2]) +{ + int s = words[0] >> 31; + int e = (words[0] >> 20) & 0x7ff; + uae_u32 m = words[0] & 0xfffff; + + if (e == 0x7ff) + { + if ((m | words[1]) != 0) + { + if (!(m & 0x80000)) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + set_nan (value, (((uae_u64) (m | 0x180000) << (32 + 11)) + | ((uae_u64) words[1] << 11)), s); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + if (e != 0) + // Add integer bit + m |= 0x100000; + else + e++; + // Remove bias + e -= DOUBLE_BIAS; + mpfr_set_uj_2exp (value.f, ((uintmax_t) m << 32) | words[1], + e - (DOUBLE_PREC - 1), MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, s, MPFR_RNDN); +} + +static void +set_from_extended (fpu_register &value, uae_u32 words[3], bool check_snan) +{ + int s = words[0] >> 31; + int e = (words[0] >> 16) & 0x7fff; + + if (e == 0x7fff) + { + if (((words[1] & 0x7fffffff) | words[2]) != 0) + { + if (check_snan) + { + if ((words[1] & 0x40000000) == 0) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + words[1] |= 0x40000000; + } + set_nan (value, ((uae_u64) words[1] << 32) | words[2], s); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + // Remove bias + e -= EXTENDED_BIAS; + mpfr_set_uj_2exp (value.f, ((uintmax_t) words[1] << 32) | words[2], + e - (EXTENDED_PREC - 1), MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, s, MPFR_RNDN); +} + +#define from_bcd(d) ((d) < 10 ? (d) : (d) - 10) + +static void +set_from_packed (fpu_register &value, uae_u32 words[3]) +{ + char str[32], *p = str; + int sm = words[0] >> 31; + int se = (words[0] >> 30) & 1; + int i; + + if (((words[0] >> 16) & 0x7fff) == 0x7fff) + { + if ((words[1] | words[2]) != 0) + { + if ((words[1] & 0x40000000) == 0) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + set_nan (value, ((uae_u64) (words[1] | 0x40000000) << 32) | words[2], + sm); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + if (sm) + *p++ = '-'; + *p++ = from_bcd (words[0] & 15) + '0'; + *p++ = '.'; + for (i = 0; i < 8; i++) + { + p[i] = from_bcd ((words[1] >> (28 - i * 4)) & 15) + '0'; + p[i + 8] = from_bcd ((words[2] >> (28 - i * 4)) & 15) + '0'; + } + p += 16; + *p++ = 'e'; + if (se) + *p++ = '-'; + *p++ = from_bcd ((words[0] >> 24) & 15) + '0'; + *p++ = from_bcd ((words[0] >> 20) & 15) + '0'; + *p++ = from_bcd ((words[0] >> 16) & 15) + '0'; + *p = 0; + mpfr_set_str (value.f, str, 10, MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, sm, MPFR_RNDN); +} + +static bool +get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register &value) +{ + int mode, reg, size; + uaecptr pc; + uae_u32 addr; + uae_u32 words[3]; + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + if ((extra & 0x4000) == 0) + { + mpfr_set (value.f, fpu.registers[(extra >> 10) & 7].f, MPFR_RNDN); + value.nan_bits = fpu.registers[(extra >> 10) & 7].nan_bits; + value.nan_sign = fpu.registers[(extra >> 10) & 7].nan_sign; + /* Check for SNaN. */ + if (mpfr_nan_p (value.f) && (value.nan_bits & (1ULL << 62)) == 0) + { + value.nan_bits |= 1ULL << 62; + cur_exceptions |= FPSR_EXCEPTION_SNAN; + } + return true; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + switch (mode) + { + case 0: + switch (size) + { + case 6: + mpfr_set_si (value.f, (uae_s8) m68k_dreg (regs, reg), MPFR_RNDN); + break; + case 4: + mpfr_set_si (value.f, (uae_s16) m68k_dreg (regs, reg), MPFR_RNDN); + break; + case 0: + mpfr_set_si (value.f, (uae_s32) m68k_dreg (regs, reg), MPFR_RNDN); + break; + case 1: + set_from_single (value, m68k_dreg (regs, reg)); + break; + default: + return false; + } + return true; + case 1: + return false; + case 2: + case 3: + addr = m68k_areg (regs, reg); + break; + case 4: + addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + addr = m68k_areg (regs, reg) + (uae_s16) next_iword (); + break; + case 6: + addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); + break; + case 7: + switch (reg) + { + case 0: + addr = (uae_s16) next_iword (); + break; + case 1: + addr = next_ilong (); + break; + case 2: + pc = m68k_getpc (); + addr = pc + (uae_s16) next_iword (); + break; + case 3: + pc = m68k_getpc (); + addr = get_disp_ea_020 (pc, next_iword ()); + break; + case 4: + addr = m68k_getpc (); + m68k_incpc (sz2[size]); + if (size == 6) // Immediate byte + addr++; + break; + default: + return false; + } + } + + switch (size) + { + case 0: + mpfr_set_si (value.f, (uae_s32) get_long (addr), MPFR_RNDN); + break; + case 1: + set_from_single (value, get_long (addr)); + break; + case 2: + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + words[2] = get_long (addr + 8); + set_from_extended (value, words, true); + break; + case 3: + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + words[2] = get_long (addr + 8); + set_from_packed (value, words); + break; + case 4: + mpfr_set_si (value.f, (uae_s16) get_word (addr), MPFR_RNDN); + break; + case 5: + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + set_from_double (value, words); + break; + case 6: + mpfr_set_si (value.f, (uae_s8) get_byte (addr), MPFR_RNDN); + break; + default: + return false; + } + + switch (mode) + { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + return true; +} + +static void +update_exceptions () +{ + uae_u32 exc, aexc; + + exc = cur_exceptions; + // Add any mpfr detected exceptions + if (mpfr_underflow_p ()) + exc |= FPSR_EXCEPTION_UNFL; + if (mpfr_overflow_p ()) + exc |= FPSR_EXCEPTION_OVFL; + if (mpfr_inexflag_p ()) + exc |= FPSR_EXCEPTION_INEX2; + set_exception_status (exc); + + aexc = get_accrued_exception (); + if (exc & (FPSR_EXCEPTION_SNAN|FPSR_EXCEPTION_OPERR)) + aexc |= FPSR_ACCR_IOP; + if (exc & FPSR_EXCEPTION_OVFL) + aexc |= FPSR_ACCR_OVFL; + if ((exc & (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) + == (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) + aexc |= FPSR_ACCR_UNFL; + if (exc & FPSR_EXCEPTION_DZ) + aexc |= FPSR_ACCR_DZ; + if (exc & (FPSR_EXCEPTION_INEX1|FPSR_EXCEPTION_INEX2|FPSR_EXCEPTION_OVFL)) + aexc |= FPSR_ACCR_INEX; + set_accrued_exception (aexc); + + if ((fpu.fpcr.exception_enable & exc) != 0) + { + fpu.instruction_address = cur_instruction_address; + // TODO: raise exceptions + // Problem: FPSP040 depends on proper FPU stack frames, it would suffer + // undefined behaviour with our dummy FSAVE implementation + } +} + +static void +set_fp_register (int reg, mpfr_t value, uae_u64 nan_bits, int nan_sign, + int t, mpfr_rnd_t rnd, bool do_flags) +{ + mpfr_subnormalize (value, t, rnd); + mpfr_set (fpu.registers[reg].f, value, rnd); + fpu.registers[reg].nan_bits = nan_bits; + fpu.registers[reg].nan_sign = nan_sign; + if (do_flags) + { + uae_u32 flags = 0; + + if (mpfr_zero_p (fpu.registers[reg].f)) + flags |= FPSR_CCB_ZERO; + if (mpfr_signbit (fpu.registers[reg].f)) + flags |= FPSR_CCB_NEGATIVE; + if (mpfr_nan_p (fpu.registers[reg].f)) + flags |= FPSR_CCB_NAN; + if (mpfr_inf_p (fpu.registers[reg].f)) + flags |= FPSR_CCB_INFINITY; + set_fpccr (flags); + } +} + +static void +set_fp_register (int reg, mpfr_t value, int t, mpfr_rnd_t rnd, bool do_flags) +{ + set_fp_register (reg, value, DEFAULT_NAN_BITS, 0, t, rnd, do_flags); +} + +static void +set_fp_register (int reg, fpu_register &value, int t, mpfr_rnd_t rnd, + bool do_flags) +{ + set_fp_register (reg, value.f, value.nan_bits, value.nan_sign, t, rnd, + do_flags); +} + +static uae_u32 +extract_to_single (fpu_register &value) +{ + uae_u32 word; + int t; + mpfr_rnd_t rnd = get_cur_rnd (); + MPFR_DECL_INIT (single, SINGLE_PREC); + + set_format (SINGLE_PREC); + // Round to single + t = mpfr_set (single, value.f, rnd); + t = mpfr_check_range (single, t, rnd); + mpfr_subnormalize (single, t, rnd); + set_format (EXTENDED_PREC); + + if (mpfr_inf_p (single)) + word = 0x7f800000; + else if (mpfr_nan_p (single)) + { + if ((value.nan_bits & (1ULL << 62)) == 0) + { + value.nan_bits |= 1ULL << 62; + cur_exceptions |= FPSR_EXCEPTION_SNAN; + } + word = 0x7f800000 | ((value.nan_bits >> (32 + 8)) & 0x7fffff); + if (value.nan_sign) + word |= 0x80000000; + } + else if (mpfr_zero_p (single)) + word = 0; + else + { + int e; + mpz_t f; + mpz_init (f); + word = 0; + // Get exponent and mantissa + e = mpfr_get_z_2exp (f, single); + // Move binary point + e += SINGLE_PREC - 1; + // Add bias + e += SINGLE_BIAS; + if (e <= 0) + { + // Denormalized number + mpz_tdiv_q_2exp (f, f, -e + 1); + e = 0; + } + mpz_export (&word, 0, 1, 4, 0, 0, f); + // Remove integer bit + word &= 0x7fffff; + word |= e << 23; + mpz_clear (f); + } + if (mpfr_signbit (single)) + word |= 0x80000000; + return word; +} + +static void +extract_to_double (fpu_register &value, uint32_t *words) +{ + int t; + mpfr_rnd_t rnd = get_cur_rnd (); + MPFR_DECL_INIT (dbl, DOUBLE_PREC); + + set_format (DOUBLE_PREC); + // Round to double + t = mpfr_set (dbl, value.f, rnd); + t = mpfr_check_range (dbl, t, rnd); + mpfr_subnormalize (dbl, t, rnd); + set_format (EXTENDED_PREC); + + if (mpfr_inf_p (dbl)) + { + words[0] = 0x7ff00000; + words[1] = 0; + } + else if (mpfr_nan_p (dbl)) + { + if ((value.nan_bits & (1ULL << 62)) == 0) + { + value.nan_bits |= 1ULL << 62; + cur_exceptions |= FPSR_EXCEPTION_SNAN; + } + words[0] = 0x7ff00000 | ((value.nan_bits >> (32 + 11)) & 0xfffff); + words[1] = value.nan_bits >> 11; + if (value.nan_sign) + words[0] |= 0x80000000; + } + else if (mpfr_zero_p (dbl)) + { + words[0] = 0; + words[1] = 0; + } + else + { + int e, off = 0; + mpz_t f; + mpz_init (f); + words[0] = words[1] = 0; + // Get exponent and mantissa + e = mpfr_get_z_2exp (f, dbl); + // Move binary point + e += DOUBLE_PREC - 1; + // Add bias + e += DOUBLE_BIAS; + if (e <= 0) + { + // Denormalized number + mpz_tdiv_q_2exp (f, f, -e + 1); + if (e <= -20) + // No more than 32 bits left + off = 1; + e = 0; + } + mpz_export (&words[off], 0, 1, 4, 0, 0, f); + // Remove integer bit + words[0] &= 0xfffff; + words[0] |= e << 20; + mpz_clear (f); + } + if (mpfr_signbit (dbl)) + words[0] |= 0x80000000; +} + +static void +extract_to_extended (fpu_register &value, uint32_t *words) +{ + if (mpfr_inf_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = 0; + words[2] = 0; + } + else if (mpfr_nan_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = value.nan_bits >> 32; + words[2] = value.nan_bits; + if (value.nan_sign) + words[0] |= 0x80000000; + } + else if (mpfr_zero_p (value.f)) + { + words[0] = 0; + words[1] = 0; + words[2] = 0; + } + else + { + int e, off = 0; + mpz_t f; + + mpz_init (f); + words[0] = words[1] = words[2] = 0; + // Get exponent and mantissa + e = mpfr_get_z_2exp (f, value.f); + // Move binary point + e += EXTENDED_PREC - 1; + // Add bias + e += EXTENDED_BIAS; + if (e < 0) + { + // Denormalized number + mpz_tdiv_q_2exp (f, f, -e); + if (e <= -32) + // No more than 32 bits left + off = 1; + e = 0; + } + mpz_export (&words[1 + off], 0, 1, 4, 0, 0, f); + words[0] = e << 16; + mpz_clear (f); + } + if (mpfr_signbit (value.f)) + words[0] |= 0x80000000; +} + +static void +extract_to_packed (fpu_register &value, int k, uae_u32 *words) +{ + if (mpfr_inf_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = 0; + words[2] = 0; + } + else if (mpfr_nan_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = value.nan_bits >> 32; + words[2] = value.nan_bits; + if (value.nan_sign) + words[0] |= 0x80000000; + } + else if (mpfr_zero_p (value.f)) + { + words[0] = 0; + words[1] = 0; + words[2] = 0; + } + else + { + char str[100], *p = str; + mpfr_exp_t e; + mpfr_rnd_t rnd = get_cur_rnd (); + + words[0] = words[1] = words[2] = 0; + if (k >= 64) + k -= 128; + else if (k >= 18) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + if (k <= 0) + { + MPFR_DECL_INIT (temp, 16); + + mpfr_log10 (temp, value.f, rnd); + k = mpfr_get_si (temp, MPFR_RNDZ) - k + 1; + } + if (k <= 0) + k = 1; + else if (k >= 18) + k = 17; + mpfr_get_str (str, &e, 10, k, value.f, rnd); + e--; + if (*p == '-') + p++; + // Pad to 17 digits + while (k < 17) + p[k++] = '0'; + if (e < 0) + { + words[0] |= 0x40000000; + e = -e; + } + words[0] |= (e % 10) << 16; + e /= 10; + words[0] |= (e % 10) << 20; + e /= 10; + words[0] |= (e % 10) << 24; + e /= 10; + if (e) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + words[0] |= e << 12; + words[0] |= *p++ & 15; + for (k = 0; k < 8; k++) + words[1] = (words[1] << 4) | (*p++ & 15); + for (k = 0; k < 8; k++) + words[2] = (words[2] << 4) | (*p++ & 15); + + } + if (mpfr_signbit (value.f)) + words[0] |= 0x80000000; +} + +static long +extract_to_integer (mpfr_t value, long min, long max) +{ + long result; + mpfr_rnd_t rnd = get_cur_rnd (); + + if (mpfr_fits_slong_p (value, rnd)) + { + result = mpfr_get_si (value, rnd); + if (result > max) + { + result = max; + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (result < min) + { + result = min; + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + } + else + { + if (!mpfr_signbit (value)) + result = max; + else + result = min; + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + return result; +} + +static bool +fpuop_fmove_memory (uae_u32 opcode, uae_u32 extra) +{ + int mode, reg, size; + uaecptr pc; + uae_u32 addr; + uae_u32 words[3]; + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + mpfr_clear_flags (); + cur_exceptions = 0; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + fpu_register &value = fpu.registers[(extra >> 7) & 7]; + + switch (mode) + { + case 0: + switch (size) + { + case 0: + m68k_dreg (regs, reg) = extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff); + break; + case 1: + m68k_dreg (regs, reg) = extract_to_single (value); + break; + case 4: + m68k_dreg (regs, reg) &= ~0xffff; + m68k_dreg (regs, reg) |= extract_to_integer (value.f, -32768, 32767) & 0xffff; + break; + case 6: + m68k_dreg (regs, reg) &= ~0xff; + m68k_dreg (regs, reg) |= extract_to_integer (value.f, -128, 127) & 0xff; + break; + default: + return false; + } + update_exceptions (); + return true; + case 1: + return false; + case 2: + addr = m68k_areg (regs, reg); + break; + case 3: + addr = m68k_areg (regs, reg); + break; + case 4: + addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); + break; + case 6: + addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) + { + case 0: + addr = (uae_s16) next_iword(); + break; + case 1: + addr = next_ilong(); + break; + case 2: + pc = m68k_getpc (); + addr = pc + (uae_s16) next_iword(); + break; + case 3: + pc = m68k_getpc (); + addr = get_disp_ea_020 (pc, next_iword ()); + break; + case 4: + addr = m68k_getpc (); + m68k_incpc (sz2[size]); + break; + default: + return false; + } + } + + switch (size) + { + case 0: + put_long (addr, extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff)); + break; + case 1: + put_long (addr, extract_to_single (value)); + break; + case 2: + extract_to_extended (value, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + break; + case 3: + extract_to_packed (value, extra & 0x7f, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + break; + case 4: + put_word (addr, extract_to_integer (value.f, -32768, 32767)); + break; + case 5: + extract_to_double (value, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + break; + case 6: + put_byte (addr, extract_to_integer (value.f, -128, 127)); + break; + case 7: + extract_to_packed (value, m68k_dreg (regs, (extra >> 4) & 7) & 0x7f, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + break; + } + + switch (mode) + { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + update_exceptions (); + return true; +} + +static bool +fpuop_fmovem_control (uae_u32 opcode, uae_u32 extra) +{ + int list, mode, reg; + uae_u32 addr; + + list = (extra >> 10) & 7; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + + if (list == 0) + return false; + + if (extra & 0x2000) + { + // FMOVEM to + if (mode == 0) + { + switch (list) + { + case 1: + m68k_dreg (regs, reg) = fpu.instruction_address; + break; + case 2: + m68k_dreg (regs, reg) = get_fpsr (); + break; + case 4: + m68k_dreg (regs, reg) = get_fpcr (); + break; + default: + return false; + } + } + else if (mode == 1) + { + if (list != 1) + return false; + m68k_areg (regs, reg) = fpu.instruction_address; + } + else + { + int nwords; + + if (!get_fp_addr (opcode, &addr, true)) + return false; + nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); + if (mode == 4) + addr -= nwords * 4; + if (list & 4) + { + put_long (addr, get_fpcr ()); + addr += 4; + } + if (list & 2) + { + put_long (addr, get_fpsr ()); + addr += 4; + } + if (list & 1) + { + put_long (addr, fpu.instruction_address); + addr += 4; + } + if (mode == 4) + m68k_areg (regs, reg) = addr - nwords * 4; + else if (mode == 3) + m68k_areg (regs, reg) = addr; + } + } + else + { + // FMOVEM from + + if (mode == 0) + { + switch (list) + { + case 1: + fpu.instruction_address = m68k_dreg (regs, reg); + break; + case 2: + set_fpsr (m68k_dreg (regs, reg)); + break; + case 4: + set_fpcr (m68k_dreg (regs, reg)); + break; + default: + return false; + } + } + else if (mode == 1) + { + if (list != 1) + return false; + fpu.instruction_address = m68k_areg (regs, reg); + } + else if ((opcode & 077) == 074) + { + switch (list) + { + case 1: + fpu.instruction_address = next_ilong (); + break; + case 2: + set_fpsr (next_ilong ()); + break; + case 4: + set_fpcr (next_ilong ()); + break; + default: + return false; + } + } + else + { + int nwords; + + if (!get_fp_addr (opcode, &addr, false)) + return false; + nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); + if (mode == 4) + addr -= nwords * 4; + if (list & 4) + { + set_fpcr (get_long (addr)); + addr += 4; + } + if (list & 2) + { + set_fpsr (get_long (addr)); + addr += 4; + } + if (list & 1) + { + fpu.instruction_address = get_long (addr); + addr += 4; + } + if (mode == 4) + m68k_areg (regs, reg) = addr - nwords * 4; + else if (mode == 3) + m68k_areg (regs, reg) = addr; + } + } + + return true; +} + +static bool +fpuop_fmovem_register (uae_u32 opcode, uae_u32 extra) +{ + uae_u32 addr; + uae_u32 words[3]; + int list; + int i; + + set_format (EXTENDED_PREC); + if (!get_fp_addr (opcode, &addr, extra & 0x2000)) + return false; + if (extra & 0x800) + list = m68k_dreg (regs, (extra >> 4) & 7) & 0xff; + else + list = extra & 0xff; + + if (extra & 0x2000) + { + // FMOVEM to memory + + switch (opcode & 070) + { + case 030: + return false; + case 040: + if (extra & 0x1000) + return false; + for (i = 7; i >= 0; i--) + if (list & (1 << i)) + { + extract_to_extended (fpu.registers[i], words); + addr -= 12; + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + } + m68k_areg (regs, opcode & 7) = addr; + break; + default: + if ((extra & 0x1000) == 0) + return false; + for (i = 0; i < 8; i++) + if (list & (0x80 >> i)) + { + extract_to_extended (fpu.registers[i], words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + addr += 12; + } + if ((opcode & 070) == 030) + m68k_areg (regs, opcode & 7) = addr; + break; + } + } + else + { + // FMOVEM from memory + + if ((opcode & 070) == 040) + return false; + + if ((extra & 0x1000) == 0) + return false; + for (i = 0; i < 8; i++) + if (list & (0x80 >> i)) + { + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + words[2] = get_long (addr + 8); + addr += 12; + set_from_extended (fpu.registers[i], words, false); + } + if ((opcode & 070) == 030) + m68k_areg (regs, opcode & 7) = addr; + } + return true; +} + +static int +do_getexp (mpfr_t value, mpfr_rnd_t rnd) +{ + int t = 0; + + if (mpfr_inf_p (value)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) + t = mpfr_set_si (value, mpfr_get_exp (value) - 1, rnd); + return t; +} + +static int +do_getman (mpfr_t value) +{ + if (mpfr_inf_p (value)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) + mpfr_set_exp (value, 1); + return 0; +} + +static int +do_scale (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) +{ + long scale; + int t = 0; + + if (mpfr_nan_p (value)) + ; + else if (mpfr_inf_p (value)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_fits_slong_p (value, rnd)) + { + scale = mpfr_get_si (value, MPFR_RNDZ); + mpfr_clear_inexflag (); + t = mpfr_mul_2si (value, reg, scale, rnd); + } + else + mpfr_set_inf (value, -mpfr_signbit (value)); + return t; +} + +static int +do_remainder (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) +{ + long quo; + int t = 0; + + if (mpfr_nan_p (value) || mpfr_nan_p (reg)) + ; + else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_remquo (value, &quo, reg, value, rnd); + if (quo < 0) + quo = (-quo & 0x7f) | 0x80; + else + quo &= 0x7f; + fpu.fpsr.quotient = quo << 16; + return t; +} + +// Unfortunately, mpfr_fmod does not return the quotient bits, so we +// have to reimplement it here +static int +mpfr_rem1 (mpfr_t rem, int *quo, mpfr_t x, mpfr_t y, mpfr_rnd_t rnd) +{ + mpfr_exp_t ex, ey; + int inex, sign, signx = mpfr_signbit (x); + mpz_t mx, my, r; + + mpz_init (mx); + mpz_init (my); + mpz_init (r); + + ex = mpfr_get_z_2exp (mx, x); /* x = mx*2^ex */ + ey = mpfr_get_z_2exp (my, y); /* y = my*2^ey */ + + /* to get rid of sign problems, we compute it separately: + quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y) + quo(-x,y) = -quo(x,y), rem(-x,y) = -rem(x,y) + thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */ + sign = (signx != mpfr_signbit (y)); + mpz_abs (mx, mx); + mpz_abs (my, my); + + /* divide my by 2^k if possible to make operations mod my easier */ + { + unsigned long k = mpz_scan1 (my, 0); + ey += k; + mpz_fdiv_q_2exp (my, my, k); + } + + if (ex <= ey) + { + /* q = x/y = mx/(my*2^(ey-ex)) */ + mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */ + /* 0 <= |r| <= |my|, r has the same sign as mx */ + mpz_tdiv_qr (mx, r, mx, my); + /* mx is the quotient */ + mpz_tdiv_r_2exp (mx, mx, 7); + *quo = mpz_get_si (mx); + } + else /* ex > ey */ + { + /* to get the low 7 more bits of the quotient, we first compute + R = X mod Y*2^7, where X and Y are defined below. Then the + low 7 of the quotient are floor(R/Y). */ + mpz_mul_2exp (my, my, 7); /* 2^7*Y */ + + mpz_set_ui (r, 2); + mpz_powm_ui (r, r, ex - ey, my); /* 2^(ex-ey) mod my */ + mpz_mul (r, r, mx); + mpz_mod (r, r, my); + + /* now 0 <= r < 2^7*Y */ + mpz_fdiv_q_2exp (my, my, 7); /* back to Y */ + mpz_tdiv_qr (mx, r, r, my); + /* oldr = mx*my + newr */ + *quo = mpz_get_si (mx); + + /* now 0 <= |r| < |my| */ + } + + if (mpz_cmp_ui (r, 0) == 0) + { + inex = mpfr_set_ui (rem, 0, MPFR_RNDN); + /* take into account sign of x */ + if (signx) + mpfr_neg (rem, rem, MPFR_RNDN); + } + else + { + /* take into account sign of x */ + if (signx) + mpz_neg (r, r); + inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd); + } + + if (sign) + *quo |= 0x80; + + mpz_clear (mx); + mpz_clear (my); + mpz_clear (r); + + return inex; +} + +static int +do_fmod (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) +{ + int t = 0; + + if (mpfr_nan_p (value) || mpfr_nan_p (reg)) + mpfr_set_nan (value); + else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_zero_p (reg) || mpfr_inf_p (value)) + { + fpu.fpsr.quotient = 0; + t = mpfr_set (value, reg, rnd); + } + else + { + int quo; + + t = mpfr_rem1 (value, &quo, reg, value, rnd); + fpu.fpsr.quotient = quo << 16; + } + return t; +} + +static void +do_fcmp (mpfr_t source, mpfr_t dest) +{ + uae_u32 flags = 0; + + if (mpfr_nan_p (source) || mpfr_nan_p (dest)) + flags |= FPSR_CCB_NAN; + else + { + int cmp = mpfr_cmp (dest, source); + if (cmp < 0) + flags |= FPSR_CCB_NEGATIVE; + else if (cmp == 0) + { + flags |= FPSR_CCB_ZERO; + if ((mpfr_zero_p (dest) || mpfr_inf_p (dest)) && mpfr_signbit (dest)) + flags |= FPSR_CCB_NEGATIVE; + } + } + set_fpccr (flags); +} + +static void +do_ftst (mpfr_t value) +{ + uae_u32 flags = 0; + + if (mpfr_signbit (value)) + flags |= FPSR_CCB_NEGATIVE; + if (mpfr_nan_p (value)) + flags |= FPSR_CCB_NAN; + else if (mpfr_zero_p (value)) + flags |= FPSR_CCB_ZERO; + else if (mpfr_inf_p (value)) + flags |= FPSR_CCB_INFINITY; + set_fpccr (flags); +} + +static bool +fpuop_general (uae_u32 opcode, uae_u32 extra) +{ + mpfr_prec_t prec = get_cur_prec (); + mpfr_rnd_t rnd = get_cur_rnd (); + int reg = (extra >> 7) & 7; + int t = 0; + fpu_register value; + bool ret; + + mpfr_init2 (value.f, prec); + value.nan_bits = DEFAULT_NAN_BITS; + value.nan_sign = 0; + + mpfr_clear_flags (); + set_format (prec); + cur_exceptions = 0; + cur_instruction_address = m68k_getpc () - 4; + if ((extra & 0xfc00) == 0x5c00) + { + // FMOVECR + int rom_index = extra & 0x7f; + if (rom_index == 0 || (rom_index >= 11 && rom_index <= 15)) + t = mpfr_set (value.f, fpu_constant_rom[rom_index], rnd); + else if (rom_index >= 48 && rom_index <= 63) + t = mpfr_set (value.f, fpu_constant_rom[rom_index - 32], rnd); + else + mpfr_set_zero (value.f, 0); + set_fp_register (reg, value, t, rnd, true); + } + else if (extra & 0x40) + { + static const char valid[64] = + { + 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 1, 0, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 0 + }; + + if (extra & 4) + // FD... + prec = DOUBLE_PREC; + else + // FS... + prec = SINGLE_PREC; + set_format (prec); + MPFR_DECL_INIT (value2, prec); + + if (!fpu.is_integral) + { + ret = false; + goto out; + } + if (!valid[extra & 0x3b]) + { + ret = false; + goto out; + } + if (!get_fp_value (opcode, extra, value)) + { + ret = false; + goto out; + } + + switch (extra & 0x3f) + { + case 0: // FSMOVE + case 4: // FDMOVE + mpfr_set (value2, value.f, rnd); + break; + case 1: // FSSQRT + case 5: // FDSQRT + if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sqrt (value2, value.f, rnd); + break; + case 24: // FSABS + case 28: // FDABS + t = mpfr_abs (value2, value.f, rnd); + break; + case 26: // FSNEG + case 30: // FDNEG + t = mpfr_neg (value2, value.f, rnd); + break; + case 32: // FSDIV + case 36: // FDDIV + if (mpfr_zero_p (value.f)) + { + if (mpfr_regular_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_zero_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); + break; + case 34: // FSADD + case 38: // FDADD + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_add (value2, fpu.registers[reg].f, value.f, rnd); + break; + case 35: // FSMUL + case 39: // FDMUL + if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); + break; + case 40: // FSSUB + case 44: // FDSUB + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sub (value2, fpu.registers[reg].f, value.f, rnd); + break; + } + set_fp_register (reg, value2, t, rnd, true); + } + else if ((extra & 0x30) == 0x30) + { + if ((extra & 15) > 10 || (extra & 15) == 9) + { + ret = false; + goto out; + } + if (!get_fp_value (opcode, extra, value)) + { + ret = false; + goto out; + } + + if ((extra & 15) < 8) + { + // FSINCOS + int reg2 = extra & 7; + MPFR_DECL_INIT (value2, prec); + + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sin_cos (value.f, value2, value.f, rnd); + if (reg2 != reg) + set_fp_register (reg2, value2, t >> 2, rnd, false); + set_fp_register (reg, value, t & 3, rnd, true); + } + else if ((extra & 15) == 8) + // FCMP + do_fcmp (value.f, fpu.registers[reg].f); + else + // FTST + do_ftst (value.f); + } + else + { + static const char valid[64] = + { + 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1 + }; + if (!valid[extra & 0x3f]) + { + ret = false; + goto out; + } + if (!get_fp_value (opcode, extra, value)) + { + ret = false; + goto out; + } + + switch (extra & 0x3f) + { + case 0: // FMOVE + break; + case 1: // FINT + t = mpfr_rint (value.f, value.f, rnd); + break; + case 2: // FSINH + t = mpfr_sinh (value.f, value.f, rnd); + break; + case 3: // FINTRZ + t = mpfr_rint (value.f, value.f, MPFR_RNDZ); + break; + case 4: // FSQRT + if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sqrt (value.f, value.f, rnd); + break; + case 6: // FLOGNP1 + if (!mpfr_nan_p (value.f)) + { + int cmp = mpfr_cmp_si (value.f, -1); + if (cmp == 0) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (cmp < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + t = mpfr_log1p (value.f, value.f, rnd); + break; + case 8: // FETOXM1 + t = mpfr_expm1 (value.f, value.f, rnd); + break; + case 9: // FTANH + t = mpfr_tanh (value.f, value.f, rnd); + break; + case 10: // FATAN + t = mpfr_atan (value.f, value.f, rnd); + break; + case 12: // FASIN + if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_asin (value.f, value.f, rnd); + break; + case 13: // FATANH + if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_atanh (value.f, value.f, rnd); + break; + case 14: // FSIN + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sin (value.f, value.f, rnd); + break; + case 15: // FTAN + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_tan (value.f, value.f, rnd); + break; + case 16: // FETOX + t = mpfr_exp (value.f, value.f, rnd); + break; + case 17: // FTWOTOX + t = mpfr_ui_pow (value.f, 2, value.f, rnd); + break; + case 18: // FTENTOX + t = mpfr_ui_pow (value.f, 10, value.f, rnd); + break; + case 20: // FLOGN + if (mpfr_zero_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_log (value.f, value.f, rnd); + break; + case 21: // FLOG10 + if (mpfr_zero_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_log10 (value.f, value.f, rnd); + break; + case 22: // FLOG2 + if (mpfr_zero_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_log2 (value.f, value.f, rnd); + break; + case 24: // FABS + t = mpfr_abs (value.f, value.f, rnd); + value.nan_sign = 0; + break; + case 25: // FCOSH + t = mpfr_cosh (value.f, value.f, rnd); + break; + case 26: // FNEG + t = mpfr_neg (value.f, value.f, rnd); + value.nan_sign = !value.nan_sign; + break; + case 28: // FACOS + if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_acos (value.f, value.f, rnd); + break; + case 29: // FCOS + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_cos (value.f, value.f, rnd); + break; + case 30: // FGETEXP + t = do_getexp (value.f, rnd); + break; + case 31: // FGETMAN + t = do_getman (value.f); + break; + case 32: // FDIV + if (mpfr_zero_p (value.f)) + { + if (mpfr_regular_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_zero_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_div (value.f, fpu.registers[reg].f, value.f, rnd); + break; + case 33: // FMOD + t = do_fmod (value.f, fpu.registers[reg].f, rnd); + break; + case 34: // FADD + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_add (value.f, fpu.registers[reg].f, value.f, rnd); + break; + case 35: // FMUL + if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_mul (value.f, fpu.registers[reg].f, value.f, rnd); + break; + case 36: // FSGLDIV + { + MPFR_DECL_INIT (value2, SINGLE_PREC); + + set_format (SINGLE_PREC); + if (mpfr_zero_p (value.f)) + { + if (mpfr_regular_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_zero_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); + mpfr_set (value.f, value2, rnd); + } + break; + case 37: // FREM + t = do_remainder (value.f, fpu.registers[reg].f, rnd); + break; + case 38: // FSCALE + t = do_scale (value.f, fpu.registers[reg].f, rnd); + break; + case 39: // FSGLMUL + { + MPFR_DECL_INIT (value2, SINGLE_PREC); + + set_format (SINGLE_PREC); + if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); + mpfr_set (value.f, value2, rnd); + } + break; + case 40: // FSUB + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sub (value.f, fpu.registers[reg].f, value.f, rnd); + break; + } + set_fp_register (reg, value, t, rnd, true); + } + update_exceptions (); + ret = true; + out: + mpfr_clear (value.f); + return ret; +} + +void +fpuop_arithmetic (uae_u32 opcode, uae_u32 extra) +{ + bool valid; + + switch ((extra >> 13) & 7) + { + case 3: + valid = fpuop_fmove_memory (opcode, extra); + break; + case 4: + case 5: + valid = fpuop_fmovem_control (opcode, extra); + break; + case 6: + case 7: + valid = fpuop_fmovem_register (opcode, extra); + break; + case 0: + case 2: + valid = fpuop_general (opcode, extra); + break; + default: + valid = false; + break; + } + + if (!valid) + { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } +} + +static bool +check_fp_cond (uae_u32 pred) +{ + uae_u32 fpcc = get_fpccr (); + + if ((pred & 16) != 0 && (fpcc & FPSR_CCB_NAN) != 0) + { + // IEEE non-aware test + set_exception_status (get_exception_status () | FPSR_EXCEPTION_BSUN); + set_accrued_exception (get_accrued_exception () | FPSR_ACCR_IOP); + } + + switch (pred & 15) + { + case 0: // F / SF + return false; + case 1: // EQ /SEQ + return (fpcc & FPSR_CCB_ZERO) != 0; + case 2: // OGT / GT + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) == 0; + case 3: // OGE / GE + return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NAN | FPSR_CCB_NEGATIVE)) == 0; + case 4: // OLT / LT + return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; + case 5: // OLE / LE + return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN)) == FPSR_CCB_NEGATIVE; + case 6: // OGL / GL + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) == 0; + case 7: // OR / GLE + return (fpcc & FPSR_CCB_NAN) == 0; + case 8: // UN / NGLE + return (fpcc & FPSR_CCB_NAN) != 0; + case 9: // UEQ / NGL + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) != 0; + case 10: // UGT / NLE + return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == 0; + case 11: // UGE / NLT + return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) != FPSR_CCB_NEGATIVE; + case 12: // ULT / NGE + return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; + case 13: // ULE / NGT + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) != 0; + case 14: // NE / SNE + return (fpcc & FPSR_CCB_ZERO) == 0; + case 15: // T / ST + return true; + default: + return false; + } +} + +void +fpuop_bcc (uae_u32 opcode, uaecptr pc, uae_u32 disp) +{ + if (check_fp_cond (opcode)) + { + if (!(opcode & (1 << 6))) + disp = (uae_s16) disp; + m68k_setpc (pc + disp); + } +} + +void +fpuop_scc (uae_u32 opcode, uae_u32 extra) +{ + uae_u32 addr; + int value = check_fp_cond (extra) ? 0xff : 0; + if ((opcode & 070) == 0) + { + int reg = opcode & 7; + m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xff) | value; + } + else if (!get_fp_addr (opcode, &addr, true)) + { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else + { + switch (opcode & 070) + { + case 030: + m68k_areg (regs, opcode & 7) += (opcode & 7) == 7 ? 2 : 1; + break; + case 040: + addr -= (opcode & 7) == 7 ? 2 : 1; + m68k_areg (regs, opcode & 7) = addr; + } + put_byte (addr, value); + } +} + +void +fpuop_dbcc (uae_u32 opcode, uae_u32 extra) +{ + uaecptr pc = m68k_getpc (); + uae_s16 disp = next_iword (); + + if (!check_fp_cond (extra)) + { + int reg = opcode & 7; + uae_u16 cnt = (m68k_dreg (regs, reg) & 0xffff) - 1; + m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xffff) | cnt; + if (cnt != 0xffff) + m68k_setpc (pc + disp); + } +} + +void +fpuop_trapcc (uae_u32, uaecptr oldpc, uae_u32 extra) +{ + if (check_fp_cond (extra)) + Exception (7, oldpc - 2); +} + +void +fpuop_save (uae_u32 opcode) +{ + uae_u32 addr; + + if ((opcode & 070) == 030 + || !get_fp_addr (opcode, &addr, true)) + { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (fpu.is_integral) + { + // 4 byte 68040 IDLE frame + // FIXME: generate proper FPU stack frames that does not result + // in undefined behaviour from FPSP040 + if ((opcode & 070) == 040) + { + addr -= 4; + m68k_areg (regs, opcode & 7) = addr; + } + put_long (addr, 0x41000000); + } + else + { + // 28 byte 68881 IDLE frame + if ((opcode & 070) == 040) + { + addr -= 28; + m68k_areg (regs, opcode & 7) = addr; + } + put_long (addr, 0x1f180000); + for (int i = 0; i < 6; i++) + { + addr += 4; + put_long (addr, 0); + } + } +} + +void +fpuop_restore (uae_u32 opcode) +{ + uae_u32 addr; + uae_u32 format; + + if ((opcode & 070) == 040 + || !get_fp_addr (opcode, &addr, false)) + { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + format = get_long (addr); + addr += 4; + if ((format & 0xff000000) == 0) + // NULL frame + fpu_reset (); + else + addr += (format & 0xff0000) >> 16; + if ((opcode & 070) == 030) + m68k_areg (regs, opcode & 7) = addr; +} + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp new file mode 100644 index 00000000..23efd8ef --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp @@ -0,0 +1,2553 @@ +/* + * fpu/fpu_uae.cpp - the old UAE FPU + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * UAE - The Un*x Amiga Emulator + * + * MC68881 emulation + * + * Copyright 1996 Herman ten Brugge + * + * + * Following fixes by Lauri Pesonen, July 1999: + * + * FMOVEM list handling: + * The lookup tables did not work correctly, rewritten. + * FINT: + * (int) cast does not work, fixed. + * Further, now honors the FPU fpcr rounding modes. + * FINTRZ: + * (int) cast cannot be used, fixed. + * FGETEXP: + * Input argument value 0 returned erroneous value. + * FMOD: + * (int) cast cannot be used. Replaced by proper rounding. + * Quotient byte handling was missing. + * FREM: + * (int) cast cannot be used. Replaced by proper rounding. + * Quotient byte handling was missing. + * FSCALE: + * Input argument value 0 was not handled correctly. + * FMOVEM Control Registers to/from address FPU registers An: + * A bug caused the code never been called. + * FMOVEM Control Registers pre-decrement: + * Moving of control regs from memory to FPP was not handled properly, + * if not all of the three FPU registers were moved. + * Condition code "Not Greater Than or Equal": + * Returned erroneous value. + * FSINCOS: + * Cosine must be loaded first if same register. + * FMOVECR: + * Status register was not updated (yes, this affects it). + * FMOVE -> reg: + * Status register was not updated (yes, this affects it). + * FMOVE reg -> reg: + * Status register was not updated. + * FDBcc: + * The loop termination condition was wrong. + * Possible leak from int16 to int32 fixed. + * get_fp_value: + * Immediate addressing mode && Operation Length == Byte -> + * Use the low-order byte of the extension word. + * Now FPU fpcr high 16 bits are always read as zeroes, no matter what was + * written to them. + * + * Other: + * - Optimized single/double/extended to/from conversion functions. + * Huge speed boost, but not (necessarily) portable to other systems. + * Enabled/disabled by #define FPU_HAVE_IEEE_DOUBLE 1 + * - Optimized versions of FSCALE, FGETEXP, FGETMAN + * - Conversion routines now handle NaN and infinity better. + * - Some constants precalculated. Not all compilers can optimize the + * expressions previously used. + * + * TODO: + * - Floating point exceptions. + * - More Infinity/NaN/overflow/underflow checking. + * - FPU instruction_address (only needed when exceptions are implemented) + * - Should be written in assembly to support long doubles. + * - Precision rounding single/double + */ + + +#include "sysdeps.h" +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#include "main.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" +#include "fpu/fpu_uae.h" + +#ifdef HAVE_NEW_HEADERS +#define _GLIBCPP_USE_C99 1 +# include +# include +using namespace __gnu_cxx; +#undef _GLIBCPP_USE_C99 +#else +# include +# include +#endif + +/* Global FPU context */ +fpu_t fpu; + +/* -------------------------------------------------------------------------- */ +/* --- Native Support --- */ +/* -------------------------------------------------------------------------- */ + +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#include "fpu/flags.cpp" +#include "fpu/exceptions.cpp" + +/* -------------------------------------------------------------------------- */ +/* --- Scopes Definition --- */ +/* -------------------------------------------------------------------------- */ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Debugging --- */ +/* -------------------------------------------------------------------------- */ + +PUBLIC void FFPU fpu_dump_registers(void) +{ + for (int i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, fpu_get_register(i)); + if ((i & 3) == 3) + printf ("\n"); + } +} + +PUBLIC void FFPU fpu_dump_flags(void) +{ + printf ("N=%d Z=%d I=%d NAN=%d\n", + (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, + (get_fpsr() & FPSR_CCB_ZERO)!= 0, + (get_fpsr() & FPSR_CCB_INFINITY) != 0, + (get_fpsr() & FPSR_CCB_NAN) != 0); +} + +/* single : S 8*E 23*F */ +/* double : S 11*E 52*F */ +/* extended : S 15*E 64*F */ +/* E = 0 & F = 0 -> 0 */ +/* E = MAX & F = 0 -> Infin */ +/* E = MAX & F # 0 -> NotANumber */ +/* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */ + +#if FPU_DEBUG + +PUBLIC void FFPU dump_registers(const char * str) +{ + char temp_str[512]; + + sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", + str, + fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3), + fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) ); + + fpu_debug((temp_str)); +} + +PUBLIC void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) +{ + char temp_buf1[256], temp_buf2[10]; + int bytes = sizeof(temp_buf1)/3-1-3; + if (actual < bytes) + bytes = actual; + + temp_buf1[0] = 0; + for (int i = 0; i < bytes; i++) { + sprintf(temp_buf2, "%02x ", (uae_u32)buffer[i]); + strcat(temp_buf1, temp_buf2); + } + + strcat(temp_buf1, "\n"); + fpu_debug((temp_buf1)); +} + +#else + +PUBLIC void FFPU dump_registers(const char *) +{ +} + +#define dump_first_bytes(a,b) + +#endif + +PRIVATE inline fpu_register FFPU round_to_zero(fpu_register const & x) +{ + return (x < 0.0 ? ceil(x) : floor(x)); +} + +PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x) +{ + return floor(x + 0.5); +} + +#if FPU_HAVE_IEEE_DOUBLE + +#ifndef HAVE_ISNAN +#define isnan(x) do_isnan((x)) +#endif + +PRIVATE inline bool FFPU do_isnan(fpu_register const & r) +{ + fpu_register_parts const p = { r }; + if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) { + // logical or is faster here. + if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) { + return true; + } + } + return false; +} + +#ifndef HAVE_ISINF +#define isinf(x) do_isinf((x)) +#endif + +PRIVATE inline bool FFPU do_isinf(fpu_register const & r) +{ + fpu_register_parts const p = { r }; + if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) { + return true; + } + return false; +} + +#ifndef HAVE_ISNEG +#define isneg(x) do_isneg((x)) +#endif + +PRIVATE inline bool FFPU do_isneg(fpu_register const & r) +{ + fpu_register_parts const p = { r }; + return ((p.parts[FHI] & 0x80000000) != 0); +} + +#ifndef HAVE_ISZERO +#define iszero(x) do_iszero((x)) +#endif + +PRIVATE inline bool FFPU do_iszero(fpu_register const & r) +{ + fpu_register_parts const p = { r }; + return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0); +} + +// May be optimized for particular processors +#ifndef FPU_USE_NATIVE_FLAGS +PRIVATE inline void FFPU make_fpsr(fpu_register const & r) +{ + FPU fpsr.condition_codes + = (iszero(r) ? NATIVE_FFLAG_ZERO : 0) + | (isneg(r) ? NATIVE_FFLAG_NEGATIVE : 0) + | (isnan(r) ? NATIVE_FFLAG_NAN : 0) + | (isinf(r) ? NATIVE_FFLAG_INFINITY : 0) + ; +} +#endif + +PRIVATE inline void FFPU get_dest_flags(fpu_register const & r) +{ + fl_dest.negative = isneg(r); + fl_dest.zero = iszero(r); + fl_dest.infinity = isinf(r); + fl_dest.nan = isnan(r); + fl_dest.in_range = !fl_dest.zero && !fl_dest.infinity && !fl_dest.nan; +} + +PRIVATE inline void FFPU get_source_flags(fpu_register const & r) +{ + fl_source.negative = isneg(r); + fl_source.zero = iszero(r); + fl_source.infinity = isinf(r); + fl_source.nan = isnan(r); + fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan; +} + +PRIVATE inline void FFPU make_nan(fpu_register & r) +{ + fpu_register_parts p; + p.parts[FLO] = 0xffffffff; + p.parts[FHI] = 0x7fffffff; + r = p.val; +} + +PRIVATE inline void FFPU make_zero_positive(fpu_register & r) +{ + fpu_register_parts p; + p.parts[FLO] = p.parts[FHI] = 0; + r = p.val; +} + +PRIVATE inline void FFPU make_zero_negative(fpu_register & r) +{ + fpu_register_parts p; + p.parts[FLO] = 0; + p.parts[FHI] = 0x80000000; + r = p.val; +} + +PRIVATE inline void FFPU make_inf_positive(fpu_register & r) +{ + fpu_register_parts p; + p.parts[FLO] = 0; + p.parts[FHI] = 0x7FF00000; + r = p.val; +} + +PRIVATE inline void FFPU make_inf_negative(fpu_register & r) +{ + fpu_register_parts p; + p.parts[FLO] = 0; + p.parts[FHI] = 0xFFF00000; + r = p.val; +} + +PRIVATE inline void FFPU fast_scale(fpu_register & r, int add) +{ + fpu_register_parts p = { r }; + int exp = (p.parts[FHI] & 0x7FF00000) >> 20; + // TODO: overflow flags + exp += add; + if(exp >= 2047) { + make_inf_positive(r); + return; + } else if(exp < 0) { + // keep sign (+/- 0) + p.parts[FHI] &= 0x80000000; + } else { + p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); + } + r = p.val; +} + +PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) +{ + fpu_register_parts const p = { r }; + int exp = (p.parts[FHI] & 0x7FF00000) >> 20; + return( exp - 1023 ); +} + +// Normalize to range 1..2 +PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) +{ + fpu_register_parts p = { r }; + p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000; + r = p.val; +} + +// The sign of the quotient is the exclusive-OR of the sign bits +// of the source and destination operands. +PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) +{ + fpu_register_parts const a = { ra }; + fpu_register_parts const b = { rb }; + return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); +} + +// Quotient Byte is loaded with the sign and least significant +// seven bits of the quotient. +PRIVATE inline void FFPU make_quotient(fpu_register const & quotient, uae_u32 sign) +{ + uae_u32 lsb = (uae_u32)fabs(quotient) & 0x7f; + FPU fpsr.quotient = sign | (lsb << 16); +} + +// to_single +PRIVATE inline fpu_register FFPU make_single(uae_u32 value) +{ + if ((value & 0x7fffffff) == 0) + return (0.0); + + fpu_register result; + fpu_register_parts p; + + uae_u32 sign = (value & 0x80000000); + uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; + + p.parts[FLO] = value << 29; + p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + + result = p.val; + + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + + return(result); +} + +// from_single +PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) +{ + if (src == 0.0) + return 0; + + uae_u32 result; + fpu_register_parts const p = { src }; + + uae_u32 sign = (p.parts[FHI] & 0x80000000); + uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20; + + if(exp + 127 < 1023) { + exp = 0; + } else if(exp > 1023 + 127) { + exp = 255; + } else { + exp = exp + 127 - 1023; + } + + result = sign | (exp << 23) | ((p.parts[FHI] & 0x000FFFFF) << 3) | (p.parts[FLO] >> 29); + + fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); + + return (result); +} + +// to_exten +PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) + return 0.0; + + fpu_register result; + fpu_register_parts p; + + uae_u32 sign = wrd1 & 0x80000000; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + + // The explicit integer bit is not set, must normalize. + if((wrd2 & 0x80000000) == 0) { + fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3)); + if( wrd2 | wrd3 ) { + // mantissa, not fraction. + uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; + while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) { + man <<= 1; + exp--; + } + wrd2 = (uae_u32)( man >> 32 ); + wrd3 = (uae_u32)( man & 0xFFFFFFFF ); + } else { + if(exp == 0x7FFF) { + // Infinity. + } else { + // Zero + exp = 16383 - 1023; + } + } + } + + if(exp < 16383 - 1023) { + // should set underflow. + exp = 0; + } else if(exp > 16383 + 1023) { + // should set overflow. + exp = 2047; + } else { + exp = exp + 1023 - 16383; + } + + // drop the explicit integer bit. + p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + + result = p.val; + + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); + + return(result); +} + +/* + Would be so much easier with full size floats :( + ... this is so vague. +*/ +// make_extended_no_normalize +PRIVATE inline void FFPU make_extended_no_normalize( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result +) +{ + // Is it zero? + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + make_zero_positive(result); + return; + } + + // Is it NaN? + if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) { + if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) { + make_nan(result); + return; + } + } + + uae_u32 sign = wrd1 & 0x80000000; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + + if(exp < 16383 - 1023) { + // should set underflow. + exp = 0; + } else if(exp > 16383 + 1023) { + // should set overflow. + exp = 2047; + } else { + exp = exp + 1023 - 16383; + } + + // drop the explicit integer bit. + fpu_register_parts p; + p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + + result = p.val; + + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); +} + +// from_exten +PRIVATE inline void FFPU extract_extended(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +) +{ + if (src == 0.0) { + *wrd1 = *wrd2 = *wrd3 = 0; + return; + } + + fpu_register_parts const p = { src }; + + fpu_debug(("extract_extended (%X,%X)\n",p.parts[FLO],p.parts[FHI])); + + uae_u32 sign = p.parts[FHI] & 0x80000000; + + uae_u32 exp = ((p.parts[FHI] >> 20) & 0x7ff); + // Check for maximum + if(exp == 0x7FF) { + exp = 0x7FFF; + } else { + exp += 16383 - 1023; + } + + *wrd1 = sign | (exp << 16); + // always set the explicit integer bit. + *wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21); + *wrd3 = p.parts[FLO] << 11; + + fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +} + +// to_double +PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) +{ + if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) + return 0.0; + + fpu_register result; + fpu_register_parts p; + p.parts[FLO] = wrd2; + p.parts[FHI] = wrd1; + + result = p.val; + + fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); + + return(result); +} + +// from_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2 +) +{ +/* + if (src == 0.0) { + *wrd1 = *wrd2 = 0; + return; + } +*/ + fpu_register_parts const p = { src }; + *wrd2 = p.parts[FLO]; + *wrd1 = p.parts[FHI]; + + fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); +} + +#else // !FPU_HAVE_IEEE_DOUBLE + +#ifndef FPU_USE_NATIVE_FLAGS +PRIVATE inline void FFPU make_fpsr(fpu_register const & r) +{ + FPU fpsr.condition_codes + = ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0) + | ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0) + ; +} +#endif + +// make_single +PRIVATE inline fpu_register FFPU make_single(uae_u32 value) +{ + if ((value & 0x7fffffff) == 0) + return (0.0); + + fpu_register frac = (fpu_register) ((value & 0x7fffff) | 0x800000) / 8388608.0; + if (value & 0x80000000) + frac = -frac; + + fpu_register result = ldexp (frac, (int)((value >> 23) & 0xff) - 127); + fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); + + return (result); +} + +// extract_single +PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) +{ + int expon; + uae_u32 tmp, result; + fpu_register frac; +#if FPU_DEBUG + fpu_register src0 = src; +#endif + + if (src == 0.0) + return 0; + if (src < 0) { + tmp = 0x80000000; + src = -src; + } else { + tmp = 0; + } + frac = frexp (src, &expon); + frac += 0.5 / 16777216.0; + if (frac >= 1.0) { + frac /= 2.0; + expon++; + } + result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff); + + // fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result)); + + return (result); +} + +// to exten +PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + fpu_register frac, result; + + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) + return 0.0; + frac = (fpu_register) wrd2 / 2147483648.0 + + (fpu_register) wrd3 / 9223372036854775808.0; + if (wrd1 & 0x80000000) + frac = -frac; + result = ldexp (frac, (int)((wrd1 >> 16) & 0x7fff) - 16383); + + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); + + return result; +} + +// extract_extended +PRIVATE inline void FFPU extract_extended(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +{ + int expon; + fpu_register frac; +#if FPU_DEBUG + fpu_register src0 = src; +#endif + + if (src == 0.0) { + *wrd1 = 0; + *wrd2 = 0; + *wrd3 = 0; + return; + } + if (src < 0) { + *wrd1 = 0x80000000; + src = -src; + } else { + *wrd1 = 0; + } + frac = frexp (src, &expon); + frac += 0.5 / 18446744073709551616.0; + if (frac >= 1.0) { + frac /= 2.0; + expon++; + } + *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); + *wrd2 = (uae_u32) (frac * 4294967296.0); + *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0); + + // fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(float)src0,*wrd1,*wrd2,*wrd3)); +} + +// make_double +PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) +{ + if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) + return 0.0; + + fpu_register frac = + (fpu_register) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 + + (fpu_register) wrd2 / 4503599627370496.0; + + if (wrd1 & 0x80000000) + frac = -frac; + + fpu_register result = ldexp (frac, (int)((wrd1 >> 20) & 0x7ff) - 1023); + fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); + + return result; +} + +// extract_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2) +{ + int expon; + int tmp; + fpu_register frac frac; +#if FPU_DEBUG + fpu_register src0 = src; +#endif + + if (src == 0.0) { + *wrd1 = 0; + *wrd2 = 0; + return; + } + if (src < 0) { + *wrd1 = 0x80000000; + src = -src; + } else { + *wrd1 = 0; + } + frac = frexp (src, &expon); + frac += 0.5 / 9007199254740992.0; + if (frac >= 1.0) { + frac /= 2.0; + expon++; + } + tmp = (uae_u32) (frac * 2097152.0); + *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff); + *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0); + + // fpu_debug(("extract_double (%.04f) = %X,%X\n",(float)src0,*wrd1,*wrd2)); +} + +#endif + +// to_pack +PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + fpu_double d; + char *cp; + char str[100]; + + cp = str; + if (wrd1 & 0x80000000) + *cp++ = '-'; + *cp++ = (char)((wrd1 & 0xf) + '0'); + *cp++ = '.'; + *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); + *cp++ = 'E'; + if (wrd1 & 0x40000000) + *cp++ = '-'; + *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); + *cp = 0; + sscanf(str, "%le", &d); + + fpu_debug(("make_packed str = %s\n",str)); + + fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); + return d; +} + +// from_pack +PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +{ + int i; + int t; + char *cp; + char str[100]; + + sprintf(str, "%.16e", src); + + fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); + + cp = str; + *wrd1 = *wrd2 = *wrd3 = 0; + if (*cp == '-') { + cp++; + *wrd1 = 0x80000000; + } + if (*cp == '+') + cp++; + *wrd1 |= (*cp++ - '0'); + if (*cp == '.') + cp++; + for (i = 0; i < 8; i++) { + *wrd2 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd2 |= *cp++ - '0'; + } + for (i = 0; i < 8; i++) { + *wrd3 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd3 |= *cp++ - '0'; + } + if (*cp == 'e' || *cp == 'E') { + cp++; + if (*cp == '-') { + cp++; + *wrd1 |= 0x40000000; + } + if (*cp == '+') + cp++; + t = 0; + for (i = 0; i < 3; i++) { + if (*cp >= '0' && *cp <= '9') + t = (t << 4) | (*cp++ - '0'); + } + *wrd1 |= t << 16; + } + + fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); +} + +PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register & src) +{ + uaecptr tmppc; + uae_u16 tmp; + int size; + int mode; + int reg; + uae_u32 ad = 0; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // fpu_debug(("get_fp_value(%X,%X)\n",(int)opcode,(int)extra)); + // dump_first_bytes( regs.pc_p-4, 16 ); + + if ((extra & 0x4000) == 0) { + src = FPU registers[(extra >> 10) & 7]; + return 1; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + + fpu_debug(("get_fp_value mode=%d, reg=%d, size=%d\n",(int)mode,(int)reg,(int)size)); + + switch (mode) { + case 0: + switch (size) { + case 6: + src = (fpu_register) (uae_s8) m68k_dreg (regs, reg); + break; + case 4: + src = (fpu_register) (uae_s16) m68k_dreg (regs, reg); + break; + case 0: + src = (fpu_register) (uae_s32) m68k_dreg (regs, reg); + break; + case 1: + src = make_single(m68k_dreg (regs, reg)); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + break; + case 4: + ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + fpu_debug(("get_fp_value next_iword()=%X\n",ad-m68k_getpc()-2)); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + if(size == 6) ad++; + break; + default: + return 0; + } + } + + fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); + fpu_debug(("get_fp_value ad=%X\n",ad)); + fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); + dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 ); + dump_first_bytes( get_real_address(ad, 0, 0), 64 ); + + switch (size) { + case 0: + src = (fpu_register) (uae_s32) get_long (ad); + break; + case 1: + src = make_single(get_long (ad)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_extended(wrd1, wrd2, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + src = make_packed(wrd1, wrd2, wrd3); + break; + } + case 4: + src = (fpu_register) (uae_s16) get_word(ad); + break; + case 5: { + uae_u32 wrd1, wrd2; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + src = make_double(wrd1, wrd2); + break; + } + case 6: + src = (fpu_register) (uae_s8) get_byte(ad); + break; + default: + return 0; + } + + switch (mode) { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); + return 1; +} + +PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) +{ + uae_u16 tmp; + uaecptr tmppc; + int size; + int mode; + int reg; + uae_u32 ad; + static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // fpu_debug(("put_fp_value(%.04f,%X,%X)\n",(float)value,(int)opcode,(int)extra)); + + if ((extra & 0x4000) == 0) { + int dest_reg = (extra >> 10) & 7; + FPU registers[dest_reg] = value; + make_fpsr(FPU registers[dest_reg]); + return 1; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + ad = 0xffffffff; + switch (mode) { + case 0: + switch (size) { + case 6: + m68k_dreg (regs, reg) + = (((uae_s32) value & 0xff) + | (m68k_dreg (regs, reg) & ~0xff)); + break; + case 4: + m68k_dreg (regs, reg) + = (((uae_s32) value & 0xffff) + | (m68k_dreg (regs, reg) & ~0xffff)); + break; + case 0: + m68k_dreg (regs, reg) = (uae_s32) value; + break; + case 1: + m68k_dreg (regs, reg) = extract_single(value); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + break; + default: + return 0; + } + } + switch (size) { + case 0: + put_long (ad, (uae_s32) value); + break; + case 1: + put_long (ad, extract_single(value)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + extract_extended(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 3: { + uae_u32 wrd1, wrd2, wrd3; + extract_packed(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + break; + } + case 4: + put_word(ad, (uae_s16) value); + break; + case 5: { + uae_u32 wrd1, wrd2; + extract_double(value, &wrd1, &wrd2); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + break; + } + case 6: + put_byte(ad, (uae_s8) value); + break; + default: + return 0; + } + return 1; +} + +PRIVATE inline int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) +{ + uae_u16 tmp; + uaecptr tmppc; + int mode; + int reg; + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) { + case 0: + case 1: + return 0; + case 2: + *ad = m68k_areg (regs, reg); + break; + case 3: + *ad = m68k_areg (regs, reg); + break; + case 4: + *ad = m68k_areg (regs, reg); + break; + case 5: + *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) { + case 0: + *ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + *ad = next_ilong(); + break; + case 2: + *ad = m68k_getpc (); + *ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: + tmppc = m68k_getpc (); + tmp = (uae_u16)next_iword(); + *ad = get_disp_ea_020 (tmppc, tmp); + break; + default: + return 0; + } + } + return 1; +} + +#if FPU_DEBUG +# define CONDRET(s,x) fpu_debug(("fpp_cond %s = %d\n",s,(uint32)(x))); return (x) +#else +# define CONDRET(s,x) return (x) +#endif + +PRIVATE inline int FFPU fpp_cond(int condition) +{ +#if 1 +# define N ((FPU fpsr.condition_codes & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE) +# define Z ((FPU fpsr.condition_codes & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO) +# define I ((FPU fpsr.condition_codes & NATIVE_FFLAG_INFINITY) == NATIVE_FFLAG_INFINITY) +# define NaN ((FPU fpsr.condition_codes & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN) +#else +# define N ((FPU fpsr.condition_codes & NATIVE_FFLAG_NEGATIVE) != 0) +# define Z ((FPU fpsr.condition_codes & NATIVE_FFLAG_ZERO) != 0) +# define I ((FPU fpsr.condition_codes & NATIVE_FFLAG_INFINITY) != 0) +# define NaN ((FPU fpsr.condition_codes & NATIVE_FFLAG_NAN) != 0) +#endif + +#if 0 + return fpcctrue(condition); +#else + switch (condition & 0x1f) { + case 0x00: CONDRET("False",0); + case 0x01: CONDRET("Equal",Z); + case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); + case 0x03: CONDRET("Ordered Greater Than or Equal",Z || !(NaN || N)); + case 0x04: CONDRET("Ordered Less Than",N && !(NaN || Z)); + case 0x05: CONDRET("Ordered Less Than or Equal",Z || (N && !NaN)); + case 0x06: CONDRET("Ordered Greater or Less Than",!(NaN || Z)); + case 0x07: CONDRET("Ordered",!NaN); + case 0x08: CONDRET("Unordered",NaN); + case 0x09: CONDRET("Unordered or Equal",NaN || Z); + case 0x0a: CONDRET("Unordered or Greater Than",NaN || !(N || Z)); + case 0x0b: CONDRET("Unordered or Greater or Equal",NaN || Z || !N); + case 0x0c: CONDRET("Unordered or Less Than",NaN || (N && !Z)); + case 0x0d: CONDRET("Unordered or Less or Equal",NaN || Z || N); + case 0x0e: CONDRET("Not Equal",!Z); + case 0x0f: CONDRET("True",1); + case 0x10: CONDRET("Signaling False",0); + case 0x11: CONDRET("Signaling Equal",Z); + case 0x12: CONDRET("Greater Than",!(NaN || Z || N)); + case 0x13: CONDRET("Greater Than or Equal",Z || !(NaN || N)); + case 0x14: CONDRET("Less Than",N && !(NaN || Z)); + case 0x15: CONDRET("Less Than or Equal",Z || (N && !NaN)); + case 0x16: CONDRET("Greater or Less Than",!(NaN || Z)); + case 0x17: CONDRET("Greater, Less or Equal",!NaN); + case 0x18: CONDRET("Not Greater, Less or Equal",NaN); + case 0x19: CONDRET("Not Greater or Less Than",NaN || Z); + case 0x1a: CONDRET("Not Less Than or Equal",NaN || !(N || Z)); + case 0x1b: CONDRET("Not Less Than",NaN || Z || !N); + case 0x1c: CONDRET("Not Greater Than or Equal", NaN || (N && !Z)); +// case 0x1c: CONDRET("Not Greater Than or Equal",!Z && (NaN || N)); + case 0x1d: CONDRET("Not Greater Than",NaN || Z || N); + case 0x1e: CONDRET("Signaling Not Equal",!Z); + case 0x1f: CONDRET("Signaling True",1); + default: CONDRET("",-1); + } +#endif + +# undef N +# undef Z +# undef I +# undef NaN +} + +void FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fdbcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uaecptr pc = (uae_u32) m68k_getpc (); + uae_s32 disp = (uae_s32) (uae_s16) next_iword(); + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (pc - 4); + op_illg (opcode); + } else if (!cc) { + int reg = opcode & 0x7; + + // this may have leaked. + /* + m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) + | ((m68k_dreg (regs, reg) - 1) & 0xffff)); + */ + m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000) + | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff)); + + + // condition reversed. + // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) + if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff) + m68k_setpc (pc + disp); + } +} + +void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) +{ + fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + uae_u32 ad; + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else if ((opcode & 0x38) == 0) { + m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | + (cc ? 0xff : 0x00); + } + else if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else + put_byte(ad, cc ? 0xff : 0x00); +} + +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +{ + fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + int cc = fpp_cond(extra & 0x3f); + if (cc == -1) { + m68k_setpc (oldpc); + op_illg (opcode); + } + if (cc) + Exception(7, oldpc - 2); +} + +// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) +void FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) +{ + fpu_debug(("fbcc_opp %X, %X at %08lx, jumpto=%X\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); + + int cc = fpp_cond(opcode & 0x3f); + if (cc == -1) { + m68k_setpc (pc); + op_illg (opcode); + } + else if (cc) { + if ((opcode & 0x40) == 0) + extra = (uae_s32) (uae_s16) extra; + m68k_setpc (pc + extra); + } +} + +// FSAVE has no post-increment +// 0x1f180000 == IDLE state frame, coprocessor version number 1F +void FFPU fpuop_save(uae_u32 opcode) +{ + fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); + + uae_u32 ad; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int i; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (CPUType == 4) { + // Put 4 byte 68040 IDLE frame. + if (incr < 0) { + ad -= 4; + put_long (ad, 0x41000000); + } + else { + put_long (ad, 0x41000000); + ad += 4; + } + } else { + // Put 28 byte 68881 IDLE frame. + if (incr < 0) { + fpu_debug(("fsave_opp pre-decrement\n")); + ad -= 4; + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + for (i = 0; i < 5; i++) { + ad -= 4; + put_long (ad, 0x00000000); + } + ad -= 4; + put_long (ad, 0x1f180000); // IDLE, vers 1f + } + else { + put_long (ad, 0x1f180000); // IDLE, vers 1f + ad += 4; + for (i = 0; i < 5; i++) { + put_long (ad, 0x00000000); + ad += 4; + } + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + ad += 4; + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + fpu_debug(("PROBLEM: fsave_opp post-increment\n")); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("fsave_opp pre-decrement %X -> A%d\n",ad,opcode & 7)); + } +} + +// FRESTORE has no pre-decrement +void FFPU fpuop_restore(uae_u32 opcode) +{ + fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); + + uae_u32 ad; + uae_u32 d; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (CPUType == 4) { + // 68040 + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); + ad -= 44; + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad -= 92; + } + } + } + else { + d = get_long (ad); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + fpu_debug(("PROBLEM: frestore_opp found UNIMP frame at %X\n",ad-4)); + ad += 44; + } + else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad += 92; + } + } + } + } + else { + // 68881 + if (incr < 0) { + fpu_debug(("PROBLEM: frestore_opp incr < 0\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { + if ((d & 0x00ff0000) == 0x00180000) + ad -= 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad -= 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad -= 45 * 4; + } + } + else { + d = get_long (ad); + fpu_debug(("frestore_opp frame at %X = %X\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0x00180000) { // IDLE + fpu_debug(("frestore_opp found IDLE frame at %X\n",ad-4)); + ad += 6 * 4; + } + else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? + ad += 14 * 4; + fpu_debug(("PROBLEM: frestore_opp found UNIMP? frame at %X\n",ad-4)); + } + else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY + fpu_debug(("PROBLEM: frestore_opp found BUSY frame at %X\n",ad-4)); + ad += 45 * 4; + } + } + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; + fpu_debug(("frestore_opp post-increment %X -> A%d\n",ad,opcode & 7)); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + fpu_debug(("PROBLEM: frestore_opp pre-decrement\n")); + } +} + +void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) +{ + int reg; + fpu_register src; + + fpu_debug(("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, + m68k_getpc () - 4)); + + dump_registers( "START"); + + switch ((extra >> 13) & 0x7) { + case 3: + fpu_debug(("FMOVE -> \n")); + if (put_fp_value (opcode, extra, FPU registers[(extra >> 7) & 7]) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + dump_registers( "END "); + return; + case 4: + case 5: + if ((opcode & 0x38) == 0) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_dreg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> D%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> D%d\n", FPU instruction_address, opcode & 7)); + } + } + else { + if (extra & 0x1000) { + set_fpcr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_dreg (regs, opcode & 7) ); + fpu_debug(("FMOVEM D%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_dreg (regs, opcode & 7); + fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } +// } else if ((opcode & 0x38) == 1) { + } + else if ((opcode & 0x38) == 8) { + if (extra & 0x2000) { // dr bit + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); + } + if (extra & 0x0800) { + m68k_areg (regs, opcode & 7) = get_fpsr(); + fpu_debug(("FMOVEM FPU fpsr (%X) -> A%d\n", get_fpsr(), opcode & 7)); + } + if (extra & 0x0400) { + m68k_areg (regs, opcode & 7) = FPU instruction_address; + fpu_debug(("FMOVEM FPU instruction_address (%X) -> A%d\n", FPU instruction_address, opcode & 7)); + } + } else { + if (extra & 0x1000) { + set_fpcr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpcr\n", opcode & 7, get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( m68k_areg (regs, opcode & 7) ); + fpu_debug(("FMOVEM A%d (%X) -> FPU fpsr\n", opcode & 7, get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = m68k_areg (regs, opcode & 7); + fpu_debug(("FMOVEM A%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); + } + } + } + else if ((opcode & 0x3f) == 0x3c) { + if ((extra & 0x2000) == 0) { + if (extra & 0x1000) { + set_fpcr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpcr\n", get_fpcr())); + } + if (extra & 0x0800) { + set_fpsr( next_ilong() ); + fpu_debug(("FMOVEM #<%X> -> FPU fpsr\n", get_fpsr())); + } + if (extra & 0x0400) { + FPU instruction_address = next_ilong(); + fpu_debug(("FMOVEM #<%X> -> FPU instruction_address\n", FPU instruction_address)); + } + } + } + else if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + uae_u32 ad; + int incr = 0; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + if ((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + } + ad -= incr; + if (extra & 0x1000) { + // according to the manual, the msb bits are always zero. + put_long (ad, get_fpcr() & 0xFFFF); + fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); + ad += 4; + } + if (extra & 0x0800) { + put_long (ad, get_fpsr()); + fpu_debug(("FMOVEM FPU fpsr (%X) -> mem %X\n", get_fpsr(), ad )); + ad += 4; + } + if (extra & 0x0400) { + put_long (ad, FPU instruction_address); + fpu_debug(("FMOVEM FPU instruction_address (%X) -> mem %X\n", FPU instruction_address, ad )); + ad += 4; + } + ad -= incr; + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + uae_u32 ad; + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + + // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; + int incr = 0; + if((opcode & 0x38) == 0x20) { + if (extra & 0x1000) + incr += 4; + if (extra & 0x0800) + incr += 4; + if (extra & 0x0400) + incr += 4; + ad = ad - incr; + } + + if (extra & 0x1000) { + set_fpcr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpcr\n", ad, get_fpcr() )); + ad += 4; + } + if (extra & 0x0800) { + set_fpsr( get_long (ad) ); + fpu_debug(("FMOVEM mem %X (%X) -> FPU fpsr\n", ad, get_fpsr() )); + ad += 4; + } + if (extra & 0x0400) { + FPU instruction_address = get_long (ad); + fpu_debug(("FMOVEM mem %X (%X) -> FPU instruction_address\n", ad, FPU instruction_address )); + ad += 4; + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? +// m68k_areg (regs, opcode & 7) = ad - 12; + m68k_areg (regs, opcode & 7) = ad - incr; + } + dump_registers( "END "); + return; + case 6: + case 7: { + uae_u32 ad, list = 0; + int incr = 0; + if (extra & 0x2000) { + /* FMOVEM FPP->memory */ + fpu_debug(("FMOVEM FPP->memory\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + if (incr < 0) { + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + extract_extended(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + else { + /* FMOVEM memory->FPP */ + fpu_debug(("FMOVEM memory->FPP\n")); + + if (get_fp_ad(opcode, &ad) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = extra & 0xff; + incr = -1; + break; + case 1: /* dynamic pred */ + fpu_debug(("memory->FMOVEM FPP not legal mode.\n")); + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 3: /* dynamic postinc */ + list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + incr = 1; + break; + } + + /**/ + if (incr < 0) { + // not reached + for(reg=7; reg>=0; reg--) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + else { + for(reg=0; reg<8; reg++) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + // FPU registers[reg] = make_extended(wrd1, wrd2, wrd3); + make_extended_no_normalize (wrd1, wrd2, wrd3, FPU registers[reg]); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) // post-increment? + m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) // pre-decrement? + m68k_areg (regs, opcode & 7) = ad; + } + dump_registers( "END "); + return; + } + case 0: + case 2: + reg = (extra >> 7) & 7; + if ((extra & 0xfc00) == 0x5c00) { + fpu_debug(("FMOVECR memory->FPP\n")); + switch (extra & 0x7f) { + case 0x00: + // FPU registers[reg] = 4.0 * atan(1.0); + FPU registers[reg] = 3.1415926535897932384626433832795; + fpu_debug(("FP const: Pi\n")); + break; + case 0x0b: + // FPU registers[reg] = log10 (2.0); + FPU registers[reg] = 0.30102999566398119521373889472449; + fpu_debug(("FP const: Log 10 (2)\n")); + break; + case 0x0c: + // FPU registers[reg] = exp (1.0); + FPU registers[reg] = 2.7182818284590452353602874713527; + fpu_debug(("FP const: e\n")); + break; + case 0x0d: + // FPU registers[reg] = log (exp (1.0)) / log (2.0); + FPU registers[reg] = 1.4426950408889634073599246810019; + fpu_debug(("FP const: Log 2 (e)\n")); + break; + case 0x0e: + // FPU registers[reg] = log (exp (1.0)) / log (10.0); + FPU registers[reg] = 0.43429448190325182765112891891661; + fpu_debug(("FP const: Log 10 (e)\n")); + break; + case 0x0f: + FPU registers[reg] = 0.0; + fpu_debug(("FP const: zero\n")); + break; + case 0x30: + // FPU registers[reg] = log (2.0); + FPU registers[reg] = 0.69314718055994530941723212145818; + fpu_debug(("FP const: ln(2)\n")); + break; + case 0x31: + // FPU registers[reg] = log (10.0); + FPU registers[reg] = 2.3025850929940456840179914546844; + fpu_debug(("FP const: ln(10)\n")); + break; + case 0x32: + // ?? + FPU registers[reg] = 1.0e0; + fpu_debug(("FP const: 1.0e0\n")); + break; + case 0x33: + FPU registers[reg] = 1.0e1; + fpu_debug(("FP const: 1.0e1\n")); + break; + case 0x34: + FPU registers[reg] = 1.0e2; + fpu_debug(("FP const: 1.0e2\n")); + break; + case 0x35: + FPU registers[reg] = 1.0e4; + fpu_debug(("FP const: 1.0e4\n")); + break; + case 0x36: + FPU registers[reg] = 1.0e8; + fpu_debug(("FP const: 1.0e8\n")); + break; + case 0x37: + FPU registers[reg] = 1.0e16; + fpu_debug(("FP const: 1.0e16\n")); + break; + case 0x38: + FPU registers[reg] = 1.0e32; + fpu_debug(("FP const: 1.0e32\n")); + break; + case 0x39: + FPU registers[reg] = 1.0e64; + fpu_debug(("FP const: 1.0e64\n")); + break; + case 0x3a: + FPU registers[reg] = 1.0e128; + fpu_debug(("FP const: 1.0e128\n")); + break; + case 0x3b: + FPU registers[reg] = 1.0e256; + fpu_debug(("FP const: 1.0e256\n")); + break; + + // Valid for 64 bits only (see fpu.cpp) +#if 0 + case 0x3c: + FPU registers[reg] = 1.0e512; + fpu_debug(("FP const: 1.0e512\n")); + break; + case 0x3d: + FPU registers[reg] = 1.0e1024; + fpu_debug(("FP const: 1.0e1024\n")); + break; + case 0x3e: + FPU registers[reg] = 1.0e2048; + fpu_debug(("FP const: 1.0e2048\n")); + break; + case 0x3f: + FPU registers[reg] = 1.0e4096; + fpu_debug(("FP const: 1.0e4096\n")); + break; +#endif + default: + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + // these *do* affect the status reg + make_fpsr(FPU registers[reg]); + dump_registers( "END "); + return; + } + + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); +#if 0 // MJ added, not tested now + if (FPU is_integral) { + // 68040-specific operations + switch (extra & 0x7f) { + case 0x40: /* FSMOVE */ + fpu_debug(("FSMOVE %.04f\n",(double)src)); + FPU registers[reg] = (float)src; + make_fpsr(FPU registers[reg]); + break; + case 0x44: /* FDMOVE */ + fpu_debug(("FDMOVE %.04f\n",(double)src)); + FPU registers[reg] = (double)src; + make_fpsr(FPU registers[reg]); + break; + case 0x41: /* FSSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (float)sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x45: /* FDSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (double)sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x58: /* FSABS */ + fpu_debug(("FSABS %.04f\n",(double)src)); + FPU registers[reg] = (float)fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5c: /* FDABS */ + fpu_debug(("FDABS %.04f\n",(double)src)); + FPU registers[reg] = (double)fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5a: /* FSNEG */ + fpu_debug(("FSNEG %.04f\n",(double)src)); + FPU registers[reg] = (float)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x5e: /* FDNEG */ + fpu_debug(("FDNEG %.04f\n",(double)src)); + FPU registers[reg] = (double)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x60: /* FSDIV */ + fpu_debug(("FSDIV %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x64: /* FDDIV */ + fpu_debug(("FDDIV %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x62: /* FSADD */ + fpu_debug(("FSADD %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x66: /* FDADD */ + fpu_debug(("FDADD %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x68: /* FSSUB */ + fpu_debug(("FSSUB %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x6c: /* FDSUB */ + fpu_debug(("FDSUB %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x63: /* FSMUL */ + case 0x67: /* FDMUL */ + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if(fl_dest.in_range && fl_source.in_range) { + if ((extra & 0x7f) == 0x63) + FPU registers[reg] = (float)(FPU registers[reg] * src); + else + FPU registers[reg] = (double)(FPU registers[reg] * src); + } + else if (fl_dest.nan || fl_source.nan || + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } + make_fpsr(FPU registers[reg]); + break; + default: + // Continue decode-execute 6888x instructions below + goto process_6888x_instructions; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + process_6888x_instructions: +#endif + switch (extra & 0x7f) { + case 0x00: /* FMOVE */ + fpu_debug(("FMOVE %.04f\n",(double)src)); + FPU registers[reg] = src; + // -> reg DOES affect the status reg + make_fpsr(FPU registers[reg]); + break; + case 0x01: /* FINT */ + fpu_debug(("FINT %.04f\n",(double)src)); + // FPU registers[reg] = (int) (src + 0.5); + // FIXME: use native rounding mode flags + switch (get_fpcr() & 0x30) { + case FPCR_ROUND_ZERO: + FPU registers[reg] = round_to_zero(src); + break; + case FPCR_ROUND_MINF: + FPU registers[reg] = floor(src); + break; + case FPCR_ROUND_NEAR: + FPU registers[reg] = round_to_nearest(src); + break; + case FPCR_ROUND_PINF: + FPU registers[reg] = ceil(src); + break; + } + make_fpsr(FPU registers[reg]); + break; + case 0x02: /* FSINH */ + fpu_debug(("FSINH %.04f\n",(double)src)); + FPU registers[reg] = sinh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x03: /* FINTRZ */ + fpu_debug(("FINTRZ %.04f\n",(double)src)); + // FPU registers[reg] = (int) src; + FPU registers[reg] = round_to_zero(src); + make_fpsr(FPU registers[reg]); + break; + case 0x04: /* FSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x06: /* FLOGNP1 */ + fpu_debug(("FLOGNP1 %.04f\n",(double)src)); + FPU registers[reg] = log (src + 1.0); + make_fpsr(FPU registers[reg]); + break; + case 0x08: /* FETOXM1 */ + fpu_debug(("FETOXM1 %.04f\n",(double)src)); + FPU registers[reg] = exp (src) - 1.0; + make_fpsr(FPU registers[reg]); + break; + case 0x09: /* FTANH */ + fpu_debug(("FTANH %.04f\n",(double)src)); + FPU registers[reg] = tanh (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0a: /* FATAN */ + fpu_debug(("FATAN %.04f\n",(double)src)); + FPU registers[reg] = atan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0c: /* FASIN */ + fpu_debug(("FASIN %.04f\n",(double)src)); + FPU registers[reg] = asin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0d: /* FATANH */ + fpu_debug(("FATANH %.04f\n",(double)src)); +#if HAVE_ATANH + FPU registers[reg] = atanh (src); +#else + /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */ + FPU registers[reg] = log ((1 + src) / (1 - src)) / 2; +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x0e: /* FSIN */ + fpu_debug(("FSIN %.04f\n",(double)src)); + FPU registers[reg] = sin (src); + make_fpsr(FPU registers[reg]); + break; + case 0x0f: /* FTAN */ + fpu_debug(("FTAN %.04f\n",(double)src)); + FPU registers[reg] = tan (src); + make_fpsr(FPU registers[reg]); + break; + case 0x10: /* FETOX */ + fpu_debug(("FETOX %.04f\n",(double)src)); + FPU registers[reg] = exp (src); + make_fpsr(FPU registers[reg]); + break; + case 0x11: /* FTWOTOX */ + fpu_debug(("FTWOTOX %.04f\n",(double)src)); + FPU registers[reg] = pow(2.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x12: /* FTENTOX */ + fpu_debug(("FTENTOX %.04f\n",(double)src)); + FPU registers[reg] = pow(10.0, src); + make_fpsr(FPU registers[reg]); + break; + case 0x14: /* FLOGN */ + fpu_debug(("FLOGN %.04f\n",(double)src)); + FPU registers[reg] = log (src); + make_fpsr(FPU registers[reg]); + break; + case 0x15: /* FLOG10 */ + fpu_debug(("FLOG10 %.04f\n",(double)src)); + FPU registers[reg] = log10 (src); + make_fpsr(FPU registers[reg]); + break; + case 0x16: /* FLOG2 */ + fpu_debug(("FLOG2 %.04f\n",(double)src)); + FPU registers[reg] = log (src) / log (2.0); + make_fpsr(FPU registers[reg]); + break; + case 0x18: /* FABS */ + case 0x58: /* single precision rounding */ + case 0x5C: /* double precision rounding */ + fpu_debug(("FABS %.04f\n",(double)src)); + FPU registers[reg] = src < 0 ? -src : src; + make_fpsr(FPU registers[reg]); + break; + case 0x19: /* FCOSH */ + fpu_debug(("FCOSH %.04f\n",(double)src)); + FPU registers[reg] = cosh(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1a: /* FNEG */ + fpu_debug(("FNEG %.04f\n",(double)src)); + FPU registers[reg] = -src; + make_fpsr(FPU registers[reg]); + break; + case 0x1c: /* FACOS */ + fpu_debug(("FACOS %.04f\n",(double)src)); + FPU registers[reg] = acos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1d: /* FCOS */ + fpu_debug(("FCOS %.04f\n",(double)src)); + FPU registers[reg] = cos(src); + make_fpsr(FPU registers[reg]); + break; + case 0x1e: /* FGETEXP */ + fpu_debug(("FGETEXP %.04f\n",(double)src)); +#if FPU_HAVE_IEEE_DOUBLE + if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = fast_fgetexp( src ); + } +#else + if(src == 0) { + FPU registers[reg] = (fpu_register)0; + } + else { + int expon; + frexp (src, &expon); + FPU registers[reg] = (fpu_register) (expon - 1); + } +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x1f: /* FGETMAN */ + fpu_debug(("FGETMAN %.04f\n",(double)src)); +#if FPU_HAVE_IEEE_DOUBLE + if( src == 0 ) { + FPU registers[reg] = 0; + } + else if( isinf(src) ) { + make_nan( FPU registers[reg] ); + } + else { + FPU registers[reg] = src; + fast_remove_exponent( FPU registers[reg] ); + } +#else + { + int expon; + FPU registers[reg] = frexp (src, &expon) * 2.0; + } +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x20: /* FDIV */ + fpu_debug(("FDIV %.04f\n",(double)src)); + FPU registers[reg] /= src; + make_fpsr(FPU registers[reg]); + break; + case 0x21: /* FMOD */ + fpu_debug(("FMOD %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (fpu_register) ((int) (FPU registers[reg] / src)) * src; + { + fpu_register quot = round_to_zero(FPU registers[reg] / src); +#if FPU_HAVE_IEEE_DOUBLE + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); +#endif + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); +#if FPU_HAVE_IEEE_DOUBLE + make_quotient(quot, sign); +#endif + } + break; + case 0x22: /* FADD */ + case 0x62: /* single */ + case 0x66: /* double */ + fpu_debug(("FADD %.04f\n",(double)src)); + FPU registers[reg] += src; + make_fpsr(FPU registers[reg]); + break; + case 0x23: /* FMUL */ + fpu_debug(("FMUL %.04f\n",(double)src)); +#if FPU_HAVE_IEEE_DOUBLE + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if(fl_dest.in_range && fl_source.in_range) { + FPU registers[reg] *= src; + } + else if (fl_dest.nan || fl_source.nan || + (fl_dest.zero && fl_source.infinity) || + (fl_dest.infinity && fl_source.zero) ) { + make_nan( FPU registers[reg] ); + } + else if (fl_dest.zero || fl_source.zero ) { + if (( fl_dest.negative && !fl_source.negative) || + (!fl_dest.negative && fl_source.negative)) { + make_zero_negative(FPU registers[reg]); + } + else { + make_zero_positive(FPU registers[reg]); + } + } + else { + if(( fl_dest.negative && !fl_source.negative) || + (!fl_dest.negative && fl_source.negative)) { + make_inf_negative(FPU registers[reg]); + } + else { + make_inf_positive(FPU registers[reg]); + } + } +#else + fpu_debug(("FMUL %.04f\n",(double)src)); + FPU registers[reg] *= src; +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x24: /* FSGLDIV */ + fpu_debug(("FSGLDIV %.04f\n",(double)src)); + // TODO: round to float. + FPU registers[reg] /= src; + make_fpsr(FPU registers[reg]); + break; + case 0x25: /* FREM */ + fpu_debug(("FREM %.04f\n",(double)src)); + // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; + { + fpu_register quot = round_to_nearest(FPU registers[reg] / src); +#if FPU_HAVE_IEEE_DOUBLE + uae_u32 sign = get_quotient_sign(FPU registers[reg],src); +#endif + FPU registers[reg] = FPU registers[reg] - quot * src; + make_fpsr(FPU registers[reg]); +#if FPU_HAVE_IEEE_DOUBLE + make_quotient(quot,sign); +#endif + } + break; + + case 0x26: /* FSCALE */ + fpu_debug(("FSCALE %.04f\n",(double)src)); + + // TODO: + // Overflow, underflow + +#if FPU_HAVE_IEEE_DOUBLE + if( isinf(FPU registers[reg]) ) { + make_nan( FPU registers[reg] ); + } + else { + // When the absolute value of the source operand is >= 2^14, + // an overflow or underflow always results. + // Here (int) cast is okay. + fast_scale( FPU registers[reg], (int)round_to_zero(src) ); + } +#else + if (src != 0) { // Manual says: src==0 -> FPn + FPU registers[reg] *= exp (log (2.0) * src); + } +#endif + make_fpsr(FPU registers[reg]); + break; + case 0x27: /* FSGLMUL */ + fpu_debug(("FSGLMUL %.04f\n",(double)src)); + FPU registers[reg] *= src; + make_fpsr(FPU registers[reg]); + break; + case 0x28: /* FSUB */ + fpu_debug(("FSUB %.04f\n",(double)src)); + FPU registers[reg] -= src; + make_fpsr(FPU registers[reg]); + break; + case 0x30: /* FSINCOS */ + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + fpu_debug(("FSINCOS %.04f\n",(double)src)); + // Cosine must be calculated first if same register + FPU registers[extra & 7] = cos(src); + FPU registers[reg] = sin (src); + // Set FPU fpsr according to the sine result + make_fpsr(FPU registers[reg]); + break; + case 0x38: /* FCMP */ + fpu_debug(("FCMP %.04f\n",(double)src)); + + // The infinity bit is always cleared by the FCMP + // instruction since it is not used by any of the + // conditional predicate equations. + +#if FPU_HAVE_IEEE_DOUBLE + if( isinf(src) ) { + if( isneg(src) ) { + // negative infinity + if( isinf(FPU registers[reg]) && isneg(FPU registers[reg]) ) { + // Zero, Negative + FPU fpsr.condition_codes = NATIVE_FFLAG_ZERO | NATIVE_FFLAG_NEGATIVE; + fpu_debug(("-INF cmp -INF -> NZ\n")); + } + else { + // None + FPU fpsr.condition_codes = 0; + fpu_debug(("x cmp -INF -> None\n")); + } + } + else { + // positive infinity + if( isinf(FPU registers[reg]) && !isneg(FPU registers[reg]) ) { + // Zero + FPU fpsr.condition_codes = NATIVE_FFLAG_ZERO; + fpu_debug(("+INF cmp +INF -> Z\n")); + } + else { + // Negative + FPU fpsr.condition_codes = NATIVE_FFLAG_NEGATIVE; + fpu_debug(("X cmp +INF -> N\n")); + } + } + } + else { + fpu_register tmp = FPU registers[reg] - src; + FPU fpsr.condition_codes + = (iszero(tmp) ? NATIVE_FFLAG_ZERO : 0) + | (isneg(tmp) ? NATIVE_FFLAG_NEGATIVE : 0) + ; + } +#else + { + fpu_register tmp = FPU registers[reg] - src; + make_fpsr(tmp); + } +#endif + break; + case 0x3a: /* FTST */ + fpu_debug(("FTST %.04f\n",(double)src)); + // make_fpsr(FPU registers[reg]); + make_fpsr(src); + break; + default: + fpu_debug(("ILLEGAL F OP %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + break; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + + fpu_debug(("ILLEGAL F OP 2 %X\n",opcode)); + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); +} + + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} + +/* -------------------------- Initialization -------------------------- */ + +void FFPU fpu_init (bool integral_68040) +{ + fpu_debug(("fpu_init\n")); + + static bool initialized_lookup_tables = false; + if (!initialized_lookup_tables) { + fpu_init_native_fflags(); + fpu_init_native_exceptions(); + fpu_init_native_accrued_exceptions(); + initialized_lookup_tables = true; + } + + FPU is_integral = integral_68040; + set_fpcr(0); + set_fpsr(0); + FPU instruction_address = 0; +} + +void FFPU fpu_exit (void) +{ + fpu_debug(("fpu_exit\n")); +} + +void FFPU fpu_reset (void) +{ + fpu_debug(("fpu_reset\n")); + fpu_exit(); + fpu_init(FPU is_integral); +} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h new file mode 100644 index 00000000..d8930e32 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h @@ -0,0 +1,217 @@ +/* + * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_UAE_H +#define FPU_UAE_H + +// Only define if you have IEEE 64 bit doubles. +#define FPU_HAVE_IEEE_DOUBLE 1 + +/* NOTE: this file shall be included from fpu/fpu_uae.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +enum { +#ifdef WORDS_BIGENDIAN + FHI = 0, + FLO = 1 +#else + FHI = 1, + FLO = 0 +#endif +}; + +// Floating-point rounding support +PRIVATE inline fpu_register round_to_zero(fpu_register const & x); +PRIVATE inline fpu_register round_to_nearest(fpu_register const & x); + +#if FPU_HAVE_IEEE_DOUBLE + +// Lauri-- full words to avoid partial register stalls. +struct double_flags { + uae_u32 in_range; + uae_u32 zero; + uae_u32 infinity; + uae_u32 nan; + uae_u32 negative; +}; +PRIVATE double_flags fl_source; +PRIVATE double_flags fl_dest; +PRIVATE inline void FFPU get_dest_flags(fpu_register const & r); +PRIVATE inline void FFPU get_source_flags(fpu_register const & r); + +PRIVATE inline bool FFPU do_isnan(fpu_register const & r); +PRIVATE inline bool FFPU do_isinf(fpu_register const & r); +PRIVATE inline bool FFPU do_isneg(fpu_register const & r); +PRIVATE inline bool FFPU do_iszero(fpu_register const & r); + +PRIVATE inline void FFPU make_nan(fpu_register & r); +PRIVATE inline void FFPU make_zero_positive(fpu_register & r); +PRIVATE inline void FFPU make_zero_negative(fpu_register & r); +PRIVATE inline void FFPU make_inf_positive(fpu_register & r); +PRIVATE inline void FFPU make_inf_negative(fpu_register & r); + +PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); +PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); + +// May be optimized for particular processors +#ifndef FPU_USE_NATIVE_FLAGS +PRIVATE inline void FFPU make_fpsr(fpu_register const & r); +#endif + +// Normalize to range 1..2 +PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r); + +// The sign of the quotient is the exclusive-OR of the sign bits +// of the source and destination operands. +PRIVATE inline uae_u32 FFPU get_quotient_sign( + fpu_register const & ra, fpu_register const & rb +); + +// Quotient Byte is loaded with the sign and least significant +// seven bits of the quotient. +PRIVATE inline void FFPU make_quotient( + fpu_register const & quotient, uae_u32 sign +); + +// to_single +PRIVATE inline fpu_register FFPU make_single( + uae_u32 value +); + +// from_single +PRIVATE inline uae_u32 FFPU extract_single( + fpu_register const & src +); + +// to_exten +PRIVATE inline fpu_register FFPU make_extended( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 +); + +/* + Would be so much easier with full size floats :( + ... this is so vague. +*/ +// to_exten_no_normalize +PRIVATE inline void FFPU make_extended_no_normalize( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result +); + +// from_exten +PRIVATE inline void FFPU extract_extended(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +); + +// to_double +PRIVATE inline fpu_register FFPU make_double( + uae_u32 wrd1, uae_u32 wrd2 +); + +// from_double +PRIVATE inline void FFPU extract_double(fpu_register const & src, + uae_u32 * wrd1, uae_u32 * wrd2 +); + +#else /* !FPU_HAVE_IEEE_DOUBLE */ + +// FIXME: may be optimized for particular processors +#ifndef FPU_USE_NATIVE_FLAGS +PRIVATE inline void FFPU make_fpsr(fpu_register const & r); +#endif + +// to_single +PRIVATE inline fpu_register make_single( + uae_u32 value +); + +// from_single +PRIVATE inline uae_u32 FFPU extract_single( + fpu_register const & src +); + +// to exten +PRIVATE inline fpu_register FFPU make_extended( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 +); + +// from_exten +PRIVATE inline void FFPU extract_extended( + fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +); + +// to_double +PRIVATE inline fpu_register FFPU make_double( + uae_u32 wrd1, uae_u32 wrd2 +); + +// from_double +PRIVATE inline void FFPU extract_double( + fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2 +); + +#endif /* FPU_HAVE_IEEE_DOUBLE */ + +PRIVATE inline fpu_register FFPU make_packed( + uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3 +); + +PRIVATE inline void FFPU extract_packed( + fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3 +); + +PRIVATE inline int FFPU get_fp_value( + uae_u32 opcode, uae_u16 extra, fpu_register & src +); + +PRIVATE inline int FFPU put_fp_value( + uae_u32 opcode, uae_u16 extra, fpu_register const & value +); + +PRIVATE inline int FFPU get_fp_ad( + uae_u32 opcode, uae_u32 * ad +); + +PRIVATE inline int FFPU fpp_cond( + int condition +); + +#endif /* FPU_UAE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp new file mode 100644 index 00000000..a4c6af2d --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp @@ -0,0 +1,6791 @@ +/* + * fpu/fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Interface + * Almost the same as original. Please see the comments in "fpu.h". + * + * + * Why assembly? + * The reason is not really speed, but to get infinities, + * NANs and flags finally working. + * + * + * How to maintain Mac and x86 FPU flags -- plan B + * + * regs.piar is not updated. + * + * regs.FPU fpcr always contains the real 68881/68040 control word. + * + * regs.FPU fpsr is not kept up-to-date, for efficiency reasons. + * Most of the FPU commands update this in a way or another, but it is not + * read nearly that often. Therefore, three host-specific words hold the + * status byte and exception byte ("x86_status_word"), accrued exception + * byte ("x86_status_word_accrued") and the quotient byte ("FPU fpsr.quotient"), + * as explained below. + * + * CONDITION CODE - QUOTIENT - EXCEPTION STATUS - ACCRUED EXCEPTION + * CONDITION CODE (N,Z,I,NAN) + * - updated after each opcode, if needed. + * - x86 assembly opcodes call FXAM and store the status word to + * "x86_status_word". + * - When regs.FPU fpsr is actually used, the value of "x86_status_word" + * is translated. + * QUOTIENT BYTE + * - Updated by frem, fmod, frestore(null frame) + * - Stored in "FPU fpsr.quotient" in correct bit position, combined when + * regs.FPU fpsr is actually used. + * EXCEPTION STATUS (BSUN,SNAN,OPERR,OVFL,UNFL,DZ,INEX2,INEX1) + * - updated after each opcode, if needed. + * - Saved in x86 form in "x86_status_word". + * - When regs.FPU fpsr is actually used, the value of "x86_status_word" + * is translated. + * - Only fcc_op can set BSUN + * ACCRUED EXCEPTION (ACCR_IOP,ACCR_OVFL,ACCR_UNFL,ACCR_DZ,ACCR_INEX) + * - updated after each opcode, if needed. + * - Logically OR'ed in x86 form to "x86_status_word_accrued". + * - When regs.FPU fpsr is actually used, the value of + * "x86_status_word_accrued" is translated. + * + * When "x86_status_word" and "x86_status_word_accrued" are stored, + * all pending x86 FPU exceptions are cleared, if there are any. + * + * Writing to "regs.FPU fpsr" reverse-maps to x86 status/exception values and + * stores the values in "x86_status_word", "x86_status_word_accrued" + * and "FPU fpsr.quotient". + * + * So, "x86_status_word" and "x86_status_word_accrued" are not in + * correct bit positions and have x86 values, but "FPU fpsr.quotient" is at + * correct position. + * + * Note that it does not matter that the reverse-mapping is not exact + * (both SW_IE and SW_DE are mapped to ACCR_IOP, but ACCR_IOP maps to + * SW_IE only), the MacOS always sees the correct exception bits. + * + * Also note the usage of the fake BSUN flag SW_FAKE_BSUN. If you change + * the x86 FPU code, you must make sure that you don't generate any FPU + * stack faults. + * + * + * x86 co-processor initialization: + * + * Bit Code Use + * 0 IM Invalid operation exception mask 1 Disabled + * 1 DM Denormalized operand exception mask 1 Disabled + * 2 ZM Zerodivide exception mask 1 Disabled + * 3 OM Overflow exception mask 1 Disabled + * 4 UM Underflow exception mask 1 Disabled + * 5 PM Precision exception mask 1 Disabled + * 6 - - - - + * 7 IEM Interrupt enable mask 0 Enabled + * 8 PC Precision control\ 1 - 64 bits + * 9 PC Precision control/ 1 / + * 10 RC Rounding control\ 0 - Nearest even + * 11 RC Rounding control/ 0 / + * 12 IC Infinity control 1 Affine + * 13 - - - - + * 14 - - - - + * 15 - - - - + * + * + * TODO: + * - Exceptions are not implemented. + * - All tbyte variables should be aligned to 16-byte boundaries. + * (for best efficiency). + * - FTRAPcc code looks like broken. + * - If USE_3_BIT_QUOTIENT is 0, exceptions should be checked after + * float -> int rounding (frem,fmod). + * - The speed can be greatly improved. Do this only after you are sure + * that there are no major bugs. + * - Support for big-endian byte order (but all assembly code needs to + * be rewritten anyway) + * I have some non-portable code like *((uae_u16 *)&m68k_dreg(regs, reg)) = newv; + * Sorry about that, you need to change these. I could do it myself, but better + * not, I would have no way to test them out. + * I tried to mark all spots with a comment TODO_BIGENDIAN. + * - to_double() may need renormalization code. Or then again, maybe not. + * - Signaling NANs should be handled better. The current mapping of + * signaling nan exception to denormalized operand exception is only + * based on the idea that the (possible) handler sees that "something + * seriously wrong" and takes the same action. Should not really get (m)any + * of those since normalization is handled on to_exten() + * + */ + +# include +# include + +#include "sysdeps.h" +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" +#include "fpu/fpu_x86.h" +#include "fpu/fpu_x86_asm.h" + +/* Global FPU context */ +fpu_t fpu; + +/* -------------------------------------------------------------------------- */ +/* --- Native Support --- */ +/* -------------------------------------------------------------------------- */ + +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#include "fpu/flags.cpp" +#include "fpu/exceptions.cpp" +#include "fpu/rounding.cpp" + +/* -------------------------------------------------------------------------- */ +/* --- Scopes Definition --- */ +/* -------------------------------------------------------------------------- */ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* ---------------------------- Compatibility ---------------------------- */ + +#define BYTE uint8 +#define WORD uint16 +#define DWORD uint32 +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +/* ---------------------------- Configuration ---------------------------- */ + +/* +If USE_3_BIT_QUOTIENT is set to 1, FREM and FMOD use a faster version +with only 3 quotient bits (those provided by the x86 FPU). If set to 0, +they calculate the same 7 bits that m68k does. It seems (as for now) that +3 bits suffice for all Mac programs I have tried. + +If you decide that you need all 7 bits (USE_3_BIT_QUOTIENT is 0), +consider checking the host exception flags after FISTP (search for +"TODO:Quotient". The result may be too large to fit into a dword. +*/ +/* +gb-- I only tested the following configurations: + USE_3_BIT_QUOTIENT 1 -- still changes to apply if no 3-bit quotient + FPU_DEBUG 1 or 0 + USE_CONSISTENCY_CHECKING 0 + I3_ON_ILLEGAL_FPU_OP 0 -- and this won't change + I3_ON_FTRAPCC 0 -- and this won't change +*/ +#define USE_3_BIT_QUOTIENT 1 + +//#define FPU_DEBUG 0 -- now defined in "fpu/fpu.h" +#define USE_CONSISTENCY_CHECKING 0 + +#define I3_ON_ILLEGAL_FPU_OP 0 +#define I3_ON_FTRAPCC 0 + +/* ---------------------------- Debugging ---------------------------- */ + +PUBLIC void FFPU fpu_dump_registers(void) +{ + for (int i = 0; i < 8; i++){ + printf ("FP%d: %g ", i, fpu_get_register(i)); + if ((i & 3) == 3) + printf ("\n"); + } +} + +PUBLIC void FFPU fpu_dump_flags(void) +{ + printf ("N=%d Z=%d I=%d NAN=%d\n", + (get_fpsr() & FPSR_CCB_NEGATIVE) != 0, + (get_fpsr() & FPSR_CCB_ZERO)!= 0, + (get_fpsr() & FPSR_CCB_INFINITY) != 0, + (get_fpsr() & FPSR_CCB_NAN) != 0); +} + +#include "debug.h" + +#if FPU_DEBUG + +PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual) +{ + char bb[10]; + int32 i, bytes = min(actual,100); + + *b = 0; + for (i=0; i= 10) _ix = 0; + + sprintf( _s[_ix], "%.04f", (float)f ); + return( _s[_ix] ); +} + +PUBLIC void FFPU dump_registers(const char *s) +{ + char b[512]; + + sprintf( + b, + "%s: %s, %s, %s, %s, %s, %s, %s, %s\r\n", + s, + etos(FPU registers[0]), + etos(FPU registers[1]), + etos(FPU registers[2]), + etos(FPU registers[3]), + etos(FPU registers[4]), + etos(FPU registers[5]), + etos(FPU registers[6]), + etos(FPU registers[7]) + ); + D(bug((char*)b)); +} + +#else + +PUBLIC void FFPU dump_registers(const char *) +{ +} + +PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32) +{ +} + +#endif + + +/* ---------------------------- FPU consistency ---------------------------- */ + +#if USE_CONSISTENCY_CHECKING +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void) +{ +/* _asm { + FNSTSW checked_sw_atstart + } */ + __asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_atstart)); +} + +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name) +{ + uae_u16 checked_sw_atend; +// _asm FNSTSW checked_sw_atend + __asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_attend)); + char msg[256]; + + // Check for FPU stack overflows/underflows. + if( (checked_sw_atend & 0x3800) != (checked_sw_atstart & 0x3800) ) { + wsprintf( + msg, + "FPU stack leak at %s, %X, %X\r\n", + name, + (int)(checked_sw_atstart & 0x3800) >> 11, + (int)(checked_sw_atend & 0x3800) >> 11 + ); + OutputDebugString(msg); + } + + // Observe status mapping. + /* + if(checked_sw_atstart != 0x400 || checked_sw_atend != 0x400) { + wsprintf( + msg, "Op %s, x86_status_word before=%X, x86_status_word after=%X\r\n", + name, (int)checked_sw_atstart, (int)checked_sw_atend + ); + OutputDebugString(msg); + } + */ +} +#else +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void) +{ +} + +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *) +{ +} +#endif + + +/* ---------------------------- Status byte ---------------------------- */ + +// Map x86 FXAM codes -> m68k fpu status byte +#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3) +#define SW_Z (SW_C3) +#define SW_I (SW_C0|SW_C2) +#define SW_NAN (SW_C0) +#define SW_FINITE (SW_C2) +#define SW_EMPTY_REGISTER (SW_C0|SW_C3) +#define SW_DENORMAL (SW_C2|SW_C3) +#define SW_UNSUPPORTED (0) +#define SW_N (SW_C1) + +// Initial state after boot, reset and frestore(null frame) +#define SW_INITIAL SW_FINITE + + +/* ---------------------------- Status functions ---------------------------- */ + +PRIVATE void inline FFPU SET_BSUN_ON_NAN () +{ + if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) { + x86_status_word |= SW_FAKE_BSUN; + x86_status_word_accrued |= SW_IE; + } +} + +PRIVATE void inline FFPU build_ex_status () +{ + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } +} + +// TODO_BIGENDIAN; all of these. +/* ---------------------------- Type functions ---------------------------- */ + +/* +When the FPU creates a NAN, the NAN always contains the same bit pattern +in the mantissa. All bits of the mantissa are ones for any precision. +When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa. +*/ +PRIVATE inline void FFPU MAKE_NAN (fpu_register & f) +{ + // Make it non-signaling. + uae_u8 * p = (uae_u8 *) &f; + memset( p, 0xFF, sizeof(fpu_register) - 1 ); + p[9] = 0x7F; +} + +/* +For single- and double-precision infinities the fraction is a zero. +For extended-precision infinities, the mantissa�s MSB, the explicit +integer bit, can be either one or zero. +*/ +PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f) +{ + uae_u8 * p = (uae_u8 *) &f; + if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { + if ((*((uae_u32 *)&p[0]) == 0) && + ((*((uae_u32 *)&p[4]) & 0x7FFFFFFF) == 0)) + return(1); + } + return(0); +} + +PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f) +{ + uae_u8 * p = (uae_u8 *) &f; + if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { + if ((*((uae_u32 *)&p[0]) == 0) && + ((*((uae_u32 *)&p[4]) & 0x7FFFFFFF) != 0)) + return(1); + } + return(0); +} + +PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f) +{ + uae_u8 * p = (uae_u8 *) &f; + return *((uae_u32 *)p) == 0 && + *((uae_u32 *)&p[4]) == 0 && + ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0; +} + +PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f) +{ + uae_u8 * p = (uae_u8 *) &f; + memset( p, 0, sizeof(fpu_register)-2 ); + *((uae_u16 *)&p[8]) = 0x7FFF; +} + +PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f) +{ + uae_u8 * p = (uae_u8 *) &f; + memset( p, 0, sizeof(fpu_register)-2 ); + *((uae_u16 *)&p[8]) = 0xFFFF; +} + +PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) +{ + uae_u32 * const p = (uae_u32 *) &f; + memset( p, 0, sizeof(fpu_register) ); +} + +PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) +{ + uae_u32 * const p = (uae_u32 *) &f; + memset( p, 0, sizeof(fpu_register) ); + *((uae_u32 *)&p[4]) = 0x80000000; +} + +PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) +{ + uae_u8 * p = (uae_u8 *) &f; + return( (p[9] & 0x80) != 0 ); +} + + +/* ---------------------------- Conversions ---------------------------- */ + +PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + +/* _asm { + MOV ESI, [f] + FILD DWORD PTR [x] + FSTP TBYTE PTR [ESI] + } */ + + __asm__ __volatile__("fildl %1\n\tfstpt %0" : "=m" (f) : "m" (x)); + D(bug("signed_to_extended (%X) = %s\r\n",(int)x,etos(f))); + FPU_CONSISTENCY_CHECK_STOP("signed_to_extended"); +} + +PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + volatile uae_s32 tmp; + volatile WORD sw_temp; + +/* _asm { + MOV EDI, [f] + FLD TBYTE PTR [EDI] + FISTP DWORD PTR tmp + FNSTSW sw_temp + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fistpl %0\n" + "fnstsw %1\n" + : "=m" (tmp), "=m" (sw_temp) + : "m" (f) + ); + + if(sw_temp & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; + // Setting the value to zero might not be the right way to go, + // but I'll leave it like this for now. + tmp = 0; + } + if(sw_temp & SW_PE) { + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; + } + } + + D(bug("extended_to_signed_32 (%s) = %X\r\n",etos(f),(int)tmp)); + FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_32"); + return tmp; +} + +PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + volatile uae_s16 tmp; + volatile WORD sw_temp; + +/* _asm { + MOV EDI, [f] + FLD TBYTE PTR [EDI] + FISTP WORD PTR tmp + FNSTSW sw_temp + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fistp %0\n" + "fnstsw %1\n" + : "=m" (tmp), "=m" (sw_temp) + : "m" (f) + ); + + if(sw_temp & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; + tmp = 0; + } + if(sw_temp & SW_PE) { + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; + } + } + + D(bug("extended_to_signed_16 (%s) = %X\r\n",etos(f),(int)tmp)); + FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_16"); + return tmp; +} + +PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + volatile uae_s16 tmp; + volatile WORD sw_temp; + +/* _asm { + MOV EDI, [f] + FLD TBYTE PTR [EDI] + FISTP WORD PTR tmp + FNSTSW sw_temp + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fistp %0\n" + "fnstsw %1\n" + : "=m" (tmp), "=m" (sw_temp) + : "m" (f) + ); + + if(sw_temp & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR. + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; + tmp = 0; + } + if(sw_temp & SW_PE) { + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; + } + } + + if(tmp > 127 || tmp < -128) { // OPERR + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; + } + + D(bug("extended_to_signed_8 (%s) = %X\r\n",etos(f),(int)tmp)); + FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_8"); + return (uae_s8)tmp; +} + +PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + +/* _asm { + MOV EDI, [f] + FLD QWORD PTR [x] + FSTP TBYTE PTR [EDI] + } */ + + __asm__ __volatile__( + "fldl %1\n" + "fstpt %0\n" + : "=m" (f) + : "m" (x) + ); + + FPU_CONSISTENCY_CHECK_STOP("double_to_extended"); +} + +PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + double result; + +/* _asm { + MOV ESI, [f] + FLD TBYTE PTR [ESI] + FSTP QWORD PTR result + } */ + + __asm__ __volatile__( + "fldt %1\n" + "fstpl %0\n" + : "=m" (result) + : "m" (f) + ); + + FPU_CONSISTENCY_CHECK_STOP("extended_to_double"); + return result; +} + +PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [f] + FLD DWORD PTR src + FSTP TBYTE PTR [ESI] + } */ + + __asm__ __volatile__( + "flds %1\n" + "fstpt %0\n" + : "=m" (f) + : "m" (src) + ); + + D(bug("to_single (%X) = %s\r\n",src,etos(f))); + FPU_CONSISTENCY_CHECK_STOP("to_single"); +} + +// TODO_BIGENDIAN +PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + uae_u32 *p = (uae_u32 *)&f; + + uae_u32 sign = (wrd1 & 0x80000000) >> 16; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + p[0] = wrd3; + p[1] = wrd2; + *((uae_u16 *)&p[2]) = (uae_u16)(sign | exp); + + D(bug("to_exten_no_normalize (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f))); + FPU_CONSISTENCY_CHECK_STOP("to_exten_no_normalize"); +} + +PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + uae_u32 *p = (uae_u32 *)&f; + + uae_u32 sign = (wrd1 & 0x80000000) >> 16; + uae_u32 exp = (wrd1 >> 16) & 0x7fff; + + // The explicit integer bit is not set, must normalize. + // Don't do it for zeroes, infinities or nans. + if( (wrd2 & 0x80000000) == 0 && exp != 0 && exp != 0x7FFF ) { + D(bug("to_exten denormalized mantissa (%X,%X,%X)\r\n",wrd1,wrd2,wrd3)); + if( wrd2 | wrd3 ) { + // mantissa, not fraction. + uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; + while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) { + man <<= 1; + exp--; + } + wrd2 = (uae_u32)( man >> 32 ); + wrd3 = (uae_u32)( man & 0xFFFFFFFF ); + if( exp == 0 || (wrd2 & 0x80000000) == 0 ) { + // underflow + wrd2 = wrd3 = exp = 0; + sign = 0; + } + } else { + if(exp != 0x7FFF && exp != 0) { + // Make a non-signaling nan. + exp = 0x7FFF; + sign = 0; + wrd2 = 0x80000000; + } + } + } + + p[0] = wrd3; + p[1] = wrd2; + *((uae_u16 *)&p[2]) = (uae_u16)(sign | exp); + + D(bug("to_exten (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f))); + FPU_CONSISTENCY_CHECK_STOP("to_exten"); +} + +PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + + // gb-- make GCC happy + union { + uae_u64 q; + uae_u32 l[2]; + } src; + + // Should renormalize if needed. I'm not sure that x86 and m68k FPU's + // do it the sama way. This should be extremely rare however. + // to_exten() is often called with denormalized values. + + src.l[0] = wrd2; + src.l[1] = wrd1; + +/* _asm { + FLD QWORD PTR src + MOV EDI, [f] + FSTP TBYTE PTR [EDI] + } */ + + __asm__ __volatile__( + "fldl %1\n" + "fstpt %0\n" + : "=m" (f) + : "m" (src.q) + ); + + D(bug("to_double (%X,%X) = %s\r\n",wrd1,wrd2,etos(f))); + FPU_CONSISTENCY_CHECK_STOP("to_double"); +} + +PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) +{ + FPU_CONSISTENCY_CHECK_START(); + volatile uae_u32 dest; + volatile WORD sw_temp; + +/* _asm { + MOV EDI, [f] + FLD TBYTE PTR [EDI] + FSTP DWORD PTR dest + FNSTSW sw_temp + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fstps %0\n" + "fnstsw %1\n" + : "=m" (dest), "=m" (sw_temp) + : "m" (f) + ); + + sw_temp &= SW_EXCEPTION_MASK; + if(sw_temp) { +// _asm FNCLEX + asm("fnclex"); + x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp; + x86_status_word_accrued |= sw_temp; + } + + D(bug("from_single (%s) = %X\r\n",etos(f),dest)); + FPU_CONSISTENCY_CHECK_STOP("from_single"); + return dest; +} + +// TODO_BIGENDIAN +PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) +{ + FPU_CONSISTENCY_CHECK_START(); + uae_u32 *p = (uae_u32 *)&f; + *wrd3 = p[0]; + *wrd2 = p[1]; + *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; + + D(bug("from_exten (%s) = %X,%X,%X\r\n",etos(f),*wrd1,*wrd2,*wrd3)); + FPU_CONSISTENCY_CHECK_STOP("from_exten"); +} + +PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) +{ + FPU_CONSISTENCY_CHECK_START(); + volatile uae_u32 dest[2]; + volatile WORD sw_temp; + +/* _asm { + MOV EDI, [f] + FLD TBYTE PTR [EDI] + FSTP QWORD PTR dest + FNSTSW sw_temp + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fstpl %0\n" + "fnstsw %1\n" + : "=m" (dest), "=m" (sw_temp) + : "m" (f) + ); + + sw_temp &= SW_EXCEPTION_MASK; + if(sw_temp) { +// _asm FNCLEX + asm("fnclex"); + x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp; + x86_status_word_accrued |= sw_temp; + } + + // TODO: There is a partial memory stall, nothing happens until FSTP retires. + // On PIII, could use MMX move w/o any penalty. + *wrd2 = dest[0]; + *wrd1 = dest[1]; + + D(bug("from_double (%s) = %X,%X\r\n",etos(f),dest[1],dest[0])); + FPU_CONSISTENCY_CHECK_STOP("from_double"); +} + +PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fmove"); +} + +PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fsmove"); +} + +PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fdmove"); +} + +/* +PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FSTP TBYTE PTR [EDI] + } + FPU_CONSISTENCY_CHECK_STOP("do_fmove_no_status"); +} +*/ + + +/* ---------------------------- Operations ---------------------------- */ + +PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FRNDINT + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "frndint\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fint"); +} + +PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + WORD cw_temp; + +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FSTCW cw_temp + and cw_temp, ~X86_ROUNDING_MODE + or cw_temp, CW_RC_ZERO + FLDCW cw_temp + FLD TBYTE PTR [ESI] + FRNDINT + FXAM + FNSTSW x86_status_word + FLDCW x86_control_word + FSTP TBYTE PTR [EDI] + } */ + + __asm__ __volatile__( + "fstcw %0\n" + "andl $(~X86_ROUNDING_MODE), %0\n" + "orl $CW_RC_ZERO, %0\n" + "fldcw %0\n" + "fldt %3\n" + "frndint\n" + "fxam \n" + "fnstsw %1\n" + "fldcw %4\n" + "fstpt %2\n" + : "+m" (cw_temp), "=m" (x86_status_word), "=m" (dest) + : "m" (src), "m" (x86_control_word) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fintrz"); +} + +PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FSQRT + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + + __asm__ __volatile__( + "fldt %2\n" + "fsqrt \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsqrt"); +} + +PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fsqrt \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fssqrt"); +} + +PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fsqrt \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt"); +} + +PRIVATE void FFPU do_ftst ( fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + FLD TBYTE PTR [ESI] + FXAM + FNSTSW x86_status_word + FSTP ST(0) + } */ + + __asm__ __volatile__( + "fldt %1\n" + "fxam \n" + "fnstsw %0\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word) + : "m" (src) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_ftst"); +} + +// These functions are calculated in 53 bits accuracy only. +// Exception checking is not complete. +PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = sinh(x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fsinh"); +} + +PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = log (x + 1.0); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_flognp1"); +} + +PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = exp (x) - 1.0; + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fetoxm1"); +} + +PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = tanh (x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_ftanh"); +} + +PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = atan (x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fatan"); +} + +PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = asin (x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fasin"); +} + +PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = log ((1 + x) / (1 - x)) / 2; + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fatanh"); +} + +PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = exp (x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fetox"); +} + +PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = pow(2.0, x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_ftwotox"); +} + +PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = pow(10.0, x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_ftentox"); +} + +PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = log (x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_flogn"); +} + +PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = log10 (x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_flog10"); +} + +PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = log (x) / log (2.0); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_flog2"); +} + +PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = acos(x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_facos"); +} + +PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + double x, y; + x = extended_to_double( src ); + y = cosh(x); + double_to_extended( y, dest ); + do_ftst( dest ); + FPU_CONSISTENCY_CHECK_STOP("do_fcosh"); +} + +PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FSIN + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fsin \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsin"); +} + +// TODO: Should check for out-of-range condition (partial tangent) +PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FPTAN + FSTP ST(0) ; pop 1.0 (the 8087/287 compatibility thing) + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fptan \n" + "fstp %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE - SW_UE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_ftan"); +} + +PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FABS + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fabs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fabs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fabs"); +} + +PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fabs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fabs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsabs"); +} + +PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fabs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fabs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdabs"); +} + +PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FCHS + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fchs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fchs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fneg"); +} + +PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fchs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fchs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsneg"); +} + +PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fchs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fchs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdneg"); +} + +PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FCOS + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fcos \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fcos"); +} + +PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FXTRACT + FSTP ST(0) ; pop mantissa + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fxtract\n" + "fstp %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fgetexp"); +} + +PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FXTRACT + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) ; pop exponent + } */ + __asm__ __volatile__( + "fldt %2\n" + "fxtract\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fgetman"); +} + +PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FDIV ST(0),ST(1) + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } */ + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fdiv %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdiv"); +} + +PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fdiv %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsdiv"); +} + +PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fdiv %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fddiv"); +} + +// The sign of the quotient is the exclusive-OR of the sign bits +// of the source and destination operands. +// Quotient Byte is loaded with the sign and least significant +// seven bits of the quotient. + +PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + + volatile uint16 status; + uae_u32 quot; +#if !USE_3_BIT_QUOTIENT + WORD cw_temp; +#endif + + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; + +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + +#if !USE_3_BIT_QUOTIENT + MOV CX, x86_control_word + AND CX, ~X86_ROUNDING_MODE + OR CX, CW_RC_ZERO + MOV cw_temp, CX + FLDCW cw_temp + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FDIV ST(0),ST(1) + FABS + FISTP DWORD PTR quot + FSTP ST(0) + FLDCW x86_control_word + // TODO:Quotient + // Should clear any possible exceptions here +#endif + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + +// loop until the remainder is not partial any more. +partial_loop: + FPREM + FNSTSW status + TEST status, SW_C2 + JNE partial_loop + + + FXAM + FNSTSW x86_status_word + + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } */ + +#if !USE_3_BIT_QUOTIENT + + __asm__ __volatile__( + "movl %6, %%ecx\n" // %6: x86_control_word (read) + "andl $(~X86_ROUNDING_MODE), %%ecx\n" + "orl $CW_RC_ZERO, %%ecx\n" + "movl %%ecx, %0\n" // %0: cw_temp (read/write) + "fldcw %0\n" + "fldt %5\n" + "fldt %4\n" + "fdiv %%st(1), %%st(0)\n" + "fabs \n" + "fistpl %1\n" // %1: quot (read/write) + "fstp %%st(0)\n" + "fldcw %6\n" + "fldt %5\n" + "fldt %4\n" + "0:\n" // partial_loop + "fprem \n" + "fnstsw %2\n" // %2: status (read/write) + "testl $SW_C2, %2\n" + "jne 0b\n" + "fxam \n" + "fnstsw %3\n" // %3: x86_status_word (write) + "fstpt %4\n" + "fstp %%st(0)\n" + : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_control_word) + : "ecx" + ); + +#else + + __asm__ __volatile__( + "fldt %3\n" + "fldt %2\n" + "0:\n" // partial_loop + "fprem \n" + "fnstsw %0\n" // %0: status (read/write) + "testl $SW_C2, %0\n" + "jne 0b\n" + "fxam \n" + "fnstsw %1\n" // %1: x86_status_word (write) + "fstpt %2\n" + "fstp %%st(0)\n" + : "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + +#endif + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; + } + +#if USE_3_BIT_QUOTIENT + // SW_C1 Set to least significant bit of quotient (Q0). + // SW_C3 Set to bit 1 (Q1) of the quotient. + // SW_C0 Set to bit 2 (Q2) of the quotient. + quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9); + FPU fpsr.quotient = (sign | quot) << 16; +#else + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; +#endif + + FPU_CONSISTENCY_CHECK_STOP("do_fmod"); +} + +PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + + volatile uint16 status; + uae_u32 quot; +#if !USE_3_BIT_QUOTIENT + WORD cw_temp; +#endif + + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; + +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + +#if !USE_3_BIT_QUOTIENT + MOV CX, x86_control_word + AND CX, ~X86_ROUNDING_MODE + OR CX, CW_RC_NEAR + MOV cw_temp, CX + FLDCW cw_temp + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FDIV ST(0),ST(1) + FABS + FISTP DWORD PTR quot + FSTP ST(0) + FLDCW x86_control_word + // TODO:Quotient + // Should clear any possible exceptions here +#endif + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + +// loop until the remainder is not partial any more. +partial_loop: + FPREM1 + FNSTSW status + TEST status, SW_C2 + JNE partial_loop + + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } */ + +#if !USE_3_BIT_QUOTIENT + + __asm__ __volatile__( + "movl %6, %%ecx\n" // %6: x86_control_word (read) + "andl $(~X86_ROUNDING_MODE), %%ecx\n" + "orl $CW_RC_NEAR, %%ecx\n" + "movl %%ecx, %0\n" // %0: cw_temp (read/write) + "fldcw %0\n" + "fldt %5\n" + "fldt %4\n" + "fdiv %%st(1), %%st(0)\n" + "fabs \n" + "fistpl %1\n" // %1: quot (read/write) + "fstp %%st(0)\n" + "fldcw %6\n" + "fldt %5\n" + "fldt %4\n" + "0:\n" // partial_loop + "fprem1 \n" + "fnstsw %2\n" // %2: status (read/write) + "testl $SW_C2, %2\n" + "jne 0b\n" + "fxam \n" + "fnstsw %3\n" // %3: x86_status_word (write) + "fstpt %4\n" + "fstp %%st(0)\n" + : "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_control_word) + : "ecx" + ); + +#else + + __asm__ __volatile__( + "fldt %3\n" + "fldt %2\n" + "0:\n" // partial_loop + "fprem1 \n" + "fnstsw %0\n" // %0: status (read/write) + "testl $SW_C2, %0\n" + "jne 0b\n" + "fxam \n" + "fnstsw %1\n" // %1: x86_status_word (write) + "fstpt %2\n" + "fstp %%st(0)\n" + : "+m" (status), "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + +#endif + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; + } + +#if USE_3_BIT_QUOTIENT + // SW_C1 Set to least significant bit of quotient (Q0). + // SW_C3 Set to bit 1 (Q1) of the quotient. + // SW_C0 Set to bit 2 (Q2) of the quotient. + quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9); + FPU fpsr.quotient = (sign | quot) << 16; +#else + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; +#endif + + FPU_CONSISTENCY_CHECK_STOP("do_frem"); +} + +// Faster versions. The current rounding mode is already correct. +#if !USE_3_BIT_QUOTIENT +PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + + volatile uint16 status; + uae_u32 quot; + + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; + + _asm { + MOV ESI, [src] + MOV EDI, [dest] + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FDIV ST(0),ST(1) + FABS + FISTP DWORD PTR quot + FSTP ST(0) + // TODO:Quotient + // Should clear any possible exceptions here + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + +// loop until the remainder is not partial any more. +partial_loop: + FPREM + FNSTSW status + TEST status, SW_C2 + JNE partial_loop + + FXAM + FNSTSW x86_status_word + + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } + if(x86_status_word & SW_EXCEPTION_MASK) { + _asm FNCLEX + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; + } + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; + FPU_CONSISTENCY_CHECK_STOP("do_fmod_dont_set_cw"); +} + +PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + + volatile uint16 status; + uae_u32 quot; + + uae_u8 * dest_p = (uae_u8 *)&dest; + uae_u8 * src_p = (uae_u8 *)&src; + uae_u32 sign = (dest_p[9] ^ src_p[9]) & 0x80; + + _asm { + MOV ESI, [src] + MOV EDI, [dest] + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FDIV ST(0),ST(1) + FABS + FISTP DWORD PTR quot + FSTP ST(0) + // TODO:Quotient + // Should clear any possible exceptions here + + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + +// loop until the remainder is not partial any more. +partial_loop: + FPREM1 + FNSTSW status + TEST status, SW_C2 + JNE partial_loop + + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } + if(x86_status_word & SW_EXCEPTION_MASK) { + _asm FNCLEX + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE); + x86_status_word_accrued |= x86_status_word; + } + FPU fpsr.quotient = (sign | (quot&0x7F)) << 16; + FPU_CONSISTENCY_CHECK_STOP("do_frem_dont_set_cw"); +} +#endif //USE_3_BIT_QUOTIENT + +PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FADD + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fadd \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fadd"); +} + +PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fadd \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsadd"); +} + +PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fadd \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdadd"); +} + +PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FMUL + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fmul \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fmul"); +} + +PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fmul \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsmul"); +} + +PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fmul \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdmul"); +} + +PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + WORD cw_temp; +/* _asm { + FSTCW cw_temp + and cw_temp, ~X86_ROUNDING_PRECISION + or cw_temp, PRECISION_CONTROL_SINGLE + FLDCW cw_temp + + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FDIV ST(0),ST(1) + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + FLDCW x86_control_word + } */ + __asm__ __volatile__( + "fstcw %0\n" + "andl $(~X86_ROUNDING_PRECISION), %0\n" + "orl $PRECISION_CONTROL_SINGLE, %0\n" + "fldcw %0\n" + "fldt %3\n" + "fldt %2\n" + "fdiv %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %1\n" + "fstpt %2\n" + "fstp %%st(0)\n" + "fldcw %4\n" + : "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_control_word) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsgldiv"); +} + +PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FSCALE + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } */ + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fscale \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_UE - SW_OE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fscale"); +} + +PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + WORD cw_temp; + +/* _asm { + FSTCW cw_temp + and cw_temp, ~X86_ROUNDING_PRECISION + or cw_temp, PRECISION_CONTROL_SINGLE + FLDCW cw_temp + + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FMUL + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + + FLDCW x86_control_word + } */ + __asm__ __volatile__( + "fstcw %0\n" + "andl $(~X86_ROUNDING_PRECISION), %0\n" + "orl $PRECISION_CONTROL_SINGLE, %0\n" + "fldcw %0\n" + "fldt %3\n" + "fldt %2\n" + "fmul \n" + "fxam \n" + "fnstsw %1\n" + "fstpt %2\n" + "fldcw %4\n" + : "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest) + : "m" (src), "m" (x86_status_word) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsglmul"); +} + +PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FSUB ST(0),ST(1) + FXAM + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } */ + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fsub %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsub"); +} + +PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fsub %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fssub"); +} + +PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fsub %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdsub"); +} + +PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest_cos] + FLD TBYTE PTR [ESI] + FSINCOS + FSTP TBYTE PTR [EDI] + FXAM + MOV EDI, [dest_sin] + FNSTSW x86_status_word + FSTP TBYTE PTR [EDI] + FSTP ST(0) + } */ + __asm__ __volatile__( + "fldt %3\n" + "fsincos\n" + "fstpt %1\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %2\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "=m" (dest_cos), "=m" (dest_sin) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsincos"); +} + +PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + MOV ESI, [src] + MOV EDI, [dest] + FLD TBYTE PTR [ESI] + FLD TBYTE PTR [EDI] + FSUB ST(0),ST(1) + FXAM + FNSTSW x86_status_word + FSTP ST(0) + FSTP ST(0) + } */ + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fsub %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstp %%st(0)\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word) + : "m" (dest), "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fcmp"); +} + +// More or less original. Should be reviewed. +PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) +{ + FPU_CONSISTENCY_CHECK_START(); + + double d; + char *cp; + char str[100]; + + cp = str; + if (wrd1 & 0x80000000) + *cp++ = '-'; + *cp++ = (char)((wrd1 & 0xf) + '0'); + *cp++ = '.'; + *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); + *cp++ = 'E'; + if (wrd1 & 0x40000000) + *cp++ = '-'; + *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); + *cp = 0; + sscanf(str, "%le", &d); + + D(bug("to_pack str = %s\r\n",str)); + + D(bug("to_pack(%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)d)); + + FPU_CONSISTENCY_CHECK_STOP("to_pack"); + + return d; +} + +// More or less original. Should be reviewed. +PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) +{ + FPU_CONSISTENCY_CHECK_START(); + + int i; + int t; + char *cp; + char str[100]; + int exponent_digit_count = 0; + + sprintf(str, "%.16e", src); + + D(bug("from_pack(%.04f,%s)\r\n",(float)src,str)); + + cp = str; + *wrd1 = *wrd2 = *wrd3 = 0; + if (*cp == '-') { + cp++; + *wrd1 = 0x80000000; + } + if (*cp == '+') + cp++; + *wrd1 |= (*cp++ - '0'); + if (*cp == '.') + cp++; + for (i = 0; i < 8; i++) { + *wrd2 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd2 |= *cp++ - '0'; + } + for (i = 0; i < 8; i++) { + *wrd3 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd3 |= *cp++ - '0'; + } + if (*cp == 'e' || *cp == 'E') { + cp++; + if (*cp == '-') { + cp++; + *wrd1 |= 0x40000000; + } + if (*cp == '+') + cp++; + t = 0; + for (i = 0; i < 3; i++) { + if (*cp >= '0' && *cp <= '9') { + t = (t << 4) | (*cp++ - '0'); + exponent_digit_count++; + } + } + *wrd1 |= t << 16; + } + + D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); + + WORD sw_temp; +// _asm FNSTSW sw_temp + __asm__ __volatile__("fnstsw %0" : "=m" (sw_temp)); + if(sw_temp & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + if(sw_temp & SW_PE) { + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; + } + } + + /* + OPERR is set if the k-factor > + 17 or the magnitude of + the decimal exponent exceeds three digits; + cleared otherwise. + */ + if(exponent_digit_count > 3) { + x86_status_word |= SW_IE; + x86_status_word_accrued |= SW_IE; + } + + FPU_CONSISTENCY_CHECK_STOP("from_pack"); +} + +PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) +{ + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra)); + // dump_first_bytes( regs.pc_p-4, 16 ); + + if ((extra & 0x4000) == 0) { + memcpy( &src, &FPU registers[(extra >> 10) & 7], sizeof(fpu_register) ); +// do_fmove_no_status( src, FPU registers[(extra >> 10) & 7] ); + return 1; + } + + int mode = (opcode >> 3) & 7; + int reg = opcode & 7; + int size = (extra >> 10) & 7; + uae_u32 ad = 0; + + // D(bug("get_fp_value mode=%d, reg=%d, size=%d\r\n",(int)mode,(int)reg,(int)size)); + + switch ((uae_u8)mode) { + case 0: + switch ((uae_u8)size) { + case 6: + signed_to_extended( (uae_s32)(uae_s8) m68k_dreg (regs, reg), src ); + break; + case 4: + signed_to_extended( (uae_s32)(uae_s16) m68k_dreg (regs, reg), src ); + break; + case 0: + signed_to_extended( (uae_s32) m68k_dreg (regs, reg), src ); + break; + case 1: + to_single( m68k_dreg (regs, reg), src ); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + break; + case 4: + ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch ((uae_u8)reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: { + uaecptr tmppc = m68k_getpc (); + uae_u16 tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + } + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + + /* + +0000 000004 FSCALE.B #$01,FP2 | F23C 5926 0001 + F23C 1111001000111100 + 5926 0101100100100110 + 0001 0000000000000001 + mode = 7 + reg = 4 + size = 6 + */ + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + + if(size == 6) ad++; + + // May be faster on a PII(I), sz2[size] is already in register + // ad += sz2[size] - sz1[size]; + + break; + default: + return 0; + } + } + + switch ((uae_u8)size) { + case 0: + signed_to_extended( (uae_s32) get_long (ad), src ); + break; + case 1: + to_single( get_long (ad), src ); + break; + + case 2:{ + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + to_exten( wrd1, wrd2, wrd3, src ); + } + break; + case 3:{ + uae_u32 wrd1, wrd2, wrd3; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + double_to_extended( to_pack(wrd1, wrd2, wrd3), src ); + } + break; + case 4: + signed_to_extended( (uae_s32)(uae_s16) get_word(ad), src ); + break; + case 5:{ + uae_u32 wrd1, wrd2; + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + to_double(wrd1, wrd2, src); + } + break; + case 6: + signed_to_extended( (uae_s32)(uae_s8) get_byte(ad), src ); + break; + default: + return 0; + } + + switch (mode) { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + // D(bug("get_fp_value result = %.04f\r\n",(float)src)); + + return 1; +} + +PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) +{ + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra)); + + if ((extra & 0x4000) == 0) { + int dest_reg = (extra >> 10) & 7; + do_fmove( FPU registers[dest_reg], value ); + build_ex_status(); + return 1; + } + + int mode = (opcode >> 3) & 7; + int reg = opcode & 7; + int size = (extra >> 10) & 7; + uae_u32 ad = 0xffffffff; + + // Clear exception status + x86_status_word &= ~SW_EXCEPTION_MASK; + + switch ((uae_u8)mode) { + case 0: + switch ((uae_u8)size) { + case 6: + *((uae_u8 *)&m68k_dreg(regs, reg)) = extended_to_signed_8(value); + break; + case 4: + // TODO_BIGENDIAN + *((uae_u16 *)&m68k_dreg(regs, reg)) = extended_to_signed_16(value); + break; + case 0: + m68k_dreg (regs, reg) = extended_to_signed_32(value); + break; + case 1: + m68k_dreg (regs, reg) = from_single(value); + break; + default: + return 0; + } + return 1; + case 1: + return 0; + case 2: + ad = m68k_areg (regs, reg); + break; + case 3: + ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); + break; + case 5: + ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch ((uae_u8)reg) { + case 0: + ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + ad = next_ilong(); + break; + case 2: + ad = m68k_getpc (); + ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: { + uaecptr tmppc = m68k_getpc (); + uae_u16 tmp = (uae_u16)next_iword(); + ad = get_disp_ea_020 (tmppc, tmp); + } + break; + case 4: + ad = m68k_getpc (); + m68k_setpc (ad + sz2[size]); + break; + default: + return 0; + } + } + switch ((uae_u8)size) { + case 0: + put_long (ad, (uae_s32) extended_to_signed_32(value)); + break; + case 1: + put_long (ad, from_single(value)); + break; + case 2: { + uae_u32 wrd1, wrd2, wrd3; + from_exten(value, &wrd1, &wrd2, &wrd3); + + x86_status_word &= ~SW_EXCEPTION_MASK; + if(wrd3) { // TODO: not correct! Just a "smart" guess. + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; + } + + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + } + break; + case 3: { + uae_u32 wrd1, wrd2, wrd3; + from_pack(extended_to_double(value), &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + } + break; + case 4: + put_word(ad, extended_to_signed_16(value)); + break; + case 5:{ + uae_u32 wrd1, wrd2; + from_double(value, &wrd1, &wrd2); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + } + break; + case 6: + put_byte(ad, extended_to_signed_8(value)); + + break; + default: + return 0; + } + return 1; +} + +PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) +{ + int mode = (opcode >> 3) & 7; + int reg = opcode & 7; + switch ( (uae_u8)mode ) { + case 0: + case 1: + if( (opcode & 0xFF00) == 0xF300 ) { + // fsave, frestore + m68k_setpc (m68k_getpc () - 2); + } else { + m68k_setpc (m68k_getpc () - 4); + } + op_illg (opcode); + dump_registers( "END "); + return 0; + case 2: + *ad = m68k_areg (regs, reg); + break; + case 3: + *ad = m68k_areg (regs, reg); + break; + case 4: + *ad = m68k_areg (regs, reg); + break; + case 5: + *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); + break; + case 6: + *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch ( (uae_u8)reg ) { + case 0: + *ad = (uae_s32) (uae_s16) next_iword(); + break; + case 1: + *ad = next_ilong(); + break; + case 2: + *ad = m68k_getpc (); + *ad += (uae_s32) (uae_s16) next_iword(); + break; + case 3: { + uaecptr tmppc = m68k_getpc (); + uae_u16 tmp = (uae_u16)next_iword(); + *ad = get_disp_ea_020 (tmppc, tmp); + } + break; + default: + if( (opcode & 0xFF00) == 0xF300 ) { + // fsave, frestore + m68k_setpc (m68k_getpc () - 2); + } else { + m68k_setpc (m68k_getpc () - 4); + } + op_illg (opcode); + dump_registers( "END "); + return 0; + } + } + return 1; +} + +#if FPU_DEBUG +#define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x) +#else +#define CONDRET(s,x) return (x) +#endif + +PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) +{ + +#define N (x86_status_word & SW_N) +#define Z ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_Z) +#define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I)) +#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN) + + switch (condition & 0x1f) { + // Common Tests, no BSUN + case 0x01: + CONDRET("Equal",Z); + case 0x0e: + CONDRET("Not Equal",!Z); + + // IEEE Nonaware Tests, BSUN + case 0x12: + SET_BSUN_ON_NAN(); + CONDRET("Greater Than",!(NotANumber || Z || N)); + case 0x1d: + SET_BSUN_ON_NAN(); + CONDRET("Not Greater Than",NotANumber || Z || N); + case 0x13: + SET_BSUN_ON_NAN(); + CONDRET("Greater Than or Equal",Z || !(NotANumber || N)); + case 0x1c: + SET_BSUN_ON_NAN(); + CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N)); + case 0x14: + SET_BSUN_ON_NAN(); + CONDRET("Less Than",N && !(NotANumber || Z)); + case 0x1b: + SET_BSUN_ON_NAN(); + CONDRET("Not Less Than",NotANumber || Z || !N); + case 0x15: + SET_BSUN_ON_NAN(); + CONDRET("Less Than or Equal",Z || (N && !NotANumber)); + case 0x1a: + SET_BSUN_ON_NAN(); + CONDRET("Not Less Than or Equal",NotANumber || !(N || Z)); + case 0x16: + SET_BSUN_ON_NAN(); + CONDRET("Greater or Less Than",!(NotANumber || Z)); + case 0x19: + SET_BSUN_ON_NAN(); + CONDRET("Not Greater or Less Than",NotANumber || Z); + case 0x17: + CONDRET("Greater, Less or Equal",!NotANumber); + case 0x18: + SET_BSUN_ON_NAN(); + CONDRET("Not Greater, Less or Equal",NotANumber); + + // IEEE Aware Tests, no BSUN + case 0x02: + CONDRET("Ordered Greater Than",!(NotANumber || Z || N)); + case 0x0d: + CONDRET("Unordered or Less or Equal",NotANumber || Z || N); + case 0x03: + CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N)); + case 0x0c: + CONDRET("Unordered or Less Than",NotANumber || (N && !Z)); + case 0x04: + CONDRET("Ordered Less Than",N && !(NotANumber || Z)); + case 0x0b: + CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N); + case 0x05: + CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber)); + case 0x0a: + CONDRET("Unordered or Greater Than",NotANumber || !(N || Z)); + case 0x06: + CONDRET("Ordered Greater or Less Than",!(NotANumber || Z)); + case 0x09: + CONDRET("Unordered or Equal",NotANumber || Z); + case 0x07: + CONDRET("Ordered",!NotANumber); + case 0x08: + CONDRET("Unordered",NotANumber); + + // Miscellaneous Tests, no BSUN + case 0x00: + CONDRET("False",0); + case 0x0f: + CONDRET("True",1); + + // Miscellaneous Tests, BSUN + case 0x10: + SET_BSUN_ON_NAN(); + CONDRET("Signaling False",0); + case 0x1f: + SET_BSUN_ON_NAN(); + CONDRET("Signaling True",1); + case 0x11: + SET_BSUN_ON_NAN(); + CONDRET("Signaling Equal",Z); + case 0x1e: + SET_BSUN_ON_NAN(); + CONDRET("Signaling Not Equal",!Z); + } + CONDRET("",-1); + +#undef N +#undef Z +#undef I +#undef NotANumber + +} + +PUBLIC void REGPARAM2 FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra) +{ + uaecptr pc = (uae_u32) m68k_getpc (); + uae_s32 disp = (uae_s32) (uae_s16) next_iword(); + int cc; + + D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + cc = fpp_cond(opcode, extra & 0x3f); + if (cc < 0) { + m68k_setpc (pc - 4); + op_illg (opcode); + } else if (!cc) { + int reg = opcode & 0x7; + + // TODO_BIGENDIAN + uae_u16 newv = (uae_u16)(m68k_dreg (regs, reg) & 0xffff) - 1; + *((uae_u16 *)&m68k_dreg(regs, reg)) = newv; + + if (newv != 0xffff) + m68k_setpc (pc + disp); + } +} + +PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) +{ + uae_u32 ad; + int cc; + + D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + + cc = fpp_cond(opcode, extra & 0x3f); + if (cc < 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } else if ((opcode & 0x38) == 0) { + // TODO_BIGENDIAN + m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | + (cc ? 0xff : 0x00); + } else { + if (get_fp_ad(opcode, &ad)) { + put_byte(ad, cc ? 0xff : 0x00); + } + } +} + +PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +{ + int cc; + + D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + +#if I3_ON_FTRAPCC +#error "FIXME: _asm int 3" + _asm int 3 +#endif + + // This must be broken. + cc = fpp_cond(opcode, extra & 0x3f); + + if (cc < 0) { + m68k_setpc (oldpc); + op_illg (opcode); + } else if (cc) + Exception(7, oldpc - 2); +} + +// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0) +PUBLIC void REGPARAM2 FFPU fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) +{ + int cc; + + D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra )); + + cc = fpp_cond(opcode, opcode & 0x3f); + if (cc < 0) { + m68k_setpc (pc); + op_illg (opcode); + } else if (cc) { + if ((opcode & 0x40) == 0) + extra = (uae_s32) (uae_s16) extra; + m68k_setpc (pc + extra); + } +} + +// FSAVE has no post-increment +// 0x1f180000 == IDLE state frame, coprocessor version number 1F +PUBLIC void REGPARAM2 FFPU fpuop_save(uae_u32 opcode) +{ + uae_u32 ad; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int i; + + D(bug("fsave_opp at %08lx\r\n", m68k_getpc ())); + + if (get_fp_ad(opcode, &ad)) { + if (FPU is_integral) { + // Put 4 byte 68040 IDLE frame. + if (incr < 0) { + ad -= 4; + put_long (ad, 0x41000000); + } else { + put_long (ad, 0x41000000); + ad += 4; + } + } else { + // Put 28 byte 68881 IDLE frame. + if (incr < 0) { + D(bug("fsave_opp pre-decrement\r\n")); + ad -= 4; + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + for (i = 0; i < 5; i++) { + ad -= 4; + put_long (ad, 0x00000000); + } + ad -= 4; + put_long (ad, 0x1f180000); // IDLE, vers 1f + } else { + put_long (ad, 0x1f180000); // IDLE, vers 1f + ad += 4; + for (i = 0; i < 5; i++) { + put_long (ad, 0x00000000); + ad += 4; + } + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + ad += 4; + } + } + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + D(bug("PROBLEM: fsave_opp post-increment\r\n")); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; + D(bug("fsave_opp pre-decrement %X -> A%d\r\n",ad,opcode & 7)); + } + } +} + +PRIVATE void FFPU do_null_frestore () +{ + // A null-restore operation sets FP7-FP0 positive, nonsignaling NANs. + for( int i=0; i<8; i++ ) { + MAKE_NAN( FPU registers[i] ); + } + + FPU instruction_address = 0; + set_fpcr(0); + set_fpsr(0); + + x86_status_word = SW_INITIAL; + x86_status_word_accrued = 0; + FPU fpsr.quotient = 0; + + x86_control_word = CW_INITIAL; +/* _asm FLDCW x86_control_word + _asm FNCLEX */ + __asm__ __volatile__("fldcw %0\n\tfnclex" : : "m" (x86_control_word)); +} + +// FSAVE has no pre-decrement +PUBLIC void REGPARAM2 FFPU fpuop_restore(uae_u32 opcode) +{ + uae_u32 ad; + uae_u32 d; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + + D(bug("frestore_opp at %08lx\r\n", m68k_getpc ())); + + if (get_fp_ad(opcode, &ad)) { + if (FPU is_integral) { + // 68040 + if (incr < 0) { + D(bug("PROBLEM: frestore_opp incr < 0\r\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) == 0) { // NULL + D(bug("frestore_opp found NULL frame at %X\r\n",ad-4)); + do_null_frestore(); + } else if ((d & 0x00ff0000) == 0) { // IDLE + D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); + ad -= 44; + } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + ad -= 92; + } else { + D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d)); + } + } else { + d = get_long (ad); + D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); + ad += 4; + if ((d & 0xff000000) == 0) { // NULL + D(bug("frestore_opp found NULL frame at %X\r\n",ad-4)); + do_null_frestore(); + } else if ((d & 0x00ff0000) == 0) { // IDLE + D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); + ad += 44; + } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + ad += 92; + } else { + D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d)); + } + } + } else { + // 68881 + if (incr < 0) { + D(bug("PROBLEM: frestore_opp incr < 0\r\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) == 0) { // NULL + do_null_frestore(); + } else if ((d & 0x00ff0000) == 0x00180000) { + ad -= 6 * 4; + } else if ((d & 0x00ff0000) == 0x00380000) { + ad -= 14 * 4; + } else if ((d & 0x00ff0000) == 0x00b40000) { + ad -= 45 * 4; + } + } else { + d = get_long (ad); + D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); + ad += 4; + if ((d & 0xff000000) == 0) { // NULL + D(bug("frestore_opp found NULL frame at %X\r\n",ad-4)); + do_null_frestore(); + } else if ((d & 0x00ff0000) == 0x00180000) { // IDLE + D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + ad += 6 * 4; + } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? + ad += 14 * 4; + D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); + } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY + D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + ad += 45 * 4; + } else { + D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d)); + } + } + } + + if ((opcode & 0x38) == 0x18) { + m68k_areg (regs, opcode & 7) = ad; + D(bug("frestore_opp post-increment %X -> A%d\r\n",ad,opcode & 7)); + } + if ((opcode & 0x38) == 0x20) { + m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 + D(bug("PROBLEM: frestore_opp pre-decrement\r\n")); + } + } +} + + +/* ---------------------------- Old-style interface ---------------------------- */ + +// #ifndef OPTIMIZED_8BIT_MEMORY_ACCESS +PUBLIC void REGPARAM2 FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) +{ + uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4); + (*fpufunctbl[mask])(opcode,extra); +} +// #endif + + +/* ---------------------------- Illegal ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("ILLEGAL F OP 2 %X\r\n",opcode)); + +#if I3_ON_ILLEGAL_FPU_OP +#error "FIXME: asm int 3" + _asm int 3 +#endif + + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); +} + + +/* ---------------------------- FPP -> ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVE -> \r\n")); + + if (put_fp_value (FPU registers[(extra >> 7) & 7], opcode, extra) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + + /* + Needed (among other things) by some Pack5/Elems68k transcendental + functions, they require the ACCR_INEX flag after a "MOVE.D, Dreg". + However, now put_fp_value() is responsible of clearing the exceptions + and merging statuses. + */ + + /* + WORD sw_temp; + _asm FNSTSW sw_temp + if(sw_temp & SW_PE) { + _asm FNCLEX + x86_status_word |= SW_PE; + x86_status_word_accrued |= SW_PE; + } + */ + + dump_registers( "END "); +} + + +/* ---------------------------- CONTROL REGS -> Dreg ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM control(none) -> D%d\r\n", opcode & 7)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> D%d\r\n", get_fpcr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> D%d\r\n", get_fpsr(), opcode & 7)); + m68k_dreg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> D%d\r\n", FPU instruction_address, opcode & 7)); + m68k_dreg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + + +/* ---------------------------- Dreg -> CONTROL REGS ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM D%d -> control(none)\r\n", opcode & 7)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra ) +{ + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_dreg (regs, opcode & 7) ); + D(bug("FMOVEM D%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_dreg (regs, opcode & 7); + D(bug("FMOVEM D%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + + +/* ---------------------------- CONTROL REGS -> Areg ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM control(none) -> A%d\r\n", opcode & 7)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM regs.FPU fpcr (%X) -> A%d\r\n", get_fpcr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpcr(); + D(bug("FMOVEM regs.FPU fpsr (%X) -> A%d\r\n", get_fpsr(), opcode & 7)); + m68k_areg (regs, opcode & 7) = get_fpsr(); + D(bug("FMOVEM FPU instruction_address (%X) -> A%d\r\n", FPU instruction_address, opcode & 7)); + m68k_areg (regs, opcode & 7) = FPU instruction_address; + dump_registers( "END "); +} + + +/* ---------------------------- Areg -> CONTROL REGS ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM A%d -> control(none)\r\n", opcode & 7)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra ) +{ + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ) +{ + set_fpcr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpcr\r\n", opcode & 7, get_fpcr())); + set_fpsr( m68k_areg (regs, opcode & 7) ); + D(bug("FMOVEM A%d (%X) -> regs.FPU fpsr\r\n", opcode & 7, get_fpsr())); + FPU instruction_address = m68k_areg (regs, opcode & 7); + D(bug("FMOVEM A%d (%X) -> FPU instruction_address\r\n", opcode & 7, FPU instruction_address)); + dump_registers( "END "); +} + + +/* ---------------------------- CONTROL REGS -> --MEMORY---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM Control regs (none) -> mem\r\n" )); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 4; + put_long (ad, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 4; + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 8; + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 4; + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 8; + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 8; + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 12; + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + put_long (ad+8, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + + +/* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM Control regs (none) -> mem\r\n" )); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); + m68k_areg (regs, opcode & 7) = ad+4; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + m68k_areg (regs, opcode & 7) = ad+4; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + m68k_areg (regs, opcode & 7) = ad+8; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + m68k_areg (regs, opcode & 7) = ad+4; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + m68k_areg (regs, opcode & 7) = ad+8; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + dump_registers( "END "); + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + m68k_areg (regs, opcode & 7) = ad+8; + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + put_long (ad+8, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); + m68k_areg (regs, opcode & 7) = ad+12; + dump_registers( "END "); + } +} + + +/* ---------------------------- CONTROL REGS -> MEMORY ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM Control regs (none) -> mem\r\n" )); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad )); + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+4 )); + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + put_long (ad, get_fpcr()); + D(bug("FMOVEM regs.FPU fpcr (%X) -> mem %X\r\n", get_fpcr(), ad )); + put_long (ad+4, get_fpsr()); + D(bug("FMOVEM regs.FPU fpsr (%X) -> mem %X\r\n", get_fpsr(), ad+4 )); + put_long (ad+8, FPU instruction_address); + D(bug("FMOVEM FPU instruction_address (%X) -> mem %X\r\n", FPU instruction_address, ad+8 )); + dump_registers( "END "); + } +} + + +/* ---------------------------- --MEMORY -> CONTROL REGS ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM --Mem -> control(none)\r\n")); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 4; + FPU instruction_address = get_long (ad); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 4; + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 8; + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 4; + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 8; + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 8; + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + ad -= 12; + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + FPU instruction_address = get_long (ad+8); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + + +/* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM Mem++ -> control(none)\r\n")); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + FPU instruction_address = get_long (ad); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad+4; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + m68k_areg (regs, opcode & 7) = ad+4; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad+8; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + m68k_areg (regs, opcode & 7) = ad+4; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad+8; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + m68k_areg (regs, opcode & 7) = ad+8; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + FPU instruction_address = get_long (ad+8); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); + m68k_areg (regs, opcode & 7) = ad+12; + dump_registers( "END "); + } +} + + +/* ---------------------------- MEMORY -> CONTROL REGS ---------------------------- */ +/* ---------------------------- and ---------------------------- */ +/* ---------------------------- IMMEDIATE -> CONTROL REGS ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVEM Mem -> control(none)\r\n")); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + FPU instruction_address = get_long (ad); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad, FPU instruction_address )); + } + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + } + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpsr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad, get_fpsr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); + } + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + } + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + FPU instruction_address = get_long (ad+4); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+4, FPU instruction_address )); + } + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + } + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ) +{ + if ((opcode & 0x3f) == 0x3c) { + set_fpcr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr())); + set_fpsr( next_ilong() ); + D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr())); + FPU instruction_address = next_ilong(); + D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address)); + } else { + uae_u32 ad; + if (get_fp_ad(opcode, &ad)) { + set_fpcr( get_long (ad) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpcr\r\n", ad, get_fpcr() )); + set_fpsr( get_long (ad+4) ); + D(bug("FMOVEM mem %X (%X) -> regs.FPU fpsr\r\n", ad+4, get_fpsr() )); + FPU instruction_address = get_long (ad+8); + D(bug("FMOVEM mem %X (%X) -> FPU instruction_address\r\n", ad+8, FPU instruction_address )); + } + } + dump_registers( "END "); +} + + +/* ---------------------------- FMOVEM MEMORY -> FPP ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + ad -= 4; + wrd3 = get_long (ad); + ad -= 4; + wrd2 = get_long (ad); + ad -= 4; + wrd1 = get_long (ad); + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM memory->FPP\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + wrd1 = get_long (ad); + ad += 4; + wrd2 = get_long (ad); + ad += 4; + wrd3 = get_long (ad); + ad += 4; + to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]); + } + list <<= 1; + } + dump_registers( "END "); + } +} + + +/* ---------------------------- FPP -> FMOVEM MEMORY ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=7; reg>=0; reg-- ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + ad -= 4; + put_long (ad, wrd3); + ad -= 4; + put_long (ad, wrd2); + ad -= 4; + put_long (ad, wrd1); + } + list <<= 1; + } + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = extra & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + m68k_areg (regs, opcode & 7) = ad; + dump_registers( "END "); + } +} +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra ) +{ + uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; + D(bug("FMOVEM FPP->memory\r\n")); + if (get_fp_ad(opcode, &ad)) { + for( int reg=0; reg<8; reg++ ) { + uae_u32 wrd1, wrd2, wrd3; + if( list & 0x80 ) { + from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + ad += 4; + } + list <<= 1; + } + dump_registers( "END "); + } +} + + +/* ---------------------------- FMOVEM CONSTANT ROM -> FPP ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: Pi\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_pi, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: Log 10 (2)\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_lg2, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: e\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_e, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: Log 2 (e)\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_l2e, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: Log 10 (e)\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_log_10_e, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: zero\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_z, sizeof(fpu_register) ); + x86_status_word = SW_Z; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: ln(2)\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_ln2, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: ln(10)\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_ln_10, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e0\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e1\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e1, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e2\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e2, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e4\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e4, sizeof(fpu_register) ); + x86_status_word = SW_FINITE; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e8\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e8, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; // Is it really FPSR_EXCEPTION_INEX2? + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e16\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e16, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e32\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e32, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e64\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e64, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e128\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e128, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e256\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e256, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e512\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e512, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e1024\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e1024, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e2048\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e2048, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra ) +{ + D(bug("FMOVECR memory->FPP FP const: 1.0e4096\r\n")); + memcpy( &FPU registers[(extra>>7) & 7], &const_1e4096, sizeof(fpu_register) ); + x86_status_word = SW_FINITE | FPSR_EXCEPTION_INEX2; + dump_registers( "END "); +} + + +/* -------------------------- 040 ALU -------------------------- */ +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSMOVE %s\r\n",etos(src))); + do_fsmove( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDMOVE %s\r\n",etos(src))); + do_fdmove( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSSQRT %s\r\n",etos(src))); + do_fssqrt( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDSQRT %s\r\n",etos(src))); + do_fdsqrt( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSABS %s\r\n",etos(src))); + do_fsabs( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDABS %s\r\n",etos(src))); + do_fdabs( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSNEG %s\r\n",etos(src))); + do_fsneg( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDNEG %s\r\n",etos(src))); + do_fdneg( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSDIV %s\r\n",etos(src))); + do_fsdiv( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDDIV %s\r\n",etos(src))); + do_fddiv( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSADD %s\r\n",etos(src))); + do_fsadd( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDADD %s\r\n",etos(src))); + do_fdadd( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSSUB %s\r\n",etos(src))); + do_fssub( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDSUB %s\r\n",etos(src))); + do_fdsub( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSMUL %s\r\n",etos(src))); + do_fsmul( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSMUL %s\r\n",etos(src))); + do_fsmul( FPU registers[reg], src ); + dump_registers( "END "); +} + +/* ---------------------------- ALU ---------------------------- */ + +PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FMOVE %s\r\n",etos(src))); + do_fmove( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FINT %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); + do_fint( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSINH %s\r\n",etos(src))); + do_fsinh( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FINTRZ %s\r\n",etos(src))); + do_fintrz( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSQRT %s\r\n",etos(src))); + do_fsqrt( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FLOGNP1 %s\r\n",etos(src))); + do_flognp1( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FETOXM1 %s\r\n",etos(src))); + do_fetoxm1( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FTANH %s\r\n",etos(src))); + do_ftanh( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FATAN %s\r\n",etos(src))); + do_fatan( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FASIN %s\r\n",etos(src))); + do_fasin( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FATANH %s\r\n",etos(src))); + do_fatanh( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSIN %s\r\n",etos(src))); + do_fsin( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FTAN %s\r\n",etos(src))); + do_ftan( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FETOX %s\r\n",etos(src))); + do_fetox( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FTWOTOX %s\r\n",etos(src))); + do_ftwotox( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FTENTOX %s\r\n",etos(src))); + do_ftentox( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FLOGN %s\r\n",etos(src))); + do_flogn( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FLOG10 %s\r\n",etos(src))); + do_flog10( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FLOG2 %s\r\n",etos(src))); + do_flog2( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FABS %s\r\n",etos(src))); + do_fabs( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FCOSH %s\r\n",etos(src))); + do_fcosh( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FNEG %s\r\n",etos(src))); + do_fneg( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FACOS %s\r\n",etos(src))); + do_facos( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FCOS %s\r\n",etos(src))); + do_fcos( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FGETEXP %s\r\n",etos(src))); + + if( IS_INFINITY(src) ) { + MAKE_NAN( FPU registers[reg] ); + do_ftst( FPU registers[reg] ); + x86_status_word |= SW_IE; + } else { + do_fgetexp( FPU registers[reg], src ); + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FGETMAN %s\r\n",etos(src))); + if( IS_INFINITY(src) ) { + MAKE_NAN( FPU registers[reg] ); + do_ftst( FPU registers[reg] ); + x86_status_word |= SW_IE; + } else { + do_fgetman( FPU registers[reg], src ); + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDIV %s\r\n",etos(src))); + do_fdiv( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FMOD %s\r\n",etos(src))); + +#if USE_3_BIT_QUOTIENT + do_fmod( FPU registers[reg], src ); +#else + if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_ZERO ) { + do_fmod_dont_set_cw( FPU registers[reg], src ); + } else { + do_fmod( FPU registers[reg], src ); + } +#endif + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FREM %s\r\n",etos(src))); +#if USE_3_BIT_QUOTIENT + do_frem( FPU registers[reg], src ); +#else + if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_NEAR ) { + do_frem_dont_set_cw( FPU registers[reg], src ); + } else { + do_frem( FPU registers[reg], src ); + } +#endif + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FADD %s\r\n",etos(src))); + do_fadd( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FMUL %s\r\n",etos(src))); + do_fmul( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSGLDIV %s\r\n",etos(src))); + do_fsgldiv( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); + if( IS_INFINITY(FPU registers[reg]) ) { + MAKE_NAN( FPU registers[reg] ); + do_ftst( FPU registers[reg] ); + x86_status_word |= SW_IE; + } else { + // When the absolute value of the source operand is >= 2^14, + // an overflow or underflow always results. + do_fscale( FPU registers[reg], src ); + } + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSGLMUL %s\r\n",etos(src))); + do_fsglmul( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSUB %s\r\n",etos(src))); + do_fsub( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSINCOS %s\r\n",etos(src))); + do_fsincos( FPU registers[reg], FPU registers[extra & 7], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FCMP %s\r\n",etos(src))); + + if( IS_INFINITY(src) ) { + if( IS_NEGATIVE(src) ) { + if( IS_INFINITY(FPU registers[reg]) && IS_NEGATIVE(FPU registers[reg]) ) { + x86_status_word = SW_Z | SW_N; + D(bug("-INF FCMP -INF -> NZ\r\n")); + } else { + x86_status_word = SW_FINITE; + D(bug("X FCMP -INF -> None\r\n")); + } + } else { + if( IS_INFINITY(FPU registers[reg]) && !IS_NEGATIVE(FPU registers[reg]) ) { + x86_status_word = SW_Z; + D(bug("+INF FCMP +INF -> Z\r\n")); + } else { + x86_status_word = SW_N; + D(bug("X FCMP +INF -> N\r\n")); + } + } + } else if( IS_INFINITY(FPU registers[reg]) ) { + if( IS_NEGATIVE(FPU registers[reg]) ) { + x86_status_word = SW_N; + D(bug("-INF FCMP X -> Negative\r\n")); + } else { + x86_status_word = SW_FINITE; + D(bug("+INF FCMP X -> None\r\n")); + } + } else { + do_fcmp( FPU registers[reg], src ); + } + + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FTST %s\r\n",etos(src))); + do_ftst( src ); + build_ex_status(); + dump_registers( "END "); +} + + + +/* ---------------------------- SETUP TABLES ---------------------------- */ + +PRIVATE void FFPU build_fpp_opp_lookup_table () +{ + for( uae_u32 opcode=0; opcode<=0x38; opcode+=8 ) { + for( uae_u32 extra=0; extra<65536; extra++ ) { + uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4); + fpufunctbl[mask] = & FFPU fpuop_illg; + + switch ((extra >> 13) & 0x7) { + case 3: + fpufunctbl[mask] = & FFPU fpuop_fmove_2_ea; + break; + case 4: + case 5: + if ((opcode & 0x38) == 0) { + if (extra & 0x2000) { // dr bit + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Dreg; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Dreg; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Dreg; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Dreg; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg; + break; + } + } else { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_none; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpiar; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar; + break; + } + } + } else if ((opcode & 0x38) == 8) { + if (extra & 0x2000) { // dr bit + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Areg; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Areg; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Areg; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Areg; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Areg; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Areg; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Areg; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg; + break; + } + } else { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_none; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpiar; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr_fpiar; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpiar; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar; + break; + } + } + } else if (extra & 0x2000) { + if ((opcode & 0x38) == 0x20) { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_predecrement; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_predecrement; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_predecrement; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_predecrement; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement; + break; + } + } else if ((opcode & 0x38) == 0x18) { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_postincrement; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_postincrement; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_postincrement; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_postincrement; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement; + break; + } + } else { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem; + break; + } + } + } else { + if ((opcode & 0x38) == 0x20) { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_predecrement; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_predecrement; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_predecrement; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_predecrement; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement; + break; + } + } else if ((opcode & 0x38) == 0x18) { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_postincrement; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_postincrement; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_postincrement; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_postincrement; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement; + break; + } + } else { + switch( extra & 0x1C00 ) { + case 0x0000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_2_Mem; + break; + case 0x0400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem; + break; + case 0x0800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem; + break; + case 0x0C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem; + break; + case 0x1000: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem; + break; + case 0x1400: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem; + break; + case 0x1800: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem; + break; + case 0x1C00: + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem; + break; + } + } + break; + case 6: + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred; + break; + case 1: /* dynamic pred */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred; + break; + case 2: /* static postinc */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc; + break; + case 3: /* dynamic postinc */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc; + break; + } + break; + case 7: + switch ((extra >> 11) & 3) { + case 0: /* static pred */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred; + break; + case 1: /* dynamic pred */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred; + break; + case 2: /* static postinc */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc; + break; + case 3: /* dynamic postinc */ + if ((opcode & 0x38) == 0x18) // post-increment? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement; + else if ((opcode & 0x38) == 0x20) // pre-decrement? + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement; + else + fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc; + break; + } + break; + case 0: + case 2: + if ((extra & 0xfc00) == 0x5c00) { + switch (extra & 0x7f) { + case 0x00: + fpufunctbl[mask] = & FFPU fpuop_do_fldpi; + break; + case 0x0b: + fpufunctbl[mask] = & FFPU fpuop_do_fldlg2; + break; + case 0x0c: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_e; + break; + case 0x0d: + fpufunctbl[mask] = & FFPU fpuop_do_fldl2e; + break; + case 0x0e: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_log_10_e; + break; + case 0x0f: + fpufunctbl[mask] = & FFPU fpuop_do_fldz; + break; + case 0x30: + fpufunctbl[mask] = & FFPU fpuop_do_fldln2; + break; + case 0x31: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_ln_10; + break; + case 0x32: + fpufunctbl[mask] = & FFPU fpuop_do_fld1; + break; + case 0x33: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1; + break; + case 0x34: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2; + break; + case 0x35: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4; + break; + case 0x36: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e8; + break; + case 0x37: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e16; + break; + case 0x38: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e32; + break; + case 0x39: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e64; + break; + case 0x3a: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e128; + break; + case 0x3b: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e256; + break; + case 0x3c: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e512; + break; + case 0x3d: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1024; + break; + case 0x3e: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2048; + break; + case 0x3f: + fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4096; + break; + } + break; + } + + if (FPU is_integral) { + switch (extra & 0x7f) { + case 0x40: + fpufunctbl[mask] = & FFPU fpuop_do_fsmove; + break; + case 0x44: + fpufunctbl[mask] = & FFPU fpuop_do_fdmove; + break; + case 0x41: + fpufunctbl[mask] = & FFPU fpuop_do_fssqrt; + break; + case 0x45: + fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt; + break; + case 0x58: + fpufunctbl[mask] = & FFPU fpuop_do_fsabs; + break; + case 0x5c: + fpufunctbl[mask] = & FFPU fpuop_do_fdabs; + break; + case 0x5a: + fpufunctbl[mask] = & FFPU fpuop_do_fsneg; + break; + case 0x5e: + fpufunctbl[mask] = & FFPU fpuop_do_fdneg; + break; + case 0x60: + fpufunctbl[mask] = & FFPU fpuop_do_fsdiv; + break; + case 0x64: + fpufunctbl[mask] = & FFPU fpuop_do_fddiv; + break; + case 0x62: + fpufunctbl[mask] = & FFPU fpuop_do_fsadd; + break; + case 0x66: + fpufunctbl[mask] = & FFPU fpuop_do_fdadd; + break; + case 0x68: + fpufunctbl[mask] = & FFPU fpuop_do_fssub; + break; + case 0x6c: + fpufunctbl[mask] = & FFPU fpuop_do_fdsub; + break; + case 0x63: + fpufunctbl[mask] = & FFPU fpuop_do_fsmul; + break; + case 0x67: + fpufunctbl[mask] = & FFPU fpuop_do_fdmul; + break; + default: + break; + } + } + + switch (extra & 0x7f) { + case 0x00: + fpufunctbl[mask] = & FFPU fpuop_do_fmove; + break; + case 0x01: + fpufunctbl[mask] = & FFPU fpuop_do_fint; + break; + case 0x02: + fpufunctbl[mask] = & FFPU fpuop_do_fsinh; + break; + case 0x03: + fpufunctbl[mask] = & FFPU fpuop_do_fintrz; + break; + case 0x04: + fpufunctbl[mask] = & FFPU fpuop_do_fsqrt; + break; + case 0x06: + fpufunctbl[mask] = & FFPU fpuop_do_flognp1; + break; + case 0x08: + fpufunctbl[mask] = & FFPU fpuop_do_fetoxm1; + break; + case 0x09: + fpufunctbl[mask] = & FFPU fpuop_do_ftanh; + break; + case 0x0a: + fpufunctbl[mask] = & FFPU fpuop_do_fatan; + break; + case 0x0c: + fpufunctbl[mask] = & FFPU fpuop_do_fasin; + break; + case 0x0d: + fpufunctbl[mask] = & FFPU fpuop_do_fatanh; + break; + case 0x0e: + fpufunctbl[mask] = & FFPU fpuop_do_fsin; + break; + case 0x0f: + fpufunctbl[mask] = & FFPU fpuop_do_ftan; + break; + case 0x10: + fpufunctbl[mask] = & FFPU fpuop_do_fetox; + break; + case 0x11: + fpufunctbl[mask] = & FFPU fpuop_do_ftwotox; + break; + case 0x12: + fpufunctbl[mask] = & FFPU fpuop_do_ftentox; + break; + case 0x14: + fpufunctbl[mask] = & FFPU fpuop_do_flogn; + break; + case 0x15: + fpufunctbl[mask] = & FFPU fpuop_do_flog10; + break; + case 0x16: + fpufunctbl[mask] = & FFPU fpuop_do_flog2; + break; + case 0x18: + fpufunctbl[mask] = & FFPU fpuop_do_fabs; + break; + case 0x19: + fpufunctbl[mask] = & FFPU fpuop_do_fcosh; + break; + case 0x1a: + fpufunctbl[mask] = & FFPU fpuop_do_fneg; + break; + case 0x1c: + fpufunctbl[mask] = & FFPU fpuop_do_facos; + break; + case 0x1d: + fpufunctbl[mask] = & FFPU fpuop_do_fcos; + break; + case 0x1e: + fpufunctbl[mask] = & FFPU fpuop_do_fgetexp; + break; + case 0x1f: + fpufunctbl[mask] = & FFPU fpuop_do_fgetman; + break; + case 0x20: + fpufunctbl[mask] = & FFPU fpuop_do_fdiv; + break; + case 0x21: + fpufunctbl[mask] = & FFPU fpuop_do_fmod; + break; + case 0x22: + fpufunctbl[mask] = & FFPU fpuop_do_fadd; + break; + case 0x23: + fpufunctbl[mask] = & FFPU fpuop_do_fmul; + break; + case 0x24: + fpufunctbl[mask] = & FFPU fpuop_do_fsgldiv; + break; + case 0x25: + fpufunctbl[mask] = & FFPU fpuop_do_frem; + break; + case 0x26: + fpufunctbl[mask] = & FFPU fpuop_do_fscale; + break; + case 0x27: + fpufunctbl[mask] = & FFPU fpuop_do_fsglmul; + break; + case 0x28: + fpufunctbl[mask] = & FFPU fpuop_do_fsub; + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + fpufunctbl[mask] = & FFPU fpuop_do_fsincos; + break; + case 0x38: + fpufunctbl[mask] = & FFPU fpuop_do_fcmp; + break; + case 0x3a: + fpufunctbl[mask] = & FFPU fpuop_do_ftst; + break; + } + } + } + } + } +} + +/* ---------------------------- CONSTANTS ---------------------------- */ + +PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ) +{ + FPU_CONSISTENCY_CHECK_START(); + if(mult == 1) { +/* _asm { + MOV ESI, [f] + FLD QWORD PTR [value] + FSTP TBYTE PTR [ESI] + } */ + __asm__ __volatile__( + "fldl %1\n" + "fstpt %0\n" + : "=m" (f) + : "m" (value) + ); + } else { +/* _asm { + MOV ESI, [f] + FILD DWORD PTR [mult] + FLD QWORD PTR [value] + FMUL + FSTP TBYTE PTR [ESI] + } */ + __asm__ __volatile__( + "fildl %2\n" + "fldl %1\n" + "fmul \n" + "fstpt %0\n" + : "=m" (f) + : "m" (value), "m" (mult) + ); + } + D(bug("set_constant (%s,%.04f) = %s\r\n",name,(float)value,etos(f))); + FPU_CONSISTENCY_CHECK_STOP( mult==1 ? "set_constant(mult==1)" : "set_constant(mult>1)" ); +} + +PRIVATE void FFPU do_fldpi ( fpu_register & dest ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + FLDPI + FXAM + FNSTSW x86_status_word + MOV EDI, [dest] + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldpi \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fldpi"); +} + +PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + FLDLG2 + FXAM + FNSTSW x86_status_word + MOV EDI, [dest] + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldlg2 \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fldlg2"); +} + +PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + FLDL2E + FXAM + FNSTSW x86_status_word + MOV EDI, [dest] + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldl2e \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fldl2e"); +} + +PRIVATE void FFPU do_fldz ( fpu_register & dest ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + FLDZ + FXAM + FNSTSW x86_status_word + MOV EDI, [dest] + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldz \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fldz"); +} + +PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + FLDLN2 + FXAM + FNSTSW x86_status_word + MOV EDI, [dest] + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fldln2 \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fldln2"); +} + +PRIVATE void FFPU do_fld1 ( fpu_register & dest ) +{ + FPU_CONSISTENCY_CHECK_START(); +/* _asm { + FLD1 + FXAM + FNSTSW x86_status_word + MOV EDI, [dest] + FSTP TBYTE PTR [EDI] + } */ + __asm__ __volatile__( + "fld1 \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fld1"); +} + + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} + +/* ---------------------------- MAIN INIT ---------------------------- */ + +#ifdef HAVE_SIGACTION +// Mega hackaround-that-happens-to-work: the following way to handle +// SIGFPE just happens to make the "fsave" below in fpu_init() *NOT* +// to abort with a floating point exception. However, we never +// actually reach sigfpe_handler(). +static void sigfpe_handler(int code, siginfo_t *sip, void *) +{ + if (code == SIGFPE && sip->si_code == FPE_FLTINV) { + fprintf(stderr, "Invalid floating point operation\n"); + abort(); + } +} +#endif + +PUBLIC void FFPU fpu_init( bool integral_68040 ) +{ + static bool done_first_time_initialization = false; + if (!done_first_time_initialization) { + fpu_init_native_fflags(); + fpu_init_native_exceptions(); + fpu_init_native_accrued_exceptions(); +#ifdef HAVE_SIGACTION + struct sigaction fpe_sa; + sigemptyset(&fpe_sa.sa_mask); + fpe_sa.sa_sigaction = sigfpe_handler; + fpe_sa.sa_flags = SA_SIGINFO; + sigaction(SIGFPE, &fpe_sa, 0); +#endif + done_first_time_initialization = true; + } + + __asm__ __volatile__("fsave %0" : "=m" (m_fpu_state_original)); + + FPU is_integral = integral_68040; + FPU instruction_address = 0; + set_fpcr(0); + set_fpsr(0); + + x86_control_word = CW_INITIAL; + x86_status_word = SW_INITIAL; + x86_status_word_accrued = 0; + FPU fpsr.quotient = 0; + + for( int i=0; i<8; i++ ) { + MAKE_NAN( FPU registers[i] ); + } + + build_fpp_opp_lookup_table(); + +/* _asm { + FNINIT + FLDCW x86_control_word + } */ + __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); + + do_fldpi( const_pi ); + do_fldlg2( const_lg2 ); + do_fldl2e( const_l2e ); + do_fldz( const_z ); + do_fldln2( const_ln2 ); + do_fld1( const_1 ); + + set_constant( const_e, "e", exp (1.0), 1 ); + set_constant( const_log_10_e, "Log 10 (e)", log (exp (1.0)) / log (10.0), 1 ); + set_constant( const_ln_10, "ln(10)", log (10.0), 1 ); + set_constant( const_1e1, "1.0e1", 1.0e1, 1 ); + set_constant( const_1e2, "1.0e2", 1.0e2, 1 ); + set_constant( const_1e4, "1.0e4", 1.0e4, 1 ); + set_constant( const_1e8, "1.0e8", 1.0e8, 1 ); + set_constant( const_1e16, "1.0e16", 1.0e16, 1 ); + set_constant( const_1e32, "1.0e32", 1.0e32, 1 ); + set_constant( const_1e64, "1.0e64", 1.0e64, 1 ) ; + set_constant( const_1e128, "1.0e128", 1.0e128, 1 ); + set_constant( const_1e256, "1.0e256", 1.0e256, 1 ); + set_constant( const_1e512, "1.0e512", 1.0e256, 10 ); + set_constant( const_1e1024, "1.0e1024", 1.0e256, 100 ); + set_constant( const_1e2048, "1.0e2048", 1.0e256, 1000 ); + set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 ); + + // Just in case. +/* _asm { + FNINIT + FLDCW x86_control_word + } */ + __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); +} + +PUBLIC void FFPU fpu_exit( void ) +{ + __asm__ __volatile__("frstor %0" : : "m" (m_fpu_state_original)); +} + +PUBLIC void FFPU fpu_reset( void ) +{ + fpu_exit(); + fpu_init(FPU is_integral); +} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h new file mode 100644 index 00000000..52a2f310 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h @@ -0,0 +1,384 @@ +/* + * fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_X86_H +#define FPU_X86_H + +/* NOTE: this file shall be included from fpu/fpu_x86.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +// Status word +PRIVATE uae_u32 x86_status_word; +PRIVATE uae_u32 x86_status_word_accrued; + +// FPU jump table +typedef void REGPARAM2 ( *fpuop_func )( uae_u32, uae_u32 ); +PRIVATE fpuop_func fpufunctbl[65536]; + +// FPU consistency +PRIVATE uae_u32 checked_sw_atstart; + +// FMOVECR constants supported byt x86 FPU +PRIVATE fpu_register const_pi; +PRIVATE fpu_register const_lg2; +PRIVATE fpu_register const_l2e; +PRIVATE fpu_register const_z; +PRIVATE fpu_register const_ln2; +PRIVATE fpu_register const_1; + +// FMOVECR constants not not suported by x86 FPU +PRIVATE fpu_register const_e; +PRIVATE fpu_register const_log_10_e; +PRIVATE fpu_register const_ln_10; +PRIVATE fpu_register const_1e1; +PRIVATE fpu_register const_1e2; +PRIVATE fpu_register const_1e4; +PRIVATE fpu_register const_1e8; +PRIVATE fpu_register const_1e16; +PRIVATE fpu_register const_1e32; +PRIVATE fpu_register const_1e64; +PRIVATE fpu_register const_1e128; +PRIVATE fpu_register const_1e256; +PRIVATE fpu_register const_1e512; +PRIVATE fpu_register const_1e1024; +PRIVATE fpu_register const_1e2048; +PRIVATE fpu_register const_1e4096; + +// Saved host FPU state +PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 + +/* -------------------------------------------------------------------------- */ +/* --- Methods --- */ +/* -------------------------------------------------------------------------- */ + +// Debug support functions +PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual); +PRIVATE char * FFPU etos(fpu_register const & e) REGPARAM; + +// FPU consistency +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void); +PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name); + +// Get special floating-point value class +PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f); + +// Make a special floating-point value +PRIVATE inline void FFPU MAKE_NAN (fpu_register & f); +PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f); + +// Conversion from extended floating-point values +PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM; +PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) REGPARAM; +PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) REGPARAM; +PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) REGPARAM; +PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) REGPARAM; +PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM; +PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM; +PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM; + +// Conversion to extended floating-point values +PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) REGPARAM; +PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) REGPARAM; +PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) REGPARAM; +PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM; +PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM; +PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) REGPARAM; +PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM; + +// Atomic floating-point arithmetic operations +PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_ftst ( fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) REGPARAM; +PRIVATE void FFPU do_fldpi ( fpu_register & dest ) REGPARAM; +PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) REGPARAM; +PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) REGPARAM; +PRIVATE void FFPU do_fldz ( fpu_register & dest ) REGPARAM; +PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) REGPARAM; +PRIVATE void FFPU do_fld1 ( fpu_register & dest ) REGPARAM; + +// Instructions handlers +PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ); + +// 040 +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ); + +// Get & Put floating-point values +PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM; +PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM; +PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM; + +// Floating-point condition-based instruction handlers +PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM; + +// Misc functions +PRIVATE void inline FFPU set_host_fpu_control_word (); +PRIVATE void inline FFPU SET_BSUN_ON_NAN (); +PRIVATE void inline FFPU build_ex_status (); +PRIVATE void FFPU do_null_frestore (); +PRIVATE void FFPU build_fpp_opp_lookup_table (); +PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ); + +#endif /* FPU_X86_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h new file mode 100644 index 00000000..6e5a3766 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h @@ -0,0 +1,104 @@ +/* + * fpu/fpu_x86_asm.h - Extra Definitions for the X86 assembly FPU core + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DEFINE_X86_MACRO(name, value) \ + asm(".local " #name "\n\t" #name " = " #value) + +DEFINE_X86_MACRO(BSUN, 0x00008000); +DEFINE_X86_MACRO(SNAN, 0x00004000); +DEFINE_X86_MACRO(OPERR, 0x00002000); +DEFINE_X86_MACRO(OVFL, 0x00001000); +DEFINE_X86_MACRO(UNFL, 0x00000800); +DEFINE_X86_MACRO(DZ, 0x00000400); +DEFINE_X86_MACRO(INEX2, 0x00000200); +DEFINE_X86_MACRO(INEX1, 0x00000100); +DEFINE_X86_MACRO(ACCR_IOP, 0x80); +DEFINE_X86_MACRO(ACCR_OVFL, 0x40); +DEFINE_X86_MACRO(ACCR_UNFL, 0x20); +DEFINE_X86_MACRO(ACCR_DZ, 0x10); +DEFINE_X86_MACRO(ACCR_INEX, 0x08); +DEFINE_X86_MACRO(ROUND_CONTROL_MASK, 0x30); +DEFINE_X86_MACRO(ROUND_TO_NEAREST, 0); +DEFINE_X86_MACRO(ROUND_TO_ZERO, 0x10); +DEFINE_X86_MACRO(ROUND_TO_NEGATIVE_INFINITY, 0x20); +DEFINE_X86_MACRO(ROUND_TO_POSITIVE_INFINITY, 0x30); +DEFINE_X86_MACRO(PRECISION_CONTROL_MASK, 0xC0); +DEFINE_X86_MACRO(PRECISION_CONTROL_EXTENDED, 0); +DEFINE_X86_MACRO(PRECISION_CONTROL_DOUBLE, 0x80); +DEFINE_X86_MACRO(PRECISION_CONTROL_SINGLE, 0x40); +DEFINE_X86_MACRO(PRECISION_CONTROL_UNDEFINED, 0xC0); +DEFINE_X86_MACRO(CW_RESET, 0x0040); +DEFINE_X86_MACRO(CW_FINIT, 0x037F); +DEFINE_X86_MACRO(SW_RESET, 0x0000); +DEFINE_X86_MACRO(SW_FINIT, 0x0000); +DEFINE_X86_MACRO(TW_RESET, 0x5555); +DEFINE_X86_MACRO(TW_FINIT, 0x0FFF); +DEFINE_X86_MACRO(CW_X, 0x1000); +DEFINE_X86_MACRO(CW_RC_ZERO, 0x0C00); +DEFINE_X86_MACRO(CW_RC_UP, 0x0800); +DEFINE_X86_MACRO(CW_RC_DOWN, 0x0400); +DEFINE_X86_MACRO(CW_RC_NEAR, 0x0000); +DEFINE_X86_MACRO(CW_PC_EXTENDED, 0x0300); +DEFINE_X86_MACRO(CW_PC_DOUBLE, 0x0200); +DEFINE_X86_MACRO(CW_PC_RESERVED, 0x0100); +DEFINE_X86_MACRO(CW_PC_SINGLE, 0x0000); +DEFINE_X86_MACRO(CW_PM, 0x0020); +DEFINE_X86_MACRO(CW_UM, 0x0010); +DEFINE_X86_MACRO(CW_OM, 0x0008); +DEFINE_X86_MACRO(CW_ZM, 0x0004); +DEFINE_X86_MACRO(CW_DM, 0x0002); +DEFINE_X86_MACRO(CW_IM, 0x0001); +DEFINE_X86_MACRO(SW_B, 0x8000); +DEFINE_X86_MACRO(SW_C3, 0x4000); +DEFINE_X86_MACRO(SW_TOP_7, 0x3800); +DEFINE_X86_MACRO(SW_TOP_6, 0x3000); +DEFINE_X86_MACRO(SW_TOP_5, 0x2800); +DEFINE_X86_MACRO(SW_TOP_4, 0x2000); +DEFINE_X86_MACRO(SW_TOP_3, 0x1800); +DEFINE_X86_MACRO(SW_TOP_2, 0x1000); +DEFINE_X86_MACRO(SW_TOP_1, 0x0800); +DEFINE_X86_MACRO(SW_TOP_0, 0x0000); +DEFINE_X86_MACRO(SW_C2, 0x0400); +DEFINE_X86_MACRO(SW_C1, 0x0200); +DEFINE_X86_MACRO(SW_C0, 0x0100); +DEFINE_X86_MACRO(SW_ES, 0x0080); +DEFINE_X86_MACRO(SW_SF, 0x0040); +DEFINE_X86_MACRO(SW_PE, 0x0020); +DEFINE_X86_MACRO(SW_UE, 0x0010); +DEFINE_X86_MACRO(SW_OE, 0x0008); +DEFINE_X86_MACRO(SW_ZE, 0x0004); +DEFINE_X86_MACRO(SW_DE, 0x0002); +DEFINE_X86_MACRO(SW_IE, 0x0001); +DEFINE_X86_MACRO(X86_ROUNDING_MODE, 0x0C00); +DEFINE_X86_MACRO(X86_ROUNDING_PRECISION, 0x0300); + +#undef DEFINE_X86_MACRO diff --git a/BasiliskII/src/uae_cpu/fpu/impl.h b/BasiliskII/src/uae_cpu/fpu/impl.h new file mode 100644 index 00000000..af7946a3 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/impl.h @@ -0,0 +1,159 @@ +/* + * fpu/impl.h - extra functions and inline implementations + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_IMPL_H +#define FPU_IMPL_H + +/* NOTE: this file shall be included from fpu/core.h */ +#undef PUBLIC +#define PUBLIC /**/ + +#undef PRIVATE +#define PRIVATE /**/ + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- X86 assembly fpu specific methods --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_X86 + +/* Return the floating-point status register in m68k format */ +static inline uae_u32 FFPU get_fpsr(void) +{ + return to_m68k_fpcond[(x86_status_word & 0x4700) >> 8] + | FPU fpsr.quotient + | exception_host2mac[x86_status_word & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)] + | accrued_exception_host2mac[x86_status_word_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)] + ; +} + +/* Set the floating-point status register from an m68k format */ +static inline void FFPU set_fpsr(uae_u32 new_fpsr) +{ + x86_status_word = to_host_fpcond[(new_fpsr & FPSR_CCB) >> 24 ] + | exception_mac2host[(new_fpsr & FPSR_EXCEPTION_STATUS) >> 8]; + x86_status_word_accrued = accrued_exception_mac2host[(new_fpsr & FPSR_ACCRUED_EXCEPTION) >> 3]; +} + +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Original UAE and IEEE FPU core methods --- */ +/* -------------------------------------------------------------------------- */ + +#ifndef FPU_X86 + +/* Return the floating-point status register in m68k format */ +static inline uae_u32 FFPU get_fpsr(void) +{ + uae_u32 condition_codes = get_fpccr(); + uae_u32 exception_status = get_exception_status(); + uae_u32 accrued_exception = get_accrued_exception(); + uae_u32 quotient = FPU fpsr.quotient; + return (condition_codes | quotient | exception_status | accrued_exception); +} + +/* Set the floating-point status register from an m68k format */ +static inline void FFPU set_fpsr(uae_u32 new_fpsr) +{ + set_fpccr ( new_fpsr & FPSR_CCB ); + set_exception_status ( new_fpsr & FPSR_EXCEPTION_STATUS ); + set_accrued_exception ( new_fpsr & FPSR_ACCRUED_EXCEPTION ); + FPU fpsr.quotient = new_fpsr & FPSR_QUOTIENT; +} + +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Common routines for control word --- */ +/* -------------------------------------------------------------------------- */ + +/* Return the floating-point control register in m68k format */ +static inline uae_u32 FFPU get_fpcr(void) +{ + uae_u32 rounding_precision = get_rounding_precision(); + uae_u32 rounding_mode = get_rounding_mode(); + uae_u32 exception_enable = FPU fpcr.exception_enable; + return (rounding_precision | rounding_mode | exception_enable); +} + +/* Set the floating-point control register from an m68k format */ +static inline void FFPU set_fpcr(uae_u32 new_fpcr) +{ + set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION); + set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE ); + set_host_control_word(); + FPU fpcr.exception_enable = new_fpcr & FPCR_EXCEPTION_ENABLE; +} + +/* -------------------------------------------------------------------------- */ +/* --- Specific part to X86 assembly FPU --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_X86 + +/* Retrieve a floating-point register value and convert it to double precision */ +static inline double FFPU fpu_get_register(int r) +{ + double f; + __asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r])); + return f; +} + +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Specific to original UAE or new IEEE-based FPU core --- */ +/* -------------------------------------------------------------------------- */ + +#if defined(FPU_UAE) || defined(FPU_IEEE) + +/* Retrieve a floating-point register value and convert it to double precision */ +static inline double FFPU fpu_get_register(int r) +{ + return FPU registers[r]; +} + +#endif + +#endif /* FPU_IMPL_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp new file mode 100644 index 00000000..46d43c95 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp @@ -0,0 +1,105 @@ +/* + * fpu/mathlib.cpp - Floating-point math support library + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ +#undef PRIVATE +#define PRIVATE static + +#undef PUBLIC +#define PUBLIC /**/ + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) + +PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y) +{ + fpu_extended value, exponent; + uae_s64 p = (uae_s64)y; + + if (x == 0.0) { + if (y > 0.0) + return (y == (double) p && (p & 1) != 0 ? x : 0.0); + else if (y < 0.0) + return (y == (double) p && (-p & 1) != 0 ? 1.0 / x : 1.0 / fp_fabs (x)); + } + + if (y == (double) p) { + fpu_extended r = 1.0; + if (p == 0) + return 1.0; + if (p < 0) { + p = -p; + x = 1.0 / x; + } + while (1) { + if (p & 1) + r *= x; + p >>= 1; + if (p == 0) + return r; + x *= x; + } + } + + __asm__ __volatile__("fyl2x" : "=t" (value) : "0" (x), "u" (1.0) : "st(1)"); + __asm__ __volatile__("fmul %%st(1) # y * log2(x)\n\t" + "fst %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (value), "=u" (exponent) : "0" (y), "1" (value)); + value += 1.0; + __asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent)); + return value; +} + +PRIVATE fpu_extended fp_do_log1p(fpu_extended x) +{ + // TODO: handle NaN and +inf/-inf + fpu_extended value; + // The fyl2xp1 can only be used for values in + // -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 + // 0.29 is a safe value. + if (fp_fabs(x) <= 0.29) + __asm__ __volatile__("fldln2; fxch; fyl2xp1" : "=t" (value) : "0" (x)); + else + __asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0)); + return value; +} + +#endif diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h new file mode 100644 index 00000000..c9a1951c --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -0,0 +1,1185 @@ +/* + * fpu/mathlib.h - Floating-point math support library + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_MATHLIB_H +#define FPU_MATHLIB_H + +/* NOTE: this file shall be included only from fpu/fpu_*.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +// Define the following macro if branches are expensive. If so, +// integer-based isnan() and isinf() functions are implemented. +// TODO: move to Makefile.in +#define BRANCHES_ARE_EXPENSIVE 1 + +// Use ISO C99 extended-precision math functions (glibc 2.1+) +#define FPU_USE_ISO_C99 1 + +// NOTE: this is irrelevant on Win32 platforms since the MS libraries +// don't support extended-precision floating-point computations +#ifdef WIN32 +#undef FPU_USE_ISO_C99 +#endif + +// Use faster implementation of math functions, but this could cause +// some incorrect results (?) +// TODO: actually implement the slower but safer versions +#define FPU_FAST_MATH 1 + +#if defined(FPU_USE_ISO_C99) +// NOTE: no prior shall be included at this point +#define __USE_ISOC99 1 // for glibc 2.2.X and newer +#define __USE_ISOC9X 1 // for glibc 2.1.X +#include +#else +#include +using namespace std; +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Floating-point register types --- */ +/* -------------------------------------------------------------------------- */ + +// Single : S 8*E 23*F +#define FP_SINGLE_EXP_MAX 0xff +#define FP_SINGLE_EXP_BIAS 0x7f + +// Double : S 11*E 52*F +#define FP_DOUBLE_EXP_MAX 0x7ff +#define FP_DOUBLE_EXP_BIAS 0x3ff + +// Extended : S 15*E 64*F +#define FP_EXTENDED_EXP_MAX 0x7fff +#define FP_EXTENDED_EXP_BIAS 0x3fff + +// Zeroes : E = 0 & F = 0 +// Infinities : E = MAX & F = 0 +// Not-A-Number : E = MAX & F # 0 + +/* -------------------------------------------------------------------------- */ +/* --- Floating-point type shapes (IEEE-compliant) --- */ +/* -------------------------------------------------------------------------- */ + +// Taken from glibc 2.2.x: ieee754.h + +// IEEE-754 float format +union fpu_single_shape { + + fpu_single value; + + /* This is the IEEE 754 single-precision format. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; +#else + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; +#endif + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int quiet_nan:1; + unsigned int mantissa:22; +#else + unsigned int mantissa:22; + unsigned int quiet_nan:1; + unsigned int exponent:8; + unsigned int negative:1; +#endif + } ieee_nan; +}; + +// IEEE-754 double format +union fpu_double_shape { + fpu_double value; + + /* This is the IEEE 754 double-precision format. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:20; + unsigned int mantissa1:32; +#else +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:19; + unsigned int mantissa1:32; +#else +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif + } ieee_nan; + + /* This format is used to extract the sign_exponent and mantissa parts only */ + struct { +#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + unsigned int msw:32; + unsigned int lsw:32; +#else + unsigned int lsw:32; + unsigned int msw:32; +#endif + } parts; +}; + +#ifdef USE_LONG_DOUBLE +// IEEE-854 long double format +union fpu_extended_shape { + fpu_extended value; + + /* This is the IEEE 854 double-extended-precision format. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +#else +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:32; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee; + + /* This is for NaNs in the IEEE 854 double-extended-precision format. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int one:1; + unsigned int quiet_nan:1; + unsigned int mantissa0:30; + unsigned int mantissa1:32; +#else +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee_nan; + + /* This format is used to extract the sign_exponent and mantissa parts only */ + struct { +#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + unsigned int sign_exponent:16; + unsigned int empty:16; + unsigned int msw:32; + unsigned int lsw:32; +#else + unsigned int lsw:32; + unsigned int msw:32; + unsigned int sign_exponent:16; + unsigned int empty:16; +#endif + } parts; +}; +#endif + +#ifdef USE_QUAD_DOUBLE +// IEEE-854 quad double format +union fpu_extended_shape { + fpu_extended value; + + /* This is the IEEE 854 quad-precision format. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int mantissa0:16; + unsigned int mantissa1:32; + unsigned int mantissa2:32; + unsigned int mantissa3:32; +#else + unsigned int mantissa3:32; + unsigned int mantissa2:32; + unsigned int mantissa1:32; + unsigned int mantissa0:16; + unsigned int exponent:15; + unsigned int negative:1; +#endif + } ieee; + + /* This is for NaNs in the IEEE 854 quad-precision format. */ + struct { +#ifdef WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int quiet_nan:1; + unsigned int mantissa0:15; + unsigned int mantissa1:32; + unsigned int mantissa2:32; + unsigned int mantissa3:32; +#else + unsigned int mantissa3:32; + unsigned int mantissa2:32; + unsigned int mantissa1:32; + unsigned int mantissa0:15; + unsigned int quiet_nan:1; + unsigned int exponent:15; + unsigned int negative:1; +#endif + } ieee_nan; + + /* This format is used to extract the sign_exponent and mantissa parts only */ +#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN + struct { + uae_u64 msw; + uae_u64 lsw; + } parts64; + struct { + uae_u32 w0; + uae_u32 w1; + uae_u32 w2; + uae_u32 w3; + } parts32; +#else + struct { + uae_u64 lsw; + uae_u64 msw; + } parts64; + struct { + uae_u32 w3; + uae_u32 w2; + uae_u32 w1; + uae_u32 w0; + } parts32; +#endif +}; +#endif + +// Declare a shape of the requested FP type +#define fp_declare_init_shape(psvar, ftype) \ + fpu_ ## ftype ## _shape psvar + +/* -------------------------------------------------------------------------- */ +/* --- Extra Math Functions --- */ +/* --- (most of them had to be defined before including ) --- */ +/* -------------------------------------------------------------------------- */ + +#undef isnan +#if 0 && defined(HAVE_ISNANL) +# define isnan(x) isnanl((x)) +#else +# define isnan(x) fp_do_isnan((x)) +#endif + +PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r) +{ +#ifdef BRANCHES_ARE_EXPENSIVE +#if !defined(USE_LONG_DOUBLE) + fp_declare_init_shape(sxp, double); + sxp.value = r; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; + hx &= 0x7fffffff; + hx |= (uae_u32)(lx | (-lx)) >> 31; + hx = 0x7ff00000 - hx; + return (int)(((uae_u32)hx) >> 31); +#elif defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s64 hx = sxp.parts64.msw; + uae_s64 lx = sxp.parts64.lsw; + hx &= 0x7fffffffffffffffLL; + hx |= (uae_u64)(lx | (-lx)) >> 63; + hx = 0x7fff000000000000LL - hx; + return (int)((uae_u64)hx >> 63); +#else + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s32 se = sxp.parts.sign_exponent; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; + se = (se & 0x7fff) << 1; + lx |= hx & 0x7fffffff; + se |= (uae_u32)(lx | (-lx)) >> 31; + se = 0xfffe - se; + return (int)(((uae_u32)(se)) >> 31); +#endif +#else +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX) +#else + fp_declare_init_shape(sxp, double); + sxp.value = r; + return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX) +#endif + && (sxp.ieee_nan.mantissa0 != 0) + && (sxp.ieee_nan.mantissa1 != 0) +#ifdef USE_QUAD_DOUBLE + && (sxp.ieee_nan.mantissa2 != 0) + && (sxp.ieee_nan.mantissa3 != 0) +#endif + ; +#endif +} + +#undef isinf +#if 0 && defined(HAVE_ISINFL) +# define isinf(x) isinfl((x)) +#else +# define isinf(x) fp_do_isinf((x)) +#endif + +PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r) +{ +#ifdef BRANCHES_ARE_EXPENSIVE +#if !defined(USE_LONG_DOUBLE) + fp_declare_init_shape(sxp, double); + sxp.value = r; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; + lx |= (hx & 0x7fffffff) ^ 0x7ff00000; + lx |= -lx; + return ~(lx >> 31) & (hx >> 30); +#elif defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s64 hx = sxp.parts64.msw; + uae_s64 lx = sxp.parts64.lsw; + lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL; + lx |= -lx; + return ~(lx >> 63) & (hx >> 62); +#else + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s32 se = sxp.parts.sign_exponent; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; + /* This additional ^ 0x80000000 is necessary because in Intel's + internal representation of the implicit one is explicit. + NOTE: anyway, this is equivalent to & 0x7fffffff in that case. */ +#ifdef CPU_i386 + lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff); +#else + lx |= (hx & 0x7fffffff) | ((se & 0x7fff) ^ 0x7fff); +#endif + lx |= -lx; + se &= 0x8000; + return ~(lx >> 31) & (1 - (se >> 14)); +#endif +#else +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX) +#else + fp_declare_init_shape(sxp, double); + sxp.value = r; + return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX) +#endif + && (sxp.ieee_nan.mantissa0 == 0) + && (sxp.ieee_nan.mantissa1 == 0) +#ifdef USE_QUAD_DOUBLE + && (sxp.ieee_nan.mantissa2 == 0) + && (sxp.ieee_nan.mantissa3 == 0) +#endif + ; +#endif +} + +#undef isneg +#define isneg(x) fp_do_isneg((x)) + +PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); +#else + fp_declare_init_shape(sxp, double); +#endif + sxp.value = r; + return sxp.ieee.negative; +} + +#undef iszero +#define iszero(x) fp_do_iszero((x)) + +PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r) +{ + // TODO: BRANCHES_ARE_EXPENSIVE +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); +#else + fp_declare_init_shape(sxp, double); +#endif + sxp.value = r; + return (sxp.ieee.exponent == 0) + && (sxp.ieee.mantissa0 == 0) + && (sxp.ieee.mantissa1 == 0) +#ifdef USE_QUAD_DOUBLE + && (sxp.ieee.mantissa2 == 0) + && (sxp.ieee.mantissa3 == 0) +#endif + ; +} + +PRIVATE inline void FFPU get_dest_flags(fpu_register const & r) +{ + fl_dest.negative = isneg(r); + fl_dest.zero = iszero(r); + fl_dest.infinity = isinf(r); + fl_dest.nan = isnan(r); + fl_dest.in_range = !fl_dest.zero && !fl_dest.infinity && !fl_dest.nan; +} + +PRIVATE inline void FFPU get_source_flags(fpu_register const & r) +{ + fl_source.negative = isneg(r); + fl_source.zero = iszero(r); + fl_source.infinity = isinf(r); + fl_source.nan = isnan(r); + fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan; +} + +PRIVATE inline void FFPU make_nan(fpu_register & r) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.ieee.exponent = FP_EXTENDED_EXP_MAX; + sxp.ieee.mantissa0 = 0xffffffff; +#else + fp_declare_init_shape(sxp, double); + sxp.ieee.exponent = FP_DOUBLE_EXP_MAX; + sxp.ieee.mantissa0 = 0xfffff; +#endif + sxp.ieee.mantissa1 = 0xffffffff; +#ifdef USE_QUAD_DOUBLE + sxp.ieee.mantissa2 = 0xffffffff; + sxp.ieee.mantissa3 = 0xffffffff; +#endif + r = sxp.value; +} + +PRIVATE inline void FFPU make_zero_positive(fpu_register & r) +{ +#if 1 + r = +0.0; +#else +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); +#else + fp_declare_init_shape(sxp, double); +#endif + sxp.ieee.negative = 0; + sxp.ieee.exponent = 0; + sxp.ieee.mantissa0 = 0; + sxp.ieee.mantissa1 = 0; +#ifdef USE_QUAD_DOUBLE + sxp.ieee.mantissa2 = 0; + sxp.ieee.mantissa3 = 0; +#endif + r = sxp.value; +#endif +} + +PRIVATE inline void FFPU make_zero_negative(fpu_register & r) +{ +#if 1 + r = -0.0; +#else +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); +#else + fp_declare_init_shape(sxp, double); +#endif + sxp.ieee.negative = 1; + sxp.ieee.exponent = 0; + sxp.ieee.mantissa0 = 0; + sxp.ieee.mantissa1 = 0; +#ifdef USE_QUAD_DOUBLE + sxp.ieee.mantissa2 = 0; + sxp.ieee.mantissa3 = 0; +#endif + r = sxp.value; +#endif +} + +PRIVATE inline void FFPU make_inf_positive(fpu_register & r) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX; +#else + fp_declare_init_shape(sxp, double); + sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX; +#endif + sxp.ieee_nan.negative = 0; + sxp.ieee_nan.mantissa0 = 0; + sxp.ieee_nan.mantissa1 = 0; +#ifdef USE_QUAD_DOUBLE + sxp.ieee_nan.mantissa2 = 0; + sxp.ieee_nan.mantissa3 = 0; +#endif + r = sxp.value; +} + +PRIVATE inline void FFPU make_inf_negative(fpu_register & r) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX; +#else + fp_declare_init_shape(sxp, double); + sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX; +#endif + sxp.ieee_nan.negative = 1; + sxp.ieee_nan.mantissa0 = 0; + sxp.ieee_nan.mantissa1 = 0; +#ifdef USE_QUAD_DOUBLE + sxp.ieee_nan.mantissa2 = 0; + sxp.ieee_nan.mantissa3 = 0; +#endif + r = sxp.value; +} + +PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + return ((int) sxp.ieee.exponent - FP_EXTENDED_EXP_BIAS); +#else + fp_declare_init_shape(sxp, double); + sxp.value = r; + return ((int) sxp.ieee.exponent - FP_DOUBLE_EXP_BIAS); +#endif +} + +// Normalize to range 1..2 +PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + sxp.ieee.exponent = FP_EXTENDED_EXP_BIAS; +#else + fp_declare_init_shape(sxp, double); + sxp.value = r; + sxp.ieee.exponent = FP_DOUBLE_EXP_BIAS; +#endif + r = sxp.value; +} + +// The sign of the quotient is the exclusive-OR of the sign bits +// of the source and destination operands. +PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sap, extended); + fp_declare_init_shape(sbp, extended); +#else + fp_declare_init_shape(sap, double); + fp_declare_init_shape(sbp, double); +#endif + sap.value = ra; + sbp.value = rb; + return ((sap.ieee.negative ^ sbp.ieee.negative) ? FPSR_QUOTIENT_SIGN : 0); +} + +/* -------------------------------------------------------------------------- */ +/* --- Math functions --- */ +/* -------------------------------------------------------------------------- */ + +#if defined(FPU_USE_ISO_C99) && (defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)) +# ifdef HAVE_LOGL +# define fp_log logl +# endif +# ifdef HAVE_LOG10L +# define fp_log10 log10l +# endif +# ifdef HAVE_EXPL +# define fp_exp expl +# endif +# ifdef HAVE_POWL +# define fp_pow powl +# endif +# ifdef HAVE_FABSL +# define fp_fabs fabsl +# endif +# ifdef HAVE_SQRTL +# define fp_sqrt sqrtl +# endif +# ifdef HAVE_SINL +# define fp_sin sinl +# endif +# ifdef HAVE_COSL +# define fp_cos cosl +# endif +# ifdef HAVE_TANL +# define fp_tan tanl +# endif +# ifdef HAVE_SINHL +# define fp_sinh sinhl +# endif +# ifdef HAVE_COSHL +# define fp_cosh coshl +# endif +# ifdef HAVE_TANHL +# define fp_tanh tanhl +# endif +# ifdef HAVE_ASINL +# define fp_asin asinl +# endif +# ifdef HAVE_ACOSL +# define fp_acos acosl +# endif +# ifdef HAVE_ATANL +# define fp_atan atanl +# endif +# ifdef HAVE_ASINHL +# define fp_asinh asinhl +# endif +# ifdef HAVE_ACOSHL +# define fp_acosh acoshl +# endif +# ifdef HAVE_ATANHL +# define fp_atanh atanhl +# endif +# ifdef HAVE_FLOORL +# define fp_floor floorl +# endif +# ifdef HAVE_CEILL +# define fp_ceil ceill +# endif +#endif + +#ifndef fp_log +# define fp_log log +#endif +#ifndef fp_log10 +# define fp_log10 log10 +#endif +#ifndef fp_exp +# define fp_exp exp +#endif +#ifndef fp_pow +# define fp_pow pow +#endif +#ifndef fp_fabs +# define fp_fabs fabs +#endif +#ifndef fp_sqrt +# define fp_sqrt sqrt +#endif +#ifndef fp_sin +# define fp_sin sin +#endif +#ifndef fp_cos +# define fp_cos cos +#endif +#ifndef fp_tan +# define fp_tan tan +#endif +#ifndef fp_sinh +# define fp_sinh sinh +#endif +#ifndef fp_cosh +# define fp_cosh cosh +#endif +#ifndef fp_tanh +# define fp_tanh tanh +#endif +#ifndef fp_asin +# define fp_asin asin +#endif +#ifndef fp_acos +# define fp_acos acos +#endif +#ifndef fp_atan +# define fp_atan atan +#endif +#ifndef fp_asinh +# define fp_asinh asinh +#endif +#ifndef fp_acosh +# define fp_acosh acosh +#endif +#ifndef fp_atanh +# define fp_atanh atanh +#endif +#ifndef fp_floor +# define fp_floor floor +#endif +#ifndef fp_ceil +# define fp_ceil ceil +#endif + +#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) +// Assembly optimized support functions. Taken from glibc 2.2.2 + +#undef fp_log +#define fp_log fp_do_log + +#ifndef FPU_FAST_MATH +// FIXME: unimplemented +PRIVATE fpu_extended fp_do_log(fpu_extended x); +#else +PRIVATE inline fpu_extended fp_do_log(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)"); + return value; +} +#endif + +#undef fp_log10 +#define fp_log10 fp_do_log10 + +#ifndef FPU_FAST_MATH +// FIXME: unimplemented +PRIVATE fpu_extended fp_do_log10(fpu_extended x); +#else +PRIVATE inline fpu_extended fp_do_log10(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fldlg2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)"); + return value; +} +#endif + +#undef fp_exp +#define fp_exp fp_do_exp + +#ifndef FPU_FAST_MATH +// FIXME: unimplemented +PRIVATE fpu_extended fp_do_exp(fpu_extended x); +#else +PRIVATE inline fpu_extended fp_do_exp(fpu_extended x) +{ + fpu_extended value, exponent; + if (isinf(x)) + { + if(isneg(x)) + return 0.; + else + return x; + } + __asm__ __volatile__("fldl2e # e^x = 2^(x * log2(e))\n\t" + "fmul %%st(1) # x * log2(e)\n\t" + "fst %%st(1)\n\t" + "frndint # int(x * log2(e))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x * log2(e))\n\t" + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" + : "=t" (value), "=u" (exponent) : "0" (x)); + value += 1.0; + __asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent)); + return value; +} +#endif + +#undef fp_pow +#define fp_pow fp_do_pow + +PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y); + +#undef fp_fabs +#define fp_fabs fp_do_fabs + +PRIVATE inline fpu_extended fp_do_fabs(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fabs" : "=t" (value) : "0" (x)); + return value; +} + +#undef fp_sqrt +#define fp_sqrt fp_do_sqrt + +PRIVATE inline fpu_extended fp_do_sqrt(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fsqrt" : "=t" (value) : "0" (x)); + return value; +} + +#ifndef ACCURATE_SIN_COS_TAN +#undef fp_sin +#define fp_sin fp_do_sin + +PRIVATE inline fpu_extended fp_do_sin(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fsin" : "=t" (value) : "0" (x)); + return value; +} + +#undef fp_cos +#define fp_cos fp_do_cos + +PRIVATE inline fpu_extended fp_do_cos(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fcos" : "=t" (value) : "0" (x)); + return value; +} + +#undef fp_tan +#define fp_tan fp_do_tan + +PRIVATE inline fpu_extended fp_do_tan(fpu_extended x) +{ + fpu_extended value, value2; + __asm__ __volatile__("fptan" : "=t" (value2), "=u" (value) : "0" (x)); + return value; +} +#endif /* ACCURATE_SIN_COS_TAN */ + +#undef fp_expm1 +#define fp_expm1 fp_do_expm1 + +// Returns: exp(X) - 1.0 +PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) +{ + fpu_extended value, exponent, temp, temp2; + if (isinf(x)) + { + if(isneg(x)) + return -1.; + else + return x; + } + __asm__ __volatile__("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" + "fmul %%st(1) # x * log2(e)\n\t" + "fst %%st(1)\n\t" + "frndint # int(x * log2(e))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x * log2(e))\n\t" + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" + "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" + : "=t" (value), "=u" (exponent) : "0" (x)); + __asm__ __volatile__("fld1 \n\t" + "fscale \n\t" + : "=t" (temp), "=u" (temp2) : "0" (exponent)); + temp -= 1.0; + return temp + value ? temp + value : x; +} + +#undef fp_sgn1 +#define fp_sgn1 fp_do_sgn1 + +PRIVATE inline fpu_extended fp_do_sgn1(fpu_extended x) +{ +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = x; + sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX>>1; + sxp.ieee_nan.one = 1; +#else + fp_declare_init_shape(sxp, double); + sxp.value = x; + sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX>>1; +#endif + sxp.ieee_nan.quiet_nan = 0; + sxp.ieee_nan.mantissa0 = 0; + sxp.ieee_nan.mantissa1 = 0; + x = sxp.value; + return x; +} + +#undef fp_sinh +#define fp_sinh fp_do_sinh + +#ifndef FPU_FAST_MATH +// FIXME: unimplemented +PRIVATE fpu_extended fp_do_sinh(fpu_extended x); +#else +PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x) +{ + if (isinf(x)) return x; + fpu_extended exm1 = fp_expm1(fp_fabs(x)); + return 0.5 * (exm1 / (exm1 + 1.0) + exm1) * fp_sgn1(x); +} +#endif + +#undef fp_cosh +#define fp_cosh fp_do_cosh + +#ifndef FPU_FAST_MATH +// FIXME: unimplemented +PRIVATE fpu_extended fp_do_cosh(fpu_extended x); +#else +PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x) +{ + fpu_extended ex = fp_exp(x); + return 0.5 * (ex + 1.0 / ex); +} +#endif + +#undef fp_tanh +#define fp_tanh fp_do_tanh + +#ifndef FPU_FAST_MATH +// FIXME: unimplemented +PRIVATE fpu_extended fp_do_tanh(fpu_extended x); +#else +PRIVATE inline fpu_extended fp_do_tanh(fpu_extended x) +{ + fpu_extended exm1 = fp_expm1(-fp_fabs(x + x)); + return exm1 / (exm1 + 2.0) * fp_sgn1(-x); +} +#endif + +#undef fp_atan2 +#define fp_atan2 fp_do_atan2 + +PRIVATE inline fpu_extended fp_do_atan2(fpu_extended y, fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fpatan" : "=t" (value) : "0" (x), "u" (y) : "st(1)"); + return value; +} + +#undef fp_asin +#define fp_asin fp_do_asin + +PRIVATE inline fpu_extended fp_do_asin(fpu_extended x) +{ + return fp_atan2(x, fp_sqrt(1.0 - x * x)); +} + +#undef fp_acos +#define fp_acos fp_do_acos + +PRIVATE inline fpu_extended fp_do_acos(fpu_extended x) +{ + return fp_atan2(fp_sqrt(1.0 - x * x), x); +} + +#undef fp_atan +#define fp_atan fp_do_atan + +PRIVATE inline fpu_extended fp_do_atan(fpu_extended x) +{ + fpu_extended value; + __asm__ __volatile__("fld1; fpatan" : "=t" (value) : "0" (x) : "st(1)"); + return value; +} + +#undef fp_log1p +#define fp_log1p fp_do_log1p + +// Returns: ln(1.0 + X) +PRIVATE fpu_extended fp_do_log1p(fpu_extended x); + +#undef fp_asinh +#define fp_asinh fp_do_asinh + +PRIVATE inline fpu_extended fp_do_asinh(fpu_extended x) +{ + fpu_extended y = fp_fabs(x); + return (fp_log1p(y * y / (fp_sqrt(y * y + 1.0) + 1.0) + y) * fp_sgn1(x)); +} + +#undef fp_acosh +#define fp_acosh fp_do_acosh + +PRIVATE inline fpu_extended fp_do_acosh(fpu_extended x) +{ + return fp_log(x + fp_sqrt(x - 1.0) * fp_sqrt(x + 1.0)); +} + +#undef fp_atanh +#define fp_atanh fp_do_atanh + +PRIVATE inline fpu_extended fp_do_atanh(fpu_extended x) +{ + fpu_extended y = fp_fabs(x); + return -0.5 * fp_log1p(-(y + y) / (1.0 + y)) * fp_sgn1(x); +} + + +/* + * LLVM 2.9 crashes on first definition, + * clang with LLVM 3.x crashes on 2nd definition... sigh + */ +#if defined(__clang__) || !defined(__llvm__) +#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ +PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended __x) \ +{ \ + register long double __value; \ + register int __ignore; \ + volatile unsigned short __cw; \ + volatile unsigned short __cwtmp; \ + __asm __volatile ("fnstcw %3\n\t" \ + "movzwl %3, %1\n\t" \ + "andl $0xf3ff, %1\n\t" \ + "orl %5, %1\n\t" \ + "movw %w1, %2\n\t" \ + "fldcw %2\n\t" \ + "frndint\n\t" \ + "fldcw %3" \ + : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ + "=m" (__cw) \ + : "0" (__x), "i"(rounding_mode)); \ + return __value; \ +} +#else +#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ +PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended x) \ +{ \ + volatile unsigned short cw; \ + __asm__ __volatile__("fnstcw %0" : "=m" (cw)); \ + volatile unsigned short cw_temp = (cw & 0xf3ff) | (rounding_mode); \ + __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); \ + fpu_extended value; \ + __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); \ + __asm__ __volatile__("fldcw %0" : : "m" (cw)); \ + return value; \ +} +#endif + +#undef fp_round_to_minus_infinity +#define fp_round_to_minus_infinity fp_do_round_to_minus_infinity + +DEFINE_ROUND_FUNC(minus_infinity, 0x400) + +#undef fp_round_to_plus_infinity +#define fp_round_to_plus_infinity fp_do_round_to_plus_infinity + +DEFINE_ROUND_FUNC(plus_infinity, 0x800) + +#undef fp_round_to_zero +#define fp_round_to_zero fp_do_round_to_zero + +DEFINE_ROUND_FUNC(zero, 0xc00) + +#undef fp_round_to_nearest +#define fp_round_to_nearest fp_do_round_to_nearest + +DEFINE_ROUND_FUNC(nearest, 0x000) + +#undef fp_ceil +#define fp_ceil fp_do_round_to_plus_infinity + +#undef fp_floor +#define fp_floor fp_do_round_to_minus_infinity + + +#endif /* USE_X87_ASSEMBLY */ + +#ifndef fp_round_to_minus_infinity +#define fp_round_to_minus_infinity(x) fp_floor(x) +#endif + +#ifndef fp_round_to_plus_infinity +#define fp_round_to_plus_infinity(x) fp_ceil(x) +#endif + +#ifndef fp_round_to_zero +#define fp_round_to_zero(x) ((int)(x)) +#endif + +#ifndef fp_round_to_nearest +#define fp_round_to_nearest(x) ((int)((x) + 0.5)) +#endif + +#endif /* FPU_MATHLIB_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.cpp b/BasiliskII/src/uae_cpu/fpu/rounding.cpp new file mode 100644 index 00000000..9942d4e8 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/rounding.cpp @@ -0,0 +1,69 @@ +/* + * fpu/rounding.cpp - system-dependant FPU rounding mode and precision + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#undef PRIVATE +#define PRIVATE /**/ + +#undef PUBLIC +#define PUBLIC /**/ + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* -------------------------------------------------------------------------- */ +/* --- Native X86 Rounding Mode --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_X86_ROUNDING_MODE +const uae_u32 FFPU x86_control_word_rm_mac2host[] = { + CW_RC_NEAR, + CW_RC_ZERO, + CW_RC_DOWN, + CW_RC_UP +}; +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Native X86 Rounding Precision --- */ +/* -------------------------------------------------------------------------- */ + +#ifdef FPU_USE_X86_ROUNDING_PRECISION +const uae_u32 FFPU x86_control_word_rp_mac2host[] = { + CW_PC_EXTENDED, + CW_PC_SINGLE, + CW_PC_DOUBLE, + CW_PC_RESERVED +}; +#endif diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.h b/BasiliskII/src/uae_cpu/fpu/rounding.h new file mode 100644 index 00000000..60c4baff --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/rounding.h @@ -0,0 +1,159 @@ +/* + * fpu/rounding.h - system-dependant FPU rounding mode and precision + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_ROUNDING_H +#define FPU_ROUNDING_H + +/* NOTE: this file shall be included from fpu/fpu_*.cpp */ +#undef PUBLIC +#define PUBLIC extern + +#undef PRIVATE +#define PRIVATE static + +#undef FFPU +#define FFPU /**/ + +#undef FPU +#define FPU fpu. + +/* Defaults to generic rounding mode and precision handling */ +#define FPU_USE_GENERIC_ROUNDING_MODE +#define FPU_USE_GENERIC_ROUNDING_PRECISION + +/* -------------------------------------------------------------------------- */ +/* --- Selection of floating-point rounding mode and precision --- */ +/* -------------------------------------------------------------------------- */ + +/* Optimized i386 fpu core must use native rounding mode */ +#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_ROUNDING_MODE +# define FPU_USE_X86_ROUNDING_MODE +#endif + +/* Optimized i386 fpu core must use native rounding precision */ +#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_ROUNDING_PRECISION +# define FPU_USE_X86_ROUNDING_PRECISION +#endif + +#if 0 // gb-- FIXME: that doesn't work +/* IEEE-based fpu core can have native rounding mode on i386 */ +#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_ROUNDING_MODE +# define FPU_USE_X86_ROUNDING_MODE +#endif + +/* IEEE-based fpu core can have native rounding precision on i386 */ +#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) +# undef FPU_USE_GENERIC_ROUNDING_PRECISION +# define FPU_USE_X86_ROUNDING_PRECISION +#endif +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Sanity checks --- */ +/* -------------------------------------------------------------------------- */ + +/* X86 rounding mode and precision work together */ +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) +# define FPU_USE_X86_ROUNDING +# define CW_INITIAL (CW_RESET|CW_X|CW_PC_EXTENDED|CW_RC_NEAR|CW_PM|CW_UM|CW_OM|CW_ZM|CW_DM|CW_IM) + PRIVATE uae_u32 x86_control_word; +#endif + +/* Control word -- rounding mode */ +#ifdef FPU_USE_X86_ROUNDING_MODE +PUBLIC const uae_u32 x86_control_word_rm_mac2host[]; +#endif + +/* Control word -- rounding precision */ +#ifdef FPU_USE_X86_ROUNDING_PRECISION +PUBLIC const uae_u32 x86_control_word_rp_mac2host[]; +#endif + +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) +/* Set host control word for rounding mode and rounding precision */ +PRIVATE inline void set_host_control_word(void) +{ + /* + Exception enable byte is ignored, but the same value is returned + that was previously set. + */ + x86_control_word + = (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION)) + | x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4] + | x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6] + ; + __asm__ __volatile__("fldcw %0" : : "m" (x86_control_word)); +} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Generic rounding mode and precision --- */ +/* -------------------------------------------------------------------------- */ + +#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION) +/* Set host control word for rounding mode and rounding precision */ +PRIVATE inline void set_host_control_word(void) + { } +#endif + +/* -------------------------------------------------------------------------- */ +/* --- Common rounding mode and precision --- */ +/* -------------------------------------------------------------------------- */ + +#if defined(FPU_USE_GENERIC_ROUNDING_MODE) || defined(FPU_USE_X86_ROUNDING_MODE) + +/* Return the current rounding mode in m68k format */ +static inline uae_u32 FFPU get_rounding_mode(void) + { return FPU fpcr.rounding_mode; } + +/* Convert and set to native rounding mode */ +static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode) + { FPU fpcr.rounding_mode = new_rounding_mode; } + +#endif + +#if defined(FPU_USE_GENERIC_ROUNDING_PRECISION) || defined(FPU_USE_X86_ROUNDING_PRECISION) + +/* Return the current rounding precision in m68k format */ +static inline uae_u32 FFPU get_rounding_precision(void) + { return FPU fpcr.rounding_precision; } + +/* Convert and set to native rounding precision */ +static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision) + { FPU fpcr.rounding_precision = new_rounding_precision; } + +#endif + +#endif /* FPU_ROUNDING_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h new file mode 100644 index 00000000..afd3ab28 --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/types.h @@ -0,0 +1,181 @@ +/* + * fpu/types.h - basic types for fpu registers + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FPU_TYPES_H +#define FPU_TYPES_H + +#include "sysdeps.h" + +/* Default behavior is *not* to use long doubles */ +#undef USE_LONG_DOUBLE +#undef USE_QUAD_DOUBLE + +/* -------------------------------------------------------------------------- */ +/* --- Original UAE fpu core --- */ +/* -------------------------------------------------------------------------- */ + +#if defined(FPU_UAE) + +/* 4-byte floats */ +#if SIZEOF_FLOAT == 4 +typedef float uae_f32; +#elif SIZEOF_DOUBLE == 4 +typedef double uae_f32; +#else +#error "No 4 byte float type, you lose." +#endif + +/* 8-byte floats */ +#if SIZEOF_DOUBLE == 8 +typedef double uae_f64; +#elif SIZEOF_LONG_DOUBLE == 8 +typedef long double uae_f64; +#else +#error "No 8 byte float type, you lose." +#endif + +/* Original UAE FPU registers are only 8 bytes long */ +typedef uae_f64 fpu_register; +typedef fpu_register fpu_extended; +typedef uae_f64 fpu_double; +typedef uae_f32 fpu_single; + +/* -------------------------------------------------------------------------- */ +/* --- Optimized core for x86 --- */ +/* -------------------------------------------------------------------------- */ + +#elif defined(FPU_X86) + +/* 4-byte floats */ +#if SIZEOF_FLOAT == 4 +typedef float uae_f32; +#elif SIZEOF_DOUBLE == 4 +typedef double uae_f32; +#else +#error "No 4 byte float type, you lose." +#endif + +/* 8-byte floats */ +#if SIZEOF_DOUBLE == 8 +typedef float uae_f64; +#elif SIZEOF_LONG_DOUBLE == 8 +typedef double uae_f64; +#else +#error "No 8 byte float type, you lose." +#endif + +/* At least 10-byte floats are required */ +#if SIZEOF_LONG_DOUBLE >= 10 +typedef long double fpu_register; +#else +#error "No float type at least 10 bytes long, you lose." +#endif + +/* X86 FPU has a custom register type that maps to a native X86 register */ +typedef fpu_register fpu_extended; +typedef uae_f64 fpu_double; +typedef uae_f32 fpu_single; + +/* -------------------------------------------------------------------------- */ +/* --- C99 implementation --- */ +/* -------------------------------------------------------------------------- */ + +#elif defined(FPU_IEEE) + +#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT +#error "No IEEE float format, you lose." +#endif + +/* 4-byte floats */ +#if SIZEOF_FLOAT == 4 +typedef float uae_f32; +#elif SIZEOF_DOUBLE == 4 +typedef double uae_f32; +#else +#error "No 4 byte float type, you lose." +#endif + +/* 8-byte floats */ +#if SIZEOF_DOUBLE == 8 +typedef double uae_f64; +#elif SIZEOF_LONG_DOUBLE == 8 +typedef long double uae_f64; +#else +#error "No 8 byte float type, you lose." +#endif + +/* 12-byte or 16-byte floats */ +#if SIZEOF_LONG_DOUBLE == 12 +typedef long double uae_f96; +typedef uae_f96 fpu_register; +#define USE_LONG_DOUBLE 1 +#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64)) +/* Long doubles on x86-64 are really held in old x87 FPU stack. */ +typedef long double uae_f128; +typedef uae_f128 fpu_register; +#define USE_LONG_DOUBLE 1 +#elif 0 +/* Disable for now and probably for good as (i) the emulator + implementation is not correct, (ii) I don't know of any CPU which + handles this kind of format *natively* with conformance to IEEE. */ +typedef long double uae_f128; +typedef uae_f128 fpu_register; +#define USE_QUAD_DOUBLE 1 +#else +typedef uae_f64 fpu_register; +#endif + +/* We need all those floating-point types */ +typedef fpu_register fpu_extended; +typedef uae_f64 fpu_double; +typedef uae_f32 fpu_single; + +#elif defined(FPU_MPFR) + +#include + +struct fpu_register { + mpfr_t f; + uae_u64 nan_bits; + int nan_sign; + operator long double (); + fpu_register &operator=(long double); +}; + +#endif + +union fpu_register_parts { + fpu_register val; + uae_u32 parts[sizeof(fpu_register) / 4]; +}; + +#endif /* FPU_TYPES_H */ diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 8e2502a3..8db74001 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -1,3 +1,27 @@ +/* + * gencpu.c - m68k emulation generator + * + * Copyright (c) 2009 ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * @@ -16,22 +40,24 @@ * Copyright 1995, 1996 Bernd Schmidt */ -#include -#include -#include -#include +#define CC_FOR_BUILD 1 #include "sysdeps.h" #include "readcpu.h" -#if defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) -#define SPARC_ASSEMBLY 0 -#endif +#include +#include +#include +#include +#include +#undef abort #define BOOL_TYPE "int" +#define VERIFY_MMU_GENAMODE 0 static FILE *headerfile; static FILE *stblfile; +static FILE *functblfile; static int using_prefetch; static int using_exception_3; @@ -47,6 +73,23 @@ static int *opcode_next_clev; static int *opcode_last_postfix; static unsigned long *counts; +#define GENA_GETV_NO_FETCH 0 +#define GENA_GETV_FETCH 1 +#define GENA_GETV_FETCH_ALIGN 2 +#define GENA_MOVEM_DO_INC 0 +#define GENA_MOVEM_NO_INC 1 +#define GENA_MOVEM_MOVE16 2 + +#define XLATE_LOG 0 +#define XLATE_PHYS 1 +#define XLATE_SFC 2 +#define XLATE_DFC 3 +static char * mem_prefix[4] = { "", "phys_", "sfc_", "dfc_" }; + +/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ +#define xBCD_KEEPS_N_FLAG 4 +#define xBCD_KEEPS_V_FLAG 3 + static void read_counts (void) { FILE *file; @@ -57,7 +100,8 @@ static void read_counts (void) file = fopen ("frequent.68k", "r"); if (file) { - fscanf (file, "Total: %lu\n", &total); + int c = fscanf (file, "Total: %lu\n", &total); + assert(c == 1); while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) { opcode_next_clev[nr] = 4; opcode_last_postfix[nr] = -1; @@ -88,7 +132,6 @@ static int need_endlabel; static int n_braces = 0; static int m68k_pc_offset = 0; -static int insn_n_cycles; static void start_brace (void) { @@ -141,9 +184,8 @@ static const char *gen_nextilong (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 4; - insn_n_cycles += 4; + m68k_pc_offset += 4; if (using_prefetch) sprintf (buffer, "get_ilong_prefetch(%d)", r); @@ -156,9 +198,8 @@ static const char *gen_nextiword (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 2; - insn_n_cycles += 2; + m68k_pc_offset += 2; if (using_prefetch) sprintf (buffer, "get_iword_prefetch(%d)", r); @@ -173,8 +214,6 @@ static const char *gen_nextibyte (void) int r = m68k_pc_offset; m68k_pc_offset += 2; - insn_n_cycles += 2; - if (using_prefetch) sprintf (buffer, "get_ibyte_prefetch(%d)", r); else @@ -196,9 +235,22 @@ static void fill_prefetch_2 (void) static void swap_opcode (void) { - printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - printf ("\topcode = ((opcode << 8) & 0xFF00) | ((opcode >> 8) & 0xFF);\n"); - printf ("#endif\n"); + printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + printf ("\topcode = do_byteswap_16(opcode);\n"); + printf("#endif\n"); +} + +static void real_opcode (int *have) +{ + if (!*have) + { + printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + printf ("\tuae_u32 real_opcode = do_byteswap_16(opcode);\n"); + printf("#else\n"); + printf ("\tuae_u32 real_opcode = opcode;\n"); + printf("#endif\n"); + *have = 1; + } } static void sync_m68k_pc (void) @@ -220,32 +272,49 @@ static void sync_m68k_pc (void) m68k_pc_offset = 0; } -/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, - * the calling routine handles Apdi and Aipi modes. */ -static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) +static void gen_set_fault_pc (void) { + sync_m68k_pc(); + printf ("regs.fault_pc = m68k_getpc ();\n"); + m68k_pc_offset = 0; +} + +/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, + * the calling routine handles Apdi and Aipi modes. + * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ + +/* fixup indicates if we want to fix up adress registers in pre decrement + * or post increment mode now (0) or later (1). A value of 2 will then be + * used to do the actual fix up. This allows to do all memory readings + * before any register is modified, and so to rerun operation without + * side effect in case a bus fault is generated by any memory access. + * XJ - 2006/11/13 */ +static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag, int fixup) +{ + if (fixup != 2) + { start_brace (); switch (mode) { case Dreg: if (movem) abort (); - if (getv == 1) + if (getv == GENA_GETV_FETCH) switch (size) { case sz_byte: -#if defined(AMIGA) && !defined(WARPUP) + printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); /* sam: I don't know why gcc.2.7.2.1 produces a code worse */ /* if it is not done like that: */ printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg); -#else + printf("#else\n"); printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg); -#endif + printf("#endif\n"); break; case sz_word: -#if defined(AMIGA) && !defined(WARPUP) + printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg); -#else + printf("#else\n"); printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg); -#endif + printf("#endif\n"); break; case sz_long: printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg); @@ -257,7 +326,7 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge case Areg: if (movem) abort (); - if (getv == 1) + if (getv == GENA_GETV_FETCH) switch (size) { case sz_word: printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg); @@ -284,10 +353,16 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg); break; case sz_word: - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2); + if (movem) + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); + else + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 2;\n", name, reg); break; case sz_long: - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4); + if (movem) + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); + else + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 4;\n", name, reg); break; default: abort (); @@ -332,7 +407,7 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ()); break; case imm: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); switch (size) { case sz_byte: @@ -349,22 +424,22 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge } return; case imm0: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ()); return; case imm1: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ()); return; case imm2: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ()); return; case immi: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_u32 %s = %s;\n", name, reg); return; @@ -375,7 +450,7 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge /* We get here for all non-reg non-immediate addressing modes to * actually fetch the value. */ - if (using_exception_3 && getv != 0 && size != sz_byte) { + if (using_exception_3 && getv != GENA_GETV_NO_FETCH && size != sz_byte) { printf ("\tif ((%sa & 1) != 0) {\n", name); printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name); printf ("\t\tlast_op_for_exception_3 = opcode;\n"); @@ -387,20 +462,29 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge start_brace (); } - if (getv == 1) { + if (getv == GENA_GETV_FETCH) { switch (size) { - case sz_byte: insn_n_cycles += 2; break; - case sz_word: insn_n_cycles += 2; break; - case sz_long: insn_n_cycles += 4; break; + case sz_byte: break; + case sz_word: break; + case sz_long: break; default: abort (); } start_brace (); + printf("\n#ifdef FULLMMU\n"); switch (size) { - case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break; - case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break; - case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break; + case sz_byte: printf ("\tuae_s8 %s = %sget_byte(%sa);\n", name, mem_prefix[xlateflag], name); break; + case sz_word: printf ("\tuae_s16 %s = %sget_word(%sa);\n", name, mem_prefix[xlateflag], name); break; + case sz_long: printf ("\tuae_s32 %s = %sget_long(%sa);\n", name, mem_prefix[xlateflag], name); break; default: abort (); } + printf("#else\n"); + switch (size) { + case sz_byte: printf ("\tuae_s8 %s = phys_get_byte(%sa);\n", name, name); break; + case sz_word: printf ("\tuae_s16 %s = phys_get_word(%sa);\n", name, name); break; + case sz_long: printf ("\tuae_s32 %s = phys_get_long(%sa);\n", name, name); break; + default: abort (); + } + printf("#endif\n"); } /* We now might have to fix up the register for pre-dec or post-inc @@ -408,6 +492,12 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge if (!movem) switch (mode) { case Aipi: + if (fixup == 1) + { + printf ("\tfixup.flag = 1;\n"); + printf ("\tfixup.reg = %s;\n", reg); + printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); + } switch (size) { case sz_byte: printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg); @@ -423,14 +513,39 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge } break; case Apdi: + if (fixup == 1) + { + printf ("\tfixup.flag = 1;\n"); + printf ("\tfixup.reg = %s;\n", reg); + printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); + } printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name); break; default: break; } + + } + else /* (fixup != 2) */ + { + if (!movem) + switch (mode) { + case Aipi: + case Apdi: + printf ("\tfixup.flag = 0;\n"); + break; + default: + break; + } + } } -static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to) +static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag) +{ + genamode2 (mode, reg, size, name, getv, movem, xlateflag, 0); +} + +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag) { switch (mode) { case Dreg: @@ -470,28 +585,32 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char case absl: case PC16: case PC8r: - if (using_prefetch) - sync_m68k_pc (); + gen_set_fault_pc (); + printf("#ifdef FULLMMU\n"); switch (size) { case sz_byte: - insn_n_cycles += 2; + printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from); + printf("#else\n"); printf ("\tput_byte(%sa,%s);\n", to, from); break; case sz_word: - insn_n_cycles += 2; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); + printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from); + printf("#else\n"); printf ("\tput_word(%sa,%s);\n", to, from); break; case sz_long: - insn_n_cycles += 4; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); + printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from); + printf("#else\n"); printf ("\tput_long(%sa,%s);\n", to, from); break; default: abort (); } + printf("#endif\n"); break; case imm: case imm0: @@ -507,23 +626,33 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char static void genmovemel (uae_u16 opcode) { - char getcode[100]; + char getcode1[100]; + char getcode2[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; - + if (table68k[opcode].size == sz_long) { - strcpy (getcode, "get_long(srca)"); + strcpy (getcode1, ""); + strcpy (getcode2, "get_long(srca)"); } else { - strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)"); + strcpy (getcode1, "(uae_s32)(uae_s16)"); + strcpy (getcode2, "get_word(srca)"); } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); start_brace (); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", - getcode, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n", - getcode, size); + printf("\n#ifdef FULLMMU\n"); + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s%s; srca += %d; dmask = movem_next[dmask]; }\n", + getcode1, getcode2, size); + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s%s; srca += %d; amask = movem_next[amask]; }\n", + getcode1, getcode2, size); + printf("#else\n"); + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %sphys_%s; srca += %d; dmask = movem_next[dmask]; }\n", + getcode1, getcode2, size); + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %sphys_%s; srca += %d; amask = movem_next[amask]; }\n", + getcode1, getcode2, size); + printf("#endif\n"); if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg(regs, dstreg) = srca;\n"); @@ -533,6 +662,7 @@ static void genmovemle (uae_u16 opcode) { char putcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; + if (table68k[opcode].size == sz_long) { strcpy (putcode, "put_long(srca,"); } else { @@ -540,24 +670,38 @@ static void genmovemle (uae_u16 opcode) } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); - if (using_prefetch) - sync_m68k_pc (); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", + GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); + sync_m68k_pc (); start_brace (); if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); + printf("#ifdef FULLMMU\n"); printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", size, putcode); printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", size, putcode); + printf("#else\n"); + printf ("\twhile (amask) { srca -= %d; phys_%s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", + size, putcode); + printf ("\twhile (dmask) { srca -= %d; phys_%s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", + size, putcode); + printf("#endif\n"); printf ("\tm68k_areg(regs, dstreg) = srca;\n"); } else { printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); + printf("#ifdef FULLMMU\n"); printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", putcode, size); printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", putcode, size); + printf("#else\n"); + printf ("\twhile (dmask) { phys_%s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", + putcode, size); + printf ("\twhile (amask) { phys_%s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", + putcode, size); + printf("#endif\n"); } } @@ -567,7 +711,7 @@ static void duplicate_carry (void) } typedef enum { - flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn, + flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_z, flag_zn, flag_av, flag_sv } flagtypes; @@ -621,6 +765,7 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * switch (type) { case flag_logical_noclobber: case flag_logical: + case flag_z: case flag_zn: case flag_av: case flag_sv: @@ -629,12 +774,10 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * break; case flag_add: - start_brace (); printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr); break; case flag_sub: case flag_cmp: - start_brace (); printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr); break; } @@ -642,6 +785,7 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * switch (type) { case flag_logical_noclobber: case flag_logical: + case flag_z: case flag_zn: break; @@ -652,7 +796,6 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * case flag_cmp: case flag_av: case flag_sv: - start_brace (); printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr); printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr); printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr); @@ -675,6 +818,9 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * case flag_sv: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n"); break; + case flag_z: + printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr); + break; case flag_zn: printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr); printf ("\tSET_NFLG (%s < 0);\n", vstr); @@ -714,163 +860,18 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * static void genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst) { -#ifdef SPARC_V8_ASSEMBLY - switch(type) - { - case flag_add: - start_brace(); - printf("\tuae_u32 %s;\n", value); - switch(size) - { - case sz_byte: - printf("\t%s = sparc_v8_flag_add_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_word: - printf("\t%s = sparc_v8_flag_add_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_long: - printf("\t%s = sparc_v8_flag_add_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - } - return; - - case flag_sub: - start_brace(); - printf("\tuae_u32 %s;\n", value); - switch(size) - { - case sz_byte: - printf("\t%s = sparc_v8_flag_sub_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_word: - printf("\t%s = sparc_v8_flag_sub_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_long: - printf("\t%s = sparc_v8_flag_sub_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - } - return; - - case flag_cmp: - switch(size) - { - case sz_byte: -// printf("\tsparc_v8_flag_cmp_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); - break; - case sz_word: -// printf("\tsparc_v8_flag_cmp_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); - break; - case sz_long: -#if 1 - printf("\tsparc_v8_flag_cmp_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); - return; -#endif - break; - } -// return; - break; - } -#elif defined(SPARC_V9_ASSEMBLY) - switch(type) - { - case flag_add: - start_brace(); - printf("\tuae_u32 %s;\n", value); - switch(size) - { - case sz_byte: - printf("\t%s = sparc_v9_flag_add_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_word: - printf("\t%s = sparc_v9_flag_add_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_long: - printf("\t%s = sparc_v9_flag_add_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - } - return; - - case flag_sub: - start_brace(); - printf("\tuae_u32 %s;\n", value); - switch(size) - { - case sz_byte: - printf("\t%s = sparc_v9_flag_sub_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_word: - printf("\t%s = sparc_v9_flag_sub_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - case sz_long: - printf("\t%s = sparc_v9_flag_sub_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", value, src, dst); - break; - } - return; - - case flag_cmp: - switch(size) - { - case sz_byte: - printf("\tsparc_v9_flag_cmp_8(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); - break; - case sz_word: - printf("\tsparc_v9_flag_cmp_16(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); - break; - case sz_long: - printf("\tsparc_v9_flag_cmp_32(®flags, (uae_u32)(%s), (uae_u32)(%s));\n", src, dst); - break; - } - return; - - case flag_logical: - if (strcmp(value, "0") == 0) { - printf("\tregflags.nzvc = 0x04;\n"); - } else { - switch(size) { - case sz_byte: - printf("\tsparc_v9_flag_test_8(®flags, (uae_u32)(%s));\n", value); - break; - case sz_word: - printf("\tsparc_v9_flag_test_16(®flags, (uae_u32)(%s));\n", value); - break; - case sz_long: - printf("\tsparc_v9_flag_test_32(®flags, (uae_u32)(%s));\n", value); - break; - } - } - return; - -#if 0 - case flag_logical_noclobber: - printf("\t{uae_u32 old_flags = regflags.nzvc & ~0x0C;\n"); - if (strcmp(value, "0") == 0) { - printf("\tregflags.nzvc = old_flags | 0x04;\n"); - } else { - switch(size) { - case sz_byte: - printf("\tsparc_v9_flag_test_8(®flags, (uae_u32)(%s));\n", value); - break; - case sz_word: - printf("\tsparc_v9_flag_test_16(®flags, (uae_u32)(%s));\n", value); - break; - case sz_long: - printf("\tsparc_v9_flag_test_32(®flags, (uae_u32)(%s));\n", value); - break; - } - printf("\tregflags.nzvc |= old_flags;\n"); - } - printf("\t}\n"); - return; -#endif - } -#elif defined(X86_ASSEMBLY) + /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have + them in the appropriate m68k.h files and use just one copy of this + code here. The API can be changed if necessary. */ + int done = 0; + + start_brace (); + printf("\n#ifdef OPTIMIZED_FLAGS\n"); switch (type) { case flag_add: case flag_sub: - start_brace (); printf ("\tuae_u32 %s;\n", value); break; - default: break; } @@ -878,233 +879,71 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch /* At least some of those casts are fairly important! */ switch (type) { case flag_logical_noclobber: - printf ("\t{uae_u32 oldcznv = regflags.cznv & ~0xC0;\n"); + printf ("\t{uae_u32 oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n"); if (strcmp (value, "0") == 0) { - printf ("\tregflags.cznv = olcznv | 64;\n"); + printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n"); } else { switch (size) { - case sz_byte: printf ("\tx86_flag_testb ((uae_s8)(%s));\n", value); break; - case sz_word: printf ("\tx86_flag_testw ((uae_s16)(%s));\n", value); break; - case sz_long: printf ("\tx86_flag_testl ((uae_s32)(%s));\n", value); break; + case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break; + case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break; + case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; } - printf ("\tregflags.cznv |= oldcznv;\n"); + printf ("\tIOR_CZNV (oldcznv);\n"); } printf ("\t}\n"); - return; + done = 1; + break; + case flag_logical: if (strcmp (value, "0") == 0) { - printf ("\tregflags.cznv = 64;\n"); + printf ("\tSET_CZNV (FLAGVAL_Z);\n"); } else { switch (size) { - case sz_byte: printf ("\tx86_flag_testb ((uae_s8)(%s));\n", value); break; - case sz_word: printf ("\tx86_flag_testw ((uae_s16)(%s));\n", value); break; - case sz_long: printf ("\tx86_flag_testl ((uae_s32)(%s));\n", value); break; + case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break; + case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break; + case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; } } - return; + done = 1; + break; case flag_add: switch (size) { - case sz_byte: printf ("\tx86_flag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; - case sz_word: printf ("\tx86_flag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; - case sz_long: printf ("\tx86_flag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; + case sz_byte: printf ("\toptflag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; + case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; + case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - return; + done = 1; + break; case flag_sub: switch (size) { - case sz_byte: printf ("\tx86_flag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; - case sz_word: printf ("\tx86_flag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; - case sz_long: printf ("\tx86_flag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; + case sz_byte: printf ("\toptflag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break; + case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; + case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - return; + done = 1; + break; case flag_cmp: switch (size) { - case sz_byte: printf ("\tx86_flag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break; - case sz_word: printf ("\tx86_flag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; - case sz_long: printf ("\tx86_flag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; + case sz_byte: printf ("\toptflag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break; + case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; + case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; } - return; + done = 1; + break; default: break; } -#elif defined(M68K_FLAG_OPT) - /* sam: here I'm cloning what X86_ASSEMBLY does */ -#define EXT(size) (size==sz_byte?"b":(size==sz_word?"w":"l")) -#define CAST(size) (size==sz_byte?"uae_s8":(size==sz_word?"uae_s16":"uae_s32")) - switch (type) { - case flag_add: - case flag_sub: - start_brace (); - printf ("\tuae_u32 %s;\n", value); - break; - - default: - break; - } - - switch (type) { - case flag_logical: - if (strcmp (value, "0") == 0) { - printf ("\t*(uae_u16 *)®flags = 4;\n"); /* Z = 1 */ - } else { - printf ("\tm68k_flag_tst (%s, (%s)(%s));\n", - EXT (size), CAST (size), value); - } - return; - - case flag_add: - printf ("\t{uae_u16 ccr;\n"); - printf ("\tm68k_flag_add (%s, (%s)%s, (%s)(%s), (%s)(%s));\n", - EXT (size), CAST (size), value, CAST (size), src, CAST (size), dst); - printf ("\t((uae_u16*)®flags)[1]=((uae_u16*)®flags)[0]=ccr;}\n"); - return; - - case flag_sub: - printf ("\t{uae_u16 ccr;\n"); - printf ("\tm68k_flag_sub (%s, (%s)%s, (%s)(%s), (%s)(%s));\n", - EXT (size), CAST (size), value, CAST (size), src, CAST (size), dst); - printf ("\t((uae_u16*)®flags)[1]=((uae_u16*)®flags)[0]=ccr;}\n"); - return; - - case flag_cmp: - printf ("\tm68k_flag_cmp (%s, (%s)(%s), (%s)(%s));\n", - EXT (size), CAST (size), src, CAST (size), dst); - return; - - default: - break; - } -#elif defined(ACORN_FLAG_OPT) && defined(__GNUC_MINOR__) -/* - * This is new. Might be quite buggy. - */ - switch (type) { - case flag_av: - case flag_sv: - case flag_zn: - case flag_addx: - case flag_subx: - break; - - case flag_logical: - if (strcmp (value, "0") == 0) { - /* v=c=n=0 z=1 */ - printf ("\t*(ULONG*)®flags = 0x40000000;\n"); - return; - } else { - start_brace (); - switch (size) { - case sz_byte: - printf ("\tUBYTE ccr;\n"); - printf ("\tULONG shift;\n"); - printf ("\t__asm__(\"mov %%2,%%1,lsl#24\n\ttst %%2,%%2\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n" - "\t: \"=r\" (ccr) : \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value); - printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); - return; - case sz_word: - printf ("\tUBYTE ccr;\n"); - printf ("\tULONG shift;\n"); - printf ("\t__asm__(\"mov %%2,%%1,lsl#16\n\ttst %%2,%%2\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n" - "\t: \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value); - printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); - return; - case sz_long: - printf ("\tUBYTE ccr;\n"); - printf ("\t__asm__(\"tst %%1,%%1\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n" - "\t: \"=r\" (ccr) : \"r\" ((LONG)%s) : \"cc\" );\n", value); - printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); - return; - } - } - break; - case flag_add: - if (strcmp (dst, "0") == 0) { - printf ("/* Error! Hier muss Peter noch was machen !!! (ADD-Flags) */"); - } else { - start_brace (); - switch (size) { - case sz_byte: - printf ("\tULONG ccr, shift, %s;\n", value); - printf ("\t__asm__(\"mov %%4,%%3,lsl#24\n\tadds %%0,%%4,%%2,lsl#24\n\tmov %%0,%%0,asr#24\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n" - "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); - printf ("\t*(ULONG*)®flags = ccr;\n"); - return; - case sz_word: - printf ("\tULONG ccr, shift, %s;\n", value); - printf ("\t__asm__(\"mov %%4,%%3,lsl#16\n\tadds %%0,%%4,%%2,lsl#16\n\tmov %%0,%%0,asr#16\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n" - "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); - printf ("\t*(ULONG*)®flags = ccr;\n"); - return; - case sz_long: - printf ("\tULONG ccr, %s;\n", value); - printf ("\t__asm__(\"adds %%0,%%3,%%2\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n" - "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", value, src, dst); - printf ("\t*(ULONG*)®flags = ccr;\n"); - return; - } - } - break; - case flag_sub: - if (strcmp (dst, "0") == 0) { - printf ("/* Error! Hier muss Peter noch was machen !!! (SUB-Flags) */"); - } else { - start_brace (); - switch (size) { - case sz_byte: - printf ("\tULONG ccr, shift, %s;\n", value); - printf ("\t__asm__(\"mov %%4,%%3,lsl#24\n\tsubs %%0,%%4,%%2,lsl#24\n\tmov %%0,%%0,asr#24\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n" - "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); - printf ("\t*(ULONG*)®flags = ccr;\n"); - return; - case sz_word: - printf ("\tULONG ccr, shift, %s;\n", value); - printf ("\t__asm__(\"mov %%4,%%3,lsl#16\n\tsubs %%0,%%4,%%2,lsl#16\n\tmov %%0,%%0,asr#16\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n" - "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value, src, dst); - printf ("\t*(ULONG*)®flags = ccr;\n"); - return; - case sz_long: - printf ("\tULONG ccr, %s;\n", value); - printf ("\t__asm__(\"subs %%0,%%3,%%2\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n" - "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", value, src, dst); - printf ("\t*(ULONG*)®flags = ccr;\n"); - return; - } - } - break; - case flag_cmp: - if (strcmp (dst, "0") == 0) { - printf ("/*Error! Hier muss Peter noch was machen !!! (CMP-Flags)*/"); - } else { - start_brace (); - switch (size) { - case sz_byte: - printf ("\tULONG shift, ccr;\n"); - printf ("\t__asm__(\"mov %%3,%%2,lsl#24\n\tcmp %%3,%%1,lsl#24\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n" - "\t: \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", src, dst); - printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); - return; - case sz_word: - printf ("\tULONG shift, ccr;\n"); - printf ("\t__asm__(\"mov %%3,%%2,lsl#16\n\tcmp %%3,%%1,lsl#16\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n" - "\t: \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", src, dst); - printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); - return; - case sz_long: - printf ("\tULONG ccr;\n"); - printf ("\t__asm__(\"cmp %%2,%%1\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n" - "\t: \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", src, dst); - printf ("\t*((UBYTE*)®flags+3) = ccr;\n"); - /*printf ("\tprintf (\"%%08x %%08x %%08x\\n\", %s, %s, *((ULONG*)®flags));\n", src, dst); */ - return; - } - } - break; - } -#endif + if (done) + printf("#else\n"); + else + printf("#endif\n"); genflags_normal (type, size, value, src, dst); + if (done) + printf("#endif\n"); } static void force_range_for_rox (const char *var, wordsizes size) @@ -1132,7 +971,7 @@ static const char *cmask (wordsizes size) case sz_byte: return "0x80"; case sz_word: return "0x8000"; case sz_long: return "0x80000000"; - default: abort (); + default: abort (); return NULL; } } @@ -1144,11 +983,10 @@ static int source_is_imm1_8 (struct instr *i) static void gen_opcode (unsigned long int opcode) { struct instr *curi = table68k + opcode; - insn_n_cycles = 2; start_brace (); #if 0 - printf ("uae_u8 *m68k_pc = regs.pc_p;\n"); + printf ("uae_u8 *m68k_pc = m68k_getpc();\n"); #endif m68k_pc_offset = 2; switch (curi->plev) { @@ -1178,16 +1016,16 @@ static void gen_opcode (unsigned long int opcode) case i_OR: case i_AND: case i_EOR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ORSR: case i_EORSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) { printf ("\tsrc &= 0xFF;\n"); } @@ -1196,7 +1034,7 @@ static void gen_opcode (unsigned long int opcode) break; case i_ANDSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) { printf ("\tsrc |= 0xFF00;\n"); } @@ -1204,134 +1042,177 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SUB: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_sub, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_SUBA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = dst - src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_SUBX: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_SBCD: - /* Let's hope this works... */ - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n"); - printf ("\tuae_u16 newv;\n"); - printf ("\tint cflg;\n"); - printf ("\tif (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }\n"); - printf ("\tnewv = newv_hi + (newv_lo & 0xF);"); - printf ("\tSET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);\n"); + printf ("\tuae_u16 newv, tmp_newv;\n"); + printf ("\tint bcd = 0;\n"); + printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); + printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n"); + printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); + printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n"); duplicate_carry (); - printf ("\tif (cflg) newv -= 0x60;\n"); - genflags (flag_zn, curi->size, "newv", "", ""); - genflags (flag_sv, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ + if (cpu_level >= xBCD_KEEPS_N_FLAG) { + if (next_cpu_level < xBCD_KEEPS_N_FLAG) + next_cpu_level = xBCD_KEEPS_N_FLAG - 1; + genflags (flag_z, curi->size, "newv", "", ""); + } else { + genflags (flag_zn, curi->size, "newv", "", ""); + } + if (cpu_level >= xBCD_KEEPS_V_FLAG) { + if (next_cpu_level < xBCD_KEEPS_V_FLAG) + next_cpu_level = xBCD_KEEPS_V_FLAG - 1; + } else { + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + } + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ADD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_add, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ADDA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = dst + src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_ADDX: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n"); genflags (flag_addx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ABCD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); - printf ("\tuae_u16 newv;\n"); + printf ("\tuae_u16 newv, tmp_newv;\n"); printf ("\tint cflg;\n"); - printf ("\tif (newv_lo > 9) { newv_lo +=6; }\n"); - printf ("\tnewv = newv_hi + newv_lo;"); - printf ("\tSET_CFLG (cflg = (newv & 0x1F0) > 0x90);\n"); - duplicate_carry (); + printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); + printf ("\tif (newv_lo > 9) { newv += 6; }\n"); + printf ("\tcflg = (newv & 0x3F0) > 0x90;\n"); printf ("\tif (cflg) newv += 0x60;\n"); - genflags (flag_zn, curi->size, "newv", "", ""); - genflags (flag_sv, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + printf ("\tSET_CFLG (cflg);\n"); + duplicate_carry (); + /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ + if (cpu_level >= xBCD_KEEPS_N_FLAG) { + if (next_cpu_level < xBCD_KEEPS_N_FLAG) + next_cpu_level = xBCD_KEEPS_N_FLAG - 1; + genflags (flag_z, curi->size, "newv", "", ""); + } else { + genflags (flag_zn, curi->size, "newv", "", ""); + } + if (cpu_level >= xBCD_KEEPS_V_FLAG) { + if (next_cpu_level < xBCD_KEEPS_V_FLAG) + next_cpu_level = xBCD_KEEPS_V_FLAG - 1; + } else { + printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); + } + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_NEG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_sub, curi->size, "dst", "src", "0"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_NEGX: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "0"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->smode, "srcreg", curi->size, "src"); + genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_NBCD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n"); printf ("\tuae_u16 newv;\n"); - printf ("\tint cflg;\n"); - printf ("\tif (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }\n"); - printf ("\tnewv = newv_hi + (newv_lo & 0xF);"); - printf ("\tSET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);\n"); - duplicate_carry(); + printf ("\tint cflg, tmp_newv;\n"); + printf ("\ttmp_newv = newv_hi + newv_lo;\n"); + printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n"); + printf ("\tnewv = newv_hi + newv_lo;\n"); + printf ("\tcflg = (newv & 0x1F0) > 0x90;\n"); printf ("\tif (cflg) newv -= 0x60;\n"); - genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->smode, "srcreg", curi->size, "src"); + printf ("\tSET_CFLG (cflg);\n"); + duplicate_carry(); + /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ + if (cpu_level >= xBCD_KEEPS_N_FLAG) { + if (next_cpu_level < xBCD_KEEPS_N_FLAG) + next_cpu_level = xBCD_KEEPS_N_FLAG - 1; + genflags (flag_z, curi->size, "newv", "", ""); + } else { + genflags (flag_zn, curi->size, "newv", "", ""); + } + if (cpu_level >= xBCD_KEEPS_V_FLAG) { + if (next_cpu_level < xBCD_KEEPS_V_FLAG) + next_cpu_level = xBCD_KEEPS_V_FLAG - 1; + } else { + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + } + genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_CLR: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); genflags (flag_logical, curi->size, "0", "", ""); - genastore ("0", curi->smode, "srcreg", curi->size, "src"); + genastore ("0", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_NOT: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 dst = ~src;\n"); genflags (flag_logical, curi->size, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_TST: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); genflags (flag_logical, curi->size, "src", "", ""); break; case i_BTST: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else @@ -1339,55 +1220,55 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); break; case i_BCHG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tdst ^= (1 << src);\n"); - printf ("\tSET_ZFLG ((dst & (1 << src)) >> src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_BCLR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst &= ~(1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_BSET: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst |= (1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_CMPM: case i_CMP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_cmp, curi->size, "newv", "src", "dst"); break; case i_CMPA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_cmp, sz_long, "newv", "src", "dst"); break; /* The next two are coded a little unconventional, but they are doing * weird things... */ case i_MVPRM: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); if (curi->size == sz_word) { @@ -1399,41 +1280,45 @@ static void gen_opcode (unsigned long int opcode) break; case i_MVPMR: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_word) { - printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n"); + printf ("\tuae_u16 val = get_byte(memp) << 8;\n"); + printf ("\t val |= get_byte(memp + 2);\n"); } else { - printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n"); - printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n"); + printf ("\tuae_u32 val = get_byte(memp) << 24;\n"); + printf ("\t val |= get_byte(memp + 2) << 16;\n"); + printf ("\t val |= get_byte(memp + 4) << 8;\n"); + printf ("\t val |= get_byte(memp + 6);\n"); } - genastore ("val", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("val", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_MOVE: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_MOVEA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_word) { printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n"); } else { printf ("\tuae_u32 val = src;\n"); } - genastore ("val", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("val", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_MVSR2: - genamode (curi->smode, "srcreg", sz_word, "src", 2, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tMakeSR();\n"); if (curi->size == sz_byte) - genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src"); + genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); else - genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src"); + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); break; case i_MV2SR: - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n"); else { @@ -1442,31 +1327,31 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SWAP: - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n"); genflags (flag_logical, sz_long, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", sz_long, "src"); + genastore ("dst", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); break; case i_EXG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_EXT: - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { - case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; - case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; - default: abort (); + case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; + case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; + default: abort (); } genflags (flag_logical, curi->size == sz_word ? sz_word : sz_long, "dst", "", ""); genastore ("dst", curi->smode, "srcreg", - curi->size == sz_word ? sz_word : sz_long, "src"); + curi->size == sz_word ? sz_word : sz_long, "src", XLATE_LOG); break; case i_MVMEL: genmovemel (opcode); @@ -1475,33 +1360,51 @@ static void gen_opcode (unsigned long int opcode) genmovemle (opcode); break; case i_TRAP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - sync_m68k_pc (); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + gen_set_fault_pc (); printf ("\tException(src+32,0);\n"); - m68k_pc_offset = 0; break; case i_MVR2USP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tregs.usp = src;\n"); break; case i_MVUSP2R: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); - genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_RESET: + printf ("\tAtariReset();\n"); break; case i_NOP: break; case i_STOP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - printf ("\tregs.sr = src;\n"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + /* + * STOP undocumented features: + * if SR is not set: + * 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu) + * 68000 (68010?): Traced STOP also runs 4 cycles faster. + * 68020 68030: STOP works normally + * 68040 68060: Immediate privilege violation exception + */ + printf ("\tuae_u16 sr = src;\n"); + if (cpu_level >= 4) { + printf("\tif (!(sr & 0x2000)) {\n"); + printf ("m68k_incpc(%d);\n", m68k_pc_offset); + printf("\t\tException(8,0); goto %s;\n", endlabelstr); + printf("\t}\n"); + } + printf("\tregs.sr = sr;\n"); printf ("\tMakeFromSR();\n"); printf ("\tm68k_setstopped(1);\n"); + sync_m68k_pc (); + /* STOP does not prefetch anything */ + /* did_prefetch = -1; */ break; case i_RTE: if (cpu_level == 0) { - genamode (Aipi, "7", sz_word, "sr", 1, 0); - genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n"); fill_prefetch_0 (); printf ("\tMakeFromSR();\n"); @@ -1510,14 +1413,14 @@ static void gen_opcode (unsigned long int opcode) if (next_cpu_level < 0) next_cpu_level = 0; printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n"); - genamode (Aipi, "7", sz_word, "sr", 1, 0); - genamode (Aipi, "7", sz_long, "pc", 1, 0); - genamode (Aipi, "7", sz_word, "format", 1, 0); + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tnewsr = sr; newpc = pc;\n"); printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); - printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); +// printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n"); @@ -1535,8 +1438,8 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_RTD: - genamode (Aipi, "7", sz_long, "pc", 1, 0); - genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tm68k_areg(regs, 7) += offs;\n"); printf ("\tm68k_setpc_rte(pc);\n"); fill_prefetch_0 (); @@ -1544,18 +1447,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_LINK: - genamode (Apdi, "7", sz_long, "old", 2, 0); - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); - genastore ("src", Apdi, "7", sz_long, "old"); - genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src"); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); printf ("\tm68k_areg(regs, 7) += offs;\n"); + genastore ("src", Apdi, "7", sz_long, "old", XLATE_LOG); break; case i_UNLK: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tm68k_areg(regs, 7) = src;\n"); - genamode (Aipi, "7", sz_long, "old", 1, 0); - genastore ("old", curi->smode, "srcreg", curi->size, "src"); + genamode (Aipi, "7", sz_long, "old", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("old", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_RTS: printf ("\tm68k_do_rts();\n"); @@ -1563,14 +1466,16 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_TRAPV: + printf ("\tuaecptr oldpc = m68k_getpc();\n"); sync_m68k_pc (); - printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr); + printf ("\tif (GET_VFLG) { Exception(7,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; break; case i_RTR: printf ("\tMakeSR();\n"); - genamode (Aipi, "7", sz_word, "sr", 1, 0); - genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n"); printf ("\tregs.sr |= sr; m68k_setpc(pc);\n"); fill_prefetch_0 (); @@ -1578,19 +1483,19 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_JSR: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_JMP: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); printf ("\tm68k_setpc(srca);\n"); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_BSR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); printf ("\tuae_s32 s = (uae_s32)src + 2;\n"); if (using_exception_3) { printf ("\tif (src & 1) {\n"); @@ -1618,8 +1523,8 @@ static void gen_opcode (unsigned long int opcode) next_cpu_level = 1; } } - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + printf ("\tif (!cctrue(%d)) goto didnt_jump_%lx;\n", curi->cc, opcode); if (using_exception_3) { printf ("\tif (src & 1) {\n"); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); @@ -1630,26 +1535,26 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); fill_prefetch_0 (); - printf ("\tgoto %s;\n", endlabelstr); - printf ("didnt_jump:;\n"); + printf ("return;\n"); + printf ("didnt_jump_%lx:;\n", opcode); need_endlabel = 1; break; case i_LEA: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_PEA: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (Apdi, "7", sz_long, "dst", 2, 0); - genastore ("srca", Apdi, "7", sz_long, "dst"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("srca", Apdi, "7", sz_long, "dst", XLATE_LOG); break; case i_DBcc: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tif (!cctrue(%d)) {\n", curi->cc); - genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src"); + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); printf ("\t\tif (src) {\n"); if (using_exception_3) { @@ -1662,22 +1567,25 @@ static void gen_opcode (unsigned long int opcode) } printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n"); fill_prefetch_0 (); - printf ("\t\tgoto %s;\n", endlabelstr); + printf ("return;\n"); printf ("\t\t}\n"); printf ("\t}\n"); need_endlabel = 1; break; case i_Scc: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc); - genastore ("val", curi->smode, "srcreg", curi->size, "src"); + genastore ("val", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_DIVU: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - printf ("\tif(src == 0) { Exception(5,oldpc); goto %s; } else {\n", endlabelstr); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + sync_m68k_pc (); + /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends + * on this (actually, it's doing a DIVS). */ + printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n"); printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n"); /* The N flag appears to be set each time there is an overflow. @@ -1685,51 +1593,48 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); printf ("\t}\n"); printf ("\t}\n"); - insn_n_cycles += 68; need_endlabel = 1; break; case i_DIVS: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); - printf ("\tif(src == 0) { Exception(5,oldpc); goto %s; } else {\n", endlabelstr); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + sync_m68k_pc (); + printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n"); printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); printf ("\t}\n"); printf ("\t}\n"); - insn_n_cycles += 72; need_endlabel = 1; break; case i_MULU: - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); - insn_n_cycles += 32; + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_MULS: - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); - insn_n_cycles += 32; + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_CHK: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr); printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; @@ -1737,8 +1642,8 @@ static void gen_opcode (unsigned long int opcode) case i_CHK2: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n"); switch (curi->size) { case sz_byte: @@ -1756,14 +1661,14 @@ static void gen_opcode (unsigned long int opcode) abort (); } printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); - printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); + printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; case i_ASR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1792,11 +1697,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ASL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1828,11 +1733,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_LSR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1857,11 +1762,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval >>= 1;\n"); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_LSL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1887,11 +1792,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1914,11 +1819,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG (val & 1);\n"); printf ("}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1941,11 +1846,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROXL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1955,12 +1860,12 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); - if (! source_is_imm1_8 (curi)) - force_range_for_rox ("cnt", curi->size); if (source_is_imm1_8 (curi)) printf ("{"); - else + else { + force_range_for_rox ("cnt", curi->size); printf ("\tif (cnt > 0) {\n"); + } printf ("\tcnt--;\n"); printf ("\t{\n\tuae_u32 carry;\n"); printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1); @@ -1971,11 +1876,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} }\n"); printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROXR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1985,12 +1890,12 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); - if (! source_is_imm1_8 (curi)) - force_range_for_rox ("cnt", curi->size); if (source_is_imm1_8 (curi)) printf ("{"); - else + else { + force_range_for_rox ("cnt", curi->size); printf ("\tif (cnt > 0) {\n"); + } printf ("\tcnt--;\n"); printf ("\t{\n\tuae_u32 carry;\n"); printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n"); @@ -2004,10 +1909,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} }\n"); printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ASRW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -2021,10 +1926,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ASLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -2041,10 +1946,10 @@ static void gen_opcode (unsigned long int opcode) duplicate_carry (); printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_LSRW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -2057,10 +1962,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_LSLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2073,10 +1978,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ROLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2089,10 +1994,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= 1;\n"); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_RORW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2105,10 +2010,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= %s;\n", cmask (curi->size)); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ROXLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2122,10 +2027,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ROXRW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2139,103 +2044,129 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_MOVEC2: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tm68k_movec2(src & 0xFFF, regp);\n"); + printf ("\tif (!m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_MOVE2C: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tm68k_move2c(src & 0xFFF, regp);\n"); + printf ("\tif (!m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_CAS: { int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint ru = (src >> 6) & 7;\n"); printf ("\tint rc = src & 7;\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst"); + sync_m68k_pc (); printf ("\tif (GET_ZFLG)"); old_brace_level = n_braces; start_brace (); - genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); pop_braces (old_brace_level); printf ("else"); start_brace (); - printf ("m68k_dreg(regs, rc) = dst;\n"); + switch (curi->size) { + case sz_byte: + printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n"); + break; + case sz_word: + printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n"); + break; + default: + printf ("\tm68k_dreg(regs, rc) = dst;\n"); + break; + } pop_braces (old_brace_level); } break; case i_CAS2: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n"); printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n"); if (curi->size == sz_word) { int old_brace_level = n_braces; + printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); + printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); printf ("\tif (GET_ZFLG) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); printf ("\tif (GET_ZFLG) {\n"); printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_word(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG) {\n"); - printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); - printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, rc2) = (m68k_dreg(regs, rc2) & ~0xffff) | (dst2 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, rc1) = (m68k_dreg(regs, rc1) & ~0xffff) | (dst1 & 0xffff);\n"); printf ("\t}\n"); } else { int old_brace_level = n_braces; + printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); + printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); printf ("\tif (GET_ZFLG) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); printf ("\tif (GET_ZFLG) {\n"); printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_long(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG) {\n"); - printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n"); - printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n"); + printf ("\tm68k_dreg(regs, rc2) = dst2;\n"); + printf ("\tm68k_dreg(regs, rc1) = dst1;\n"); printf ("\t}\n"); } break; - case i_MOVES: /* ignore DFC and SFC because we have no MMU */ + case i_MOVES: { - int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - printf ("\tif (extra & 0x800)\n"); - old_brace_level = n_braces; - start_brace (); - printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); - pop_braces (old_brace_level); - printf ("else"); - start_brace (); - genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0); - printf ("\tif (extra & 0x8000) {\n"); - switch (curi->size) { - case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; - case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; - default: abort (); - } - printf ("\t} else {\n"); - genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, ""); - printf ("\t}\n"); - pop_braces (old_brace_level); + int old_brace_level; + + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + start_brace(); + printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */ + { + int old_m68k_pc_offset = m68k_pc_offset; + /* use DFC */ + old_brace_level = n_braces; + start_brace (); + printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_DFC); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC); + pop_braces (old_brace_level); + m68k_pc_offset = old_m68k_pc_offset; + } + printf ("else"); /* from ea to reg */ + { + /* use SFC */ + start_brace (); + genamode (curi->dmode, "dstreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_SFC); + printf ("\tif (extra & 0x8000) {\n"); /* address/data */ + switch (curi->size) { + case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; + case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; + default: abort (); + } + printf ("\t} else {\n"); + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG); + printf ("\t}\n"); + sync_m68k_pc(); + pop_braces (old_brace_level); + } } break; case i_BKPT: /* only needed for hardware emulators */ @@ -2251,23 +2182,23 @@ static void gen_opcode (unsigned long int opcode) printf ("\top_illg(opcode);\n"); break; case i_TRAPcc: + printf ("\tuaecptr oldpc = m68k_getpc();\n"); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); - printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr); + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + sync_m68k_pc (); + printf ("\tif (cctrue(%d)) { Exception(7,oldpc); goto %s; }\n", curi->cc, endlabelstr); need_endlabel = 1; break; case i_DIVL: - sync_m68k_pc (); - start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n"); break; case i_MULL: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); printf ("\tm68k_mull(opcode, dst, extra);\n"); break; @@ -2279,34 +2210,37 @@ static void gen_opcode (unsigned long int opcode) case i_BFFFO: case i_BFSET: case i_BFINS: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); + printf ("\tuae_u32 bdata[2];"); printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n"); printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n"); if (curi->dmode == Dreg) { - printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n"); + printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg);\n"); + printf ("\toffset &= 0x1f;\n"); + printf ("\ttmp = (tmp << offset) | (tmp >> (32 - offset));\n"); + printf ("\tbdata[0] = tmp & ((1 << (32 - width)) - 1);\n"); } else { - printf ("\tuae_u32 tmp,bf0,bf1;\n"); - printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n"); - printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n"); - printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n"); + printf ("\tuae_u32 tmp;\n"); + printf ("\tdsta += offset >> 3;\n"); + printf ("\ttmp = get_bitfield(dsta, bdata, offset, width);\n"); } - printf ("\ttmp >>= (32 - width);\n"); - printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n"); + printf ("\tSET_NFLG_ALWAYS (((uae_s32)tmp) < 0 ? 1 : 0);\n"); + if (curi->mnemo == i_BFEXTS) + printf ("\ttmp = (uae_s32)tmp >> (32 - width);\n"); + else + printf ("\ttmp >>= (32 - width);\n"); printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n"); switch (curi->mnemo) { case i_BFTST: break; case i_BFEXTU: + case i_BFEXTS: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCHG: - printf ("\ttmp = ~tmp;\n"); - break; - case i_BFEXTS: - printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n"); - printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); + printf ("\ttmp = tmp ^ (0xffffffffu >> (32 - width));\n"); break; case i_BFCLR: printf ("\ttmp = 0;\n"); @@ -2317,10 +2251,13 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n"); break; case i_BFSET: - printf ("\ttmp = 0xffffffff;\n"); + printf ("\ttmp = 0xffffffffu >> (32 - width);\n"); break; case i_BFINS: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n"); + printf ("\ttmp = tmp & (0xffffffffu >> (32 - width));\n"); + printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width - 1)) ? 1 : 0);\n"); + printf ("\tSET_ZFLG (tmp == 0);\n"); break; default: break; @@ -2328,26 +2265,12 @@ static void gen_opcode (unsigned long int opcode) if (curi->mnemo == i_BFCHG || curi->mnemo == i_BFCLR || curi->mnemo == i_BFSET - || curi->mnemo == i_BFINS) - { - printf ("\ttmp <<= (32 - width);\n"); + || curi->mnemo == i_BFINS) { if (curi->dmode == Dreg) { - printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n"); - printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n"); - printf ("\t\t(tmp >> (offset & 0x1f)) |\n"); - printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n"); - printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n"); + printf ("\ttmp = bdata[0] | (tmp << (32 - width));\n"); + printf ("\tm68k_dreg(regs, dstreg) = (tmp >> offset) | (tmp << (32 - offset));\n"); } else { - printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n"); - printf ("\t\t(tmp >> (offset & 7)) |\n"); - printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n"); - printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n"); - printf ("\tput_long(dsta,bf0 );\n"); - printf ("\tif (((offset & 7) + width) > 32) {\n"); - printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n"); - printf ("\t\t\t(tmp << (8 - (offset & 7)));\n"); - printf ("\t\tput_byte(dsta+4,bf1);\n"); - printf ("\t}\n"); + printf ("\tput_bitfield(dsta, bdata, tmp, offset, width);\n"); } } break; @@ -2357,11 +2280,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); - printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ()); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); + printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg) - 2 * areg_byteinc[srcreg]) << 8)) + %s;\n", gen_nextiword ()); + printf ("\tm68k_areg(regs, srcreg) -= 2;\n"); printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); + gen_set_fault_pc (); printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n"); } break; @@ -2372,92 +2295,167 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ()); - printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); - printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n"); - printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); - printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n"); + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); + printf ("\tm68k_areg(regs, dstreg) -= 2;\n"); + gen_set_fault_pc (); + printf ("\tput_word(m68k_areg(regs, dstreg), val);\n"); } break; case i_TAS: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); genflags (flag_logical, curi->size, "src", "", ""); printf ("\tsrc |= 0x80;\n"); - genastore ("src", curi->smode, "srcreg", curi->size, "src"); + genastore ("src", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_FPP: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfpp_opp(opcode,extra);\n"); + printf ("\tfpuop_arithmetic(opcode, extra);\n"); break; case i_FDBcc: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfdbcc_opp(opcode,extra);\n"); + printf ("\tfpuop_dbcc(opcode, extra);\n"); break; case i_FScc: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfscc_opp(opcode,extra);\n"); + printf ("\tfpuop_scc(opcode, extra);\n"); break; case i_FTRAPcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); + printf ("\tuae_u16 extra = %s;\n", gen_nextiword()); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tftrapcc_opp(opcode,oldpc);\n"); + printf ("\tfpuop_trapcc(opcode, oldpc, extra);\n"); break; case i_FBcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr pc = m68k_getpc();\n"); - genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfbcc_opp(opcode,pc,extra);\n"); + printf ("\tfpuop_bcc(opcode, pc, extra);\n"); break; case i_FSAVE: sync_m68k_pc (); swap_opcode (); - printf ("\tfsave_opp(opcode);\n"); + printf ("\tfpuop_save(opcode);\n"); break; case i_FRESTORE: sync_m68k_pc (); swap_opcode (); - printf ("\tfrestore_opp(opcode);\n"); + printf ("\tfpuop_restore(opcode);\n"); break; case i_CINVL: + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache(31);\n"); + printf("#endif\n"); + break; case i_CINVP: + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache(32);\n"); + printf("#endif\n"); + break; case i_CINVA: + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache(33);\n"); + printf("#endif\n"); + break; case i_CPUSHL: + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache(41);\n"); + printf("#endif\n"); + break; case i_CPUSHP: + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache(42);\n"); + printf("#endif\n"); + break; case i_CPUSHA: + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache(43);\n"); + printf("#endif\n"); break; case i_MOVE16: - printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); - printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); - printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); - printf ("\tput_long(memd, get_long(mems));\n"); - printf ("\tput_long(memd+4, get_long(mems+4));\n"); - printf ("\tput_long(memd+8, get_long(mems+8));\n"); - printf ("\tput_long(memd+12, get_long(mems+12));\n"); - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - break; + if ((opcode & 0xfff8) == 0xf620) { + /* MOVE16 (Ax)+,(Ay)+ */ + printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); + printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); + printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); + printf ("\tput_long(memd, get_long(mems));\n"); + printf ("\tput_long(memd+4, get_long(mems+4));\n"); + printf ("\tput_long(memd+8, get_long(mems+8));\n"); + printf ("\tput_long(memd+12, get_long(mems+12));\n"); + printf ("\tif (srcreg != dstreg)\n"); + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } else { + /* Other variants */ + genamode (curi->smode, "srcreg", curi->size, "mems", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "memd", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); + printf ("\tmemsa &= ~15;\n"); + printf ("\tmemda &= ~15;\n"); + printf ("\tput_long(memda, get_long(memsa));\n"); + printf ("\tput_long(memda+4, get_long(memsa+4));\n"); + printf ("\tput_long(memda+8, get_long(memsa+8));\n"); + printf ("\tput_long(memda+12, get_long(memsa+12));\n"); + if ((opcode & 0xfff8) == 0xf600) + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + else if ((opcode & 0xfff8) == 0xf608) + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } + break; case i_MMUOP: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); printf ("\tmmu_op(opcode,extra);\n"); break; + + case i_EMULOP_RETURN: + printf ("\tm68k_emulop_return();\n"); + m68k_pc_offset = 0; + break; + + case i_EMULOP: + printf ("\n"); + swap_opcode (); + printf ("\tm68k_emulop(opcode);\n"); + break; + + case i_NATFEAT_ID: + printf ("\n"); + printf ("\tm68k_natfeat_id();\n"); + break; + + case i_NATFEAT_CALL: + printf ("\n"); + printf ("\tm68k_natfeat_call();\n"); + break; + default: abort (); break; @@ -2473,17 +2471,43 @@ static void generate_includes (FILE * f) fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); + fprintf (f, "#ifdef USE_JIT\n"); + fprintf (f, "#include \"compiler/compemu.h\"\n"); + fprintf (f, "#endif\n"); + fprintf (f, "#include \"fpu/fpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); + fprintf (f, "#include \"cpu_emulation.h\"\n"); + fprintf (f, "#include \"debug.h\"\n"); + + fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); + fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); + fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); + fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); + fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); + + fprintf (f, "#ifdef NOFLAGS\n"); + fprintf (f, "# include \"noflags.h\"\n"); + fprintf (f, "#endif\n"); } static int postfix; +struct gencputbl { + char handler[80]; + uae_u16 specific; + uae_u16 opcode; + int namei; +}; +struct gencputbl cpustbl[65536]; +static int n_cpustbl; + static void generate_one_opcode (int rp) { int i; uae_u16 smsk, dmsk; - long int opcode = opcode_map[rp]; - + int opcode = opcode_map[rp]; + int have_realopcode = 0; + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) return; @@ -2497,13 +2521,37 @@ static void generate_one_opcode (int rp) return; if (opcode_next_clev[rp] != cpu_level) { - fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], - opcode, lookuptab[i].name); + sprintf(cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, opcode_last_postfix[rp]); + cpustbl[n_cpustbl].specific = 0; + cpustbl[n_cpustbl].opcode = opcode; + cpustbl[n_cpustbl].namei = i; + fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, lookuptab[i].name); + n_cpustbl++; return; } - fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name); - fprintf (headerfile, "extern cpuop_func op_%lx_%d;\n", opcode, postfix); - printf ("void REGPARAM2 op_%lx_%d(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); + + if (table68k[opcode].flagdead == 0) + /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ + sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC_FF(op_%x_%d)", opcode, postfix); + else + sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, postfix); + cpustbl[n_cpustbl].specific = 0; + cpustbl[n_cpustbl].opcode = opcode; + cpustbl[n_cpustbl].namei = i; + fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, lookuptab[i].name); + n_cpustbl++; + + fprintf (headerfile, "extern cpuop_func op_%x_%d_nf;\n", opcode, postfix); + fprintf (headerfile, "extern cpuop_func op_%x_%d_ff;\n", opcode, postfix); + + printf ("void REGPARAM2 CPUFUNC(op_%x_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); + printf ("\tcpuop_begin();\n"); + /* gb-- The "nf" variant for an instruction that doesn't set the condition + codes at all is the same as the "ff" variant, so we don't need the "nf" + variant to be compiled since it is mapped to the "ff" variant in the + smalltbl. */ + if (table68k[opcode].flagdead == 0) + printf ("#ifndef NOFLAGS\n"); switch (table68k[opcode].stype) { case 0: smsk = 7; break; @@ -2512,6 +2560,8 @@ static void generate_one_opcode (int rp) case 3: smsk = 7; break; case 4: smsk = 7; break; case 5: smsk = 63; break; + case 6: smsk = 255; break; + case 7: smsk = 3; break; default: abort (); } dmsk = 7; @@ -2521,7 +2571,12 @@ static void generate_one_opcode (int rp) && table68k[opcode].smode != imm && table68k[opcode].smode != imm0 && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2 && table68k[opcode].smode != absw && table68k[opcode].smode != absl - && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16) + && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16 + /* gb-- We don't want to fetch the EmulOp code since the EmulOp() + routine uses the whole opcode value. Maybe all the EmulOps + could be expanded out but I don't think it is an improvement */ + && table68k[opcode].stype != 6 + ) { if (table68k[opcode].spos == -1) { if (((int) table68k[opcode].sreg) >= 128) @@ -2537,38 +2592,17 @@ static void generate_one_opcode (int rp) if (pos < 8 && (smsk >> (8 - pos)) != 0) abort (); #endif - printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - - if (pos < 8 && (smsk >> (8 - pos)) != 0) - sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)", - pos ^ 8, 8 - pos, dmsk); - else if (pos != 8) - sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk); - else - sprintf (source, "(opcode & %d)", smsk); - - if (table68k[opcode].stype == 3) - printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); - else if (table68k[opcode].stype == 1) - printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); - else - printf ("\tuae_u32 srcreg = %s;\n", source); - - printf ("#else\n"); - + real_opcode(&have_realopcode); if (pos) - sprintf (source, "((opcode >> %d) & %d)", pos, smsk); + sprintf (source, "((real_opcode >> %d) & %d)", pos, smsk); else - sprintf (source, "(opcode & %d)", smsk); - + sprintf (source, "(real_opcode & %d)", smsk); if (table68k[opcode].stype == 3) printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); else if (table68k[opcode].stype == 1) printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); else printf ("\tuae_u32 srcreg = %s;\n", source); - - printf ("#endif\n"); } } if (table68k[opcode].duse @@ -2588,27 +2622,13 @@ static void generate_one_opcode (int rp) /* Check that we can do the little endian optimization safely. */ if (pos < 8 && (dmsk >> (8 - pos)) != 0) abort (); -#endif - printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - - if (pos < 8 && (dmsk >> (8 - pos)) != 0) - printf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", - pos ^ 8, 8 - pos, dmsk); - else if (pos != 8) - printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", - pos ^ 8, dmsk); - else - printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); - - printf ("#else\n"); - +#endif + real_opcode(&have_realopcode); if (pos) - printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", + printf ("\tuae_u32 dstreg = (real_opcode >> %d) & %d;\n", pos, dmsk); else - printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); - - printf ("#endif\n"); + printf ("\tuae_u32 dstreg = real_opcode & %d;\n", dmsk); } } need_endlabel = 0; @@ -2617,6 +2637,9 @@ static void generate_one_opcode (int rp) gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); + if (table68k[opcode].flagdead == 0) + printf ("\n#endif\n"); + printf ("\tcpuop_end();\n"); printf ("}\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; @@ -2628,24 +2651,18 @@ static void generate_func (void) using_prefetch = 0; using_exception_3 = 0; - for (i = 0; i < 6; i++) { + + for (i = 0; i < 1; i++) { cpu_level = 4 - i; - if (i == 5) { - cpu_level = 0; - using_prefetch = 1; - using_exception_3 = 1; - for (rp = 0; rp < nr_cpuop_funcs; rp++) - opcode_next_clev[rp] = 0; - } postfix = i; - fprintf (stblfile, "struct cputbl op_smalltbl_%d[] = {\n", postfix); + fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); /* sam: this is for people with low memory (eg. me :)) */ printf ("\n" - "#if !defined(PART_1) && !defined(PART_2) && " - "!defined(PART_3) && !defined(PART_4) && " - "!defined(PART_5) && !defined(PART_6) && " - "!defined(PART_7) && !defined(PART_8)" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" "\n" "#define PART_1 1\n" "#define PART_2 1\n" @@ -2656,8 +2673,8 @@ static void generate_func (void) "#define PART_7 1\n" "#define PART_8 1\n" "#endif\n\n"); - rp = 0; + n_cpustbl = 0; for(j=1;j<=8;++j) { int k = (j*nr_cpuop_funcs)/8; printf ("#ifdef PART_%d\n",j); @@ -2665,12 +2682,88 @@ static void generate_func (void) generate_one_opcode (rp); printf ("#endif\n\n"); } - fprintf (stblfile, "{ 0, 0, 0 }};\n"); } } -int main (int argc, char **argv) +static struct { + const char *handler; + const char *name; +} cpufunctbl[65536]; +static char const op_illg_1[] = "op_illg_1"; +static char const illegal[] = "ILLEGAL"; + +static void generate_functbl (void) +{ + int i; + unsigned int opcode; + int cpu_level = 4; + struct gencputbl *tbl = cpustbl; + + for (opcode = 0; opcode < 65536; opcode++) + { + cpufunctbl[opcode].handler = op_illg_1; + cpufunctbl[opcode].name = illegal; + } + for (i = 0; i < n_cpustbl; i++) + { + if (! tbl[i].specific) + { + cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; + cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; + } + } + for (opcode = 0; opcode < 65536; opcode++) + { + const char *f; + + if (table68k[opcode].mnemo == i_ILLG || (unsigned)table68k[opcode].clev > (unsigned)cpu_level) + continue; + + if (table68k[opcode].handler != -1) + { + f = cpufunctbl[table68k[opcode].handler].handler; + if (f == op_illg_1) + abort(); + cpufunctbl[opcode].handler = f; + cpufunctbl[opcode].name = cpufunctbl[table68k[opcode].handler].name; + } + } + for (i = 0; i < n_cpustbl; i++) + { + if (tbl[i].specific) + { + cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; + cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; + } + } + + fprintf(functblfile, "\n"); + fprintf(functblfile, "cpuop_func *cpufunctbl[65536] = {\n"); + fprintf(functblfile, "#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU)\n"); + for (opcode = 0; opcode < 65536; opcode++) + { + fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[opcode].handler, opcode < 65535 ? "," : "", cpufunctbl[opcode].name); + } + fprintf(functblfile, "#else\n"); + for (opcode = 0; opcode < 65536; opcode++) + { + unsigned int map = do_byteswap_16(opcode); + fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[map].handler, opcode < 65535 ? "," : "", cpufunctbl[map].name); + } + fprintf(functblfile, "#endif\n"); + fprintf(functblfile, "};\n"); +} + +#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) +void cygwin_mingw_abort() +{ +#undef abort + abort(); +} +#endif + +int main () { read_table68k (); do_merges (); @@ -2685,15 +2778,28 @@ int main (int argc, char **argv) * cputbl.h that way), but cpuopti can't cope. That could be fixed, but * I don't dare to touch the 68k version. */ - headerfile = fopen ("cputbl.h", "wb"); - stblfile = fopen ("cpustbl.cpp", "wb"); - freopen ("cpuemu.cpp", "wb", stdout); + if ((headerfile = fopen ("cputbl.h", "wb")) == NULL) + abort(); + if ((stblfile = fopen ("cpustbl.cpp", "wb")) == NULL) + abort(); + if ((functblfile = fopen ("cpufunctbl.cpp", "wb")) == NULL) + abort(); + if (freopen ("cpuemu.cpp", "wb", stdout) == NULL) + abort(); generate_includes (stdout); + fprintf(stdout, "#ifdef HAVE_CFLAG_NO_REDZONE\n"); + fprintf(stdout, "#ifndef NOFLAGS\n"); + fprintf(stdout, "#pragma GCC option \"-mno-red-zone\"\n"); + fprintf(stdout, "#endif\n"); + fprintf(stdout, "#endif\n"); generate_includes (stblfile); - + generate_includes (functblfile); generate_func (); - + generate_functbl (); free (table68k); + fclose(headerfile); + fclose(stblfile); + fclose(functblfile); return 0; } diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index f1ff6977..dc79136b 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -1,36 +1,85 @@ +/* + * m68k.h - machine dependent bits + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * * MC68000 emulation - machine dependent bits * * Copyright 1996 Bernd Schmidt + * */ -#if defined(__i386__) && defined(X86_ASSEMBLY) +#ifndef M68K_FLAGS_H +#define M68K_FLAGS_H +#ifdef OPTIMIZED_FLAGS + +#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY)) + +# include + +#ifndef SAHF_SETO_PROFITABLE + +/* PUSH/POP instructions are naturally 64-bit sized on x86-64, thus + unsigned long hereunder is either 64-bit or 32-bit wide depending + on the target. */ struct flag_struct { - unsigned int cznv; - unsigned int x; +#if defined(CPU_x86_64) + uint64 cznv; + uint64 x; +#else + uint32 cznv; + uint32 x; +#endif }; -#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6)) -#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11)) -#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7)) -#define SET_XFLG(y) (regflags.x = (y)) +#define FLAGVAL_Z 0x40 +#define FLAGVAL_N 0x80 -#define GET_ZFLG ((regflags.cznv >> 6) & 1) -#define GET_CFLG (regflags.cznv & 1) -#define GET_VFLG ((regflags.cznv >> 11) & 1) -#define GET_NFLG ((regflags.cznv >> 7) & 1) -#define GET_XFLG (regflags.x & 1) +#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x40) | (((y) & 1) << 6)) +#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~1) | ((y) & 1)) +#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x800) | (((y) & 1) << 11)) +#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x80) | (((y) & 1) << 7)) +#define SET_XFLG(y) (regflags.x = (y)) -#define CLEAR_CZNV (regflags.cznv = 0) -#define COPY_CARRY (regflags.x = regflags.cznv) +#define GET_ZFLG ((regflags.cznv >> 6) & 1) +#define GET_CFLG (regflags.cznv & 1) +#define GET_VFLG ((regflags.cznv >> 11) & 1) +#define GET_NFLG ((regflags.cznv >> 7) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.cznv = 0) +#define GET_CZNV (regflags.cznv) +#define IOR_CZNV(X) (regflags.cznv |= (X)) +#define SET_CZNV(X) (regflags.cznv = (X)) + +#define COPY_CARRY (regflags.x = regflags.cznv) extern struct flag_struct regflags __asm__ ("regflags"); -static __inline__ int cctrue(int cc) +static inline int cctrue(int cc) { uae_u32 cznv = regflags.cznv; switch(cc){ @@ -58,91 +107,553 @@ static __inline__ int cctrue(int cc) return 0; } -#define x86_flag_testl(v) \ - __asm__ __volatile__ ("testl %1,%1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv) : "r" (v) : "cc") +#define optflag_testl(v) \ + __asm__ __volatile__ ("andl %1,%1\n\t" \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv) : "r" (v) : "memory", "cc") -#define x86_flag_testw(v) \ - __asm__ __volatile__ ("testw %w1,%w1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv) : "r" (v) : "cc") +#define optflag_testw(v) \ + __asm__ __volatile__ ("andw %w1,%w1\n\t" \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv) : "r" (v) : "memory", "cc") -#define x86_flag_testb(v) \ - __asm__ __volatile__ ("testb %b1,%b1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv) : "q" (v) : "cc") +#define optflag_testb(v) \ + __asm__ __volatile__ ("andb %b1,%b1\n\t" \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv) : "q" (v) : "memory", "cc") -#define x86_flag_addl(v, s, d) do { \ +#define optflag_addl(v, s, d) do { \ __asm__ __volatile__ ("addl %k2,%k1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ COPY_CARRY; \ } while (0) -#define x86_flag_addw(v, s, d) do { \ +#define optflag_addw(v, s, d) do { \ __asm__ __volatile__ ("addw %w2,%w1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ COPY_CARRY; \ } while (0) -#define x86_flag_addb(v, s, d) do { \ +#define optflag_addb(v, s, d) do { \ __asm__ __volatile__ ("addb %b2,%b1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ + "pushf\n\t" \ + "pop %0\n\t" \ : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) -#define x86_flag_subl(v, s, d) do { \ +#define optflag_subl(v, s, d) do { \ __asm__ __volatile__ ("subl %k2,%k1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ COPY_CARRY; \ } while (0) -#define x86_flag_subw(v, s, d) do { \ +#define optflag_subw(v, s, d) do { \ __asm__ __volatile__ ("subw %w2,%w1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ COPY_CARRY; \ } while (0) -#define x86_flag_subb(v, s, d) do { \ +#define optflag_subb(v, s, d) do { \ __asm__ __volatile__ ("subb %b2,%b1\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "memory", "cc"); \ COPY_CARRY; \ } while (0) -#define x86_flag_cmpl(s, d) \ +#define optflag_cmpl(s, d) \ __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc") -#define x86_flag_cmpw(s, d) \ +#define optflag_cmpw(s, d) \ __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc") -#define x86_flag_cmpb(s, d) \ +#define optflag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \ - "pushfl\n\t" \ - "popl %0\n\t" \ - : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc") + "pushf\n\t" \ + "pop %0\n\t" \ + : "=rm" (regflags.cznv) : "qmi" (s), "q" (d) : "memory", "cc") -#elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)) +#else + +struct flag_struct { + uae_u32 cznv; + uae_u32 x; +}; + +#define FLAGVAL_Z 0x4000 +#define FLAGVAL_N 0x8000 + +#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14)) +#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8)) +#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1))) +#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15)) +#define SET_XFLG(y) (regflags.x = (y)) + +#define GET_ZFLG ((regflags.cznv >> 14) & 1) +#define GET_CFLG ((regflags.cznv >> 8) & 1) +#define GET_VFLG ((regflags.cznv >> 0) & 1) +#define GET_NFLG ((regflags.cznv >> 15) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.cznv = 0) +#define GET_CZNV (regflags.cznv) +#define IOR_CZNV(X) (regflags.cznv |= (X)) +#define SET_CZNV(X) (regflags.cznv = (X)) + +#define COPY_CARRY (regflags.x = (regflags.cznv)>>8) + +extern struct flag_struct regflags __asm__ ("regflags"); + +static inline int cctrue(int cc) +{ + uae_u32 cznv = regflags.cznv; + switch(cc){ + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ + case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */ + case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */ + case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */ + case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */ + case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */ + case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */ + case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */ + case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */ + case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */ + case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */ + case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */ + case 14: + cznv &= 0xc001; + return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ + case 15: + cznv &= 0xc001; + return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + } + abort(); + return 0; +} + +/* Manually emit LAHF instruction so that 64-bit assemblers can grok it */ +#if defined CPU_x86_64 && defined __GNUC__ +#define ASM_LAHF ".byte 0x9f" +#else +#define ASM_LAHF "lahf" +#endif + +/* Is there any way to do this without declaring *all* memory clobbered? + I.e. any way to tell gcc that some byte-sized value is in %al? */ +#define optflag_testl(v) \ + __asm__ __volatile__ ("andl %0,%0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "r" (v) : "%eax","cc","memory") + +#define optflag_testw(v) \ + __asm__ __volatile__ ("andw %w0,%w0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "r" (v) : "%eax","cc","memory") + +#define optflag_testb(v) \ + __asm__ __volatile__ ("andb %b0,%b0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "q" (v) : "%eax","cc","memory") + +#define optflag_addl(v, s, d) do { \ + __asm__ __volatile__ ("addl %k1,%k0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_addw(v, s, d) do { \ + __asm__ __volatile__ ("addw %w1,%w0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_addb(v, s, d) do { \ + __asm__ __volatile__ ("addb %b1,%b0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_subl(v, s, d) do { \ + __asm__ __volatile__ ("subl %k1,%k0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_subw(v, s, d) do { \ + __asm__ __volatile__ ("subw %w1,%w0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_subb(v, s, d) do { \ + __asm__ __volatile__ ("subb %b1,%b0\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_cmpl(s, d) \ + __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "rmi" (s), "r" (d) : "%eax","cc","memory") + +#define optflag_cmpw(s, d) \ + __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "rmi" (s), "r" (d) : "%eax","cc","memory") + +#define optflag_cmpb(s, d) \ + __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ + ASM_LAHF "\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "qmi" (s), "q" (d) : "%eax","cc","memory") + +#endif + +#elif defined(CPU_arm) && defined(ARM_ASSEMBLY) + +struct flag_struct { + uae_u32 nzcv; + uae_u32 x; +}; + +#define FLAGVAL_Q 0x08000000 +#define FLAGVAL_V 0x10000000 +#define FLAGVAL_C 0x20000000 +#define FLAGVAL_Z 0x40000000 +#define FLAGVAL_N 0x80000000 + +#define SET_NFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x80000000) | (((y) & 1) << 31)) +#define SET_ZFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x40000000) | (((y) & 1) << 30)) +#define SET_CFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x20000000) | (((y) & 1) << 29)) +#define SET_VFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x10000000) | (((y) & 1) << 28)) +#define SET_XFLG(y) (regflags.x = (y)) + +#define GET_NFLG ((regflags.nzcv >> 31) & 1) +#define GET_ZFLG ((regflags.nzcv >> 30) & 1) +#define GET_CFLG ((regflags.nzcv >> 29) & 1) +#define GET_VFLG ((regflags.nzcv >> 28) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.nzcv = 0) +#define GET_CZNV (regflags.nzcv) +#define IOR_CZNV(X) (regflags.nzcv |= (X)) +#define SET_CZNV(X) (regflags.nzcv = (X)) + +#define COPY_CARRY (regflags.x = (regflags.nzcv)>>29) + +extern struct flag_struct regflags __asm__ ("regflags"); + +static inline int cctrue(int cc) +{ + unsigned int nzcv = regflags.nzcv; + switch(cc){ + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (nzcv & 0x60000000) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ + case 3: return (nzcv & 0x60000000) != 0; /* GET_CFLG || GET_ZFLG; LS */ + case 4: return (nzcv & 0x20000000) == 0; /* !GET_CFLG; CC */ + case 5: return (nzcv & 0x20000000) != 0; /* GET_CFLG; CS */ + case 6: return (nzcv & 0x40000000) == 0; /* !GET_ZFLG; NE */ + case 7: return (nzcv & 0x40000000) != 0; /* GET_ZFLG; EQ */ + case 8: return (nzcv & 0x10000000) == 0; /* !GET_VFLG; VC */ + case 9: return (nzcv & 0x10000000) != 0; /* GET_VFLG; VS */ + case 10:return (nzcv & 0x80000000) == 0; /* !GET_NFLG; PL */ + case 11:return (nzcv & 0x80000000) != 0; /* GET_NFLG; MI */ + case 12:return (((nzcv << 3) ^ nzcv) & 0x80000000) == 0; /* GET_NFLG == GET_VFLG; GE */ + case 13:return (((nzcv << 3) ^ nzcv) & 0x80000000) != 0; /* GET_NFLG != GET_VFLG; LT */ + case 14: + nzcv &= 0xd0000000; + return (((nzcv << 3) ^ nzcv) & 0xc0000000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ + case 15: + nzcv &= 0xd0000000; + return (((nzcv << 3) ^ nzcv) & 0xc0000000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + } + return 0; +} + +#define optflag_testl(v) do {\ + __asm__ __volatile__ ("tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "r" (v) \ + : "cc"); \ + } while(0) + +#define optflag_addl(v, s, d) do { \ + __asm__ __volatile__ ("adds %[rv],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_subl(v, s, d) do { \ + __asm__ __volatile__ ("subs %[rv],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_cmpl(s, d) do { \ + __asm__ __volatile__ ("cmp %[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#if defined(ARMV6_ASSEMBLY) + +// #pragma message "ARM/v6 Assembly optimized flags" + +#define optflag_testw(v) do { \ + __asm__ __volatile__ ("sxth %[rv],%[rv]\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_testb(v) do {\ + __asm__ __volatile__ ("sxtb %[rv],%[rv]\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_addw(v, s, d) do { \ + __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ + "sxth %[rs],%[rs]\n\t" \ + "adds %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_addb(v, s, d) do { \ + __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ + "sxtb %[rs],%[rs]\n\t" \ + "adds %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_subw(v, s, d) do { \ + __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ + "sxth %[rs],%[rs]\n\t" \ + "subs %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_subb(v, s, d) do { \ + __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ + "sxtb %[rs],%[rs]\n\t" \ + "subs %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_cmpw(s, d) do { \ + __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ + "sxth %[rs],%[rs]\n\t" \ + "cmp %[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#define optflag_cmpb(s, d) do { \ + __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ + "sxtb %[rs],%[rs]\n\t" \ + "cmp %[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#else + +// #pragma message "ARM/generic Assembly optimized flags" + +#define optflag_testw(v) do { \ + __asm__ __volatile__ ("lsl %[rv],%[rv],#16\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_testb(v) do {\ + __asm__ __volatile__ ("lsl %[rv],%[rv],#24\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_addw(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ + "adds %[rd],%[rd],%[rs],lsl #16\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "lsr %[rv],%[rd],#16\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_addb(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ + "adds %[rd],%[rd],%[rs],lsl #24\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "lsr %[rv],%[rd],#24\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_subw(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ + "subs %[rd],%[rd],%[rs],lsl #16\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + "lsr %[rv],%[rd],#16\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_subb(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ + "subs %[rd],%[rd],%[rs],lsl #24\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + "lsr %[rv],%[rd],#24\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY; \ + } while(0) + +#define optflag_cmpw(s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ + "cmp %[rd],%[rs],lsl #16\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#define optflag_cmpb(s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ + "cmp %[rd],%[rs],lsl #24\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#endif + +#elif defined(CPU_sparc) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)) struct flag_struct { unsigned char nzvc; @@ -151,22 +662,29 @@ struct flag_struct { extern struct flag_struct regflags; -#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) -#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) -#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) -#define SET_XFLG(y) (regflags.x = (y)) +#define FLAGVAL_Z 0x04 +#define FLAGVAL_N 0x08 -#define GET_ZFLG ((regflags.nzvc >> 2) & 1) -#define GET_CFLG (regflags.nzvc & 1) -#define GET_VFLG ((regflags.nzvc >> 1) & 1) -#define GET_NFLG ((regflags.nzvc >> 3) & 1) -#define GET_XFLG (regflags.x & 1) +#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) +#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) +#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) +#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) +#define SET_XFLG(y) (regflags.x = (y)) + +#define GET_ZFLG ((regflags.nzvc >> 2) & 1) +#define GET_CFLG (regflags.nzvc & 1) +#define GET_VFLG ((regflags.nzvc >> 1) & 1) +#define GET_NFLG ((regflags.nzvc >> 3) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.nzvc = 0) +#define GET_CZNV (reflags.nzvc) +#define IOR_CZNV(X) (refglags.nzvc |= (X)) +#define SET_CZNV(X) (regflags.nzvc = (X)) -#define CLEAR_CZNV (regflags.nzvc = 0) #define COPY_CARRY (regflags.x = regflags.nzvc) -static __inline__ int cctrue(int cc) +static inline int cctrue(int cc) { uae_u32 nzvc = regflags.nzvc; switch(cc){ @@ -787,6 +1305,8 @@ static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae #endif /* SPARC_V9_ASSEMBLY */ +#endif + #else struct flag_struct { @@ -805,7 +1325,28 @@ extern struct flag_struct regflags; #define VFLG (regflags.v) #define XFLG (regflags.x) -static __inline__ int cctrue(const int cc) +#define SET_CFLG(x) (CFLG = (x)) +#define SET_NFLG(x) (NFLG = (x)) +#define SET_VFLG(x) (VFLG = (x)) +#define SET_ZFLG(x) (ZFLG = (x)) +#define SET_XFLG(x) (XFLG = (x)) + +#define GET_CFLG CFLG +#define GET_NFLG NFLG +#define GET_VFLG VFLG +#define GET_ZFLG ZFLG +#define GET_XFLG XFLG + +#define CLEAR_CZNV do { \ + SET_CFLG (0); \ + SET_ZFLG (0); \ + SET_NFLG (0); \ + SET_VFLG (0); \ +} while (0) + +#define COPY_CARRY (SET_XFLG (GET_CFLG)) + +static inline int cctrue(const int cc) { switch(cc){ case 0: return 1; /* T */ @@ -828,4 +1369,6 @@ static __inline__ int cctrue(const int cc) return 0; } -#endif +#endif /* OPTIMIZED_FLAGS */ + +#endif /* M68K_FLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/memory-uae.h b/BasiliskII/src/uae_cpu/memory-uae.h new file mode 100644 index 00000000..c93aeb37 --- /dev/null +++ b/BasiliskII/src/uae_cpu/memory-uae.h @@ -0,0 +1,606 @@ +/* + * memory.h - memory management + * + * Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + /* + * UAE - The Un*x Amiga Emulator + * + * memory management + * + * Copyright 1995 Bernd Schmidt + */ + +#ifndef UAE_MEMORY_H +#define UAE_MEMORY_H + +#include "sysdeps.h" +#include "string.h" +#include "hardware.h" +#include "parameters.h" +#include "registers.h" +#include "cpummu.h" +#include "readcpu.h" + +# include + +// newcpu.h +extern void Exception (int, uaecptr); +#ifdef EXCEPTIONS_VIA_LONGJMP + extern JMP_BUF excep_env; + #define SAVE_EXCEPTION \ + JMP_BUF excep_env_old; \ + memcpy(excep_env_old, excep_env, sizeof(JMP_BUF)) + #define RESTORE_EXCEPTION \ + memcpy(excep_env, excep_env_old, sizeof(JMP_BUF)) + #define TRY(var) int var = SETJMP(excep_env); if (!var) + #define CATCH(var) else + #define THROW(n) LONGJMP(excep_env, n) + #define THROW_AGAIN(var) LONGJMP(excep_env, var) + #define VOLATILE volatile +#else + struct m68k_exception { + int prb; + m68k_exception (int exc) : prb (exc) {} + operator int() { return prb; } + }; + #define SAVE_EXCEPTION + #define RESTORE_EXCEPTION + #define TRY(var) try + #define CATCH(var) catch(m68k_exception var) + #define THROW(n) throw m68k_exception(n) + #define THROW_AGAIN(var) throw + #define VOLATILE +#endif /* EXCEPTIONS_VIA_LONGJMP */ +extern int in_exception_2; + +#define STRAM_END 0x0e00000UL // should be replaced by global ROMBase as soon as ROMBase will be a constant +#define ROM_END 0x0e80000UL // should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes +#define FastRAM_BEGIN 0x1000000UL // should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant +#ifdef FixedSizeFastRAM +#define FastRAM_SIZE (FixedSizeFastRAM * 1024 * 1024) +#else +#define FastRAM_SIZE FastRAMSize +#endif + +#ifdef FIXED_VIDEORAM +#define ARANYMVRAMSTART 0xf0000000UL +#endif + +#define ARANYMVRAMSIZE 0x00100000 // should be a variable to protect VGA card offscreen memory + +#ifdef FIXED_VIDEORAM +extern uintptr VMEMBaseDiff; +#else +extern uae_u32 VideoRAMBase; +#endif + +#ifdef ARAM_PAGE_CHECK +extern uaecptr pc_page, read_page, write_page; +extern uintptr pc_offset, read_offset, write_offset; +# ifdef PROTECT2K +# define ARAM_PAGE_MASK 0x7ff +# else +# ifdef FULLMMU +# define ARAM_PAGE_MASK 0xfff +# else +# define ARAM_PAGE_MASK 0xfffff +# endif +# endif +#endif + +extern uintptr MEMBaseDiff; +extern uintptr ROMBaseDiff; +extern uintptr FastRAMBaseDiff; +# define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra)) +# define InitROMBaseDiff(va, ra) (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra)) +# define InitFastRAMBaseDiff(va, ra) (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra)) + +#ifdef FIXED_VIDEORAM +#define InitVMEMBaseDiff(va, ra) (VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra)) +#else +#define InitVMEMBaseDiff(va, ra) (ra = (uintptr)(va) + MEMBaseDiff) +#endif + +extern "C" void breakpt(void); + + +static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);} +static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);} + + +#ifndef NOCHECKBOUNDARY +static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write) +{ + if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) { +#ifdef PROTECT2K + // protect first 2kB of RAM - access in supervisor mode only + if (!super && addr < 0x00000800UL) + return false; +#endif + // check for write access to protected areas: + // - first two longwords of ST-RAM are non-writable (ROM shadow) + // - non-writable area between end of ST-RAM and begin of FastRAM + if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size))) + return true; + } +#ifdef FIXED_VIDEORAM + return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size); +#else + return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size); +#endif +} +/* + * "size" is the size of the memory access (byte = 1, word = 2, long = 4) + */ +static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write) +{ + if (test_ram_boundary(addr, size, regs.s, write)) + return; + + // D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr)); + regs.mmu_fault_addr = addr; + regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8)); + breakpt(); + THROW(2); +} + +#else +static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; } +static inline void check_ram_boundary(uaecptr, int, bool) { } +#endif + +#ifdef FIXED_VIDEORAM +# define do_get_real_address(a) ((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff))) +#else +# define do_get_real_address(a) ((uae_u8 *)((uintptr)(a) + MEMBaseDiff)) +#endif + +static inline uae_u8 *phys_get_real_address(uaecptr addr) +{ + return do_get_real_address(addr); +} + +#ifndef NOCHECKBOUNDARY +static inline bool phys_valid_address(uaecptr addr, bool write, int sz) +{ + return test_ram_boundary(addr, sz, regs.s, write); +} +#else +static inline bool phys_valid_address(uaecptr, bool, int) { return true; } +#endif + +static inline uae_u64 phys_get_quad(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_quad((uae_u64*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */ +#endif + check_ram_boundary(addr, 8, false); + uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_quad(m); +} + +static inline uae_u32 phys_get_long(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_long((uae_u32*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); +#endif + check_ram_boundary(addr, 4, false); + uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_long(m); +} + +static inline uae_u32 phys_get_word(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_word((uae_u16*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr); +#endif + check_ram_boundary(addr, 2, false); + uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_word(m); +} + +static inline uae_u32 phys_get_byte(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_byte((uae_u8*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr); +#endif + check_ram_boundary(addr, 1, false); + uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_byte(m); +} + +static inline void phys_put_quad(uaecptr addr, uae_u64 l) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_quad((uae_u64*)(addr + write_offset), l); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_l(addr, l); /* TODO: must be HWput_q */ + return; + } +#endif + check_ram_boundary(addr, 8, true); + uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_quad(m, l); +} + +static inline void phys_put_long(uaecptr addr, uae_u32 l) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_long((uae_u32*)(addr + write_offset), l); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_l(addr, l); + return; + } +#endif + check_ram_boundary(addr, 4, true); + uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_long(m, l); +} + +static inline void phys_put_word(uaecptr addr, uae_u32 w) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_word((uae_u16*)(addr + write_offset), w); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_w(addr, w); + return; + } +#endif + check_ram_boundary(addr, 2, true); + uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_word(m, w); +} + +static inline void phys_put_byte(uaecptr addr, uae_u32 b) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_byte((uae_u8*)(addr + write_offset), b); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_b(addr, b); + return; + } +#endif + check_ram_boundary(addr, 1, true); + uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_byte(m, b); +} + +#ifdef FULLMMU +static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size) +{ + return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000); +} + +static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) +{ + return do_get_real_address(cl->phys + addr); +} + +static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl)); + return mmu_get_quad_slow(addr, regs.s, data, cl); +} + +static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr) +{ + return mmu_get_quad(addr, 1); +} + +static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); + return mmu_get_long_slow(addr, regs.s, data, size, cl); +} + +static ALWAYS_INLINE uae_u32 get_long(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_long_unaligned(addr, 1); + return mmu_get_long(addr, 1, sz_long); +} + +static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); + return mmu_get_word_slow(addr, regs.s, data, size, cl); +} + +static ALWAYS_INLINE uae_u16 get_word(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 2))) + return mmu_get_word_unaligned(addr, 1); + return mmu_get_word(addr, 1, sz_word); +} + +static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); + return mmu_get_byte_slow(addr, regs.s, data, size, cl); +} + +static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr) +{ + return mmu_get_byte(addr, 1, sz_byte); +} + +static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_quad_slow(addr, val, regs.s, data, cl); +} + +static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val) +{ + mmu_put_quad(addr, val, 1); +} + +static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_long_slow(addr, val, regs.s, data, size, cl); +} + +static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val) +{ + if (unlikely(is_unaligned(addr, 4))) + mmu_put_long_unaligned(addr, val, 1); + else + mmu_put_long(addr, val, 1, sz_long); +} + +static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_word_slow(addr, val, regs.s, data, size, cl); +} + +static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val) +{ + if (unlikely(is_unaligned(addr, 2))) + mmu_put_word_unaligned(addr, val, 1); + else + mmu_put_word(addr, val, 1, sz_word); +} + +static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_byte_slow(addr, val, regs.s, data, size, cl); +} + +static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val) +{ + mmu_put_byte(addr, val, 1, sz_byte); +} + +static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz) +{ + (void)sz; + return phys_get_real_address(mmu_translate(addr, regs.s, 1, write)); +} + +static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) + return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); + return mmu_get_long_slow(addr, super, data, size, cl); +} + +static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) + return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); + return mmu_get_word_slow(addr, super, data, size, cl); +} + +static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) + return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); + return mmu_get_byte_slow(addr, super, data, size, cl); +} + +static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) + do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_long_slow(addr, val, super, data, size, cl); +} + +static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) + do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_word_slow(addr, val, super, data, size, cl); +} + +static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) + do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_byte_slow(addr, val, super, data, size, cl); +} + +static inline bool valid_address(uaecptr addr, bool write, int sz) +{ + SAVE_EXCEPTION; + TRY(prb) { + (void)sz; + check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write); + RESTORE_EXCEPTION; + return true; + } + CATCH(prb) { + RESTORE_EXCEPTION; + return false; + } +} + +#else + +# define get_quad(a) phys_get_quad(a) +# define get_long(a) phys_get_long(a) +# define get_word(a) phys_get_word(a) +# define get_byte(a) phys_get_byte(a) +# define put_quad(a,b) phys_put_quad(a,b) +# define put_long(a,b) phys_put_long(a,b) +# define put_word(a,b) phys_put_word(a,b) +# define put_byte(a,b) phys_put_byte(a,b) +# define get_real_address(a,w,s) phys_get_real_address(a) + +#define valid_address(a,w,s) phys_valid_address(a,w,s) +#endif + +static inline void flush_internals() { +#ifdef ARAM_PAGE_CHECK + pc_page = 0xeeeeeeee; + read_page = 0xeeeeeeee; + write_page = 0xeeeeeeee; +#endif +} + +#endif /* MEMORY_H */ + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/memory.cpp b/BasiliskII/src/uae_cpu/memory.cpp new file mode 100644 index 00000000..e56f993d --- /dev/null +++ b/BasiliskII/src/uae_cpu/memory.cpp @@ -0,0 +1,59 @@ +/* + * memory.cpp - memory management + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + /* + * UAE - The Un*x Amiga Emulator + * + * Memory management + * + * (c) 1995 Bernd Schmidt + */ + +#include "sysdeps.h" + +#include "memory.h" +#define DEBUG 0 +#include "debug.h" + +#ifdef ARAM_PAGE_CHECK +uaecptr pc_page = 0xeeeeeeee; +uintptr pc_offset = 0; +uaecptr read_page = 0xeeeeeeee; +uintptr read_offset = 0; +uaecptr write_page = 0xeeeeeeee; +uintptr write_offset = 0; +#endif + +extern "C" void breakpt(void) +{ + // bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr); +} + +#if !KNOWN_ALLOC && !NORMAL_ADDRESSING +// This part need rewrite for ARAnyM !! +// It can be taken from hatari. + +#error Not prepared for your platform, maybe you need memory banks from hatari + +#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */ diff --git a/BasiliskII/src/uae_cpu/memory.h b/BasiliskII/src/uae_cpu/memory.h index 670c2ee7..f7bab41d 100644 --- a/BasiliskII/src/uae_cpu/memory.h +++ b/BasiliskII/src/uae_cpu/memory.h @@ -27,6 +27,34 @@ extern uintptr MEMBaseDiff; #endif +extern void Exception (int, uaecptr); +#ifdef EXCEPTIONS_VIA_LONGJMP + extern JMP_BUF excep_env; + #define SAVE_EXCEPTION \ + JMP_BUF excep_env_old; \ + memcpy(excep_env_old, excep_env, sizeof(JMP_BUF)) + #define RESTORE_EXCEPTION \ + memcpy(excep_env, excep_env_old, sizeof(JMP_BUF)) + #define TRY(var) int var = SETJMP(excep_env); if (!var) + #define CATCH(var) else + #define THROW(n) LONGJMP(excep_env, n) + #define THROW_AGAIN(var) LONGJMP(excep_env, var) + #define VOLATILE volatile +#else + struct m68k_exception { + int prb; + m68k_exception (int exc) : prb (exc) {} + operator int() { return prb; } + }; + #define SAVE_EXCEPTION + #define RESTORE_EXCEPTION + #define TRY(var) try + #define CATCH(var) catch(m68k_exception var) + #define THROW(n) throw m68k_exception(n) + #define THROW_AGAIN(var) throw + #define VOLATILE +#endif /* EXCEPTIONS_VIA_LONGJMP */ + #if DIRECT_ADDRESSING static __inline__ uae_u8 *do_get_real_address(uaecptr addr) { @@ -41,40 +69,57 @@ static __inline__ uae_u32 get_long(uaecptr addr) uae_u32 * const m = (uae_u32 *)do_get_real_address(addr); return do_get_mem_long(m); } +#define phys_get_long get_long static __inline__ uae_u32 get_word(uaecptr addr) { uae_u16 * const m = (uae_u16 *)do_get_real_address(addr); return do_get_mem_word(m); } +#define phys_get_word get_word static __inline__ uae_u32 get_byte(uaecptr addr) { uae_u8 * const m = (uae_u8 *)do_get_real_address(addr); return do_get_mem_byte(m); } +#define phys_get_byte get_byte static __inline__ void put_long(uaecptr addr, uae_u32 l) { uae_u32 * const m = (uae_u32 *)do_get_real_address(addr); do_put_mem_long(m, l); } +#define phys_put_long put_long static __inline__ void put_word(uaecptr addr, uae_u32 w) { uae_u16 * const m = (uae_u16 *)do_get_real_address(addr); do_put_mem_word(m, w); } +#define phys_put_word put_word static __inline__ void put_byte(uaecptr addr, uae_u32 b) { uae_u8 * const m = (uae_u8 *)do_get_real_address(addr); do_put_mem_byte(m, b); } +#define phys_put_byte put_byte static __inline__ uae_u8 *get_real_address(uaecptr addr) { return do_get_real_address(addr); } +static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz) +{ + return do_get_real_address(addr); +} +static inline uae_u8 *phys_get_real_address(uaecptr addr) +{ + return do_get_real_address(addr); +} static __inline__ uae_u32 get_virtual_address(uae_u8 *addr) { return do_get_virtual_address(addr); } #endif /* DIRECT_ADDRESSING */ +static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {} +static inline void flush_internals() {} + #endif /* MEMORY_H */ diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index 4adf0cc8..ac1505f5 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -1,3 +1,28 @@ +/* + * newcpu.cpp - CPU emulation + * + * Copyright (c) 2010 ARAnyM dev team (see AUTHORS) + * + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * @@ -6,27 +31,44 @@ * (c) 1995 Bernd Schmidt */ -#include -#include -#include - #include "sysdeps.h" +#include #include "cpu_emulation.h" #include "main.h" #include "emul_op.h" - -extern int intlev(void); // From baisilisk_glue.cpp - #include "m68k.h" #include "memory.h" #include "readcpu.h" #include "newcpu.h" +#ifdef USE_JIT +# include "compiler/compemu.h" +#endif +#include "fpu/fpu.h" +#include "cpummu.h" +// #include "natfeats.h" +// #include "disasm-glue.h" + +#include + +#define DEBUG 0 +#include "debug.h" + +#define SANITY_CHECK_ATC 1 + +struct fixup fixup = {0, 0, 0}; int quit_program = 0; -int debugging = 0; + +// For instruction $7139 +bool cpu_debugging = false; + struct flag_struct regflags; +/* LongJump buffers */ +#ifdef EXCEPTIONS_VIA_LONGJMP +JMP_BUF excep_env; +#endif /* Opcode of faulting instruction */ uae_u16 last_op_for_exception_3; /* PC at fault time */ @@ -41,128 +83,132 @@ int movem_index1[256]; int movem_index2[256]; int movem_next[256]; -int fpp_movem_index1[256]; -int fpp_movem_index2[256]; -int fpp_movem_next[256]; +#ifdef FLIGHT_RECORDER -cpuop_func *cpufunctbl[65536]; +// feel free to edit the following defines to customize the dump +#define FRLOG_HOTKEY 1 /* 1 = dump only when hotkey is held down */ +#define FRLOG_ALL 1 /* 1 = dump continuously to ever growing log */ +#define FRLOG_IRQ 0 /* 1 = dump also CPU in interrupts */ +#define FRLOG_REGS 0 /* 1 = dump also all data/address registers */ +#define FRLOG_SIZE 8192 /* this many instructions in single dump */ -#define COUNT_INSTRS 0 +struct rec_step { + uae_u32 d[8]; + uae_u32 a[8]; + uae_u32 pc; + uae_u16 sr; + uae_u32 usp; + uae_u32 msp; + uae_u32 isp; + uae_u16 instr; +}; -#if COUNT_INSTRS -static unsigned long int instrcount[65536]; -static uae_u16 opcodenums[65536]; +bool cpu_flight_recorder_active = false; -static int compfn (const void *el1, const void *el2) -{ - return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2]; -} - -static char *icountfilename (void) -{ - char *name = getenv ("INSNCOUNT"); - if (name) - return name; - return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount"; -} - -void dump_counts (void) -{ - FILE *f = fopen (icountfilename (), "w"); - unsigned long int total; - int i; - - write_log ("Writing instruction count file...\n"); - for (i = 0; i < 65536; i++) { - opcodenums[i] = i; - total += instrcount[i]; - } - qsort (opcodenums, 65536, sizeof(uae_u16), compfn); - - fprintf (f, "Total: %lu\n", total); - for (i=0; i < 65536; i++) { - unsigned long int cnt = instrcount[opcodenums[i]]; - struct instr *dp; - struct mnemolookup *lookup; - if (!cnt) - break; - dp = table68k + opcodenums[i]; - for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) - ; - fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name); - } - fclose (f); -} +#if FRLOG_ALL +const int LOG_SIZE = 10; #else -void dump_counts (void) -{ -} +const int LOG_SIZE = FRLOG_SIZE; #endif +static rec_step frlog[LOG_SIZE]; +static int log_ptr = -1; // First time initialization + +static const char *log_filename(void) +{ + const char *name = getenv("M68K_LOG_FILE"); + return name ? name : "log.68k"; +} + +void dump_flight_recorder(void) +{ +#if FRLOG_ALL + FILE *f = fopen(log_filename(), "a"); +#else + FILE *f = fopen(log_filename(), "w"); +#endif + if (f == NULL) + return; + for (int i = 0; i < LOG_SIZE; i++) { + int j = (i + log_ptr) % LOG_SIZE; + fprintf(f, "pc %08x instr %04x sr %04x usp %08x msp %08x isp %08x\n", frlog[j].pc, frlog[j].instr, frlog[j].sr, frlog[j].usp, frlog[j].msp, frlog[j].isp); + // adding a simple opcode -> assembler conversion table would help +#if FRLOG_REGS + fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", frlog[j].d[0], frlog[j].d[1], frlog[j].d[2], frlog[j].d[3]); + fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", frlog[j].d[4], frlog[j].d[5], frlog[j].d[6], frlog[j].d[7]); + fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", frlog[j].a[0], frlog[j].a[1], frlog[j].a[2], frlog[j].a[3]); + fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", frlog[j].a[4], frlog[j].a[5], frlog[j].a[6], frlog[j].a[7]); +#endif + } + fclose(f); +} + +void m68k_record_step(uaecptr pc, int opcode) +{ + static bool last_state = false; + +#if FRLOG_HOTKEY + if (! cpu_flight_recorder_active) { + if (last_state) { + // dump log out + dump_flight_recorder(); + + // remember last state + last_state = false; + } + return; + } +#endif + + if (! last_state) { + // reset old log + log_ptr = 0; + memset(frlog, 0, sizeof(frlog)); + // remember last state + last_state = true; + } + +#if FRLOG_REGS + for (int i = 0; i < 8; i++) { + frlog[log_ptr].d[i] = m68k_dreg(regs, i); + frlog[log_ptr].a[i] = m68k_areg(regs, i); + } +#endif + frlog[log_ptr].pc = pc; + + MakeSR(); +#if ! FRLOG_IRQ + // is CPU in interrupt handler? Quit if should not be logged. + if (regs.s && !regs.m) return; +#endif + frlog[log_ptr].sr = regs.sr; + frlog[log_ptr].usp = regs.usp; + frlog[log_ptr].msp = regs.msp; + frlog[log_ptr].isp = regs.isp; + frlog[log_ptr].instr = opcode; + + log_ptr = (log_ptr + 1) % LOG_SIZE; +#if FRLOG_ALL + if (log_ptr == 0) dump_flight_recorder(); +#endif +} +#endif /* FLIGHT_RECORDER */ int broken_in; -static __inline__ unsigned int cft_map (unsigned int f) +static inline unsigned int cft_map (unsigned int f) { -#ifndef HAVE_GET_WORD_UNSWAPPED +#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU) return f; #else - return ((f >> 8) & 255) | ((f & 255) << 8); + return do_byteswap_16(f); #endif } -static void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; - -static void REGPARAM2 op_illg_1 (uae_u32 opcode) +void REGPARAM2 op_illg_1 (uae_u32 opcode) { op_illg (cft_map (opcode)); } -static void build_cpufunctbl (void) -{ - int i; - unsigned long opcode; - int cpu_level = 0; // 68000 (default) - if (CPUType == 4) - cpu_level = 4; // 68040 with FPU - else { - if (FPUType) - cpu_level = 3; // 68020 with FPU - else if (CPUType >= 2) - cpu_level = 2; // 68020 - else if (CPUType == 1) - cpu_level = 1; - } - struct cputbl *tbl = ( - cpu_level == 4 ? op_smalltbl_0 - : cpu_level == 3 ? op_smalltbl_1 - : cpu_level == 2 ? op_smalltbl_2 - : cpu_level == 1 ? op_smalltbl_3 - : op_smalltbl_4); - - for (opcode = 0; opcode < 65536; opcode++) - cpufunctbl[cft_map (opcode)] = op_illg_1; - for (i = 0; tbl[i].handler != NULL; i++) { - if (! tbl[i].specific) - cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; - } - for (opcode = 0; opcode < 65536; opcode++) { - cpuop_func *f; - - if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) - continue; - - if (table68k[opcode].handler != -1) { - f = cpufunctbl[cft_map (table68k[opcode].handler)]; - if (f == op_illg_1) - abort(); - cpufunctbl[cft_map (opcode)] = f; - } - } - for (i = 0; tbl[i].handler != NULL; i++) { - if (tbl[i].specific) - cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; - } -} void init_m68k (void) { @@ -177,343 +223,123 @@ void init_m68k (void) movem_index2[i] = 7-j; movem_next[i] = i & (~(1 << j)); } - for (i = 0 ; i < 256 ; i++) { - int j; - for (j = 7 ; j >= 0 ; j--) { - if (i & (1 << j)) break; - } - fpp_movem_index1[i] = 7-j; - fpp_movem_index2[i] = j; - fpp_movem_next[i] = i & (~(1 << j)); - } -#if COUNT_INSTRS - { - FILE *f = fopen (icountfilename (), "r"); - memset (instrcount, 0, sizeof instrcount); - if (f) { - uae_u32 opcode, count, total; - char name[20]; - write_log ("Reading instruction count file...\n"); - fscanf (f, "Total: %lu\n", &total); - while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) { - instrcount[opcode] = count; - } - fclose(f); - } - } -#endif +#ifdef USE_JIT + /* still needed by build_comp(); FIXME */ read_table68k (); do_merges (); +#endif + fpu_init (CPUType == 4); +} - build_cpufunctbl (); +void exit_m68k (void) +{ + fpu_exit (); + + free(table68k); + table68k = NULL; } struct regstruct regs, lastint_regs; -static struct regstruct regs_backup[16]; -static int backup_pointer = 0; -static long int m68kpc_offset; +// MJ static struct regstruct regs_backup[16]; +// MJ static int backup_pointer = 0; int lastint_no; -#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) -#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) -#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) -uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf) +#ifdef FULLMMU +static inline uae_u8 get_ibyte_1(uae_u32 o) { - uae_u16 dp; - uae_s8 disp8; - uae_s16 disp16; - int r; - uae_u32 dispreg; - uaecptr addr; - uae_s32 offset = 0; - char buffer[80]; + return get_ibyte(o); +} +static inline uae_u16 get_iword_1(uae_u32 o) +{ + return get_iword(o); +} +static inline uae_u32 get_ilong_1(uae_u32 o) +{ + return get_ilong(o); +} +#else +# define get_ibyte_1(o) get_byte(m68k_getpc() + (o) + 1) +# define get_iword_1(o) get_word(m68k_getpc() + (o)) +# define get_ilong_1(o) get_long(m68k_getpc() + (o)) +#endif - switch (mode){ - case Dreg: - sprintf (buffer,"D%d", reg); - break; - case Areg: - sprintf (buffer,"A%d", reg); - break; - case Aind: - sprintf (buffer,"(A%d)", reg); - break; - case Aipi: - sprintf (buffer,"(A%d)+", reg); - break; - case Apdi: - sprintf (buffer,"-(A%d)", reg); - break; - case Ad16: - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr = m68k_areg(regs,reg) + (uae_s16)disp16; - sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff, - (unsigned long)addr); - break; - case Ad8r: - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; +/* + * extract bitfield data from memory and return it in the MSBs + * bdata caches the unmodified data for put_bitfield() + */ +uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) +{ + uae_u32 tmp, res, mask; - if (dp & 0x100) { - uae_s32 outer = 0, disp = 0; - uae_s32 base = m68k_areg(regs,reg); - char name[10]; - sprintf (name,"A%d, ",reg); - if (dp & 0x80) { base = 0; name[0] = 0; } - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name, - dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', - 1 << ((dp >> 9) & 3), - disp,outer, - (unsigned long)addr); - } else { - addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg; - sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, - dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', - 1 << ((dp >> 9) & 3), disp8, - (unsigned long)addr); + offset &= 7; + mask = 0xffffffffu << (32 - width); + switch ((offset + width + 7) >> 3) { + case 1: + tmp = get_byte(src); + res = tmp << (24 + offset); + bdata[0] = tmp & ~(mask >> (24 + offset)); + break; + case 2: + tmp = get_word(src); + res = tmp << (16 + offset); + bdata[0] = tmp & ~(mask >> (16 + offset)); + break; + case 3: + tmp = get_word(src); + res = tmp << (16 + offset); + bdata[0] = tmp & ~(mask >> (16 + offset)); + tmp = get_byte(src + 2); + res |= tmp << (8 + offset); + bdata[1] = tmp & ~(mask >> (8 + offset)); + break; + case 4: + tmp = get_long(src); + res = tmp << offset; + bdata[0] = tmp & ~(mask >> offset); + break; + case 5: + tmp = get_long(src); + res = tmp << offset; + bdata[0] = tmp & ~(mask >> offset); + tmp = get_byte(src + 4); + res |= tmp >> (8 - offset); + bdata[1] = tmp & ~(mask << (8 - offset)); + break; + default: + /* Panic? */ + res = 0; + break; } - break; - case PC16: - addr = m68k_getpc () + m68kpc_offset; - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr += (uae_s16)disp16; - sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr); - break; - case PC8r: - addr = m68k_getpc () + m68kpc_offset; - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; - - if (dp & 0x100) { - uae_s32 outer = 0,disp = 0; - uae_s32 base = addr; - char name[10]; - sprintf (name,"PC, "); - if (dp & 0x80) { base = 0; name[0] = 0; } - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name, - dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', - 1 << ((dp >> 9) & 3), - disp,outer, - (unsigned long)addr); - } else { - addr += (uae_s32)((uae_s8)disp8) + dispreg; - sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', - (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), - disp8, (unsigned long)addr); - } - break; - case absw: - sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset)); - m68kpc_offset += 2; - break; - case absl: - sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset)); - m68kpc_offset += 4; - break; - case imm: - switch (size){ - case sz_byte: - sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff)); - m68kpc_offset += 2; - break; - case sz_word: - sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff)); - m68kpc_offset += 2; - break; - case sz_long: - sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset))); - m68kpc_offset += 4; - break; - default: - break; - } - break; - case imm0: - offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff)); - break; - case imm1: - offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff)); - break; - case imm2: - offset = (uae_s32)get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - sprintf (buffer,"#$%08lx", (unsigned long)offset); - break; - case immi: - offset = (uae_s32)(uae_s8)(reg & 0xff); - sprintf (buffer,"#$%08lx", (unsigned long)offset); - break; - default: - break; - } - if (buf == 0) - printf ("%s", buffer); - else - strcat (buf, buffer); - return offset; + return res; } -/* The plan is that this will take over the job of exception 3 handling - - * the CPU emulation functions will just do a longjmp to m68k_go whenever - * they hit an odd address. */ -static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val) +/* + * write bitfield data (in the LSBs) back to memory, upper bits + * must be cleared already. + */ +void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) { - uae_u16 dp; - uae_s8 disp8; - uae_s16 disp16; - int r; - uae_u32 dispreg; - uaecptr addr; - uae_s32 offset = 0; - - switch (mode){ - case Dreg: - *val = m68k_dreg (regs, reg); - return 1; - case Areg: - *val = m68k_areg (regs, reg); - return 1; - - case Aind: - case Aipi: - addr = m68k_areg (regs, reg); - break; - case Apdi: - addr = m68k_areg (regs, reg); - break; - case Ad16: - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr = m68k_areg(regs,reg) + (uae_s16)disp16; - break; - case Ad8r: - addr = m68k_areg (regs, reg); - d8r_common: - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; - - if (dp & 0x100) { - uae_s32 outer = 0, disp = 0; - uae_s32 base = addr; - if (dp & 0x80) base = 0; - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - } else { - addr += (uae_s32)((uae_s8)disp8) + dispreg; + offset = (offset & 7) + width; + switch ((offset + 7) >> 3) { + case 1: + put_byte(dst, bdata[0] | (val << (8 - offset))); + break; + case 2: + put_word(dst, bdata[0] | (val << (16 - offset))); + break; + case 3: + put_word(dst, bdata[0] | (val >> (offset - 16))); + put_byte(dst + 2, bdata[1] | (val << (24 - offset))); + break; + case 4: + put_long(dst, bdata[0] | (val << (32 - offset))); + break; + case 5: + put_long(dst, bdata[0] | (val >> (offset - 32))); + put_byte(dst + 4, bdata[1] | (val << (40 - offset))); + break; } - break; - case PC16: - addr = m68k_getpc () + m68kpc_offset; - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr += (uae_s16)disp16; - break; - case PC8r: - addr = m68k_getpc () + m68kpc_offset; - goto d8r_common; - case absw: - addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - break; - case absl: - addr = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - break; - case imm: - switch (size){ - case sz_byte: - *val = get_iword_1 (m68kpc_offset) & 0xff; - m68kpc_offset += 2; - break; - case sz_word: - *val = get_iword_1 (m68kpc_offset) & 0xffff; - m68kpc_offset += 2; - break; - case sz_long: - *val = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - break; - default: - break; - } - return 1; - case imm0: - *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - return 1; - case imm1: - *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - return 1; - case imm2: - *val = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - return 1; - case immi: - *val = (uae_s32)(uae_s8)(reg & 0xff); - return 1; - default: - addr = 0; - break; - } - if ((addr & 1) == 0) - return 1; - - last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset; - last_fault_for_exception_3 = addr; - return 0; } uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp) @@ -595,6 +421,7 @@ void MakeFromSR (void) regs.t1 = (regs.sr >> 15) & 1; regs.t0 = (regs.sr >> 14) & 1; regs.s = (regs.sr >> 13) & 1; + mmu_set_super(regs.s); regs.m = (regs.sr >> 12) & 1; regs.intmask = (regs.sr >> 8) & 7; SET_XFLG ((regs.sr >> 4) & 1); @@ -602,7 +429,6 @@ void MakeFromSR (void) SET_ZFLG ((regs.sr >> 2) & 1); SET_VFLG ((regs.sr >> 1) & 1); SET_CFLG (regs.sr & 1); - if (CPUType >= 2) { if (olds != regs.s) { if (olds) { if (oldm) @@ -623,89 +449,149 @@ void MakeFromSR (void) m68k_areg(regs, 7) = regs.msp; } } - } else { - if (olds != regs.s) { - if (olds) { - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.usp; - } else { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - } - } + + SPCFLAGS_SET( SPCFLAG_INT ); + if (regs.t1 || regs.t0) + SPCFLAGS_SET( SPCFLAG_TRACE ); + else + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); +} + +/* for building exception frames */ +static inline void exc_push_word(uae_u16 w) +{ + m68k_areg(regs, 7) -= 2; + put_word(m68k_areg(regs, 7), w); +} +static inline void exc_push_long(uae_u32 l) +{ + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), l); +} + +static inline void exc_make_frame( + int format, + uae_u16 sr, + uae_u32 currpc, + int nr, + uae_u32 x0, + uae_u32 x1 +) +{ + switch(format) { + case 4: + exc_push_long(x1); + exc_push_long(x0); + break; + case 3: + case 2: + exc_push_long(x0); + break; } - regs.spcflags |= SPCFLAG_INT; - if (regs.t1 || regs.t0) - regs.spcflags |= SPCFLAG_TRACE; - else - regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + exc_push_word((format << 12) + (nr * 4)); /* format | vector */ + exc_push_long(currpc); + exc_push_word(sr); } +#ifdef EXCEPTIONS_VIA_LONGJMP +static int building_bus_fault_stack_frame=0; +#endif + void Exception(int nr, uaecptr oldpc) { + uae_u32 currpc = m68k_getpc (); MakeSR(); + + if (fixup.flag) + { + m68k_areg(regs, fixup.reg) = fixup.value; + fixup.flag = 0; + } + if (!regs.s) { regs.usp = m68k_areg(regs, 7); - if (CPUType >= 2) - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - else - m68k_areg(regs, 7) = regs.isp; + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; regs.s = 1; + mmu_set_super(1); } - if (CPUType > 0) { - if (nr == 2 || nr == 3) { - int i; - /* @@@ this is probably wrong (?) */ - for (i = 0 ; i < 12 ; i++) { - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0); - } - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0xa000 + nr * 4); - } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), oldpc); - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0x2000 + nr * 4); - } else if (regs.m && nr >= 24 && nr < 32) { - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), nr * 4); - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), m68k_getpc ()); - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), regs.sr); - regs.sr |= (1 << 13); - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0x1000 + nr * 4); - } else { - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), nr * 4); + + if (nr == 2) { + /* BUS ERROR handler begins */ +#ifdef ENABLE_EPSLIMITER + check_eps_limit(currpc); +#endif + // panicbug("Exception Nr. %d CPC: %08lx NPC: %08lx SP=%08lx Addr: %08lx", nr, currpc, get_long (regs.vbr + 4*nr), m68k_areg(regs, 7), regs.mmu_fault_addr); + +#ifdef EXCEPTIONS_VIA_LONGJMP + if (!building_bus_fault_stack_frame) +#else + try +#endif + { +#ifdef EXCEPTIONS_VIA_LONGJMP + building_bus_fault_stack_frame= 1; +#endif + /* 68040 */ + exc_push_long(0); /* PD3 */ + exc_push_long(0); /* PD2 */ + exc_push_long(0); /* PD1 */ + exc_push_long(0); /* PD0/WB1D */ + exc_push_long(0); /* WB1A */ + exc_push_long(0); /* WB2D */ + exc_push_long(0); /* WB2A */ + exc_push_long(regs.wb3_data); /* WB3D */ + exc_push_long(regs.mmu_fault_addr); /* WB3A */ + exc_push_long(regs.mmu_fault_addr); + exc_push_word(0); /* WB1S */ + exc_push_word(0); /* WB2S */ + exc_push_word(regs.wb3_status); /* WB3S */ + regs.wb3_status = 0; + exc_push_word(regs.mmu_ssw); + exc_push_long(regs.mmu_fault_addr); /* EA */ + exc_make_frame(7, regs.sr, regs.fault_pc, 2, 0, 0); + } +#ifdef EXCEPTIONS_VIA_LONGJMP + else +#else + catch (m68k_exception) +#endif + { + report_double_bus_error(); +#ifdef EXCEPTIONS_VIA_LONGJMP + building_bus_fault_stack_frame= 0; +#endif + return; + } + +#ifdef EXCEPTIONS_VIA_LONGJMP + building_bus_fault_stack_frame= 0; +#endif + /* end of BUS ERROR handler */ + } else if (nr == 3) { + exc_make_frame(2, regs.sr, last_addr_for_exception_3, nr, + last_fault_for_exception_3 & 0xfffffffe, 0); + } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { + /* div by zero, CHK, TRAP or TRACE */ + exc_make_frame(2, regs.sr, currpc, nr, oldpc, 0); + } else if (regs.m && nr >= 24 && nr < 32) { + /* interrupts! */ + exc_make_frame(0, regs.sr, currpc, nr, 0, 0); + regs.sr |= (1 << 13); + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + + exc_make_frame(1, /* throwaway */ + regs.sr, currpc, nr, 0, 0); } else { - if (nr == 2 || nr == 3) { - m68k_areg(regs, 7) -= 12; - /* ??????? */ - if (nr == 3) { - put_long (m68k_areg(regs, 7), last_fault_for_exception_3); - put_word (m68k_areg(regs, 7)+4, last_op_for_exception_3); - put_long (m68k_areg(regs, 7)+8, last_addr_for_exception_3); - } - write_log ("Exception!\n"); - goto kludge_me_do; - } + exc_make_frame(0, regs.sr, currpc, nr, 0, 0); } - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), m68k_getpc ()); -kludge_me_do: - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), regs.sr); m68k_setpc (get_long (regs.vbr + 4*nr)); + SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); fill_prefetch_0 (); regs.t1 = regs.t0 = regs.m = 0; - regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + SPCFLAGS_CLEAR(SPCFLAG_TRACE | SPCFLAG_DOTRACE); } static void Interrupt(int nr) @@ -716,62 +602,90 @@ static void Interrupt(int nr) Exception(nr+24, 0); regs.intmask = nr; - regs.spcflags |= SPCFLAG_INT; + SPCFLAGS_SET( SPCFLAG_INT ); } -static int caar, cacr, tc, itt0, itt1, dtt0, dtt1; - -void m68k_move2c (int regno, uae_u32 *regp) +static void SCCInterrupt(int nr) +{ + // fprintf(stderr, "CPU: in SCCInterrupt\n"); + lastint_regs = regs; + lastint_no = 5;// ex 5 + Exception(nr, 0); + + regs.intmask = 5;// ex 5 +} + +static void MFPInterrupt(int nr) +{ + // fprintf(stderr, "CPU: in MFPInterrupt\n"); + lastint_regs = regs; + lastint_no = 6; + Exception(nr, 0); + + regs.intmask = 6; +} + +int m68k_move2c (int regno, uae_u32 *regp) { - if (CPUType == 1 && (regno & 0x7FF) > 1) - op_illg (0x4E7B); - else switch (regno) { case 0: regs.sfc = *regp & 7; break; case 1: regs.dfc = *regp & 7; break; - case 2: cacr = *regp & 0x3; break; /* ignore C and CE */ - case 3: tc = *regp & 0xc000; break; - case 4: itt0 = *regp & 0xffffe364; break; - case 5: itt1 = *regp & 0xffffe364; break; - case 6: dtt0 = *regp & 0xffffe364; break; - case 7: dtt1 = *regp & 0xffffe364; break; + case 2: regs.cacr = *regp & 0x80008000; +#ifdef USE_JIT + set_cache_state(regs.cacr & 0x8000); + if (*regp & 0x08) { /* Just to be on the safe side */ + flush_icache(2); + } +#endif + break; + case 3: mmu_set_tc(*regp & 0xc000); break; + case 4: + case 5: + case 6: + case 7: mmu_set_ttr(regno, *regp & 0xffffe364); break; case 0x800: regs.usp = *regp; break; case 0x801: regs.vbr = *regp; break; - case 0x802: caar = *regp &0xfc; break; + case 0x802: regs.caar = *regp & 0xfc; break; case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; + case 0x805: mmu_set_mmusr(*regp); break; + case 0x806: regs.urp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; + case 0x807: regs.srp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; default: op_illg (0x4E7B); - break; + return 0; } + return 1; } -void m68k_movec2 (int regno, uae_u32 *regp) +int m68k_movec2 (int regno, uae_u32 *regp) { - if (CPUType == 1 && (regno & 0x7FF) > 1) - op_illg (0x4E7A); - else switch (regno) { case 0: *regp = regs.sfc; break; case 1: *regp = regs.dfc; break; - case 2: *regp = cacr; break; - case 3: *regp = tc; break; - case 4: *regp = itt0; break; - case 5: *regp = itt1; break; - case 6: *regp = dtt0; break; - case 7: *regp = dtt1; break; + case 2: *regp = regs.cacr; break; + case 3: *regp = regs.tc; break; + case 4: *regp = regs.itt0; break; + case 5: *regp = regs.itt1; break; + case 6: *regp = regs.dtt0; break; + case 7: *regp = regs.dtt1; break; case 0x800: *regp = regs.usp; break; case 0x801: *regp = regs.vbr; break; - case 0x802: *regp = caar; break; + case 0x802: *regp = regs.caar; break; case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; + case 0x805: *regp = regs.mmusr; break; + case 0x806: *regp = regs.urp; break; + case 0x807: *regp = regs.srp; break; default: op_illg (0x4E7A); - break; + return 0; } + return 1; } -static __inline__ int +#if !defined(uae_s64) +static inline int div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem) { uae_u32 q = 0, cbit = 0; @@ -795,8 +709,9 @@ div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem = src_hi; return 0; } +#endif -void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) +void m68k_divl (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra, uaecptr oldpc) { #if defined(uae_s64) if (src == 0) { @@ -917,7 +832,8 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) #endif } -static __inline__ void +#if !defined(uae_s64) +static inline void mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) { uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff); @@ -935,8 +851,9 @@ mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) *dst_lo = lo; *dst_hi = r3; } +#endif -void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra) +void m68k_mull (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra) { #if defined(uae_s64) if (extra & 0x800) { @@ -1022,16 +939,16 @@ void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra) } #endif } -static char* ccnames[] = -{ "T ","F ","HI","LS","CC","CS","NE","EQ", - "VC","VS","PL","MI","GE","LT","GT","LE" }; + +// If value is greater than zero, this means we are still processing an EmulOp +// because the counter is incremented only in m68k_execute(), i.e. interpretive +// execution only +#ifdef USE_JIT +static int m68k_execute_depth = 0; +#endif void m68k_reset (void) { - m68k_areg (regs, 7) = 0x2000; - m68k_setpc (ROMBaseMac + 0x2a); - fill_prefetch_0 (); - regs.kick_mask = 0xF80000; regs.s = 1; regs.m = 0; regs.stopped = 0; @@ -1042,76 +959,242 @@ void m68k_reset (void) SET_CFLG (0); SET_VFLG (0); SET_NFLG (0); - regs.spcflags = 0; + SPCFLAGS_INIT( 0 ); regs.intmask = 7; regs.vbr = regs.sfc = regs.dfc = 0; - regs.fpcr = regs.fpsr = regs.fpiar = 0; + + // need to ensure the following order of initialization is correct + // (it is definitely better than what it was before this commit + // since it was reading from 0x00000000 in User mode and with active MMU) + mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */ + m68k_areg (regs, 7) = phys_get_long(0x00000000); + m68k_setpc (phys_get_long(0x00000004)); + fill_prefetch_0 (); + + /* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init() + regs.fpcr = regs.fpsr = regs.fpiar = 0; */ + fpu_reset(); + // MMU + mmu_reset(); + mmu_set_super(1); + // Cache + regs.cacr = 0; + regs.caar = 0; +#ifdef FLIGHT_RECORDER + log_ptr = 0; + memset(frlog, 0, sizeof(frlog)); +#endif +} + +void m68k_emulop_return(void) +{ + SPCFLAGS_SET( SPCFLAG_BRK ); + quit_program = 1; +} + +static void save_regs(struct M68kRegisters &r) +{ + int i; + + for (i=0; i<8; i++) { + r.d[i] = m68k_dreg(regs, i); + r.a[i] = m68k_areg(regs, i); + } + r.pc = m68k_getpc(); + MakeSR(); + r.sr = regs.sr; + r.isp = regs.isp; + r.usp = regs.usp; + r.msp = regs.msp; + if ((r.sr & 0x2000) == 0) + r.usp = r.a[7]; + else if ((r.sr & 0x1000) != 0) + r.msp = r.a[7]; + else + r.isp = r.a[7]; +} + +static void restore_regs(struct M68kRegisters &r) +{ + int i; + + for (i=0; i<8; i++) { + m68k_dreg(regs, i) = r.d[i]; + m68k_areg(regs, i) = r.a[i]; + } + regs.isp = r.isp; + regs.usp = r.usp; + regs.msp = r.msp; + regs.sr = r.sr; + MakeFromSR(); +} + +void m68k_emulop(uae_u32 opcode) +{ + struct M68kRegisters r; + save_regs(r); + EmulOp(opcode, &r); + restore_regs(r); +} + +// void m68k_natfeat_id(void) +// { +// struct M68kRegisters r; + +// /* is it really necessary to save all registers? */ +// save_regs(r); + +// memptr stack = r.a[7] + 4; /* skip return address */ +// r.d[0] = nf_get_id(stack); + +// restore_regs(r); +// } + +// void m68k_natfeat_call(void) +// { +// struct M68kRegisters r; + +// /* is it really necessary to save all registers? */ +// save_regs(r); + +// memptr stack = r.a[7] + 4; /* skip return address */ +// bool isSupervisorMode = ((r.sr & 0x2000) == 0x2000); +// r.d[0] = nf_call(stack, isSupervisorMode); + +// restore_regs(r); +// } + +static int m68k_call(uae_u32 pc) +{ + VOLATILE int exc = 0; + m68k_setpc(pc); + TRY(prb) { +#ifdef USE_JIT + if (bx_options.jit.jit) { + exec_nostats(); + // m68k_do_compile_execute(); + // The above call to m68k_do_compile_execute fails with BadAccess in sigsegv_handler (MAC, if it is executed after the first compile_block) + // (NULL pointer to addr_instr). + // Call exec_nostats avoids calling compile_block, because stack modification is only temporary + // which will fill up compile cache with BOGUS data. + // we can call exec_nostats directly, do our code, and return back here. + } + else +#endif + m68k_do_execute(); + } + CATCH(prb) { + exc = int(prb); + } + return exc; +} + +static uae_u32 m68k_alloca(int size) +{ + uae_u32 sp = (m68k_areg(regs, 7) - size) & ~1; + m68k_areg(regs, 7) = sp; + if ((regs.sr & 0x2000) == 0) + regs.usp = sp; + else if ((regs.sr & 0x1000) != 0) + regs.msp = sp; + else + regs.isp = sp; + return sp; +} + +// uae_u32 linea68000(volatile uae_u16 opcode) +// { +// sigjmp_buf jmp; +// struct M68kRegisters r; +// volatile uae_u32 abase = 0; + +// SAVE_EXCEPTION; +// save_regs(r); + +// const int sz = 8 + sizeof(void *); +// volatile uae_u32 sp = 0; +// uae_u32 backup[(sz + 3) / 4]; + +// if (sigsetjmp(jmp, 1) == 0) +// { +// void *p = jmp; +// uae_u8 *sp_p; +// int exc; + +// sp = m68k_alloca(sz); +// memcpy(backup, phys_get_real_address(sp), sz); + +// WriteHWMemInt16(sp, opcode); +// WriteHWMemInt16(sp + 2, 0xa0ff); +// WriteHWMemInt32(sp + 4, 13); +// sp_p = phys_get_real_address(sp + 8); +// *((void **)sp_p) = p; +// if ((exc = m68k_call(sp)) != 0) +// { +// panicbug("exception %d in LINEA", exc); +// m68k_dreg(regs, 0) = 0; +// } +// } else +// { +// abase = m68k_dreg(regs, 0); +// } + +// if (sp) { +// memcpy(phys_get_real_address(sp), backup, sz); +// } +// restore_regs(r); +// m68k_setpc(r.pc); +// RESTORE_EXCEPTION; +// return abase; +// } + + +static void rts68000() +{ + uae_u32 SP = m68k_getpc() + 6; + sigjmp_buf *p; + uae_u8 *sp_p = phys_get_real_address(SP); + + p = (sigjmp_buf *)(*((void **)sp_p)); + SP += sizeof(void *); + m68k_areg(regs, 7) = SP; + siglongjmp(*p, 1); } void REGPARAM2 op_illg (uae_u32 opcode) { - uaecptr pc = m68k_getpc (); + uaecptr pc = m68k_getpc (); - - if ((opcode & 0xFF00) == 0x7100) { - struct M68kRegisters r; - int i; - - // Return from Execute68k()? - if (opcode == M68K_EXEC_RETURN) { - regs.spcflags |= SPCFLAG_BRK; - quit_program = 1; - return; - } - - // Call EMUL_OP opcode - for (i=0; i<8; i++) { - r.d[i] = m68k_dreg(regs, i); - r.a[i] = m68k_areg(regs, i); - } - MakeSR(); - r.sr = regs.sr; - EmulOp(opcode, &r); - for (i=0; i<8; i++) { - m68k_dreg(regs, i) = r.d[i]; - m68k_areg(regs, i) = r.a[i]; - } - regs.sr = r.sr; - MakeFromSR(); - m68k_incpc(2); - fill_prefetch_0 (); + if ((opcode & 0xF000) == 0xA000) { + // if (opcode == 0xa0ff) + // { + // uae_u32 call = ReadHWMemInt32(pc + 2); + // switch (call) + // { + // case 13: + // rts68000(); + // return; + // } + // m68k_setpc(pc + 6); + // } + Exception(0xA,0); return; } - if ((opcode & 0xF000) == 0xA000) { - Exception(0xA,0); + if ((opcode & 0xF000) == 0xF000) { + Exception(0xB,0); + return; + } + + D(bug("Illegal instruction: %04x at %08x", opcode, pc)); +#if defined(USE_JIT) && defined(JIT_DEBUG) + compiler_dumpstate(); +#endif + + Exception (4,0); return; - } - -// write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); - - if ((opcode & 0xF000) == 0xF000) { - Exception(0xB,0); - return; - } - - write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); - - Exception (4,0); } -void mmu_op(uae_u32 opcode, uae_u16 extra) -{ - if ((extra & 0xB000) == 0) { /* PMOVE instruction */ - - } else if ((extra & 0xF000) == 0x2000) { /* PLOAD instruction */ - } else if ((extra & 0xF000) == 0x8000) { /* PTEST instruction */ - } else - op_illg (opcode); -} - -static int n_insns = 0, n_spcinsns = 0; - static uaecptr last_trace_ad = 0; static void do_trace (void) @@ -1123,7 +1206,7 @@ static void do_trace (void) /* We can afford this to be inefficient... */ m68k_setpc (m68k_getpc ()); fill_prefetch_0 (); - opcode = get_word (regs.pc); + opcode = get_word(m68k_getpc()); if (opcode == 0x4e72 /* RTE */ || opcode == 0x4e74 /* RTD */ || opcode == 0x4e75 /* RTS */ @@ -1139,216 +1222,362 @@ static void do_trace (void) && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) { last_trace_ad = m68k_getpc (); - regs.spcflags &= ~SPCFLAG_TRACE; - regs.spcflags |= SPCFLAG_DOTRACE; + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } } else if (regs.t1) { last_trace_ad = m68k_getpc (); - regs.spcflags &= ~SPCFLAG_TRACE; - regs.spcflags |= SPCFLAG_DOTRACE; + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } } +// #define SERVE_VBL_MFP(resetStop) \ +// { \ +// if (SPCFLAGS_TEST( SPCFLAG_INT3|SPCFLAG_VBL|SPCFLAG_INT5|SPCFLAG_SCC|SPCFLAG_MFP )) { \ +// if (SPCFLAGS_TEST( SPCFLAG_INT3 )) { \ +// if (3 > regs.intmask) { \ +// Interrupt(3); \ +// regs.stopped = 0; \ +// SPCFLAGS_CLEAR( SPCFLAG_INT3 ); \ +// if (resetStop) \ +// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ +// } \ +// } \ +// if (SPCFLAGS_TEST( SPCFLAG_VBL )) { \ +// if (4 > regs.intmask) { \ +// Interrupt(4); \ +// regs.stopped = 0; \ +// SPCFLAGS_CLEAR( SPCFLAG_VBL ); \ +// if (resetStop) \ +// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ +// } \ +// } \ +// if (SPCFLAGS_TEST( SPCFLAG_INT5 )) { \ +// if (5 > regs.intmask) { \ +// Interrupt(5); \ +// regs.stopped = 0; \ +// SPCFLAGS_CLEAR( SPCFLAG_INT5 ); \ +// if (resetStop) \ +// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ +// } \ +// } \ +// if (SPCFLAGS_TEST( SPCFLAG_SCC )) { \ +// if (5 > regs.intmask) { \ +// int vector_number=SCCdoInterrupt(); \ +// if(vector_number){ \ +// SCCInterrupt(vector_number); \ +// regs.stopped = 0; \ +// SPCFLAGS_CLEAR( SPCFLAG_SCC); \ +// if (resetStop) \ +// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ +// } \ +// else \ +// SPCFLAGS_CLEAR( SPCFLAG_SCC ); \ +// } \ +// } \ +// if (SPCFLAGS_TEST( SPCFLAG_MFP )) { \ +// if (6 > regs.intmask) { \ +// int vector_number = MFPdoInterrupt(); \ +// if (vector_number) { \ +// MFPInterrupt(vector_number); \ +// regs.stopped = 0; \ +// if (resetStop) \ +// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ +// } \ +// else \ +// SPCFLAGS_CLEAR( SPCFLAG_MFP ); \ +// } \ +// } \ +// } \ +// } -static int do_specialties (void) +// #define SERVE_INTERNAL_IRQ() \ +// { \ +// if (SPCFLAGS_TEST( SPCFLAG_INTERNAL_IRQ )) { \ +// SPCFLAGS_CLEAR( SPCFLAG_INTERNAL_IRQ ); \ +// invoke200HzInterrupt(); \ +// } \ +// } + +int m68k_do_specialties(void) { - /*n_spcinsns++;*/ - if (regs.spcflags & SPCFLAG_DOTRACE) { - Exception (9,last_trace_ad); - } - while (regs.spcflags & SPCFLAG_STOP) { - if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ - int intr = intlev (); - regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); - if (intr != -1 && intr > regs.intmask) { - Interrupt (intr); - regs.stopped = 0; - regs.spcflags &= ~SPCFLAG_STOP; - } - } - } - if (regs.spcflags & SPCFLAG_TRACE) - do_trace (); + // SERVE_INTERNAL_IRQ(); +#ifdef USE_JIT + // Block was compiled + SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE ); - if (regs.spcflags & SPCFLAG_DOINT) { - int intr = intlev (); - regs.spcflags &= ~SPCFLAG_DOINT; - if (intr != -1 && intr > regs.intmask) { - Interrupt (intr); - regs.stopped = 0; + // Retain the request to get out of compiled code until + // we reached the toplevel execution, i.e. the one that + // can compile then run compiled code. This also means + // we processed all (nested) EmulOps + if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN )) + SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN ); +#endif + /*n_spcinsns++;*/ + if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { + Exception (9,last_trace_ad); } - } - if (regs.spcflags & SPCFLAG_INT) { - regs.spcflags &= ~SPCFLAG_INT; - regs.spcflags |= SPCFLAG_DOINT; - } - if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { - regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); - return 1; - } - return 0; -} +#if 0 /* not for ARAnyM; emulating 040 only */ + if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) { + // 68000/68010 undocumented special case: + // if STOP clears S-bit and T was not set: + // cause privilege violation exception, PC pointing to following instruction. + // If T was set before STOP: STOP works as documented. + m68k_unset_stop(); + Exception(8, 0); + } +#endif + while (SPCFLAGS_TEST( SPCFLAG_STOP )) { + //TODO: Check + if ((regs.sr & 0x700) == 0x700) + { + // panicbug("STOPed with interrupts disabled, exiting; pc=$%08x", m68k_getpc()); + m68k_dumpstate (stderr, NULL); +#if 0 + quit_program = 1; +#endif +#ifdef FULL_HISTORY + ndebug::showHistory(20, false); + m68k_dumpstate (stderr, NULL); +#endif + return 1; + } + if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ + SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); + int intr = intlev (); + if (intr != -1 && intr > regs.intmask) { + Interrupt (intr); + regs.stopped = 0; + SPCFLAGS_CLEAR( SPCFLAG_STOP ); + } + } -static void m68k_run_1 (void) -{ - for (;;) { - uae_u32 opcode = GET_OPCODE; - (*cpufunctbl[opcode])(opcode); - if (regs.spcflags) { - if (do_specialties()) - return; + // SERVE_INTERNAL_IRQ(); + // SERVE_VBL_MFP(true); + if (SPCFLAGS_TEST( SPCFLAG_BRK )) + break; + } + if (SPCFLAGS_TEST( SPCFLAG_TRACE )) + do_trace (); + + // SERVE_VBL_MFP(false); + + if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { + SPCFLAGS_CLEAR( SPCFLAG_DOINT ); + int intr = intlev (); + if (intr != -1 && intr > regs.intmask) { + Interrupt (intr); + regs.stopped = 0; } } + + if (SPCFLAGS_TEST( SPCFLAG_INT )) { + SPCFLAGS_CLEAR( SPCFLAG_INT ); + SPCFLAGS_SET( SPCFLAG_DOINT ); + } + + if (SPCFLAGS_TEST( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ )) { + SPCFLAGS_CLEAR( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ ); + return 1; + } + + return 0; } -#define m68k_run1 m68k_run_1 - -int in_m68k_go = 0; - -void m68k_go (int may_quit) +void m68k_do_execute (void) { -// m68k_go() must be reentrant for Execute68k() and Execute68kTrap() to work -/* - if (in_m68k_go || !may_quit) { - write_log("Bug! m68k_go is not reentrant.\n"); - abort(); - } -*/ - in_m68k_go++; + uae_u32 pc; + uae_u32 opcode; for (;;) { - if (quit_program > 0) { - if (quit_program == 1) - break; - quit_program = 0; - m68k_reset (); + regs.fault_pc = pc = m68k_getpc(); +#ifdef FULL_HISTORY +#ifdef NEED_TO_DEBUG_BADLY + history[lasthist] = regs; + historyf[lasthist] = regflags; +#else + history[lasthist] = m68k_getpc(); +#endif + if (++lasthist == MAX_HIST) lasthist = 0; + if (lasthist == firsthist) { + if (++firsthist == MAX_HIST) firsthist = 0; } - m68k_run1(); - } - if (debugging) { - uaecptr nextpc; - m68k_dumpstate(&nextpc); - exit(1); +#endif + +#ifndef FULLMMU +#ifdef ARAM_PAGE_CHECK + if (((pc ^ pc_page) > ARAM_PAGE_MASK)) { + check_ram_boundary(pc, 2, false); + pc_page = pc; + pc_offset = (uintptr)get_real_address(pc, 0, sz_word) - pc; } - in_m68k_go--; -} +#else + check_ram_boundary(pc, 2, false); +#endif +#endif + opcode = GET_OPCODE; +#ifdef FLIGHT_RECORDER + m68k_record_step(m68k_getpc(), opcode); +#endif + (*cpufunctbl[opcode])(opcode); + cpu_check_ticks(); + regs.fault_pc = m68k_getpc(); -static void m68k_verify (uaecptr addr, uaecptr *nextpc) -{ - uae_u32 opcode, val; - struct instr *dp; - - opcode = get_iword_1(0); - last_op_for_exception_3 = opcode; - m68kpc_offset = 2; - - if (cpufunctbl[cft_map (opcode)] == op_illg_1) { - opcode = 0x4AFC; - } - dp = table68k + opcode; - - if (dp->suse) { - if (!verify_ea (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, &val)) { - Exception (3, 0); - return; - } - } - if (dp->duse) { - if (!verify_ea (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, &val)) { - Exception (3, 0); - return; + if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { + if (m68k_do_specialties()) + return; } } } -void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt) +void m68k_execute (void) { - uaecptr newpc = 0; - m68kpc_offset = addr - m68k_getpc (); +#ifdef USE_JIT + m68k_execute_depth++; +#endif +#ifdef DEBUGGER + VOLATILE bool after_exception = false; +#endif + +setjmpagain: + TRY(prb) { + for (;;) { + if (quit_program > 0) { + if (quit_program == 1) { +#ifdef FLIGHT_RECORDER + dump_flight_recorder(); +#endif + break; + } + quit_program = 0; + m68k_reset (); + } +#ifdef DEBUGGER + if (debugging && !after_exception) debug(); + after_exception = false; +#endif + m68k_do_execute(); + } + } + CATCH(prb) { + Exception(prb, 0); +#ifdef DEBUGGER + after_exception = true; +#endif + goto setjmpagain; + } + +#ifdef USE_JIT + m68k_execute_depth--; +#endif +} + +void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) +{ +#ifdef HAVE_DISASM_M68K + char buf[256]; + int size; + + disasm_info.memory_vma = addr; while (cnt-- > 0) { - char instrname[20],*ccpt; - int opwords; - uae_u32 opcode; - struct mnemolookup *lookup; - struct instr *dp; - printf ("%08lx: ", m68k_getpc () + m68kpc_offset); - for (opwords = 0; opwords < 5; opwords++){ - printf ("%04x ", get_iword_1 (m68kpc_offset + opwords*2)); + size = m68k_disasm_to_buf(&disasm_info, buf); + fprintf(f, "%s\n", buf); + if (size < 0) + break; } - opcode = get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - if (cpufunctbl[cft_map (opcode)] == op_illg_1) { - opcode = 0x4AFC; - } - dp = table68k + opcode; - for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) - ; + if (nextpc) + *nextpc = disasm_info.memory_vma; +#else + if (nextpc) + *nextpc = addr; + (void) f; + (void) cnt; +#endif +} - strcpy (instrname, lookup->name); - ccpt = strstr (instrname, "cc"); - if (ccpt != 0) { - strncpy (ccpt, ccnames[dp->cc], 2); - } - printf ("%s", instrname); - switch (dp->size){ - case sz_byte: printf (".B "); break; - case sz_word: printf (".W "); break; - case sz_long: printf (".L "); break; - default: printf (" "); break; - } +#ifdef DEBUGGER +void newm68k_disasm(FILE *f, uaecptr addr, uaecptr *nextpc, unsigned int cnt) +{ +#ifdef HAVE_DISASM_M68K + char buf[256]; - if (dp->suse) { - newpc = m68k_getpc () + m68kpc_offset; - newpc += ShowEA (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); - } - if (dp->suse && dp->duse) - printf (","); - if (dp->duse) { - newpc = m68k_getpc () + m68kpc_offset; - newpc += ShowEA (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 0); - } - if (ccpt != 0) { - if (cctrue(dp->cc)) - printf (" == %08lx (TRUE)", newpc); - else - printf (" == %08lx (FALSE)", newpc); - } else if ((opcode & 0xff00) == 0x6100) /* BSR */ - printf (" == %08lx", newpc); - printf ("\n"); + disasm_info.memory_vma = addr; + if (cnt == 0) { + m68k_disasm_to_buf(&disasm_info, buf); + } else { + while (cnt-- > 0) { + m68k_disasm_to_buf(&disasm_info, buf); + fprintf(f, "%s\n", buf); + } } if (nextpc) - *nextpc = m68k_getpc () + m68kpc_offset; + *nextpc = disasm_info.memory_vma; +#else + if (nextpc) + *nextpc = addr; + (void) cnt; +#endif } -void m68k_dumpstate (uaecptr *nextpc) +#endif /* DEBUGGER */ + +#ifdef FULL_HISTORY +void showDisasm(uaecptr addr) { +#ifdef HAVE_DISASM_M68K + char buf[256]; + + disasm_info.memory_vma = addr; + m68k_disasm_to_buf(&disasm_info, buf); + bug("%s", buf); +#else + (void) addr; +#endif +} +#endif /* FULL_HISTORY */ + +void m68k_dumpstate (FILE *out, uaecptr *nextpc) { int i; for (i = 0; i < 8; i++){ - printf ("D%d: %08lx ", i, m68k_dreg(regs, i)); - if ((i & 3) == 3) printf ("\n"); + fprintf (out, "D%d: %08lx ", i, (unsigned long)m68k_dreg(regs, i)); + if ((i & 3) == 3) fprintf (out, "\n"); } for (i = 0; i < 8; i++){ - printf ("A%d: %08lx ", i, m68k_areg(regs, i)); - if ((i & 3) == 3) printf ("\n"); + fprintf (out, "A%d: %08lx ", i, (unsigned long)m68k_areg(regs, i)); + if ((i & 3) == 3) fprintf (out, "\n"); } if (regs.s == 0) regs.usp = m68k_areg(regs, 7); if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); - printf ("USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", - regs.usp,regs.isp,regs.msp,regs.vbr); - printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n", + fprintf (out, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", + (unsigned long)regs.usp, (unsigned long)regs.isp, + (unsigned long)regs.msp, (unsigned long)regs.vbr); + fprintf (out, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d TCE=%d TCP=%d\n", regs.t1, regs.t0, regs.s, regs.m, - GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); + (int)GET_XFLG, (int)GET_NFLG, (int)GET_ZFLG, (int)GET_VFLG, (int)GET_CFLG, regs.intmask, + regs.mmu_enabled, regs.mmu_pagesize_8k); + fprintf (out, "CACR=%08lx CAAR=%08lx URP=%08lx SRP=%08lx\n", + (unsigned long)regs.cacr, + (unsigned long)regs.caar, + (unsigned long)regs.urp, + (unsigned long)regs.srp); + fprintf (out, "DTT0=%08lx DTT1=%08lx ITT0=%08lx ITT1=%08lx\n", + (unsigned long)regs.dtt0, + (unsigned long)regs.dtt1, + (unsigned long)regs.itt0, + (unsigned long)regs.itt1); for (i = 0; i < 8; i++){ - printf ("FP%d: %g ", i, regs.fp[i]); - if ((i & 3) == 3) printf ("\n"); + fprintf (out, "FP%d: %g ", i, (double)fpu.registers[i]); + if ((i & 3) == 3) fprintf (out, "\n"); } - printf ("N=%d Z=%d I=%d NAN=%d\n", +#if 0 + fprintf (out, "N=%d Z=%d I=%d NAN=%d\n", (regs.fpsr & 0x8000000) != 0, (regs.fpsr & 0x4000000) != 0, (regs.fpsr & 0x2000000) != 0, (regs.fpsr & 0x1000000) != 0); - - m68k_disasm(m68k_getpc (), nextpc, 1); +#endif + m68k_disasm(out, m68k_getpc (), nextpc, 1); if (nextpc) - printf ("next PC: %08lx\n", *nextpc); + fprintf (out, "next PC: %08lx\n", (unsigned long)*nextpc); } diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index dc174a78..13a51b82 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -1,3 +1,27 @@ +/* + * newcpu.h - CPU emulation + * + * Copyright (c) 2009 ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * @@ -6,41 +30,22 @@ * Copyright 1995 Bernd Schmidt */ -#define SPCFLAG_STOP 2 -#define SPCFLAG_DISK 4 -#define SPCFLAG_INT 8 -#define SPCFLAG_BRK 16 -#define SPCFLAG_EXTRA_CYCLES 32 -#define SPCFLAG_TRACE 64 -#define SPCFLAG_DOTRACE 128 -#define SPCFLAG_DOINT 256 -#define SPCFLAG_BLTNASTY 512 -#define SPCFLAG_EXEC 1024 -#define SPCFLAG_MODE_CHANGE 8192 +#ifndef NEWCPU_H +#define NEWCPU_H -#ifndef SET_CFLG +#include "sysdeps.h" +#include "registers.h" +#include "spcflags.h" +#include "m68k.h" +#include "memory.h" -#define SET_CFLG(x) (CFLG = (x)) -#define SET_NFLG(x) (NFLG = (x)) -#define SET_VFLG(x) (VFLG = (x)) -#define SET_ZFLG(x) (ZFLG = (x)) -#define SET_XFLG(x) (XFLG = (x)) +# include -#define GET_CFLG CFLG -#define GET_NFLG NFLG -#define GET_VFLG VFLG -#define GET_ZFLG ZFLG -#define GET_XFLG XFLG - -#define CLEAR_CZNV do { \ - SET_CFLG (0); \ - SET_ZFLG (0); \ - SET_NFLG (0); \ - SET_VFLG (0); \ -} while (0) - -#define COPY_CARRY (SET_XFLG (GET_CFLG)) -#endif +extern struct fixup { + int flag; + uae_u32 reg; + uaecptr value; +}fixup; extern int areg_byteinc[]; extern int imm8_table[]; @@ -49,112 +54,126 @@ extern int movem_index1[256]; extern int movem_index2[256]; extern int movem_next[256]; -extern int fpp_movem_index1[256]; -extern int fpp_movem_index2[256]; -extern int fpp_movem_next[256]; - extern int broken_in; +#ifdef X86_ASSEMBLY +/* This hack seems to force all register saves (pushl %reg) to be moved to the + begining of the function, thus making it possible to cpuopti to remove them + since m68k_run_1 will save those registers before calling the instruction + handler */ +# define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag ) +#else +# define cpuop_tag(tag) ; +#endif + +#define cpuop_begin() do { cpuop_tag("begin"); } while (0) +#define cpuop_end() do { cpuop_tag("end"); } while (0) + typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM; struct cputbl { cpuop_func *handler; - int specific; + uae_u16 specific; uae_u16 opcode; }; +extern cpuop_func *cpufunctbl[65536]; + +#ifdef USE_JIT +typedef void compop_func (uae_u32) REGPARAM; + +struct comptbl { + compop_func *handler; + uae_u32 opcode; + uae_u32 specific; +#define COMP_OPCODE_ISJUMP 0x0001 +#define COMP_OPCODE_LONG_OPCODE 0x0002 +#define COMP_OPCODE_CMOV 0x0004 +#define COMP_OPCODE_ISADDX 0x0008 +#define COMP_OPCODE_ISCJUMP 0x0010 +#define COMP_OPCODE_USES_FPU 0x0020 +}; +#endif + extern void REGPARAM2 op_illg (uae_u32) REGPARAM; -typedef char flagtype; - -extern struct regstruct -{ - uae_u32 regs[16]; - uaecptr usp,isp,msp; - uae_u16 sr; - flagtype t1; - flagtype t0; - flagtype s; - flagtype m; - flagtype x; - flagtype stopped; - int intmask; - - uae_u32 pc; - uae_u8 *pc_p; - uae_u8 *pc_oldp; - - uae_u32 vbr,sfc,dfc; - - double fp[8]; - uae_u32 fpcr,fpsr,fpiar; - - uae_u32 spcflags; - uae_u32 kick_mask; - - /* Fellow sources say this is 4 longwords. That's impossible. It needs - * to be at least a longword. The HRM has some cryptic comment about two - * instructions being on the same longword boundary. - * The way this is implemented now seems like a good compromise. - */ - uae_u32 prefetch; -} regs, lastint_regs; - #define m68k_dreg(r,num) ((r).regs[(num)]) #define m68k_areg(r,num) (((r).regs + 8)[(num)]) -#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1)) -#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o))) -#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o))) +#ifdef FULLMMU +static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o) +{ + return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte); +} +static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o) +{ + return mmu_get_word(m68k_getpc() + o, 0, sz_word); +} +static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o) +{ + uaecptr addr = m68k_getpc() + o; + + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_long_unaligned(addr, 0); + return mmu_get_long(addr, 0, sz_long); +} -#ifdef HAVE_GET_WORD_UNSWAPPED -#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p)) #else -#define GET_OPCODE (get_iword (0)) +#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1)) +#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o))) +#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o))) #endif -static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o) +#if 0 +static inline uae_u32 get_ibyte_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1)); + return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1)); return do_get_mem_byte((uae_u8 *)(((uae_u8 *)®s.prefetch) + o + 1)); } -static __inline__ uae_u32 get_iword_prefetch (uae_s32 o) +static inline uae_u32 get_iword_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_word((uae_u16 *)(regs.pc_p + o)); + return do_get_mem_word((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + o)); return do_get_mem_word((uae_u16 *)(((uae_u8 *)®s.prefetch) + o)); } -static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o) +static inline uae_u32 get_ilong_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_long((uae_u32 *)(regs.pc_p + o)); + return do_get_mem_long((uae_u32 *)(do_get_real_address(regs.pcp, false, false) + o)); if (o == 0) return do_get_mem_long(®s.prefetch); - return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4)); + return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + 4)); } +#endif +#ifdef FULLMMU +#define m68k_incpc(o) (regs.pc += (o)) +#else #define m68k_incpc(o) (regs.pc_p += (o)) +#endif -static __inline__ void fill_prefetch_0 (void) +static inline void fill_prefetch_0 (void) { +#if USE_PREFETCH_BUFFER uae_u32 r; #ifdef UNALIGNED_PROFITABLE - r = *(uae_u32 *)regs.pc_p; + r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false); regs.prefetch = r; #else - r = do_get_mem_long ((uae_u32 *)regs.pc_p); + r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false)); do_put_mem_long (®s.prefetch, r); #endif +#endif } #if 0 -static __inline__ void fill_prefetch_2 (void) +static inline void fill_prefetch_2 (void) { uae_u32 r = do_get_mem_long (®s.prefetch) << 16; - uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1); + uae_u32 r2 = do_get_mem_word (((uae_u16 *)do_get_real_address(regs.pcp, false, false)) + 1); r |= r2; do_put_mem_long (®s.prefetch, r); } @@ -164,103 +183,114 @@ static __inline__ void fill_prefetch_2 (void) /* These are only used by the 68020/68881 code, and therefore don't * need to handle prefetch. */ -static __inline__ uae_u32 next_ibyte (void) +static inline uae_u32 next_ibyte (void) { uae_u32 r = get_ibyte (0); m68k_incpc (2); return r; } -static __inline__ uae_u32 next_iword (void) +static inline uae_u32 next_iword (void) { uae_u32 r = get_iword (0); m68k_incpc (2); return r; } -static __inline__ uae_u32 next_ilong (void) +static inline uae_u32 next_ilong (void) { uae_u32 r = get_ilong (0); m68k_incpc (4); return r; } -static __inline__ void m68k_setpc (uaecptr newpc) +static inline void m68k_setpc (uaecptr newpc) { - regs.pc_p = regs.pc_oldp = get_real_address(newpc); - regs.pc = newpc; -} - -static __inline__ uaecptr m68k_getpc (void) -{ - return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); -} - -static __inline__ uaecptr m68k_getpc_p (uae_u8 *p) -{ - return regs.pc + ((char *)p - (char *)regs.pc_oldp); -} - -static __inline__ void m68k_do_rts(void) -{ - m68k_setpc(get_long(m68k_areg(regs, 7))); - m68k_areg(regs, 7) += 4; -} - -static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) -{ - m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); - m68k_incpc(offset); -} - -static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest) -{ - m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); - m68k_setpc(dest); +#ifndef FULLMMU + regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word); +#endif + regs.fault_pc = regs.pc = newpc; } #define m68k_setpc_fast m68k_setpc #define m68k_setpc_bcc m68k_setpc #define m68k_setpc_rte m68k_setpc -static __inline__ void m68k_setstopped (int stop) +static inline void m68k_do_rts(void) { - regs.stopped = stop; - if (stop) - regs.spcflags |= SPCFLAG_STOP; + m68k_setpc(get_long(m68k_areg(regs, 7))); + m68k_areg(regs, 7) += 4; +} + +static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) +{ + put_long(m68k_areg(regs, 7) - 4, oldpc); + m68k_areg(regs, 7) -= 4; + m68k_incpc(offset); +} + +static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest) +{ + put_long(m68k_areg(regs, 7) - 4, oldpc); + m68k_areg(regs, 7) -= 4; + m68k_setpc(dest); } -extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); -extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); +static inline void m68k_setstopped (int stop) +{ + regs.stopped = stop; + /* A traced STOP instruction drops through immediately without + actually stopping. */ + if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE ))) + SPCFLAGS_SET( SPCFLAG_STOP ); +} + +#ifdef FULLMMU +# define GET_OPCODE (get_iword (0)) +#elif defined ARAM_PAGE_CHECK +# ifdef HAVE_GET_WORD_UNSWAPPED +# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset))); +# else +# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset))); +# endif +#else +# ifdef HAVE_GET_WORD_UNSWAPPED +# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word))) +# else +# define GET_OPCODE (get_iword (0)) +# endif +#endif + +extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); +extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); +extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width); +extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width); + -extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf); extern void MakeSR (void); extern void MakeFromSR (void); extern void Exception (int, uaecptr); extern void dump_counts (void); -extern void m68k_move2c (int, uae_u32 *); -extern void m68k_movec2 (int, uae_u32 *); +extern int m68k_move2c (int, uae_u32 *); +extern int m68k_movec2 (int, uae_u32 *); extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); extern void m68k_mull (uae_u32, uae_u32, uae_u16); +extern void m68k_emulop (uae_u32); +extern void m68k_emulop_return (void); +extern void m68k_natfeat_id(void); +extern void m68k_natfeat_call(void); extern void init_m68k (void); -extern void m68k_go (int); -extern void m68k_dumpstate (uaecptr *); -extern void m68k_disasm (uaecptr, uaecptr *, int); +extern void exit_m68k (void); +extern void m68k_dumpstate (FILE *, uaecptr *); +extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int); +extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int); +extern void showDisasm(uaecptr); extern void m68k_reset (void); extern void m68k_enter_debugger(void); - -extern void mmu_op (uae_u32, uae_u16); - -extern void fpp_opp (uae_u32, uae_u16); -extern void fdbcc_opp (uae_u32, uae_u16); -extern void fscc_opp (uae_u32, uae_u16); -extern void ftrapcc_opp (uae_u32,uaecptr); -extern void fbcc_opp (uae_u32, uaecptr, uae_u32); -extern void fsave_opp (uae_u32); -extern void frestore_opp (uae_u32); +extern int m68k_do_specialties(void); +extern void m68k_instr_set(void); +uae_u32 linea68000(uae_u16 opcode); /* Opcode of faulting instruction */ extern uae_u16 last_op_for_exception_3; @@ -271,16 +301,34 @@ extern uaecptr last_fault_for_exception_3; #define CPU_OP_NAME(a) op ## a -/* 68020 + 68881 */ -extern struct cputbl op_smalltbl_0[]; -/* 68020 */ -extern struct cputbl op_smalltbl_1[]; -/* 68010 */ -extern struct cputbl op_smalltbl_2[]; -/* 68000 */ -extern struct cputbl op_smalltbl_3[]; -/* 68000 slow but compatible. */ -extern struct cputbl op_smalltbl_4[]; +/* 68040+ 68881 */ +extern const struct cputbl op_smalltbl_0_ff[]; +extern const struct cputbl op_smalltbl_0_nf[]; -extern cpuop_func *cpufunctbl[65536]; +#ifdef FLIGHT_RECORDER +extern void m68k_record_step(uaecptr, int); +#endif +extern void m68k_do_execute(void); +extern void m68k_execute(void); +#ifdef USE_JIT +extern void m68k_compile_execute(void); +extern void m68k_do_compile_execute(void); +#endif +#ifdef USE_CPU_EMUL_SERVICES +extern int32 emulated_ticks; +extern void cpu_do_check_ticks(void); + +static inline void cpu_check_ticks(void) +{ + if (--emulated_ticks <= 0) + cpu_do_check_ticks(); +} +#else +#define cpu_check_ticks() +#define cpu_do_check_ticks() +#endif + +cpuop_func op_illg_1; + +#endif /* NEWCPU_H */ diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h new file mode 100644 index 00000000..d680b200 --- /dev/null +++ b/BasiliskII/src/uae_cpu/noflags.h @@ -0,0 +1,142 @@ +#ifndef NOFLAGS_H +#define NOFLAGS_H + +/* Undefine everything that will *set* flags. Note: Leave *reading* + flags alone ;-). We assume that nobody does something like + SET_ZFLG(a=b+c), i.e. expect side effects of the macros. That would + be a stupid thing to do when using macros. +*/ + +/* Gwenole Beauchesne pointed out that CAS and CAS2 use flag_cmp to set + flags that are then used internally, and that thus the noflags versions + of those instructions were broken. Oops! + Easy fix: Leave flag_cmp alone. It is only used by CMP* and CAS* + instructions. For CAS*, noflags is a bad idea. For CMP*, which has + setting flags as its only function, the noflags version is kinda pointless, + anyway. + Note that this will only work while using the optflag_* routines --- + as we do on all (one ;-) platforms that will ever use the noflags + versions, anyway. + However, if you try to compile without optimized flags, the "SET_ZFLAG" + macro will be left unchanged, to make CAS and CAS2 work right. Of course, + this is contrary to the whole idea of noflags, but better be right than + be fast. + + Another problem exists with one of the bitfield operations. Once again, + one of the operations sets a flag, and looks at it later. And the CHK2 + instruction does so as well. For those, a different solution is possible. + the *_ALWAYS versions of the SET_?FLG macros shall remain untouched by + the redefinitions in this file. + Unfortunately, they are defined in terms of the macros we *do* redefine. + So here comes a bit of trickery.... +*/ +#define NOFLAGS_CMP 0 + +#undef SET_NFLG_ALWAYS +static inline void SET_NFLG_ALWAYS(uae_u32 x) +{ + SET_NFLG(x); /* This has not yet been redefined */ +} + +#undef SET_CFLG_ALWAYS +static inline void SET_CFLG_ALWAYS(uae_u32 x) +{ + SET_CFLG(x); /* This has not yet been redefined */ +} + +#undef CPUFUNC +#define CPUFUNC(x) x##_nf + +#ifndef OPTIMIZED_FLAGS +#undef SET_ZFLG +#define SET_ZFLG(y) do {uae_u32 dummy=(y); } while (0) +#endif + +#undef SET_CFLG +#define SET_CFLG(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_VFLG +#define SET_VFLG(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_NFLG +#define SET_NFLG(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_XFLG +#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0) + +#undef CLEAR_CZNV +#define CLEAR_CZNV +#undef IOR_CZNV +#define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_CZNV +#define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0) +#undef COPY_CARRY +#define COPY_CARRY + +#ifdef optflag_testl +#undef optflag_testl +#endif + +#ifdef optflag_testw +#undef optflag_testw +#endif + +#ifdef optflag_testb +#undef optflag_testb +#endif + +#ifdef optflag_addl +#undef optflag_addl +#endif + +#ifdef optflag_addw +#undef optflag_addw +#endif + +#ifdef optflag_addb +#undef optflag_addb +#endif + +#ifdef optflag_subl +#undef optflag_subl +#endif + +#ifdef optflag_subw +#undef optflag_subw +#endif + +#ifdef optflag_subb +#undef optflag_subb +#endif + +#if NOFLAGS_CMP +#ifdef optflag_cmpl +#undef optflag_cmpl +#endif + +#ifdef optflag_cmpw +#undef optflag_cmpw +#endif + +#ifdef optflag_cmpb +#undef optflag_cmpb +#endif +#endif + +#define optflag_testl(v) do { } while (0) +#define optflag_testw(v) do { } while (0) +#define optflag_testb(v) do { } while (0) + +#define optflag_addl(v, s, d) (v = (uae_s32)(d) + (uae_s32)(s)) +#define optflag_addw(v, s, d) (v = (uae_s16)(d) + (uae_s16)(s)) +#define optflag_addb(v, s, d) (v = (uae_s8)(d) + (uae_s8)(s)) + +#define optflag_subl(v, s, d) (v = (uae_s32)(d) - (uae_s32)(s)) +#define optflag_subw(v, s, d) (v = (uae_s16)(d) - (uae_s16)(s)) +#define optflag_subb(v, s, d) (v = (uae_s8)(d) - (uae_s8)(s)) + +#if NOFLAGS_CMP +/* These are just for completeness sake */ +#define optflag_cmpl(s, d) do { } while (0) +#define optflag_cmpw(s, d) do { } while (0) +#define optflag_cmpb(s, d) do { } while (0) +#endif + +#endif diff --git a/BasiliskII/src/uae_cpu/readcpu.cpp b/BasiliskII/src/uae_cpu/readcpu.cpp index abb3faae..1c385b98 100644 --- a/BasiliskII/src/uae_cpu/readcpu.cpp +++ b/BasiliskII/src/uae_cpu/readcpu.cpp @@ -1,3 +1,4 @@ +/* 2002 MJ */ /* * UAE - The Un*x Amiga Emulator * @@ -6,14 +7,21 @@ * Copyright 1995,1996 Bernd Schmidt */ -#include -#include -#include -#include - #include "sysdeps.h" #include "readcpu.h" +#include +#include +#include +#include + +using std::strncmp; +using std::abort; +using std::fprintf; +using std::strcmp; +using std::strlen; +using std::malloc; + int nr_cpuop_funcs; struct mnemolookup lookuptab[] = { @@ -139,13 +147,20 @@ struct mnemolookup lookuptab[] = { { i_CPUSHA, "CPUSHA" }, { i_MOVE16, "MOVE16" }, + { i_EMULOP_RETURN, "EMULOP_RETURN" }, + { i_EMULOP, "EMULOP" }, + { i_MMUOP, "MMUOP" }, + + {i_NATFEAT_ID, "NATFEAT_ID" }, + {i_NATFEAT_CALL, "NATFEAT_CALL" }, + { i_ILLG, "" }, }; struct instr *table68k; -static __inline__ amodes mode_from_str (const char *str) +static inline amodes mode_from_str (const char *str) { if (strncmp (str, "Dreg", 4) == 0) return Dreg; if (strncmp (str, "Areg", 4) == 0) return Areg; @@ -163,7 +178,7 @@ static __inline__ amodes mode_from_str (const char *str) return (amodes)0; } -static __inline__ amodes mode_from_mr (int mode, int reg) +static inline amodes mode_from_mr (int mode, int reg) { switch (mode) { case 0: return Dreg; @@ -195,12 +210,31 @@ static void build_insn (int insn) int variants; struct instr_def id; const char *opcstr; - int i; + int i, n; int flaglive = 0, flagdead = 0; + int cflow = 0; id = defs68k[insn]; + // Control flow information + cflow = id.cflow; + + // Mask of flags set/used + unsigned char flags_set(0), flags_used(0); + + for (i = 0, n = 4; i < 5; i++, n--) { + switch (id.flaginfo[i].flagset) { + case fa_unset: case fa_isjmp: break; + default: flags_set |= (1 << n); + } + + switch (id.flaginfo[i].flaguse) { + case fu_unused: case fu_isjmp: break; + default: flags_used |= (1 << n); + } + } + for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flagset){ case fa_unset: break; @@ -236,7 +270,7 @@ static void build_insn (int insn) int pos = 0; int mnp = 0; int bitno = 0; - char mnemonic[10]; + char mnemonic[64]; wordsizes sz = sz_long; int srcgather = 0, dstgather = 0; @@ -274,6 +308,9 @@ static void build_insn (int insn) if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) continue; + if (bitcnt[bitE] && (bitval[bitE] == 0x00)) + continue; + /* bitI and bitC get copied to biti and bitc */ if (bitcnt[bitI]) { bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI]; @@ -311,6 +348,11 @@ static void build_insn (int insn) } } mnp++; + if ((unsigned)mnp >= (sizeof(mnemonic)-1)) { + mnemonic[sizeof(mnemonic)-1] = '\0'; + fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic); + abort(); + } } pos++; } @@ -339,6 +381,7 @@ static void build_insn (int insn) case 'A': srcmode = Areg; switch (opcstr[pos++]) { + case 'l': srcmode = absl; break; case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break; case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break; default: abort(); @@ -348,6 +391,11 @@ static void build_insn (int insn) case 'P': srcmode = Aipi; pos++; break; } break; +#if 0 + case 'L': + srcmode = absl; + break; +#endif case '#': switch (opcstr[pos++]) { case 'z': srcmode = imm; break; @@ -393,6 +441,22 @@ static void build_insn (int insn) srcpos = bitpos[bitK]; } break; + case 'E': srcmode = immi; srcreg = bitval[bitE]; + if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? + /* 1..255 */ + srcgather = 1; + srctype = 6; + srcpos = bitpos[bitE]; + } + break; + case 'p': srcmode = immi; srcreg = bitval[bitp]; + if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? + /* 0..3 */ + srcgather = 1; + srctype = 7; + srcpos = bitpos[bitp]; + } + break; default: abort(); } break; @@ -517,12 +581,16 @@ static void build_insn (int insn) case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; default: abort(); } + if (dstpos < 0 || dstpos >= 32) + abort(); break; case 'A': destmode = Areg; switch (opcstr[pos++]) { + case 'l': destmode = absl; break; case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; + case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; default: abort(); } switch (opcstr[pos]) { @@ -530,6 +598,11 @@ static void build_insn (int insn) case 'P': destmode = Aipi; pos++; break; } break; +#if 0 + case 'L': + destmode = absl; + break; +#endif case '#': switch (opcstr[pos++]) { case 'z': destmode = imm; break; @@ -700,8 +773,44 @@ static void build_insn (int insn) table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; } #endif + + // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions + if ( table68k[opc].mnemo == i_Scc + || table68k[opc].mnemo == i_Bcc + || table68k[opc].mnemo == i_DBcc + || table68k[opc].mnemo == i_TRAPcc + ) { + switch (table68k[opc].cc) { + // CC mask: XNZVC + // 8421 + case 0: flags_used = 0x00; break; /* T */ + case 1: flags_used = 0x00; break; /* F */ + case 2: flags_used = 0x05; break; /* HI */ + case 3: flags_used = 0x05; break; /* LS */ + case 4: flags_used = 0x01; break; /* CC */ + case 5: flags_used = 0x01; break; /* CS */ + case 6: flags_used = 0x04; break; /* NE */ + case 7: flags_used = 0x04; break; /* EQ */ + case 8: flags_used = 0x02; break; /* VC */ + case 9: flags_used = 0x02; break; /* VS */ + case 10:flags_used = 0x08; break; /* PL */ + case 11:flags_used = 0x08; break; /* MI */ + case 12:flags_used = 0x0A; break; /* GE */ + case 13:flags_used = 0x0A; break; /* LT */ + case 14:flags_used = 0x0E; break; /* GT */ + case 15:flags_used = 0x0E; break; /* LE */ + } + } + +#if 1 + /* gb-- flagdead and flaglive would not have correct information */ + table68k[opc].flagdead = flags_set; + table68k[opc].flaglive = flags_used; +#else table68k[opc].flagdead = flagdead; table68k[opc].flaglive = flaglive; +#endif + table68k[opc].cflow = cflow; nomatch: /* FOO! */; } @@ -722,7 +831,7 @@ void read_table68k (void) } } -static int mismatch; +static int readcpu_mismatch; static void handle_merges (long int opcode) { @@ -747,6 +856,10 @@ static void handle_merges (long int opcode) smsk = 7; sbitdst = 8; break; case 5: smsk = 63; sbitdst = 64; break; + case 6: + smsk = 255; sbitdst = 256; break; + case 7: + smsk = 3; sbitdst = 4; break; default: smsk = 0; sbitdst = 0; abort(); @@ -775,20 +888,20 @@ static void handle_merges (long int opcode) || table68k[code].suse != table68k[opcode].suse || table68k[code].duse != table68k[opcode].duse) { - mismatch++; continue; + readcpu_mismatch++; continue; } if (table68k[opcode].suse && (table68k[opcode].spos != table68k[code].spos || table68k[opcode].smode != table68k[code].smode || table68k[opcode].stype != table68k[code].stype)) { - mismatch++; continue; + readcpu_mismatch++; continue; } if (table68k[opcode].duse && (table68k[opcode].dpos != table68k[code].dpos || table68k[opcode].dmode != table68k[code].dmode)) { - mismatch++; continue; + readcpu_mismatch++; continue; } if (code != opcode) @@ -801,7 +914,7 @@ void do_merges (void) { long int opcode; int nr = 0; - mismatch = 0; + readcpu_mismatch = 0; for (opcode = 0; opcode < 65536; opcode++) { if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG) continue; @@ -813,5 +926,5 @@ void do_merges (void) int get_no_mismatches (void) { - return mismatch; + return readcpu_mismatch; } diff --git a/BasiliskII/src/uae_cpu/readcpu.h b/BasiliskII/src/uae_cpu/readcpu.h index 4f225f13..7855ecc7 100644 --- a/BasiliskII/src/uae_cpu/readcpu.h +++ b/BasiliskII/src/uae_cpu/readcpu.h @@ -1,13 +1,17 @@ +/* 2002 MJ */ +#ifndef READCPU_H +#define READCPU_H + #ifdef __cplusplus extern "C" { #endif -ENUMDECL { +typedef enum { Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r, absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg -} ENUMNAME (amodes); +} amodes; -ENUMDECL { +typedef enum { i_ILLG, i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR, @@ -32,30 +36,42 @@ ENUMDECL { i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES, i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE, i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16, - i_MMUOP -} ENUMNAME (instrmnem); + i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL +} instrmnem; extern struct mnemolookup { instrmnem mnemo; const char *name; } lookuptab[]; -ENUMDECL { +typedef enum { sz_byte, sz_word, sz_long -} ENUMNAME (wordsizes); +} wordsizes; -ENUMDECL { - fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp -} ENUMNAME (flagaffect); +typedef enum { + fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp, + fa_isbranch +} flagaffect; -ENUMDECL { +typedef enum { fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp -} ENUMNAME (flaguse); +} flaguse; -ENUMDECL { +typedef enum { + fl_normal = 0, + fl_branch = 1, + fl_jump = 2, + fl_return = 3, + fl_trap = 4, + fl_const_jump = 8, + /* Instructions that can trap don't mark the end of a block */ + fl_end_block = 3 +} cflow_t; + +typedef enum { bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK, - bits, bitS, bitd, bitD, bitr, bitR, bitz, lastbit -} ENUMNAME (bitvals); + bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit +} bitvals; struct instr_def { unsigned int bits; @@ -68,6 +84,7 @@ struct instr_def { unsigned int flaguse:3; unsigned int flagset:3; } flaginfo[5]; + unsigned char cflow; unsigned char sduse; const char *opcstr; }; @@ -86,22 +103,16 @@ extern struct instr { unsigned int mnemo:8; unsigned int cc:4; unsigned int plev:2; -#ifdef sgi wordsizes size:2; amodes smode:5; unsigned int stype:3; amodes dmode:5; -#else - unsigned int size:2; - unsigned int smode:5; - unsigned int stype:3; - unsigned int dmode:5; -#endif unsigned int suse:1; unsigned int duse:1; unsigned int unused1:1; unsigned int clev:3; - unsigned int unused2:5; + unsigned int cflow:3; + unsigned int unused2:2; } *table68k; extern void read_table68k (void); @@ -112,3 +123,5 @@ extern int nr_cpuop_funcs; #ifdef __cplusplus } #endif + +#endif diff --git a/BasiliskII/src/uae_cpu/readcpua.cpp b/BasiliskII/src/uae_cpu/readcpua.cpp new file mode 100644 index 00000000..521c241f --- /dev/null +++ b/BasiliskII/src/uae_cpu/readcpua.cpp @@ -0,0 +1,5 @@ +/* + * readcpu.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "readcpu.cpp" diff --git a/BasiliskII/src/uae_cpu/registers.h b/BasiliskII/src/uae_cpu/registers.h new file mode 100644 index 00000000..f7daef1f --- /dev/null +++ b/BasiliskII/src/uae_cpu/registers.h @@ -0,0 +1,116 @@ +/* 2001 MJ */ + +#ifndef REGISTERS_H +#define REGISTERS_H + +#include "sysdeps.h" +#include "spcflags.h" +typedef char flagtype; + + +struct xttrx { + uae_u32 log_addr_base : 8; + uae_u32 log_addr_mask : 8; + uae_u32 enable : 1; + uae_u32 s_field : 2; + uae_u32 : 3; + uae_u32 usr1 : 1; + uae_u32 usr0 : 1; + uae_u32 : 1; + uae_u32 cmode : 2; + uae_u32 : 2; + uae_u32 write : 1; + uae_u32 : 2; +}; + +struct mmusr_t { + uae_u32 phys_addr : 20; + uae_u32 bus_err : 1; + uae_u32 global : 1; + uae_u32 usr1 : 1; + uae_u32 usr0 : 1; + uae_u32 super : 1; + uae_u32 cmode : 2; + uae_u32 modif : 1; + uae_u32 : 1; + uae_u32 write : 1; + uae_u32 ttrhit : 1; + uae_u32 resident : 1; +}; + +struct log_addr4 { + uae_u32 rif : 7; + uae_u32 pif : 7; + uae_u32 paif : 6; + uae_u32 poff : 12; +}; + +struct log_addr8 { + uae_u32 rif : 7; + uae_u32 pif : 7; + uae_u32 paif : 5; + uae_u32 poff : 13; +}; + +extern struct regstruct +{ + uae_u32 regs[16]; + uaecptr usp,isp,msp; + uae_u16 sr; + flagtype t1; + flagtype t0; + flagtype s; + flagtype m; + flagtype x; + flagtype stopped; + int intmask; + + uae_u32 pc; + uae_u32 fault_pc; + uae_u8 *pc_p; + uae_u8 *pc_oldp; + + uae_u32 vbr,sfc,dfc; + + volatile uae_u32 spcflags; + +#if 0 + uae_u32 kick_mask; + + /* Fellow sources say this is 4 longwords. That's impossible. It needs + * to be at least a longword. The HRM has some cryptic comment about two + * instructions being on the same longword boundary. + * The way this is implemented now seems like a good compromise. + */ + uae_u32 prefetch; +#endif + + /* MMU reg*/ + uae_u32 urp,srp; + uae_u32 tc; + + int mmu_enabled; /* flagtype tce; */ + int mmu_pagesize_8k; /* flagtype tcp; */ + + uae_u32 dtt0,dtt1,itt0,itt1; + uae_u32 mmusr; + + uae_u32 mmu_fslw, mmu_fault_addr; + uae_u16 mmu_ssw; + uae_u32 wb3_data; + uae_u16 wb3_status; + + /* Cache reg*/ + uae_u32 cacr,caar; +} regs, lastint_regs; + +static inline uaecptr m68k_getpc (void) +{ +#ifdef FULLMMU + return regs.pc; +#else + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); +#endif +} + +#endif diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h new file mode 100644 index 00000000..b2084372 --- /dev/null +++ b/BasiliskII/src/uae_cpu/spcflags.h @@ -0,0 +1,104 @@ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * Copyright 1995 Bernd Schmidt + */ + +#ifndef SPCFLAGS_H +#define SPCFLAGS_H + +typedef uae_u32 spcflags_t; + +enum { + SPCFLAG_STOP = 0x01, + SPCFLAG_INT = 0x02, + SPCFLAG_BRK = 0x04, + SPCFLAG_TRACE = 0x08, + SPCFLAG_DOTRACE = 0x10, + SPCFLAG_DOINT = 0x20, +#ifdef USE_JIT + SPCFLAG_JIT_END_COMPILE = 0x40, + SPCFLAG_JIT_EXEC_RETURN = 0x80, +#else + SPCFLAG_JIT_END_COMPILE = 0, + SPCFLAG_JIT_EXEC_RETURN = 0, +#endif + SPCFLAG_VBL = 0x100, + SPCFLAG_MFP = 0x200, + SPCFLAG_INT3 = 0x800, + SPCFLAG_INT5 = 0x1000, + SPCFLAG_SCC = 0x2000, +// SPCFLAG_MODE_CHANGE = 0x4000, + SPCFLAG_ALL = SPCFLAG_STOP + | SPCFLAG_INT + | SPCFLAG_BRK + | SPCFLAG_TRACE + | SPCFLAG_DOTRACE + | SPCFLAG_DOINT + | SPCFLAG_JIT_END_COMPILE + | SPCFLAG_JIT_EXEC_RETURN + | SPCFLAG_INT3 + | SPCFLAG_VBL + | SPCFLAG_INT5 + | SPCFLAG_SCC + | SPCFLAG_MFP + , + + SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN + +}; + +#define SPCFLAGS_TEST(m) \ + ((regs.spcflags & (m)) != 0) + +/* Macro only used in m68k_reset() */ +#define SPCFLAGS_INIT(m) do { \ + regs.spcflags = (m); \ +} while (0) + +#if !(ENABLE_EXCLUSIVE_SPCFLAGS) + +#define SPCFLAGS_SET(m) do { \ + regs.spcflags |= (m); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + regs.spcflags &= ~(m); \ +} while (0) + +#elif defined(X86_ASSEMBLY) + +#define HAVE_HARDWARE_LOCKS + +#define SPCFLAGS_SET(m) do { \ + __asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + __asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \ +} while (0) + +#else + +#undef HAVE_HARDWARE_LOCKS + +#include "main.h" +extern B2_mutex *spcflags_lock; + +#define SPCFLAGS_SET(m) do { \ + B2_lock_mutex(spcflags_lock); \ + regs.spcflags |= (m); \ + B2_unlock_mutex(spcflags_lock); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + B2_lock_mutex(spcflags_lock); \ + regs.spcflags &= ~(m); \ + B2_unlock_mutex(spcflags_lock); \ +} while (0) + +#endif + +#endif /* SPCFLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/table68k b/BasiliskII/src/uae_cpu/table68k index 54f7c5f3..4445cb50 100644 --- a/BasiliskII/src/uae_cpu/table68k +++ b/BasiliskII/src/uae_cpu/table68k @@ -4,11 +4,13 @@ % C: condition codes, except F % f: direction % i: immediate +% E: immediate, except 00 (for EmulOp instructions) % I: immediate, except 00 and ff % j: immediate 1..8 % J: immediate 0..15 % k: immediate 0..7 % K: immediate 0..63 +% p: immediate 0..3 (CINV and CPUSH: cache field) % s: source mode % S: source reg % d: dest mode @@ -24,15 +26,17 @@ % % Arp: --> -(Ar) % ArP: --> (Ar)+ +% L: --> (xxx.L) % -% Fields on a line: -% 16 chars bitpattern : -% CPU level / privilege level : +% Fields on a line: +% 16 chars bitpattern : +% CPU level / privildge level : % CPU level 0: 68000 % 1: 68010 % 2: 68020 % 3: 68020/68881 % 4: 68040 +% 5: 68060 % privilege level 0: not privileged % 1: unprivileged only on 68000 (check regs.s) % 2: privileged (check regs.s) @@ -43,10 +47,19 @@ % 0 means flag reset % 1 means flag set % ? means programmer was too lazy to check or instruction may trap -% + means instruction is conditional branch -% everything else means flag set/used -% / means instruction is unconditional branch/call +% + means instruction is conditional branch (ignored, only for sync) +% / means instruction is unconditional branch/call (ignored, only for sync) % x means flag is unknown and well-behaved programs shouldn't check it +% everything else means flag set/used +% +% Control flow +% two letters, combination of +% - nothing +% T the instruction may trap or cause an exception +% B branch instruction +% J jump instruction +% R return instruction +% % srcaddr status destaddr status : % bitmasks of % 1 means fetched @@ -56,197 +69,218 @@ % instruction % -0000 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1 -0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1 -0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd] -0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg] -0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1 -0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1 -0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg] -0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg] -0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg] -0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd] -0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg] -0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg] -0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd] -0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd] -0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd] -0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1 -0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1 -0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg] -0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd] +0000 0000 0011 1100:00:XNZVC:XNZVC:--:10: ORSR.B #1 +0000 0000 0111 1100:02:XNZVC:XNZVC:T-:10: ORSR.W #1 +0000 0zz0 11ss sSSS:20:-?Z?C:-----:T-:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd] +0000 0000 zzdd dDDD:00:-NZ00:-----:--:13: OR.z #z,d[!Areg] +0000 0010 0011 1100:00:XNZVC:XNZVC:--:10: ANDSR.B #1 +0000 0010 0111 1100:02:XNZVC:XNZVC:T-:10: ANDSR.W #1 +0000 0010 zzdd dDDD:00:-NZ00:-----:--:13: AND.z #z,d[!Areg] +0000 0100 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #z,d[!Areg] +0000 0110 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #z,d[!Areg] +0000 0110 11ss sSSS:20:-----:XNZVC:--:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd] +0000 0110 11ss sSSS:20:XNZVC:-----:-R:10: RTM s[Dreg,Areg] +0000 1000 00ss sSSS:00:--Z--:-----:--:11: BTST #1,s[!Areg] +0000 1000 01ss sSSS:00:--Z--:-----:--:13: BCHG #1,s[!Areg,Immd] +0000 1000 10ss sSSS:00:--Z--:-----:--:13: BCLR #1,s[!Areg,Immd] +0000 1000 11ss sSSS:00:--Z--:-----:--:13: BSET #1,s[!Areg,Immd] +0000 1010 0011 1100:00:XNZVC:XNZVC:--:10: EORSR.B #1 +0000 1010 0111 1100:02:XNZVC:XNZVC:T-:10: EORSR.W #1 +0000 1010 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z #z,d[!Areg] +0000 1100 zzss sSSS:00:-NZVC:-----:--:11: CMP.z #z,s[!Areg,Immd] -0000 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2 -0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2 +0000 1010 11ss sSSS:20:-NZVC:-----:--:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1100 11ss sSSS:20:-NZVC:-----:--:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1100 1111 1100:20:-NZVC:-----:--:10: CAS2.W #2 +0000 1110 zzss sSSS:22:-----:-----:T-:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1110 11ss sSSS:20:-NZVC:-----:--:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1110 1111 1100:20:-NZVC:-----:--:10: CAS2.L #2 -0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr -0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr -0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16] -0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16] -0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg] -0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd] -0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd] -0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd] +0000 rrr1 00dd dDDD:00:-----:-----:--:12: MVPMR.W d[Areg-Ad16],Dr +0000 rrr1 01dd dDDD:00:-----:-----:--:12: MVPMR.L d[Areg-Ad16],Dr +0000 rrr1 10dd dDDD:00:-----:-----:--:12: MVPRM.W Dr,d[Areg-Ad16] +0000 rrr1 11dd dDDD:00:-----:-----:--:12: MVPRM.L Dr,d[Areg-Ad16] +0000 rrr1 00ss sSSS:00:--Z--:-----:--:11: BTST Dr,s[!Areg] +0000 rrr1 01ss sSSS:00:--Z--:-----:--:13: BCHG Dr,s[!Areg,Immd] +0000 rrr1 10ss sSSS:00:--Z--:-----:--:13: BCLR Dr,s[!Areg,Immd] +0000 rrr1 11ss sSSS:00:--Z--:-----:--:13: BSET Dr,s[!Areg,Immd] -0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg] -0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg] -0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg] -0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg] -0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg] +0001 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.B s,d[!Areg] +0010 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.L s,d[Areg] +0010 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.L s,d[!Areg] +0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg] +0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg] -0100 0000 zzdd dDDD:00:XxZxC:-----:30: NEGX.z d[!Areg] -0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg] -0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg] -0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg] -0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg] -0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg] -0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg] -0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg] -0100 1000 0000 1rrr:20:-----:-----:31: LINK.L Ar,#2 -0100 1000 00dd dDDD:00:X?Z?C:X-Z--:30: NBCD.B d[!Areg] -0100 1000 0100 1kkk:20:?????:?????:10: BKPT #k -0100 1000 01ss sSSS:00:-NZ00:-----:30: SWAP.W s[Dreg] -0100 1000 01ss sSSS:00:-----:-----:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 1000 10dd dDDD:00:-NZ00:-----:30: EXT.W d[Dreg] -0100 1000 10dd dDDD:00:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] -0100 1000 11dd dDDD:00:-NZ00:-----:30: EXT.L d[Dreg] -0100 1000 11dd dDDD:00:-----:-----:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] -0100 1001 11dd dDDD:00:-NZ00:-----:30: EXT.B d[Dreg] -0100 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s -0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg] -0100 1010 1111 1100:00:?????:?????:00: ILLEGAL -0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg] -0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg] -0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd] -0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd] -0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J -0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1 -0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar -0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar -0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar -0100 1110 0111 0000:02:-----:-----:00: RESET -0100 1110 0111 0001:00:-----:-----:00: NOP -0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1 -0100 1110 0111 0011:02:XNZVC:-----:00: RTE -0100 1110 0111 0100:00:?????:?????:10: RTD #1 -0100 1110 0111 0101:00:-----:-----:00: RTS -0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV -0100 1110 0111 0111:00:XNZVC:-----:00: RTR -0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1 -0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1 -0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 rrr1 00ss sSSS:00:?????:?????:11: CHK.L s[!Areg],Dr -0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr -0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar +0100 0000 zzdd dDDD:00:XNZVC:X-Z--:--:30: NEGX.z d[!Areg] +0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg] +0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg] +0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg] +0100 0100 zzdd dDDD:00:XNZVC:-----:--:30: NEG.z d[!Areg] +0100 0100 11ss sSSS:00:XNZVC:-----:--:10: MV2SR.B s[!Areg] +0100 0110 zzdd dDDD:00:-NZ00:-----:--:30: NOT.z d[!Areg] +0100 0110 11ss sSSS:02:XNZVC:XNZVC:T-:10: MV2SR.W s[!Areg] +0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2 +0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg] +0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k +0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] +0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] +0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] +0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] +0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] +0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] +0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s +0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg] +0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL +0100 1100 00ss sSSS:20:-NZVC:-----:--:13: MULL.L #1,s[!Areg] +0100 1100 01ss sSSS:20:-NZV0:-----:T-:13: DIVL.L #1,s[!Areg] +0100 1100 10ss sSSS:00:-----:-----:--:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd] +0100 1100 11ss sSSS:00:-----:-----:--:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd] +0100 1110 0100 JJJJ:00:-----:XNZVC:--:10: TRAP #J +0100 1110 0101 0rrr:00:-----:-----:--:31: LINK.W Ar,#1 +0100 1110 0101 1rrr:00:-----:-----:--:30: UNLK.L Ar +0100 1110 0110 0rrr:02:-----:-----:T-:10: MVR2USP.L Ar +0100 1110 0110 1rrr:02:-----:-----:T-:20: MVUSP2R.L Ar +0100 1110 0111 0000:02:-----:-----:T-:00: RESET +0100 1110 0111 0001:00:-----:-----:--:00: NOP +0100 1110 0111 0010:02:XNZVC:-----:T-:10: STOP #1 +0100 1110 0111 0011:02:XNZVC:-----:TR:00: RTE +0100 1110 0111 0100:00:-----:-----:-R:10: RTD #1 +0100 1110 0111 0101:00:-----:-----:-R:00: RTS +0100 1110 0111 0110:00:-----:XNZVC:T-:00: TRAPV +0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR +0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1 +0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1 +0100 1110 10ss sSSS:00://///://///:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr +0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr +0100 1110 11ss sSSS:00://///://///:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar -0101 jjj0 zzdd dDDD:00:-----:-----:13: ADDA.z #j,d[Areg] -0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg] -0101 jjj1 zzdd dDDD:00:-----:-----:13: SUBA.z #j,d[Areg] -0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg] -0101 cccc 1100 1rrr:00:-----:+++++:31: DBcc.W Dr,#1 -0101 cccc 11dd dDDD:00:-----:+++++:20: Scc.B d[!Areg] -0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1 -0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2 -0101 cccc 1111 1100:20:?????:?????:00: TRAPcc +% This variant of ADDQ is word and long sized only +0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] +0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] +0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg] + +% This variant of SUBQ is word and long sized only +0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] +0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] +0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg] + +0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1 +0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg] +0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1 +0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2 +0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc % Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal % instruction exceptions when compiling a 68000 only emulation, which isn't % what we want either. -0110 0001 0000 0000:00://///://///:40: BSR.W #1 -0110 0001 IIII IIII:00://///://///:40: BSR.B #i -0110 0001 1111 1111:00://///://///:40: BSR.L #2 -0110 CCCC 0000 0000:00:-----:+++++:40: Bcc.W #1 -0110 CCCC IIII IIII:00:-----:+++++:40: Bcc.B #i -0110 CCCC 1111 1111:00:-----:+++++:40: Bcc.L #2 +0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1 +0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i +0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2 +0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1 +0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i +0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2 -0111 rrr0 iiii iiii:00:-NZ00:-----:12: MOVE.L #i,Dr +0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr -1000 rrr0 zzss sSSS:00:-NZ00:-----:13: OR.z s[!Areg],Dr -1000 rrr0 11ss sSSS:00:?????:?????:13: DIVU.W s[!Areg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Dreg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Areg-Apdi],Arp -1000 rrr1 zzdd dDDD:00:-NZ00:-----:13: OR.z Dr,d[!Areg,Dreg] -1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Dreg],Dr -1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Areg-Apdi],Arp -1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Dreg],Dr -1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Areg-Apdi],Arp -1000 rrr1 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],Dr +1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr +1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr +1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Dreg],Dr +1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp +1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg] +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp +1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr -1001 rrr0 zzss sSSS:00:XNZVC:-----:13: SUB.z s,Dr -1001 rrr0 11ss sSSS:00:-----:-----:13: SUBA.W s,Ar -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Dreg],Dr -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Areg-Apdi],Arp -1001 rrr1 zzdd dDDD:00:XNZVC:-----:13: SUB.z Dr,d[!Areg,Dreg] -1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar +1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr +1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp +1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg] +1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar -1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr -1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar -1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar -1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP -1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg] +1011 rrr0 zzss sSSS:00:-NZVC:-----:--:11: CMP.z s,Dr +1011 rrr0 11ss sSSS:00:-NZVC:-----:--:11: CMPA.W s,Ar +1011 rrr1 11ss sSSS:00:-NZVC:-----:--:11: CMPA.L s,Ar +1011 rrr1 zzdd dDDD:00:-NZVC:-----:--:11: CMPM.z d[Areg-Aipi],ArP +1011 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z Dr,d[!Areg] -1100 rrr0 zzss sSSS:00:-NZ00:-----:13: AND.z s[!Areg],Dr -1100 rrr0 11ss sSSS:00:-NZ00:-----:13: MULU.W s[!Areg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Dreg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Areg-Apdi],Arp -1100 rrr1 zzdd dDDD:00:-NZ00:-----:13: AND.z Dr,d[!Areg,Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Dr,d[Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Ar,d[Areg] -1100 rrr1 10dd dDDD:00:-----:-----:33: EXG.L Dr,d[Areg] -1100 rrr1 11ss sSSS:00:-NZ00:-----:13: MULS.W s[!Areg],Dr +1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr +1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr +1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Dreg],Dr +1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp +1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] +1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] +1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr -1101 rrr0 zzss sSSS:00:XNZVC:-----:13: ADD.z s,Dr -1101 rrr0 11ss sSSS:00:-----:-----:13: ADDA.W s,Ar -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Dreg],Dr -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Areg-Apdi],Arp -1101 rrr1 zzdd dDDD:00:XNZVC:-----:13: ADD.z Dr,d[!Areg,Dreg] -1101 rrr1 11ss sSSS:00:-----:-----:13: ADDA.L s,Ar +1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr +1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp +1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg] +1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar -1110 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR -1110 jjjf zz00 1RRR:00:XNZ0C:-----:13: LSf.z #j,DR -1110 jjjf zz01 0RRR:00:XNZ0C:X----:13: ROXf.z #j,DR -1110 jjjf zz01 1RRR:00:-NZ0C:-----:13: ROf.z #j,DR -1110 rrrf zz10 0RRR:00:XNZVC:X----:13: ASf.z Dr,DR -1110 rrrf zz10 1RRR:00:XNZ0C:X----:13: LSf.z Dr,DR -1110 rrrf zz11 0RRR:00:XNZ0C:X----:13: ROXf.z Dr,DR -1110 rrrf zz11 1RRR:00:-NZ0C:-----:13: ROf.z Dr,DR -1110 000f 11dd dDDD:00:XNZVC:-----:13: ASfW.W d[!Dreg,Areg] -1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg] -1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg] -1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg] +1110 jjjf zz00 0RRR:00:XNZVC:-----:--:13: ASf.z #j,DR +1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR +1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR +1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR +1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR +1110 rrrf zz10 1RRR:00:XNZ0C:X----:--:13: LSf.z Dr,DR +1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR +1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR +1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg] +1110 001f 11dd dDDD:00:XNZ0C:-----:--:13: LSfW.W d[!Dreg,Areg] +1110 010f 11dd dDDD:00:XNZ0C:X----:--:13: ROXfW.W d[!Dreg,Areg] +1110 011f 11dd dDDD:00:-NZ0C:-----:--:13: ROfW.W d[!Dreg,Areg] -1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd] -1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd] -1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd] -1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd] -1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1000 11ss sSSS:20:-NZ00:-----:--:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd] +1110 1001 11ss sSSS:20:-NZ00:-----:--:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd] +1110 1010 11ss sSSS:20:-NZ00:-----:--:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1011 11ss sSSS:20:-NZ00:-----:--:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd] +1110 1100 11ss sSSS:20:-NZ00:-----:--:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1101 11ss sSSS:20:-NZ00:-----:--:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd] +1110 1110 11ss sSSS:20:-NZ00:-----:--:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1111 11ss sSSS:20:-NZ00:-----:--:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] % floating point co processor -% TODO: FPU is currently commented out -% 1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s -% 1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg] -% 1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16] -% 1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1 -% 1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2 -% 1111 0010 0111 1100:30:?????:?????:00: FTRAPcc -% 1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1 -% 1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2 -% 1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16] -% 1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] +1111 0010 00ss sSSS:30:-----:-----:--:11: FPP #1,s +1111 0010 01ss sSSS:30:-----:-----:-B:11: FDBcc #1,s[Areg-Dreg] +1111 0010 01ss sSSS:30:-----:-----:--:11: FScc #1,s[!Areg,Immd,PC8r,PC16] +1111 0010 0111 1010:30:-----:-----:T-:10: FTRAPcc #1 +1111 0010 0111 1011:30:-----:-----:T-:10: FTRAPcc #2 +1111 0010 0111 1100:30:-----:-----:T-:00: FTRAPcc +1111 0010 10KK KKKK:30:-----:-----:-B:11: FBcc #K,#1 +1111 0010 11KK KKKK:30:-----:-----:-B:11: FBcc #K,#2 +1111 0011 00ss sSSS:32:-----:-----:--:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16] +1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] % 68040 instructions -1111 0100 ii00 1rrr:42:-----:-----:02: CINVL #i,Ar -1111 0100 ii01 0rrr:42:-----:-----:02: CINVP #i,Ar -1111 0100 ii01 1rrr:42:-----:-----:00: CINVA #i -1111 0100 ii10 1rrr:42:-----:-----:02: CPUSHL #i,Ar -1111 0100 ii11 0rrr:42:-----:-----:02: CPUSHP #i,Ar -1111 0100 ii11 1rrr:42:-----:-----:00: CPUSHA #i -1111 0110 0010 0rrr:40:-----:-----:12: MOVE16 ArP,ARP +1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar +1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar +1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p +1111 0100 pp10 1rrr:42:-----:-----:T-:02: CPUSHL #p,Ar +1111 0100 pp11 0rrr:42:-----:-----:T-:02: CPUSHP #p,Ar +1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p +% destination register number is encoded in the following word +1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi] +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind] + +% MMU disabled +% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s + +% EmulOp instructions (deprecated, to be removed) +0111 0001 0000 0000:02:-----:-----:-R:00: EMULOP_RETURN +0111 0001 EEEE EEEE:02:-----:-----:-J:10: EMULOP #E + +% NatFea instructions (do I have the srcaddr correct?) disabled +% 0111 0011 0000 0000:00:-----:-----:-J:00: NATFEAT_ID +% 0111 0011 0000 0001:00:-----:-----:-J:00: NATFEAT_CALL From 77e20bda2abeebc62646c0674daddaa8192eeb50 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 22 Apr 2018 20:39:37 -0500 Subject: [PATCH 06/20] Back to BasiliskII uae_cpu but with ARAnyM JIT --- BasiliskII/src/CrossPlatform/video_blit.h | 21 +- BasiliskII/src/CrossPlatform/video_vosf.h | 647 ----- BasiliskII/src/SDL/video_sdl.cpp | 477 +--- BasiliskII/src/Unix/CMakeLists.txt | 25 +- BasiliskII/src/Unix/main_unix.cpp | 24 +- BasiliskII/src/Unix/sysdeps.h | 7 +- BasiliskII/src/include/main.h | 7 + BasiliskII/src/include/prefs.h | 6 - BasiliskII/src/prefs.cpp | 10 - BasiliskII/src/prefs_items.cpp | 10 + BasiliskII/src/uae_cpu/Makefile.am | 80 - BasiliskII/src/uae_cpu/aranym_glue.cpp | 327 --- BasiliskII/src/uae_cpu/basilisk_glue.cpp | 2 - BasiliskII/src/uae_cpu/build68k.c | 72 +- .../src/uae_cpu/compiler/codegen_x86.cpp | 6 +- BasiliskII/src/uae_cpu/compiler/compemu.h | 4 +- .../src/uae_cpu/compiler/compemu_support.cpp | 132 +- BasiliskII/src/uae_cpu/compiler/gencomp.c | 13 +- BasiliskII/src/uae_cpu/compiler/gencomp_arm.c | 2 +- BasiliskII/src/uae_cpu/cpu_emulation.h | 40 +- BasiliskII/src/uae_cpu/cpudefsa.cpp | 5 - BasiliskII/src/uae_cpu/cpuemu1.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu1_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpuemu2.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu2_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpuemu3.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu3_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpuemu4.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu4_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpuemu5.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu5_nf.cpp | 4 - BasiliskII/src/uae_cpu/cpuemu6.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu6_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpuemu7.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu7_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpuemu8.cpp | 2 - BasiliskII/src/uae_cpu/cpuemu8_nf.cpp | 3 - BasiliskII/src/uae_cpu/cpufunctbla.cpp | 5 - BasiliskII/src/uae_cpu/cpummu.cpp | 1096 -------- BasiliskII/src/uae_cpu/cpummu.h | 267 -- BasiliskII/src/uae_cpu/cpuopti.c | 312 +++ BasiliskII/src/uae_cpu/cpustbl_nf.cpp | 2 - BasiliskII/src/uae_cpu/cpustbla.cpp | 5 - BasiliskII/src/uae_cpu/debug.cpp | 82 - BasiliskII/src/uae_cpu/fpu/core.h | 69 +- BasiliskII/src/uae_cpu/fpu/exceptions.cpp | 45 +- BasiliskII/src/uae_cpu/fpu/exceptions.h | 45 +- BasiliskII/src/uae_cpu/fpu/flags.cpp | 45 +- BasiliskII/src/uae_cpu/fpu/flags.h | 49 +- BasiliskII/src/uae_cpu/fpu/fpu.h | 50 +- BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp | 656 ++--- BasiliskII/src/uae_cpu/fpu/fpu_ieee.h | 47 +- BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp | 2110 --------------- BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp | 410 +-- BasiliskII/src/uae_cpu/fpu/fpu_uae.h | 45 +- BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp | 749 +----- BasiliskII/src/uae_cpu/fpu/fpu_x86.h | 87 +- BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h | 32 - BasiliskII/src/uae_cpu/fpu/impl.h | 52 +- BasiliskII/src/uae_cpu/fpu/mathlib.cpp | 43 +- BasiliskII/src/uae_cpu/fpu/mathlib.h | 484 ++-- BasiliskII/src/uae_cpu/fpu/rounding.cpp | 45 +- BasiliskII/src/uae_cpu/fpu/rounding.h | 45 +- BasiliskII/src/uae_cpu/fpu/types.h | 70 +- BasiliskII/src/uae_cpu/gencpu.c | 1449 +++++----- BasiliskII/src/uae_cpu/m68k.h | 361 +-- BasiliskII/src/uae_cpu/memory-uae.h | 606 ----- BasiliskII/src/uae_cpu/memory.cpp | 649 ++++- BasiliskII/src/uae_cpu/memory.h | 157 +- BasiliskII/src/uae_cpu/newcpu.cpp | 2370 ++++++++--------- BasiliskII/src/uae_cpu/newcpu.h | 353 ++- BasiliskII/src/uae_cpu/noflags.h | 4 +- BasiliskII/src/uae_cpu/readcpu.cpp | 239 +- BasiliskII/src/uae_cpu/readcpu.h | 65 +- BasiliskII/src/uae_cpu/readcpua.cpp | 5 - BasiliskII/src/uae_cpu/registers.h | 116 - BasiliskII/src/uae_cpu/spcflags.h | 83 +- BasiliskII/src/uae_cpu/table68k | 110 +- 78 files changed, 4487 insertions(+), 10985 deletions(-) delete mode 100644 BasiliskII/src/uae_cpu/Makefile.am delete mode 100644 BasiliskII/src/uae_cpu/aranym_glue.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpudefsa.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu1.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu1_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu2.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu2_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu3.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu3_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu4.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu4_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu5.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu5_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu6.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu6_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu7.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu7_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu8.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpuemu8_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpufunctbla.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpummu.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpummu.h create mode 100644 BasiliskII/src/uae_cpu/cpuopti.c delete mode 100644 BasiliskII/src/uae_cpu/cpustbl_nf.cpp delete mode 100644 BasiliskII/src/uae_cpu/cpustbla.cpp delete mode 100644 BasiliskII/src/uae_cpu/debug.cpp delete mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp delete mode 100644 BasiliskII/src/uae_cpu/memory-uae.h delete mode 100644 BasiliskII/src/uae_cpu/readcpua.cpp delete mode 100644 BasiliskII/src/uae_cpu/registers.h diff --git a/BasiliskII/src/CrossPlatform/video_blit.h b/BasiliskII/src/CrossPlatform/video_blit.h index 9ca19ad6..1b6cb68b 100644 --- a/BasiliskII/src/CrossPlatform/video_blit.h +++ b/BasiliskII/src/CrossPlatform/video_blit.h @@ -36,25 +36,7 @@ extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length); extern bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_order, int mac_depth); extern uint32 ExpandMap[256]; -// Glue for SheepShaver and BasiliskII -#ifdef SHEEPSHAVER -enum { - VIDEO_DEPTH_1BIT = APPLE_1_BIT, - VIDEO_DEPTH_2BIT = APPLE_2_BIT, - VIDEO_DEPTH_4BIT = APPLE_4_BIT, - VIDEO_DEPTH_8BIT = APPLE_8_BIT, - VIDEO_DEPTH_16BIT = APPLE_16_BIT, - VIDEO_DEPTH_32BIT = APPLE_32_BIT -}; -#define VIDEO_MODE VideoInfo -#define VIDEO_MODE_INIT VideoInfo const & mode = VModes[cur_mode] -#define VIDEO_MODE_INIT_MONITOR VIDEO_MODE_INIT -#define VIDEO_MODE_ROW_BYTES mode.viRowBytes -#define VIDEO_MODE_X mode.viXsize -#define VIDEO_MODE_Y mode.viYsize -#define VIDEO_MODE_RESOLUTION mode.viAppleID -#define VIDEO_MODE_DEPTH mode.viAppleMode -#else +// Glue for BasiliskII enum { VIDEO_DEPTH_1BIT = VDEPTH_1BIT, VIDEO_DEPTH_2BIT = VDEPTH_2BIT, @@ -71,7 +53,6 @@ enum { #define VIDEO_MODE_Y mode.y #define VIDEO_MODE_RESOLUTION mode.resolution_id #define VIDEO_MODE_DEPTH mode.depth -#endif #endif /* VIDEO_BLIT_H */ diff --git a/BasiliskII/src/CrossPlatform/video_vosf.h b/BasiliskII/src/CrossPlatform/video_vosf.h index 148a9e6f..980ea34d 100644 --- a/BasiliskII/src/CrossPlatform/video_vosf.h +++ b/BasiliskII/src/CrossPlatform/video_vosf.h @@ -21,651 +21,4 @@ #ifndef VIDEO_VOSF_H #define VIDEO_VOSF_H -// Note: this file must be #include'd only in video_x.cpp -#ifdef ENABLE_VOSF - -#include "sigsegv.h" -#include "vm_alloc.h" - -// Glue for SDL and X11 support -#ifdef TEST_VOSF_PERFORMANCE -#define MONITOR_INIT /* nothing */ -#else -#ifdef USE_SDL_VIDEO -#define MONITOR_INIT SDL_monitor_desc &monitor -#define VIDEO_DRV_WIN_INIT driver_base *drv -#define VIDEO_DRV_DGA_INIT driver_base *drv -#define VIDEO_DRV_LOCK_PIXELS SDL_VIDEO_LOCK_SURFACE(drv->s) -#define VIDEO_DRV_UNLOCK_PIXELS SDL_VIDEO_UNLOCK_SURFACE(drv->s) -#define VIDEO_DRV_DEPTH drv->s->format->BitsPerPixel -#define VIDEO_DRV_WIDTH drv->s->w -#define VIDEO_DRV_HEIGHT drv->s->h -#define VIDEO_DRV_ROW_BYTES drv->s->pitch -#else -#ifdef SHEEPSHAVER -#define MONITOR_INIT /* nothing */ -#define VIDEO_DRV_WIN_INIT /* nothing */ -#define VIDEO_DRV_DGA_INIT /* nothing */ -#define VIDEO_DRV_WINDOW the_win -#define VIDEO_DRV_GC the_gc -#define VIDEO_DRV_IMAGE img -#define VIDEO_DRV_HAVE_SHM have_shm -#else -#define MONITOR_INIT X11_monitor_desc &monitor -#define VIDEO_DRV_WIN_INIT driver_window *drv -#define VIDEO_DRV_DGA_INIT driver_dga *drv -#define VIDEO_DRV_WINDOW drv->w -#define VIDEO_DRV_GC drv->gc -#define VIDEO_DRV_IMAGE drv->img -#define VIDEO_DRV_HAVE_SHM drv->have_shm -#endif -#define VIDEO_DRV_LOCK_PIXELS /* nothing */ -#define VIDEO_DRV_UNLOCK_PIXELS /* nothing */ -#define VIDEO_DRV_DEPTH VIDEO_DRV_IMAGE->depth -#define VIDEO_DRV_WIDTH VIDEO_DRV_IMAGE->width -#define VIDEO_DRV_HEIGHT VIDEO_DRV_IMAGE->height -#define VIDEO_DRV_ROW_BYTES VIDEO_DRV_IMAGE->bytes_per_line -#endif -#endif - -// Prototypes -static void vosf_do_set_dirty_area(uintptr first, uintptr last); -static void vosf_set_dirty_area(int x, int y, int w, int h, unsigned screen_width, unsigned screen_height, unsigned bytes_per_row); - -// Variables for Video on SEGV support -static uint8 *the_host_buffer; // Host frame buffer in VOSF mode - -struct ScreenPageInfo { - unsigned top, bottom; // Mapping between this virtual page and Mac scanlines -}; - -struct ScreenInfo { - uintptr memStart; // Start address aligned to page boundary - uint32 memLength; // Length of the memory addressed by the screen pages - - uintptr pageSize; // Size of a page - int pageBits; // Shift count to get the page number - uint32 pageCount; // Number of pages allocated to the screen - - bool dirty; // Flag: set if the frame buffer was touched - bool very_dirty; // Flag: set if the frame buffer was completely modified (e.g. colormap changes) - char * dirtyPages; // Table of flags set if page was altered - ScreenPageInfo * pageInfo; // Table of mappings page -> Mac scanlines -}; - -static ScreenInfo mainBuffer; - -#define PFLAG_SET_VALUE 0x00 -#define PFLAG_CLEAR_VALUE 0x01 -#define PFLAG_SET_VALUE_4 0x00000000 -#define PFLAG_CLEAR_VALUE_4 0x01010101 -#define PFLAG_SET(page) mainBuffer.dirtyPages[page] = PFLAG_SET_VALUE -#define PFLAG_CLEAR(page) mainBuffer.dirtyPages[page] = PFLAG_CLEAR_VALUE -#define PFLAG_ISSET(page) (mainBuffer.dirtyPages[page] == PFLAG_SET_VALUE) -#define PFLAG_ISCLEAR(page) (mainBuffer.dirtyPages[page] != PFLAG_SET_VALUE) - -#ifdef UNALIGNED_PROFITABLE -# define PFLAG_ISSET_4(page) (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_SET_VALUE_4) -# define PFLAG_ISCLEAR_4(page) (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_CLEAR_VALUE_4) -#else -# define PFLAG_ISSET_4(page) \ - PFLAG_ISSET(page ) && PFLAG_ISSET(page+1) \ - && PFLAG_ISSET(page+2) && PFLAG_ISSET(page+3) -# define PFLAG_ISCLEAR_4(page) \ - PFLAG_ISCLEAR(page ) && PFLAG_ISCLEAR(page+1) \ - && PFLAG_ISCLEAR(page+2) && PFLAG_ISCLEAR(page+3) -#endif - -// Set the selected page range [ first_page, last_page [ into the SET state -#define PFLAG_SET_RANGE(first_page, last_page) \ - memset(mainBuffer.dirtyPages + (first_page), PFLAG_SET_VALUE, \ - (last_page) - (first_page)) - -// Set the selected page range [ first_page, last_page [ into the CLEAR state -#define PFLAG_CLEAR_RANGE(first_page, last_page) \ - memset(mainBuffer.dirtyPages + (first_page), PFLAG_CLEAR_VALUE, \ - (last_page) - (first_page)) - -#define PFLAG_SET_ALL do { \ - PFLAG_SET_RANGE(0, mainBuffer.pageCount); \ - mainBuffer.dirty = true; \ -} while (0) - -#define PFLAG_CLEAR_ALL do { \ - PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount); \ - mainBuffer.dirty = false; \ - mainBuffer.very_dirty = false; \ -} while (0) - -#define PFLAG_SET_VERY_DIRTY do { \ - mainBuffer.very_dirty = true; \ -} while (0) - -// Set the following macro definition to 1 if your system -// provides a really fast strchr() implementation -//#define HAVE_FAST_STRCHR 0 - -static inline unsigned find_next_page_set(unsigned page) -{ -#if HAVE_FAST_STRCHR - char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_SET_VALUE); - return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount; -#else - while (PFLAG_ISCLEAR_4(page)) - page += 4; - while (PFLAG_ISCLEAR(page)) - page++; - return page; -#endif -} - -static inline unsigned find_next_page_clear(unsigned page) -{ -#if HAVE_FAST_STRCHR - char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_CLEAR_VALUE); - return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount; -#else - while (PFLAG_ISSET_4(page)) - page += 4; - while (PFLAG_ISSET(page)) - page++; - return page; -#endif -} - -#if defined(HAVE_PTHREADS) -static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect frame buffer (dirtyPages in fact) -#define LOCK_VOSF pthread_mutex_lock(&vosf_lock); -#define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock); -#elif defined(HAVE_SPINLOCKS) -static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED; // Mutex to protect frame buffer (dirtyPages in fact) -#define LOCK_VOSF spin_lock(&vosf_lock) -#define UNLOCK_VOSF spin_unlock(&vosf_lock) -#else -#define LOCK_VOSF -#define UNLOCK_VOSF -#endif - -static int log_base_2(uint32 x) -{ - uint32 mask = 0x80000000; - int l = 31; - while (l >= 0 && (x & mask) == 0) { - mask >>= 1; - l--; - } - return l; -} - -// Extend size to page boundary -static uint32 page_extend(uint32 size) -{ - const uint32 page_size = vm_get_page_size(); - const uint32 page_mask = page_size - 1; - return (size + page_mask) & ~page_mask; -} - - -/* - * Check if VOSF acceleration is profitable on this platform - */ - -#ifndef VOSF_PROFITABLE_TRIES -#define VOSF_PROFITABLE_TRIES VOSF_PROFITABLE_TRIES_DFL -#endif -const int VOSF_PROFITABLE_TRIES_DFL = 3; // Make 3 attempts for full screen update -const int VOSF_PROFITABLE_THRESHOLD = 16667/2; // 60 Hz (half of the quantum) - -static bool video_vosf_profitable(uint32 *duration_p = NULL, uint32 *n_page_faults_p = NULL) -{ - uint32 duration = 0; - uint32 n_tries = VOSF_PROFITABLE_TRIES; - const uint32 n_page_faults = mainBuffer.pageCount * n_tries; - -#ifdef SHEEPSHAVER - const bool accel = PrefsFindBool("gfxaccel"); -#else - const bool accel = false; -#endif - - for (uint32 i = 0; i < n_tries; i++) { - uint64 start = GetTicks_usec(); - for (uint32 p = 0; p < mainBuffer.pageCount; p++) { - uint8 *addr = (uint8 *)(mainBuffer.memStart + (p * mainBuffer.pageSize)); - if (accel) - vosf_do_set_dirty_area((uintptr)addr, (uintptr)addr + mainBuffer.pageSize - 1); - else - addr[0] = 0; // Trigger Screen_fault_handler() - } - duration += uint32(GetTicks_usec() - start); - - PFLAG_CLEAR_ALL; - mainBuffer.dirty = false; - if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0) - return false; - } - - if (duration_p) - *duration_p = duration; - if (n_page_faults_p) - *n_page_faults_p = n_page_faults; - - D(bug("Triggered %d page faults in %ld usec (%.1f usec per fault)\n", n_page_faults, duration, double(duration) / double(n_page_faults))); - return ((duration / n_tries) < (VOSF_PROFITABLE_THRESHOLD * (frame_skip ? frame_skip : 1))); -} - - -/* - * Initialize the VOSF system (mainBuffer structure, SIGSEGV handler) - */ - -static bool video_vosf_init(MONITOR_INIT) -{ - VIDEO_MODE_INIT_MONITOR; - - const uintptr page_size = vm_get_page_size(); - const uintptr page_mask = page_size - 1; - - // Round up frame buffer base to page boundary - mainBuffer.memStart = (((uintptr) the_buffer) + page_mask) & ~page_mask; - - // The frame buffer size shall already be aligned to page boundary (use page_extend) - mainBuffer.memLength = the_buffer_size; - - mainBuffer.pageSize = page_size; - mainBuffer.pageBits = log_base_2(mainBuffer.pageSize); - mainBuffer.pageCount = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize; - - // The "2" more bytes requested are a safety net to insure the - // loops in the update routines will terminate. - // See "How can we deal with array overrun conditions ?" hereunder for further details. - mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2); - if (mainBuffer.dirtyPages == NULL) - return false; - - PFLAG_CLEAR_ALL; - PFLAG_CLEAR(mainBuffer.pageCount); - PFLAG_SET(mainBuffer.pageCount+1); - - // Allocate and fill in pageInfo with start and end (inclusive) row in number of bytes - mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo)); - if (mainBuffer.pageInfo == NULL) - return false; - - uint32 a = 0; - for (unsigned i = 0; i < mainBuffer.pageCount; i++) { - unsigned y1 = a / VIDEO_MODE_ROW_BYTES; - if (y1 >= VIDEO_MODE_Y) - y1 = VIDEO_MODE_Y - 1; - - unsigned y2 = (a + mainBuffer.pageSize) / VIDEO_MODE_ROW_BYTES; - if (y2 >= VIDEO_MODE_Y) - y2 = VIDEO_MODE_Y - 1; - - mainBuffer.pageInfo[i].top = y1; - mainBuffer.pageInfo[i].bottom = y2; - - a += mainBuffer.pageSize; - if (a > mainBuffer.memLength) - a = mainBuffer.memLength; - } - - // We can now write-protect the frame buffer - if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0) - return false; - - // The frame buffer is sane, i.e. there is no write to it yet - mainBuffer.dirty = false; - return true; -} - - -/* - * Deinitialize VOSF system - */ - -static void video_vosf_exit(void) -{ - if (mainBuffer.pageInfo) { - free(mainBuffer.pageInfo); - mainBuffer.pageInfo = NULL; - } - if (mainBuffer.dirtyPages) { - free(mainBuffer.dirtyPages); - mainBuffer.dirtyPages = NULL; - } -} - - -/* - * Update VOSF state with specified dirty area - */ - -static void vosf_do_set_dirty_area(uintptr first, uintptr last) -{ - const int first_page = (first - mainBuffer.memStart) >> mainBuffer.pageBits; - const int last_page = (last - mainBuffer.memStart) >> mainBuffer.pageBits; - uint8 *addr = (uint8 *)(first & ~(mainBuffer.pageSize - 1)); - for (int i = first_page; i <= last_page; i++) { - if (PFLAG_ISCLEAR(i)) { - PFLAG_SET(i); - vm_protect(addr, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE); - } - addr += mainBuffer.pageSize; - } -} - -static void vosf_set_dirty_area(int x, int y, int w, int h, unsigned screen_width, unsigned screen_height, unsigned bytes_per_row) -{ - if (x < 0) { - w -= -x; - x = 0; - } - if (y < 0) { - h -= -y; - y = 0; - } - if (w <= 0 || h <= 0) - return; - if (unsigned(x + w) > screen_width) - w -= unsigned(x + w) - screen_width; - if (unsigned(y + h) > screen_height) - h -= unsigned(y + h) - screen_height; - LOCK_VOSF; - if (bytes_per_row >= screen_width) { - const int bytes_per_pixel = bytes_per_row / screen_width; - if (bytes_per_row <= mainBuffer.pageSize) { - const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x * bytes_per_pixel; - const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) * bytes_per_pixel; - vosf_do_set_dirty_area(a0, a1); - } else { - for (int j = y; j < y + h; j++) { - const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x * bytes_per_pixel; - const uintptr a1 = a0 + (w - 1) * bytes_per_pixel; - vosf_do_set_dirty_area(a0, a1); - } - } - } else { - const int pixels_per_byte = screen_width / bytes_per_row; - if (bytes_per_row <= mainBuffer.pageSize) { - const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x / pixels_per_byte; - const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) / pixels_per_byte; - vosf_do_set_dirty_area(a0, a1); - } else { - for (int j = y; j < y + h; j++) { - const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x / pixels_per_byte; - const uintptr a1 = mainBuffer.memStart + j * bytes_per_row + (x + w - 1) / pixels_per_byte; - vosf_do_set_dirty_area(a0, a1); - } - } - } - mainBuffer.dirty = true; - UNLOCK_VOSF; -} - - -/* - * Screen fault handler - */ - -bool Screen_fault_handler(sigsegv_info_t *sip) -{ - const uintptr addr = (uintptr)sigsegv_get_fault_address(sip); - - /* Someone attempted to write to the frame buffer. Make it writeable - * now so that the data could actually be written to. It will be made - * read-only back in one of the screen update_*() functions. - */ - if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) { - const int page = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits; - LOCK_VOSF; - if (PFLAG_ISCLEAR(page)) { - PFLAG_SET(page); - vm_protect((char *)(addr & ~(mainBuffer.pageSize - 1)), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE); - } - mainBuffer.dirty = true; - UNLOCK_VOSF; - return true; - } - - /* Otherwise, we don't know how to handle the fault, let it crash */ - return false; -} - - -/* - * Update display for Windowed mode and VOSF - */ - -/* How can we deal with array overrun conditions ? - - The state of the framebuffer pages that have been touched are maintained - in the dirtyPages[] table. That table is (pageCount + 2) bytes long. - -Terminology - - "Last Page" denotes the pageCount-nth page, i.e. dirtyPages[pageCount - 1]. - "CLEAR Page Guard" refers to the page following the Last Page but is always - in the CLEAR state. "SET Page Guard" refers to the page following the CLEAR - Page Guard but is always in the SET state. - -Rough process - - The update routines must determine which pages have to be blitted to the - screen. This job consists in finding the first_page that was touched. - i.e. find the next page that is SET. Then, finding how many pages were - touched starting from first_page. i.e. find the next page that is CLEAR. - -There are two cases to check: - - - Last Page is CLEAR: find_next_page_set() will reach the SET Page Guard - but it is beyond the valid pageCount value. Therefore, we exit from the - update routine. - - - Last Page is SET: first_page equals (pageCount - 1) and - find_next_page_clear() will reach the CLEAR Page Guard. We blit the last - page to the screen. On the next iteration, page equals pageCount and - find_next_page_set() will reach the SET Page Guard. We still safely exit - from the update routine because the SET Page Guard position is greater - than pageCount. -*/ - -#ifndef TEST_VOSF_PERFORMANCE -static void update_display_window_vosf(VIDEO_DRV_WIN_INIT) -{ - VIDEO_MODE_INIT; - - unsigned page = 0; - for (;;) { - const unsigned first_page = find_next_page_set(page); - if (first_page >= mainBuffer.pageCount) - break; - - page = find_next_page_clear(first_page); - PFLAG_CLEAR_RANGE(first_page, page); - - // Make the dirty pages read-only again - const int32 offset = first_page << mainBuffer.pageBits; - const uint32 length = (page - first_page) << mainBuffer.pageBits; - vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ); - - // There is at least one line to update - const int y1 = mainBuffer.pageInfo[first_page].top; - const int y2 = mainBuffer.pageInfo[page - 1].bottom; - const int height = y2 - y1 + 1; - - // Update the_host_buffer - VIDEO_DRV_LOCK_PIXELS; - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES; - int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; - for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row); - i1 += src_bytes_per_row; - i2 += dst_bytes_per_row; - } - VIDEO_DRV_UNLOCK_PIXELS; - -#ifdef USE_SDL_VIDEO - SDL_UpdateRect(drv->s, 0, y1, VIDEO_MODE_X, height); -#else - if (VIDEO_DRV_HAVE_SHM) - XShmPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height, 0); - else - XPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height); -#endif - } - mainBuffer.dirty = false; -} -#endif - - -/* - * Update display for DGA mode and VOSF - * (only in Real or Direct Addressing mode) - */ - -#ifndef TEST_VOSF_PERFORMANCE -#if DIRECT_ADDRESSING -static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT) -{ - VIDEO_MODE_INIT; - - // Compute number of bytes per row, take care to virtual screens - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = TrivialBytesPerRow(VIDEO_MODE_X, DepthModeForPixelDepth(VIDEO_DRV_DEPTH)); - const int scr_bytes_per_row = VIDEO_DRV_ROW_BYTES; - assert(dst_bytes_per_row <= scr_bytes_per_row); - const int scr_bytes_left = scr_bytes_per_row - dst_bytes_per_row; - - // Full screen update requested? - if (mainBuffer.very_dirty) { - PFLAG_CLEAR_ALL; - vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ); - memcpy(the_buffer_copy, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); - VIDEO_DRV_LOCK_PIXELS; - int i1 = 0, i2 = 0; - for (uint32_t j = 0; j < VIDEO_MODE_Y; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row); - i1 += src_bytes_per_row; - i2 += scr_bytes_per_row; - } -#ifdef USE_SDL_VIDEO - SDL_UpdateRect(drv->s, 0, 0, VIDEO_MODE_X, VIDEO_MODE_Y); -#endif - VIDEO_DRV_UNLOCK_PIXELS; - return; - } - - // Setup partial blitter (use 64-pixel wide chunks) - const uint32 n_pixels = 64; - const uint32 n_chunks = VIDEO_MODE_X / n_pixels; - const uint32 n_pixels_left = VIDEO_MODE_X - (n_chunks * n_pixels); - const uint32 src_chunk_size = src_bytes_per_row / n_chunks; - const uint32 dst_chunk_size = dst_bytes_per_row / n_chunks; - const uint32 src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size); - const uint32 dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size); - - unsigned page = 0; - uint32 last_scanline = uint32(-1); - for (;;) { - const unsigned first_page = find_next_page_set(page); - if (first_page >= mainBuffer.pageCount) - break; - - page = find_next_page_clear(first_page); - PFLAG_CLEAR_RANGE(first_page, page); - - // Make the dirty pages read-only again - const int32 offset = first_page << mainBuffer.pageBits; - const uint32 length = (page - first_page) << mainBuffer.pageBits; - vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ); - - // Optimized for scanlines, don't process overlapping lines again - uint32 y1 = mainBuffer.pageInfo[first_page].top; - uint32 y2 = mainBuffer.pageInfo[page - 1].bottom; - if (last_scanline != uint32(-1)) { - if (y1 <= last_scanline && ++y1 >= VIDEO_MODE_Y) - continue; - if (y2 <= last_scanline && ++y2 >= VIDEO_MODE_Y) - continue; - } - last_scanline = y2; - - // Update the_host_buffer and copy of the_buffer, one line at a time - uint32 i1 = y1 * src_bytes_per_row; - uint32 i2 = y1 * scr_bytes_per_row; -#ifdef USE_SDL_VIDEO - int bbi = 0; - SDL_Rect bb[3] = { - { Sint16(VIDEO_MODE_X), Sint16(y1), 0, 0 }, - { Sint16(VIDEO_MODE_X), -1, 0, 0 }, - { Sint16(VIDEO_MODE_X), -1, 0, 0 } - }; -#endif - VIDEO_DRV_LOCK_PIXELS; - for (uint32 j = y1; j <= y2; j++) { - for (uint32 i = 0; i < n_chunks; i++) { - if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size) != 0) { - memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size); - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size); -#ifdef USE_SDL_VIDEO - const int x = i * n_pixels; - if (x < bb[bbi].x) { - if (bb[bbi].w) - bb[bbi].w += bb[bbi].x - x; - else - bb[bbi].w = n_pixels; - bb[bbi].x = x; - } - else if (x >= bb[bbi].x + bb[bbi].w) - bb[bbi].w = x + n_pixels - bb[bbi].x; -#endif - } - i1 += src_chunk_size; - i2 += dst_chunk_size; - } - if (src_chunk_size_left && dst_chunk_size_left) { - if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left) != 0) { - memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left); - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size_left); - } - i1 += src_chunk_size_left; - i2 += dst_chunk_size_left; -#ifdef USE_SDL_VIDEO - const int x = n_chunks * n_pixels; - if (x < bb[bbi].x) { - if (bb[bbi].w) - bb[bbi].w += bb[bbi].x - x; - else - bb[bbi].w = n_pixels_left; - bb[bbi].x = x; - } - else if (x >= bb[bbi].x + bb[bbi].w) - bb[bbi].w = x + n_pixels_left - bb[bbi].x; -#endif - } - i2 += scr_bytes_left; -#ifdef USE_SDL_VIDEO - bb[bbi].h++; - if (bb[bbi].w && (j == y1 || j == y2 - 1 || j == y2)) { - bbi++; - assert(bbi <= 3); - if (j != y2) - bb[bbi].y = j + 1; - } -#endif - } -#ifdef USE_SDL_VIDEO - SDL_UpdateRects(drv->s, bbi, bb); -#endif - VIDEO_DRV_UNLOCK_PIXELS; - } - mainBuffer.dirty = false; -} -#endif -#endif - -#endif /* ENABLE_VOSF */ - #endif /* VIDEO_VOSF_H */ diff --git a/BasiliskII/src/SDL/video_sdl.cpp b/BasiliskII/src/SDL/video_sdl.cpp index 9b2855da..9158d729 100644 --- a/BasiliskII/src/SDL/video_sdl.cpp +++ b/BasiliskII/src/SDL/video_sdl.cpp @@ -67,19 +67,11 @@ using std::vector; static vector VideoModes; // Display types -#ifdef SHEEPSHAVER -enum { - DISPLAY_WINDOW = DIS_WINDOW, // windowed display - DISPLAY_SCREEN = DIS_SCREEN // fullscreen display -}; -extern int display_type; // See enum above -#else enum { DISPLAY_WINDOW, // windowed display DISPLAY_SCREEN // fullscreen display }; static int display_type = DISPLAY_WINDOW; // See enum above -#endif // Constants const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; @@ -102,11 +94,7 @@ static volatile bool thread_stop_req = false; static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req #endif -#ifdef ENABLE_VOSF -static bool use_vosf = false; // Flag: VOSF enabled -#else static const bool use_vosf = false; // VOSF not possible -#endif static bool ctrl_down = false; // Flag: Ctrl key pressed static bool caps_on = false; // Flag: Caps Lock on @@ -160,14 +148,7 @@ extern void SysMountFirstFloppy(void); * SDL surface locking glue */ -#ifdef ENABLE_VOSF -#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) do { \ - if ((SURFACE)->flags & (SDL_HWSURFACE | SDL_FULLSCREEN)) \ - the_host_buffer = (uint8 *)(SURFACE)->pixels; \ -} while (0) -#else #define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) -#endif #define SDL_VIDEO_LOCK_SURFACE(SURFACE) do { \ if (SDL_MUSTLOCK(SURFACE)) { \ @@ -209,83 +190,6 @@ static inline void vm_release_framebuffer(void *fb, uint32 size) } - -/* - * SheepShaver glue - */ - -#ifdef SHEEPSHAVER -// Color depth modes type -typedef int video_depth; - -// 1, 2, 4 and 8 bit depths use a color palette -static inline bool IsDirectMode(VIDEO_MODE const & mode) -{ - return IsDirectMode(mode.viAppleMode); -} - -// Abstract base class representing one (possibly virtual) monitor -// ("monitor" = rectangular display with a contiguous frame buffer) -class monitor_desc { -public: - monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id) {} - virtual ~monitor_desc() {} - - // Get current Mac frame buffer base address - uint32 get_mac_frame_base(void) const {return screen_base;} - - // Set Mac frame buffer base address (called from switch_to_mode()) - void set_mac_frame_base(uint32 base) {screen_base = base;} - - // Get current video mode - const VIDEO_MODE &get_current_mode(void) const {return VModes[cur_mode];} - - // Called by the video driver to switch the video mode on this display - // (must call set_mac_frame_base()) - virtual void switch_to_current_mode(void) = 0; - - // Called by the video driver to set the color palette (in indexed modes) - // or the gamma table (in direct modes) - virtual void set_palette(uint8 *pal, int num) = 0; -}; - -// Vector of pointers to available monitor descriptions, filled by VideoInit() -static vector VideoMonitors; - -// Find Apple mode matching best specified dimensions -static int find_apple_resolution(int xsize, int ysize) -{ - if (xsize == 640 && ysize == 480) - return APPLE_640x480; - if (xsize == 800 && ysize == 600) - return APPLE_800x600; - if (xsize == 1024 && ysize == 768) - return APPLE_1024x768; - if (xsize == 1152 && ysize == 768) - return APPLE_1152x768; - if (xsize == 1152 && ysize == 900) - return APPLE_1152x900; - if (xsize == 1280 && ysize == 1024) - return APPLE_1280x1024; - if (xsize == 1600 && ysize == 1200) - return APPLE_1600x1200; - return APPLE_CUSTOM; -} - -// Display error alert -static void ErrorAlert(int error) -{ - ErrorAlert(GetString(error)); -} - -// Display warning alert -static void WarningAlert(int warning) -{ - WarningAlert(GetString(warning)); -} -#endif - - /* * monitor_desc subclass for SDL display */ @@ -417,11 +321,6 @@ static inline int sdl_display_height(void) // Check wether specified mode is available static bool has_mode(int type, int width, int height, int depth) { -#ifdef SHEEPSHAVER - // Filter out Classic resolutions - if (width == 512 && height == 384) - return false; -#endif // Filter out out-of-bounds resolutions if (width > sdl_display_width() || height > sdl_display_height()) @@ -442,10 +341,6 @@ static void add_mode(int type, int width, int height, int resolution_id, int byt // Fill in VideoMode entry VIDEO_MODE mode; -#ifdef SHEEPSHAVER - resolution_id = find_apple_resolution(width, height); - mode.viType = type; -#endif VIDEO_MODE_X = width; VIDEO_MODE_Y = height; VIDEO_MODE_RESOLUTION = resolution_id; @@ -483,50 +378,7 @@ static SDL_GrabMode set_grab_mode(SDL_GrabMode mode) // Migrate preferences items (XXX to be handled in MigratePrefs()) static void migrate_screen_prefs(void) { -#ifdef SHEEPSHAVER - // Look-up priorities are: "screen", "screenmodes", "windowmodes". - if (PrefsFindString("screen")) - return; - uint32 window_modes = PrefsFindInt32("windowmodes"); - uint32 screen_modes = PrefsFindInt32("screenmodes"); - int width = 0, height = 0; - if (screen_modes) { - static const struct { - int id; - int width; - int height; - } - modes[] = { - { 1, 640, 480 }, - { 2, 800, 600 }, - { 4, 1024, 768 }, - { 64, 1152, 768 }, - { 8, 1152, 900 }, - { 16, 1280, 1024 }, - { 32, 1600, 1200 }, - { 0, } - }; - for (int i = 0; modes[i].id != 0; i++) { - if (screen_modes & modes[i].id) { - if (width < modes[i].width && height < modes[i].height) { - width = modes[i].width; - height = modes[i].height; - } - } - } - } else { - if (window_modes & 1) - width = 640, height = 480; - if (window_modes & 2) - width = 800, height = 600; - } - if (width && height) { - char str[32]; - sprintf(str, "%s/%d/%d", screen_modes ? "dga" : "win", width, height); - PrefsReplaceString("screen", str); - } -#endif } @@ -563,17 +415,10 @@ public: SDL_Surface *s; // The surface we draw into }; -#ifdef ENABLE_VOSF -static void update_display_window_vosf(driver_base *drv); -#endif static void update_display_static(driver_base *drv); static driver_base *drv = NULL; // Pointer to currently used driver object -#ifdef ENABLE_VOSF -# include "video_vosf.h" -#endif - driver_base::driver_base(SDL_monitor_desc &m) : monitor(m), mode(m.get_current_mode()), init_ok(false), s(NULL) { @@ -587,9 +432,6 @@ void driver_base::set_video_mode(int flags) if ((s = SDL_SetVideoMode(VIDEO_MODE_X, VIDEO_MODE_Y, depth, SDL_HWSURFACE | flags)) == NULL) return; -#ifdef ENABLE_VOSF - the_host_buffer = (uint8 *)s->pixels; -#endif } void driver_base::init() @@ -597,30 +439,6 @@ void driver_base::init() set_video_mode(display_type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0); int aligned_height = (VIDEO_MODE_Y + 15) & ~15; -#ifdef ENABLE_VOSF - use_vosf = true; - // Allocate memory for frame buffer (SIZE is extended to page-boundary) - the_buffer_size = page_extend((aligned_height + 2) * s->pitch); - the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); - the_buffer_copy = (uint8 *)malloc(the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); - - // Check whether we can initialize the VOSF subsystem and it's profitable - if (!video_vosf_init(monitor)) { - WarningAlert(STR_VOSF_INIT_ERR); - use_vosf = false; - } - else if (!video_vosf_profitable()) { - video_vosf_exit(); - printf("VOSF acceleration is not profitable on this platform, disabling it\n"); - use_vosf = false; - } - if (!use_vosf) { - free(the_buffer_copy); - vm_release(the_buffer, the_buffer_size); - the_host_buffer = NULL; - } -#endif if (!use_vosf) { // Allocate memory for frame buffer the_buffer_size = (aligned_height + 2) * s->pitch; @@ -654,18 +472,6 @@ void driver_base::adapt_to_video_mode() { bool hardware_cursor = false; -#ifdef SHEEPSHAVER - hardware_cursor = video_can_change_cursor(); - if (hardware_cursor) { - // Create cursor - if ((sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, 0, 0)) != NULL) { - SDL_SetCursor(sdl_cursor); - } - } - // Tell the video driver there's a change in cursor type - if (private_data) - private_data->cursorHardware = hardware_cursor; -#endif // Hide cursor SDL_ShowCursor(hardware_cursor); @@ -698,18 +504,6 @@ driver_base::~driver_base() the_buffer_copy = NULL; } } -#ifdef ENABLE_VOSF - else { - if (the_buffer_copy) { - D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy)); - free(the_buffer_copy); - the_buffer_copy = NULL; - } - - // Deinitialize VOSF - video_vosf_exit(); - } -#endif SDL_ShowCursor(1); } @@ -892,22 +686,10 @@ bool SDL_monitor_desc::video_open(void) return true; } -#ifdef SHEEPSHAVER -bool VideoInit(void) -{ - const bool classic = false; -#else bool VideoInit(bool classic) { -#endif classic_mode = classic; -#ifdef ENABLE_VOSF - // Zero the mainBuffer structure - mainBuffer.dirtyPages = NULL; - mainBuffer.pageInfo = NULL; -#endif - // Create Mutexes if ((sdl_events_lock = SDL_CreateMutex()) == NULL) return false; @@ -1035,10 +817,6 @@ bool VideoInit(bool classic) const VIDEO_MODE & mode = (*i); if (VIDEO_MODE_X == default_width && VIDEO_MODE_Y == default_height && VIDEO_MODE_DEPTH == default_depth) { default_id = VIDEO_MODE_RESOLUTION; -#ifdef SHEEPSHAVER - std::vector::const_iterator begin = VideoModes.begin(); - cur_mode = distance(begin, i); -#endif break; } } @@ -1046,22 +824,8 @@ bool VideoInit(bool classic) const VIDEO_MODE & mode = VideoModes[0]; default_depth = VIDEO_MODE_DEPTH; default_id = VIDEO_MODE_RESOLUTION; -#ifdef SHEEPSHAVER - cur_mode = 0; -#endif } -#ifdef SHEEPSHAVER - for (int i = 0; i < VideoModes.size(); i++) - VModes[i] = VideoModes[i]; - VideoInfo *p = &VModes[VideoModes.size()]; - p->viType = DIS_INVALID; // End marker - p->viRowBytes = 0; - p->viXsize = p->viYsize = 0; - p->viAppleMode = 0; - p->viAppleID = 0; -#endif - #if DEBUG D(bug("Available video modes:\n")); for (i = VideoModes.begin(); i != end; ++i) { @@ -1162,9 +926,6 @@ static void do_toggle_fullscreen(void) drv->adapt_to_video_mode(); // reset the palette -#ifdef SHEEPSHAVER - video_set_palette(); -#endif drv->update_palette(); // restore the screen contents @@ -1196,26 +957,6 @@ static void do_toggle_fullscreen(void) * Execute video VBL routine */ -#ifdef SHEEPSHAVER -void VideoVBL(void) -{ - // Emergency quit requested? Then quit - if (emerg_quit) - QuitEmulator(); - - if (toggle_fullscreen) - do_toggle_fullscreen(); - - // Temporarily give up frame buffer lock (this is the point where - // we are suspended when the user presses Ctrl-Tab) - UNLOCK_FRAME_BUFFER; - LOCK_FRAME_BUFFER; - - // Execute video VBL - if (private_data != NULL && private_data->interruptsEnabled) - VSLDoInterruptService(private_data->vslServiceID); -} -#else void VideoInterrupt(void) { // We must fill in the events queue in the same thread that did call SDL_SetVideoMode() @@ -1233,28 +974,12 @@ void VideoInterrupt(void) UNLOCK_FRAME_BUFFER; LOCK_FRAME_BUFFER; } -#endif /* * Set palette */ -#ifdef SHEEPSHAVER -void video_set_palette(void) -{ - monitor_desc * monitor = VideoMonitors[0]; - int n_colors = palette_size(monitor->get_current_mode().viAppleMode); - uint8 pal[256 * 3]; - for (int c = 0; c < n_colors; c++) { - pal[c*3 + 0] = mac_pal[c].red; - pal[c*3 + 1] = mac_pal[c].green; - pal[c*3 + 2] = mac_pal[c].blue; - } - monitor->set_palette(pal, n_colors); -} -#endif - void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) { const VIDEO_MODE &mode = get_current_mode(); @@ -1284,15 +1009,6 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) ExpandMap[i] = SDL_MapRGB(drv->s->format, pal[c*3+0], pal[c*3+1], pal[c*3+2]); } -#ifdef ENABLE_VOSF - if (use_vosf) { - // We have to redraw everything because the interpretation of pixel values changed - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); - } -#endif } // Tell redraw thread to change palette @@ -1306,46 +1022,6 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) * Switch video mode */ -#ifdef SHEEPSHAVER -int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr) -{ - /* return if no mode change */ - if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) && - (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr; - - /* first find video mode in table */ - for (int i=0; VModes[i].viType != DIS_INVALID; i++) { - if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) && - (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) { - csSave->saveMode = ReadMacInt16(ParamPtr + csMode); - csSave->saveData = ReadMacInt32(ParamPtr + csData); - csSave->savePage = ReadMacInt16(ParamPtr + csPage); - - // Disable interrupts and pause redraw thread - DisableInterrupt(); - thread_stop_ack = false; - thread_stop_req = true; - while (!thread_stop_ack) ; - - cur_mode = i; - monitor_desc *monitor = VideoMonitors[0]; - monitor->switch_to_current_mode(); - - WriteMacInt32(ParamPtr + csBaseAddr, screen_base); - csSave->saveBaseAddr=screen_base; - csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ - csSave->saveMode=VModes[cur_mode].viAppleMode; - - // Enable interrupts and resume redraw thread - thread_stop_req = false; - EnableInterrupt(); - return noErr; - } - } - return paramErr; -} -#endif - void SDL_monitor_desc::switch_to_current_mode(void) { // Close and reopen display @@ -1360,77 +1036,6 @@ void SDL_monitor_desc::switch_to_current_mode(void) } } - -/* - * Can we set the MacOS cursor image into the window? - */ - -#ifdef SHEEPSHAVER -bool video_can_change_cursor(void) -{ - if (display_type != DISPLAY_WINDOW) - return false; - -#if defined(__APPLE__) - static char driver[] = "Quartz?"; - static int quartzok = -1; - - if (quartzok < 0) { - if (SDL_VideoDriverName(driver, sizeof driver) == NULL || strncmp(driver, "Quartz", sizeof driver)) - quartzok = true; - else { - // Quartz driver bug prevents cursor changing in SDL 1.2.11 to 1.2.14. - const SDL_version *vp = SDL_Linked_Version(); - int version = SDL_VERSIONNUM(vp->major, vp->minor, vp->patch); - quartzok = (version <= SDL_VERSIONNUM(1, 2, 10) || version >= SDL_VERSIONNUM(1, 2, 15)); - } - } - - return quartzok; -#else - return true; -#endif -} -#endif - - -/* - * Set cursor image for window - */ - -#ifdef SHEEPSHAVER -void video_set_cursor(void) -{ - // Set new cursor image if it was changed - if (sdl_cursor) { - SDL_FreeCursor(sdl_cursor); - sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]); - if (sdl_cursor) { - SDL_ShowCursor(private_data == NULL || private_data->cursorVisible); - SDL_SetCursor(sdl_cursor); - - // XXX Windows apparently needs an extra mouse event to - // make the new cursor image visible. - // On Mac, if mouse is grabbed, SDL_ShowCursor() recenters the - // mouse, we have to put it back. - bool move = false; -#if defined(__APPLE__) - move = mouse_grabbed; -#endif - if (move) { - int visible = SDL_ShowCursor(-1); - if (visible) { - int x, y; - SDL_GetMouseState(&x, &y); - SDL_WarpMouse(x, y); - } - } - } - } -} -#endif - - /* * Keyboard-related utilify functions */ @@ -1609,13 +1214,6 @@ static int event2keycode(SDL_KeyboardEvent const &ev, bool key_down) static void force_complete_window_refresh() { if (display_type == DISPLAY_WINDOW) { -#ifdef ENABLE_VOSF - if (use_vosf) { // VOSF refresh - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - } -#endif // Ensure each byte of the_buffer_copy differs from the_buffer to force a full update. const VIDEO_MODE &mode = VideoMonitors[0]->get_current_mode(); const int len = VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y; @@ -2017,43 +1615,6 @@ static void video_refresh_dga(void) video_refresh_window_static(); } -#ifdef ENABLE_VOSF -#if DIRECT_ADDRESSING -static void video_refresh_dga_vosf(void) -{ - // Quit DGA mode if requested - possibly_quit_dga_mode(); - - // Update display (VOSF variant) - static uint32 tick_counter = 0; - if (++tick_counter >= frame_skip) { - tick_counter = 0; - if (mainBuffer.dirty) { - LOCK_VOSF; - update_display_dga_vosf(drv); - UNLOCK_VOSF; - } - } -} -#endif - -static void video_refresh_window_vosf(void) -{ - // Ungrab mouse if requested - possibly_ungrab_mouse(); - - // Update display (VOSF variant) - static uint32 tick_counter = 0; - if (++tick_counter >= frame_skip) { - tick_counter = 0; - if (mainBuffer.dirty) { - LOCK_VOSF; - update_display_window_vosf(drv); - UNLOCK_VOSF; - } - } -} -#endif // def ENABLE_VOSF static void video_refresh_window_static(void) { @@ -2081,20 +1642,10 @@ static void VideoRefreshInit(void) { // TODO: set up specialised 8bpp VideoRefresh handlers ? if (display_type == DISPLAY_SCREEN) { -#if ENABLE_VOSF && (DIRECT_ADDRESSING) - if (use_vosf) - video_refresh = video_refresh_dga_vosf; - else -#endif - video_refresh = video_refresh_dga; + video_refresh = video_refresh_dga; } else { -#ifdef ENABLE_VOSF - if (use_vosf) - video_refresh = video_refresh_window_vosf; - else -#endif - video_refresh = video_refresh_window_static; + video_refresh = video_refresh_window_static; } } @@ -2159,27 +1710,3 @@ static int redraw_func(void *arg) return 0; } #endif - - -/* - * Record dirty area from NQD - */ - -#ifdef SHEEPSHAVER -void video_set_dirty_area(int x, int y, int w, int h) -{ -#ifdef ENABLE_VOSF - const VIDEO_MODE &mode = drv->mode; - const unsigned screen_width = VIDEO_MODE_X; - const unsigned screen_height = VIDEO_MODE_Y; - const unsigned bytes_per_row = VIDEO_MODE_ROW_BYTES; - - if (use_vosf) { - vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row); - return; - } -#endif - - // XXX handle dirty bounding boxes for non-VOSF modes -} -#endif diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index 65a607f8..9bc6431f 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -5,7 +5,7 @@ project(BasiliskII) find_package(SDL REQUIRED) find_library(COREFOUNDATION_LIBRARY CoreFoundation) find_library(IOKIT_LIBRARY IOKit) -include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL_INCLUDE_DIR}) +include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) add_executable(build68k ../uae_cpu/build68k.c) @@ -15,7 +15,12 @@ add_custom_command(OUTPUT cpudefs.cpp add_executable(gencpu ../uae_cpu/gencpu.c ../uae_cpu/readcpu.cpp cpudefs.cpp) -add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu) +#add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu) +add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu) + +add_executable(gencomp ../uae_cpu/compiler/gencomp.c ../uae_cpu/readcpu.cpp cpudefs.cpp) + +add_custom_command(OUTPUT compemu.cpp compstbl.cpp comptbl.h COMMAND gencomp DEPENDS gencomp) set(BasiliskII_SRCS ../main.cpp @@ -76,11 +81,16 @@ set(BasiliskII_SRCS ../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp ../uae_cpu/readcpu.cpp - ../uae_cpu/fpu/fpu_uae.cpp + ../uae_cpu/fpu/fpu_ieee.cpp cpustbl.cpp cpudefs.cpp cpuemu.cpp - cpufunctbl.cpp + compemu.cpp + compstbl.cpp + ../uae_cpu/compiler/compemu_support.cpp + ../uae_cpu/compiler/compemu_fpp.cpp + cpustbl_nf.cpp + cpuemu_nf.cpp #addressing mode =direct -DDIRECT_ADDRESSING #includes ) @@ -88,10 +98,15 @@ set(BasiliskII_SRCS add_executable(BasiliskII ${BasiliskII_SRCS}) set_source_files_properties(${BasiliskII_SRCS} - PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"") + PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DCPU_x86_64 -DFIXED_ADDRESSING -DCPU_64_BIT -DNOFLAGS_SUPPORT -DFPU_IEEE -DUSE_JIT -DJIT -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS -DWINUAE_ARANYM -DUSE_JIT_FPU -DUSE_INLINING -DDATADIR=\\\".\\\"") + +# set_property(SOURCE compemu_support.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O0 ") target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY}) +SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 0x2000" ) + +add_definitions(-march=native) #keycodes -> ../SDL/keycodes diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 3affe236..60824593 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -57,6 +57,10 @@ using std::string; #include "sigsegv.h" #include "rpc.h" +#if USE_JIT +extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp +#endif + #define DEBUG 0 #include "debug.h" @@ -166,12 +170,6 @@ static int vm_acquire_mac_fixed(void *addr, size_t size) static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip) { const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip); -#if ENABLE_VOSF - // Handle screen fault - extern bool Screen_fault_handler(sigsegv_info_t *sip); - if (Screen_fault_handler(sip)) - return SIGSEGV_RETURN_SUCCESS; -#endif #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION // Ignore writes to ROM @@ -199,10 +197,13 @@ static void sigsegv_dump_state(sigsegv_info_t *sip) fprintf(stderr, " [IP=%p]", fault_instruction); fprintf(stderr, "\n"); #if EMULATED_68K - extern void m68k_dumpstate (FILE *, uaecptr *); - m68k_dumpstate(stderr, 0); + extern void m68k_dumpstate (uaecptr *); + m68k_dumpstate(0); +#endif +#if USE_JIT && JIT_DEBUG + extern void compiler_dumpstate(void); + compiler_dumpstate(); #endif - VideoQuitFullScreen(); QuitEmulator(); @@ -652,7 +653,10 @@ void QuitEmulator(void) void FlushCodeCache(void *start, uint32 size) { - +#if USE_JIT + if (UseJIT) + flush_icache_range((uint8 *)start, size); +#endif } diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index 56b7a71d..68deb7b6 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -21,7 +21,9 @@ #ifndef SYSDEPS_H #define SYSDEPS_H - +#ifndef UNUSED +#define UNUSED(x) ((void)x) +#endif #if 1 @@ -35,9 +37,6 @@ /* Define if your system supports TUN/TAP devices. */ /* #undef ENABLE_TUNTAP */ -/* Define if using video enabled on SEGV signals. */ -#define ENABLE_VOSF 1 - /* Define to 1 if you have the header file. */ #define HAVE_ARPA_INET_H 1 diff --git a/BasiliskII/src/include/main.h b/BasiliskII/src/include/main.h index b55ddc6d..1ba7b6ac 100644 --- a/BasiliskII/src/include/main.h +++ b/BasiliskII/src/include/main.h @@ -31,6 +31,13 @@ extern int FPUType; // Flag: 24-bit-addressing? extern bool TwentyFourBitAddressing; +// 68k register structure (for Execute68k()) +struct M68kRegisters { + uint32 d[8]; + uint32 a[8]; + uint16 sr; +}; + // General functions extern bool InitAll(const char *vmdir); extern void ExitAll(void); diff --git a/BasiliskII/src/include/prefs.h b/BasiliskII/src/include/prefs.h index 216137f2..bce4a6e0 100644 --- a/BasiliskII/src/include/prefs.h +++ b/BasiliskII/src/include/prefs.h @@ -53,12 +53,6 @@ extern int32 PrefsFindInt32(const char *name); extern void PrefsRemoveItem(const char *name, int index = 0); -#ifdef SHEEPSHAVER -// Platform specific functions: -extern void prefs_init(); -extern void prefs_exit(); -#endif - /* * Definition of preferences items */ diff --git a/BasiliskII/src/prefs.cpp b/BasiliskII/src/prefs.cpp index 434992ce..27131b74 100644 --- a/BasiliskII/src/prefs.cpp +++ b/BasiliskII/src/prefs.cpp @@ -121,11 +121,6 @@ void PrefsInit(const char *vmdir, int &argc, char **&argv) argc -= k; } } - -#ifdef SHEEPSHAVER - // System specific initialization - prefs_init(); -#endif } @@ -135,11 +130,6 @@ void PrefsInit(const char *vmdir, int &argc, char **&argv) void PrefsExit(void) { -#ifdef SHEEPSHAVER - // System specific deinitialization - prefs_exit(); -#endif - // Free prefs list prefs_node *p = the_prefs, *next; while (p) { diff --git a/BasiliskII/src/prefs_items.cpp b/BasiliskII/src/prefs_items.cpp index afb692b9..4a7f1a34 100644 --- a/BasiliskII/src/prefs_items.cpp +++ b/BasiliskII/src/prefs_items.cpp @@ -92,7 +92,17 @@ void AddPrefsDefaults(void) PrefsAddBool("noclipconversion", false); PrefsAddBool("nogui", false); +#if USE_JIT + // JIT compiler specific options + PrefsAddBool("jit", true); + PrefsAddBool("jitfpu", true); + PrefsAddBool("jitdebug", false); + PrefsAddInt32("jitcachesize", 8192); + PrefsAddBool("jitlazyflush", true); + PrefsAddBool("jitinline", true); +#else PrefsAddBool("jit", false); +#endif PrefsAddInt32("keyboardtype", 5); } diff --git a/BasiliskII/src/uae_cpu/Makefile.am b/BasiliskII/src/uae_cpu/Makefile.am deleted file mode 100644 index 0f27219d..00000000 --- a/BasiliskII/src/uae_cpu/Makefile.am +++ /dev/null @@ -1,80 +0,0 @@ -# -# Note: this Makefile only contains rules for the source -# generator tools. -# - -# -# suppress warnings about overriding LDFLAGS and CPPFLAGS -# -AUTOMAKE_OPTIONS = -Wno-gnu - -AM_CPPFLAGS = $(DEFINES) \ - "-I$(srcdir)/../include" \ - "-I$(srcdir)/../Unix" \ - "-I$(builddir)/.." \ - "-I$(builddir)" \ - "-I$(srcdir)" - -CC = $(CC_FOR_BUILD) -CXX = $(CXX_FOR_BUILD) - -LDFLAGS = $(LDFLAGS_FOR_BUILD) -CPPFLAGS = $(CPPFLAGS_FOR_BUILD) -CFLAGS = $(CFLAGS_FOR_BUILD) -CXXFLAGS = $(CXXFLAGS_FOR_BUILD) -LIBS=-lm - -CFLAGS_NOWARN = $(DBGSP) -AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS) -AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS) - -noinst_PROGRAMS = build68k gencpu -if USE_JIT -noinst_PROGRAMS += gencomp -endif - -BUILT_SOURCES = \ - cpudefs.cpp \ - cpuemu.cpp \ - cpustbl.cpp \ - cpufunctbl.cpp \ - cputbl.h \ - $(empty) - -build68k_SOURCES = build68k.c -gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp -gencomp_SOURCES = -if GENCOMP_ARCH_X86 -gencomp_SOURCES += compiler/gencomp.c -endif -if GENCOMP_ARCH_ARM -gencomp_SOURCES += compiler/gencomp_arm.c -endif -gencomp_SOURCES += readcpu.cpp cpudefs.cpp - -if USE_JIT -BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h -endif - - -cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k - ./build68k <$(srcdir)/table68k > $@ -cpuemu.cpp: gencpu$(EXEEXT) - ./gencpu$(EXEEXT) -cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp -compemu.cpp: gencomp$(EXEEXT) - ./gencomp$(EXEEXT) -compstbl.cpp comptbl.h: compemu.cpp - -CLEANFILES = $(BUILT_SOURCES) - -EXTRA_DIST = \ - table68k \ - compiler/codegen_arm.cpp compiler/codegen_arm.h \ - compiler/compemu_midfunc_arm.cpp compiler/compemu_midfunc_arm.h \ - compiler/compemu_midfunc_arm2.cpp compiler/compemu_midfunc_arm2.h \ - compiler/test_codegen_arm.c \ - compiler/codegen_x86.cpp compiler/codegen_x86.h \ - compiler/compemu_midfunc_x86.cpp compiler/compemu_midfunc_x86.h \ - compiler/test_codegen_x86.cpp \ - $(empty) diff --git a/BasiliskII/src/uae_cpu/aranym_glue.cpp b/BasiliskII/src/uae_cpu/aranym_glue.cpp deleted file mode 100644 index 7148d446..00000000 --- a/BasiliskII/src/uae_cpu/aranym_glue.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * aranym_glue.cpp - CPU interface - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" - -#include "cpu_emulation.h" -#include "newcpu.h" -#include "hardware.h" -#include "input.h" -#ifdef USE_JIT -# include "compiler/compemu.h" -#endif -#include "nf_objs.h" - -#include "debug.h" - -// RAM and ROM pointers -memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important -uint8 *RAMBaseHost; // RAM base (host address space) -uint32 RAMSize = 0x00e00000; // Size of RAM - -memptr ROMBase = 0x00e00000; // ROM base (Atari address space) -uint8 *ROMBaseHost; // ROM base (host address space) -uint32 ROMSize = 0x00100000; // Size of ROM - -uint32 RealROMSize; // Real size of ROM - -memptr HWBase = 0x00f00000; // HW base (Atari address space) -uint8 *HWBaseHost; // HW base (host address space) -uint32 HWSize = 0x00100000; // Size of HW space - -memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space) -uint8 *FastRAMBaseHost; // Fast-RAM base (host address space) - -#ifdef HW_SIGSEGV -uint8 *FakeIOBaseHost; -#endif - -#ifdef FIXED_VIDEORAM -memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space) -#else -memptr VideoRAMBase; // VideoRAM base (Atari address space) -#endif -uint8 *VideoRAMBaseHost;// VideoRAM base (host address space) -//uint32 VideoRAMSize; // Size of VideoRAM - -#ifndef NOT_MALLOC -uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent -uintptr ROMBaseDiff; -uintptr FastRAMBaseDiff; -#endif - -uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap - -// From newcpu.cpp -extern int quit_program; - -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) -SDL_mutex *spcflags_lock; -#endif -#if defined(ENABLE_REALSTOP) -SDL_cond *stop_condition; -#endif - - -/* - * Initialize 680x0 emulation - */ - -bool InitMEM() { - InitMEMBaseDiff(RAMBaseHost, RAMBase); - InitROMBaseDiff(ROMBaseHost, ROMBase); - InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase); - InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase); - return true; -} - -bool Init680x0(void) -{ - init_m68k(); - -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) - if ((spcflags_lock = SDL_CreateMutex()) == NULL) { - panicbug("Error by SDL_CreateMutex()"); - exit(EXIT_FAILURE); - } -#endif - -#if ENABLE_REALSTOP - if ((stop_condition = SDL_CreateCond()) == NULL) { - panicbug("Error by SDL_CreateCond()"); - exit(EXIT_FAILURE); - } -#endif - -#ifdef USE_JIT - if (bx_options.jit.jit) compiler_init(); -#endif - return true; -} - -/* - * Instr. RESET - */ - -void AtariReset(void) -{ - // reset Atari hardware here - HWReset(); - // reset NatFeats here - NFReset(); - // reset the input devices (input.cpp) - InputReset(); - -} - -/* - * Reset CPU - */ - -void Reset680x0(void) -{ - m68k_reset(); -} - -/* - * Deinitialize 680x0 emulation - */ - -void Exit680x0(void) -{ -#ifdef USE_JIT - if (bx_options.jit.jit) compiler_exit(); -#endif - exit_m68k(); -} - - -/* - * Reset and start 680x0 emulation - */ - -void Start680x0(void) -{ - m68k_reset(); -#ifdef USE_JIT - if (bx_options.jit.jit) { - m68k_compile_execute(); - } - else -#endif - m68k_execute(); -} - -/* - * Restart running 680x0 emulation safely from different thread - */ -void Restart680x0(void) -{ - quit_program = 2; - TriggerNMI(); -} - -/* - * Quit 680x0 emulation safely from different thread - */ -void Quit680x0(void) -{ - quit_program = 1; - TriggerNMI(); -} - - -int MFPdoInterrupt(void) -{ - return getMFP()->doInterrupt(); -} - -int SCCdoInterrupt(void) -{ - return getSCC()->doInterrupt(); -} - -/* - * Trigger interrupts - */ -void TriggerInternalIRQ(void) -{ - SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ ); -} - -void TriggerInt3(void) -{ - SPCFLAGS_SET( SPCFLAG_INT3 ); -} - -void TriggerVBL(void) -{ - SPCFLAGS_SET( SPCFLAG_VBL ); -} - -void TriggerInt5(void) -{ - SPCFLAGS_SET( SPCFLAG_INT5 ); -} - -void TriggerSCC(bool enable) -{ - if (enable) - SPCFLAGS_SET( SPCFLAG_SCC ); - else - SPCFLAGS_CLEAR( SPCFLAG_SCC ); -} - -void TriggerMFP(bool enable) -{ - if (enable) - SPCFLAGS_SET( SPCFLAG_MFP ); - else - SPCFLAGS_CLEAR( SPCFLAG_MFP ); -} - -void TriggerNMI(void) -{ - SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI -} - -#ifndef REBOOT_OR_HALT -#define REBOOT_OR_HALT 0 // halt by default -#endif - -#if REBOOT_OR_HALT == 1 -# define CPU_MSG "CPU: Rebooting" -# define CPU_ACTION Restart680x0() -#else -# define CPU_MSG "CPU: Halting" -# define CPU_ACTION Quit680x0() -#endif - -#ifdef ENABLE_EPSLIMITER - -#ifndef EPS_LIMIT -# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */ -#endif - -void check_eps_limit(uaecptr pc) -{ - static long last_exception_time=-1; - static long exception_per_sec=0; - static long exception_per_sec_pc=0; - static uaecptr prevpc = 0; - - if (bx_options.cpu.eps_enabled) { - if (last_exception_time == -1) { - last_exception_time = SDL_GetTicks(); - } - - exception_per_sec++; - - if (pc == prevpc) { - /* BUS ERRORs occur at the same PC - watch out! */ - exception_per_sec_pc++; - } - else { - exception_per_sec_pc = 0; - prevpc = pc; - } - - if (SDL_GetTicks() - last_exception_time > 1000) { - last_exception_time = SDL_GetTicks(); - if (exception_per_sec_pc > bx_options.cpu.eps_max || - exception_per_sec > EPS_LIMIT /* make it configurable */) { - panicbug("CPU: Exception per second limit reached: %ld/%ld", - exception_per_sec_pc, exception_per_sec); - /* would be cool to open SDL dialog here: */ - /* [Exception per seconds limit reached. XXXXX exception - occured in the last second. The limit is set to YYYYY - in your config file. Do you want to continue emulation, - reset ARAnyM or quit ?][Continue] [Reset] [Quit] - */ - panicbug(CPU_MSG); - CPU_ACTION; - } - exception_per_sec = 0; - exception_per_sec_pc = 0; - } - } -} -#endif - -void report_double_bus_error() -{ - panicbug("CPU: Double bus fault detected !"); - /* would be cool to open SDL dialog here: */ - /* [Double bus fault detected. The emulated system crashed badly. - Do you want to reset ARAnyM or quit ?] [Reset] [Quit]" - */ - panicbug(CPU_MSG); - CPU_ACTION; -} - -#ifdef FLIGHT_RECORDER -extern bool cpu_flight_recorder_active; -void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; } -#endif diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index 1b03160a..b29c7702 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -264,5 +264,3 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) r->a[i] = m68k_areg(regs, i); quit_program = false; } - -void report_double_bus_error() {} diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index e996758d..8ec3ab55 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -1,43 +1,31 @@ -/* - * build68k.c - m68k CPU builder - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ /* * UAE - The Un*x Amiga Emulator * * Read 68000 CPU specs from file "table68k" and build table68k.c * * Copyright 1995,1996 Bernd Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "readcpu.h" - -#include -#include -#include -#include #include -#undef abort +#include +#include + +#include "sysdeps.h" +#include "readcpu.h" static FILE *tablef; static int nextch = 0; @@ -77,15 +65,15 @@ static int nextchtohex(void) } } -int main() +int main(int argc, char **argv) { int no_insns = 0; printf ("#include \"sysdeps.h\"\n"); printf ("#include \"readcpu.h\"\n"); printf ("struct instr_def defs68k[] = {\n"); -#if 0 - tablef = fopen("table68k","r"); +#ifdef WIN32 + tablef = fopen(argc > 1 ? argv[1] : "table68k","r"); if (tablef == NULL) { fprintf(stderr, "table68k not found\n"); exit(1); @@ -134,8 +122,8 @@ int main() case 'r': currbit = bitr; break; case 'R': currbit = bitR; break; case 'z': currbit = bitz; break; - case 'E': currbit = bitE; break; - case 'p': currbit = bitp; break; + case 'E': currbit = bitE; break; + case 'p': currbit = bitp; break; default: abort(); } if (!(bitmask & 1)) { @@ -150,7 +138,6 @@ int main() patbits[i] = nextch; getnextch(); } - (void) patbits; while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */ getnextch(); @@ -185,8 +172,6 @@ int main() getnextch(); switch(nextch){ case '-': flagset[i] = fa_unset; break; - case '/': flagset[i] = fa_isjmp; break; - case '+': flagset[i] = fa_isbranch; break; case '0': flagset[i] = fa_zero; break; case '1': flagset[i] = fa_one; break; case 'x': flagset[i] = fa_dontcare; break; @@ -206,8 +191,6 @@ int main() getnextch(); switch(nextch){ case '-': flaguse[i] = fu_unused; break; - case '/': flaguse[i] = fu_isjmp; break; - case '+': flaguse[i] = fu_maybecc; break; case '?': flaguse[i] = fu_unknown; break; default: flaguse[i] = fu_used; break; } @@ -252,7 +235,7 @@ int main() if (nextch != ':') abort(); - assert(fgets(opcstr, 250, tablef) != NULL); + fgets(opcstr, 250, tablef); getnextch(); { int j; @@ -260,12 +243,12 @@ int main() char *opstrp = opcstr, *osendp; int slen = 0; - while (isspace((int)*opstrp)) + while (isspace(*opstrp)) opstrp++; osendp = opstrp; while (*osendp) { - if (!isspace ((int)*osendp)) + if (!isspace (*osendp)) slen = osendp - opstrp + 1; osendp++; } @@ -288,5 +271,6 @@ int main() } } printf("};\nint n_defs68k = %d;\n", no_insns); + fflush(stdout); return 0; } diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp index 32e6982a..24cfb548 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp @@ -3629,7 +3629,7 @@ enum { X86_PROCESSOR_max }; -#if defined(UAE) || (defined(DEBUG) && DEBUG) +// #if defined(UAE) || (defined(DEBUG) && DEBUG) static const char * x86_processor_string_table[X86_PROCESSOR_max] = { "80386", "80486", @@ -3640,7 +3640,7 @@ static const char * x86_processor_string_table[X86_PROCESSOR_max] = { "Pentium4", "x86-64" }; -#endif +// #endif static struct ptt { const int align_loop; @@ -3890,7 +3890,7 @@ raw_init_cpu(void) } #ifndef UAE -static void __attribute_noinline__ prevent_redzone_use(void) {} +static void inline prevent_redzone_use(void) {} static bool target_check_bsf(void) { diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h index 6e3abb1e..15edd102 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -42,7 +42,7 @@ typedef uae_u64 uintptr; typedef uae_u32 uintptr; #endif /* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */ -// #define USE_JIT +#define USE_JIT #endif #ifdef USE_JIT @@ -515,7 +515,7 @@ void jit_abort(const TCHAR *format, ...); #else #ifdef WINUAE_ARANYM -#define jit_log(format, ...) D(bug(format, ##__VA_ARGS__)) +#define jit_log(format, ...) write_log(format"\n", ##__VA_ARGS__) #define jit_log2(format, ...) D2(bug(format, ##__VA_ARGS__)) void jit_abort(const char *format,...) __attribute__((format(printf, 1, 2))) __attribute__((__noreturn__)); #else diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index c7b94244..62fcfd36 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -58,7 +58,7 @@ /* kludge for Brian, so he can compile under MSVC++ */ #define USE_NORMAL_CALLING_CONVENTION 0 -#include "sysconfig.h" +// #include "sysconfig.h" #include "sysdeps.h" #ifdef JIT @@ -71,6 +71,7 @@ #else #include "cpu_emulation.h" #include "main.h" +#include "prefs.h" #include "vm_alloc.h" #include "m68k.h" @@ -85,9 +86,14 @@ #include "compiler/compemu.h" #include "fpu/fpu.h" #include "fpu/flags.h" -#include "parameters.h" +// #include "parameters.h" #endif -#include "verify.h" +// #include "verify.h" + +// #define jit_log(format, ...) \ +// uae_log("JIT: " format "\n", ##__VA_ARGS__); +#define D2 D + #ifdef UAE #include "uae/log.h" @@ -174,7 +180,7 @@ void jit_abort(const char *format, ...) { va_list args; va_start(args, format); - ndebug::pdbvprintf(format, args); + vprintf(format, args); va_end(args); abort(); } @@ -254,6 +260,8 @@ extern int quit_program; // gb-- Extra data for Basilisk II/JIT #ifdef JIT_DEBUG static bool JITDebug = false; // Enable runtime disassemblers through mon? +#else +const bool JITDebug = false; #endif #if USE_INLINING #ifdef UAE @@ -504,7 +512,7 @@ static inline blockinfo* get_blockinfo_addr(void* addr) #if defined(CPU_arm) #define TARGET_NATIVE TARGET_ARM #endif -#include "disasm-glue.h" +// #include "disasm-glue.h" #ifdef JIT_DEBUG static void disasm_block(int disasm_target, const uint8 *start, size_t length) @@ -2642,13 +2650,13 @@ void compiler_init(void) #else #ifdef JIT_DEBUG // JIT debug mode ? - JITDebug = bx_options.jit.jitdebug; + JITDebug = PrefsFindBool("jitdebug"); #endif jit_log(" : enable runtime disassemblers : %s", JITDebug ? "yes" : "no"); #ifdef USE_JIT_FPU // Use JIT compiler for FPU instructions ? - avoid_fpu = !bx_options.jit.jitfpu; + avoid_fpu = !PrefsFindBool("jitfpu"); #else // JIT FPU is always disabled avoid_fpu = true; @@ -2656,7 +2664,7 @@ void compiler_init(void) jit_log(" : compile FPU instructions : %s", !avoid_fpu ? "yes" : "no"); // Get size of the translation cache (in KB) - cache_size = bx_options.jit.jitcachesize; + cache_size = PrefsFindInt32("jitcachesize"); jit_log(" : requested translation cache size : %d KB", cache_size); // Initialize target CPU (check for features, e.g. CMOV, rat stalls) @@ -2671,7 +2679,7 @@ void compiler_init(void) #endif // Translation cache flush mechanism - lazy_flush = (bx_options.jit.jitlazyflush == 0) ? false : true; + lazy_flush = PrefsFindBool("jitlazyflush"); jit_log(" : lazy translation cache invalidation : %s", str_on_off(lazy_flush)); flush_icache = lazy_flush ? flush_icache_lazy : flush_icache_hard; @@ -2680,7 +2688,7 @@ void compiler_init(void) jit_log(" : FP register aliasing : %s", str_on_off(USE_F_ALIAS)); jit_log(" : lazy constant offsetting : %s", str_on_off(USE_OFFSET)); #if USE_INLINING - follow_const_jumps = bx_options.jit.jitinline; + follow_const_jumps = PrefsFindBool("jitinline"); #endif jit_log(" : block inlining : %s", str_on_off(follow_const_jumps)); jit_log(" : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA)); @@ -2786,12 +2794,12 @@ void compiler_exit(void) bool compiler_use_jit(void) { // Check for the "jit" prefs item - if (!bx_options.jit.jit) + if (!PrefsFindBool("jit")) return false; // Don't use JIT if translation cache size is less then MIN_CACHE_SIZE KB - if (bx_options.jit.jitcachesize < MIN_CACHE_SIZE) { - panicbug(" : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE); + if (PrefsFindInt32("jitcachesize") < MIN_CACHE_SIZE) { + write_log(" : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE); return false; } @@ -3579,6 +3587,8 @@ void alloc_cache(void) } } +extern void op_illg_1 (uae_u32 opcode) REGPARAM; + static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2) { uae_u32 k1 = 0; @@ -3869,7 +3879,7 @@ static inline void create_popalls(void) r=REG_PC_TMP; compemu_raw_mov_l_rm(r, uae_p32(®s.pc_p)); compemu_raw_and_l_ri(r,TAGMASK); - verify(sizeof(cache_tags[0]) == sizeof(void *)); + assert(sizeof(cache_tags[0]) == sizeof(void *)); compemu_raw_jmp_m_indexed(uae_p32(cache_tags), r, sizeof(void *)); /* now the exit points */ @@ -4009,7 +4019,7 @@ static bool merge_blacklist() #ifdef UAE const char *blacklist = ""; #else - const char *blacklist = bx_options.jit.jitblacklist; + const char *blacklist = PrefsFindString("jitblacklist"); #endif if (blacklist[0] != '\0') { const char *p = blacklist; @@ -4346,38 +4356,86 @@ void flush_icache(int n) #ifdef UAE static #endif -void flush_icache_range(uae_u32 start, uae_u32 length) +// void flush_icache_range(uae_u32 start, uae_u32 length) +// { +// if (!active) +// return; + +// #if LAZY_FLUSH_ICACHE_RANGE +// uae_u8 *start_p = get_real_address(start); +// blockinfo *bi = active; +// while (bi) { +// #if USE_CHECKSUM_INFO +// bool invalidate = false; +// for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) +// invalidate = (((start_p - csi->start_p) < csi->length) || +// ((csi->start_p - start_p) < length)); +// #else +// // Assume system is consistent and would invalidate the right range +// const bool invalidate = (bi->pc_p - start_p) < length; +// #endif +// if (invalidate) { +// uae_u32 cl = cacheline(bi->pc_p); +// if (bi == cache_tags[cl + 1].bi) +// cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; +// bi->handler_to_use = (cpuop_func *)popall_execute_normal; +// set_dhtu(bi, bi->direct_pen); +// bi->status = BI_NEED_RECOMP; +// } +// bi = bi->next; +// } +// return; +// #else +// UNUSED(start); +// UNUSED(length); +// #endif +// flush_icache(-1); +// } + +void flush_icache_range(uae_u8 *start_p, uae_u32 length) { if (!active) return; #if LAZY_FLUSH_ICACHE_RANGE - uae_u8 *start_p = get_real_address(start); blockinfo *bi = active; while (bi) { #if USE_CHECKSUM_INFO - bool invalidate = false; - for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) - invalidate = (((start_p - csi->start_p) < csi->length) || - ((csi->start_p - start_p) < length)); + bool candidate = false; + for (checksum_info *csi = bi->csi; csi; csi = csi->next) { + if (((start_p - csi->start_p) < csi->length) || + ((csi->start_p - start_p) < length)) { + candidate = true; + break; + } + } #else // Assume system is consistent and would invalidate the right range - const bool invalidate = (bi->pc_p - start_p) < length; + const bool candidate = (bi->pc_p - start_p) < length; #endif - if (invalidate) { - uae_u32 cl = cacheline(bi->pc_p); - if (bi == cache_tags[cl + 1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; - bi->handler_to_use = (cpuop_func *)popall_execute_normal; - set_dhtu(bi, bi->direct_pen); - bi->status = BI_NEED_RECOMP; - } + blockinfo *dbi = bi; bi = bi->next; + if (candidate) { + uae_u32 cl = cacheline(dbi->pc_p); + if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) { + if (dbi == cache_tags[cl+1].bi) + cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; + dbi->handler_to_use = (cpuop_func *)popall_execute_normal; + set_dhtu(dbi, dbi->direct_pen); + dbi->status = BI_INVALID; + } + else { + if (dbi == cache_tags[cl+1].bi) + cache_tags[cl].handler = (cpuop_func *)popall_check_checksum; + dbi->handler_to_use = (cpuop_func *)popall_check_checksum; + set_dhtu(dbi, dbi->direct_pcc); + dbi->status = BI_NEED_CHECK; + } + remove_from_list(dbi); + add_to_dormant(dbi); + } } return; -#else - UNUSED(start); - UNUSED(length); #endif flush_icache(-1); } @@ -4631,7 +4689,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) comptbl=compfunctbl; } -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER { /* store also opcode to second register */ clobber_flags(); @@ -5008,7 +5066,7 @@ void exec_nostats(void) { for (;;) { uae_u32 opcode = GET_OPCODE; -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER m68k_record_step(m68k_getpc(), opcode); #endif (*cpufunctbl[opcode])(opcode); @@ -5038,7 +5096,7 @@ void execute_normal(void) for (;;) { /* Take note: This is the do-it-normal loop */ pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p; uae_u32 opcode = GET_OPCODE; -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER m68k_record_step(m68k_getpc(), opcode); #endif (*cpufunctbl[opcode])(opcode); @@ -5082,7 +5140,7 @@ setjmpagain: for (;;) { if (quit_program > 0) { if (quit_program == 1) { -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER dump_flight_recorder(); #endif break; diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index a7c4ee2b..febeddc9 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -28,7 +28,8 @@ */ #define CC_FOR_BUILD 1 -#include "sysconfig.h" +// #include "sysconfig.h" +#define WINUAE_ARANYM #include "sysdeps.h" #include "readcpu.h" @@ -3101,10 +3102,10 @@ gen_opcode (unsigned int opcode) failure; break; - case i_NATFEAT_ID: - case i_NATFEAT_CALL: - failure; - break; + // case i_NATFEAT_ID: + // case i_NATFEAT_CALL: + // failure; + // break; case i_MMUOP: isjump; @@ -3127,7 +3128,7 @@ gen_opcode (unsigned int opcode) static void generate_includes (FILE * f) { - fprintf (f, "#include \"sysconfig.h\"\n"); + // fprintf (f, "#include \"sysconfig.h\"\n"); fprintf (f, "#if defined(JIT)\n"); fprintf (f, "#include \"sysdeps.h\"\n"); #ifdef UAE diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c index 13e2776e..e9bf9bb4 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c @@ -50,7 +50,7 @@ */ #define CC_FOR_BUILD 1 -#include "sysconfig.h" +// #include "sysconfig.h" #include "sysdeps.h" #include "readcpu.h" diff --git a/BasiliskII/src/uae_cpu/cpu_emulation.h b/BasiliskII/src/uae_cpu/cpu_emulation.h index 2e926874..cd588ec1 100644 --- a/BasiliskII/src/uae_cpu/cpu_emulation.h +++ b/BasiliskII/src/uae_cpu/cpu_emulation.h @@ -1,7 +1,7 @@ /* - * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.8 version) + * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version) * - * Basilisk II (C) 1997-1999 Christian Bauer + * Basilisk II (C) 1997-2008 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,8 @@ #ifndef CPU_EMULATION_H #define CPU_EMULATION_H +#include + /* * Memory system @@ -35,15 +37,15 @@ extern uint32 ROMBaseMac; // ROM base (Mac address space) extern uint8 *ROMBaseHost; // ROM base (host address space) extern uint32 ROMSize; // Size of ROM -#if !REAL_ADDRESSING -// If we are not using real addressing, the Mac frame buffer gets mapped to this location -// The memory must be allocated by VideoInit(). If multiple monitors are used, they must -// share the frame buffer +#if !REAL_ADDRESSING && !DIRECT_ADDRESSING +// If we are not using real or direct addressing, the Mac frame buffer gets +// mapped to this location. The memory must be allocated by VideoInit(). +// If multiple monitors are used, they must share the frame buffer const uint32 MacFrameBaseMac = 0xa0000000; extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space) extern uint32 MacFrameSize; // Size of frame buffer -extern int MacFrameLayout; // Frame buffer layout (see defines below) #endif +extern int MacFrameLayout; // Frame buffer layout (see defines below) // Possible frame buffer layouts enum { @@ -78,15 +80,17 @@ static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return me // Initialization extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation extern void Exit680x0(void); +extern void InitFrameBufferMapping(void); + +// 680x0 dynamic recompilation activation flag +#if USE_JIT +extern bool UseJIT; +#else +const bool UseJIT = false; +#endif // 680x0 emulation functions -struct M68kRegisters { - uint32 d[8]; - memptr a[8]; - uint16 sr; - memptr usp, isp, msp; - memptr pc; -}; +struct M68kRegisters; extern void Start680x0(void); // Reset and start 680x0 extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine @@ -95,12 +99,4 @@ extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first) extern void TriggerNMI(void); // Trigger interrupt level 7 -// CPU looping handlers -void check_eps_limit(uaecptr); -void report_double_bus_error(void); - -extern int intlev(void); - -static inline void AtariReset(void) {} - #endif diff --git a/BasiliskII/src/uae_cpu/cpudefsa.cpp b/BasiliskII/src/uae_cpu/cpudefsa.cpp deleted file mode 100644 index ad7d6979..00000000 --- a/BasiliskII/src/uae_cpu/cpudefsa.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * cpudefs.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "cpudefs.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1.cpp b/BasiliskII/src/uae_cpu/cpuemu1.cpp deleted file mode 100644 index 089eefd4..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu1.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_1 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp deleted file mode 100644 index 58acf444..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_1 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2.cpp b/BasiliskII/src/uae_cpu/cpuemu2.cpp deleted file mode 100644 index 1e18b587..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu2.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_2 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp deleted file mode 100644 index 8e5136c4..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_2 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3.cpp b/BasiliskII/src/uae_cpu/cpuemu3.cpp deleted file mode 100644 index 0385e2f0..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu3.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_3 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp deleted file mode 100644 index 6565dc8c..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_3 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4.cpp b/BasiliskII/src/uae_cpu/cpuemu4.cpp deleted file mode 100644 index 13d27e7a..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu4.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_4 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp deleted file mode 100644 index a16c36cb..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_4 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5.cpp b/BasiliskII/src/uae_cpu/cpuemu5.cpp deleted file mode 100644 index 9b33a654..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu5.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_5 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp deleted file mode 100644 index 5bf24360..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#define NOFLAGS 1 -#define PART_5 -#include "cpuemu.cpp" - diff --git a/BasiliskII/src/uae_cpu/cpuemu6.cpp b/BasiliskII/src/uae_cpu/cpuemu6.cpp deleted file mode 100644 index e4b1efb0..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu6.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_6 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp deleted file mode 100644 index 7afe15d4..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_6 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7.cpp b/BasiliskII/src/uae_cpu/cpuemu7.cpp deleted file mode 100644 index faec7ef8..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu7.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_7 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp deleted file mode 100644 index 1e404dea..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_7 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8.cpp b/BasiliskII/src/uae_cpu/cpuemu8.cpp deleted file mode 100644 index c4efcfa3..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu8.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_8 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp deleted file mode 100644 index 7c7f8f6e..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_8 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpufunctbla.cpp b/BasiliskII/src/uae_cpu/cpufunctbla.cpp deleted file mode 100644 index 17dd0d3f..00000000 --- a/BasiliskII/src/uae_cpu/cpufunctbla.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * cpufunctbl.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "cpufunctbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpummu.cpp b/BasiliskII/src/uae_cpu/cpummu.cpp deleted file mode 100644 index 1630bc78..00000000 --- a/BasiliskII/src/uae_cpu/cpummu.cpp +++ /dev/null @@ -1,1096 +0,0 @@ -/* - * cpummu.cpp - MMU emulation - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by UAE MMU patch - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define DEBUG 0 -#include "sysdeps.h" - -#include "cpummu.h" -#include "memory.h" -#include "newcpu.h" -#include "debug.h" -#ifdef USE_JIT -# include "compiler/compemu.h" -#endif - -#define DBG_MMU_VERBOSE 1 -#define DBG_MMU_SANITY 1 - -#ifdef FULLMMU - -mmu_atc_l1_array atc_l1[2]; -mmu_atc_l1_array *current_atc; -struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; - -# ifdef ATC_STATS -static unsigned int mmu_atc_hits[ATC_L2_SIZE]; -# endif - - -static void mmu_dump_ttr(const char * label, uae_u32 ttr) -{ - DUNUSED(label); -#if DEBUG - uae_u32 from_addr, to_addr; - - from_addr = ttr & MMU_TTR_LOGICAL_BASE; - to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8; - - D(bug("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d", - label, ttr, - from_addr, to_addr, - ttr & MMU_TTR_BIT_ENABLED ? 1 : 0, - (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT, - ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0, - (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT - )); -#else - DUNUSED(ttr); -#endif -} - -void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode) -{ - uae_u32 * ttr; - uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0; - uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1; - - if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0) - ttr = ttr1; - else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0) - ttr = ttr0; - else - return; - - *ttr = baseaddr & MMU_TTR_LOGICAL_BASE; - *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8; - *ttr |= MMU_TTR_BIT_ENABLED; - - D(bug("MMU: map transparent mapping of %08x", *ttr)); -} - -/* check if an address matches a ttr */ -static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, int super) -{ - if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ - uae_u8 msb, mask; - - msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; - mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; - - if (!(msb & ~mask)) { - - if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { - if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { - return TTR_NO_MATCH; - } - } - - return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; - } - } - return TTR_NO_MATCH; -} - -static inline int mmu_match_ttr(uaecptr addr, int super, int data) -{ - int res; - - if (data) { - res = mmu_do_match_ttr(regs.dtt0, addr, super); - if (res == TTR_NO_MATCH) - res = mmu_do_match_ttr(regs.dtt1, addr, super); - } else { - res = mmu_do_match_ttr(regs.itt0, addr, super); - if (res == TTR_NO_MATCH) - res = mmu_do_match_ttr(regs.itt1, addr, super); - } - return res; -} - -#if DEBUG -/* {{{ mmu_dump_table */ -static void mmu_dump_table(const char * label, uaecptr root_ptr) -{ - DUNUSED(label); - const int ROOT_TABLE_SIZE = 128, - PTR_TABLE_SIZE = 128, - PAGE_TABLE_SIZE = regs.mmu_pagesize_8k ? 32 : 64, - ROOT_INDEX_SHIFT = 25, - PTR_INDEX_SHIFT = 18; - const uae_u32 ptr_addr_mask = (regs.mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4); - const uae_u32 page_addr_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4); - const uae_u32 page_ur_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4); - const uae_u32 page_size = (regs.mmu_pagesize_8k ? (1 << 13) : (1 << 12)); - int root_idx, ptr_idx, page_idx; - uae_u32 root_des, ptr_des, page_des; - uaecptr ptr_des_addr, page_addr, - root_log, ptr_log, page_log; - - D(bug("%s: root=%x", label, root_ptr)); - - for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) { - root_des = phys_get_long(root_ptr + (root_idx << 2)); - - if ((root_des & 2) == 0) - continue; /* invalid */ - - D(bug("ROOT: %03d U=%d W=%d UDT=%02d", root_idx, - root_des & 8 ? 1 : 0, - root_des & 4 ? 1 : 0, - root_des & 3 - )); - - root_log = root_idx << ROOT_INDEX_SHIFT; - - ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK; - - for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) { - struct { - uaecptr log, phys; - int start_idx, n_pages; /* number of pages covered by this entry */ - uae_u32 match; - } page_info[PAGE_TABLE_SIZE]; - int n_pages_used; - - ptr_des = phys_get_long(ptr_des_addr + (ptr_idx << 2)); - ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT); - - if ((ptr_des & 2) == 0) - continue; /* invalid */ - - page_addr = ptr_des & ptr_addr_mask; - - n_pages_used = -1; - for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) { - - page_des = phys_get_long(page_addr + (page_idx << 2)); - page_log = ptr_log | (page_idx * page_size); - - switch (page_des & 3) { - case 0: /* invalid */ - continue; - case 1: case 3: /* resident */ - case 2: /* indirect */ - if (n_pages_used == -1 || - (page_info[n_pages_used].match & ~page_addr_mask) != (page_des & ~page_addr_mask) || - page_info[n_pages_used].phys + (page_info[n_pages_used].n_pages * page_size) != (page_des & page_addr_mask)) - { - /* use the next entry */ - n_pages_used++; - - page_info[n_pages_used].match = page_des; - page_info[n_pages_used].n_pages = 1; - page_info[n_pages_used].start_idx = page_idx; - page_info[n_pages_used].log = page_log; - page_info[n_pages_used].phys = page_des & page_addr_mask; - } else { - page_info[n_pages_used].n_pages++; - } - break; - } - } - - if (n_pages_used == -1) - continue; - - D(bug(" PTR: %03d U=%d W=%d UDT=%02d", ptr_idx, - ptr_des & 8 ? 1 : 0, - ptr_des & 4 ? 1 : 0, - ptr_des & 3 - )); - - - for (page_idx = 0; page_idx <= n_pages_used; page_idx++) { - page_des = page_info[page_idx].match; - - if ((page_des & MMU_PDT_MASK) == 2) { - D(bug(" PAGE: %03d-%03d log=%08x INDIRECT --> addr=%08x", - page_info[page_idx].start_idx, - page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, - page_info[page_idx].log, - page_des & MMU_PAGE_INDIRECT_MASK - )); - - } else { - D(bug(" PAGE: %03d-%03d log=%08x addr=%08x UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d", - page_info[page_idx].start_idx, - page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, - page_info[page_idx].log, - page_info[page_idx].phys, - (page_des & page_ur_mask) >> MMU_PAGE_UR_SHIFT, - page_des & MMU_DES_GLOBAL ? 1 : 0, - (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT, - page_des & MMU_DES_SUPER ? 1 : 0, - (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT, - page_des & MMU_DES_MODIFIED ? 1 : 0, - page_des & MMU_DES_USED ? 1 : 0, - page_des & MMU_DES_WP ? 1 : 0 - )); - } - } - } - - } -} -/* }}} */ -#endif - -/* {{{ mmu_dump_atc */ -void mmu_dump_atc(void) -{ - int i, j; - for (i = 0; i < 2; i++) { - for (j = 0; j < ATC_L2_SIZE; j++) { - if (atc_l2[i][j].tag == 0x8000) - continue; - D(bug("ATC[%02d] G=%d TT=%d M=%d WP=%d VD=%d VI=%d tag=%08x --> phys=%08x", - j, atc_l2[i][j].global, atc_l2[i][j].tt, atc_l2[i][j].modified, - atc_l2[i][j].write_protect, atc_l2[i][j].valid_data, atc_l2[i][j].valid_inst, - atc_l2[i][j].tag, atc_l2[i][j].phys)); - } - } -} -/* }}} */ - -/* {{{ mmu_dump_tables */ -void mmu_dump_tables(void) -{ - D(bug("URP: %08x SRP: %08x MMUSR: %x TC: %x", regs.urp, regs.srp, regs.mmusr, regs.tc)); - mmu_dump_ttr("DTT0", regs.dtt0); - mmu_dump_ttr("DTT1", regs.dtt1); - mmu_dump_ttr("ITT0", regs.itt0); - mmu_dump_ttr("ITT1", regs.itt1); - mmu_dump_atc(); - //mmu_dump_table("SRP", regs.srp); -} -/* }}} */ - -static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write); - -static ALWAYS_INLINE int mmu_get_fc(bool super, bool data) -{ - return (super ? 4 : 0) | (data ? 1 : 2); -} - -static void mmu_bus_error(uaecptr addr, int fc, int write, int size) -{ - uae_u16 ssw = 0; - - ssw |= fc & MMU_SSW_TM; /* Copy TM */ - switch (size) { - case sz_byte: - ssw |= MMU_SSW_SIZE_B; - break; - case sz_word: - ssw |= MMU_SSW_SIZE_W; - break; - case sz_long: - ssw |= MMU_SSW_SIZE_L; - break; - } - - regs.wb3_status = write ? 0x80 | ssw : 0; - if (!write) - ssw |= MMU_SSW_RW; - - regs.mmu_fault_addr = addr; - regs.mmu_ssw = ssw | MMU_SSW_ATC; - - D(bug("BUS ERROR: fc=%d w=%d log=%08x ssw=%04x", fc, write, addr, ssw)); - - breakpt(); - THROW(2); -} - -/* - * Update the atc line for a given address by doing a mmu lookup. - */ -static uaecptr mmu_fill_atc_l2(uaecptr addr, int super, int data, int write, - struct mmu_atc_line *l) -{ - int res; - uae_u32 desc; - - l->tag = ATC_TAG(addr); - l->hw = l->bus_fault = 0; - - /* check ttr0 */ - res = mmu_match_ttr(addr, super, data); - if (res != TTR_NO_MATCH) { - l->tt = 1; - if (data) { - l->valid_data = 1; - l->valid_inst = mmu_match_ttr(addr, super, 0) == res; - } else { - l->valid_inst = 1; - l->valid_data = mmu_match_ttr(addr, super, 1) == res; - } - l->global = 1; - l->modified = 1; - l->write_protect = (res == TTR_NO_WRITE); - l->phys = 0; - - return 0; - } - - l->tt = 0; - if (!regs.mmu_enabled) { - l->valid_data = l->valid_inst = 1; - l->global = 1; - l->modified = 1; - l->write_protect = 0; - l->phys = 0; - return 0; - } - - SAVE_EXCEPTION; - TRY(prb) { - desc = mmu_lookup_pagetable(addr, super, write); - D(bug("translate: %x,%u,%u,%u -> %x", addr, super, write, data, desc)); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - /* bus error during table search */ - desc = 0; - goto fail; - } - - if ((desc & 1) == 0 || (!super && desc & MMU_MMUSR_S)) { - fail: - l->valid_data = l->valid_inst = 0; - l->global = 0; - } else { - l->valid_data = l->valid_inst = 1; - if (regs.mmu_pagesize_8k) - l->phys = (desc & ~0x1fff) - (addr & ~0x1fff); - else - l->phys = (desc & ~0xfff) - (addr & ~0xfff); - l->global = (desc & MMU_MMUSR_G) != 0; - l->modified = (desc & MMU_MMUSR_M) != 0; - l->write_protect = (desc & MMU_MMUSR_W) != 0; - } - - return desc; -} - -static ALWAYS_INLINE bool -mmu_fill_atc_l1(uaecptr addr, int super, int data, int write, - struct mmu_atc_line *l1) -{ - int idx = ATC_L2_INDEX(addr); - int tag = ATC_TAG(addr); - struct mmu_atc_line *l = &atc_l2[super][idx]; - uaecptr phys_addr; - - if (l->tag != tag) { - restart: - mmu_fill_atc_l2(addr, super, data, write, l); - } - if (!(data ? l->valid_data : l->valid_inst)) { - D(bug("MMU: non-resident page (%x,%x,%x)!", addr, regs.pc, regs.fault_pc)); - goto fail; - } - if (write) { - if (l->write_protect) { - D(bug("MMU: write protected (via %s) %x", l->tt ? "ttr" : "atc", addr)); - goto fail; - } - if (!l->modified) - goto restart; - } - *l1 = *l; - - phys_addr = addr + l1->phys; - if ((phys_addr & 0xfff00000) == 0x00f00000) { - l1->hw = 1; - goto fail; - } - if ((phys_addr & 0xfff00000) == 0xfff00000) { - l1->hw = 1; - l1->phys -= 0xff000000; - goto fail; - } - - if (!test_ram_boundary(phys_addr, 1, super, write)) { - l1->bus_fault = 1; - goto fail; - } - - return true; - -fail: - l1->tag = ~l1->tag; - return false; -} - -uaecptr mmu_translate(uaecptr addr, int super, int data, int write) -{ - struct mmu_atc_line *l; - - l = &atc_l2[super][ATC_L2_INDEX(addr)]; - mmu_fill_atc_l2(addr, super, data, write, l); - if (!(data ? l->valid_data : l->valid_inst)) - { - breakpt(); - THROW(2); - } - - return addr + l->phys; -} - -/* - * Lookup the address by walking the page table and updating - * the page descriptors accordingly. Returns the found descriptor - * or produces a bus error. - */ -static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write) -{ - uae_u32 desc, desc_addr, wp; - int i; - - wp = 0; - desc = super ? regs.srp : regs.urp; - - /* fetch root table descriptor */ - i = (addr >> 23) & 0x1fc; - desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; - desc = phys_get_long(desc_addr); - if ((desc & 2) == 0) { - D(bug("MMU: invalid root descriptor for %x", addr)); - return 0; - } - - wp |= desc; - if ((desc & MMU_DES_USED) == 0) - phys_put_long(desc_addr, desc | MMU_DES_USED); - - /* fetch pointer table descriptor */ - i = (addr >> 16) & 0x1fc; - desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; - desc = phys_get_long(desc_addr); - if ((desc & 2) == 0) { - D(bug("MMU: invalid ptr descriptor for %x", addr)); - return 0; - } - wp |= desc; - if ((desc & MMU_DES_USED) == 0) - phys_put_long(desc_addr, desc | MMU_DES_USED); - - /* fetch page table descriptor */ - if (regs.mmu_pagesize_8k) { - i = (addr >> 11) & 0x7c; - desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) | i; - } else { - i = (addr >> 10) & 0xfc; - desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) | i; - } - - desc = phys_get_long(desc_addr); - if ((desc & 3) == 2) { - /* indirect */ - desc_addr = desc & MMU_PAGE_INDIRECT_MASK; - desc = phys_get_long(desc_addr); - } - if ((desc & 1) == 0) { - D(bug("MMU: invalid page descriptor log=%08x desc=%08x @%08x", addr, desc, desc_addr)); - return desc; - } - - desc |= wp & MMU_DES_WP; - if (write) { - if (desc & MMU_DES_WP) { - if ((desc & MMU_DES_USED) == 0) { - desc |= MMU_DES_USED; - phys_put_long(desc_addr, desc); - } - } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) != - (MMU_DES_USED|MMU_DES_MODIFIED)) { - desc |= MMU_DES_USED|MMU_DES_MODIFIED; - phys_put_long(desc_addr, desc); - } - } else { - if ((desc & MMU_DES_USED) == 0) { - desc |= MMU_DES_USED; - phys_put_long(desc_addr, desc); - } - } - return desc; -} - -uae_u16 mmu_get_word_unaligned(uaecptr addr, int data) -{ - uae_u16 res; - - res = (uae_u16)mmu_get_byte(addr, data, sz_word) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_byte(addr + 1, data, sz_word); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - return res; -} - -uae_u32 mmu_get_long_unaligned(uaecptr addr, int data) -{ - uae_u32 res; - - if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_word(addr, data, sz_long) << 16; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_word(addr + 2, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } else { - res = (uae_u32)mmu_get_byte(addr, data, sz_long) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res = (res | mmu_get_byte(addr + 1, data, sz_long)) << 8; - res = (res | mmu_get_byte(addr + 2, data, sz_long)) << 8; - res |= mmu_get_byte(addr + 3, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } - return res; -} - -uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) - return HWget_b(cl->phys + addr); - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); - return 0; - } - - if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) - goto redo; - - return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); -} - -uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) - return HWget_w(cl->phys + addr); - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); - return 0; - } - - if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) - goto redo; - - return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); -} - -uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) - return HWget_l(cl->phys + addr); - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); - return 0; - } - - if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) - goto redo; - - return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); -} - - -uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, - struct mmu_atc_line *cl) -{ - uae_u64 h = mmu_get_long_slow(addr, super, data, sz_long, cl); - uae_u64 l = mmu_get_long_slow(addr + 4, super, data, sz_long, cl); - return (h << 32) | l; -} - -REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data) -{ - SAVE_EXCEPTION; - TRY(prb) { - if (likely(!(addr & 1))) { - mmu_put_word(addr, val >> 16, data, sz_long); - mmu_put_word(addr + 2, val, data, sz_long); - } else { - mmu_put_byte(addr, val >> 24, data, sz_long); - mmu_put_byte(addr + 1, val >> 16, data, sz_long); - mmu_put_byte(addr + 2, val >> 8, data, sz_long); - mmu_put_byte(addr + 3, val, data, sz_long); - } - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data) -{ - SAVE_EXCEPTION; - TRY(prb) { - mmu_put_byte(addr, val >> 8, data, sz_word); - mmu_put_byte(addr + 1, val, data, sz_word); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) { - HWput_b(cl->phys + addr, val); - return; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); - return; - } - - if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) - goto redo; - - do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); -} - -REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) { - HWput_w(cl->phys + addr, val); - return; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); - return; - } - - if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) - goto redo; - - do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); -} - -REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) { - HWput_l(cl->phys + addr, val); - return; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); - return; - } - - if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) - goto redo; - - do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); -} - -REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, - struct mmu_atc_line *cl) -{ - mmu_put_long_slow(addr, (uae_u32)(val >> 32), super, data, sz_long, cl); - mmu_put_long_slow(addr + 4, (uae_u32)(val), super, data, sz_long, cl); -} - -uae_u32 sfc_get_long(uaecptr addr) -{ - int super = (regs.sfc & 4) != 0; - int data = (regs.sfc & 3) != 2; - uae_u32 res; - - if (likely(!is_unaligned(addr, 4))) - return mmu_get_user_long(addr, super, data, sz_long); - - if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_user_word(addr + 2, super, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } else { - res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8; - res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8; - res |= mmu_get_user_byte(addr + 3, super, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } - return res; -} - -uae_u16 sfc_get_word(uaecptr addr) -{ - int super = (regs.sfc & 4) != 0; - int data = (regs.sfc & 3) != 2; - uae_u16 res; - - if (likely(!is_unaligned(addr, 2))) - return mmu_get_user_word(addr, super, data, sz_word); - - res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_user_byte(addr + 1, super, data, sz_word); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - return res; -} - -uae_u8 sfc_get_byte(uaecptr addr) -{ - int super = (regs.sfc & 4) != 0; - int data = (regs.sfc & 3) != 2; - - return mmu_get_user_byte(addr, super, data, sz_byte); -} - -void dfc_put_long(uaecptr addr, uae_u32 val) -{ - int super = (regs.dfc & 4) != 0; - int data = (regs.dfc & 3) != 2; - - SAVE_EXCEPTION; - TRY(prb) { - if (likely(!is_unaligned(addr, 4))) - mmu_put_user_long(addr, val, super, data, sz_long); - else if (likely(!(addr & 1))) { - mmu_put_user_word(addr, val >> 16, super, data, sz_long); - mmu_put_user_word(addr + 2, val, super, data, sz_long); - } else { - mmu_put_user_byte(addr, val >> 24, super, data, sz_long); - mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long); - mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long); - mmu_put_user_byte(addr + 3, val, super, data, sz_long); - } - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -void dfc_put_word(uaecptr addr, uae_u16 val) -{ - int super = (regs.dfc & 4) != 0; - int data = (regs.dfc & 3) != 2; - - SAVE_EXCEPTION; - TRY(prb) { - if (likely(!is_unaligned(addr, 2))) - mmu_put_user_word(addr, val, super, data, sz_word); - else { - mmu_put_user_byte(addr, val >> 8, super, data, sz_word); - mmu_put_user_byte(addr + 1, val, super, data, sz_word); - } - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -void dfc_put_byte(uaecptr addr, uae_u8 val) -{ - int super = (regs.dfc & 4) != 0; - int data = (regs.dfc & 3) != 2; - - SAVE_EXCEPTION; - TRY(prb) { - mmu_put_user_byte(addr, val, super, data, sz_byte); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - breakpt(); - THROW_AGAIN(prb); - } -} - -void mmu_op(uae_u32 opcode, uae_u16 extra) -{ - int super = (regs.dfc & 4) != 0; - DUNUSED(extra); - if ((opcode & 0xFE0) == 0x0500) { - int regno, glob; - //D(didflush = 0); - uae_u32 addr; - /* PFLUSH */ - regno = opcode & 7; - glob = (opcode & 8) != 0; - - if (opcode & 16) { - D(bug("pflusha(%u,%u)", glob, regs.dfc)); - mmu_flush_atc_all(glob); - } else { - addr = m68k_areg(regs, regno); - D(bug("pflush(%u,%u,%x)", glob, regs.dfc, addr)); - mmu_flush_atc(addr, super, glob); - } - flush_internals(); -#ifdef USE_JIT - flush_icache(0); -#endif - } else if ((opcode & 0x0FD8) == 0x548) { - int write, regno; - uae_u32 addr; - - regno = opcode & 7; - write = (opcode & 32) == 0; - addr = m68k_areg(regs, regno); - //bug("ptest(%u,%u,%x)", write, regs.dfc, addr); - D(bug("PTEST%c (A%d) %08x DFC=%d", write ? 'W' : 'R', regno, addr, regs.dfc)); - mmu_flush_atc(addr, super, true); - SAVE_EXCEPTION; - TRY(prb) { - struct mmu_atc_line *l; - uae_u32 desc; - bool data = (regs.dfc & 3) != 2; - - l = &atc_l2[super][ATC_L2_INDEX(addr)]; - desc = mmu_fill_atc_l2(addr, super, data, write, l); - if (!(data ? l->valid_data : l->valid_inst)) - regs.mmusr = MMU_MMUSR_B; - else if (l->tt) - regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R; - else { - regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S| - MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W); - regs.mmusr |= MMU_MMUSR_R; - } - } - CATCH(prb) { - regs.mmusr = MMU_MMUSR_B; - } - RESTORE_EXCEPTION; - D(bug("PTEST result: mmusr %08x", regs.mmusr)); - } else - op_illg (opcode); -} - -void mmu_flush_atc(uaecptr addr, bool super, bool global) -{ - struct mmu_atc_line *l; - int i, j; - - l = atc_l1[super][0][0]; - i = ATC_L1_INDEX(addr); - for (j = 0; j < 4; j++) { - if (global || !l[i].global) - l[i].tag = 0x8000; - l += ATC_L1_SIZE; - } - if (regs.mmu_pagesize_8k) { - i = ATC_L1_INDEX(addr) ^ 1; - for (j = 0; j < 4; j++) { - if (global || !l[i].global) - l[i].tag = 0x8000; - l += ATC_L1_SIZE; - } - } - l = atc_l2[super]; - i = ATC_L2_INDEX(addr); - if (global || !l[i].global) - l[i].tag = 0x8000; - if (regs.mmu_pagesize_8k) { - i ^= 1; - if (global || !l[i].global) - l[i].tag = 0x8000; - } -} - -void mmu_flush_atc_all(bool global) -{ - struct mmu_atc_line *l; - unsigned int i; - - l = atc_l1[0][0][0]; - for (i = 0; i < sizeof(atc_l1) / sizeof(*l); l++, i++) { - if (global || !l->global) - l->tag = 0x8000; - } - - l = atc_l2[0]; - for (i = 0; i < sizeof(atc_l2) / sizeof(*l); l++, i++) { - if (global || !l->global) - l->tag = 0x8000; - } -} - -void mmu_reset(void) -{ - mmu_flush_atc_all(true); - - regs.urp = regs.srp = 0; - regs.itt0 = regs.itt1 = 0; - regs.dtt0 = regs.dtt1 = 0; - regs.mmusr = 0; -} - - -void mmu_set_tc(uae_u16 tc) -{ - if (regs.tc == tc) - return; - - regs.tc = tc; - regs.mmu_enabled = tc & 0x8000 ? 1 : 0; - regs.mmu_pagesize_8k = tc & 0x4000 ? 1 : 0; - mmu_flush_atc_all(true); - - D(bug("MMU: enabled=%d page8k=%d\n", regs.mmu_enabled, regs.mmu_pagesize_8k)); -} - -void mmu_set_super(bool super) -{ - current_atc = &atc_l1[super]; -} - -#else - -void mmu_op(uae_u32 opcode, uae_u16 /*extra*/) -{ - if ((opcode & 0xFE0) == 0x0500) { - /* PFLUSH instruction */ - flush_internals(); - } else if ((opcode & 0x0FD8) == 0x548) { - /* PTEST instruction */ - } else - op_illg(opcode); -} - -#endif - -/* -vim:ts=4:sw=4: -*/ diff --git a/BasiliskII/src/uae_cpu/cpummu.h b/BasiliskII/src/uae_cpu/cpummu.h deleted file mode 100644 index 01359f6f..00000000 --- a/BasiliskII/src/uae_cpu/cpummu.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * cpummu.h - MMU emulation - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by UAE MMU patch - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CPUMMU_H -#define CPUMMU_H - -#include "registers.h" - -# include - -#define MMU_TEST_PTEST 1 -#define MMU_TEST_VERBOSE 2 -#define MMU_TEST_FORCE_TABLE_SEARCH 4 -#define MMU_TEST_NO_BUSERR 8 - -extern void mmu_dump_tables(void); - -#define MMU_TTR_LOGICAL_BASE 0xff000000 -#define MMU_TTR_LOGICAL_MASK 0x00ff0000 -#define MMU_TTR_BIT_ENABLED (1 << 15) -#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) -#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) -#define MMU_TTR_SFIELD_SHIFT 13 -#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) -#define MMU_TTR_UX_SHIFT 8 -#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) -#define MMU_TTR_CACHE_SHIFT 5 -#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) - -#define MMU_UDT_MASK 3 -#define MMU_PDT_MASK 3 - -#define MMU_DES_WP 4 -#define MMU_DES_USED 8 - -/* page descriptors only */ -#define MMU_DES_MODIFIED 16 -#define MMU_DES_SUPER (1 << 7) -#define MMU_DES_GLOBAL (1 << 10) - -#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 -#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 -#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 - -#define MMU_PAGE_INDIRECT_MASK 0xfffffffc -#define MMU_PAGE_ADDR_MASK_8 0xffffe000 -#define MMU_PAGE_ADDR_MASK_4 0xfffff000 -#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) -#define MMU_PAGE_UR_MASK_4 (1 << 11) -#define MMU_PAGE_UR_SHIFT 11 - -#define MMU_MMUSR_ADDR_MASK 0xfffff000 -#define MMU_MMUSR_B (1 << 11) -#define MMU_MMUSR_G (1 << 10) -#define MMU_MMUSR_U1 (1 << 9) -#define MMU_MMUSR_U0 (1 << 8) -#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) -#define MMU_MMUSR_S (1 << 7) -#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) -#define MMU_MMUSR_M (1 << 4) -#define MMU_MMUSR_W (1 << 2) -#define MMU_MMUSR_T (1 << 1) -#define MMU_MMUSR_R (1 << 0) - -/* special status word (access error stack frame) */ -#define MMU_SSW_TM 0x0007 -#define MMU_SSW_TT 0x0018 -#define MMU_SSW_SIZE 0x0060 -#define MMU_SSW_SIZE_B 0x0020 -#define MMU_SSW_SIZE_W 0x0040 -#define MMU_SSW_SIZE_L 0x0000 -#define MMU_SSW_RW 0x0100 -#define MMU_SSW_LK 0x0200 -#define MMU_SSW_ATC 0x0400 -#define MMU_SSW_MA 0x0800 - -#define TTR_I0 4 -#define TTR_I1 5 -#define TTR_D0 6 -#define TTR_D1 7 - -#define TTR_NO_MATCH 0 -#define TTR_NO_WRITE 1 -#define TTR_OK_MATCH 2 - -struct mmu_atc_line { - uae_u16 tag; - unsigned tt : 1; - unsigned valid_data : 1; - unsigned valid_inst : 1; - unsigned global : 1; - unsigned modified : 1; - unsigned write_protect : 1; - unsigned hw : 1; - unsigned bus_fault : 1; - uaecptr phys; -}; - -/* - * We don't need to store the whole logical address in the atc cache, as part of - * it is encoded as index into the cache. 14 bits of the address are stored in - * the tag, this means at least 6 bits must go into the index. The upper two - * bits of the tag define the type of data in the atc line: - * - 00: a normal memory address - * - 11: invalid memory address or hardware access - * (generated via ~ATC_TAG(addr) in the slow path) - * - 10: empty atc line - */ - -#define ATC_TAG_SHIFT 18 -#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT) - - -#define ATC_L1_SIZE_LOG 8 -#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG) - -#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE) - -/* - * first level atc cache - * indexed by [super][data][rw][idx] - */ - -typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE]; -extern mmu_atc_l1_array atc_l1[2]; -extern mmu_atc_l1_array *current_atc; - -#define ATC_L2_SIZE_LOG 12 -#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG) - -#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE) - -extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; - -/* - * lookup address in the level 1 atc cache, - * the data and write arguments are constant in the common, - * thus allows gcc to generate a constant offset. - */ -static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write, - struct mmu_atc_line **cl) -{ - addr >>= 12; - *cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE]; - return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); -} - -/* - * similiar to mmu_user_lookup, but for the use of the moves instruction - */ -static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data, - bool write, struct mmu_atc_line **cl) -{ - addr >>= 12; - *cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE]; - return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); -} - -extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data); -extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data); - -extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, - struct mmu_atc_line *cl); - -extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data); -extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data); - -extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, - struct mmu_atc_line *cl); - -extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); - -static inline void mmu_set_ttr(int regno, uae_u32 val) -{ - uae_u32 * ttr; - switch(regno) { - case TTR_I0: ttr = ®s.itt0; break; - case TTR_I1: ttr = ®s.itt1; break; - case TTR_D0: ttr = ®s.dtt0; break; - case TTR_D1: ttr = ®s.dtt1; break; - default: abort(); - } - *ttr = val; -} - -static inline void mmu_set_mmusr(uae_u32 val) -{ - regs.mmusr = val; -} - -#define FC_DATA (regs.s ? 5 : 1) -#define FC_INST (regs.s ? 6 : 2) - -extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write); - -extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr); -extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr); -extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr); -extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val); -extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val); -extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val); - - -extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global); -extern void REGPARAM2 mmu_flush_atc_all(bool global); -extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra); - -#ifdef FULLMMU - -extern void REGPARAM2 mmu_reset(void); -extern void REGPARAM2 mmu_set_tc(uae_u16 tc); -extern void REGPARAM2 mmu_set_super(bool super); - -#else - -static inline void mmu_reset(void) -{ -} - -static inline void mmu_set_tc(uae_u16 /*tc*/) -{ -} - -static inline void mmu_set_super(bool /*super*/) -{ -} - -#endif - -#endif /* CPUMMU_H */ -/* -vim:ts=4:sw=4: -*/ diff --git a/BasiliskII/src/uae_cpu/cpuopti.c b/BasiliskII/src/uae_cpu/cpuopti.c new file mode 100644 index 00000000..28ba7c22 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuopti.c @@ -0,0 +1,312 @@ +/* + * UAE - The Un*x Amiga Emulator + * + * cpuopti.c - Small optimizer for cpu*.s files + * Based on work by Tauno Taipaleenmaki + * + * Copyright 1996 Bernd Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "sysdeps.h" + +struct line { + struct line *next, *prev; + int delet; + char *data; +}; + +struct func { + struct line *first_line, *last_line; + int initial_offset; +}; + +static void oops(void) +{ + fprintf(stderr, "Don't know how to optimize this file.\n"); + exit(1); +} + +static char * match(struct line *l, const char *m) +{ + char *str = l->data; + int len = strlen(m); + while (isspace(*str)) + str++; + + if (strncmp(str, m, len) != 0) + return NULL; + return str + len; +} + +static int insn_references_reg (struct line *l, char *reg) +{ + if (reg[0] != 'e') { + fprintf(stderr, "Unknown register?!?\n"); + exit(1); + } + if (strstr (l->data, reg) != 0) + return 1; + if (strstr (l->data, reg+1) != 0) + return 1; + if (strcmp (reg, "eax") == 0 + && (strstr (l->data, "%al") != 0 || strstr (l->data, "%ah") != 0)) + return 1; + if (strcmp (reg, "ebx") == 0 + && (strstr (l->data, "%bl") != 0 || strstr (l->data, "%bh") != 0)) + return 1; + if (strcmp (reg, "ecx") == 0 + && (strstr (l->data, "%cl") != 0 || strstr (l->data, "%ch") != 0)) + return 1; + if (strcmp (reg, "edx") == 0 + && (strstr (l->data, "%dl") != 0 || strstr (l->data, "%dh") != 0)) + return 1; + return 0; +} + +static void do_function(struct func *f) +{ + int v; + int pops_at_end = 0; + struct line *l, *l1, *fl, *l2; + char *s, *s2; + int in_pop_area = 1; + + f->initial_offset = 0; + + l = f->last_line; + fl = f->first_line; + + if (match(l,".LFE")) + l = l->prev; + if (!match(l,"ret")) + oops(); + + while (!match(fl, "op_")) + fl = fl->next; + fl = fl->next; + + /* Try reordering the insns at the end of the function so that the + * pops are all at the end. */ + l2 = l->prev; + /* Tolerate one stack adjustment */ + if (match (l2, "addl $") && strstr(l2->data, "esp") != 0) + l2 = l2->prev; + for (;;) { + char *forbidden_reg; + struct line *l3, *l4; + + while (match (l2, "popl %")) + l2 = l2->prev; + + l3 = l2; + for (;;) { + forbidden_reg = match (l3, "popl %"); + if (forbidden_reg) + break; + if (l3 == fl) + goto reordered; + /* Jumps and labels put an end to our attempts... */ + if (strstr (l3->data, ".L") != 0) + goto reordered; + /* Likewise accesses to the stack pointer... */ + if (strstr (l3->data, "esp") != 0) + goto reordered; + /* Function calls... */ + if (strstr (l3->data, "call") != 0) + goto reordered; + l3 = l3->prev; + } + if (l3 == l2) + exit(1); + for (l4 = l2; l4 != l3; l4 = l4->prev) { + /* The register may not be referenced by any of the insns that we + * move the popl past */ + if (insn_references_reg (l4, forbidden_reg)) + goto reordered; + } + l3->prev->next = l3->next; + l3->next->prev = l3->prev; + l2->next->prev = l3; + l3->next = l2->next; + l2->next = l3; + l3->prev = l2; + } +reordered: + + l = l->prev; + + s = match (l, "addl $"); + s2 = match (fl, "subl $"); + + l1 = l; + if (s == 0) { + char *t = match (l, "popl %"); + if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) { + s = "4,%esp"; + l = l->prev; + t = match (l, "popl %"); + if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) { + s = "8,%esp"; + l = l->prev; + } + } + } else { + l = l->prev; + } + + if (s && s2) { + int v = 0; + if (strcmp (s, s2) != 0) { + fprintf (stderr, "Stack adjustment not matching.\n"); + return; + } + + while (isdigit(*s)) { + v = v * 10 + (*s) - '0'; + s++; + } + + if (strcmp (s, ",%esp") != 0) { + fprintf (stderr, "Not adjusting the stack pointer.\n"); + return; + } + f->initial_offset = v; + fl->delet = 3; + fl = fl->next; + l1->delet = 2; + l1 = l1->prev; + while (l1 != l) { + l1->delet = 1; + l1 = l1->prev; + } + } + + while (in_pop_area) { + char *popm, *pushm; + popm = match (l, "popl %"); + pushm = match (fl, "pushl %"); + if (popm && pushm && strcmp(pushm, popm) == 0) { + pops_at_end++; + fl->delet = l->delet = 1; + } else + in_pop_area = 0; + l = l->prev; + fl = fl->next; + } + if (f->initial_offset) + f->initial_offset += 4 * pops_at_end; +} + +static void output_function(struct func *f) +{ + struct line *l = f->first_line; + + while (l) { + switch (l->delet) { + case 1: + break; + case 0: + printf("%s\n", l->data); + break; + case 2: + if (f->initial_offset) + printf("\taddl $%d,%%esp\n", f->initial_offset); + break; + case 3: + if (f->initial_offset) + printf("\tsubl $%d,%%esp\n", f->initial_offset); + break; + } + l = l->next; + } +} + +int main(int argc, char **argv) +{ + FILE *infile = stdin; + char tmp[4096]; + +#ifdef __mc68000__ + if(system("perl machdep/cpuopti")==-1) { + perror("perl machdep/cpuopti"); + return 10; + } else return 0; +#endif + + /* For debugging... */ + if (argc == 2) + infile = fopen (argv[1], "r"); + + for(;;) { + char *s; + + if ((fgets(tmp, 4095, infile)) == NULL) + break; + + s = strchr (tmp, '\n'); + if (s != NULL) + *s = 0; + + if (strncmp(tmp, ".globl op_", 10) == 0) { + struct line *first_line = NULL, *prev = NULL; + struct line **nextp = &first_line; + struct func f; + int nr_rets = 0; + int can_opt = 1; + + do { + struct line *current; + + if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) { + current = *nextp = (struct line *)malloc(sizeof (struct line)); + nextp = ¤t->next; + current->prev = prev; prev = current; + current->next = NULL; + current->delet = 0; + current->data = strdup (tmp); + if (match (current, "movl %esp,%ebp") || match (current, "enter")) { + fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data); + can_opt = 0; + } + + if (match (current, "ret")) + nr_rets++; + } + if ((fgets(tmp, 4095, infile)) == NULL) + oops(); + s = strchr (tmp, '\n'); + if (s != NULL) + *s = 0; + } while (strncmp (tmp,".Lfe", 4) != 0); + + f.first_line = first_line; + f.last_line = prev; + + if (nr_rets == 1 && can_opt) + do_function(&f); + /*else + fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/ + output_function(&f); + } + printf("%s\n", tmp); + } + return 0; +} diff --git a/BasiliskII/src/uae_cpu/cpustbl_nf.cpp b/BasiliskII/src/uae_cpu/cpustbl_nf.cpp deleted file mode 100644 index 0ea66010..00000000 --- a/BasiliskII/src/uae_cpu/cpustbl_nf.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define NOFLAGS 1 -#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpustbla.cpp b/BasiliskII/src/uae_cpu/cpustbla.cpp deleted file mode 100644 index f3f8e320..00000000 --- a/BasiliskII/src/uae_cpu/cpustbla.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * cpustbl.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/debug.cpp b/BasiliskII/src/uae_cpu/debug.cpp deleted file mode 100644 index 8b2f14e0..00000000 --- a/BasiliskII/src/uae_cpu/debug.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * debug.cpp - CPU debugger - * - * Copyright (c) 2001-2010 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Bernd Schmidt's UAE - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * UAE - The Un*x Amiga Emulator - * - * Debugger - * - * (c) 1995 Bernd Schmidt - * - */ - -#include "sysdeps.h" - -#include "memory.h" -#include "newcpu.h" -#include "debug.h" - -#include "input.h" -#include "cpu_emulation.h" - -#include "main.h" - -static int debugger_active = 0; -int debugging = 0; -int irqindebug = 0; - -int ignore_irq = 0; - - -void activate_debugger (void) -{ -#ifdef DEBUGGER - ndebug::do_skip = false; -#endif - debugger_active = 1; - SPCFLAGS_SET( SPCFLAG_BRK ); - debugging = 1; - /* use_debugger = 1; */ -} - -void deactivate_debugger(void) -{ - debugging = 0; - debugger_active = 0; -} - -void debug (void) -{ - if (ignore_irq && regs.s && !regs.m ) { - SPCFLAGS_SET( SPCFLAG_BRK ); - return; - } -#ifdef DEBUGGER - ndebug::run(); -#endif -} - -/* -vim:ts=4:sw=4: -*/ diff --git a/BasiliskII/src/uae_cpu/fpu/core.h b/BasiliskII/src/uae_cpu/fpu/core.h index 1801ff7c..66358a2d 100644 --- a/BasiliskII/src/uae_cpu/fpu/core.h +++ b/BasiliskII/src/uae_cpu/fpu/core.h @@ -1,33 +1,28 @@ /* - * fpu/core.h - base fpu context definition + * fpu/core.h - base fpu context definition * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_CORE_H @@ -39,15 +34,11 @@ /* Always use x87 FPU stack on IA-32. */ #if defined(X86_ASSEMBLY) #define USE_X87_ASSEMBLY 1 -#ifndef USE_JIT_FPU -#define ACCURATE_SIN_COS_TAN 1 -#endif #endif /* Only use x87 FPU on x86-64 if long double precision is requested. */ -#if defined(X86_64_ASSEMBLY) && defined(USE_LONG_DOUBLE) +#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE #define USE_X87_ASSEMBLY 1 -#define ACCURATE_SIN_COS_TAN 1 #endif /* ========================================================================== */ @@ -116,7 +107,7 @@ struct fpu_t { /* Floating-Point Condition Code Byte */ uae_u32 condition_codes; - #define FPSR_CCB 0x0f000000 + #define FPSR_CCB 0xff000000 #define FPSR_CCB_NEGATIVE 0x08000000 #define FPSR_CCB_ZERO 0x04000000 #define FPSR_CCB_INFINITY 0x02000000 @@ -228,7 +219,7 @@ struct fpu_t { extern fpu_t fpu; /* Return the address of a particular register */ -inline fpu_register * fpu_register_address(int i) +inline fpu_register * const fpu_register_address(int i) { return &fpu.registers[i]; } /* Dump functions for m68k_dumpstate */ @@ -236,16 +227,16 @@ extern void fpu_dump_registers(void); extern void fpu_dump_flags(void); /* Accessors to FPU Control Register */ -//static inline uae_u32 get_fpcr(void); -//static inline void set_fpcr(uae_u32 new_fpcr); +static inline uae_u32 get_fpcr(void); +static inline void set_fpcr(uae_u32 new_fpcr); /* Accessors to FPU Status Register */ -//static inline uae_u32 get_fpsr(void); -//static inline void set_fpsr(uae_u32 new_fpsr); +static inline uae_u32 get_fpsr(void); +static inline void set_fpsr(uae_u32 new_fpsr); /* Accessors to FPU Instruction Address Register */ -//static inline uae_u32 get_fpiar(); -//static inline void set_fpiar(uae_u32 new_fpiar); +static inline uae_u32 get_fpiar(); +static inline void set_fpiar(uae_u32 new_fpiar); /* Initialization / Finalization */ extern void fpu_init(bool integral_68040); @@ -263,6 +254,6 @@ void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM; /* Floating-point system control operations */ void fpuop_save(uae_u32 opcode) REGPARAM; void fpuop_restore(uae_u32 opcode) REGPARAM; -void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) REGPARAM; +void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM; #endif /* FPU_CORE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp index 2a597997..6aa6431a 100644 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp @@ -1,33 +1,28 @@ /* - * fpu/exceptions.cpp - system-dependant FPU exceptions management + * fpu/exceptions.cpp - system-dependant FPU exceptions management * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #undef PRIVATE diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.h b/BasiliskII/src/uae_cpu/fpu/exceptions.h index f943da04..8c69a69d 100644 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.h +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.h @@ -1,33 +1,28 @@ /* - * fpu/exceptions.h - system-dependant FPU exceptions management + * fpu/exceptions.h - system-dependant FPU exceptions management * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_EXCEPTIONS_H diff --git a/BasiliskII/src/uae_cpu/fpu/flags.cpp b/BasiliskII/src/uae_cpu/fpu/flags.cpp index 4b0972df..2eabef85 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.cpp +++ b/BasiliskII/src/uae_cpu/fpu/flags.cpp @@ -1,33 +1,28 @@ /* - * fpu/flags.cpp - Floating-point flags + * fpu/flags.cpp - Floating-point flags * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* NOTE: this file shall be included only from fpu/fpu_*.cpp */ diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h index 3d144ac2..7c0c5b74 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.h +++ b/BasiliskII/src/uae_cpu/fpu/flags.h @@ -1,33 +1,28 @@ /* - * fpu/flags.h - Floating-point flags + * fpu/flags.h - Floating-point flags * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_FLAGS_H @@ -117,7 +112,7 @@ PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) /* Make FPSR according to the value passed in argument */ PRIVATE inline void FFPU make_fpsr(fpu_register const & r) - { uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=a" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } + { uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } /* Return the corresponding ID of the current floating-point condition codes */ /* NOTE: only valid for evaluation of a condition */ @@ -222,7 +217,7 @@ PRIVATE inline void FFPU make_fpsr(fpu_register const & r) /* -------------------------------------------------------------------------- */ /* Return the address of the floating-point condition codes register */ -static inline uae_u32 * FFPU address_of_fpccr(void) +static inline uae_u32 * const FFPU address_of_fpccr(void) { return ((uae_u32 *)& FPU fpsr.condition_codes); } #endif /* FPU_FLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu.h b/BasiliskII/src/uae_cpu/fpu/fpu.h index d1fe6dd2..3940a75b 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu.h @@ -1,33 +1,28 @@ /* - * fpu/fpu.h - public header + * fpu/fpu.h - public header * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_PUBLIC_HEADER_H @@ -51,9 +46,4 @@ #include "fpu/types.h" #include "fpu/core.h" -void fpu_set_fpsr(uae_u32 new_fpsr); -uae_u32 fpu_get_fpsr(void); -void fpu_set_fpcr(uae_u32 new_fpcr); -uae_u32 fpu_get_fpcr(void); - #endif /* FPU_PUBLIC_HEADER_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp index 5fa1ad0b..f5a1aeb4 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp @@ -1,42 +1,31 @@ /* - * fpu_ieee.cpp - the IEEE FPU + * fpu/fpu_ieee.cpp * - * Copyright (c) 2001-2008 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation * - * MC68881/68040 fpu emulation + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* - * UAE - The Un*x Amiga Emulator - * - * MC68881/MC68040 emulation - * - * Copyright 1996 Herman ten Brugge - * - * * Following fixes by Lauri Pesonen, July 1999: * * FMOVEM list handling: @@ -98,7 +87,7 @@ */ #include "sysdeps.h" -#include +#include #include "memory.h" #include "readcpu.h" #include "newcpu.h" @@ -141,24 +130,6 @@ fpu_t fpu; #include "fpu/exceptions.cpp" #include "fpu/rounding.cpp" -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) -#define LD(x) x ## L -#ifdef HAVE_POWL -#define POWL(x, y) powl(x, y) -#else -#define POWL(x, y) pow(x, y) -#endif -#ifdef HAVE_LOG10L -#define LOG10L(x) log10l(x) -#else -#define LOG10L(x) log10(x) -#endif -#else -#define LD(x) x -#define POWL(x, y) pow(x, y) -#define LOG10L(x) log10(x) -#endif - /* -------------------------------------------------------------------------- */ /* --- Debugging --- */ /* -------------------------------------------------------------------------- */ @@ -181,9 +152,9 @@ PUBLIC void FFPU fpu_dump_flags(void) (get_fpsr() & FPSR_CCB_NAN) != 0); } -#if FPU_DEBUG && FPU_DUMP_REGISTERS PRIVATE void FFPU dump_registers(const char * str) { +#if FPU_DEBUG && FPU_DUMP_REGISTERS char temp_str[512]; sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", @@ -193,15 +164,12 @@ PRIVATE void FFPU dump_registers(const char * str) fpu_get_register(6), fpu_get_register(7) ); fpu_debug((temp_str)); -#else -PRIVATE void FFPU dump_registers(const char *) -{ #endif } -#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) { +#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES char temp_buf1[256], temp_buf2[10]; int bytes = sizeof(temp_buf1)/3-1-3; if (actual < bytes) @@ -215,9 +183,6 @@ PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) strcat(temp_buf1, "\n"); fpu_debug((temp_buf1)); -#else - PRIVATE void FFPU dump_first_bytes(uae_u8 *, uae_s32) -{ #endif } @@ -235,12 +200,11 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) #if 1 // Use a single, otherwise some checks for NaN, Inf, Zero would have to // be performed - fpu_single result = 0; - fp_declare_init_shape(srp, single); - srp.ieee.negative = (value >> 31) & 1; - srp.ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; - srp.ieee.mantissa = value & 0x007fffff; - result = srp.value; + fpu_single result = 0; // = 0 to workaround a compiler bug on SPARC + fp_declare_init_shape(srp, result, single); + srp->ieee.negative = (value >> 31) & 1; + srp->ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; + srp->ieee.mantissa = value & 0x007fffff; fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); return result; #elif 0 /* Original code */ @@ -248,13 +212,13 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) return (0.0); fpu_register result; - fpu_register_parts *p = (fpu_register_parts *)&result; + uae_u32 * p = (uae_u32 *)&result; uae_u32 sign = (value & 0x80000000); uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - p->parts[FLO] = value << 29; - p->parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + p[FLO] = value << 29; + p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); @@ -267,11 +231,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) { #if 1 fpu_single input = (fpu_single) src; - fp_declare_init_shape(sip, single); - sip.value = input; - uae_u32 result = (sip.ieee.negative << 31) - | (sip.ieee.exponent << 23) - | sip.ieee.mantissa; + fp_declare_init_shape(sip, input, single); + uae_u32 result = (sip->ieee.negative << 31) + | (sip->ieee.exponent << 23) + | sip->ieee.mantissa; fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); return result; #elif 0 /* Original code */ @@ -279,10 +242,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) return 0; uae_u32 result; - fpu_register_parts const *p = (fpu_register_parts const *)&src; + uae_u32 *p = (uae_u32 *)&src; - uae_u32 sign = (p->parts[FHI] & 0x80000000); - uae_u32 exp = (p->parts[FHI] & 0x7FF00000) >> 20; + uae_u32 sign = (p[FHI] & 0x80000000); + uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; if(exp + 127 < 1023) { exp = 0; @@ -292,7 +255,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) exp = exp + 127 - 1023; } - result = sign | (exp << 23) | ((p->parts[FHI] & 0x000FFFFF) << 3) | (p->parts[FLO] >> 29); + result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); @@ -305,37 +268,36 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u { // is it zero? if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return (wrd1 & 0x80000000) ? -0.0 : 0.0; + return 0.0; fpu_register result; -#if defined(USE_QUAD_DOUBLE) +#if USE_QUAD_DOUBLE // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { make_nan(result); return result; } // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { if ((wrd1 & 0x80000000) == 0) make_inf_positive(result); else make_inf_negative(result); return result; } - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp.ieee.mantissa3 = 0; -#elif defined(USE_LONG_DOUBLE) - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = wrd2; - srp.ieee.mantissa1 = wrd3; - + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp->ieee.mantissa3 = 0; +#elif USE_LONG_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; #else uae_u32 sgn = (wrd1 >> 31) & 1; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -364,14 +326,13 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - fp_declare_init_shape(srp, double); - srp.ieee.negative = sgn; - srp.ieee.exponent = exp; + fp_declare_init_shape(srp, result, double); + srp->ieee.negative = sgn; + srp->ieee.exponent = exp; // drop the explicit integer bit - srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); + srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); #endif - result = srp.value; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); return result; } @@ -386,40 +347,37 @@ PRIVATE inline void FFPU make_extended_no_normalize( ) { // is it zero? - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - if (wrd1 & 0x80000000) - make_zero_negative(result); - else - make_zero_positive(result); + if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + make_zero_positive(result); return; } // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { make_nan(result); return; } -#if defined(USE_QUAD_DOUBLE) +#if USE_QUAD_DOUBLE // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { if ((wrd1 & 0x80000000) == 0) make_inf_positive(result); else make_inf_negative(result); return; } - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp.ieee.mantissa3 = 0; -#elif defined(USE_LONG_DOUBLE) - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = wrd2; - srp.ieee.mantissa1 = wrd3; + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp->ieee.mantissa3 = 0; +#elif USE_LONG_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; #else uae_u32 exp = (wrd1 >> 16) & 0x7fff; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) @@ -429,14 +387,13 @@ PRIVATE inline void FFPU make_extended_no_normalize( else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - fp_declare_init_shape(srp, double); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = exp; + fp_declare_init_shape(srp, result, double); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = exp; // drop the explicit integer bit - srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); + srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); #endif - result = srp.value; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); } @@ -449,43 +406,41 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = *wrd2 = *wrd3 = 0; return; } -#if defined(USE_QUAD_DOUBLE) +#if USE_QUAD_DOUBLE // FIXME: deal with denormals? - fp_declare_init_shape(srp, extended); - srp.value = src; - *wrd1 = (srp.ieee.negative << 31) | (srp.ieee.exponent << 16); + fp_declare_init_shape(srp, src, extended); + *wrd1 = (srp->ieee.negative << 31) | (srp->ieee.exponent << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 15) | ((srp.ieee.mantissa1 & 0xfffe0000) >> 17); - *wrd3 = (srp.ieee.mantissa1 << 15) | ((srp.ieee.mantissa2 & 0xfffe0000) >> 17); -#elif defined(USE_LONG_DOUBLE) - fpu_register_parts p = { src }; + *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 15) | ((srp->ieee.mantissa1 & 0xfffe0000) >> 17); + *wrd3 = (srp->ieee.mantissa1 << 15) | ((srp->ieee.mantissa2 & 0xfffe0000) >> 17); +#elif USE_LONG_DOUBLE + uae_u32 *p = (uae_u32 *)&src; #ifdef WORDS_BIGENDIAN - *wrd1 = p.parts[0]; - *wrd2 = p.parts[1]; - *wrd3 = p.parts[2]; + *wrd1 = p[0]; + *wrd2 = p[1]; + *wrd3 = p[2]; #else - *wrd3 = p.parts[0]; - *wrd2 = p.parts[1]; - *wrd1 = (p.parts[2] & 0xffff) << 16; + *wrd3 = p[0]; + *wrd2 = p[1]; + *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; #endif #else - fp_declare_init_shape(srp, double); - srp.value = src; + fp_declare_init_shape(srp, src, double); fpu_debug(("extract_extended (%d,%d,%X,%X)\n", - srp.ieee.negative , srp.ieee.exponent, - srp.ieee.mantissa0, srp.ieee.mantissa1)); + srp->ieee.negative , srp->ieee.exponent, + srp->ieee.mantissa0, srp->ieee.mantissa1)); - uae_u32 exp = srp.ieee.exponent; + uae_u32 exp = srp->ieee.exponent; if (exp == FP_DOUBLE_EXP_MAX) exp = FP_EXTENDED_EXP_MAX; else exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; - *wrd1 = (srp.ieee.negative << 31) | (exp << 16); + *wrd1 = (srp->ieee.negative << 31) | (exp << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 11) | ((srp.ieee.mantissa1 & 0xffe00000) >> 21); - *wrd3 = srp.ieee.mantissa1 << 11; + *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21); + *wrd3 = srp->ieee.mantissa1 << 11; #endif fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -531,88 +486,41 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, // to_pack PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { - fpu_register d; - bool sm = (wrd1 & 0x80000000) != 0; - bool se = (wrd1 & 0x40000000) != 0; - int exp = (wrd1 & 0x7fff0000) >> 16; - unsigned int dig; - fpu_register pwr; - - if (exp == 0x7fff) - { - if (wrd2 == 0 && wrd3 == 0) - { - sm ? make_inf_negative(d) : make_inf_positive(d); - } else - { - make_nan(d); - } - return d; - } - dig = wrd1 & 0x0000000f; - if (dig == 0 && wrd2 == 0 && wrd3 == 0) - { - sm ? make_zero_negative(d) : make_zero_positive(d); - return d; - } + fpu_double d; + char *cp; + char str[100]; - /* - * Convert the bcd exponent to binary by successive adds and - * muls. Set the sign according to SE. Subtract 16 to compensate - * for the mantissa which is to be interpreted as 17 integer - * digits, rather than 1 integer and 16 fraction digits. - * Note: this operation can never overflow. - */ - exp = ((wrd1 >> 24) & 0xf); - exp = exp * 10 + ((wrd1 >> 20) & 0xf); - exp = exp * 10 + ((wrd1 >> 16) & 0xf); - if (se) - exp = -exp; - /* sub to compensate for shift of mant */ - exp = exp - 16; - - /* - * Convert the bcd mantissa to binary by successive - * adds and muls. Set the sign according to SM. - * The mantissa digits will be converted with the decimal point - * assumed following the least-significant digit. - * Note: this operation can never overflow. - */ - d = wrd1 & 0xf; - d = (d * LD(10.0)) + ((wrd2 >> 28) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 24) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 20) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 16) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 12) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 8) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 4) & 0xf); - d = (d * LD(10.0)) + ((wrd2 ) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 28) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 24) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 20) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 16) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 12) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 8) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 4) & 0xf); - d = (d * LD(10.0)) + ((wrd3 ) & 0xf); + cp = str; + if (wrd1 & 0x80000000) + *cp++ = '-'; + *cp++ = (char)((wrd1 & 0xf) + '0'); + *cp++ = '.'; + *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); + *cp++ = 'E'; + if (wrd1 & 0x40000000) + *cp++ = '-'; + *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); + *cp = 0; + sscanf(str, "%le", &d); - /* Check the sign of the mant and make the value in fp0 the same sign. */ - if (sm) - d = -d; - - /* - * Calculate power-of-ten factor from exponent. - */ - if (exp < 0) - { - exp = -exp; - pwr = POWL(LD(10.0), exp); - d = d / pwr; - } else - { - pwr = POWL(LD(10.0), exp); - d = d * pwr; - } + fpu_debug(("make_packed str = %s\n",str)); fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); return d; @@ -621,88 +529,52 @@ PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 // from_pack PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) { - fpu_register pwr; - int exp; - fpu_register d; - bool sm, se; - int dig; - + int i; + int t; + char *cp; + char str[100]; + + sprintf(str, "%.16e", src); + + fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); + + cp = str; *wrd1 = *wrd2 = *wrd3 = 0; - - d = src; - sm = false; - if (isneg(src)) - { - d = -d; - sm = true; + if (*cp == '-') { + cp++; + *wrd1 = 0x80000000; + } + if (*cp == '+') + cp++; + *wrd1 |= (*cp++ - '0'); + if (*cp == '.') + cp++; + for (i = 0; i < 8; i++) { + *wrd2 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd2 |= *cp++ - '0'; + } + for (i = 0; i < 8; i++) { + *wrd3 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd3 |= *cp++ - '0'; + } + if (*cp == 'e' || *cp == 'E') { + cp++; + if (*cp == '-') { + cp++; + *wrd1 |= 0x40000000; + } + if (*cp == '+') + cp++; + t = 0; + for (i = 0; i < 3; i++) { + if (*cp >= '0' && *cp <= '9') + t = (t << 4) | (*cp++ - '0'); + } + *wrd1 |= t << 16; } - if (isnan(src)) - { - *wrd1 = sm ? 0xffff0000 : 0x7fff0000; - *wrd2 = 0xffffffff; - *wrd3 = 0xffffffff; - return; - } - if (isinf(src)) - { - *wrd1 = sm ? 0xffff0000 : 0x7fff0000; - *wrd2 = *wrd3 = 0; - return; - } - if (iszero(src)) - { - *wrd1 = sm ? 0x80000000 : 0x00000000; - *wrd2 = *wrd3 = 0; - return; - } - sm = false; - if (isneg(src)) - { - d = -d; - sm = true; - } - exp = (int)floor(LOG10L(d)); - se = false; - if (exp < 0) - { - exp = -exp; - se = true; - pwr = POWL(LD(10.0), exp); - d = d * pwr; - } else - { - pwr = POWL(LD(10.0), exp); - d = d / pwr; - } - dig = (int)d; d = LD(10) * (d - dig); *wrd1 |= dig; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 28; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 24; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 20; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 16; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 12; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 8; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 4; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 28; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 24; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 20; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 16; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 12; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 8; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 4; - dig = (int)d; *wrd3 |= dig; - - dig = (exp / 100) % 10; - *wrd1 |= dig << 24; - dig = (exp / 10) % 10; - *wrd1 |= dig << 20; - dig = (exp) % 10; - *wrd1 |= dig << 16; - if (sm) - *wrd1 |= 0x80000000; - if (se) - *wrd1 |= 0x40000000; fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -756,9 +628,11 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe break; case 3: ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -799,8 +673,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); fpu_debug(("get_fp_value ad=%X\n",ad)); fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); - //dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 ); - //dump_first_bytes( get_real_address(ad, 0, 0), 64 ); + dump_first_bytes( get_real_address(ad)-64, 64 ); + dump_first_bytes( get_real_address(ad), 64 ); switch (size) { case 0: @@ -847,15 +721,6 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe return 0; } - switch (mode) { - case 3: - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - break; - } - // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); return 1; } @@ -864,7 +729,7 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) { fpu_register result; - switch (get_fpcr() & FPCR_ROUNDING_MODE) { + switch (get_fpcr() & 0x30) { case FPCR_ROUND_ZERO: result = fp_round_to_zero(src); break; @@ -1086,7 +951,7 @@ PRIVATE inline int FFPU fpp_cond(int condition) if (NaN) N = Z = 0; - switch (condition & 0x1f) { + switch (condition) { case 0x00: CONDRET("False",0); case 0x01: CONDRET("Equal",Z); case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); @@ -1156,7 +1021,7 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) { fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - uae_u32 ad = 0; + uae_u32 ad; int cc = fpp_cond(extra & 0x3f); if (cc == -1) { m68k_setpc (m68k_getpc () - 4); @@ -1174,11 +1039,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) put_byte(ad, cc ? 0xff : 0x00); } -void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) { - fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); - int cc = fpp_cond(extra & 0x3f); + int cc = fpp_cond(opcode & 0x3f); if (cc == -1) { m68k_setpc (oldpc); op_illg (opcode); @@ -1210,7 +1075,7 @@ void FFPU fpuop_save(uae_u32 opcode) { fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); - uae_u32 ad = 0; + uae_u32 ad; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; int i; @@ -1271,7 +1136,7 @@ void FFPU fpuop_restore(uae_u32 opcode) { fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); - uae_u32 ad = 0; + uae_u32 ad; uae_u32 d; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; @@ -1468,7 +1333,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } else if (extra & 0x2000) { /* FMOVEM FPP->memory */ - uae_u32 ad = 0; + uae_u32 ad; int incr = 0; if (get_fp_ad(opcode, &ad) == 0) { @@ -1510,7 +1375,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } else { /* FMOVEM memory->FPP */ - uae_u32 ad = 0; + uae_u32 ad; if (get_fp_ad(opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); @@ -1556,7 +1421,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) return; case 6: case 7: { - uae_u32 ad = 0, list = 0; + uae_u32 ad, list = 0; int incr = 0; if (extra & 0x2000) { /* FMOVEM FPP->memory */ @@ -1703,27 +1568,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) switch (extra & 0x7f) { case 0x00: // FPU registers[reg] = 4.0 * atan(1.0); - FPU registers[reg] = LD(3.1415926535897932384626433832795029); + FPU registers[reg] = 3.1415926535897932384626433832795; fpu_debug(("FP const: Pi\n")); break; case 0x0b: // FPU registers[reg] = log10 (2.0); - FPU registers[reg] = LD(0.30102999566398119521); // 0.3010299956639811952137388947244930L + FPU registers[reg] = 0.30102999566398119521373889472449; fpu_debug(("FP const: Log 10 (2)\n")); break; case 0x0c: // FPU registers[reg] = exp (1.0); - FPU registers[reg] = LD(2.7182818284590452353); // 2.7182818284590452353602874713526625L + FPU registers[reg] = 2.7182818284590452353602874713527; fpu_debug(("FP const: e\n")); break; case 0x0d: // FPU registers[reg] = log (exp (1.0)) / log (2.0); - FPU registers[reg] = LD(1.4426950408889634073599246810019); + FPU registers[reg] = 1.4426950408889634073599246810019; fpu_debug(("FP const: Log 2 (e)\n")); break; case 0x0e: // FPU registers[reg] = log (exp (1.0)) / log (10.0); - FPU registers[reg] = LD(0.4342944819032518276511289189166051); + FPU registers[reg] = 0.43429448190325182765112891891661; fpu_debug(("FP const: Log 10 (e)\n")); break; case 0x0f: @@ -1732,70 +1597,70 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x30: // FPU registers[reg] = log (2.0); - FPU registers[reg] = LD(0.6931471805599453094172321214581766); + FPU registers[reg] = 0.69314718055994530941723212145818; fpu_debug(("FP const: ln(2)\n")); break; case 0x31: // FPU registers[reg] = log (10.0); - FPU registers[reg] = LD(2.3025850929940456840179914546843642); + FPU registers[reg] = 2.3025850929940456840179914546844; fpu_debug(("FP const: ln(10)\n")); break; case 0x32: // ?? - FPU registers[reg] = LD(1.0e0); + FPU registers[reg] = 1.0e0; fpu_debug(("FP const: 1.0e0\n")); break; case 0x33: - FPU registers[reg] = LD(1.0e1); + FPU registers[reg] = 1.0e1; fpu_debug(("FP const: 1.0e1\n")); break; case 0x34: - FPU registers[reg] = LD(1.0e2); + FPU registers[reg] = 1.0e2; fpu_debug(("FP const: 1.0e2\n")); break; case 0x35: - FPU registers[reg] = LD(1.0e4); + FPU registers[reg] = 1.0e4; fpu_debug(("FP const: 1.0e4\n")); break; case 0x36: - FPU registers[reg] = LD(1.0e8); + FPU registers[reg] = 1.0e8; fpu_debug(("FP const: 1.0e8\n")); break; case 0x37: - FPU registers[reg] = LD(1.0e16); + FPU registers[reg] = 1.0e16; fpu_debug(("FP const: 1.0e16\n")); break; case 0x38: - FPU registers[reg] = LD(1.0e32); + FPU registers[reg] = 1.0e32; fpu_debug(("FP const: 1.0e32\n")); break; case 0x39: - FPU registers[reg] = LD(1.0e64); + FPU registers[reg] = 1.0e64; fpu_debug(("FP const: 1.0e64\n")); break; case 0x3a: - FPU registers[reg] = LD(1.0e128); + FPU registers[reg] = 1.0e128; fpu_debug(("FP const: 1.0e128\n")); break; case 0x3b: - FPU registers[reg] = LD(1.0e256); + FPU registers[reg] = 1.0e256; fpu_debug(("FP const: 1.0e256\n")); break; -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE case 0x3c: - FPU registers[reg] = LD(1.0e512); + FPU registers[reg] = 1.0e512L; fpu_debug(("FP const: 1.0e512\n")); break; case 0x3d: - FPU registers[reg] = LD(1.0e1024); + FPU registers[reg] = 1.0e1024L; fpu_debug(("FP const: 1.0e1024\n")); break; case 0x3e: - FPU registers[reg] = LD(1.0e2048); + FPU registers[reg] = 1.0e2048L; fpu_debug(("FP const: 1.0e2048\n")); break; case 0x3f: - FPU registers[reg] = LD(1.0e4096); + FPU registers[reg] = 1.0e4096L; fpu_debug(("FP const: 1.0e4096\n")); #endif break; @@ -1896,20 +1761,20 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMUL %.04f\n",(double)src)); get_dest_flags(FPU registers[reg]); get_source_flags(src); - if (fl_dest.in_range && fl_source.in_range) { + if(fl_dest.in_range && fl_source.in_range) { if ((extra & 0x7f) == 0x63) FPU registers[reg] = (float)(FPU registers[reg] * src); else FPU registers[reg] = (double)(FPU registers[reg] * src); } else if (fl_dest.nan || fl_source.nan || - (fl_dest.zero && fl_source.infinity) || - (fl_dest.infinity && fl_source.zero) ) { + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { make_nan( FPU registers[reg] ); } else if (fl_dest.zero || fl_source.zero ) { - if ( (fl_dest.negative && !fl_source.negative) || - (!fl_dest.negative && fl_source.negative) ) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { make_zero_negative(FPU registers[reg]); } else { @@ -1917,8 +1782,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } } else { - if ( (fl_dest.negative && !fl_source.negative) || - (!fl_dest.negative && fl_source.negative) ) { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { make_inf_negative(FPU registers[reg]); } else { @@ -2102,21 +1967,17 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMUL %.04f\n",(double)src)); get_dest_flags(FPU registers[reg]); get_source_flags(src); - if (fl_dest.in_range && fl_source.in_range) { + if(fl_dest.in_range && fl_source.in_range) { FPU registers[reg] *= src; - if (unlikely(isinf(FPU registers[reg]))) - { - isneg(FPU registers[reg]) ? make_inf_negative(FPU registers[reg]) : make_inf_positive(FPU registers[reg]); - } } else if (fl_dest.nan || fl_source.nan || - (fl_dest.zero && fl_source.infinity) || - (fl_dest.infinity && fl_source.zero) ) { + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { make_nan( FPU registers[reg] ); } else if (fl_dest.zero || fl_source.zero ) { - if ( (fl_dest.negative && !fl_source.negative) || - (!fl_dest.negative && fl_source.negative) ) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { make_zero_negative(FPU registers[reg]); } else { @@ -2124,8 +1985,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } } else { - if ( (fl_dest.negative && !fl_source.negative) || - (!fl_dest.negative && fl_source.negative) ) { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { make_inf_negative(FPU registers[reg]); } else { @@ -2161,23 +2022,19 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) // an overflow or underflow always results. // Here (int) cast is okay. int scale_factor = (int)fp_round_to_zero(src); -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = FPU registers[reg]; - sxp.ieee.exponent += scale_factor; - FPU registers[reg] = sxp.value; +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, FPU registers[reg], extended); + sxp->ieee.exponent += scale_factor; #else - fp_declare_init_shape(sxp, double); - sxp.value = FPU registers[reg]; - uae_u32 exp = sxp.ieee.exponent + scale_factor; + fp_declare_init_shape(sxp, FPU registers[reg], double); + uae_u32 exp = sxp->ieee.exponent + scale_factor; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) exp = 0; else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) exp = FP_DOUBLE_EXP_MAX; else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - sxp.ieee.exponent = exp; - FPU registers[reg] = sxp.value; + sxp->ieee.exponent = exp; #endif } else if (fl_source.infinity) { @@ -2199,10 +2056,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x22: /* FADD */ fpu_debug(("FADD %.04f\n",(double)src)); FPU registers[reg] += src; - if (unlikely(isinf(FPU registers[reg]))) - { - isneg(FPU registers[reg]) ? make_inf_negative(FPU registers[reg]) : make_inf_positive(FPU registers[reg]); - } make_fpsr(FPU registers[reg]); break; case 0x30: /* FSINCOS */ @@ -2223,17 +2076,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x38: /* FCMP */ fpu_debug(("FCMP %.04f\n",(double)src)); set_fpsr(0); - if (isinf(FPU registers[reg])) - { - if (isinf(src) && isneg(FPU registers[reg]) == isneg (src)) - make_fpsr(0); - else - make_fpsr(FPU registers[reg]); - } - else if (isinf(src)) - make_fpsr(-src); - else - make_fpsr(FPU registers[reg] - src); + make_fpsr(FPU registers[reg] - src); break; case 0x3a: /* FTST */ fpu_debug(("FTST %.04f\n",(double)src)); @@ -2257,27 +2100,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) dump_registers( "END "); } - -void fpu_set_fpsr(uae_u32 new_fpsr) -{ - set_fpsr(new_fpsr); -} - -uae_u32 fpu_get_fpsr(void) -{ - return get_fpsr(); -} - -void fpu_set_fpcr(uae_u32 new_fpcr) -{ - set_fpcr(new_fpcr); -} - -uae_u32 fpu_get_fpcr(void) -{ - return get_fpcr(); -} - /* -------------------------- Initialization -------------------------- */ PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h index 3321891a..89501956 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h @@ -1,33 +1,28 @@ /* - * fpu/fpu_ieee.h - Extra Definitions for the IEEE FPU core + * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_IEEE_H @@ -65,7 +60,7 @@ PRIVATE inline void FFPU make_zero_negative(fpu_register & r); PRIVATE inline void FFPU make_inf_positive(fpu_register & r); PRIVATE inline void FFPU make_inf_negative(fpu_register & r); -// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); +PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); // May be optimized for particular processors diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp deleted file mode 100644 index 1975aba8..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp +++ /dev/null @@ -1,2110 +0,0 @@ -/* - * fpu_mpfr.cpp - emulate 68881/68040 fpu with mpfr - * - * Copyright (c) 2012, 2013 Andreas Schwab - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "sysdeps.h" -#include -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#include "main.h" -#define FPU_IMPLEMENTATION -#include "fpu/fpu.h" - -#include "fpu/flags.h" -#include "fpu/exceptions.h" -#include "fpu/rounding.h" -#include "fpu/impl.h" - -#define SINGLE_PREC 24 -#define SINGLE_MIN_EXP -126 -#define SINGLE_MAX_EXP 127 -#define SINGLE_BIAS 127 -#define DOUBLE_PREC 53 -#define DOUBLE_MIN_EXP -1022 -#define DOUBLE_MAX_EXP 1023 -#define DOUBLE_BIAS 1023 -#define EXTENDED_PREC 64 -#define EXTENDED_MIN_EXP -16383 -#define EXTENDED_MAX_EXP 16383 -#define EXTENDED_BIAS 16383 - -fpu_t fpu; -// The constant ROM -// Constants 48 to 63 are mapped to index 16 to 31 -const int num_fpu_constants = 32; -static mpfr_t fpu_constant_rom[num_fpu_constants]; -#define FPU_CONSTANT_ONE fpu_constant_rom[18] -// Exceptions generated during execution in addition to the ones -// maintained by mpfr -static uae_u32 cur_exceptions; -static uaecptr cur_instruction_address; - -static void -set_format (int prec) -{ - // MPFR represents numbers as 0.m*2^e - switch (prec) - { - case SINGLE_PREC: - mpfr_set_emin (SINGLE_MIN_EXP + 1 - (SINGLE_PREC - 1)); - mpfr_set_emax (SINGLE_MAX_EXP + 1); - break; - case DOUBLE_PREC: - mpfr_set_emin (DOUBLE_MIN_EXP + 1 - (DOUBLE_PREC - 1)); - mpfr_set_emax (DOUBLE_MAX_EXP + 1); - break; - case EXTENDED_PREC: - mpfr_set_emin (EXTENDED_MIN_EXP + 1 - (EXTENDED_PREC - 1)); - mpfr_set_emax (EXTENDED_MAX_EXP + 1); - break; - } -} - -static mpfr_rnd_t -get_cur_rnd () -{ - switch (get_rounding_mode ()) - { - default: - case FPCR_ROUND_NEAR: - return MPFR_RNDN; - case FPCR_ROUND_ZERO: - return MPFR_RNDZ; - case FPCR_ROUND_MINF: - return MPFR_RNDD; - case FPCR_ROUND_PINF: - return MPFR_RNDU; - } -} - -static mpfr_prec_t -get_cur_prec () -{ - switch (get_rounding_precision ()) - { - default: - case FPCR_PRECISION_EXTENDED: - return EXTENDED_PREC; - case FPCR_PRECISION_SINGLE: - return SINGLE_PREC; - case FPCR_PRECISION_DOUBLE: - return DOUBLE_PREC; - } -} - -#define DEFAULT_NAN_BITS 0xffffffffffffffffULL - -static void -set_nan (fpu_register ®, uae_u64 nan_bits, int nan_sign) -{ - mpfr_set_nan (reg.f); - reg.nan_bits = nan_bits; - reg.nan_sign = nan_sign; -} - -static void -set_nan (fpu_register ®) -{ - set_nan (reg, DEFAULT_NAN_BITS, 0); -} - -static bool fpu_inited; - -void -fpu_init (bool integral_68040) -{ - fpu.is_integral = integral_68040; - - mpfr_set_default_prec (EXTENDED_PREC); - mpfr_set_default_rounding_mode (MPFR_RNDN); - set_format (EXTENDED_PREC); - - for (int i = 0; i < 8; i++) - mpfr_init (fpu.registers[i].f); - mpfr_init (fpu.result.f); - - // Initialize constant ROM - for (int i = 0; i < num_fpu_constants; i++) - mpfr_init (fpu_constant_rom[i]); - - // 0: pi - mpfr_const_pi (fpu_constant_rom[0], MPFR_RNDN); - // 11: log10 (2) - mpfr_set_ui (fpu_constant_rom[11], 2, MPFR_RNDN); - mpfr_log10 (fpu_constant_rom[11], fpu_constant_rom[11], MPFR_RNDZ); - // 12: e - mpfr_set_ui (fpu_constant_rom[12], 1, MPFR_RNDN); - mpfr_exp (fpu_constant_rom[12], fpu_constant_rom[12], MPFR_RNDZ); - // 13: log2 (e) - mpfr_log2 (fpu_constant_rom[13], fpu_constant_rom[12], MPFR_RNDU); - // 14: log10 (e) - mpfr_log10 (fpu_constant_rom[14], fpu_constant_rom[12], MPFR_RNDU); - // 15: 0 - mpfr_set_zero (fpu_constant_rom[15], 0); - // 48: ln (2) - mpfr_const_log2 (fpu_constant_rom[16], MPFR_RNDN); - // 49: ln (10) - mpfr_set_ui (fpu_constant_rom[17], 10, MPFR_RNDN); - mpfr_log (fpu_constant_rom[17], fpu_constant_rom[17], MPFR_RNDN); - // 50 to 63: powers of 10 - mpfr_set_ui (fpu_constant_rom[18], 1, MPFR_RNDN); - for (int i = 19; i < 32; i++) - { - mpfr_set_ui (fpu_constant_rom[i], 1L << (i - 19) , MPFR_RNDN); - mpfr_exp10 (fpu_constant_rom[i], fpu_constant_rom[i], MPFR_RNDN); - } - - fpu_inited = true; - - fpu_reset (); -} - -void -fpu_exit () -{ - if (!fpu_inited) return; - - for (int i = 0; i < 8; i++) - mpfr_clear (fpu.registers[i].f); - mpfr_clear (fpu.result.f); - for (int i = 0; i < num_fpu_constants; i++) - mpfr_clear (fpu_constant_rom[i]); -} - -void -fpu_reset () -{ - set_fpcr (0); - set_fpsr (0); - fpu.instruction_address = 0; - - for (int i = 0; i < 8; i++) - set_nan (fpu.registers[i]); -} - -fpu_register::operator long double () -{ - return mpfr_get_ld (f, MPFR_RNDN); -} - -fpu_register & -fpu_register::operator= (long double x) -{ - mpfr_set_ld (f, x, MPFR_RNDN); - nan_bits = DEFAULT_NAN_BITS; - nan_sign = 0; - return *this; -} - -static bool -get_fp_addr (uae_u32 opcode, uae_u32 *addr, bool write) -{ - uaecptr pc; - int mode; - int reg; - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) - { - case 0: - case 1: - return false; - case 2: - *addr = m68k_areg (regs, reg); - break; - case 3: - *addr = m68k_areg (regs, reg); - break; - case 4: - *addr = m68k_areg (regs, reg); - break; - case 5: - *addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); - break; - case 6: - *addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) - { - case 0: - *addr = (uae_s16) next_iword(); - break; - case 1: - *addr = next_ilong(); - break; - case 2: - if (write) - return false; - pc = m68k_getpc (); - *addr = pc + (uae_s16) next_iword(); - break; - case 3: - if (write) - return false; - pc = m68k_getpc (); - *addr = get_disp_ea_020 (pc, next_iword()); - break; - default: - return false; - } - } - return true; -} - -static void -set_from_single (fpu_register &value, uae_u32 data) -{ - int s = data >> 31; - int e = (data >> 23) & 0xff; - uae_u32 m = data & 0x7fffff; - - if (e == 0xff) - { - if (m != 0) - { - if (!(m & 0x400000)) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - set_nan (value, (uae_u64) (m | 0xc00000) << (32 + 8), s); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - if (e != 0) - // Add integer bit - m |= 0x800000; - else - e++; - // Remove bias - e -= SINGLE_BIAS; - mpfr_set_ui_2exp (value.f, m, e - (SINGLE_PREC - 1), MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, s, MPFR_RNDN); -} - -static void -set_from_double (fpu_register &value, uae_u32 words[2]) -{ - int s = words[0] >> 31; - int e = (words[0] >> 20) & 0x7ff; - uae_u32 m = words[0] & 0xfffff; - - if (e == 0x7ff) - { - if ((m | words[1]) != 0) - { - if (!(m & 0x80000)) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - set_nan (value, (((uae_u64) (m | 0x180000) << (32 + 11)) - | ((uae_u64) words[1] << 11)), s); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - if (e != 0) - // Add integer bit - m |= 0x100000; - else - e++; - // Remove bias - e -= DOUBLE_BIAS; - mpfr_set_uj_2exp (value.f, ((uintmax_t) m << 32) | words[1], - e - (DOUBLE_PREC - 1), MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, s, MPFR_RNDN); -} - -static void -set_from_extended (fpu_register &value, uae_u32 words[3], bool check_snan) -{ - int s = words[0] >> 31; - int e = (words[0] >> 16) & 0x7fff; - - if (e == 0x7fff) - { - if (((words[1] & 0x7fffffff) | words[2]) != 0) - { - if (check_snan) - { - if ((words[1] & 0x40000000) == 0) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - words[1] |= 0x40000000; - } - set_nan (value, ((uae_u64) words[1] << 32) | words[2], s); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - // Remove bias - e -= EXTENDED_BIAS; - mpfr_set_uj_2exp (value.f, ((uintmax_t) words[1] << 32) | words[2], - e - (EXTENDED_PREC - 1), MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, s, MPFR_RNDN); -} - -#define from_bcd(d) ((d) < 10 ? (d) : (d) - 10) - -static void -set_from_packed (fpu_register &value, uae_u32 words[3]) -{ - char str[32], *p = str; - int sm = words[0] >> 31; - int se = (words[0] >> 30) & 1; - int i; - - if (((words[0] >> 16) & 0x7fff) == 0x7fff) - { - if ((words[1] | words[2]) != 0) - { - if ((words[1] & 0x40000000) == 0) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - set_nan (value, ((uae_u64) (words[1] | 0x40000000) << 32) | words[2], - sm); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - if (sm) - *p++ = '-'; - *p++ = from_bcd (words[0] & 15) + '0'; - *p++ = '.'; - for (i = 0; i < 8; i++) - { - p[i] = from_bcd ((words[1] >> (28 - i * 4)) & 15) + '0'; - p[i + 8] = from_bcd ((words[2] >> (28 - i * 4)) & 15) + '0'; - } - p += 16; - *p++ = 'e'; - if (se) - *p++ = '-'; - *p++ = from_bcd ((words[0] >> 24) & 15) + '0'; - *p++ = from_bcd ((words[0] >> 20) & 15) + '0'; - *p++ = from_bcd ((words[0] >> 16) & 15) + '0'; - *p = 0; - mpfr_set_str (value.f, str, 10, MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, sm, MPFR_RNDN); -} - -static bool -get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register &value) -{ - int mode, reg, size; - uaecptr pc; - uae_u32 addr; - uae_u32 words[3]; - static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - if ((extra & 0x4000) == 0) - { - mpfr_set (value.f, fpu.registers[(extra >> 10) & 7].f, MPFR_RNDN); - value.nan_bits = fpu.registers[(extra >> 10) & 7].nan_bits; - value.nan_sign = fpu.registers[(extra >> 10) & 7].nan_sign; - /* Check for SNaN. */ - if (mpfr_nan_p (value.f) && (value.nan_bits & (1ULL << 62)) == 0) - { - value.nan_bits |= 1ULL << 62; - cur_exceptions |= FPSR_EXCEPTION_SNAN; - } - return true; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - switch (mode) - { - case 0: - switch (size) - { - case 6: - mpfr_set_si (value.f, (uae_s8) m68k_dreg (regs, reg), MPFR_RNDN); - break; - case 4: - mpfr_set_si (value.f, (uae_s16) m68k_dreg (regs, reg), MPFR_RNDN); - break; - case 0: - mpfr_set_si (value.f, (uae_s32) m68k_dreg (regs, reg), MPFR_RNDN); - break; - case 1: - set_from_single (value, m68k_dreg (regs, reg)); - break; - default: - return false; - } - return true; - case 1: - return false; - case 2: - case 3: - addr = m68k_areg (regs, reg); - break; - case 4: - addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); - break; - case 5: - addr = m68k_areg (regs, reg) + (uae_s16) next_iword (); - break; - case 6: - addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); - break; - case 7: - switch (reg) - { - case 0: - addr = (uae_s16) next_iword (); - break; - case 1: - addr = next_ilong (); - break; - case 2: - pc = m68k_getpc (); - addr = pc + (uae_s16) next_iword (); - break; - case 3: - pc = m68k_getpc (); - addr = get_disp_ea_020 (pc, next_iword ()); - break; - case 4: - addr = m68k_getpc (); - m68k_incpc (sz2[size]); - if (size == 6) // Immediate byte - addr++; - break; - default: - return false; - } - } - - switch (size) - { - case 0: - mpfr_set_si (value.f, (uae_s32) get_long (addr), MPFR_RNDN); - break; - case 1: - set_from_single (value, get_long (addr)); - break; - case 2: - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - words[2] = get_long (addr + 8); - set_from_extended (value, words, true); - break; - case 3: - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - words[2] = get_long (addr + 8); - set_from_packed (value, words); - break; - case 4: - mpfr_set_si (value.f, (uae_s16) get_word (addr), MPFR_RNDN); - break; - case 5: - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - set_from_double (value, words); - break; - case 6: - mpfr_set_si (value.f, (uae_s8) get_byte (addr), MPFR_RNDN); - break; - default: - return false; - } - - switch (mode) - { - case 3: - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - break; - } - - return true; -} - -static void -update_exceptions () -{ - uae_u32 exc, aexc; - - exc = cur_exceptions; - // Add any mpfr detected exceptions - if (mpfr_underflow_p ()) - exc |= FPSR_EXCEPTION_UNFL; - if (mpfr_overflow_p ()) - exc |= FPSR_EXCEPTION_OVFL; - if (mpfr_inexflag_p ()) - exc |= FPSR_EXCEPTION_INEX2; - set_exception_status (exc); - - aexc = get_accrued_exception (); - if (exc & (FPSR_EXCEPTION_SNAN|FPSR_EXCEPTION_OPERR)) - aexc |= FPSR_ACCR_IOP; - if (exc & FPSR_EXCEPTION_OVFL) - aexc |= FPSR_ACCR_OVFL; - if ((exc & (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) - == (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) - aexc |= FPSR_ACCR_UNFL; - if (exc & FPSR_EXCEPTION_DZ) - aexc |= FPSR_ACCR_DZ; - if (exc & (FPSR_EXCEPTION_INEX1|FPSR_EXCEPTION_INEX2|FPSR_EXCEPTION_OVFL)) - aexc |= FPSR_ACCR_INEX; - set_accrued_exception (aexc); - - if ((fpu.fpcr.exception_enable & exc) != 0) - { - fpu.instruction_address = cur_instruction_address; - // TODO: raise exceptions - // Problem: FPSP040 depends on proper FPU stack frames, it would suffer - // undefined behaviour with our dummy FSAVE implementation - } -} - -static void -set_fp_register (int reg, mpfr_t value, uae_u64 nan_bits, int nan_sign, - int t, mpfr_rnd_t rnd, bool do_flags) -{ - mpfr_subnormalize (value, t, rnd); - mpfr_set (fpu.registers[reg].f, value, rnd); - fpu.registers[reg].nan_bits = nan_bits; - fpu.registers[reg].nan_sign = nan_sign; - if (do_flags) - { - uae_u32 flags = 0; - - if (mpfr_zero_p (fpu.registers[reg].f)) - flags |= FPSR_CCB_ZERO; - if (mpfr_signbit (fpu.registers[reg].f)) - flags |= FPSR_CCB_NEGATIVE; - if (mpfr_nan_p (fpu.registers[reg].f)) - flags |= FPSR_CCB_NAN; - if (mpfr_inf_p (fpu.registers[reg].f)) - flags |= FPSR_CCB_INFINITY; - set_fpccr (flags); - } -} - -static void -set_fp_register (int reg, mpfr_t value, int t, mpfr_rnd_t rnd, bool do_flags) -{ - set_fp_register (reg, value, DEFAULT_NAN_BITS, 0, t, rnd, do_flags); -} - -static void -set_fp_register (int reg, fpu_register &value, int t, mpfr_rnd_t rnd, - bool do_flags) -{ - set_fp_register (reg, value.f, value.nan_bits, value.nan_sign, t, rnd, - do_flags); -} - -static uae_u32 -extract_to_single (fpu_register &value) -{ - uae_u32 word; - int t; - mpfr_rnd_t rnd = get_cur_rnd (); - MPFR_DECL_INIT (single, SINGLE_PREC); - - set_format (SINGLE_PREC); - // Round to single - t = mpfr_set (single, value.f, rnd); - t = mpfr_check_range (single, t, rnd); - mpfr_subnormalize (single, t, rnd); - set_format (EXTENDED_PREC); - - if (mpfr_inf_p (single)) - word = 0x7f800000; - else if (mpfr_nan_p (single)) - { - if ((value.nan_bits & (1ULL << 62)) == 0) - { - value.nan_bits |= 1ULL << 62; - cur_exceptions |= FPSR_EXCEPTION_SNAN; - } - word = 0x7f800000 | ((value.nan_bits >> (32 + 8)) & 0x7fffff); - if (value.nan_sign) - word |= 0x80000000; - } - else if (mpfr_zero_p (single)) - word = 0; - else - { - int e; - mpz_t f; - mpz_init (f); - word = 0; - // Get exponent and mantissa - e = mpfr_get_z_2exp (f, single); - // Move binary point - e += SINGLE_PREC - 1; - // Add bias - e += SINGLE_BIAS; - if (e <= 0) - { - // Denormalized number - mpz_tdiv_q_2exp (f, f, -e + 1); - e = 0; - } - mpz_export (&word, 0, 1, 4, 0, 0, f); - // Remove integer bit - word &= 0x7fffff; - word |= e << 23; - mpz_clear (f); - } - if (mpfr_signbit (single)) - word |= 0x80000000; - return word; -} - -static void -extract_to_double (fpu_register &value, uint32_t *words) -{ - int t; - mpfr_rnd_t rnd = get_cur_rnd (); - MPFR_DECL_INIT (dbl, DOUBLE_PREC); - - set_format (DOUBLE_PREC); - // Round to double - t = mpfr_set (dbl, value.f, rnd); - t = mpfr_check_range (dbl, t, rnd); - mpfr_subnormalize (dbl, t, rnd); - set_format (EXTENDED_PREC); - - if (mpfr_inf_p (dbl)) - { - words[0] = 0x7ff00000; - words[1] = 0; - } - else if (mpfr_nan_p (dbl)) - { - if ((value.nan_bits & (1ULL << 62)) == 0) - { - value.nan_bits |= 1ULL << 62; - cur_exceptions |= FPSR_EXCEPTION_SNAN; - } - words[0] = 0x7ff00000 | ((value.nan_bits >> (32 + 11)) & 0xfffff); - words[1] = value.nan_bits >> 11; - if (value.nan_sign) - words[0] |= 0x80000000; - } - else if (mpfr_zero_p (dbl)) - { - words[0] = 0; - words[1] = 0; - } - else - { - int e, off = 0; - mpz_t f; - mpz_init (f); - words[0] = words[1] = 0; - // Get exponent and mantissa - e = mpfr_get_z_2exp (f, dbl); - // Move binary point - e += DOUBLE_PREC - 1; - // Add bias - e += DOUBLE_BIAS; - if (e <= 0) - { - // Denormalized number - mpz_tdiv_q_2exp (f, f, -e + 1); - if (e <= -20) - // No more than 32 bits left - off = 1; - e = 0; - } - mpz_export (&words[off], 0, 1, 4, 0, 0, f); - // Remove integer bit - words[0] &= 0xfffff; - words[0] |= e << 20; - mpz_clear (f); - } - if (mpfr_signbit (dbl)) - words[0] |= 0x80000000; -} - -static void -extract_to_extended (fpu_register &value, uint32_t *words) -{ - if (mpfr_inf_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = 0; - words[2] = 0; - } - else if (mpfr_nan_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = value.nan_bits >> 32; - words[2] = value.nan_bits; - if (value.nan_sign) - words[0] |= 0x80000000; - } - else if (mpfr_zero_p (value.f)) - { - words[0] = 0; - words[1] = 0; - words[2] = 0; - } - else - { - int e, off = 0; - mpz_t f; - - mpz_init (f); - words[0] = words[1] = words[2] = 0; - // Get exponent and mantissa - e = mpfr_get_z_2exp (f, value.f); - // Move binary point - e += EXTENDED_PREC - 1; - // Add bias - e += EXTENDED_BIAS; - if (e < 0) - { - // Denormalized number - mpz_tdiv_q_2exp (f, f, -e); - if (e <= -32) - // No more than 32 bits left - off = 1; - e = 0; - } - mpz_export (&words[1 + off], 0, 1, 4, 0, 0, f); - words[0] = e << 16; - mpz_clear (f); - } - if (mpfr_signbit (value.f)) - words[0] |= 0x80000000; -} - -static void -extract_to_packed (fpu_register &value, int k, uae_u32 *words) -{ - if (mpfr_inf_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = 0; - words[2] = 0; - } - else if (mpfr_nan_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = value.nan_bits >> 32; - words[2] = value.nan_bits; - if (value.nan_sign) - words[0] |= 0x80000000; - } - else if (mpfr_zero_p (value.f)) - { - words[0] = 0; - words[1] = 0; - words[2] = 0; - } - else - { - char str[100], *p = str; - mpfr_exp_t e; - mpfr_rnd_t rnd = get_cur_rnd (); - - words[0] = words[1] = words[2] = 0; - if (k >= 64) - k -= 128; - else if (k >= 18) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - if (k <= 0) - { - MPFR_DECL_INIT (temp, 16); - - mpfr_log10 (temp, value.f, rnd); - k = mpfr_get_si (temp, MPFR_RNDZ) - k + 1; - } - if (k <= 0) - k = 1; - else if (k >= 18) - k = 17; - mpfr_get_str (str, &e, 10, k, value.f, rnd); - e--; - if (*p == '-') - p++; - // Pad to 17 digits - while (k < 17) - p[k++] = '0'; - if (e < 0) - { - words[0] |= 0x40000000; - e = -e; - } - words[0] |= (e % 10) << 16; - e /= 10; - words[0] |= (e % 10) << 20; - e /= 10; - words[0] |= (e % 10) << 24; - e /= 10; - if (e) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - words[0] |= e << 12; - words[0] |= *p++ & 15; - for (k = 0; k < 8; k++) - words[1] = (words[1] << 4) | (*p++ & 15); - for (k = 0; k < 8; k++) - words[2] = (words[2] << 4) | (*p++ & 15); - - } - if (mpfr_signbit (value.f)) - words[0] |= 0x80000000; -} - -static long -extract_to_integer (mpfr_t value, long min, long max) -{ - long result; - mpfr_rnd_t rnd = get_cur_rnd (); - - if (mpfr_fits_slong_p (value, rnd)) - { - result = mpfr_get_si (value, rnd); - if (result > max) - { - result = max; - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (result < min) - { - result = min; - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - } - else - { - if (!mpfr_signbit (value)) - result = max; - else - result = min; - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - return result; -} - -static bool -fpuop_fmove_memory (uae_u32 opcode, uae_u32 extra) -{ - int mode, reg, size; - uaecptr pc; - uae_u32 addr; - uae_u32 words[3]; - static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - mpfr_clear_flags (); - cur_exceptions = 0; - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - fpu_register &value = fpu.registers[(extra >> 7) & 7]; - - switch (mode) - { - case 0: - switch (size) - { - case 0: - m68k_dreg (regs, reg) = extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff); - break; - case 1: - m68k_dreg (regs, reg) = extract_to_single (value); - break; - case 4: - m68k_dreg (regs, reg) &= ~0xffff; - m68k_dreg (regs, reg) |= extract_to_integer (value.f, -32768, 32767) & 0xffff; - break; - case 6: - m68k_dreg (regs, reg) &= ~0xff; - m68k_dreg (regs, reg) |= extract_to_integer (value.f, -128, 127) & 0xff; - break; - default: - return false; - } - update_exceptions (); - return true; - case 1: - return false; - case 2: - addr = m68k_areg (regs, reg); - break; - case 3: - addr = m68k_areg (regs, reg); - break; - case 4: - addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); - break; - case 5: - addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); - break; - case 6: - addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) - { - case 0: - addr = (uae_s16) next_iword(); - break; - case 1: - addr = next_ilong(); - break; - case 2: - pc = m68k_getpc (); - addr = pc + (uae_s16) next_iword(); - break; - case 3: - pc = m68k_getpc (); - addr = get_disp_ea_020 (pc, next_iword ()); - break; - case 4: - addr = m68k_getpc (); - m68k_incpc (sz2[size]); - break; - default: - return false; - } - } - - switch (size) - { - case 0: - put_long (addr, extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff)); - break; - case 1: - put_long (addr, extract_to_single (value)); - break; - case 2: - extract_to_extended (value, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - break; - case 3: - extract_to_packed (value, extra & 0x7f, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - break; - case 4: - put_word (addr, extract_to_integer (value.f, -32768, 32767)); - break; - case 5: - extract_to_double (value, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - break; - case 6: - put_byte (addr, extract_to_integer (value.f, -128, 127)); - break; - case 7: - extract_to_packed (value, m68k_dreg (regs, (extra >> 4) & 7) & 0x7f, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - break; - } - - switch (mode) - { - case 3: - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - break; - } - - update_exceptions (); - return true; -} - -static bool -fpuop_fmovem_control (uae_u32 opcode, uae_u32 extra) -{ - int list, mode, reg; - uae_u32 addr; - - list = (extra >> 10) & 7; - mode = (opcode >> 3) & 7; - reg = opcode & 7; - - if (list == 0) - return false; - - if (extra & 0x2000) - { - // FMOVEM to - if (mode == 0) - { - switch (list) - { - case 1: - m68k_dreg (regs, reg) = fpu.instruction_address; - break; - case 2: - m68k_dreg (regs, reg) = get_fpsr (); - break; - case 4: - m68k_dreg (regs, reg) = get_fpcr (); - break; - default: - return false; - } - } - else if (mode == 1) - { - if (list != 1) - return false; - m68k_areg (regs, reg) = fpu.instruction_address; - } - else - { - int nwords; - - if (!get_fp_addr (opcode, &addr, true)) - return false; - nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); - if (mode == 4) - addr -= nwords * 4; - if (list & 4) - { - put_long (addr, get_fpcr ()); - addr += 4; - } - if (list & 2) - { - put_long (addr, get_fpsr ()); - addr += 4; - } - if (list & 1) - { - put_long (addr, fpu.instruction_address); - addr += 4; - } - if (mode == 4) - m68k_areg (regs, reg) = addr - nwords * 4; - else if (mode == 3) - m68k_areg (regs, reg) = addr; - } - } - else - { - // FMOVEM from - - if (mode == 0) - { - switch (list) - { - case 1: - fpu.instruction_address = m68k_dreg (regs, reg); - break; - case 2: - set_fpsr (m68k_dreg (regs, reg)); - break; - case 4: - set_fpcr (m68k_dreg (regs, reg)); - break; - default: - return false; - } - } - else if (mode == 1) - { - if (list != 1) - return false; - fpu.instruction_address = m68k_areg (regs, reg); - } - else if ((opcode & 077) == 074) - { - switch (list) - { - case 1: - fpu.instruction_address = next_ilong (); - break; - case 2: - set_fpsr (next_ilong ()); - break; - case 4: - set_fpcr (next_ilong ()); - break; - default: - return false; - } - } - else - { - int nwords; - - if (!get_fp_addr (opcode, &addr, false)) - return false; - nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); - if (mode == 4) - addr -= nwords * 4; - if (list & 4) - { - set_fpcr (get_long (addr)); - addr += 4; - } - if (list & 2) - { - set_fpsr (get_long (addr)); - addr += 4; - } - if (list & 1) - { - fpu.instruction_address = get_long (addr); - addr += 4; - } - if (mode == 4) - m68k_areg (regs, reg) = addr - nwords * 4; - else if (mode == 3) - m68k_areg (regs, reg) = addr; - } - } - - return true; -} - -static bool -fpuop_fmovem_register (uae_u32 opcode, uae_u32 extra) -{ - uae_u32 addr; - uae_u32 words[3]; - int list; - int i; - - set_format (EXTENDED_PREC); - if (!get_fp_addr (opcode, &addr, extra & 0x2000)) - return false; - if (extra & 0x800) - list = m68k_dreg (regs, (extra >> 4) & 7) & 0xff; - else - list = extra & 0xff; - - if (extra & 0x2000) - { - // FMOVEM to memory - - switch (opcode & 070) - { - case 030: - return false; - case 040: - if (extra & 0x1000) - return false; - for (i = 7; i >= 0; i--) - if (list & (1 << i)) - { - extract_to_extended (fpu.registers[i], words); - addr -= 12; - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - } - m68k_areg (regs, opcode & 7) = addr; - break; - default: - if ((extra & 0x1000) == 0) - return false; - for (i = 0; i < 8; i++) - if (list & (0x80 >> i)) - { - extract_to_extended (fpu.registers[i], words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - addr += 12; - } - if ((opcode & 070) == 030) - m68k_areg (regs, opcode & 7) = addr; - break; - } - } - else - { - // FMOVEM from memory - - if ((opcode & 070) == 040) - return false; - - if ((extra & 0x1000) == 0) - return false; - for (i = 0; i < 8; i++) - if (list & (0x80 >> i)) - { - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - words[2] = get_long (addr + 8); - addr += 12; - set_from_extended (fpu.registers[i], words, false); - } - if ((opcode & 070) == 030) - m68k_areg (regs, opcode & 7) = addr; - } - return true; -} - -static int -do_getexp (mpfr_t value, mpfr_rnd_t rnd) -{ - int t = 0; - - if (mpfr_inf_p (value)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) - t = mpfr_set_si (value, mpfr_get_exp (value) - 1, rnd); - return t; -} - -static int -do_getman (mpfr_t value) -{ - if (mpfr_inf_p (value)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) - mpfr_set_exp (value, 1); - return 0; -} - -static int -do_scale (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) -{ - long scale; - int t = 0; - - if (mpfr_nan_p (value)) - ; - else if (mpfr_inf_p (value)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_fits_slong_p (value, rnd)) - { - scale = mpfr_get_si (value, MPFR_RNDZ); - mpfr_clear_inexflag (); - t = mpfr_mul_2si (value, reg, scale, rnd); - } - else - mpfr_set_inf (value, -mpfr_signbit (value)); - return t; -} - -static int -do_remainder (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) -{ - long quo; - int t = 0; - - if (mpfr_nan_p (value) || mpfr_nan_p (reg)) - ; - else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_remquo (value, &quo, reg, value, rnd); - if (quo < 0) - quo = (-quo & 0x7f) | 0x80; - else - quo &= 0x7f; - fpu.fpsr.quotient = quo << 16; - return t; -} - -// Unfortunately, mpfr_fmod does not return the quotient bits, so we -// have to reimplement it here -static int -mpfr_rem1 (mpfr_t rem, int *quo, mpfr_t x, mpfr_t y, mpfr_rnd_t rnd) -{ - mpfr_exp_t ex, ey; - int inex, sign, signx = mpfr_signbit (x); - mpz_t mx, my, r; - - mpz_init (mx); - mpz_init (my); - mpz_init (r); - - ex = mpfr_get_z_2exp (mx, x); /* x = mx*2^ex */ - ey = mpfr_get_z_2exp (my, y); /* y = my*2^ey */ - - /* to get rid of sign problems, we compute it separately: - quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y) - quo(-x,y) = -quo(x,y), rem(-x,y) = -rem(x,y) - thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */ - sign = (signx != mpfr_signbit (y)); - mpz_abs (mx, mx); - mpz_abs (my, my); - - /* divide my by 2^k if possible to make operations mod my easier */ - { - unsigned long k = mpz_scan1 (my, 0); - ey += k; - mpz_fdiv_q_2exp (my, my, k); - } - - if (ex <= ey) - { - /* q = x/y = mx/(my*2^(ey-ex)) */ - mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */ - /* 0 <= |r| <= |my|, r has the same sign as mx */ - mpz_tdiv_qr (mx, r, mx, my); - /* mx is the quotient */ - mpz_tdiv_r_2exp (mx, mx, 7); - *quo = mpz_get_si (mx); - } - else /* ex > ey */ - { - /* to get the low 7 more bits of the quotient, we first compute - R = X mod Y*2^7, where X and Y are defined below. Then the - low 7 of the quotient are floor(R/Y). */ - mpz_mul_2exp (my, my, 7); /* 2^7*Y */ - - mpz_set_ui (r, 2); - mpz_powm_ui (r, r, ex - ey, my); /* 2^(ex-ey) mod my */ - mpz_mul (r, r, mx); - mpz_mod (r, r, my); - - /* now 0 <= r < 2^7*Y */ - mpz_fdiv_q_2exp (my, my, 7); /* back to Y */ - mpz_tdiv_qr (mx, r, r, my); - /* oldr = mx*my + newr */ - *quo = mpz_get_si (mx); - - /* now 0 <= |r| < |my| */ - } - - if (mpz_cmp_ui (r, 0) == 0) - { - inex = mpfr_set_ui (rem, 0, MPFR_RNDN); - /* take into account sign of x */ - if (signx) - mpfr_neg (rem, rem, MPFR_RNDN); - } - else - { - /* take into account sign of x */ - if (signx) - mpz_neg (r, r); - inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd); - } - - if (sign) - *quo |= 0x80; - - mpz_clear (mx); - mpz_clear (my); - mpz_clear (r); - - return inex; -} - -static int -do_fmod (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) -{ - int t = 0; - - if (mpfr_nan_p (value) || mpfr_nan_p (reg)) - mpfr_set_nan (value); - else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_zero_p (reg) || mpfr_inf_p (value)) - { - fpu.fpsr.quotient = 0; - t = mpfr_set (value, reg, rnd); - } - else - { - int quo; - - t = mpfr_rem1 (value, &quo, reg, value, rnd); - fpu.fpsr.quotient = quo << 16; - } - return t; -} - -static void -do_fcmp (mpfr_t source, mpfr_t dest) -{ - uae_u32 flags = 0; - - if (mpfr_nan_p (source) || mpfr_nan_p (dest)) - flags |= FPSR_CCB_NAN; - else - { - int cmp = mpfr_cmp (dest, source); - if (cmp < 0) - flags |= FPSR_CCB_NEGATIVE; - else if (cmp == 0) - { - flags |= FPSR_CCB_ZERO; - if ((mpfr_zero_p (dest) || mpfr_inf_p (dest)) && mpfr_signbit (dest)) - flags |= FPSR_CCB_NEGATIVE; - } - } - set_fpccr (flags); -} - -static void -do_ftst (mpfr_t value) -{ - uae_u32 flags = 0; - - if (mpfr_signbit (value)) - flags |= FPSR_CCB_NEGATIVE; - if (mpfr_nan_p (value)) - flags |= FPSR_CCB_NAN; - else if (mpfr_zero_p (value)) - flags |= FPSR_CCB_ZERO; - else if (mpfr_inf_p (value)) - flags |= FPSR_CCB_INFINITY; - set_fpccr (flags); -} - -static bool -fpuop_general (uae_u32 opcode, uae_u32 extra) -{ - mpfr_prec_t prec = get_cur_prec (); - mpfr_rnd_t rnd = get_cur_rnd (); - int reg = (extra >> 7) & 7; - int t = 0; - fpu_register value; - bool ret; - - mpfr_init2 (value.f, prec); - value.nan_bits = DEFAULT_NAN_BITS; - value.nan_sign = 0; - - mpfr_clear_flags (); - set_format (prec); - cur_exceptions = 0; - cur_instruction_address = m68k_getpc () - 4; - if ((extra & 0xfc00) == 0x5c00) - { - // FMOVECR - int rom_index = extra & 0x7f; - if (rom_index == 0 || (rom_index >= 11 && rom_index <= 15)) - t = mpfr_set (value.f, fpu_constant_rom[rom_index], rnd); - else if (rom_index >= 48 && rom_index <= 63) - t = mpfr_set (value.f, fpu_constant_rom[rom_index - 32], rnd); - else - mpfr_set_zero (value.f, 0); - set_fp_register (reg, value, t, rnd, true); - } - else if (extra & 0x40) - { - static const char valid[64] = - { - 1, 1, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 1, 1, 0, 1, 1, - 1, 0, 0, 0, 1, 0, 0, 0 - }; - - if (extra & 4) - // FD... - prec = DOUBLE_PREC; - else - // FS... - prec = SINGLE_PREC; - set_format (prec); - MPFR_DECL_INIT (value2, prec); - - if (!fpu.is_integral) - { - ret = false; - goto out; - } - if (!valid[extra & 0x3b]) - { - ret = false; - goto out; - } - if (!get_fp_value (opcode, extra, value)) - { - ret = false; - goto out; - } - - switch (extra & 0x3f) - { - case 0: // FSMOVE - case 4: // FDMOVE - mpfr_set (value2, value.f, rnd); - break; - case 1: // FSSQRT - case 5: // FDSQRT - if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sqrt (value2, value.f, rnd); - break; - case 24: // FSABS - case 28: // FDABS - t = mpfr_abs (value2, value.f, rnd); - break; - case 26: // FSNEG - case 30: // FDNEG - t = mpfr_neg (value2, value.f, rnd); - break; - case 32: // FSDIV - case 36: // FDDIV - if (mpfr_zero_p (value.f)) - { - if (mpfr_regular_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_zero_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); - break; - case 34: // FSADD - case 38: // FDADD - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_add (value2, fpu.registers[reg].f, value.f, rnd); - break; - case 35: // FSMUL - case 39: // FDMUL - if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); - break; - case 40: // FSSUB - case 44: // FDSUB - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sub (value2, fpu.registers[reg].f, value.f, rnd); - break; - } - set_fp_register (reg, value2, t, rnd, true); - } - else if ((extra & 0x30) == 0x30) - { - if ((extra & 15) > 10 || (extra & 15) == 9) - { - ret = false; - goto out; - } - if (!get_fp_value (opcode, extra, value)) - { - ret = false; - goto out; - } - - if ((extra & 15) < 8) - { - // FSINCOS - int reg2 = extra & 7; - MPFR_DECL_INIT (value2, prec); - - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sin_cos (value.f, value2, value.f, rnd); - if (reg2 != reg) - set_fp_register (reg2, value2, t >> 2, rnd, false); - set_fp_register (reg, value, t & 3, rnd, true); - } - else if ((extra & 15) == 8) - // FCMP - do_fcmp (value.f, fpu.registers[reg].f); - else - // FTST - do_ftst (value.f); - } - else - { - static const char valid[64] = - { - 1, 1, 1, 1, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 1, - 1, 1, 1, 0, 1, 1, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1 - }; - if (!valid[extra & 0x3f]) - { - ret = false; - goto out; - } - if (!get_fp_value (opcode, extra, value)) - { - ret = false; - goto out; - } - - switch (extra & 0x3f) - { - case 0: // FMOVE - break; - case 1: // FINT - t = mpfr_rint (value.f, value.f, rnd); - break; - case 2: // FSINH - t = mpfr_sinh (value.f, value.f, rnd); - break; - case 3: // FINTRZ - t = mpfr_rint (value.f, value.f, MPFR_RNDZ); - break; - case 4: // FSQRT - if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sqrt (value.f, value.f, rnd); - break; - case 6: // FLOGNP1 - if (!mpfr_nan_p (value.f)) - { - int cmp = mpfr_cmp_si (value.f, -1); - if (cmp == 0) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (cmp < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - t = mpfr_log1p (value.f, value.f, rnd); - break; - case 8: // FETOXM1 - t = mpfr_expm1 (value.f, value.f, rnd); - break; - case 9: // FTANH - t = mpfr_tanh (value.f, value.f, rnd); - break; - case 10: // FATAN - t = mpfr_atan (value.f, value.f, rnd); - break; - case 12: // FASIN - if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_asin (value.f, value.f, rnd); - break; - case 13: // FATANH - if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_atanh (value.f, value.f, rnd); - break; - case 14: // FSIN - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sin (value.f, value.f, rnd); - break; - case 15: // FTAN - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_tan (value.f, value.f, rnd); - break; - case 16: // FETOX - t = mpfr_exp (value.f, value.f, rnd); - break; - case 17: // FTWOTOX - t = mpfr_ui_pow (value.f, 2, value.f, rnd); - break; - case 18: // FTENTOX - t = mpfr_ui_pow (value.f, 10, value.f, rnd); - break; - case 20: // FLOGN - if (mpfr_zero_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_log (value.f, value.f, rnd); - break; - case 21: // FLOG10 - if (mpfr_zero_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_log10 (value.f, value.f, rnd); - break; - case 22: // FLOG2 - if (mpfr_zero_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_log2 (value.f, value.f, rnd); - break; - case 24: // FABS - t = mpfr_abs (value.f, value.f, rnd); - value.nan_sign = 0; - break; - case 25: // FCOSH - t = mpfr_cosh (value.f, value.f, rnd); - break; - case 26: // FNEG - t = mpfr_neg (value.f, value.f, rnd); - value.nan_sign = !value.nan_sign; - break; - case 28: // FACOS - if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_acos (value.f, value.f, rnd); - break; - case 29: // FCOS - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_cos (value.f, value.f, rnd); - break; - case 30: // FGETEXP - t = do_getexp (value.f, rnd); - break; - case 31: // FGETMAN - t = do_getman (value.f); - break; - case 32: // FDIV - if (mpfr_zero_p (value.f)) - { - if (mpfr_regular_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_zero_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_div (value.f, fpu.registers[reg].f, value.f, rnd); - break; - case 33: // FMOD - t = do_fmod (value.f, fpu.registers[reg].f, rnd); - break; - case 34: // FADD - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_add (value.f, fpu.registers[reg].f, value.f, rnd); - break; - case 35: // FMUL - if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_mul (value.f, fpu.registers[reg].f, value.f, rnd); - break; - case 36: // FSGLDIV - { - MPFR_DECL_INIT (value2, SINGLE_PREC); - - set_format (SINGLE_PREC); - if (mpfr_zero_p (value.f)) - { - if (mpfr_regular_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_zero_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); - mpfr_set (value.f, value2, rnd); - } - break; - case 37: // FREM - t = do_remainder (value.f, fpu.registers[reg].f, rnd); - break; - case 38: // FSCALE - t = do_scale (value.f, fpu.registers[reg].f, rnd); - break; - case 39: // FSGLMUL - { - MPFR_DECL_INIT (value2, SINGLE_PREC); - - set_format (SINGLE_PREC); - if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); - mpfr_set (value.f, value2, rnd); - } - break; - case 40: // FSUB - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sub (value.f, fpu.registers[reg].f, value.f, rnd); - break; - } - set_fp_register (reg, value, t, rnd, true); - } - update_exceptions (); - ret = true; - out: - mpfr_clear (value.f); - return ret; -} - -void -fpuop_arithmetic (uae_u32 opcode, uae_u32 extra) -{ - bool valid; - - switch ((extra >> 13) & 7) - { - case 3: - valid = fpuop_fmove_memory (opcode, extra); - break; - case 4: - case 5: - valid = fpuop_fmovem_control (opcode, extra); - break; - case 6: - case 7: - valid = fpuop_fmovem_register (opcode, extra); - break; - case 0: - case 2: - valid = fpuop_general (opcode, extra); - break; - default: - valid = false; - break; - } - - if (!valid) - { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } -} - -static bool -check_fp_cond (uae_u32 pred) -{ - uae_u32 fpcc = get_fpccr (); - - if ((pred & 16) != 0 && (fpcc & FPSR_CCB_NAN) != 0) - { - // IEEE non-aware test - set_exception_status (get_exception_status () | FPSR_EXCEPTION_BSUN); - set_accrued_exception (get_accrued_exception () | FPSR_ACCR_IOP); - } - - switch (pred & 15) - { - case 0: // F / SF - return false; - case 1: // EQ /SEQ - return (fpcc & FPSR_CCB_ZERO) != 0; - case 2: // OGT / GT - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) == 0; - case 3: // OGE / GE - return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NAN | FPSR_CCB_NEGATIVE)) == 0; - case 4: // OLT / LT - return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; - case 5: // OLE / LE - return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN)) == FPSR_CCB_NEGATIVE; - case 6: // OGL / GL - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) == 0; - case 7: // OR / GLE - return (fpcc & FPSR_CCB_NAN) == 0; - case 8: // UN / NGLE - return (fpcc & FPSR_CCB_NAN) != 0; - case 9: // UEQ / NGL - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) != 0; - case 10: // UGT / NLE - return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == 0; - case 11: // UGE / NLT - return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) != FPSR_CCB_NEGATIVE; - case 12: // ULT / NGE - return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; - case 13: // ULE / NGT - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) != 0; - case 14: // NE / SNE - return (fpcc & FPSR_CCB_ZERO) == 0; - case 15: // T / ST - return true; - default: - return false; - } -} - -void -fpuop_bcc (uae_u32 opcode, uaecptr pc, uae_u32 disp) -{ - if (check_fp_cond (opcode)) - { - if (!(opcode & (1 << 6))) - disp = (uae_s16) disp; - m68k_setpc (pc + disp); - } -} - -void -fpuop_scc (uae_u32 opcode, uae_u32 extra) -{ - uae_u32 addr; - int value = check_fp_cond (extra) ? 0xff : 0; - if ((opcode & 070) == 0) - { - int reg = opcode & 7; - m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xff) | value; - } - else if (!get_fp_addr (opcode, &addr, true)) - { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - else - { - switch (opcode & 070) - { - case 030: - m68k_areg (regs, opcode & 7) += (opcode & 7) == 7 ? 2 : 1; - break; - case 040: - addr -= (opcode & 7) == 7 ? 2 : 1; - m68k_areg (regs, opcode & 7) = addr; - } - put_byte (addr, value); - } -} - -void -fpuop_dbcc (uae_u32 opcode, uae_u32 extra) -{ - uaecptr pc = m68k_getpc (); - uae_s16 disp = next_iword (); - - if (!check_fp_cond (extra)) - { - int reg = opcode & 7; - uae_u16 cnt = (m68k_dreg (regs, reg) & 0xffff) - 1; - m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xffff) | cnt; - if (cnt != 0xffff) - m68k_setpc (pc + disp); - } -} - -void -fpuop_trapcc (uae_u32, uaecptr oldpc, uae_u32 extra) -{ - if (check_fp_cond (extra)) - Exception (7, oldpc - 2); -} - -void -fpuop_save (uae_u32 opcode) -{ - uae_u32 addr; - - if ((opcode & 070) == 030 - || !get_fp_addr (opcode, &addr, true)) - { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - if (fpu.is_integral) - { - // 4 byte 68040 IDLE frame - // FIXME: generate proper FPU stack frames that does not result - // in undefined behaviour from FPSP040 - if ((opcode & 070) == 040) - { - addr -= 4; - m68k_areg (regs, opcode & 7) = addr; - } - put_long (addr, 0x41000000); - } - else - { - // 28 byte 68881 IDLE frame - if ((opcode & 070) == 040) - { - addr -= 28; - m68k_areg (regs, opcode & 7) = addr; - } - put_long (addr, 0x1f180000); - for (int i = 0; i < 6; i++) - { - addr += 4; - put_long (addr, 0); - } - } -} - -void -fpuop_restore (uae_u32 opcode) -{ - uae_u32 addr; - uae_u32 format; - - if ((opcode & 070) == 040 - || !get_fp_addr (opcode, &addr, false)) - { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - format = get_long (addr); - addr += 4; - if ((format & 0xff000000) == 0) - // NULL frame - fpu_reset (); - else - addr += (format & 0xff0000) >> 16; - if ((opcode & 070) == 030) - m68k_areg (regs, opcode & 7) = addr; -} - -void fpu_set_fpsr(uae_u32 new_fpsr) -{ - set_fpsr(new_fpsr); -} - -uae_u32 fpu_get_fpsr(void) -{ - return get_fpsr(); -} - -void fpu_set_fpcr(uae_u32 new_fpcr) -{ - set_fpcr(new_fpcr); -} - -uae_u32 fpu_get_fpcr(void) -{ - return get_fpcr(); -} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp index 23efd8ef..ffc784a5 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp @@ -1,42 +1,31 @@ /* - * fpu/fpu_uae.cpp - the old UAE FPU + * fpu/fpu_uae.cpp * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation * - * MC68881/68040 fpu emulation + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* - * UAE - The Un*x Amiga Emulator - * - * MC68881 emulation - * - * Copyright 1996 Herman ten Brugge - * - * * Following fixes by Lauri Pesonen, July 1999: * * FMOVEM list handling: @@ -97,8 +86,9 @@ * - Precision rounding single/double */ - #include "sysdeps.h" +#include +#include #include "memory.h" #include "readcpu.h" #include "newcpu.h" @@ -107,17 +97,6 @@ #include "fpu/fpu.h" #include "fpu/fpu_uae.h" -#ifdef HAVE_NEW_HEADERS -#define _GLIBCPP_USE_C99 1 -# include -# include -using namespace __gnu_cxx; -#undef _GLIBCPP_USE_C99 -#else -# include -# include -#endif - /* Global FPU context */ fpu_t fpu; @@ -187,8 +166,8 @@ PUBLIC void FFPU dump_registers(const char * str) sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", str, - fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3), - fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) ); + get_register(0), get_register(1), get_register(2), get_register(3), + get_register(4), get_register(5), get_register(6), get_register(7) ); fpu_debug((temp_str)); } @@ -216,7 +195,9 @@ PUBLIC void FFPU dump_registers(const char *) { } -#define dump_first_bytes(a,b) +PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32) +{ +} #endif @@ -238,10 +219,10 @@ PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x) PRIVATE inline bool FFPU do_isnan(fpu_register const & r) { - fpu_register_parts const p = { r }; - if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) { + uae_u32 * p = (uae_u32 *)&r; + if ((p[FHI] & 0x7FF00000) == 0x7FF00000) { // logical or is faster here. - if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) { + if ((p[FHI] & 0x000FFFFF) || p[FLO]) { return true; } } @@ -254,8 +235,8 @@ PRIVATE inline bool FFPU do_isnan(fpu_register const & r) PRIVATE inline bool FFPU do_isinf(fpu_register const & r) { - fpu_register_parts const p = { r }; - if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) { + uae_u32 * p = (uae_u32 *)&r; + if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) { return true; } return false; @@ -267,8 +248,8 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r) PRIVATE inline bool FFPU do_isneg(fpu_register const & r) { - fpu_register_parts const p = { r }; - return ((p.parts[FHI] & 0x80000000) != 0); + uae_u32 * p = (uae_u32 *)&r; + return ((p[FHI] & 0x80000000) != 0); } #ifndef HAVE_ISZERO @@ -277,8 +258,8 @@ PRIVATE inline bool FFPU do_isneg(fpu_register const & r) PRIVATE inline bool FFPU do_iszero(fpu_register const & r) { - fpu_register_parts const p = { r }; - return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0); + uae_u32 * p = (uae_u32 *)&r; + return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0); } // May be optimized for particular processors @@ -314,83 +295,75 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r) PRIVATE inline void FFPU make_nan(fpu_register & r) { - fpu_register_parts p; - p.parts[FLO] = 0xffffffff; - p.parts[FHI] = 0x7fffffff; - r = p.val; + uae_u32 * const p = (uae_u32 *)&r; + p[FLO] = 0xffffffff; + p[FHI] = 0x7fffffff; } PRIVATE inline void FFPU make_zero_positive(fpu_register & r) { - fpu_register_parts p; - p.parts[FLO] = p.parts[FHI] = 0; - r = p.val; + uae_u32 * const p = (uae_u32 *)&r; + p[FLO] = p[FHI] = 0; } PRIVATE inline void FFPU make_zero_negative(fpu_register & r) { - fpu_register_parts p; - p.parts[FLO] = 0; - p.parts[FHI] = 0x80000000; - r = p.val; + uae_u32 * const p = (uae_u32 *)&r; + p[FLO] = 0; + p[FHI] = 0x80000000; } PRIVATE inline void FFPU make_inf_positive(fpu_register & r) { - fpu_register_parts p; - p.parts[FLO] = 0; - p.parts[FHI] = 0x7FF00000; - r = p.val; + uae_u32 * const p = (uae_u32 *)&r; + p[FLO] = 0; + p[FHI] = 0x7FF00000; } PRIVATE inline void FFPU make_inf_negative(fpu_register & r) { - fpu_register_parts p; - p.parts[FLO] = 0; - p.parts[FHI] = 0xFFF00000; - r = p.val; + uae_u32 * const p = (uae_u32 *)&r; + p[FLO] = 0; + p[FHI] = 0xFFF00000; } PRIVATE inline void FFPU fast_scale(fpu_register & r, int add) { - fpu_register_parts p = { r }; - int exp = (p.parts[FHI] & 0x7FF00000) >> 20; + uae_u32 * const p = (uae_u32 *)&r; + int exp = (p[FHI] & 0x7FF00000) >> 20; // TODO: overflow flags exp += add; if(exp >= 2047) { make_inf_positive(r); - return; } else if(exp < 0) { // keep sign (+/- 0) - p.parts[FHI] &= 0x80000000; + p[FHI] &= 0x80000000; } else { - p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); + p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); } - r = p.val; } PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) { - fpu_register_parts const p = { r }; - int exp = (p.parts[FHI] & 0x7FF00000) >> 20; + uae_u32 * const p = (uae_u32 *)&r; + int exp = (p[FHI] & 0x7FF00000) >> 20; return( exp - 1023 ); } // Normalize to range 1..2 PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) { - fpu_register_parts p = { r }; - p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000; - r = p.val; + uae_u32 * const p = (uae_u32 *)&r; + p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000; } // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) { - fpu_register_parts const a = { ra }; - fpu_register_parts const b = { rb }; - return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); + uae_u32 * const a = (uae_u32 *)&ra; + uae_u32 * const b = (uae_u32 *)&rb; + return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); } // Quotient Byte is loaded with the sign and least significant @@ -408,15 +381,13 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) return (0.0); fpu_register result; - fpu_register_parts p; + uae_u32 * p = (uae_u32 *)&result; uae_u32 sign = (value & 0x80000000); uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - p.parts[FLO] = value << 29; - p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); - - result = p.val; + p[FLO] = value << 29; + p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); @@ -430,10 +401,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) return 0; uae_u32 result; - fpu_register_parts const p = { src }; + uae_u32 *p = (uae_u32 *)&src; - uae_u32 sign = (p.parts[FHI] & 0x80000000); - uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20; + uae_u32 sign = (p[FHI] & 0x80000000); + uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; if(exp + 127 < 1023) { exp = 0; @@ -443,7 +414,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) exp = exp + 127 - 1023; } - result = sign | (exp << 23) | ((p.parts[FHI] & 0x000FFFFF) << 3) | (p.parts[FLO] >> 29); + result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); @@ -457,8 +428,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u return 0.0; fpu_register result; - fpu_register_parts p; - + uae_u32 *p = (uae_u32 *)&result; + uae_u32 sign = wrd1 & 0x80000000; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -495,10 +466,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u } // drop the explicit integer bit. - p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11); - p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - - result = p.val; + p[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); @@ -542,13 +511,11 @@ PRIVATE inline void FFPU make_extended_no_normalize( } // drop the explicit integer bit. - fpu_register_parts p; - p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11); - p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + uae_u32 *p = (uae_u32 *)&result; + p[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - result = p.val; - - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); } // from_exten @@ -560,14 +527,14 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = *wrd2 = *wrd3 = 0; return; } - - fpu_register_parts const p = { src }; - fpu_debug(("extract_extended (%X,%X)\n",p.parts[FLO],p.parts[FHI])); + uae_u32 *p = (uae_u32 *)&src; + + fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI])); - uae_u32 sign = p.parts[FHI] & 0x80000000; + uae_u32 sign = p[FHI] & 0x80000000; - uae_u32 exp = ((p.parts[FHI] >> 20) & 0x7ff); + uae_u32 exp = ((p[FHI] >> 20) & 0x7ff); // Check for maximum if(exp == 0x7FF) { exp = 0x7FFF; @@ -577,8 +544,8 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = sign | (exp << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21); - *wrd3 = p.parts[FLO] << 11; + *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); + *wrd3 = p[FLO] << 11; fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -590,11 +557,9 @@ PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) return 0.0; fpu_register result; - fpu_register_parts p; - p.parts[FLO] = wrd2; - p.parts[FHI] = wrd1; - - result = p.val; + uae_u32 *p = (uae_u32 *)&result; + p[FLO] = wrd2; + p[FHI] = wrd1; fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); @@ -612,9 +577,9 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, return; } */ - fpu_register_parts const p = { src }; - *wrd2 = p.parts[FLO]; - *wrd1 = p.parts[FHI]; + uae_u32 *p = (uae_u32 *)&src; + *wrd2 = p[FLO]; + *wrd1 = p[FHI]; fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); } @@ -657,25 +622,25 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) fpu_register src0 = src; #endif - if (src == 0.0) + if (src == 0.0) return 0; - if (src < 0) { + if (src < 0) { tmp = 0x80000000; src = -src; - } else { + } else { tmp = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 16777216.0; - if (frac >= 1.0) { + } + frac = frexp (src, &expon); + frac += 0.5 / 16777216.0; + if (frac >= 1.0) { frac /= 2.0; expon++; - } + } result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff); // fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result)); - return (result); + return (result); } // to exten @@ -930,9 +895,11 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe break; case 3: ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -973,8 +940,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); fpu_debug(("get_fp_value ad=%X\n",ad)); fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); - dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 ); - dump_first_bytes( get_real_address(ad, 0, 0), 64 ); + dump_first_bytes( get_real_address(ad)-64, 64 ); + dump_first_bytes( get_real_address(ad), 64 ); switch (size) { case 0: @@ -1021,15 +988,6 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe return 0; } - switch (mode) { - case 3: - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - break; - } - // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); return 1; } @@ -1246,7 +1204,7 @@ PRIVATE inline int FFPU fpp_cond(int condition) #if 0 return fpcctrue(condition); #else - switch (condition & 0x1f) { + switch (condition) { case 0x00: CONDRET("False",0); case 0x01: CONDRET("Equal",Z); case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); @@ -1341,11 +1299,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) put_byte(ad, cc ? 0xff : 0x00); } -void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) { - fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); - int cc = fpp_cond(extra & 0x3f); + int cc = fpp_cond(opcode & 0x3f); if (cc == -1) { m68k_setpc (oldpc); op_illg (opcode); @@ -1948,8 +1906,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) FPU registers[reg] = 1.0e256; fpu_debug(("FP const: 1.0e256\n")); break; - - // Valid for 64 bits only (see fpu.cpp) #if 0 case 0x3c: FPU registers[reg] = 1.0e512; @@ -1986,126 +1942,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) return; } fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); -#if 0 // MJ added, not tested now - if (FPU is_integral) { - // 68040-specific operations - switch (extra & 0x7f) { - case 0x40: /* FSMOVE */ - fpu_debug(("FSMOVE %.04f\n",(double)src)); - FPU registers[reg] = (float)src; - make_fpsr(FPU registers[reg]); - break; - case 0x44: /* FDMOVE */ - fpu_debug(("FDMOVE %.04f\n",(double)src)); - FPU registers[reg] = (double)src; - make_fpsr(FPU registers[reg]); - break; - case 0x41: /* FSSQRT */ - fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = (float)sqrt (src); - make_fpsr(FPU registers[reg]); - break; - case 0x45: /* FDSQRT */ - fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = (double)sqrt (src); - make_fpsr(FPU registers[reg]); - break; - case 0x58: /* FSABS */ - fpu_debug(("FSABS %.04f\n",(double)src)); - FPU registers[reg] = (float)fabs(src); - make_fpsr(FPU registers[reg]); - break; - case 0x5c: /* FDABS */ - fpu_debug(("FDABS %.04f\n",(double)src)); - FPU registers[reg] = (double)fabs(src); - make_fpsr(FPU registers[reg]); - break; - case 0x5a: /* FSNEG */ - fpu_debug(("FSNEG %.04f\n",(double)src)); - FPU registers[reg] = (float)-src; - make_fpsr(FPU registers[reg]); - break; - case 0x5e: /* FDNEG */ - fpu_debug(("FDNEG %.04f\n",(double)src)); - FPU registers[reg] = (double)-src; - make_fpsr(FPU registers[reg]); - break; - case 0x60: /* FSDIV */ - fpu_debug(("FSDIV %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] / src); - make_fpsr(FPU registers[reg]); - break; - case 0x64: /* FDDIV */ - fpu_debug(("FDDIV %.04f\n",(double)src)); - FPU registers[reg] = (double)(FPU registers[reg] / src); - make_fpsr(FPU registers[reg]); - break; - case 0x62: /* FSADD */ - fpu_debug(("FSADD %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] + src); - make_fpsr(FPU registers[reg]); - break; - case 0x66: /* FDADD */ - fpu_debug(("FDADD %.04f\n",(double)src)); - FPU registers[reg] = (double)(FPU registers[reg] + src); - make_fpsr(FPU registers[reg]); - break; - case 0x68: /* FSSUB */ - fpu_debug(("FSSUB %.04f\n",(double)src)); - FPU registers[reg] = (float)(FPU registers[reg] - src); - make_fpsr(FPU registers[reg]); - break; - case 0x6c: /* FDSUB */ - fpu_debug(("FDSUB %.04f\n",(double)src)); - FPU registers[reg] = (double)(FPU registers[reg] - src); - make_fpsr(FPU registers[reg]); - break; - case 0x63: /* FSMUL */ - case 0x67: /* FDMUL */ - get_dest_flags(FPU registers[reg]); - get_source_flags(src); - if(fl_dest.in_range && fl_source.in_range) { - if ((extra & 0x7f) == 0x63) - FPU registers[reg] = (float)(FPU registers[reg] * src); - else - FPU registers[reg] = (double)(FPU registers[reg] * src); - } - else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); - } - else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } - } - else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } - } - make_fpsr(FPU registers[reg]); - break; - default: - // Continue decode-execute 6888x instructions below - goto process_6888x_instructions; - } - fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); - dump_registers( "END "); - return; - } - process_6888x_instructions: -#endif switch (extra & 0x7f) { case 0x00: /* FMOVE */ fpu_debug(("FMOVE %.04f\n",(double)src)); @@ -2329,13 +2166,13 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) FPU registers[reg] *= src; } else if (fl_dest.nan || fl_source.nan || - (fl_dest.zero && fl_source.infinity) || - (fl_dest.infinity && fl_source.zero) ) { + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { make_nan( FPU registers[reg] ); } else if (fl_dest.zero || fl_source.zero ) { - if (( fl_dest.negative && !fl_source.negative) || - (!fl_dest.negative && fl_source.negative)) { + if (fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { make_zero_negative(FPU registers[reg]); } else { @@ -2343,8 +2180,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } } else { - if(( fl_dest.negative && !fl_source.negative) || - (!fl_dest.negative && fl_source.negative)) { + if( fl_dest.negative && !fl_source.negative || + !fl_dest.negative && fl_source.negative) { make_inf_negative(FPU registers[reg]); } else { @@ -2499,27 +2336,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) dump_registers( "END "); } - -void fpu_set_fpsr(uae_u32 new_fpsr) -{ - set_fpsr(new_fpsr); -} - -uae_u32 fpu_get_fpsr(void) -{ - return get_fpsr(); -} - -void fpu_set_fpcr(uae_u32 new_fpcr) -{ - set_fpcr(new_fpcr); -} - -uae_u32 fpu_get_fpcr(void) -{ - return get_fpcr(); -} - /* -------------------------- Initialization -------------------------- */ void FFPU fpu_init (bool integral_68040) diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h index d8930e32..7fc4ebbd 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h @@ -1,33 +1,28 @@ /* - * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core + * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_UAE_H diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp index a4c6af2d..70e59086 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp @@ -1,33 +1,27 @@ /* - * fpu/fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. + * fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation * - * MC68881/68040 fpu emulation + * Based on UAE FPU, original copyright 1996 Herman ten Brugge, + * rewritten for x86 by Lauri Pesonen 1999-2000, + * accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Interface @@ -140,8 +134,10 @@ * */ -# include -# include +#include +#include +#include +#include #include "sysdeps.h" #include "memory.h" @@ -242,6 +238,8 @@ PUBLIC void FFPU fpu_dump_flags(void) #include "debug.h" #if FPU_DEBUG +#undef __inline__ +#define __inline__ PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual) { @@ -392,7 +390,7 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *) /* ---------------------------- Status functions ---------------------------- */ -PRIVATE void inline FFPU SET_BSUN_ON_NAN () +PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN () { if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) { x86_status_word |= SW_FAKE_BSUN; @@ -400,7 +398,7 @@ PRIVATE void inline FFPU SET_BSUN_ON_NAN () } } -PRIVATE void inline FFPU build_ex_status () +PRIVATE void __inline__ FFPU build_ex_status () { if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX @@ -417,7 +415,7 @@ When the FPU creates a NAN, the NAN always contains the same bit pattern in the mantissa. All bits of the mantissa are ones for any precision. When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa. */ -PRIVATE inline void FFPU MAKE_NAN (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f) { // Make it non-signaling. uae_u8 * p = (uae_u8 *) &f; @@ -427,10 +425,10 @@ PRIVATE inline void FFPU MAKE_NAN (fpu_register & f) /* For single- and double-precision infinities the fraction is a zero. -For extended-precision infinities, the mantissa�s MSB, the explicit +For extended-precision infinities, the mantissa’s MSB, the explicit integer bit, can be either one or zero. */ -PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { @@ -441,7 +439,7 @@ PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f) return(0); } -PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { @@ -452,7 +450,7 @@ PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f) return(0); } -PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; return *((uae_u32 *)p) == 0 && @@ -460,34 +458,34 @@ PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f) ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0; } -PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f) { uae_u8 * p = (uae_u8 *) &f; memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0x7FFF; } -PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f) { uae_u8 * p = (uae_u8 *) &f; memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0xFFFF; } -PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) { uae_u32 * const p = (uae_u32 *) &f; memset( p, 0, sizeof(fpu_register) ); } -PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) { uae_u32 * const p = (uae_u32 *) &f; memset( p, 0, sizeof(fpu_register) ); *((uae_u32 *)&p[4]) = 0x80000000; } -PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; return( (p[9] & 0x80) != 0 ); @@ -902,34 +900,6 @@ PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fmove"); } -PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fsmove"); -} - -PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fdmove"); -} - /* PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) { @@ -1053,50 +1023,6 @@ PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fsqrt"); } -PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fsqrt \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fssqrt"); -} - -PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fsqrt \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt"); -} - PRIVATE void FFPU do_ftst ( fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1385,48 +1311,6 @@ PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fabs"); } -PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fabs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fabs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsabs"); -} - -PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fabs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fabs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdabs"); -} - PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1457,48 +1341,6 @@ PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fneg"); } -PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fchs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fchs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsneg"); -} - -PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fchs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fchs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdneg"); -} - PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1624,50 +1466,6 @@ PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fdiv"); } -PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fdiv %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsdiv"); -} - -PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fdiv %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fddiv"); -} - // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. // Quotient Byte is loaded with the sign and least significant @@ -2053,48 +1851,6 @@ PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fadd"); } -PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fadd \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsadd"); -} - -PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fadd \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdadd"); -} - PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2126,48 +1882,6 @@ PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fmul"); } -PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fmul \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsmul"); -} - -PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fmul \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdmul"); -} - PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2326,52 +2040,6 @@ PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fsub"); } -PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fsub %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fssub"); -} - -PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fsub %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdsub"); -} - PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2616,9 +2284,11 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src break; case 3: ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -2717,15 +2387,6 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src return 0; } - switch (mode) { - case 3: - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - break; - } - // D(bug("get_fp_value result = %.04f\r\n",(float)src)); return 1; @@ -2951,7 +2612,7 @@ PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) #define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I)) #define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN) - switch (condition & 0x1f) { + switch (condition) { // Common Tests, no BSUN case 0x01: CONDRET("Equal",Z); @@ -3096,11 +2757,11 @@ PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) } } -PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) { int cc; - D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ())); #if I3_ON_FTRAPCC #error "FIXME: _asm int 3" @@ -3108,7 +2769,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 e #endif // This must be broken. - cc = fpp_cond(opcode, extra & 0x3f); + cc = fpp_cond(opcode, opcode & 0x3f); if (cc < 0) { m68k_setpc (oldpc); @@ -4985,249 +4646,6 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 } -/* -------------------------- 040 ALU -------------------------- */ -PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSMOVE %s\r\n",etos(src))); - do_fsmove( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDMOVE %s\r\n",etos(src))); - do_fdmove( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSSQRT %s\r\n",etos(src))); - do_fssqrt( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDSQRT %s\r\n",etos(src))); - do_fdsqrt( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSABS %s\r\n",etos(src))); - do_fsabs( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDABS %s\r\n",etos(src))); - do_fdabs( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSNEG %s\r\n",etos(src))); - do_fsneg( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDNEG %s\r\n",etos(src))); - do_fdneg( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSDIV %s\r\n",etos(src))); - do_fsdiv( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDDIV %s\r\n",etos(src))); - do_fddiv( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSADD %s\r\n",etos(src))); - do_fsadd( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDADD %s\r\n",etos(src))); - do_fdadd( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSSUB %s\r\n",etos(src))); - do_fssub( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDSUB %s\r\n",etos(src))); - do_fdsub( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSMUL %s\r\n",etos(src))); - do_fsmul( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSMUL %s\r\n",etos(src))); - do_fsmul( FPU registers[reg], src ); - dump_registers( "END "); -} - /* ---------------------------- ALU ---------------------------- */ PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ) @@ -6326,61 +5744,6 @@ PRIVATE void FFPU build_fpp_opp_lookup_table () } break; } - - if (FPU is_integral) { - switch (extra & 0x7f) { - case 0x40: - fpufunctbl[mask] = & FFPU fpuop_do_fsmove; - break; - case 0x44: - fpufunctbl[mask] = & FFPU fpuop_do_fdmove; - break; - case 0x41: - fpufunctbl[mask] = & FFPU fpuop_do_fssqrt; - break; - case 0x45: - fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt; - break; - case 0x58: - fpufunctbl[mask] = & FFPU fpuop_do_fsabs; - break; - case 0x5c: - fpufunctbl[mask] = & FFPU fpuop_do_fdabs; - break; - case 0x5a: - fpufunctbl[mask] = & FFPU fpuop_do_fsneg; - break; - case 0x5e: - fpufunctbl[mask] = & FFPU fpuop_do_fdneg; - break; - case 0x60: - fpufunctbl[mask] = & FFPU fpuop_do_fsdiv; - break; - case 0x64: - fpufunctbl[mask] = & FFPU fpuop_do_fddiv; - break; - case 0x62: - fpufunctbl[mask] = & FFPU fpuop_do_fsadd; - break; - case 0x66: - fpufunctbl[mask] = & FFPU fpuop_do_fdadd; - break; - case 0x68: - fpufunctbl[mask] = & FFPU fpuop_do_fssub; - break; - case 0x6c: - fpufunctbl[mask] = & FFPU fpuop_do_fdsub; - break; - case 0x63: - fpufunctbl[mask] = & FFPU fpuop_do_fsmul; - break; - case 0x67: - fpufunctbl[mask] = & FFPU fpuop_do_fdmul; - break; - default: - break; - } - } switch (extra & 0x7f) { case 0x00: @@ -6670,26 +6033,6 @@ PRIVATE void FFPU do_fld1 ( fpu_register & dest ) } -void fpu_set_fpsr(uae_u32 new_fpsr) -{ - set_fpsr(new_fpsr); -} - -uae_u32 fpu_get_fpsr(void) -{ - return get_fpsr(); -} - -void fpu_set_fpcr(uae_u32 new_fpcr) -{ - set_fpcr(new_fpcr); -} - -uae_u32 fpu_get_fpcr(void) -{ - return get_fpcr(); -} - /* ---------------------------- MAIN INIT ---------------------------- */ #ifdef HAVE_SIGACTION @@ -6741,10 +6084,6 @@ PUBLIC void FFPU fpu_init( bool integral_68040 ) build_fpp_opp_lookup_table(); -/* _asm { - FNINIT - FLDCW x86_control_word - } */ __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); do_fldpi( const_pi ); @@ -6772,10 +6111,6 @@ PUBLIC void FFPU fpu_init( bool integral_68040 ) set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 ); // Just in case. -/* _asm { - FNINIT - FLDCW x86_control_word - } */ __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); } diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h index 52a2f310..96f1d959 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h @@ -1,33 +1,28 @@ /* - * fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core + * fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_X86_H @@ -99,17 +94,17 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void); PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name); // Get special floating-point value class -PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f); -PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f); -PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f); -PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f); +PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f); +PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f); +PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f); +PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f); // Make a special floating-point value -PRIVATE inline void FFPU MAKE_NAN (fpu_register & f); -PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f); -PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f); -PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f); -PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f); +PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f); +PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f); +PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f); +PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f); +PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f); // Conversion from extended floating-point values PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM; @@ -347,24 +342,6 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ); PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ); PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ); -// 040 -PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ); -PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ); - // Get & Put floating-point values PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM; PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM; @@ -374,9 +351,9 @@ PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM; PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM; // Misc functions -PRIVATE void inline FFPU set_host_fpu_control_word (); -PRIVATE void inline FFPU SET_BSUN_ON_NAN (); -PRIVATE void inline FFPU build_ex_status (); +PRIVATE void __inline__ FFPU set_host_fpu_control_word (); +PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN (); +PRIVATE void __inline__ FFPU build_ex_status (); PRIVATE void FFPU do_null_frestore (); PRIVATE void FFPU build_fpp_opp_lookup_table (); PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ); diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h index 6e5a3766..ecdecfbc 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h @@ -1,35 +1,3 @@ -/* - * fpu/fpu_x86_asm.h - Extra Definitions for the X86 assembly FPU core - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - #define DEFINE_X86_MACRO(name, value) \ asm(".local " #name "\n\t" #name " = " #value) diff --git a/BasiliskII/src/uae_cpu/fpu/impl.h b/BasiliskII/src/uae_cpu/fpu/impl.h index af7946a3..c79d1f3f 100644 --- a/BasiliskII/src/uae_cpu/fpu/impl.h +++ b/BasiliskII/src/uae_cpu/fpu/impl.h @@ -1,38 +1,28 @@ /* * fpu/impl.h - extra functions and inline implementations * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_IMPL_H @@ -113,8 +103,7 @@ static inline uae_u32 FFPU get_fpcr(void) { uae_u32 rounding_precision = get_rounding_precision(); uae_u32 rounding_mode = get_rounding_mode(); - uae_u32 exception_enable = FPU fpcr.exception_enable; - return (rounding_precision | rounding_mode | exception_enable); + return (rounding_precision | rounding_mode); } /* Set the floating-point control register from an m68k format */ @@ -123,7 +112,6 @@ static inline void FFPU set_fpcr(uae_u32 new_fpcr) set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION); set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE ); set_host_control_word(); - FPU fpcr.exception_enable = new_fpcr & FPCR_EXCEPTION_ENABLE; } /* -------------------------------------------------------------------------- */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp index 46d43c95..eabb376e 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp @@ -1,33 +1,28 @@ /* * fpu/mathlib.cpp - Floating-point math support library * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* NOTE: this file shall be included only from fpu/fpu_*.cpp */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h index c9a1951c..2363af56 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.h +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -1,33 +1,28 @@ /* - * fpu/mathlib.h - Floating-point math support library + * fpu/mathlib.h - Floating-point math support library * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_MATHLIB_H @@ -56,16 +51,20 @@ // NOTE: this is irrelevant on Win32 platforms since the MS libraries // don't support extended-precision floating-point computations -#ifdef WIN32 +#if defined(WIN32) && USE_LONG_DOUBLE #undef FPU_USE_ISO_C99 #endif // Use faster implementation of math functions, but this could cause // some incorrect results (?) -// TODO: actually implement the slower but safer versions +#ifdef _MSC_VER +// MSVC uses intrinsics for all of the math functions, so it should still be fast +#define FPU_FAST_MATH 0 +#else #define FPU_FAST_MATH 1 +#endif -#if defined(FPU_USE_ISO_C99) +#if FPU_USE_ISO_C99 // NOTE: no prior shall be included at this point #define __USE_ISOC99 1 // for glibc 2.2.X and newer #define __USE_ISOC9X 1 // for glibc 2.1.X @@ -148,7 +147,7 @@ union fpu_double_shape { unsigned int mantissa0:20; unsigned int mantissa1:32; #else -# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +# if HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int mantissa0:20; unsigned int exponent:11; unsigned int negative:1; @@ -173,7 +172,7 @@ union fpu_double_shape { unsigned int mantissa0:19; unsigned int mantissa1:32; #else -# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +# if HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int mantissa0:19; unsigned int quiet_nan:1; unsigned int exponent:11; @@ -192,7 +191,7 @@ union fpu_double_shape { /* This format is used to extract the sign_exponent and mantissa parts only */ struct { -#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +#if HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int msw:32; unsigned int lsw:32; #else @@ -216,7 +215,7 @@ union fpu_extended_shape { unsigned int mantissa0:32; unsigned int mantissa1:32; #else -# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +# if HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int exponent:15; unsigned int negative:1; unsigned int empty:16; @@ -243,7 +242,7 @@ union fpu_extended_shape { unsigned int mantissa0:30; unsigned int mantissa1:32; #else -# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +# if HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int exponent:15; unsigned int negative:1; unsigned int empty:16; @@ -265,7 +264,7 @@ union fpu_extended_shape { /* This format is used to extract the sign_exponent and mantissa parts only */ struct { -#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +#if HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int sign_exponent:16; unsigned int empty:16; unsigned int msw:32; @@ -311,7 +310,7 @@ union fpu_extended_shape { unsigned int exponent:15; unsigned int quiet_nan:1; unsigned int mantissa0:15; - unsigned int mantissa1:32; + unsigned int mantissa1:30; unsigned int mantissa2:32; unsigned int mantissa3:32; #else @@ -326,7 +325,7 @@ union fpu_extended_shape { } ieee_nan; /* This format is used to extract the sign_exponent and mantissa parts only */ -#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN +#if HOST_FLOAT_WORDS_BIG_ENDIAN struct { uae_u64 msw; uae_u64 lsw; @@ -352,9 +351,9 @@ union fpu_extended_shape { }; #endif -// Declare a shape of the requested FP type -#define fp_declare_init_shape(psvar, ftype) \ - fpu_ ## ftype ## _shape psvar +// Declare and initialize a pointer to a shape of the requested FP type +#define fp_declare_init_shape(psvar, rfvar, ftype) \ + fpu_ ## ftype ## _shape * psvar = (fpu_ ## ftype ## _shape *)( &rfvar ) /* -------------------------------------------------------------------------- */ /* --- Extra Math Functions --- */ @@ -371,51 +370,47 @@ union fpu_extended_shape { PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r) { #ifdef BRANCHES_ARE_EXPENSIVE -#if !defined(USE_LONG_DOUBLE) - fp_declare_init_shape(sxp, double); - sxp.value = r; - uae_s32 hx = sxp.parts.msw; - uae_s32 lx = sxp.parts.lsw; +#ifndef USE_LONG_DOUBLE + fp_declare_init_shape(sxp, r, double); + uae_s32 hx = sxp->parts.msw; + uae_s32 lx = sxp->parts.lsw; hx &= 0x7fffffff; hx |= (uae_u32)(lx | (-lx)) >> 31; hx = 0x7ff00000 - hx; - return (int)(((uae_u32)hx) >> 31); -#elif defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = r; - uae_s64 hx = sxp.parts64.msw; - uae_s64 lx = sxp.parts64.lsw; + return (((uae_u32)hx) >> 31) != 0; +#elif USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + uae_s64 hx = sxp->parts64.msw; + uae_s64 lx = sxp->parts64.lsw; hx &= 0x7fffffffffffffffLL; hx |= (uae_u64)(lx | (-lx)) >> 63; hx = 0x7fff000000000000LL - hx; - return (int)((uae_u64)hx >> 63); + return ((uae_u64)hx >> 63) != 0; #else - fp_declare_init_shape(sxp, extended); - sxp.value = r; - uae_s32 se = sxp.parts.sign_exponent; - uae_s32 hx = sxp.parts.msw; - uae_s32 lx = sxp.parts.lsw; + fp_declare_init_shape(sxp, r, extended); + uae_s32 se = sxp->parts.sign_exponent; + uae_s32 hx = sxp->parts.msw; + uae_s32 lx = sxp->parts.lsw; se = (se & 0x7fff) << 1; lx |= hx & 0x7fffffff; se |= (uae_u32)(lx | (-lx)) >> 31; se = 0xfffe - se; - return (int)(((uae_u32)(se)) >> 31); + // TODO: check whether rshift count is 16 or 31 + return (((uae_u32)(se)) >> 16) != 0; #endif #else -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = r; - return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX) +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX) #else - fp_declare_init_shape(sxp, double); - sxp.value = r; - return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX) + fp_declare_init_shape(sxp, r, double); + return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX) #endif - && (sxp.ieee_nan.mantissa0 != 0) - && (sxp.ieee_nan.mantissa1 != 0) + && (sxp->ieee_nan.mantissa0 != 0) + && (sxp->ieee_nan.mantissa1 != 0) #ifdef USE_QUAD_DOUBLE - && (sxp.ieee_nan.mantissa2 != 0) - && (sxp.ieee_nan.mantissa3 != 0) + && (sxp->ieee_nan.mantissa2 != 0) + && (sxp->ieee_nan.mantissa3 != 0) #endif ; #endif @@ -431,55 +426,50 @@ PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r) PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r) { #ifdef BRANCHES_ARE_EXPENSIVE -#if !defined(USE_LONG_DOUBLE) - fp_declare_init_shape(sxp, double); - sxp.value = r; - uae_s32 hx = sxp.parts.msw; - uae_s32 lx = sxp.parts.lsw; +#ifndef USE_LONG_DOUBLE + fp_declare_init_shape(sxp, r, double); + uae_s32 hx = sxp->parts.msw; + uae_s32 lx = sxp->parts.lsw; lx |= (hx & 0x7fffffff) ^ 0x7ff00000; lx |= -lx; - return ~(lx >> 31) & (hx >> 30); -#elif defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = r; - uae_s64 hx = sxp.parts64.msw; - uae_s64 lx = sxp.parts64.lsw; + return (~(lx >> 31) & (hx >> 30)) != 0; +#elif USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + uae_s64 hx = sxp->parts64.msw; + uae_s64 lx = sxp->parts64.lsw; lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL; lx |= -lx; - return ~(lx >> 63) & (hx >> 62); + return (~(lx >> 63) & (hx >> 62)) != 0; #else - fp_declare_init_shape(sxp, extended); - sxp.value = r; - uae_s32 se = sxp.parts.sign_exponent; - uae_s32 hx = sxp.parts.msw; - uae_s32 lx = sxp.parts.lsw; + fp_declare_init_shape(sxp, r, extended); + uae_s32 se = sxp->parts.sign_exponent; + uae_s32 hx = sxp->parts.msw; + uae_s32 lx = sxp->parts.lsw; /* This additional ^ 0x80000000 is necessary because in Intel's internal representation of the implicit one is explicit. NOTE: anyway, this is equivalent to & 0x7fffffff in that case. */ -#ifdef CPU_i386 +#ifdef __i386__ lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff); #else lx |= (hx & 0x7fffffff) | ((se & 0x7fff) ^ 0x7fff); #endif lx |= -lx; se &= 0x8000; - return ~(lx >> 31) & (1 - (se >> 14)); + return (~(lx >> 31) & (1 - (se >> 14))) != 0; #endif #else -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = r; - return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX) +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX) #else - fp_declare_init_shape(sxp, double); - sxp.value = r; - return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX) + fp_declare_init_shape(sxp, r, double); + return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX) #endif - && (sxp.ieee_nan.mantissa0 == 0) - && (sxp.ieee_nan.mantissa1 == 0) + && (sxp->ieee_nan.mantissa0 == 0) + && (sxp->ieee_nan.mantissa1 == 0) #ifdef USE_QUAD_DOUBLE - && (sxp.ieee_nan.mantissa2 == 0) - && (sxp.ieee_nan.mantissa3 == 0) + && (sxp->ieee_nan.mantissa2 == 0) + && (sxp->ieee_nan.mantissa3 == 0) #endif ; #endif @@ -490,13 +480,12 @@ PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r) PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); #else - fp_declare_init_shape(sxp, double); + fp_declare_init_shape(sxp, r, double); #endif - sxp.value = r; - return sxp.ieee.negative; + return sxp->ieee.negative; } #undef iszero @@ -505,18 +494,17 @@ PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r) PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r) { // TODO: BRANCHES_ARE_EXPENSIVE -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); #else - fp_declare_init_shape(sxp, double); + fp_declare_init_shape(sxp, r, double); #endif - sxp.value = r; - return (sxp.ieee.exponent == 0) - && (sxp.ieee.mantissa0 == 0) - && (sxp.ieee.mantissa1 == 0) + return (sxp->ieee.exponent == 0) + && (sxp->ieee.mantissa0 == 0) + && (sxp->ieee.mantissa1 == 0) #ifdef USE_QUAD_DOUBLE - && (sxp.ieee.mantissa2 == 0) - && (sxp.ieee.mantissa3 == 0) + && (sxp->ieee.mantissa2 == 0) + && (sxp->ieee.mantissa3 == 0) #endif ; } @@ -541,21 +529,21 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r) PRIVATE inline void FFPU make_nan(fpu_register & r) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.ieee.exponent = FP_EXTENDED_EXP_MAX; - sxp.ieee.mantissa0 = 0xffffffff; + // FIXME: is that correct ? +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + sxp->ieee.exponent = FP_EXTENDED_EXP_MAX; + sxp->ieee.mantissa0 = 0xffffffff; #else - fp_declare_init_shape(sxp, double); - sxp.ieee.exponent = FP_DOUBLE_EXP_MAX; - sxp.ieee.mantissa0 = 0xfffff; + fp_declare_init_shape(sxp, r, double); + sxp->ieee.exponent = FP_DOUBLE_EXP_MAX; + sxp->ieee.mantissa0 = 0xfffff; #endif - sxp.ieee.mantissa1 = 0xffffffff; + sxp->ieee.mantissa1 = 0xffffffff; #ifdef USE_QUAD_DOUBLE - sxp.ieee.mantissa2 = 0xffffffff; - sxp.ieee.mantissa3 = 0xffffffff; + sxp->ieee.mantissa2 = 0xffffffff; + sxp->ieee.mantissa3 = 0xffffffff; #endif - r = sxp.value; } PRIVATE inline void FFPU make_zero_positive(fpu_register & r) @@ -563,20 +551,19 @@ PRIVATE inline void FFPU make_zero_positive(fpu_register & r) #if 1 r = +0.0; #else -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); #else - fp_declare_init_shape(sxp, double); + fp_declare_init_shape(sxp, r, double); #endif - sxp.ieee.negative = 0; - sxp.ieee.exponent = 0; - sxp.ieee.mantissa0 = 0; - sxp.ieee.mantissa1 = 0; + sxp->ieee.negative = 0; + sxp->ieee.exponent = 0; + sxp->ieee.mantissa0 = 0; + sxp->ieee.mantissa1 = 0; #ifdef USE_QUAD_DOUBLE - sxp.ieee.mantissa2 = 0; - sxp.ieee.mantissa3 = 0; + sxp->ieee.mantissa2 = 0; + sxp->ieee.mantissa3 = 0; #endif - r = sxp.value; #endif } @@ -585,110 +572,101 @@ PRIVATE inline void FFPU make_zero_negative(fpu_register & r) #if 1 r = -0.0; #else -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); #else - fp_declare_init_shape(sxp, double); + fp_declare_init_shape(sxp, r, double); #endif - sxp.ieee.negative = 1; - sxp.ieee.exponent = 0; - sxp.ieee.mantissa0 = 0; - sxp.ieee.mantissa1 = 0; + sxp->ieee.negative = 1; + sxp->ieee.exponent = 0; + sxp->ieee.mantissa0 = 0; + sxp->ieee.mantissa1 = 0; #ifdef USE_QUAD_DOUBLE - sxp.ieee.mantissa2 = 0; - sxp.ieee.mantissa3 = 0; + sxp->ieee.mantissa2 = 0; + sxp->ieee.mantissa3 = 0; #endif - r = sxp.value; #endif } PRIVATE inline void FFPU make_inf_positive(fpu_register & r) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX; +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; #else - fp_declare_init_shape(sxp, double); - sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX; + fp_declare_init_shape(sxp, r, double); + sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; #endif - sxp.ieee_nan.negative = 0; - sxp.ieee_nan.mantissa0 = 0; - sxp.ieee_nan.mantissa1 = 0; + sxp->ieee_nan.negative = 0; + sxp->ieee_nan.mantissa0 = 0; + sxp->ieee_nan.mantissa1 = 0; #ifdef USE_QUAD_DOUBLE - sxp.ieee_nan.mantissa2 = 0; - sxp.ieee_nan.mantissa3 = 0; + sxp->ieee_nan.mantissa2 = 0; + sxp->ieee_nan.mantissa3 = 0; #endif - r = sxp.value; } PRIVATE inline void FFPU make_inf_negative(fpu_register & r) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX; +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; #else - fp_declare_init_shape(sxp, double); - sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX; + fp_declare_init_shape(sxp, r, double); + sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; #endif - sxp.ieee_nan.negative = 1; - sxp.ieee_nan.mantissa0 = 0; - sxp.ieee_nan.mantissa1 = 0; + sxp->ieee_nan.negative = 1; + sxp->ieee_nan.mantissa0 = 0; + sxp->ieee_nan.mantissa1 = 0; #ifdef USE_QUAD_DOUBLE - sxp.ieee_nan.mantissa2 = 0; - sxp.ieee_nan.mantissa3 = 0; + sxp->ieee_nan.mantissa2 = 0; + sxp->ieee_nan.mantissa3 = 0; #endif - r = sxp.value; } PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = r; - return ((int) sxp.ieee.exponent - FP_EXTENDED_EXP_BIAS); +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + return (sxp->ieee.exponent - FP_EXTENDED_EXP_BIAS); #else - fp_declare_init_shape(sxp, double); - sxp.value = r; - return ((int) sxp.ieee.exponent - FP_DOUBLE_EXP_BIAS); + fp_declare_init_shape(sxp, r, double); + return (sxp->ieee.exponent - FP_DOUBLE_EXP_BIAS); #endif } // Normalize to range 1..2 PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = r; - sxp.ieee.exponent = FP_EXTENDED_EXP_BIAS; +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, r, extended); + sxp->ieee.exponent = FP_EXTENDED_EXP_BIAS; #else - fp_declare_init_shape(sxp, double); - sxp.value = r; - sxp.ieee.exponent = FP_DOUBLE_EXP_BIAS; + fp_declare_init_shape(sxp, r, double); + sxp->ieee.exponent = FP_DOUBLE_EXP_BIAS; #endif - r = sxp.value; } // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sap, extended); - fp_declare_init_shape(sbp, extended); +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sap, ra, extended); + fp_declare_init_shape(sbp, rb, extended); #else - fp_declare_init_shape(sap, double); - fp_declare_init_shape(sbp, double); + fp_declare_init_shape(sap, ra, double); + fp_declare_init_shape(sbp, rb, double); #endif - sap.value = ra; - sbp.value = rb; - return ((sap.ieee.negative ^ sbp.ieee.negative) ? FPSR_QUOTIENT_SIGN : 0); + return ((sap->ieee.negative ^ sbp->ieee.negative) ? FPSR_QUOTIENT_SIGN : 0); } /* -------------------------------------------------------------------------- */ /* --- Math functions --- */ /* -------------------------------------------------------------------------- */ -#if defined(FPU_USE_ISO_C99) && (defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)) +#if FPU_USE_ISO_C99 +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE # ifdef HAVE_LOGL # define fp_log logl # endif @@ -812,14 +790,13 @@ PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_regis # define fp_ceil ceil #endif -#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) +#elif defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) // Assembly optimized support functions. Taken from glibc 2.2.2 #undef fp_log #define fp_log fp_do_log -#ifndef FPU_FAST_MATH -// FIXME: unimplemented +#if !FPU_FAST_MATH PRIVATE fpu_extended fp_do_log(fpu_extended x); #else PRIVATE inline fpu_extended fp_do_log(fpu_extended x) @@ -833,7 +810,7 @@ PRIVATE inline fpu_extended fp_do_log(fpu_extended x) #undef fp_log10 #define fp_log10 fp_do_log10 -#ifndef FPU_FAST_MATH +#if !FPU_FAST_MATH // FIXME: unimplemented PRIVATE fpu_extended fp_do_log10(fpu_extended x); #else @@ -848,20 +825,13 @@ PRIVATE inline fpu_extended fp_do_log10(fpu_extended x) #undef fp_exp #define fp_exp fp_do_exp -#ifndef FPU_FAST_MATH +#if !FPU_FAST_MATH // FIXME: unimplemented PRIVATE fpu_extended fp_do_exp(fpu_extended x); #else PRIVATE inline fpu_extended fp_do_exp(fpu_extended x) { fpu_extended value, exponent; - if (isinf(x)) - { - if(isneg(x)) - return 0.; - else - return x; - } __asm__ __volatile__("fldl2e # e^x = 2^(x * log2(e))\n\t" "fmul %%st(1) # x * log2(e)\n\t" "fst %%st(1)\n\t" @@ -901,7 +871,6 @@ PRIVATE inline fpu_extended fp_do_sqrt(fpu_extended x) return value; } -#ifndef ACCURATE_SIN_COS_TAN #undef fp_sin #define fp_sin fp_do_sin @@ -927,11 +896,10 @@ PRIVATE inline fpu_extended fp_do_cos(fpu_extended x) PRIVATE inline fpu_extended fp_do_tan(fpu_extended x) { - fpu_extended value, value2; - __asm__ __volatile__("fptan" : "=t" (value2), "=u" (value) : "0" (x)); + fpu_extended value; + __asm__ __volatile__("fptan" : "=t" (value) : "0" (x)); return value; } -#endif /* ACCURATE_SIN_COS_TAN */ #undef fp_expm1 #define fp_expm1 fp_do_expm1 @@ -939,14 +907,7 @@ PRIVATE inline fpu_extended fp_do_tan(fpu_extended x) // Returns: exp(X) - 1.0 PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) { - fpu_extended value, exponent, temp, temp2; - if (isinf(x)) - { - if(isneg(x)) - return -1.; - else - return x; - } + fpu_extended value, exponent, temp; __asm__ __volatile__("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" "fmul %%st(1) # x * log2(e)\n\t" "fst %%st(1)\n\t" @@ -956,9 +917,7 @@ PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" : "=t" (value), "=u" (exponent) : "0" (x)); - __asm__ __volatile__("fld1 \n\t" - "fscale \n\t" - : "=t" (temp), "=u" (temp2) : "0" (exponent)); + __asm__ __volatile__("fscale" : "=t" (temp) : "0" (1.0), "u" (exponent)); temp -= 1.0; return temp + value ? temp + value : x; } @@ -968,33 +927,29 @@ PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) PRIVATE inline fpu_extended fp_do_sgn1(fpu_extended x) { -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = x; - sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX>>1; - sxp.ieee_nan.one = 1; +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, x, extended); + sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; + sxp->ieee_nan.one = 1; #else - fp_declare_init_shape(sxp, double); - sxp.value = x; - sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX>>1; + fp_declare_init_shape(sxp, x, double); + sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; #endif - sxp.ieee_nan.quiet_nan = 0; - sxp.ieee_nan.mantissa0 = 0; - sxp.ieee_nan.mantissa1 = 0; - x = sxp.value; + sxp->ieee_nan.quiet_nan = 0; + sxp->ieee_nan.mantissa0 = 0; + sxp->ieee_nan.mantissa1 = 0; return x; } #undef fp_sinh #define fp_sinh fp_do_sinh -#ifndef FPU_FAST_MATH +#if !FPU_FAST_MATH // FIXME: unimplemented PRIVATE fpu_extended fp_do_sinh(fpu_extended x); #else PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x) { - if (isinf(x)) return x; fpu_extended exm1 = fp_expm1(fp_fabs(x)); return 0.5 * (exm1 / (exm1 + 1.0) + exm1) * fp_sgn1(x); } @@ -1003,7 +958,7 @@ PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x) #undef fp_cosh #define fp_cosh fp_do_cosh -#ifndef FPU_FAST_MATH +#if !FPU_FAST_MATH // FIXME: unimplemented PRIVATE fpu_extended fp_do_cosh(fpu_extended x); #else @@ -1017,7 +972,7 @@ PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x) #undef fp_tanh #define fp_tanh fp_do_tanh -#ifndef FPU_FAST_MATH +#if !FPU_FAST_MATH // FIXME: unimplemented PRIVATE fpu_extended fp_do_tanh(fpu_extended x); #else @@ -1096,46 +1051,48 @@ PRIVATE inline fpu_extended fp_do_atanh(fpu_extended x) return -0.5 * fp_log1p(-(y + y) / (1.0 + y)) * fp_sgn1(x); } +#undef fp_floor +#define fp_floor fp_do_floor -/* - * LLVM 2.9 crashes on first definition, - * clang with LLVM 3.x crashes on 2nd definition... sigh - */ -#if defined(__clang__) || !defined(__llvm__) -#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ -PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended __x) \ -{ \ - register long double __value; \ - register int __ignore; \ - volatile unsigned short __cw; \ - volatile unsigned short __cwtmp; \ - __asm __volatile ("fnstcw %3\n\t" \ - "movzwl %3, %1\n\t" \ - "andl $0xf3ff, %1\n\t" \ - "orl %5, %1\n\t" \ - "movw %w1, %2\n\t" \ - "fldcw %2\n\t" \ - "frndint\n\t" \ - "fldcw %3" \ - : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ - "=m" (__cw) \ - : "0" (__x), "i"(rounding_mode)); \ - return __value; \ +PRIVATE inline fpu_extended fp_do_floor(fpu_extended x) +{ + volatile unsigned int cw; + __asm__ __volatile__("fnstcw %0" : "=m" (cw)); + volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0400; // rounding down + __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); + fpu_extended value; + __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); + __asm__ __volatile__("fldcw %0" : : "m" (cw)); + return value; } -#else + +#undef fp_ceil +#define fp_ceil fp_do_ceil + +PRIVATE inline fpu_extended fp_do_ceil(fpu_extended x) +{ + volatile unsigned int cw; + __asm__ __volatile__("fnstcw %0" : "=m" (cw)); + volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0800; // rounding up + __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); + fpu_extended value; + __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); + __asm__ __volatile__("fldcw %0" : : "m" (cw)); + return value; +} + #define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended x) \ { \ - volatile unsigned short cw; \ + volatile unsigned int cw; \ __asm__ __volatile__("fnstcw %0" : "=m" (cw)); \ - volatile unsigned short cw_temp = (cw & 0xf3ff) | (rounding_mode); \ + volatile unsigned int cw_temp = (cw & 0xf3ff) | (rounding_mode); \ __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); \ fpu_extended value; \ __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); \ __asm__ __volatile__("fldcw %0" : : "m" (cw)); \ return value; \ } -#endif #undef fp_round_to_minus_infinity #define fp_round_to_minus_infinity fp_do_round_to_minus_infinity @@ -1157,13 +1114,6 @@ DEFINE_ROUND_FUNC(zero, 0xc00) DEFINE_ROUND_FUNC(nearest, 0x000) -#undef fp_ceil -#define fp_ceil fp_do_round_to_plus_infinity - -#undef fp_floor -#define fp_floor fp_do_round_to_minus_infinity - - #endif /* USE_X87_ASSEMBLY */ #ifndef fp_round_to_minus_infinity diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.cpp b/BasiliskII/src/uae_cpu/fpu/rounding.cpp index 9942d4e8..1f8b3618 100644 --- a/BasiliskII/src/uae_cpu/fpu/rounding.cpp +++ b/BasiliskII/src/uae_cpu/fpu/rounding.cpp @@ -1,33 +1,28 @@ /* - * fpu/rounding.cpp - system-dependant FPU rounding mode and precision + * fpu/rounding.cpp - system-dependant FPU rounding mode and precision * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #undef PRIVATE diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.h b/BasiliskII/src/uae_cpu/fpu/rounding.h index 60c4baff..67db5519 100644 --- a/BasiliskII/src/uae_cpu/fpu/rounding.h +++ b/BasiliskII/src/uae_cpu/fpu/rounding.h @@ -1,33 +1,28 @@ /* - * fpu/rounding.h - system-dependant FPU rounding mode and precision + * fpu/rounding.h - system-dependant FPU rounding mode and precision * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_ROUNDING_H diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h index afd3ab28..778567a9 100644 --- a/BasiliskII/src/uae_cpu/fpu/types.h +++ b/BasiliskII/src/uae_cpu/fpu/types.h @@ -1,33 +1,28 @@ /* - * fpu/types.h - basic types for fpu registers + * types.h - basic types for fpu registers * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_TYPES_H @@ -111,9 +106,9 @@ typedef uae_f32 fpu_single; #elif defined(FPU_IEEE) -#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT -#error "No IEEE float format, you lose." -#endif +// #if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT +// #error "No IEEE float format, you lose." +// #endif /* 4-byte floats */ #if SIZEOF_FLOAT == 4 @@ -138,7 +133,7 @@ typedef long double uae_f64; typedef long double uae_f96; typedef uae_f96 fpu_register; #define USE_LONG_DOUBLE 1 -#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64)) +#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__)) /* Long doubles on x86-64 are really held in old x87 FPU stack. */ typedef long double uae_f128; typedef uae_f128 fpu_register; @@ -159,23 +154,6 @@ typedef fpu_register fpu_extended; typedef uae_f64 fpu_double; typedef uae_f32 fpu_single; -#elif defined(FPU_MPFR) - -#include - -struct fpu_register { - mpfr_t f; - uae_u64 nan_bits; - int nan_sign; - operator long double (); - fpu_register &operator=(long double); -}; - #endif -union fpu_register_parts { - fpu_register val; - uae_u32 parts[sizeof(fpu_register) / 4]; -}; - #endif /* FPU_TYPES_H */ diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 8db74001..1653adab 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -1,27 +1,3 @@ -/* - * gencpu.c - m68k emulation generator - * - * Copyright (c) 2009 ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ /* * UAE - The Un*x Amiga Emulator * @@ -38,26 +14,42 @@ * take care of this. * * Copyright 1995, 1996 Bernd Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * */ -#define CC_FOR_BUILD 1 - -#include "sysdeps.h" -#include "readcpu.h" - #include #include #include #include -#include -#undef abort + +#include "sysdeps.h" +#include "readcpu.h" + +#if defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) +#define SPARC_ASSEMBLY 0 +#endif #define BOOL_TYPE "int" -#define VERIFY_MMU_GENAMODE 0 + +/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ +#define xBCD_KEEPS_NV_FLAGS 4 static FILE *headerfile; static FILE *stblfile; -static FILE *functblfile; static int using_prefetch; static int using_exception_3; @@ -73,23 +65,6 @@ static int *opcode_next_clev; static int *opcode_last_postfix; static unsigned long *counts; -#define GENA_GETV_NO_FETCH 0 -#define GENA_GETV_FETCH 1 -#define GENA_GETV_FETCH_ALIGN 2 -#define GENA_MOVEM_DO_INC 0 -#define GENA_MOVEM_NO_INC 1 -#define GENA_MOVEM_MOVE16 2 - -#define XLATE_LOG 0 -#define XLATE_PHYS 1 -#define XLATE_SFC 2 -#define XLATE_DFC 3 -static char * mem_prefix[4] = { "", "phys_", "sfc_", "dfc_" }; - -/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ -#define xBCD_KEEPS_N_FLAG 4 -#define xBCD_KEEPS_V_FLAG 3 - static void read_counts (void) { FILE *file; @@ -100,8 +75,7 @@ static void read_counts (void) file = fopen ("frequent.68k", "r"); if (file) { - int c = fscanf (file, "Total: %lu\n", &total); - assert(c == 1); + fscanf (file, "Total: %lu\n", &total); while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) { opcode_next_clev[nr] = 4; opcode_last_postfix[nr] = -1; @@ -132,6 +106,7 @@ static int need_endlabel; static int n_braces = 0; static int m68k_pc_offset = 0; +static int insn_n_cycles; static void start_brace (void) { @@ -184,9 +159,10 @@ static const char *gen_nextilong (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 4; + insn_n_cycles += 4; + if (using_prefetch) sprintf (buffer, "get_ilong_prefetch(%d)", r); else @@ -198,9 +174,10 @@ static const char *gen_nextiword (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 2; + insn_n_cycles += 2; + if (using_prefetch) sprintf (buffer, "get_iword_prefetch(%d)", r); else @@ -214,6 +191,8 @@ static const char *gen_nextibyte (void) int r = m68k_pc_offset; m68k_pc_offset += 2; + insn_n_cycles += 2; + if (using_prefetch) sprintf (buffer, "get_ibyte_prefetch(%d)", r); else @@ -235,22 +214,9 @@ static void fill_prefetch_2 (void) static void swap_opcode (void) { - printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); - printf ("\topcode = do_byteswap_16(opcode);\n"); - printf("#endif\n"); -} - -static void real_opcode (int *have) -{ - if (!*have) - { - printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); - printf ("\tuae_u32 real_opcode = do_byteswap_16(opcode);\n"); - printf("#else\n"); - printf ("\tuae_u32 real_opcode = opcode;\n"); - printf("#endif\n"); - *have = 1; - } + printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); + printf ("\topcode = ((opcode << 8) & 0xFF00) | ((opcode >> 8) & 0xFF);\n"); + printf ("#endif\n"); } static void sync_m68k_pc (void) @@ -272,49 +238,33 @@ static void sync_m68k_pc (void) m68k_pc_offset = 0; } -static void gen_set_fault_pc (void) -{ - sync_m68k_pc(); - printf ("regs.fault_pc = m68k_getpc ();\n"); - m68k_pc_offset = 0; -} - /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, * the calling routine handles Apdi and Aipi modes. * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ - -/* fixup indicates if we want to fix up adress registers in pre decrement - * or post increment mode now (0) or later (1). A value of 2 will then be - * used to do the actual fix up. This allows to do all memory readings - * before any register is modified, and so to rerun operation without - * side effect in case a bus fault is generated by any memory access. - * XJ - 2006/11/13 */ -static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag, int fixup) +static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) { - if (fixup != 2) - { start_brace (); switch (mode) { case Dreg: if (movem) abort (); - if (getv == GENA_GETV_FETCH) + if (getv == 1) switch (size) { case sz_byte: - printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); +#if defined(AMIGA) && !defined(WARPUP) /* sam: I don't know why gcc.2.7.2.1 produces a code worse */ /* if it is not done like that: */ printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg); - printf("#else\n"); +#else printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg); - printf("#endif\n"); +#endif break; case sz_word: - printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); +#if defined(AMIGA) && !defined(WARPUP) printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg); - printf("#else\n"); +#else printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg); - printf("#endif\n"); +#endif break; case sz_long: printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg); @@ -326,7 +276,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g case Areg: if (movem) abort (); - if (getv == GENA_GETV_FETCH) + if (getv == 1) switch (size) { case sz_word: printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg); @@ -353,16 +303,10 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg); break; case sz_word: - if (movem) - printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); - else - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 2;\n", name, reg); + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2); break; case sz_long: - if (movem) - printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); - else - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 4;\n", name, reg); + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4); break; default: abort (); @@ -407,7 +351,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ()); break; case imm: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); switch (size) { case sz_byte: @@ -424,22 +368,22 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } return; case imm0: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ()); return; case imm1: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ()); return; case imm2: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ()); return; case immi: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_u32 %s = %s;\n", name, reg); return; @@ -450,7 +394,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g /* We get here for all non-reg non-immediate addressing modes to * actually fetch the value. */ - if (using_exception_3 && getv != GENA_GETV_NO_FETCH && size != sz_byte) { + if (using_exception_3 && getv != 0 && size != sz_byte) { printf ("\tif ((%sa & 1) != 0) {\n", name); printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name); printf ("\t\tlast_op_for_exception_3 = opcode;\n"); @@ -462,29 +406,20 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g start_brace (); } - if (getv == GENA_GETV_FETCH) { + if (getv == 1) { switch (size) { - case sz_byte: break; - case sz_word: break; - case sz_long: break; + case sz_byte: insn_n_cycles += 2; break; + case sz_word: insn_n_cycles += 2; break; + case sz_long: insn_n_cycles += 4; break; default: abort (); } start_brace (); - printf("\n#ifdef FULLMMU\n"); switch (size) { - case sz_byte: printf ("\tuae_s8 %s = %sget_byte(%sa);\n", name, mem_prefix[xlateflag], name); break; - case sz_word: printf ("\tuae_s16 %s = %sget_word(%sa);\n", name, mem_prefix[xlateflag], name); break; - case sz_long: printf ("\tuae_s32 %s = %sget_long(%sa);\n", name, mem_prefix[xlateflag], name); break; + case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break; + case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break; + case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break; default: abort (); } - printf("#else\n"); - switch (size) { - case sz_byte: printf ("\tuae_s8 %s = phys_get_byte(%sa);\n", name, name); break; - case sz_word: printf ("\tuae_s16 %s = phys_get_word(%sa);\n", name, name); break; - case sz_long: printf ("\tuae_s32 %s = phys_get_long(%sa);\n", name, name); break; - default: abort (); - } - printf("#endif\n"); } /* We now might have to fix up the register for pre-dec or post-inc @@ -492,12 +427,6 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (!movem) switch (mode) { case Aipi: - if (fixup == 1) - { - printf ("\tfixup.flag = 1;\n"); - printf ("\tfixup.reg = %s;\n", reg); - printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); - } switch (size) { case sz_byte: printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg); @@ -513,39 +442,14 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } break; case Apdi: - if (fixup == 1) - { - printf ("\tfixup.flag = 1;\n"); - printf ("\tfixup.reg = %s;\n", reg); - printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); - } printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name); break; default: break; } - - } - else /* (fixup != 2) */ - { - if (!movem) - switch (mode) { - case Aipi: - case Apdi: - printf ("\tfixup.flag = 0;\n"); - break; - default: - break; - } - } } -static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag) -{ - genamode2 (mode, reg, size, name, getv, movem, xlateflag, 0); -} - -static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag) +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to) { switch (mode) { case Dreg: @@ -585,32 +489,28 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char case absl: case PC16: case PC8r: - gen_set_fault_pc (); - printf("#ifdef FULLMMU\n"); + if (using_prefetch) + sync_m68k_pc (); switch (size) { case sz_byte: - printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from); - printf("#else\n"); + insn_n_cycles += 2; printf ("\tput_byte(%sa,%s);\n", to, from); break; case sz_word: + insn_n_cycles += 2; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from); - printf("#else\n"); printf ("\tput_word(%sa,%s);\n", to, from); break; case sz_long: + insn_n_cycles += 4; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from); - printf("#else\n"); printf ("\tput_long(%sa,%s);\n", to, from); break; default: abort (); } - printf("#endif\n"); break; case imm: case imm0: @@ -626,33 +526,23 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char static void genmovemel (uae_u16 opcode) { - char getcode1[100]; - char getcode2[100]; + char getcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; - + if (table68k[opcode].size == sz_long) { - strcpy (getcode1, ""); - strcpy (getcode2, "get_long(srca)"); + strcpy (getcode, "get_long(srca)"); } else { - strcpy (getcode1, "(uae_s32)(uae_s16)"); - strcpy (getcode2, "get_word(srca)"); + strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)"); } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); start_brace (); - printf("\n#ifdef FULLMMU\n"); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s%s; srca += %d; dmask = movem_next[dmask]; }\n", - getcode1, getcode2, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s%s; srca += %d; amask = movem_next[amask]; }\n", - getcode1, getcode2, size); - printf("#else\n"); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %sphys_%s; srca += %d; dmask = movem_next[dmask]; }\n", - getcode1, getcode2, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %sphys_%s; srca += %d; amask = movem_next[amask]; }\n", - getcode1, getcode2, size); - printf("#endif\n"); + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", + getcode, size); + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n", + getcode, size); if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg(regs, dstreg) = srca;\n"); @@ -662,7 +552,6 @@ static void genmovemle (uae_u16 opcode) { char putcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; - if (table68k[opcode].size == sz_long) { strcpy (putcode, "put_long(srca,"); } else { @@ -670,38 +559,24 @@ static void genmovemle (uae_u16 opcode) } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", - GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); - sync_m68k_pc (); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + if (using_prefetch) + sync_m68k_pc (); start_brace (); if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); - printf("#ifdef FULLMMU\n"); printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", size, putcode); printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", size, putcode); - printf("#else\n"); - printf ("\twhile (amask) { srca -= %d; phys_%s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", - size, putcode); - printf ("\twhile (dmask) { srca -= %d; phys_%s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", - size, putcode); - printf("#endif\n"); printf ("\tm68k_areg(regs, dstreg) = srca;\n"); } else { printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf("#ifdef FULLMMU\n"); printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", putcode, size); printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", putcode, size); - printf("#else\n"); - printf ("\twhile (dmask) { phys_%s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", - putcode, size); - printf ("\twhile (amask) { phys_%s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", - putcode, size); - printf("#endif\n"); } } @@ -774,10 +649,12 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * break; case flag_add: + start_brace (); printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr); break; case flag_sub: case flag_cmp: + start_brace (); printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr); break; } @@ -796,6 +673,7 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * case flag_cmp: case flag_av: case flag_sv: + start_brace (); printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr); printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr); printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr); @@ -863,13 +741,11 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have them in the appropriate m68k.h files and use just one copy of this code here. The API can be changed if necessary. */ - int done = 0; - - start_brace (); - printf("\n#ifdef OPTIMIZED_FLAGS\n"); +#ifdef OPTIMIZED_FLAGS switch (type) { case flag_add: case flag_sub: + start_brace (); printf ("\tuae_u32 %s;\n", value); break; default: @@ -891,9 +767,8 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch printf ("\tIOR_CZNV (oldcznv);\n"); } printf ("\t}\n"); - done = 1; - break; - + return; + case flag_logical: if (strcmp (value, "0") == 0) { printf ("\tSET_CZNV (FLAGVAL_Z);\n"); @@ -904,8 +779,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; } } - done = 1; - break; + return; case flag_add: switch (size) { @@ -913,8 +787,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - done = 1; - break; + return; case flag_sub: switch (size) { @@ -922,8 +795,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - done = 1; - break; + return; case flag_cmp: switch (size) { @@ -931,19 +803,13 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; } - done = 1; - break; + return; default: break; } - if (done) - printf("#else\n"); - else - printf("#endif\n"); +#endif genflags_normal (type, size, value, src, dst); - if (done) - printf("#endif\n"); } static void force_range_for_rox (const char *var, wordsizes size) @@ -971,7 +837,7 @@ static const char *cmask (wordsizes size) case sz_byte: return "0x80"; case sz_word: return "0x8000"; case sz_long: return "0x80000000"; - default: abort (); return NULL; + default: abort (); } } @@ -983,10 +849,11 @@ static int source_is_imm1_8 (struct instr *i) static void gen_opcode (unsigned long int opcode) { struct instr *curi = table68k + opcode; + insn_n_cycles = 2; start_brace (); #if 0 - printf ("uae_u8 *m68k_pc = m68k_getpc();\n"); + printf ("uae_u8 *m68k_pc = regs.pc_p;\n"); #endif m68k_pc_offset = 2; switch (curi->plev) { @@ -1016,16 +883,16 @@ static void gen_opcode (unsigned long int opcode) case i_OR: case i_AND: case i_EOR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ORSR: case i_EORSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); if (curi->size == sz_byte) { printf ("\tsrc &= 0xFF;\n"); } @@ -1034,7 +901,7 @@ static void gen_opcode (unsigned long int opcode) break; case i_ANDSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); if (curi->size == sz_byte) { printf ("\tsrc |= 0xFF00;\n"); } @@ -1042,33 +909,31 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SUB: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_sub, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_SUBA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst - src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); break; case i_SUBX: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_SBCD: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n"); @@ -1079,50 +944,44 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ - if (cpu_level >= xBCD_KEEPS_N_FLAG) { - if (next_cpu_level < xBCD_KEEPS_N_FLAG) - next_cpu_level = xBCD_KEEPS_N_FLAG - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } else { - genflags (flag_zn, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68040 don't change them */ + if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { + if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) + next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; + genflags (flag_z, curi->size, "newv", "", ""); } - if (cpu_level >= xBCD_KEEPS_V_FLAG) { - if (next_cpu_level < xBCD_KEEPS_V_FLAG) - next_cpu_level = xBCD_KEEPS_V_FLAG - 1; - } else { - printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + else { + genflags (flag_zn, curi->size, "newv", "", ""); + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); } - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ADD: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_add, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ADDA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst + src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); break; case i_ADDX: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n"); genflags (flag_addx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ABCD: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); @@ -1134,85 +993,75 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (cflg) newv += 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ - if (cpu_level >= xBCD_KEEPS_N_FLAG) { - if (next_cpu_level < xBCD_KEEPS_N_FLAG) - next_cpu_level = xBCD_KEEPS_N_FLAG - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } else { - genflags (flag_zn, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68040 don't change them */ + if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { + if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) + next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; + genflags (flag_z, curi->size, "newv", "", ""); } - if (cpu_level >= xBCD_KEEPS_V_FLAG) { - if (next_cpu_level < xBCD_KEEPS_V_FLAG) - next_cpu_level = xBCD_KEEPS_V_FLAG - 1; - } else { - printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); + else { + genflags (flag_zn, curi->size, "newv", "", ""); + printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); } - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_NEG: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); genflags (flag_sub, curi->size, "dst", "src", "0"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); break; case i_NEGX: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "0"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("newv", curi->smode, "srcreg", curi->size, "src"); break; case i_NBCD: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n"); printf ("\tuae_u16 newv;\n"); - printf ("\tint cflg, tmp_newv;\n"); - printf ("\ttmp_newv = newv_hi + newv_lo;\n"); + printf ("\tint cflg;\n"); printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n"); printf ("\tnewv = newv_hi + newv_lo;\n"); printf ("\tcflg = (newv & 0x1F0) > 0x90;\n"); printf ("\tif (cflg) newv -= 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry(); - /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ - if (cpu_level >= xBCD_KEEPS_N_FLAG) { - if (next_cpu_level < xBCD_KEEPS_N_FLAG) - next_cpu_level = xBCD_KEEPS_N_FLAG - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } else { - genflags (flag_zn, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68040 don't change them */ + if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { + if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) + next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; + genflags (flag_z, curi->size, "newv", "", ""); } - if (cpu_level >= xBCD_KEEPS_V_FLAG) { - if (next_cpu_level < xBCD_KEEPS_V_FLAG) - next_cpu_level = xBCD_KEEPS_V_FLAG - 1; - } else { - printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + else { + genflags (flag_zn, curi->size, "newv", "", ""); } - genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("newv", curi->smode, "srcreg", curi->size, "src"); break; case i_CLR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); genflags (flag_logical, curi->size, "0", "", ""); - genastore ("0", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("0", curi->smode, "srcreg", curi->size, "src"); break; case i_NOT: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tuae_u32 dst = ~src;\n"); genflags (flag_logical, curi->size, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); break; case i_TST: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genflags (flag_logical, curi->size, "src", "", ""); break; case i_BTST: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else @@ -1220,55 +1069,55 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); break; case i_BCHG: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tdst ^= (1 << src);\n"); printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_BCLR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst &= ~(1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_BSET: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst |= (1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_CMPM: case i_CMP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_cmp, curi->size, "newv", "src", "dst"); break; case i_CMPA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); genflags (flag_cmp, sz_long, "newv", "src", "dst"); break; /* The next two are coded a little unconventional, but they are doing * weird things... */ case i_MVPRM: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); if (curi->size == sz_word) { @@ -1280,45 +1129,41 @@ static void gen_opcode (unsigned long int opcode) break; case i_MVPMR: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); if (curi->size == sz_word) { - printf ("\tuae_u16 val = get_byte(memp) << 8;\n"); - printf ("\t val |= get_byte(memp + 2);\n"); + printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n"); } else { - printf ("\tuae_u32 val = get_byte(memp) << 24;\n"); - printf ("\t val |= get_byte(memp + 2) << 16;\n"); - printf ("\t val |= get_byte(memp + 4) << 8;\n"); - printf ("\t val |= get_byte(memp + 6);\n"); + printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n"); + printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n"); } - genastore ("val", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "dst"); break; case i_MOVE: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; case i_MOVEA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); if (curi->size == sz_word) { printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n"); } else { printf ("\tuae_u32 val = src;\n"); } - genastore ("val", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", sz_long, "dst"); break; case i_MVSR2: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 2, 0); printf ("\tMakeSR();\n"); if (curi->size == sz_byte) - genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); + genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src"); else - genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src"); break; case i_MV2SR: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); if (curi->size == sz_byte) printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n"); else { @@ -1327,84 +1172,66 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SWAP: - genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); start_brace (); printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n"); genflags (flag_logical, sz_long, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", sz_long, "src"); break; case i_EXG: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; case i_EXT: - genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); start_brace (); switch (curi->size) { - case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; - case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; - default: abort (); + case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; + case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; + default: abort (); } genflags (flag_logical, curi->size == sz_word ? sz_word : sz_long, "dst", "", ""); genastore ("dst", curi->smode, "srcreg", - curi->size == sz_word ? sz_word : sz_long, "src", XLATE_LOG); + curi->size == sz_word ? sz_word : sz_long, "src"); break; case i_MVMEL: - genmovemel (opcode); + genmovemel ((uae_u16)opcode); break; case i_MVMLE: - genmovemle (opcode); + genmovemle ((uae_u16)opcode); break; case i_TRAP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - gen_set_fault_pc (); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + sync_m68k_pc (); printf ("\tException(src+32,0);\n"); + m68k_pc_offset = 0; break; case i_MVR2USP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tregs.usp = src;\n"); break; case i_MVUSP2R: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src"); break; case i_RESET: - printf ("\tAtariReset();\n"); break; case i_NOP: break; case i_STOP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - /* - * STOP undocumented features: - * if SR is not set: - * 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu) - * 68000 (68010?): Traced STOP also runs 4 cycles faster. - * 68020 68030: STOP works normally - * 68040 68060: Immediate privilege violation exception - */ - printf ("\tuae_u16 sr = src;\n"); - if (cpu_level >= 4) { - printf("\tif (!(sr & 0x2000)) {\n"); - printf ("m68k_incpc(%d);\n", m68k_pc_offset); - printf("\t\tException(8,0); goto %s;\n", endlabelstr); - printf("\t}\n"); - } - printf("\tregs.sr = sr;\n"); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tregs.sr = src;\n"); printf ("\tMakeFromSR();\n"); printf ("\tm68k_setstopped(1);\n"); - sync_m68k_pc (); - /* STOP does not prefetch anything */ - /* did_prefetch = -1; */ break; case i_RTE: if (cpu_level == 0) { - genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_word, "sr", 1, 0); + genamode (Aipi, "7", sz_long, "pc", 1, 0); printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n"); fill_prefetch_0 (); printf ("\tMakeFromSR();\n"); @@ -1413,14 +1240,15 @@ static void gen_opcode (unsigned long int opcode) if (next_cpu_level < 0) next_cpu_level = 0; printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n"); - genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_word, "sr", 1, 0); + genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode (Aipi, "7", sz_word, "format", 1, 0); printf ("\tnewsr = sr; newpc = pc;\n"); printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); -// printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); + /* gb-- the next two lines are deleted in Bernie's gencpu.c */ + printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n"); @@ -1438,8 +1266,8 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_RTD: - genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); printf ("\tm68k_areg(regs, 7) += offs;\n"); printf ("\tm68k_setpc_rte(pc);\n"); fill_prefetch_0 (); @@ -1447,18 +1275,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_LINK: - genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); + genamode (Apdi, "7", sz_long, "old", 2, 0); + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genastore ("src", Apdi, "7", sz_long, "old"); + genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src"); + genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); printf ("\tm68k_areg(regs, 7) += offs;\n"); - genastore ("src", Apdi, "7", sz_long, "old", XLATE_LOG); break; case i_UNLK: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tm68k_areg(regs, 7) = src;\n"); - genamode (Aipi, "7", sz_long, "old", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("old", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genamode (Aipi, "7", sz_long, "old", 1, 0); + genastore ("old", curi->smode, "srcreg", curi->size, "src"); break; case i_RTS: printf ("\tm68k_do_rts();\n"); @@ -1466,16 +1294,14 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_TRAPV: - printf ("\tuaecptr oldpc = m68k_getpc();\n"); sync_m68k_pc (); - printf ("\tif (GET_VFLG) { Exception(7,oldpc); goto %s; }\n", endlabelstr); + printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr); need_endlabel = 1; break; case i_RTR: printf ("\tMakeSR();\n"); - genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (Aipi, "7", sz_word, "sr", 1, 0); + genamode (Aipi, "7", sz_long, "pc", 1, 0); printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n"); printf ("\tregs.sr |= sr; m68k_setpc(pc);\n"); fill_prefetch_0 (); @@ -1483,19 +1309,19 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_JSR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_JMP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); printf ("\tm68k_setpc(srca);\n"); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_BSR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tuae_s32 s = (uae_s32)src + 2;\n"); if (using_exception_3) { printf ("\tif (src & 1) {\n"); @@ -1510,6 +1336,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_Bcc: + if (0 && !using_prefetch && !using_exception_3 && (cpu_level >= 2)) { + /* gb-- variant probably more favorable to compiler optimizations + also assumes no prefetch buffer is used + Hmm, that would make sense with processors capable of conditional moves */ + if (curi->size == sz_long && next_cpu_level < 1) + next_cpu_level = 1; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tm68k_incpc (cctrue(%d) ? ((uae_s32)src + 2) : %d);\n", curi->cc, m68k_pc_offset); + m68k_pc_offset = 0; + } + else { + /* original code for branch instructions */ if (curi->size == sz_long) { if (cpu_level < 2) { printf ("\tm68k_incpc(2);\n"); @@ -1523,8 +1361,8 @@ static void gen_opcode (unsigned long int opcode) next_cpu_level = 1; } } - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); - printf ("\tif (!cctrue(%d)) goto didnt_jump_%lx;\n", curi->cc, opcode); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc); if (using_exception_3) { printf ("\tif (src & 1) {\n"); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); @@ -1536,25 +1374,26 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); fill_prefetch_0 (); printf ("return;\n"); - printf ("didnt_jump_%lx:;\n", opcode); + printf ("didnt_jump:;\n"); need_endlabel = 1; + } break; case i_LEA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("srca", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); break; case i_PEA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("srca", Apdi, "7", sz_long, "dst", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (Apdi, "7", sz_long, "dst", 2, 0); + genastore ("srca", Apdi, "7", sz_long, "dst"); break; case i_DBcc: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); printf ("\tif (!cctrue(%d)) {\n", curi->cc); - genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src"); printf ("\t\tif (src) {\n"); if (using_exception_3) { @@ -1573,15 +1412,15 @@ static void gen_opcode (unsigned long int opcode) need_endlabel = 1; break; case i_Scc: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); start_brace (); printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc); - genastore ("val", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "src"); break; case i_DIVU: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); sync_m68k_pc (); /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends * on this (actually, it's doing a DIVS). */ @@ -1593,15 +1432,16 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); printf ("\t}\n"); printf ("\t}\n"); + insn_n_cycles += 68; need_endlabel = 1; break; case i_DIVS: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); sync_m68k_pc (); printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); @@ -1610,31 +1450,34 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); printf ("\t}\n"); printf ("\t}\n"); + insn_n_cycles += 72; need_endlabel = 1; break; case i_MULU: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + insn_n_cycles += 32; break; case i_MULS: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + insn_n_cycles += 32; break; case i_CHK: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr); printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; @@ -1642,8 +1485,8 @@ static void gen_opcode (unsigned long int opcode) case i_CHK2: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n"); switch (curi->size) { case sz_byte: @@ -1667,8 +1510,8 @@ static void gen_opcode (unsigned long int opcode) break; case i_ASR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1680,7 +1523,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); - printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size)); + printf ("\t\tval = %s & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size)); printf ("\t\tSET_CFLG (sign);\n"); duplicate_carry (); if (source_is_imm1_8 (curi)) @@ -1691,17 +1534,17 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tSET_CFLG (val & 1);\n"); duplicate_carry (); printf ("\t\tval >>= 1;\n"); - printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n", + printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size), bit_size (curi->size)); printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ASL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1733,11 +1576,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_LSR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1762,11 +1605,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval >>= 1;\n"); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_LSL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1792,11 +1635,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1819,11 +1662,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG (val & 1);\n"); printf ("}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1846,11 +1689,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROXL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1876,11 +1719,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} }\n"); printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROXR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1909,10 +1752,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} }\n"); printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ASRW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1926,10 +1769,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ASLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1946,10 +1789,10 @@ static void gen_opcode (unsigned long int opcode) duplicate_carry (); printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_LSRW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1962,10 +1805,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_LSLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1978,10 +1821,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ROLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1994,10 +1837,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= 1;\n"); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_RORW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2010,10 +1853,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= %s;\n", cmask (curi->size)); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ROXLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2027,10 +1870,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ROXRW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2044,129 +1887,103 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_MOVEC2: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (!m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_MOVE2C: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (!m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_CAS: { int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tint ru = (src >> 6) & 7;\n"); printf ("\tint rc = src & 7;\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst"); - sync_m68k_pc (); printf ("\tif (GET_ZFLG)"); old_brace_level = n_braces; start_brace (); - genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); pop_braces (old_brace_level); printf ("else"); start_brace (); - switch (curi->size) { - case sz_byte: - printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n"); - break; - case sz_word: - printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n"); - break; - default: - printf ("\tm68k_dreg(regs, rc) = dst;\n"); - break; - } + printf ("m68k_dreg(regs, rc) = dst;\n"); pop_braces (old_brace_level); } break; case i_CAS2: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n"); printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n"); if (curi->size == sz_word) { int old_brace_level = n_braces; - printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); - printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); printf ("\tif (GET_ZFLG) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); printf ("\tif (GET_ZFLG) {\n"); printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_word(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG) {\n"); - printf ("\tm68k_dreg(regs, rc2) = (m68k_dreg(regs, rc2) & ~0xffff) | (dst2 & 0xffff);\n"); - printf ("\tm68k_dreg(regs, rc1) = (m68k_dreg(regs, rc1) & ~0xffff) | (dst1 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); printf ("\t}\n"); } else { int old_brace_level = n_braces; - printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); - printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); printf ("\tif (GET_ZFLG) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); printf ("\tif (GET_ZFLG) {\n"); printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_long(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG) {\n"); - printf ("\tm68k_dreg(regs, rc2) = dst2;\n"); - printf ("\tm68k_dreg(regs, rc1) = dst1;\n"); + printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n"); + printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n"); printf ("\t}\n"); } break; - case i_MOVES: + case i_MOVES: /* ignore DFC and SFC because we have no MMU */ { - int old_brace_level; - - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - start_brace(); - printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */ - { - int old_m68k_pc_offset = m68k_pc_offset; - /* use DFC */ - old_brace_level = n_braces; - start_brace (); - printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_DFC); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC); - pop_braces (old_brace_level); - m68k_pc_offset = old_m68k_pc_offset; - } - printf ("else"); /* from ea to reg */ - { - /* use SFC */ - start_brace (); - genamode (curi->dmode, "dstreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_SFC); - printf ("\tif (extra & 0x8000) {\n"); /* address/data */ - switch (curi->size) { - case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; - case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; - default: abort (); - } - printf ("\t} else {\n"); - genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG); - printf ("\t}\n"); - sync_m68k_pc(); - pop_braces (old_brace_level); - } + int old_brace_level; + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + printf ("\tif (extra & 0x800)\n"); + old_brace_level = n_braces; + start_brace (); + printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + pop_braces (old_brace_level); + printf ("else"); + start_brace (); + genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0); + printf ("\tif (extra & 0x8000) {\n"); + switch (curi->size) { + case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; + case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; + default: abort (); + } + printf ("\t} else {\n"); + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, ""); + printf ("\t}\n"); + pop_braces (old_brace_level); } break; case i_BKPT: /* only needed for hardware emulators */ @@ -2182,23 +1999,23 @@ static void gen_opcode (unsigned long int opcode) printf ("\top_illg(opcode);\n"); break; case i_TRAPcc: - printf ("\tuaecptr oldpc = m68k_getpc();\n"); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - sync_m68k_pc (); - printf ("\tif (cctrue(%d)) { Exception(7,oldpc); goto %s; }\n", curi->cc, endlabelstr); + genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); + printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr); need_endlabel = 1; break; case i_DIVL: + sync_m68k_pc (); + start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); sync_m68k_pc (); printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n"); break; case i_MULL: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); sync_m68k_pc (); printf ("\tm68k_mull(opcode, dst, extra);\n"); break; @@ -2210,37 +2027,34 @@ static void gen_opcode (unsigned long int opcode) case i_BFFFO: case i_BFSET: case i_BFINS: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0); start_brace (); - printf ("\tuae_u32 bdata[2];"); printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n"); printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n"); if (curi->dmode == Dreg) { - printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg);\n"); - printf ("\toffset &= 0x1f;\n"); - printf ("\ttmp = (tmp << offset) | (tmp >> (32 - offset));\n"); - printf ("\tbdata[0] = tmp & ((1 << (32 - width)) - 1);\n"); + printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n"); } else { - printf ("\tuae_u32 tmp;\n"); - printf ("\tdsta += offset >> 3;\n"); - printf ("\ttmp = get_bitfield(dsta, bdata, offset, width);\n"); + printf ("\tuae_u32 tmp,bf0,bf1;\n"); + printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n"); + printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n"); + printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n"); } - printf ("\tSET_NFLG_ALWAYS (((uae_s32)tmp) < 0 ? 1 : 0);\n"); - if (curi->mnemo == i_BFEXTS) - printf ("\ttmp = (uae_s32)tmp >> (32 - width);\n"); - else - printf ("\ttmp >>= (32 - width);\n"); + printf ("\ttmp >>= (32 - width);\n"); + printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width-1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n"); switch (curi->mnemo) { case i_BFTST: break; case i_BFEXTU: - case i_BFEXTS: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCHG: - printf ("\ttmp = tmp ^ (0xffffffffu >> (32 - width));\n"); + printf ("\ttmp = ~tmp;\n"); + break; + case i_BFEXTS: + printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n"); + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCLR: printf ("\ttmp = 0;\n"); @@ -2251,11 +2065,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n"); break; case i_BFSET: - printf ("\ttmp = 0xffffffffu >> (32 - width);\n"); + printf ("\ttmp = 0xffffffff;\n"); break; case i_BFINS: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n"); - printf ("\ttmp = tmp & (0xffffffffu >> (32 - width));\n"); printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width - 1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0);\n"); break; @@ -2265,12 +2078,26 @@ static void gen_opcode (unsigned long int opcode) if (curi->mnemo == i_BFCHG || curi->mnemo == i_BFCLR || curi->mnemo == i_BFSET - || curi->mnemo == i_BFINS) { + || curi->mnemo == i_BFINS) + { + printf ("\ttmp <<= (32 - width);\n"); if (curi->dmode == Dreg) { - printf ("\ttmp = bdata[0] | (tmp << (32 - width));\n"); - printf ("\tm68k_dreg(regs, dstreg) = (tmp >> offset) | (tmp << (32 - offset));\n"); + printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n"); + printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n"); + printf ("\t\t(tmp >> (offset & 0x1f)) |\n"); + printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n"); + printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n"); } else { - printf ("\tput_bitfield(dsta, bdata, tmp, offset, width);\n"); + printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n"); + printf ("\t\t(tmp >> (offset & 7)) |\n"); + printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n"); + printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n"); + printf ("\tput_long(dsta,bf0 );\n"); + printf ("\tif (((offset & 7) + width) > 32) {\n"); + printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n"); + printf ("\t\t\t(tmp << (8 - (offset & 7)));\n"); + printf ("\t\tput_byte(dsta+4,bf1);\n"); + printf ("\t}\n"); } } break; @@ -2280,11 +2107,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); - printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg) - 2 * areg_byteinc[srcreg]) << 8)) + %s;\n", gen_nextiword ()); - printf ("\tm68k_areg(regs, srcreg) -= 2;\n"); + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); + printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ()); printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); - gen_set_fault_pc (); printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n"); } break; @@ -2295,57 +2122,57 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); - printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ()); printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tm68k_areg(regs, dstreg) -= 2;\n"); - gen_set_fault_pc (); - printf ("\tput_word(m68k_areg(regs, dstreg), val);\n"); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); + printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ()); + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); + printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n"); + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); + printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n"); } break; case i_TAS: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genflags (flag_logical, curi->size, "src", "", ""); printf ("\tsrc |= 0x80;\n"); - genastore ("src", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("src", curi->smode, "srcreg", curi->size, "src"); break; case i_FPP: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); printf ("\tfpuop_arithmetic(opcode, extra);\n"); break; case i_FDBcc: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); printf ("\tfpuop_dbcc(opcode, extra);\n"); break; case i_FScc: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_scc(opcode, extra);\n"); + printf ("\tfpuop_scc(opcode,extra);\n"); break; case i_FTRAPcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); - printf ("\tuae_u16 extra = %s;\n", gen_nextiword()); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_trapcc(opcode, oldpc, extra);\n"); + printf ("\tfpuop_trapcc(opcode,oldpc);\n"); break; case i_FBcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr pc = m68k_getpc();\n"); - genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_bcc(opcode, pc, extra);\n"); + printf ("\tfpuop_bcc(opcode,pc,extra);\n"); break; case i_FSAVE: sync_m68k_pc (); @@ -2358,104 +2185,67 @@ static void gen_opcode (unsigned long int opcode) printf ("\tfpuop_restore(opcode);\n"); break; case i_CINVL: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(31);\n"); - printf("#endif\n"); - break; case i_CINVP: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(32);\n"); - printf("#endif\n"); - break; case i_CINVA: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(33);\n"); - printf("#endif\n"); + /* gb-- srcreg now contains the cache field */ + printf ("\tif (srcreg&0x2)\n"); + printf ("\t\tflush_icache(%d);\n", 30 + ((opcode >> 3) & 3)); break; case i_CPUSHL: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(41);\n"); - printf("#endif\n"); - break; case i_CPUSHP: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(42);\n"); - printf("#endif\n"); - break; case i_CPUSHA: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(43);\n"); - printf("#endif\n"); + /* gb-- srcreg now contains the cache field */ + printf ("\tif (srcreg&0x2)\n"); + printf ("\t\tflush_icache(%d);\n", 40 + ((opcode >> 3) & 3)); break; case i_MOVE16: - if ((opcode & 0xfff8) == 0xf620) { - /* MOVE16 (Ax)+,(Ay)+ */ - printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); - printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); - printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); - printf ("\tput_long(memd, get_long(mems));\n"); - printf ("\tput_long(memd+4, get_long(mems+4));\n"); - printf ("\tput_long(memd+8, get_long(mems+8));\n"); - printf ("\tput_long(memd+12, get_long(mems+12));\n"); - printf ("\tif (srcreg != dstreg)\n"); - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } else { - /* Other variants */ - genamode (curi->smode, "srcreg", curi->size, "mems", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "memd", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); - printf ("\tmemsa &= ~15;\n"); - printf ("\tmemda &= ~15;\n"); - printf ("\tput_long(memda, get_long(memsa));\n"); - printf ("\tput_long(memda+4, get_long(memsa+4));\n"); - printf ("\tput_long(memda+8, get_long(memsa+8));\n"); - printf ("\tput_long(memda+12, get_long(memsa+12));\n"); - if ((opcode & 0xfff8) == 0xf600) - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - else if ((opcode & 0xfff8) == 0xf608) - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } - break; + if ((opcode & 0xfff8) == 0xf620) { + /* MOVE16 (Ax)+,(Ay)+ */ + printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); + printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); + printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); + printf ("\tput_long(memd, get_long(mems));\n"); + printf ("\tput_long(memd+4, get_long(mems+4));\n"); + printf ("\tput_long(memd+8, get_long(mems+8));\n"); + printf ("\tput_long(memd+12, get_long(mems+12));\n"); + printf ("\tif (srcreg != dstreg)\n"); + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } + else { + /* Other variants */ + genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2); + genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2); + printf ("\tmemsa &= ~15;\n"); + printf ("\tmemda &= ~15;\n"); + printf ("\tput_long(memda, get_long(memsa));\n"); + printf ("\tput_long(memda+4, get_long(memsa+4));\n"); + printf ("\tput_long(memda+8, get_long(memsa+8));\n"); + printf ("\tput_long(memda+12, get_long(memsa+12));\n"); + if ((opcode & 0xfff8) == 0xf600) + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + else if ((opcode & 0xfff8) == 0xf608) + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } + break; case i_MMUOP: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); printf ("\tmmu_op(opcode,extra);\n"); break; - - case i_EMULOP_RETURN: + + case i_EMULOP_RETURN: printf ("\tm68k_emulop_return();\n"); m68k_pc_offset = 0; break; - case i_EMULOP: + case i_EMULOP: printf ("\n"); swap_opcode (); printf ("\tm68k_emulop(opcode);\n"); break; - - case i_NATFEAT_ID: - printf ("\n"); - printf ("\tm68k_natfeat_id();\n"); - break; - - case i_NATFEAT_CALL: - printf ("\n"); - printf ("\tm68k_natfeat_call();\n"); - break; - + default: abort (); break; @@ -2467,92 +2257,73 @@ static void gen_opcode (unsigned long int opcode) static void generate_includes (FILE * f) { fprintf (f, "#include \"sysdeps.h\"\n"); + fprintf (f, "#include \"m68k.h\"\n"); fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); - fprintf (f, "#ifdef USE_JIT\n"); fprintf (f, "#include \"compiler/compemu.h\"\n"); - fprintf (f, "#endif\n"); fprintf (f, "#include \"fpu/fpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); - fprintf (f, "#include \"cpu_emulation.h\"\n"); - fprintf (f, "#include \"debug.h\"\n"); - - fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); - fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); - fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); - fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); - fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); - fprintf (f, "#ifdef NOFLAGS\n"); - fprintf (f, "# include \"noflags.h\"\n"); - fprintf (f, "#endif\n"); + fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); + fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); + fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); + fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); + fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); + + fprintf (f, "#ifdef NOFLAGS\n"); + fprintf (f, "# include \"noflags.h\"\n"); + fprintf (f, "#endif\n"); } static int postfix; -struct gencputbl { - char handler[80]; - uae_u16 specific; - uae_u16 opcode; - int namei; -}; -struct gencputbl cpustbl[65536]; -static int n_cpustbl; - static void generate_one_opcode (int rp) { - int i; uae_u16 smsk, dmsk; - int opcode = opcode_map[rp]; - int have_realopcode = 0; - - if (table68k[opcode].mnemo == i_ILLG - || table68k[opcode].clev > cpu_level) - return; + long int opcode = opcode_map[rp]; + const char *opcode_str; - for (i = 0; lookuptab[i].name[0]; i++) { - if (table68k[opcode].mnemo == lookuptab[i].mnemo) - break; - } + if (table68k[opcode].mnemo == i_ILLG + || table68k[opcode].clev > (unsigned)cpu_level) + return; if (table68k[opcode].handler != -1) return; - if (opcode_next_clev[rp] != cpu_level) { - sprintf(cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, opcode_last_postfix[rp]); - cpustbl[n_cpustbl].specific = 0; - cpustbl[n_cpustbl].opcode = opcode; - cpustbl[n_cpustbl].namei = i; - fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, lookuptab[i].name); - n_cpustbl++; - return; - } + opcode_str = get_instruction_string (opcode); + if (opcode_next_clev[rp] != cpu_level) { if (table68k[opcode].flagdead == 0) /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ - sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC_FF(op_%x_%d)", opcode, postfix); + fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], + opcode, opcode_str); else - sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, postfix); - cpustbl[n_cpustbl].specific = 0; - cpustbl[n_cpustbl].opcode = opcode; - cpustbl[n_cpustbl].namei = i; - fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, lookuptab[i].name); - n_cpustbl++; + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], + opcode, opcode_str); + return; + } + + if (table68k[opcode].flagdead == 0) + /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ + fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); + else + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); - fprintf (headerfile, "extern cpuop_func op_%x_%d_nf;\n", opcode, postfix); - fprintf (headerfile, "extern cpuop_func op_%x_%d_ff;\n", opcode, postfix); - - printf ("void REGPARAM2 CPUFUNC(op_%x_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); - printf ("\tcpuop_begin();\n"); + fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix); + fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix); + /* gb-- The "nf" variant for an instruction that doesn't set the condition codes at all is the same as the "ff" variant, so we don't need the "nf" variant to be compiled since it is mapped to the "ff" variant in the smalltbl. */ - if (table68k[opcode].flagdead == 0) + if (table68k[opcode].flagdead == 0) printf ("#ifndef NOFLAGS\n"); + printf ("void REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, opcode_str); + printf ("\tcpuop_begin();\n"); + switch (table68k[opcode].stype) { case 0: smsk = 7; break; case 1: smsk = 255; break; @@ -2560,8 +2331,8 @@ static void generate_one_opcode (int rp) case 3: smsk = 7; break; case 4: smsk = 7; break; case 5: smsk = 63; break; - case 6: smsk = 255; break; - case 7: smsk = 3; break; + case 6: smsk = 255; break; + case 7: smsk = 3; break; default: abort (); } dmsk = 7; @@ -2592,17 +2363,38 @@ static void generate_one_opcode (int rp) if (pos < 8 && (smsk >> (8 - pos)) != 0) abort (); #endif - real_opcode(&have_realopcode); - if (pos) - sprintf (source, "((real_opcode >> %d) & %d)", pos, smsk); + printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); + + if (pos < 8 && (smsk >> (8 - pos)) != 0) + sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk); else - sprintf (source, "(real_opcode & %d)", smsk); + sprintf (source, "(opcode & %d)", smsk); + if (table68k[opcode].stype == 3) printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); else if (table68k[opcode].stype == 1) printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); else printf ("\tuae_u32 srcreg = %s;\n", source); + + printf ("#else\n"); + + if (pos) + sprintf (source, "((opcode >> %d) & %d)", pos, smsk); + else + sprintf (source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + printf ("\tuae_u32 srcreg = %s;\n", source); + + printf ("#endif\n"); } } if (table68k[opcode].duse @@ -2622,13 +2414,27 @@ static void generate_one_opcode (int rp) /* Check that we can do the little endian optimization safely. */ if (pos < 8 && (dmsk >> (8 - pos)) != 0) abort (); -#endif - real_opcode(&have_realopcode); +#endif + printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); + + if (pos < 8 && (dmsk >> (8 - pos)) != 0) + printf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", + pos ^ 8, dmsk); + else + printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + printf ("#else\n"); + if (pos) - printf ("\tuae_u32 dstreg = (real_opcode >> %d) & %d;\n", + printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", pos, dmsk); else - printf ("\tuae_u32 dstreg = real_opcode & %d;\n", dmsk); + printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + printf ("#endif\n"); } } need_endlabel = 0; @@ -2637,10 +2443,10 @@ static void generate_one_opcode (int rp) gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); - if (table68k[opcode].flagdead == 0) - printf ("\n#endif\n"); - printf ("\tcpuop_end();\n"); + printf ("\tcpuop_end();\n"); printf ("}\n"); + if (table68k[opcode].flagdead == 0) + printf ("\n#endif\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; } @@ -2651,18 +2457,36 @@ static void generate_func (void) using_prefetch = 0; using_exception_3 = 0; - - for (i = 0; i < 1; i++) { +#if !USE_PREFETCH_BUFFER + /* gb-- No need for a prefetch buffer, nor exception 3 handling */ + /* Anyway, Basilisk2 does not use the op_smalltbl_5 table... */ + for (i = 0; i <= 4; i++) { +#else + for (i = 0; i < 6; i++) { +#endif cpu_level = 4 - i; + if (i == 5) { + cpu_level = 0; + using_prefetch = 1; + using_exception_3 = 1; + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = 0; + } postfix = i; - fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); + fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); + + /* Disable spurious warnings. */ + printf ("\n" + "#ifdef _MSC_VER\n" + "#pragma warning(disable:4102) /* unreferenced label */\n" + "#endif\n"); /* sam: this is for people with low memory (eg. me :)) */ printf ("\n" - "#if !defined(PART_1) && !defined(PART_2) && " - "!defined(PART_3) && !defined(PART_4) && " - "!defined(PART_5) && !defined(PART_6) && " - "!defined(PART_7) && !defined(PART_8)" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" "\n" "#define PART_1 1\n" "#define PART_2 1\n" @@ -2673,8 +2497,8 @@ static void generate_func (void) "#define PART_7 1\n" "#define PART_8 1\n" "#endif\n\n"); + rp = 0; - n_cpustbl = 0; for(j=1;j<=8;++j) { int k = (j*nr_cpuop_funcs)/8; printf ("#ifdef PART_%d\n",j); @@ -2682,89 +2506,14 @@ static void generate_func (void) generate_one_opcode (rp); printf ("#endif\n\n"); } + fprintf (stblfile, "{ 0, 0, 0 }};\n"); } } -static struct { - const char *handler; - const char *name; -} cpufunctbl[65536]; -static char const op_illg_1[] = "op_illg_1"; -static char const illegal[] = "ILLEGAL"; - -static void generate_functbl (void) -{ - int i; - unsigned int opcode; - int cpu_level = 4; - struct gencputbl *tbl = cpustbl; - - for (opcode = 0; opcode < 65536; opcode++) - { - cpufunctbl[opcode].handler = op_illg_1; - cpufunctbl[opcode].name = illegal; - } - for (i = 0; i < n_cpustbl; i++) - { - if (! tbl[i].specific) - { - cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; - cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; - } - } - for (opcode = 0; opcode < 65536; opcode++) - { - const char *f; - - if (table68k[opcode].mnemo == i_ILLG || (unsigned)table68k[opcode].clev > (unsigned)cpu_level) - continue; - - if (table68k[opcode].handler != -1) - { - f = cpufunctbl[table68k[opcode].handler].handler; - if (f == op_illg_1) - abort(); - cpufunctbl[opcode].handler = f; - cpufunctbl[opcode].name = cpufunctbl[table68k[opcode].handler].name; - } - } - for (i = 0; i < n_cpustbl; i++) - { - if (tbl[i].specific) - { - cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; - cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; - } - } - - fprintf(functblfile, "\n"); - fprintf(functblfile, "cpuop_func *cpufunctbl[65536] = {\n"); - fprintf(functblfile, "#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU)\n"); - for (opcode = 0; opcode < 65536; opcode++) - { - fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[opcode].handler, opcode < 65535 ? "," : "", cpufunctbl[opcode].name); - } - fprintf(functblfile, "#else\n"); - for (opcode = 0; opcode < 65536; opcode++) - { - unsigned int map = do_byteswap_16(opcode); - fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[map].handler, opcode < 65535 ? "," : "", cpufunctbl[map].name); - } - fprintf(functblfile, "#endif\n"); - fprintf(functblfile, "};\n"); -} - -#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) -void cygwin_mingw_abort() -{ -#undef abort - abort(); -} -#endif - -int main () +int main (int argc, char **argv) { + FILE *out; read_table68k (); do_merges (); @@ -2778,28 +2527,32 @@ int main () * cputbl.h that way), but cpuopti can't cope. That could be fixed, but * I don't dare to touch the 68k version. */ - if ((headerfile = fopen ("cputbl.h", "wb")) == NULL) - abort(); - if ((stblfile = fopen ("cpustbl.cpp", "wb")) == NULL) - abort(); - if ((functblfile = fopen ("cpufunctbl.cpp", "wb")) == NULL) - abort(); - if (freopen ("cpuemu.cpp", "wb", stdout) == NULL) - abort(); + headerfile = fopen ("cputbl.h", "w"); + stblfile = fopen ("cpustbl.cpp", "w"); + out = freopen ("cpuemu.cpp", "w", stdout); generate_includes (stdout); - fprintf(stdout, "#ifdef HAVE_CFLAG_NO_REDZONE\n"); - fprintf(stdout, "#ifndef NOFLAGS\n"); - fprintf(stdout, "#pragma GCC option \"-mno-red-zone\"\n"); - fprintf(stdout, "#endif\n"); - fprintf(stdout, "#endif\n"); generate_includes (stblfile); - generate_includes (functblfile); + generate_func (); - generate_functbl (); + free (table68k); - fclose(headerfile); - fclose(stblfile); - fclose(functblfile); + fclose (headerfile); + fclose (stblfile); + fflush (out); + + /* For build systems (IDEs mainly) that don't make it easy to compile the + * same file twice with different settings. */ + stblfile = fopen ("cpustbl_nf.cpp", "w"); + out = freopen ("cpuemu_nf.cpp", "w", stdout); + + fprintf (stblfile, "#define NOFLAGS\n"); + fprintf (stblfile, "#include \"cpustbl.cpp\"\n"); + fclose (stblfile); + + printf ("#define NOFLAGS\n"); + printf ("#include \"cpuemu.cpp\"\n"); + fflush (out); + return 0; } diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index dc79136b..f329cb3e 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -1,44 +1,31 @@ -/* - * m68k.h - machine dependent bits - * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) +/* + * UAE - The Un*x Amiga Emulator * - * Inspired by Christian Bauer's Basilisk II + * MC68000 emulation - machine dependent bits * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * Copyright 1996 Bernd Schmidt * - * ARAnyM is free software; you can redistribute it and/or modify + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * ARAnyM is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - machine dependent bits - * - * Copyright 1996 Bernd Schmidt - * - */ #ifndef M68K_FLAGS_H #define M68K_FLAGS_H #ifdef OPTIMIZED_FLAGS -#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY)) - -# include +#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) || defined(MSVC_INTRINSICS) #ifndef SAHF_SETO_PROFITABLE @@ -46,13 +33,8 @@ unsigned long hereunder is either 64-bit or 32-bit wide depending on the target. */ struct flag_struct { -#if defined(CPU_x86_64) - uint64 cznv; - uint64 x; -#else - uint32 cznv; - uint32 x; -#endif + unsigned long cznv; + unsigned long x; }; #define FLAGVAL_Z 0x40 @@ -77,9 +59,9 @@ struct flag_struct { #define COPY_CARRY (regflags.x = regflags.cznv) -extern struct flag_struct regflags __asm__ ("regflags"); +extern struct flag_struct regflags ASM_SYM ("regflags"); -static inline int cctrue(int cc) +static __inline__ int cctrue(int cc) { uae_u32 cznv = regflags.cznv; switch(cc){ @@ -111,25 +93,25 @@ static inline int cctrue(int cc) __asm__ __volatile__ ("andl %1,%1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv) : "r" (v) : "memory", "cc") + : "=r" (regflags.cznv) : "r" (v) : "cc") #define optflag_testw(v) \ __asm__ __volatile__ ("andw %w1,%w1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv) : "r" (v) : "memory", "cc") + : "=r" (regflags.cznv) : "r" (v) : "cc") #define optflag_testb(v) \ __asm__ __volatile__ ("andb %b1,%b1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv) : "q" (v) : "memory", "cc") + : "=r" (regflags.cznv) : "q" (v) : "cc") #define optflag_addl(v, s, d) do { \ __asm__ __volatile__ ("addl %k2,%k1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) @@ -137,7 +119,7 @@ static inline int cctrue(int cc) __asm__ __volatile__ ("addw %w2,%w1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) @@ -153,7 +135,7 @@ static inline int cctrue(int cc) __asm__ __volatile__ ("subl %k2,%k1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) @@ -161,7 +143,7 @@ static inline int cctrue(int cc) __asm__ __volatile__ ("subw %w2,%w1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) @@ -169,7 +151,7 @@ static inline int cctrue(int cc) __asm__ __volatile__ ("subb %b2,%b1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "memory", "cc"); \ + : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ COPY_CARRY; \ } while (0) @@ -177,19 +159,19 @@ static inline int cctrue(int cc) __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc") + : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") #define optflag_cmpw(s, d) \ __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc") + : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") #define optflag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=rm" (regflags.cznv) : "qmi" (s), "q" (d) : "memory", "cc") + : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc") #else @@ -220,9 +202,9 @@ struct flag_struct { #define COPY_CARRY (regflags.x = (regflags.cznv)>>8) -extern struct flag_struct regflags __asm__ ("regflags"); +extern struct flag_struct regflags ASM_SYM("regflags"); -static inline int cctrue(int cc) +static __inline__ int cctrue(int cc) { uae_u32 cznv = regflags.cznv; switch(cc){ @@ -252,7 +234,7 @@ static inline int cctrue(int cc) } /* Manually emit LAHF instruction so that 64-bit assemblers can grok it */ -#if defined CPU_x86_64 && defined __GNUC__ +#if defined __x86_64__ && defined __GNUC__ #define ASM_LAHF ".byte 0x9f" #else #define ASM_LAHF "lahf" @@ -358,7 +340,7 @@ static inline int cctrue(int cc) "seto %%al\n\t" \ "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ - : : "rmi" (s), "r" (d) : "%eax","cc","memory") + : : "rmi" (s), "r" (d) : "%eax","cc","memory"); #define optflag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ @@ -370,290 +352,7 @@ static inline int cctrue(int cc) #endif -#elif defined(CPU_arm) && defined(ARM_ASSEMBLY) - -struct flag_struct { - uae_u32 nzcv; - uae_u32 x; -}; - -#define FLAGVAL_Q 0x08000000 -#define FLAGVAL_V 0x10000000 -#define FLAGVAL_C 0x20000000 -#define FLAGVAL_Z 0x40000000 -#define FLAGVAL_N 0x80000000 - -#define SET_NFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x80000000) | (((y) & 1) << 31)) -#define SET_ZFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x40000000) | (((y) & 1) << 30)) -#define SET_CFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x20000000) | (((y) & 1) << 29)) -#define SET_VFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x10000000) | (((y) & 1) << 28)) -#define SET_XFLG(y) (regflags.x = (y)) - -#define GET_NFLG ((regflags.nzcv >> 31) & 1) -#define GET_ZFLG ((regflags.nzcv >> 30) & 1) -#define GET_CFLG ((regflags.nzcv >> 29) & 1) -#define GET_VFLG ((regflags.nzcv >> 28) & 1) -#define GET_XFLG (regflags.x & 1) - -#define CLEAR_CZNV (regflags.nzcv = 0) -#define GET_CZNV (regflags.nzcv) -#define IOR_CZNV(X) (regflags.nzcv |= (X)) -#define SET_CZNV(X) (regflags.nzcv = (X)) - -#define COPY_CARRY (regflags.x = (regflags.nzcv)>>29) - -extern struct flag_struct regflags __asm__ ("regflags"); - -static inline int cctrue(int cc) -{ - unsigned int nzcv = regflags.nzcv; - switch(cc){ - case 0: return 1; /* T */ - case 1: return 0; /* F */ - case 2: return (nzcv & 0x60000000) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ - case 3: return (nzcv & 0x60000000) != 0; /* GET_CFLG || GET_ZFLG; LS */ - case 4: return (nzcv & 0x20000000) == 0; /* !GET_CFLG; CC */ - case 5: return (nzcv & 0x20000000) != 0; /* GET_CFLG; CS */ - case 6: return (nzcv & 0x40000000) == 0; /* !GET_ZFLG; NE */ - case 7: return (nzcv & 0x40000000) != 0; /* GET_ZFLG; EQ */ - case 8: return (nzcv & 0x10000000) == 0; /* !GET_VFLG; VC */ - case 9: return (nzcv & 0x10000000) != 0; /* GET_VFLG; VS */ - case 10:return (nzcv & 0x80000000) == 0; /* !GET_NFLG; PL */ - case 11:return (nzcv & 0x80000000) != 0; /* GET_NFLG; MI */ - case 12:return (((nzcv << 3) ^ nzcv) & 0x80000000) == 0; /* GET_NFLG == GET_VFLG; GE */ - case 13:return (((nzcv << 3) ^ nzcv) & 0x80000000) != 0; /* GET_NFLG != GET_VFLG; LT */ - case 14: - nzcv &= 0xd0000000; - return (((nzcv << 3) ^ nzcv) & 0xc0000000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ - case 15: - nzcv &= 0xd0000000; - return (((nzcv << 3) ^ nzcv) & 0xc0000000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ - } - return 0; -} - -#define optflag_testl(v) do {\ - __asm__ __volatile__ ("tst %[rv],%[rv]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "bic %[nzcv],#0x30000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rv] "r" (v) \ - : "cc"); \ - } while(0) - -#define optflag_addl(v, s, d) do { \ - __asm__ __volatile__ ("adds %[rv],%[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_subl(v, s, d) do { \ - __asm__ __volatile__ ("subs %[rv],%[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_cmpl(s, d) do { \ - __asm__ __volatile__ ("cmp %[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rs] "ri" (s), [rd] "0" (d) \ - : "cc"); \ - } while(0) - -#if defined(ARMV6_ASSEMBLY) - -// #pragma message "ARM/v6 Assembly optimized flags" - -#define optflag_testw(v) do { \ - __asm__ __volatile__ ("sxth %[rv],%[rv]\n\t" \ - "tst %[rv],%[rv]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "bic %[nzcv],#0x30000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rv] "0" (v) \ - : "cc"); \ - }while(0) - -#define optflag_testb(v) do {\ - __asm__ __volatile__ ("sxtb %[rv],%[rv]\n\t" \ - "tst %[rv],%[rv]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "bic %[nzcv],#0x30000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rv] "0" (v) \ - : "cc"); \ - }while(0) - -#define optflag_addw(v, s, d) do { \ - __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ - "sxth %[rs],%[rs]\n\t" \ - "adds %[rd],%[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_addb(v, s, d) do { \ - __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ - "sxtb %[rs],%[rs]\n\t" \ - "adds %[rd],%[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_subw(v, s, d) do { \ - __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ - "sxth %[rs],%[rs]\n\t" \ - "subs %[rd],%[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_subb(v, s, d) do { \ - __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ - "sxtb %[rs],%[rs]\n\t" \ - "subs %[rd],%[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_cmpw(s, d) do { \ - __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ - "sxth %[rs],%[rs]\n\t" \ - "cmp %[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rs] "ri" (s), [rd] "0" (d) \ - : "cc"); \ - } while(0) - -#define optflag_cmpb(s, d) do { \ - __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ - "sxtb %[rs],%[rs]\n\t" \ - "cmp %[rd],%[rs]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rs] "ri" (s), [rd] "0" (d) \ - : "cc"); \ - } while(0) - -#else - -// #pragma message "ARM/generic Assembly optimized flags" - -#define optflag_testw(v) do { \ - __asm__ __volatile__ ("lsl %[rv],%[rv],#16\n\t" \ - "tst %[rv],%[rv]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "bic %[nzcv],#0x30000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rv] "0" (v) \ - : "cc"); \ - }while(0) - -#define optflag_testb(v) do {\ - __asm__ __volatile__ ("lsl %[rv],%[rv],#24\n\t" \ - "tst %[rv],%[rv]\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "bic %[nzcv],#0x30000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rv] "0" (v) \ - : "cc"); \ - }while(0) - -#define optflag_addw(v, s, d) do { \ - __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ - "adds %[rd],%[rd],%[rs],lsl #16\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "lsr %[rv],%[rd],#16\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_addb(v, s, d) do { \ - __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ - "adds %[rd],%[rd],%[rs],lsl #24\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "lsr %[rv],%[rd],#24\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_subw(v, s, d) do { \ - __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ - "subs %[rd],%[rd],%[rs],lsl #16\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - "lsr %[rv],%[rd],#16\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_subb(v, s, d) do { \ - __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ - "subs %[rd],%[rd],%[rs],lsl #24\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - "lsr %[rv],%[rd],#24\n\t" \ - : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ - : [rs] "ri" (s), [rd] "1" (d) \ - : "cc"); \ - COPY_CARRY; \ - } while(0) - -#define optflag_cmpw(s, d) do { \ - __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ - "cmp %[rd],%[rs],lsl #16\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rs] "ri" (s), [rd] "0" (d) \ - : "cc"); \ - } while(0) - -#define optflag_cmpb(s, d) do { \ - __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ - "cmp %[rd],%[rs],lsl #24\n\t" \ - "mrs %[nzcv],cpsr\n\t" \ - "eor %[nzcv],#0x20000000\n\t" \ - : [nzcv] "=r" (regflags.nzcv) \ - : [rs] "ri" (s), [rd] "0" (d) \ - : "cc"); \ - } while(0) - -#endif - -#elif defined(CPU_sparc) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)) +#elif defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) struct flag_struct { unsigned char nzvc; @@ -684,7 +383,7 @@ extern struct flag_struct regflags; #define COPY_CARRY (regflags.x = regflags.nzvc) -static inline int cctrue(int cc) +static __inline__ int cctrue(int cc) { uae_u32 nzvc = regflags.nzvc; switch(cc){ @@ -1346,7 +1045,7 @@ extern struct flag_struct regflags; #define COPY_CARRY (SET_XFLG (GET_CFLG)) -static inline int cctrue(const int cc) +static __inline__ int cctrue(const int cc) { switch(cc){ case 0: return 1; /* T */ diff --git a/BasiliskII/src/uae_cpu/memory-uae.h b/BasiliskII/src/uae_cpu/memory-uae.h deleted file mode 100644 index c93aeb37..00000000 --- a/BasiliskII/src/uae_cpu/memory-uae.h +++ /dev/null @@ -1,606 +0,0 @@ -/* - * memory.h - memory management - * - * Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II - * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - /* - * UAE - The Un*x Amiga Emulator - * - * memory management - * - * Copyright 1995 Bernd Schmidt - */ - -#ifndef UAE_MEMORY_H -#define UAE_MEMORY_H - -#include "sysdeps.h" -#include "string.h" -#include "hardware.h" -#include "parameters.h" -#include "registers.h" -#include "cpummu.h" -#include "readcpu.h" - -# include - -// newcpu.h -extern void Exception (int, uaecptr); -#ifdef EXCEPTIONS_VIA_LONGJMP - extern JMP_BUF excep_env; - #define SAVE_EXCEPTION \ - JMP_BUF excep_env_old; \ - memcpy(excep_env_old, excep_env, sizeof(JMP_BUF)) - #define RESTORE_EXCEPTION \ - memcpy(excep_env, excep_env_old, sizeof(JMP_BUF)) - #define TRY(var) int var = SETJMP(excep_env); if (!var) - #define CATCH(var) else - #define THROW(n) LONGJMP(excep_env, n) - #define THROW_AGAIN(var) LONGJMP(excep_env, var) - #define VOLATILE volatile -#else - struct m68k_exception { - int prb; - m68k_exception (int exc) : prb (exc) {} - operator int() { return prb; } - }; - #define SAVE_EXCEPTION - #define RESTORE_EXCEPTION - #define TRY(var) try - #define CATCH(var) catch(m68k_exception var) - #define THROW(n) throw m68k_exception(n) - #define THROW_AGAIN(var) throw - #define VOLATILE -#endif /* EXCEPTIONS_VIA_LONGJMP */ -extern int in_exception_2; - -#define STRAM_END 0x0e00000UL // should be replaced by global ROMBase as soon as ROMBase will be a constant -#define ROM_END 0x0e80000UL // should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes -#define FastRAM_BEGIN 0x1000000UL // should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant -#ifdef FixedSizeFastRAM -#define FastRAM_SIZE (FixedSizeFastRAM * 1024 * 1024) -#else -#define FastRAM_SIZE FastRAMSize -#endif - -#ifdef FIXED_VIDEORAM -#define ARANYMVRAMSTART 0xf0000000UL -#endif - -#define ARANYMVRAMSIZE 0x00100000 // should be a variable to protect VGA card offscreen memory - -#ifdef FIXED_VIDEORAM -extern uintptr VMEMBaseDiff; -#else -extern uae_u32 VideoRAMBase; -#endif - -#ifdef ARAM_PAGE_CHECK -extern uaecptr pc_page, read_page, write_page; -extern uintptr pc_offset, read_offset, write_offset; -# ifdef PROTECT2K -# define ARAM_PAGE_MASK 0x7ff -# else -# ifdef FULLMMU -# define ARAM_PAGE_MASK 0xfff -# else -# define ARAM_PAGE_MASK 0xfffff -# endif -# endif -#endif - -extern uintptr MEMBaseDiff; -extern uintptr ROMBaseDiff; -extern uintptr FastRAMBaseDiff; -# define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra)) -# define InitROMBaseDiff(va, ra) (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra)) -# define InitFastRAMBaseDiff(va, ra) (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra)) - -#ifdef FIXED_VIDEORAM -#define InitVMEMBaseDiff(va, ra) (VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra)) -#else -#define InitVMEMBaseDiff(va, ra) (ra = (uintptr)(va) + MEMBaseDiff) -#endif - -extern "C" void breakpt(void); - - -static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);} -static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);} - - -#ifndef NOCHECKBOUNDARY -static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write) -{ - if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) { -#ifdef PROTECT2K - // protect first 2kB of RAM - access in supervisor mode only - if (!super && addr < 0x00000800UL) - return false; -#endif - // check for write access to protected areas: - // - first two longwords of ST-RAM are non-writable (ROM shadow) - // - non-writable area between end of ST-RAM and begin of FastRAM - if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size))) - return true; - } -#ifdef FIXED_VIDEORAM - return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size); -#else - return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size); -#endif -} -/* - * "size" is the size of the memory access (byte = 1, word = 2, long = 4) - */ -static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write) -{ - if (test_ram_boundary(addr, size, regs.s, write)) - return; - - // D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr)); - regs.mmu_fault_addr = addr; - regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8)); - breakpt(); - THROW(2); -} - -#else -static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; } -static inline void check_ram_boundary(uaecptr, int, bool) { } -#endif - -#ifdef FIXED_VIDEORAM -# define do_get_real_address(a) ((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff))) -#else -# define do_get_real_address(a) ((uae_u8 *)((uintptr)(a) + MEMBaseDiff)) -#endif - -static inline uae_u8 *phys_get_real_address(uaecptr addr) -{ - return do_get_real_address(addr); -} - -#ifndef NOCHECKBOUNDARY -static inline bool phys_valid_address(uaecptr addr, bool write, int sz) -{ - return test_ram_boundary(addr, sz, regs.s, write); -} -#else -static inline bool phys_valid_address(uaecptr, bool, int) { return true; } -#endif - -static inline uae_u64 phys_get_quad(uaecptr addr) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ read_page) <= ARAM_PAGE_MASK)) - return do_get_mem_quad((uae_u64*)(addr + read_offset)); -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */ -#endif - check_ram_boundary(addr, 8, false); - uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - read_page = addr; - read_offset = (uintptr)m - (uintptr)addr; -#endif - return do_get_mem_quad(m); -} - -static inline uae_u32 phys_get_long(uaecptr addr) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ read_page) <= ARAM_PAGE_MASK)) - return do_get_mem_long((uae_u32*)(addr + read_offset)); -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); -#endif - check_ram_boundary(addr, 4, false); - uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - read_page = addr; - read_offset = (uintptr)m - (uintptr)addr; -#endif - return do_get_mem_long(m); -} - -static inline uae_u32 phys_get_word(uaecptr addr) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ read_page) <= ARAM_PAGE_MASK)) - return do_get_mem_word((uae_u16*)(addr + read_offset)); -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr); -#endif - check_ram_boundary(addr, 2, false); - uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - read_page = addr; - read_offset = (uintptr)m - (uintptr)addr; -#endif - return do_get_mem_word(m); -} - -static inline uae_u32 phys_get_byte(uaecptr addr) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ read_page) <= ARAM_PAGE_MASK)) - return do_get_mem_byte((uae_u8*)(addr + read_offset)); -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr); -#endif - check_ram_boundary(addr, 1, false); - uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - read_page = addr; - read_offset = (uintptr)m - (uintptr)addr; -#endif - return do_get_mem_byte(m); -} - -static inline void phys_put_quad(uaecptr addr, uae_u64 l) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { - do_put_mem_quad((uae_u64*)(addr + write_offset), l); - return; - } -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) { - HWput_l(addr, l); /* TODO: must be HWput_q */ - return; - } -#endif - check_ram_boundary(addr, 8, true); - uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - write_page = addr; - write_offset = (uintptr)m - (uintptr)addr; -#endif - do_put_mem_quad(m, l); -} - -static inline void phys_put_long(uaecptr addr, uae_u32 l) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { - do_put_mem_long((uae_u32*)(addr + write_offset), l); - return; - } -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) { - HWput_l(addr, l); - return; - } -#endif - check_ram_boundary(addr, 4, true); - uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - write_page = addr; - write_offset = (uintptr)m - (uintptr)addr; -#endif - do_put_mem_long(m, l); -} - -static inline void phys_put_word(uaecptr addr, uae_u32 w) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { - do_put_mem_word((uae_u16*)(addr + write_offset), w); - return; - } -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) { - HWput_w(addr, w); - return; - } -#endif - check_ram_boundary(addr, 2, true); - uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - write_page = addr; - write_offset = (uintptr)m - (uintptr)addr; -#endif - do_put_mem_word(m, w); -} - -static inline void phys_put_byte(uaecptr addr, uae_u32 b) -{ -#ifdef ARAM_PAGE_CHECK - if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { - do_put_mem_byte((uae_u8*)(addr + write_offset), b); - return; - } -#endif -#ifndef HW_SIGSEGV - addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; - if ((addr & 0xfff00000) == 0x00f00000) { - HWput_b(addr, b); - return; - } -#endif - check_ram_boundary(addr, 1, true); - uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr); -#ifdef ARAM_PAGE_CHECK - write_page = addr; - write_offset = (uintptr)m - (uintptr)addr; -#endif - do_put_mem_byte(m, b); -} - -#ifdef FULLMMU -static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size) -{ - return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000); -} - -static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) -{ - return do_get_real_address(cl->phys + addr); -} - -static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 0, &cl))) - return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl)); - return mmu_get_quad_slow(addr, regs.s, data, cl); -} - -static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr) -{ - return mmu_get_quad(addr, 1); -} - -static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 0, &cl))) - return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); - return mmu_get_long_slow(addr, regs.s, data, size, cl); -} - -static ALWAYS_INLINE uae_u32 get_long(uaecptr addr) -{ - if (unlikely(is_unaligned(addr, 4))) - return mmu_get_long_unaligned(addr, 1); - return mmu_get_long(addr, 1, sz_long); -} - -static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 0, &cl))) - return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); - return mmu_get_word_slow(addr, regs.s, data, size, cl); -} - -static ALWAYS_INLINE uae_u16 get_word(uaecptr addr) -{ - if (unlikely(is_unaligned(addr, 2))) - return mmu_get_word_unaligned(addr, 1); - return mmu_get_word(addr, 1, sz_word); -} - -static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 0, &cl))) - return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); - return mmu_get_byte_slow(addr, regs.s, data, size, cl); -} - -static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr) -{ - return mmu_get_byte(addr, 1, sz_byte); -} - -static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 1, &cl))) - do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_quad_slow(addr, val, regs.s, data, cl); -} - -static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val) -{ - mmu_put_quad(addr, val, 1); -} - -static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 1, &cl))) - do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_long_slow(addr, val, regs.s, data, size, cl); -} - -static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val) -{ - if (unlikely(is_unaligned(addr, 4))) - mmu_put_long_unaligned(addr, val, 1); - else - mmu_put_long(addr, val, 1, sz_long); -} - -static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 1, &cl))) - do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_word_slow(addr, val, regs.s, data, size, cl); -} - -static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val) -{ - if (unlikely(is_unaligned(addr, 2))) - mmu_put_word_unaligned(addr, val, 1); - else - mmu_put_word(addr, val, 1, sz_word); -} - -static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_lookup(addr, data, 1, &cl))) - do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_byte_slow(addr, val, regs.s, data, size, cl); -} - -static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val) -{ - mmu_put_byte(addr, val, 1, sz_byte); -} - -static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz) -{ - (void)sz; - return phys_get_real_address(mmu_translate(addr, regs.s, 1, write)); -} - -static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) - return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); - return mmu_get_long_slow(addr, super, data, size, cl); -} - -static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) - return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); - return mmu_get_word_slow(addr, super, data, size, cl); -} - -static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) - return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); - return mmu_get_byte_slow(addr, super, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) - do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_long_slow(addr, val, super, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) - do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_word_slow(addr, val, super, data, size, cl); -} - -static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size) -{ - struct mmu_atc_line *cl; - - if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) - do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); - else - mmu_put_byte_slow(addr, val, super, data, size, cl); -} - -static inline bool valid_address(uaecptr addr, bool write, int sz) -{ - SAVE_EXCEPTION; - TRY(prb) { - (void)sz; - check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write); - RESTORE_EXCEPTION; - return true; - } - CATCH(prb) { - RESTORE_EXCEPTION; - return false; - } -} - -#else - -# define get_quad(a) phys_get_quad(a) -# define get_long(a) phys_get_long(a) -# define get_word(a) phys_get_word(a) -# define get_byte(a) phys_get_byte(a) -# define put_quad(a,b) phys_put_quad(a,b) -# define put_long(a,b) phys_put_long(a,b) -# define put_word(a,b) phys_put_word(a,b) -# define put_byte(a,b) phys_put_byte(a,b) -# define get_real_address(a,w,s) phys_get_real_address(a) - -#define valid_address(a,w,s) phys_valid_address(a,w,s) -#endif - -static inline void flush_internals() { -#ifdef ARAM_PAGE_CHECK - pc_page = 0xeeeeeeee; - read_page = 0xeeeeeeee; - write_page = 0xeeeeeeee; -#endif -} - -#endif /* MEMORY_H */ - -/* -vim:ts=4:sw=4: -*/ diff --git a/BasiliskII/src/uae_cpu/memory.cpp b/BasiliskII/src/uae_cpu/memory.cpp index e56f993d..7483f506 100644 --- a/BasiliskII/src/uae_cpu/memory.cpp +++ b/BasiliskII/src/uae_cpu/memory.cpp @@ -1,59 +1,642 @@ /* - * memory.cpp - memory management + * UAE - The Un*x Amiga Emulator * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Memory management * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * (c) 1995 Bernd Schmidt * - * ARAnyM is free software; you can redistribute it and/or modify + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * ARAnyM is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* - * UAE - The Un*x Amiga Emulator - * - * Memory management - * - * (c) 1995 Bernd Schmidt - */ + +#include +#include #include "sysdeps.h" -#include "memory.h" -#define DEBUG 0 -#include "debug.h" +#include "cpu_emulation.h" +#include "main.h" +#include "video.h" -#ifdef ARAM_PAGE_CHECK -uaecptr pc_page = 0xeeeeeeee; -uintptr pc_offset = 0; -uaecptr read_page = 0xeeeeeeee; -uintptr read_offset = 0; -uaecptr write_page = 0xeeeeeeee; -uintptr write_offset = 0; +#include "m68k.h" +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" + +#if !REAL_ADDRESSING && !DIRECT_ADDRESSING + +static bool illegal_mem = false; + +#ifdef SAVE_MEMORY_BANKS +addrbank *mem_banks[65536]; +#else +addrbank mem_banks[65536]; #endif -extern "C" void breakpt(void) +#ifdef WORDS_BIGENDIAN +# define swap_words(X) (X) +#else +# define swap_words(X) (((X) >> 16) | ((X) << 16)) +#endif + +#ifdef NO_INLINE_MEMORY_ACCESS +uae_u32 longget (uaecptr addr) { - // bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr); + return call_mem_get_func (get_mem_bank (addr).lget, addr); +} +uae_u32 wordget (uaecptr addr) +{ + return call_mem_get_func (get_mem_bank (addr).wget, addr); +} +uae_u32 byteget (uaecptr addr) +{ + return call_mem_get_func (get_mem_bank (addr).bget, addr); +} +void longput (uaecptr addr, uae_u32 l) +{ + call_mem_put_func (get_mem_bank (addr).lput, addr, l); +} +void wordput (uaecptr addr, uae_u32 w) +{ + call_mem_put_func (get_mem_bank (addr).wput, addr, w); +} +void byteput (uaecptr addr, uae_u32 b) +{ + call_mem_put_func (get_mem_bank (addr).bput, addr, b); +} +#endif + +/* A dummy bank that only contains zeros */ + +static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM; +static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM; +static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM; +static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM; + +uae_u32 REGPARAM2 dummy_lget (uaecptr addr) +{ + if (illegal_mem) + write_log ("Illegal lget at %08x\n", addr); + + return 0; } -#if !KNOWN_ALLOC && !NORMAL_ADDRESSING -// This part need rewrite for ARAnyM !! -// It can be taken from hatari. +uae_u32 REGPARAM2 dummy_wget (uaecptr addr) +{ + if (illegal_mem) + write_log ("Illegal wget at %08x\n", addr); -#error Not prepared for your platform, maybe you need memory banks from hatari + return 0; +} + +uae_u32 REGPARAM2 dummy_bget (uaecptr addr) +{ + if (illegal_mem) + write_log ("Illegal bget at %08x\n", addr); + + return 0; +} + +void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l) +{ + if (illegal_mem) + write_log ("Illegal lput at %08x\n", addr); +} +void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w) +{ + if (illegal_mem) + write_log ("Illegal wput at %08x\n", addr); +} +void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b) +{ + if (illegal_mem) + write_log ("Illegal bput at %08x\n", addr); +} + +/* Mac RAM (32 bit addressing) */ + +static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM; +static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM; +static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM; + +static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac + +uae_u32 REGPARAM2 ram_lget(uaecptr addr) +{ + uae_u32 *m; + m = (uae_u32 *)(RAMBaseDiff + addr); + return do_get_mem_long(m); +} + +uae_u32 REGPARAM2 ram_wget(uaecptr addr) +{ + uae_u16 *m; + m = (uae_u16 *)(RAMBaseDiff + addr); + return do_get_mem_word(m); +} + +uae_u32 REGPARAM2 ram_bget(uaecptr addr) +{ + return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr); +} + +void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l) +{ + uae_u32 *m; + m = (uae_u32 *)(RAMBaseDiff + addr); + do_put_mem_long(m, l); +} + +void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w) +{ + uae_u16 *m; + m = (uae_u16 *)(RAMBaseDiff + addr); + do_put_mem_word(m, w); +} + +void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b) +{ + *(uae_u8 *)(RAMBaseDiff + addr) = b; +} + +uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) +{ + return (uae_u8 *)(RAMBaseDiff + addr); +} + +/* Mac RAM (24 bit addressing) */ + +static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM; +static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM; +static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM; + +uae_u32 REGPARAM2 ram24_lget(uaecptr addr) +{ + uae_u32 *m; + m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); + return do_get_mem_long(m); +} + +uae_u32 REGPARAM2 ram24_wget(uaecptr addr) +{ + uae_u16 *m; + m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); + return do_get_mem_word(m); +} + +uae_u32 REGPARAM2 ram24_bget(uaecptr addr) +{ + return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)); +} + +void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l) +{ + uae_u32 *m; + m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); + do_put_mem_long(m, l); +} + +void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w) +{ + uae_u16 *m; + m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); + do_put_mem_word(m, w); +} + +void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b) +{ + *(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b; +} + +uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) +{ + return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)); +} + +/* Mac ROM (32 bit addressing) */ + +static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM; +static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM; +static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM; + +static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac + +uae_u32 REGPARAM2 rom_lget(uaecptr addr) +{ + uae_u32 *m; + m = (uae_u32 *)(ROMBaseDiff + addr); + return do_get_mem_long(m); +} + +uae_u32 REGPARAM2 rom_wget(uaecptr addr) +{ + uae_u16 *m; + m = (uae_u16 *)(ROMBaseDiff + addr); + return do_get_mem_word(m); +} + +uae_u32 REGPARAM2 rom_bget(uaecptr addr) +{ + return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr); +} + +void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b) +{ + if (illegal_mem) + write_log ("Illegal ROM lput at %08x\n", addr); +} + +void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b) +{ + if (illegal_mem) + write_log ("Illegal ROM wput at %08x\n", addr); +} + +void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b) +{ + if (illegal_mem) + write_log ("Illegal ROM bput at %08x\n", addr); +} + +uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) +{ + return (uae_u8 *)(ROMBaseDiff + addr); +} + +/* Mac ROM (24 bit addressing) */ + +static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM; +static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM; + +uae_u32 REGPARAM2 rom24_lget(uaecptr addr) +{ + uae_u32 *m; + m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff)); + return do_get_mem_long(m); +} + +uae_u32 REGPARAM2 rom24_wget(uaecptr addr) +{ + uae_u16 *m; + m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff)); + return do_get_mem_word(m); +} + +uae_u32 REGPARAM2 rom24_bget(uaecptr addr) +{ + return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff)); +} + +uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) +{ + return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff)); +} + +/* Frame buffer */ + +static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM; +static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM; + +static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM; +static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM; + +static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM; +static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM; +static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM; + +static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM; +static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM; + +static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM; + +static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac + +uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr) +{ + uae_u32 *m; + m = (uae_u32 *)(FrameBaseDiff + addr); + return do_get_mem_long(m); +} + +uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr) +{ + uae_u16 *m; + m = (uae_u16 *)(FrameBaseDiff + addr); + return do_get_mem_word(m); +} + +uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr) +{ + return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr); +} + +void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l) +{ + uae_u32 *m; + m = (uae_u32 *)(FrameBaseDiff + addr); + do_put_mem_long(m, l); +} + +void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w) +{ + uae_u16 *m; + m = (uae_u16 *)(FrameBaseDiff + addr); + do_put_mem_word(m, w); +} + +void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b) +{ + *(uae_u8 *)(FrameBaseDiff + addr) = b; +} + +uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr) +{ + uae_u32 *m, l; + m = (uae_u32 *)(FrameBaseDiff + addr); + l = *m; + return swap_words(l); +} + +uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr) +{ + uae_u16 *m; + m = (uae_u16 *)(FrameBaseDiff + addr); + return *m; +} + +void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l) +{ + uae_u32 *m; + m = (uae_u32 *)(FrameBaseDiff + addr); + *m = swap_words(l); +} + +void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w) +{ + uae_u16 *m; + m = (uae_u16 *)(FrameBaseDiff + addr); + *m = w; +} + +uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr) +{ + uae_u32 *m, l; + m = (uae_u32 *)(FrameBaseDiff + addr); + l = *m; + l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0); + return swap_words(l); +} + +uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr) +{ + uae_u16 *m, w; + m = (uae_u16 *)(FrameBaseDiff + addr); + w = *m; + return (w & 0x1f) | ((w >> 1) & 0x7fe0); +} + +void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l) +{ + uae_u32 *m; + m = (uae_u32 *)(FrameBaseDiff + addr); + l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0); + *m = swap_words(l); +} + +void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w) +{ + uae_u16 *m; + m = (uae_u16 *)(FrameBaseDiff + addr); + *m = (w & 0x1f) | ((w << 1) & 0xffc0); +} + +uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr) +{ + uae_u32 *m, l; + m = (uae_u32 *)(FrameBaseDiff + addr); + return *m; +} + +void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l) +{ + uae_u32 *m; + m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac); + *m = l; +} + +uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) +{ + return (uae_u8 *)(FrameBaseDiff + addr); +} + +/* Mac framebuffer RAM (24 bit addressing) + * + * This works by duplicating appropriate writes to the 32-bit + * address-space framebuffer. + */ + +static void REGPARAM2 fram24_lput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 fram24_wput(uaecptr, uae_u32) REGPARAM; +static void REGPARAM2 fram24_bput(uaecptr, uae_u32) REGPARAM; + +void REGPARAM2 fram24_lput(uaecptr addr, uae_u32 l) +{ + uaecptr page_off = addr & 0xffff; + if (0xa700 <= page_off && page_off < 0xfc80) { + uae_u32 *fm; + fm = (uae_u32 *)(MacFrameBaseHost + page_off - 0xa700); + do_put_mem_long(fm, l); + } + + uae_u32 *m; + m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); + do_put_mem_long(m, l); +} + +void REGPARAM2 fram24_wput(uaecptr addr, uae_u32 w) +{ + uaecptr page_off = addr & 0xffff; + if (0xa700 <= page_off && page_off < 0xfc80) { + uae_u16 *fm; + fm = (uae_u16 *)(MacFrameBaseHost + page_off - 0xa700); + do_put_mem_word(fm, w); + } + + uae_u16 *m; + m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); + do_put_mem_word(m, w); +} + +void REGPARAM2 fram24_bput(uaecptr addr, uae_u32 b) +{ + uaecptr page_off = addr & 0xffff; + if (0xa700 <= page_off && page_off < 0xfc80) { + *(uae_u8 *)(MacFrameBaseHost + page_off - 0xa700) = b; + } + + *(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b; +} + +/* Default memory access functions */ + +uae_u8 *REGPARAM2 default_xlate (uaecptr a) +{ + write_log("Your Mac program just did something terribly stupid\n"); + return NULL; +} + +/* Address banks */ + +addrbank dummy_bank = { + dummy_lget, dummy_wget, dummy_bget, + dummy_lput, dummy_wput, dummy_bput, + default_xlate +}; + +addrbank ram_bank = { + ram_lget, ram_wget, ram_bget, + ram_lput, ram_wput, ram_bput, + ram_xlate +}; + +addrbank ram24_bank = { + ram24_lget, ram24_wget, ram24_bget, + ram24_lput, ram24_wput, ram24_bput, + ram24_xlate +}; + +addrbank rom_bank = { + rom_lget, rom_wget, rom_bget, + rom_lput, rom_wput, rom_bput, + rom_xlate +}; + +addrbank rom24_bank = { + rom24_lget, rom24_wget, rom24_bget, + rom_lput, rom_wput, rom_bput, + rom24_xlate +}; + +addrbank frame_direct_bank = { + frame_direct_lget, frame_direct_wget, frame_direct_bget, + frame_direct_lput, frame_direct_wput, frame_direct_bput, + frame_xlate +}; + +addrbank frame_host_555_bank = { + frame_host_555_lget, frame_host_555_wget, frame_direct_bget, + frame_host_555_lput, frame_host_555_wput, frame_direct_bput, + frame_xlate +}; + +addrbank frame_host_565_bank = { + frame_host_565_lget, frame_host_565_wget, frame_direct_bget, + frame_host_565_lput, frame_host_565_wput, frame_direct_bput, + frame_xlate +}; + +addrbank frame_host_888_bank = { + frame_host_888_lget, frame_direct_wget, frame_direct_bget, + frame_host_888_lput, frame_direct_wput, frame_direct_bput, + frame_xlate +}; + +addrbank fram24_bank = { + ram24_lget, ram24_wget, ram24_bget, + fram24_lput, fram24_wput, fram24_bput, + ram24_xlate +}; + +void memory_init(void) +{ + for(long i=0; i<65536; i++) + put_mem_bank(i<<16, &dummy_bank); + + // Limit RAM size to not overlap ROM + uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize; + + RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac; + ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac; + FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac; + + // Map RAM, ROM and display + if (TwentyFourBitAddressing) { + map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16); + map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16); + + // Map frame buffer at end of RAM. + map_banks(&fram24_bank, ((RAMBaseMac + ram_size) >> 16) - 1, 1); + } else { + map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16); + map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16); + + // Map frame buffer + switch (MacFrameLayout) { + case FLAYOUT_DIRECT: + map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); + break; + case FLAYOUT_HOST_555: + map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); + break; + case FLAYOUT_HOST_565: + map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); + break; + case FLAYOUT_HOST_888: + map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); + break; + } + } +} + +void map_banks(addrbank *bank, int start, int size) +{ + int bnr; + unsigned long int hioffs = 0, endhioffs = 0x100; + + if (start >= 0x100) { + for (bnr = start; bnr < start + size; bnr++) + put_mem_bank (bnr << 16, bank); + return; + } + if (TwentyFourBitAddressing) endhioffs = 0x10000; + for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) + for (bnr = start; bnr < start+size; bnr++) + put_mem_bank((bnr + hioffs) << 16, bank); +} + +#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */ -#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */ diff --git a/BasiliskII/src/uae_cpu/memory.h b/BasiliskII/src/uae_cpu/memory.h index f7bab41d..26b3c5f1 100644 --- a/BasiliskII/src/uae_cpu/memory.h +++ b/BasiliskII/src/uae_cpu/memory.h @@ -23,10 +23,6 @@ #ifndef UAE_MEMORY_H #define UAE_MEMORY_H -#if DIRECT_ADDRESSING -extern uintptr MEMBaseDiff; -#endif - extern void Exception (int, uaecptr); #ifdef EXCEPTIONS_VIA_LONGJMP extern JMP_BUF excep_env; @@ -54,8 +50,109 @@ extern void Exception (int, uaecptr); #define THROW_AGAIN(var) throw #define VOLATILE #endif /* EXCEPTIONS_VIA_LONGJMP */ +extern int in_exception_2; -#if DIRECT_ADDRESSING +#if !DIRECT_ADDRESSING && !REAL_ADDRESSING + +/* Enabling this adds one additional native memory reference per 68k memory + * access, but saves one shift (on the x86). Enabling this is probably + * better for the cache. My favourite benchmark (PP2) doesn't show a + * difference, so I leave this enabled. */ + +#if 1 || defined SAVE_MEMORY +#define SAVE_MEMORY_BANKS +#endif + +typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM; +typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM; +typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM; + +#undef DIRECT_MEMFUNCS_SUCCESSFUL + +#ifndef CAN_MAP_MEMORY +#undef USE_COMPILER +#endif + +#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY) +#define USE_MAPPED_MEMORY +#endif + +typedef struct { + /* These ones should be self-explanatory... */ + mem_get_func lget, wget, bget; + mem_put_func lput, wput, bput; + /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can + * be used to address memory without calling the wget/wput functions. + * This doesn't work for all memory banks, so this function may call + * abort(). */ + xlate_func xlateaddr; +} addrbank; + +extern uae_u8 filesysory[65536]; + +extern addrbank ram_bank; // Mac RAM +extern addrbank rom_bank; // Mac ROM +extern addrbank frame_bank; // Frame buffer + +/* Default memory access functions */ + +extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM; + +#define bankindex(addr) (((uaecptr)(addr)) >> 16) + +#ifdef SAVE_MEMORY_BANKS +extern addrbank *mem_banks[65536]; +#define get_mem_bank(addr) (*mem_banks[bankindex(addr)]) +#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b)) +#else +extern addrbank mem_banks[65536]; +#define get_mem_bank(addr) (mem_banks[bankindex(addr)]) +#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b)) +#endif + +extern void memory_init(void); +extern void map_banks(addrbank *bank, int first, int count); + +#ifndef NO_INLINE_MEMORY_ACCESS + +#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr)) +#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr)) +#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr)) +#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l)) +#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w)) +#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b)) + +#else + +extern uae_u32 longget(uaecptr addr); +extern uae_u32 wordget(uaecptr addr); +extern uae_u32 byteget(uaecptr addr); +extern void longput(uaecptr addr, uae_u32 l); +extern void wordput(uaecptr addr, uae_u32 w); +extern void byteput(uaecptr addr, uae_u32 b); + +#endif + +#ifndef MD_HAVE_MEM_1_FUNCS + +#define longget_1 longget +#define wordget_1 wordget +#define byteget_1 byteget +#define longput_1 longput +#define wordput_1 wordput +#define byteput_1 byteput + +#endif + +#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */ + +#if REAL_ADDRESSING +const uintptr MEMBaseDiff = 0; +#elif DIRECT_ADDRESSING +extern uintptr MEMBaseDiff; +#endif + +#if REAL_ADDRESSING || DIRECT_ADDRESSING static __inline__ uae_u8 *do_get_real_address(uaecptr addr) { return (uae_u8 *)MEMBaseDiff + addr; @@ -69,57 +166,71 @@ static __inline__ uae_u32 get_long(uaecptr addr) uae_u32 * const m = (uae_u32 *)do_get_real_address(addr); return do_get_mem_long(m); } -#define phys_get_long get_long static __inline__ uae_u32 get_word(uaecptr addr) { uae_u16 * const m = (uae_u16 *)do_get_real_address(addr); return do_get_mem_word(m); } -#define phys_get_word get_word static __inline__ uae_u32 get_byte(uaecptr addr) { uae_u8 * const m = (uae_u8 *)do_get_real_address(addr); return do_get_mem_byte(m); } -#define phys_get_byte get_byte static __inline__ void put_long(uaecptr addr, uae_u32 l) { uae_u32 * const m = (uae_u32 *)do_get_real_address(addr); do_put_mem_long(m, l); } -#define phys_put_long put_long static __inline__ void put_word(uaecptr addr, uae_u32 w) { uae_u16 * const m = (uae_u16 *)do_get_real_address(addr); do_put_mem_word(m, w); } -#define phys_put_word put_word static __inline__ void put_byte(uaecptr addr, uae_u32 b) { uae_u8 * const m = (uae_u8 *)do_get_real_address(addr); do_put_mem_byte(m, b); } -#define phys_put_byte put_byte static __inline__ uae_u8 *get_real_address(uaecptr addr) { return do_get_real_address(addr); } -static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz) -{ - return do_get_real_address(addr); -} -static inline uae_u8 *phys_get_real_address(uaecptr addr) -{ - return do_get_real_address(addr); -} static __inline__ uae_u32 get_virtual_address(uae_u8 *addr) { return do_get_virtual_address(addr); } -#endif /* DIRECT_ADDRESSING */ - -static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {} -static inline void flush_internals() {} +#else +static __inline__ uae_u32 get_long(uaecptr addr) +{ + return longget_1(addr); +} +static __inline__ uae_u32 get_word(uaecptr addr) +{ + return wordget_1(addr); +} +static __inline__ uae_u32 get_byte(uaecptr addr) +{ + return byteget_1(addr); +} +static __inline__ void put_long(uaecptr addr, uae_u32 l) +{ + longput_1(addr, l); +} +static __inline__ void put_word(uaecptr addr, uae_u32 w) +{ + wordput_1(addr, w); +} +static __inline__ void put_byte(uaecptr addr, uae_u32 b) +{ + byteput_1(addr, b); +} +static __inline__ uae_u8 *get_real_address(uaecptr addr) +{ + return get_mem_bank(addr).xlateaddr(addr); +} +/* gb-- deliberately not implemented since it shall not be used... */ +extern uae_u32 get_virtual_address(uae_u8 *addr); +#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */ #endif /* MEMORY_H */ diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index ac1505f5..e9d0b88d 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -1,74 +1,51 @@ /* - * newcpu.cpp - CPU emulation + * UAE - The Un*x Amiga Emulator * - * Copyright (c) 2010 ARAnyM dev team (see AUTHORS) - * + * MC68000 emulation * - * Inspired by Christian Bauer's Basilisk II + * (c) 1995 Bernd Schmidt * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. - * - * ARAnyM is free software; you can redistribute it and/or modify + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * ARAnyM is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * (c) 1995 Bernd Schmidt - */ + +#include +#include +#include #include "sysdeps.h" -#include #include "cpu_emulation.h" #include "main.h" #include "emul_op.h" + +extern int intlev(void); // From baisilisk_glue.cpp + #include "m68k.h" #include "memory.h" #include "readcpu.h" #include "newcpu.h" -#ifdef USE_JIT -# include "compiler/compemu.h" -#endif +#include "compiler/compemu.h" #include "fpu/fpu.h" -#include "cpummu.h" -// #include "natfeats.h" -// #include "disasm-glue.h" -#include - -#define DEBUG 0 -#include "debug.h" - -#define SANITY_CHECK_ATC 1 - -struct fixup fixup = {0, 0, 0}; - -int quit_program = 0; - -// For instruction $7139 -bool cpu_debugging = false; +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) +B2_mutex *spcflags_lock = NULL; +#endif +bool quit_program = false; struct flag_struct regflags; -/* LongJump buffers */ -#ifdef EXCEPTIONS_VIA_LONGJMP -JMP_BUF excep_env; -#endif /* Opcode of faulting instruction */ uae_u16 last_op_for_exception_3; /* PC at fault time */ @@ -83,34 +60,19 @@ int movem_index1[256]; int movem_index2[256]; int movem_next[256]; -#ifdef FLIGHT_RECORDER - -// feel free to edit the following defines to customize the dump -#define FRLOG_HOTKEY 1 /* 1 = dump only when hotkey is held down */ -#define FRLOG_ALL 1 /* 1 = dump continuously to ever growing log */ -#define FRLOG_IRQ 0 /* 1 = dump also CPU in interrupts */ -#define FRLOG_REGS 0 /* 1 = dump also all data/address registers */ -#define FRLOG_SIZE 8192 /* this many instructions in single dump */ +cpuop_func *cpufunctbl[65536]; +#if FLIGHT_RECORDER struct rec_step { + uae_u32 pc; +#if FLIGHT_RECORDER >= 2 uae_u32 d[8]; uae_u32 a[8]; - uae_u32 pc; - uae_u16 sr; - uae_u32 usp; - uae_u32 msp; - uae_u32 isp; - uae_u16 instr; +#endif }; -bool cpu_flight_recorder_active = false; - -#if FRLOG_ALL -const int LOG_SIZE = 10; -#else -const int LOG_SIZE = FRLOG_SIZE; -#endif -static rec_step frlog[LOG_SIZE]; +const int LOG_SIZE = 32768; +static rec_step log[LOG_SIZE]; static int log_ptr = -1; // First time initialization static const char *log_filename(void) @@ -119,580 +81,848 @@ static const char *log_filename(void) return name ? name : "log.68k"; } -void dump_flight_recorder(void) +void m68k_record_step(uaecptr pc) { -#if FRLOG_ALL - FILE *f = fopen(log_filename(), "a"); -#else - FILE *f = fopen(log_filename(), "w"); +#if FLIGHT_RECORDER >= 2 + /* XXX: if LSB is set, we are recording from generated code and we + don't support registers recording yet. */ + if ((pc & 1) == 0) { + for (int i = 0; i < 8; i++) { + log[log_ptr].d[i] = m68k_dreg(regs, i); + log[log_ptr].a[i] = m68k_areg(regs, i); + } + } #endif + log[log_ptr].pc = pc; + log_ptr = (log_ptr + 1) % LOG_SIZE; +} + +static void dump_log(void) +{ + FILE *f = fopen(log_filename(), "w"); if (f == NULL) return; for (int i = 0; i < LOG_SIZE; i++) { int j = (i + log_ptr) % LOG_SIZE; - fprintf(f, "pc %08x instr %04x sr %04x usp %08x msp %08x isp %08x\n", frlog[j].pc, frlog[j].instr, frlog[j].sr, frlog[j].usp, frlog[j].msp, frlog[j].isp); - // adding a simple opcode -> assembler conversion table would help -#if FRLOG_REGS - fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", frlog[j].d[0], frlog[j].d[1], frlog[j].d[2], frlog[j].d[3]); - fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", frlog[j].d[4], frlog[j].d[5], frlog[j].d[6], frlog[j].d[7]); - fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", frlog[j].a[0], frlog[j].a[1], frlog[j].a[2], frlog[j].a[3]); - fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", frlog[j].a[4], frlog[j].a[5], frlog[j].a[6], frlog[j].a[7]); + uae_u32 pc = log[j].pc & ~1; + fprintf(f, "pc %08x", pc); +#if FLIGHT_RECORDER >= 2 + fprintf(f, "\n"); + if ((log[j].pc & 1) == 0) { + fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]); + fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]); + fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]); + fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]); + } +#else + fprintf(f, " | "); +#endif +#if ENABLE_MON + disass_68k(f, pc); #endif } fclose(f); } +#endif -void m68k_record_step(uaecptr pc, int opcode) +#if ENABLE_MON +static void dump_regs(void) { - static bool last_state = false; - -#if FRLOG_HOTKEY - if (! cpu_flight_recorder_active) { - if (last_state) { - // dump log out - dump_flight_recorder(); - - // remember last state - last_state = false; - } - return; - } -#endif - - if (! last_state) { - // reset old log - log_ptr = 0; - memset(frlog, 0, sizeof(frlog)); - // remember last state - last_state = true; - } - -#if FRLOG_REGS - for (int i = 0; i < 8; i++) { - frlog[log_ptr].d[i] = m68k_dreg(regs, i); - frlog[log_ptr].a[i] = m68k_areg(regs, i); - } -#endif - frlog[log_ptr].pc = pc; - - MakeSR(); -#if ! FRLOG_IRQ - // is CPU in interrupt handler? Quit if should not be logged. - if (regs.s && !regs.m) return; -#endif - frlog[log_ptr].sr = regs.sr; - frlog[log_ptr].usp = regs.usp; - frlog[log_ptr].msp = regs.msp; - frlog[log_ptr].isp = regs.isp; - frlog[log_ptr].instr = opcode; - - log_ptr = (log_ptr + 1) % LOG_SIZE; -#if FRLOG_ALL - if (log_ptr == 0) dump_flight_recorder(); -#endif + m68k_dumpstate(NULL); } -#endif /* FLIGHT_RECORDER */ +#endif + +#define COUNT_INSTRS 0 + +#if COUNT_INSTRS +static unsigned long int instrcount[65536]; +static uae_u16 opcodenums[65536]; + +static int compfn (const void *el1, const void *el2) +{ + return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2]; +} + +static char *icountfilename (void) +{ + char *name = getenv ("INSNCOUNT"); + if (name) + return name; + return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount"; +} + +void dump_counts (void) +{ + FILE *f = fopen (icountfilename (), "w"); + unsigned long int total; + int i; + + write_log ("Writing instruction count file...\n"); + for (i = 0; i < 65536; i++) { + opcodenums[i] = i; + total += instrcount[i]; + } + qsort (opcodenums, 65536, sizeof(uae_u16), compfn); + + fprintf (f, "Total: %lu\n", total); + for (i=0; i < 65536; i++) { + unsigned long int cnt = instrcount[opcodenums[i]]; + struct instr *dp; + struct mnemolookup *lookup; + if (!cnt) + break; + dp = table68k + opcodenums[i]; + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) + ; + fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name); + } + fclose (f); +} +#else +void dump_counts (void) +{ +} +#endif int broken_in; -static inline unsigned int cft_map (unsigned int f) +static __inline__ unsigned int cft_map (unsigned int f) { -#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU) - return f; +#ifndef HAVE_GET_WORD_UNSWAPPED + return f; #else - return do_byteswap_16(f); + return ((f >> 8) & 255) | ((f & 255) << 8); #endif } +void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; + void REGPARAM2 op_illg_1 (uae_u32 opcode) { - op_illg (cft_map (opcode)); + op_illg (cft_map (opcode)); } +static void build_cpufunctbl (void) +{ + int i; + unsigned long opcode; + unsigned int cpu_level = 0; // 68000 (default) + if (CPUType == 4) + cpu_level = 4; // 68040 with FPU + else { + if (FPUType) + cpu_level = 3; // 68020 with FPU + else if (CPUType >= 2) + cpu_level = 2; // 68020 + else if (CPUType == 1) + cpu_level = 1; + } + struct cputbl *tbl = ( + cpu_level == 4 ? op_smalltbl_0_ff + : cpu_level == 3 ? op_smalltbl_1_ff + : cpu_level == 2 ? op_smalltbl_2_ff + : cpu_level == 1 ? op_smalltbl_3_ff + : op_smalltbl_4_ff); + + for (opcode = 0; opcode < 65536; opcode++) + cpufunctbl[cft_map (opcode)] = op_illg_1; + for (i = 0; tbl[i].handler != NULL; i++) { + if (! tbl[i].specific) + cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; + } + for (opcode = 0; opcode < 65536; opcode++) { + cpuop_func *f; + + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) + continue; + + if (table68k[opcode].handler != -1) { + f = cpufunctbl[cft_map (table68k[opcode].handler)]; + if (f == op_illg_1) + abort(); + cpufunctbl[cft_map (opcode)] = f; + } + } + for (i = 0; tbl[i].handler != NULL; i++) { + if (tbl[i].specific) + cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; + } +} void init_m68k (void) { - int i; + int i; - for (i = 0 ; i < 256 ; i++) { - int j; - for (j = 0 ; j < 8 ; j++) { - if (i & (1 << j)) break; + for (i = 0 ; i < 256 ; i++) { + int j; + for (j = 0 ; j < 8 ; j++) { + if (i & (1 << j)) break; + } + movem_index1[i] = j; + movem_index2[i] = 7-j; + movem_next[i] = i & (~(1 << j)); + } +#if COUNT_INSTRS + { + FILE *f = fopen (icountfilename (), "r"); + memset (instrcount, 0, sizeof instrcount); + if (f) { + uae_u32 opcode, count, total; + char name[20]; + write_log ("Reading instruction count file...\n"); + fscanf (f, "Total: %lu\n", &total); + while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) { + instrcount[opcode] = count; + } + fclose(f); + } } - movem_index1[i] = j; - movem_index2[i] = 7-j; - movem_next[i] = i & (~(1 << j)); - } -#ifdef USE_JIT - /* still needed by build_comp(); FIXME */ - read_table68k (); - do_merges (); #endif - fpu_init (CPUType == 4); + read_table68k (); + do_merges (); + + build_cpufunctbl (); + +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) + spcflags_lock = B2_create_mutex(); +#endif + fpu_init(CPUType == 4); } void exit_m68k (void) { fpu_exit (); - - free(table68k); - table68k = NULL; +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) + B2_delete_mutex(spcflags_lock); +#endif } struct regstruct regs, lastint_regs; -// MJ static struct regstruct regs_backup[16]; -// MJ static int backup_pointer = 0; +static struct regstruct regs_backup[16]; +static int backup_pointer = 0; +static long int m68kpc_offset; int lastint_no; - -#ifdef FULLMMU -static inline uae_u8 get_ibyte_1(uae_u32 o) -{ - return get_ibyte(o); -} -static inline uae_u16 get_iword_1(uae_u32 o) -{ - return get_iword(o); -} -static inline uae_u32 get_ilong_1(uae_u32 o) -{ - return get_ilong(o); -} +#if REAL_ADDRESSING || DIRECT_ADDRESSING +#define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1) +#define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o)) +#define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o)) #else -# define get_ibyte_1(o) get_byte(m68k_getpc() + (o) + 1) -# define get_iword_1(o) get_word(m68k_getpc() + (o)) -# define get_ilong_1(o) get_long(m68k_getpc() + (o)) +#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) +#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) +#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) #endif -/* - * extract bitfield data from memory and return it in the MSBs - * bdata caches the unmodified data for put_bitfield() - */ -uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) +uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf) { - uae_u32 tmp, res, mask; + uae_u16 dp; + uae_s8 disp8; + uae_s16 disp16; + int r; + uae_u32 dispreg; + uaecptr addr; + uae_s32 offset = 0; + char buffer[80]; - offset &= 7; - mask = 0xffffffffu << (32 - width); - switch ((offset + width + 7) >> 3) { - case 1: - tmp = get_byte(src); - res = tmp << (24 + offset); - bdata[0] = tmp & ~(mask >> (24 + offset)); + switch (mode){ + case Dreg: + sprintf (buffer,"D%d", reg); break; - case 2: - tmp = get_word(src); - res = tmp << (16 + offset); - bdata[0] = tmp & ~(mask >> (16 + offset)); + case Areg: + sprintf (buffer,"A%d", reg); break; - case 3: - tmp = get_word(src); - res = tmp << (16 + offset); - bdata[0] = tmp & ~(mask >> (16 + offset)); - tmp = get_byte(src + 2); - res |= tmp << (8 + offset); - bdata[1] = tmp & ~(mask >> (8 + offset)); + case Aind: + sprintf (buffer,"(A%d)", reg); break; - case 4: - tmp = get_long(src); - res = tmp << offset; - bdata[0] = tmp & ~(mask >> offset); + case Aipi: + sprintf (buffer,"(A%d)+", reg); break; - case 5: - tmp = get_long(src); - res = tmp << offset; - bdata[0] = tmp & ~(mask >> offset); - tmp = get_byte(src + 4); - res |= tmp >> (8 - offset); - bdata[1] = tmp & ~(mask << (8 - offset)); + case Apdi: + sprintf (buffer,"-(A%d)", reg); + break; + case Ad16: + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr = m68k_areg(regs,reg) + (uae_s16)disp16; + sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff, + (unsigned long)addr); + break; + case Ad8r: + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + disp8 = dp & 0xFF; + r = (dp & 0x7000) >> 12; + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); + dispreg <<= (dp >> 9) & 3; + + if (dp & 0x100) { + uae_s32 outer = 0, disp = 0; + uae_s32 base = m68k_areg(regs,reg); + char name[10]; + sprintf (name,"A%d, ",reg); + if (dp & 0x80) { base = 0; name[0] = 0; } + if (dp & 0x40) dispreg = 0; + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + base += disp; + + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + + if (!(dp & 4)) base += dispreg; + if (dp & 3) base = get_long (base); + if (dp & 4) base += dispreg; + + addr = base + outer; + sprintf (buffer,"(%s%c%d.%c*%d+%d)+%d == $%08lx", name, + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', + 1 << ((dp >> 9) & 3), + disp,outer, + (unsigned long)addr); + } else { + addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg; + sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', + 1 << ((dp >> 9) & 3), disp8, + (unsigned long)addr); + } + break; + case PC16: + addr = m68k_getpc () + m68kpc_offset; + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr += (uae_s16)disp16; + sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr); + break; + case PC8r: + addr = m68k_getpc () + m68kpc_offset; + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + disp8 = dp & 0xFF; + r = (dp & 0x7000) >> 12; + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); + dispreg <<= (dp >> 9) & 3; + + if (dp & 0x100) { + uae_s32 outer = 0,disp = 0; + uae_s32 base = addr; + char name[10]; + sprintf (name,"PC, "); + if (dp & 0x80) { base = 0; name[0] = 0; } + if (dp & 0x40) dispreg = 0; + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + base += disp; + + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + + if (!(dp & 4)) base += dispreg; + if (dp & 3) base = get_long (base); + if (dp & 4) base += dispreg; + + addr = base + outer; + sprintf (buffer,"(%s%c%d.%c*%d+%d)+%d == $%08lx", name, + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', + 1 << ((dp >> 9) & 3), + disp,outer, + (unsigned long)addr); + } else { + addr += (uae_s32)((uae_s8)disp8) + dispreg; + sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', + (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), + disp8, (unsigned long)addr); + } + break; + case absw: + sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset)); + m68kpc_offset += 2; + break; + case absl: + sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset)); + m68kpc_offset += 4; + break; + case imm: + switch (size){ + case sz_byte: + sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff)); + m68kpc_offset += 2; + break; + case sz_word: + sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff)); + m68kpc_offset += 2; + break; + case sz_long: + sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset))); + m68kpc_offset += 4; + break; + default: + break; + } + break; + case imm0: + offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff)); + break; + case imm1: + offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff)); + break; + case imm2: + offset = (uae_s32)get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + sprintf (buffer,"#$%08lx", (unsigned long)offset); + break; + case immi: + offset = (uae_s32)(uae_s8)(reg & 0xff); + sprintf (buffer,"#$%08lx", (unsigned long)offset); break; default: - /* Panic? */ - res = 0; break; } - return res; + if (buf == 0) + printf ("%s", buffer); + else + strcat (buf, buffer); + return offset; } -/* - * write bitfield data (in the LSBs) back to memory, upper bits - * must be cleared already. - */ -void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) +/* The plan is that this will take over the job of exception 3 handling - + * the CPU emulation functions will just do a longjmp to m68k_go whenever + * they hit an odd address. */ +static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val) { - offset = (offset & 7) + width; - switch ((offset + 7) >> 3) { - case 1: - put_byte(dst, bdata[0] | (val << (8 - offset))); + uae_u16 dp; + uae_s8 disp8; + uae_s16 disp16; + int r; + uae_u32 dispreg; + uaecptr addr; + uae_s32 offset = 0; + + switch (mode){ + case Dreg: + *val = m68k_dreg (regs, reg); + return 1; + case Areg: + *val = m68k_areg (regs, reg); + return 1; + + case Aind: + case Aipi: + addr = m68k_areg (regs, reg); break; - case 2: - put_word(dst, bdata[0] | (val << (16 - offset))); + case Apdi: + addr = m68k_areg (regs, reg); break; - case 3: - put_word(dst, bdata[0] | (val >> (offset - 16))); - put_byte(dst + 2, bdata[1] | (val << (24 - offset))); + case Ad16: + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr = m68k_areg(regs,reg) + (uae_s16)disp16; break; - case 4: - put_long(dst, bdata[0] | (val << (32 - offset))); + case Ad8r: + addr = m68k_areg (regs, reg); +d8r_common: + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + disp8 = dp & 0xFF; + r = (dp & 0x7000) >> 12; + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); + dispreg <<= (dp >> 9) & 3; + + if (dp & 0x100) { + uae_s32 outer = 0, disp = 0; + uae_s32 base = addr; + if (dp & 0x80) base = 0; + if (dp & 0x40) dispreg = 0; + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + base += disp; + + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + + if (!(dp & 4)) base += dispreg; + if (dp & 3) base = get_long (base); + if (dp & 4) base += dispreg; + + addr = base + outer; + } else { + addr += (uae_s32)((uae_s8)disp8) + dispreg; + } break; - case 5: - put_long(dst, bdata[0] | (val >> (offset - 32))); - put_byte(dst + 4, bdata[1] | (val << (40 - offset))); + case PC16: + addr = m68k_getpc () + m68kpc_offset; + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr += (uae_s16)disp16; + break; + case PC8r: + addr = m68k_getpc () + m68kpc_offset; + goto d8r_common; + case absw: + addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + break; + case absl: + addr = get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + break; + case imm: + switch (size){ + case sz_byte: + *val = get_iword_1 (m68kpc_offset) & 0xff; + m68kpc_offset += 2; + break; + case sz_word: + *val = get_iword_1 (m68kpc_offset) & 0xffff; + m68kpc_offset += 2; + break; + case sz_long: + *val = get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + break; + default: + break; + } + return 1; + case imm0: + *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + return 1; + case imm1: + *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + return 1; + case imm2: + *val = get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + return 1; + case immi: + *val = (uae_s32)(uae_s8)(reg & 0xff); + return 1; + default: + addr = 0; break; } + if ((addr & 1) == 0) + return 1; + + last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset; + last_fault_for_exception_3 = addr; + return 0; } uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp) { - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - regd <<= (dp >> 9) & 3; - if (dp & 0x100) { - uae_s32 outer = 0; - if (dp & 0x80) base = 0; - if (dp & 0x40) regd = 0; + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + regd <<= (dp >> 9) & 3; + if (dp & 0x100) { + uae_s32 outer = 0; + if (dp & 0x80) base = 0; + if (dp & 0x40) regd = 0; - if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword(); - if ((dp & 0x30) == 0x30) base += next_ilong(); + if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword(); + if ((dp & 0x30) == 0x30) base += next_ilong(); - if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword(); - if ((dp & 0x3) == 0x3) outer = next_ilong(); + if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword(); + if ((dp & 0x3) == 0x3) outer = next_ilong(); - if ((dp & 0x4) == 0) base += regd; - if (dp & 0x3) base = get_long (base); - if (dp & 0x4) base += regd; + if ((dp & 0x4) == 0) base += regd; + if (dp & 0x3) base = get_long (base); + if (dp & 0x4) base += regd; - return base + outer; - } else { - return base + (uae_s32)((uae_s8)dp) + regd; - } + return base + outer; + } else { + return base + (uae_s32)((uae_s8)dp) + regd; + } } uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp) { - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; #if 1 - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - return base + (uae_s8)dp + regd; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + return base + (uae_s8)dp + regd; #else - /* Branch-free code... benchmark this again now that - * things are no longer inline. */ - uae_s32 regd16; - uae_u32 mask; - mask = ((dp & 0x800) >> 11) - 1; - regd16 = (uae_s32)(uae_s16)regd; - regd16 &= mask; - mask = ~mask; - base += (uae_s8)dp; - regd &= mask; - regd |= regd16; - return base + regd; + /* Branch-free code... benchmark this again now that + * things are no longer inline. */ + uae_s32 regd16; + uae_u32 mask; + mask = ((dp & 0x800) >> 11) - 1; + regd16 = (uae_s32)(uae_s16)regd; + regd16 &= mask; + mask = ~mask; + base += (uae_s8)dp; + regd &= mask; + regd |= regd16; + return base + regd; #endif } void MakeSR (void) { #if 0 - assert((regs.t1 & 1) == regs.t1); - assert((regs.t0 & 1) == regs.t0); - assert((regs.s & 1) == regs.s); - assert((regs.m & 1) == regs.m); - assert((XFLG & 1) == XFLG); - assert((NFLG & 1) == NFLG); - assert((ZFLG & 1) == ZFLG); - assert((VFLG & 1) == VFLG); - assert((CFLG & 1) == CFLG); + assert((regs.t1 & 1) == regs.t1); + assert((regs.t0 & 1) == regs.t0); + assert((regs.s & 1) == regs.s); + assert((regs.m & 1) == regs.m); + assert((XFLG & 1) == XFLG); + assert((NFLG & 1) == NFLG); + assert((ZFLG & 1) == ZFLG); + assert((VFLG & 1) == VFLG); + assert((CFLG & 1) == CFLG); #endif - regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) - | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) - | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) - | GET_CFLG); + regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) + | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) + | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) + | GET_CFLG); } void MakeFromSR (void) { - int oldm = regs.m; - int olds = regs.s; + int oldm = regs.m; + int olds = regs.s; - regs.t1 = (regs.sr >> 15) & 1; - regs.t0 = (regs.sr >> 14) & 1; - regs.s = (regs.sr >> 13) & 1; - mmu_set_super(regs.s); - regs.m = (regs.sr >> 12) & 1; - regs.intmask = (regs.sr >> 8) & 7; - SET_XFLG ((regs.sr >> 4) & 1); - SET_NFLG ((regs.sr >> 3) & 1); - SET_ZFLG ((regs.sr >> 2) & 1); - SET_VFLG ((regs.sr >> 1) & 1); - SET_CFLG (regs.sr & 1); - if (olds != regs.s) { - if (olds) { - if (oldm) - regs.msp = m68k_areg(regs, 7); - else - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.usp; - } else { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - } - } else if (olds && oldm != regs.m) { - if (oldm) { - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - } else { - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.msp; - } + regs.t1 = (regs.sr >> 15) & 1; + regs.t0 = (regs.sr >> 14) & 1; + regs.s = (regs.sr >> 13) & 1; + regs.m = (regs.sr >> 12) & 1; + regs.intmask = (regs.sr >> 8) & 7; + SET_XFLG ((regs.sr >> 4) & 1); + SET_NFLG ((regs.sr >> 3) & 1); + SET_ZFLG ((regs.sr >> 2) & 1); + SET_VFLG ((regs.sr >> 1) & 1); + SET_CFLG (regs.sr & 1); + if (CPUType >= 2) { + if (olds != regs.s) { + if (olds) { + if (oldm) + regs.msp = m68k_areg(regs, 7); + else + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; + } + } else if (olds && oldm != regs.m) { + if (oldm) { + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + } else { + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.msp; + } + } + } else { + if (olds != regs.s) { + if (olds) { + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + } + } } - SPCFLAGS_SET( SPCFLAG_INT ); - if (regs.t1 || regs.t0) - SPCFLAGS_SET( SPCFLAG_TRACE ); - else - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_INT ); + if (regs.t1 || regs.t0) + SPCFLAGS_SET( SPCFLAG_TRACE ); + else + /* Keep SPCFLAG_DOTRACE, we still want a trace exception for + SR-modifying instructions (including STOP). */ + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); } -/* for building exception frames */ -static inline void exc_push_word(uae_u16 w) -{ - m68k_areg(regs, 7) -= 2; - put_word(m68k_areg(regs, 7), w); -} -static inline void exc_push_long(uae_u32 l) -{ - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), l); -} - -static inline void exc_make_frame( - int format, - uae_u16 sr, - uae_u32 currpc, - int nr, - uae_u32 x0, - uae_u32 x1 -) -{ - switch(format) { - case 4: - exc_push_long(x1); - exc_push_long(x0); - break; - case 3: - case 2: - exc_push_long(x0); - break; - } - - exc_push_word((format << 12) + (nr * 4)); /* format | vector */ - exc_push_long(currpc); - exc_push_word(sr); -} - -#ifdef EXCEPTIONS_VIA_LONGJMP -static int building_bus_fault_stack_frame=0; -#endif - void Exception(int nr, uaecptr oldpc) { - uae_u32 currpc = m68k_getpc (); - MakeSR(); - - if (fixup.flag) - { - m68k_areg(regs, fixup.reg) = fixup.value; - fixup.flag = 0; - } - - if (!regs.s) { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - regs.s = 1; - mmu_set_super(1); - } - - if (nr == 2) { - /* BUS ERROR handler begins */ -#ifdef ENABLE_EPSLIMITER - check_eps_limit(currpc); -#endif - // panicbug("Exception Nr. %d CPC: %08lx NPC: %08lx SP=%08lx Addr: %08lx", nr, currpc, get_long (regs.vbr + 4*nr), m68k_areg(regs, 7), regs.mmu_fault_addr); - -#ifdef EXCEPTIONS_VIA_LONGJMP - if (!building_bus_fault_stack_frame) -#else - try -#endif - { -#ifdef EXCEPTIONS_VIA_LONGJMP - building_bus_fault_stack_frame= 1; -#endif - /* 68040 */ - exc_push_long(0); /* PD3 */ - exc_push_long(0); /* PD2 */ - exc_push_long(0); /* PD1 */ - exc_push_long(0); /* PD0/WB1D */ - exc_push_long(0); /* WB1A */ - exc_push_long(0); /* WB2D */ - exc_push_long(0); /* WB2A */ - exc_push_long(regs.wb3_data); /* WB3D */ - exc_push_long(regs.mmu_fault_addr); /* WB3A */ - exc_push_long(regs.mmu_fault_addr); - exc_push_word(0); /* WB1S */ - exc_push_word(0); /* WB2S */ - exc_push_word(regs.wb3_status); /* WB3S */ - regs.wb3_status = 0; - exc_push_word(regs.mmu_ssw); - exc_push_long(regs.mmu_fault_addr); /* EA */ - exc_make_frame(7, regs.sr, regs.fault_pc, 2, 0, 0); - + uae_u32 currpc = m68k_getpc (); + MakeSR(); + if (!regs.s) { + regs.usp = m68k_areg(regs, 7); + if (CPUType >= 2) + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; + else + m68k_areg(regs, 7) = regs.isp; + regs.s = 1; } -#ifdef EXCEPTIONS_VIA_LONGJMP - else -#else - catch (m68k_exception) -#endif - { - report_double_bus_error(); -#ifdef EXCEPTIONS_VIA_LONGJMP - building_bus_fault_stack_frame= 0; -#endif - return; - } - -#ifdef EXCEPTIONS_VIA_LONGJMP - building_bus_fault_stack_frame= 0; -#endif - /* end of BUS ERROR handler */ - } else if (nr == 3) { - exc_make_frame(2, regs.sr, last_addr_for_exception_3, nr, - last_fault_for_exception_3 & 0xfffffffe, 0); - } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { - /* div by zero, CHK, TRAP or TRACE */ - exc_make_frame(2, regs.sr, currpc, nr, oldpc, 0); - } else if (regs.m && nr >= 24 && nr < 32) { - /* interrupts! */ - exc_make_frame(0, regs.sr, currpc, nr, 0, 0); - regs.sr |= (1 << 13); - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - - exc_make_frame(1, /* throwaway */ - regs.sr, currpc, nr, 0, 0); - } else { - exc_make_frame(0, regs.sr, currpc, nr, 0, 0); - } - m68k_setpc (get_long (regs.vbr + 4*nr)); - SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); - fill_prefetch_0 (); - regs.t1 = regs.t0 = regs.m = 0; - SPCFLAGS_CLEAR(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + if (CPUType > 0) { + if (nr == 2 || nr == 3) { + int i; + /* @@@ this is probably wrong (?) */ + for (i = 0 ; i < 12 ; i++) { + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0); + } + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0xa000 + nr * 4); + } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), oldpc); + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0x2000 + nr * 4); + } else if (regs.m && nr >= 24 && nr < 32) { + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), nr * 4); + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), currpc); + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), regs.sr); + regs.sr |= (1 << 13); + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0x1000 + nr * 4); + } else { + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), nr * 4); + } + } else { + if (nr == 2 || nr == 3) { + m68k_areg(regs, 7) -= 12; + /* ??????? */ + if (nr == 3) { + put_long (m68k_areg(regs, 7), last_fault_for_exception_3); + put_word (m68k_areg(regs, 7)+4, last_op_for_exception_3); + put_long (m68k_areg(regs, 7)+8, last_addr_for_exception_3); + } + write_log ("Exception!\n"); + goto kludge_me_do; + } + } + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), currpc); +kludge_me_do: + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), regs.sr); + m68k_setpc (get_long (regs.vbr + 4*nr)); + SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); + fill_prefetch_0 (); + regs.t1 = regs.t0 = regs.m = 0; + SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE ); } static void Interrupt(int nr) { - assert(nr < 8 && nr >= 0); - lastint_regs = regs; - lastint_no = nr; - Exception(nr+24, 0); + assert(nr < 8 && nr >= 0); + lastint_regs = regs; + lastint_no = nr; + Exception(nr+24, 0); - regs.intmask = nr; - SPCFLAGS_SET( SPCFLAG_INT ); + regs.intmask = nr; + SPCFLAGS_SET( SPCFLAG_INT ); } -static void SCCInterrupt(int nr) +static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp; + +static int movec_illg (int regno) { - // fprintf(stderr, "CPU: in SCCInterrupt\n"); - lastint_regs = regs; - lastint_no = 5;// ex 5 - Exception(nr, 0); - - regs.intmask = 5;// ex 5 -} - -static void MFPInterrupt(int nr) -{ - // fprintf(stderr, "CPU: in MFPInterrupt\n"); - lastint_regs = regs; - lastint_no = 6; - Exception(nr, 0); - - regs.intmask = 6; + switch (CPUType) { + case 1: + if ((regno & 0x7ff) <= 1) + return 0; + break; + case 2: + case 3: + if ((regno & 0x7ff) <= 2) + return 0; + if (regno == 3 || regno == 4) + return 0; + break; + case 4: + if ((regno & 0x7ff) <= 7) { + if (regno != 0x802) + return 0; + } + break; + } + return 1; } int m68k_move2c (int regno, uae_u32 *regp) { - switch (regno) { - case 0: regs.sfc = *regp & 7; break; - case 1: regs.dfc = *regp & 7; break; - case 2: regs.cacr = *regp & 0x80008000; -#ifdef USE_JIT - set_cache_state(regs.cacr & 0x8000); - if (*regp & 0x08) { /* Just to be on the safe side */ - flush_icache(2); - } + if (movec_illg (regno)) { + op_illg (0x4E7B); + return 0; + } else { + switch (regno) { + case 0: regs.sfc = *regp & 7; break; + case 1: regs.dfc = *regp & 7; break; + case 2: + cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); +#if USE_JIT + set_cache_state(regs.cacr & 0x8000); + if (*regp & 0x08) { /* Just to be on the safe side */ + flush_icache(2); + } #endif - break; - case 3: mmu_set_tc(*regp & 0xc000); break; - case 4: - case 5: - case 6: - case 7: mmu_set_ttr(regno, *regp & 0xffffe364); break; - case 0x800: regs.usp = *regp; break; - case 0x801: regs.vbr = *regp; break; - case 0x802: regs.caar = *regp & 0xfc; break; - case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; - case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; - case 0x805: mmu_set_mmusr(*regp); break; - case 0x806: regs.urp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; - case 0x807: regs.srp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; - default: - op_illg (0x4E7B); - return 0; + break; + case 3: tc = *regp & 0xc000; break; + case 4: itt0 = *regp & 0xffffe364; break; + case 5: itt1 = *regp & 0xffffe364; break; + case 6: dtt0 = *regp & 0xffffe364; break; + case 7: dtt1 = *regp & 0xffffe364; break; + case 0x800: regs.usp = *regp; break; + case 0x801: regs.vbr = *regp; break; + case 0x802: caar = *regp &0xfc; break; + case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; + case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; + case 0x805: mmusr = *regp; break; + case 0x806: urp = *regp; break; + case 0x807: srp = *regp; break; + default: + op_illg (0x4E7B); + return 0; + } } - return 1; + return 1; } int m68k_movec2 (int regno, uae_u32 *regp) { - switch (regno) { - case 0: *regp = regs.sfc; break; - case 1: *regp = regs.dfc; break; - case 2: *regp = regs.cacr; break; - case 3: *regp = regs.tc; break; - case 4: *regp = regs.itt0; break; - case 5: *regp = regs.itt1; break; - case 6: *regp = regs.dtt0; break; - case 7: *regp = regs.dtt1; break; - case 0x800: *regp = regs.usp; break; - case 0x801: *regp = regs.vbr; break; - case 0x802: *regp = regs.caar; break; - case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; - case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; - case 0x805: *regp = regs.mmusr; break; - case 0x806: *regp = regs.urp; break; - case 0x807: *regp = regs.srp; break; - default: - op_illg (0x4E7A); - return 0; + if (movec_illg (regno)) + { + op_illg (0x4E7A); + return 0; + } else { + switch (regno) { + case 0: *regp = regs.sfc; break; + case 1: *regp = regs.dfc; break; + case 2: *regp = cacr; break; + case 3: *regp = tc; break; + case 4: *regp = itt0; break; + case 5: *regp = itt1; break; + case 6: *regp = dtt0; break; + case 7: *regp = dtt1; break; + case 0x800: *regp = regs.usp; break; + case 0x801: *regp = regs.vbr; break; + case 0x802: *regp = caar; break; + case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; + case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; + case 0x805: *regp = mmusr; break; + case 0x806: *regp = urp; break; + case 0x807: *regp = srp; break; + default: + op_illg (0x4E7A); + return 0; + } } - return 1; + return 1; } -#if !defined(uae_s64) -static inline int +static __inline__ int div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem) { uae_u32 q = 0, cbit = 0; int i; if (div <= src_hi) { - return 1; + return 1; } for (i = 0 ; i < 32 ; i++) { cbit = src_hi & 0x80000000ul; @@ -709,131 +939,129 @@ div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem = src_hi; return 0; } -#endif -void m68k_divl (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra, uaecptr oldpc) +void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) { #if defined(uae_s64) - if (src == 0) { - Exception (5, oldpc); - return; - } - if (extra & 0x800) { - /* signed variant */ - uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - uae_s64 quot, rem; + if (src == 0) { + Exception (5, oldpc); + return; + } + if (extra & 0x800) { + /* signed variant */ + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + uae_s64 quot, rem; - if (extra & 0x400) { - a &= 0xffffffffu; - a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32; - } - rem = a % (uae_s64)(uae_s32)src; - quot = a / (uae_s64)(uae_s32)src; - if ((quot & UVAL64(0xffffffff80000000)) != 0 - && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) - { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); + if (extra & 0x400) { + a &= 0xffffffffu; + a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32; + } + rem = a % (uae_s64)(uae_s32)src; + quot = a / (uae_s64)(uae_s32)src; + if ((quot & UVAL64(0xffffffff80000000)) != 0 + && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) + { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = (uae_u32)rem; + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; + } } else { - if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } else { - /* unsigned */ - uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - uae_u64 quot, rem; + /* unsigned */ + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + uae_u64 quot, rem; - if (extra & 0x400) { - a &= 0xffffffffu; - a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32; + if (extra & 0x400) { + a &= 0xffffffffu; + a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32; + } + rem = a % (uae_u64)src; + quot = a / (uae_u64)src; + if (quot > 0xffffffffu) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = (uae_u32)rem; + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; + } } - rem = a % (uae_u64)src; - quot = a / (uae_u64)src; - if (quot > 0xffffffffu) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } #else - if (src == 0) { - Exception (5, oldpc); - return; - } - if (extra & 0x800) { - /* signed variant */ - uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - uae_s32 hi = lo < 0 ? -1 : 0; - uae_s32 save_high; - uae_u32 quot, rem; - uae_u32 sign; + if (src == 0) { + Exception (5, oldpc); + return; + } + if (extra & 0x800) { + /* signed variant */ + uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + uae_s32 hi = lo < 0 ? -1 : 0; + uae_s32 save_high; + uae_u32 quot, rem; + uae_u32 sign; - if (extra & 0x400) { - hi = (uae_s32)m68k_dreg(regs, extra & 7); - } - save_high = hi; - sign = (hi ^ src); - if (hi < 0) { - hi = ~hi; - lo = -lo; - if (lo == 0) hi++; - } - if ((uae_s32)src < 0) src = -src; - if (div_unsigned(hi, lo, src, ", &rem) || - (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); + if (extra & 0x400) { + hi = (uae_s32)m68k_dreg(regs, extra & 7); + } + save_high = hi; + sign = (hi ^ src); + if (hi < 0) { + hi = ~hi; + lo = -lo; + if (lo == 0) hi++; + } + if ((uae_s32)src < 0) src = -src; + if (div_unsigned(hi, lo, src, ", &rem) || + (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + if (sign & 0x80000000) quot = -quot; + if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; + } } else { - if (sign & 0x80000000) quot = -quot; - if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } else { - /* unsigned */ - uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - uae_u32 hi = 0; - uae_u32 quot, rem; + /* unsigned */ + uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + uae_u32 hi = 0; + uae_u32 quot, rem; - if (extra & 0x400) { - hi = (uae_u32)m68k_dreg(regs, extra & 7); + if (extra & 0x400) { + hi = (uae_u32)m68k_dreg(regs, extra & 7); + } + if (div_unsigned(hi, lo, src, ", &rem)) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; + } } - if (div_unsigned(hi, lo, src, ", &rem)) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } #endif } -#if !defined(uae_s64) -static inline void +static __inline__ void mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) { uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff); @@ -851,314 +1079,164 @@ mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) *dst_lo = lo; *dst_hi = r3; } -#endif -void m68k_mull (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra) +void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra) { #if defined(uae_s64) - if (extra & 0x800) { - /* signed variant */ - uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + if (extra & 0x800) { + /* signed variant */ + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - a *= (uae_s64)(uae_s32)src; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (a == 0); - SET_NFLG (a < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = a >> 32; - else if ((a & UVAL64(0xffffffff80000000)) != 0 - && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) - { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; - } else { - /* unsigned */ - uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + a *= (uae_s64)(uae_s32)src; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (a == 0); + SET_NFLG (a < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = a >> 32; + else if ((a & UVAL64(0xffffffff80000000)) != 0 + && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) + { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; + } else { + /* unsigned */ + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - a *= (uae_u64)src; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (a == 0); - SET_NFLG (((uae_s64)a) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = a >> 32; - else if ((a & UVAL64(0xffffffff00000000)) != 0) { - SET_VFLG (1); + a *= (uae_u64)src; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (a == 0); + SET_NFLG (((uae_s64)a) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = a >> 32; + else if ((a & UVAL64(0xffffffff00000000)) != 0) { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; } - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; - } #else - if (extra & 0x800) { - /* signed variant */ - uae_s32 src1,src2; - uae_u32 dst_lo,dst_hi; - uae_u32 sign; + if (extra & 0x800) { + /* signed variant */ + uae_s32 src1,src2; + uae_u32 dst_lo,dst_hi; + uae_u32 sign; - src1 = (uae_s32)src; - src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - sign = (src1 ^ src2); - if (src1 < 0) src1 = -src1; - if (src2 < 0) src2 = -src2; - mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo); - if (sign & 0x80000000) { - dst_hi = ~dst_hi; - dst_lo = -dst_lo; - if (dst_lo == 0) dst_hi++; - } - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (dst_hi == 0 && dst_lo == 0); - SET_NFLG (((uae_s32)dst_hi) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = dst_hi; - else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) - && ((dst_hi & 0xffffffff) != 0xffffffff - || (dst_lo & 0x80000000) != 0x80000000)) - { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; - } else { - /* unsigned */ - uae_u32 dst_lo,dst_hi; + src1 = (uae_s32)src; + src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + sign = (src1 ^ src2); + if (src1 < 0) src1 = -src1; + if (src2 < 0) src2 = -src2; + mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo); + if (sign & 0x80000000) { + dst_hi = ~dst_hi; + dst_lo = -dst_lo; + if (dst_lo == 0) dst_hi++; + } + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (dst_hi == 0 && dst_lo == 0); + SET_NFLG (((uae_s32)dst_hi) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = dst_hi; + else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) + && ((dst_hi & 0xffffffff) != 0xffffffff + || (dst_lo & 0x80000000) != 0x80000000)) + { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; + } else { + /* unsigned */ + uae_u32 dst_lo,dst_hi; - mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo); + mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo); - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (dst_hi == 0 && dst_lo == 0); - SET_NFLG (((uae_s32)dst_hi) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = dst_hi; - else if (dst_hi != 0) { - SET_VFLG (1); + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (dst_hi == 0 && dst_lo == 0); + SET_NFLG (((uae_s32)dst_hi) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = dst_hi; + else if (dst_hi != 0) { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; } - m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; - } #endif } +static const char* ccnames[] = +{ "T ","F ","HI","LS","CC","CS","NE","EQ", + "VC","VS","PL","MI","GE","LT","GT","LE" }; // If value is greater than zero, this means we are still processing an EmulOp // because the counter is incremented only in m68k_execute(), i.e. interpretive // execution only -#ifdef USE_JIT static int m68k_execute_depth = 0; -#endif void m68k_reset (void) { - regs.s = 1; - regs.m = 0; - regs.stopped = 0; - regs.t1 = 0; - regs.t0 = 0; - SET_ZFLG (0); - SET_XFLG (0); - SET_CFLG (0); - SET_VFLG (0); - SET_NFLG (0); - SPCFLAGS_INIT( 0 ); - regs.intmask = 7; - regs.vbr = regs.sfc = regs.dfc = 0; + m68k_areg (regs, 7) = 0x2000; + m68k_setpc (ROMBaseMac + 0x2a); + fill_prefetch_0 (); + regs.s = 1; + regs.m = 0; + regs.stopped = 0; + regs.t1 = 0; + regs.t0 = 0; + SET_ZFLG (0); + SET_XFLG (0); + SET_CFLG (0); + SET_VFLG (0); + SET_NFLG (0); + SPCFLAGS_INIT( 0 ); + regs.intmask = 7; + regs.vbr = regs.sfc = regs.dfc = 0; + fpu_reset(); - // need to ensure the following order of initialization is correct - // (it is definitely better than what it was before this commit - // since it was reading from 0x00000000 in User mode and with active MMU) - mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */ - m68k_areg (regs, 7) = phys_get_long(0x00000000); - m68k_setpc (phys_get_long(0x00000004)); - fill_prefetch_0 (); - - /* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init() - regs.fpcr = regs.fpsr = regs.fpiar = 0; */ - fpu_reset(); - // MMU - mmu_reset(); - mmu_set_super(1); - // Cache - regs.cacr = 0; - regs.caar = 0; -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER log_ptr = 0; - memset(frlog, 0, sizeof(frlog)); + memset(log, 0, sizeof(log)); +#endif + +#if ENABLE_MON + static bool first_time = true; + if (first_time) { + first_time = false; + mon_add_command("regs", dump_regs, "regs Dump m68k emulator registers\n"); +#if FLIGHT_RECORDER + // Install "log" command in mon + mon_add_command("log", dump_log, "log Dump m68k emulation log\n"); +#endif + } #endif } void m68k_emulop_return(void) { SPCFLAGS_SET( SPCFLAG_BRK ); - quit_program = 1; -} - -static void save_regs(struct M68kRegisters &r) -{ - int i; - - for (i=0; i<8; i++) { - r.d[i] = m68k_dreg(regs, i); - r.a[i] = m68k_areg(regs, i); - } - r.pc = m68k_getpc(); - MakeSR(); - r.sr = regs.sr; - r.isp = regs.isp; - r.usp = regs.usp; - r.msp = regs.msp; - if ((r.sr & 0x2000) == 0) - r.usp = r.a[7]; - else if ((r.sr & 0x1000) != 0) - r.msp = r.a[7]; - else - r.isp = r.a[7]; -} - -static void restore_regs(struct M68kRegisters &r) -{ - int i; - - for (i=0; i<8; i++) { - m68k_dreg(regs, i) = r.d[i]; - m68k_areg(regs, i) = r.a[i]; - } - regs.isp = r.isp; - regs.usp = r.usp; - regs.msp = r.msp; - regs.sr = r.sr; - MakeFromSR(); + quit_program = true; } void m68k_emulop(uae_u32 opcode) { struct M68kRegisters r; - save_regs(r); + int i; + + for (i=0; i<8; i++) { + r.d[i] = m68k_dreg(regs, i); + r.a[i] = m68k_areg(regs, i); + } + MakeSR(); + r.sr = regs.sr; EmulOp(opcode, &r); - restore_regs(r); -} - -// void m68k_natfeat_id(void) -// { -// struct M68kRegisters r; - -// /* is it really necessary to save all registers? */ -// save_regs(r); - -// memptr stack = r.a[7] + 4; /* skip return address */ -// r.d[0] = nf_get_id(stack); - -// restore_regs(r); -// } - -// void m68k_natfeat_call(void) -// { -// struct M68kRegisters r; - -// /* is it really necessary to save all registers? */ -// save_regs(r); - -// memptr stack = r.a[7] + 4; /* skip return address */ -// bool isSupervisorMode = ((r.sr & 0x2000) == 0x2000); -// r.d[0] = nf_call(stack, isSupervisorMode); - -// restore_regs(r); -// } - -static int m68k_call(uae_u32 pc) -{ - VOLATILE int exc = 0; - m68k_setpc(pc); - TRY(prb) { -#ifdef USE_JIT - if (bx_options.jit.jit) { - exec_nostats(); - // m68k_do_compile_execute(); - // The above call to m68k_do_compile_execute fails with BadAccess in sigsegv_handler (MAC, if it is executed after the first compile_block) - // (NULL pointer to addr_instr). - // Call exec_nostats avoids calling compile_block, because stack modification is only temporary - // which will fill up compile cache with BOGUS data. - // we can call exec_nostats directly, do our code, and return back here. - } - else -#endif - m68k_do_execute(); - } - CATCH(prb) { - exc = int(prb); - } - return exc; -} - -static uae_u32 m68k_alloca(int size) -{ - uae_u32 sp = (m68k_areg(regs, 7) - size) & ~1; - m68k_areg(regs, 7) = sp; - if ((regs.sr & 0x2000) == 0) - regs.usp = sp; - else if ((regs.sr & 0x1000) != 0) - regs.msp = sp; - else - regs.isp = sp; - return sp; -} - -// uae_u32 linea68000(volatile uae_u16 opcode) -// { -// sigjmp_buf jmp; -// struct M68kRegisters r; -// volatile uae_u32 abase = 0; - -// SAVE_EXCEPTION; -// save_regs(r); - -// const int sz = 8 + sizeof(void *); -// volatile uae_u32 sp = 0; -// uae_u32 backup[(sz + 3) / 4]; - -// if (sigsetjmp(jmp, 1) == 0) -// { -// void *p = jmp; -// uae_u8 *sp_p; -// int exc; - -// sp = m68k_alloca(sz); -// memcpy(backup, phys_get_real_address(sp), sz); - -// WriteHWMemInt16(sp, opcode); -// WriteHWMemInt16(sp + 2, 0xa0ff); -// WriteHWMemInt32(sp + 4, 13); -// sp_p = phys_get_real_address(sp + 8); -// *((void **)sp_p) = p; -// if ((exc = m68k_call(sp)) != 0) -// { -// panicbug("exception %d in LINEA", exc); -// m68k_dreg(regs, 0) = 0; -// } -// } else -// { -// abase = m68k_dreg(regs, 0); -// } - -// if (sp) { -// memcpy(phys_get_real_address(sp), backup, sz); -// } -// restore_regs(r); -// m68k_setpc(r.pc); -// RESTORE_EXCEPTION; -// return abase; -// } - - -static void rts68000() -{ - uae_u32 SP = m68k_getpc() + 6; - sigjmp_buf *p; - uae_u8 *sp_p = phys_get_real_address(SP); - - p = (sigjmp_buf *)(*((void **)sp_p)); - SP += sizeof(void *); - m68k_areg(regs, 7) = SP; - siglongjmp(*p, 1); + for (i=0; i<8; i++) { + m68k_dreg(regs, i) = r.d[i]; + m68k_areg(regs, i) = r.a[i]; + } + regs.sr = r.sr; + MakeFromSR(); } void REGPARAM2 op_illg (uae_u32 opcode) @@ -1166,17 +1244,6 @@ void REGPARAM2 op_illg (uae_u32 opcode) uaecptr pc = m68k_getpc (); if ((opcode & 0xF000) == 0xA000) { - // if (opcode == 0xa0ff) - // { - // uae_u32 call = ReadHWMemInt32(pc + 2); - // switch (call) - // { - // case 13: - // rts68000(); - // return; - // } - // m68k_setpc(pc + 6); - // } Exception(0xA,0); return; } @@ -1186,8 +1253,8 @@ void REGPARAM2 op_illg (uae_u32 opcode) return; } - D(bug("Illegal instruction: %04x at %08x", opcode, pc)); -#if defined(USE_JIT) && defined(JIT_DEBUG) + write_log ("Illegal instruction: %04x at %08x\n", opcode, pc); +#if USE_JIT && JIT_DEBUG compiler_dumpstate(); #endif @@ -1195,115 +1262,59 @@ void REGPARAM2 op_illg (uae_u32 opcode) return; } +void mmu_op(uae_u32 opcode, uae_u16 extra) +{ + if ((opcode & 0xFE0) == 0x0500) { + /* PFLUSH */ + mmusr = 0; + } else if ((opcode & 0x0FD8) == 0x548) { + /* PTEST */ + } else + op_illg (opcode); +} + +static int n_insns = 0, n_spcinsns = 0; + static uaecptr last_trace_ad = 0; static void do_trace (void) { - if (regs.t0) { - uae_u16 opcode; - /* should also include TRAP, CHK, SR modification FPcc */ - /* probably never used so why bother */ - /* We can afford this to be inefficient... */ - m68k_setpc (m68k_getpc ()); - fill_prefetch_0 (); - opcode = get_word(m68k_getpc()); - if (opcode == 0x4e72 /* RTE */ - || opcode == 0x4e74 /* RTD */ - || opcode == 0x4e75 /* RTS */ - || opcode == 0x4e77 /* RTR */ - || opcode == 0x4e76 /* TRAPV */ - || (opcode & 0xffc0) == 0x4e80 /* JSR */ - || (opcode & 0xffc0) == 0x4ec0 /* JMP */ - || (opcode & 0xff00) == 0x6100 /* BSR */ - || ((opcode & 0xf000) == 0x6000 /* Bcc */ - && cctrue((opcode >> 8) & 0xf)) - || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ - && !cctrue((opcode >> 8) & 0xf) - && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) - { - last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); + if (regs.t0 && CPUType >= 2) { + uae_u16 opcode; + /* should also include TRAP, CHK, SR modification FPcc */ + /* probably never used so why bother */ + /* We can afford this to be inefficient... */ + m68k_setpc (m68k_getpc ()); + fill_prefetch_0 (); + opcode = get_word(m68k_getpc()); + if (opcode == 0x4e72 /* RTE */ + || opcode == 0x4e74 /* RTD */ + || opcode == 0x4e75 /* RTS */ + || opcode == 0x4e77 /* RTR */ + || opcode == 0x4e76 /* TRAPV */ + || (opcode & 0xffc0) == 0x4e80 /* JSR */ + || (opcode & 0xffc0) == 0x4ec0 /* JMP */ + || (opcode & 0xff00) == 0x6100 /* BSR */ + || ((opcode & 0xf000) == 0x6000 /* Bcc */ + && cctrue((opcode >> 8) & 0xf)) + || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ + && !cctrue((opcode >> 8) & 0xf) + && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) + { + last_trace_ad = m68k_getpc (); + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); + } + } else if (regs.t1) { + last_trace_ad = m68k_getpc (); + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } - } else if (regs.t1) { - last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); - } } -// #define SERVE_VBL_MFP(resetStop) \ -// { \ -// if (SPCFLAGS_TEST( SPCFLAG_INT3|SPCFLAG_VBL|SPCFLAG_INT5|SPCFLAG_SCC|SPCFLAG_MFP )) { \ -// if (SPCFLAGS_TEST( SPCFLAG_INT3 )) { \ -// if (3 > regs.intmask) { \ -// Interrupt(3); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_INT3 ); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_VBL )) { \ -// if (4 > regs.intmask) { \ -// Interrupt(4); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_VBL ); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_INT5 )) { \ -// if (5 > regs.intmask) { \ -// Interrupt(5); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_INT5 ); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_SCC )) { \ -// if (5 > regs.intmask) { \ -// int vector_number=SCCdoInterrupt(); \ -// if(vector_number){ \ -// SCCInterrupt(vector_number); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_SCC); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// else \ -// SPCFLAGS_CLEAR( SPCFLAG_SCC ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_MFP )) { \ -// if (6 > regs.intmask) { \ -// int vector_number = MFPdoInterrupt(); \ -// if (vector_number) { \ -// MFPInterrupt(vector_number); \ -// regs.stopped = 0; \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// else \ -// SPCFLAGS_CLEAR( SPCFLAG_MFP ); \ -// } \ -// } \ -// } \ -// } - -// #define SERVE_INTERNAL_IRQ() \ -// { \ -// if (SPCFLAGS_TEST( SPCFLAG_INTERNAL_IRQ )) { \ -// SPCFLAGS_CLEAR( SPCFLAG_INTERNAL_IRQ ); \ -// invoke200HzInterrupt(); \ -// } \ -// } - -int m68k_do_specialties(void) +int m68k_do_specialties (void) { - // SERVE_INTERNAL_IRQ(); -#ifdef USE_JIT +#if USE_JIT // Block was compiled SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE ); @@ -1314,35 +1325,11 @@ int m68k_do_specialties(void) if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN )) SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN ); #endif - /*n_spcinsns++;*/ + if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { Exception (9,last_trace_ad); } -#if 0 /* not for ARAnyM; emulating 040 only */ - if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) { - // 68000/68010 undocumented special case: - // if STOP clears S-bit and T was not set: - // cause privilege violation exception, PC pointing to following instruction. - // If T was set before STOP: STOP works as documented. - m68k_unset_stop(); - Exception(8, 0); - } -#endif while (SPCFLAGS_TEST( SPCFLAG_STOP )) { - //TODO: Check - if ((regs.sr & 0x700) == 0x700) - { - // panicbug("STOPed with interrupts disabled, exiting; pc=$%08x", m68k_getpc()); - m68k_dumpstate (stderr, NULL); -#if 0 - quit_program = 1; -#endif -#ifdef FULL_HISTORY - ndebug::showHistory(20, false); - m68k_dumpstate (stderr, NULL); -#endif - return 1; - } if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); int intr = intlev (); @@ -1352,17 +1339,10 @@ int m68k_do_specialties(void) SPCFLAGS_CLEAR( SPCFLAG_STOP ); } } - - // SERVE_INTERNAL_IRQ(); - // SERVE_VBL_MFP(true); - if (SPCFLAGS_TEST( SPCFLAG_BRK )) - break; } if (SPCFLAGS_TEST( SPCFLAG_TRACE )) do_trace (); - // SERVE_VBL_MFP(false); - if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { SPCFLAGS_CLEAR( SPCFLAG_DOINT ); int intr = intlev (); @@ -1371,213 +1351,159 @@ int m68k_do_specialties(void) regs.stopped = 0; } } - if (SPCFLAGS_TEST( SPCFLAG_INT )) { SPCFLAGS_CLEAR( SPCFLAG_INT ); SPCFLAGS_SET( SPCFLAG_DOINT ); } - - if (SPCFLAGS_TEST( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ )) { - SPCFLAGS_CLEAR( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ ); + if (SPCFLAGS_TEST( SPCFLAG_BRK )) { + SPCFLAGS_CLEAR( SPCFLAG_BRK ); return 1; } - return 0; } void m68k_do_execute (void) { - uae_u32 pc; - uae_u32 opcode; - for (;;) { - regs.fault_pc = pc = m68k_getpc(); -#ifdef FULL_HISTORY -#ifdef NEED_TO_DEBUG_BADLY - history[lasthist] = regs; - historyf[lasthist] = regflags; -#else - history[lasthist] = m68k_getpc(); + for (;;) { + uae_u32 opcode = GET_OPCODE; +#if FLIGHT_RECORDER + m68k_record_step(m68k_getpc()); #endif - if (++lasthist == MAX_HIST) lasthist = 0; - if (lasthist == firsthist) { - if (++firsthist == MAX_HIST) firsthist = 0; + (*cpufunctbl[opcode])(opcode); + cpu_check_ticks(); + if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { + if (m68k_do_specialties()) + return; + } } -#endif - -#ifndef FULLMMU -#ifdef ARAM_PAGE_CHECK - if (((pc ^ pc_page) > ARAM_PAGE_MASK)) { - check_ram_boundary(pc, 2, false); - pc_page = pc; - pc_offset = (uintptr)get_real_address(pc, 0, sz_word) - pc; - } -#else - check_ram_boundary(pc, 2, false); -#endif -#endif - opcode = GET_OPCODE; -#ifdef FLIGHT_RECORDER - m68k_record_step(m68k_getpc(), opcode); -#endif - (*cpufunctbl[opcode])(opcode); - cpu_check_ticks(); - regs.fault_pc = m68k_getpc(); - - if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { - if (m68k_do_specialties()) - return; - } - } } void m68k_execute (void) { -#ifdef USE_JIT - m68k_execute_depth++; +#if USE_JIT + ++m68k_execute_depth; #endif -#ifdef DEBUGGER - VOLATILE bool after_exception = false; -#endif - -setjmpagain: - TRY(prb) { for (;;) { - if (quit_program > 0) { - if (quit_program == 1) { -#ifdef FLIGHT_RECORDER - dump_flight_recorder(); + if (quit_program) + break; + m68k_do_execute(); + } +#if USE_JIT + --m68k_execute_depth; #endif - break; +} + +static void m68k_verify (uaecptr addr, uaecptr *nextpc) +{ + uae_u32 opcode, val; + struct instr *dp; + + opcode = get_iword_1(0); + last_op_for_exception_3 = opcode; + m68kpc_offset = 2; + + if (cpufunctbl[cft_map (opcode)] == op_illg_1) { + opcode = 0x4AFC; + } + dp = table68k + opcode; + + if (dp->suse) { + if (!verify_ea (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, &val)) { + Exception (3, 0); + return; } - quit_program = 0; - m68k_reset (); - } -#ifdef DEBUGGER - if (debugging && !after_exception) debug(); - after_exception = false; -#endif - m68k_do_execute(); } - } - CATCH(prb) { - Exception(prb, 0); -#ifdef DEBUGGER - after_exception = true; -#endif - goto setjmpagain; - } - -#ifdef USE_JIT - m68k_execute_depth--; -#endif -} - -void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) -{ -#ifdef HAVE_DISASM_M68K - char buf[256]; - int size; - - disasm_info.memory_vma = addr; - while (cnt-- > 0) { - size = m68k_disasm_to_buf(&disasm_info, buf); - fprintf(f, "%s\n", buf); - if (size < 0) - break; + if (dp->duse) { + if (!verify_ea (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, &val)) { + Exception (3, 0); + return; + } } - if (nextpc) - *nextpc = disasm_info.memory_vma; -#else - if (nextpc) - *nextpc = addr; - (void) f; - (void) cnt; -#endif } -#ifdef DEBUGGER -void newm68k_disasm(FILE *f, uaecptr addr, uaecptr *nextpc, unsigned int cnt) +void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt) { -#ifdef HAVE_DISASM_M68K - char buf[256]; + uaecptr newpc = 0; + m68kpc_offset = addr - m68k_getpc (); + while (cnt-- > 0) { + char instrname[20],*ccpt; + int opwords; + uae_u32 opcode; + struct mnemolookup *lookup; + struct instr *dp; + printf ("%08lx: ", m68k_getpc () + m68kpc_offset); + for (opwords = 0; opwords < 5; opwords++){ + printf ("%04x ", get_iword_1 (m68kpc_offset + opwords*2)); + } + opcode = get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + if (cpufunctbl[cft_map (opcode)] == op_illg_1) { + opcode = 0x4AFC; + } + dp = table68k + opcode; + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) + ; - disasm_info.memory_vma = addr; - if (cnt == 0) { - m68k_disasm_to_buf(&disasm_info, buf); - } else { - while (cnt-- > 0) { - m68k_disasm_to_buf(&disasm_info, buf); - fprintf(f, "%s\n", buf); - } - } - if (nextpc) - *nextpc = disasm_info.memory_vma; -#else - if (nextpc) - *nextpc = addr; - (void) cnt; -#endif + strcpy (instrname, lookup->name); + ccpt = strstr (instrname, "cc"); + if (ccpt != 0) { + strncpy (ccpt, ccnames[dp->cc], 2); + } + printf ("%s", instrname); + switch (dp->size){ + case sz_byte: printf (".B "); break; + case sz_word: printf (".W "); break; + case sz_long: printf (".L "); break; + default: printf (" "); break; + } + + if (dp->suse) { + newpc = m68k_getpc () + m68kpc_offset; + newpc += ShowEA (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); + } + if (dp->suse && dp->duse) + printf (","); + if (dp->duse) { + newpc = m68k_getpc () + m68kpc_offset; + newpc += ShowEA (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 0); + } + if (ccpt != 0) { + if (cctrue(dp->cc)) + printf (" == %08x (TRUE)", newpc); + else + printf (" == %08x (FALSE)", newpc); + } else if ((opcode & 0xff00) == 0x6100) /* BSR */ + printf (" == %08x", newpc); + printf ("\n"); + } + if (nextpc) + *nextpc = m68k_getpc () + m68kpc_offset; } -#endif /* DEBUGGER */ - -#ifdef FULL_HISTORY -void showDisasm(uaecptr addr) { -#ifdef HAVE_DISASM_M68K - char buf[256]; - - disasm_info.memory_vma = addr; - m68k_disasm_to_buf(&disasm_info, buf); - bug("%s", buf); -#else - (void) addr; -#endif -} -#endif /* FULL_HISTORY */ - -void m68k_dumpstate (FILE *out, uaecptr *nextpc) +void m68k_dumpstate (uaecptr *nextpc) { - int i; - for (i = 0; i < 8; i++){ - fprintf (out, "D%d: %08lx ", i, (unsigned long)m68k_dreg(regs, i)); - if ((i & 3) == 3) fprintf (out, "\n"); - } - for (i = 0; i < 8; i++){ - fprintf (out, "A%d: %08lx ", i, (unsigned long)m68k_areg(regs, i)); - if ((i & 3) == 3) fprintf (out, "\n"); - } - if (regs.s == 0) regs.usp = m68k_areg(regs, 7); - if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); - if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); - fprintf (out, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", - (unsigned long)regs.usp, (unsigned long)regs.isp, - (unsigned long)regs.msp, (unsigned long)regs.vbr); - fprintf (out, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d TCE=%d TCP=%d\n", - regs.t1, regs.t0, regs.s, regs.m, - (int)GET_XFLG, (int)GET_NFLG, (int)GET_ZFLG, (int)GET_VFLG, (int)GET_CFLG, regs.intmask, - regs.mmu_enabled, regs.mmu_pagesize_8k); - fprintf (out, "CACR=%08lx CAAR=%08lx URP=%08lx SRP=%08lx\n", - (unsigned long)regs.cacr, - (unsigned long)regs.caar, - (unsigned long)regs.urp, - (unsigned long)regs.srp); - fprintf (out, "DTT0=%08lx DTT1=%08lx ITT0=%08lx ITT1=%08lx\n", - (unsigned long)regs.dtt0, - (unsigned long)regs.dtt1, - (unsigned long)regs.itt0, - (unsigned long)regs.itt1); - for (i = 0; i < 8; i++){ - fprintf (out, "FP%d: %g ", i, (double)fpu.registers[i]); - if ((i & 3) == 3) fprintf (out, "\n"); - } -#if 0 - fprintf (out, "N=%d Z=%d I=%d NAN=%d\n", - (regs.fpsr & 0x8000000) != 0, - (regs.fpsr & 0x4000000) != 0, - (regs.fpsr & 0x2000000) != 0, - (regs.fpsr & 0x1000000) != 0); -#endif - m68k_disasm(out, m68k_getpc (), nextpc, 1); - if (nextpc) - fprintf (out, "next PC: %08lx\n", (unsigned long)*nextpc); + int i; + for (i = 0; i < 8; i++){ + printf ("D%d: %08x ", i, m68k_dreg(regs, i)); + if ((i & 3) == 3) printf ("\n"); + } + for (i = 0; i < 8; i++){ + printf ("A%d: %08x ", i, m68k_areg(regs, i)); + if ((i & 3) == 3) printf ("\n"); + } + if (regs.s == 0) regs.usp = m68k_areg(regs, 7); + if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); + if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); + printf ("USP=%08x ISP=%08x MSP=%08x VBR=%08x\n", + regs.usp,regs.isp,regs.msp,regs.vbr); + printf ("T=%d%d S=%d M=%d X=%ld N=%ld Z=%ld V=%ld C=%ld IMASK=%d\n", + regs.t1, regs.t0, regs.s, regs.m, + GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); + + fpu_dump_registers(); + fpu_dump_flags(); + + m68k_disasm(m68k_getpc (), nextpc, 1); + if (nextpc) + printf ("next PC: %08x\n", *nextpc); } diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index 13a51b82..97731f59 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -1,51 +1,41 @@ /* - * newcpu.h - CPU emulation + * UAE - The Un*x Amiga Emulator * - * Copyright (c) 2009 ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * MC68000 emulation * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * Copyright 1995 Bernd Schmidt * - * ARAnyM is free software; you can redistribute it and/or modify + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * ARAnyM is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * Copyright 1995 Bernd Schmidt - */ #ifndef NEWCPU_H #define NEWCPU_H -#include "sysdeps.h" -#include "registers.h" -#include "spcflags.h" +#ifndef FLIGHT_RECORDER +#define FLIGHT_RECORDER 0 +#endif + #include "m68k.h" -#include "memory.h" +#include "readcpu.h" +#include "spcflags.h" -# include +#if ENABLE_MON +#include "mon.h" +#include "mon_disass.h" +#endif -extern struct fixup { - int flag; - uae_u32 reg; - uaecptr value; -}fixup; extern int areg_byteinc[]; extern int imm8_table[]; @@ -67,25 +57,27 @@ extern int broken_in; #endif #define cpuop_begin() do { cpuop_tag("begin"); } while (0) -#define cpuop_end() do { cpuop_tag("end"); } while (0) +#define cpuop_end() do { cpuop_tag("end"); } while (0) typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM; - + struct cputbl { cpuop_func *handler; uae_u16 specific; uae_u16 opcode; }; -extern cpuop_func *cpufunctbl[65536]; +extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl"); -#ifdef USE_JIT +#if USE_JIT typedef void compop_func (uae_u32) REGPARAM; +//NOTE: The "opcode" and "specific" fields were switched in the original source code! + struct comptbl { compop_func *handler; - uae_u32 opcode; - uae_u32 specific; + uae_u32 opcode; + uae_u32 specific; #define COMP_OPCODE_ISJUMP 0x0001 #define COMP_OPCODE_LONG_OPCODE 0x0002 #define COMP_OPCODE_CMOV 0x0004 @@ -96,84 +88,151 @@ struct comptbl { #endif extern void REGPARAM2 op_illg (uae_u32) REGPARAM; +extern void m68k_dumpstate(uaecptr *nextpc); + +typedef char flagtype; + +// struct regstruct { +// uae_u32 regs[16]; + +// uae_u32 pc; +// uae_u8 * pc_p; +// uae_u8 * pc_oldp; + +// spcflags_t spcflags; +// int intmask; + +// uae_u32 vbr, sfc, dfc; +// uaecptr usp, isp, msp; +// uae_u16 sr; +// flagtype t1; +// flagtype t0; +// flagtype s; +// flagtype m; +// flagtype x; +// flagtype stopped; + +// #if USE_PREFETCH_BUFFER +// /* Fellow sources say this is 4 longwords. That's impossible. It needs +// * to be at least a longword. The HRM has some cryptic comment about two +// * instructions being on the same longword boundary. +// * The way this is implemented now seems like a good compromise. +// */ +// uae_u32 prefetch; +// #endif +// }; + +struct regstruct +{ + uae_u32 regs[16]; + uaecptr usp,isp,msp; + uae_u16 sr; + flagtype t1; + flagtype t0; + flagtype s; + flagtype m; + flagtype x; + flagtype stopped; + int intmask; + + uae_u32 pc; + uae_u32 fault_pc; + uae_u8 *pc_p; + uae_u8 *pc_oldp; + + uae_u32 vbr,sfc,dfc; + + volatile uae_u32 spcflags; + +#if 1 + uae_u32 kick_mask; + + /* Fellow sources say this is 4 longwords. That's impossible. It needs + * to be at least a longword. The HRM has some cryptic comment about two + * instructions being on the same longword boundary. + * The way this is implemented now seems like a good compromise. + */ + uae_u32 prefetch; +#endif + + /* MMU reg*/ + uae_u32 urp,srp; + uae_u32 tc; + + int mmu_enabled; /* flagtype tce; */ + int mmu_pagesize_8k; /* flagtype tcp; */ + + uae_u32 dtt0,dtt1,itt0,itt1; + uae_u32 mmusr; + + uae_u32 mmu_fslw, mmu_fault_addr; + uae_u16 mmu_ssw; + uae_u32 wb3_data; + uae_u16 wb3_status; + + /* Cache reg*/ + uae_u32 cacr,caar; +}; + +extern regstruct regs, lastint_regs; #define m68k_dreg(r,num) ((r).regs[(num)]) #define m68k_areg(r,num) (((r).regs + 8)[(num)]) -#ifdef FULLMMU -static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o) -{ - return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte); -} -static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o) -{ - return mmu_get_word(m68k_getpc() + o, 0, sz_word); -} -static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o) -{ - uaecptr addr = m68k_getpc() + o; - - if (unlikely(is_unaligned(addr, 4))) - return mmu_get_long_unaligned(addr, 0); - return mmu_get_long(addr, 0, sz_long); -} +#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1)) +#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o))) +#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o))) +#ifdef HAVE_GET_WORD_UNSWAPPED +#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p)) #else -#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1)) -#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o))) -#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o))) +#define GET_OPCODE (get_iword (0)) #endif -#if 0 -static inline uae_u32 get_ibyte_prefetch (uae_s32 o) +#if USE_PREFETCH_BUFFER +static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1)); + return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1)); return do_get_mem_byte((uae_u8 *)(((uae_u8 *)®s.prefetch) + o + 1)); } -static inline uae_u32 get_iword_prefetch (uae_s32 o) +static __inline__ uae_u32 get_iword_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_word((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + o)); + return do_get_mem_word((uae_u16 *)(regs.pc_p + o)); return do_get_mem_word((uae_u16 *)(((uae_u8 *)®s.prefetch) + o)); } -static inline uae_u32 get_ilong_prefetch (uae_s32 o) +static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_long((uae_u32 *)(do_get_real_address(regs.pcp, false, false) + o)); + return do_get_mem_long((uae_u32 *)(regs.pc_p + o)); if (o == 0) return do_get_mem_long(®s.prefetch); - return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + 4)); + return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4)); } #endif -#ifdef FULLMMU -#define m68k_incpc(o) (regs.pc += (o)) -#else -#define m68k_incpc(o) (regs.pc_p += (o)) -#endif - -static inline void fill_prefetch_0 (void) +static __inline__ void fill_prefetch_0 (void) { #if USE_PREFETCH_BUFFER uae_u32 r; #ifdef UNALIGNED_PROFITABLE - r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false); + r = *(uae_u32 *)regs.pc_p; regs.prefetch = r; #else - r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false)); + r = do_get_mem_long ((uae_u32 *)regs.pc_p); do_put_mem_long (®s.prefetch, r); #endif #endif } #if 0 -static inline void fill_prefetch_2 (void) +static __inline__ void fill_prefetch_2 (void) { uae_u32 r = do_get_mem_long (®s.prefetch) << 16; - uae_u32 r2 = do_get_mem_word (((uae_u16 *)do_get_real_address(regs.pcp, false, false)) + 1); + uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1); r |= r2; do_put_mem_long (®s.prefetch, r); } @@ -181,92 +240,115 @@ static inline void fill_prefetch_2 (void) #define fill_prefetch_2 fill_prefetch_0 #endif +static __inline__ uaecptr m68k_getpc (void) +{ +#if REAL_ADDRESSING || DIRECT_ADDRESSING + return get_virtual_address(regs.pc_p); +#else + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); +#endif +} + +static __inline__ void m68k_setpc (uaecptr newpc) +{ +#if ENABLE_MON + uae_u32 previous_pc = m68k_getpc(); +#endif + +#if REAL_ADDRESSING || DIRECT_ADDRESSING + regs.pc_p = get_real_address(newpc); +#else + regs.pc_p = regs.pc_oldp = get_real_address(newpc); + regs.pc = newpc; +#endif + +#if ENABLE_MON + if (IS_BREAK_POINT(newpc)) { + printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc); + m68k_dumpstate(NULL); + const char *arg[4] = {"mon", "-m", "-r", NULL}; + mon(3, arg); + } +#endif // end of #if ENABLE_MON +} + +static __inline__ void m68k_incpc (uae_s32 delta) +{ +#if ENABLE_MON + uae_u32 previous_pc = m68k_getpc(); +#endif + regs.pc_p += (delta); +#if ENABLE_MON + uaecptr next_pc = m68k_getpc(); + if (IS_BREAK_POINT(next_pc)) { + printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc); + m68k_dumpstate(NULL); + const char *arg[4] = {"mon", "-m", "-r", NULL}; + mon(3, arg); + } +#endif // end of #if ENABLE_MON +} + /* These are only used by the 68020/68881 code, and therefore don't * need to handle prefetch. */ -static inline uae_u32 next_ibyte (void) +static __inline__ uae_u32 next_ibyte (void) { uae_u32 r = get_ibyte (0); m68k_incpc (2); return r; } -static inline uae_u32 next_iword (void) +static __inline__ uae_u32 next_iword (void) { uae_u32 r = get_iword (0); m68k_incpc (2); return r; } -static inline uae_u32 next_ilong (void) +static __inline__ uae_u32 next_ilong (void) { uae_u32 r = get_ilong (0); m68k_incpc (4); return r; } -static inline void m68k_setpc (uaecptr newpc) -{ -#ifndef FULLMMU - regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word); -#endif - regs.fault_pc = regs.pc = newpc; -} - #define m68k_setpc_fast m68k_setpc #define m68k_setpc_bcc m68k_setpc #define m68k_setpc_rte m68k_setpc -static inline void m68k_do_rts(void) +static __inline__ void m68k_do_rts(void) { - m68k_setpc(get_long(m68k_areg(regs, 7))); - m68k_areg(regs, 7) += 4; + m68k_setpc(get_long(m68k_areg(regs, 7))); + m68k_areg(regs, 7) += 4; } -static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) +static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) { - put_long(m68k_areg(regs, 7) - 4, oldpc); - m68k_areg(regs, 7) -= 4; - m68k_incpc(offset); + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), oldpc); + m68k_incpc(offset); } -static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest) +static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest) { - put_long(m68k_areg(regs, 7) - 4, oldpc); - m68k_areg(regs, 7) -= 4; - m68k_setpc(dest); + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), oldpc); + m68k_setpc(dest); } -static inline void m68k_setstopped (int stop) +static __inline__ void m68k_setstopped (int stop) { regs.stopped = stop; /* A traced STOP instruction drops through immediately without actually stopping. */ - if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE ))) - SPCFLAGS_SET( SPCFLAG_STOP ); + if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0) + SPCFLAGS_SET( SPCFLAG_STOP ); } -#ifdef FULLMMU -# define GET_OPCODE (get_iword (0)) -#elif defined ARAM_PAGE_CHECK -# ifdef HAVE_GET_WORD_UNSWAPPED -# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset))); -# else -# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset))); -# endif -#else -# ifdef HAVE_GET_WORD_UNSWAPPED -# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word))) -# else -# define GET_OPCODE (get_iword (0)) -# endif -#endif - -extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); -extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); -extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width); -extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width); - +extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); +extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); +extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf); extern void MakeSR (void); extern void MakeFromSR (void); @@ -278,19 +360,15 @@ extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); extern void m68k_mull (uae_u32, uae_u32, uae_u16); extern void m68k_emulop (uae_u32); extern void m68k_emulop_return (void); -extern void m68k_natfeat_id(void); -extern void m68k_natfeat_call(void); extern void init_m68k (void); extern void exit_m68k (void); -extern void m68k_dumpstate (FILE *, uaecptr *); -extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int); -extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int); -extern void showDisasm(uaecptr); +extern void m68k_dumpstate (uaecptr *); +extern void m68k_disasm (uaecptr, uaecptr *, int); extern void m68k_reset (void); extern void m68k_enter_debugger(void); extern int m68k_do_specialties(void); -extern void m68k_instr_set(void); -uae_u32 linea68000(uae_u16 opcode); + +extern void mmu_op (uae_u32, uae_u16); /* Opcode of faulting instruction */ extern uae_u16 last_op_for_exception_3; @@ -301,19 +379,24 @@ extern uaecptr last_fault_for_exception_3; #define CPU_OP_NAME(a) op ## a -/* 68040+ 68881 */ -extern const struct cputbl op_smalltbl_0_ff[]; -extern const struct cputbl op_smalltbl_0_nf[]; +/* 68020 + 68881 */ +extern struct cputbl op_smalltbl_0_ff[]; +/* 68020 */ +extern struct cputbl op_smalltbl_1_ff[]; +/* 68010 */ +extern struct cputbl op_smalltbl_2_ff[]; +/* 68000 */ +extern struct cputbl op_smalltbl_3_ff[]; +/* 68000 slow but compatible. */ +extern struct cputbl op_smalltbl_4_ff[]; -#ifdef FLIGHT_RECORDER -extern void m68k_record_step(uaecptr, int); +#if FLIGHT_RECORDER +extern void m68k_record_step(uaecptr) REGPARAM; #endif - extern void m68k_do_execute(void); extern void m68k_execute(void); -#ifdef USE_JIT +#if USE_JIT extern void m68k_compile_execute(void); -extern void m68k_do_compile_execute(void); #endif #ifdef USE_CPU_EMUL_SERVICES extern int32 emulated_ticks; @@ -328,7 +411,5 @@ static inline void cpu_check_ticks(void) #define cpu_check_ticks() #define cpu_do_check_ticks() #endif - -cpuop_func op_illg_1; - + #endif /* NEWCPU_H */ diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h index d680b200..eacbc214 100644 --- a/BasiliskII/src/uae_cpu/noflags.h +++ b/BasiliskII/src/uae_cpu/noflags.h @@ -33,13 +33,13 @@ #define NOFLAGS_CMP 0 #undef SET_NFLG_ALWAYS -static inline void SET_NFLG_ALWAYS(uae_u32 x) +static __inline__ void SET_NFLG_ALWAYS(uae_u32 x) { SET_NFLG(x); /* This has not yet been redefined */ } #undef SET_CFLG_ALWAYS -static inline void SET_CFLG_ALWAYS(uae_u32 x) +static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) { SET_CFLG(x); /* This has not yet been redefined */ } diff --git a/BasiliskII/src/uae_cpu/readcpu.cpp b/BasiliskII/src/uae_cpu/readcpu.cpp index 1c385b98..3fccdfb7 100644 --- a/BasiliskII/src/uae_cpu/readcpu.cpp +++ b/BasiliskII/src/uae_cpu/readcpu.cpp @@ -1,27 +1,33 @@ -/* 2002 MJ */ /* * UAE - The Un*x Amiga Emulator * * Read 68000 CPU specs from file "table68k" * * Copyright 1995,1996 Bernd Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include +#include +#include + #include "sysdeps.h" #include "readcpu.h" -#include -#include -#include -#include - -using std::strncmp; -using std::abort; -using std::fprintf; -using std::strcmp; -using std::strlen; -using std::malloc; - int nr_cpuop_funcs; struct mnemolookup lookuptab[] = { @@ -147,20 +153,16 @@ struct mnemolookup lookuptab[] = { { i_CPUSHA, "CPUSHA" }, { i_MOVE16, "MOVE16" }, - { i_EMULOP_RETURN, "EMULOP_RETURN" }, - { i_EMULOP, "EMULOP" }, - + { i_EMULOP_RETURN, "EMULOP_RETURN" }, + { i_EMULOP, "EMULOP" }, + { i_MMUOP, "MMUOP" }, - - {i_NATFEAT_ID, "NATFEAT_ID" }, - {i_NATFEAT_CALL, "NATFEAT_CALL" }, - { i_ILLG, "" }, }; struct instr *table68k; -static inline amodes mode_from_str (const char *str) +static __inline__ amodes mode_from_str (const char *str) { if (strncmp (str, "Dreg", 4) == 0) return Dreg; if (strncmp (str, "Areg", 4) == 0) return Areg; @@ -178,7 +180,7 @@ static inline amodes mode_from_str (const char *str) return (amodes)0; } -static inline amodes mode_from_mr (int mode, int reg) +static __inline__ amodes mode_from_mr (int mode, int reg) { switch (mode) { case 0: return Dreg; @@ -213,32 +215,31 @@ static void build_insn (int insn) int i, n; int flaglive = 0, flagdead = 0; - int cflow = 0; + int cflow = 0; id = defs68k[insn]; - // Control flow information - cflow = id.cflow; - - // Mask of flags set/used - unsigned char flags_set(0), flags_used(0); - - for (i = 0, n = 4; i < 5; i++, n--) { - switch (id.flaginfo[i].flagset) { - case fa_unset: case fa_isjmp: break; - default: flags_set |= (1 << n); + // Control flow information + cflow = id.cflow; + + // Mask of flags set/used + unsigned char flags_set(0), flags_used(0); + + for (i = 0, n = 4; i < 5; i++, n--) { + switch (id.flaginfo[i].flagset) { + case fa_unset: case fa_isjmp: break; + default: flags_set |= (1 << n); + } + + switch (id.flaginfo[i].flaguse) { + case fu_unused: case fu_isjmp: break; + default: flags_used |= (1 << n); + } } - - switch (id.flaginfo[i].flaguse) { - case fu_unused: case fu_isjmp: break; - default: flags_used |= (1 << n); - } - } - + for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flagset){ case fa_unset: break; - case fa_isjmp: break; case fa_zero: flagdead |= 1 << i; break; case fa_one: flagdead |= 1 << i; break; case fa_dontcare: flagdead |= 1 << i; break; @@ -251,8 +252,6 @@ static void build_insn (int insn) for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flaguse) { case fu_unused: break; - case fu_isjmp: flaglive |= 1 << i; break; - case fu_maybecc: flaglive |= 1 << i; break; case fu_unknown: flaglive = -1; goto out2; case fu_used: flaglive |= 1 << i; break; } @@ -307,7 +306,6 @@ static void build_insn (int insn) continue; if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) continue; - if (bitcnt[bitE] && (bitval[bitE] == 0x00)) continue; @@ -348,9 +346,9 @@ static void build_insn (int insn) } } mnp++; - if ((unsigned)mnp >= (sizeof(mnemonic)-1)) { - mnemonic[sizeof(mnemonic)-1] = '\0'; - fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic); + if ((unsigned)mnp >= sizeof(mnemonic) - 1) { + mnemonic[sizeof(mnemonic) - 1] = 0; + fprintf(stderr, "Instruction %s overflow\n", mnemonic); abort(); } } @@ -381,7 +379,6 @@ static void build_insn (int insn) case 'A': srcmode = Areg; switch (opcstr[pos++]) { - case 'l': srcmode = absl; break; case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break; case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break; default: abort(); @@ -391,11 +388,9 @@ static void build_insn (int insn) case 'P': srcmode = Aipi; pos++; break; } break; -#if 0 case 'L': srcmode = absl; break; -#endif case '#': switch (opcstr[pos++]) { case 'z': srcmode = imm; break; @@ -441,7 +436,7 @@ static void build_insn (int insn) srcpos = bitpos[bitK]; } break; - case 'E': srcmode = immi; srcreg = bitval[bitE]; + case 'E': srcmode = immi; srcreg = bitval[bitE]; if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? /* 1..255 */ srcgather = 1; @@ -449,8 +444,8 @@ static void build_insn (int insn) srcpos = bitpos[bitE]; } break; - case 'p': srcmode = immi; srcreg = bitval[bitp]; - if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? + case 'p': srcmode = immi; srcreg = bitval[bitp]; + if (CPU_EMU_SIZE < 5) { /* 0..3 */ srcgather = 1; srctype = 7; @@ -587,22 +582,21 @@ static void build_insn (int insn) case 'A': destmode = Areg; switch (opcstr[pos++]) { - case 'l': destmode = absl; break; case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; - case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; + case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; default: abort(); } + if (dstpos < 0 || dstpos >= 32) + abort(); switch (opcstr[pos]) { case 'p': destmode = Apdi; pos++; break; case 'P': destmode = Aipi; pos++; break; } break; -#if 0 case 'L': destmode = absl; break; -#endif case '#': switch (opcstr[pos++]) { case 'z': destmode = imm; break; @@ -773,7 +767,7 @@ static void build_insn (int insn) table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; } #endif - + // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions if ( table68k[opc].mnemo == i_Scc || table68k[opc].mnemo == i_Bcc @@ -801,7 +795,7 @@ static void build_insn (int insn) case 15:flags_used = 0x0E; break; /* LE */ } } - + #if 1 /* gb-- flagdead and flaglive would not have correct information */ table68k[opc].flagdead = flags_set; @@ -831,7 +825,7 @@ void read_table68k (void) } } -static int readcpu_mismatch; +static int mismatch; static void handle_merges (long int opcode) { @@ -857,9 +851,9 @@ static void handle_merges (long int opcode) case 5: smsk = 63; sbitdst = 64; break; case 6: - smsk = 255; sbitdst = 256; break; + smsk = 255; sbitdst = 256; break; case 7: - smsk = 3; sbitdst = 4; break; + smsk = 3; sbitdst = 4; break; default: smsk = 0; sbitdst = 0; abort(); @@ -875,7 +869,7 @@ static void handle_merges (long int opcode) } for (srcreg=0; srcreg < sbitdst; srcreg++) { for (dstreg=0; dstreg < dstend; dstreg++) { - uae_u16 code = opcode; + uae_u16 code = uae_u16(opcode); code = (code & ~smsk) | (srcreg << table68k[opcode].spos); code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos); @@ -888,20 +882,20 @@ static void handle_merges (long int opcode) || table68k[code].suse != table68k[opcode].suse || table68k[code].duse != table68k[opcode].duse) { - readcpu_mismatch++; continue; + mismatch++; continue; } if (table68k[opcode].suse && (table68k[opcode].spos != table68k[code].spos || table68k[opcode].smode != table68k[code].smode || table68k[opcode].stype != table68k[code].stype)) { - readcpu_mismatch++; continue; + mismatch++; continue; } if (table68k[opcode].duse && (table68k[opcode].dpos != table68k[code].dpos || table68k[opcode].dmode != table68k[code].dmode)) { - readcpu_mismatch++; continue; + mismatch++; continue; } if (code != opcode) @@ -914,7 +908,7 @@ void do_merges (void) { long int opcode; int nr = 0; - readcpu_mismatch = 0; + mismatch = 0; for (opcode = 0; opcode < 65536; opcode++) { if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG) continue; @@ -926,5 +920,114 @@ void do_merges (void) int get_no_mismatches (void) { - return readcpu_mismatch; + return mismatch; +} + +const char *get_instruction_name (unsigned int opcode) +{ + struct instr *ins = &table68k[opcode]; + for (int i = 0; lookuptab[i].name[0]; i++) { + if (ins->mnemo == lookuptab[i].mnemo) + return lookuptab[i].name; + } + abort(); + return NULL; +} + +static char *get_ea_string (amodes mode, wordsizes size) +{ + static char buffer[80]; + + buffer[0] = 0; + switch (mode){ + case Dreg: + strcpy (buffer,"Dn"); + break; + case Areg: + strcpy (buffer,"An"); + break; + case Aind: + strcpy (buffer,"(An)"); + break; + case Aipi: + strcpy (buffer,"(An)+"); + break; + case Apdi: + strcpy (buffer,"-(An)"); + break; + case Ad16: + strcpy (buffer,"(d16,An)"); + break; + case Ad8r: + strcpy (buffer,"(d8,An,Xn)"); + break; + case PC16: + strcpy (buffer,"(d16,PC)"); + break; + case PC8r: + strcpy (buffer,"(d8,PC,Xn)"); + break; + case absw: + strcpy (buffer,"(xxx).W"); + break; + case absl: + strcpy (buffer,"(xxx).L"); + break; + case imm: + switch (size){ + case sz_byte: + strcpy (buffer,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + break; + + default: + break; + } + return buffer; +} + +const char *get_instruction_string (unsigned int opcode) +{ + static char out[100]; + struct instr *ins; + + strcpy (out, get_instruction_name (opcode)); + + ins = &table68k[opcode]; + if (ins->size == sz_byte) + strcat (out,".B"); + if (ins->size == sz_word) + strcat (out,".W"); + if (ins->size == sz_long) + strcat (out,".L"); + strcat (out," "); + if (ins->suse) + strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size))); + if (ins->duse) { + if (ins->suse) + strcat (out,","); + strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size))); + } + return out; } diff --git a/BasiliskII/src/uae_cpu/readcpu.h b/BasiliskII/src/uae_cpu/readcpu.h index 7855ecc7..6fba3c39 100644 --- a/BasiliskII/src/uae_cpu/readcpu.h +++ b/BasiliskII/src/uae_cpu/readcpu.h @@ -1,4 +1,3 @@ -/* 2002 MJ */ #ifndef READCPU_H #define READCPU_H @@ -6,12 +5,12 @@ extern "C" { #endif -typedef enum { +ENUMDECL { Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r, absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg -} amodes; +} ENUMNAME (amodes); -typedef enum { +ENUMDECL { i_ILLG, i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR, @@ -36,42 +35,43 @@ typedef enum { i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES, i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE, i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16, - i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL -} instrmnem; + i_MMUOP, + i_EMULOP_RETURN, i_EMULOP +} ENUMNAME (instrmnem); extern struct mnemolookup { instrmnem mnemo; const char *name; } lookuptab[]; -typedef enum { +ENUMDECL { sz_byte, sz_word, sz_long -} wordsizes; +} ENUMNAME (wordsizes); -typedef enum { - fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp, - fa_isbranch -} flagaffect; +ENUMDECL { + fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp +} ENUMNAME (flagaffect); -typedef enum { +ENUMDECL { fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp -} flaguse; +} ENUMNAME (flaguse); -typedef enum { - fl_normal = 0, +ENUMDECL { + fl_normal = 0, fl_branch = 1, - fl_jump = 2, - fl_return = 3, - fl_trap = 4, - fl_const_jump = 8, - /* Instructions that can trap don't mark the end of a block */ - fl_end_block = 3 -} cflow_t; + fl_jump = 2, + fl_return = 3, + fl_trap = 4, + fl_const_jump = 8, + + /* Instructions that can trap don't mark the end of a block */ + fl_end_block = 3 +} ENUMNAME (cflow_t); -typedef enum { +ENUMDECL { bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK, bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit -} bitvals; +} ENUMNAME (bitvals); struct instr_def { unsigned int bits; @@ -84,7 +84,7 @@ struct instr_def { unsigned int flaguse:3; unsigned int flagset:3; } flaginfo[5]; - unsigned char cflow; + unsigned char cflow; unsigned char sduse; const char *opcstr; }; @@ -103,15 +103,15 @@ extern struct instr { unsigned int mnemo:8; unsigned int cc:4; unsigned int plev:2; - wordsizes size:2; - amodes smode:5; + unsigned int size:2; + unsigned int smode:5; unsigned int stype:3; - amodes dmode:5; + unsigned int dmode:5; unsigned int suse:1; unsigned int duse:1; unsigned int unused1:1; unsigned int clev:3; - unsigned int cflow:3; + unsigned int cflow:3; unsigned int unused2:2; } *table68k; @@ -120,8 +120,11 @@ extern void do_merges (void); extern int get_no_mismatches (void); extern int nr_cpuop_funcs; +extern const char *get_instruction_name (unsigned int opcode); +extern const char *get_instruction_string (unsigned int opcode); + #ifdef __cplusplus } #endif -#endif +#endif /* READCPU_H */ diff --git a/BasiliskII/src/uae_cpu/readcpua.cpp b/BasiliskII/src/uae_cpu/readcpua.cpp deleted file mode 100644 index 521c241f..00000000 --- a/BasiliskII/src/uae_cpu/readcpua.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * readcpu.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "readcpu.cpp" diff --git a/BasiliskII/src/uae_cpu/registers.h b/BasiliskII/src/uae_cpu/registers.h deleted file mode 100644 index f7daef1f..00000000 --- a/BasiliskII/src/uae_cpu/registers.h +++ /dev/null @@ -1,116 +0,0 @@ -/* 2001 MJ */ - -#ifndef REGISTERS_H -#define REGISTERS_H - -#include "sysdeps.h" -#include "spcflags.h" -typedef char flagtype; - - -struct xttrx { - uae_u32 log_addr_base : 8; - uae_u32 log_addr_mask : 8; - uae_u32 enable : 1; - uae_u32 s_field : 2; - uae_u32 : 3; - uae_u32 usr1 : 1; - uae_u32 usr0 : 1; - uae_u32 : 1; - uae_u32 cmode : 2; - uae_u32 : 2; - uae_u32 write : 1; - uae_u32 : 2; -}; - -struct mmusr_t { - uae_u32 phys_addr : 20; - uae_u32 bus_err : 1; - uae_u32 global : 1; - uae_u32 usr1 : 1; - uae_u32 usr0 : 1; - uae_u32 super : 1; - uae_u32 cmode : 2; - uae_u32 modif : 1; - uae_u32 : 1; - uae_u32 write : 1; - uae_u32 ttrhit : 1; - uae_u32 resident : 1; -}; - -struct log_addr4 { - uae_u32 rif : 7; - uae_u32 pif : 7; - uae_u32 paif : 6; - uae_u32 poff : 12; -}; - -struct log_addr8 { - uae_u32 rif : 7; - uae_u32 pif : 7; - uae_u32 paif : 5; - uae_u32 poff : 13; -}; - -extern struct regstruct -{ - uae_u32 regs[16]; - uaecptr usp,isp,msp; - uae_u16 sr; - flagtype t1; - flagtype t0; - flagtype s; - flagtype m; - flagtype x; - flagtype stopped; - int intmask; - - uae_u32 pc; - uae_u32 fault_pc; - uae_u8 *pc_p; - uae_u8 *pc_oldp; - - uae_u32 vbr,sfc,dfc; - - volatile uae_u32 spcflags; - -#if 0 - uae_u32 kick_mask; - - /* Fellow sources say this is 4 longwords. That's impossible. It needs - * to be at least a longword. The HRM has some cryptic comment about two - * instructions being on the same longword boundary. - * The way this is implemented now seems like a good compromise. - */ - uae_u32 prefetch; -#endif - - /* MMU reg*/ - uae_u32 urp,srp; - uae_u32 tc; - - int mmu_enabled; /* flagtype tce; */ - int mmu_pagesize_8k; /* flagtype tcp; */ - - uae_u32 dtt0,dtt1,itt0,itt1; - uae_u32 mmusr; - - uae_u32 mmu_fslw, mmu_fault_addr; - uae_u16 mmu_ssw; - uae_u32 wb3_data; - uae_u16 wb3_status; - - /* Cache reg*/ - uae_u32 cacr,caar; -} regs, lastint_regs; - -static inline uaecptr m68k_getpc (void) -{ -#ifdef FULLMMU - return regs.pc; -#else - return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); -#endif -} - -#endif diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h index b2084372..3c3fc032 100644 --- a/BasiliskII/src/uae_cpu/spcflags.h +++ b/BasiliskII/src/uae_cpu/spcflags.h @@ -1,10 +1,24 @@ - /* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * Copyright 1995 Bernd Schmidt - */ +/* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * Copyright 1995 Bernd Schmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #ifndef SPCFLAGS_H #define SPCFLAGS_H @@ -12,42 +26,31 @@ typedef uae_u32 spcflags_t; enum { - SPCFLAG_STOP = 0x01, - SPCFLAG_INT = 0x02, - SPCFLAG_BRK = 0x04, - SPCFLAG_TRACE = 0x08, - SPCFLAG_DOTRACE = 0x10, - SPCFLAG_DOINT = 0x20, -#ifdef USE_JIT - SPCFLAG_JIT_END_COMPILE = 0x40, - SPCFLAG_JIT_EXEC_RETURN = 0x80, + SPCFLAG_STOP = 0x01, + SPCFLAG_INT = 0x02, + SPCFLAG_BRK = 0x04, + SPCFLAG_TRACE = 0x08, + SPCFLAG_DOTRACE = 0x10, + SPCFLAG_DOINT = 0x20, +#if USE_JIT + SPCFLAG_JIT_END_COMPILE = 0x40, + SPCFLAG_JIT_EXEC_RETURN = 0x80, #else - SPCFLAG_JIT_END_COMPILE = 0, - SPCFLAG_JIT_EXEC_RETURN = 0, + SPCFLAG_JIT_END_COMPILE = 0, + SPCFLAG_JIT_EXEC_RETURN = 0, #endif - SPCFLAG_VBL = 0x100, - SPCFLAG_MFP = 0x200, - SPCFLAG_INT3 = 0x800, - SPCFLAG_INT5 = 0x1000, - SPCFLAG_SCC = 0x2000, -// SPCFLAG_MODE_CHANGE = 0x4000, - SPCFLAG_ALL = SPCFLAG_STOP - | SPCFLAG_INT - | SPCFLAG_BRK - | SPCFLAG_TRACE - | SPCFLAG_DOTRACE - | SPCFLAG_DOINT - | SPCFLAG_JIT_END_COMPILE - | SPCFLAG_JIT_EXEC_RETURN - | SPCFLAG_INT3 - | SPCFLAG_VBL - | SPCFLAG_INT5 - | SPCFLAG_SCC - | SPCFLAG_MFP - , - + + SPCFLAG_ALL = SPCFLAG_STOP + | SPCFLAG_INT + | SPCFLAG_BRK + | SPCFLAG_TRACE + | SPCFLAG_DOTRACE + | SPCFLAG_DOINT + | SPCFLAG_JIT_END_COMPILE + | SPCFLAG_JIT_EXEC_RETURN + , + SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN - }; #define SPCFLAGS_TEST(m) \ diff --git a/BasiliskII/src/uae_cpu/table68k b/BasiliskII/src/uae_cpu/table68k index 4445cb50..ab9eabe1 100644 --- a/BasiliskII/src/uae_cpu/table68k +++ b/BasiliskII/src/uae_cpu/table68k @@ -10,7 +10,7 @@ % J: immediate 0..15 % k: immediate 0..7 % K: immediate 0..63 -% p: immediate 0..3 (CINV and CPUSH: cache field) +% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field) % s: source mode % S: source reg % d: dest mode @@ -28,15 +28,14 @@ % ArP: --> (Ar)+ % L: --> (xxx.L) % -% Fields on a line: -% 16 chars bitpattern : -% CPU level / privildge level : +% Fields on a line: +% 16 chars bitpattern : +% CPU level / privilege level : % CPU level 0: 68000 % 1: 68010 % 2: 68020 % 3: 68020/68881 % 4: 68040 -% 5: 68060 % privilege level 0: not privileged % 1: unprivileged only on 68000 (check regs.s) % 2: privileged (check regs.s) @@ -47,10 +46,8 @@ % 0 means flag reset % 1 means flag set % ? means programmer was too lazy to check or instruction may trap -% + means instruction is conditional branch (ignored, only for sync) -% / means instruction is unconditional branch/call (ignored, only for sync) -% x means flag is unknown and well-behaved programs shouldn't check it % everything else means flag set/used +% x means flag is unknown and well-behaved programs shouldn't check it % % Control flow % two letters, combination of @@ -111,7 +108,7 @@ 0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg] 0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg] -0100 0000 zzdd dDDD:00:XNZVC:X-Z--:--:30: NEGX.z d[!Areg] +0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg] 0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg] 0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg] 0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg] @@ -122,13 +119,13 @@ 0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2 0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg] 0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k -0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] +0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] 0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] +0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] 0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] -0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] +0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] 0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] -0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] +0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] 0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s 0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg] 0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL @@ -151,24 +148,21 @@ 0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR 0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1 0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1 -0100 1110 10ss sSSS:00://///://///:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] 0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr 0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr -0100 1110 11ss sSSS:00://///://///:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] 0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar -% This variant of ADDQ is word and long sized only -0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] -0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] +0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] +0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] 0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg] - -% This variant of SUBQ is word and long sized only -0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] -0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] +0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] +0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] 0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg] -0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1 -0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg] +0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1 +0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg] 0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1 0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2 0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc @@ -176,30 +170,30 @@ % Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal % instruction exceptions when compiling a 68000 only emulation, which isn't % what we want either. -0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1 -0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i -0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2 -0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1 -0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i -0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2 +0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1 +0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i +0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2 +0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1 +0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i +0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2 0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr 1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr 1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr -1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Dreg],Dr -1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp +1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr +1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp 1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg] -1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr -1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp -1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr -1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp 1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr 1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr 1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp 1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg] 1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar @@ -211,18 +205,18 @@ 1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr 1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr -1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Dreg],Dr -1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp +1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr +1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp 1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] -1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] +1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] 1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr 1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr 1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp 1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg] 1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar @@ -230,8 +224,8 @@ 1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR 1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR 1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR -1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR -1110 rrrf zz10 1RRR:00:XNZ0C:X----:--:13: LSf.z Dr,DR +1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR +1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR 1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR 1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR 1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg] @@ -261,6 +255,7 @@ 1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] % 68040 instructions +1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s 1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar 1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar 1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p @@ -269,18 +264,11 @@ 1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p % destination register number is encoded in the following word 1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP -1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al -1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi] -1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al -1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind] +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi] +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind] -% MMU disabled -% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s - -% EmulOp instructions (deprecated, to be removed) -0111 0001 0000 0000:02:-----:-----:-R:00: EMULOP_RETURN -0111 0001 EEEE EEEE:02:-----:-----:-J:10: EMULOP #E - -% NatFea instructions (do I have the srcaddr correct?) disabled -% 0111 0011 0000 0000:00:-----:-----:-J:00: NATFEAT_ID -% 0111 0011 0000 0001:00:-----:-----:-J:00: NATFEAT_CALL +% EmulOp instructions +0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN +0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E From 8353a9ed44f20737764656978c92a86d01c6481c Mon Sep 17 00:00:00 2001 From: uyjulian Date: Wed, 6 Jun 2018 23:11:08 -0500 Subject: [PATCH 07/20] Hope it works --- BasiliskII/src/Unix/CMakeLists.txt | 2 + BasiliskII/src/Unix/main_unix.cpp | 241 ++---------------- BasiliskII/src/Unix/timer_unix.cpp | 114 +++++---- BasiliskII/src/uae_cpu/basilisk_glue.cpp | 2 +- BasiliskII/src/uae_cpu/compiler/compemu.h | 5 + .../src/uae_cpu/compiler/compemu_support.cpp | 61 ++--- BasiliskII/src/uae_cpu/newcpu.cpp | 7 +- 7 files changed, 124 insertions(+), 308 deletions(-) diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index 9bc6431f..4454d69a 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -104,6 +104,8 @@ set_source_files_properties(${BasiliskII_SRCS} target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY}) +# set(CMAKE_POSITION_INDEPENDENT_CODE OFF) + SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 0x2000" ) add_definitions(-march=native) diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 60824593..05f9717d 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -83,27 +83,17 @@ bool TwentyFourBitAddressing; static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes -#ifdef HAVE_PTHREADS - static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread -static pthread_t xpram_thread; // XPRAM watchdog +static SDL_Thread *xpram_thread = NULL; // XPRAM watchdog static bool tick_thread_active = false; // Flag: 60Hz thread installed static volatile bool tick_thread_cancel = false; // Flag: Cancel 60Hz thread -static pthread_t tick_thread; // 60Hz thread -static pthread_attr_t tick_thread_attr; // 60Hz thread attributes +static SDL_Thread *tick_thread; // 60Hz thread -static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect InterruptFlags -#define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock) -#define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock) - -#else - -#define LOCK_INTFLAGS -#define UNLOCK_INTFLAGS - -#endif +static SDL_mutex *intflag_lock = NULL; // Mutex to protect InterruptFlags +#define LOCK_INTFLAGS SDL_LockMutex(intflag_lock) +#define UNLOCK_INTFLAGS SDL_UnlockMutex(intflag_lock) #if USE_SCRATCHMEM_SUBTERFUGE uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes @@ -124,8 +114,8 @@ static const char *gui_connection_path = NULL; // GUI connection identifier // Prototypes -static void *xpram_func(void *arg); -static void *tick_func(void *arg); +static int xpram_func(void *arg); +static int tick_func(void *arg); static void one_tick(...); @@ -482,11 +472,10 @@ int main(int argc, char **argv) #ifndef USE_CPU_EMUL_SERVICES -#if defined(HAVE_PTHREADS) +#ifdef USE_SDL - // POSIX threads available, start 60Hz thread - Set_pthread_attr(&tick_thread_attr, 0); - tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0); + // SDL threads available, start 60Hz thread + tick_thread_active = ((tick_thread = SDL_CreateThread(tick_func, NULL)) != NULL); if (!tick_thread_active) { sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno)); ErrorAlert(str); @@ -494,60 +483,13 @@ int main(int argc, char **argv) } D(bug("60Hz thread started\n")); -#elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS) - - // POSIX.4 timers and real-time signals available, start 60Hz timer - sigemptyset(&timer_sa.sa_mask); - timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick; - timer_sa.sa_flags = SA_SIGINFO | SA_RESTART; - if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } - struct sigevent timer_event; - timer_event.sigev_notify = SIGEV_SIGNAL; - timer_event.sigev_signo = SIG_TIMER; - if (timer_create(CLOCK_REALTIME, &timer_event, &timer) < 0) { - sprintf(str, GetString(STR_TIMER_CREATE_ERR), strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } - struct itimerspec req; - req.it_value.tv_sec = 0; - req.it_value.tv_nsec = 16625000; - req.it_interval.tv_sec = 0; - req.it_interval.tv_nsec = 16625000; - if (timer_settime(timer, 0, &req, NULL) < 0) { - sprintf(str, GetString(STR_TIMER_SETTIME_ERR), strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } - D(bug("60Hz timer started\n")); - -#else - - // Start 60Hz timer - sigemptyset(&timer_sa.sa_mask); // Block virtual 68k interrupts during SIGARLM handling - timer_sa.sa_handler = one_tick; - timer_sa.sa_flags = SA_ONSTACK | SA_RESTART; - if (sigaction(SIGALRM, &timer_sa, NULL) < 0) { - sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGALRM", strerror(errno)); - ErrorAlert(str); - QuitEmulator(); - } - struct itimerval req; - req.it_interval.tv_sec = req.it_value.tv_sec = 0; - req.it_interval.tv_usec = req.it_value.tv_usec = 16625; - setitimer(ITIMER_REAL, &req, NULL); - #endif #endif -#ifdef USE_PTHREADS_SERVICES +#ifdef USE_SDL // Start XPRAM watchdog thread memcpy(last_xpram, XPRAM, XPRAM_SIZE); - xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0); + xpram_thread_active = ((xpram_thread = SDL_CreateThread(xpram_func, NULL)) != NULL); D(bug("XPRAM thread started\n")); #endif @@ -573,41 +515,17 @@ void QuitEmulator(void) Exit680x0(); #endif -#if defined(USE_CPU_EMUL_SERVICES) - // Show statistics - uint64 emulated_ticks_end = GetTicks_usec(); - D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n", - (long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start), - emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks)); -#elif defined(USE_PTHREADS_SERVICES) // Stop 60Hz thread if (tick_thread_active) { tick_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(tick_thread); -#endif - pthread_join(tick_thread, NULL); + SDL_WaitThread(tick_thread, NULL); } -#elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS) - // Stop 60Hz timer - timer_delete(timer); -#else - struct itimerval req; - req.it_interval.tv_sec = req.it_value.tv_sec = 0; - req.it_interval.tv_usec = req.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &req, NULL); -#endif -#ifdef USE_PTHREADS_SERVICES // Stop XPRAM watchdog thread if (xpram_thread_active) { xpram_thread_cancel = true; -#ifdef HAVE_PTHREAD_CANCEL - pthread_cancel(xpram_thread); -#endif - pthread_join(xpram_thread, NULL); + SDL_WaitThread(xpram_thread, NULL); } -#endif // Deinitialize everything ExitAll(); @@ -659,71 +577,14 @@ void FlushCodeCache(void *start, uint32 size) #endif } - - -#ifdef HAVE_PTHREADS -/* - * Pthread configuration - */ - -void Set_pthread_attr(pthread_attr_t *attr, int priority) -{ - pthread_attr_init(attr); -#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) - // Some of these only work for superuser - if (geteuid() == 0) { - pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); - pthread_attr_setschedpolicy(attr, SCHED_FIFO); - struct sched_param fifo_param; - fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) + - sched_get_priority_max(SCHED_FIFO)) / 2 + - priority); - pthread_attr_setschedparam(attr, &fifo_param); - } - if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) { -#ifdef PTHREAD_SCOPE_BOUND_NP - // If system scope is not available (eg. we're not running - // with CAP_SCHED_MGT capability on an SGI box), try bound - // scope. It exposes pthread scheduling to the kernel, - // without setting realtime priority. - pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP); -#endif - } -#endif -} -#endif // HAVE_PTHREADS - - /* * Mutexes */ -#ifdef HAVE_PTHREADS - struct B2_mutex { - B2_mutex() { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - // Initialize the mutex for priority inheritance -- - // required for accurate timing. -#if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__) - pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); -#endif -#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL) - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); -#endif -#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); -#endif - pthread_mutex_init(&m, &attr); - pthread_mutexattr_destroy(&attr); - } - ~B2_mutex() { - pthread_mutex_trylock(&m); // Make sure it's locked before - pthread_mutex_unlock(&m); // unlocking it. - pthread_mutex_destroy(&m); - } - pthread_mutex_t m; + B2_mutex() { m = SDL_CreateMutex(); } + ~B2_mutex() { if (m) SDL_DestroyMutex(m); } + SDL_mutex *m; }; B2_mutex *B2_create_mutex(void) @@ -733,12 +594,14 @@ B2_mutex *B2_create_mutex(void) void B2_lock_mutex(B2_mutex *mutex) { - pthread_mutex_lock(&mutex->m); + if (mutex) + SDL_LockMutex(mutex->m); } void B2_unlock_mutex(B2_mutex *mutex) { - pthread_mutex_unlock(&mutex->m); + if (mutex) + SDL_UnlockMutex(mutex->m); } void B2_delete_mutex(B2_mutex *mutex) @@ -746,33 +609,6 @@ void B2_delete_mutex(B2_mutex *mutex) delete mutex; } -#else - -struct B2_mutex { - int dummy; -}; - -B2_mutex *B2_create_mutex(void) -{ - return new B2_mutex; -} - -void B2_lock_mutex(B2_mutex *mutex) -{ -} - -void B2_unlock_mutex(B2_mutex *mutex) -{ -} - -void B2_delete_mutex(B2_mutex *mutex) -{ - delete mutex; -} - -#endif - - /* * Interrupt flags (must be handled atomically!) */ @@ -808,17 +644,15 @@ static void xpram_watchdog(void) } } -#ifdef USE_PTHREADS_SERVICES -static void *xpram_func(void *arg) +static int xpram_func(void *arg) { while (!xpram_thread_cancel) { for (int i=0; i<60 && !xpram_thread_cancel; i++) Delay_usec(999999); // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true xpram_watchdog(); } - return NULL; + return 0; } -#endif /* @@ -832,14 +666,6 @@ static void one_second(void) SetInterruptFlag(INTFLAG_1HZ); TriggerInterrupt(); - -#ifndef USE_PTHREADS_SERVICES - static int second_counter = 0; - if (++second_counter > 60) { - second_counter = 0; - xpram_watchdog(); - } -#endif } static void one_tick(...) @@ -850,16 +676,6 @@ static void one_tick(...) one_second(); } -#ifndef USE_PTHREADS_SERVICES - // Threads not used to trigger interrupts, perform video refresh from here - VideoRefresh(); -#endif - -#ifndef HAVE_PTHREADS - // No threads available, perform networking from here - SetInterruptFlag(INTFLAG_ETHER); -#endif - // Trigger 60Hz interrupt if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) { SetInterruptFlag(INTFLAG_60HZ); @@ -867,8 +683,7 @@ static void one_tick(...) } } -#ifdef USE_PTHREADS_SERVICES -static void *tick_func(void *arg) +static int tick_func(void *arg) { uint64 start = GetTicks_usec(); int64 ticks = 0; @@ -878,17 +693,15 @@ static void *tick_func(void *arg) next += 16625; int64 delay = next - GetTicks_usec(); if (delay > 0) - Delay_usec(delay); + Delay_usec(uint32(delay)); else if (delay < -16625) next = GetTicks_usec(); ticks++; } uint64 end = GetTicks_usec(); - D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); - return NULL; + D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); + return 0; } -#endif - /* * Display error alert diff --git a/BasiliskII/src/Unix/timer_unix.cpp b/BasiliskII/src/Unix/timer_unix.cpp index a73e4280..f6db115e 100644 --- a/BasiliskII/src/Unix/timer_unix.cpp +++ b/BasiliskII/src/Unix/timer_unix.cpp @@ -315,51 +315,54 @@ void Delay_usec(uint32 usec) * Suspend emulator thread, virtual CPU in idle mode */ -#ifdef HAVE_PTHREADS -#if defined(HAVE_PTHREAD_COND_INIT) -#define IDLE_USES_COND_WAIT 1 -static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t idle_cond = PTHREAD_COND_INITIALIZER; -#elif defined(HAVE_SEM_INIT) -#define IDLE_USES_SEMAPHORE 1 -#include -#ifdef HAVE_SPINLOCKS -static spinlock_t idle_lock = SPIN_LOCK_UNLOCKED; -#define LOCK_IDLE spin_lock(&idle_lock) -#define UNLOCK_IDLE spin_unlock(&idle_lock) -#else -static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_IDLE pthread_mutex_lock(&idle_lock) -#define UNLOCK_IDLE pthread_mutex_unlock(&idle_lock) -#endif -static sem_t idle_sem; -static int idle_sem_ok = -1; -#endif -#endif +// #ifdef HAVE_PTHREADS +// #if defined(HAVE_PTHREAD_COND_INIT) +// #define IDLE_USES_COND_WAIT 1 +// static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER; +// static pthread_cond_t idle_cond = PTHREAD_COND_INITIALIZER; +// #elif defined(HAVE_SEM_INIT) +// #define IDLE_USES_SEMAPHORE 1 +// #include +// #ifdef HAVE_SPINLOCKS +// static spinlock_t idle_lock = SPIN_LOCK_UNLOCKED; +// #define LOCK_IDLE spin_lock(&idle_lock) +// #define UNLOCK_IDLE spin_unlock(&idle_lock) +// #else +// static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER; +// #define LOCK_IDLE pthread_mutex_lock(&idle_lock) +// #define UNLOCK_IDLE pthread_mutex_unlock(&idle_lock) +// #endif +// static sem_t idle_sem; +// static int idle_sem_ok = -1; +// #endif +// #endif void idle_wait(void) { -#ifdef IDLE_USES_COND_WAIT - pthread_mutex_lock(&idle_lock); - pthread_cond_wait(&idle_cond, &idle_lock); - pthread_mutex_unlock(&idle_lock); -#else -#ifdef IDLE_USES_SEMAPHORE - LOCK_IDLE; - if (idle_sem_ok < 0) - idle_sem_ok = (sem_init(&idle_sem, 0, 0) == 0); - if (idle_sem_ok > 0) { - idle_sem_ok++; - UNLOCK_IDLE; - sem_wait(&idle_sem); - return; - } - UNLOCK_IDLE; -#endif + //This causes events to not process randomly in JIT so commented out + usleep(10); - // Fallback: sleep 10 ms - Delay_usec(10000); -#endif +// #ifdef IDLE_USES_COND_WAIT +// pthread_mutex_lock(&idle_lock); +// pthread_cond_wait(&idle_cond, &idle_lock); +// pthread_mutex_unlock(&idle_lock); +// #else +// #ifdef IDLE_USES_SEMAPHORE +// LOCK_IDLE; +// if (idle_sem_ok < 0) +// idle_sem_ok = (sem_init(&idle_sem, 0, 0) == 0); +// if (idle_sem_ok > 0) { +// idle_sem_ok++; +// UNLOCK_IDLE; +// sem_wait(&idle_sem); +// return; +// } +// UNLOCK_IDLE; +// #endif + +// // Fallback: sleep 10 ms +// Delay_usec(10000); +// #endif } @@ -369,18 +372,19 @@ void idle_wait(void) void idle_resume(void) { -#ifdef IDLE_USES_COND_WAIT - pthread_cond_signal(&idle_cond); -#else -#ifdef IDLE_USES_SEMAPHORE - LOCK_IDLE; - if (idle_sem_ok > 1) { - idle_sem_ok--; - UNLOCK_IDLE; - sem_post(&idle_sem); - return; - } - UNLOCK_IDLE; -#endif -#endif + //This causes events to not process randomly in JIT so commented out +// #ifdef IDLE_USES_COND_WAIT +// pthread_cond_signal(&idle_cond); +// #else +// #ifdef IDLE_USES_SEMAPHORE +// LOCK_IDLE; +// if (idle_sem_ok > 1) { +// idle_sem_ok--; +// UNLOCK_IDLE; +// sem_post(&idle_sem); +// return; +// } +// UNLOCK_IDLE; +// #endif +// #endif } diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index b29c7702..6bfadb9d 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -159,7 +159,7 @@ void TriggerInterrupt(void) void TriggerNMI(void) { - //!! not implemented yet + SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI } diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h index 15edd102..118251c8 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -35,6 +35,11 @@ // #include "sysconfig.h" #include "newcpu.h" +#ifdef __x86_64__ +#define CPU_64_BIT 1 +#define CPU_x86_64 1 +#endif + #ifdef UAE #ifdef CPU_64_BIT typedef uae_u64 uintptr; diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index 62fcfd36..068123b8 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -43,6 +43,12 @@ #error "Only [LS]AHF scheme to [gs]et flags is supported with the JIT Compiler" #endif +//TODO: detect i386 and arm platforms + +#ifdef __x86_64__ +#define CPU_x86_64 1 +#endif + /* NOTE: support for AMD64 assumes translation cache and other code * buffers are allocated into a 32-bit address space because (i) B2/JIT * code is not 64-bit clean and (ii) it's faster to resolve branches @@ -254,7 +260,7 @@ uae_u8* comp_pc_p; #else // External variables // newcpu.cpp -extern int quit_program; +extern bool quit_program; #endif // gb-- Extra data for Basilisk II/JIT @@ -4401,41 +4407,28 @@ void flush_icache_range(uae_u8 *start_p, uae_u32 length) blockinfo *bi = active; while (bi) { #if USE_CHECKSUM_INFO - bool candidate = false; - for (checksum_info *csi = bi->csi; csi; csi = csi->next) { - if (((start_p - csi->start_p) < csi->length) || - ((csi->start_p - start_p) < length)) { - candidate = true; - break; - } - } + bool invalidate = false; + for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) + invalidate = (((start_p - csi->start_p) < csi->length) || + ((csi->start_p - start_p) < length)); #else // Assume system is consistent and would invalidate the right range - const bool candidate = (bi->pc_p - start_p) < length; + const bool invalidate = (bi->pc_p - start_p) < length; #endif - blockinfo *dbi = bi; - bi = bi->next; - if (candidate) { - uae_u32 cl = cacheline(dbi->pc_p); - if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) { - if (dbi == cache_tags[cl+1].bi) + if (invalidate) { + uae_u32 cl = cacheline(bi->pc_p); + if (bi == cache_tags[cl + 1].bi) cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; - dbi->handler_to_use = (cpuop_func *)popall_execute_normal; - set_dhtu(dbi, dbi->direct_pen); - dbi->status = BI_INVALID; - } - else { - if (dbi == cache_tags[cl+1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_check_checksum; - dbi->handler_to_use = (cpuop_func *)popall_check_checksum; - set_dhtu(dbi, dbi->direct_pcc); - dbi->status = BI_NEED_CHECK; - } - remove_from_list(dbi); - add_to_dormant(dbi); + bi->handler_to_use = (cpuop_func *)popall_execute_normal; + set_dhtu(bi, bi->direct_pen); + bi->status = BI_NEED_RECOMP; } + bi = bi->next; } return; +#else + // UNUSED(start); + // UNUSED(length); #endif flush_icache(-1); } @@ -5138,15 +5131,11 @@ void m68k_compile_execute (void) setjmpagain: TRY(prb) { for (;;) { - if (quit_program > 0) { - if (quit_program == 1) { + if (quit_program == 1) { #if FLIGHT_RECORDER - dump_flight_recorder(); + dump_flight_recorder(); #endif - break; - } - quit_program = 0; - m68k_reset (); + break; } m68k_do_compile_execute(); } diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index e9d0b88d..e981aa2b 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -854,11 +854,11 @@ int m68k_move2c (int regno, uae_u32 *regp) case 0: regs.sfc = *regp & 7; break; case 1: regs.dfc = *regp & 7; break; case 2: - cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); + regs.cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); #if USE_JIT set_cache_state(regs.cacr & 0x8000); if (*regp & 0x08) { /* Just to be on the safe side */ - flush_icache(2); + flush_icache(1); } #endif break; @@ -1267,6 +1267,9 @@ void mmu_op(uae_u32 opcode, uae_u16 extra) if ((opcode & 0xFE0) == 0x0500) { /* PFLUSH */ mmusr = 0; +#ifdef USE_JIT + flush_icache(0); +#endif } else if ((opcode & 0x0FD8) == 0x548) { /* PTEST */ } else From e99d4e579cf77157223add0eb7be890eddaf21e8 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Thu, 7 Jun 2018 15:01:48 -0500 Subject: [PATCH 08/20] Remove low memory globals hack (it doesn't work) --- BasiliskII/src/Unix/Darwin/gtk-osx.patch | 179 ---------------- BasiliskII/src/Unix/Darwin/lowmem.c | 253 ----------------------- BasiliskII/src/Unix/Darwin/mkstandalone | 89 -------- BasiliskII/src/Unix/Darwin/pagezero.c | 31 --- BasiliskII/src/Unix/Darwin/testlmem.sh | 34 --- 5 files changed, 586 deletions(-) delete mode 100644 BasiliskII/src/Unix/Darwin/gtk-osx.patch delete mode 100644 BasiliskII/src/Unix/Darwin/lowmem.c delete mode 100755 BasiliskII/src/Unix/Darwin/mkstandalone delete mode 100644 BasiliskII/src/Unix/Darwin/pagezero.c delete mode 100755 BasiliskII/src/Unix/Darwin/testlmem.sh diff --git a/BasiliskII/src/Unix/Darwin/gtk-osx.patch b/BasiliskII/src/Unix/Darwin/gtk-osx.patch deleted file mode 100644 index b8b45c18..00000000 --- a/BasiliskII/src/Unix/Darwin/gtk-osx.patch +++ /dev/null @@ -1,179 +0,0 @@ -2006-05-05 Gwenole Beauchesne - - * gtk/gtkaqua.c (gtk_aqua_draw_focus): Don't crash if "detail" is - NULL. - - * gdk/MacCarbonEvents.c (mouse_motion_handler): Another NULL - pointer check. - -2006-04-17 Gwenole Beauchesne - - * glib-1.2.10/gmain.c (g_main_run): Don't block in - RunApplicationEventLoop(), code inspired from Inside Mac - technote. - - This patch only suits Basilisk II needs. i.e. this may not work - for other programs. - -2006-04-17 Gwenole Beauchesne - - * glib-1.2.10/glibconfig.h (G_VA_COPY): Don't redefine. - ---- gtk-osx-0.7/gdk/MacCarbonEvents.c Sat May 8 16:59:12 2004 -+++ gtk-osx-0.7/gdk/MacCarbonEvents.c Fri May 5 07:48:45 2006 -@@ -227,7 +227,7 @@ mouse_motion_handler (EventHandlerCallRe - local_point.v = global_point.v; - } - -- if (gdk_window != g_win_containing_mouse) -+ if (gdk_window && gdk_window != g_win_containing_mouse) - { - - if(GDK_LEAVE_NOTIFY_MASK & ((GdkWindowPrivate*) g_win_containing_mouse)->event_mask) { ---- gtk-osx-0.7/glib-1.2.10/glibconfig.h Thu Jan 2 05:29:18 2003 -+++ gtk-osx-0.7/glib-1.2.10/glibconfig.h Mon Apr 17 21:12:34 2006 -@@ -62,8 +62,9 @@ G_GNUC_EXTENSION typedef unsigned long l - #define GLIB_MINOR_VERSION 2 - #define GLIB_MICRO_VERSION 10 - -- -+#ifndef G_VA_COPY - #define G_VA_COPY __va_copy -+#endif - - #ifdef __cplusplus - #define G_HAVE_INLINE 1 ---- gtk-osx-0.7/glib-1.2.10/gmain.c Sat Dec 27 22:23:06 2003 -+++ gtk-osx-0.7/glib-1.2.10/gmain.c Mon Apr 17 22:12:15 2006 -@@ -145,6 +145,7 @@ static gboolean g_idle_dispatch ( - gpointer user_data); - - #ifdef MAC_CARBON_EVENTS -+static void mac_run_application_event_loop (GMainLoop *loop); - static void mac_handle_idle_action (EventLoopTimerRef timer_ref, - EventLoopIdleTimerMessage state, - void* user_data); -@@ -1116,7 +1117,7 @@ g_main_run (GMainLoop *loop) - loop->is_running = TRUE; - - #ifdef MAC_CARBON_EVENTS -- RunApplicationEventLoop (); -+ mac_run_application_event_loop (loop); - #else - while (loop->is_running) - g_main_iterate (TRUE, TRUE); -@@ -1870,4 +1871,94 @@ mac_handle_g_main_iteration_action (Even - #endif - } - --#endif /* MAC_CARBON_EVENTS */ -\ No newline at end of file -+static EventHandlerUPP g_quit_event_handler_upp; -+ -+static pascal OSStatus QuitEventHandler(EventHandlerCallRef inHandlerCallRef, -+ EventRef inEvent, void *inUserData) -+{ -+ OSStatus err; -+ -+ if ((err = CallNextEventHandler(inHandlerCallRef, inEvent)) == noErr) -+ *((Boolean *)inUserData) = TRUE; -+ -+ return err; -+} -+ -+static EventHandlerUPP g_event_loop_event_handler_upp; -+ -+static pascal OSStatus EventLoopEventHandler(EventHandlerCallRef inHandlerCallRef, -+ EventRef inEvent, void *inUserData) -+{ -+ OSStatus err; -+ OSStatus junk; -+ EventHandlerRef installedHandler; -+ EventTargetRef theTarget; -+ EventRef theEvent; -+ EventTimeout timeToWaitForEvent; -+ Boolean quitNow; -+ GMainLoop * loop = (GMainLoop *)inUserData; -+ static const EventTypeSpec eventSpec = {kEventClassApplication, kEventAppQuit}; -+ -+ quitNow = false; -+ -+ err = InstallEventHandler(GetApplicationEventTarget(), -+ g_quit_event_handler_upp, -+ 1, &eventSpec, &quitNow, &installedHandler); -+ if (err == noErr) { -+ theTarget = GetEventDispatcherTarget(); -+ do { -+ timeToWaitForEvent = kEventDurationNoWait; -+ err = ReceiveNextEvent(0, NULL, timeToWaitForEvent, -+ true, &theEvent); -+ if (err == noErr) { -+ SendEventToEventTarget(theEvent, theTarget); -+ ReleaseEvent(theEvent); -+ } -+ YieldToAnyThread(); -+ } while ( loop->is_running && ! quitNow ); -+ junk = RemoveEventHandler(installedHandler); -+ } -+ -+ return err; -+} -+ -+static void -+mac_run_application_event_loop (GMainLoop *loop) -+{ -+ static const EventTypeSpec eventSpec = {'KWIN', 'KWIN' }; -+ OSStatus err; -+ OSStatus junk; -+ EventHandlerRef installedHandler; -+ EventRef dummyEvent; -+ -+ dummyEvent = nil; -+ -+ err = noErr; -+ if (g_event_loop_event_handler_upp == nil) -+ g_event_loop_event_handler_upp = NewEventHandlerUPP(EventLoopEventHandler); -+ if (g_quit_event_handler_upp == nil) -+ g_quit_event_handler_upp = NewEventHandlerUPP(QuitEventHandler); -+ if (g_event_loop_event_handler_upp == nil || g_quit_event_handler_upp == nil) -+ err = memFullErr; -+ -+ if (err == noErr) { -+ err = InstallEventHandler(GetApplicationEventTarget(), -+ g_event_loop_event_handler_upp, -+ 1, &eventSpec, loop, &installedHandler); -+ if (err == noErr) { -+ err = MacCreateEvent(nil, 'KWIN', 'KWIN', GetCurrentEventTime(), -+ kEventAttributeNone, &dummyEvent); -+ if (err == noErr) -+ err = PostEventToQueue(GetMainEventQueue(), dummyEvent, -+ kEventPriorityHigh); -+ if (err == noErr) -+ RunApplicationEventLoop(); -+ -+ junk = RemoveEventHandler(installedHandler); -+ } -+ } -+ -+ if (dummyEvent != nil) -+ ReleaseEvent(dummyEvent); -+} -+#endif /* MAC_CARBON_EVENTS */ ---- gtk-osx-0.7/gtk/gtkaqua.c Sat Dec 27 23:33:36 2003 -+++ gtk-osx-0.7/gtk/gtkaqua.c Fri May 5 07:13:30 2006 -@@ -2183,11 +2183,12 @@ gtk_aqua_draw_focus (GtkStyle *styl - g_return_if_fail (window != NULL); - - // aqua button focus is not just a simple rectangle, so we don't draw anything here -- if ( strcmp( detail, "button" ) == 0 ) { -+ if (detail) { -+ if ( strcmp( detail, "button" ) == 0 ) - return; -- } else if ( strcmp( detail, "checkbutton" ) == 0 ) { -+ else if ( strcmp( detail, "checkbutton" ) == 0 ) - return; -- } else if ( strcmp( detail, "togglebutton" ) == 0 ) { -+ else if ( strcmp( detail, "togglebutton" ) == 0 ) - return; - } - diff --git a/BasiliskII/src/Unix/Darwin/lowmem.c b/BasiliskII/src/Unix/Darwin/lowmem.c deleted file mode 100644 index 297f52f7..00000000 --- a/BasiliskII/src/Unix/Darwin/lowmem.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * lowmem.c - enable access to low memory globals on Darwin - * - * Copyright (c) 2003 Michael Z. Sliczniak - * - * Basilisk II (C) 1997-2005 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char progname[] = "lowmem"; -static const char *filename; - -static int do_swap = 0; - -static uint32_t target_uint32(uint32_t value) -{ - if (do_swap) - value = OSSwapInt32(value); - return value; -} - -void pagezero_32(struct mach_header *machhead) -{ - struct segment_command *sc_cmd; - - if (target_uint32(machhead->filetype) != MH_EXECUTE) { - (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n", - progname, filename); - exit(1); - } - if (machhead->ncmds == 0) { - (void)fprintf(stderr, "%s: %s does not contain any load commands\n", - progname, filename); - exit(1); - } - sc_cmd = (void *)&machhead[1]; - if (target_uint32(sc_cmd->cmd) != LC_SEGMENT){ - (void)fprintf(stderr, "%s: load segment not first command in %s\n", - progname, filename); - exit(1); - } - if (strncmp(sc_cmd->segname, "__PAGEZERO", sizeof (*sc_cmd->segname))) { - (void)fprintf(stderr, "%s: zero page not first segment in %s\n", - progname, filename); - exit(1); - } - /* change the permissions */ - sc_cmd->maxprot = target_uint32(VM_PROT_ALL); - sc_cmd->initprot = target_uint32(VM_PROT_ALL); - -#ifdef MH_PIE - /* disable pie in header */ - machhead->flags = target_uint32(target_uint32(machhead->flags) & ~MH_PIE); -#endif -} - -#if defined(MH_MAGIC_64) -void pagezero_64(struct mach_header_64 *machhead) -{ - struct segment_command_64 *sc_cmd; - - if (target_uint32(machhead->filetype) != MH_EXECUTE) { - (void)fprintf(stderr, "%s: %s does not appear to be an executable file\n", - progname, filename); - exit(1); - } - if (machhead->ncmds == 0) { - (void)fprintf(stderr, "%s: %s does not contain any load commands\n", - progname, filename); - exit(1); - } - sc_cmd = (void *)&machhead[1]; - if (target_uint32(sc_cmd->cmd) != LC_SEGMENT_64) { - (void)fprintf(stderr, "%s: load segment not first command in %s\n", - progname, filename); - exit(1); - } - if (strncmp(sc_cmd->segname, "__PAGEZERO", sizeof(*sc_cmd->segname))) { - (void)fprintf(stderr, "%s: zero page not first segment in %s\n", - progname, filename); - exit(1); - } - /* change the permissions */ - sc_cmd->maxprot = target_uint32(VM_PROT_ALL); - sc_cmd->initprot = target_uint32(VM_PROT_ALL); -} -#endif - -/* - * Under Mach there is very little assumed about the memory map of object - * files. It is the job of the loader to create the initial memory map of an - * executable. In a Mach-O executable there will be numerous loader commands - * that the loader must process. Some of these will create the initial memory - * map used by the executable. Under Darwin the static object file linker, - * ld, automatically adds the __PAGEZERO segment to all executables. The - * default size of this segment is the page size of the target system and - * the initial and maximum permissions are set to allow no access. This is so - * that all programs fault on a NULL pointer dereference. Arguably this is - * incorrect and the maximum permissions shoould be rwx so that programs can - * change this default behavior. Then programs could be written that assume - * a null string at the null address, which was the convention on some - * systems. In our case we need to have 8K mapped at zero for the low memory - * globals and this program modifies the segment load command in the - * basiliskII executable so that it can be used for data. - */ - -int -main(int argc, const char *argv[]) -{ - int fd; - char *addr; - off_t file_size; - struct mach_header *machhead; -#if defined(MH_MAGIC_64) - struct mach_header_64 *machhead64; -#endif - struct fat_header *fathead; - struct stat f; - - if (argc != 2) { - (void)fprintf(stderr, "Usage: %s executable\n", progname); - exit(1); - } - - filename = argv[1]; - - if (stat(filename, &f)) { - (void)fprintf(stderr, "%s: could not stat %s: %s\n", - progname, filename, strerror(errno)); - exit(1); - } - file_size = f.st_size; - - fd = open(filename, O_RDWR, 0); - if (fd == -1) { - (void)fprintf(stderr, "%s: could not open %s: %s\n", - progname, filename, strerror(errno)); - exit(1); - } - - /* - * Size does not really matter, it will be rounded-up to a multiple - * of the page size automatically. - */ - addr = mmap(NULL, file_size, PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, fd, 0); - if (addr == NULL || addr == MAP_FAILED) { - (void)fprintf(stderr, "%s: could not mmap %s: %s\n", - progname, filename, strerror(errno)); - exit(1); - } - - /* - * Check to see if the Mach-O magic bytes are in the header. - */ - machhead = (void *)addr; -#if defined(MH_MAGIC_64) - machhead64 = (void *)addr; -#endif - fathead = (void *)addr; - -#if defined(MH_MAGIC_64) - do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM || machhead64->magic == MH_CIGAM_64; -#else - do_swap = machhead->magic == MH_CIGAM || fathead->magic == FAT_CIGAM; -#endif - - if (target_uint32(machhead->magic) == MH_MAGIC) { - pagezero_32(machhead); -#if defined(MH_MAGIC_64) - } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) { - pagezero_64(machhead64); -#endif - } else if (target_uint32(fathead->magic) == FAT_MAGIC) { - struct fat_arch *arch = (void *)&fathead[1]; - int saved_swap = do_swap; - int i; - for (i = 0; i < target_uint32(fathead->nfat_arch); ++i, ++arch) { - machhead = (void *)(addr + target_uint32(arch->offset)); -#if defined(MH_MAGIC_64) - machhead64 = (void *)(addr + target_uint32(arch->offset)); -#endif -#if defined(MH_MAGIC_64) - do_swap = machhead->magic == MH_CIGAM || machhead64->magic == MH_CIGAM_64; -#else - do_swap = machhead->magic == MH_CIGAM; -#endif - if (target_uint32(machhead->magic) == MH_MAGIC) { - pagezero_32(machhead); -#if defined(MH_MAGIC_64) - } else if (target_uint32(machhead64->magic) == MH_MAGIC_64) { - pagezero_64(machhead64); -#endif - } else { - (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n", - progname, filename); - exit(1); - } - do_swap = saved_swap; - } - } else { - (void)fprintf(stderr, "%s: %s does not appear to be a Mach-O object file\n", - progname, filename); - exit(1); - } - - /* - * We do not make __PAGEZERO 8K in this program because then - * all of the offsets would be wrong in the object file after - * this segment. Instead we use the -pagezero_size option - * to link the executable. - */ - if (msync(addr, file_size, MS_SYNC) == -1) { - (void)fprintf(stderr, "%s: could not sync %s: %s\n", - progname, filename, strerror(errno)); - exit(1); - } - - if (munmap(addr, file_size) == -1) { - (void)fprintf(stderr, "%s: could not unmap %s: %s\n", - progname, filename, strerror(errno)); - exit(1); - } - - (void)close(fd); - - exit(0); -} diff --git a/BasiliskII/src/Unix/Darwin/mkstandalone b/BasiliskII/src/Unix/Darwin/mkstandalone deleted file mode 100755 index 7da10e38..00000000 --- a/BasiliskII/src/Unix/Darwin/mkstandalone +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/sh -# -# mkstandalone - Make a standalone bundle with GTK runtime -# -# Basilisk II (C) 1997-2006 Christian Bauer -# -# mkstandalone Copyright (C) 2006 Gwenole Beauchesne -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -PROG="${1%.app}" - -[ -n "$PROG" ] || { - echo "Usage: ${0##*/} " - exit 1 -} - -[ -d "$PROG.app" ] || { - echo "ERROR: $PROG.app bundle does not exist" - exit 1 -} - -[ -x "$PROG.app/Contents/MacOS/$PROG" ] || { - echo "ERROR: $PROG.app is not a properly formed bundle" - exit 1 -} - -echo "Processing bundle $PROG.app" - -FRAMEWORKS="GLib GDK GTK" - -rm -r -f $PROG.app/Contents/Frameworks -mkdir -p $PROG.app/Contents/Frameworks - -int_args="" -for fmk_path in `otool -L $PROG.app/Contents/MacOS/$PROG | \ - sed -n '/ *\(\/.*\.framework\/.*\) ([^)]*)/s//\1/p'` -do - fmk_spath="${fmk_path%/Versions/*}" - fmk="${fmk_spath%.framework}" - fmk="${fmk##*/}" - - case " $FRAMEWORKS " in - (*" $fmk "*) ;; - (*) continue ;; - esac - - echo " Linking in framework $fmk" - fmk_dpath=$PROG.app/Contents/Frameworks/$fmk.framework - rm -rf $fmk_dpath - cp -Rf $fmk_spath $fmk_dpath - find $fmk_dpath -name "*Headers*" | xargs rm -rf - fmk_vpath="${fmk_path##*.framework/}" - - # change library dependency - install_name_tool -change \ - $fmk_spath/$fmk_vpath \ - @executable_path/../Frameworks/$fmk.framework/$fmk_vpath \ - $PROG.app/Contents/MacOS/$PROG - - # change shared library id name - fmk_newid="@executable_path/../Frameworks/${fmk_path#*/Frameworks/}" - install_name_tool -id $fmk_newid $fmk_dpath/$fmk_vpath - - # expand final install_name_tool args list - int_args="$int_args -change $fmk_path $fmk_newid" - - # strip shared library - strip -x $fmk_dpath/$fmk_vpath -done - -# change remaining dependency libs names -for f in $FRAMEWORKS; do - install_name_tool $int_args $PROG.app/Contents/Frameworks/$f.framework/$f -done - -exit 0 diff --git a/BasiliskII/src/Unix/Darwin/pagezero.c b/BasiliskII/src/Unix/Darwin/pagezero.c deleted file mode 100644 index 6f3f061e..00000000 --- a/BasiliskII/src/Unix/Darwin/pagezero.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * pagezero.c - test to see if low memory globals can be accessed - * - * Copyright (c) 2003 Michael Z. Sliczniak - * - * Basilisk II (C) 1997-2003 Christian Bauer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -int -main(int argc, const char *argv[]) -{ - volatile char *pagezero = (void *)0; - - pagezero[0x1234] = pagezero[0x123]; - - return (0); -} diff --git a/BasiliskII/src/Unix/Darwin/testlmem.sh b/BasiliskII/src/Unix/Darwin/testlmem.sh deleted file mode 100755 index 3c07f437..00000000 --- a/BasiliskII/src/Unix/Darwin/testlmem.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -# testlmem.sh - test whether the Mach-O hack works -# -# Basilisk II (C) 1997-2005 Christian Bauer -# -# testlmem.sh Copyright (C) 2003 Michael Z. Sliczniak -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -PAGEZERO_SIZE=0x2000 -[[ -n "$1" ]] && PAGEZERO_SIZE=$1 -# You want all the output to go to stderr so that configure is quiet but -# config.log is verbose. -{ echo 'building lowmem utility' && \ -make -f /dev/null Darwin/lowmem && \ -echo 'building pagezero test' && \ -make -f /dev/null LDFLAGS="-pagezero_size $PAGEZERO_SIZE" Darwin/pagezero && \ -echo 'enabling low memory globals in pagezero' && \ -Darwin/lowmem Darwin/pagezero && \ -echo 'running pagezero test' && \ -Darwin/pagezero; } 1>&2 From 8c0a84c536f429dd2ff068c5f5515e1512940fd6 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Thu, 7 Jun 2018 15:06:41 -0500 Subject: [PATCH 09/20] Removed more unused files --- BasiliskII/src/Unix/CMakeLists.txt | 2 - BasiliskII/src/Unix/main_unix.cpp | 41 - BasiliskII/src/Unix/posix_sem.cpp | 143 ---- BasiliskII/src/Unix/rpc.h | 102 --- BasiliskII/src/Unix/rpc_unix.cpp | 1257 ---------------------------- BasiliskII/src/Unix/semaphore.h | 44 - 6 files changed, 1589 deletions(-) delete mode 100644 BasiliskII/src/Unix/posix_sem.cpp delete mode 100644 BasiliskII/src/Unix/rpc.h delete mode 100644 BasiliskII/src/Unix/rpc_unix.cpp delete mode 100644 BasiliskII/src/Unix/semaphore.h diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index 4454d69a..c47046b3 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -48,7 +48,6 @@ set(BasiliskII_SRCS ../extfs.cpp ../user_strings.cpp user_strings_unix.cpp - rpc_unix.cpp # XPLAT_SRCS ../CrossPlatform/vm_alloc.cpp ../CrossPlatform/sigsegv.cpp @@ -67,7 +66,6 @@ set(BasiliskII_SRCS ../dummy/scsi_dummy.cpp #audio src ../SDL/audio_sdl.cpp - #sem src: posix_sem.cpp #ui src ../dummy/prefs_editor_dummy.cpp #extra sys diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 05f9717d..36814ffa 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -55,7 +55,6 @@ using std::string; #include "main.h" #include "vm_alloc.h" #include "sigsegv.h" -#include "rpc.h" #if USE_JIT extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp @@ -108,11 +107,6 @@ static timer_t timer; // 60Hz timer #endif #endif // !HAVE_PTHREADS - -static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI -static const char *gui_connection_path = NULL; // GUI connection identifier - - // Prototypes static int xpram_func(void *arg); static int tick_func(void *arg); @@ -300,12 +294,6 @@ int main(int argc, char **argv) for (int i=1; i -#include -#include -#include -#include - -#include "semaphore.h" - -extern "C" { - -int sem_init(sem_t* sem, int pshared, unsigned int value) -{ - if(sem==NULL||value>SEM_VALUE_MAX) { - errno = EINVAL; - return -1; - } - if(pshared) { - errno = ENOSYS; - return -1; - } - pthread_mutex_init(&sem->sem_lock, NULL); - sem->sem_value = value; - sem->sem_waiting = 0; - return 0; -} - - -int sem_destroy(sem_t* sem) -{ - if(sem==NULL) { - errno = EINVAL; - return -1; - } - if(sem->sem_waiting) { - errno = EBUSY; - return -1; - } - pthread_mutex_destroy(&sem->sem_lock); - sem->sem_waiting = 0; - sem->sem_value = 0; - return 0; -} - -sem_t sem_open(const char* name, int oflag, ...) -{ - errno = ENOSYS; - return *(sem_t*)NULL; -} - -int sem_close(sem_t* sem) -{ - errno = ENOSYS; - return -1; -} - -int sem_unlink(const char* name) -{ - errno = ENOSYS; - return -1; -} - -int sem_wait(sem_t* sem) -{ - struct timespec req = { 1, 0 }; - - if(sem==NULL) { - errno = EINVAL; - return -1; - } - pthread_mutex_lock(&sem->sem_lock); - sem->sem_waiting++; - if(sem->sem_value > 0) { - --sem->sem_value; - return 0; - } - while(!sem->sem_value) nanosleep(NULL, &req); - pthread_mutex_unlock(&sem->sem_lock); - return 0; -} - -int sem_trywait(sem_t* sem) -{ - errno = ENOSYS; - return -1; -} - -int sem_post(sem_t* sem) -{ - if(sem==NULL) { - errno = EINVAL; - return -1; - } - if(!sem->sem_waiting) { - if(sem->sem_value >= SEM_VALUE_MAX) { - errno = ERANGE; - pthread_mutex_unlock(&sem->sem_lock); - return -1; - } - ++sem->sem_value; - pthread_mutex_unlock(&sem->sem_lock); - } - else { - sem->sem_waiting--; - ++sem->sem_value; -// pthread_mutex_unlock(&sem->sem_lock); - } - return 0; -} - -int sem_getvalue(sem_t* sem, int* sval) -{ - errno = ENOSYS; - return -1; -} - -} diff --git a/BasiliskII/src/Unix/rpc.h b/BasiliskII/src/Unix/rpc.h deleted file mode 100644 index a43dfaef..00000000 --- a/BasiliskII/src/Unix/rpc.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * rpc.h - Remote Procedure Calls - * - * Basilisk II (C) 1997-2008 Christian Bauer - * Contributed by Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef RPC_H -#define RPC_H - -// Error Types -enum { - RPC_ERROR_NO_ERROR = 0, - RPC_ERROR_GENERIC = -1000, - RPC_ERROR_ERRNO_SET = -1001, - RPC_ERROR_NO_MEMORY = -1002, - RPC_ERROR_CONNECTION_NULL = -1003, - RPC_ERROR_CONNECTION_TYPE_MISMATCH = -1004, - RPC_ERROR_MESSAGE_TRUNCATED = -1005, - RPC_ERROR_MESSAGE_ARGUMENT_MISMATCH = -1006, - RPC_ERROR_MESSAGE_ARGUMENT_UNKNOWN = -1007, -}; - -// Connection Handling -typedef struct rpc_connection_t rpc_connection_t; -extern rpc_connection_t *rpc_init_server(const char *ident); -extern rpc_connection_t *rpc_init_client(const char *ident); -extern int rpc_exit(rpc_connection_t *connection); -extern int rpc_listen_socket(rpc_connection_t *connection); -extern int rpc_listen(rpc_connection_t *connection); -extern int rpc_dispatch(rpc_connection_t *connection); -extern int rpc_wait_dispatch(rpc_connection_t *connection, int timeout); -extern int rpc_connection_busy(rpc_connection_t *connection); - -// Message Passing -enum { - RPC_TYPE_INVALID = 0, - RPC_TYPE_CHAR = -2000, - RPC_TYPE_BOOLEAN = -2001, - RPC_TYPE_INT32 = -2002, - RPC_TYPE_UINT32 = -2003, - RPC_TYPE_STRING = -2004, - RPC_TYPE_ARRAY = -2005, -}; -typedef struct rpc_message_t rpc_message_t; -extern int rpc_message_send_char(rpc_message_t *message, char c); -extern int rpc_message_send_int32(rpc_message_t *message, int32_t value); -extern int rpc_message_send_uint32(rpc_message_t *message, uint32_t value); -extern int rpc_message_send_string(rpc_message_t *message, const char *str); -extern int rpc_message_send_bytes(rpc_message_t *message, unsigned char *bytes, int count); -extern int rpc_message_recv_char(rpc_message_t *message, char *ret); -extern int rpc_message_recv_int32(rpc_message_t *message, int32_t *ret); -extern int rpc_message_recv_uint32(rpc_message_t *message, uint32_t *ret); -extern int rpc_message_recv_string(rpc_message_t *message, char **ret); -extern int rpc_message_recv_bytes(rpc_message_t *message, unsigned char *bytes, int count); -typedef int (*rpc_message_callback_t)(rpc_message_t *message, void *p_value); -typedef struct { - int id; - int size; - rpc_message_callback_t send_callback; - rpc_message_callback_t recv_callback; -} rpc_message_descriptor_t; -extern int rpc_message_add_callbacks(const rpc_message_descriptor_t *descs, int n_descs); - -// Method Callbacks Handling -typedef int (*rpc_method_callback_t)(rpc_connection_t *connection); -typedef struct { - int id; - rpc_method_callback_t callback; -} rpc_method_descriptor_t; -extern int rpc_method_add_callbacks(rpc_connection_t *connection, const rpc_method_descriptor_t *descs, int n_descs); -extern int rpc_method_remove_callback_id(rpc_connection_t *connection, int id); -extern int rpc_method_remove_callbacks(rpc_connection_t *connection, const rpc_method_descriptor_t *descs, int n_descs); - -// Remote Procedure Call (method invocation) -extern int rpc_method_invoke(rpc_connection_t *connection, int method, ...); -extern int rpc_method_wait_for_reply(rpc_connection_t *connection, ...); -extern int rpc_method_get_args(rpc_connection_t *connection, ...); -extern int rpc_method_send_reply(rpc_connection_t *connection, ...); - -// Message Protocol -enum { - RPC_METHOD_ERROR_ALERT = 1, - RPC_METHOD_WARNING_ALERT, - RPC_METHOD_EXIT -}; - -#endif /* RPC_H */ diff --git a/BasiliskII/src/Unix/rpc_unix.cpp b/BasiliskII/src/Unix/rpc_unix.cpp deleted file mode 100644 index cbc23b60..00000000 --- a/BasiliskII/src/Unix/rpc_unix.cpp +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * rpc_unix.cpp - Remote Procedure Calls, Unix specific backend - * - * Basilisk II (C) 1997-2008 Christian Bauer - * Contributed by Gwenole Beauchesne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * NOTES: - * - this is subject to rewrite but the API is to be kept intact - * - this RPC system is very minimal and only suited for 1:1 communication - * - * TODO: - * - better failure conditions - * - windows rpc - */ - -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rpc.h" - -#define DEBUG 0 -#include "debug.h" - -#define NON_BLOCKING_IO 0 - -/* ====================================================================== */ -/* === PThreads Glue === */ -/* ====================================================================== */ - -//#define USE_THREADS - -#ifndef USE_THREADS -#define pthread_t void * -#define pthread_cancel(th) -#define pthread_join(th, ret) -#define pthread_testcancel() -#define pthread_create(th, attr, start, arg) dummy_thread_create() -static inline int dummy_thread_create(void) { errno = ENOSYS; return -1; } - -#undef pthread_mutex_t -#define pthread_mutex_t volatile int -#undef pthread_mutex_lock -#define pthread_mutex_lock(m) -1 -#undef pthread_mutex_unlock -#define pthread_mutex_unlock(m) -1 -#undef PTHREAD_MUTEX_INITIALIZER -#define PTHREAD_MUTEX_INITIALIZER 0 -#endif - - -/* ====================================================================== */ -/* === RPC Connection Handling === */ -/* ====================================================================== */ - -// Connection type -enum { - RPC_CONNECTION_SERVER, - RPC_CONNECTION_CLIENT, -}; - -// Connection status -enum { - RPC_STATUS_IDLE, - RPC_STATUS_BUSY, -}; - -// Client / Server connection -struct rpc_connection_t { - int type; - int status; - int socket; - char *socket_path; - int server_socket; - int server_thread_active; - pthread_t server_thread; - rpc_method_descriptor_t *callbacks; - int n_callbacks; - int send_offset; - char send_buffer[BUFSIZ]; -}; - -#define return_error(ERROR) do { error = (ERROR); goto do_return; } while (0) - -// Set connection status (XXX protect connection with a lock?) -static inline void rpc_connection_set_status(rpc_connection_t *connection, int status) -{ - connection->status = status; -} - -// Returns TRUE if the connection is busy (e.g. waiting for a reply) -int rpc_connection_busy(rpc_connection_t *connection) -{ - return connection && connection->status == RPC_STATUS_BUSY; -} - -// Prepare socket path for addr.sun_path[] -static int _rpc_socket_path(char **pathp, const char *ident) -{ - int i, len; - len = strlen(ident); - - if (pathp == NULL) - return 0; - - char *path; -#if USE_ABSTRACT_NAMESPACES - const int len_bias = 1; - if ((path = (char *)malloc(len + len_bias + 1)) == NULL) - return 0; - path[0] = 0; - strcpy(&path[len_bias], ident); -#else - const int len_bias = 5; - if ((path = (char *)malloc(len + len_bias + 1)) == NULL) - return 0; - strcpy(path, "/tmp/"); - for (i = 0; i < len; i++) { - char ch = ident[i]; - if (ch == '/') - ch = '_'; - path[len_bias + i] = ch; - } -#endif - len += len_bias; - path[len] = '\0'; - if (*pathp) - free(*pathp); - *pathp = path; - return len; -} - -// Initialize server-side RPC system -rpc_connection_t *rpc_init_server(const char *ident) -{ - D(bug("rpc_init_server ident='%s'\n", ident)); - - rpc_connection_t *connection; - struct sockaddr_un addr; - socklen_t addr_len; - - if (ident == NULL) - return NULL; - - connection = (rpc_connection_t *)malloc(sizeof(*connection)); - if (connection == NULL) - return NULL; - connection->type = RPC_CONNECTION_SERVER; - connection->status = RPC_STATUS_IDLE; - connection->socket = -1; - connection->server_thread_active = 0; - connection->callbacks = NULL; - connection->n_callbacks = 0; - - if ((connection->server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - perror("server socket"); - free(connection); - return NULL; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - connection->socket_path = NULL; - addr_len = _rpc_socket_path(&connection->socket_path, ident); - memcpy(&addr.sun_path[0], connection->socket_path, addr_len); - addr_len += sizeof(struct sockaddr_un) - sizeof(addr.sun_path); - - if (bind(connection->server_socket, (struct sockaddr *)&addr, addr_len) < 0) { - perror("server bind"); - close(connection->socket); - free(connection); - return NULL; - } - - if (listen(connection->server_socket, 1) < 0) { - perror("server listen"); - close(connection->socket); - free(connection); - return NULL; - } - - return connection; -} - -// Initialize client-side RPC system -rpc_connection_t *rpc_init_client(const char *ident) -{ - D(bug("rpc_init_client ident='%s'\n", ident)); - - rpc_connection_t *connection; - struct sockaddr_un addr; - socklen_t addr_len; - - if (ident == NULL) - return NULL; - - connection = (rpc_connection_t *)malloc(sizeof(*connection)); - if (connection == NULL) - return NULL; - connection->type = RPC_CONNECTION_CLIENT; - connection->status = RPC_STATUS_IDLE; - connection->server_socket = -1; - connection->callbacks = NULL; - connection->n_callbacks = 0; - - if ((connection->socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - perror("client socket"); - free(connection); - return NULL; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - connection->socket_path = NULL; - addr_len = _rpc_socket_path(&connection->socket_path, ident); - memcpy(&addr.sun_path[0], connection->socket_path, addr_len); - addr_len += sizeof(struct sockaddr_un) - sizeof(addr.sun_path); - - // Wait at most 5 seconds for server to initialize - const int N_CONNECT_WAIT_DELAY = 10; - int n_connect_attempts = 5000 / N_CONNECT_WAIT_DELAY; - if (n_connect_attempts == 0) - n_connect_attempts = 1; - while (n_connect_attempts > 0) { - if (connect(connection->socket, (struct sockaddr *)&addr, addr_len) == 0) - break; - if (n_connect_attempts > 1 && errno != ECONNREFUSED && errno != ENOENT) { - perror("client_connect"); - close(connection->socket); - free(connection); - return NULL; - } - n_connect_attempts--; - usleep(N_CONNECT_WAIT_DELAY); - } - if (n_connect_attempts == 0) { - close(connection->socket); - free(connection); - return NULL; - } - - return connection; -} - -// Close RPC connection -int rpc_exit(rpc_connection_t *connection) -{ - D(bug("rpc_exit\n")); - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - - if (connection->socket_path) { - if (connection->socket_path[0]) - unlink(connection->socket_path); - free(connection->socket_path); - } - - if (connection->type == RPC_CONNECTION_SERVER) { - if (connection->server_thread_active) { - pthread_cancel(connection->server_thread); - pthread_join(connection->server_thread, NULL); - } - if (connection->socket != -1) - close(connection->socket); - if (connection->server_socket != -1) - close(connection->server_socket); - } - else { - if (connection->socket != -1) - close(connection->socket); - } - - if (connection->callbacks) - free(connection->callbacks); - free(connection); - - return RPC_ERROR_NO_ERROR; -} - -// Wait for a message to arrive on the connection port -static inline int _rpc_wait_dispatch(rpc_connection_t *connection, int timeout) -{ - struct timeval tv; - tv.tv_sec = timeout / 1000000; - tv.tv_usec = timeout % 1000000; - - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(connection->socket, &rfds); - return select(connection->socket + 1, &rfds, NULL, NULL, &tv); -} - -int rpc_wait_dispatch(rpc_connection_t *connection, int timeout) -{ - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_SERVER) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - return _rpc_wait_dispatch(connection, timeout); -} - -#ifdef USE_THREADS -// Process incoming messages in the background -static void *rpc_server_func(void *arg) -{ - rpc_connection_t *connection = (rpc_connection_t *)arg; - - int ret = rpc_listen_socket(connection); - if (ret < 0) - return NULL; - - connection->server_thread_active = 1; - for (;;) { - // XXX broken MacOS X doesn't implement cancellation points correctly - pthread_testcancel(); - - // wait for data to arrive - int ret = _rpc_wait_dispatch(connection, 50000); - if (ret == 0) - continue; - if (ret < 0) - break; - - rpc_dispatch(connection); - } - connection->server_thread_active = 0; - return NULL; -} -#endif - -// Return listen socket of RPC connection -int rpc_listen_socket(rpc_connection_t *connection) -{ - D(bug("rpc_listen_socket\n")); - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_SERVER) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - struct sockaddr_un addr; - socklen_t addr_len = sizeof(addr); - if ((connection->socket = accept(connection->server_socket, (struct sockaddr *)&addr, &addr_len)) < 0) { - perror("server accept"); - return RPC_ERROR_ERRNO_SET; - } - -#if NON_BLOCKING_IO - int val = fcntl(connection->socket, F_GETFL, 0); - if (val < 0) { - perror("server fcntl F_GETFL"); - return RPC_ERROR_ERRNO_SET; - } - if (fcntl(connection->socket, F_SETFL, val | O_NONBLOCK) < 0) { - perror("server fcntl F_SETFL"); - return RPC_ERROR_ERRNO_SET; - } -#endif - - return connection->socket; -} - -// Listen for incoming messages on RPC connection -#ifdef USE_THREADS -int rpc_listen(rpc_connection_t *connection) -{ - D(bug("rpc_listen\n")); - - if (pthread_create(&connection->server_thread, NULL, rpc_server_func, connection) != 0) { - perror("server thread"); - return RPC_ERROR_ERRNO_SET; - } - - return RPC_ERROR_NO_ERROR; -} -#endif - - -/* ====================================================================== */ -/* === Message Passing === */ -/* ====================================================================== */ - -// Message markers -enum { - RPC_MESSAGE_START = -3000, - RPC_MESSAGE_END = -3001, - RPC_MESSAGE_ACK = -3002, - RPC_MESSAGE_REPLY = -3003, - RPC_MESSAGE_FAILURE = -3004, -}; - -// Message type -struct rpc_message_t { - int socket; - int offset; - unsigned char buffer[BUFSIZ]; -}; - -// User-defined marshalers -static struct { - rpc_message_descriptor_t *descs; - int last; - int count; -} g_message_descriptors = { NULL, 0, 0 }; -static pthread_mutex_t g_message_descriptors_lock = PTHREAD_MUTEX_INITIALIZER; - -// Add a user-defined marshaler -static int rpc_message_add_callback(const rpc_message_descriptor_t *desc) -{ - D(bug("rpc_message_add_callback\n")); - - const int N_ENTRIES_ALLOC = 8; - int error = RPC_ERROR_NO_ERROR; - - pthread_mutex_lock(&g_message_descriptors_lock); - if (g_message_descriptors.descs == NULL) { - g_message_descriptors.count = N_ENTRIES_ALLOC; - if ((g_message_descriptors.descs = (rpc_message_descriptor_t *)malloc(g_message_descriptors.count * sizeof(g_message_descriptors.descs[0]))) == NULL) { - pthread_mutex_unlock(&g_message_descriptors_lock); - return RPC_ERROR_NO_MEMORY; - } - g_message_descriptors.last = 0; - } - else if (g_message_descriptors.last >= g_message_descriptors.count) { - g_message_descriptors.count += N_ENTRIES_ALLOC; - if ((g_message_descriptors.descs = (rpc_message_descriptor_t *)realloc(g_message_descriptors.descs, g_message_descriptors.count * sizeof(g_message_descriptors.descs[0]))) == NULL) { - pthread_mutex_unlock(&g_message_descriptors_lock); - return RPC_ERROR_NO_MEMORY; - } - } - - // XXX only one callback per ID - int i; - for (i = 0; i < g_message_descriptors.last; i++) { - if (g_message_descriptors.descs[i].id == desc->id) { - pthread_mutex_unlock(&g_message_descriptors_lock); - return RPC_ERROR_NO_ERROR; - } - } - - g_message_descriptors.descs[g_message_descriptors.last++] = *desc; - pthread_mutex_unlock(&g_message_descriptors_lock); - return error; -} - -// Add user-defined marshalers -int rpc_message_add_callbacks(const rpc_message_descriptor_t *descs, int n_descs) -{ - D(bug("rpc_message_add_callbacks\n")); - - int i, error; - for (i = 0; i < n_descs; i++) { - if ((error = rpc_message_add_callback(&descs[i])) < 0) - return error; - } - - return RPC_ERROR_NO_ERROR; -} - -// Find user-defined marshaler -static rpc_message_descriptor_t *rpc_message_find_descriptor(int id) -{ - D(bug("rpc_message_find_descriptor\n")); - - if (g_message_descriptors.descs) { - int i; - for (i = 0; i < g_message_descriptors.count; i++) { - if (g_message_descriptors.descs[i].id == id) - return &g_message_descriptors.descs[i]; - } - } - - return NULL; -} - -// Initialize message -static inline void rpc_message_init(rpc_message_t *message, rpc_connection_t *connection) -{ - message->socket = connection->socket; - message->offset = 0; -} - -// Send BYTES -static inline int _rpc_message_send_bytes(rpc_message_t *message, unsigned char *bytes, int count) -{ - if (send(message->socket, bytes, count, 0) != count) - return RPC_ERROR_ERRNO_SET; - return RPC_ERROR_NO_ERROR; -} - -// Send message on wire -static inline int rpc_message_flush(rpc_message_t *message) -{ - int error = _rpc_message_send_bytes(message, message->buffer, message->offset); - message->offset = 0; - return error; -} - -// Send BYTES (public interface, may need to flush internal buffer) -int rpc_message_send_bytes(rpc_message_t *message, unsigned char *bytes, int count) -{ - if (message->offset > 0) { - int error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - return _rpc_message_send_bytes(message, bytes, count); -} - -// Send BYTES (buffered) -static inline void _rpc_message_send_bytes_buffered(rpc_message_t *message, unsigned char *bytes, int count) -{ - memcpy(&message->buffer[message->offset], bytes, count); - message->offset += count; -} - -// Send CHAR -int rpc_message_send_char(rpc_message_t *message, char c) -{ - D(bug(" send CHAR '%c'\n", c)); - - unsigned char e_value = c; - if (message->offset + sizeof(e_value) >= sizeof(message->buffer)) { - int error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - _rpc_message_send_bytes_buffered(message, (unsigned char *)&e_value, sizeof(e_value)); - return RPC_ERROR_NO_ERROR; -} - -// Send INT32 -int rpc_message_send_int32(rpc_message_t *message, int32_t value) -{ - D(bug(" send INT32 %d\n", value)); - - int32_t e_value = htonl(value); - if (message->offset + sizeof(e_value) >= sizeof(message->buffer)) { - int error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - _rpc_message_send_bytes_buffered(message, (unsigned char *)&e_value, sizeof(e_value)); - return RPC_ERROR_NO_ERROR; -} - -// Send UINT32 -int rpc_message_send_uint32(rpc_message_t *message, uint32_t value) -{ - D(bug(" send UINT32 %u\n", value)); - - uint32_t e_value = htonl(value); - if (message->offset + sizeof(e_value) >= sizeof(message->buffer)) { - int error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - _rpc_message_send_bytes_buffered(message, (unsigned char *)&e_value, sizeof(e_value)); - return RPC_ERROR_NO_ERROR; -} - -// Send STRING -int rpc_message_send_string(rpc_message_t *message, const char *str) -{ - D(bug(" send STRING \"%s\"\n", str)); - - int error, length = str ? strlen(str) : 0; - uint32_t e_value = htonl(length); - if (message->offset + sizeof(e_value) >= sizeof(message->buffer)) { - error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - _rpc_message_send_bytes_buffered(message, (unsigned char *)&e_value, sizeof(e_value)); - error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - D(bug("str=%p\n", str)); - return _rpc_message_send_bytes(message, (unsigned char *)str, length); -} - -// Send message arguments -static int rpc_message_send_args(rpc_message_t *message, va_list args) -{ - int type; - rpc_message_descriptor_t *desc; - while ((type = va_arg(args, int)) != RPC_TYPE_INVALID) { - int error = rpc_message_send_int32(message, type); - if (error != RPC_ERROR_NO_ERROR) - return error; - switch (type) { - case RPC_TYPE_CHAR: - error = rpc_message_send_char(message, (char )va_arg(args, int)); - break; - case RPC_TYPE_BOOLEAN: - case RPC_TYPE_INT32: - error = rpc_message_send_int32(message, va_arg(args, int)); - break; - case RPC_TYPE_UINT32: - error = rpc_message_send_uint32(message, va_arg(args, unsigned int)); - break; - case RPC_TYPE_STRING: - error = rpc_message_send_string(message, va_arg(args, char *)); - break; - case RPC_TYPE_ARRAY: { - int i; - int array_type = va_arg(args, int32_t); - int array_size = va_arg(args, uint32_t); - if ((error = rpc_message_send_int32(message, array_type)) < 0) - return error; - if ((error = rpc_message_send_uint32(message, array_size)) < 0) - return error; - switch (array_type) { - case RPC_TYPE_CHAR: { - unsigned char *array = va_arg(args, unsigned char *); - error = rpc_message_flush(message); - if (error != RPC_ERROR_NO_ERROR) - return error; - error = _rpc_message_send_bytes(message, array, array_size); - break; - } - case RPC_TYPE_BOOLEAN: - case RPC_TYPE_INT32: { - int32_t *array = va_arg(args, int32_t *); - for (i = 0; i < array_size; i++) { - if ((error = rpc_message_send_int32(message, array[i])) < 0) - break; - } - break; - } - case RPC_TYPE_UINT32: { - uint32_t *array = va_arg(args, uint32_t *); - for (i = 0; i < array_size; i++) { - if ((error = rpc_message_send_uint32(message, array[i])) < 0) - break; - } - break; - } - case RPC_TYPE_STRING: { - char **array = va_arg(args, char **); - for (i = 0; i < array_size; i++) { - if ((error = rpc_message_send_string(message, array[i])) < 0) - break; - } - break; - } - default: - if ((desc = rpc_message_find_descriptor(array_type)) != NULL) { - uint8_t *array = va_arg(args, uint8_t *); - for (i = 0; i < array_size; i++) { - if ((error = desc->send_callback(message, &array[i * desc->size])) < 0) - break; - } - } - else { - fprintf(stderr, "unknown array arg type %d to send\n", type); - error = RPC_ERROR_MESSAGE_ARGUMENT_UNKNOWN; - } - break; - } - break; - } - default: - if ((desc = rpc_message_find_descriptor(type)) != NULL) - error = desc->send_callback(message, va_arg(args, uint8_t *)); - else { - fprintf(stderr, "unknown arg type %d to send\n", type); - error = RPC_ERROR_MESSAGE_ARGUMENT_UNKNOWN; - } - break; - } - if (error != RPC_ERROR_NO_ERROR) - return error; - } - return RPC_ERROR_NO_ERROR; -} - -// Receive raw BYTES -static inline int _rpc_message_recv_bytes(rpc_message_t *message, unsigned char *bytes, int count) -{ - do { - int n = recv(message->socket, bytes, count, 0); - if (n > 0) { - count -= n; - bytes += n; - } - else if (n == -1 && errno == EINTR) - continue; - else { -#if NON_BLOCKING_IO - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // wait for data to arrive - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(message->socket, &rfds); - int ret = select(message->socket + 1, &rfds, NULL, NULL, NULL); - if (ret > 0) - continue; - } -#endif - return RPC_ERROR_ERRNO_SET; - } - } while (count > 0); - return RPC_ERROR_NO_ERROR; -} - -int rpc_message_recv_bytes(rpc_message_t *message, unsigned char *bytes, int count) -{ - return _rpc_message_recv_bytes(message, bytes, count); -} - -// Receive CHAR -int rpc_message_recv_char(rpc_message_t *message, char *ret) -{ - char r_value; - int error; - if ((error = _rpc_message_recv_bytes(message, (unsigned char *)&r_value, sizeof(r_value))) < 0) - return error; - *ret = r_value; - D(bug(" recv CHAR '%c'\n", *ret)); - return RPC_ERROR_NO_ERROR; -} - -// Receive INT32 -int rpc_message_recv_int32(rpc_message_t *message, int32_t *ret) -{ - int32_t r_value; - int error; - if ((error = _rpc_message_recv_bytes(message, (unsigned char *)&r_value, sizeof(r_value))) < 0) - return error; - *ret = ntohl(r_value); - D(bug(" recv INT32 %d\n", *ret)); - return RPC_ERROR_NO_ERROR; -} - -// Receive UINT32 -int rpc_message_recv_uint32(rpc_message_t *message, uint32_t *ret) -{ - uint32_t r_value; - int error; - if ((error = _rpc_message_recv_bytes(message, (unsigned char *)&r_value, sizeof(r_value))) < 0) - return error; - *ret = ntohl(r_value); - D(bug(" recv UINT32 %u\n", *ret)); - return RPC_ERROR_NO_ERROR; -} - -// Receive STRING -int rpc_message_recv_string(rpc_message_t *message, char **ret) -{ - char *str; - int length; - uint32_t r_value; - int error; - if ((error = _rpc_message_recv_bytes(message, (unsigned char *)&r_value, sizeof(r_value))) < 0) - return error; - length = ntohl(r_value); - if (length == 0) { - str = NULL; - } else { - if ((str = (char *)malloc(length + 1)) == NULL) - return RPC_ERROR_NO_MEMORY; - if ((error = _rpc_message_recv_bytes(message, (unsigned char *)str, length)) < 0) { - free(str); - return error; - } - str[length] = '\0'; - } - *ret = str; - D(bug(" recv STRING \"%s\"\n", *ret)); - return RPC_ERROR_NO_ERROR; -} - -// Receive message arguments -static int rpc_message_recv_args(rpc_message_t *message, va_list args) -{ - int expected_type, error; - rpc_message_descriptor_t *desc; - - while ((expected_type = va_arg(args, int)) != RPC_TYPE_INVALID) { - void *p_value = va_arg(args, void *); - int32_t type; - if ((error = rpc_message_recv_int32(message, &type)) < 0) - return error; - if (type != expected_type) - return RPC_ERROR_MESSAGE_ARGUMENT_MISMATCH; - switch (type) { - case RPC_TYPE_CHAR: - error = rpc_message_recv_char(message, (char *)p_value); - break; - case RPC_TYPE_BOOLEAN: - case RPC_TYPE_INT32: - error = rpc_message_recv_int32(message, (int32_t *)p_value); - break; - case RPC_TYPE_UINT32: - error = rpc_message_recv_uint32(message, (uint32_t *)p_value); - break; - case RPC_TYPE_STRING: - error = rpc_message_recv_string(message, (char **)p_value); - break; - case RPC_TYPE_ARRAY: { - int i; - int32_t array_type; - uint32_t array_size; - if ((error = rpc_message_recv_int32(message, &array_type)) < 0) - return error; - if ((error = rpc_message_recv_uint32(message, &array_size)) < 0) - return error; - p_value = va_arg(args, void *); - *((uint32_t *)p_value) = array_size; - p_value = va_arg(args, void *); - switch (array_type) { - case RPC_TYPE_CHAR: { - unsigned char *array; - if ((array = (unsigned char *)malloc(array_size * sizeof(*array))) == NULL) - return RPC_ERROR_NO_MEMORY; - error = _rpc_message_recv_bytes(message, array, array_size); - if (error != RPC_ERROR_NO_ERROR) { - free(array); - return error; - } - *((void **)p_value) = (void *)array; - break; - } - case RPC_TYPE_BOOLEAN: - case RPC_TYPE_INT32: { - int *array; - if ((array = (int *)malloc(array_size * sizeof(*array))) == NULL) - return RPC_ERROR_NO_MEMORY; - for (i = 0; i < array_size; i++) { - int32_t value; - if ((error = rpc_message_recv_int32(message, &value)) < 0) { - free(array); - return error; - } - array[i] = value; - } - *((void **)p_value) = (void *)array; - break; - } - case RPC_TYPE_UINT32: { - unsigned int *array; - if ((array = (unsigned int *)malloc(array_size * sizeof(*array))) == NULL) - return RPC_ERROR_NO_MEMORY; - for (i = 0; i < array_size; i++) { - uint32_t value; - if ((error = rpc_message_recv_uint32(message, &value)) < 0) { - free(array); - return error; - } - array[i] = value; - } - *((void **)p_value) = (void *)array; - break; - } - case RPC_TYPE_STRING: { - char **array; - if ((array = (char **)malloc(array_size * sizeof(*array))) == NULL) - return RPC_ERROR_NO_MEMORY; - for (i = 0; i < array_size; i++) { - char *str; - if ((error = rpc_message_recv_string(message, &str)) < 0) { - free(array); - return error; - } - array[i] = str; - } - *((void **)p_value) = (void *)array; - break; - } - default: - if ((desc = rpc_message_find_descriptor(array_type)) != NULL) { - char *array; - if ((array = (char *)malloc(array_size * desc->size)) == NULL) - return RPC_ERROR_NO_MEMORY; - for (i = 0; i < array_size; i++) { - if ((error = desc->recv_callback(message, &array[i * desc->size])) < 0) { - free(array); - return error; - } - } - *((void **)p_value) = array; - } - else { - fprintf(stderr, "unknown array arg type %d to receive\n", type); - error = RPC_ERROR_MESSAGE_ARGUMENT_UNKNOWN; - } - break; - } - break; - } - default: - if ((desc = rpc_message_find_descriptor(type)) != NULL) - error = desc->recv_callback(message, p_value); - else { - fprintf(stderr, "unknown arg type %d to send\n", type); - error = RPC_ERROR_MESSAGE_ARGUMENT_UNKNOWN; - } - break; - } - if (error != RPC_ERROR_NO_ERROR) - return error; - } - return RPC_ERROR_NO_ERROR; -} - -// Skip message argument -static int rpc_message_skip_arg(rpc_message_t *message, int type) -{ - unsigned char dummy[BUFSIZ]; - int error = RPC_ERROR_GENERIC; - switch (type) { - case RPC_TYPE_CHAR: - error = _rpc_message_recv_bytes(message, dummy, 1); - break; - case RPC_TYPE_BOOLEAN: - case RPC_TYPE_INT32: - case RPC_TYPE_UINT32: - error = _rpc_message_recv_bytes(message, dummy, 4); - break; - case RPC_TYPE_STRING: { - int32_t length; - if ((error = rpc_message_recv_int32(message, &length)) < 0) - return error; - while (length >= sizeof(dummy)) { - if ((error = _rpc_message_recv_bytes(message, dummy, sizeof(dummy))) < 0) - return error; - length -= sizeof(dummy); - } - if (length > 0) { - if ((error = _rpc_message_recv_bytes(message, dummy, length)) < 0) - return error; - } - break; - } - default: - fprintf(stderr, "unknown arg type %d to receive\n", type); - break; - } - return error; -} - -// Dispatch message received in the server loop -int rpc_dispatch(rpc_connection_t *connection) -{ - rpc_message_t message; - rpc_message_init(&message, connection); - - int32_t method, value, ret = RPC_MESSAGE_FAILURE; - if (rpc_message_recv_int32(&message, &value) != RPC_ERROR_NO_ERROR || - value != RPC_MESSAGE_START) - return ret; - - D(bug("receiving message\n")); - if (rpc_message_recv_int32(&message, &method) == RPC_ERROR_NO_ERROR && - connection->callbacks != NULL) { - int i; - for (i = 0; i < connection->n_callbacks; i++) { - if (connection->callbacks[i].id == method) { - if (connection->callbacks[i].callback && - connection->callbacks[i].callback(connection) == RPC_ERROR_NO_ERROR) { - if (rpc_message_recv_int32(&message, &value) == RPC_ERROR_NO_ERROR && value == RPC_MESSAGE_END) - ret = RPC_MESSAGE_ACK; - else { - fprintf(stderr, "corrupted message handler %d\n", method); - for (;;) { - if (rpc_message_skip_arg(&message, value) != RPC_ERROR_NO_ERROR) - break; - if (rpc_message_recv_int32(&message, &value) != RPC_ERROR_NO_ERROR) - break; - if (value == RPC_MESSAGE_END) - break; - } - } - break; - } - } - } - } - rpc_message_send_int32(&message, ret); - rpc_message_flush(&message); - D(bug(" -- message received\n")); - return ret == RPC_MESSAGE_ACK ? method : ret; -} - - -/* ====================================================================== */ -/* === Method Callbacks Handling === */ -/* ====================================================================== */ - -// Add a user-defined method callback (server side) -static int rpc_method_add_callback(rpc_connection_t *connection, const rpc_method_descriptor_t *desc) -{ - const int N_ENTRIES_ALLOC = 8; - int i; - - // pre-allocate up to N_ENTRIES_ALLOC entries - if (connection->callbacks == NULL) { - if ((connection->callbacks = (rpc_method_descriptor_t *)calloc(N_ENTRIES_ALLOC, sizeof(connection->callbacks[0]))) == NULL) - return RPC_ERROR_NO_MEMORY; - connection->n_callbacks = N_ENTRIES_ALLOC; - } - - // look for a free slot - for (i = connection->n_callbacks - 1; i >= 0; i--) { - if (connection->callbacks[i].callback == NULL) - break; - } - - // none found, reallocate - if (i < 0) { - if ((connection->callbacks = (rpc_method_descriptor_t *)realloc(connection->callbacks, (connection->n_callbacks + N_ENTRIES_ALLOC) * sizeof(connection->callbacks[0]))) == NULL) - return RPC_ERROR_NO_MEMORY; - i = connection->n_callbacks; - memset(&connection->callbacks[i], 0, N_ENTRIES_ALLOC * sizeof(connection->callbacks[0])); - connection->n_callbacks += N_ENTRIES_ALLOC; - } - - D(bug("rpc_method_add_callback for method %d in slot %d\n", desc->id, i)); - connection->callbacks[i] = *desc; - return RPC_ERROR_NO_ERROR; -} - -// Add user-defined method callbacks (server side) -int rpc_method_add_callbacks(rpc_connection_t *connection, const rpc_method_descriptor_t *descs, int n_descs) -{ - D(bug("rpc_method_add_callbacks\n")); - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_SERVER) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - while (--n_descs >= 0) { - int error = rpc_method_add_callback(connection, &descs[n_descs]); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - - return RPC_ERROR_NO_ERROR; -} - -// Remove a user-defined method callback (common code) -int rpc_method_remove_callback_id(rpc_connection_t *connection, int id) -{ - D(bug("rpc_method_remove_callback_id\n")); - - if (connection->callbacks) { - int i; - for (i = 0; i < connection->n_callbacks; i++) { - if (connection->callbacks[i].id == id) { - connection->callbacks[i].callback = NULL; - return RPC_ERROR_NO_ERROR; - } - } - } - - return RPC_ERROR_GENERIC; -} - -// Remove user-defined method callbacks (server side) -int rpc_method_remove_callbacks(rpc_connection_t *connection, const rpc_method_descriptor_t *callbacks, int n_callbacks) -{ - D(bug("rpc_method_remove_callbacks\n")); - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_SERVER) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - while (--n_callbacks >= 0) { - int error = rpc_method_remove_callback_id(connection, callbacks[n_callbacks].id); - if (error != RPC_ERROR_NO_ERROR) - return error; - } - - return RPC_ERROR_NO_ERROR; -} - - -/* ====================================================================== */ -/* === Remote Procedure Call (method invocation) === */ -/* ====================================================================== */ - -// Invoke remote procedure (client side) -int rpc_method_invoke(rpc_connection_t *connection, int method, ...) -{ - D(bug("rpc_method_invoke method=%d\n", method)); - - rpc_message_t message; - int error; - va_list args; - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_CLIENT) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - rpc_message_init(&message, connection); - error = rpc_message_send_int32(&message, RPC_MESSAGE_START); - if (error != RPC_ERROR_NO_ERROR) - return error; - error = rpc_message_send_int32(&message, method); - if (error != RPC_ERROR_NO_ERROR) - return error; - va_start(args, method); - error = rpc_message_send_args(&message, args); - va_end(args); - if (error != RPC_ERROR_NO_ERROR) - return error; - error = rpc_message_send_int32(&message, RPC_MESSAGE_END); - if (error != RPC_ERROR_NO_ERROR) - return error; - error = rpc_message_flush(&message); - if (error != RPC_ERROR_NO_ERROR) - return error; - return RPC_ERROR_NO_ERROR; -} - -// Retrieve procedure arguments (server side) -int rpc_method_get_args(rpc_connection_t *connection, ...) -{ - D(bug("rpc_method_get_args\n")); - - int error; - va_list args; - rpc_message_t message; - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_SERVER) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - rpc_message_init(&message, connection); - va_start(args, connection); - error = rpc_message_recv_args(&message, args); - va_end(args); - - return error; -} - -// Wait for a reply from the remote procedure (client side) -int rpc_method_wait_for_reply(rpc_connection_t *connection, ...) -{ - D(bug("rpc_method_wait_for_reply\n")); - - int error, type; - int32_t ret; - va_list args; - rpc_message_t message; - - if (connection == NULL) - return RPC_ERROR_CONNECTION_NULL; - if (connection->type != RPC_CONNECTION_CLIENT) - return RPC_ERROR_CONNECTION_TYPE_MISMATCH; - - rpc_connection_set_status(connection, RPC_STATUS_BUSY); - - rpc_message_init(&message, connection); - va_start(args, connection); - type = va_arg(args, int); - va_end(args); - - if (type != RPC_TYPE_INVALID) { - error = rpc_message_recv_int32(&message, &ret); - if (error != RPC_ERROR_NO_ERROR) - return_error(error); - if (ret != RPC_MESSAGE_REPLY) { - D(bug("TRUNCATED 1 [%d]\n", ret)); - return_error(RPC_ERROR_MESSAGE_TRUNCATED); - } - va_start(args, connection); - error = rpc_message_recv_args(&message, args); - va_end(args); - if (error != RPC_ERROR_NO_ERROR) - return_error(error); - error = rpc_message_recv_int32(&message, &ret); - if (error != RPC_ERROR_NO_ERROR) - return_error(error); - if (ret != RPC_MESSAGE_END) { - D(bug("TRUNCATED 2 [%d]\n", ret)); - return_error(RPC_ERROR_MESSAGE_TRUNCATED); - } - } - - error = rpc_message_recv_int32(&message, &ret); - if (error != RPC_ERROR_NO_ERROR) - return_error(error); - if (ret != RPC_MESSAGE_ACK) { - D(bug("TRUNCATED 3 [%d]\n", ret)); - return_error(RPC_ERROR_MESSAGE_TRUNCATED); - } - - return_error(RPC_ERROR_NO_ERROR); - - do_return: - rpc_connection_set_status(connection, RPC_STATUS_IDLE); - return error; -} - -// Send a reply to the client (server side) -int rpc_method_send_reply(rpc_connection_t *connection, ...) -{ - D(bug("rpc_method_send_reply\n")); - - rpc_message_t message; - int error; - va_list args; - - if (connection == NULL) - return RPC_ERROR_GENERIC; - if (connection->type != RPC_CONNECTION_SERVER) - return RPC_ERROR_GENERIC; - - rpc_message_init(&message, connection); - error = rpc_message_send_int32(&message, RPC_MESSAGE_REPLY); - if (error != RPC_ERROR_NO_ERROR) - return error; - va_start(args, connection); - error = rpc_message_send_args(&message, args); - va_end(args); - if (error != RPC_ERROR_NO_ERROR) - return error; - error = rpc_message_send_int32(&message, RPC_MESSAGE_END); - if (error != RPC_ERROR_NO_ERROR) - return error; - error = rpc_message_flush(&message); - if (error != RPC_ERROR_NO_ERROR) - return error; - return RPC_ERROR_NO_ERROR; -} diff --git a/BasiliskII/src/Unix/semaphore.h b/BasiliskII/src/Unix/semaphore.h deleted file mode 100644 index fc9954f9..00000000 --- a/BasiliskII/src/Unix/semaphore.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __SEMAPHORE_H -#define __SEMAPHORE_H - -#define SEM_VALUE_MAX 64 - -#if defined(c_plusplus) || defined(__cplusplus) -extern "C" { -#endif /* c_plusplus || __cplusplus */ - -/* MacOS X doesn't implement unnamed POSIX semaphores, event though - the libc defines them! */ -#if (defined(__MACH__) && defined(__APPLE__)) -#include -#include -#include - -#define sem_t semaphore_t -#define sem_init(SEM,UNUSED,VALUE) semaphore_create(current_task(), (SEM), SYNC_POLICY_FIFO, (VALUE)) -#define sem_destroy(SEM) semaphore_destroy(current_task(), *(SEM)) -#define sem_wait(SEM) semaphore_wait(*(SEM)) -#define sem_post(SEM) semaphore_signal(*(SEM)) -#else -typedef struct psem { - pthread_mutex_t sem_lock; - int sem_value; - int sem_waiting; -} sem_t; - -int sem_init(sem_t* sem, int pshared, unsigned int value); -int sem_destroy(sem_t* sem); -sem_t sem_open(const char* name, int oflag, ...); -int sem_close(sem_t* sem); -int sem_unlink(const char* name); -int sem_wait(sem_t* sem); -int sem_trywait(sem_t* sem); -int sem_post(sem_t* sem); -int sem_getvalue(sem_t* sem, int* sval); -#endif - -#if defined(c_plusplus) || defined(__cplusplus) -}; -#endif /* c_plusplus || __cplusplus */ - -#endif /* __SEMAPHORE_H */ From fcdfd2f799909ff479fc6535789e6c540c57acd5 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 1 Sep 2019 14:37:24 -0500 Subject: [PATCH 10/20] Cleanup of sysdeps header file --- BasiliskII/src/Unix/sysdeps.h | 299 ---------------------------------- 1 file changed, 299 deletions(-) diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index 68deb7b6..b25ee042 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -34,15 +34,6 @@ /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ -/* Define if your system supports TUN/TAP devices. */ -/* #undef ENABLE_TUNTAP */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define if your system has header. */ -/* #undef HAVE_ASM_UCONTEXT */ - /* Define to 1 if you have the `atanh' function. */ #define HAVE_ATANH 1 @@ -52,48 +43,15 @@ /* Define to 1 if the system has the type `caddr_t'. */ #define HAVE_CADDR_T 1 -/* Define to 1 if you have the `cfmakeraw' function. */ -#define HAVE_CFMAKERAW 1 - /* Define to 1 if you have the `clock_gettime' function. */ #define HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 -/* Define to 1 if you have the `finite' function. */ -#define HAVE_FINITE 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FLOATINGPOINT_H */ - -/* Define if framework AppKit is available. */ -#define HAVE_FRAMEWORK_APPKIT 1 - -/* Define if framework Carbon is available. */ -#define HAVE_FRAMEWORK_CARBON 1 - /* Define if framework CoreFoundation is available. */ #define HAVE_FRAMEWORK_COREFOUNDATION 1 -/* Define if framework IOKit is available. */ -#define HAVE_FRAMEWORK_IOKIT 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_IEEE754_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_IEEEFP_H */ - -/* Define to 1 if you have the `inet_aton' function. */ -#define HAVE_INET_ATON 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - /* Define to 1 if you have the header file. */ #define HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDEVICE_H 1 @@ -104,24 +62,6 @@ /* Define to 1 if you have the `isnan' function. */ #define HAVE_ISNAN 1 -/* Define to 1 if you have the `isnormal' function. */ -/* #undef HAVE_ISNORMAL */ - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `posix4' library (-lposix4). */ -/* #undef HAVE_LIBPOSIX4 */ - -/* Define to 1 if you have the `pthread' library (-lpthread). */ -#define HAVE_LIBPTHREAD 1 - -/* Define to 1 if you have the `PTL' library (-lPTL). */ -/* #undef HAVE_LIBPTL */ - -/* Define to 1 if you have the `rt' library (-lrt). */ -/* #undef HAVE_LIBRT */ - /* Define if there is a linker script to relocate the executable above 0x70000000. */ /* #undef HAVE_LINKER_SCRIPT */ @@ -132,9 +72,6 @@ /* Define if your system supports Mach exceptions. */ #define HAVE_MACH_EXCEPTIONS 1 -/* Define to 1 if you have the header file. */ -#define HAVE_MACH_MACH_H 1 - /* Define to 1 if you have the `mach_task_self' function. */ #define HAVE_MACH_TASK_SELF 1 @@ -142,12 +79,6 @@ */ #define HAVE_MACH_VM 1 -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mmap' function. */ -#define HAVE_MMAP 1 - /* Define if defines MAP_ANON and mmap()'ing with MAP_ANON works. */ /* #undef HAVE_MMAP_ANON */ @@ -159,48 +90,12 @@ /* Define if your system has a working mmap()-based memory allocator. */ /* #undef HAVE_MMAP_VM */ -/* Define to 1 if you have the `mprotect' function. */ -#define HAVE_MPROTECT 1 - -/* Define to 1 if you have the `munmap' function. */ -#define HAVE_MUNMAP 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NAN_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - /* Define if pthreads are available. */ #define HAVE_PTHREADS 1 -/* Define to 1 if you have the `pthread_cancel' function. */ -#define HAVE_PTHREAD_CANCEL 1 - /* Define to 1 if you have the `pthread_cond_init' function. */ #define HAVE_PTHREAD_COND_INIT 1 -/* Define to 1 if you have the `pthread_mutexattr_setprotocol' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL 1 - -/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1 - -/* Define to 1 if you have the `pthread_mutexattr_settype' function. */ -#define HAVE_PTHREAD_MUTEXATTR_SETTYPE 1 - -/* Define to 1 if you have the `pthread_testcancel' function. */ -#define HAVE_PTHREAD_TESTCANCEL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_READLINE_HISTORY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_READLINE_READLINE_H 1 - /* Define to 1 if you have the `sem_init' function. */ #define HAVE_SEM_INIT 1 @@ -213,73 +108,19 @@ /* Define if your system supports extended signals. */ /* #undef HAVE_SIGINFO_T */ -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the `signbit' function. */ -/* #undef HAVE_SIGNBIT */ - /* Define if we can ignore the fault (instruction skipping in SIGSEGV handler). */ #define HAVE_SIGSEGV_SKIP_INSTRUCTION 1 -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STROPTS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_FILIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - /* Define to 1 if you have the header file. */ #define HAVE_SYS_MMAN_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_POLL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STROPTS_H */ - /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - /* Define to 1 if you have the `task_self' function. */ /* #undef HAVE_TASK_SELF */ @@ -289,18 +130,6 @@ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 -/* Define to 1 if you have the `vm_allocate' function. */ -#define HAVE_VM_ALLOCATE 1 - -/* Define to 1 if you have the `vm_deallocate' function. */ -#define HAVE_VM_DEALLOCATE 1 - -/* Define to 1 if you have the `vm_protect' function. */ -#define HAVE_VM_PROTECT 1 - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - /* Define this program name. */ #define PACKAGE "Basilisk II" @@ -322,10 +151,6 @@ /* Define to the version of this package. */ #define PACKAGE_VERSION "1.0" -/* Define if the __PAGEZERO Mach-O Low Memory Globals hack works on this - system. */ -/* #undef PAGEZERO_HACK */ - /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void @@ -341,36 +166,15 @@ /* The size of `float', as computed by sizeof. */ #define SIZEOF_FLOAT 4 -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - /* The size of `long double', as computed by sizeof. */ #define SIZEOF_LONG_DOUBLE 16 -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - /* The size of `void *', as computed by sizeof. */ #define SIZEOF_VOID_P 8 -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define if BSD-style non-blocking I/O is to be used */ -/* #undef USE_FIONBIO */ - /* Define to enble SDL support */ #define USE_SDL 1 @@ -380,28 +184,6 @@ /* Define to enable SDL video graphics support */ #define USE_SDL_VIDEO 1 -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# define _ALL_SOURCE 1 -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS 1 -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# define _TANDEM_SOURCE 1 -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# define __EXTENSIONS__ 1 -#endif - - /* Define this program version. */ #define VERSION "1.0" @@ -422,39 +204,6 @@ # define _DARWIN_USE_64_BIT_INODE 1 #endif -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define to 'int' if doesn't define. */ -/* #undef socklen_t */ #else #include "config.h" #endif @@ -589,46 +338,6 @@ typedef uae_u32 uaecptr; extern uint64 GetTicks_usec(void); extern void Delay_usec(uint32 usec); -typedef volatile int spinlock_t; - -static const spinlock_t SPIN_LOCK_UNLOCKED = 0; - -#if HAVE_TEST_AND_SET -#define HAVE_SPINLOCKS 1 -static inline void spin_lock(spinlock_t *lock) -{ - while (testandset(lock)); -} - -static inline void spin_unlock(spinlock_t *lock) -{ - *lock = 0; -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return !testandset(lock); -} -#else -static inline void spin_lock(spinlock_t *lock) -{ -} - -static inline void spin_unlock(spinlock_t *lock) -{ -} - -static inline int spin_trylock(spinlock_t *lock) -{ - return 1; -} -#endif - -#ifdef HAVE_PTHREADS -/* Centralized pthread attribute setup */ -void Set_pthread_attr(pthread_attr_t *attr, int priority); -#endif - /* UAE CPU defines */ #if defined(__i386__) || defined(__x86_64__) @@ -711,14 +420,6 @@ static inline uae_u32 do_byteswap_16(uae_u32 v) #endif #define REGPARAM2 - -#if __GNUC__ < 3 -# define __builtin_expect(foo,bar) (foo) -#endif -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#define ALWAYS_INLINE inline __attribute__((always_inline)) - #define memptr uint32 From 730ca109b7baeb4fd304720c33695b2c4e65c9f4 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 1 Sep 2019 14:51:28 -0500 Subject: [PATCH 11/20] Remove SDL1 support; add SDL2 support from kanjitalk755 repository --- BasiliskII/src/SDL/audio_sdl.cpp | 20 +- .../src/SDL/{video_sdl.cpp => video_sdl2.cpp} | 1413 ++++++++++++++--- BasiliskII/src/Unix/CMakeLists.txt | 8 +- BasiliskII/src/Unix/main_unix.cpp | 4 +- BasiliskII/src/Unix/timer_unix.cpp | 17 +- 5 files changed, 1255 insertions(+), 207 deletions(-) rename BasiliskII/src/SDL/{video_sdl.cpp => video_sdl2.cpp} (51%) diff --git a/BasiliskII/src/SDL/audio_sdl.cpp b/BasiliskII/src/SDL/audio_sdl.cpp index 85ad4c8b..05edebb1 100644 --- a/BasiliskII/src/SDL/audio_sdl.cpp +++ b/BasiliskII/src/SDL/audio_sdl.cpp @@ -28,11 +28,13 @@ #include #include +#include #define DEBUG 0 #include "debug.h" + #define MAC_MAX_VOLUME 0x0100 // The currently selected audio parameters (indices in audio_sample_rates[] etc. vectors) @@ -83,6 +85,7 @@ static bool open_sdl_audio(void) } SDL_AudioSpec audio_spec; + memset(&audio_spec, 0, sizeof(audio_spec)); audio_spec.freq = audio_sample_rates[audio_sample_rate_index] >> 16; audio_spec.format = (audio_sample_sizes[audio_sample_size_index] == 8) ? AUDIO_U8 : AUDIO_S16MSB; audio_spec.channels = audio_channel_counts[audio_channel_count_index]; @@ -95,9 +98,23 @@ static bool open_sdl_audio(void) fprintf(stderr, "WARNING: Cannot open audio: %s\n", SDL_GetError()); return false; } + +#if SDL_VERSION_ATLEAST(2,0,0) + // HACK: workaround a bug in SDL pre-2.0.6 (reported via https://bugzilla.libsdl.org/show_bug.cgi?id=3710 ) + // whereby SDL does not update audio_spec.size + if (audio_spec.size == 0) { + audio_spec.size = (SDL_AUDIO_BITSIZE(audio_spec.format) / 8) * audio_spec.channels * audio_spec.samples; + } +#endif + +#if SDL_VERSION_ATLEAST(2,0,0) + const char * driver_name = SDL_GetCurrentAudioDriver(); +#else char driver_name[32]; - printf("Using SDL/%s audio output\n", SDL_AudioDriverName(driver_name, sizeof(driver_name) - 1)); + SDL_AudioDriverName(driver_name, sizeof(driver_name) - 1); +#endif + printf("Using SDL/%s audio output\n", driver_name ? driver_name : ""); silence_byte = audio_spec.silence; SDL_PauseAudio(0); @@ -227,7 +244,6 @@ static void stream_func(void *arg, uint8 *stream, int stream_len) // Audio not active, play silence silence: memset(stream, silence_byte, stream_len); } - } diff --git a/BasiliskII/src/SDL/video_sdl.cpp b/BasiliskII/src/SDL/video_sdl2.cpp similarity index 51% rename from BasiliskII/src/SDL/video_sdl.cpp rename to BasiliskII/src/SDL/video_sdl2.cpp index 9158d729..2618a163 100644 --- a/BasiliskII/src/SDL/video_sdl.cpp +++ b/BasiliskII/src/SDL/video_sdl2.cpp @@ -1,5 +1,5 @@ /* - * video_sdl.cpp - Video/graphics emulation, SDL specific stuff + * video_sdl2.cpp - Video/graphics emulation, SDL 2.x specific stuff * * Basilisk II (C) 1997-2008 Christian Bauer * @@ -31,7 +31,6 @@ * - Ctr-Tab for suspend/resume but how? SDL does not support that for non-Linux * - Ctrl-Fn doesn't generate SDL_KEYDOWN events (SDL bug?) * - Mouse acceleration, there is no API in SDL yet for that - * - Force relative mode in Grab mode even if SDL provides absolute coordinates? * - Gamma tables support is likely to be broken here * - Events processing is bound to the general emulation thread as SDL requires * to PumpEvents() within the same thread as the one that called SetVideoMode(). @@ -43,12 +42,19 @@ #include "sysdeps.h" #include +#if SDL_VERSION_ATLEAST(2,0,0) + #include #include #include #include +#include -#include "cpu_emulation.h" +#ifdef WIN32 +#include /* alloca() */ +#endif + +#include #include "main.h" #include "adb.h" #include "macos_util.h" @@ -67,14 +73,28 @@ using std::vector; static vector VideoModes; // Display types +#ifdef SHEEPSHAVER +enum { + DISPLAY_WINDOW = DIS_WINDOW, // windowed display + DISPLAY_SCREEN = DIS_SCREEN // fullscreen display +}; +extern int display_type; // See enum above +#else enum { DISPLAY_WINDOW, // windowed display DISPLAY_SCREEN // fullscreen display }; static int display_type = DISPLAY_WINDOW; // See enum above +#endif // Constants +#ifdef WIN32 +const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes"; +#elif __MACOSX__ +const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes"; +#else const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; +#endif // Global variables @@ -94,10 +114,15 @@ static volatile bool thread_stop_req = false; static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req #endif +#ifdef ENABLE_VOSF +static bool use_vosf = false; // Flag: VOSF enabled +#else static const bool use_vosf = false; // VOSF not possible +#endif static bool ctrl_down = false; // Flag: Ctrl key pressed -static bool caps_on = false; // Flag: Caps Lock on +static bool opt_down = false; // Flag: Opt key pressed +static bool cmd_down = false; // Flag: Cmd key pressed static bool quit_full_screen = false; // Flag: DGA close requested from redraw thread static bool emerg_quit = false; // Flag: Ctrl-Esc pressed, emergency quit requested from MacOS thread static bool emul_suspended = false; // Flag: Emulator suspended @@ -108,12 +133,20 @@ static bool use_keycodes = false; // Flag: Use keycodes rather than keysyms static int keycode_table[256]; // X keycode -> Mac keycode translation table // SDL variables +SDL_Window * sdl_window = NULL; // Wraps an OS-native window +static SDL_Surface * host_surface = NULL; // Surface in host-OS display format +static SDL_Surface * guest_surface = NULL; // Surface in guest-OS display format +static SDL_Renderer * sdl_renderer = NULL; // Handle to SDL2 renderer +static SDL_threadID sdl_renderer_thread_id = 0; // Thread ID where the SDL_renderer was created, and SDL_renderer ops should run (for compatibility w/ d3d9) +static SDL_Texture * sdl_texture = NULL; // Handle to a GPU texture, with which to draw guest_surface to +static SDL_Rect sdl_update_video_rect = {0,0,0,0}; // Union of all rects to update, when updating sdl_texture +static SDL_mutex * sdl_update_video_mutex = NULL; // Mutex to protect sdl_update_video_rect static int screen_depth; // Depth of current screen -static SDL_Cursor *sdl_cursor; // Copy of Mac cursor -static SDL_Color sdl_palette[256]; // Color palette to be used as CLUT and gamma table +static SDL_Cursor *sdl_cursor = NULL; // Copy of Mac cursor +static SDL_Palette *sdl_palette = NULL; // Color palette to be used as CLUT and gamma table static bool sdl_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors static bool toggle_fullscreen = false; -static const int sdl_eventmask = SDL_MOUSEEVENTMASK | SDL_KEYEVENTMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK | SDL_ACTIVEEVENTMASK; +static bool did_add_event_watch = false; static bool mouse_grabbed = false; @@ -139,6 +172,9 @@ static void (*video_refresh)(void); // Prototypes static int redraw_func(void *arg); +static int present_sdl_video(); +static int SDLCALL on_sdl_event_generated(void *userdata, SDL_Event * event); +static bool is_fullscreen(SDL_Window *); // From sys_unix.cpp extern void SysMountFirstFloppy(void); @@ -148,7 +184,14 @@ extern void SysMountFirstFloppy(void); * SDL surface locking glue */ +#ifdef ENABLE_VOSF +#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) do { \ + if (sdl_window && SDL_GetWindowFlags(sdl_window) & (SDL_WINDOW_FULLSCREEN)) \ + the_host_buffer = (uint8 *)(SURFACE)->pixels; \ +} while (0) +#else #define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) +#endif #define SDL_VIDEO_LOCK_SURFACE(SURFACE) do { \ if (SDL_MUSTLOCK(SURFACE)) { \ @@ -189,6 +232,135 @@ static inline void vm_release_framebuffer(void *fb, uint32 size) vm_release(fb, size); } +static inline int get_customized_color_depth(int default_depth) +{ + int display_color_depth = PrefsFindInt32("displaycolordepth"); + + D(bug("Get displaycolordepth %d\n", display_color_depth)); + + if(0 == display_color_depth) + return default_depth; + else{ + switch (display_color_depth) { + case 8: + return VIDEO_DEPTH_8BIT; + case 15: case 16: + return VIDEO_DEPTH_16BIT; + case 24: case 32: + return VIDEO_DEPTH_32BIT; + default: + return default_depth; + } + } +} + +/* + * Windows message handler + */ + +#ifdef WIN32 +#include +static WNDPROC sdl_window_proc = NULL; // Window proc used by SDL + +extern void SysMediaArrived(void); +extern void SysMediaRemoved(void); +extern HWND GetMainWindowHandle(void); + +static LRESULT CALLBACK windows_message_handler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_DEVICECHANGE: + if (wParam == DBT_DEVICEREMOVECOMPLETE) { + DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; + if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) + SysMediaRemoved(); + } + else if (wParam == DBT_DEVICEARRIVAL) { + DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; + if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) + SysMediaArrived(); + } + return 0; + + default: + if (sdl_window_proc) + return CallWindowProc(sdl_window_proc, hwnd, msg, wParam, lParam); + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} +#endif + + +/* + * SheepShaver glue + */ + +#ifdef SHEEPSHAVER +// Color depth modes type +typedef int video_depth; + +// 1, 2, 4 and 8 bit depths use a color palette +static inline bool IsDirectMode(VIDEO_MODE const & mode) +{ + return IsDirectMode(mode.viAppleMode); +} + +// Abstract base class representing one (possibly virtual) monitor +// ("monitor" = rectangular display with a contiguous frame buffer) +class monitor_desc { +public: + monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id) {} + virtual ~monitor_desc() {} + + // Get current Mac frame buffer base address + uint32 get_mac_frame_base(void) const {return screen_base;} + + // Set Mac frame buffer base address (called from switch_to_mode()) + void set_mac_frame_base(uint32 base) {screen_base = base;} + + // Get current video mode + const VIDEO_MODE &get_current_mode(void) const {return VModes[cur_mode];} + + // Called by the video driver to switch the video mode on this display + // (must call set_mac_frame_base()) + virtual void switch_to_current_mode(void) = 0; + + // Called by the video driver to set the color palette (in indexed modes) + // or the gamma table (in direct modes) + virtual void set_palette(uint8 *pal, int num) = 0; +}; + +// Vector of pointers to available monitor descriptions, filled by VideoInit() +static vector VideoMonitors; + +// Find Apple mode matching best specified dimensions +static int find_apple_resolution(int xsize, int ysize) +{ + if (xsize == 640 && ysize == 480) + return APPLE_640x480; + if (xsize == 800 && ysize == 600) + return APPLE_800x600; + if (xsize == 1024 && ysize == 768) + return APPLE_1024x768; + if (xsize == 1152 && ysize == 768) + return APPLE_1152x768; + if (xsize == 1152 && ysize == 900) + return APPLE_1152x900; + if (xsize == 1280 && ysize == 1024) + return APPLE_1280x1024; + if (xsize == 1600 && ysize == 1200) + return APPLE_1600x1200; + return APPLE_CUSTOM; +} + +// Display error alert +static void ErrorAlert(int error) +{ + ErrorAlert(GetString(error)); +} +#endif + /* * monitor_desc subclass for SDL display @@ -225,26 +397,6 @@ static int palette_size(int mode) } } -// Return bytes per pixel for requested depth -static inline int bytes_per_pixel(int depth) -{ - int bpp; - switch (depth) { - case 8: - bpp = 1; - break; - case 15: case 16: - bpp = 2; - break; - case 24: case 32: - bpp = 4; - break; - default: - abort(); - } - return bpp; -} - // Map video_mode depth ID to numerical depth value static int mac_depth_of_video_depth(int video_depth) { @@ -283,25 +435,15 @@ static int sdl_depth_of_video_depth(int video_depth) // Get screen dimensions static void sdl_display_dimensions(int &width, int &height) { - static int max_width, max_height; - if (max_width == 0 && max_height == 0) { - max_width = 640 ; max_height = 480; - SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); - if (modes && modes != (SDL_Rect **)-1) { - // It turns out that on some implementations, and contrary to the documentation, - // the returned list is not sorted from largest to smallest (e.g. Windows) - for (int i = 0; modes[i] != NULL; i++) { - const int w = modes[i]->w; - const int h = modes[i]->h; - if (w > max_width && h > max_height) { - max_width = w; - max_height = h; - } - } - } + SDL_DisplayMode desktop_mode; + const int display_index = 0; // TODO: try supporting multiple displays + if (SDL_GetDesktopDisplayMode(display_index, &desktop_mode) != 0) { + // TODO: report a warning, here? + width = height = 0; + return; } - width = max_width; - height = max_height; + width = desktop_mode.w; + height = desktop_mode.h; } static inline int sdl_display_width(void) @@ -318,18 +460,15 @@ static inline int sdl_display_height(void) return height; } -// Check wether specified mode is available +// Check whether specified mode is available static bool has_mode(int type, int width, int height, int depth) { - // Filter out out-of-bounds resolutions if (width > sdl_display_width() || height > sdl_display_height()) return false; - // Rely on SDL capabilities - return SDL_VideoModeOK(width, height, - sdl_depth_of_video_depth(depth), - SDL_HWSURFACE | (type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0)) != 0; + // Whatever size it is, beyond what we've checked, we'll scale to/from as appropriate. + return true; } // Add mode to list of supported modes @@ -341,6 +480,10 @@ static void add_mode(int type, int width, int height, int resolution_id, int byt // Fill in VideoMode entry VIDEO_MODE mode; +#ifdef SHEEPSHAVER + resolution_id = find_apple_resolution(width, height); + mode.viType = type; +#endif VIDEO_MODE_X = width; VIDEO_MODE_Y = height; VIDEO_MODE_RESOLUTION = resolution_id; @@ -352,33 +495,107 @@ static void add_mode(int type, int width, int height, int resolution_id, int byt // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac) static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool native_byte_order) { +#if !REAL_ADDRESSING && !DIRECT_ADDRESSING + int layout = FLAYOUT_DIRECT; + if (depth == VIDEO_DEPTH_16BIT) + layout = (screen_depth == 15) ? FLAYOUT_HOST_555 : FLAYOUT_HOST_565; + else if (depth == VIDEO_DEPTH_32BIT) + layout = (screen_depth == 24) ? FLAYOUT_HOST_888 : FLAYOUT_DIRECT; + if (native_byte_order) + MacFrameLayout = layout; + else + MacFrameLayout = FLAYOUT_DIRECT; + monitor.set_mac_frame_base(MacFrameBaseMac); + // Set variables used by UAE memory banking + const VIDEO_MODE &mode = monitor.get_current_mode(); + MacFrameBaseHost = the_buffer; + MacFrameSize = VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y; + InitFrameBufferMapping(); +#else monitor.set_mac_frame_base(Host2MacAddr(the_buffer)); - +#endif D(bug("monitor.mac_frame_base = %08x\n", monitor.get_mac_frame_base())); } // Set window name and class static void set_window_name(int name) { - const SDL_VideoInfo *vi = SDL_GetVideoInfo(); - if (vi && vi->wm_available) { - const char *str = GetString(name); - SDL_WM_SetCaption(str, str); + if (!sdl_window) { + return; } + const char *str = GetString(name); + SDL_SetWindowTitle(sdl_window, str); +} + +static void set_window_name_grabbed() { + if (!sdl_window) return; + int hotkey = PrefsFindInt32("hotkey"); + if (!hotkey) hotkey = 1; + // std::string s = GetString(STR_WINDOW_TITLE_GRABBED0); + // if (hotkey & 1) s += GetString(STR_WINDOW_TITLE_GRABBED1); + // if (hotkey & 2) s += GetString(STR_WINDOW_TITLE_GRABBED2); + // if (hotkey & 4) s += GetString(STR_WINDOW_TITLE_GRABBED3); + // s += GetString(STR_WINDOW_TITLE_GRABBED4); + // SDL_SetWindowTitle(sdl_window, s.c_str()); } // Set mouse grab mode -static SDL_GrabMode set_grab_mode(SDL_GrabMode mode) +static void set_grab_mode(bool grab) { - const SDL_VideoInfo *vi = SDL_GetVideoInfo(); - return (vi && vi->wm_available ? SDL_WM_GrabInput(mode) : SDL_GRAB_OFF); + if (!sdl_window) { + return; + } + SDL_SetWindowGrab(sdl_window, grab ? SDL_TRUE : SDL_FALSE); } // Migrate preferences items (XXX to be handled in MigratePrefs()) static void migrate_screen_prefs(void) { +#ifdef SHEEPSHAVER + // Look-up priorities are: "screen", "screenmodes", "windowmodes". + if (PrefsFindString("screen")) + return; + uint32 window_modes = PrefsFindInt32("windowmodes"); + uint32 screen_modes = PrefsFindInt32("screenmodes"); + int width = 0, height = 0; + if (screen_modes) { + static const struct { + int id; + int width; + int height; + } + modes[] = { + { 1, 640, 480 }, + { 2, 800, 600 }, + { 4, 1024, 768 }, + { 64, 1152, 768 }, + { 8, 1152, 900 }, + { 16, 1280, 1024 }, + { 32, 1600, 1200 }, + { 0, } + }; + for (int i = 0; modes[i].id != 0; i++) { + if (screen_modes & modes[i].id) { + if (width < modes[i].width && height < modes[i].height) { + width = modes[i].width; + height = modes[i].height; + } + } + } + } else { + if (window_modes & 1) + width = 640, height = 480; + if (window_modes & 2) + width = 800, height = 600; + } + if (width && height) { + char str[32]; + sprintf(str, "%s/%d/%d", screen_modes ? "dga" : "win", width, height); + PrefsReplaceString("screen", str); + } +#endif } @@ -415,10 +632,17 @@ public: SDL_Surface *s; // The surface we draw into }; +#ifdef ENABLE_VOSF +static void update_display_window_vosf(driver_base *drv); +#endif static void update_display_static(driver_base *drv); static driver_base *drv = NULL; // Pointer to currently used driver object +#ifdef ENABLE_VOSF +# include "video_vosf.h" +#endif + driver_base::driver_base(SDL_monitor_desc &m) : monitor(m), mode(m.get_current_mode()), init_ok(false), s(NULL) { @@ -426,19 +650,365 @@ driver_base::driver_base(SDL_monitor_desc &m) the_buffer_copy = NULL; } +static void delete_sdl_video_surfaces() +{ + if (sdl_texture) { + SDL_DestroyTexture(sdl_texture); + sdl_texture = NULL; + } + + if (host_surface) { + if (host_surface == guest_surface) { + guest_surface = NULL; + } + + SDL_FreeSurface(host_surface); + host_surface = NULL; + } + + if (guest_surface) { + SDL_FreeSurface(guest_surface); + guest_surface = NULL; + } +} + +static void delete_sdl_video_window() +{ + if (sdl_renderer) { + SDL_DestroyRenderer(sdl_renderer); + sdl_renderer = NULL; + } + + if (sdl_window) { + SDL_DestroyWindow(sdl_window); + sdl_window = NULL; + } +} + +static void shutdown_sdl_video() +{ + delete_sdl_video_surfaces(); + delete_sdl_video_window(); +} + +static SDL_Surface * init_sdl_video(int width, int height, int bpp, Uint32 flags) +{ + if (guest_surface) { + delete_sdl_video_surfaces(); + } + + int window_width = width; + int window_height = height; + Uint32 window_flags = SDL_WINDOW_ALLOW_HIGHDPI; + const int window_flags_to_monitor = SDL_WINDOW_FULLSCREEN; + + if (flags & SDL_WINDOW_FULLSCREEN) { + SDL_DisplayMode desktop_mode; + if (SDL_GetDesktopDisplayMode(0, &desktop_mode) != 0) { + shutdown_sdl_video(); + return NULL; + } +#ifdef __MACOSX__ + window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; +#else + window_flags |= SDL_WINDOW_FULLSCREEN; +#endif + window_width = desktop_mode.w; + window_height = desktop_mode.h; + } + + if (sdl_window) { + int old_window_width, old_window_height, old_window_flags; + SDL_GetWindowSize(sdl_window, &old_window_width, &old_window_height); + old_window_flags = SDL_GetWindowFlags(sdl_window); + if (old_window_width != window_width || + old_window_height != window_height || + (old_window_flags & window_flags_to_monitor) != (window_flags & window_flags_to_monitor)) + { + delete_sdl_video_window(); + } + } + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, PrefsFindBool("scale_nearest") ? "nearest" : "linear"); + +/* + // Always use a resize-able window. This helps allow SDL to manage + // transitions involving fullscreen to or from windowed-mode. + window_flags |= SDL_WINDOW_RESIZABLE; +*/ + if (!sdl_window) { + sdl_window = SDL_CreateWindow( + "Basilisk II", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + window_width, + window_height, + window_flags); + if (!sdl_window) { + shutdown_sdl_video(); + return NULL; + } + } + if (flags & SDL_WINDOW_FULLSCREEN) SDL_SetWindowGrab(sdl_window, SDL_TRUE); + + // Some SDL events (regarding some native-window events), need processing + // as they are generated. SDL2 has a facility, SDL_AddEventWatch(), which + // allows events to be processed as they are generated. + if (!did_add_event_watch) { + SDL_AddEventWatch(&on_sdl_event_generated, NULL); + did_add_event_watch = true; + } + + if (!sdl_renderer) { +#ifdef WIN32 + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); +#else + SDL_SetHint(SDL_HINT_RENDER_DRIVER, ""); +#endif + sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0); + if (!sdl_renderer) { + shutdown_sdl_video(); + return NULL; + } + sdl_renderer_thread_id = SDL_ThreadID(); + + SDL_RendererInfo info; + memset(&info, 0, sizeof(info)); + SDL_GetRendererInfo(sdl_renderer, &info); + printf("Using SDL_Renderer driver: %s\n", (info.name ? info.name : "(null)")); + } + + if (!sdl_update_video_mutex) { + sdl_update_video_mutex = SDL_CreateMutex(); + } + + SDL_assert(sdl_texture == NULL); + sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height); + if (!sdl_texture) { + shutdown_sdl_video(); + return NULL; + } + sdl_update_video_rect.x = 0; + sdl_update_video_rect.y = 0; + sdl_update_video_rect.w = 0; + sdl_update_video_rect.h = 0; + + SDL_assert(guest_surface == NULL); + SDL_assert(host_surface == NULL); + switch (bpp) { + case 8: + guest_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0); + break; + case 16: + guest_surface = SDL_CreateRGBSurface(0, width, height, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000); + break; + case 32: + guest_surface = SDL_CreateRGBSurface(0, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); + host_surface = guest_surface; + break; + default: + printf("WARNING: An unsupported bpp of %d was used\n", bpp); + break; + } + if (!guest_surface) { + shutdown_sdl_video(); + return NULL; + } + + if (!host_surface) { + Uint32 texture_format; + if (SDL_QueryTexture(sdl_texture, &texture_format, NULL, NULL, NULL) != 0) { + printf("ERROR: Unable to get the SDL texture's pixel format: %s\n", SDL_GetError()); + shutdown_sdl_video(); + return NULL; + } + + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + if (!SDL_PixelFormatEnumToMasks(texture_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + printf("ERROR: Unable to determine format for host SDL_surface: %s\n", SDL_GetError()); + shutdown_sdl_video(); + return NULL; + } + + host_surface = SDL_CreateRGBSurface(0, width, height, bpp, Rmask, Gmask, Bmask, Amask); + if (!host_surface) { + printf("ERROR: Unable to create host SDL_surface: %s\n", SDL_GetError()); + shutdown_sdl_video(); + return NULL; + } + } + + if (SDL_RenderSetLogicalSize(sdl_renderer, width, height) != 0) { + printf("ERROR: Unable to set SDL rendeer's logical size (to %dx%d): %s\n", + width, height, SDL_GetError()); + shutdown_sdl_video(); + return NULL; + } + + SDL_RenderSetIntegerScale(sdl_renderer, PrefsFindBool("scale_integer") ? SDL_TRUE : SDL_FALSE); + + return guest_surface; +} + +static int present_sdl_video() +{ + if (SDL_RectEmpty(&sdl_update_video_rect)) return 0; + + if (!sdl_renderer || !sdl_texture || !guest_surface) { + printf("WARNING: A video mode does not appear to have been set.\n"); + return -1; + } + + // Some systems, such as D3D9, can fail if and when they are used across + // certain operations. To address this, only utilize SDL_Renderer in a + // single thread, preferably the main thread. + // + // This was added as part of a fix for https://github.com/DavidLudwig/macemu/issues/21 + // "BasiliskII, Win32: resizing a window does not stretch " + SDL_assert(SDL_ThreadID() == sdl_renderer_thread_id); + + // Make sure the display's internal (to SDL, possibly the OS) buffer gets + // cleared. Not doing so can, if and when letterboxing is applied (whereby + // colored bars are drawn on the screen's sides to help with aspect-ratio + // correction), the colored bars can be an unknown color. + SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 0); // Use black + SDL_RenderClear(sdl_renderer); // Clear the display + + // We're about to work with sdl_update_video_rect, so stop other threads from + // modifying it! + LOCK_PALETTE; + SDL_LockMutex(sdl_update_video_mutex); + // Convert from the guest OS' pixel format, to the host OS' texture, if necessary. + if (host_surface != guest_surface && + host_surface != NULL && + guest_surface != NULL) + { + SDL_Rect destRect = sdl_update_video_rect; + int result = SDL_BlitSurface(guest_surface, &sdl_update_video_rect, host_surface, &destRect); + if (result != 0) { + SDL_UnlockMutex(sdl_update_video_mutex); + UNLOCK_PALETTE; + return -1; + } + } + UNLOCK_PALETTE; // passed potential deadlock, can unlock palette + + // Update the host OS' texture + void * srcPixels = (void *)((uint8_t *)host_surface->pixels + + sdl_update_video_rect.y * host_surface->pitch + + sdl_update_video_rect.x * host_surface->format->BytesPerPixel); + + if (SDL_UpdateTexture(sdl_texture, &sdl_update_video_rect, srcPixels, host_surface->pitch) != 0) { + SDL_UnlockMutex(sdl_update_video_mutex); + return -1; + } + + // We are done working with pixels in host_surface. Reset sdl_update_video_rect, then let + // other threads modify it, as-needed. + sdl_update_video_rect.x = 0; + sdl_update_video_rect.y = 0; + sdl_update_video_rect.w = 0; + sdl_update_video_rect.h = 0; + SDL_UnlockMutex(sdl_update_video_mutex); + + // Copy the texture to the display + if (SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL) != 0) { + return -1; + } + + // Update the display + SDL_RenderPresent(sdl_renderer); + + // Indicate success to the caller! + return 0; +} + +void update_sdl_video(SDL_Surface *s, int numrects, SDL_Rect *rects) +{ + // TODO: make sure SDL_Renderer resources get displayed, if and when + // MacsBug is running (and VideoInterrupt() might not get called) + + SDL_LockMutex(sdl_update_video_mutex); + for (int i = 0; i < numrects; ++i) { + SDL_UnionRect(&sdl_update_video_rect, &rects[i], &sdl_update_video_rect); + } + SDL_UnlockMutex(sdl_update_video_mutex); +} + +void update_sdl_video(SDL_Surface *s, Sint32 x, Sint32 y, Sint32 w, Sint32 h) +{ + SDL_Rect temp = {x, y, w, h}; + update_sdl_video(s, 1, &temp); +} + +#ifdef SHEEPSHAVER +static void MagBits(Uint8 *dst, Uint8 *src, int mag) { + for (int y = 0; y < 16; y++) + for (int x = 0; x < 16; x++) { + int sa = 16 * y + x; + if (!(src[sa >> 3] & 0x80 >> (sa & 7))) continue; + for (int dy = 0; dy < mag; dy++) + for (int dx = 0; dx < mag; dx++) { + int da = 16 * mag * (mag * y + dy) + mag * x + dx; + dst[da >> 3] |= 0x80 >> (da & 7); + } + } +} +static SDL_Cursor *MagCursor(bool hot) { + int w, h; + SDL_GetWindowSize(sdl_window, &w, &h); + int mag = std::min(w / drv->VIDEO_MODE_X, h / drv->VIDEO_MODE_Y); + Uint8 *data = (Uint8 *)SDL_calloc(1, 32 * mag * mag); + Uint8 *mask = (Uint8 *)SDL_calloc(1, 32 * mag * mag); + MagBits(data, &MacCursor[4], mag); + MagBits(mask, &MacCursor[36], mag); + SDL_Cursor *cursor = SDL_CreateCursor(data, mask, 16 * mag, 16 * mag, hot ? MacCursor[2] * mag : 0, hot ? MacCursor[3] * mag : 0); + SDL_free(data); + SDL_free(mask); + return cursor; +} +#endif + void driver_base::set_video_mode(int flags) { int depth = sdl_depth_of_video_depth(VIDEO_MODE_DEPTH); - if ((s = SDL_SetVideoMode(VIDEO_MODE_X, VIDEO_MODE_Y, depth, - SDL_HWSURFACE | flags)) == NULL) + if ((s = init_sdl_video(VIDEO_MODE_X, VIDEO_MODE_Y, depth, flags)) == NULL) return; +#ifdef ENABLE_VOSF + the_host_buffer = (uint8 *)s->pixels; +#endif } void driver_base::init() { - set_video_mode(display_type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0); + set_video_mode(display_type == DISPLAY_SCREEN ? SDL_WINDOW_FULLSCREEN : 0); int aligned_height = (VIDEO_MODE_Y + 15) & ~15; +#ifdef ENABLE_VOSF + use_vosf = true; + // Allocate memory for frame buffer (SIZE is extended to page-boundary) + the_buffer_size = page_extend((aligned_height + 2) * s->pitch); + the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); + the_buffer_copy = (uint8 *)malloc(the_buffer_size); + D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); + + // Check whether we can initialize the VOSF subsystem and it's profitable + if (!video_vosf_init(monitor)) { + WarningAlert(GetString(STR_VOSF_INIT_ERR)); + use_vosf = false; + } + else if (!video_vosf_profitable()) { + video_vosf_exit(); + printf("VOSF acceleration is not profitable on this platform, disabling it\n"); + use_vosf = false; + } + if (!use_vosf) { + free(the_buffer_copy); + vm_release(the_buffer, the_buffer_size); + the_host_buffer = NULL; + } +#endif if (!use_vosf) { // Allocate memory for frame buffer the_buffer_size = (aligned_height + 2) * s->pitch; @@ -454,7 +1024,7 @@ void driver_base::init() } void driver_base::adapt_to_video_mode() { - ADBSetRelMouseMode(false); + ADBSetRelMouseMode(mouse_grabbed); // Init blitting routines SDL_PixelFormat *f = s->format; @@ -472,11 +1042,30 @@ void driver_base::adapt_to_video_mode() { bool hardware_cursor = false; +#ifdef SHEEPSHAVER + hardware_cursor = video_can_change_cursor(); + if (hardware_cursor) { + // Create cursor + if ((sdl_cursor = MagCursor(false)) != NULL) { + SDL_SetCursor(sdl_cursor); + } + } + // Tell the video driver there's a change in cursor type + if (private_data) + private_data->cursorHardware = hardware_cursor; +#endif + SDL_LockMutex(sdl_update_video_mutex); + sdl_update_video_rect.x = 0; + sdl_update_video_rect.y = 0; + sdl_update_video_rect.w = VIDEO_MODE_X; + sdl_update_video_rect.h = VIDEO_MODE_Y; + SDL_UnlockMutex(sdl_update_video_mutex); + // Hide cursor SDL_ShowCursor(hardware_cursor); // Set window name/class - set_window_name(STR_WINDOW_TITLE); + mouse_grabbed ? set_window_name_grabbed() : set_window_name((int)STR_WINDOW_TITLE); // Everything went well init_ok = true; @@ -487,8 +1076,14 @@ driver_base::~driver_base() ungrab_mouse(); restore_mouse_accel(); - if (s) - SDL_FreeSurface(s); + // HACK: Just delete instances of SDL_Surface and SDL_Texture, rather + // than also the SDL_Window and SDL_Renderer. This fixes a bug whereby + // OSX hosts, when in fullscreen, will, on a guest OS resolution change, + // do a series of switches (using OSX's "Spaces" feature) to and from + // the Basilisk II desktop, + delete_sdl_video_surfaces(); // This deletes instances of SDL_Surface and SDL_Texture + //shutdown_sdl_video(); // This deletes SDL_Window, SDL_Renderer, in addition to + // instances of SDL_Surface and SDL_Texture. // the_buffer shall always be mapped through vm_acquire_framebuffer() if (the_buffer != VM_MAP_FAILED) { @@ -504,6 +1099,18 @@ driver_base::~driver_base() the_buffer_copy = NULL; } } +#ifdef ENABLE_VOSF + else { + if (the_buffer_copy) { + D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy)); + free(the_buffer_copy); + the_buffer_copy = NULL; + } + + // Deinitialize VOSF + video_vosf_exit(); + } +#endif SDL_ShowCursor(1); } @@ -513,8 +1120,15 @@ void driver_base::update_palette(void) { const VIDEO_MODE &mode = monitor.get_current_mode(); - if ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) - SDL_SetPalette(s, SDL_PHYSPAL, sdl_palette, 0, 256); + if ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) { + SDL_SetSurfacePalette(s, sdl_palette); + SDL_LockMutex(sdl_update_video_mutex); + sdl_update_video_rect.x = 0; + sdl_update_video_rect.y = 0; + sdl_update_video_rect.w = VIDEO_MODE_X; + sdl_update_video_rect.h = VIDEO_MODE_Y; + SDL_UnlockMutex(sdl_update_video_mutex); + } } // Disable mouse acceleration @@ -536,16 +1150,24 @@ void driver_base::toggle_mouse_grab(void) grab_mouse(); } +static void update_mouse_grab() +{ + if (mouse_grabbed) { + SDL_SetRelativeMouseMode(SDL_TRUE); + } else { + SDL_SetRelativeMouseMode(SDL_FALSE); + } +} + // Grab mouse, switch to relative mouse mode void driver_base::grab_mouse(void) { if (!mouse_grabbed) { - SDL_GrabMode new_mode = set_grab_mode(SDL_GRAB_ON); - if (new_mode == SDL_GRAB_ON) { - set_window_name(STR_WINDOW_TITLE_GRABBED); - disable_mouse_accel(); - mouse_grabbed = true; - } + mouse_grabbed = true; + update_mouse_grab(); + set_window_name_grabbed(); + disable_mouse_accel(); + ADBSetRelMouseMode(true); } } @@ -553,12 +1175,11 @@ void driver_base::grab_mouse(void) void driver_base::ungrab_mouse(void) { if (mouse_grabbed) { - SDL_GrabMode new_mode = set_grab_mode(SDL_GRAB_OFF); - if (new_mode == SDL_GRAB_OFF) { - set_window_name(STR_WINDOW_TITLE); - restore_mouse_accel(); - mouse_grabbed = false; - } + mouse_grabbed = false; + update_mouse_grab(); + set_window_name(STR_WINDOW_TITLE); + restore_mouse_accel(); + ADBSetRelMouseMode(false); } } @@ -589,8 +1210,7 @@ static void keycode_init(void) keycode_table[i] = -1; // Search for server vendor string, then read keycodes - char video_driver[256]; - SDL_VideoDriverName(video_driver, sizeof(video_driver)); + const char * video_driver = SDL_GetCurrentVideoDriver(); bool video_driver_found = false; char line[256]; int n_keys = 0; @@ -623,7 +1243,7 @@ static void keycode_init(void) static const char sdl_str[] = "sdl"; if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0) { char *p = line + sizeof(sdl_str); - if (strstr(video_driver, p) == video_driver) + if (video_driver && strstr(video_driver, p) == video_driver) video_driver_found = true; } } @@ -636,12 +1256,12 @@ static void keycode_init(void) // Vendor not found? Then display warning if (!video_driver_found) { char str[256]; - snprintf(str, sizeof(str), GetString(STR_KEYCODE_VENDOR_WARN), video_driver, kc_path ? kc_path : KEYCODE_FILE_NAME); + snprintf(str, sizeof(str), GetString(STR_KEYCODE_VENDOR_WARN), video_driver ? video_driver : "", kc_path ? kc_path : KEYCODE_FILE_NAME); WarningAlert(str); return; } - D(bug("Using SDL/%s keycodes table, %d key mappings\n", video_driver, n_keys)); + D(bug("Using SDL/%s keycodes table, %d key mappings\n", video_driver ? video_driver : "", n_keys)); } } @@ -666,6 +1286,13 @@ bool SDL_monitor_desc::video_open(void) return false; } +#ifdef WIN32 + // Chain in a new message handler for WM_DEVICECHANGE + HWND the_window = GetMainWindowHandle(); + sdl_window_proc = (WNDPROC)GetWindowLongPtr(the_window, GWLP_WNDPROC); + SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)windows_message_handler); +#endif + // Initialize VideoRefresh function VideoRefreshInit(); @@ -675,7 +1302,7 @@ bool SDL_monitor_desc::video_open(void) // Start redraw/input thread #ifndef USE_CPU_EMUL_SERVICES redraw_thread_cancel = false; - redraw_thread_active = ((redraw_thread = SDL_CreateThread(redraw_func, NULL)) != NULL); + redraw_thread_active = ((redraw_thread = SDL_CreateThread(redraw_func, "Redraw Thread", NULL)) != NULL); if (!redraw_thread_active) { printf("FATAL: cannot create redraw thread\n"); return false; @@ -686,10 +1313,22 @@ bool SDL_monitor_desc::video_open(void) return true; } +#ifdef SHEEPSHAVER +bool VideoInit(void) +{ + const bool classic = false; +#else bool VideoInit(bool classic) { +#endif classic_mode = classic; +#ifdef ENABLE_VOSF + // Zero the mainBuffer structure + mainBuffer.dirtyPages = NULL; + mainBuffer.pageInfo = NULL; +#endif + // Create Mutexes if ((sdl_events_lock = SDL_CreateMutex()) == NULL) return false; @@ -741,7 +1380,11 @@ bool VideoInit(bool classic) default_height = sdl_display_height(); // Mac screen depth follows X depth - screen_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel; + screen_depth = 32; + SDL_DisplayMode desktop_mode; + if (SDL_GetDesktopDisplayMode(0, &desktop_mode) == 0) { + screen_depth = SDL_BITSPERPIXEL(desktop_mode.format); + } int default_depth; switch (screen_depth) { case 8: @@ -764,6 +1407,19 @@ bool VideoInit(bool classic) int h; int resolution_id; } +#ifdef SHEEPSHAVER + // Omit Classic resolutions + video_modes[] = { + { -1, -1, 0x80 }, + { 640, 480, 0x81 }, + { 800, 600, 0x82 }, + { 1024, 768, 0x83 }, + { 1152, 870, 0x84 }, + { 1280, 1024, 0x85 }, + { 1600, 1200, 0x86 }, + { 0, } + }; +#else video_modes[] = { { -1, -1, 0x80 }, { 512, 384, 0x80 }, @@ -775,6 +1431,7 @@ bool VideoInit(bool classic) { 1600, 1200, 0x86 }, { 0, } }; +#endif video_modes[0].w = default_width; video_modes[0].h = default_height; @@ -798,8 +1455,6 @@ bool VideoInit(bool classic) const int h = video_modes[i].h; if (i > 0 && (w >= default_width || h >= default_height)) continue; - if (w == 512 && h == 384) - continue; for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d); } @@ -817,6 +1472,10 @@ bool VideoInit(bool classic) const VIDEO_MODE & mode = (*i); if (VIDEO_MODE_X == default_width && VIDEO_MODE_Y == default_height && VIDEO_MODE_DEPTH == default_depth) { default_id = VIDEO_MODE_RESOLUTION; +#ifdef SHEEPSHAVER + std::vector::const_iterator begin = VideoModes.begin(); + cur_mode = distance(begin, i); +#endif break; } } @@ -824,8 +1483,22 @@ bool VideoInit(bool classic) const VIDEO_MODE & mode = VideoModes[0]; default_depth = VIDEO_MODE_DEPTH; default_id = VIDEO_MODE_RESOLUTION; +#ifdef SHEEPSHAVER + cur_mode = 0; +#endif } +#ifdef SHEEPSHAVER + for (int i = 0; i < VideoModes.size(); i++) + VModes[i] = VideoModes[i]; + VideoInfo *p = &VModes[VideoModes.size()]; + p->viType = DIS_INVALID; // End marker + p->viRowBytes = 0; + p->viXsize = p->viYsize = 0; + p->viAppleMode = 0; + p->viAppleID = 0; +#endif + #if DEBUG D(bug("Available video modes:\n")); for (i = VideoModes.begin(); i != end; ++i) { @@ -839,8 +1512,12 @@ bool VideoInit(bool classic) } #endif + int color_depth = get_customized_color_depth(default_depth); + + D(bug("Return get_customized_color_depth %d\n", color_depth)); + // Create SDL_monitor_desc for this (the only) display - SDL_monitor_desc *monitor = new SDL_monitor_desc(VideoModes, (video_depth)default_depth, default_id); + SDL_monitor_desc *monitor = new SDL_monitor_desc(VideoModes, (video_depth)color_depth, default_id); VideoMonitors.push_back(monitor); // Open display @@ -857,6 +1534,12 @@ void SDL_monitor_desc::video_close(void) { D(bug("video_close()\n")); +#ifdef WIN32 + // Remove message handler for WM_DEVICECHANGE + HWND the_window = GetMainWindowHandle(); + SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)sdl_window_proc); +#endif + // Stop redraw thread #ifndef USE_CPU_EMUL_SERVICES if (redraw_thread_active) { @@ -911,37 +1594,40 @@ static void do_toggle_fullscreen(void) while (!thread_stop_ack) ; #endif - // save the mouse position - int x, y; - SDL_GetMouseState(&x, &y); - - // save the screen contents - SDL_Surface *tmp_surface = SDL_ConvertSurface(drv->s, drv->s->format, - drv->s->flags); + // Apply fullscreen + if (sdl_window) { + if (display_type == DISPLAY_SCREEN) { + display_type = DISPLAY_WINDOW; + SDL_SetWindowFullscreen(sdl_window, 0); + const VIDEO_MODE &mode = drv->mode; + SDL_SetWindowSize(sdl_window, VIDEO_MODE_X, VIDEO_MODE_Y); + SDL_SetWindowGrab(sdl_window, SDL_FALSE); + } else { + display_type = DISPLAY_SCREEN; +#ifdef __MACOSX__ + SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN_DESKTOP); +#else + SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN); +#endif + SDL_SetWindowGrab(sdl_window, SDL_TRUE); + } + } // switch modes - display_type = (display_type == DISPLAY_SCREEN) ? DISPLAY_WINDOW - : DISPLAY_SCREEN; - drv->set_video_mode(display_type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0); drv->adapt_to_video_mode(); // reset the palette +#ifdef SHEEPSHAVER + video_set_palette(); +#endif drv->update_palette(); - // restore the screen contents - SDL_BlitSurface(tmp_surface, NULL, drv->s, NULL); - SDL_FreeSurface(tmp_surface); - SDL_UpdateRect(drv->s, 0, 0, 0, 0); - // reset the video refresh handler VideoRefreshInit(); // while SetVideoMode is happening, control key up may be missed ADBKeyUp(0x36); - - // restore the mouse position - SDL_WarpMouse(x, y); - + // resume redraw thread toggle_fullscreen = false; #ifndef USE_CPU_EMUL_SERVICES @@ -957,6 +1643,48 @@ static void do_toggle_fullscreen(void) * Execute video VBL routine */ +static bool is_fullscreen(SDL_Window * window) +{ +// #ifdef __MACOSX__ +// // On OSX, SDL, at least as of 2.0.5 (and possibly beyond), does not always +// // report changes to fullscreen via the SDL_WINDOW_FULLSCREEN flag. +// // (Example: https://bugzilla.libsdl.org/show_bug.cgi?id=3766 , which +// // involves fullscreen/windowed toggles via window-manager UI controls). +// // Until it does, or adds a facility to do so, we'll use a platform-specific +// // code path to detect fullscreen changes. +// extern bool is_fullscreen_osx(SDL_Window * window); +// return is_fullscreen_osx(sdl_window); +// #else + if (!window) { + return false; + } + const Uint32 sdl_window_flags = SDL_GetWindowFlags(sdl_window); + return (sdl_window_flags & SDL_WINDOW_FULLSCREEN) != 0; +// #endif +} + +#ifdef SHEEPSHAVER +void VideoVBL(void) +{ + // Emergency quit requested? Then quit + if (emerg_quit) + QuitEmulator(); + + if (toggle_fullscreen) + do_toggle_fullscreen(); + + present_sdl_video(); + + // Temporarily give up frame buffer lock (this is the point where + // we are suspended when the user presses Ctrl-Tab) + UNLOCK_FRAME_BUFFER; + LOCK_FRAME_BUFFER; + + // Execute video VBL + if (private_data != NULL && private_data->interruptsEnabled) + VSLDoInterruptService(private_data->vslServiceID); +} +#else void VideoInterrupt(void) { // We must fill in the events queue in the same thread that did call SDL_SetVideoMode() @@ -969,17 +1697,35 @@ void VideoInterrupt(void) if (toggle_fullscreen) do_toggle_fullscreen(); + present_sdl_video(); + // Temporarily give up frame buffer lock (this is the point where // we are suspended when the user presses Ctrl-Tab) UNLOCK_FRAME_BUFFER; LOCK_FRAME_BUFFER; } +#endif /* * Set palette */ +#ifdef SHEEPSHAVER +void video_set_palette(void) +{ + monitor_desc * monitor = VideoMonitors[0]; + int n_colors = palette_size(monitor->get_current_mode().viAppleMode); + uint8 pal[256 * 3]; + for (int c = 0; c < n_colors; c++) { + pal[c*3 + 0] = mac_pal[c].red; + pal[c*3 + 1] = mac_pal[c].green; + pal[c*3 + 2] = mac_pal[c].blue; + } + monitor->set_palette(pal, n_colors); +} +#endif + void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) { const VIDEO_MODE &mode = get_current_mode(); @@ -993,7 +1739,12 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) // Convert colors to XColor array int num_out = 256; bool stretch = false; - SDL_Color *p = sdl_palette; + + if (!sdl_palette) { + sdl_palette = SDL_AllocPalette(num_out); + } + + SDL_Color *p = sdl_palette->colors; for (int i=0; ir = pal[c*3 + 0] * 0x0101; @@ -1009,6 +1760,15 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) ExpandMap[i] = SDL_MapRGB(drv->s->format, pal[c*3+0], pal[c*3+1], pal[c*3+2]); } +#ifdef ENABLE_VOSF + if (use_vosf) { + // We have to redraw everything because the interpretation of pixel values changed + LOCK_VOSF; + PFLAG_SET_ALL; + UNLOCK_VOSF; + memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); + } +#endif } // Tell redraw thread to change palette @@ -1022,6 +1782,46 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in) * Switch video mode */ +#ifdef SHEEPSHAVER +int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr) +{ + /* return if no mode change */ + if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) && + (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr; + + /* first find video mode in table */ + for (int i=0; VModes[i].viType != DIS_INVALID; i++) { + if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) && + (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) { + csSave->saveMode = ReadMacInt16(ParamPtr + csMode); + csSave->saveData = ReadMacInt32(ParamPtr + csData); + csSave->savePage = ReadMacInt16(ParamPtr + csPage); + + // Disable interrupts and pause redraw thread + DisableInterrupt(); + thread_stop_ack = false; + thread_stop_req = true; + while (!thread_stop_ack) ; + + cur_mode = i; + monitor_desc *monitor = VideoMonitors[0]; + monitor->switch_to_current_mode(); + + WriteMacInt32(ParamPtr + csBaseAddr, screen_base); + csSave->saveBaseAddr=screen_base; + csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ + csSave->saveMode=VModes[cur_mode].viAppleMode; + + // Enable interrupts and resume redraw thread + thread_stop_req = false; + EnableInterrupt(); + return noErr; + } + } + return paramErr; +} +#endif + void SDL_monitor_desc::switch_to_current_mode(void) { // Close and reopen display @@ -1036,6 +1836,59 @@ void SDL_monitor_desc::switch_to_current_mode(void) } } + +/* + * Can we set the MacOS cursor image into the window? + */ + +#ifdef SHEEPSHAVER +bool video_can_change_cursor(void) +{ + return PrefsFindBool("hardcursor") && (display_type == DISPLAY_WINDOW || PrefsFindBool("scale_integer")); +} +#endif + + +/* + * Set cursor image for window + */ + +#ifdef SHEEPSHAVER +void video_set_cursor(void) +{ + // Set new cursor image if it was changed + if (sdl_cursor) { + SDL_FreeCursor(sdl_cursor); + sdl_cursor = MagCursor(true); + if (sdl_cursor) { + SDL_ShowCursor(private_data == NULL || private_data->cursorVisible); + SDL_SetCursor(sdl_cursor); + + // XXX Windows apparently needs an extra mouse event to + // make the new cursor image visible. + // On Mac, if mouse is grabbed, SDL_ShowCursor() recenters the + // mouse, we have to put it back. + bool move = false; +#ifdef WIN32 + move = true; +#elif defined(__APPLE__) + move = mouse_grabbed; +#endif + if (move) { + int visible = SDL_ShowCursor(-1); + if (visible) { + int x, y; + SDL_GetMouseState(&x, &y); + printf("WarpMouse to {%d,%d} via video_set_cursor\n", x, y); + SDL_WarpMouseGlobal(x, y); + } + } + } + } +} +#endif + + /* * Keyboard-related utilify functions */ @@ -1043,29 +1896,31 @@ void SDL_monitor_desc::switch_to_current_mode(void) static bool is_modifier_key(SDL_KeyboardEvent const & e) { switch (e.keysym.sym) { - case SDLK_NUMLOCK: + case SDLK_NUMLOCKCLEAR: case SDLK_CAPSLOCK: - case SDLK_SCROLLOCK: + case SDLK_SCROLLLOCK: case SDLK_RSHIFT: case SDLK_LSHIFT: case SDLK_RCTRL: case SDLK_LCTRL: case SDLK_RALT: case SDLK_LALT: - case SDLK_RMETA: - case SDLK_LMETA: - case SDLK_LSUPER: - case SDLK_RSUPER: + case SDLK_RGUI: + case SDLK_LGUI: case SDLK_MODE: - case SDLK_COMPOSE: + case SDLK_APPLICATION: return true; } return false; } -static bool is_ctrl_down(SDL_keysym const & ks) +static bool is_hotkey_down(SDL_Keysym const & ks) { - return ctrl_down || (ks.mod & KMOD_CTRL); + int hotkey = PrefsFindInt32("hotkey"); + if (!hotkey) hotkey = 1; + return (ctrl_down || (ks.mod & KMOD_CTRL) || !(hotkey & 1)) && + (opt_down || (ks.mod & KMOD_ALT) || !(hotkey & 2)) && + (cmd_down || (ks.mod & KMOD_GUI) || !(hotkey & 4)); } @@ -1074,7 +1929,7 @@ static bool is_ctrl_down(SDL_keysym const & ks) * and -2 if the key was recognized as a hotkey */ -static int kc_decode(SDL_keysym const & ks, bool key_down) +static int kc_decode(SDL_Keysym const & ks, bool key_down) { switch (ks.sym) { case SDLK_a: return 0x00; @@ -1115,7 +1970,7 @@ static int kc_decode(SDL_keysym const & ks, bool key_down) case SDLK_9: return 0x19; case SDLK_0: return 0x1d; - case SDLK_BACKQUOTE: return 0x0a; + case SDLK_BACKQUOTE: case 167: return 0x32; case SDLK_MINUS: case SDLK_UNDERSCORE: return 0x1b; case SDLK_EQUALS: case SDLK_PLUS: return 0x18; case SDLK_LEFTBRACKET: return 0x21; @@ -1127,8 +1982,8 @@ static int kc_decode(SDL_keysym const & ks, bool key_down) case SDLK_PERIOD: case SDLK_GREATER: return 0x2f; case SDLK_SLASH: case SDLK_QUESTION: return 0x2c; - case SDLK_TAB: if (is_ctrl_down(ks)) {if (!key_down) drv->suspend(); return -2;} else return 0x30; - case SDLK_RETURN: if (is_ctrl_down(ks)) {if (!key_down) toggle_fullscreen = true; return -2;} else return 0x24; + case SDLK_TAB: if (is_hotkey_down(ks)) {if (!key_down) drv->suspend(); return -2;} else return 0x30; + case SDLK_RETURN: if (is_hotkey_down(ks)) {if (!key_down) toggle_fullscreen = true; return -2;} else return 0x24; case SDLK_SPACE: return 0x31; case SDLK_BACKSPACE: return 0x33; @@ -1143,35 +1998,33 @@ static int kc_decode(SDL_keysym const & ks, bool key_down) case SDLK_RCTRL: return 0x36; case SDLK_LSHIFT: return 0x38; case SDLK_RSHIFT: return 0x38; -#if (defined(__APPLE__) && defined(__MACH__)) +#ifdef __APPLE__ case SDLK_LALT: return 0x3a; case SDLK_RALT: return 0x3a; - case SDLK_LMETA: return 0x37; - case SDLK_RMETA: return 0x37; + case SDLK_LGUI: return 0x37; + case SDLK_RGUI: return 0x37; #else case SDLK_LALT: return 0x37; case SDLK_RALT: return 0x37; - case SDLK_LMETA: return 0x3a; - case SDLK_RMETA: return 0x3a; + case SDLK_LGUI: return 0x3a; + case SDLK_RGUI: return 0x3a; #endif - case SDLK_LSUPER: return 0x3a; // "Windows" key - case SDLK_RSUPER: return 0x3a; case SDLK_MENU: return 0x32; case SDLK_CAPSLOCK: return 0x39; - case SDLK_NUMLOCK: return 0x47; + case SDLK_NUMLOCKCLEAR: return 0x47; case SDLK_UP: return 0x3e; case SDLK_DOWN: return 0x3d; case SDLK_LEFT: return 0x3b; case SDLK_RIGHT: return 0x3c; - case SDLK_ESCAPE: if (is_ctrl_down(ks)) {if (!key_down) { quit_full_screen = true; emerg_quit = true; } return -2;} else return 0x35; + case SDLK_ESCAPE: if (is_hotkey_down(ks)) {if (!key_down) { quit_full_screen = true; emerg_quit = true; } return -2;} else return 0x35; - case SDLK_F1: if (is_ctrl_down(ks)) {if (!key_down) SysMountFirstFloppy(); return -2;} else return 0x7a; + case SDLK_F1: if (is_hotkey_down(ks)) {if (!key_down) SysMountFirstFloppy(); return -2;} else return 0x7a; case SDLK_F2: return 0x78; case SDLK_F3: return 0x63; case SDLK_F4: return 0x76; - case SDLK_F5: if (is_ctrl_down(ks)) {if (!key_down) drv->toggle_mouse_grab(); return -2;} else return 0x60; + case SDLK_F5: return 0x60; case SDLK_F6: return 0x61; case SDLK_F7: return 0x62; case SDLK_F8: return 0x64; @@ -1180,20 +2033,20 @@ static int kc_decode(SDL_keysym const & ks, bool key_down) case SDLK_F11: return 0x67; case SDLK_F12: return 0x6f; - case SDLK_PRINT: return 0x69; - case SDLK_SCROLLOCK: return 0x6b; + case SDLK_PRINTSCREEN: return 0x69; + case SDLK_SCROLLLOCK: return 0x6b; case SDLK_PAUSE: return 0x71; - case SDLK_KP0: return 0x52; - case SDLK_KP1: return 0x53; - case SDLK_KP2: return 0x54; - case SDLK_KP3: return 0x55; - case SDLK_KP4: return 0x56; - case SDLK_KP5: return 0x57; - case SDLK_KP6: return 0x58; - case SDLK_KP7: return 0x59; - case SDLK_KP8: return 0x5b; - case SDLK_KP9: return 0x5c; + case SDLK_KP_0: return 0x52; + case SDLK_KP_1: return 0x53; + case SDLK_KP_2: return 0x54; + case SDLK_KP_3: return 0x55; + case SDLK_KP_4: return 0x56; + case SDLK_KP_5: return 0x57; + case SDLK_KP_6: return 0x58; + case SDLK_KP_7: return 0x59; + case SDLK_KP_8: return 0x5b; + case SDLK_KP_9: return 0x5c; case SDLK_KP_PERIOD: return 0x41; case SDLK_KP_PLUS: return 0x45; case SDLK_KP_MINUS: return 0x4e; @@ -1214,6 +2067,13 @@ static int event2keycode(SDL_KeyboardEvent const &ev, bool key_down) static void force_complete_window_refresh() { if (display_type == DISPLAY_WINDOW) { +#ifdef ENABLE_VOSF + if (use_vosf) { // VOSF refresh + LOCK_VOSF; + PFLAG_SET_ALL; + UNLOCK_VOSF; + } +#endif // Ensure each byte of the_buffer_copy differs from the_buffer to force a full update. const VIDEO_MODE &mode = VideoMonitors[0]->get_current_mode(); const int len = VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y; @@ -1226,15 +2086,78 @@ static void force_complete_window_refresh() * SDL event handling */ +// possible return codes for SDL-registered event watches +enum { + EVENT_DROP_FROM_QUEUE = 0, + EVENT_ADD_TO_QUEUE = 1 +}; + +// Some events need to be processed in the host-app's main thread, due to +// host-OS requirements. +// +// This function is called by SDL, whenever it generates an SDL_Event. It has +// the ability to process events, and optionally, to prevent them from being +// added to SDL's event queue (and retrieve-able via SDL_PeepEvents(), etc.) +static int SDLCALL on_sdl_event_generated(void *userdata, SDL_Event * event) +{ + switch (event->type) { + case SDL_KEYUP: { + SDL_Keysym const & ks = event->key.keysym; + switch (ks.sym) { + case SDLK_F5: { + if (is_hotkey_down(ks) && !PrefsFindBool("hardcursor")) { + drv->toggle_mouse_grab(); + return EVENT_DROP_FROM_QUEUE; + } + } break; + } + } break; + + case SDL_WINDOWEVENT: { + switch (event->window.event) { + case SDL_WINDOWEVENT_RESIZED: { + // Handle changes of fullscreen. This is done here, in + // on_sdl_event_generated() and not the main SDL_Event-processing + // loop, in order to perform this change on the main thread. + // (Some os'es UI APIs, such as OSX's NSWindow, are not + // thread-safe.) + const bool is_full = is_fullscreen(sdl_window); + const bool adjust_fullscreen = \ + (display_type == DISPLAY_WINDOW && is_full) || + (display_type == DISPLAY_SCREEN && !is_full); + if (adjust_fullscreen) { + do_toggle_fullscreen(); + +// #if __MACOSX__ +// // HACK-FIX: on OSX hosts, make sure that the OSX menu +// // bar does not show up in fullscreen mode, when the +// // cursor is near the top of the screen, lest the +// // guest OS' menu bar be obscured. +// if (is_full) { +// extern void set_menu_bar_visible_osx(bool); +// set_menu_bar_visible_osx(false); +// } +// #endif + } + } break; + } + } break; + } + + return EVENT_ADD_TO_QUEUE; +} + + static void handle_events(void) { SDL_Event events[10]; const int n_max_events = sizeof(events) / sizeof(events[0]); int n_events; - while ((n_events = SDL_PeepEvents(events, n_max_events, SDL_GETEVENT, sdl_eventmask)) > 0) { + while ((n_events = SDL_PeepEvents(events, n_max_events, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) > 0) { for (int i = 0; i < n_events; i++) { - SDL_Event const & event = events[i]; + SDL_Event & event = events[i]; + switch (event.type) { // Mouse button @@ -1246,19 +2169,6 @@ static void handle_events(void) ADBMouseDown(1); else if (button == SDL_BUTTON_MIDDLE) ADBMouseDown(2); - else if (button < 6) { // Wheel mouse - if (mouse_wheel_mode == 0) { - int key = (button == 5) ? 0x79 : 0x74; // Page up/down - ADBKeyDown(key); - ADBKeyUp(key); - } else { - int key = (button == 5) ? 0x3d : 0x3e; // Cursor up/down - for(int i=0; imouse_moved(event.motion.x, event.motion.y); + if (mouse_grabbed) { + drv->mouse_moved(event.motion.xrel, event.motion.yrel); + } else { + drv->mouse_moved(event.motion.x, event.motion.y); + } break; + case SDL_MOUSEWHEEL: + if (!event.wheel.y) break; + if (!mouse_wheel_mode) { + int key = event.wheel.y < 0 ? 0x79 : 0x74; // Page up/down + ADBKeyDown(key); + ADBKeyUp(key); + } + else { + int key = event.wheel.y < 0 ? 0x3d : 0x3e; // Cursor up/down + for (int i = 0; i < mouse_wheel_lines; i++) { + ADBKeyDown(key); + ADBKeyUp(key); + } + } + break; + // Keyboard case SDL_KEYDOWN: { int code = -1; @@ -1287,18 +2217,24 @@ static void handle_events(void) code = event2keycode(event.key, true); if (code >= 0) { if (!emul_suspended) { - if (code == 0x39) { // Caps Lock pressed - if (caps_on) { - ADBKeyUp(code); - caps_on = false; - } else { - ADBKeyDown(code); - caps_on = true; - } - } else + if (code == 0x39) + (SDL_GetModState() & KMOD_CAPS ? ADBKeyDown : ADBKeyUp)(code); + else ADBKeyDown(code); if (code == 0x36) ctrl_down = true; +#ifdef __APPLE__ + if (code == 0x3a) + opt_down = true; + if (code == 0x37) + cmd_down = true; +#else + if (code == 0x37) + opt_down = true; + if (code == 0x3a) + cmd_down = true; +#endif + } else { if (code == 0x31) drv->resume(); // Space wakes us up @@ -1314,39 +2250,47 @@ static void handle_events(void) } else code = event2keycode(event.key, false); if (code >= 0) { - if (code == 0x39) { // Caps Lock released - if (caps_on) { - ADBKeyUp(code); - caps_on = false; - } else { - ADBKeyDown(code); - caps_on = true; - } - } else + if (code != 0x39) ADBKeyUp(code); if (code == 0x36) ctrl_down = false; +#ifdef __APPLE__ + if (code == 0x3a) + opt_down = false; + if (code == 0x37) + cmd_down = false; +#else + if (code == 0x37) + opt_down = false; + if (code == 0x3a) + cmd_down = false; +#endif + } + break; + } + + case SDL_WINDOWEVENT: { + switch (event.window.event) { + // Hidden parts exposed, force complete refresh of window + case SDL_WINDOWEVENT_EXPOSED: + force_complete_window_refresh(); + break; + + // Force a complete window refresh when activating, to avoid redraw artifacts otherwise. + case SDL_WINDOWEVENT_RESTORED: + force_complete_window_refresh(); + break; + } break; } - // Hidden parts exposed, force complete refresh of window - case SDL_VIDEOEXPOSE: - force_complete_window_refresh(); - break; - // Window "close" widget clicked case SDL_QUIT: + if (SDL_GetModState() & (KMOD_LALT | KMOD_RALT)) break; ADBKeyDown(0x7f); // Power key ADBKeyUp(0x7f); break; - - // Application activate/deactivate - case SDL_ACTIVEEVENT: - // Force a complete window refresh when activating, to avoid redraw artifacts otherwise. - if (event.active.gain && (event.active.state & SDL_APPACTIVE)) - force_complete_window_refresh(); - break; } } } @@ -1386,7 +2330,7 @@ static void update_display_static(driver_base *drv) // Check for first column from left and first column from right that have changed if (high) { - if (VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { + if ((int)VIDEO_MODE_DEPTH < (int)VIDEO_DEPTH_8BIT) { const int src_bytes_per_row = bytes_per_row; const int dst_bytes_per_row = drv->s->pitch; const int pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row; @@ -1443,7 +2387,7 @@ static void update_display_static(driver_base *drv) SDL_UnlockSurface(drv->s); // Refresh display - SDL_UpdateRect(drv->s, x1, y1, wide, high); + update_sdl_video(drv->s, x1, y1, wide, high); } } else { @@ -1499,7 +2443,7 @@ static void update_display_static(driver_base *drv) SDL_UnlockSurface(drv->s); // Refresh display - SDL_UpdateRect(drv->s, x1, y1, wide, high); + update_sdl_video(drv->s, x1, y1, wide, high); } } } @@ -1562,7 +2506,7 @@ static void update_display_static_bbox(driver_base *drv) // Refresh display if (nr_boxes) - SDL_UpdateRects(drv->s, nr_boxes, boxes); + update_sdl_video(drv->s, nr_boxes, boxes); } @@ -1615,6 +2559,43 @@ static void video_refresh_dga(void) video_refresh_window_static(); } +#ifdef ENABLE_VOSF +#if REAL_ADDRESSING || DIRECT_ADDRESSING +static void video_refresh_dga_vosf(void) +{ + // Quit DGA mode if requested + possibly_quit_dga_mode(); + + // Update display (VOSF variant) + static uint32 tick_counter = 0; + if (++tick_counter >= frame_skip) { + tick_counter = 0; + if (mainBuffer.dirty) { + LOCK_VOSF; + update_display_dga_vosf(drv); + UNLOCK_VOSF; + } + } +} +#endif + +static void video_refresh_window_vosf(void) +{ + // Ungrab mouse if requested + possibly_ungrab_mouse(); + + // Update display (VOSF variant) + static uint32 tick_counter = 0; + if (++tick_counter >= frame_skip) { + tick_counter = 0; + if (mainBuffer.dirty) { + LOCK_VOSF; + update_display_window_vosf(drv); + UNLOCK_VOSF; + } + } +} +#endif // def ENABLE_VOSF static void video_refresh_window_static(void) { @@ -1642,10 +2623,20 @@ static void VideoRefreshInit(void) { // TODO: set up specialised 8bpp VideoRefresh handlers ? if (display_type == DISPLAY_SCREEN) { - video_refresh = video_refresh_dga; +#if ENABLE_VOSF && (REAL_ADDRESSING || DIRECT_ADDRESSING) + if (use_vosf) + video_refresh = video_refresh_dga_vosf; + else +#endif + video_refresh = video_refresh_dga; } else { - video_refresh = video_refresh_window_static; +#ifdef ENABLE_VOSF + if (use_vosf) + video_refresh = video_refresh_window_vosf; + else +#endif + video_refresh = video_refresh_window_static; } } @@ -1710,3 +2701,29 @@ static int redraw_func(void *arg) return 0; } #endif + + +/* + * Record dirty area from NQD + */ + +#ifdef SHEEPSHAVER +void video_set_dirty_area(int x, int y, int w, int h) +{ +#ifdef ENABLE_VOSF + const VIDEO_MODE &mode = drv->mode; + const unsigned screen_width = VIDEO_MODE_X; + const unsigned screen_height = VIDEO_MODE_Y; + const unsigned bytes_per_row = VIDEO_MODE_ROW_BYTES; + + if (use_vosf) { + vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row); + return; + } +#endif + + // XXX handle dirty bounding boxes for non-VOSF modes +} +#endif + +#endif // ends: SDL version check diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index c47046b3..eb217226 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -2,10 +2,10 @@ cmake_minimum_required(VERSION 3.0.0) project(BasiliskII) -find_package(SDL REQUIRED) +find_package(SDL2 REQUIRED) find_library(COREFOUNDATION_LIBRARY CoreFoundation) find_library(IOKIT_LIBRARY IOKit) -include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL2_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) add_executable(build68k ../uae_cpu/build68k.c) @@ -55,7 +55,7 @@ set(BasiliskII_SRCS #SYSSRC #SDL USE_SDL USE_SDL_VIDEO USE_SDL_AUDIO #video src - ../SDL/video_sdl.cpp + ../SDL/video_sdl2.cpp #EXTFSSRC extfs_unix.cpp #Serial src @@ -100,7 +100,7 @@ set_source_files_properties(${BasiliskII_SRCS} # set_property(SOURCE compemu_support.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O0 ") -target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY}) +target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL2_LIBRARIES}) # set(CMAKE_POSITION_INDEPENDENT_CODE OFF) diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 36814ffa..fd51fee8 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -450,7 +450,7 @@ int main(int argc, char **argv) #ifdef USE_SDL // SDL threads available, start 60Hz thread - tick_thread_active = ((tick_thread = SDL_CreateThread(tick_func, NULL)) != NULL); + tick_thread_active = ((tick_thread = SDL_CreateThread(tick_func, NULL, NULL)) != NULL); if (!tick_thread_active) { sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno)); ErrorAlert(str); @@ -464,7 +464,7 @@ int main(int argc, char **argv) #ifdef USE_SDL // Start XPRAM watchdog thread memcpy(last_xpram, XPRAM, XPRAM_SIZE); - xpram_thread_active = ((xpram_thread = SDL_CreateThread(xpram_func, NULL)) != NULL); + xpram_thread_active = ((xpram_thread = SDL_CreateThread(xpram_func, NULL, NULL)) != NULL); D(bug("XPRAM thread started\n")); #endif diff --git a/BasiliskII/src/Unix/timer_unix.cpp b/BasiliskII/src/Unix/timer_unix.cpp index f6db115e..03225ef5 100644 --- a/BasiliskII/src/Unix/timer_unix.cpp +++ b/BasiliskII/src/Unix/timer_unix.cpp @@ -22,6 +22,10 @@ #include "macos_util.h" #include "timer.h" +// #ifdef USE_SDL +// # include +// #endif + #include #define DEBUG 0 @@ -337,10 +341,19 @@ void Delay_usec(uint32 usec) // #endif // #endif +// SDL_mutex *idle_lock; +// SDL_cond *idle_cond; + void idle_wait(void) { //This causes events to not process randomly in JIT so commented out - usleep(10); + // if (!idle_lock) + // idle_lock = SDL_CreateMutex(); + // if (!idle_cond) + // idle_cond = SDL_CreateCond(); + // SDL_LockMutex(idle_lock); + // SDL_CondWait(idle_cond, idle_lock); + // SDL_UnlockMutex(idle_lock); // #ifdef IDLE_USES_COND_WAIT // pthread_mutex_lock(&idle_lock); @@ -373,6 +386,8 @@ void idle_wait(void) void idle_resume(void) { //This causes events to not process randomly in JIT so commented out + // if (idle_cond) + // SDL_CondSignal(idle_cond); // #ifdef IDLE_USES_COND_WAIT // pthread_cond_signal(&idle_cond); // #else From 48a41966fdb21154a166031f7ec1cdf2f05f8b6f Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 1 Sep 2019 16:56:03 -0500 Subject: [PATCH 12/20] Sync with ARAnyM compiler sources --- BasiliskII/src/Unix/main_unix.cpp | 4 +- BasiliskII/src/Unix/timer_unix.cpp | 28 +- .../src/uae_cpu/compiler/codegen_arm.cpp | 161 +- BasiliskII/src/uae_cpu/compiler/codegen_arm.h | 66 +- .../src/uae_cpu/compiler/codegen_x86.cpp | 2153 +------------ BasiliskII/src/uae_cpu/compiler/codegen_x86.h | 50 +- BasiliskII/src/uae_cpu/compiler/compemu.h | 89 +- .../src/uae_cpu/compiler/compemu_fpp.cpp | 2832 ++++++++++------- .../uae_cpu/compiler/compemu_midfunc_arm.cpp | 143 - .../uae_cpu/compiler/compemu_midfunc_arm.h | 2 + .../uae_cpu/compiler/compemu_midfunc_arm2.cpp | 233 -- .../uae_cpu/compiler/compemu_midfunc_x86.cpp | 369 +-- .../uae_cpu/compiler/compemu_midfunc_x86.h | 19 +- .../src/uae_cpu/compiler/compemu_support.cpp | 426 +-- BasiliskII/src/uae_cpu/compiler/gencomp.c | 695 ++-- BasiliskII/src/uae_cpu/compiler/gencomp_arm.c | 110 +- BasiliskII/src/uae_cpu/gencpu.c | 108 +- BasiliskII/src/uae_cpu/m68k.h | 711 ++++- BasiliskII/src/uae_cpu/newcpu.cpp | 10 +- BasiliskII/src/uae_cpu/noflags.h | 4 +- 20 files changed, 3100 insertions(+), 5113 deletions(-) diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index fd51fee8..6d17121f 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -57,7 +57,7 @@ using std::string; #include "sigsegv.h" #if USE_JIT -extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp +extern void (*flush_icache)(void); // from compemu_support.cpp #endif @@ -542,7 +542,7 @@ void FlushCodeCache(void *start, uint32 size) { #if USE_JIT if (UseJIT) - flush_icache_range((uint8 *)start, size); + flush_icache(); #endif } diff --git a/BasiliskII/src/Unix/timer_unix.cpp b/BasiliskII/src/Unix/timer_unix.cpp index 03225ef5..6fb8cf3e 100644 --- a/BasiliskII/src/Unix/timer_unix.cpp +++ b/BasiliskII/src/Unix/timer_unix.cpp @@ -22,9 +22,9 @@ #include "macos_util.h" #include "timer.h" -// #ifdef USE_SDL -// # include -// #endif +#ifdef USE_SDL +# include +#endif #include @@ -341,19 +341,19 @@ void Delay_usec(uint32 usec) // #endif // #endif -// SDL_mutex *idle_lock; -// SDL_cond *idle_cond; +SDL_mutex *idle_lock; +SDL_cond *idle_cond; void idle_wait(void) { //This causes events to not process randomly in JIT so commented out - // if (!idle_lock) - // idle_lock = SDL_CreateMutex(); - // if (!idle_cond) - // idle_cond = SDL_CreateCond(); - // SDL_LockMutex(idle_lock); - // SDL_CondWait(idle_cond, idle_lock); - // SDL_UnlockMutex(idle_lock); + if (!idle_lock) + idle_lock = SDL_CreateMutex(); + if (!idle_cond) + idle_cond = SDL_CreateCond(); + SDL_LockMutex(idle_lock); + SDL_CondWait(idle_cond, idle_lock); + SDL_UnlockMutex(idle_lock); // #ifdef IDLE_USES_COND_WAIT // pthread_mutex_lock(&idle_lock); @@ -386,8 +386,8 @@ void idle_wait(void) void idle_resume(void) { //This causes events to not process randomly in JIT so commented out - // if (idle_cond) - // SDL_CondSignal(idle_cond); + if (idle_cond) + SDL_CondSignal(idle_cond); // #ifdef IDLE_USES_COND_WAIT // pthread_cond_signal(&idle_cond); // #else diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp index fb7e69c7..01c49e30 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp @@ -190,13 +190,11 @@ LOWFUNC(NONE,WRITE,1,raw_push_l_r,(RR4 r)) { PUSH(r); } -LENDFUNC(NONE,WRITE,1,raw_push_l_r,(RR4 r)) LOWFUNC(NONE,READ,1,raw_pop_l_r,(RR4 r)) { POP(r); } -LENDFUNC(NONE,READ,1,raw_pop_l_r,(RR4 r)) LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, RR1 s)) { @@ -210,7 +208,6 @@ LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, RR1 s)) BIC_rri(d, d, 0xFF); // bic %[d],%[d],#0xFF ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], R3 LSR #24 } -LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, RR1 s)) LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, RR2 s)) { @@ -228,13 +225,11 @@ LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, RR2 s)) ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr %[d], %[d], r3, lsr #16 #endif } -LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, RR2 s)) LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, RR4 s)) { ADCS_rrr(d, d, s); // adcs %[d],%[d],%[s] } -LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, RR1 s)) { @@ -246,7 +241,6 @@ LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, RR1 s)) BIC_rri(d, d, 0xFF); // bic %[d],%[d],#0xFF ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], r3 LSR #24 } -LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, RR2 s)) { @@ -263,13 +257,11 @@ LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, RR2 s)) ORR_rrrLSRi(d, d, REG_WORK2, 16); // orr r7, r7, r3, LSR #16 #endif } -LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, RR4 s)) { ADDS_rrr(d, d, s); // adds %[d], %[d], %[s] } -LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) { @@ -305,7 +297,6 @@ LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) //: #endif } -LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) { @@ -316,7 +307,6 @@ LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) BIC_rri(d, d, 0xFF); // bic %[d],%[d], #0xFF ORR_rrrLSRi(d, d, REG_WORK2, 24); // orr %[d],%[d], r3, lsr #24 } -LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) { @@ -334,7 +324,6 @@ LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) //: #endif } -LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, RR1 s)) { @@ -348,7 +337,6 @@ LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, RR1 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, RR2 s)) { @@ -362,7 +350,6 @@ LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, RR2 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, RR4 s)) { @@ -372,7 +359,6 @@ LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, RR4 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) { @@ -396,7 +382,6 @@ LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) //: #endif } -LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, RR4 s)) { @@ -414,7 +399,6 @@ LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, RR4 s)) CC_ORR_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_Z_FLAG); // orr r3,r3,#0x40000000 MSR_CPSR_r(REG_WORK2); // msr cpsr,r3 } -LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, RR4 s)) LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) { @@ -435,7 +419,6 @@ LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) ORR_rrrLSLi(r,r,REG_WORK1, 8); // orr r6, r6, r2, lsl #8 #endif } -LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) { @@ -448,7 +431,6 @@ LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) EOR_rrrLSRi(r, r, REG_WORK1, 8); // eor r6, r6, r2, lsr #8 #endif } -LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(RR4 r, IMM i)) { @@ -460,7 +442,6 @@ LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(RR4 r, IMM i)) CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 } -LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(RR4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(RR4 r, RR4 b)) { @@ -473,7 +454,6 @@ LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(RR4 r, RR4 b)) CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3, r3, #0x20000000 MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 } -LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(RR4 r, RR4 b)) LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, RR4 b)) { @@ -488,7 +468,6 @@ LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, RR4 b)) EOR_rrr(r, r, REG_WORK1); // eor r6, r6, r2 MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 } -LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, RR4 b)) LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, RR4 b)) { @@ -503,7 +482,6 @@ LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, RR4 b)) BIC_rrr(r, r, REG_WORK1); // bic r6, r6, r2 MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 } -LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, RR4 b)) LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, RR4 b)) { @@ -518,7 +496,6 @@ LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, RR4 b)) ORR_rrr(r, r, REG_WORK1); // orr r6, r6, r2 MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 } -LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, RR4 b)) LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, RR4 s, IMM cc)) { @@ -543,7 +520,6 @@ LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, RR4 s, IMM cc)) } //: } -LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, RR4 s, IMM cc)) LOWFUNC(WRITE,NONE,2,raw_cmp_b,(RR1 d, RR1 s)) { @@ -560,7 +536,6 @@ LOWFUNC(WRITE,NONE,2,raw_cmp_b,(RR1 d, RR1 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_cmp_b,(RR1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_cmp_w,(RR2 d, RR2 s)) { @@ -578,7 +553,6 @@ LOWFUNC(WRITE,NONE,2,raw_cmp_w,(RR2 d, RR2 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_cmp_w,(RR2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_cmp_l,(RR4 d, RR4 s)) { @@ -588,14 +562,12 @@ LOWFUNC(WRITE,NONE,2,raw_cmp_l,(RR4 d, RR4 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_cmp_l,(RR4 d, RR4 s)) LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, RR4 s)) { SMULL_rrrr(REG_WORK1, REG_WORK2, d, s); // smull r2,r3,r7,r6 MOV_rr(d, REG_WORK1); // mov r7,r2 } -LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, RR4 s)) LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) { @@ -603,7 +575,6 @@ LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) MOV_rr(MUL_NREG1, REG_WORK1); // mov r7,r2 MOV_rr(MUL_NREG2, REG_WORK2); } -LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) { @@ -621,7 +592,6 @@ LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) //: #endif } -LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) { @@ -649,7 +619,6 @@ LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, I //; #endif } -LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) { @@ -664,7 +633,6 @@ LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) ADD_rrrLSLi(d, s, index, shft); // ADD R7,R6,R5,LSL #2 } -LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, RR4 s, IMM offset)) { @@ -686,7 +654,6 @@ LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, RR4 s, IMM offset)) //: #endif } -LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, RR4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(RR4 d, RR1 s, IMM offset)) { @@ -704,7 +671,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(RR4 d, RR1 s, IMM offset)) //: #endif } -LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(RR4 d, RR1 s, IMM offset)) LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) { @@ -725,7 +691,6 @@ LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) //: #endif } -LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, RR1 s)) { @@ -743,14 +708,12 @@ LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, RR1 s)) //: #endif } -LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, RR1 s)) LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) { BIC_rri(d, d, 0xff); // bic %[d], %[d], #0xff ORR_rri(d, d, (s & 0xff)); // orr %[d], %[d], #%[s] } -LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) { @@ -771,7 +734,6 @@ LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) //: #endif } -LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) { @@ -779,7 +741,6 @@ LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) BIC_rri(d, d, 0x0ff); // bic %[d], %[d], #0xff ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 } -LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, RR1 s)) LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, RR4 s, IMM offset)) { @@ -797,7 +758,6 @@ LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, RR4 s, IMM offset)) //: #endif } -LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, RR4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(RR4 d, RR4 s, IMM offset)) { @@ -815,7 +775,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(RR4 d, RR4 s, IMM offset)) //: #endif } -LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(RR4 d, RR4 s, IMM offset)) LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) { @@ -843,7 +802,6 @@ LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) //: #endif } -LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, RR4 s, IMM offset)) { @@ -874,7 +832,6 @@ LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, RR4 s, IMM offset)) //: #endif } -LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, RR4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(RR4 d, RR2 s, IMM offset)) { @@ -892,7 +849,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(RR4 d, RR2 s, IMM offset)) //: #endif } -LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(RR4 d, RR2 s, IMM offset)) LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, RR2 s)) { @@ -910,7 +866,6 @@ LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, RR2 s)) //: #endif } -LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, RR2 s)) LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) { @@ -942,7 +897,6 @@ LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) //: #endif } -LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) { @@ -973,7 +927,6 @@ LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) //: #endif } -LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) { @@ -991,7 +944,6 @@ LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) //: #endif } -LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, RR4 s)) LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(RR4 d, IMM i, IMM offset)) { @@ -1016,7 +968,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(RR4 d, IMM i, IMM offset)) //: #endif } -LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(RR4 d, IMM i, IMM offset)) LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) { @@ -1037,7 +988,6 @@ LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) //: #endif } -LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, RR2 s)) { @@ -1045,7 +995,6 @@ LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, RR2 s)) ORR_rrrLSRi(d, REG_WORK1, d, 16); // orr r7, r2, r7, lsr #16 ROR_rri(d, d, 16); // ror r7, r7, #16 } -LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, RR2 s)) LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, RR4 s, IMM offset)) { @@ -1064,7 +1013,6 @@ LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, RR4 s, IMM offset)) ORR_rrr(d, d, REG_WORK1); // orr r7, r7, r2 #endif } -LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, RR4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(RR4 d, RR2 s, IMM offset)) { @@ -1075,7 +1023,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(RR4 d, RR2 s, IMM offset)) else STRH_rRi(s, d, -offset);// strh r6, [r7, #-0x7f] } -LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(RR4 d, RR2 s, IMM offset)) LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) { @@ -1093,7 +1040,6 @@ LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) //: #endif } -LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor)) { @@ -1119,7 +1065,6 @@ LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor //: #endif } -LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, MEMR base, RR4 index, IMM factor)) LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(RR4 d, IMM i, IMM offset8)) { @@ -1143,7 +1088,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(RR4 d, IMM i, IMM offset8)) //: #endif } -LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(RR4 d, IMM i, IMM offset)) LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, RR4 s, IMM offset)) { @@ -1154,13 +1098,11 @@ LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, RR4 s, IMM offset)) } else LDR_rRi(d, s, -offset); // ldr r2, [r1, #12] } -LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, RR4 s, IMM offset)) LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, RR4 s)) { MOV_rr(d, s); // mov %[d], %[s] } -LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, RR4 s)) LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(RR4 d, RR4 s, IMM offset)) { @@ -1171,7 +1113,6 @@ LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(RR4 d, RR4 s, IMM offset)) else STR_rRi(s, d, -offset); // str r6, [r7, #-12] } -LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(RR4 d, RR4 s, IMM offset)) LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) { @@ -1179,7 +1120,6 @@ LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) MOV_rr(MUL_NREG1, REG_WORK1); // mov r7,r2 MOV_rr(MUL_NREG2, REG_WORK2); } -LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, RR1 s)) { @@ -1191,7 +1131,6 @@ LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, RR1 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, RR2 s)) { @@ -1208,7 +1147,6 @@ LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, RR2 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, RR4 s)) { @@ -1218,7 +1156,6 @@ LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, RR4 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) { @@ -1242,7 +1179,6 @@ LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) //jp: #endif } -LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) { @@ -1265,7 +1201,6 @@ LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) BIC_rri(r, r, 0xff); // bic r7,r7,#0xff ORR_rrr(r, r, REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, RR1 r)) { @@ -1292,7 +1227,6 @@ LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, RR1 r)) ORR_rrr(d, d, REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) { @@ -1315,7 +1249,6 @@ LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) ORR_rrrLSRi(r, r, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 } -LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, RR1 r)) { @@ -1341,7 +1274,6 @@ LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, RR1 r)) ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr r2,r2,r7,lsr #16 } -LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) { @@ -1356,13 +1288,11 @@ LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 MSR_CPSR_r(REG_WORK2); } -LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) { RORS_rri(r, r, i & 0x1F); // RORS r7,r7,#12 } -LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, RR1 r)) { @@ -1380,13 +1310,11 @@ LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, RR1 r)) CC_BIC_rri(NATIVE_CC_EQ, REG_WORK2, REG_WORK2, ARM_C_FLAG); // bic r3,r3,#0x20000000 MSR_CPSR_r(REG_WORK2); } -LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, RR1 r)) { RORS_rrr(d, d, r); // RORS r7,r7,r6 } -LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) { @@ -1400,7 +1328,6 @@ LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) BIC_rri(r, r, 0xff); // bic r7,r7,#0xff ORR_rrr(r, r, REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, RR1 r)) { @@ -1414,7 +1341,6 @@ LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, RR1 r)) BIC_rri(d, d, 0xff); // bic r7,r7,#0xff ORR_rrr(d, d, REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) { @@ -1428,7 +1354,6 @@ LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) ORR_rrrLSRi(r, r, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 } -LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, RR1 r)) { @@ -1442,7 +1367,6 @@ LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, RR1 r)) ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr r7,r7,r2,lsr #16 } -LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, RR1 r)) LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, RR1 s)) { @@ -1461,7 +1385,6 @@ LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, RR1 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, RR1 s)) LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, RR4 s)) { @@ -1475,7 +1398,6 @@ LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, RR4 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, RR4 s)) LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, RR2 s)) { @@ -1495,7 +1417,6 @@ LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, RR2 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, RR2 s)) LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) { @@ -1530,7 +1451,6 @@ LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) } //: } -LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) { @@ -1577,7 +1497,6 @@ LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) //: #endif } -LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) { @@ -1588,7 +1507,6 @@ LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) BIC_rri(r, r, 0xff); // BIC r7,r7,0xff ORR_rrrLSRi(r, r, REG_WORK1, 24); // ORR r7,r7,r2,lsr #24 } -LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, RR1 r)) { @@ -1597,19 +1515,16 @@ LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, RR1 r)) BIC_rri(d, d, 0xff); // BIC r7,r7,#0xff ORR_rrrLSRi(d, d, REG_WORK1, 24); // ORR r7,r7,r2,lsr #24 } -LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) { LSLS_rri(r,r, i & 0x1f); // lsls r7,r7,#12 } -LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, RR1 r)) { LSLS_rrr(d, d, r); } -LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) { @@ -1620,7 +1535,6 @@ LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) ROR_rri(r, REG_WORK1, 16); // ROR r7,r2,#16 } -LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, RR1 r)) { @@ -1629,7 +1543,6 @@ LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, RR1 r)) ORR_rrrLSRi(REG_WORK1, REG_WORK1, d, 16); // ORR r2,r2,r7,lsr #16 ROR_rri(d, REG_WORK1, 16); // ROR r7,r2,#16 } -LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) { @@ -1642,7 +1555,6 @@ LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) BIC_rri(r,r, 0xff); // bic r7,r7,#0xff ORR_rrr(r,r,REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, RR1 r)) { @@ -1656,7 +1568,6 @@ LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, RR1 r)) ORR_rrr(d,d,REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) { @@ -1677,7 +1588,6 @@ LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) ORR_rrr(r,r,REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, RR1 r)) { @@ -1698,19 +1608,16 @@ LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, RR1 r)) ORR_rrr(d,d,REG_WORK1); // orr r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) { ASRS_rri(r, r, i & 0x1f); // ASRS r7,r7,#12 } -LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, RR1 r)) { ASRS_rrr(d, d, r); // ASRS r7,r7,r6 } -LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) { @@ -1721,7 +1628,6 @@ LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) BIC_rri(r, r, 0xFF); // BIC r7,r7,#0xff ORR_rrr(r, r, REG_WORK1); // ORR r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, RR1 r)) { @@ -1732,13 +1638,11 @@ LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, RR1 r)) BIC_rri(d, d, 0xFF); // BIC r7,r7,#0xff ORR_rrr(d, d, REG_WORK1); // ORR r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) { LSRS_rri(r, r, i & 0x1f); // LSRS r7,r7,#12 } -LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) { @@ -1755,7 +1659,6 @@ LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) BIC_rri(r, r, 0xFF00); // BIC r7,r7,#0xff00 ORR_rrr(r, r, REG_WORK1); // ORR r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, RR1 r)) { @@ -1772,13 +1675,11 @@ LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, RR1 r)) BIC_rri(d, d, 0xFF00); // BIC r7,r7,#0xff00 ORR_rrr(d, d, REG_WORK1); // ORR r7,r7,r2 } -LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, RR1 r)) { LSRS_rrr(d, d, r); } -LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, RR1 r)) LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, RR1 s)) { @@ -1793,7 +1694,6 @@ LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, RR1 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) { @@ -1807,7 +1707,6 @@ LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, RR4 s)) { @@ -1817,7 +1716,6 @@ LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, RR4 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) { @@ -1841,7 +1739,6 @@ LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) //: #endif } -LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, RR2 s)) { @@ -1857,7 +1754,6 @@ LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, RR2 s)) EOR_rri(REG_WORK1, REG_WORK1, ARM_C_FLAG); // eor r2, r2, #0x20000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) { @@ -1890,7 +1786,6 @@ LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) //: #endif } -LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(RR1 d, RR1 s)) { @@ -1908,7 +1803,6 @@ LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(RR1 d, RR1 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(RR1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(RR4 d, IMM i)) { @@ -1932,7 +1826,6 @@ LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(RR4 d, IMM i)) //: #endif } -LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(RR4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(RR4 d, RR4 s)) { @@ -1942,7 +1835,6 @@ LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(RR4 d, RR4 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(RR4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(RR2 d, RR2 s)) { @@ -1960,7 +1852,6 @@ LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(RR2 d, RR2 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(RR2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, RR1 s)) { @@ -1972,7 +1863,6 @@ LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, RR1 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, RR2 s)) { @@ -1989,7 +1879,6 @@ LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, RR2 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, RR4 s)) { @@ -1999,7 +1888,6 @@ LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, RR4 s)) BIC_rri(REG_WORK1, REG_WORK1, ARM_CV_FLAGS); // bic r2, r2, #0x30000000 MSR_CPSR_r(REG_WORK1); // msr CPSR_fc, r2 } -LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, RR4 s)) LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, RR2 s)) { @@ -2010,7 +1898,6 @@ LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, RR2 s)) ASR_rri(d, d, 16); // asr r6, r6, #16 #endif } -LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, RR2 s)) LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, RR1 s)) { @@ -2021,7 +1908,6 @@ LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, RR1 s)) ASR_rri(d, d, 24); // asr r6, r6, #24 #endif } -LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, RR1 s)) LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, RR1 s)) { @@ -2032,7 +1918,6 @@ LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, RR1 s)) LSR_rri(d, d, 24); // lsr r2, r2, #24 #endif } -LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, RR1 s)) LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, RR2 s)) { @@ -2043,7 +1928,6 @@ LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, RR2 s)) BIC_rri(d, d, 0x00ff0000); // bic %[d], %[d], #0x00ff0000 #endif } -LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, RR2 s)) static inline void raw_dec_sp(int off) { @@ -2167,29 +2051,25 @@ D(panicbug("raw_fp_cleanup_drop")); raw_fp_init(); } -LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMPTRW m, FR r)) { jit_unimplemented("raw_fmov_mr_drop %x %x", m, r); } -LENDFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) -LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMPTRW m, FR r)) { jit_unimplemented("raw_fmov_mr %x %x", m, r); } -LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) -LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) +LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMPTRR m)) { jit_unimplemented("raw_fmov_rm %x %x", r, m); } -LENDFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) { jit_unimplemented("raw_fmov_rr %x %x", d, s); } -LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) static inline void raw_emit_nop_filler(int nbytes) { @@ -2235,19 +2115,16 @@ LOWFUNC(WRITE,NONE,2,raw_ADD_l_rr,(RW4 d, RR4 s)) { ADD_rrr(d, d, s); } -LENDFUNC(WRITE,NONE,2,raw_ADD_l_rr,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_ADD_l_rri,(RW4 d, RR4 s, IMM i)) { ADD_rri(d, s, i); } -LENDFUNC(WRITE,NONE,2,raw_ADD_l_rri,(RW4 d, RR4 s, IMM i)) LOWFUNC(WRITE,NONE,2,raw_SUB_l_rri,(RW4 d, RR4 s, IMM i)) { SUB_rri(d, s, i); } -LENDFUNC(WRITE,NONE,2,raw_SUB_l_rri,(RW4 d, RR4 s, IMM i)) LOWFUNC(WRITE,NONE,2,raw_AND_b_rr,(RW1 d, RR1 s)) { @@ -2255,19 +2132,16 @@ LOWFUNC(WRITE,NONE,2,raw_AND_b_rr,(RW1 d, RR1 s)) MVN_rrLSRi(REG_WORK1, REG_WORK1, 24); // mvn r2, %[s], lsr #24 AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 } -LENDFUNC(WRITE,NONE,2,raw_AND_b_rr,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_AND_l_rr,(RW4 d, RR4 s)) { AND_rrr(d, d, s); } -LENDFUNC(WRITE,NONE,2,raw_AND_l_rr,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_AND_l_ri,(RW4 d, IMM i)) { AND_rri(d, d, i); } -LENDFUNC(WRITE,NONE,2,raw_AND_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_AND_w_rr,(RW2 d, RR2 s)) { @@ -2275,7 +2149,6 @@ LOWFUNC(WRITE,NONE,2,raw_AND_w_rr,(RW2 d, RR2 s)) MVN_rrLSRi(REG_WORK1, REG_WORK1, 16); // mvn r2, %[s], lsr #16 AND_rrr(d, d, REG_WORK1); // and %[d], %[d], r2 } -LENDFUNC(WRITE,NONE,2,raw_AND_w_rr,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_EOR_b_rr,(RW1 d, RR1 s)) { @@ -2286,13 +2159,11 @@ LOWFUNC(WRITE,NONE,2,raw_EOR_b_rr,(RW1 d, RR1 s)) #endif EOR_rrr(d, d, REG_WORK1); // eor %[d], %[d], r2 } -LENDFUNC(WRITE,NONE,2,raw_EOR_b_rr,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_EOR_l_rr,(RW4 d, RR4 s)) { EOR_rrr(d, d, s); // eors r7, r7, r6 } -LENDFUNC(WRITE,NONE,2,raw_EOR_l_rr,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_EOR_w_rr,(RW2 d, RR2 s)) { @@ -2304,7 +2175,6 @@ LOWFUNC(WRITE,NONE,2,raw_EOR_w_rr,(RW2 d, RR2 s)) EOR_rrrLSRi(d, d, REG_WORK1, 16); // orr %[d], %[d], r2 #endif } -LENDFUNC(WRITE,NONE,2,raw_EOR_w_rr,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_LDR_l_ri,(RW4 d, IMM i)) { @@ -2317,13 +2187,11 @@ LOWFUNC(WRITE,NONE,2,raw_LDR_l_ri,(RW4 d, IMM i)) emit_long(i); #endif } -LENDFUNC(WRITE,NONE,2,raw_LDR_l_rr,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_MOV_l_ri8,(RW4 d, IMM i)) { MOV_ri(d, i); } -LENDFUNC(WRITE,NONE,2,raw_MOV_l_ri8,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_ORR_b_rr,(RW1 d, RR1 s)) { @@ -2334,13 +2202,11 @@ LOWFUNC(WRITE,NONE,2,raw_ORR_b_rr,(RW1 d, RR1 s)) #endif ORR_rrr(d, d, REG_WORK1); // orr %[d], %[d], r2 } -LENDFUNC(WRITE,NONE,2,raw_ORR_b_rr,(RW1 d, RR1 s)) LOWFUNC(WRITE,NONE,2,raw_ORR_l_rr,(RW4 d, RR4 s)) { ORR_rrr(d, d, s); } -LENDFUNC(WRITE,NONE,2,raw_ORR_l_rr,(RW4 d, RR4 s)) LOWFUNC(WRITE,NONE,2,raw_ORR_w_rr,(RW2 d, RR2 s)) { @@ -2352,13 +2218,11 @@ LOWFUNC(WRITE,NONE,2,raw_ORR_w_rr,(RW2 d, RR2 s)) ORR_rrrLSRi(d, d, REG_WORK1, 16); // orr %[d], %[d], r2 #endif } -LENDFUNC(WRITE,NONE,2,raw_ORR_w_rr,(RW2 d, RR2 s)) LOWFUNC(WRITE,NONE,2,raw_ROR_l_ri,(RW4 r, IMM i)) { ROR_rri(r, r, i); } -LENDFUNC(WRITE,NONE,2,raw_ROR_l_ri,(RW4 r, IMM i)) // // compuemu_support used raw calls @@ -2401,7 +2265,6 @@ LOWFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) //: #endif } -LENDFUNC(WRITE,RMW,2,compemu_raw_add_l_mi,(IMM d, IMM s)) LOWFUNC(WRITE,NONE,2,compemu_raw_and_l_ri,(RW4 d, IMM i)) { @@ -2416,7 +2279,6 @@ LOWFUNC(WRITE,NONE,2,compemu_raw_and_l_ri,(RW4 d, IMM i)) emit_long(i); #endif } -LENDFUNC(WRITE,NONE,2,compemu_raw_and_l_ri,(RW4 d, IMM i)) LOWFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) { @@ -2429,7 +2291,6 @@ LOWFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) EOR_rrrLSRi(r, r, REG_WORK1, 8); // eor r6, r6, r2, lsr #8 #endif } -LENDFUNC(NONE,NONE,1,compemu_raw_bswap_32,(RW4 r)) LOWFUNC(WRITE,NONE,2,compemu_raw_bt_l_ri,(RR4 r, IMM i)) { @@ -2441,7 +2302,6 @@ LOWFUNC(WRITE,NONE,2,compemu_raw_bt_l_ri,(RR4 r, IMM i)) CC_ORR_rri(NATIVE_CC_NE, REG_WORK2, REG_WORK2, ARM_C_FLAG); // orr r3, r3, #0x20000000 MSR_CPSR_r(REG_WORK2); // msr CPSR_fc, r3 } -LENDFUNC(WRITE,NONE,2,compemu_raw_bt_l_ri,(RR4 r, IMM i)) LOWFUNC(NONE,READ,5,compemu_raw_cmov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor, IMM cond)) { @@ -2478,7 +2338,6 @@ LOWFUNC(NONE,READ,5,compemu_raw_cmov_l_rm_indexed,(W4 d, IMM base, RR4 index, IM //: #endif } -LENDFUNC(NONE,READ,5,compemu_raw_cmov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor, IMM cond)) LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) { @@ -2510,7 +2369,6 @@ LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) //: #endif } -LENDFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi,(MEMR d, IMM s)) LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi8,(MEMR d, IMM s)) { @@ -2532,7 +2390,6 @@ LOWFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi8,(MEMR d, IMM s)) //: #endif } -LENDFUNC(WRITE,READ,2,compemu_raw_cmp_l_mi8,(MEMR d, IMM s)) LOWFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) { @@ -2550,7 +2407,6 @@ LOWFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) //: #endif } -LENDFUNC(NONE,NONE,3,compemu_raw_lea_l_brr,(W4 d, RR4 s, IMM offset)) LOWFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) { @@ -2565,7 +2421,6 @@ LOWFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM fa ADD_rrrLSLi(d, s, index, shft); // ADD R7,R6,R5,LSL #2 } -LENDFUNC(NONE,NONE,4,compemu_raw_lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) LOWFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) { @@ -2583,7 +2438,6 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) //: #endif } -LENDFUNC(NONE,WRITE,2,compemu_raw_mov_b_mr,(IMM d, RR1 s)) LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) { @@ -2608,7 +2462,6 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) //: #endif } -LENDFUNC(NONE,WRITE,2,compemu_raw_mov_l_mi,(MEMW d, IMM s)) LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) { @@ -2626,7 +2479,6 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) //: #endif } -LENDFUNC(NONE,WRITE,2,compemu_raw_mov_l_mr,(IMM d, RR4 s)) LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) { @@ -2642,7 +2494,6 @@ LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) //: #endif } -LENDFUNC(NONE,NONE,2,compemu_raw_mov_l_ri,(W4 d, IMM s)) LOWFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) { @@ -2659,13 +2510,11 @@ LOWFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) //: #endif } -LENDFUNC(NONE,READ,2,compemu_raw_mov_l_rm,(W4 d, MEMR s)) LOWFUNC(NONE,NONE,2,compemu_raw_mov_l_rr,(W4 d, RR4 s)) { MOV_rr(d, s); // mov %[d], %[s] } -LENDFUNC(NONE,NONE,2,compemu_raw_mov_l_rr,(W4 d, RR4 s)) LOWFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) { @@ -2683,7 +2532,6 @@ LOWFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) //: #endif } -LENDFUNC(NONE,WRITE,2,compemu_raw_mov_w_mr,(IMM d, RR2 s)) LOWFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) { @@ -2722,13 +2570,11 @@ LOWFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) //: #endif } -LENDFUNC(WRITE,RMW,2,compemu_raw_sub_l_mi,(MEMRW d, IMM s)) LOWFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) { TST_rr(d, s); // tst r7, r6 } -LENDFUNC(WRITE,NONE,2,compemu_raw_test_l_rr,(RR4 d, RR4 s)) LOWFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) { @@ -2739,7 +2585,6 @@ LOWFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) BIC_rri(d, d, 0x00ff0000); // bic %[d], %[d], #0x00ff0000 #endif } -LENDFUNC(NONE,NONE,2,compemu_raw_zero_extend_16_rr,(W4 d, RR2 s)) static inline void compemu_raw_call(uae_u32 t) { diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_arm.h b/BasiliskII/src/uae_cpu/compiler/codegen_arm.h index f92bb1da..e04ab9b8 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_arm.h +++ b/BasiliskII/src/uae_cpu/compiler/codegen_arm.h @@ -66,22 +66,22 @@ /* --- ENCODINGS ----------------------------------------------------------- */ /* ========================================================================= */ -#define IMM32(c) ((c & 0xffffff00) == 0 ? c : \ - (c & 0x3fffffc0) == 0 ? (0x100 | ((c >> 30) & 0x3) | ((c << 2) & 0xfc)) : \ - (c & 0x0ffffff0) == 0 ? (0x200 | ((c >> 28) & 0xf) | ((c << 4) & 0xf0)) : \ - (c & 0x03fffffc) == 0 ? (0x300 | ((c >> 26) & 0x3f) | ((c << 6) & 0xc0) ) : \ - (c & 0x00ffffff) == 0 ? (0x400 | ((c >> 24) & 0xff)) : \ - (c & 0xc03fffff) == 0 ? (0x500 | (c >> 22)) : \ - (c & 0xf00fffff) == 0 ? (0x600 | (c >> 20)) : \ - (c & 0xfc03ffff) == 0 ? (0x700 | (c >> 18)) : \ - (c & 0xff00ffff) == 0 ? (0x800 | (c >> 16)) : \ - (c & 0xffc03fff) == 0 ? (0x900 | (c >> 14)) : \ - (c & 0xfff00fff) == 0 ? (0xa00 | (c >> 12)) : \ - (c & 0xfffc03ff) == 0 ? (0xb00 | (c >> 10)) : \ - (c & 0xffff00ff) == 0 ? (0xc00 | (c >> 8)) : \ - (c & 0xffffc03f) == 0 ? (0xd00 | (c >> 6)) : \ - (c & 0xfffff00f) == 0 ? (0xe00 | (c >> 4)) : \ - (c & 0xfffffc03) == 0 ? (0xf00 | (c >> 2)) : \ +#define IMM32(c) (((c) & 0xffffff00) == 0 ? (c) : \ + ((c) & 0x3fffffc0) == 0 ? (0x100 | (((c) >> 30) & 0x3) | ((((c) & 0x0000003f) << 2))) : \ + ((c) & 0x0ffffff0) == 0 ? (0x200 | (((c) >> 28) & 0xf) | ((((c) & 0x0000000f) << 4))) : \ + ((c) & 0x03fffffc) == 0 ? (0x300 | (((c) >> 26) & 0x3f) | ((((c) & 0x00000003) << 6)) ) : \ + ((c) & 0x00ffffff) == 0 ? (0x400 | (((c) >> 24) & 0xff)) : \ + ((c) & 0xc03fffff) == 0 ? (0x500 | ((c) >> 22)) : \ + ((c) & 0xf00fffff) == 0 ? (0x600 | ((c) >> 20)) : \ + ((c) & 0xfc03ffff) == 0 ? (0x700 | ((c) >> 18)) : \ + ((c) & 0xff00ffff) == 0 ? (0x800 | ((c) >> 16)) : \ + ((c) & 0xffc03fff) == 0 ? (0x900 | ((c) >> 14)) : \ + ((c) & 0xfff00fff) == 0 ? (0xa00 | ((c) >> 12)) : \ + ((c) & 0xfffc03ff) == 0 ? (0xb00 | ((c) >> 10)) : \ + ((c) & 0xffff00ff) == 0 ? (0xc00 | ((c) >> 8)) : \ + ((c) & 0xffffc03f) == 0 ? (0xd00 | ((c) >> 6)) : \ + ((c) & 0xfffff00f) == 0 ? (0xe00 | ((c) >> 4)) : \ + ((c) & 0xfffffc03) == 0 ? (0xf00 | ((c) >> 2)) : \ 0\ ) @@ -102,7 +102,7 @@ #define SHIFT_RRX(Rm) ((Rm) | 0x60) #define SHIFT_PK(Rm,s) ((Rm) | ((s) << 7)) -// Load/Store addressings +/* Load/Store addressings */ #define ADR_ADD(v) ((1 << 23) | (v)) #define ADR_SUB(v) (v) @@ -138,16 +138,16 @@ #define ADD2_REG(Rm) ADR_ADD(Rm) #define SUB2_REG(Rm) ADR_SUB(Rm) -// MOV, MVN +/* MOV, MVN */ #define _OP1(cc,op,s,Rd,shift) _W(((cc) << 28) | ((op) << 21) | ((s) << 20) | ((Rd) << 12) | (shift)) -// CMP, CMN, TST, TEQ +/* CMP, CMN, TST, TEQ */ #define _OP2(cc,op,Rn,shift) _W(((cc) << 28) | ((op) << 21) | (1 << 20) | ((Rn) << 16) | (shift)) -// ADD, SUB, RSB, ADC, SBC, RSC, AND, BIC, EOR, ORR +/* ADD, SUB, RSB, ADC, SBC, RSC, AND, BIC, EOR, ORR */ #define _OP3(cc,op,s,Rd,Rn,shift) _W(((cc) << 28) | ((op) << 21) | ((s) << 20) | ((Rn) << 16) | ((Rd) << 12) | (shift)) -// LDR, STR +/* LDR, STR */ #define _LS1(cc,l,b,Rd,Rn,a) _W(((cc) << 28) | (0x01 << 26) | ((l) << 20) | ((b) << 22) | ((Rn) << 16) | ((Rd) << 12) | (a)) #define _LS2(cc,p,l,s,h,Rd,Rn,a) _W(((cc) << 28) | ((p) << 24) | ((l) << 20) | ((Rn) << 16) | ((Rd) << 12) | ((s) << 6) | ((h) << 5) | 0x90 | _LS2_ADDR((a))) @@ -211,9 +211,9 @@ enum { /* Data processing instructions */ /* Opcodes Type 1 */ -// MOVcc rd,#i +/* MOVcc rd,#i */ #define CC_MOV_ri8(cc,Rd,i) _OP1(cc,_MOV,0,Rd,UNSHIFTED_IMM8(i)) -// MOVcc Rd,#i ROR #s +/* MOVcc Rd,#i ROR #s */ #define CC_MOV_ri8RORi(cc,Rd,i,s) _OP1(cc,_MOV,0,Rd,SHIFT_IMM8_ROR(i,s)) #define CC_MOV_ri(cc,Rd,i) _OP1(cc,_MOV,0,Rd,SHIFT_IMM(i)) #define CC_MOV_rr(cc,Rd,Rm) _OP1(cc,_MOV,0,Rd,SHIFT_REG(Rm)) @@ -227,9 +227,9 @@ enum { #define CC_MOV_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MOV,0,Rd,SHIFT_ROR_r(Rm,Rs)) #define CC_MOV_rrRRX(cc,Rd,Rm) _OP1(cc,_MOV,0,Rd,SHIFT_RRX(Rm)) -// MOV rd,#i +/* MOV rd,#i */ #define MOV_ri8(Rd,i) CC_MOV_ri8(NATIVE_CC_AL,Rd,i) -// MOV Rd,#i ROR #s +/* MOV Rd,#i ROR #s */ #define MOV_ri8RORi(Rd,i,s) CC_MOV_ri8RORi(NATIVE_CC_AL,Rd,i,s) #define MOV_ri(Rd,i) CC_MOV_ri(NATIVE_CC_AL,Rd,i) #define MOV_rr(Rd,Rm) CC_MOV_rr(NATIVE_CC_AL,Rd,Rm) @@ -267,9 +267,9 @@ enum { #define MOVS_rrRORr(Rd,Rm,Rs) CC_MOVS_rrRORr(NATIVE_CC_AL,Rd,Rm,Rs) #define MOVS_rrRRX(Rd,Rm) CC_MOVS_rrRRX(NATIVE_CC_AL,Rd,Rm) -// MVNcc rd,#i +/* MVNcc rd,#i */ #define CC_MVN_ri8(cc,Rd,i) _OP1(cc,_MVN,0,Rd,UNSHIFTED_IMM8(i)) -// MVNcc Rd,#i ROR #s +/* MVNcc Rd,#i ROR #s */ #define CC_MVN_ri8RORi(cc,Rd,i,s) _OP1(cc,_MVN,0,Rd,SHIFT_IMM8_ROR(i,s)) #define CC_MVN_ri(cc,Rd,i) _OP1(cc,_MVN,0,Rd,SHIFT_IMM(i)) #define CC_MVN_rr(cc,Rd,Rm) _OP1(cc,_MVN,0,Rd,SHIFT_REG(Rm)) @@ -283,9 +283,9 @@ enum { #define CC_MVN_rrRORr(cc,Rd,Rm,Rs) _OP1(cc,_MVN,0,Rd,SHIFT_ROR_r(Rm,Rs)) #define CC_MVN_rrRRX(cc,Rd,Rm) _OP1(cc,_MVN,0,Rd,SHIFT_RRX(Rm)) -// MVN rd,#i +/* MVN rd,#i */ #define MVN_ri8(Rd,i) CC_MVN_ri8(NATIVE_CC_AL,Rd,i) -// MVN Rd,#i ROR #s +/* MVN Rd,#i ROR #s */ #define MVN_ri8RORi(Rd,i,s) CC_MVN_ri8RORi(NATIVE_CC_AL,Rd,i,s) #define MVN_ri(Rd,i) CC_MVN_ri(NATIVE_CC_AL,Rd,i) #define MVN_rr(Rd,Rm) CC_MVN_rr(NATIVE_CC_AL,Rd,Rm) @@ -811,9 +811,9 @@ enum { #define RSCS_rrrRORr(Rd,Rn,Rm,Rs) CC_RSCS_rrrRORr(NATIVE_CC_AL,Rd,Rn,Rm,Rs) #define RSCS_rrrRRX(Rd,Rn,Rm) CC_RSCS_rrrRRX(NATIVE_CC_AL,Rd,Rn,Rm) -// ORRcc Rd,Rn,#i +/* ORRcc Rd,Rn,#i */ #define CC_ORR_rri8(cc,Rd,Rn,i) _OP3(cc,_ORR,0,Rd,Rn,UNSHIFTED_IMM8(i)) -// ORRcc Rd,Rn,#i ROR #s +/* ORRcc Rd,Rn,#i ROR #s */ #define CC_ORR_rri8RORi(cc,Rd,Rn,i,s) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_IMM8_ROR(i,s)) #define CC_ORR_rri(cc,Rd,Rn,i) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_IMM(i)) @@ -828,9 +828,9 @@ enum { #define CC_ORR_rrrRORr(cc,Rd,Rn,Rm,Rs) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_ROR_r(Rm,Rs)) #define CC_ORR_rrrRRX(cc,Rd,Rn,Rm) _OP3(cc,_ORR,0,Rd,Rn,SHIFT_RRX(Rm)) -// ORR Rd,Rn,#i +/* ORR Rd,Rn,#i */ #define ORR_rri8(Rd,Rn,i) CC_ORR_rri8(NATIVE_CC_AL,Rd,Rn,i) -// ORR Rd,Rn,#i ROR #s +/* ORR Rd,Rn,#i ROR #s */ #define ORR_rri8RORi(Rd,Rn,i,s) CC_ORR_rri8RORi(NATIVE_CC_AL,Rd,Rn,i,s) #define ORR_rri(Rd,Rn,i) CC_ORR_rri(NATIVE_CC_AL,Rd,Rn,i) diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp index 24cfb548..573f2f9a 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp @@ -107,6 +107,10 @@ #if defined(CPU_x86_64) #ifdef UAE +/* Register R12 (and ESP) cannot be used with simple [r/m + disp32] addressing, + * since r/m bits 100 implies SIB byte. Simplest fix is to not use these + * registers. Also note that these registers are listed in the freescratch + * function as well. */ uae_s8 always_used[] = { ESP_INDEX, R12_INDEX, -1 }; #else uae_s8 always_used[] = { ESP_INDEX, -1 }; @@ -192,11 +196,6 @@ static const uae_u8 need_to_preserve[]={0,0,0,1,0,1,1,1}; #define CLOBBER_BT clobber_flags() #define CLOBBER_BSF clobber_flags() -/* The older code generator is now deprecated. */ -#define USE_NEW_RTASM 1 - -#if USE_NEW_RTASM - #if defined(CPU_x86_64) #define X86_TARGET_64BIT 1 /* The address override prefix causes a 5 cycles penalty on Intel Core @@ -296,7 +295,6 @@ LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) PUSHLr(r); #endif } -LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) { @@ -306,7 +304,6 @@ LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) POPLr(r); #endif } -LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) { @@ -316,307 +313,256 @@ LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) POPLm(d, X86_NOREG, X86_NOREG, 1); #endif } -LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) { BTLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) { BTLrr(b, r); } -LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) { BTCLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) { BTCLrr(b, r); } -LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) { BTRLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) { BTRLrr(b, r); } -LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) { BTSLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) { BTSLrr(b, r); } -LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) { SUBWir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) { ADDR32 MOVLmr(s, X86_NOREG, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) { ADDR32 MOVLim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) { ADDR32 MOVWim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) { ADDR32 MOVBim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) { ADDR32 ROLBim(i, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) { ROLBir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) { ROLWir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) { ROLLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) { ROLLrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) { ROLWrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) { ROLBrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) { SHLLrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) { SHLWrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) { SHLBrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) { RORBir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) { RORWir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) { ADDR32 ORLmr(s, X86_NOREG, X86_NOREG, 1, d); } -LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) { RORLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) { RORLrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) { RORWrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) { RORBrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) { SHRLrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) { SHRWrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) { SHRBrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) { SARLrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) { SARWrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) { SARBrr(r, d); } -LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) { SHLLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) { SHLWir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) { SHLBir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) { SHRLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) { SHRWir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) { SHRBir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) { SARLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) { SARWir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) { SARBir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) LOWFUNC(WRITE,NONE,1,raw_sahf,(R2)) { SAHF(); } -LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) LOWFUNC(NONE,NONE,1,raw_cpuid,(R4)) { CPUID(); } -LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) LOWFUNC(READ,NONE,1,raw_lahf,(W2)) { LAHF(); } -LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) { SETCCir(cc, d); } -LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) { ADDR32 SETCCim(cc, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) { @@ -629,49 +575,41 @@ LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); } } -LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) { BSFLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) LOWFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) { MOVSLQrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_sign_extend_32_rr,(W4 d, R4 s)) LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) { MOVSWLrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) { MOVSBLrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) { MOVZWLrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) { MOVZBLrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) { IMULLrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) { @@ -680,7 +618,6 @@ LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) } IMULLr(s); } -LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) { @@ -689,103 +626,86 @@ LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) } MULLr(s); } -LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4, R4)) { - abort(); /* %^$&%^$%#^ x86! */ + x86_emit_failure("raw_mul_32_32"); /* %^$&%^$%#^ x86! */ } -LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) { MOVBrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) { MOVWrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) { ADDR32 MOVLmr(0, baser, index, factor, d); } -LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) { ADDR32 MOVWmr(0, baser, index, factor, d); } -LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) { ADDR32 MOVBmr(0, baser, index, factor, d); } -LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) { ADDR32 MOVLrm(s, 0, baser, index, factor); } -LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) { ADDR32 MOVWrm(s, 0, baser, index, factor); } -LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) { ADDR32 MOVBrm(s, 0, baser, index, factor); } -LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) { ADDR32 MOVLrm(s, base, baser, index, factor); } -LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) { ADDR32 MOVWrm(s, base, baser, index, factor); } -LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) { ADDR32 MOVBrm(s, base, baser, index, factor); } -LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) { ADDR32 MOVLmr(base, baser, index, factor, d); } -LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) { ADDR32 MOVWmr(base, baser, index, factor, d); } -LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) { ADDR32 MOVBmr(base, baser, index, factor, d); } -LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) { ADDR32 MOVLmr(base, X86_NOREG, index, factor, d); } -LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) { @@ -798,7 +718,6 @@ LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); } } -LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) { @@ -811,493 +730,411 @@ LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) *target_p = (uintptr)x86_get_target() - ((uintptr)target_p + 1); } } -LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) { ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) { ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) { ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) { ADDR32 MOVLmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) { ADDR32 MOVWmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) { ADDR32 MOVBmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) { ADDR32 MOVLim(i, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) { ADDR32 MOVWim(i, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) { ADDR32 MOVBim(i, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) { ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) { ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) { ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) { ADDR32 LEALmr(offset, s, X86_NOREG, 1, d); } -LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) { ADDR32 LEALmr(offset, s, index, factor, d); } -LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) { ADDR32 LEALmr(0, s, index, factor, d); } -LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) LOWFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) { ADDR32 LEALmr(0, X86_NOREG, index, factor, d); } -LENDFUNC(NONE,NONE,4,raw_lea_l_r_scaled,(W4 d, R4 index, IMM factor)) LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) { ADDR32 MOVLrm(s, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) { ADDR32 MOVWrm(s, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) { ADDR32 MOVBrm(s, offset, d, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) { BSWAPLr(r); } -LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) { ROLWir(8, r); } -LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) { MOVLrr(s, d); } -LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) { ADDR32 MOVLrm(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) { ADDR32 MOVWrm(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) { ADDR32 MOVWmr(s, X86_NOREG, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) { ADDR32 MOVBrm(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) { ADDR32 MOVBmr(s, X86_NOREG, X86_NOREG, 1, d); } -LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) { MOVLir(s, d); } -LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) { MOVWir(s, d); } -LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) { MOVBir(s, d); } -LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) { ADDR32 ADCLim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) { ADDR32 ADDLim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) { ADDR32 ADDWim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) { ADDR32 ADDBim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) { TESTLir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) { TESTLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) { TESTWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) { TESTBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) { XORLir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) { ANDLir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) { ANDWir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) { ANDLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) { ANDWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) { ANDBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) { ORLir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) { ORLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) { ORWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) { ORBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) { ADCLrr(s, d); } -LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) { ADCWrr(s, d); } -LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) { ADCBrr(s, d); } -LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) { ADDLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) { ADDWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) { ADDBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) { SUBLir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) { SUBBir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) { ADDLir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) { ADDWir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) { ADDBir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) { SBBLrr(s, d); } -LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) { SBBWrr(s, d); } -LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) { SBBBrr(s, d); } -LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) { SUBLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) { SUBWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) { SUBBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) { CMPLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) { CMPLir(i, r); } -LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) { CMPWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) { ADDR32 CMPBim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) { CMPBir(i, d); } -LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) { CMPBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) { ADDR32 CMPLmr(offset, X86_NOREG, index, factor, d); } -LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) { XORLrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) { XORWrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) { XORBrr(s, d); } -LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) { ADDR32 SUBLim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) { ADDR32 CMPLim(s, d, X86_NOREG, X86_NOREG, 1); } -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) { XCHGLrr(r2, r1); } -LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) { XCHGBrr(r2, r1); } -LENDFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) { PUSHF(); } -LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) LOWFUNC(WRITE,READ,0,raw_popfl,(void)) { POPF(); } -LENDFUNC(WRITE,READ,0,raw_popfl,(void)) /* Generate floating-point instructions */ static inline void x86_fadd_m(MEMR s) @@ -1305,1796 +1142,6 @@ static inline void x86_fadd_m(MEMR s) ADDR32 FADDLm(s,X86_NOREG,X86_NOREG,1); } -#else - -const bool optimize_accum = true; -const bool optimize_imm8 = true; -const bool optimize_shift_once = true; - -/************************************************************************* - * Actual encoding of the instructions on the target CPU * - *************************************************************************/ - -static inline int isaccum(int r) -{ - return (r == EAX_INDEX); -} - -static inline int isbyte(uae_s32 x) -{ - return (x>=-128 && x<=127); -} - -static inline int isword(uae_s32 x) -{ - return (x>=-32768 && x<=32767); -} - -LOWFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) -{ - emit_byte(0x50+r); -} -LENDFUNC(NONE,WRITE,1,raw_push_l_r,(R4 r)) - -LOWFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) -{ - emit_byte(0x58+r); -} -LENDFUNC(NONE,READ,1,raw_pop_l_r,(R4 r)) - -LOWFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) -{ - emit_byte(0x8f); - emit_byte(0x05); - emit_long(d); -} -LENDFUNC(NONE,READ,1,raw_pop_l_m,(MEMW d)) - -LOWFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xe0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_bt_l_ri,(R4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xa3); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_bt_l_rr,(R4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xf8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_btc_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xbb); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_btc_l_rr,(RW4 r, R4 b)) - - -LOWFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xf0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_btr_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xb3); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_btr_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) -{ - emit_byte(0x0f); - emit_byte(0xba); - emit_byte(0xe8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_bts_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) -{ - emit_byte(0x0f); - emit_byte(0xab); - emit_byte(0xc0+8*b+r); -} -LENDFUNC(WRITE,NONE,2,raw_bts_l_rr,(RW4 r, R4 b)) - -LOWFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) -{ - emit_byte(0x66); - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe8+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x2d); - else { - emit_byte(0x81); - emit_byte(0xe8+d); - } - emit_word(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_sub_w_ri,(RW2 d, IMM i)) - - -LOWFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) -{ - emit_byte(0x8b); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(NONE,READ,2,raw_mov_l_rm,(W4 d, MEMR s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) -{ - emit_byte(0xc7); - emit_byte(0x05); - emit_long(d); - emit_long(s); -} -LENDFUNC(NONE,WRITE,2,raw_mov_l_mi,(MEMW d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0xc7); - emit_byte(0x05); - emit_long(d); - emit_word(s); -} -LENDFUNC(NONE,WRITE,2,raw_mov_w_mi,(MEMW d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) -{ - emit_byte(0xc6); - emit_byte(0x05); - emit_long(d); - emit_byte(s); -} -LENDFUNC(NONE,WRITE,2,raw_mov_b_mi,(MEMW d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0x05); - emit_long(d); - } - else { - emit_byte(0xc0); - emit_byte(0x05); - emit_long(d); - emit_byte(i); - } -} -LENDFUNC(WRITE,RMW,2,raw_rol_b_mi,(MEMRW d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xc0+r); - } - else { - emit_byte(0xc0); - emit_byte(0xc0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_rol_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xc0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_rol_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xc0+r); - } - else { - emit_byte(0xc1); - emit_byte(0xc0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_rol_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xc0+d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xc0+d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xc0+d); -} -LENDFUNC(WRITE,NONE,2,raw_rol_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xe0+d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xe0+d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xe0+d); -} -LENDFUNC(WRITE,NONE,2,raw_shll_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xc8+r); - } - else { - emit_byte(0xc0); - emit_byte(0xc8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_ror_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xc8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_ror_w_ri,(RW2 r, IMM i)) - -// gb-- used for making an fpcr value in compemu_fpp.cpp -LOWFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) -{ - emit_byte(0x0b); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(WRITE,READ,2,raw_or_l_rm,(RW4 d, MEMR s)) - -LOWFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xc8+r); - } - else { - emit_byte(0xc1); - emit_byte(0xc8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_ror_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xc8+d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xc8+d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xc8+d); -} -LENDFUNC(WRITE,NONE,2,raw_ror_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xe8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xe8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xe8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) -{ - emit_byte(0xd3); - emit_byte(0xf8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_l_rr,(RW4 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) -{ - emit_byte(0x66); - emit_byte(0xd3); - emit_byte(0xf8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_w_rr,(RW2 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) -{ - emit_byte(0xd2); - emit_byte(0xf8+d); -} -LENDFUNC(WRITE,NONE,2,raw_shra_b_rr,(RW1 d, R1 r)) - -LOWFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xe0+r); - } - else { - emit_byte(0xc1); - emit_byte(0xe0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shll_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xe0+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_shll_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xe0+r); - } - else { - emit_byte(0xc0); - emit_byte(0xe0+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shll_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xe8+r); - } - else { - emit_byte(0xc1); - emit_byte(0xe8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shrl_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xe8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_shrl_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xe8+r); - } - else { - emit_byte(0xc0); - emit_byte(0xe8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shrl_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd1); - emit_byte(0xf8+r); - } - else { - emit_byte(0xc1); - emit_byte(0xf8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shra_l_ri,(RW4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xf8+r); - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_shra_w_ri,(RW2 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) -{ - if (optimize_shift_once && (i == 1)) { - emit_byte(0xd0); - emit_byte(0xf8+r); - } - else { - emit_byte(0xc0); - emit_byte(0xf8+r); - emit_byte(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_shra_b_ri,(RW1 r, IMM i)) - -LOWFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) -{ - emit_byte(0x9e); -} -LENDFUNC(WRITE,NONE,1,raw_sahf,(R2 dummy_ah)) - -LOWFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) -{ - emit_byte(0x0f); - emit_byte(0xa2); -} -LENDFUNC(NONE,NONE,1,raw_cpuid,(R4 dummy_eax)) - -LOWFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) -{ - emit_byte(0x9f); -} -LENDFUNC(READ,NONE,1,raw_lahf,(W2 dummy_ah)) - -LOWFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) -{ - emit_byte(0x0f); - emit_byte(0x90+cc); - emit_byte(0xc0+d); -} -LENDFUNC(READ,NONE,2,raw_setcc,(W1 d, IMM cc)) - -LOWFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) -{ - emit_byte(0x0f); - emit_byte(0x90+cc); - emit_byte(0x05); - emit_long(d); -} -LENDFUNC(READ,WRITE,2,raw_setcc_m,(MEMW d, IMM cc)) - -LOWFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) -{ - if (have_cmov) { - emit_byte(0x0f); - emit_byte(0x40+cc); - emit_byte(0xc0+8*d+s); - } - else { /* replacement using branch and mov */ - int uncc=(cc^1); - emit_byte(0x70+uncc); - emit_byte(2); /* skip next 2 bytes if not cc=true */ - emit_byte(0x89); - emit_byte(0xc0+8*s+d); - } -} -LENDFUNC(READ,NONE,3,raw_cmov_l_rr,(RW4 d, R4 s, IMM cc)) - -LOWFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) -{ - emit_byte(0x0f); - emit_byte(0xbc); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(WRITE,NONE,2,raw_bsf_l_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) -{ - emit_byte(0x0f); - emit_byte(0xbf); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_16_rr,(W4 d, R2 s)) - -LOWFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) -{ - emit_byte(0x0f); - emit_byte(0xbe); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_sign_extend_8_rr,(W4 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) -{ - emit_byte(0x0f); - emit_byte(0xb7); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_zero_extend_16_rr,(W4 d, R2 s)) - -LOWFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) -{ - emit_byte(0x0f); - emit_byte(0xb6); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_zero_extend_8_rr,(W4 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) -{ - emit_byte(0x0f); - emit_byte(0xaf); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_imul_32_32,(RW4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) -{ - if (d!=MUL_NREG1 || s!=MUL_NREG2) { - jit_abort("Bad register in IMUL: d=%d, s=%d\n",d,s); - } - emit_byte(0xf7); - emit_byte(0xea); -} -LENDFUNC(NONE,NONE,2,raw_imul_64_32,(RW4 d, RW4 s)) - -LOWFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) -{ - if (d!=MUL_NREG1 || s!=MUL_NREG2) { - jit_abort("Bad register in MUL: d=%d, s=%d",d,s); - } - emit_byte(0xf7); - emit_byte(0xe2); -} -LENDFUNC(NONE,NONE,2,raw_mul_64_32,(RW4 d, RW4 s)) - -LOWFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) -{ - jit_abort("unsupported MUL"); /* %^$&%^$%#^ x86! */ - emit_byte(0x0f); - emit_byte(0xaf); - emit_byte(0xc0+8*d+s); -} -LENDFUNC(NONE,NONE,2,raw_mul_32_32,(RW4 d, R4 s)) - -LOWFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) -{ - emit_byte(0x88); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(NONE,NONE,2,raw_mov_b_rr,(W1 d, R1 s)) - -LOWFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(NONE,NONE,2,raw_mov_w_rr,(W2 d, R2 s)) - -LOWFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) -{ - int isebp=(baser==5)?0x40:0; - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - - emit_byte(0x8b); - emit_byte(0x04+8*d+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,READ,4,raw_mov_l_rrm_indexed,(W4 d,R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x04+8*d+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,READ,4,raw_mov_w_rrm_indexed,(W2 d, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x8a); - emit_byte(0x04+8*d+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,READ,4,raw_mov_b_rrm_indexed,(W1 d, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - - isebp=(baser==5)?0x40:0; - - emit_byte(0x89); - emit_byte(0x04+8*s+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,WRITE,4,raw_mov_l_mrr_indexed,(R4 baser, R4 index, IMM factor, R4 s)) - -LOWFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x04+8*s+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,WRITE,4,raw_mov_w_mrr_indexed,(R4 baser, R4 index, IMM factor, R2 s)) - -LOWFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) -{ - int fi; - int isebp; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - isebp=(baser==5)?0x40:0; - - emit_byte(0x88); - emit_byte(0x04+8*s+isebp); - emit_byte(baser+8*index+0x40*fi); - if (isebp) - emit_byte(0x00); -} -LENDFUNC(NONE,WRITE,4,raw_mov_b_mrr_indexed,(R4 baser, R4 index, IMM factor, R1 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x89); - emit_byte(0x84+8*s); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,WRITE,5,raw_mov_l_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R4 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x84+8*s); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,WRITE,5,raw_mov_w_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R2 s)) - -LOWFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x88); - emit_byte(0x84+8*s); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,WRITE,5,raw_mov_b_bmrr_indexed,(IMM base, R4 baser, R4 index, IMM factor, R1 s)) - -LOWFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x8b); - emit_byte(0x84+8*d); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,5,raw_mov_l_brrm_indexed,(W4 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x84+8*d); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,5,raw_mov_w_brrm_indexed,(W2 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x8a); - emit_byte(0x84+8*d); - emit_byte(baser+8*index+0x40*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,5,raw_mov_b_brrm_indexed,(W1 d, IMM base, R4 baser, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) -{ - int fi; - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: - jit_abort("Bad factor %d in mov_l_rm_indexed!",factor); - } - emit_byte(0x8b); - emit_byte(0x04+8*d); - emit_byte(0x05+8*index+64*fi); - emit_long(base); -} -LENDFUNC(NONE,READ,4,raw_mov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor)) - -LOWFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) -{ - int fi; - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: - jit_abort("Bad factor %d in mov_l_rm_indexed!",factor); - } - if (have_cmov) { - emit_byte(0x0f); - emit_byte(0x40+cond); - emit_byte(0x04+8*d); - emit_byte(0x05+8*index+64*fi); - emit_long(base); - } - else { /* replacement using branch and mov */ - int uncc=(cond^1); - emit_byte(0x70+uncc); - emit_byte(7); /* skip next 7 bytes if not cc=true */ - emit_byte(0x8b); - emit_byte(0x04+8*d); - emit_byte(0x05+8*index+64*fi); - emit_long(base); - } -} -LENDFUNC(NONE,READ,5,raw_cmov_l_rm_indexed,(W4 d, IMM base, R4 index, IMM factor, IMM cond)) - -LOWFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) -{ - if (have_cmov) { - emit_byte(0x0f); - emit_byte(0x40+cond); - emit_byte(0x05+8*d); - emit_long(mem); - } - else { /* replacement using branch and mov */ - int uncc=(cond^1); - emit_byte(0x70+uncc); - emit_byte(6); /* skip next 6 bytes if not cc=true */ - emit_byte(0x8b); - emit_byte(0x05+8*d); - emit_long(mem); - } -} -LENDFUNC(NONE,READ,3,raw_cmov_l_rm,(W4 d, IMM mem, IMM cond)) - -LOWFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x8b); - emit_byte(0x40+8*d+s); - emit_byte(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_l_rR,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x40+8*d+s); - emit_byte(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_w_rR,(W2 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x8a); - emit_byte(0x40+8*d+s); - emit_byte(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_b_rR,(W1 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) -{ - emit_byte(0x8b); - emit_byte(0x80+8*d+s); - emit_long(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_l_brR,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) -{ - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x80+8*d+s); - emit_long(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_w_brR,(W2 d, R4 s, IMM offset)) - -LOWFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) -{ - emit_byte(0x8a); - emit_byte(0x80+8*d+s); - emit_long(offset); -} -LENDFUNC(NONE,READ,3,raw_mov_b_brR,(W1 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0xc7); - emit_byte(0x40+d); - emit_byte(offset); - emit_long(i); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x66); - emit_byte(0xc7); - emit_byte(0x40+d); - emit_byte(offset); - emit_word(i); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0xc6); - emit_byte(0x40+d); - emit_byte(offset); - emit_byte(i); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_Ri,(R4 d, IMM i, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x89); - emit_byte(0x40+8*s+d); - emit_byte(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_Rr,(R4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x40+8*s+d); - emit_byte(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_Rr,(R4 d, R2 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) -{ - Dif(!isbyte(offset)) abort(); - emit_byte(0x88); - emit_byte(0x40+8*s+d); - emit_byte(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_Rr,(R4 d, R1 s, IMM offset)) - -LOWFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) -{ - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x8d); - emit_byte(0x40+8*d+s); - emit_byte(offset); - } - else { - emit_byte(0x8d); - emit_byte(0x80+8*d+s); - emit_long(offset); - } -} -LENDFUNC(NONE,NONE,3,raw_lea_l_brr,(W4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x8d); - emit_byte(0x44+8*d); - emit_byte(0x40*fi+8*index+s); - emit_byte(offset); - } - else { - emit_byte(0x8d); - emit_byte(0x84+8*d); - emit_byte(0x40*fi+8*index+s); - emit_long(offset); - } -} -LENDFUNC(NONE,NONE,5,raw_lea_l_brr_indexed,(W4 d, R4 s, R4 index, IMM factor, IMM offset)) - -LOWFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) -{ - int isebp=(s==5)?0x40:0; - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - - emit_byte(0x8d); - emit_byte(0x04+8*d+isebp); - emit_byte(0x40*fi+8*index+s); - if (isebp) - emit_byte(0); -} -LENDFUNC(NONE,NONE,4,raw_lea_l_rr_indexed,(W4 d, R4 s, R4 index, IMM factor)) - -LOWFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) -{ - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x89); - emit_byte(0x40+8*s+d); - emit_byte(offset); - } - else { - emit_byte(0x89); - emit_byte(0x80+8*s+d); - emit_long(offset); - } -} -LENDFUNC(NONE,WRITE,3,raw_mov_l_bRr,(R4 d, R4 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) -{ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x80+8*s+d); - emit_long(offset); -} -LENDFUNC(NONE,WRITE,3,raw_mov_w_bRr,(R4 d, R2 s, IMM offset)) - -LOWFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) -{ - if (optimize_imm8 && isbyte(offset)) { - emit_byte(0x88); - emit_byte(0x40+8*s+d); - emit_byte(offset); - } - else { - emit_byte(0x88); - emit_byte(0x80+8*s+d); - emit_long(offset); - } -} -LENDFUNC(NONE,WRITE,3,raw_mov_b_bRr,(R4 d, R1 s, IMM offset)) - -LOWFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) -{ - emit_byte(0x0f); - emit_byte(0xc8+r); -} -LENDFUNC(NONE,NONE,1,raw_bswap_32,(RW4 r)) - -LOWFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) -{ - emit_byte(0x66); - emit_byte(0xc1); - emit_byte(0xc0+r); - emit_byte(0x08); -} -LENDFUNC(WRITE,NONE,1,raw_bswap_16,(RW2 r)) - -LOWFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) -{ - emit_byte(0x89); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(NONE,NONE,2,raw_mov_l_rr,(W4 d, R4 s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) -{ - emit_byte(0x89); - emit_byte(0x05+8*s); - emit_long(d); -} -LENDFUNC(NONE,WRITE,2,raw_mov_l_mr,(IMM d, R4 s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x89); - emit_byte(0x05+8*s); - emit_long(d); -} -LENDFUNC(NONE,WRITE,2,raw_mov_w_mr,(IMM d, R2 s)) - -LOWFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0x8b); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(NONE,READ,2,raw_mov_w_rm,(W2 d, IMM s)) - -LOWFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) -{ - emit_byte(0x88); - emit_byte(0x05+8*(s&0xf)); /* XXX this handles %ah case (defined as 0x10+4) and others */ - emit_long(d); -} -LENDFUNC(NONE,WRITE,2,raw_mov_b_mr,(IMM d, R1 s)) - -LOWFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) -{ - emit_byte(0x8a); - emit_byte(0x05+8*d); - emit_long(s); -} -LENDFUNC(NONE,READ,2,raw_mov_b_rm,(W1 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) -{ - emit_byte(0xb8+d); - emit_long(s); -} -LENDFUNC(NONE,NONE,2,raw_mov_l_ri,(W4 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0xb8+d); - emit_word(s); -} -LENDFUNC(NONE,NONE,2,raw_mov_w_ri,(W2 d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) -{ - emit_byte(0xb0+d); - emit_byte(s); -} -LENDFUNC(NONE,NONE,2,raw_mov_b_ri,(W1 d, IMM s)) - -LOWFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) -{ - emit_byte(0x81); - emit_byte(0x15); - emit_long(d); - emit_long(s); -} -LENDFUNC(RMW,RMW,2,raw_adc_l_mi,(MEMRW d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) -{ - if (optimize_imm8 && isbyte(s)) { - emit_byte(0x83); - emit_byte(0x05); - emit_long(d); - emit_byte(s); - } - else { - emit_byte(0x81); - emit_byte(0x05); - emit_long(d); - emit_long(s); - } -} -LENDFUNC(WRITE,RMW,2,raw_add_l_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) -{ - emit_byte(0x66); - emit_byte(0x81); - emit_byte(0x05); - emit_long(d); - emit_word(s); -} -LENDFUNC(WRITE,RMW,2,raw_add_w_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) -{ - emit_byte(0x80); - emit_byte(0x05); - emit_long(d); - emit_byte(s); -} -LENDFUNC(WRITE,RMW,2,raw_add_b_mi,(IMM d, IMM s)) - -LOWFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0xa9); - else { - emit_byte(0xf7); - emit_byte(0xc0+d); - } - emit_long(i); -} -LENDFUNC(WRITE,NONE,2,raw_test_l_ri,(R4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) -{ - emit_byte(0x85); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_test_l_rr,(R4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x85); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_test_w_rr,(R2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) -{ - emit_byte(0x84); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) -{ - emit_byte(0x81); - emit_byte(0xf0+d); - emit_long(i); -} -LENDFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) -{ - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x25); - else { - emit_byte(0x81); - emit_byte(0xe0+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_and_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) -{ - emit_byte(0x66); - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x25); - else { - emit_byte(0x81); - emit_byte(0xe0+d); - } - emit_word(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_and_w_ri,(RW2 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) -{ - emit_byte(0x21); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_and_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x21); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_and_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) -{ - emit_byte(0x20); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_and_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) -{ - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xc8+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x0d); - else { - emit_byte(0x81); - emit_byte(0xc8+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_or_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) -{ - emit_byte(0x09); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_or_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x09); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_or_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) -{ - emit_byte(0x08); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_or_b,(RW1 d, R1 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) -{ - emit_byte(0x11); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_adc_l,(RW4 d, R4 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x11); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_adc_w,(RW2 d, R2 s)) - -LOWFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) -{ - emit_byte(0x10); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_adc_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) -{ - emit_byte(0x01); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_add_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x01); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_add_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) -{ - emit_byte(0x00); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_add_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) -{ - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xe8+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x2d); - else { - emit_byte(0x81); - emit_byte(0xe8+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_sub_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0x2c); - else { - emit_byte(0x80); - emit_byte(0xe8+d); - } - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_sub_b_ri,(RW1 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) -{ - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xc0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x05); - else { - emit_byte(0x81); - emit_byte(0xc0+d); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_add_l_ri,(RW4 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) -{ - emit_byte(0x66); - if (isbyte(i)) { - emit_byte(0x83); - emit_byte(0xc0+d); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(d)) - emit_byte(0x05); - else { - emit_byte(0x81); - emit_byte(0xc0+d); - } - emit_word(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_add_w_ri,(RW2 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0x04); - else { - emit_byte(0x80); - emit_byte(0xc0+d); - } - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_add_b_ri,(RW1 d, IMM i)) - -LOWFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) -{ - emit_byte(0x19); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_l,(RW4 d, R4 s)) - -LOWFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x19); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_w,(RW2 d, R2 s)) - -LOWFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) -{ - emit_byte(0x18); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(RMW,NONE,2,raw_sbb_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) -{ - emit_byte(0x29); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x29); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) -{ - emit_byte(0x28); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_sub_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) -{ - emit_byte(0x39); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_l,(R4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) -{ - if (optimize_imm8 && isbyte(i)) { - emit_byte(0x83); - emit_byte(0xf8+r); - emit_byte(i); - } - else { - if (optimize_accum && isaccum(r)) - emit_byte(0x3d); - else { - emit_byte(0x81); - emit_byte(0xf8+r); - } - emit_long(i); - } -} -LENDFUNC(WRITE,NONE,2,raw_cmp_l_ri,(R4 r, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x39); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_w,(R2 d, R2 s)) - -LOWFUNC(WRITE,READ,2,raw_cmp_b_mi,(MEMR d, IMM s)) -{ - emit_byte(0x80); - emit_byte(0x3d); - emit_long(d); - emit_byte(s); -} -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) -{ - if (optimize_accum && isaccum(d)) - emit_byte(0x3c); - else { - emit_byte(0x80); - emit_byte(0xf8+d); - } - emit_byte(i); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_b_ri,(R1 d, IMM i)) - -LOWFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) -{ - emit_byte(0x38); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_cmp_b,(R1 d, R1 s)) - -LOWFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) -{ - int fi; - - switch(factor) { - case 1: fi=0; break; - case 2: fi=1; break; - case 4: fi=2; break; - case 8: fi=3; break; - default: abort(); - } - emit_byte(0x39); - emit_byte(0x04+8*d); - emit_byte(5+8*index+0x40*fi); - emit_long(offset); -} -LENDFUNC(WRITE,READ,4,raw_cmp_l_rm_indexed,(R4 d, IMM offset, R4 index, IMM factor)) - -LOWFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) -{ - emit_byte(0x31); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_l,(RW4 d, R4 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) -{ - emit_byte(0x66); - emit_byte(0x31); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_w,(RW2 d, R2 s)) - -LOWFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) -{ - emit_byte(0x30); - emit_byte(0xc0+8*s+d); -} -LENDFUNC(WRITE,NONE,2,raw_xor_b,(RW1 d, R1 s)) - -LOWFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) -{ - if (optimize_imm8 && isbyte(s)) { - emit_byte(0x83); - emit_byte(0x2d); - emit_long(d); - emit_byte(s); - } - else { - emit_byte(0x81); - emit_byte(0x2d); - emit_long(d); - emit_long(s); - } -} -LENDFUNC(WRITE,RMW,2,raw_sub_l_mi,(MEMRW d, IMM s)) - -LOWFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) -{ - if (optimize_imm8 && isbyte(s)) { - emit_byte(0x83); - emit_byte(0x3d); - emit_long(d); - emit_byte(s); - } - else { - emit_byte(0x81); - emit_byte(0x3d); - emit_long(d); - emit_long(s); - } -} -LENDFUNC(WRITE,READ,2,raw_cmp_l_mi,(MEMR d, IMM s)) - -LOWFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) -{ - emit_byte(0x87); - emit_byte(0xc0+8*r1+r2); -} -LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) - -LOWFUNC(NONE,NONE,2,raw_xchg_b_rr,(RW4 r1, RW4 r2)) -{ - emit_byte(0x86); - emit_byte(0xc0+8*(r1&0xf)+(r2&0xf)); /* XXX this handles upper-halves registers (e.g. %ah defined as 0x10+4) */ -} -LENDFUNC(NONE,NONE,2,raw_xchg_l_rr,(RW4 r1, RW4 r2)) - -/************************************************************************* - * FIXME: mem access modes probably wrong * - *************************************************************************/ - -LOWFUNC(READ,WRITE,0,raw_pushfl,(void)) -{ - emit_byte(0x9c); -} -LENDFUNC(READ,WRITE,0,raw_pushfl,(void)) - -LOWFUNC(WRITE,READ,0,raw_popfl,(void)) -{ - emit_byte(0x9d); -} -LENDFUNC(WRITE,READ,0,raw_popfl,(void)) - -/* Generate floating-point instructions */ -static inline void x86_fadd_m(MEMR s) -{ - emit_byte(0xdc); - emit_byte(0x05); - emit_long(s); -} - -#endif /************************************************************************* * Unoptimizable stuff --- jump * @@ -3102,62 +1149,22 @@ static inline void x86_fadd_m(MEMR s) static inline void raw_call_r(R4 r) { -#if USE_NEW_RTASM CALLsr(r); -#else - emit_byte(0xff); - emit_byte(0xd0+r); -#endif } static inline void raw_call_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) { -#if USE_NEW_RTASM ADDR32 CALLsm(base, X86_NOREG, r, m); -#else - int mu; - switch(m) { - case 1: mu=0; break; - case 2: mu=1; break; - case 4: mu=2; break; - case 8: mu=3; break; - default: abort(); - } - emit_byte(0xff); - emit_byte(0x14); - emit_byte(0x05+8*r+0x40*mu); - emit_long(base); -#endif } static inline void raw_jmp_r(R4 r) { -#if USE_NEW_RTASM JMPsr(r); -#else - emit_byte(0xff); - emit_byte(0xe0+r); -#endif } static inline void raw_jmp_m_indexed(uae_u32 base, uae_u32 r, uae_u32 m) { -#if USE_NEW_RTASM ADDR32 JMPsm(base, X86_NOREG, r, m); -#else - int mu; - switch (m) { - case 1: mu=0; break; - case 2: mu=1; break; - case 4: mu=2; break; - case 8: mu=3; break; - default: abort(); - } - emit_byte(0xff); - emit_byte(0x24); - emit_byte(0x05+8*r+0x40*mu); - emit_long(base); -#endif } static inline void raw_jmp_m(uae_u32 base) @@ -3170,22 +1177,12 @@ static inline void raw_jmp_m(uae_u32 base) static inline void raw_call(uae_u32 t) { -#if USE_NEW_RTASM ADDR32 CALLm(t); -#else - emit_byte(0xe8); - emit_long(t-(uintptr)target-4); -#endif } static inline void raw_jmp(uae_u32 t) { -#if USE_NEW_RTASM ADDR32 JMPm(t); -#else - emit_byte(0xe9); - emit_long(t-(uintptr)target-4); -#endif } static inline void raw_jl(uae_u32 t) @@ -3385,10 +1382,12 @@ static __inline__ void raw_flags_set_zero_FLAGREG(int s, int tmp) { raw_mov_l_rr(tmp,s); raw_lahf(s); /* flags into ah */ + SETOr(X86_AL); /* V flag into al */ raw_and_l_ri(s,0xffffbfff); raw_and_l_ri(tmp,0x00004000); raw_xor_l_ri(tmp,0x00004000); raw_or_l(s,tmp); + raw_cmp_b_ri(X86_AL,-127); /* set V */ raw_sahf(s); } @@ -3509,28 +1508,18 @@ static inline void raw_flags_init_FLAGGEN(void) flag reload to avoid the partial memory stall */ static inline void raw_load_flagreg(uae_u32 target, uae_u32 r) { -#if 1 + /* attention: in 64bit mode, relies on LITTE_ENDIANESS of regflags.cznv */ raw_mov_l_rm(target,(uintptr)live.state[r].mem); -#else - raw_mov_b_rm(target,(uintptr)live.state[r].mem); - raw_mov_b_rm(target+4,((uintptr)live.state[r].mem)+1); -#endif } -#ifdef UAE -/* FLAGX is word-sized */ -#else -/* FLAGX is byte sized, and we *do* write it at that size */ -#endif static inline void raw_load_flagx(uae_u32 target, uae_u32 r) { -#ifdef UAE - if (live.nat[target].canword) -#else +#if FLAGBIT_X < 8 if (live.nat[target].canbyte) raw_mov_b_rm(target,(uintptr)live.state[r].mem); - else if (live.nat[target].canword) + else #endif + if (live.nat[target].canword) raw_mov_w_rm(target,(uintptr)live.state[r].mem); else raw_mov_l_rm(target,(uintptr)live.state[r].mem); @@ -3742,8 +1731,7 @@ cpuid(uae_u32 op, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 *edx) cpuid_count(op, 0, eax, ebx, ecx, edx); } -static void -raw_init_cpu(void) +static void raw_init_cpu(void) { struct cpuinfo_x86 *c = &cpuinfo; uae_u32 dummy; @@ -3890,7 +1878,7 @@ raw_init_cpu(void) } #ifndef UAE -static void inline prevent_redzone_use(void) {} +static void __attribute__((noinline)) prevent_redzone_use(void) {} static bool target_check_bsf(void) { @@ -4049,9 +2037,8 @@ static inline void tos_make(int r) } /* FP helper functions */ -#if USE_NEW_RTASM #define DEFINE_OP(NAME, GEN) \ -static inline void raw_##NAME(uint32 m) \ +static inline void raw_##NAME(uintptr m) \ { \ GEN(m, X86_NOREG, X86_NOREG, 1); \ } @@ -4065,35 +2052,15 @@ DEFINE_OP(fsts, FSTSm); DEFINE_OP(fstpt, FSTPTm); DEFINE_OP(fldt, FLDTm); DEFINE_OP(fistpl, FISTPLm); -#else -#define DEFINE_OP(NAME, OP1, OP2) \ -static inline void raw_##NAME(uint32 m) \ -{ \ - emit_byte(OP1); \ - emit_byte(OP2); \ - emit_long(m); \ -} -DEFINE_OP(fstl, 0xdd, 0x15); -DEFINE_OP(fstpl, 0xdd, 0x1d); -DEFINE_OP(fldl, 0xdd, 0x05); -DEFINE_OP(fildl, 0xdb, 0x05); -DEFINE_OP(fistl, 0xdb, 0x15); -DEFINE_OP(flds, 0xd9, 0x05); -DEFINE_OP(fsts, 0xd9, 0x15); -DEFINE_OP(fstpt, 0xdb, 0x3d); -DEFINE_OP(fldt, 0xdb, 0x2d); -DEFINE_OP(fistpl, 0xdb, 0x1d); -#endif #undef DEFINE_OP -LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMPTRW m, FR r)) { make_tos(r); raw_fstl(m); } -LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) -LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMPTRW m, FR r)) { make_tos(r); raw_fstpl(m); @@ -4101,30 +2068,26 @@ LOWFUNC(NONE,WRITE,2,raw_fmov_mr_drop,(MEMW m, FR r)) live.tos--; live.spos[r]=-2; } -LENDFUNC(NONE,WRITE,2,raw_fmov_mr,(MEMW m, FR r)) -LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) +LOWFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMPTRR m)) { raw_fldl(m); tos_make(r); } -LENDFUNC(NONE,READ,2,raw_fmov_rm,(FW r, MEMR m)) -LOWFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMR m)) +LOWFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMPTRR m)) { raw_fildl(m); tos_make(r); } -LENDFUNC(NONE,READ,2,raw_fmovi_rm,(FW r, MEMR m)) -LOWFUNC(NONE,WRITE,2,raw_fmovi_mr,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmovi_mr,(MEMPTRW m, FR r)) { make_tos(r); raw_fistl(m); } -LENDFUNC(NONE,WRITE,2,raw_fmovi_mr,(MEMW m, FR r)) -LOWFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) +LOWFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMPTRW m, FR r, double *bounds)) { /* Clamp value to the given range and convert to integer. */ @@ -4155,23 +2118,20 @@ LOWFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) /* Store to destination */ raw_fistpl(m); } -LENDFUNC(NONE,WRITE,3,raw_fmovi_mrb,(MEMW m, FR r, double *bounds)) -LOWFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMR m)) +LOWFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMPTRR m)) { raw_flds(m); tos_make(r); } -LENDFUNC(NONE,READ,2,raw_fmovs_rm,(FW r, MEMR m)) -LOWFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMPTRW m, FR r)) { make_tos(r); raw_fsts(m); } -LENDFUNC(NONE,WRITE,2,raw_fmovs_mr,(MEMW m, FR r)) -LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMPTRW m, FR r)) { int rs; @@ -4183,9 +2143,8 @@ LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) raw_fstpt(m); /* store and pop it */ } -LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) -LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr_drop,(MEMW m, FR r)) +LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr_drop,(MEMPTRW m, FR r)) { make_tos(r); raw_fstpt(m); /* store and pop it */ @@ -4193,14 +2152,12 @@ LOWFUNC(NONE,WRITE,2,raw_fmov_ext_mr_drop,(MEMW m, FR r)) live.tos--; live.spos[r]=-2; } -LENDFUNC(NONE,WRITE,2,raw_fmov_ext_mr,(MEMW m, FR r)) -LOWFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m)) +LOWFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMPTRR m)) { raw_fldt(m); tos_make(r); } -LENDFUNC(NONE,READ,2,raw_fmov_ext_rm,(FW r, MEMR m)) LOWFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) { @@ -4208,7 +2165,6 @@ LOWFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) emit_byte(0xeb); tos_make(r); } -LENDFUNC(NONE,NONE,1,raw_fmov_pi,(FW r)) LOWFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) { @@ -4216,7 +2172,6 @@ LOWFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) emit_byte(0xec); tos_make(r); } -LENDFUNC(NONE,NONE,1,raw_fmov_log10_2,(FW r)) LOWFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) { @@ -4224,7 +2179,6 @@ LOWFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) emit_byte(0xea); tos_make(r); } -LENDFUNC(NONE,NONE,1,raw_fmov_log2_e,(FW r)) LOWFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) { @@ -4232,7 +2186,6 @@ LOWFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) emit_byte(0xed); tos_make(r); } -LENDFUNC(NONE,NONE,1,raw_fmov_loge_2,(FW r)) LOWFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) { @@ -4240,7 +2193,6 @@ LOWFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) emit_byte(0xe8); tos_make(r); } -LENDFUNC(NONE,NONE,1,raw_fmov_1,(FW r)) LOWFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) { @@ -4248,7 +2200,6 @@ LOWFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) emit_byte(0xee); tos_make(r); } -LENDFUNC(NONE,NONE,1,raw_fmov_0,(FW r)) LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) { @@ -4268,7 +2219,6 @@ LOWFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) tos_make(d); /* store to destination, pop if necessary */ } } -LENDFUNC(NONE,NONE,2,raw_fmov_rr,(FW d, FR s)) LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) { @@ -4277,7 +2227,6 @@ LOWFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) emit_byte(0xa8 + index); emit_long(base); } -LENDFUNC(NONE,READ,2,raw_fldcw_m_indexed,(R4 index, IMM base)) LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) { @@ -4298,7 +2247,6 @@ LOWFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) emit_byte(0xfa); /* take square root */ } } -LENDFUNC(NONE,NONE,2,raw_fsqrt_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) { @@ -4319,7 +2267,6 @@ LOWFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) emit_byte(0xe1); /* take fabs */ } } -LENDFUNC(NONE,NONE,2,raw_fabs_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) { @@ -4340,7 +2287,6 @@ LOWFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) emit_byte(0xfc); /* take frndint */ } } -LENDFUNC(NONE,NONE,2,raw_frndint_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) { @@ -4361,7 +2307,6 @@ LOWFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) emit_byte(0xff); /* take cos */ } } -LENDFUNC(NONE,NONE,2,raw_fcos_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) { @@ -4382,7 +2327,6 @@ LOWFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) emit_byte(0xfe); /* fsin y=sin(x) */ } } -LENDFUNC(NONE,NONE,2,raw_fsin_rr,(FW d, FR s)) static const double one = 1; @@ -4399,19 +2343,18 @@ LOWFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) emit_byte(0xd9); emit_byte(0xfc); /* frndint int(x) */ emit_byte(0xd9); - emit_byte(0xc9); /* swap top two elements */ + emit_byte(0xc9); /* swap top two elements */ emit_byte(0xd8); - emit_byte(0xe1); /* subtract rounded from original */ + emit_byte(0xe1); /* fsub frac(x) = x - int(x) */ emit_byte(0xd9); - emit_byte(0xf0); /* f2xm1 */ - x86_fadd_m((uintptr)&one); /* Add '1' without using extra stack space */ + emit_byte(0xf0); /* f2xm1 (2^frac(x))-1 */ + x86_fadd_m((uintptr) &one); /* Add '1' without using extra stack space */ emit_byte(0xd9); - emit_byte(0xfd); /* and scale it */ + emit_byte(0xfd); /* fscale (2^frac(x))*2^int(x) */ emit_byte(0xdd); - emit_byte(0xd9); /* take he rounded value off */ - tos_make(d); /* store to destination */ + emit_byte(0xd9); /* fstp copy & pop */ + tos_make(d); /* store y=2^x */ } -LENDFUNC(NONE,NONE,2,raw_ftwotox_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) { @@ -4443,7 +2386,6 @@ LOWFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) emit_byte(0xd9); /* take he rounded value off */ tos_make(d); /* store to destination */ } -LENDFUNC(NONE,NONE,2,raw_fetox_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) { @@ -4461,7 +2403,6 @@ LOWFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) emit_byte(0xf1); /* take 1*log2(x) */ tos_make(d); /* store to destination */ } -LENDFUNC(NONE,NONE,2,raw_flog2_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) @@ -4483,7 +2424,6 @@ LOWFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) emit_byte(0xe0); /* take fchs */ } } -LENDFUNC(NONE,NONE,2,raw_fneg_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) { @@ -4506,7 +2446,6 @@ LOWFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) emit_byte(0xc0+ds); /* add source to dest*/ } } -LENDFUNC(NONE,NONE,2,raw_fadd_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) { @@ -4529,7 +2468,6 @@ LOWFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) emit_byte(0xe0+ds); /* sub src from dest */ } } -LENDFUNC(NONE,NONE,2,raw_fsub_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) { @@ -4544,7 +2482,6 @@ LOWFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) emit_byte(0xdd); emit_byte(0xe0+ds); /* cmp dest with source*/ } -LENDFUNC(NONE,NONE,2,raw_fcmp_rr,(FR d, FR s)) LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) { @@ -4567,7 +2504,6 @@ LOWFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) emit_byte(0xc8+ds); /* mul dest by source*/ } } -LENDFUNC(NONE,NONE,2,raw_fmul_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) { @@ -4590,7 +2526,6 @@ LOWFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) emit_byte(0xf0+ds); /* div dest by source*/ } } -LENDFUNC(NONE,NONE,2,raw_fdiv_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) { @@ -4608,7 +2543,6 @@ LOWFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) emit_byte(0xd9); emit_byte(0xf8); /* take rem from dest by source */ } -LENDFUNC(NONE,NONE,2,raw_frem_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) { @@ -4626,7 +2560,6 @@ LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) emit_byte(0xd9); emit_byte(0xf5); /* take rem1 from dest by source */ } -LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) @@ -4635,7 +2568,6 @@ LOWFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) emit_byte(0xd9); /* ftst */ emit_byte(0xe4); } -LENDFUNC(NONE,NONE,1,raw_ftst_r,(FR r)) LOWFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) { @@ -4669,7 +2601,6 @@ LOWFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=(e^x)-1 */ } -LENDFUNC(NONE,NONE,2,raw_fetoxM1_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) { @@ -4704,7 +2635,6 @@ LOWFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=10^x */ } -LENDFUNC(NONE,NONE,2,raw_ftentox_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) { @@ -4749,7 +2679,6 @@ LOWFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) tos_make(d); /* store sin(x) to destination */ } } -LENDFUNC(NONE,NONE,3,raw_fsincos_rr,(FW d, FW c, FR s)) LOWFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) { @@ -4770,7 +2699,6 @@ LOWFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) tos_make(d); /* store y=y*(2^x) */ } } -LENDFUNC(NONE,NONE,2,raw_fscale_rr,(FRW d, FR s)) LOWFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) { @@ -4794,7 +2722,6 @@ LOWFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) emit_byte(0xd8); /* fstp pop 1.0 */ } } -LENDFUNC(NONE,NONE,2,raw_ftan_rr,(FW d, FR s)) #ifdef CPU_x86_64 #define REX64() emit_byte(0x48) @@ -4821,7 +2748,6 @@ LOWFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) emit_byte(0xc4); emit_byte(0x04); /* add +4 to esp */ } -LENDFUNC(NONE,NONE,1,raw_fcuts_r,(FRW r)) LOWFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) { @@ -4842,7 +2768,6 @@ LOWFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) emit_byte(0xc4); emit_byte(0x08); /* add +8 to esp */ } -LENDFUNC(NONE,NONE,1,raw_fcut_r,(FRW r)) LOWFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) { @@ -4866,7 +2791,6 @@ LOWFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) emit_byte(0xd8); /* fstp just pop man */ } } -LENDFUNC(NONE,NONE,2,raw_fgetexp_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) { @@ -4890,7 +2814,6 @@ LOWFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) emit_byte(0xd9); /* fstp copy man up & pop */ } } -LENDFUNC(NONE,NONE,2,raw_fgetman_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) { @@ -4912,7 +2835,6 @@ LOWFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=logN(x) */ } -LENDFUNC(NONE,NONE,2,raw_flogN_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) { @@ -4934,7 +2856,6 @@ LOWFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=logN(x+1) */ } -LENDFUNC(NONE,NONE,2,raw_flogNP1_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) { @@ -4956,7 +2877,6 @@ LOWFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=log10(x) */ } -LENDFUNC(NONE,NONE,2,raw_flog10_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) { @@ -4981,9 +2901,8 @@ LOWFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) emit_byte(0xf3); /* fpatan atan(x/sqrt(1-(x^2))) & pop */ tos_make(d); /* store y=asin(x) */ } -LENDFUNC(NONE,NONE,2,raw_fasin_rr,(FW d, FR s)) -static uae_u32 pihalf[] = {0x2168c234, 0xc90fdaa2, 0x3fff}; // LSB=0 to get acos(1)=0 +static uae_u32 const pihalf[] = {0x2168c234, 0xc90fdaa2, 0x3fff}; // LSB=0 to get acos(1)=0 LOWFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) { @@ -5011,7 +2930,6 @@ LOWFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) emit_byte(0xe1); /* fsubrp pi/2 - asin(x) & pop */ tos_make(d); /* store y=acos(x) */ } -LENDFUNC(NONE,NONE,2,raw_facos_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) { @@ -5031,7 +2949,6 @@ LOWFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=atan(x) */ } -LENDFUNC(NONE,NONE,2,raw_fatan_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) { @@ -5066,7 +2983,6 @@ LOWFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) emit_byte(0xd9); /* fstp copy & pop */ tos_make(d); /* store y=atanh(x) */ } -LENDFUNC(NONE,NONE,2,raw_fatanh_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) { @@ -5159,7 +3075,6 @@ LOWFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=sinh(x) */ } -LENDFUNC(NONE,NONE,2,raw_fsinh_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) { @@ -5248,7 +3163,6 @@ LOWFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=cosh(x) */ } -LENDFUNC(NONE,NONE,2,raw_fcosh_rr,(FW d, FR s)) LOWFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) { @@ -5337,7 +3251,6 @@ LOWFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) if (s!=d) tos_make(d); /* store y=tanh(x) */ } -LENDFUNC(NONE,NONE,2,raw_ftanh_rr,(FW d, FR s)) /* %eax register is clobbered if target processor doesn't support fucomi */ #define FFLAG_NREG_CLOBBER_CONDITION !have_cmov diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.h b/BasiliskII/src/uae_cpu/compiler/codegen_x86.h index 6743392d..0eaef50a 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.h +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.h @@ -402,22 +402,54 @@ typedef unsigned int _ul; /* --- Memory subformats - urgh! ------------------------------------------- */ /* _r_D() is RIP addressing mode if X86_TARGET_64BIT, use _r_DSIB() instead */ -#define _r_D( R, D ) (_Mrm(_b00,_rN(R),_b101 ) ,_L((long)(D))) -#define _r_DSIB(R, D ) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(1),_b100 ,_b101 ),_L((long)(D))) +#define _r_D( R, D ) (_Mrm(_b00,_rN(R),_b101 ) ,_L((uae_u32)(D))) +#define _r_DSIB(R, D ) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(1),_b100 ,_b101 ),_L((uae_u32)(D))) #define _r_0B( R, B ) (_Mrm(_b00,_rN(R),_rA(B)) ) #define _r_0BIS(R, B,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)) ) -#define _r_1B( R, D,B ) (_Mrm(_b01,_rN(R),_rA(B)) ,_B((long)(D))) -#define _r_1BIS(R, D,B,I,S) (_Mrm(_b01,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_B((long)(D))) -#define _r_4B( R, D,B ) (_Mrm(_b10,_rN(R),_rA(B)) ,_L((long)(D))) -#define _r_4IS( R, D,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_b101 ),_L((long)(D))) -#define _r_4BIS(R, D,B,I,S) (_Mrm(_b10,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_L((long)(D))) +#define _r_1B( R, D,B ) (_Mrm(_b01,_rN(R),_rA(B)) ,_B((uae_u32)(D))) +#define _r_1BIS(R, D,B,I,S) (_Mrm(_b01,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_B((uae_u32)(D))) +#define _r_4B( R, D,B ) (_Mrm(_b10,_rN(R),_rA(B)) ,_L((uae_u32)(D))) +#define _r_4IS( R, D,I,S) (_Mrm(_b00,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_b101 ),_L((uae_u32)(D))) +#define _r_4BIS(R, D,B,I,S) (_Mrm(_b10,_rN(R),_b100 ),_SIB(_SCL(S),_rA(I),_rA(B)),_L((uae_u32)(D))) #define _r_DB( R, D,B ) ((_s0P(D) && (!_rbp13P(B)) ? _r_0B (R, B ) : (_s8P(D) ? _r_1B( R,D,B ) : _r_4B( R,D,B )))) #define _r_DBIS(R, D,B,I,S) ((_s0P(D) && (!_rbp13P(B)) ? _r_0BIS(R, B,I,S) : (_s8P(D) ? _r_1BIS(R,D,B,I,S) : _r_4BIS(R,D,B,I,S)))) /* Use RIP-addressing in 64-bit mode, if possible */ -#define _x86_RIP_addressing_possible(D,O) (X86_RIP_RELATIVE_ADDR && \ - ((uintptr)x86_get_target() + 4 + (O) - (D) <= 0xffffffff)) +#define _x86_RIP_addressing_possible(D,O) (X86_RIP_RELATIVE_ADDR && x86_RIP_addressing_possible(D, O)) + +static inline int x86_RIP_addressing_possible(uintptr addr, uintptr offset) +{ +#if X86_TARGET_64BIT + /* + * address of the next instruction. + * The opcode has already been emmitted, + * so this is the size of an 32bit displacement + + * the size of any immediate value that is part of the instruction (offset), + */ + uintptr dst = (uintptr)get_target() + 4 + offset; + intptr disp = dst - addr; + int ok = disp >= -0x80000000LL && disp <= 0x7fffffffLL; + /* fprintf(stderr, "x86_RIP_addressing_possible: %llx - %llx %16llx = %d\n", (unsigned long long)dst, (unsigned long long)addr, (long long)disp, ok); */ + return ok; +#else + UNUSED(addr); + UNUSED(offset); + return 0; +#endif +} + + +static inline int x86_DISP32_addressing_possible(uintptr addr) +{ +#if X86_TARGET_64BIT + return addr <= 0xFFFFFFFFULL; +#else + UNUSED(addr); + return 1; +#endif +} + #define _r_X( R, D,B,I,S,O) (_r0P(I) ? (_r0P(B) ? (!X86_TARGET_64BIT ? _r_D(R,D) : \ (_x86_RIP_addressing_possible(D, O) ? \ diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h index 118251c8..10a97d14 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -35,11 +35,6 @@ // #include "sysconfig.h" #include "newcpu.h" -#ifdef __x86_64__ -#define CPU_64_BIT 1 -#define CPU_x86_64 1 -#endif - #ifdef UAE #ifdef CPU_64_BIT typedef uae_u64 uintptr; @@ -135,11 +130,19 @@ union cacheline { for jump targets */ #define INDIVIDUAL_INST 0 +#ifdef WINUAE_ARANYM #define FLAG_X 0x0010 #define FLAG_N 0x0008 #define FLAG_Z 0x0004 #define FLAG_V 0x0002 #define FLAG_C 0x0001 +#else +#define FLAG_C 0x0010 +#define FLAG_V 0x0008 +#define FLAG_Z 0x0004 +#define FLAG_N 0x0002 +#define FLAG_X 0x0001 +#endif #define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V) #define FLAG_ALL (FLAG_C | FLAG_Z | FLAG_N | FLAG_V | FLAG_X) #define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V) @@ -165,27 +168,74 @@ extern void compiler_init(void); extern void compiler_exit(void); extern bool compiler_use_jit(void); #endif -extern void init_comp(void); extern void flush(int save_regs); -extern void small_flush(int save_regs); extern void set_target(uae_u8* t); extern uae_u8* get_target(void); -extern void freescratch(void); +#ifdef UAE extern void build_comp(void); +#endif extern void set_cache_state(int enabled); extern int get_cache_state(void); extern uae_u32 get_jitted_size(void); #ifdef JIT -#ifdef WINUAE_ARANYM -extern void (*flush_icache)(int n); -#else -extern void flush_icache(int n); -#endif +extern void (*flush_icache)(void); #endif extern void alloc_cache(void); extern int check_for_cache_miss(void); /* JIT FPU compilation */ +struct jit_disable_opcodes { + bool fbcc; + bool fdbcc; + bool fscc; + bool ftrapcc; + bool fsave; + bool frestore; + bool fmove; + bool fmovem; + bool fmovec; /* for move control register */ + bool fmovecr; /* for move from constant rom */ + bool fint; + bool fsinh; + bool fintrz; + bool fsqrt; + bool flognp1; + bool fetoxm1; + bool ftanh; + bool fatan; + bool fasin; + bool fatanh; + bool fsin; + bool ftan; + bool fetox; + bool ftwotox; + bool ftentox; + bool flogn; + bool flog10; + bool flog2; + bool fabs; + bool fcosh; + bool fneg; + bool facos; + bool fcos; + bool fgetexp; + bool fgetman; + bool fdiv; + bool fmod; + bool fadd; + bool fmul; + bool fsgldiv; + bool frem; + bool fscale; + bool fsglmul; + bool fsub; + bool fsincos; + bool fcmp; + bool ftst; +}; +extern struct jit_disable_opcodes jit_disable; + + extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra); extern void comp_fbcc_opp (uae_u32 opcode); extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra); @@ -320,18 +370,20 @@ extern int touchcnt; #define RW4 uae_u32 #define MEMR uae_u32 #define MEMW uae_u32 -#define MEMRW uae_u32 +#define MEMRW uae_u32 +#define MEMPTR uintptr +#define MEMPTRR MEMPTR +#define MEMPTRW MEMPTR +#define MEMPTRRW MEMPTR #define FW uae_u32 #define FR uae_u32 #define FRW uae_u32 #define MIDFUNC(nargs,func,args) void func args -#define MENDFUNC(nargs,func,args) #define COMPCALL(func) func #define LOWFUNC(flags,mem,nargs,func,args) static inline void func args -#define LENDFUNC(flags,mem,nargs,func,args) /* What we expose to the outside */ #define DECLARE_MIDFUNC(func) extern void func @@ -456,8 +508,7 @@ void do_nothing(void); #else -static inline void flush_icache(int) { } -static inline void build_comp() { } +static inline void flush_icache(void) { } #endif /* !USE_JIT */ @@ -520,7 +571,7 @@ void jit_abort(const TCHAR *format, ...); #else #ifdef WINUAE_ARANYM -#define jit_log(format, ...) write_log(format"\n", ##__VA_ARGS__) +#define jit_log(format, ...) D(bug(format, ##__VA_ARGS__)) #define jit_log2(format, ...) D2(bug(format, ##__VA_ARGS__)) void jit_abort(const char *format,...) __attribute__((format(printf, 1, 2))) __attribute__((__noreturn__)); #else diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp index cef6d43e..5d5de2cd 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp @@ -29,19 +29,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* - * UAE - The Un*x Amiga Emulator - * - * MC68881 emulation - * - * Copyright 1996 Herman ten Brugge - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - */ + * UAE - The Un*x Amiga Emulator + * + * MC68881 emulation + * + * Copyright 1996 Herman ten Brugge + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + */ #include "sysdeps.h" -# include -# include -# include +#include +#include +#include #include "memory.h" #include "readcpu.h" @@ -56,6 +56,14 @@ #define DEBUG 0 #include "debug.h" +struct jit_disable_opcodes jit_disable; + +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +#define LD(x) x ## L +#else +#define LD(x) x +#endif + // gb-- WARNING: get_fpcr() and set_fpcr() support is experimental #define HANDLE_FPCR 0 @@ -87,6 +95,7 @@ #define delay2 nop() ;nop() #define UNKNOWN_EXTRA 0xFFFFFFFF +#if 0 static void fpuop_illg(uae_u32 opcode, uae_u32 /* extra */) { /* @@ -97,623 +106,715 @@ static void fpuop_illg(uae_u32 opcode, uae_u32 /* extra */) */ op_illg(opcode); } +#endif uae_s32 temp_fp[4]; /* To convert between FP/integer */ /* return register number, or -1 for failure */ -STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra) +STATIC_INLINE int get_fp_value(uae_u32 opcode, uae_u16 extra) { - uaecptr tmppc; - uae_u16 tmp; - int size; - int mode; - int reg; - uae_u32 ad = 0; - static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; - static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; + int size; + int mode; + int reg; + uae_u32 ad = 0; + static int const sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; + static int const sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; - if ((extra & 0x4000) == 0) { - return ((extra >> 10) & 7); - } - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - switch (mode) { - case 0: - switch (size) { - case 6: - sign_extend_8_rr(S1,reg); - mov_l_mr((uintptr)temp_fp,S1); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - return FS1; - case 4: - sign_extend_16_rr(S1,reg); - mov_l_mr((uintptr)temp_fp,S1); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - return FS1; - case 0: - mov_l_mr((uintptr)temp_fp,reg); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - return FS1; - case 1: - mov_l_mr((uintptr)temp_fp,reg); - delay2; - fmovs_rm(FS1,(uintptr)temp_fp); - return FS1; - default: - return -1; + if ((extra & 0x4000) == 0) + { + return ((extra >> 10) & 7); } - return -1; /* Should be unreachable */ - case 1: - return -1; /* Genuine invalid instruction */ - default: - break; - } - /* OK, we *will* have to load something from an address. Let's make - sure we know how to handle that, or quit early --- i.e. *before* - we do any postincrement/predecrement that we may regret */ - switch (size) { - case 3: - return -1; - case 0: - case 1: - case 2: - case 4: - case 5: - case 6: - break; - default: - return -1; - } - - switch (mode) { - case 2: - ad=S1; /* We will change it, anyway ;-) */ - mov_l_rr(ad,reg+8); - break; - case 3: - ad=S1; - mov_l_rr(ad,reg+8); - lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size])); - break; - case 4: - ad=S1; - - lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size])); - mov_l_rr(ad,reg+8); - break; - case 5: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_rr(ad,reg+8); - lea_l_brr(ad,ad,off); - break; - } - case 6: - { - uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - calc_disp_ea_020(reg+8,dp,ad,S2); - break; - } - case 7: - switch (reg) { - case 0: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 1: - { - uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 2: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ - m68k_pc_offset; - uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,address+PC16off); - break; - } - case 3: - return -1; - tmppc = m68k_getpc (); - tmp = next_iword (); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ m68k_pc_offset; - ad=S1; - // Immediate addressing mode && Operation Length == Byte -> - // Use the low-order byte of the extension word. - if (size == 6) address++; - mov_l_ri(ad,address); - m68k_pc_offset+=sz2[size]; - break; - } - default: - return -1; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + switch (mode) + { + case 0: /* Dn */ + switch (size) + { + case 6: /* byte */ + sign_extend_8_rr(S1, reg); + mov_l_mr((uintptr) temp_fp, S1); + delay2; + fmovi_rm(FS1, (uintptr) temp_fp); + return FS1; + case 4: /* word */ + sign_extend_16_rr(S1, reg); + mov_l_mr((uintptr) temp_fp, S1); + delay2; + fmovi_rm(FS1, (uintptr) temp_fp); + return FS1; + case 0: /* long */ + mov_l_mr((uintptr) temp_fp, reg); + delay2; + fmovi_rm(FS1, (uintptr) temp_fp); + return FS1; + case 1: /* single precision */ + mov_l_mr((uintptr) temp_fp, reg); + delay2; + fmovs_rm(FS1, (uintptr) temp_fp); + return FS1; + default: + return -1; + } + return -1; /* Should be unreachable */ + case 1: /* An */ + return -1; /* Genuine invalid instruction */ + default: + break; } - } - switch (size) { - case 0: - readlong(ad,S2,S3); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - break; - case 1: - readlong(ad,S2,S3); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovs_rm(FS1,(uintptr)temp_fp); - break; - case 2: - readword(ad,S2,S3); - mov_w_mr(((uintptr)temp_fp)+8,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp)+4,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - delay2; - fmov_ext_rm(FS1,(uintptr)(temp_fp)); - break; - case 3: - return -1; /* Some silly "packed" stuff */ - case 4: - readword(ad,S2,S3); - sign_extend_16_rr(S2,S2); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - break; - case 5: - readlong(ad,S2,S3); - mov_l_mr(((uintptr)temp_fp)+4,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - delay2; - fmov_rm(FS1,(uintptr)(temp_fp)); - break; - case 6: - readbyte(ad,S2,S3); - sign_extend_8_rr(S2,S2); - mov_l_mr((uintptr)temp_fp,S2); - delay2; - fmovi_rm(FS1,(uintptr)temp_fp); - break; - default: - return -1; - } - return FS1; + /* OK, we *will* have to load something from an address. Let's make + sure we know how to handle that, or quit early --- i.e. *before* + we do any postincrement/predecrement that we may regret */ + switch (size) + { + case 0: /* long */ + case 1: /* single precision */ + case 2: /* extended precision */ + case 4: /* word */ + case 5: /* double precision */ + case 6: /* byte */ + break; + case 3: /* packed decimal static */ + default: + return -1; + } + + switch (mode) + { + case 2: /* (An) */ + ad = S1; /* We will change it, anyway ;-) */ + mov_l_rr(ad, reg + 8); + break; + case 3: /* (An)+ */ + ad = S1; + mov_l_rr(ad, reg + 8); + lea_l_brr(reg + 8, reg + 8, (reg == 7 ? sz2[size] : sz1[size])); + break; + case 4: /* -(An) */ + ad = S1; + lea_l_brr(reg + 8, reg + 8, -(reg == 7 ? sz2[size] : sz1[size])); + mov_l_rr(ad, reg + 8); + break; + case 5: /* d16(An) */ + { + uae_u32 off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + mov_l_rr(ad, reg + 8); + lea_l_brr(ad, ad, off); + } + break; + case 6: /* d8(An,Xn) */ + { + uae_u32 dp = comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + calc_disp_ea_020(reg + 8, dp, ad, S2); + } + break; + case 7: + switch (reg) + { + case 0: /* abs.w */ + { + uae_u32 off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + mov_l_ri(ad, off); + } + break; + case 1: /* abs.l */ + { + uae_u32 off = comp_get_ilong((m68k_pc_offset += 4) - 4); + + ad = S1; + mov_l_ri(ad, off); + } + break; + case 2: /* d16(pc) */ + { + uae_u32 address = start_pc + ((char *) comp_pc_p - (char *) start_pc_p) + m68k_pc_offset; + uae_s32 PC16off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + mov_l_ri(ad, address + PC16off); + } + break; + case 3: /* d8(pc,Xn) */ + return -1; + case 4: /* #imm */ + { + uae_u32 address = start_pc + ((char *) comp_pc_p - (char *) start_pc_p) + m68k_pc_offset; + + ad = S1; + // Immediate addressing mode && Operation Length == Byte -> + // Use the low-order byte of the extension word. + if (size == 6) + address++; + mov_l_ri(ad, address); + m68k_pc_offset += sz2[size]; + } + break; + default: + return -1; + } + } + + switch (size) + { + case 0: /* long */ + readlong(ad, S2, S3); + mov_l_mr((uintptr) temp_fp, S2); + delay2; + fmovi_rm(FS1, (uintptr) temp_fp); + break; + case 1: /* single precision */ + readlong(ad, S2, S3); + mov_l_mr((uintptr) temp_fp, S2); + delay2; + fmovs_rm(FS1, (uintptr) temp_fp); + break; + case 2: /* extended precision */ + readword(ad, S2, S3); + mov_w_mr(((uintptr) temp_fp) + 8, S2); + add_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp) + 4, S2); + add_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp), S2); + delay2; + fmov_ext_rm(FS1, (uintptr) (temp_fp)); + break; + case 3: /* packed decimal static */ + return -1; /* Some silly "packed" stuff */ + case 4: /* word */ + readword(ad, S2, S3); + sign_extend_16_rr(S2, S2); + mov_l_mr((uintptr) temp_fp, S2); + delay2; + fmovi_rm(FS1, (uintptr) temp_fp); + break; + case 5: /* double precision */ + readlong(ad, S2, S3); + mov_l_mr(((uintptr) temp_fp) + 4, S2); + add_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp), S2); + delay2; + fmov_rm(FS1, (uintptr) (temp_fp)); + break; + case 6: /* byte */ + readbyte(ad, S2, S3); + sign_extend_8_rr(S2, S2); + mov_l_mr((uintptr) temp_fp, S2); + delay2; + fmovi_rm(FS1, (uintptr) temp_fp); + break; + default: + return -1; + } + return FS1; } -/* return of -1 means failure, >=0 means OK */ -STATIC_INLINE int put_fp_value (int val, uae_u32 opcode, uae_u16 extra) -{ - uae_u16 tmp; - uaecptr tmppc; - int size; - int mode; - int reg; - uae_u32 ad; - static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; - static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; - if ((extra & 0x4000) == 0) { +/* return of -1 means failure, >=0 means OK */ +STATIC_INLINE int put_fp_value(int val, uae_u32 opcode, uae_u16 extra) +{ + int size; + int mode; + int reg; + uae_u32 ad; + static int const sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; + static int const sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; + + if ((extra & 0x4000) == 0) + { const int dest_reg = (extra >> 10) & 7; + fmov_rr(dest_reg, val); // gb-- status register is affected MAKE_FPSR(dest_reg); return 0; - } - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - ad = (uae_u32)-1; - switch (mode) { - case 0: - switch (size) { - case 6: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_b_rm(reg,(uintptr)temp_fp); - return 0; - case 4: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_w_rm(reg,(uintptr)temp_fp); - return 0; - case 0: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(reg,(uintptr)temp_fp); - return 0; - case 1: - fmovs_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(reg,(uintptr)temp_fp); - return 0; - default: - return -1; } - case 1: - return -1; /* genuine invalid instruction */ - default: break; - } - /* Let's make sure we get out *before* doing something silly if - we can't handle the size */ - switch (size) { - case 0: - case 4: - case 5: - case 6: - case 2: - case 1: - break; - case 3: - default: - return -1; - } - - switch (mode) { - case 2: - ad=S1; - mov_l_rr(ad,reg+8); - break; - case 3: - ad=S1; - mov_l_rr(ad,reg+8); - lea_l_brr(reg+8,reg+8,(reg == 7?sz2[size]:sz1[size])); - break; - case 4: - ad=S1; - lea_l_brr(reg+8,reg+8,-(reg == 7?sz2[size]:sz1[size])); - mov_l_rr(ad,reg+8); - break; - case 5: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_rr(ad,reg+8); - add_l_ri(ad,off); - break; - } - case 6: - { - uae_u32 dp=comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - calc_disp_ea_020(reg+8,dp,ad,S2); - break; - } - case 7: - switch (reg) { - case 0: - { - uae_u32 off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 1: - { - uae_u32 off=comp_get_ilong((m68k_pc_offset+=4)-4); - ad=S1; - mov_l_ri(ad,off); - break; - } - case 2: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ - m68k_pc_offset; - uae_s32 PC16off =(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - ad=S1; - mov_l_ri(ad,address+PC16off); - break; - } - case 3: - return -1; - tmppc = m68k_getpc (); - tmp = next_iword (); - ad = get_disp_ea_020 (tmppc, tmp); - break; - case 4: - { - uae_u32 address=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+ - m68k_pc_offset; - ad=S1; - mov_l_ri(ad,address); - m68k_pc_offset+=sz2[size]; - break; - } - default: - return -1; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + ad = (uae_u32) -1; + switch (mode) + { + case 0: /* Dn */ + switch (size) + { + case 6: /* byte */ + fmovi_mr((uintptr) temp_fp, val); + delay; + mov_b_rm(reg, (uintptr) temp_fp); + return 0; + case 4: /* word */ + fmovi_mr((uintptr) temp_fp, val); + delay; + mov_w_rm(reg, (uintptr) temp_fp); + return 0; + case 0: /* long */ + fmovi_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(reg, (uintptr) temp_fp); + return 0; + case 1: /* single precision */ + fmovs_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(reg, (uintptr) temp_fp); + return 0; + default: + return -1; + } + case 1: /* An */ + return -1; /* genuine invalid instruction */ + default: + break; } - } - switch (size) { - case 0: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 1: - fmovs_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 2: - fmov_ext_mr((uintptr)temp_fp,val); - delay; - mov_w_rm(S2,(uintptr)temp_fp+8); - writeword_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 3: return -1; /* Packed */ - case 4: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writeword_clobber(ad,S2,S3); - break; - case 5: - fmov_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - break; - case 6: - fmovi_mr((uintptr)temp_fp,val); - delay; - mov_l_rm(S2,(uintptr)temp_fp); - writebyte(ad,S2,S3); - break; - default: - return -1; - } - return 0; + /* Let's make sure we get out *before* doing something silly if + we can't handle the size */ + switch (size) + { + case 0: /* long */ + case 1: /* single precision */ + case 2: /* extended precision */ + case 4: /* word */ + case 5: /* double precision */ + case 6: /* byte */ + break; + case 3: /* packed decimal static */ + default: + return -1; + } + + switch (mode) + { + case 2: /* (An) */ + ad = S1; + mov_l_rr(ad, reg + 8); + break; + case 3: /* (An)+ */ + ad = S1; + mov_l_rr(ad, reg + 8); + lea_l_brr(reg + 8, reg + 8, (reg == 7 ? sz2[size] : sz1[size])); + break; + case 4: /* -(An) */ + ad = S1; + lea_l_brr(reg + 8, reg + 8, -(reg == 7 ? sz2[size] : sz1[size])); + mov_l_rr(ad, reg + 8); + break; + case 5: /* d16(An) */ + { + uae_u32 off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + mov_l_rr(ad, reg + 8); + add_l_ri(ad, off); + } + break; + case 6: /* d8(An,Xn) */ + { + uae_u32 dp = comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + calc_disp_ea_020(reg + 8, dp, ad, S2); + } + break; + case 7: + switch (reg) + { + case 0: /* abs.w */ + { + uae_u32 off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + mov_l_ri(ad, off); + } + break; + case 1: /* abs.l */ + { + uae_u32 off = comp_get_ilong((m68k_pc_offset += 4) - 4); + + ad = S1; + mov_l_ri(ad, off); + } + break; + case 2: /* d16(pc) */ + { + uae_u32 address = start_pc + ((char *) comp_pc_p - (char *) start_pc_p) + m68k_pc_offset; + uae_s32 PC16off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + + ad = S1; + mov_l_ri(ad, address + PC16off); + } + break; + case 3: /* d8(pc,Xn) */ + return -1; + case 4: /* #imm */ + { + uae_u32 address = start_pc + ((char *) comp_pc_p - (char *) start_pc_p) + m68k_pc_offset; + + ad = S1; + mov_l_ri(ad, address); + m68k_pc_offset += sz2[size]; + } + break; + default: + return -1; + } + } + + switch (size) + { + case 0: /* long */ + fmovi_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(S2, (uintptr) temp_fp); + writelong_clobber(ad, S2, S3); + break; + case 1: /* single precision */ + fmovs_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(S2, (uintptr) temp_fp); + writelong_clobber(ad, S2, S3); + break; + case 2: /* extended precision */ + fmov_ext_mr((uintptr) temp_fp, val); + delay; + mov_w_rm(S2, (uintptr) temp_fp + 8); + writeword_clobber(ad, S2, S3); + add_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp + 4); + writelong_clobber(ad, S2, S3); + add_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp); + writelong_clobber(ad, S2, S3); + break; + case 3: /* packed decimal static */ + return -1; /* Packed */ + case 4: /* word */ + fmovi_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(S2, (uintptr) temp_fp); + writeword_clobber(ad, S2, S3); + break; + case 5: /* double precision */ + fmov_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(S2, (uintptr) temp_fp + 4); + writelong_clobber(ad, S2, S3); + add_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp); + writelong_clobber(ad, S2, S3); + break; + case 6: /* byte */ + fmovi_mr((uintptr) temp_fp, val); + delay; + mov_l_rm(S2, (uintptr) temp_fp); + writebyte(ad, S2, S3); + break; + default: + return -1; + } + return 0; } + /* return -1 for failure, or register number for success */ -STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad) +STATIC_INLINE int get_fp_ad(uae_u32 opcode) { - uae_u16 tmp; - uaecptr tmppc; - int mode; - int reg; - uae_s32 off; + int mode; + int reg; + uae_s32 off; - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) { - case 0: - case 1: - return -1; - case 2: - case 3: - case 4: - mov_l_rr(S1,8+reg); - return S1; - *ad = m68k_areg (regs, reg); - break; - case 5: - off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - - mov_l_rr(S1,8+reg); - add_l_ri(S1,off); - return S1; - case 6: - return -1; - break; - case 7: - switch (reg) { - case 0: - off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - mov_l_ri(S1,off); - return S1; - case 1: - off=comp_get_ilong((m68k_pc_offset+=4)-4); - mov_l_ri(S1,off); - return S1; - case 2: - return -1; -// *ad = m68k_getpc (); -// *ad += (uae_s32) (uae_s16) next_iword (); - off=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset; - off+=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - mov_l_ri(S1,off); - return S1; - case 3: - return -1; - tmppc = m68k_getpc (); - tmp = next_iword (); - *ad = get_disp_ea_020 (tmppc, tmp); - break; - default: - return -1; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) + { + case 0: /* Dn */ + case 1: /* An */ + return -1; + case 2: /* (An) */ + case 3: /* (An)+ */ + case 4: /* -(An) */ + mov_l_rr(S1, 8 + reg); + return S1; + case 5: /* d16(An) */ + off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + mov_l_rr(S1, 8 + reg); + add_l_ri(S1, off); + return S1; + case 6: /* d8(An,Xn) */ + return -1; + break; + case 7: + switch (reg) + { + case 0: /* abs.w */ + off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + mov_l_ri(S1, off); + return S1; + case 1: /* abs.l */ + off = comp_get_ilong((m68k_pc_offset += 4) - 4); + mov_l_ri(S1, off); + return S1; + case 2: /* d16(pc) */ + off = start_pc + ((char *) comp_pc_p - (char *) start_pc_p) + m68k_pc_offset; + off += (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + mov_l_ri(S1, off); + return S1; + case 3: /* d8(pc,Xn) */ + return -1; + default: + return -1; + } } - } - abort(); + abort(); } + +/* return -1 for failure, or register number for success */ void comp_fdbcc_opp (uae_u32 /* opcode */, uae_u16 /* extra */) { + if (jit_disable.fdbcc) + { + FAIL(1); + return; + } FAIL(1); return; } -void comp_fscc_opp (uae_u32 opcode, uae_u16 extra) + +void comp_fscc_opp(uae_u32 opcode, uae_u16 extra) { - uae_u32 ad; - int cc; - int reg; + int reg; -#ifdef DEBUG_FPP - printf ("fscc_opp at %08lx\n", m68k_getpc ()); - fflush (stdout); -#endif + if (jit_disable.fscc) + { + FAIL(1); + return; + } + if (extra & 0x20) + { /* only cc from 00 to 1f are defined */ + FAIL(1); + return; + } + if ((opcode & 0x38) != 0) + { /* We can only do to integer register */ + FAIL(1); + return; + } - if (extra&0x20) { /* only cc from 00 to 1f are defined */ - FAIL(1); - return; - } - if ((opcode & 0x38) != 0) { /* We can only do to integer register */ - FAIL(1); - return; - } + fflags_into_flags(S2); + reg = (opcode & 7); - fflags_into_flags(S2); - reg=(opcode&7); - - mov_l_ri(S1,255); - mov_l_ri(S4,0); - switch(extra&0x0f) { /* according to fpp.c, the 0x10 bit is ignored - */ - case 0: break; /* set never */ - case 1: mov_l_rr(S2,S4); - cmov_l_rr(S4,S1,4); - cmov_l_rr(S4,S2,10); break; - case 2: cmov_l_rr(S4,S1,7); break; - case 3: cmov_l_rr(S4,S1,3); break; - case 4: mov_l_rr(S2,S4); - cmov_l_rr(S4,S1,2); - cmov_l_rr(S4,S2,10); break; - case 5: mov_l_rr(S2,S4); - cmov_l_rr(S4,S1,6); - cmov_l_rr(S4,S2,10); break; - case 6: cmov_l_rr(S4,S1,5); break; - case 7: cmov_l_rr(S4,S1,11); break; - case 8: cmov_l_rr(S4,S1,10); break; - case 9: cmov_l_rr(S4,S1,4); break; - case 10: cmov_l_rr(S4,S1,10); cmov_l_rr(S4,S1,7); break; - case 11: cmov_l_rr(S4,S1,4); cmov_l_rr(S4,S1,3); break; - case 12: cmov_l_rr(S4,S1,2); break; - case 13: cmov_l_rr(S4,S1,6); break; - case 14: cmov_l_rr(S4,S1,5); cmov_l_rr(S4,S1,10); break; - case 15: mov_l_rr(S4,S1); break; - } + mov_l_ri(S1, 255); + mov_l_ri(S4, 0); + switch (extra & 0x0f) + { /* according to fpp.c, the 0x10 bit is ignored + */ + case 0: + break; /* set never */ + case 1: + mov_l_rr(S2, S4); + cmov_l_rr(S4, S1, 4); + cmov_l_rr(S4, S2, 10); + break; + case 2: + cmov_l_rr(S4, S1, 7); + break; + case 3: + cmov_l_rr(S4, S1, 3); + break; + case 4: + mov_l_rr(S2, S4); + cmov_l_rr(S4, S1, 2); + cmov_l_rr(S4, S2, 10); + break; + case 5: + mov_l_rr(S2, S4); + cmov_l_rr(S4, S1, 6); + cmov_l_rr(S4, S2, 10); + break; + case 6: + cmov_l_rr(S4, S1, 5); + break; + case 7: + cmov_l_rr(S4, S1, 11); + break; + case 8: + cmov_l_rr(S4, S1, 10); + break; + case 9: + cmov_l_rr(S4, S1, 4); + break; + case 10: + cmov_l_rr(S4, S1, 10); + cmov_l_rr(S4, S1, 7); + break; + case 11: + cmov_l_rr(S4, S1, 4); + cmov_l_rr(S4, S1, 3); + break; + case 12: + cmov_l_rr(S4, S1, 2); + break; + case 13: + cmov_l_rr(S4, S1, 6); + break; + case 14: + cmov_l_rr(S4, S1, 5); + cmov_l_rr(S4, S1, 10); + break; + case 15: + mov_l_rr(S4, S1); + break; + } - if ((opcode & 0x38) == 0) { - mov_b_rr(reg,S4); - } else { - abort(); - if (get_fp_ad (opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 4); - fpuop_illg (opcode,extra); + if ((opcode & 0x38) == 0) + { + mov_b_rr(reg, S4); } else - put_byte (ad, cc ? 0xff : 0x00); - } + { + abort(); +#if 0 + int cc; + + if (get_fp_ad(opcode) < 0) + { + FAIL(1); + } else + { + put_byte(ad, cc ? 0xff : 0x00); + } +#endif + } } + void comp_ftrapcc_opp (uae_u32 /* opcode */, uaecptr /* oldpc */) { - FAIL(1); - return; -} - -void comp_fbcc_opp (uae_u32 opcode) -{ - uae_u32 start_68k_offset=m68k_pc_offset; - uae_u32 off; - uae_u32 v1; - uae_u32 v2; - int cc; - - // comp_pc_p is expected to be bound to 32-bit addresses - assert((uintptr)comp_pc_p <= 0xffffffffUL); - - if (opcode&0x20) { /* only cc from 00 to 1f are defined */ FAIL(1); return; - } - if ((opcode&0x40)==0) { - off=(uae_s32)(uae_s16)comp_get_iword((m68k_pc_offset+=2)-2); - } - else { - off=comp_get_ilong((m68k_pc_offset+=4)-4); - } - mov_l_ri(S1,(uintptr) - (comp_pc_p+off-(m68k_pc_offset-start_68k_offset))); - mov_l_ri(PC_P,(uintptr)comp_pc_p); - - /* Now they are both constant. Might as well fold in m68k_pc_offset */ - add_l_ri(S1,m68k_pc_offset); - add_l_ri(PC_P,m68k_pc_offset); - m68k_pc_offset=0; - - /* according to fpp.c, the 0x10 bit is ignored - (it handles exception handling, which we don't - do, anyway ;-) */ - cc=opcode&0x0f; - v1=get_const(PC_P); - v2=get_const(S1); - fflags_into_flags(S2); - - switch(cc) { - case 0: break; /* jump never */ - case 1: - mov_l_rr(S2,PC_P); - cmov_l_rr(PC_P,S1,4); - cmov_l_rr(PC_P,S2,10); break; - case 2: register_branch(v1,v2,7); break; - case 3: register_branch(v1,v2,3); break; - case 4: - mov_l_rr(S2,PC_P); - cmov_l_rr(PC_P,S1,2); - cmov_l_rr(PC_P,S2,10); break; - case 5: - mov_l_rr(S2,PC_P); - cmov_l_rr(PC_P,S1,6); - cmov_l_rr(PC_P,S2,10); break; - case 6: register_branch(v1,v2,5); break; - case 7: register_branch(v1,v2,11); break; - case 8: register_branch(v1,v2,10); break; - case 9: register_branch(v1,v2,4); break; - case 10: - cmov_l_rr(PC_P,S1,10); - cmov_l_rr(PC_P,S1,7); break; - case 11: - cmov_l_rr(PC_P,S1,4); - cmov_l_rr(PC_P,S1,3); break; - case 12: register_branch(v1,v2,2); break; - case 13: register_branch(v1,v2,6); break; - case 14: - cmov_l_rr(PC_P,S1,5); - cmov_l_rr(PC_P,S1,10); break; - case 15: mov_l_rr(PC_P,S1); break; - } } + +void comp_fbcc_opp(uae_u32 opcode) +{ + uae_u32 start_68k_offset = m68k_pc_offset; + uae_u32 off; + uae_u32 v1; + uae_u32 v2; + int cc; + + // comp_pc_p is expected to be bound to 32-bit addresses + assert((uintptr) comp_pc_p <= 0xffffffffUL); + + if (jit_disable.fbcc) + { + FAIL(1); + return; + } + if (opcode & 0x20) + { /* only cc from 00 to 1f are defined */ + FAIL(1); + return; + } + if ((opcode & 0x40) == 0) + { + off = (uae_s32) (uae_s16) comp_get_iword((m68k_pc_offset += 2) - 2); + } else + { + off = comp_get_ilong((m68k_pc_offset += 4) - 4); + } + mov_l_ri(S1, (uintptr) (comp_pc_p + off - (m68k_pc_offset - start_68k_offset))); + mov_l_ri(PC_P, (uintptr) comp_pc_p); + + /* Now they are both constant. Might as well fold in m68k_pc_offset */ + add_l_ri(S1, m68k_pc_offset); + add_l_ri(PC_P, m68k_pc_offset); + m68k_pc_offset = 0; + + /* according to fpp.c, the 0x10 bit is ignored + (it handles exception handling, which we don't + do, anyway ;-) */ + cc = opcode & 0x0f; + v1 = get_const(PC_P); + v2 = get_const(S1); + fflags_into_flags(S2); + + switch (cc) + { + case 0: + break; /* jump never */ + case 1: + mov_l_rr(S2, PC_P); + cmov_l_rr(PC_P, S1, 4); + cmov_l_rr(PC_P, S2, 10); + break; + case 2: + register_branch(v1, v2, 7); + break; + case 3: + register_branch(v1, v2, 3); + break; + case 4: + mov_l_rr(S2, PC_P); + cmov_l_rr(PC_P, S1, 2); + cmov_l_rr(PC_P, S2, 10); + break; + case 5: + mov_l_rr(S2, PC_P); + cmov_l_rr(PC_P, S1, 6); + cmov_l_rr(PC_P, S2, 10); + break; + case 6: + register_branch(v1, v2, 5); + break; + case 7: + register_branch(v1, v2, 11); + break; + case 8: + register_branch(v1, v2, 10); + break; + case 9: + register_branch(v1, v2, 4); + break; + case 10: + cmov_l_rr(PC_P, S1, 10); + cmov_l_rr(PC_P, S1, 7); + break; + case 11: + cmov_l_rr(PC_P, S1, 4); + cmov_l_rr(PC_P, S1, 3); + break; + case 12: + register_branch(v1, v2, 2); + break; + case 13: + register_branch(v1, v2, 6); + break; + case 14: + cmov_l_rr(PC_P, S1, 5); + cmov_l_rr(PC_P, S1, 10); + break; + case 15: + mov_l_rr(PC_P, S1); + break; + } +} + + /* Floating point conditions The "NotANumber" part could be problematic; Howver, when NaN is encountered, the ftst instruction sets bot N and Z to 1 on the x87, @@ -784,150 +885,179 @@ x86 conditions 0001 : 10 1110 : 11 */ -void comp_fsave_opp (uae_u32 opcode) + +void comp_fsave_opp(uae_u32 opcode) { - uae_u32 ad; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; - int i; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int i; + int ad; - FAIL(1); - return; - -#ifdef DEBUG_FPP - printf ("fsave_opp at %08lx\n", m68k_getpc ()); - fflush (stdout); -#endif - if (get_fp_ad (opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 2); - fpuop_illg (opcode,UNKNOWN_EXTRA); + if (jit_disable.fsave) + { + FAIL(1); + return; + } + FAIL(1); return; - } - if (CPUType == 4) { - /* 4 byte 68040 IDLE frame. */ - if (incr < 0) { - ad -= 4; - put_long (ad, 0x41000000); - } else { - put_long (ad, 0x41000000); - ad += 4; + if ((ad = get_fp_ad(opcode)) < 0) + { + FAIL(1); + return; } - } else { - if (incr < 0) { - ad -= 4; - put_long (ad, 0x70000000); - for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); - } - ad -= 4; - put_long (ad, 0x1f180000); - } else { - put_long (ad, 0x1f180000); - ad += 4; - for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); - ad += 4; - } - put_long (ad, 0x70000000); - ad += 4; + + if (CPUType == 4) + { + /* 4 byte 68040 IDLE frame. */ + if (incr < 0) + { + ad -= 4; + put_long(ad, 0x41000000); + } else + { + put_long(ad, 0x41000000); + ad += 4; + } + } else + { + if (incr < 0) + { + ad -= 4; + put_long(ad, 0x70000000); + for (i = 0; i < 5; i++) + { + ad -= 4; + put_long(ad, 0x00000000); + } + ad -= 4; + put_long(ad, 0x1f180000); + } else + { + put_long(ad, 0x1f180000); + ad += 4; + for (i = 0; i < 5; i++) + { + put_long(ad, 0x00000000); + ad += 4; + } + put_long(ad, 0x70000000); + ad += 4; + } } - } - if ((opcode & 0x38) == 0x18) - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) - m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x18) + m68k_areg(regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) + m68k_areg(regs, opcode & 7) = ad; } -void comp_frestore_opp (uae_u32 opcode) + +void comp_frestore_opp(uae_u32 opcode) { - uae_u32 ad; - uae_u32 d; - int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + uae_u32 d; + int incr = (opcode & 0x38) == 0x20 ? -1 : 1; + int ad; - FAIL(1); - return; - -#ifdef DEBUG_FPP - printf ("frestore_opp at %08lx\n", m68k_getpc ()); - fflush (stdout); -#endif - if (get_fp_ad (opcode, &ad) == 0) { - m68k_setpc (m68k_getpc () - 2); - fpuop_illg (opcode,UNKNOWN_EXTRA); + if (jit_disable.frestore) + { + FAIL(1); + return; + } + FAIL(1); return; - } - if (CPUType == 4) { - /* 68040 */ - if (incr < 0) { - /* @@@ This may be wrong. */ - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { /* Not a NULL frame? */ - if ((d & 0x00ff0000) == 0) { /* IDLE */ - } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */ - ad -= 44; - } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */ - ad -= 92; - } - } - } else { - d = get_long (ad); - ad += 4; - if ((d & 0xff000000) != 0) { /* Not a NULL frame? */ - if ((d & 0x00ff0000) == 0) { /* IDLE */ - } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */ - ad += 44; - } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */ - ad += 92; - } - } + + if ((ad = get_fp_ad(opcode)) < 0) + { + FAIL(1); + return; } - } else { - if (incr < 0) { - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad -= 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad -= 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad -= 45 * 4; - } - } else { - d = get_long (ad); - ad += 4; - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad += 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad += 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad += 45 * 4; - } + if (CPUType == 4) + { + /* 68040 */ + if (incr < 0) + { + /* @@@ This may be wrong. */ + ad -= 4; + d = get_long(ad); + if ((d & 0xff000000) != 0) + { /* Not a NULL frame? */ + if ((d & 0x00ff0000) == 0) + { /* IDLE */ + } else if ((d & 0x00ff0000) == 0x00300000) + { /* UNIMP */ + ad -= 44; + } else if ((d & 0x00ff0000) == 0x00600000) + { /* BUSY */ + ad -= 92; + } + } + } else + { + d = get_long(ad); + ad += 4; + if ((d & 0xff000000) != 0) + { /* Not a NULL frame? */ + if ((d & 0x00ff0000) == 0) + { /* IDLE */ + } else if ((d & 0x00ff0000) == 0x00300000) + { /* UNIMP */ + ad += 44; + } else if ((d & 0x00ff0000) == 0x00600000) + { /* BUSY */ + ad += 92; + } + } + } + } else + { + if (incr < 0) + { + ad -= 4; + d = get_long(ad); + if ((d & 0xff000000) != 0) + { + if ((d & 0x00ff0000) == 0x00180000) + ad -= 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad -= 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad -= 45 * 4; + } + } else + { + d = get_long(ad); + ad += 4; + if ((d & 0xff000000) != 0) + { + if ((d & 0x00ff0000) == 0x00180000) + ad += 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad += 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad += 45 * 4; + } + } } - } - if ((opcode & 0x38) == 0x18) - m68k_areg (regs, opcode & 7) = ad; - if ((opcode & 0x38) == 0x20) - m68k_areg (regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x18) + m68k_areg(regs, opcode & 7) = ad; + if ((opcode & 0x38) == 0x20) + m68k_areg(regs, opcode & 7) = ad; } -#if USE_LONG_DOUBLE -static const fpu_register const_e = 2.7182818284590452353602874713526625L; -static const fpu_register const_log10_e = 0.4342944819032518276511289189166051L; -static const fpu_register const_loge_10 = 2.3025850929940456840179914546843642L; + +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +static const fpu_register const_e = LD(2.7182818284590452353); // LD(2.7182818284590452353602874713526625); +static const fpu_register const_log10_e = LD(0.4342944819032518276511289189166051); +static const fpu_register const_loge_10 = LD(2.3025850929940456840179914546843642); #else -static const fpu_register const_e = 2.7182818284590452354; +static const fpu_register const_e = 2.7182818284590452354; static const fpu_register const_log10_e = 0.43429448190325182765; static const fpu_register const_loge_10 = 2.30258509299404568402; #endif static const fpu_register power10[] = { - 1e0, 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, 1e64, 1e128, 1e256 -#if USE_LONG_DOUBLE -, 1e512L, 1e1024L, 1e2048L, 1e4096L + LD(1e0), LD(1e1), LD(1e2), LD(1e4), LD(1e8), LD(1e16), LD(1e32), LD(1e64), LD(1e128), LD(1e256) +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +, LD(1e512), LD(1e1024), LD(1e2048), LD(1e4096) #endif }; @@ -958,277 +1088,346 @@ static uae_u16 x86_fpucw[]={ #endif -void comp_fpp_opp (uae_u32 opcode, uae_u16 extra) +void comp_fpp_opp(uae_u32 opcode, uae_u16 extra) { - int reg; - int src; - - switch ((extra >> 13) & 0x7) { - case 3: /* 2nd most common */ - if (put_fp_value ((extra >> 7)&7 , opcode, extra) < 0) { - FAIL(1); - return; + int reg; + int src; - } - return; - case 6: - case 7: + switch ((extra >> 13) & 0x7) { - uae_u32 ad, list = 0; - int incr = 0; - if (extra & 0x2000) { + case 1: /* illegal */ + break; - /* FMOVEM FPP->memory */ - switch ((extra >> 11) & 3) { /* Get out early if failure */ - case 0: - case 2: - break; - case 1: - case 3: - default: - FAIL(1); return; - } - ad=get_fp_ad (opcode, &ad); - if ((uae_s32)ad<0) { - m68k_setpc (m68k_getpc () - 4); - fpuop_illg (opcode,extra); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 1: /* dynamic pred */ - case 3: /* dynamic postinc */ - abort(); - } - if (incr < 0) { /* Predecrement */ - for (reg = 7; reg >= 0; reg--) { - if (list & 0x80) { - fmov_ext_mr((uintptr)temp_fp,reg); - delay; - sub_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - sub_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - sub_l_ri(ad,4); - mov_w_rm(S2,(uintptr)temp_fp+8); - writeword_clobber(ad,S2,S3); - } - list <<= 1; - } - } - else { /* Postincrement */ - for (reg = 0; reg < 8; reg++) { - if (list & 0x80) { - fmov_ext_mr((uintptr)temp_fp,reg); - delay; - mov_w_rm(S2,(uintptr)temp_fp+8); - writeword_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp+4); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - mov_l_rm(S2,(uintptr)temp_fp); - writelong_clobber(ad,S2,S3); - add_l_ri(ad,4); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) - mov_l_rr((opcode & 7)+8,ad); - if ((opcode & 0x38) == 0x20) - mov_l_rr((opcode & 7)+8,ad); - } else { - /* FMOVEM memory->FPP */ - - uae_u32 ad; - switch ((extra >> 11) & 3) { /* Get out early if failure */ - case 0: - case 2: - break; - case 1: - case 3: - default: - FAIL(1); return; - } - ad=get_fp_ad (opcode, &ad); - if ((uae_s32)ad<0) { - m68k_setpc (m68k_getpc () - 4); - D(bug("no ad\n")); - fpuop_illg (opcode,extra); - return; - } - switch ((extra >> 11) & 3) { - case 0: /* static pred */ - list = extra & 0xff; - incr = -1; - break; - case 2: /* static postinc */ - list = extra & 0xff; - incr = 1; - break; - case 1: /* dynamic pred */ - case 3: /* dynamic postinc */ - abort(); - } - - if (incr < 0) { - // not reached - for (reg = 7; reg >= 0; reg--) { - if (list & 0x80) { - sub_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - sub_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp)+4,S2); - sub_l_ri(ad,4); - readword(ad,S2,S3); - mov_w_mr(((uintptr)temp_fp)+8,S2); - delay2; - fmov_ext_rm(reg,(uintptr)(temp_fp)); - } - list <<= 1; - } - } - else { - for (reg = 0; reg < 8; reg++) { - if (list & 0x80) { - readword(ad,S2,S3); - mov_w_mr(((uintptr)temp_fp)+8,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp)+4,S2); - add_l_ri(ad,4); - readlong(ad,S2,S3); - mov_l_mr((uintptr)(temp_fp),S2); - add_l_ri(ad,4); - delay2; - fmov_ext_rm(reg,(uintptr)(temp_fp)); - } - list <<= 1; - } - } - if ((opcode & 0x38) == 0x18) - mov_l_rr((opcode & 7)+8,ad); - if ((opcode & 0x38) == 0x20) - mov_l_rr((opcode & 7)+8,ad); - } - } - return; - - case 4: - case 5: /* rare */ - if ((opcode & 0x30) == 0) { - if (extra & 0x2000) { - if (extra & 0x1000) { -#if HANDLE_FPCR - mov_l_rm(opcode & 15, (uintptr)&fpu.fpcr.rounding_mode); - or_l_rm(opcode & 15, (uintptr)&fpu.fpcr.rounding_precision); -#else + case 3: /* FMOVE Fpn, */ + /* 2nd most common */ + if (jit_disable.fmove) + { FAIL(1); return; -#endif } - if (extra & 0x0800) { - FAIL(1); - return; - } - if (extra & 0x0400) { - mov_l_rm(opcode & 15,(uintptr)&fpu.instruction_address); - return; - } - } else { - // gb-- moved here so that we may FAIL() without generating any code - if (extra & 0x0800) { - // set_fpsr(m68k_dreg (regs, opcode & 15)); - FAIL(1); - return; - } - if (extra & 0x1000) { -#if HANDLE_FPCR -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) + + if (put_fp_value((extra >> 7) & 7, opcode, extra) < 0) + { FAIL(1); return; -#endif - mov_l_rr(S1,opcode & 15); - mov_l_rr(S2,opcode & 15); - and_l_ri(S1,FPCR_ROUNDING_PRECISION); - and_l_ri(S2,FPCR_ROUNDING_MODE); - mov_l_mr((uintptr)&fpu.fpcr.rounding_precision,S1); - mov_l_mr((uintptr)&fpu.fpcr.rounding_mode,S2); -#else - FAIL(1); - return; -#endif -// return; gb-- FMOVEM could also operate on fpiar - } - if (extra & 0x0400) { - mov_l_mr((uintptr)&fpu.instruction_address,opcode & 15); -// return; gb-- we have to process all FMOVEM bits before returning } return; - } - } else if ((opcode & 0x3f) == 0x3c) { - if ((extra & 0x2000) == 0) { - // gb-- moved here so that we may FAIL() without generating any code - if (extra & 0x0800) { - FAIL(1); - return; - } - if (extra & 0x1000) { - comp_get_ilong((m68k_pc_offset+=4)-4); -#if HANDLE_FPCR -#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) + + case 6: /* FMOVEM , */ + case 7: /* FMOVEM , */ + if (jit_disable.fmovem) + { FAIL(1); return; -#endif -// mov_l_mi((uintptr)®s.fpcr,val); - mov_l_ri(S1,val); - mov_l_ri(S2,val); - and_l_ri(S1,FPCR_ROUNDING_PRECISION); - and_l_ri(S2,FPCR_ROUNDING_MODE); - mov_l_mr((uintptr)&fpu.fpcr.rounding_precision,S1); - mov_l_mr((uintptr)&fpu.fpcr.rounding_mode,S2); -#else - FAIL(1); - return; -#endif -// return; gb-- FMOVEM could also operate on fpiar } - if (extra & 0x0400) { - uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4); - mov_l_mi((uintptr)&fpu.instruction_address,val); -// return; gb-- we have to process all FMOVEM bits before returning + + { + int ad; + uae_u32 list = 0; + int incr = 0; + + if (extra & 0x2000) + { + /* FMOVEM FPP->memory */ + switch ((extra >> 11) & 3) + { /* Get out early if failure */ + case 0: /* static pred */ + case 2: /* static postinc */ + break; + case 1: /* dynamic pred */ + case 3: /* dynamic postinc */ + default: + FAIL(1); + return; + } + if ((ad = get_fp_ad(opcode)) < 0) + { + FAIL(1); + return; + } + switch ((extra >> 11) & 3) + { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 1: /* dynamic pred */ + case 3: /* dynamic postinc */ + abort(); + } + if (incr < 0) + { /* Predecrement */ + for (reg = 7; reg >= 0; reg--) + { + if (list & 0x80) + { + fmov_ext_mr((uintptr) temp_fp, reg); + delay; + sub_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp); + writelong_clobber(ad, S2, S3); + sub_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp + 4); + writelong_clobber(ad, S2, S3); + sub_l_ri(ad, 4); + mov_w_rm(S2, (uintptr) temp_fp + 8); + writeword_clobber(ad, S2, S3); + } + list <<= 1; + } + } else + { /* Postincrement */ + for (reg = 0; reg < 8; reg++) + { + if (list & 0x80) + { + fmov_ext_mr((uintptr) temp_fp, reg); + delay; + mov_w_rm(S2, (uintptr) temp_fp + 8); + writeword_clobber(ad, S2, S3); + add_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp + 4); + writelong_clobber(ad, S2, S3); + add_l_ri(ad, 4); + mov_l_rm(S2, (uintptr) temp_fp); + writelong_clobber(ad, S2, S3); + add_l_ri(ad, 4); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) + mov_l_rr((opcode & 7) + 8, ad); + if ((opcode & 0x38) == 0x20) + mov_l_rr((opcode & 7) + 8, ad); + } else + { + /* FMOVEM memory->FPP */ + + int ad; + + switch ((extra >> 11) & 3) + { /* Get out early if failure */ + case 0: /* static pred */ + case 2: /* static postinc */ + break; + case 1: /* dynamic pred */ + case 3: /* dynamic postinc */ + default: + FAIL(1); + return; + } + ad = get_fp_ad(opcode); + if (ad < 0) + { + D(bug("no ad\n")); + FAIL(1); + return; + } + switch ((extra >> 11) & 3) + { + case 0: /* static pred */ + list = extra & 0xff; + incr = -1; + break; + case 2: /* static postinc */ + list = extra & 0xff; + incr = 1; + break; + case 1: /* dynamic pred */ + case 3: /* dynamic postinc */ + abort(); + } + + if (incr < 0) + { + // not reached + for (reg = 7; reg >= 0; reg--) + { + if (list & 0x80) + { + sub_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp), S2); + sub_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp) + 4, S2); + sub_l_ri(ad, 4); + readword(ad, S2, S3); + mov_w_mr(((uintptr) temp_fp) + 8, S2); + delay2; + fmov_ext_rm(reg, (uintptr) (temp_fp)); + } + list <<= 1; + } + } else + { + for (reg = 0; reg < 8; reg++) + { + if (list & 0x80) + { + readword(ad, S2, S3); + mov_w_mr(((uintptr) temp_fp) + 8, S2); + add_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp) + 4, S2); + add_l_ri(ad, 4); + readlong(ad, S2, S3); + mov_l_mr((uintptr) (temp_fp), S2); + add_l_ri(ad, 4); + delay2; + fmov_ext_rm(reg, (uintptr) (temp_fp)); + } + list <<= 1; + } + } + if ((opcode & 0x38) == 0x18) + mov_l_rr((opcode & 7) + 8, ad); + if ((opcode & 0x38) == 0x20) + mov_l_rr((opcode & 7) + 8, ad); + } } return; - } - FAIL(1); - return; - } else if (extra & 0x2000) { - FAIL(1); - return; - } else { - FAIL(1); - return; - } - FAIL(1); - return; + + case 4: /* FMOVEM , */ + case 5: /* FMOVEM , */ + if (jit_disable.fmovec) + { + FAIL(1); + return; + } + + /* rare */ + if ((opcode & 0x30) == 0) + { + /* = Dn or An */ + if (extra & 0x2000) + { + if (extra & 0x1000) + { +#if HANDLE_FPCR + mov_l_rm(opcode & 15, (uintptr) & fpu.fpcr.rounding_mode); + or_l_rm(opcode & 15, (uintptr) & fpu.fpcr.rounding_precision); +#else + FAIL(1); + return; +#endif + } + if (extra & 0x0800) + { + FAIL(1); + return; + } + if (extra & 0x0400) + { + /* FPIAR: fixme; we cannot correctly return the address from compiled code */ + mov_l_rm(opcode & 15, (uintptr) & fpu.instruction_address); + return; + } + } else + { + // gb-- moved here so that we may FAIL() without generating any code + if (extra & 0x0800) + { + // set_fpsr(m68k_dreg (regs, opcode & 15)); + FAIL(1); + return; + } + if (extra & 0x1000) + { +#if HANDLE_FPCR +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) + FAIL(1); + return; +#endif + mov_l_rr(S1, opcode & 15); + mov_l_rr(S2, opcode & 15); + and_l_ri(S1, FPCR_ROUNDING_PRECISION); + and_l_ri(S2, FPCR_ROUNDING_MODE); + mov_l_mr((uintptr) & fpu.fpcr.rounding_precision, S1); + mov_l_mr((uintptr) & fpu.fpcr.rounding_mode, S2); +#else + FAIL(1); + return; +#endif + } + if (extra & 0x0400) + { + /* FPIAR: does that make sense at all? */ + mov_l_mr((uintptr) & fpu.instruction_address, opcode & 15); + } + return; + } + } else if ((opcode & 0x3f) == 0x3c) + { + /* = #imm */ + if ((extra & 0x2000) == 0) + { + // gb-- moved here so that we may FAIL() without generating any code + if (extra & 0x0800) + { + FAIL(1); + return; + } + if (extra & 0x1000) + { + comp_get_ilong((m68k_pc_offset += 4) - 4); +#if HANDLE_FPCR +#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION) + FAIL(1); + return; +#endif + // mov_l_mi((uintptr)®s.fpcr,val); + mov_l_ri(S1, val); + mov_l_ri(S2, val); + and_l_ri(S1, FPCR_ROUNDING_PRECISION); + and_l_ri(S2, FPCR_ROUNDING_MODE); + mov_l_mr((uintptr) & fpu.fpcr.rounding_precision, S1); + mov_l_mr((uintptr) & fpu.fpcr.rounding_mode, S2); +#else + FAIL(1); + return; +#endif + } + if (extra & 0x0400) + { + uae_u32 val = comp_get_ilong((m68k_pc_offset += 4) - 4); + + mov_l_mi((uintptr) & fpu.instruction_address, val); + } + return; + } + FAIL(1); + return; + } else if (extra & 0x2000) + { + FAIL(1); + return; + } else + { + FAIL(1); + return; + } + FAIL(1); + return; case 0: - case 2: /* Extremely common */ + case 2: /* Extremely common */ reg = (extra >> 7) & 7; - if ((extra & 0xfc00) == 0x5c00) { - switch (extra & 0x7f) { + if ((extra & 0xfc00) == 0x5c00) + { + if (jit_disable.fmovecr) + { + FAIL(1); + return; + } + + switch (extra & 0x7f) + { case 0x00: fmov_pi(reg); break; @@ -1236,20 +1435,20 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra) fmov_log10_2(reg); break; case 0x0c: -#if USE_LONG_DOUBLE - fmov_ext_rm(reg,(uintptr)&const_e); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fmov_ext_rm(reg, (uintptr) & const_e); #else - fmov_rm(reg,(uintptr)&const_e); + fmov_rm(reg, (uintptr) & const_e); #endif break; case 0x0d: fmov_log2_e(reg); break; case 0x0e: -#if USE_LONG_DOUBLE - fmov_ext_rm(reg,(uintptr)&const_log10_e); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fmov_ext_rm(reg, (uintptr) & const_log10_e); #else - fmov_rm(reg,(uintptr)&const_log10_e); + fmov_rm(reg, (uintptr) & const_log10_e); #endif break; case 0x0f: @@ -1259,10 +1458,10 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra) fmov_loge_2(reg); break; case 0x31: -#if USE_LONG_DOUBLE - fmov_ext_rm(reg,(uintptr)&const_loge_10); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fmov_ext_rm(reg, (uintptr) & const_loge_10); #else - fmov_rm(reg,(uintptr)&const_loge_10); + fmov_rm(reg, (uintptr) & const_loge_10); #endif break; case 0x32: @@ -1277,14 +1476,14 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra) case 0x39: case 0x3a: case 0x3b: -#if USE_LONG_DOUBLE +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) case 0x3c: case 0x3d: case 0x3e: case 0x3f: - fmov_ext_rm(reg,(uintptr)(power10+(extra & 0x7f)-0x32)); + fmov_ext_rm(reg, (uintptr) (power10 + (extra & 0x7f) - 0x32)); #else - fmov_rm(reg,(uintptr)(power10+(extra & 0x7f)-0x32)); + fmov_rm(reg, (uintptr) (power10 + (extra & 0x7f) - 0x32)); #endif break; default: @@ -1294,310 +1493,536 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra) } return; } - - switch (extra & 0x7f) { - case 0x00: /* FMOVE */ - case 0x40: /* Explicit rounding. This is just a quick fix. Same - * for all other cases that have three choices */ - case 0x44: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + + switch (extra & 0x7f) + { + case 0x00: /* FMOVE */ + case 0x40: /* FSMOVE: Explicit rounding. This is just a quick fix. Same + * for all other cases that have three choices */ + case 0x44: /* FDMOVE */ + if (jit_disable.fmove) + { + FAIL(1); return; } - fmov_rr(reg,src); - MAKE_FPSR (src); + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fmov_rr(reg, src); + MAKE_FPSR(src); break; - case 0x01: /* FINT */ - FAIL(1); + case 0x01: /* FINT */ + if (jit_disable.fint) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x02: /* FSINH */ - FAIL(1); + case 0x02: /* FSINH */ + if (jit_disable.fsinh) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x03: /* FINTRZ */ -#ifdef USE_X86_FPUCW + case 0x03: /* FINTRZ */ + if (jit_disable.fintrz) + { + FAIL(1); + return; + } +#ifdef USE_X86_FPUCW /* If we have control over the CW, we can do this */ dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ return; } - mov_l_ri(S1,16); /* Switch to "round to zero" mode */ - fldcw_m_indexed(S1,(uae_u32)x86_fpucw); - - frndint_rr(reg,src); + mov_l_ri(S1, 16); /* Switch to "round to zero" mode */ + fldcw_m_indexed(S1, (uintptr) x86_fpucw); + + frndint_rr(reg, src); /* restore control word */ - mov_l_rm(S1,(uintptr)®s.fpcr); - and_l_ri(S1,0x000000f0); - fldcw_m_indexed(S1,(uintptr)x86_fpucw); + mov_l_rm(S1, (uintptr) & regs.fpcr); + and_l_ri(S1, 0x000000f0); + fldcw_m_indexed(S1, (uintptr) x86_fpucw); - MAKE_FPSR (reg); + MAKE_FPSR(reg); break; -#endif - FAIL(1); +#endif + FAIL(1); return; break; - case 0x04: /* FSQRT */ - case 0x41: - case 0x45: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x04: /* FSQRT */ + case 0x41: /* FSSQRT */ + case 0x45: /* FDSQRT */ + if (jit_disable.fsqrt) + { + FAIL(1); return; } - fsqrt_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x06: /* FLOGNP1 */ - FAIL(1); - return; + dont_care_fflags(); - break; - case 0x08: /* FETOXM1 */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x09: /* FTANH */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0a: /* FATAN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0c: /* FASIN */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0d: /* FATANH */ - FAIL(1); - return; - dont_care_fflags(); - break; - case 0x0e: /* FSIN */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ return; } - fsin_rr(reg,src); - MAKE_FPSR (reg); + fsqrt_rr(reg, src); + MAKE_FPSR(reg); break; - case 0x0f: /* FTAN */ - FAIL(1); + case 0x06: /* FLOGNP1 */ + if (jit_disable.flognp1) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x10: /* FETOX */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x08: /* FETOXM1 */ + if (jit_disable.fetoxm1) + { + FAIL(1); return; } - fetox_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x11: /* FTWOTOX */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - ftwotox_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x12: /* FTENTOX */ - FAIL(1); + + FAIL(1); return; dont_care_fflags(); break; - case 0x14: /* FLOGN */ - FAIL(1); + case 0x09: /* FTANH */ + if (jit_disable.ftanh) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x15: /* FLOG10 */ - FAIL(1); + case 0x0a: /* FATAN */ + if (jit_disable.fatan) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x16: /* FLOG2 */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x0c: /* FASIN */ + if (jit_disable.fasin) + { + FAIL(1); return; } - flog2_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x18: /* FABS */ - case 0x58: - case 0x5c: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ - return; - } - fabs_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x19: /* FCOSH */ - FAIL(1); + + FAIL(1); return; dont_care_fflags(); break; - case 0x1a: /* FNEG */ - case 0x5a: - case 0x5e: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x0d: /* FATANH */ + if (jit_disable.fatanh) + { + FAIL(1); return; } - fneg_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x1c: /* FACOS */ - FAIL(1); + + FAIL(1); return; dont_care_fflags(); break; - case 0x1d: /* FCOS */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x0e: /* FSIN */ + if (jit_disable.fsin) + { + FAIL(1); return; } - fcos_rr(reg,src); - MAKE_FPSR (reg); + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fsin_rr(reg, src); + MAKE_FPSR(reg); break; - case 0x1e: /* FGETEXP */ - FAIL(1); + case 0x0f: /* FTAN */ + if (jit_disable.ftan) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x1f: /* FGETMAN */ - FAIL(1); + case 0x10: /* FETOX */ + if (jit_disable.fetox) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fetox_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x11: /* FTWOTOX */ + if (jit_disable.ftwotox) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + ftwotox_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x12: /* FTENTOX */ + if (jit_disable.ftentox) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x20: /* FDIV */ - case 0x60: - case 0x64: - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x14: /* FLOGN */ + if (jit_disable.flogn) + { + FAIL(1); return; } - fdiv_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x21: /* FMOD */ + + FAIL(1); + return; dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + break; + case 0x15: /* FLOG10 */ + if (jit_disable.flog10) + { + FAIL(1); return; } - frem_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x22: /* FADD */ - case 0x62: - case 0x66: + + FAIL(1); + return; dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + break; + case 0x16: /* FLOG2 */ + if (jit_disable.flog2) + { + FAIL(1); return; } - fadd_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x23: /* FMUL */ - case 0x63: - case 0x67: + dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ return; } - fmul_rr(reg,src); - MAKE_FPSR (reg); + flog2_rr(reg, src); + MAKE_FPSR(reg); break; - case 0x24: /* FSGLDIV */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x18: /* FABS */ + case 0x58: /* FSABS */ + case 0x5c: /* FDABS */ + if (jit_disable.fabs) + { + FAIL(1); return; } - fdiv_rr(reg,src); - MAKE_FPSR (reg); + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fabs_rr(reg, src); + MAKE_FPSR(reg); break; - case 0x25: /* FREM */ + case 0x19: /* FCOSH */ + if (jit_disable.fcosh) + { + FAIL(1); + return; + } + + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x1a: /* FNEG */ + case 0x5a: /* FSNEG */ + case 0x5e: /* FDNEG */ + if (jit_disable.fneg) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fneg_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x1c: /* FACOS */ + if (jit_disable.facos) + { + FAIL(1); + return; + } + + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x1d: /* FCOS */ + if (jit_disable.fcos) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fcos_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x1e: /* FGETEXP */ + if (jit_disable.fgetexp) + { + FAIL(1); + return; + } + + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x1f: /* FGETMAN */ + if (jit_disable.fgetman) + { + FAIL(1); + return; + } + + FAIL(1); + return; + dont_care_fflags(); + break; + case 0x20: /* FDIV */ + case 0x60: /* FSDIV */ + case 0x64: /* FDDIV */ + if (jit_disable.fdiv) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fdiv_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x21: /* FMOD */ + if (jit_disable.fmod) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + frem_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x22: /* FADD */ + case 0x62: /* FSADD */ + case 0x66: /* FDADD */ + if (jit_disable.fadd) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fadd_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x23: /* FMUL */ + case 0x63: /* FSMUL */ + case 0x67: /* FDMUL */ + if (jit_disable.fmul) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fmul_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x24: /* FSGLDIV */ + if (jit_disable.fsgldiv) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fdiv_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x25: /* FREM */ + if (jit_disable.frem) + { + FAIL(1); + return; + } // gb-- disabled because the quotient byte must be computed // otherwise, free rotation in ClarisWorks doesn't work. FAIL(1); return; dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ return; } - frem1_rr(reg,src); - MAKE_FPSR (reg); + frem1_rr(reg, src); + MAKE_FPSR(reg); break; - case 0x26: /* FSCALE */ - dont_care_fflags(); - FAIL(1); + case 0x26: /* FSCALE */ + if (jit_disable.fscale) + { + FAIL(1); + return; + } + + FAIL(1); return; break; - case 0x27: /* FSGLMUL */ - dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x27: /* FSGLMUL */ + if (jit_disable.fsglmul) + { + FAIL(1); return; } - fmul_rr(reg,src); - MAKE_FPSR (reg); - break; - case 0x28: /* FSUB */ - case 0x68: - case 0x6c: + dont_care_fflags(); - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ return; } - fsub_rr(reg,src); - MAKE_FPSR (reg); + fmul_rr(reg, src); + MAKE_FPSR(reg); break; - case 0x30: /* FSINCOS */ + case 0x28: /* FSUB */ + case 0x68: /* FSSUB */ + case 0x6c: /* FDSUB */ + if (jit_disable.fsub) + { + FAIL(1); + return; + } + + dont_care_fflags(); + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fsub_rr(reg, src); + MAKE_FPSR(reg); + break; + case 0x30: /* FSINCOS */ case 0x31: case 0x32: case 0x33: @@ -1605,34 +2030,53 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra) case 0x35: case 0x36: case 0x37: - FAIL(1); + if (jit_disable.fsincos) + { + FAIL(1); + return; + } + + FAIL(1); return; dont_care_fflags(); break; - case 0x38: /* FCMP */ - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x38: /* FCMP */ + if (jit_disable.fcmp) + { + FAIL(1); return; } - fmov_rr(FP_RESULT,reg); - fsub_rr(FP_RESULT,src); /* Right way? */ + + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fmov_rr(FP_RESULT, reg); + fsub_rr(FP_RESULT, src); /* Right way? */ break; - case 0x3a: /* FTST */ - src=get_fp_value (opcode, extra); - if (src < 0) { - FAIL(1); /* Illegal instruction */ + case 0x3a: /* FTST */ + if (jit_disable.ftst) + { + FAIL(1); return; } - fmov_rr(FP_RESULT,src); + + src = get_fp_value(opcode, extra); + if (src < 0) + { + FAIL(1); /* Illegal instruction */ + return; + } + fmov_rr(FP_RESULT, src); break; default: - FAIL(1); + FAIL(1); return; break; } return; - } - m68k_setpc (m68k_getpc () - 4); - fpuop_illg (opcode,extra); + } + FAIL(1); } diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp index 6c1ede09..4fa745b4 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp @@ -61,13 +61,11 @@ MIDFUNC(0,live_flags,(void)) live.flags_in_flags=VALID; live.flags_are_important=1; } -MENDFUNC(0,live_flags,(void)) MIDFUNC(0,dont_care_flags,(void)) { live.flags_are_important=0; } -MENDFUNC(0,dont_care_flags,(void)) MIDFUNC(0,duplicate_carry,(void)) { @@ -76,7 +74,6 @@ MIDFUNC(0,duplicate_carry,(void)) COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem,NATIVE_CC_CS); log_vwrite(FLAGX); } -MENDFUNC(0,duplicate_carry,(void)) MIDFUNC(0,restore_carry,(void)) { @@ -100,25 +97,21 @@ MIDFUNC(0,restore_carry,(void)) } #endif } -MENDFUNC(0,restore_carry,(void)) MIDFUNC(0,start_needflags,(void)) { needflags=1; } -MENDFUNC(0,start_needflags,(void)) MIDFUNC(0,end_needflags,(void)) { needflags=0; } -MENDFUNC(0,end_needflags,(void)) MIDFUNC(0,make_flags_live,(void)) { make_flags_live_internal(); } -MENDFUNC(0,make_flags_live,(void)) MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ { @@ -130,7 +123,6 @@ MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ raw_bt_l_ri(r,i); unlock2(r); } -MENDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ { @@ -141,7 +133,6 @@ MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ unlock2(r); unlock2(b); } -MENDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) { @@ -152,7 +143,6 @@ MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) unlock2(r); unlock2(b); } -MENDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) { @@ -163,7 +153,6 @@ MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) unlock2(r); unlock2(b); } -MENDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) { @@ -174,7 +163,6 @@ MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) unlock2(r); unlock2(b); } -MENDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) { @@ -183,7 +171,6 @@ MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) raw_mov_l_rm(d,s); unlock2(d); } -MENDFUNC(2,mov_l_rm,(W4 d, IMM s)) MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) { @@ -194,28 +181,24 @@ MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) unlock2(index); unlock2(d); } -MENDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) MIDFUNC(2,mov_l_mi,(IMM d, IMM s)) { CLOBBER_MOV; raw_mov_l_mi(d,s); } -MENDFUNC(2,mov_l_mi,(IMM d, IMM s)) MIDFUNC(2,mov_w_mi,(IMM d, IMM s)) { CLOBBER_MOV; raw_mov_w_mi(d,s); } -MENDFUNC(2,mov_w_mi,(IMM d, IMM s)) MIDFUNC(2,mov_b_mi,(IMM d, IMM s)) { CLOBBER_MOV; raw_mov_b_mi(d,s); } -MENDFUNC(2,mov_b_mi,(IMM d, IMM s)) MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) { @@ -226,7 +209,6 @@ MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) raw_rol_b_ri(r,i); unlock2(r); } -MENDFUNC(2,rol_b_ri,(RW1 r, IMM i)) MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) { @@ -237,7 +219,6 @@ MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) raw_rol_w_ri(r,i); unlock2(r); } -MENDFUNC(2,rol_w_ri,(RW2 r, IMM i)) MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) { @@ -248,7 +229,6 @@ MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) raw_rol_l_ri(r,i); unlock2(r); } -MENDFUNC(2,rol_l_ri,(RW4 r, IMM i)) MIDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) { @@ -263,7 +243,6 @@ MIDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -279,7 +258,6 @@ MIDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -295,7 +273,6 @@ MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) { @@ -310,7 +287,6 @@ MIDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -326,7 +302,6 @@ MIDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -342,7 +317,6 @@ MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) { @@ -353,7 +327,6 @@ MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) raw_ror_b_ri(r,i); unlock2(r); } -MENDFUNC(2,ror_b_ri,(RR1 r, IMM i)) MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) { @@ -364,7 +337,6 @@ MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) raw_ror_w_ri(r,i); unlock2(r); } -MENDFUNC(2,ror_w_ri,(RR2 r, IMM i)) MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) { @@ -375,7 +347,6 @@ MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) raw_ror_l_ri(r,i); unlock2(r); } -MENDFUNC(2,ror_l_ri,(RR4 r, IMM i)) MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) { @@ -390,7 +361,6 @@ MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) { @@ -405,7 +375,6 @@ MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) { @@ -421,7 +390,6 @@ MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) MIDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) { @@ -436,7 +404,6 @@ MIDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -452,7 +419,6 @@ MIDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -469,7 +435,6 @@ MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) { @@ -484,7 +449,6 @@ MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) raw_shll_l_ri(r,i); unlock2(r); } -MENDFUNC(2,shll_l_ri,(RW4 r, IMM i)) MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) { @@ -495,7 +459,6 @@ MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) raw_shll_w_ri(r,i); unlock2(r); } -MENDFUNC(2,shll_w_ri,(RW2 r, IMM i)) MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) { @@ -506,7 +469,6 @@ MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) raw_shll_b_ri(r,i); unlock2(r); } -MENDFUNC(2,shll_b_ri,(RW1 r, IMM i)) MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) { @@ -521,7 +483,6 @@ MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) raw_shrl_l_ri(r,i); unlock2(r); } -MENDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) { @@ -532,7 +493,6 @@ MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) raw_shrl_w_ri(r,i); unlock2(r); } -MENDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) { @@ -543,7 +503,6 @@ MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) raw_shrl_b_ri(r,i); unlock2(r); } -MENDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) { @@ -554,7 +513,6 @@ MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) raw_shra_l_ri(r,i); unlock2(r); } -MENDFUNC(2,shra_l_ri,(RW4 r, IMM i)) MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) { @@ -565,7 +523,6 @@ MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) raw_shra_w_ri(r,i); unlock2(r); } -MENDFUNC(2,shra_w_ri,(RW2 r, IMM i)) MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) { @@ -576,7 +533,6 @@ MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) raw_shra_b_ri(r,i); unlock2(r); } -MENDFUNC(2,shra_b_ri,(RW1 r, IMM i)) MIDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) { @@ -591,7 +547,6 @@ MIDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -607,7 +562,6 @@ MIDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ @@ -624,7 +578,6 @@ MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,setcc,(W1 d, IMM cc)) { @@ -633,14 +586,12 @@ MIDFUNC(2,setcc,(W1 d, IMM cc)) raw_setcc(d,cc); unlock2(d); } -MENDFUNC(2,setcc,(W1 d, IMM cc)) MIDFUNC(2,setcc_m,(IMM d, IMM cc)) { CLOBBER_SETCC; raw_setcc_m(d,cc); } -MENDFUNC(2,setcc_m,(IMM d, IMM cc)) MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) { @@ -653,7 +604,6 @@ MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) unlock2(s); unlock2(d); } -MENDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) MIDFUNC(2,bsf_l_rr,(W4 d, W4 s)) { @@ -664,7 +614,6 @@ MIDFUNC(2,bsf_l_rr,(W4 d, W4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,bsf_l_rr,(W4 d, W4 s)) /* Set the Z flag depending on the value in s. Note that the value has to be 0 or -1 (or, more precisely, for non-zero @@ -678,7 +627,6 @@ MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) unlock2(tmp); unlock2(s); } -MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) { @@ -689,7 +637,6 @@ MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,imul_32_32,(RW4 d, RR4 s)) MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) { @@ -700,7 +647,6 @@ MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,imul_64_32,(RW4 d, RW4 s)) MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) { @@ -711,7 +657,6 @@ MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,mul_64_32,(RW4 d, RW4 s)) MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) { @@ -741,7 +686,6 @@ MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) unlock2(s); } } -MENDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) { @@ -773,7 +717,6 @@ MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) unlock2(s); } } -MENDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) { @@ -803,7 +746,6 @@ MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) unlock2(s); } } -MENDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) { @@ -834,7 +776,6 @@ MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) unlock2(s); } } -MENDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) { @@ -852,7 +793,6 @@ MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,mov_b_rr,(W1 d, RR1 s)) MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) { @@ -870,7 +810,6 @@ MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,mov_w_rr,(W2 d, RR2 s)) /* read the long at the address contained in s+offset and store in d */ MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) @@ -887,7 +826,6 @@ MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) @@ -904,7 +842,6 @@ MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) /* read the long at the address contained in s+offset and store in d */ MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) @@ -923,7 +860,6 @@ MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) @@ -943,7 +879,6 @@ MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) @@ -963,7 +898,6 @@ MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) { @@ -979,7 +913,6 @@ MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) raw_mov_l_Ri(d,i,offset); unlock2(d); } -MENDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) { @@ -995,7 +928,6 @@ MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) raw_mov_w_Ri(d,i,offset); unlock2(d); } -MENDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) /* Warning! OFFSET is byte sized only! */ MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) @@ -1017,7 +949,6 @@ MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) { @@ -1037,7 +968,6 @@ MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) { @@ -1058,7 +988,6 @@ MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) { @@ -1076,7 +1005,6 @@ MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) unlock2(index); unlock2(s); } -MENDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) { @@ -1090,7 +1018,6 @@ MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) unlock2(index); unlock2(s); } -MENDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) /* write d to the long at the address contained in s+offset */ MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) @@ -1110,7 +1037,6 @@ MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) /* write the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) @@ -1130,7 +1056,6 @@ MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) { @@ -1148,7 +1073,6 @@ MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) MIDFUNC(1,mid_bswap_32,(RW4 r)) { @@ -1164,7 +1088,6 @@ MIDFUNC(1,mid_bswap_32,(RW4 r)) raw_bswap_32(r); unlock2(r); } -MENDFUNC(1,mid_bswap_32,(RW4 r)) MIDFUNC(1,mid_bswap_16,(RW2 r)) { @@ -1181,7 +1104,6 @@ MIDFUNC(1,mid_bswap_16,(RW2 r)) raw_bswap_16(r); unlock2(r); } -MENDFUNC(1,mid_bswap_16,(RW2 r)) MIDFUNC(2,mov_l_rr,(W4 d, RR4 s)) { @@ -1210,7 +1132,6 @@ MIDFUNC(2,mov_l_rr,(W4 d, RR4 s)) D2(panicbug("Added %d to nreg %d(%d), now holds %d regs", d,s,live.state[d].realind,live.nat[s].nholds)); unlock2(s); } -MENDFUNC(2,mov_l_rr,(W4 d, RR4 s)) MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) { @@ -1224,7 +1145,6 @@ MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) raw_mov_l_mr(d,s); unlock2(s); } -MENDFUNC(2,mov_l_mr,(IMM d, RR4 s)) MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) { @@ -1238,7 +1158,6 @@ MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) raw_mov_w_mr(d,s); unlock2(s); } -MENDFUNC(2,mov_w_mr,(IMM d, RR2 s)) MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) { @@ -1248,7 +1167,6 @@ MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) raw_mov_w_rm(d,s); unlock2(d); } -MENDFUNC(2,mov_w_rm,(W2 d, IMM s)) MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) { @@ -1263,7 +1181,6 @@ MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) raw_mov_b_mr(d,s); unlock2(s); } -MENDFUNC(2,mov_b_mr,(IMM d, RR1 s)) MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) { @@ -1273,14 +1190,12 @@ MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) raw_mov_b_rm(d,s); unlock2(d); } -MENDFUNC(2,mov_b_rm,(W1 d, IMM s)) MIDFUNC(2,mov_l_ri,(W4 d, IMM s)) { set_const(d,s); return; } -MENDFUNC(2,mov_l_ri,(W4 d, IMM s)) MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) { @@ -1290,7 +1205,6 @@ MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) raw_mov_w_ri(d,s); unlock2(d); } -MENDFUNC(2,mov_w_ri,(W2 d, IMM s)) MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) { @@ -1300,7 +1214,6 @@ MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) raw_mov_b_ri(d,s); unlock2(d); } -MENDFUNC(2,mov_b_ri,(W1 d, IMM s)) MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) { @@ -1310,7 +1223,6 @@ MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) raw_test_l_ri(d,i); unlock2(d); } -MENDFUNC(2,test_l_ri,(RR4 d, IMM i)) MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) { @@ -1322,7 +1234,6 @@ MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,test_l_rr,(RR4 d, RR4 s)) MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) { @@ -1334,7 +1245,6 @@ MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,test_w_rr,(RR2 d, RR2 s)) MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) { @@ -1346,7 +1256,6 @@ MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,test_b_rr,(RR1 d, RR1 s)) MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) { @@ -1361,7 +1270,6 @@ MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) raw_and_l_ri(d,i); unlock2(d); } -MENDFUNC(2,and_l_ri,(RW4 d, IMM i)) MIDFUNC(2,and_l,(RW4 d, RR4 s)) { @@ -1373,7 +1281,6 @@ MIDFUNC(2,and_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,and_l,(RW4 d, RR4 s)) MIDFUNC(2,and_w,(RW2 d, RR2 s)) { @@ -1385,7 +1292,6 @@ MIDFUNC(2,and_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,and_w,(RW2 d, RR2 s)) MIDFUNC(2,and_b,(RW1 d, RR1 s)) { @@ -1397,7 +1303,6 @@ MIDFUNC(2,and_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,and_b,(RW1 d, RR1 s)) MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) { @@ -1411,7 +1316,6 @@ MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) raw_or_l_ri(d,i); unlock2(d); } -MENDFUNC(2,or_l_ri,(RW4 d, IMM i)) MIDFUNC(2,or_l,(RW4 d, RR4 s)) { @@ -1427,7 +1331,6 @@ MIDFUNC(2,or_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,or_l,(RW4 d, RR4 s)) MIDFUNC(2,or_w,(RW2 d, RR2 s)) { @@ -1439,7 +1342,6 @@ MIDFUNC(2,or_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,or_w,(RW2 d, RR2 s)) MIDFUNC(2,or_b,(RW1 d, RR1 s)) { @@ -1451,7 +1353,6 @@ MIDFUNC(2,or_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,or_b,(RW1 d, RR1 s)) MIDFUNC(2,adc_l,(RW4 d, RR4 s)) { @@ -1464,7 +1365,6 @@ MIDFUNC(2,adc_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,adc_l,(RW4 d, RR4 s)) MIDFUNC(2,adc_w,(RW2 d, RR2 s)) { @@ -1476,7 +1376,6 @@ MIDFUNC(2,adc_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,adc_w,(RW2 d, RR2 s)) MIDFUNC(2,adc_b,(RW1 d, RR1 s)) { @@ -1488,7 +1387,6 @@ MIDFUNC(2,adc_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,adc_b,(RW1 d, RR1 s)) MIDFUNC(2,add_l,(RW4 d, RR4 s)) { @@ -1506,7 +1404,6 @@ MIDFUNC(2,add_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,add_l,(RW4 d, RR4 s)) MIDFUNC(2,add_w,(RW2 d, RR2 s)) { @@ -1523,7 +1420,6 @@ MIDFUNC(2,add_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,add_w,(RW2 d, RR2 s)) MIDFUNC(2,add_b,(RW1 d, RR1 s)) { @@ -1540,7 +1436,6 @@ MIDFUNC(2,add_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,add_b,(RW1 d, RR1 s)) MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) { @@ -1563,7 +1458,6 @@ MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) raw_sub_l_ri(d,i); unlock2(d); } -MENDFUNC(2,sub_l_ri,(RW4 d, IMM i)) MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) { @@ -1576,7 +1470,6 @@ MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) raw_sub_w_ri(d,i); unlock2(d); } -MENDFUNC(2,sub_w_ri,(RW2 d, IMM i)) MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) { @@ -1590,7 +1483,6 @@ MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) unlock2(d); } -MENDFUNC(2,sub_b_ri,(RW1 d, IMM i)) MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) { @@ -1611,7 +1503,6 @@ MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) raw_add_l_ri(d,i); unlock2(d); } -MENDFUNC(2,add_l_ri,(RW4 d, IMM i)) MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) { @@ -1624,7 +1515,6 @@ MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) raw_add_w_ri(d,i); unlock2(d); } -MENDFUNC(2,add_w_ri,(RW2 d, IMM i)) MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) { @@ -1638,7 +1528,6 @@ MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) unlock2(d); } -MENDFUNC(2,add_b_ri,(RW1 d, IMM i)) MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) { @@ -1650,7 +1539,6 @@ MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sbb_l,(RW4 d, RR4 s)) MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) { @@ -1662,7 +1550,6 @@ MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sbb_w,(RW2 d, RR2 s)) MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) { @@ -1674,7 +1561,6 @@ MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sbb_b,(RW1 d, RR1 s)) MIDFUNC(2,sub_l,(RW4 d, RR4 s)) { @@ -1691,7 +1577,6 @@ MIDFUNC(2,sub_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sub_l,(RW4 d, RR4 s)) MIDFUNC(2,sub_w,(RW2 d, RR2 s)) { @@ -1708,7 +1593,6 @@ MIDFUNC(2,sub_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sub_w,(RW2 d, RR2 s)) MIDFUNC(2,sub_b,(RW1 d, RR1 s)) { @@ -1725,7 +1609,6 @@ MIDFUNC(2,sub_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sub_b,(RW1 d, RR1 s)) MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) { @@ -1737,7 +1620,6 @@ MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,cmp_l,(RR4 d, RR4 s)) MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) { @@ -1749,7 +1631,6 @@ MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,cmp_w,(RR2 d, RR2 s)) MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) { @@ -1761,7 +1642,6 @@ MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,cmp_b,(RR1 d, RR1 s)) MIDFUNC(2,xor_l,(RW4 d, RR4 s)) { @@ -1773,7 +1653,6 @@ MIDFUNC(2,xor_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,xor_l,(RW4 d, RR4 s)) MIDFUNC(2,xor_w,(RW2 d, RR2 s)) { @@ -1785,7 +1664,6 @@ MIDFUNC(2,xor_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,xor_w,(RW2 d, RR2 s)) MIDFUNC(2,xor_b,(RW1 d, RR1 s)) { @@ -1797,7 +1675,6 @@ MIDFUNC(2,xor_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,xor_b,(RW1 d, RR1 s)) MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) { @@ -1812,7 +1689,6 @@ MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) prepare_for_call_2(); compemu_raw_call_r(r); } -MENDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) { @@ -1849,13 +1725,11 @@ MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) live.state[out1].dirtysize=osize; set_status(out1,DIRTY); } -MENDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) MIDFUNC(0,nop,(void)) { raw_emit_nop(); } -MENDFUNC(0,nop,(void)) /* forget_about() takes a mid-layer register */ MIDFUNC(1,forget_about,(W4 r)) @@ -1865,7 +1739,6 @@ MIDFUNC(1,forget_about,(W4 r)) live.state[r].val=0; set_status(r,UNDEF); } -MENDFUNC(1,forget_about,(W4 r)) MIDFUNC(1,f_forget_about,(FW r)) { @@ -1873,7 +1746,6 @@ MIDFUNC(1,f_forget_about,(FW r)) f_disassociate(r); live.fate[r].status=UNDEF; } -MENDFUNC(1,f_forget_about,(FW r)) // ARM optimized functions @@ -1892,7 +1764,6 @@ MIDFUNC(2,arm_ADD_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_ADD_l,(RW4 d, RR4 s)) MIDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) { @@ -1911,7 +1782,6 @@ MIDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) raw_ADD_l_rr(d,REG_WORK1); unlock2(d); } -MENDFUNC(2,arm_ADD_l_ri,(RW4 d, IMM i)) MIDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) { @@ -1929,7 +1799,6 @@ MIDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) raw_ADD_l_rri(d,d,i); unlock2(d); } -MENDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) MIDFUNC(2,arm_SUB_l_ri8,(RW4 d, IMM i)) { @@ -1947,7 +1816,6 @@ MIDFUNC(2,arm_SUB_l_ri8,(RW4 d, IMM i)) raw_SUB_l_rri(d,d,i); unlock2(d); } -MENDFUNC(2,arm_ADD_l_ri8,(RW4 d, IMM i)) MIDFUNC(2,arm_AND_l,(RW4 d, RR4 s)) { @@ -1958,7 +1826,6 @@ MIDFUNC(2,arm_AND_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_AND_l,(RW4 d, RR4 s)) MIDFUNC(2,arm_AND_w,(RW2 d, RR2 s)) { @@ -1969,7 +1836,6 @@ MIDFUNC(2,arm_AND_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_AND_w,(RW2 d, RR2 s)) MIDFUNC(2,arm_AND_b,(RW1 d, RR1 s)) { @@ -1980,7 +1846,6 @@ MIDFUNC(2,arm_AND_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_AND_b,(RW1 d, RR1 s)) MIDFUNC(2,arm_AND_l_ri8,(RW4 d, IMM i)) { @@ -1994,7 +1859,6 @@ MIDFUNC(2,arm_AND_l_ri8,(RW4 d, IMM i)) raw_AND_l_ri(d,i); unlock2(d); } -MENDFUNC(2,arm_AND_l_ri8,(RW4 d, IMM i)) MIDFUNC(2,arm_EOR_b,(RW1 d, RR1 s)) { @@ -2005,7 +1869,6 @@ MIDFUNC(2,arm_EOR_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_EOR_b,(RW1 d, RR1 s)) MIDFUNC(2,arm_EOR_l,(RW4 d, RR4 s)) { @@ -2016,7 +1879,6 @@ MIDFUNC(2,arm_EOR_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_EOR_l,(RW4 d, RR4 s)) MIDFUNC(2,arm_EOR_w,(RW2 d, RR2 s)) { @@ -2027,7 +1889,6 @@ MIDFUNC(2,arm_EOR_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_EOR_w,(RW2 d, RR2 s)) MIDFUNC(2,arm_ORR_b,(RW1 d, RR1 s)) { @@ -2038,7 +1899,6 @@ MIDFUNC(2,arm_ORR_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_ORR_b,(RW1 d, RR1 s)) MIDFUNC(2,arm_ORR_l,(RW4 d, RR4 s)) { @@ -2053,7 +1913,6 @@ MIDFUNC(2,arm_ORR_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_ORR_l,(RW4 d, RR4 s)) MIDFUNC(2,arm_ORR_w,(RW2 d, RR2 s)) { @@ -2064,7 +1923,6 @@ MIDFUNC(2,arm_ORR_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,arm_ORR_w,(RW2 d, RR2 s)) MIDFUNC(2,arm_ROR_l_ri8,(RW4 r, IMM i)) { @@ -2075,7 +1933,6 @@ MIDFUNC(2,arm_ROR_l_ri8,(RW4 r, IMM i)) raw_ROR_l_ri(r,i); unlock2(r); } -MENDFUNC(2,arm_ROR_l_ri8,(RW4 r, IMM i)) // Other static inline void flush_cpu_icache(void *start, void *stop) diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h index 52541326..baedb153 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h @@ -64,6 +64,7 @@ DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i)); DECLARE_MIDFUNC(rol_l_rr(RW4 d, RR1 r)); DECLARE_MIDFUNC(rol_w_rr(RW2 d, RR1 r)); DECLARE_MIDFUNC(rol_b_rr(RW1 d, RR1 r)); +DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i)); DECLARE_MIDFUNC(shll_l_rr(RW4 d, RR1 r)); DECLARE_MIDFUNC(shll_w_rr(RW2 d, RR1 r)); DECLARE_MIDFUNC(shll_b_rr(RW1 d, RR1 r)); @@ -98,6 +99,7 @@ DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, RR2 s)); DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, RR1 s)); DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, RR2 s)); DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, RR1 s)); +DECLARE_MIDFUNC(simulate_bsf(W4 tmp, RW4 s)); DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s)); DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s)); DECLARE_MIDFUNC(imul_32_32(RW4 d, RR4 s)); diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp index 9da2c058..5f55d1bf 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp @@ -129,7 +129,6 @@ MIDFUNC(0,restore_inverted_carry,(void)) MSR_CPSRf_r(REG_WORK1); unlock2(r); } -MENDFUNC(0,restore_inverted_carry,(void)) /* * ADD @@ -161,7 +160,6 @@ MIDFUNC(3,jnf_ADD_imm,(W4 d, RR4 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ADD_imm,(W4 d, RR4 s, IMM v)) MIDFUNC(3,jnf_ADD,(W4 d, RR4 s, RR4 v)) { @@ -180,7 +178,6 @@ MIDFUNC(3,jnf_ADD,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jnf_ADD,(W4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_ADD_b_imm,(W4 d, RR1 s, IMM v)) { @@ -194,7 +191,6 @@ MIDFUNC(3,jff_ADD_b_imm,(W4 d, RR1 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ADD_b_imm,(W4 d, RR1 s, IMM v)) MIDFUNC(3,jff_ADD_b,(W4 d, RR1 s, RR1 v)) { @@ -215,7 +211,6 @@ MIDFUNC(3,jff_ADD_b,(W4 d, RR1 s, RR1 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_ADD_b,(W4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) { @@ -229,7 +224,6 @@ MIDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ADD_w_imm,(W4 d, RR2 s, IMM v)) MIDFUNC(3,jff_ADD_w,(W4 d, RR2 s, RR2 v)) { @@ -249,7 +243,6 @@ MIDFUNC(3,jff_ADD_w,(W4 d, RR2 s, RR2 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_ADD_w,(W4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) { @@ -262,7 +255,6 @@ MIDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ADD_l_imm,(W4 d, RR4 s, IMM v)) MIDFUNC(3,jff_ADD_l,(W4 d, RR4 s, RR4 v)) { @@ -281,7 +273,6 @@ MIDFUNC(3,jff_ADD_l,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_ADD_l,(W4 d, RR4 s, RR4 v)) /* * ADDA @@ -303,7 +294,6 @@ MIDFUNC(2,jnf_ADDA_b,(W4 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ADDA_b,(W4 d, RR1 s)) MIDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) { @@ -316,7 +306,6 @@ MIDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ADDA_w,(W4 d, RR2 s)) MIDFUNC(2,jnf_ADDA_l,(W4 d, RR4 s)) { @@ -328,7 +317,6 @@ MIDFUNC(2,jnf_ADDA_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ADDA_l,(W4 d, RR4 s)) /* * ADDX @@ -358,7 +346,6 @@ MIDFUNC(3,jnf_ADDX,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jnf_ADDX,(W4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) { @@ -383,7 +370,6 @@ MIDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_ADDX_b,(W4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) { @@ -408,7 +394,6 @@ MIDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_ADDX_w,(W4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) { @@ -431,7 +416,6 @@ MIDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_ADDX_l,(W4 d, RR4 s, RR4 v)) /* * ANDI @@ -458,7 +442,6 @@ MIDFUNC(1,jff_ANDSR,(IMM s, IMM x)) STRB_rR(REG_WORK2, REG_WORK1); } } -MENDFUNC(1,jff_ANDSR,(IMM s)) /* * AND @@ -493,7 +476,6 @@ MIDFUNC(3,jnf_AND,(W4 d, RR4 s, RR4 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_AND,(RW4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_AND_b,(W4 d, RR1 s, RR1 v)) { @@ -510,7 +492,6 @@ MIDFUNC(3,jff_AND_b,(W4 d, RR1 s, RR1 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_AND_b,(RW4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_AND_w,(W4 d, RR2 s, RR2 v)) { @@ -527,7 +508,6 @@ MIDFUNC(3,jff_AND_w,(W4 d, RR2 s, RR2 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_AND_w,(RW4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_AND_l,(W4 d, RR4 s, RR4 v)) { @@ -542,7 +522,6 @@ MIDFUNC(3,jff_AND_l,(W4 d, RR4 s, RR4 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_AND_l,(RW4 d, RR4 s, RR4 v)) /* * ASL @@ -592,7 +571,6 @@ MIDFUNC(3,jff_ASL_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ASL_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ASL_w_imm,(W4 d, RR4 s, IMM i)) { @@ -627,7 +605,6 @@ MIDFUNC(3,jff_ASL_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ASL_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ASL_l_imm,(W4 d, RR4 s, IMM i)) { @@ -660,7 +637,6 @@ MIDFUNC(3,jff_ASL_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ASL_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ASL_b_reg,(W4 d, RR4 s, RR4 i)) { @@ -695,7 +671,6 @@ MIDFUNC(3,jff_ASL_b_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ASL_b_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ASL_w_reg,(W4 d, RR4 s, RR4 i)) { @@ -730,7 +705,6 @@ MIDFUNC(3,jff_ASL_w_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ASL_w_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ASL_l_reg,(W4 d, RR4 s, RR4 i)) { @@ -763,7 +737,6 @@ MIDFUNC(3,jff_ASL_l_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ASL_l_reg,(W4 d, RR4 s, RR4 i)) /* * ASLW @@ -788,7 +761,6 @@ MIDFUNC(2,jnf_ASLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ASLW,(W4 d, RR4 s)) MIDFUNC(2,jff_ASLW,(W4 d, RR4 s)) { @@ -806,7 +778,6 @@ MIDFUNC(2,jff_ASLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_ASLW,(W4 d, RR4 s)) /* * ASR @@ -836,7 +807,6 @@ MIDFUNC(3,jnf_ASR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ASR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ASR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -851,7 +821,6 @@ MIDFUNC(3,jnf_ASR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ASR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ASR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -865,7 +834,6 @@ MIDFUNC(3,jnf_ASR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ASR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ASR_b_imm,(W4 d, RR4 s, IMM i)) { @@ -885,7 +853,6 @@ MIDFUNC(3,jff_ASR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ASR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ASR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -905,7 +872,6 @@ MIDFUNC(3,jff_ASR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ASR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ASR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -924,7 +890,6 @@ MIDFUNC(3,jff_ASR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ASR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ASR_b_reg,(W4 d, RR4 s, RR4 i)) { @@ -940,7 +905,6 @@ MIDFUNC(3,jnf_ASR_b_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ASR_b_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ASR_w_reg,(W4 d, RR4 s, RR4 i)) { @@ -956,7 +920,6 @@ MIDFUNC(3,jnf_ASR_w_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ASR_w_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ASR_l_reg,(W4 d, RR4 s, RR4 i)) { @@ -971,7 +934,6 @@ MIDFUNC(3,jnf_ASR_l_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ASR_l_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ASR_b_reg,(W4 d, RR4 s, RR4 i)) { @@ -989,7 +951,6 @@ MIDFUNC(3,jff_ASR_b_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ASR_b_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ASR_w_reg,(W4 d, RR4 s, RR4 i)) { @@ -1007,7 +968,6 @@ MIDFUNC(3,jff_ASR_w_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ASR_w_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ASR_l_reg,(W4 d, RR4 s, RR4 i)) { @@ -1024,7 +984,6 @@ MIDFUNC(3,jff_ASR_l_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ASR_l_reg,(W4 d, RR4 s, RR4 i)) /* * ASRW @@ -1050,7 +1009,6 @@ MIDFUNC(2,jnf_ASRW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ASRW,(W4 d, RR4 s)) MIDFUNC(2,jff_ASRW,(W4 d, RR4 s)) { @@ -1064,7 +1022,6 @@ MIDFUNC(2,jff_ASRW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_ASRW,(W4 d, RR4 s)) /* * BCHG @@ -1086,7 +1043,6 @@ MIDFUNC(2,jnf_BCHG_b_imm,(RW4 d, IMM s)) EOR_rri(d,d,(1 << s)); unlock2(d); } -MENDFUNC(2,jnf_BCHG_b_imm,(RW4 d, IMM s)) MIDFUNC(2,jnf_BCHG_l_imm,(RW4 d, IMM s)) { @@ -1094,7 +1050,6 @@ MIDFUNC(2,jnf_BCHG_l_imm,(RW4 d, IMM s)) EOR_rri(d,d,(1 << s)); unlock2(d); } -MENDFUNC(2,jnf_BCHG_l_imm,(RW4 d, IMM s)) MIDFUNC(2,jnf_BCHG_b,(RW4 d, RR4 s)) { @@ -1114,7 +1069,6 @@ MIDFUNC(2,jnf_BCHG_b,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_BCHG_b,(RW4 d, RR4 s)) MIDFUNC(2,jnf_BCHG_l,(RW4 d, RR4 s)) { @@ -1135,7 +1089,6 @@ MIDFUNC(2,jnf_BCHG_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_BCHG_l,(RW4 d, RR4 s)) MIDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) { @@ -1151,7 +1104,6 @@ MIDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BCHG_b_imm,(RW4 d, IMM s)) MIDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) { @@ -1167,7 +1119,6 @@ MIDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BCHG_l_imm,(RW4 d, IMM s)) MIDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) { @@ -1192,7 +1143,6 @@ MIDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BCHG_b,(RW4 d, RR4 s)) MIDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) { @@ -1218,7 +1168,6 @@ MIDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BCHG_l,(RW4 d, RR4 s)) /* * BCLR @@ -1240,7 +1189,6 @@ MIDFUNC(2,jnf_BCLR_b_imm,(RW4 d, IMM s)) BIC_rri(d,d,(1 << s)); unlock2(d); } -MENDFUNC(2,jnf_BCLR_b_imm,(RW4 d, IMM s)) MIDFUNC(2,jnf_BCLR_l_imm,(RW4 d, IMM s)) { @@ -1248,7 +1196,6 @@ MIDFUNC(2,jnf_BCLR_l_imm,(RW4 d, IMM s)) BIC_rri(d,d,(1 << s)); unlock2(d); } -MENDFUNC(2,jnf_BCLR_l_imm,(RW4 d, IMM s)) MIDFUNC(2,jnf_BCLR_b,(RW4 d, RR4 s)) { @@ -1268,7 +1215,6 @@ MIDFUNC(2,jnf_BCLR_b,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_BCLR_b,(RW4 d, RR4 s)) MIDFUNC(2,jnf_BCLR_l,(RW4 d, RR4 s)) { @@ -1289,7 +1235,6 @@ MIDFUNC(2,jnf_BCLR_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_BCLR_l,(RW4 d, RR4 s)) MIDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) { @@ -1305,7 +1250,6 @@ MIDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BCLR_b_imm,(RW4 d, IMM s)) MIDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) { @@ -1321,7 +1265,6 @@ MIDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BCLR_l_imm,(RW4 d, IMM s)) MIDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) { @@ -1346,7 +1289,6 @@ MIDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BCLR_b,(RW4 d, RR4 s)) MIDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) { @@ -1372,7 +1314,6 @@ MIDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BCLR_l,(RW4 d, RR4 s)) /* * BSET @@ -1394,7 +1335,6 @@ MIDFUNC(2,jnf_BSET_b_imm,(RW4 d, IMM s)) ORR_rri(d,d,(1 << s)); unlock2(d); } -MENDFUNC(2,jnf_BSET_b_imm,(RW4 d, IMM s)) MIDFUNC(2,jnf_BSET_l_imm,(RW4 d, IMM s)) { @@ -1402,7 +1342,6 @@ MIDFUNC(2,jnf_BSET_l_imm,(RW4 d, IMM s)) ORR_rri(d,d,(1 << s)); unlock2(d); } -MENDFUNC(2,jnf_BSET_l_imm,(RW4 d, IMM s)) MIDFUNC(2,jnf_BSET_b,(RW4 d, RR4 s)) { @@ -1422,7 +1361,6 @@ MIDFUNC(2,jnf_BSET_b,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_BSET_b,(RW4 d, RR4 s)) MIDFUNC(2,jnf_BSET_l,(RW4 d, RR4 s)) { @@ -1443,7 +1381,6 @@ MIDFUNC(2,jnf_BSET_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_BSET_l,(RW4 d, RR4 s)) MIDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) { @@ -1459,7 +1396,6 @@ MIDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BSET_b_imm,(RW4 d, IMM s)) MIDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) { @@ -1475,7 +1411,6 @@ MIDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BSET_l_imm,(RW4 d, IMM s)) MIDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) { @@ -1500,7 +1435,6 @@ MIDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BSET_b,(RW4 d, RR4 s)) MIDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) { @@ -1526,7 +1460,6 @@ MIDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BSET_l,(RW4 d, RR4 s)) /* * BTST @@ -1554,7 +1487,6 @@ MIDFUNC(2,jff_BTST_b_imm,(RR4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BTST_b_imm,(RR4 d, IMM s)) MIDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) { @@ -1568,7 +1500,6 @@ MIDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_BTST_l_imm,(RR4 d, IMM s)) MIDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) { @@ -1592,7 +1523,6 @@ MIDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BTST_b,(RR4 d, RR4 s)) MIDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) { @@ -1617,7 +1547,6 @@ MIDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_BTST_l,(RR4 d, RR4 s)) /* * CLR @@ -1638,7 +1567,6 @@ MIDFUNC(1,jnf_CLR,(W4 d)) MOV_ri(d,0); unlock2(d); } -MENDFUNC(1,jnf_CLR,(W4 d)) MIDFUNC(1,jff_CLR,(W4 d)) { @@ -1647,7 +1575,6 @@ MIDFUNC(1,jff_CLR,(W4 d)) MSR_CPSR_i(ARM_Z_FLAG); unlock2(d); } -MENDFUNC(1,jff_CLR,(W4 d)) /* * CMP @@ -1679,7 +1606,6 @@ MIDFUNC(2,jff_CMP_b,(RR1 d, RR1 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_CMP_b,(RR1 d, RR1 s)) MIDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) { @@ -1698,7 +1624,6 @@ MIDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_CMP_w,(RR2 d, RR2 s)) MIDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) { @@ -1715,7 +1640,6 @@ MIDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_CMP_l,(RR4 d, RR4 s)) /* * CMPA @@ -1746,7 +1670,6 @@ MIDFUNC(2,jff_CMPA_b,(RR1 d, RR1 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_CMPA_b,(RR1 d, RR1 s)) MIDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) { @@ -1764,7 +1687,6 @@ MIDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_CMPA_w,(RR2 d, RR2 s)) MIDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) { @@ -1781,7 +1703,6 @@ MIDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_CMPA_l,(RR4 d, RR4 s)) /* * EOR @@ -1815,7 +1736,6 @@ MIDFUNC(3,jnf_EOR,(W4 d, RR4 s, RR4 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_EOR,(RW4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_EOR_b,(W4 d, RR1 s, RR1 v)) { @@ -1832,7 +1752,6 @@ MIDFUNC(3,jff_EOR_b,(W4 d, RR1 s, RR1 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_EOR_b,(RW4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_EOR_w,(W4 d, RR2 s, RR2 v)) { @@ -1849,7 +1768,6 @@ MIDFUNC(3,jff_EOR_w,(W4 d, RR2 s, RR2 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_EOR_w,(RW4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_EOR_l,(W4 d, RR4 s, RR4 v)) { @@ -1864,7 +1782,6 @@ MIDFUNC(3,jff_EOR_l,(W4 d, RR4 s, RR4 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_EOR_l,(RW4 d, RR4 s, RR4 v)) /* * EORI @@ -1892,7 +1809,6 @@ MIDFUNC(1,jff_EORSR,(IMM s, IMM x)) STRB_rR(REG_WORK2, REG_WORK1); } } -MENDFUNC(1,jff_EORSR,(IMM s)) /* * EXT @@ -1922,7 +1838,6 @@ MIDFUNC(2,jnf_EXT_b,(W4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_EXT_b,(W4 d, RR4 s)) MIDFUNC(2,jnf_EXT_w,(W4 d, RR4 s)) { @@ -1939,7 +1854,6 @@ MIDFUNC(2,jnf_EXT_w,(W4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_EXT_w,(W4 d, RR4 s)) MIDFUNC(2,jnf_EXT_l,(W4 d, RR4 s)) { @@ -1956,7 +1870,6 @@ MIDFUNC(2,jnf_EXT_l,(W4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_EXT_l,(W4 d, RR4 s)) MIDFUNC(2,jff_EXT_b,(W4 d, RR4 s)) { @@ -1975,7 +1888,6 @@ MIDFUNC(2,jff_EXT_b,(W4 d, RR4 s)) unlock2(d); } -MENDFUNC(2,jff_EXT_b,(W4 d, RR4 s)) MIDFUNC(2,jff_EXT_w,(W4 d, RR4 s)) { @@ -1994,7 +1906,6 @@ MIDFUNC(2,jff_EXT_w,(W4 d, RR4 s)) unlock2(d); } -MENDFUNC(2,jff_EXT_w,(W4 d, RR4 s)) MIDFUNC(2,jff_EXT_l,(W4 d, RR4 s)) { @@ -2012,7 +1923,6 @@ MIDFUNC(2,jff_EXT_l,(W4 d, RR4 s)) unlock2(d); } -MENDFUNC(2,jff_EXT_l,(W4 d, RR4 s)) /* * LSL @@ -2041,7 +1951,6 @@ MIDFUNC(3,jnf_LSL_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_LSL_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_LSL_reg,(W4 d, RR4 s, RR4 i)) { @@ -2056,7 +1965,6 @@ MIDFUNC(3,jnf_LSL_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_LSL_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_LSL_b_imm,(W4 d, RR4 s, IMM i)) { @@ -2077,7 +1985,6 @@ MIDFUNC(3,jff_LSL_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_LSL_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_LSL_w_imm,(W4 d, RR4 s, IMM i)) { @@ -2097,7 +2004,6 @@ MIDFUNC(3,jff_LSL_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_LSL_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_LSL_l_imm,(W4 d, RR4 s, IMM i)) { @@ -2115,7 +2021,6 @@ MIDFUNC(3,jff_LSL_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_LSL_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_LSL_b_reg,(W4 d, RR4 s, RR4 i)) { @@ -2135,7 +2040,6 @@ MIDFUNC(3,jff_LSL_b_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_LSL_b_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_LSL_w_reg,(W4 d, RR4 s, RR4 i)) { @@ -2154,7 +2058,6 @@ MIDFUNC(3,jff_LSL_w_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_LSL_w_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_LSL_l_reg,(W4 d, RR4 s, RR4 i)) { @@ -2171,7 +2074,6 @@ MIDFUNC(3,jff_LSL_l_reg,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_LSL_l_reg,(W4 d, RR4 s, RR4 i)) /* * LSLW @@ -2196,7 +2098,6 @@ MIDFUNC(2,jnf_LSLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_LSLW,(W4 d, RR4 s)) MIDFUNC(2,jff_LSLW,(W4 d, RR4 s)) { @@ -2210,7 +2111,6 @@ MIDFUNC(2,jff_LSLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_LSLW,(W4 d, RR4 s)) /* * LSR @@ -2256,7 +2156,6 @@ MIDFUNC(3,jnf_LSR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(s); } } -MENDFUNC(3,jnf_LSR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_LSR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -2285,7 +2184,6 @@ MIDFUNC(3,jnf_LSR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(s); } } -MENDFUNC(3,jnf_LSR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_LSR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -2313,7 +2211,6 @@ MIDFUNC(3,jnf_LSR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(s); } } -MENDFUNC(3,jnf_LSR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_LSR_b_imm,(W4 d, RR4 s, IMM i)) { @@ -2343,7 +2240,6 @@ MIDFUNC(3,jff_LSR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(s); } } -MENDFUNC(3,jff_LSR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_LSR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -2373,7 +2269,6 @@ MIDFUNC(3,jff_LSR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(s); } } -MENDFUNC(3,jff_LSR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_LSR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -2402,7 +2297,6 @@ MIDFUNC(3,jff_LSR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(s); } } -MENDFUNC(3,jff_LSR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_LSR_b_reg,(W4 d, RR4 s, RR4 i)) { @@ -2431,7 +2325,6 @@ MIDFUNC(3,jnf_LSR_b_reg,(W4 d, RR4 s, RR4 i)) } unlock2(i); } -MENDFUNC(3,jnf_LSR_b_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_LSR_w_reg,(W4 d, RR4 s, RR4 i)) { @@ -2460,7 +2353,6 @@ MIDFUNC(3,jnf_LSR_w_reg,(W4 d, RR4 s, RR4 i)) } unlock2(i); } -MENDFUNC(3,jnf_LSR_w_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_LSR_l_reg,(W4 d, RR4 s, RR4 i)) { @@ -2488,7 +2380,6 @@ MIDFUNC(3,jnf_LSR_l_reg,(W4 d, RR4 s, RR4 i)) } unlock2(i); } -MENDFUNC(3,jnf_LSR_l_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_LSR_b_reg,(W4 d, RR4 s, RR4 i)) { @@ -2519,7 +2410,6 @@ MIDFUNC(3,jff_LSR_b_reg,(W4 d, RR4 s, RR4 i)) } unlock2(i); } -MENDFUNC(3,jff_LSR_b_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_LSR_w_reg,(W4 d, RR4 s, RR4 i)) { @@ -2550,7 +2440,6 @@ MIDFUNC(3,jff_LSR_w_reg,(W4 d, RR4 s, RR4 i)) } unlock2(i); } -MENDFUNC(3,jff_LSR_w_reg,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_LSR_l_reg,(W4 d, RR4 s, RR4 i)) { @@ -2580,7 +2469,6 @@ MIDFUNC(3,jff_LSR_l_reg,(W4 d, RR4 s, RR4 i)) } unlock2(i); } -MENDFUNC(3,jff_LSR_l_reg,(W4 d, RR4 s, RR4 i)) /* * LSRW @@ -2606,7 +2494,6 @@ MIDFUNC(2,jnf_LSRW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_LSRW,(W4 d, RR4 s)) MIDFUNC(2,jff_LSRW,(W4 d, RR4 s)) { @@ -2620,7 +2507,6 @@ MIDFUNC(2,jff_LSRW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_LSRW,(W4 d, RR4 s)) /* * MOVE @@ -2649,7 +2535,6 @@ MIDFUNC(2,jnf_MOVE,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_MOVE,(W4 d, RR4 s)) MIDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) { @@ -2661,7 +2546,6 @@ MIDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_MOVE_b_imm,(W4 d, IMM s)) MIDFUNC(2,jff_MOVE_w_imm,(W4 d, IMM s)) { @@ -2673,7 +2557,6 @@ MIDFUNC(2,jff_MOVE_w_imm,(W4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_MOVE_w_imm,(W4 d, IMM s)) MIDFUNC(2,jff_MOVE_l_imm,(W4 d, IMM s)) { @@ -2685,7 +2568,6 @@ MIDFUNC(2,jff_MOVE_l_imm,(W4 d, IMM s)) unlock2(d); } -MENDFUNC(2,jff_MOVE_l_imm,(W4 d, IMM s)) MIDFUNC(2,jff_MOVE_b,(W4 d, RR1 s)) { @@ -2704,7 +2586,6 @@ MIDFUNC(2,jff_MOVE_b,(W4 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_MOVE_b,(W4 d, RR1 s)) MIDFUNC(2,jff_MOVE_w,(W4 d, RR2 s)) { @@ -2723,7 +2604,6 @@ MIDFUNC(2,jff_MOVE_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_MOVE_w,(W4 d, RR2 s)) MIDFUNC(2,jff_MOVE_l,(W4 d, RR4 s)) { @@ -2741,7 +2621,6 @@ MIDFUNC(2,jff_MOVE_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_MOVE_l,(W4 d, RR4 s)) /* * MOVE16 @@ -2776,7 +2655,6 @@ MIDFUNC(2,jnf_MOVE16,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_MOVE16,(RR4 d, RR4 s)) /* * MOVEA @@ -2797,7 +2675,6 @@ MIDFUNC(2,jnf_MOVEA_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_MOVEA_w,(W4 d, RR2 s)) MIDFUNC(2,jnf_MOVEA_l,(W4 d, RR4 s)) { @@ -2809,7 +2686,6 @@ MIDFUNC(2,jnf_MOVEA_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_MOVEA_l,(W4 d, RR4 s)) /* * MULS @@ -2836,7 +2712,6 @@ MIDFUNC(2,jnf_MULS,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_MULS,(RW4 d, RR4 s)) MIDFUNC(2,jff_MULS,(RW4 d, RR4 s)) { @@ -2852,7 +2727,6 @@ MIDFUNC(2,jff_MULS,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_MULS,(RW4 d, RR4 s)) MIDFUNC(2,jnf_MULS32,(RW4 d, RR4 s)) { @@ -2864,7 +2738,6 @@ MIDFUNC(2,jnf_MULS32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_MULS32,(RW4 d, RR4 s)) MIDFUNC(2,jff_MULS32,(RW4 d, RR4 s)) { @@ -2882,7 +2755,6 @@ MIDFUNC(2,jff_MULS32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_MULS32,(RW4 d, RR4 s)) MIDFUNC(2,jnf_MULS64,(RW4 d, RW4 s)) { @@ -2895,7 +2767,6 @@ MIDFUNC(2,jnf_MULS64,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_MULS64,(RW4 d, RW4 s)) MIDFUNC(2,jff_MULS64,(RW4 d, RW4 s)) { @@ -2913,7 +2784,6 @@ MIDFUNC(2,jff_MULS64,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_MULS64,(RW4 d, RW4 s)) /* * MULU @@ -2941,7 +2811,6 @@ MIDFUNC(2,jnf_MULU,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_MULU,(RW4 d, RR4 s)) MIDFUNC(2,jff_MULU,(RW4 d, RR4 s)) { @@ -2957,7 +2826,6 @@ MIDFUNC(2,jff_MULU,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_MULU,(RW4 d, RR4 s)) MIDFUNC(2,jnf_MULU32,(RW4 d, RR4 s)) { @@ -2969,7 +2837,6 @@ MIDFUNC(2,jnf_MULU32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_MULU32,(RW4 d, RR4 s)) MIDFUNC(2,jff_MULU32,(RW4 d, RR4 s)) { @@ -2987,7 +2854,6 @@ MIDFUNC(2,jff_MULU32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_MULU32,(RW4 d, RR4 s)) MIDFUNC(2,jnf_MULU64,(RW4 d, RW4 s)) { @@ -3000,7 +2866,6 @@ MIDFUNC(2,jnf_MULU64,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jnf_MULU64,(RW4 d, RW4 s)) MIDFUNC(2,jff_MULU64,(RW4 d, RW4 s)) { @@ -3018,7 +2883,6 @@ MIDFUNC(2,jff_MULU64,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,jff_MULU64,(RW4 d, RW4 s)) /* * NEG @@ -3043,7 +2907,6 @@ MIDFUNC(2,jnf_NEG,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_NEG,(W4 d, RR4 s)) MIDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) { @@ -3061,7 +2924,6 @@ MIDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NEG_b,(W4 d, RR1 s)) MIDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) { @@ -3079,7 +2941,6 @@ MIDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NEG_w,(W4 d, RR2 s)) MIDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) { @@ -3096,7 +2957,6 @@ MIDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NEG_l,(W4 d, RR4 s)) /* * NEGX @@ -3123,7 +2983,6 @@ MIDFUNC(2,jnf_NEGX,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_NEGX,(W4 d, RR4 s)) MIDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) { @@ -3145,7 +3004,6 @@ MIDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NEGX_b,(W4 d, RR1 s)) MIDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) { @@ -3167,7 +3025,6 @@ MIDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NEGX_w,(W4 d, RR2 s)) MIDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) { @@ -3188,7 +3045,6 @@ MIDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NEGX_l,(W4 d, RR4 s)) /* * NOT @@ -3213,7 +3069,6 @@ MIDFUNC(2,jnf_NOT,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_NOT,(W4 d, RR4 s)) MIDFUNC(2,jff_NOT_b,(W4 d, RR1 s)) { @@ -3227,7 +3082,6 @@ MIDFUNC(2,jff_NOT_b,(W4 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NOT_b,(W4 d, RR1 s)) MIDFUNC(2,jff_NOT_w,(W4 d, RR2 s)) { @@ -3241,7 +3095,6 @@ MIDFUNC(2,jff_NOT_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NOT_w,(W4 d, RR2 s)) MIDFUNC(2,jff_NOT_l,(W4 d, RR4 s)) { @@ -3254,7 +3107,6 @@ MIDFUNC(2,jff_NOT_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_NOT_l,(W4 d, RR4 s)) /* * OR @@ -3288,7 +3140,6 @@ MIDFUNC(3,jnf_OR,(W4 d, RR4 s, RR4 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_OR,(RW4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_OR_b,(W4 d, RR1 s, RR1 v)) { @@ -3305,7 +3156,6 @@ MIDFUNC(3,jff_OR_b,(W4 d, RR1 s, RR1 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_OR_b,(RW4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_OR_w,(W4 d, RR2 s, RR2 v)) { @@ -3322,7 +3172,6 @@ MIDFUNC(3,jff_OR_w,(W4 d, RR2 s, RR2 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_OR_w,(RW4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_OR_l,(W4 d, RR4 s, RR4 v)) { @@ -3337,7 +3186,6 @@ MIDFUNC(3,jff_OR_l,(W4 d, RR4 s, RR4 v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_OR_l,(RW4 d, RR4 s, RR4 v)) /* * ORI @@ -3364,7 +3212,6 @@ MIDFUNC(1,jff_ORSR,(IMM s, IMM x)) STRB_rR(REG_WORK2, REG_WORK1); } } -MENDFUNC(1,jff_ORSR,(IMM s)) /* * ROL @@ -3394,7 +3241,6 @@ MIDFUNC(3,jnf_ROL_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROL_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) { @@ -3408,7 +3254,6 @@ MIDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROL_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROL_l_imm,(W4 d, RR4 s, IMM i)) { @@ -3420,7 +3265,6 @@ MIDFUNC(3,jnf_ROL_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROL_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) { @@ -3447,7 +3291,6 @@ MIDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROL_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) { @@ -3473,7 +3316,6 @@ MIDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROL_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) { @@ -3497,7 +3339,6 @@ MIDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROL_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROL_b,(W4 d, RR4 s, RR4 i)) { @@ -3521,7 +3362,6 @@ MIDFUNC(3,jnf_ROL_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROL_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) { @@ -3544,7 +3384,6 @@ MIDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROL_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROL_l,(W4 d, RR4 s, RR4 i)) { @@ -3565,7 +3404,6 @@ MIDFUNC(3,jnf_ROL_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROL_l,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) { @@ -3597,7 +3435,6 @@ MIDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROL_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) { @@ -3628,7 +3465,6 @@ MIDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROL_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) { @@ -3657,7 +3493,6 @@ MIDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROL_l,(W4 d, RR4 s, RR4 i)) /* * ROLW @@ -3684,7 +3519,6 @@ MIDFUNC(2,jnf_ROLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ROLW,(W4 d, RR4 s)) MIDFUNC(2,jff_ROLW,(W4 d, RR4 s)) { @@ -3705,7 +3539,6 @@ MIDFUNC(2,jff_ROLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_ROLW,(W4 d, RR4 s)) /* * RORW @@ -3732,7 +3565,6 @@ MIDFUNC(2,jnf_RORW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_RORW,(W4 d, RR4 s)) MIDFUNC(2,jff_RORW,(W4 d, RR4 s)) { @@ -3747,7 +3579,6 @@ MIDFUNC(2,jff_RORW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_RORW,(W4 d, RR4 s)) /* * ROXL @@ -3780,7 +3611,6 @@ MIDFUNC(3,jnf_ROXL_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROXL_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROXL_w_imm,(W4 d, RR4 s, IMM i)) { @@ -3799,7 +3629,6 @@ MIDFUNC(3,jnf_ROXL_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROXL_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROXL_l_imm,(W4 d, RR4 s, IMM i)) { @@ -3817,7 +3646,6 @@ MIDFUNC(3,jnf_ROXL_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROXL_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROXL_b_imm,(W4 d, RR4 s, IMM i)) { @@ -3843,7 +3671,6 @@ MIDFUNC(3,jff_ROXL_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROXL_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROXL_w_imm,(W4 d, RR4 s, IMM i)) { @@ -3869,7 +3696,6 @@ MIDFUNC(3,jff_ROXL_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROXL_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROXL_l_imm,(W4 d, RR4 s, IMM i)) { @@ -3893,7 +3719,6 @@ MIDFUNC(3,jff_ROXL_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROXL_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROXL_b,(W4 d, RR4 s, RR4 i)) { @@ -3940,7 +3765,6 @@ MIDFUNC(3,jnf_ROXL_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROXL_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROXL_w,(W4 d, RR4 s, RR4 i)) { @@ -3984,7 +3808,6 @@ MIDFUNC(3,jnf_ROXL_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROXL_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROXL_l,(W4 d, RR4 s, RR4 i)) { @@ -4016,7 +3839,6 @@ MIDFUNC(3,jnf_ROXL_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROXL_l,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROXL_b,(W4 d, RR4 s, RR4 i)) { @@ -4082,7 +3904,6 @@ MIDFUNC(3,jff_ROXL_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROXL_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROXL_w,(W4 d, RR4 s, RR4 i)) { @@ -4147,7 +3968,6 @@ MIDFUNC(3,jff_ROXL_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROXL_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROXL_l,(W4 d, RR4 s, RR4 i)) { @@ -4196,7 +4016,6 @@ MIDFUNC(3,jff_ROXL_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROXL_l,(W4 d, RR4 s, RR4 i)) /* * ROXLW @@ -4222,7 +4041,6 @@ MIDFUNC(2,jnf_ROXLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ROXLW,(W4 d, RR4 s)) MIDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) { @@ -4238,7 +4056,6 @@ MIDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_ROXLW,(W4 d, RR4 s)) /* * ROR @@ -4268,7 +4085,6 @@ MIDFUNC(3,jnf_ROR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -4282,7 +4098,6 @@ MIDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -4294,7 +4109,6 @@ MIDFUNC(3,jnf_ROR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) { @@ -4310,7 +4124,6 @@ MIDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -4325,7 +4138,6 @@ MIDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -4338,7 +4150,6 @@ MIDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROR_b,(W4 d, RR4 s, RR4 i)) { @@ -4359,7 +4170,6 @@ MIDFUNC(3,jnf_ROR_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROR_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) { @@ -4379,7 +4189,6 @@ MIDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROR_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROR_l,(W4 d, RR4 s, RR4 i)) { @@ -4397,7 +4206,6 @@ MIDFUNC(3,jnf_ROR_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROR_l,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROR_b,(W4 d, RR4 s, RR4 i)) { @@ -4421,7 +4229,6 @@ MIDFUNC(3,jff_ROR_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROR_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) { @@ -4444,7 +4251,6 @@ MIDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROR_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROR_l,(W4 d, RR4 s, RR4 i)) { @@ -4465,7 +4271,6 @@ MIDFUNC(3,jff_ROR_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROR_l,(W4 d, RR4 s, RR4 i)) /* * ROXR @@ -4497,7 +4302,6 @@ MIDFUNC(3,jnf_ROXR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROXR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROXR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -4515,7 +4319,6 @@ MIDFUNC(3,jnf_ROXR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROXR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROXR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -4533,7 +4336,6 @@ MIDFUNC(3,jnf_ROXR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_ROXR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROXR_b_imm,(W4 d, RR4 s, IMM i)) { @@ -4559,7 +4361,6 @@ MIDFUNC(3,jff_ROXR_b_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROXR_b_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROXR_w_imm,(W4 d, RR4 s, IMM i)) { @@ -4585,7 +4386,6 @@ MIDFUNC(3,jff_ROXR_w_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROXR_w_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jff_ROXR_l_imm,(W4 d, RR4 s, IMM i)) { @@ -4609,7 +4409,6 @@ MIDFUNC(3,jff_ROXR_l_imm,(W4 d, RR4 s, IMM i)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_ROXR_l_imm,(W4 d, RR4 s, IMM i)) MIDFUNC(3,jnf_ROXR_b,(W4 d, RR4 s, RR4 i)) { @@ -4647,7 +4446,6 @@ MIDFUNC(3,jnf_ROXR_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROXR_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROXR_w,(W4 d, RR4 s, RR4 i)) { @@ -4682,7 +4480,6 @@ MIDFUNC(3,jnf_ROXR_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROXR_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jnf_ROXR_l,(W4 d, RR4 s, RR4 i)) { @@ -4715,7 +4512,6 @@ MIDFUNC(3,jnf_ROXR_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jnf_ROXR_l,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROXR_b,(W4 d, RR4 s, RR4 i)) { @@ -4769,7 +4565,6 @@ MIDFUNC(3,jff_ROXR_b,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROXR_b,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROXR_w,(W4 d, RR4 s, RR4 i)) { @@ -4821,7 +4616,6 @@ MIDFUNC(3,jff_ROXR_w,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROXR_w,(W4 d, RR4 s, RR4 i)) MIDFUNC(3,jff_ROXR_l,(W4 d, RR4 s, RR4 i)) { @@ -4870,7 +4664,6 @@ MIDFUNC(3,jff_ROXR_l,(W4 d, RR4 s, RR4 i)) unlock2(s); unlock2(i); } -MENDFUNC(3,jff_ROXR_l,(W4 d, RR4 s, RR4 i)) /* * ROXRW @@ -4897,7 +4690,6 @@ MIDFUNC(2,jnf_ROXRW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_ROXRW,(W4 d, RR4 s)) MIDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) { @@ -4912,7 +4704,6 @@ MIDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jff_ROXRW,(W4 d, RR4 s)) /* * SUB @@ -4944,7 +4735,6 @@ MIDFUNC(3,jnf_SUB_b_imm,(W4 d, RR4 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_SUB_b_imm,(W4 d, RR4 s, IMM v)) MIDFUNC(3,jnf_SUB_b,(W4 d, RR4 s, RR4 v)) { @@ -4964,7 +4754,6 @@ MIDFUNC(3,jnf_SUB_b,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jnf_SUB_b,(W4 d, RR4 s, RR4 v)) MIDFUNC(3,jnf_SUB_w_imm,(W4 d, RR4 s, IMM v)) { @@ -4982,7 +4771,6 @@ MIDFUNC(3,jnf_SUB_w_imm,(W4 d, RR4 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_SUB_w_imm,(W4 d, RR4 s, IMM v)) MIDFUNC(3,jnf_SUB_w,(W4 d, RR4 s, RR4 v)) { @@ -5002,7 +4790,6 @@ MIDFUNC(3,jnf_SUB_w,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jnf_SUB_w,(W4 d, RR4 s, RR4 v)) MIDFUNC(3,jnf_SUB_l_imm,(W4 d, RR4 s, IMM v)) { @@ -5020,7 +4807,6 @@ MIDFUNC(3,jnf_SUB_l_imm,(W4 d, RR4 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jnf_SUB_l_imm,(W4 d, RR4 s, IMM v)) MIDFUNC(3,jnf_SUB_l,(W4 d, RR4 s, RR4 v)) { @@ -5040,7 +4826,6 @@ MIDFUNC(3,jnf_SUB_l,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jnf_SUB_l,(W4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) { @@ -5060,7 +4845,6 @@ MIDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_SUB_b_imm,(W4 d, RR1 s, IMM v)) MIDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) { @@ -5087,7 +4871,6 @@ MIDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_SUB_b,(W4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_SUB_w_imm,(W4 d, RR2 s, IMM v)) { @@ -5107,7 +4890,6 @@ MIDFUNC(3,jff_SUB_w_imm,(W4 d, RR2 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jitc_SUB_ff_w2l_rri,(W4 d, RR2 s, IMM v)) MIDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) { @@ -5134,7 +4916,6 @@ MIDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_SUB_w,(W4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) { @@ -5153,7 +4934,6 @@ MIDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) unlock2(d); unlock2(s); } -MENDFUNC(3,jff_SUB_l_imm,(W4 d, RR4 s, IMM v)) MIDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) { @@ -5178,7 +4958,6 @@ MIDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_SUB_l,(W4 d, RR4 s, RR4 v)) /* * SUBA @@ -5201,7 +4980,6 @@ MIDFUNC(2,jnf_SUBA_b,(W4 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_SUBA_b,(W4 d, RR1 s)) MIDFUNC(2,jnf_SUBA_w,(W4 d, RR2 s)) { @@ -5214,7 +4992,6 @@ MIDFUNC(2,jnf_SUBA_w,(W4 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_SUBA_w,(W4 d, RR2 s)) MIDFUNC(2,jnf_SUBA_l,(W4 d, RR4 s)) { @@ -5226,7 +5003,6 @@ MIDFUNC(2,jnf_SUBA_l,(W4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,jnf_SUBA_l,(W4 d, RR4 s)) /* * SUBX @@ -5256,7 +5032,6 @@ MIDFUNC(3,jnf_SUBX,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jnf_SUBX,(W4 d, RR4 s, RR4 v)) MIDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) { @@ -5283,7 +5058,6 @@ MIDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_SUBX_b,(W4 d, RR1 s, RR1 v)) MIDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) { @@ -5310,7 +5084,6 @@ MIDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_SUBX_w,(W4 d, RR2 s, RR2 v)) MIDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) { @@ -5333,7 +5106,6 @@ MIDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) unlock2(s); unlock2(v); } -MENDFUNC(3,jff_SUBX_l,(W4 d, RR4 s, RR4 v)) /* * SWAP @@ -5356,7 +5128,6 @@ MIDFUNC(1,jnf_SWAP,(RW4 d)) unlock2(d); } -MENDFUNC(1,jnf_SWAP,(RW4 d)) MIDFUNC(1,jff_SWAP,(RW4 d)) { @@ -5368,7 +5139,6 @@ MIDFUNC(1,jff_SWAP,(RW4 d)) unlock2(d); } -MENDFUNC(1,jff_SWAP,(RW4 d)) /* * TST @@ -5395,7 +5165,6 @@ MIDFUNC(1,jff_TST_b,(RR1 s)) MSR_CPSRf_i(0); TST_rr(REG_WORK1,REG_WORK1); } -MENDFUNC(1,jff_TST_b,(RR1 s)) MIDFUNC(1,jff_TST_w,(RR2 s)) { @@ -5409,7 +5178,6 @@ MIDFUNC(1,jff_TST_w,(RR2 s)) MSR_CPSRf_i(0); TST_rr(REG_WORK1,REG_WORK1); } -MENDFUNC(1,jff_TST_w,(RR2 s)) MIDFUNC(1,jff_TST_l,(RR4 s)) { @@ -5425,4 +5193,3 @@ MIDFUNC(1,jff_TST_l,(RR4 s)) unlock2(s); } } -MENDFUNC(1,jff_TST_l,(RR4 s)) diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp index d5e2e053..c322e590 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp @@ -98,14 +98,16 @@ MIDFUNC(0,live_flags,(void)) live.flags_in_flags=VALID; live.flags_are_important=1; } -MENDFUNC(0,live_flags,(void)) MIDFUNC(0,dont_care_flags,(void)) { live.flags_are_important=0; } -MENDFUNC(0,dont_care_flags,(void)) +/* + * store the state of the x86 carry bit into regflags.x, + * into the position denoted by FLAGBIT_X + */ MIDFUNC(0,duplicate_carry,(void)) { evict(FLAGX); @@ -117,54 +119,96 @@ MIDFUNC(0,duplicate_carry,(void)) #endif log_vwrite(FLAGX); } -MENDFUNC(0,duplicate_carry,(void)) +MIDFUNC(3,setcc_for_cntzero,(RR4 /* cnt */, RR4 data, int size)) +{ + uae_u8 *branchadd; + uae_u8 *branchadd2; + + evict(FLAGX); + make_flags_live_internal(); + + raw_pushfl(); + /* + * shift count can only be in CL register; see shrl_b_rr + */ + raw_test_b_rr(X86_CL, X86_CL); + /* if zero, leave X unaffected; carry flag will already be cleared */ + raw_jz_b_oponly(); + branchadd = get_target(); + skip_byte(); + + /* shift count was non-zero; update also x-flag */ + raw_popfl(); +#ifdef UAE + COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem + 1, NATIVE_CC_CS); +#else + COMPCALL(setcc_m)((uintptr)live.state[FLAGX].mem, NATIVE_CC_CS); +#endif + log_vwrite(FLAGX); + raw_jmp_b_oponly(); + branchadd2 = get_target(); + skip_byte(); + *branchadd = (uintptr)get_target() - ((uintptr)branchadd + 1); + + /* shift count was zero; need to set Z & N flags since the native flags were unaffected */ + raw_popfl(); + data = readreg(data, size); + switch (size) + { + case 1: raw_test_b_rr(data, data); break; + case 2: raw_test_w_rr(data, data); break; + case 4: raw_test_l_rr(data, data); break; + } + unlock2(data); + *branchadd2 = (uintptr)get_target() - ((uintptr)branchadd2 + 1); +} + +/* + * Set the x86 carry flag from regflags.x, from the position + * denoted by FLAGBIT_X + */ MIDFUNC(0,restore_carry,(void)) { if (!have_rat_stall) { /* Not a P6 core, i.e. no partial stalls */ #ifdef UAE - bt_l_ri_noclobber(FLAGX, 8); + bt_l_ri_noclobber(FLAGX, FLAGBIT_X+8); #else - bt_l_ri_noclobber(FLAGX, 0); + bt_l_ri_noclobber(FLAGX, FLAGBIT_X); #endif } else { /* Avoid the stall the above creates. This is slow on non-P6, though. */ -#ifdef UAE - COMPCALL(rol_w_ri(FLAGX, 8)); +#if defined(UAE) || FLAGBIT_X >= 8 + COMPCALL(rol_w_ri(FLAGX, 16 - FLAGBIT_X)); #else - COMPCALL(rol_b_ri(FLAGX, 8)); + COMPCALL(rol_b_ri(FLAGX, 8 - FLAGBIT_X)); #endif isclean(FLAGX); } } -MENDFUNC(0,restore_carry,(void)) MIDFUNC(0,start_needflags,(void)) { needflags=1; } -MENDFUNC(0,start_needflags,(void)) MIDFUNC(0,end_needflags,(void)) { needflags=0; } -MENDFUNC(0,end_needflags,(void)) MIDFUNC(0,make_flags_live,(void)) { make_flags_live_internal(); } -MENDFUNC(0,make_flags_live,(void)) MIDFUNC(1,fflags_into_flags,(W2 tmp)) { clobber_flags(); fflags_into_flags_internal(tmp); } -MENDFUNC(1,fflags_into_flags,(W2 tmp)) MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ { @@ -176,7 +220,6 @@ MIDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ raw_bt_l_ri(r,i); unlock2(r); } -MENDFUNC(2,bt_l_ri,(RR4 r, IMM i)) /* This is defined as only affecting C */ MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ { @@ -187,7 +230,6 @@ MIDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ unlock2(r); unlock2(b); } -MENDFUNC(2,bt_l_rr,(RR4 r, RR4 b)) /* This is defined as only affecting C */ MIDFUNC(2,btc_l_ri,(RW4 r, IMM i)) { @@ -199,7 +241,6 @@ MIDFUNC(2,btc_l_ri,(RW4 r, IMM i)) raw_btc_l_ri(r,i); unlock2(r); } -MENDFUNC(2,btc_l_ri,(RW4 r, IMM i)) MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) { @@ -210,7 +251,6 @@ MIDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) unlock2(r); unlock2(b); } -MENDFUNC(2,btc_l_rr,(RW4 r, RR4 b)) MIDFUNC(2,btr_l_ri,(RW4 r, IMM i)) { @@ -222,7 +262,6 @@ MIDFUNC(2,btr_l_ri,(RW4 r, IMM i)) raw_btr_l_ri(r,i); unlock2(r); } -MENDFUNC(2,btr_l_ri,(RW4 r, IMM i)) MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) { @@ -233,7 +272,6 @@ MIDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) unlock2(r); unlock2(b); } -MENDFUNC(2,btr_l_rr,(RW4 r, RR4 b)) MIDFUNC(2,bts_l_ri,(RW4 r, IMM i)) { @@ -245,7 +283,6 @@ MIDFUNC(2,bts_l_ri,(RW4 r, IMM i)) raw_bts_l_ri(r,i); unlock2(r); } -MENDFUNC(2,bts_l_ri,(RW4 r, IMM i)) MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) { @@ -256,7 +293,6 @@ MIDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) unlock2(r); unlock2(b); } -MENDFUNC(2,bts_l_rr,(RW4 r, RR4 b)) MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) { @@ -265,7 +301,6 @@ MIDFUNC(2,mov_l_rm,(W4 d, IMM s)) raw_mov_l_rm(d,s); unlock2(d); } -MENDFUNC(2,mov_l_rm,(W4 d, IMM s)) MIDFUNC(1,call_r,(RR4 r)) /* Clobbering is implicit */ { @@ -275,35 +310,30 @@ MIDFUNC(1,call_r,(RR4 r)) /* Clobbering is implicit */ raw_inc_sp(STACK_SHADOW_SPACE); unlock2(r); } -MENDFUNC(1,call_r,(RR4 r)) /* Clobbering is implicit */ MIDFUNC(2,sub_l_mi,(IMM d, IMM s)) { CLOBBER_SUB; raw_sub_l_mi(d,s) ; } -MENDFUNC(2,sub_l_mi,(IMM d, IMM s)) MIDFUNC(2,mov_l_mi,(IMM d, IMM s)) { CLOBBER_MOV; raw_mov_l_mi(d,s) ; } -MENDFUNC(2,mov_l_mi,(IMM d, IMM s)) MIDFUNC(2,mov_w_mi,(IMM d, IMM s)) { CLOBBER_MOV; raw_mov_w_mi(d,s) ; } -MENDFUNC(2,mov_w_mi,(IMM d, IMM s)) MIDFUNC(2,mov_b_mi,(IMM d, IMM s)) { CLOBBER_MOV; raw_mov_b_mi(d,s) ; } -MENDFUNC(2,mov_b_mi,(IMM d, IMM s)) MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) { @@ -314,7 +344,6 @@ MIDFUNC(2,rol_b_ri,(RW1 r, IMM i)) raw_rol_b_ri(r,i); unlock2(r); } -MENDFUNC(2,rol_b_ri,(RW1 r, IMM i)) MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) { @@ -325,7 +354,6 @@ MIDFUNC(2,rol_w_ri,(RW2 r, IMM i)) raw_rol_w_ri(r,i); unlock2(r); } -MENDFUNC(2,rol_w_ri,(RW2 r, IMM i)) MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) { @@ -336,49 +364,46 @@ MIDFUNC(2,rol_l_ri,(RW4 r, IMM i)) raw_rol_l_ri(r,i); unlock2(r); } -MENDFUNC(2,rol_l_ri,(RW4 r, IMM i)) MIDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(rol_l_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_ROL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,4,4); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_rol_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in rol_l_rr",r); } raw_rol_l_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,rol_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(rol_w_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_ROL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,2,2); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_rol_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in rol_w_rr",r); } raw_rol_w_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,rol_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(rol_b_ri)(d,(uae_u8)live.state[r].val); return; } @@ -386,57 +411,54 @@ MIDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) CLOBBER_ROL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,1,1); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_rol_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in rol_b_rr",r); } raw_rol_b_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,rol_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shll_l_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_SHLL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,4,4); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_rol_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shll_l_rr",r); } raw_shll_l_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shll_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shll_w_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_SHLL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,2,2); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_shll_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shll_w_rr",r); } raw_shll_w_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shll_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shll_b_ri)(d,(uae_u8)live.state[r].val); return; } @@ -444,14 +466,13 @@ MIDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) CLOBBER_SHLL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,1,1); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_shll_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shll_b_rr",r); } raw_shll_b_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shll_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) @@ -463,7 +484,6 @@ MIDFUNC(2,ror_b_ri,(RR1 r, IMM i)) raw_ror_b_ri(r,i); unlock2(r); } -MENDFUNC(2,ror_b_ri,(RR1 r, IMM i)) MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) { @@ -474,7 +494,6 @@ MIDFUNC(2,ror_w_ri,(RR2 r, IMM i)) raw_ror_w_ri(r,i); unlock2(r); } -MENDFUNC(2,ror_w_ri,(RR2 r, IMM i)) MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) { @@ -485,11 +504,10 @@ MIDFUNC(2,ror_l_ri,(RR4 r, IMM i)) raw_ror_l_ri(r,i); unlock2(r); } -MENDFUNC(2,ror_l_ri,(RR4 r, IMM i)) MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(ror_l_ri)(d,(uae_u8)live.state[r].val); return; } @@ -500,11 +518,10 @@ MIDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,ror_l_rr,(RR4 d, RR1 r)) MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(ror_w_ri)(d,(uae_u8)live.state[r].val); return; } @@ -515,11 +532,10 @@ MIDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,ror_w_rr,(RR2 d, RR1 r)) MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(ror_b_ri)(d,(uae_u8)live.state[r].val); return; } @@ -531,49 +547,46 @@ MIDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) unlock2(r); unlock2(d); } -MENDFUNC(2,ror_b_rr,(RR1 d, RR1 r)) MIDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shrl_l_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_SHRL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,4,4); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_rol_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shrl_l_rr",r); } raw_shrl_l_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shrl_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shrl_w_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_SHRL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,2,2); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_shrl_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shrl_w_rr",r); } raw_shrl_w_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shrl_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shrl_b_ri)(d,(uae_u8)live.state[r].val); return; } @@ -581,14 +594,13 @@ MIDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) CLOBBER_SHRL; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,1,1); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_shrl_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shrl_b_rr",r); } raw_shrl_b_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shrl_b_rr,(RW1 d, RR1 r)) @@ -605,7 +617,6 @@ MIDFUNC(2,shll_l_ri,(RW4 r, IMM i)) raw_shll_l_ri(r,i); unlock2(r); } -MENDFUNC(2,shll_l_ri,(RW4 r, IMM i)) MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) { @@ -616,7 +627,6 @@ MIDFUNC(2,shll_w_ri,(RW2 r, IMM i)) raw_shll_w_ri(r,i); unlock2(r); } -MENDFUNC(2,shll_w_ri,(RW2 r, IMM i)) MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) { @@ -627,7 +637,6 @@ MIDFUNC(2,shll_b_ri,(RW1 r, IMM i)) raw_shll_b_ri(r,i); unlock2(r); } -MENDFUNC(2,shll_b_ri,(RW1 r, IMM i)) MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) { @@ -642,7 +651,6 @@ MIDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) raw_shrl_l_ri(r,i); unlock2(r); } -MENDFUNC(2,shrl_l_ri,(RW4 r, IMM i)) MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) { @@ -653,7 +661,6 @@ MIDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) raw_shrl_w_ri(r,i); unlock2(r); } -MENDFUNC(2,shrl_w_ri,(RW2 r, IMM i)) MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) { @@ -664,7 +671,6 @@ MIDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) raw_shrl_b_ri(r,i); unlock2(r); } -MENDFUNC(2,shrl_b_ri,(RW1 r, IMM i)) MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) { @@ -675,7 +681,6 @@ MIDFUNC(2,shra_l_ri,(RW4 r, IMM i)) raw_shra_l_ri(r,i); unlock2(r); } -MENDFUNC(2,shra_l_ri,(RW4 r, IMM i)) MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) { @@ -686,7 +691,6 @@ MIDFUNC(2,shra_w_ri,(RW2 r, IMM i)) raw_shra_w_ri(r,i); unlock2(r); } -MENDFUNC(2,shra_w_ri,(RW2 r, IMM i)) MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) { @@ -697,49 +701,46 @@ MIDFUNC(2,shra_b_ri,(RW1 r, IMM i)) raw_shra_b_ri(r,i); unlock2(r); } -MENDFUNC(2,shra_b_ri,(RW1 r, IMM i)) MIDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) { - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shra_l_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_SHRA; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,4,4); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_rol_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shra_l_rr",r); } raw_shra_l_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shra_l_rr,(RW4 d, RR1 r)) MIDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shra_w_ri)(d,(uae_u8)live.state[r].val); return; } CLOBBER_SHRA; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,2,2); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_shra_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shra_w_rr",r); } raw_shra_w_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shra_w_rr,(RW2 d, RR1 r)) MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) { /* Can only do this with r==1, i.e. cl */ - if (isconst(r)) { + if (isconst(r) && (uae_u8)live.state[r].val != 0) { COMPCALL(shra_b_ri)(d,(uae_u8)live.state[r].val); return; } @@ -747,14 +748,13 @@ MIDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) CLOBBER_SHRA; r=readreg_specific(r,1,SHIFTCOUNT_NREG); d=rmw(d,1,1); - Dif (r!=1) { - jit_abort("Illegal register %d in raw_shra_b",r); + Dif (r!=X86_CL) { + jit_abort("Illegal register %d in shra_b_rr",r); } raw_shra_b_rr(d,r) ; unlock2(r); unlock2(d); } -MENDFUNC(2,shra_b_rr,(RW1 d, RR1 r)) MIDFUNC(2,setcc,(W1 d, IMM cc)) @@ -764,14 +764,12 @@ MIDFUNC(2,setcc,(W1 d, IMM cc)) raw_setcc(d,cc); unlock2(d); } -MENDFUNC(2,setcc,(W1 d, IMM cc)) MIDFUNC(2,setcc_m,(IMM d, IMM cc)) { CLOBBER_SETCC; raw_setcc_m(d,cc); } -MENDFUNC(2,setcc_m,(IMM d, IMM cc)) MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) { @@ -784,7 +782,6 @@ MIDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) unlock2(s); unlock2(d); } -MENDFUNC(3,cmov_l_rr,(RW4 d, RR4 s, IMM cc)) MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) { @@ -793,7 +790,6 @@ MIDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) raw_cmov_l_rm(d,s,cc); unlock2(d); } -MENDFUNC(3,cmov_l_rm,(RW4 d, IMM s, IMM cc)) MIDFUNC(2,bsf_l_rr,(W4 d, RR4 s)) { @@ -804,7 +800,6 @@ MIDFUNC(2,bsf_l_rr,(W4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,bsf_l_rr,(W4 d, RR4 s)) /* Set the Z flag depending on the value in s. Note that the value has to be 0 or -1 (or, more precisely, for non-zero @@ -818,7 +813,6 @@ MIDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) unlock2(tmp); unlock2(s); } -MENDFUNC(2,simulate_bsf,(W4 tmp, RW4 s)) MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) { @@ -829,7 +823,6 @@ MIDFUNC(2,imul_32_32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,imul_32_32,(RW4 d, RR4 s)) MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) { @@ -840,7 +833,6 @@ MIDFUNC(2,imul_64_32,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,imul_64_32,(RW4 d, RW4 s)) MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) { @@ -851,7 +843,6 @@ MIDFUNC(2,mul_64_32,(RW4 d, RW4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,mul_64_32,(RW4 d, RW4 s)) MIDFUNC(2,mul_32_32,(RW4 d, RR4 s)) { @@ -862,7 +853,6 @@ MIDFUNC(2,mul_32_32,(RW4 d, RR4 s)) unlock2(s); unlock2(d); } -MENDFUNC(2,mul_32_32,(RW4 d, RR4 s)) #if SIZEOF_VOID_P == 8 MIDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s)) @@ -893,7 +883,6 @@ MIDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s)) unlock2(s); } } -MENDFUNC(2,sign_extend_32_rr,(W4 d, RR2 s)) #endif MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) @@ -924,7 +913,6 @@ MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) unlock2(s); } } -MENDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s)) MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) { @@ -956,7 +944,6 @@ MIDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) unlock2(s); } } -MENDFUNC(2,sign_extend_8_rr,(W4 d, RR1 s)) MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) @@ -987,7 +974,6 @@ MIDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) unlock2(s); } } -MENDFUNC(2,zero_extend_16_rr,(W4 d, RR2 s)) MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) { @@ -1018,7 +1004,6 @@ MIDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) unlock2(s); } } -MENDFUNC(2,zero_extend_8_rr,(W4 d, RR1 s)) MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) { @@ -1036,7 +1021,6 @@ MIDFUNC(2,mov_b_rr,(W1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,mov_b_rr,(W1 d, RR1 s)) MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) { @@ -1054,7 +1038,6 @@ MIDFUNC(2,mov_w_rr,(W2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,mov_w_rr,(W2 d, RR2 s)) MIDFUNC(4,mov_l_rrm_indexed,(W4 d,RR4 baser, RR4 index, IMM factor)) { @@ -1068,7 +1051,6 @@ MIDFUNC(4,mov_l_rrm_indexed,(W4 d,RR4 baser, RR4 index, IMM factor)) unlock2(baser); unlock2(index); } -MENDFUNC(4,mov_l_rrm_indexed,(W4 d,RR4 baser, RR4 index, IMM factor)) MIDFUNC(4,mov_w_rrm_indexed,(W2 d, RR4 baser, RR4 index, IMM factor)) { @@ -1082,7 +1064,6 @@ MIDFUNC(4,mov_w_rrm_indexed,(W2 d, RR4 baser, RR4 index, IMM factor)) unlock2(baser); unlock2(index); } -MENDFUNC(4,mov_w_rrm_indexed,(W2 d, RR4 baser, RR4 index, IMM factor)) MIDFUNC(4,mov_b_rrm_indexed,(W1 d, RR4 baser, RR4 index, IMM factor)) { @@ -1097,7 +1078,6 @@ MIDFUNC(4,mov_b_rrm_indexed,(W1 d, RR4 baser, RR4 index, IMM factor)) unlock2(baser); unlock2(index); } -MENDFUNC(4,mov_b_rrm_indexed,(W1 d, RR4 baser, RR4 index, IMM factor)) MIDFUNC(4,mov_l_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR4 s)) @@ -1116,7 +1096,6 @@ MIDFUNC(4,mov_l_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR4 s)) unlock2(baser); unlock2(index); } -MENDFUNC(4,mov_l_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR4 s)) MIDFUNC(4,mov_w_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR2 s)) { @@ -1130,7 +1109,6 @@ MIDFUNC(4,mov_w_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR2 s)) unlock2(baser); unlock2(index); } -MENDFUNC(4,mov_w_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR2 s)) MIDFUNC(4,mov_b_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR1 s)) { @@ -1144,7 +1122,6 @@ MIDFUNC(4,mov_b_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR1 s)) unlock2(baser); unlock2(index); } -MENDFUNC(4,mov_b_mrr_indexed,(RR4 baser, RR4 index, IMM factor, RR1 s)) MIDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s)) @@ -1165,7 +1142,6 @@ MIDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s) unlock2(baser); unlock2(index); } -MENDFUNC(5,mov_l_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s)) MIDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s)) { @@ -1185,7 +1161,6 @@ MIDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s) unlock2(baser); unlock2(index); } -MENDFUNC(5,mov_w_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s)) MIDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s)) { @@ -1205,7 +1180,6 @@ MIDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s) unlock2(baser); unlock2(index); } -MENDFUNC(5,mov_b_bmrr_indexed,(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s)) @@ -1226,7 +1200,6 @@ MIDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, RR4 baser, RR4 index, IMM factor)) unlock2(baser); unlock2(index); } -MENDFUNC(5,mov_l_brrm_indexed,(W4 d, IMM base, RR4 baser, RR4 index, IMM factor)) MIDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor)) @@ -1246,7 +1219,6 @@ MIDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor)) unlock2(baser); unlock2(index); } -MENDFUNC(5,mov_w_brrm_indexed,(W2 d, IMM base, RR4 baser, RR4 index, IMM factor)) MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor)) @@ -1266,7 +1238,6 @@ MIDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor)) unlock2(baser); unlock2(index); } -MENDFUNC(5,mov_b_brrm_indexed,(W1 d, IMM base, RR4 baser, RR4 index, IMM factor)) /* Read a long from base+factor*index */ MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) @@ -1287,7 +1258,6 @@ MIDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) unlock2(index); unlock2(d); } -MENDFUNC(4,mov_l_rm_indexed,(W4 d, IMM base, RR4 index, IMM factor)) /* read the long at the address contained in s+offset and store in d */ MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) @@ -1304,7 +1274,6 @@ MIDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_rR,(W4 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) @@ -1321,7 +1290,6 @@ MIDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_rR,(W2 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset)) @@ -1338,7 +1306,6 @@ MIDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_b_rR,(W1 d, RR4 s, IMM offset)) /* read the long at the address contained in s+offset and store in d */ MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) @@ -1357,7 +1324,6 @@ MIDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_brR,(W4 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) @@ -1377,7 +1343,6 @@ MIDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_brR,(W2 d, RR4 s, IMM offset)) /* read the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) @@ -1397,7 +1362,6 @@ MIDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_b_brR,(W1 d, RR4 s, IMM offset)) MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) { @@ -1413,7 +1377,6 @@ MIDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) raw_mov_l_Ri(d,i,offset); unlock2(d); } -MENDFUNC(3,mov_l_Ri,(RR4 d, IMM i, IMM offset)) MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) { @@ -1429,7 +1392,6 @@ MIDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) raw_mov_w_Ri(d,i,offset); unlock2(d); } -MENDFUNC(3,mov_w_Ri,(RR4 d, IMM i, IMM offset)) MIDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset)) { @@ -1445,7 +1407,6 @@ MIDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset)) raw_mov_b_Ri(d,i,offset); unlock2(d); } -MENDFUNC(3,mov_b_Ri,(RR4 d, IMM i, IMM offset)) /* Warning! OFFSET is byte sized only! */ MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) @@ -1467,7 +1428,6 @@ MIDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_Rr,(RR4 d, RR4 s, IMM offset)) MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) { @@ -1487,7 +1447,6 @@ MIDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_Rr,(RR4 d, RR2 s, IMM offset)) MIDFUNC(3,mov_b_Rr,(RR4 d, RR1 s, IMM offset)) { @@ -1507,7 +1466,6 @@ MIDFUNC(3,mov_b_Rr,(RR4 d, RR1 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_b_Rr,(RR4 d, RR1 s, IMM offset)) MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) { @@ -1528,7 +1486,6 @@ MIDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,lea_l_brr,(W4 d, RR4 s, IMM offset)) MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) { @@ -1546,7 +1503,6 @@ MIDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) unlock2(index); unlock2(s); } -MENDFUNC(5,lea_l_brr_indexed,(W4 d, RR4 s, RR4 index, IMM factor, IMM offset)) MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) { @@ -1560,7 +1516,6 @@ MIDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) unlock2(index); unlock2(s); } -MENDFUNC(4,lea_l_rr_indexed,(W4 d, RR4 s, RR4 index, IMM factor)) /* write d to the long at the address contained in s+offset */ MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) @@ -1580,7 +1535,6 @@ MIDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_l_bRr,(RR4 d, RR4 s, IMM offset)) /* write the word at the address contained in s+offset and store in d */ MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) @@ -1600,7 +1554,6 @@ MIDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_w_bRr,(RR4 d, RR2 s, IMM offset)) MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) { @@ -1618,7 +1571,6 @@ MIDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) unlock2(d); unlock2(s); } -MENDFUNC(3,mov_b_bRr,(RR4 d, RR1 s, IMM offset)) MIDFUNC(1,mid_bswap_32,(RW4 r)) { @@ -1634,7 +1586,6 @@ MIDFUNC(1,mid_bswap_32,(RW4 r)) raw_bswap_32(r); unlock2(r); } -MENDFUNC(1,mid_bswap_32,(RW4 r)) MIDFUNC(1,mid_bswap_16,(RW2 r)) { @@ -1650,7 +1601,6 @@ MIDFUNC(1,mid_bswap_16,(RW2 r)) raw_bswap_16(r); unlock2(r); } -MENDFUNC(1,mid_bswap_16,(RW2 r)) @@ -1681,7 +1631,6 @@ MIDFUNC(2,mov_l_rr,(W4 d, RR4 s)) jit_log2("Added %d to nreg %d(%d), now holds %d regs", d,s,live.state[d].realind,live.nat[s].nholds); unlock2(s); } -MENDFUNC(2,mov_l_rr,(W4 d, RR4 s)) MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) { @@ -1695,7 +1644,6 @@ MIDFUNC(2,mov_l_mr,(IMM d, RR4 s)) raw_mov_l_mr(d,s); unlock2(s); } -MENDFUNC(2,mov_l_mr,(IMM d, RR4 s)) MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) @@ -1710,7 +1658,6 @@ MIDFUNC(2,mov_w_mr,(IMM d, RR2 s)) raw_mov_w_mr(d,s); unlock2(s); } -MENDFUNC(2,mov_w_mr,(IMM d, RR2 s)) MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) { @@ -1720,7 +1667,6 @@ MIDFUNC(2,mov_w_rm,(W2 d, IMM s)) raw_mov_w_rm(d,s); unlock2(d); } -MENDFUNC(2,mov_w_rm,(W2 d, IMM s)) MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) { @@ -1735,7 +1681,6 @@ MIDFUNC(2,mov_b_mr,(IMM d, RR1 s)) raw_mov_b_mr(d,s); unlock2(s); } -MENDFUNC(2,mov_b_mr,(IMM d, RR1 s)) MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) { @@ -1745,14 +1690,12 @@ MIDFUNC(2,mov_b_rm,(W1 d, IMM s)) raw_mov_b_rm(d,s); unlock2(d); } -MENDFUNC(2,mov_b_rm,(W1 d, IMM s)) MIDFUNC(2,mov_l_ri,(W4 d, IMM s)) { set_const(d,s); return; } -MENDFUNC(2,mov_l_ri,(W4 d, IMM s)) MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) { @@ -1762,7 +1705,6 @@ MIDFUNC(2,mov_w_ri,(W2 d, IMM s)) raw_mov_w_ri(d,s); unlock2(d); } -MENDFUNC(2,mov_w_ri,(W2 d, IMM s)) MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) { @@ -1772,28 +1714,24 @@ MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) raw_mov_b_ri(d,s); unlock2(d); } -MENDFUNC(2,mov_b_ri,(W1 d, IMM s)) MIDFUNC(2,add_l_mi,(IMM d, IMM s)) { CLOBBER_ADD; raw_add_l_mi(d,s) ; } -MENDFUNC(2,add_l_mi,(IMM d, IMM s)) MIDFUNC(2,add_w_mi,(IMM d, IMM s)) { CLOBBER_ADD; raw_add_w_mi(d,s) ; } -MENDFUNC(2,add_w_mi,(IMM d, IMM s)) MIDFUNC(2,add_b_mi,(IMM d, IMM s)) { CLOBBER_ADD; raw_add_b_mi(d,s) ; } -MENDFUNC(2,add_b_mi,(IMM d, IMM s)) MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) { @@ -1803,7 +1741,6 @@ MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) raw_test_l_ri(d,i); unlock2(d); } -MENDFUNC(2,test_l_ri,(RR4 d, IMM i)) MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) { @@ -1815,7 +1752,6 @@ MIDFUNC(2,test_l_rr,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,test_l_rr,(RR4 d, RR4 s)) MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) { @@ -1827,7 +1763,6 @@ MIDFUNC(2,test_w_rr,(RR2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,test_w_rr,(RR2 d, RR2 s)) MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) { @@ -1839,7 +1774,6 @@ MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,test_b_rr,(RR1 d, RR1 s)) MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) @@ -1855,7 +1789,6 @@ MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) raw_and_l_ri(d,i); unlock2(d); } -MENDFUNC(2,and_l_ri,(RW4 d, IMM i)) MIDFUNC(2,and_l,(RW4 d, RR4 s)) { @@ -1867,7 +1800,6 @@ MIDFUNC(2,and_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,and_l,(RW4 d, RR4 s)) MIDFUNC(2,and_w,(RW2 d, RR2 s)) { @@ -1879,7 +1811,6 @@ MIDFUNC(2,and_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,and_w,(RW2 d, RR2 s)) MIDFUNC(2,and_b,(RW1 d, RR1 s)) { @@ -1891,7 +1822,6 @@ MIDFUNC(2,and_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,and_b,(RW1 d, RR1 s)) // gb-- used for making an fpcr value in compemu_fpp.cpp MIDFUNC(2,or_l_rm,(RW4 d, IMM s)) @@ -1902,7 +1832,6 @@ MIDFUNC(2,or_l_rm,(RW4 d, IMM s)) raw_or_l_rm(d,s); unlock2(d); } -MENDFUNC(2,or_l_rm,(RW4 d, IMM s)) MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) { @@ -1916,7 +1845,6 @@ MIDFUNC(2,or_l_ri,(RW4 d, IMM i)) raw_or_l_ri(d,i); unlock2(d); } -MENDFUNC(2,or_l_ri,(RW4 d, IMM i)) MIDFUNC(2,or_l,(RW4 d, RR4 s)) { @@ -1932,7 +1860,6 @@ MIDFUNC(2,or_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,or_l,(RW4 d, RR4 s)) MIDFUNC(2,or_w,(RW2 d, RR2 s)) { @@ -1944,7 +1871,6 @@ MIDFUNC(2,or_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,or_w,(RW2 d, RR2 s)) MIDFUNC(2,or_b,(RW1 d, RR1 s)) { @@ -1956,7 +1882,6 @@ MIDFUNC(2,or_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,or_b,(RW1 d, RR1 s)) MIDFUNC(2,adc_l,(RW4 d, RR4 s)) { @@ -1969,7 +1894,6 @@ MIDFUNC(2,adc_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,adc_l,(RW4 d, RR4 s)) MIDFUNC(2,adc_w,(RW2 d, RR2 s)) { @@ -1981,7 +1905,6 @@ MIDFUNC(2,adc_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,adc_w,(RW2 d, RR2 s)) MIDFUNC(2,adc_b,(RW1 d, RR1 s)) { @@ -1993,7 +1916,6 @@ MIDFUNC(2,adc_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,adc_b,(RW1 d, RR1 s)) MIDFUNC(2,add_l,(RW4 d, RR4 s)) { @@ -2011,7 +1933,6 @@ MIDFUNC(2,add_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,add_l,(RW4 d, RR4 s)) MIDFUNC(2,add_w,(RW2 d, RR2 s)) { @@ -2028,7 +1949,6 @@ MIDFUNC(2,add_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,add_w,(RW2 d, RR2 s)) MIDFUNC(2,add_b,(RW1 d, RR1 s)) { @@ -2045,7 +1965,6 @@ MIDFUNC(2,add_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,add_b,(RW1 d, RR1 s)) MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) { @@ -2068,7 +1987,6 @@ MIDFUNC(2,sub_l_ri,(RW4 d, IMM i)) raw_sub_l_ri(d,i); unlock2(d); } -MENDFUNC(2,sub_l_ri,(RW4 d, IMM i)) MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) { @@ -2081,7 +1999,6 @@ MIDFUNC(2,sub_w_ri,(RW2 d, IMM i)) raw_sub_w_ri(d,i); unlock2(d); } -MENDFUNC(2,sub_w_ri,(RW2 d, IMM i)) MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) { @@ -2095,7 +2012,6 @@ MIDFUNC(2,sub_b_ri,(RW1 d, IMM i)) unlock2(d); } -MENDFUNC(2,sub_b_ri,(RW1 d, IMM i)) MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) { @@ -2116,7 +2032,6 @@ MIDFUNC(2,add_l_ri,(RW4 d, IMM i)) raw_add_l_ri(d,i); unlock2(d); } -MENDFUNC(2,add_l_ri,(RW4 d, IMM i)) MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) { @@ -2129,7 +2044,6 @@ MIDFUNC(2,add_w_ri,(RW2 d, IMM i)) raw_add_w_ri(d,i); unlock2(d); } -MENDFUNC(2,add_w_ri,(RW2 d, IMM i)) MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) { @@ -2143,7 +2057,6 @@ MIDFUNC(2,add_b_ri,(RW1 d, IMM i)) unlock2(d); } -MENDFUNC(2,add_b_ri,(RW1 d, IMM i)) MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) { @@ -2155,7 +2068,6 @@ MIDFUNC(2,sbb_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sbb_l,(RW4 d, RR4 s)) MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) { @@ -2167,7 +2079,6 @@ MIDFUNC(2,sbb_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sbb_w,(RW2 d, RR2 s)) MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) { @@ -2179,7 +2090,6 @@ MIDFUNC(2,sbb_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sbb_b,(RW1 d, RR1 s)) MIDFUNC(2,sub_l,(RW4 d, RR4 s)) { @@ -2196,7 +2106,6 @@ MIDFUNC(2,sub_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sub_l,(RW4 d, RR4 s)) MIDFUNC(2,sub_w,(RW2 d, RR2 s)) { @@ -2213,7 +2122,6 @@ MIDFUNC(2,sub_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sub_w,(RW2 d, RR2 s)) MIDFUNC(2,sub_b,(RW1 d, RR1 s)) { @@ -2230,7 +2138,6 @@ MIDFUNC(2,sub_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,sub_b,(RW1 d, RR1 s)) MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) { @@ -2242,7 +2149,6 @@ MIDFUNC(2,cmp_l,(RR4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,cmp_l,(RR4 d, RR4 s)) MIDFUNC(2,cmp_l_ri,(RR4 r, IMM i)) { @@ -2252,7 +2158,6 @@ MIDFUNC(2,cmp_l_ri,(RR4 r, IMM i)) raw_cmp_l_ri(r,i); unlock2(r); } -MENDFUNC(2,cmp_l_ri,(RR4 r, IMM i)) MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) { @@ -2264,7 +2169,6 @@ MIDFUNC(2,cmp_w,(RR2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,cmp_w,(RR2 d, RR2 s)) MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) { @@ -2276,7 +2180,6 @@ MIDFUNC(2,cmp_b,(RR1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,cmp_b,(RR1 d, RR1 s)) MIDFUNC(2,xor_l,(RW4 d, RR4 s)) @@ -2289,7 +2192,6 @@ MIDFUNC(2,xor_l,(RW4 d, RR4 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,xor_l,(RW4 d, RR4 s)) MIDFUNC(2,xor_w,(RW2 d, RR2 s)) { @@ -2301,7 +2203,6 @@ MIDFUNC(2,xor_w,(RW2 d, RR2 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,xor_w,(RW2 d, RR2 s)) MIDFUNC(2,xor_b,(RW1 d, RR1 s)) { @@ -2313,7 +2214,6 @@ MIDFUNC(2,xor_b,(RW1 d, RR1 s)) unlock2(d); unlock2(s); } -MENDFUNC(2,xor_b,(RW1 d, RR1 s)) MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) { @@ -2360,7 +2260,6 @@ MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) live.state[out1].dirtysize=osize; set_status(out1,DIRTY); } -MENDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) { @@ -2387,7 +2286,6 @@ MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) raw_inc_sp(8); #endif } -MENDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) /* forget_about() takes a mid-layer register */ MIDFUNC(1,forget_about,(W4 r)) @@ -2397,13 +2295,11 @@ MIDFUNC(1,forget_about,(W4 r)) live.state[r].val=0; set_status(r,UNDEF); } -MENDFUNC(1,forget_about,(W4 r)) MIDFUNC(0,nop,(void)) { raw_emit_nop(); } -MENDFUNC(0,nop,(void)) MIDFUNC(1,f_forget_about,(FW r)) { @@ -2411,7 +2307,6 @@ MIDFUNC(1,f_forget_about,(FW r)) f_disassociate(r); live.fate[r].status=UNDEF; } -MENDFUNC(1,f_forget_about,(FW r)) MIDFUNC(1,fmov_pi,(FW r)) { @@ -2419,7 +2314,6 @@ MIDFUNC(1,fmov_pi,(FW r)) raw_fmov_pi(r); f_unlock(r); } -MENDFUNC(1,fmov_pi,(FW r)) MIDFUNC(1,fmov_log10_2,(FW r)) { @@ -2427,7 +2321,6 @@ MIDFUNC(1,fmov_log10_2,(FW r)) raw_fmov_log10_2(r); f_unlock(r); } -MENDFUNC(1,fmov_log10_2,(FW r)) MIDFUNC(1,fmov_log2_e,(FW r)) { @@ -2435,7 +2328,6 @@ MIDFUNC(1,fmov_log2_e,(FW r)) raw_fmov_log2_e(r); f_unlock(r); } -MENDFUNC(1,fmov_log2_e,(FW r)) MIDFUNC(1,fmov_loge_2,(FW r)) { @@ -2443,7 +2335,6 @@ MIDFUNC(1,fmov_loge_2,(FW r)) raw_fmov_loge_2(r); f_unlock(r); } -MENDFUNC(1,fmov_loge_2,(FW r)) MIDFUNC(1,fmov_1,(FW r)) { @@ -2451,7 +2342,6 @@ MIDFUNC(1,fmov_1,(FW r)) raw_fmov_1(r); f_unlock(r); } -MENDFUNC(1,fmov_1,(FW r)) MIDFUNC(1,fmov_0,(FW r)) { @@ -2459,55 +2349,48 @@ MIDFUNC(1,fmov_0,(FW r)) raw_fmov_0(r); f_unlock(r); } -MENDFUNC(1,fmov_0,(FW r)) -MIDFUNC(2,fmov_rm,(FW r, MEMR m)) +MIDFUNC(2,fmov_rm,(FW r, MEMPTRR m)) { r=f_writereg(r); raw_fmov_rm(r,m); f_unlock(r); } -MENDFUNC(2,fmov_rm,(FW r, MEMR m)) -MIDFUNC(2,fmovi_rm,(FW r, MEMR m)) +MIDFUNC(2,fmovi_rm,(FW r, MEMPTRR m)) { r=f_writereg(r); raw_fmovi_rm(r,m); f_unlock(r); } -MENDFUNC(2,fmovi_rm,(FW r, MEMR m)) -MIDFUNC(2,fmovi_mr,(MEMW m, FR r)) +MIDFUNC(2,fmovi_mr,(MEMPTRW m, FR r)) { r=f_readreg(r); raw_fmovi_mr(m,r); f_unlock(r); } -MENDFUNC(2,fmovi_mr,(MEMW m, FR r)) -MIDFUNC(3,fmovi_mrb,(MEMW m, FR r, double *bounds)) +MIDFUNC(3,fmovi_mrb,(MEMPTRW m, FR r, double *bounds)) { r=f_readreg(r); raw_fmovi_mrb(m,r,bounds); f_unlock(r); } -MENDFUNC(3,fmovi_mrb,(MEMW m, FR r, double *bounds)) -MIDFUNC(2,fmovs_rm,(FW r, MEMR m)) +MIDFUNC(2,fmovs_rm,(FW r, MEMPTRR m)) { r=f_writereg(r); raw_fmovs_rm(r,m); f_unlock(r); } -MENDFUNC(2,fmovs_rm,(FW r, MEMR m)) -MIDFUNC(2,fmovs_mr,(MEMW m, FR r)) +MIDFUNC(2,fmovs_mr,(MEMPTRW m, FR r)) { r=f_readreg(r); raw_fmovs_mr(m,r); f_unlock(r); } -MENDFUNC(2,fmovs_mr,(MEMW m, FR r)) MIDFUNC(1,fcuts_r,(FRW r)) { @@ -2515,7 +2398,6 @@ MIDFUNC(1,fcuts_r,(FRW r)) raw_fcuts_r(r); f_unlock(r); } -MENDFUNC(1,fcuts_r,(FRW r)) MIDFUNC(1,fcut_r,(FRW r)) { @@ -2523,31 +2405,27 @@ MIDFUNC(1,fcut_r,(FRW r)) raw_fcut_r(r); f_unlock(r); } -MENDFUNC(1,fcut_r,(FRW r)) -MIDFUNC(2,fmov_ext_mr,(MEMW m, FR r)) +MIDFUNC(2,fmov_ext_mr,(MEMPTRW m, FR r)) { r=f_readreg(r); raw_fmov_ext_mr(m,r); f_unlock(r); } -MENDFUNC(2,fmov_ext_mr,(MEMW m, FR r)) -MIDFUNC(2,fmov_mr,(MEMW m, FR r)) +MIDFUNC(2,fmov_mr,(MEMPTRW m, FR r)) { r=f_readreg(r); raw_fmov_mr(m,r); f_unlock(r); } -MENDFUNC(2,fmov_mr,(MEMW m, FR r)) -MIDFUNC(2,fmov_ext_rm,(FW r, MEMR m)) +MIDFUNC(2,fmov_ext_rm,(FW r, MEMPTRR m)) { r=f_writereg(r); raw_fmov_ext_rm(r,m); f_unlock(r); } -MENDFUNC(2,fmov_ext_rm,(FW r, MEMR m)) MIDFUNC(2,fmov_rr,(FW d, FR s)) { @@ -2571,7 +2449,6 @@ MIDFUNC(2,fmov_rr,(FW d, FR s)) f_unlock(d); #endif } -MENDFUNC(2,fmov_rr,(FW d, FR s)) MIDFUNC(2,fldcw_m_indexed,(RR4 index, IMM base)) { @@ -2580,7 +2457,6 @@ MIDFUNC(2,fldcw_m_indexed,(RR4 index, IMM base)) raw_fldcw_m_indexed(index,base); unlock2(index); } -MENDFUNC(2,fldcw_m_indexed,(RR4 index, IMM base)) MIDFUNC(1,ftst_r,(FR r)) { @@ -2588,13 +2464,11 @@ MIDFUNC(1,ftst_r,(FR r)) raw_ftst_r(r); f_unlock(r); } -MENDFUNC(1,ftst_r,(FR r)) MIDFUNC(0,dont_care_fflags,(void)) { f_disassociate(FP_RESULT); } -MENDFUNC(0,dont_care_fflags,(void)) MIDFUNC(2,fsqrt_rr,(FW d, FR s)) { @@ -2604,7 +2478,6 @@ MIDFUNC(2,fsqrt_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fsqrt_rr,(FW d, FR s)) MIDFUNC(2,fabs_rr,(FW d, FR s)) { @@ -2614,7 +2487,6 @@ MIDFUNC(2,fabs_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fabs_rr,(FW d, FR s)) MIDFUNC(2,fgetexp_rr,(FW d, FR s)) { @@ -2624,7 +2496,6 @@ MIDFUNC(2,fgetexp_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fgetexp_rr,(FW d, FR s)) MIDFUNC(2,fgetman_rr,(FW d, FR s)) { @@ -2634,7 +2505,6 @@ MIDFUNC(2,fgetman_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fgetman_rr,(FW d, FR s)) MIDFUNC(2,fsin_rr,(FW d, FR s)) { @@ -2644,7 +2514,6 @@ MIDFUNC(2,fsin_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fsin_rr,(FW d, FR s)) MIDFUNC(2,fcos_rr,(FW d, FR s)) { @@ -2654,7 +2523,6 @@ MIDFUNC(2,fcos_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fcos_rr,(FW d, FR s)) MIDFUNC(2,ftan_rr,(FW d, FR s)) { @@ -2664,7 +2532,6 @@ MIDFUNC(2,ftan_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,ftan_rr,(FW d, FR s)) MIDFUNC(3,fsincos_rr,(FW d, FW c, FR s)) { @@ -2676,7 +2543,6 @@ MIDFUNC(3,fsincos_rr,(FW d, FW c, FR s)) f_unlock(d); f_unlock(c); } -MENDFUNC(3,fsincos_rr,(FW d, FW c, FR s)) MIDFUNC(2,fscale_rr,(FRW d, FR s)) { @@ -2686,7 +2552,6 @@ MIDFUNC(2,fscale_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fscale_rr,(FRW d, FR s)) MIDFUNC(2,ftwotox_rr,(FW d, FR s)) { @@ -2696,7 +2561,6 @@ MIDFUNC(2,ftwotox_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,ftwotox_rr,(FW d, FR s)) MIDFUNC(2,fetox_rr,(FW d, FR s)) { @@ -2706,7 +2570,6 @@ MIDFUNC(2,fetox_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fetox_rr,(FW d, FR s)) MIDFUNC(2,frndint_rr,(FW d, FR s)) { @@ -2716,7 +2579,6 @@ MIDFUNC(2,frndint_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,frndint_rr,(FW d, FR s)) MIDFUNC(2,fetoxM1_rr,(FW d, FR s)) { @@ -2726,7 +2588,6 @@ MIDFUNC(2,fetoxM1_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fetoxM1_rr,(FW d, FR s)) MIDFUNC(2,ftentox_rr,(FW d, FR s)) { @@ -2736,7 +2597,6 @@ MIDFUNC(2,ftentox_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,ftentox_rr,(FW d, FR s)) MIDFUNC(2,flog2_rr,(FW d, FR s)) { @@ -2746,7 +2606,6 @@ MIDFUNC(2,flog2_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,flog2_rr,(FW d, FR s)) MIDFUNC(2,flogN_rr,(FW d, FR s)) { @@ -2756,7 +2615,6 @@ MIDFUNC(2,flogN_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,flogN_rr,(FW d, FR s)) MIDFUNC(2,flogNP1_rr,(FW d, FR s)) { @@ -2766,7 +2624,6 @@ MIDFUNC(2,flogNP1_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,flogNP1_rr,(FW d, FR s)) MIDFUNC(2,flog10_rr,(FW d, FR s)) { @@ -2776,7 +2633,6 @@ MIDFUNC(2,flog10_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,flog10_rr,(FW d, FR s)) MIDFUNC(2,fasin_rr,(FW d, FR s)) { @@ -2786,7 +2642,6 @@ MIDFUNC(2,fasin_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fasin_rr,(FW d, FR s)) MIDFUNC(2,facos_rr,(FW d, FR s)) { @@ -2796,7 +2651,6 @@ MIDFUNC(2,facos_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,facos_rr,(FW d, FR s)) MIDFUNC(2,fatan_rr,(FW d, FR s)) { @@ -2806,7 +2660,6 @@ MIDFUNC(2,fatan_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fatan_rr,(FW d, FR s)) MIDFUNC(2,fatanh_rr,(FW d, FR s)) { @@ -2816,7 +2669,6 @@ MIDFUNC(2,fatanh_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fatanh_rr,(FW d, FR s)) MIDFUNC(2,fsinh_rr,(FW d, FR s)) { @@ -2826,7 +2678,6 @@ MIDFUNC(2,fsinh_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fsinh_rr,(FW d, FR s)) MIDFUNC(2,fcosh_rr,(FW d, FR s)) { @@ -2836,7 +2687,6 @@ MIDFUNC(2,fcosh_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fcosh_rr,(FW d, FR s)) MIDFUNC(2,ftanh_rr,(FW d, FR s)) { @@ -2846,7 +2696,6 @@ MIDFUNC(2,ftanh_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,ftanh_rr,(FW d, FR s)) MIDFUNC(2,fneg_rr,(FW d, FR s)) { @@ -2856,7 +2705,6 @@ MIDFUNC(2,fneg_rr,(FW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fneg_rr,(FW d, FR s)) MIDFUNC(2,fadd_rr,(FRW d, FR s)) { @@ -2866,7 +2714,6 @@ MIDFUNC(2,fadd_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fadd_rr,(FRW d, FR s)) MIDFUNC(2,fsub_rr,(FRW d, FR s)) { @@ -2876,7 +2723,6 @@ MIDFUNC(2,fsub_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fsub_rr,(FRW d, FR s)) MIDFUNC(2,fcmp_rr,(FR d, FR s)) { @@ -2886,7 +2732,6 @@ MIDFUNC(2,fcmp_rr,(FR d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fcmp_rr,(FR d, FR s)) MIDFUNC(2,fdiv_rr,(FRW d, FR s)) { @@ -2896,7 +2741,6 @@ MIDFUNC(2,fdiv_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fdiv_rr,(FRW d, FR s)) MIDFUNC(2,frem_rr,(FRW d, FR s)) { @@ -2906,7 +2750,6 @@ MIDFUNC(2,frem_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,frem_rr,(FRW d, FR s)) MIDFUNC(2,frem1_rr,(FRW d, FR s)) { @@ -2916,7 +2759,6 @@ MIDFUNC(2,frem1_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,frem1_rr,(FRW d, FR s)) MIDFUNC(2,fmul_rr,(FRW d, FR s)) { @@ -2926,7 +2768,6 @@ MIDFUNC(2,fmul_rr,(FRW d, FR s)) f_unlock(s); f_unlock(d); } -MENDFUNC(2,fmul_rr,(FRW d, FR s)) #ifdef __GNUC__ diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h index a0f5cf92..8476d947 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h @@ -185,6 +185,7 @@ DECLARE_MIDFUNC(xor_b(RW1 d, RR1 s)); DECLARE_MIDFUNC(live_flags(void)); DECLARE_MIDFUNC(dont_care_flags(void)); DECLARE_MIDFUNC(duplicate_carry(void)); +DECLARE_MIDFUNC(setcc_for_cntzero(RR4 d, RR4 data, int size)); DECLARE_MIDFUNC(restore_carry(void)); DECLARE_MIDFUNC(start_needflags(void)); DECLARE_MIDFUNC(end_needflags(void)); @@ -201,17 +202,17 @@ DECLARE_MIDFUNC(fmov_log2_e(FW r)); DECLARE_MIDFUNC(fmov_loge_2(FW r)); DECLARE_MIDFUNC(fmov_1(FW r)); DECLARE_MIDFUNC(fmov_0(FW r)); -DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmovi_mrb(MEMW m, FR r, double *bounds)); -DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m)); -DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r)); +DECLARE_MIDFUNC(fmov_rm(FW r, MEMPTRR m)); +DECLARE_MIDFUNC(fmov_mr(MEMPTRW m, FR r)); +DECLARE_MIDFUNC(fmovi_rm(FW r, MEMPTRR m)); +DECLARE_MIDFUNC(fmovi_mr(MEMPTRW m, FR r)); +DECLARE_MIDFUNC(fmovi_mrb(MEMPTRW m, FR r, double *bounds)); +DECLARE_MIDFUNC(fmovs_rm(FW r, MEMPTRR m)); +DECLARE_MIDFUNC(fmovs_mr(MEMPTRW m, FR r)); DECLARE_MIDFUNC(fcuts_r(FRW r)); DECLARE_MIDFUNC(fcut_r(FRW r)); -DECLARE_MIDFUNC(fmov_ext_mr(MEMW m, FR r)); -DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMR m)); +DECLARE_MIDFUNC(fmov_ext_mr(MEMPTRW m, FR r)); +DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMPTRR m)); DECLARE_MIDFUNC(fmov_rr(FW d, FR s)); DECLARE_MIDFUNC(fldcw_m_indexed(RR4 index, IMM base)); DECLARE_MIDFUNC(ftst_r(FR r)); diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index 068123b8..9b178c0f 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -43,12 +43,6 @@ #error "Only [LS]AHF scheme to [gs]et flags is supported with the JIT Compiler" #endif -//TODO: detect i386 and arm platforms - -#ifdef __x86_64__ -#define CPU_x86_64 1 -#endif - /* NOTE: support for AMD64 assumes translation cache and other code * buffers are allocated into a 32-bit address space because (i) B2/JIT * code is not 64-bit clean and (ii) it's faster to resolve branches @@ -72,7 +66,7 @@ #ifdef UAE #include "options.h" #include "events.h" -#include "memory.h" +#include "uae/memory.h" #include "custom.h" #else #include "cpu_emulation.h" @@ -88,11 +82,15 @@ #include "comptbl.h" #ifdef UAE #include "compemu.h" +#ifdef FSUAE +#include "codegen_udis86.h" +#endif #else #include "compiler/compemu.h" #include "fpu/fpu.h" #include "fpu/flags.h" // #include "parameters.h" +static void build_comp(void); #endif // #include "verify.h" @@ -100,10 +98,16 @@ // uae_log("JIT: " format "\n", ##__VA_ARGS__); #define D2 D - #ifdef UAE +#ifdef FSUAE +#include "uae/fs.h" +#endif #include "uae/log.h" +#if defined(__pie__) || defined (__PIE__) +#error Position-independent code (PIE) cannot be used with JIT +#endif + #include "uae/vm.h" #define VM_PAGE_READ UAE_VM_READ #define VM_PAGE_WRITE UAE_VM_WRITE @@ -149,6 +153,15 @@ static inline int distrust_check(int value) return 1; #else int distrust = value; +#ifdef FSUAE + switch (value) { + case 0: distrust = 0; break; + case 1: distrust = 1; break; + case 2: distrust = ((start_pc & 0xF80000) == 0xF80000); break; + case 3: distrust = !have_done_picasso; break; + default: abort(); + } +#endif return distrust; #endif } @@ -237,7 +250,7 @@ static clock_t emul_end_time = 0; #endif #ifdef PROFILE_UNTRANSLATED_INSNS -static const int untranslated_top_ten = 20; +static const int untranslated_top_ten = 50; static uae_u32 raw_cputbl_count[65536] = { 0, }; static uae_u16 opcode_nums[65536]; @@ -266,8 +279,10 @@ extern bool quit_program; // gb-- Extra data for Basilisk II/JIT #ifdef JIT_DEBUG static bool JITDebug = false; // Enable runtime disassemblers through mon? +// #define JITDebug bx_options.jit.jitdebug // Enable runtime disassemblers through mon? #else const bool JITDebug = false; +// #define JITDebug false // Don't use JIT debug mode at all #endif #if USE_INLINING #ifdef UAE @@ -283,6 +298,7 @@ const uae_u32 MIN_CACHE_SIZE = 1024; // Minimal translation cache size (1 MB) static uae_u32 cache_size = 0; // Size of total cache allocated for compiled blocks static uae_u32 current_cache_size = 0; // Cache grows upwards: how much has been consumed already static bool lazy_flush = true; // Flag: lazy translation cache invalidation +// Flag: compile FPU instructions ? #ifdef UAE #ifdef USE_JIT_FPU #define avoid_fpu (!currprefs.compfpu) @@ -291,6 +307,11 @@ static bool lazy_flush = true; // Flag: lazy translation cache invalidation #endif #else static bool avoid_fpu = true; // Flag: compile FPU instructions ? +// #ifdef USE_JIT_FPU +// #define avoid_fpu (!bx_options.jit.jitfpu) +// #else +// #define avoid_fpu (true) +// #endif #endif static bool have_cmov = false; // target has CMOV instructions ? static bool have_rat_stall = true; // target has partial register stalls ? @@ -370,10 +391,9 @@ static uintptr taken_pc_p; static int branch_cc; static int redo_current_block; +#ifdef UAE int segvcount=0; -int soft_flush_count=0; -int hard_flush_count=0; -int checksum_count=0; +#endif static uae_u8* current_compile_p=NULL; static uae_u8* max_compile_start; static uae_u8* compiled_code=NULL; @@ -395,7 +415,7 @@ static void* popall_check_checksum=NULL; * lists that we maintain for each hash result. */ static cacheline cache_tags[TAGSIZE]; -int letit=0; +static int cache_enabled=0; static blockinfo* hold_bi[MAX_HOLD_BI]; static blockinfo* active; static blockinfo* dormant; @@ -420,12 +440,10 @@ extern const struct cputbl op_smalltbl_4_nf[]; extern const struct cputbl op_smalltbl_5_nf[]; #endif -#ifdef WINUAE_ARANYM -static void flush_icache_hard(int n); -static void flush_icache_lazy(int n); -static void flush_icache_none(int n); -void (*flush_icache)(int n) = flush_icache_none; -#endif +static void flush_icache_hard(void); +static void flush_icache_lazy(void); +static void flush_icache_none(void); +void (*flush_icache)(void) = flush_icache_none; static bigstate live; static smallstate empty_ss; @@ -452,7 +470,7 @@ uae_u32 m68k_pc_offset; * side effects they would have on the flags are not important. This * variable indicates whether we need the side effects or not */ -uae_u32 needflags=0; +static uae_u32 needflags=0; /* Flag handling is complicated. * @@ -500,7 +518,7 @@ static inline blockinfo* get_blockinfo_addr(void* addr) /******************************************************************* * Disassembler support * *******************************************************************/ - + #define TARGET_M68K 0 #define TARGET_POWERPC 1 #define TARGET_X86 2 @@ -531,11 +549,11 @@ static void disasm_block(int disasm_target, const uint8 *start, size_t length) #if defined(HAVE_DISASM_M68K) { char buf[256]; - + disasm_info.memory_vma = ((memptr)((uintptr_t)(start) - MEMBaseDiff)); while (length > 0) { - int isize = m68k_disasm_to_buf(&disasm_info, buf); + int isize = m68k_disasm_to_buf(&disasm_info, buf, 1); bug("%s", buf); if (isize < 0) break; @@ -552,10 +570,10 @@ static void disasm_block(int disasm_target, const uint8 *start, size_t length) { const uint8 *end = start + length; char buf[256]; - + while (start < end) { - start = x86_disasm(start, buf); + start = x86_disasm(start, buf, 1); bug("%s", buf); } } @@ -566,10 +584,10 @@ static void disasm_block(int disasm_target, const uint8 *start, size_t length) { const uint8 *end = start + length; char buf[256]; - + while (start < end) { - start = arm_disasm(start, buf); + start = arm_disasm(start, buf, 1); bug("%s", buf); } } @@ -2640,8 +2658,10 @@ static scratch_t scratch; * Support functions exposed to newcpu * ********************************************************************/ -#define str_on_off(b) b ? "on" : "off" - +static inline const char *str_on_off(bool b) +{ + return b ? "on" : "off"; +} #ifdef UAE static @@ -2673,8 +2693,6 @@ void compiler_init(void) cache_size = PrefsFindInt32("jitcachesize"); jit_log(" : requested translation cache size : %d KB", cache_size); - // Initialize target CPU (check for features, e.g. CMOV, rat stalls) - raw_init_cpu(); setzflg_uses_bsf = target_check_bsf(); jit_log(" : target processor has CMOV instructions : %s", have_cmov ? "yes" : "no"); jit_log(" : target processor can suffer from partial register stalls : %s", have_rat_stall ? "yes" : "no"); @@ -2700,6 +2718,8 @@ void compiler_init(void) jit_log(" : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA)); // Build compiler tables + read_table68k(); + do_merges(); build_comp(); #endif @@ -2728,7 +2748,7 @@ void compiler_exit(void) #else #if DEBUG #if defined(USE_DATA_BUFFER) - jit_log("data_wasted = %d bytes", data_wasted); + jit_log("data_wasted = %ld bytes", data_wasted); #endif #endif @@ -2759,7 +2779,7 @@ void compiler_exit(void) opcode_nums[i] = i; untranslated_count += raw_cputbl_count[i]; } - jit_log("Sorting out untranslated instructions count..."); + bug("Sorting out untranslated instructions count..."); qsort(opcode_nums, 65536, sizeof(uae_u16), untranslated_compfn); jit_log("Rank Opc Count Name"); for (int i = 0; i < untranslated_top_ten; i++) { @@ -2771,7 +2791,7 @@ void compiler_exit(void) dp = table68k + opcode_nums[i]; for (lookup = lookuptab; lookup->mnemo != (instrmnem)dp->mnemo; lookup++) ; - jit_log("%03d: %04x %10u %s", i, opcode_nums[i], count, lookup->name); + bug("%03d: %04x %10u %s", i, opcode_nums[i], count, lookup->name); } #endif @@ -2793,6 +2813,8 @@ void compiler_exit(void) 100.0*double(cum_reg_count)/double(tot_reg_count)); } #endif + + // exit_table68k(); } #ifdef UAE @@ -2813,7 +2835,7 @@ bool compiler_use_jit(void) } #endif -void init_comp(void) +static void init_comp(void) { int i; uae_s8* cb=can_byte; @@ -3015,14 +3037,18 @@ static void flush_keepflags(void) } #endif -void freescratch(void) +static void freescratch(void) { int i; for (i=0;i= CODE_ALLOC_MAX_ATTEMPTS) - return NULL; - - return do_alloc_code(size, depth + 1); -#else UNUSED(depth); uint8 *code = (uint8 *)vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); return code == VM_MAP_FAILED ? NULL : code; -#endif } static inline uint8 *alloc_code(uint32 size) @@ -3559,7 +3540,7 @@ static inline uint8 *alloc_code(uint32 size) void alloc_cache(void) { if (compiled_code) { - flush_icache_hard(6); + flush_icache_hard(); vm_release(compiled_code, cache_size * 1024); compiled_code = 0; } @@ -3719,8 +3700,6 @@ static inline int block_check_checksum(blockinfo* bi) if (bi->status!=BI_NEED_CHECK) return 1; /* This block is in a checked state */ - checksum_count++; - if (bi->c1 || bi->c2) calc_checksum(bi,&c1,&c2); else { @@ -3885,7 +3864,10 @@ static inline void create_popalls(void) r=REG_PC_TMP; compemu_raw_mov_l_rm(r, uae_p32(®s.pc_p)); compemu_raw_and_l_ri(r,TAGMASK); - assert(sizeof(cache_tags[0]) == sizeof(void *)); + { + assert(sizeof(cache_tags[0]) == sizeof(void *)); + // verify(sizeof(cache_tags[0]) == sizeof(void *)); + } compemu_raw_jmp_m_indexed(uae_p32(cache_tags), r, sizeof(void *)); /* now the exit points */ @@ -4020,12 +4002,98 @@ static int read_opcode(const char *p) return opcode; } + +#ifdef USE_JIT_FPU +static struct { + const char *name; + bool *const disabled; +} const jit_opcodes[] = { + { "fbcc", &jit_disable.fbcc }, + { "fdbcc", &jit_disable.fdbcc }, + { "fscc", &jit_disable.fscc }, + { "ftrapcc", &jit_disable.ftrapcc }, + { "fsave", &jit_disable.fsave }, + { "frestore", &jit_disable.frestore }, + { "fmove", &jit_disable.fmove }, + { "fmovec", &jit_disable.fmovec }, + { "fmovem", &jit_disable.fmovem }, + { "fmovecr", &jit_disable.fmovecr }, + { "fint", &jit_disable.fint }, + { "fsinh", &jit_disable.fsinh }, + { "fintrz", &jit_disable.fintrz }, + { "fsqrt", &jit_disable.fsqrt }, + { "flognp1", &jit_disable.flognp1 }, + { "fetoxm1", &jit_disable.fetoxm1 }, + { "ftanh", &jit_disable.ftanh }, + { "fatan", &jit_disable.fatan }, + { "fasin", &jit_disable.fasin }, + { "fatanh", &jit_disable.fatanh }, + { "fsin", &jit_disable.fsin }, + { "ftan", &jit_disable.ftan }, + { "fetox", &jit_disable.fetox }, + { "ftwotox", &jit_disable.ftwotox }, + { "ftentox", &jit_disable.ftentox }, + { "flogn", &jit_disable.flogn }, + { "flog10", &jit_disable.flog10 }, + { "flog2", &jit_disable.flog2 }, + { "fabs", &jit_disable.fabs }, + { "fcosh", &jit_disable.fcosh }, + { "fneg", &jit_disable.fneg }, + { "facos", &jit_disable.facos }, + { "fcos", &jit_disable.fcos }, + { "fgetexp", &jit_disable.fgetexp }, + { "fgetman", &jit_disable.fgetman }, + { "fdiv", &jit_disable.fdiv }, + { "fmod", &jit_disable.fmod }, + { "fadd", &jit_disable.fadd }, + { "fmul", &jit_disable.fmul }, + { "fsgldiv", &jit_disable.fsgldiv }, + { "frem", &jit_disable.frem }, + { "fscale", &jit_disable.fscale }, + { "fsglmul", &jit_disable.fsglmul }, + { "fsub", &jit_disable.fsub }, + { "fsincos", &jit_disable.fsincos }, + { "fcmp", &jit_disable.fcmp }, + { "ftst", &jit_disable.ftst }, +}; + +static bool read_fpu_opcode(const char **pp) +{ + const char *p = *pp; + const char *end; + size_t len; + unsigned int i; + + end = p; + while (*end != '\0' && *end != ',') + end++; + len = end - p; + if (*end != '\0') + end++; + for (i = 0; i < (sizeof(jit_opcodes) / sizeof(jit_opcodes[0])); i++) + { + if (len == strlen(jit_opcodes[i].name) && strncasecmp(jit_opcodes[i].name, p, len) == 0) + { + *jit_opcodes[i].disabled = true; + jit_log(" : disabled %s", jit_opcodes[i].name); + *pp = end; + return true; + } + } + return false; +} +#endif + static bool merge_blacklist() { #ifdef UAE const char *blacklist = ""; #else const char *blacklist = PrefsFindString("jitblacklist"); +#endif +#ifdef USE_JIT_FPU + for (unsigned int i = 0; i < (sizeof(jit_opcodes) / sizeof(jit_opcodes[0])); i++) + *jit_opcodes[i].disabled = false; #endif if (blacklist[0] != '\0') { const char *p = blacklist; @@ -4035,7 +4103,14 @@ static bool merge_blacklist() int opcode1 = read_opcode(p); if (opcode1 < 0) + { +#ifdef USE_JIT_FPU + if (read_fpu_opcode(&p)) + continue; +#endif + bug(" : invalid opcode %s", p); return false; + } p += 4; int opcode2 = opcode1; @@ -4043,7 +4118,10 @@ static bool merge_blacklist() p++; opcode2 = read_opcode(p); if (opcode2 < 0) + { + bug(" : invalid opcode %s", p); return false; + } p += 4; } @@ -4066,6 +4144,12 @@ static bool merge_blacklist() void build_comp(void) { +#ifdef FSUAE + if (!g_fs_uae_jit_compiler) { + jit_log("JIT: JIT compiler is not enabled"); + return; + } +#endif int i; unsigned long opcode; const struct comptbl* tbl=op_smalltbl_0_comp_ff; @@ -4084,6 +4168,8 @@ void build_comp(void) : op_smalltbl_5_nf); #endif #endif + // Initialize target CPU (check for features, e.g. CMOV, rat stalls) + raw_init_cpu(); #ifdef NATMEM_OFFSET #ifdef UAE @@ -4220,7 +4306,7 @@ void build_comp(void) { jit_log(" : blacklist merge failure!"); } - + count=0; for (opcode = 0; opcode < 65536; opcode++) { if (compfunctbl[cft_map(opcode)]) @@ -4258,21 +4344,19 @@ void build_comp(void) } -static void flush_icache_none(int) +static void flush_icache_none(void) { /* Nothing to do. */ } -static void flush_icache_hard(int n) +void flush_icache_hard(void) { blockinfo* bi, *dbi; - hard_flush_count++; #ifndef UAE jit_log("JIT: Flush Icache_hard(%d/%x/%p), %u KB", n,regs.pc,regs.pc_p,current_cache_size/1024); #endif - UNUSED(n); bi=active; while(bi) { cache_tags[cacheline(bi->pc_p)].handler=(cpuop_func*)popall_execute_normal; @@ -4309,22 +4393,11 @@ static void flush_icache_hard(int n) we simply mark everything as "needs to be checked". */ -#ifdef WINUAE_ARANYM -static inline void flush_icache_lazy(int) -#else -void flush_icache(int n) -#endif +static inline void flush_icache_lazy(void) { blockinfo* bi; blockinfo* bi2; -#ifdef UAE - if (currprefs.comp_hardflush) { - flush_icache_hard(n); - return; - } -#endif - soft_flush_count++; if (!active) return; @@ -4359,51 +4432,15 @@ void flush_icache(int n) active=NULL; } -#ifdef UAE -static -#endif -// void flush_icache_range(uae_u32 start, uae_u32 length) -// { -// if (!active) -// return; -// #if LAZY_FLUSH_ICACHE_RANGE -// uae_u8 *start_p = get_real_address(start); -// blockinfo *bi = active; -// while (bi) { -// #if USE_CHECKSUM_INFO -// bool invalidate = false; -// for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) -// invalidate = (((start_p - csi->start_p) < csi->length) || -// ((csi->start_p - start_p) < length)); -// #else -// // Assume system is consistent and would invalidate the right range -// const bool invalidate = (bi->pc_p - start_p) < length; -// #endif -// if (invalidate) { -// uae_u32 cl = cacheline(bi->pc_p); -// if (bi == cache_tags[cl + 1].bi) -// cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; -// bi->handler_to_use = (cpuop_func *)popall_execute_normal; -// set_dhtu(bi, bi->direct_pen); -// bi->status = BI_NEED_RECOMP; -// } -// bi = bi->next; -// } -// return; -// #else -// UNUSED(start); -// UNUSED(length); -// #endif -// flush_icache(-1); -// } - -void flush_icache_range(uae_u8 *start_p, uae_u32 length) +#if 0 +static void flush_icache_range(uae_u32 start, uae_u32 length) { if (!active) return; #if LAZY_FLUSH_ICACHE_RANGE + uae_u8 *start_p = get_real_address(start); blockinfo *bi = active; while (bi) { #if USE_CHECKSUM_INFO @@ -4427,18 +4464,13 @@ void flush_icache_range(uae_u8 *start_p, uae_u32 length) } return; #else - // UNUSED(start); - // UNUSED(length); + UNUSED(start); + UNUSED(length); #endif - flush_icache(-1); + flush_icache(); } +#endif -/* -static void catastrophe(void) -{ - jit_abort("catastprophe"); -} -*/ int failure; @@ -4465,45 +4497,45 @@ void compiler_dumpstate(void) if (!JITDebug) return; - bug("### Host addresses"); - bug("MEM_BASE : %lx", (unsigned long)MEMBaseDiff); - bug("PC_P : %p", ®s.pc_p); - bug("SPCFLAGS : %p", ®s.spcflags); - bug("D0-D7 : %p-%p", ®s.regs[0], ®s.regs[7]); - bug("A0-A7 : %p-%p", ®s.regs[8], ®s.regs[15]); - bug(" "); + jit_log("### Host addresses"); + jit_log("MEM_BASE : %lx", (unsigned long)MEMBaseDiff); + jit_log("PC_P : %p", ®s.pc_p); + jit_log("SPCFLAGS : %p", ®s.spcflags); + jit_log("D0-D7 : %p-%p", ®s.regs[0], ®s.regs[7]); + jit_log("A0-A7 : %p-%p", ®s.regs[8], ®s.regs[15]); + jit_log(" "); - bug("### M68k processor state"); + jit_log("### M68k processor state"); m68k_dumpstate(stderr, 0); - bug(" "); + jit_log(" "); - bug("### Block in Atari address space"); - bug("M68K block : %p", + jit_log("### Block in Atari address space"); + jit_log("M68K block : %p", (void *)(uintptr)last_regs_pc_p); if (last_regs_pc_p != 0) { - bug("Native block : %p (%d bytes)", + jit_log("Native block : %p (%d bytes)", (void *)last_compiled_block_addr, get_blockinfo_addr(last_regs_pc_p)->direct_handler_size); } - bug(" "); + jit_log(" "); } #endif #ifdef UAE void compile_block(cpu_history *pc_hist, int blocklen, int totcycles) { - if (letit && compiled_code && currprefs.cpu_model >= 68020) { + if (cache_enabled && compiled_code && currprefs.cpu_model >= 68020) { #else static void compile_block(cpu_history* pc_hist, int blocklen) { - if (letit && compiled_code) { + if (cache_enabled && compiled_code) { #endif #ifdef PROFILE_COMPILE_TIME compile_count++; clock_t start_time = clock(); #endif #ifdef JIT_DEBUG - bool disasm_block = true; + bool disasm_block = false; #endif /* OK, here we need to 'compile' a block */ @@ -4527,7 +4559,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) redo_current_block=0; if (current_compile_p >= MAX_COMPILE_PTR) - flush_icache_hard(7); + flush_icache_hard(); alloc_blockinfos(); @@ -4643,12 +4675,12 @@ static void compile_block(cpu_history* pc_hist, int blocklen) #ifdef USE_CPU_EMUL_SERVICES compemu_raw_sub_l_mi((uintptr)&emulated_ticks,blocklen); compemu_raw_jcc_b_oponly(NATIVE_CC_GT); - uae_s8 *branchadd=(uae_s8*)get_target(); + uae_u8 *branchadd=get_target(); skip_byte(); raw_dec_sp(STACK_SHADOW_SPACE); compemu_raw_call((uintptr)cpu_do_check_ticks); raw_inc_sp(STACK_SHADOW_SPACE); - *branchadd=(uintptr)get_target()-((uintptr)branchadd+1); + *branchadd=get_target()-(branchadd+1); #endif #ifdef JIT_DEBUG @@ -4690,7 +4722,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) prepare_for_call_1(); prepare_for_call_2(); raw_mov_l_ri(REG_PAR1, ((uintptr)(pc_hist[i].location)) - MEMBaseDiff); - raw_mov_w_ri(REG_PAR2, opcode); + raw_mov_w_ri(REG_PAR2, cft_map(opcode)); raw_dec_sp(STACK_SHADOW_SPACE); compemu_raw_call((uintptr)m68k_record_step); raw_inc_sp(STACK_SHADOW_SPACE); @@ -4706,11 +4738,13 @@ static void compile_block(cpu_history* pc_hist, int blocklen) } was_comp=1; +#ifdef WINUAE_ARANYM bool isnop = do_get_mem_word(pc_hist[i].location) == 0x4e71 || ((i + 1) < blocklen && do_get_mem_word(pc_hist[i+1].location) == 0x4e71); if (isnop) compemu_raw_mov_l_mi((uintptr)®s.fault_pc, ((uintptr)(pc_hist[i].location)) - MEMBaseDiff); +#endif comptbl[opcode](opcode); freescratch(); @@ -4724,6 +4758,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) flush(1); was_comp=0; #endif +#ifdef WINUAE_ARANYM /* * workaround for buserror handling: on a "nop", write registers back */ @@ -4733,6 +4768,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) nop(); was_comp=0; } +#endif } if (failure) { @@ -4758,7 +4794,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) #endif if (i < blocklen - 1) { - uae_s8* branchadd; + uae_u8* branchadd; /* if (SPCFLAGS_TEST(SPCFLAG_STOP)) popall_do_nothing() */ compemu_raw_mov_l_rm(0,(uintptr)specflags); @@ -4767,13 +4803,13 @@ static void compile_block(cpu_history* pc_hist, int blocklen) data_check_end(8, 64); // just a pessimistic guess... #endif compemu_raw_jz_b_oponly(); - branchadd=(uae_s8*)get_target(); + branchadd=get_target(); skip_byte(); #ifdef UAE raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles)); #endif compemu_raw_jmp((uintptr)popall_do_nothing); - *branchadd=(uintptr)get_target()-(uintptr)branchadd-1; + *branchadd=get_target()-branchadd-1; } } } @@ -4804,7 +4840,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) } #endif log_flush(); - + if (next_pc_p) { /* A branch was registered */ uintptr t1=next_pc_p; uintptr t2=taken_pc_p; @@ -4900,7 +4936,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) tbi = get_blockinfo_addr_new((void*) v, 1); match_states(tbi); - + #ifdef UAE raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles)); raw_jcc_l_oponly(NATIVE_CC_PL); @@ -4936,10 +4972,10 @@ static void compile_block(cpu_history* pc_hist, int blocklen) if (callers_need_recompile(&live,&(bi->env))) { mark_callers_recompile(bi); } - + big_to_small_state(&live,&(bi->env)); #endif - + #if USE_CHECKSUM_INFO remove_from_list(bi); if (trace_in_rom) { @@ -4974,7 +5010,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) } #endif - current_cache_size += get_target() - (uae_u8 *)current_compile_p; + current_cache_size += get_target() - current_compile_p; #ifdef JIT_DEBUG bi->direct_handler_size = get_target() - (uae_u8 *)current_block_start_target; @@ -4983,9 +5019,13 @@ static void compile_block(cpu_history* pc_hist, int blocklen) uaecptr block_addr = start_pc + ((char *)pc_hist[0].location - (char *)start_pc_p); jit_log("M68K block @ 0x%08x (%d insns)", block_addr, blocklen); uae_u32 block_size = ((uae_u8 *)pc_hist[blocklen - 1].location - (uae_u8 *)pc_hist[0].location) + 1; +#ifdef WINUAE_ARANYM disasm_m68k_block((const uae_u8 *)pc_hist[0].location, block_size); +#endif jit_log("Compiled block @ %p", pc_hist[0].location); +#ifdef WINUAE_ARANYM disasm_native_block((const uae_u8 *)current_block_start_target, bi->direct_handler_size); +#endif UNUSED(block_addr); } #endif @@ -5022,7 +5062,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) /* We will flush soon, anyway, so let's do it now */ if (current_compile_p >= MAX_COMPILE_PTR) - flush_icache_hard(7); + flush_icache_hard(); bi->status=BI_ACTIVE; if (redo_current_block) @@ -5037,7 +5077,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) #endif } -#ifndef UAE +#ifdef USE_CPU_EMUL_SERVICES /* Account for compilation time */ cpu_do_check_ticks(); #endif @@ -5060,7 +5100,7 @@ void exec_nostats(void) for (;;) { uae_u32 opcode = GET_OPCODE; #if FLIGHT_RECORDER - m68k_record_step(m68k_getpc(), opcode); + m68k_record_step(m68k_getpc(), cft_map(opcode)); #endif (*cpufunctbl[opcode])(opcode); cpu_check_ticks(); @@ -5090,7 +5130,7 @@ void execute_normal(void) pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p; uae_u32 opcode = GET_OPCODE; #if FLIGHT_RECORDER - m68k_record_step(m68k_getpc(), opcode); + m68k_record_step(m68k_getpc(), cft_map(opcode)); #endif (*cpufunctbl[opcode])(opcode); cpu_check_ticks(); @@ -5131,11 +5171,15 @@ void m68k_compile_execute (void) setjmpagain: TRY(prb) { for (;;) { - if (quit_program == 1) { + if (quit_program > 0) { + if (quit_program == 1) { #if FLIGHT_RECORDER - dump_flight_recorder(); + dump_flight_recorder(); #endif - break; + break; + } + quit_program = 0; + m68k_reset (); } m68k_do_compile_execute(); } @@ -5148,7 +5192,7 @@ setjmpagain: regs.fault_pc, regs.mmu_fault_addr, get_long (regs.vbr + 4*prb), regs.regs[15]); - flush_icache(0); + flush_icache(); Exception(prb, 0); goto setjmpagain; } diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index febeddc9..712d7873 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -93,11 +93,16 @@ #define DISABLE_I_FSCC #define DISABLE_I_MOVE16 */ + #endif /* UAE */ #ifdef UAE #define JIT_PATH "jit/" +#ifdef FSUAE +#define GEN_PATH "gen/" +#else #define GEN_PATH "jit/" +#endif #define RETURN "return 0;" #define RETTYPE "uae_u32" #define NEXT_CPU_LEVEL 5 @@ -107,7 +112,6 @@ #define RETURN "return;" #define RETTYPE "void" #define NEXT_CPU_LEVEL 4 -#define ua(s) s #endif #define BOOL_TYPE "int" @@ -738,8 +742,9 @@ static void genmov16(uae_u32 opcode, struct instr *curi) "\tadd_l_ri(dst,4);\n" "\treadlong(src,tmp,scratchie);\n" "\twritelong_clobber(dst,tmp,scratchie);\n"); - comprintf("\t} else {\n"); + comprintf("\t} else\n"); #endif + start_brace(); comprintf("\tint tmp=scratchie;\n"); comprintf("\tscratchie+=4;\n" "\tget_n_addr(src,src,scratchie);\n" @@ -755,9 +760,7 @@ static void genmov16(uae_u32 opcode, struct instr *curi) "\tmov_l_Rr(dst,tmp+2,8);\n" "\tforget_about(tmp+2);\n" "\tmov_l_Rr(dst,tmp+3,12);\n"); -#ifdef UAE - comprintf("\t}\n"); -#endif + close_brace(); } static void @@ -1304,11 +1307,11 @@ genflags (flagtypes type, wordsizes size, const char *value, const char *src, co break; } comprintf("\tlive_flags();\n"); - comprintf("\tif (needed_flags&FLAG_Z) {\n" - "\tcmov_l_rr(zero,one,%d);\n" - "\tset_zero(zero, one);\n" /* No longer need one */ - "\tlive_flags();\n" - "\t}\n",NATIVE_CC_NE); + comprintf("\tif (needed_flags&FLAG_Z) {\n"); + comprintf("\tcmov_l_rr(zero,one,%d);\n", NATIVE_CC_NE); + comprintf("\tset_zero(zero, one);\n"); /* No longer need one */ + comprintf("\tlive_flags();\n"); + comprintf("\t}\n"); comprintf("\tend_needflags();\n"); duplicate_carry(); comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); @@ -2181,158 +2184,63 @@ gen_opcode (unsigned int opcode) genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint width;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n" - "\tint highshift=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,cnt);\n" - "\thighmask=0x38;\n" - "\twidth=8;\n"); - break; - case sz_word: comprintf("\tshra_w_rr(data,cnt);\n" - "\thighmask=0x30;\n" - "\twidth=16;\n"); - break; - case sz_long: comprintf("\tshra_l_rr(data,cnt);\n" - "\thighmask=0x20;\n" - "\twidth=32;\n"); - break; - default: assert(0); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(highshift,0);\n" - "mov_l_ri(scratchie,width/2);\n" - "cmov_l_rr(highshift,scratchie,%d);\n", NATIVE_CC_NE); - /* The x86 masks out bits, so we now make sure that things - really get shifted as much as planned */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; - case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; - case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; - default: assert(0); - } - /* And again */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; - case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; - case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; - default: assert(0); - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(cdata,tmpcnt);\n");break; - case sz_word: comprintf("\tshra_w_rr(cdata,tmpcnt);\n");break; - case sz_long: comprintf("\tshra_l_rr(cdata,tmpcnt);\n");break; - default: assert(0); - } - /* If the shift count was higher than the width, we need - to pick up the sign from data */ - comprintf("test_l_ri(tmpcnt,highmask);\n" - "cmov_l_rr(cdata,data,%d);\n", NATIVE_CC_NE); - /* And create the flags */ + start_brace(); + if (!noflags) comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { + if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint highmask;\n" - "\tint width;\n" - "\tint highshift=scratchie++;\n"); + comprintf("\tint zero = scratchie++;\n"); + comprintf("\tint minus1 = scratchie++;\n"); + comprintf("\tand_l_ri(cnt,63);\n"); + comprintf("\tmov_l_ri(zero, 0);\n"); + comprintf("\tmov_l_ri(minus1, -1);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,cnt);\n" - "\thighmask=0x38;\n" - "\twidth=8;\n"); - break; - case sz_word: comprintf("\tshra_w_rr(data,cnt);\n" - "\thighmask=0x30;\n" - "\twidth=16;\n"); - break; - case sz_long: comprintf("\tshra_l_rr(data,cnt);\n" - "\thighmask=0x20;\n" - "\twidth=32;\n"); - break; + case sz_byte: + comprintf("\ttest_b_rr(data,data);\n"); + comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n"); + comprintf("\ttest_l_ri(cnt, 0x38);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshra_b_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\ttest_w_rr(data,data);\n"); + comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n"); + comprintf("\ttest_l_ri(cnt, 0x30);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshra_w_rr(data,cnt);\n"); + break; + case sz_long: + comprintf("\ttest_l_rr(data,data);\n"); + comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n"); + comprintf("\ttest_l_ri(cnt, 0x20);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshra_l_rr(data,cnt);\n"); + break; default: assert(0); } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(highshift,0);\n" - "mov_l_ri(scratchie,width/2);\n" - "cmov_l_rr(highshift,scratchie,%d);\n",NATIVE_CC_NE); - /* The x86 masks out bits, so we now make sure that things - really get shifted as much as planned */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; - case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; - case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; - default: assert(0); - } - /* And again */ - switch(curi->size) { - case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; - case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; - case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; - default: assert(0); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } + /* Result of shift is now in data. */ } else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshra_b_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_word: comprintf("\tshra_w_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_long: comprintf("\tshra_l_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; + case sz_byte: comprintf("\tshra_b_ri(data,srcreg);\n"); break; + case sz_word: comprintf("\tshra_w_ri(data,srcreg);\n"); break; + case sz_long: comprintf("\tshra_l_ri(data,srcreg);\n"); break; default: assert(0); } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); } + /* And create the flags */ + if (!noflags) { + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (curi->smode!=immi) + comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + else + comprintf("\tduplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); break; case i_ASL: @@ -2359,129 +2267,54 @@ gen_opcode (unsigned int opcode) genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,%d);\n",NATIVE_CC_NE); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: assert(0); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: assert(0); - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break; - case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break; - case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break; - default: assert(0); - } - comprintf("test_l_ri(tmpcnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(cdata,scratchie,%d);\n",NATIVE_CC_NE); - /* And create the flags */ - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,7);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,15);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,31);\n"); break; - } - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { + if (!noflags) + comprintf("\tstart_needflags();\n"); + if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint highmask;\n"); + comprintf("\tint zero = scratchie++;\n"); + comprintf("\tand_l_ri(cnt,63);\n"); + comprintf("\tmov_l_ri(zero, 0);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; + case sz_byte: + comprintf("\ttest_l_ri(cnt, 0x38);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshll_b_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\ttest_l_ri(cnt, 0x30);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshll_w_rr(data,cnt);\n"); + break; + case sz_long: + comprintf("\ttest_l_ri(cnt, 0x20);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshll_l_rr(data,cnt);\n"); + break; default: assert(0); } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: assert(0); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } + /* Result of shift is now in data. */ } else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n" - "\tbp=8-srcreg;\n"); break; - case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n" - "\tbp=16-srcreg;\n"); break; - case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n" - "\tbp=32-srcreg;\n"); break; + case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n"); break; + case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n"); break; + case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n"); break; default: assert(0); } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); } + /* And create the flags */ + if (!noflags) { + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (curi->smode!=immi) + comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + else + comprintf("\tduplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); break; case i_LSR: @@ -2500,126 +2333,55 @@ gen_opcode (unsigned int opcode) genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,%d);\n",NATIVE_CC_NE); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshrl_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: assert(0); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: assert(0); - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_rr(cdata,tmpcnt);\n");break; - case sz_word: comprintf("\tshrl_w_rr(cdata,tmpcnt);\n");break; - case sz_long: comprintf("\tshrl_l_rr(cdata,tmpcnt);\n");break; - default: assert(0); - } - comprintf("test_l_ri(tmpcnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(cdata,scratchie,%d);\n",NATIVE_CC_NE); - /* And create the flags */ + + start_brace(); + if (!noflags) comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { + if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint highmask;\n"); + comprintf("\tint zero = scratchie++;\n"); + comprintf("\tand_l_ri(cnt,63);\n"); + comprintf("\tmov_l_ri(zero, 0);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshrl_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; + case sz_byte: + comprintf("\ttest_l_ri(cnt, 0x38);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshrl_b_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\ttest_l_ri(cnt, 0x30);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshrl_w_rr(data,cnt);\n"); + break; + case sz_long: + comprintf("\ttest_l_ri(cnt, 0x20);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshrl_l_rr(data, cnt);\n"); + break; default: assert(0); } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: assert(0); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } + /* Result of shift is now in data. */ } else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshrl_b_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_word: comprintf("\tshrl_w_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; - case sz_long: comprintf("\tshrl_l_ri(data,srcreg);\n" - "\tbp=srcreg-1;\n"); break; + case sz_byte: comprintf("\tshrl_b_ri(data,srcreg);\n"); break; + case sz_word: comprintf("\tshrl_w_ri(data,srcreg);\n"); break; + case sz_long: comprintf("\tshrl_l_ri(data,srcreg);\n"); break; default: assert(0); } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); } + /* And create the flags */ + if (!noflags) { + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (curi->smode!=immi) + comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + else + comprintf("\tduplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); break; case i_LSL: @@ -2638,128 +2400,55 @@ gen_opcode (unsigned int opcode) genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); - if (curi->smode!=immi) { - if (!noflags) { - uses_cmov; - start_brace(); - comprintf("\tint highmask;\n" - "\tint cdata=scratchie++;\n" - "\tint tmpcnt=scratchie++;\n"); - comprintf("\tmov_l_rr(tmpcnt,cnt);\n" - "\tand_l_ri(tmpcnt,63);\n" - "\tmov_l_ri(cdata,0);\n" - "\tcmov_l_rr(cdata,data,%d);\n",NATIVE_CC_NE); - /* cdata is now either data (for shift count!=0) or - 0 (for shift count==0) */ - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; - default: assert(0); - } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: assert(0); - } - /* Result of shift is now in data. Now we need to determine - the carry by shifting cdata one less */ - comprintf("\tsub_l_ri(tmpcnt,1);\n"); - switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break; - case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break; - case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break; - default: assert(0); - } - comprintf("test_l_ri(tmpcnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(cdata,scratchie,%d);\n",NATIVE_CC_NE); - /* And create the flags */ + + start_brace(); + if (!noflags) comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,7);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,15);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); - comprintf("\t bt_l_ri(cdata,31);\n"); break; - } - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } - else { + if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint highmask;\n"); + comprintf("\tint zero = scratchie++;\n"); + comprintf("\tand_l_ri(cnt,63);\n"); + comprintf("\tmov_l_ri(zero, 0);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" - "\thighmask=0x38;\n"); - break; - case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" - "\thighmask=0x30;\n"); - break; - case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" - "\thighmask=0x20;\n"); - break; + case sz_byte: + comprintf("\ttest_l_ri(cnt, 0x38);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshll_b_rr(data,cnt);\n"); + break; + case sz_word: + comprintf("\ttest_l_ri(cnt, 0x30);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshll_w_rr(data,cnt);\n"); + break; + case sz_long: + comprintf("\ttest_l_ri(cnt, 0x20);\n"); + comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); + comprintf("\tshll_l_rr(data,cnt);\n"); + break; default: assert(0); } - comprintf("test_l_ri(cnt,highmask);\n" - "mov_l_ri(scratchie,0);\n" - "cmov_l_rr(scratchie,data,%d);\n",NATIVE_CC_EQ); - switch(curi->size) { - case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; - case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; - case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; - default: assert(0); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); - } + /* Result of shift is now in data. */ } else { - start_brace(); - comprintf("\tint tmp=scratchie++;\n" - "\tint bp;\n" - "\tmov_l_rr(tmp,data);\n"); switch(curi->size) { - case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n" - "\tbp=8-srcreg;\n"); break; - case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n" - "\tbp=16-srcreg;\n"); break; - case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n" - "\tbp=32-srcreg;\n"); break; + case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n"); break; + case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n"); break; + case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n"); break; default: assert(0); } - - if (!noflags) { - comprintf("\tstart_needflags();\n"); - comprintf("\tif (needed_flags & FLAG_ZNV)\n"); - switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; - } - comprintf("\t bt_l_ri(tmp,bp);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); - comprintf("\t duplicate_carry();\n"); - comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); - } - genastore ("data", curi->dmode, "dstreg", curi->size, "data"); } + /* And create the flags */ + if (!noflags) { + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); + if (curi->smode!=immi) + comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + else + comprintf("\tduplicate_carry();\n"); + comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); + } + genastore ("data", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROL: @@ -2787,6 +2476,9 @@ gen_opcode (unsigned int opcode) if (!noflags) { comprintf("\tstart_needflags();\n"); + /* + * x86 ROL instruction does not set ZF/SF, so we need extra checks here + */ comprintf("\tif (needed_flags & FLAG_ZNV)\n"); switch(curi->size) { case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; @@ -2825,6 +2517,9 @@ gen_opcode (unsigned int opcode) if (!noflags) { comprintf("\tstart_needflags();\n"); + /* + * x86 ROR instruction does not set ZF/SF, so we need extra checks here + */ comprintf("\tif (needed_flags & FLAG_ZNV)\n"); switch(curi->size) { case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; @@ -3133,7 +2828,7 @@ generate_includes (FILE * f) fprintf (f, "#include \"sysdeps.h\"\n"); #ifdef UAE fprintf (f, "#include \"options.h\"\n"); - fprintf (f, "#include \"memory.h\"\n"); + fprintf (f, "#include \"uae/memory.h\"\n"); #else fprintf (f, "#include \"m68k.h\"\n"); fprintf (f, "#include \"memory.h\"\n"); @@ -3147,7 +2842,6 @@ generate_includes (FILE * f) static int postfix; -#ifdef UAE static char *decodeEA (amodes mode, wordsizes size) { static char buffer[80]; @@ -3221,22 +2915,13 @@ static char *decodeEA (amodes mode, wordsizes size) return buffer; } -static char *outopcode (int opcode) +static char *outopcode (const char *name, int opcode) { static char out[100]; struct instr *ins; - int i; ins = &table68k[opcode]; - for (i = 0; lookuptab[i].name[0]; i++) { - if (ins->mnemo == lookuptab[i].mnemo) - break; - } - { - char *s = ua (lookuptab[i].name); - strcpy (out, s); - xfree (s); - } + strcpy (out, name); if (ins->smode == immi) strcat (out, "Q"); if (ins->size == sz_byte) @@ -3254,7 +2939,6 @@ static char *outopcode (int opcode) } return out; } -#endif static void @@ -3266,11 +2950,7 @@ generate_one_opcode (int rp, int noflags) int aborted=0; int have_srcreg=0; int have_dstreg=0; -#ifdef UAE - char *name; -#else const char *name; -#endif if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) @@ -3459,34 +3139,23 @@ generate_one_opcode (int rp, int noflags) else strcpy(flags, "0"); -#ifdef UAE +#ifdef UAE /* RETTYPE != void */ comprintf ("return 0;\n"); #endif comprintf ("}\n"); -#ifdef UAE - name = ua (lookuptab[i].name); -#else name = lookuptab[i].name; -#endif if (aborted) { fprintf (stblfile, "{ NULL, %u, %s }, /* %s */\n", opcode, flags, name); com_discard(); } else { const char *tbl = noflags ? "nf" : "ff"; -#ifdef UAE - printf ("/* %s */\n", outopcode (opcode)); -#else - printf ("/* %s */\n", name); -#endif fprintf (stblfile, "{ op_%x_%d_comp_%s, %u, %s }, /* %s */\n", opcode, postfix, tbl, opcode, flags, name); fprintf (headerfile, "extern compop_func op_%x_%d_comp_%s;\n", opcode, postfix, tbl); - printf (RETTYPE " REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode)\n{\n", opcode, postfix, tbl); + printf ("/* %s */\n", outopcode (name, opcode)); + printf (RETTYPE " REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, tbl, name); com_flush(); } -#ifdef UAE - xfree (name); -#endif } opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; @@ -3552,7 +3221,12 @@ void cygwin_mingw_abort() } #endif +#if defined(FSUAE) && defined (WINDOWS) +#include "windows.h" +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +#else int main(void) +#endif { read_table68k (); do_merges (); @@ -3582,6 +3256,7 @@ int main(void) generate_includes (stblfile); printf("#include \"" JIT_PATH "compemu.h\"\n"); + printf("#include \"" JIT_PATH "flags_x86.h\"\n"); noflags=0; generate_func (noflags); diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c index e9bf9bb4..7ec9ff76 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c @@ -677,6 +677,7 @@ static void gen_move16(uae_u32 opcode, struct instr *curi) { else if ((opcode & 0xfff8) == 0xf608) comprintf("\tarm_ADD_l_ri8(dstreg+8,16);\n"); + start_brace(); comprintf("\tint tmp=scratchie;\n"); comprintf("\tscratchie+=4;\n"); @@ -693,6 +694,7 @@ static void gen_move16(uae_u32 opcode, struct instr *curi) { "\tmov_l_Rr(dst,tmp+2,8);\n" "\tforget_about(tmp+2);\n" "\tmov_l_Rr(dst,tmp+3,12);\n"); + close_brace(); #endif } @@ -4632,10 +4634,10 @@ gen_opcode(unsigned long int opcode) { failure; break; - case i_NATFEAT_ID: - case i_NATFEAT_CALL: - failure; - break; + // case i_NATFEAT_ID: + // case i_NATFEAT_CALL: + // failure; + // break; case i_MMUOP: isjump; @@ -4665,6 +4667,105 @@ static void generate_includes(FILE * f) { static int postfix; +static char *decodeEA (amodes mode, wordsizes size) +{ + static char buffer[80]; + + buffer[0] = 0; + switch (mode){ + case Dreg: + strcpy (buffer,"Dn"); + break; + case Areg: + strcpy (buffer,"An"); + break; + case Aind: + strcpy (buffer,"(An)"); + break; + case Aipi: + strcpy (buffer,"(An)+"); + break; + case Apdi: + strcpy (buffer,"-(An)"); + break; + case Ad16: + strcpy (buffer,"(d16,An)"); + break; + case Ad8r: + strcpy (buffer,"(d8,An,Xn)"); + break; + case PC16: + strcpy (buffer,"(d16,PC)"); + break; + case PC8r: + strcpy (buffer,"(d8,PC,Xn)"); + break; + case absw: + strcpy (buffer,"(xxx).W"); + break; + case absl: + strcpy (buffer,"(xxx).L"); + break; + case imm: + switch (size){ + case sz_byte: + strcpy (buffer,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + break; + + default: + break; + } + return buffer; +} + +static char *outopcode (const char *name, int opcode) +{ + static char out[100]; + struct instr *ins; + + ins = &table68k[opcode]; + strcpy (out, name); + if (ins->smode == immi) + strcat (out, "Q"); + if (ins->size == sz_byte) + strcat (out,".B"); + if (ins->size == sz_word) + strcat (out,".W"); + if (ins->size == sz_long) + strcat (out,".L"); + strcat (out," "); + if (ins->suse) + strcat (out, decodeEA (ins->smode, ins->size)); + if (ins->duse) { + if (ins->suse) strcat (out,","); + strcat (out, decodeEA (ins->dmode, ins->size)); + } + return out; +} + + static void generate_one_opcode(int rp, int noflags) { int i; uae_u16 smsk, dmsk; @@ -4858,6 +4959,7 @@ static void generate_one_opcode(int rp, int noflags) { opcode, postfix, tbl, opcode, flags, name); fprintf(headerfile, "extern compop_func op_%x_%d_comp_%s;\n", opcode, postfix, tbl); + printf ("/* %s */\n", outopcode (name, opcode)); printf( "void REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, tbl, name); diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 1653adab..5ab3895a 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -582,7 +582,7 @@ static void genmovemle (uae_u16 opcode) static void duplicate_carry (void) { - printf ("\tCOPY_CARRY;\n"); + printf ("\tCOPY_CARRY();\n"); } typedef enum { @@ -682,7 +682,7 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * switch (type) { case flag_logical: - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); printf ("\tSET_ZFLG (%s == 0);\n", vstr); printf ("\tSET_NFLG (%s < 0);\n", vstr); break; @@ -697,10 +697,10 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n"); break; case flag_z: - printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr); + printf ("\tSET_ZFLG (GET_ZFLG() & (%s == 0));\n", vstr); break; case flag_zn: - printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr); + printf ("\tSET_ZFLG (GET_ZFLG() & (%s == 0));\n", vstr); printf ("\tSET_NFLG (%s < 0);\n", vstr); break; case flag_add: @@ -926,7 +926,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); - printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n"); + printf ("\tuae_u32 newv = dst - src - (GET_XFLG() ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); @@ -935,14 +935,14 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); - printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); + printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG() ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n"); printf ("\tuae_u16 newv, tmp_newv;\n"); printf ("\tint bcd = 0;\n"); printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n"); - printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); - printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n"); + printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG() ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); + printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG() ? 1 : 0)) & 0x300) > 0xFF);\n"); duplicate_carry (); /* Manual says bits NV are undefined though a real 68040 don't change them */ if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { @@ -974,7 +974,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); - printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n"); + printf ("\tuae_u32 newv = dst + src + (GET_XFLG() ? 1 : 0);\n"); genflags (flag_addx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); @@ -983,7 +983,7 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); - printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n"); + printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG() ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); printf ("\tuae_u16 newv, tmp_newv;\n"); printf ("\tint cflg;\n"); @@ -1014,7 +1014,7 @@ static void gen_opcode (unsigned long int opcode) case i_NEGX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); - printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n"); + printf ("\tuae_u32 newv = 0 - src - (GET_XFLG() ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "0"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->smode, "srcreg", curi->size, "src"); @@ -1022,7 +1022,7 @@ static void gen_opcode (unsigned long int opcode) case i_NBCD: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); - printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); + printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG() ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n"); printf ("\tuae_u16 newv;\n"); printf ("\tint cflg;\n"); @@ -1295,7 +1295,7 @@ static void gen_opcode (unsigned long int opcode) break; case i_TRAPV: sync_m68k_pc (); - printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr); + printf ("\tif (GET_VFLG()) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr); need_endlabel = 1; break; case i_RTR: @@ -1505,7 +1505,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); - printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); + printf ("\tif ((extra & 0x800) && GET_CFLG()) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; @@ -1521,7 +1521,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1); printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tval = %s & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size)); printf ("\t\tSET_CFLG (sign);\n"); @@ -1553,7 +1553,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tSET_VFLG (val != 0);\n"); printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n", @@ -1589,7 +1589,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n", bit_size (curi->size), bit_size (curi->size) - 1); @@ -1618,7 +1618,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n", bit_size (curi->size)); @@ -1648,7 +1648,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); if (source_is_imm1_8 (curi)) printf ("{"); else @@ -1675,7 +1675,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); if (source_is_imm1_8 (curi)) printf ("{"); else @@ -1702,7 +1702,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); if (source_is_imm1_8 (curi)) printf ("{"); else { @@ -1713,11 +1713,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t{\n\tuae_u32 carry;\n"); printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1); printf ("\tcarry = loval & 1;\n"); - printf ("\tval = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);\n"); + printf ("\tval = (((val << 1) | GET_XFLG()) << cnt) | (loval >> 1);\n"); printf ("\tSET_XFLG (carry);\n"); printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t} }\n"); - printf ("\tSET_CFLG (GET_XFLG);\n"); + printf ("\tSET_CFLG (GET_XFLG());\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; @@ -1732,7 +1732,7 @@ static void gen_opcode (unsigned long int opcode) default: abort (); } printf ("\tcnt &= 63;\n"); - printf ("\tCLEAR_CZNV;\n"); + printf ("\tCLEAR_CZNV();\n"); if (source_is_imm1_8 (curi)) printf ("{"); else { @@ -1741,7 +1741,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tcnt--;\n"); printf ("\t{\n\tuae_u32 carry;\n"); - printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n"); + printf ("\tuae_u32 hival = (val << 1) | GET_XFLG();\n"); printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1); printf ("\tval >>= cnt;\n"); printf ("\tcarry = val & 1;\n"); @@ -1750,7 +1750,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_XFLG (carry);\n"); printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t} }\n"); - printf ("\tSET_CFLG (GET_XFLG);\n"); + printf ("\tSET_CFLG (GET_XFLG());\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; @@ -1788,7 +1788,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG (sign != 0);\n"); duplicate_carry (); - printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n"); + printf ("\tSET_VFLG (GET_VFLG() | (sign2 != sign));\n"); genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_LSRW: @@ -1866,7 +1866,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size)); printf ("\tval <<= 1;\n"); - printf ("\tif (GET_XFLG) val |= 1;\n"); + printf ("\tif (GET_XFLG()) val |= 1;\n"); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); @@ -1883,7 +1883,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tuae_u32 carry = val & 1;\n"); printf ("\tval >>= 1;\n"); - printf ("\tif (GET_XFLG) val |= %s;\n", cmask (curi->size)); + printf ("\tif (GET_XFLG()) val |= %s;\n", cmask (curi->size)); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); @@ -1912,7 +1912,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tint ru = (src >> 6) & 7;\n"); printf ("\tint rc = src & 7;\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst"); - printf ("\tif (GET_ZFLG)"); + printf ("\tif (GET_ZFLG())"); old_brace_level = n_braces; start_brace (); genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); @@ -1931,14 +1931,14 @@ static void gen_opcode (unsigned long int opcode) int old_brace_level = n_braces; printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); - printf ("\tif (GET_ZFLG) {\n"); + printf ("\tif (GET_ZFLG()) {\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); - printf ("\tif (GET_ZFLG) {\n"); + printf ("\tif (GET_ZFLG()) {\n"); printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); - printf ("\tif (! GET_ZFLG) {\n"); + printf ("\tif (! GET_ZFLG()) {\n"); printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); printf ("\t}\n"); @@ -1946,14 +1946,14 @@ static void gen_opcode (unsigned long int opcode) int old_brace_level = n_braces; printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); - printf ("\tif (GET_ZFLG) {\n"); + printf ("\tif (GET_ZFLG()) {\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); - printf ("\tif (GET_ZFLG) {\n"); + printf ("\tif (GET_ZFLG()) {\n"); printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); - printf ("\tif (! GET_ZFLG) {\n"); + printf ("\tif (! GET_ZFLG()) {\n"); printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n"); printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n"); printf ("\t}\n"); @@ -2053,7 +2053,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\ttmp = ~tmp;\n"); break; case i_BFEXTS: - printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n"); + printf ("\tif (GET_NFLG()) tmp |= width == 32 ? 0 : (-1 << width);\n"); printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCLR: @@ -2185,18 +2185,40 @@ static void gen_opcode (unsigned long int opcode) printf ("\tfpuop_restore(opcode);\n"); break; case i_CINVL: + printf("\n#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache();\n"); + printf("#endif\n"); + break; case i_CINVP: + printf("\n#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache();\n"); + printf("#endif\n"); + break; case i_CINVA: - /* gb-- srcreg now contains the cache field */ - printf ("\tif (srcreg&0x2)\n"); - printf ("\t\tflush_icache(%d);\n", 30 + ((opcode >> 3) & 3)); + printf("\n#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache();\n"); + printf("#endif\n"); break; case i_CPUSHL: + printf("\n#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache();\n"); + printf("#endif\n"); + break; case i_CPUSHP: + printf("\n#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache();\n"); + printf("#endif\n"); + break; case i_CPUSHA: - /* gb-- srcreg now contains the cache field */ - printf ("\tif (srcreg&0x2)\n"); - printf ("\t\tflush_icache(%d);\n", 40 + ((opcode >> 3) & 3)); + printf("\n#ifdef USE_JIT\n"); + printf ("\tif (opcode&0x80)\n" + "\t\tflush_icache();\n"); + printf("#endif\n"); break; case i_MOVE16: if ((opcode & 0xfff8) == 0xf620) { diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index f329cb3e..d4d28484 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -25,67 +25,108 @@ #ifdef OPTIMIZED_FLAGS -#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) || defined(MSVC_INTRINSICS) +#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY)) + +# include #ifndef SAHF_SETO_PROFITABLE +/* + * Machine dependent structure for holding the 68k CCR flags + */ /* PUSH/POP instructions are naturally 64-bit sized on x86-64, thus unsigned long hereunder is either 64-bit or 32-bit wide depending on the target. */ struct flag_struct { - unsigned long cznv; - unsigned long x; +#if defined(CPU_x86_64) + uint64 cznv; + uint64 x; +#else + uint32 cznv; + uint32 x; +#endif }; -#define FLAGVAL_Z 0x40 -#define FLAGVAL_N 0x80 +/* + * The bits in the cznv field in the above structure are assigned to + * allow the easy mirroring of the x86 rFLAGS register. + * + * The 68k CZNV flags are thus assigned in cznv as: + * + * 76543210 FEDCBA98 --------- --------- + * SZxxxxxC xxxxVxxx xxxxxxxxx xxxxxxxxx + */ -#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x40) | (((y) & 1) << 6)) -#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x800) | (((y) & 1) << 11)) -#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x80) | (((y) & 1) << 7)) -#define SET_XFLG(y) (regflags.x = (y)) +#define FLAGBIT_N 7 +#define FLAGBIT_Z 6 +#define FLAGBIT_C 0 +#define FLAGBIT_V 11 +#define FLAGBIT_X 0 /* must be in position 0 for duplicate_carry() to work */ -#define GET_ZFLG ((regflags.cznv >> 6) & 1) -#define GET_CFLG (regflags.cznv & 1) -#define GET_VFLG ((regflags.cznv >> 11) & 1) -#define GET_NFLG ((regflags.cznv >> 7) & 1) -#define GET_XFLG (regflags.x & 1) +#define FLAGVAL_N (1 << FLAGBIT_N) +#define FLAGVAL_Z (1 << FLAGBIT_Z) +#define FLAGVAL_C (1 << FLAGBIT_C) +#define FLAGVAL_V (1 << FLAGBIT_V) +#define FLAGVAL_X (1 << FLAGBIT_X) -#define CLEAR_CZNV (regflags.cznv = 0) -#define GET_CZNV (regflags.cznv) -#define IOR_CZNV(X) (regflags.cznv |= (X)) -#define SET_CZNV(X) (regflags.cznv = (X)) +#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z)) +#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C)) +#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V)) +#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_N) | (((y) & 1) << FLAGBIT_N)) +#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X) -#define COPY_CARRY (regflags.x = regflags.cznv) +#define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1) +#define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1) +#define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1) +#define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1) +#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1) -extern struct flag_struct regflags ASM_SYM ("regflags"); +#define CLEAR_CZNV() (regflags.cznv = 0) +#define GET_CZNV() (regflags.cznv) +#define IOR_CZNV(X) (regflags.cznv |= (X)) +#define SET_CZNV(X) (regflags.cznv = (X)) -static __inline__ int cctrue(int cc) +#define COPY_CARRY() (regflags.x = regflags.cznv >> (FLAGBIT_C - FLAGBIT_X)) + +extern struct flag_struct regflags __asm__ ("regflags"); + +/* + * Test CCR condition + */ +static inline int cctrue(int cc) { uae_u32 cznv = regflags.cznv; - switch(cc){ - case 0: return 1; /* T */ - case 1: return 0; /* F */ - case 2: return (cznv & 0x41) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ - case 3: return (cznv & 0x41) != 0; /* GET_CFLG || GET_ZFLG; LS */ - case 4: return (cznv & 1) == 0; /* !GET_CFLG; CC */ - case 5: return (cznv & 1) != 0; /* GET_CFLG; CS */ - case 6: return (cznv & 0x40) == 0; /* !GET_ZFLG; NE */ - case 7: return (cznv & 0x40) != 0; /* GET_ZFLG; EQ */ - case 8: return (cznv & 0x800) == 0;/* !GET_VFLG; VC */ - case 9: return (cznv & 0x800) != 0;/* GET_VFLG; VS */ - case 10:return (cznv & 0x80) == 0; /* !GET_NFLG; PL */ - case 11:return (cznv & 0x80) != 0; /* GET_NFLG; MI */ - case 12:return (((cznv << 4) ^ cznv) & 0x800) == 0; /* GET_NFLG == GET_VFLG; GE */ - case 13:return (((cznv << 4) ^ cznv) & 0x800) != 0;/* GET_NFLG != GET_VFLG; LT */ - case 14: - cznv &= 0x8c0; - return (((cznv << 4) ^ cznv) & 0x840) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ - case 15: - cznv &= 0x8c0; - return (((cznv << 4) ^ cznv) & 0x840) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + + switch (cc) { + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */ + case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */ + case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */ + case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */ + case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */ + case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */ + case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */ + case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */ + case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */ + case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */ +#if FLAGBIT_N > FLAGBIT_V + case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */ + case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */ + case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */ + return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0; + case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */ + return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0; +#else + case 12: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) == 0; /* NFLG == VFLG GE */ + case 13: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) != 0; /* NFLG != VFLG LT */ + case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */ + return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) == 0; + case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */ + return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) != 0; +#endif } + abort (); return 0; } @@ -93,34 +134,34 @@ static __inline__ int cctrue(int cc) __asm__ __volatile__ ("andl %1,%1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv) : "r" (v) : "cc") + : "=rm" (regflags.cznv) : "r" (v) : "memory", "cc") #define optflag_testw(v) \ __asm__ __volatile__ ("andw %w1,%w1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv) : "r" (v) : "cc") + : "=rm" (regflags.cznv) : "r" (v) : "memory", "cc") #define optflag_testb(v) \ __asm__ __volatile__ ("andb %b1,%b1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv) : "q" (v) : "cc") + : "=rm" (regflags.cznv) : "q" (v) : "memory", "cc") #define optflag_addl(v, s, d) do { \ __asm__ __volatile__ ("addl %k2,%k1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ - COPY_CARRY; \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + COPY_CARRY(); \ } while (0) #define optflag_addw(v, s, d) do { \ __asm__ __volatile__ ("addw %w2,%w1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ - COPY_CARRY; \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + COPY_CARRY(); \ } while (0) #define optflag_addb(v, s, d) do { \ @@ -128,113 +169,151 @@ static __inline__ int cctrue(int cc) "pushf\n\t" \ "pop %0\n\t" \ : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_subl(v, s, d) do { \ __asm__ __volatile__ ("subl %k2,%k1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ - COPY_CARRY; \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + COPY_CARRY(); \ } while (0) #define optflag_subw(v, s, d) do { \ __asm__ __volatile__ ("subw %w2,%w1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \ - COPY_CARRY; \ + : "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \ + COPY_CARRY(); \ } while (0) #define optflag_subb(v, s, d) do { \ __asm__ __volatile__ ("subb %b2,%b1\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \ - COPY_CARRY; \ + : "=rm" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "memory", "cc"); \ + COPY_CARRY(); \ } while (0) #define optflag_cmpl(s, d) \ __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") + : "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc") #define optflag_cmpw(s, d) \ __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") + : "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc") #define optflag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \ "pushf\n\t" \ "pop %0\n\t" \ - : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc") + : "=rm" (regflags.cznv) : "qmi" (s), "q" (d) : "memory", "cc") -#else +#else /* !SAHF_SETO_PROFITABLE */ +/* + * Machine dependent structure for holding the 68k CCR flags + */ struct flag_struct { - uae_u32 cznv; - uae_u32 x; + uae_u32 cznv; + uae_u32 x; }; -#define FLAGVAL_Z 0x4000 -#define FLAGVAL_N 0x8000 +extern struct flag_struct regflags __asm__ ("regflags"); -#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14)) -#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8)) -#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1))) -#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15)) -#define SET_XFLG(y) (regflags.x = (y)) +/* + * The bits in the cznv field in the above structure are assigned to + * allow the easy mirroring of the x86 condition flags. (For example, + * from the AX register - the x86 overflow flag can be copied to AL + * with a setto %AL instr and the other flags copied to AH with an + * lahf instr). + * + * The 68k CZNV flags are thus assigned in cznv as: + * + * <--AL--> <--AH--> + * 76543210 FEDCBA98 --------- --------- + * xxxxxxxV NZxxxxxC xxxxxxxxx xxxxxxxxx + */ -#define GET_ZFLG ((regflags.cznv >> 14) & 1) -#define GET_CFLG ((regflags.cznv >> 8) & 1) -#define GET_VFLG ((regflags.cznv >> 0) & 1) -#define GET_NFLG ((regflags.cznv >> 15) & 1) -#define GET_XFLG (regflags.x & 1) +#define FLAGBIT_N 15 +#define FLAGBIT_Z 14 +#define FLAGBIT_C 8 +#define FLAGBIT_V 0 +#define FLAGBIT_X 0 /* must be in position 0 for duplicate_carry() to work */ -#define CLEAR_CZNV (regflags.cznv = 0) -#define GET_CZNV (regflags.cznv) -#define IOR_CZNV(X) (regflags.cznv |= (X)) -#define SET_CZNV(X) (regflags.cznv = (X)) +#define FLAGVAL_N (1 << FLAGBIT_N) +#define FLAGVAL_Z (1 << FLAGBIT_Z) +#define FLAGVAL_C (1 << FLAGBIT_C) +#define FLAGVAL_V (1 << FLAGBIT_V) +#define FLAGVAL_X (1 << FLAGBIT_X) -#define COPY_CARRY (regflags.x = (regflags.cznv)>>8) +#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z)) +#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C)) +#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V)) +#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_N) | (((y) & 1) << FLAGBIT_N)) +#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X) -extern struct flag_struct regflags ASM_SYM("regflags"); +#define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1) +#define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1) +#define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1) +#define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1) +#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1) -static __inline__ int cctrue(int cc) +#define CLEAR_CZNV() (regflags.cznv = 0) +#define GET_CZNV() (regflags.cznv) +#define IOR_CZNV(X) (regflags.cznv |= (X)) +#define SET_CZNV(X) (regflags.cznv = (X)) + +#define COPY_CARRY() (regflags.x = regflags.cznv >> (FLAGBIT_C - FLAGBIT_X)) + + +/* + * Test CCR condition + */ +static inline int cctrue(int cc) { uae_u32 cznv = regflags.cznv; - switch(cc){ - case 0: return 1; /* T */ - case 1: return 0; /* F */ - case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ - case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */ - case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */ - case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */ - case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */ - case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */ - case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */ - case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */ - case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */ - case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */ - case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */ - case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */ - case 14: - cznv &= 0xc001; - return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ - case 15: - cznv &= 0xc001; - return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + + switch (cc) { + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */ + case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */ + case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */ + case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */ + case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */ + case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */ + case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */ + case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */ + case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */ + case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */ +#if FLAGBIT_N > FLAGBIT_V + case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */ + case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */ + case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */ + return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0; + case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */ + return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0; +#else + case 12: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) == 0; /* NFLG == VFLG GE */ + case 13: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) != 0; /* NFLG != VFLG LT */ + case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */ + return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) == 0; + case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */ + return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) != 0; +#endif } - abort(); + abort (); return 0; } /* Manually emit LAHF instruction so that 64-bit assemblers can grok it */ -#if defined __x86_64__ && defined __GNUC__ +#if defined CPU_x86_64 && defined __GNUC__ #define ASM_LAHF ".byte 0x9f" #else #define ASM_LAHF "lahf" @@ -273,7 +352,7 @@ static __inline__ int cctrue(int cc) "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_addw(v, s, d) do { \ @@ -283,7 +362,7 @@ static __inline__ int cctrue(int cc) "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_addb(v, s, d) do { \ @@ -293,7 +372,7 @@ static __inline__ int cctrue(int cc) "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_subl(v, s, d) do { \ @@ -303,7 +382,7 @@ static __inline__ int cctrue(int cc) "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_subw(v, s, d) do { \ @@ -313,7 +392,7 @@ static __inline__ int cctrue(int cc) "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_subb(v, s, d) do { \ @@ -323,7 +402,7 @@ static __inline__ int cctrue(int cc) "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ - COPY_CARRY; \ + COPY_CARRY(); \ } while (0) #define optflag_cmpl(s, d) \ @@ -340,7 +419,7 @@ static __inline__ int cctrue(int cc) "seto %%al\n\t" \ "movb %%al,regflags\n\t" \ "movb %%ah,regflags+1\n\t" \ - : : "rmi" (s), "r" (d) : "%eax","cc","memory"); + : : "rmi" (s), "r" (d) : "%eax","cc","memory") #define optflag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ @@ -350,10 +429,306 @@ static __inline__ int cctrue(int cc) "movb %%ah,regflags+1\n\t" \ : : "qmi" (s), "q" (d) : "%eax","cc","memory") +#endif /* SAHF_SETO_PROFITABLE */ + +#elif defined(CPU_arm) && defined(ARM_ASSEMBLY) + +/* + * Machine dependent structure for holding the 68k CCR flags + */ +struct flag_struct { + uae_u32 nzcv; + uae_u32 x; +}; + +#define FLAGBIT_N 31 +#define FLAGBIT_Z 30 +#define FLAGBIT_C 29 +#define FLAGBIT_V 28 +#define FLAGBIT_X FLAGBIT_C /* must be in the same position in as x flag */ + +#define FLAGVAL_N (1 << FLAGBIT_N) +#define FLAGVAL_Z (1 << FLAGBIT_Z) +#define FLAGVAL_C (1 << FLAGBIT_C) +#define FLAGVAL_V (1 << FLAGBIT_V) +#define FLAGVAL_X (1 << FLAGBIT_X) + +#define SET_NFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_N) | (((y) & 1) << FLAGBIT_N)) +#define SET_ZFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z)) +#define SET_CFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C)) +#define SET_VFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V)) +#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X) + +#define GET_NFLG() ((regflags.nzcv >> FLAGBIT_N) & 1) +#define GET_ZFLG() ((regflags.nzcv >> FLAGBIT_Z) & 1) +#define GET_CFLG() ((regflags.nzcv >> FLAGBIT_C) & 1) +#define GET_VFLG() ((regflags.nzcv >> FLAGBIT_V) & 1) +#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1) + +#define CLEAR_CZNV() (regflags.nzcv = 0) +#define GET_CZNV() (regflags.nzcv) +#define IOR_CZNV(X) (regflags.nzcv |= (X)) +#define SET_CZNV(X) (regflags.nzcv = (X)) + +#define COPY_CARRY() (regflags.x = regflags.nzcv >> (FLAGBIT_C - FLAGBIT_X)) + +extern struct flag_struct regflags __asm__ ("regflags"); + +/* + * Test CCR condition + */ +static inline int cctrue(int cc) +{ + unsigned int nzcv = regflags.nzcv; + switch(cc){ + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (nzcv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ + case 3: return (nzcv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* GET_CFLG || GET_ZFLG; LS */ + case 4: return (nzcv & FLAGVAL_C) == 0; /* !GET_CFLG; CC */ + case 5: return (nzcv & FLAGVAL_C) != 0; /* GET_CFLG; CS */ + case 6: return (nzcv & FLAGVAL_Z) == 0; /* !GET_ZFLG; NE */ + case 7: return (nzcv & FLAGVAL_Z) != 0; /* GET_ZFLG; EQ */ + case 8: return (nzcv & FLAGVAL_V) == 0; /* !GET_VFLG; VC */ + case 9: return (nzcv & FLAGVAL_V) != 0; /* GET_VFLG; VS */ + case 10:return (nzcv & FLAGVAL_N) == 0; /* !GET_NFLG; PL */ + case 11:return (nzcv & FLAGVAL_N) != 0; /* GET_NFLG; MI */ + case 12:return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & FLAGVAL_N) == 0; /* GET_NFLG == GET_VFLG; GE */ + case 13:return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & FLAGVAL_N) != 0; /* GET_NFLG != GET_VFLG; LT */ + case 14: nzcv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); + return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & (FLAGVAL_N | FLAGVAL_Z)) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ + case 15: nzcv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); + return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & (FLAGVAL_N | FLAGVAL_Z)) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + } + return 0; +} + +#define optflag_testl(v) do {\ + __asm__ __volatile__ ("tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "r" (v) \ + : "cc"); \ + } while(0) + +#define optflag_addl(v, s, d) do { \ + __asm__ __volatile__ ("adds %[rv],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_subl(v, s, d) do { \ + __asm__ __volatile__ ("subs %[rv],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_cmpl(s, d) do { \ + __asm__ __volatile__ ("cmp %[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#if defined(ARMV6_ASSEMBLY) + +// #pragma message "ARM/v6 Assembly optimized flags" + +#define optflag_testw(v) do { \ + __asm__ __volatile__ ("sxth %[rv],%[rv]\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_testb(v) do {\ + __asm__ __volatile__ ("sxtb %[rv],%[rv]\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_addw(v, s, d) do { \ + __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ + "sxth %[rs],%[rs]\n\t" \ + "adds %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_addb(v, s, d) do { \ + __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ + "sxtb %[rs],%[rs]\n\t" \ + "adds %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_subw(v, s, d) do { \ + __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ + "sxth %[rs],%[rs]\n\t" \ + "subs %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_subb(v, s, d) do { \ + __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ + "sxtb %[rs],%[rs]\n\t" \ + "subs %[rd],%[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_cmpw(s, d) do { \ + __asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \ + "sxth %[rs],%[rs]\n\t" \ + "cmp %[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#define optflag_cmpb(s, d) do { \ + __asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \ + "sxtb %[rs],%[rs]\n\t" \ + "cmp %[rd],%[rs]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#else + +// #pragma message "ARM/generic Assembly optimized flags" + +#define optflag_testw(v) do { \ + __asm__ __volatile__ ("lsl %[rv],%[rv],#16\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_testb(v) do {\ + __asm__ __volatile__ ("lsl %[rv],%[rv],#24\n\t" \ + "tst %[rv],%[rv]\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "bic %[nzcv],#0x30000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rv] "0" (v) \ + : "cc"); \ + }while(0) + +#define optflag_addw(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ + "adds %[rd],%[rd],%[rs],lsl #16\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "lsr %[rv],%[rd],#16\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_addb(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ + "adds %[rd],%[rd],%[rs],lsl #24\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "lsr %[rv],%[rd],#24\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_subw(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ + "subs %[rd],%[rd],%[rs],lsl #16\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + "lsr %[rv],%[rd],#16\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_subb(v, s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ + "subs %[rd],%[rd],%[rs],lsl #24\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + "lsr %[rv],%[rd],#24\n\t" \ + : [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \ + : [rs] "ri" (s), [rd] "1" (d) \ + : "cc"); \ + COPY_CARRY(); \ + } while(0) + +#define optflag_cmpw(s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \ + "cmp %[rd],%[rs],lsl #16\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + +#define optflag_cmpb(s, d) do { \ + __asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \ + "cmp %[rd],%[rs],lsl #24\n\t" \ + "mrs %[nzcv],cpsr\n\t" \ + "eor %[nzcv],#0x20000000\n\t" \ + : [nzcv] "=r" (regflags.nzcv) \ + : [rs] "ri" (s), [rd] "0" (d) \ + : "cc"); \ + } while(0) + #endif -#elif defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) +#elif defined(CPU_sparc) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)) +/* + * Machine dependent structure for holding the 68k CCR flags + */ struct flag_struct { unsigned char nzvc; unsigned char x; @@ -361,52 +736,62 @@ struct flag_struct { extern struct flag_struct regflags; -#define FLAGVAL_Z 0x04 -#define FLAGVAL_N 0x08 +#define FLAGBIT_N 3 +#define FLAGBIT_Z 2 +#define FLAGBIT_V 1 +#define FLAGBIT_C 0 +#define FLAGBIT_X FLAGBIT_C /* should be in the same position as the x flag */ -#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) -#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) -#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) -#define SET_XFLG(y) (regflags.x = (y)) +#define FLAGVAL_N (1 << FLAGBIT_N) +#define FLAGVAL_Z (1 << FLAGBIT_Z) +#define FLAGVAL_C (1 << FLAGBIT_C) +#define FLAGVAL_V (1 << FLAGBIT_V) +#define FLAGVAL_X (1 << FLAGBIT_X) -#define GET_ZFLG ((regflags.nzvc >> 2) & 1) -#define GET_CFLG (regflags.nzvc & 1) -#define GET_VFLG ((regflags.nzvc >> 1) & 1) -#define GET_NFLG ((regflags.nzvc >> 3) & 1) -#define GET_XFLG (regflags.x & 1) +#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z)) +#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C)) +#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V)) +#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_N)) +#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X) -#define CLEAR_CZNV (regflags.nzvc = 0) -#define GET_CZNV (reflags.nzvc) -#define IOR_CZNV(X) (refglags.nzvc |= (X)) -#define SET_CZNV(X) (regflags.nzvc = (X)) +#define GET_ZFLG() ((regflags.nzvc >> FLAGBIT_Z) & 1) +#define GET_CFLG() ((regflags.nzvc >> FLAGBIT_C) & 1) +#define GET_VFLG() ((regflags.nzvc >> FLAGBIT_V) & 1) +#define GET_NFLG() ((regflags.nzvc >> FLAGBIT_N) & 1) +#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1) -#define COPY_CARRY (regflags.x = regflags.nzvc) +#define CLEAR_CZNV() (regflags.nzvc = 0) +#define GET_CZNV() (regflags.nzvc) +#define IOR_CZNV(X) (regflags.nzvc |= (X)) +#define SET_CZNV(X) (regflags.nzvc = (X)) -static __inline__ int cctrue(int cc) +#define COPY_CARRY() (regflags.x = regflags.nzvc >> (FLAGBIT_C - FLAGBIT_X)) + +/* + * Test CCR condition + */ +static inline int cctrue(int cc) { uae_u32 nzvc = regflags.nzvc; - switch(cc){ - case 0: return 1; /* T */ - case 1: return 0; /* F */ - case 2: return (nzvc & 0x05) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ - case 3: return (nzvc & 0x05) != 0; /* GET_CFLG || GET_ZFLG; LS */ - case 4: return (nzvc & 1) == 0; /* !GET_CFLG; CC */ - case 5: return (nzvc & 1) != 0; /* GET_CFLG; CS */ - case 6: return (nzvc & 0x04) == 0; /* !GET_ZFLG; NE */ - case 7: return (nzvc & 0x04) != 0; /* GET_ZFLG; EQ */ - case 8: return (nzvc & 0x02) == 0;/* !GET_VFLG; VC */ - case 9: return (nzvc & 0x02) != 0;/* GET_VFLG; VS */ - case 10:return (nzvc & 0x08) == 0; /* !GET_NFLG; PL */ - case 11:return (nzvc & 0x08) != 0; /* GET_NFLG; MI */ - case 12:return (((nzvc << 2) ^ nzvc) & 0x08) == 0; /* GET_NFLG == GET_VFLG; GE */ - case 13:return (((nzvc << 2) ^ nzvc) & 0x08) != 0;/* GET_NFLG != GET_VFLG; LT */ - case 14: - nzvc &= 0x0e; - return (((nzvc << 2) ^ nzvc) & 0x0c) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ - case 15: - nzvc &= 0x0e; - return (((nzvc << 2) ^ nzvc) & 0x0c) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + switch (cc) { + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */ + case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */ + case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */ + case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */ + case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */ + case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */ + case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */ + case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */ + case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */ + case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */ + case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */ + case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */ + case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG && (NFLG == VFLG) GT */ + return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0; + case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG && (NFLG != VFLG) LE */ + return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0; } return 0; } @@ -1008,6 +1393,9 @@ static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae #else +/* + * Machine independent structure for holding the 68k CCR flags + */ struct flag_struct { unsigned int c; unsigned int z; @@ -1030,22 +1418,25 @@ extern struct flag_struct regflags; #define SET_ZFLG(x) (ZFLG = (x)) #define SET_XFLG(x) (XFLG = (x)) -#define GET_CFLG CFLG -#define GET_NFLG NFLG -#define GET_VFLG VFLG -#define GET_ZFLG ZFLG -#define GET_XFLG XFLG +#define GET_CFLG() CFLG +#define GET_NFLG() NFLG +#define GET_VFLG() VFLG +#define GET_ZFLG() ZFLG +#define GET_XFLG() XFLG -#define CLEAR_CZNV do { \ +#define CLEAR_CZNV() do { \ SET_CFLG (0); \ SET_ZFLG (0); \ SET_NFLG (0); \ SET_VFLG (0); \ } while (0) -#define COPY_CARRY (SET_XFLG (GET_CFLG)) +#define COPY_CARRY() (SET_XFLG (GET_CFLG ())) -static __inline__ int cctrue(const int cc) +/* + * Test CCR condition + */ +static inline int cctrue(const int cc) { switch(cc){ case 0: return 1; /* T */ diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index e981aa2b..dc109422 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -678,8 +678,8 @@ void MakeSR (void) #endif regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) - | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) - | GET_CFLG); + | (GET_XFLG() << 4) | (GET_NFLG() << 3) | (GET_ZFLG() << 2) | (GET_VFLG() << 1) + | GET_CFLG()); } void MakeFromSR (void) @@ -858,7 +858,7 @@ int m68k_move2c (int regno, uae_u32 *regp) #if USE_JIT set_cache_state(regs.cacr & 0x8000); if (*regp & 0x08) { /* Just to be on the safe side */ - flush_icache(1); + flush_icache(); } #endif break; @@ -1268,7 +1268,7 @@ void mmu_op(uae_u32 opcode, uae_u16 extra) /* PFLUSH */ mmusr = 0; #ifdef USE_JIT - flush_icache(0); + flush_icache(); #endif } else if ((opcode & 0x0FD8) == 0x548) { /* PTEST */ @@ -1501,7 +1501,7 @@ void m68k_dumpstate (uaecptr *nextpc) regs.usp,regs.isp,regs.msp,regs.vbr); printf ("T=%d%d S=%d M=%d X=%ld N=%ld Z=%ld V=%ld C=%ld IMASK=%d\n", regs.t1, regs.t0, regs.s, regs.m, - GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); + GET_XFLG(), GET_NFLG(), GET_ZFLG(), GET_VFLG(), GET_CFLG(), regs.intmask); fpu_dump_registers(); fpu_dump_flags(); diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h index eacbc214..e87d22b4 100644 --- a/BasiliskII/src/uae_cpu/noflags.h +++ b/BasiliskII/src/uae_cpu/noflags.h @@ -62,13 +62,13 @@ static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) #define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0) #undef CLEAR_CZNV -#define CLEAR_CZNV +#define CLEAR_CZNV() do {} while (0) #undef IOR_CZNV #define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0) #undef SET_CZNV #define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0) #undef COPY_CARRY -#define COPY_CARRY +#define COPY_CARRY() do {} while (0) #ifdef optflag_testl #undef optflag_testl From 28bc58ccd20a1914e2c2c3bba2236ae124fb3a9a Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 1 Sep 2019 17:01:25 -0500 Subject: [PATCH 13/20] Use release configuration by default --- BasiliskII/src/Unix/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index eb217226..e222edc3 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -1,6 +1,11 @@ cmake_minimum_required(VERSION 3.0.0) project(BasiliskII) +if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt) + if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) + endif() +endif() find_package(SDL2 REQUIRED) find_library(COREFOUNDATION_LIBRARY CoreFoundation) From 03fc337242c7f249a3d58f9d8fc2006edc18f9df Mon Sep 17 00:00:00 2001 From: uyjulian Date: Mon, 2 Sep 2019 14:40:01 -0500 Subject: [PATCH 14/20] uae_cpu is based upon ARAnyM sources --- BasiliskII/src/Unix/CMakeLists.txt | 19 +- BasiliskII/src/Unix/main_unix.cpp | 5 +- BasiliskII/src/Unix/sysdeps.h | 7 + BasiliskII/src/emul_op.cpp | 12 +- BasiliskII/src/include/emul_op.h | 2 +- BasiliskII/src/include/main.h | 4 +- BasiliskII/src/uae_cpu/Makefile.am | 80 + BasiliskII/src/uae_cpu/aranym_glue.cpp | 326 +++ BasiliskII/src/uae_cpu/basilisk_glue.cpp | 31 +- BasiliskII/src/uae_cpu/build68k.c | 72 +- .../src/uae_cpu/compiler/compemu_support.cpp | 7 +- BasiliskII/src/uae_cpu/compiler/gencomp.c | 3 +- BasiliskII/src/uae_cpu/compiler/gencomp_arm.c | 3 +- BasiliskII/src/uae_cpu/cpu_emulation.h | 235 +- BasiliskII/src/uae_cpu/cpudefsa.cpp | 5 + BasiliskII/src/uae_cpu/cpuemu1.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu1_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu2.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu2_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu3.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu3_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu4.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu4_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu5.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu5_nf.cpp | 4 + BasiliskII/src/uae_cpu/cpuemu6.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu6_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu7.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu7_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpuemu8.cpp | 2 + BasiliskII/src/uae_cpu/cpuemu8_nf.cpp | 3 + BasiliskII/src/uae_cpu/cpufunctbla.cpp | 5 + BasiliskII/src/uae_cpu/cpummu.cpp | 1096 ++++++++ BasiliskII/src/uae_cpu/cpummu.h | 267 ++ BasiliskII/src/uae_cpu/cpustbl_nf.cpp | 2 + BasiliskII/src/uae_cpu/cpustbla.cpp | 5 + BasiliskII/src/uae_cpu/debug.cpp | 82 + BasiliskII/src/uae_cpu/fpu/core.h | 78 +- BasiliskII/src/uae_cpu/fpu/exceptions.cpp | 45 +- BasiliskII/src/uae_cpu/fpu/exceptions.h | 45 +- BasiliskII/src/uae_cpu/fpu/flags.cpp | 45 +- BasiliskII/src/uae_cpu/fpu/flags.h | 71 +- BasiliskII/src/uae_cpu/fpu/fpu.h | 50 +- BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp | 920 ++++--- BasiliskII/src/uae_cpu/fpu/fpu_ieee.h | 55 +- BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp | 2110 +++++++++++++++ BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp | 451 ++-- BasiliskII/src/uae_cpu/fpu/fpu_uae.h | 53 +- BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp | 761 +++++- BasiliskII/src/uae_cpu/fpu/fpu_x86.h | 87 +- BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h | 32 + BasiliskII/src/uae_cpu/fpu/impl.h | 61 +- BasiliskII/src/uae_cpu/fpu/mathlib.cpp | 47 +- BasiliskII/src/uae_cpu/fpu/mathlib.h | 614 +++-- BasiliskII/src/uae_cpu/fpu/rounding.cpp | 45 +- BasiliskII/src/uae_cpu/fpu/rounding.h | 61 +- BasiliskII/src/uae_cpu/fpu/types.h | 72 +- BasiliskII/src/uae_cpu/gencpu.c | 1576 ++++++----- BasiliskII/src/uae_cpu/m68k.h | 25 +- BasiliskII/src/uae_cpu/memory-uae.h | 606 +++++ BasiliskII/src/uae_cpu/memory.cpp | 647 +---- BasiliskII/src/uae_cpu/memory.h | 157 +- BasiliskII/src/uae_cpu/newcpu.cpp | 2393 +++++++++-------- BasiliskII/src/uae_cpu/newcpu.h | 353 +-- BasiliskII/src/uae_cpu/noflags.h | 8 +- BasiliskII/src/uae_cpu/readcpu.cpp | 267 +- BasiliskII/src/uae_cpu/readcpu.h | 73 +- BasiliskII/src/uae_cpu/readcpua.cpp | 5 + BasiliskII/src/uae_cpu/registers.h | 116 + BasiliskII/src/uae_cpu/spcflags.h | 210 +- BasiliskII/src/uae_cpu/table68k | 111 +- 71 files changed, 10246 insertions(+), 4313 deletions(-) create mode 100644 BasiliskII/src/uae_cpu/Makefile.am create mode 100644 BasiliskII/src/uae_cpu/aranym_glue.cpp create mode 100644 BasiliskII/src/uae_cpu/cpudefsa.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu1.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu1_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu2.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu2_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu3.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu3_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu4.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu4_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu5.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu5_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu6.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu6_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu7.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu7_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu8.cpp create mode 100644 BasiliskII/src/uae_cpu/cpuemu8_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpufunctbla.cpp create mode 100644 BasiliskII/src/uae_cpu/cpummu.cpp create mode 100644 BasiliskII/src/uae_cpu/cpummu.h create mode 100644 BasiliskII/src/uae_cpu/cpustbl_nf.cpp create mode 100644 BasiliskII/src/uae_cpu/cpustbla.cpp create mode 100644 BasiliskII/src/uae_cpu/debug.cpp create mode 100644 BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp create mode 100644 BasiliskII/src/uae_cpu/memory-uae.h create mode 100644 BasiliskII/src/uae_cpu/readcpua.cpp create mode 100644 BasiliskII/src/uae_cpu/registers.h diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index e222edc3..0711d0d7 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.0.0) project(BasiliskII) -if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt) - if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) - endif() -endif() +# if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt) +# if (NOT CMAKE_BUILD_TYPE) +# set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) +# endif() +# endif() find_package(SDL2 REQUIRED) find_library(COREFOUNDATION_LIBRARY CoreFoundation) @@ -21,7 +21,9 @@ add_custom_command(OUTPUT cpudefs.cpp add_executable(gencpu ../uae_cpu/gencpu.c ../uae_cpu/readcpu.cpp cpudefs.cpp) #add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu) -add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu) +# add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu) +# add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu) +add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu) add_executable(gencomp ../uae_cpu/compiler/gencomp.c ../uae_cpu/readcpu.cpp cpudefs.cpp) @@ -88,12 +90,11 @@ set(BasiliskII_SRCS cpustbl.cpp cpudefs.cpp cpuemu.cpp + cpufunctbl.cpp compemu.cpp compstbl.cpp ../uae_cpu/compiler/compemu_support.cpp ../uae_cpu/compiler/compemu_fpp.cpp - cpustbl_nf.cpp - cpuemu_nf.cpp #addressing mode =direct -DDIRECT_ADDRESSING #includes ) @@ -101,7 +102,7 @@ set(BasiliskII_SRCS add_executable(BasiliskII ${BasiliskII_SRCS}) set_source_files_properties(${BasiliskII_SRCS} - PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DCPU_x86_64 -DFIXED_ADDRESSING -DCPU_64_BIT -DNOFLAGS_SUPPORT -DFPU_IEEE -DUSE_JIT -DJIT -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS -DWINUAE_ARANYM -DUSE_JIT_FPU -DUSE_INLINING -DDATADIR=\\\".\\\"") + PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DCPU_x86_64 -DFIXED_ADDRESSING -DCPU_64_BIT -DFPU_IEEE -DUSE_JIT -DJIT -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS -DWINUAE_ARANYM -DUSE_JIT_FPU -DUSE_INLINING -DDATADIR=\\\".\\\"") # set_property(SOURCE compemu_support.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O0 ") diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 6d17121f..f7dcc682 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -58,6 +58,7 @@ using std::string; #if USE_JIT extern void (*flush_icache)(void); // from compemu_support.cpp +extern bool UseJIT; #endif @@ -181,8 +182,8 @@ static void sigsegv_dump_state(sigsegv_info_t *sip) fprintf(stderr, " [IP=%p]", fault_instruction); fprintf(stderr, "\n"); #if EMULATED_68K - extern void m68k_dumpstate (uaecptr *); - m68k_dumpstate(0); + extern void m68k_dumpstate (FILE *, uaecptr *); + m68k_dumpstate(stderr, 0); #endif #if USE_JIT && JIT_DEBUG extern void compiler_dumpstate(void); diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index b25ee042..1a1f12a8 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -419,6 +419,13 @@ static inline uae_u32 do_byteswap_16(uae_u32 v) # define REGPARAM #endif #define REGPARAM2 + +#if __GNUC__ < 3 +# define __builtin_expect(foo,bar) (foo) +#endif +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#define ALWAYS_INLINE inline __attribute__((always_inline)) #define memptr uint32 diff --git a/BasiliskII/src/emul_op.cpp b/BasiliskII/src/emul_op.cpp index 549d1de0..25679f70 100644 --- a/BasiliskII/src/emul_op.cpp +++ b/BasiliskII/src/emul_op.cpp @@ -51,7 +51,7 @@ * Execute EMUL_OP opcode (called by 68k emulator or Illegal Instruction trap handler) */ -void EmulOp(uint16 opcode, M68kRegisters *r) +bool EmulOp(uint16 opcode, M68kRegisters *r) { D(bug("EmulOp %04x\n", opcode)); switch (opcode) { @@ -68,12 +68,12 @@ void EmulOp(uint16 opcode, M68kRegisters *r) VideoQuitFullScreen(); QuitEmulator(); - break; + return false; } case M68K_EMUL_OP_SHUTDOWN: // Quit emulator QuitEmulator(); - break; + return false; case M68K_EMUL_OP_RESET: { // MacOS reset D(bug("*** RESET ***\n")); @@ -101,7 +101,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r) r->a[1] = ROMBaseMac + UniversalInfo; // UniversalInfo r->a[6] = boot_globs; // BootGlobs r->a[7] = RAMBaseMac + 0x10000; // Boot stack - break; + return false; } case M68K_EMUL_OP_CLKNOMEM: { // Clock/PRAM operations @@ -570,6 +570,8 @@ void EmulOp(uint16 opcode, M68kRegisters *r) r->sr); QuitEmulator(); - break; + return false; } + + return true; } diff --git a/BasiliskII/src/include/emul_op.h b/BasiliskII/src/include/emul_op.h index b6d3a1e6..5774a580 100644 --- a/BasiliskII/src/include/emul_op.h +++ b/BasiliskII/src/include/emul_op.h @@ -94,6 +94,6 @@ enum { }; // Functions -extern void EmulOp(uint16 opcode, struct M68kRegisters *r); // Execute EMUL_OP opcode (called by 68k emulator or Line-F trap handler) +extern bool EmulOp(uint16 opcode, struct M68kRegisters *r); // Execute EMUL_OP opcode (called by 68k emulator or Line-F trap handler) #endif diff --git a/BasiliskII/src/include/main.h b/BasiliskII/src/include/main.h index 1ba7b6ac..9a78cf6e 100644 --- a/BasiliskII/src/include/main.h +++ b/BasiliskII/src/include/main.h @@ -34,8 +34,10 @@ extern bool TwentyFourBitAddressing; // 68k register structure (for Execute68k()) struct M68kRegisters { uint32 d[8]; - uint32 a[8]; + memptr a[8]; uint16 sr; + memptr usp, isp, msp; + memptr pc; }; // General functions diff --git a/BasiliskII/src/uae_cpu/Makefile.am b/BasiliskII/src/uae_cpu/Makefile.am new file mode 100644 index 00000000..fa42287d --- /dev/null +++ b/BasiliskII/src/uae_cpu/Makefile.am @@ -0,0 +1,80 @@ +# +# Note: this Makefile only contains rules for the source +# generator tools. +# + +# +# suppress warnings about overriding LDFLAGS and CPPFLAGS +# +AUTOMAKE_OPTIONS = -Wno-gnu + +AM_CPPFLAGS = $(DEFINES) \ + "-I$(srcdir)/../include" \ + "-I$(srcdir)/../Unix" \ + "-I$(builddir)/.." \ + "-I$(builddir)" \ + "-I$(srcdir)" + +CC = $(CC_FOR_BUILD) +CXX = $(CXX_FOR_BUILD) + +LDFLAGS = $(LDFLAGS_FOR_BUILD) +CPPFLAGS = $(CPPFLAGS_FOR_BUILD) +CFLAGS = $(CFLAGS_FOR_BUILD) +CXXFLAGS = $(CXXFLAGS_FOR_BUILD) +LIBS=-lm + +CFLAGS_NOWARN = $(DBGSP) +AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS) +AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS) + +noinst_PROGRAMS = build68k gencpu +if USE_JIT +noinst_PROGRAMS += gencomp +endif + +BUILT_SOURCES = \ + cpudefs.cpp \ + cpuemu.cpp \ + cpustbl.cpp \ + cpufunctbl.cpp \ + cputbl.h \ + $(empty) + +build68k_SOURCES = build68k.c +gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp +gencomp_SOURCES = +if GENCOMP_ARCH_X86 +gencomp_SOURCES += compiler/gencomp.c +endif +if GENCOMP_ARCH_ARM +gencomp_SOURCES += compiler/gencomp_arm.c +endif +gencomp_SOURCES += readcpu.cpp cpudefs.cpp + +if USE_JIT +BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h +endif + + +cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k + $(AM_V_GEN)./build68k <$(srcdir)/table68k > $@ +cpuemu.cpp: gencpu$(EXEEXT) + $(AM_V_GEN)./gencpu$(EXEEXT) +cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp +compemu.cpp: gencomp$(EXEEXT) + $(AM_V_GEN)./gencomp$(EXEEXT) +compstbl.cpp comptbl.h: compemu.cpp + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = \ + table68k \ + compiler/codegen_arm.cpp compiler/codegen_arm.h \ + compiler/compemu_midfunc_arm.cpp compiler/compemu_midfunc_arm.h \ + compiler/compemu_midfunc_arm2.cpp compiler/compemu_midfunc_arm2.h \ + compiler/test_codegen_arm.c \ + compiler/codegen_x86.cpp compiler/codegen_x86.h \ + compiler/compemu_midfunc_x86.cpp compiler/compemu_midfunc_x86.h \ + compiler/test_codegen_x86.cpp \ + $(empty) diff --git a/BasiliskII/src/uae_cpu/aranym_glue.cpp b/BasiliskII/src/uae_cpu/aranym_glue.cpp new file mode 100644 index 00000000..02f7b149 --- /dev/null +++ b/BasiliskII/src/uae_cpu/aranym_glue.cpp @@ -0,0 +1,326 @@ +/* + * aranym_glue.cpp - CPU interface + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" + +#include "cpu_emulation.h" +#include "newcpu.h" +#include "hardware.h" +#include "scc.h" +#include "input.h" +#ifdef USE_JIT +# include "compiler/compemu.h" +#endif +#include "nf_objs.h" + +#include "debug.h" + +// RAM and ROM pointers +memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important +uint8 *RAMBaseHost; // RAM base (host address space) +uint32 RAMSize = 0x00e00000; // Size of RAM + +memptr ROMBase = 0x00e00000; // ROM base (Atari address space) +uint8 *ROMBaseHost; // ROM base (host address space) +uint32 ROMSize = 0x00100000; // Size of ROM + +uint32 RealROMSize; // Real size of ROM + +memptr HWBase = 0x00f00000; // HW base (Atari address space) +uint8 *HWBaseHost; // HW base (host address space) +uint32 HWSize = 0x00100000; // Size of HW space + +memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space) +uint8 *FastRAMBaseHost; // Fast-RAM base (host address space) + +#ifdef HW_SIGSEGV +uint8 *FakeIOBaseHost; +#endif + +#ifdef FIXED_VIDEORAM +memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space) +#else +memptr VideoRAMBase; // VideoRAM base (Atari address space) +#endif +uint8 *VideoRAMBaseHost;// VideoRAM base (host address space) +//uint32 VideoRAMSize; // Size of VideoRAM + +#ifndef NOT_MALLOC +uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent +uintptr ROMBaseDiff; +uintptr FastRAMBaseDiff; +#endif + +uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap + + +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) +SDL_mutex *spcflags_lock; +#endif +#if defined(ENABLE_REALSTOP) +SDL_cond *stop_condition; +#endif + + +/* + * Initialize 680x0 emulation + */ + +bool InitMEM() { + InitMEMBaseDiff(RAMBaseHost, RAMBase); + InitROMBaseDiff(ROMBaseHost, ROMBase); + InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase); + InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase); + return true; +} + +bool Init680x0(void) +{ + init_m68k(); + +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) + if ((spcflags_lock = SDL_CreateMutex()) == NULL) { + panicbug("Error by SDL_CreateMutex()"); + exit(EXIT_FAILURE); + } +#endif + +#if ENABLE_REALSTOP + if ((stop_condition = SDL_CreateCond()) == NULL) { + panicbug("Error by SDL_CreateCond()"); + exit(EXIT_FAILURE); + } +#endif + +#ifdef USE_JIT + if (bx_options.jit.jit) compiler_init(); +#endif + return true; +} + +/* + * Instr. RESET + */ + +void AtariReset(void) +{ + // reset Atari hardware here + HWReset(); + // reset NatFeats here + NFReset(); + // reset the input devices (input.cpp) + InputReset(); + +} + +/* + * Reset CPU + */ + +void Reset680x0(void) +{ + m68k_reset(); +} + +/* + * Deinitialize 680x0 emulation + */ + +void Exit680x0(void) +{ +#ifdef USE_JIT + if (bx_options.jit.jit) compiler_exit(); +#endif + exit_m68k(); +} + + +/* + * Reset and start 680x0 emulation + */ + +void Start680x0(void) +{ + m68k_reset(); +#ifdef USE_JIT + if (bx_options.jit.jit) { + m68k_compile_execute(); + } + else +#endif + m68k_execute(); +} + +/* + * Restart running 680x0 emulation safely from different thread + */ +void Restart680x0(void) +{ + quit_program = 2; + TriggerNMI(); +} + +/* + * Quit 680x0 emulation safely from different thread + */ +void Quit680x0(void) +{ + quit_program = 1; + TriggerNMI(); +} + + +int MFPdoInterrupt(void) +{ + return getMFP()->doInterrupt(); +} + +int SCCdoInterrupt(void) +{ + return getSCC()->doInterrupt(); +} + +/* + * Trigger interrupts + */ +void TriggerInternalIRQ(void) +{ + SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ ); +} + +void TriggerInt3(void) +{ + SPCFLAGS_SET( SPCFLAG_INT3 ); +} + +void TriggerVBL(void) +{ + SPCFLAGS_SET( SPCFLAG_VBL ); +} + +void TriggerInt5(void) +{ + SPCFLAGS_SET( SPCFLAG_INT5 ); +} + +void TriggerSCC(bool enable) +{ + if (enable) + SPCFLAGS_SET( SPCFLAG_SCC ); + else + SPCFLAGS_CLEAR( SPCFLAG_SCC ); +} + +void TriggerMFP(bool enable) +{ + if (enable) + SPCFLAGS_SET( SPCFLAG_MFP ); + else + SPCFLAGS_CLEAR( SPCFLAG_MFP ); +} + +void TriggerNMI(void) +{ + SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI +} + +#ifndef REBOOT_OR_HALT +#define REBOOT_OR_HALT 0 // halt by default +#endif + +#if REBOOT_OR_HALT == 1 +# define CPU_MSG "CPU: Rebooting" +# define CPU_ACTION Restart680x0() +#else +# define CPU_MSG "CPU: Halting" +# define CPU_ACTION Quit680x0() +#endif + +#ifdef ENABLE_EPSLIMITER + +#ifndef EPS_LIMIT +# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */ +#endif + +void check_eps_limit(uaecptr pc) +{ + static long last_exception_time=-1; + static long exception_per_sec=0; + static long exception_per_sec_pc=0; + static uaecptr prevpc = 0; + + if (bx_options.cpu.eps_enabled) { + if (last_exception_time == -1) { + last_exception_time = SDL_GetTicks(); + } + + exception_per_sec++; + + if (pc == prevpc) { + /* BUS ERRORs occur at the same PC - watch out! */ + exception_per_sec_pc++; + } + else { + exception_per_sec_pc = 0; + prevpc = pc; + } + + if (SDL_GetTicks() - last_exception_time > 1000) { + last_exception_time = SDL_GetTicks(); + if (exception_per_sec_pc > bx_options.cpu.eps_max || + exception_per_sec > EPS_LIMIT /* make it configurable */) { + panicbug("CPU: Exception per second limit reached: %ld/%ld", + exception_per_sec_pc, exception_per_sec); + /* would be cool to open SDL dialog here: */ + /* [Exception per seconds limit reached. XXXXX exception + occured in the last second. The limit is set to YYYYY + in your config file. Do you want to continue emulation, + reset ARAnyM or quit ?][Continue] [Reset] [Quit] + */ + panicbug(CPU_MSG); + CPU_ACTION; + } + exception_per_sec = 0; + exception_per_sec_pc = 0; + } + } +} +#endif + +void report_double_bus_error() +{ + panicbug("CPU: Double bus fault detected !"); + /* would be cool to open SDL dialog here: */ + /* [Double bus fault detected. The emulated system crashed badly. + Do you want to reset ARAnyM or quit ?] [Reset] [Quit]" + */ + panicbug(CPU_MSG); + CPU_ACTION; +} + +#ifdef FLIGHT_RECORDER +extern bool cpu_flight_recorder_active; +void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; } +#endif diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index 6bfadb9d..9a794b48 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -56,8 +56,12 @@ uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equiva bool UseJIT = false; #endif +// #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) +B2_mutex *spcflags_lock = NULL; +// #endif + // From newcpu.cpp -extern bool quit_program; +extern int quit_program; /* @@ -66,6 +70,7 @@ extern bool quit_program; bool Init680x0(void) { + spcflags_lock = B2_create_mutex(); #if REAL_ADDRESSING // Mac address space = host address space RAMBaseMac = (uintptr)RAMBaseHost; @@ -159,7 +164,8 @@ void TriggerInterrupt(void) void TriggerNMI(void) { - SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI + //!! not implemented yet + // SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI } @@ -200,7 +206,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) // Execute trap m68k_setpc(m68k_areg(regs, 7)); fill_prefetch_0(); - quit_program = false; + quit_program = 0; m68k_execute(); // Clean up stack @@ -215,7 +221,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) r->d[i] = m68k_dreg(regs, i); for (i=0; i<7; i++) r->a[i] = m68k_areg(regs, i); - quit_program = false; + quit_program = 0; } @@ -247,7 +253,7 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) // Execute routine m68k_setpc(addr); fill_prefetch_0(); - quit_program = false; + quit_program = 0; m68k_execute(); // Clean up stack @@ -262,5 +268,18 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) r->d[i] = m68k_dreg(regs, i); for (i=0; i<7; i++) r->a[i] = m68k_areg(regs, i); - quit_program = false; + quit_program = 0; +} + +void report_double_bus_error() +{ +#if 0 + panicbug("CPU: Double bus fault detected !"); + /* would be cool to open SDL dialog here: */ + /* [Double bus fault detected. The emulated system crashed badly. + Do you want to reset ARAnyM or quit ?] [Reset] [Quit]" + */ + panicbug(CPU_MSG); + CPU_ACTION; +#endif } diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index 8ec3ab55..e996758d 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -1,32 +1,44 @@ +/* + * build68k.c - m68k CPU builder + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * * Read 68000 CPU specs from file "table68k" and build table68k.c * * Copyright 1995,1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include - -#include "sysdeps.h" #include "readcpu.h" +#include +#include +#include +#include +#include +#undef abort + static FILE *tablef; static int nextch = 0; @@ -65,15 +77,15 @@ static int nextchtohex(void) } } -int main(int argc, char **argv) +int main() { int no_insns = 0; printf ("#include \"sysdeps.h\"\n"); printf ("#include \"readcpu.h\"\n"); printf ("struct instr_def defs68k[] = {\n"); -#ifdef WIN32 - tablef = fopen(argc > 1 ? argv[1] : "table68k","r"); +#if 0 + tablef = fopen("table68k","r"); if (tablef == NULL) { fprintf(stderr, "table68k not found\n"); exit(1); @@ -122,8 +134,8 @@ int main(int argc, char **argv) case 'r': currbit = bitr; break; case 'R': currbit = bitR; break; case 'z': currbit = bitz; break; - case 'E': currbit = bitE; break; - case 'p': currbit = bitp; break; + case 'E': currbit = bitE; break; + case 'p': currbit = bitp; break; default: abort(); } if (!(bitmask & 1)) { @@ -138,6 +150,7 @@ int main(int argc, char **argv) patbits[i] = nextch; getnextch(); } + (void) patbits; while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */ getnextch(); @@ -172,6 +185,8 @@ int main(int argc, char **argv) getnextch(); switch(nextch){ case '-': flagset[i] = fa_unset; break; + case '/': flagset[i] = fa_isjmp; break; + case '+': flagset[i] = fa_isbranch; break; case '0': flagset[i] = fa_zero; break; case '1': flagset[i] = fa_one; break; case 'x': flagset[i] = fa_dontcare; break; @@ -191,6 +206,8 @@ int main(int argc, char **argv) getnextch(); switch(nextch){ case '-': flaguse[i] = fu_unused; break; + case '/': flaguse[i] = fu_isjmp; break; + case '+': flaguse[i] = fu_maybecc; break; case '?': flaguse[i] = fu_unknown; break; default: flaguse[i] = fu_used; break; } @@ -235,7 +252,7 @@ int main(int argc, char **argv) if (nextch != ':') abort(); - fgets(opcstr, 250, tablef); + assert(fgets(opcstr, 250, tablef) != NULL); getnextch(); { int j; @@ -243,12 +260,12 @@ int main(int argc, char **argv) char *opstrp = opcstr, *osendp; int slen = 0; - while (isspace(*opstrp)) + while (isspace((int)*opstrp)) opstrp++; osendp = opstrp; while (*osendp) { - if (!isspace (*osendp)) + if (!isspace ((int)*osendp)) slen = osendp - opstrp + 1; osendp++; } @@ -271,6 +288,5 @@ int main(int argc, char **argv) } } printf("};\nint n_defs68k = %d;\n", no_insns); - fflush(stdout); return 0; } diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index 9b178c0f..8932e61d 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -273,7 +273,7 @@ uae_u8* comp_pc_p; #else // External variables // newcpu.cpp -extern bool quit_program; +extern int quit_program; #endif // gb-- Extra data for Basilisk II/JIT @@ -2718,8 +2718,7 @@ void compiler_init(void) jit_log(" : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA)); // Build compiler tables - read_table68k(); - do_merges(); + init_table68k (); build_comp(); #endif @@ -4157,7 +4156,9 @@ void build_comp(void) int count; #ifdef WINUAE_ARANYM unsigned int cpu_level = 4; // 68040 +#if 0 const struct cputbl *nfctbl = op_smalltbl_0_nf; +#endif #else #ifdef NOFLAGS_SUPPORT struct comptbl *nfctbl = (currprefs.cpu_level >= 5 ? op_smalltbl_0_nf diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index 712d7873..202774ac 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -3228,8 +3228,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine int main(void) #endif { - read_table68k (); - do_merges (); + init_table68k (); opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs); opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs); diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c index 7ec9ff76..913361ab 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c @@ -5025,8 +5025,7 @@ void cygwin_mingw_abort() int main(void) { - read_table68k(); - do_merges(); + init_table68k (); opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs); opcode_last_postfix = (int *) malloc(sizeof(int) * nr_cpuop_funcs); diff --git a/BasiliskII/src/uae_cpu/cpu_emulation.h b/BasiliskII/src/uae_cpu/cpu_emulation.h index cd588ec1..b014be79 100644 --- a/BasiliskII/src/uae_cpu/cpu_emulation.h +++ b/BasiliskII/src/uae_cpu/cpu_emulation.h @@ -1,52 +1,170 @@ /* - * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version) + * cpu_emulation.h - CPU interface * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2005 Milan Jurik of ARAnyM dev team (see AUTHORS) * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Inspired by Christian Bauer's Basilisk II * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef CPU_EMULATION_H #define CPU_EMULATION_H -#include - - /* * Memory system */ +#if 0 +#include "sysdeps.h" +#include "memory.h" +#include "tools.h" +#endif + // RAM and ROM pointers (allocated and set by main_*.cpp) +#if 0 +extern memptr RAMBase; // RAM base (Atari address space), does not include Low Mem when != 0 +#else extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0 -extern uint8 *RAMBaseHost; // RAM base (host address space) -extern uint32 RAMSize; // Size of RAM - +#endif +extern uint8 *RAMBaseHost; // RAM base (host address space) +extern uint32 RAMSize; // Size of RAM +#if 0 +extern memptr ROMBase; // ROM base (Atari address space) +#else extern uint32 ROMBaseMac; // ROM base (Mac address space) -extern uint8 *ROMBaseHost; // ROM base (host address space) -extern uint32 ROMSize; // Size of ROM +#endif +extern uint8 *ROMBaseHost; // ROM base (host address space) +extern uint32 ROMSize; // Size of ROM +#if 0 +extern uint32 RealROMSize; // Real size of ROM +extern memptr HWBase; // HW base (Atari address space) +extern uint8 *HWBaseHost; // HW base (host address space) +extern uint32 HWSize; // Size of HW space -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING -// If we are not using real or direct addressing, the Mac frame buffer gets -// mapped to this location. The memory must be allocated by VideoInit(). -// If multiple monitors are used, they must share the frame buffer +extern memptr FastRAMBase; // Fast-RAM base (Atari address space) +extern uint8 *FastRAMBaseHost; // Fast-RAM base (host address space) +extern memptr VideoRAMBase; // VideoRAM base (Atari address space) +extern uint8 *VideoRAMBaseHost; // VideoRAM base (host address space) + +#ifdef HW_SIGSEGV +extern uint8 *FakeIOBaseHost; +#endif + +#ifdef RAMENDNEEDED +# define RAMEnd 0x01000000 // Not accessible top of memory +#else +# define RAMEnd 0 +#endif +#endif +#if !REAL_ADDRESSING +// If we are not using real addressing, the Mac frame buffer gets mapped to this location +// The memory must be allocated by VideoInit(). If multiple monitors are used, they must +// share the frame buffer const uint32 MacFrameBaseMac = 0xa0000000; extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space) extern uint32 MacFrameSize; // Size of frame buffer -#endif extern int MacFrameLayout; // Frame buffer layout (see defines below) +#endif +#if 0 +// Atari memory access functions +// Direct access to CPU address space +// For HW operations +// Read/WriteAtariIntXX +// +static inline uint64 ReadAtariInt64(memptr addr) {return phys_get_quad(addr);} +static inline uint32 ReadAtariInt32(memptr addr) {return phys_get_long(addr);} +static inline uint16 ReadAtariInt16(memptr addr) {return phys_get_word(addr);} +static inline uint8 ReadAtariInt8(memptr addr) {return phys_get_byte(addr);} +static inline void WriteAtariInt64(memptr addr, uint64 q) {phys_put_quad(addr, q);} +static inline void WriteAtariInt32(memptr addr, uint32 l) {phys_put_long(addr, l);} +static inline void WriteAtariInt16(memptr addr, uint16 w) {phys_put_word(addr, w);} +static inline void WriteAtariInt8(memptr addr, uint8 b) {phys_put_byte(addr, b);} + +// Direct access to allocated memory +// Ignores HW checks, so that be carefull +// Read/WriteHWMemIntXX +// +static inline uint32 ReadHWMemInt32(memptr addr) {return do_get_mem_long((uae_u32 *)phys_get_real_address(addr));} +static inline uint16 ReadHWMemInt16(memptr addr) {return do_get_mem_word((uae_u16 *)phys_get_real_address(addr));} +static inline uint8 ReadHWMemInt8(memptr addr) {return do_get_mem_byte((uae_u8 *)phys_get_real_address(addr));} +static inline void WriteHWMemInt32(memptr addr, uint32 l) {do_put_mem_long((uae_u32 *)phys_get_real_address(addr), l);} +static inline void WriteHWMemInt16(memptr addr, uint16 w) {do_put_mem_word((uae_u16 *)phys_get_real_address(addr), w);} +static inline void WriteHWMemInt8(memptr addr, uint8 b) {do_put_mem_byte((uae_u8 *)phys_get_real_address(addr), b);} + +// Indirect access to CPU address space +// Uses MMU if available +// For SW operations +// Only data space +// Read/WriteIntXX +// +static inline uint64 ReadInt64(memptr addr) {return get_quad(addr);} +static inline uint32 ReadInt32(memptr addr) {return get_long(addr);} +static inline uint16 ReadInt16(memptr addr) {return get_word(addr);} +static inline uint8 ReadInt8(memptr addr) {return get_byte(addr);} +static inline void WriteInt64(memptr addr, uint64 q) {put_quad(addr, q);} +static inline void WriteInt32(memptr addr, uint32 l) {put_long(addr, l);} +static inline void WriteInt16(memptr addr, uint16 w) {put_word(addr, w);} +static inline void WriteInt8(memptr addr, uint8 b) {put_byte(addr, b);} + +#ifdef EXTENDED_SIGSEGV +extern int in_handler; +#ifdef NO_NESTED_SIGSEGV +extern JMP_BUF sigsegv_env; +# define BUS_ERROR(a) \ +{ \ + regs.mmu_fault_addr=(a); \ + if (in_handler) \ + { \ + in_handler = 0; \ + LONGJMP(sigsegv_env, 1); \ + } \ + else { \ + breakpt(); \ + THROW(2); \ + } \ +} +#else /* NO_NESTED_SIGSEGV */ +# define BUS_ERROR(a) \ +{ \ + regs.mmu_fault_addr=(a); \ + in_handler = 0; \ + breakpt(); \ + THROW(2); \ +} +#endif /* NO_NESTED_SIGSEGV */ +#else /* EXTENDED_SIGSEGV */ +# define BUS_ERROR(a) \ +{ \ + regs.mmu_fault_addr=(a); \ + breakpt(); \ + THROW(2); \ +} +#endif /* EXTENDED_SIGSEGV */ + +// For address validation +static inline bool ValidAtariAddr(memptr addr, bool write, uint32 len) { return phys_valid_address(addr, write, len); } +static inline bool ValidAddr(memptr addr, bool write, uint32 len) { return valid_address(addr, write, len); } + +// Helper functions for usual memory operations +static inline uint8 *Atari2HostAddr(memptr addr) {return phys_get_real_address(addr);} +#endif // Possible frame buffer layouts enum { FLAYOUT_NONE, // No frame buffer @@ -73,30 +191,73 @@ static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {ret static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return memcpy(Mac2HostAddr(dest), Mac2HostAddr(src), n);} +// From newcpu.cpp +extern int quit_program; +extern int exit_val; + /* * 680x0 emulation */ // Initialization -extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation +#if 0 +extern bool InitMEM(); +#endif +extern bool Init680x0(void); +#if 0 +extern void Reset680x0(void); +#endif extern void Exit680x0(void); -extern void InitFrameBufferMapping(void); - -// 680x0 dynamic recompilation activation flag -#if USE_JIT -extern bool UseJIT; -#else -const bool UseJIT = false; +#if 0 +extern void AtariReset(void); #endif // 680x0 emulation functions struct M68kRegisters; -extern void Start680x0(void); // Reset and start 680x0 +extern void Start680x0(void); // Reset and start 680x0 +#if 0 +extern void Restart680x0(void); // Restart running 680x0 +extern void Quit680x0(void); // Quit 680x0 +#endif + extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine // Interrupt functions -extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first) -extern void TriggerNMI(void); // Trigger interrupt level 7 +#if 0 +extern int MFPdoInterrupt(void); +extern int SCCdoInterrupt(void); +extern void TriggerInternalIRQ(void); +extern void TriggerInt3(void); // Trigger interrupt level 3 +extern void TriggerVBL(void); // Trigger interrupt level 4 +extern void TriggerInt5(void); // Trigger interrupt level 5 +extern void TriggerSCC(bool); // Trigger interrupt level 5 +extern void TriggerMFP(bool); // Trigger interrupt level 6 +#endif +extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first) +extern void TriggerNMI(void); // Trigger interrupt level 7 + +#if 0 +#ifdef FLIGHT_RECORDER +extern void cpu_flight_recorder(int); +extern void dump_flight_recorder(void); +#endif +#endif + +// CPU looping handlers +void check_eps_limit(uaecptr); +void report_double_bus_error(void); + +#if 0 +// This function will be removed +static inline uaecptr showPC(void) { return m68k_getpc(); } // for debugging only +#endif + +extern int intlev(void); +static inline void AtariReset(void) {} #endif + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/cpudefsa.cpp b/BasiliskII/src/uae_cpu/cpudefsa.cpp new file mode 100644 index 00000000..ad7d6979 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpudefsa.cpp @@ -0,0 +1,5 @@ +/* + * cpudefs.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "cpudefs.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1.cpp b/BasiliskII/src/uae_cpu/cpuemu1.cpp new file mode 100644 index 00000000..089eefd4 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu1.cpp @@ -0,0 +1,2 @@ +#define PART_1 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp new file mode 100644 index 00000000..58acf444 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_1 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2.cpp b/BasiliskII/src/uae_cpu/cpuemu2.cpp new file mode 100644 index 00000000..1e18b587 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu2.cpp @@ -0,0 +1,2 @@ +#define PART_2 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp new file mode 100644 index 00000000..8e5136c4 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_2 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3.cpp b/BasiliskII/src/uae_cpu/cpuemu3.cpp new file mode 100644 index 00000000..0385e2f0 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu3.cpp @@ -0,0 +1,2 @@ +#define PART_3 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp new file mode 100644 index 00000000..6565dc8c --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_3 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4.cpp b/BasiliskII/src/uae_cpu/cpuemu4.cpp new file mode 100644 index 00000000..13d27e7a --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu4.cpp @@ -0,0 +1,2 @@ +#define PART_4 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp new file mode 100644 index 00000000..a16c36cb --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_4 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5.cpp b/BasiliskII/src/uae_cpu/cpuemu5.cpp new file mode 100644 index 00000000..9b33a654 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu5.cpp @@ -0,0 +1,2 @@ +#define PART_5 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp new file mode 100644 index 00000000..5bf24360 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp @@ -0,0 +1,4 @@ +#define NOFLAGS 1 +#define PART_5 +#include "cpuemu.cpp" + diff --git a/BasiliskII/src/uae_cpu/cpuemu6.cpp b/BasiliskII/src/uae_cpu/cpuemu6.cpp new file mode 100644 index 00000000..e4b1efb0 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu6.cpp @@ -0,0 +1,2 @@ +#define PART_6 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp new file mode 100644 index 00000000..7afe15d4 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_6 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7.cpp b/BasiliskII/src/uae_cpu/cpuemu7.cpp new file mode 100644 index 00000000..faec7ef8 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu7.cpp @@ -0,0 +1,2 @@ +#define PART_7 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp new file mode 100644 index 00000000..1e404dea --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_7 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8.cpp b/BasiliskII/src/uae_cpu/cpuemu8.cpp new file mode 100644 index 00000000..c4efcfa3 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu8.cpp @@ -0,0 +1,2 @@ +#define PART_8 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp new file mode 100644 index 00000000..7c7f8f6e --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp @@ -0,0 +1,3 @@ +#define NOFLAGS 1 +#define PART_8 +#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpufunctbla.cpp b/BasiliskII/src/uae_cpu/cpufunctbla.cpp new file mode 100644 index 00000000..17dd0d3f --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpufunctbla.cpp @@ -0,0 +1,5 @@ +/* + * cpufunctbl.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "cpufunctbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpummu.cpp b/BasiliskII/src/uae_cpu/cpummu.cpp new file mode 100644 index 00000000..1a3bd91a --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpummu.cpp @@ -0,0 +1,1096 @@ +/* + * cpummu.cpp - MMU emulation + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by UAE MMU patch + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DEBUG 0 +#include "sysdeps.h" + +#include "cpummu.h" +#include "memory.h" +#include "newcpu.h" +#include "debug.h" +#ifdef USE_JIT +# include "compiler/compemu.h" +#endif + +#define DBG_MMU_VERBOSE 1 +#define DBG_MMU_SANITY 1 + +#ifdef FULLMMU + +mmu_atc_l1_array atc_l1[2]; +mmu_atc_l1_array *current_atc; +struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; + +# ifdef ATC_STATS +static unsigned int mmu_atc_hits[ATC_L2_SIZE]; +# endif + + +static void mmu_dump_ttr(const char * label, uae_u32 ttr) +{ + DUNUSED(label); +#if DEBUG + uae_u32 from_addr, to_addr; + + from_addr = ttr & MMU_TTR_LOGICAL_BASE; + to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8; + + D(bug("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d", + label, ttr, + from_addr, to_addr, + ttr & MMU_TTR_BIT_ENABLED ? 1 : 0, + (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT, + ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0, + (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT + )); +#else + DUNUSED(ttr); +#endif +} + +void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode) +{ + uae_u32 * ttr; + uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0; + uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1; + + if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0) + ttr = ttr1; + else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0) + ttr = ttr0; + else + return; + + *ttr = baseaddr & MMU_TTR_LOGICAL_BASE; + *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8; + *ttr |= MMU_TTR_BIT_ENABLED; + + D(bug("MMU: map transparent mapping of %08x", *ttr)); +} + +/* check if an address matches a ttr */ +static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, int super) +{ + if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ + uae_u8 msb, mask; + + msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; + mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; + + if (!(msb & ~mask)) { + + if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { + if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { + return TTR_NO_MATCH; + } + } + + return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; + } + } + return TTR_NO_MATCH; +} + +static inline int mmu_match_ttr(uaecptr addr, int super, int data) +{ + int res; + + if (data) { + res = mmu_do_match_ttr(regs.dtt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.dtt1, addr, super); + } else { + res = mmu_do_match_ttr(regs.itt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.itt1, addr, super); + } + return res; +} + +#if DEBUG +/* {{{ mmu_dump_table */ +static void mmu_dump_table(const char * label, uaecptr root_ptr) +{ + DUNUSED(label); + const int ROOT_TABLE_SIZE = 128, + PTR_TABLE_SIZE = 128, + PAGE_TABLE_SIZE = regs.mmu_pagesize_8k ? 32 : 64, + ROOT_INDEX_SHIFT = 25, + PTR_INDEX_SHIFT = 18; + const uae_u32 ptr_addr_mask = (regs.mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4); + const uae_u32 page_addr_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4); + const uae_u32 page_ur_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4); + const uae_u32 page_size = (regs.mmu_pagesize_8k ? (1 << 13) : (1 << 12)); + int root_idx, ptr_idx, page_idx; + uae_u32 root_des, ptr_des, page_des; + uaecptr ptr_des_addr, page_addr, + root_log, ptr_log, page_log; + + D(bug("%s: root=%x", label, root_ptr)); + + for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) { + root_des = phys_get_long(root_ptr + (root_idx << 2)); + + if ((root_des & 2) == 0) + continue; /* invalid */ + + D(bug("ROOT: %03d U=%d W=%d UDT=%02d", root_idx, + root_des & 8 ? 1 : 0, + root_des & 4 ? 1 : 0, + root_des & 3 + )); + + root_log = root_idx << ROOT_INDEX_SHIFT; + + ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK; + + for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) { + struct { + uaecptr log, phys; + int start_idx, n_pages; /* number of pages covered by this entry */ + uae_u32 match; + } page_info[PAGE_TABLE_SIZE]; + int n_pages_used; + + ptr_des = phys_get_long(ptr_des_addr + (ptr_idx << 2)); + ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT); + + if ((ptr_des & 2) == 0) + continue; /* invalid */ + + page_addr = ptr_des & ptr_addr_mask; + + n_pages_used = -1; + for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) { + + page_des = phys_get_long(page_addr + (page_idx << 2)); + page_log = ptr_log | (page_idx * page_size); + + switch (page_des & 3) { + case 0: /* invalid */ + continue; + case 1: case 3: /* resident */ + case 2: /* indirect */ + if (n_pages_used == -1 || + (page_info[n_pages_used].match & ~page_addr_mask) != (page_des & ~page_addr_mask) || + page_info[n_pages_used].phys + (page_info[n_pages_used].n_pages * page_size) != (page_des & page_addr_mask)) + { + /* use the next entry */ + n_pages_used++; + + page_info[n_pages_used].match = page_des; + page_info[n_pages_used].n_pages = 1; + page_info[n_pages_used].start_idx = page_idx; + page_info[n_pages_used].log = page_log; + page_info[n_pages_used].phys = page_des & page_addr_mask; + } else { + page_info[n_pages_used].n_pages++; + } + break; + } + } + + if (n_pages_used == -1) + continue; + + D(bug(" PTR: %03d U=%d W=%d UDT=%02d", ptr_idx, + ptr_des & 8 ? 1 : 0, + ptr_des & 4 ? 1 : 0, + ptr_des & 3 + )); + + + for (page_idx = 0; page_idx <= n_pages_used; page_idx++) { + page_des = page_info[page_idx].match; + + if ((page_des & MMU_PDT_MASK) == 2) { + D(bug(" PAGE: %03d-%03d log=%08x INDIRECT --> addr=%08x", + page_info[page_idx].start_idx, + page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, + page_info[page_idx].log, + page_des & MMU_PAGE_INDIRECT_MASK + )); + + } else { + D(bug(" PAGE: %03d-%03d log=%08x addr=%08x UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d", + page_info[page_idx].start_idx, + page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, + page_info[page_idx].log, + page_info[page_idx].phys, + (page_des & page_ur_mask) >> MMU_PAGE_UR_SHIFT, + page_des & MMU_DES_GLOBAL ? 1 : 0, + (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT, + page_des & MMU_DES_SUPER ? 1 : 0, + (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT, + page_des & MMU_DES_MODIFIED ? 1 : 0, + page_des & MMU_DES_USED ? 1 : 0, + page_des & MMU_DES_WP ? 1 : 0 + )); + } + } + } + + } +} +/* }}} */ +#endif + +/* {{{ mmu_dump_atc */ +void mmu_dump_atc(void) +{ + int i, j; + for (i = 0; i < 2; i++) { + for (j = 0; j < ATC_L2_SIZE; j++) { + if (atc_l2[i][j].tag == 0x8000) + continue; + D(bug("ATC[%02d] G=%d TT=%d M=%d WP=%d VD=%d VI=%d tag=%08x --> phys=%08x", + j, atc_l2[i][j].global, atc_l2[i][j].tt, atc_l2[i][j].modified, + atc_l2[i][j].write_protect, atc_l2[i][j].valid_data, atc_l2[i][j].valid_inst, + atc_l2[i][j].tag, atc_l2[i][j].phys)); + } + } +} +/* }}} */ + +/* {{{ mmu_dump_tables */ +void mmu_dump_tables(void) +{ + D(bug("URP: %08x SRP: %08x MMUSR: %x TC: %x", regs.urp, regs.srp, regs.mmusr, regs.tc)); + mmu_dump_ttr("DTT0", regs.dtt0); + mmu_dump_ttr("DTT1", regs.dtt1); + mmu_dump_ttr("ITT0", regs.itt0); + mmu_dump_ttr("ITT1", regs.itt1); + mmu_dump_atc(); + //mmu_dump_table("SRP", regs.srp); +} +/* }}} */ + +static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write); + +static ALWAYS_INLINE int mmu_get_fc(bool super, bool data) +{ + return (super ? 4 : 0) | (data ? 1 : 2); +} + +static void mmu_bus_error(uaecptr addr, int fc, int write, int size) +{ + uae_u16 ssw = 0; + + ssw |= fc & MMU_SSW_TM; /* Copy TM */ + switch (size) { + case sz_byte: + ssw |= MMU_SSW_SIZE_B; + break; + case sz_word: + ssw |= MMU_SSW_SIZE_W; + break; + case sz_long: + ssw |= MMU_SSW_SIZE_L; + break; + } + + regs.wb3_status = write ? 0x80 | ssw : 0; + if (!write) + ssw |= MMU_SSW_RW; + + regs.mmu_fault_addr = addr; + regs.mmu_ssw = ssw | MMU_SSW_ATC; + + D(bug("BUS ERROR: fc=%d w=%d log=%08x ssw=%04x", fc, write, addr, ssw)); + + breakpt(); + THROW(2); +} + +/* + * Update the atc line for a given address by doing a mmu lookup. + */ +static uaecptr mmu_fill_atc_l2(uaecptr addr, int super, int data, int write, + struct mmu_atc_line *l) +{ + int res; + uae_u32 desc; + + l->tag = ATC_TAG(addr); + l->hw = l->bus_fault = 0; + + /* check ttr0 */ + res = mmu_match_ttr(addr, super, data); + if (res != TTR_NO_MATCH) { + l->tt = 1; + if (data) { + l->valid_data = 1; + l->valid_inst = mmu_match_ttr(addr, super, 0) == res; + } else { + l->valid_inst = 1; + l->valid_data = mmu_match_ttr(addr, super, 1) == res; + } + l->global = 1; + l->modified = 1; + l->write_protect = (res == TTR_NO_WRITE); + l->phys = 0; + + return 0; + } + + l->tt = 0; + if (!regs.mmu_enabled) { + l->valid_data = l->valid_inst = 1; + l->global = 1; + l->modified = 1; + l->write_protect = 0; + l->phys = 0; + return 0; + } + + SAVE_EXCEPTION; + TRY(prb) { + desc = mmu_lookup_pagetable(addr, super, write); + D(bug("translate: %x,%u,%u,%u -> %x", addr, super, write, data, desc)); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + /* bus error during table search */ + desc = 0; + goto fail; + } + + if ((desc & 1) == 0 || (!super && desc & MMU_MMUSR_S)) { + fail: + l->valid_data = l->valid_inst = 0; + l->global = 0; + } else { + l->valid_data = l->valid_inst = 1; + if (regs.mmu_pagesize_8k) + l->phys = (desc & ~0x1fff) - (addr & ~0x1fff); + else + l->phys = (desc & ~0xfff) - (addr & ~0xfff); + l->global = (desc & MMU_MMUSR_G) != 0; + l->modified = (desc & MMU_MMUSR_M) != 0; + l->write_protect = (desc & MMU_MMUSR_W) != 0; + } + + return desc; +} + +static ALWAYS_INLINE bool +mmu_fill_atc_l1(uaecptr addr, int super, int data, int write, + struct mmu_atc_line *l1) +{ + int idx = ATC_L2_INDEX(addr); + int tag = ATC_TAG(addr); + struct mmu_atc_line *l = &atc_l2[super][idx]; + uaecptr phys_addr; + + if (l->tag != tag) { + restart: + mmu_fill_atc_l2(addr, super, data, write, l); + } + if (!(data ? l->valid_data : l->valid_inst)) { + D(bug("MMU: non-resident page (%x,%x,%x)!", addr, regs.pc, regs.fault_pc)); + goto fail; + } + if (write) { + if (l->write_protect) { + D(bug("MMU: write protected (via %s) %x", l->tt ? "ttr" : "atc", addr)); + goto fail; + } + if (!l->modified) + goto restart; + } + *l1 = *l; + + phys_addr = addr + l1->phys; + if ((phys_addr & 0xfff00000) == 0x00f00000) { + l1->hw = 1; + goto fail; + } + if ((phys_addr & 0xfff00000) == 0xfff00000) { + l1->hw = 1; + l1->phys -= 0xff000000; + goto fail; + } + + if (!test_ram_boundary(phys_addr, 1, super, write)) { + l1->bus_fault = 1; + goto fail; + } + + return true; + +fail: + l1->tag = ~l1->tag; + return false; +} + +uaecptr mmu_translate(uaecptr addr, int super, int data, int write) +{ + struct mmu_atc_line *l; + + l = &atc_l2[super][ATC_L2_INDEX(addr)]; + mmu_fill_atc_l2(addr, super, data, write, l); + if (!(data ? l->valid_data : l->valid_inst)) + { + breakpt(); + THROW(2); + } + + return addr + l->phys; +} + +/* + * Lookup the address by walking the page table and updating + * the page descriptors accordingly. Returns the found descriptor + * or produces a bus error. + */ +static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write) +{ + uae_u32 desc, desc_addr, wp; + int i; + + wp = 0; + desc = super ? regs.srp : regs.urp; + + /* fetch root table descriptor */ + i = (addr >> 23) & 0x1fc; + desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; + desc = phys_get_long(desc_addr); + if ((desc & 2) == 0) { + D(bug("MMU: invalid root descriptor for %x", addr)); + return 0; + } + + wp |= desc; + if ((desc & MMU_DES_USED) == 0) + phys_put_long(desc_addr, desc | MMU_DES_USED); + + /* fetch pointer table descriptor */ + i = (addr >> 16) & 0x1fc; + desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; + desc = phys_get_long(desc_addr); + if ((desc & 2) == 0) { + D(bug("MMU: invalid ptr descriptor for %x", addr)); + return 0; + } + wp |= desc; + if ((desc & MMU_DES_USED) == 0) + phys_put_long(desc_addr, desc | MMU_DES_USED); + + /* fetch page table descriptor */ + if (regs.mmu_pagesize_8k) { + i = (addr >> 11) & 0x7c; + desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) | i; + } else { + i = (addr >> 10) & 0xfc; + desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) | i; + } + + desc = phys_get_long(desc_addr); + if ((desc & 3) == 2) { + /* indirect */ + desc_addr = desc & MMU_PAGE_INDIRECT_MASK; + desc = phys_get_long(desc_addr); + } + if ((desc & 1) == 0) { + D(bug("MMU: invalid page descriptor log=%08x desc=%08x @%08x", addr, desc, desc_addr)); + return desc; + } + + desc |= wp & MMU_DES_WP; + if (write) { + if (desc & MMU_DES_WP) { + if ((desc & MMU_DES_USED) == 0) { + desc |= MMU_DES_USED; + phys_put_long(desc_addr, desc); + } + } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) != + (MMU_DES_USED|MMU_DES_MODIFIED)) { + desc |= MMU_DES_USED|MMU_DES_MODIFIED; + phys_put_long(desc_addr, desc); + } + } else { + if ((desc & MMU_DES_USED) == 0) { + desc |= MMU_DES_USED; + phys_put_long(desc_addr, desc); + } + } + return desc; +} + +uae_u16 mmu_get_word_unaligned(uaecptr addr, int data) +{ + uae_u16 res; + + res = (uae_u16)mmu_get_byte(addr, data, sz_word) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_byte(addr + 1, data, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + return res; +} + +uae_u32 mmu_get_long_unaligned(uaecptr addr, int data) +{ + uae_u32 res; + + if (likely(!(addr & 1))) { + res = (uae_u32)mmu_get_word(addr, data, sz_long) << 16; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_word(addr + 2, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } else { + res = (uae_u32)mmu_get_byte(addr, data, sz_long) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res = (res | mmu_get_byte(addr + 1, data, sz_long)) << 8; + res = (res | mmu_get_byte(addr + 2, data, sz_long)) << 8; + res |= mmu_get_byte(addr + 3, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } + return res; +} + +uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) + return HWget_b(cl->phys + addr); + mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); + return 0; + } + + if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) + goto redo; + + return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); +} + +uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) + return HWget_w(cl->phys + addr); + mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); + return 0; + } + + if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) + goto redo; + + return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); +} + +uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) + return HWget_l(cl->phys + addr); + mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); + return 0; + } + + if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) + goto redo; + + return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); +} + + +uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, + struct mmu_atc_line *cl) +{ + uae_u64 h = mmu_get_long_slow(addr, super, data, sz_long, cl); + uae_u64 l = mmu_get_long_slow(addr + 4, super, data, sz_long, cl); + return (h << 32) | l; +} + +REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data) +{ + SAVE_EXCEPTION; + TRY(prb) { + if (likely(!(addr & 1))) { + mmu_put_word(addr, val >> 16, data, sz_long); + mmu_put_word(addr + 2, val, data, sz_long); + } else { + mmu_put_byte(addr, val >> 24, data, sz_long); + mmu_put_byte(addr + 1, val >> 16, data, sz_long); + mmu_put_byte(addr + 2, val >> 8, data, sz_long); + mmu_put_byte(addr + 3, val, data, sz_long); + } + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data) +{ + SAVE_EXCEPTION; + TRY(prb) { + mmu_put_byte(addr, val >> 8, data, sz_word); + mmu_put_byte(addr + 1, val, data, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) { + HWput_b(cl->phys + addr, val); + return; + } + regs.wb3_data = val; + mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); + return; + } + + if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) + goto redo; + + do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); +} + +REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) { + HWput_w(cl->phys + addr, val); + return; + } + regs.wb3_data = val; + mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); + return; + } + + if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) + goto redo; + + do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); +} + +REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, + int size, struct mmu_atc_line *cl) +{ + uae_u32 tag = ATC_TAG(addr); + + if (cl->tag == (uae_u16)~tag) { + redo: + if (cl->hw) { + HWput_l(cl->phys + addr, val); + return; + } + regs.wb3_data = val; + mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); + return; + } + + if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) + goto redo; + + do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); +} + +REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, + struct mmu_atc_line *cl) +{ + mmu_put_long_slow(addr, (uae_u32)(val >> 32), super, data, sz_long, cl); + mmu_put_long_slow(addr + 4, (uae_u32)(val), super, data, sz_long, cl); +} + +uae_u32 sfc_get_long(uaecptr addr) +{ + int super = (regs.sfc & 4) != 0; + int data = (regs.sfc & 3) != 2; + uae_u32 res; + + if (likely(!is_unaligned(addr, 4))) + return mmu_get_user_long(addr, super, data, sz_long); + + if (likely(!(addr & 1))) { + res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_user_word(addr + 2, super, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } else { + res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8; + res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8; + res |= mmu_get_user_byte(addr + 3, super, data, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + } + return res; +} + +uae_u16 sfc_get_word(uaecptr addr) +{ + int super = (regs.sfc & 4) != 0; + int data = (regs.sfc & 3) != 2; + uae_u16 res; + + if (likely(!is_unaligned(addr, 2))) + return mmu_get_user_word(addr, super, data, sz_word); + + res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_user_byte(addr + 1, super, data, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + breakpt(); + THROW_AGAIN(prb); + } + return res; +} + +uae_u8 sfc_get_byte(uaecptr addr) +{ + int super = (regs.sfc & 4) != 0; + int data = (regs.sfc & 3) != 2; + + return mmu_get_user_byte(addr, super, data, sz_byte); +} + +void dfc_put_long(uaecptr addr, uae_u32 val) +{ + int super = (regs.dfc & 4) != 0; + int data = (regs.dfc & 3) != 2; + + SAVE_EXCEPTION; + TRY(prb) { + if (likely(!is_unaligned(addr, 4))) + mmu_put_user_long(addr, val, super, data, sz_long); + else if (likely(!(addr & 1))) { + mmu_put_user_word(addr, val >> 16, super, data, sz_long); + mmu_put_user_word(addr + 2, val, super, data, sz_long); + } else { + mmu_put_user_byte(addr, val >> 24, super, data, sz_long); + mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long); + mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long); + mmu_put_user_byte(addr + 3, val, super, data, sz_long); + } + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +void dfc_put_word(uaecptr addr, uae_u16 val) +{ + int super = (regs.dfc & 4) != 0; + int data = (regs.dfc & 3) != 2; + + SAVE_EXCEPTION; + TRY(prb) { + if (likely(!is_unaligned(addr, 2))) + mmu_put_user_word(addr, val, super, data, sz_word); + else { + mmu_put_user_byte(addr, val >> 8, super, data, sz_word); + mmu_put_user_byte(addr + 1, val, super, data, sz_word); + } + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + if (regs.mmu_fault_addr != addr) { + regs.mmu_fault_addr = addr; + regs.mmu_ssw |= MMU_SSW_MA; + } + breakpt(); + THROW_AGAIN(prb); + } +} + +void dfc_put_byte(uaecptr addr, uae_u8 val) +{ + int super = (regs.dfc & 4) != 0; + int data = (regs.dfc & 3) != 2; + + SAVE_EXCEPTION; + TRY(prb) { + mmu_put_user_byte(addr, val, super, data, sz_byte); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.wb3_data = val; + breakpt(); + THROW_AGAIN(prb); + } +} + +void mmu_op(uae_u32 opcode, uae_u16 extra) +{ + int super = (regs.dfc & 4) != 0; + DUNUSED(extra); + if ((opcode & 0xFE0) == 0x0500) { + int regno, glob; + //D(didflush = 0); + uae_u32 addr; + /* PFLUSH */ + regno = opcode & 7; + glob = (opcode & 8) != 0; + + if (opcode & 16) { + D(bug("pflusha(%u,%u)", glob, regs.dfc)); + mmu_flush_atc_all(glob); + } else { + addr = m68k_areg(regs, regno); + D(bug("pflush(%u,%u,%x)", glob, regs.dfc, addr)); + mmu_flush_atc(addr, super, glob); + } + flush_internals(); +#ifdef USE_JIT + flush_icache(); +#endif + } else if ((opcode & 0x0FD8) == 0x548) { + int write, regno; + uae_u32 addr; + + regno = opcode & 7; + write = (opcode & 32) == 0; + addr = m68k_areg(regs, regno); + //bug("ptest(%u,%u,%x)", write, regs.dfc, addr); + D(bug("PTEST%c (A%d) %08x DFC=%d", write ? 'W' : 'R', regno, addr, regs.dfc)); + mmu_flush_atc(addr, super, true); + SAVE_EXCEPTION; + TRY(prb) { + struct mmu_atc_line *l; + uae_u32 desc; + bool data = (regs.dfc & 3) != 2; + + l = &atc_l2[super][ATC_L2_INDEX(addr)]; + desc = mmu_fill_atc_l2(addr, super, data, write, l); + if (!(data ? l->valid_data : l->valid_inst)) + regs.mmusr = MMU_MMUSR_B; + else if (l->tt) + regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R; + else { + regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S| + MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W); + regs.mmusr |= MMU_MMUSR_R; + } + } + CATCH(prb) { + regs.mmusr = MMU_MMUSR_B; + } + RESTORE_EXCEPTION; + D(bug("PTEST result: mmusr %08x", regs.mmusr)); + } else + op_illg (opcode); +} + +void mmu_flush_atc(uaecptr addr, bool super, bool global) +{ + struct mmu_atc_line *l; + int i, j; + + l = atc_l1[super][0][0]; + i = ATC_L1_INDEX(addr); + for (j = 0; j < 4; j++) { + if (global || !l[i].global) + l[i].tag = 0x8000; + l += ATC_L1_SIZE; + } + if (regs.mmu_pagesize_8k) { + i = ATC_L1_INDEX(addr) ^ 1; + for (j = 0; j < 4; j++) { + if (global || !l[i].global) + l[i].tag = 0x8000; + l += ATC_L1_SIZE; + } + } + l = atc_l2[super]; + i = ATC_L2_INDEX(addr); + if (global || !l[i].global) + l[i].tag = 0x8000; + if (regs.mmu_pagesize_8k) { + i ^= 1; + if (global || !l[i].global) + l[i].tag = 0x8000; + } +} + +void mmu_flush_atc_all(bool global) +{ + struct mmu_atc_line *l; + unsigned int i; + + l = atc_l1[0][0][0]; + for (i = 0; i < sizeof(atc_l1) / sizeof(*l); l++, i++) { + if (global || !l->global) + l->tag = 0x8000; + } + + l = atc_l2[0]; + for (i = 0; i < sizeof(atc_l2) / sizeof(*l); l++, i++) { + if (global || !l->global) + l->tag = 0x8000; + } +} + +void mmu_reset(void) +{ + mmu_flush_atc_all(true); + + regs.urp = regs.srp = 0; + regs.itt0 = regs.itt1 = 0; + regs.dtt0 = regs.dtt1 = 0; + regs.mmusr = 0; +} + + +void mmu_set_tc(uae_u16 tc) +{ + if (regs.tc == tc) + return; + + regs.tc = tc; + regs.mmu_enabled = tc & 0x8000 ? 1 : 0; + regs.mmu_pagesize_8k = tc & 0x4000 ? 1 : 0; + mmu_flush_atc_all(true); + + D(bug("MMU: enabled=%d page8k=%d\n", regs.mmu_enabled, regs.mmu_pagesize_8k)); +} + +void mmu_set_super(bool super) +{ + current_atc = &atc_l1[super]; +} + +#else + +void mmu_op(uae_u32 opcode, uae_u16 /*extra*/) +{ + if ((opcode & 0xFE0) == 0x0500) { + /* PFLUSH instruction */ + flush_internals(); + } else if ((opcode & 0x0FD8) == 0x548) { + /* PTEST instruction */ + } else + op_illg(opcode); +} + +#endif + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/cpummu.h b/BasiliskII/src/uae_cpu/cpummu.h new file mode 100644 index 00000000..01359f6f --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpummu.h @@ -0,0 +1,267 @@ +/* + * cpummu.h - MMU emulation + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by UAE MMU patch + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CPUMMU_H +#define CPUMMU_H + +#include "registers.h" + +# include + +#define MMU_TEST_PTEST 1 +#define MMU_TEST_VERBOSE 2 +#define MMU_TEST_FORCE_TABLE_SEARCH 4 +#define MMU_TEST_NO_BUSERR 8 + +extern void mmu_dump_tables(void); + +#define MMU_TTR_LOGICAL_BASE 0xff000000 +#define MMU_TTR_LOGICAL_MASK 0x00ff0000 +#define MMU_TTR_BIT_ENABLED (1 << 15) +#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) +#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) +#define MMU_TTR_SFIELD_SHIFT 13 +#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) +#define MMU_TTR_UX_SHIFT 8 +#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) +#define MMU_TTR_CACHE_SHIFT 5 +#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) + +#define MMU_UDT_MASK 3 +#define MMU_PDT_MASK 3 + +#define MMU_DES_WP 4 +#define MMU_DES_USED 8 + +/* page descriptors only */ +#define MMU_DES_MODIFIED 16 +#define MMU_DES_SUPER (1 << 7) +#define MMU_DES_GLOBAL (1 << 10) + +#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 +#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 +#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 + +#define MMU_PAGE_INDIRECT_MASK 0xfffffffc +#define MMU_PAGE_ADDR_MASK_8 0xffffe000 +#define MMU_PAGE_ADDR_MASK_4 0xfffff000 +#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) +#define MMU_PAGE_UR_MASK_4 (1 << 11) +#define MMU_PAGE_UR_SHIFT 11 + +#define MMU_MMUSR_ADDR_MASK 0xfffff000 +#define MMU_MMUSR_B (1 << 11) +#define MMU_MMUSR_G (1 << 10) +#define MMU_MMUSR_U1 (1 << 9) +#define MMU_MMUSR_U0 (1 << 8) +#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) +#define MMU_MMUSR_S (1 << 7) +#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) +#define MMU_MMUSR_M (1 << 4) +#define MMU_MMUSR_W (1 << 2) +#define MMU_MMUSR_T (1 << 1) +#define MMU_MMUSR_R (1 << 0) + +/* special status word (access error stack frame) */ +#define MMU_SSW_TM 0x0007 +#define MMU_SSW_TT 0x0018 +#define MMU_SSW_SIZE 0x0060 +#define MMU_SSW_SIZE_B 0x0020 +#define MMU_SSW_SIZE_W 0x0040 +#define MMU_SSW_SIZE_L 0x0000 +#define MMU_SSW_RW 0x0100 +#define MMU_SSW_LK 0x0200 +#define MMU_SSW_ATC 0x0400 +#define MMU_SSW_MA 0x0800 + +#define TTR_I0 4 +#define TTR_I1 5 +#define TTR_D0 6 +#define TTR_D1 7 + +#define TTR_NO_MATCH 0 +#define TTR_NO_WRITE 1 +#define TTR_OK_MATCH 2 + +struct mmu_atc_line { + uae_u16 tag; + unsigned tt : 1; + unsigned valid_data : 1; + unsigned valid_inst : 1; + unsigned global : 1; + unsigned modified : 1; + unsigned write_protect : 1; + unsigned hw : 1; + unsigned bus_fault : 1; + uaecptr phys; +}; + +/* + * We don't need to store the whole logical address in the atc cache, as part of + * it is encoded as index into the cache. 14 bits of the address are stored in + * the tag, this means at least 6 bits must go into the index. The upper two + * bits of the tag define the type of data in the atc line: + * - 00: a normal memory address + * - 11: invalid memory address or hardware access + * (generated via ~ATC_TAG(addr) in the slow path) + * - 10: empty atc line + */ + +#define ATC_TAG_SHIFT 18 +#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT) + + +#define ATC_L1_SIZE_LOG 8 +#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG) + +#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE) + +/* + * first level atc cache + * indexed by [super][data][rw][idx] + */ + +typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE]; +extern mmu_atc_l1_array atc_l1[2]; +extern mmu_atc_l1_array *current_atc; + +#define ATC_L2_SIZE_LOG 12 +#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG) + +#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE) + +extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; + +/* + * lookup address in the level 1 atc cache, + * the data and write arguments are constant in the common, + * thus allows gcc to generate a constant offset. + */ +static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write, + struct mmu_atc_line **cl) +{ + addr >>= 12; + *cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE]; + return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); +} + +/* + * similiar to mmu_user_lookup, but for the use of the moves instruction + */ +static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data, + bool write, struct mmu_atc_line **cl) +{ + addr >>= 12; + *cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE]; + return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); +} + +extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data); +extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data); + +extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, + struct mmu_atc_line *cl); + +extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data); +extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data); + +extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, + int size, struct mmu_atc_line *cl); +extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, + struct mmu_atc_line *cl); + +extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); + +static inline void mmu_set_ttr(int regno, uae_u32 val) +{ + uae_u32 * ttr; + switch(regno) { + case TTR_I0: ttr = ®s.itt0; break; + case TTR_I1: ttr = ®s.itt1; break; + case TTR_D0: ttr = ®s.dtt0; break; + case TTR_D1: ttr = ®s.dtt1; break; + default: abort(); + } + *ttr = val; +} + +static inline void mmu_set_mmusr(uae_u32 val) +{ + regs.mmusr = val; +} + +#define FC_DATA (regs.s ? 5 : 1) +#define FC_INST (regs.s ? 6 : 2) + +extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write); + +extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr); +extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr); +extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr); +extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val); +extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val); +extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val); + + +extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global); +extern void REGPARAM2 mmu_flush_atc_all(bool global); +extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra); + +#ifdef FULLMMU + +extern void REGPARAM2 mmu_reset(void); +extern void REGPARAM2 mmu_set_tc(uae_u16 tc); +extern void REGPARAM2 mmu_set_super(bool super); + +#else + +static inline void mmu_reset(void) +{ +} + +static inline void mmu_set_tc(uae_u16 /*tc*/) +{ +} + +static inline void mmu_set_super(bool /*super*/) +{ +} + +#endif + +#endif /* CPUMMU_H */ +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/cpustbl_nf.cpp b/BasiliskII/src/uae_cpu/cpustbl_nf.cpp new file mode 100644 index 00000000..0ea66010 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpustbl_nf.cpp @@ -0,0 +1,2 @@ +#define NOFLAGS 1 +#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpustbla.cpp b/BasiliskII/src/uae_cpu/cpustbla.cpp new file mode 100644 index 00000000..f3f8e320 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpustbla.cpp @@ -0,0 +1,5 @@ +/* + * cpustbl.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/debug.cpp b/BasiliskII/src/uae_cpu/debug.cpp new file mode 100644 index 00000000..8b2f14e0 --- /dev/null +++ b/BasiliskII/src/uae_cpu/debug.cpp @@ -0,0 +1,82 @@ +/* + * debug.cpp - CPU debugger + * + * Copyright (c) 2001-2010 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Bernd Schmidt's UAE + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * UAE - The Un*x Amiga Emulator + * + * Debugger + * + * (c) 1995 Bernd Schmidt + * + */ + +#include "sysdeps.h" + +#include "memory.h" +#include "newcpu.h" +#include "debug.h" + +#include "input.h" +#include "cpu_emulation.h" + +#include "main.h" + +static int debugger_active = 0; +int debugging = 0; +int irqindebug = 0; + +int ignore_irq = 0; + + +void activate_debugger (void) +{ +#ifdef DEBUGGER + ndebug::do_skip = false; +#endif + debugger_active = 1; + SPCFLAGS_SET( SPCFLAG_BRK ); + debugging = 1; + /* use_debugger = 1; */ +} + +void deactivate_debugger(void) +{ + debugging = 0; + debugger_active = 0; +} + +void debug (void) +{ + if (ignore_irq && regs.s && !regs.m ) { + SPCFLAGS_SET( SPCFLAG_BRK ); + return; + } +#ifdef DEBUGGER + ndebug::run(); +#endif +} + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/fpu/core.h b/BasiliskII/src/uae_cpu/fpu/core.h index 66358a2d..2eccc4d2 100644 --- a/BasiliskII/src/uae_cpu/fpu/core.h +++ b/BasiliskII/src/uae_cpu/fpu/core.h @@ -1,28 +1,33 @@ /* - * fpu/core.h - base fpu context definition + * fpu/core.h - base fpu context definition * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_CORE_H @@ -34,11 +39,15 @@ /* Always use x87 FPU stack on IA-32. */ #if defined(X86_ASSEMBLY) #define USE_X87_ASSEMBLY 1 +#ifndef USE_JIT_FPU +#define ACCURATE_SIN_COS_TAN 1 +#endif #endif /* Only use x87 FPU on x86-64 if long double precision is requested. */ -#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE +#if defined(X86_64_ASSEMBLY) && defined(USE_LONG_DOUBLE) #define USE_X87_ASSEMBLY 1 +#define ACCURATE_SIN_COS_TAN 1 #endif /* ========================================================================== */ @@ -65,10 +74,7 @@ struct fpu_t { /* --- Floating-Point Control Register --- */ /* ---------------------------------------------------------------------- */ - struct { - /* Exception Enable Byte */ - uae_u32 exception_enable; #define FPCR_EXCEPTION_ENABLE 0x0000ff00 #define FPCR_EXCEPTION_BSUN 0x00008000 #define FPCR_EXCEPTION_SNAN 0x00004000 @@ -83,21 +89,19 @@ struct fpu_t { #define FPCR_MODE_CONTROL 0x000000ff /* Rounding precision */ - uae_u32 rounding_precision; #define FPCR_ROUNDING_PRECISION 0x000000c0 #define FPCR_PRECISION_SINGLE 0x00000040 #define FPCR_PRECISION_DOUBLE 0x00000080 #define FPCR_PRECISION_EXTENDED 0x00000000 /* Rounding mode */ - uae_u32 rounding_mode; #define FPCR_ROUNDING_MODE 0x00000030 #define FPCR_ROUND_NEAR 0x00000000 #define FPCR_ROUND_ZERO 0x00000010 #define FPCR_ROUND_MINF 0x00000020 #define FPCR_ROUND_PINF 0x00000030 - } fpcr; + uae_u32 fpcr; /* ---------------------------------------------------------------------- */ /* --- Floating-Point Status Register --- */ @@ -107,7 +111,7 @@ struct fpu_t { /* Floating-Point Condition Code Byte */ uae_u32 condition_codes; - #define FPSR_CCB 0xff000000 + #define FPSR_CCB 0x0f000000 #define FPSR_CCB_NEGATIVE 0x08000000 #define FPSR_CCB_ZERO 0x04000000 #define FPSR_CCB_INFINITY 0x02000000 @@ -133,7 +137,7 @@ struct fpu_t { /* Accrued Exception Byte */ uae_u32 accrued_exception; - #define FPSR_ACCRUED_EXCEPTION 0x000000ff + #define FPSR_ACCRUED_EXCEPTION 0x000000f8 #define FPSR_ACCR_IOP 0x00000080 #define FPSR_ACCR_OVFL 0x00000040 #define FPSR_ACCR_UNFL 0x00000020 @@ -219,7 +223,7 @@ struct fpu_t { extern fpu_t fpu; /* Return the address of a particular register */ -inline fpu_register * const fpu_register_address(int i) +inline fpu_register * fpu_register_address(int i) { return &fpu.registers[i]; } /* Dump functions for m68k_dumpstate */ @@ -227,16 +231,16 @@ extern void fpu_dump_registers(void); extern void fpu_dump_flags(void); /* Accessors to FPU Control Register */ -static inline uae_u32 get_fpcr(void); -static inline void set_fpcr(uae_u32 new_fpcr); +//static inline uae_u32 get_fpcr(void); +//static inline void set_fpcr(uae_u32 new_fpcr); /* Accessors to FPU Status Register */ -static inline uae_u32 get_fpsr(void); -static inline void set_fpsr(uae_u32 new_fpsr); +//static inline uae_u32 get_fpsr(void); +//static inline void set_fpsr(uae_u32 new_fpsr); /* Accessors to FPU Instruction Address Register */ -static inline uae_u32 get_fpiar(); -static inline void set_fpiar(uae_u32 new_fpiar); +//static inline uae_u32 get_fpiar(); +//static inline void set_fpiar(uae_u32 new_fpiar); /* Initialization / Finalization */ extern void fpu_init(bool integral_68040); @@ -254,6 +258,6 @@ void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM; /* Floating-point system control operations */ void fpuop_save(uae_u32 opcode) REGPARAM; void fpuop_restore(uae_u32 opcode) REGPARAM; -void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM; +void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) REGPARAM; #endif /* FPU_CORE_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp index 6aa6431a..2a597997 100644 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp @@ -1,28 +1,33 @@ /* - * fpu/exceptions.cpp - system-dependant FPU exceptions management + * fpu/exceptions.cpp - system-dependant FPU exceptions management * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #undef PRIVATE diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.h b/BasiliskII/src/uae_cpu/fpu/exceptions.h index 8c69a69d..f943da04 100644 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.h +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.h @@ -1,28 +1,33 @@ /* - * fpu/exceptions.h - system-dependant FPU exceptions management + * fpu/exceptions.h - system-dependant FPU exceptions management * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_EXCEPTIONS_H diff --git a/BasiliskII/src/uae_cpu/fpu/flags.cpp b/BasiliskII/src/uae_cpu/fpu/flags.cpp index 2eabef85..4b0972df 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.cpp +++ b/BasiliskII/src/uae_cpu/fpu/flags.cpp @@ -1,28 +1,33 @@ /* - * fpu/flags.cpp - Floating-point flags + * fpu/flags.cpp - Floating-point flags * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* NOTE: this file shall be included only from fpu/fpu_*.cpp */ diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h index 7c0c5b74..de25a2b6 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.h +++ b/BasiliskII/src/uae_cpu/fpu/flags.h @@ -1,28 +1,33 @@ /* - * fpu/flags.h - Floating-point flags + * fpu/flags.h - Floating-point flags * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_FLAGS_H @@ -112,7 +117,7 @@ PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) /* Make FPSR according to the value passed in argument */ PRIVATE inline void FFPU make_fpsr(fpu_register const & r) - { uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } + { uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=a" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; } /* Return the corresponding ID of the current floating-point condition codes */ /* NOTE: only valid for evaluation of a condition */ @@ -181,27 +186,27 @@ PRIVATE inline uae_u32 FFPU get_fpccr(void) uae_u32 fpccr = 0; if (isnan(FPU result)) fpccr |= FPSR_CCB_NAN; - else if (FPU result == 0.0) - fpccr |= FPSR_CCB_ZERO; - else if (FPU result < 0.0) - fpccr |= FPSR_CCB_NEGATIVE; - if (isinf(FPU result)) + else if (isinf(FPU result)) fpccr |= FPSR_CCB_INFINITY; + else if (iszero(FPU result)) + fpccr |= FPSR_CCB_ZERO; + if (isneg(FPU result)) + fpccr |= FPSR_CCB_NEGATIVE; return fpccr; } /* M68k to native floating-point condition codes - SELF */ PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond) { + bool negative = (new_fpcond & FPSR_CCB_NEGATIVE) != 0; if (new_fpcond & FPSR_CCB_NAN) - make_nan(FPU result); + make_nan(FPU result, negative); + else if (new_fpcond & FPSR_CCB_INFINITY) + make_inf(FPU result, negative); else if (new_fpcond & FPSR_CCB_ZERO) - FPU result = 0.0; - else if (new_fpcond & FPSR_CCB_NEGATIVE) - FPU result = -1.0; + make_zero(FPU result, negative); else - FPU result = +1.0; - /* gb-- where is Infinity ? */ + FPU result = negative ? -1.0 : +1.0; } /* Make FPSR according to the value passed in argument */ @@ -217,7 +222,7 @@ PRIVATE inline void FFPU make_fpsr(fpu_register const & r) /* -------------------------------------------------------------------------- */ /* Return the address of the floating-point condition codes register */ -static inline uae_u32 * const FFPU address_of_fpccr(void) +static inline uae_u32 * FFPU address_of_fpccr(void) { return ((uae_u32 *)& FPU fpsr.condition_codes); } #endif /* FPU_FLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu.h b/BasiliskII/src/uae_cpu/fpu/fpu.h index 3940a75b..d1fe6dd2 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu.h @@ -1,28 +1,33 @@ /* - * fpu/fpu.h - public header + * fpu/fpu.h - public header * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_PUBLIC_HEADER_H @@ -46,4 +51,9 @@ #include "fpu/types.h" #include "fpu/core.h" +void fpu_set_fpsr(uae_u32 new_fpsr); +uae_u32 fpu_get_fpsr(void); +void fpu_set_fpcr(uae_u32 new_fpcr); +uae_u32 fpu_get_fpcr(void); + #endif /* FPU_PUBLIC_HEADER_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp index f5a1aeb4..c76d56e6 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp @@ -1,31 +1,42 @@ /* - * fpu/fpu_ieee.cpp + * fpu_ieee.cpp - the IEEE FPU * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2008 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * MC68881/68040 fpu emulation * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* + * UAE - The Un*x Amiga Emulator + * + * MC68881/MC68040 emulation + * + * Copyright 1996 Herman ten Brugge + * + * * Following fixes by Lauri Pesonen, July 1999: * * FMOVEM list handling: @@ -87,7 +98,7 @@ */ #include "sysdeps.h" -#include +#include #include "memory.h" #include "readcpu.h" #include "newcpu.h" @@ -130,6 +141,24 @@ fpu_t fpu; #include "fpu/exceptions.cpp" #include "fpu/rounding.cpp" +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +#define LD(x) x ## L +#ifdef HAVE_POWL +#define POWL(x, y) powl(x, y) +#else +#define POWL(x, y) pow(x, y) +#endif +#ifdef HAVE_LOG10L +#define LOG10L(x) log10l(x) +#else +#define LOG10L(x) log10(x) +#endif +#else +#define LD(x) x +#define POWL(x, y) pow(x, y) +#define LOG10L(x) log10(x) +#endif + /* -------------------------------------------------------------------------- */ /* --- Debugging --- */ /* -------------------------------------------------------------------------- */ @@ -152,9 +181,9 @@ PUBLIC void FFPU fpu_dump_flags(void) (get_fpsr() & FPSR_CCB_NAN) != 0); } +#if FPU_DEBUG && FPU_DUMP_REGISTERS PRIVATE void FFPU dump_registers(const char * str) { -#if FPU_DEBUG && FPU_DUMP_REGISTERS char temp_str[512]; sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", @@ -164,12 +193,15 @@ PRIVATE void FFPU dump_registers(const char * str) fpu_get_register(6), fpu_get_register(7) ); fpu_debug((temp_str)); +#else +PRIVATE void FFPU dump_registers(const char *) +{ #endif } +#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) { -#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES char temp_buf1[256], temp_buf2[10]; int bytes = sizeof(temp_buf1)/3-1-3; if (actual < bytes) @@ -183,6 +215,9 @@ PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) strcat(temp_buf1, "\n"); fpu_debug((temp_buf1)); +#else + PRIVATE void FFPU dump_first_bytes(uae_u8 *, uae_s32) +{ #endif } @@ -200,11 +235,12 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) #if 1 // Use a single, otherwise some checks for NaN, Inf, Zero would have to // be performed - fpu_single result = 0; // = 0 to workaround a compiler bug on SPARC - fp_declare_init_shape(srp, result, single); - srp->ieee.negative = (value >> 31) & 1; - srp->ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; - srp->ieee.mantissa = value & 0x007fffff; + fpu_single result = 0; + fp_declare_init_shape(srp, single); + srp.ieee.negative = (value >> 31) & 1; + srp.ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; + srp.ieee.mantissa = value & 0x007fffff; + result = srp.value; fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); return result; #elif 0 /* Original code */ @@ -212,13 +248,13 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) return (0.0); fpu_register result; - uae_u32 * p = (uae_u32 *)&result; + fpu_register_parts *p = (fpu_register_parts *)&result; uae_u32 sign = (value & 0x80000000); uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - p[FLO] = value << 29; - p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + p->parts[FLO] = value << 29; + p->parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); @@ -231,10 +267,11 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) { #if 1 fpu_single input = (fpu_single) src; - fp_declare_init_shape(sip, input, single); - uae_u32 result = (sip->ieee.negative << 31) - | (sip->ieee.exponent << 23) - | sip->ieee.mantissa; + fp_declare_init_shape(sip, single); + sip.value = input; + uae_u32 result = (sip.ieee.negative << 31) + | (sip.ieee.exponent << 23) + | sip.ieee.mantissa; fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); return result; #elif 0 /* Original code */ @@ -242,10 +279,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) return 0; uae_u32 result; - uae_u32 *p = (uae_u32 *)&src; + fpu_register_parts const *p = (fpu_register_parts const *)&src; - uae_u32 sign = (p[FHI] & 0x80000000); - uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; + uae_u32 sign = (p->parts[FHI] & 0x80000000); + uae_u32 exp = (p->parts[FHI] & 0x7FF00000) >> 20; if(exp + 127 < 1023) { exp = 0; @@ -255,7 +292,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) exp = exp + 127 - 1023; } - result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); + result = sign | (exp << 23) | ((p->parts[FHI] & 0x000FFFFF) << 3) | (p->parts[FLO] >> 29); fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); @@ -268,36 +305,34 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u { // is it zero? if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return 0.0; + return (wrd1 & 0x80000000) ? -0.0 : 0.0; fpu_register result; -#if USE_QUAD_DOUBLE +#if defined(USE_QUAD_DOUBLE) // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { - make_nan(result); + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + make_nan(result, (wrd1 & 0x80000000) != 0); return result; } // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { - if ((wrd1 & 0x80000000) == 0) - make_inf_positive(result); - else - make_inf_negative(result); + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + make_inf(result, (wrd1 & 0x80000000) != 0); return result; } - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp->ieee.mantissa3 = 0; -#elif USE_LONG_DOUBLE - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = wrd2; - srp->ieee.mantissa1 = wrd3; + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp.ieee.mantissa3 = 0; +#elif defined(USE_LONG_DOUBLE) + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = wrd2; + srp.ieee.mantissa1 = wrd3; + #else uae_u32 sgn = (wrd1 >> 31) & 1; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -326,13 +361,14 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - fp_declare_init_shape(srp, result, double); - srp->ieee.negative = sgn; - srp->ieee.exponent = exp; + fp_declare_init_shape(srp, double); + srp.ieee.negative = sgn; + srp.ieee.exponent = exp; // drop the explicit integer bit - srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); + srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); #endif + result = srp.value; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); return result; } @@ -347,37 +383,34 @@ PRIVATE inline void FFPU make_extended_no_normalize( ) { // is it zero? - if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - make_zero_positive(result); + if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + make_zero(result, (wrd1 & 0x80000000) != 0); return; } // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { - make_nan(result); + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + make_nan(result, (wrd1 & 0x80000000) != 0); return; } -#if USE_QUAD_DOUBLE +#if defined(USE_QUAD_DOUBLE) // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { - if ((wrd1 & 0x80000000) == 0) - make_inf_positive(result); - else - make_inf_negative(result); + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + make_inf(result, (wrd1 & 0x80000000) != 0); return; } - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp->ieee.mantissa3 = 0; -#elif USE_LONG_DOUBLE - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = wrd2; - srp->ieee.mantissa1 = wrd3; + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp.ieee.mantissa3 = 0; +#elif defined(USE_LONG_DOUBLE) + fp_declare_init_shape(srp, extended); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp.ieee.mantissa0 = wrd2; + srp.ieee.mantissa1 = wrd3; #else uae_u32 exp = (wrd1 >> 16) & 0x7fff; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) @@ -387,13 +420,14 @@ PRIVATE inline void FFPU make_extended_no_normalize( else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - fp_declare_init_shape(srp, result, double); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = exp; + fp_declare_init_shape(srp, double); + srp.ieee.negative = (wrd1 >> 31) & 1; + srp.ieee.exponent = exp; // drop the explicit integer bit - srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); + srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); #endif + result = srp.value; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); } @@ -406,41 +440,43 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = *wrd2 = *wrd3 = 0; return; } -#if USE_QUAD_DOUBLE +#if defined(USE_QUAD_DOUBLE) // FIXME: deal with denormals? - fp_declare_init_shape(srp, src, extended); - *wrd1 = (srp->ieee.negative << 31) | (srp->ieee.exponent << 16); + fp_declare_init_shape(srp, extended); + srp.value = src; + *wrd1 = (srp.ieee.negative << 31) | (srp.ieee.exponent << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 15) | ((srp->ieee.mantissa1 & 0xfffe0000) >> 17); - *wrd3 = (srp->ieee.mantissa1 << 15) | ((srp->ieee.mantissa2 & 0xfffe0000) >> 17); -#elif USE_LONG_DOUBLE - uae_u32 *p = (uae_u32 *)&src; + *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 15) | ((srp.ieee.mantissa1 & 0xfffe0000) >> 17); + *wrd3 = (srp.ieee.mantissa1 << 15) | ((srp.ieee.mantissa2 & 0xfffe0000) >> 17); +#elif defined(USE_LONG_DOUBLE) + fpu_register_parts p = { src }; #ifdef WORDS_BIGENDIAN - *wrd1 = p[0]; - *wrd2 = p[1]; - *wrd3 = p[2]; + *wrd1 = p.parts[0]; + *wrd2 = p.parts[1]; + *wrd3 = p.parts[2]; #else - *wrd3 = p[0]; - *wrd2 = p[1]; - *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; + *wrd3 = p.parts[0]; + *wrd2 = p.parts[1]; + *wrd1 = (p.parts[2] & 0xffff) << 16; #endif #else - fp_declare_init_shape(srp, src, double); + fp_declare_init_shape(srp, double); + srp.value = src; fpu_debug(("extract_extended (%d,%d,%X,%X)\n", - srp->ieee.negative , srp->ieee.exponent, - srp->ieee.mantissa0, srp->ieee.mantissa1)); + srp.ieee.negative , srp.ieee.exponent, + srp.ieee.mantissa0, srp.ieee.mantissa1)); - uae_u32 exp = srp->ieee.exponent; + uae_u32 exp = srp.ieee.exponent; if (exp == FP_DOUBLE_EXP_MAX) exp = FP_EXTENDED_EXP_MAX; else exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; - *wrd1 = (srp->ieee.negative << 31) | (exp << 16); + *wrd1 = (srp.ieee.negative << 31) | (exp << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21); - *wrd3 = srp->ieee.mantissa1 << 11; + *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 11) | ((srp.ieee.mantissa1 & 0xffe00000) >> 21); + *wrd3 = srp.ieee.mantissa1 << 11; #endif fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -486,41 +522,88 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, // to_pack PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { - fpu_double d; - char *cp; - char str[100]; + fpu_register d; + bool sm = (wrd1 & 0x80000000) != 0; + bool se = (wrd1 & 0x40000000) != 0; + int exp = (wrd1 & 0x7fff0000) >> 16; + unsigned int dig; + fpu_register pwr; + + if (exp == 0x7fff) + { + if ((wrd2 & 0x7fffffff) == 0 && wrd3 == 0) + { + make_inf(d, sm); + } else + { + make_nan(d, sm); + } + return d; + } + dig = wrd1 & 0x0000000f; + if (dig == 0 && wrd2 == 0 && wrd3 == 0) + { + make_zero(d, sm); + return d; + } - cp = str; - if (wrd1 & 0x80000000) - *cp++ = '-'; - *cp++ = (char)((wrd1 & 0xf) + '0'); - *cp++ = '.'; - *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); - *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); - *cp++ = 'E'; - if (wrd1 & 0x40000000) - *cp++ = '-'; - *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); - *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); - *cp = 0; - sscanf(str, "%le", &d); + /* + * Convert the bcd exponent to binary by successive adds and + * muls. Set the sign according to SE. Subtract 16 to compensate + * for the mantissa which is to be interpreted as 17 integer + * digits, rather than 1 integer and 16 fraction digits. + * Note: this operation can never overflow. + */ + exp = ((wrd1 >> 24) & 0xf); + exp = exp * 10 + ((wrd1 >> 20) & 0xf); + exp = exp * 10 + ((wrd1 >> 16) & 0xf); + if (se) + exp = -exp; + /* sub to compensate for shift of mant */ + exp = exp - 16; + + /* + * Convert the bcd mantissa to binary by successive + * adds and muls. Set the sign according to SM. + * The mantissa digits will be converted with the decimal point + * assumed following the least-significant digit. + * Note: this operation can never overflow. + */ + d = wrd1 & 0xf; + d = (d * LD(10.0)) + ((wrd2 >> 28) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 24) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 20) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 16) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 12) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 8) & 0xf); + d = (d * LD(10.0)) + ((wrd2 >> 4) & 0xf); + d = (d * LD(10.0)) + ((wrd2 ) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 28) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 24) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 20) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 16) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 12) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 8) & 0xf); + d = (d * LD(10.0)) + ((wrd3 >> 4) & 0xf); + d = (d * LD(10.0)) + ((wrd3 ) & 0xf); - fpu_debug(("make_packed str = %s\n",str)); + /* Check the sign of the mant and make the value in fp0 the same sign. */ + if (sm) + d = -d; + + /* + * Calculate power-of-ten factor from exponent. + */ + if (exp < 0) + { + exp = -exp; + pwr = POWL(LD(10.0), exp); + d = d / pwr; + } else + { + pwr = POWL(LD(10.0), exp); + d = d * pwr; + } fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); return d; @@ -529,52 +612,88 @@ PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 // from_pack PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) { - int i; - int t; - char *cp; - char str[100]; - - sprintf(str, "%.16e", src); - - fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); - - cp = str; + fpu_register pwr; + int exp; + fpu_register d; + bool sm, se; + int dig; + *wrd1 = *wrd2 = *wrd3 = 0; - if (*cp == '-') { - cp++; - *wrd1 = 0x80000000; - } - if (*cp == '+') - cp++; - *wrd1 |= (*cp++ - '0'); - if (*cp == '.') - cp++; - for (i = 0; i < 8; i++) { - *wrd2 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd2 |= *cp++ - '0'; - } - for (i = 0; i < 8; i++) { - *wrd3 <<= 4; - if (*cp >= '0' && *cp <= '9') - *wrd3 |= *cp++ - '0'; - } - if (*cp == 'e' || *cp == 'E') { - cp++; - if (*cp == '-') { - cp++; - *wrd1 |= 0x40000000; - } - if (*cp == '+') - cp++; - t = 0; - for (i = 0; i < 3; i++) { - if (*cp >= '0' && *cp <= '9') - t = (t << 4) | (*cp++ - '0'); - } - *wrd1 |= t << 16; + + d = src; + sm = false; + if (isneg(src)) + { + d = -d; + sm = true; } + if (isnan(src)) + { + *wrd1 = sm ? 0xffff0000 : 0x7fff0000; + *wrd2 = 0xffffffff; + *wrd3 = 0xffffffff; + return; + } + if (isinf(src)) + { + *wrd1 = sm ? 0xffff0000 : 0x7fff0000; + *wrd2 = *wrd3 = 0; + return; + } + if (iszero(src)) + { + *wrd1 = sm ? 0x80000000 : 0x00000000; + *wrd2 = *wrd3 = 0; + return; + } + sm = false; + if (isneg(src)) + { + d = -d; + sm = true; + } + exp = (int)floor(LOG10L(d)); + se = false; + if (exp < 0) + { + exp = -exp; + se = true; + pwr = POWL(LD(10.0), exp); + d = d * pwr; + } else + { + pwr = POWL(LD(10.0), exp); + d = d / pwr; + } + dig = (int)d; d = LD(10) * (d - dig); *wrd1 |= dig; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 28; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 24; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 20; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 16; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 12; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 8; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 4; + dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 28; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 24; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 20; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 16; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 12; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 8; + dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 4; + dig = (int)d; *wrd3 |= dig; + + dig = (exp / 100) % 10; + *wrd1 |= dig << 24; + dig = (exp / 10) % 10; + *wrd1 |= dig << 20; + dig = (exp) % 10; + *wrd1 |= dig << 16; + if (sm) + *wrd1 |= 0x80000000; + if (se) + *wrd1 |= 0x40000000; fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -628,11 +747,9 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe break; case 3: ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); + ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -673,8 +790,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); fpu_debug(("get_fp_value ad=%X\n",ad)); fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); - dump_first_bytes( get_real_address(ad)-64, 64 ); - dump_first_bytes( get_real_address(ad), 64 ); + //dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 ); + //dump_first_bytes( get_real_address(ad, 0, 0), 64 ); switch (size) { case 0: @@ -721,15 +838,24 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe return 0; } + switch (mode) { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); return 1; } /* Convert the FP value to integer according to the current m68k rounding mode */ -PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) +PRIVATE inline fpu_register FFPU fp_doround(fpu_register const & src) { fpu_register result; - switch (get_fpcr() & 0x30) { + switch (get_fpcr() & FPCR_ROUNDING_MODE) { case FPCR_ROUND_ZERO: result = fp_round_to_zero(src); break; @@ -746,7 +872,12 @@ PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) result = src; /* should never be reached */ break; } - return (uae_s32)result; + return result; +} + +PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) +{ + return (uae_s32)fp_doround(src); } PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_register const & value) @@ -951,7 +1082,7 @@ PRIVATE inline int FFPU fpp_cond(int condition) if (NaN) N = Z = 0; - switch (condition) { + switch (condition & 0x1f) { case 0x00: CONDRET("False",0); case 0x01: CONDRET("Equal",Z); case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); @@ -1021,7 +1152,7 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) { fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - uae_u32 ad; + uae_u32 ad = 0; int cc = fpp_cond(extra & 0x3f); if (cc == -1) { m68k_setpc (m68k_getpc () - 4); @@ -1039,11 +1170,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) put_byte(ad, cc ? 0xff : 0x00); } -void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) { - fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); + fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - int cc = fpp_cond(opcode & 0x3f); + int cc = fpp_cond(extra & 0x3f); if (cc == -1) { m68k_setpc (oldpc); op_illg (opcode); @@ -1075,7 +1206,7 @@ void FFPU fpuop_save(uae_u32 opcode) { fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); - uae_u32 ad; + uae_u32 ad = 0; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; int i; @@ -1136,7 +1267,7 @@ void FFPU fpuop_restore(uae_u32 opcode) { fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); - uae_u32 ad; + uae_u32 ad = 0; uae_u32 d; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; @@ -1256,8 +1387,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) if ((opcode & 0x38) == 0) { if (extra & 0x2000) { // dr bit if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + m68k_dreg (regs, opcode & 7) = get_fpcr(); fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); } if (extra & 0x0800) { @@ -1283,13 +1413,11 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMOVEM D%d (%X) -> FPU instruction_address\n", opcode & 7, FPU instruction_address)); } } -// } else if ((opcode & 0x38) == 1) { } else if ((opcode & 0x38) == 8) { if (extra & 0x2000) { // dr bit if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + m68k_areg (regs, opcode & 7) = get_fpcr(); fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); } if (extra & 0x0800) { @@ -1333,7 +1461,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } else if (extra & 0x2000) { /* FMOVEM FPP->memory */ - uae_u32 ad; + uae_u32 ad = 0; int incr = 0; if (get_fp_ad(opcode, &ad) == 0) { @@ -1352,8 +1480,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } ad -= incr; if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - put_long (ad, get_fpcr() & 0xFFFF); + put_long (ad, get_fpcr()); fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); ad += 4; } @@ -1375,7 +1502,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } else { /* FMOVEM memory->FPP */ - uae_u32 ad; + uae_u32 ad = 0; if (get_fp_ad(opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); @@ -1421,7 +1548,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) return; case 6: case 7: { - uae_u32 ad, list = 0; + uae_u32 ad = 0, list = 0; int incr = 0; if (extra & 0x2000) { /* FMOVEM FPP->memory */ @@ -1568,27 +1695,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) switch (extra & 0x7f) { case 0x00: // FPU registers[reg] = 4.0 * atan(1.0); - FPU registers[reg] = 3.1415926535897932384626433832795; + FPU registers[reg] = LD(3.1415926535897932384626433832795029); fpu_debug(("FP const: Pi\n")); break; case 0x0b: // FPU registers[reg] = log10 (2.0); - FPU registers[reg] = 0.30102999566398119521373889472449; + FPU registers[reg] = LD(0.30102999566398119521); // 0.3010299956639811952137388947244930L fpu_debug(("FP const: Log 10 (2)\n")); break; case 0x0c: // FPU registers[reg] = exp (1.0); - FPU registers[reg] = 2.7182818284590452353602874713527; + FPU registers[reg] = LD(2.7182818284590452353); // 2.7182818284590452353602874713526625L fpu_debug(("FP const: e\n")); break; case 0x0d: // FPU registers[reg] = log (exp (1.0)) / log (2.0); - FPU registers[reg] = 1.4426950408889634073599246810019; + FPU registers[reg] = LD(1.4426950408889634073599246810019); fpu_debug(("FP const: Log 2 (e)\n")); break; case 0x0e: // FPU registers[reg] = log (exp (1.0)) / log (10.0); - FPU registers[reg] = 0.43429448190325182765112891891661; + FPU registers[reg] = LD(0.4342944819032518276511289189166051); fpu_debug(("FP const: Log 10 (e)\n")); break; case 0x0f: @@ -1597,73 +1724,79 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x30: // FPU registers[reg] = log (2.0); - FPU registers[reg] = 0.69314718055994530941723212145818; + FPU registers[reg] = LD(0.6931471805599453094172321214581766); fpu_debug(("FP const: ln(2)\n")); break; case 0x31: // FPU registers[reg] = log (10.0); - FPU registers[reg] = 2.3025850929940456840179914546844; + FPU registers[reg] = LD(2.3025850929940456840179914546843642); fpu_debug(("FP const: ln(10)\n")); break; case 0x32: - // ?? - FPU registers[reg] = 1.0e0; + FPU registers[reg] = LD(1.0e0); fpu_debug(("FP const: 1.0e0\n")); break; case 0x33: - FPU registers[reg] = 1.0e1; + FPU registers[reg] = LD(1.0e1); fpu_debug(("FP const: 1.0e1\n")); break; case 0x34: - FPU registers[reg] = 1.0e2; + FPU registers[reg] = LD(1.0e2); fpu_debug(("FP const: 1.0e2\n")); break; case 0x35: - FPU registers[reg] = 1.0e4; + FPU registers[reg] = LD(1.0e4); fpu_debug(("FP const: 1.0e4\n")); break; case 0x36: - FPU registers[reg] = 1.0e8; + FPU registers[reg] = LD(1.0e8); fpu_debug(("FP const: 1.0e8\n")); break; case 0x37: - FPU registers[reg] = 1.0e16; + FPU registers[reg] = LD(1.0e16); fpu_debug(("FP const: 1.0e16\n")); break; case 0x38: - FPU registers[reg] = 1.0e32; + FPU registers[reg] = LD(1.0e32); fpu_debug(("FP const: 1.0e32\n")); break; case 0x39: - FPU registers[reg] = 1.0e64; + FPU registers[reg] = LD(1.0e64); fpu_debug(("FP const: 1.0e64\n")); break; case 0x3a: - FPU registers[reg] = 1.0e128; + FPU registers[reg] = LD(1.0e128); fpu_debug(("FP const: 1.0e128\n")); break; case 0x3b: - FPU registers[reg] = 1.0e256; + FPU registers[reg] = LD(1.0e256); fpu_debug(("FP const: 1.0e256\n")); break; -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) case 0x3c: - FPU registers[reg] = 1.0e512L; + FPU registers[reg] = LD(1.0e512); fpu_debug(("FP const: 1.0e512\n")); break; case 0x3d: - FPU registers[reg] = 1.0e1024L; + FPU registers[reg] = LD(1.0e1024); fpu_debug(("FP const: 1.0e1024\n")); break; case 0x3e: - FPU registers[reg] = 1.0e2048L; + FPU registers[reg] = LD(1.0e2048); fpu_debug(("FP const: 1.0e2048\n")); break; case 0x3f: - FPU registers[reg] = 1.0e4096L; + FPU registers[reg] = LD(1.0e4096); fpu_debug(("FP const: 1.0e4096\n")); -#endif break; +#else + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + make_inf(FPU registers[reg], false); + break; +#endif default: m68k_setpc (m68k_getpc () - 4); op_illg (opcode); @@ -1761,34 +1894,22 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMUL %.04f\n",(double)src)); get_dest_flags(FPU registers[reg]); get_source_flags(src); - if(fl_dest.in_range && fl_source.in_range) { + if (fl_dest.in_range && fl_source.in_range) { if ((extra & 0x7f) == 0x63) FPU registers[reg] = (float)(FPU registers[reg] * src); else FPU registers[reg] = (double)(FPU registers[reg] * src); } else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); + (fl_dest.zero && fl_source.infinity) || + (fl_dest.infinity && fl_source.zero) ) { + make_nan( FPU registers[reg], fl_dest.negative ); } else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } + make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative); } else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } + make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative); } make_fpsr(FPU registers[reg]); break; @@ -1809,43 +1930,68 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) make_fpsr(FPU registers[reg]); break; case 0x01: /* FINT */ + /* + * FIXME: in round-to-nearest, x87 + * uses round-to-odd, but m68k round-to-even rule + */ fpu_debug(("FINT %.04f\n",(double)src)); - FPU registers[reg] = toint(src); + if (isinf(src)) + FPU registers[reg] = src; + else + FPU registers[reg] = fp_doround(src); make_fpsr(FPU registers[reg]); break; case 0x02: /* FSINH */ fpu_debug(("FSINH %.04f\n",(double)src)); - FPU registers[reg] = fp_sinh (src); + if (isinf(src)) + FPU registers[reg] = src; + else + FPU registers[reg] = fp_sinh (src); make_fpsr(FPU registers[reg]); break; case 0x03: /* FINTRZ */ fpu_debug(("FINTRZ %.04f\n",(double)src)); - FPU registers[reg] = fp_round_to_zero(src); + if (isinf(src)) + FPU registers[reg] = src; + else + FPU registers[reg] = fp_round_to_zero(src); make_fpsr(FPU registers[reg]); break; case 0x04: /* FSQRT */ fpu_debug(("FSQRT %.04f\n",(double)src)); - FPU registers[reg] = fp_sqrt (src); + if (isinf(src) && !isneg(src)) + FPU registers[reg] = src; + else + FPU registers[reg] = fp_sqrt (src); make_fpsr(FPU registers[reg]); break; case 0x06: /* FLOGNP1 */ fpu_debug(("FLOGNP1 %.04f\n",(double)src)); - FPU registers[reg] = fp_log (src + 1.0); + if (isinf(src) && !isneg(src)) + make_inf(FPU registers[reg], false); + else + FPU registers[reg] = fp_log1p (src); make_fpsr(FPU registers[reg]); break; case 0x08: /* FETOXM1 */ fpu_debug(("FETOXM1 %.04f\n",(double)src)); - FPU registers[reg] = fp_exp (src) - 1.0; + FPU registers[reg] = fp_expm1 (src); make_fpsr(FPU registers[reg]); break; case 0x09: /* FTANH */ fpu_debug(("FTANH %.04f\n",(double)src)); - FPU registers[reg] = fp_tanh (src); + if (isinf(src)) + FPU registers[reg] = isneg(src) ? LD(-1.0) : LD(1.0); + else + FPU registers[reg] = fp_tanh (src); make_fpsr(FPU registers[reg]); break; case 0x0a: /* FATAN */ fpu_debug(("FATAN %.04f\n",(double)src)); - FPU registers[reg] = fp_atan (src); + if (isinf(src)) + FPU registers[reg] = isneg (src) ? LD(-1.570796326794896619231321691639751442) : LD(1.570796326794896619231321691639751442); + else + FPU registers[reg] = fp_atan (src); make_fpsr(FPU registers[reg]); break; case 0x0c: /* FASIN */ @@ -1870,32 +2016,65 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x10: /* FETOX */ fpu_debug(("FETOX %.04f\n",(double)src)); - FPU registers[reg] = fp_exp (src); + if (isinf(src)) + { + make_zero(FPU registers[reg], isneg(src)); + } else + { + FPU registers[reg] = fp_exp (src); + } make_fpsr(FPU registers[reg]); break; case 0x11: /* FTWOTOX */ fpu_debug(("FTWOTOX %.04f\n",(double)src)); - FPU registers[reg] = fp_pow(2.0, src); + if (isinf(src)) + { + if (isneg(src)) + make_zero(FPU registers[reg], false); + else + make_inf(FPU registers[reg], true); + } else + { + FPU registers[reg] = fp_pow2(src); + } make_fpsr(FPU registers[reg]); break; case 0x12: /* FTENTOX */ fpu_debug(("FTENTOX %.04f\n",(double)src)); - FPU registers[reg] = fp_pow(10.0, src); + if (isinf(src)) + { + if (isneg(src)) + make_zero(FPU registers[reg], false); + else + make_inf(FPU registers[reg], true); + } else + { + FPU registers[reg] = fp_pow10(src); + } make_fpsr(FPU registers[reg]); break; case 0x14: /* FLOGN */ fpu_debug(("FLOGN %.04f\n",(double)src)); - FPU registers[reg] = fp_log (src); + if (isinf(src) && !isneg(src)) + make_inf(FPU registers[reg], false); + else + FPU registers[reg] = fp_log (src); make_fpsr(FPU registers[reg]); break; case 0x15: /* FLOG10 */ fpu_debug(("FLOG10 %.04f\n",(double)src)); - FPU registers[reg] = fp_log10 (src); + if (isinf(src) && !isneg(src)) + make_inf(FPU registers[reg], false); + else + FPU registers[reg] = fp_log10 (src); make_fpsr(FPU registers[reg]); break; case 0x16: /* FLOG2 */ fpu_debug(("FLOG2 %.04f\n",(double)src)); - FPU registers[reg] = fp_log (src) / fp_log (2.0); + if (isinf(src) && !isneg(src)) + make_inf(FPU registers[reg], false); + else + FPU registers[reg] = fp_log2 (src); make_fpsr(FPU registers[reg]); break; case 0x18: /* FABS */ @@ -1905,12 +2084,21 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x19: /* FCOSH */ fpu_debug(("FCOSH %.04f\n",(double)src)); - FPU registers[reg] = fp_cosh(src); + if (isinf(src)) + { + make_inf(FPU registers[reg], false); + } else + { + FPU registers[reg] = fp_cosh(src); + } make_fpsr(FPU registers[reg]); break; case 0x1a: /* FNEG */ fpu_debug(("FNEG %.04f\n",(double)src)); - FPU registers[reg] = -src; + if (iszero(src)) + make_zero(FPU registers[reg], !isneg(src)); + else + FPU registers[reg] = -src; make_fpsr(FPU registers[reg]); break; case 0x1c: /* FACOS */ @@ -1926,20 +2114,24 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x1e: /* FGETEXP */ fpu_debug(("FGETEXP %.04f\n",(double)src)); if( isinf(src) ) { - make_nan( FPU registers[reg] ); + make_nan( FPU registers[reg], isneg(src) ); + } + else if( iszero(src) ) { + make_zero(FPU registers[reg], isneg(src)); } else { + /* FIXME: subnormals not supported */ FPU registers[reg] = fast_fgetexp( src ); } make_fpsr(FPU registers[reg]); break; case 0x1f: /* FGETMAN */ fpu_debug(("FGETMAN %.04f\n",(double)src)); - if( src == 0 ) { - FPU registers[reg] = 0; + if( iszero(src)) { + make_zero(FPU registers[reg], isneg(src)); } - else if( isinf(src) ) { - make_nan( FPU registers[reg] ); + else if( isinf(src) || isnan(src) ) { + make_nan( FPU registers[reg], 0 ); } else { FPU registers[reg] = src; @@ -1949,7 +2141,28 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x20: /* FDIV */ fpu_debug(("FDIV %.04f\n",(double)src)); - FPU registers[reg] /= src; + if (isnan(src) || isnan(FPU registers[reg])) + { + make_nan(FPU registers[reg], false); + } else if (isinf(src)) + { + if (isinf(FPU registers[reg])) + make_nan(FPU registers[reg], false); + else + make_zero(FPU registers[reg], isneg(src) != isneg(FPU registers[reg])); + } else if (isinf(FPU registers[reg])) + { + if (isinf(src)) + make_nan(FPU registers[reg], false); + else + make_inf(FPU registers[reg], isneg(src) != isneg(FPU registers[reg])); + } else if (iszero(FPU registers[reg]) && !iszero(src)) + { + make_zero(FPU registers[reg], isneg(FPU registers[reg]) != isneg(src)); + } else + { + FPU registers[reg] /= src; + } make_fpsr(FPU registers[reg]); break; case 0x21: /* FMOD */ @@ -1967,31 +2180,23 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMUL %.04f\n",(double)src)); get_dest_flags(FPU registers[reg]); get_source_flags(src); - if(fl_dest.in_range && fl_source.in_range) { + if (fl_dest.in_range && fl_source.in_range) { FPU registers[reg] *= src; + if (unlikely(isinf(FPU registers[reg]))) + { + make_inf(FPU registers[reg], isneg(FPU registers[reg])); + } } else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); + (fl_dest.zero && fl_source.infinity) || + (fl_dest.infinity && fl_source.zero) ) { + make_nan( FPU registers[reg], fl_dest.negative ); } else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } + make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative); } else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } + make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative); } make_fpsr(FPU registers[reg]); break; @@ -2022,24 +2227,49 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) // an overflow or underflow always results. // Here (int) cast is okay. int scale_factor = (int)fp_round_to_zero(src); -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, FPU registers[reg], extended); - sxp->ieee.exponent += scale_factor; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = FPU registers[reg]; + int exp = sxp.ieee.exponent; + exp += scale_factor; + if (scale_factor >= FP_EXTENDED_EXP_MAX || exp >= FP_EXTENDED_EXP_MAX) /* overflow */ + { + make_inf(FPU registers[reg], isneg(FPU registers[reg])); + FPU fpsr.exception_status |= FPSR_EXCEPTION_OVFL; + } else if (scale_factor < -FP_EXTENDED_EXP_MAX || exp <= -64) /* underflow */ + { + make_zero(FPU registers[reg], isneg(FPU registers[reg])); + FPU fpsr.exception_status |= FPSR_EXCEPTION_UNFL; + } else if (exp >= 0) /* normal result */ + { + sxp.ieee.exponent = exp; + FPU registers[reg] = sxp.value; + } else /* subnormal result */ + { + exp += 64; + sxp.ieee.exponent = exp; + sxp.value = sxp.value * 5.421010862427522170037e-20L; /* 2^-64 */ + } #else - fp_declare_init_shape(sxp, FPU registers[reg], double); - uae_u32 exp = sxp->ieee.exponent + scale_factor; + fp_declare_init_shape(sxp, double); + sxp.value = FPU registers[reg]; + uae_u32 exp = sxp.ieee.exponent + scale_factor; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) exp = 0; else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) exp = FP_DOUBLE_EXP_MAX; else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - sxp->ieee.exponent = exp; + sxp.ieee.exponent = exp; + FPU registers[reg] = sxp.value; #endif } - else if (fl_source.infinity) { + else if (fl_source.infinity || fl_source.nan) { // Returns NaN for any Infinity source - make_nan( FPU registers[reg] ); + make_nan( FPU registers[reg], fl_source.negative ); + } else { + // source was zero, or dest was inf or nan + // in either case, dest is unchanged } make_fpsr(FPU registers[reg]); break; @@ -2050,12 +2280,52 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x28: /* FSUB */ fpu_debug(("FSUB %.04f\n",(double)src)); - FPU registers[reg] -= src; + if (isnan(src) || isnan(FPU registers[reg])) + { + make_nan(FPU registers[reg], false); + } else if (isinf(src)) + { + if (isinf(FPU registers[reg]) && isneg(src) == isneg(FPU registers[reg])) + make_nan(FPU registers[reg], false); + else + make_inf(FPU registers[reg], isneg(src)); + } else if (isinf(FPU registers[reg])) + { + if (isinf(src) && isneg(src) == isneg(FPU registers[reg])) + make_nan(FPU registers[reg], false); + else + make_inf(FPU registers[reg], isneg(FPU registers[reg])); + } else + { + FPU registers[reg] -= src; + } make_fpsr(FPU registers[reg]); break; case 0x22: /* FADD */ fpu_debug(("FADD %.04f\n",(double)src)); - FPU registers[reg] += src; + /* + * WTF. inf + some value generates NaN on x87, + * but we need inf in most cases + */ + if (isnan(src) || isnan(FPU registers[reg])) + { + make_nan(FPU registers[reg], false); + } else if (isinf(src)) + { + if (isinf(FPU registers[reg]) && isneg(src) != isneg(FPU registers[reg])) + make_nan(FPU registers[reg], false); + else + make_inf(FPU registers[reg], isneg(src)); + } else if (isinf(FPU registers[reg])) + { + if (isinf(src) && isneg(src) != isneg(FPU registers[reg])) + make_nan(FPU registers[reg], false); + else + make_inf(FPU registers[reg], isneg(FPU registers[reg])); + } else + { + FPU registers[reg] += src; + } make_fpsr(FPU registers[reg]); break; case 0x30: /* FSINCOS */ @@ -2068,6 +2338,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x37: fpu_debug(("FSINCOS %.04f\n",(double)src)); // Cosine must be calculated first if same register + // note: no need to use special sincos() function here; compiler will optimize that anyway FPU registers[extra & 7] = fp_cos(src); FPU registers[reg] = fp_sin (src); // Set FPU fpsr according to the sine result @@ -2076,7 +2347,17 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x38: /* FCMP */ fpu_debug(("FCMP %.04f\n",(double)src)); set_fpsr(0); - make_fpsr(FPU registers[reg] - src); + if (isinf(FPU registers[reg])) + { + if (isinf(src) && isneg(FPU registers[reg]) == isneg (src)) + make_fpsr(0); + else + make_fpsr(FPU registers[reg]); + } + else if (isinf(src)) + make_fpsr(-src); + else + make_fpsr(FPU registers[reg] - src); break; case 0x3a: /* FTST */ fpu_debug(("FTST %.04f\n",(double)src)); @@ -2100,6 +2381,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) dump_registers( "END "); } + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} + /* -------------------------- Initialization -------------------------- */ PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 @@ -2136,7 +2438,7 @@ PUBLIC void FFPU fpu_init (bool integral_68040) FPU result = 1; for (int i = 0; i < 8; i++) - make_nan(FPU registers[i]); + make_nan(FPU registers[i], false); } PUBLIC void FFPU fpu_exit (void) diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h index 89501956..5735874c 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h @@ -1,28 +1,33 @@ /* - * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core + * fpu/fpu_ieee.h - Extra Definitions for the IEEE FPU core * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_IEEE_H @@ -54,13 +59,11 @@ PRIVATE double_flags fl_dest; PRIVATE inline void FFPU get_dest_flags(fpu_register const & r); PRIVATE inline void FFPU get_source_flags(fpu_register const & r); -PRIVATE inline void FFPU make_nan(fpu_register & r); -PRIVATE inline void FFPU make_zero_positive(fpu_register & r); -PRIVATE inline void FFPU make_zero_negative(fpu_register & r); -PRIVATE inline void FFPU make_inf_positive(fpu_register & r); -PRIVATE inline void FFPU make_inf_negative(fpu_register & r); +PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative); +PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative); +PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative); -PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); +// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); // May be optimized for particular processors diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp new file mode 100644 index 00000000..4eda14ca --- /dev/null +++ b/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp @@ -0,0 +1,2110 @@ +/* + * fpu_mpfr.cpp - emulate 68881/68040 fpu with mpfr + * + * Copyright (c) 2012, 2013 Andreas Schwab + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" +#include +#include "memory.h" +#include "readcpu.h" +#include "newcpu.h" +#include "main.h" +#define FPU_IMPLEMENTATION +#include "fpu/fpu.h" + +#include "fpu/flags.h" +#include "fpu/exceptions.h" +#include "fpu/rounding.h" +#include "fpu/impl.h" + +#define SINGLE_PREC 24 +#define SINGLE_MIN_EXP -126 +#define SINGLE_MAX_EXP 127 +#define SINGLE_BIAS 127 +#define DOUBLE_PREC 53 +#define DOUBLE_MIN_EXP -1022 +#define DOUBLE_MAX_EXP 1023 +#define DOUBLE_BIAS 1023 +#define EXTENDED_PREC 64 +#define EXTENDED_MIN_EXP -16383 +#define EXTENDED_MAX_EXP 16383 +#define EXTENDED_BIAS 16383 + +fpu_t fpu; +// The constant ROM +// Constants 48 to 63 are mapped to index 16 to 31 +const int num_fpu_constants = 32; +static mpfr_t fpu_constant_rom[num_fpu_constants]; +#define FPU_CONSTANT_ONE fpu_constant_rom[18] +// Exceptions generated during execution in addition to the ones +// maintained by mpfr +static uae_u32 cur_exceptions; +static uaecptr cur_instruction_address; + +static void +set_format (int prec) +{ + // MPFR represents numbers as 0.m*2^e + switch (prec) + { + case SINGLE_PREC: + mpfr_set_emin (SINGLE_MIN_EXP + 1 - (SINGLE_PREC - 1)); + mpfr_set_emax (SINGLE_MAX_EXP + 1); + break; + case DOUBLE_PREC: + mpfr_set_emin (DOUBLE_MIN_EXP + 1 - (DOUBLE_PREC - 1)); + mpfr_set_emax (DOUBLE_MAX_EXP + 1); + break; + case EXTENDED_PREC: + mpfr_set_emin (EXTENDED_MIN_EXP + 1 - (EXTENDED_PREC - 1)); + mpfr_set_emax (EXTENDED_MAX_EXP + 1); + break; + } +} + +static mpfr_rnd_t +get_cur_rnd () +{ + switch (get_rounding_mode ()) + { + default: + case FPCR_ROUND_NEAR: + return MPFR_RNDN; + case FPCR_ROUND_ZERO: + return MPFR_RNDZ; + case FPCR_ROUND_MINF: + return MPFR_RNDD; + case FPCR_ROUND_PINF: + return MPFR_RNDU; + } +} + +static mpfr_prec_t +get_cur_prec () +{ + switch (get_rounding_precision ()) + { + default: + case FPCR_PRECISION_EXTENDED: + return EXTENDED_PREC; + case FPCR_PRECISION_SINGLE: + return SINGLE_PREC; + case FPCR_PRECISION_DOUBLE: + return DOUBLE_PREC; + } +} + +#define DEFAULT_NAN_BITS 0xffffffffffffffffULL + +static void +set_nan (fpu_register ®, uae_u64 nan_bits, int nan_sign) +{ + mpfr_set_nan (reg.f); + reg.nan_bits = nan_bits; + reg.nan_sign = nan_sign; +} + +static void +set_nan (fpu_register ®) +{ + set_nan (reg, DEFAULT_NAN_BITS, 0); +} + +static bool fpu_inited; + +void +fpu_init (bool integral_68040) +{ + fpu.is_integral = integral_68040; + + mpfr_set_default_prec (EXTENDED_PREC); + mpfr_set_default_rounding_mode (MPFR_RNDN); + set_format (EXTENDED_PREC); + + for (int i = 0; i < 8; i++) + mpfr_init (fpu.registers[i].f); + mpfr_init (fpu.result.f); + + // Initialize constant ROM + for (int i = 0; i < num_fpu_constants; i++) + mpfr_init (fpu_constant_rom[i]); + + // 0: pi + mpfr_const_pi (fpu_constant_rom[0], MPFR_RNDN); + // 11: log10 (2) + mpfr_set_ui (fpu_constant_rom[11], 2, MPFR_RNDN); + mpfr_log10 (fpu_constant_rom[11], fpu_constant_rom[11], MPFR_RNDZ); + // 12: e + mpfr_set_ui (fpu_constant_rom[12], 1, MPFR_RNDN); + mpfr_exp (fpu_constant_rom[12], fpu_constant_rom[12], MPFR_RNDZ); + // 13: log2 (e) + mpfr_log2 (fpu_constant_rom[13], fpu_constant_rom[12], MPFR_RNDU); + // 14: log10 (e) + mpfr_log10 (fpu_constant_rom[14], fpu_constant_rom[12], MPFR_RNDU); + // 15: 0 + mpfr_set_zero (fpu_constant_rom[15], 0); + // 48: ln (2) + mpfr_const_log2 (fpu_constant_rom[16], MPFR_RNDN); + // 49: ln (10) + mpfr_set_ui (fpu_constant_rom[17], 10, MPFR_RNDN); + mpfr_log (fpu_constant_rom[17], fpu_constant_rom[17], MPFR_RNDN); + // 50 to 63: powers of 10 + mpfr_set_ui (fpu_constant_rom[18], 1, MPFR_RNDN); + for (int i = 19; i < 32; i++) + { + mpfr_set_ui (fpu_constant_rom[i], 1L << (i - 19) , MPFR_RNDN); + mpfr_exp10 (fpu_constant_rom[i], fpu_constant_rom[i], MPFR_RNDN); + } + + fpu_inited = true; + + fpu_reset (); +} + +void +fpu_exit () +{ + if (!fpu_inited) return; + + for (int i = 0; i < 8; i++) + mpfr_clear (fpu.registers[i].f); + mpfr_clear (fpu.result.f); + for (int i = 0; i < num_fpu_constants; i++) + mpfr_clear (fpu_constant_rom[i]); +} + +void +fpu_reset () +{ + set_fpcr (0); + set_fpsr (0); + fpu.instruction_address = 0; + + for (int i = 0; i < 8; i++) + set_nan (fpu.registers[i]); +} + +fpu_register::operator long double () +{ + return mpfr_get_ld (f, MPFR_RNDN); +} + +fpu_register & +fpu_register::operator= (long double x) +{ + mpfr_set_ld (f, x, MPFR_RNDN); + nan_bits = DEFAULT_NAN_BITS; + nan_sign = 0; + return *this; +} + +static bool +get_fp_addr (uae_u32 opcode, uae_u32 *addr, bool write) +{ + uaecptr pc; + int mode; + int reg; + + mode = (opcode >> 3) & 7; + reg = opcode & 7; + switch (mode) + { + case 0: + case 1: + return false; + case 2: + *addr = m68k_areg (regs, reg); + break; + case 3: + *addr = m68k_areg (regs, reg); + break; + case 4: + *addr = m68k_areg (regs, reg); + break; + case 5: + *addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); + break; + case 6: + *addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) + { + case 0: + *addr = (uae_s16) next_iword(); + break; + case 1: + *addr = next_ilong(); + break; + case 2: + if (write) + return false; + pc = m68k_getpc (); + *addr = pc + (uae_s16) next_iword(); + break; + case 3: + if (write) + return false; + pc = m68k_getpc (); + *addr = get_disp_ea_020 (pc, next_iword()); + break; + default: + return false; + } + } + return true; +} + +static void +set_from_single (fpu_register &value, uae_u32 data) +{ + int s = data >> 31; + int e = (data >> 23) & 0xff; + uae_u32 m = data & 0x7fffff; + + if (e == 0xff) + { + if (m != 0) + { + if (!(m & 0x400000)) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + set_nan (value, (uae_u64) (m | 0xc00000) << (32 + 8), s); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + if (e != 0) + // Add integer bit + m |= 0x800000; + else + e++; + // Remove bias + e -= SINGLE_BIAS; + mpfr_set_ui_2exp (value.f, m, e - (SINGLE_PREC - 1), MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, s, MPFR_RNDN); +} + +static void +set_from_double (fpu_register &value, uae_u32 words[2]) +{ + int s = words[0] >> 31; + int e = (words[0] >> 20) & 0x7ff; + uae_u32 m = words[0] & 0xfffff; + + if (e == 0x7ff) + { + if ((m | words[1]) != 0) + { + if (!(m & 0x80000)) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + set_nan (value, (((uae_u64) (m | 0x180000) << (32 + 11)) + | ((uae_u64) words[1] << 11)), s); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + if (e != 0) + // Add integer bit + m |= 0x100000; + else + e++; + // Remove bias + e -= DOUBLE_BIAS; + mpfr_set_uj_2exp (value.f, ((uintmax_t) m << 32) | words[1], + e - (DOUBLE_PREC - 1), MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, s, MPFR_RNDN); +} + +static void +set_from_extended (fpu_register &value, uae_u32 words[3], bool check_snan) +{ + int s = words[0] >> 31; + int e = (words[0] >> 16) & 0x7fff; + + if (e == 0x7fff) + { + if (((words[1] & 0x7fffffff) | words[2]) != 0) + { + if (check_snan) + { + if ((words[1] & 0x40000000) == 0) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + words[1] |= 0x40000000; + } + set_nan (value, ((uae_u64) words[1] << 32) | words[2], s); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + // Remove bias + e -= EXTENDED_BIAS; + mpfr_set_uj_2exp (value.f, ((uintmax_t) words[1] << 32) | words[2], + e - (EXTENDED_PREC - 1), MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, s, MPFR_RNDN); +} + +#define from_bcd(d) ((d) < 10 ? (d) : (d) - 10) + +static void +set_from_packed (fpu_register &value, uae_u32 words[3]) +{ + char str[32], *p = str; + int sm = words[0] >> 31; + int se = (words[0] >> 30) & 1; + int i; + + if (((words[0] >> 16) & 0x7fff) == 0x7fff) + { + if ((words[1] | words[2]) != 0) + { + if ((words[1] & 0x40000000) == 0) + cur_exceptions |= FPSR_EXCEPTION_SNAN; + set_nan (value, ((uae_u64) (words[1] | 0x40000000) << 32) | words[2], + sm); + } + else + mpfr_set_inf (value.f, 0); + } + else + { + if (sm) + *p++ = '-'; + *p++ = from_bcd (words[0] & 15) + '0'; + *p++ = '.'; + for (i = 0; i < 8; i++) + { + p[i] = from_bcd ((words[1] >> (28 - i * 4)) & 15) + '0'; + p[i + 8] = from_bcd ((words[2] >> (28 - i * 4)) & 15) + '0'; + } + p += 16; + *p++ = 'e'; + if (se) + *p++ = '-'; + *p++ = from_bcd ((words[0] >> 24) & 15) + '0'; + *p++ = from_bcd ((words[0] >> 20) & 15) + '0'; + *p++ = from_bcd ((words[0] >> 16) & 15) + '0'; + *p = 0; + mpfr_set_str (value.f, str, 10, MPFR_RNDN); + } + mpfr_setsign (value.f, value.f, sm, MPFR_RNDN); +} + +static bool +get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register &value) +{ + int mode, reg, size; + uaecptr pc; + uae_u32 addr; + uae_u32 words[3]; + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + if ((extra & 0x4000) == 0) + { + mpfr_set (value.f, fpu.registers[(extra >> 10) & 7].f, MPFR_RNDN); + value.nan_bits = fpu.registers[(extra >> 10) & 7].nan_bits; + value.nan_sign = fpu.registers[(extra >> 10) & 7].nan_sign; + /* Check for SNaN. */ + if (mpfr_nan_p (value.f) && (value.nan_bits & (1ULL << 62)) == 0) + { + value.nan_bits |= 1ULL << 62; + cur_exceptions |= FPSR_EXCEPTION_SNAN; + } + return true; + } + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + switch (mode) + { + case 0: + switch (size) + { + case 6: + mpfr_set_si (value.f, (uae_s8) m68k_dreg (regs, reg), MPFR_RNDN); + break; + case 4: + mpfr_set_si (value.f, (uae_s16) m68k_dreg (regs, reg), MPFR_RNDN); + break; + case 0: + mpfr_set_si (value.f, (uae_s32) m68k_dreg (regs, reg), MPFR_RNDN); + break; + case 1: + set_from_single (value, m68k_dreg (regs, reg)); + break; + default: + return false; + } + return true; + case 1: + return false; + case 2: + case 3: + addr = m68k_areg (regs, reg); + break; + case 4: + addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + addr = m68k_areg (regs, reg) + (uae_s16) next_iword (); + break; + case 6: + addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); + break; + case 7: + switch (reg) + { + case 0: + addr = (uae_s16) next_iword (); + break; + case 1: + addr = next_ilong (); + break; + case 2: + pc = m68k_getpc (); + addr = pc + (uae_s16) next_iword (); + break; + case 3: + pc = m68k_getpc (); + addr = get_disp_ea_020 (pc, next_iword ()); + break; + case 4: + addr = m68k_getpc (); + m68k_incpc (sz2[size]); + if (size == 6) // Immediate byte + addr++; + break; + default: + return false; + } + } + + switch (size) + { + case 0: + mpfr_set_si (value.f, (uae_s32) get_long (addr), MPFR_RNDN); + break; + case 1: + set_from_single (value, get_long (addr)); + break; + case 2: + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + words[2] = get_long (addr + 8); + set_from_extended (value, words, true); + break; + case 3: + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + words[2] = get_long (addr + 8); + set_from_packed (value, words); + break; + case 4: + mpfr_set_si (value.f, (uae_s16) get_word (addr), MPFR_RNDN); + break; + case 5: + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + set_from_double (value, words); + break; + case 6: + mpfr_set_si (value.f, (uae_s8) get_byte (addr), MPFR_RNDN); + break; + default: + return false; + } + + switch (mode) + { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + return true; +} + +static void +update_exceptions () +{ + uae_u32 exc, aexc; + + exc = cur_exceptions; + // Add any mpfr detected exceptions + if (mpfr_underflow_p ()) + exc |= FPSR_EXCEPTION_UNFL; + if (mpfr_overflow_p ()) + exc |= FPSR_EXCEPTION_OVFL; + if (mpfr_inexflag_p ()) + exc |= FPSR_EXCEPTION_INEX2; + set_exception_status (exc); + + aexc = get_accrued_exception (); + if (exc & (FPSR_EXCEPTION_SNAN|FPSR_EXCEPTION_OPERR)) + aexc |= FPSR_ACCR_IOP; + if (exc & FPSR_EXCEPTION_OVFL) + aexc |= FPSR_ACCR_OVFL; + if ((exc & (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) + == (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) + aexc |= FPSR_ACCR_UNFL; + if (exc & FPSR_EXCEPTION_DZ) + aexc |= FPSR_ACCR_DZ; + if (exc & (FPSR_EXCEPTION_INEX1|FPSR_EXCEPTION_INEX2|FPSR_EXCEPTION_OVFL)) + aexc |= FPSR_ACCR_INEX; + set_accrued_exception (aexc); + + if ((fpu.fpcr & exc) != 0) + { + fpu.instruction_address = cur_instruction_address; + // TODO: raise exceptions + // Problem: FPSP040 depends on proper FPU stack frames, it would suffer + // undefined behaviour with our dummy FSAVE implementation + } +} + +static void +set_fp_register (int reg, mpfr_t value, uae_u64 nan_bits, int nan_sign, + int t, mpfr_rnd_t rnd, bool do_flags) +{ + mpfr_subnormalize (value, t, rnd); + mpfr_set (fpu.registers[reg].f, value, rnd); + fpu.registers[reg].nan_bits = nan_bits; + fpu.registers[reg].nan_sign = nan_sign; + if (do_flags) + { + uae_u32 flags = 0; + + if (mpfr_zero_p (fpu.registers[reg].f)) + flags |= FPSR_CCB_ZERO; + if (mpfr_signbit (fpu.registers[reg].f)) + flags |= FPSR_CCB_NEGATIVE; + if (mpfr_nan_p (fpu.registers[reg].f)) + flags |= FPSR_CCB_NAN; + if (mpfr_inf_p (fpu.registers[reg].f)) + flags |= FPSR_CCB_INFINITY; + set_fpccr (flags); + } +} + +static void +set_fp_register (int reg, mpfr_t value, int t, mpfr_rnd_t rnd, bool do_flags) +{ + set_fp_register (reg, value, DEFAULT_NAN_BITS, 0, t, rnd, do_flags); +} + +static void +set_fp_register (int reg, fpu_register &value, int t, mpfr_rnd_t rnd, + bool do_flags) +{ + set_fp_register (reg, value.f, value.nan_bits, value.nan_sign, t, rnd, + do_flags); +} + +static uae_u32 +extract_to_single (fpu_register &value) +{ + uae_u32 word; + int t; + mpfr_rnd_t rnd = get_cur_rnd (); + MPFR_DECL_INIT (single, SINGLE_PREC); + + set_format (SINGLE_PREC); + // Round to single + t = mpfr_set (single, value.f, rnd); + t = mpfr_check_range (single, t, rnd); + mpfr_subnormalize (single, t, rnd); + set_format (EXTENDED_PREC); + + if (mpfr_inf_p (single)) + word = 0x7f800000; + else if (mpfr_nan_p (single)) + { + if ((value.nan_bits & (1ULL << 62)) == 0) + { + value.nan_bits |= 1ULL << 62; + cur_exceptions |= FPSR_EXCEPTION_SNAN; + } + word = 0x7f800000 | ((value.nan_bits >> (32 + 8)) & 0x7fffff); + if (value.nan_sign) + word |= 0x80000000; + } + else if (mpfr_zero_p (single)) + word = 0; + else + { + int e; + mpz_t f; + mpz_init (f); + word = 0; + // Get exponent and mantissa + e = mpfr_get_z_2exp (f, single); + // Move binary point + e += SINGLE_PREC - 1; + // Add bias + e += SINGLE_BIAS; + if (e <= 0) + { + // Denormalized number + mpz_tdiv_q_2exp (f, f, -e + 1); + e = 0; + } + mpz_export (&word, 0, 1, 4, 0, 0, f); + // Remove integer bit + word &= 0x7fffff; + word |= e << 23; + mpz_clear (f); + } + if (mpfr_signbit (single)) + word |= 0x80000000; + return word; +} + +static void +extract_to_double (fpu_register &value, uint32_t *words) +{ + int t; + mpfr_rnd_t rnd = get_cur_rnd (); + MPFR_DECL_INIT (dbl, DOUBLE_PREC); + + set_format (DOUBLE_PREC); + // Round to double + t = mpfr_set (dbl, value.f, rnd); + t = mpfr_check_range (dbl, t, rnd); + mpfr_subnormalize (dbl, t, rnd); + set_format (EXTENDED_PREC); + + if (mpfr_inf_p (dbl)) + { + words[0] = 0x7ff00000; + words[1] = 0; + } + else if (mpfr_nan_p (dbl)) + { + if ((value.nan_bits & (1ULL << 62)) == 0) + { + value.nan_bits |= 1ULL << 62; + cur_exceptions |= FPSR_EXCEPTION_SNAN; + } + words[0] = 0x7ff00000 | ((value.nan_bits >> (32 + 11)) & 0xfffff); + words[1] = value.nan_bits >> 11; + if (value.nan_sign) + words[0] |= 0x80000000; + } + else if (mpfr_zero_p (dbl)) + { + words[0] = 0; + words[1] = 0; + } + else + { + int e, off = 0; + mpz_t f; + mpz_init (f); + words[0] = words[1] = 0; + // Get exponent and mantissa + e = mpfr_get_z_2exp (f, dbl); + // Move binary point + e += DOUBLE_PREC - 1; + // Add bias + e += DOUBLE_BIAS; + if (e <= 0) + { + // Denormalized number + mpz_tdiv_q_2exp (f, f, -e + 1); + if (e <= -20) + // No more than 32 bits left + off = 1; + e = 0; + } + mpz_export (&words[off], 0, 1, 4, 0, 0, f); + // Remove integer bit + words[0] &= 0xfffff; + words[0] |= e << 20; + mpz_clear (f); + } + if (mpfr_signbit (dbl)) + words[0] |= 0x80000000; +} + +static void +extract_to_extended (fpu_register &value, uint32_t *words) +{ + if (mpfr_inf_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = 0; + words[2] = 0; + } + else if (mpfr_nan_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = value.nan_bits >> 32; + words[2] = value.nan_bits; + if (value.nan_sign) + words[0] |= 0x80000000; + } + else if (mpfr_zero_p (value.f)) + { + words[0] = 0; + words[1] = 0; + words[2] = 0; + } + else + { + int e, off = 0; + mpz_t f; + + mpz_init (f); + words[0] = words[1] = words[2] = 0; + // Get exponent and mantissa + e = mpfr_get_z_2exp (f, value.f); + // Move binary point + e += EXTENDED_PREC - 1; + // Add bias + e += EXTENDED_BIAS; + if (e < 0) + { + // Denormalized number + mpz_tdiv_q_2exp (f, f, -e); + if (e <= -32) + // No more than 32 bits left + off = 1; + e = 0; + } + mpz_export (&words[1 + off], 0, 1, 4, 0, 0, f); + words[0] = e << 16; + mpz_clear (f); + } + if (mpfr_signbit (value.f)) + words[0] |= 0x80000000; +} + +static void +extract_to_packed (fpu_register &value, int k, uae_u32 *words) +{ + if (mpfr_inf_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = 0; + words[2] = 0; + } + else if (mpfr_nan_p (value.f)) + { + words[0] = 0x7fff0000; + words[1] = value.nan_bits >> 32; + words[2] = value.nan_bits; + if (value.nan_sign) + words[0] |= 0x80000000; + } + else if (mpfr_zero_p (value.f)) + { + words[0] = 0; + words[1] = 0; + words[2] = 0; + } + else + { + char str[100], *p = str; + mpfr_exp_t e; + mpfr_rnd_t rnd = get_cur_rnd (); + + words[0] = words[1] = words[2] = 0; + if (k >= 64) + k -= 128; + else if (k >= 18) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + if (k <= 0) + { + MPFR_DECL_INIT (temp, 16); + + mpfr_log10 (temp, value.f, rnd); + k = mpfr_get_si (temp, MPFR_RNDZ) - k + 1; + } + if (k <= 0) + k = 1; + else if (k >= 18) + k = 17; + mpfr_get_str (str, &e, 10, k, value.f, rnd); + e--; + if (*p == '-') + p++; + // Pad to 17 digits + while (k < 17) + p[k++] = '0'; + if (e < 0) + { + words[0] |= 0x40000000; + e = -e; + } + words[0] |= (e % 10) << 16; + e /= 10; + words[0] |= (e % 10) << 20; + e /= 10; + words[0] |= (e % 10) << 24; + e /= 10; + if (e) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + words[0] |= e << 12; + words[0] |= *p++ & 15; + for (k = 0; k < 8; k++) + words[1] = (words[1] << 4) | (*p++ & 15); + for (k = 0; k < 8; k++) + words[2] = (words[2] << 4) | (*p++ & 15); + + } + if (mpfr_signbit (value.f)) + words[0] |= 0x80000000; +} + +static long +extract_to_integer (mpfr_t value, long min, long max) +{ + long result; + mpfr_rnd_t rnd = get_cur_rnd (); + + if (mpfr_fits_slong_p (value, rnd)) + { + result = mpfr_get_si (value, rnd); + if (result > max) + { + result = max; + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (result < min) + { + result = min; + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + } + else + { + if (!mpfr_signbit (value)) + result = max; + else + result = min; + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + return result; +} + +static bool +fpuop_fmove_memory (uae_u32 opcode, uae_u32 extra) +{ + int mode, reg, size; + uaecptr pc; + uae_u32 addr; + uae_u32 words[3]; + static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; + static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; + + mpfr_clear_flags (); + cur_exceptions = 0; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + size = (extra >> 10) & 7; + fpu_register &value = fpu.registers[(extra >> 7) & 7]; + + switch (mode) + { + case 0: + switch (size) + { + case 0: + m68k_dreg (regs, reg) = extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff); + break; + case 1: + m68k_dreg (regs, reg) = extract_to_single (value); + break; + case 4: + m68k_dreg (regs, reg) &= ~0xffff; + m68k_dreg (regs, reg) |= extract_to_integer (value.f, -32768, 32767) & 0xffff; + break; + case 6: + m68k_dreg (regs, reg) &= ~0xff; + m68k_dreg (regs, reg) |= extract_to_integer (value.f, -128, 127) & 0xff; + break; + default: + return false; + } + update_exceptions (); + return true; + case 1: + return false; + case 2: + addr = m68k_areg (regs, reg); + break; + case 3: + addr = m68k_areg (regs, reg); + break; + case 4: + addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + break; + case 5: + addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); + break; + case 6: + addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); + break; + case 7: + switch (reg) + { + case 0: + addr = (uae_s16) next_iword(); + break; + case 1: + addr = next_ilong(); + break; + case 2: + pc = m68k_getpc (); + addr = pc + (uae_s16) next_iword(); + break; + case 3: + pc = m68k_getpc (); + addr = get_disp_ea_020 (pc, next_iword ()); + break; + case 4: + addr = m68k_getpc (); + m68k_incpc (sz2[size]); + break; + default: + return false; + } + } + + switch (size) + { + case 0: + put_long (addr, extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff)); + break; + case 1: + put_long (addr, extract_to_single (value)); + break; + case 2: + extract_to_extended (value, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + break; + case 3: + extract_to_packed (value, extra & 0x7f, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + break; + case 4: + put_word (addr, extract_to_integer (value.f, -32768, 32767)); + break; + case 5: + extract_to_double (value, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + break; + case 6: + put_byte (addr, extract_to_integer (value.f, -128, 127)); + break; + case 7: + extract_to_packed (value, m68k_dreg (regs, (extra >> 4) & 7) & 0x7f, words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + break; + } + + switch (mode) + { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + + update_exceptions (); + return true; +} + +static bool +fpuop_fmovem_control (uae_u32 opcode, uae_u32 extra) +{ + int list, mode, reg; + uae_u32 addr; + + list = (extra >> 10) & 7; + mode = (opcode >> 3) & 7; + reg = opcode & 7; + + if (list == 0) + return false; + + if (extra & 0x2000) + { + // FMOVEM to + if (mode == 0) + { + switch (list) + { + case 1: + m68k_dreg (regs, reg) = fpu.instruction_address; + break; + case 2: + m68k_dreg (regs, reg) = get_fpsr (); + break; + case 4: + m68k_dreg (regs, reg) = get_fpcr (); + break; + default: + return false; + } + } + else if (mode == 1) + { + if (list != 1) + return false; + m68k_areg (regs, reg) = fpu.instruction_address; + } + else + { + int nwords; + + if (!get_fp_addr (opcode, &addr, true)) + return false; + nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); + if (mode == 4) + addr -= nwords * 4; + if (list & 4) + { + put_long (addr, get_fpcr ()); + addr += 4; + } + if (list & 2) + { + put_long (addr, get_fpsr ()); + addr += 4; + } + if (list & 1) + { + put_long (addr, fpu.instruction_address); + addr += 4; + } + if (mode == 4) + m68k_areg (regs, reg) = addr - nwords * 4; + else if (mode == 3) + m68k_areg (regs, reg) = addr; + } + } + else + { + // FMOVEM from + + if (mode == 0) + { + switch (list) + { + case 1: + fpu.instruction_address = m68k_dreg (regs, reg); + break; + case 2: + set_fpsr (m68k_dreg (regs, reg)); + break; + case 4: + set_fpcr (m68k_dreg (regs, reg)); + break; + default: + return false; + } + } + else if (mode == 1) + { + if (list != 1) + return false; + fpu.instruction_address = m68k_areg (regs, reg); + } + else if ((opcode & 077) == 074) + { + switch (list) + { + case 1: + fpu.instruction_address = next_ilong (); + break; + case 2: + set_fpsr (next_ilong ()); + break; + case 4: + set_fpcr (next_ilong ()); + break; + default: + return false; + } + } + else + { + int nwords; + + if (!get_fp_addr (opcode, &addr, false)) + return false; + nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); + if (mode == 4) + addr -= nwords * 4; + if (list & 4) + { + set_fpcr (get_long (addr)); + addr += 4; + } + if (list & 2) + { + set_fpsr (get_long (addr)); + addr += 4; + } + if (list & 1) + { + fpu.instruction_address = get_long (addr); + addr += 4; + } + if (mode == 4) + m68k_areg (regs, reg) = addr - nwords * 4; + else if (mode == 3) + m68k_areg (regs, reg) = addr; + } + } + + return true; +} + +static bool +fpuop_fmovem_register (uae_u32 opcode, uae_u32 extra) +{ + uae_u32 addr; + uae_u32 words[3]; + int list; + int i; + + set_format (EXTENDED_PREC); + if (!get_fp_addr (opcode, &addr, extra & 0x2000)) + return false; + if (extra & 0x800) + list = m68k_dreg (regs, (extra >> 4) & 7) & 0xff; + else + list = extra & 0xff; + + if (extra & 0x2000) + { + // FMOVEM to memory + + switch (opcode & 070) + { + case 030: + return false; + case 040: + if (extra & 0x1000) + return false; + for (i = 7; i >= 0; i--) + if (list & (1 << i)) + { + extract_to_extended (fpu.registers[i], words); + addr -= 12; + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + } + m68k_areg (regs, opcode & 7) = addr; + break; + default: + if ((extra & 0x1000) == 0) + return false; + for (i = 0; i < 8; i++) + if (list & (0x80 >> i)) + { + extract_to_extended (fpu.registers[i], words); + put_long (addr, words[0]); + put_long (addr + 4, words[1]); + put_long (addr + 8, words[2]); + addr += 12; + } + if ((opcode & 070) == 030) + m68k_areg (regs, opcode & 7) = addr; + break; + } + } + else + { + // FMOVEM from memory + + if ((opcode & 070) == 040) + return false; + + if ((extra & 0x1000) == 0) + return false; + for (i = 0; i < 8; i++) + if (list & (0x80 >> i)) + { + words[0] = get_long (addr); + words[1] = get_long (addr + 4); + words[2] = get_long (addr + 8); + addr += 12; + set_from_extended (fpu.registers[i], words, false); + } + if ((opcode & 070) == 030) + m68k_areg (regs, opcode & 7) = addr; + } + return true; +} + +static int +do_getexp (mpfr_t value, mpfr_rnd_t rnd) +{ + int t = 0; + + if (mpfr_inf_p (value)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) + t = mpfr_set_si (value, mpfr_get_exp (value) - 1, rnd); + return t; +} + +static int +do_getman (mpfr_t value) +{ + if (mpfr_inf_p (value)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) + mpfr_set_exp (value, 1); + return 0; +} + +static int +do_scale (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) +{ + long scale; + int t = 0; + + if (mpfr_nan_p (value)) + ; + else if (mpfr_inf_p (value)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_fits_slong_p (value, rnd)) + { + scale = mpfr_get_si (value, MPFR_RNDZ); + mpfr_clear_inexflag (); + t = mpfr_mul_2si (value, reg, scale, rnd); + } + else + mpfr_set_inf (value, -mpfr_signbit (value)); + return t; +} + +static int +do_remainder (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) +{ + long quo; + int t = 0; + + if (mpfr_nan_p (value) || mpfr_nan_p (reg)) + ; + else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_remquo (value, &quo, reg, value, rnd); + if (quo < 0) + quo = (-quo & 0x7f) | 0x80; + else + quo &= 0x7f; + fpu.fpsr.quotient = quo << 16; + return t; +} + +// Unfortunately, mpfr_fmod does not return the quotient bits, so we +// have to reimplement it here +static int +mpfr_rem1 (mpfr_t rem, int *quo, mpfr_t x, mpfr_t y, mpfr_rnd_t rnd) +{ + mpfr_exp_t ex, ey; + int inex, sign, signx = mpfr_signbit (x); + mpz_t mx, my, r; + + mpz_init (mx); + mpz_init (my); + mpz_init (r); + + ex = mpfr_get_z_2exp (mx, x); /* x = mx*2^ex */ + ey = mpfr_get_z_2exp (my, y); /* y = my*2^ey */ + + /* to get rid of sign problems, we compute it separately: + quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y) + quo(-x,y) = -quo(x,y), rem(-x,y) = -rem(x,y) + thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */ + sign = (signx != mpfr_signbit (y)); + mpz_abs (mx, mx); + mpz_abs (my, my); + + /* divide my by 2^k if possible to make operations mod my easier */ + { + unsigned long k = mpz_scan1 (my, 0); + ey += k; + mpz_fdiv_q_2exp (my, my, k); + } + + if (ex <= ey) + { + /* q = x/y = mx/(my*2^(ey-ex)) */ + mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */ + /* 0 <= |r| <= |my|, r has the same sign as mx */ + mpz_tdiv_qr (mx, r, mx, my); + /* mx is the quotient */ + mpz_tdiv_r_2exp (mx, mx, 7); + *quo = mpz_get_si (mx); + } + else /* ex > ey */ + { + /* to get the low 7 more bits of the quotient, we first compute + R = X mod Y*2^7, where X and Y are defined below. Then the + low 7 of the quotient are floor(R/Y). */ + mpz_mul_2exp (my, my, 7); /* 2^7*Y */ + + mpz_set_ui (r, 2); + mpz_powm_ui (r, r, ex - ey, my); /* 2^(ex-ey) mod my */ + mpz_mul (r, r, mx); + mpz_mod (r, r, my); + + /* now 0 <= r < 2^7*Y */ + mpz_fdiv_q_2exp (my, my, 7); /* back to Y */ + mpz_tdiv_qr (mx, r, r, my); + /* oldr = mx*my + newr */ + *quo = mpz_get_si (mx); + + /* now 0 <= |r| < |my| */ + } + + if (mpz_cmp_ui (r, 0) == 0) + { + inex = mpfr_set_ui (rem, 0, MPFR_RNDN); + /* take into account sign of x */ + if (signx) + mpfr_neg (rem, rem, MPFR_RNDN); + } + else + { + /* take into account sign of x */ + if (signx) + mpz_neg (r, r); + inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd); + } + + if (sign) + *quo |= 0x80; + + mpz_clear (mx); + mpz_clear (my); + mpz_clear (r); + + return inex; +} + +static int +do_fmod (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) +{ + int t = 0; + + if (mpfr_nan_p (value) || mpfr_nan_p (reg)) + mpfr_set_nan (value); + else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) + { + mpfr_set_nan (value); + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_zero_p (reg) || mpfr_inf_p (value)) + { + fpu.fpsr.quotient = 0; + t = mpfr_set (value, reg, rnd); + } + else + { + int quo; + + t = mpfr_rem1 (value, &quo, reg, value, rnd); + fpu.fpsr.quotient = quo << 16; + } + return t; +} + +static void +do_fcmp (mpfr_t source, mpfr_t dest) +{ + uae_u32 flags = 0; + + if (mpfr_nan_p (source) || mpfr_nan_p (dest)) + flags |= FPSR_CCB_NAN; + else + { + int cmp = mpfr_cmp (dest, source); + if (cmp < 0) + flags |= FPSR_CCB_NEGATIVE; + else if (cmp == 0) + { + flags |= FPSR_CCB_ZERO; + if ((mpfr_zero_p (dest) || mpfr_inf_p (dest)) && mpfr_signbit (dest)) + flags |= FPSR_CCB_NEGATIVE; + } + } + set_fpccr (flags); +} + +static void +do_ftst (mpfr_t value) +{ + uae_u32 flags = 0; + + if (mpfr_signbit (value)) + flags |= FPSR_CCB_NEGATIVE; + if (mpfr_nan_p (value)) + flags |= FPSR_CCB_NAN; + else if (mpfr_zero_p (value)) + flags |= FPSR_CCB_ZERO; + else if (mpfr_inf_p (value)) + flags |= FPSR_CCB_INFINITY; + set_fpccr (flags); +} + +static bool +fpuop_general (uae_u32 opcode, uae_u32 extra) +{ + mpfr_prec_t prec = get_cur_prec (); + mpfr_rnd_t rnd = get_cur_rnd (); + int reg = (extra >> 7) & 7; + int t = 0; + fpu_register value; + bool ret; + + mpfr_init2 (value.f, prec); + value.nan_bits = DEFAULT_NAN_BITS; + value.nan_sign = 0; + + mpfr_clear_flags (); + set_format (prec); + cur_exceptions = 0; + cur_instruction_address = m68k_getpc () - 4; + if ((extra & 0xfc00) == 0x5c00) + { + // FMOVECR + int rom_index = extra & 0x7f; + if (rom_index == 0 || (rom_index >= 11 && rom_index <= 15)) + t = mpfr_set (value.f, fpu_constant_rom[rom_index], rnd); + else if (rom_index >= 48 && rom_index <= 63) + t = mpfr_set (value.f, fpu_constant_rom[rom_index - 32], rnd); + else + mpfr_set_zero (value.f, 0); + set_fp_register (reg, value, t, rnd, true); + } + else if (extra & 0x40) + { + static const char valid[64] = + { + 1, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 1, 0, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 0 + }; + + if (extra & 4) + // FD... + prec = DOUBLE_PREC; + else + // FS... + prec = SINGLE_PREC; + set_format (prec); + MPFR_DECL_INIT (value2, prec); + + if (!fpu.is_integral) + { + ret = false; + goto out; + } + if (!valid[extra & 0x3b]) + { + ret = false; + goto out; + } + if (!get_fp_value (opcode, extra, value)) + { + ret = false; + goto out; + } + + switch (extra & 0x3f) + { + case 0: // FSMOVE + case 4: // FDMOVE + mpfr_set (value2, value.f, rnd); + break; + case 1: // FSSQRT + case 5: // FDSQRT + if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sqrt (value2, value.f, rnd); + break; + case 24: // FSABS + case 28: // FDABS + t = mpfr_abs (value2, value.f, rnd); + break; + case 26: // FSNEG + case 30: // FDNEG + t = mpfr_neg (value2, value.f, rnd); + break; + case 32: // FSDIV + case 36: // FDDIV + if (mpfr_zero_p (value.f)) + { + if (mpfr_regular_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_zero_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); + break; + case 34: // FSADD + case 38: // FDADD + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_add (value2, fpu.registers[reg].f, value.f, rnd); + break; + case 35: // FSMUL + case 39: // FDMUL + if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); + break; + case 40: // FSSUB + case 44: // FDSUB + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sub (value2, fpu.registers[reg].f, value.f, rnd); + break; + } + set_fp_register (reg, value2, t, rnd, true); + } + else if ((extra & 0x30) == 0x30) + { + if ((extra & 15) > 10 || (extra & 15) == 9) + { + ret = false; + goto out; + } + if (!get_fp_value (opcode, extra, value)) + { + ret = false; + goto out; + } + + if ((extra & 15) < 8) + { + // FSINCOS + int reg2 = extra & 7; + MPFR_DECL_INIT (value2, prec); + + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sin_cos (value.f, value2, value.f, rnd); + if (reg2 != reg) + set_fp_register (reg2, value2, t >> 2, rnd, false); + set_fp_register (reg, value, t & 3, rnd, true); + } + else if ((extra & 15) == 8) + // FCMP + do_fcmp (value.f, fpu.registers[reg].f); + else + // FTST + do_ftst (value.f); + } + else + { + static const char valid[64] = + { + 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1 + }; + if (!valid[extra & 0x3f]) + { + ret = false; + goto out; + } + if (!get_fp_value (opcode, extra, value)) + { + ret = false; + goto out; + } + + switch (extra & 0x3f) + { + case 0: // FMOVE + break; + case 1: // FINT + t = mpfr_rint (value.f, value.f, rnd); + break; + case 2: // FSINH + t = mpfr_sinh (value.f, value.f, rnd); + break; + case 3: // FINTRZ + t = mpfr_rint (value.f, value.f, MPFR_RNDZ); + break; + case 4: // FSQRT + if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sqrt (value.f, value.f, rnd); + break; + case 6: // FLOGNP1 + if (!mpfr_nan_p (value.f)) + { + int cmp = mpfr_cmp_si (value.f, -1); + if (cmp == 0) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (cmp < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + t = mpfr_log1p (value.f, value.f, rnd); + break; + case 8: // FETOXM1 + t = mpfr_expm1 (value.f, value.f, rnd); + break; + case 9: // FTANH + t = mpfr_tanh (value.f, value.f, rnd); + break; + case 10: // FATAN + t = mpfr_atan (value.f, value.f, rnd); + break; + case 12: // FASIN + if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_asin (value.f, value.f, rnd); + break; + case 13: // FATANH + if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_atanh (value.f, value.f, rnd); + break; + case 14: // FSIN + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sin (value.f, value.f, rnd); + break; + case 15: // FTAN + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_tan (value.f, value.f, rnd); + break; + case 16: // FETOX + t = mpfr_exp (value.f, value.f, rnd); + break; + case 17: // FTWOTOX + t = mpfr_ui_pow (value.f, 2, value.f, rnd); + break; + case 18: // FTENTOX + t = mpfr_ui_pow (value.f, 10, value.f, rnd); + break; + case 20: // FLOGN + if (mpfr_zero_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_log (value.f, value.f, rnd); + break; + case 21: // FLOG10 + if (mpfr_zero_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_log10 (value.f, value.f, rnd); + break; + case 22: // FLOG2 + if (mpfr_zero_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_sgn (value.f) < 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_log2 (value.f, value.f, rnd); + break; + case 24: // FABS + t = mpfr_abs (value.f, value.f, rnd); + value.nan_sign = 0; + break; + case 25: // FCOSH + t = mpfr_cosh (value.f, value.f, rnd); + break; + case 26: // FNEG + t = mpfr_neg (value.f, value.f, rnd); + value.nan_sign = !value.nan_sign; + break; + case 28: // FACOS + if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_acos (value.f, value.f, rnd); + break; + case 29: // FCOS + if (mpfr_inf_p (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_cos (value.f, value.f, rnd); + break; + case 30: // FGETEXP + t = do_getexp (value.f, rnd); + break; + case 31: // FGETMAN + t = do_getman (value.f); + break; + case 32: // FDIV + if (mpfr_zero_p (value.f)) + { + if (mpfr_regular_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_zero_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_div (value.f, fpu.registers[reg].f, value.f, rnd); + break; + case 33: // FMOD + t = do_fmod (value.f, fpu.registers[reg].f, rnd); + break; + case 34: // FADD + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_add (value.f, fpu.registers[reg].f, value.f, rnd); + break; + case 35: // FMUL + if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_mul (value.f, fpu.registers[reg].f, value.f, rnd); + break; + case 36: // FSGLDIV + { + MPFR_DECL_INIT (value2, SINGLE_PREC); + + set_format (SINGLE_PREC); + if (mpfr_zero_p (value.f)) + { + if (mpfr_regular_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_DZ; + else if (mpfr_zero_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + } + else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); + mpfr_set (value.f, value2, rnd); + } + break; + case 37: // FREM + t = do_remainder (value.f, fpu.registers[reg].f, rnd); + break; + case 38: // FSCALE + t = do_scale (value.f, fpu.registers[reg].f, rnd); + break; + case 39: // FSGLMUL + { + MPFR_DECL_INIT (value2, SINGLE_PREC); + + set_format (SINGLE_PREC); + if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) + || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); + mpfr_set (value.f, value2, rnd); + } + break; + case 40: // FSUB + if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) + && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) + cur_exceptions |= FPSR_EXCEPTION_OPERR; + t = mpfr_sub (value.f, fpu.registers[reg].f, value.f, rnd); + break; + } + set_fp_register (reg, value, t, rnd, true); + } + update_exceptions (); + ret = true; + out: + mpfr_clear (value.f); + return ret; +} + +void +fpuop_arithmetic (uae_u32 opcode, uae_u32 extra) +{ + bool valid; + + switch ((extra >> 13) & 7) + { + case 3: + valid = fpuop_fmove_memory (opcode, extra); + break; + case 4: + case 5: + valid = fpuop_fmovem_control (opcode, extra); + break; + case 6: + case 7: + valid = fpuop_fmovem_register (opcode, extra); + break; + case 0: + case 2: + valid = fpuop_general (opcode, extra); + break; + default: + valid = false; + break; + } + + if (!valid) + { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } +} + +static bool +check_fp_cond (uae_u32 pred) +{ + uae_u32 fpcc = get_fpccr (); + + if ((pred & 16) != 0 && (fpcc & FPSR_CCB_NAN) != 0) + { + // IEEE non-aware test + set_exception_status (get_exception_status () | FPSR_EXCEPTION_BSUN); + set_accrued_exception (get_accrued_exception () | FPSR_ACCR_IOP); + } + + switch (pred & 15) + { + case 0: // F / SF + return false; + case 1: // EQ /SEQ + return (fpcc & FPSR_CCB_ZERO) != 0; + case 2: // OGT / GT + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) == 0; + case 3: // OGE / GE + return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NAN | FPSR_CCB_NEGATIVE)) == 0; + case 4: // OLT / LT + return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; + case 5: // OLE / LE + return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN)) == FPSR_CCB_NEGATIVE; + case 6: // OGL / GL + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) == 0; + case 7: // OR / GLE + return (fpcc & FPSR_CCB_NAN) == 0; + case 8: // UN / NGLE + return (fpcc & FPSR_CCB_NAN) != 0; + case 9: // UEQ / NGL + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) != 0; + case 10: // UGT / NLE + return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == 0; + case 11: // UGE / NLT + return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) != FPSR_CCB_NEGATIVE; + case 12: // ULT / NGE + return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; + case 13: // ULE / NGT + return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) != 0; + case 14: // NE / SNE + return (fpcc & FPSR_CCB_ZERO) == 0; + case 15: // T / ST + return true; + default: + return false; + } +} + +void +fpuop_bcc (uae_u32 opcode, uaecptr pc, uae_u32 disp) +{ + if (check_fp_cond (opcode)) + { + if (!(opcode & (1 << 6))) + disp = (uae_s16) disp; + m68k_setpc (pc + disp); + } +} + +void +fpuop_scc (uae_u32 opcode, uae_u32 extra) +{ + uae_u32 addr; + int value = check_fp_cond (extra) ? 0xff : 0; + if ((opcode & 070) == 0) + { + int reg = opcode & 7; + m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xff) | value; + } + else if (!get_fp_addr (opcode, &addr, true)) + { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + } + else + { + switch (opcode & 070) + { + case 030: + m68k_areg (regs, opcode & 7) += (opcode & 7) == 7 ? 2 : 1; + break; + case 040: + addr -= (opcode & 7) == 7 ? 2 : 1; + m68k_areg (regs, opcode & 7) = addr; + } + put_byte (addr, value); + } +} + +void +fpuop_dbcc (uae_u32 opcode, uae_u32 extra) +{ + uaecptr pc = m68k_getpc (); + uae_s16 disp = next_iword (); + + if (!check_fp_cond (extra)) + { + int reg = opcode & 7; + uae_u16 cnt = (m68k_dreg (regs, reg) & 0xffff) - 1; + m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xffff) | cnt; + if (cnt != 0xffff) + m68k_setpc (pc + disp); + } +} + +void +fpuop_trapcc (uae_u32, uaecptr oldpc, uae_u32 extra) +{ + if (check_fp_cond (extra)) + Exception (7, oldpc - 2); +} + +void +fpuop_save (uae_u32 opcode) +{ + uae_u32 addr; + + if ((opcode & 070) == 030 + || !get_fp_addr (opcode, &addr, true)) + { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + if (fpu.is_integral) + { + // 4 byte 68040 IDLE frame + // FIXME: generate proper FPU stack frames that does not result + // in undefined behaviour from FPSP040 + if ((opcode & 070) == 040) + { + addr -= 4; + m68k_areg (regs, opcode & 7) = addr; + } + put_long (addr, 0x41000000); + } + else + { + // 28 byte 68881 IDLE frame + if ((opcode & 070) == 040) + { + addr -= 28; + m68k_areg (regs, opcode & 7) = addr; + } + put_long (addr, 0x1f180000); + for (int i = 0; i < 6; i++) + { + addr += 4; + put_long (addr, 0); + } + } +} + +void +fpuop_restore (uae_u32 opcode) +{ + uae_u32 addr; + uae_u32 format; + + if ((opcode & 070) == 040 + || !get_fp_addr (opcode, &addr, false)) + { + m68k_setpc (m68k_getpc () - 2); + op_illg (opcode); + return; + } + + format = get_long (addr); + addr += 4; + if ((format & 0xff000000) == 0) + // NULL frame + fpu_reset (); + else + addr += (format & 0xff0000) >> 16; + if ((opcode & 070) == 030) + m68k_areg (regs, opcode & 7) = addr; +} + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp index ffc784a5..ca4b841d 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp @@ -1,31 +1,42 @@ /* - * fpu/fpu_uae.cpp + * fpu/fpu_uae.cpp - the old UAE FPU * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * MC68881/68040 fpu emulation * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* + * UAE - The Un*x Amiga Emulator + * + * MC68881 emulation + * + * Copyright 1996 Herman ten Brugge + * + * * Following fixes by Lauri Pesonen, July 1999: * * FMOVEM list handling: @@ -86,9 +97,8 @@ * - Precision rounding single/double */ + #include "sysdeps.h" -#include -#include #include "memory.h" #include "readcpu.h" #include "newcpu.h" @@ -97,6 +107,17 @@ #include "fpu/fpu.h" #include "fpu/fpu_uae.h" +#ifdef HAVE_NEW_HEADERS +#define _GLIBCPP_USE_C99 1 +# include +# include +using namespace __gnu_cxx; +#undef _GLIBCPP_USE_C99 +#else +# include +# include +#endif + /* Global FPU context */ fpu_t fpu; @@ -166,8 +187,8 @@ PUBLIC void FFPU dump_registers(const char * str) sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", str, - get_register(0), get_register(1), get_register(2), get_register(3), - get_register(4), get_register(5), get_register(6), get_register(7) ); + fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3), + fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) ); fpu_debug((temp_str)); } @@ -195,9 +216,7 @@ PUBLIC void FFPU dump_registers(const char *) { } -PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32) -{ -} +#define dump_first_bytes(a,b) #endif @@ -219,10 +238,10 @@ PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x) PRIVATE inline bool FFPU do_isnan(fpu_register const & r) { - uae_u32 * p = (uae_u32 *)&r; - if ((p[FHI] & 0x7FF00000) == 0x7FF00000) { + fpu_register_parts const p = { r }; + if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) { // logical or is faster here. - if ((p[FHI] & 0x000FFFFF) || p[FLO]) { + if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) { return true; } } @@ -235,8 +254,8 @@ PRIVATE inline bool FFPU do_isnan(fpu_register const & r) PRIVATE inline bool FFPU do_isinf(fpu_register const & r) { - uae_u32 * p = (uae_u32 *)&r; - if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) { + fpu_register_parts const p = { r }; + if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) { return true; } return false; @@ -248,8 +267,8 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r) PRIVATE inline bool FFPU do_isneg(fpu_register const & r) { - uae_u32 * p = (uae_u32 *)&r; - return ((p[FHI] & 0x80000000) != 0); + fpu_register_parts const p = { r }; + return ((p.parts[FHI] & 0x80000000) != 0); } #ifndef HAVE_ISZERO @@ -258,8 +277,8 @@ PRIVATE inline bool FFPU do_isneg(fpu_register const & r) PRIVATE inline bool FFPU do_iszero(fpu_register const & r) { - uae_u32 * p = (uae_u32 *)&r; - return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0); + fpu_register_parts const p = { r }; + return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0); } // May be optimized for particular processors @@ -293,77 +312,70 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r) fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan; } -PRIVATE inline void FFPU make_nan(fpu_register & r) +PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative) { - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0xffffffff; - p[FHI] = 0x7fffffff; + fpu_register_parts p; + p.parts[FLO] = 0xffffffff; + p.parts[FHI] = negative ? 0xffffffff : 0x7fffffff; + r = p.val; } -PRIVATE inline void FFPU make_zero_positive(fpu_register & r) +PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative) { - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = p[FHI] = 0; + fpu_register_parts p; + p.parts[FLO] = 0; + p.parts[FHI] = negative ? 0x80000000 : 0; + r = p.val; } -PRIVATE inline void FFPU make_zero_negative(fpu_register & r) +PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative) { - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0; - p[FHI] = 0x80000000; -} - -PRIVATE inline void FFPU make_inf_positive(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0; - p[FHI] = 0x7FF00000; -} - -PRIVATE inline void FFPU make_inf_negative(fpu_register & r) -{ - uae_u32 * const p = (uae_u32 *)&r; - p[FLO] = 0; - p[FHI] = 0xFFF00000; + fpu_register_parts p; + p.parts[FLO] = 0; + p.parts[FHI] = negative ? 0xFFF00000 : 0x7FF00000; + r = p.val; } PRIVATE inline void FFPU fast_scale(fpu_register & r, int add) { - uae_u32 * const p = (uae_u32 *)&r; - int exp = (p[FHI] & 0x7FF00000) >> 20; + fpu_register_parts p = { r }; + int exp = (p.parts[FHI] & 0x7FF00000) >> 20; // TODO: overflow flags exp += add; if(exp >= 2047) { - make_inf_positive(r); + make_inf(r, false); + return; } else if(exp < 0) { // keep sign (+/- 0) - p[FHI] &= 0x80000000; + p.parts[FHI] &= 0x80000000; } else { - p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); + p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); } + r = p.val; } PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) { - uae_u32 * const p = (uae_u32 *)&r; - int exp = (p[FHI] & 0x7FF00000) >> 20; + fpu_register_parts const p = { r }; + int exp = (p.parts[FHI] & 0x7FF00000) >> 20; return( exp - 1023 ); } // Normalize to range 1..2 PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) { - uae_u32 * const p = (uae_u32 *)&r; - p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000; + fpu_register_parts p = { r }; + p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000; + r = p.val; } // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) { - uae_u32 * const a = (uae_u32 *)&ra; - uae_u32 * const b = (uae_u32 *)&rb; - return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); + fpu_register_parts const a = { ra }; + fpu_register_parts const b = { rb }; + return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0); } // Quotient Byte is loaded with the sign and least significant @@ -381,13 +393,15 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) return (0.0); fpu_register result; - uae_u32 * p = (uae_u32 *)&result; + fpu_register_parts p; uae_u32 sign = (value & 0x80000000); uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - p[FLO] = value << 29; - p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + p.parts[FLO] = value << 29; + p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + + result = p.val; fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); @@ -401,10 +415,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) return 0; uae_u32 result; - uae_u32 *p = (uae_u32 *)&src; + fpu_register_parts const p = { src }; - uae_u32 sign = (p[FHI] & 0x80000000); - uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; + uae_u32 sign = (p.parts[FHI] & 0x80000000); + uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20; if(exp + 127 < 1023) { exp = 0; @@ -414,7 +428,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) exp = exp + 127 - 1023; } - result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); + result = sign | (exp << 23) | ((p.parts[FHI] & 0x000FFFFF) << 3) | (p.parts[FLO] >> 29); fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); @@ -428,8 +442,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u return 0.0; fpu_register result; - uae_u32 *p = (uae_u32 *)&result; - + fpu_register_parts p; + uae_u32 sign = wrd1 & 0x80000000; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -466,8 +480,10 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u } // drop the explicit integer bit. - p[FLO] = (wrd2 << 21) | (wrd3 >> 11); - p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + + result = p.val; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); @@ -485,14 +501,14 @@ PRIVATE inline void FFPU make_extended_no_normalize( { // Is it zero? if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - make_zero_positive(result); + make_zero(result, false); return; } // Is it NaN? if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) { if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) { - make_nan(result); + make_nan(result, (wrd1 & 0x80000000) != 0); return; } } @@ -511,11 +527,13 @@ PRIVATE inline void FFPU make_extended_no_normalize( } // drop the explicit integer bit. - uae_u32 *p = (uae_u32 *)&result; - p[FLO] = (wrd2 << 21) | (wrd3 >> 11); - p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + fpu_register_parts p; + p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); - fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p))); + result = p.val; + + fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); } // from_exten @@ -527,14 +545,14 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = *wrd2 = *wrd3 = 0; return; } - - uae_u32 *p = (uae_u32 *)&src; - - fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI])); - uae_u32 sign = p[FHI] & 0x80000000; + fpu_register_parts const p = { src }; + + fpu_debug(("extract_extended (%X,%X)\n",p.parts[FLO],p.parts[FHI])); - uae_u32 exp = ((p[FHI] >> 20) & 0x7ff); + uae_u32 sign = p.parts[FHI] & 0x80000000; + + uae_u32 exp = ((p.parts[FHI] >> 20) & 0x7ff); // Check for maximum if(exp == 0x7FF) { exp = 0x7FFF; @@ -544,8 +562,8 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = sign | (exp << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); - *wrd3 = p[FLO] << 11; + *wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21); + *wrd3 = p.parts[FLO] << 11; fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -557,9 +575,11 @@ PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2) return 0.0; fpu_register result; - uae_u32 *p = (uae_u32 *)&result; - p[FLO] = wrd2; - p[FHI] = wrd1; + fpu_register_parts p; + p.parts[FLO] = wrd2; + p.parts[FHI] = wrd1; + + result = p.val; fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result)); @@ -577,9 +597,9 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, return; } */ - uae_u32 *p = (uae_u32 *)&src; - *wrd2 = p[FLO]; - *wrd1 = p[FHI]; + fpu_register_parts const p = { src }; + *wrd2 = p.parts[FLO]; + *wrd1 = p.parts[FHI]; fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2)); } @@ -590,8 +610,8 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, PRIVATE inline void FFPU make_fpsr(fpu_register const & r) { FPU fpsr.condition_codes - = ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0) - | ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0) + = (iszero(r) ? NATIVE_FFLAG_ZERO : 0) + | (isneg(r) ? NATIVE_FFLAG_NEGATIVE : 0) ; } #endif @@ -622,25 +642,25 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) fpu_register src0 = src; #endif - if (src == 0.0) + if (src == 0.0) return 0; - if (src < 0) { + if (src < 0) { tmp = 0x80000000; src = -src; - } else { + } else { tmp = 0; - } - frac = frexp (src, &expon); - frac += 0.5 / 16777216.0; - if (frac >= 1.0) { + } + frac = frexp (src, &expon); + frac += 0.5 / 16777216.0; + if (frac >= 1.0) { frac /= 2.0; expon++; - } + } result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff); // fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result)); - return (result); + return (result); } // to exten @@ -895,11 +915,9 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe break; case 3: ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); + ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -940,8 +958,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc())); fpu_debug(("get_fp_value ad=%X\n",ad)); fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad))); - dump_first_bytes( get_real_address(ad)-64, 64 ); - dump_first_bytes( get_real_address(ad), 64 ); + dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 ); + dump_first_bytes( get_real_address(ad, 0, 0), 64 ); switch (size) { case 0: @@ -988,6 +1006,15 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe return 0; } + switch (mode) { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + // fpu_debug(("get_fp_value result = %.04f\n",(float)src)); return 1; } @@ -1204,7 +1231,7 @@ PRIVATE inline int FFPU fpp_cond(int condition) #if 0 return fpcctrue(condition); #else - switch (condition) { + switch (condition & 0x1f) { case 0x00: CONDRET("False",0); case 0x01: CONDRET("Equal",Z); case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); @@ -1299,11 +1326,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) put_byte(ad, cc ? 0xff : 0x00); } -void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) +void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) { - fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ())); + fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - int cc = fpp_cond(opcode & 0x3f); + int cc = fpp_cond(extra & 0x3f); if (cc == -1) { m68k_setpc (oldpc); op_illg (opcode); @@ -1516,8 +1543,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) if ((opcode & 0x38) == 0) { if (extra & 0x2000) { // dr bit if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + m68k_dreg (regs, opcode & 7) = get_fpcr(); fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7)); } if (extra & 0x0800) { @@ -1548,8 +1574,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) else if ((opcode & 0x38) == 8) { if (extra & 0x2000) { // dr bit if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF; + m68k_areg (regs, opcode & 7) = get_fpcr(); fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7)); } if (extra & 0x0800) { @@ -1612,8 +1637,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } ad -= incr; if (extra & 0x1000) { - // according to the manual, the msb bits are always zero. - put_long (ad, get_fpcr() & 0xFFFF); + put_long (ad, get_fpcr()); fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad )); ad += 4; } @@ -1906,6 +1930,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) FPU registers[reg] = 1.0e256; fpu_debug(("FP const: 1.0e256\n")); break; + + // Valid for 64 bits only (see fpu.cpp) #if 0 case 0x3c: FPU registers[reg] = 1.0e512; @@ -1942,7 +1968,114 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) return; } fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc())); +#if 0 // MJ added, not tested now + if (FPU is_integral) { + // 68040-specific operations + switch (extra & 0x7f) { + case 0x40: /* FSMOVE */ + fpu_debug(("FSMOVE %.04f\n",(double)src)); + FPU registers[reg] = (float)src; + make_fpsr(FPU registers[reg]); + break; + case 0x44: /* FDMOVE */ + fpu_debug(("FDMOVE %.04f\n",(double)src)); + FPU registers[reg] = (double)src; + make_fpsr(FPU registers[reg]); + break; + case 0x41: /* FSSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (float)sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x45: /* FDSQRT */ + fpu_debug(("FSQRT %.04f\n",(double)src)); + FPU registers[reg] = (double)sqrt (src); + make_fpsr(FPU registers[reg]); + break; + case 0x58: /* FSABS */ + fpu_debug(("FSABS %.04f\n",(double)src)); + FPU registers[reg] = (float)fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5c: /* FDABS */ + fpu_debug(("FDABS %.04f\n",(double)src)); + FPU registers[reg] = (double)fabs(src); + make_fpsr(FPU registers[reg]); + break; + case 0x5a: /* FSNEG */ + fpu_debug(("FSNEG %.04f\n",(double)src)); + FPU registers[reg] = (float)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x5e: /* FDNEG */ + fpu_debug(("FDNEG %.04f\n",(double)src)); + FPU registers[reg] = (double)-src; + make_fpsr(FPU registers[reg]); + break; + case 0x60: /* FSDIV */ + fpu_debug(("FSDIV %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x64: /* FDDIV */ + fpu_debug(("FDDIV %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] / src); + make_fpsr(FPU registers[reg]); + break; + case 0x62: /* FSADD */ + fpu_debug(("FSADD %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x66: /* FDADD */ + fpu_debug(("FDADD %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] + src); + make_fpsr(FPU registers[reg]); + break; + case 0x68: /* FSSUB */ + fpu_debug(("FSSUB %.04f\n",(double)src)); + FPU registers[reg] = (float)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x6c: /* FDSUB */ + fpu_debug(("FDSUB %.04f\n",(double)src)); + FPU registers[reg] = (double)(FPU registers[reg] - src); + make_fpsr(FPU registers[reg]); + break; + case 0x63: /* FSMUL */ + case 0x67: /* FDMUL */ + get_dest_flags(FPU registers[reg]); + get_source_flags(src); + if(fl_dest.in_range && fl_source.in_range) { + if ((extra & 0x7f) == 0x63) + FPU registers[reg] = (float)(FPU registers[reg] * src); + else + FPU registers[reg] = (double)(FPU registers[reg] * src); + } + else if (fl_dest.nan || fl_source.nan || + fl_dest.zero && fl_source.infinity || + fl_dest.infinity && fl_source.zero ) { + make_nan( FPU registers[reg], fl_dest.negative ); + } + else if (fl_dest.zero || fl_source.zero ) { + make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative); + } + else { + make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative); + } + make_fpsr(FPU registers[reg]); + break; + default: + // Continue decode-execute 6888x instructions below + goto process_6888x_instructions; + } + fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc())); + dump_registers( "END "); + return; + } + process_6888x_instructions: +#endif switch (extra & 0x7f) { case 0x00: /* FMOVE */ fpu_debug(("FMOVE %.04f\n",(double)src)); @@ -1954,7 +2087,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FINT %.04f\n",(double)src)); // FPU registers[reg] = (int) (src + 0.5); // FIXME: use native rounding mode flags - switch (get_fpcr() & 0x30) { + switch (get_fpcr() & FPCR_ROUNDING_MODE) { case FPCR_ROUND_ZERO: FPU registers[reg] = round_to_zero(src); break; @@ -2075,7 +2208,10 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x1a: /* FNEG */ fpu_debug(("FNEG %.04f\n",(double)src)); - FPU registers[reg] = -src; + if (iszero(src)) + make_zero(FPU registers[reg], !isneg(src)); + else + FPU registers[reg] = -src; make_fpsr(FPU registers[reg]); break; case 0x1c: /* FACOS */ @@ -2092,7 +2228,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FGETEXP %.04f\n",(double)src)); #if FPU_HAVE_IEEE_DOUBLE if( isinf(src) ) { - make_nan( FPU registers[reg] ); + make_nan( FPU registers[reg], isneg(src) ); } else { FPU registers[reg] = fast_fgetexp( src ); @@ -2116,7 +2252,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) FPU registers[reg] = 0; } else if( isinf(src) ) { - make_nan( FPU registers[reg] ); + make_nan( FPU registers[reg], isneg(src) ); } else { FPU registers[reg] = src; @@ -2166,27 +2302,15 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) FPU registers[reg] *= src; } else if (fl_dest.nan || fl_source.nan || - fl_dest.zero && fl_source.infinity || - fl_dest.infinity && fl_source.zero ) { - make_nan( FPU registers[reg] ); + (fl_dest.zero && fl_source.infinity) || + (fl_dest.infinity && fl_source.zero) ) { + make_nan( FPU registers[reg], fl_dest.negative ); } else if (fl_dest.zero || fl_source.zero ) { - if (fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_zero_negative(FPU registers[reg]); - } - else { - make_zero_positive(FPU registers[reg]); - } + make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative); } else { - if( fl_dest.negative && !fl_source.negative || - !fl_dest.negative && fl_source.negative) { - make_inf_negative(FPU registers[reg]); - } - else { - make_inf_positive(FPU registers[reg]); - } + make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative); } #else fpu_debug(("FMUL %.04f\n",(double)src)); @@ -2223,8 +2347,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) // Overflow, underflow #if FPU_HAVE_IEEE_DOUBLE - if( isinf(FPU registers[reg]) ) { - make_nan( FPU registers[reg] ); + if( isinf(src) ) { + make_nan( FPU registers[reg], isneg(src) ); } else { // When the absolute value of the source operand is >= 2^14, @@ -2336,6 +2460,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) dump_registers( "END "); } + +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} + /* -------------------------- Initialization -------------------------- */ void FFPU fpu_init (bool integral_68040) diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h index 7fc4ebbd..822fc220 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h @@ -1,28 +1,33 @@ /* - * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core + * fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_UAE_H @@ -78,11 +83,9 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r); PRIVATE inline bool FFPU do_isneg(fpu_register const & r); PRIVATE inline bool FFPU do_iszero(fpu_register const & r); -PRIVATE inline void FFPU make_nan(fpu_register & r); -PRIVATE inline void FFPU make_zero_positive(fpu_register & r); -PRIVATE inline void FFPU make_zero_negative(fpu_register & r); -PRIVATE inline void FFPU make_inf_positive(fpu_register & r); -PRIVATE inline void FFPU make_inf_negative(fpu_register & r); +PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative); +PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative); +PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative); PRIVATE inline void FFPU fast_scale(fpu_register & r, int add); PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r); diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp index 70e59086..29af7ddb 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp @@ -1,27 +1,33 @@ /* - * fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. + * fpu/fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86. * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * Based on UAE FPU, original copyright 1996 Herman ten Brugge, - * rewritten for x86 by Lauri Pesonen 1999-2000, - * accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000. + * MC68881/68040 fpu emulation * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Interface @@ -134,10 +140,8 @@ * */ -#include -#include -#include -#include +# include +# include #include "sysdeps.h" #include "memory.h" @@ -238,8 +242,6 @@ PUBLIC void FFPU fpu_dump_flags(void) #include "debug.h" #if FPU_DEBUG -#undef __inline__ -#define __inline__ PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual) { @@ -390,7 +392,7 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *) /* ---------------------------- Status functions ---------------------------- */ -PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN () +PRIVATE void inline FFPU SET_BSUN_ON_NAN () { if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) { x86_status_word |= SW_FAKE_BSUN; @@ -398,7 +400,7 @@ PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN () } } -PRIVATE void __inline__ FFPU build_ex_status () +PRIVATE void inline FFPU build_ex_status () { if(x86_status_word & SW_EXCEPTION_MASK) { // _asm FNCLEX @@ -415,20 +417,20 @@ When the FPU creates a NAN, the NAN always contains the same bit pattern in the mantissa. All bits of the mantissa are ones for any precision. When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa. */ -PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f) +PRIVATE inline void FFPU MAKE_NAN (fpu_register & f, bool negative) { // Make it non-signaling. uae_u8 * p = (uae_u8 *) &f; memset( p, 0xFF, sizeof(fpu_register) - 1 ); - p[9] = 0x7F; + p[9] = negative ? 0xff : 0x7F; } /* For single- and double-precision infinities the fraction is a zero. -For extended-precision infinities, the mantissa’s MSB, the explicit +For extended-precision infinities, the mantissa�s MSB, the explicit integer bit, can be either one or zero. */ -PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f) +PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { @@ -439,7 +441,7 @@ PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f) return(0); } -PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f) +PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { @@ -450,7 +452,7 @@ PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f) return(0); } -PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f) +PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; return *((uae_u32 *)p) == 0 && @@ -458,34 +460,34 @@ PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f) ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0; } -PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f) +PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f) { uae_u8 * p = (uae_u8 *) &f; memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0x7FFF; } -PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f) +PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f) { uae_u8 * p = (uae_u8 *) &f; memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0xFFFF; } -PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) +PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) { uae_u32 * const p = (uae_u32 *) &f; memset( p, 0, sizeof(fpu_register) ); } -PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) +PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) { uae_u32 * const p = (uae_u32 *) &f; memset( p, 0, sizeof(fpu_register) ); *((uae_u32 *)&p[4]) = 0x80000000; } -PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) +PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; return( (p[9] & 0x80) != 0 ); @@ -900,6 +902,34 @@ PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fmove"); } +PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fsmove"); +} + +PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + FPU_CONSISTENCY_CHECK_STOP("do_fdmove"); +} + /* PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) { @@ -1023,6 +1053,50 @@ PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fsqrt"); } +PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fsqrt \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fssqrt"); +} + +PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fsqrt \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt"); +} + PRIVATE void FFPU do_ftst ( fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1311,6 +1385,48 @@ PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fabs"); } +PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fabs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fabs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsabs"); +} + +PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fabs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fabs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdabs"); +} + PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1341,6 +1457,48 @@ PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fneg"); } +PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fchs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fchs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsneg"); +} + +PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fchs \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "=m" (dest) + : "m" (src) + ); + // x86 fchs should not rise any exceptions (except stack underflow) + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~SW_EXCEPTION_MASK; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdneg"); +} + PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1466,6 +1624,50 @@ PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fdiv"); } +PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fdiv %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsdiv"); +} + +PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fdiv %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fddiv"); +} + // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. // Quotient Byte is loaded with the sign and least significant @@ -1851,6 +2053,48 @@ PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fadd"); } +PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fadd \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsadd"); +} + +PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fadd \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdadd"); +} + PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1882,6 +2126,48 @@ PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fmul"); } +PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fmul \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fsmul"); +} + +PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fmul \n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdmul"); +} + PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2040,6 +2326,52 @@ PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fsub"); } +PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fsub %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fssub"); +} + +PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src ) +{ + FPU_CONSISTENCY_CHECK_START(); + __asm__ __volatile__( + "fldt %2\n" + "fldt %1\n" + "fsub %%st(1), %%st(0)\n" + "fxam \n" + "fnstsw %0\n" + "fstpt %1\n" + "fstp %%st(0)\n" + : "=m" (x86_status_word), "+m" (dest) + : "m" (src) + ); + if(x86_status_word & SW_EXCEPTION_MASK) { +// _asm FNCLEX + __asm__ __volatile__("fnclex"); + x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); + x86_status_word_accrued |= x86_status_word; + } + FPU_CONSISTENCY_CHECK_STOP("do_fdsub"); +} + PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2284,11 +2616,9 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src break; case 3: ad = m68k_areg (regs, reg); - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - ad = m68k_areg (regs, reg); + ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -2387,6 +2717,15 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src return 0; } + switch (mode) { + case 3: + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; + break; + case 4: + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + break; + } + // D(bug("get_fp_value result = %.04f\r\n",(float)src)); return 1; @@ -2612,7 +2951,7 @@ PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) #define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I)) #define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN) - switch (condition) { + switch (condition & 0x1f) { // Common Tests, no BSUN case 0x01: CONDRET("Equal",Z); @@ -2757,11 +3096,11 @@ PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) } } -PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) +PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) { int cc; - D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ())); + D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); #if I3_ON_FTRAPCC #error "FIXME: _asm int 3" @@ -2769,7 +3108,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) #endif // This must be broken. - cc = fpp_cond(opcode, opcode & 0x3f); + cc = fpp_cond(opcode, extra & 0x3f); if (cc < 0) { m68k_setpc (oldpc); @@ -2856,7 +3195,7 @@ PRIVATE void FFPU do_null_frestore () { // A null-restore operation sets FP7-FP0 positive, nonsignaling NANs. for( int i=0; i<8; i++ ) { - MAKE_NAN( FPU registers[i] ); + MAKE_NAN( FPU registers[i], false ); } FPU instruction_address = 0; @@ -4646,6 +4985,249 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 } +/* -------------------------- 040 ALU -------------------------- */ +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSMOVE %s\r\n",etos(src))); + do_fsmove( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDMOVE %s\r\n",etos(src))); + do_fdmove( FPU registers[reg], src ); + build_ex_status(); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSSQRT %s\r\n",etos(src))); + do_fssqrt( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDSQRT %s\r\n",etos(src))); + do_fdsqrt( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSABS %s\r\n",etos(src))); + do_fsabs( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDABS %s\r\n",etos(src))); + do_fdabs( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSNEG %s\r\n",etos(src))); + do_fsneg( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDNEG %s\r\n",etos(src))); + do_fdneg( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSDIV %s\r\n",etos(src))); + do_fsdiv( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDDIV %s\r\n",etos(src))); + do_fddiv( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSADD %s\r\n",etos(src))); + do_fsadd( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDADD %s\r\n",etos(src))); + do_fdadd( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSSUB %s\r\n",etos(src))); + do_fssub( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FDSUB %s\r\n",etos(src))); + do_fdsub( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSMUL %s\r\n",etos(src))); + do_fsmul( FPU registers[reg], src ); + dump_registers( "END "); +} + +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ) +{ + int reg = (extra >> 7) & 7; + fpu_register src; + if (get_fp_value (opcode, extra, src) == 0) { + m68k_setpc (m68k_getpc () - 4); + op_illg (opcode); + dump_registers( "END "); + return; + } + D(bug("FSMUL %s\r\n",etos(src))); + do_fsmul( FPU registers[reg], src ); + dump_registers( "END "); +} + /* ---------------------------- ALU ---------------------------- */ PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ) @@ -5037,7 +5619,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra ) D(bug("FGETEXP %s\r\n",etos(src))); if( IS_INFINITY(src) ) { - MAKE_NAN( FPU registers[reg] ); + MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) ); do_ftst( FPU registers[reg] ); x86_status_word |= SW_IE; } else { @@ -5058,7 +5640,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra ) } D(bug("FGETMAN %s\r\n",etos(src))); if( IS_INFINITY(src) ) { - MAKE_NAN( FPU registers[reg] ); + MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) ); do_ftst( FPU registers[reg] ); x86_status_word |= SW_IE; } else { @@ -5186,7 +5768,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra ) } D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc())); if( IS_INFINITY(FPU registers[reg]) ) { - MAKE_NAN( FPU registers[reg] ); + MAKE_NAN( FPU registers[reg], IS_NEGATIVE(FPU registers[reg]) ); do_ftst( FPU registers[reg] ); x86_status_word |= SW_IE; } else { @@ -5744,6 +6326,61 @@ PRIVATE void FFPU build_fpp_opp_lookup_table () } break; } + + if (FPU is_integral) { + switch (extra & 0x7f) { + case 0x40: + fpufunctbl[mask] = & FFPU fpuop_do_fsmove; + break; + case 0x44: + fpufunctbl[mask] = & FFPU fpuop_do_fdmove; + break; + case 0x41: + fpufunctbl[mask] = & FFPU fpuop_do_fssqrt; + break; + case 0x45: + fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt; + break; + case 0x58: + fpufunctbl[mask] = & FFPU fpuop_do_fsabs; + break; + case 0x5c: + fpufunctbl[mask] = & FFPU fpuop_do_fdabs; + break; + case 0x5a: + fpufunctbl[mask] = & FFPU fpuop_do_fsneg; + break; + case 0x5e: + fpufunctbl[mask] = & FFPU fpuop_do_fdneg; + break; + case 0x60: + fpufunctbl[mask] = & FFPU fpuop_do_fsdiv; + break; + case 0x64: + fpufunctbl[mask] = & FFPU fpuop_do_fddiv; + break; + case 0x62: + fpufunctbl[mask] = & FFPU fpuop_do_fsadd; + break; + case 0x66: + fpufunctbl[mask] = & FFPU fpuop_do_fdadd; + break; + case 0x68: + fpufunctbl[mask] = & FFPU fpuop_do_fssub; + break; + case 0x6c: + fpufunctbl[mask] = & FFPU fpuop_do_fdsub; + break; + case 0x63: + fpufunctbl[mask] = & FFPU fpuop_do_fsmul; + break; + case 0x67: + fpufunctbl[mask] = & FFPU fpuop_do_fdmul; + break; + default: + break; + } + } switch (extra & 0x7f) { case 0x00: @@ -6033,6 +6670,26 @@ PRIVATE void FFPU do_fld1 ( fpu_register & dest ) } +void fpu_set_fpsr(uae_u32 new_fpsr) +{ + set_fpsr(new_fpsr); +} + +uae_u32 fpu_get_fpsr(void) +{ + return get_fpsr(); +} + +void fpu_set_fpcr(uae_u32 new_fpcr) +{ + set_fpcr(new_fpcr); +} + +uae_u32 fpu_get_fpcr(void) +{ + return get_fpcr(); +} + /* ---------------------------- MAIN INIT ---------------------------- */ #ifdef HAVE_SIGACTION @@ -6079,11 +6736,15 @@ PUBLIC void FFPU fpu_init( bool integral_68040 ) FPU fpsr.quotient = 0; for( int i=0; i<8; i++ ) { - MAKE_NAN( FPU registers[i] ); + MAKE_NAN( FPU registers[i], false ); } build_fpp_opp_lookup_table(); +/* _asm { + FNINIT + FLDCW x86_control_word + } */ __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); do_fldpi( const_pi ); @@ -6111,6 +6772,10 @@ PUBLIC void FFPU fpu_init( bool integral_68040 ) set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 ); // Just in case. +/* _asm { + FNINIT + FLDCW x86_control_word + } */ __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); } diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h index 96f1d959..c42bfa91 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h @@ -1,28 +1,33 @@ /* - * fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core + * fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_X86_H @@ -94,17 +99,17 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void); PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name); // Get special floating-point value class -PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f); -PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f); -PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f); -PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f); +PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f); // Make a special floating-point value -PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f); -PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_NAN (fpu_register & f, bool negative); +PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f); +PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f); // Conversion from extended floating-point values PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM; @@ -342,6 +347,24 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra ); PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra ); PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra ); +// 040 +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ); +PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ); + // Get & Put floating-point values PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM; PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM; @@ -351,9 +374,9 @@ PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM; PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM; // Misc functions -PRIVATE void __inline__ FFPU set_host_fpu_control_word (); -PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN (); -PRIVATE void __inline__ FFPU build_ex_status (); +PRIVATE void inline FFPU set_host_fpu_control_word (); +PRIVATE void inline FFPU SET_BSUN_ON_NAN (); +PRIVATE void inline FFPU build_ex_status (); PRIVATE void FFPU do_null_frestore (); PRIVATE void FFPU build_fpp_opp_lookup_table (); PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult ); diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h index ecdecfbc..6e5a3766 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h @@ -1,3 +1,35 @@ +/* + * fpu/fpu_x86_asm.h - Extra Definitions for the X86 assembly FPU core + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #define DEFINE_X86_MACRO(name, value) \ asm(".local " #name "\n\t" #name " = " #value) diff --git a/BasiliskII/src/uae_cpu/fpu/impl.h b/BasiliskII/src/uae_cpu/fpu/impl.h index c79d1f3f..ec5648a9 100644 --- a/BasiliskII/src/uae_cpu/fpu/impl.h +++ b/BasiliskII/src/uae_cpu/fpu/impl.h @@ -1,28 +1,38 @@ /* * fpu/impl.h - extra functions and inline implementations * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_IMPL_H @@ -101,14 +111,16 @@ static inline void FFPU set_fpsr(uae_u32 new_fpsr) /* Return the floating-point control register in m68k format */ static inline uae_u32 FFPU get_fpcr(void) { - uae_u32 rounding_precision = get_rounding_precision(); - uae_u32 rounding_mode = get_rounding_mode(); - return (rounding_precision | rounding_mode); + // according to the manual, the msb bits are always zero. + // According to Toni Wilen, on '040 the least + // significant 4 bits are not masked out + return FPU fpcr & (CPUType == 4 ? 0xffff : 0xfff0); } /* Set the floating-point control register from an m68k format */ static inline void FFPU set_fpcr(uae_u32 new_fpcr) { + FPU fpcr = new_fpcr; set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION); set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE ); set_host_control_word(); @@ -123,9 +135,8 @@ static inline void FFPU set_fpcr(uae_u32 new_fpcr) /* Retrieve a floating-point register value and convert it to double precision */ static inline double FFPU fpu_get_register(int r) { - double f; - __asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r])); - return f; + /* only used for debug output; no need for any fancy asm here */ + return FPU registers[r]; } #endif diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp index eabb376e..c9616927 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp @@ -1,28 +1,33 @@ /* * fpu/mathlib.cpp - Floating-point math support library * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* NOTE: this file shall be included only from fpu/fpu_*.cpp */ @@ -40,6 +45,7 @@ #if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) +#if !defined(HAVE_EXP10L) && !defined(HAVE_POW10L) PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y) { fpu_extended value, exponent; @@ -82,7 +88,9 @@ PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y) __asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent)); return value; } +#endif +#ifndef HAVE_LOG1PL PRIVATE fpu_extended fp_do_log1p(fpu_extended x) { // TODO: handle NaN and +inf/-inf @@ -96,5 +104,6 @@ PRIVATE fpu_extended fp_do_log1p(fpu_extended x) __asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0)); return value; } +#endif #endif diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h index 2363af56..26e47ff8 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.h +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -1,28 +1,33 @@ /* - * fpu/mathlib.h - Floating-point math support library + * fpu/mathlib.h - Floating-point math support library * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_MATHLIB_H @@ -49,22 +54,7 @@ // Use ISO C99 extended-precision math functions (glibc 2.1+) #define FPU_USE_ISO_C99 1 -// NOTE: this is irrelevant on Win32 platforms since the MS libraries -// don't support extended-precision floating-point computations -#if defined(WIN32) && USE_LONG_DOUBLE -#undef FPU_USE_ISO_C99 -#endif - -// Use faster implementation of math functions, but this could cause -// some incorrect results (?) -#ifdef _MSC_VER -// MSVC uses intrinsics for all of the math functions, so it should still be fast -#define FPU_FAST_MATH 0 -#else -#define FPU_FAST_MATH 1 -#endif - -#if FPU_USE_ISO_C99 +#if defined(FPU_USE_ISO_C99) // NOTE: no prior shall be included at this point #define __USE_ISOC99 1 // for glibc 2.2.X and newer #define __USE_ISOC9X 1 // for glibc 2.1.X @@ -147,7 +137,7 @@ union fpu_double_shape { unsigned int mantissa0:20; unsigned int mantissa1:32; #else -# if HOST_FLOAT_WORDS_BIG_ENDIAN +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int mantissa0:20; unsigned int exponent:11; unsigned int negative:1; @@ -172,7 +162,7 @@ union fpu_double_shape { unsigned int mantissa0:19; unsigned int mantissa1:32; #else -# if HOST_FLOAT_WORDS_BIG_ENDIAN +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int mantissa0:19; unsigned int quiet_nan:1; unsigned int exponent:11; @@ -191,7 +181,7 @@ union fpu_double_shape { /* This format is used to extract the sign_exponent and mantissa parts only */ struct { -#if HOST_FLOAT_WORDS_BIG_ENDIAN +#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int msw:32; unsigned int lsw:32; #else @@ -215,7 +205,7 @@ union fpu_extended_shape { unsigned int mantissa0:32; unsigned int mantissa1:32; #else -# if HOST_FLOAT_WORDS_BIG_ENDIAN +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int exponent:15; unsigned int negative:1; unsigned int empty:16; @@ -242,7 +232,7 @@ union fpu_extended_shape { unsigned int mantissa0:30; unsigned int mantissa1:32; #else -# if HOST_FLOAT_WORDS_BIG_ENDIAN +# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int exponent:15; unsigned int negative:1; unsigned int empty:16; @@ -264,7 +254,7 @@ union fpu_extended_shape { /* This format is used to extract the sign_exponent and mantissa parts only */ struct { -#if HOST_FLOAT_WORDS_BIG_ENDIAN +#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN unsigned int sign_exponent:16; unsigned int empty:16; unsigned int msw:32; @@ -310,7 +300,7 @@ union fpu_extended_shape { unsigned int exponent:15; unsigned int quiet_nan:1; unsigned int mantissa0:15; - unsigned int mantissa1:30; + unsigned int mantissa1:32; unsigned int mantissa2:32; unsigned int mantissa3:32; #else @@ -325,7 +315,7 @@ union fpu_extended_shape { } ieee_nan; /* This format is used to extract the sign_exponent and mantissa parts only */ -#if HOST_FLOAT_WORDS_BIG_ENDIAN +#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN struct { uae_u64 msw; uae_u64 lsw; @@ -351,9 +341,9 @@ union fpu_extended_shape { }; #endif -// Declare and initialize a pointer to a shape of the requested FP type -#define fp_declare_init_shape(psvar, rfvar, ftype) \ - fpu_ ## ftype ## _shape * psvar = (fpu_ ## ftype ## _shape *)( &rfvar ) +// Declare a shape of the requested FP type +#define fp_declare_init_shape(psvar, ftype) \ + fpu_ ## ftype ## _shape psvar /* -------------------------------------------------------------------------- */ /* --- Extra Math Functions --- */ @@ -370,47 +360,51 @@ union fpu_extended_shape { PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r) { #ifdef BRANCHES_ARE_EXPENSIVE -#ifndef USE_LONG_DOUBLE - fp_declare_init_shape(sxp, r, double); - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; +#if !defined(USE_LONG_DOUBLE) + fp_declare_init_shape(sxp, double); + sxp.value = r; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; hx &= 0x7fffffff; hx |= (uae_u32)(lx | (-lx)) >> 31; hx = 0x7ff00000 - hx; - return (((uae_u32)hx) >> 31) != 0; -#elif USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - uae_s64 hx = sxp->parts64.msw; - uae_s64 lx = sxp->parts64.lsw; + return (int)(((uae_u32)hx) >> 31); +#elif defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s64 hx = sxp.parts64.msw; + uae_s64 lx = sxp.parts64.lsw; hx &= 0x7fffffffffffffffLL; hx |= (uae_u64)(lx | (-lx)) >> 63; hx = 0x7fff000000000000LL - hx; - return ((uae_u64)hx >> 63) != 0; + return (int)((uae_u64)hx >> 63); #else - fp_declare_init_shape(sxp, r, extended); - uae_s32 se = sxp->parts.sign_exponent; - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s32 se = sxp.parts.sign_exponent; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; se = (se & 0x7fff) << 1; lx |= hx & 0x7fffffff; se |= (uae_u32)(lx | (-lx)) >> 31; se = 0xfffe - se; - // TODO: check whether rshift count is 16 or 31 - return (((uae_u32)(se)) >> 16) != 0; + return (int)(((uae_u32)(se)) >> 31); #endif #else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX) +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + return (sxp.ieee.exponent == FP_EXTENDED_EXP_MAX) #else - fp_declare_init_shape(sxp, r, double); - return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX) + fp_declare_init_shape(sxp, double); + sxp.value = r; + return (sxp.ieee.exponent == FP_DOUBLE_EXP_MAX) #endif - && (sxp->ieee_nan.mantissa0 != 0) - && (sxp->ieee_nan.mantissa1 != 0) + && (sxp.ieee.mantissa0 & 0x7fffffff) != 0 + && sxp.ieee.mantissa1 != 0 #ifdef USE_QUAD_DOUBLE - && (sxp->ieee_nan.mantissa2 != 0) - && (sxp->ieee_nan.mantissa3 != 0) + && sxp.ieee.mantissa2 != 0 + && sxp.ieee.mantissa3 != 0 #endif ; #endif @@ -426,50 +420,62 @@ PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r) PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r) { #ifdef BRANCHES_ARE_EXPENSIVE -#ifndef USE_LONG_DOUBLE - fp_declare_init_shape(sxp, r, double); - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; +#if !defined(USE_LONG_DOUBLE) + fp_declare_init_shape(sxp, double); + sxp.value = r; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; lx |= (hx & 0x7fffffff) ^ 0x7ff00000; lx |= -lx; - return (~(lx >> 31) & (hx >> 30)) != 0; -#elif USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - uae_s64 hx = sxp->parts64.msw; - uae_s64 lx = sxp->parts64.lsw; + return ~(lx >> 31) & (hx >> 30); +#elif defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + uae_s64 hx = sxp.parts64.msw; + uae_s64 lx = sxp.parts64.lsw; lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL; lx |= -lx; - return (~(lx >> 63) & (hx >> 62)) != 0; + return ~(lx >> 63) & (hx >> 62); #else - fp_declare_init_shape(sxp, r, extended); - uae_s32 se = sxp->parts.sign_exponent; - uae_s32 hx = sxp->parts.msw; - uae_s32 lx = sxp->parts.lsw; + fp_declare_init_shape(sxp, extended); + sxp.value = r; + /* NOTE: This function should work for both m68k and native INFs. */ +#if 0 + uae_s32 se = sxp.parts.sign_exponent; + uae_s32 hx = sxp.parts.msw; + uae_s32 lx = sxp.parts.lsw; /* This additional ^ 0x80000000 is necessary because in Intel's internal representation of the implicit one is explicit. NOTE: anyway, this is equivalent to & 0x7fffffff in that case. */ -#ifdef __i386__ +#ifdef CPU_i386 lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff); #else lx |= (hx & 0x7fffffff) | ((se & 0x7fff) ^ 0x7fff); #endif lx |= -lx; se &= 0x8000; - return (~(lx >> 31) & (1 - (se >> 14))) != 0; + return ~(lx >> 31) & (1 - (se >> 14)); +#else + return sxp.ieee.exponent == FP_EXTENDED_EXP_MAX + && (sxp.ieee.mantissa0 & 0x7fffffff) == 0 + && sxp.ieee.mantissa1 == 0; +#endif #endif #else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX) +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX) #else - fp_declare_init_shape(sxp, r, double); - return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX) + fp_declare_init_shape(sxp, double); + sxp.value = r; + return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX) #endif - && (sxp->ieee_nan.mantissa0 == 0) - && (sxp->ieee_nan.mantissa1 == 0) + && (sxp.ieee.mantissa0 & 0x7fffffff) == 0 + && sxp.ieee.mantissa1 == 0 #ifdef USE_QUAD_DOUBLE - && (sxp->ieee_nan.mantissa2 == 0) - && (sxp->ieee_nan.mantissa3 == 0) + && sxp.ieee.mantissa2 == 0 + && sxp.ieee.mantissa3 == 0 #endif ; #endif @@ -480,12 +486,13 @@ PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r) PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r) { -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); #else - fp_declare_init_shape(sxp, r, double); + fp_declare_init_shape(sxp, double); #endif - return sxp->ieee.negative; + sxp.value = r; + return sxp.ieee.negative; } #undef iszero @@ -494,17 +501,18 @@ PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r) PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r) { // TODO: BRANCHES_ARE_EXPENSIVE -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); #else - fp_declare_init_shape(sxp, r, double); + fp_declare_init_shape(sxp, double); #endif - return (sxp->ieee.exponent == 0) - && (sxp->ieee.mantissa0 == 0) - && (sxp->ieee.mantissa1 == 0) + sxp.value = r; + return (sxp.ieee.exponent == 0) + && (sxp.ieee.mantissa0 == 0) + && (sxp.ieee.mantissa1 == 0) #ifdef USE_QUAD_DOUBLE - && (sxp->ieee.mantissa2 == 0) - && (sxp->ieee.mantissa3 == 0) + && (sxp.ieee.mantissa2 == 0) + && (sxp.ieee.mantissa3 == 0) #endif ; } @@ -527,158 +535,155 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r) fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan; } -PRIVATE inline void FFPU make_nan(fpu_register & r) +PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative) { - // FIXME: is that correct ? -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee.exponent = FP_EXTENDED_EXP_MAX; - sxp->ieee.mantissa0 = 0xffffffff; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.ieee.exponent = FP_EXTENDED_EXP_MAX; + sxp.ieee.empty = 0; + sxp.ieee.mantissa0 = 0xffffffff; #else - fp_declare_init_shape(sxp, r, double); - sxp->ieee.exponent = FP_DOUBLE_EXP_MAX; - sxp->ieee.mantissa0 = 0xfffff; + fp_declare_init_shape(sxp, double); + sxp.ieee.exponent = FP_DOUBLE_EXP_MAX; + sxp.ieee.mantissa0 = 0xfffff; #endif - sxp->ieee.mantissa1 = 0xffffffff; + sxp.ieee.mantissa1 = 0xffffffff; #ifdef USE_QUAD_DOUBLE - sxp->ieee.mantissa2 = 0xffffffff; - sxp->ieee.mantissa3 = 0xffffffff; + sxp.ieee.mantissa2 = 0xffffffff; + sxp.ieee.mantissa3 = 0xffffffff; #endif + sxp.ieee.negative = negative; + r = sxp.value; } -PRIVATE inline void FFPU make_zero_positive(fpu_register & r) +PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative) { #if 1 - r = +0.0; + r = negative ? -0.0 : +0.0; #else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.ieee.empty = 0; #else - fp_declare_init_shape(sxp, r, double); + fp_declare_init_shape(sxp, double); #endif - sxp->ieee.negative = 0; - sxp->ieee.exponent = 0; - sxp->ieee.mantissa0 = 0; - sxp->ieee.mantissa1 = 0; + sxp.ieee.negative = negative; + sxp.ieee.exponent = 0; + sxp.ieee.mantissa0 = 0; + sxp.ieee.mantissa1 = 0; #ifdef USE_QUAD_DOUBLE - sxp->ieee.mantissa2 = 0; - sxp->ieee.mantissa3 = 0; + sxp.ieee.mantissa2 = 0; + sxp.ieee.mantissa3 = 0; #endif + r = sxp.value; #endif } -PRIVATE inline void FFPU make_zero_negative(fpu_register & r) +PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative) { -#if 1 - r = -0.0; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.ieee.exponent = FP_EXTENDED_EXP_MAX; + sxp.ieee.mantissa0 = 0x80000000; + sxp.ieee.empty = 0; #else -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); -#else - fp_declare_init_shape(sxp, r, double); + fp_declare_init_shape(sxp, double); + sxp.ieee.exponent = FP_DOUBLE_EXP_MAX; + sxp.ieee.mantissa0 = 0; #endif - sxp->ieee.negative = 1; - sxp->ieee.exponent = 0; - sxp->ieee.mantissa0 = 0; - sxp->ieee.mantissa1 = 0; + sxp.ieee.negative = negative; + sxp.ieee.mantissa1 = 0; #ifdef USE_QUAD_DOUBLE - sxp->ieee.mantissa2 = 0; - sxp->ieee.mantissa3 = 0; -#endif -#endif -} - -PRIVATE inline void FFPU make_inf_positive(fpu_register & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; -#else - fp_declare_init_shape(sxp, r, double); - sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; -#endif - sxp->ieee_nan.negative = 0; - sxp->ieee_nan.mantissa0 = 0; - sxp->ieee_nan.mantissa1 = 0; -#ifdef USE_QUAD_DOUBLE - sxp->ieee_nan.mantissa2 = 0; - sxp->ieee_nan.mantissa3 = 0; -#endif -} - -PRIVATE inline void FFPU make_inf_negative(fpu_register & r) -{ -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; -#else - fp_declare_init_shape(sxp, r, double); - sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; -#endif - sxp->ieee_nan.negative = 1; - sxp->ieee_nan.mantissa0 = 0; - sxp->ieee_nan.mantissa1 = 0; -#ifdef USE_QUAD_DOUBLE - sxp->ieee_nan.mantissa2 = 0; - sxp->ieee_nan.mantissa3 = 0; + sxp.ieee.mantissa2 = 0; + sxp.ieee.mantissa3 = 0; #endif + r = sxp.value; } PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r) { -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - return (sxp->ieee.exponent - FP_EXTENDED_EXP_BIAS); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + return ((int) sxp.ieee.exponent - FP_EXTENDED_EXP_BIAS); #else - fp_declare_init_shape(sxp, r, double); - return (sxp->ieee.exponent - FP_DOUBLE_EXP_BIAS); + fp_declare_init_shape(sxp, double); + sxp.value = r; + return ((int) sxp.ieee.exponent - FP_DOUBLE_EXP_BIAS); #endif } // Normalize to range 1..2 PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r) { -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, r, extended); - sxp->ieee.exponent = FP_EXTENDED_EXP_BIAS; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = r; + sxp.ieee.exponent = FP_EXTENDED_EXP_BIAS; #else - fp_declare_init_shape(sxp, r, double); - sxp->ieee.exponent = FP_DOUBLE_EXP_BIAS; + fp_declare_init_shape(sxp, double); + sxp.value = r; + sxp.ieee.exponent = FP_DOUBLE_EXP_BIAS; #endif + r = sxp.value; } // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb) { -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sap, ra, extended); - fp_declare_init_shape(sbp, rb, extended); +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sap, extended); + fp_declare_init_shape(sbp, extended); #else - fp_declare_init_shape(sap, ra, double); - fp_declare_init_shape(sbp, rb, double); + fp_declare_init_shape(sap, double); + fp_declare_init_shape(sbp, double); #endif - return ((sap->ieee.negative ^ sbp->ieee.negative) ? FPSR_QUOTIENT_SIGN : 0); + sap.value = ra; + sbp.value = rb; + return ((sap.ieee.negative ^ sbp.ieee.negative) ? FPSR_QUOTIENT_SIGN : 0); } /* -------------------------------------------------------------------------- */ /* --- Math functions --- */ /* -------------------------------------------------------------------------- */ -#if FPU_USE_ISO_C99 -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE +#if defined(FPU_USE_ISO_C99) && (defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)) # ifdef HAVE_LOGL # define fp_log logl # endif +# ifdef HAVE_LOG1PL +# define fp_log1p log1pl +# endif +# ifdef HAVE_EXPM1L +# define fp_expm1 expm1l +# endif # ifdef HAVE_LOG10L # define fp_log10 log10l # endif +# ifdef HAVE_LOG2L +# define fp_log2 log2l +# endif # ifdef HAVE_EXPL # define fp_exp expl # endif # ifdef HAVE_POWL # define fp_pow powl # endif +# if defined(HAVE_EXP10L) +# define fp_pow10 exp10l +# elif defined(HAVE_POW10L) +# define fp_pow10 pow10l +# else +# define fp_pow10(x) fp_pow(LD(10.0), x) +# endif +# if defined(HAVE_EXP2L) +# define fp_pow2 exp2l +# elif defined(HAVE_POW2L) +# define fp_pow2 pow2l +# else +# define fp_pow2(x) fp_pow(LD(2.0), x) +# endif # ifdef HAVE_FABSL # define fp_fabs fabsl # endif @@ -732,15 +737,38 @@ PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_regis #ifndef fp_log # define fp_log log #endif +#ifndef fp_log1p +# define fp_log1p log1p +#endif +#ifndef fp_expm1 +# define fp_expm1 expm1 +#endif #ifndef fp_log10 # define fp_log10 log10 #endif +#ifndef fp_log2 +# define fp_log2 log2 +#endif #ifndef fp_exp # define fp_exp exp #endif #ifndef fp_pow # define fp_pow pow #endif +#ifndef fp_pow10 +# ifdef HAVE_POW10 +# define fp_pow10 pow10 +# else +# define fp_pow10 exp10 +# endif +#endif +#ifndef fp_pow2 +# ifdef HAVE_POW2 +# define fp_pow2 pow2 +# else +# define fp_pow2 exp2 +# endif +#endif #ifndef fp_fabs # define fp_fabs fabs #endif @@ -790,48 +818,43 @@ PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_regis # define fp_ceil ceil #endif -#elif defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) +#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) // Assembly optimized support functions. Taken from glibc 2.2.2 #undef fp_log #define fp_log fp_do_log -#if !FPU_FAST_MATH -PRIVATE fpu_extended fp_do_log(fpu_extended x); -#else PRIVATE inline fpu_extended fp_do_log(fpu_extended x) { fpu_extended value; __asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)"); return value; } -#endif #undef fp_log10 #define fp_log10 fp_do_log10 -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_log10(fpu_extended x); -#else PRIVATE inline fpu_extended fp_do_log10(fpu_extended x) { fpu_extended value; __asm__ __volatile__("fldlg2; fxch; fyl2x" : "=t" (value) : "0" (x) : "st(1)"); return value; } -#endif +#if !defined(HAVE_EXPL) #undef fp_exp #define fp_exp fp_do_exp -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_exp(fpu_extended x); -#else PRIVATE inline fpu_extended fp_do_exp(fpu_extended x) { fpu_extended value, exponent; + if (isinf(x)) + { + if(isneg(x)) + return 0.; + else + return x; + } __asm__ __volatile__("fldl2e # e^x = 2^(x * log2(e))\n\t" "fmul %%st(1) # x * log2(e)\n\t" "fst %%st(1)\n\t" @@ -846,10 +869,12 @@ PRIVATE inline fpu_extended fp_do_exp(fpu_extended x) } #endif +#if !defined(HAVE_EXP10L) && !defined(HAVE_POW10L) #undef fp_pow #define fp_pow fp_do_pow PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y); +#endif #undef fp_fabs #define fp_fabs fp_do_fabs @@ -871,6 +896,7 @@ PRIVATE inline fpu_extended fp_do_sqrt(fpu_extended x) return value; } +#ifndef ACCURATE_SIN_COS_TAN #undef fp_sin #define fp_sin fp_do_sin @@ -896,18 +922,27 @@ PRIVATE inline fpu_extended fp_do_cos(fpu_extended x) PRIVATE inline fpu_extended fp_do_tan(fpu_extended x) { - fpu_extended value; - __asm__ __volatile__("fptan" : "=t" (value) : "0" (x)); + fpu_extended value, value2; + __asm__ __volatile__("fptan" : "=t" (value2), "=u" (value) : "0" (x)); return value; } +#endif /* ACCURATE_SIN_COS_TAN */ +#ifndef HAVE_EXPM1L #undef fp_expm1 #define fp_expm1 fp_do_expm1 // Returns: exp(X) - 1.0 PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) { - fpu_extended value, exponent, temp; + fpu_extended value, exponent, temp, temp2; + if (isinf(x)) + { + if(isneg(x)) + return -1.; + else + return x; + } __asm__ __volatile__("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" "fmul %%st(1) # x * log2(e)\n\t" "fst %%st(1)\n\t" @@ -917,51 +952,52 @@ PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x) "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" : "=t" (value), "=u" (exponent) : "0" (x)); - __asm__ __volatile__("fscale" : "=t" (temp) : "0" (1.0), "u" (exponent)); + __asm__ __volatile__("fld1 \n\t" + "fscale \n\t" + : "=t" (temp), "=u" (temp2) : "0" (exponent)); temp -= 1.0; return temp + value ? temp + value : x; } +#endif #undef fp_sgn1 #define fp_sgn1 fp_do_sgn1 PRIVATE inline fpu_extended fp_do_sgn1(fpu_extended x) { -#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE - fp_declare_init_shape(sxp, x, extended); - sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX; - sxp->ieee_nan.one = 1; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fp_declare_init_shape(sxp, extended); + sxp.value = x; + sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX>>1; + sxp.ieee_nan.one = 1; #else - fp_declare_init_shape(sxp, x, double); - sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX; + fp_declare_init_shape(sxp, double); + sxp.value = x; + sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX>>1; #endif - sxp->ieee_nan.quiet_nan = 0; - sxp->ieee_nan.mantissa0 = 0; - sxp->ieee_nan.mantissa1 = 0; + sxp.ieee_nan.quiet_nan = 0; + sxp.ieee_nan.mantissa0 = 0; + sxp.ieee_nan.mantissa1 = 0; + x = sxp.value; return x; } +#ifndef HAVE_SINHL #undef fp_sinh #define fp_sinh fp_do_sinh -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_sinh(fpu_extended x); -#else PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x) { + if (isinf(x)) return x; fpu_extended exm1 = fp_expm1(fp_fabs(x)); return 0.5 * (exm1 / (exm1 + 1.0) + exm1) * fp_sgn1(x); } #endif +#ifndef HAVE_COSHL #undef fp_cosh #define fp_cosh fp_do_cosh -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_cosh(fpu_extended x); -#else PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x) { fpu_extended ex = fp_exp(x); @@ -969,13 +1005,10 @@ PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x) } #endif +#ifndef HAVE_TANHL #undef fp_tanh #define fp_tanh fp_do_tanh -#if !FPU_FAST_MATH -// FIXME: unimplemented -PRIVATE fpu_extended fp_do_tanh(fpu_extended x); -#else PRIVATE inline fpu_extended fp_do_tanh(fpu_extended x) { fpu_extended exm1 = fp_expm1(-fp_fabs(x + x)); @@ -993,6 +1026,7 @@ PRIVATE inline fpu_extended fp_do_atan2(fpu_extended y, fpu_extended x) return value; } +#ifndef HAVE_ASINL #undef fp_asin #define fp_asin fp_do_asin @@ -1000,7 +1034,9 @@ PRIVATE inline fpu_extended fp_do_asin(fpu_extended x) { return fp_atan2(x, fp_sqrt(1.0 - x * x)); } +#endif +#ifndef HAVE_ACOSL #undef fp_acos #define fp_acos fp_do_acos @@ -1008,6 +1044,7 @@ PRIVATE inline fpu_extended fp_do_acos(fpu_extended x) { return fp_atan2(fp_sqrt(1.0 - x * x), x); } +#endif #undef fp_atan #define fp_atan fp_do_atan @@ -1019,12 +1056,15 @@ PRIVATE inline fpu_extended fp_do_atan(fpu_extended x) return value; } +#ifndef HAVE_LOG1PL #undef fp_log1p #define fp_log1p fp_do_log1p // Returns: ln(1.0 + X) PRIVATE fpu_extended fp_do_log1p(fpu_extended x); +#endif +#ifndef HAVE_ASINHL #undef fp_asinh #define fp_asinh fp_do_asinh @@ -1033,7 +1073,9 @@ PRIVATE inline fpu_extended fp_do_asinh(fpu_extended x) fpu_extended y = fp_fabs(x); return (fp_log1p(y * y / (fp_sqrt(y * y + 1.0) + 1.0) + y) * fp_sgn1(x)); } +#endif +#ifndef HAVE_ACOSHL #undef fp_acosh #define fp_acosh fp_do_acosh @@ -1041,7 +1083,9 @@ PRIVATE inline fpu_extended fp_do_acosh(fpu_extended x) { return fp_log(x + fp_sqrt(x - 1.0) * fp_sqrt(x + 1.0)); } +#endif +#ifndef HAVE_ATANHL #undef fp_atanh #define fp_atanh fp_do_atanh @@ -1050,69 +1094,87 @@ PRIVATE inline fpu_extended fp_do_atanh(fpu_extended x) fpu_extended y = fp_fabs(x); return -0.5 * fp_log1p(-(y + y) / (1.0 + y)) * fp_sgn1(x); } +#endif -#undef fp_floor -#define fp_floor fp_do_floor -PRIVATE inline fpu_extended fp_do_floor(fpu_extended x) -{ - volatile unsigned int cw; - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); - volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0400; // rounding down - __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); - fpu_extended value; - __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); - __asm__ __volatile__("fldcw %0" : : "m" (cw)); - return value; +/* + * LLVM 2.9 crashes on first definition, + * clang with LLVM 3.x crashes on 2nd definition... sigh + */ +#if defined(__clang__) || !defined(__llvm__) +#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ +PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended __x) \ +{ \ + register long double __value; \ + register int __ignore; \ + volatile unsigned short __cw; \ + volatile unsigned short __cwtmp; \ + __asm __volatile ("fnstcw %3\n\t" \ + "movzwl %3, %1\n\t" \ + "andl $0xf3ff, %1\n\t" \ + "orl %5, %1\n\t" \ + "movw %w1, %2\n\t" \ + "fldcw %2\n\t" \ + "frndint\n\t" \ + "fldcw %3" \ + : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ + "=m" (__cw) \ + : "0" (__x), "i"(rounding_mode)); \ + return __value; \ } - -#undef fp_ceil -#define fp_ceil fp_do_ceil - -PRIVATE inline fpu_extended fp_do_ceil(fpu_extended x) -{ - volatile unsigned int cw; - __asm__ __volatile__("fnstcw %0" : "=m" (cw)); - volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0800; // rounding up - __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); - fpu_extended value; - __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); - __asm__ __volatile__("fldcw %0" : : "m" (cw)); - return value; -} - +#else #define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \ PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended x) \ { \ - volatile unsigned int cw; \ + volatile unsigned short cw; \ __asm__ __volatile__("fnstcw %0" : "=m" (cw)); \ - volatile unsigned int cw_temp = (cw & 0xf3ff) | (rounding_mode); \ + volatile unsigned short cw_temp = (cw & 0xf3ff) | (rounding_mode); \ __asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); \ fpu_extended value; \ __asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); \ __asm__ __volatile__("fldcw %0" : : "m" (cw)); \ return value; \ } +#endif #undef fp_round_to_minus_infinity +#ifdef HAVE_FLOORL +#define fp_round_to_minus_infinity floorl +#else #define fp_round_to_minus_infinity fp_do_round_to_minus_infinity - -DEFINE_ROUND_FUNC(minus_infinity, 0x400) +DEFINE_ROUND_FUNC(minus_infinity, CW_RC_DOWN) +#endif #undef fp_round_to_plus_infinity +#ifdef HAVE_CEILL +#define fp_round_to_plus_infinity ceill +#else #define fp_round_to_plus_infinity fp_do_round_to_plus_infinity - -DEFINE_ROUND_FUNC(plus_infinity, 0x800) +DEFINE_ROUND_FUNC(plus_infinity, CW_RC_UP) +#endif #undef fp_round_to_zero +#ifdef HAVE_TRUNCL +#define fp_round_to_zero truncl +#else #define fp_round_to_zero fp_do_round_to_zero - -DEFINE_ROUND_FUNC(zero, 0xc00) +DEFINE_ROUND_FUNC(zero, CW_RC_ZERO) +#endif #undef fp_round_to_nearest +#ifdef HAVE_ROUNDL +#define fp_round_to_nearest roundl +#else #define fp_round_to_nearest fp_do_round_to_nearest +DEFINE_ROUND_FUNC(nearest, CW_RC_NEAR) +#endif + +#undef fp_ceil +#define fp_ceil fp_do_round_to_plus_infinity + +#undef fp_floor +#define fp_floor fp_do_round_to_minus_infinity -DEFINE_ROUND_FUNC(nearest, 0x000) #endif /* USE_X87_ASSEMBLY */ diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.cpp b/BasiliskII/src/uae_cpu/fpu/rounding.cpp index 1f8b3618..9942d4e8 100644 --- a/BasiliskII/src/uae_cpu/fpu/rounding.cpp +++ b/BasiliskII/src/uae_cpu/fpu/rounding.cpp @@ -1,28 +1,33 @@ /* - * fpu/rounding.cpp - system-dependant FPU rounding mode and precision + * fpu/rounding.cpp - system-dependant FPU rounding mode and precision * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #undef PRIVATE diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.h b/BasiliskII/src/uae_cpu/fpu/rounding.h index 67db5519..aa2c9ced 100644 --- a/BasiliskII/src/uae_cpu/fpu/rounding.h +++ b/BasiliskII/src/uae_cpu/fpu/rounding.h @@ -1,28 +1,33 @@ /* - * fpu/rounding.h - system-dependant FPU rounding mode and precision + * fpu/rounding.h - system-dependant FPU rounding mode and precision * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_ROUNDING_H @@ -106,8 +111,8 @@ PRIVATE inline void set_host_control_word(void) */ x86_control_word = (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION)) - | x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4] - | x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6] + | x86_control_word_rm_mac2host[(FPU fpcr & FPCR_ROUNDING_MODE) >> 4] + | x86_control_word_rp_mac2host[(FPU fpcr & FPCR_ROUNDING_PRECISION) >> 6] ; __asm__ __volatile__("fldcw %0" : : "m" (x86_control_word)); } @@ -131,11 +136,11 @@ PRIVATE inline void set_host_control_word(void) /* Return the current rounding mode in m68k format */ static inline uae_u32 FFPU get_rounding_mode(void) - { return FPU fpcr.rounding_mode; } + { return FPU fpcr & FPCR_ROUNDING_MODE; } /* Convert and set to native rounding mode */ -static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode) - { FPU fpcr.rounding_mode = new_rounding_mode; } +static inline void FFPU set_rounding_mode(uae_u32 /* new_rounding_mode */ ) + { } #endif @@ -143,11 +148,11 @@ static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode) /* Return the current rounding precision in m68k format */ static inline uae_u32 FFPU get_rounding_precision(void) - { return FPU fpcr.rounding_precision; } + { return FPU fpcr & FPCR_ROUNDING_PRECISION; } /* Convert and set to native rounding precision */ -static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision) - { FPU fpcr.rounding_precision = new_rounding_precision; } +static inline void FFPU set_rounding_precision(uae_u32 /* new_rounding_precision */) + { } #endif diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h index 778567a9..50e07ec2 100644 --- a/BasiliskII/src/uae_cpu/fpu/types.h +++ b/BasiliskII/src/uae_cpu/fpu/types.h @@ -1,28 +1,33 @@ /* - * types.h - basic types for fpu registers + * fpu/types.h - basic types for fpu registers * - * Basilisk II (C) 1997-2008 Christian Bauer + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * MC68881/68040 fpu emulation - * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2000 Lauri Pesonen - * New framework, copyright 2000 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MC68881/68040 fpu emulation * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2001 Lauri Pesonen + * New framework, copyright 2000-2001 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_TYPES_H @@ -106,9 +111,11 @@ typedef uae_f32 fpu_single; #elif defined(FPU_IEEE) -// #if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT -// #error "No IEEE float format, you lose." -// #endif +#if 0 +#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT +#error "No IEEE float format, you lose." +#endif +#endif /* 4-byte floats */ #if SIZEOF_FLOAT == 4 @@ -133,7 +140,7 @@ typedef long double uae_f64; typedef long double uae_f96; typedef uae_f96 fpu_register; #define USE_LONG_DOUBLE 1 -#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__)) +#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64)) /* Long doubles on x86-64 are really held in old x87 FPU stack. */ typedef long double uae_f128; typedef uae_f128 fpu_register; @@ -154,6 +161,23 @@ typedef fpu_register fpu_extended; typedef uae_f64 fpu_double; typedef uae_f32 fpu_single; +#elif defined(FPU_MPFR) + +#include + +struct fpu_register { + mpfr_t f; + uae_u64 nan_bits; + int nan_sign; + operator long double (); + fpu_register &operator=(long double); +}; + #endif +union fpu_register_parts { + fpu_register val; + uae_u32 parts[sizeof(fpu_register) / 4]; +}; + #endif /* FPU_TYPES_H */ diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 5ab3895a..e28c370a 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -1,3 +1,27 @@ +/* + * gencpu.c - m68k emulation generator + * + * Copyright (c) 2009 ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* * UAE - The Un*x Amiga Emulator * @@ -14,42 +38,26 @@ * take care of this. * * Copyright 1995, 1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ +#define CC_FOR_BUILD 1 + +#include "sysdeps.h" +#include "readcpu.h" + #include #include #include #include - -#include "sysdeps.h" -#include "readcpu.h" - -#if defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) -#define SPARC_ASSEMBLY 0 -#endif +#include +#undef abort #define BOOL_TYPE "int" - -/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ -#define xBCD_KEEPS_NV_FLAGS 4 +#define VERIFY_MMU_GENAMODE 0 static FILE *headerfile; static FILE *stblfile; +static FILE *functblfile; static int using_prefetch; static int using_exception_3; @@ -65,6 +73,23 @@ static int *opcode_next_clev; static int *opcode_last_postfix; static unsigned long *counts; +#define GENA_GETV_NO_FETCH 0 +#define GENA_GETV_FETCH 1 +#define GENA_GETV_FETCH_ALIGN 2 +#define GENA_MOVEM_DO_INC 0 +#define GENA_MOVEM_NO_INC 1 +#define GENA_MOVEM_MOVE16 2 + +#define XLATE_LOG 0 +#define XLATE_PHYS 1 +#define XLATE_SFC 2 +#define XLATE_DFC 3 +static char * mem_prefix[4] = { "", "phys_", "sfc_", "dfc_" }; + +/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ +#define xBCD_KEEPS_N_FLAG 4 +#define xBCD_KEEPS_V_FLAG 3 + static void read_counts (void) { FILE *file; @@ -75,7 +100,8 @@ static void read_counts (void) file = fopen ("frequent.68k", "r"); if (file) { - fscanf (file, "Total: %lu\n", &total); + int c = fscanf (file, "Total: %lu\n", &total); + assert(c == 1); while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) { opcode_next_clev[nr] = 4; opcode_last_postfix[nr] = -1; @@ -106,7 +132,6 @@ static int need_endlabel; static int n_braces = 0; static int m68k_pc_offset = 0; -static int insn_n_cycles; static void start_brace (void) { @@ -159,9 +184,8 @@ static const char *gen_nextilong (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 4; - insn_n_cycles += 4; + m68k_pc_offset += 4; if (using_prefetch) sprintf (buffer, "get_ilong_prefetch(%d)", r); @@ -174,9 +198,8 @@ static const char *gen_nextiword (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 2; - insn_n_cycles += 2; + m68k_pc_offset += 2; if (using_prefetch) sprintf (buffer, "get_iword_prefetch(%d)", r); @@ -191,8 +214,6 @@ static const char *gen_nextibyte (void) int r = m68k_pc_offset; m68k_pc_offset += 2; - insn_n_cycles += 2; - if (using_prefetch) sprintf (buffer, "get_ibyte_prefetch(%d)", r); else @@ -214,9 +235,22 @@ static void fill_prefetch_2 (void) static void swap_opcode (void) { - printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - printf ("\topcode = ((opcode << 8) & 0xFF00) | ((opcode >> 8) & 0xFF);\n"); - printf ("#endif\n"); + printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + printf ("\topcode = do_byteswap_16(opcode);\n"); + printf("#endif\n"); +} + +static void real_opcode (int *have) +{ + if (!*have) + { + printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); + printf ("\tuae_u32 real_opcode = do_byteswap_16(opcode);\n"); + printf("#else\n"); + printf ("\tuae_u32 real_opcode = opcode;\n"); + printf("#endif\n"); + *have = 1; + } } static void sync_m68k_pc (void) @@ -238,33 +272,49 @@ static void sync_m68k_pc (void) m68k_pc_offset = 0; } +static void gen_set_fault_pc (void) +{ + sync_m68k_pc(); + printf ("regs.fault_pc = m68k_getpc ();\n"); + m68k_pc_offset = 0; +} + /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, * the calling routine handles Apdi and Aipi modes. * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ -static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) + +/* fixup indicates if we want to fix up adress registers in pre decrement + * or post increment mode now (0) or later (1). A value of 2 will then be + * used to do the actual fix up. This allows to do all memory readings + * before any register is modified, and so to rerun operation without + * side effect in case a bus fault is generated by any memory access. + * XJ - 2006/11/13 */ +static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag, int fixup) { + if (fixup != 2) + { start_brace (); switch (mode) { case Dreg: if (movem) abort (); - if (getv == 1) + if (getv == GENA_GETV_FETCH) switch (size) { case sz_byte: -#if defined(AMIGA) && !defined(WARPUP) + printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); /* sam: I don't know why gcc.2.7.2.1 produces a code worse */ /* if it is not done like that: */ printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg); -#else + printf("#else\n"); printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg); -#endif + printf("#endif\n"); break; case sz_word: -#if defined(AMIGA) && !defined(WARPUP) + printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg); -#else + printf("#else\n"); printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg); -#endif + printf("#endif\n"); break; case sz_long: printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg); @@ -276,7 +326,7 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge case Areg: if (movem) abort (); - if (getv == 1) + if (getv == GENA_GETV_FETCH) switch (size) { case sz_word: printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg); @@ -303,10 +353,16 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg); break; case sz_word: - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2); + if (movem) + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); + else + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 2;\n", name, reg); break; case sz_long: - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4); + if (movem) + printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); + else + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 4;\n", name, reg); break; default: abort (); @@ -351,7 +407,7 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ()); break; case imm: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); switch (size) { case sz_byte: @@ -368,22 +424,22 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge } return; case imm0: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ()); return; case imm1: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ()); return; case imm2: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ()); return; case immi: - if (getv != 1) + if (getv != GENA_GETV_FETCH) abort (); printf ("\tuae_u32 %s = %s;\n", name, reg); return; @@ -394,7 +450,7 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge /* We get here for all non-reg non-immediate addressing modes to * actually fetch the value. */ - if (using_exception_3 && getv != 0 && size != sz_byte) { + if (using_exception_3 && getv != GENA_GETV_NO_FETCH && size != sz_byte) { printf ("\tif ((%sa & 1) != 0) {\n", name); printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name); printf ("\t\tlast_op_for_exception_3 = opcode;\n"); @@ -406,20 +462,29 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge start_brace (); } - if (getv == 1) { + if (getv == GENA_GETV_FETCH) { switch (size) { - case sz_byte: insn_n_cycles += 2; break; - case sz_word: insn_n_cycles += 2; break; - case sz_long: insn_n_cycles += 4; break; + case sz_byte: break; + case sz_word: break; + case sz_long: break; default: abort (); } start_brace (); + printf("\n#ifdef FULLMMU\n"); switch (size) { - case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break; - case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break; - case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break; + case sz_byte: printf ("\tuae_s8 %s = %sget_byte(%sa);\n", name, mem_prefix[xlateflag], name); break; + case sz_word: printf ("\tuae_s16 %s = %sget_word(%sa);\n", name, mem_prefix[xlateflag], name); break; + case sz_long: printf ("\tuae_s32 %s = %sget_long(%sa);\n", name, mem_prefix[xlateflag], name); break; default: abort (); } + printf("#else\n"); + switch (size) { + case sz_byte: printf ("\tuae_s8 %s = phys_get_byte(%sa);\n", name, name); break; + case sz_word: printf ("\tuae_s16 %s = phys_get_word(%sa);\n", name, name); break; + case sz_long: printf ("\tuae_s32 %s = phys_get_long(%sa);\n", name, name); break; + default: abort (); + } + printf("#endif\n"); } /* We now might have to fix up the register for pre-dec or post-inc @@ -427,6 +492,12 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge if (!movem) switch (mode) { case Aipi: + if (fixup == 1) + { + printf ("\tfixup.flag = 1;\n"); + printf ("\tfixup.reg = %s;\n", reg); + printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); + } switch (size) { case sz_byte: printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg); @@ -442,14 +513,39 @@ static void genamode (amodes mode, char *reg, wordsizes size, char *name, int ge } break; case Apdi: + if (fixup == 1) + { + printf ("\tfixup.flag = 1;\n"); + printf ("\tfixup.reg = %s;\n", reg); + printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); + } printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name); break; default: break; } + + } + else /* (fixup != 2) */ + { + if (!movem) + switch (mode) { + case Aipi: + case Apdi: + printf ("\tfixup.flag = 0;\n"); + break; + default: + break; + } + } } -static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to) +static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag) +{ + genamode2 (mode, reg, size, name, getv, movem, xlateflag, 0); +} + +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag) { switch (mode) { case Dreg: @@ -489,28 +585,32 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char case absl: case PC16: case PC8r: - if (using_prefetch) - sync_m68k_pc (); + gen_set_fault_pc (); + printf("#ifdef FULLMMU\n"); switch (size) { case sz_byte: - insn_n_cycles += 2; + printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from); + printf("#else\n"); printf ("\tput_byte(%sa,%s);\n", to, from); break; case sz_word: - insn_n_cycles += 2; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); + printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from); + printf("#else\n"); printf ("\tput_word(%sa,%s);\n", to, from); break; case sz_long: - insn_n_cycles += 4; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); + printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from); + printf("#else\n"); printf ("\tput_long(%sa,%s);\n", to, from); break; default: abort (); } + printf("#endif\n"); break; case imm: case imm0: @@ -526,23 +626,33 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char static void genmovemel (uae_u16 opcode) { - char getcode[100]; + char getcode1[100]; + char getcode2[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; - + if (table68k[opcode].size == sz_long) { - strcpy (getcode, "get_long(srca)"); + strcpy (getcode1, ""); + strcpy (getcode2, "get_long(srca)"); } else { - strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)"); + strcpy (getcode1, "(uae_s32)(uae_s16)"); + strcpy (getcode2, "get_word(srca)"); } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); start_brace (); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", - getcode, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n", - getcode, size); + printf("\n#ifdef FULLMMU\n"); + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s%s; srca += %d; dmask = movem_next[dmask]; }\n", + getcode1, getcode2, size); + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s%s; srca += %d; amask = movem_next[amask]; }\n", + getcode1, getcode2, size); + printf("#else\n"); + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %sphys_%s; srca += %d; dmask = movem_next[dmask]; }\n", + getcode1, getcode2, size); + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %sphys_%s; srca += %d; amask = movem_next[amask]; }\n", + getcode1, getcode2, size); + printf("#endif\n"); if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg(regs, dstreg) = srca;\n"); @@ -552,6 +662,7 @@ static void genmovemle (uae_u16 opcode) { char putcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; + if (table68k[opcode].size == sz_long) { strcpy (putcode, "put_long(srca,"); } else { @@ -559,24 +670,38 @@ static void genmovemle (uae_u16 opcode) } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); - if (using_prefetch) - sync_m68k_pc (); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", + GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); + sync_m68k_pc (); start_brace (); if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); + printf("#ifdef FULLMMU\n"); printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", size, putcode); printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", size, putcode); + printf("#else\n"); + printf ("\twhile (amask) { srca -= %d; phys_%s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", + size, putcode); + printf ("\twhile (dmask) { srca -= %d; phys_%s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", + size, putcode); + printf("#endif\n"); printf ("\tm68k_areg(regs, dstreg) = srca;\n"); } else { printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); + printf("#ifdef FULLMMU\n"); printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", putcode, size); printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", putcode, size); + printf("#else\n"); + printf ("\twhile (dmask) { phys_%s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", + putcode, size); + printf ("\twhile (amask) { phys_%s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", + putcode, size); + printf("#endif\n"); } } @@ -649,12 +774,10 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * break; case flag_add: - start_brace (); printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr); break; case flag_sub: case flag_cmp: - start_brace (); printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr); break; } @@ -673,7 +796,6 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * case flag_cmp: case flag_av: case flag_sv: - start_brace (); printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr); printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr); printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr); @@ -697,10 +819,10 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n"); break; case flag_z: - printf ("\tSET_ZFLG (GET_ZFLG() & (%s == 0));\n", vstr); + printf ("\tSET_ZFLG (GET_ZFLG () & (%s == 0));\n", vstr); break; case flag_zn: - printf ("\tSET_ZFLG (GET_ZFLG() & (%s == 0));\n", vstr); + printf ("\tSET_ZFLG (GET_ZFLG () & (%s == 0));\n", vstr); printf ("\tSET_NFLG (%s < 0);\n", vstr); break; case flag_add: @@ -741,11 +863,13 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have them in the appropriate m68k.h files and use just one copy of this code here. The API can be changed if necessary. */ -#ifdef OPTIMIZED_FLAGS + int done = 0; + + start_brace (); + printf("\n#ifdef OPTIMIZED_FLAGS\n"); switch (type) { case flag_add: case flag_sub: - start_brace (); printf ("\tuae_u32 %s;\n", value); break; default: @@ -755,7 +879,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch /* At least some of those casts are fairly important! */ switch (type) { case flag_logical_noclobber: - printf ("\t{uae_u32 oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n"); + printf ("\t{uae_u32 oldcznv = GET_CZNV() & ~(FLAGVAL_Z | FLAGVAL_N);\n"); if (strcmp (value, "0") == 0) { printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n"); } else { @@ -767,8 +891,9 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch printf ("\tIOR_CZNV (oldcznv);\n"); } printf ("\t}\n"); - return; - + done = 1; + break; + case flag_logical: if (strcmp (value, "0") == 0) { printf ("\tSET_CZNV (FLAGVAL_Z);\n"); @@ -779,7 +904,8 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; } } - return; + done = 1; + break; case flag_add: switch (size) { @@ -787,7 +913,8 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - return; + done = 1; + break; case flag_sub: switch (size) { @@ -795,7 +922,8 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - return; + done = 1; + break; case flag_cmp: switch (size) { @@ -803,13 +931,19 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; } - return; + done = 1; + break; default: break; } -#endif + if (done) + printf("#else\n"); + else + printf("#endif\n"); genflags_normal (type, size, value, src, dst); + if (done) + printf("#endif\n"); } static void force_range_for_rox (const char *var, wordsizes size) @@ -837,7 +971,7 @@ static const char *cmask (wordsizes size) case sz_byte: return "0x80"; case sz_word: return "0x8000"; case sz_long: return "0x80000000"; - default: abort (); + default: abort (); return NULL; } } @@ -849,11 +983,10 @@ static int source_is_imm1_8 (struct instr *i) static void gen_opcode (unsigned long int opcode) { struct instr *curi = table68k + opcode; - insn_n_cycles = 2; start_brace (); #if 0 - printf ("uae_u8 *m68k_pc = regs.pc_p;\n"); + printf ("uae_u8 *m68k_pc = m68k_getpc();\n"); #endif m68k_pc_offset = 2; switch (curi->plev) { @@ -883,16 +1016,16 @@ static void gen_opcode (unsigned long int opcode) case i_OR: case i_AND: case i_EOR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ORSR: case i_EORSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) { printf ("\tsrc &= 0xFF;\n"); } @@ -901,7 +1034,7 @@ static void gen_opcode (unsigned long int opcode) break; case i_ANDSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) { printf ("\tsrc |= 0xFF00;\n"); } @@ -909,81 +1042,89 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SUB: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_sub, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_SUBA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = dst - src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_SUBX: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); - printf ("\tuae_u32 newv = dst - src - (GET_XFLG() ? 1 : 0);\n"); + printf ("\tuae_u32 newv = dst - src - (GET_XFLG () ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_SBCD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); - printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG() ? 1 : 0);\n"); + printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n"); printf ("\tuae_u16 newv, tmp_newv;\n"); printf ("\tint bcd = 0;\n"); printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n"); - printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG() ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); - printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG() ? 1 : 0)) & 0x300) > 0xFF);\n"); + printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG () ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); + printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG () ? 1 : 0)) & 0x300) > 0xFF);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68040 don't change them */ - if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { - if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) - next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; - genflags (flag_z, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ + if (cpu_level >= xBCD_KEEPS_N_FLAG) { + if (next_cpu_level < xBCD_KEEPS_N_FLAG) + next_cpu_level = xBCD_KEEPS_N_FLAG - 1; + genflags (flag_z, curi->size, "newv", "", ""); + } else { + genflags (flag_zn, curi->size, "newv", "", ""); } - else { - genflags (flag_zn, curi->size, "newv", "", ""); - printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + if (cpu_level >= xBCD_KEEPS_V_FLAG) { + if (next_cpu_level < xBCD_KEEPS_V_FLAG) + next_cpu_level = xBCD_KEEPS_V_FLAG - 1; + } else { + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); } - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ADD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_add, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ADDA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = dst + src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_ADDX: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); - printf ("\tuae_u32 newv = dst + src + (GET_XFLG() ? 1 : 0);\n"); + printf ("\tuae_u32 newv = dst + src + (GET_XFLG () ? 1 : 0);\n"); genflags (flag_addx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_ABCD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); start_brace (); - printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG() ? 1 : 0);\n"); + printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG () ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); printf ("\tuae_u16 newv, tmp_newv;\n"); printf ("\tint cflg;\n"); @@ -993,75 +1134,85 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (cflg) newv += 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68040 don't change them */ - if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { - if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) - next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; - genflags (flag_z, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ + if (cpu_level >= xBCD_KEEPS_N_FLAG) { + if (next_cpu_level < xBCD_KEEPS_N_FLAG) + next_cpu_level = xBCD_KEEPS_N_FLAG - 1; + genflags (flag_z, curi->size, "newv", "", ""); + } else { + genflags (flag_zn, curi->size, "newv", "", ""); } - else { - genflags (flag_zn, curi->size, "newv", "", ""); - printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); + if (cpu_level >= xBCD_KEEPS_V_FLAG) { + if (next_cpu_level < xBCD_KEEPS_V_FLAG) + next_cpu_level = xBCD_KEEPS_V_FLAG - 1; + } else { + printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); } - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_NEG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_sub, curi->size, "dst", "src", "0"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_NEGX: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); - printf ("\tuae_u32 newv = 0 - src - (GET_XFLG() ? 1 : 0);\n"); + printf ("\tuae_u32 newv = 0 - src - (GET_XFLG () ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "0"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->smode, "srcreg", curi->size, "src"); + genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_NBCD: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); - printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG() ? 1 : 0);\n"); + printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n"); printf ("\tuae_u16 newv;\n"); - printf ("\tint cflg;\n"); + printf ("\tint cflg, tmp_newv;\n"); + printf ("\ttmp_newv = newv_hi + newv_lo;\n"); printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n"); printf ("\tnewv = newv_hi + newv_lo;\n"); printf ("\tcflg = (newv & 0x1F0) > 0x90;\n"); printf ("\tif (cflg) newv -= 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry(); - /* Manual says bits NV are undefined though a real 68040 don't change them */ - if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { - if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) - next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; - genflags (flag_z, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ + if (cpu_level >= xBCD_KEEPS_N_FLAG) { + if (next_cpu_level < xBCD_KEEPS_N_FLAG) + next_cpu_level = xBCD_KEEPS_N_FLAG - 1; + genflags (flag_z, curi->size, "newv", "", ""); + } else { + genflags (flag_zn, curi->size, "newv", "", ""); } - else { - genflags (flag_zn, curi->size, "newv", "", ""); + if (cpu_level >= xBCD_KEEPS_V_FLAG) { + if (next_cpu_level < xBCD_KEEPS_V_FLAG) + next_cpu_level = xBCD_KEEPS_V_FLAG - 1; + } else { + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); } - genastore ("newv", curi->smode, "srcreg", curi->size, "src"); + genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_CLR: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); genflags (flag_logical, curi->size, "0", "", ""); - genastore ("0", curi->smode, "srcreg", curi->size, "src"); + genastore ("0", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_NOT: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 dst = ~src;\n"); genflags (flag_logical, curi->size, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_TST: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); genflags (flag_logical, curi->size, "src", "", ""); break; case i_BTST: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else @@ -1069,55 +1220,55 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); break; case i_BCHG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tdst ^= (1 << src);\n"); printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_BCLR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst &= ~(1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_BSET: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst |= (1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_CMPM: case i_CMP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_cmp, curi->size, "newv", "src", "dst"); break; case i_CMPA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); genflags (flag_cmp, sz_long, "newv", "src", "dst"); break; /* The next two are coded a little unconventional, but they are doing * weird things... */ case i_MVPRM: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); if (curi->size == sz_word) { @@ -1129,41 +1280,45 @@ static void gen_opcode (unsigned long int opcode) break; case i_MVPMR: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_word) { - printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n"); + printf ("\tuae_u16 val = get_byte(memp) << 8;\n"); + printf ("\t val |= get_byte(memp + 2);\n"); } else { - printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n"); - printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n"); + printf ("\tuae_u32 val = get_byte(memp) << 24;\n"); + printf ("\t val |= get_byte(memp + 2) << 16;\n"); + printf ("\t val |= get_byte(memp + 4) << 8;\n"); + printf ("\t val |= get_byte(memp + 6);\n"); } - genastore ("val", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("val", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_MOVE: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_MOVEA: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_word) { printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n"); } else { printf ("\tuae_u32 val = src;\n"); } - genastore ("val", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("val", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_MVSR2: - genamode (curi->smode, "srcreg", sz_word, "src", 2, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tMakeSR();\n"); if (curi->size == sz_byte) - genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src"); + genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); else - genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src"); + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); break; case i_MV2SR: - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); if (curi->size == sz_byte) printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n"); else { @@ -1172,66 +1327,84 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SWAP: - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n"); genflags (flag_logical, sz_long, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", sz_long, "src"); + genastore ("dst", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); break; case i_EXG: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - genastore ("dst", curi->smode, "srcreg", curi->size, "src"); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_EXT: - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { - case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; - case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; - default: abort (); + case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; + case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; + default: abort (); } genflags (flag_logical, curi->size == sz_word ? sz_word : sz_long, "dst", "", ""); genastore ("dst", curi->smode, "srcreg", - curi->size == sz_word ? sz_word : sz_long, "src"); + curi->size == sz_word ? sz_word : sz_long, "src", XLATE_LOG); break; case i_MVMEL: - genmovemel ((uae_u16)opcode); + genmovemel (opcode); break; case i_MVMLE: - genmovemle ((uae_u16)opcode); + genmovemle (opcode); break; case i_TRAP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - sync_m68k_pc (); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + gen_set_fault_pc (); printf ("\tException(src+32,0);\n"); - m68k_pc_offset = 0; break; case i_MVR2USP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tregs.usp = src;\n"); break; case i_MVUSP2R: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); - genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_RESET: + printf ("\tAtariReset();\n"); break; case i_NOP: break; case i_STOP: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - printf ("\tregs.sr = src;\n"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + /* + * STOP undocumented features: + * if SR is not set: + * 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu) + * 68000 (68010?): Traced STOP also runs 4 cycles faster. + * 68020 68030: STOP works normally + * 68040 68060: Immediate privilege violation exception + */ + printf ("\tuae_u16 sr = src;\n"); + if (cpu_level >= 4) { + printf("\tif (!(sr & 0x2000)) {\n"); + printf ("m68k_incpc(%d);\n", m68k_pc_offset); + printf("\t\tException(8,0); goto %s;\n", endlabelstr); + printf("\t}\n"); + } + printf("\tregs.sr = sr;\n"); printf ("\tMakeFromSR();\n"); printf ("\tm68k_setstopped(1);\n"); + sync_m68k_pc (); + /* STOP does not prefetch anything */ + /* did_prefetch = -1; */ break; case i_RTE: if (cpu_level == 0) { - genamode (Aipi, "7", sz_word, "sr", 1, 0); - genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n"); fill_prefetch_0 (); printf ("\tMakeFromSR();\n"); @@ -1240,15 +1413,14 @@ static void gen_opcode (unsigned long int opcode) if (next_cpu_level < 0) next_cpu_level = 0; printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n"); - genamode (Aipi, "7", sz_word, "sr", 1, 0); - genamode (Aipi, "7", sz_long, "pc", 1, 0); - genamode (Aipi, "7", sz_word, "format", 1, 0); + genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tnewsr = sr; newpc = pc;\n"); printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); - /* gb-- the next two lines are deleted in Bernie's gencpu.c */ - printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); +// printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n"); @@ -1266,8 +1438,8 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_RTD: - genamode (Aipi, "7", sz_long, "pc", 1, 0); - genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tm68k_areg(regs, 7) += offs;\n"); printf ("\tm68k_setpc_rte(pc);\n"); fill_prefetch_0 (); @@ -1275,18 +1447,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_LINK: - genamode (Apdi, "7", sz_long, "old", 2, 0); - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); - genastore ("src", Apdi, "7", sz_long, "old"); - genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src"); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); printf ("\tm68k_areg(regs, 7) += offs;\n"); + genastore ("src", Apdi, "7", sz_long, "old", XLATE_LOG); break; case i_UNLK: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tm68k_areg(regs, 7) = src;\n"); - genamode (Aipi, "7", sz_long, "old", 1, 0); - genastore ("old", curi->smode, "srcreg", curi->size, "src"); + genamode (Aipi, "7", sz_long, "old", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("old", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_RTS: printf ("\tm68k_do_rts();\n"); @@ -1294,14 +1466,16 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_TRAPV: + printf ("\tuaecptr oldpc = m68k_getpc();\n"); sync_m68k_pc (); - printf ("\tif (GET_VFLG()) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr); + printf ("\tif (GET_VFLG ()) { Exception(7,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; break; case i_RTR: printf ("\tMakeSR();\n"); - genamode (Aipi, "7", sz_word, "sr", 1, 0); - genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); + genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n"); printf ("\tregs.sr |= sr; m68k_setpc(pc);\n"); fill_prefetch_0 (); @@ -1309,19 +1483,19 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_JSR: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_JMP: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); printf ("\tm68k_setpc(srca);\n"); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_BSR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); printf ("\tuae_s32 s = (uae_s32)src + 2;\n"); if (using_exception_3) { printf ("\tif (src & 1) {\n"); @@ -1336,18 +1510,6 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_Bcc: - if (0 && !using_prefetch && !using_exception_3 && (cpu_level >= 2)) { - /* gb-- variant probably more favorable to compiler optimizations - also assumes no prefetch buffer is used - Hmm, that would make sense with processors capable of conditional moves */ - if (curi->size == sz_long && next_cpu_level < 1) - next_cpu_level = 1; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - printf ("\tm68k_incpc (cctrue(%d) ? ((uae_s32)src + 2) : %d);\n", curi->cc, m68k_pc_offset); - m68k_pc_offset = 0; - } - else { - /* original code for branch instructions */ if (curi->size == sz_long) { if (cpu_level < 2) { printf ("\tm68k_incpc(2);\n"); @@ -1361,8 +1523,8 @@ static void gen_opcode (unsigned long int opcode) next_cpu_level = 1; } } - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + printf ("\tif (!cctrue(%d)) goto didnt_jump_%lx;\n", curi->cc, opcode); if (using_exception_3) { printf ("\tif (src & 1) {\n"); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); @@ -1374,26 +1536,25 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); fill_prefetch_0 (); printf ("return;\n"); - printf ("didnt_jump:;\n"); + printf ("didnt_jump_%lx:;\n", opcode); need_endlabel = 1; - } break; case i_LEA: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); break; case i_PEA: - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (Apdi, "7", sz_long, "dst", 2, 0); - genastore ("srca", Apdi, "7", sz_long, "dst"); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genastore ("srca", Apdi, "7", sz_long, "dst", XLATE_LOG); break; case i_DBcc: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tif (!cctrue(%d)) {\n", curi->cc); - genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src"); + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); printf ("\t\tif (src) {\n"); if (using_exception_3) { @@ -1412,15 +1573,15 @@ static void gen_opcode (unsigned long int opcode) need_endlabel = 1; break; case i_Scc: - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc); - genastore ("val", curi->smode, "srcreg", curi->size, "src"); + genastore ("val", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_DIVU: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends * on this (actually, it's doing a DIVS). */ @@ -1432,16 +1593,15 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); printf ("\t}\n"); printf ("\t}\n"); - insn_n_cycles += 68; need_endlabel = 1; break; case i_DIVS: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); @@ -1450,34 +1610,31 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); printf ("\t}\n"); printf ("\t}\n"); - insn_n_cycles += 72; need_endlabel = 1; break; case i_MULU: - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); - insn_n_cycles += 32; + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_MULS: - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); - insn_n_cycles += 32; + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); break; case i_CHK: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr); printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; @@ -1485,8 +1642,8 @@ static void gen_opcode (unsigned long int opcode) case i_CHK2: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n"); switch (curi->size) { case sz_byte: @@ -1505,13 +1662,13 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); - printf ("\tif ((extra & 0x800) && GET_CFLG()) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); + printf ("\tif ((extra & 0x800) && GET_CFLG ()) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; case i_ASR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1523,7 +1680,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV();\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); - printf ("\t\tval = %s & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size)); + printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size)); printf ("\t\tSET_CFLG (sign);\n"); duplicate_carry (); if (source_is_imm1_8 (curi)) @@ -1534,17 +1691,17 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tSET_CFLG (val & 1);\n"); duplicate_carry (); printf ("\t\tval >>= 1;\n"); - printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-(uae_s32)sign;\n", + printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n", bit_mask (curi->size), bit_size (curi->size)); printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ASL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1576,11 +1733,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_LSR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1605,11 +1762,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval >>= 1;\n"); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_LSL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1635,11 +1792,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1662,11 +1819,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG (val & 1);\n"); printf ("}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1689,11 +1846,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROXL: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1713,17 +1870,17 @@ static void gen_opcode (unsigned long int opcode) printf ("\t{\n\tuae_u32 carry;\n"); printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1); printf ("\tcarry = loval & 1;\n"); - printf ("\tval = (((val << 1) | GET_XFLG()) << cnt) | (loval >> 1);\n"); + printf ("\tval = (((val << 1) | GET_XFLG ()) << cnt) | (loval >> 1);\n"); printf ("\tSET_XFLG (carry);\n"); printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t} }\n"); - printf ("\tSET_CFLG (GET_XFLG());\n"); + printf ("\tSET_CFLG (GET_XFLG ());\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ROXR: - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1741,7 +1898,7 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tcnt--;\n"); printf ("\t{\n\tuae_u32 carry;\n"); - printf ("\tuae_u32 hival = (val << 1) | GET_XFLG();\n"); + printf ("\tuae_u32 hival = (val << 1) | GET_XFLG ();\n"); printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1); printf ("\tval >>= cnt;\n"); printf ("\tcarry = val & 1;\n"); @@ -1750,12 +1907,12 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_XFLG (carry);\n"); printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t} }\n"); - printf ("\tSET_CFLG (GET_XFLG());\n"); + printf ("\tSET_CFLG (GET_XFLG ());\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); break; case i_ASRW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1769,10 +1926,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ASLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1788,11 +1945,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG (sign != 0);\n"); duplicate_carry (); - printf ("\tSET_VFLG (GET_VFLG() | (sign2 != sign));\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + printf ("\tSET_VFLG (GET_VFLG () | (sign2 != sign));\n"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_LSRW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1805,10 +1962,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_LSLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1821,10 +1978,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ROLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1837,10 +1994,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= 1;\n"); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_RORW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1853,10 +2010,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= %s;\n", cmask (curi->size)); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ROXLW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1866,14 +2023,14 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size)); printf ("\tval <<= 1;\n"); - printf ("\tif (GET_XFLG()) val |= 1;\n"); + printf ("\tif (GET_XFLG ()) val |= 1;\n"); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_ROXRW: - genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1883,107 +2040,133 @@ static void gen_opcode (unsigned long int opcode) } printf ("\tuae_u32 carry = val & 1;\n"); printf ("\tval >>= 1;\n"); - printf ("\tif (GET_XFLG()) val |= %s;\n", cmask (curi->size)); + printf ("\tif (GET_XFLG ()) val |= %s;\n", cmask (curi->size)); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data"); + genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); break; case i_MOVEC2: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tif (!m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_MOVE2C: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tif (!m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_CAS: { int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); printf ("\tint ru = (src >> 6) & 7;\n"); printf ("\tint rc = src & 7;\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst"); - printf ("\tif (GET_ZFLG())"); + sync_m68k_pc (); + printf ("\tif (GET_ZFLG ())"); old_brace_level = n_braces; start_brace (); - genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); pop_braces (old_brace_level); printf ("else"); start_brace (); - printf ("m68k_dreg(regs, rc) = dst;\n"); + switch (curi->size) { + case sz_byte: + printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n"); + break; + case sz_word: + printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n"); + break; + default: + printf ("\tm68k_dreg(regs, rc) = dst;\n"); + break; + } pop_braces (old_brace_level); } break; case i_CAS2: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n"); printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n"); if (curi->size == sz_word) { int old_brace_level = n_braces; + printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); + printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); - printf ("\tif (GET_ZFLG()) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); - printf ("\tif (GET_ZFLG()) {\n"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); + printf ("\tif (GET_ZFLG ()) {\n"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); + printf ("\tif (GET_ZFLG ()) {\n"); printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_word(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); - printf ("\tif (! GET_ZFLG()) {\n"); - printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); - printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); + printf ("\tif (! GET_ZFLG ()) {\n"); + printf ("\tm68k_dreg(regs, rc2) = (m68k_dreg(regs, rc2) & ~0xffff) | (dst2 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, rc1) = (m68k_dreg(regs, rc1) & ~0xffff) | (dst1 & 0xffff);\n"); printf ("\t}\n"); } else { int old_brace_level = n_braces; + printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); + printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); - printf ("\tif (GET_ZFLG()) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); - printf ("\tif (GET_ZFLG()) {\n"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); + printf ("\tif (GET_ZFLG ()) {\n"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); + printf ("\tif (GET_ZFLG ()) {\n"); printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_long(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); - printf ("\tif (! GET_ZFLG()) {\n"); - printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n"); - printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n"); + printf ("\tif (! GET_ZFLG ()) {\n"); + printf ("\tm68k_dreg(regs, rc2) = dst2;\n"); + printf ("\tm68k_dreg(regs, rc1) = dst1;\n"); printf ("\t}\n"); } break; - case i_MOVES: /* ignore DFC and SFC because we have no MMU */ + case i_MOVES: { - int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - printf ("\tif (extra & 0x800)\n"); - old_brace_level = n_braces; - start_brace (); - printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); - pop_braces (old_brace_level); - printf ("else"); - start_brace (); - genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0); - printf ("\tif (extra & 0x8000) {\n"); - switch (curi->size) { - case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; - case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; - default: abort (); - } - printf ("\t} else {\n"); - genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, ""); - printf ("\t}\n"); - pop_braces (old_brace_level); + int old_brace_level; + + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + start_brace(); + printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */ + { + int old_m68k_pc_offset = m68k_pc_offset; + /* use DFC */ + old_brace_level = n_braces; + start_brace (); + printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_DFC); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC); + pop_braces (old_brace_level); + m68k_pc_offset = old_m68k_pc_offset; + } + printf ("else"); /* from ea to reg */ + { + /* use SFC */ + start_brace (); + genamode (curi->dmode, "dstreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_SFC); + printf ("\tif (extra & 0x8000) {\n"); /* address/data */ + switch (curi->size) { + case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; + case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; + default: abort (); + } + printf ("\t} else {\n"); + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG); + printf ("\t}\n"); + sync_m68k_pc(); + pop_braces (old_brace_level); + } } break; case i_BKPT: /* only needed for hardware emulators */ @@ -1999,23 +2182,23 @@ static void gen_opcode (unsigned long int opcode) printf ("\top_illg(opcode);\n"); break; case i_TRAPcc: + printf ("\tuaecptr oldpc = m68k_getpc();\n"); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); - printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr); + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + sync_m68k_pc (); + printf ("\tif (cctrue(%d)) { Exception(7,oldpc); goto %s; }\n", curi->cc, endlabelstr); need_endlabel = 1; break; case i_DIVL: - sync_m68k_pc (); - start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n"); break; case i_MULL: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); printf ("\tm68k_mull(opcode, dst, extra);\n"); break; @@ -2027,34 +2210,37 @@ static void gen_opcode (unsigned long int opcode) case i_BFFFO: case i_BFSET: case i_BFINS: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); start_brace (); + printf ("\tuae_u32 bdata[2];"); printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n"); printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n"); if (curi->dmode == Dreg) { - printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n"); + printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg);\n"); + printf ("\toffset &= 0x1f;\n"); + printf ("\ttmp = (tmp << offset) | (tmp >> (32 - offset));\n"); + printf ("\tbdata[0] = tmp & ((1 << (32 - width)) - 1);\n"); } else { - printf ("\tuae_u32 tmp,bf0,bf1;\n"); - printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n"); - printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n"); - printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n"); + printf ("\tuae_u32 tmp;\n"); + printf ("\tdsta += offset >> 3;\n"); + printf ("\ttmp = get_bitfield(dsta, bdata, offset, width);\n"); } - printf ("\ttmp >>= (32 - width);\n"); - printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width-1)) ? 1 : 0);\n"); + printf ("\tSET_NFLG_ALWAYS (((uae_s32)tmp) < 0 ? 1 : 0);\n"); + if (curi->mnemo == i_BFEXTS) + printf ("\ttmp = (uae_s32)tmp >> (32 - width);\n"); + else + printf ("\ttmp >>= (32 - width);\n"); printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n"); switch (curi->mnemo) { case i_BFTST: break; case i_BFEXTU: + case i_BFEXTS: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCHG: - printf ("\ttmp = ~tmp;\n"); - break; - case i_BFEXTS: - printf ("\tif (GET_NFLG()) tmp |= width == 32 ? 0 : (-1 << width);\n"); - printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); + printf ("\ttmp = tmp ^ (0xffffffffu >> (32 - width));\n"); break; case i_BFCLR: printf ("\ttmp = 0;\n"); @@ -2065,10 +2251,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n"); break; case i_BFSET: - printf ("\ttmp = 0xffffffff;\n"); + printf ("\ttmp = 0xffffffffu >> (32 - width);\n"); break; case i_BFINS: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n"); + printf ("\ttmp = tmp & (0xffffffffu >> (32 - width));\n"); printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width - 1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0);\n"); break; @@ -2078,26 +2265,12 @@ static void gen_opcode (unsigned long int opcode) if (curi->mnemo == i_BFCHG || curi->mnemo == i_BFCLR || curi->mnemo == i_BFSET - || curi->mnemo == i_BFINS) - { - printf ("\ttmp <<= (32 - width);\n"); + || curi->mnemo == i_BFINS) { if (curi->dmode == Dreg) { - printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n"); - printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n"); - printf ("\t\t(tmp >> (offset & 0x1f)) |\n"); - printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n"); - printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n"); + printf ("\ttmp = bdata[0] | (tmp << (32 - width));\n"); + printf ("\tm68k_dreg(regs, dstreg) = (tmp >> offset) | (tmp << (32 - offset));\n"); } else { - printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n"); - printf ("\t\t(tmp >> (offset & 7)) |\n"); - printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n"); - printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n"); - printf ("\tput_long(dsta,bf0 );\n"); - printf ("\tif (((offset & 7) + width) > 32) {\n"); - printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n"); - printf ("\t\t\t(tmp << (8 - (offset & 7)));\n"); - printf ("\t\tput_byte(dsta+4,bf1);\n"); - printf ("\t}\n"); + printf ("\tput_bitfield(dsta, bdata, tmp, offset, width);\n"); } } break; @@ -2107,11 +2280,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); - printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ()); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); + printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg) - 2 * areg_byteinc[srcreg]) << 8)) + %s;\n", gen_nextiword ()); + printf ("\tm68k_areg(regs, srcreg) -= 2;\n"); printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); + gen_set_fault_pc (); printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n"); } break; @@ -2122,57 +2295,57 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ()); - printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); - printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n"); - printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); - printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n"); + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); + printf ("\tm68k_areg(regs, dstreg) -= 2;\n"); + gen_set_fault_pc (); + printf ("\tput_word(m68k_areg(regs, dstreg), val);\n"); } break; case i_TAS: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); genflags (flag_logical, curi->size, "src", "", ""); printf ("\tsrc |= 0x80;\n"); - genastore ("src", curi->smode, "srcreg", curi->size, "src"); + genastore ("src", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); break; case i_FPP: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); printf ("\tfpuop_arithmetic(opcode, extra);\n"); break; case i_FDBcc: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); printf ("\tfpuop_dbcc(opcode, extra);\n"); break; case i_FScc: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_scc(opcode,extra);\n"); + printf ("\tfpuop_scc(opcode, extra);\n"); break; case i_FTRAPcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); + printf ("\tuae_u16 extra = %s;\n", gen_nextiword()); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_trapcc(opcode,oldpc);\n"); + printf ("\tfpuop_trapcc(opcode, oldpc, extra);\n"); break; case i_FBcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr pc = m68k_getpc();\n"); - genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_bcc(opcode,pc,extra);\n"); + printf ("\tfpuop_bcc(opcode, pc, extra);\n"); break; case i_FSAVE: sync_m68k_pc (); @@ -2185,89 +2358,104 @@ static void gen_opcode (unsigned long int opcode) printf ("\tfpuop_restore(opcode);\n"); break; case i_CINVL: - printf("\n#ifdef USE_JIT\n"); + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); printf ("\tif (opcode&0x80)\n" "\t\tflush_icache();\n"); printf("#endif\n"); break; case i_CINVP: - printf("\n#ifdef USE_JIT\n"); + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); printf ("\tif (opcode&0x80)\n" "\t\tflush_icache();\n"); printf("#endif\n"); break; case i_CINVA: - printf("\n#ifdef USE_JIT\n"); + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); printf ("\tif (opcode&0x80)\n" "\t\tflush_icache();\n"); printf("#endif\n"); break; case i_CPUSHL: - printf("\n#ifdef USE_JIT\n"); + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); printf ("\tif (opcode&0x80)\n" "\t\tflush_icache();\n"); printf("#endif\n"); break; case i_CPUSHP: - printf("\n#ifdef USE_JIT\n"); + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); printf ("\tif (opcode&0x80)\n" "\t\tflush_icache();\n"); printf("#endif\n"); break; case i_CPUSHA: - printf("\n#ifdef USE_JIT\n"); + printf ("\tflush_internals();\n"); + printf("#ifdef USE_JIT\n"); printf ("\tif (opcode&0x80)\n" "\t\tflush_icache();\n"); printf("#endif\n"); break; case i_MOVE16: - if ((opcode & 0xfff8) == 0xf620) { - /* MOVE16 (Ax)+,(Ay)+ */ - printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); - printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); - printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); - printf ("\tput_long(memd, get_long(mems));\n"); - printf ("\tput_long(memd+4, get_long(mems+4));\n"); - printf ("\tput_long(memd+8, get_long(mems+8));\n"); - printf ("\tput_long(memd+12, get_long(mems+12));\n"); - printf ("\tif (srcreg != dstreg)\n"); - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } - else { - /* Other variants */ - genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2); - genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2); - printf ("\tmemsa &= ~15;\n"); - printf ("\tmemda &= ~15;\n"); - printf ("\tput_long(memda, get_long(memsa));\n"); - printf ("\tput_long(memda+4, get_long(memsa+4));\n"); - printf ("\tput_long(memda+8, get_long(memsa+8));\n"); - printf ("\tput_long(memda+12, get_long(memsa+12));\n"); - if ((opcode & 0xfff8) == 0xf600) - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - else if ((opcode & 0xfff8) == 0xf608) - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } - break; + if ((opcode & 0xfff8) == 0xf620) { + /* MOVE16 (Ax)+,(Ay)+ */ + printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); + printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); + printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); + printf ("\tput_long(memd, get_long(mems));\n"); + printf ("\tput_long(memd+4, get_long(mems+4));\n"); + printf ("\tput_long(memd+8, get_long(mems+8));\n"); + printf ("\tput_long(memd+12, get_long(mems+12));\n"); + printf ("\tif (srcreg != dstreg)\n"); + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } else { + /* Other variants */ + genamode (curi->smode, "srcreg", curi->size, "mems", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "memd", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); + printf ("\tmemsa &= ~15;\n"); + printf ("\tmemda &= ~15;\n"); + printf ("\tput_long(memda, get_long(memsa));\n"); + printf ("\tput_long(memda+4, get_long(memsa+4));\n"); + printf ("\tput_long(memda+8, get_long(memsa+8));\n"); + printf ("\tput_long(memda+12, get_long(memsa+12));\n"); + if ((opcode & 0xfff8) == 0xf600) + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + else if ((opcode & 0xfff8) == 0xf608) + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } + break; case i_MMUOP: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); sync_m68k_pc (); swap_opcode (); printf ("\tmmu_op(opcode,extra);\n"); break; - - case i_EMULOP_RETURN: + + case i_EMULOP_RETURN: printf ("\tm68k_emulop_return();\n"); m68k_pc_offset = 0; break; - case i_EMULOP: + case i_EMULOP: printf ("\n"); swap_opcode (); printf ("\tm68k_emulop(opcode);\n"); break; - + + case i_NATFEAT_ID: + printf ("\n"); + printf ("\tm68k_natfeat_id();\n"); + break; + + case i_NATFEAT_CALL: + printf ("\n"); + printf ("\tm68k_natfeat_call();\n"); + break; + default: abort (); break; @@ -2279,73 +2467,194 @@ static void gen_opcode (unsigned long int opcode) static void generate_includes (FILE * f) { fprintf (f, "#include \"sysdeps.h\"\n"); - fprintf (f, "#include \"m68k.h\"\n"); fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); + fprintf (f, "#ifdef USE_JIT\n"); fprintf (f, "#include \"compiler/compemu.h\"\n"); + fprintf (f, "#endif\n"); fprintf (f, "#include \"fpu/fpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); + fprintf (f, "#include \"cpu_emulation.h\"\n"); + fprintf (f, "#include \"debug.h\"\n"); + + fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); + fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); + fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); + fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); + fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); - fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); - fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); - fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); - fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); - fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); - - fprintf (f, "#ifdef NOFLAGS\n"); - fprintf (f, "# include \"noflags.h\"\n"); - fprintf (f, "#endif\n"); + fprintf (f, "#ifdef NOFLAGS\n"); + fprintf (f, "# include \"noflags.h\"\n"); + fprintf (f, "#endif\n"); } static int postfix; +struct gencputbl { + char handler[80]; + uae_u16 specific; + uae_u16 opcode; + int namei; +}; +struct gencputbl cpustbl[65536]; +static int n_cpustbl; + +static char *decodeEA (amodes mode, wordsizes size) +{ + static char buffer[80]; + + buffer[0] = 0; + switch (mode){ + case Dreg: + strcpy (buffer,"Dn"); + break; + case Areg: + strcpy (buffer,"An"); + break; + case Aind: + strcpy (buffer,"(An)"); + break; + case Aipi: + strcpy (buffer,"(An)+"); + break; + case Apdi: + strcpy (buffer,"-(An)"); + break; + case Ad16: + strcpy (buffer,"(d16,An)"); + break; + case Ad8r: + strcpy (buffer,"(d8,An,Xn)"); + break; + case PC16: + strcpy (buffer,"(d16,PC)"); + break; + case PC8r: + strcpy (buffer,"(d8,PC,Xn)"); + break; + case absw: + strcpy (buffer,"(xxx).W"); + break; + case absl: + strcpy (buffer,"(xxx).L"); + break; + case imm: + switch (size){ + case sz_byte: + strcpy (buffer,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + break; + + default: + break; + } + return buffer; +} + +static char *outopcode (const char *name, int opcode) +{ + static char out[100]; + struct instr *ins; + + ins = &table68k[opcode]; + strcpy (out, name); + if (ins->smode == immi) + strcat (out, "Q"); + if (ins->size == sz_byte) + strcat (out,".B"); + if (ins->size == sz_word) + strcat (out,".W"); + if (ins->size == sz_long) + strcat (out,".L"); + strcat (out," "); + if (ins->suse) + strcat (out, decodeEA (ins->smode, ins->size)); + if (ins->duse) { + if (ins->suse) strcat (out,","); + strcat (out, decodeEA (ins->dmode, ins->size)); + } + return out; +} + + static void generate_one_opcode (int rp) { + int i; uae_u16 smsk, dmsk; - long int opcode = opcode_map[rp]; - const char *opcode_str; + int opcode = opcode_map[rp]; + int have_realopcode = 0; + const char *name; if (table68k[opcode].mnemo == i_ILLG - || table68k[opcode].clev > (unsigned)cpu_level) + || table68k[opcode].clev > cpu_level) return; + for (i = 0; lookuptab[i].name[0]; i++) { + if (table68k[opcode].mnemo == lookuptab[i].mnemo) + break; + } + if (table68k[opcode].handler != -1) return; - opcode_str = get_instruction_string (opcode); - + name = lookuptab[i].name; if (opcode_next_clev[rp] != cpu_level) { - if (table68k[opcode].flagdead == 0) - /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ - fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], - opcode, opcode_str); - else - fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], - opcode, opcode_str); + sprintf(cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, opcode_last_postfix[rp]); + cpustbl[n_cpustbl].specific = 0; + cpustbl[n_cpustbl].opcode = opcode; + cpustbl[n_cpustbl].namei = i; + fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, name); + n_cpustbl++; return; } - + if (table68k[opcode].flagdead == 0) /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ - fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); + sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC_FF(op_%x_%d)", opcode, postfix); else - fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); + sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, postfix); + cpustbl[n_cpustbl].specific = 0; + cpustbl[n_cpustbl].opcode = opcode; + cpustbl[n_cpustbl].namei = i; + fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, name); + n_cpustbl++; - fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix); - fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix); - + fprintf (headerfile, "extern cpuop_func op_%x_%d_nf;\n", opcode, postfix); + fprintf (headerfile, "extern cpuop_func op_%x_%d_ff;\n", opcode, postfix); + + printf ("/* %s */\n", outopcode (name, opcode)); + printf ("void REGPARAM2 CPUFUNC(op_%x_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, name); + printf ("\tcpuop_begin();\n"); /* gb-- The "nf" variant for an instruction that doesn't set the condition codes at all is the same as the "ff" variant, so we don't need the "nf" variant to be compiled since it is mapped to the "ff" variant in the smalltbl. */ - if (table68k[opcode].flagdead == 0) + if (table68k[opcode].flagdead == 0) printf ("#ifndef NOFLAGS\n"); - printf ("void REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, opcode_str); - printf ("\tcpuop_begin();\n"); - switch (table68k[opcode].stype) { case 0: smsk = 7; break; case 1: smsk = 255; break; @@ -2353,8 +2662,8 @@ static void generate_one_opcode (int rp) case 3: smsk = 7; break; case 4: smsk = 7; break; case 5: smsk = 63; break; - case 6: smsk = 255; break; - case 7: smsk = 3; break; + case 6: smsk = 255; break; + case 7: smsk = 3; break; default: abort (); } dmsk = 7; @@ -2385,38 +2694,17 @@ static void generate_one_opcode (int rp) if (pos < 8 && (smsk >> (8 - pos)) != 0) abort (); #endif - printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - - if (pos < 8 && (smsk >> (8 - pos)) != 0) - sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)", - pos ^ 8, 8 - pos, dmsk); - else if (pos != 8) - sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk); - else - sprintf (source, "(opcode & %d)", smsk); - - if (table68k[opcode].stype == 3) - printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); - else if (table68k[opcode].stype == 1) - printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); - else - printf ("\tuae_u32 srcreg = %s;\n", source); - - printf ("#else\n"); - + real_opcode(&have_realopcode); if (pos) - sprintf (source, "((opcode >> %d) & %d)", pos, smsk); + sprintf (source, "((real_opcode >> %d) & %d)", pos, smsk); else - sprintf (source, "(opcode & %d)", smsk); - + sprintf (source, "(real_opcode & %d)", smsk); if (table68k[opcode].stype == 3) printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); else if (table68k[opcode].stype == 1) printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); else printf ("\tuae_u32 srcreg = %s;\n", source); - - printf ("#endif\n"); } } if (table68k[opcode].duse @@ -2436,27 +2724,13 @@ static void generate_one_opcode (int rp) /* Check that we can do the little endian optimization safely. */ if (pos < 8 && (dmsk >> (8 - pos)) != 0) abort (); -#endif - printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); - - if (pos < 8 && (dmsk >> (8 - pos)) != 0) - printf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", - pos ^ 8, 8 - pos, dmsk); - else if (pos != 8) - printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", - pos ^ 8, dmsk); - else - printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); - - printf ("#else\n"); - +#endif + real_opcode(&have_realopcode); if (pos) - printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", + printf ("\tuae_u32 dstreg = (real_opcode >> %d) & %d;\n", pos, dmsk); else - printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); - - printf ("#endif\n"); + printf ("\tuae_u32 dstreg = real_opcode & %d;\n", dmsk); } } need_endlabel = 0; @@ -2465,10 +2739,10 @@ static void generate_one_opcode (int rp) gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); - printf ("\tcpuop_end();\n"); - printf ("}\n"); - if (table68k[opcode].flagdead == 0) + if (table68k[opcode].flagdead == 0) printf ("\n#endif\n"); + printf ("\tcpuop_end();\n"); + printf ("}\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; } @@ -2479,36 +2753,18 @@ static void generate_func (void) using_prefetch = 0; using_exception_3 = 0; -#if !USE_PREFETCH_BUFFER - /* gb-- No need for a prefetch buffer, nor exception 3 handling */ - /* Anyway, Basilisk2 does not use the op_smalltbl_5 table... */ - for (i = 0; i <= 4; i++) { -#else - for (i = 0; i < 6; i++) { -#endif - cpu_level = 4 - i; - if (i == 5) { - cpu_level = 0; - using_prefetch = 1; - using_exception_3 = 1; - for (rp = 0; rp < nr_cpuop_funcs; rp++) - opcode_next_clev[rp] = 0; - } - postfix = i; - fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); - /* Disable spurious warnings. */ - printf ("\n" - "#ifdef _MSC_VER\n" - "#pragma warning(disable:4102) /* unreferenced label */\n" - "#endif\n"); + for (i = 0; i < 1; i++) { + cpu_level = 4 - i; + postfix = i; + fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); /* sam: this is for people with low memory (eg. me :)) */ printf ("\n" - "#if !defined(PART_1) && !defined(PART_2) && " - "!defined(PART_3) && !defined(PART_4) && " - "!defined(PART_5) && !defined(PART_6) && " - "!defined(PART_7) && !defined(PART_8)" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" "\n" "#define PART_1 1\n" "#define PART_2 1\n" @@ -2519,8 +2775,8 @@ static void generate_func (void) "#define PART_7 1\n" "#define PART_8 1\n" "#endif\n\n"); - rp = 0; + n_cpustbl = 0; for(j=1;j<=8;++j) { int k = (j*nr_cpuop_funcs)/8; printf ("#ifdef PART_%d\n",j); @@ -2528,16 +2784,90 @@ static void generate_func (void) generate_one_opcode (rp); printf ("#endif\n\n"); } - fprintf (stblfile, "{ 0, 0, 0 }};\n"); } } -int main (int argc, char **argv) +static struct { + const char *handler; + const char *name; +} cpufunctbl[65536]; +static char const op_illg_1[] = "op_illg_1"; +static char const illegal[] = "ILLEGAL"; + +static void generate_functbl (void) { - FILE *out; - read_table68k (); - do_merges (); + int i; + unsigned int opcode; + int cpu_level = 4; + struct gencputbl *tbl = cpustbl; + + for (opcode = 0; opcode < 65536; opcode++) + { + cpufunctbl[opcode].handler = op_illg_1; + cpufunctbl[opcode].name = illegal; + } + for (i = 0; i < n_cpustbl; i++) + { + if (! tbl[i].specific) + { + cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; + cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; + } + } + for (opcode = 0; opcode < 65536; opcode++) + { + const char *f; + + if (table68k[opcode].mnemo == i_ILLG || (unsigned)table68k[opcode].clev > (unsigned)cpu_level) + continue; + + if (table68k[opcode].handler != -1) + { + f = cpufunctbl[table68k[opcode].handler].handler; + if (f == op_illg_1) + abort(); + cpufunctbl[opcode].handler = f; + cpufunctbl[opcode].name = cpufunctbl[table68k[opcode].handler].name; + } + } + for (i = 0; i < n_cpustbl; i++) + { + if (tbl[i].specific) + { + cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; + cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; + } + } + + fprintf(functblfile, "\n"); + fprintf(functblfile, "cpuop_func *cpufunctbl[65536] = {\n"); + fprintf(functblfile, "#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU)\n"); + for (opcode = 0; opcode < 65536; opcode++) + { + fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[opcode].handler, opcode < 65535 ? "," : "", cpufunctbl[opcode].name); + } + fprintf(functblfile, "#else\n"); + for (opcode = 0; opcode < 65536; opcode++) + { + unsigned int map = do_byteswap_16(opcode); + fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[map].handler, opcode < 65535 ? "," : "", cpufunctbl[map].name); + } + fprintf(functblfile, "#endif\n"); + fprintf(functblfile, "};\n"); +} + +#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) +void cygwin_mingw_abort() +{ +#undef abort + abort(); +} +#endif + +int main(void) +{ + init_table68k (); opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs); opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs); @@ -2549,32 +2879,28 @@ int main (int argc, char **argv) * cputbl.h that way), but cpuopti can't cope. That could be fixed, but * I don't dare to touch the 68k version. */ - headerfile = fopen ("cputbl.h", "w"); - stblfile = fopen ("cpustbl.cpp", "w"); - out = freopen ("cpuemu.cpp", "w", stdout); + if ((headerfile = fopen ("cputbl.h", "wb")) == NULL) + abort(); + if ((stblfile = fopen ("cpustbl.cpp", "wb")) == NULL) + abort(); + if ((functblfile = fopen ("cpufunctbl.cpp", "wb")) == NULL) + abort(); + if (freopen ("cpuemu.cpp", "wb", stdout) == NULL) + abort(); generate_includes (stdout); + fprintf(stdout, "#ifdef HAVE_CFLAG_NO_REDZONE\n"); + fprintf(stdout, "#ifndef NOFLAGS\n"); + fprintf(stdout, "#pragma GCC option \"-mno-red-zone\"\n"); + fprintf(stdout, "#endif\n"); + fprintf(stdout, "#endif\n"); generate_includes (stblfile); - + generate_includes (functblfile); generate_func (); - + generate_functbl (); free (table68k); - fclose (headerfile); - fclose (stblfile); - fflush (out); - - /* For build systems (IDEs mainly) that don't make it easy to compile the - * same file twice with different settings. */ - stblfile = fopen ("cpustbl_nf.cpp", "w"); - out = freopen ("cpuemu_nf.cpp", "w", stdout); - - fprintf (stblfile, "#define NOFLAGS\n"); - fprintf (stblfile, "#include \"cpustbl.cpp\"\n"); - fclose (stblfile); - - printf ("#define NOFLAGS\n"); - printf ("#include \"cpuemu.cpp\"\n"); - fflush (out); - + fclose(headerfile); + fclose(stblfile); + fclose(functblfile); return 0; } diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index d4d28484..6a434daf 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -1,24 +1,35 @@ -/* - * UAE - The Un*x Amiga Emulator +/* + * m68k.h - machine dependent bits + * + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) * - * MC68000 emulation - machine dependent bits + * Inspired by Christian Bauer's Basilisk II * - * Copyright 1996 Bernd Schmidt + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is free software; you can redistribute it and/or modify + * ARAnyM is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * ARAnyM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with ARAnyM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation - machine dependent bits + * + * Copyright 1996 Bernd Schmidt + * + */ #ifndef M68K_FLAGS_H #define M68K_FLAGS_H diff --git a/BasiliskII/src/uae_cpu/memory-uae.h b/BasiliskII/src/uae_cpu/memory-uae.h new file mode 100644 index 00000000..c93aeb37 --- /dev/null +++ b/BasiliskII/src/uae_cpu/memory-uae.h @@ -0,0 +1,606 @@ +/* + * memory.h - memory management + * + * Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II + * + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ARAnyM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ARAnyM; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + /* + * UAE - The Un*x Amiga Emulator + * + * memory management + * + * Copyright 1995 Bernd Schmidt + */ + +#ifndef UAE_MEMORY_H +#define UAE_MEMORY_H + +#include "sysdeps.h" +#include "string.h" +#include "hardware.h" +#include "parameters.h" +#include "registers.h" +#include "cpummu.h" +#include "readcpu.h" + +# include + +// newcpu.h +extern void Exception (int, uaecptr); +#ifdef EXCEPTIONS_VIA_LONGJMP + extern JMP_BUF excep_env; + #define SAVE_EXCEPTION \ + JMP_BUF excep_env_old; \ + memcpy(excep_env_old, excep_env, sizeof(JMP_BUF)) + #define RESTORE_EXCEPTION \ + memcpy(excep_env, excep_env_old, sizeof(JMP_BUF)) + #define TRY(var) int var = SETJMP(excep_env); if (!var) + #define CATCH(var) else + #define THROW(n) LONGJMP(excep_env, n) + #define THROW_AGAIN(var) LONGJMP(excep_env, var) + #define VOLATILE volatile +#else + struct m68k_exception { + int prb; + m68k_exception (int exc) : prb (exc) {} + operator int() { return prb; } + }; + #define SAVE_EXCEPTION + #define RESTORE_EXCEPTION + #define TRY(var) try + #define CATCH(var) catch(m68k_exception var) + #define THROW(n) throw m68k_exception(n) + #define THROW_AGAIN(var) throw + #define VOLATILE +#endif /* EXCEPTIONS_VIA_LONGJMP */ +extern int in_exception_2; + +#define STRAM_END 0x0e00000UL // should be replaced by global ROMBase as soon as ROMBase will be a constant +#define ROM_END 0x0e80000UL // should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes +#define FastRAM_BEGIN 0x1000000UL // should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant +#ifdef FixedSizeFastRAM +#define FastRAM_SIZE (FixedSizeFastRAM * 1024 * 1024) +#else +#define FastRAM_SIZE FastRAMSize +#endif + +#ifdef FIXED_VIDEORAM +#define ARANYMVRAMSTART 0xf0000000UL +#endif + +#define ARANYMVRAMSIZE 0x00100000 // should be a variable to protect VGA card offscreen memory + +#ifdef FIXED_VIDEORAM +extern uintptr VMEMBaseDiff; +#else +extern uae_u32 VideoRAMBase; +#endif + +#ifdef ARAM_PAGE_CHECK +extern uaecptr pc_page, read_page, write_page; +extern uintptr pc_offset, read_offset, write_offset; +# ifdef PROTECT2K +# define ARAM_PAGE_MASK 0x7ff +# else +# ifdef FULLMMU +# define ARAM_PAGE_MASK 0xfff +# else +# define ARAM_PAGE_MASK 0xfffff +# endif +# endif +#endif + +extern uintptr MEMBaseDiff; +extern uintptr ROMBaseDiff; +extern uintptr FastRAMBaseDiff; +# define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra)) +# define InitROMBaseDiff(va, ra) (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra)) +# define InitFastRAMBaseDiff(va, ra) (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra)) + +#ifdef FIXED_VIDEORAM +#define InitVMEMBaseDiff(va, ra) (VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra)) +#else +#define InitVMEMBaseDiff(va, ra) (ra = (uintptr)(va) + MEMBaseDiff) +#endif + +extern "C" void breakpt(void); + + +static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);} +static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);} + + +#ifndef NOCHECKBOUNDARY +static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write) +{ + if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) { +#ifdef PROTECT2K + // protect first 2kB of RAM - access in supervisor mode only + if (!super && addr < 0x00000800UL) + return false; +#endif + // check for write access to protected areas: + // - first two longwords of ST-RAM are non-writable (ROM shadow) + // - non-writable area between end of ST-RAM and begin of FastRAM + if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size))) + return true; + } +#ifdef FIXED_VIDEORAM + return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size); +#else + return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size); +#endif +} +/* + * "size" is the size of the memory access (byte = 1, word = 2, long = 4) + */ +static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write) +{ + if (test_ram_boundary(addr, size, regs.s, write)) + return; + + // D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr)); + regs.mmu_fault_addr = addr; + regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8)); + breakpt(); + THROW(2); +} + +#else +static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; } +static inline void check_ram_boundary(uaecptr, int, bool) { } +#endif + +#ifdef FIXED_VIDEORAM +# define do_get_real_address(a) ((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff))) +#else +# define do_get_real_address(a) ((uae_u8 *)((uintptr)(a) + MEMBaseDiff)) +#endif + +static inline uae_u8 *phys_get_real_address(uaecptr addr) +{ + return do_get_real_address(addr); +} + +#ifndef NOCHECKBOUNDARY +static inline bool phys_valid_address(uaecptr addr, bool write, int sz) +{ + return test_ram_boundary(addr, sz, regs.s, write); +} +#else +static inline bool phys_valid_address(uaecptr, bool, int) { return true; } +#endif + +static inline uae_u64 phys_get_quad(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_quad((uae_u64*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */ +#endif + check_ram_boundary(addr, 8, false); + uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_quad(m); +} + +static inline uae_u32 phys_get_long(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_long((uae_u32*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); +#endif + check_ram_boundary(addr, 4, false); + uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_long(m); +} + +static inline uae_u32 phys_get_word(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_word((uae_u16*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr); +#endif + check_ram_boundary(addr, 2, false); + uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_word(m); +} + +static inline uae_u32 phys_get_byte(uaecptr addr) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ read_page) <= ARAM_PAGE_MASK)) + return do_get_mem_byte((uae_u8*)(addr + read_offset)); +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr); +#endif + check_ram_boundary(addr, 1, false); + uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + read_page = addr; + read_offset = (uintptr)m - (uintptr)addr; +#endif + return do_get_mem_byte(m); +} + +static inline void phys_put_quad(uaecptr addr, uae_u64 l) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_quad((uae_u64*)(addr + write_offset), l); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_l(addr, l); /* TODO: must be HWput_q */ + return; + } +#endif + check_ram_boundary(addr, 8, true); + uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_quad(m, l); +} + +static inline void phys_put_long(uaecptr addr, uae_u32 l) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_long((uae_u32*)(addr + write_offset), l); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_l(addr, l); + return; + } +#endif + check_ram_boundary(addr, 4, true); + uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_long(m, l); +} + +static inline void phys_put_word(uaecptr addr, uae_u32 w) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_word((uae_u16*)(addr + write_offset), w); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_w(addr, w); + return; + } +#endif + check_ram_boundary(addr, 2, true); + uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_word(m, w); +} + +static inline void phys_put_byte(uaecptr addr, uae_u32 b) +{ +#ifdef ARAM_PAGE_CHECK + if (((addr ^ write_page) <= ARAM_PAGE_MASK)) { + do_put_mem_byte((uae_u8*)(addr + write_offset), b); + return; + } +#endif +#ifndef HW_SIGSEGV + addr = addr < 0xff000000 ? addr : addr & 0x00ffffff; + if ((addr & 0xfff00000) == 0x00f00000) { + HWput_b(addr, b); + return; + } +#endif + check_ram_boundary(addr, 1, true); + uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr); +#ifdef ARAM_PAGE_CHECK + write_page = addr; + write_offset = (uintptr)m - (uintptr)addr; +#endif + do_put_mem_byte(m, b); +} + +#ifdef FULLMMU +static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size) +{ + return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000); +} + +static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) +{ + return do_get_real_address(cl->phys + addr); +} + +static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl)); + return mmu_get_quad_slow(addr, regs.s, data, cl); +} + +static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr) +{ + return mmu_get_quad(addr, 1); +} + +static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); + return mmu_get_long_slow(addr, regs.s, data, size, cl); +} + +static ALWAYS_INLINE uae_u32 get_long(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_long_unaligned(addr, 1); + return mmu_get_long(addr, 1, sz_long); +} + +static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); + return mmu_get_word_slow(addr, regs.s, data, size, cl); +} + +static ALWAYS_INLINE uae_u16 get_word(uaecptr addr) +{ + if (unlikely(is_unaligned(addr, 2))) + return mmu_get_word_unaligned(addr, 1); + return mmu_get_word(addr, 1, sz_word); +} + +static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 0, &cl))) + return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); + return mmu_get_byte_slow(addr, regs.s, data, size, cl); +} + +static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr) +{ + return mmu_get_byte(addr, 1, sz_byte); +} + +static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_quad_slow(addr, val, regs.s, data, cl); +} + +static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val) +{ + mmu_put_quad(addr, val, 1); +} + +static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_long_slow(addr, val, regs.s, data, size, cl); +} + +static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val) +{ + if (unlikely(is_unaligned(addr, 4))) + mmu_put_long_unaligned(addr, val, 1); + else + mmu_put_long(addr, val, 1, sz_long); +} + +static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_word_slow(addr, val, regs.s, data, size, cl); +} + +static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val) +{ + if (unlikely(is_unaligned(addr, 2))) + mmu_put_word_unaligned(addr, val, 1); + else + mmu_put_word(addr, val, 1, sz_word); +} + +static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_lookup(addr, data, 1, &cl))) + do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_byte_slow(addr, val, regs.s, data, size, cl); +} + +static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val) +{ + mmu_put_byte(addr, val, 1, sz_byte); +} + +static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz) +{ + (void)sz; + return phys_get_real_address(mmu_translate(addr, regs.s, 1, write)); +} + +static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) + return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); + return mmu_get_long_slow(addr, super, data, size, cl); +} + +static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) + return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); + return mmu_get_word_slow(addr, super, data, size, cl); +} + +static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 0, &cl))) + return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); + return mmu_get_byte_slow(addr, super, data, size, cl); +} + +static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) + do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_long_slow(addr, val, super, data, size, cl); +} + +static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) + do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_word_slow(addr, val, super, data, size, cl); +} + +static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size) +{ + struct mmu_atc_line *cl; + + if (likely(mmu_user_lookup(addr, super, data, 1, &cl))) + do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); + else + mmu_put_byte_slow(addr, val, super, data, size, cl); +} + +static inline bool valid_address(uaecptr addr, bool write, int sz) +{ + SAVE_EXCEPTION; + TRY(prb) { + (void)sz; + check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write); + RESTORE_EXCEPTION; + return true; + } + CATCH(prb) { + RESTORE_EXCEPTION; + return false; + } +} + +#else + +# define get_quad(a) phys_get_quad(a) +# define get_long(a) phys_get_long(a) +# define get_word(a) phys_get_word(a) +# define get_byte(a) phys_get_byte(a) +# define put_quad(a,b) phys_put_quad(a,b) +# define put_long(a,b) phys_put_long(a,b) +# define put_word(a,b) phys_put_word(a,b) +# define put_byte(a,b) phys_put_byte(a,b) +# define get_real_address(a,w,s) phys_get_real_address(a) + +#define valid_address(a,w,s) phys_valid_address(a,w,s) +#endif + +static inline void flush_internals() { +#ifdef ARAM_PAGE_CHECK + pc_page = 0xeeeeeeee; + read_page = 0xeeeeeeee; + write_page = 0xeeeeeeee; +#endif +} + +#endif /* MEMORY_H */ + +/* +vim:ts=4:sw=4: +*/ diff --git a/BasiliskII/src/uae_cpu/memory.cpp b/BasiliskII/src/uae_cpu/memory.cpp index 7483f506..e56f993d 100644 --- a/BasiliskII/src/uae_cpu/memory.cpp +++ b/BasiliskII/src/uae_cpu/memory.cpp @@ -1,642 +1,59 @@ /* - * UAE - The Un*x Amiga Emulator + * memory.cpp - memory management * - * Memory management + * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * (c) 1995 Bernd Schmidt + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is free software; you can redistribute it and/or modify + * ARAnyM is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * ARAnyM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with ARAnyM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include -#include + /* + * UAE - The Un*x Amiga Emulator + * + * Memory management + * + * (c) 1995 Bernd Schmidt + */ #include "sysdeps.h" -#include "cpu_emulation.h" -#include "main.h" -#include "video.h" - -#include "m68k.h" #include "memory.h" -#include "readcpu.h" -#include "newcpu.h" +#define DEBUG 0 +#include "debug.h" -#if !REAL_ADDRESSING && !DIRECT_ADDRESSING - -static bool illegal_mem = false; - -#ifdef SAVE_MEMORY_BANKS -addrbank *mem_banks[65536]; -#else -addrbank mem_banks[65536]; +#ifdef ARAM_PAGE_CHECK +uaecptr pc_page = 0xeeeeeeee; +uintptr pc_offset = 0; +uaecptr read_page = 0xeeeeeeee; +uintptr read_offset = 0; +uaecptr write_page = 0xeeeeeeee; +uintptr write_offset = 0; #endif -#ifdef WORDS_BIGENDIAN -# define swap_words(X) (X) -#else -# define swap_words(X) (((X) >> 16) | ((X) << 16)) -#endif - -#ifdef NO_INLINE_MEMORY_ACCESS -uae_u32 longget (uaecptr addr) +extern "C" void breakpt(void) { - return call_mem_get_func (get_mem_bank (addr).lget, addr); -} -uae_u32 wordget (uaecptr addr) -{ - return call_mem_get_func (get_mem_bank (addr).wget, addr); -} -uae_u32 byteget (uaecptr addr) -{ - return call_mem_get_func (get_mem_bank (addr).bget, addr); -} -void longput (uaecptr addr, uae_u32 l) -{ - call_mem_put_func (get_mem_bank (addr).lput, addr, l); -} -void wordput (uaecptr addr, uae_u32 w) -{ - call_mem_put_func (get_mem_bank (addr).wput, addr, w); -} -void byteput (uaecptr addr, uae_u32 b) -{ - call_mem_put_func (get_mem_bank (addr).bput, addr, b); -} -#endif - -/* A dummy bank that only contains zeros */ - -static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM; -static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM; -static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM; -static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM; - -uae_u32 REGPARAM2 dummy_lget (uaecptr addr) -{ - if (illegal_mem) - write_log ("Illegal lget at %08x\n", addr); - - return 0; + // bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr); } -uae_u32 REGPARAM2 dummy_wget (uaecptr addr) -{ - if (illegal_mem) - write_log ("Illegal wget at %08x\n", addr); +#if !KNOWN_ALLOC && !NORMAL_ADDRESSING +// This part need rewrite for ARAnyM !! +// It can be taken from hatari. - return 0; -} - -uae_u32 REGPARAM2 dummy_bget (uaecptr addr) -{ - if (illegal_mem) - write_log ("Illegal bget at %08x\n", addr); - - return 0; -} - -void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l) -{ - if (illegal_mem) - write_log ("Illegal lput at %08x\n", addr); -} -void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w) -{ - if (illegal_mem) - write_log ("Illegal wput at %08x\n", addr); -} -void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal bput at %08x\n", addr); -} - -/* Mac RAM (32 bit addressing) */ - -static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM; -static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM; -static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM; - -static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac - -uae_u32 REGPARAM2 ram_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + addr); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 ram_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + addr); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 ram_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr); -} - -void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + addr); - do_put_mem_long(m, l); -} - -void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + addr); - do_put_mem_word(m, w); -} - -void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b) -{ - *(uae_u8 *)(RAMBaseDiff + addr) = b; -} - -uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) -{ - return (uae_u8 *)(RAMBaseDiff + addr); -} - -/* Mac RAM (24 bit addressing) */ - -static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM; -static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM; -static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM; - -uae_u32 REGPARAM2 ram24_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 ram24_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 ram24_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)); -} - -void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); - do_put_mem_long(m, l); -} - -void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); - do_put_mem_word(m, w); -} - -void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b) -{ - *(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b; -} - -uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) -{ - return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)); -} - -/* Mac ROM (32 bit addressing) */ - -static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM; -static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM; -static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM; - -static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac - -uae_u32 REGPARAM2 rom_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(ROMBaseDiff + addr); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 rom_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(ROMBaseDiff + addr); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 rom_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr); -} - -void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal ROM lput at %08x\n", addr); -} - -void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal ROM wput at %08x\n", addr); -} - -void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b) -{ - if (illegal_mem) - write_log ("Illegal ROM bput at %08x\n", addr); -} - -uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) -{ - return (uae_u8 *)(ROMBaseDiff + addr); -} - -/* Mac ROM (24 bit addressing) */ - -static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM; -static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM; - -uae_u32 REGPARAM2 rom24_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff)); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 rom24_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff)); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 rom24_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff)); -} - -uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) -{ - return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff)); -} - -/* Frame buffer */ - -static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM; -static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM; - -static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM; -static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM; - -static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM; -static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM; -static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM; - -static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM; -static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM; - -static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM; - -static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac - -uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - return do_get_mem_long(m); -} - -uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - return do_get_mem_word(m); -} - -uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr) -{ - return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr); -} - -void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - do_put_mem_long(m, l); -} - -void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - do_put_mem_word(m, w); -} - -void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b) -{ - *(uae_u8 *)(FrameBaseDiff + addr) = b; -} - -uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr) -{ - uae_u32 *m, l; - m = (uae_u32 *)(FrameBaseDiff + addr); - l = *m; - return swap_words(l); -} - -uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - return *m; -} - -void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - *m = swap_words(l); -} - -void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - *m = w; -} - -uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr) -{ - uae_u32 *m, l; - m = (uae_u32 *)(FrameBaseDiff + addr); - l = *m; - l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0); - return swap_words(l); -} - -uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr) -{ - uae_u16 *m, w; - m = (uae_u16 *)(FrameBaseDiff + addr); - w = *m; - return (w & 0x1f) | ((w >> 1) & 0x7fe0); -} - -void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(FrameBaseDiff + addr); - l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0); - *m = swap_words(l); -} - -void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w) -{ - uae_u16 *m; - m = (uae_u16 *)(FrameBaseDiff + addr); - *m = (w & 0x1f) | ((w << 1) & 0xffc0); -} - -uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr) -{ - uae_u32 *m, l; - m = (uae_u32 *)(FrameBaseDiff + addr); - return *m; -} - -void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l) -{ - uae_u32 *m; - m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac); - *m = l; -} - -uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) -{ - return (uae_u8 *)(FrameBaseDiff + addr); -} - -/* Mac framebuffer RAM (24 bit addressing) - * - * This works by duplicating appropriate writes to the 32-bit - * address-space framebuffer. - */ - -static void REGPARAM2 fram24_lput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 fram24_wput(uaecptr, uae_u32) REGPARAM; -static void REGPARAM2 fram24_bput(uaecptr, uae_u32) REGPARAM; - -void REGPARAM2 fram24_lput(uaecptr addr, uae_u32 l) -{ - uaecptr page_off = addr & 0xffff; - if (0xa700 <= page_off && page_off < 0xfc80) { - uae_u32 *fm; - fm = (uae_u32 *)(MacFrameBaseHost + page_off - 0xa700); - do_put_mem_long(fm, l); - } - - uae_u32 *m; - m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff)); - do_put_mem_long(m, l); -} - -void REGPARAM2 fram24_wput(uaecptr addr, uae_u32 w) -{ - uaecptr page_off = addr & 0xffff; - if (0xa700 <= page_off && page_off < 0xfc80) { - uae_u16 *fm; - fm = (uae_u16 *)(MacFrameBaseHost + page_off - 0xa700); - do_put_mem_word(fm, w); - } - - uae_u16 *m; - m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff)); - do_put_mem_word(m, w); -} - -void REGPARAM2 fram24_bput(uaecptr addr, uae_u32 b) -{ - uaecptr page_off = addr & 0xffff; - if (0xa700 <= page_off && page_off < 0xfc80) { - *(uae_u8 *)(MacFrameBaseHost + page_off - 0xa700) = b; - } - - *(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b; -} - -/* Default memory access functions */ - -uae_u8 *REGPARAM2 default_xlate (uaecptr a) -{ - write_log("Your Mac program just did something terribly stupid\n"); - return NULL; -} - -/* Address banks */ - -addrbank dummy_bank = { - dummy_lget, dummy_wget, dummy_bget, - dummy_lput, dummy_wput, dummy_bput, - default_xlate -}; - -addrbank ram_bank = { - ram_lget, ram_wget, ram_bget, - ram_lput, ram_wput, ram_bput, - ram_xlate -}; - -addrbank ram24_bank = { - ram24_lget, ram24_wget, ram24_bget, - ram24_lput, ram24_wput, ram24_bput, - ram24_xlate -}; - -addrbank rom_bank = { - rom_lget, rom_wget, rom_bget, - rom_lput, rom_wput, rom_bput, - rom_xlate -}; - -addrbank rom24_bank = { - rom24_lget, rom24_wget, rom24_bget, - rom_lput, rom_wput, rom_bput, - rom24_xlate -}; - -addrbank frame_direct_bank = { - frame_direct_lget, frame_direct_wget, frame_direct_bget, - frame_direct_lput, frame_direct_wput, frame_direct_bput, - frame_xlate -}; - -addrbank frame_host_555_bank = { - frame_host_555_lget, frame_host_555_wget, frame_direct_bget, - frame_host_555_lput, frame_host_555_wput, frame_direct_bput, - frame_xlate -}; - -addrbank frame_host_565_bank = { - frame_host_565_lget, frame_host_565_wget, frame_direct_bget, - frame_host_565_lput, frame_host_565_wput, frame_direct_bput, - frame_xlate -}; - -addrbank frame_host_888_bank = { - frame_host_888_lget, frame_direct_wget, frame_direct_bget, - frame_host_888_lput, frame_direct_wput, frame_direct_bput, - frame_xlate -}; - -addrbank fram24_bank = { - ram24_lget, ram24_wget, ram24_bget, - fram24_lput, fram24_wput, fram24_bput, - ram24_xlate -}; - -void memory_init(void) -{ - for(long i=0; i<65536; i++) - put_mem_bank(i<<16, &dummy_bank); - - // Limit RAM size to not overlap ROM - uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize; - - RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac; - ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac; - FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac; - - // Map RAM, ROM and display - if (TwentyFourBitAddressing) { - map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16); - map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16); - - // Map frame buffer at end of RAM. - map_banks(&fram24_bank, ((RAMBaseMac + ram_size) >> 16) - 1, 1); - } else { - map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16); - map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16); - - // Map frame buffer - switch (MacFrameLayout) { - case FLAYOUT_DIRECT: - map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - case FLAYOUT_HOST_555: - map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - case FLAYOUT_HOST_565: - map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - case FLAYOUT_HOST_888: - map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1); - break; - } - } -} - -void map_banks(addrbank *bank, int start, int size) -{ - int bnr; - unsigned long int hioffs = 0, endhioffs = 0x100; - - if (start >= 0x100) { - for (bnr = start; bnr < start + size; bnr++) - put_mem_bank (bnr << 16, bank); - return; - } - if (TwentyFourBitAddressing) endhioffs = 0x10000; - for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100) - for (bnr = start; bnr < start+size; bnr++) - put_mem_bank((bnr + hioffs) << 16, bank); -} - -#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */ +#error Not prepared for your platform, maybe you need memory banks from hatari +#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */ diff --git a/BasiliskII/src/uae_cpu/memory.h b/BasiliskII/src/uae_cpu/memory.h index 26b3c5f1..f7bab41d 100644 --- a/BasiliskII/src/uae_cpu/memory.h +++ b/BasiliskII/src/uae_cpu/memory.h @@ -23,6 +23,10 @@ #ifndef UAE_MEMORY_H #define UAE_MEMORY_H +#if DIRECT_ADDRESSING +extern uintptr MEMBaseDiff; +#endif + extern void Exception (int, uaecptr); #ifdef EXCEPTIONS_VIA_LONGJMP extern JMP_BUF excep_env; @@ -50,109 +54,8 @@ extern void Exception (int, uaecptr); #define THROW_AGAIN(var) throw #define VOLATILE #endif /* EXCEPTIONS_VIA_LONGJMP */ -extern int in_exception_2; -#if !DIRECT_ADDRESSING && !REAL_ADDRESSING - -/* Enabling this adds one additional native memory reference per 68k memory - * access, but saves one shift (on the x86). Enabling this is probably - * better for the cache. My favourite benchmark (PP2) doesn't show a - * difference, so I leave this enabled. */ - -#if 1 || defined SAVE_MEMORY -#define SAVE_MEMORY_BANKS -#endif - -typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM; -typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM; -typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM; - -#undef DIRECT_MEMFUNCS_SUCCESSFUL - -#ifndef CAN_MAP_MEMORY -#undef USE_COMPILER -#endif - -#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY) -#define USE_MAPPED_MEMORY -#endif - -typedef struct { - /* These ones should be self-explanatory... */ - mem_get_func lget, wget, bget; - mem_put_func lput, wput, bput; - /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can - * be used to address memory without calling the wget/wput functions. - * This doesn't work for all memory banks, so this function may call - * abort(). */ - xlate_func xlateaddr; -} addrbank; - -extern uae_u8 filesysory[65536]; - -extern addrbank ram_bank; // Mac RAM -extern addrbank rom_bank; // Mac ROM -extern addrbank frame_bank; // Frame buffer - -/* Default memory access functions */ - -extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM; - -#define bankindex(addr) (((uaecptr)(addr)) >> 16) - -#ifdef SAVE_MEMORY_BANKS -extern addrbank *mem_banks[65536]; -#define get_mem_bank(addr) (*mem_banks[bankindex(addr)]) -#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b)) -#else -extern addrbank mem_banks[65536]; -#define get_mem_bank(addr) (mem_banks[bankindex(addr)]) -#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b)) -#endif - -extern void memory_init(void); -extern void map_banks(addrbank *bank, int first, int count); - -#ifndef NO_INLINE_MEMORY_ACCESS - -#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr)) -#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr)) -#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr)) -#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l)) -#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w)) -#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b)) - -#else - -extern uae_u32 longget(uaecptr addr); -extern uae_u32 wordget(uaecptr addr); -extern uae_u32 byteget(uaecptr addr); -extern void longput(uaecptr addr, uae_u32 l); -extern void wordput(uaecptr addr, uae_u32 w); -extern void byteput(uaecptr addr, uae_u32 b); - -#endif - -#ifndef MD_HAVE_MEM_1_FUNCS - -#define longget_1 longget -#define wordget_1 wordget -#define byteget_1 byteget -#define longput_1 longput -#define wordput_1 wordput -#define byteput_1 byteput - -#endif - -#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */ - -#if REAL_ADDRESSING -const uintptr MEMBaseDiff = 0; -#elif DIRECT_ADDRESSING -extern uintptr MEMBaseDiff; -#endif - -#if REAL_ADDRESSING || DIRECT_ADDRESSING +#if DIRECT_ADDRESSING static __inline__ uae_u8 *do_get_real_address(uaecptr addr) { return (uae_u8 *)MEMBaseDiff + addr; @@ -166,71 +69,57 @@ static __inline__ uae_u32 get_long(uaecptr addr) uae_u32 * const m = (uae_u32 *)do_get_real_address(addr); return do_get_mem_long(m); } +#define phys_get_long get_long static __inline__ uae_u32 get_word(uaecptr addr) { uae_u16 * const m = (uae_u16 *)do_get_real_address(addr); return do_get_mem_word(m); } +#define phys_get_word get_word static __inline__ uae_u32 get_byte(uaecptr addr) { uae_u8 * const m = (uae_u8 *)do_get_real_address(addr); return do_get_mem_byte(m); } +#define phys_get_byte get_byte static __inline__ void put_long(uaecptr addr, uae_u32 l) { uae_u32 * const m = (uae_u32 *)do_get_real_address(addr); do_put_mem_long(m, l); } +#define phys_put_long put_long static __inline__ void put_word(uaecptr addr, uae_u32 w) { uae_u16 * const m = (uae_u16 *)do_get_real_address(addr); do_put_mem_word(m, w); } +#define phys_put_word put_word static __inline__ void put_byte(uaecptr addr, uae_u32 b) { uae_u8 * const m = (uae_u8 *)do_get_real_address(addr); do_put_mem_byte(m, b); } +#define phys_put_byte put_byte static __inline__ uae_u8 *get_real_address(uaecptr addr) { return do_get_real_address(addr); } +static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz) +{ + return do_get_real_address(addr); +} +static inline uae_u8 *phys_get_real_address(uaecptr addr) +{ + return do_get_real_address(addr); +} static __inline__ uae_u32 get_virtual_address(uae_u8 *addr) { return do_get_virtual_address(addr); } -#else -static __inline__ uae_u32 get_long(uaecptr addr) -{ - return longget_1(addr); -} -static __inline__ uae_u32 get_word(uaecptr addr) -{ - return wordget_1(addr); -} -static __inline__ uae_u32 get_byte(uaecptr addr) -{ - return byteget_1(addr); -} -static __inline__ void put_long(uaecptr addr, uae_u32 l) -{ - longput_1(addr, l); -} -static __inline__ void put_word(uaecptr addr, uae_u32 w) -{ - wordput_1(addr, w); -} -static __inline__ void put_byte(uaecptr addr, uae_u32 b) -{ - byteput_1(addr, b); -} -static __inline__ uae_u8 *get_real_address(uaecptr addr) -{ - return get_mem_bank(addr).xlateaddr(addr); -} -/* gb-- deliberately not implemented since it shall not be used... */ -extern uae_u32 get_virtual_address(uae_u8 *addr); -#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */ +#endif /* DIRECT_ADDRESSING */ + +static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {} +static inline void flush_internals() {} #endif /* MEMORY_H */ diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index dc109422..351a0de3 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -1,51 +1,80 @@ /* - * UAE - The Un*x Amiga Emulator + * newcpu.cpp - CPU emulation * - * MC68000 emulation + * Copyright (c) 2010 ARAnyM dev team (see AUTHORS) + * * - * (c) 1995 Bernd Schmidt + * Inspired by Christian Bauer's Basilisk II * - * This program is free software; you can redistribute it and/or modify + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * + * ARAnyM is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * ARAnyM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with ARAnyM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include -#include -#include + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * (c) 1995 Bernd Schmidt + */ #include "sysdeps.h" +#include #include "cpu_emulation.h" #include "main.h" #include "emul_op.h" - -extern int intlev(void); // From baisilisk_glue.cpp - #include "m68k.h" #include "memory.h" #include "readcpu.h" #include "newcpu.h" -#include "compiler/compemu.h" +#ifdef USE_JIT +# include "compiler/compemu.h" +#endif #include "fpu/fpu.h" - -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) -B2_mutex *spcflags_lock = NULL; +#include "cpummu.h" +#if 0 +#include "natfeats.h" +#include "disasm-glue.h" +#endif +#if USE_JIT +extern bool UseJIT; #endif -bool quit_program = false; +#include + +#define DEBUG 0 +#include "debug.h" + +#define SANITY_CHECK_ATC 1 + +struct fixup fixup = {0, 0, 0}; + +int quit_program = 0; +int exit_val = 0; + +// For instruction $7139 +bool cpu_debugging = false; + struct flag_struct regflags; +/* LongJump buffers */ +#ifdef EXCEPTIONS_VIA_LONGJMP +JMP_BUF excep_env; +#endif /* Opcode of faulting instruction */ uae_u16 last_op_for_exception_3; /* PC at fault time */ @@ -60,19 +89,34 @@ int movem_index1[256]; int movem_index2[256]; int movem_next[256]; -cpuop_func *cpufunctbl[65536]; +#ifdef FLIGHT_RECORDER + +// feel free to edit the following defines to customize the dump +#define FRLOG_HOTKEY 1 /* 1 = dump only when hotkey is held down */ +#define FRLOG_ALL 1 /* 1 = dump continuously to ever growing log */ +#define FRLOG_IRQ 0 /* 1 = dump also CPU in interrupts */ +#define FRLOG_REGS 0 /* 1 = dump also all data/address registers */ +#define FRLOG_SIZE 8192 /* this many instructions in single dump */ -#if FLIGHT_RECORDER struct rec_step { - uae_u32 pc; -#if FLIGHT_RECORDER >= 2 uae_u32 d[8]; uae_u32 a[8]; -#endif + uae_u32 pc; + uae_u16 sr; + uae_u32 usp; + uae_u32 msp; + uae_u32 isp; + uae_u16 instr; }; -const int LOG_SIZE = 32768; -static rec_step log[LOG_SIZE]; +bool cpu_flight_recorder_active = false; + +#if FRLOG_ALL +const int LOG_SIZE = 10; +#else +const int LOG_SIZE = FRLOG_SIZE; +#endif +static rec_step frlog[LOG_SIZE]; static int log_ptr = -1; // First time initialization static const char *log_filename(void) @@ -81,848 +125,568 @@ static const char *log_filename(void) return name ? name : "log.68k"; } -void m68k_record_step(uaecptr pc) -{ -#if FLIGHT_RECORDER >= 2 - /* XXX: if LSB is set, we are recording from generated code and we - don't support registers recording yet. */ - if ((pc & 1) == 0) { - for (int i = 0; i < 8; i++) { - log[log_ptr].d[i] = m68k_dreg(regs, i); - log[log_ptr].a[i] = m68k_areg(regs, i); - } - } -#endif - log[log_ptr].pc = pc; - log_ptr = (log_ptr + 1) % LOG_SIZE; -} - -static void dump_log(void) +void dump_flight_recorder(void) { +#if FRLOG_ALL + FILE *f = fopen(log_filename(), "a"); +#else FILE *f = fopen(log_filename(), "w"); +#endif if (f == NULL) return; for (int i = 0; i < LOG_SIZE; i++) { int j = (i + log_ptr) % LOG_SIZE; - uae_u32 pc = log[j].pc & ~1; - fprintf(f, "pc %08x", pc); -#if FLIGHT_RECORDER >= 2 - fprintf(f, "\n"); - if ((log[j].pc & 1) == 0) { - fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]); - fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]); - fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]); - fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]); - } -#else - fprintf(f, " | "); -#endif -#if ENABLE_MON - disass_68k(f, pc); + fprintf(f, "pc %08x instr %04x sr %04x usp %08x msp %08x isp %08x\n", frlog[j].pc, frlog[j].instr, frlog[j].sr, frlog[j].usp, frlog[j].msp, frlog[j].isp); + // adding a simple opcode -> assembler conversion table would help +#if FRLOG_REGS + fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", frlog[j].d[0], frlog[j].d[1], frlog[j].d[2], frlog[j].d[3]); + fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", frlog[j].d[4], frlog[j].d[5], frlog[j].d[6], frlog[j].d[7]); + fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", frlog[j].a[0], frlog[j].a[1], frlog[j].a[2], frlog[j].a[3]); + fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", frlog[j].a[4], frlog[j].a[5], frlog[j].a[6], frlog[j].a[7]); #endif + m68k_disasm(f, frlog[j].pc, NULL, 1); } fclose(f); } -#endif -#if ENABLE_MON -static void dump_regs(void) +void m68k_record_step(uaecptr pc, int opcode) { - m68k_dumpstate(NULL); -} -#endif + static bool last_state = false; -#define COUNT_INSTRS 0 +#if FRLOG_HOTKEY + if (! cpu_flight_recorder_active) { + if (last_state) { + // dump log out + dump_flight_recorder(); -#if COUNT_INSTRS -static unsigned long int instrcount[65536]; -static uae_u16 opcodenums[65536]; - -static int compfn (const void *el1, const void *el2) -{ - return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2]; -} - -static char *icountfilename (void) -{ - char *name = getenv ("INSNCOUNT"); - if (name) - return name; - return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount"; -} - -void dump_counts (void) -{ - FILE *f = fopen (icountfilename (), "w"); - unsigned long int total; - int i; - - write_log ("Writing instruction count file...\n"); - for (i = 0; i < 65536; i++) { - opcodenums[i] = i; - total += instrcount[i]; + // remember last state + last_state = false; + } + return; } - qsort (opcodenums, 65536, sizeof(uae_u16), compfn); - - fprintf (f, "Total: %lu\n", total); - for (i=0; i < 65536; i++) { - unsigned long int cnt = instrcount[opcodenums[i]]; - struct instr *dp; - struct mnemolookup *lookup; - if (!cnt) - break; - dp = table68k + opcodenums[i]; - for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) - ; - fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name); - } - fclose (f); -} -#else -void dump_counts (void) -{ -} #endif + if (! last_state) { + // reset old log + log_ptr = 0; + memset(frlog, 0, sizeof(frlog)); + // remember last state + last_state = true; + } + +#if FRLOG_REGS + for (int i = 0; i < 8; i++) { + frlog[log_ptr].d[i] = m68k_dreg(regs, i); + frlog[log_ptr].a[i] = m68k_areg(regs, i); + } +#endif + frlog[log_ptr].pc = pc; + + MakeSR(); +#if ! FRLOG_IRQ + // is CPU in interrupt handler? Quit if should not be logged. + if (regs.s && !regs.m) return; +#endif + frlog[log_ptr].sr = regs.sr; + frlog[log_ptr].usp = regs.usp; + frlog[log_ptr].msp = regs.msp; + frlog[log_ptr].isp = regs.isp; + frlog[log_ptr].instr = opcode; + + log_ptr = (log_ptr + 1) % LOG_SIZE; +#if FRLOG_ALL + if (log_ptr == 0) dump_flight_recorder(); +#endif +} +#endif /* FLIGHT_RECORDER */ + int broken_in; -static __inline__ unsigned int cft_map (unsigned int f) +static inline unsigned int cft_map (unsigned int f) { -#ifndef HAVE_GET_WORD_UNSWAPPED - return f; +#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU) + return f; #else - return ((f >> 8) & 255) | ((f & 255) << 8); + return do_byteswap_16(f); #endif } -void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; - void REGPARAM2 op_illg_1 (uae_u32 opcode) { - op_illg (cft_map (opcode)); + op_illg (cft_map (opcode)); } -static void build_cpufunctbl (void) -{ - int i; - unsigned long opcode; - unsigned int cpu_level = 0; // 68000 (default) - if (CPUType == 4) - cpu_level = 4; // 68040 with FPU - else { - if (FPUType) - cpu_level = 3; // 68020 with FPU - else if (CPUType >= 2) - cpu_level = 2; // 68020 - else if (CPUType == 1) - cpu_level = 1; - } - struct cputbl *tbl = ( - cpu_level == 4 ? op_smalltbl_0_ff - : cpu_level == 3 ? op_smalltbl_1_ff - : cpu_level == 2 ? op_smalltbl_2_ff - : cpu_level == 1 ? op_smalltbl_3_ff - : op_smalltbl_4_ff); - - for (opcode = 0; opcode < 65536; opcode++) - cpufunctbl[cft_map (opcode)] = op_illg_1; - for (i = 0; tbl[i].handler != NULL; i++) { - if (! tbl[i].specific) - cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; - } - for (opcode = 0; opcode < 65536; opcode++) { - cpuop_func *f; - - if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) - continue; - - if (table68k[opcode].handler != -1) { - f = cpufunctbl[cft_map (table68k[opcode].handler)]; - if (f == op_illg_1) - abort(); - cpufunctbl[cft_map (opcode)] = f; - } - } - for (i = 0; tbl[i].handler != NULL; i++) { - if (tbl[i].specific) - cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; - } -} void init_m68k (void) { - int i; + int i; - for (i = 0 ; i < 256 ; i++) { - int j; - for (j = 0 ; j < 8 ; j++) { - if (i & (1 << j)) break; - } - movem_index1[i] = j; - movem_index2[i] = 7-j; - movem_next[i] = i & (~(1 << j)); + for (i = 0 ; i < 256 ; i++) { + int j; + for (j = 0 ; j < 8 ; j++) { + if (i & (1 << j)) break; } -#if COUNT_INSTRS - { - FILE *f = fopen (icountfilename (), "r"); - memset (instrcount, 0, sizeof instrcount); - if (f) { - uae_u32 opcode, count, total; - char name[20]; - write_log ("Reading instruction count file...\n"); - fscanf (f, "Total: %lu\n", &total); - while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) { - instrcount[opcode] = count; - } - fclose(f); - } - } -#endif - read_table68k (); - do_merges (); - - build_cpufunctbl (); - -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) - spcflags_lock = B2_create_mutex(); -#endif - fpu_init(CPUType == 4); + movem_index1[i] = j; + movem_index2[i] = 7-j; + movem_next[i] = i & (~(1 << j)); + } + fpu_init (CPUType == 4); } void exit_m68k (void) { fpu_exit (); -#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) - B2_delete_mutex(spcflags_lock); -#endif } -struct regstruct regs, lastint_regs; -static struct regstruct regs_backup[16]; -static int backup_pointer = 0; -static long int m68kpc_offset; -int lastint_no; +struct regstruct regs; +// MJ static struct regstruct regs_backup[16]; +// MJ static int backup_pointer = 0; -#if REAL_ADDRESSING || DIRECT_ADDRESSING -#define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1) -#define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o)) -#define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o)) + +#ifdef FULLMMU +static inline uae_u8 get_ibyte_1(uae_u32 o) +{ + return get_ibyte(o); +} +static inline uae_u16 get_iword_1(uae_u32 o) +{ + return get_iword(o); +} +static inline uae_u32 get_ilong_1(uae_u32 o) +{ + return get_ilong(o); +} #else -#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) -#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) -#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) +# define get_ibyte_1(o) get_byte(m68k_getpc() + (o) + 1) +# define get_iword_1(o) get_word(m68k_getpc() + (o)) +# define get_ilong_1(o) get_long(m68k_getpc() + (o)) #endif -uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf) +/* + * extract bitfield data from memory and return it in the MSBs + * bdata caches the unmodified data for put_bitfield() + */ +uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) { - uae_u16 dp; - uae_s8 disp8; - uae_s16 disp16; - int r; - uae_u32 dispreg; - uaecptr addr; - uae_s32 offset = 0; - char buffer[80]; + uae_u32 tmp, res, mask; - switch (mode){ - case Dreg: - sprintf (buffer,"D%d", reg); + offset &= 7; + mask = 0xffffffffu << (32 - width); + switch ((offset + width + 7) >> 3) { + case 1: + tmp = get_byte(src); + res = tmp << (24 + offset); + bdata[0] = tmp & ~(mask >> (24 + offset)); break; - case Areg: - sprintf (buffer,"A%d", reg); + case 2: + tmp = get_word(src); + res = tmp << (16 + offset); + bdata[0] = tmp & ~(mask >> (16 + offset)); break; - case Aind: - sprintf (buffer,"(A%d)", reg); + case 3: + tmp = get_word(src); + res = tmp << (16 + offset); + bdata[0] = tmp & ~(mask >> (16 + offset)); + tmp = get_byte(src + 2); + res |= tmp << (8 + offset); + bdata[1] = tmp & ~(mask >> (8 + offset)); break; - case Aipi: - sprintf (buffer,"(A%d)+", reg); + case 4: + tmp = get_long(src); + res = tmp << offset; + bdata[0] = tmp & ~(mask >> offset); break; - case Apdi: - sprintf (buffer,"-(A%d)", reg); - break; - case Ad16: - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr = m68k_areg(regs,reg) + (uae_s16)disp16; - sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff, - (unsigned long)addr); - break; - case Ad8r: - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; - - if (dp & 0x100) { - uae_s32 outer = 0, disp = 0; - uae_s32 base = m68k_areg(regs,reg); - char name[10]; - sprintf (name,"A%d, ",reg); - if (dp & 0x80) { base = 0; name[0] = 0; } - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - sprintf (buffer,"(%s%c%d.%c*%d+%d)+%d == $%08lx", name, - dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', - 1 << ((dp >> 9) & 3), - disp,outer, - (unsigned long)addr); - } else { - addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg; - sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, - dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', - 1 << ((dp >> 9) & 3), disp8, - (unsigned long)addr); - } - break; - case PC16: - addr = m68k_getpc () + m68kpc_offset; - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr += (uae_s16)disp16; - sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr); - break; - case PC8r: - addr = m68k_getpc () + m68kpc_offset; - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; - - if (dp & 0x100) { - uae_s32 outer = 0,disp = 0; - uae_s32 base = addr; - char name[10]; - sprintf (name,"PC, "); - if (dp & 0x80) { base = 0; name[0] = 0; } - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - sprintf (buffer,"(%s%c%d.%c*%d+%d)+%d == $%08lx", name, - dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', - 1 << ((dp >> 9) & 3), - disp,outer, - (unsigned long)addr); - } else { - addr += (uae_s32)((uae_s8)disp8) + dispreg; - sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', - (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), - disp8, (unsigned long)addr); - } - break; - case absw: - sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset)); - m68kpc_offset += 2; - break; - case absl: - sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset)); - m68kpc_offset += 4; - break; - case imm: - switch (size){ - case sz_byte: - sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff)); - m68kpc_offset += 2; - break; - case sz_word: - sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff)); - m68kpc_offset += 2; - break; - case sz_long: - sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset))); - m68kpc_offset += 4; - break; - default: - break; - } - break; - case imm0: - offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff)); - break; - case imm1: - offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff)); - break; - case imm2: - offset = (uae_s32)get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - sprintf (buffer,"#$%08lx", (unsigned long)offset); - break; - case immi: - offset = (uae_s32)(uae_s8)(reg & 0xff); - sprintf (buffer,"#$%08lx", (unsigned long)offset); + case 5: + tmp = get_long(src); + res = tmp << offset; + bdata[0] = tmp & ~(mask >> offset); + tmp = get_byte(src + 4); + res |= tmp >> (8 - offset); + bdata[1] = tmp & ~(mask << (8 - offset)); break; default: + /* Panic? */ + res = 0; break; } - if (buf == 0) - printf ("%s", buffer); - else - strcat (buf, buffer); - return offset; + return res; } -/* The plan is that this will take over the job of exception 3 handling - - * the CPU emulation functions will just do a longjmp to m68k_go whenever - * they hit an odd address. */ -static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val) +/* + * write bitfield data (in the LSBs) back to memory, upper bits + * must be cleared already. + */ +void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) { - uae_u16 dp; - uae_s8 disp8; - uae_s16 disp16; - int r; - uae_u32 dispreg; - uaecptr addr; - uae_s32 offset = 0; - - switch (mode){ - case Dreg: - *val = m68k_dreg (regs, reg); - return 1; - case Areg: - *val = m68k_areg (regs, reg); - return 1; - - case Aind: - case Aipi: - addr = m68k_areg (regs, reg); + offset = (offset & 7) + width; + switch ((offset + 7) >> 3) { + case 1: + put_byte(dst, bdata[0] | (val << (8 - offset))); break; - case Apdi: - addr = m68k_areg (regs, reg); + case 2: + put_word(dst, bdata[0] | (val << (16 - offset))); break; - case Ad16: - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr = m68k_areg(regs,reg) + (uae_s16)disp16; + case 3: + put_word(dst, bdata[0] | (val >> (offset - 16))); + put_byte(dst + 2, bdata[1] | (val << (24 - offset))); break; - case Ad8r: - addr = m68k_areg (regs, reg); -d8r_common: - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; - - if (dp & 0x100) { - uae_s32 outer = 0, disp = 0; - uae_s32 base = addr; - if (dp & 0x80) base = 0; - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - } else { - addr += (uae_s32)((uae_s8)disp8) + dispreg; - } + case 4: + put_long(dst, bdata[0] | (val << (32 - offset))); break; - case PC16: - addr = m68k_getpc () + m68kpc_offset; - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr += (uae_s16)disp16; - break; - case PC8r: - addr = m68k_getpc () + m68kpc_offset; - goto d8r_common; - case absw: - addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - break; - case absl: - addr = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - break; - case imm: - switch (size){ - case sz_byte: - *val = get_iword_1 (m68kpc_offset) & 0xff; - m68kpc_offset += 2; - break; - case sz_word: - *val = get_iword_1 (m68kpc_offset) & 0xffff; - m68kpc_offset += 2; - break; - case sz_long: - *val = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - break; - default: - break; - } - return 1; - case imm0: - *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - return 1; - case imm1: - *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - return 1; - case imm2: - *val = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - return 1; - case immi: - *val = (uae_s32)(uae_s8)(reg & 0xff); - return 1; - default: - addr = 0; + case 5: + put_long(dst, bdata[0] | (val >> (offset - 32))); + put_byte(dst + 4, bdata[1] | (val << (40 - offset))); break; } - if ((addr & 1) == 0) - return 1; - - last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset; - last_fault_for_exception_3 = addr; - return 0; } uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp) { - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - regd <<= (dp >> 9) & 3; - if (dp & 0x100) { - uae_s32 outer = 0; - if (dp & 0x80) base = 0; - if (dp & 0x40) regd = 0; + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + regd <<= (dp >> 9) & 3; + if (dp & 0x100) { + uae_s32 outer = 0; + if (dp & 0x80) base = 0; + if (dp & 0x40) regd = 0; - if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword(); - if ((dp & 0x30) == 0x30) base += next_ilong(); + if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword(); + if ((dp & 0x30) == 0x30) base += next_ilong(); - if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword(); - if ((dp & 0x3) == 0x3) outer = next_ilong(); + if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword(); + if ((dp & 0x3) == 0x3) outer = next_ilong(); - if ((dp & 0x4) == 0) base += regd; - if (dp & 0x3) base = get_long (base); - if (dp & 0x4) base += regd; + if ((dp & 0x4) == 0) base += regd; + if (dp & 0x3) base = get_long (base); + if (dp & 0x4) base += regd; - return base + outer; - } else { - return base + (uae_s32)((uae_s8)dp) + regd; - } + return base + outer; + } else { + return base + (uae_s32)((uae_s8)dp) + regd; + } } uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp) { - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; #if 1 - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - return base + (uae_s8)dp + regd; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + return base + (uae_s8)dp + regd; #else - /* Branch-free code... benchmark this again now that - * things are no longer inline. */ - uae_s32 regd16; - uae_u32 mask; - mask = ((dp & 0x800) >> 11) - 1; - regd16 = (uae_s32)(uae_s16)regd; - regd16 &= mask; - mask = ~mask; - base += (uae_s8)dp; - regd &= mask; - regd |= regd16; - return base + regd; + /* Branch-free code... benchmark this again now that + * things are no longer inline. */ + uae_s32 regd16; + uae_u32 mask; + mask = ((dp & 0x800) >> 11) - 1; + regd16 = (uae_s32)(uae_s16)regd; + regd16 &= mask; + mask = ~mask; + base += (uae_s8)dp; + regd &= mask; + regd |= regd16; + return base + regd; #endif } void MakeSR (void) { #if 0 - assert((regs.t1 & 1) == regs.t1); - assert((regs.t0 & 1) == regs.t0); - assert((regs.s & 1) == regs.s); - assert((regs.m & 1) == regs.m); - assert((XFLG & 1) == XFLG); - assert((NFLG & 1) == NFLG); - assert((ZFLG & 1) == ZFLG); - assert((VFLG & 1) == VFLG); - assert((CFLG & 1) == CFLG); + assert((regs.t1 & 1) == regs.t1); + assert((regs.t0 & 1) == regs.t0); + assert((regs.s & 1) == regs.s); + assert((regs.m & 1) == regs.m); + assert((XFLG & 1) == XFLG); + assert((NFLG & 1) == NFLG); + assert((ZFLG & 1) == ZFLG); + assert((VFLG & 1) == VFLG); + assert((CFLG & 1) == CFLG); #endif - regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) - | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) - | (GET_XFLG() << 4) | (GET_NFLG() << 3) | (GET_ZFLG() << 2) | (GET_VFLG() << 1) - | GET_CFLG()); + regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) + | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) + | (GET_XFLG() << 4) | (GET_NFLG() << 3) | (GET_ZFLG() << 2) | (GET_VFLG() << 1) + | GET_CFLG()); } void MakeFromSR (void) { - int oldm = regs.m; - int olds = regs.s; + int oldm = regs.m; + int olds = regs.s; - regs.t1 = (regs.sr >> 15) & 1; - regs.t0 = (regs.sr >> 14) & 1; - regs.s = (regs.sr >> 13) & 1; - regs.m = (regs.sr >> 12) & 1; - regs.intmask = (regs.sr >> 8) & 7; - SET_XFLG ((regs.sr >> 4) & 1); - SET_NFLG ((regs.sr >> 3) & 1); - SET_ZFLG ((regs.sr >> 2) & 1); - SET_VFLG ((regs.sr >> 1) & 1); - SET_CFLG (regs.sr & 1); - if (CPUType >= 2) { - if (olds != regs.s) { - if (olds) { - if (oldm) - regs.msp = m68k_areg(regs, 7); - else - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.usp; - } else { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - } - } else if (olds && oldm != regs.m) { - if (oldm) { - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - } else { - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.msp; - } - } - } else { - if (olds != regs.s) { - if (olds) { - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.usp; - } else { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - } - } + regs.t1 = (regs.sr >> 15) & 1; + regs.t0 = (regs.sr >> 14) & 1; + regs.s = (regs.sr >> 13) & 1; + mmu_set_super(regs.s); + regs.m = (regs.sr >> 12) & 1; + regs.intmask = (regs.sr >> 8) & 7; + SET_XFLG ((regs.sr >> 4) & 1); + SET_NFLG ((regs.sr >> 3) & 1); + SET_ZFLG ((regs.sr >> 2) & 1); + SET_VFLG ((regs.sr >> 1) & 1); + SET_CFLG (regs.sr & 1); + if (olds != regs.s) { + if (olds) { + if (oldm) + regs.msp = m68k_areg(regs, 7); + else + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; + } + } else if (olds && oldm != regs.m) { + if (oldm) { + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + } else { + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.msp; + } } - SPCFLAGS_SET( SPCFLAG_INT ); - if (regs.t1 || regs.t0) - SPCFLAGS_SET( SPCFLAG_TRACE ); - else - /* Keep SPCFLAG_DOTRACE, we still want a trace exception for - SR-modifying instructions (including STOP). */ - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + // SPCFLAGS_SET( SPCFLAG_INT ); + SPCFLAGS_SET( SPCFLAG_INT ); + if (regs.t1 || regs.t0) + SPCFLAGS_SET( SPCFLAG_TRACE ); + else + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); } +/* for building exception frames */ +static inline void exc_push_word(uae_u16 w) +{ + m68k_areg(regs, 7) -= 2; + put_word(m68k_areg(regs, 7), w); +} +static inline void exc_push_long(uae_u32 l) +{ + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), l); +} + +static inline void exc_make_frame( + int format, + uae_u16 sr, + uae_u32 currpc, + int nr, + uae_u32 x0, + uae_u32 x1 +) +{ + switch(format) { + case 4: + exc_push_long(x1); + exc_push_long(x0); + break; + case 3: + case 2: + exc_push_long(x0); + break; + } + + exc_push_word((format << 12) + (nr * 4)); /* format | vector */ + exc_push_long(currpc); + exc_push_word(sr); +} + +#ifdef EXCEPTIONS_VIA_LONGJMP +static int building_bus_fault_stack_frame=0; +#endif + void Exception(int nr, uaecptr oldpc) { - uae_u32 currpc = m68k_getpc (); - MakeSR(); - if (!regs.s) { - regs.usp = m68k_areg(regs, 7); - if (CPUType >= 2) - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - else - m68k_areg(regs, 7) = regs.isp; - regs.s = 1; + uae_u32 currpc = m68k_getpc (); + MakeSR(); + + if (fixup.flag) + { + m68k_areg(regs, fixup.reg) = fixup.value; + fixup.flag = 0; + } + + if (!regs.s) { + regs.usp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; + regs.s = 1; + mmu_set_super(1); + } + + if (nr == 2) { + /* BUS ERROR handler begins */ +#ifdef ENABLE_EPSLIMITER + check_eps_limit(currpc); +#endif + // panicbug("Exception Nr. %d CPC: %08x NPC: %08x SP=%08x Addr: %08x", nr, currpc, get_long (regs.vbr + 4*nr), m68k_areg(regs, 7), regs.mmu_fault_addr); +#ifdef EXCEPTIONS_VIA_LONGJMP + if (!building_bus_fault_stack_frame) +#else + try +#endif + { +#ifdef EXCEPTIONS_VIA_LONGJMP + building_bus_fault_stack_frame= 1; +#endif + /* 68040 */ + exc_push_long(0); /* PD3 */ + exc_push_long(0); /* PD2 */ + exc_push_long(0); /* PD1 */ + exc_push_long(0); /* PD0/WB1D */ + exc_push_long(0); /* WB1A */ + exc_push_long(0); /* WB2D */ + exc_push_long(0); /* WB2A */ + exc_push_long(regs.wb3_data); /* WB3D */ + exc_push_long(regs.mmu_fault_addr); /* WB3A */ + exc_push_long(regs.mmu_fault_addr); + exc_push_word(0); /* WB1S */ + exc_push_word(0); /* WB2S */ + exc_push_word(regs.wb3_status); /* WB3S */ + regs.wb3_status = 0; + exc_push_word(regs.mmu_ssw); + exc_push_long(regs.mmu_fault_addr); /* EA */ + exc_make_frame(7, regs.sr, regs.fault_pc, 2, 0, 0); + } - if (CPUType > 0) { - if (nr == 2 || nr == 3) { - int i; - /* @@@ this is probably wrong (?) */ - for (i = 0 ; i < 12 ; i++) { - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0); - } - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0xa000 + nr * 4); - } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), oldpc); - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0x2000 + nr * 4); - } else if (regs.m && nr >= 24 && nr < 32) { - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), nr * 4); - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), currpc); - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), regs.sr); - regs.sr |= (1 << 13); - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), 0x1000 + nr * 4); - } else { - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), nr * 4); - } - } else { - if (nr == 2 || nr == 3) { - m68k_areg(regs, 7) -= 12; - /* ??????? */ - if (nr == 3) { - put_long (m68k_areg(regs, 7), last_fault_for_exception_3); - put_word (m68k_areg(regs, 7)+4, last_op_for_exception_3); - put_long (m68k_areg(regs, 7)+8, last_addr_for_exception_3); - } - write_log ("Exception!\n"); - goto kludge_me_do; - } - } - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), currpc); -kludge_me_do: - m68k_areg(regs, 7) -= 2; - put_word (m68k_areg(regs, 7), regs.sr); - m68k_setpc (get_long (regs.vbr + 4*nr)); - SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); - fill_prefetch_0 (); - regs.t1 = regs.t0 = regs.m = 0; - SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE ); +#ifdef EXCEPTIONS_VIA_LONGJMP + else +#else + catch (m68k_exception) +#endif + { + report_double_bus_error(); +#ifdef EXCEPTIONS_VIA_LONGJMP + building_bus_fault_stack_frame= 0; +#endif + return; + } + +#ifdef EXCEPTIONS_VIA_LONGJMP + building_bus_fault_stack_frame= 0; +#endif + /* end of BUS ERROR handler */ + } else if (nr == 3) { + exc_make_frame(2, regs.sr, last_addr_for_exception_3, nr, + last_fault_for_exception_3 & 0xfffffffe, 0); + } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { + /* div by zero, CHK, TRAP or TRACE */ + exc_make_frame(2, regs.sr, currpc, nr, oldpc, 0); + } else if (regs.m && nr >= 24 && nr < 32) { + /* interrupts! */ + exc_make_frame(0, regs.sr, currpc, nr, 0, 0); + regs.sr |= (1 << 13); + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + + exc_make_frame(1, /* throwaway */ + regs.sr, currpc, nr, 0, 0); + } else { + exc_make_frame(0, regs.sr, currpc, nr, 0, 0); + } + m68k_setpc (get_long (regs.vbr + 4*nr)); + SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); + fill_prefetch_0 (); + regs.t1 = regs.t0 = regs.m = 0; + SPCFLAGS_CLEAR(SPCFLAG_TRACE | SPCFLAG_DOTRACE); } static void Interrupt(int nr) { - assert(nr < 8 && nr >= 0); - lastint_regs = regs; - lastint_no = nr; - Exception(nr+24, 0); + assert(nr < 8 && nr >= 0); + Exception(nr+24, 0); - regs.intmask = nr; - SPCFLAGS_SET( SPCFLAG_INT ); + regs.intmask = nr; + // why the hell the SPCFLAG_INT is to be set??? (joy) + // regs.spcflags |= SPCFLAG_INT; (disabled by joy) + SPCFLAGS_SET( SPCFLAG_INT ); } -static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp; - -static int movec_illg (int regno) +static void SCCInterrupt(int nr) { - switch (CPUType) { - case 1: - if ((regno & 0x7ff) <= 1) - return 0; - break; - case 2: - case 3: - if ((regno & 0x7ff) <= 2) - return 0; - if (regno == 3 || regno == 4) - return 0; - break; - case 4: - if ((regno & 0x7ff) <= 7) { - if (regno != 0x802) - return 0; - } - break; - } - return 1; + // fprintf(stderr, "CPU: in SCCInterrupt\n"); + Exception(nr, 0); + + regs.intmask = 5;// ex 5 +} + +static void MFPInterrupt(int nr) +{ + // fprintf(stderr, "CPU: in MFPInterrupt\n"); + Exception(nr, 0); + + regs.intmask = 6; } int m68k_move2c (int regno, uae_u32 *regp) { - if (movec_illg (regno)) { - op_illg (0x4E7B); - return 0; - } else { - switch (regno) { - case 0: regs.sfc = *regp & 7; break; - case 1: regs.dfc = *regp & 7; break; - case 2: - regs.cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); -#if USE_JIT - set_cache_state(regs.cacr & 0x8000); - if (*regp & 0x08) { /* Just to be on the safe side */ - flush_icache(); - } + switch (regno) { + case 0: regs.sfc = *regp & 7; break; + case 1: regs.dfc = *regp & 7; break; + case 2: regs.cacr = *regp & 0x80008000; +#ifdef USE_JIT + set_cache_state(regs.cacr & 0x8000); + if (*regp & 0x08) { /* Just to be on the safe side */ + flush_icache(); + } #endif - break; - case 3: tc = *regp & 0xc000; break; - case 4: itt0 = *regp & 0xffffe364; break; - case 5: itt1 = *regp & 0xffffe364; break; - case 6: dtt0 = *regp & 0xffffe364; break; - case 7: dtt1 = *regp & 0xffffe364; break; - case 0x800: regs.usp = *regp; break; - case 0x801: regs.vbr = *regp; break; - case 0x802: caar = *regp &0xfc; break; - case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; - case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; - case 0x805: mmusr = *regp; break; - case 0x806: urp = *regp; break; - case 0x807: srp = *regp; break; - default: - op_illg (0x4E7B); - return 0; - } + break; + case 3: mmu_set_tc(*regp & 0xc000); break; + case 4: + case 5: + case 6: + case 7: mmu_set_ttr(regno, *regp & 0xffffe364); break; + case 0x800: regs.usp = *regp; break; + case 0x801: regs.vbr = *regp; break; + case 0x802: regs.caar = *regp & 0xfc; break; + case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; + case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; + case 0x805: mmu_set_mmusr(*regp); break; + case 0x806: regs.urp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; + case 0x807: regs.srp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; + default: + op_illg (0x4E7B); + return 0; } - return 1; + return 1; } int m68k_movec2 (int regno, uae_u32 *regp) { - if (movec_illg (regno)) - { - op_illg (0x4E7A); - return 0; - } else { - switch (regno) { - case 0: *regp = regs.sfc; break; - case 1: *regp = regs.dfc; break; - case 2: *regp = cacr; break; - case 3: *regp = tc; break; - case 4: *regp = itt0; break; - case 5: *regp = itt1; break; - case 6: *regp = dtt0; break; - case 7: *regp = dtt1; break; - case 0x800: *regp = regs.usp; break; - case 0x801: *regp = regs.vbr; break; - case 0x802: *regp = caar; break; - case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; - case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; - case 0x805: *regp = mmusr; break; - case 0x806: *regp = urp; break; - case 0x807: *regp = srp; break; - default: - op_illg (0x4E7A); - return 0; - } + switch (regno) { + case 0: *regp = regs.sfc; break; + case 1: *regp = regs.dfc; break; + case 2: *regp = regs.cacr; break; + case 3: *regp = regs.tc; break; + case 4: *regp = regs.itt0; break; + case 5: *regp = regs.itt1; break; + case 6: *regp = regs.dtt0; break; + case 7: *regp = regs.dtt1; break; + case 0x800: *regp = regs.usp; break; + case 0x801: *regp = regs.vbr; break; + case 0x802: *regp = regs.caar; break; + case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; + case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; + case 0x805: *regp = regs.mmusr; break; + case 0x806: *regp = regs.urp; break; + case 0x807: *regp = regs.srp; break; + default: + op_illg (0x4E7A); + return 0; } - return 1; + return 1; } -static __inline__ int +#if !defined(uae_s64) +static inline int div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem) { uae_u32 q = 0, cbit = 0; int i; if (div <= src_hi) { - return 1; + return 1; } for (i = 0 ; i < 32 ; i++) { cbit = src_hi & 0x80000000ul; @@ -939,129 +703,131 @@ div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem = src_hi; return 0; } +#endif -void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) +void m68k_divl (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra, uaecptr oldpc) { #if defined(uae_s64) - if (src == 0) { - Exception (5, oldpc); - return; - } - if (extra & 0x800) { - /* signed variant */ - uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - uae_s64 quot, rem; + if (src == 0) { + Exception (5, oldpc); + return; + } + if (extra & 0x800) { + /* signed variant */ + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + uae_s64 quot, rem; - if (extra & 0x400) { - a &= 0xffffffffu; - a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32; - } - rem = a % (uae_s64)(uae_s32)src; - quot = a / (uae_s64)(uae_s32)src; - if ((quot & UVAL64(0xffffffff80000000)) != 0 - && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) - { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = (uae_u32)rem; - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; - } + if (extra & 0x400) { + a &= 0xffffffffu; + a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32; + } + rem = a % (uae_s64)(uae_s32)src; + quot = a / (uae_s64)(uae_s32)src; + if ((quot & UVAL64(0xffffffff80000000)) != 0 + && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) + { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); } else { - /* unsigned */ - uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - uae_u64 quot, rem; - - if (extra & 0x400) { - a &= 0xffffffffu; - a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32; - } - rem = a % (uae_u64)src; - quot = a / (uae_u64)src; - if (quot > 0xffffffffu) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = (uae_u32)rem; - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; - } + if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; } + } else { + /* unsigned */ + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + uae_u64 quot, rem; + + if (extra & 0x400) { + a &= 0xffffffffu; + a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32; + } + rem = a % (uae_u64)src; + quot = a / (uae_u64)src; + if (quot > 0xffffffffu) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; + } + } #else - if (src == 0) { - Exception (5, oldpc); - return; - } - if (extra & 0x800) { - /* signed variant */ - uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - uae_s32 hi = lo < 0 ? -1 : 0; - uae_s32 save_high; - uae_u32 quot, rem; - uae_u32 sign; + if (src == 0) { + Exception (5, oldpc); + return; + } + if (extra & 0x800) { + /* signed variant */ + uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + uae_s32 hi = lo < 0 ? -1 : 0; + uae_s32 save_high; + uae_u32 quot, rem; + uae_u32 sign; - if (extra & 0x400) { - hi = (uae_s32)m68k_dreg(regs, extra & 7); - } - save_high = hi; - sign = (hi ^ src); - if (hi < 0) { - hi = ~hi; - lo = -lo; - if (lo == 0) hi++; - } - if ((uae_s32)src < 0) src = -src; - if (div_unsigned(hi, lo, src, ", &rem) || - (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - if (sign & 0x80000000) quot = -quot; - if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } + if (extra & 0x400) { + hi = (uae_s32)m68k_dreg(regs, extra & 7); + } + save_high = hi; + sign = (hi ^ src); + if (hi < 0) { + hi = ~hi; + lo = -lo; + if (lo == 0) hi++; + } + if ((uae_s32)src < 0) src = -src; + if (div_unsigned(hi, lo, src, ", &rem) || + (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); } else { - /* unsigned */ - uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - uae_u32 hi = 0; - uae_u32 quot, rem; - - if (extra & 0x400) { - hi = (uae_u32)m68k_dreg(regs, extra & 7); - } - if (div_unsigned(hi, lo, src, ", &rem)) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } + if (sign & 0x80000000) quot = -quot; + if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; } + } else { + /* unsigned */ + uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + uae_u32 hi = 0; + uae_u32 quot, rem; + + if (extra & 0x400) { + hi = (uae_u32)m68k_dreg(regs, extra & 7); + } + if (div_unsigned(hi, lo, src, ", &rem)) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; + } + } #endif } -static __inline__ void +#if !defined(uae_s64) +static inline void mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) { uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff); @@ -1079,148 +845,198 @@ mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) *dst_lo = lo; *dst_hi = r3; } +#endif -void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra) +void m68k_mull (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra) { #if defined(uae_s64) - if (extra & 0x800) { - /* signed variant */ - uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + if (extra & 0x800) { + /* signed variant */ + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - a *= (uae_s64)(uae_s32)src; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (a == 0); - SET_NFLG (a < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = a >> 32; - else if ((a & UVAL64(0xffffffff80000000)) != 0 - && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) - { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; - } else { - /* unsigned */ - uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - - a *= (uae_u64)src; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (a == 0); - SET_NFLG (((uae_s64)a) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = a >> 32; - else if ((a & UVAL64(0xffffffff00000000)) != 0) { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; + a *= (uae_s64)(uae_s32)src; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (a == 0); + SET_NFLG (a < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = a >> 32; + else if ((a & UVAL64(0xffffffff80000000)) != 0 + && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) + { + SET_VFLG (1); } + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; + } else { + /* unsigned */ + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + + a *= (uae_u64)src; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (a == 0); + SET_NFLG (((uae_s64)a) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = a >> 32; + else if ((a & UVAL64(0xffffffff00000000)) != 0) { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; + } #else - if (extra & 0x800) { - /* signed variant */ - uae_s32 src1,src2; - uae_u32 dst_lo,dst_hi; - uae_u32 sign; + if (extra & 0x800) { + /* signed variant */ + uae_s32 src1,src2; + uae_u32 dst_lo,dst_hi; + uae_u32 sign; - src1 = (uae_s32)src; - src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - sign = (src1 ^ src2); - if (src1 < 0) src1 = -src1; - if (src2 < 0) src2 = -src2; - mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo); - if (sign & 0x80000000) { - dst_hi = ~dst_hi; - dst_lo = -dst_lo; - if (dst_lo == 0) dst_hi++; - } - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (dst_hi == 0 && dst_lo == 0); - SET_NFLG (((uae_s32)dst_hi) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = dst_hi; - else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) - && ((dst_hi & 0xffffffff) != 0xffffffff - || (dst_lo & 0x80000000) != 0x80000000)) - { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; - } else { - /* unsigned */ - uae_u32 dst_lo,dst_hi; - - mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo); - - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (dst_hi == 0 && dst_lo == 0); - SET_NFLG (((uae_s32)dst_hi) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = dst_hi; - else if (dst_hi != 0) { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; + src1 = (uae_s32)src; + src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + sign = (src1 ^ src2); + if (src1 < 0) src1 = -src1; + if (src2 < 0) src2 = -src2; + mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo); + if (sign & 0x80000000) { + dst_hi = ~dst_hi; + dst_lo = -dst_lo; + if (dst_lo == 0) dst_hi++; } + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (dst_hi == 0 && dst_lo == 0); + SET_NFLG (((uae_s32)dst_hi) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = dst_hi; + else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) + && ((dst_hi & 0xffffffff) != 0xffffffff + || (dst_lo & 0x80000000) != 0x80000000)) + { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; + } else { + /* unsigned */ + uae_u32 dst_lo,dst_hi; + + mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo); + + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (dst_hi == 0 && dst_lo == 0); + SET_NFLG (((uae_s32)dst_hi) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = dst_hi; + else if (dst_hi != 0) { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; + } #endif } -static const char* ccnames[] = -{ "T ","F ","HI","LS","CC","CS","NE","EQ", - "VC","VS","PL","MI","GE","LT","GT","LE" }; // If value is greater than zero, this means we are still processing an EmulOp // because the counter is incremented only in m68k_execute(), i.e. interpretive // execution only +#ifdef USE_JIT static int m68k_execute_depth = 0; +#endif void m68k_reset (void) { - m68k_areg (regs, 7) = 0x2000; - m68k_setpc (ROMBaseMac + 0x2a); - fill_prefetch_0 (); - regs.s = 1; - regs.m = 0; - regs.stopped = 0; - regs.t1 = 0; - regs.t0 = 0; - SET_ZFLG (0); - SET_XFLG (0); - SET_CFLG (0); - SET_VFLG (0); - SET_NFLG (0); - SPCFLAGS_INIT( 0 ); - regs.intmask = 7; - regs.vbr = regs.sfc = regs.dfc = 0; - fpu_reset(); + regs.s = 1; + regs.m = 0; + regs.stopped = 0; + regs.t1 = 0; + regs.t0 = 0; + SET_ZFLG (0); + SET_XFLG (0); + SET_CFLG (0); + SET_VFLG (0); + SET_NFLG (0); + SPCFLAGS_INIT( 0 ); + regs.intmask = 7; + regs.vbr = regs.sfc = regs.dfc = 0; -#if FLIGHT_RECORDER + // need to ensure the following order of initialization is correct + // (it is definitely better than what it was before this commit + // since it was reading from 0x00000000 in User mode and with active MMU) + mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */ + m68k_areg (regs, 7) = phys_get_long(0x00000000); +#if 0 + m68k_setpc (phys_get_long(0x00000004)); +#else + m68k_setpc (ROMBaseMac + 0x2a); +#endif + fill_prefetch_0 (); + + /* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init() + regs.fpcr = regs.fpsr = regs.fpiar = 0; */ + fpu_reset(); +#if 0 + // MMU + mmu_reset(); + mmu_set_super(1); + // Cache + regs.cacr = 0; + regs.caar = 0; +#endif +#ifdef FLIGHT_RECORDER log_ptr = 0; - memset(log, 0, sizeof(log)); -#endif - -#if ENABLE_MON - static bool first_time = true; - if (first_time) { - first_time = false; - mon_add_command("regs", dump_regs, "regs Dump m68k emulator registers\n"); -#if FLIGHT_RECORDER - // Install "log" command in mon - mon_add_command("log", dump_log, "log Dump m68k emulation log\n"); -#endif - } + memset(frlog, 0, sizeof(frlog)); #endif } void m68k_emulop_return(void) { SPCFLAGS_SET( SPCFLAG_BRK ); - quit_program = true; + quit_program = 1; +} + +static void save_regs(struct M68kRegisters &r) +{ + int i; + + for (i=0; i<8; i++) { + r.d[i] = m68k_dreg(regs, i); + r.a[i] = m68k_areg(regs, i); + } + r.pc = m68k_getpc(); + MakeSR(); + r.sr = regs.sr; + r.isp = regs.isp; + r.usp = regs.usp; + r.msp = regs.msp; + if ((r.sr & 0x2000) == 0) + r.usp = r.a[7]; + else if ((r.sr & 0x1000) != 0) + r.msp = r.a[7]; + else + r.isp = r.a[7]; +} + +static void restore_regs(struct M68kRegisters &r) +{ + int i; + + for (i=0; i<8; i++) { + m68k_dreg(regs, i) = r.d[i]; + m68k_areg(regs, i) = r.a[i]; + } + regs.isp = r.isp; + regs.usp = r.usp; + regs.msp = r.msp; + regs.sr = r.sr; + MakeFromSR(); } void m68k_emulop(uae_u32 opcode) { +#if 0 + struct M68kRegisters r; + save_regs(r); + if (EmulOp(opcode, &r)) + restore_regs(r); +#else struct M68kRegisters r; int i; @@ -1237,6 +1053,135 @@ void m68k_emulop(uae_u32 opcode) } regs.sr = r.sr; MakeFromSR(); +#endif +} + +#if 0 +void m68k_natfeat_id(void) +{ + struct M68kRegisters r; + + /* is it really necessary to save all registers? */ + save_regs(r); + + memptr stack = r.a[7] + 4; /* skip return address */ + r.d[0] = nf_get_id(stack); + + restore_regs(r); +} + +void m68k_natfeat_call(void) +{ + struct M68kRegisters r; + + /* is it really necessary to save all registers? */ + save_regs(r); + + memptr stack = r.a[7] + 4; /* skip return address */ + bool isSupervisorMode = ((r.sr & 0x2000) == 0x2000); + r.d[0] = nf_call(stack, isSupervisorMode); + + restore_regs(r); +} +#endif + +static int m68k_call(uae_u32 pc) +{ + VOLATILE int exc = 0; + m68k_setpc(pc); + TRY(prb) { +#ifdef USE_JIT + if (UseJIT) { + exec_nostats(); + // m68k_do_compile_execute(); + // The above call to m68k_do_compile_execute fails with BadAccess in sigsegv_handler (MAC, if it is executed after the first compile_block) + // (NULL pointer to addr_instr). + // Call exec_nostats avoids calling compile_block, because stack modification is only temporary + // which will fill up compile cache with BOGUS data. + // we can call exec_nostats directly, do our code, and return back here. + } + else +#endif + m68k_do_execute(); + } + CATCH(prb) { + exc = int(prb); + } + return exc; +} + +static uae_u32 m68k_alloca(int size) +{ + uae_u32 sp = (m68k_areg(regs, 7) - size) & ~1; + m68k_areg(regs, 7) = sp; + if ((regs.sr & 0x2000) == 0) + regs.usp = sp; + else if ((regs.sr & 0x1000) != 0) + regs.msp = sp; + else + regs.isp = sp; + return sp; +} + +#if 0 +uae_u32 linea68000(volatile uae_u16 opcode) +{ + sigjmp_buf jmp; + struct M68kRegisters r; + volatile uae_u32 abase = 0; + + SAVE_EXCEPTION; + save_regs(r); + + const int sz = 8 + sizeof(void *); + volatile uae_u32 sp = 0; + uae_u32 backup[(sz + 3) / 4]; + + if (sigsetjmp(jmp, 1) == 0) + { + void *p = jmp; + uae_u8 *sp_p; + int exc; + + sp = m68k_alloca(sz); + memcpy(backup, phys_get_real_address(sp), sz); + + WriteHWMemInt16(sp, opcode); + WriteHWMemInt16(sp + 2, 0xa0ff); + WriteHWMemInt32(sp + 4, 13); + sp_p = phys_get_real_address(sp + 8); + *((void **)sp_p) = p; + if ((exc = m68k_call(sp)) != 0) + { + panicbug("exception %d in LINEA", exc); + m68k_dreg(regs, 0) = 0; + } + } else + { + abase = m68k_dreg(regs, 0); + } + + if (sp) { + memcpy(phys_get_real_address(sp), backup, sz); + } + restore_regs(r); + m68k_setpc(r.pc); + RESTORE_EXCEPTION; + return abase; +} +#endif + + +static void rts68000() +{ + uae_u32 SP = m68k_getpc() + 6; + sigjmp_buf *p; + uae_u8 *sp_p = phys_get_real_address(SP); + + p = (sigjmp_buf *)(*((void **)sp_p)); + SP += sizeof(void *); + m68k_areg(regs, 7) = SP; + siglongjmp(*p, 1); } void REGPARAM2 op_illg (uae_u32 opcode) @@ -1244,6 +1189,19 @@ void REGPARAM2 op_illg (uae_u32 opcode) uaecptr pc = m68k_getpc (); if ((opcode & 0xF000) == 0xA000) { +#if 0 + if (opcode == 0xa0ff) + { + uae_u32 call = ReadHWMemInt32(pc + 2); + switch (call) + { + case 13: + rts68000(); + return; + } + m68k_setpc(pc + 6); + } +#endif Exception(0xA,0); return; } @@ -1253,8 +1211,8 @@ void REGPARAM2 op_illg (uae_u32 opcode) return; } - write_log ("Illegal instruction: %04x at %08x\n", opcode, pc); -#if USE_JIT && JIT_DEBUG + D(bug("Illegal instruction: %04x at %08x", opcode, pc)); +#if defined(USE_JIT) && defined(JIT_DEBUG) compiler_dumpstate(); #endif @@ -1262,62 +1220,119 @@ void REGPARAM2 op_illg (uae_u32 opcode) return; } -void mmu_op(uae_u32 opcode, uae_u16 extra) -{ - if ((opcode & 0xFE0) == 0x0500) { - /* PFLUSH */ - mmusr = 0; -#ifdef USE_JIT - flush_icache(); -#endif - } else if ((opcode & 0x0FD8) == 0x548) { - /* PTEST */ - } else - op_illg (opcode); -} - -static int n_insns = 0, n_spcinsns = 0; - static uaecptr last_trace_ad = 0; static void do_trace (void) { - if (regs.t0 && CPUType >= 2) { - uae_u16 opcode; - /* should also include TRAP, CHK, SR modification FPcc */ - /* probably never used so why bother */ - /* We can afford this to be inefficient... */ - m68k_setpc (m68k_getpc ()); - fill_prefetch_0 (); - opcode = get_word(m68k_getpc()); - if (opcode == 0x4e72 /* RTE */ - || opcode == 0x4e74 /* RTD */ - || opcode == 0x4e75 /* RTS */ - || opcode == 0x4e77 /* RTR */ - || opcode == 0x4e76 /* TRAPV */ - || (opcode & 0xffc0) == 0x4e80 /* JSR */ - || (opcode & 0xffc0) == 0x4ec0 /* JMP */ - || (opcode & 0xff00) == 0x6100 /* BSR */ - || ((opcode & 0xf000) == 0x6000 /* Bcc */ - && cctrue((opcode >> 8) & 0xf)) - || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ - && !cctrue((opcode >> 8) & 0xf) - && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) - { - last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); - } - } else if (regs.t1) { - last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); + if (regs.t0) { + uae_u16 opcode; + /* should also include TRAP, CHK, SR modification FPcc */ + /* probably never used so why bother */ + /* We can afford this to be inefficient... */ + m68k_setpc (m68k_getpc ()); + fill_prefetch_0 (); + opcode = get_word(m68k_getpc()); + if (opcode == 0x4e72 /* RTE */ + || opcode == 0x4e74 /* RTD */ + || opcode == 0x4e75 /* RTS */ + || opcode == 0x4e77 /* RTR */ + || opcode == 0x4e76 /* TRAPV */ + || (opcode & 0xffc0) == 0x4e80 /* JSR */ + || (opcode & 0xffc0) == 0x4ec0 /* JMP */ + || (opcode & 0xff00) == 0x6100 /* BSR */ + || ((opcode & 0xf000) == 0x6000 /* Bcc */ + && cctrue((opcode >> 8) & 0xf)) + || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ + && !cctrue((opcode >> 8) & 0xf) + && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) + { + last_trace_ad = m68k_getpc (); + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } + } else if (regs.t1) { + last_trace_ad = m68k_getpc (); + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); + } } -int m68k_do_specialties (void) +#if 0 +#define SERVE_VBL_MFP(resetStop) \ +{ \ + if (SPCFLAGS_TEST( SPCFLAG_INT3|SPCFLAG_VBL|SPCFLAG_INT5|SPCFLAG_SCC|SPCFLAG_MFP )) { \ + if (SPCFLAGS_TEST( SPCFLAG_INT3 )) { \ + if (3 > regs.intmask) { \ + Interrupt(3); \ + regs.stopped = 0; \ + SPCFLAGS_CLEAR( SPCFLAG_INT3 ); \ + if (resetStop) \ + SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ + } \ + } \ + if (SPCFLAGS_TEST( SPCFLAG_VBL )) { \ + if (4 > regs.intmask) { \ + Interrupt(4); \ + regs.stopped = 0; \ + SPCFLAGS_CLEAR( SPCFLAG_VBL ); \ + if (resetStop) \ + SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ + } \ + } \ + if (SPCFLAGS_TEST( SPCFLAG_INT5 )) { \ + if (5 > regs.intmask) { \ + Interrupt(5); \ + regs.stopped = 0; \ + SPCFLAGS_CLEAR( SPCFLAG_INT5 ); \ + if (resetStop) \ + SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ + } \ + } \ + if (SPCFLAGS_TEST( SPCFLAG_SCC )) { \ + if (5 > regs.intmask) { \ + int vector_number=SCCdoInterrupt(); \ + if(vector_number){ \ + SCCInterrupt(vector_number); \ + regs.stopped = 0; \ + SPCFLAGS_CLEAR( SPCFLAG_SCC); \ + if (resetStop) \ + SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ + } \ + else \ + SPCFLAGS_CLEAR( SPCFLAG_SCC ); \ + } \ + } \ + if (SPCFLAGS_TEST( SPCFLAG_MFP )) { \ + if (6 > regs.intmask) { \ + int vector_number = MFPdoInterrupt(); \ + if (vector_number) { \ + MFPInterrupt(vector_number); \ + regs.stopped = 0; \ + if (resetStop) \ + SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ + } \ + else \ + SPCFLAGS_CLEAR( SPCFLAG_MFP ); \ + } \ + } \ + } \ +} + +#define SERVE_INTERNAL_IRQ() \ +{ \ + if (SPCFLAGS_TEST( SPCFLAG_INTERNAL_IRQ )) { \ + SPCFLAGS_CLEAR( SPCFLAG_INTERNAL_IRQ ); \ + invoke200HzInterrupt(); \ + } \ +} +#endif + +int m68k_do_specialties(void) { -#if USE_JIT +#if 0 + SERVE_INTERNAL_IRQ(); +#endif +#ifdef USE_JIT // Block was compiled SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE ); @@ -1328,11 +1343,39 @@ int m68k_do_specialties (void) if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN )) SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN ); #endif - + /*n_spcinsns++;*/ if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { Exception (9,last_trace_ad); } +#if 0 /* not for ARAnyM; emulating 040 only */ + if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) { + // 68000/68010 undocumented special case: + // if STOP clears S-bit and T was not set: + // cause privilege violation exception, PC pointing to following instruction. + // If T was set before STOP: STOP works as documented. + m68k_unset_stop(); + Exception(8, 0); + } +#endif while (SPCFLAGS_TEST( SPCFLAG_STOP )) { + //TODO: Check +#if 0 + if ((regs.sr & 0x700) == 0x700) + { + panicbug("STOPed with interrupts disabled, exiting; pc=$%08x", m68k_getpc()); + m68k_dumpstate (stderr, NULL); + quit_program = 1; +#ifdef FULL_HISTORY + ndebug::showHistory(20, false); + m68k_dumpstate (stderr, NULL); +#endif + return 1; + } +#endif +#if 0 + // give unused time slices back to OS + SleepAndWait(); +#endif if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); int intr = intlev (); @@ -1342,10 +1385,30 @@ int m68k_do_specialties (void) SPCFLAGS_CLEAR( SPCFLAG_STOP ); } } + +#if 0 + SERVE_INTERNAL_IRQ(); + SERVE_VBL_MFP(true); +#endif +#if 0 + if (SPCFLAGS_TEST( SPCFLAG_BRK )) + break; +#endif } if (SPCFLAGS_TEST( SPCFLAG_TRACE )) do_trace (); +#if 0 + SERVE_VBL_MFP(false); +#endif + +/* +// do not understand the INT vs DOINT stuff so I disabled it (joy) + if (regs.spcflags & SPCFLAG_INT) { + regs.spcflags &= ~SPCFLAG_INT; + regs.spcflags |= SPCFLAG_DOINT; + } +*/ if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { SPCFLAGS_CLEAR( SPCFLAG_DOINT ); int intr = intlev (); @@ -1354,159 +1417,213 @@ int m68k_do_specialties (void) regs.stopped = 0; } } + if (SPCFLAGS_TEST( SPCFLAG_INT )) { SPCFLAGS_CLEAR( SPCFLAG_INT ); SPCFLAGS_SET( SPCFLAG_DOINT ); } - if (SPCFLAGS_TEST( SPCFLAG_BRK )) { - SPCFLAGS_CLEAR( SPCFLAG_BRK ); + + if (SPCFLAGS_TEST( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ )) { + SPCFLAGS_CLEAR( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ ); return 1; } + return 0; } void m68k_do_execute (void) { - for (;;) { - uae_u32 opcode = GET_OPCODE; -#if FLIGHT_RECORDER - m68k_record_step(m68k_getpc()); + uae_u32 pc; + uae_u32 opcode; + for (;;) { + regs.fault_pc = pc = m68k_getpc(); +#ifdef FULL_HISTORY +#ifdef NEED_TO_DEBUG_BADLY + history[lasthist] = regs; + historyf[lasthist] = regflags; +#else + history[lasthist] = m68k_getpc(); #endif - (*cpufunctbl[opcode])(opcode); - cpu_check_ticks(); - if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { - if (m68k_do_specialties()) - return; - } + if (++lasthist == MAX_HIST) lasthist = 0; + if (lasthist == firsthist) { + if (++firsthist == MAX_HIST) firsthist = 0; } +#endif + +#ifndef FULLMMU +#ifdef ARAM_PAGE_CHECK + if (((pc ^ pc_page) > ARAM_PAGE_MASK)) { + check_ram_boundary(pc, 2, false); + pc_page = pc; + pc_offset = (uintptr)get_real_address(pc, 0, sz_word) - pc; + } +#else + check_ram_boundary(pc, 2, false); +#endif +#endif + opcode = GET_OPCODE; +#ifdef FLIGHT_RECORDER + m68k_record_step(m68k_getpc(), cft_map(opcode)); +#endif + (*cpufunctbl[opcode])(opcode); + cpu_check_ticks(); + regs.fault_pc = m68k_getpc(); + + if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { + if (m68k_do_specialties()) + return; + } + } } void m68k_execute (void) { -#if USE_JIT - ++m68k_execute_depth; +#ifdef USE_JIT + m68k_execute_depth++; #endif +#ifdef DEBUGGER + VOLATILE bool after_exception = false; +#endif + +setjmpagain: + TRY(prb) { for (;;) { - if (quit_program) - break; - m68k_do_execute(); + if (quit_program > 0) { + if (quit_program == 1) { +#ifdef FLIGHT_RECORDER + dump_flight_recorder(); +#endif + break; + } + quit_program = 0; + m68k_reset (); + } +#ifdef DEBUGGER + if (debugging && !after_exception) debug(); + after_exception = false; +#endif + m68k_do_execute(); } -#if USE_JIT - --m68k_execute_depth; + } + CATCH(prb) { + Exception(prb, 0); +#ifdef DEBUGGER + after_exception = true; +#endif + goto setjmpagain; + } + +#ifdef USE_JIT + m68k_execute_depth--; #endif } -static void m68k_verify (uaecptr addr, uaecptr *nextpc) +void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) { - uae_u32 opcode, val; - struct instr *dp; +#ifdef HAVE_DISASM_M68K + char buf[256]; + int size; - opcode = get_iword_1(0); - last_op_for_exception_3 = opcode; - m68kpc_offset = 2; - - if (cpufunctbl[cft_map (opcode)] == op_illg_1) { - opcode = 0x4AFC; - } - dp = table68k + opcode; - - if (dp->suse) { - if (!verify_ea (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, &val)) { - Exception (3, 0); - return; - } - } - if (dp->duse) { - if (!verify_ea (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, &val)) { - Exception (3, 0); - return; - } + disasm_info.memory_vma = addr; + while (cnt-- > 0) { + size = m68k_disasm_to_buf(&disasm_info, buf, 1); + fprintf(f, "%s\n", buf); + if (size < 0) + break; } + if (nextpc) + *nextpc = disasm_info.memory_vma; +#else + if (nextpc) + *nextpc = addr; + (void) f; + (void) cnt; +#endif } -void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt) +#ifdef DEBUGGER +void newm68k_disasm(FILE *f, uaecptr addr, uaecptr *nextpc, unsigned int cnt) { - uaecptr newpc = 0; - m68kpc_offset = addr - m68k_getpc (); - while (cnt-- > 0) { - char instrname[20],*ccpt; - int opwords; - uae_u32 opcode; - struct mnemolookup *lookup; - struct instr *dp; - printf ("%08lx: ", m68k_getpc () + m68kpc_offset); - for (opwords = 0; opwords < 5; opwords++){ - printf ("%04x ", get_iword_1 (m68kpc_offset + opwords*2)); - } - opcode = get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - if (cpufunctbl[cft_map (opcode)] == op_illg_1) { - opcode = 0x4AFC; - } - dp = table68k + opcode; - for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) - ; +#ifdef HAVE_DISASM_M68K + char buf[256]; - strcpy (instrname, lookup->name); - ccpt = strstr (instrname, "cc"); - if (ccpt != 0) { - strncpy (ccpt, ccnames[dp->cc], 2); - } - printf ("%s", instrname); - switch (dp->size){ - case sz_byte: printf (".B "); break; - case sz_word: printf (".W "); break; - case sz_long: printf (".L "); break; - default: printf (" "); break; - } - - if (dp->suse) { - newpc = m68k_getpc () + m68kpc_offset; - newpc += ShowEA (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); - } - if (dp->suse && dp->duse) - printf (","); - if (dp->duse) { - newpc = m68k_getpc () + m68kpc_offset; - newpc += ShowEA (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 0); - } - if (ccpt != 0) { - if (cctrue(dp->cc)) - printf (" == %08x (TRUE)", newpc); - else - printf (" == %08x (FALSE)", newpc); - } else if ((opcode & 0xff00) == 0x6100) /* BSR */ - printf (" == %08x", newpc); - printf ("\n"); - } - if (nextpc) - *nextpc = m68k_getpc () + m68kpc_offset; + disasm_info.memory_vma = addr; + if (cnt == 0) { + m68k_disasm_to_buf(&disasm_info, buf, 1); + } else { + while (cnt-- > 0) { + m68k_disasm_to_buf(&disasm_info, buf, 1); + fprintf(f, "%s\n", buf); + } + } + if (nextpc) + *nextpc = disasm_info.memory_vma; +#else + if (nextpc) + *nextpc = addr; + (void) cnt; +#endif } -void m68k_dumpstate (uaecptr *nextpc) -{ - int i; - for (i = 0; i < 8; i++){ - printf ("D%d: %08x ", i, m68k_dreg(regs, i)); - if ((i & 3) == 3) printf ("\n"); - } - for (i = 0; i < 8; i++){ - printf ("A%d: %08x ", i, m68k_areg(regs, i)); - if ((i & 3) == 3) printf ("\n"); - } - if (regs.s == 0) regs.usp = m68k_areg(regs, 7); - if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); - if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); - printf ("USP=%08x ISP=%08x MSP=%08x VBR=%08x\n", - regs.usp,regs.isp,regs.msp,regs.vbr); - printf ("T=%d%d S=%d M=%d X=%ld N=%ld Z=%ld V=%ld C=%ld IMASK=%d\n", - regs.t1, regs.t0, regs.s, regs.m, - GET_XFLG(), GET_NFLG(), GET_ZFLG(), GET_VFLG(), GET_CFLG(), regs.intmask); +#endif /* DEBUGGER */ - fpu_dump_registers(); - fpu_dump_flags(); +#ifdef FULL_HISTORY +void showDisasm(uaecptr addr) { +#ifdef HAVE_DISASM_M68K + char buf[256]; - m68k_disasm(m68k_getpc (), nextpc, 1); - if (nextpc) - printf ("next PC: %08x\n", *nextpc); + disasm_info.memory_vma = addr; + m68k_disasm_to_buf(&disasm_info, buf, 1); + bug("%s", buf); +#else + (void) addr; +#endif +} +#endif /* FULL_HISTORY */ + +void m68k_dumpstate (FILE *out, uaecptr *nextpc) +{ + int i; + for (i = 0; i < 8; i++){ + fprintf (out, "D%d: %08lx ", i, (unsigned long)m68k_dreg(regs, i)); + if ((i & 3) == 3) fprintf (out, "\n"); + } + for (i = 0; i < 8; i++){ + fprintf (out, "A%d: %08lx ", i, (unsigned long)m68k_areg(regs, i)); + if ((i & 3) == 3) fprintf (out, "\n"); + } + if (regs.s == 0) regs.usp = m68k_areg(regs, 7); + if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); + if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); + fprintf (out, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", + (unsigned long)regs.usp, (unsigned long)regs.isp, + (unsigned long)regs.msp, (unsigned long)regs.vbr); + fprintf (out, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d TCE=%d TCP=%d\n", + regs.t1, regs.t0, regs.s, regs.m, + (int)GET_XFLG(), (int)GET_NFLG(), (int)GET_ZFLG(), (int)GET_VFLG(), (int)GET_CFLG(), regs.intmask, + regs.mmu_enabled, regs.mmu_pagesize_8k); + fprintf (out, "CACR=%08lx CAAR=%08lx URP=%08lx SRP=%08lx\n", + (unsigned long)regs.cacr, + (unsigned long)regs.caar, + (unsigned long)regs.urp, + (unsigned long)regs.srp); + fprintf (out, "DTT0=%08lx DTT1=%08lx ITT0=%08lx ITT1=%08lx\n", + (unsigned long)regs.dtt0, + (unsigned long)regs.dtt1, + (unsigned long)regs.itt0, + (unsigned long)regs.itt1); + for (i = 0; i < 8; i++){ + fprintf (out, "FP%d: %g ", i, (double)fpu.registers[i]); + if ((i & 3) == 3) fprintf (out, "\n"); + } +#if 0 + fprintf (out, "N=%d Z=%d I=%d NAN=%d\n", + (regs.fpsr & 0x8000000) != 0, + (regs.fpsr & 0x4000000) != 0, + (regs.fpsr & 0x2000000) != 0, + (regs.fpsr & 0x1000000) != 0); +#endif + m68k_disasm(out, m68k_getpc (), nextpc, 1); + if (nextpc) + fprintf (out, "next PC: %08lx\n", (unsigned long)*nextpc); } diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index 97731f59..13a51b82 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -1,41 +1,51 @@ /* - * UAE - The Un*x Amiga Emulator + * newcpu.h - CPU emulation * - * MC68000 emulation + * Copyright (c) 2009 ARAnyM dev team (see AUTHORS) + * + * Inspired by Christian Bauer's Basilisk II * - * Copyright 1995 Bernd Schmidt + * This file is part of the ARAnyM project which builds a new and powerful + * TOS/FreeMiNT compatible virtual machine running on almost any hardware. * - * This program is free software; you can redistribute it and/or modify + * ARAnyM is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * ARAnyM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with ARAnyM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * Copyright 1995 Bernd Schmidt + */ #ifndef NEWCPU_H #define NEWCPU_H -#ifndef FLIGHT_RECORDER -#define FLIGHT_RECORDER 0 -#endif - -#include "m68k.h" -#include "readcpu.h" +#include "sysdeps.h" +#include "registers.h" #include "spcflags.h" +#include "m68k.h" +#include "memory.h" -#if ENABLE_MON -#include "mon.h" -#include "mon_disass.h" -#endif +# include +extern struct fixup { + int flag; + uae_u32 reg; + uaecptr value; +}fixup; extern int areg_byteinc[]; extern int imm8_table[]; @@ -57,27 +67,25 @@ extern int broken_in; #endif #define cpuop_begin() do { cpuop_tag("begin"); } while (0) -#define cpuop_end() do { cpuop_tag("end"); } while (0) +#define cpuop_end() do { cpuop_tag("end"); } while (0) typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM; - + struct cputbl { cpuop_func *handler; uae_u16 specific; uae_u16 opcode; }; -extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl"); +extern cpuop_func *cpufunctbl[65536]; -#if USE_JIT +#ifdef USE_JIT typedef void compop_func (uae_u32) REGPARAM; -//NOTE: The "opcode" and "specific" fields were switched in the original source code! - struct comptbl { compop_func *handler; - uae_u32 opcode; - uae_u32 specific; + uae_u32 opcode; + uae_u32 specific; #define COMP_OPCODE_ISJUMP 0x0001 #define COMP_OPCODE_LONG_OPCODE 0x0002 #define COMP_OPCODE_CMOV 0x0004 @@ -88,151 +96,84 @@ struct comptbl { #endif extern void REGPARAM2 op_illg (uae_u32) REGPARAM; -extern void m68k_dumpstate(uaecptr *nextpc); - -typedef char flagtype; - -// struct regstruct { -// uae_u32 regs[16]; - -// uae_u32 pc; -// uae_u8 * pc_p; -// uae_u8 * pc_oldp; - -// spcflags_t spcflags; -// int intmask; - -// uae_u32 vbr, sfc, dfc; -// uaecptr usp, isp, msp; -// uae_u16 sr; -// flagtype t1; -// flagtype t0; -// flagtype s; -// flagtype m; -// flagtype x; -// flagtype stopped; - -// #if USE_PREFETCH_BUFFER -// /* Fellow sources say this is 4 longwords. That's impossible. It needs -// * to be at least a longword. The HRM has some cryptic comment about two -// * instructions being on the same longword boundary. -// * The way this is implemented now seems like a good compromise. -// */ -// uae_u32 prefetch; -// #endif -// }; - -struct regstruct -{ - uae_u32 regs[16]; - uaecptr usp,isp,msp; - uae_u16 sr; - flagtype t1; - flagtype t0; - flagtype s; - flagtype m; - flagtype x; - flagtype stopped; - int intmask; - - uae_u32 pc; - uae_u32 fault_pc; - uae_u8 *pc_p; - uae_u8 *pc_oldp; - - uae_u32 vbr,sfc,dfc; - - volatile uae_u32 spcflags; - -#if 1 - uae_u32 kick_mask; - - /* Fellow sources say this is 4 longwords. That's impossible. It needs - * to be at least a longword. The HRM has some cryptic comment about two - * instructions being on the same longword boundary. - * The way this is implemented now seems like a good compromise. - */ - uae_u32 prefetch; -#endif - - /* MMU reg*/ - uae_u32 urp,srp; - uae_u32 tc; - - int mmu_enabled; /* flagtype tce; */ - int mmu_pagesize_8k; /* flagtype tcp; */ - - uae_u32 dtt0,dtt1,itt0,itt1; - uae_u32 mmusr; - - uae_u32 mmu_fslw, mmu_fault_addr; - uae_u16 mmu_ssw; - uae_u32 wb3_data; - uae_u16 wb3_status; - - /* Cache reg*/ - uae_u32 cacr,caar; -}; - -extern regstruct regs, lastint_regs; #define m68k_dreg(r,num) ((r).regs[(num)]) #define m68k_areg(r,num) (((r).regs + 8)[(num)]) -#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1)) -#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o))) -#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o))) +#ifdef FULLMMU +static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o) +{ + return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte); +} +static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o) +{ + return mmu_get_word(m68k_getpc() + o, 0, sz_word); +} +static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o) +{ + uaecptr addr = m68k_getpc() + o; + + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_long_unaligned(addr, 0); + return mmu_get_long(addr, 0, sz_long); +} -#ifdef HAVE_GET_WORD_UNSWAPPED -#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p)) #else -#define GET_OPCODE (get_iword (0)) +#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1)) +#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o))) +#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o))) #endif -#if USE_PREFETCH_BUFFER -static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o) +#if 0 +static inline uae_u32 get_ibyte_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1)); + return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1)); return do_get_mem_byte((uae_u8 *)(((uae_u8 *)®s.prefetch) + o + 1)); } -static __inline__ uae_u32 get_iword_prefetch (uae_s32 o) +static inline uae_u32 get_iword_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_word((uae_u16 *)(regs.pc_p + o)); + return do_get_mem_word((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + o)); return do_get_mem_word((uae_u16 *)(((uae_u8 *)®s.prefetch) + o)); } -static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o) +static inline uae_u32 get_ilong_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_long((uae_u32 *)(regs.pc_p + o)); + return do_get_mem_long((uae_u32 *)(do_get_real_address(regs.pcp, false, false) + o)); if (o == 0) return do_get_mem_long(®s.prefetch); - return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4)); + return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + 4)); } #endif -static __inline__ void fill_prefetch_0 (void) +#ifdef FULLMMU +#define m68k_incpc(o) (regs.pc += (o)) +#else +#define m68k_incpc(o) (regs.pc_p += (o)) +#endif + +static inline void fill_prefetch_0 (void) { #if USE_PREFETCH_BUFFER uae_u32 r; #ifdef UNALIGNED_PROFITABLE - r = *(uae_u32 *)regs.pc_p; + r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false); regs.prefetch = r; #else - r = do_get_mem_long ((uae_u32 *)regs.pc_p); + r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false)); do_put_mem_long (®s.prefetch, r); #endif #endif } #if 0 -static __inline__ void fill_prefetch_2 (void) +static inline void fill_prefetch_2 (void) { uae_u32 r = do_get_mem_long (®s.prefetch) << 16; - uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1); + uae_u32 r2 = do_get_mem_word (((uae_u16 *)do_get_real_address(regs.pcp, false, false)) + 1); r |= r2; do_put_mem_long (®s.prefetch, r); } @@ -240,115 +181,92 @@ static __inline__ void fill_prefetch_2 (void) #define fill_prefetch_2 fill_prefetch_0 #endif -static __inline__ uaecptr m68k_getpc (void) -{ -#if REAL_ADDRESSING || DIRECT_ADDRESSING - return get_virtual_address(regs.pc_p); -#else - return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); -#endif -} - -static __inline__ void m68k_setpc (uaecptr newpc) -{ -#if ENABLE_MON - uae_u32 previous_pc = m68k_getpc(); -#endif - -#if REAL_ADDRESSING || DIRECT_ADDRESSING - regs.pc_p = get_real_address(newpc); -#else - regs.pc_p = regs.pc_oldp = get_real_address(newpc); - regs.pc = newpc; -#endif - -#if ENABLE_MON - if (IS_BREAK_POINT(newpc)) { - printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc); - m68k_dumpstate(NULL); - const char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); - } -#endif // end of #if ENABLE_MON -} - -static __inline__ void m68k_incpc (uae_s32 delta) -{ -#if ENABLE_MON - uae_u32 previous_pc = m68k_getpc(); -#endif - regs.pc_p += (delta); -#if ENABLE_MON - uaecptr next_pc = m68k_getpc(); - if (IS_BREAK_POINT(next_pc)) { - printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc); - m68k_dumpstate(NULL); - const char *arg[4] = {"mon", "-m", "-r", NULL}; - mon(3, arg); - } -#endif // end of #if ENABLE_MON -} - /* These are only used by the 68020/68881 code, and therefore don't * need to handle prefetch. */ -static __inline__ uae_u32 next_ibyte (void) +static inline uae_u32 next_ibyte (void) { uae_u32 r = get_ibyte (0); m68k_incpc (2); return r; } -static __inline__ uae_u32 next_iword (void) +static inline uae_u32 next_iword (void) { uae_u32 r = get_iword (0); m68k_incpc (2); return r; } -static __inline__ uae_u32 next_ilong (void) +static inline uae_u32 next_ilong (void) { uae_u32 r = get_ilong (0); m68k_incpc (4); return r; } +static inline void m68k_setpc (uaecptr newpc) +{ +#ifndef FULLMMU + regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word); +#endif + regs.fault_pc = regs.pc = newpc; +} + #define m68k_setpc_fast m68k_setpc #define m68k_setpc_bcc m68k_setpc #define m68k_setpc_rte m68k_setpc -static __inline__ void m68k_do_rts(void) +static inline void m68k_do_rts(void) { - m68k_setpc(get_long(m68k_areg(regs, 7))); - m68k_areg(regs, 7) += 4; + m68k_setpc(get_long(m68k_areg(regs, 7))); + m68k_areg(regs, 7) += 4; } -static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) +static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) { - m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); - m68k_incpc(offset); + put_long(m68k_areg(regs, 7) - 4, oldpc); + m68k_areg(regs, 7) -= 4; + m68k_incpc(offset); } -static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest) +static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest) { - m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); - m68k_setpc(dest); + put_long(m68k_areg(regs, 7) - 4, oldpc); + m68k_areg(regs, 7) -= 4; + m68k_setpc(dest); } -static __inline__ void m68k_setstopped (int stop) +static inline void m68k_setstopped (int stop) { regs.stopped = stop; /* A traced STOP instruction drops through immediately without actually stopping. */ - if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0) - SPCFLAGS_SET( SPCFLAG_STOP ); + if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE ))) + SPCFLAGS_SET( SPCFLAG_STOP ); } -extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); -extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); +#ifdef FULLMMU +# define GET_OPCODE (get_iword (0)) +#elif defined ARAM_PAGE_CHECK +# ifdef HAVE_GET_WORD_UNSWAPPED +# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset))); +# else +# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset))); +# endif +#else +# ifdef HAVE_GET_WORD_UNSWAPPED +# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word))) +# else +# define GET_OPCODE (get_iword (0)) +# endif +#endif + +extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); +extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); +extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width); +extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width); + -extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf); extern void MakeSR (void); extern void MakeFromSR (void); @@ -360,15 +278,19 @@ extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); extern void m68k_mull (uae_u32, uae_u32, uae_u16); extern void m68k_emulop (uae_u32); extern void m68k_emulop_return (void); +extern void m68k_natfeat_id(void); +extern void m68k_natfeat_call(void); extern void init_m68k (void); extern void exit_m68k (void); -extern void m68k_dumpstate (uaecptr *); -extern void m68k_disasm (uaecptr, uaecptr *, int); +extern void m68k_dumpstate (FILE *, uaecptr *); +extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int); +extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int); +extern void showDisasm(uaecptr); extern void m68k_reset (void); extern void m68k_enter_debugger(void); extern int m68k_do_specialties(void); - -extern void mmu_op (uae_u32, uae_u16); +extern void m68k_instr_set(void); +uae_u32 linea68000(uae_u16 opcode); /* Opcode of faulting instruction */ extern uae_u16 last_op_for_exception_3; @@ -379,24 +301,19 @@ extern uaecptr last_fault_for_exception_3; #define CPU_OP_NAME(a) op ## a -/* 68020 + 68881 */ -extern struct cputbl op_smalltbl_0_ff[]; -/* 68020 */ -extern struct cputbl op_smalltbl_1_ff[]; -/* 68010 */ -extern struct cputbl op_smalltbl_2_ff[]; -/* 68000 */ -extern struct cputbl op_smalltbl_3_ff[]; -/* 68000 slow but compatible. */ -extern struct cputbl op_smalltbl_4_ff[]; +/* 68040+ 68881 */ +extern const struct cputbl op_smalltbl_0_ff[]; +extern const struct cputbl op_smalltbl_0_nf[]; -#if FLIGHT_RECORDER -extern void m68k_record_step(uaecptr) REGPARAM; +#ifdef FLIGHT_RECORDER +extern void m68k_record_step(uaecptr, int); #endif + extern void m68k_do_execute(void); extern void m68k_execute(void); -#if USE_JIT +#ifdef USE_JIT extern void m68k_compile_execute(void); +extern void m68k_do_compile_execute(void); #endif #ifdef USE_CPU_EMUL_SERVICES extern int32 emulated_ticks; @@ -411,5 +328,7 @@ static inline void cpu_check_ticks(void) #define cpu_check_ticks() #define cpu_do_check_ticks() #endif - + +cpuop_func op_illg_1; + #endif /* NEWCPU_H */ diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h index e87d22b4..e3b7a3a5 100644 --- a/BasiliskII/src/uae_cpu/noflags.h +++ b/BasiliskII/src/uae_cpu/noflags.h @@ -33,13 +33,13 @@ #define NOFLAGS_CMP 0 #undef SET_NFLG_ALWAYS -static __inline__ void SET_NFLG_ALWAYS(uae_u32 x) +static inline void SET_NFLG_ALWAYS(uae_u32 x) { SET_NFLG(x); /* This has not yet been redefined */ } #undef SET_CFLG_ALWAYS -static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) +static inline void SET_CFLG_ALWAYS(uae_u32 x) { SET_CFLG(x); /* This has not yet been redefined */ } @@ -62,13 +62,13 @@ static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) #define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0) #undef CLEAR_CZNV -#define CLEAR_CZNV() do {} while (0) +#define CLEAR_CZNV() #undef IOR_CZNV #define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0) #undef SET_CZNV #define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0) #undef COPY_CARRY -#define COPY_CARRY() do {} while (0) +#define COPY_CARRY() #ifdef optflag_testl #undef optflag_testl diff --git a/BasiliskII/src/uae_cpu/readcpu.cpp b/BasiliskII/src/uae_cpu/readcpu.cpp index 3fccdfb7..742e0be5 100644 --- a/BasiliskII/src/uae_cpu/readcpu.cpp +++ b/BasiliskII/src/uae_cpu/readcpu.cpp @@ -1,34 +1,30 @@ +/* 2002 MJ */ /* * UAE - The Un*x Amiga Emulator * * Read 68000 CPU specs from file "table68k" * * Copyright 1995,1996 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include - #include "sysdeps.h" #include "readcpu.h" +#include +#include +#include +#include + +using std::strncmp; +using std::abort; +using std::fprintf; +using std::strcmp; +using std::strlen; +using std::malloc; + int nr_cpuop_funcs; +struct instr *table68k; +static int readcpu_mismatch; struct mnemolookup lookuptab[] = { { i_ILLG, "ILLEGAL" }, @@ -153,16 +149,19 @@ struct mnemolookup lookuptab[] = { { i_CPUSHA, "CPUSHA" }, { i_MOVE16, "MOVE16" }, - { i_EMULOP_RETURN, "EMULOP_RETURN" }, - { i_EMULOP, "EMULOP" }, - + { i_EMULOP_RETURN, "EMULOP_RETURN" }, + { i_EMULOP, "EMULOP" }, + { i_MMUOP, "MMUOP" }, + + {i_NATFEAT_ID, "NATFEAT_ID" }, + {i_NATFEAT_CALL, "NATFEAT_CALL" }, + { i_ILLG, "" }, }; -struct instr *table68k; -static __inline__ amodes mode_from_str (const char *str) +static inline amodes mode_from_str (const char *str) { if (strncmp (str, "Dreg", 4) == 0) return Dreg; if (strncmp (str, "Areg", 4) == 0) return Areg; @@ -180,7 +179,7 @@ static __inline__ amodes mode_from_str (const char *str) return (amodes)0; } -static __inline__ amodes mode_from_mr (int mode, int reg) +static inline amodes mode_from_mr (int mode, int reg) { switch (mode) { case 0: return Dreg; @@ -215,31 +214,32 @@ static void build_insn (int insn) int i, n; int flaglive = 0, flagdead = 0; - int cflow = 0; + int cflow = 0; id = defs68k[insn]; - // Control flow information - cflow = id.cflow; - - // Mask of flags set/used - unsigned char flags_set(0), flags_used(0); - - for (i = 0, n = 4; i < 5; i++, n--) { - switch (id.flaginfo[i].flagset) { - case fa_unset: case fa_isjmp: break; - default: flags_set |= (1 << n); - } - - switch (id.flaginfo[i].flaguse) { - case fu_unused: case fu_isjmp: break; - default: flags_used |= (1 << n); - } + // Control flow information + cflow = id.cflow; + + // Mask of flags set/used + unsigned char flags_set(0), flags_used(0); + + for (i = 0, n = 4; i < 5; i++, n--) { + switch (id.flaginfo[i].flagset) { + case fa_unset: case fa_isjmp: break; + default: flags_set |= (1 << n); } - + + switch (id.flaginfo[i].flaguse) { + case fu_unused: case fu_isjmp: break; + default: flags_used |= (1 << n); + } + } + for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flagset){ case fa_unset: break; + case fa_isjmp: break; case fa_zero: flagdead |= 1 << i; break; case fa_one: flagdead |= 1 << i; break; case fa_dontcare: flagdead |= 1 << i; break; @@ -252,6 +252,8 @@ static void build_insn (int insn) for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flaguse) { case fu_unused: break; + case fu_isjmp: flaglive |= 1 << i; break; + case fu_maybecc: flaglive |= 1 << i; break; case fu_unknown: flaglive = -1; goto out2; case fu_used: flaglive |= 1 << i; break; } @@ -306,6 +308,7 @@ static void build_insn (int insn) continue; if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) continue; + if (bitcnt[bitE] && (bitval[bitE] == 0x00)) continue; @@ -346,9 +349,9 @@ static void build_insn (int insn) } } mnp++; - if ((unsigned)mnp >= sizeof(mnemonic) - 1) { - mnemonic[sizeof(mnemonic) - 1] = 0; - fprintf(stderr, "Instruction %s overflow\n", mnemonic); + if ((unsigned)mnp >= (sizeof(mnemonic)-1)) { + mnemonic[sizeof(mnemonic)-1] = '\0'; + fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic); abort(); } } @@ -379,6 +382,7 @@ static void build_insn (int insn) case 'A': srcmode = Areg; switch (opcstr[pos++]) { + case 'l': srcmode = absl; break; case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break; case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break; default: abort(); @@ -388,9 +392,11 @@ static void build_insn (int insn) case 'P': srcmode = Aipi; pos++; break; } break; +#if 0 case 'L': srcmode = absl; break; +#endif case '#': switch (opcstr[pos++]) { case 'z': srcmode = imm; break; @@ -436,7 +442,7 @@ static void build_insn (int insn) srcpos = bitpos[bitK]; } break; - case 'E': srcmode = immi; srcreg = bitval[bitE]; + case 'E': srcmode = immi; srcreg = bitval[bitE]; if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? /* 1..255 */ srcgather = 1; @@ -444,8 +450,8 @@ static void build_insn (int insn) srcpos = bitpos[bitE]; } break; - case 'p': srcmode = immi; srcreg = bitval[bitp]; - if (CPU_EMU_SIZE < 5) { + case 'p': srcmode = immi; srcreg = bitval[bitp]; + if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? /* 0..3 */ srcgather = 1; srctype = 7; @@ -582,21 +588,22 @@ static void build_insn (int insn) case 'A': destmode = Areg; switch (opcstr[pos++]) { + case 'l': destmode = absl; break; case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; - case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; + case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; default: abort(); } - if (dstpos < 0 || dstpos >= 32) - abort(); switch (opcstr[pos]) { case 'p': destmode = Apdi; pos++; break; case 'P': destmode = Aipi; pos++; break; } break; +#if 0 case 'L': destmode = absl; break; +#endif case '#': switch (opcstr[pos++]) { case 'z': destmode = imm; break; @@ -767,7 +774,7 @@ static void build_insn (int insn) table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; } #endif - + // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions if ( table68k[opc].mnemo == i_Scc || table68k[opc].mnemo == i_Bcc @@ -795,7 +802,7 @@ static void build_insn (int insn) case 15:flags_used = 0x0E; break; /* LE */ } } - + #if 1 /* gb-- flagdead and flaglive would not have correct information */ table68k[opc].flagdead = flags_set; @@ -811,22 +818,6 @@ static void build_insn (int insn) } -void read_table68k (void) -{ - int i; - - table68k = (struct instr *)malloc (65536 * sizeof (struct instr)); - for (i = 0; i < 65536; i++) { - table68k[i].mnemo = i_ILLG; - table68k[i].handler = -1; - } - for (i = 0; i < n_defs68k; i++) { - build_insn (i); - } -} - -static int mismatch; - static void handle_merges (long int opcode) { uae_u16 smsk; @@ -851,9 +842,9 @@ static void handle_merges (long int opcode) case 5: smsk = 63; sbitdst = 64; break; case 6: - smsk = 255; sbitdst = 256; break; + smsk = 255; sbitdst = 256; break; case 7: - smsk = 3; sbitdst = 4; break; + smsk = 3; sbitdst = 4; break; default: smsk = 0; sbitdst = 0; abort(); @@ -869,7 +860,7 @@ static void handle_merges (long int opcode) } for (srcreg=0; srcreg < sbitdst; srcreg++) { for (dstreg=0; dstreg < dstend; dstreg++) { - uae_u16 code = uae_u16(opcode); + uae_u16 code = opcode; code = (code & ~smsk) | (srcreg << table68k[opcode].spos); code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos); @@ -882,20 +873,20 @@ static void handle_merges (long int opcode) || table68k[code].suse != table68k[opcode].suse || table68k[code].duse != table68k[opcode].duse) { - mismatch++; continue; + readcpu_mismatch++; continue; } if (table68k[opcode].suse && (table68k[opcode].spos != table68k[code].spos || table68k[opcode].smode != table68k[code].smode || table68k[opcode].stype != table68k[code].stype)) { - mismatch++; continue; + readcpu_mismatch++; continue; } if (table68k[opcode].duse && (table68k[opcode].dpos != table68k[code].dpos || table68k[opcode].dmode != table68k[code].dmode)) { - mismatch++; continue; + readcpu_mismatch++; continue; } if (code != opcode) @@ -904,11 +895,11 @@ static void handle_merges (long int opcode) } } -void do_merges (void) +static void do_merges (void) { long int opcode; int nr = 0; - mismatch = 0; + readcpu_mismatch = 0; for (opcode = 0; opcode < 65536; opcode++) { if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG) continue; @@ -918,116 +909,26 @@ void do_merges (void) nr_cpuop_funcs = nr; } -int get_no_mismatches (void) -{ - return mismatch; -} -const char *get_instruction_name (unsigned int opcode) +void init_table68k (void) { - struct instr *ins = &table68k[opcode]; - for (int i = 0; lookuptab[i].name[0]; i++) { - if (ins->mnemo == lookuptab[i].mnemo) - return lookuptab[i].name; + int i; + + free(table68k); + table68k = (struct instr *)malloc (65536 * sizeof (struct instr)); + for (i = 0; i < 65536; i++) { + table68k[i].mnemo = i_ILLG; + table68k[i].handler = -1; } - abort(); - return NULL; -} - -static char *get_ea_string (amodes mode, wordsizes size) -{ - static char buffer[80]; - - buffer[0] = 0; - switch (mode){ - case Dreg: - strcpy (buffer,"Dn"); - break; - case Areg: - strcpy (buffer,"An"); - break; - case Aind: - strcpy (buffer,"(An)"); - break; - case Aipi: - strcpy (buffer,"(An)+"); - break; - case Apdi: - strcpy (buffer,"-(An)"); - break; - case Ad16: - strcpy (buffer,"(d16,An)"); - break; - case Ad8r: - strcpy (buffer,"(d8,An,Xn)"); - break; - case PC16: - strcpy (buffer,"(d16,PC)"); - break; - case PC8r: - strcpy (buffer,"(d8,PC,Xn)"); - break; - case absw: - strcpy (buffer,"(xxx).W"); - break; - case absl: - strcpy (buffer,"(xxx).L"); - break; - case imm: - switch (size){ - case sz_byte: - strcpy (buffer,"#.B"); - break; - case sz_word: - strcpy (buffer,"#.W"); - break; - case sz_long: - strcpy (buffer,"#.L"); - break; - default: - break; - } - break; - case imm0: - strcpy (buffer,"#.B"); - break; - case imm1: - strcpy (buffer,"#.W"); - break; - case imm2: - strcpy (buffer,"#.L"); - break; - case immi: - strcpy (buffer,"#"); - break; - - default: - break; + for (i = 0; i < n_defs68k; i++) { + build_insn (i); } - return buffer; + do_merges(); } -const char *get_instruction_string (unsigned int opcode) + +void exit_table68k (void) { - static char out[100]; - struct instr *ins; - - strcpy (out, get_instruction_name (opcode)); - - ins = &table68k[opcode]; - if (ins->size == sz_byte) - strcat (out,".B"); - if (ins->size == sz_word) - strcat (out,".W"); - if (ins->size == sz_long) - strcat (out,".L"); - strcat (out," "); - if (ins->suse) - strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size))); - if (ins->duse) { - if (ins->suse) - strcat (out,","); - strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size))); - } - return out; + free(table68k); + table68k = NULL; } diff --git a/BasiliskII/src/uae_cpu/readcpu.h b/BasiliskII/src/uae_cpu/readcpu.h index 6fba3c39..3bdc0cd6 100644 --- a/BasiliskII/src/uae_cpu/readcpu.h +++ b/BasiliskII/src/uae_cpu/readcpu.h @@ -1,16 +1,16 @@ -#ifndef READCPU_H -#define READCPU_H +#ifndef UAE_READCPU_H +#define UAE_READCPU_H #ifdef __cplusplus extern "C" { #endif -ENUMDECL { +typedef enum { Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r, absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg -} ENUMNAME (amodes); +} amodes; -ENUMDECL { +typedef enum { i_ILLG, i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR, @@ -35,43 +35,42 @@ ENUMDECL { i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES, i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE, i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16, - i_MMUOP, - i_EMULOP_RETURN, i_EMULOP -} ENUMNAME (instrmnem); + i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL +} instrmnem; extern struct mnemolookup { instrmnem mnemo; const char *name; } lookuptab[]; -ENUMDECL { +typedef enum { sz_byte, sz_word, sz_long -} ENUMNAME (wordsizes); +} wordsizes; -ENUMDECL { - fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp -} ENUMNAME (flagaffect); +typedef enum { + fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp, + fa_isbranch +} flagaffect; -ENUMDECL { +typedef enum { fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp -} ENUMNAME (flaguse); +} flaguse; -ENUMDECL { - fl_normal = 0, +typedef enum { + fl_normal = 0, fl_branch = 1, - fl_jump = 2, - fl_return = 3, - fl_trap = 4, - fl_const_jump = 8, - - /* Instructions that can trap don't mark the end of a block */ - fl_end_block = 3 -} ENUMNAME (cflow_t); + fl_jump = 2, + fl_return = 3, + fl_trap = 4, + fl_const_jump = 8, + /* Instructions that can trap don't mark the end of a block */ + fl_end_block = 3 +} cflow_t; -ENUMDECL { +typedef enum { bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK, bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit -} ENUMNAME (bitvals); +} bitvals; struct instr_def { unsigned int bits; @@ -84,7 +83,7 @@ struct instr_def { unsigned int flaguse:3; unsigned int flagset:3; } flaginfo[5]; - unsigned char cflow; + unsigned char cflow; unsigned char sduse; const char *opcstr; }; @@ -103,28 +102,24 @@ extern struct instr { unsigned int mnemo:8; unsigned int cc:4; unsigned int plev:2; - unsigned int size:2; - unsigned int smode:5; + wordsizes size:2; + amodes smode:5; unsigned int stype:3; - unsigned int dmode:5; + amodes dmode:5; unsigned int suse:1; unsigned int duse:1; unsigned int unused1:1; unsigned int clev:3; - unsigned int cflow:3; + unsigned int cflow:3; unsigned int unused2:2; } *table68k; -extern void read_table68k (void); -extern void do_merges (void); -extern int get_no_mismatches (void); +extern void init_table68k(void); +extern void exit_table68k(void); extern int nr_cpuop_funcs; -extern const char *get_instruction_name (unsigned int opcode); -extern const char *get_instruction_string (unsigned int opcode); - #ifdef __cplusplus } #endif -#endif /* READCPU_H */ +#endif diff --git a/BasiliskII/src/uae_cpu/readcpua.cpp b/BasiliskII/src/uae_cpu/readcpua.cpp new file mode 100644 index 00000000..521c241f --- /dev/null +++ b/BasiliskII/src/uae_cpu/readcpua.cpp @@ -0,0 +1,5 @@ +/* + * readcpu.cpp must be compiled twice, once for the generator program + * and once for the actual executable + */ +#include "readcpu.cpp" diff --git a/BasiliskII/src/uae_cpu/registers.h b/BasiliskII/src/uae_cpu/registers.h new file mode 100644 index 00000000..c3459719 --- /dev/null +++ b/BasiliskII/src/uae_cpu/registers.h @@ -0,0 +1,116 @@ +/* 2001 MJ */ + +#ifndef REGISTERS_H +#define REGISTERS_H + +#include "sysdeps.h" +#include "spcflags.h" +typedef char flagtype; + + +struct xttrx { + uae_u32 log_addr_base : 8; + uae_u32 log_addr_mask : 8; + uae_u32 enable : 1; + uae_u32 s_field : 2; + uae_u32 : 3; + uae_u32 usr1 : 1; + uae_u32 usr0 : 1; + uae_u32 : 1; + uae_u32 cmode : 2; + uae_u32 : 2; + uae_u32 write : 1; + uae_u32 : 2; +}; + +struct mmusr_t { + uae_u32 phys_addr : 20; + uae_u32 bus_err : 1; + uae_u32 global : 1; + uae_u32 usr1 : 1; + uae_u32 usr0 : 1; + uae_u32 super : 1; + uae_u32 cmode : 2; + uae_u32 modif : 1; + uae_u32 : 1; + uae_u32 write : 1; + uae_u32 ttrhit : 1; + uae_u32 resident : 1; +}; + +struct log_addr4 { + uae_u32 rif : 7; + uae_u32 pif : 7; + uae_u32 paif : 6; + uae_u32 poff : 12; +}; + +struct log_addr8 { + uae_u32 rif : 7; + uae_u32 pif : 7; + uae_u32 paif : 5; + uae_u32 poff : 13; +}; + +extern struct regstruct +{ + uae_u32 regs[16]; + uaecptr usp,isp,msp; + uae_u16 sr; + flagtype t1; + flagtype t0; + flagtype s; + flagtype m; + flagtype x; + flagtype stopped; + int intmask; + + uae_u32 pc; + uae_u32 fault_pc; + uae_u8 *pc_p; + uae_u8 *pc_oldp; + + uae_u32 vbr,sfc,dfc; + + volatile uae_u32 spcflags; + +#if 0 + uae_u32 kick_mask; + + /* Fellow sources say this is 4 longwords. That's impossible. It needs + * to be at least a longword. The HRM has some cryptic comment about two + * instructions being on the same longword boundary. + * The way this is implemented now seems like a good compromise. + */ + uae_u32 prefetch; +#endif + + /* MMU reg*/ + uae_u32 urp,srp; + uae_u32 tc; + + int mmu_enabled; /* flagtype tce; */ + int mmu_pagesize_8k; /* flagtype tcp; */ + + uae_u32 dtt0,dtt1,itt0,itt1; + uae_u32 mmusr; + + uae_u32 mmu_fslw, mmu_fault_addr; + uae_u16 mmu_ssw; + uae_u32 wb3_data; + uae_u16 wb3_status; + + /* Cache reg*/ + uae_u32 cacr,caar; +} regs; + +static inline uaecptr m68k_getpc (void) +{ +#ifdef FULLMMU + return regs.pc; +#else + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); +#endif +} + +#endif diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h index 3c3fc032..eb465e72 100644 --- a/BasiliskII/src/uae_cpu/spcflags.h +++ b/BasiliskII/src/uae_cpu/spcflags.h @@ -1,92 +1,78 @@ -/* - * UAE - The Un*x Amiga Emulator - * - * MC68000 emulation - * - * Copyright 1995 Bernd Schmidt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * Copyright 1995 Bernd Schmidt + */ #ifndef SPCFLAGS_H #define SPCFLAGS_H -typedef uae_u32 spcflags_t; +#if 0 +#include "SDL_compat.h" +#endif enum { - SPCFLAG_STOP = 0x01, - SPCFLAG_INT = 0x02, - SPCFLAG_BRK = 0x04, - SPCFLAG_TRACE = 0x08, - SPCFLAG_DOTRACE = 0x10, - SPCFLAG_DOINT = 0x20, -#if USE_JIT - SPCFLAG_JIT_END_COMPILE = 0x40, - SPCFLAG_JIT_EXEC_RETURN = 0x80, + SPCFLAG_STOP = 0x01, +#if 0 + SPCFLAG_INTERNAL_IRQ = 0x02, #else - SPCFLAG_JIT_END_COMPILE = 0, - SPCFLAG_JIT_EXEC_RETURN = 0, + SPCFLAG_INT = 0x02, #endif - - SPCFLAG_ALL = SPCFLAG_STOP - | SPCFLAG_INT - | SPCFLAG_BRK - | SPCFLAG_TRACE - | SPCFLAG_DOTRACE - | SPCFLAG_DOINT - | SPCFLAG_JIT_END_COMPILE - | SPCFLAG_JIT_EXEC_RETURN - , - + SPCFLAG_BRK = 0x04, + SPCFLAG_TRACE = 0x08, + SPCFLAG_DOTRACE = 0x10, + SPCFLAG_DOINT = 0x20, +#ifdef USE_JIT + SPCFLAG_JIT_END_COMPILE = 0x40, + SPCFLAG_JIT_EXEC_RETURN = 0x80, +#else + SPCFLAG_JIT_END_COMPILE = 0, + SPCFLAG_JIT_EXEC_RETURN = 0, +#endif + SPCFLAG_VBL = 0x100, + SPCFLAG_MFP = 0x200, + SPCFLAG_INT3 = 0x800, + SPCFLAG_INT5 = 0x1000, + SPCFLAG_SCC = 0x2000, +// SPCFLAG_MODE_CHANGE = 0x4000, + SPCFLAG_ALL = SPCFLAG_STOP +#if 0 + | SPCFLAG_INTERNAL_IRQ +#else + | SPCFLAG_INT +#endif + | SPCFLAG_BRK + | SPCFLAG_TRACE + | SPCFLAG_DOTRACE + | SPCFLAG_DOINT + | SPCFLAG_JIT_END_COMPILE + | SPCFLAG_JIT_EXEC_RETURN + | SPCFLAG_INT3 + | SPCFLAG_VBL + | SPCFLAG_INT5 + | SPCFLAG_SCC + | SPCFLAG_MFP + , + SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN + }; +#if 0 +#define SPCFLAGS_TEST(m) \ + (regs.spcflags & (m)) +#else #define SPCFLAGS_TEST(m) \ ((regs.spcflags & (m)) != 0) +#endif /* Macro only used in m68k_reset() */ #define SPCFLAGS_INIT(m) do { \ regs.spcflags = (m); \ } while (0) -#if !(ENABLE_EXCLUSIVE_SPCFLAGS) - -#define SPCFLAGS_SET(m) do { \ - regs.spcflags |= (m); \ -} while (0) - -#define SPCFLAGS_CLEAR(m) do { \ - regs.spcflags &= ~(m); \ -} while (0) - -#elif defined(X86_ASSEMBLY) - -#define HAVE_HARDWARE_LOCKS - -#define SPCFLAGS_SET(m) do { \ - __asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \ -} while (0) - -#define SPCFLAGS_CLEAR(m) do { \ - __asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \ -} while (0) - -#else - -#undef HAVE_HARDWARE_LOCKS - #include "main.h" extern B2_mutex *spcflags_lock; @@ -99,9 +85,91 @@ extern B2_mutex *spcflags_lock; #define SPCFLAGS_CLEAR(m) do { \ B2_lock_mutex(spcflags_lock); \ regs.spcflags &= ~(m); \ - B2_unlock_mutex(spcflags_lock); \ + B2_unlock_mutex(spcflags_lock); \ } while (0) +#define SleepAndWait() usleep(1000); + +#if 0 +#ifndef ENABLE_EXCLUSIVE_SPCFLAGS + +#define SPCFLAGS_SET(m) do { \ + regs.spcflags |= (m); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + regs.spcflags &= ~(m); \ +} while (0) + +#if 0 +#define SleepAndWait() usleep(1000) +#endif + +#elif defined(X86_ASSEMBLY) +// #elif (defined(CPU_i386) || defined(CPU_x86_64)) && defined(X86_ASSEMBLY) && !defined(ENABLE_REALSTOP) + +// #define HAVE_HARDWARE_LOCKS 1 +#define HAVE_HARDWARE_LOCKS + +#define SPCFLAGS_SET(m) do { \ + __asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + __asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \ +} while (0) + +// #define SleepAndWait() usleep(1000) + +// #elif !defined(ENABLE_REALSTOP) + +// #undef HAVE_HARDWARE_LOCKS +// extern SDL_mutex *spcflags_lock; + +// #define SPCFLAGS_SET(m) do { \ +// SDL_LockMutex(spcflags_lock); \ +// regs.spcflags |= (m); \ +// SDL_UnlockMutex(spcflags_lock); \ +// } while (0) + +// #define SPCFLAGS_CLEAR(m) do { \ +// SDL_LockMutex(spcflags_lock); \ +// regs.spcflags &= ~(m); \ +// SDL_UnlockMutex(spcflags_lock); \ +// } while (0) + +// #define SleepAndWait() usleep(1000) + +#else +/// Full STOP instruction implementation (default configuration) + +#undef HAVE_HARDWARE_LOCKS +#if 0 +extern SDL_mutex *spcflags_lock; +extern SDL_cond *stop_condition; + +#define SPCFLAGS_SET(m) do { \ + SDL_LockMutex(spcflags_lock); \ + regs.spcflags |= (m); \ + if (regs.spcflags & SPCFLAG_STOP) \ + SDL_CondSignal(stop_condition); \ + SDL_UnlockMutex(spcflags_lock); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + SDL_LockMutex(spcflags_lock); \ + regs.spcflags &= ~(m); \ + SDL_UnlockMutex(spcflags_lock); \ +} while (0) + +#define SleepAndWait() do { \ + SDL_LockMutex(spcflags_lock); \ + SDL_CondWait(stop_condition, spcflags_lock); \ + SDL_UnlockMutex(spcflags_lock); \ +} while (0) +#endif + +#endif #endif #endif /* SPCFLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/table68k b/BasiliskII/src/uae_cpu/table68k index ab9eabe1..7405bd31 100644 --- a/BasiliskII/src/uae_cpu/table68k +++ b/BasiliskII/src/uae_cpu/table68k @@ -10,7 +10,7 @@ % J: immediate 0..15 % k: immediate 0..7 % K: immediate 0..63 -% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field) +% p: immediate 0..3 (CINV and CPUSH: cache field) % s: source mode % S: source reg % d: dest mode @@ -28,14 +28,15 @@ % ArP: --> (Ar)+ % L: --> (xxx.L) % -% Fields on a line: -% 16 chars bitpattern : -% CPU level / privilege level : +% Fields on a line: +% 16 chars bitpattern : +% CPU level / privildge level : % CPU level 0: 68000 % 1: 68010 % 2: 68020 % 3: 68020/68881 % 4: 68040 +% 5: 68060 % privilege level 0: not privileged % 1: unprivileged only on 68000 (check regs.s) % 2: privileged (check regs.s) @@ -46,8 +47,10 @@ % 0 means flag reset % 1 means flag set % ? means programmer was too lazy to check or instruction may trap -% everything else means flag set/used +% + means instruction is conditional branch (ignored, only for sync) +% / means instruction is unconditional branch/call (ignored, only for sync) % x means flag is unknown and well-behaved programs shouldn't check it +% everything else means flag set/used % % Control flow % two letters, combination of @@ -108,7 +111,7 @@ 0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg] 0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg] -0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg] +0100 0000 zzdd dDDD:00:XNZVC:X-Z--:--:30: NEGX.z d[!Areg] 0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg] 0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg] 0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg] @@ -119,13 +122,13 @@ 0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2 0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg] 0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k -0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] +0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] 0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] +0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] 0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] -0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] +0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] 0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] -0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] +0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] 0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s 0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg] 0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL @@ -148,21 +151,24 @@ 0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR 0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1 0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1 -0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1110 10ss sSSS:00://///://///:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] 0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr 0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr -0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1110 11ss sSSS:00://///://///:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] 0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar -0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] -0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] +% This variant of ADDQ is word and long sized only +0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] +0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] 0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg] -0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] -0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] + +% This variant of SUBQ is word and long sized only +0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] +0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] 0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg] -0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1 -0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg] +0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1 +0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg] 0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1 0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2 0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc @@ -170,30 +176,30 @@ % Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal % instruction exceptions when compiling a 68000 only emulation, which isn't % what we want either. -0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1 -0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i -0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2 -0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1 -0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i -0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2 +0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1 +0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i +0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2 +0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1 +0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i +0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2 0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr 1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr 1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp +1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Dreg],Dr +1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp 1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg] -1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr -1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp -1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr -1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp 1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr 1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr 1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp 1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg] 1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar @@ -205,18 +211,18 @@ 1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr 1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp +1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Dreg],Dr +1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp 1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] -1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] +1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] 1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr 1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr 1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp 1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg] 1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar @@ -224,8 +230,8 @@ 1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR 1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR 1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR -1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR -1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR +1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR +1110 rrrf zz10 1RRR:00:XNZ0C:X----:--:13: LSf.z Dr,DR 1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR 1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR 1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg] @@ -255,7 +261,6 @@ 1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] % 68040 instructions -1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s 1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar 1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar 1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p @@ -264,11 +269,19 @@ 1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p % destination register number is encoded in the following word 1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP -1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L -1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi] -1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L -1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind] +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi] +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind] -% EmulOp instructions -0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN -0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E +% MMU disabled +% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s + +% EmulOp instructions (used by linux68k) +0111 0001 0000 0000:02:-----:XNZVC:-R:00: EMULOP_RETURN +0111 0001 EEEE EEEE:00:-----:XNZVC:-J:10: EMULOP #E + +% NatFea instructions (do I have the srcaddr correct?) +% NatFeat disabled +% 0111 0011 0000 0000:00:-----:XNZVC:-J:00: NATFEAT_ID +% 0111 0011 0000 0001:00:-----:XNZVC:-J:00: NATFEAT_CALL From 67dd2e6676cc16a89595626b61e8468da0466e58 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 12 Jan 2020 09:45:10 -0600 Subject: [PATCH 15/20] Disable PIE, add sanity check for >4GB --- BasiliskII/src/CrossPlatform/vm_alloc.cpp | 7 +++++++ BasiliskII/src/Unix/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/BasiliskII/src/CrossPlatform/vm_alloc.cpp b/BasiliskII/src/CrossPlatform/vm_alloc.cpp index d529337f..15c110d0 100644 --- a/BasiliskII/src/CrossPlatform/vm_alloc.cpp +++ b/BasiliskII/src/CrossPlatform/vm_alloc.cpp @@ -196,6 +196,13 @@ void * vm_acquire(size_t size, int options) errno = vm_error(ret_code); return VM_MAP_FAILED; } + + // Sanity checks for 64-bit platforms + if (sizeof(void *) > 4 && (options & VM_MAP_32BIT) && !(((char *)addr + size) <= (char *)0xffffffff)) + { + vm_release(addr, size); + return VM_MAP_FAILED; + } #elif defined(HAVE_MMAP_VM) int fd = zero_fd; int the_map_flags = translate_map_flags(options) | map_flags; diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index 0711d0d7..12c81e38 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -110,7 +110,7 @@ target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SD # set(CMAKE_POSITION_INDEPENDENT_CODE OFF) -SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 0x2000" ) +SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 0x2000 -Wl,-no_pie" ) add_definitions(-march=native) From 9dc485c56a59d0e82ef481dcfdfb6245e68de86e Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 12 Jan 2020 09:50:04 -0600 Subject: [PATCH 16/20] Sync with latest ARAnyM changes --- .../src/uae_cpu/compiler/codegen_arm.cpp | 23 +- .../src/uae_cpu/compiler/codegen_x86.cpp | 97 ++-- BasiliskII/src/uae_cpu/compiler/compemu.h | 7 + .../uae_cpu/compiler/compemu_midfunc_arm.cpp | 4 + .../uae_cpu/compiler/compemu_midfunc_x86.cpp | 21 +- .../uae_cpu/compiler/compemu_midfunc_x86.h | 7 +- .../src/uae_cpu/compiler/compemu_support.cpp | 507 ++++++++++++++---- BasiliskII/src/uae_cpu/compiler/gencomp.c | 196 ++++--- BasiliskII/src/uae_cpu/gencpu.c | 25 +- BasiliskII/src/uae_cpu/m68k.h | 4 + BasiliskII/src/uae_cpu/memory-uae.h | 2 +- BasiliskII/src/uae_cpu/newcpu.cpp | 61 ++- BasiliskII/src/uae_cpu/newcpu.h | 1 + BasiliskII/src/uae_cpu/registers.h | 3 +- 14 files changed, 696 insertions(+), 262 deletions(-) diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp index 01c49e30..334ae753 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp @@ -1961,9 +1961,9 @@ static inline void raw_pop_preserved_regs(void) { // Verify!!! /* FLAGX is byte sized, and we *do* write it at that size */ -static inline void raw_load_flagx(uae_u32 t, uae_u32 r) +static inline void raw_load_flagx(uae_u32 t) { - raw_mov_l_rm(t,(uintptr)live.state[r].mem); + raw_mov_l_rm(t,(uintptr)live.state[FLAGX].mem); } static inline void raw_flags_evicted(int r) @@ -2007,9 +2007,9 @@ static inline void raw_reg_to_flags(int r) /* Apparently, there are enough instructions between flag store and flag reload to avoid the partial memory stall */ -static inline void raw_load_flagreg(uae_u32 t, uae_u32 r) +static inline void raw_load_flagreg(uae_u32 t) { - raw_mov_l_rm(t,(uintptr)live.state[r].mem); + raw_mov_l_rm(t,(uintptr)live.state[FLAGTMP].mem); } /* %eax register is clobbered if target processor doesn't support fucomi */ @@ -2606,12 +2606,14 @@ static inline void compemu_raw_call(uae_u32 t) #endif } +#if defined(UAE) static inline void compemu_raw_call_r(RR4 r) { PUSH(RLR_INDEX); // push {lr} BLX_r(r); // blx r0 POP(RLR_INDEX); // pop {lr} } +#endif static inline void compemu_raw_jcc_l_oponly(int cc) { @@ -2706,7 +2708,18 @@ static inline void compemu_raw_jz_b_oponly(void) LDRSB_rRI(REG_WORK1, RPC_INDEX, 3); // ldrsb r2,[pc,#3] ADD_rrr(RPC_INDEX, RPC_INDEX, REG_WORK1); // add pc,pc,r2 - skip_n_bytes(3); + skip_n_bytes(3); /* additionally 1 byte skipped by generic code */ + + // +} + +static inline void compemu_raw_jnz_b_oponly(void) +{ + BEQ_i(2); // beq jp + LDRSB_rRI(REG_WORK1, RPC_INDEX, 3); // ldrsb r2,[pc,#3] + ADD_rrr(RPC_INDEX, RPC_INDEX, REG_WORK1); // add pc,pc,r2 + + skip_n_bytes(3); /* additionally 1 byte skipped by generic code */ // } diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp index 573f2f9a..22c01080 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp @@ -267,6 +267,7 @@ static inline void x86_64_prefix( #define compemu_raw_jmp_r(a) raw_jmp_r(a) #define compemu_raw_jnz(a) raw_jnz(a) #define compemu_raw_jz_b_oponly() raw_jz_b_oponly() +#define compemu_raw_jnz_b_oponly() raw_jnz_b_oponly() #define compemu_raw_lea_l_brr(a,b,c) raw_lea_l_brr(a,b,c) #define compemu_raw_lea_l_brr_indexed(a,b,c,d,e) raw_lea_l_brr_indexed(a,b,c,d,e) #define compemu_raw_mov_b_mr(a,b) raw_mov_b_mr(a,b) @@ -921,6 +922,11 @@ LOWFUNC(WRITE,NONE,2,raw_test_b_rr,(R1 d, R1 s)) TESTBrr(s, d); } +LOWFUNC(WRITE,READ,2,raw_test_b_mi,(IMM d, IMM s)) +{ + ADDR32 TESTBim(s, d, X86_NOREG, X86_NOREG, 1); +} + LOWFUNC(WRITE,NONE,2,raw_xor_l_ri,(RW4 d, IMM i)) { XORLir(i, d); @@ -1185,47 +1191,38 @@ static inline void raw_jmp(uae_u32 t) ADDR32 JMPm(t); } -static inline void raw_jl(uae_u32 t) -{ - emit_byte(0x0f); - emit_byte(0x8c); - emit_long(t-(uintptr)target-4); -} - -static inline void raw_jz(uae_u32 t) -{ - emit_byte(0x0f); - emit_byte(0x84); - emit_long(t-(uintptr)target-4); -} - -static inline void raw_jnz(uae_u32 t) -{ - emit_byte(0x0f); - emit_byte(0x85); - emit_long(t-(uintptr)target-4); -} - -static inline void raw_jnz_l_oponly(void) -{ - emit_byte(0x0f); - emit_byte(0x85); -} - static inline void raw_jcc_l_oponly(int cc) { emit_byte(0x0f); emit_byte(0x80+cc); } -static inline void raw_jnz_b_oponly(void) +static inline void raw_jz_l_oponly(void) { - emit_byte(0x75); + raw_jcc_l_oponly(NATIVE_CC_EQ); } -static inline void raw_jz_b_oponly(void) +static inline void raw_jnz_l_oponly(void) { - emit_byte(0x74); + raw_jcc_l_oponly(NATIVE_CC_NE); +} + +static inline void raw_jl(uae_u32 t) +{ + raw_jcc_l_oponly(NATIVE_CC_LT); + emit_long(t-(uintptr)target-4); +} + +static inline void raw_jz(uae_u32 t) +{ + raw_jz_l_oponly(); + emit_long(t-(uintptr)target-4); +} + +static inline void raw_jnz(uae_u32 t) +{ + raw_jnz_l_oponly(); + emit_long(t-(uintptr)target-4); } static inline void raw_jcc_b_oponly(int cc) @@ -1233,6 +1230,16 @@ static inline void raw_jcc_b_oponly(int cc) emit_byte(0x70+cc); } +static inline void raw_jnz_b_oponly(void) +{ + raw_jcc_b_oponly(NATIVE_CC_NE); +} + +static inline void raw_jz_b_oponly(void) +{ + raw_jcc_b_oponly(NATIVE_CC_EQ); +} + static inline void raw_jmp_l_oponly(void) { emit_byte(0xe9); @@ -1356,7 +1363,7 @@ static inline void raw_flags_evicted(int r) live.nat[r].nholds=0; } -#define FLAG_NREG1_FLAGREG 0 /* Set to -1 if any register will do */ +#define FLAG_NREG1_FLAGREG EAX_INDEX /* Set to -1 if any register will do */ static inline void raw_flags_to_reg_FLAGREG(int r) { raw_lahf(0); /* Most flags in AH */ @@ -1370,14 +1377,14 @@ static inline void raw_flags_to_reg_FLAGREG(int r) #endif } -#define FLAG_NREG2_FLAGREG 0 /* Set to -1 if any register will do */ +#define FLAG_NREG2_FLAGREG EAX_INDEX /* Set to -1 if any register will do */ static inline void raw_reg_to_flags_FLAGREG(int r) { raw_cmp_b_ri(r,-127); /* set V */ raw_sahf(0); } -#define FLAG_NREG3_FLAGREG 0 /* Set to -1 if any register will do */ +#define FLAG_NREG3_FLAGREG EAX_INDEX /* Set to -1 if any register will do */ static __inline__ void raw_flags_set_zero_FLAGREG(int s, int tmp) { raw_mov_l_rr(tmp,s); @@ -1429,7 +1436,7 @@ static inline void raw_flags_init_FLAGSTK(void) { } /* Try to use the LAHF/SETO method on x86_64 since it is faster. This can't be the default because some older CPUs don't support LAHF/SAHF in long mode. */ -static int FLAG_NREG1_FLAGGEN = 0; +static int FLAG_NREG1_FLAGGEN = EAX_INDEX; static inline void raw_flags_to_reg_FLAGGEN(int r) { if (have_lahf_lm) { @@ -1448,7 +1455,7 @@ static inline void raw_flags_to_reg_FLAGGEN(int r) raw_flags_to_reg_FLAGSTK(r); } -static int FLAG_NREG2_FLAGGEN = 0; +static int FLAG_NREG2_FLAGGEN = EAX_INDEX; static inline void raw_reg_to_flags_FLAGGEN(int r) { if (have_lahf_lm) { @@ -1460,7 +1467,7 @@ static inline void raw_reg_to_flags_FLAGGEN(int r) raw_reg_to_flags_FLAGSTK(r); } -static int FLAG_NREG3_FLAGGEN = 0; +static int FLAG_NREG3_FLAGGEN = EAX_INDEX; static inline void raw_flags_set_zero_FLAGGEN(int s, int tmp) { if (have_lahf_lm) @@ -1474,12 +1481,12 @@ static inline void raw_flags_init_FLAGGEN(void) if (have_lahf_lm) { FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGREG; FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGREG; - FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGREG; + FLAG_NREG3_FLAGGEN = FLAG_NREG3_FLAGREG; } else { FLAG_NREG1_FLAGGEN = FLAG_NREG1_FLAGSTK; FLAG_NREG2_FLAGGEN = FLAG_NREG2_FLAGSTK; - FLAG_NREG1_FLAGGEN = FLAG_NREG3_FLAGSTK; + FLAG_NREG3_FLAGGEN = FLAG_NREG3_FLAGSTK; } } #endif @@ -1506,23 +1513,23 @@ static inline void raw_flags_init_FLAGGEN(void) /* Apparently, there are enough instructions between flag store and flag reload to avoid the partial memory stall */ -static inline void raw_load_flagreg(uae_u32 target, uae_u32 r) +static inline void raw_load_flagreg(uae_u32 target) { /* attention: in 64bit mode, relies on LITTE_ENDIANESS of regflags.cznv */ - raw_mov_l_rm(target,(uintptr)live.state[r].mem); + raw_mov_l_rm(target,(uintptr)live.state[FLAGTMP].mem); } -static inline void raw_load_flagx(uae_u32 target, uae_u32 r) +static inline void raw_load_flagx(uae_u32 target) { #if FLAGBIT_X < 8 if (live.nat[target].canbyte) - raw_mov_b_rm(target,(uintptr)live.state[r].mem); + raw_mov_b_rm(target,(uintptr)live.state[FLAGX].mem); else #endif if (live.nat[target].canword) - raw_mov_w_rm(target,(uintptr)live.state[r].mem); + raw_mov_w_rm(target,(uintptr)live.state[FLAGX].mem); else - raw_mov_l_rm(target,(uintptr)live.state[r].mem); + raw_mov_l_rm(target,(uintptr)live.state[FLAGX].mem); } static inline void raw_dec_sp(int off) diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h index 10a97d14..62ee94e4 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -169,6 +169,7 @@ extern void compiler_exit(void); extern bool compiler_use_jit(void); #endif extern void flush(int save_regs); +void flush_reg(int reg); extern void set_target(uae_u8* t); extern uae_u8* get_target(void); #ifdef UAE @@ -279,6 +280,7 @@ typedef struct { uae_u8 needflush; } freg_status; +#define SP_REG 15 #define PC_P 16 #define FLAGX 17 #define FLAGTMP 18 @@ -427,6 +429,11 @@ extern void sync_m68k_pc(void); extern uae_u32 get_const(int r); extern int is_const(int r); extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond); +void compemu_make_sr(int sr, int tmp); +void compemu_enter_super(int sr); +void compemu_exc_make_frame(int format, int sr, int currpc, int nr, int tmp); +void compemu_bkpt(void); +extern bool disasm_this_inst; #define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1)) #define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o))) diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp index 4fa745b4..aa9a7181 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp @@ -1676,6 +1676,7 @@ MIDFUNC(2,xor_b,(RW1 d, RR1 s)) unlock2(s); } +#if defined(UAE) MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) { clobber_flags(); @@ -1689,7 +1690,9 @@ MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) prepare_for_call_2(); compemu_raw_call_r(r); } +#endif +#if defined(UAE) MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) { clobber_flags(); @@ -1725,6 +1728,7 @@ MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) live.state[out1].dirtysize=osize; set_status(out1,DIRTY); } +#endif MIDFUNC(0,nop,(void)) { diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp index c322e590..8d35c1b9 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp @@ -1718,19 +1718,19 @@ MIDFUNC(2,mov_b_ri,(W1 d, IMM s)) MIDFUNC(2,add_l_mi,(IMM d, IMM s)) { CLOBBER_ADD; - raw_add_l_mi(d,s) ; + raw_add_l_mi(d,s); } MIDFUNC(2,add_w_mi,(IMM d, IMM s)) { CLOBBER_ADD; - raw_add_w_mi(d,s) ; + raw_add_w_mi(d,s); } MIDFUNC(2,add_b_mi,(IMM d, IMM s)) { CLOBBER_ADD; - raw_add_b_mi(d,s) ; + raw_add_b_mi(d,s); } MIDFUNC(2,test_l_ri,(RR4 d, IMM i)) @@ -1775,6 +1775,11 @@ MIDFUNC(2,test_b_rr,(RR1 d, RR1 s)) unlock2(s); } +MIDFUNC(2,test_b_mi,(IMM d, IMM s)) +{ + CLOBBER_TEST; + raw_test_b_mi(d,s); +} MIDFUNC(2,and_l_ri,(RW4 d, IMM i)) { @@ -2215,6 +2220,7 @@ MIDFUNC(2,xor_b,(RW1 d, RR1 s)) unlock2(s); } +#ifdef UAE MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) { clobber_flags(); @@ -2260,7 +2266,9 @@ MIDFUNC(5,call_r_11,(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize)) live.state[out1].dirtysize=osize; set_status(out1,DIRTY); } +#endif +#if defined(UAE) MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) { clobber_flags(); @@ -2286,6 +2294,7 @@ MIDFUNC(5,call_r_02,(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2)) raw_inc_sp(8); #endif } +#endif /* forget_about() takes a mid-layer register */ MIDFUNC(1,forget_about,(W4 r)) @@ -2821,3 +2830,9 @@ static inline void write_jmp_target(uae_u32 *jmpaddr, cpuop_func* a) { static inline void emit_jmp_target(uae_u32 a) { emit_long(a-((uintptr)target+4)); } + + +void compemu_bkpt(void) +{ + emit_byte(0xcc); +} diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h index 8476d947..82b75415 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h @@ -141,13 +141,14 @@ DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s)); DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s)); DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s)); DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s)); -DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s) ); -DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s) ); -DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s) ); +DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s)); +DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s)); DECLARE_MIDFUNC(test_l_ri(RR4 d, IMM i)); DECLARE_MIDFUNC(test_l_rr(RR4 d, RR4 s)); DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s)); DECLARE_MIDFUNC(test_b_rr(RR1 d, RR1 s)); +DECLARE_MIDFUNC(test_b_mi(IMM d, IMM s)); DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i)); DECLARE_MIDFUNC(and_l(RW4 d, RR4 s)); DECLARE_MIDFUNC(and_w(RW2 d, RR2 s)); diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index 8932e61d..d21f1c36 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -231,7 +231,7 @@ void jit_abort(const char *format, ...) #ifdef RECORD_REGISTER_USAGE static uint64 reg_count[16]; -static int reg_count_local[16]; +static uint64 reg_count_local[16]; static int reg_count_compare(const void *ap, const void *bp) { @@ -455,13 +455,8 @@ static void unlock2(int r); static void setlock(int r); static int readreg_specific(int r, int size, int spec); static int writereg_specific(int r, int size, int spec); -static void prepare_for_call_1(void); -static void prepare_for_call_2(void); -static void align_target(uae_u32 a); -static void inline flush_cpu_icache(void *from, void *to); static void inline write_jmp_target(uae_u32 *jmpaddr, cpuop_func* a); -static void inline emit_jmp_target(uae_u32 a); uae_u32 m68k_pc_offset; @@ -538,7 +533,9 @@ static inline blockinfo* get_blockinfo_addr(void* addr) #endif // #include "disasm-glue.h" -#ifdef JIT_DEBUG +bool disasm_this_inst; + +#if defined(JIT_DEBUG) || (defined(HAVE_DISASM_NATIVE) && defined(HAVE_DISASM_M68K)) static void disasm_block(int disasm_target, const uint8 *start, size_t length) { UNUSED(start); @@ -606,7 +603,7 @@ static inline void disasm_m68k_block(const uint8 *start, size_t length) disasm_block(TARGET_M68K, start, length); } #endif -#endif +#endif /* WINUAE_ARANYM */ /******************************************************************* @@ -1552,9 +1549,9 @@ static inline void log_visused(int r) static inline void do_load_reg(int n, int r) { if (r == FLAGTMP) - raw_load_flagreg(n, r); + raw_load_flagreg(n); else if (r == FLAGX) - raw_load_flagx(n, r); + raw_load_flagx(n); else compemu_raw_mov_l_rm(n, (uintptr) live.state[r].mem); } @@ -1775,6 +1772,7 @@ static inline void disassociate(int r) evict(r); } +/* XXFIXME: val may be 64bit address for PC_P */ static inline void set_const(int r, uae_u32 val) { disassociate(r); @@ -2591,6 +2589,80 @@ static inline int f_writereg(int r) return answer; } +/******************************************************************** + * Support functions, internal * + ********************************************************************/ + + +static void align_target(uae_u32 a) +{ + if (!a) + return; + + if (tune_nop_fillers) + raw_emit_nop_filler(a - (((uintptr)target) & (a - 1))); + else { + /* Fill with NOPs --- makes debugging with gdb easier */ + while ((uintptr)target&(a-1)) + emit_byte(0x90); // Attention x86 specific code + } +} + +static inline int isinrom(uintptr addr) +{ +#ifdef UAE + return (addr >= uae_p32(kickmem_bank.baseaddr) && + addr < uae_p32(kickmem_bank.baseaddr + 8 * 65536)); +#else + return ((addr >= (uintptr)ROMBaseHost) && (addr < (uintptr)ROMBaseHost + ROMSize)); +#endif +} + +#if defined(UAE) || defined(FLIGHT_RECORDER) +static void flush_all(void) +{ + int i; + + log_flush(); + for (i=0;i0) + free_nreg(i); + + for (i=0;i0) + f_free_nreg(i); + + live.flags_in_flags=TRASH; /* Note: We assume we already rescued the + flags at the very start of the call_r + functions! */ +} +#endif + #if defined(CPU_arm) #include "compemu_midfunc_arm.cpp" @@ -2643,6 +2715,165 @@ void sync_m68k_pc(void) } } +/* for building exception frames */ +void compemu_exc_make_frame(int format, int sr, int ret, int nr, int tmp) +{ + lea_l_brr(SP_REG, SP_REG, -2); + mov_l_ri(tmp, (format << 12) + (nr * 4)); /* format | vector */ + writeword(SP_REG, tmp, tmp); + + lea_l_brr(SP_REG, SP_REG, -4); + writelong(SP_REG, ret, tmp); + + lea_l_brr(SP_REG, SP_REG, -2); + writeword_clobber(SP_REG, sr, tmp); + remove_offset(SP_REG, -1); + if (isinreg(SP_REG)) + evict(SP_REG); + else + flush_reg(SP_REG); +} + +void compemu_make_sr(int sr, int tmp) +{ + flush_flags(); /* low level */ + flush_reg(FLAGX); + +#ifdef OPTIMIZED_FLAGS + + /* + * x86 EFLAGS: (!SAHF_SETO_PROFITABLE) + * FEDCBA98 76543210 + * ----V--- NZ-----C + * + * <--AH--> <--AL--> (SAHF_SETO_PROFITABLE) + * FEDCBA98 76543210 + * NZxxxxxC xxxxxxxV + * + * arm RFLAGS: + * FEDCBA98 76543210 FEDCBA98 76543210 + * NZCV---- -------- -------- -------- + * + * -> m68k SR: + * --S--III ---XNZVC + * + * Master-Bit and traceflags are ignored here, + * since they are not emulated in JIT code + */ + mov_l_rm(sr, uae_p32(live.state[FLAGTMP].mem)); + mov_l_ri(tmp, FLAGVAL_N|FLAGVAL_Z|FLAGVAL_V|FLAGVAL_C); + and_l(sr, tmp); + mov_l_rr(tmp, sr); + +#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY)) +#ifndef SAHF_SETO_PROFITABLE + ror_b_ri(sr, FLAGBIT_N - 3); /* move NZ into position; C->4 */ + shrl_w_ri(tmp, FLAGBIT_V - 1); /* move V into position in tmp */ + or_l(sr, tmp); /* or V flag to SR */ + mov_l_rr(tmp, sr); + shrl_b_ri(tmp, (8 - (FLAGBIT_N - 3)) - FLAGBIT_C); /* move C into position in tmp */ + or_l(sr, tmp); /* or C flag to SR */ +#else + ror_w_ri(sr, FLAGBIT_N - 3); /* move NZ in position; V->4, C->12 */ + shrl_w_ri(tmp, (16 - (FLAGBIT_N - 3)) - FLAGBIT_V - 1); /* move V into position in tmp; C->9 */ + or_l(sr, tmp); /* or V flag to SR */ + shrl_w_ri(tmp, FLAGBIT_C + FLAGBIT_V - 1); /* move C into position in tmp */ + or_l(sr, tmp); /* or C flag to SR */ +#endif + mov_l_ri(tmp, 0x0f); + and_l(sr, tmp); + + mov_b_rm(tmp, uae_p32(®flags.x)); + and_l_ri(tmp, FLAGVAL_X); + shll_l_ri(tmp, 4); + or_l(sr, tmp); + +#elif defined(CPU_arm) && defined(ARM_ASSEMBLY) + shrl_l_ri(sr, FLAGBIT_N - 3); /* move NZ into position */ + ror_l_ri(tmp, FLAGBIT_C - 1); /* move C into position in tmp; V->31 */ + and_l_ri(sr, 0xc); + or_l(sr, tmp); /* or C flag to SR */ + shrl_l_ri(tmp, 31); /* move V into position in tmp */ + or_l(sr, tmp); /* or V flag to SR */ + + mov_b_rm(tmp, uae_p32(®flags.x)); + and_l_ri(tmp, FLAGVAL_X); + shrl_l_ri(tmp, FLAGBIT_X - 4); + or_l(sr, tmp); + +#else +#error "unknown CPU" +#endif + +#else + + xor_l(sr, sr); + xor_l(tmp, tmp); + mov_b_rm(tmp, uae_p32(®s.c)); + shll_l_ri(tmp, 0); + or_l(sr, tmp); + mov_b_rm(tmp, uae_p32(®s.v)); + shll_l_ri(tmp, 1); + or_l(sr, tmp); + mov_b_rm(tmp, uae_p32(®s.z)); + shll_l_ri(tmp, 2); + or_l(sr, tmp); + mov_b_rm(tmp, uae_p32(®s.n)); + shll_l_ri(tmp, 3); + or_l(sr, tmp); + +#endif /* OPTIMIZED_FLAGS */ + + mov_b_rm(tmp, uae_p32(®s.s)); + shll_l_ri(tmp, 13); + or_l(sr, tmp); + mov_l_rm(tmp, uae_p32(®s.intmask)); + shll_l_ri(tmp, 8); + or_l(sr, tmp); + and_l_ri(sr, 0x271f); + mov_w_mr(uae_p32(®s.sr), sr); +} + +void compemu_enter_super(int sr) +{ +#if 0 + fprintf(stderr, "enter_super: isinreg=%d rr=%d nholds=%d\n", isinreg(SP_REG), live.state[SP_REG].realreg, isinreg(SP_REG) ? live.nat[live.state[SP_REG].realreg].nholds : -1); +#endif + remove_offset(SP_REG, -1); + if (isinreg(SP_REG)) + evict(SP_REG); + else + flush_reg(SP_REG); + /* + * equivalent to: + * if (!regs.s) + * { + * regs.usp = m68k_areg(regs, 7); + * m68k_areg(regs, 7) = regs.isp; + * regs.s = 1; + * mmu_set_super(1); + * } + */ + test_l_ri(sr, 0x2000); +#if defined(CPU_i386) || defined(CPU_x86_64) + compemu_raw_jnz_b_oponly(); + uae_u8 *branchadd = get_target(); + skip_byte(); +#elif defined(CPU_arm) + compemu_raw_jnz_b_oponly(); + uae_u8 *branchadd = get_target(); + skip_byte(); +#endif + mov_l_mr((uintptr)®s.usp, SP_REG); + mov_l_rm(SP_REG, uae_p32(®s.isp)); + mov_b_mi(uae_p32(®s.s), 1); +#if defined(CPU_i386) || defined(CPU_x86_64) + *branchadd = get_target() - (branchadd + 1); +#elif defined(CPU_arm) + *((uae_u32 *)branchadd - 3) = get_target() - (branchadd + 1); +#endif +} + /******************************************************************** * Scratch registers management * ********************************************************************/ @@ -2941,6 +3172,39 @@ static void init_comp(void) raw_fp_init(); } +void flush_reg(int reg) +{ + if (live.state[reg].needflush==NF_TOMEM) + { + switch (live.state[reg].status) + { + case INMEM: + if (live.state[reg].val) + { + compemu_raw_add_l_mi((uintptr)live.state[reg].mem, live.state[reg].val); + log_vwrite(reg); + live.state[reg].val = 0; + } + break; + case CLEAN: + case DIRTY: + remove_offset(reg, -1); + tomem(reg); + break; + case ISCONST: + if (reg != PC_P) + writeback_const(reg); + break; + default: + break; + } + Dif (live.state[reg].val && reg!=PC_P) + { + jit_log("Register %d still has val %x", reg, live.state[reg].val); + } + } +} + /* Only do this if you really mean it! The next call should be to init!*/ void flush(int save_regs) { @@ -2958,30 +3222,7 @@ void flush(int save_regs) } } for (i=0;i= uae_p32(kickmem_bank.baseaddr) && - addr < uae_p32(kickmem_bank.baseaddr + 8 * 65536)); -#else - return ((addr >= (uintptr)ROMBaseHost) && (addr < (uintptr)ROMBaseHost + ROMSize)); -#endif -} - -static void flush_all(void) -{ - int i; - - log_flush(); - for (i=0;i0) - free_nreg(i); - - for (i=0;i0) - f_free_nreg(i); - - live.flags_in_flags=TRASH; /* Note: We assume we already rescued the - flags at the very start of the call_r - functions! */ -} - /******************************************************************** * Memory access and related functions, CREATE time * ********************************************************************/ @@ -4522,6 +4691,75 @@ void compiler_dumpstate(void) } #endif + +#if 0 /* debugging helpers; activate as needed */ +static void print_exc_frame(uae_u32 opcode) +{ + int nr = (opcode & 0x0f) + 32; + if (nr != 0x45 && /* Timer-C */ + nr != 0x1c && /* VBL */ + nr != 0x46) /* ACIA */ + { + memptr sp = m68k_areg(regs, 7); + uae_u16 sr = get_word(sp); + fprintf(stderr, "Exc:%02x SP: %08x USP: %08x SR: %04x PC: %08x Format: %04x", nr, sp, regs.usp, sr, get_long(sp + 2), get_word(sp + 6)); + if (nr >= 32 && nr < 48) + { + fprintf(stderr, " Opcode: $%04x", sr & 0x2000 ? get_word(sp + 8) : get_word(regs.usp)); + } + fprintf(stderr, "\n"); + } +} + +static void push_all_nat(void) +{ + raw_pushfl(); + raw_push_l_r(EAX_INDEX); + raw_push_l_r(ECX_INDEX); + raw_push_l_r(EDX_INDEX); + raw_push_l_r(EBX_INDEX); + raw_push_l_r(EBP_INDEX); + raw_push_l_r(EDI_INDEX); + raw_push_l_r(ESI_INDEX); + raw_push_l_r(R8_INDEX); + raw_push_l_r(R9_INDEX); + raw_push_l_r(R10_INDEX); + raw_push_l_r(R11_INDEX); + raw_push_l_r(R12_INDEX); + raw_push_l_r(R13_INDEX); + raw_push_l_r(R14_INDEX); + raw_push_l_r(R15_INDEX); +} + +static void pop_all_nat(void) +{ + raw_pop_l_r(R15_INDEX); + raw_pop_l_r(R14_INDEX); + raw_pop_l_r(R13_INDEX); + raw_pop_l_r(R12_INDEX); + raw_pop_l_r(R11_INDEX); + raw_pop_l_r(R10_INDEX); + raw_pop_l_r(R9_INDEX); + raw_pop_l_r(R8_INDEX); + raw_pop_l_r(ESI_INDEX); + raw_pop_l_r(EDI_INDEX); + raw_pop_l_r(EBP_INDEX); + raw_pop_l_r(EBX_INDEX); + raw_pop_l_r(EDX_INDEX); + raw_pop_l_r(ECX_INDEX); + raw_pop_l_r(EAX_INDEX); + raw_popfl(); +} +#endif + +#if 0 +static void print_inst(void) +{ + disasm_m68k_block(regs.fault_pc + (uint8 *)MEMBaseDiff, 1); +} +#endif + + #ifdef UAE void compile_block(cpu_history *pc_hist, int blocklen, int totcycles) { @@ -4722,7 +4960,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) remove_all_offsets(); prepare_for_call_1(); prepare_for_call_2(); - raw_mov_l_ri(REG_PAR1, ((uintptr)(pc_hist[i].location)) - MEMBaseDiff); + raw_mov_l_ri(REG_PAR1, (memptr)((uintptr)pc_hist[i].location - MEMBaseDiff)); raw_mov_w_ri(REG_PAR2, cft_map(opcode)); raw_dec_sp(STACK_SHADOW_SPACE); compemu_raw_call((uintptr)m68k_record_step); @@ -4738,7 +4976,16 @@ static void compile_block(cpu_history* pc_hist, int blocklen) init_comp(); } was_comp=1; - + +#if defined(HAVE_DISASM_NATIVE) && defined(HAVE_DISASM_M68K) +/* debugging helpers; activate as needed */ +#if 1 + disasm_this_inst = false; + const uae_u8 *start_m68k_thisinst = (const uae_u8 *)pc_hist[i].location; + uae_u8 *start_native_thisinst = get_target(); +#endif +#endif + #ifdef WINUAE_ARANYM bool isnop = do_get_mem_word(pc_hist[i].location) == 0x4e71 || ((i + 1) < blocklen && do_get_mem_word(pc_hist[i+1].location) == 0x4e71); @@ -4769,6 +5016,44 @@ static void compile_block(cpu_history* pc_hist, int blocklen) nop(); was_comp=0; } +#endif +#if defined(HAVE_DISASM_NATIVE) && defined(HAVE_DISASM_M68K) + +/* debugging helpers; activate as needed */ +#if 0 + disasm_m68k_block(start_m68k_thisinst, 1); + push_all_nat(); + compemu_raw_mov_l_mi(uae_p32(®s.fault_pc), (uintptr)start_m68k_thisinst - MEMBaseDiff); + raw_dec_sp(STACK_SHADOW_SPACE); + compemu_raw_call(uae_p32(print_instn)); + raw_inc_sp(STACK_SHADOW_SPACE); + pop_all_nat(); +#endif + + if (disasm_this_inst) + { + disasm_m68k_block(start_m68k_thisinst, 1); +#if 1 + disasm_native_block(start_native_thisinst, get_target() - start_native_thisinst); +#endif + +#if 0 + push_all_nat(); + + raw_dec_sp(STACK_SHADOW_SPACE); + compemu_raw_mov_l_ri(REG_PAR1, (uae_u32)cft_map(opcode)); + compemu_raw_call((uintptr)print_exc_frame); + raw_inc_sp(STACK_SHADOW_SPACE); + + pop_all_nat(); +#endif + + if (failure) + { + bug("(discarded)"); + target = start_native_thisinst; + } + } #endif } @@ -4797,8 +5082,8 @@ static void compile_block(cpu_history* pc_hist, int blocklen) if (i < blocklen - 1) { uae_u8* branchadd; - /* if (SPCFLAGS_TEST(SPCFLAG_STOP)) popall_do_nothing() */ - compemu_raw_mov_l_rm(0,(uintptr)specflags); + /* if (SPCFLAGS_TEST(SPCFLAG_ALL)) popall_do_nothing() */ + compemu_raw_mov_l_rm(0, (uintptr)specflags); compemu_raw_test_l_rr(0,0); #if defined(USE_DATA_BUFFER) data_check_end(8, 64); // just a pessimistic guess... @@ -4810,7 +5095,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) raw_sub_l_mi(uae_p32(&countdown),scaled_cycles(totcycles)); #endif compemu_raw_jmp((uintptr)popall_do_nothing); - *branchadd=get_target()-branchadd-1; + *branchadd = get_target() - (branchadd + 1); } } } diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index 202774ac..14b1d44f 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -262,6 +262,7 @@ finish_braces (void) { while (n_braces > 0) close_brace (); + comprintf ("\n"); } static inline void gen_update_next_handler(void) @@ -355,7 +356,33 @@ swap_opcode (void) static void sync_m68k_pc (void) { - comprintf("\t if (m68k_pc_offset > SYNC_PC_OFFSET) sync_m68k_pc();\n"); + comprintf(" if (m68k_pc_offset > SYNC_PC_OFFSET)\n sync_m68k_pc();\n"); +} + + +static void gen_set_fault_pc(void) +{ + start_brace(); + comprintf("\tsync_m68k_pc();\n"); + comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); + comprintf("\tint ret=scratchie++;\n" + "\tmov_l_ri(ret,retadd);\n" + "\tmov_l_mr((uintptr)®s.fault_pc,ret);\n"); +} + + +static void make_sr(void) +{ + start_brace(); + comprintf("\tint sr = scratchie++;\n"); + comprintf("\tint tmp = scratchie++;\n"); + comprintf("\tcompemu_make_sr(sr, tmp);\n"); +} + + +static void disasm_this_inst(void) +{ + comprintf("\tdisasm_this_inst = true;\n"); } @@ -1751,7 +1778,31 @@ gen_opcode (unsigned int opcode) break; case i_TRAP: +#ifdef DISABLE_I_TRAP + failure; +#endif isjump; + mayfail; + start_brace(); + comprintf(" int trapno = srcreg + 32;\n"); + gen_set_fault_pc(); + make_sr(); + comprintf(" compemu_enter_super(sr);\n"); + comprintf(" compemu_exc_make_frame(0, sr, ret, trapno, scratchie);\n"); + comprintf(" forget_about(ret);\n"); + /* m68k_setpc (get_long (regs.vbr + 4*nr)); */ + start_brace(); + comprintf(" int srca = scratchie++;\n"); + comprintf(" mov_l_rm(srca, (uintptr)®s.vbr);\n"); + comprintf(" mov_l_brR(srca, srca, MEMBaseDiff + trapno * 4); mid_bswap_32(srca);\n"); + comprintf(" mov_l_mr((uintptr)®s.pc, srca);\n"); + comprintf(" get_n_addr_jmp(srca, PC_P, scratchie);\n"); + comprintf(" mov_l_mr((uintptr)®s.pc_oldp, PC_P);\n"); + gen_update_next_handler(); + disasm_this_inst(); /* for debugging only */ + /* + * this currently deactivates this feature, since it does not work yet + */ failure; break; @@ -1792,12 +1843,12 @@ gen_opcode (unsigned int opcode) comprintf("\tadd_l_ri(offs,4);\n"); start_brace(); comprintf("\tint newad=scratchie++;\n" - "\treadlong(15,newad,scratchie);\n" + "\treadlong(SP_REG,newad,scratchie);\n" "\tmov_l_mr((uintptr)®s.pc,newad);\n" "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" "\tm68k_pc_offset=0;\n" - "\tadd_l(15,offs);\n"); + "\tadd_l(SP_REG,offs);\n"); gen_update_next_handler(); isjump; break; @@ -1808,12 +1859,12 @@ gen_opcode (unsigned int opcode) #endif genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); - comprintf("\tsub_l_ri(15,4);\n" - "\twritelong_clobber(15,src,scratchie);\n" - "\tmov_l_rr(src,15);\n"); + comprintf("\tsub_l_ri(SP_REG,4);\n" + "\twritelong_clobber(SP_REG,src,scratchie);\n" + "\tmov_l_rr(src,SP_REG);\n"); if (curi->size==sz_word) comprintf("\tsign_extend_16_rr(offs,offs);\n"); - comprintf("\tadd_l(15,offs);\n"); + comprintf("\tadd_l(SP_REG,offs);\n"); genastore ("src", curi->smode, "srcreg", sz_long, "src"); break; @@ -1822,9 +1873,9 @@ gen_opcode (unsigned int opcode) failure; #endif genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - comprintf("\tmov_l_rr(15,src);\n" - "\treadlong(15,src,scratchie);\n" - "\tadd_l_ri(15,4);\n"); + comprintf("\tmov_l_rr(SP_REG,src);\n" + "\treadlong(SP_REG,src,scratchie);\n" + "\tadd_l_ri(SP_REG,4);\n"); genastore ("src", curi->smode, "srcreg", curi->size, "src"); break; @@ -1833,12 +1884,12 @@ gen_opcode (unsigned int opcode) failure; #endif comprintf("\tint newad=scratchie++;\n" - "\treadlong(15,newad,scratchie);\n" + "\treadlong(SP_REG,newad,scratchie);\n" "\tmov_l_mr((uintptr)®s.pc,newad);\n" "\tget_n_addr_jmp(newad,PC_P,scratchie);\n" "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" "\tm68k_pc_offset=0;\n" - "\tlea_l_brr(15,15,4);\n"); + "\tlea_l_brr(SP_REG,SP_REG,4);\n"); gen_update_next_handler(); isjump; break; @@ -1863,8 +1914,8 @@ gen_opcode (unsigned int opcode) comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); comprintf("\tint ret=scratchie++;\n" "\tmov_l_ri(ret,retadd);\n" - "\tsub_l_ri(15,4);\n" - "\twritelong_clobber(15,ret,scratchie);\n"); + "\tsub_l_ri(SP_REG,4);\n" + "\twritelong_clobber(SP_REG,ret,scratchie);\n"); comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" @@ -1895,13 +1946,14 @@ gen_opcode (unsigned int opcode) comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); comprintf("\tint ret=scratchie++;\n" "\tmov_l_ri(ret,retadd);\n" - "\tsub_l_ri(15,4);\n" - "\twritelong_clobber(15,ret,scratchie);\n"); + "\tsub_l_ri(SP_REG,4);\n" + "\twritelong_clobber(SP_REG,ret,scratchie);\n"); comprintf("\tadd_l_ri(src,m68k_pc_offset_thisinst+2);\n"); comprintf("\tm68k_pc_offset=0;\n"); comprintf("\tadd_l(PC_P,src);\n"); comprintf("\tcomp_pc_p=(uae_u8*)(uintptr)get_const(PC_P);\n"); + gen_update_next_handler(); break; case i_Bcc: @@ -2029,7 +2081,7 @@ gen_opcode (unsigned int opcode) case 1: comprintf("\tstart_needflags();\n"); comprintf("\tsub_w_ri(src,1);\n"); - comprintf("\t end_needflags();\n"); + comprintf("\tend_needflags();\n"); start_brace(); comprintf("\tuae_u32 v2,v;\n" "\tuae_u32 v1=get_const(PC_P);\n"); @@ -2063,9 +2115,9 @@ gen_opcode (unsigned int opcode) so whether we move them around doesn't matter. However, if cc=false, we have offs==jump_pc, and src==nsrc-1 */ - comprintf("\t start_needflags();\n"); + comprintf("\tstart_needflags();\n"); comprintf("\ttest_w_rr(nsrc,nsrc);\n"); - comprintf("\t end_needflags();\n"); + comprintf("\tend_needflags();\n"); comprintf("\tcmov_l_rr(PC_P,offs,%d);\n", NATIVE_CC_NE); break; default: assert(0); @@ -2174,10 +2226,11 @@ gen_opcode (unsigned int opcode) #endif mayfail; if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); start_brace(); } comprintf("\tdont_care_flags();\n"); @@ -2249,10 +2302,11 @@ gen_opcode (unsigned int opcode) #endif mayfail; if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); start_brace(); } comprintf("\tdont_care_flags();\n"); @@ -2260,10 +2314,11 @@ gen_opcode (unsigned int opcode) LSL. The handling of V is, uhm, unpleasant, so if it's needed, let the normal emulation handle it. Shoulders of giants kinda thing ;-) */ - comprintf("if (needed_flags & FLAG_V) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if (needed_flags & FLAG_V) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); @@ -2323,10 +2378,11 @@ gen_opcode (unsigned int opcode) #endif mayfail; if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); start_brace(); } comprintf("\tdont_care_flags();\n"); @@ -2390,10 +2446,11 @@ gen_opcode (unsigned int opcode) #endif mayfail; if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); start_brace(); } comprintf("\tdont_care_flags();\n"); @@ -2457,10 +2514,11 @@ gen_opcode (unsigned int opcode) #endif mayfail; if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); start_brace(); } comprintf("\tdont_care_flags();\n"); @@ -2469,9 +2527,9 @@ gen_opcode (unsigned int opcode) start_brace (); switch(curi->size) { - case sz_long: comprintf("\t rol_l_rr(data,cnt);\n"); break; - case sz_word: comprintf("\t rol_w_rr(data,cnt);\n"); break; - case sz_byte: comprintf("\t rol_b_rr(data,cnt);\n"); break; + case sz_long: comprintf("\trol_l_rr(data,cnt);\n"); break; + case sz_word: comprintf("\trol_w_rr(data,cnt);\n"); break; + case sz_byte: comprintf("\trol_b_rr(data,cnt);\n"); break; } if (!noflags) { @@ -2481,13 +2539,13 @@ gen_opcode (unsigned int opcode) */ comprintf("\tif (needed_flags & FLAG_ZNV)\n"); switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; } - comprintf("\t bt_l_ri(data,0x00);\n"); /* Set C */ - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); + comprintf("\tbt_l_ri(data,0x00);\n"); /* Set C */ + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); } genastore ("data", curi->dmode, "dstreg", curi->size, "data"); break; @@ -2498,10 +2556,11 @@ gen_opcode (unsigned int opcode) #endif mayfail; if (curi->smode==Dreg) { - comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" - " FAIL(1);\n" - " " RETURN "\n" - "} \n"); + comprintf( + " if ((uae_u32)srcreg==(uae_u32)dstreg) {\n" + " FAIL(1);\n" + " " RETURN "\n" + " }\n"); start_brace(); } comprintf("\tdont_care_flags();\n"); @@ -2510,9 +2569,9 @@ gen_opcode (unsigned int opcode) start_brace (); switch(curi->size) { - case sz_long: comprintf("\t ror_l_rr(data,cnt);\n"); break; - case sz_word: comprintf("\t ror_w_rr(data,cnt);\n"); break; - case sz_byte: comprintf("\t ror_b_rr(data,cnt);\n"); break; + case sz_long: comprintf("\tror_l_rr(data,cnt);\n"); break; + case sz_word: comprintf("\tror_w_rr(data,cnt);\n"); break; + case sz_byte: comprintf("\tror_b_rr(data,cnt);\n"); break; } if (!noflags) { @@ -2522,17 +2581,17 @@ gen_opcode (unsigned int opcode) */ comprintf("\tif (needed_flags & FLAG_ZNV)\n"); switch(curi->size) { - case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; - case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; - case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; + case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; + case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; + case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; } switch(curi->size) { - case sz_byte: comprintf("\t bt_l_ri(data,0x07);\n"); break; - case sz_word: comprintf("\t bt_l_ri(data,0x0f);\n"); break; - case sz_long: comprintf("\t bt_l_ri(data,0x1f);\n"); break; + case sz_byte: comprintf("\tbt_l_ri(data,0x07);\n"); break; + case sz_word: comprintf("\tbt_l_ri(data,0x0f);\n"); break; + case sz_long: comprintf("\tbt_l_ri(data,0x1f);\n"); break; } - comprintf("\t live_flags();\n"); - comprintf("\t end_needflags();\n"); + comprintf("\tlive_flags();\n"); + comprintf("\tend_needflags();\n"); } genastore ("data", curi->dmode, "dstreg", curi->size, "data"); break; @@ -2816,7 +2875,7 @@ gen_opcode (unsigned int opcode) finish_braces (); sync_m68k_pc (); if (global_mayfail) - comprintf("\tif (failure) m68k_pc_offset=m68k_pc_offset_thisinst;\n"); + comprintf(" if (failure)\n m68k_pc_offset = m68k_pc_offset_thisinst;\n"); return global_failure; } @@ -3284,6 +3343,7 @@ int main(void) free (table68k); fclose (stblfile); fclose (headerfile); + (void)disasm_this_inst; return 0; } diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index e28c370a..295a49e5 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -1409,30 +1409,9 @@ static void gen_opcode (unsigned long int opcode) fill_prefetch_0 (); printf ("\tMakeFromSR();\n"); } else { - int old_brace_level = n_braces; - if (next_cpu_level < 0) + if (next_cpu_level < 0) next_cpu_level = 0; - printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n"); - genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - printf ("\tnewsr = sr; newpc = pc;\n"); - printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); - printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); - printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); -// printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); - printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); - printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); - printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n"); - printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n"); - printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n"); - printf ("\telse { Exception(14,0); goto %s; }\n", endlabelstr); - printf ("\tregs.sr = newsr; MakeFromSR();\n}\n"); - pop_braces (old_brace_level); - printf ("\tregs.sr = newsr; MakeFromSR();\n"); - printf ("\tm68k_setpc_rte(newpc);\n"); - fill_prefetch_0 (); - need_endlabel = 1; + printf ("\tex_rte();\n"); } /* PC is set and prefetch filled. */ m68k_pc_offset = 0; diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index 6a434daf..c307bdfd 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -38,7 +38,11 @@ #if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY)) +#ifdef __cplusplus # include +#else +# include +#endif #ifndef SAHF_SETO_PROFITABLE diff --git a/BasiliskII/src/uae_cpu/memory-uae.h b/BasiliskII/src/uae_cpu/memory-uae.h index c93aeb37..cbae60b0 100644 --- a/BasiliskII/src/uae_cpu/memory-uae.h +++ b/BasiliskII/src/uae_cpu/memory-uae.h @@ -159,7 +159,7 @@ static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write) // D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr)); regs.mmu_fault_addr = addr; - regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8)); + regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8)); /* MMU_SW_RW */ breakpt(); THROW(2); } diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index 351a0de3..382b2d94 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -491,6 +491,65 @@ static inline void exc_make_frame( exc_push_word((format << 12) + (nr * 4)); /* format | vector */ exc_push_long(currpc); exc_push_word(sr); +#if 0 /* debugging helpers; activate as needed */ + if (/* nr != 0x45 && */ /* Timer-C */ + nr != 0x1c && /* VBL */ + nr != 0x46) /* ACIA */ + { + memptr sp = m68k_areg(regs, 7); + uae_u16 sr = get_word(sp); + fprintf(stderr, "Exc:%02x SP: %08x USP: %08x SR: %04x PC: %08x Format: %04x", nr, sp, regs.usp, sr, get_long(sp + 2), get_word(sp + 6)); + if (nr >= 32 && nr < 48) + { + fprintf(stderr, " Opcode: $%04x", sr & 0x2000 ? get_word(sp + 8) : get_word(regs.usp)); + } + fprintf(stderr, "\n"); + } +#endif +} + + +void ex_rte(void) +{ + uae_u16 newsr; + uae_u32 newpc; + uae_s16 format; + + for (;;) + { + newsr = get_word(m68k_areg(regs, 7)); + m68k_areg(regs, 7) += 2; + newpc = get_long(m68k_areg(regs, 7)); + m68k_areg(regs, 7) += 4; + format = get_word(m68k_areg(regs, 7)); + m68k_areg(regs, 7) += 2; + if ((format & 0xF000) == 0x0000) break; + else if ((format & 0xF000) == 0x1000) { ; } + else if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; } +// else if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; } + else if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; } + else if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; } + else if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; } + else if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; } + else if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; } + else { Exception(14,0); return; } + regs.sr = newsr; + MakeFromSR(); + } +#if 0 /* debugging helpers; activate as needed */ + { + memptr sp = m68k_areg(regs, 7) - 8; + int nr = (format & 0xfff) >> 2; + if (/* nr != 0x45 && */ /* Timer-C */ + nr != 0x1c && /* VBL */ + nr != 0x46) /* ACIA */ + fprintf(stderr, "RTE SP: %08x USP: %08x SR: %04x PC: %08x Format: %04x olds=%d nr=%02x -> %08x\n", sp, regs.usp, newsr, m68k_getpc(), format, regs.s, nr, newpc); + } +#endif + regs.sr = newsr; + MakeFromSR(); + m68k_setpc_rte(newpc); + fill_prefetch_0(); } #ifdef EXCEPTIONS_VIA_LONGJMP @@ -570,7 +629,7 @@ void Exception(int nr, uaecptr oldpc) } else if (nr == 3) { exc_make_frame(2, regs.sr, last_addr_for_exception_3, nr, last_fault_for_exception_3 & 0xfffffffe, 0); - } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { + } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) { /* div by zero, CHK, TRAP or TRACE */ exc_make_frame(2, regs.sr, currpc, nr, oldpc, 0); } else if (regs.m && nr >= 24 && nr < 32) { diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index 13a51b82..478a3785 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -271,6 +271,7 @@ extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, ua extern void MakeSR (void); extern void MakeFromSR (void); extern void Exception (int, uaecptr); +extern void ex_rte(void); extern void dump_counts (void); extern int m68k_move2c (int, uae_u32 *); extern int m68k_movec2 (int, uae_u32 *); diff --git a/BasiliskII/src/uae_cpu/registers.h b/BasiliskII/src/uae_cpu/registers.h index c3459719..16f67092 100644 --- a/BasiliskII/src/uae_cpu/registers.h +++ b/BasiliskII/src/uae_cpu/registers.h @@ -61,9 +61,8 @@ extern struct regstruct flagtype t0; flagtype s; flagtype m; - flagtype x; flagtype stopped; - int intmask; + uint32_t intmask; uae_u32 pc; uae_u32 fault_pc; From 63ddee1be13f0d9cdcf1c75e2707b9fa8a4dad68 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Wed, 22 Jan 2020 02:35:11 -0600 Subject: [PATCH 17/20] Set areg 7 to 0x2000 on m68k reset --- BasiliskII/src/uae_cpu/newcpu.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index 382b2d94..0832df82 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -1020,7 +1020,11 @@ void m68k_reset (void) // (it is definitely better than what it was before this commit // since it was reading from 0x00000000 in User mode and with active MMU) mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */ +#if 0 m68k_areg (regs, 7) = phys_get_long(0x00000000); +#else + m68k_areg (regs, 7) = 0x2000; +#endif #if 0 m68k_setpc (phys_get_long(0x00000004)); #else From cfcfde04802579a3528fad1a6907caa1b7410b29 Mon Sep 17 00:00:00 2001 From: uyjulian Date: Wed, 22 Jan 2020 02:35:48 -0600 Subject: [PATCH 18/20] Use locking on idle wait cond --- BasiliskII/src/Unix/timer_unix.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/BasiliskII/src/Unix/timer_unix.cpp b/BasiliskII/src/Unix/timer_unix.cpp index 6fb8cf3e..aa2e285c 100644 --- a/BasiliskII/src/Unix/timer_unix.cpp +++ b/BasiliskII/src/Unix/timer_unix.cpp @@ -386,8 +386,16 @@ void idle_wait(void) void idle_resume(void) { //This causes events to not process randomly in JIT so commented out - if (idle_cond) - SDL_CondSignal(idle_cond); + if (idle_lock) + { + SDL_LockMutex(idle_lock); + if (idle_cond) + { + SDL_CondSignal(idle_cond); + } + SDL_UnlockMutex(idle_lock); + } + // #ifdef IDLE_USES_COND_WAIT // pthread_cond_signal(&idle_cond); // #else From 36b6d0769b71954577a75f7e8b7d5f040c0cc55c Mon Sep 17 00:00:00 2001 From: uyjulian Date: Wed, 22 Jan 2020 02:41:06 -0600 Subject: [PATCH 19/20] Zero out memory --- BasiliskII/src/Unix/main_unix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index f7dcc682..e7879bbc 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -394,6 +394,7 @@ int main(int argc, char **argv) ErrorAlert(STR_NO_MEM_ERR); QuitEmulator(); } + memset(ram_rom_area, 0, RAMSize + 0x100000); RAMBaseHost = ram_rom_area; ROMBaseHost = RAMBaseHost + RAMSize; } @@ -405,6 +406,7 @@ int main(int argc, char **argv) ErrorAlert(STR_NO_MEM_ERR); QuitEmulator(); } + memset(ScratchMem, 0, SCRATCH_MEM_SIZE); ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block #endif From bb5caf093ab3d5ce5e5be56502c81e1b0bba609d Mon Sep 17 00:00:00 2001 From: uyjulian Date: Sun, 23 Aug 2020 08:34:42 -0500 Subject: [PATCH 20/20] Merge latest ARAnyM changes --- .../src/uae_cpu/compiler/compemu_fpp.cpp | 3 + BasiliskII/src/uae_cpu/compiler/gencomp.c | 304 ++++++++++-------- BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp | 81 +++-- BasiliskII/src/uae_cpu/fpu/mathlib.h | 23 ++ 4 files changed, 244 insertions(+), 167 deletions(-) diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp index 5d5de2cd..4ffcca0d 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp @@ -282,6 +282,8 @@ STATIC_INLINE int get_fp_value(uae_u32 opcode, uae_u16 extra) mov_w_mr(((uintptr) temp_fp) + 8, S2); add_l_ri(ad, 4); readlong(ad, S2, S3); + // always set the explicit integer bit. + or_l_ri(S2, 0x80000000); mov_l_mr((uintptr) (temp_fp) + 4, S2); add_l_ri(ad, 4); readlong(ad, S2, S3); @@ -1891,6 +1893,7 @@ void comp_fpp_opp(uae_u32 opcode, uae_u16 extra) return; } + // FIXME: the quotient byte must be computed dont_care_fflags(); src = get_fp_value(opcode, extra); if (src < 0) diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index 14b1d44f..d301ced7 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -147,6 +147,13 @@ static int comp_index=0; # endif #endif +#define GENA_GETV_NO_FETCH 0 +#define GENA_GETV_FETCH 1 +#define GENA_GETV_FETCH_ALIGN 2 +#define GENA_MOVEM_DO_INC 0 +#define GENA_MOVEM_NO_INC 1 +#define GENA_MOVEM_MOVE16 2 + static int cond_codes[]={-1,-1, NATIVE_CC_HI,NATIVE_CC_LS, @@ -395,8 +402,8 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n switch (mode) { case Dreg: /* Do we need to check dodgy here? */ - assert (!movem); - if (getv == 1 || getv == 2) + assert (movem == GENA_MOVEM_DO_INC); + if (getv == GENA_GETV_FETCH || getv == GENA_GETV_FETCH_ALIGN) { /* We generate the variable even for getv==2, so we can use it as a destination for MOVE */ @@ -405,12 +412,12 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n return; case Areg: - assert (!movem); - if (getv == 1 || getv == 2) + assert (movem == GENA_MOVEM_DO_INC); + if (getv == GENA_GETV_FETCH || getv == GENA_GETV_FETCH_ALIGN) { /* see above */ comprintf("\tint %s = dodgy ? scratchie++ : %s + 8;\n", name, reg); - if (getv == 1) + if (getv == GENA_GETV_FETCH) { comprintf("\tif (dodgy) \n"); comprintf("\t\tmov_l_rr(%s, %s + 8);\n", name, reg); @@ -431,7 +438,7 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n switch (size) { case sz_byte: - if (movem) + if (movem != GENA_MOVEM_DO_INC) { comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); comprintf("\tif (dodgy)\n"); @@ -446,7 +453,7 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n } break; case sz_word: - if (movem) + if (movem != GENA_MOVEM_DO_INC) { comprintf("\tint %sa=dodgy?scratchie++:%s+8;\n", name, reg); comprintf("\tif (dodgy) \n"); @@ -461,7 +468,7 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n } break; case sz_long: - if (movem) + if (movem != GENA_MOVEM_DO_INC) { comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg); comprintf("\tif (dodgy)\n"); @@ -515,7 +522,7 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n comprintf("\tmov_l_ri(%sa, %s); /* absl */\n", name, gen_nextilong()); break; case imm: - assert (getv == 1); + assert (getv == GENA_GETV_FETCH); switch (size) { case sz_byte: @@ -536,22 +543,22 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n } return; case imm0: - assert (getv == 1); + assert (getv == GENA_GETV_FETCH); comprintf("\tint %s = scratchie++;\n", name); comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte()); return; case imm1: - assert (getv == 1); + assert (getv == GENA_GETV_FETCH); comprintf("\tint %s = scratchie++;\n", name); comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword()); return; case imm2: - assert (getv == 1); + assert (getv == GENA_GETV_FETCH); comprintf("\tint %s = scratchie++;\n", name); comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong()); return; case immi: - assert (getv == 1); + assert (getv == GENA_GETV_FETCH); comprintf("\tint %s = scratchie++;\n", name); comprintf("\tmov_l_ri(%s, %s);\n", name, reg); return; @@ -562,7 +569,7 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n /* We get here for all non-reg non-immediate addressing modes to * actually fetch the value. */ - if (getv == 1) + if (getv == GENA_GETV_FETCH) { char astring[80]; sprintf(astring, "%sa", name); @@ -602,7 +609,7 @@ static void genamode(amodes mode, const char *reg, wordsizes size, const char *n /* We now might have to fix up the register for pre-dec or post-inc * addressing modes. */ - if (!movem) + if (movem == GENA_MOVEM_DO_INC) { switch (mode) { @@ -731,8 +738,8 @@ static void genmov16(uae_u32 opcode, struct instr *curi) } else { /* Other variants */ - genamode (curi->smode, "srcreg", curi->size, "src", 0, 2); - genamode (curi->dmode, "dstreg", curi->size, "dst", 0, 2); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16); comprintf("\tmov_l_rr(src,srca);\n"); comprintf("\tmov_l_rr(dst,dsta);\n"); } @@ -797,7 +804,7 @@ genmovemel (uae_u16 opcode) comprintf ("\tint native=scratchie++;\n"); comprintf ("\tint i;\n"); comprintf ("\tsigned char offset=0;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC); #ifdef UAE if (table68k[opcode].size == sz_long) comprintf("\tif (1 && !special_mem) {\n"); @@ -870,7 +877,7 @@ genmovemle (uae_u16 opcode) comprintf ("\tint i;\n"); comprintf ("\tint tmp=scratchie++;\n"); comprintf ("\tsigned char offset=0;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC); #ifdef UAE /* *Sigh* Some clever geek realized that the fastest way to copy a @@ -1406,8 +1413,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_OR_AND_EOR failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); switch(curi->mnemo) { case i_OR: genflags (flag_or, curi->size, "", "src", "dst"); break; case i_AND: genflags (flag_and, curi->size, "", "src", "dst"); break; @@ -1431,8 +1438,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_SUB failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); genflags (flag_sub, curi->size, "", "src", "dst"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; @@ -1441,8 +1448,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_SUBA failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint tmp=scratchie++;\n"); switch(curi->size) { @@ -1460,8 +1467,8 @@ gen_opcode (unsigned int opcode) failure; #endif isaddx; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); genflags (flag_subx, curi->size, "", "src", "dst"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; @@ -1475,8 +1482,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_ADD failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); genflags (flag_add, curi->size, "", "src", "dst"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; @@ -1485,8 +1492,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_ADDA failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint tmp=scratchie++;\n"); switch(curi->size) { @@ -1504,8 +1511,8 @@ gen_opcode (unsigned int opcode) failure; #endif isaddx; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); genflags (flag_addx, curi->size, "", "src", "dst"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); @@ -1520,7 +1527,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_NEG failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace (); comprintf("\tint dst=scratchie++;\n"); comprintf("\tmov_l_ri(dst,0);\n"); @@ -1533,7 +1540,7 @@ gen_opcode (unsigned int opcode) failure; #endif isaddx; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace (); comprintf("\tint dst=scratchie++;\n"); comprintf("\tmov_l_ri(dst,0);\n"); @@ -1550,7 +1557,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_CLR failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint dst=scratchie++;\n"); comprintf("\tmov_l_ri(dst,0);\n"); @@ -1562,7 +1569,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_NOT failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace (); comprintf("\tint dst=scratchie++;\n"); comprintf("\tmov_l_ri(dst,0xffffffff);\n"); @@ -1574,7 +1581,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_TST failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); genflags (flag_logical, curi->size, "src", "", ""); break; case i_BCHG: @@ -1584,8 +1591,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_BCHG_BCLR_BSET_BTST failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint s=scratchie++;\n" "\tint tmp=scratchie++;\n" @@ -1626,8 +1633,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_CMPM_CMP failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace (); genflags (flag_cmp, curi->size, "", "src", "dst"); break; @@ -1636,8 +1643,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_CMPA failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint tmps=scratchie++;\n"); switch(curi->size) { @@ -1668,14 +1675,14 @@ gen_opcode (unsigned int opcode) switch(curi->dmode) { case Dreg: case Areg: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); genflags (flag_mov, curi->size, "", "src", "dst"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; default: /* It goes to memory, not a register */ - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); genflags (flag_logical, curi->size, "src", "", ""); genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; @@ -1686,8 +1693,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_MOVEA failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint tmps=scratchie++;\n"); @@ -1713,7 +1720,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_SWAP failure; #endif - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); comprintf("\tdont_care_flags();\n"); comprintf("\trol_l_ri(src,16);\n"); genflags (flag_logical, sz_long, "src", "", ""); @@ -1724,8 +1731,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_EXG failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tint tmp=scratchie++;\n" "\tmov_l_rr(tmp,src);\n"); @@ -1737,7 +1744,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_EXT failure; #endif - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); comprintf("\tdont_care_flags();\n"); start_brace (); switch (curi->size) @@ -1838,7 +1845,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_RTD failure; #endif - genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); /* offs is constant */ comprintf("\tadd_l_ri(offs,4);\n"); start_brace(); @@ -1857,8 +1864,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_LINK failure; #endif - genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); comprintf("\tsub_l_ri(SP_REG,4);\n" "\twritelong_clobber(SP_REG,src,scratchie);\n" "\tmov_l_rr(src,SP_REG);\n"); @@ -1872,7 +1879,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_UNLK failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); comprintf("\tmov_l_rr(SP_REG,src);\n" "\treadlong(SP_REG,src,scratchie);\n" "\tadd_l_ri(SP_REG,4);\n"); @@ -1909,7 +1916,7 @@ gen_opcode (unsigned int opcode) failure; #endif isjump; - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); comprintf("\tint ret=scratchie++;\n" @@ -1928,7 +1935,7 @@ gen_opcode (unsigned int opcode) failure; #endif isjump; - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC); comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n" "\tget_n_addr_jmp(srca,PC_P,scratchie);\n" "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n" @@ -1941,7 +1948,7 @@ gen_opcode (unsigned int opcode) failure; #endif is_const_jump; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n"); comprintf("\tint ret=scratchie++;\n" @@ -1961,7 +1968,7 @@ gen_opcode (unsigned int opcode) failure; #endif comprintf("\tuae_u32 v,v1,v2;\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); /* That source is an immediate, so we can clobber it with abandon */ switch(curi->size) { case sz_byte: comprintf("\tsign_extend_8_rr(src,src);\n"); break; @@ -2020,8 +2027,8 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_LEA failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); break; @@ -2037,8 +2044,8 @@ gen_opcode (unsigned int opcode) table68k[opcode].smode==Ad8r) comprintf("if (srcreg==7) dodgy=1;\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); - genamode (Apdi, "7", sz_long, "dst", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC); + genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); genastore ("srca", Apdi, "7", sz_long, "dst"); break; @@ -2048,8 +2055,8 @@ gen_opcode (unsigned int opcode) #endif isjump; uses_cmov; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); /* That offs is an immediate, so we can clobber it with abandon */ switch(curi->size) { @@ -2130,7 +2137,7 @@ gen_opcode (unsigned int opcode) #ifdef DISABLE_I_SCC failure; #endif - genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC); start_brace (); comprintf ("\tint val = scratchie++;\n"); @@ -2183,8 +2190,8 @@ gen_opcode (unsigned int opcode) failure; #endif comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); /* To do 16x16 unsigned multiplication, we actually use 32x32 signed, and zero-extend the registers first. That solves the problem of MUL needing dedicated registers @@ -2201,8 +2208,8 @@ gen_opcode (unsigned int opcode) failure; #endif comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); - genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); + genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); comprintf("\tsign_extend_16_rr(scratchie,src);\n" "\tsign_extend_16_rr(dst,dst);\n" "\timul_32_32(dst,scratchie);\n"); @@ -2235,8 +2242,8 @@ gen_opcode (unsigned int opcode) } comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); if (!noflags) @@ -2245,31 +2252,40 @@ gen_opcode (unsigned int opcode) uses_cmov; start_brace(); comprintf("\tint zero = scratchie++;\n"); + comprintf("\tint tmpcnt = scratchie++;\n"); comprintf("\tint minus1 = scratchie++;\n"); - comprintf("\tand_l_ri(cnt,63);\n"); + comprintf("\tint cdata = minus1;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n"); + comprintf("\tand_l_ri(tmpcnt,63);\n"); comprintf("\tmov_l_ri(zero, 0);\n"); comprintf("\tmov_l_ri(minus1, -1);\n"); switch(curi->size) { case sz_byte: comprintf("\ttest_b_rr(data,data);\n"); comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n"); - comprintf("\ttest_l_ri(cnt, 0x38);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshra_b_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x38);\n"); + comprintf("\tmov_l_rr(cdata,data);\n"); + comprintf("\tcmov_l_rr(cdata, zero, NATIVE_CC_NE);\n"); + comprintf("\tshra_b_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_b_rr(data,cdata);\n"); break; case sz_word: comprintf("\ttest_w_rr(data,data);\n"); comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n"); - comprintf("\ttest_l_ri(cnt, 0x30);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshra_w_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x30);\n"); + comprintf("\tmov_l_rr(cdata,data);\n"); + comprintf("\tcmov_l_rr(cdata, zero, NATIVE_CC_NE);\n"); + comprintf("\tshra_w_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_w_rr(data,cdata);\n"); break; case sz_long: comprintf("\ttest_l_rr(data,data);\n"); comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n"); - comprintf("\ttest_l_ri(cnt, 0x20);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshra_l_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x20);\n"); + comprintf("\tmov_l_rr(cdata,data);\n"); + comprintf("\tcmov_l_rr(cdata, zero, NATIVE_CC_NE);\n"); + comprintf("\tshra_l_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_l_rr(data,cdata);\n"); break; default: assert(0); } @@ -2288,7 +2304,7 @@ gen_opcode (unsigned int opcode) comprintf("\tlive_flags();\n"); comprintf("\tend_needflags();\n"); if (curi->smode!=immi) - comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + comprintf("\tsetcc_for_cntzero(tmpcnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); else comprintf("\tduplicate_carry();\n"); comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); @@ -2320,32 +2336,38 @@ gen_opcode (unsigned int opcode) " " RETURN "\n" " }\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + start_brace(); if (!noflags) comprintf("\tstart_needflags();\n"); if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint zero = scratchie++;\n"); - comprintf("\tand_l_ri(cnt,63);\n"); - comprintf("\tmov_l_ri(zero, 0);\n"); + comprintf("\tint cdata = scratchie++;\n"); + comprintf("\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n"); + comprintf("\tand_l_ri(tmpcnt,63);\n"); + comprintf("\tmov_l_ri(cdata, 0);\n"); switch(curi->size) { case sz_byte: - comprintf("\ttest_l_ri(cnt, 0x38);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshll_b_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x38);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshll_b_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_b_rr(data, cdata);\n"); break; case sz_word: - comprintf("\ttest_l_ri(cnt, 0x30);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshll_w_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x30);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshll_w_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_w_rr(data, cdata);\n"); break; case sz_long: - comprintf("\ttest_l_ri(cnt, 0x20);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshll_l_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x20);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshll_l_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_l_rr(data, cdata);\n"); break; default: assert(0); } @@ -2364,7 +2386,7 @@ gen_opcode (unsigned int opcode) comprintf("\tlive_flags();\n"); comprintf("\tend_needflags();\n"); if (curi->smode!=immi) - comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + comprintf("\tsetcc_for_cntzero(tmpcnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); else comprintf("\tduplicate_carry();\n"); comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); @@ -2387,8 +2409,8 @@ gen_opcode (unsigned int opcode) } comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); if (!noflags) @@ -2396,24 +2418,29 @@ gen_opcode (unsigned int opcode) if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint zero = scratchie++;\n"); - comprintf("\tand_l_ri(cnt,63);\n"); - comprintf("\tmov_l_ri(zero, 0);\n"); + comprintf("\tint cdata = scratchie++;\n"); + comprintf("\tint tmpcnt=scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n"); + comprintf("\tand_l_ri(tmpcnt,63);\n"); + comprintf("\tmov_l_ri(cdata, 0);\n"); switch(curi->size) { case sz_byte: - comprintf("\ttest_l_ri(cnt, 0x38);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshrl_b_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x38);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshrl_b_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_b_rr(data, cdata);\n"); break; case sz_word: - comprintf("\ttest_l_ri(cnt, 0x30);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshrl_w_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x30);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshrl_w_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_w_rr(data, cdata);\n"); break; case sz_long: - comprintf("\ttest_l_ri(cnt, 0x20);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshrl_l_rr(data, cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x20);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshrl_l_rr(cdata, tmpcnt);\n"); + comprintf("\tmov_l_rr(data, cdata);\n"); break; default: assert(0); } @@ -2432,7 +2459,7 @@ gen_opcode (unsigned int opcode) comprintf("\tlive_flags();\n"); comprintf("\tend_needflags();\n"); if (curi->smode!=immi) - comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + comprintf("\tsetcc_for_cntzero(tmpcnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); else comprintf("\tduplicate_carry();\n"); comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); @@ -2455,8 +2482,8 @@ gen_opcode (unsigned int opcode) } comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace(); if (!noflags) @@ -2464,24 +2491,29 @@ gen_opcode (unsigned int opcode) if (curi->smode!=immi) { uses_cmov; start_brace(); - comprintf("\tint zero = scratchie++;\n"); - comprintf("\tand_l_ri(cnt,63);\n"); - comprintf("\tmov_l_ri(zero, 0);\n"); + comprintf("\tint cdata = scratchie++;\n"); + comprintf("\tint tmpcnt = scratchie++;\n"); + comprintf("\tmov_l_rr(tmpcnt,cnt);\n"); + comprintf("\tand_l_ri(tmpcnt,63);\n"); + comprintf("\tmov_l_ri(cdata, 0);\n"); switch(curi->size) { case sz_byte: - comprintf("\ttest_l_ri(cnt, 0x38);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshll_b_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x38);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshll_b_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_b_rr(data, cdata);\n"); break; case sz_word: - comprintf("\ttest_l_ri(cnt, 0x30);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshll_w_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x30);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshll_w_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_w_rr(data, cdata);\n"); break; case sz_long: - comprintf("\ttest_l_ri(cnt, 0x20);\n"); - comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n"); - comprintf("\tshll_l_rr(data,cnt);\n"); + comprintf("\ttest_l_ri(tmpcnt, 0x20);\n"); + comprintf("\tcmov_l_rr(cdata, data, NATIVE_CC_EQ);\n"); + comprintf("\tshll_l_rr(cdata,tmpcnt);\n"); + comprintf("\tmov_l_rr(data, cdata);\n"); break; default: assert(0); } @@ -2500,7 +2532,7 @@ gen_opcode (unsigned int opcode) comprintf("\tlive_flags();\n"); comprintf("\tend_needflags();\n"); if (curi->smode!=immi) - comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); + comprintf("\tsetcc_for_cntzero(tmpcnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4); else comprintf("\tduplicate_carry();\n"); comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); @@ -2522,8 +2554,8 @@ gen_opcode (unsigned int opcode) start_brace(); } comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace (); switch(curi->size) { @@ -2564,8 +2596,8 @@ gen_opcode (unsigned int opcode) start_brace(); } comprintf("\tdont_care_flags();\n"); - genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); + genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); start_brace (); switch(curi->size) { @@ -2696,7 +2728,7 @@ gen_opcode (unsigned int opcode) comprintf("\tint r2=(extra>>12)&7;\n" "\tint tmp=scratchie++;\n"); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC); /* The two operands are in dst and r2 */ comprintf("\tif (extra&0x0400) {\n" /* Need full 64 bit result */ "\tint r3=(extra&7);\n" diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp index c76d56e6..ce18967e 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp @@ -508,7 +508,14 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, fpu_double value; uae_u32 parts[2]; } dest; +#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) + fpu_register_parts p = { src }; + // always set the explicit integer bit. + p.parts[1] |= 0x80000000; + dest.value = (fpu_double)p.val; +#else dest.value = (fpu_double)src; +#endif #ifdef WORDS_BIGENDIAN *wrd1 = dest.parts[0]; *wrd2 = dest.parts[1]; @@ -975,37 +982,40 @@ PRIVATE inline int FFPU put_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe case 1: put_long (ad, extract_single(value)); break; - case 2: { - uae_u32 wrd1, wrd2, wrd3; - extract_extended(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); + case 2: + { + uae_u32 wrd1, wrd2, wrd3; + extract_extended(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + } break; - } - case 3: { - uae_u32 wrd1, wrd2, wrd3; - extract_packed(value, &wrd1, &wrd2, &wrd3); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); - ad += 4; - put_long (ad, wrd3); + case 3: + { + uae_u32 wrd1, wrd2, wrd3; + extract_packed(value, &wrd1, &wrd2, &wrd3); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + ad += 4; + put_long (ad, wrd3); + } break; - } case 4: put_word(ad, (uae_s16) toint(value)); break; - case 5: { - uae_u32 wrd1, wrd2; - extract_double(value, &wrd1, &wrd2); - put_long (ad, wrd1); - ad += 4; - put_long (ad, wrd2); + case 5: + { + uae_u32 wrd1, wrd2; + extract_double(value, &wrd1, &wrd2); + put_long (ad, wrd1); + ad += 4; + put_long (ad, wrd2); + } break; - } case 6: put_byte(ad, (uae_s8) toint(value)); break; @@ -2209,7 +2219,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FREM %.04f\n",(double)src)); // FPU registers[reg] = FPU registers[reg] - (double) ((int) (FPU registers[reg] / src + 0.5)) * src; { - fpu_register quot = fp_round_to_nearest(FPU registers[reg] / src); + fpu_register quot = fp_round_to_even(FPU registers[reg] / src); uae_u32 sign = get_quotient_sign(FPU registers[reg],src); FPU registers[reg] = FPU registers[reg] - quot * src; make_fpsr(FPU registers[reg]); @@ -2347,17 +2357,26 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x38: /* FCMP */ fpu_debug(("FCMP %.04f\n",(double)src)); set_fpsr(0); - if (isinf(FPU registers[reg])) + if (isnan(src) || isnan(FPU registers[reg])) + { + make_nan(src, false); + make_fpsr(src); + } else if (isinf(FPU registers[reg])) { if (isinf(src) && isneg(FPU registers[reg]) == isneg (src)) + { make_fpsr(0); - else + } else + { make_fpsr(FPU registers[reg]); - } - else if (isinf(src)) + } + } else if (isinf(src)) + { make_fpsr(-src); - else + } else + { make_fpsr(FPU registers[reg] - src); + } break; case 0x3a: /* FTST */ fpu_debug(("FTST %.04f\n",(double)src)); diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h index 26e47ff8..8b03dd2a 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.h +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -648,6 +648,17 @@ PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_regis /* --- Math functions --- */ /* -------------------------------------------------------------------------- */ +#ifdef __HAIKU__ +#ifdef __cplusplus +extern "C" { +#endif +/* Haiku seems to lack some declarations, even if the functions are there */ +extern long double exp10l(long double); +#ifdef __cplusplus +} +#endif +#endif + #if defined(FPU_USE_ISO_C99) && (defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)) # ifdef HAVE_LOGL # define fp_log logl @@ -1169,6 +1180,14 @@ DEFINE_ROUND_FUNC(zero, CW_RC_ZERO) DEFINE_ROUND_FUNC(nearest, CW_RC_NEAR) #endif +#undef fp_round_to_even +#ifdef HAVE_RINTL +#define fp_round_to_even rintl +#else +#define fp_round_to_even fp_do_round_to_even +DEFINE_ROUND_FUNC(even, CW_RC_NEAR) +#endif + #undef fp_ceil #define fp_ceil fp_do_round_to_plus_infinity @@ -1194,4 +1213,8 @@ DEFINE_ROUND_FUNC(nearest, CW_RC_NEAR) #define fp_round_to_nearest(x) ((int)((x) + 0.5)) #endif +#ifndef fp_round_to_even +#define fp_round_to_even fp_round_to_nearest +#endif + #endif /* FPU_MATHLIB_H */